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