aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2013-03-26 14:46:15 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-04-08 09:21:01 -0400
commite80436bbb241abbf2168c65622fb98d9378432fa (patch)
treed6588ca690f6a87f9bf3e4b8bd02178249e5ff25 /drivers/mfd
parent9d53dfdc82503b819f7b854e627a555cc65224e3 (diff)
mfd: arizona: Add a hardware patch mechanism
This patch adds facilities for apply a register patch contained within the chip using the write sequencer. Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/arizona-core.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index b09b119d4966..d6b40df64c4a 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -242,6 +242,90 @@ static int arizona_wait_for_boot(struct arizona *arizona)
242 return ret; 242 return ret;
243} 243}
244 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;
264 }
265
266 /* Start up SYSCLK using the FLL in free running mode */
267 ret = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1,
268 ARIZONA_FLL1_ENA | ARIZONA_FLL1_FREERUN);
269 if (ret != 0) {
270 dev_err(arizona->dev,
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;
281 }
282
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 }
288
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;
327}
328
245#ifdef CONFIG_PM_RUNTIME 329#ifdef CONFIG_PM_RUNTIME
246static int arizona_runtime_resume(struct device *dev) 330static int arizona_runtime_resume(struct device *dev)
247{ 331{
@@ -271,6 +355,17 @@ static int arizona_runtime_resume(struct device *dev)
271 ret); 355 ret);
272 goto err; 356 goto err;
273 } 357 }
358
359 ret = arizona_apply_hardware_patch(arizona);
360 if (ret != 0) {
361 dev_err(arizona->dev,
362 "Failed to apply hardware patch: %d\n",
363 ret);
364 goto err;
365 }
366 break;
367 default:
368 break;
274 } 369 }
275 370
276 ret = regcache_sync(arizona->regmap); 371 ret = regcache_sync(arizona->regmap);
@@ -513,6 +608,20 @@ int arizona_dev_init(struct arizona *arizona)
513 ret); 608 ret);
514 goto err_reset; 609 goto err_reset;
515 } 610 }
611
612 switch (arizona->type) {
613 case WM5102:
614 ret = arizona_apply_hardware_patch(arizona);
615 if (ret != 0) {
616 dev_err(arizona->dev,
617 "Failed to apply hardware patch: %d\n",
618 ret);
619 goto err_reset;
620 }
621 break;
622 default:
623 break;
624 }
516 } 625 }
517 626
518 for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { 627 for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {