summaryrefslogtreecommitdiff
path: root/drivers/regulator/rk808-regulator.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator/rk808-regulator.c')
-rw-r--r--drivers/regulator/rk808-regulator.c261
1 files changed, 235 insertions, 26 deletions
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index d89ae7f16d7a..7d82bd1b36df 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Regulator driver for Rockchip RK805/RK808/RK818
+ * Regulator driver for Rockchip RK80x and RK81x PMIC series
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
@@ -23,7 +23,7 @@
#include <linux/regulator/of_regulator.h>
#include <linux/gpio/consumer.h>
-/* Field Definitions */
+/* Field definitions */
#define RK808_BUCK_VSEL_MASK 0x3f
#define RK808_BUCK4_VSEL_MASK 0xf
#define RK808_LDO_VSEL_MASK 0x1f
@@ -158,6 +158,11 @@
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
};
@@ -534,15 +539,25 @@ static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv)
{
unsigned int reg;
int sel = regulator_map_voltage_linear_range(rdev, uv, uv);
+ int ret;
if (sel < 0)
return -EINVAL;
reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET;
- return regmap_update_bits(rdev->regmap, reg,
- rdev->desc->vsel_mask,
- sel);
+ ret = regmap_update_bits(rdev->regmap, reg,
+ rdev->desc->vsel_mask,
+ sel);
+ if (ret)
+ return ret;
+
+ if (rdev->desc->apply_bit)
+ ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg,
+ rdev->desc->apply_bit,
+ rdev->desc->apply_bit);
+
+ return ret;
}
static int rk805_set_suspend_enable(struct regulator_dev *rdev)
@@ -630,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)
{
@@ -903,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,
@@ -1284,6 +1379,8 @@ static const struct regulator_desc rk809_reg[] = {
.n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
.vsel_reg = RK817_BUCK3_ON_VSEL_REG,
.vsel_mask = RK817_BUCK_VSEL_MASK,
+ .apply_reg = RK817_POWER_CONFIG,
+ .apply_bit = RK817_BUCK3_FB_RES_INTER,
.enable_reg = RK817_POWER_EN_REG(0),
.enable_mask = ENABLE_MASK(RK817_ID_DCDC3),
.enable_val = ENABLE_MASK(RK817_ID_DCDC3),
@@ -1382,6 +1479,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",
@@ -1623,9 +1831,8 @@ static const struct regulator_desc rk818_reg[] = {
RK818_DCDC_EN_REG, BIT(7)),
};
-static int rk808_regulator_dt_parse_pdata(struct device *dev,
- struct regmap *map,
- struct rk808_regulator_data *pdata)
+static int rk808_regulator_dt_parse_pdata(struct device *dev, struct regmap *map,
+ struct rk808_regulator_data *pdata)
{
struct device_node *np;
int tmp, ret = 0, i;
@@ -1636,23 +1843,21 @@ static int rk808_regulator_dt_parse_pdata(struct device *dev,
for (i = 0; i < ARRAY_SIZE(pdata->dvs_gpio); i++) {
pdata->dvs_gpio[i] =
- devm_gpiod_get_index_optional(dev, "dvs", i,
- GPIOD_OUT_LOW);
+ devm_gpiod_get_index_optional(dev, "dvs", i, GPIOD_OUT_LOW);
if (IS_ERR(pdata->dvs_gpio[i])) {
- ret = PTR_ERR(pdata->dvs_gpio[i]);
- dev_err(dev, "failed to get dvs%d gpio (%d)\n", i, ret);
+ ret = dev_err_probe(dev, PTR_ERR(pdata->dvs_gpio[i]),
+ "failed to get dvs%d gpio\n", i);
goto dt_parse_end;
}
if (!pdata->dvs_gpio[i]) {
- dev_info(dev, "there is no dvs%d gpio\n", i);
+ dev_dbg(dev, "there is no dvs%d gpio\n", i);
continue;
}
tmp = i ? RK808_DVS2_POL : RK808_DVS1_POL;
ret = regmap_update_bits(map, RK808_IO_POL_REG, tmp,
- gpiod_is_active_low(pdata->dvs_gpio[i]) ?
- 0 : tmp);
+ gpiod_is_active_low(pdata->dvs_gpio[i]) ? 0 : tmp);
}
dt_parse_end:
@@ -1681,12 +1886,6 @@ static int rk808_regulator_probe(struct platform_device *pdev)
if (!pdata)
return -ENOMEM;
- ret = rk808_regulator_dt_parse_pdata(&pdev->dev, regmap, pdata);
- if (ret < 0)
- return ret;
-
- platform_set_drvdata(pdev, pdata);
-
switch (rk808->variant) {
case RK805_ID:
regulators = rk805_reg;
@@ -1697,6 +1896,11 @@ static int rk808_regulator_probe(struct platform_device *pdev)
nregulators = ARRAY_SIZE(rk806_reg);
break;
case RK808_ID:
+ /* DVS0/1 GPIOs are supported on the RK808 only */
+ ret = rk808_regulator_dt_parse_pdata(&pdev->dev, regmap, pdata);
+ if (ret < 0)
+ return ret;
+
regulators = rk808_reg;
nregulators = RK808_NUM_REGULATORS;
break;
@@ -1704,6 +1908,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;
@@ -1713,11 +1921,12 @@ static int rk808_regulator_probe(struct platform_device *pdev)
nregulators = RK818_NUM_REGULATORS;
break;
default:
- dev_err(&pdev->dev, "unsupported RK8XX ID %lu\n",
- rk808->variant);
- return -EINVAL;
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "unsupported RK8xx ID %lu\n", rk808->variant);
}
+ platform_set_drvdata(pdev, pdata);
+
config.dev = &pdev->dev;
config.driver_data = pdata;
config.regmap = regmap;
@@ -1744,7 +1953,7 @@ static struct platform_driver rk808_regulator_driver = {
module_platform_driver(rk808_regulator_driver);
-MODULE_DESCRIPTION("regulator driver for the RK805/RK808/RK818 series PMICs");
+MODULE_DESCRIPTION("Rockchip RK80x/RK81x PMIC series regulator driver");
MODULE_AUTHOR("Tony xie <tony.xie@rock-chips.com>");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");