pmic: add RK817 support

include sub modules: pmic, regulator, pwrkey

Change-Id: I3a1cbaa3c4d069cbac17124f9c0fe3b01184697c
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
Joseph Chen 2018-02-07 15:08:31 +08:00 committed by Kever Yang
parent 2f22a22f29
commit 7f18d96c70
4 changed files with 269 additions and 27 deletions

View File

@ -14,6 +14,17 @@
#include <asm/arch/periph.h> #include <asm/arch/periph.h>
#include <dm/pinctrl.h> #include <dm/pinctrl.h>
#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_STS_REG1 0x49
#define RK816_INT_MSK_REG1 0x4a #define RK816_INT_MSK_REG1 0x4a
#define RK816_INT_STS_REG2 0x4c #define RK816_INT_STS_REG2 0x4c
@ -44,6 +55,26 @@ struct rk8xx_key_priv {
u32 irq_reg_num; 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[] = { static struct reg_data rk816_init_reg[] = {
/* only enable rise/fall interrupt */ /* only enable rise/fall interrupt */
{ RK816_INT_MSK_REG1, 0x9f }, { 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); struct input_key *key = dev_get_platdata(dev);
int ret, val, i; int ret, val, i;
debug("%s: irq = %d\n", __func__, irq);
/* read status */ /* read status */
val = pmic_reg_read(dev->parent, priv->int_sts_reg); val = pmic_reg_read(dev->parent, priv->int_sts_reg);
if (val < 0) { 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", printf("%s: i2c write reg 0x%x failed, ret=%d\n",
__func__, priv->irq_reg[i].reg, ret); __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 = rk816_irq_reg;
priv->irq_reg_num = ARRAY_SIZE(rk816_irq_reg); priv->irq_reg_num = ARRAY_SIZE(rk816_irq_reg);
break; 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: default:
return -EINVAL; return -EINVAL;
} }
@ -225,6 +270,9 @@ static int rk8xx_pwrkey_probe(struct udevice *dev)
__func__, priv->init_reg[i].reg, ret); __func__, priv->init_reg[i].reg, ret);
return 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); return pwrkey_interrupt_init(dev);

View File

@ -27,6 +27,7 @@ static const struct pmic_child_info power_key_info[] = {
static const struct pmic_child_info fuel_gauge_info[] = { static const struct pmic_child_info fuel_gauge_info[] = {
{ .prefix = "battery", .driver = "rk818_fg"}, { .prefix = "battery", .driver = "rk818_fg"},
{ .prefix = "battery", .driver = "rk817_fg"},
{ .prefix = "battery", .driver = "rk816_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) static int rk8xx_shutdown(struct udevice *dev)
{ {
struct rk8xx_priv *priv = dev_get_priv(dev); struct rk8xx_priv *priv = dev_get_priv(dev);
u8 val, dev_off; u8 val, dev_off, devctrl_reg;
int ret = 0; int ret = 0;
switch (priv->variant) { switch (priv->variant) {
case RK808_ID: case RK808_ID:
devctrl_reg = REG_DEVCTRL;
dev_off = BIT(3); dev_off = BIT(3);
break; break;
case RK805_ID: case RK805_ID:
case RK816_ID: case RK816_ID:
case RK818_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); dev_off = BIT(0);
break; break;
default: default:
@ -83,18 +90,18 @@ static int rk8xx_shutdown(struct udevice *dev)
return -EINVAL; return -EINVAL;
} }
ret = dm_i2c_read(dev, REG_DEVCTRL, &val, 1); ret = dm_i2c_read(dev, devctrl_reg, &val, 1);
if (ret) { if (ret) {
printf("read error from device: %p register: %#x!", printf("read error from device: %p register: %#x!",
dev, REG_DEVCTRL); dev, devctrl_reg);
return ret; return ret;
} }
val |= dev_off; val |= dev_off;
ret = dm_i2c_write(dev, REG_DEVCTRL, &val, 1); ret = dm_i2c_write(dev, devctrl_reg, &val, 1);
if (ret) { if (ret) {
printf("write error to device: %p register: %#x!", printf("write error to device: %p register: %#x!",
dev, REG_DEVCTRL); dev, devctrl_reg);
return ret; return ret;
} }
@ -136,14 +143,24 @@ static int rk8xx_bind(struct udevice *dev)
static int rk8xx_probe(struct udevice *dev) static int rk8xx_probe(struct udevice *dev)
{ {
struct rk8xx_priv *priv = dev_get_priv(dev); struct rk8xx_priv *priv = dev_get_priv(dev);
uint8_t msb, lsb; uint8_t msb, lsb, id_msb, id_lsb;
/* read Chip variant */ /* read Chip variant */
rk8xx_read(dev, ID_MSB, &msb, 1); if (device_is_compatible(dev, "rockchip,rk817")) {
rk8xx_read(dev, ID_LSB, &lsb, 1); 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; priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
printf("PMIC: RK%x\n", priv->variant);
return 0; return 0;
} }
@ -158,6 +175,7 @@ static const struct udevice_id rk8xx_ids[] = {
{ .compatible = "rockchip,rk805" }, { .compatible = "rockchip,rk805" },
{ .compatible = "rockchip,rk808" }, { .compatible = "rockchip,rk808" },
{ .compatible = "rockchip,rk816" }, { .compatible = "rockchip,rk816" },
{ .compatible = "rockchip,rk817" },
{ .compatible = "rockchip,rk818" }, { .compatible = "rockchip,rk818" },
{ } { }
}; };

View File

@ -33,12 +33,27 @@
#define RK818_USB_ILIM_SEL_MASK 0x0f #define RK818_USB_ILIM_SEL_MASK 0x0f
#define RK818_USB_CHG_SD_VSEL_MASK 0x70 #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 { struct rk8xx_reg_info {
uint min_uv; uint min_uv;
uint step_uv; uint step_uv;
s8 vsel_reg; u8 vsel_reg;
s8 vsel_sleep_reg; u8 vsel_sleep_reg;
u8 vsel_mask; u8 vsel_mask;
u8 min_sel;
}; };
static const struct rk8xx_reg_info rk808_buck[] = { 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, }, { 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[] = { 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_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, }, { 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, }, { 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[] = { 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_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, }, { 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: default:
return &rk816_buck[num + 4]; 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: case RK818_ID:
return &rk818_buck[num]; return &rk818_buck[num];
default: default:
@ -146,9 +228,14 @@ static int _buck_set_value(struct udevice *pmic, int buck, int uvolt)
if (info->vsel_reg == -1) if (info->vsel_reg == -1)
return -ENOSYS; return -ENOSYS;
val = (uvolt - info->min_uv) / info->step_uv;
debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask, if (info->step_uv == 0) /* Fixed voltage */
val); 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); 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, ret = pmic_clrsetbits(pmic, REG_DCDC_EN, mask,
enable ? mask : 0); enable ? mask : 0);
break; 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: default:
ret = -EINVAL; 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) if (info->vsel_sleep_reg == -1)
return -ENOSYS; 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, if (info->step_uv == 0)
val); 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); 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) if (ret < 0)
return ret; return ret;
break; 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; 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, ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF1, mask,
enable ? 0 : mask); enable ? 0 : mask);
break; break;
case RK817_ID:
mask = 1 << buck;
ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask,
enable ? mask : 0);
break;
default: default:
ret = -EINVAL; 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, 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); 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 RK805_ID:
case RK816_ID: case RK816_ID:
return &rk816_ldo[num]; 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: case RK818_ID:
return &rk818_ldo[num]; return &rk818_ldo[num];
default: default:
@ -309,6 +423,20 @@ static int _ldo_get_enable(struct udevice *pmic, int ldo)
if (ret < 0) if (ret < 0)
return ret; return ret;
break; 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; 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, ret = pmic_clrsetbits(pmic, REG_LDO_EN, mask,
enable ? mask : 0); enable ? mask : 0);
break; 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; 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, ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF2, mask,
enable ? 0 : mask); enable ? 0 : mask);
break; 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; 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) static int buck_get_value(struct udevice *dev)
{ {
int buck = dev->driver_data - 1; 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); const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck, 0);
int mask = info->vsel_mask; int mask = info->vsel_mask;
int ret, val; int ret, val;
if (info->vsel_reg == -1) if (info->vsel_reg == -1)
return -ENOSYS; return -ENOSYS;
ret = pmic_reg_read(dev->parent, info->vsel_reg); ret = pmic_reg_read(dev->parent, info->vsel_reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -425,7 +584,7 @@ static int buck_get_enable(struct udevice *dev)
static int ldo_get_value(struct udevice *dev) static int ldo_get_value(struct udevice *dev)
{ {
int ldo = dev->driver_data - 1; 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 mask = info->vsel_mask;
int ret, val; 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) static int ldo_set_value(struct udevice *dev, int uvolt)
{ {
int ldo = dev->driver_data - 1; 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 mask = info->vsel_mask;
int val; int val;
if (info->vsel_reg == -1) if (info->vsel_reg == -1)
return -ENOSYS; return -ENOSYS;
val = (uvolt - info->min_uv) / info->step_uv;
debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask, if (info->step_uv == 0)
val); 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); 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) static int ldo_set_suspend_value(struct udevice *dev, int uvolt)
{ {
int ldo = dev->driver_data - 1; 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 mask = info->vsel_mask;
int val; int val;
if (info->vsel_sleep_reg == -1) if (info->vsel_sleep_reg == -1)
return -ENOSYS; 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, if (info->step_uv == 0)
val); 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); return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val);
} }

View File

@ -170,6 +170,10 @@ enum {
RK808_NUM_OF_REGS, RK808_NUM_OF_REGS,
}; };
enum {
RK817_REG_SYS_CFG3 = 0xf4,
};
enum { enum {
RK816_REG_DCDC_EN1 = 0x23, RK816_REG_DCDC_EN1 = 0x23,
RK816_REG_DCDC_EN2, RK816_REG_DCDC_EN2,
@ -183,9 +187,12 @@ enum {
RK805_ID = 0x8050, RK805_ID = 0x8050,
RK808_ID = 0x0000, RK808_ID = 0x0000,
RK816_ID = 0x8160, RK816_ID = 0x8160,
RK817_ID = 0x8170,
RK818_ID = 0x8180, RK818_ID = 0x8180,
}; };
#define RK817_ID_MSB 0xed
#define RK817_ID_LSB 0xee
#define RK8XX_ID_MSK 0xfff0 #define RK8XX_ID_MSK 0xfff0
struct rk8xx_reg_table { struct rk8xx_reg_table {