regulator: rk808: Add RK816 support
authorAlex Bee <knaerzche@gmail.com>
Tue, 16 Apr 2024 16:12:37 +0000 (18:12 +0200)
committerLee Jones <lee@kernel.org>
Fri, 3 May 2024 08:15:38 +0000 (09:15 +0100)
Add support for rk816 to the existing rk808 regulator driver.

The infrastructure of the driver can be re-used as is. A peculiarity for
this version is, that BUCK1/BUCK2 have a (common) bit which needs to
toggled after a voltage change to confirm the change. Regulator regmap
takes care of that by defining a apply_bit and apply_reg for those
regulators.

Signed-off-by: Alex Bee <knaerzche@gmail.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20240416161237.2500037-6-knaerzche@gmail.com
Signed-off-by: Lee Jones <lee@kernel.org>
drivers/regulator/rk808-regulator.c

index a6a563e402d06c9b0af6b5aa43e446cff57eb3bc..14b60abd6afc641d598f609f981d5ebfbdac46a4 100644 (file)
        RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg,  \
        _vmask, _ereg, _emask, 0, 0, _etime, &rk808_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,  \
+       _vmask, _ereg, _emask, _emask, _disval, _etime, &rk816_reg_ops)
+
 #define RK817_DESC(_id, _match, _supply, _min, _max, _step, _vreg,     \
        _vmask, _ereg, _emask, _disval, _etime)                         \
        RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg,  \
@@ -258,7 +263,7 @@ static const unsigned int rk808_buck1_2_ramp_table[] = {
        2000, 4000, 6000, 10000
 };
 
-/* RK817 RK809 */
+/* RK817/RK809/RK816 (buck 1/2 only) */
 static const unsigned int rk817_buck1_4_ramp_table[] = {
        3000, 6300, 12500, 25000
 };
@@ -640,6 +645,38 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev)
                                  rdev->desc->enable_mask);
 }
 
+static const struct rk8xx_register_bit rk816_suspend_bits[] = {
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 0),
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 1),
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 2),
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 3),
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 0),
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 1),
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 2),
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 3),
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 4),
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG2, 5),
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 5),
+       RK8XX_REG_BIT(RK818_SLEEP_SET_OFF_REG1, 6),
+};
+
+static int rk816_set_suspend_enable(struct regulator_dev *rdev)
+{
+       int rid = rdev_get_id(rdev);
+
+       return regmap_update_bits(rdev->regmap, rk816_suspend_bits[rid].reg,
+                                 rk816_suspend_bits[rid].bit,
+                                 rk816_suspend_bits[rid].bit);
+}
+
+static int rk816_set_suspend_disable(struct regulator_dev *rdev)
+{
+       int rid = rdev_get_id(rdev);
+
+       return regmap_update_bits(rdev->regmap, rk816_suspend_bits[rid].reg,
+                                 rk816_suspend_bits[rid].bit, 0);
+}
+
 static int rk817_set_suspend_enable_ctrl(struct regulator_dev *rdev,
                                         unsigned int en)
 {
@@ -913,6 +950,54 @@ static const struct regulator_ops rk809_buck5_ops_range = {
        .set_suspend_disable    = rk817_set_suspend_disable,
 };
 
+static const struct regulator_ops rk816_buck1_2_ops_ranges = {
+       .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   = regulator_set_voltage_time_sel,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .set_mode               = rk8xx_set_mode,
+       .get_mode               = rk8xx_get_mode,
+       .set_suspend_mode       = rk8xx_set_suspend_mode,
+       .set_ramp_delay         = regulator_set_ramp_delay_regmap,
+       .set_suspend_voltage    = rk808_set_suspend_voltage_range,
+       .set_suspend_enable     = rk816_set_suspend_enable,
+       .set_suspend_disable    = rk816_set_suspend_disable,
+};
+
+static const struct regulator_ops rk816_buck4_ops_ranges = {
+       .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   = regulator_set_voltage_time_sel,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .set_mode               = rk8xx_set_mode,
+       .get_mode               = rk8xx_get_mode,
+       .set_suspend_mode       = rk8xx_set_suspend_mode,
+       .set_suspend_voltage    = rk808_set_suspend_voltage_range,
+       .set_suspend_enable     = rk816_set_suspend_enable,
+       .set_suspend_disable    = rk816_set_suspend_disable,
+};
+
+static const struct regulator_ops rk816_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             = rk8xx_is_enabled_wmsk_regmap,
+       .set_suspend_voltage    = rk808_set_suspend_voltage,
+       .set_suspend_enable     = rk816_set_suspend_enable,
+       .set_suspend_disable    = rk816_set_suspend_disable,
+};
+
 static const struct regulator_ops rk817_reg_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
@@ -1392,6 +1477,117 @@ static const struct regulator_desc rk809_reg[] = {
                          DISABLE_VAL(3)),
 };
 
+static const struct linear_range rk816_buck_4_voltage_ranges[] = {
+       REGULATOR_LINEAR_RANGE(800000, 0, 26, 100000),
+       REGULATOR_LINEAR_RANGE(3500000, 27, 31, 0),
+};
+
+static const struct regulator_desc rk816_reg[] = {
+       {
+               .name = "dcdc1",
+               .supply_name = "vcc1",
+               .of_match = of_match_ptr("dcdc1"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = RK816_ID_DCDC1,
+               .ops = &rk816_buck1_2_ops_ranges,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = 64,
+               .linear_ranges = rk805_buck_1_2_voltage_ranges,
+               .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges),
+               .vsel_reg = RK818_BUCK1_ON_VSEL_REG,
+               .vsel_mask = RK818_BUCK_VSEL_MASK,
+               .apply_reg = RK816_DCDC_EN_REG2,
+               .apply_bit = RK816_BUCK_DVS_CONFIRM,
+               .enable_reg = RK816_DCDC_EN_REG1,
+               .enable_mask = BIT(4) | BIT(0),
+               .enable_val = BIT(4) | BIT(0),
+               .disable_val = BIT(4),
+               .ramp_reg = RK818_BUCK1_CONFIG_REG,
+               .ramp_mask = RK808_RAMP_RATE_MASK,
+               .ramp_delay_table = rk817_buck1_4_ramp_table,
+               .n_ramp_values = ARRAY_SIZE(rk817_buck1_4_ramp_table),
+               .of_map_mode = rk8xx_regulator_of_map_mode,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "dcdc2",
+               .supply_name = "vcc2",
+               .of_match = of_match_ptr("dcdc2"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = RK816_ID_DCDC2,
+               .ops = &rk816_buck1_2_ops_ranges,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = 64,
+               .linear_ranges = rk805_buck_1_2_voltage_ranges,
+               .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges),
+               .vsel_reg = RK818_BUCK2_ON_VSEL_REG,
+               .vsel_mask = RK818_BUCK_VSEL_MASK,
+               .apply_reg = RK816_DCDC_EN_REG2,
+               .apply_bit = RK816_BUCK_DVS_CONFIRM,
+               .enable_reg = RK816_DCDC_EN_REG1,
+               .enable_mask = BIT(5) | BIT(1),
+               .enable_val = BIT(5) | BIT(1),
+               .disable_val = BIT(5),
+               .ramp_reg = RK818_BUCK2_CONFIG_REG,
+               .ramp_mask = RK808_RAMP_RATE_MASK,
+               .ramp_delay_table = rk817_buck1_4_ramp_table,
+               .n_ramp_values = ARRAY_SIZE(rk817_buck1_4_ramp_table),
+               .of_map_mode = rk8xx_regulator_of_map_mode,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "dcdc3",
+               .supply_name = "vcc3",
+               .of_match = of_match_ptr("dcdc3"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = RK816_ID_DCDC3,
+               .ops = &rk808_switch_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = 1,
+               .enable_reg = RK816_DCDC_EN_REG1,
+               .enable_mask = BIT(6) | BIT(2),
+               .enable_val =  BIT(6) | BIT(2),
+               .disable_val = BIT(6),
+               .of_map_mode = rk8xx_regulator_of_map_mode,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "dcdc4",
+               .supply_name = "vcc4",
+               .of_match = of_match_ptr("dcdc4"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = RK816_ID_DCDC4,
+               .ops = &rk816_buck4_ops_ranges,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = 32,
+               .linear_ranges = rk816_buck_4_voltage_ranges,
+               .n_linear_ranges = ARRAY_SIZE(rk816_buck_4_voltage_ranges),
+               .vsel_reg = RK818_BUCK4_ON_VSEL_REG,
+               .vsel_mask = RK818_BUCK4_VSEL_MASK,
+               .enable_reg = RK816_DCDC_EN_REG1,
+               .enable_mask = BIT(7) | BIT(3),
+               .enable_val = BIT(7) | BIT(3),
+               .disable_val = BIT(7),
+               .of_map_mode = rk8xx_regulator_of_map_mode,
+               .owner = THIS_MODULE,
+       },
+       RK816_DESC(RK816_ID_LDO1, "ldo1", "vcc5", 800, 3400, 100,
+                  RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
+                  RK816_LDO_EN_REG1, ENABLE_MASK(0), DISABLE_VAL(0), 400),
+       RK816_DESC(RK816_ID_LDO2, "ldo2", "vcc5", 800, 3400, 100,
+                  RK818_LDO2_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
+                  RK816_LDO_EN_REG1, ENABLE_MASK(1), DISABLE_VAL(1), 400),
+       RK816_DESC(RK816_ID_LDO3, "ldo3", "vcc5", 800, 3400, 100,
+                  RK818_LDO3_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
+                  RK816_LDO_EN_REG1, ENABLE_MASK(2), DISABLE_VAL(2), 400),
+       RK816_DESC(RK816_ID_LDO4, "ldo4", "vcc6", 800, 3400, 100,
+                  RK818_LDO4_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
+                  RK816_LDO_EN_REG1, ENABLE_MASK(3), DISABLE_VAL(3), 400),
+       RK816_DESC(RK816_ID_LDO5, "ldo5", "vcc6", 800, 3400, 100,
+                  RK818_LDO5_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
+                  RK816_LDO_EN_REG2, ENABLE_MASK(0), DISABLE_VAL(0), 400),
+       RK816_DESC(RK816_ID_LDO6, "ldo6", "vcc6", 800, 3400, 100,
+                  RK818_LDO6_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
+                  RK816_LDO_EN_REG2, ENABLE_MASK(1), DISABLE_VAL(1), 400),
+};
+
 static const struct regulator_desc rk817_reg[] = {
        {
                .name = "DCDC_REG1",
@@ -1714,6 +1910,10 @@ static int rk808_regulator_probe(struct platform_device *pdev)
                regulators = rk809_reg;
                nregulators = RK809_NUM_REGULATORS;
                break;
+       case RK816_ID:
+               regulators = rk816_reg;
+               nregulators = ARRAY_SIZE(rk816_reg);
+               break;
        case RK817_ID:
                regulators = rk817_reg;
                nregulators = RK817_NUM_REGULATORS;