diff options
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/Kconfig | 14 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 2 | ||||
-rw-r--r-- | drivers/regulator/aat2870-regulator.c | 232 | ||||
-rw-r--r-- | drivers/regulator/tps65023-regulator.c | 97 | ||||
-rw-r--r-- | drivers/regulator/tps65912-regulator.c | 800 |
5 files changed, 1075 insertions, 70 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index d7ed20f293d7..c7fd2c0e3f2b 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -235,6 +235,7 @@ config REGULATOR_TPS6105X | |||
235 | config REGULATOR_TPS65023 | 235 | config REGULATOR_TPS65023 |
236 | tristate "TI TPS65023 Power regulators" | 236 | tristate "TI TPS65023 Power regulators" |
237 | depends on I2C | 237 | depends on I2C |
238 | select REGMAP_I2C | ||
238 | help | 239 | help |
239 | This driver supports TPS65023 voltage regulator chips. TPS65023 provides | 240 | This driver supports TPS65023 voltage regulator chips. TPS65023 provides |
240 | three step-down converters and two general-purpose LDO voltage regulators. | 241 | three step-down converters and two general-purpose LDO voltage regulators. |
@@ -248,6 +249,12 @@ config REGULATOR_TPS6507X | |||
248 | three step-down converters and two general-purpose LDO voltage regulators. | 249 | three step-down converters and two general-purpose LDO voltage regulators. |
249 | It supports TI's software based Class-2 SmartReflex implementation. | 250 | It supports TI's software based Class-2 SmartReflex implementation. |
250 | 251 | ||
252 | config REGULATOR_TPS65912 | ||
253 | tristate "TI TPS65912 Power regulator" | ||
254 | depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI) | ||
255 | help | ||
256 | This driver supports TPS65912 voltage regulator chip. | ||
257 | |||
251 | config REGULATOR_88PM8607 | 258 | config REGULATOR_88PM8607 |
252 | bool "Marvell 88PM8607 Power regulators" | 259 | bool "Marvell 88PM8607 Power regulators" |
253 | depends on MFD_88PM860X=y | 260 | depends on MFD_88PM860X=y |
@@ -303,5 +310,12 @@ config REGULATOR_TPS65910 | |||
303 | help | 310 | help |
304 | This driver supports TPS65910 voltage regulator chips. | 311 | This driver supports TPS65910 voltage regulator chips. |
305 | 312 | ||
313 | config REGULATOR_AAT2870 | ||
314 | tristate "AnalogicTech AAT2870 Regulators" | ||
315 | depends on MFD_AAT2870_CORE | ||
316 | help | ||
317 | If you have a AnalogicTech AAT2870 say Y to enable the | ||
318 | regulator driver. | ||
319 | |||
306 | endif | 320 | endif |
307 | 321 | ||
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 3932d2ec38f3..040d5aa63535 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -38,10 +38,12 @@ obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o | |||
38 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o | 38 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o |
39 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o | 39 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o |
40 | obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o | 40 | obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o |
41 | obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o | ||
41 | obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o | 42 | obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o |
42 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o | 43 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o |
43 | obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o | 44 | obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o |
44 | obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o | 45 | obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o |
45 | obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o | 46 | obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o |
47 | obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o | ||
46 | 48 | ||
47 | ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG | 49 | ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG |
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c new file mode 100644 index 000000000000..cd4104542f0d --- /dev/null +++ b/drivers/regulator/aat2870-regulator.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * linux/drivers/regulator/aat2870-regulator.c | ||
3 | * | ||
4 | * Copyright (c) 2011, NVIDIA Corporation. | ||
5 | * Author: Jin Park <jinyoungp@nvidia.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
19 | * 02110-1301 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/regulator/driver.h> | ||
29 | #include <linux/regulator/machine.h> | ||
30 | #include <linux/mfd/aat2870.h> | ||
31 | |||
32 | struct aat2870_regulator { | ||
33 | struct platform_device *pdev; | ||
34 | struct regulator_desc desc; | ||
35 | |||
36 | const int *voltages; /* uV */ | ||
37 | |||
38 | int min_uV; | ||
39 | int max_uV; | ||
40 | |||
41 | u8 enable_addr; | ||
42 | u8 enable_shift; | ||
43 | u8 enable_mask; | ||
44 | |||
45 | u8 voltage_addr; | ||
46 | u8 voltage_shift; | ||
47 | u8 voltage_mask; | ||
48 | }; | ||
49 | |||
50 | static int aat2870_ldo_list_voltage(struct regulator_dev *rdev, | ||
51 | unsigned selector) | ||
52 | { | ||
53 | struct aat2870_regulator *ri = rdev_get_drvdata(rdev); | ||
54 | |||
55 | return ri->voltages[selector]; | ||
56 | } | ||
57 | |||
58 | static int aat2870_ldo_set_voltage_sel(struct regulator_dev *rdev, | ||
59 | unsigned selector) | ||
60 | { | ||
61 | struct aat2870_regulator *ri = rdev_get_drvdata(rdev); | ||
62 | struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent); | ||
63 | |||
64 | return aat2870->update(aat2870, ri->voltage_addr, ri->voltage_mask, | ||
65 | (selector << ri->voltage_shift) & ri->voltage_mask); | ||
66 | } | ||
67 | |||
68 | static int aat2870_ldo_get_voltage_sel(struct regulator_dev *rdev) | ||
69 | { | ||
70 | struct aat2870_regulator *ri = rdev_get_drvdata(rdev); | ||
71 | struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent); | ||
72 | u8 val; | ||
73 | int ret; | ||
74 | |||
75 | ret = aat2870->read(aat2870, ri->voltage_addr, &val); | ||
76 | if (ret) | ||
77 | return ret; | ||
78 | |||
79 | return (val & ri->voltage_mask) >> ri->voltage_shift; | ||
80 | } | ||
81 | |||
82 | static int aat2870_ldo_enable(struct regulator_dev *rdev) | ||
83 | { | ||
84 | struct aat2870_regulator *ri = rdev_get_drvdata(rdev); | ||
85 | struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent); | ||
86 | |||
87 | return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask, | ||
88 | ri->enable_mask); | ||
89 | } | ||
90 | |||
91 | static int aat2870_ldo_disable(struct regulator_dev *rdev) | ||
92 | { | ||
93 | struct aat2870_regulator *ri = rdev_get_drvdata(rdev); | ||
94 | struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent); | ||
95 | |||
96 | return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask, 0); | ||
97 | } | ||
98 | |||
99 | static int aat2870_ldo_is_enabled(struct regulator_dev *rdev) | ||
100 | { | ||
101 | struct aat2870_regulator *ri = rdev_get_drvdata(rdev); | ||
102 | struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent); | ||
103 | u8 val; | ||
104 | int ret; | ||
105 | |||
106 | ret = aat2870->read(aat2870, ri->enable_addr, &val); | ||
107 | if (ret) | ||
108 | return ret; | ||
109 | |||
110 | return val & ri->enable_mask ? 1 : 0; | ||
111 | } | ||
112 | |||
113 | static struct regulator_ops aat2870_ldo_ops = { | ||
114 | .list_voltage = aat2870_ldo_list_voltage, | ||
115 | .set_voltage_sel = aat2870_ldo_set_voltage_sel, | ||
116 | .get_voltage_sel = aat2870_ldo_get_voltage_sel, | ||
117 | .enable = aat2870_ldo_enable, | ||
118 | .disable = aat2870_ldo_disable, | ||
119 | .is_enabled = aat2870_ldo_is_enabled, | ||
120 | }; | ||
121 | |||
122 | static const int aat2870_ldo_voltages[] = { | ||
123 | 1200000, 1300000, 1500000, 1600000, | ||
124 | 1800000, 2000000, 2200000, 2500000, | ||
125 | 2600000, 2700000, 2800000, 2900000, | ||
126 | 3000000, 3100000, 3200000, 3300000, | ||
127 | }; | ||
128 | |||
129 | #define AAT2870_LDO(ids) \ | ||
130 | { \ | ||
131 | .desc = { \ | ||
132 | .name = #ids, \ | ||
133 | .id = AAT2870_ID_##ids, \ | ||
134 | .n_voltages = ARRAY_SIZE(aat2870_ldo_voltages), \ | ||
135 | .ops = &aat2870_ldo_ops, \ | ||
136 | .type = REGULATOR_VOLTAGE, \ | ||
137 | .owner = THIS_MODULE, \ | ||
138 | }, \ | ||
139 | .voltages = aat2870_ldo_voltages, \ | ||
140 | .min_uV = 1200000, \ | ||
141 | .max_uV = 3300000, \ | ||
142 | } | ||
143 | |||
144 | static struct aat2870_regulator aat2870_regulators[] = { | ||
145 | AAT2870_LDO(LDOA), | ||
146 | AAT2870_LDO(LDOB), | ||
147 | AAT2870_LDO(LDOC), | ||
148 | AAT2870_LDO(LDOD), | ||
149 | }; | ||
150 | |||
151 | static struct aat2870_regulator *aat2870_get_regulator(int id) | ||
152 | { | ||
153 | struct aat2870_regulator *ri = NULL; | ||
154 | int i; | ||
155 | |||
156 | for (i = 0; i < ARRAY_SIZE(aat2870_regulators); i++) { | ||
157 | ri = &aat2870_regulators[i]; | ||
158 | if (ri->desc.id == id) | ||
159 | break; | ||
160 | } | ||
161 | |||
162 | if (!ri) | ||
163 | return NULL; | ||
164 | |||
165 | ri->enable_addr = AAT2870_LDO_EN; | ||
166 | ri->enable_shift = id - AAT2870_ID_LDOA; | ||
167 | ri->enable_mask = 0x1 << ri->enable_shift; | ||
168 | |||
169 | ri->voltage_addr = (id - AAT2870_ID_LDOA) / 2 ? | ||
170 | AAT2870_LDO_CD : AAT2870_LDO_AB; | ||
171 | ri->voltage_shift = (id - AAT2870_ID_LDOA) % 2 ? 0 : 4; | ||
172 | ri->voltage_mask = 0xF << ri->voltage_shift; | ||
173 | |||
174 | return ri; | ||
175 | } | ||
176 | |||
177 | static int aat2870_regulator_probe(struct platform_device *pdev) | ||
178 | { | ||
179 | struct aat2870_regulator *ri; | ||
180 | struct regulator_dev *rdev; | ||
181 | |||
182 | ri = aat2870_get_regulator(pdev->id); | ||
183 | if (!ri) { | ||
184 | dev_err(&pdev->dev, "Invalid device ID, %d\n", pdev->id); | ||
185 | return -EINVAL; | ||
186 | } | ||
187 | ri->pdev = pdev; | ||
188 | |||
189 | rdev = regulator_register(&ri->desc, &pdev->dev, | ||
190 | pdev->dev.platform_data, ri); | ||
191 | if (IS_ERR(rdev)) { | ||
192 | dev_err(&pdev->dev, "Failed to register regulator %s\n", | ||
193 | ri->desc.name); | ||
194 | return PTR_ERR(rdev); | ||
195 | } | ||
196 | platform_set_drvdata(pdev, rdev); | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static int __devexit aat2870_regulator_remove(struct platform_device *pdev) | ||
202 | { | ||
203 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | ||
204 | |||
205 | regulator_unregister(rdev); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static struct platform_driver aat2870_regulator_driver = { | ||
210 | .driver = { | ||
211 | .name = "aat2870-regulator", | ||
212 | .owner = THIS_MODULE, | ||
213 | }, | ||
214 | .probe = aat2870_regulator_probe, | ||
215 | .remove = __devexit_p(aat2870_regulator_remove), | ||
216 | }; | ||
217 | |||
218 | static int __init aat2870_regulator_init(void) | ||
219 | { | ||
220 | return platform_driver_register(&aat2870_regulator_driver); | ||
221 | } | ||
222 | subsys_initcall(aat2870_regulator_init); | ||
223 | |||
224 | static void __exit aat2870_regulator_exit(void) | ||
225 | { | ||
226 | platform_driver_unregister(&aat2870_regulator_driver); | ||
227 | } | ||
228 | module_exit(aat2870_regulator_exit); | ||
229 | |||
230 | MODULE_DESCRIPTION("AnalogicTech AAT2870 Regulator"); | ||
231 | MODULE_LICENSE("GPL"); | ||
232 | MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>"); | ||
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index fbddc15e1811..701a5900f83f 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/regmap.h> | ||
28 | 29 | ||
29 | /* Register definitions */ | 30 | /* Register definitions */ |
30 | #define TPS65023_REG_VERSION 0 | 31 | #define TPS65023_REG_VERSION 0 |
@@ -125,93 +126,35 @@ struct tps_pmic { | |||
125 | struct i2c_client *client; | 126 | struct i2c_client *client; |
126 | struct regulator_dev *rdev[TPS65023_NUM_REGULATOR]; | 127 | struct regulator_dev *rdev[TPS65023_NUM_REGULATOR]; |
127 | const struct tps_info *info[TPS65023_NUM_REGULATOR]; | 128 | const struct tps_info *info[TPS65023_NUM_REGULATOR]; |
128 | struct mutex io_lock; | 129 | struct regmap *regmap; |
129 | }; | 130 | }; |
130 | 131 | ||
131 | static inline int tps_65023_read(struct tps_pmic *tps, u8 reg) | ||
132 | { | ||
133 | return i2c_smbus_read_byte_data(tps->client, reg); | ||
134 | } | ||
135 | |||
136 | static inline int tps_65023_write(struct tps_pmic *tps, u8 reg, u8 val) | ||
137 | { | ||
138 | return i2c_smbus_write_byte_data(tps->client, reg, val); | ||
139 | } | ||
140 | |||
141 | static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask) | 132 | static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask) |
142 | { | 133 | { |
143 | int err, data; | 134 | return regmap_update_bits(tps->regmap, reg, mask, mask); |
144 | |||
145 | mutex_lock(&tps->io_lock); | ||
146 | |||
147 | data = tps_65023_read(tps, reg); | ||
148 | if (data < 0) { | ||
149 | dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); | ||
150 | err = data; | ||
151 | goto out; | ||
152 | } | ||
153 | |||
154 | data |= mask; | ||
155 | err = tps_65023_write(tps, reg, data); | ||
156 | if (err) | ||
157 | dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); | ||
158 | |||
159 | out: | ||
160 | mutex_unlock(&tps->io_lock); | ||
161 | return err; | ||
162 | } | 135 | } |
163 | 136 | ||
164 | static int tps_65023_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask) | 137 | static int tps_65023_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask) |
165 | { | 138 | { |
166 | int err, data; | 139 | return regmap_update_bits(tps->regmap, reg, mask, 0); |
167 | |||
168 | mutex_lock(&tps->io_lock); | ||
169 | |||
170 | data = tps_65023_read(tps, reg); | ||
171 | if (data < 0) { | ||
172 | dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); | ||
173 | err = data; | ||
174 | goto out; | ||
175 | } | ||
176 | |||
177 | data &= ~mask; | ||
178 | |||
179 | err = tps_65023_write(tps, reg, data); | ||
180 | if (err) | ||
181 | dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); | ||
182 | |||
183 | out: | ||
184 | mutex_unlock(&tps->io_lock); | ||
185 | return err; | ||
186 | |||
187 | } | 140 | } |
188 | 141 | ||
189 | static int tps_65023_reg_read(struct tps_pmic *tps, u8 reg) | 142 | static int tps_65023_reg_read(struct tps_pmic *tps, u8 reg) |
190 | { | 143 | { |
191 | int data; | 144 | unsigned int val; |
145 | int ret; | ||
192 | 146 | ||
193 | mutex_lock(&tps->io_lock); | 147 | ret = regmap_read(tps->regmap, reg, &val); |
194 | 148 | ||
195 | data = tps_65023_read(tps, reg); | 149 | if (ret != 0) |
196 | if (data < 0) | 150 | return ret; |
197 | dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); | 151 | else |
198 | 152 | return val; | |
199 | mutex_unlock(&tps->io_lock); | ||
200 | return data; | ||
201 | } | 153 | } |
202 | 154 | ||
203 | static int tps_65023_reg_write(struct tps_pmic *tps, u8 reg, u8 val) | 155 | static int tps_65023_reg_write(struct tps_pmic *tps, u8 reg, u8 val) |
204 | { | 156 | { |
205 | int err; | 157 | return regmap_write(tps->regmap, reg, val); |
206 | |||
207 | mutex_lock(&tps->io_lock); | ||
208 | |||
209 | err = tps_65023_write(tps, reg, val); | ||
210 | if (err < 0) | ||
211 | dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); | ||
212 | |||
213 | mutex_unlock(&tps->io_lock); | ||
214 | return err; | ||
215 | } | 158 | } |
216 | 159 | ||
217 | static int tps65023_dcdc_is_enabled(struct regulator_dev *dev) | 160 | static int tps65023_dcdc_is_enabled(struct regulator_dev *dev) |
@@ -463,6 +406,11 @@ static struct regulator_ops tps65023_ldo_ops = { | |||
463 | .list_voltage = tps65023_ldo_list_voltage, | 406 | .list_voltage = tps65023_ldo_list_voltage, |
464 | }; | 407 | }; |
465 | 408 | ||
409 | static struct regmap_config tps65023_regmap_config = { | ||
410 | .reg_bits = 8, | ||
411 | .val_bits = 8, | ||
412 | }; | ||
413 | |||
466 | static int __devinit tps_65023_probe(struct i2c_client *client, | 414 | static int __devinit tps_65023_probe(struct i2c_client *client, |
467 | const struct i2c_device_id *id) | 415 | const struct i2c_device_id *id) |
468 | { | 416 | { |
@@ -488,7 +436,13 @@ static int __devinit tps_65023_probe(struct i2c_client *client, | |||
488 | if (!tps) | 436 | if (!tps) |
489 | return -ENOMEM; | 437 | return -ENOMEM; |
490 | 438 | ||
491 | mutex_init(&tps->io_lock); | 439 | tps->regmap = regmap_init_i2c(client, &tps65023_regmap_config); |
440 | if (IS_ERR(tps->regmap)) { | ||
441 | error = PTR_ERR(tps->regmap); | ||
442 | dev_err(&client->dev, "Failed to allocate register map: %d\n", | ||
443 | error); | ||
444 | goto fail_alloc; | ||
445 | } | ||
492 | 446 | ||
493 | /* common for all regulators */ | 447 | /* common for all regulators */ |
494 | tps->client = client; | 448 | tps->client = client; |
@@ -527,6 +481,8 @@ static int __devinit tps_65023_probe(struct i2c_client *client, | |||
527 | while (--i >= 0) | 481 | while (--i >= 0) |
528 | regulator_unregister(tps->rdev[i]); | 482 | regulator_unregister(tps->rdev[i]); |
529 | 483 | ||
484 | regmap_exit(tps->regmap); | ||
485 | fail_alloc: | ||
530 | kfree(tps); | 486 | kfree(tps); |
531 | return error; | 487 | return error; |
532 | } | 488 | } |
@@ -545,6 +501,7 @@ static int __devexit tps_65023_remove(struct i2c_client *client) | |||
545 | for (i = 0; i < TPS65023_NUM_REGULATOR; i++) | 501 | for (i = 0; i < TPS65023_NUM_REGULATOR; i++) |
546 | regulator_unregister(tps->rdev[i]); | 502 | regulator_unregister(tps->rdev[i]); |
547 | 503 | ||
504 | regmap_exit(tps->regmap); | ||
548 | kfree(tps); | 505 | kfree(tps); |
549 | 506 | ||
550 | return 0; | 507 | return 0; |
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c new file mode 100644 index 000000000000..3a9313e00fac --- /dev/null +++ b/drivers/regulator/tps65912-regulator.c | |||
@@ -0,0 +1,800 @@ | |||
1 | /* | ||
2 | * tps65912.c -- TI tps65912 | ||
3 | * | ||
4 | * Copyright 2011 Texas Instruments Inc. | ||
5 | * | ||
6 | * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This driver is based on wm8350 implementation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/regulator/driver.h> | ||
22 | #include <linux/regulator/machine.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/gpio.h> | ||
26 | #include <linux/mfd/tps65912.h> | ||
27 | |||
28 | /* DCDC's */ | ||
29 | #define TPS65912_REG_DCDC1 0 | ||
30 | #define TPS65912_REG_DCDC2 1 | ||
31 | #define TPS65912_REG_DCDC3 2 | ||
32 | #define TPS65912_REG_DCDC4 3 | ||
33 | |||
34 | /* LDOs */ | ||
35 | #define TPS65912_REG_LDO1 4 | ||
36 | #define TPS65912_REG_LDO2 5 | ||
37 | #define TPS65912_REG_LDO3 6 | ||
38 | #define TPS65912_REG_LDO4 7 | ||
39 | #define TPS65912_REG_LDO5 8 | ||
40 | #define TPS65912_REG_LDO6 9 | ||
41 | #define TPS65912_REG_LDO7 10 | ||
42 | #define TPS65912_REG_LDO8 11 | ||
43 | #define TPS65912_REG_LDO9 12 | ||
44 | #define TPS65912_REG_LDO10 13 | ||
45 | |||
46 | #define TPS65912_MAX_REG_ID TPS65912_REG_LDO_10 | ||
47 | |||
48 | /* Number of step-down converters available */ | ||
49 | #define TPS65912_NUM_DCDC 4 | ||
50 | |||
51 | /* Number of LDO voltage regulators available */ | ||
52 | #define TPS65912_NUM_LDO 10 | ||
53 | |||
54 | /* Number of total regulators available */ | ||
55 | #define TPS65912_NUM_REGULATOR (TPS65912_NUM_DCDC + TPS65912_NUM_LDO) | ||
56 | |||
57 | #define TPS65912_REG_ENABLED 0x80 | ||
58 | #define OP_SELREG_MASK 0x40 | ||
59 | #define OP_SELREG_SHIFT 6 | ||
60 | |||
61 | struct tps_info { | ||
62 | const char *name; | ||
63 | }; | ||
64 | |||
65 | static struct tps_info tps65912_regs[] = { | ||
66 | { | ||
67 | .name = "DCDC1", | ||
68 | }, | ||
69 | { | ||
70 | .name = "DCDC2", | ||
71 | }, | ||
72 | { | ||
73 | .name = "DCDC3", | ||
74 | }, | ||
75 | { | ||
76 | .name = "DCDC4", | ||
77 | }, | ||
78 | { | ||
79 | .name = "LDO1", | ||
80 | }, | ||
81 | { | ||
82 | .name = "LDO2", | ||
83 | }, | ||
84 | { | ||
85 | .name = "LDO3", | ||
86 | }, | ||
87 | { | ||
88 | .name = "LDO4", | ||
89 | }, | ||
90 | { | ||
91 | .name = "LDO5", | ||
92 | }, | ||
93 | { | ||
94 | .name = "LDO6", | ||
95 | }, | ||
96 | { | ||
97 | .name = "LDO7", | ||
98 | }, | ||
99 | { | ||
100 | .name = "LDO8", | ||
101 | }, | ||
102 | { | ||
103 | .name = "LDO9", | ||
104 | }, | ||
105 | { | ||
106 | .name = "LDO10", | ||
107 | }, | ||
108 | }; | ||
109 | |||
110 | struct tps65912_reg { | ||
111 | struct regulator_desc desc[TPS65912_NUM_REGULATOR]; | ||
112 | struct tps65912 *mfd; | ||
113 | struct regulator_dev *rdev[TPS65912_NUM_REGULATOR]; | ||
114 | struct tps_info *info[TPS65912_NUM_REGULATOR]; | ||
115 | /* for read/write access */ | ||
116 | struct mutex io_lock; | ||
117 | int mode; | ||
118 | int (*get_ctrl_reg)(int); | ||
119 | int dcdc1_range; | ||
120 | int dcdc2_range; | ||
121 | int dcdc3_range; | ||
122 | int dcdc4_range; | ||
123 | int pwm_mode_reg; | ||
124 | int eco_reg; | ||
125 | }; | ||
126 | |||
127 | static int tps65912_get_range(struct tps65912_reg *pmic, int id) | ||
128 | { | ||
129 | struct tps65912 *mfd = pmic->mfd; | ||
130 | |||
131 | if (id > TPS65912_REG_DCDC4) | ||
132 | return 0; | ||
133 | |||
134 | switch (id) { | ||
135 | case TPS65912_REG_DCDC1: | ||
136 | pmic->dcdc1_range = tps65912_reg_read(mfd, | ||
137 | TPS65912_DCDC1_LIMIT); | ||
138 | if (pmic->dcdc1_range < 0) | ||
139 | return pmic->dcdc1_range; | ||
140 | pmic->dcdc1_range = (pmic->dcdc1_range & | ||
141 | DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT; | ||
142 | return pmic->dcdc1_range; | ||
143 | case TPS65912_REG_DCDC2: | ||
144 | pmic->dcdc2_range = tps65912_reg_read(mfd, | ||
145 | TPS65912_DCDC2_LIMIT); | ||
146 | if (pmic->dcdc2_range < 0) | ||
147 | return pmic->dcdc2_range; | ||
148 | pmic->dcdc2_range = (pmic->dcdc2_range & | ||
149 | DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT; | ||
150 | return pmic->dcdc2_range; | ||
151 | case TPS65912_REG_DCDC3: | ||
152 | pmic->dcdc3_range = tps65912_reg_read(mfd, | ||
153 | TPS65912_DCDC3_LIMIT); | ||
154 | if (pmic->dcdc3_range < 0) | ||
155 | return pmic->dcdc3_range; | ||
156 | pmic->dcdc3_range = (pmic->dcdc3_range & | ||
157 | DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT; | ||
158 | return pmic->dcdc3_range; | ||
159 | case TPS65912_REG_DCDC4: | ||
160 | pmic->dcdc4_range = tps65912_reg_read(mfd, | ||
161 | TPS65912_DCDC4_LIMIT); | ||
162 | if (pmic->dcdc4_range < 0) | ||
163 | return pmic->dcdc4_range; | ||
164 | pmic->dcdc4_range = (pmic->dcdc4_range & | ||
165 | DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT; | ||
166 | return pmic->dcdc4_range; | ||
167 | default: | ||
168 | return 0; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static unsigned long tps65912_vsel_to_uv_range0(u8 vsel) | ||
173 | { | ||
174 | unsigned long uv; | ||
175 | |||
176 | uv = ((vsel * 12500) + 500000); | ||
177 | return uv; | ||
178 | } | ||
179 | |||
180 | static unsigned long tps65912_vsel_to_uv_range1(u8 vsel) | ||
181 | { | ||
182 | unsigned long uv; | ||
183 | |||
184 | uv = ((vsel * 12500) + 700000); | ||
185 | return uv; | ||
186 | } | ||
187 | |||
188 | static unsigned long tps65912_vsel_to_uv_range2(u8 vsel) | ||
189 | { | ||
190 | unsigned long uv; | ||
191 | |||
192 | uv = ((vsel * 25000) + 500000); | ||
193 | return uv; | ||
194 | } | ||
195 | |||
196 | static unsigned long tps65912_vsel_to_uv_range3(u8 vsel) | ||
197 | { | ||
198 | unsigned long uv; | ||
199 | |||
200 | if (vsel == 0x3f) | ||
201 | uv = 3800000; | ||
202 | else | ||
203 | uv = ((vsel * 50000) + 500000); | ||
204 | |||
205 | return uv; | ||
206 | } | ||
207 | |||
208 | static unsigned long tps65912_vsel_to_uv_ldo(u8 vsel) | ||
209 | { | ||
210 | unsigned long uv = 0; | ||
211 | |||
212 | if (vsel <= 32) | ||
213 | uv = ((vsel * 25000) + 800000); | ||
214 | else if (vsel > 32 && vsel <= 60) | ||
215 | uv = (((vsel - 32) * 50000) + 1600000); | ||
216 | else if (vsel > 60) | ||
217 | uv = (((vsel - 60) * 100000) + 3000000); | ||
218 | |||
219 | return uv; | ||
220 | } | ||
221 | |||
222 | static int tps65912_get_ctrl_register(int id) | ||
223 | { | ||
224 | switch (id) { | ||
225 | case TPS65912_REG_DCDC1: | ||
226 | return TPS65912_DCDC1_AVS; | ||
227 | case TPS65912_REG_DCDC2: | ||
228 | return TPS65912_DCDC2_AVS; | ||
229 | case TPS65912_REG_DCDC3: | ||
230 | return TPS65912_DCDC3_AVS; | ||
231 | case TPS65912_REG_DCDC4: | ||
232 | return TPS65912_DCDC4_AVS; | ||
233 | case TPS65912_REG_LDO1: | ||
234 | return TPS65912_LDO1_AVS; | ||
235 | case TPS65912_REG_LDO2: | ||
236 | return TPS65912_LDO2_AVS; | ||
237 | case TPS65912_REG_LDO3: | ||
238 | return TPS65912_LDO3_AVS; | ||
239 | case TPS65912_REG_LDO4: | ||
240 | return TPS65912_LDO4_AVS; | ||
241 | case TPS65912_REG_LDO5: | ||
242 | return TPS65912_LDO5; | ||
243 | case TPS65912_REG_LDO6: | ||
244 | return TPS65912_LDO6; | ||
245 | case TPS65912_REG_LDO7: | ||
246 | return TPS65912_LDO7; | ||
247 | case TPS65912_REG_LDO8: | ||
248 | return TPS65912_LDO8; | ||
249 | case TPS65912_REG_LDO9: | ||
250 | return TPS65912_LDO9; | ||
251 | case TPS65912_REG_LDO10: | ||
252 | return TPS65912_LDO10; | ||
253 | default: | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | } | ||
257 | |||
258 | static int tps65912_get_dcdc_sel_register(struct tps65912_reg *pmic, int id) | ||
259 | { | ||
260 | struct tps65912 *mfd = pmic->mfd; | ||
261 | int opvsel = 0, sr = 0; | ||
262 | u8 reg = 0; | ||
263 | |||
264 | if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_DCDC4) | ||
265 | return -EINVAL; | ||
266 | |||
267 | switch (id) { | ||
268 | case TPS65912_REG_DCDC1: | ||
269 | opvsel = tps65912_reg_read(mfd, TPS65912_DCDC1_OP); | ||
270 | sr = ((opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT); | ||
271 | if (sr) | ||
272 | reg = TPS65912_DCDC1_AVS; | ||
273 | else | ||
274 | reg = TPS65912_DCDC1_OP; | ||
275 | break; | ||
276 | case TPS65912_REG_DCDC2: | ||
277 | opvsel = tps65912_reg_read(mfd, TPS65912_DCDC2_OP); | ||
278 | sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT; | ||
279 | if (sr) | ||
280 | reg = TPS65912_DCDC2_AVS; | ||
281 | else | ||
282 | reg = TPS65912_DCDC2_OP; | ||
283 | break; | ||
284 | case TPS65912_REG_DCDC3: | ||
285 | opvsel = tps65912_reg_read(mfd, TPS65912_DCDC3_OP); | ||
286 | sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT; | ||
287 | if (sr) | ||
288 | reg = TPS65912_DCDC3_AVS; | ||
289 | else | ||
290 | reg = TPS65912_DCDC3_OP; | ||
291 | break; | ||
292 | case TPS65912_REG_DCDC4: | ||
293 | opvsel = tps65912_reg_read(mfd, TPS65912_DCDC4_OP); | ||
294 | sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT; | ||
295 | if (sr) | ||
296 | reg = TPS65912_DCDC4_AVS; | ||
297 | else | ||
298 | reg = TPS65912_DCDC4_OP; | ||
299 | break; | ||
300 | } | ||
301 | return reg; | ||
302 | } | ||
303 | |||
304 | static int tps65912_get_ldo_sel_register(struct tps65912_reg *pmic, int id) | ||
305 | { | ||
306 | struct tps65912 *mfd = pmic->mfd; | ||
307 | int opvsel = 0, sr = 0; | ||
308 | u8 reg = 0; | ||
309 | |||
310 | if (id < TPS65912_REG_LDO1 || id > TPS65912_REG_LDO10) | ||
311 | return -EINVAL; | ||
312 | |||
313 | switch (id) { | ||
314 | case TPS65912_REG_LDO1: | ||
315 | opvsel = tps65912_reg_read(mfd, TPS65912_LDO1_OP); | ||
316 | sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT; | ||
317 | if (sr) | ||
318 | reg = TPS65912_LDO1_AVS; | ||
319 | else | ||
320 | reg = TPS65912_LDO1_OP; | ||
321 | break; | ||
322 | case TPS65912_REG_LDO2: | ||
323 | opvsel = tps65912_reg_read(mfd, TPS65912_LDO2_OP); | ||
324 | sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT; | ||
325 | if (sr) | ||
326 | reg = TPS65912_LDO2_AVS; | ||
327 | else | ||
328 | reg = TPS65912_LDO2_OP; | ||
329 | break; | ||
330 | case TPS65912_REG_LDO3: | ||
331 | opvsel = tps65912_reg_read(mfd, TPS65912_LDO3_OP); | ||
332 | sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT; | ||
333 | if (sr) | ||
334 | reg = TPS65912_LDO3_AVS; | ||
335 | else | ||
336 | reg = TPS65912_LDO3_OP; | ||
337 | break; | ||
338 | case TPS65912_REG_LDO4: | ||
339 | opvsel = tps65912_reg_read(mfd, TPS65912_LDO4_OP); | ||
340 | sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT; | ||
341 | if (sr) | ||
342 | reg = TPS65912_LDO4_AVS; | ||
343 | else | ||
344 | reg = TPS65912_LDO4_OP; | ||
345 | break; | ||
346 | case TPS65912_REG_LDO5: | ||
347 | reg = TPS65912_LDO5; | ||
348 | break; | ||
349 | case TPS65912_REG_LDO6: | ||
350 | reg = TPS65912_LDO6; | ||
351 | break; | ||
352 | case TPS65912_REG_LDO7: | ||
353 | reg = TPS65912_LDO7; | ||
354 | break; | ||
355 | case TPS65912_REG_LDO8: | ||
356 | reg = TPS65912_LDO8; | ||
357 | break; | ||
358 | case TPS65912_REG_LDO9: | ||
359 | reg = TPS65912_LDO9; | ||
360 | break; | ||
361 | case TPS65912_REG_LDO10: | ||
362 | reg = TPS65912_LDO10; | ||
363 | break; | ||
364 | } | ||
365 | |||
366 | return reg; | ||
367 | } | ||
368 | |||
369 | static int tps65912_get_mode_regiters(struct tps65912_reg *pmic, int id) | ||
370 | { | ||
371 | switch (id) { | ||
372 | case TPS65912_REG_DCDC1: | ||
373 | pmic->pwm_mode_reg = TPS65912_DCDC1_CTRL; | ||
374 | pmic->eco_reg = TPS65912_DCDC1_AVS; | ||
375 | break; | ||
376 | case TPS65912_REG_DCDC2: | ||
377 | pmic->pwm_mode_reg = TPS65912_DCDC2_CTRL; | ||
378 | pmic->eco_reg = TPS65912_DCDC2_AVS; | ||
379 | break; | ||
380 | case TPS65912_REG_DCDC3: | ||
381 | pmic->pwm_mode_reg = TPS65912_DCDC3_CTRL; | ||
382 | pmic->eco_reg = TPS65912_DCDC3_AVS; | ||
383 | break; | ||
384 | case TPS65912_REG_DCDC4: | ||
385 | pmic->pwm_mode_reg = TPS65912_DCDC4_CTRL; | ||
386 | pmic->eco_reg = TPS65912_DCDC4_AVS; | ||
387 | break; | ||
388 | default: | ||
389 | return -EINVAL; | ||
390 | } | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static int tps65912_reg_is_enabled(struct regulator_dev *dev) | ||
396 | { | ||
397 | struct tps65912_reg *pmic = rdev_get_drvdata(dev); | ||
398 | struct tps65912 *mfd = pmic->mfd; | ||
399 | int reg, value, id = rdev_get_id(dev); | ||
400 | |||
401 | if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10) | ||
402 | return -EINVAL; | ||
403 | |||
404 | reg = pmic->get_ctrl_reg(id); | ||
405 | if (reg < 0) | ||
406 | return reg; | ||
407 | |||
408 | value = tps65912_reg_read(mfd, reg); | ||
409 | if (value < 0) | ||
410 | return value; | ||
411 | |||
412 | return value & TPS65912_REG_ENABLED; | ||
413 | } | ||
414 | |||
415 | static int tps65912_reg_enable(struct regulator_dev *dev) | ||
416 | { | ||
417 | struct tps65912_reg *pmic = rdev_get_drvdata(dev); | ||
418 | struct tps65912 *mfd = pmic->mfd; | ||
419 | int id = rdev_get_id(dev); | ||
420 | int reg; | ||
421 | |||
422 | if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10) | ||
423 | return -EINVAL; | ||
424 | |||
425 | reg = pmic->get_ctrl_reg(id); | ||
426 | if (reg < 0) | ||
427 | return reg; | ||
428 | |||
429 | return tps65912_set_bits(mfd, reg, TPS65912_REG_ENABLED); | ||
430 | } | ||
431 | |||
432 | static int tps65912_reg_disable(struct regulator_dev *dev) | ||
433 | { | ||
434 | struct tps65912_reg *pmic = rdev_get_drvdata(dev); | ||
435 | struct tps65912 *mfd = pmic->mfd; | ||
436 | int id = rdev_get_id(dev), reg; | ||
437 | |||
438 | reg = pmic->get_ctrl_reg(id); | ||
439 | if (reg < 0) | ||
440 | return reg; | ||
441 | |||
442 | return tps65912_clear_bits(mfd, reg, TPS65912_REG_ENABLED); | ||
443 | } | ||
444 | |||
445 | static int tps65912_set_mode(struct regulator_dev *dev, unsigned int mode) | ||
446 | { | ||
447 | struct tps65912_reg *pmic = rdev_get_drvdata(dev); | ||
448 | struct tps65912 *mfd = pmic->mfd; | ||
449 | int pwm_mode, eco, id = rdev_get_id(dev); | ||
450 | |||
451 | tps65912_get_mode_regiters(pmic, id); | ||
452 | |||
453 | pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg); | ||
454 | eco = tps65912_reg_read(mfd, pmic->eco_reg); | ||
455 | |||
456 | pwm_mode &= DCDCCTRL_DCDC_MODE_MASK; | ||
457 | eco &= DCDC_AVS_ECO_MASK; | ||
458 | |||
459 | switch (mode) { | ||
460 | case REGULATOR_MODE_FAST: | ||
461 | /* Verify if mode alredy set */ | ||
462 | if (pwm_mode && !eco) | ||
463 | break; | ||
464 | tps65912_set_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK); | ||
465 | tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK); | ||
466 | break; | ||
467 | case REGULATOR_MODE_NORMAL: | ||
468 | case REGULATOR_MODE_IDLE: | ||
469 | if (!pwm_mode && !eco) | ||
470 | break; | ||
471 | tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK); | ||
472 | tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK); | ||
473 | break; | ||
474 | case REGULATOR_MODE_STANDBY: | ||
475 | if (!pwm_mode && eco) | ||
476 | break; | ||
477 | tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK); | ||
478 | tps65912_set_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK); | ||
479 | break; | ||
480 | default: | ||
481 | return -EINVAL; | ||
482 | } | ||
483 | |||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static unsigned int tps65912_get_mode(struct regulator_dev *dev) | ||
488 | { | ||
489 | struct tps65912_reg *pmic = rdev_get_drvdata(dev); | ||
490 | struct tps65912 *mfd = pmic->mfd; | ||
491 | int pwm_mode, eco, mode = 0, id = rdev_get_id(dev); | ||
492 | |||
493 | tps65912_get_mode_regiters(pmic, id); | ||
494 | |||
495 | pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg); | ||
496 | eco = tps65912_reg_read(mfd, pmic->eco_reg); | ||
497 | |||
498 | pwm_mode &= DCDCCTRL_DCDC_MODE_MASK; | ||
499 | eco &= DCDC_AVS_ECO_MASK; | ||
500 | |||
501 | if (pwm_mode && !eco) | ||
502 | mode = REGULATOR_MODE_FAST; | ||
503 | else if (!pwm_mode && !eco) | ||
504 | mode = REGULATOR_MODE_NORMAL; | ||
505 | else if (!pwm_mode && eco) | ||
506 | mode = REGULATOR_MODE_STANDBY; | ||
507 | |||
508 | return mode; | ||
509 | } | ||
510 | |||
511 | static int tps65912_get_voltage_dcdc(struct regulator_dev *dev) | ||
512 | { | ||
513 | struct tps65912_reg *pmic = rdev_get_drvdata(dev); | ||
514 | struct tps65912 *mfd = pmic->mfd; | ||
515 | int id = rdev_get_id(dev), voltage = 0, range; | ||
516 | int opvsel = 0, avsel = 0, sr, vsel; | ||
517 | |||
518 | switch (id) { | ||
519 | case TPS65912_REG_DCDC1: | ||
520 | opvsel = tps65912_reg_read(mfd, TPS65912_DCDC1_OP); | ||
521 | avsel = tps65912_reg_read(mfd, TPS65912_DCDC1_AVS); | ||
522 | range = pmic->dcdc1_range; | ||
523 | break; | ||
524 | case TPS65912_REG_DCDC2: | ||
525 | opvsel = tps65912_reg_read(mfd, TPS65912_DCDC2_OP); | ||
526 | avsel = tps65912_reg_read(mfd, TPS65912_DCDC2_AVS); | ||
527 | range = pmic->dcdc2_range; | ||
528 | break; | ||
529 | case TPS65912_REG_DCDC3: | ||
530 | opvsel = tps65912_reg_read(mfd, TPS65912_DCDC3_OP); | ||
531 | avsel = tps65912_reg_read(mfd, TPS65912_DCDC3_AVS); | ||
532 | range = pmic->dcdc3_range; | ||
533 | break; | ||
534 | case TPS65912_REG_DCDC4: | ||
535 | opvsel = tps65912_reg_read(mfd, TPS65912_DCDC4_OP); | ||
536 | avsel = tps65912_reg_read(mfd, TPS65912_DCDC4_AVS); | ||
537 | range = pmic->dcdc4_range; | ||
538 | break; | ||
539 | default: | ||
540 | return -EINVAL; | ||
541 | } | ||
542 | |||
543 | sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT; | ||
544 | if (sr) | ||
545 | vsel = avsel; | ||
546 | else | ||
547 | vsel = opvsel; | ||
548 | vsel &= 0x3F; | ||
549 | |||
550 | switch (range) { | ||
551 | case 0: | ||
552 | /* 0.5 - 1.2875V in 12.5mV steps */ | ||
553 | voltage = tps65912_vsel_to_uv_range0(vsel); | ||
554 | break; | ||
555 | case 1: | ||
556 | /* 0.7 - 1.4875V in 12.5mV steps */ | ||
557 | voltage = tps65912_vsel_to_uv_range1(vsel); | ||
558 | break; | ||
559 | case 2: | ||
560 | /* 0.5 - 2.075V in 25mV steps */ | ||
561 | voltage = tps65912_vsel_to_uv_range2(vsel); | ||
562 | break; | ||
563 | case 3: | ||
564 | /* 0.5 - 3.8V in 50mV steps */ | ||
565 | voltage = tps65912_vsel_to_uv_range3(vsel); | ||
566 | break; | ||
567 | } | ||
568 | return voltage; | ||
569 | } | ||
570 | |||
571 | static int tps65912_set_voltage_dcdc(struct regulator_dev *dev, | ||
572 | unsigned selector) | ||
573 | { | ||
574 | struct tps65912_reg *pmic = rdev_get_drvdata(dev); | ||
575 | struct tps65912 *mfd = pmic->mfd; | ||
576 | int id = rdev_get_id(dev); | ||
577 | int value; | ||
578 | u8 reg; | ||
579 | |||
580 | reg = tps65912_get_dcdc_sel_register(pmic, id); | ||
581 | value = tps65912_reg_read(mfd, reg); | ||
582 | value &= 0xC0; | ||
583 | return tps65912_reg_write(mfd, reg, selector | value); | ||
584 | } | ||
585 | |||
586 | static int tps65912_get_voltage_ldo(struct regulator_dev *dev) | ||
587 | { | ||
588 | struct tps65912_reg *pmic = rdev_get_drvdata(dev); | ||
589 | struct tps65912 *mfd = pmic->mfd; | ||
590 | int id = rdev_get_id(dev); | ||
591 | int vsel = 0; | ||
592 | u8 reg; | ||
593 | |||
594 | reg = tps65912_get_ldo_sel_register(pmic, id); | ||
595 | vsel = tps65912_reg_read(mfd, reg); | ||
596 | vsel &= 0x3F; | ||
597 | |||
598 | return tps65912_vsel_to_uv_ldo(vsel); | ||
599 | } | ||
600 | |||
601 | static int tps65912_set_voltage_ldo(struct regulator_dev *dev, | ||
602 | unsigned selector) | ||
603 | { | ||
604 | struct tps65912_reg *pmic = rdev_get_drvdata(dev); | ||
605 | struct tps65912 *mfd = pmic->mfd; | ||
606 | int id = rdev_get_id(dev), reg, value; | ||
607 | |||
608 | reg = tps65912_get_ldo_sel_register(pmic, id); | ||
609 | value = tps65912_reg_read(mfd, reg); | ||
610 | value &= 0xC0; | ||
611 | return tps65912_reg_write(mfd, reg, selector | value); | ||
612 | } | ||
613 | |||
614 | static int tps65912_list_voltage_dcdc(struct regulator_dev *dev, | ||
615 | unsigned selector) | ||
616 | { | ||
617 | struct tps65912_reg *pmic = rdev_get_drvdata(dev); | ||
618 | int range, voltage = 0, id = rdev_get_id(dev); | ||
619 | |||
620 | switch (id) { | ||
621 | case TPS65912_REG_DCDC1: | ||
622 | range = pmic->dcdc1_range; | ||
623 | break; | ||
624 | case TPS65912_REG_DCDC2: | ||
625 | range = pmic->dcdc2_range; | ||
626 | break; | ||
627 | case TPS65912_REG_DCDC3: | ||
628 | range = pmic->dcdc3_range; | ||
629 | break; | ||
630 | case TPS65912_REG_DCDC4: | ||
631 | range = pmic->dcdc4_range; | ||
632 | break; | ||
633 | default: | ||
634 | return -EINVAL; | ||
635 | } | ||
636 | |||
637 | switch (range) { | ||
638 | case 0: | ||
639 | /* 0.5 - 1.2875V in 12.5mV steps */ | ||
640 | voltage = tps65912_vsel_to_uv_range0(selector); | ||
641 | break; | ||
642 | case 1: | ||
643 | /* 0.7 - 1.4875V in 12.5mV steps */ | ||
644 | voltage = tps65912_vsel_to_uv_range1(selector); | ||
645 | break; | ||
646 | case 2: | ||
647 | /* 0.5 - 2.075V in 25mV steps */ | ||
648 | voltage = tps65912_vsel_to_uv_range2(selector); | ||
649 | break; | ||
650 | case 3: | ||
651 | /* 0.5 - 3.8V in 50mV steps */ | ||
652 | voltage = tps65912_vsel_to_uv_range3(selector); | ||
653 | break; | ||
654 | } | ||
655 | return voltage; | ||
656 | } | ||
657 | |||
658 | static int tps65912_list_voltage_ldo(struct regulator_dev *dev, | ||
659 | unsigned selector) | ||
660 | { | ||
661 | int ldo = rdev_get_id(dev); | ||
662 | |||
663 | if (ldo < TPS65912_REG_LDO1 || ldo > TPS65912_REG_LDO10) | ||
664 | return -EINVAL; | ||
665 | |||
666 | return tps65912_vsel_to_uv_ldo(selector); | ||
667 | } | ||
668 | |||
669 | /* Operations permitted on DCDCx */ | ||
670 | static struct regulator_ops tps65912_ops_dcdc = { | ||
671 | .is_enabled = tps65912_reg_is_enabled, | ||
672 | .enable = tps65912_reg_enable, | ||
673 | .disable = tps65912_reg_disable, | ||
674 | .set_mode = tps65912_set_mode, | ||
675 | .get_mode = tps65912_get_mode, | ||
676 | .get_voltage = tps65912_get_voltage_dcdc, | ||
677 | .set_voltage_sel = tps65912_set_voltage_dcdc, | ||
678 | .list_voltage = tps65912_list_voltage_dcdc, | ||
679 | }; | ||
680 | |||
681 | /* Operations permitted on LDOx */ | ||
682 | static struct regulator_ops tps65912_ops_ldo = { | ||
683 | .is_enabled = tps65912_reg_is_enabled, | ||
684 | .enable = tps65912_reg_enable, | ||
685 | .disable = tps65912_reg_disable, | ||
686 | .get_voltage = tps65912_get_voltage_ldo, | ||
687 | .set_voltage_sel = tps65912_set_voltage_ldo, | ||
688 | .list_voltage = tps65912_list_voltage_ldo, | ||
689 | }; | ||
690 | |||
691 | static __devinit int tps65912_probe(struct platform_device *pdev) | ||
692 | { | ||
693 | struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent); | ||
694 | struct tps_info *info; | ||
695 | struct regulator_init_data *reg_data; | ||
696 | struct regulator_dev *rdev; | ||
697 | struct tps65912_reg *pmic; | ||
698 | struct tps65912_board *pmic_plat_data; | ||
699 | int i, err; | ||
700 | |||
701 | pmic_plat_data = dev_get_platdata(tps65912->dev); | ||
702 | if (!pmic_plat_data) | ||
703 | return -EINVAL; | ||
704 | |||
705 | reg_data = pmic_plat_data->tps65912_pmic_init_data; | ||
706 | |||
707 | pmic = kzalloc(sizeof(*pmic), GFP_KERNEL); | ||
708 | if (!pmic) | ||
709 | return -ENOMEM; | ||
710 | |||
711 | mutex_init(&pmic->io_lock); | ||
712 | pmic->mfd = tps65912; | ||
713 | platform_set_drvdata(pdev, pmic); | ||
714 | |||
715 | pmic->get_ctrl_reg = &tps65912_get_ctrl_register; | ||
716 | info = tps65912_regs; | ||
717 | |||
718 | for (i = 0; i < TPS65912_NUM_REGULATOR; i++, info++, reg_data++) { | ||
719 | int range = 0; | ||
720 | /* Register the regulators */ | ||
721 | pmic->info[i] = info; | ||
722 | |||
723 | pmic->desc[i].name = info->name; | ||
724 | pmic->desc[i].id = i; | ||
725 | pmic->desc[i].n_voltages = 64; | ||
726 | pmic->desc[i].ops = (i > TPS65912_REG_DCDC4 ? | ||
727 | &tps65912_ops_ldo : &tps65912_ops_dcdc); | ||
728 | pmic->desc[i].type = REGULATOR_VOLTAGE; | ||
729 | pmic->desc[i].owner = THIS_MODULE; | ||
730 | range = tps65912_get_range(pmic, i); | ||
731 | rdev = regulator_register(&pmic->desc[i], | ||
732 | tps65912->dev, reg_data, pmic); | ||
733 | if (IS_ERR(rdev)) { | ||
734 | dev_err(tps65912->dev, | ||
735 | "failed to register %s regulator\n", | ||
736 | pdev->name); | ||
737 | err = PTR_ERR(rdev); | ||
738 | goto err; | ||
739 | } | ||
740 | |||
741 | /* Save regulator for cleanup */ | ||
742 | pmic->rdev[i] = rdev; | ||
743 | } | ||
744 | return 0; | ||
745 | |||
746 | err: | ||
747 | while (--i >= 0) | ||
748 | regulator_unregister(pmic->rdev[i]); | ||
749 | |||
750 | kfree(pmic); | ||
751 | return err; | ||
752 | } | ||
753 | |||
754 | static int __devexit tps65912_remove(struct platform_device *pdev) | ||
755 | { | ||
756 | struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev); | ||
757 | int i; | ||
758 | |||
759 | for (i = 0; i < TPS65912_NUM_REGULATOR; i++) | ||
760 | regulator_unregister(tps65912_reg->rdev[i]); | ||
761 | |||
762 | kfree(tps65912_reg); | ||
763 | return 0; | ||
764 | } | ||
765 | |||
766 | static struct platform_driver tps65912_driver = { | ||
767 | .driver = { | ||
768 | .name = "tps65912-pmic", | ||
769 | .owner = THIS_MODULE, | ||
770 | }, | ||
771 | .probe = tps65912_probe, | ||
772 | .remove = __devexit_p(tps65912_remove), | ||
773 | }; | ||
774 | |||
775 | /** | ||
776 | * tps65912_init | ||
777 | * | ||
778 | * Module init function | ||
779 | */ | ||
780 | static int __init tps65912_init(void) | ||
781 | { | ||
782 | return platform_driver_register(&tps65912_driver); | ||
783 | } | ||
784 | subsys_initcall(tps65912_init); | ||
785 | |||
786 | /** | ||
787 | * tps65912_cleanup | ||
788 | * | ||
789 | * Module exit function | ||
790 | */ | ||
791 | static void __exit tps65912_cleanup(void) | ||
792 | { | ||
793 | platform_driver_unregister(&tps65912_driver); | ||
794 | } | ||
795 | module_exit(tps65912_cleanup); | ||
796 | |||
797 | MODULE_AUTHOR("Margarita Olaya Cabrera <magi@slimlogic.co.uk>"); | ||
798 | MODULE_DESCRIPTION("TPS65912 voltage regulator driver"); | ||
799 | MODULE_LICENSE("GPL v2"); | ||
800 | MODULE_ALIAS("platform:tps65912-pmic"); | ||