aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/regulator/tps51632-regulator.txt27
-rw-r--r--drivers/regulator/tps51632-regulator.c152
2 files changed, 130 insertions, 49 deletions
diff --git a/Documentation/devicetree/bindings/regulator/tps51632-regulator.txt b/Documentation/devicetree/bindings/regulator/tps51632-regulator.txt
new file mode 100644
index 000000000000..2f7e44a96414
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/tps51632-regulator.txt
@@ -0,0 +1,27 @@
1TPS51632 Voltage regulators
2
3Required properties:
4- compatible: Must be "ti,tps51632"
5- reg: I2C slave address
6
7Optional properties:
8- ti,enable-pwm-dvfs: Enable the DVFS voltage control through the PWM interface.
9- ti,dvfs-step-20mV: The 20mV step voltage when PWM DVFS enabled. Missing this
10 will set 10mV step voltage in PWM DVFS mode. In normal mode, the voltage
11 step is 10mV as per datasheet.
12
13Any property defined as part of the core regulator binding, defined in
14regulator.txt, can also be used.
15
16Example:
17
18 tps51632 {
19 compatible = "ti,tps51632";
20 reg = <0x43>;
21 regulator-name = "tps51632-vout";
22 regulator-min-microvolt = <500000>;
23 regulator-max-microvolt = <1500000>;
24 regulator-boot-on;
25 ti,enable-pwm-dvfs;
26 ti,dvfs-step-20mV;
27 };
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
index ab21133e6784..6e67be75ea1b 100644
--- a/drivers/regulator/tps51632-regulator.c
+++ b/drivers/regulator/tps51632-regulator.c
@@ -28,10 +28,13 @@
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/of.h>
32#include <linux/of_device.h>
31#include <linux/platform_device.h> 33#include <linux/platform_device.h>
32#include <linux/regmap.h> 34#include <linux/regmap.h>
33#include <linux/regulator/driver.h> 35#include <linux/regulator/driver.h>
34#include <linux/regulator/machine.h> 36#include <linux/regulator/machine.h>
37#include <linux/regulator/of_regulator.h>
35#include <linux/regulator/tps51632-regulator.h> 38#include <linux/regulator/tps51632-regulator.h>
36#include <linux/slab.h> 39#include <linux/slab.h>
37 40
@@ -85,49 +88,8 @@ struct tps51632_chip {
85 struct regulator_desc desc; 88 struct regulator_desc desc;
86 struct regulator_dev *rdev; 89 struct regulator_dev *rdev;
87 struct regmap *regmap; 90 struct regmap *regmap;
88 bool enable_pwm_dvfs;
89}; 91};
90 92
91static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev)
92{
93 struct tps51632_chip *tps = rdev_get_drvdata(rdev);
94 unsigned int data;
95 int ret;
96 unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
97 int vsel;
98
99 if (tps->enable_pwm_dvfs)
100 reg = TPS51632_VOLTAGE_BASE_REG;
101
102 ret = regmap_read(tps->regmap, reg, &data);
103 if (ret < 0) {
104 dev_err(tps->dev, "reg read failed, err %d\n", ret);
105 return ret;
106 }
107
108 vsel = data & TPS51632_VOUT_MASK;
109 return vsel;
110}
111
112static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev,
113 unsigned selector)
114{
115 struct tps51632_chip *tps = rdev_get_drvdata(rdev);
116 int ret;
117 unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
118
119 if (tps->enable_pwm_dvfs)
120 reg = TPS51632_VOLTAGE_BASE_REG;
121
122 if (selector > TPS51632_MAX_VSEL)
123 return -EINVAL;
124
125 ret = regmap_write(tps->regmap, reg, selector);
126 if (ret < 0)
127 dev_err(tps->dev, "reg write failed, err %d\n", ret);
128 return ret;
129}
130
131static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev, 93static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
132 int ramp_delay) 94 int ramp_delay)
133{ 95{
@@ -144,8 +106,8 @@ static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
144} 106}
145 107
146static struct regulator_ops tps51632_dcdc_ops = { 108static struct regulator_ops tps51632_dcdc_ops = {
147 .get_voltage_sel = tps51632_dcdc_get_voltage_sel, 109 .get_voltage_sel = regulator_get_voltage_sel_regmap,
148 .set_voltage_sel = tps51632_dcdc_set_voltage_sel, 110 .set_voltage_sel = regulator_set_voltage_sel_regmap,
149 .list_voltage = regulator_list_voltage_linear, 111 .list_voltage = regulator_list_voltage_linear,
150 .set_voltage_time_sel = regulator_set_voltage_time_sel, 112 .set_voltage_time_sel = regulator_set_voltage_time_sel,
151 .set_ramp_delay = tps51632_dcdc_set_ramp_delay, 113 .set_ramp_delay = tps51632_dcdc_set_ramp_delay,
@@ -162,7 +124,6 @@ static int tps51632_init_dcdc(struct tps51632_chip *tps,
162 goto skip_pwm_config; 124 goto skip_pwm_config;
163 125
164 control |= TPS51632_DVFS_PWMEN; 126 control |= TPS51632_DVFS_PWMEN;
165 tps->enable_pwm_dvfs = pdata->enable_pwm_dvfs;
166 vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV); 127 vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV);
167 ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel); 128 ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel);
168 if (ret < 0) { 129 if (ret < 0) {
@@ -205,22 +166,96 @@ skip_pwm_config:
205 return ret; 166 return ret;
206} 167}
207 168
208static bool rd_wr_reg(struct device *dev, unsigned int reg) 169static bool is_volatile_reg(struct device *dev, unsigned int reg)
170{
171 switch (reg) {
172 case TPS51632_OFFSET_REG:
173 case TPS51632_FAULT_REG:
174 case TPS51632_IMON_REG:
175 return true;
176 default:
177 return false;
178 }
179}
180
181static bool is_read_reg(struct device *dev, unsigned int reg)
209{ 182{
210 if ((reg >= 0x8) && (reg <= 0x10)) 183 switch (reg) {
184 case 0x08 ... 0x0F:
211 return false; 185 return false;
212 return true; 186 default:
187 return true;
188 }
189}
190
191static bool is_write_reg(struct device *dev, unsigned int reg)
192{
193 switch (reg) {
194 case TPS51632_VOLTAGE_SELECT_REG:
195 case TPS51632_VOLTAGE_BASE_REG:
196 case TPS51632_VMAX_REG:
197 case TPS51632_DVFS_CONTROL_REG:
198 case TPS51632_POWER_STATE_REG:
199 case TPS51632_SLEW_REGS:
200 return true;
201 default:
202 return false;
203 }
213} 204}
214 205
215static const struct regmap_config tps51632_regmap_config = { 206static const struct regmap_config tps51632_regmap_config = {
216 .reg_bits = 8, 207 .reg_bits = 8,
217 .val_bits = 8, 208 .val_bits = 8,
218 .writeable_reg = rd_wr_reg, 209 .writeable_reg = is_write_reg,
219 .readable_reg = rd_wr_reg, 210 .readable_reg = is_read_reg,
211 .volatile_reg = is_volatile_reg,
220 .max_register = TPS51632_MAX_REG - 1, 212 .max_register = TPS51632_MAX_REG - 1,
221 .cache_type = REGCACHE_RBTREE, 213 .cache_type = REGCACHE_RBTREE,
222}; 214};
223 215
216#if defined(CONFIG_OF)
217static const struct of_device_id tps51632_of_match[] = {
218 { .compatible = "ti,tps51632",},
219 {},
220};
221MODULE_DEVICE_TABLE(of, tps51632_of_match);
222
223static struct tps51632_regulator_platform_data *
224 of_get_tps51632_platform_data(struct device *dev)
225{
226 struct tps51632_regulator_platform_data *pdata;
227 struct device_node *np = dev->of_node;
228
229 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
230 if (!pdata) {
231 dev_err(dev, "Memory alloc failed for platform data\n");
232 return NULL;
233 }
234
235 pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node);
236 if (!pdata->reg_init_data) {
237 dev_err(dev, "Not able to get OF regulator init data\n");
238 return NULL;
239 }
240
241 pdata->enable_pwm_dvfs =
242 of_property_read_bool(np, "ti,enable-pwm-dvfs");
243 pdata->dvfs_step_20mV = of_property_read_bool(np, "ti,dvfs-step-20mV");
244
245 pdata->base_voltage_uV = pdata->reg_init_data->constraints.min_uV ? :
246 TPS51632_MIN_VOLATGE;
247 pdata->max_voltage_uV = pdata->reg_init_data->constraints.max_uV ? :
248 TPS51632_MAX_VOLATGE;
249 return pdata;
250}
251#else
252static struct tps51632_regulator_platform_data *
253 of_get_tps51632_platform_data(struct device *dev)
254{
255 return NULL;
256}
257#endif
258
224static int tps51632_probe(struct i2c_client *client, 259static int tps51632_probe(struct i2c_client *client,
225 const struct i2c_device_id *id) 260 const struct i2c_device_id *id)
226{ 261{
@@ -230,7 +265,19 @@ static int tps51632_probe(struct i2c_client *client,
230 int ret; 265 int ret;
231 struct regulator_config config = { }; 266 struct regulator_config config = { };
232 267
268 if (client->dev.of_node) {
269 const struct of_device_id *match;
270 match = of_match_device(of_match_ptr(tps51632_of_match),
271 &client->dev);
272 if (!match) {
273 dev_err(&client->dev, "Error: No device match found\n");
274 return -ENODEV;
275 }
276 }
277
233 pdata = client->dev.platform_data; 278 pdata = client->dev.platform_data;
279 if (!pdata && client->dev.of_node)
280 pdata = of_get_tps51632_platform_data(&client->dev);
234 if (!pdata) { 281 if (!pdata) {
235 dev_err(&client->dev, "No Platform data\n"); 282 dev_err(&client->dev, "No Platform data\n");
236 return -EINVAL; 283 return -EINVAL;
@@ -269,6 +316,12 @@ static int tps51632_probe(struct i2c_client *client,
269 tps->desc.type = REGULATOR_VOLTAGE; 316 tps->desc.type = REGULATOR_VOLTAGE;
270 tps->desc.owner = THIS_MODULE; 317 tps->desc.owner = THIS_MODULE;
271 318
319 if (pdata->enable_pwm_dvfs)
320 tps->desc.vsel_reg = TPS51632_VOLTAGE_BASE_REG;
321 else
322 tps->desc.vsel_reg = TPS51632_VOLTAGE_SELECT_REG;
323 tps->desc.vsel_mask = TPS51632_VOUT_MASK;
324
272 tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config); 325 tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config);
273 if (IS_ERR(tps->regmap)) { 326 if (IS_ERR(tps->regmap)) {
274 ret = PTR_ERR(tps->regmap); 327 ret = PTR_ERR(tps->regmap);
@@ -319,6 +372,7 @@ static struct i2c_driver tps51632_i2c_driver = {
319 .driver = { 372 .driver = {
320 .name = "tps51632", 373 .name = "tps51632",
321 .owner = THIS_MODULE, 374 .owner = THIS_MODULE,
375 .of_match_table = of_match_ptr(tps51632_of_match),
322 }, 376 },
323 .probe = tps51632_probe, 377 .probe = tps51632_probe,
324 .remove = tps51632_remove, 378 .remove = tps51632_remove,