diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 38bcc87d6325..5f2a182bf355 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -257,6 +257,14 @@ static const struct rk808_reg_data rk805_pre_init_reg[] = { {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C}, }; +static struct rk808_reg_data rk805_suspend_reg[] = { + {RK805_BUCK3_CONFIG_REG, PWM_MODE_MSK, AUTO_PWM_MODE}, +}; + +static struct rk808_reg_data rk805_resume_reg[] = { + {RK805_BUCK3_CONFIG_REG, PWM_MODE_MSK, FPWM_MODE}, +}; + static const struct rk808_reg_data rk808_pre_init_reg[] = { { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, @@ -398,6 +406,18 @@ static const struct regmap_irq rk808_irqs[] = { }, }; +static struct rk808_reg_data rk816_suspend_reg[] = { + /* set bat 3.4v low and act irq */ + { RK816_VB_MON_REG, VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK, + RK816_VBAT_LOW_3V4 | EN_VBAT_LOW_IRQ }, +}; + +static struct rk808_reg_data rk816_resume_reg[] = { + /* set bat 3.0v low and act shutdown */ + { RK816_VB_MON_REG, VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK, + RK816_VBAT_LOW_3V0 | EN_VABT_LOW_SHUT_DOWN }, +}; + static const struct regmap_irq rk816_irqs[] = { /* INT_STS */ [RK816_IRQ_PWRON_FALL] = { @@ -438,6 +458,18 @@ static const struct regmap_irq rk816_irqs[] = { }, }; +static struct rk808_reg_data rk818_suspend_reg[] = { + /* set bat 3.4v low and act irq */ + { RK808_VB_MON_REG, VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK, + RK808_VBAT_LOW_3V4 | EN_VBAT_LOW_IRQ }, +}; + +static struct rk808_reg_data rk818_resume_reg[] = { + /* set bat 3.0v low and act shutdown */ + { RK808_VB_MON_REG, VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK, + RK808_VBAT_LOW_3V0 | EN_VABT_LOW_SHUT_DOWN }, +}; + static const struct regmap_irq rk818_irqs[] = { /* INT_STS */ [RK818_IRQ_VOUT_LO] = { @@ -638,6 +670,8 @@ static const struct regmap_irq_chip rk818_irq_chip = { }; static struct i2c_client *rk808_i2c_client; +static struct rk808_reg_data *suspend_reg, *resume_reg; +static int suspend_reg_num, resume_reg_num; static void rk808_pm_power_off(void) { @@ -1015,6 +1049,10 @@ static int rk808_probe(struct i2c_client *client, nr_cells = ARRAY_SIZE(rk805s); on_source = RK805_ON_SOURCE_REG; off_source = RK805_OFF_SOURCE_REG; + suspend_reg = rk805_suspend_reg; + suspend_reg_num = ARRAY_SIZE(rk805_suspend_reg); + resume_reg = rk805_resume_reg; + resume_reg_num = ARRAY_SIZE(rk805_resume_reg); break; case RK808_ID: rk808->regmap_cfg = &rk808_regmap_config; @@ -1034,6 +1072,10 @@ static int rk808_probe(struct i2c_client *client, nr_cells = ARRAY_SIZE(rk816s); on_source = RK816_ON_SOURCE_REG; off_source = RK816_OFF_SOURCE_REG; + suspend_reg = rk816_suspend_reg; + suspend_reg_num = ARRAY_SIZE(rk816_suspend_reg); + resume_reg = rk816_resume_reg; + resume_reg_num = ARRAY_SIZE(rk816_resume_reg); break; case RK818_ID: rk808->regmap_cfg = &rk818_regmap_config; @@ -1044,6 +1086,10 @@ static int rk808_probe(struct i2c_client *client, nr_cells = ARRAY_SIZE(rk818s); on_source = RK818_ON_SOURCE_REG; off_source = RK818_OFF_SOURCE_REG; + suspend_reg = rk818_suspend_reg; + suspend_reg_num = ARRAY_SIZE(rk818_suspend_reg); + resume_reg = rk818_resume_reg; + resume_reg_num = ARRAY_SIZE(rk818_resume_reg); break; case RK809_ID: case RK817_ID: @@ -1183,9 +1229,21 @@ static int rk808_remove(struct i2c_client *client) static int __maybe_unused rk8xx_suspend(struct device *dev) { struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev)); - int ret = 0; + int i, ret = 0; int value; + for (i = 0; i < suspend_reg_num; i++) { + ret = regmap_update_bits(rk808->regmap, + suspend_reg[i].addr, + suspend_reg[i].mask, + suspend_reg[i].value); + if (ret) { + dev_err(dev, "0x%x write err\n", + suspend_reg[i].addr); + return ret; + } + } + switch (rk808->variant) { case RK805_ID: ret = regmap_update_bits(rk808->regmap, @@ -1235,7 +1293,19 @@ static int __maybe_unused rk8xx_resume(struct device *dev) { struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev)); int value; - int ret = 0; + int i, ret = 0; + + for (i = 0; i < resume_reg_num; i++) { + ret = regmap_update_bits(rk808->regmap, + resume_reg[i].addr, + resume_reg[i].mask, + resume_reg[i].value); + if (ret) { + dev_err(dev, "0x%x write err\n", + resume_reg[i].addr); + return ret; + } + } switch (rk808->variant) { case RK809_ID: @@ -1273,7 +1343,7 @@ static int __maybe_unused rk8xx_resume(struct device *dev) return ret; } -static SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume); +SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume); static struct i2c_driver rk808_i2c_driver = { .driver = {