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:
Charles Keepax 2015-05-11 13:58:03 +01:00 committed by Lee Jones
parent 2229875dc0
commit 1c1c6bba57
1 changed files with 40 additions and 10 deletions

View File

@ -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 */