regulator: rk801: Add driver and fix voltage scale issue

Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
Change-Id: I0fc66ed8e4279a3fbe1ed9d791de745ffaa30891
This commit is contained in:
Joseph Chen 2024-10-16 17:42:29 +08:00
commit ef4c4aba2a
5 changed files with 687 additions and 2 deletions

View file

@ -217,7 +217,7 @@ static const struct resource rk817_pwrkey_resources[] = {
};
static const struct mfd_cell rk801s[] = {
{ .name = "rk808-regulator", },
{ .name = "rk801-regulator", },
{
.name = "rk805-pwrkey",
.num_resources = ARRAY_SIZE(rk801_key_resources),

View file

@ -1053,6 +1053,15 @@ config REGULATOR_RC5T583
through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication.
config REGULATOR_RK801
tristate "Rockchip RK801 Power regulators"
depends on MFD_RK808
help
Select this option to enable the power regulator of ROCKCHIP
PMIC RK801. This driver supports the control of different power rails
of device through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication.
config REGULATOR_RK806
tristate "Rockchip RK806 Power regulator"
depends on MFD_RK806

View file

@ -126,6 +126,7 @@ obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY) += rpi-panel-attiny-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_RK801) += rk801-regulator.o
obj-$(CONFIG_REGULATOR_RK806) += rk806-regulator.o
obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o
obj-$(CONFIG_REGULATOR_RK860X) += rk860x-regulator.o

View file

@ -0,0 +1,669 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Regulator driver for Rockchip RK801
*
* Copyright (c) 2024, Rockchip Electronics Co., Ltd
*/
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/mfd/rk808.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/syscore_ops.h>
#include <linux/gpio/consumer.h>
/* Field Definitions */
#define RK801_BUCK_VSEL_MASK 0x7f
#define RK801_LDO_VSEL_MASK 0x3f
#define ENABLE_MASK(id) (BIT(4 + (id)) | BIT(id))
#define ENABLE_VAL(id) (BIT(4 + (id)) | BIT(id))
#define DISABLE_VAL(id) (BIT(4 + (id)) | 0)
#define RK801_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _enval, _disval, _etime) \
{ \
.name = (_match), \
.supply_name = (_supply), \
.of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \
.type = REGULATOR_VOLTAGE, \
.id = (_id), \
.n_voltages = (((_max) - (_min)) / (_step) + 1), \
.owner = THIS_MODULE, \
.min_uV = (_min) * 1000, \
.uV_step = (_step) * 1000, \
.vsel_reg = (_vreg), \
.vsel_mask = (_vmask), \
.enable_reg = (_ereg), \
.enable_mask = (_emask), \
.enable_val = (_enval), \
.disable_val = (_disval), \
.enable_time = (_etime), \
.ops = &rk801_reg_ops, \
}
#define RK801_DESC_SWITCH(_id, _match, _supply, _ereg, _emask, _enval, \
_disval, _etime) \
{ \
.name = (_match), \
.supply_name = (_supply), \
.of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \
.type = REGULATOR_VOLTAGE, \
.id = (_id), \
.enable_reg = (_ereg), \
.enable_mask = (_emask), \
.enable_val = (_enval), \
.disable_val = (_disval), \
.enable_time = (_etime), \
.owner = THIS_MODULE, \
.ops = &rk801_switch_ops \
}
struct suspend_device {
struct regulator_dev *rdev;
int enable;
int uv;
};
struct runtime_device {
int reg_src;
int reg_dst;
};
struct rk801_regulator_data {
struct gpio_desc *pwrctrl_gpio;
struct suspend_device sdev[RK801_ID_MAX];
bool pwrctrl_dvs;
};
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 unsigned int rk801_regulator_of_map_mode(unsigned int mode)
{
switch (mode) {
case 1:
return REGULATOR_MODE_FAST;
case 2:
return REGULATOR_MODE_NORMAL;
default:
return REGULATOR_MODE_INVALID;
}
}
static unsigned int rk801_get_mode(struct regulator_dev *rdev)
{
unsigned int pmw_mode_msk;
unsigned int val;
int err;
pmw_mode_msk = BIT(rdev->desc->id);
err = regmap_read(rdev->regmap, RK801_POWER_FPWM_EN_REG, &val);
if (err)
return err;
if ((val & pmw_mode_msk) == RK801_FPWM_MODE)
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)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
unsigned int reg;
int sel;
if (pdata->pwrctrl_dvs) {
pdata->sdev[rdev->desc->id].rdev = rdev;
pdata->sdev[rdev->desc->id].uv = uv;
} else {
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);
}
return 0;
}
static int rk801_set_suspend_enable(struct regulator_dev *rdev)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
if (pdata->pwrctrl_dvs) {
pdata->sdev[rdev->desc->id].rdev = rdev;
pdata->sdev[rdev->desc->id].enable = 1;
} else {
return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
BIT(rdev->desc->id), BIT(rdev->desc->id));
}
return 0;
}
static int rk801_set_suspend_disable(struct regulator_dev *rdev)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
if (pdata->pwrctrl_dvs) {
pdata->sdev[rdev->desc->id].rdev = rdev;
pdata->sdev[rdev->desc->id].enable = 0;
} else {
return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
BIT(rdev->desc->id), 0);
}
return 0;
}
static int rk801_set_enable(struct regulator_dev *rdev)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
int ret;
ret = regulator_enable_regmap(rdev);
if (ret)
return ret;
if (pdata->pwrctrl_dvs)
return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
BIT(rdev->desc->id), BIT(rdev->desc->id));
return 0;
}
static int rk801_set_disable(struct regulator_dev *rdev)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
int ret;
ret = regulator_disable_regmap(rdev);
if (ret)
return ret;
if (pdata->pwrctrl_dvs)
return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
BIT(rdev->desc->id), 0);
return 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) + 32;
}
static int rk801_set_voltage_sel(struct regulator_dev *rdev, unsigned sel)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
struct gpio_desc *gpio = pdata->pwrctrl_gpio;
unsigned int reg0 = rdev->desc->vsel_reg;
unsigned int reg1 = rdev->desc->vsel_reg + RK801_SLP_REG_OFFSET;
unsigned int reg;
int ret, gpio_level;
if (pdata->pwrctrl_dvs) {
gpio_level = gpiod_get_value(gpio);
reg = (gpio_level == 1) ? reg0 : reg1;
sel <<= ffs(rdev->desc->vsel_mask) - 1;
ret = regmap_update_bits(rdev->regmap, reg, rdev->desc->vsel_mask, sel);
if (ret)
return ret;
udelay(40); /* hw sync */
gpiod_set_value(gpio, !gpio_level);
if (reg == reg0)
ret = regmap_update_bits(rdev->regmap, reg1,
rdev->desc->vsel_mask, sel);
else
ret = regmap_update_bits(rdev->regmap, reg0,
rdev->desc->vsel_mask, sel);
} else {
ret = regulator_set_voltage_sel_regmap(rdev, sel);
}
return ret;
}
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 = rk801_set_voltage_sel,
.set_voltage_time_sel = rk801_set_voltage_time_sel,
.enable = rk801_set_enable,
.disable = rk801_set_disable,
.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 = rk801_set_voltage_sel,
.enable = rk801_set_enable,
.disable = rk801_set_disable,
.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_desc rk801_reg[] = {
{
.name = "DCDC_REG1",
.supply_name = "vcc1",
.of_match = of_match_ptr("DCDC_REG1"),
.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_VAL(RK801_ID_DCDC1),
.disable_val = DISABLE_VAL(RK801_ID_DCDC1),
.ramp_delay = 1,
.of_map_mode = rk801_regulator_of_map_mode,
.enable_time = 400,
.owner = THIS_MODULE,
}, {
.name = "DCDC_REG2",
.supply_name = "vcc2",
.of_match = of_match_ptr("DCDC_REG2"),
.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_VAL(RK801_ID_DCDC2),
.disable_val = DISABLE_VAL(RK801_ID_DCDC2),
.ramp_delay = 1,
.of_map_mode = rk801_regulator_of_map_mode,
.enable_time = 400,
.owner = THIS_MODULE,
}, {
.name = "DCDC_REG3",
.supply_name = "vcc3",
.of_match = of_match_ptr("DCDC_REG3"),
.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_VAL(RK801_ID_DCDC3),
.disable_val = DISABLE_VAL(RK801_ID_DCDC3),
.of_map_mode = rk801_regulator_of_map_mode,
.enable_time = 400,
.owner = THIS_MODULE,
}, {
.name = "DCDC_REG4",
.supply_name = "vcc4",
.of_match = of_match_ptr("DCDC_REG4"),
.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_VAL(RK801_ID_DCDC4),
.disable_val = DISABLE_VAL(RK801_ID_DCDC4),
.ramp_delay = 1,
.of_map_mode = rk801_regulator_of_map_mode,
.enable_time = 400,
.owner = THIS_MODULE,
},
RK801_DESC(RK801_ID_LDO1, "LDO_REG1", "vcc5", 500, 3400, 50,
RK801_LDO1_ON_VSEL_REG, RK801_LDO_VSEL_MASK, RK801_POWER_EN1_REG,
ENABLE_MASK(0), ENABLE_VAL(0), DISABLE_VAL(0), 400),
RK801_DESC(RK801_ID_LDO2, "LDO_REG2", "vcc6", 500, 3400, 50,
RK801_LDO2_ON_VSEL_REG, RK801_LDO_VSEL_MASK, RK801_POWER_EN1_REG,
ENABLE_MASK(1), ENABLE_VAL(1), DISABLE_VAL(1), 400),
RK801_DESC_SWITCH(RK801_ID_SWITCH, "SWITCH_REG", "vcc7", RK801_POWER_EN1_REG,
ENABLE_MASK(2), ENABLE_VAL(2), DISABLE_VAL(2), 400),
};
static int rk801_regulator_dt_parse_pdata(struct device *dev,
struct device *client_dev,
struct regmap *map,
struct rk801_regulator_data *pdata)
{
struct device_node *np;
int ret = 0;
np = of_get_child_by_name(client_dev->of_node, "regulators");
if (!np)
return -ENXIO;
if (pdata->pwrctrl_dvs) {
pdata->pwrctrl_gpio = devm_gpiod_get_optional(client_dev,
"pwrctrl", GPIOD_OUT_LOW);
if (IS_ERR(pdata->pwrctrl_gpio)) {
ret = PTR_ERR(pdata->pwrctrl_gpio);
dev_err(dev, "failed to get pwrctrl gpio! ret=%d\n", ret);
goto dt_parse_end;
}
if (!pdata->pwrctrl_gpio) {
dev_err(dev, "there is no pwrctrl gpio!\n");
ret = -EINVAL;
}
}
dt_parse_end:
of_node_put(np);
return ret;
}
static int rk801_regulator_init(struct device *dev)
{
struct rk808 *rk808 = dev_get_drvdata(dev->parent);
struct rk801_regulator_data *pdata = dev_get_drvdata(dev);
struct runtime_device rdev[] = {
{ RK801_BUCK1_ON_VSEL_REG, RK801_BUCK1_SLP_VSEL_REG },
{ RK801_BUCK2_ON_VSEL_REG, RK801_BUCK2_SLP_VSEL_REG },
{ RK801_BUCK4_ON_VSEL_REG, RK801_BUCK4_SLP_VSEL_REG },
{ RK801_LDO1_ON_VSEL_REG, RK801_LDO1_SLP_VSEL_REG },
{ RK801_LDO2_ON_VSEL_REG, RK801_LDO2_SLP_VSEL_REG },
};
uint val, en0, en1;
int i, ret;
/* pwrctrl gpio active high and use sleep function */
ret = regmap_update_bits(rk808->regmap, RK801_SYS_CFG2_REG,
RK801_SLEEP_POL_MSK, RK801_SLEEP_ACT_H);
if (ret)
return ret;
ret = regmap_update_bits(rk808->regmap, RK801_SLEEP_CFG_REG,
RK801_SLEEP_FUN_MSK, RK801_SLEEP_FUN);
if (ret)
return ret;
/* disable buck/pldo slp lp */
ret = regmap_update_bits(rk808->regmap, RK801_SLP_LP_CONFIG_REG,
RK801_SLP_LP_MASK, 0);
if (ret)
return ret;
/* copy en/slp_en */
ret = regmap_read(rk808->regmap, RK801_POWER_EN0_REG, &en0);
if (ret)
return ret;
ret = regmap_read(rk808->regmap, RK801_POWER_EN1_REG, &en1);
if (ret)
return ret;
val = (en0 & 0x0f) | ((en1 & 0x0f) << 4);
ret = regmap_write(rk808->regmap, RK801_POWER_SLP_EN_REG, val);
if (ret)
return ret;
/* copy on_vsel/slp_vsel */
for (i = 0; i < ARRAY_SIZE(rdev); i++) {
ret = regmap_read(rk808->regmap, rdev[i].reg_src, &val);
if (ret)
return ret;
ret = regmap_write(rk808->regmap, rdev[i].reg_dst, val);
if (ret)
return ret;
}
/* init */
for (i = 0; i < ARRAY_SIZE(pdata->sdev); i++) {
pdata->sdev[i].rdev = NULL;
pdata->sdev[i].uv = -EINVAL;
pdata->sdev[i].enable = -EINVAL;
}
return 0;
}
static int rk801_set_suspend_dev(struct suspend_device sdev)
{
struct regulator_dev *rdev = sdev.rdev;
int enable = sdev.enable;
int uv = sdev.uv;
int val, sel, reg;
int ret, mask;
if (!rdev)
return 0;
if (uv != -EINVAL) {
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;
ret = regmap_update_bits(rdev->regmap, reg,
rdev->desc->vsel_mask, sel);
if (ret)
return ret;
}
if (enable != -EINVAL) {
mask = BIT(rdev->desc->id);
val = enable ? mask : 0;
ret = regmap_update_bits(rdev->regmap,
RK801_POWER_SLP_EN_REG, mask, val);
if (ret)
return ret;
}
return 0;
}
static int rk801_regulator_suspend_late(struct device *dev)
{
struct rk808 *rk808 = dev_get_drvdata(dev->parent);
struct rk801_regulator_data *pdata = dev_get_drvdata(dev);
struct gpio_desc *gpio = pdata->pwrctrl_gpio;
int i, ret;
if (!pdata->pwrctrl_dvs)
return 0;
/* set pwrctrl pin low */
gpiod_set_value(gpio, 0);
udelay(40);
/* set buck/ldo/switch suspend */
for (i = 0; i < ARRAY_SIZE(pdata->sdev); i++) {
ret = rk801_set_suspend_dev(pdata->sdev[i]);
if (ret)
return ret;
}
/* enable buck/pldo lp enable */
return regmap_update_bits(rk808->regmap, RK801_SLP_LP_CONFIG_REG,
RK801_SLP_LP_MASK, RK801_SLP_LP_MASK);
}
static int rk801_regulator_resume_early(struct device *dev)
{
struct rk801_regulator_data *pdata = dev_get_drvdata(dev);
if (!pdata->pwrctrl_dvs)
return 0;
return rk801_regulator_init(dev);
}
static int rk801_regulator_probe(struct platform_device *pdev)
{
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
struct i2c_client *client = rk808->i2c;
struct regulator_config config = {};
struct regulator_dev *rk801_rdev;
struct rk801_regulator_data *pdata;
int id_lsb, i, ret;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
ret = regmap_read(rk808->regmap, RK801_ID_LSB, &id_lsb);
if (ret)
return ret;
pdata->pwrctrl_dvs = (id_lsb & 0x0f) < 4;
dev_info(&pdev->dev, "pwrctrl dvs: %d\n", pdata->pwrctrl_dvs);
ret = rk801_regulator_dt_parse_pdata(&pdev->dev, &client->dev,
rk808->regmap, pdata);
if (ret < 0)
return ret;
platform_set_drvdata(pdev, pdata);
config.dev = &client->dev;
config.driver_data = pdata;
config.regmap = rk808->regmap;
ret = rk801_regulator_init(&pdev->dev);
if (ret)
return ret;
for (i = 0; i < RK801_NUM_REGULATORS; i++) {
rk801_rdev = devm_regulator_register(&pdev->dev,
&rk801_reg[i], &config);
if (IS_ERR(rk801_rdev)) {
dev_err(&client->dev,
"failed to register %d regulator\n", i);
return PTR_ERR(rk801_rdev);
}
}
return 0;
}
static const struct dev_pm_ops rk801_pm_ops = {
.suspend_late = pm_sleep_ptr(rk801_regulator_suspend_late),
.resume_early = pm_sleep_ptr(rk801_regulator_resume_early),
};
static struct platform_driver rk801_regulator_driver = {
.probe = rk801_regulator_probe,
.driver = {
.name = "rk801-regulator",
.pm = pm_sleep_ptr(&rk801_pm_ops),
},
};
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
static int __init rk801_regulator_driver_init(void)
{
return platform_driver_register(&rk801_regulator_driver);
}
subsys_initcall(rk801_regulator_driver_init);
static void __exit rk801_regulator_driver_exit(void)
{
platform_driver_unregister(&rk801_regulator_driver);
}
module_exit(rk801_regulator_driver_exit);
#else
module_platform_driver(rk801_regulator_driver);
#endif
MODULE_DESCRIPTION("regulator driver for the RK801 PMIC");
MODULE_AUTHOR("Joseph Chen <chenjh@rock-chips.com>");
MODULE_LICENSE("GPL");

View file

@ -22,11 +22,12 @@
enum rk801_reg {
RK801_ID_DCDC1,
RK801_ID_DCDC2,
RK801_ID_DCDC3,
RK801_ID_DCDC4,
RK801_ID_DCDC3,
RK801_ID_LDO1,
RK801_ID_LDO2,
RK801_ID_SWITCH,
RK801_ID_MAX,
};
#define RK801_SLP_REG_OFFSET 5
@ -107,6 +108,11 @@ enum rk801_reg {
#define RK801_IRQ_VDC_RISE_MSK BIT(5)
#define RK801_IRQ_VDC_FALL_MSK BIT(6)
/* RK801_SLP_LP_CONFIG_REG */
#define RK801_BUCK_SLP_LP_EN BIT(3)
#define RK801_PLDO_SLP_LP_EN BIT(1)
#define RK801_SLP_LP_MASK (RK801_PLDO_SLP_LP_EN | RK801_BUCK_SLP_LP_EN)
/* RK801_SLEEP_CFG_REG */
#define RK801_SLEEP_FUN_MSK 0x3
#define RK801_NONE_FUN 0x0