blob: 058d2f2675e902c8d2856b83b3ee5a6b4c7c5503 [file] [log] [blame]
Cyril Chemparathy1394fd22010-12-07 12:04:11 -05001/*
2 * Regulator driver for TPS6524x PMIC
3 *
4 * Copyright (C) 2010 Texas Instruments
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
11 * whether express or implied; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/err.h>
19#include <linux/errno.h>
20#include <linux/slab.h>
21#include <linux/spi/spi.h>
22#include <linux/regulator/driver.h>
23#include <linux/regulator/machine.h>
24
25#define REG_LDO_SET 0x0
26#define LDO_ILIM_MASK 1 /* 0 = 400-800, 1 = 900-1500 */
27#define LDO_VSEL_MASK 0x0f
28#define LDO2_ILIM_SHIFT 12
29#define LDO2_VSEL_SHIFT 4
30#define LDO1_ILIM_SHIFT 8
31#define LDO1_VSEL_SHIFT 0
32
33#define REG_BLOCK_EN 0x1
34#define BLOCK_MASK 1
35#define BLOCK_LDO1_SHIFT 0
36#define BLOCK_LDO2_SHIFT 1
37#define BLOCK_LCD_SHIFT 2
38#define BLOCK_USB_SHIFT 3
39
40#define REG_DCDC_SET 0x2
41#define DCDC_VDCDC_MASK 0x1f
42#define DCDC_VDCDC1_SHIFT 0
43#define DCDC_VDCDC2_SHIFT 5
44#define DCDC_VDCDC3_SHIFT 10
45
46#define REG_DCDC_EN 0x3
47#define DCDCDCDC_EN_MASK 0x1
48#define DCDCDCDC1_EN_SHIFT 0
49#define DCDCDCDC1_PG_MSK BIT(1)
50#define DCDCDCDC2_EN_SHIFT 2
51#define DCDCDCDC2_PG_MSK BIT(3)
52#define DCDCDCDC3_EN_SHIFT 4
53#define DCDCDCDC3_PG_MSK BIT(5)
54
55#define REG_USB 0x4
56#define USB_ILIM_SHIFT 0
57#define USB_ILIM_MASK 0x3
58#define USB_TSD_SHIFT 2
59#define USB_TSD_MASK 0x3
60#define USB_TWARN_SHIFT 4
61#define USB_TWARN_MASK 0x3
62#define USB_IWARN_SD BIT(6)
63#define USB_FAST_LOOP BIT(7)
64
65#define REG_ALARM 0x5
66#define ALARM_LDO1 BIT(0)
67#define ALARM_DCDC1 BIT(1)
68#define ALARM_DCDC2 BIT(2)
69#define ALARM_DCDC3 BIT(3)
70#define ALARM_LDO2 BIT(4)
71#define ALARM_USB_WARN BIT(5)
72#define ALARM_USB_ALARM BIT(6)
73#define ALARM_LCD BIT(9)
74#define ALARM_TEMP_WARM BIT(10)
75#define ALARM_TEMP_HOT BIT(11)
76#define ALARM_NRST BIT(14)
77#define ALARM_POWERUP BIT(15)
78
79#define REG_INT_ENABLE 0x6
80#define INT_LDO1 BIT(0)
81#define INT_DCDC1 BIT(1)
82#define INT_DCDC2 BIT(2)
83#define INT_DCDC3 BIT(3)
84#define INT_LDO2 BIT(4)
85#define INT_USB_WARN BIT(5)
86#define INT_USB_ALARM BIT(6)
87#define INT_LCD BIT(9)
88#define INT_TEMP_WARM BIT(10)
89#define INT_TEMP_HOT BIT(11)
90#define INT_GLOBAL_EN BIT(15)
91
92#define REG_INT_STATUS 0x7
93#define STATUS_LDO1 BIT(0)
94#define STATUS_DCDC1 BIT(1)
95#define STATUS_DCDC2 BIT(2)
96#define STATUS_DCDC3 BIT(3)
97#define STATUS_LDO2 BIT(4)
98#define STATUS_USB_WARN BIT(5)
99#define STATUS_USB_ALARM BIT(6)
100#define STATUS_LCD BIT(9)
101#define STATUS_TEMP_WARM BIT(10)
102#define STATUS_TEMP_HOT BIT(11)
103
104#define REG_SOFTWARE_RESET 0xb
105#define REG_WRITE_ENABLE 0xd
106#define REG_REV_ID 0xf
107
108#define N_DCDC 3
109#define N_LDO 2
110#define N_SWITCH 2
Axel Lin4d984d12012-03-09 11:37:30 +0800111#define N_REGULATORS (N_DCDC + N_LDO + N_SWITCH)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500112
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500113#define CMD_READ(reg) ((reg) << 6)
114#define CMD_WRITE(reg) (BIT(5) | (reg) << 6)
115#define STAT_CLK BIT(3)
116#define STAT_WRITE BIT(2)
117#define STAT_INVALID BIT(1)
118#define STAT_WP BIT(0)
119
120struct field {
121 int reg;
122 int shift;
123 int mask;
124};
125
126struct supply_info {
127 const char *name;
128 int n_voltages;
Axel Lincac87fd2012-06-20 22:30:15 +0800129 const unsigned int *voltages;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500130 int n_ilimsels;
Axel Lin1e12dfc2012-06-20 22:32:08 +0800131 const unsigned int *ilimsels;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500132 struct field enable, voltage, ilimsel;
133};
134
135struct tps6524x {
136 struct device *dev;
137 struct spi_device *spi;
138 struct mutex lock;
139 struct regulator_desc desc[N_REGULATORS];
140 struct regulator_dev *rdev[N_REGULATORS];
141};
142
143static int __read_reg(struct tps6524x *hw, int reg)
144{
145 int error = 0;
146 u16 cmd = CMD_READ(reg), in;
147 u8 status;
148 struct spi_message m;
149 struct spi_transfer t[3];
150
151 spi_message_init(&m);
152 memset(t, 0, sizeof(t));
153
154 t[0].tx_buf = &cmd;
155 t[0].len = 2;
156 t[0].bits_per_word = 12;
157 spi_message_add_tail(&t[0], &m);
158
159 t[1].rx_buf = &in;
160 t[1].len = 2;
161 t[1].bits_per_word = 16;
162 spi_message_add_tail(&t[1], &m);
163
164 t[2].rx_buf = &status;
165 t[2].len = 1;
166 t[2].bits_per_word = 4;
167 spi_message_add_tail(&t[2], &m);
168
169 error = spi_sync(hw->spi, &m);
170 if (error < 0)
171 return error;
172
173 dev_dbg(hw->dev, "read reg %d, data %x, status %x\n",
174 reg, in, status);
175
176 if (!(status & STAT_CLK) || (status & STAT_WRITE))
177 return -EIO;
178
179 if (status & STAT_INVALID)
180 return -EINVAL;
181
182 return in;
183}
184
185static int read_reg(struct tps6524x *hw, int reg)
186{
187 int ret;
188
189 mutex_lock(&hw->lock);
190 ret = __read_reg(hw, reg);
191 mutex_unlock(&hw->lock);
192
193 return ret;
194}
195
196static int __write_reg(struct tps6524x *hw, int reg, int val)
197{
198 int error = 0;
199 u16 cmd = CMD_WRITE(reg), out = val;
200 u8 status;
201 struct spi_message m;
202 struct spi_transfer t[3];
203
204 spi_message_init(&m);
205 memset(t, 0, sizeof(t));
206
207 t[0].tx_buf = &cmd;
208 t[0].len = 2;
209 t[0].bits_per_word = 12;
210 spi_message_add_tail(&t[0], &m);
211
212 t[1].tx_buf = &out;
213 t[1].len = 2;
214 t[1].bits_per_word = 16;
215 spi_message_add_tail(&t[1], &m);
216
217 t[2].rx_buf = &status;
218 t[2].len = 1;
219 t[2].bits_per_word = 4;
220 spi_message_add_tail(&t[2], &m);
221
222 error = spi_sync(hw->spi, &m);
223 if (error < 0)
224 return error;
225
226 dev_dbg(hw->dev, "wrote reg %d, data %x, status %x\n",
227 reg, out, status);
228
229 if (!(status & STAT_CLK) || !(status & STAT_WRITE))
230 return -EIO;
231
232 if (status & (STAT_INVALID | STAT_WP))
233 return -EINVAL;
234
235 return error;
236}
237
238static int __rmw_reg(struct tps6524x *hw, int reg, int mask, int val)
239{
240 int ret;
241
242 ret = __read_reg(hw, reg);
243 if (ret < 0)
244 return ret;
245
246 ret &= ~mask;
247 ret |= val;
248
249 ret = __write_reg(hw, reg, ret);
250
251 return (ret < 0) ? ret : 0;
252}
253
254static int rmw_protect(struct tps6524x *hw, int reg, int mask, int val)
255{
256 int ret;
257
258 mutex_lock(&hw->lock);
259
260 ret = __write_reg(hw, REG_WRITE_ENABLE, 1);
261 if (ret) {
262 dev_err(hw->dev, "failed to set write enable\n");
263 goto error;
264 }
265
266 ret = __rmw_reg(hw, reg, mask, val);
267 if (ret)
268 dev_err(hw->dev, "failed to rmw register %d\n", reg);
269
270 ret = __write_reg(hw, REG_WRITE_ENABLE, 0);
271 if (ret) {
272 dev_err(hw->dev, "failed to clear write enable\n");
273 goto error;
274 }
275
276error:
277 mutex_unlock(&hw->lock);
278
279 return ret;
280}
281
282static int read_field(struct tps6524x *hw, const struct field *field)
283{
284 int tmp;
285
286 tmp = read_reg(hw, field->reg);
287 if (tmp < 0)
288 return tmp;
289
290 return (tmp >> field->shift) & field->mask;
291}
292
293static int write_field(struct tps6524x *hw, const struct field *field,
294 int val)
295{
296 if (val & ~field->mask)
297 return -EOVERFLOW;
298
299 return rmw_protect(hw, field->reg,
300 field->mask << field->shift,
301 val << field->shift);
302}
303
Axel Lincac87fd2012-06-20 22:30:15 +0800304static const unsigned int dcdc1_voltages[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500305 800000, 825000, 850000, 875000,
306 900000, 925000, 950000, 975000,
307 1000000, 1025000, 1050000, 1075000,
308 1100000, 1125000, 1150000, 1175000,
309 1200000, 1225000, 1250000, 1275000,
310 1300000, 1325000, 1350000, 1375000,
311 1400000, 1425000, 1450000, 1475000,
312 1500000, 1525000, 1550000, 1575000,
313};
314
Axel Lincac87fd2012-06-20 22:30:15 +0800315static const unsigned int dcdc2_voltages[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500316 1400000, 1450000, 1500000, 1550000,
317 1600000, 1650000, 1700000, 1750000,
318 1800000, 1850000, 1900000, 1950000,
319 2000000, 2050000, 2100000, 2150000,
320 2200000, 2250000, 2300000, 2350000,
321 2400000, 2450000, 2500000, 2550000,
322 2600000, 2650000, 2700000, 2750000,
323 2800000, 2850000, 2900000, 2950000,
324};
325
Axel Lincac87fd2012-06-20 22:30:15 +0800326static const unsigned int dcdc3_voltages[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500327 2400000, 2450000, 2500000, 2550000, 2600000,
328 2650000, 2700000, 2750000, 2800000, 2850000,
329 2900000, 2950000, 3000000, 3050000, 3100000,
330 3150000, 3200000, 3250000, 3300000, 3350000,
331 3400000, 3450000, 3500000, 3550000, 3600000,
332};
333
Axel Lincac87fd2012-06-20 22:30:15 +0800334static const unsigned int ldo1_voltages[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500335 4300000, 4350000, 4400000, 4450000,
336 4500000, 4550000, 4600000, 4650000,
337 4700000, 4750000, 4800000, 4850000,
338 4900000, 4950000, 5000000, 5050000,
339};
340
Axel Lincac87fd2012-06-20 22:30:15 +0800341static const unsigned int ldo2_voltages[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500342 1100000, 1150000, 1200000, 1250000,
343 1300000, 1700000, 1750000, 1800000,
344 1850000, 1900000, 3150000, 3200000,
345 3250000, 3300000, 3350000, 3400000,
346};
347
Axel Lincac87fd2012-06-20 22:30:15 +0800348static const unsigned int fixed_5000000_voltage[] = {
349 5000000
350};
351
Axel Lin1e12dfc2012-06-20 22:32:08 +0800352static const unsigned int ldo_ilimsel[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500353 400000, 1500000
354};
355
Axel Lin1e12dfc2012-06-20 22:32:08 +0800356static const unsigned int usb_ilimsel[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500357 200000, 400000, 800000, 1000000
358};
359
Axel Lin1e12dfc2012-06-20 22:32:08 +0800360static const unsigned int fixed_2400000_ilimsel[] = {
361 2400000
362};
363
364static const unsigned int fixed_1200000_ilimsel[] = {
365 1200000
366};
367
368static const unsigned int fixed_400000_ilimsel[] = {
369 400000
370};
371
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500372#define __MK_FIELD(_reg, _mask, _shift) \
373 { .reg = (_reg), .mask = (_mask), .shift = (_shift), }
374
375static const struct supply_info supply_info[N_REGULATORS] = {
376 {
377 .name = "DCDC1",
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500378 .n_voltages = ARRAY_SIZE(dcdc1_voltages),
379 .voltages = dcdc1_voltages,
Axel Lin1e12dfc2012-06-20 22:32:08 +0800380 .n_ilimsels = ARRAY_SIZE(fixed_2400000_ilimsel),
381 .ilimsels = fixed_2400000_ilimsel,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500382 .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
383 DCDCDCDC1_EN_SHIFT),
384 .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
385 DCDC_VDCDC1_SHIFT),
386 },
387 {
388 .name = "DCDC2",
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500389 .n_voltages = ARRAY_SIZE(dcdc2_voltages),
390 .voltages = dcdc2_voltages,
Axel Lin1e12dfc2012-06-20 22:32:08 +0800391 .n_ilimsels = ARRAY_SIZE(fixed_1200000_ilimsel),
392 .ilimsels = fixed_1200000_ilimsel,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500393 .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
394 DCDCDCDC2_EN_SHIFT),
395 .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
396 DCDC_VDCDC2_SHIFT),
397 },
398 {
399 .name = "DCDC3",
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500400 .n_voltages = ARRAY_SIZE(dcdc3_voltages),
401 .voltages = dcdc3_voltages,
Axel Lin1e12dfc2012-06-20 22:32:08 +0800402 .n_ilimsels = ARRAY_SIZE(fixed_1200000_ilimsel),
403 .ilimsels = fixed_1200000_ilimsel,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500404 .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
405 DCDCDCDC3_EN_SHIFT),
406 .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
407 DCDC_VDCDC3_SHIFT),
408 },
409 {
410 .name = "LDO1",
411 .n_voltages = ARRAY_SIZE(ldo1_voltages),
412 .voltages = ldo1_voltages,
413 .n_ilimsels = ARRAY_SIZE(ldo_ilimsel),
414 .ilimsels = ldo_ilimsel,
415 .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
416 BLOCK_LDO1_SHIFT),
417 .voltage = __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK,
418 LDO1_VSEL_SHIFT),
419 .ilimsel = __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK,
420 LDO1_ILIM_SHIFT),
421 },
422 {
423 .name = "LDO2",
424 .n_voltages = ARRAY_SIZE(ldo2_voltages),
425 .voltages = ldo2_voltages,
426 .n_ilimsels = ARRAY_SIZE(ldo_ilimsel),
427 .ilimsels = ldo_ilimsel,
428 .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
429 BLOCK_LDO2_SHIFT),
430 .voltage = __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK,
431 LDO2_VSEL_SHIFT),
432 .ilimsel = __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK,
433 LDO2_ILIM_SHIFT),
434 },
435 {
436 .name = "USB",
Axel Lincac87fd2012-06-20 22:30:15 +0800437 .n_voltages = ARRAY_SIZE(fixed_5000000_voltage),
438 .voltages = fixed_5000000_voltage,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500439 .n_ilimsels = ARRAY_SIZE(usb_ilimsel),
440 .ilimsels = usb_ilimsel,
441 .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
442 BLOCK_USB_SHIFT),
443 .ilimsel = __MK_FIELD(REG_USB, USB_ILIM_MASK,
444 USB_ILIM_SHIFT),
445 },
446 {
447 .name = "LCD",
Axel Lincac87fd2012-06-20 22:30:15 +0800448 .n_voltages = ARRAY_SIZE(fixed_5000000_voltage),
449 .voltages = fixed_5000000_voltage,
Axel Lin1e12dfc2012-06-20 22:32:08 +0800450 .n_ilimsels = ARRAY_SIZE(fixed_400000_ilimsel),
451 .ilimsels = fixed_400000_ilimsel,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500452 .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
453 BLOCK_LCD_SHIFT),
454 },
455};
456
Axel Linf8ee3392012-03-28 19:45:43 +0800457static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500458{
459 const struct supply_info *info;
460 struct tps6524x *hw;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500461
462 hw = rdev_get_drvdata(rdev);
463 info = &supply_info[rdev_get_id(rdev)];
464
Axel Lincac87fd2012-06-20 22:30:15 +0800465 if (rdev->desc->n_voltages == 1)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500466 return -EINVAL;
467
Axel Linf8ee3392012-03-28 19:45:43 +0800468 return write_field(hw, &info->voltage, selector);
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500469}
470
Axel Lin4af7c1d2012-03-28 19:46:39 +0800471static int get_voltage_sel(struct regulator_dev *rdev)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500472{
473 const struct supply_info *info;
474 struct tps6524x *hw;
475 int ret;
476
477 hw = rdev_get_drvdata(rdev);
478 info = &supply_info[rdev_get_id(rdev)];
479
Axel Lincac87fd2012-06-20 22:30:15 +0800480 if (rdev->desc->n_voltages == 1)
Axel Lin8386a002012-06-14 16:00:53 +0800481 return 0;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500482
483 ret = read_field(hw, &info->voltage);
484 if (ret < 0)
485 return ret;
486 if (WARN_ON(ret >= info->n_voltages))
487 return -EIO;
488
Axel Lin4af7c1d2012-03-28 19:46:39 +0800489 return ret;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500490}
491
492static int set_current_limit(struct regulator_dev *rdev, int min_uA,
493 int max_uA)
494{
495 const struct supply_info *info;
496 struct tps6524x *hw;
497 int i;
498
499 hw = rdev_get_drvdata(rdev);
500 info = &supply_info[rdev_get_id(rdev)];
501
Axel Lin1e12dfc2012-06-20 22:32:08 +0800502 if (info->n_ilimsels == 1)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500503 return -EINVAL;
504
Axel Lin73f4f3d2012-08-08 20:21:30 +0800505 for (i = info->n_ilimsels - 1; i >= 0; i--) {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500506 if (min_uA <= info->ilimsels[i] &&
507 max_uA >= info->ilimsels[i])
Axel Lin73f4f3d2012-08-08 20:21:30 +0800508 return write_field(hw, &info->ilimsel, i);
509 }
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500510
Axel Lin73f4f3d2012-08-08 20:21:30 +0800511 return -EINVAL;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500512}
513
514static int get_current_limit(struct regulator_dev *rdev)
515{
516 const struct supply_info *info;
517 struct tps6524x *hw;
518 int ret;
519
520 hw = rdev_get_drvdata(rdev);
521 info = &supply_info[rdev_get_id(rdev)];
522
Axel Lin1e12dfc2012-06-20 22:32:08 +0800523 if (info->n_ilimsels == 1)
524 return info->ilimsels[0];
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500525
526 ret = read_field(hw, &info->ilimsel);
527 if (ret < 0)
528 return ret;
529 if (WARN_ON(ret >= info->n_ilimsels))
530 return -EIO;
531
532 return info->ilimsels[ret];
533}
534
535static int enable_supply(struct regulator_dev *rdev)
536{
537 const struct supply_info *info;
538 struct tps6524x *hw;
539
540 hw = rdev_get_drvdata(rdev);
541 info = &supply_info[rdev_get_id(rdev)];
542
543 return write_field(hw, &info->enable, 1);
544}
545
546static int disable_supply(struct regulator_dev *rdev)
547{
548 const struct supply_info *info;
549 struct tps6524x *hw;
550
551 hw = rdev_get_drvdata(rdev);
552 info = &supply_info[rdev_get_id(rdev)];
553
554 return write_field(hw, &info->enable, 0);
555}
556
557static int is_supply_enabled(struct regulator_dev *rdev)
558{
559 const struct supply_info *info;
560 struct tps6524x *hw;
561
562 hw = rdev_get_drvdata(rdev);
563 info = &supply_info[rdev_get_id(rdev)];
564
565 return read_field(hw, &info->enable);
566}
567
568static struct regulator_ops regulator_ops = {
569 .is_enabled = is_supply_enabled,
570 .enable = enable_supply,
571 .disable = disable_supply,
Axel Lin4af7c1d2012-03-28 19:46:39 +0800572 .get_voltage_sel = get_voltage_sel,
Axel Linf8ee3392012-03-28 19:45:43 +0800573 .set_voltage_sel = set_voltage_sel,
Axel Lincac87fd2012-06-20 22:30:15 +0800574 .list_voltage = regulator_list_voltage_table,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500575 .set_current_limit = set_current_limit,
576 .get_current_limit = get_current_limit,
577};
578
Randy Dunlap5362b092011-03-24 13:30:59 -0700579static int pmic_remove(struct spi_device *spi)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500580{
581 struct tps6524x *hw = spi_get_drvdata(spi);
582 int i;
583
584 if (!hw)
585 return 0;
586 for (i = 0; i < N_REGULATORS; i++) {
587 if (hw->rdev[i])
588 regulator_unregister(hw->rdev[i]);
589 hw->rdev[i] = NULL;
590 }
591 spi_set_drvdata(spi, NULL);
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500592 return 0;
593}
594
595static int __devinit pmic_probe(struct spi_device *spi)
596{
597 struct tps6524x *hw;
598 struct device *dev = &spi->dev;
599 const struct supply_info *info = supply_info;
600 struct regulator_init_data *init_data;
Mark Brownc1727082012-04-04 00:50:22 +0100601 struct regulator_config config = { };
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500602 int ret = 0, i;
603
604 init_data = dev->platform_data;
605 if (!init_data) {
606 dev_err(dev, "could not find regulator platform data\n");
607 return -EINVAL;
608 }
609
Axel Lin9eb0c422012-04-11 14:40:18 +0800610 hw = devm_kzalloc(&spi->dev, sizeof(struct tps6524x), GFP_KERNEL);
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500611 if (!hw) {
612 dev_err(dev, "cannot allocate regulator private data\n");
613 return -ENOMEM;
614 }
615 spi_set_drvdata(spi, hw);
616
617 memset(hw, 0, sizeof(struct tps6524x));
618 hw->dev = dev;
619 hw->spi = spi_dev_get(spi);
620 mutex_init(&hw->lock);
621
622 for (i = 0; i < N_REGULATORS; i++, info++, init_data++) {
623 hw->desc[i].name = info->name;
624 hw->desc[i].id = i;
625 hw->desc[i].n_voltages = info->n_voltages;
Axel Lincac87fd2012-06-20 22:30:15 +0800626 hw->desc[i].volt_table = info->voltages;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500627 hw->desc[i].ops = &regulator_ops;
628 hw->desc[i].type = REGULATOR_VOLTAGE;
629 hw->desc[i].owner = THIS_MODULE;
630
Mark Brownc1727082012-04-04 00:50:22 +0100631 config.dev = dev;
632 config.init_data = init_data;
633 config.driver_data = hw;
634
635 hw->rdev[i] = regulator_register(&hw->desc[i], &config);
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500636 if (IS_ERR(hw->rdev[i])) {
637 ret = PTR_ERR(hw->rdev[i]);
638 hw->rdev[i] = NULL;
639 goto fail;
640 }
641 }
642
643 return 0;
644
645fail:
646 pmic_remove(spi);
647 return ret;
648}
649
650static struct spi_driver pmic_driver = {
651 .probe = pmic_probe,
652 .remove = __devexit_p(pmic_remove),
653 .driver = {
654 .name = "tps6524x",
655 .owner = THIS_MODULE,
656 },
657};
658
Mark Brown173f24d2012-04-04 00:34:23 +0100659module_spi_driver(pmic_driver);
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500660
661MODULE_DESCRIPTION("TPS6524X PMIC Driver");
662MODULE_AUTHOR("Cyril Chemparathy");
663MODULE_LICENSE("GPL");
664MODULE_ALIAS("spi:tps6524x");