mirror of
https://github.com/brain-hackers/linux-brain.git
synced 2024-06-09 23:36:23 +09:00
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:
parent
add090516f
commit
4aa2a2a928
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user