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