aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/88pm8607.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator/88pm8607.c')
-rw-r--r--drivers/regulator/88pm8607.c136
1 files changed, 120 insertions, 16 deletions
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index c3482b954cb7..1c5ab0172ea2 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -12,6 +12,8 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/err.h> 13#include <linux/err.h>
14#include <linux/i2c.h> 14#include <linux/i2c.h>
15#include <linux/of.h>
16#include <linux/regulator/of_regulator.h>
15#include <linux/platform_device.h> 17#include <linux/platform_device.h>
16#include <linux/regulator/driver.h> 18#include <linux/regulator/driver.h>
17#include <linux/regulator/machine.h> 19#include <linux/regulator/machine.h>
@@ -23,6 +25,7 @@ struct pm8607_regulator_info {
23 struct pm860x_chip *chip; 25 struct pm860x_chip *chip;
24 struct regulator_dev *regulator; 26 struct regulator_dev *regulator;
25 struct i2c_client *i2c; 27 struct i2c_client *i2c;
28 struct i2c_client *i2c_8606;
26 29
27 unsigned int *vol_table; 30 unsigned int *vol_table;
28 unsigned int *vol_suspend; 31 unsigned int *vol_suspend;
@@ -242,6 +245,35 @@ static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
242 return ret; 245 return ret;
243} 246}
244 247
248static int pm8606_preg_enable(struct regulator_dev *rdev)
249{
250 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
251
252 return pm860x_set_bits(info->i2c, rdev->desc->enable_reg,
253 1 << rdev->desc->enable_mask, 0);
254}
255
256static int pm8606_preg_disable(struct regulator_dev *rdev)
257{
258 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
259
260 return pm860x_set_bits(info->i2c, rdev->desc->enable_reg,
261 1 << rdev->desc->enable_mask,
262 1 << rdev->desc->enable_mask);
263}
264
265static int pm8606_preg_is_enabled(struct regulator_dev *rdev)
266{
267 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
268 int ret;
269
270 ret = pm860x_reg_read(info->i2c, rdev->desc->enable_reg);
271 if (ret < 0)
272 return ret;
273
274 return !((unsigned char)ret & (1 << rdev->desc->enable_mask));
275}
276
245static struct regulator_ops pm8607_regulator_ops = { 277static struct regulator_ops pm8607_regulator_ops = {
246 .list_voltage = pm8607_list_voltage, 278 .list_voltage = pm8607_list_voltage,
247 .set_voltage_sel = pm8607_set_voltage_sel, 279 .set_voltage_sel = pm8607_set_voltage_sel,
@@ -251,6 +283,25 @@ static struct regulator_ops pm8607_regulator_ops = {
251 .is_enabled = regulator_is_enabled_regmap, 283 .is_enabled = regulator_is_enabled_regmap,
252}; 284};
253 285
286static struct regulator_ops pm8606_preg_ops = {
287 .enable = pm8606_preg_enable,
288 .disable = pm8606_preg_disable,
289 .is_enabled = pm8606_preg_is_enabled,
290};
291
292#define PM8606_PREG(ereg, ebit) \
293{ \
294 .desc = { \
295 .name = "PREG", \
296 .ops = &pm8606_preg_ops, \
297 .type = REGULATOR_CURRENT, \
298 .id = PM8606_ID_PREG, \
299 .owner = THIS_MODULE, \
300 .enable_reg = PM8606_##ereg, \
301 .enable_mask = (ebit), \
302 }, \
303}
304
254#define PM8607_DVC(vreg, ureg, ubit, ereg, ebit) \ 305#define PM8607_DVC(vreg, ureg, ubit, ereg, ebit) \
255{ \ 306{ \
256 .desc = { \ 307 .desc = { \
@@ -311,6 +362,38 @@ static struct pm8607_regulator_info pm8607_regulator_info[] = {
311 PM8607_LDO(14, LDO14, 0, SUPPLIES_EN12, 6), 362 PM8607_LDO(14, LDO14, 0, SUPPLIES_EN12, 6),
312}; 363};
313 364
365static struct pm8607_regulator_info pm8606_regulator_info[] = {
366 PM8606_PREG(PREREGULATORB, 5),
367};
368
369#ifdef CONFIG_OF
370static int pm8607_regulator_dt_init(struct platform_device *pdev,
371 struct pm8607_regulator_info *info,
372 struct regulator_config *config)
373{
374 struct device_node *nproot, *np;
375 nproot = pdev->dev.parent->of_node;
376 if (!nproot)
377 return -ENODEV;
378 nproot = of_find_node_by_name(nproot, "regulators");
379 if (!nproot) {
380 dev_err(&pdev->dev, "failed to find regulators node\n");
381 return -ENODEV;
382 }
383 for_each_child_of_node(nproot, np) {
384 if (!of_node_cmp(np->name, info->desc.name)) {
385 config->init_data =
386 of_get_regulator_init_data(&pdev->dev, np);
387 config->of_node = np;
388 break;
389 }
390 }
391 return 0;
392}
393#else
394#define pm8607_regulator_dt_init(x, y, z) (-1)
395#endif
396
314static int __devinit pm8607_regulator_probe(struct platform_device *pdev) 397static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
315{ 398{
316 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); 399 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -320,22 +403,28 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
320 struct resource *res; 403 struct resource *res;
321 int i; 404 int i;
322 405
323 res = platform_get_resource(pdev, IORESOURCE_IO, 0); 406 res = platform_get_resource(pdev, IORESOURCE_REG, 0);
324 if (res == NULL) { 407 if (res) {
325 dev_err(&pdev->dev, "No I/O resource!\n"); 408 /* There're resources in 88PM8607 regulator driver */
326 return -EINVAL; 409 for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
327 } 410 info = &pm8607_regulator_info[i];
328 for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) { 411 if (info->desc.vsel_reg == res->start)
329 info = &pm8607_regulator_info[i]; 412 break;
330 if (info->desc.id == res->start) 413 }
331 break; 414 if (i == ARRAY_SIZE(pm8607_regulator_info)) {
332 } 415 dev_err(&pdev->dev, "Failed to find regulator %llu\n",
333 if (i == ARRAY_SIZE(pm8607_regulator_info)) { 416 (unsigned long long)res->start);
334 dev_err(&pdev->dev, "Failed to find regulator %llu\n", 417 return -EINVAL;
335 (unsigned long long)res->start); 418 }
336 return -EINVAL; 419 } else {
420 /* There's no resource in 88PM8606 PREG regulator driver */
421 info = &pm8606_regulator_info[0];
422 /* i is used to check regulator ID */
423 i = -1;
337 } 424 }
338 info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; 425 info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
426 info->i2c_8606 = (chip->id == CHIP_PM8607) ? chip->companion :
427 chip->client;
339 info->chip = chip; 428 info->chip = chip;
340 429
341 /* check DVC ramp slope double */ 430 /* check DVC ramp slope double */
@@ -343,15 +432,17 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
343 info->slope_double = 1; 432 info->slope_double = 1;
344 433
345 config.dev = &pdev->dev; 434 config.dev = &pdev->dev;
346 config.init_data = pdata;
347 config.driver_data = info; 435 config.driver_data = info;
348 436
437 if (pm8607_regulator_dt_init(pdev, info, &config))
438 if (pdata)
439 config.init_data = pdata;
440
349 if (chip->id == CHIP_PM8607) 441 if (chip->id == CHIP_PM8607)
350 config.regmap = chip->regmap; 442 config.regmap = chip->regmap;
351 else 443 else
352 config.regmap = chip->regmap_companion; 444 config.regmap = chip->regmap_companion;
353 445
354 /* replace driver_data with info */
355 info->regulator = regulator_register(&info->desc, &config); 446 info->regulator = regulator_register(&info->desc, &config);
356 if (IS_ERR(info->regulator)) { 447 if (IS_ERR(info->regulator)) {
357 dev_err(&pdev->dev, "failed to register regulator %s\n", 448 dev_err(&pdev->dev, "failed to register regulator %s\n",
@@ -372,6 +463,18 @@ static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
372 return 0; 463 return 0;
373} 464}
374 465
466static struct platform_device_id pm8607_regulator_driver_ids[] = {
467 {
468 .name = "88pm860x-regulator",
469 .driver_data = 0,
470 }, {
471 .name = "88pm860x-preg",
472 .driver_data = 0,
473 },
474 { },
475};
476MODULE_DEVICE_TABLE(platform, pm8607_regulator_driver_ids);
477
375static struct platform_driver pm8607_regulator_driver = { 478static struct platform_driver pm8607_regulator_driver = {
376 .driver = { 479 .driver = {
377 .name = "88pm860x-regulator", 480 .name = "88pm860x-regulator",
@@ -379,6 +482,7 @@ static struct platform_driver pm8607_regulator_driver = {
379 }, 482 },
380 .probe = pm8607_regulator_probe, 483 .probe = pm8607_regulator_probe,
381 .remove = __devexit_p(pm8607_regulator_remove), 484 .remove = __devexit_p(pm8607_regulator_remove),
485 .id_table = pm8607_regulator_driver_ids,
382}; 486};
383 487
384static int __init pm8607_regulator_init(void) 488static int __init pm8607_regulator_init(void)