diff options
Diffstat (limited to 'drivers/mfd/twl6040.c')
-rw-r--r-- | drivers/mfd/twl6040.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index 6e88f25832fb..ae26d84b3a59 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c | |||
@@ -87,8 +87,13 @@ static struct reg_default twl6040_defaults[] = { | |||
87 | }; | 87 | }; |
88 | 88 | ||
89 | static struct reg_default twl6040_patch[] = { | 89 | static struct reg_default twl6040_patch[] = { |
90 | /* Select I2C bus access to dual access registers */ | 90 | /* |
91 | { TWL6040_REG_ACCCTL, 0x09 }, | 91 | * Select I2C bus access to dual access registers |
92 | * Interrupt register is cleared on read | ||
93 | * Select fast mode for i2c (400KHz) | ||
94 | */ | ||
95 | { TWL6040_REG_ACCCTL, | ||
96 | TWL6040_I2CSEL | TWL6040_INTCLRMODE | TWL6040_I2CMODE(1) }, | ||
92 | }; | 97 | }; |
93 | 98 | ||
94 | 99 | ||
@@ -286,6 +291,8 @@ int twl6040_power(struct twl6040 *twl6040, int on) | |||
286 | if (twl6040->power_count++) | 291 | if (twl6040->power_count++) |
287 | goto out; | 292 | goto out; |
288 | 293 | ||
294 | clk_prepare_enable(twl6040->clk32k); | ||
295 | |||
289 | /* Allow writes to the chip */ | 296 | /* Allow writes to the chip */ |
290 | regcache_cache_only(twl6040->regmap, false); | 297 | regcache_cache_only(twl6040->regmap, false); |
291 | 298 | ||
@@ -341,6 +348,8 @@ int twl6040_power(struct twl6040 *twl6040, int on) | |||
341 | 348 | ||
342 | twl6040->sysclk = 0; | 349 | twl6040->sysclk = 0; |
343 | twl6040->mclk = 0; | 350 | twl6040->mclk = 0; |
351 | |||
352 | clk_disable_unprepare(twl6040->clk32k); | ||
344 | } | 353 | } |
345 | 354 | ||
346 | out: | 355 | out: |
@@ -432,12 +441,9 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
432 | TWL6040_HPLLENA; | 441 | TWL6040_HPLLENA; |
433 | break; | 442 | break; |
434 | case 19200000: | 443 | case 19200000: |
435 | /* | 444 | /* PLL enabled, bypass mode */ |
436 | * PLL disabled | 445 | hppllctl |= TWL6040_MCLK_19200KHZ | |
437 | * (enable PLL if MCLK jitter quality | 446 | TWL6040_HPLLBP | TWL6040_HPLLENA; |
438 | * doesn't meet specification) | ||
439 | */ | ||
440 | hppllctl |= TWL6040_MCLK_19200KHZ; | ||
441 | break; | 447 | break; |
442 | case 26000000: | 448 | case 26000000: |
443 | /* PLL enabled, active mode */ | 449 | /* PLL enabled, active mode */ |
@@ -445,9 +451,9 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, | |||
445 | TWL6040_HPLLENA; | 451 | TWL6040_HPLLENA; |
446 | break; | 452 | break; |
447 | case 38400000: | 453 | case 38400000: |
448 | /* PLL enabled, active mode */ | 454 | /* PLL enabled, bypass mode */ |
449 | hppllctl |= TWL6040_MCLK_38400KHZ | | 455 | hppllctl |= TWL6040_MCLK_38400KHZ | |
450 | TWL6040_HPLLENA; | 456 | TWL6040_HPLLBP | TWL6040_HPLLENA; |
451 | break; | 457 | break; |
452 | default: | 458 | default: |
453 | dev_err(twl6040->dev, | 459 | dev_err(twl6040->dev, |
@@ -639,6 +645,12 @@ static int twl6040_probe(struct i2c_client *client, | |||
639 | 645 | ||
640 | i2c_set_clientdata(client, twl6040); | 646 | i2c_set_clientdata(client, twl6040); |
641 | 647 | ||
648 | twl6040->clk32k = devm_clk_get(&client->dev, "clk32k"); | ||
649 | if (IS_ERR(twl6040->clk32k)) { | ||
650 | dev_info(&client->dev, "clk32k is not handled\n"); | ||
651 | twl6040->clk32k = NULL; | ||
652 | } | ||
653 | |||
642 | twl6040->supplies[0].supply = "vio"; | 654 | twl6040->supplies[0].supply = "vio"; |
643 | twl6040->supplies[1].supply = "v2v1"; | 655 | twl6040->supplies[1].supply = "v2v1"; |
644 | ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES, | 656 | ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES, |
@@ -660,6 +672,9 @@ static int twl6040_probe(struct i2c_client *client, | |||
660 | mutex_init(&twl6040->mutex); | 672 | mutex_init(&twl6040->mutex); |
661 | init_completion(&twl6040->ready); | 673 | init_completion(&twl6040->ready); |
662 | 674 | ||
675 | regmap_register_patch(twl6040->regmap, twl6040_patch, | ||
676 | ARRAY_SIZE(twl6040_patch)); | ||
677 | |||
663 | twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV); | 678 | twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV); |
664 | if (twl6040->rev < 0) { | 679 | if (twl6040->rev < 0) { |
665 | dev_err(&client->dev, "Failed to read revision register: %d\n", | 680 | dev_err(&client->dev, "Failed to read revision register: %d\n", |
@@ -679,6 +694,9 @@ static int twl6040_probe(struct i2c_client *client, | |||
679 | GPIOF_OUT_INIT_LOW, "audpwron"); | 694 | GPIOF_OUT_INIT_LOW, "audpwron"); |
680 | if (ret) | 695 | if (ret) |
681 | goto gpio_err; | 696 | goto gpio_err; |
697 | |||
698 | /* Clear any pending interrupt */ | ||
699 | twl6040_reg_read(twl6040, TWL6040_REG_INTID); | ||
682 | } | 700 | } |
683 | 701 | ||
684 | ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq, IRQF_ONESHOT, | 702 | ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq, IRQF_ONESHOT, |
@@ -707,10 +725,6 @@ static int twl6040_probe(struct i2c_client *client, | |||
707 | goto readyirq_err; | 725 | goto readyirq_err; |
708 | } | 726 | } |
709 | 727 | ||
710 | /* dual-access registers controlled by I2C only */ | ||
711 | regmap_register_patch(twl6040->regmap, twl6040_patch, | ||
712 | ARRAY_SIZE(twl6040_patch)); | ||
713 | |||
714 | /* | 728 | /* |
715 | * The main functionality of twl6040 to provide audio on OMAP4+ systems. | 729 | * The main functionality of twl6040 to provide audio on OMAP4+ systems. |
716 | * We can add the ASoC codec child whenever this driver has been loaded. | 730 | * We can add the ASoC codec child whenever this driver has been loaded. |