summaryrefslogtreecommitdiff
path: root/drivers/power/regulator/rk8xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/regulator/rk8xx.c')
-rw-r--r--drivers/power/regulator/rk8xx.c595
1 files changed, 549 insertions, 46 deletions
diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c
index e80bd6c3723..1bd4605d43a 100644
--- a/drivers/power/regulator/rk8xx.c
+++ b/drivers/power/regulator/rk8xx.c
@@ -25,6 +25,19 @@
#define NA 0xff
/* Field Definitions */
+#define RK806_BUCK_CONFIG(n) (0x10 + (n) - 1)
+#define RK806_BUCK_ON_VSEL(n) (0x1a + (n) - 1)
+#define RK806_BUCK_SLP_VSEL(n) (0x24 + (n) - 1)
+#define RK806_BUCK_VSEL_MASK 0xff
+
+#define RK806_NLDO_ON_VSEL(n) (0x43 + (n) - 1)
+#define RK806_NLDO_SLP_VSEL(n) (0x48 + (n) - 1)
+#define RK806_NLDO_VSEL_MASK 0xff
+
+#define RK806_PLDO_ON_VSEL(n) (0x4e + (n) - 1)
+#define RK806_PLDO_SLP_VSEL(n) (0x54 + (n) - 1)
+#define RK806_PLDO_VSEL_MASK 0xff
+
#define RK808_BUCK_VSEL_MASK 0x3f
#define RK808_BUCK4_VSEL_MASK 0xf
#define RK808_LDO_VSEL_MASK 0x1f
@@ -91,6 +104,49 @@ struct rk8xx_reg_info {
u8 max_sel;
};
+static const struct rk8xx_reg_info rk806_buck[] = {
+ /* buck 1 */
+ { 500000, 6250, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0x00, 0x9f },
+ { 1500000, 25000, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb },
+ { 3400000, 0, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xec, 0xff },
+ /* buck 2 */
+ { 500000, 6250, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0x00, 0x9f },
+ { 1500000, 25000, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb },
+ { 3400000, 0, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xec, 0xff },
+ /* buck 3 */
+ { 500000, 6250, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0x00, 0x9f },
+ { 1500000, 25000, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb },
+ { 3400000, 0, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xec, 0xff },
+ /* buck 4 */
+ { 500000, 6250, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0x00, 0x9f },
+ { 1500000, 25000, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb },
+ { 3400000, 0, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xec, 0xff },
+ /* buck 5 */
+ { 500000, 6250, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0x00, 0x9f },
+ { 1500000, 25000, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb },
+ { 3400000, 0, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xec, 0xff },
+ /* buck 6 */
+ { 500000, 6250, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0x00, 0x9f },
+ { 1500000, 25000, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb },
+ { 3400000, 0, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xec, 0xff },
+ /* buck 7 */
+ { 500000, 6250, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0x00, 0x9f },
+ { 1500000, 25000, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb },
+ { 3400000, 0, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xec, 0xff },
+ /* buck 8 */
+ { 500000, 6250, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0x00, 0x9f },
+ { 1500000, 25000, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb },
+ { 3400000, 0, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xec, 0xff },
+ /* buck 9 */
+ { 500000, 6250, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0x00, 0x9f },
+ { 1500000, 25000, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb },
+ { 3400000, 0, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xec, 0xff },
+ /* buck 10 */
+ { 500000, 6250, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0x00, 0x9f },
+ { 1500000, 25000, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb },
+ { 3400000, 0, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xec, 0xff },
+};
+
static const struct rk8xx_reg_info rk808_buck[] = {
{ 712500, 12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK808_BUCK_VSEL_MASK, 0x00, 0x3f },
{ 712500, 12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK808_BUCK_VSEL_MASK, 0x00, 0x3f },
@@ -148,6 +204,45 @@ static const struct rk8xx_reg_info rk818_buck[] = {
};
#ifdef ENABLE_DRIVER
+static const struct rk8xx_reg_info rk806_nldo[] = {
+ /* nldo 1 */
+ { 500000, 12500, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0x00, 0xe7},
+ { 3400000, 0, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0xe8, 0xff},
+ /* nldo 2 */
+ { 500000, 12500, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0x00, 0xe7},
+ { 3400000, 0, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0xe8, 0xff},
+ /* nldo 3 */
+ { 500000, 12500, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0x00, 0xe7},
+ { 3400000, 0, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0xe8, 0xff},
+ /* nldo 4 */
+ { 500000, 12500, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0x00, 0xe7},
+ { 3400000, 0, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0xe8, 0xff},
+ /* nldo 5 */
+ { 500000, 12500, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0x00, 0xe7},
+ { 3400000, 0, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0xe8, 0xff},
+};
+
+static const struct rk8xx_reg_info rk806_pldo[] = {
+ /* pldo 1 */
+ { 500000, 12500, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7},
+ { 3400000, 0, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff},
+ /* pldo 2 */
+ { 500000, 12500, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7},
+ { 3400000, 0, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff},
+ /* pldo 3 */
+ { 500000, 12500, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7},
+ { 3400000, 0, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff},
+ /* pldo 4 */
+ { 500000, 12500, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7},
+ { 3400000, 0, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff},
+ /* pldo 5 */
+ { 500000, 12500, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7},
+ { 3400000, 0, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff},
+ /* pldo 6 */
+ { 500000, 12500, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7},
+ { 3400000, 0, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff},
+};
+
static const struct rk8xx_reg_info rk808_ldo[] = {
{ 1800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
{ 1800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
@@ -210,14 +305,6 @@ static const struct rk8xx_reg_info rk818_ldo[] = {
};
#endif
-static const u16 rk818_chrg_cur_input_array[] = {
- 450, 800, 850, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000
-};
-
-static const uint rk818_chrg_shutdown_vsel_array[] = {
- 2780000, 2850000, 2920000, 2990000, 3060000, 3130000, 3190000, 3260000
-};
-
static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic,
int num, int uvolt)
{
@@ -238,7 +325,12 @@ static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic,
default:
return &rk816_buck[num + 4];
}
-
+ case RK806_ID:
+ if (uvolt < 1500000)
+ return &rk806_buck[num * 3 + 0];
+ else if (uvolt < 3400000)
+ return &rk806_buck[num * 3 + 1];
+ return &rk806_buck[num * 3 + 2];
case RK809_ID:
case RK817_ID:
switch (num) {
@@ -322,7 +414,11 @@ static int _buck_set_enable(struct udevice *pmic, int buck, bool enable)
value = ((0 << buck) | (1 << (buck + 4)));
ret = pmic_reg_write(pmic, en_reg, value);
break;
-
+ case RK806_ID:
+ value = RK806_POWER_EN_CLRSETBITS(buck % 4, enable);
+ en_reg = RK806_POWER_EN((buck + 1) / 4);
+ ret = pmic_reg_write(pmic, en_reg, value);
+ break;
case RK808_ID:
case RK818_ID:
mask = 1 << buck;
@@ -397,6 +493,10 @@ static int _buck_get_enable(struct udevice *pmic, int buck)
ret = pmic_reg_read(pmic, RK816_REG_DCDC_EN1);
}
break;
+ case RK806_ID:
+ mask = BIT(buck % 4);
+ ret = pmic_reg_read(pmic, RK806_POWER_EN((buck + 1) / 4));
+ break;
case RK808_ID:
case RK818_ID:
mask = 1 << buck;
@@ -436,6 +536,20 @@ static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable)
ret = pmic_clrsetbits(pmic, RK816_REG_DCDC_SLP_EN, mask,
enable ? mask : 0);
break;
+ case RK806_ID:
+ {
+ u8 reg;
+
+ if (buck + 1 >= 9) {
+ reg = RK806_POWER_SLP_EN1;
+ mask = BIT(buck + 1 - 3);
+ } else {
+ reg = RK806_POWER_SLP_EN0;
+ mask = BIT(buck + 1);
+ }
+ ret = pmic_clrsetbits(pmic, reg, mask, enable ? mask : 0);
+ }
+ break;
case RK808_ID:
case RK818_ID:
mask = 1 << buck;
@@ -473,6 +587,21 @@ static int _buck_get_suspend_enable(struct udevice *pmic, int buck)
return val;
ret = val & mask ? 1 : 0;
break;
+ case RK806_ID:
+ {
+ u8 reg;
+
+ if (buck + 1 >= 9) {
+ reg = RK806_POWER_SLP_EN1;
+ mask = BIT(buck + 1 - 3);
+ } else {
+ reg = RK806_POWER_SLP_EN0;
+ mask = BIT(buck + 1);
+ }
+ val = pmic_reg_read(pmic, reg);
+ }
+ ret = (val & mask) ? 1 : 0;
+ break;
case RK808_ID:
case RK818_ID:
mask = 1 << buck;
@@ -522,6 +651,34 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic,
}
}
+static const struct rk8xx_reg_info *get_nldo_reg(struct udevice *pmic,
+ int num, int uvolt)
+{
+ const struct rk8xx_priv *priv = dev_get_priv(pmic);
+
+ switch (priv->variant) {
+ case RK806_ID:
+ default:
+ if (uvolt < 3400000)
+ return &rk806_nldo[num * 2 + 0];
+ return &rk806_nldo[num * 2 + 1];
+ }
+}
+
+static const struct rk8xx_reg_info *get_pldo_reg(struct udevice *pmic,
+ int num, int uvolt)
+{
+ const struct rk8xx_priv *priv = dev_get_priv(pmic);
+
+ switch (priv->variant) {
+ case RK806_ID:
+ default:
+ if (uvolt < 3400000)
+ return &rk806_pldo[num * 2 + 0];
+ return &rk806_pldo[num * 2 + 1];
+ }
+}
+
static int _ldo_get_enable(struct udevice *pmic, int ldo)
{
struct rk8xx_priv *priv = dev_get_priv(pmic);
@@ -569,6 +726,63 @@ static int _ldo_get_enable(struct udevice *pmic, int ldo)
return ret & mask ? true : false;
}
+static int _nldo_get_enable(struct udevice *pmic, int nldo)
+{
+ struct rk8xx_priv *priv = dev_get_priv(pmic);
+ uint mask = 0;
+ int ret = 0;
+ u8 en_reg = 0;
+
+ switch (priv->variant) {
+ case RK806_ID:
+ default:
+ if (nldo + 1 >= 5) {
+ mask = BIT(2);
+ en_reg = RK806_POWER_EN(5);
+ } else {
+ mask = BIT(nldo);
+ en_reg = RK806_POWER_EN(3);
+ }
+ ret = pmic_reg_read(pmic, en_reg);
+ break;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ return (ret & mask) ? 1 : 0;
+}
+
+static int _pldo_get_enable(struct udevice *pmic, int pldo)
+{
+ struct rk8xx_priv *priv = dev_get_priv(pmic);
+ uint mask = 0;
+ int ret = 0;
+ u8 en_reg = 0;
+
+ switch (priv->variant) {
+ case RK806_ID:
+ default:
+ if (pldo + 1 <= 3) {
+ mask = BIT(pldo + 1);
+ en_reg = RK806_POWER_EN(4);
+ } else if (pldo + 1 == 6) {
+ mask = BIT(0);
+ en_reg = RK806_POWER_EN(4);
+ } else {
+ mask = BIT((pldo + 1) % 4);
+ en_reg = RK806_POWER_EN(5);
+ }
+ ret = pmic_reg_read(pmic, en_reg);
+ break;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ return (ret & mask) ? 1 : 0;
+}
+
static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable)
{
struct rk8xx_priv *priv = dev_get_priv(pmic);
@@ -624,6 +838,62 @@ static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable)
return ret;
}
+static int _nldo_set_enable(struct udevice *pmic, int nldo, bool enable)
+{
+ struct rk8xx_priv *priv = dev_get_priv(pmic);
+ uint value, en_reg;
+ int ret = 0;
+
+ switch (priv->variant) {
+ case RK806_ID:
+ default:
+ if (nldo + 1 >= 5) {
+ value = RK806_POWER_EN_CLRSETBITS(2, enable);
+ en_reg = RK806_POWER_EN(5);
+ } else {
+ value = RK806_POWER_EN_CLRSETBITS(nldo, enable);
+ en_reg = RK806_POWER_EN(3);
+ }
+ ret = pmic_reg_write(pmic, en_reg, value);
+ break;
+ }
+
+ if (enable)
+ udelay(500);
+
+ return ret;
+}
+
+static int _pldo_set_enable(struct udevice *pmic, int pldo, bool enable)
+{
+ struct rk8xx_priv *priv = dev_get_priv(pmic);
+ uint value, en_reg;
+ int ret = 0;
+
+ switch (priv->variant) {
+ case RK806_ID:
+ default:
+ /* PLDO */
+ if (pldo + 1 <= 3) {
+ value = RK806_POWER_EN_CLRSETBITS(pldo + 1, enable);
+ en_reg = RK806_POWER_EN(4);
+ } else if (pldo + 1 == 6) {
+ value = RK806_POWER_EN_CLRSETBITS(0, enable);
+ en_reg = RK806_POWER_EN(4);
+ } else {
+ value = RK806_POWER_EN_CLRSETBITS((pldo + 1) % 4, enable);
+ en_reg = RK806_POWER_EN(5);
+ }
+ ret = pmic_reg_write(pmic, en_reg, value);
+ break;
+ }
+
+ if (enable)
+ udelay(500);
+
+ return ret;
+}
+
static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable)
{
struct rk8xx_priv *priv = dev_get_priv(pmic);
@@ -660,6 +930,43 @@ static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable)
return ret;
}
+static int _nldo_set_suspend_enable(struct udevice *pmic, int nldo, bool enable)
+{
+ struct rk8xx_priv *priv = dev_get_priv(pmic);
+ uint mask;
+ int ret = 0;
+
+ switch (priv->variant) {
+ case RK806_ID:
+ default:
+ mask = BIT(nldo);
+ ret = pmic_clrsetbits(pmic, RK806_POWER_SLP_EN1, mask, enable ? mask : 0);
+ break;
+ }
+
+ return ret;
+}
+
+static int _pldo_set_suspend_enable(struct udevice *pmic, int pldo, bool enable)
+{
+ struct rk8xx_priv *priv = dev_get_priv(pmic);
+ uint mask;
+ int ret = 0;
+
+ switch (priv->variant) {
+ case RK806_ID:
+ default:
+ if (pldo + 1 >= 6)
+ mask = BIT(0);
+ else
+ mask = BIT(pldo + 1);
+ ret = pmic_clrsetbits(pmic, RK806_POWER_SLP_EN2, mask, enable ? mask : 0);
+ break;
+ }
+
+ return ret;
+}
+
static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo)
{
struct rk8xx_priv *priv = dev_get_priv(pmic);
@@ -704,6 +1011,45 @@ static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo)
return ret;
}
+static int _nldo_get_suspend_enable(struct udevice *pmic, int nldo)
+{
+ struct rk8xx_priv *priv = dev_get_priv(pmic);
+ int val, ret = 0;
+ uint mask;
+
+ switch (priv->variant) {
+ case RK806_ID:
+ default:
+ mask = BIT(nldo);
+ val = pmic_reg_read(pmic, RK806_POWER_SLP_EN1);
+ ret = (val & mask) ? 1 : 0;
+ break;
+ }
+
+ return ret;
+}
+
+static int _pldo_get_suspend_enable(struct udevice *pmic, int pldo)
+{
+ struct rk8xx_priv *priv = dev_get_priv(pmic);
+ int val, ret = 0;
+ uint mask;
+
+ switch (priv->variant) {
+ case RK806_ID:
+ default:
+ if (pldo + 1 >= 6)
+ mask = BIT(0);
+ else
+ mask = BIT(pldo + 1);
+ val = pmic_reg_read(pmic, RK806_POWER_SLP_EN2);
+ ret = (val & mask) ? 1 : 0;
+ break;
+ }
+
+ return ret;
+}
+
static int buck_get_value(struct udevice *dev)
{
int buck = dev->driver_data - 1;
@@ -788,10 +1134,8 @@ static int buck_get_enable(struct udevice *dev)
return _buck_get_enable(dev->parent, buck);
}
-static int ldo_get_value(struct udevice *dev)
+static int _ldo_get_value(struct udevice *dev, const struct rk8xx_reg_info *info)
{
- int ldo = dev->driver_data - 1;
- const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0);
int mask = info->vsel_mask;
int ret, val;
@@ -805,10 +1149,32 @@ static int ldo_get_value(struct udevice *dev)
return info->min_uv + val * info->step_uv;
}
-static int ldo_set_value(struct udevice *dev, int uvolt)
+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, uvolt);
+ const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0);
+
+ return _ldo_get_value(dev, info);
+}
+
+static int nldo_get_value(struct udevice *dev)
+{
+ int nldo = dev->driver_data - 1;
+ const struct rk8xx_reg_info *info = get_nldo_reg(dev->parent, nldo, 0);
+
+ return _ldo_get_value(dev, info);
+}
+
+static int pldo_get_value(struct udevice *dev)
+{
+ int pldo = dev->driver_data - 1;
+ const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, pldo, 0);
+
+ return _ldo_get_value(dev, info);
+}
+
+static int _ldo_set_value(struct udevice *dev, const struct rk8xx_reg_info *info, int uvolt)
+{
int mask = info->vsel_mask;
int val;
@@ -820,16 +1186,38 @@ static int ldo_set_value(struct udevice *dev, int uvolt)
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);
+ debug("%s: volt=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
+ __func__, uvolt, info->vsel_reg, mask, val);
return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val);
}
-static int ldo_set_suspend_value(struct udevice *dev, int uvolt)
+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, uvolt);
+
+ return _ldo_set_value(dev, info, uvolt);
+}
+
+static int nldo_set_value(struct udevice *dev, int uvolt)
+{
+ int nldo = dev->driver_data - 1;
+ const struct rk8xx_reg_info *info = get_nldo_reg(dev->parent, nldo, uvolt);
+
+ return _ldo_set_value(dev, info, uvolt);
+}
+
+static int pldo_set_value(struct udevice *dev, int uvolt)
+{
+ int pldo = dev->driver_data - 1;
+ const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, pldo, uvolt);
+
+ return _ldo_set_value(dev, info, uvolt);
+}
+
+static int _ldo_set_suspend_value(struct udevice *dev, const struct rk8xx_reg_info *info, int uvolt)
+{
int mask = info->vsel_mask;
int val;
@@ -841,16 +1229,38 @@ static int ldo_set_suspend_value(struct udevice *dev, int uvolt)
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);
+ debug("%s: volt=%d, reg=0x%x, mask=0x%x, val=0x%x\n",
+ __func__, uvolt, info->vsel_sleep_reg, mask, val);
return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val);
}
-static int ldo_get_suspend_value(struct udevice *dev)
+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, 0);
+ const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt);
+
+ return _ldo_set_suspend_value(dev->parent, info, uvolt);
+}
+
+static int nldo_set_suspend_value(struct udevice *dev, int uvolt)
+{
+ int nldo = dev->driver_data - 1;
+ const struct rk8xx_reg_info *info = get_nldo_reg(dev->parent, nldo, uvolt);
+
+ return _ldo_set_suspend_value(dev->parent, info, uvolt);
+}
+
+static int pldo_set_suspend_value(struct udevice *dev, int uvolt)
+{
+ int pldo = dev->driver_data - 1;
+ const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, pldo, uvolt);
+
+ return _ldo_set_suspend_value(dev->parent, info, uvolt);
+}
+
+static int _ldo_get_suspend_value(struct udevice *dev, const struct rk8xx_reg_info *info)
+{
int mask = info->vsel_mask;
int val, ret;
@@ -866,6 +1276,30 @@ static int ldo_get_suspend_value(struct udevice *dev)
return info->min_uv + val * info->step_uv;
}
+static int ldo_get_suspend_value(struct udevice *dev)
+{
+ int ldo = dev->driver_data - 1;
+ const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0);
+
+ return _ldo_get_suspend_value(dev->parent, info);
+}
+
+static int nldo_get_suspend_value(struct udevice *dev)
+{
+ int nldo = dev->driver_data - 1;
+ const struct rk8xx_reg_info *info = get_nldo_reg(dev->parent, nldo, 0);
+
+ return _ldo_get_suspend_value(dev->parent, info);
+}
+
+static int pldo_get_suspend_value(struct udevice *dev)
+{
+ int pldo = dev->driver_data - 1;
+ const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, pldo, 0);
+
+ return _ldo_get_suspend_value(dev->parent, info);
+}
+
static int ldo_set_enable(struct udevice *dev, bool enable)
{
int ldo = dev->driver_data - 1;
@@ -873,6 +1307,20 @@ static int ldo_set_enable(struct udevice *dev, bool enable)
return _ldo_set_enable(dev->parent, ldo, enable);
}
+static int nldo_set_enable(struct udevice *dev, bool enable)
+{
+ int nldo = dev->driver_data - 1;
+
+ return _nldo_set_enable(dev->parent, nldo, enable);
+}
+
+static int pldo_set_enable(struct udevice *dev, bool enable)
+{
+ int pldo = dev->driver_data - 1;
+
+ return _pldo_set_enable(dev->parent, pldo, enable);
+}
+
static int ldo_set_suspend_enable(struct udevice *dev, bool enable)
{
int ldo = dev->driver_data - 1;
@@ -880,6 +1328,20 @@ static int ldo_set_suspend_enable(struct udevice *dev, bool enable)
return _ldo_set_suspend_enable(dev->parent, ldo, enable);
}
+static int nldo_set_suspend_enable(struct udevice *dev, bool enable)
+{
+ int nldo = dev->driver_data - 1;
+
+ return _nldo_set_suspend_enable(dev->parent, nldo, enable);
+}
+
+static int pldo_set_suspend_enable(struct udevice *dev, bool enable)
+{
+ int pldo = dev->driver_data - 1;
+
+ return _pldo_set_suspend_enable(dev->parent, pldo, enable);
+}
+
static int ldo_get_suspend_enable(struct udevice *dev)
{
int ldo = dev->driver_data - 1;
@@ -887,6 +1349,20 @@ static int ldo_get_suspend_enable(struct udevice *dev)
return _ldo_get_suspend_enable(dev->parent, ldo);
}
+static int nldo_get_suspend_enable(struct udevice *dev)
+{
+ int nldo = dev->driver_data - 1;
+
+ return _nldo_get_suspend_enable(dev->parent, nldo);
+}
+
+static int pldo_get_suspend_enable(struct udevice *dev)
+{
+ int pldo = dev->driver_data - 1;
+
+ return _pldo_get_suspend_enable(dev->parent, pldo);
+}
+
static int ldo_get_enable(struct udevice *dev)
{
int ldo = dev->driver_data - 1;
@@ -894,6 +1370,20 @@ static int ldo_get_enable(struct udevice *dev)
return _ldo_get_enable(dev->parent, ldo);
}
+static int nldo_get_enable(struct udevice *dev)
+{
+ int nldo = dev->driver_data - 1;
+
+ return _nldo_get_enable(dev->parent, nldo);
+}
+
+static int pldo_get_enable(struct udevice *dev)
+{
+ int pldo = dev->driver_data - 1;
+
+ return _pldo_get_enable(dev->parent, pldo);
+}
+
static int switch_set_enable(struct udevice *dev, bool enable)
{
struct rk8xx_priv *priv = dev_get_priv(dev->parent);
@@ -909,7 +1399,7 @@ static int switch_set_enable(struct udevice *dev, bool enable)
case RK809_ID:
mask = (1 << (sw + 2)) | (1 << (sw + 6));
ret = pmic_clrsetbits(dev->parent, RK817_POWER_EN(3), mask,
- enable ? mask : 0);
+ enable ? mask : (1 << (sw + 6)));
break;
case RK818_ID:
mask = 1 << 6;
@@ -1117,6 +1607,28 @@ static const struct dm_regulator_ops rk8xx_ldo_ops = {
.get_suspend_enable = ldo_get_suspend_enable,
};
+static const struct dm_regulator_ops rk8xx_nldo_ops = {
+ .get_value = nldo_get_value,
+ .set_value = nldo_set_value,
+ .set_suspend_value = nldo_set_suspend_value,
+ .get_suspend_value = nldo_get_suspend_value,
+ .get_enable = nldo_get_enable,
+ .set_enable = nldo_set_enable,
+ .set_suspend_enable = nldo_set_suspend_enable,
+ .get_suspend_enable = nldo_get_suspend_enable,
+};
+
+static const struct dm_regulator_ops rk8xx_pldo_ops = {
+ .get_value = pldo_get_value,
+ .set_value = pldo_set_value,
+ .set_suspend_value = pldo_set_suspend_value,
+ .get_suspend_value = pldo_get_suspend_value,
+ .get_enable = pldo_get_enable,
+ .set_enable = pldo_set_enable,
+ .set_suspend_enable = pldo_set_suspend_enable,
+ .get_suspend_enable = pldo_get_suspend_enable,
+};
+
static const struct dm_regulator_ops rk8xx_switch_ops = {
.get_value = switch_get_value,
.set_value = switch_set_value,
@@ -1142,6 +1654,20 @@ U_BOOT_DRIVER(rk8xx_ldo) = {
.probe = rk8xx_ldo_probe,
};
+U_BOOT_DRIVER(rk8xx_nldo) = {
+ .name = "rk8xx_nldo",
+ .id = UCLASS_REGULATOR,
+ .ops = &rk8xx_nldo_ops,
+ .probe = rk8xx_ldo_probe,
+};
+
+U_BOOT_DRIVER(rk8xx_pldo) = {
+ .name = "rk8xx_pldo",
+ .id = UCLASS_REGULATOR,
+ .ops = &rk8xx_pldo_ops,
+ .probe = rk8xx_ldo_probe,
+};
+
U_BOOT_DRIVER(rk8xx_switch) = {
.name = "rk8xx_switch",
.id = UCLASS_REGULATOR,
@@ -1160,26 +1686,3 @@ int rk8xx_spl_configure_buck(struct udevice *pmic, int buck, int uvolt)
return _buck_set_enable(pmic, buck, true);
}
-
-int rk818_spl_configure_usb_input_current(struct udevice *pmic, int current_ma)
-{
- uint i;
-
- for (i = 0; i < ARRAY_SIZE(rk818_chrg_cur_input_array); i++)
- if (current_ma <= rk818_chrg_cur_input_array[i])
- break;
-
- return pmic_clrsetbits(pmic, REG_USB_CTRL, RK818_USB_ILIM_SEL_MASK, i);
-}
-
-int rk818_spl_configure_usb_chrg_shutdown(struct udevice *pmic, int uvolt)
-{
- uint i;
-
- for (i = 0; i < ARRAY_SIZE(rk818_chrg_shutdown_vsel_array); i++)
- if (uvolt <= rk818_chrg_shutdown_vsel_array[i])
- break;
-
- return pmic_clrsetbits(pmic, REG_USB_CTRL, RK818_USB_CHG_SD_VSEL_MASK,
- i);
-}