All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v1 0/8] power: pmic: support more PMIC
@ 2019-09-04  7:08 Elaine Zhang
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 1/7] dm: regulator: support regulator more state Elaine Zhang
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: Elaine Zhang @ 2019-09-04  7:08 UTC (permalink / raw)
  To: u-boot

Support more PMIC and improve compatibility between pmics.

Elaine Zhang (2):
  power: pmic: rk816: support rk816 pmic
  power: pmic: rk805: support rk805 pmic

Joseph Chen (6):
  dm: regulator: support regulator more state
  power: pmic: rk8xx: bind more function
  dm: pmic: add pmic_shutdown() interface
  power: pmic: rk8xx: add pmic_shutdown() implement
  pmic: add RK817 support
  pmic: add rk809 support

 drivers/power/pmic/pmic-uclass.c           |  11 +
 drivers/power/pmic/rk8xx.c                 | 173 +++++-
 drivers/power/regulator/regulator-uclass.c |  67 ++
 drivers/power/regulator/rk8xx.c            | 940 ++++++++++++++++++++++++++---
 include/power/pmic.h                       |   9 +
 include/power/regulator.h                  |  42 ++
 include/power/rk8xx_pmic.h                 |  42 ++
 7 files changed, 1196 insertions(+), 88 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v1 1/7] dm: regulator: support regulator more state
  2019-09-04  7:08 [U-Boot] [PATCH v1 0/8] power: pmic: support more PMIC Elaine Zhang
@ 2019-09-04  7:08 ` Elaine Zhang
  2019-09-04 10:19   ` Lukasz Majewski
  2019-09-17  5:47   ` Simon Glass
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 2/7] power: pmic: rk816: support rk816 pmic Elaine Zhang
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 12+ messages in thread
From: Elaine Zhang @ 2019-09-04  7:08 UTC (permalink / raw)
  To: u-boot

From: Joseph Chen <chenjh@rock-chips.com>

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 <chenjh@rock-chips.com>
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/power/regulator/regulator-uclass.c | 67 ++++++++++++++++++++++++++++++
 include/power/regulator.h                  | 42 +++++++++++++++++++
 2 files changed, 109 insertions(+)

diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
index 76be95bcd159..972a5b210c3c 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -77,6 +77,33 @@ int regulator_set_value(struct udevice *dev, int uV)
 	return ret;
 }
 
+int regulator_set_suspend_value(struct udevice *dev, int uV)
+{
+	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+	if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV)
+		return -EINVAL;
+	if (uc_pdata->max_uV != -ENODATA && uV > uc_pdata->max_uV)
+		return -EINVAL;
+
+	if (!ops || !ops->set_suspend_value)
+		return -ENOSYS;
+
+	return ops->set_suspend_value(dev, uV);
+}
+
+int regulator_get_suspend_value(struct udevice *dev)
+{
+	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
+
+	if (!ops || !ops->get_suspend_value)
+		return -ENOSYS;
+
+	return ops->get_suspend_value(dev);
+}
+
 /*
  * To be called with at most caution as there is no check
  * before setting the actual voltage value.
@@ -170,6 +197,26 @@ int regulator_set_enable_if_allowed(struct udevice *dev, bool enable)
 	return ret;
 }
 
+int regulator_set_suspend_enable(struct udevice *dev, bool enable)
+{
+	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
+
+	if (!ops || !ops->set_suspend_enable)
+		return -ENOSYS;
+
+	return ops->set_suspend_enable(dev, enable);
+}
+
+int regulator_get_suspend_enable(struct udevice *dev)
+{
+	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
+
+	if (!ops || !ops->get_suspend_enable)
+		return -ENOSYS;
+
+	return ops->get_suspend_enable(dev);
+}
+
 int regulator_get_mode(struct udevice *dev)
 {
 	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
@@ -235,6 +282,11 @@ int regulator_autoset(struct udevice *dev)
 	int ret = 0;
 
 	uc_pdata = dev_get_uclass_platdata(dev);
+
+	ret = regulator_set_suspend_enable(dev, uc_pdata->suspend_on);
+	if (!ret && uc_pdata->suspend_on)
+		ret = regulator_set_suspend_value(dev, uc_pdata->suspend_uV);
+
 	if (!uc_pdata->always_on && !uc_pdata->boot_on)
 		return -EMEDIUMTYPE;
 
@@ -243,6 +295,8 @@ int regulator_autoset(struct udevice *dev)
 
 	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
 		ret = regulator_set_value(dev, uc_pdata->min_uV);
+	if (uc_pdata->init_uV > 0)
+		ret = regulator_set_value(dev, uc_pdata->init_uV);
 	if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
 		ret = regulator_set_current(dev, uc_pdata->min_uA);
 
@@ -363,6 +417,7 @@ static int regulator_post_bind(struct udevice *dev)
 static int regulator_pre_probe(struct udevice *dev)
 {
 	struct dm_regulator_uclass_platdata *uc_pdata;
+	ofnode node;
 
 	uc_pdata = dev_get_uclass_platdata(dev);
 	if (!uc_pdata)
@@ -373,6 +428,8 @@ static int regulator_pre_probe(struct udevice *dev)
 						-ENODATA);
 	uc_pdata->max_uV = dev_read_u32_default(dev, "regulator-max-microvolt",
 						-ENODATA);
+	uc_pdata->init_uV = dev_read_u32_default(dev, "regulator-init-microvolt",
+						-ENODATA);
 	uc_pdata->min_uA = dev_read_u32_default(dev, "regulator-min-microamp",
 						-ENODATA);
 	uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
@@ -382,6 +439,16 @@ static int regulator_pre_probe(struct udevice *dev)
 	uc_pdata->ramp_delay = dev_read_u32_default(dev, "regulator-ramp-delay",
 						    0);
 
+	node = dev_read_subnode(dev, "regulator-state-mem");
+	if (ofnode_valid(node)) {
+		uc_pdata->suspend_on = !ofnode_read_bool(node, "regulator-off-in-suspend");
+		if (ofnode_read_u32(node, "regulator-suspend-microvolt", &uc_pdata->suspend_uV))
+			uc_pdata->suspend_uV = uc_pdata->max_uA;
+	} else {
+		uc_pdata->suspend_on = true;
+		uc_pdata->suspend_uV = uc_pdata->max_uA;
+	}
+
 	/* Those values are optional (-ENODATA if unset) */
 	if ((uc_pdata->min_uV != -ENODATA) &&
 	    (uc_pdata->max_uV != -ENODATA) &&
diff --git a/include/power/regulator.h b/include/power/regulator.h
index 6c6e2cd4f996..64c5108950a0 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 */
@@ -192,6 +195,8 @@ struct dm_regulator_ops {
 	 */
 	int (*get_value)(struct udevice *dev);
 	int (*set_value)(struct udevice *dev, int uV);
+	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.
@@ -216,6 +221,8 @@ struct dm_regulator_ops {
 	 */
 	int (*get_enable)(struct udevice *dev);
 	int (*set_enable)(struct udevice *dev, bool enable);
+	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-
@@ -262,6 +269,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
  *
@@ -317,6 +341,24 @@ 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 - 0 on success 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
  *
  * @dev    - pointer to the regulator device
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v1 2/7] power: pmic: rk816: support rk816 pmic
  2019-09-04  7:08 [U-Boot] [PATCH v1 0/8] power: pmic: support more PMIC Elaine Zhang
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 1/7] dm: regulator: support regulator more state Elaine Zhang
@ 2019-09-04  7:08 ` Elaine Zhang
  2019-09-04  7:45   ` Kever Yang
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 3/7] power: pmic: rk805: support rk805 pmic Elaine Zhang
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 12+ messages in thread
From: Elaine Zhang @ 2019-09-04  7:08 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/power/pmic/rk8xx.c      |   1 +
 drivers/power/regulator/rk8xx.c | 674 +++++++++++++++++++++++++++++++++++-----
 include/power/rk8xx_pmic.h      |  11 +-
 3 files changed, 600 insertions(+), 86 deletions(-)

diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index 25c339ab12cc..1900de9d1cdb 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 aa4f3a161c47..a62af0b467ef 100644
--- a/drivers/power/regulator/rk8xx.c
+++ b/drivers/power/regulator/rk8xx.c
@@ -1,4 +1,3 @@
-// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (C) 2015 Google, Inc
  * Written by Simon Glass <sjg@chromium.org>
@@ -6,6 +5,8 @@
  * Based on Rockchip's drivers/power/pmic/pmic_rk808.c:
  * Copyright (C) 2012 rockchips
  * zyw <zyw@rock-chips.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
@@ -19,6 +20,9 @@
 #define ENABLE_DRIVER
 #endif
 
+/* Not used or exisit register and configure */
+#define NA			-1
+
 /* Field Definitions */
 #define RK808_BUCK_VSEL_MASK	0x3f
 #define RK808_BUCK4_VSEL_MASK	0xf
@@ -32,49 +36,85 @@
 #define RK818_USB_ILIM_SEL_MASK		0x0f
 #define RK818_USB_CHG_SD_VSEL_MASK	0x70
 
+/*
+ * Ramp delay
+ */
+#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)
 
 struct rk8xx_reg_info {
 	uint min_uv;
 	uint step_uv;
-	s8 vsel_reg;
+	u8 vsel_reg;
+	u8 vsel_sleep_reg;
+	u8 config_reg;
 	u8 vsel_mask;
+	u8 min_sel;
 };
 
 static const struct rk8xx_reg_info rk808_buck[] = {
-	{ 712500, 12500, REG_BUCK1_ON_VSEL, RK808_BUCK_VSEL_MASK, },
-	{ 712500, 12500, REG_BUCK2_ON_VSEL, RK808_BUCK_VSEL_MASK, },
-	{ 712500, 12500, -1, RK808_BUCK_VSEL_MASK, },
-	{ 1800000, 100000, REG_BUCK4_ON_VSEL, RK808_BUCK4_VSEL_MASK, },
+	{ 712500,   12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK808_BUCK_VSEL_MASK, },
+	{ 712500,   12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK808_BUCK_VSEL_MASK, },
+	{ 712500,   12500, NA,		      NA,		  REG_BUCK3_CONFIG, RK808_BUCK_VSEL_MASK, },
+	{ 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, RK818_BUCK_VSEL_MASK, },
-	{ 712500, 12500, REG_BUCK2_ON_VSEL, RK818_BUCK_VSEL_MASK, },
-	{ 712500, 12500, -1, RK818_BUCK_VSEL_MASK, },
-	{ 1800000, 100000, REG_BUCK4_ON_VSEL, RK818_BUCK4_VSEL_MASK, },
+	{ 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, },
+	{ 712500,   12500, NA,		      NA,		  REG_BUCK3_CONFIG, RK818_BUCK_VSEL_MASK, },
+	{ 1800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK, },
 };
 
 #ifdef ENABLE_DRIVER
 static const struct rk8xx_reg_info rk808_ldo[] = {
-	{ 1800000, 100000, REG_LDO1_ON_VSEL, RK808_LDO_VSEL_MASK, },
-	{ 1800000, 100000, REG_LDO2_ON_VSEL, RK808_LDO_VSEL_MASK, },
-	{ 800000, 100000, REG_LDO3_ON_VSEL, RK808_BUCK4_VSEL_MASK, },
-	{ 1800000, 100000, REG_LDO4_ON_VSEL, RK808_LDO_VSEL_MASK, },
-	{ 1800000, 100000, REG_LDO5_ON_VSEL, RK808_LDO_VSEL_MASK, },
-	{ 800000, 100000, REG_LDO6_ON_VSEL, RK808_LDO_VSEL_MASK, },
-	{ 800000, 100000, REG_LDO7_ON_VSEL, RK808_LDO_VSEL_MASK, },
-	{ 1800000, 100000, REG_LDO8_ON_VSEL, RK808_LDO_VSEL_MASK, },
+	{ 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, },
+	{  800000, 100000, REG_LDO3_ON_VSEL, REG_LDO3_SLP_VSEL, NA, RK808_BUCK4_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO4_ON_VSEL, REG_LDO4_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO5_ON_VSEL, REG_LDO5_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
+	{  800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
+	{  800000, 100000, REG_LDO7_ON_VSEL, REG_LDO7_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
+	{ 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, RK818_LDO_VSEL_MASK, },
-	{ 1800000, 100000, REG_LDO2_ON_VSEL, RK818_LDO_VSEL_MASK, },
-	{ 800000, 100000, REG_LDO3_ON_VSEL, RK818_LDO3_ON_VSEL_MASK, },
-	{ 1800000, 100000, REG_LDO4_ON_VSEL, RK818_LDO_VSEL_MASK, },
-	{ 1800000, 100000, REG_LDO5_ON_VSEL, RK818_LDO_VSEL_MASK, },
-	{ 800000, 100000, REG_LDO6_ON_VSEL, RK818_LDO_VSEL_MASK, },
-	{ 800000, 100000, REG_LDO7_ON_VSEL, RK818_LDO_VSEL_MASK, },
-	{ 1800000, 100000, REG_LDO8_ON_VSEL, RK818_LDO_VSEL_MASK, },
+	{ 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, },
+	{  800000, 100000, REG_LDO3_ON_VSEL, REG_LDO3_SLP_VSEL, NA, RK818_LDO3_ON_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO4_ON_VSEL, REG_LDO4_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
+	{ 1800000, 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, },
+	{  800000, 100000, REG_LDO7_ON_VSEL, REG_LDO7_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO8_ON_VSEL, REG_LDO8_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
 };
 #endif
 
@@ -87,10 +127,24 @@ static const uint rk818_chrg_shutdown_vsel_array[] = {
 };
 
 static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic,
-					     int num)
+						 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:
@@ -100,44 +154,185 @@ 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 - 1);
+	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 == -1)
+	if (info->vsel_reg == NA)
 		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);
 
-	return pmic_clrsetbits(pmic, 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);
+
+	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);
 
-	buck--;
-	mask = 1 << buck;
-	if (enable) {
-		ret = pmic_clrsetbits(pmic, REG_DCDC_ILMAX, 0, 3 << (buck * 2));
-		if (ret)
-			return ret;
-		ret = pmic_clrsetbits(pmic, REG_DCDC_UV_ACT, 1 << buck, 0);
-		if (ret)
-			return ret;
+	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;
+		if (enable) {
+			ret = pmic_clrsetbits(pmic, REG_DCDC_ILMAX,
+					      0, 3 << (buck * 2));
+			if (ret)
+				return ret;
+		}
+		ret = pmic_clrsetbits(pmic, REG_DCDC_EN, mask,
+				      enable ? mask : 0);
+		break;
+	default:
+		ret = -EINVAL;
 	}
 
-	return pmic_clrsetbits(pmic, REG_DCDC_EN, mask, enable ? mask : 0);
+	return ret;
 }
 
 #ifdef ENABLE_DRIVER
+static int _buck_set_suspend_value(struct udevice *pmic, int buck, int uvolt)
+{
+	const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt);
+	int mask = info->vsel_mask;
+	int val;
+
+	if (info->vsel_sleep_reg == NA)
+		return -ENOSYS;
+
+	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);
+}
+
+static int _buck_get_enable(struct udevice *pmic, int buck)
+{
+	struct rk8xx_priv *priv = dev_get_priv(pmic);
+	uint mask = 0;
+	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;
+		ret = pmic_reg_read(pmic, REG_DCDC_EN);
+		if (ret < 0)
+			return ret;
+		break;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	return ret & mask ? true : false;
+}
+
+static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable)
+{
+	uint mask;
+	int ret;
+	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;
+		ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF1, mask,
+				      enable ? 0 : mask);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int _buck_get_suspend_enable(struct udevice *pmic, int buck)
+{
+	struct rk8xx_priv *priv = dev_get_priv(pmic);
+	int ret, val;
+	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;
+		val = pmic_reg_read(pmic, REG_SLEEP_SET_OFF1);
+		if (val < 0)
+			return val;
+		ret = val & mask ? 0 : 1;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
 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);
+
 	switch (priv->variant) {
+	case RK816_ID:
+		return &rk816_ldo[num];
 	case RK818_ID:
 		return &rk818_ldo[num];
 	default:
@@ -145,15 +340,131 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic,
 	}
 }
 
+static int _ldo_get_enable(struct udevice *pmic, int ldo)
+{
+	struct rk8xx_priv *priv = dev_get_priv(pmic);
+	uint mask = 0;
+	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;
+		ret = pmic_reg_read(pmic, REG_LDO_EN);
+		if (ret < 0)
+			return ret;
+		break;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	return ret & mask ? true : false;
+}
+
+
+static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable)
+{
+	struct rk8xx_priv *priv = dev_get_priv(pmic);
+	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);
+		break;
+	}
+
+	return ret;
+}
+
+static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable)
+{
+	struct rk8xx_priv *priv = dev_get_priv(pmic);
+	uint mask;
+	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;
+		ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF2, mask,
+				      enable ? 0 : mask);
+		break;
+	}
+
+	return ret;
+}
+
+static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo)
+{
+	struct rk8xx_priv *priv = dev_get_priv(pmic);
+	int val, ret = 0;
+	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;
+		val = pmic_reg_read(pmic, REG_SLEEP_SET_OFF2);
+		if (val < 0)
+			return val;
+		ret = val & mask ? 0 : 1;
+		break;
+	}
+
+	return ret;
+}
+
 static int buck_get_value(struct udevice *dev)
 {
 	int buck = dev->driver_data - 1;
-	const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck);
+	/* 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)
+	if (info->vsel_reg == NA)
 		return -ENOSYS;
+
 	ret = pmic_reg_read(dev->parent, info->vsel_reg);
 	if (ret < 0)
 		return ret;
@@ -164,41 +475,74 @@ static int buck_get_value(struct udevice *dev)
 
 static int buck_set_value(struct udevice *dev, int uvolt)
 {
-	int buck = dev->driver_data;
+	int buck = dev->driver_data - 1;
 
 	return _buck_set_value(dev->parent, buck, uvolt);
 }
 
+static int buck_get_suspend_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_sleep_reg == NA)
+		return -ENOSYS;
+
+	ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
+	if (ret < 0)
+		return ret;
+
+	val = ret & mask;
+
+	return info->min_uv + val * info->step_uv;
+}
+
+static int buck_set_suspend_value(struct udevice *dev, int uvolt)
+{
+	int buck = dev->driver_data - 1;
+
+	return _buck_set_suspend_value(dev->parent, buck, uvolt);
+}
+
 static int buck_set_enable(struct udevice *dev, bool enable)
 {
-	int buck = dev->driver_data;
+	int buck = dev->driver_data - 1;
 
 	return _buck_set_enable(dev->parent, buck, enable);
 }
 
-static int buck_get_enable(struct udevice *dev)
+static int buck_set_suspend_enable(struct udevice *dev, bool enable)
 {
 	int buck = dev->driver_data - 1;
-	int ret;
-	uint mask;
 
-	mask = 1 << buck;
+	return _buck_set_suspend_enable(dev->parent, buck, enable);
+}
 
-	ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
-	if (ret < 0)
-		return ret;
+static int buck_get_suspend_enable(struct udevice *dev)
+{
+	int buck = dev->driver_data - 1;
 
-	return ret & mask ? true : false;
+	return _buck_get_suspend_enable(dev->parent, buck);
+}
+
+static int buck_get_enable(struct udevice *dev)
+{
+	int buck = dev->driver_data - 1;
+
+	return _buck_get_enable(dev->parent, buck);
 }
 
 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;
 
-	if (info->vsel_reg == -1)
+	if (info->vsel_reg == NA)
 		return -ENOSYS;
 	ret = pmic_reg_read(dev->parent, info->vsel_reg);
 	if (ret < 0)
@@ -211,71 +555,217 @@ 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)
+	if (info->vsel_reg == NA)
 		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);
 }
 
-static int ldo_set_enable(struct udevice *dev, bool enable)
+static int ldo_set_suspend_value(struct udevice *dev, int uvolt)
 {
 	int ldo = dev->driver_data - 1;
-	uint mask;
+	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 == NA)
+		return -ENOSYS;
+
+	if (info->step_uv == 0)
+		val = info->min_sel;
+	else
+		val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
 
-	mask = 1 << ldo;
+	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, REG_LDO_EN, mask,
-			       enable ? mask : 0);
+	return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val);
 }
 
-static int ldo_get_enable(struct udevice *dev)
+static int ldo_get_suspend_value(struct udevice *dev)
 {
 	int ldo = dev->driver_data - 1;
-	int ret;
-	uint mask;
+	const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0);
+	int mask = info->vsel_mask;
+	int val, ret;
 
-	mask = 1 << ldo;
+	if (info->vsel_sleep_reg == NA)
+		return -ENOSYS;
 
-	ret = pmic_reg_read(dev->parent, REG_LDO_EN);
+	ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
 	if (ret < 0)
 		return ret;
 
-	return ret & mask ? true : false;
+	val = ret & mask;
+
+	return info->min_uv + val * info->step_uv;
+}
+
+static int ldo_set_enable(struct udevice *dev, bool enable)
+{
+	int ldo = dev->driver_data - 1;
+
+	return _ldo_set_enable(dev->parent, ldo, enable);
+}
+
+static int ldo_set_suspend_enable(struct udevice *dev, bool enable)
+{
+	int ldo = dev->driver_data - 1;
+
+	return _ldo_set_suspend_enable(dev->parent, ldo, enable);
+}
+
+static int ldo_get_suspend_enable(struct udevice *dev)
+{
+	int ldo = dev->driver_data - 1;
+
+	return _ldo_get_suspend_enable(dev->parent, ldo);
+}
+
+static int ldo_get_enable(struct udevice *dev)
+{
+	int ldo = dev->driver_data - 1;
+
+	return _ldo_get_enable(dev->parent, ldo);
 }
 
 static int switch_set_enable(struct udevice *dev, bool enable)
 {
-	int sw = dev->driver_data - 1;
-	uint mask;
+	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
+	int ret = 0, sw = dev->driver_data - 1;
+	uint mask = 0;
 
-	mask = 1 << (sw + 5);
+	switch (priv->variant) {
+	case RK808_ID:
+		mask = 1 << (sw + 5);
+		ret = pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
+				      enable ? mask : 0);
+		break;
+	case RK818_ID:
+		mask = 1 << 6;
+		ret = pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
+				      enable ? mask : 0);
+		break;
+	}
+
+	debug("%s: switch%d, enable=%d, mask=0x%x\n",
+	      __func__, sw + 1, enable, mask);
 
-	return pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
-			       enable ? mask : 0);
+	return ret;
 }
 
 static int switch_get_enable(struct udevice *dev)
 {
-	int sw = dev->driver_data - 1;
-	int ret;
-	uint mask;
+	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
+	int ret = 0, sw = dev->driver_data - 1;
+	uint mask = 0;
 
-	mask = 1 << (sw + 5);
+	switch (priv->variant) {
+	case RK808_ID:
+		mask = 1 << (sw + 5);
+		ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
+		break;
+	case RK818_ID:
+		mask = 1 << 6;
+		ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
+		break;
+	}
 
-	ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
 	if (ret < 0)
 		return ret;
 
 	return ret & mask ? true : false;
 }
 
+static int switch_set_suspend_value(struct udevice *dev, int uvolt)
+{
+	return 0;
+}
+
+static int switch_get_suspend_value(struct udevice *dev)
+{
+	return 0;
+}
+
+static int switch_set_suspend_enable(struct udevice *dev, bool enable)
+{
+	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
+	int ret = 0, sw = dev->driver_data - 1;
+	uint mask = 0;
+
+	switch (priv->variant) {
+	case RK808_ID:
+		mask = 1 << (sw + 5);
+		ret = pmic_clrsetbits(dev->parent, REG_SLEEP_SET_OFF1, mask,
+				      enable ? 0 : mask);
+		break;
+	case RK818_ID:
+		mask = 1 << 6;
+		ret = pmic_clrsetbits(dev->parent, REG_SLEEP_SET_OFF1, mask,
+				      enable ? 0 : mask);
+		break;
+	}
+
+	debug("%s: switch%d, enable=%d, mask=0x%x\n",
+	      __func__, sw + 1, enable, mask);
+
+	return ret;
+}
+
+static int switch_get_suspend_enable(struct udevice *dev)
+{
+	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
+	int val, ret = 0, sw = dev->driver_data - 1;
+	uint mask = 0;
+
+	switch (priv->variant) {
+	case RK808_ID:
+		mask = 1 << (sw + 5);
+		val = pmic_reg_read(dev->parent, REG_SLEEP_SET_OFF1);
+		if (val < 0)
+			return val;
+		ret = val & mask ? 0 : 1;
+		break;
+	case RK818_ID:
+		mask = 1 << 6;
+		val = pmic_reg_read(dev->parent, REG_SLEEP_SET_OFF1);
+		if (val < 0)
+			return val;
+		ret = val & mask ? 0 : 1;
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * RK8xx switch does not need to set the voltage,
+ * but if dts set regulator-min-microvolt/regulator-max-microvolt,
+ * will cause regulator set value fail and not to enable this switch.
+ * So add an empty function to return success.
+ */
+static int switch_get_value(struct udevice *dev)
+{
+	return 0;
+}
+
+static int switch_set_value(struct udevice *dev, int uvolt)
+{
+	return 0;
+}
+
 static int rk8xx_buck_probe(struct udevice *dev)
 {
 	struct dm_regulator_uclass_platdata *uc_pdata;
@@ -315,20 +805,34 @@ static int rk8xx_switch_probe(struct udevice *dev)
 static const struct dm_regulator_ops rk8xx_buck_ops = {
 	.get_value  = buck_get_value,
 	.set_value  = buck_set_value,
+	.set_suspend_value = buck_set_suspend_value,
+	.get_suspend_value = buck_get_suspend_value,
 	.get_enable = buck_get_enable,
 	.set_enable = buck_set_enable,
+	.set_suspend_enable = buck_set_suspend_enable,
+	.get_suspend_enable = buck_get_suspend_enable,
 };
 
 static const struct dm_regulator_ops rk8xx_ldo_ops = {
 	.get_value  = ldo_get_value,
 	.set_value  = ldo_set_value,
+	.set_suspend_value = ldo_set_suspend_value,
+	.get_suspend_value = ldo_get_suspend_value,
 	.get_enable = ldo_get_enable,
 	.set_enable = ldo_set_enable,
+	.set_suspend_enable = ldo_set_suspend_enable,
+	.get_suspend_enable = ldo_get_suspend_enable,
 };
 
 static const struct dm_regulator_ops rk8xx_switch_ops = {
+	.get_value  = switch_get_value,
+	.set_value  = switch_set_value,
 	.get_enable = switch_get_enable,
 	.set_enable = switch_set_enable,
+	.set_suspend_enable = switch_set_suspend_enable,
+	.get_suspend_enable = switch_get_suspend_enable,
+	.set_suspend_value = switch_set_suspend_value,
+	.get_suspend_value = switch_get_suspend_value,
 };
 
 U_BOOT_DRIVER(rk8xx_buck) = {
diff --git a/include/power/rk8xx_pmic.h b/include/power/rk8xx_pmic.h
index c06248f75183..44e8d687dfba 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,
 };
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v1 3/7] power: pmic: rk805: support rk805 pmic
  2019-09-04  7:08 [U-Boot] [PATCH v1 0/8] power: pmic: support more PMIC Elaine Zhang
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 1/7] dm: regulator: support regulator more state Elaine Zhang
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 2/7] power: pmic: rk816: support rk816 pmic Elaine Zhang
@ 2019-09-04  7:08 ` Elaine Zhang
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 4/7] dm: pmic: add pmic_shutdown() interface Elaine Zhang
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Elaine Zhang @ 2019-09-04  7:08 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/power/pmic/rk8xx.c      |  1 +
 drivers/power/regulator/rk8xx.c | 17 +++++++++++++++++
 include/power/rk8xx_pmic.h      |  1 +
 3 files changed, 19 insertions(+)

diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index 1900de9d1cdb..00c8a2e091d8 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 a62af0b467ef..2416477f5c06 100644
--- a/drivers/power/regulator/rk8xx.c
+++ b/drivers/power/regulator/rk8xx.c
@@ -39,7 +39,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)
@@ -132,6 +139,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:
@@ -186,6 +194,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;
@@ -247,6 +256,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);
@@ -278,6 +288,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,
@@ -303,6 +314,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);
@@ -331,6 +343,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:
@@ -347,6 +360,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);
@@ -379,6 +393,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;
@@ -411,6 +426,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,
@@ -434,6 +450,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 44e8d687dfba..7784c2a5e473 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,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v1 4/7] dm: pmic: add pmic_shutdown() interface
  2019-09-04  7:08 [U-Boot] [PATCH v1 0/8] power: pmic: support more PMIC Elaine Zhang
                   ` (2 preceding siblings ...)
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 3/7] power: pmic: rk805: support rk805 pmic Elaine Zhang
@ 2019-09-04  7:08 ` Elaine Zhang
  2019-09-04  7:10 ` [U-Boot] [PATCH v1 5/7] power: pmic: rk8xx: add pmic_shutdown() implement Elaine Zhang
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Elaine Zhang @ 2019-09-04  7:08 UTC (permalink / raw)
  To: u-boot

From: Joseph Chen <chenjh@rock-chips.com>

Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/power/pmic/pmic-uclass.c | 11 +++++++++++
 include/power/pmic.h             |  9 +++++++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/power/pmic/pmic-uclass.c b/drivers/power/pmic/pmic-uclass.c
index db68c766f5d7..28cfe0c987a2 100644
--- a/drivers/power/pmic/pmic-uclass.c
+++ b/drivers/power/pmic/pmic-uclass.c
@@ -191,6 +191,17 @@ static int pmic_pre_probe(struct udevice *dev)
 	return 0;
 }
 
+
+int pmic_shutdown(struct udevice *dev)
+{
+	const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
+
+	if (!ops || !ops->shutdown)
+		return -ENOSYS;
+
+	return ops->shutdown(dev);
+}
+
 UCLASS_DRIVER(pmic) = {
 	.id		= UCLASS_PMIC,
 	.name		= "pmic",
diff --git a/include/power/pmic.h b/include/power/pmic.h
index be9de6b4de7e..231195e5ea85 100644
--- a/include/power/pmic.h
+++ b/include/power/pmic.h
@@ -164,6 +164,7 @@ struct dm_pmic_ops {
 	int (*read)(struct udevice *dev, uint reg, uint8_t *buffer, int len);
 	int (*write)(struct udevice *dev, uint reg, const uint8_t *buffer,
 		     int len);
+	int (*shutdown)(struct udevice *dev);
 };
 
 /**
@@ -306,6 +307,14 @@ struct uc_pmic_priv {
 	uint trans_len;
 };
 
+/**
+ * pmic_shutdown() - power off supplies of PMIC
+ *
+ * @dev:	PMIC device to update
+ * @return 0 on success or negative value of errno.
+ */
+int pmic_shutdown(struct udevice *dev);
+
 #endif /* CONFIG_DM_PMIC */
 
 #ifdef CONFIG_POWER
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v1 5/7] power: pmic: rk8xx: add pmic_shutdown() implement
  2019-09-04  7:08 [U-Boot] [PATCH v1 0/8] power: pmic: support more PMIC Elaine Zhang
                   ` (3 preceding siblings ...)
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 4/7] dm: pmic: add pmic_shutdown() interface Elaine Zhang
@ 2019-09-04  7:10 ` Elaine Zhang
  2019-09-04  7:10 ` [U-Boot] [PATCH v1 6/7] pmic: add RK817 support Elaine Zhang
  2019-09-04  7:10 ` [U-Boot] [PATCH v1 7/7] pmic: add rk809 support Elaine Zhang
  6 siblings, 0 replies; 12+ messages in thread
From: Elaine Zhang @ 2019-09-04  7:10 UTC (permalink / raw)
  To: u-boot

From: Joseph Chen <chenjh@rock-chips.com>

Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/power/pmic/rk8xx.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index 00c8a2e091d8..df2056913ced 100644
--- a/drivers/power/pmic/rk8xx.c
+++ b/drivers/power/pmic/rk8xx.c
@@ -49,6 +49,44 @@ static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 	return 0;
 }
 
+static int rk8xx_shutdown(struct udevice *dev)
+{
+	struct rk8xx_priv *priv = dev_get_priv(dev);
+	u8 val, dev_off;
+	int ret = 0;
+
+	switch (priv->variant) {
+	case RK808_ID:
+		dev_off = BIT(3);
+		break;
+	case RK805_ID:
+	case RK816_ID:
+	case RK818_ID:
+		dev_off = BIT(0);
+		break;
+	default:
+		printf("Unknown PMIC: RK%x\n", priv->variant);
+		return -EINVAL;
+	}
+
+	ret = dm_i2c_read(dev, REG_DEVCTRL, &val, 1);
+	if (ret) {
+		printf("read error from device: %p register: %#x!",
+		       dev, REG_DEVCTRL);
+		return ret;
+	}
+
+	val |= dev_off;
+	ret = dm_i2c_write(dev, REG_DEVCTRL, &val, 1);
+	if (ret) {
+		printf("write error to device: %p register: %#x!",
+		       dev, REG_DEVCTRL);
+		return ret;
+	}
+
+	return 0;
+}
+
 #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
 static int rk8xx_bind(struct udevice *dev)
 {
@@ -91,6 +129,7 @@ static struct dm_pmic_ops rk8xx_ops = {
 	.reg_count = rk8xx_reg_count,
 	.read = rk8xx_read,
 	.write = rk8xx_write,
+	.shutdown = rk8xx_shutdown,
 };
 
 static const struct udevice_id rk8xx_ids[] = {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v1 6/7] pmic: add RK817 support
  2019-09-04  7:08 [U-Boot] [PATCH v1 0/8] power: pmic: support more PMIC Elaine Zhang
                   ` (4 preceding siblings ...)
  2019-09-04  7:10 ` [U-Boot] [PATCH v1 5/7] power: pmic: rk8xx: add pmic_shutdown() implement Elaine Zhang
@ 2019-09-04  7:10 ` Elaine Zhang
  2019-09-04  7:40   ` Kever Yang
  2019-09-04  7:10 ` [U-Boot] [PATCH v1 7/7] pmic: add rk809 support Elaine Zhang
  6 siblings, 1 reply; 12+ messages in thread
From: Elaine Zhang @ 2019-09-04  7:10 UTC (permalink / raw)
  To: u-boot

From: Joseph Chen <chenjh@rock-chips.com>

include sub modules: pmic, regulator

Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/power/pmic/rk8xx.c      | 109 ++++++++++++++++++++--
 drivers/power/regulator/rk8xx.c | 198 +++++++++++++++++++++++++++++++++++++++-
 include/power/rk8xx_pmic.h      |  31 +++++++
 3 files changed, 329 insertions(+), 9 deletions(-)

diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index df2056913ced..b7ce87d0eff5 100644
--- a/drivers/power/pmic/rk8xx.c
+++ b/drivers/power/pmic/rk8xx.c
@@ -10,6 +10,22 @@
 #include <power/rk8xx_pmic.h>
 #include <power/pmic.h>
 
+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},
+/*
+ * Only when system suspend while U-Boot charge needs this config support
+ */
+#ifdef CONFIG_DM_CHARGE_DISPLAY
+	/* Set pmic_sleep as sleep function */
+	{ RK817_PMIC_SYS_CFG3, 0x08, 0x18 },
+	/* Set pmic_int active low */
+	{ RK817_GPIO_INT_CFG,  0x00, 0x02 },
+#endif
+};
+
 static const struct pmic_child_info pmic_children_info[] = {
 	{ .prefix = "DCDC_REG", .driver = "rk8xx_buck"},
 	{ .prefix = "LDO_REG", .driver = "rk8xx_ldo"},
@@ -52,16 +68,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:
@@ -69,18 +91,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;
 	}
 
@@ -114,13 +136,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;
 }
@@ -136,6 +228,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 2416477f5c06..0d95e54220b0 100644
--- a/drivers/power/regulator/rk8xx.c
+++ b/drivers/power/regulator/rk8xx.c
@@ -28,6 +28,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
@@ -46,13 +61,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;
@@ -85,6 +106,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, },
@@ -113,6 +153,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, },
@@ -153,6 +223,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:
@@ -221,6 +309,22 @@ 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);
+		/* 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:
 		ret = -EINVAL;
 	}
@@ -273,6 +377,16 @@ 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));
+		/* BUCK5 for RK809 */
+		} else {
+			mask = 1 << 1;
+			ret = pmic_reg_read(pmic, RK817_POWER_EN(3));
+		}
+		break;
 	}
 
 	if (ret < 0)
@@ -300,6 +414,14 @@ 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;
+		else
+			mask = 1 << 5;	/* BUCK5 for RK809 */
+		ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask,
+				      enable ? mask : 0);
+		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -330,6 +452,17 @@ 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;
+		else
+			mask = 1 << 5;	/* BUCK5 for RK809 */
+
+		val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(0));
+		if (val < 0)
+			return val;
+		ret = val & mask ? 1 : 0;
+		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -346,6 +479,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:
@@ -377,6 +515,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)
@@ -414,6 +566,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;
@@ -438,6 +608,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;
@@ -466,6 +647,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 7784c2a5e473..d93cecedddf7 100644
--- a/include/power/rk8xx_pmic.h
+++ b/include/power/rk8xx_pmic.h
@@ -170,6 +170,10 @@ enum {
 };
 
 enum {
+	RK817_REG_SYS_CFG3 = 0xf4,
+};
+
+enum {
 	RK816_REG_DCDC_EN1 = 0x23,
 	RK816_REG_DCDC_EN2,
 	RK816_REG_DCDC_SLP_EN,
@@ -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;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v1 7/7] pmic: add rk809 support
  2019-09-04  7:08 [U-Boot] [PATCH v1 0/8] power: pmic: support more PMIC Elaine Zhang
                   ` (5 preceding siblings ...)
  2019-09-04  7:10 ` [U-Boot] [PATCH v1 6/7] pmic: add RK817 support Elaine Zhang
@ 2019-09-04  7:10 ` Elaine Zhang
  6 siblings, 0 replies; 12+ messages in thread
From: Elaine Zhang @ 2019-09-04  7:10 UTC (permalink / raw)
  To: u-boot

From: Joseph Chen <chenjh@rock-chips.com>

include sub modules: pmic, regulator

Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/power/pmic/rk8xx.c      |  6 ++++-
 drivers/power/regulator/rk8xx.c | 55 ++++++++++++++++++++++++++++++++++++++++-
 include/power/rk8xx_pmic.h      |  1 +
 3 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index b7ce87d0eff5..4cf581cd8b1b 100644
--- a/drivers/power/pmic/rk8xx.c
+++ b/drivers/power/pmic/rk8xx.c
@@ -82,6 +82,7 @@ static int rk8xx_shutdown(struct udevice *dev)
 		devctrl_reg = REG_DEVCTRL;
 		dev_off = BIT(0);
 		break;
+	case RK809_ID:
 	case RK817_ID:
 		devctrl_reg = RK817_REG_SYS_CFG3;
 		dev_off = BIT(0);
@@ -145,7 +146,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 {
@@ -172,6 +174,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;
@@ -227,6 +230,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 0d95e54220b0..0817e1a35e89 100644
--- a/drivers/power/regulator/rk8xx.c
+++ b/drivers/power/regulator/rk8xx.c
@@ -28,6 +28,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))
@@ -60,6 +64,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)
@@ -106,6 +111,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, },
@@ -224,6 +237,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:
@@ -240,6 +254,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];
@@ -309,6 +333,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)
@@ -377,6 +402,7 @@ 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;
@@ -414,6 +440,7 @@ 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;
@@ -452,6 +479,7 @@ 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;
@@ -479,6 +507,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];
@@ -515,6 +544,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;
@@ -537,7 +567,6 @@ static int _ldo_get_enable(struct udevice *pmic, int ldo)
 	return ret & mask ? true : false;
 }
 
-
 static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable)
 {
 	struct rk8xx_priv *priv = dev_get_priv(pmic);
@@ -566,6 +595,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);
@@ -608,6 +638,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 */
@@ -647,6 +678,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 */
@@ -866,6 +898,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,
@@ -890,6 +927,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);
@@ -924,6 +965,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,
@@ -951,6 +997,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 d93cecedddf7..8ff0af35c57a 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,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v1 6/7] pmic: add RK817 support
  2019-09-04  7:10 ` [U-Boot] [PATCH v1 6/7] pmic: add RK817 support Elaine Zhang
@ 2019-09-04  7:40   ` Kever Yang
  0 siblings, 0 replies; 12+ messages in thread
From: Kever Yang @ 2019-09-04  7:40 UTC (permalink / raw)
  To: u-boot

Hi Elaine,


On 2019/9/4 下午3:10, Elaine Zhang wrote:
> From: Joseph Chen <chenjh@rock-chips.com>
>
> include sub modules: pmic, regulator
>
> Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
>   drivers/power/pmic/rk8xx.c      | 109 ++++++++++++++++++++--
>   drivers/power/regulator/rk8xx.c | 198 +++++++++++++++++++++++++++++++++++++++-
>   include/power/rk8xx_pmic.h      |  31 +++++++
>   3 files changed, 329 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
> index df2056913ced..b7ce87d0eff5 100644
> --- a/drivers/power/pmic/rk8xx.c
> +++ b/drivers/power/pmic/rk8xx.c
> @@ -10,6 +10,22 @@
>   #include <power/rk8xx_pmic.h>
>   #include <power/pmic.h>
>   
> +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},
> +/*
> + * Only when system suspend while U-Boot charge needs this config support
> + */
> +#ifdef CONFIG_DM_CHARGE_DISPLAY
> +	/* Set pmic_sleep as sleep function */
> +	{ RK817_PMIC_SYS_CFG3, 0x08, 0x18 },
> +	/* Set pmic_int active low */
> +	{ RK817_GPIO_INT_CFG,  0x00, 0x02 },
> +#endif


This DM_CHARGE_DISPLAY is not available on upstream,  please drop this blob.

> +};
> +
>   static const struct pmic_child_info pmic_children_info[] = {
>   	{ .prefix = "DCDC_REG", .driver = "rk8xx_buck"},
>   	{ .prefix = "LDO_REG", .driver = "rk8xx_ldo"},
> @@ -52,16 +68,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:
> @@ -69,18 +91,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;
>   	}
>   
> @@ -114,13 +136,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;
>   }
> @@ -136,6 +228,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 2416477f5c06..0d95e54220b0 100644
> --- a/drivers/power/regulator/rk8xx.c
> +++ b/drivers/power/regulator/rk8xx.c
> @@ -28,6 +28,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
> @@ -46,13 +61,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;
> @@ -85,6 +106,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, },
> @@ -113,6 +153,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, },
> @@ -153,6 +223,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:
> @@ -221,6 +309,22 @@ 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);
> +		/* BUCK5 for RK809 */

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:
>   		ret = -EINVAL;
>   	}
> @@ -273,6 +377,16 @@ 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));
> +		/* BUCK5 for RK809 */
?
> +		} else {
> +			mask = 1 << 1;
> +			ret = pmic_reg_read(pmic, RK817_POWER_EN(3));
> +		}
> +		break;
>   	}
>   
>   	if (ret < 0)
> @@ -300,6 +414,14 @@ 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;
> +		else
> +			mask = 1 << 5;	/* BUCK5 for RK809 */
> +		ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask,
> +				      enable ? mask : 0);
> +		break;
>   	default:
>   		ret = -EINVAL;
>   	}
> @@ -330,6 +452,17 @@ 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;
> +		else
> +			mask = 1 << 5;	/* BUCK5 for RK809 */

same


Thanks,

- Kever

> +
> +		val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(0));
> +		if (val < 0)
> +			return val;
> +		ret = val & mask ? 1 : 0;
> +		break;
>   	default:
>   		ret = -EINVAL;
>   	}
> @@ -346,6 +479,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:
> @@ -377,6 +515,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)
> @@ -414,6 +566,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;
> @@ -438,6 +608,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;
> @@ -466,6 +647,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 7784c2a5e473..d93cecedddf7 100644
> --- a/include/power/rk8xx_pmic.h
> +++ b/include/power/rk8xx_pmic.h
> @@ -170,6 +170,10 @@ enum {
>   };
>   
>   enum {
> +	RK817_REG_SYS_CFG3 = 0xf4,
> +};
> +
> +enum {
>   	RK816_REG_DCDC_EN1 = 0x23,
>   	RK816_REG_DCDC_EN2,
>   	RK816_REG_DCDC_SLP_EN,
> @@ -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;

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v1 2/7] power: pmic: rk816: support rk816 pmic
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 2/7] power: pmic: rk816: support rk816 pmic Elaine Zhang
@ 2019-09-04  7:45   ` Kever Yang
  0 siblings, 0 replies; 12+ messages in thread
From: Kever Yang @ 2019-09-04  7:45 UTC (permalink / raw)
  To: u-boot

Hi Elaine,

     Please add commit message for each patch, eg. for new pmic support,

you can share some pmic feature in commit message.


Thanks,

- Kever

On 2019/9/4 下午3:08, Elaine Zhang wrote:
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
>   drivers/power/pmic/rk8xx.c      |   1 +
>   drivers/power/regulator/rk8xx.c | 674 +++++++++++++++++++++++++++++++++++-----
>   include/power/rk8xx_pmic.h      |  11 +-
>   3 files changed, 600 insertions(+), 86 deletions(-)
>
> diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
> index 25c339ab12cc..1900de9d1cdb 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 aa4f3a161c47..a62af0b467ef 100644
> --- a/drivers/power/regulator/rk8xx.c
> +++ b/drivers/power/regulator/rk8xx.c
> @@ -1,4 +1,3 @@
> -// SPDX-License-Identifier: GPL-2.0+
>   /*
>    * Copyright (C) 2015 Google, Inc
>    * Written by Simon Glass <sjg@chromium.org>
> @@ -6,6 +5,8 @@
>    * Based on Rockchip's drivers/power/pmic/pmic_rk808.c:
>    * Copyright (C) 2012 rockchips
>    * zyw <zyw@rock-chips.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+


This update is not correct, please drop it.

>    */
>   
>   #include <common.h>
> @@ -19,6 +20,9 @@
>   #define ENABLE_DRIVER
>   #endif
>   
> +/* Not used or exisit register and configure */
> +#define NA			-1
> +
>   /* Field Definitions */
>   #define RK808_BUCK_VSEL_MASK	0x3f
>   #define RK808_BUCK4_VSEL_MASK	0xf
> @@ -32,49 +36,85 @@
>   #define RK818_USB_ILIM_SEL_MASK		0x0f
>   #define RK818_USB_CHG_SD_VSEL_MASK	0x70
>   
> +/*
> + * Ramp delay
> + */
> +#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)
>   
>   struct rk8xx_reg_info {
>   	uint min_uv;
>   	uint step_uv;
> -	s8 vsel_reg;
> +	u8 vsel_reg;
> +	u8 vsel_sleep_reg;
> +	u8 config_reg;
>   	u8 vsel_mask;
> +	u8 min_sel;
>   };
>   
>   static const struct rk8xx_reg_info rk808_buck[] = {
> -	{ 712500, 12500, REG_BUCK1_ON_VSEL, RK808_BUCK_VSEL_MASK, },
> -	{ 712500, 12500, REG_BUCK2_ON_VSEL, RK808_BUCK_VSEL_MASK, },
> -	{ 712500, 12500, -1, RK808_BUCK_VSEL_MASK, },
> -	{ 1800000, 100000, REG_BUCK4_ON_VSEL, RK808_BUCK4_VSEL_MASK, },
> +	{ 712500,   12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK808_BUCK_VSEL_MASK, },
> +	{ 712500,   12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK808_BUCK_VSEL_MASK, },
> +	{ 712500,   12500, NA,		      NA,		  REG_BUCK3_CONFIG, RK808_BUCK_VSEL_MASK, },
> +	{ 1800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK808_BUCK4_VSEL_MASK, },
> +};


Please split rk808/rk818 code update and add new pmic rk816 into 
different patches.

Thanks,
- Kever
> +
> +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, RK818_BUCK_VSEL_MASK, },
> -	{ 712500, 12500, REG_BUCK2_ON_VSEL, RK818_BUCK_VSEL_MASK, },
> -	{ 712500, 12500, -1, RK818_BUCK_VSEL_MASK, },
> -	{ 1800000, 100000, REG_BUCK4_ON_VSEL, RK818_BUCK4_VSEL_MASK, },
> +	{ 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, },
> +	{ 712500,   12500, NA,		      NA,		  REG_BUCK3_CONFIG, RK818_BUCK_VSEL_MASK, },
> +	{ 1800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK, },
>   };
>   
>   #ifdef ENABLE_DRIVER
>   static const struct rk8xx_reg_info rk808_ldo[] = {
> -	{ 1800000, 100000, REG_LDO1_ON_VSEL, RK808_LDO_VSEL_MASK, },
> -	{ 1800000, 100000, REG_LDO2_ON_VSEL, RK808_LDO_VSEL_MASK, },
> -	{ 800000, 100000, REG_LDO3_ON_VSEL, RK808_BUCK4_VSEL_MASK, },
> -	{ 1800000, 100000, REG_LDO4_ON_VSEL, RK808_LDO_VSEL_MASK, },
> -	{ 1800000, 100000, REG_LDO5_ON_VSEL, RK808_LDO_VSEL_MASK, },
> -	{ 800000, 100000, REG_LDO6_ON_VSEL, RK808_LDO_VSEL_MASK, },
> -	{ 800000, 100000, REG_LDO7_ON_VSEL, RK808_LDO_VSEL_MASK, },
> -	{ 1800000, 100000, REG_LDO8_ON_VSEL, RK808_LDO_VSEL_MASK, },
> +	{ 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, },
> +	{  800000, 100000, REG_LDO3_ON_VSEL, REG_LDO3_SLP_VSEL, NA, RK808_BUCK4_VSEL_MASK, },
> +	{ 1800000, 100000, REG_LDO4_ON_VSEL, REG_LDO4_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
> +	{ 1800000, 100000, REG_LDO5_ON_VSEL, REG_LDO5_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
> +	{  800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
> +	{  800000, 100000, REG_LDO7_ON_VSEL, REG_LDO7_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, },
> +	{ 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, RK818_LDO_VSEL_MASK, },
> -	{ 1800000, 100000, REG_LDO2_ON_VSEL, RK818_LDO_VSEL_MASK, },
> -	{ 800000, 100000, REG_LDO3_ON_VSEL, RK818_LDO3_ON_VSEL_MASK, },
> -	{ 1800000, 100000, REG_LDO4_ON_VSEL, RK818_LDO_VSEL_MASK, },
> -	{ 1800000, 100000, REG_LDO5_ON_VSEL, RK818_LDO_VSEL_MASK, },
> -	{ 800000, 100000, REG_LDO6_ON_VSEL, RK818_LDO_VSEL_MASK, },
> -	{ 800000, 100000, REG_LDO7_ON_VSEL, RK818_LDO_VSEL_MASK, },
> -	{ 1800000, 100000, REG_LDO8_ON_VSEL, RK818_LDO_VSEL_MASK, },
> +	{ 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, },
> +	{  800000, 100000, REG_LDO3_ON_VSEL, REG_LDO3_SLP_VSEL, NA, RK818_LDO3_ON_VSEL_MASK, },
> +	{ 1800000, 100000, REG_LDO4_ON_VSEL, REG_LDO4_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
> +	{ 1800000, 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, },
> +	{  800000, 100000, REG_LDO7_ON_VSEL, REG_LDO7_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
> +	{ 1800000, 100000, REG_LDO8_ON_VSEL, REG_LDO8_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
>   };
>   #endif
>   
> @@ -87,10 +127,24 @@ static const uint rk818_chrg_shutdown_vsel_array[] = {
>   };
>   
>   static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic,
> -					     int num)
> +						 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:
> @@ -100,44 +154,185 @@ 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 - 1);
> +	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 == -1)
> +	if (info->vsel_reg == NA)
>   		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);
>   
> -	return pmic_clrsetbits(pmic, 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);
> +
> +	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);
>   
> -	buck--;
> -	mask = 1 << buck;
> -	if (enable) {
> -		ret = pmic_clrsetbits(pmic, REG_DCDC_ILMAX, 0, 3 << (buck * 2));
> -		if (ret)
> -			return ret;
> -		ret = pmic_clrsetbits(pmic, REG_DCDC_UV_ACT, 1 << buck, 0);
> -		if (ret)
> -			return ret;
> +	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;
> +		if (enable) {
> +			ret = pmic_clrsetbits(pmic, REG_DCDC_ILMAX,
> +					      0, 3 << (buck * 2));
> +			if (ret)
> +				return ret;
> +		}
> +		ret = pmic_clrsetbits(pmic, REG_DCDC_EN, mask,
> +				      enable ? mask : 0);
> +		break;
> +	default:
> +		ret = -EINVAL;
>   	}
>   
> -	return pmic_clrsetbits(pmic, REG_DCDC_EN, mask, enable ? mask : 0);
> +	return ret;
>   }
>   
>   #ifdef ENABLE_DRIVER
> +static int _buck_set_suspend_value(struct udevice *pmic, int buck, int uvolt)
> +{
> +	const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt);
> +	int mask = info->vsel_mask;
> +	int val;
> +
> +	if (info->vsel_sleep_reg == NA)
> +		return -ENOSYS;
> +
> +	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);
> +}
> +
> +static int _buck_get_enable(struct udevice *pmic, int buck)
> +{
> +	struct rk8xx_priv *priv = dev_get_priv(pmic);
> +	uint mask = 0;
> +	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;
> +		ret = pmic_reg_read(pmic, REG_DCDC_EN);
> +		if (ret < 0)
> +			return ret;
> +		break;
> +	}
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	return ret & mask ? true : false;
> +}
> +
> +static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable)
> +{
> +	uint mask;
> +	int ret;
> +	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;
> +		ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF1, mask,
> +				      enable ? 0 : mask);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +static int _buck_get_suspend_enable(struct udevice *pmic, int buck)
> +{
> +	struct rk8xx_priv *priv = dev_get_priv(pmic);
> +	int ret, val;
> +	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;
> +		val = pmic_reg_read(pmic, REG_SLEEP_SET_OFF1);
> +		if (val < 0)
> +			return val;
> +		ret = val & mask ? 0 : 1;
> +		break;
> +	default:
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
>   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);
> +
>   	switch (priv->variant) {
> +	case RK816_ID:
> +		return &rk816_ldo[num];
>   	case RK818_ID:
>   		return &rk818_ldo[num];
>   	default:
> @@ -145,15 +340,131 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic,
>   	}
>   }
>   
> +static int _ldo_get_enable(struct udevice *pmic, int ldo)
> +{
> +	struct rk8xx_priv *priv = dev_get_priv(pmic);
> +	uint mask = 0;
> +	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;
> +		ret = pmic_reg_read(pmic, REG_LDO_EN);
> +		if (ret < 0)
> +			return ret;
> +		break;
> +	}
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	return ret & mask ? true : false;
> +}
> +
> +
> +static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable)
> +{
> +	struct rk8xx_priv *priv = dev_get_priv(pmic);
> +	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);
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable)
> +{
> +	struct rk8xx_priv *priv = dev_get_priv(pmic);
> +	uint mask;
> +	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;
> +		ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF2, mask,
> +				      enable ? 0 : mask);
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo)
> +{
> +	struct rk8xx_priv *priv = dev_get_priv(pmic);
> +	int val, ret = 0;
> +	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;
> +		val = pmic_reg_read(pmic, REG_SLEEP_SET_OFF2);
> +		if (val < 0)
> +			return val;
> +		ret = val & mask ? 0 : 1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
>   static int buck_get_value(struct udevice *dev)
>   {
>   	int buck = dev->driver_data - 1;
> -	const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck);
> +	/* 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)
> +	if (info->vsel_reg == NA)
>   		return -ENOSYS;
> +
>   	ret = pmic_reg_read(dev->parent, info->vsel_reg);
>   	if (ret < 0)
>   		return ret;
> @@ -164,41 +475,74 @@ static int buck_get_value(struct udevice *dev)
>   
>   static int buck_set_value(struct udevice *dev, int uvolt)
>   {
> -	int buck = dev->driver_data;
> +	int buck = dev->driver_data - 1;
>   
>   	return _buck_set_value(dev->parent, buck, uvolt);
>   }
>   
> +static int buck_get_suspend_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_sleep_reg == NA)
> +		return -ENOSYS;
> +
> +	ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
> +	if (ret < 0)
> +		return ret;
> +
> +	val = ret & mask;
> +
> +	return info->min_uv + val * info->step_uv;
> +}
> +
> +static int buck_set_suspend_value(struct udevice *dev, int uvolt)
> +{
> +	int buck = dev->driver_data - 1;
> +
> +	return _buck_set_suspend_value(dev->parent, buck, uvolt);
> +}
> +
>   static int buck_set_enable(struct udevice *dev, bool enable)
>   {
> -	int buck = dev->driver_data;
> +	int buck = dev->driver_data - 1;
>   
>   	return _buck_set_enable(dev->parent, buck, enable);
>   }
>   
> -static int buck_get_enable(struct udevice *dev)
> +static int buck_set_suspend_enable(struct udevice *dev, bool enable)
>   {
>   	int buck = dev->driver_data - 1;
> -	int ret;
> -	uint mask;
>   
> -	mask = 1 << buck;
> +	return _buck_set_suspend_enable(dev->parent, buck, enable);
> +}
>   
> -	ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
> -	if (ret < 0)
> -		return ret;
> +static int buck_get_suspend_enable(struct udevice *dev)
> +{
> +	int buck = dev->driver_data - 1;
>   
> -	return ret & mask ? true : false;
> +	return _buck_get_suspend_enable(dev->parent, buck);
> +}
> +
> +static int buck_get_enable(struct udevice *dev)
> +{
> +	int buck = dev->driver_data - 1;
> +
> +	return _buck_get_enable(dev->parent, buck);
>   }
>   
>   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;
>   
> -	if (info->vsel_reg == -1)
> +	if (info->vsel_reg == NA)
>   		return -ENOSYS;
>   	ret = pmic_reg_read(dev->parent, info->vsel_reg);
>   	if (ret < 0)
> @@ -211,71 +555,217 @@ 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)
> +	if (info->vsel_reg == NA)
>   		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);
>   }
>   
> -static int ldo_set_enable(struct udevice *dev, bool enable)
> +static int ldo_set_suspend_value(struct udevice *dev, int uvolt)
>   {
>   	int ldo = dev->driver_data - 1;
> -	uint mask;
> +	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 == NA)
> +		return -ENOSYS;
> +
> +	if (info->step_uv == 0)
> +		val = info->min_sel;
> +	else
> +		val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel;
>   
> -	mask = 1 << ldo;
> +	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, REG_LDO_EN, mask,
> -			       enable ? mask : 0);
> +	return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val);
>   }
>   
> -static int ldo_get_enable(struct udevice *dev)
> +static int ldo_get_suspend_value(struct udevice *dev)
>   {
>   	int ldo = dev->driver_data - 1;
> -	int ret;
> -	uint mask;
> +	const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0);
> +	int mask = info->vsel_mask;
> +	int val, ret;
>   
> -	mask = 1 << ldo;
> +	if (info->vsel_sleep_reg == NA)
> +		return -ENOSYS;
>   
> -	ret = pmic_reg_read(dev->parent, REG_LDO_EN);
> +	ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
>   	if (ret < 0)
>   		return ret;
>   
> -	return ret & mask ? true : false;
> +	val = ret & mask;
> +
> +	return info->min_uv + val * info->step_uv;
> +}
> +
> +static int ldo_set_enable(struct udevice *dev, bool enable)
> +{
> +	int ldo = dev->driver_data - 1;
> +
> +	return _ldo_set_enable(dev->parent, ldo, enable);
> +}
> +
> +static int ldo_set_suspend_enable(struct udevice *dev, bool enable)
> +{
> +	int ldo = dev->driver_data - 1;
> +
> +	return _ldo_set_suspend_enable(dev->parent, ldo, enable);
> +}
> +
> +static int ldo_get_suspend_enable(struct udevice *dev)
> +{
> +	int ldo = dev->driver_data - 1;
> +
> +	return _ldo_get_suspend_enable(dev->parent, ldo);
> +}
> +
> +static int ldo_get_enable(struct udevice *dev)
> +{
> +	int ldo = dev->driver_data - 1;
> +
> +	return _ldo_get_enable(dev->parent, ldo);
>   }
>   
>   static int switch_set_enable(struct udevice *dev, bool enable)
>   {
> -	int sw = dev->driver_data - 1;
> -	uint mask;
> +	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
> +	int ret = 0, sw = dev->driver_data - 1;
> +	uint mask = 0;
>   
> -	mask = 1 << (sw + 5);
> +	switch (priv->variant) {
> +	case RK808_ID:
> +		mask = 1 << (sw + 5);
> +		ret = pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
> +				      enable ? mask : 0);
> +		break;
> +	case RK818_ID:
> +		mask = 1 << 6;
> +		ret = pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
> +				      enable ? mask : 0);
> +		break;
> +	}
> +
> +	debug("%s: switch%d, enable=%d, mask=0x%x\n",
> +	      __func__, sw + 1, enable, mask);
>   
> -	return pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
> -			       enable ? mask : 0);
> +	return ret;
>   }
>   
>   static int switch_get_enable(struct udevice *dev)
>   {
> -	int sw = dev->driver_data - 1;
> -	int ret;
> -	uint mask;
> +	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
> +	int ret = 0, sw = dev->driver_data - 1;
> +	uint mask = 0;
>   
> -	mask = 1 << (sw + 5);
> +	switch (priv->variant) {
> +	case RK808_ID:
> +		mask = 1 << (sw + 5);
> +		ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
> +		break;
> +	case RK818_ID:
> +		mask = 1 << 6;
> +		ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
> +		break;
> +	}
>   
> -	ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
>   	if (ret < 0)
>   		return ret;
>   
>   	return ret & mask ? true : false;
>   }
>   
> +static int switch_set_suspend_value(struct udevice *dev, int uvolt)
> +{
> +	return 0;
> +}
> +
> +static int switch_get_suspend_value(struct udevice *dev)
> +{
> +	return 0;
> +}
> +
> +static int switch_set_suspend_enable(struct udevice *dev, bool enable)
> +{
> +	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
> +	int ret = 0, sw = dev->driver_data - 1;
> +	uint mask = 0;
> +
> +	switch (priv->variant) {
> +	case RK808_ID:
> +		mask = 1 << (sw + 5);
> +		ret = pmic_clrsetbits(dev->parent, REG_SLEEP_SET_OFF1, mask,
> +				      enable ? 0 : mask);
> +		break;
> +	case RK818_ID:
> +		mask = 1 << 6;
> +		ret = pmic_clrsetbits(dev->parent, REG_SLEEP_SET_OFF1, mask,
> +				      enable ? 0 : mask);
> +		break;
> +	}
> +
> +	debug("%s: switch%d, enable=%d, mask=0x%x\n",
> +	      __func__, sw + 1, enable, mask);
> +
> +	return ret;
> +}
> +
> +static int switch_get_suspend_enable(struct udevice *dev)
> +{
> +	struct rk8xx_priv *priv = dev_get_priv(dev->parent);
> +	int val, ret = 0, sw = dev->driver_data - 1;
> +	uint mask = 0;
> +
> +	switch (priv->variant) {
> +	case RK808_ID:
> +		mask = 1 << (sw + 5);
> +		val = pmic_reg_read(dev->parent, REG_SLEEP_SET_OFF1);
> +		if (val < 0)
> +			return val;
> +		ret = val & mask ? 0 : 1;
> +		break;
> +	case RK818_ID:
> +		mask = 1 << 6;
> +		val = pmic_reg_read(dev->parent, REG_SLEEP_SET_OFF1);
> +		if (val < 0)
> +			return val;
> +		ret = val & mask ? 0 : 1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +/*
> + * RK8xx switch does not need to set the voltage,
> + * but if dts set regulator-min-microvolt/regulator-max-microvolt,
> + * will cause regulator set value fail and not to enable this switch.
> + * So add an empty function to return success.
> + */
> +static int switch_get_value(struct udevice *dev)
> +{
> +	return 0;
> +}
> +
> +static int switch_set_value(struct udevice *dev, int uvolt)
> +{
> +	return 0;
> +}
> +
>   static int rk8xx_buck_probe(struct udevice *dev)
>   {
>   	struct dm_regulator_uclass_platdata *uc_pdata;
> @@ -315,20 +805,34 @@ static int rk8xx_switch_probe(struct udevice *dev)
>   static const struct dm_regulator_ops rk8xx_buck_ops = {
>   	.get_value  = buck_get_value,
>   	.set_value  = buck_set_value,
> +	.set_suspend_value = buck_set_suspend_value,
> +	.get_suspend_value = buck_get_suspend_value,
>   	.get_enable = buck_get_enable,
>   	.set_enable = buck_set_enable,
> +	.set_suspend_enable = buck_set_suspend_enable,
> +	.get_suspend_enable = buck_get_suspend_enable,
>   };
>   
>   static const struct dm_regulator_ops rk8xx_ldo_ops = {
>   	.get_value  = ldo_get_value,
>   	.set_value  = ldo_set_value,
> +	.set_suspend_value = ldo_set_suspend_value,
> +	.get_suspend_value = ldo_get_suspend_value,
>   	.get_enable = ldo_get_enable,
>   	.set_enable = ldo_set_enable,
> +	.set_suspend_enable = ldo_set_suspend_enable,
> +	.get_suspend_enable = ldo_get_suspend_enable,
>   };
>   
>   static const struct dm_regulator_ops rk8xx_switch_ops = {
> +	.get_value  = switch_get_value,
> +	.set_value  = switch_set_value,
>   	.get_enable = switch_get_enable,
>   	.set_enable = switch_set_enable,
> +	.set_suspend_enable = switch_set_suspend_enable,
> +	.get_suspend_enable = switch_get_suspend_enable,
> +	.set_suspend_value = switch_set_suspend_value,
> +	.get_suspend_value = switch_get_suspend_value,
>   };
>   
>   U_BOOT_DRIVER(rk8xx_buck) = {
> diff --git a/include/power/rk8xx_pmic.h b/include/power/rk8xx_pmic.h
> index c06248f75183..44e8d687dfba 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,
>   };
>   

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v1 1/7] dm: regulator: support regulator more state
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 1/7] dm: regulator: support regulator more state Elaine Zhang
@ 2019-09-04 10:19   ` Lukasz Majewski
  2019-09-17  5:47   ` Simon Glass
  1 sibling, 0 replies; 12+ messages in thread
From: Lukasz Majewski @ 2019-09-04 10:19 UTC (permalink / raw)
  To: u-boot

On Wed,  4 Sep 2019 15:08:21 +0800
Elaine Zhang <zhangqing@rock-chips.com> wrote:

> From: Joseph Chen <chenjh@rock-chips.com>
> 
> 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 <chenjh@rock-chips.com>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
>  drivers/power/regulator/regulator-uclass.c | 67

You add the code to the uclass (regulator-uclass.c). By default such
change shall be covered by sandbox tests.

Please provide tests for functions which you introduce.

As an example:
https://patchwork.ozlabs.org/patch/1121329/

> ++++++++++++++++++++++++++++++ include/power/regulator.h
>     | 42 +++++++++++++++++++ 2 files changed, 109 insertions(+)
> 
> diff --git a/drivers/power/regulator/regulator-uclass.c
> b/drivers/power/regulator/regulator-uclass.c index
> 76be95bcd159..972a5b210c3c 100644 ---
> a/drivers/power/regulator/regulator-uclass.c +++
> b/drivers/power/regulator/regulator-uclass.c @@ -77,6 +77,33 @@ int
> regulator_set_value(struct udevice *dev, int uV) return ret;
>  }
>  
> +int regulator_set_suspend_value(struct udevice *dev, int uV)
> +{
> +	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> +	struct dm_regulator_uclass_platdata *uc_pdata;
> +
> +	uc_pdata = dev_get_uclass_platdata(dev);
> +	if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV)
> +		return -EINVAL;
> +	if (uc_pdata->max_uV != -ENODATA && uV > uc_pdata->max_uV)
> +		return -EINVAL;
> +
> +	if (!ops || !ops->set_suspend_value)
> +		return -ENOSYS;
> +
> +	return ops->set_suspend_value(dev, uV);
> +}
> +
> +int regulator_get_suspend_value(struct udevice *dev)
> +{
> +	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> +
> +	if (!ops || !ops->get_suspend_value)
> +		return -ENOSYS;
> +
> +	return ops->get_suspend_value(dev);
> +}
> +
>  /*
>   * To be called with at most caution as there is no check
>   * before setting the actual voltage value.
> @@ -170,6 +197,26 @@ int regulator_set_enable_if_allowed(struct
> udevice *dev, bool enable) return ret;
>  }
>  
> +int regulator_set_suspend_enable(struct udevice *dev, bool enable)
> +{
> +	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> +
> +	if (!ops || !ops->set_suspend_enable)
> +		return -ENOSYS;
> +
> +	return ops->set_suspend_enable(dev, enable);
> +}
> +
> +int regulator_get_suspend_enable(struct udevice *dev)
> +{
> +	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> +
> +	if (!ops || !ops->get_suspend_enable)
> +		return -ENOSYS;
> +
> +	return ops->get_suspend_enable(dev);
> +}
> +
>  int regulator_get_mode(struct udevice *dev)
>  {
>  	const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> @@ -235,6 +282,11 @@ int regulator_autoset(struct udevice *dev)
>  	int ret = 0;
>  
>  	uc_pdata = dev_get_uclass_platdata(dev);
> +
> +	ret = regulator_set_suspend_enable(dev,
> uc_pdata->suspend_on);
> +	if (!ret && uc_pdata->suspend_on)
> +		ret = regulator_set_suspend_value(dev,
> uc_pdata->suspend_uV); +
>  	if (!uc_pdata->always_on && !uc_pdata->boot_on)
>  		return -EMEDIUMTYPE;
>  
> @@ -243,6 +295,8 @@ int regulator_autoset(struct udevice *dev)
>  
>  	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
>  		ret = regulator_set_value(dev, uc_pdata->min_uV);
> +	if (uc_pdata->init_uV > 0)
> +		ret = regulator_set_value(dev, uc_pdata->init_uV);
>  	if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
>  		ret = regulator_set_current(dev, uc_pdata->min_uA);
>  
> @@ -363,6 +417,7 @@ static int regulator_post_bind(struct udevice
> *dev) static int regulator_pre_probe(struct udevice *dev)
>  {
>  	struct dm_regulator_uclass_platdata *uc_pdata;
> +	ofnode node;
>  
>  	uc_pdata = dev_get_uclass_platdata(dev);
>  	if (!uc_pdata)
> @@ -373,6 +428,8 @@ static int regulator_pre_probe(struct udevice
> *dev) -ENODATA);
>  	uc_pdata->max_uV = dev_read_u32_default(dev,
> "regulator-max-microvolt", -ENODATA);
> +	uc_pdata->init_uV = dev_read_u32_default(dev,
> "regulator-init-microvolt",
> +						-ENODATA);
>  	uc_pdata->min_uA = dev_read_u32_default(dev,
> "regulator-min-microamp", -ENODATA);
>  	uc_pdata->max_uA = dev_read_u32_default(dev,
> "regulator-max-microamp", @@ -382,6 +439,16 @@ static int
> regulator_pre_probe(struct udevice *dev) uc_pdata->ramp_delay =
> dev_read_u32_default(dev, "regulator-ramp-delay", 0);
>  
> +	node = dev_read_subnode(dev, "regulator-state-mem");
> +	if (ofnode_valid(node)) {
> +		uc_pdata->suspend_on = !ofnode_read_bool(node,
> "regulator-off-in-suspend");
> +		if (ofnode_read_u32(node,
> "regulator-suspend-microvolt", &uc_pdata->suspend_uV))
> +			uc_pdata->suspend_uV = uc_pdata->max_uA;
> +	} else {
> +		uc_pdata->suspend_on = true;
> +		uc_pdata->suspend_uV = uc_pdata->max_uA;
> +	}
> +
>  	/* Those values are optional (-ENODATA if unset) */
>  	if ((uc_pdata->min_uV != -ENODATA) &&
>  	    (uc_pdata->max_uV != -ENODATA) &&
> diff --git a/include/power/regulator.h b/include/power/regulator.h
> index 6c6e2cd4f996..64c5108950a0 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 */
> @@ -192,6 +195,8 @@ struct dm_regulator_ops {
>  	 */
>  	int (*get_value)(struct udevice *dev);
>  	int (*set_value)(struct udevice *dev, int uV);
> +	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. @@ -216,6 +221,8 @@ struct dm_regulator_ops {
>  	 */
>  	int (*get_enable)(struct udevice *dev);
>  	int (*set_enable)(struct udevice *dev, bool enable);
> +	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- @@ -262,6 +269,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
>   *
> @@ -317,6 +341,24 @@ 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 - 0 on success 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 *
>   * @dev    - pointer to the regulator device



Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190904/081f44b1/attachment.sig>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [U-Boot] [PATCH v1 1/7] dm: regulator: support regulator more state
  2019-09-04  7:08 ` [U-Boot] [PATCH v1 1/7] dm: regulator: support regulator more state Elaine Zhang
  2019-09-04 10:19   ` Lukasz Majewski
@ 2019-09-17  5:47   ` Simon Glass
  1 sibling, 0 replies; 12+ messages in thread
From: Simon Glass @ 2019-09-17  5:47 UTC (permalink / raw)
  To: u-boot

Hi Elaine,

On Wed, 4 Sep 2019 at 01:09, Elaine Zhang <zhangqing@rock-chips.com> wrote:
>
> From: Joseph Chen <chenjh@rock-chips.com>
>
> 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 <chenjh@rock-chips.com>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
>  drivers/power/regulator/regulator-uclass.c | 67 ++++++++++++++++++++++++++++++
>  include/power/regulator.h                  | 42 +++++++++++++++++++
>  2 files changed, 109 insertions(+)
>
> diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
> index 76be95bcd159..972a5b210c3c 100644
> --- a/drivers/power/regulator/regulator-uclass.c
> +++ b/drivers/power/regulator/regulator-uclass.c
> @@ -77,6 +77,33 @@ int regulator_set_value(struct udevice *dev, int uV)
>         return ret;
>  }
>
> +int regulator_set_suspend_value(struct udevice *dev, int uV)
> +{
> +       const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> +       struct dm_regulator_uclass_platdata *uc_pdata;
> +
> +       uc_pdata = dev_get_uclass_platdata(dev);
> +       if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV)
> +               return -EINVAL;
> +       if (uc_pdata->max_uV != -ENODATA && uV > uc_pdata->max_uV)
> +               return -EINVAL;
> +
> +       if (!ops || !ops->set_suspend_value)

We don't need the !ops - that would be a bug.

> +               return -ENOSYS;
> +
> +       return ops->set_suspend_value(dev, uV);
> +}
> +
> +int regulator_get_suspend_value(struct udevice *dev)
> +{
> +       const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> +
> +       if (!ops || !ops->get_suspend_value)
> +               return -ENOSYS;
> +
> +       return ops->get_suspend_value(dev);
> +}
> +
>  /*
>   * To be called with at most caution as there is no check
>   * before setting the actual voltage value.
> @@ -170,6 +197,26 @@ int regulator_set_enable_if_allowed(struct udevice *dev, bool enable)
>         return ret;
>  }
>
> +int regulator_set_suspend_enable(struct udevice *dev, bool enable)
> +{
> +       const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> +
> +       if (!ops || !ops->set_suspend_enable)
> +               return -ENOSYS;
> +
> +       return ops->set_suspend_enable(dev, enable);
> +}
> +
> +int regulator_get_suspend_enable(struct udevice *dev)
> +{
> +       const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> +
> +       if (!ops || !ops->get_suspend_enable)
> +               return -ENOSYS;
> +
> +       return ops->get_suspend_enable(dev);
> +}
> +
>  int regulator_get_mode(struct udevice *dev)
>  {
>         const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> @@ -235,6 +282,11 @@ int regulator_autoset(struct udevice *dev)
>         int ret = 0;
>
>         uc_pdata = dev_get_uclass_platdata(dev);
> +
> +       ret = regulator_set_suspend_enable(dev, uc_pdata->suspend_on);
> +       if (!ret && uc_pdata->suspend_on)
> +               ret = regulator_set_suspend_value(dev, uc_pdata->suspend_uV);

Where are the return values being checked?

> +
>         if (!uc_pdata->always_on && !uc_pdata->boot_on)
>                 return -EMEDIUMTYPE;
>
> @@ -243,6 +295,8 @@ int regulator_autoset(struct udevice *dev)
>
>         if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
>                 ret = regulator_set_value(dev, uc_pdata->min_uV);
> +       if (uc_pdata->init_uV > 0)
> +               ret = regulator_set_value(dev, uc_pdata->init_uV);
>         if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
>                 ret = regulator_set_current(dev, uc_pdata->min_uA);
>
> @@ -363,6 +417,7 @@ static int regulator_post_bind(struct udevice *dev)
>  static int regulator_pre_probe(struct udevice *dev)
>  {
>         struct dm_regulator_uclass_platdata *uc_pdata;
> +       ofnode node;
>
>         uc_pdata = dev_get_uclass_platdata(dev);
>         if (!uc_pdata)
> @@ -373,6 +428,8 @@ static int regulator_pre_probe(struct udevice *dev)
>                                                 -ENODATA);
>         uc_pdata->max_uV = dev_read_u32_default(dev, "regulator-max-microvolt",
>                                                 -ENODATA);
> +       uc_pdata->init_uV = dev_read_u32_default(dev, "regulator-init-microvolt",
> +                                               -ENODATA);
>         uc_pdata->min_uA = dev_read_u32_default(dev, "regulator-min-microamp",
>                                                 -ENODATA);
>         uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
> @@ -382,6 +439,16 @@ static int regulator_pre_probe(struct udevice *dev)
>         uc_pdata->ramp_delay = dev_read_u32_default(dev, "regulator-ramp-delay",
>                                                     0);
>
> +       node = dev_read_subnode(dev, "regulator-state-mem");
> +       if (ofnode_valid(node)) {
> +               uc_pdata->suspend_on = !ofnode_read_bool(node, "regulator-off-in-suspend");
> +               if (ofnode_read_u32(node, "regulator-suspend-microvolt", &uc_pdata->suspend_uV))
> +                       uc_pdata->suspend_uV = uc_pdata->max_uA;
> +       } else {
> +               uc_pdata->suspend_on = true;
> +               uc_pdata->suspend_uV = uc_pdata->max_uA;
> +       }
> +
>         /* Those values are optional (-ENODATA if unset) */
>         if ((uc_pdata->min_uV != -ENODATA) &&
>             (uc_pdata->max_uV != -ENODATA) &&
> diff --git a/include/power/regulator.h b/include/power/regulator.h
> index 6c6e2cd4f996..64c5108950a0 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;

Please add docs for this in comment above!

>         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 */
> @@ -192,6 +195,8 @@ struct dm_regulator_ops {
>          */
>         int (*get_value)(struct udevice *dev);
>         int (*set_value)(struct udevice *dev, int uV);
> +       int (*set_suspend_value)(struct udevice *dev, int uV);
> +       int (*get_suspend_value)(struct udevice *dev);

Please add documentation as to what these do. You can copy it from
what you have below.

>
>         /**
>          * The regulator output current function calls operates on a micro Amps.
> @@ -216,6 +221,8 @@ struct dm_regulator_ops {
>          */
>         int (*get_enable)(struct udevice *dev);
>         int (*set_enable)(struct udevice *dev, bool enable);
> +       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-
> @@ -262,6 +269,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
>   *
> @@ -317,6 +341,24 @@ 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 - 0 on success or -errno val if fails

So how does it return the the stage? I would expect this to return 0 or 1.

> + */
> +int regulator_get_suspend_enable(struct udevice *dev);
> +
> +/**
>   * regulator_get_mode: get active operation mode id of a given regulator
>   *
>   * @dev    - pointer to the regulator device
> --
> 1.9.1
>
>
>

Please add to the regulator.c tests to cover the above functions.

Regards,
Simon

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2019-09-17  5:47 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-04  7:08 [U-Boot] [PATCH v1 0/8] power: pmic: support more PMIC Elaine Zhang
2019-09-04  7:08 ` [U-Boot] [PATCH v1 1/7] dm: regulator: support regulator more state Elaine Zhang
2019-09-04 10:19   ` Lukasz Majewski
2019-09-17  5:47   ` Simon Glass
2019-09-04  7:08 ` [U-Boot] [PATCH v1 2/7] power: pmic: rk816: support rk816 pmic Elaine Zhang
2019-09-04  7:45   ` Kever Yang
2019-09-04  7:08 ` [U-Boot] [PATCH v1 3/7] power: pmic: rk805: support rk805 pmic Elaine Zhang
2019-09-04  7:08 ` [U-Boot] [PATCH v1 4/7] dm: pmic: add pmic_shutdown() interface Elaine Zhang
2019-09-04  7:10 ` [U-Boot] [PATCH v1 5/7] power: pmic: rk8xx: add pmic_shutdown() implement Elaine Zhang
2019-09-04  7:10 ` [U-Boot] [PATCH v1 6/7] pmic: add RK817 support Elaine Zhang
2019-09-04  7:40   ` Kever Yang
2019-09-04  7:10 ` [U-Boot] [PATCH v1 7/7] pmic: add rk809 support Elaine Zhang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.