[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260112124351.17707-4-chenjh@rock-chips.com>
Date: Mon, 12 Jan 2026 20:43:51 +0800
From: Joseph Chen <chenjh@...k-chips.com>
To: Conor Dooley <conor+dt@...nel.org>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Lee Jones <lee@...nel.org>,
Liam Girdwood <lgirdwood@...il.com>,
Mark Brown <broonie@...nel.org>,
Rob Herring <robh@...nel.org>
Cc: Heiko Stuebner <heiko@...ech.de>,
devicetree@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org,
linux-kernel@...r.kernel.org,
linux-rockchip@...ts.infradead.org,
Joseph Chen <chenjh@...k-chips.com>
Subject: [PATCH v3 3/3] regulator: rk808: Add RK801 support
Add support for rk801 to the existing rk808 regulator driver.
It provides 4 BUCK, 2 LDO and 1 SWITCH.
Signed-off-by: Joseph Chen <chenjh@...k-chips.com>
---
drivers/regulator/rk808-regulator.c | 243 ++++++++++++++++++++++++++++
1 file changed, 243 insertions(+)
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 1e814247965..e66408f23bb 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -24,6 +24,9 @@
#include <linux/gpio/consumer.h>
/* Field definitions */
+#define RK801_BUCK_VSEL_MASK 0x7f
+#define RK801_LDO_VSEL_MASK 0x3f
+
#define RK808_BUCK_VSEL_MASK 0x3f
#define RK808_BUCK4_VSEL_MASK 0xf
#define RK808_LDO_VSEL_MASK 0x1f
@@ -158,6 +161,11 @@
RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, 0, 0, _etime, &rk808_reg_ops)
+#define RK801_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, _disval, _etime) \
+ RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, _emask, _disval, _etime, &rk801_reg_ops)
+
#define RK816_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _disval, _etime) \
RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \
@@ -185,6 +193,11 @@
.ops = _ops \
}
+#define RK801_DESC_SWITCH(_id, _match, _supply, _ereg, _emask, \
+ _disval) \
+ RKXX_DESC_SWITCH_COM(_id, _match, _supply, _ereg, _emask, \
+ _emask, _disval, &rk801_switch_ops)
+
#define RK817_DESC_SWITCH(_id, _match, _supply, _ereg, _emask, \
_disval) \
RKXX_DESC_SWITCH_COM(_id, _match, _supply, _ereg, _emask, \
@@ -802,6 +815,115 @@ static unsigned int rk8xx_regulator_of_map_mode(unsigned int mode)
}
}
+static unsigned int rk801_get_mode(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int err;
+
+ err = regmap_read(rdev->regmap, RK801_POWER_FPWM_EN_REG, &val);
+ if (err)
+ return err;
+
+ if (val & BIT(rdev->desc->id))
+ return REGULATOR_MODE_FAST;
+ else
+ return REGULATOR_MODE_NORMAL;
+}
+
+static int rk801_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ unsigned int offset = rdev->desc->id;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ return regmap_update_bits(rdev->regmap, RK801_POWER_FPWM_EN_REG,
+ BIT(offset), RK801_FPWM_MODE << offset);
+ case REGULATOR_MODE_NORMAL:
+ return regmap_update_bits(rdev->regmap, RK801_POWER_FPWM_EN_REG,
+ BIT(offset), RK801_AUTO_PWM_MODE << offset);
+ default:
+ dev_err(&rdev->dev, "do not support this mode\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rk801_set_suspend_voltage(struct regulator_dev *rdev, int uv)
+{
+ unsigned int reg;
+ int sel;
+
+ if (rdev->desc->id < RK801_ID_LDO1)
+ sel = regulator_map_voltage_linear_range(rdev, uv, uv);
+ else
+ sel = regulator_map_voltage_linear(rdev, uv, uv);
+ if (sel < 0)
+ return -EINVAL;
+
+ reg = rdev->desc->vsel_reg + RK801_SLP_REG_OFFSET;
+
+ return regmap_update_bits(rdev->regmap, reg,
+ rdev->desc->vsel_mask, sel);
+}
+
+static int rk801_set_suspend_enable(struct regulator_dev *rdev)
+{
+ return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
+ BIT(rdev->desc->id), BIT(rdev->desc->id));
+}
+
+static int rk801_set_suspend_disable(struct regulator_dev *rdev)
+{
+ return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
+ BIT(rdev->desc->id), 0);
+}
+
+static int rk801_set_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector,
+ unsigned int new_selector)
+{
+ return regulator_set_voltage_time_sel(rdev, old_selector,
+ new_selector) + RK801_HW_SYNC_US;
+}
+
+static const struct regulator_ops rk801_buck_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = rk801_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_mode = rk801_set_mode,
+ .get_mode = rk801_get_mode,
+ .set_suspend_voltage = rk801_set_suspend_voltage,
+ .set_suspend_enable = rk801_set_suspend_enable,
+ .set_suspend_disable = rk801_set_suspend_disable,
+};
+
+static const struct regulator_ops rk801_reg_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_voltage = rk801_set_suspend_voltage,
+ .set_suspend_enable = rk801_set_suspend_enable,
+ .set_suspend_disable = rk801_set_suspend_disable,
+};
+
+static const struct regulator_ops rk801_switch_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_enable = rk801_set_suspend_enable,
+ .set_suspend_disable = rk801_set_suspend_disable,
+};
+
static const struct regulator_ops rk805_reg_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
@@ -1049,6 +1171,123 @@ static const struct regulator_ops rk817_switch_ops = {
.set_suspend_disable = rk817_set_suspend_disable,
};
+static const struct linear_range rk801_buck1_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 80, 12500), /* 0.5v - 1.5v */
+ REGULATOR_LINEAR_RANGE(1800000, 81, 82, 400000),/* 1.8v - 2.2v */
+ REGULATOR_LINEAR_RANGE(3300000, 83, 83, 0), /* 3.3v */
+ REGULATOR_LINEAR_RANGE(5000000, 84, 84, 0), /* 5.0v */
+ REGULATOR_LINEAR_RANGE(5250000, 85, 85, 0), /* 5.25v */
+};
+
+static const struct linear_range rk801_buck2_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(800000, 0, 2, 50000), /* 0.8v - 0.9v */
+ REGULATOR_LINEAR_RANGE(1800000, 3, 4, 400000), /* 1.8v - 2.2v */
+ REGULATOR_LINEAR_RANGE(3300000, 5, 5, 0), /* 3.3v */
+ REGULATOR_LINEAR_RANGE(5000000, 6, 6, 0), /* 5.0v */
+ REGULATOR_LINEAR_RANGE(5250000, 7, 7, 0), /* 5.25v */
+};
+
+static const struct linear_range rk801_buck4_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 80, 12500), /* 0.5v - 1.5v */
+ REGULATOR_LINEAR_RANGE(1800000, 81, 82, 400000),/* 1.8v - 2.2v */
+ REGULATOR_LINEAR_RANGE(2500000, 83, 83, 0), /* 2.5v */
+ REGULATOR_LINEAR_RANGE(2800000, 84, 84, 0), /* 2.8v */
+ REGULATOR_LINEAR_RANGE(3000000, 85, 85, 0), /* 3.0v */
+ REGULATOR_LINEAR_RANGE(3300000, 86, 86, 0), /* 3.3v */
+};
+
+static const struct regulator_desc rk801_reg[] = {
+ {
+ .name = "dcdc1",
+ .supply_name = "vcc1",
+ .of_match = of_match_ptr("dcdc1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = RK801_ID_DCDC1,
+ .ops = &rk801_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 86,
+ .linear_ranges = rk801_buck1_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk801_buck1_voltage_ranges),
+ .vsel_reg = RK801_BUCK1_ON_VSEL_REG,
+ .vsel_mask = RK801_BUCK_VSEL_MASK,
+ .enable_reg = RK801_POWER_EN0_REG,
+ .enable_mask = ENABLE_MASK(RK801_ID_DCDC1),
+ .enable_val = ENABLE_MASK(RK801_ID_DCDC1),
+ .disable_val = DISABLE_VAL(RK801_ID_DCDC1),
+ .ramp_delay = 1000,
+ .of_map_mode = rk8xx_regulator_of_map_mode,
+ .enable_time = 400,
+ .owner = THIS_MODULE,
+ }, {
+ .name = "dcdc2",
+ .supply_name = "vcc2",
+ .of_match = of_match_ptr("dcdc2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = RK801_ID_DCDC2,
+ .ops = &rk801_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 8,
+ .linear_ranges = rk801_buck2_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk801_buck2_voltage_ranges),
+ .vsel_reg = RK801_BUCK2_ON_VSEL_REG,
+ .vsel_mask = RK801_BUCK_VSEL_MASK,
+ .enable_reg = RK801_POWER_EN0_REG,
+ .enable_mask = ENABLE_MASK(RK801_ID_DCDC2),
+ .enable_val = ENABLE_MASK(RK801_ID_DCDC2),
+ .disable_val = DISABLE_VAL(RK801_ID_DCDC2),
+ .ramp_delay = 1000,
+ .of_map_mode = rk8xx_regulator_of_map_mode,
+ .enable_time = 400,
+ .owner = THIS_MODULE,
+ }, {
+ .name = "dcdc3",
+ .supply_name = "vcc3",
+ .of_match = of_match_ptr("dcdc3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = RK801_ID_DCDC3,
+ .ops = &rk801_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 1,
+ .enable_reg = RK801_POWER_EN0_REG,
+ .enable_mask = ENABLE_MASK(RK801_ID_DCDC3),
+ .enable_val = ENABLE_MASK(RK801_ID_DCDC3),
+ .disable_val = DISABLE_VAL(RK801_ID_DCDC3),
+ .of_map_mode = rk8xx_regulator_of_map_mode,
+ .enable_time = 400,
+ .owner = THIS_MODULE,
+ }, {
+ .name = "dcdc4",
+ .supply_name = "vcc4",
+ .of_match = of_match_ptr("dcdc4"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = RK801_ID_DCDC4,
+ .ops = &rk801_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 87,
+ .linear_ranges = rk801_buck4_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk801_buck4_voltage_ranges),
+ .vsel_reg = RK801_BUCK4_ON_VSEL_REG,
+ .vsel_mask = RK801_BUCK_VSEL_MASK,
+ .enable_reg = RK801_POWER_EN0_REG,
+ .enable_mask = ENABLE_MASK(RK801_ID_DCDC4),
+ .enable_val = ENABLE_MASK(RK801_ID_DCDC4),
+ .disable_val = DISABLE_VAL(RK801_ID_DCDC4),
+ .ramp_delay = 1000,
+ .of_map_mode = rk8xx_regulator_of_map_mode,
+ .enable_time = 400,
+ .owner = THIS_MODULE,
+ },
+
+ RK801_DESC(RK801_ID_LDO1, "ldo1", "vcc5", 500, 3400, 50,
+ RK801_LDO1_ON_VSEL_REG, RK801_LDO_VSEL_MASK, RK801_POWER_EN1_REG,
+ ENABLE_MASK(0), DISABLE_VAL(0), 400),
+ RK801_DESC(RK801_ID_LDO2, "ldo2", "vcc6", 500, 3400, 50,
+ RK801_LDO2_ON_VSEL_REG, RK801_LDO_VSEL_MASK, RK801_POWER_EN1_REG,
+ ENABLE_MASK(1), DISABLE_VAL(1), 400),
+ RK801_DESC_SWITCH(RK801_ID_SWITCH, "switch", "vcc7", RK801_POWER_EN1_REG,
+ ENABLE_MASK(2), DISABLE_VAL(2)),
+};
+
static const struct regulator_desc rk805_reg[] = {
{
.name = "DCDC_REG1",
@@ -1887,6 +2126,10 @@ static int rk808_regulator_probe(struct platform_device *pdev)
return -ENOMEM;
switch (rk808->variant) {
+ case RK801_ID:
+ regulators = rk801_reg;
+ nregulators = RK801_NUM_REGULATORS;
+ break;
case RK805_ID:
regulators = rk805_reg;
nregulators = RK805_NUM_REGULATORS;
--
2.25.1
Powered by blists - more mailing lists