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