blob: 740aeccdfb1ff53d0c0a77e685f9031b451eac0d [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];
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500140};
141
142static int __read_reg(struct tps6524x *hw, int reg)
143{
144 int error = 0;
145 u16 cmd = CMD_READ(reg), in;
146 u8 status;
147 struct spi_message m;
148 struct spi_transfer t[3];
149
150 spi_message_init(&m);
151 memset(t, 0, sizeof(t));
152
153 t[0].tx_buf = &cmd;
154 t[0].len = 2;
155 t[0].bits_per_word = 12;
156 spi_message_add_tail(&t[0], &m);
157
158 t[1].rx_buf = &in;
159 t[1].len = 2;
160 t[1].bits_per_word = 16;
161 spi_message_add_tail(&t[1], &m);
162
163 t[2].rx_buf = &status;
164 t[2].len = 1;
165 t[2].bits_per_word = 4;
166 spi_message_add_tail(&t[2], &m);
167
168 error = spi_sync(hw->spi, &m);
169 if (error < 0)
170 return error;
171
172 dev_dbg(hw->dev, "read reg %d, data %x, status %x\n",
173 reg, in, status);
174
175 if (!(status & STAT_CLK) || (status & STAT_WRITE))
176 return -EIO;
177
178 if (status & STAT_INVALID)
179 return -EINVAL;
180
181 return in;
182}
183
184static int read_reg(struct tps6524x *hw, int reg)
185{
186 int ret;
187
188 mutex_lock(&hw->lock);
189 ret = __read_reg(hw, reg);
190 mutex_unlock(&hw->lock);
191
192 return ret;
193}
194
195static int __write_reg(struct tps6524x *hw, int reg, int val)
196{
197 int error = 0;
198 u16 cmd = CMD_WRITE(reg), out = val;
199 u8 status;
200 struct spi_message m;
201 struct spi_transfer t[3];
202
203 spi_message_init(&m);
204 memset(t, 0, sizeof(t));
205
206 t[0].tx_buf = &cmd;
207 t[0].len = 2;
208 t[0].bits_per_word = 12;
209 spi_message_add_tail(&t[0], &m);
210
211 t[1].tx_buf = &out;
212 t[1].len = 2;
213 t[1].bits_per_word = 16;
214 spi_message_add_tail(&t[1], &m);
215
216 t[2].rx_buf = &status;
217 t[2].len = 1;
218 t[2].bits_per_word = 4;
219 spi_message_add_tail(&t[2], &m);
220
221 error = spi_sync(hw->spi, &m);
222 if (error < 0)
223 return error;
224
225 dev_dbg(hw->dev, "wrote reg %d, data %x, status %x\n",
226 reg, out, status);
227
228 if (!(status & STAT_CLK) || !(status & STAT_WRITE))
229 return -EIO;
230
231 if (status & (STAT_INVALID | STAT_WP))
232 return -EINVAL;
233
234 return error;
235}
236
237static int __rmw_reg(struct tps6524x *hw, int reg, int mask, int val)
238{
239 int ret;
240
241 ret = __read_reg(hw, reg);
242 if (ret < 0)
243 return ret;
244
245 ret &= ~mask;
246 ret |= val;
247
248 ret = __write_reg(hw, reg, ret);
249
250 return (ret < 0) ? ret : 0;
251}
252
253static int rmw_protect(struct tps6524x *hw, int reg, int mask, int val)
254{
255 int ret;
256
257 mutex_lock(&hw->lock);
258
259 ret = __write_reg(hw, REG_WRITE_ENABLE, 1);
260 if (ret) {
261 dev_err(hw->dev, "failed to set write enable\n");
262 goto error;
263 }
264
265 ret = __rmw_reg(hw, reg, mask, val);
266 if (ret)
267 dev_err(hw->dev, "failed to rmw register %d\n", reg);
268
269 ret = __write_reg(hw, REG_WRITE_ENABLE, 0);
270 if (ret) {
271 dev_err(hw->dev, "failed to clear write enable\n");
272 goto error;
273 }
274
275error:
276 mutex_unlock(&hw->lock);
277
278 return ret;
279}
280
281static int read_field(struct tps6524x *hw, const struct field *field)
282{
283 int tmp;
284
285 tmp = read_reg(hw, field->reg);
286 if (tmp < 0)
287 return tmp;
288
289 return (tmp >> field->shift) & field->mask;
290}
291
292static int write_field(struct tps6524x *hw, const struct field *field,
293 int val)
294{
295 if (val & ~field->mask)
296 return -EOVERFLOW;
297
298 return rmw_protect(hw, field->reg,
299 field->mask << field->shift,
300 val << field->shift);
301}
302
Axel Lincac87fd2012-06-20 22:30:15 +0800303static const unsigned int dcdc1_voltages[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500304 800000, 825000, 850000, 875000,
305 900000, 925000, 950000, 975000,
306 1000000, 1025000, 1050000, 1075000,
307 1100000, 1125000, 1150000, 1175000,
308 1200000, 1225000, 1250000, 1275000,
309 1300000, 1325000, 1350000, 1375000,
310 1400000, 1425000, 1450000, 1475000,
311 1500000, 1525000, 1550000, 1575000,
312};
313
Axel Lincac87fd2012-06-20 22:30:15 +0800314static const unsigned int dcdc2_voltages[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500315 1400000, 1450000, 1500000, 1550000,
316 1600000, 1650000, 1700000, 1750000,
317 1800000, 1850000, 1900000, 1950000,
318 2000000, 2050000, 2100000, 2150000,
319 2200000, 2250000, 2300000, 2350000,
320 2400000, 2450000, 2500000, 2550000,
321 2600000, 2650000, 2700000, 2750000,
322 2800000, 2850000, 2900000, 2950000,
323};
324
Axel Lincac87fd2012-06-20 22:30:15 +0800325static const unsigned int dcdc3_voltages[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500326 2400000, 2450000, 2500000, 2550000, 2600000,
327 2650000, 2700000, 2750000, 2800000, 2850000,
328 2900000, 2950000, 3000000, 3050000, 3100000,
329 3150000, 3200000, 3250000, 3300000, 3350000,
330 3400000, 3450000, 3500000, 3550000, 3600000,
331};
332
Axel Lincac87fd2012-06-20 22:30:15 +0800333static const unsigned int ldo1_voltages[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500334 4300000, 4350000, 4400000, 4450000,
335 4500000, 4550000, 4600000, 4650000,
336 4700000, 4750000, 4800000, 4850000,
337 4900000, 4950000, 5000000, 5050000,
338};
339
Axel Lincac87fd2012-06-20 22:30:15 +0800340static const unsigned int ldo2_voltages[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500341 1100000, 1150000, 1200000, 1250000,
342 1300000, 1700000, 1750000, 1800000,
343 1850000, 1900000, 3150000, 3200000,
344 3250000, 3300000, 3350000, 3400000,
345};
346
Axel Lincac87fd2012-06-20 22:30:15 +0800347static const unsigned int fixed_5000000_voltage[] = {
348 5000000
349};
350
Axel Lin1e12dfc2012-06-20 22:32:08 +0800351static const unsigned int ldo_ilimsel[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500352 400000, 1500000
353};
354
Axel Lin1e12dfc2012-06-20 22:32:08 +0800355static const unsigned int usb_ilimsel[] = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500356 200000, 400000, 800000, 1000000
357};
358
Axel Lin1e12dfc2012-06-20 22:32:08 +0800359static const unsigned int fixed_2400000_ilimsel[] = {
360 2400000
361};
362
363static const unsigned int fixed_1200000_ilimsel[] = {
364 1200000
365};
366
367static const unsigned int fixed_400000_ilimsel[] = {
368 400000
369};
370
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500371#define __MK_FIELD(_reg, _mask, _shift) \
372 { .reg = (_reg), .mask = (_mask), .shift = (_shift), }
373
374static const struct supply_info supply_info[N_REGULATORS] = {
375 {
376 .name = "DCDC1",
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500377 .n_voltages = ARRAY_SIZE(dcdc1_voltages),
378 .voltages = dcdc1_voltages,
Axel Lin1e12dfc2012-06-20 22:32:08 +0800379 .n_ilimsels = ARRAY_SIZE(fixed_2400000_ilimsel),
380 .ilimsels = fixed_2400000_ilimsel,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500381 .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
382 DCDCDCDC1_EN_SHIFT),
383 .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
384 DCDC_VDCDC1_SHIFT),
385 },
386 {
387 .name = "DCDC2",
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500388 .n_voltages = ARRAY_SIZE(dcdc2_voltages),
389 .voltages = dcdc2_voltages,
Axel Lin1e12dfc2012-06-20 22:32:08 +0800390 .n_ilimsels = ARRAY_SIZE(fixed_1200000_ilimsel),
391 .ilimsels = fixed_1200000_ilimsel,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500392 .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
393 DCDCDCDC2_EN_SHIFT),
394 .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
395 DCDC_VDCDC2_SHIFT),
396 },
397 {
398 .name = "DCDC3",
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500399 .n_voltages = ARRAY_SIZE(dcdc3_voltages),
400 .voltages = dcdc3_voltages,
Axel Lin1e12dfc2012-06-20 22:32:08 +0800401 .n_ilimsels = ARRAY_SIZE(fixed_1200000_ilimsel),
402 .ilimsels = fixed_1200000_ilimsel,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500403 .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
404 DCDCDCDC3_EN_SHIFT),
405 .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
406 DCDC_VDCDC3_SHIFT),
407 },
408 {
409 .name = "LDO1",
410 .n_voltages = ARRAY_SIZE(ldo1_voltages),
411 .voltages = ldo1_voltages,
412 .n_ilimsels = ARRAY_SIZE(ldo_ilimsel),
413 .ilimsels = ldo_ilimsel,
414 .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
415 BLOCK_LDO1_SHIFT),
416 .voltage = __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK,
417 LDO1_VSEL_SHIFT),
418 .ilimsel = __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK,
419 LDO1_ILIM_SHIFT),
420 },
421 {
422 .name = "LDO2",
423 .n_voltages = ARRAY_SIZE(ldo2_voltages),
424 .voltages = ldo2_voltages,
425 .n_ilimsels = ARRAY_SIZE(ldo_ilimsel),
426 .ilimsels = ldo_ilimsel,
427 .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
428 BLOCK_LDO2_SHIFT),
429 .voltage = __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK,
430 LDO2_VSEL_SHIFT),
431 .ilimsel = __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK,
432 LDO2_ILIM_SHIFT),
433 },
434 {
435 .name = "USB",
Axel Lincac87fd2012-06-20 22:30:15 +0800436 .n_voltages = ARRAY_SIZE(fixed_5000000_voltage),
437 .voltages = fixed_5000000_voltage,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500438 .n_ilimsels = ARRAY_SIZE(usb_ilimsel),
439 .ilimsels = usb_ilimsel,
440 .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
441 BLOCK_USB_SHIFT),
442 .ilimsel = __MK_FIELD(REG_USB, USB_ILIM_MASK,
443 USB_ILIM_SHIFT),
444 },
445 {
446 .name = "LCD",
Axel Lincac87fd2012-06-20 22:30:15 +0800447 .n_voltages = ARRAY_SIZE(fixed_5000000_voltage),
448 .voltages = fixed_5000000_voltage,
Axel Lin1e12dfc2012-06-20 22:32:08 +0800449 .n_ilimsels = ARRAY_SIZE(fixed_400000_ilimsel),
450 .ilimsels = fixed_400000_ilimsel,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500451 .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
452 BLOCK_LCD_SHIFT),
453 },
454};
455
Axel Linf8ee3392012-03-28 19:45:43 +0800456static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500457{
458 const struct supply_info *info;
459 struct tps6524x *hw;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500460
461 hw = rdev_get_drvdata(rdev);
462 info = &supply_info[rdev_get_id(rdev)];
463
Axel Lincac87fd2012-06-20 22:30:15 +0800464 if (rdev->desc->n_voltages == 1)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500465 return -EINVAL;
466
Axel Linf8ee3392012-03-28 19:45:43 +0800467 return write_field(hw, &info->voltage, selector);
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500468}
469
Axel Lin4af7c1d2012-03-28 19:46:39 +0800470static int get_voltage_sel(struct regulator_dev *rdev)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500471{
472 const struct supply_info *info;
473 struct tps6524x *hw;
474 int ret;
475
476 hw = rdev_get_drvdata(rdev);
477 info = &supply_info[rdev_get_id(rdev)];
478
Axel Lincac87fd2012-06-20 22:30:15 +0800479 if (rdev->desc->n_voltages == 1)
Axel Lin8386a002012-06-14 16:00:53 +0800480 return 0;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500481
482 ret = read_field(hw, &info->voltage);
483 if (ret < 0)
484 return ret;
485 if (WARN_ON(ret >= info->n_voltages))
486 return -EIO;
487
Axel Lin4af7c1d2012-03-28 19:46:39 +0800488 return ret;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500489}
490
491static int set_current_limit(struct regulator_dev *rdev, int min_uA,
492 int max_uA)
493{
494 const struct supply_info *info;
495 struct tps6524x *hw;
496 int i;
497
498 hw = rdev_get_drvdata(rdev);
499 info = &supply_info[rdev_get_id(rdev)];
500
Axel Lin1e12dfc2012-06-20 22:32:08 +0800501 if (info->n_ilimsels == 1)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500502 return -EINVAL;
503
Axel Lin73f4f3d2012-08-08 20:21:30 +0800504 for (i = info->n_ilimsels - 1; i >= 0; i--) {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500505 if (min_uA <= info->ilimsels[i] &&
506 max_uA >= info->ilimsels[i])
Axel Lin73f4f3d2012-08-08 20:21:30 +0800507 return write_field(hw, &info->ilimsel, i);
508 }
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500509
Axel Lin73f4f3d2012-08-08 20:21:30 +0800510 return -EINVAL;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500511}
512
513static int get_current_limit(struct regulator_dev *rdev)
514{
515 const struct supply_info *info;
516 struct tps6524x *hw;
517 int ret;
518
519 hw = rdev_get_drvdata(rdev);
520 info = &supply_info[rdev_get_id(rdev)];
521
Axel Lin1e12dfc2012-06-20 22:32:08 +0800522 if (info->n_ilimsels == 1)
523 return info->ilimsels[0];
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500524
525 ret = read_field(hw, &info->ilimsel);
526 if (ret < 0)
527 return ret;
528 if (WARN_ON(ret >= info->n_ilimsels))
529 return -EIO;
530
531 return info->ilimsels[ret];
532}
533
534static int enable_supply(struct regulator_dev *rdev)
535{
536 const struct supply_info *info;
537 struct tps6524x *hw;
538
539 hw = rdev_get_drvdata(rdev);
540 info = &supply_info[rdev_get_id(rdev)];
541
542 return write_field(hw, &info->enable, 1);
543}
544
545static int disable_supply(struct regulator_dev *rdev)
546{
547 const struct supply_info *info;
548 struct tps6524x *hw;
549
550 hw = rdev_get_drvdata(rdev);
551 info = &supply_info[rdev_get_id(rdev)];
552
553 return write_field(hw, &info->enable, 0);
554}
555
556static int is_supply_enabled(struct regulator_dev *rdev)
557{
558 const struct supply_info *info;
559 struct tps6524x *hw;
560
561 hw = rdev_get_drvdata(rdev);
562 info = &supply_info[rdev_get_id(rdev)];
563
564 return read_field(hw, &info->enable);
565}
566
Axel Lin357db022019-04-13 15:30:01 +0800567static const struct regulator_ops regulator_ops = {
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500568 .is_enabled = is_supply_enabled,
569 .enable = enable_supply,
570 .disable = disable_supply,
Axel Lin4af7c1d2012-03-28 19:46:39 +0800571 .get_voltage_sel = get_voltage_sel,
Axel Linf8ee3392012-03-28 19:45:43 +0800572 .set_voltage_sel = set_voltage_sel,
Axel Lincac87fd2012-06-20 22:30:15 +0800573 .list_voltage = regulator_list_voltage_table,
Axel Linb92f5672013-04-26 14:25:52 +0800574 .map_voltage = regulator_map_voltage_ascend,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500575 .set_current_limit = set_current_limit,
576 .get_current_limit = get_current_limit,
577};
578
Bill Pembertona5023572012-11-19 13:22:22 -0500579static int pmic_probe(struct spi_device *spi)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500580{
581 struct tps6524x *hw;
582 struct device *dev = &spi->dev;
583 const struct supply_info *info = supply_info;
584 struct regulator_init_data *init_data;
Mark Brownc172708d2012-04-04 00:50:22 +0100585 struct regulator_config config = { };
Axel Lin7a8b0e62019-04-13 15:30:02 +0800586 struct regulator_dev *rdev;
Jingoo Han5e085572013-09-30 09:58:36 +0900587 int i;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500588
Jingoo Handff91d02013-07-30 17:20:47 +0900589 init_data = dev_get_platdata(dev);
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500590 if (!init_data) {
591 dev_err(dev, "could not find regulator platform data\n");
592 return -EINVAL;
593 }
594
Axel Lin9eb0c422012-04-11 14:40:18 +0800595 hw = devm_kzalloc(&spi->dev, sizeof(struct tps6524x), GFP_KERNEL);
Sachin Kamat516add12014-02-20 14:23:16 +0530596 if (!hw)
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500597 return -ENOMEM;
Sachin Kamat516add12014-02-20 14:23:16 +0530598
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500599 spi_set_drvdata(spi, hw);
600
601 memset(hw, 0, sizeof(struct tps6524x));
602 hw->dev = dev;
Mark Brownae714c32016-04-19 18:19:08 +0100603 hw->spi = spi;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500604 mutex_init(&hw->lock);
605
606 for (i = 0; i < N_REGULATORS; i++, info++, init_data++) {
607 hw->desc[i].name = info->name;
608 hw->desc[i].id = i;
609 hw->desc[i].n_voltages = info->n_voltages;
Axel Lincac87fd2012-06-20 22:30:15 +0800610 hw->desc[i].volt_table = info->voltages;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500611 hw->desc[i].ops = &regulator_ops;
612 hw->desc[i].type = REGULATOR_VOLTAGE;
613 hw->desc[i].owner = THIS_MODULE;
614
Mark Brownc172708d2012-04-04 00:50:22 +0100615 config.dev = dev;
616 config.init_data = init_data;
617 config.driver_data = hw;
618
Axel Lin7a8b0e62019-04-13 15:30:02 +0800619 rdev = devm_regulator_register(dev, &hw->desc[i], &config);
620 if (IS_ERR(rdev))
621 return PTR_ERR(rdev);
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500622 }
623
624 return 0;
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500625}
626
627static struct spi_driver pmic_driver = {
628 .probe = pmic_probe,
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500629 .driver = {
630 .name = "tps6524x",
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500631 },
632};
633
Mark Brown173f24d2012-04-04 00:34:23 +0100634module_spi_driver(pmic_driver);
Cyril Chemparathy1394fd22010-12-07 12:04:11 -0500635
636MODULE_DESCRIPTION("TPS6524X PMIC Driver");
637MODULE_AUTHOR("Cyril Chemparathy");
638MODULE_LICENSE("GPL");
639MODULE_ALIAS("spi:tps6524x");