diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 4789507f325b..cbb5f2665f86 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1116,14 +1116,14 @@ config MFD_RC5T583 different functionality of the device. config MFD_RK808 - tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip" + tristate "Rockchip RK805/RK808/RK809/RK816/RK817/RK818 Power Management Chip" depends on I2C && OF select MFD_CORE select REGMAP_I2C select REGMAP_IRQ help If you say yes here you get support for the RK805, RK808, RK809, - RK817 and RK818 Power Management chips. + RK816, RK817, RK818 Power Management chips. This driver provides common support for accessing the device through I2C interface. The device supports multiple sub-devices including interrupts, RTC, LDO & DCDC regulators, and onkey. diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 7198e13655b8..b0e83c6cb8aa 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -929,11 +929,11 @@ config REGULATOR_RC5T583 outputs which can be controlled by i2c communication. config REGULATOR_RK808 - tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power regulators" + tristate "Rockchip RK805/RK808/RK809/RK816/RK817/RK818 Power regulators" depends on MFD_RK808 help Select this option to enable the power regulator of ROCKCHIP - PMIC RK805,RK809&RK817,RK808 and RK818. + PMIC RK805,RK809&RK817,RK808, RK816 and RK818. This driver supports the control of different power rails of device through regulator interface. The device supports multiple DCDC/LDO outputs which can be controlled by i2c communication. diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index e926c1a85846..4e9cd9da11f4 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -34,6 +34,11 @@ #define RK817_BOOST_VSEL_MASK 0x7 #define RK817_BUCK_VSEL_MASK 0x7f +#define RK816_DCDC_SLP_EN_REG_OFFSET 2 +#define RK816_SWITCH_SLP_EN_REG_OFFSET 1 +#define RK816_LDO1_4_SLP_EN_REG_OFFSET 1 +#define RK816_LDO5_6_SLP_EN_REG_OFFSET 2 + #define RK818_BUCK_VSEL_MASK 0x3f #define RK818_BUCK4_VSEL_MASK 0x1f #define RK818_LDO_VSEL_MASK 0x1f @@ -113,6 +118,11 @@ .ops = _ops, \ } +#define RK816_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _disval, _etime) \ + RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _emask, _disval, _etime, &rk808_reg_ops) + #define RK805_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, _etime) \ RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \ @@ -170,6 +180,17 @@ static const struct linear_range rk808_ldo3_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0), }; +static const struct linear_range rk816_buck_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(712500, 0, 59, 12500), /* 0.7125v - 1.45v */ + REGULATOR_LINEAR_RANGE(1800000, 60, 62, 200000),/* 1.8v - 2.2v */ + REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0), /* 2.3v - 2.3v */ +}; + +static const struct linear_range rk816_buck4_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0, 26, 100000), /* 0.8v - 3.4 */ + REGULATOR_LINEAR_RANGE(3500000, 27, 31, 0), /* 3.5v */ +}; + #define RK809_BUCK5_SEL_CNT (8) static const struct linear_range rk809_buck5_voltage_ranges[] = { @@ -287,6 +308,58 @@ static int rk808_buck1_2_i2c_set_voltage_sel(struct regulator_dev *rdev, return ret; } +#ifdef CONFIG_CLK_RK312X +extern void rkclk_cpuclk_div_setting(int div); +#else +static inline void rkclk_cpuclk_div_setting(int div) {} +#endif + +static int rk816_regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, + unsigned int sel) +{ + int ret, real_sel, delay = 100; + int rk816_type; + int id = rdev_get_id(rdev); + + regmap_read(rdev->regmap, RK816_CHIP_VER_REG, &rk816_type); + rk816_type &= RK816_CHIP_VERSION_MASK; + sel <<= ffs(rdev->desc->vsel_mask) - 1; + + if ((rk816_type != RK816_TYPE_ES2) && (id == 0)) { + if (sel > 23) + rkclk_cpuclk_div_setting(4); + else + rkclk_cpuclk_div_setting(2); + } + + do { + ret = regmap_update_bits(rdev->regmap, + rdev->desc->vsel_reg, + rdev->desc->vsel_mask, sel); + if (ret) + return ret; + + if (rk816_type == RK816_TYPE_ES2) { + ret = regmap_update_bits(rdev->regmap, + RK816_DCDC_EN_REG2, + RK816_BUCK_DVS_CONFIRM, + RK816_BUCK_DVS_CONFIRM); + if (ret) + return ret; + } + + regmap_read(rdev->regmap, + rdev->desc->vsel_reg, &real_sel); + real_sel &= rdev->desc->vsel_mask; + delay--; + } while ((sel != real_sel) && (delay > 0)); + + if ((rk816_type != RK816_TYPE_ES2) && (id == 0)) + rkclk_cpuclk_div_setting(1); + + return ret; +} + static int rk808_buck1_2_set_voltage_sel(struct regulator_dev *rdev, unsigned sel) { @@ -366,6 +439,11 @@ static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) RK808_RAMP_RATE_MASK, ramp_value); } +static int rk8xx_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + return rk808_set_ramp_delay(rdev, ramp_delay); +} + /* * RK817 RK809 */ @@ -448,9 +526,61 @@ static int rk805_set_suspend_disable(struct regulator_dev *rdev) 0); } +static int rk816_set_suspend_enable(struct regulator_dev *rdev) +{ + unsigned int reg, val; + + if (rdev->desc->id <= RK816_ID_DCDC4) { + reg = rdev->desc->enable_reg + + RK816_DCDC_SLP_EN_REG_OFFSET; + val = 1 << rdev->desc->id; + } else if ((rdev->desc->id > RK816_ID_DCDC4) && + (rdev->desc->id <= RK816_ID_LDO4)) { + reg = rdev->desc->enable_reg - + RK816_LDO1_4_SLP_EN_REG_OFFSET; + val = 1 << (rdev->desc->id - RK816_ID_LDO1); + } else { + reg = rdev->desc->enable_reg - + RK816_LDO5_6_SLP_EN_REG_OFFSET; + val = 1 << (rdev->desc->id - RK816_ID_LDO1); + } + + return regmap_update_bits(rdev->regmap, reg, + val, + val); +} + +static int rk816_set_suspend_disable(struct regulator_dev *rdev) +{ + unsigned int reg, val; + + if (rdev->desc->id <= RK816_ID_DCDC4) { + reg = rdev->desc->enable_reg + + RK816_DCDC_SLP_EN_REG_OFFSET; + val = 1 << rdev->desc->id; + } else if ((rdev->desc->id > RK816_ID_DCDC4) && + (rdev->desc->id <= RK816_ID_LDO4)) { + reg = rdev->desc->enable_reg - + RK816_LDO1_4_SLP_EN_REG_OFFSET; + val = 1 << (rdev->desc->id - RK816_ID_LDO1); + } else { + reg = rdev->desc->enable_reg - + RK816_LDO5_6_SLP_EN_REG_OFFSET; + val = 1 << (rdev->desc->id - RK816_ID_LDO1); + } + + return regmap_update_bits(rdev->regmap, reg, + val, + 0); +} + static int rk808_set_suspend_enable(struct regulator_dev *rdev) { unsigned int reg; + struct rk808 *rk808 = dev_get_drvdata(rdev->dev.parent); + + if (rk808->variant == RK816_ID) + return rk816_set_suspend_enable(rdev); reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET; @@ -462,6 +592,10 @@ static int rk808_set_suspend_enable(struct regulator_dev *rdev) static int rk808_set_suspend_disable(struct regulator_dev *rdev) { unsigned int reg; + struct rk808 *rk808 = dev_get_drvdata(rdev->dev.parent); + + if (rk808->variant == RK816_ID) + return rk816_set_suspend_disable(rdev); reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET; @@ -631,6 +765,24 @@ static const struct regulator_ops rk808_buck1_2_ops = { .set_suspend_disable = rk808_set_suspend_disable, }; +static const struct regulator_ops rk816_buck1_2_ops_ranges = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = rk816_regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_mode = rk8xx_set_mode, + .get_mode = rk8xx_get_mode, + .set_suspend_mode = rk8xx_set_suspend_mode, + .set_ramp_delay = rk8xx_set_ramp_delay, + .set_suspend_voltage = rk808_set_suspend_voltage_range, + .set_suspend_enable = rk808_set_suspend_enable, + .set_suspend_disable = rk808_set_suspend_disable, +}; + static const struct regulator_ops rk808_reg_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -892,6 +1044,101 @@ static const struct regulator_desc rk808_reg[] = { RK808_DCDC_EN_REG, BIT(6)), }; +static const struct regulator_desc rk816_reg[] = { + { + .name = "DCDC_REG1", + .supply_name = "vcc1", + .of_match = of_match_ptr("DCDC_REG1"), + .regulators_node = of_match_ptr("regulators"), + .id = RK816_ID_DCDC1, + .ops = &rk816_buck1_2_ops_ranges, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk816_buck_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk816_buck_voltage_ranges), + .vsel_reg = RK816_BUCK1_ON_VSEL_REG, + .vsel_mask = RK818_BUCK_VSEL_MASK, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(4) | BIT(0), + .enable_val = BIT(4) | BIT(0), + .disable_val = BIT(4), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG2", + .supply_name = "vcc2", + .of_match = of_match_ptr("DCDC_REG2"), + .regulators_node = of_match_ptr("regulators"), + .id = RK816_ID_DCDC2, + .ops = &rk816_buck1_2_ops_ranges, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk816_buck_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk816_buck_voltage_ranges), + .vsel_reg = RK816_BUCK2_ON_VSEL_REG, + .vsel_mask = RK818_BUCK_VSEL_MASK, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(5) | BIT(1), + .enable_val = BIT(5) | BIT(1), + .disable_val = BIT(5), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG3", + .supply_name = "vcc3", + .of_match = of_match_ptr("DCDC_REG3"), + .regulators_node = of_match_ptr("regulators"), + .id = RK818_ID_DCDC3, + .ops = &rk808_switch_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 1, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(6) | BIT(2), + .enable_val = BIT(6) | BIT(2), + .disable_val = BIT(6), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG4", + .supply_name = "vcc4", + .of_match = of_match_ptr("DCDC_REG4"), + .regulators_node = of_match_ptr("regulators"), + .id = RK816_ID_DCDC4, + .ops = &rk808_reg_ops_ranges, + .type = REGULATOR_VOLTAGE, + .n_voltages = 32, + .linear_ranges = rk816_buck4_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk816_buck4_voltage_ranges), + .vsel_reg = RK816_BUCK4_ON_VSEL_REG, + .vsel_mask = RK818_BUCK4_VSEL_MASK, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(7) | BIT(3), + .enable_val = BIT(7) | BIT(3), + .disable_val = BIT(7), + .of_map_mode = rk8xx_regulator_of_map_mode, + .owner = THIS_MODULE, + }, + + RK816_DESC(RK816_ID_LDO1, "LDO_REG1", "vcc5", 800, 3400, 100, + RK816_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, ENABLE_MASK(0), DISABLE_VAL(0), 400), + RK816_DESC(RK816_ID_LDO2, "LDO_REG2", "vcc5", 800, 3400, 100, + RK816_LDO2_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, ENABLE_MASK(1), DISABLE_VAL(1), 400), + RK816_DESC(RK816_ID_LDO3, "LDO_REG3", "vcc5", 800, 3400, 100, + RK816_LDO3_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, ENABLE_MASK(2), DISABLE_VAL(2), 400), + RK816_DESC(RK816_ID_LDO4, "LDO_REG4", "vcc6", 800, 3400, 100, + RK816_LDO4_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, ENABLE_MASK(3), DISABLE_VAL(3), 400), + RK816_DESC(RK816_ID_LDO5, "LDO_REG5", "vcc6", 800, 3400, 100, + RK816_LDO5_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG2, ENABLE_MASK(0), DISABLE_VAL(0), 400), + RK816_DESC(RK816_ID_LDO6, "LDO_REG6", "vcc6", 800, 3400, 100, + RK816_LDO6_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG2, ENABLE_MASK(1), DISABLE_VAL(1), 400), +}; + static const struct regulator_desc rk809_reg[] = { { .name = "DCDC_REG1", @@ -1331,6 +1578,10 @@ static int rk808_regulator_probe(struct platform_device *pdev) regulators = rk809_reg; nregulators = RK809_NUM_REGULATORS; break; + case RK816_ID: + regulators = rk816_reg; + nregulators = RK816_NUM_REGULATORS; + break; case RK817_ID: regulators = rk817_reg; nregulators = RK817_NUM_REGULATORS; @@ -1372,7 +1623,7 @@ static struct platform_driver rk808_regulator_driver = { module_platform_driver(rk808_regulator_driver); -MODULE_DESCRIPTION("regulator driver for the RK805/RK808/RK818 series PMICs"); +MODULE_DESCRIPTION("regulator driver for the RK805/RK808/RK816/RK818 series PMICs"); MODULE_AUTHOR("Tony xie "); MODULE_AUTHOR("Chris Zhong "); MODULE_AUTHOR("Zhang Qing "); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 33e4ecd6c665..fc654551bf2f 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -375,11 +375,11 @@ config RTC_DRV_MAX77686 will be called rtc-max77686. config RTC_DRV_RK808 - tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC" + tristate "Rockchip RK805/RK808/RK809/RK816/RK817/RK818 RTC" depends on MFD_RK808 help If you say yes here you will get support for the - RTC of RK805, RK809 and RK817, RK808 and RK818 PMIC. + RTC of RK805, RK809 and RK817, RK808, RK816 and RK818 PMIC. This driver can also be built as a module. If so, the module will be called rk808-rtc.