From 11406b8f7e24385ae8ee4065c5a193f2449fc08a Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Thu, 26 Sep 2019 15:43:52 +0800 Subject: dm: regulator: support regulator more state support parse regulator standard property: regulator-off-in-suspend; regulator-init-microvolt; regulator-suspend-microvolt: regulator_get_suspend_enable regulator_set_suspend_enable regulator_get_suspend_value regulator_set_suspend_value Signed-off-by: Joseph Chen Signed-off-by: Elaine Zhang Reviewed-by: Kever Yang --- include/power/regulator.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'include') diff --git a/include/power/regulator.h b/include/power/regulator.h index 6c6e2cd4f99..74938dd61e4 100644 --- a/include/power/regulator.h +++ b/include/power/regulator.h @@ -168,6 +168,7 @@ struct dm_regulator_uclass_platdata { int mode_count; int min_uV; int max_uV; + int init_uV; int min_uA; int max_uA; unsigned int ramp_delay; @@ -177,6 +178,8 @@ struct dm_regulator_uclass_platdata { int flags; u8 ctrl_reg; u8 volt_reg; + bool suspend_on; + u32 suspend_uV; }; /* Regulator device operations */ @@ -193,6 +196,19 @@ struct dm_regulator_ops { int (*get_value)(struct udevice *dev); int (*set_value)(struct udevice *dev, int uV); + /** + * The regulator suspend output value function calls operates + * on a micro Volts. + * + * get/set_suspen_value - get/set suspend mode output value + * @dev - regulator device + * Sets: + * @uV - set the suspend output value [micro Volts] + * @return output value [uV] on success or negative errno if fail. + */ + int (*set_suspend_value)(struct udevice *dev, int uV); + int (*get_suspend_value)(struct udevice *dev); + /** * The regulator output current function calls operates on a micro Amps. * @@ -217,6 +233,19 @@ struct dm_regulator_ops { int (*get_enable)(struct udevice *dev); int (*set_enable)(struct udevice *dev, bool enable); + /** + * The most basic feature of the regulator output is its enable state + * in suspend mode. + * + * get/set_suspend_enable - get/set enable state of the suspend output + * @dev - regulator device + * Sets: + * @enable - set true - enable or false - disable + * @return true/false for get or -errno if fail; 0 / -errno for set. + */ + int (*set_suspend_enable)(struct udevice *dev, bool enable); + int (*get_suspend_enable)(struct udevice *dev); + /** * The 'get/set_mode()' function calls should operate on a driver- * specific mode id definitions, which should be found in: @@ -261,6 +290,23 @@ int regulator_get_value(struct udevice *dev); */ int regulator_set_value(struct udevice *dev, int uV); +/** + * regulator_set_suspend_value: set the suspend microvoltage value of a given regulator. + * + * @dev - pointer to the regulator device + * @uV - the output suspend value to set [micro Volts] + * @return - 0 on success or -errno val if fails + */ +int regulator_set_suspend_value(struct udevice *dev, int uV); + +/** + * regulator_get_suspend_value: get the suspend microvoltage value of a given regulator. + * + * @dev - pointer to the regulator device + * @return - positive output value [uV] on success or negative errno if fail. + */ +int regulator_get_suspend_value(struct udevice *dev); + /** * regulator_set_value_force: set the microvoltage value of a given regulator * without any min-,max condition check @@ -316,6 +362,23 @@ int regulator_set_enable(struct udevice *dev, bool enable); */ int regulator_set_enable_if_allowed(struct udevice *dev, bool enable); +/** + * regulator_set_suspend_enable: set regulator suspend enable state + * + * @dev - pointer to the regulator device + * @enable - set true or false + * @return - 0 on success or -errno val if fails + */ +int regulator_set_suspend_enable(struct udevice *dev, bool enable); + +/** + * regulator_get_suspend_enable: get regulator suspend enable state + * + * @dev - pointer to the regulator device + * @return - true/false of enable state or -errno val if fails + */ +int regulator_get_suspend_enable(struct udevice *dev); + /** * regulator_get_mode: get active operation mode id of a given regulator * -- cgit v1.3.1 From addd062beaccc028fccdc90500d5d17647461da6 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 26 Sep 2019 15:43:54 +0800 Subject: power: pmic: rk816: support rk816 pmic The RK816 is a Power Management IC (PMIC) for multimedia and handheld devices. They contains the following components: - Regulators(4*BUCKs, 1*BOOST, 6*LDOs, 1*SWITCH) - RTC - Clocking Signed-off-by: Elaine Zhang Reviewed-by: Kever Yang --- drivers/power/pmic/rk8xx.c | 1 + drivers/power/regulator/rk8xx.c | 129 ++++++++++++++++++++++++++++++++++++++-- include/power/rk8xx_pmic.h | 11 +++- 3 files changed, 135 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c index 25c339ab12c..1900de9d1cd 100644 --- a/drivers/power/pmic/rk8xx.c +++ b/drivers/power/pmic/rk8xx.c @@ -95,6 +95,7 @@ static struct dm_pmic_ops rk8xx_ops = { static const struct udevice_id rk8xx_ids[] = { { .compatible = "rockchip,rk808" }, + { .compatible = "rockchip,rk816" }, { .compatible = "rockchip,rk818" }, { } }; diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c index ccea0693dc8..5a474c73132 100644 --- a/drivers/power/regulator/rk8xx.c +++ b/drivers/power/regulator/rk8xx.c @@ -62,6 +62,21 @@ static const struct rk8xx_reg_info rk808_buck[] = { { 1800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK808_BUCK4_VSEL_MASK, }, }; +static const struct rk8xx_reg_info rk816_buck[] = { + /* buck 1 */ + { 712500, 12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, 0x00, }, + { 1800000, 200000, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, 0x3c, }, + { 2300000, 0, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, 0x3f, }, + /* buck 2 */ + { 712500, 12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, 0x00, }, + { 1800000, 200000, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, 0x3c, }, + { 2300000, 0, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, 0x3f, }, + /* buck 3 */ + { 712500, 12500, NA, NA, REG_BUCK3_CONFIG, RK818_BUCK_VSEL_MASK, }, + /* buck 4 */ + { 800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK, }, +}; + static const struct rk8xx_reg_info rk818_buck[] = { { 712500, 12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, }, { 712500, 12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, }, @@ -81,6 +96,15 @@ static const struct rk8xx_reg_info rk808_ldo[] = { { 1800000, 100000, REG_LDO8_ON_VSEL, REG_LDO8_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, }, }; +static const struct rk8xx_reg_info rk816_ldo[] = { + { 800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, }, + { 800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, }, + { 800000, 100000, REG_LDO3_ON_VSEL, REG_LDO3_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, }, + { 800000, 100000, REG_LDO4_ON_VSEL, REG_LDO4_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, }, + { 800000, 100000, REG_LDO5_ON_VSEL, REG_LDO5_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, }, + { 800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, }, +}; + static const struct rk8xx_reg_info rk818_ldo[] = { { 1800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, }, { 1800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, }, @@ -105,7 +129,21 @@ static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic, int num, int uvolt) { struct rk8xx_priv *priv = dev_get_priv(pmic); + switch (priv->variant) { + case RK816_ID: + switch (num) { + case 0: + case 1: + if (uvolt <= 1450000) + return &rk816_buck[num * 3 + 0]; + else if (uvolt <= 2200000) + return &rk816_buck[num * 3 + 1]; + else + return &rk816_buck[num * 3 + 2]; + default: + return &rk816_buck[num + 4]; + } case RK818_ID: return &rk818_buck[num]; default: @@ -116,11 +154,13 @@ static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic, static int _buck_set_value(struct udevice *pmic, int buck, int uvolt) { const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt); + struct rk8xx_priv *priv = dev_get_priv(pmic); int mask = info->vsel_mask; int val; if (info->vsel_reg == NA) return -ENOSYS; + if (info->step_uv == 0) /* Fixed voltage */ val = info->min_sel; else @@ -129,17 +169,36 @@ static int _buck_set_value(struct udevice *pmic, int buck, int uvolt) debug("%s: volt=%d, buck=%d, reg=0x%x, mask=0x%x, val=0x%x\n", __func__, uvolt, buck + 1, info->vsel_reg, mask, val); - - return pmic_clrsetbits(pmic, info->vsel_reg, mask, val); + if (priv->variant == RK816_ID) { + pmic_clrsetbits(pmic, info->vsel_reg, mask, val); + return pmic_clrsetbits(pmic, RK816_REG_DCDC_EN2, + 1 << 7, 1 << 7); + } else { + return pmic_clrsetbits(pmic, info->vsel_reg, mask, val); + } } static int _buck_set_enable(struct udevice *pmic, int buck, bool enable) { - uint mask; + uint mask, value, en_reg; int ret; struct rk8xx_priv *priv = dev_get_priv(pmic); switch (priv->variant) { + case RK816_ID: + if (buck >= 4) { + buck -= 4; + en_reg = RK816_REG_DCDC_EN2; + } else { + en_reg = RK816_REG_DCDC_EN1; + } + if (enable) + value = ((1 << buck) | (1 << (buck + 4))); + else + value = ((0 << buck) | (1 << (buck + 4))); + ret = pmic_reg_write(pmic, en_reg, value); + break; + case RK808_ID: case RK818_ID: mask = 1 << buck; @@ -187,6 +246,15 @@ static int _buck_get_enable(struct udevice *pmic, int buck) int ret = 0; switch (priv->variant) { + case RK816_ID: + if (buck >= 4) { + mask = 1 << (buck - 4); + ret = pmic_reg_read(pmic, RK816_REG_DCDC_EN2); + } else { + mask = 1 << buck; + ret = pmic_reg_read(pmic, RK816_REG_DCDC_EN1); + } + break; case RK808_ID: case RK818_ID: mask = 1 << buck; @@ -209,6 +277,11 @@ static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable) struct rk8xx_priv *priv = dev_get_priv(pmic); switch (priv->variant) { + case RK816_ID: + mask = 1 << buck; + ret = pmic_clrsetbits(pmic, RK816_REG_DCDC_SLP_EN, mask, + enable ? mask : 0); + break; case RK808_ID: case RK818_ID: mask = 1 << buck; @@ -229,6 +302,13 @@ static int _buck_get_suspend_enable(struct udevice *pmic, int buck) uint mask; switch (priv->variant) { + case RK816_ID: + mask = 1 << buck; + val = pmic_reg_read(pmic, RK816_REG_DCDC_SLP_EN); + if (val < 0) + return val; + ret = val & mask ? 1 : 0; + break; case RK808_ID: case RK818_ID: mask = 1 << buck; @@ -248,7 +328,10 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic, int num, int uvolt) { struct rk8xx_priv *priv = dev_get_priv(pmic); + switch (priv->variant) { + case RK816_ID: + return &rk816_ldo[num]; case RK818_ID: return &rk818_ldo[num]; default: @@ -263,6 +346,15 @@ static int _ldo_get_enable(struct udevice *pmic, int ldo) int ret = 0; switch (priv->variant) { + case RK816_ID: + if (ldo >= 4) { + mask = 1 << (ldo - 4); + ret = pmic_reg_read(pmic, RK816_REG_LDO_EN2); + } else { + mask = 1 << ldo; + ret = pmic_reg_read(pmic, RK816_REG_LDO_EN1); + } + break; case RK808_ID: case RK818_ID: mask = 1 << ldo; @@ -281,15 +373,29 @@ static int _ldo_get_enable(struct udevice *pmic, int ldo) static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable) { struct rk8xx_priv *priv = dev_get_priv(pmic); - uint mask; + uint mask, value, en_reg; int ret = 0; switch (priv->variant) { + case RK816_ID: + if (ldo >= 4) { + ldo -= 4; + en_reg = RK816_REG_LDO_EN2; + } else { + en_reg = RK816_REG_LDO_EN1; + } + if (enable) + value = ((1 << ldo) | (1 << (ldo + 4))); + else + value = ((0 << ldo) | (1 << (ldo + 4))); + + ret = pmic_reg_write(pmic, en_reg, value); + break; case RK808_ID: case RK818_ID: mask = 1 << ldo; ret = pmic_clrsetbits(pmic, REG_LDO_EN, mask, - enable ? mask : 0); + enable ? mask : 0); break; } @@ -303,6 +409,11 @@ static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable) int ret = 0; switch (priv->variant) { + case RK816_ID: + mask = 1 << ldo; + ret = pmic_clrsetbits(pmic, RK816_REG_LDO_SLP_EN, mask, + enable ? mask : 0); + break; case RK808_ID: case RK818_ID: mask = 1 << ldo; @@ -321,6 +432,13 @@ static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo) uint mask; switch (priv->variant) { + case RK816_ID: + mask = 1 << ldo; + val = pmic_reg_read(pmic, RK816_REG_LDO_SLP_EN); + if (val < 0) + return val; + ret = val & mask ? 1 : 0; + break; case RK808_ID: case RK818_ID: mask = 1 << ldo; @@ -344,6 +462,7 @@ static int buck_get_value(struct udevice *dev) if (info->vsel_reg == NA) return -ENOSYS; + ret = pmic_reg_read(dev->parent, info->vsel_reg); if (ret < 0) return ret; diff --git a/include/power/rk8xx_pmic.h b/include/power/rk8xx_pmic.h index c06248f7518..44e8d687dfb 100644 --- a/include/power/rk8xx_pmic.h +++ b/include/power/rk8xx_pmic.h @@ -170,8 +170,17 @@ enum { }; enum { - RK805_ID = 0x8050, + RK816_REG_DCDC_EN1 = 0x23, + RK816_REG_DCDC_EN2, + RK816_REG_DCDC_SLP_EN, + RK816_REG_LDO_SLP_EN, + RK816_REG_LDO_EN1 = 0x27, + RK816_REG_LDO_EN2, +}; + +enum { RK808_ID = 0x0000, + RK816_ID = 0x8160, RK818_ID = 0x8180, }; -- cgit v1.3.1 From b62280745e553b5800fa0797b920e547c92da82d Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 26 Sep 2019 15:43:55 +0800 Subject: power: pmic: rk805: support rk805 pmic The RK805 are a Power Management IC (PMIC) for multimedia and handheld devices. They contains the following components: - Regulators(4*BUCKs, 3*LDOs) - RTC - Clocking Signed-off-by: Elaine Zhang Reviewed-by: Kever Yang --- drivers/power/pmic/rk8xx.c | 1 + drivers/power/regulator/rk8xx.c | 17 +++++++++++++++++ include/power/rk8xx_pmic.h | 1 + 3 files changed, 19 insertions(+) (limited to 'include') diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c index 1900de9d1cd..00c8a2e091d 100644 --- a/drivers/power/pmic/rk8xx.c +++ b/drivers/power/pmic/rk8xx.c @@ -94,6 +94,7 @@ static struct dm_pmic_ops rk8xx_ops = { }; static const struct udevice_id rk8xx_ids[] = { + { .compatible = "rockchip,rk805" }, { .compatible = "rockchip,rk808" }, { .compatible = "rockchip,rk816" }, { .compatible = "rockchip,rk818" }, diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c index 5a474c73132..466a871b7e8 100644 --- a/drivers/power/regulator/rk8xx.c +++ b/drivers/power/regulator/rk8xx.c @@ -38,7 +38,14 @@ /* * Ramp delay */ +#define RK805_RAMP_RATE_OFFSET 3 +#define RK805_RAMP_RATE_MASK (3 << RK805_RAMP_RATE_OFFSET) +#define RK805_RAMP_RATE_3MV_PER_US (0 << RK805_RAMP_RATE_OFFSET) +#define RK805_RAMP_RATE_6MV_PER_US (1 << RK805_RAMP_RATE_OFFSET) +#define RK805_RAMP_RATE_12_5MV_PER_US (2 << RK805_RAMP_RATE_OFFSET) +#define RK805_RAMP_RATE_25MV_PER_US (3 << RK805_RAMP_RATE_OFFSET) #define RK808_RAMP_RATE_OFFSET 3 + #define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET) #define RK808_RAMP_RATE_2MV_PER_US (0 << RK808_RAMP_RATE_OFFSET) #define RK808_RAMP_RATE_4MV_PER_US (1 << RK808_RAMP_RATE_OFFSET) @@ -131,6 +138,7 @@ static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic, struct rk8xx_priv *priv = dev_get_priv(pmic); switch (priv->variant) { + case RK805_ID: case RK816_ID: switch (num) { case 0: @@ -185,6 +193,7 @@ static int _buck_set_enable(struct udevice *pmic, int buck, bool enable) struct rk8xx_priv *priv = dev_get_priv(pmic); switch (priv->variant) { + case RK805_ID: case RK816_ID: if (buck >= 4) { buck -= 4; @@ -246,6 +255,7 @@ static int _buck_get_enable(struct udevice *pmic, int buck) int ret = 0; switch (priv->variant) { + case RK805_ID: case RK816_ID: if (buck >= 4) { mask = 1 << (buck - 4); @@ -277,6 +287,7 @@ static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable) struct rk8xx_priv *priv = dev_get_priv(pmic); switch (priv->variant) { + case RK805_ID: case RK816_ID: mask = 1 << buck; ret = pmic_clrsetbits(pmic, RK816_REG_DCDC_SLP_EN, mask, @@ -302,6 +313,7 @@ static int _buck_get_suspend_enable(struct udevice *pmic, int buck) uint mask; switch (priv->variant) { + case RK805_ID: case RK816_ID: mask = 1 << buck; val = pmic_reg_read(pmic, RK816_REG_DCDC_SLP_EN); @@ -330,6 +342,7 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic, struct rk8xx_priv *priv = dev_get_priv(pmic); switch (priv->variant) { + case RK805_ID: case RK816_ID: return &rk816_ldo[num]; case RK818_ID: @@ -346,6 +359,7 @@ static int _ldo_get_enable(struct udevice *pmic, int ldo) int ret = 0; switch (priv->variant) { + case RK805_ID: case RK816_ID: if (ldo >= 4) { mask = 1 << (ldo - 4); @@ -377,6 +391,7 @@ static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable) int ret = 0; switch (priv->variant) { + case RK805_ID: case RK816_ID: if (ldo >= 4) { ldo -= 4; @@ -409,6 +424,7 @@ static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable) int ret = 0; switch (priv->variant) { + case RK805_ID: case RK816_ID: mask = 1 << ldo; ret = pmic_clrsetbits(pmic, RK816_REG_LDO_SLP_EN, mask, @@ -432,6 +448,7 @@ static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo) uint mask; switch (priv->variant) { + case RK805_ID: case RK816_ID: mask = 1 << ldo; val = pmic_reg_read(pmic, RK816_REG_LDO_SLP_EN); diff --git a/include/power/rk8xx_pmic.h b/include/power/rk8xx_pmic.h index 44e8d687dfb..7784c2a5e47 100644 --- a/include/power/rk8xx_pmic.h +++ b/include/power/rk8xx_pmic.h @@ -179,6 +179,7 @@ enum { }; enum { + RK805_ID = 0x8050, RK808_ID = 0x0000, RK816_ID = 0x8160, RK818_ID = 0x8180, -- cgit v1.3.1 From b4a35574b38d0fb42031be32a47fb1095cceafa7 Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Thu, 26 Sep 2019 15:44:55 +0800 Subject: power: pmic: rk817: support rk817 pmic The RK817 is a Power Management IC (PMIC) for multimedia and handheld devices. They contains the following components: - Regulators(4*BUCKs, 1* BOOST, 9*LDOs, 1*SWITCH) - RTC - Clocking Signed-off-by: Joseph Chen Signed-off-by: Elaine Zhang Reviewed-by: Kever Yang --- drivers/power/pmic/rk8xx.c | 84 +++++++++++++++++- drivers/power/regulator/rk8xx.c | 189 +++++++++++++++++++++++++++++++++++++++- include/power/rk8xx_pmic.h | 31 +++++++ 3 files changed, 297 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c index 00c8a2e091d..df0bf83a054 100644 --- a/drivers/power/pmic/rk8xx.c +++ b/drivers/power/pmic/rk8xx.c @@ -10,6 +10,13 @@ #include #include +static struct reg_data rk817_init_reg[] = { +/* enable the under-voltage protection, + * the under-voltage protection will shutdown the LDO3 and reset the PMIC + */ + { RK817_BUCK4_CMIN, 0x60, 0x60}, +}; + static const struct pmic_child_info pmic_children_info[] = { { .prefix = "DCDC_REG", .driver = "rk8xx_buck"}, { .prefix = "LDO_REG", .driver = "rk8xx_ldo"}, @@ -76,13 +83,83 @@ static int rk8xx_bind(struct udevice *dev) static int rk8xx_probe(struct udevice *dev) { struct rk8xx_priv *priv = dev_get_priv(dev); - uint8_t msb, lsb; + struct reg_data *init_data = NULL; + int init_data_num = 0; + int ret = 0, i, show_variant; + u8 msb, lsb, id_msb, id_lsb; + u8 on_source = 0, off_source = 0; + u8 power_en0, power_en1, power_en2, power_en3; + u8 value; /* read Chip variant */ - rk8xx_read(dev, ID_MSB, &msb, 1); - rk8xx_read(dev, ID_LSB, &lsb, 1); + if (device_is_compatible(dev, "rockchip,rk817")) { + id_msb = RK817_ID_MSB; + id_lsb = RK817_ID_LSB; + } else { + id_msb = ID_MSB; + id_lsb = ID_LSB; + } + + ret = rk8xx_read(dev, id_msb, &msb, 1); + if (ret) + return ret; + ret = rk8xx_read(dev, id_lsb, &lsb, 1); + if (ret) + return ret; priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK; + show_variant = priv->variant; + switch (priv->variant) { + case RK808_ID: + show_variant = 0x808; /* RK808 hardware ID is 0 */ + break; + case RK805_ID: + case RK816_ID: + case RK818_ID: + on_source = RK8XX_ON_SOURCE; + off_source = RK8XX_OFF_SOURCE; + break; + case RK817_ID: + on_source = RK817_ON_SOURCE; + off_source = RK817_OFF_SOURCE; + init_data = rk817_init_reg; + init_data_num = ARRAY_SIZE(rk817_init_reg); + power_en0 = pmic_reg_read(dev, RK817_POWER_EN0); + power_en1 = pmic_reg_read(dev, RK817_POWER_EN1); + power_en2 = pmic_reg_read(dev, RK817_POWER_EN2); + power_en3 = pmic_reg_read(dev, RK817_POWER_EN3); + + value = (power_en0 & 0x0f) | ((power_en1 & 0x0f) << 4); + pmic_reg_write(dev, RK817_POWER_EN_SAVE0, value); + value = (power_en2 & 0x0f) | ((power_en3 & 0x0f) << 4); + pmic_reg_write(dev, RK817_POWER_EN_SAVE1, value); + break; + default: + printf("Unknown PMIC: RK%x!!\n", priv->variant); + return -EINVAL; + } + + for (i = 0; i < init_data_num; i++) { + ret = pmic_clrsetbits(dev, + init_data[i].reg, + init_data[i].mask, + init_data[i].val); + if (ret < 0) { + printf("%s: i2c set reg 0x%x failed, ret=%d\n", + __func__, init_data[i].reg, ret); + } + + debug("%s: reg[0x%x] = 0x%x\n", __func__, init_data[i].reg, + pmic_reg_read(dev, init_data[i].reg)); + } + + printf("PMIC: RK%x ", show_variant); + + if (on_source && off_source) + printf("(on=0x%02x, off=0x%02x)", + pmic_reg_read(dev, on_source), + pmic_reg_read(dev, off_source)); + printf("\n"); return 0; } @@ -97,6 +174,7 @@ static const struct udevice_id rk8xx_ids[] = { { .compatible = "rockchip,rk805" }, { .compatible = "rockchip,rk808" }, { .compatible = "rockchip,rk816" }, + { .compatible = "rockchip,rk817" }, { .compatible = "rockchip,rk818" }, { } }; diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c index 466a871b7e8..a5692edd002 100644 --- a/drivers/power/regulator/rk8xx.c +++ b/drivers/power/regulator/rk8xx.c @@ -27,6 +27,21 @@ #define RK808_BUCK4_VSEL_MASK 0xf #define RK808_LDO_VSEL_MASK 0x1f +/* RK817 BUCK */ +#define RK817_BUCK_ON_VSEL(n) (0xbb + 3 * ((n) - 1)) +#define RK817_BUCK_SLP_VSEL(n) (0xbc + 3 * ((n) - 1)) +#define RK817_BUCK_VSEL_MASK 0x7f +#define RK817_BUCK_CONFIG(i) (0xba + (i) * 3) + +/* RK817 LDO */ +#define RK817_LDO_ON_VSEL(n) (0xcc + 2 * ((n) - 1)) +#define RK817_LDO_SLP_VSEL(n) (0xcd + 2 * ((n) - 1)) +#define RK817_LDO_VSEL_MASK 0x7f + +/* RK817 ENABLE */ +#define RK817_POWER_EN(n) (0xb1 + (n)) +#define RK817_POWER_SLP_EN(n) (0xb5 + (n)) + #define RK818_BUCK_VSEL_MASK 0x3f #define RK818_BUCK4_VSEL_MASK 0x1f #define RK818_LDO_VSEL_MASK 0x1f @@ -45,13 +60,19 @@ #define RK805_RAMP_RATE_12_5MV_PER_US (2 << RK805_RAMP_RATE_OFFSET) #define RK805_RAMP_RATE_25MV_PER_US (3 << RK805_RAMP_RATE_OFFSET) #define RK808_RAMP_RATE_OFFSET 3 - #define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET) #define RK808_RAMP_RATE_2MV_PER_US (0 << RK808_RAMP_RATE_OFFSET) #define RK808_RAMP_RATE_4MV_PER_US (1 << RK808_RAMP_RATE_OFFSET) #define RK808_RAMP_RATE_6MV_PER_US (2 << RK808_RAMP_RATE_OFFSET) #define RK808_RAMP_RATE_10MV_PER_US (3 << RK808_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_OFFSET 6 +#define RK817_RAMP_RATE_MASK (0x3 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_3MV_PER_US (0x0 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_6_3MV_PER_US (0x1 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_12_5MV_PER_US (0x2 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_25MV_PER_US (0x3 << RK817_RAMP_RATE_OFFSET) + struct rk8xx_reg_info { uint min_uv; uint step_uv; @@ -84,6 +105,25 @@ static const struct rk8xx_reg_info rk816_buck[] = { { 800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK, }, }; +static const struct rk8xx_reg_info rk817_buck[] = { + /* buck 1 */ + { 500000, 12500, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x00, }, + { 1500000, 100000, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x50, }, + { 2400000, 0, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x59, }, + /* buck 2 */ + { 500000, 12500, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x00, }, + { 1500000, 100000, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x50, }, + { 2400000, 0, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x59, }, + /* buck 3 */ + { 500000, 12500, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x00, }, + { 1500000, 100000, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x50, }, + { 2400000, 0, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x59, }, + /* buck 4 */ + { 500000, 12500, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x00, }, + { 1500000, 100000, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x50, }, + { 3400000, 0, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x63, }, +}; + static const struct rk8xx_reg_info rk818_buck[] = { { 712500, 12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, }, { 712500, 12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, }, @@ -112,6 +152,36 @@ static const struct rk8xx_reg_info rk816_ldo[] = { { 800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, }, }; +static const struct rk8xx_reg_info rk817_ldo[] = { + /* ldo1 */ + { 600000, 25000, RK817_LDO_ON_VSEL(1), RK817_LDO_SLP_VSEL(1), NA, RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(1), RK817_LDO_SLP_VSEL(1), NA, RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo2 */ + { 600000, 25000, RK817_LDO_ON_VSEL(2), RK817_LDO_SLP_VSEL(2), NA, RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(2), RK817_LDO_SLP_VSEL(2), NA, RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo3 */ + { 600000, 25000, RK817_LDO_ON_VSEL(3), RK817_LDO_SLP_VSEL(3), NA, RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(3), RK817_LDO_SLP_VSEL(3), NA, RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo4 */ + { 600000, 25000, RK817_LDO_ON_VSEL(4), RK817_LDO_SLP_VSEL(4), NA, RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(4), RK817_LDO_SLP_VSEL(4), NA, RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo5 */ + { 600000, 25000, RK817_LDO_ON_VSEL(5), RK817_LDO_SLP_VSEL(5), NA, RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(5), RK817_LDO_SLP_VSEL(5), NA, RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo6 */ + { 600000, 25000, RK817_LDO_ON_VSEL(6), RK817_LDO_SLP_VSEL(6), NA, RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(6), RK817_LDO_SLP_VSEL(6), NA, RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo7 */ + { 600000, 25000, RK817_LDO_ON_VSEL(7), RK817_LDO_SLP_VSEL(7), NA, RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(7), RK817_LDO_SLP_VSEL(7), NA, RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo8 */ + { 600000, 25000, RK817_LDO_ON_VSEL(8), RK817_LDO_SLP_VSEL(8), NA, RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(8), RK817_LDO_SLP_VSEL(8), NA, RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo9 */ + { 600000, 25000, RK817_LDO_ON_VSEL(9), RK817_LDO_SLP_VSEL(9), NA, RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(9), RK817_LDO_SLP_VSEL(9), NA, RK817_LDO_VSEL_MASK, 0x70, }, +}; + static const struct rk8xx_reg_info rk818_ldo[] = { { 1800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, }, { 1800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, }, @@ -152,6 +222,24 @@ static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic, default: return &rk816_buck[num + 4]; } + + case RK817_ID: + switch (num) { + case 0 ... 2: + if (uvolt < 1500000) + return &rk817_buck[num * 3 + 0]; + else if (uvolt < 2400000) + return &rk817_buck[num * 3 + 1]; + else + return &rk817_buck[num * 3 + 2]; + case 3: + if (uvolt < 1500000) + return &rk817_buck[num * 3 + 0]; + else if (uvolt < 3400000) + return &rk817_buck[num * 3 + 1]; + else + return &rk817_buck[num * 3 + 2]; + } case RK818_ID: return &rk818_buck[num]; default: @@ -189,7 +277,7 @@ static int _buck_set_value(struct udevice *pmic, int buck, int uvolt) static int _buck_set_enable(struct udevice *pmic, int buck, bool enable) { uint mask, value, en_reg; - int ret; + int ret = 0; struct rk8xx_priv *priv = dev_get_priv(pmic); switch (priv->variant) { @@ -220,6 +308,15 @@ static int _buck_set_enable(struct udevice *pmic, int buck, bool enable) ret = pmic_clrsetbits(pmic, REG_DCDC_EN, mask, enable ? mask : 0); break; + case RK817_ID: + if (buck < 4) { + if (enable) + value = ((1 << buck) | (1 << (buck + 4))); + else + value = ((0 << buck) | (1 << (buck + 4))); + ret = pmic_reg_write(pmic, RK817_POWER_EN(0), value); + } + break; default: ret = -EINVAL; } @@ -272,6 +369,12 @@ static int _buck_get_enable(struct udevice *pmic, int buck) if (ret < 0) return ret; break; + case RK817_ID: + if (buck < 4) { + mask = 1 << buck; + ret = pmic_reg_read(pmic, RK817_POWER_EN(0)); + } + break; } if (ret < 0) @@ -282,7 +385,7 @@ static int _buck_get_enable(struct udevice *pmic, int buck) static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable) { - uint mask; + uint mask = 0; int ret; struct rk8xx_priv *priv = dev_get_priv(pmic); @@ -299,6 +402,12 @@ static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable) ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF1, mask, enable ? 0 : mask); break; + case RK817_ID: + if (buck < 4) + mask = 1 << buck; + ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask, + enable ? mask : 0); + break; default: ret = -EINVAL; } @@ -310,7 +419,7 @@ static int _buck_get_suspend_enable(struct udevice *pmic, int buck) { struct rk8xx_priv *priv = dev_get_priv(pmic); int ret, val; - uint mask; + uint mask = 0; switch (priv->variant) { case RK805_ID: @@ -329,6 +438,15 @@ static int _buck_get_suspend_enable(struct udevice *pmic, int buck) return val; ret = val & mask ? 0 : 1; break; + case RK817_ID: + if (buck < 4) + mask = 1 << buck; + + val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(0)); + if (val < 0) + return val; + ret = val & mask ? 1 : 0; + break; default: ret = -EINVAL; } @@ -345,6 +463,11 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic, case RK805_ID: case RK816_ID: return &rk816_ldo[num]; + case RK817_ID: + if (uvolt < 3400000) + return &rk817_ldo[num * 2 + 0]; + else + return &rk817_ldo[num * 2 + 1]; case RK818_ID: return &rk818_ldo[num]; default: @@ -376,6 +499,20 @@ static int _ldo_get_enable(struct udevice *pmic, int ldo) if (ret < 0) return ret; break; + case RK817_ID: + if (ldo < 4) { + mask = 1 << ldo; + ret = pmic_reg_read(pmic, RK817_POWER_EN(1)); + } else if (ldo < 8) { + mask = 1 << (ldo - 4); + ret = pmic_reg_read(pmic, RK817_POWER_EN(2)); + } else if (ldo == 8) { + mask = 1 << 0; + ret = pmic_reg_read(pmic, RK817_POWER_EN(3)); + } else { + return false; + } + break; } if (ret < 0) @@ -412,6 +549,24 @@ static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable) ret = pmic_clrsetbits(pmic, REG_LDO_EN, mask, enable ? mask : 0); break; + case RK817_ID: + if (ldo < 4) { + en_reg = RK817_POWER_EN(1); + } else if (ldo < 8) { + ldo -= 4; + en_reg = RK817_POWER_EN(2); + } else if (ldo == 8) { + ldo = 0; /* BIT 0 */ + en_reg = RK817_POWER_EN(3); + } else { + return -EINVAL; + } + if (enable) + value = ((1 << ldo) | (1 << (ldo + 4))); + else + value = ((0 << ldo) | (1 << (ldo + 4))); + ret = pmic_reg_write(pmic, en_reg, value); + break; } return ret; @@ -436,6 +591,17 @@ static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable) ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF2, mask, enable ? 0 : mask); break; + case RK817_ID: + if (ldo == 8) { + mask = 1 << 4; /* LDO9 */ + ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask, + enable ? mask : 0); + } else { + mask = 1 << ldo; + ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(1), mask, + enable ? mask : 0); + } + break; } return ret; @@ -464,6 +630,21 @@ static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo) return val; ret = val & mask ? 0 : 1; break; + case RK817_ID: + if (ldo == 8) { + mask = 1 << 4; /* LDO9 */ + val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(0)); + if (val < 0) + return val; + ret = val & mask ? 1 : 0; + } else { + mask = 1 << ldo; + val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(1)); + if (val < 0) + return val; + ret = val & mask ? 1 : 0; + } + break; } return ret; diff --git a/include/power/rk8xx_pmic.h b/include/power/rk8xx_pmic.h index 7784c2a5e47..d93cecedddf 100644 --- a/include/power/rk8xx_pmic.h +++ b/include/power/rk8xx_pmic.h @@ -169,6 +169,10 @@ enum { RK808_NUM_OF_REGS, }; +enum { + RK817_REG_SYS_CFG3 = 0xf4, +}; + enum { RK816_REG_DCDC_EN1 = 0x23, RK816_REG_DCDC_EN2, @@ -182,11 +186,38 @@ enum { RK805_ID = 0x8050, RK808_ID = 0x0000, RK816_ID = 0x8160, + RK817_ID = 0x8170, RK818_ID = 0x8180, }; +enum { + RK817_POWER_EN0 = 0xb1, + RK817_POWER_EN1, + RK817_POWER_EN2, + RK817_POWER_EN3, +}; + +#define RK817_POWER_EN_SAVE0 0x99 +#define RK817_POWER_EN_SAVE1 0xa4 + +#define RK817_ID_MSB 0xed +#define RK817_ID_LSB 0xee #define RK8XX_ID_MSK 0xfff0 +#define RK817_PMIC_SYS_CFG3 0xf4 +#define RK817_GPIO_INT_CFG 0xfe + +#define RK8XX_ON_SOURCE 0xae +#define RK8XX_OFF_SOURCE 0xaf +#define RK817_BUCK4_CMIN 0xc6 +#define RK817_ON_SOURCE 0xf5 +#define RK817_OFF_SOURCE 0xf6 + +struct reg_data { + u8 reg; + u8 val; + u8 mask; +}; struct rk8xx_reg_table { char *name; u8 reg_ctl; -- cgit v1.3.1 From ee30068fa5742ef611d796e16bfc5047db2d7f9e Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Thu, 26 Sep 2019 15:45:07 +0800 Subject: power: pmic: rk809: support rk809 pmic The RK809 is a Power Management IC (PMIC) for multimedia and handheld devices. They contains the following components: - Regulators(5*BUCKs, 9*LDOs, 2*SWITCHes) - RTC - Clocking Signed-off-by: Joseph Chen Signed-off-by: Elaine Zhang Reviewed-by: Kever Yang --- drivers/power/pmic/rk8xx.c | 5 ++- drivers/power/regulator/rk8xx.c | 69 +++++++++++++++++++++++++++++++++++++++++ include/power/rk8xx_pmic.h | 1 + 3 files changed, 74 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c index df0bf83a054..52e6d9d8c0e 100644 --- a/drivers/power/pmic/rk8xx.c +++ b/drivers/power/pmic/rk8xx.c @@ -92,7 +92,8 @@ static int rk8xx_probe(struct udevice *dev) u8 value; /* read Chip variant */ - if (device_is_compatible(dev, "rockchip,rk817")) { + if (device_is_compatible(dev, "rockchip,rk817") || + device_is_compatible(dev, "rockchip,rk809")) { id_msb = RK817_ID_MSB; id_lsb = RK817_ID_LSB; } else { @@ -119,6 +120,7 @@ static int rk8xx_probe(struct udevice *dev) on_source = RK8XX_ON_SOURCE; off_source = RK8XX_OFF_SOURCE; break; + case RK809_ID: case RK817_ID: on_source = RK817_ON_SOURCE; off_source = RK817_OFF_SOURCE; @@ -173,6 +175,7 @@ static struct dm_pmic_ops rk8xx_ops = { static const struct udevice_id rk8xx_ids[] = { { .compatible = "rockchip,rk805" }, { .compatible = "rockchip,rk808" }, + { .compatible = "rockchip,rk809" }, { .compatible = "rockchip,rk816" }, { .compatible = "rockchip,rk817" }, { .compatible = "rockchip,rk818" }, diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c index a5692edd002..e99331f6c96 100644 --- a/drivers/power/regulator/rk8xx.c +++ b/drivers/power/regulator/rk8xx.c @@ -27,6 +27,10 @@ #define RK808_BUCK4_VSEL_MASK 0xf #define RK808_LDO_VSEL_MASK 0x1f +/* RK809 BUCK5 */ +#define RK809_BUCK5_CONFIG(n) (0xde + (n) * 1) +#define RK809_BUCK5_VSEL_MASK 0x07 + /* RK817 BUCK */ #define RK817_BUCK_ON_VSEL(n) (0xbb + 3 * ((n) - 1)) #define RK817_BUCK_SLP_VSEL(n) (0xbc + 3 * ((n) - 1)) @@ -59,6 +63,7 @@ #define RK805_RAMP_RATE_6MV_PER_US (1 << RK805_RAMP_RATE_OFFSET) #define RK805_RAMP_RATE_12_5MV_PER_US (2 << RK805_RAMP_RATE_OFFSET) #define RK805_RAMP_RATE_25MV_PER_US (3 << RK805_RAMP_RATE_OFFSET) + #define RK808_RAMP_RATE_OFFSET 3 #define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET) #define RK808_RAMP_RATE_2MV_PER_US (0 << RK808_RAMP_RATE_OFFSET) @@ -105,6 +110,14 @@ static const struct rk8xx_reg_info rk816_buck[] = { { 800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK, }, }; +static const struct rk8xx_reg_info rk809_buck5[] = { + /* buck 5 */ + { 1500000, 0, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x00, }, + { 1800000, 200000, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x01, }, + { 2800000, 200000, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x04, }, + { 3300000, 300000, RK809_BUCK5_CONFIG(0), RK809_BUCK5_CONFIG(1), NA, RK809_BUCK5_VSEL_MASK, 0x06, }, +}; + static const struct rk8xx_reg_info rk817_buck[] = { /* buck 1 */ { 500000, 12500, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x00, }, @@ -223,6 +236,7 @@ static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic, return &rk816_buck[num + 4]; } + case RK809_ID: case RK817_ID: switch (num) { case 0 ... 2: @@ -239,6 +253,16 @@ static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic, return &rk817_buck[num * 3 + 1]; else return &rk817_buck[num * 3 + 2]; + /* BUCK5 for RK809 */ + default: + if (uvolt < 1800000) + return &rk809_buck5[0]; + else if (uvolt < 2800000) + return &rk809_buck5[1]; + else if (uvolt < 3300000) + return &rk809_buck5[2]; + else + return &rk809_buck5[3]; } case RK818_ID: return &rk818_buck[num]; @@ -308,6 +332,7 @@ static int _buck_set_enable(struct udevice *pmic, int buck, bool enable) ret = pmic_clrsetbits(pmic, REG_DCDC_EN, mask, enable ? mask : 0); break; + case RK809_ID: case RK817_ID: if (buck < 4) { if (enable) @@ -315,6 +340,13 @@ static int _buck_set_enable(struct udevice *pmic, int buck, bool enable) else value = ((0 << buck) | (1 << (buck + 4))); ret = pmic_reg_write(pmic, RK817_POWER_EN(0), value); + /* BUCK5 for RK809 */ + } else { + if (enable) + value = ((1 << 1) | (1 << 5)); + else + value = ((0 << 1) | (1 << 5)); + ret = pmic_reg_write(pmic, RK817_POWER_EN(3), value); } break; default: @@ -369,10 +401,15 @@ static int _buck_get_enable(struct udevice *pmic, int buck) if (ret < 0) return ret; break; + case RK809_ID: case RK817_ID: if (buck < 4) { mask = 1 << buck; ret = pmic_reg_read(pmic, RK817_POWER_EN(0)); + /* BUCK5 for RK809 */ + } else { + mask = 1 << 1; + ret = pmic_reg_read(pmic, RK817_POWER_EN(3)); } break; } @@ -402,9 +439,12 @@ static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable) ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF1, mask, enable ? 0 : mask); break; + case RK809_ID: case RK817_ID: if (buck < 4) mask = 1 << buck; + else + mask = 1 << 5; /* BUCK5 for RK809 */ ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask, enable ? mask : 0); break; @@ -438,9 +478,12 @@ static int _buck_get_suspend_enable(struct udevice *pmic, int buck) return val; ret = val & mask ? 0 : 1; break; + case RK809_ID: case RK817_ID: if (buck < 4) mask = 1 << buck; + else + mask = 1 << 5; /* BUCK5 for RK809 */ val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(0)); if (val < 0) @@ -463,6 +506,7 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic, case RK805_ID: case RK816_ID: return &rk816_ldo[num]; + case RK809_ID: case RK817_ID: if (uvolt < 3400000) return &rk817_ldo[num * 2 + 0]; @@ -499,6 +543,7 @@ static int _ldo_get_enable(struct udevice *pmic, int ldo) if (ret < 0) return ret; break; + case RK809_ID: case RK817_ID: if (ldo < 4) { mask = 1 << ldo; @@ -549,6 +594,7 @@ static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable) ret = pmic_clrsetbits(pmic, REG_LDO_EN, mask, enable ? mask : 0); break; + case RK809_ID: case RK817_ID: if (ldo < 4) { en_reg = RK817_POWER_EN(1); @@ -591,6 +637,7 @@ static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable) ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF2, mask, enable ? 0 : mask); break; + case RK809_ID: case RK817_ID: if (ldo == 8) { mask = 1 << 4; /* LDO9 */ @@ -630,6 +677,7 @@ static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo) return val; ret = val & mask ? 0 : 1; break; + case RK809_ID: case RK817_ID: if (ldo == 8) { mask = 1 << 4; /* LDO9 */ @@ -849,6 +897,11 @@ static int switch_set_enable(struct udevice *dev, bool enable) ret = pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask, enable ? mask : 0); break; + case RK809_ID: + mask = (1 << (sw + 2)) | (1 << (sw + 6)); + ret = pmic_clrsetbits(dev->parent, RK817_POWER_EN(3), mask, + enable ? mask : 0); + break; case RK818_ID: mask = 1 << 6; ret = pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask, @@ -873,6 +926,10 @@ static int switch_get_enable(struct udevice *dev) mask = 1 << (sw + 5); ret = pmic_reg_read(dev->parent, REG_DCDC_EN); break; + case RK809_ID: + mask = 1 << (sw + 2); + ret = pmic_reg_read(dev->parent, RK817_POWER_EN(3)); + break; case RK818_ID: mask = 1 << 6; ret = pmic_reg_read(dev->parent, REG_DCDC_EN); @@ -907,6 +964,11 @@ static int switch_set_suspend_enable(struct udevice *dev, bool enable) ret = pmic_clrsetbits(dev->parent, REG_SLEEP_SET_OFF1, mask, enable ? 0 : mask); break; + case RK809_ID: + mask = 1 << (sw + 6); + ret = pmic_clrsetbits(dev->parent, RK817_POWER_SLP_EN(0), mask, + enable ? mask : 0); + break; case RK818_ID: mask = 1 << 6; ret = pmic_clrsetbits(dev->parent, REG_SLEEP_SET_OFF1, mask, @@ -934,6 +996,13 @@ static int switch_get_suspend_enable(struct udevice *dev) return val; ret = val & mask ? 0 : 1; break; + case RK809_ID: + mask = 1 << (sw + 6); + val = pmic_reg_read(dev->parent, RK817_POWER_SLP_EN(0)); + if (val < 0) + return val; + ret = val & mask ? 1 : 0; + break; case RK818_ID: mask = 1 << 6; val = pmic_reg_read(dev->parent, REG_SLEEP_SET_OFF1); diff --git a/include/power/rk8xx_pmic.h b/include/power/rk8xx_pmic.h index d93cecedddf..8ff0af35c57 100644 --- a/include/power/rk8xx_pmic.h +++ b/include/power/rk8xx_pmic.h @@ -185,6 +185,7 @@ enum { enum { RK805_ID = 0x8050, RK808_ID = 0x0000, + RK809_ID = 0x8090, RK816_ID = 0x8160, RK817_ID = 0x8170, RK818_ID = 0x8180, -- cgit v1.3.1 From 6024467bcc0e38fb5f1d2d80b73e770c94e4530c Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Fri, 18 Oct 2019 15:54:16 +0800 Subject: rockchip: config: update CONFIG_SPL_MAX_SIZE for 64bit CPUs Since we move the ATF bl31 entry for 64bit CPUs to 0x40000, we need to limit the SPL size in 0x40000(start from 0) so that we don't need to do the relocate for ATF loading. Note that there will be separate BSS, STACK and MALLOC heap, so the size 0x40000(256KB) should be enough for SPL text. Signed-off-by: Kever Yang --- include/configs/rk3328_common.h | 2 +- include/configs/rk3368_common.h | 2 +- include/configs/rk3399_common.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/configs/rk3328_common.h b/include/configs/rk3328_common.h index 3ff3331c808..e51e1b0e0e7 100644 --- a/include/configs/rk3328_common.h +++ b/include/configs/rk3328_common.h @@ -18,7 +18,7 @@ #define CONFIG_SYS_INIT_SP_ADDR 0x00300000 #define CONFIG_SYS_LOAD_ADDR 0x00800800 #define CONFIG_SPL_STACK 0x00400000 -#define CONFIG_SPL_MAX_SIZE 0x100000 +#define CONFIG_SPL_MAX_SIZE 0x40000 #define CONFIG_SPL_BSS_START_ADDR 0x2000000 #define CONFIG_SPL_BSS_MAX_SIZE 0x2000 diff --git a/include/configs/rk3368_common.h b/include/configs/rk3368_common.h index e4b2114a0dd..e57d0efa7f9 100644 --- a/include/configs/rk3368_common.h +++ b/include/configs/rk3368_common.h @@ -27,7 +27,7 @@ #define CONFIG_SYS_INIT_SP_ADDR 0x00300000 #define CONFIG_SYS_LOAD_ADDR 0x00280000 -#define CONFIG_SPL_MAX_SIZE 0x60000 +#define CONFIG_SPL_MAX_SIZE 0x40000 #define CONFIG_SPL_BSS_START_ADDR 0x400000 #define CONFIG_SPL_BSS_MAX_SIZE 0x20000 #define CONFIG_SPL_STACK 0x00188000 diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h index 126c34763ea..7331c6dc026 100644 --- a/include/configs/rk3399_common.h +++ b/include/configs/rk3399_common.h @@ -21,7 +21,7 @@ #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_TPL_BOOTROM_SUPPORT) #define CONFIG_SPL_STACK 0x00400000 -#define CONFIG_SPL_MAX_SIZE 0x100000 +#define CONFIG_SPL_MAX_SIZE 0x40000 #define CONFIG_SPL_BSS_START_ADDR 0x00400000 #define CONFIG_SPL_BSS_MAX_SIZE 0x2000 #else -- cgit v1.3.1