MLK-11550-1: regulator: pfuze100: restore some registers after LPSR for pfuze3000

Some registers on pfuze3000 will lost after exit from LPSR, need restore them,
otherwise system may reboot with below command after system enter LPSR one time:

root@imx7d_all:~# echo enabled > /sys/class/tty/ttymxc0/power/wakeup
root@imx7d_all:~# echo mem > /sys/power/state

because LDOGCTL not recover as 1. Add 'fsl,lpsr-mode' property to this case,
please add this property if your board support LPSR mode as imx7d-12x12-lpddr3-arm2
board.

Signed-off-by: Robin Gong <b38343@freescale.com>
This commit is contained in:
Robin Gong 2015-09-15 12:46:39 +08:00 committed by Jason Liu
parent add090516f
commit 4aa2a2a928
2 changed files with 94 additions and 0 deletions

View File

@ -3,6 +3,8 @@ PFUZE100 family of regulators
Required properties:
- compatible: "fsl,pfuze100", "fsl,pfuze200", "fsl,pfuze3000"
- reg: I2C slave address
- fsl,lpsr-mode: some registers need to be saved and restored in lpsr mode
for pfuze3000
Required child node:
- regulators: This is the list of child nodes that specify the regulator

View File

@ -35,6 +35,15 @@
#define PFUZE100_STANDBY_OFFSET 1
#define PFUZE100_MODE_OFFSET 3
#define PFUZE100_CONF_OFFSET 4
/*
* below regs will lost after exit from LPSR mode(PFUZE3000), need to be saved
* and restored:
* 0x20~0x40: 33
* 0x66~0x71: 12
* 0x7f: 1
* total 46 registers.
*/
#define PFUZE100_REG_SAVED_NUM (33 + 12 + 1)
#define PFUZE100_DEVICEID 0x0
#define PFUZE100_REVID 0x3
@ -69,6 +78,8 @@ struct pfuze_chip {
int chip_id;
struct regmap *regmap;
struct device *dev;
bool need_restore;
unsigned int reg_save_array[PFUZE100_REG_SAVED_NUM];
struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR];
struct regulator_dev *regulators[PFUZE100_MAX_REGULATOR];
struct pfuze_regulator *pfuze_regulators;
@ -660,14 +671,95 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
}
}
if (of_get_property(client->dev.of_node, "fsl,lpsr-mode", NULL))
pfuze_chip->need_restore = true;
return 0;
}
static int pfuze_reg_save_restore(struct pfuze_chip *pfuze_chip, int start,
int end, int index, bool save)
{
int i, ret;
for (i = 0; i < end - start + 1; i++) {
if (save)
ret = regmap_read(pfuze_chip->regmap, start + i,
&pfuze_chip->reg_save_array[index + i]);
else
ret = regmap_write(pfuze_chip->regmap, start + i,
pfuze_chip->reg_save_array[index + i]);
if (ret)
return ret;
}
return index + i;
}
static int pfuze_suspend(struct device *dev)
{
struct pfuze_chip *pfuze_chip = i2c_get_clientdata(to_i2c_client(dev));
int index = 0;
if (pfuze_chip->need_restore) {
/* 0x20~0x40 */
index = pfuze_reg_save_restore(pfuze_chip, 0x20, 0x40, index, true);
if (index < 0)
goto err_ret;
/* 0x66~0x71 */
index = pfuze_reg_save_restore(pfuze_chip, 0x66, 0x71, ++index, true);
if (index < 0)
goto err_ret;
/* 0x7f */
index = pfuze_reg_save_restore(pfuze_chip, 0x7f, 0x7f, ++index, true);
if (index < 0)
goto err_ret;
}
return 0;
err_ret:
return index;
}
static int pfuze_resume(struct device *dev)
{
struct pfuze_chip *pfuze_chip = i2c_get_clientdata(to_i2c_client(dev));
int index = 0;
if (pfuze_chip->need_restore) {
/* 0x20~0x40 */
index = pfuze_reg_save_restore(pfuze_chip, 0x20, 0x40, index, false);
if (index < 0)
goto err_ret;
/* 0x66~0x71 */
index = pfuze_reg_save_restore(pfuze_chip, 0x66, 0x71, ++index, false);
if (index < 0)
goto err_ret;
/* 0x7f */
index = pfuze_reg_save_restore(pfuze_chip, 0x7f, 0x7f, ++index, false);
if (index < 0)
goto err_ret;
}
return 0;
err_ret:
return index;
}
static const struct dev_pm_ops pfuze_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pfuze_suspend, pfuze_resume)
};
static struct i2c_driver pfuze_driver = {
.id_table = pfuze_device_id,
.driver = {
.name = "pfuze100-regulator",
.of_match_table = pfuze_dt_ids,
.pm = &pfuze_pm_ops,
},
.probe = pfuze100_regulator_probe,
};