diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index 247f12df8974..93154c9c98dd 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -1147,6 +1147,143 @@ static int pca9450_i2c_restart_handler(struct sys_off_data *data) return 0; } +static int pca9450_of_init(struct pca9450 *pca9450) +{ + struct i2c_client *i2c = container_of(pca9450->dev, struct i2c_client, dev); + int ret; + unsigned int val; + unsigned int reset_ctrl; + unsigned int rstb_deb_ctrl; + unsigned int t_on_deb, t_off_deb; + unsigned int t_on_step, t_off_step; + unsigned int t_restart; + + if (of_property_read_bool(i2c->dev.of_node, "nxp,wdog_b-warm-reset")) + reset_ctrl = WDOG_B_CFG_WARM; + else + reset_ctrl = WDOG_B_CFG_COLD_LDO12; + + /* Set reset behavior on assertion of WDOG_B signal */ + ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL, + WDOG_B_CFG_MASK, reset_ctrl); + if (ret) + return dev_err_probe(&i2c->dev, ret, "Failed to set WDOG_B reset behavior\n"); + + ret = of_property_read_u32(i2c->dev.of_node, "npx,pmic-rst-b-debounce-ms", &val); + if (ret == -EINVAL) + rstb_deb_ctrl = T_PMIC_RST_DEB_50MS; + else if (ret) + return ret; + else { + switch (val) { + case 10: rstb_deb_ctrl = T_PMIC_RST_DEB_10MS; break; + case 50: rstb_deb_ctrl = T_PMIC_RST_DEB_50MS; break; + case 100: rstb_deb_ctrl = T_PMIC_RST_DEB_100MS; break; + case 500: rstb_deb_ctrl = T_PMIC_RST_DEB_500MS; break; + case 1000: rstb_deb_ctrl = T_PMIC_RST_DEB_1S; break; + case 2000: rstb_deb_ctrl = T_PMIC_RST_DEB_2S; break; + case 4000: rstb_deb_ctrl = T_PMIC_RST_DEB_4S; break; + case 8000: rstb_deb_ctrl = T_PMIC_RST_DEB_8S; break; + default: return -EINVAL; + } + } + ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL, + T_PMIC_RST_DEB_MASK, rstb_deb_ctrl); + if (ret) + return dev_err_probe(&i2c->dev, ret, "Failed to set PMIC_RST_B debounce time\n"); + + ret = of_property_read_u32(i2c->dev.of_node, "nxp,pmic-on-req-on-debounce-us", &val); + if (ret == -EINVAL) + t_on_deb = T_ON_DEB_20MS; + else if (ret) + return ret; + else { + switch (val) { + case 120: t_on_deb = T_ON_DEB_120US; break; + case 20000: t_on_deb = T_ON_DEB_20MS; break; + case 100000: t_on_deb = T_ON_DEB_100MS; break; + case 750000: t_on_deb = T_ON_DEB_750MS; break; + default: return -EINVAL; + } + } + + ret = of_property_read_u32(i2c->dev.of_node, "nxp,pmic-on-req-off-debounce-us", &val); + if (ret == -EINVAL) + t_off_deb = T_OFF_DEB_120US; + else if (ret) + return ret; + else { + switch (val) { + case 120: t_off_deb = T_OFF_DEB_120US; break; + case 2000: t_off_deb = T_OFF_DEB_2MS; break; + default: return -EINVAL; + } + } + + ret = of_property_read_u32(i2c->dev.of_node, "nxp,power-on-step-ms", &val); + if (ret == -EINVAL) + t_on_step = T_ON_STEP_2MS; + else if (ret) + return ret; + else { + switch (val) { + case 1: t_on_step = T_ON_STEP_1MS; break; + case 2: t_on_step = T_ON_STEP_2MS; break; + case 4: t_on_step = T_ON_STEP_4MS; break; + case 8: t_on_step = T_ON_STEP_8MS; break; + default: return -EINVAL; + } + } + + ret = of_property_read_u32(i2c->dev.of_node, "nxp,power-down-step-ms", &val); + if (ret == -EINVAL) + t_off_step = T_OFF_STEP_8MS; + else if (ret) + return ret; + else { + switch (val) { + case 2: t_off_step = T_OFF_STEP_2MS; break; + case 4: t_off_step = T_OFF_STEP_4MS; break; + case 8: t_off_step = T_OFF_STEP_8MS; break; + case 16: t_off_step = T_OFF_STEP_16MS; break; + default: return -EINVAL; + } + } + + ret = of_property_read_u32(i2c->dev.of_node, "nxp,restart-ms", &val); + if (ret == -EINVAL) + t_restart = T_RESTART_250MS; + else if (ret) + return ret; + else { + switch (val) { + case 250: t_restart = T_RESTART_250MS; break; + case 500: t_restart = T_RESTART_500MS; break; + default: return -EINVAL; + } + } + + ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_PWRCTRL, + T_ON_DEB_MASK | T_OFF_DEB_MASK | T_ON_STEP_MASK | + T_OFF_STEP_MASK | T_RESTART_MASK, + t_on_deb | t_off_deb | t_on_step | + t_off_step | t_restart); + if (ret) + return dev_err_probe(&i2c->dev, ret, + "Failed to set PWR_CTRL debounce configuration\n"); + + if (of_property_read_bool(i2c->dev.of_node, "nxp,i2c-lt-enable")) { + /* Enable I2C Level Translator */ + ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_CONFIG2, + I2C_LT_MASK, I2C_LT_ON_STANDBY_RUN); + if (ret) + return dev_err_probe(&i2c->dev, ret, + "Failed to enable I2C level translator\n"); + } + + return 0; +} + static int pca9450_i2c_probe(struct i2c_client *i2c) { enum pca9450_chip_type type = (unsigned int)(uintptr_t) @@ -1156,7 +1293,6 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) struct regulator_dev *ldo5; struct pca9450 *pca9450; unsigned int device_id, i; - unsigned int reset_ctrl; int ret; pca9450 = devm_kzalloc(&i2c->dev, sizeof(struct pca9450), GFP_KERNEL); @@ -1254,25 +1390,9 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) if (ret) return dev_err_probe(&i2c->dev, ret, "Failed to clear PRESET_EN bit\n"); - if (of_property_read_bool(i2c->dev.of_node, "nxp,wdog_b-warm-reset")) - reset_ctrl = WDOG_B_CFG_WARM; - else - reset_ctrl = WDOG_B_CFG_COLD_LDO12; - - /* Set reset behavior on assertion of WDOG_B signal */ - ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL, - WDOG_B_CFG_MASK, reset_ctrl); + ret = pca9450_of_init(pca9450); if (ret) - return dev_err_probe(&i2c->dev, ret, "Failed to set WDOG_B reset behavior\n"); - - if (of_property_read_bool(i2c->dev.of_node, "nxp,i2c-lt-enable")) { - /* Enable I2C Level Translator */ - ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_CONFIG2, - I2C_LT_MASK, I2C_LT_ON_STANDBY_RUN); - if (ret) - return dev_err_probe(&i2c->dev, ret, - "Failed to enable I2C level translator\n"); - } + return dev_err_probe(&i2c->dev, ret, "Unable to parse OF data\n"); /* * For LDO5 we need to be able to check the status of the SD_VSEL input in diff --git a/include/linux/regulator/pca9450.h b/include/linux/regulator/pca9450.h index 85b4fecc10d8..0df8b3c48082 100644 --- a/include/linux/regulator/pca9450.h +++ b/include/linux/regulator/pca9450.h @@ -223,12 +223,44 @@ enum { #define IRQ_THERM_105 0x02 #define IRQ_THERM_125 0x01 +/* PCA9450_REG_PWRCTRL bits */ +#define T_ON_DEB_MASK 0xC0 +#define T_ON_DEB_120US (0 << 6) +#define T_ON_DEB_20MS (1 << 6) +#define T_ON_DEB_100MS (2 << 6) +#define T_ON_DEB_750MS (3 << 6) +#define T_OFF_DEB_MASK 0x20 +#define T_OFF_DEB_120US (0 << 5) +#define T_OFF_DEB_2MS (1 << 5) +#define T_ON_STEP_MASK 0x18 +#define T_ON_STEP_1MS (0 << 3) +#define T_ON_STEP_2MS (1 << 3) +#define T_ON_STEP_4MS (2 << 3) +#define T_ON_STEP_8MS (3 << 3) +#define T_OFF_STEP_MASK 0x06 +#define T_OFF_STEP_2MS (0 << 1) +#define T_OFF_STEP_4MS (1 << 1) +#define T_OFF_STEP_8MS (2 << 1) +#define T_OFF_STEP_16MS (3 << 1) +#define T_RESTART_MASK 0x01 +#define T_RESTART_250MS 0 +#define T_RESTART_500MS 1 + /* PCA9450_REG_RESET_CTRL bits */ #define WDOG_B_CFG_MASK 0xC0 #define WDOG_B_CFG_NONE 0x00 #define WDOG_B_CFG_WARM 0x40 #define WDOG_B_CFG_COLD_LDO12 0x80 #define WDOG_B_CFG_COLD 0xC0 +#define T_PMIC_RST_DEB_MASK 0x07 +#define T_PMIC_RST_DEB_10MS 0x00 +#define T_PMIC_RST_DEB_50MS 0x01 +#define T_PMIC_RST_DEB_100MS 0x02 +#define T_PMIC_RST_DEB_500MS 0x03 +#define T_PMIC_RST_DEB_1S 0x04 +#define T_PMIC_RST_DEB_2S 0x05 +#define T_PMIC_RST_DEB_4S 0x06 +#define T_PMIC_RST_DEB_8S 0x07 /* PCA9450_REG_CONFIG2 bits */ #define I2C_LT_MASK 0x03