diff options
Diffstat (limited to 'drivers/mfd/wm8350-core.c')
-rw-r--r-- | drivers/mfd/wm8350-core.c | 325 |
1 files changed, 11 insertions, 314 deletions
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index fadcbbe9e2ba..7c1ae24605d9 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c | |||
@@ -60,181 +60,32 @@ | |||
60 | /* | 60 | /* |
61 | * WM8350 Device IO | 61 | * WM8350 Device IO |
62 | */ | 62 | */ |
63 | static DEFINE_MUTEX(io_mutex); | ||
64 | static DEFINE_MUTEX(reg_lock_mutex); | 63 | static DEFINE_MUTEX(reg_lock_mutex); |
65 | 64 | ||
66 | /* Perform a physical read from the device. | ||
67 | */ | ||
68 | static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs, | ||
69 | u16 *dest) | ||
70 | { | ||
71 | int i, ret; | ||
72 | int bytes = num_regs * 2; | ||
73 | |||
74 | dev_dbg(wm8350->dev, "volatile read\n"); | ||
75 | ret = regmap_raw_read(wm8350->regmap, reg, dest, bytes); | ||
76 | |||
77 | for (i = reg; i < reg + num_regs; i++) { | ||
78 | /* Cache is CPU endian */ | ||
79 | dest[i - reg] = be16_to_cpu(dest[i - reg]); | ||
80 | |||
81 | /* Mask out non-readable bits */ | ||
82 | dest[i - reg] &= wm8350_reg_io_map[i].readable; | ||
83 | } | ||
84 | |||
85 | dump(num_regs, dest); | ||
86 | |||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest) | ||
91 | { | ||
92 | int i; | ||
93 | int end = reg + num_regs; | ||
94 | int ret = 0; | ||
95 | int bytes = num_regs * 2; | ||
96 | |||
97 | if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { | ||
98 | dev_err(wm8350->dev, "invalid reg %x\n", | ||
99 | reg + num_regs - 1); | ||
100 | return -EINVAL; | ||
101 | } | ||
102 | |||
103 | dev_dbg(wm8350->dev, | ||
104 | "%s R%d(0x%2.2x) %d regs\n", __func__, reg, reg, num_regs); | ||
105 | |||
106 | #if WM8350_BUS_DEBUG | ||
107 | /* we can _safely_ read any register, but warn if read not supported */ | ||
108 | for (i = reg; i < end; i++) { | ||
109 | if (!wm8350_reg_io_map[i].readable) | ||
110 | dev_warn(wm8350->dev, | ||
111 | "reg R%d is not readable\n", i); | ||
112 | } | ||
113 | #endif | ||
114 | |||
115 | /* if any volatile registers are required, then read back all */ | ||
116 | for (i = reg; i < end; i++) | ||
117 | if (wm8350_reg_io_map[i].vol) | ||
118 | return wm8350_phys_read(wm8350, reg, num_regs, dest); | ||
119 | |||
120 | /* no volatiles, then cache is good */ | ||
121 | dev_dbg(wm8350->dev, "cache read\n"); | ||
122 | memcpy(dest, &wm8350->reg_cache[reg], bytes); | ||
123 | dump(num_regs, dest); | ||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg) | ||
128 | { | ||
129 | if (reg == WM8350_SECURITY || | ||
130 | wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY) | ||
131 | return 0; | ||
132 | |||
133 | if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 && | ||
134 | reg <= WM8350_GPIO_FUNCTION_SELECT_4) || | ||
135 | (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && | ||
136 | reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) | ||
137 | return 1; | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src) | ||
142 | { | ||
143 | int i; | ||
144 | int end = reg + num_regs; | ||
145 | int bytes = num_regs * 2; | ||
146 | |||
147 | if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { | ||
148 | dev_err(wm8350->dev, "invalid reg %x\n", | ||
149 | reg + num_regs - 1); | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | |||
153 | /* it's generally not a good idea to write to RO or locked registers */ | ||
154 | for (i = reg; i < end; i++) { | ||
155 | if (!wm8350_reg_io_map[i].writable) { | ||
156 | dev_err(wm8350->dev, | ||
157 | "attempted write to read only reg R%d\n", i); | ||
158 | return -EINVAL; | ||
159 | } | ||
160 | |||
161 | if (is_reg_locked(wm8350, i)) { | ||
162 | dev_err(wm8350->dev, | ||
163 | "attempted write to locked reg R%d\n", i); | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
167 | src[i - reg] &= wm8350_reg_io_map[i].writable; | ||
168 | |||
169 | wm8350->reg_cache[i] = | ||
170 | (wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable) | ||
171 | | src[i - reg]; | ||
172 | |||
173 | src[i - reg] = cpu_to_be16(src[i - reg]); | ||
174 | } | ||
175 | |||
176 | /* Actually write it out */ | ||
177 | return regmap_raw_write(wm8350->regmap, reg, src, bytes); | ||
178 | } | ||
179 | |||
180 | /* | 65 | /* |
181 | * Safe read, modify, write methods | 66 | * Safe read, modify, write methods |
182 | */ | 67 | */ |
183 | int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask) | 68 | int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask) |
184 | { | 69 | { |
185 | u16 data; | 70 | return regmap_update_bits(wm8350->regmap, reg, mask, 0); |
186 | int err; | ||
187 | |||
188 | mutex_lock(&io_mutex); | ||
189 | err = wm8350_read(wm8350, reg, 1, &data); | ||
190 | if (err) { | ||
191 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); | ||
192 | goto out; | ||
193 | } | ||
194 | |||
195 | data &= ~mask; | ||
196 | err = wm8350_write(wm8350, reg, 1, &data); | ||
197 | if (err) | ||
198 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); | ||
199 | out: | ||
200 | mutex_unlock(&io_mutex); | ||
201 | return err; | ||
202 | } | 71 | } |
203 | EXPORT_SYMBOL_GPL(wm8350_clear_bits); | 72 | EXPORT_SYMBOL_GPL(wm8350_clear_bits); |
204 | 73 | ||
205 | int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask) | 74 | int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask) |
206 | { | 75 | { |
207 | u16 data; | 76 | return regmap_update_bits(wm8350->regmap, reg, mask, mask); |
208 | int err; | ||
209 | |||
210 | mutex_lock(&io_mutex); | ||
211 | err = wm8350_read(wm8350, reg, 1, &data); | ||
212 | if (err) { | ||
213 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); | ||
214 | goto out; | ||
215 | } | ||
216 | |||
217 | data |= mask; | ||
218 | err = wm8350_write(wm8350, reg, 1, &data); | ||
219 | if (err) | ||
220 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); | ||
221 | out: | ||
222 | mutex_unlock(&io_mutex); | ||
223 | return err; | ||
224 | } | 77 | } |
225 | EXPORT_SYMBOL_GPL(wm8350_set_bits); | 78 | EXPORT_SYMBOL_GPL(wm8350_set_bits); |
226 | 79 | ||
227 | u16 wm8350_reg_read(struct wm8350 *wm8350, int reg) | 80 | u16 wm8350_reg_read(struct wm8350 *wm8350, int reg) |
228 | { | 81 | { |
229 | u16 data; | 82 | unsigned int data; |
230 | int err; | 83 | int err; |
231 | 84 | ||
232 | mutex_lock(&io_mutex); | 85 | err = regmap_read(wm8350->regmap, reg, &data); |
233 | err = wm8350_read(wm8350, reg, 1, &data); | ||
234 | if (err) | 86 | if (err) |
235 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); | 87 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); |
236 | 88 | ||
237 | mutex_unlock(&io_mutex); | ||
238 | return data; | 89 | return data; |
239 | } | 90 | } |
240 | EXPORT_SYMBOL_GPL(wm8350_reg_read); | 91 | EXPORT_SYMBOL_GPL(wm8350_reg_read); |
@@ -242,13 +93,11 @@ EXPORT_SYMBOL_GPL(wm8350_reg_read); | |||
242 | int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val) | 93 | int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val) |
243 | { | 94 | { |
244 | int ret; | 95 | int ret; |
245 | u16 data = val; | ||
246 | 96 | ||
247 | mutex_lock(&io_mutex); | 97 | ret = regmap_write(wm8350->regmap, reg, val); |
248 | ret = wm8350_write(wm8350, reg, 1, &data); | 98 | |
249 | if (ret) | 99 | if (ret) |
250 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); | 100 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); |
251 | mutex_unlock(&io_mutex); | ||
252 | return ret; | 101 | return ret; |
253 | } | 102 | } |
254 | EXPORT_SYMBOL_GPL(wm8350_reg_write); | 103 | EXPORT_SYMBOL_GPL(wm8350_reg_write); |
@@ -258,12 +107,11 @@ int wm8350_block_read(struct wm8350 *wm8350, int start_reg, int regs, | |||
258 | { | 107 | { |
259 | int err = 0; | 108 | int err = 0; |
260 | 109 | ||
261 | mutex_lock(&io_mutex); | 110 | err = regmap_bulk_read(wm8350->regmap, start_reg, dest, regs); |
262 | err = wm8350_read(wm8350, start_reg, regs, dest); | ||
263 | if (err) | 111 | if (err) |
264 | dev_err(wm8350->dev, "block read starting from R%d failed\n", | 112 | dev_err(wm8350->dev, "block read starting from R%d failed\n", |
265 | start_reg); | 113 | start_reg); |
266 | mutex_unlock(&io_mutex); | 114 | |
267 | return err; | 115 | return err; |
268 | } | 116 | } |
269 | EXPORT_SYMBOL_GPL(wm8350_block_read); | 117 | EXPORT_SYMBOL_GPL(wm8350_block_read); |
@@ -273,12 +121,11 @@ int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs, | |||
273 | { | 121 | { |
274 | int ret = 0; | 122 | int ret = 0; |
275 | 123 | ||
276 | mutex_lock(&io_mutex); | 124 | ret = regmap_bulk_write(wm8350->regmap, start_reg, src, regs); |
277 | ret = wm8350_write(wm8350, start_reg, regs, src); | ||
278 | if (ret) | 125 | if (ret) |
279 | dev_err(wm8350->dev, "block write starting at R%d failed\n", | 126 | dev_err(wm8350->dev, "block write starting at R%d failed\n", |
280 | start_reg); | 127 | start_reg); |
281 | mutex_unlock(&io_mutex); | 128 | |
282 | return ret; | 129 | return ret; |
283 | } | 130 | } |
284 | EXPORT_SYMBOL_GPL(wm8350_block_write); | 131 | EXPORT_SYMBOL_GPL(wm8350_block_write); |
@@ -402,146 +249,6 @@ static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data) | |||
402 | } | 249 | } |
403 | 250 | ||
404 | /* | 251 | /* |
405 | * Cache is always host endian. | ||
406 | */ | ||
407 | static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode) | ||
408 | { | ||
409 | int i, ret = 0; | ||
410 | u16 value; | ||
411 | const u16 *reg_map; | ||
412 | |||
413 | switch (type) { | ||
414 | case 0: | ||
415 | switch (mode) { | ||
416 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0 | ||
417 | case 0: | ||
418 | reg_map = wm8350_mode0_defaults; | ||
419 | break; | ||
420 | #endif | ||
421 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1 | ||
422 | case 1: | ||
423 | reg_map = wm8350_mode1_defaults; | ||
424 | break; | ||
425 | #endif | ||
426 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2 | ||
427 | case 2: | ||
428 | reg_map = wm8350_mode2_defaults; | ||
429 | break; | ||
430 | #endif | ||
431 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3 | ||
432 | case 3: | ||
433 | reg_map = wm8350_mode3_defaults; | ||
434 | break; | ||
435 | #endif | ||
436 | default: | ||
437 | dev_err(wm8350->dev, | ||
438 | "WM8350 configuration mode %d not supported\n", | ||
439 | mode); | ||
440 | return -EINVAL; | ||
441 | } | ||
442 | break; | ||
443 | |||
444 | case 1: | ||
445 | switch (mode) { | ||
446 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0 | ||
447 | case 0: | ||
448 | reg_map = wm8351_mode0_defaults; | ||
449 | break; | ||
450 | #endif | ||
451 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1 | ||
452 | case 1: | ||
453 | reg_map = wm8351_mode1_defaults; | ||
454 | break; | ||
455 | #endif | ||
456 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2 | ||
457 | case 2: | ||
458 | reg_map = wm8351_mode2_defaults; | ||
459 | break; | ||
460 | #endif | ||
461 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3 | ||
462 | case 3: | ||
463 | reg_map = wm8351_mode3_defaults; | ||
464 | break; | ||
465 | #endif | ||
466 | default: | ||
467 | dev_err(wm8350->dev, | ||
468 | "WM8351 configuration mode %d not supported\n", | ||
469 | mode); | ||
470 | return -EINVAL; | ||
471 | } | ||
472 | break; | ||
473 | |||
474 | case 2: | ||
475 | switch (mode) { | ||
476 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0 | ||
477 | case 0: | ||
478 | reg_map = wm8352_mode0_defaults; | ||
479 | break; | ||
480 | #endif | ||
481 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1 | ||
482 | case 1: | ||
483 | reg_map = wm8352_mode1_defaults; | ||
484 | break; | ||
485 | #endif | ||
486 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2 | ||
487 | case 2: | ||
488 | reg_map = wm8352_mode2_defaults; | ||
489 | break; | ||
490 | #endif | ||
491 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3 | ||
492 | case 3: | ||
493 | reg_map = wm8352_mode3_defaults; | ||
494 | break; | ||
495 | #endif | ||
496 | default: | ||
497 | dev_err(wm8350->dev, | ||
498 | "WM8352 configuration mode %d not supported\n", | ||
499 | mode); | ||
500 | return -EINVAL; | ||
501 | } | ||
502 | break; | ||
503 | |||
504 | default: | ||
505 | dev_err(wm8350->dev, | ||
506 | "WM835x configuration mode %d not supported\n", | ||
507 | mode); | ||
508 | return -EINVAL; | ||
509 | } | ||
510 | |||
511 | wm8350->reg_cache = | ||
512 | kmalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL); | ||
513 | if (wm8350->reg_cache == NULL) | ||
514 | return -ENOMEM; | ||
515 | |||
516 | /* Read the initial cache state back from the device - this is | ||
517 | * a PMIC so the device many not be in a virgin state and we | ||
518 | * can't rely on the silicon values. | ||
519 | */ | ||
520 | ret = regmap_raw_read(wm8350->regmap, 0, wm8350->reg_cache, | ||
521 | sizeof(u16) * (WM8350_MAX_REGISTER + 1)); | ||
522 | if (ret < 0) { | ||
523 | dev_err(wm8350->dev, | ||
524 | "failed to read initial cache values\n"); | ||
525 | goto out; | ||
526 | } | ||
527 | |||
528 | /* Mask out uncacheable/unreadable bits and the audio. */ | ||
529 | for (i = 0; i < WM8350_MAX_REGISTER; i++) { | ||
530 | if (wm8350_reg_io_map[i].readable && | ||
531 | (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) { | ||
532 | value = be16_to_cpu(wm8350->reg_cache[i]); | ||
533 | value &= wm8350_reg_io_map[i].readable; | ||
534 | wm8350->reg_cache[i] = value; | ||
535 | } else | ||
536 | wm8350->reg_cache[i] = reg_map[i]; | ||
537 | } | ||
538 | |||
539 | out: | ||
540 | kfree(wm8350->reg_cache); | ||
541 | return ret; | ||
542 | } | ||
543 | |||
544 | /* | ||
545 | * Register a client device. This is non-fatal since there is no need to | 252 | * Register a client device. This is non-fatal since there is no need to |
546 | * fail the entire device init due to a single platform device failing. | 253 | * fail the entire device init due to a single platform device failing. |
547 | */ | 254 | */ |
@@ -688,18 +395,12 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
688 | goto err; | 395 | goto err; |
689 | } | 396 | } |
690 | 397 | ||
691 | ret = wm8350_create_cache(wm8350, mask_rev, mode); | ||
692 | if (ret < 0) { | ||
693 | dev_err(wm8350->dev, "Failed to create register cache\n"); | ||
694 | return ret; | ||
695 | } | ||
696 | |||
697 | mutex_init(&wm8350->auxadc_mutex); | 398 | mutex_init(&wm8350->auxadc_mutex); |
698 | init_completion(&wm8350->auxadc_done); | 399 | init_completion(&wm8350->auxadc_done); |
699 | 400 | ||
700 | ret = wm8350_irq_init(wm8350, irq, pdata); | 401 | ret = wm8350_irq_init(wm8350, irq, pdata); |
701 | if (ret < 0) | 402 | if (ret < 0) |
702 | goto err_free; | 403 | goto err; |
703 | 404 | ||
704 | if (wm8350->irq_base) { | 405 | if (wm8350->irq_base) { |
705 | ret = request_threaded_irq(wm8350->irq_base + | 406 | ret = request_threaded_irq(wm8350->irq_base + |
@@ -737,8 +438,6 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
737 | 438 | ||
738 | err_irq: | 439 | err_irq: |
739 | wm8350_irq_exit(wm8350); | 440 | wm8350_irq_exit(wm8350); |
740 | err_free: | ||
741 | kfree(wm8350->reg_cache); | ||
742 | err: | 441 | err: |
743 | return ret; | 442 | return ret; |
744 | } | 443 | } |
@@ -765,8 +464,6 @@ void wm8350_device_exit(struct wm8350 *wm8350) | |||
765 | free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350); | 464 | free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350); |
766 | 465 | ||
767 | wm8350_irq_exit(wm8350); | 466 | wm8350_irq_exit(wm8350); |
768 | |||
769 | kfree(wm8350->reg_cache); | ||
770 | } | 467 | } |
771 | EXPORT_SYMBOL_GPL(wm8350_device_exit); | 468 | EXPORT_SYMBOL_GPL(wm8350_device_exit); |
772 | 469 | ||