1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Arizona core driver |
4 | * |
5 | * Copyright 2012 Wolfson Microelectronics plc |
6 | * |
7 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
8 | */ |
9 | |
10 | #include <linux/clk.h> |
11 | #include <linux/delay.h> |
12 | #include <linux/err.h> |
13 | #include <linux/gpio/consumer.h> |
14 | #include <linux/interrupt.h> |
15 | #include <linux/mfd/core.h> |
16 | #include <linux/module.h> |
17 | #include <linux/of.h> |
18 | #include <linux/pm_runtime.h> |
19 | #include <linux/regmap.h> |
20 | #include <linux/regulator/consumer.h> |
21 | #include <linux/regulator/machine.h> |
22 | #include <linux/slab.h> |
23 | #include <linux/ktime.h> |
24 | #include <linux/platform_device.h> |
25 | |
26 | #include <linux/mfd/arizona/core.h> |
27 | #include <linux/mfd/arizona/registers.h> |
28 | |
29 | #include "arizona.h" |
30 | |
31 | static const char * const wm5102_core_supplies[] = { |
32 | "AVDD" , |
33 | "DBVDD1" , |
34 | }; |
35 | |
36 | int arizona_clk32k_enable(struct arizona *arizona) |
37 | { |
38 | int ret = 0; |
39 | |
40 | mutex_lock(&arizona->clk_lock); |
41 | |
42 | arizona->clk32k_ref++; |
43 | |
44 | if (arizona->clk32k_ref == 1) { |
45 | switch (arizona->pdata.clk32k_src) { |
46 | case ARIZONA_32KZ_MCLK1: |
47 | ret = pm_runtime_resume_and_get(dev: arizona->dev); |
48 | if (ret != 0) |
49 | goto err_ref; |
50 | ret = clk_prepare_enable(clk: arizona->mclk[ARIZONA_MCLK1]); |
51 | if (ret != 0) { |
52 | pm_runtime_put_sync(dev: arizona->dev); |
53 | goto err_ref; |
54 | } |
55 | break; |
56 | case ARIZONA_32KZ_MCLK2: |
57 | ret = clk_prepare_enable(clk: arizona->mclk[ARIZONA_MCLK2]); |
58 | if (ret != 0) |
59 | goto err_ref; |
60 | break; |
61 | } |
62 | |
63 | ret = regmap_update_bits(map: arizona->regmap, ARIZONA_CLOCK_32K_1, |
64 | ARIZONA_CLK_32K_ENA, |
65 | ARIZONA_CLK_32K_ENA); |
66 | } |
67 | |
68 | err_ref: |
69 | if (ret != 0) |
70 | arizona->clk32k_ref--; |
71 | |
72 | mutex_unlock(lock: &arizona->clk_lock); |
73 | |
74 | return ret; |
75 | } |
76 | EXPORT_SYMBOL_GPL(arizona_clk32k_enable); |
77 | |
78 | int arizona_clk32k_disable(struct arizona *arizona) |
79 | { |
80 | mutex_lock(&arizona->clk_lock); |
81 | |
82 | WARN_ON(arizona->clk32k_ref <= 0); |
83 | |
84 | arizona->clk32k_ref--; |
85 | |
86 | if (arizona->clk32k_ref == 0) { |
87 | regmap_update_bits(map: arizona->regmap, ARIZONA_CLOCK_32K_1, |
88 | ARIZONA_CLK_32K_ENA, val: 0); |
89 | |
90 | switch (arizona->pdata.clk32k_src) { |
91 | case ARIZONA_32KZ_MCLK1: |
92 | pm_runtime_put_sync(dev: arizona->dev); |
93 | clk_disable_unprepare(clk: arizona->mclk[ARIZONA_MCLK1]); |
94 | break; |
95 | case ARIZONA_32KZ_MCLK2: |
96 | clk_disable_unprepare(clk: arizona->mclk[ARIZONA_MCLK2]); |
97 | break; |
98 | } |
99 | } |
100 | |
101 | mutex_unlock(lock: &arizona->clk_lock); |
102 | |
103 | return 0; |
104 | } |
105 | EXPORT_SYMBOL_GPL(arizona_clk32k_disable); |
106 | |
107 | static irqreturn_t arizona_clkgen_err(int irq, void *data) |
108 | { |
109 | struct arizona *arizona = data; |
110 | |
111 | dev_err(arizona->dev, "CLKGEN error\n" ); |
112 | |
113 | return IRQ_HANDLED; |
114 | } |
115 | |
116 | static irqreturn_t arizona_underclocked(int irq, void *data) |
117 | { |
118 | struct arizona *arizona = data; |
119 | unsigned int val; |
120 | int ret; |
121 | |
122 | ret = regmap_read(map: arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_8, |
123 | val: &val); |
124 | if (ret != 0) { |
125 | dev_err(arizona->dev, "Failed to read underclock status: %d\n" , |
126 | ret); |
127 | return IRQ_NONE; |
128 | } |
129 | |
130 | if (val & ARIZONA_AIF3_UNDERCLOCKED_STS) |
131 | dev_err(arizona->dev, "AIF3 underclocked\n" ); |
132 | if (val & ARIZONA_AIF2_UNDERCLOCKED_STS) |
133 | dev_err(arizona->dev, "AIF2 underclocked\n" ); |
134 | if (val & ARIZONA_AIF1_UNDERCLOCKED_STS) |
135 | dev_err(arizona->dev, "AIF1 underclocked\n" ); |
136 | if (val & ARIZONA_ISRC3_UNDERCLOCKED_STS) |
137 | dev_err(arizona->dev, "ISRC3 underclocked\n" ); |
138 | if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS) |
139 | dev_err(arizona->dev, "ISRC2 underclocked\n" ); |
140 | if (val & ARIZONA_ISRC1_UNDERCLOCKED_STS) |
141 | dev_err(arizona->dev, "ISRC1 underclocked\n" ); |
142 | if (val & ARIZONA_FX_UNDERCLOCKED_STS) |
143 | dev_err(arizona->dev, "FX underclocked\n" ); |
144 | if (val & ARIZONA_ASRC_UNDERCLOCKED_STS) |
145 | dev_err(arizona->dev, "ASRC underclocked\n" ); |
146 | if (val & ARIZONA_DAC_UNDERCLOCKED_STS) |
147 | dev_err(arizona->dev, "DAC underclocked\n" ); |
148 | if (val & ARIZONA_ADC_UNDERCLOCKED_STS) |
149 | dev_err(arizona->dev, "ADC underclocked\n" ); |
150 | if (val & ARIZONA_MIXER_UNDERCLOCKED_STS) |
151 | dev_err(arizona->dev, "Mixer dropped sample\n" ); |
152 | |
153 | return IRQ_HANDLED; |
154 | } |
155 | |
156 | static irqreturn_t arizona_overclocked(int irq, void *data) |
157 | { |
158 | struct arizona *arizona = data; |
159 | unsigned int val[3]; |
160 | int ret; |
161 | |
162 | ret = regmap_bulk_read(map: arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_6, |
163 | val: &val[0], val_count: 3); |
164 | if (ret != 0) { |
165 | dev_err(arizona->dev, "Failed to read overclock status: %d\n" , |
166 | ret); |
167 | return IRQ_NONE; |
168 | } |
169 | |
170 | switch (arizona->type) { |
171 | case WM8998: |
172 | case WM1814: |
173 | /* Some bits are shifted on WM8998, |
174 | * rearrange to match the standard bit layout |
175 | */ |
176 | val[0] = ((val[0] & 0x60e0) >> 1) | |
177 | ((val[0] & 0x1e00) >> 2) | |
178 | (val[0] & 0x000f); |
179 | break; |
180 | default: |
181 | break; |
182 | } |
183 | |
184 | if (val[0] & ARIZONA_PWM_OVERCLOCKED_STS) |
185 | dev_err(arizona->dev, "PWM overclocked\n" ); |
186 | if (val[0] & ARIZONA_FX_CORE_OVERCLOCKED_STS) |
187 | dev_err(arizona->dev, "FX core overclocked\n" ); |
188 | if (val[0] & ARIZONA_DAC_SYS_OVERCLOCKED_STS) |
189 | dev_err(arizona->dev, "DAC SYS overclocked\n" ); |
190 | if (val[0] & ARIZONA_DAC_WARP_OVERCLOCKED_STS) |
191 | dev_err(arizona->dev, "DAC WARP overclocked\n" ); |
192 | if (val[0] & ARIZONA_ADC_OVERCLOCKED_STS) |
193 | dev_err(arizona->dev, "ADC overclocked\n" ); |
194 | if (val[0] & ARIZONA_MIXER_OVERCLOCKED_STS) |
195 | dev_err(arizona->dev, "Mixer overclocked\n" ); |
196 | if (val[0] & ARIZONA_AIF3_SYNC_OVERCLOCKED_STS) |
197 | dev_err(arizona->dev, "AIF3 overclocked\n" ); |
198 | if (val[0] & ARIZONA_AIF2_SYNC_OVERCLOCKED_STS) |
199 | dev_err(arizona->dev, "AIF2 overclocked\n" ); |
200 | if (val[0] & ARIZONA_AIF1_SYNC_OVERCLOCKED_STS) |
201 | dev_err(arizona->dev, "AIF1 overclocked\n" ); |
202 | if (val[0] & ARIZONA_PAD_CTRL_OVERCLOCKED_STS) |
203 | dev_err(arizona->dev, "Pad control overclocked\n" ); |
204 | |
205 | if (val[1] & ARIZONA_SLIMBUS_SUBSYS_OVERCLOCKED_STS) |
206 | dev_err(arizona->dev, "Slimbus subsystem overclocked\n" ); |
207 | if (val[1] & ARIZONA_SLIMBUS_ASYNC_OVERCLOCKED_STS) |
208 | dev_err(arizona->dev, "Slimbus async overclocked\n" ); |
209 | if (val[1] & ARIZONA_SLIMBUS_SYNC_OVERCLOCKED_STS) |
210 | dev_err(arizona->dev, "Slimbus sync overclocked\n" ); |
211 | if (val[1] & ARIZONA_ASRC_ASYNC_SYS_OVERCLOCKED_STS) |
212 | dev_err(arizona->dev, "ASRC async system overclocked\n" ); |
213 | if (val[1] & ARIZONA_ASRC_ASYNC_WARP_OVERCLOCKED_STS) |
214 | dev_err(arizona->dev, "ASRC async WARP overclocked\n" ); |
215 | if (val[1] & ARIZONA_ASRC_SYNC_SYS_OVERCLOCKED_STS) |
216 | dev_err(arizona->dev, "ASRC sync system overclocked\n" ); |
217 | if (val[1] & ARIZONA_ASRC_SYNC_WARP_OVERCLOCKED_STS) |
218 | dev_err(arizona->dev, "ASRC sync WARP overclocked\n" ); |
219 | if (val[1] & ARIZONA_ADSP2_1_OVERCLOCKED_STS) |
220 | dev_err(arizona->dev, "DSP1 overclocked\n" ); |
221 | if (val[1] & ARIZONA_ISRC3_OVERCLOCKED_STS) |
222 | dev_err(arizona->dev, "ISRC3 overclocked\n" ); |
223 | if (val[1] & ARIZONA_ISRC2_OVERCLOCKED_STS) |
224 | dev_err(arizona->dev, "ISRC2 overclocked\n" ); |
225 | if (val[1] & ARIZONA_ISRC1_OVERCLOCKED_STS) |
226 | dev_err(arizona->dev, "ISRC1 overclocked\n" ); |
227 | |
228 | if (val[2] & ARIZONA_SPDIF_OVERCLOCKED_STS) |
229 | dev_err(arizona->dev, "SPDIF overclocked\n" ); |
230 | |
231 | return IRQ_HANDLED; |
232 | } |
233 | |
234 | #define ARIZONA_REG_POLL_DELAY_US 7500 |
235 | |
236 | static inline bool arizona_poll_reg_delay(ktime_t timeout) |
237 | { |
238 | if (ktime_compare(cmp1: ktime_get(), cmp2: timeout) > 0) |
239 | return false; |
240 | |
241 | usleep_range(ARIZONA_REG_POLL_DELAY_US / 2, ARIZONA_REG_POLL_DELAY_US); |
242 | |
243 | return true; |
244 | } |
245 | |
246 | static int arizona_poll_reg(struct arizona *arizona, |
247 | int timeout_ms, unsigned int reg, |
248 | unsigned int mask, unsigned int target) |
249 | { |
250 | ktime_t timeout = ktime_add_us(kt: ktime_get(), usec: timeout_ms * USEC_PER_MSEC); |
251 | unsigned int val = 0; |
252 | int ret; |
253 | |
254 | do { |
255 | ret = regmap_read(map: arizona->regmap, reg, val: &val); |
256 | |
257 | if ((val & mask) == target) |
258 | return 0; |
259 | } while (arizona_poll_reg_delay(timeout)); |
260 | |
261 | if (ret) { |
262 | dev_err(arizona->dev, "Failed polling reg 0x%x: %d\n" , |
263 | reg, ret); |
264 | return ret; |
265 | } |
266 | |
267 | dev_err(arizona->dev, "Polling reg 0x%x timed out: %x\n" , reg, val); |
268 | return -ETIMEDOUT; |
269 | } |
270 | |
271 | static int arizona_wait_for_boot(struct arizona *arizona) |
272 | { |
273 | int ret; |
274 | |
275 | /* |
276 | * We can't use an interrupt as we need to runtime resume to do so, |
277 | * we won't race with the interrupt handler as it'll be blocked on |
278 | * runtime resume. |
279 | */ |
280 | ret = arizona_poll_reg(arizona, timeout_ms: 30, ARIZONA_INTERRUPT_RAW_STATUS_5, |
281 | ARIZONA_BOOT_DONE_STS, ARIZONA_BOOT_DONE_STS); |
282 | |
283 | if (!ret) |
284 | regmap_write(map: arizona->regmap, ARIZONA_INTERRUPT_STATUS_5, |
285 | ARIZONA_BOOT_DONE_STS); |
286 | |
287 | pm_runtime_mark_last_busy(dev: arizona->dev); |
288 | |
289 | return ret; |
290 | } |
291 | |
292 | static inline void arizona_enable_reset(struct arizona *arizona) |
293 | { |
294 | if (arizona->pdata.reset) |
295 | gpiod_set_raw_value_cansleep(desc: arizona->pdata.reset, value: 0); |
296 | } |
297 | |
298 | static void arizona_disable_reset(struct arizona *arizona) |
299 | { |
300 | if (arizona->pdata.reset) { |
301 | switch (arizona->type) { |
302 | case WM5110: |
303 | case WM8280: |
304 | /* Meet requirements for minimum reset duration */ |
305 | usleep_range(min: 5000, max: 10000); |
306 | break; |
307 | default: |
308 | break; |
309 | } |
310 | |
311 | gpiod_set_raw_value_cansleep(desc: arizona->pdata.reset, value: 1); |
312 | usleep_range(min: 1000, max: 5000); |
313 | } |
314 | } |
315 | |
316 | struct arizona_sysclk_state { |
317 | unsigned int fll; |
318 | unsigned int sysclk; |
319 | }; |
320 | |
321 | static int arizona_enable_freerun_sysclk(struct arizona *arizona, |
322 | struct arizona_sysclk_state *state) |
323 | { |
324 | int ret, err; |
325 | |
326 | /* Cache existing FLL and SYSCLK settings */ |
327 | ret = regmap_read(map: arizona->regmap, ARIZONA_FLL1_CONTROL_1, val: &state->fll); |
328 | if (ret) { |
329 | dev_err(arizona->dev, "Failed to cache FLL settings: %d\n" , |
330 | ret); |
331 | return ret; |
332 | } |
333 | ret = regmap_read(map: arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, |
334 | val: &state->sysclk); |
335 | if (ret) { |
336 | dev_err(arizona->dev, "Failed to cache SYSCLK settings: %d\n" , |
337 | ret); |
338 | return ret; |
339 | } |
340 | |
341 | /* Start up SYSCLK using the FLL in free running mode */ |
342 | ret = regmap_write(map: arizona->regmap, ARIZONA_FLL1_CONTROL_1, |
343 | ARIZONA_FLL1_ENA | ARIZONA_FLL1_FREERUN); |
344 | if (ret) { |
345 | dev_err(arizona->dev, |
346 | "Failed to start FLL in freerunning mode: %d\n" , |
347 | ret); |
348 | return ret; |
349 | } |
350 | ret = arizona_poll_reg(arizona, timeout_ms: 180, ARIZONA_INTERRUPT_RAW_STATUS_5, |
351 | ARIZONA_FLL1_CLOCK_OK_STS, |
352 | ARIZONA_FLL1_CLOCK_OK_STS); |
353 | if (ret) |
354 | goto err_fll; |
355 | |
356 | ret = regmap_write(map: arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, val: 0x0144); |
357 | if (ret) { |
358 | dev_err(arizona->dev, "Failed to start SYSCLK: %d\n" , ret); |
359 | goto err_fll; |
360 | } |
361 | |
362 | return 0; |
363 | |
364 | err_fll: |
365 | err = regmap_write(map: arizona->regmap, ARIZONA_FLL1_CONTROL_1, val: state->fll); |
366 | if (err) |
367 | dev_err(arizona->dev, |
368 | "Failed to re-apply old FLL settings: %d\n" , err); |
369 | |
370 | return ret; |
371 | } |
372 | |
373 | static int arizona_disable_freerun_sysclk(struct arizona *arizona, |
374 | struct arizona_sysclk_state *state) |
375 | { |
376 | int ret; |
377 | |
378 | ret = regmap_write(map: arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, |
379 | val: state->sysclk); |
380 | if (ret) { |
381 | dev_err(arizona->dev, |
382 | "Failed to re-apply old SYSCLK settings: %d\n" , ret); |
383 | return ret; |
384 | } |
385 | |
386 | ret = regmap_write(map: arizona->regmap, ARIZONA_FLL1_CONTROL_1, val: state->fll); |
387 | if (ret) { |
388 | dev_err(arizona->dev, |
389 | "Failed to re-apply old FLL settings: %d\n" , ret); |
390 | return ret; |
391 | } |
392 | |
393 | return 0; |
394 | } |
395 | |
396 | static int wm5102_apply_hardware_patch(struct arizona *arizona) |
397 | { |
398 | struct arizona_sysclk_state state; |
399 | int err, ret; |
400 | |
401 | ret = arizona_enable_freerun_sysclk(arizona, state: &state); |
402 | if (ret) |
403 | return ret; |
404 | |
405 | /* Start the write sequencer and wait for it to finish */ |
406 | ret = regmap_write(map: arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0, |
407 | ARIZONA_WSEQ_ENA | ARIZONA_WSEQ_START | 160); |
408 | if (ret) { |
409 | dev_err(arizona->dev, "Failed to start write sequencer: %d\n" , |
410 | ret); |
411 | goto err; |
412 | } |
413 | |
414 | ret = arizona_poll_reg(arizona, timeout_ms: 30, ARIZONA_WRITE_SEQUENCER_CTRL_1, |
415 | ARIZONA_WSEQ_BUSY, target: 0); |
416 | if (ret) |
417 | regmap_write(map: arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0, |
418 | ARIZONA_WSEQ_ABORT); |
419 | |
420 | err: |
421 | err = arizona_disable_freerun_sysclk(arizona, state: &state); |
422 | |
423 | return ret ?: err; |
424 | } |
425 | |
426 | /* |
427 | * Register patch to some of the CODECs internal write sequences |
428 | * to ensure a clean exit from the low power sleep state. |
429 | */ |
430 | static const struct reg_sequence wm5110_sleep_patch[] = { |
431 | { 0x337A, 0xC100 }, |
432 | { 0x337B, 0x0041 }, |
433 | { 0x3300, 0xA210 }, |
434 | { 0x3301, 0x050C }, |
435 | }; |
436 | |
437 | static int wm5110_apply_sleep_patch(struct arizona *arizona) |
438 | { |
439 | struct arizona_sysclk_state state; |
440 | int err, ret; |
441 | |
442 | ret = arizona_enable_freerun_sysclk(arizona, state: &state); |
443 | if (ret) |
444 | return ret; |
445 | |
446 | ret = regmap_multi_reg_write_bypassed(map: arizona->regmap, |
447 | regs: wm5110_sleep_patch, |
448 | ARRAY_SIZE(wm5110_sleep_patch)); |
449 | |
450 | err = arizona_disable_freerun_sysclk(arizona, state: &state); |
451 | |
452 | return ret ?: err; |
453 | } |
454 | |
455 | static int wm5102_clear_write_sequencer(struct arizona *arizona) |
456 | { |
457 | int ret; |
458 | |
459 | ret = regmap_write(map: arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_3, |
460 | val: 0x0); |
461 | if (ret) { |
462 | dev_err(arizona->dev, |
463 | "Failed to clear write sequencer state: %d\n" , ret); |
464 | return ret; |
465 | } |
466 | |
467 | arizona_enable_reset(arizona); |
468 | regulator_disable(regulator: arizona->dcvdd); |
469 | |
470 | msleep(msecs: 20); |
471 | |
472 | ret = regulator_enable(regulator: arizona->dcvdd); |
473 | if (ret) { |
474 | dev_err(arizona->dev, "Failed to re-enable DCVDD: %d\n" , ret); |
475 | return ret; |
476 | } |
477 | arizona_disable_reset(arizona); |
478 | |
479 | return 0; |
480 | } |
481 | |
482 | static int arizona_isolate_dcvdd(struct arizona *arizona) |
483 | { |
484 | int ret; |
485 | |
486 | ret = regmap_update_bits(map: arizona->regmap, |
487 | ARIZONA_ISOLATION_CONTROL, |
488 | ARIZONA_ISOLATE_DCVDD1, |
489 | ARIZONA_ISOLATE_DCVDD1); |
490 | if (ret != 0) |
491 | dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n" , ret); |
492 | |
493 | return ret; |
494 | } |
495 | |
496 | static int arizona_connect_dcvdd(struct arizona *arizona) |
497 | { |
498 | int ret; |
499 | |
500 | ret = regmap_update_bits(map: arizona->regmap, |
501 | ARIZONA_ISOLATION_CONTROL, |
502 | ARIZONA_ISOLATE_DCVDD1, val: 0); |
503 | if (ret != 0) |
504 | dev_err(arizona->dev, "Failed to connect DCVDD: %d\n" , ret); |
505 | |
506 | return ret; |
507 | } |
508 | |
509 | static int arizona_is_jack_det_active(struct arizona *arizona) |
510 | { |
511 | unsigned int val; |
512 | int ret; |
513 | |
514 | ret = regmap_read(map: arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, val: &val); |
515 | if (ret) { |
516 | dev_err(arizona->dev, |
517 | "Failed to check jack det status: %d\n" , ret); |
518 | return ret; |
519 | } else if (val & ARIZONA_JD1_ENA) { |
520 | return 1; |
521 | } else { |
522 | return 0; |
523 | } |
524 | } |
525 | |
526 | static int arizona_runtime_resume(struct device *dev) |
527 | { |
528 | struct arizona *arizona = dev_get_drvdata(dev); |
529 | int ret; |
530 | |
531 | dev_dbg(arizona->dev, "Leaving AoD mode\n" ); |
532 | |
533 | if (arizona->has_fully_powered_off) { |
534 | dev_dbg(arizona->dev, "Re-enabling core supplies\n" ); |
535 | |
536 | ret = regulator_bulk_enable(num_consumers: arizona->num_core_supplies, |
537 | consumers: arizona->core_supplies); |
538 | if (ret) { |
539 | dev_err(dev, "Failed to enable core supplies: %d\n" , |
540 | ret); |
541 | return ret; |
542 | } |
543 | } |
544 | |
545 | ret = regulator_enable(regulator: arizona->dcvdd); |
546 | if (ret != 0) { |
547 | dev_err(arizona->dev, "Failed to enable DCVDD: %d\n" , ret); |
548 | if (arizona->has_fully_powered_off) |
549 | regulator_bulk_disable(num_consumers: arizona->num_core_supplies, |
550 | consumers: arizona->core_supplies); |
551 | return ret; |
552 | } |
553 | |
554 | if (arizona->has_fully_powered_off) { |
555 | arizona_disable_reset(arizona); |
556 | enable_irq(irq: arizona->irq); |
557 | arizona->has_fully_powered_off = false; |
558 | } |
559 | |
560 | regcache_cache_only(map: arizona->regmap, enable: false); |
561 | |
562 | switch (arizona->type) { |
563 | case WM5102: |
564 | if (arizona->external_dcvdd) { |
565 | ret = arizona_connect_dcvdd(arizona); |
566 | if (ret != 0) |
567 | goto err; |
568 | } |
569 | |
570 | ret = wm5102_patch(arizona); |
571 | if (ret != 0) { |
572 | dev_err(arizona->dev, "Failed to apply patch: %d\n" , |
573 | ret); |
574 | goto err; |
575 | } |
576 | |
577 | ret = wm5102_apply_hardware_patch(arizona); |
578 | if (ret) { |
579 | dev_err(arizona->dev, |
580 | "Failed to apply hardware patch: %d\n" , |
581 | ret); |
582 | goto err; |
583 | } |
584 | break; |
585 | case WM5110: |
586 | case WM8280: |
587 | ret = arizona_wait_for_boot(arizona); |
588 | if (ret) |
589 | goto err; |
590 | |
591 | if (arizona->external_dcvdd) { |
592 | ret = arizona_connect_dcvdd(arizona); |
593 | if (ret != 0) |
594 | goto err; |
595 | } else { |
596 | /* |
597 | * As this is only called for the internal regulator |
598 | * (where we know voltage ranges available) it is ok |
599 | * to request an exact range. |
600 | */ |
601 | ret = regulator_set_voltage(regulator: arizona->dcvdd, |
602 | min_uV: 1200000, max_uV: 1200000); |
603 | if (ret < 0) { |
604 | dev_err(arizona->dev, |
605 | "Failed to set resume voltage: %d\n" , |
606 | ret); |
607 | goto err; |
608 | } |
609 | } |
610 | |
611 | ret = wm5110_apply_sleep_patch(arizona); |
612 | if (ret) { |
613 | dev_err(arizona->dev, |
614 | "Failed to re-apply sleep patch: %d\n" , |
615 | ret); |
616 | goto err; |
617 | } |
618 | break; |
619 | case WM1831: |
620 | case CS47L24: |
621 | ret = arizona_wait_for_boot(arizona); |
622 | if (ret != 0) |
623 | goto err; |
624 | break; |
625 | default: |
626 | ret = arizona_wait_for_boot(arizona); |
627 | if (ret != 0) |
628 | goto err; |
629 | |
630 | if (arizona->external_dcvdd) { |
631 | ret = arizona_connect_dcvdd(arizona); |
632 | if (ret != 0) |
633 | goto err; |
634 | } |
635 | break; |
636 | } |
637 | |
638 | ret = regcache_sync(map: arizona->regmap); |
639 | if (ret != 0) { |
640 | dev_err(arizona->dev, "Failed to restore register cache\n" ); |
641 | goto err; |
642 | } |
643 | |
644 | return 0; |
645 | |
646 | err: |
647 | regcache_cache_only(map: arizona->regmap, enable: true); |
648 | regulator_disable(regulator: arizona->dcvdd); |
649 | return ret; |
650 | } |
651 | |
652 | static int arizona_runtime_suspend(struct device *dev) |
653 | { |
654 | struct arizona *arizona = dev_get_drvdata(dev); |
655 | int jd_active = 0; |
656 | int ret; |
657 | |
658 | dev_dbg(arizona->dev, "Entering AoD mode\n" ); |
659 | |
660 | switch (arizona->type) { |
661 | case WM5110: |
662 | case WM8280: |
663 | jd_active = arizona_is_jack_det_active(arizona); |
664 | if (jd_active < 0) |
665 | return jd_active; |
666 | |
667 | if (arizona->external_dcvdd) { |
668 | ret = arizona_isolate_dcvdd(arizona); |
669 | if (ret != 0) |
670 | return ret; |
671 | } else { |
672 | /* |
673 | * As this is only called for the internal regulator |
674 | * (where we know voltage ranges available) it is ok |
675 | * to request an exact range. |
676 | */ |
677 | ret = regulator_set_voltage(regulator: arizona->dcvdd, |
678 | min_uV: 1175000, max_uV: 1175000); |
679 | if (ret < 0) { |
680 | dev_err(arizona->dev, |
681 | "Failed to set suspend voltage: %d\n" , |
682 | ret); |
683 | return ret; |
684 | } |
685 | } |
686 | break; |
687 | case WM5102: |
688 | jd_active = arizona_is_jack_det_active(arizona); |
689 | if (jd_active < 0) |
690 | return jd_active; |
691 | |
692 | if (arizona->external_dcvdd) { |
693 | ret = arizona_isolate_dcvdd(arizona); |
694 | if (ret != 0) |
695 | return ret; |
696 | } |
697 | |
698 | if (!jd_active) { |
699 | ret = regmap_write(map: arizona->regmap, |
700 | ARIZONA_WRITE_SEQUENCER_CTRL_3, val: 0x0); |
701 | if (ret) { |
702 | dev_err(arizona->dev, |
703 | "Failed to clear write sequencer: %d\n" , |
704 | ret); |
705 | return ret; |
706 | } |
707 | } |
708 | break; |
709 | case WM1831: |
710 | case CS47L24: |
711 | break; |
712 | default: |
713 | jd_active = arizona_is_jack_det_active(arizona); |
714 | if (jd_active < 0) |
715 | return jd_active; |
716 | |
717 | if (arizona->external_dcvdd) { |
718 | ret = arizona_isolate_dcvdd(arizona); |
719 | if (ret != 0) |
720 | return ret; |
721 | } |
722 | break; |
723 | } |
724 | |
725 | regcache_cache_only(map: arizona->regmap, enable: true); |
726 | regcache_mark_dirty(map: arizona->regmap); |
727 | regulator_disable(regulator: arizona->dcvdd); |
728 | |
729 | /* Allow us to completely power down if no jack detection */ |
730 | if (!jd_active) { |
731 | dev_dbg(arizona->dev, "Fully powering off\n" ); |
732 | |
733 | arizona->has_fully_powered_off = true; |
734 | |
735 | disable_irq_nosync(irq: arizona->irq); |
736 | arizona_enable_reset(arizona); |
737 | regulator_bulk_disable(num_consumers: arizona->num_core_supplies, |
738 | consumers: arizona->core_supplies); |
739 | } |
740 | |
741 | return 0; |
742 | } |
743 | |
744 | static int arizona_suspend(struct device *dev) |
745 | { |
746 | struct arizona *arizona = dev_get_drvdata(dev); |
747 | |
748 | dev_dbg(arizona->dev, "Suspend, disabling IRQ\n" ); |
749 | disable_irq(irq: arizona->irq); |
750 | |
751 | return 0; |
752 | } |
753 | |
754 | static int arizona_suspend_noirq(struct device *dev) |
755 | { |
756 | struct arizona *arizona = dev_get_drvdata(dev); |
757 | |
758 | dev_dbg(arizona->dev, "Late suspend, reenabling IRQ\n" ); |
759 | enable_irq(irq: arizona->irq); |
760 | |
761 | return 0; |
762 | } |
763 | |
764 | static int arizona_resume_noirq(struct device *dev) |
765 | { |
766 | struct arizona *arizona = dev_get_drvdata(dev); |
767 | |
768 | dev_dbg(arizona->dev, "Early resume, disabling IRQ\n" ); |
769 | disable_irq(irq: arizona->irq); |
770 | |
771 | return 0; |
772 | } |
773 | |
774 | static int arizona_resume(struct device *dev) |
775 | { |
776 | struct arizona *arizona = dev_get_drvdata(dev); |
777 | |
778 | dev_dbg(arizona->dev, "Resume, reenabling IRQ\n" ); |
779 | enable_irq(irq: arizona->irq); |
780 | |
781 | return 0; |
782 | } |
783 | |
784 | EXPORT_GPL_DEV_PM_OPS(arizona_pm_ops) = { |
785 | RUNTIME_PM_OPS(arizona_runtime_suspend, |
786 | arizona_runtime_resume, |
787 | NULL) |
788 | SYSTEM_SLEEP_PM_OPS(arizona_suspend, arizona_resume) |
789 | NOIRQ_SYSTEM_SLEEP_PM_OPS(arizona_suspend_noirq, |
790 | arizona_resume_noirq) |
791 | }; |
792 | |
793 | #ifdef CONFIG_OF |
794 | static int arizona_of_get_core_pdata(struct arizona *arizona) |
795 | { |
796 | struct arizona_pdata *pdata = &arizona->pdata; |
797 | int ret, i; |
798 | |
799 | /* Handle old non-standard DT binding */ |
800 | pdata->reset = devm_gpiod_get(dev: arizona->dev, con_id: "wlf,reset" , flags: GPIOD_OUT_LOW); |
801 | if (IS_ERR(ptr: pdata->reset)) { |
802 | ret = PTR_ERR(ptr: pdata->reset); |
803 | |
804 | /* |
805 | * Reset missing will be caught when other binding is read |
806 | * but all other errors imply this binding is in use but has |
807 | * encountered a problem so should be handled. |
808 | */ |
809 | if (ret == -EPROBE_DEFER) |
810 | return ret; |
811 | else if (ret != -ENOENT && ret != -ENOSYS) |
812 | dev_err(arizona->dev, "Reset GPIO malformed: %d\n" , |
813 | ret); |
814 | |
815 | pdata->reset = NULL; |
816 | } |
817 | |
818 | ret = of_property_read_u32_array(np: arizona->dev->of_node, |
819 | propname: "wlf,gpio-defaults" , |
820 | out_values: pdata->gpio_defaults, |
821 | ARRAY_SIZE(pdata->gpio_defaults)); |
822 | if (ret >= 0) { |
823 | /* |
824 | * All values are literal except out of range values |
825 | * which are chip default, translate into platform |
826 | * data which uses 0 as chip default and out of range |
827 | * as zero. |
828 | */ |
829 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) { |
830 | if (pdata->gpio_defaults[i] > 0xffff) |
831 | pdata->gpio_defaults[i] = 0; |
832 | else if (pdata->gpio_defaults[i] == 0) |
833 | pdata->gpio_defaults[i] = 0x10000; |
834 | } |
835 | } else { |
836 | dev_err(arizona->dev, "Failed to parse GPIO defaults: %d\n" , |
837 | ret); |
838 | } |
839 | |
840 | return 0; |
841 | } |
842 | #else |
843 | static inline int arizona_of_get_core_pdata(struct arizona *arizona) |
844 | { |
845 | return 0; |
846 | } |
847 | #endif |
848 | |
849 | static const struct mfd_cell early_devs[] = { |
850 | { .name = "arizona-ldo1" }, |
851 | }; |
852 | |
853 | static const char * const wm5102_supplies[] = { |
854 | "MICVDD" , |
855 | "DBVDD2" , |
856 | "DBVDD3" , |
857 | "CPVDD" , |
858 | "SPKVDDL" , |
859 | "SPKVDDR" , |
860 | }; |
861 | |
862 | static const struct mfd_cell wm5102_devs[] = { |
863 | { .name = "arizona-micsupp" }, |
864 | { .name = "arizona-gpio" }, |
865 | { .name = "arizona-haptics" }, |
866 | { .name = "arizona-pwm" }, |
867 | { |
868 | .name = "wm5102-codec" , |
869 | .parent_supplies = wm5102_supplies, |
870 | .num_parent_supplies = ARRAY_SIZE(wm5102_supplies), |
871 | }, |
872 | }; |
873 | |
874 | static const struct mfd_cell wm5110_devs[] = { |
875 | { .name = "arizona-micsupp" }, |
876 | { .name = "arizona-gpio" }, |
877 | { .name = "arizona-haptics" }, |
878 | { .name = "arizona-pwm" }, |
879 | { |
880 | .name = "wm5110-codec" , |
881 | .parent_supplies = wm5102_supplies, |
882 | .num_parent_supplies = ARRAY_SIZE(wm5102_supplies), |
883 | }, |
884 | }; |
885 | |
886 | static const char * const cs47l24_supplies[] = { |
887 | "MICVDD" , |
888 | "CPVDD" , |
889 | "SPKVDD" , |
890 | }; |
891 | |
892 | static const struct mfd_cell cs47l24_devs[] = { |
893 | { .name = "arizona-gpio" }, |
894 | { .name = "arizona-haptics" }, |
895 | { .name = "arizona-pwm" }, |
896 | { |
897 | .name = "cs47l24-codec" , |
898 | .parent_supplies = cs47l24_supplies, |
899 | .num_parent_supplies = ARRAY_SIZE(cs47l24_supplies), |
900 | }, |
901 | }; |
902 | |
903 | static const char * const wm8997_supplies[] = { |
904 | "MICVDD" , |
905 | "DBVDD2" , |
906 | "CPVDD" , |
907 | "SPKVDD" , |
908 | }; |
909 | |
910 | static const struct mfd_cell wm8997_devs[] = { |
911 | { .name = "arizona-micsupp" }, |
912 | { .name = "arizona-gpio" }, |
913 | { .name = "arizona-haptics" }, |
914 | { .name = "arizona-pwm" }, |
915 | { |
916 | .name = "wm8997-codec" , |
917 | .parent_supplies = wm8997_supplies, |
918 | .num_parent_supplies = ARRAY_SIZE(wm8997_supplies), |
919 | }, |
920 | }; |
921 | |
922 | static const struct mfd_cell wm8998_devs[] = { |
923 | { .name = "arizona-micsupp" }, |
924 | { .name = "arizona-gpio" }, |
925 | { .name = "arizona-haptics" }, |
926 | { .name = "arizona-pwm" }, |
927 | { |
928 | .name = "wm8998-codec" , |
929 | .parent_supplies = wm5102_supplies, |
930 | .num_parent_supplies = ARRAY_SIZE(wm5102_supplies), |
931 | }, |
932 | }; |
933 | |
934 | int arizona_dev_init(struct arizona *arizona) |
935 | { |
936 | static const char * const mclk_name[] = { "mclk1" , "mclk2" }; |
937 | struct device *dev = arizona->dev; |
938 | const char *type_name = NULL; |
939 | unsigned int reg, val; |
940 | int (*apply_patch)(struct arizona *) = NULL; |
941 | const struct mfd_cell *subdevs = NULL; |
942 | int n_subdevs = 0, ret, i; |
943 | |
944 | dev_set_drvdata(dev: arizona->dev, data: arizona); |
945 | mutex_init(&arizona->clk_lock); |
946 | |
947 | if (dev_get_platdata(dev: arizona->dev)) { |
948 | memcpy(&arizona->pdata, dev_get_platdata(arizona->dev), |
949 | sizeof(arizona->pdata)); |
950 | } else { |
951 | ret = arizona_of_get_core_pdata(arizona); |
952 | if (ret < 0) |
953 | return ret; |
954 | } |
955 | |
956 | BUILD_BUG_ON(ARRAY_SIZE(arizona->mclk) != ARRAY_SIZE(mclk_name)); |
957 | for (i = 0; i < ARRAY_SIZE(arizona->mclk); i++) { |
958 | arizona->mclk[i] = devm_clk_get(dev: arizona->dev, id: mclk_name[i]); |
959 | if (IS_ERR(ptr: arizona->mclk[i])) { |
960 | dev_info(arizona->dev, "Failed to get %s: %ld\n" , |
961 | mclk_name[i], PTR_ERR(arizona->mclk[i])); |
962 | arizona->mclk[i] = NULL; |
963 | } |
964 | } |
965 | |
966 | regcache_cache_only(map: arizona->regmap, enable: true); |
967 | |
968 | switch (arizona->type) { |
969 | case WM5102: |
970 | case WM5110: |
971 | case WM8280: |
972 | case WM8997: |
973 | case WM8998: |
974 | case WM1814: |
975 | case WM1831: |
976 | case CS47L24: |
977 | for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++) |
978 | arizona->core_supplies[i].supply |
979 | = wm5102_core_supplies[i]; |
980 | arizona->num_core_supplies = ARRAY_SIZE(wm5102_core_supplies); |
981 | break; |
982 | default: |
983 | dev_err(arizona->dev, "Unknown device type %d\n" , |
984 | arizona->type); |
985 | return -ENODEV; |
986 | } |
987 | |
988 | /* Mark DCVDD as external, LDO1 driver will clear if internal */ |
989 | arizona->external_dcvdd = true; |
990 | |
991 | switch (arizona->type) { |
992 | case WM1831: |
993 | case CS47L24: |
994 | break; /* No LDO1 regulator */ |
995 | default: |
996 | ret = mfd_add_devices(parent: arizona->dev, id: -1, cells: early_devs, |
997 | ARRAY_SIZE(early_devs), NULL, irq_base: 0, NULL); |
998 | if (ret != 0) { |
999 | dev_err(dev, "Failed to add early children: %d\n" , ret); |
1000 | return ret; |
1001 | } |
1002 | break; |
1003 | } |
1004 | |
1005 | ret = devm_regulator_bulk_get(dev, num_consumers: arizona->num_core_supplies, |
1006 | consumers: arizona->core_supplies); |
1007 | if (ret != 0) { |
1008 | dev_err(dev, "Failed to request core supplies: %d\n" , |
1009 | ret); |
1010 | goto err_early; |
1011 | } |
1012 | |
1013 | /** |
1014 | * Don't use devres here because the only device we have to get |
1015 | * against is the MFD device and DCVDD will likely be supplied by |
1016 | * one of its children. Meaning that the regulator will be |
1017 | * destroyed by the time devres calls regulator put. |
1018 | */ |
1019 | arizona->dcvdd = regulator_get(dev: arizona->dev, id: "DCVDD" ); |
1020 | if (IS_ERR(ptr: arizona->dcvdd)) { |
1021 | ret = PTR_ERR(ptr: arizona->dcvdd); |
1022 | dev_err(dev, "Failed to request DCVDD: %d\n" , ret); |
1023 | goto err_early; |
1024 | } |
1025 | |
1026 | if (!arizona->pdata.reset) { |
1027 | /* Start out with /RESET low to put the chip into reset */ |
1028 | arizona->pdata.reset = devm_gpiod_get(dev: arizona->dev, con_id: "reset" , |
1029 | flags: GPIOD_OUT_LOW); |
1030 | if (IS_ERR(ptr: arizona->pdata.reset)) { |
1031 | ret = PTR_ERR(ptr: arizona->pdata.reset); |
1032 | if (ret == -EPROBE_DEFER) |
1033 | goto err_dcvdd; |
1034 | |
1035 | dev_err(arizona->dev, |
1036 | "Reset GPIO missing/malformed: %d\n" , ret); |
1037 | |
1038 | arizona->pdata.reset = NULL; |
1039 | } |
1040 | } |
1041 | |
1042 | ret = regulator_bulk_enable(num_consumers: arizona->num_core_supplies, |
1043 | consumers: arizona->core_supplies); |
1044 | if (ret != 0) { |
1045 | dev_err(dev, "Failed to enable core supplies: %d\n" , |
1046 | ret); |
1047 | goto err_dcvdd; |
1048 | } |
1049 | |
1050 | ret = regulator_enable(regulator: arizona->dcvdd); |
1051 | if (ret != 0) { |
1052 | dev_err(dev, "Failed to enable DCVDD: %d\n" , ret); |
1053 | goto err_enable; |
1054 | } |
1055 | |
1056 | arizona_disable_reset(arizona); |
1057 | |
1058 | regcache_cache_only(map: arizona->regmap, enable: false); |
1059 | |
1060 | /* Verify that this is a chip we know about */ |
1061 | ret = regmap_read(map: arizona->regmap, ARIZONA_SOFTWARE_RESET, val: ®); |
1062 | if (ret != 0) { |
1063 | dev_err(dev, "Failed to read ID register: %d\n" , ret); |
1064 | goto err_reset; |
1065 | } |
1066 | |
1067 | switch (reg) { |
1068 | case 0x5102: |
1069 | case 0x5110: |
1070 | case 0x6349: |
1071 | case 0x6363: |
1072 | case 0x8997: |
1073 | break; |
1074 | default: |
1075 | dev_err(arizona->dev, "Unknown device ID: %x\n" , reg); |
1076 | ret = -ENODEV; |
1077 | goto err_reset; |
1078 | } |
1079 | |
1080 | /* If we have a /RESET GPIO we'll already be reset */ |
1081 | if (!arizona->pdata.reset) { |
1082 | ret = regmap_write(map: arizona->regmap, ARIZONA_SOFTWARE_RESET, val: 0); |
1083 | if (ret != 0) { |
1084 | dev_err(dev, "Failed to reset device: %d\n" , ret); |
1085 | goto err_reset; |
1086 | } |
1087 | |
1088 | usleep_range(min: 1000, max: 5000); |
1089 | } |
1090 | |
1091 | /* Ensure device startup is complete */ |
1092 | switch (arizona->type) { |
1093 | case WM5102: |
1094 | ret = regmap_read(map: arizona->regmap, |
1095 | ARIZONA_WRITE_SEQUENCER_CTRL_3, val: &val); |
1096 | if (ret) { |
1097 | dev_err(dev, |
1098 | "Failed to check write sequencer state: %d\n" , |
1099 | ret); |
1100 | } else if (val & 0x01) { |
1101 | ret = wm5102_clear_write_sequencer(arizona); |
1102 | if (ret) |
1103 | return ret; |
1104 | } |
1105 | break; |
1106 | default: |
1107 | break; |
1108 | } |
1109 | |
1110 | ret = arizona_wait_for_boot(arizona); |
1111 | if (ret) { |
1112 | dev_err(arizona->dev, "Device failed initial boot: %d\n" , ret); |
1113 | goto err_reset; |
1114 | } |
1115 | |
1116 | /* Read the device ID information & do device specific stuff */ |
1117 | ret = regmap_read(map: arizona->regmap, ARIZONA_SOFTWARE_RESET, val: ®); |
1118 | if (ret != 0) { |
1119 | dev_err(dev, "Failed to read ID register: %d\n" , ret); |
1120 | goto err_reset; |
1121 | } |
1122 | |
1123 | ret = regmap_read(map: arizona->regmap, ARIZONA_DEVICE_REVISION, |
1124 | val: &arizona->rev); |
1125 | if (ret != 0) { |
1126 | dev_err(dev, "Failed to read revision register: %d\n" , ret); |
1127 | goto err_reset; |
1128 | } |
1129 | arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; |
1130 | |
1131 | switch (reg) { |
1132 | case 0x5102: |
1133 | if (IS_ENABLED(CONFIG_MFD_WM5102)) { |
1134 | type_name = "WM5102" ; |
1135 | if (arizona->type != WM5102) { |
1136 | dev_warn(arizona->dev, |
1137 | "WM5102 registered as %d\n" , |
1138 | arizona->type); |
1139 | arizona->type = WM5102; |
1140 | } |
1141 | |
1142 | apply_patch = wm5102_patch; |
1143 | arizona->rev &= 0x7; |
1144 | subdevs = wm5102_devs; |
1145 | n_subdevs = ARRAY_SIZE(wm5102_devs); |
1146 | } |
1147 | break; |
1148 | case 0x5110: |
1149 | if (IS_ENABLED(CONFIG_MFD_WM5110)) { |
1150 | switch (arizona->type) { |
1151 | case WM5110: |
1152 | type_name = "WM5110" ; |
1153 | break; |
1154 | case WM8280: |
1155 | type_name = "WM8280" ; |
1156 | break; |
1157 | default: |
1158 | type_name = "WM5110" ; |
1159 | dev_warn(arizona->dev, |
1160 | "WM5110 registered as %d\n" , |
1161 | arizona->type); |
1162 | arizona->type = WM5110; |
1163 | break; |
1164 | } |
1165 | |
1166 | apply_patch = wm5110_patch; |
1167 | subdevs = wm5110_devs; |
1168 | n_subdevs = ARRAY_SIZE(wm5110_devs); |
1169 | } |
1170 | break; |
1171 | case 0x6363: |
1172 | if (IS_ENABLED(CONFIG_MFD_CS47L24)) { |
1173 | switch (arizona->type) { |
1174 | case CS47L24: |
1175 | type_name = "CS47L24" ; |
1176 | break; |
1177 | |
1178 | case WM1831: |
1179 | type_name = "WM1831" ; |
1180 | break; |
1181 | |
1182 | default: |
1183 | dev_warn(arizona->dev, |
1184 | "CS47L24 registered as %d\n" , |
1185 | arizona->type); |
1186 | arizona->type = CS47L24; |
1187 | break; |
1188 | } |
1189 | |
1190 | apply_patch = cs47l24_patch; |
1191 | subdevs = cs47l24_devs; |
1192 | n_subdevs = ARRAY_SIZE(cs47l24_devs); |
1193 | } |
1194 | break; |
1195 | case 0x8997: |
1196 | if (IS_ENABLED(CONFIG_MFD_WM8997)) { |
1197 | type_name = "WM8997" ; |
1198 | if (arizona->type != WM8997) { |
1199 | dev_warn(arizona->dev, |
1200 | "WM8997 registered as %d\n" , |
1201 | arizona->type); |
1202 | arizona->type = WM8997; |
1203 | } |
1204 | |
1205 | apply_patch = wm8997_patch; |
1206 | subdevs = wm8997_devs; |
1207 | n_subdevs = ARRAY_SIZE(wm8997_devs); |
1208 | } |
1209 | break; |
1210 | case 0x6349: |
1211 | if (IS_ENABLED(CONFIG_MFD_WM8998)) { |
1212 | switch (arizona->type) { |
1213 | case WM8998: |
1214 | type_name = "WM8998" ; |
1215 | break; |
1216 | |
1217 | case WM1814: |
1218 | type_name = "WM1814" ; |
1219 | break; |
1220 | |
1221 | default: |
1222 | type_name = "WM8998" ; |
1223 | dev_warn(arizona->dev, |
1224 | "WM8998 registered as %d\n" , |
1225 | arizona->type); |
1226 | arizona->type = WM8998; |
1227 | } |
1228 | |
1229 | apply_patch = wm8998_patch; |
1230 | subdevs = wm8998_devs; |
1231 | n_subdevs = ARRAY_SIZE(wm8998_devs); |
1232 | } |
1233 | break; |
1234 | default: |
1235 | dev_err(arizona->dev, "Unknown device ID %x\n" , reg); |
1236 | ret = -ENODEV; |
1237 | goto err_reset; |
1238 | } |
1239 | |
1240 | if (!subdevs) { |
1241 | dev_err(arizona->dev, |
1242 | "No kernel support for device ID %x\n" , reg); |
1243 | ret = -ENODEV; |
1244 | goto err_reset; |
1245 | } |
1246 | |
1247 | dev_info(dev, "%s revision %c\n" , type_name, arizona->rev + 'A'); |
1248 | |
1249 | if (apply_patch) { |
1250 | ret = apply_patch(arizona); |
1251 | if (ret != 0) { |
1252 | dev_err(arizona->dev, "Failed to apply patch: %d\n" , |
1253 | ret); |
1254 | goto err_reset; |
1255 | } |
1256 | |
1257 | switch (arizona->type) { |
1258 | case WM5102: |
1259 | ret = wm5102_apply_hardware_patch(arizona); |
1260 | if (ret) { |
1261 | dev_err(arizona->dev, |
1262 | "Failed to apply hardware patch: %d\n" , |
1263 | ret); |
1264 | goto err_reset; |
1265 | } |
1266 | break; |
1267 | case WM5110: |
1268 | case WM8280: |
1269 | ret = wm5110_apply_sleep_patch(arizona); |
1270 | if (ret) { |
1271 | dev_err(arizona->dev, |
1272 | "Failed to apply sleep patch: %d\n" , |
1273 | ret); |
1274 | goto err_reset; |
1275 | } |
1276 | break; |
1277 | default: |
1278 | break; |
1279 | } |
1280 | } |
1281 | |
1282 | for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { |
1283 | if (!arizona->pdata.gpio_defaults[i]) |
1284 | continue; |
1285 | |
1286 | regmap_write(map: arizona->regmap, ARIZONA_GPIO1_CTRL + i, |
1287 | val: arizona->pdata.gpio_defaults[i]); |
1288 | } |
1289 | |
1290 | /* Chip default */ |
1291 | if (!arizona->pdata.clk32k_src) |
1292 | arizona->pdata.clk32k_src = ARIZONA_32KZ_MCLK2; |
1293 | |
1294 | switch (arizona->pdata.clk32k_src) { |
1295 | case ARIZONA_32KZ_MCLK1: |
1296 | case ARIZONA_32KZ_MCLK2: |
1297 | regmap_update_bits(map: arizona->regmap, ARIZONA_CLOCK_32K_1, |
1298 | ARIZONA_CLK_32K_SRC_MASK, |
1299 | val: arizona->pdata.clk32k_src - 1); |
1300 | arizona_clk32k_enable(arizona); |
1301 | break; |
1302 | case ARIZONA_32KZ_NONE: |
1303 | regmap_update_bits(map: arizona->regmap, ARIZONA_CLOCK_32K_1, |
1304 | ARIZONA_CLK_32K_SRC_MASK, val: 2); |
1305 | break; |
1306 | default: |
1307 | dev_err(arizona->dev, "Invalid 32kHz clock source: %d\n" , |
1308 | arizona->pdata.clk32k_src); |
1309 | ret = -EINVAL; |
1310 | goto err_reset; |
1311 | } |
1312 | |
1313 | for (i = 0; i < ARIZONA_MAX_MICBIAS; i++) { |
1314 | if (!arizona->pdata.micbias[i].mV && |
1315 | !arizona->pdata.micbias[i].bypass) |
1316 | continue; |
1317 | |
1318 | /* Apply default for bypass mode */ |
1319 | if (!arizona->pdata.micbias[i].mV) |
1320 | arizona->pdata.micbias[i].mV = 2800; |
1321 | |
1322 | val = (arizona->pdata.micbias[i].mV - 1500) / 100; |
1323 | |
1324 | val <<= ARIZONA_MICB1_LVL_SHIFT; |
1325 | |
1326 | if (arizona->pdata.micbias[i].ext_cap) |
1327 | val |= ARIZONA_MICB1_EXT_CAP; |
1328 | |
1329 | if (arizona->pdata.micbias[i].discharge) |
1330 | val |= ARIZONA_MICB1_DISCH; |
1331 | |
1332 | if (arizona->pdata.micbias[i].soft_start) |
1333 | val |= ARIZONA_MICB1_RATE; |
1334 | |
1335 | if (arizona->pdata.micbias[i].bypass) |
1336 | val |= ARIZONA_MICB1_BYPASS; |
1337 | |
1338 | regmap_update_bits(map: arizona->regmap, |
1339 | ARIZONA_MIC_BIAS_CTRL_1 + i, |
1340 | ARIZONA_MICB1_LVL_MASK | |
1341 | ARIZONA_MICB1_EXT_CAP | |
1342 | ARIZONA_MICB1_DISCH | |
1343 | ARIZONA_MICB1_BYPASS | |
1344 | ARIZONA_MICB1_RATE, val); |
1345 | } |
1346 | |
1347 | pm_runtime_set_active(dev: arizona->dev); |
1348 | pm_runtime_enable(dev: arizona->dev); |
1349 | |
1350 | /* Set up for interrupts */ |
1351 | ret = arizona_irq_init(arizona); |
1352 | if (ret != 0) |
1353 | goto err_pm; |
1354 | |
1355 | pm_runtime_set_autosuspend_delay(dev: arizona->dev, delay: 100); |
1356 | pm_runtime_use_autosuspend(dev: arizona->dev); |
1357 | |
1358 | arizona_request_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, name: "CLKGEN error" , |
1359 | handler: arizona_clkgen_err, data: arizona); |
1360 | arizona_request_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, name: "Overclocked" , |
1361 | handler: arizona_overclocked, data: arizona); |
1362 | arizona_request_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, name: "Underclocked" , |
1363 | handler: arizona_underclocked, data: arizona); |
1364 | |
1365 | ret = mfd_add_devices(parent: arizona->dev, PLATFORM_DEVID_NONE, |
1366 | cells: subdevs, n_devs: n_subdevs, NULL, irq_base: 0, NULL); |
1367 | |
1368 | if (ret) { |
1369 | dev_err(arizona->dev, "Failed to add subdevices: %d\n" , ret); |
1370 | goto err_irq; |
1371 | } |
1372 | |
1373 | return 0; |
1374 | |
1375 | err_irq: |
1376 | arizona_irq_exit(arizona); |
1377 | err_pm: |
1378 | pm_runtime_disable(dev: arizona->dev); |
1379 | |
1380 | switch (arizona->pdata.clk32k_src) { |
1381 | case ARIZONA_32KZ_MCLK1: |
1382 | case ARIZONA_32KZ_MCLK2: |
1383 | arizona_clk32k_disable(arizona); |
1384 | break; |
1385 | default: |
1386 | break; |
1387 | } |
1388 | err_reset: |
1389 | arizona_enable_reset(arizona); |
1390 | regulator_disable(regulator: arizona->dcvdd); |
1391 | err_enable: |
1392 | regulator_bulk_disable(num_consumers: arizona->num_core_supplies, |
1393 | consumers: arizona->core_supplies); |
1394 | err_dcvdd: |
1395 | regulator_put(regulator: arizona->dcvdd); |
1396 | err_early: |
1397 | mfd_remove_devices(parent: dev); |
1398 | return ret; |
1399 | } |
1400 | EXPORT_SYMBOL_GPL(arizona_dev_init); |
1401 | |
1402 | int arizona_dev_exit(struct arizona *arizona) |
1403 | { |
1404 | disable_irq(irq: arizona->irq); |
1405 | pm_runtime_disable(dev: arizona->dev); |
1406 | |
1407 | regulator_disable(regulator: arizona->dcvdd); |
1408 | regulator_put(regulator: arizona->dcvdd); |
1409 | |
1410 | switch (arizona->pdata.clk32k_src) { |
1411 | case ARIZONA_32KZ_MCLK1: |
1412 | case ARIZONA_32KZ_MCLK2: |
1413 | arizona_clk32k_disable(arizona); |
1414 | break; |
1415 | default: |
1416 | break; |
1417 | } |
1418 | |
1419 | mfd_remove_devices(parent: arizona->dev); |
1420 | arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, data: arizona); |
1421 | arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, data: arizona); |
1422 | arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, data: arizona); |
1423 | arizona_irq_exit(arizona); |
1424 | arizona_enable_reset(arizona); |
1425 | |
1426 | regulator_bulk_disable(num_consumers: arizona->num_core_supplies, |
1427 | consumers: arizona->core_supplies); |
1428 | return 0; |
1429 | } |
1430 | EXPORT_SYMBOL_GPL(arizona_dev_exit); |
1431 | |
1432 | MODULE_LICENSE("GPL v2" ); |
1433 | |