[U-Boot] [PATCH v1 0/8] power: pmic: support more PMIC

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(-)

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

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)
if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)) ret = regulator_set_current(dev, uc_pdata->min_uA);ret = regulator_set_value(dev, uc_pdata->init_uV);
@@ -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",
uc_pdata->min_uA = dev_read_u32_default(dev,-ENODATA);
"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@denx.de

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

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, };

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)
{ struct rk8xx_priv *priv = dev_get_priv(pmic);int num, int uvolt)
- 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)
{ struct rk8xx_priv *priv = dev_get_priv(pmic);int num, int uvolt)
- switch (priv->variant) {
- case RK816_ID:
case RK818_ID: return &rk818_ldo[num]; default:return &rk816_ldo[num];
@@ -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, };

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,

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

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[] = {

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;

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);
return ret; }dev, devctrl_reg);
@@ -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);
}
default: ret = -EINVAL; }break;
@@ -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);
default: ret = -EINVAL; }break;
@@ -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;
default: ret = -EINVAL; }break;
@@ -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
case RK818_ID: return &rk818_ldo[num]; default:return &rk817_ldo[num * 2 + 1];
@@ -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;

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,
participants (4)
-
Elaine Zhang
-
Kever Yang
-
Lukasz Majewski
-
Simon Glass