aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/arizona-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/arizona-core.c')
-rw-r--r--drivers/mfd/arizona-core.c267
1 files changed, 222 insertions, 45 deletions
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index b562c7bf8a46..6ab03043fd60 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -39,11 +39,21 @@ int arizona_clk32k_enable(struct arizona *arizona)
39 39
40 arizona->clk32k_ref++; 40 arizona->clk32k_ref++;
41 41
42 if (arizona->clk32k_ref == 1) 42 if (arizona->clk32k_ref == 1) {
43 switch (arizona->pdata.clk32k_src) {
44 case ARIZONA_32KZ_MCLK1:
45 ret = pm_runtime_get_sync(arizona->dev);
46 if (ret != 0)
47 goto out;
48 break;
49 }
50
43 ret = regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1, 51 ret = regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1,
44 ARIZONA_CLK_32K_ENA, 52 ARIZONA_CLK_32K_ENA,
45 ARIZONA_CLK_32K_ENA); 53 ARIZONA_CLK_32K_ENA);
54 }
46 55
56out:
47 if (ret != 0) 57 if (ret != 0)
48 arizona->clk32k_ref--; 58 arizona->clk32k_ref--;
49 59
@@ -63,10 +73,17 @@ int arizona_clk32k_disable(struct arizona *arizona)
63 73
64 arizona->clk32k_ref--; 74 arizona->clk32k_ref--;
65 75
66 if (arizona->clk32k_ref == 0) 76 if (arizona->clk32k_ref == 0) {
67 regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1, 77 regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1,
68 ARIZONA_CLK_32K_ENA, 0); 78 ARIZONA_CLK_32K_ENA, 0);
69 79
80 switch (arizona->pdata.clk32k_src) {
81 case ARIZONA_32KZ_MCLK1:
82 pm_runtime_put_sync(arizona->dev);
83 break;
84 }
85 }
86
70 mutex_unlock(&arizona->clk_lock); 87 mutex_unlock(&arizona->clk_lock);
71 88
72 return ret; 89 return ret;
@@ -179,42 +196,134 @@ static irqreturn_t arizona_overclocked(int irq, void *data)
179 return IRQ_HANDLED; 196 return IRQ_HANDLED;
180} 197}
181 198
182static int arizona_wait_for_boot(struct arizona *arizona) 199static int arizona_poll_reg(struct arizona *arizona,
200 int timeout, unsigned int reg,
201 unsigned int mask, unsigned int target)
183{ 202{
184 unsigned int reg; 203 unsigned int val = 0;
185 int ret, i; 204 int ret, i;
186 205
206 for (i = 0; i < timeout; i++) {
207 ret = regmap_read(arizona->regmap, reg, &val);
208 if (ret != 0) {
209 dev_err(arizona->dev, "Failed to read reg %u: %d\n",
210 reg, ret);
211 continue;
212 }
213
214 if ((val & mask) == target)
215 return 0;
216
217 msleep(1);
218 }
219
220 dev_err(arizona->dev, "Polling reg %u timed out: %x\n", reg, val);
221 return -ETIMEDOUT;
222}
223
224static int arizona_wait_for_boot(struct arizona *arizona)
225{
226 int ret;
227
187 /* 228 /*
188 * We can't use an interrupt as we need to runtime resume to do so, 229 * We can't use an interrupt as we need to runtime resume to do so,
189 * we won't race with the interrupt handler as it'll be blocked on 230 * we won't race with the interrupt handler as it'll be blocked on
190 * runtime resume. 231 * runtime resume.
191 */ 232 */
192 for (i = 0; i < 5; i++) { 233 ret = arizona_poll_reg(arizona, 5, ARIZONA_INTERRUPT_RAW_STATUS_5,
193 msleep(1); 234 ARIZONA_BOOT_DONE_STS, ARIZONA_BOOT_DONE_STS);
194 235
195 ret = regmap_read(arizona->regmap, 236 if (!ret)
196 ARIZONA_INTERRUPT_RAW_STATUS_5, &reg); 237 regmap_write(arizona->regmap, ARIZONA_INTERRUPT_STATUS_5,
197 if (ret != 0) { 238 ARIZONA_BOOT_DONE_STS);
198 dev_err(arizona->dev, "Failed to read boot state: %d\n",
199 ret);
200 continue;
201 }
202 239
203 if (reg & ARIZONA_BOOT_DONE_STS) 240 pm_runtime_mark_last_busy(arizona->dev);
204 break; 241
242 return ret;
243}
244
245static int arizona_apply_hardware_patch(struct arizona* arizona)
246{
247 unsigned int fll, sysclk;
248 int ret, err;
249
250 regcache_cache_bypass(arizona->regmap, true);
251
252 /* Cache existing FLL and SYSCLK settings */
253 ret = regmap_read(arizona->regmap, ARIZONA_FLL1_CONTROL_1, &fll);
254 if (ret != 0) {
255 dev_err(arizona->dev, "Failed to cache FLL settings: %d\n",
256 ret);
257 return ret;
258 }
259 ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &sysclk);
260 if (ret != 0) {
261 dev_err(arizona->dev, "Failed to cache SYSCLK settings: %d\n",
262 ret);
263 return ret;
205 } 264 }
206 265
207 if (reg & ARIZONA_BOOT_DONE_STS) { 266 /* Start up SYSCLK using the FLL in free running mode */
208 regmap_write(arizona->regmap, ARIZONA_INTERRUPT_STATUS_5, 267 ret = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1,
209 ARIZONA_BOOT_DONE_STS); 268 ARIZONA_FLL1_ENA | ARIZONA_FLL1_FREERUN);
210 } else { 269 if (ret != 0) {
211 dev_err(arizona->dev, "Device boot timed out: %x\n", reg); 270 dev_err(arizona->dev,
212 return -ETIMEDOUT; 271 "Failed to start FLL in freerunning mode: %d\n",
272 ret);
273 return ret;
274 }
275 ret = arizona_poll_reg(arizona, 25, ARIZONA_INTERRUPT_RAW_STATUS_5,
276 ARIZONA_FLL1_CLOCK_OK_STS,
277 ARIZONA_FLL1_CLOCK_OK_STS);
278 if (ret != 0) {
279 ret = -ETIMEDOUT;
280 goto err_fll;
213 } 281 }
214 282
215 pm_runtime_mark_last_busy(arizona->dev); 283 ret = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, 0x0144);
284 if (ret != 0) {
285 dev_err(arizona->dev, "Failed to start SYSCLK: %d\n", ret);
286 goto err_fll;
287 }
216 288
217 return 0; 289 /* Start the write sequencer and wait for it to finish */
290 ret = regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0,
291 ARIZONA_WSEQ_ENA | ARIZONA_WSEQ_START | 160);
292 if (ret != 0) {
293 dev_err(arizona->dev, "Failed to start write sequencer: %d\n",
294 ret);
295 goto err_sysclk;
296 }
297 ret = arizona_poll_reg(arizona, 5, ARIZONA_WRITE_SEQUENCER_CTRL_1,
298 ARIZONA_WSEQ_BUSY, 0);
299 if (ret != 0) {
300 regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_0,
301 ARIZONA_WSEQ_ABORT);
302 ret = -ETIMEDOUT;
303 }
304
305err_sysclk:
306 err = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, sysclk);
307 if (err != 0) {
308 dev_err(arizona->dev,
309 "Failed to re-apply old SYSCLK settings: %d\n",
310 err);
311 }
312
313err_fll:
314 err = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, fll);
315 if (err != 0) {
316 dev_err(arizona->dev,
317 "Failed to re-apply old FLL settings: %d\n",
318 err);
319 }
320
321 regcache_cache_bypass(arizona->regmap, false);
322
323 if (ret != 0)
324 return ret;
325 else
326 return err;
218} 327}
219 328
220#ifdef CONFIG_PM_RUNTIME 329#ifdef CONFIG_PM_RUNTIME
@@ -233,20 +342,44 @@ static int arizona_runtime_resume(struct device *dev)
233 342
234 regcache_cache_only(arizona->regmap, false); 343 regcache_cache_only(arizona->regmap, false);
235 344
236 ret = arizona_wait_for_boot(arizona); 345 switch (arizona->type) {
237 if (ret != 0) { 346 case WM5102:
238 regulator_disable(arizona->dcvdd); 347 ret = wm5102_patch(arizona);
239 return ret; 348 if (ret != 0) {
349 dev_err(arizona->dev, "Failed to apply patch: %d\n",
350 ret);
351 goto err;
352 }
353
354 ret = arizona_apply_hardware_patch(arizona);
355 if (ret != 0) {
356 dev_err(arizona->dev,
357 "Failed to apply hardware patch: %d\n",
358 ret);
359 goto err;
360 }
361 break;
362 default:
363 ret = arizona_wait_for_boot(arizona);
364 if (ret != 0) {
365 goto err;
366 }
367
368 break;
240 } 369 }
241 370
242 ret = regcache_sync(arizona->regmap); 371 ret = regcache_sync(arizona->regmap);
243 if (ret != 0) { 372 if (ret != 0) {
244 dev_err(arizona->dev, "Failed to restore register cache\n"); 373 dev_err(arizona->dev, "Failed to restore register cache\n");
245 regulator_disable(arizona->dcvdd); 374 goto err;
246 return ret;
247 } 375 }
248 376
249 return 0; 377 return 0;
378
379err:
380 regcache_cache_only(arizona->regmap, true);
381 regulator_disable(arizona->dcvdd);
382 return ret;
250} 383}
251 384
252static int arizona_runtime_suspend(struct device *dev) 385static int arizona_runtime_suspend(struct device *dev)
@@ -371,6 +504,17 @@ int arizona_dev_init(struct arizona *arizona)
371 goto err_early; 504 goto err_early;
372 } 505 }
373 506
507 if (arizona->pdata.reset) {
508 /* Start out with /RESET low to put the chip into reset */
509 ret = gpio_request_one(arizona->pdata.reset,
510 GPIOF_DIR_OUT | GPIOF_INIT_LOW,
511 "arizona /RESET");
512 if (ret != 0) {
513 dev_err(dev, "Failed to request /RESET: %d\n", ret);
514 goto err_early;
515 }
516 }
517
374 ret = regulator_bulk_enable(arizona->num_core_supplies, 518 ret = regulator_bulk_enable(arizona->num_core_supplies,
375 arizona->core_supplies); 519 arizona->core_supplies);
376 if (ret != 0) { 520 if (ret != 0) {
@@ -386,16 +530,8 @@ int arizona_dev_init(struct arizona *arizona)
386 } 530 }
387 531
388 if (arizona->pdata.reset) { 532 if (arizona->pdata.reset) {
389 /* Start out with /RESET low to put the chip into reset */
390 ret = gpio_request_one(arizona->pdata.reset,
391 GPIOF_DIR_OUT | GPIOF_INIT_LOW,
392 "arizona /RESET");
393 if (ret != 0) {
394 dev_err(dev, "Failed to request /RESET: %d\n", ret);
395 goto err_dcvdd;
396 }
397
398 gpio_set_value_cansleep(arizona->pdata.reset, 1); 533 gpio_set_value_cansleep(arizona->pdata.reset, 1);
534 msleep(1);
399 } 535 }
400 536
401 regcache_cache_only(arizona->regmap, false); 537 regcache_cache_only(arizona->regmap, false);
@@ -424,6 +560,7 @@ int arizona_dev_init(struct arizona *arizona)
424 arizona->type = WM5102; 560 arizona->type = WM5102;
425 } 561 }
426 apply_patch = wm5102_patch; 562 apply_patch = wm5102_patch;
563 arizona->rev &= 0x7;
427 break; 564 break;
428#endif 565#endif
429#ifdef CONFIG_MFD_WM5110 566#ifdef CONFIG_MFD_WM5110
@@ -454,6 +591,8 @@ int arizona_dev_init(struct arizona *arizona)
454 goto err_reset; 591 goto err_reset;
455 } 592 }
456 593
594 msleep(1);
595
457 ret = regcache_sync(arizona->regmap); 596 ret = regcache_sync(arizona->regmap);
458 if (ret != 0) { 597 if (ret != 0) {
459 dev_err(dev, "Failed to sync device: %d\n", ret); 598 dev_err(dev, "Failed to sync device: %d\n", ret);
@@ -461,10 +600,24 @@ int arizona_dev_init(struct arizona *arizona)
461 } 600 }
462 } 601 }
463 602
464 ret = arizona_wait_for_boot(arizona); 603 switch (arizona->type) {
465 if (ret != 0) { 604 case WM5102:
466 dev_err(arizona->dev, "Device failed initial boot: %d\n", ret); 605 ret = regmap_read(arizona->regmap, 0x19, &val);
467 goto err_reset; 606 if (ret != 0)
607 dev_err(dev,
608 "Failed to check write sequencer state: %d\n",
609 ret);
610 else if (val & 0x01)
611 break;
612 /* Fall through */
613 default:
614 ret = arizona_wait_for_boot(arizona);
615 if (ret != 0) {
616 dev_err(arizona->dev,
617 "Device failed initial boot: %d\n", ret);
618 goto err_reset;
619 }
620 break;
468 } 621 }
469 622
470 if (apply_patch) { 623 if (apply_patch) {
@@ -474,6 +627,20 @@ int arizona_dev_init(struct arizona *arizona)
474 ret); 627 ret);
475 goto err_reset; 628 goto err_reset;
476 } 629 }
630
631 switch (arizona->type) {
632 case WM5102:
633 ret = arizona_apply_hardware_patch(arizona);
634 if (ret != 0) {
635 dev_err(arizona->dev,
636 "Failed to apply hardware patch: %d\n",
637 ret);
638 goto err_reset;
639 }
640 break;
641 default:
642 break;
643 }
477 } 644 }
478 645
479 for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { 646 for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
@@ -498,6 +665,7 @@ int arizona_dev_init(struct arizona *arizona)
498 regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1, 665 regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1,
499 ARIZONA_CLK_32K_SRC_MASK, 666 ARIZONA_CLK_32K_SRC_MASK,
500 arizona->pdata.clk32k_src - 1); 667 arizona->pdata.clk32k_src - 1);
668 arizona_clk32k_enable(arizona);
501 break; 669 break;
502 case ARIZONA_32KZ_NONE: 670 case ARIZONA_32KZ_NONE:
503 regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1, 671 regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1,
@@ -511,10 +679,16 @@ int arizona_dev_init(struct arizona *arizona)
511 } 679 }
512 680
513 for (i = 0; i < ARIZONA_MAX_MICBIAS; i++) { 681 for (i = 0; i < ARIZONA_MAX_MICBIAS; i++) {
514 if (!arizona->pdata.micbias[i].mV) 682 if (!arizona->pdata.micbias[i].mV &&
683 !arizona->pdata.micbias[i].bypass)
515 continue; 684 continue;
516 685
686 /* Apply default for bypass mode */
687 if (!arizona->pdata.micbias[i].mV)
688 arizona->pdata.micbias[i].mV = 2800;
689
517 val = (arizona->pdata.micbias[i].mV - 1500) / 100; 690 val = (arizona->pdata.micbias[i].mV - 1500) / 100;
691
518 val <<= ARIZONA_MICB1_LVL_SHIFT; 692 val <<= ARIZONA_MICB1_LVL_SHIFT;
519 693
520 if (arizona->pdata.micbias[i].ext_cap) 694 if (arizona->pdata.micbias[i].ext_cap)
@@ -526,10 +700,14 @@ int arizona_dev_init(struct arizona *arizona)
526 if (arizona->pdata.micbias[i].fast_start) 700 if (arizona->pdata.micbias[i].fast_start)
527 val |= ARIZONA_MICB1_RATE; 701 val |= ARIZONA_MICB1_RATE;
528 702
703 if (arizona->pdata.micbias[i].bypass)
704 val |= ARIZONA_MICB1_BYPASS;
705
529 regmap_update_bits(arizona->regmap, 706 regmap_update_bits(arizona->regmap,
530 ARIZONA_MIC_BIAS_CTRL_1 + i, 707 ARIZONA_MIC_BIAS_CTRL_1 + i,
531 ARIZONA_MICB1_LVL_MASK | 708 ARIZONA_MICB1_LVL_MASK |
532 ARIZONA_MICB1_DISCH | 709 ARIZONA_MICB1_DISCH |
710 ARIZONA_MICB1_BYPASS |
533 ARIZONA_MICB1_RATE, val); 711 ARIZONA_MICB1_RATE, val);
534 } 712 }
535 713
@@ -610,10 +788,9 @@ err_irq:
610 arizona_irq_exit(arizona); 788 arizona_irq_exit(arizona);
611err_reset: 789err_reset:
612 if (arizona->pdata.reset) { 790 if (arizona->pdata.reset) {
613 gpio_set_value_cansleep(arizona->pdata.reset, 1); 791 gpio_set_value_cansleep(arizona->pdata.reset, 0);
614 gpio_free(arizona->pdata.reset); 792 gpio_free(arizona->pdata.reset);
615 } 793 }
616err_dcvdd:
617 regulator_disable(arizona->dcvdd); 794 regulator_disable(arizona->dcvdd);
618err_enable: 795err_enable:
619 regulator_bulk_disable(arizona->num_core_supplies, 796 regulator_bulk_disable(arizona->num_core_supplies,