blob: 0a2b8d41a7020229223c7dcf5876d2d9cc532b43 [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>
Mark Brown7e9f9fd2009-07-27 14:45:54 +010017#include <linux/bcd.h>
18#include <linux/delay.h>
Mark Brownd2bedfe2009-07-27 14:45:52 +010019#include <linux/mfd/core.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/slab.h>
Mark Brown1df59812011-06-10 19:28:10 +010021#include <linux/err.h>
Mark Brownd2bedfe2009-07-27 14:45:52 +010022
23#include <linux/mfd/wm831x/core.h>
24#include <linux/mfd/wm831x/pdata.h>
Mark Brown7d4d0a32009-07-27 14:45:53 +010025#include <linux/mfd/wm831x/irq.h>
Mark Brown7e9f9fd2009-07-27 14:45:54 +010026#include <linux/mfd/wm831x/auxadc.h>
Mark Brown6704e512009-07-27 14:45:56 +010027#include <linux/mfd/wm831x/otp.h>
Mark Brown523d9cf2011-09-15 18:54:53 +020028#include <linux/mfd/wm831x/pmu.h>
Mark Brown698659d2009-07-27 14:45:57 +010029#include <linux/mfd/wm831x/regulator.h>
30
31/* Current settings - values are 2*2^(reg_val/4) microamps. These are
32 * exported since they are used by multiple drivers.
33 */
Mark Brown77169772009-11-30 13:24:18 +000034int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1] = {
Mark Brown698659d2009-07-27 14:45:57 +010035 2,
36 2,
37 3,
38 3,
39 4,
40 5,
41 6,
42 7,
43 8,
44 10,
45 11,
46 13,
47 16,
48 19,
49 23,
50 27,
51 32,
52 38,
53 45,
54 54,
55 64,
56 76,
57 91,
58 108,
59 128,
60 152,
61 181,
62 215,
63 256,
64 304,
65 362,
66 431,
67 512,
68 609,
69 724,
70 861,
71 1024,
72 1218,
73 1448,
74 1722,
75 2048,
76 2435,
77 2896,
78 3444,
79 4096,
80 4871,
81 5793,
82 6889,
83 8192,
84 9742,
85 11585,
86 13777,
87 16384,
88 19484,
89 23170,
90 27554,
91};
92EXPORT_SYMBOL_GPL(wm831x_isinkv_values);
Mark Brownd2bedfe2009-07-27 14:45:52 +010093
Mark Brownd2bedfe2009-07-27 14:45:52 +010094static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg)
95{
96 if (!wm831x->locked)
97 return 0;
98
99 switch (reg) {
100 case WM831X_WATCHDOG:
101 case WM831X_DC4_CONTROL:
102 case WM831X_ON_PIN_CONTROL:
103 case WM831X_BACKUP_CHARGER_CONTROL:
104 case WM831X_CHARGER_CONTROL_1:
105 case WM831X_CHARGER_CONTROL_2:
106 return 1;
107
108 default:
109 return 0;
110 }
111}
112
113/**
114 * wm831x_reg_unlock: Unlock user keyed registers
115 *
116 * The WM831x has a user key preventing writes to particularly
117 * critical registers. This function locks those registers,
118 * allowing writes to them.
119 */
120void wm831x_reg_lock(struct wm831x *wm831x)
121{
122 int ret;
123
124 ret = wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0);
125 if (ret == 0) {
126 dev_vdbg(wm831x->dev, "Registers locked\n");
127
128 mutex_lock(&wm831x->io_lock);
129 WARN_ON(wm831x->locked);
130 wm831x->locked = 1;
131 mutex_unlock(&wm831x->io_lock);
132 } else {
133 dev_err(wm831x->dev, "Failed to lock registers: %d\n", ret);
134 }
135
136}
137EXPORT_SYMBOL_GPL(wm831x_reg_lock);
138
139/**
140 * wm831x_reg_unlock: Unlock user keyed registers
141 *
142 * The WM831x has a user key preventing writes to particularly
143 * critical registers. This function locks those registers,
144 * preventing spurious writes.
145 */
146int wm831x_reg_unlock(struct wm831x *wm831x)
147{
148 int ret;
149
150 /* 0x9716 is the value required to unlock the registers */
151 ret = wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0x9716);
152 if (ret == 0) {
153 dev_vdbg(wm831x->dev, "Registers unlocked\n");
154
155 mutex_lock(&wm831x->io_lock);
156 WARN_ON(!wm831x->locked);
157 wm831x->locked = 0;
158 mutex_unlock(&wm831x->io_lock);
159 }
160
161 return ret;
162}
163EXPORT_SYMBOL_GPL(wm831x_reg_unlock);
164
Mark Brown2e47fff2011-07-21 17:30:08 +0100165static bool wm831x_reg_readable(struct device *dev, unsigned int reg)
166{
167 switch (reg) {
168 case WM831X_RESET_ID:
169 case WM831X_REVISION:
170 case WM831X_PARENT_ID:
171 case WM831X_SYSVDD_CONTROL:
172 case WM831X_THERMAL_MONITORING:
173 case WM831X_POWER_STATE:
174 case WM831X_WATCHDOG:
175 case WM831X_ON_PIN_CONTROL:
176 case WM831X_RESET_CONTROL:
177 case WM831X_CONTROL_INTERFACE:
178 case WM831X_SECURITY_KEY:
179 case WM831X_SOFTWARE_SCRATCH:
180 case WM831X_OTP_CONTROL:
181 case WM831X_GPIO_LEVEL:
182 case WM831X_SYSTEM_STATUS:
183 case WM831X_ON_SOURCE:
184 case WM831X_OFF_SOURCE:
185 case WM831X_SYSTEM_INTERRUPTS:
186 case WM831X_INTERRUPT_STATUS_1:
187 case WM831X_INTERRUPT_STATUS_2:
188 case WM831X_INTERRUPT_STATUS_3:
189 case WM831X_INTERRUPT_STATUS_4:
190 case WM831X_INTERRUPT_STATUS_5:
191 case WM831X_IRQ_CONFIG:
192 case WM831X_SYSTEM_INTERRUPTS_MASK:
193 case WM831X_INTERRUPT_STATUS_1_MASK:
194 case WM831X_INTERRUPT_STATUS_2_MASK:
195 case WM831X_INTERRUPT_STATUS_3_MASK:
196 case WM831X_INTERRUPT_STATUS_4_MASK:
197 case WM831X_INTERRUPT_STATUS_5_MASK:
198 case WM831X_RTC_WRITE_COUNTER:
199 case WM831X_RTC_TIME_1:
200 case WM831X_RTC_TIME_2:
201 case WM831X_RTC_ALARM_1:
202 case WM831X_RTC_ALARM_2:
203 case WM831X_RTC_CONTROL:
204 case WM831X_RTC_TRIM:
205 case WM831X_TOUCH_CONTROL_1:
206 case WM831X_TOUCH_CONTROL_2:
207 case WM831X_TOUCH_DATA_X:
208 case WM831X_TOUCH_DATA_Y:
209 case WM831X_TOUCH_DATA_Z:
210 case WM831X_AUXADC_DATA:
211 case WM831X_AUXADC_CONTROL:
212 case WM831X_AUXADC_SOURCE:
213 case WM831X_COMPARATOR_CONTROL:
214 case WM831X_COMPARATOR_1:
215 case WM831X_COMPARATOR_2:
216 case WM831X_COMPARATOR_3:
217 case WM831X_COMPARATOR_4:
218 case WM831X_GPIO1_CONTROL:
219 case WM831X_GPIO2_CONTROL:
220 case WM831X_GPIO3_CONTROL:
221 case WM831X_GPIO4_CONTROL:
222 case WM831X_GPIO5_CONTROL:
223 case WM831X_GPIO6_CONTROL:
224 case WM831X_GPIO7_CONTROL:
225 case WM831X_GPIO8_CONTROL:
226 case WM831X_GPIO9_CONTROL:
227 case WM831X_GPIO10_CONTROL:
228 case WM831X_GPIO11_CONTROL:
229 case WM831X_GPIO12_CONTROL:
230 case WM831X_GPIO13_CONTROL:
231 case WM831X_GPIO14_CONTROL:
232 case WM831X_GPIO15_CONTROL:
233 case WM831X_GPIO16_CONTROL:
234 case WM831X_CHARGER_CONTROL_1:
235 case WM831X_CHARGER_CONTROL_2:
236 case WM831X_CHARGER_STATUS:
237 case WM831X_BACKUP_CHARGER_CONTROL:
238 case WM831X_STATUS_LED_1:
239 case WM831X_STATUS_LED_2:
240 case WM831X_CURRENT_SINK_1:
241 case WM831X_CURRENT_SINK_2:
242 case WM831X_DCDC_ENABLE:
243 case WM831X_LDO_ENABLE:
244 case WM831X_DCDC_STATUS:
245 case WM831X_LDO_STATUS:
246 case WM831X_DCDC_UV_STATUS:
247 case WM831X_LDO_UV_STATUS:
248 case WM831X_DC1_CONTROL_1:
249 case WM831X_DC1_CONTROL_2:
250 case WM831X_DC1_ON_CONFIG:
251 case WM831X_DC1_SLEEP_CONTROL:
252 case WM831X_DC1_DVS_CONTROL:
253 case WM831X_DC2_CONTROL_1:
254 case WM831X_DC2_CONTROL_2:
255 case WM831X_DC2_ON_CONFIG:
256 case WM831X_DC2_SLEEP_CONTROL:
257 case WM831X_DC2_DVS_CONTROL:
258 case WM831X_DC3_CONTROL_1:
259 case WM831X_DC3_CONTROL_2:
260 case WM831X_DC3_ON_CONFIG:
261 case WM831X_DC3_SLEEP_CONTROL:
262 case WM831X_DC4_CONTROL:
263 case WM831X_DC4_SLEEP_CONTROL:
264 case WM831X_EPE1_CONTROL:
265 case WM831X_EPE2_CONTROL:
266 case WM831X_LDO1_CONTROL:
267 case WM831X_LDO1_ON_CONTROL:
268 case WM831X_LDO1_SLEEP_CONTROL:
269 case WM831X_LDO2_CONTROL:
270 case WM831X_LDO2_ON_CONTROL:
271 case WM831X_LDO2_SLEEP_CONTROL:
272 case WM831X_LDO3_CONTROL:
273 case WM831X_LDO3_ON_CONTROL:
274 case WM831X_LDO3_SLEEP_CONTROL:
275 case WM831X_LDO4_CONTROL:
276 case WM831X_LDO4_ON_CONTROL:
277 case WM831X_LDO4_SLEEP_CONTROL:
278 case WM831X_LDO5_CONTROL:
279 case WM831X_LDO5_ON_CONTROL:
280 case WM831X_LDO5_SLEEP_CONTROL:
281 case WM831X_LDO6_CONTROL:
282 case WM831X_LDO6_ON_CONTROL:
283 case WM831X_LDO6_SLEEP_CONTROL:
284 case WM831X_LDO7_CONTROL:
285 case WM831X_LDO7_ON_CONTROL:
286 case WM831X_LDO7_SLEEP_CONTROL:
287 case WM831X_LDO8_CONTROL:
288 case WM831X_LDO8_ON_CONTROL:
289 case WM831X_LDO8_SLEEP_CONTROL:
290 case WM831X_LDO9_CONTROL:
291 case WM831X_LDO9_ON_CONTROL:
292 case WM831X_LDO9_SLEEP_CONTROL:
293 case WM831X_LDO10_CONTROL:
294 case WM831X_LDO10_ON_CONTROL:
295 case WM831X_LDO10_SLEEP_CONTROL:
296 case WM831X_LDO11_ON_CONTROL:
297 case WM831X_LDO11_SLEEP_CONTROL:
298 case WM831X_POWER_GOOD_SOURCE_1:
299 case WM831X_POWER_GOOD_SOURCE_2:
300 case WM831X_CLOCK_CONTROL_1:
301 case WM831X_CLOCK_CONTROL_2:
302 case WM831X_FLL_CONTROL_1:
303 case WM831X_FLL_CONTROL_2:
304 case WM831X_FLL_CONTROL_3:
305 case WM831X_FLL_CONTROL_4:
306 case WM831X_FLL_CONTROL_5:
307 case WM831X_UNIQUE_ID_1:
308 case WM831X_UNIQUE_ID_2:
309 case WM831X_UNIQUE_ID_3:
310 case WM831X_UNIQUE_ID_4:
311 case WM831X_UNIQUE_ID_5:
312 case WM831X_UNIQUE_ID_6:
313 case WM831X_UNIQUE_ID_7:
314 case WM831X_UNIQUE_ID_8:
315 case WM831X_FACTORY_OTP_ID:
316 case WM831X_FACTORY_OTP_1:
317 case WM831X_FACTORY_OTP_2:
318 case WM831X_FACTORY_OTP_3:
319 case WM831X_FACTORY_OTP_4:
320 case WM831X_FACTORY_OTP_5:
321 case WM831X_CUSTOMER_OTP_ID:
322 case WM831X_DC1_OTP_CONTROL:
323 case WM831X_DC2_OTP_CONTROL:
324 case WM831X_DC3_OTP_CONTROL:
325 case WM831X_LDO1_2_OTP_CONTROL:
326 case WM831X_LDO3_4_OTP_CONTROL:
327 case WM831X_LDO5_6_OTP_CONTROL:
328 case WM831X_LDO7_8_OTP_CONTROL:
329 case WM831X_LDO9_10_OTP_CONTROL:
330 case WM831X_LDO11_EPE_CONTROL:
331 case WM831X_GPIO1_OTP_CONTROL:
332 case WM831X_GPIO2_OTP_CONTROL:
333 case WM831X_GPIO3_OTP_CONTROL:
334 case WM831X_GPIO4_OTP_CONTROL:
335 case WM831X_GPIO5_OTP_CONTROL:
336 case WM831X_GPIO6_OTP_CONTROL:
337 case WM831X_DBE_CHECK_DATA:
338 return true;
339 default:
340 return false;
341 }
342}
343
344static bool wm831x_reg_writeable(struct device *dev, unsigned int reg)
345{
346 struct wm831x *wm831x = dev_get_drvdata(dev);
347
348 if (wm831x_reg_locked(wm831x, reg))
349 return false;
350
351 switch (reg) {
352 case WM831X_SYSVDD_CONTROL:
353 case WM831X_THERMAL_MONITORING:
354 case WM831X_POWER_STATE:
355 case WM831X_WATCHDOG:
356 case WM831X_ON_PIN_CONTROL:
357 case WM831X_RESET_CONTROL:
358 case WM831X_CONTROL_INTERFACE:
359 case WM831X_SECURITY_KEY:
360 case WM831X_SOFTWARE_SCRATCH:
361 case WM831X_OTP_CONTROL:
362 case WM831X_GPIO_LEVEL:
363 case WM831X_INTERRUPT_STATUS_1:
364 case WM831X_INTERRUPT_STATUS_2:
365 case WM831X_INTERRUPT_STATUS_3:
366 case WM831X_INTERRUPT_STATUS_4:
367 case WM831X_INTERRUPT_STATUS_5:
368 case WM831X_IRQ_CONFIG:
369 case WM831X_SYSTEM_INTERRUPTS_MASK:
370 case WM831X_INTERRUPT_STATUS_1_MASK:
371 case WM831X_INTERRUPT_STATUS_2_MASK:
372 case WM831X_INTERRUPT_STATUS_3_MASK:
373 case WM831X_INTERRUPT_STATUS_4_MASK:
374 case WM831X_INTERRUPT_STATUS_5_MASK:
375 case WM831X_RTC_TIME_1:
376 case WM831X_RTC_TIME_2:
377 case WM831X_RTC_ALARM_1:
378 case WM831X_RTC_ALARM_2:
379 case WM831X_RTC_CONTROL:
380 case WM831X_RTC_TRIM:
381 case WM831X_TOUCH_CONTROL_1:
382 case WM831X_TOUCH_CONTROL_2:
383 case WM831X_AUXADC_CONTROL:
384 case WM831X_AUXADC_SOURCE:
385 case WM831X_COMPARATOR_CONTROL:
386 case WM831X_COMPARATOR_1:
387 case WM831X_COMPARATOR_2:
388 case WM831X_COMPARATOR_3:
389 case WM831X_COMPARATOR_4:
390 case WM831X_GPIO1_CONTROL:
391 case WM831X_GPIO2_CONTROL:
392 case WM831X_GPIO3_CONTROL:
393 case WM831X_GPIO4_CONTROL:
394 case WM831X_GPIO5_CONTROL:
395 case WM831X_GPIO6_CONTROL:
396 case WM831X_GPIO7_CONTROL:
397 case WM831X_GPIO8_CONTROL:
398 case WM831X_GPIO9_CONTROL:
399 case WM831X_GPIO10_CONTROL:
400 case WM831X_GPIO11_CONTROL:
401 case WM831X_GPIO12_CONTROL:
402 case WM831X_GPIO13_CONTROL:
403 case WM831X_GPIO14_CONTROL:
404 case WM831X_GPIO15_CONTROL:
405 case WM831X_GPIO16_CONTROL:
406 case WM831X_CHARGER_CONTROL_1:
407 case WM831X_CHARGER_CONTROL_2:
408 case WM831X_CHARGER_STATUS:
409 case WM831X_BACKUP_CHARGER_CONTROL:
410 case WM831X_STATUS_LED_1:
411 case WM831X_STATUS_LED_2:
412 case WM831X_CURRENT_SINK_1:
413 case WM831X_CURRENT_SINK_2:
414 case WM831X_DCDC_ENABLE:
415 case WM831X_LDO_ENABLE:
416 case WM831X_DC1_CONTROL_1:
417 case WM831X_DC1_CONTROL_2:
418 case WM831X_DC1_ON_CONFIG:
419 case WM831X_DC1_SLEEP_CONTROL:
420 case WM831X_DC1_DVS_CONTROL:
421 case WM831X_DC2_CONTROL_1:
422 case WM831X_DC2_CONTROL_2:
423 case WM831X_DC2_ON_CONFIG:
424 case WM831X_DC2_SLEEP_CONTROL:
425 case WM831X_DC2_DVS_CONTROL:
426 case WM831X_DC3_CONTROL_1:
427 case WM831X_DC3_CONTROL_2:
428 case WM831X_DC3_ON_CONFIG:
429 case WM831X_DC3_SLEEP_CONTROL:
430 case WM831X_DC4_CONTROL:
431 case WM831X_DC4_SLEEP_CONTROL:
432 case WM831X_EPE1_CONTROL:
433 case WM831X_EPE2_CONTROL:
434 case WM831X_LDO1_CONTROL:
435 case WM831X_LDO1_ON_CONTROL:
436 case WM831X_LDO1_SLEEP_CONTROL:
437 case WM831X_LDO2_CONTROL:
438 case WM831X_LDO2_ON_CONTROL:
439 case WM831X_LDO2_SLEEP_CONTROL:
440 case WM831X_LDO3_CONTROL:
441 case WM831X_LDO3_ON_CONTROL:
442 case WM831X_LDO3_SLEEP_CONTROL:
443 case WM831X_LDO4_CONTROL:
444 case WM831X_LDO4_ON_CONTROL:
445 case WM831X_LDO4_SLEEP_CONTROL:
446 case WM831X_LDO5_CONTROL:
447 case WM831X_LDO5_ON_CONTROL:
448 case WM831X_LDO5_SLEEP_CONTROL:
449 case WM831X_LDO6_CONTROL:
450 case WM831X_LDO6_ON_CONTROL:
451 case WM831X_LDO6_SLEEP_CONTROL:
452 case WM831X_LDO7_CONTROL:
453 case WM831X_LDO7_ON_CONTROL:
454 case WM831X_LDO7_SLEEP_CONTROL:
455 case WM831X_LDO8_CONTROL:
456 case WM831X_LDO8_ON_CONTROL:
457 case WM831X_LDO8_SLEEP_CONTROL:
458 case WM831X_LDO9_CONTROL:
459 case WM831X_LDO9_ON_CONTROL:
460 case WM831X_LDO9_SLEEP_CONTROL:
461 case WM831X_LDO10_CONTROL:
462 case WM831X_LDO10_ON_CONTROL:
463 case WM831X_LDO10_SLEEP_CONTROL:
464 case WM831X_LDO11_ON_CONTROL:
465 case WM831X_LDO11_SLEEP_CONTROL:
466 case WM831X_POWER_GOOD_SOURCE_1:
467 case WM831X_POWER_GOOD_SOURCE_2:
468 case WM831X_CLOCK_CONTROL_1:
469 case WM831X_CLOCK_CONTROL_2:
470 case WM831X_FLL_CONTROL_1:
471 case WM831X_FLL_CONTROL_2:
472 case WM831X_FLL_CONTROL_3:
473 case WM831X_FLL_CONTROL_4:
474 case WM831X_FLL_CONTROL_5:
475 return true;
476 default:
477 return false;
478 }
479}
480
481static bool wm831x_reg_volatile(struct device *dev, unsigned int reg)
482{
483 switch (reg) {
484 case WM831X_SYSTEM_STATUS:
485 case WM831X_ON_SOURCE:
486 case WM831X_OFF_SOURCE:
487 case WM831X_GPIO_LEVEL:
488 case WM831X_SYSTEM_INTERRUPTS:
489 case WM831X_INTERRUPT_STATUS_1:
490 case WM831X_INTERRUPT_STATUS_2:
491 case WM831X_INTERRUPT_STATUS_3:
492 case WM831X_INTERRUPT_STATUS_4:
493 case WM831X_INTERRUPT_STATUS_5:
494 case WM831X_RTC_TIME_1:
495 case WM831X_RTC_TIME_2:
496 case WM831X_TOUCH_DATA_X:
497 case WM831X_TOUCH_DATA_Y:
498 case WM831X_TOUCH_DATA_Z:
499 case WM831X_AUXADC_DATA:
500 case WM831X_CHARGER_STATUS:
501 case WM831X_DCDC_STATUS:
502 case WM831X_LDO_STATUS:
503 case WM831X_DCDC_UV_STATUS:
504 case WM831X_LDO_UV_STATUS:
505 return true;
506 default:
507 return false;
508 }
509}
510
Mark Brownd2bedfe2009-07-27 14:45:52 +0100511/**
512 * wm831x_reg_read: Read a single WM831x register.
513 *
514 * @wm831x: Device to read from.
515 * @reg: Register to read.
516 */
517int wm831x_reg_read(struct wm831x *wm831x, unsigned short reg)
518{
Mark Brown1df59812011-06-10 19:28:10 +0100519 unsigned int val;
Mark Brownd2bedfe2009-07-27 14:45:52 +0100520 int ret;
521
Mark Brown1df59812011-06-10 19:28:10 +0100522 ret = regmap_read(wm831x->regmap, reg, &val);
Mark Brownd2bedfe2009-07-27 14:45:52 +0100523
524 if (ret < 0)
525 return ret;
526 else
527 return val;
528}
529EXPORT_SYMBOL_GPL(wm831x_reg_read);
530
531/**
532 * wm831x_bulk_read: Read multiple WM831x registers
533 *
534 * @wm831x: Device to read from
535 * @reg: First register
536 * @count: Number of registers
537 * @buf: Buffer to fill.
538 */
539int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
540 int count, u16 *buf)
541{
Mark Brown1df59812011-06-10 19:28:10 +0100542 return regmap_bulk_read(wm831x->regmap, reg, buf, count);
Mark Brownd2bedfe2009-07-27 14:45:52 +0100543}
544EXPORT_SYMBOL_GPL(wm831x_bulk_read);
545
546static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
547 int bytes, void *src)
548{
549 u16 *buf = src;
Mark Brown1df59812011-06-10 19:28:10 +0100550 int i, ret;
Mark Brownd2bedfe2009-07-27 14:45:52 +0100551
552 BUG_ON(bytes % 2);
553 BUG_ON(bytes <= 0);
554
555 for (i = 0; i < bytes / 2; i++) {
556 if (wm831x_reg_locked(wm831x, reg))
557 return -EPERM;
558
559 dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n",
560 buf[i], reg + i, reg + i);
Mark Brown1df59812011-06-10 19:28:10 +0100561 ret = regmap_write(wm831x->regmap, reg + i, buf[i]);
Mark Brownd2bedfe2009-07-27 14:45:52 +0100562 }
563
Mark Brown1df59812011-06-10 19:28:10 +0100564 return 0;
Mark Brownd2bedfe2009-07-27 14:45:52 +0100565}
566
567/**
568 * wm831x_reg_write: Write a single WM831x register.
569 *
570 * @wm831x: Device to write to.
571 * @reg: Register to write to.
572 * @val: Value to write.
573 */
574int wm831x_reg_write(struct wm831x *wm831x, unsigned short reg,
575 unsigned short val)
576{
577 int ret;
578
579 mutex_lock(&wm831x->io_lock);
580
581 ret = wm831x_write(wm831x, reg, 2, &val);
582
583 mutex_unlock(&wm831x->io_lock);
584
585 return ret;
586}
587EXPORT_SYMBOL_GPL(wm831x_reg_write);
588
589/**
590 * wm831x_set_bits: Set the value of a bitfield in a WM831x register
591 *
592 * @wm831x: Device to write to.
593 * @reg: Register to write to.
594 * @mask: Mask of bits to set.
595 * @val: Value to set (unshifted)
596 */
597int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
598 unsigned short mask, unsigned short val)
599{
600 int ret;
Mark Brownd2bedfe2009-07-27 14:45:52 +0100601
602 mutex_lock(&wm831x->io_lock);
603
Mark Brown1df59812011-06-10 19:28:10 +0100604 if (!wm831x_reg_locked(wm831x, reg))
605 ret = regmap_update_bits(wm831x->regmap, reg, mask, val);
606 else
607 ret = -EPERM;
Mark Brownd2bedfe2009-07-27 14:45:52 +0100608
Mark Brownd2bedfe2009-07-27 14:45:52 +0100609 mutex_unlock(&wm831x->io_lock);
610
611 return ret;
612}
613EXPORT_SYMBOL_GPL(wm831x_set_bits);
614
615static struct resource wm831x_dcdc1_resources[] = {
616 {
617 .start = WM831X_DC1_CONTROL_1,
618 .end = WM831X_DC1_DVS_CONTROL,
619 .flags = IORESOURCE_IO,
620 },
621 {
622 .name = "UV",
623 .start = WM831X_IRQ_UV_DC1,
624 .end = WM831X_IRQ_UV_DC1,
625 .flags = IORESOURCE_IRQ,
626 },
627 {
628 .name = "HC",
629 .start = WM831X_IRQ_HC_DC1,
630 .end = WM831X_IRQ_HC_DC1,
631 .flags = IORESOURCE_IRQ,
632 },
633};
634
635
636static struct resource wm831x_dcdc2_resources[] = {
637 {
638 .start = WM831X_DC2_CONTROL_1,
639 .end = WM831X_DC2_DVS_CONTROL,
640 .flags = IORESOURCE_IO,
641 },
642 {
643 .name = "UV",
644 .start = WM831X_IRQ_UV_DC2,
645 .end = WM831X_IRQ_UV_DC2,
646 .flags = IORESOURCE_IRQ,
647 },
648 {
649 .name = "HC",
650 .start = WM831X_IRQ_HC_DC2,
651 .end = WM831X_IRQ_HC_DC2,
652 .flags = IORESOURCE_IRQ,
653 },
654};
655
656static struct resource wm831x_dcdc3_resources[] = {
657 {
658 .start = WM831X_DC3_CONTROL_1,
659 .end = WM831X_DC3_SLEEP_CONTROL,
660 .flags = IORESOURCE_IO,
661 },
662 {
663 .name = "UV",
664 .start = WM831X_IRQ_UV_DC3,
665 .end = WM831X_IRQ_UV_DC3,
666 .flags = IORESOURCE_IRQ,
667 },
668};
669
670static struct resource wm831x_dcdc4_resources[] = {
671 {
672 .start = WM831X_DC4_CONTROL,
673 .end = WM831X_DC4_SLEEP_CONTROL,
674 .flags = IORESOURCE_IO,
675 },
676 {
677 .name = "UV",
678 .start = WM831X_IRQ_UV_DC4,
679 .end = WM831X_IRQ_UV_DC4,
680 .flags = IORESOURCE_IRQ,
681 },
682};
683
Mark Brownd4e0a892009-10-01 15:41:07 +0100684static struct resource wm8320_dcdc4_buck_resources[] = {
685 {
686 .start = WM831X_DC4_CONTROL,
687 .end = WM832X_DC4_SLEEP_CONTROL,
688 .flags = IORESOURCE_IO,
689 },
690 {
691 .name = "UV",
692 .start = WM831X_IRQ_UV_DC4,
693 .end = WM831X_IRQ_UV_DC4,
694 .flags = IORESOURCE_IRQ,
695 },
696};
697
Mark Brownd2bedfe2009-07-27 14:45:52 +0100698static struct resource wm831x_gpio_resources[] = {
699 {
700 .start = WM831X_IRQ_GPIO_1,
701 .end = WM831X_IRQ_GPIO_16,
702 .flags = IORESOURCE_IRQ,
703 },
704};
705
706static struct resource wm831x_isink1_resources[] = {
707 {
708 .start = WM831X_CURRENT_SINK_1,
709 .end = WM831X_CURRENT_SINK_1,
710 .flags = IORESOURCE_IO,
711 },
712 {
713 .start = WM831X_IRQ_CS1,
714 .end = WM831X_IRQ_CS1,
715 .flags = IORESOURCE_IRQ,
716 },
717};
718
719static struct resource wm831x_isink2_resources[] = {
720 {
721 .start = WM831X_CURRENT_SINK_2,
722 .end = WM831X_CURRENT_SINK_2,
723 .flags = IORESOURCE_IO,
724 },
725 {
726 .start = WM831X_IRQ_CS2,
727 .end = WM831X_IRQ_CS2,
728 .flags = IORESOURCE_IRQ,
729 },
730};
731
732static struct resource wm831x_ldo1_resources[] = {
733 {
734 .start = WM831X_LDO1_CONTROL,
735 .end = WM831X_LDO1_SLEEP_CONTROL,
736 .flags = IORESOURCE_IO,
737 },
738 {
739 .name = "UV",
740 .start = WM831X_IRQ_UV_LDO1,
741 .end = WM831X_IRQ_UV_LDO1,
742 .flags = IORESOURCE_IRQ,
743 },
744};
745
746static struct resource wm831x_ldo2_resources[] = {
747 {
748 .start = WM831X_LDO2_CONTROL,
749 .end = WM831X_LDO2_SLEEP_CONTROL,
750 .flags = IORESOURCE_IO,
751 },
752 {
753 .name = "UV",
754 .start = WM831X_IRQ_UV_LDO2,
755 .end = WM831X_IRQ_UV_LDO2,
756 .flags = IORESOURCE_IRQ,
757 },
758};
759
760static struct resource wm831x_ldo3_resources[] = {
761 {
762 .start = WM831X_LDO3_CONTROL,
763 .end = WM831X_LDO3_SLEEP_CONTROL,
764 .flags = IORESOURCE_IO,
765 },
766 {
767 .name = "UV",
768 .start = WM831X_IRQ_UV_LDO3,
769 .end = WM831X_IRQ_UV_LDO3,
770 .flags = IORESOURCE_IRQ,
771 },
772};
773
774static struct resource wm831x_ldo4_resources[] = {
775 {
776 .start = WM831X_LDO4_CONTROL,
777 .end = WM831X_LDO4_SLEEP_CONTROL,
778 .flags = IORESOURCE_IO,
779 },
780 {
781 .name = "UV",
782 .start = WM831X_IRQ_UV_LDO4,
783 .end = WM831X_IRQ_UV_LDO4,
784 .flags = IORESOURCE_IRQ,
785 },
786};
787
788static struct resource wm831x_ldo5_resources[] = {
789 {
790 .start = WM831X_LDO5_CONTROL,
791 .end = WM831X_LDO5_SLEEP_CONTROL,
792 .flags = IORESOURCE_IO,
793 },
794 {
795 .name = "UV",
796 .start = WM831X_IRQ_UV_LDO5,
797 .end = WM831X_IRQ_UV_LDO5,
798 .flags = IORESOURCE_IRQ,
799 },
800};
801
802static struct resource wm831x_ldo6_resources[] = {
803 {
804 .start = WM831X_LDO6_CONTROL,
805 .end = WM831X_LDO6_SLEEP_CONTROL,
806 .flags = IORESOURCE_IO,
807 },
808 {
809 .name = "UV",
810 .start = WM831X_IRQ_UV_LDO6,
811 .end = WM831X_IRQ_UV_LDO6,
812 .flags = IORESOURCE_IRQ,
813 },
814};
815
816static struct resource wm831x_ldo7_resources[] = {
817 {
818 .start = WM831X_LDO7_CONTROL,
819 .end = WM831X_LDO7_SLEEP_CONTROL,
820 .flags = IORESOURCE_IO,
821 },
822 {
823 .name = "UV",
824 .start = WM831X_IRQ_UV_LDO7,
825 .end = WM831X_IRQ_UV_LDO7,
826 .flags = IORESOURCE_IRQ,
827 },
828};
829
830static struct resource wm831x_ldo8_resources[] = {
831 {
832 .start = WM831X_LDO8_CONTROL,
833 .end = WM831X_LDO8_SLEEP_CONTROL,
834 .flags = IORESOURCE_IO,
835 },
836 {
837 .name = "UV",
838 .start = WM831X_IRQ_UV_LDO8,
839 .end = WM831X_IRQ_UV_LDO8,
840 .flags = IORESOURCE_IRQ,
841 },
842};
843
844static struct resource wm831x_ldo9_resources[] = {
845 {
846 .start = WM831X_LDO9_CONTROL,
847 .end = WM831X_LDO9_SLEEP_CONTROL,
848 .flags = IORESOURCE_IO,
849 },
850 {
851 .name = "UV",
852 .start = WM831X_IRQ_UV_LDO9,
853 .end = WM831X_IRQ_UV_LDO9,
854 .flags = IORESOURCE_IRQ,
855 },
856};
857
858static struct resource wm831x_ldo10_resources[] = {
859 {
860 .start = WM831X_LDO10_CONTROL,
861 .end = WM831X_LDO10_SLEEP_CONTROL,
862 .flags = IORESOURCE_IO,
863 },
864 {
865 .name = "UV",
866 .start = WM831X_IRQ_UV_LDO10,
867 .end = WM831X_IRQ_UV_LDO10,
868 .flags = IORESOURCE_IRQ,
869 },
870};
871
872static struct resource wm831x_ldo11_resources[] = {
873 {
874 .start = WM831X_LDO11_ON_CONTROL,
875 .end = WM831X_LDO11_SLEEP_CONTROL,
876 .flags = IORESOURCE_IO,
877 },
878};
879
880static struct resource wm831x_on_resources[] = {
881 {
882 .start = WM831X_IRQ_ON,
883 .end = WM831X_IRQ_ON,
884 .flags = IORESOURCE_IRQ,
885 },
886};
887
888
889static struct resource wm831x_power_resources[] = {
890 {
891 .name = "SYSLO",
892 .start = WM831X_IRQ_PPM_SYSLO,
893 .end = WM831X_IRQ_PPM_SYSLO,
894 .flags = IORESOURCE_IRQ,
895 },
896 {
897 .name = "PWR SRC",
898 .start = WM831X_IRQ_PPM_PWR_SRC,
899 .end = WM831X_IRQ_PPM_PWR_SRC,
900 .flags = IORESOURCE_IRQ,
901 },
902 {
903 .name = "USB CURR",
904 .start = WM831X_IRQ_PPM_USB_CURR,
905 .end = WM831X_IRQ_PPM_USB_CURR,
906 .flags = IORESOURCE_IRQ,
907 },
908 {
909 .name = "BATT HOT",
910 .start = WM831X_IRQ_CHG_BATT_HOT,
911 .end = WM831X_IRQ_CHG_BATT_HOT,
912 .flags = IORESOURCE_IRQ,
913 },
914 {
915 .name = "BATT COLD",
916 .start = WM831X_IRQ_CHG_BATT_COLD,
917 .end = WM831X_IRQ_CHG_BATT_COLD,
918 .flags = IORESOURCE_IRQ,
919 },
920 {
921 .name = "BATT FAIL",
922 .start = WM831X_IRQ_CHG_BATT_FAIL,
923 .end = WM831X_IRQ_CHG_BATT_FAIL,
924 .flags = IORESOURCE_IRQ,
925 },
926 {
927 .name = "OV",
928 .start = WM831X_IRQ_CHG_OV,
929 .end = WM831X_IRQ_CHG_OV,
930 .flags = IORESOURCE_IRQ,
931 },
932 {
933 .name = "END",
934 .start = WM831X_IRQ_CHG_END,
935 .end = WM831X_IRQ_CHG_END,
936 .flags = IORESOURCE_IRQ,
937 },
938 {
939 .name = "TO",
940 .start = WM831X_IRQ_CHG_TO,
941 .end = WM831X_IRQ_CHG_TO,
942 .flags = IORESOURCE_IRQ,
943 },
944 {
945 .name = "MODE",
946 .start = WM831X_IRQ_CHG_MODE,
947 .end = WM831X_IRQ_CHG_MODE,
948 .flags = IORESOURCE_IRQ,
949 },
950 {
951 .name = "START",
952 .start = WM831X_IRQ_CHG_START,
953 .end = WM831X_IRQ_CHG_START,
954 .flags = IORESOURCE_IRQ,
955 },
956};
957
958static struct resource wm831x_rtc_resources[] = {
959 {
960 .name = "PER",
961 .start = WM831X_IRQ_RTC_PER,
962 .end = WM831X_IRQ_RTC_PER,
963 .flags = IORESOURCE_IRQ,
964 },
965 {
966 .name = "ALM",
967 .start = WM831X_IRQ_RTC_ALM,
968 .end = WM831X_IRQ_RTC_ALM,
969 .flags = IORESOURCE_IRQ,
970 },
971};
972
973static struct resource wm831x_status1_resources[] = {
974 {
975 .start = WM831X_STATUS_LED_1,
976 .end = WM831X_STATUS_LED_1,
977 .flags = IORESOURCE_IO,
978 },
979};
980
981static struct resource wm831x_status2_resources[] = {
982 {
983 .start = WM831X_STATUS_LED_2,
984 .end = WM831X_STATUS_LED_2,
985 .flags = IORESOURCE_IO,
986 },
987};
988
989static struct resource wm831x_touch_resources[] = {
990 {
991 .name = "TCHPD",
992 .start = WM831X_IRQ_TCHPD,
993 .end = WM831X_IRQ_TCHPD,
994 .flags = IORESOURCE_IRQ,
995 },
996 {
997 .name = "TCHDATA",
998 .start = WM831X_IRQ_TCHDATA,
999 .end = WM831X_IRQ_TCHDATA,
1000 .flags = IORESOURCE_IRQ,
1001 },
1002};
1003
1004static struct resource wm831x_wdt_resources[] = {
1005 {
1006 .start = WM831X_IRQ_WDOG_TO,
1007 .end = WM831X_IRQ_WDOG_TO,
1008 .flags = IORESOURCE_IRQ,
1009 },
1010};
1011
1012static struct mfd_cell wm8310_devs[] = {
1013 {
Mark Brownc26964e2009-10-01 15:41:06 +01001014 .name = "wm831x-backup",
1015 },
1016 {
Mark Brownd2bedfe2009-07-27 14:45:52 +01001017 .name = "wm831x-buckv",
1018 .id = 1,
1019 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
1020 .resources = wm831x_dcdc1_resources,
1021 },
1022 {
1023 .name = "wm831x-buckv",
1024 .id = 2,
1025 .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources),
1026 .resources = wm831x_dcdc2_resources,
1027 },
1028 {
1029 .name = "wm831x-buckp",
1030 .id = 3,
1031 .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources),
1032 .resources = wm831x_dcdc3_resources,
1033 },
1034 {
1035 .name = "wm831x-boostp",
1036 .id = 4,
1037 .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
1038 .resources = wm831x_dcdc4_resources,
1039 },
1040 {
Mark Browna5e06782011-06-24 12:17:07 +01001041 .name = "wm831x-clk",
1042 },
1043 {
Mark Brownd2bedfe2009-07-27 14:45:52 +01001044 .name = "wm831x-epe",
1045 .id = 1,
1046 },
1047 {
1048 .name = "wm831x-epe",
1049 .id = 2,
1050 },
1051 {
1052 .name = "wm831x-gpio",
1053 .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
1054 .resources = wm831x_gpio_resources,
1055 },
1056 {
1057 .name = "wm831x-hwmon",
1058 },
1059 {
1060 .name = "wm831x-isink",
1061 .id = 1,
1062 .num_resources = ARRAY_SIZE(wm831x_isink1_resources),
1063 .resources = wm831x_isink1_resources,
1064 },
1065 {
1066 .name = "wm831x-isink",
1067 .id = 2,
1068 .num_resources = ARRAY_SIZE(wm831x_isink2_resources),
1069 .resources = wm831x_isink2_resources,
1070 },
1071 {
1072 .name = "wm831x-ldo",
1073 .id = 1,
1074 .num_resources = ARRAY_SIZE(wm831x_ldo1_resources),
1075 .resources = wm831x_ldo1_resources,
1076 },
1077 {
1078 .name = "wm831x-ldo",
1079 .id = 2,
1080 .num_resources = ARRAY_SIZE(wm831x_ldo2_resources),
1081 .resources = wm831x_ldo2_resources,
1082 },
1083 {
1084 .name = "wm831x-ldo",
1085 .id = 3,
1086 .num_resources = ARRAY_SIZE(wm831x_ldo3_resources),
1087 .resources = wm831x_ldo3_resources,
1088 },
1089 {
1090 .name = "wm831x-ldo",
1091 .id = 4,
1092 .num_resources = ARRAY_SIZE(wm831x_ldo4_resources),
1093 .resources = wm831x_ldo4_resources,
1094 },
1095 {
1096 .name = "wm831x-ldo",
1097 .id = 5,
1098 .num_resources = ARRAY_SIZE(wm831x_ldo5_resources),
1099 .resources = wm831x_ldo5_resources,
1100 },
1101 {
1102 .name = "wm831x-ldo",
1103 .id = 6,
1104 .num_resources = ARRAY_SIZE(wm831x_ldo6_resources),
1105 .resources = wm831x_ldo6_resources,
1106 },
1107 {
1108 .name = "wm831x-aldo",
1109 .id = 7,
1110 .num_resources = ARRAY_SIZE(wm831x_ldo7_resources),
1111 .resources = wm831x_ldo7_resources,
1112 },
1113 {
1114 .name = "wm831x-aldo",
1115 .id = 8,
1116 .num_resources = ARRAY_SIZE(wm831x_ldo8_resources),
1117 .resources = wm831x_ldo8_resources,
1118 },
1119 {
1120 .name = "wm831x-aldo",
1121 .id = 9,
1122 .num_resources = ARRAY_SIZE(wm831x_ldo9_resources),
1123 .resources = wm831x_ldo9_resources,
1124 },
1125 {
1126 .name = "wm831x-aldo",
1127 .id = 10,
1128 .num_resources = ARRAY_SIZE(wm831x_ldo10_resources),
1129 .resources = wm831x_ldo10_resources,
1130 },
1131 {
1132 .name = "wm831x-alive-ldo",
1133 .id = 11,
1134 .num_resources = ARRAY_SIZE(wm831x_ldo11_resources),
1135 .resources = wm831x_ldo11_resources,
1136 },
1137 {
1138 .name = "wm831x-on",
1139 .num_resources = ARRAY_SIZE(wm831x_on_resources),
1140 .resources = wm831x_on_resources,
1141 },
1142 {
1143 .name = "wm831x-power",
1144 .num_resources = ARRAY_SIZE(wm831x_power_resources),
1145 .resources = wm831x_power_resources,
1146 },
1147 {
Mark Brownd2bedfe2009-07-27 14:45:52 +01001148 .name = "wm831x-status",
1149 .id = 1,
1150 .num_resources = ARRAY_SIZE(wm831x_status1_resources),
1151 .resources = wm831x_status1_resources,
1152 },
1153 {
1154 .name = "wm831x-status",
1155 .id = 2,
1156 .num_resources = ARRAY_SIZE(wm831x_status2_resources),
1157 .resources = wm831x_status2_resources,
1158 },
1159 {
1160 .name = "wm831x-watchdog",
1161 .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
1162 .resources = wm831x_wdt_resources,
1163 },
1164};
1165
1166static struct mfd_cell wm8311_devs[] = {
1167 {
Mark Brownc26964e2009-10-01 15:41:06 +01001168 .name = "wm831x-backup",
1169 },
1170 {
Mark Brownd2bedfe2009-07-27 14:45:52 +01001171 .name = "wm831x-buckv",
1172 .id = 1,
1173 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
1174 .resources = wm831x_dcdc1_resources,
1175 },
1176 {
1177 .name = "wm831x-buckv",
1178 .id = 2,
1179 .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources),
1180 .resources = wm831x_dcdc2_resources,
1181 },
1182 {
1183 .name = "wm831x-buckp",
1184 .id = 3,
1185 .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources),
1186 .resources = wm831x_dcdc3_resources,
1187 },
1188 {
1189 .name = "wm831x-boostp",
1190 .id = 4,
1191 .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
1192 .resources = wm831x_dcdc4_resources,
1193 },
1194 {
Mark Browna5e06782011-06-24 12:17:07 +01001195 .name = "wm831x-clk",
1196 },
1197 {
Mark Brownd2bedfe2009-07-27 14:45:52 +01001198 .name = "wm831x-epe",
1199 .id = 1,
1200 },
1201 {
1202 .name = "wm831x-epe",
1203 .id = 2,
1204 },
1205 {
1206 .name = "wm831x-gpio",
1207 .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
1208 .resources = wm831x_gpio_resources,
1209 },
1210 {
1211 .name = "wm831x-hwmon",
1212 },
1213 {
1214 .name = "wm831x-isink",
1215 .id = 1,
1216 .num_resources = ARRAY_SIZE(wm831x_isink1_resources),
1217 .resources = wm831x_isink1_resources,
1218 },
1219 {
1220 .name = "wm831x-isink",
1221 .id = 2,
1222 .num_resources = ARRAY_SIZE(wm831x_isink2_resources),
1223 .resources = wm831x_isink2_resources,
1224 },
1225 {
1226 .name = "wm831x-ldo",
1227 .id = 1,
1228 .num_resources = ARRAY_SIZE(wm831x_ldo1_resources),
1229 .resources = wm831x_ldo1_resources,
1230 },
1231 {
1232 .name = "wm831x-ldo",
1233 .id = 2,
1234 .num_resources = ARRAY_SIZE(wm831x_ldo2_resources),
1235 .resources = wm831x_ldo2_resources,
1236 },
1237 {
1238 .name = "wm831x-ldo",
1239 .id = 3,
1240 .num_resources = ARRAY_SIZE(wm831x_ldo3_resources),
1241 .resources = wm831x_ldo3_resources,
1242 },
1243 {
1244 .name = "wm831x-ldo",
1245 .id = 4,
1246 .num_resources = ARRAY_SIZE(wm831x_ldo4_resources),
1247 .resources = wm831x_ldo4_resources,
1248 },
1249 {
1250 .name = "wm831x-ldo",
1251 .id = 5,
1252 .num_resources = ARRAY_SIZE(wm831x_ldo5_resources),
1253 .resources = wm831x_ldo5_resources,
1254 },
1255 {
1256 .name = "wm831x-aldo",
1257 .id = 7,
1258 .num_resources = ARRAY_SIZE(wm831x_ldo7_resources),
1259 .resources = wm831x_ldo7_resources,
1260 },
1261 {
1262 .name = "wm831x-alive-ldo",
1263 .id = 11,
1264 .num_resources = ARRAY_SIZE(wm831x_ldo11_resources),
1265 .resources = wm831x_ldo11_resources,
1266 },
1267 {
1268 .name = "wm831x-on",
1269 .num_resources = ARRAY_SIZE(wm831x_on_resources),
1270 .resources = wm831x_on_resources,
1271 },
1272 {
1273 .name = "wm831x-power",
1274 .num_resources = ARRAY_SIZE(wm831x_power_resources),
1275 .resources = wm831x_power_resources,
1276 },
1277 {
Mark Brownd2bedfe2009-07-27 14:45:52 +01001278 .name = "wm831x-status",
1279 .id = 1,
1280 .num_resources = ARRAY_SIZE(wm831x_status1_resources),
1281 .resources = wm831x_status1_resources,
1282 },
1283 {
1284 .name = "wm831x-status",
1285 .id = 2,
1286 .num_resources = ARRAY_SIZE(wm831x_status2_resources),
1287 .resources = wm831x_status2_resources,
1288 },
1289 {
Mark Brownd2bedfe2009-07-27 14:45:52 +01001290 .name = "wm831x-watchdog",
1291 .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
1292 .resources = wm831x_wdt_resources,
1293 },
1294};
1295
1296static struct mfd_cell wm8312_devs[] = {
1297 {
Mark Brownc26964e2009-10-01 15:41:06 +01001298 .name = "wm831x-backup",
1299 },
1300 {
Mark Brownd2bedfe2009-07-27 14:45:52 +01001301 .name = "wm831x-buckv",
1302 .id = 1,
1303 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
1304 .resources = wm831x_dcdc1_resources,
1305 },
1306 {
1307 .name = "wm831x-buckv",
1308 .id = 2,
1309 .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources),
1310 .resources = wm831x_dcdc2_resources,
1311 },
1312 {
1313 .name = "wm831x-buckp",
1314 .id = 3,
1315 .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources),
1316 .resources = wm831x_dcdc3_resources,
1317 },
1318 {
1319 .name = "wm831x-boostp",
1320 .id = 4,
1321 .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
1322 .resources = wm831x_dcdc4_resources,
1323 },
1324 {
Mark Browna5e06782011-06-24 12:17:07 +01001325 .name = "wm831x-clk",
1326 },
1327 {
Mark Brownd2bedfe2009-07-27 14:45:52 +01001328 .name = "wm831x-epe",
1329 .id = 1,
1330 },
1331 {
1332 .name = "wm831x-epe",
1333 .id = 2,
1334 },
1335 {
1336 .name = "wm831x-gpio",
1337 .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
1338 .resources = wm831x_gpio_resources,
1339 },
1340 {
1341 .name = "wm831x-hwmon",
1342 },
1343 {
1344 .name = "wm831x-isink",
1345 .id = 1,
1346 .num_resources = ARRAY_SIZE(wm831x_isink1_resources),
1347 .resources = wm831x_isink1_resources,
1348 },
1349 {
1350 .name = "wm831x-isink",
1351 .id = 2,
1352 .num_resources = ARRAY_SIZE(wm831x_isink2_resources),
1353 .resources = wm831x_isink2_resources,
1354 },
1355 {
1356 .name = "wm831x-ldo",
1357 .id = 1,
1358 .num_resources = ARRAY_SIZE(wm831x_ldo1_resources),
1359 .resources = wm831x_ldo1_resources,
1360 },
1361 {
1362 .name = "wm831x-ldo",
1363 .id = 2,
1364 .num_resources = ARRAY_SIZE(wm831x_ldo2_resources),
1365 .resources = wm831x_ldo2_resources,
1366 },
1367 {
1368 .name = "wm831x-ldo",
1369 .id = 3,
1370 .num_resources = ARRAY_SIZE(wm831x_ldo3_resources),
1371 .resources = wm831x_ldo3_resources,
1372 },
1373 {
1374 .name = "wm831x-ldo",
1375 .id = 4,
1376 .num_resources = ARRAY_SIZE(wm831x_ldo4_resources),
1377 .resources = wm831x_ldo4_resources,
1378 },
1379 {
1380 .name = "wm831x-ldo",
1381 .id = 5,
1382 .num_resources = ARRAY_SIZE(wm831x_ldo5_resources),
1383 .resources = wm831x_ldo5_resources,
1384 },
1385 {
1386 .name = "wm831x-ldo",
1387 .id = 6,
1388 .num_resources = ARRAY_SIZE(wm831x_ldo6_resources),
1389 .resources = wm831x_ldo6_resources,
1390 },
1391 {
1392 .name = "wm831x-aldo",
1393 .id = 7,
1394 .num_resources = ARRAY_SIZE(wm831x_ldo7_resources),
1395 .resources = wm831x_ldo7_resources,
1396 },
1397 {
1398 .name = "wm831x-aldo",
1399 .id = 8,
1400 .num_resources = ARRAY_SIZE(wm831x_ldo8_resources),
1401 .resources = wm831x_ldo8_resources,
1402 },
1403 {
1404 .name = "wm831x-aldo",
1405 .id = 9,
1406 .num_resources = ARRAY_SIZE(wm831x_ldo9_resources),
1407 .resources = wm831x_ldo9_resources,
1408 },
1409 {
1410 .name = "wm831x-aldo",
1411 .id = 10,
1412 .num_resources = ARRAY_SIZE(wm831x_ldo10_resources),
1413 .resources = wm831x_ldo10_resources,
1414 },
1415 {
1416 .name = "wm831x-alive-ldo",
1417 .id = 11,
1418 .num_resources = ARRAY_SIZE(wm831x_ldo11_resources),
1419 .resources = wm831x_ldo11_resources,
1420 },
1421 {
1422 .name = "wm831x-on",
1423 .num_resources = ARRAY_SIZE(wm831x_on_resources),
1424 .resources = wm831x_on_resources,
1425 },
1426 {
1427 .name = "wm831x-power",
1428 .num_resources = ARRAY_SIZE(wm831x_power_resources),
1429 .resources = wm831x_power_resources,
1430 },
1431 {
Mark Brownd2bedfe2009-07-27 14:45:52 +01001432 .name = "wm831x-status",
1433 .id = 1,
1434 .num_resources = ARRAY_SIZE(wm831x_status1_resources),
1435 .resources = wm831x_status1_resources,
1436 },
1437 {
1438 .name = "wm831x-status",
1439 .id = 2,
1440 .num_resources = ARRAY_SIZE(wm831x_status2_resources),
1441 .resources = wm831x_status2_resources,
1442 },
1443 {
Mark Brownd2bedfe2009-07-27 14:45:52 +01001444 .name = "wm831x-watchdog",
1445 .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
1446 .resources = wm831x_wdt_resources,
1447 },
1448};
1449
Mark Brownd4e0a892009-10-01 15:41:07 +01001450static struct mfd_cell wm8320_devs[] = {
1451 {
1452 .name = "wm831x-backup",
1453 },
1454 {
1455 .name = "wm831x-buckv",
1456 .id = 1,
1457 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
1458 .resources = wm831x_dcdc1_resources,
1459 },
1460 {
1461 .name = "wm831x-buckv",
1462 .id = 2,
1463 .num_resources = ARRAY_SIZE(wm831x_dcdc2_resources),
1464 .resources = wm831x_dcdc2_resources,
1465 },
1466 {
1467 .name = "wm831x-buckp",
1468 .id = 3,
1469 .num_resources = ARRAY_SIZE(wm831x_dcdc3_resources),
1470 .resources = wm831x_dcdc3_resources,
1471 },
1472 {
1473 .name = "wm831x-buckp",
1474 .id = 4,
1475 .num_resources = ARRAY_SIZE(wm8320_dcdc4_buck_resources),
1476 .resources = wm8320_dcdc4_buck_resources,
1477 },
1478 {
Mark Browna5e06782011-06-24 12:17:07 +01001479 .name = "wm831x-clk",
1480 },
1481 {
Mark Brownd4e0a892009-10-01 15:41:07 +01001482 .name = "wm831x-gpio",
1483 .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
1484 .resources = wm831x_gpio_resources,
1485 },
1486 {
1487 .name = "wm831x-hwmon",
1488 },
1489 {
1490 .name = "wm831x-ldo",
1491 .id = 1,
1492 .num_resources = ARRAY_SIZE(wm831x_ldo1_resources),
1493 .resources = wm831x_ldo1_resources,
1494 },
1495 {
1496 .name = "wm831x-ldo",
1497 .id = 2,
1498 .num_resources = ARRAY_SIZE(wm831x_ldo2_resources),
1499 .resources = wm831x_ldo2_resources,
1500 },
1501 {
1502 .name = "wm831x-ldo",
1503 .id = 3,
1504 .num_resources = ARRAY_SIZE(wm831x_ldo3_resources),
1505 .resources = wm831x_ldo3_resources,
1506 },
1507 {
1508 .name = "wm831x-ldo",
1509 .id = 4,
1510 .num_resources = ARRAY_SIZE(wm831x_ldo4_resources),
1511 .resources = wm831x_ldo4_resources,
1512 },
1513 {
1514 .name = "wm831x-ldo",
1515 .id = 5,
1516 .num_resources = ARRAY_SIZE(wm831x_ldo5_resources),
1517 .resources = wm831x_ldo5_resources,
1518 },
1519 {
1520 .name = "wm831x-ldo",
1521 .id = 6,
1522 .num_resources = ARRAY_SIZE(wm831x_ldo6_resources),
1523 .resources = wm831x_ldo6_resources,
1524 },
1525 {
1526 .name = "wm831x-aldo",
1527 .id = 7,
1528 .num_resources = ARRAY_SIZE(wm831x_ldo7_resources),
1529 .resources = wm831x_ldo7_resources,
1530 },
1531 {
1532 .name = "wm831x-aldo",
1533 .id = 8,
1534 .num_resources = ARRAY_SIZE(wm831x_ldo8_resources),
1535 .resources = wm831x_ldo8_resources,
1536 },
1537 {
1538 .name = "wm831x-aldo",
1539 .id = 9,
1540 .num_resources = ARRAY_SIZE(wm831x_ldo9_resources),
1541 .resources = wm831x_ldo9_resources,
1542 },
1543 {
1544 .name = "wm831x-aldo",
1545 .id = 10,
1546 .num_resources = ARRAY_SIZE(wm831x_ldo10_resources),
1547 .resources = wm831x_ldo10_resources,
1548 },
1549 {
1550 .name = "wm831x-alive-ldo",
1551 .id = 11,
1552 .num_resources = ARRAY_SIZE(wm831x_ldo11_resources),
1553 .resources = wm831x_ldo11_resources,
1554 },
1555 {
1556 .name = "wm831x-on",
1557 .num_resources = ARRAY_SIZE(wm831x_on_resources),
1558 .resources = wm831x_on_resources,
1559 },
1560 {
Mark Brownd4e0a892009-10-01 15:41:07 +01001561 .name = "wm831x-status",
1562 .id = 1,
1563 .num_resources = ARRAY_SIZE(wm831x_status1_resources),
1564 .resources = wm831x_status1_resources,
1565 },
1566 {
1567 .name = "wm831x-status",
1568 .id = 2,
1569 .num_resources = ARRAY_SIZE(wm831x_status2_resources),
1570 .resources = wm831x_status2_resources,
1571 },
1572 {
1573 .name = "wm831x-watchdog",
1574 .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
1575 .resources = wm831x_wdt_resources,
1576 },
1577};
1578
Mark Brown266a5e02011-06-02 19:18:49 +01001579static struct mfd_cell touch_devs[] = {
1580 {
1581 .name = "wm831x-touch",
1582 .num_resources = ARRAY_SIZE(wm831x_touch_resources),
1583 .resources = wm831x_touch_resources,
1584 },
1585};
1586
Mark Brownb9d03d92011-06-02 19:18:50 +01001587static struct mfd_cell rtc_devs[] = {
1588 {
1589 .name = "wm831x-rtc",
1590 .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
1591 .resources = wm831x_rtc_resources,
1592 },
1593};
Mark Brown266a5e02011-06-02 19:18:49 +01001594
Mark Brown63aed852009-07-27 14:45:55 +01001595static struct mfd_cell backlight_devs[] = {
1596 {
1597 .name = "wm831x-backlight",
1598 },
1599};
1600
Mark Brown1df59812011-06-10 19:28:10 +01001601struct regmap_config wm831x_regmap_config = {
1602 .reg_bits = 16,
1603 .val_bits = 16,
Mark Brown2e47fff2011-07-21 17:30:08 +01001604
Mark Brown7cccbdc2011-10-09 13:38:06 +01001605 .cache_type = REGCACHE_RBTREE,
1606
Mark Brown2e47fff2011-07-21 17:30:08 +01001607 .max_register = WM831X_DBE_CHECK_DATA,
1608 .readable_reg = wm831x_reg_readable,
1609 .writeable_reg = wm831x_reg_writeable,
1610 .volatile_reg = wm831x_reg_volatile,
Mark Brown1df59812011-06-10 19:28:10 +01001611};
1612EXPORT_SYMBOL_GPL(wm831x_regmap_config);
1613
Mark Brownd2bedfe2009-07-27 14:45:52 +01001614/*
1615 * Instantiate the generic non-control parts of the device.
1616 */
Mark Browne5b48682010-10-19 23:57:56 +02001617int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
Mark Brownd2bedfe2009-07-27 14:45:52 +01001618{
1619 struct wm831x_pdata *pdata = wm831x->dev->platform_data;
Mark Browneb503dc2011-06-02 19:18:48 +01001620 int rev, wm831x_num;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001621 enum wm831x_parent parent;
Mark Brown0b14c222011-04-04 11:04:42 +09001622 int ret, i;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001623
1624 mutex_init(&wm831x->io_lock);
1625 mutex_init(&wm831x->key_lock);
1626 dev_set_drvdata(wm831x->dev, wm831x);
Mark Brown523d9cf2011-09-15 18:54:53 +02001627 wm831x->soft_shutdown = pdata->soft_shutdown;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001628
1629 ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
1630 if (ret < 0) {
1631 dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
Mark Brown1df59812011-06-10 19:28:10 +01001632 goto err_regmap;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001633 }
Mark Brownb93cef52010-12-02 16:25:43 +00001634 switch (ret) {
1635 case 0x6204:
1636 case 0x6246:
1637 break;
1638 default:
Mark Brownd2bedfe2009-07-27 14:45:52 +01001639 dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
1640 ret = -EINVAL;
Mark Brown1df59812011-06-10 19:28:10 +01001641 goto err_regmap;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001642 }
1643
1644 ret = wm831x_reg_read(wm831x, WM831X_REVISION);
1645 if (ret < 0) {
1646 dev_err(wm831x->dev, "Failed to read revision: %d\n", ret);
Mark Brown1df59812011-06-10 19:28:10 +01001647 goto err_regmap;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001648 }
1649 rev = (ret & WM831X_PARENT_REV_MASK) >> WM831X_PARENT_REV_SHIFT;
1650
1651 ret = wm831x_reg_read(wm831x, WM831X_RESET_ID);
1652 if (ret < 0) {
1653 dev_err(wm831x->dev, "Failed to read device ID: %d\n", ret);
Mark Brown1df59812011-06-10 19:28:10 +01001654 goto err_regmap;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001655 }
1656
Mark Brown894362f2009-10-01 15:41:04 +01001657 /* Some engineering samples do not have the ID set, rely on
1658 * the device being registered correctly.
1659 */
1660 if (ret == 0) {
1661 dev_info(wm831x->dev, "Device is an engineering sample\n");
1662 ret = id;
1663 }
1664
Mark Brownd2bedfe2009-07-27 14:45:52 +01001665 switch (ret) {
Mark Brown894362f2009-10-01 15:41:04 +01001666 case WM8310:
Mark Brownd2bedfe2009-07-27 14:45:52 +01001667 parent = WM8310;
Mark Brown6f2ecaa2009-10-01 15:41:05 +01001668 wm831x->num_gpio = 16;
Mark Brownb03b4d72010-04-08 10:02:39 +02001669 wm831x->charger_irq_wake = 1;
Mark Brownf92e8f82010-02-17 18:45:25 +00001670 if (rev > 0) {
1671 wm831x->has_gpio_ena = 1;
1672 wm831x->has_cs_sts = 1;
1673 }
1674
Mark Brown894362f2009-10-01 15:41:04 +01001675 dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001676 break;
1677
Mark Brown894362f2009-10-01 15:41:04 +01001678 case WM8311:
Mark Brownd2bedfe2009-07-27 14:45:52 +01001679 parent = WM8311;
Mark Brown6f2ecaa2009-10-01 15:41:05 +01001680 wm831x->num_gpio = 16;
Mark Brownb03b4d72010-04-08 10:02:39 +02001681 wm831x->charger_irq_wake = 1;
Mark Brownf92e8f82010-02-17 18:45:25 +00001682 if (rev > 0) {
1683 wm831x->has_gpio_ena = 1;
1684 wm831x->has_cs_sts = 1;
1685 }
1686
Mark Brown894362f2009-10-01 15:41:04 +01001687 dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001688 break;
1689
Mark Brown894362f2009-10-01 15:41:04 +01001690 case WM8312:
Mark Brownd2bedfe2009-07-27 14:45:52 +01001691 parent = WM8312;
Mark Brown6f2ecaa2009-10-01 15:41:05 +01001692 wm831x->num_gpio = 16;
Mark Brownb03b4d72010-04-08 10:02:39 +02001693 wm831x->charger_irq_wake = 1;
Mark Brownf92e8f82010-02-17 18:45:25 +00001694 if (rev > 0) {
1695 wm831x->has_gpio_ena = 1;
1696 wm831x->has_cs_sts = 1;
1697 }
1698
Mark Brown894362f2009-10-01 15:41:04 +01001699 dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001700 break;
1701
Mark Brownd4e0a892009-10-01 15:41:07 +01001702 case WM8320:
1703 parent = WM8320;
1704 wm831x->num_gpio = 12;
1705 dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev);
1706 break;
1707
Mark Brown88913522010-07-21 14:23:37 +01001708 case WM8321:
1709 parent = WM8321;
1710 wm831x->num_gpio = 12;
1711 dev_info(wm831x->dev, "WM8321 revision %c\n", 'A' + rev);
1712 break;
1713
Mark Brown0b315882010-09-28 09:13:39 -07001714 case WM8325:
1715 parent = WM8325;
1716 wm831x->num_gpio = 12;
1717 dev_info(wm831x->dev, "WM8325 revision %c\n", 'A' + rev);
1718 break;
1719
Mark Brown412dc112010-11-24 18:01:41 +00001720 case WM8326:
1721 parent = WM8326;
1722 wm831x->num_gpio = 12;
1723 dev_info(wm831x->dev, "WM8326 revision %c\n", 'A' + rev);
1724 break;
1725
Mark Brownd2bedfe2009-07-27 14:45:52 +01001726 default:
1727 dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
1728 ret = -EINVAL;
Mark Brown1df59812011-06-10 19:28:10 +01001729 goto err_regmap;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001730 }
1731
1732 /* This will need revisiting in future but is OK for all
1733 * current parts.
1734 */
1735 if (parent != id)
Mark Brown894362f2009-10-01 15:41:04 +01001736 dev_warn(wm831x->dev, "Device was registered as a WM%lx\n",
Mark Brownd2bedfe2009-07-27 14:45:52 +01001737 id);
1738
1739 /* Bootstrap the user key */
1740 ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY);
1741 if (ret < 0) {
1742 dev_err(wm831x->dev, "Failed to read security key: %d\n", ret);
Mark Brown1df59812011-06-10 19:28:10 +01001743 goto err_regmap;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001744 }
1745 if (ret != 0) {
1746 dev_warn(wm831x->dev, "Security key had non-zero value %x\n",
1747 ret);
1748 wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0);
1749 }
1750 wm831x->locked = 1;
1751
1752 if (pdata && pdata->pre_init) {
1753 ret = pdata->pre_init(wm831x);
1754 if (ret != 0) {
1755 dev_err(wm831x->dev, "pre_init() failed: %d\n", ret);
Mark Brown1df59812011-06-10 19:28:10 +01001756 goto err_regmap;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001757 }
1758 }
1759
Mark Brown0b14c222011-04-04 11:04:42 +09001760 if (pdata) {
1761 for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
1762 if (!pdata->gpio_defaults[i])
1763 continue;
1764
1765 wm831x_reg_write(wm831x,
1766 WM831X_GPIO1_CONTROL + i,
1767 pdata->gpio_defaults[i] & 0xffff);
1768 }
1769 }
1770
Mark Browneb503dc2011-06-02 19:18:48 +01001771 /* Multiply by 10 as we have many subdevices of the same type */
1772 if (pdata && pdata->wm831x_num)
1773 wm831x_num = pdata->wm831x_num * 10;
1774 else
1775 wm831x_num = -1;
1776
Mark Brown7d4d0a32009-07-27 14:45:53 +01001777 ret = wm831x_irq_init(wm831x, irq);
1778 if (ret != 0)
Mark Brown1df59812011-06-10 19:28:10 +01001779 goto err_regmap;
Mark Brown7d4d0a32009-07-27 14:45:53 +01001780
Mark Browne69b6de2011-06-02 19:18:53 +01001781 wm831x_auxadc_init(wm831x);
Mark Brown473fe732010-02-23 11:08:06 +00001782
Mark Brownd2bedfe2009-07-27 14:45:52 +01001783 /* The core device is up, instantiate the subdevices. */
1784 switch (parent) {
1785 case WM8310:
Mark Browneb503dc2011-06-02 19:18:48 +01001786 ret = mfd_add_devices(wm831x->dev, wm831x_num,
Mark Brownd2bedfe2009-07-27 14:45:52 +01001787 wm8310_devs, ARRAY_SIZE(wm8310_devs),
Mark Brown5fb4d382009-11-11 16:10:22 +00001788 NULL, wm831x->irq_base);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001789 break;
1790
1791 case WM8311:
Mark Browneb503dc2011-06-02 19:18:48 +01001792 ret = mfd_add_devices(wm831x->dev, wm831x_num,
Mark Brownd2bedfe2009-07-27 14:45:52 +01001793 wm8311_devs, ARRAY_SIZE(wm8311_devs),
Mark Brown5fb4d382009-11-11 16:10:22 +00001794 NULL, wm831x->irq_base);
Mark Brown266a5e02011-06-02 19:18:49 +01001795 if (!pdata || !pdata->disable_touch)
1796 mfd_add_devices(wm831x->dev, wm831x_num,
1797 touch_devs, ARRAY_SIZE(touch_devs),
1798 NULL, wm831x->irq_base);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001799 break;
1800
1801 case WM8312:
Mark Browneb503dc2011-06-02 19:18:48 +01001802 ret = mfd_add_devices(wm831x->dev, wm831x_num,
Mark Brownd2bedfe2009-07-27 14:45:52 +01001803 wm8312_devs, ARRAY_SIZE(wm8312_devs),
Mark Brown5fb4d382009-11-11 16:10:22 +00001804 NULL, wm831x->irq_base);
Mark Brown266a5e02011-06-02 19:18:49 +01001805 if (!pdata || !pdata->disable_touch)
1806 mfd_add_devices(wm831x->dev, wm831x_num,
1807 touch_devs, ARRAY_SIZE(touch_devs),
1808 NULL, wm831x->irq_base);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001809 break;
1810
Mark Brownd4e0a892009-10-01 15:41:07 +01001811 case WM8320:
Mark Brown88913522010-07-21 14:23:37 +01001812 case WM8321:
Mark Brown0b315882010-09-28 09:13:39 -07001813 case WM8325:
Mark Brown412dc112010-11-24 18:01:41 +00001814 case WM8326:
Mark Browneb503dc2011-06-02 19:18:48 +01001815 ret = mfd_add_devices(wm831x->dev, wm831x_num,
Mark Brown0b315882010-09-28 09:13:39 -07001816 wm8320_devs, ARRAY_SIZE(wm8320_devs),
Mark Brownbd7c72e2010-11-24 18:01:39 +00001817 NULL, wm831x->irq_base);
Mark Brown0b315882010-09-28 09:13:39 -07001818 break;
1819
Mark Brownd2bedfe2009-07-27 14:45:52 +01001820 default:
1821 /* If this happens the bus probe function is buggy */
1822 BUG();
1823 }
1824
1825 if (ret != 0) {
1826 dev_err(wm831x->dev, "Failed to add children\n");
Mark Brown7d4d0a32009-07-27 14:45:53 +01001827 goto err_irq;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001828 }
1829
Mark Brownb9d03d92011-06-02 19:18:50 +01001830 /* The RTC can only be used if the 32.768kHz crystal is
1831 * enabled; this can't be controlled by software at runtime.
1832 */
1833 ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
1834 if (ret < 0) {
1835 dev_err(wm831x->dev, "Failed to read clock status: %d\n", ret);
1836 goto err_irq;
1837 }
1838
1839 if (ret & WM831X_XTAL_ENA) {
1840 ret = mfd_add_devices(wm831x->dev, wm831x_num,
1841 rtc_devs, ARRAY_SIZE(rtc_devs),
1842 NULL, wm831x->irq_base);
1843 if (ret != 0) {
1844 dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret);
1845 goto err_irq;
1846 }
1847 } else {
1848 dev_info(wm831x->dev, "32.768kHz clock disabled, no RTC\n");
1849 }
1850
Mark Brown63aed852009-07-27 14:45:55 +01001851 if (pdata && pdata->backlight) {
1852 /* Treat errors as non-critical */
Mark Browneb503dc2011-06-02 19:18:48 +01001853 ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs,
Mark Brown5fb4d382009-11-11 16:10:22 +00001854 ARRAY_SIZE(backlight_devs), NULL,
1855 wm831x->irq_base);
Mark Brown63aed852009-07-27 14:45:55 +01001856 if (ret < 0)
1857 dev_err(wm831x->dev, "Failed to add backlight: %d\n",
1858 ret);
1859 }
1860
Mark Brown6704e512009-07-27 14:45:56 +01001861 wm831x_otp_init(wm831x);
1862
Mark Brownd2bedfe2009-07-27 14:45:52 +01001863 if (pdata && pdata->post_init) {
1864 ret = pdata->post_init(wm831x);
1865 if (ret != 0) {
1866 dev_err(wm831x->dev, "post_init() failed: %d\n", ret);
Mark Brown7d4d0a32009-07-27 14:45:53 +01001867 goto err_irq;
Mark Brownd2bedfe2009-07-27 14:45:52 +01001868 }
1869 }
1870
1871 return 0;
1872
Mark Brown7d4d0a32009-07-27 14:45:53 +01001873err_irq:
1874 wm831x_irq_exit(wm831x);
Mark Brown1df59812011-06-10 19:28:10 +01001875err_regmap:
Mark Brownd2bedfe2009-07-27 14:45:52 +01001876 mfd_remove_devices(wm831x->dev);
Mark Brown1df59812011-06-10 19:28:10 +01001877 regmap_exit(wm831x->regmap);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001878 kfree(wm831x);
1879 return ret;
1880}
1881
Mark Browne5b48682010-10-19 23:57:56 +02001882void wm831x_device_exit(struct wm831x *wm831x)
Mark Brownd2bedfe2009-07-27 14:45:52 +01001883{
Mark Brown6704e512009-07-27 14:45:56 +01001884 wm831x_otp_exit(wm831x);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001885 mfd_remove_devices(wm831x->dev);
Mark Brown473fe732010-02-23 11:08:06 +00001886 if (wm831x->irq_base)
1887 free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
Mark Brown7d4d0a32009-07-27 14:45:53 +01001888 wm831x_irq_exit(wm831x);
Mark Brown1df59812011-06-10 19:28:10 +01001889 regmap_exit(wm831x->regmap);
Mark Brownd2bedfe2009-07-27 14:45:52 +01001890 kfree(wm831x);
1891}
1892
Mark Browne5b48682010-10-19 23:57:56 +02001893int wm831x_device_suspend(struct wm831x *wm831x)
Mark Brownb03b4d72010-04-08 10:02:39 +02001894{
1895 int reg, mask;
1896
1897 /* If the charger IRQs are a wake source then make sure we ack
1898 * them even if they're not actively being used (eg, no power
1899 * driver or no IRQ line wired up) then acknowledge the
1900 * interrupts otherwise suspend won't last very long.
1901 */
1902 if (wm831x->charger_irq_wake) {
1903 reg = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_2_MASK);
1904
1905 mask = WM831X_CHG_BATT_HOT_EINT |
1906 WM831X_CHG_BATT_COLD_EINT |
1907 WM831X_CHG_BATT_FAIL_EINT |
1908 WM831X_CHG_OV_EINT | WM831X_CHG_END_EINT |
1909 WM831X_CHG_TO_EINT | WM831X_CHG_MODE_EINT |
1910 WM831X_CHG_START_EINT;
1911
1912 /* If any of the interrupts are masked read the statuses */
1913 if (reg & mask)
1914 reg = wm831x_reg_read(wm831x,
1915 WM831X_INTERRUPT_STATUS_2);
1916
1917 if (reg & mask) {
1918 dev_info(wm831x->dev,
1919 "Acknowledging masked charger IRQs: %x\n",
1920 reg & mask);
1921 wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_2,
1922 reg & mask);
1923 }
1924 }
1925
1926 return 0;
1927}
1928
Mark Brown523d9cf2011-09-15 18:54:53 +02001929void wm831x_device_shutdown(struct wm831x *wm831x)
1930{
1931 if (wm831x->soft_shutdown) {
1932 dev_info(wm831x->dev, "Initiating shutdown...\n");
1933 wm831x_set_bits(wm831x, WM831X_POWER_STATE, WM831X_CHIP_ON, 0);
1934 }
1935}
1936EXPORT_SYMBOL_GPL(wm831x_device_shutdown);
1937
Mark Browne5b48682010-10-19 23:57:56 +02001938MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
Mark Brownd2bedfe2009-07-27 14:45:52 +01001939MODULE_LICENSE("GPL");
1940MODULE_AUTHOR("Mark Brown");