diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 11841f4b7b2b..df375e2601da 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -997,14 +997,14 @@ config MFD_RC5T583 different functionality of the device. config MFD_RK808 - tristate "Rockchip RK805/RK808/RK818 Power Management Chip" + tristate "Rockchip RK805/RK808/RK816/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 and RK818 - Power Management chips. + If you say yes here you get support for the RK805, RK808 , RK816 + and 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/mfd/rk808.c b/drivers/mfd/rk808.c index b6f18e14f50f..b1f2c1620b6d 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -62,6 +62,40 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) return false; } +static bool rk818_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* + * Notes: + * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but + * we don't use that feature. It's better to cache. + * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since + * bits are cleared in case when we shutoff anyway, but better safe. + */ + + switch (reg) { + case RK808_SECONDS_REG ... RK808_WEEKS_REG: + case RK808_RTC_STATUS_REG: + case RK808_VB_MON_REG: + case RK808_THERMAL_REG: + case RK808_DCDC_EN_REG: + case RK808_LDO_EN_REG: + case RK808_DCDC_UV_STS_REG: + case RK808_LDO_UV_STS_REG: + case RK808_DCDC_PG_REG: + case RK808_LDO_PG_REG: + case RK808_DEVCTRL_REG: + case RK808_INT_STS_REG1: + case RK808_INT_STS_REG2: + case RK808_INT_STS_MSK_REG1: + case RK808_INT_STS_MSK_REG2: + case RK816_INT_STS_REG1: + case RK816_INT_STS_MSK_REG1: + return true; + } + + return false; +} + static const struct regmap_config rk818_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -86,6 +120,14 @@ static const struct regmap_config rk808_regmap_config = { .volatile_reg = rk808_is_volatile_reg, }; +static const struct regmap_config rk816_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK816_DATA18_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk818_is_volatile_reg, +}; + static struct resource rtc_resources[] = { { .start = RK808_IRQ_RTC_ALARM, @@ -94,6 +136,14 @@ static struct resource rtc_resources[] = { } }; +static struct resource rk816_rtc_resources[] = { + { + .start = RK816_IRQ_RTC_ALARM, + .end = RK816_IRQ_RTC_ALARM, + .flags = IORESOURCE_IRQ, + } +}; + static struct resource rk805_key_resources[] = { { .start = RK805_IRQ_PWRON_FALL, @@ -107,6 +157,19 @@ static struct resource rk805_key_resources[] = { } }; +static struct resource rk816_pwrkey_resources[] = { + { + .start = RK816_IRQ_PWRON_RISE, + .end = RK816_IRQ_PWRON_RISE, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK816_IRQ_PWRON_FALL, + .end = RK816_IRQ_PWRON_FALL, + .flags = IORESOURCE_IRQ, + }, +}; + static const struct mfd_cell rk805s[] = { { .name = "rk808-clkout", }, { .name = "rk808-regulator", }, @@ -132,6 +195,23 @@ static const struct mfd_cell rk808s[] = { }, }; +static const struct mfd_cell rk816s[] = { + { .name = "rk808-clkout", }, + { .name = "rk808-regulator", }, + { .name = "rk8xx-gpio", }, + { .name = "rk816-battery", .of_compatible = "rk816-battery", }, + { + .name = "rk8xx-pwrkey", + .num_resources = ARRAY_SIZE(rk816_pwrkey_resources), + .resources = &rk816_pwrkey_resources[0], + }, + { + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rk816_rtc_resources), + .resources = &rk816_rtc_resources[0], + }, +}; + static const struct mfd_cell rk818s[] = { { .name = "rk808-clkout", }, { .name = "rk808-regulator", }, @@ -169,6 +249,33 @@ static const struct rk808_reg_data rk808_pre_init_reg[] = { VB_LO_SEL_3500MV }, }; +static const struct rk808_reg_data rk816_pre_init_reg[] = { + /* buck4 Max ILMIT*/ + { RK816_BUCK4_CONFIG_REG, REG_WRITE_MSK, BUCK4_MAX_ILIMIT }, + /* hotdie temperature: 105c*/ + { RK816_THERMAL_REG, REG_WRITE_MSK, TEMP105C }, + /* set buck 12.5mv/us */ + { RK816_BUCK1_CONFIG_REG, BUCK_RATE_MSK, BUCK_RATE_12_5MV_US }, + { RK816_BUCK2_CONFIG_REG, BUCK_RATE_MSK, BUCK_RATE_12_5MV_US }, + /* enable RTC_PERIOD & RTC_ALARM int */ + { RK816_INT_STS_MSK_REG2, REG_WRITE_MSK, RTC_PERIOD_ALARM_INT_EN }, + /* set bat 3.0 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 }, + /* enable PWRON rising/faling int */ + { RK816_INT_STS_MSK_REG1, REG_WRITE_MSK, RK816_PWRON_FALL_RISE_INT_EN }, + /* enable PLUG IN/OUT int */ + { RK816_INT_STS_MSK_REG3, REG_WRITE_MSK, PLUGIN_OUT_INT_EN }, + /* clear int flags */ + { RK816_INT_STS_REG1, REG_WRITE_MSK, ALL_INT_FLAGS_ST }, + { RK816_INT_STS_REG2, REG_WRITE_MSK, ALL_INT_FLAGS_ST }, + { RK816_INT_STS_REG3, REG_WRITE_MSK, ALL_INT_FLAGS_ST }, + { RK816_DCDC_EN_REG2, BOOST_EN_MASK, BOOST_DISABLE }, + /* set write mask bit 1, otherwise 'is_enabled()' get wrong status */ + { RK816_LDO_EN_REG1, REGS_WMSK, REGS_WMSK }, + { RK816_LDO_EN_REG2, REGS_WMSK, REGS_WMSK }, +}; + static const struct rk808_reg_data rk818_pre_init_reg[] = { /* improve efficiency */ { RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA }, @@ -265,6 +372,46 @@ static const struct regmap_irq rk808_irqs[] = { }, }; +static const struct regmap_irq rk816_irqs[] = { + /* INT_STS */ + [RK816_IRQ_PWRON_FALL] = { + .mask = RK816_IRQ_PWRON_FALL_MSK, + .reg_offset = 0, + }, + [RK816_IRQ_PWRON_RISE] = { + .mask = RK816_IRQ_PWRON_RISE_MSK, + .reg_offset = 0, + }, + [RK816_IRQ_VB_LOW] = { + .mask = RK816_IRQ_VB_LOW_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_PWRON] = { + .mask = RK816_IRQ_PWRON_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_PWRON_LP] = { + .mask = RK816_IRQ_PWRON_LP_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_HOTDIE] = { + .mask = RK816_IRQ_HOTDIE_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_RTC_ALARM] = { + .mask = RK816_IRQ_RTC_ALARM_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_RTC_PERIOD] = { + .mask = RK816_IRQ_RTC_PERIOD_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_USB_OV] = { + .mask = RK816_IRQ_USB_OV_MSK, + .reg_offset = 1, + }, +}; + static const struct regmap_irq rk818_irqs[] = { /* INT_STS */ [RK818_IRQ_VOUT_LO] = { @@ -358,6 +505,18 @@ static const struct regmap_irq_chip rk808_irq_chip = { .init_ack_masked = true, }; +static struct regmap_irq_chip rk816_irq_chip = { + .name = "rk816", + .irqs = rk816_irqs, + .num_irqs = ARRAY_SIZE(rk816_irqs), + .num_regs = 2, + .irq_reg_stride = 3, + .status_base = RK816_INT_STS_REG1, + .mask_base = RK816_INT_STS_MSK_REG1, + .ack_base = RK816_INT_STS_REG1, + .init_ack_masked = true, +}; + static const struct regmap_irq_chip rk818_irq_chip = { .name = "rk818", .irqs = rk818_irqs, @@ -408,6 +567,24 @@ static void rk808_device_shutdown(void) dev_err(&rk808_i2c_client->dev, "power off error!\n"); } +static void rk816_device_shutdown(void) +{ + int ret; + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + + if (!rk808) { + dev_warn(&rk808_i2c_client->dev, + "have no rk805, so do nothing here\n"); + return; + } + + ret = regmap_update_bits(rk808->regmap, + RK816_DEV_CTRL_REG, + DEV_OFF, DEV_OFF); + if (ret) + dev_err(&rk808_i2c_client->dev, "power off error!\n"); +} + static void rk818_device_shutdown(void) { int ret; @@ -429,6 +606,7 @@ static void rk818_device_shutdown(void) static const struct of_device_id rk808_of_match[] = { { .compatible = "rockchip,rk805" }, { .compatible = "rockchip,rk808" }, + { .compatible = "rockchip,rk816" }, { .compatible = "rockchip,rk818" }, { }, }; @@ -489,6 +667,15 @@ static int rk808_probe(struct i2c_client *client, nr_cells = ARRAY_SIZE(rk808s); pm_pwroff_fn = rk808_device_shutdown; break; + case RK816_ID: + rk808->regmap_cfg = &rk816_regmap_config; + rk808->regmap_irq_chip = &rk816_irq_chip; + pre_init_reg = rk816_pre_init_reg; + nr_pre_init_regs = ARRAY_SIZE(rk816_pre_init_reg); + cells = rk816s; + nr_cells = ARRAY_SIZE(rk816s); + pm_pwroff_fn = rk816_device_shutdown; + break; case RK818_ID: rk808->regmap_cfg = &rk818_regmap_config; rk808->regmap_irq_chip = &rk818_irq_chip; @@ -574,6 +761,7 @@ static int rk808_remove(struct i2c_client *client) static const struct i2c_device_id rk808_ids[] = { { "rk805" }, { "rk808" }, + { "rk816" }, { "rk818" }, { }, }; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 1a55a7859a62..4d21b30f9b41 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -741,11 +741,11 @@ config REGULATOR_RC5T583 outputs which can be controlled by i2c communication. config REGULATOR_RK808 - tristate "Rockchip RK805/RK808/RK818 Power regulators" + tristate "Rockchip RK805/RK808/RK816/RK818 Power regulators" depends on MFD_RK808 help Select this option to enable the power regulator of ROCKCHIP - PMIC RK805,RK808 and RK818. + PMIC RK805,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 213b68743cc8..3648f351a99d 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -36,6 +36,11 @@ #define RK808_BUCK4_VSEL_MASK 0xf #define RK808_LDO_VSEL_MASK 0x1f +#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 @@ -107,6 +112,28 @@ .ops = &rk808_reg_ops, \ } +#define RK816_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _enval, _disval, _etime) \ + [_id] = { \ + .name = (_match), \ + .supply_name = (_supply), \ + .of_match = of_match_ptr(_match), \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE, \ + .id = (_id), \ + .n_voltages = (((_max) - (_min)) / (_step) + 1), \ + .owner = THIS_MODULE, \ + .min_uV = (_min) * 1000, \ + .uV_step = (_step) * 1000, \ + .vsel_reg = (_vreg), \ + .vsel_mask = (_vmask), \ + .enable_reg = (_ereg), \ + .enable_mask = (_emask), \ + .enable_val = (_enval), \ + .disable_val = (_disval), \ + .enable_time = (_etime), \ + .ops = &rk808_reg_ops, \ + } #define RK8XX_DESC_SWITCH(_id, _match, _supply, _ereg, _emask) \ [_id] = { \ .name = (_match), \ @@ -138,6 +165,27 @@ static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0), }; +static const struct regulator_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 regulator_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 */ +}; + +static unsigned int rk8xx_regulator_of_map_mode(unsigned int mode) +{ + if (mode == 1) + return REGULATOR_MODE_FAST; + if (mode == 2) + return REGULATOR_MODE_NORMAL; + + return -EINVAL; +} + static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev) { struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); @@ -210,6 +258,58 @@ static int rk808_buck1_2_i2c_set_voltage_sel(struct regulator_dev *rdev, return ret; } +#ifdef CONFIG_CPU_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) { @@ -363,6 +463,59 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev) rdev->desc->enable_mask); } +static int rk8xx_set_suspend_mode(struct regulator_dev *rdev, unsigned int mode) +{ + unsigned int reg; + + reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET; + + switch (mode) { + case REGULATOR_MODE_FAST: + return regmap_update_bits(rdev->regmap, reg, + PWM_MODE_MSK, FPWM_MODE); + case REGULATOR_MODE_NORMAL: + return regmap_update_bits(rdev->regmap, reg, + PWM_MODE_MSK, AUTO_PWM_MODE); + default: + pr_err("do not support this mode\n"); + return -EINVAL; + } + + return 0; +} + +static int rk8xx_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + switch (mode) { + case REGULATOR_MODE_FAST: + return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, + PWM_MODE_MSK, FPWM_MODE); + case REGULATOR_MODE_NORMAL: + return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, + PWM_MODE_MSK, AUTO_PWM_MODE); + default: + pr_err("do not support this mode\n"); + return -EINVAL; + } + + return 0; +} + +static unsigned int rk8xx_get_mode(struct regulator_dev *rdev) +{ + unsigned int val; + int err; + + err = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); + if (err) + return err; + + if (val & FPWM_MODE) + return REGULATOR_MODE_FAST; + else + return REGULATOR_MODE_NORMAL; +} + static struct regulator_ops rk805_reg_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -433,6 +586,42 @@ static struct regulator_ops rk808_switch_ops = { .set_suspend_disable = rk808_set_suspend_disable, }; +static struct regulator_ops rk8xx_buck_ops_range = { + .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 = 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 = rk808_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 struct regulator_ops rk816_buck_ops_range = { + .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 = rk808_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_desc rk805_reg[] = { { .name = "DCDC_REG1", @@ -589,6 +778,106 @@ 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_buck_ops_range, + .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_buck_ops_range, + .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 = &rk8xx_buck_ops_range, + .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, BIT(4) | BIT(0), BIT(4) | BIT(0), + BIT(4), 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, BIT(5) | BIT(1), BIT(5) | BIT(1), + BIT(5), 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, BIT(6) | BIT(2), BIT(6) | BIT(2), + BIT(6), 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, BIT(7) | BIT(3), BIT(7) | BIT(3), + BIT(7), 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, BIT(4) | BIT(0), BIT(4) | BIT(0), + BIT(4), 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, BIT(5) | BIT(1), BIT(5) | BIT(1), + BIT(5), 400), +}; + static const struct regulator_desc rk818_reg[] = { { .name = "DCDC_REG1", @@ -759,6 +1048,10 @@ static int rk808_regulator_probe(struct platform_device *pdev) regulators = rk808_reg; nregulators = RK808_NUM_REGULATORS; break; + case RK816_ID: + regulators = rk816_reg; + nregulators = RK816_NUM_REGULATORS; + break; case RK818_ID: regulators = rk818_reg; nregulators = RK818_NUM_REGULATORS; @@ -796,7 +1089,7 @@ static struct platform_driver rk808_regulator_driver = { module_platform_driver(rk808_regulator_driver); -MODULE_DESCRIPTION("regulator driver for the RK808/RK818 series PMICs"); +MODULE_DESCRIPTION("regulator driver for the RK808/RK816/RK818 series PMICs"); MODULE_AUTHOR("Chris Zhong "); MODULE_AUTHOR("Zhang Qing "); MODULE_AUTHOR("Wadim Egorov "); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 7d7be60a2413..717bc92ece30 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -362,11 +362,11 @@ config RTC_DRV_MAX77686 will be called rtc-max77686. config RTC_DRV_RK808 - tristate "Rockchip RK805/RK808/RK818 RTC" + tristate "Rockchip RK805/RK808/RK816/RK818 RTC" depends on MFD_RK808 help If you say yes here you will get support for the - RTC of RK805, RK808 and RK818 PMIC. + RTC of RK805, RK808 , RK816 and RK818 PMIC. This driver can also be built as a module. If so, the module will be called rk808-rtc. diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 088b514f426f..dbfafdeac13e 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -121,6 +121,234 @@ enum rk808_reg { #define RK808_INT_STS_MSK_REG2 0x4f #define RK808_IO_POL_REG 0x50 +/* RK816 */ +enum rk816_reg { + RK816_ID_DCDC1, + RK816_ID_DCDC2, + RK816_ID_DCDC3, + RK816_ID_DCDC4, + RK816_ID_LDO1, + RK816_ID_LDO2, + RK816_ID_LDO3, + RK816_ID_LDO4, + RK816_ID_LDO5, + RK816_ID_LDO6, +}; + +/*VERSION REGISTER*/ +#define RK816_CHIP_NAME_REG 0x17 +#define RK816_CHIP_VER_REG 0x18 +#define RK816_OTP_VER_REG 0x19 +#define RK816_NUM_REGULATORS 10 + +/*POWER ON/OFF REGISTER*/ +#define RK816_VB_MON_REG 0x21 +#define RK816_THERMAL_REG 0x22 +#define RK816_PWRON_LP_INT_TIME_REG 0x47 +#define RK816_PWRON_DB_REG 0x48 +#define RK816_DEV_CTRL_REG 0x4B +#define RK816_ON_SOURCE_REG 0xAE +#define RK816_OFF_SOURCE_REG 0xAF + +/*POWER CHANNELS ENABLE REGISTER*/ +#define RK816_DCDC_EN_REG1 0x23 +#define RK816_DCDC_EN_REG2 0x24 +#define RK816_SLP_DCDC_EN_REG 0x25 +#define RK816_SLP_LDO_EN_REG 0x26 +#define RK816_LDO_EN_REG1 0x27 +#define RK816_LDO_EN_REG2 0x28 + +/*BUCK AND LDO CONFIG REGISTER*/ +#define RK816_BUCK1_CONFIG_REG 0x2E +#define RK816_BUCK1_ON_VSEL_REG 0x2F +#define RK816_BUCK1_SLP_VSEL_REG 0x30 +#define RK816_BUCK2_CONFIG_REG 0x32 +#define RK816_BUCK2_ON_VSEL_REG 0x33 +#define RK816_BUCK2_SLP_VSEL_REG 0x34 +#define RK816_BUCK3_CONFIG_REG 0x36 +#define RK816_BUCK4_CONFIG_REG 0x37 +#define RK816_BUCK4_ON_VSEL_REG 0x38 +#define RK816_BUCK4_SLP_VSEL_REG 0x39 +#define RK816_LDO1_ON_VSEL_REG 0x3B +#define RK816_LDO1_SLP_VSEL_REG 0x3C +#define RK816_LDO2_ON_VSEL_REG 0x3D +#define RK816_LDO2_SLP_VSEL_REG 0x3E +#define RK816_LDO3_ON_VSEL_REG 0x3F +#define RK816_LDO3_SLP_VSEL_REG 0x40 +#define RK816_LDO4_ON_VSEL_REG 0x41 +#define RK816_LDO4_SLP_VSEL_REG 0x42 +#define RK816_LDO5_ON_VSEL_REG 0x43 +#define RK816_LDO5_SLP_VSEL_REG 0x44 +#define RK816_LDO6_ON_VSEL_REG 0x45 +#define RK816_LDO6_SLP_VSEL_REG 0x46 + +/*CHARGER BOOST AND OTG REGISTER*/ +#define RK816_OTG_BUCK_LDO_CONFIG_REG 0x2A +#define RK816_CHRG_CONFIG_REG 0x2B +#define RK816_BOOST_ON_VESL_REG 0x54 +#define RK816_BOOST_SLP_VSEL_REG 0x55 +#define RK816_CHRG_BOOST_CONFIG_REG 0x9A +#define RK816_SUP_STS_REG 0xA0 +#define RK816_USB_CTRL_REG 0xA1 +#define RK816_CHRG_CTRL_REG1 0xA3 +#define RK816_CHRG_CTRL_REG2 0xA4 +#define RK816_CHRG_CTRL_REG3 0xA5 +#define RK816_BAT_CTRL_REG 0xA6 +#define RK816_BAT_HTS_TS_REG 0xA8 +#define RK816_BAT_LTS_TS_REG 0xA9 + +#define RK816_TS_CTRL_REG 0xAC +#define RK816_ADC_CTRL_REG 0xAD +#define RK816_GGCON_REG 0xB0 +#define RK816_GGSTS_REG 0xB1 +#define RK816_ZERO_CUR_ADC_REGH 0xB2 +#define RK816_ZERO_CUR_ADC_REGL 0xB3 +#define RK816_GASCNT_CAL_REG3 0xB4 +#define RK816_GASCNT_CAL_REG2 0xB5 +#define RK816_GASCNT_CAL_REG1 0xB6 +#define RK816_GASCNT_CAL_REG0 0xB7 +#define RK816_GASCNT_REG3 0xB8 +#define RK816_GASCNT_REG2 0xB9 +#define RK816_GASCNT_REG1 0xBA +#define RK816_GASCNT_REG0 0xBB +#define RK816_BAT_CUR_AVG_REGH 0xBC +#define RK816_BAT_CUR_AVG_REGL 0xBD +#define RK816_TS_ADC_REGH 0xBE +#define RK816_TS_ADC_REGL 0xBF +#define RK816_USB_ADC_REGH 0xC0 +#define RK816_USB_ADC_REGL 0xC1 +#define RK816_BAT_OCV_REGH 0xC2 +#define RK816_BAT_OCV_REGL 0xC3 +#define RK816_BAT_VOL_REGH 0xC4 +#define RK816_BAT_VOL_REGL 0xC5 +#define RK816_RELAX_ENTRY_THRES_REGH 0xC6 +#define RK816_RELAX_ENTRY_THRES_REGL 0xC7 +#define RK816_RELAX_EXIT_THRES_REGH 0xC8 +#define RK816_RELAX_EXIT_THRES_REGL 0xC9 +#define RK816_RELAX_VOL1_REGH 0xCA +#define RK816_RELAX_VOL1_REGL 0xCB +#define RK816_RELAX_VOL2_REGH 0xCC +#define RK816_RELAX_VOL2_REGL 0xCD +#define RK816_RELAX_CUR1_REGH 0xCE +#define RK816_RELAX_CUR1_REGL 0xCF +#define RK816_RELAX_CUR2_REGH 0xD0 +#define RK816_RELAX_CUR2_REGL 0xD1 +#define RK816_CAL_OFFSET_REGH 0xD2 +#define RK816_CAL_OFFSET_REGL 0xD3 +#define RK816_NON_ACT_TIMER_CNT_REG 0xD4 +#define RK816_VCALIB0_REGH 0xD5 +#define RK816_VCALIB0_REGL 0xD6 +#define RK816_VCALIB1_REGH 0xD7 +#define RK816_VCALIB1_REGL 0xD8 +#define RK816_FCC_GASCNT_REG3 0xD9 +#define RK816_FCC_GASCNT_REG2 0xDA +#define RK816_FCC_GASCNT_REG1 0xDB +#define RK816_FCC_GASCNT_REG0 0xDC +#define RK816_IOFFSET_REGH 0xDD +#define RK816_IOFFSET_REGL 0xDE +#define RK816_SLEEP_CON_SAMP_CUR_REG 0xDF + +/*DATA REGISTER*/ +#define RK816_SOC_REG 0xE0 +#define RK816_REMAIN_CAP_REG3 0xE1 +#define RK816_REMAIN_CAP_REG2 0xE2 +#define RK816_REMAIN_CAP_REG1 0xE3 +#define RK816_REMAIN_CAP_REG0 0xE4 +#define RK816_UPDATE_LEVE_REG 0xE5 +#define RK816_NEW_FCC_REG3 0xE6 +#define RK816_NEW_FCC_REG2 0xE7 +#define RK816_NEW_FCC_REG1 0xE8 +#define RK816_NEW_FCC_REG0 0xE9 +#define RK816_NON_ACT_TIMER_CNT_REG_SAVE 0xEA +#define RK816_OCV_VOL_VALID_REG 0xEB +#define RK816_REBOOT_CNT_REG 0xEC +#define RK816_PCB_IOFFSET_REG 0xED +#define RK816_MISC_MARK_REG 0xEE +#define RK816_HALT_CNT_REG 0xEF +#define RK816_CALC_REST_REGH 0xF0 +#define RK816_CALC_REST_REGL 0xF1 +#define DATA18_REG 0xF2 + +/*INTERRUPT REGISTER*/ +#define RK816_INT_STS_REG1 0x49 +#define RK816_INT_STS_MSK_REG1 0x4A +#define RK816_INT_STS_REG2 0x4C +#define RK816_INT_STS_MSK_REG2 0x4D +#define RK816_INT_STS_REG3 0x4E +#define RK816_INT_STS_MSK_REG3 0x4F +#define RK816_GPIO_IO_POL_REG 0x50 + +#define RK816_DATA18_REG 0xF2 + +/* IRQ Definitions */ +#define RK816_IRQ_PWRON_FALL 0 +#define RK816_IRQ_PWRON_RISE 1 +#define RK816_IRQ_VB_LOW 2 +#define RK816_IRQ_PWRON 3 +#define RK816_IRQ_PWRON_LP 4 +#define RK816_IRQ_HOTDIE 5 +#define RK816_IRQ_RTC_ALARM 6 +#define RK816_IRQ_RTC_PERIOD 7 +#define RK816_IRQ_USB_OV 8 +#define RK816_IRQ_PLUG_IN 9 +#define RK816_IRQ_PLUG_OUT 10 +#define RK816_IRQ_CHG_OK 11 +#define RK816_IRQ_CHG_TE 12 +#define RK816_IRQ_CHG_TS 13 +#define RK816_IRQ_CHG_CVTLIM 14 +#define RK816_IRQ_DISCHG_ILIM 15 + +#define RK816_IRQ_PWRON_FALL_MSK BIT(5) +#define RK816_IRQ_PWRON_RISE_MSK BIT(6) +#define RK816_IRQ_VB_LOW_MSK BIT(1) +#define RK816_IRQ_PWRON_MSK BIT(2) +#define RK816_IRQ_PWRON_LP_MSK BIT(3) +#define RK816_IRQ_HOTDIE_MSK BIT(4) +#define RK816_IRQ_RTC_ALARM_MSK BIT(5) +#define RK816_IRQ_RTC_PERIOD_MSK BIT(6) +#define RK816_IRQ_USB_OV_MSK BIT(7) +#define RK816_IRQ_PLUG_IN_MSK BIT(0) +#define RK816_IRQ_PLUG_OUT_MSK BIT(1) +#define RK816_IRQ_CHG_OK_MSK BIT(2) +#define RK816_IRQ_CHG_TE_MSK BIT(3) +#define RK816_IRQ_CHG_TS_MSK BIT(4) +#define RK816_IRQ_CHG_CVTLIM_MSK BIT(6) +#define RK816_IRQ_DISCHG_ILIM_MSK BIT(7) + +#define RK816_VBAT_LOW_2V8 0x00 +#define RK816_VBAT_LOW_2V9 0x01 +#define RK816_VBAT_LOW_3V0 0x02 +#define RK816_VBAT_LOW_3V1 0x03 +#define RK816_VBAT_LOW_3V2 0x04 +#define RK816_VBAT_LOW_3V3 0x05 +#define RK816_VBAT_LOW_3V4 0x06 +#define RK816_VBAT_LOW_3V5 0x07 +#define RK816_PWR_FALL_INT_STATUS (0x1 << 5) +#define RK816_PWR_RISE_INT_STATUS (0x1 << 6) +#define RK816_ALARM_INT_STATUS (0x1 << 5) +#define EN_VBAT_LOW_IRQ (0x1 << 4) +#define VBAT_LOW_ACT_MASK (0x1 << 4) +#define RTC_TIMER_ALARM_INT_MSK (0x3 << 2) +#define RTC_TIMER_ALARM_INT_DIS (0x0 << 2) +#define RTC_PERIOD_ALARM_INT_MSK (0x3 << 5) +#define RTC_PERIOD_ALARM_INT_ST (0x3 << 5) +#define RTC_PERIOD_ALARM_INT_DIS (0x3 << 5) +#define RTC_PERIOD_ALARM_INT_EN (0x9f) +#define REG_WRITE_MSK 0xff +#define BUCK4_MAX_ILIMIT 0x2c +#define BUCK_RATE_MSK (0x3 << 3) +#define BUCK_RATE_12_5MV_US (0x2 << 3) +#define ALL_INT_FLAGS_ST 0xff +#define PLUGIN_OUT_INT_EN 0xfc +#define RK816_PWRON_FALL_RISE_INT_EN 0x9f +#define BUCK1_2_IMAX_MAX (0x3 << 6) +#define BUCK3_4_IMAX_MAX (0x3 << 3) +#define BOOST_DISABLE ((0x1 << 5) | (0x0 << 1)) +#define BUCK4_VRP_3PERCENT 0xc0 +#define RK816_BUCK_DVS_CONFIRM (0x1 << 7) +#define RK816_TYPE_ES2 0x05 +#define RK816_CHIP_VERSION_MASK 0x0f + /* RK818 */ #define RK818_DCDC1 0 #define RK818_LDO1 4 @@ -356,6 +584,25 @@ enum rk805_reg { #define RK818_NUM_IRQ 16 +/*RK818_DCDC_EN_REG*/ +#define BUCK1_EN_MASK BIT(0) +#define BUCK2_EN_MASK BIT(1) +#define BUCK3_EN_MASK BIT(2) +#define BUCK4_EN_MASK BIT(3) +#define BOOST_EN_MASK BIT(4) +#define LDO9_EN_MASK BIT(5) +#define SWITCH_EN_MASK BIT(6) +#define OTG_EN_MASK BIT(7) + +#define BUCK1_EN_ENABLE BIT(0) +#define BUCK2_EN_ENABLE BIT(1) +#define BUCK3_EN_ENABLE BIT(2) +#define BUCK4_EN_ENABLE BIT(3) +#define BOOST_EN_ENABLE BIT(4) +#define LDO9_EN_ENABLE BIT(5) +#define SWITCH_EN_ENABLE BIT(6) +#define OTG_EN_ENABLE BIT(7) + #define RK808_VBAT_LOW_2V8 0x00 #define RK808_VBAT_LOW_2V9 0x01 #define RK808_VBAT_LOW_3V0 0x02 @@ -390,13 +637,17 @@ enum rk805_reg { #define VOUT_LO_INT BIT(0) #define CLK32KOUT2_EN BIT(0) +#define TEMP105C 0x08 #define TEMP115C 0x0c #define TEMP_HOTDIE_MSK 0x0c #define SLP_SD_MSK (0x3 << 2) #define SHUTDOWN_FUN (0x2 << 2) #define SLEEP_FUN (0x1 << 2) #define RK8XX_ID_MSK 0xfff0 +#define PWM_MODE_MSK BIT(7) #define FPWM_MODE BIT(7) +#define AUTO_PWM_MODE 0 +#define REGS_WMSK 0xf0 enum { BUCK_ILMIN_50MA, @@ -444,6 +695,7 @@ enum { enum { RK805_ID = 0x8050, RK808_ID = 0x0000, + RK816_ID = 0x8160, RK818_ID = 0x8181, };