diff options
author | Todd Fischer <todd.fischer@ridgerun.com> | 2010-04-08 03:04:55 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2010-05-27 19:37:38 -0400 |
commit | 31dd6a2672e337f5de188df3e5169ee732798236 (patch) | |
tree | d0a12a6622d9a32a107267a4479f6e12a495dbd3 /drivers/regulator | |
parent | 4ce5ba5ba2dfc8186bf31fe7f2d23ff6b5384124 (diff) |
mfd: Add TPS6507x support
TPS6507x are multi function (PM, touchscreen) chipsets from TI.
This commit also changes the corresponding regulator driver from being
standalone to an MFD subdevice.
Signed-off-by: Todd Fischer <todd.fischer@ridgerun.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/tps6507x-regulator.c | 153 |
1 files changed, 74 insertions, 79 deletions
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index ea44741fcd47..14b4576281c5 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/regulator/driver.h> | 23 | #include <linux/regulator/driver.h> |
24 | #include <linux/regulator/machine.h> | 24 | #include <linux/regulator/machine.h> |
25 | #include <linux/i2c.h> | ||
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
28 | #include <linux/mfd/tps6507x.h> | 27 | #include <linux/mfd/tps6507x.h> |
@@ -104,22 +103,67 @@ struct tps_info { | |||
104 | const u16 *table; | 103 | const u16 *table; |
105 | }; | 104 | }; |
106 | 105 | ||
106 | static const struct tps_info tps6507x_pmic_regs[] = { | ||
107 | { | ||
108 | .name = "VDCDC1", | ||
109 | .min_uV = 725000, | ||
110 | .max_uV = 3300000, | ||
111 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
112 | .table = VDCDCx_VSEL_table, | ||
113 | }, | ||
114 | { | ||
115 | .name = "VDCDC2", | ||
116 | .min_uV = 725000, | ||
117 | .max_uV = 3300000, | ||
118 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
119 | .table = VDCDCx_VSEL_table, | ||
120 | }, | ||
121 | { | ||
122 | .name = "VDCDC3", | ||
123 | .min_uV = 725000, | ||
124 | .max_uV = 3300000, | ||
125 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
126 | .table = VDCDCx_VSEL_table, | ||
127 | }, | ||
128 | { | ||
129 | .name = "LDO1", | ||
130 | .min_uV = 1000000, | ||
131 | .max_uV = 3300000, | ||
132 | .table_len = ARRAY_SIZE(LDO1_VSEL_table), | ||
133 | .table = LDO1_VSEL_table, | ||
134 | }, | ||
135 | { | ||
136 | .name = "LDO2", | ||
137 | .min_uV = 725000, | ||
138 | .max_uV = 3300000, | ||
139 | .table_len = ARRAY_SIZE(LDO2_VSEL_table), | ||
140 | .table = LDO2_VSEL_table, | ||
141 | }, | ||
142 | }; | ||
143 | |||
107 | struct tps6507x_pmic { | 144 | struct tps6507x_pmic { |
108 | struct regulator_desc desc[TPS6507X_NUM_REGULATOR]; | 145 | struct regulator_desc desc[TPS6507X_NUM_REGULATOR]; |
109 | struct i2c_client *client; | 146 | struct tps6507x_dev *mfd; |
110 | struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR]; | 147 | struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR]; |
111 | const struct tps_info *info[TPS6507X_NUM_REGULATOR]; | 148 | const struct tps_info *info[TPS6507X_NUM_REGULATOR]; |
112 | struct mutex io_lock; | 149 | struct mutex io_lock; |
113 | }; | 150 | }; |
114 | |||
115 | static inline int tps6507x_pmic_read(struct tps6507x_pmic *tps, u8 reg) | 151 | static inline int tps6507x_pmic_read(struct tps6507x_pmic *tps, u8 reg) |
116 | { | 152 | { |
117 | return i2c_smbus_read_byte_data(tps->client, reg); | 153 | u8 val; |
154 | int err; | ||
155 | |||
156 | err = tps->mfd->read_dev(tps->mfd, reg, 1, &val); | ||
157 | |||
158 | if (err) | ||
159 | return err; | ||
160 | |||
161 | return val; | ||
118 | } | 162 | } |
119 | 163 | ||
120 | static inline int tps6507x_pmic_write(struct tps6507x_pmic *tps, u8 reg, u8 val) | 164 | static inline int tps6507x_pmic_write(struct tps6507x_pmic *tps, u8 reg, u8 val) |
121 | { | 165 | { |
122 | return i2c_smbus_write_byte_data(tps->client, reg, val); | 166 | return tps->mfd->write_dev(tps->mfd, reg, 1, &val); |
123 | } | 167 | } |
124 | 168 | ||
125 | static int tps6507x_pmic_set_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask) | 169 | static int tps6507x_pmic_set_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask) |
@@ -130,7 +174,7 @@ static int tps6507x_pmic_set_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask) | |||
130 | 174 | ||
131 | data = tps6507x_pmic_read(tps, reg); | 175 | data = tps6507x_pmic_read(tps, reg); |
132 | if (data < 0) { | 176 | if (data < 0) { |
133 | dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); | 177 | dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg); |
134 | err = data; | 178 | err = data; |
135 | goto out; | 179 | goto out; |
136 | } | 180 | } |
@@ -138,7 +182,7 @@ static int tps6507x_pmic_set_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask) | |||
138 | data |= mask; | 182 | data |= mask; |
139 | err = tps6507x_pmic_write(tps, reg, data); | 183 | err = tps6507x_pmic_write(tps, reg, data); |
140 | if (err) | 184 | if (err) |
141 | dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); | 185 | dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg); |
142 | 186 | ||
143 | out: | 187 | out: |
144 | mutex_unlock(&tps->io_lock); | 188 | mutex_unlock(&tps->io_lock); |
@@ -153,7 +197,7 @@ static int tps6507x_pmic_clear_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask) | |||
153 | 197 | ||
154 | data = tps6507x_pmic_read(tps, reg); | 198 | data = tps6507x_pmic_read(tps, reg); |
155 | if (data < 0) { | 199 | if (data < 0) { |
156 | dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); | 200 | dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg); |
157 | err = data; | 201 | err = data; |
158 | goto out; | 202 | goto out; |
159 | } | 203 | } |
@@ -161,7 +205,7 @@ static int tps6507x_pmic_clear_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask) | |||
161 | data &= ~mask; | 205 | data &= ~mask; |
162 | err = tps6507x_pmic_write(tps, reg, data); | 206 | err = tps6507x_pmic_write(tps, reg, data); |
163 | if (err) | 207 | if (err) |
164 | dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); | 208 | dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg); |
165 | 209 | ||
166 | out: | 210 | out: |
167 | mutex_unlock(&tps->io_lock); | 211 | mutex_unlock(&tps->io_lock); |
@@ -176,7 +220,7 @@ static int tps6507x_pmic_reg_read(struct tps6507x_pmic *tps, u8 reg) | |||
176 | 220 | ||
177 | data = tps6507x_pmic_read(tps, reg); | 221 | data = tps6507x_pmic_read(tps, reg); |
178 | if (data < 0) | 222 | if (data < 0) |
179 | dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); | 223 | dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg); |
180 | 224 | ||
181 | mutex_unlock(&tps->io_lock); | 225 | mutex_unlock(&tps->io_lock); |
182 | return data; | 226 | return data; |
@@ -190,7 +234,7 @@ static int tps6507x_pmic_reg_write(struct tps6507x_pmic *tps, u8 reg, u8 val) | |||
190 | 234 | ||
191 | err = tps6507x_pmic_write(tps, reg, val); | 235 | err = tps6507x_pmic_write(tps, reg, val); |
192 | if (err < 0) | 236 | if (err < 0) |
193 | dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); | 237 | dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg); |
194 | 238 | ||
195 | mutex_unlock(&tps->io_lock); | 239 | mutex_unlock(&tps->io_lock); |
196 | return err; | 240 | return err; |
@@ -483,11 +527,12 @@ static struct regulator_ops tps6507x_pmic_ldo_ops = { | |||
483 | .list_voltage = tps6507x_pmic_ldo_list_voltage, | 527 | .list_voltage = tps6507x_pmic_ldo_list_voltage, |
484 | }; | 528 | }; |
485 | 529 | ||
486 | static int __devinit tps6507x_pmic_probe(struct i2c_client *client, | 530 | static __devinit |
487 | const struct i2c_device_id *id) | 531 | int tps6507x_pmic_probe(struct platform_device *pdev) |
488 | { | 532 | { |
533 | struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); | ||
489 | static int desc_id; | 534 | static int desc_id; |
490 | const struct tps_info *info = (void *)id->driver_data; | 535 | const struct tps_info *info = &tps6507x_pmic_regs[0]; |
491 | struct regulator_init_data *init_data; | 536 | struct regulator_init_data *init_data; |
492 | struct regulator_dev *rdev; | 537 | struct regulator_dev *rdev; |
493 | struct tps6507x_pmic *tps; | 538 | struct tps6507x_pmic *tps; |
@@ -495,16 +540,12 @@ static int __devinit tps6507x_pmic_probe(struct i2c_client *client, | |||
495 | int i; | 540 | int i; |
496 | int error; | 541 | int error; |
497 | 542 | ||
498 | if (!i2c_check_functionality(client->adapter, | ||
499 | I2C_FUNC_SMBUS_BYTE_DATA)) | ||
500 | return -EIO; | ||
501 | |||
502 | /** | 543 | /** |
503 | * tps_board points to pmic related constants | 544 | * tps_board points to pmic related constants |
504 | * coming from the board-evm file. | 545 | * coming from the board-evm file. |
505 | */ | 546 | */ |
506 | 547 | ||
507 | tps_board = dev_get_platdata(&client->dev); | 548 | tps_board = dev_get_platdata(tps6507x_dev->dev); |
508 | if (!tps_board) | 549 | if (!tps_board) |
509 | return -EINVAL; | 550 | return -EINVAL; |
510 | 551 | ||
@@ -523,7 +564,7 @@ static int __devinit tps6507x_pmic_probe(struct i2c_client *client, | |||
523 | mutex_init(&tps->io_lock); | 564 | mutex_init(&tps->io_lock); |
524 | 565 | ||
525 | /* common for all regulators */ | 566 | /* common for all regulators */ |
526 | tps->client = client; | 567 | tps->mfd = tps6507x_dev; |
527 | 568 | ||
528 | for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) { | 569 | for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) { |
529 | /* Register the regulators */ | 570 | /* Register the regulators */ |
@@ -537,10 +578,11 @@ static int __devinit tps6507x_pmic_probe(struct i2c_client *client, | |||
537 | tps->desc[i].owner = THIS_MODULE; | 578 | tps->desc[i].owner = THIS_MODULE; |
538 | 579 | ||
539 | rdev = regulator_register(&tps->desc[i], | 580 | rdev = regulator_register(&tps->desc[i], |
540 | &client->dev, init_data, tps); | 581 | tps6507x_dev->dev, init_data, tps); |
541 | if (IS_ERR(rdev)) { | 582 | if (IS_ERR(rdev)) { |
542 | dev_err(&client->dev, "failed to register %s\n", | 583 | dev_err(tps6507x_dev->dev, |
543 | id->name); | 584 | "failed to register %s regulator\n", |
585 | pdev->name); | ||
544 | error = PTR_ERR(rdev); | 586 | error = PTR_ERR(rdev); |
545 | goto fail; | 587 | goto fail; |
546 | } | 588 | } |
@@ -549,7 +591,7 @@ static int __devinit tps6507x_pmic_probe(struct i2c_client *client, | |||
549 | tps->rdev[i] = rdev; | 591 | tps->rdev[i] = rdev; |
550 | } | 592 | } |
551 | 593 | ||
552 | i2c_set_clientdata(client, tps); | 594 | tps6507x_dev->pmic = tps; |
553 | 595 | ||
554 | return 0; | 596 | return 0; |
555 | 597 | ||
@@ -567,14 +609,12 @@ fail: | |||
567 | * | 609 | * |
568 | * Unregister TPS driver as an i2c client device driver | 610 | * Unregister TPS driver as an i2c client device driver |
569 | */ | 611 | */ |
570 | static int __devexit tps6507x_pmic_remove(struct i2c_client *client) | 612 | static int __devexit tps6507x_pmic_remove(struct platform_device *pdev) |
571 | { | 613 | { |
572 | struct tps6507x_pmic *tps = i2c_get_clientdata(client); | 614 | struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); |
615 | struct tps6507x_pmic *tps = tps6507x_dev->pmic; | ||
573 | int i; | 616 | int i; |
574 | 617 | ||
575 | /* clear the client data in i2c */ | ||
576 | i2c_set_clientdata(client, NULL); | ||
577 | |||
578 | for (i = 0; i < TPS6507X_NUM_REGULATOR; i++) | 618 | for (i = 0; i < TPS6507X_NUM_REGULATOR; i++) |
579 | regulator_unregister(tps->rdev[i]); | 619 | regulator_unregister(tps->rdev[i]); |
580 | 620 | ||
@@ -583,59 +623,13 @@ static int __devexit tps6507x_pmic_remove(struct i2c_client *client) | |||
583 | return 0; | 623 | return 0; |
584 | } | 624 | } |
585 | 625 | ||
586 | static const struct tps_info tps6507x_pmic_regs[] = { | 626 | static struct platform_driver tps6507x_pmic_driver = { |
587 | { | ||
588 | .name = "VDCDC1", | ||
589 | .min_uV = 725000, | ||
590 | .max_uV = 3300000, | ||
591 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
592 | .table = VDCDCx_VSEL_table, | ||
593 | }, | ||
594 | { | ||
595 | .name = "VDCDC2", | ||
596 | .min_uV = 725000, | ||
597 | .max_uV = 3300000, | ||
598 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
599 | .table = VDCDCx_VSEL_table, | ||
600 | }, | ||
601 | { | ||
602 | .name = "VDCDC3", | ||
603 | .min_uV = 725000, | ||
604 | .max_uV = 3300000, | ||
605 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
606 | .table = VDCDCx_VSEL_table, | ||
607 | }, | ||
608 | { | ||
609 | .name = "LDO1", | ||
610 | .min_uV = 1000000, | ||
611 | .max_uV = 3300000, | ||
612 | .table_len = ARRAY_SIZE(LDO1_VSEL_table), | ||
613 | .table = LDO1_VSEL_table, | ||
614 | }, | ||
615 | { | ||
616 | .name = "LDO2", | ||
617 | .min_uV = 725000, | ||
618 | .max_uV = 3300000, | ||
619 | .table_len = ARRAY_SIZE(LDO2_VSEL_table), | ||
620 | .table = LDO2_VSEL_table, | ||
621 | }, | ||
622 | }; | ||
623 | |||
624 | static const struct i2c_device_id tps6507x_pmic_id[] = { | ||
625 | {.name = "tps6507x", | ||
626 | .driver_data = (unsigned long) tps6507x_pmic_regs,}, | ||
627 | { }, | ||
628 | }; | ||
629 | MODULE_DEVICE_TABLE(i2c, tps6507x_pmic_id); | ||
630 | |||
631 | static struct i2c_driver tps6507x_i2c_driver = { | ||
632 | .driver = { | 627 | .driver = { |
633 | .name = "tps6507x", | 628 | .name = "tps6507x-pmic", |
634 | .owner = THIS_MODULE, | 629 | .owner = THIS_MODULE, |
635 | }, | 630 | }, |
636 | .probe = tps6507x_pmic_probe, | 631 | .probe = tps6507x_pmic_probe, |
637 | .remove = __devexit_p(tps6507x_pmic_remove), | 632 | .remove = __devexit_p(tps6507x_pmic_remove), |
638 | .id_table = tps6507x_pmic_id, | ||
639 | }; | 633 | }; |
640 | 634 | ||
641 | /** | 635 | /** |
@@ -645,7 +639,7 @@ static struct i2c_driver tps6507x_i2c_driver = { | |||
645 | */ | 639 | */ |
646 | static int __init tps6507x_pmic_init(void) | 640 | static int __init tps6507x_pmic_init(void) |
647 | { | 641 | { |
648 | return i2c_add_driver(&tps6507x_i2c_driver); | 642 | return platform_driver_register(&tps6507x_pmic_driver); |
649 | } | 643 | } |
650 | subsys_initcall(tps6507x_pmic_init); | 644 | subsys_initcall(tps6507x_pmic_init); |
651 | 645 | ||
@@ -656,10 +650,11 @@ subsys_initcall(tps6507x_pmic_init); | |||
656 | */ | 650 | */ |
657 | static void __exit tps6507x_pmic_cleanup(void) | 651 | static void __exit tps6507x_pmic_cleanup(void) |
658 | { | 652 | { |
659 | i2c_del_driver(&tps6507x_i2c_driver); | 653 | platform_driver_unregister(&tps6507x_pmic_driver); |
660 | } | 654 | } |
661 | module_exit(tps6507x_pmic_cleanup); | 655 | module_exit(tps6507x_pmic_cleanup); |
662 | 656 | ||
663 | MODULE_AUTHOR("Texas Instruments"); | 657 | MODULE_AUTHOR("Texas Instruments"); |
664 | MODULE_DESCRIPTION("TPS6507x voltage regulator driver"); | 658 | MODULE_DESCRIPTION("TPS6507x voltage regulator driver"); |
665 | MODULE_LICENSE("GPL v2"); | 659 | MODULE_LICENSE("GPL v2"); |
660 | MODULE_ALIAS("platform:tps6507x-pmic"); | ||