Merge branch 'bkl/procfs' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[linux-2.6-block.git] / drivers / mfd / wm831x-core.c
CommitLineData
d2bedfe7
MB
1/*
2 * wm831x-core.c -- Device access for Wolfson WM831x PMICs
3 *
4 * Copyright 2009 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/i2c.h>
7e9f9fd4
MB
18#include <linux/bcd.h>
19#include <linux/delay.h>
d2bedfe7 20#include <linux/mfd/core.h>
5a0e3ad6 21#include <linux/slab.h>
d2bedfe7
MB
22
23#include <linux/mfd/wm831x/core.h>
24#include <linux/mfd/wm831x/pdata.h>
7d4d0a3e 25#include <linux/mfd/wm831x/irq.h>
7e9f9fd4 26#include <linux/mfd/wm831x/auxadc.h>
6704e517 27#include <linux/mfd/wm831x/otp.h>
698659d5
MB
28#include <linux/mfd/wm831x/regulator.h>
29
30/* Current settings - values are 2*2^(reg_val/4) microamps. These are
31 * exported since they are used by multiple drivers.
32 */
7716977b 33int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1] = {
698659d5
MB
34 2,
35 2,
36 3,
37 3,
38 4,
39 5,
40 6,
41 7,
42 8,
43 10,
44 11,
45 13,
46 16,
47 19,
48 23,
49 27,
50 32,
51 38,
52 45,
53 54,
54 64,
55 76,
56 91,
57 108,
58 128,
59 152,
60 181,
61 215,
62 256,
63 304,
64 362,
65 431,
66 512,
67 609,
68 724,
69 861,
70 1024,
71 1218,
72 1448,
73 1722,
74 2048,
75 2435,
76 2896,
77 3444,
78 4096,
79 4871,
80 5793,
81 6889,
82 8192,
83 9742,
84 11585,
85 13777,
86 16384,
87 19484,
88 23170,
89 27554,
90};
91EXPORT_SYMBOL_GPL(wm831x_isinkv_values);
d2bedfe7
MB
92
93enum wm831x_parent {
894362f5
MB
94 WM8310 = 0x8310,
95 WM8311 = 0x8311,
96 WM8312 = 0x8312,
d4e0a89e 97 WM8320 = 0x8320,
d2bedfe7
MB
98};
99
100static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg)
101{
102 if (!wm831x->locked)
103 return 0;
104
105 switch (reg) {
106 case WM831X_WATCHDOG:
107 case WM831X_DC4_CONTROL:
108 case WM831X_ON_PIN_CONTROL:
109 case WM831X_BACKUP_CHARGER_CONTROL:
110 case WM831X_CHARGER_CONTROL_1:
111 case WM831X_CHARGER_CONTROL_2:
112 return 1;
113
114 default:
115 return 0;
116 }
117}
118
119/**
120 * wm831x_reg_unlock: Unlock user keyed registers
121 *
122 * The WM831x has a user key preventing writes to particularly
123 * critical registers. This function locks those registers,
124 * allowing writes to them.
125 */
126void wm831x_reg_lock(struct wm831x *wm831x)
127{
128 int ret;
129
130 ret = wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0);
131 if (ret == 0) {
132 dev_vdbg(wm831x->dev, "Registers locked\n");
133
134 mutex_lock(&wm831x->io_lock);
135 WARN_ON(wm831x->locked);
136 wm831x->locked = 1;
137 mutex_unlock(&wm831x->io_lock);
138 } else {
139 dev_err(wm831x->dev, "Failed to lock registers: %d\n", ret);
140 }
141
142}
143EXPORT_SYMBOL_GPL(wm831x_reg_lock);
144
145/**
146 * wm831x_reg_unlock: Unlock user keyed registers
147 *
148 * The WM831x has a user key preventing writes to particularly
149 * critical registers. This function locks those registers,
150 * preventing spurious writes.
151 */
152int wm831x_reg_unlock(struct wm831x *wm831x)
153{
154 int ret;
155
156 /* 0x9716 is the value required to unlock the registers */
157 ret = wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0x9716);
158 if (ret == 0) {
159 dev_vdbg(wm831x->dev, "Registers unlocked\n");
160
161 mutex_lock(&wm831x->io_lock);
162 WARN_ON(!wm831x->locked);
163 wm831x->locked = 0;
164 mutex_unlock(&wm831x->io_lock);
165 }
166
167 return ret;
168}
169EXPORT_SYMBOL_GPL(wm831x_reg_unlock);
170
171static int wm831x_read(struct wm831x *wm831x, unsigned short reg,
172 int bytes, void *dest)
173{
174 int ret, i;
175 u16 *buf = dest;
176
177 BUG_ON(bytes % 2);
178 BUG_ON(bytes <= 0);
179
180 ret = wm831x->read_dev(wm831x, reg, bytes, dest);
181 if (ret < 0)
182 return ret;
183
184 for (i = 0; i < bytes / 2; i++) {
185 buf[i] = be16_to_cpu(buf[i]);
186
187 dev_vdbg(wm831x->dev, "Read %04x from R%d(0x%x)\n",
188 buf[i], reg + i, reg + i);
189 }
190
191 return 0;
192}
193
194/**
195 * wm831x_reg_read: Read a single WM831x register.
196 *
197 * @wm831x: Device to read from.
198 * @reg: Register to read.
199 */
200int wm831x_reg_read(struct wm831x *wm831x, unsigned short reg)
201{
202 unsigned short val;
203 int ret;
204
205 mutex_lock(&wm831x->io_lock);
206
207 ret = wm831x_read(wm831x, reg, 2, &val);
208
209 mutex_unlock(&wm831x->io_lock);
210
211 if (ret < 0)
212 return ret;
213 else
214 return val;
215}
216EXPORT_SYMBOL_GPL(wm831x_reg_read);
217
218/**
219 * wm831x_bulk_read: Read multiple WM831x registers
220 *
221 * @wm831x: Device to read from
222 * @reg: First register
223 * @count: Number of registers
224 * @buf: Buffer to fill.
225 */
226int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
227 int count, u16 *buf)
228{
229 int ret;
230
231 mutex_lock(&wm831x->io_lock);
232
233 ret = wm831x_read(wm831x, reg, count * 2, buf);
234
235 mutex_unlock(&wm831x->io_lock);
236
237 return ret;
238}
239EXPORT_SYMBOL_GPL(wm831x_bulk_read);
240
241static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
242 int bytes, void *src)
243{
244 u16 *buf = src;
245 int i;
246
247 BUG_ON(bytes % 2);
248 BUG_ON(bytes <= 0);
249
250 for (i = 0; i < bytes / 2; i++) {
251 if (wm831x_reg_locked(wm831x, reg))
252 return -EPERM;
253
254 dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n",
255 buf[i], reg + i, reg + i);
256
257 buf[i] = cpu_to_be16(buf[i]);
258 }
259
260 return wm831x->write_dev(wm831x, reg, bytes, src);
261}
262
263/**
264 * wm831x_reg_write: Write a single WM831x register.
265 *
266 * @wm831x: Device to write to.
267 * @reg: Register to write to.
268 * @val: Value to write.
269 */
270int wm831x_reg_write(struct wm831x *wm831x, unsigned short reg,
271 unsigned short val)
272{
273 int ret;
274
275 mutex_lock(&wm831x->io_lock);
276
277 ret = wm831x_write(wm831x, reg, 2, &val);
278
279 mutex_unlock(&wm831x->io_lock);
280
281 return ret;
282}
283EXPORT_SYMBOL_GPL(wm831x_reg_write);
284
285/**
286 * wm831x_set_bits: Set the value of a bitfield in a WM831x register
287 *
288 * @wm831x: Device to write to.
289 * @reg: Register to write to.
290 * @mask: Mask of bits to set.
291 * @val: Value to set (unshifted)
292 */
293int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
294 unsigned short mask, unsigned short val)
295{
296 int ret;
297 u16 r;
298
299 mutex_lock(&wm831x->io_lock);
300
301 ret = wm831x_read(wm831x, reg, 2, &r);
302 if (ret < 0)
303 goto out;
304
305 r &= ~mask;
306 r |= val;
307
308 ret = wm831x_write(wm831x, reg, 2, &r);
309
310out:
311 mutex_unlock(&wm831x->io_lock);
312
313 return ret;
314}
315EXPORT_SYMBOL_GPL(wm831x_set_bits);
316
7e9f9fd4
MB
317/**
318 * wm831x_auxadc_read: Read a value from the WM831x AUXADC
319 *
320 * @wm831x: Device to read from.
321 * @input: AUXADC input to read.
322 */
323int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
324{
7e9f9fd4
MB
325 int ret, src;
326
327 mutex_lock(&wm831x->auxadc_lock);
328
329 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
330 WM831X_AUX_ENA, WM831X_AUX_ENA);
331 if (ret < 0) {
332 dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret);
333 goto out;
334 }
335
336 /* We force a single source at present */
337 src = input;
338 ret = wm831x_reg_write(wm831x, WM831X_AUXADC_SOURCE,
339 1 << src);
340 if (ret < 0) {
341 dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret);
342 goto out;
343 }
344
345 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
346 WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
347 if (ret < 0) {
348 dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret);
349 goto disable;
350 }
351
5051d411
MB
352 /* If an interrupt arrived late clean up after it */
353 try_wait_for_completion(&wm831x->auxadc_done);
354
473fe736
MB
355 /* Ignore the result to allow us to soldier on without IRQ hookup */
356 wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5));
7e9f9fd4 357
473fe736
MB
358 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL);
359 if (ret < 0) {
360 dev_err(wm831x->dev, "AUXADC status read failed: %d\n", ret);
361 goto disable;
362 }
7e9f9fd4
MB
363
364 if (ret & WM831X_AUX_CVT_ENA) {
365 dev_err(wm831x->dev, "Timed out reading AUXADC\n");
366 ret = -EBUSY;
367 goto disable;
368 }
369
370 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
371 if (ret < 0) {
372 dev_err(wm831x->dev, "Failed to read AUXADC data: %d\n", ret);
373 } else {
374 src = ((ret & WM831X_AUX_DATA_SRC_MASK)
375 >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
376
377 if (src == 14)
378 src = WM831X_AUX_CAL;
379
380 if (src != input) {
381 dev_err(wm831x->dev, "Data from source %d not %d\n",
382 src, input);
383 ret = -EINVAL;
384 } else {
385 ret &= WM831X_AUX_DATA_MASK;
386 }
387 }
388
389disable:
390 wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0);
391out:
392 mutex_unlock(&wm831x->auxadc_lock);
393 return ret;
394}
395EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
396
473fe736
MB
397static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
398{
399 struct wm831x *wm831x = irq_data;
400
401 complete(&wm831x->auxadc_done);
402
403 return IRQ_HANDLED;
404}
405
7e9f9fd4
MB
406/**
407 * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
408 *
409 * @wm831x: Device to read from.
410 * @input: AUXADC input to read.
411 */
412int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input)
413{
414 int ret;
415
416 ret = wm831x_auxadc_read(wm831x, input);
417 if (ret < 0)
418 return ret;
419
420 ret *= 1465;
421
422 return ret;
423}
424EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv);
425
d2bedfe7
MB
426static struct resource wm831x_dcdc1_resources[] = {
427 {
428 .start = WM831X_DC1_CONTROL_1,
429 .end = WM831X_DC1_DVS_CONTROL,
430 .flags = IORESOURCE_IO,
431 },
432 {
433 .name = "UV",
434 .start = WM831X_IRQ_UV_DC1,
435 .end = WM831X_IRQ_UV_DC1,
436 .flags = IORESOURCE_IRQ,
437 },
438 {
439 .name = "HC",
440 .start = WM831X_IRQ_HC_DC1,
441 .end = WM831X_IRQ_HC_DC1,
442 .flags = IORESOURCE_IRQ,
443 },
444};
445
446
447static struct resource wm831x_dcdc2_resources[] = {
448 {
449 .start = WM831X_DC2_CONTROL_1,
450 .end = WM831X_DC2_DVS_CONTROL,
451 .flags = IORESOURCE_IO,
452 },
453 {
454 .name = "UV",
455 .start = WM831X_IRQ_UV_DC2,
456 .end = WM831X_IRQ_UV_DC2,
457 .flags = IORESOURCE_IRQ,
458 },
459 {
460 .name = "HC",
461 .start = WM831X_IRQ_HC_DC2,
462 .end = WM831X_IRQ_HC_DC2,
463 .flags = IORESOURCE_IRQ,
464 },
465};
466
467static struct resource wm831x_dcdc3_resources[] = {
468 {
469 .start = WM831X_DC3_CONTROL_1,
470 .end = WM831X_DC3_SLEEP_CONTROL,
471 .flags = IORESOURCE_IO,
472 },
473 {
474 .name = "UV",
475 .start = WM831X_IRQ_UV_DC3,
476 .end = WM831X_IRQ_UV_DC3,
477 .flags = IORESOURCE_IRQ,
478 },
479};
480
481static struct resource wm831x_dcdc4_resources[] = {
482 {
483 .start = WM831X_DC4_CONTROL,
484 .end = WM831X_DC4_SLEEP_CONTROL,
485 .flags = IORESOURCE_IO,
486 },
487 {
488 .name = "UV",
489 .start = WM831X_IRQ_UV_DC4,
490 .end = WM831X_IRQ_UV_DC4,
491 .flags = IORESOURCE_IRQ,
492 },
493};
494
d4e0a89e
MB
495static struct resource wm8320_dcdc4_buck_resources[] = {
496 {
497 .start = WM831X_DC4_CONTROL,
498 .end = WM832X_DC4_SLEEP_CONTROL,
499 .flags = IORESOURCE_IO,
500 },
501 {
502 .name = "UV",
503 .start = WM831X_IRQ_UV_DC4,
504 .end = WM831X_IRQ_UV_DC4,
505 .flags = IORESOURCE_IRQ,
506 },
507};
508
d2bedfe7
MB
509static struct resource wm831x_gpio_resources[] = {
510 {
511 .start = WM831X_IRQ_GPIO_1,
512 .end = WM831X_IRQ_GPIO_16,
513 .flags = IORESOURCE_IRQ,
514 },
515};
516
517static struct resource wm831x_isink1_resources[] = {
518 {
519 .start = WM831X_CURRENT_SINK_1,
520 .end = WM831X_CURRENT_SINK_1,
521 .flags = IORESOURCE_IO,
522 },
523 {
524 .start = WM831X_IRQ_CS1,
525 .end = WM831X_IRQ_CS1,
526 .flags = IORESOURCE_IRQ,
527 },
528};
529
530static struct resource wm831x_isink2_resources[] = {
531 {
532 .start = WM831X_CURRENT_SINK_2,
533 .end = WM831X_CURRENT_SINK_2,
534 .flags = IORESOURCE_IO,
535 },
536 {
537 .start = WM831X_IRQ_CS2,
538 .end = WM831X_IRQ_CS2,
539 .flags = IORESOURCE_IRQ,
540 },
541};
542
543static struct resource wm831x_ldo1_resources[] = {
544 {
545 .start = WM831X_LDO1_CONTROL,
546 .end = WM831X_LDO1_SLEEP_CONTROL,
547 .flags = IORESOURCE_IO,
548 },
549 {
550 .name = "UV",
551 .start = WM831X_IRQ_UV_LDO1,
552 .end = WM831X_IRQ_UV_LDO1,
553 .flags = IORESOURCE_IRQ,
554 },
555};
556
557static struct resource wm831x_ldo2_resources[] = {
558 {
559 .start = WM831X_LDO2_CONTROL,
560 .end = WM831X_LDO2_SLEEP_CONTROL,
561 .flags = IORESOURCE_IO,
562 },
563 {
564 .name = "UV",
565 .start = WM831X_IRQ_UV_LDO2,
566 .end = WM831X_IRQ_UV_LDO2,
567 .flags = IORESOURCE_IRQ,
568 },
569};
570
571static struct resource wm831x_ldo3_resources[] = {
572 {
573 .start = WM831X_LDO3_CONTROL,
574 .end = WM831X_LDO3_SLEEP_CONTROL,
575 .flags = IORESOURCE_IO,
576 },
577 {
578 .name = "UV",
579 .start = WM831X_IRQ_UV_LDO3,
580 .end = WM831X_IRQ_UV_LDO3,
581 .flags = IORESOURCE_IRQ,
582 },
583};
584
585static struct resource wm831x_ldo4_resources[] = {
586 {
587 .start = WM831X_LDO4_CONTROL,
588 .end = WM831X_LDO4_SLEEP_CONTROL,
589 .flags = IORESOURCE_IO,
590 },
591 {
592 .name = "UV",
593 .start = WM831X_IRQ_UV_LDO4,
594 .end = WM831X_IRQ_UV_LDO4,
595 .flags = IORESOURCE_IRQ,
596 },
597};
598
599static struct resource wm831x_ldo5_resources[] = {
600 {
601 .start = WM831X_LDO5_CONTROL,
602 .end = WM831X_LDO5_SLEEP_CONTROL,
603 .flags = IORESOURCE_IO,
604 },
605 {
606 .name = "UV",
607 .start = WM831X_IRQ_UV_LDO5,
608 .end = WM831X_IRQ_UV_LDO5,
609 .flags = IORESOURCE_IRQ,
610 },
611};
612
613static struct resource wm831x_ldo6_resources[] = {
614 {
615 .start = WM831X_LDO6_CONTROL,
616 .end = WM831X_LDO6_SLEEP_CONTROL,
617 .flags = IORESOURCE_IO,
618 },
619 {
620 .name = "UV",
621 .start = WM831X_IRQ_UV_LDO6,
622 .end = WM831X_IRQ_UV_LDO6,
623 .flags = IORESOURCE_IRQ,
624 },
625};
626
627static struct resource wm831x_ldo7_resources[] = {
628 {
629 .start = WM831X_LDO7_CONTROL,
630 .end = WM831X_LDO7_SLEEP_CONTROL,
631 .flags = IORESOURCE_IO,
632 },
633 {
634 .name = "UV",
635 .start = WM831X_IRQ_UV_LDO7,
636 .end = WM831X_IRQ_UV_LDO7,
637 .flags = IORESOURCE_IRQ,
638 },
639};
640
641static struct resource wm831x_ldo8_resources[] = {
642 {
643 .start = WM831X_LDO8_CONTROL,
644 .end = WM831X_LDO8_SLEEP_CONTROL,
645 .flags = IORESOURCE_IO,
646 },
647 {
648 .name = "UV",
649 .start = WM831X_IRQ_UV_LDO8,
650 .end = WM831X_IRQ_UV_LDO8,
651 .flags = IORESOURCE_IRQ,
652 },
653};
654
655static struct resource wm831x_ldo9_resources[] = {
656 {
657 .start = WM831X_LDO9_CONTROL,
658 .end = WM831X_LDO9_SLEEP_CONTROL,
659 .flags = IORESOURCE_IO,
660 },
661 {
662 .name = "UV",
663 .start = WM831X_IRQ_UV_LDO9,
664 .end = WM831X_IRQ_UV_LDO9,
665 .flags = IORESOURCE_IRQ,
666 },
667};
668
669static struct resource wm831x_ldo10_resources[] = {
670 {
671 .start = WM831X_LDO10_CONTROL,
672 .end = WM831X_LDO10_SLEEP_CONTROL,
673 .flags = IORESOURCE_IO,
674 },
675 {
676 .name = "UV",
677 .start = WM831X_IRQ_UV_LDO10,
678 .end = WM831X_IRQ_UV_LDO10,
679 .flags = IORESOURCE_IRQ,
680 },
681};
682
683static struct resource wm831x_ldo11_resources[] = {
684 {
685 .start = WM831X_LDO11_ON_CONTROL,
686 .end = WM831X_LDO11_SLEEP_CONTROL,
687 .flags = IORESOURCE_IO,
688 },
689};
690
691static struct resource wm831x_on_resources[] = {
692 {
693 .start = WM831X_IRQ_ON,
694 .end = WM831X_IRQ_ON,
695 .flags = IORESOURCE_IRQ,
696 },
697};
698
699
700static struct resource wm831x_power_resources[] = {
701 {
702 .name = "SYSLO",
703 .start = WM831X_IRQ_PPM_SYSLO,
704 .end = WM831X_IRQ_PPM_SYSLO,
705 .flags = IORESOURCE_IRQ,
706 },
707 {
708 .name = "PWR SRC",
709 .start = WM831X_IRQ_PPM_PWR_SRC,
710 .end = WM831X_IRQ_PPM_PWR_SRC,
711 .flags = IORESOURCE_IRQ,
712 },
713 {
714 .name = "USB CURR",
715 .start = WM831X_IRQ_PPM_USB_CURR,
716 .end = WM831X_IRQ_PPM_USB_CURR,
717 .flags = IORESOURCE_IRQ,
718 },
719 {
720 .name = "BATT HOT",
721 .start = WM831X_IRQ_CHG_BATT_HOT,
722 .end = WM831X_IRQ_CHG_BATT_HOT,
723 .flags = IORESOURCE_IRQ,
724 },
725 {
726 .name = "BATT COLD",
727 .start = WM831X_IRQ_CHG_BATT_COLD,
728 .end = WM831X_IRQ_CHG_BATT_COLD,
729 .flags = IORESOURCE_IRQ,
730 },
731 {
732 .name = "BATT FAIL",
733 .start = WM831X_IRQ_CHG_BATT_FAIL,
734 .end = WM831X_IRQ_CHG_BATT_FAIL,
735 .flags = IORESOURCE_IRQ,
736 },
737 {
738 .name = "OV",
739 .start = WM831X_IRQ_CHG_OV,
740 .end = WM831X_IRQ_CHG_OV,
741 .flags = IORESOURCE_IRQ,
742 },
743 {
744 .name = "END",
745 .start = WM831X_IRQ_CHG_END,
746 .end = WM831X_IRQ_CHG_END,
747 .flags = IORESOURCE_IRQ,
748 },
749 {
750 .name = "TO",
751 .start = WM831X_IRQ_CHG_TO,
752 .end = WM831X_IRQ_CHG_TO,
753 .flags = IORESOURCE_IRQ,
754 },
755 {
756 .name = "MODE",
757 .start = WM831X_IRQ_CHG_MODE,
758 .end = WM831X_IRQ_CHG_MODE,
759 .flags = IORESOURCE_IRQ,
760 },
761 {
762 .name = "START",
763 .start = WM831X_IRQ_CHG_START,
764 .end = WM831X_IRQ_CHG_START,
765 .flags = IORESOURCE_IRQ,
766 },
767};
768
769static struct resource wm831x_rtc_resources[] = {
770 {
771 .name = "PER",
772 .start = WM831X_IRQ_RTC_PER,
773 .end = WM831X_IRQ_RTC_PER,
774 .flags = IORESOURCE_IRQ,
775 },
776 {
777 .name = "ALM",
778 .start = WM831X_IRQ_RTC_ALM,
779 .end = WM831X_IRQ_RTC_ALM,
780 .flags = IORESOURCE_IRQ,
781 },
782};
783
784static struct resource wm831x_status1_resources[] = {
785 {
786 .start = WM831X_STATUS_LED_1,
787 .end = WM831X_STATUS_LED_1,
788 .flags = IORESOURCE_IO,
789 },
790};
791
792static struct resource wm831x_status2_resources[] = {
793 {
794 .start = WM831X_STATUS_LED_2,
795 .end = WM831X_STATUS_LED_2,
796 .flags = IORESOURCE_IO,
797 },
798};
799
800static struct resource wm831x_touch_resources[] = {
801 {
802 .name = "TCHPD",
803 .start = WM831X_IRQ_TCHPD,
804 .end = WM831X_IRQ_TCHPD,
805 .flags = IORESOURCE_IRQ,
806 },
807 {
808 .name = "TCHDATA",
809 .start = WM831X_IRQ_TCHDATA,
810 .end = WM831X_IRQ_TCHDATA,
811 .flags = IORESOURCE_IRQ,
812 },
813};
814
815static struct resource wm831x_wdt_resources[] = {
816 {
817 .start = WM831X_IRQ_WDOG_TO,
818 .end = WM831X_IRQ_WDOG_TO,
819 .flags = IORESOURCE_IRQ,
820 },
821};
822
823static struct mfd_cell wm8310_devs[] = {
c26964ea
MB
824 {
825 .name = "wm831x-backup",
826 },
d2bedfe7
MB
827 {
828 .name = "wm831x-buckv",
829 .id = 1,
830 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
831 .resources = wm831x_dcdc1_resources,
832 },
833 {
834 .name = "wm831x-buckv",
835 .id = 2,
836 .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources),
837 .resources = wm831x_dcdc2_resources,
838 },
839 {
840 .name = "wm831x-buckp",
841 .id = 3,
842 .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources),
843 .resources = wm831x_dcdc3_resources,
844 },
845 {
846 .name = "wm831x-boostp",
847 .id = 4,
848 .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
849 .resources = wm831x_dcdc4_resources,
850 },
851 {
852 .name = "wm831x-epe",
853 .id = 1,
854 },
855 {
856 .name = "wm831x-epe",
857 .id = 2,
858 },
859 {
860 .name = "wm831x-gpio",
861 .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
862 .resources = wm831x_gpio_resources,
863 },
864 {
865 .name = "wm831x-hwmon",
866 },
867 {
868 .name = "wm831x-isink",
869 .id = 1,
870 .num_resources = ARRAY_SIZE(wm831x_isink1_resources),
871 .resources = wm831x_isink1_resources,
872 },
873 {
874 .name = "wm831x-isink",
875 .id = 2,
876 .num_resources = ARRAY_SIZE(wm831x_isink2_resources),
877 .resources = wm831x_isink2_resources,
878 },
879 {
880 .name = "wm831x-ldo",
881 .id = 1,
882 .num_resources = ARRAY_SIZE(wm831x_ldo1_resources),
883 .resources = wm831x_ldo1_resources,
884 },
885 {
886 .name = "wm831x-ldo",
887 .id = 2,
888 .num_resources = ARRAY_SIZE(wm831x_ldo2_resources),
889 .resources = wm831x_ldo2_resources,
890 },
891 {
892 .name = "wm831x-ldo",
893 .id = 3,
894 .num_resources = ARRAY_SIZE(wm831x_ldo3_resources),
895 .resources = wm831x_ldo3_resources,
896 },
897 {
898 .name = "wm831x-ldo",
899 .id = 4,
900 .num_resources = ARRAY_SIZE(wm831x_ldo4_resources),
901 .resources = wm831x_ldo4_resources,
902 },
903 {
904 .name = "wm831x-ldo",
905 .id = 5,
906 .num_resources = ARRAY_SIZE(wm831x_ldo5_resources),
907 .resources = wm831x_ldo5_resources,
908 },
909 {
910 .name = "wm831x-ldo",
911 .id = 6,
912 .num_resources = ARRAY_SIZE(wm831x_ldo6_resources),
913 .resources = wm831x_ldo6_resources,
914 },
915 {
916 .name = "wm831x-aldo",
917 .id = 7,
918 .num_resources = ARRAY_SIZE(wm831x_ldo7_resources),
919 .resources = wm831x_ldo7_resources,
920 },
921 {
922 .name = "wm831x-aldo",
923 .id = 8,
924 .num_resources = ARRAY_SIZE(wm831x_ldo8_resources),
925 .resources = wm831x_ldo8_resources,
926 },
927 {
928 .name = "wm831x-aldo",
929 .id = 9,
930 .num_resources = ARRAY_SIZE(wm831x_ldo9_resources),
931 .resources = wm831x_ldo9_resources,
932 },
933 {
934 .name = "wm831x-aldo",
935 .id = 10,
936 .num_resources = ARRAY_SIZE(wm831x_ldo10_resources),
937 .resources = wm831x_ldo10_resources,
938 },
939 {
940 .name = "wm831x-alive-ldo",
941 .id = 11,
942 .num_resources = ARRAY_SIZE(wm831x_ldo11_resources),
943 .resources = wm831x_ldo11_resources,
944 },
945 {
946 .name = "wm831x-on",
947 .num_resources = ARRAY_SIZE(wm831x_on_resources),
948 .resources = wm831x_on_resources,
949 },
950 {
951 .name = "wm831x-power",
952 .num_resources = ARRAY_SIZE(wm831x_power_resources),
953 .resources = wm831x_power_resources,
954 },
955 {
956 .name = "wm831x-rtc",
957 .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
958 .resources = wm831x_rtc_resources,
959 },
960 {
961 .name = "wm831x-status",
962 .id = 1,
963 .num_resources = ARRAY_SIZE(wm831x_status1_resources),
964 .resources = wm831x_status1_resources,
965 },
966 {
967 .name = "wm831x-status",
968 .id = 2,
969 .num_resources = ARRAY_SIZE(wm831x_status2_resources),
970 .resources = wm831x_status2_resources,
971 },
972 {
973 .name = "wm831x-watchdog",
974 .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
975 .resources = wm831x_wdt_resources,
976 },
977};
978
979static struct mfd_cell wm8311_devs[] = {
c26964ea
MB
980 {
981 .name = "wm831x-backup",
982 },
d2bedfe7
MB
983 {
984 .name = "wm831x-buckv",
985 .id = 1,
986 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
987 .resources = wm831x_dcdc1_resources,
988 },
989 {
990 .name = "wm831x-buckv",
991 .id = 2,
992 .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources),
993 .resources = wm831x_dcdc2_resources,
994 },
995 {
996 .name = "wm831x-buckp",
997 .id = 3,
998 .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources),
999 .resources = wm831x_dcdc3_resources,
1000 },
1001 {
1002 .name = "wm831x-boostp",
1003 .id = 4,
1004 .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
1005 .resources = wm831x_dcdc4_resources,
1006 },
1007 {
1008 .name = "wm831x-epe",
1009 .id = 1,
1010 },
1011 {
1012 .name = "wm831x-epe",
1013 .id = 2,
1014 },
1015 {
1016 .name = "wm831x-gpio",
1017 .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
1018 .resources = wm831x_gpio_resources,
1019 },
1020 {
1021 .name = "wm831x-hwmon",
1022 },
1023 {
1024 .name = "wm831x-isink",
1025 .id = 1,
1026 .num_resources = ARRAY_SIZE(wm831x_isink1_resources),
1027 .resources = wm831x_isink1_resources,
1028 },
1029 {
1030 .name = "wm831x-isink",
1031 .id = 2,
1032 .num_resources = ARRAY_SIZE(wm831x_isink2_resources),
1033 .resources = wm831x_isink2_resources,
1034 },
1035 {
1036 .name = "wm831x-ldo",
1037 .id = 1,
1038 .num_resources = ARRAY_SIZE(wm831x_ldo1_resources),
1039 .resources = wm831x_ldo1_resources,
1040 },
1041 {
1042 .name = "wm831x-ldo",
1043 .id = 2,
1044 .num_resources = ARRAY_SIZE(wm831x_ldo2_resources),
1045 .resources = wm831x_ldo2_resources,
1046 },
1047 {
1048 .name = "wm831x-ldo",
1049 .id = 3,
1050 .num_resources = ARRAY_SIZE(wm831x_ldo3_resources),
1051 .resources = wm831x_ldo3_resources,
1052 },
1053 {
1054 .name = "wm831x-ldo",
1055 .id = 4,
1056 .num_resources = ARRAY_SIZE(wm831x_ldo4_resources),
1057 .resources = wm831x_ldo4_resources,
1058 },
1059 {
1060 .name = "wm831x-ldo",
1061 .id = 5,
1062 .num_resources = ARRAY_SIZE(wm831x_ldo5_resources),
1063 .resources = wm831x_ldo5_resources,
1064 },
1065 {
1066 .name = "wm831x-aldo",
1067 .id = 7,
1068 .num_resources = ARRAY_SIZE(wm831x_ldo7_resources),
1069 .resources = wm831x_ldo7_resources,
1070 },
1071 {
1072 .name = "wm831x-alive-ldo",
1073 .id = 11,
1074 .num_resources = ARRAY_SIZE(wm831x_ldo11_resources),
1075 .resources = wm831x_ldo11_resources,
1076 },
1077 {
1078 .name = "wm831x-on",
1079 .num_resources = ARRAY_SIZE(wm831x_on_resources),
1080 .resources = wm831x_on_resources,
1081 },
1082 {
1083 .name = "wm831x-power",
1084 .num_resources = ARRAY_SIZE(wm831x_power_resources),
1085 .resources = wm831x_power_resources,
1086 },
1087 {
1088 .name = "wm831x-rtc",
1089 .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
1090 .resources = wm831x_rtc_resources,
1091 },
1092 {
1093 .name = "wm831x-status",
1094 .id = 1,
1095 .num_resources = ARRAY_SIZE(wm831x_status1_resources),
1096 .resources = wm831x_status1_resources,
1097 },
1098 {
1099 .name = "wm831x-status",
1100 .id = 2,
1101 .num_resources = ARRAY_SIZE(wm831x_status2_resources),
1102 .resources = wm831x_status2_resources,
1103 },
1104 {
1105 .name = "wm831x-touch",
1106 .num_resources = ARRAY_SIZE(wm831x_touch_resources),
1107 .resources = wm831x_touch_resources,
1108 },
1109 {
1110 .name = "wm831x-watchdog",
1111 .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
1112 .resources = wm831x_wdt_resources,
1113 },
1114};
1115
1116static struct mfd_cell wm8312_devs[] = {
c26964ea
MB
1117 {
1118 .name = "wm831x-backup",
1119 },
d2bedfe7
MB
1120 {
1121 .name = "wm831x-buckv",
1122 .id = 1,
1123 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
1124 .resources = wm831x_dcdc1_resources,
1125 },
1126 {
1127 .name = "wm831x-buckv",
1128 .id = 2,
1129 .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources),
1130 .resources = wm831x_dcdc2_resources,
1131 },
1132 {
1133 .name = "wm831x-buckp",
1134 .id = 3,
1135 .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources),
1136 .resources = wm831x_dcdc3_resources,
1137 },
1138 {
1139 .name = "wm831x-boostp",
1140 .id = 4,
1141 .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
1142 .resources = wm831x_dcdc4_resources,
1143 },
1144 {
1145 .name = "wm831x-epe",
1146 .id = 1,
1147 },
1148 {
1149 .name = "wm831x-epe",
1150 .id = 2,
1151 },
1152 {
1153 .name = "wm831x-gpio",
1154 .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
1155 .resources = wm831x_gpio_resources,
1156 },
1157 {
1158 .name = "wm831x-hwmon",
1159 },
1160 {
1161 .name = "wm831x-isink",
1162 .id = 1,
1163 .num_resources = ARRAY_SIZE(wm831x_isink1_resources),
1164 .resources = wm831x_isink1_resources,
1165 },
1166 {
1167 .name = "wm831x-isink",
1168 .id = 2,
1169 .num_resources = ARRAY_SIZE(wm831x_isink2_resources),
1170 .resources = wm831x_isink2_resources,
1171 },
1172 {
1173 .name = "wm831x-ldo",
1174 .id = 1,
1175 .num_resources = ARRAY_SIZE(wm831x_ldo1_resources),
1176 .resources = wm831x_ldo1_resources,
1177 },
1178 {
1179 .name = "wm831x-ldo",
1180 .id = 2,
1181 .num_resources = ARRAY_SIZE(wm831x_ldo2_resources),
1182 .resources = wm831x_ldo2_resources,
1183 },
1184 {
1185 .name = "wm831x-ldo",
1186 .id = 3,
1187 .num_resources = ARRAY_SIZE(wm831x_ldo3_resources),
1188 .resources = wm831x_ldo3_resources,
1189 },
1190 {
1191 .name = "wm831x-ldo",
1192 .id = 4,
1193 .num_resources = ARRAY_SIZE(wm831x_ldo4_resources),
1194 .resources = wm831x_ldo4_resources,
1195 },
1196 {
1197 .name = "wm831x-ldo",
1198 .id = 5,
1199 .num_resources = ARRAY_SIZE(wm831x_ldo5_resources),
1200 .resources = wm831x_ldo5_resources,
1201 },
1202 {
1203 .name = "wm831x-ldo",
1204 .id = 6,
1205 .num_resources = ARRAY_SIZE(wm831x_ldo6_resources),
1206 .resources = wm831x_ldo6_resources,
1207 },
1208 {
1209 .name = "wm831x-aldo",
1210 .id = 7,
1211 .num_resources = ARRAY_SIZE(wm831x_ldo7_resources),
1212 .resources = wm831x_ldo7_resources,
1213 },
1214 {
1215 .name = "wm831x-aldo",
1216 .id = 8,
1217 .num_resources = ARRAY_SIZE(wm831x_ldo8_resources),
1218 .resources = wm831x_ldo8_resources,
1219 },
1220 {
1221 .name = "wm831x-aldo",
1222 .id = 9,
1223 .num_resources = ARRAY_SIZE(wm831x_ldo9_resources),
1224 .resources = wm831x_ldo9_resources,
1225 },
1226 {
1227 .name = "wm831x-aldo",
1228 .id = 10,
1229 .num_resources = ARRAY_SIZE(wm831x_ldo10_resources),
1230 .resources = wm831x_ldo10_resources,
1231 },
1232 {
1233 .name = "wm831x-alive-ldo",
1234 .id = 11,
1235 .num_resources = ARRAY_SIZE(wm831x_ldo11_resources),
1236 .resources = wm831x_ldo11_resources,
1237 },
1238 {
1239 .name = "wm831x-on",
1240 .num_resources = ARRAY_SIZE(wm831x_on_resources),
1241 .resources = wm831x_on_resources,
1242 },
1243 {
1244 .name = "wm831x-power",
1245 .num_resources = ARRAY_SIZE(wm831x_power_resources),
1246 .resources = wm831x_power_resources,
1247 },
1248 {
1249 .name = "wm831x-rtc",
1250 .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
1251 .resources = wm831x_rtc_resources,
1252 },
1253 {
1254 .name = "wm831x-status",
1255 .id = 1,
1256 .num_resources = ARRAY_SIZE(wm831x_status1_resources),
1257 .resources = wm831x_status1_resources,
1258 },
1259 {
1260 .name = "wm831x-status",
1261 .id = 2,
1262 .num_resources = ARRAY_SIZE(wm831x_status2_resources),
1263 .resources = wm831x_status2_resources,
1264 },
1265 {
1266 .name = "wm831x-touch",
1267 .num_resources = ARRAY_SIZE(wm831x_touch_resources),
1268 .resources = wm831x_touch_resources,
1269 },
1270 {
1271 .name = "wm831x-watchdog",
1272 .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
1273 .resources = wm831x_wdt_resources,
1274 },
1275};
1276
d4e0a89e
MB
1277static struct mfd_cell wm8320_devs[] = {
1278 {
1279 .name = "wm831x-backup",
1280 },
1281 {
1282 .name = "wm831x-buckv",
1283 .id = 1,
1284 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
1285 .resources = wm831x_dcdc1_resources,
1286 },
1287 {
1288 .name = "wm831x-buckv",
1289 .id = 2,
1290 .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources),
1291 .resources = wm831x_dcdc2_resources,
1292 },
1293 {
1294 .name = "wm831x-buckp",
1295 .id = 3,
1296 .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources),
1297 .resources = wm831x_dcdc3_resources,
1298 },
1299 {
1300 .name = "wm831x-buckp",
1301 .id = 4,
1302 .num_resources = ARRAY_SIZE(wm8320_dcdc4_buck_resources),
1303 .resources = wm8320_dcdc4_buck_resources,
1304 },
1305 {
1306 .name = "wm831x-gpio",
1307 .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
1308 .resources = wm831x_gpio_resources,
1309 },
1310 {
1311 .name = "wm831x-hwmon",
1312 },
1313 {
1314 .name = "wm831x-ldo",
1315 .id = 1,
1316 .num_resources = ARRAY_SIZE(wm831x_ldo1_resources),
1317 .resources = wm831x_ldo1_resources,
1318 },
1319 {
1320 .name = "wm831x-ldo",
1321 .id = 2,
1322 .num_resources = ARRAY_SIZE(wm831x_ldo2_resources),
1323 .resources = wm831x_ldo2_resources,
1324 },
1325 {
1326 .name = "wm831x-ldo",
1327 .id = 3,
1328 .num_resources = ARRAY_SIZE(wm831x_ldo3_resources),
1329 .resources = wm831x_ldo3_resources,
1330 },
1331 {
1332 .name = "wm831x-ldo",
1333 .id = 4,
1334 .num_resources = ARRAY_SIZE(wm831x_ldo4_resources),
1335 .resources = wm831x_ldo4_resources,
1336 },
1337 {
1338 .name = "wm831x-ldo",
1339 .id = 5,
1340 .num_resources = ARRAY_SIZE(wm831x_ldo5_resources),
1341 .resources = wm831x_ldo5_resources,
1342 },
1343 {
1344 .name = "wm831x-ldo",
1345 .id = 6,
1346 .num_resources = ARRAY_SIZE(wm831x_ldo6_resources),
1347 .resources = wm831x_ldo6_resources,
1348 },
1349 {
1350 .name = "wm831x-aldo",
1351 .id = 7,
1352 .num_resources = ARRAY_SIZE(wm831x_ldo7_resources),
1353 .resources = wm831x_ldo7_resources,
1354 },
1355 {
1356 .name = "wm831x-aldo",
1357 .id = 8,
1358 .num_resources = ARRAY_SIZE(wm831x_ldo8_resources),
1359 .resources = wm831x_ldo8_resources,
1360 },
1361 {
1362 .name = "wm831x-aldo",
1363 .id = 9,
1364 .num_resources = ARRAY_SIZE(wm831x_ldo9_resources),
1365 .resources = wm831x_ldo9_resources,
1366 },
1367 {
1368 .name = "wm831x-aldo",
1369 .id = 10,
1370 .num_resources = ARRAY_SIZE(wm831x_ldo10_resources),
1371 .resources = wm831x_ldo10_resources,
1372 },
1373 {
1374 .name = "wm831x-alive-ldo",
1375 .id = 11,
1376 .num_resources = ARRAY_SIZE(wm831x_ldo11_resources),
1377 .resources = wm831x_ldo11_resources,
1378 },
1379 {
1380 .name = "wm831x-on",
1381 .num_resources = ARRAY_SIZE(wm831x_on_resources),
1382 .resources = wm831x_on_resources,
1383 },
1384 {
1385 .name = "wm831x-rtc",
1386 .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
1387 .resources = wm831x_rtc_resources,
1388 },
1389 {
1390 .name = "wm831x-status",
1391 .id = 1,
1392 .num_resources = ARRAY_SIZE(wm831x_status1_resources),
1393 .resources = wm831x_status1_resources,
1394 },
1395 {
1396 .name = "wm831x-status",
1397 .id = 2,
1398 .num_resources = ARRAY_SIZE(wm831x_status2_resources),
1399 .resources = wm831x_status2_resources,
1400 },
1401 {
1402 .name = "wm831x-watchdog",
1403 .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
1404 .resources = wm831x_wdt_resources,
1405 },
1406};
1407
63aed85e
MB
1408static struct mfd_cell backlight_devs[] = {
1409 {
1410 .name = "wm831x-backlight",
1411 },
1412};
1413
d2bedfe7
MB
1414/*
1415 * Instantiate the generic non-control parts of the device.
1416 */
1417static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1418{
1419 struct wm831x_pdata *pdata = wm831x->dev->platform_data;
1420 int rev;
1421 enum wm831x_parent parent;
1422 int ret;
1423
1424 mutex_init(&wm831x->io_lock);
1425 mutex_init(&wm831x->key_lock);
7e9f9fd4 1426 mutex_init(&wm831x->auxadc_lock);
473fe736 1427 init_completion(&wm831x->auxadc_done);
d2bedfe7
MB
1428 dev_set_drvdata(wm831x->dev, wm831x);
1429
1430 ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
1431 if (ret < 0) {
1432 dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
1433 goto err;
1434 }
1435 if (ret != 0x6204) {
1436 dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
1437 ret = -EINVAL;
1438 goto err;
1439 }
1440
1441 ret = wm831x_reg_read(wm831x, WM831X_REVISION);
1442 if (ret < 0) {
1443 dev_err(wm831x->dev, "Failed to read revision: %d\n", ret);
1444 goto err;
1445 }
1446 rev = (ret & WM831X_PARENT_REV_MASK) >> WM831X_PARENT_REV_SHIFT;
1447
1448 ret = wm831x_reg_read(wm831x, WM831X_RESET_ID);
1449 if (ret < 0) {
1450 dev_err(wm831x->dev, "Failed to read device ID: %d\n", ret);
1451 goto err;
1452 }
1453
894362f5
MB
1454 /* Some engineering samples do not have the ID set, rely on
1455 * the device being registered correctly.
1456 */
1457 if (ret == 0) {
1458 dev_info(wm831x->dev, "Device is an engineering sample\n");
1459 ret = id;
1460 }
1461
d2bedfe7 1462 switch (ret) {
894362f5 1463 case WM8310:
d2bedfe7 1464 parent = WM8310;
6f2ecaae 1465 wm831x->num_gpio = 16;
f92e8f81
MB
1466 if (rev > 0) {
1467 wm831x->has_gpio_ena = 1;
1468 wm831x->has_cs_sts = 1;
1469 }
1470
894362f5 1471 dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev);
d2bedfe7
MB
1472 break;
1473
894362f5 1474 case WM8311:
d2bedfe7 1475 parent = WM8311;
6f2ecaae 1476 wm831x->num_gpio = 16;
f92e8f81
MB
1477 if (rev > 0) {
1478 wm831x->has_gpio_ena = 1;
1479 wm831x->has_cs_sts = 1;
1480 }
1481
894362f5 1482 dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev);
d2bedfe7
MB
1483 break;
1484
894362f5 1485 case WM8312:
d2bedfe7 1486 parent = WM8312;
6f2ecaae 1487 wm831x->num_gpio = 16;
f92e8f81
MB
1488 if (rev > 0) {
1489 wm831x->has_gpio_ena = 1;
1490 wm831x->has_cs_sts = 1;
1491 }
1492
894362f5 1493 dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev);
d2bedfe7
MB
1494 break;
1495
d4e0a89e
MB
1496 case WM8320:
1497 parent = WM8320;
1498 wm831x->num_gpio = 12;
1499 dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev);
1500 break;
1501
d2bedfe7
MB
1502 default:
1503 dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
1504 ret = -EINVAL;
1505 goto err;
1506 }
1507
1508 /* This will need revisiting in future but is OK for all
1509 * current parts.
1510 */
1511 if (parent != id)
894362f5 1512 dev_warn(wm831x->dev, "Device was registered as a WM%lx\n",
d2bedfe7
MB
1513 id);
1514
1515 /* Bootstrap the user key */
1516 ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY);
1517 if (ret < 0) {
1518 dev_err(wm831x->dev, "Failed to read security key: %d\n", ret);
1519 goto err;
1520 }
1521 if (ret != 0) {
1522 dev_warn(wm831x->dev, "Security key had non-zero value %x\n",
1523 ret);
1524 wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0);
1525 }
1526 wm831x->locked = 1;
1527
1528 if (pdata && pdata->pre_init) {
1529 ret = pdata->pre_init(wm831x);
1530 if (ret != 0) {
1531 dev_err(wm831x->dev, "pre_init() failed: %d\n", ret);
1532 goto err;
1533 }
1534 }
1535
7d4d0a3e
MB
1536 ret = wm831x_irq_init(wm831x, irq);
1537 if (ret != 0)
1538 goto err;
1539
473fe736
MB
1540 if (wm831x->irq_base) {
1541 ret = request_threaded_irq(wm831x->irq_base +
1542 WM831X_IRQ_AUXADC_DATA,
1543 NULL, wm831x_auxadc_irq, 0,
1544 "auxadc", wm831x);
1545 if (ret < 0)
1546 dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n",
1547 ret);
1548 }
1549
d2bedfe7
MB
1550 /* The core device is up, instantiate the subdevices. */
1551 switch (parent) {
1552 case WM8310:
1553 ret = mfd_add_devices(wm831x->dev, -1,
1554 wm8310_devs, ARRAY_SIZE(wm8310_devs),
5fb4d38b 1555 NULL, wm831x->irq_base);
d2bedfe7
MB
1556 break;
1557
1558 case WM8311:
1559 ret = mfd_add_devices(wm831x->dev, -1,
1560 wm8311_devs, ARRAY_SIZE(wm8311_devs),
5fb4d38b 1561 NULL, wm831x->irq_base);
d2bedfe7
MB
1562 break;
1563
1564 case WM8312:
1565 ret = mfd_add_devices(wm831x->dev, -1,
1566 wm8312_devs, ARRAY_SIZE(wm8312_devs),
5fb4d38b 1567 NULL, wm831x->irq_base);
d2bedfe7
MB
1568 break;
1569
d4e0a89e
MB
1570 case WM8320:
1571 ret = mfd_add_devices(wm831x->dev, -1,
1572 wm8320_devs, ARRAY_SIZE(wm8320_devs),
1573 NULL, 0);
1574 break;
1575
d2bedfe7
MB
1576 default:
1577 /* If this happens the bus probe function is buggy */
1578 BUG();
1579 }
1580
1581 if (ret != 0) {
1582 dev_err(wm831x->dev, "Failed to add children\n");
7d4d0a3e 1583 goto err_irq;
d2bedfe7
MB
1584 }
1585
63aed85e
MB
1586 if (pdata && pdata->backlight) {
1587 /* Treat errors as non-critical */
1588 ret = mfd_add_devices(wm831x->dev, -1, backlight_devs,
5fb4d38b
MB
1589 ARRAY_SIZE(backlight_devs), NULL,
1590 wm831x->irq_base);
63aed85e
MB
1591 if (ret < 0)
1592 dev_err(wm831x->dev, "Failed to add backlight: %d\n",
1593 ret);
1594 }
1595
6704e517
MB
1596 wm831x_otp_init(wm831x);
1597
d2bedfe7
MB
1598 if (pdata && pdata->post_init) {
1599 ret = pdata->post_init(wm831x);
1600 if (ret != 0) {
1601 dev_err(wm831x->dev, "post_init() failed: %d\n", ret);
7d4d0a3e 1602 goto err_irq;
d2bedfe7
MB
1603 }
1604 }
1605
1606 return 0;
1607
7d4d0a3e
MB
1608err_irq:
1609 wm831x_irq_exit(wm831x);
d2bedfe7
MB
1610err:
1611 mfd_remove_devices(wm831x->dev);
1612 kfree(wm831x);
1613 return ret;
1614}
1615
1616static void wm831x_device_exit(struct wm831x *wm831x)
1617{
6704e517 1618 wm831x_otp_exit(wm831x);
d2bedfe7 1619 mfd_remove_devices(wm831x->dev);
473fe736
MB
1620 if (wm831x->irq_base)
1621 free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
7d4d0a3e 1622 wm831x_irq_exit(wm831x);
d2bedfe7
MB
1623 kfree(wm831x);
1624}
1625
1626static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg,
1627 int bytes, void *dest)
1628{
1629 struct i2c_client *i2c = wm831x->control_data;
1630 int ret;
1631 u16 r = cpu_to_be16(reg);
1632
1633 ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
1634 if (ret < 0)
1635 return ret;
1636 if (ret != 2)
1637 return -EIO;
1638
1639 ret = i2c_master_recv(i2c, dest, bytes);
1640 if (ret < 0)
1641 return ret;
1642 if (ret != bytes)
1643 return -EIO;
1644 return 0;
1645}
1646
1647/* Currently we allocate the write buffer on the stack; this is OK for
1648 * small writes - if we need to do large writes this will need to be
1649 * revised.
1650 */
1651static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg,
1652 int bytes, void *src)
1653{
1654 struct i2c_client *i2c = wm831x->control_data;
1655 unsigned char msg[bytes + 2];
1656 int ret;
1657
1658 reg = cpu_to_be16(reg);
1659 memcpy(&msg[0], &reg, 2);
1660 memcpy(&msg[2], src, bytes);
1661
1662 ret = i2c_master_send(i2c, msg, bytes + 2);
1663 if (ret < 0)
1664 return ret;
1665 if (ret < bytes + 2)
1666 return -EIO;
1667
1668 return 0;
1669}
1670
1671static int wm831x_i2c_probe(struct i2c_client *i2c,
1672 const struct i2c_device_id *id)
1673{
1674 struct wm831x *wm831x;
1675
1676 wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
1677 if (wm831x == NULL) {
1678 kfree(i2c);
1679 return -ENOMEM;
1680 }
1681
1682 i2c_set_clientdata(i2c, wm831x);
1683 wm831x->dev = &i2c->dev;
1684 wm831x->control_data = i2c;
1685 wm831x->read_dev = wm831x_i2c_read_device;
1686 wm831x->write_dev = wm831x_i2c_write_device;
1687
1688 return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
1689}
1690
1691static int wm831x_i2c_remove(struct i2c_client *i2c)
1692{
1693 struct wm831x *wm831x = i2c_get_clientdata(i2c);
1694
1695 wm831x_device_exit(wm831x);
1696
1697 return 0;
1698}
1699
1700static const struct i2c_device_id wm831x_i2c_id[] = {
1701 { "wm8310", WM8310 },
1702 { "wm8311", WM8311 },
1703 { "wm8312", WM8312 },
d4e0a89e 1704 { "wm8320", WM8320 },
d2bedfe7
MB
1705 { }
1706};
1707MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
1708
1709
1710static struct i2c_driver wm831x_i2c_driver = {
1711 .driver = {
1712 .name = "wm831x",
1713 .owner = THIS_MODULE,
1714 },
1715 .probe = wm831x_i2c_probe,
1716 .remove = wm831x_i2c_remove,
1717 .id_table = wm831x_i2c_id,
1718};
1719
1720static int __init wm831x_i2c_init(void)
1721{
1722 int ret;
1723
1724 ret = i2c_add_driver(&wm831x_i2c_driver);
1725 if (ret != 0)
1726 pr_err("Failed to register wm831x I2C driver: %d\n", ret);
1727
1728 return ret;
1729}
1730subsys_initcall(wm831x_i2c_init);
1731
1732static void __exit wm831x_i2c_exit(void)
1733{
1734 i2c_del_driver(&wm831x_i2c_driver);
1735}
1736module_exit(wm831x_i2c_exit);
1737
1738MODULE_DESCRIPTION("I2C support for the WM831X AudioPlus PMIC");
1739MODULE_LICENSE("GPL");
1740MODULE_AUTHOR("Mark Brown");