aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-02-19 07:43:09 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-02-19 07:43:09 -0500
commitb67a2ecb540b3ac08c962742d2142104390ff60c (patch)
tree8568617fa2b18d1181acc14c2793fa57827f4bb1 /drivers/regulator
parent178a097d5e6ae57d67310ff18bef0afb5589f2dd (diff)
parentd94d9aca5bccba682b5a764c962bcdde7c4bf95a (diff)
Merge remote-tracking branch 'regulator/topic/tps51632' into regulator-next
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/tps51632-regulator.c152
1 files changed, 103 insertions, 49 deletions
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,