Blame view

drivers/mfd/wm8350-core.c 18.1 KB
89b4012be   Mark Brown   mfd: Core support...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * wm8350-core.c  --  Device access for Wolfson WM8350
   *
   * Copyright 2007, 2008 Wolfson Microelectronics PLC.
   *
   * Author: Liam Girdwood, Mark Brown
   *
   *  This program is free software; you can redistribute  it and/or modify it
   *  under  the terms of  the GNU General  Public License as published by the
   *  Free Software Foundation;  either version 2 of the  License, or (at your
   *  option) any later version.
   *
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
18
  #include <linux/slab.h>
ebccec0fa   Mark Brown   mfd: Add WM8350 i...
19
  #include <linux/bug.h>
89b4012be   Mark Brown   mfd: Core support...
20
21
22
  #include <linux/device.h>
  #include <linux/delay.h>
  #include <linux/interrupt.h>
ebccec0fa   Mark Brown   mfd: Add WM8350 i...
23
  #include <linux/workqueue.h>
89b4012be   Mark Brown   mfd: Core support...
24
25
26
  
  #include <linux/mfd/wm8350/core.h>
  #include <linux/mfd/wm8350/audio.h>
ebccec0fa   Mark Brown   mfd: Add WM8350 i...
27
  #include <linux/mfd/wm8350/comparator.h>
89b4012be   Mark Brown   mfd: Core support...
28
29
  #include <linux/mfd/wm8350/gpio.h>
  #include <linux/mfd/wm8350/pmic.h>
ebccec0fa   Mark Brown   mfd: Add WM8350 i...
30
  #include <linux/mfd/wm8350/rtc.h>
89b4012be   Mark Brown   mfd: Core support...
31
  #include <linux/mfd/wm8350/supply.h>
ebccec0fa   Mark Brown   mfd: Add WM8350 i...
32
  #include <linux/mfd/wm8350/wdt.h>
89b4012be   Mark Brown   mfd: Core support...
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  
  #define WM8350_UNLOCK_KEY		0x0013
  #define WM8350_LOCK_KEY			0x0000
  
  #define WM8350_CLOCK_CONTROL_1		0x28
  #define WM8350_AIF_TEST			0x74
  
  /* debug */
  #define WM8350_BUS_DEBUG 0
  #if WM8350_BUS_DEBUG
  #define dump(regs, src) do { \
  	int i_; \
  	u16 *src_ = src; \
  	printk(KERN_DEBUG); \
  	for (i_ = 0; i_ < regs; i_++) \
  		printk(" 0x%4.4x", *src_++); \
  	printk("
  "); \
  } while (0);
  #else
  #define dump(bytes, src)
  #endif
  
  #define WM8350_LOCK_DEBUG 0
  #if WM8350_LOCK_DEBUG
  #define ldbg(format, arg...) printk(format, ## arg)
  #else
  #define ldbg(format, arg...)
  #endif
  
  /*
   * WM8350 Device IO
   */
  static DEFINE_MUTEX(io_mutex);
  static DEFINE_MUTEX(reg_lock_mutex);
89b4012be   Mark Brown   mfd: Core support...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  
  /* Perform a physical read from the device.
   */
  static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs,
  			    u16 *dest)
  {
  	int i, ret;
  	int bytes = num_regs * 2;
  
  	dev_dbg(wm8350->dev, "volatile read
  ");
  	ret = wm8350->read_dev(wm8350, reg, bytes, (char *)dest);
  
  	for (i = reg; i < reg + num_regs; i++) {
  		/* Cache is CPU endian */
  		dest[i - reg] = be16_to_cpu(dest[i - reg]);
89b4012be   Mark Brown   mfd: Core support...
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  		/* Mask out non-readable bits */
  		dest[i - reg] &= wm8350_reg_io_map[i].readable;
  	}
  
  	dump(num_regs, dest);
  
  	return ret;
  }
  
  static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest)
  {
  	int i;
  	int end = reg + num_regs;
  	int ret = 0;
  	int bytes = num_regs * 2;
  
  	if (wm8350->read_dev == NULL)
  		return -ENODEV;
  
  	if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) {
  		dev_err(wm8350->dev, "invalid reg %x
  ",
  			reg + num_regs - 1);
  		return -EINVAL;
  	}
  
  	dev_dbg(wm8350->dev,
  		"%s R%d(0x%2.2x) %d regs
  ", __func__, reg, reg, num_regs);
  
  #if WM8350_BUS_DEBUG
  	/* we can _safely_ read any register, but warn if read not supported */
  	for (i = reg; i < end; i++) {
  		if (!wm8350_reg_io_map[i].readable)
  			dev_warn(wm8350->dev,
  				"reg R%d is not readable
  ", i);
  	}
  #endif
  
  	/* if any volatile registers are required, then read back all */
  	for (i = reg; i < end; i++)
  		if (wm8350_reg_io_map[i].vol)
  			return wm8350_phys_read(wm8350, reg, num_regs, dest);
  
  	/* no volatiles, then cache is good */
  	dev_dbg(wm8350->dev, "cache read
  ");
  	memcpy(dest, &wm8350->reg_cache[reg], bytes);
  	dump(num_regs, dest);
  	return ret;
  }
  
  static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg)
  {
  	if (reg == WM8350_SECURITY ||
  	    wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY)
  		return 0;
8e6ba2dfa   Mark Brown   mfd: WM835x GPIO ...
142
  	if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 &&
89b4012be   Mark Brown   mfd: Core support...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  	     reg <= WM8350_GPIO_FUNCTION_SELECT_4) ||
  	    (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 &&
  	     reg <= WM8350_BATTERY_CHARGER_CONTROL_3))
  		return 1;
  	return 0;
  }
  
  static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src)
  {
  	int i;
  	int end = reg + num_regs;
  	int bytes = num_regs * 2;
  
  	if (wm8350->write_dev == NULL)
  		return -ENODEV;
  
  	if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) {
  		dev_err(wm8350->dev, "invalid reg %x
  ",
  			reg + num_regs - 1);
  		return -EINVAL;
  	}
  
  	/* it's generally not a good idea to write to RO or locked registers */
  	for (i = reg; i < end; i++) {
  		if (!wm8350_reg_io_map[i].writable) {
  			dev_err(wm8350->dev,
  				"attempted write to read only reg R%d
  ", i);
  			return -EINVAL;
  		}
  
  		if (is_reg_locked(wm8350, i)) {
  			dev_err(wm8350->dev,
  			       "attempted write to locked reg R%d
  ", i);
  			return -EINVAL;
  		}
  
  		src[i - reg] &= wm8350_reg_io_map[i].writable;
  
  		wm8350->reg_cache[i] =
  			(wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable)
  			| src[i - reg];
  
  		src[i - reg] = cpu_to_be16(src[i - reg]);
  	}
  
  	/* Actually write it out */
  	return wm8350->write_dev(wm8350, reg, bytes, (char *)src);
  }
  
  /*
   * Safe read, modify, write methods
   */
  int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask)
  {
  	u16 data;
  	int err;
  
  	mutex_lock(&io_mutex);
  	err = wm8350_read(wm8350, reg, 1, &data);
  	if (err) {
  		dev_err(wm8350->dev, "read from reg R%d failed
  ", reg);
  		goto out;
  	}
  
  	data &= ~mask;
  	err = wm8350_write(wm8350, reg, 1, &data);
  	if (err)
  		dev_err(wm8350->dev, "write to reg R%d failed
  ", reg);
  out:
  	mutex_unlock(&io_mutex);
  	return err;
  }
  EXPORT_SYMBOL_GPL(wm8350_clear_bits);
  
  int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask)
  {
  	u16 data;
  	int err;
  
  	mutex_lock(&io_mutex);
  	err = wm8350_read(wm8350, reg, 1, &data);
  	if (err) {
  		dev_err(wm8350->dev, "read from reg R%d failed
  ", reg);
  		goto out;
  	}
  
  	data |= mask;
  	err = wm8350_write(wm8350, reg, 1, &data);
  	if (err)
  		dev_err(wm8350->dev, "write to reg R%d failed
  ", reg);
  out:
  	mutex_unlock(&io_mutex);
  	return err;
  }
  EXPORT_SYMBOL_GPL(wm8350_set_bits);
  
  u16 wm8350_reg_read(struct wm8350 *wm8350, int reg)
  {
  	u16 data;
  	int err;
  
  	mutex_lock(&io_mutex);
  	err = wm8350_read(wm8350, reg, 1, &data);
  	if (err)
  		dev_err(wm8350->dev, "read from reg R%d failed
  ", reg);
  
  	mutex_unlock(&io_mutex);
  	return data;
  }
  EXPORT_SYMBOL_GPL(wm8350_reg_read);
  
  int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val)
  {
  	int ret;
  	u16 data = val;
  
  	mutex_lock(&io_mutex);
  	ret = wm8350_write(wm8350, reg, 1, &data);
  	if (ret)
  		dev_err(wm8350->dev, "write to reg R%d failed
  ", reg);
  	mutex_unlock(&io_mutex);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(wm8350_reg_write);
  
  int wm8350_block_read(struct wm8350 *wm8350, int start_reg, int regs,
  		      u16 *dest)
  {
  	int err = 0;
  
  	mutex_lock(&io_mutex);
  	err = wm8350_read(wm8350, start_reg, regs, dest);
  	if (err)
  		dev_err(wm8350->dev, "block read starting from R%d failed
  ",
  			start_reg);
  	mutex_unlock(&io_mutex);
  	return err;
  }
  EXPORT_SYMBOL_GPL(wm8350_block_read);
  
  int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs,
  		       u16 *src)
  {
  	int ret = 0;
  
  	mutex_lock(&io_mutex);
  	ret = wm8350_write(wm8350, start_reg, regs, src);
  	if (ret)
  		dev_err(wm8350->dev, "block write starting at R%d failed
  ",
  			start_reg);
  	mutex_unlock(&io_mutex);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(wm8350_block_write);
858e67446   Mark Brown   mfd: Add some doc...
308
309
310
311
312
313
314
  /**
   * wm8350_reg_lock()
   *
   * The WM8350 has a hardware lock which can be used to prevent writes to
   * some registers (generally those which can cause particularly serious
   * problems if misused).  This function enables that lock.
   */
89b4012be   Mark Brown   mfd: Core support...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
  int wm8350_reg_lock(struct wm8350 *wm8350)
  {
  	u16 key = WM8350_LOCK_KEY;
  	int ret;
  
  	ldbg(__func__);
  	mutex_lock(&io_mutex);
  	ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
  	if (ret)
  		dev_err(wm8350->dev, "lock failed
  ");
  	mutex_unlock(&io_mutex);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(wm8350_reg_lock);
858e67446   Mark Brown   mfd: Add some doc...
330
331
332
333
334
335
336
337
338
  /**
   * wm8350_reg_unlock()
   *
   * The WM8350 has a hardware lock which can be used to prevent writes to
   * some registers (generally those which can cause particularly serious
   * problems if misused).  This function disables that lock so updates
   * can be performed.  For maximum safety this should be done only when
   * required.
   */
89b4012be   Mark Brown   mfd: Core support...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  int wm8350_reg_unlock(struct wm8350 *wm8350)
  {
  	u16 key = WM8350_UNLOCK_KEY;
  	int ret;
  
  	ldbg(__func__);
  	mutex_lock(&io_mutex);
  	ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
  	if (ret)
  		dev_err(wm8350->dev, "unlock failed
  ");
  	mutex_unlock(&io_mutex);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(wm8350_reg_unlock);
674885263   Mark Brown   mfd: Add AUXADC s...
354
355
356
  int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
  {
  	u16 reg, result = 0;
674885263   Mark Brown   mfd: Add AUXADC s...
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
  
  	if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP)
  		return -EINVAL;
  	if (channel >= WM8350_AUXADC_USB && channel <= WM8350_AUXADC_TEMP
  	    && (scale != 0 || vref != 0))
  		return -EINVAL;
  
  	mutex_lock(&wm8350->auxadc_mutex);
  
  	/* Turn on the ADC */
  	reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5);
  	wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5, reg | WM8350_AUXADC_ENA);
  
  	if (scale || vref) {
  		reg = scale << 13;
  		reg |= vref << 12;
  		wm8350_reg_write(wm8350, WM8350_AUX1_READBACK + channel, reg);
  	}
  
  	reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
  	reg |= 1 << channel | WM8350_AUXADC_POLL;
  	wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg);
5051d411e   Mark Brown   mfd: Clean up aft...
379
380
381
  	/* If a late IRQ left the completion signalled then consume
  	 * the completion. */
  	try_wait_for_completion(&wm8350->auxadc_done);
d19663ac6   Mark Brown   mfd: Use completi...
382
383
384
385
  	/* We ignore the result of the completion and just check for a
  	 * conversion result, allowing us to soldier on if the IRQ
  	 * infrastructure is not set up for the chip. */
  	wait_for_completion_timeout(&wm8350->auxadc_done, msecs_to_jiffies(5));
674885263   Mark Brown   mfd: Add AUXADC s...
386

d19663ac6   Mark Brown   mfd: Use completi...
387
388
  	reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
  	if (reg & WM8350_AUXADC_POLL)
674885263   Mark Brown   mfd: Add AUXADC s...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
  		dev_err(wm8350->dev, "adc chn %d read timeout
  ", channel);
  	else
  		result = wm8350_reg_read(wm8350,
  					 WM8350_AUX1_READBACK + channel);
  
  	/* Turn off the ADC */
  	reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5);
  	wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5,
  			 reg & ~WM8350_AUXADC_ENA);
  
  	mutex_unlock(&wm8350->auxadc_mutex);
  
  	return result & WM8350_AUXADC_DATA1_MASK;
  }
  EXPORT_SYMBOL_GPL(wm8350_read_auxadc);
d19663ac6   Mark Brown   mfd: Use completi...
405
406
407
408
409
410
411
412
  static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data)
  {
  	struct wm8350 *wm8350 = irq_data;
  
  	complete(&wm8350->auxadc_done);
  
  	return IRQ_HANDLED;
  }
89b4012be   Mark Brown   mfd: Core support...
413
414
415
  /*
   * Cache is always host endian.
   */
969206306   Mark Brown   mfd: Add WM8352 s...
416
  static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode)
89b4012be   Mark Brown   mfd: Core support...
417
418
419
420
  {
  	int i, ret = 0;
  	u16 value;
  	const u16 *reg_map;
969206306   Mark Brown   mfd: Add WM8352 s...
421
  	switch (type) {
89b4012be   Mark Brown   mfd: Core support...
422
  	case 0:
969206306   Mark Brown   mfd: Add WM8352 s...
423
424
425
426
427
  		switch (mode) {
  #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
  		case 0:
  			reg_map = wm8350_mode0_defaults;
  			break;
89b4012be   Mark Brown   mfd: Core support...
428
429
  #endif
  #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1
969206306   Mark Brown   mfd: Add WM8352 s...
430
431
432
  		case 1:
  			reg_map = wm8350_mode1_defaults;
  			break;
89b4012be   Mark Brown   mfd: Core support...
433
434
  #endif
  #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2
969206306   Mark Brown   mfd: Add WM8352 s...
435
436
437
  		case 2:
  			reg_map = wm8350_mode2_defaults;
  			break;
89b4012be   Mark Brown   mfd: Core support...
438
439
  #endif
  #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3
969206306   Mark Brown   mfd: Add WM8352 s...
440
441
442
  		case 3:
  			reg_map = wm8350_mode3_defaults;
  			break;
89b4012be   Mark Brown   mfd: Core support...
443
  #endif
969206306   Mark Brown   mfd: Add WM8352 s...
444
445
446
447
448
449
450
  		default:
  			dev_err(wm8350->dev,
  				"WM8350 configuration mode %d not supported
  ",
  				mode);
  			return -EINVAL;
  		}
4331bb323   Mark Brown   mfd: Add missing ...
451
  		break;
969206306   Mark Brown   mfd: Add WM8352 s...
452

ca23f8c1b   Mark Brown   mfd: Add WM8351 s...
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  	case 1:
  		switch (mode) {
  #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0
  		case 0:
  			reg_map = wm8351_mode0_defaults;
  			break;
  #endif
  #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1
  		case 1:
  			reg_map = wm8351_mode1_defaults;
  			break;
  #endif
  #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2
  		case 2:
  			reg_map = wm8351_mode2_defaults;
  			break;
  #endif
  #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3
  		case 3:
  			reg_map = wm8351_mode3_defaults;
  			break;
  #endif
  		default:
  			dev_err(wm8350->dev,
  				"WM8351 configuration mode %d not supported
  ",
  				mode);
  			return -EINVAL;
  		}
  		break;
969206306   Mark Brown   mfd: Add WM8352 s...
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
  	case 2:
  		switch (mode) {
  #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0
  		case 0:
  			reg_map = wm8352_mode0_defaults;
  			break;
  #endif
  #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1
  		case 1:
  			reg_map = wm8352_mode1_defaults;
  			break;
  #endif
  #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2
  		case 2:
  			reg_map = wm8352_mode2_defaults;
  			break;
  #endif
  #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3
  		case 3:
  			reg_map = wm8352_mode3_defaults;
  			break;
  #endif
  		default:
  			dev_err(wm8350->dev,
  				"WM8352 configuration mode %d not supported
  ",
  				mode);
  			return -EINVAL;
  		}
  		break;
89b4012be   Mark Brown   mfd: Core support...
513
  	default:
969206306   Mark Brown   mfd: Add WM8352 s...
514
515
516
  		dev_err(wm8350->dev,
  			"WM835x configuration mode %d not supported
  ",
89b4012be   Mark Brown   mfd: Core support...
517
518
519
520
521
  			mode);
  		return -EINVAL;
  	}
  
  	wm8350->reg_cache =
9dfd33819   Mark Brown   mfd: Use bulk rea...
522
  		kmalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL);
89b4012be   Mark Brown   mfd: Core support...
523
524
525
526
527
528
529
  	if (wm8350->reg_cache == NULL)
  		return -ENOMEM;
  
  	/* Read the initial cache state back from the device - this is
  	 * a PMIC so the device many not be in a virgin state and we
  	 * can't rely on the silicon values.
  	 */
9dfd33819   Mark Brown   mfd: Use bulk rea...
530
531
532
533
534
535
536
537
538
539
540
  	ret = wm8350->read_dev(wm8350, 0,
  			       sizeof(u16) * (WM8350_MAX_REGISTER + 1),
  			       wm8350->reg_cache);
  	if (ret < 0) {
  		dev_err(wm8350->dev,
  			"failed to read initial cache values
  ");
  		goto out;
  	}
  
  	/* Mask out uncacheable/unreadable bits and the audio. */
89b4012be   Mark Brown   mfd: Core support...
541
  	for (i = 0; i < WM8350_MAX_REGISTER; i++) {
89b4012be   Mark Brown   mfd: Core support...
542
543
  		if (wm8350_reg_io_map[i].readable &&
  		    (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) {
9dfd33819   Mark Brown   mfd: Use bulk rea...
544
  			value = be16_to_cpu(wm8350->reg_cache[i]);
89b4012be   Mark Brown   mfd: Core support...
545
546
547
548
549
550
551
  			value &= wm8350_reg_io_map[i].readable;
  			wm8350->reg_cache[i] = value;
  		} else
  			wm8350->reg_cache[i] = reg_map[i];
  	}
  
  out:
8c46cf30f   Axel Lin   mfd: Fix wrong wm...
552
  	kfree(wm8350->reg_cache);
89b4012be   Mark Brown   mfd: Core support...
553
554
  	return ret;
  }
89b4012be   Mark Brown   mfd: Core support...
555

9201d38b9   Mark Brown   mfd: Add WM8350 s...
556
557
558
559
560
561
562
563
564
565
566
  /*
   * Register a client device.  This is non-fatal since there is no need to
   * fail the entire device init due to a single platform device failing.
   */
  static void wm8350_client_dev_register(struct wm8350 *wm8350,
  				       const char *name,
  				       struct platform_device **pdev)
  {
  	int ret;
  
  	*pdev = platform_device_alloc(name, -1);
cb9b22450   Dan Carpenter   mfd: Fix incorrec...
567
  	if (*pdev == NULL) {
9201d38b9   Mark Brown   mfd: Add WM8350 s...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
  		dev_err(wm8350->dev, "Failed to allocate %s
  ", name);
  		return;
  	}
  
  	(*pdev)->dev.parent = wm8350->dev;
  	platform_set_drvdata(*pdev, wm8350);
  	ret = platform_device_add(*pdev);
  	if (ret != 0) {
  		dev_err(wm8350->dev, "Failed to register %s: %d
  ", name, ret);
  		platform_device_put(*pdev);
  		*pdev = NULL;
  	}
  }
ebccec0fa   Mark Brown   mfd: Add WM8350 i...
583
  int wm8350_device_init(struct wm8350 *wm8350, int irq,
bcdd4efc1   Mark Brown   mfd: Add initiali...
584
  		       struct wm8350_platform_data *pdata)
89b4012be   Mark Brown   mfd: Core support...
585
  {
85c93ea7d   Mark Brown   mfd: Improve diag...
586
  	int ret;
b797a5551   Mark Brown   mfd: Refactor WM8...
587
588
  	u16 id1, id2, mask_rev;
  	u16 cust_id, mode, chip_rev;
89b4012be   Mark Brown   mfd: Core support...
589

18bf50a37   Mark Brown   mfd: Store wm8350...
590
  	dev_set_drvdata(wm8350->dev, wm8350);
89b4012be   Mark Brown   mfd: Core support...
591
  	/* get WM8350 revision and config mode */
85c93ea7d   Mark Brown   mfd: Improve diag...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
  	ret = wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
  	if (ret != 0) {
  		dev_err(wm8350->dev, "Failed to read ID: %d
  ", ret);
  		goto err;
  	}
  
  	ret = wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
  	if (ret != 0) {
  		dev_err(wm8350->dev, "Failed to read ID: %d
  ", ret);
  		goto err;
  	}
  
  	ret = wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev),
  			       &mask_rev);
  	if (ret != 0) {
  		dev_err(wm8350->dev, "Failed to read revision: %d
  ", ret);
  		goto err;
  	}
89b4012be   Mark Brown   mfd: Core support...
613
614
615
  
  	id1 = be16_to_cpu(id1);
  	id2 = be16_to_cpu(id2);
b797a5551   Mark Brown   mfd: Refactor WM8...
616
  	mask_rev = be16_to_cpu(mask_rev);
89b4012be   Mark Brown   mfd: Core support...
617

b797a5551   Mark Brown   mfd: Refactor WM8...
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
  	if (id1 != 0x6143) {
  		dev_err(wm8350->dev,
  			"Device with ID %x is not a WM8350
  ", id1);
  		ret = -ENODEV;
  		goto err;
  	}
  
  	mode = id2 & WM8350_CONF_STS_MASK >> 10;
  	cust_id = id2 & WM8350_CUST_ID_MASK;
  	chip_rev = (id2 & WM8350_CHIP_REV_MASK) >> 12;
  	dev_info(wm8350->dev,
  		 "CONF_STS %d, CUST_ID %d, MASK_REV %d, CHIP_REV %d
  ",
  		 mode, cust_id, mask_rev, chip_rev);
  
  	if (cust_id != 0) {
  		dev_err(wm8350->dev, "Unsupported CUST_ID
  ");
  		ret = -ENODEV;
  		goto err;
  	}
  
  	switch (mask_rev) {
  	case 0:
645524a9c   Mark Brown   mfd: Support conf...
643
644
  		wm8350->pmic.max_dcdc = WM8350_DCDC_6;
  		wm8350->pmic.max_isink = WM8350_ISINK_B;
b797a5551   Mark Brown   mfd: Refactor WM8...
645
  		switch (chip_rev) {
89b4012be   Mark Brown   mfd: Core support...
646
  		case WM8350_REV_E:
b797a5551   Mark Brown   mfd: Refactor WM8...
647
648
  			dev_info(wm8350->dev, "WM8350 Rev E
  ");
89b4012be   Mark Brown   mfd: Core support...
649
650
  			break;
  		case WM8350_REV_F:
b797a5551   Mark Brown   mfd: Refactor WM8...
651
652
  			dev_info(wm8350->dev, "WM8350 Rev F
  ");
89b4012be   Mark Brown   mfd: Core support...
653
654
  			break;
  		case WM8350_REV_G:
b797a5551   Mark Brown   mfd: Refactor WM8...
655
656
  			dev_info(wm8350->dev, "WM8350 Rev G
  ");
d756f4a44   Mark Brown   mfd: Switch WM835...
657
  			wm8350->power.rev_g_coeff = 1;
89b4012be   Mark Brown   mfd: Core support...
658
  			break;
0c8a60167   Mark Brown   mfd: Add WM8350 r...
659
  		case WM8350_REV_H:
b797a5551   Mark Brown   mfd: Refactor WM8...
660
661
  			dev_info(wm8350->dev, "WM8350 Rev H
  ");
d756f4a44   Mark Brown   mfd: Switch WM835...
662
  			wm8350->power.rev_g_coeff = 1;
0c8a60167   Mark Brown   mfd: Add WM8350 r...
663
  			break;
89b4012be   Mark Brown   mfd: Core support...
664
665
  		default:
  			/* For safety we refuse to run on unknown hardware */
b797a5551   Mark Brown   mfd: Refactor WM8...
666
667
  			dev_err(wm8350->dev, "Unknown WM8350 CHIP_REV
  ");
89b4012be   Mark Brown   mfd: Core support...
668
669
670
  			ret = -ENODEV;
  			goto err;
  		}
b797a5551   Mark Brown   mfd: Refactor WM8...
671
  		break;
ca23f8c1b   Mark Brown   mfd: Add WM8351 s...
672
673
674
675
676
677
678
679
680
681
  	case 1:
  		wm8350->pmic.max_dcdc = WM8350_DCDC_4;
  		wm8350->pmic.max_isink = WM8350_ISINK_A;
  
  		switch (chip_rev) {
  		case 0:
  			dev_info(wm8350->dev, "WM8351 Rev A
  ");
  			wm8350->power.rev_g_coeff = 1;
  			break;
02d46e07e   Mark Brown   mfd: add support ...
682
683
684
685
686
  		case 1:
  			dev_info(wm8350->dev, "WM8351 Rev B
  ");
  			wm8350->power.rev_g_coeff = 1;
  			break;
ca23f8c1b   Mark Brown   mfd: Add WM8351 s...
687
688
689
690
691
692
693
  		default:
  			dev_err(wm8350->dev, "Unknown WM8351 CHIP_REV
  ");
  			ret = -ENODEV;
  			goto err;
  		}
  		break;
969206306   Mark Brown   mfd: Add WM8352 s...
694
  	case 2:
645524a9c   Mark Brown   mfd: Support conf...
695
696
  		wm8350->pmic.max_dcdc = WM8350_DCDC_6;
  		wm8350->pmic.max_isink = WM8350_ISINK_B;
969206306   Mark Brown   mfd: Add WM8352 s...
697
698
699
700
701
702
703
704
705
706
707
708
709
710
  		switch (chip_rev) {
  		case 0:
  			dev_info(wm8350->dev, "WM8352 Rev A
  ");
  			wm8350->power.rev_g_coeff = 1;
  			break;
  
  		default:
  			dev_err(wm8350->dev, "Unknown WM8352 CHIP_REV
  ");
  			ret = -ENODEV;
  			goto err;
  		}
  		break;
b797a5551   Mark Brown   mfd: Refactor WM8...
711
712
713
  	default:
  		dev_err(wm8350->dev, "Unknown MASK_REV
  ");
89b4012be   Mark Brown   mfd: Core support...
714
715
716
  		ret = -ENODEV;
  		goto err;
  	}
969206306   Mark Brown   mfd: Add WM8352 s...
717
  	ret = wm8350_create_cache(wm8350, mask_rev, mode);
89b4012be   Mark Brown   mfd: Core support...
718
  	if (ret < 0) {
b797a5551   Mark Brown   mfd: Refactor WM8...
719
720
  		dev_err(wm8350->dev, "Failed to create register cache
  ");
89b4012be   Mark Brown   mfd: Core support...
721
722
  		return ret;
  	}
674885263   Mark Brown   mfd: Add AUXADC s...
723
  	mutex_init(&wm8350->auxadc_mutex);
d19663ac6   Mark Brown   mfd: Use completi...
724
  	init_completion(&wm8350->auxadc_done);
320645035   Mark Brown   mfd: Support acti...
725

e0a3389ab   Mark Brown   mfd: Split wm8350...
726
727
  	ret = wm8350_irq_init(wm8350, irq, pdata);
  	if (ret < 0)
8c46cf30f   Axel Lin   mfd: Fix wrong wm...
728
  		goto err_free;
ebccec0fa   Mark Brown   mfd: Add WM8350 i...
729

d19663ac6   Mark Brown   mfd: Use completi...
730
731
732
733
734
735
736
737
738
739
  	if (wm8350->irq_base) {
  		ret = request_threaded_irq(wm8350->irq_base +
  					   WM8350_IRQ_AUXADC_DATARDY,
  					   NULL, wm8350_auxadc_irq, 0,
  					   "auxadc", wm8350);
  		if (ret < 0)
  			dev_warn(wm8350->dev,
  				 "Failed to request AUXADC IRQ: %d
  ", ret);
  	}
62571c29a   Mark Brown   mfd: Initialise W...
740
741
742
743
744
745
  	if (pdata && pdata->init) {
  		ret = pdata->init(wm8350);
  		if (ret != 0) {
  			dev_err(wm8350->dev, "Platform init() failed: %d
  ",
  				ret);
e0a3389ab   Mark Brown   mfd: Split wm8350...
746
  			goto err_irq;
62571c29a   Mark Brown   mfd: Initialise W...
747
748
  		}
  	}
ebccec0fa   Mark Brown   mfd: Add WM8350 i...
749
  	wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0x0);
add41cb46   Mark Brown   mfd: Add placehol...
750
751
752
753
  	wm8350_client_dev_register(wm8350, "wm8350-codec",
  				   &(wm8350->codec.pdev));
  	wm8350_client_dev_register(wm8350, "wm8350-gpio",
  				   &(wm8350->gpio.pdev));
fb6c023a2   Mark Brown   hwmon: Add WM835x...
754
755
  	wm8350_client_dev_register(wm8350, "wm8350-hwmon",
  				   &(wm8350->hwmon.pdev));
add41cb46   Mark Brown   mfd: Add placehol...
756
757
758
759
  	wm8350_client_dev_register(wm8350, "wm8350-power",
  				   &(wm8350->power.pdev));
  	wm8350_client_dev_register(wm8350, "wm8350-rtc", &(wm8350->rtc.pdev));
  	wm8350_client_dev_register(wm8350, "wm8350-wdt", &(wm8350->wdt.pdev));
89b4012be   Mark Brown   mfd: Core support...
760
  	return 0;
e0a3389ab   Mark Brown   mfd: Split wm8350...
761
762
  err_irq:
  	wm8350_irq_exit(wm8350);
8c46cf30f   Axel Lin   mfd: Fix wrong wm...
763
  err_free:
89b4012be   Mark Brown   mfd: Core support...
764
  	kfree(wm8350->reg_cache);
8c46cf30f   Axel Lin   mfd: Fix wrong wm...
765
  err:
89b4012be   Mark Brown   mfd: Core support...
766
767
768
769
770
771
  	return ret;
  }
  EXPORT_SYMBOL_GPL(wm8350_device_init);
  
  void wm8350_device_exit(struct wm8350 *wm8350)
  {
da09155ac   Mark Brown   regulator: Add WM...
772
  	int i;
0081e8020   Mark Brown   leds: Add WM8350 ...
773
774
  	for (i = 0; i < ARRAY_SIZE(wm8350->pmic.led); i++)
  		platform_device_unregister(wm8350->pmic.led[i].pdev);
da09155ac   Mark Brown   regulator: Add WM...
775
  	for (i = 0; i < ARRAY_SIZE(wm8350->pmic.pdev); i++)
add41cb46   Mark Brown   mfd: Add placehol...
776
777
778
779
780
  		platform_device_unregister(wm8350->pmic.pdev[i]);
  
  	platform_device_unregister(wm8350->wdt.pdev);
  	platform_device_unregister(wm8350->rtc.pdev);
  	platform_device_unregister(wm8350->power.pdev);
fb6c023a2   Mark Brown   hwmon: Add WM835x...
781
  	platform_device_unregister(wm8350->hwmon.pdev);
add41cb46   Mark Brown   mfd: Add placehol...
782
783
  	platform_device_unregister(wm8350->gpio.pdev);
  	platform_device_unregister(wm8350->codec.pdev);
da09155ac   Mark Brown   regulator: Add WM...
784

d19663ac6   Mark Brown   mfd: Use completi...
785
786
  	if (wm8350->irq_base)
  		free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350);
e0a3389ab   Mark Brown   mfd: Split wm8350...
787
  	wm8350_irq_exit(wm8350);
89b4012be   Mark Brown   mfd: Core support...
788
789
790
  	kfree(wm8350->reg_cache);
  }
  EXPORT_SYMBOL_GPL(wm8350_device_exit);
ebccec0fa   Mark Brown   mfd: Add WM8350 i...
791
  MODULE_DESCRIPTION("WM8350 AudioPlus PMIC core driver");
89b4012be   Mark Brown   mfd: Core support...
792
  MODULE_LICENSE("GPL");