]>
Commit | Line | Data |
---|---|---|
518fb721 GG |
1 | /* |
2 | * tps65910.c -- TI tps65910 | |
3 | * | |
4 | * Copyright 2010 Texas Instruments Inc. | |
5 | * | |
6 | * Author: Graeme Gregory <gg@slimlogic.co.uk> | |
7 | * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify it | |
10 | * under the terms of the GNU General Public License as published by the | |
11 | * Free Software Foundation; either version 2 of the License, or (at your | |
12 | * option) any later version. | |
13 | * | |
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/tps65910.h> | |
27 | ||
28 | #define TPS65910_REG_VRTC 0 | |
29 | #define TPS65910_REG_VIO 1 | |
30 | #define TPS65910_REG_VDD1 2 | |
31 | #define TPS65910_REG_VDD2 3 | |
32 | #define TPS65910_REG_VDD3 4 | |
33 | #define TPS65910_REG_VDIG1 5 | |
34 | #define TPS65910_REG_VDIG2 6 | |
35 | #define TPS65910_REG_VPLL 7 | |
36 | #define TPS65910_REG_VDAC 8 | |
37 | #define TPS65910_REG_VAUX1 9 | |
38 | #define TPS65910_REG_VAUX2 10 | |
39 | #define TPS65910_REG_VAUX33 11 | |
40 | #define TPS65910_REG_VMMC 12 | |
41 | ||
42 | #define TPS65910_NUM_REGULATOR 13 | |
43 | ||
44 | #define TPS65910_SUPPLY_STATE_ENABLED 0x1 | |
45 | ||
46 | /* supported VIO voltages in milivolts */ | |
47 | static const u16 VIO_VSEL_table[] = { | |
48 | 1500, 1800, 2500, 3300, | |
49 | }; | |
50 | ||
51 | /* supported VIO voltages in milivolts */ | |
52 | static const u16 VDD3_VSEL_table[] = { | |
53 | 5000, | |
54 | }; | |
55 | ||
56 | /* supported VDIG1 voltages in milivolts */ | |
57 | static const u16 VDIG1_VSEL_table[] = { | |
58 | 1200, 1500, 1800, 2700, | |
59 | }; | |
60 | ||
61 | /* supported VDIG2 voltages in milivolts */ | |
62 | static const u16 VDIG2_VSEL_table[] = { | |
63 | 1000, 1100, 1200, 1800, | |
64 | }; | |
65 | ||
66 | /* supported VPLL voltages in milivolts */ | |
67 | static const u16 VPLL_VSEL_table[] = { | |
68 | 1000, 1100, 1800, 2500, | |
69 | }; | |
70 | ||
71 | /* supported VDAC voltages in milivolts */ | |
72 | static const u16 VDAC_VSEL_table[] = { | |
73 | 1800, 2600, 2800, 2850, | |
74 | }; | |
75 | ||
76 | /* supported VAUX1 voltages in milivolts */ | |
77 | static const u16 VAUX1_VSEL_table[] = { | |
78 | 1800, 2500, 2800, 2850, | |
79 | }; | |
80 | ||
81 | /* supported VAUX2 voltages in milivolts */ | |
82 | static const u16 VAUX2_VSEL_table[] = { | |
83 | 1800, 2800, 2900, 3300, | |
84 | }; | |
85 | ||
86 | /* supported VAUX33 voltages in milivolts */ | |
87 | static const u16 VAUX33_VSEL_table[] = { | |
88 | 1800, 2000, 2800, 3300, | |
89 | }; | |
90 | ||
91 | /* supported VMMC voltages in milivolts */ | |
92 | static const u16 VMMC_VSEL_table[] = { | |
93 | 1800, 2800, 3000, 3300, | |
94 | }; | |
95 | ||
96 | struct tps_info { | |
97 | const char *name; | |
98 | unsigned min_uV; | |
99 | unsigned max_uV; | |
100 | u8 table_len; | |
101 | const u16 *table; | |
102 | }; | |
103 | ||
104 | static struct tps_info tps65910_regs[] = { | |
105 | { | |
106 | .name = "VRTC", | |
107 | }, | |
108 | { | |
109 | .name = "VIO", | |
110 | .min_uV = 1500000, | |
111 | .max_uV = 3300000, | |
112 | .table_len = ARRAY_SIZE(VIO_VSEL_table), | |
113 | .table = VIO_VSEL_table, | |
114 | }, | |
115 | { | |
116 | .name = "VDD1", | |
117 | .min_uV = 600000, | |
118 | .max_uV = 4500000, | |
119 | }, | |
120 | { | |
121 | .name = "VDD2", | |
122 | .min_uV = 600000, | |
123 | .max_uV = 4500000, | |
124 | }, | |
125 | { | |
126 | .name = "VDD3", | |
127 | .min_uV = 5000000, | |
128 | .max_uV = 5000000, | |
129 | .table_len = ARRAY_SIZE(VDD3_VSEL_table), | |
130 | .table = VDD3_VSEL_table, | |
131 | }, | |
132 | { | |
133 | .name = "VDIG1", | |
134 | .min_uV = 1200000, | |
135 | .max_uV = 2700000, | |
136 | .table_len = ARRAY_SIZE(VDIG1_VSEL_table), | |
137 | .table = VDIG1_VSEL_table, | |
138 | }, | |
139 | { | |
140 | .name = "VDIG2", | |
141 | .min_uV = 1000000, | |
142 | .max_uV = 1800000, | |
143 | .table_len = ARRAY_SIZE(VDIG2_VSEL_table), | |
144 | .table = VDIG2_VSEL_table, | |
145 | }, | |
146 | { | |
147 | .name = "VPLL", | |
148 | .min_uV = 1000000, | |
149 | .max_uV = 2500000, | |
150 | .table_len = ARRAY_SIZE(VPLL_VSEL_table), | |
151 | .table = VPLL_VSEL_table, | |
152 | }, | |
153 | { | |
154 | .name = "VDAC", | |
155 | .min_uV = 1800000, | |
156 | .max_uV = 2850000, | |
157 | .table_len = ARRAY_SIZE(VDAC_VSEL_table), | |
158 | .table = VDAC_VSEL_table, | |
159 | }, | |
160 | { | |
161 | .name = "VAUX1", | |
162 | .min_uV = 1800000, | |
163 | .max_uV = 2850000, | |
164 | .table_len = ARRAY_SIZE(VAUX1_VSEL_table), | |
165 | .table = VAUX1_VSEL_table, | |
166 | }, | |
167 | { | |
168 | .name = "VAUX2", | |
169 | .min_uV = 1800000, | |
170 | .max_uV = 3300000, | |
171 | .table_len = ARRAY_SIZE(VAUX2_VSEL_table), | |
172 | .table = VAUX2_VSEL_table, | |
173 | }, | |
174 | { | |
175 | .name = "VAUX33", | |
176 | .min_uV = 1800000, | |
177 | .max_uV = 3300000, | |
178 | .table_len = ARRAY_SIZE(VAUX33_VSEL_table), | |
179 | .table = VAUX33_VSEL_table, | |
180 | }, | |
181 | { | |
182 | .name = "VMMC", | |
183 | .min_uV = 1800000, | |
184 | .max_uV = 3300000, | |
185 | .table_len = ARRAY_SIZE(VMMC_VSEL_table), | |
186 | .table = VMMC_VSEL_table, | |
187 | }, | |
188 | }; | |
189 | ||
190 | struct tps65910_reg { | |
191 | struct regulator_desc desc[TPS65910_NUM_REGULATOR]; | |
192 | struct tps65910 *mfd; | |
193 | struct regulator_dev *rdev[TPS65910_NUM_REGULATOR]; | |
194 | struct tps_info *info[TPS65910_NUM_REGULATOR]; | |
195 | struct mutex mutex; | |
196 | int mode; | |
197 | }; | |
198 | ||
199 | static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg) | |
200 | { | |
201 | u8 val; | |
202 | int err; | |
203 | ||
204 | err = pmic->mfd->read(pmic->mfd, reg, 1, &val); | |
205 | if (err) | |
206 | return err; | |
207 | ||
208 | return val; | |
209 | } | |
210 | ||
211 | static inline int tps65910_write(struct tps65910_reg *pmic, u8 reg, u8 val) | |
212 | { | |
213 | return pmic->mfd->write(pmic->mfd, reg, 1, &val); | |
214 | } | |
215 | ||
216 | static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg, | |
217 | u8 set_mask, u8 clear_mask) | |
218 | { | |
219 | int err, data; | |
220 | ||
221 | mutex_lock(&pmic->mutex); | |
222 | ||
223 | data = tps65910_read(pmic, reg); | |
224 | if (data < 0) { | |
225 | dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg); | |
226 | err = data; | |
227 | goto out; | |
228 | } | |
229 | ||
230 | data &= ~clear_mask; | |
231 | data |= set_mask; | |
232 | err = tps65910_write(pmic, reg, data); | |
233 | if (err) | |
234 | dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); | |
235 | ||
236 | out: | |
237 | mutex_unlock(&pmic->mutex); | |
238 | return err; | |
239 | } | |
240 | ||
241 | static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg) | |
242 | { | |
243 | int data; | |
244 | ||
245 | mutex_lock(&pmic->mutex); | |
246 | ||
247 | data = tps65910_read(pmic, reg); | |
248 | if (data < 0) | |
249 | dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg); | |
250 | ||
251 | mutex_unlock(&pmic->mutex); | |
252 | return data; | |
253 | } | |
254 | ||
255 | static int tps65910_reg_write(struct tps65910_reg *pmic, u8 reg, u8 val) | |
256 | { | |
257 | int err; | |
258 | ||
259 | mutex_lock(&pmic->mutex); | |
260 | ||
261 | err = tps65910_write(pmic, reg, val); | |
262 | if (err < 0) | |
263 | dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); | |
264 | ||
265 | mutex_unlock(&pmic->mutex); | |
266 | return err; | |
267 | } | |
268 | ||
269 | static int tps65910_get_ctrl_register(int id) | |
270 | { | |
271 | switch (id) { | |
272 | case TPS65910_REG_VRTC: | |
273 | return TPS65910_VRTC; | |
274 | case TPS65910_REG_VIO: | |
275 | return TPS65910_VIO; | |
276 | case TPS65910_REG_VDD1: | |
277 | return TPS65910_VDD1; | |
278 | case TPS65910_REG_VDD2: | |
279 | return TPS65910_VDD2; | |
280 | case TPS65910_REG_VDD3: | |
281 | return TPS65910_VDD3; | |
282 | case TPS65910_REG_VDIG1: | |
283 | return TPS65910_VDIG1; | |
284 | case TPS65910_REG_VDIG2: | |
285 | return TPS65910_VDIG2; | |
286 | case TPS65910_REG_VPLL: | |
287 | return TPS65910_VPLL; | |
288 | case TPS65910_REG_VDAC: | |
289 | return TPS65910_VDAC; | |
290 | case TPS65910_REG_VAUX1: | |
291 | return TPS65910_VAUX1; | |
292 | case TPS65910_REG_VAUX2: | |
293 | return TPS65910_VAUX2; | |
294 | case TPS65910_REG_VAUX33: | |
295 | return TPS65910_VAUX33; | |
296 | case TPS65910_REG_VMMC: | |
297 | return TPS65910_VMMC; | |
298 | default: | |
299 | return -EINVAL; | |
300 | } | |
301 | } | |
302 | ||
303 | static int tps65910_is_enabled(struct regulator_dev *dev) | |
304 | { | |
305 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | |
306 | int reg, value, id = rdev_get_id(dev); | |
307 | ||
308 | reg = tps65910_get_ctrl_register(id); | |
309 | if (reg < 0) | |
310 | return reg; | |
311 | ||
312 | value = tps65910_reg_read(pmic, reg); | |
313 | if (value < 0) | |
314 | return value; | |
315 | ||
316 | return value & TPS65910_SUPPLY_STATE_ENABLED; | |
317 | } | |
318 | ||
319 | static int tps65910_enable(struct regulator_dev *dev) | |
320 | { | |
321 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | |
322 | struct tps65910 *mfd = pmic->mfd; | |
323 | int reg, id = rdev_get_id(dev); | |
324 | ||
325 | reg = tps65910_get_ctrl_register(id); | |
326 | if (reg < 0) | |
327 | return reg; | |
328 | ||
329 | return tps65910_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); | |
330 | } | |
331 | ||
332 | static int tps65910_disable(struct regulator_dev *dev) | |
333 | { | |
334 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | |
335 | struct tps65910 *mfd = pmic->mfd; | |
336 | int reg, id = rdev_get_id(dev); | |
337 | ||
338 | reg = tps65910_get_ctrl_register(id); | |
339 | if (reg < 0) | |
340 | return reg; | |
341 | ||
342 | return tps65910_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); | |
343 | } | |
344 | ||
345 | ||
346 | static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) | |
347 | { | |
348 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | |
349 | struct tps65910 *mfd = pmic->mfd; | |
350 | int reg, value, id = rdev_get_id(dev); | |
351 | reg = tps65910_get_ctrl_register(id); | |
352 | if (reg < 0) | |
353 | return reg; | |
354 | ||
355 | switch (mode) { | |
356 | case REGULATOR_MODE_NORMAL: | |
357 | return tps65910_modify_bits(pmic, reg, LDO_ST_ON_BIT, | |
358 | LDO_ST_MODE_BIT); | |
359 | case REGULATOR_MODE_IDLE: | |
360 | value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT; | |
361 | return tps65910_set_bits(mfd, reg, value); | |
362 | case REGULATOR_MODE_STANDBY: | |
363 | return tps65910_clear_bits(mfd, reg, LDO_ST_ON_BIT); | |
364 | } | |
365 | ||
366 | return -EINVAL; | |
367 | } | |
368 | ||
369 | static unsigned int tps65910_get_mode(struct regulator_dev *dev) | |
370 | { | |
371 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | |
372 | int reg, value, id = rdev_get_id(dev); | |
373 | ||
374 | reg = tps65910_get_ctrl_register(id); | |
375 | if (reg < 0) | |
376 | return reg; | |
377 | ||
378 | value = tps65910_reg_read(pmic, reg); | |
379 | if (value < 0) | |
380 | return value; | |
381 | ||
382 | if (value & LDO_ST_ON_BIT) | |
383 | return REGULATOR_MODE_STANDBY; | |
384 | else if (value & LDO_ST_MODE_BIT) | |
385 | return REGULATOR_MODE_IDLE; | |
386 | else | |
387 | return REGULATOR_MODE_NORMAL; | |
388 | } | |
389 | ||
390 | static int tps65910_get_voltage_dcdc(struct regulator_dev *dev) | |
391 | { | |
392 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | |
393 | int id = rdev_get_id(dev), voltage = 0; | |
394 | int opvsel = 0, srvsel = 0, mult = 0, sr = 0; | |
395 | ||
396 | switch (id) { | |
397 | case TPS65910_REG_VDD1: | |
398 | opvsel = tps65910_reg_read(pmic, TPS65910_VDD1_OP); | |
399 | mult = tps65910_reg_read(pmic, TPS65910_VDD1); | |
400 | mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT; | |
401 | srvsel = tps65910_reg_read(pmic, TPS65910_VDD1_SR); | |
402 | sr = opvsel & VDD1_OP_CMD_MASK; | |
403 | opvsel &= VDD1_OP_SEL_MASK; | |
404 | srvsel &= VDD1_SR_SEL_MASK; | |
405 | break; | |
406 | case TPS65910_REG_VDD2: | |
407 | opvsel = tps65910_reg_read(pmic, TPS65910_VDD2_OP); | |
408 | mult = tps65910_reg_read(pmic, TPS65910_VDD2); | |
409 | mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT; | |
410 | srvsel = tps65910_reg_read(pmic, TPS65910_VDD2_SR); | |
411 | sr = opvsel & VDD2_OP_CMD_MASK; | |
412 | opvsel &= VDD2_OP_SEL_MASK; | |
413 | srvsel &= VDD2_SR_SEL_MASK; | |
414 | break; | |
415 | } | |
416 | ||
417 | /* multiplier 0 == 1 but 2,3 normal */ | |
418 | if (!mult) | |
419 | mult=1; | |
420 | ||
421 | if (sr) { | |
422 | /* Valid range is 3-75 so normalise */ | |
423 | if (srvsel < 3) srvsel = 3; | |
424 | if (srvsel > 75) srvsel = 75; | |
425 | srvsel -= 3; | |
426 | ||
427 | voltage = (srvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100; | |
428 | } else { | |
429 | ||
430 | /* Valid range is 3-75 so normalise */ | |
431 | if (opvsel < 3) opvsel = 3; | |
432 | if (opvsel > 75) opvsel = 75; | |
433 | opvsel -= 3; | |
434 | ||
435 | voltage = (opvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100; | |
436 | } | |
437 | ||
438 | voltage *= mult; | |
439 | ||
440 | return voltage; | |
441 | } | |
442 | ||
443 | static int tps65910_get_voltage(struct regulator_dev *dev) | |
444 | { | |
445 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | |
446 | int reg, value, id = rdev_get_id(dev), voltage = 0; | |
447 | ||
448 | reg = tps65910_get_ctrl_register(id); | |
449 | if (reg < 0) | |
450 | return reg; | |
451 | ||
452 | value = tps65910_reg_read(pmic, reg); | |
453 | if (value < 0) | |
454 | return value; | |
455 | ||
456 | switch (id) { | |
457 | case TPS65910_REG_VIO: | |
458 | case TPS65910_REG_VDIG1: | |
459 | case TPS65910_REG_VDIG2: | |
460 | case TPS65910_REG_VPLL: | |
461 | case TPS65910_REG_VDAC: | |
462 | case TPS65910_REG_VAUX1: | |
463 | case TPS65910_REG_VAUX2: | |
464 | case TPS65910_REG_VAUX33: | |
465 | case TPS65910_REG_VMMC: | |
466 | value &= LDO_SEL_MASK; | |
467 | value >>= LDO_SEL_SHIFT; | |
468 | break; | |
469 | default: | |
470 | return -EINVAL; | |
471 | } | |
472 | ||
473 | voltage = pmic->info[id]->table[value] * 1000; | |
474 | ||
475 | return voltage; | |
476 | } | |
477 | ||
478 | static int tps65910_get_voltage_vdd3(struct regulator_dev *dev) | |
479 | { | |
480 | return 5 * 1000 * 1000; | |
481 | } | |
482 | ||
483 | static int tps65910_set_voltage_dcdc(struct regulator_dev *dev, | |
484 | unsigned selector) | |
485 | { | |
486 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | |
487 | int id = rdev_get_id(dev), vsel; | |
488 | int dcdc_mult; | |
489 | ||
490 | /* Split vsel into appropriate registers */ | |
491 | dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1; | |
492 | if (dcdc_mult == 1) dcdc_mult--; | |
493 | ||
494 | vsel = (selector % VDD1_2_NUM_VOLTS) + 3; | |
495 | ||
496 | if (id == TPS65910_REG_VDD1) { | |
497 | tps65910_modify_bits(pmic, TPS65910_VDD1, | |
498 | (dcdc_mult << VDD1_VGAIN_SEL_SHIFT), | |
499 | VDD1_VGAIN_SEL_MASK); | |
500 | tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel); | |
501 | } else { | |
502 | tps65910_modify_bits(pmic, TPS65910_VDD2, | |
503 | (dcdc_mult << VDD2_VGAIN_SEL_SHIFT), | |
504 | VDD1_VGAIN_SEL_MASK); | |
505 | tps65910_reg_write(pmic, TPS65910_VDD2_OP, vsel); | |
506 | } | |
507 | ||
508 | return 0; | |
509 | } | |
510 | ||
511 | static int tps65910_set_voltage(struct regulator_dev *dev, unsigned selector) | |
512 | { | |
513 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | |
514 | int reg, id = rdev_get_id(dev); | |
515 | ||
516 | reg = tps65910_get_ctrl_register(id); | |
517 | if (reg < 0) | |
518 | return reg; | |
519 | ||
520 | switch (id) { | |
521 | case TPS65910_REG_VIO: | |
522 | case TPS65910_REG_VDIG1: | |
523 | case TPS65910_REG_VDIG2: | |
524 | case TPS65910_REG_VPLL: | |
525 | case TPS65910_REG_VDAC: | |
526 | case TPS65910_REG_VAUX1: | |
527 | case TPS65910_REG_VAUX2: | |
528 | case TPS65910_REG_VAUX33: | |
529 | case TPS65910_REG_VMMC: | |
530 | return tps65910_modify_bits(pmic, reg, | |
531 | (selector << LDO_SEL_SHIFT), LDO_SEL_MASK); | |
532 | } | |
533 | ||
534 | return -EINVAL; | |
535 | } | |
536 | ||
537 | static int tps65910_list_voltage_dcdc(struct regulator_dev *dev, | |
538 | unsigned selector) | |
539 | { | |
540 | int mult, volt; | |
541 | ||
542 | mult = (selector / VDD1_2_NUM_VOLTS) + 1; | |
543 | ||
544 | volt = VDD1_2_MIN_VOLT + (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET; | |
545 | ||
546 | return volt * 100 * mult; | |
547 | } | |
548 | ||
549 | static int tps65910_list_voltage(struct regulator_dev *dev, | |
550 | unsigned selector) | |
551 | { | |
552 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | |
553 | int id = rdev_get_id(dev), voltage; | |
554 | ||
555 | if (id < TPS65910_REG_VIO || id > TPS65910_REG_VMMC) | |
556 | return -EINVAL; | |
557 | ||
558 | if (selector >= pmic->info[id]->table_len) | |
559 | return -EINVAL; | |
560 | else | |
561 | voltage = pmic->info[id]->table[selector] * 1000; | |
562 | ||
563 | return voltage; | |
564 | } | |
565 | ||
566 | /* Regulator ops (except VRTC) */ | |
567 | static struct regulator_ops tps65910_ops_dcdc = { | |
568 | .is_enabled = tps65910_is_enabled, | |
569 | .enable = tps65910_enable, | |
570 | .disable = tps65910_disable, | |
571 | .set_mode = tps65910_set_mode, | |
572 | .get_mode = tps65910_get_mode, | |
573 | .get_voltage = tps65910_get_voltage_dcdc, | |
574 | .set_voltage_sel = tps65910_set_voltage_dcdc, | |
575 | .list_voltage = tps65910_list_voltage_dcdc, | |
576 | }; | |
577 | ||
578 | static struct regulator_ops tps65910_ops_vdd3 = { | |
579 | .is_enabled = tps65910_is_enabled, | |
580 | .enable = tps65910_enable, | |
581 | .disable = tps65910_disable, | |
582 | .set_mode = tps65910_set_mode, | |
583 | .get_mode = tps65910_get_mode, | |
584 | .get_voltage = tps65910_get_voltage_vdd3, | |
585 | .list_voltage = tps65910_list_voltage, | |
586 | }; | |
587 | ||
588 | static struct regulator_ops tps65910_ops = { | |
589 | .is_enabled = tps65910_is_enabled, | |
590 | .enable = tps65910_enable, | |
591 | .disable = tps65910_disable, | |
592 | .set_mode = tps65910_set_mode, | |
593 | .get_mode = tps65910_get_mode, | |
594 | .get_voltage = tps65910_get_voltage, | |
595 | .set_voltage_sel = tps65910_set_voltage, | |
596 | .list_voltage = tps65910_list_voltage, | |
597 | }; | |
598 | ||
599 | static __devinit int tps65910_probe(struct platform_device *pdev) | |
600 | { | |
601 | struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); | |
602 | struct tps_info *info = tps65910_regs; | |
603 | struct regulator_init_data *reg_data; | |
604 | struct regulator_dev *rdev; | |
605 | struct tps65910_reg *pmic; | |
606 | struct tps65910_board *pmic_plat_data; | |
518fb721 GG |
607 | int i, err; |
608 | ||
609 | pmic_plat_data = dev_get_platdata(tps65910->dev); | |
610 | if (!pmic_plat_data) | |
611 | return -EINVAL; | |
612 | ||
613 | reg_data = pmic_plat_data->tps65910_pmic_init_data; | |
614 | ||
615 | pmic = kzalloc(sizeof(*pmic), GFP_KERNEL); | |
616 | if (!pmic) | |
617 | return -ENOMEM; | |
618 | ||
619 | mutex_init(&pmic->mutex); | |
620 | pmic->mfd = tps65910; | |
621 | platform_set_drvdata(pdev, pmic); | |
622 | ||
623 | /* Give control of all register to control port */ | |
624 | tps65910_set_bits(pmic->mfd, TPS65910_DEVCTRL, | |
625 | DEVCTRL_SR_CTL_I2C_SEL_MASK); | |
626 | ||
627 | for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) { | |
628 | /* Register the regulators */ | |
629 | pmic->info[i] = info; | |
630 | ||
631 | pmic->desc[i].name = info->name; | |
77fa44d0 | 632 | pmic->desc[i].id = i; |
518fb721 GG |
633 | pmic->desc[i].n_voltages = info->table_len; |
634 | ||
635 | if ((i == TPS65910_REG_VDD1) || (i == TPS65910_REG_VDD2)) | |
636 | pmic->desc[i].ops = &tps65910_ops_dcdc; | |
637 | else if (i == TPS65910_REG_VDD3) | |
638 | pmic->desc[i].ops = &tps65910_ops_vdd3; | |
639 | else | |
640 | pmic->desc[i].ops = &tps65910_ops; | |
641 | ||
642 | pmic->desc[i].type = REGULATOR_VOLTAGE; | |
643 | pmic->desc[i].owner = THIS_MODULE; | |
644 | ||
645 | rdev = regulator_register(&pmic->desc[i], | |
646 | tps65910->dev, reg_data, pmic); | |
647 | if (IS_ERR(rdev)) { | |
648 | dev_err(tps65910->dev, | |
649 | "failed to register %s regulator\n", | |
650 | pdev->name); | |
651 | err = PTR_ERR(rdev); | |
652 | goto err; | |
653 | } | |
654 | ||
655 | /* Save regulator for cleanup */ | |
656 | pmic->rdev[i] = rdev; | |
657 | } | |
658 | return 0; | |
659 | ||
660 | err: | |
661 | while (--i >= 0) | |
662 | regulator_unregister(pmic->rdev[i]); | |
663 | ||
664 | kfree(pmic); | |
665 | return err; | |
666 | } | |
667 | ||
668 | static int __devexit tps65910_remove(struct platform_device *pdev) | |
669 | { | |
670 | struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev); | |
671 | int i; | |
672 | ||
673 | for (i = 0; i < TPS65910_NUM_REGULATOR; i++) | |
674 | regulator_unregister(tps65910_reg->rdev[i]); | |
675 | ||
676 | kfree(tps65910_reg); | |
677 | return 0; | |
678 | } | |
679 | ||
680 | static struct platform_driver tps65910_driver = { | |
681 | .driver = { | |
682 | .name = "tps65910-pmic", | |
683 | .owner = THIS_MODULE, | |
684 | }, | |
685 | .probe = tps65910_probe, | |
686 | .remove = __devexit_p(tps65910_remove), | |
687 | }; | |
688 | ||
689 | static int __init tps65910_init(void) | |
690 | { | |
691 | return platform_driver_register(&tps65910_driver); | |
692 | } | |
693 | subsys_initcall(tps65910_init); | |
694 | ||
695 | static void __exit tps65910_cleanup(void) | |
696 | { | |
697 | platform_driver_unregister(&tps65910_driver); | |
698 | } | |
699 | module_exit(tps65910_cleanup); | |
700 | ||
701 | MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); | |
702 | MODULE_DESCRIPTION("TPS6507x voltage regulator driver"); | |
703 | MODULE_LICENSE("GPL v2"); | |
704 | MODULE_ALIAS("platform:tps65910-pmic"); |