mfd: wm5102: Ensure we always boot the device fully
The wm5102 uses a custom boot sequence and the standard boot sequence is disabled. However, the standard boot sequence must be run at least once after a cold boot (caused by either a hard reset or removal of AVDD). Unfortunately the register WRITE_SEQUENCER_CTRL_3 is not affected by the hardware reset. This means if the device has been previously booted but the AVDD supply has never been removed, arizona_dev_init will reset the chip but the boot sequence will not run, which can cause numerous problems. The solution is to manually clear this register and then boot the chip again, which is what this patch does. Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
This commit is contained in:
parent
2229875dc0
commit
1c1c6bba57
|
@ -344,6 +344,33 @@ static int arizona_apply_hardware_patch(struct arizona* arizona)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int wm5102_clear_write_sequencer(struct arizona *arizona)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_3,
|
||||
0x0);
|
||||
if (ret) {
|
||||
dev_err(arizona->dev,
|
||||
"Failed to clear write sequencer state: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
arizona_enable_reset(arizona);
|
||||
regulator_disable(arizona->dcvdd);
|
||||
|
||||
msleep(20);
|
||||
|
||||
ret = regulator_enable(arizona->dcvdd);
|
||||
if (ret) {
|
||||
dev_err(arizona->dev, "Failed to re-enable DCVDD: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
arizona_disable_reset(arizona);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int arizona_runtime_resume(struct device *dev)
|
||||
{
|
||||
|
@ -802,21 +829,24 @@ int arizona_dev_init(struct arizona *arizona)
|
|||
case WM5102:
|
||||
ret = regmap_read(arizona->regmap,
|
||||
ARIZONA_WRITE_SEQUENCER_CTRL_3, &val);
|
||||
if (ret != 0)
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Failed to check write sequencer state: %d\n",
|
||||
ret);
|
||||
else if (val & 0x01)
|
||||
break;
|
||||
/* Fall through */
|
||||
default:
|
||||
ret = arizona_wait_for_boot(arizona);
|
||||
if (ret != 0) {
|
||||
dev_err(arizona->dev,
|
||||
"Device failed initial boot: %d\n", ret);
|
||||
goto err_reset;
|
||||
} else if (val & 0x01) {
|
||||
ret = wm5102_clear_write_sequencer(arizona);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = arizona_wait_for_boot(arizona);
|
||||
if (ret) {
|
||||
dev_err(arizona->dev, "Device failed initial boot: %d\n", ret);
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
/* Read the device ID information & do device specific stuff */
|
||||
|
|
Loading…
Reference in New Issue