mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
regulator: xz3216: update drivers to support vsel set
Signed-off-by: Zorro Liu <lyx@rock-chips.com> Change-Id: Ifd686fb977f9d397d856cf6338499fcbbe674fd2
This commit is contained in:
@@ -66,15 +66,19 @@ struct xz3216 {
|
||||
struct i2c_client *i2c;
|
||||
int num_regulators;
|
||||
struct regulator_dev *rdev;
|
||||
struct regulator_desc desc;
|
||||
struct regulator_init_data *regulator;
|
||||
struct regmap *regmap;
|
||||
/* Voltage setting register */
|
||||
unsigned int vol_reg;
|
||||
unsigned int sleep_reg;
|
||||
unsigned int en_reg;
|
||||
unsigned int sleep_en_reg;
|
||||
/* Voltage range and step(linear) */
|
||||
unsigned int vsel_min;
|
||||
unsigned int vsel_step;
|
||||
unsigned int sleep_vol_cache;
|
||||
unsigned int sleep_vsel_id;
|
||||
};
|
||||
|
||||
struct xz3216_regulator {
|
||||
@@ -86,6 +90,7 @@ struct xz3216_regulator {
|
||||
struct xz3216_board {
|
||||
struct regulator_init_data *xz3216_init_data;
|
||||
struct device_node *of_node;
|
||||
unsigned int sleep_vsel_id;
|
||||
};
|
||||
|
||||
static unsigned int xz3216_dcdc_get_mode(struct regulator_dev *dev)
|
||||
@@ -120,19 +125,51 @@ static int xz3216_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode)
|
||||
}
|
||||
}
|
||||
|
||||
static int xz3216_dcdc_is_enable(struct regulator_dev *dev)
|
||||
{
|
||||
struct xz3216 *xz3216 = rdev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
unsigned int val;
|
||||
|
||||
ret = regmap_read(xz3216->regmap, xz3216->en_reg, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (val & VSEL_BUCK_EN)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xz3216_dcdc_enable(struct regulator_dev *dev)
|
||||
{
|
||||
struct xz3216 *xz3216 = rdev_get_drvdata(dev);
|
||||
|
||||
return regmap_update_bits(xz3216->regmap, xz3216->en_reg,
|
||||
VSEL_BUCK_EN, VSEL_BUCK_EN);
|
||||
}
|
||||
|
||||
static int xz3216_dcdc_disable(struct regulator_dev *dev)
|
||||
{
|
||||
struct xz3216 *xz3216 = rdev_get_drvdata(dev);
|
||||
|
||||
return regmap_update_bits(xz3216->regmap, xz3216->en_reg,
|
||||
VSEL_BUCK_EN, 0);
|
||||
}
|
||||
|
||||
static int xz3216_dcdc_suspend_enable(struct regulator_dev *dev)
|
||||
{
|
||||
struct xz3216 *xz3216 = rdev_get_drvdata(dev);
|
||||
return regmap_update_bits(xz3216->regmap, XZ3216_BUCK1_SLP_VOL_BASE,
|
||||
VSEL_BUCK_EN, VSEL_BUCK_EN);
|
||||
|
||||
return regmap_update_bits(xz3216->regmap, xz3216->sleep_en_reg,
|
||||
VSEL_BUCK_EN, VSEL_BUCK_EN);
|
||||
}
|
||||
|
||||
static int xz3216_dcdc_suspend_disable(struct regulator_dev *dev)
|
||||
{
|
||||
struct xz3216 *xz3216 = rdev_get_drvdata(dev);
|
||||
return regmap_update_bits(xz3216->regmap, XZ3216_BUCK1_SLP_VOL_BASE,
|
||||
VSEL_BUCK_EN, 0);
|
||||
|
||||
return regmap_update_bits(xz3216->regmap, xz3216->sleep_en_reg,
|
||||
VSEL_BUCK_EN, 0);
|
||||
}
|
||||
|
||||
static int xz3216_dcdc_set_sleep_voltage(struct regulator_dev *dev,
|
||||
@@ -146,13 +183,13 @@ static int xz3216_dcdc_set_sleep_voltage(struct regulator_dev *dev,
|
||||
ret = regulator_map_voltage_linear(dev, uV, uV);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = regmap_update_bits(xz3216->regmap, XZ3216_BUCK1_SLP_VOL_BASE,
|
||||
ret = regmap_update_bits(xz3216->regmap, xz3216->sleep_reg,
|
||||
VSEL_NSEL_MASK, ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
xz3216->sleep_vol_cache = uV;
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xz3216_dcdc_set_suspend_mode(struct regulator_dev *dev,
|
||||
@@ -162,11 +199,11 @@ static int xz3216_dcdc_set_suspend_mode(struct regulator_dev *dev,
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
return regmap_update_bits(xz3216->regmap, xz3216->vol_reg,
|
||||
VSEL_MODE, VSEL_MODE);
|
||||
return regmap_update_bits(xz3216->regmap, xz3216->sleep_reg,
|
||||
VSEL_MODE, VSEL_MODE);
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
return regmap_update_bits(xz3216->regmap, xz3216->vol_reg,
|
||||
VSEL_MODE, 0);
|
||||
return regmap_update_bits(xz3216->regmap, xz3216->sleep_reg,
|
||||
VSEL_MODE, 0);
|
||||
default:
|
||||
DBG_ERR("error:dcdc_xz3216 only auto and pwm mode\n");
|
||||
return -EINVAL;
|
||||
@@ -209,9 +246,9 @@ static struct regulator_ops xz3216_dcdc_ops = {
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = xz3216_dcdc_is_enable,
|
||||
.enable = xz3216_dcdc_enable,
|
||||
.disable = xz3216_dcdc_disable,
|
||||
.get_mode = xz3216_dcdc_get_mode,
|
||||
.set_mode = xz3216_dcdc_set_mode,
|
||||
.set_suspend_voltage = xz3216_dcdc_set_sleep_voltage,
|
||||
@@ -222,24 +259,44 @@ static struct regulator_ops xz3216_dcdc_ops = {
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
};
|
||||
|
||||
static struct regulator_desc regulators[] = {
|
||||
{
|
||||
.name = "XZ_DCDC1",
|
||||
.supply_name = "vin",
|
||||
.id = 0,
|
||||
.ops = &xz3216_dcdc_ops,
|
||||
.n_voltages = 64,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.enable_time = 400,
|
||||
.enable_reg = XZ3216_BUCK1_SET_VOL_BASE,
|
||||
.enable_mask = VSEL_BUCK_EN,
|
||||
.min_uV = 600000,
|
||||
.uV_step = 12500,
|
||||
.vsel_reg = XZ3216_BUCK1_SET_VOL_BASE,
|
||||
.vsel_mask = VSEL_NSEL_MASK,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
static int xz3216_regulator_register(struct xz3216 *xz3216, struct regulator_config *config)
|
||||
{
|
||||
struct regulator_desc *rdesc = &xz3216->desc;
|
||||
|
||||
rdesc->name = "XZ_DCDC1";
|
||||
rdesc->supply_name = "vin";
|
||||
rdesc->id = 0;
|
||||
rdesc->ops = &xz3216_dcdc_ops;
|
||||
rdesc->type = REGULATOR_VOLTAGE;
|
||||
rdesc->n_voltages = 64;
|
||||
rdesc->enable_mask = VSEL_BUCK_EN;
|
||||
rdesc->min_uV = 600000;
|
||||
rdesc->uV_step = 12500;
|
||||
rdesc->vsel_mask = VSEL_NSEL_MASK;
|
||||
rdesc->owner = THIS_MODULE;
|
||||
rdesc->enable_time = 400;
|
||||
|
||||
if (xz3216->sleep_vsel_id) {
|
||||
rdesc->vsel_reg = XZ3216_BUCK1_SET_VOL_BASE;
|
||||
rdesc->enable_reg = XZ3216_BUCK1_SET_VOL_BASE;
|
||||
|
||||
xz3216->vol_reg = rdesc->vsel_reg;
|
||||
xz3216->en_reg = rdesc->vsel_reg;
|
||||
xz3216->sleep_reg = XZ3216_BUCK1_SLP_VOL_BASE;
|
||||
xz3216->sleep_en_reg = xz3216->sleep_reg;
|
||||
} else {
|
||||
rdesc->vsel_reg = XZ3216_BUCK1_SLP_VOL_BASE;
|
||||
rdesc->enable_reg = XZ3216_BUCK1_SLP_VOL_BASE;
|
||||
|
||||
xz3216->vol_reg = rdesc->vsel_reg;
|
||||
xz3216->en_reg = rdesc->vsel_reg;
|
||||
xz3216->sleep_reg = XZ3216_BUCK1_SET_VOL_BASE;
|
||||
xz3216->sleep_en_reg = xz3216->sleep_reg;
|
||||
}
|
||||
xz3216->rdev = devm_regulator_register(xz3216->dev, &xz3216->desc, config);
|
||||
|
||||
return PTR_ERR_OR_ZERO(xz3216->rdev);
|
||||
}
|
||||
|
||||
static const struct regmap_config xz3216_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
@@ -265,26 +322,47 @@ static struct xz3216_board *xz3216_parse_dt(struct xz3216 *xz3216)
|
||||
struct device_node *regs;
|
||||
struct device_node *xz3216_np;
|
||||
int count;
|
||||
u32 tmp;
|
||||
|
||||
pdata = devm_kzalloc(xz3216->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return NULL;
|
||||
|
||||
xz3216_np = of_node_get(xz3216->dev->of_node);
|
||||
if (!xz3216_np) {
|
||||
DBG_ERR("could not find pmic sub-node\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
regs = of_find_node_by_name(xz3216_np, "regulator");
|
||||
if (!regs) {
|
||||
DBG_ERR("can not found regulator node\n");
|
||||
return NULL;
|
||||
}
|
||||
count = of_property_read_u32(regs, "fcs,suspend-voltage-selector",
|
||||
&tmp);
|
||||
if (!count) {
|
||||
pdata->sleep_vsel_id = tmp;
|
||||
pr_info("xz3216, suspend-voltage-selector = %d\n", pdata->sleep_vsel_id);
|
||||
} else {
|
||||
pdata->sleep_vsel_id = 0;
|
||||
pr_info("xz3216, get suspend-voltage-selector failed, use default value\n");
|
||||
}
|
||||
of_node_put(regs);
|
||||
|
||||
regs = of_find_node_by_name(xz3216_np, "regulators");
|
||||
if (!regs)
|
||||
return NULL;
|
||||
count = of_regulator_match(xz3216->dev, regs, xz3216_reg_matches,
|
||||
XZ3216_NUM_REGULATORS);
|
||||
of_node_put(regs);
|
||||
pdata = devm_kzalloc(xz3216->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
if (!count)
|
||||
return NULL;
|
||||
pdata->xz3216_init_data = xz3216_reg_matches[0].init_data;
|
||||
pdata->of_node = xz3216_reg_matches[0].of_node;
|
||||
|
||||
return pdata;
|
||||
}
|
||||
|
||||
#else
|
||||
static struct xz3216_board *xz3216_parse_dt(struct i2c_client *i2c)
|
||||
{
|
||||
@@ -300,7 +378,7 @@ static int xz3216_i2c_probe(struct i2c_client *i2c,
|
||||
const struct of_device_id *match;
|
||||
struct regulator_config config = { };
|
||||
int ret;
|
||||
DBG("%s, line=%d\n", __func__, __LINE__);
|
||||
|
||||
xz3216 = devm_kzalloc(&i2c->dev, sizeof(struct xz3216),
|
||||
GFP_KERNEL);
|
||||
if (!xz3216) {
|
||||
@@ -329,6 +407,7 @@ static int xz3216_i2c_probe(struct i2c_client *i2c,
|
||||
if (!pdev)
|
||||
pdev = xz3216_parse_dt(xz3216);
|
||||
if (pdev) {
|
||||
xz3216->sleep_vsel_id = pdev->sleep_vsel_id;
|
||||
xz3216->num_regulators = XZ3216_NUM_REGULATORS;
|
||||
xz3216->rdev = kcalloc(XZ3216_NUM_REGULATORS,
|
||||
sizeof(struct regulator_dev),
|
||||
@@ -342,9 +421,8 @@ static int xz3216_i2c_probe(struct i2c_client *i2c,
|
||||
config.dev = xz3216->dev;
|
||||
config.driver_data = xz3216;
|
||||
config.init_data = xz3216->regulator;
|
||||
xz3216->rdev = devm_regulator_register(xz3216->dev,
|
||||
®ulators[0], &config);
|
||||
ret = PTR_ERR_OR_ZERO(xz3216->rdev);
|
||||
config.regmap = xz3216->regmap;
|
||||
ret = xz3216_regulator_register(xz3216, &config);
|
||||
if (ret < 0)
|
||||
dev_err(&i2c->dev, "Failed to register regulator!\n");
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user