blob: 42bef1dd2ca1028d5d9fb45a8827340086b491d2 [file] [log] [blame]
Mark Brownd2bedfe2009-07-27 14:45:52 +01001/*
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>
Mark Brown7e9f9fd2009-07-27 14:45:54 +010018#include <linux/bcd.h>
19#include <linux/delay.h>
Mark Brownd2bedfe2009-07-27 14:45:52 +010020#include <linux/mfd/core.h>
21
22#include <linux/mfd/wm831x/core.h>
23#include <linux/mfd/wm831x/pdata.h>
Mark Brown7d4d0a32009-07-27 14:45:53 +010024#include <linux/mfd/wm831x/irq.h>
Mark Brown7e9f9fd2009-07-27 14:45:54 +010025#include <linux/mfd/wm831x/auxadc.h>
Mark Brownd2bedfe2009-07-27 14:45:52 +010026
27enum wm831x_parent {
28 WM8310 = 0,
29 WM8311 = 1,
30 WM8312 = 2,
31};
32
33static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg)
34{
35 if (!wm831x->locked)
36 return 0;
37
38 switch (reg) {
39 case WM831X_WATCHDOG:
40 case WM831X_DC4_CONTROL:
41 case WM831X_ON_PIN_CONTROL:
42 case WM831X_BACKUP_CHARGER_CONTROL:
43 case WM831X_CHARGER_CONTROL_1:
44 case WM831X_CHARGER_CONTROL_2:
45 return 1;
46
47 default:
48 return 0;
49 }
50}
51
52/**
53 * wm831x_reg_unlock: Unlock user keyed registers
54 *
55 * The WM831x has a user key preventing writes to particularly
56 * critical registers. This function locks those registers,
57 * allowing writes to them.
58 */
59void wm831x_reg_lock(struct wm831x *wm831x)
60{
61 int ret;
62
63 ret = wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0);
64 if (ret == 0) {
65 dev_vdbg(wm831x->dev, "Registers locked\n");
66
67 mutex_lock(&wm831x->io_lock);
68 WARN_ON(wm831x->locked);
69 wm831x->locked = 1;
70 mutex_unlock(&wm831x->io_lock);
71 } else {
72 dev_err(wm831x->dev, "Failed to lock registers: %d\n", ret);
73 }
74
75}
76EXPORT_SYMBOL_GPL(wm831x_reg_lock);
77
78/**
79 * wm831x_reg_unlock: Unlock user keyed registers
80 *
81 * The WM831x has a user key preventing writes to particularly
82 * critical registers. This function locks those registers,
83 * preventing spurious writes.
84 */
85int wm831x_reg_unlock(struct wm831x *wm831x)
86{
87 int ret;
88
89 /* 0x9716 is the value required to unlock the registers */
90 ret = wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0x9716);
91 if (ret == 0) {
92 dev_vdbg(wm831x->dev, "Registers unlocked\n");
93
94 mutex_lock(&wm831x->io_lock);
95 WARN_ON(!wm831x->locked);
96 wm831x->locked = 0;
97 mutex_unlock(&wm831x->io_lock);
98 }
99
100 return ret;
101}
102EXPORT_SYMBOL_GPL(wm831x_reg_unlock);
103
104static int wm831x_read(struct wm831x *wm831x, unsigned short reg,
105 int bytes, void *dest)
106{
107 int ret, i;
108 u16 *buf = dest;
109
110 BUG_ON(bytes % 2);
111 BUG_ON(bytes <= 0);
112
113 ret = wm831x->read_dev(wm831x, reg, bytes, dest);
114 if (ret < 0)
115 return ret;
116
117 for (i = 0; i < bytes / 2; i++) {
118 buf[i] = be16_to_cpu(buf[i]);
119
120 dev_vdbg(wm831x->dev, "Read %04x from R%d(0x%x)\n",
121 buf[i], reg + i, reg + i);
122 }
123
124 return 0;
125}
126
127/**
128 * wm831x_reg_read: Read a single WM831x register.
129 *
130 * @wm831x: Device to read from.
131 * @reg: Register to read.
132 */
133int wm831x_reg_read(struct wm831x *wm831x, unsigned short reg)
134{
135 unsigned short val;
136 int ret;
137
138 mutex_lock(&wm831x->io_lock);
139
140 ret = wm831x_read(wm831x, reg, 2, &val);
141
142 mutex_unlock(&wm831x->io_lock);
143
144 if (ret < 0)
145 return ret;
146 else
147 return val;
148}
149EXPORT_SYMBOL_GPL(wm831x_reg_read);
150
151/**
152 * wm831x_bulk_read: Read multiple WM831x registers
153 *
154 * @wm831x: Device to read from
155 * @reg: First register
156 * @count: Number of registers
157 * @buf: Buffer to fill.
158 */
159int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
160 int count, u16 *buf)
161{
162 int ret;
163
164 mutex_lock(&wm831x->io_lock);
165
166 ret = wm831x_read(wm831x, reg, count * 2, buf);
167
168 mutex_unlock(&wm831x->io_lock);
169
170 return ret;
171}
172EXPORT_SYMBOL_GPL(wm831x_bulk_read);
173
174static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
175 int bytes, void *src)
176{
177 u16 *buf = src;
178 int i;
179
180 BUG_ON(bytes % 2);
181 BUG_ON(bytes <= 0);
182
183 for (i = 0; i < bytes / 2; i++) {
184 if (wm831x_reg_locked(wm831x, reg))
185 return -EPERM;
186
187 dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n",
188 buf[i], reg + i, reg + i);
189
190 buf[i] = cpu_to_be16(buf[i]);
191 }
192
193 return wm831x->write_dev(wm831x, reg, bytes, src);
194}
195
196/**
197 * wm831x_reg_write: Write a single WM831x register.
198 *
199 * @wm831x: Device to write to.
200 * @reg: Register to write to.
201 * @val: Value to write.
202 */
203int wm831x_reg_write(struct wm831x *wm831x, unsigned short reg,
204 unsigned short val)
205{
206 int ret;
207
208 mutex_lock(&wm831x->io_lock);
209
210 ret = wm831x_write(wm831x, reg, 2, &val);
211
212 mutex_unlock(&wm831x->io_lock);
213
214 return ret;
215}
216EXPORT_SYMBOL_GPL(wm831x_reg_write);
217
218/**
219 * wm831x_set_bits: Set the value of a bitfield in a WM831x register
220 *
221 * @wm831x: Device to write to.
222 * @reg: Register to write to.
223 * @mask: Mask of bits to set.
224 * @val: Value to set (unshifted)
225 */
226int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
227 unsigned short mask, unsigned short val)
228{
229 int ret;
230 u16 r;
231
232 mutex_lock(&wm831x->io_lock);
233
234 ret = wm831x_read(wm831x, reg, 2, &r);
235 if (ret < 0)
236 goto out;
237
238 r &= ~mask;
239 r |= val;
240
241 ret = wm831x_write(wm831x, reg, 2, &r);
242
243out:
244 mutex_unlock(&wm831x->io_lock);
245
246 return ret;
247}
248EXPORT_SYMBOL_GPL(wm831x_set_bits);
249
Mark Brown7e9f9fd2009-07-27 14:45:54 +0100250/**
251 * wm831x_auxadc_read: Read a value from the WM831x AUXADC
252 *
253 * @wm831x: Device to read from.
254 * @input: AUXADC input to read.
255 */
256int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
257{
258 int tries = 10;
259 int ret, src;
260
261 mutex_lock(&wm831x->auxadc_lock);
262
263 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
264 WM831X_AUX_ENA, WM831X_AUX_ENA);
265 if (ret < 0) {
266 dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret);
267 goto out;
268 }
269
270 /* We force a single source at present */
271 src = input;
272 ret = wm831x_reg_write(wm831x, WM831X_AUXADC_SOURCE,
273 1 << src);
274 if (ret < 0) {
275 dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret);
276 goto out;
277 }
278
279 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
280 WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
281 if (ret < 0) {
282 dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret);
283 goto disable;
284 }
285
286 do {
287 msleep(1);
288
289 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL);
290 if (ret < 0)
291 ret = WM831X_AUX_CVT_ENA;
292 } while ((ret & WM831X_AUX_CVT_ENA) && --tries);
293
294 if (ret & WM831X_AUX_CVT_ENA) {
295 dev_err(wm831x->dev, "Timed out reading AUXADC\n");
296 ret = -EBUSY;
297 goto disable;
298 }
299
300 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
301 if (ret < 0) {
302 dev_err(wm831x->dev, "Failed to read AUXADC data: %d\n", ret);
303 } else {
304 src = ((ret & WM831X_AUX_DATA_SRC_MASK)
305 >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
306
307 if (src == 14)
308 src = WM831X_AUX_CAL;
309
310 if (src != input) {
311 dev_err(wm831x->dev, "Data from source %d not %d\n",
312 src, input);
313 ret = -EINVAL;
314 } else {
315 ret &= WM831X_AUX_DATA_MASK;
316 }
317 }
318
319disable:
320 wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0);
321out:
322 mutex_unlock(&wm831x->auxadc_lock);
323 return ret;
324}
325EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
326
327/**
328 * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
329 *
330 * @wm831x: Device to read from.
331 * @input: AUXADC input to read.
332 */
333int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input)
334{
335 int ret;
336
337 ret = wm831x_auxadc_read(wm831x, input);
338 if (ret < 0)
339 return ret;
340
341 ret *= 1465;
342
343 return ret;
344}
345EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv);
346
Mark Brownd2bedfe2009-07-27 14:45:52 +0100347static struct resource wm831x_dcdc1_resources[] = {
348 {
349 .start = WM831X_DC1_CONTROL_1,
350 .end = WM831X_DC1_DVS_CONTROL,
351 .flags = IORESOURCE_IO,
352 },
353 {
354 .name = "UV",
355 .start = WM831X_IRQ_UV_DC1,
356 .end = WM831X_IRQ_UV_DC1,
357 .flags = IORESOURCE_IRQ,
358 },
359 {
360 .name = "HC",
361 .start = WM831X_IRQ_HC_DC1,
362 .end = WM831X_IRQ_HC_DC1,
363 .flags = IORESOURCE_IRQ,
364 },
365};
366
367
368static struct resource wm831x_dcdc2_resources[] = {
369 {
370 .start = WM831X_DC2_CONTROL_1,
371 .end = WM831X_DC2_DVS_CONTROL,
372 .flags = IORESOURCE_IO,
373 },
374 {
375 .name = "UV",
376 .start = WM831X_IRQ_UV_DC2,
377 .end = WM831X_IRQ_UV_DC2,
378 .flags = IORESOURCE_IRQ,
379 },
380 {
381 .name = "HC",
382 .start = WM831X_IRQ_HC_DC2,
383 .end = WM831X_IRQ_HC_DC2,
384 .flags = IORESOURCE_IRQ,
385 },
386};
387
388static struct resource wm831x_dcdc3_resources[] = {
389 {
390 .start = WM831X_DC3_CONTROL_1,
391 .end = WM831X_DC3_SLEEP_CONTROL,
392 .flags = IORESOURCE_IO,
393 },
394 {
395 .name = "UV",
396 .start = WM831X_IRQ_UV_DC3,
397 .end = WM831X_IRQ_UV_DC3,
398 .flags = IORESOURCE_IRQ,
399 },
400};
401
402static struct resource wm831x_dcdc4_resources[] = {
403 {
404 .start = WM831X_DC4_CONTROL,
405 .end = WM831X_DC4_SLEEP_CONTROL,
406 .flags = IORESOURCE_IO,
407 },
408 {
409 .name = "UV",
410 .start = WM831X_IRQ_UV_DC4,
411 .end = WM831X_IRQ_UV_DC4,
412 .flags = IORESOURCE_IRQ,
413 },
414};
415
416static struct resource wm831x_gpio_resources[] = {
417 {
418 .start = WM831X_IRQ_GPIO_1,
419 .end = WM831X_IRQ_GPIO_16,
420 .flags = IORESOURCE_IRQ,
421 },
422};
423
424static struct resource wm831x_isink1_resources[] = {
425 {
426 .start = WM831X_CURRENT_SINK_1,
427 .end = WM831X_CURRENT_SINK_1,
428 .flags = IORESOURCE_IO,
429 },
430 {
431 .start = WM831X_IRQ_CS1,
432 .end = WM831X_IRQ_CS1,
433 .flags = IORESOURCE_IRQ,
434 },
435};
436
437static struct resource wm831x_isink2_resources[] = {
438 {
439 .start = WM831X_CURRENT_SINK_2,
440 .end = WM831X_CURRENT_SINK_2,
441 .flags = IORESOURCE_IO,
442 },
443 {
444 .start = WM831X_IRQ_CS2,
445 .end = WM831X_IRQ_CS2,
446 .flags = IORESOURCE_IRQ,
447 },
448};
449
450static struct resource wm831x_ldo1_resources[] = {
451 {
452 .start = WM831X_LDO1_CONTROL,
453 .end = WM831X_LDO1_SLEEP_CONTROL,
454 .flags = IORESOURCE_IO,
455 },
456 {
457 .name = "UV",
458 .start = WM831X_IRQ_UV_LDO1,
459 .end = WM831X_IRQ_UV_LDO1,
460 .flags = IORESOURCE_IRQ,
461 },
462};
463
464static struct resource wm831x_ldo2_resources[] = {
465 {
466 .start = WM831X_LDO2_CONTROL,
467 .end = WM831X_LDO2_SLEEP_CONTROL,
468 .flags = IORESOURCE_IO,
469 },
470 {
471 .name = "UV",
472 .start = WM831X_IRQ_UV_LDO2,
473 .end = WM831X_IRQ_UV_LDO2,
474 .flags = IORESOURCE_IRQ,
475 },
476};
477
478static struct resource wm831x_ldo3_resources[] = {
479 {
480 .start = WM831X_LDO3_CONTROL,
481 .end = WM831X_LDO3_SLEEP_CONTROL,
482 .flags = IORESOURCE_IO,
483 },
484 {
485 .name = "UV",
486 .start = WM831X_IRQ_UV_LDO3,
487 .end = WM831X_IRQ_UV_LDO3,
488 .flags = IORESOURCE_IRQ,
489 },
490};
491
492static struct resource wm831x_ldo4_resources[] = {
493 {
494 .start = WM831X_LDO4_CONTROL,
495 .end = WM831X_LDO4_SLEEP_CONTROL,
496 .flags = IORESOURCE_IO,
497 },
498 {
499 .name = "UV",
500 .start = WM831X_IRQ_UV_LDO4,
501 .end = WM831X_IRQ_UV_LDO4,
502 .flags = IORESOURCE_IRQ,
503 },
504};
505
506static struct resource wm831x_ldo5_resources[] = {
507 {
508 .start = WM831X_LDO5_CONTROL,
509 .end = WM831X_LDO5_SLEEP_CONTROL,
510 .flags = IORESOURCE_IO,
511 },
512 {
513 .name = "UV",
514 .start = WM831X_IRQ_UV_LDO5,
515 .end = WM831X_IRQ_UV_LDO5,
516 .flags = IORESOURCE_IRQ,
517 },
518};
519
520static struct resource wm831x_ldo6_resources[] = {
521 {
522 .start = WM831X_LDO6_CONTROL,
523 .end = WM831X_LDO6_SLEEP_CONTROL,
524 .flags = IORESOURCE_IO,
525 },
526 {
527 .name = "UV",
528 .start = WM831X_IRQ_UV_LDO6,
529 .end = WM831X_IRQ_UV_LDO6,
530 .flags = IORESOURCE_IRQ,
531 },
532};
533
534static struct resource wm831x_ldo7_resources[] = {
535 {
536 .start = WM831X_LDO7_CONTROL,
537 .end = WM831X_LDO7_SLEEP_CONTROL,
538 .flags = IORESOURCE_IO,
539 },
540 {
541 .name = "UV",
542 .start = WM831X_IRQ_UV_LDO7,
543 .end = WM831X_IRQ_UV_LDO7,
544 .flags = IORESOURCE_IRQ,
545 },
546};
547
548static struct resource wm831x_ldo8_resources[] = {
549 {
550 .start = WM831X_LDO8_CONTROL,
551 .end = WM831X_LDO8_SLEEP_CONTROL,
552 .flags = IORESOURCE_IO,
553 },
554 {
555 .name = "UV",
556 .start = WM831X_IRQ_UV_LDO8,
557 .end = WM831X_IRQ_UV_LDO8,
558 .flags = IORESOURCE_IRQ,
559 },
560};
561
562static struct resource wm831x_ldo9_resources[] = {
563 {
564 .start = WM831X_LDO9_CONTROL,
565 .end = WM831X_LDO9_SLEEP_CONTROL,
566 .flags = IORESOURCE_IO,
567 },
568 {
569 .name = "UV",
570 .start = WM831X_IRQ_UV_LDO9,
571 .end = WM831X_IRQ_UV_LDO9,
572 .flags = IORESOURCE_IRQ,
573 },
574};
575
576static struct resource wm831x_ldo10_resources[] = {
577 {
578 .start = WM831X_LDO10_CONTROL,
579 .end = WM831X_LDO10_SLEEP_CONTROL,
580 .flags = IORESOURCE_IO,
581 },
582 {
583 .name = "UV",
584 .start = WM831X_IRQ_UV_LDO10,
585 .end = WM831X_IRQ_UV_LDO10,
586 .flags = IORESOURCE_IRQ,
587 },
588};
589
590static struct resource wm831x_ldo11_resources[] = {
591 {
592 .start = WM831X_LDO11_ON_CONTROL,
593 .end = WM831X_LDO11_SLEEP_CONTROL,
594 .flags = IORESOURCE_IO,
595 },
596};
597
598static struct resource wm831x_on_resources[] = {
599 {
600 .start = WM831X_IRQ_ON,
601 .end = WM831X_IRQ_ON,
602 .flags = IORESOURCE_IRQ,
603 },
604};
605
606
607static struct resource wm831x_power_resources[] = {
608 {
609 .name = "SYSLO",
610 .start = WM831X_IRQ_PPM_SYSLO,
611 .end = WM831X_IRQ_PPM_SYSLO,
612 .flags = IORESOURCE_IRQ,
613 },
614 {
615 .name = "PWR SRC",
616 .start = WM831X_IRQ_PPM_PWR_SRC,
617 .end = WM831X_IRQ_PPM_PWR_SRC,
618 .flags = IORESOURCE_IRQ,
619 },
620 {
621 .name = "USB CURR",
622 .start = WM831X_IRQ_PPM_USB_CURR,
623 .end = WM831X_IRQ_PPM_USB_CURR,
624 .flags = IORESOURCE_IRQ,
625 },
626 {
627 .name = "BATT HOT",
628 .start = WM831X_IRQ_CHG_BATT_HOT,
629 .end = WM831X_IRQ_CHG_BATT_HOT,
630 .flags = IORESOURCE_IRQ,
631 },
632 {
633 .name = "BATT COLD",
634 .start = WM831X_IRQ_CHG_BATT_COLD,
635 .end = WM831X_IRQ_CHG_BATT_COLD,
636 .flags = IORESOURCE_IRQ,
637 },
638 {
639 .name = "BATT FAIL",
640 .start = WM831X_IRQ_CHG_BATT_FAIL,
641 .end = WM831X_IRQ_CHG_BATT_FAIL,
642 .flags = IORESOURCE_IRQ,
643 },
644 {
645 .name = "OV",
646 .start = WM831X_IRQ_CHG_OV,
647 .end = WM831X_IRQ_CHG_OV,
648 .flags = IORESOURCE_IRQ,
649 },
650 {
651 .name = "END",
652 .start = WM831X_IRQ_CHG_END,
653 .end = WM831X_IRQ_CHG_END,
654 .flags = IORESOURCE_IRQ,
655 },
656 {
657 .name = "TO",
658 .start = WM831X_IRQ_CHG_TO,
659 .end = WM831X_IRQ_CHG_TO,
660 .flags = IORESOURCE_IRQ,
661 },
662 {
663 .name = "MODE",
664 .start = WM831X_IRQ_CHG_MODE,
665 .end = WM831X_IRQ_CHG_MODE,
666 .flags = IORESOURCE_IRQ,
667 },
668 {
669 .name = "START",
670 .start = WM831X_IRQ_CHG_START,
671 .end = WM831X_IRQ_CHG_START,
672 .flags = IORESOURCE_IRQ,
673 },
674};
675
676static struct resource wm831x_rtc_resources[] = {
677 {
678 .name = "PER",
679 .start = WM831X_IRQ_RTC_PER,
680 .end = WM831X_IRQ_RTC_PER,
681 .flags = IORESOURCE_IRQ,
682 },
683 {
684 .name = "ALM",
685 .start = WM831X_IRQ_RTC_ALM,
686 .end = WM831X_IRQ_RTC_ALM,
687 .flags = IORESOURCE_IRQ,
688 },
689};
690
691static struct resource wm831x_status1_resources[] = {
692 {
693 .start = WM831X_STATUS_LED_1,
694 .end = WM831X_STATUS_LED_1,
695 .flags = IORESOURCE_IO,
696 },
697};
698
699static struct resource wm831x_status2_resources[] = {
700 {
701 .start = WM831X_STATUS_LED_2,
702 .end = WM831X_STATUS_LED_2,
703 .flags = IORESOURCE_IO,
704 },
705};
706
707static struct resource wm831x_touch_resources[] = {
708 {
709 .name = "TCHPD",
710 .start = WM831X_IRQ_TCHPD,
711 .end = WM831X_IRQ_TCHPD,
712 .flags = IORESOURCE_IRQ,
713 },
714 {
715 .name = "TCHDATA",
716 .start = WM831X_IRQ_TCHDATA,
717 .end = WM831X_IRQ_TCHDATA,
718 .flags = IORESOURCE_IRQ,
719 },
720};
721
722static struct resource wm831x_wdt_resources[] = {
723 {
724 .start = WM831X_IRQ_WDOG_TO,
725 .end = WM831X_IRQ_WDOG_TO,
726 .flags = IORESOURCE_IRQ,
727 },
728};
729
730static struct mfd_cell wm8310_devs[] = {
731 {
732 .name = "wm831x-buckv",
733 .id = 1,
734 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
735 .resources = wm831x_dcdc1_resources,
736 },
737 {
738 .name = "wm831x-buckv",
739 .id = 2,
740 .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources),
741 .resources = wm831x_dcdc2_resources,
742 },
743 {
744 .name = "wm831x-buckp",
745 .id = 3,
746 .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources),
747 .resources = wm831x_dcdc3_resources,
748 },
749 {
750 .name = "wm831x-boostp",
751 .id = 4,
752 .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
753 .resources = wm831x_dcdc4_resources,
754 },
755 {
756 .name = "wm831x-epe",
757 .id = 1,
758 },
759 {
760 .name = "wm831x-epe",
761 .id = 2,
762 },
763 {
764 .name = "wm831x-gpio",
765 .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
766 .resources = wm831x_gpio_resources,
767 },
768 {
769 .name = "wm831x-hwmon",
770 },
771 {
772 .name = "wm831x-isink",
773 .id = 1,
774 .num_resources = ARRAY_SIZE(wm831x_isink1_resources),
775 .resources = wm831x_isink1_resources,
776 },
777 {
778 .name = "wm831x-isink",
779 .id = 2,
780 .num_resources = ARRAY_SIZE(wm831x_isink2_resources),
781 .resources = wm831x_isink2_resources,
782 },
783 {
784 .name = "wm831x-ldo",
785 .id = 1,
786 .num_resources = ARRAY_SIZE(wm831x_ldo1_resources),
787 .resources = wm831x_ldo1_resources,
788 },
789 {
790 .name = "wm831x-ldo",
791 .id = 2,
792 .num_resources = ARRAY_SIZE(wm831x_ldo2_resources),
793 .resources = wm831x_ldo2_resources,
794 },
795 {
796 .name = "wm831x-ldo",
797 .id = 3,
798 .num_resources = ARRAY_SIZE(wm831x_ldo3_resources),
799 .resources = wm831x_ldo3_resources,
800 },
801 {
802 .name = "wm831x-ldo",
803 .id = 4,
804 .num_resources = ARRAY_SIZE(wm831x_ldo4_resources),
805 .resources = wm831x_ldo4_resources,
806 },
807 {
808 .name = "wm831x-ldo",
809 .id = 5,
810 .num_resources = ARRAY_SIZE(wm831x_ldo5_resources),
811 .resources = wm831x_ldo5_resources,
812 },
813 {
814 .name = "wm831x-ldo",
815 .id = 6,
816 .num_resources = ARRAY_SIZE(wm831x_ldo6_resources),
817 .resources = wm831x_ldo6_resources,
818 },
819 {
820 .name = "wm831x-aldo",
821 .id = 7,
822 .num_resources = ARRAY_SIZE(wm831x_ldo7_resources),
823 .resources = wm831x_ldo7_resources,
824 },
825 {
826 .name = "wm831x-aldo",
827 .id = 8,
828 .num_resources = ARRAY_SIZE(wm831x_ldo8_resources),
829 .resources = wm831x_ldo8_resources,
830 },
831 {
832 .name = "wm831x-aldo",
833 .id = 9,
834 .num_resources = ARRAY_SIZE(wm831x_ldo9_resources),
835 .resources = wm831x_ldo9_resources,
836 },
837 {
838 .name = "wm831x-aldo",
839 .id = 10,
840 .num_resources = ARRAY_SIZE(wm831x_ldo10_resources),
841 .resources = wm831x_ldo10_resources,
842 },
843 {
844 .name = "wm831x-alive-ldo",
845 .id = 11,
846 .num_resources = ARRAY_SIZE(wm831x_ldo11_resources),
847 .resources = wm831x_ldo11_resources,
848 },
849 {
850 .name = "wm831x-on",
851 .num_resources = ARRAY_SIZE(wm831x_on_resources),
852 .resources = wm831x_on_resources,
853 },
854 {
855 .name = "wm831x-power",
856 .num_resources = ARRAY_SIZE(wm831x_power_resources),
857 .resources = wm831x_power_resources,
858 },
859 {
860 .name = "wm831x-rtc",
861 .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
862 .resources = wm831x_rtc_resources,
863 },
864 {
865 .name = "wm831x-status",
866 .id = 1,
867 .num_resources = ARRAY_SIZE(wm831x_status1_resources),
868 .resources = wm831x_status1_resources,
869 },
870 {
871 .name = "wm831x-status",
872 .id = 2,
873 .num_resources = ARRAY_SIZE(wm831x_status2_resources),
874 .resources = wm831x_status2_resources,
875 },
876 {
877 .name = "wm831x-watchdog",
878 .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
879 .resources = wm831x_wdt_resources,
880 },
881};
882
883static struct mfd_cell wm8311_devs[] = {
884 {
885 .name = "wm831x-buckv",
886 .id = 1,
887 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
888 .resources = wm831x_dcdc1_resources,
889 },
890 {
891 .name = "wm831x-buckv",
892 .id = 2,
893 .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources),
894 .resources = wm831x_dcdc2_resources,
895 },
896 {
897 .name = "wm831x-buckp",
898 .id = 3,
899 .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources),
900 .resources = wm831x_dcdc3_resources,
901 },
902 {
903 .name = "wm831x-boostp",
904 .id = 4,
905 .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
906 .resources = wm831x_dcdc4_resources,
907 },
908 {
909 .name = "wm831x-epe",
910 .id = 1,
911 },
912 {
913 .name = "wm831x-epe",
914 .id = 2,
915 },
916 {
917 .name = "wm831x-gpio",
918 .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
919 .resources = wm831x_gpio_resources,
920 },
921 {
922 .name = "wm831x-hwmon",
923 },
924 {
925 .name = "wm831x-isink",
926 .id = 1,
927 .num_resources = ARRAY_SIZE(wm831x_isink1_resources),
928 .resources = wm831x_isink1_resources,
929 },
930 {
931 .name = "wm831x-isink",
932 .id = 2,
933 .num_resources = ARRAY_SIZE(wm831x_isink2_resources),
934 .resources = wm831x_isink2_resources,
935 },
936 {
937 .name = "wm831x-ldo",
938 .id = 1,
939 .num_resources = ARRAY_SIZE(wm831x_ldo1_resources),
940 .resources = wm831x_ldo1_resources,
941 },
942 {
943 .name = "wm831x-ldo",
944 .id = 2,
945 .num_resources = ARRAY_SIZE(wm831x_ldo2_resources),
946 .resources = wm831x_ldo2_resources,
947 },
948 {
949 .name = "wm831x-ldo",
950 .id = 3,
951 .num_resources = ARRAY_SIZE(wm831x_ldo3_resources),
952 .resources = wm831x_ldo3_resources,
953 },
954 {
955 .name = "wm831x-ldo",
956 .id = 4,
957 .num_resources = ARRAY_SIZE(wm831x_ldo4_resources),
958 .resources = wm831x_ldo4_resources,
959 },
960 {
961 .name = "wm831x-ldo",
962 .id = 5,
963 .num_resources = ARRAY_SIZE(wm831x_ldo5_resources),
964 .resources = wm831x_ldo5_resources,
965 },
966 {
967 .name = "wm831x-aldo",
968 .id = 7,
969 .num_resources = ARRAY_SIZE(wm831x_ldo7_resources),
970 .resources = wm831x_ldo7_resources,
971 },
972 {
973 .name = "wm831x-alive-ldo",
974 .id = 11,
975 .num_resources = ARRAY_SIZE(wm831x_ldo11_resources),
976 .resources = wm831x_ldo11_resources,
977 },
978 {
979 .name = "wm831x-on",
980 .num_resources = ARRAY_SIZE(wm831x_on_resources),
981 .resources = wm831x_on_resources,
982 },
983 {
984 .name = "wm831x-power",
985 .num_resources = ARRAY_SIZE(wm831x_power_resources),
986 .resources = wm831x_power_resources,
987 },
988 {
989 .name = "wm831x-rtc",
990 .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
991 .resources = wm831x_rtc_resources,
992 },
993 {
994 .name = "wm831x-status",
995 .id = 1,
996 .num_resources = ARRAY_SIZE(wm831x_status1_resources),
997 .resources = wm831x_status1_resources,
998 },
999 {
1000 .name = "wm831x-status",
1001 .id = 2,
1002 .num_resources = ARRAY_SIZE(wm831x_status2_resources),
1003 .resources = wm831x_status2_resources,
1004 },
1005 {
1006 .name = "wm831x-touch",
1007 .num_resources = ARRAY_SIZE(wm831x_touch_resources),
1008 .resources = wm831x_touch_resources,
1009 },
1010 {
1011 .name = "wm831x-watchdog",
1012 .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
1013 .resources = wm831x_wdt_resources,
1014 },
1015};
1016
1017static struct mfd_cell wm8312_devs[] = {
1018 {
1019 .name = "wm831x-buckv",
1020 .id = 1,
1021 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
1022 .resources = wm831x_dcdc1_resources,
1023 },
1024 {
1025 .name = "wm831x-buckv",
1026 .id = 2,
1027 .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources),
1028 .resources = wm831x_dcdc2_resources,
1029 },
1030 {
1031 .name = "wm831x-buckp",
1032 .id = 3,
1033 .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources),
1034 .resources = wm831x_dcdc3_resources,
1035 },
1036 {
1037 .name = "wm831x-boostp",
1038 .id = 4,
1039 .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
1040 .resources = wm831x_dcdc4_resources,
1041 },
1042 {
1043 .name = "wm831x-epe",
1044 .id = 1,
1045 },
1046 {
1047 .name = "wm831x-epe",
1048 .id = 2,
1049 },
1050 {
1051 .name = "wm831x-gpio",
1052 .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
1053 .resources = wm831x_gpio_resources,
1054 },
1055 {
1056 .name = "wm831x-hwmon",
1057 },
1058 {
1059 .name = "wm831x-isink",
1060 .id = 1,
1061 .num_resources = ARRAY_SIZE(wm831x_isink1_resources),
1062 .resources = wm831x_isink1_resources,
1063 },
1064 {
1065 .name = "wm831x-isink",
1066 .id = 2,
1067 .num_resources = ARRAY_SIZE(wm831x_isink2_resources),
1068 .resources = wm831x_isink2_resources,
1069 },
1070 {
1071 .name = "wm831x-ldo",
1072 .id = 1,
1073 .num_resources = ARRAY_SIZE(wm831x_ldo1_resources),
1074 .resources = wm831x_ldo1_resources,
1075 },
1076 {
1077 .name = "wm831x-ldo",
1078 .id = 2,
1079 .num_resources = ARRAY_SIZE(wm831x_ldo2_resources),
1080 .resources = wm831x_ldo2_resources,
1081 },
1082 {
1083 .name = "wm831x-ldo",
1084 .id = 3,
1085 .num_resources = ARRAY_SIZE(wm831x_ldo3_resources),
1086 .resources = wm831x_ldo3_resources,
1087 },
1088 {
1089 .name = "wm831x-ldo",
1090 .id = 4,
1091 .num_resources = ARRAY_SIZE(wm831x_ldo4_resources),
1092 .resources = wm831x_ldo4_resources,
1093 },
1094 {
1095 .name = "wm831x-ldo",
1096 .id = 5,
1097 .num_resources = ARRAY_SIZE(wm831x_ldo5_resources),
1098 .resources = wm831x_ldo5_resources,
1099 },
1100 {
1101 .name = "wm831x-ldo",
1102 .id = 6,
1103 .num_resources = ARRAY_SIZE(wm831x_ldo6_resources),
1104 .resources = wm831x_ldo6_resources,
1105 },
1106 {
1107 .name = "wm831x-aldo",
1108 .id = 7,
1109 .num_resources = ARRAY_SIZE(wm831x_ldo7_resources),
1110 .resources = wm831x_ldo7_resources,
1111 },
1112 {
1113 .name = "wm831x-aldo",
1114 .id = 8,
1115 .num_resources = ARRAY_SIZE(wm831x_ldo8_resources),
1116 .resources = wm831x_ldo8_resources,
1117 },
1118 {
1119 .name = "wm831x-aldo",
1120 .id = 9,
1121 .num_resources = ARRAY_SIZE(wm831x_ldo9_resources),
1122 .resources = wm831x_ldo9_resources,
1123 },
1124 {
1125 .name = "wm831x-aldo",
1126 .id = 10,
1127 .num_resources = ARRAY_SIZE(wm831x_ldo10_resources),
1128 .resources = wm831x_ldo10_resources,
1129 },
1130 {
1131 .name = "wm831x-alive-ldo",
1132 .id = 11,
1133 .num_resources = ARRAY_SIZE(wm831x_ldo11_resources),
1134 .resources = wm831x_ldo11_resources,
1135 },
1136 {
1137 .name = "wm831x-on",
1138 .num_resources = ARRAY_SIZE(wm831x_on_resources),
1139 .resources = wm831x_on_resources,
1140 },
1141 {
1142 .name = "wm831x-power",
1143 .num_resources = ARRAY_SIZE(wm831x_power_resources),
1144 .resources = wm831x_power_resources,
1145 },
1146 {
1147 .name = "wm831x-rtc",
1148 .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
1149 .resources = wm831x_rtc_resources,
1150 },
1151 {
1152 .name = "wm831x-status",
1153 .id = 1,
1154 .num_resources = ARRAY_SIZE(wm831x_status1_resources),
1155 .resources = wm831x_status1_resources,
1156 },
1157 {
1158 .name = "wm831x-status",
1159 .id = 2,
1160 .num_resources = ARRAY_SIZE(wm831x_status2_resources),
1161 .resources = wm831x_status2_resources,
1162 },
1163 {
1164 .name = "wm831x-touch",
1165 .num_resources = ARRAY_SIZE(wm831x_touch_resources),
1166 .resources = wm831x_touch_resources,
1167 },
1168 {
1169 .name = "wm831x-watchdog",
1170 .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
1171 .resources = wm831x_wdt_resources,
1172 },
1173};
1174
1175/*
1176 * Instantiate the generic non-control parts of the device.
1177 */
1178static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1179{
1180 struct wm831x_pdata *pdata = wm831x->dev->platform_data;
1181 int rev;
1182 enum wm831x_parent parent;
1183 int ret;
1184
1185 mutex_init(&wm831x->io_lock);
1186 mutex_init(&wm831x->key_lock);
Mark Brown7e9f9fd2009-07-27 14:45:54 +01001187 mutex_init(&wm831x->auxadc_lock);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001188 dev_set_drvdata(wm831x->dev, wm831x);
1189
1190 ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
1191 if (ret < 0) {
1192 dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
1193 goto err;
1194 }
1195 if (ret != 0x6204) {
1196 dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
1197 ret = -EINVAL;
1198 goto err;
1199 }
1200
1201 ret = wm831x_reg_read(wm831x, WM831X_REVISION);
1202 if (ret < 0) {
1203 dev_err(wm831x->dev, "Failed to read revision: %d\n", ret);
1204 goto err;
1205 }
1206 rev = (ret & WM831X_PARENT_REV_MASK) >> WM831X_PARENT_REV_SHIFT;
1207
1208 ret = wm831x_reg_read(wm831x, WM831X_RESET_ID);
1209 if (ret < 0) {
1210 dev_err(wm831x->dev, "Failed to read device ID: %d\n", ret);
1211 goto err;
1212 }
1213
1214 switch (ret) {
1215 case 0x8310:
1216 parent = WM8310;
1217 switch (rev) {
1218 case 0:
1219 dev_info(wm831x->dev, "WM8310 revision %c\n",
1220 'A' + rev);
1221 break;
1222 }
1223 break;
1224
1225 case 0x8311:
1226 parent = WM8311;
1227 switch (rev) {
1228 case 0:
1229 dev_info(wm831x->dev, "WM8311 revision %c\n",
1230 'A' + rev);
1231 break;
1232 }
1233 break;
1234
1235 case 0x8312:
1236 parent = WM8312;
1237 switch (rev) {
1238 case 0:
1239 dev_info(wm831x->dev, "WM8312 revision %c\n",
1240 'A' + rev);
1241 break;
1242 }
1243 break;
1244
1245 case 0:
1246 /* Some engineering samples do not have the ID set,
1247 * rely on the device being registered correctly.
1248 * This will need revisiting for future devices with
1249 * multiple dies.
1250 */
1251 parent = id;
1252 switch (rev) {
1253 case 0:
1254 dev_info(wm831x->dev, "WM831%d ES revision %c\n",
1255 parent, 'A' + rev);
1256 break;
1257 }
1258 break;
1259
1260 default:
1261 dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
1262 ret = -EINVAL;
1263 goto err;
1264 }
1265
1266 /* This will need revisiting in future but is OK for all
1267 * current parts.
1268 */
1269 if (parent != id)
1270 dev_warn(wm831x->dev, "Device was registered as a WM831%lu\n",
1271 id);
1272
1273 /* Bootstrap the user key */
1274 ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY);
1275 if (ret < 0) {
1276 dev_err(wm831x->dev, "Failed to read security key: %d\n", ret);
1277 goto err;
1278 }
1279 if (ret != 0) {
1280 dev_warn(wm831x->dev, "Security key had non-zero value %x\n",
1281 ret);
1282 wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0);
1283 }
1284 wm831x->locked = 1;
1285
1286 if (pdata && pdata->pre_init) {
1287 ret = pdata->pre_init(wm831x);
1288 if (ret != 0) {
1289 dev_err(wm831x->dev, "pre_init() failed: %d\n", ret);
1290 goto err;
1291 }
1292 }
1293
Mark Brown7d4d0a32009-07-27 14:45:53 +01001294 ret = wm831x_irq_init(wm831x, irq);
1295 if (ret != 0)
1296 goto err;
1297
Mark Brownd2bedfe2009-07-27 14:45:52 +01001298 /* The core device is up, instantiate the subdevices. */
1299 switch (parent) {
1300 case WM8310:
1301 ret = mfd_add_devices(wm831x->dev, -1,
1302 wm8310_devs, ARRAY_SIZE(wm8310_devs),
1303 NULL, 0);
1304 break;
1305
1306 case WM8311:
1307 ret = mfd_add_devices(wm831x->dev, -1,
1308 wm8311_devs, ARRAY_SIZE(wm8311_devs),
1309 NULL, 0);
1310 break;
1311
1312 case WM8312:
1313 ret = mfd_add_devices(wm831x->dev, -1,
1314 wm8312_devs, ARRAY_SIZE(wm8312_devs),
1315 NULL, 0);
1316 break;
1317
1318 default:
1319 /* If this happens the bus probe function is buggy */
1320 BUG();
1321 }
1322
1323 if (ret != 0) {
1324 dev_err(wm831x->dev, "Failed to add children\n");
Mark Brown7d4d0a32009-07-27 14:45:53 +01001325 goto err_irq;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001326 }
1327
1328 if (pdata && pdata->post_init) {
1329 ret = pdata->post_init(wm831x);
1330 if (ret != 0) {
1331 dev_err(wm831x->dev, "post_init() failed: %d\n", ret);
Mark Brown7d4d0a32009-07-27 14:45:53 +01001332 goto err_irq;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001333 }
1334 }
1335
1336 return 0;
1337
Mark Brown7d4d0a32009-07-27 14:45:53 +01001338err_irq:
1339 wm831x_irq_exit(wm831x);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001340err:
1341 mfd_remove_devices(wm831x->dev);
1342 kfree(wm831x);
1343 return ret;
1344}
1345
1346static void wm831x_device_exit(struct wm831x *wm831x)
1347{
1348 mfd_remove_devices(wm831x->dev);
Mark Brown7d4d0a32009-07-27 14:45:53 +01001349 wm831x_irq_exit(wm831x);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001350 kfree(wm831x);
1351}
1352
1353static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg,
1354 int bytes, void *dest)
1355{
1356 struct i2c_client *i2c = wm831x->control_data;
1357 int ret;
1358 u16 r = cpu_to_be16(reg);
1359
1360 ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
1361 if (ret < 0)
1362 return ret;
1363 if (ret != 2)
1364 return -EIO;
1365
1366 ret = i2c_master_recv(i2c, dest, bytes);
1367 if (ret < 0)
1368 return ret;
1369 if (ret != bytes)
1370 return -EIO;
1371 return 0;
1372}
1373
1374/* Currently we allocate the write buffer on the stack; this is OK for
1375 * small writes - if we need to do large writes this will need to be
1376 * revised.
1377 */
1378static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg,
1379 int bytes, void *src)
1380{
1381 struct i2c_client *i2c = wm831x->control_data;
1382 unsigned char msg[bytes + 2];
1383 int ret;
1384
1385 reg = cpu_to_be16(reg);
1386 memcpy(&msg[0], &reg, 2);
1387 memcpy(&msg[2], src, bytes);
1388
1389 ret = i2c_master_send(i2c, msg, bytes + 2);
1390 if (ret < 0)
1391 return ret;
1392 if (ret < bytes + 2)
1393 return -EIO;
1394
1395 return 0;
1396}
1397
1398static int wm831x_i2c_probe(struct i2c_client *i2c,
1399 const struct i2c_device_id *id)
1400{
1401 struct wm831x *wm831x;
1402
1403 wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
1404 if (wm831x == NULL) {
1405 kfree(i2c);
1406 return -ENOMEM;
1407 }
1408
1409 i2c_set_clientdata(i2c, wm831x);
1410 wm831x->dev = &i2c->dev;
1411 wm831x->control_data = i2c;
1412 wm831x->read_dev = wm831x_i2c_read_device;
1413 wm831x->write_dev = wm831x_i2c_write_device;
1414
1415 return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
1416}
1417
1418static int wm831x_i2c_remove(struct i2c_client *i2c)
1419{
1420 struct wm831x *wm831x = i2c_get_clientdata(i2c);
1421
1422 wm831x_device_exit(wm831x);
1423
1424 return 0;
1425}
1426
1427static const struct i2c_device_id wm831x_i2c_id[] = {
1428 { "wm8310", WM8310 },
1429 { "wm8311", WM8311 },
1430 { "wm8312", WM8312 },
1431 { }
1432};
1433MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
1434
1435
1436static struct i2c_driver wm831x_i2c_driver = {
1437 .driver = {
1438 .name = "wm831x",
1439 .owner = THIS_MODULE,
1440 },
1441 .probe = wm831x_i2c_probe,
1442 .remove = wm831x_i2c_remove,
1443 .id_table = wm831x_i2c_id,
1444};
1445
1446static int __init wm831x_i2c_init(void)
1447{
1448 int ret;
1449
1450 ret = i2c_add_driver(&wm831x_i2c_driver);
1451 if (ret != 0)
1452 pr_err("Failed to register wm831x I2C driver: %d\n", ret);
1453
1454 return ret;
1455}
1456subsys_initcall(wm831x_i2c_init);
1457
1458static void __exit wm831x_i2c_exit(void)
1459{
1460 i2c_del_driver(&wm831x_i2c_driver);
1461}
1462module_exit(wm831x_i2c_exit);
1463
1464MODULE_DESCRIPTION("I2C support for the WM831X AudioPlus PMIC");
1465MODULE_LICENSE("GPL");
1466MODULE_AUTHOR("Mark Brown");