]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
regulator: rk808: Add RK801 support
authorJoseph Chen <chenjh@rock-chips.com>
Mon, 12 Jan 2026 12:43:51 +0000 (20:43 +0800)
committerLee Jones <lee@kernel.org>
Tue, 20 Jan 2026 14:58:12 +0000 (14:58 +0000)
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@rock-chips.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Link: https://patch.msgid.link/20260112124351.17707-4-chenjh@rock-chips.com
Signed-off-by: Lee Jones <lee@kernel.org>
drivers/regulator/rk808-regulator.c

index 1e8142479656a0e7d912cdad3d9d17a6d23bd750..e66408f23bb64cd77a385fc2daddd160b7c5e668 100644 (file)
@@ -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
        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,  \
                .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;