aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/regulator/tps65023-regulator.c107
1 files changed, 21 insertions, 86 deletions
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 43e4902d7af..08b3b41270a 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -72,7 +72,7 @@
72 72
73/* LDO_CTRL bitfields */ 73/* LDO_CTRL bitfields */
74#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4) 74#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4)
75#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0xF0 >> ((ldo_id)*4)) 75#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0x0F << ((ldo_id)*4))
76 76
77/* Number of step-down converters available */ 77/* Number of step-down converters available */
78#define TPS65023_NUM_DCDC 3 78#define TPS65023_NUM_DCDC 3
@@ -261,50 +261,28 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
261 return tps->info[dcdc]->min_uV; 261 return tps->info[dcdc]->min_uV;
262} 262}
263 263
264static int tps65023_dcdc_set_voltage(struct regulator_dev *dev, 264static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev,
265 int min_uV, int max_uV, 265 unsigned selector)
266 unsigned *selector)
267{ 266{
268 struct tps_pmic *tps = rdev_get_drvdata(dev); 267 struct tps_pmic *tps = rdev_get_drvdata(dev);
269 int dcdc = rdev_get_id(dev); 268 int dcdc = rdev_get_id(dev);
270 int vsel;
271 int ret; 269 int ret;
272 270
273 if (dcdc != tps->core_regulator) 271 if (dcdc != tps->core_regulator)
274 return -EINVAL; 272 return -EINVAL;
275 if (min_uV < tps->info[dcdc]->min_uV
276 || min_uV > tps->info[dcdc]->max_uV)
277 return -EINVAL;
278 if (max_uV < tps->info[dcdc]->min_uV
279 || max_uV > tps->info[dcdc]->max_uV)
280 return -EINVAL;
281
282 for (vsel = 0; vsel < tps->info[dcdc]->table_len; vsel++) {
283 int mV = tps->info[dcdc]->table[vsel];
284 int uV = mV * 1000;
285
286 /* Break at the first in-range value */
287 if (min_uV <= uV && uV <= max_uV)
288 break;
289 }
290 273
291 *selector = vsel; 274 ret = regmap_write(tps->regmap, TPS65023_REG_DEF_CORE, selector);
292 275 if (ret)
293 if (vsel == tps->info[dcdc]->table_len) 276 goto out;
294 goto failed;
295
296 ret = regmap_write(tps->regmap, TPS65023_REG_DEF_CORE, vsel);
297 277
298 /* Tell the chip that we have changed the value in DEFCORE 278 /* Tell the chip that we have changed the value in DEFCORE
299 * and its time to update the core voltage 279 * and its time to update the core voltage
300 */ 280 */
301 regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2, 281 ret = regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2,
302 TPS65023_REG_CTRL2_GO, TPS65023_REG_CTRL2_GO); 282 TPS65023_REG_CTRL2_GO, TPS65023_REG_CTRL2_GO);
303 283
284out:
304 return ret; 285 return ret;
305
306failed:
307 return -EINVAL;
308} 286}
309 287
310static int tps65023_ldo_get_voltage(struct regulator_dev *dev) 288static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
@@ -325,42 +303,15 @@ static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
325 return tps->info[ldo]->table[data] * 1000; 303 return tps->info[ldo]->table[data] * 1000;
326} 304}
327 305
328static int tps65023_ldo_set_voltage(struct regulator_dev *dev, 306static int tps65023_ldo_set_voltage_sel(struct regulator_dev *dev,
329 int min_uV, int max_uV, unsigned *selector) 307 unsigned selector)
330{ 308{
331 struct tps_pmic *tps = rdev_get_drvdata(dev); 309 struct tps_pmic *tps = rdev_get_drvdata(dev);
332 int data, vsel, ldo = rdev_get_id(dev); 310 int ldo_index = rdev_get_id(dev) - TPS65023_LDO_1;
333 int ret;
334
335 if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
336 return -EINVAL;
337
338 if (min_uV < tps->info[ldo]->min_uV || min_uV > tps->info[ldo]->max_uV)
339 return -EINVAL;
340 if (max_uV < tps->info[ldo]->min_uV || max_uV > tps->info[ldo]->max_uV)
341 return -EINVAL;
342 311
343 for (vsel = 0; vsel < tps->info[ldo]->table_len; vsel++) { 312 return regmap_update_bits(tps->regmap, TPS65023_REG_LDO_CTRL,
344 int mV = tps->info[ldo]->table[vsel]; 313 TPS65023_LDO_CTRL_LDOx_MASK(ldo_index),
345 int uV = mV * 1000; 314 selector << TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_index));
346
347 /* Break at the first in-range value */
348 if (min_uV <= uV && uV <= max_uV)
349 break;
350 }
351
352 if (vsel == tps->info[ldo]->table_len)
353 return -EINVAL;
354
355 *selector = vsel;
356
357 ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data);
358 if (ret != 0)
359 return ret;
360
361 data &= TPS65023_LDO_CTRL_LDOx_MASK(ldo - TPS65023_LDO_1);
362 data |= (vsel << (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1)));
363 return regmap_write(tps->regmap, TPS65023_REG_LDO_CTRL, data);
364} 315}
365 316
366static int tps65023_dcdc_list_voltage(struct regulator_dev *dev, 317static int tps65023_dcdc_list_voltage(struct regulator_dev *dev,
@@ -402,7 +353,7 @@ static struct regulator_ops tps65023_dcdc_ops = {
402 .enable = tps65023_dcdc_enable, 353 .enable = tps65023_dcdc_enable,
403 .disable = tps65023_dcdc_disable, 354 .disable = tps65023_dcdc_disable,
404 .get_voltage = tps65023_dcdc_get_voltage, 355 .get_voltage = tps65023_dcdc_get_voltage,
405 .set_voltage = tps65023_dcdc_set_voltage, 356 .set_voltage_sel = tps65023_dcdc_set_voltage_sel,
406 .list_voltage = tps65023_dcdc_list_voltage, 357 .list_voltage = tps65023_dcdc_list_voltage,
407}; 358};
408 359
@@ -412,7 +363,7 @@ static struct regulator_ops tps65023_ldo_ops = {
412 .enable = tps65023_ldo_enable, 363 .enable = tps65023_ldo_enable,
413 .disable = tps65023_ldo_disable, 364 .disable = tps65023_ldo_disable,
414 .get_voltage = tps65023_ldo_get_voltage, 365 .get_voltage = tps65023_ldo_get_voltage,
415 .set_voltage = tps65023_ldo_set_voltage, 366 .set_voltage_sel = tps65023_ldo_set_voltage_sel,
416 .list_voltage = tps65023_ldo_list_voltage, 367 .list_voltage = tps65023_ldo_list_voltage,
417}; 368};
418 369
@@ -503,12 +454,6 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
503 return error; 454 return error;
504} 455}
505 456
506/**
507 * tps_65023_remove - TPS65023 driver i2c remove handler
508 * @client: i2c driver client device structure
509 *
510 * Unregister TPS driver as an i2c client device driver
511 */
512static int __devexit tps_65023_remove(struct i2c_client *client) 457static int __devexit tps_65023_remove(struct i2c_client *client)
513{ 458{
514 struct tps_pmic *tps = i2c_get_clientdata(client); 459 struct tps_pmic *tps = i2c_get_clientdata(client);
@@ -638,13 +583,13 @@ static struct tps_driver_data tps65020_drv_data = {
638}; 583};
639 584
640static struct tps_driver_data tps65021_drv_data = { 585static struct tps_driver_data tps65021_drv_data = {
641 .info = tps65021_regs, 586 .info = tps65021_regs,
642 .core_regulator = TPS65023_DCDC_3, 587 .core_regulator = TPS65023_DCDC_3,
643}; 588};
644 589
645static struct tps_driver_data tps65023_drv_data = { 590static struct tps_driver_data tps65023_drv_data = {
646 .info = tps65023_regs, 591 .info = tps65023_regs,
647 .core_regulator = TPS65023_DCDC_1, 592 .core_regulator = TPS65023_DCDC_1,
648}; 593};
649 594
650static const struct i2c_device_id tps_65023_id[] = { 595static const struct i2c_device_id tps_65023_id[] = {
@@ -669,22 +614,12 @@ static struct i2c_driver tps_65023_i2c_driver = {
669 .id_table = tps_65023_id, 614 .id_table = tps_65023_id,
670}; 615};
671 616
672/**
673 * tps_65023_init
674 *
675 * Module init function
676 */
677static int __init tps_65023_init(void) 617static int __init tps_65023_init(void)
678{ 618{
679 return i2c_add_driver(&tps_65023_i2c_driver); 619 return i2c_add_driver(&tps_65023_i2c_driver);
680} 620}
681subsys_initcall(tps_65023_init); 621subsys_initcall(tps_65023_init);
682 622
683/**
684 * tps_65023_cleanup
685 *
686 * Module exit function
687 */
688static void __exit tps_65023_cleanup(void) 623static void __exit tps_65023_cleanup(void)
689{ 624{
690 i2c_del_driver(&tps_65023_i2c_driver); 625 i2c_del_driver(&tps_65023_i2c_driver);