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