From 7f18d96c7080c9ed0c4236884e6094197f250da3 Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Wed, 7 Feb 2018 15:08:31 +0800 Subject: [PATCH] pmic: add RK817 support include sub modules: pmic, regulator, pwrkey Change-Id: I3a1cbaa3c4d069cbac17124f9c0fe3b01184697c Signed-off-by: Joseph Chen --- drivers/input/rk8xx_pwrkey.c | 50 +++++++- drivers/power/pmic/rk8xx.c | 34 ++++-- drivers/power/regulator/rk8xx.c | 205 +++++++++++++++++++++++++++++--- include/power/rk8xx_pmic.h | 7 ++ 4 files changed, 269 insertions(+), 27 deletions(-) diff --git a/drivers/input/rk8xx_pwrkey.c b/drivers/input/rk8xx_pwrkey.c index 68530a6fd0..f9a8dd7816 100644 --- a/drivers/input/rk8xx_pwrkey.c +++ b/drivers/input/rk8xx_pwrkey.c @@ -14,6 +14,17 @@ #include #include +#define RK817_GPIO_INT_CFG 0xfe +#define RK817_INT_STS_REG0 0xf8 +#define RK817_INT_MSK_REG0 0xf9 +#define RK817_INT_STS_REG1 0xfa +#define RK817_INT_MSK_REG1 0xfb +#define RK817_INT_STS_REG2 0xfc +#define RK817_INT_MSK_REG2 0xfd +#define RK817_PWRON_RISE_INT (1 << 1) +#define RK817_PWRON_FALL_INT (1 << 0) +#define RK817_INT_POL_MSK BIT(1) + #define RK816_INT_STS_REG1 0x49 #define RK816_INT_MSK_REG1 0x4a #define RK816_INT_STS_REG2 0x4c @@ -44,6 +55,26 @@ struct rk8xx_key_priv { u32 irq_reg_num; }; +static struct reg_data rk817_init_reg[] = { + /* only enable rise/fall interrupt */ + { RK817_INT_MSK_REG0, 0xfc }, + { RK817_INT_MSK_REG1, 0xff }, + { RK817_INT_MSK_REG2, 0xff }, + /* clear all interrupt states */ + { RK817_INT_STS_REG0, 0xff }, + { RK817_INT_STS_REG1, 0xff }, + { RK817_INT_STS_REG2, 0xff }, + /* pmic_int active low */ + { RK817_GPIO_INT_CFG, 0x20 }, +}; + +static struct reg_data rk817_irq_reg[] = { + /* clear all interrupt states */ + { RK817_INT_STS_REG0, 0xff }, + { RK817_INT_STS_REG1, 0xff }, + { RK817_INT_STS_REG2, 0xff }, +}; + static struct reg_data rk816_init_reg[] = { /* only enable rise/fall interrupt */ { RK816_INT_MSK_REG1, 0x9f }, @@ -118,6 +149,8 @@ static void pwrkey_irq_handler(int irq, void *data) struct input_key *key = dev_get_platdata(dev); int ret, val, i; + debug("%s: irq = %d\n", __func__, irq); + /* read status */ val = pmic_reg_read(dev->parent, priv->int_sts_reg); if (val < 0) { @@ -146,6 +179,9 @@ static void pwrkey_irq_handler(int irq, void *data) printf("%s: i2c write reg 0x%x failed, ret=%d\n", __func__, priv->irq_reg[i].reg, ret); } + + debug("%s: reg[0x%x] = 0x%x\n", __func__, priv->irq_reg[i].reg, + pmic_reg_read(dev->parent, priv->irq_reg[i].reg)); } } @@ -210,7 +246,16 @@ static int rk8xx_pwrkey_probe(struct udevice *dev) priv->irq_reg = rk816_irq_reg; priv->irq_reg_num = ARRAY_SIZE(rk816_irq_reg); break; - + case RK817_ID: + priv->int_sts_reg = RK817_INT_STS_REG0; + priv->int_msk_reg = RK817_INT_MSK_REG0; + priv->pwron_rise_int = RK817_PWRON_RISE_INT; + priv->pwron_fall_int = RK817_PWRON_FALL_INT; + priv->init_reg = rk817_init_reg; + priv->init_reg_num = ARRAY_SIZE(rk817_init_reg); + priv->irq_reg = rk817_irq_reg; + priv->irq_reg_num = ARRAY_SIZE(rk817_irq_reg); + break; default: return -EINVAL; } @@ -225,6 +270,9 @@ static int rk8xx_pwrkey_probe(struct udevice *dev) __func__, priv->init_reg[i].reg, ret); return ret; } + + debug("%s: reg[%x] = 0x%x\n", __func__, priv->init_reg[i].reg, + pmic_reg_read(dev->parent, priv->init_reg[i].reg)); } return pwrkey_interrupt_init(dev); diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c index 4aa6e64978..81bbc38891 100644 --- a/drivers/power/pmic/rk8xx.c +++ b/drivers/power/pmic/rk8xx.c @@ -27,6 +27,7 @@ static const struct pmic_child_info power_key_info[] = { static const struct pmic_child_info fuel_gauge_info[] = { { .prefix = "battery", .driver = "rk818_fg"}, + { .prefix = "battery", .driver = "rk817_fg"}, { .prefix = "battery", .driver = "rk816_fg"}, { }, }; @@ -66,16 +67,22 @@ static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len) static int rk8xx_shutdown(struct udevice *dev) { struct rk8xx_priv *priv = dev_get_priv(dev); - u8 val, dev_off; + u8 val, dev_off, devctrl_reg; int ret = 0; switch (priv->variant) { case RK808_ID: + devctrl_reg = REG_DEVCTRL; dev_off = BIT(3); break; case RK805_ID: case RK816_ID: case RK818_ID: + devctrl_reg = REG_DEVCTRL; + dev_off = BIT(0); + break; + case RK817_ID: + devctrl_reg = RK817_REG_SYS_CFG3; dev_off = BIT(0); break; default: @@ -83,18 +90,18 @@ static int rk8xx_shutdown(struct udevice *dev) return -EINVAL; } - ret = dm_i2c_read(dev, REG_DEVCTRL, &val, 1); + ret = dm_i2c_read(dev, devctrl_reg, &val, 1); if (ret) { printf("read error from device: %p register: %#x!", - dev, REG_DEVCTRL); + dev, devctrl_reg); return ret; } val |= dev_off; - ret = dm_i2c_write(dev, REG_DEVCTRL, &val, 1); + ret = dm_i2c_write(dev, devctrl_reg, &val, 1); if (ret) { printf("write error to device: %p register: %#x!", - dev, REG_DEVCTRL); + dev, devctrl_reg); return ret; } @@ -136,14 +143,24 @@ 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; + uint8_t msb, lsb, id_msb, id_lsb; /* 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; + } + + rk8xx_read(dev, id_msb, &msb, 1); + rk8xx_read(dev, id_lsb, &lsb, 1); priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK; + printf("PMIC: RK%x\n", priv->variant); + return 0; } @@ -158,6 +175,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 9b51c243dc..eae5112010 100644 --- a/drivers/power/regulator/rk8xx.c +++ b/drivers/power/regulator/rk8xx.c @@ -33,12 +33,27 @@ #define RK818_USB_ILIM_SEL_MASK 0x0f #define RK818_USB_CHG_SD_VSEL_MASK 0x70 +/* 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 + +/* 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)) + struct rk8xx_reg_info { uint min_uv; uint step_uv; - s8 vsel_reg; - s8 vsel_sleep_reg; + u8 vsel_reg; + u8 vsel_sleep_reg; u8 vsel_mask; + u8 min_sel; }; static const struct rk8xx_reg_info rk808_buck[] = { @@ -63,6 +78,25 @@ static const struct rk8xx_reg_info rk816_buck[] = { { 800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, 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_VSEL_MASK, 0x00, }, + { 1500000, 100000, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_VSEL_MASK, 0x50, }, + { 2400000, 0, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_VSEL_MASK, 0x59, }, + /* buck 2 */ + { 500000, 12500, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_VSEL_MASK, 0x00, }, + { 1500000, 100000, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_VSEL_MASK, 0x50, }, + { 2400000, 0, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_VSEL_MASK, 0x59, }, + /* buck 3 */ + { 500000, 12500, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_VSEL_MASK, 0x00, }, + { 1500000, 100000, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_VSEL_MASK, 0x50, }, + { 2400000, 0, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_VSEL_MASK, 0x59, }, + /* buck 4 */ + { 500000, 12500, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_VSEL_MASK, 0x00, }, + { 1500000, 100000, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_VSEL_MASK, 0x50, }, + { 3400000, 0, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_VSEL_MASK, 0x63, }, +}; + static const struct rk8xx_reg_info rk818_buck[] = { { 712500, 12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, RK818_BUCK_VSEL_MASK, }, { 712500, 12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, RK818_BUCK_VSEL_MASK, }, @@ -91,6 +125,36 @@ static const struct rk8xx_reg_info rk816_ldo[] = { { 800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, 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), RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(1), RK817_LDO_SLP_VSEL(1), RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo2 */ + { 600000, 25000, RK817_LDO_ON_VSEL(2), RK817_LDO_SLP_VSEL(2), RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(2), RK817_LDO_SLP_VSEL(2), RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo3 */ + { 600000, 25000, RK817_LDO_ON_VSEL(3), RK817_LDO_SLP_VSEL(3), RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(3), RK817_LDO_SLP_VSEL(3), RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo4 */ + { 600000, 25000, RK817_LDO_ON_VSEL(4), RK817_LDO_SLP_VSEL(4), RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(4), RK817_LDO_SLP_VSEL(4), RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo5 */ + { 600000, 25000, RK817_LDO_ON_VSEL(5), RK817_LDO_SLP_VSEL(5), RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(5), RK817_LDO_SLP_VSEL(5), RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo6 */ + { 600000, 25000, RK817_LDO_ON_VSEL(6), RK817_LDO_SLP_VSEL(6), RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(6), RK817_LDO_SLP_VSEL(6), RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo7 */ + { 600000, 25000, RK817_LDO_ON_VSEL(7), RK817_LDO_SLP_VSEL(7), RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(7), RK817_LDO_SLP_VSEL(7), RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo8 */ + { 600000, 25000, RK817_LDO_ON_VSEL(8), RK817_LDO_SLP_VSEL(8), RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(8), RK817_LDO_SLP_VSEL(8), RK817_LDO_VSEL_MASK, 0x70, }, + /* ldo9 */ + { 600000, 25000, RK817_LDO_ON_VSEL(9), RK817_LDO_SLP_VSEL(9), RK817_LDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK817_LDO_ON_VSEL(9), RK817_LDO_SLP_VSEL(9), RK817_LDO_VSEL_MASK, 0x70, }, +}; + static const struct rk8xx_reg_info rk818_ldo[] = { { 1800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, RK818_LDO_VSEL_MASK, }, { 1800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, RK818_LDO_VSEL_MASK, }, @@ -131,6 +195,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]; + default: + 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: @@ -146,9 +228,14 @@ static int _buck_set_value(struct udevice *pmic, int buck, int uvolt) if (info->vsel_reg == -1) return -ENOSYS; - val = (uvolt - info->min_uv) / info->step_uv; - debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask, - val); + + if (info->step_uv == 0) /* Fixed voltage */ + val = info->min_sel; + else + val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; + + 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); } @@ -191,6 +278,13 @@ 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 (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; } @@ -207,9 +301,14 @@ static int _buck_set_suspend_value(struct udevice *pmic, int buck, int uvolt) if (info->vsel_sleep_reg == -1) return -ENOSYS; - val = (uvolt - info->min_uv) / info->step_uv; - debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_sleep_reg, mask, - val); + + if (info->step_uv == 0) + val = info->min_sel; + else + val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; + + debug("%s: volt=%d, buck=%d, reg=0x%x, mask=0x%x, val=0x%x\n", + __func__, uvolt, buck+1, info->vsel_sleep_reg, mask, val); return pmic_clrsetbits(pmic, info->vsel_sleep_reg, mask, val); } @@ -238,6 +337,11 @@ static int _buck_get_enable(struct udevice *pmic, int buck) if (ret < 0) return ret; break; + case RK817_ID: + mask = 1 << buck; + ret = pmic_reg_read(pmic, RK817_POWER_EN(0)); + debug("%s: %s, buck=%d, en=%x\n", __func__, pmic->name, buck, ret); + break; } return ret & mask ? true : false; } @@ -262,6 +366,11 @@ 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: + mask = 1 << buck; + ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask, + enable ? mask : 0); + break; default: ret = -EINVAL; } @@ -270,7 +379,7 @@ static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable) } static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic, - int num) + int num, int uvolt) { struct rk8xx_priv *priv = dev_get_priv(pmic); @@ -278,6 +387,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: @@ -309,6 +423,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; } return ret & mask ? true : false; } @@ -341,6 +469,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; @@ -365,6 +511,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; @@ -373,12 +530,14 @@ static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable) static int buck_get_value(struct udevice *dev) { int buck = dev->driver_data - 1; + /* We assume level-1 voltage is enough for usage in U-Boot */ const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck, 0); int mask = info->vsel_mask; int ret, val; if (info->vsel_reg == -1) return -ENOSYS; + ret = pmic_reg_read(dev->parent, info->vsel_reg); if (ret < 0) return ret; @@ -425,7 +584,7 @@ static int buck_get_enable(struct udevice *dev) static int ldo_get_value(struct udevice *dev) { int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo); + const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0); int mask = info->vsel_mask; int ret, val; @@ -442,15 +601,20 @@ static int ldo_get_value(struct udevice *dev) static int ldo_set_value(struct udevice *dev, int uvolt) { int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo); + const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt); int mask = info->vsel_mask; int val; if (info->vsel_reg == -1) return -ENOSYS; - val = (uvolt - info->min_uv) / info->step_uv; - debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask, - val); + + if (info->step_uv == 0) + val = info->min_sel; + else + val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; + + debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", + __func__, uvolt, ldo+1, info->vsel_reg, mask, val); return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val); } @@ -458,15 +622,20 @@ static int ldo_set_value(struct udevice *dev, int uvolt) static int ldo_set_suspend_value(struct udevice *dev, int uvolt) { int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo); + const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt); int mask = info->vsel_mask; int val; if (info->vsel_sleep_reg == -1) return -ENOSYS; - val = (uvolt - info->min_uv) / info->step_uv; - debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_sleep_reg, mask, - val); + + if (info->step_uv == 0) + val = info->min_sel; + else + val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; + + debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", + __func__, uvolt, ldo+1, info->vsel_sleep_reg, mask, val); return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val); } diff --git a/include/power/rk8xx_pmic.h b/include/power/rk8xx_pmic.h index 699fd87dba..79c57896bd 100644 --- a/include/power/rk8xx_pmic.h +++ b/include/power/rk8xx_pmic.h @@ -170,6 +170,10 @@ enum { RK808_NUM_OF_REGS, }; +enum { + RK817_REG_SYS_CFG3 = 0xf4, +}; + enum { RK816_REG_DCDC_EN1 = 0x23, RK816_REG_DCDC_EN2, @@ -183,9 +187,12 @@ enum { RK805_ID = 0x8050, RK808_ID = 0x0000, RK816_ID = 0x8160, + RK817_ID = 0x8170, RK818_ID = 0x8180, }; +#define RK817_ID_MSB 0xed +#define RK817_ID_LSB 0xee #define RK8XX_ID_MSK 0xfff0 struct rk8xx_reg_table {