]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/regulator/lp8788-buck.c
lp8788-buck: fix a for-loop coding style
[karo-tx-linux.git] / drivers / regulator / lp8788-buck.c
1 /*
2  * TI LP8788 MFD - buck regulator driver
3  *
4  * Copyright 2012 Texas Instruments
5  *
6  * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  */
13
14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/err.h>
17 #include <linux/platform_device.h>
18 #include <linux/regulator/driver.h>
19 #include <linux/mfd/lp8788.h>
20 #include <linux/gpio.h>
21
22 /* register address */
23 #define LP8788_EN_BUCK                  0x0C
24 #define LP8788_BUCK_DVS_SEL             0x1D
25 #define LP8788_BUCK1_VOUT0              0x1E
26 #define LP8788_BUCK1_VOUT1              0x1F
27 #define LP8788_BUCK1_VOUT2              0x20
28 #define LP8788_BUCK1_VOUT3              0x21
29 #define LP8788_BUCK2_VOUT0              0x22
30 #define LP8788_BUCK2_VOUT1              0x23
31 #define LP8788_BUCK2_VOUT2              0x24
32 #define LP8788_BUCK2_VOUT3              0x25
33 #define LP8788_BUCK3_VOUT               0x26
34 #define LP8788_BUCK4_VOUT               0x27
35 #define LP8788_BUCK1_TIMESTEP           0x28
36 #define LP8788_BUCK_PWM                 0x2D
37
38 /* mask/shift bits */
39 #define LP8788_EN_BUCK1_M               BIT(0)  /* Addr 0Ch */
40 #define LP8788_EN_BUCK2_M               BIT(1)
41 #define LP8788_EN_BUCK3_M               BIT(2)
42 #define LP8788_EN_BUCK4_M               BIT(3)
43 #define LP8788_BUCK1_DVS_SEL_M          0x04    /* Addr 1Dh */
44 #define LP8788_BUCK1_DVS_M              0x03
45 #define LP8788_BUCK1_DVS_S              0
46 #define LP8788_BUCK2_DVS_SEL_M          0x40
47 #define LP8788_BUCK2_DVS_M              0x30
48 #define LP8788_BUCK2_DVS_S              4
49 #define LP8788_BUCK1_DVS_I2C            BIT(2)
50 #define LP8788_BUCK2_DVS_I2C            BIT(6)
51 #define LP8788_BUCK1_DVS_PIN            (0 << 2)
52 #define LP8788_BUCK2_DVS_PIN            (0 << 6)
53 #define LP8788_VOUT_M                   0x1F    /* Addr 1Eh ~ 27h */
54 #define LP8788_STARTUP_TIME_M           0xF8    /* Addr 28h ~ 2Bh */
55 #define LP8788_STARTUP_TIME_S           3
56 #define LP8788_FPWM_BUCK1_M             BIT(0)  /* Addr 2Dh */
57 #define LP8788_FPWM_BUCK1_S             0
58 #define LP8788_FPWM_BUCK2_M             BIT(1)
59 #define LP8788_FPWM_BUCK2_S             1
60 #define LP8788_FPWM_BUCK3_M             BIT(2)
61 #define LP8788_FPWM_BUCK3_S             2
62 #define LP8788_FPWM_BUCK4_M             BIT(3)
63 #define LP8788_FPWM_BUCK4_S             3
64
65 #define INVALID_ADDR                    0xFF
66 #define LP8788_FORCE_PWM                1
67 #define LP8788_AUTO_PWM                 0
68 #define PIN_LOW                         0
69 #define PIN_HIGH                        1
70 #define ENABLE_TIME_USEC                32
71
72 #define BUCK_FPWM_MASK(x)               (1 << (x))
73 #define BUCK_FPWM_SHIFT(x)              (x)
74
75 enum lp8788_dvs_state {
76         DVS_LOW  = GPIOF_OUT_INIT_LOW,
77         DVS_HIGH = GPIOF_OUT_INIT_HIGH,
78 };
79
80 enum lp8788_dvs_mode {
81         REGISTER,
82         EXTPIN,
83 };
84
85 enum lp8788_buck_id {
86         BUCK1,
87         BUCK2,
88         BUCK3,
89         BUCK4,
90 };
91
92 struct lp8788_buck {
93         struct lp8788 *lp;
94         struct regulator_dev *regulator;
95         void *dvs;
96 };
97
98 /* BUCK 1 ~ 4 voltage table */
99 static const int lp8788_buck_vtbl[] = {
100          500000,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000,
101         1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
102         1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
103         1950000, 2000000,
104 };
105
106 static const u8 buck1_vout_addr[] = {
107         LP8788_BUCK1_VOUT0, LP8788_BUCK1_VOUT1,
108         LP8788_BUCK1_VOUT2, LP8788_BUCK1_VOUT3,
109 };
110
111 static const u8 buck2_vout_addr[] = {
112         LP8788_BUCK2_VOUT0, LP8788_BUCK2_VOUT1,
113         LP8788_BUCK2_VOUT2, LP8788_BUCK2_VOUT3,
114 };
115
116 static void lp8788_buck1_set_dvs(struct lp8788_buck *buck)
117 {
118         struct lp8788_buck1_dvs *dvs = (struct lp8788_buck1_dvs *)buck->dvs;
119         enum lp8788_dvs_state pinstate;
120
121         if (!dvs)
122                 return;
123
124         pinstate = dvs->vsel == DVS_SEL_V0 ? DVS_LOW : DVS_HIGH;
125         if (gpio_is_valid(dvs->gpio))
126                 gpio_set_value(dvs->gpio, pinstate);
127 }
128
129 static void lp8788_buck2_set_dvs(struct lp8788_buck *buck)
130 {
131         struct lp8788_buck2_dvs *dvs = (struct lp8788_buck2_dvs *)buck->dvs;
132         enum lp8788_dvs_state pin1, pin2;
133
134         if (!dvs)
135                 return;
136
137         switch (dvs->vsel) {
138         case DVS_SEL_V0:
139                 pin1 = DVS_LOW;
140                 pin2 = DVS_LOW;
141                 break;
142         case DVS_SEL_V1:
143                 pin1 = DVS_HIGH;
144                 pin2 = DVS_LOW;
145                 break;
146         case DVS_SEL_V2:
147                 pin1 = DVS_LOW;
148                 pin2 = DVS_HIGH;
149                 break;
150         case DVS_SEL_V3:
151                 pin1 = DVS_HIGH;
152                 pin2 = DVS_HIGH;
153                 break;
154         default:
155                 return;
156         }
157
158         if (gpio_is_valid(dvs->gpio[0]))
159                 gpio_set_value(dvs->gpio[0], pin1);
160
161         if (gpio_is_valid(dvs->gpio[1]))
162                 gpio_set_value(dvs->gpio[1], pin2);
163 }
164
165 static void lp8788_set_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
166 {
167         switch (id) {
168         case BUCK1:
169                 lp8788_buck1_set_dvs(buck);
170                 break;
171         case BUCK2:
172                 lp8788_buck2_set_dvs(buck);
173                 break;
174         default:
175                 break;
176         }
177 }
178
179 static enum lp8788_dvs_mode
180 lp8788_get_buck_dvs_ctrl_mode(struct lp8788_buck *buck, enum lp8788_buck_id id)
181 {
182         u8 val, mask;
183
184         switch (id) {
185         case BUCK1:
186                 mask = LP8788_BUCK1_DVS_SEL_M;
187                 break;
188         case BUCK2:
189                 mask = LP8788_BUCK2_DVS_SEL_M;
190                 break;
191         default:
192                 return REGISTER;
193         }
194
195         lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
196
197         return val & mask ? REGISTER : EXTPIN;
198 }
199
200 static bool lp8788_is_valid_buck_addr(u8 addr)
201 {
202         switch (addr) {
203         case LP8788_BUCK1_VOUT0:
204         case LP8788_BUCK1_VOUT1:
205         case LP8788_BUCK1_VOUT2:
206         case LP8788_BUCK1_VOUT3:
207         case LP8788_BUCK2_VOUT0:
208         case LP8788_BUCK2_VOUT1:
209         case LP8788_BUCK2_VOUT2:
210         case LP8788_BUCK2_VOUT3:
211                 return true;
212         default:
213                 return false;
214         }
215 }
216
217 static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck,
218                                         enum lp8788_buck_id id)
219 {
220         enum lp8788_dvs_mode mode = lp8788_get_buck_dvs_ctrl_mode(buck, id);
221         struct lp8788_buck1_dvs *b1_dvs;
222         struct lp8788_buck2_dvs *b2_dvs;
223         u8 val, idx, addr;
224         int pin1, pin2;
225
226         switch (id) {
227         case BUCK1:
228                 if (mode == EXTPIN) {
229                         b1_dvs = (struct lp8788_buck1_dvs *)buck->dvs;
230                         if (!b1_dvs)
231                                 goto err;
232
233                         idx = gpio_get_value(b1_dvs->gpio) ? 1 : 0;
234                 } else {
235                         lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
236                         idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S;
237                 }
238                 addr = buck1_vout_addr[idx];
239                 break;
240         case BUCK2:
241                 if (mode == EXTPIN) {
242                         b2_dvs = (struct lp8788_buck2_dvs *)buck->dvs;
243                         if (!b2_dvs)
244                                 goto err;
245
246                         pin1 = gpio_get_value(b2_dvs->gpio[0]);
247                         pin2 = gpio_get_value(b2_dvs->gpio[1]);
248
249                         if (pin1 == PIN_LOW && pin2 == PIN_LOW)
250                                 idx = 0;
251                         else if (pin1 == PIN_LOW && pin2 == PIN_HIGH)
252                                 idx = 2;
253                         else if (pin1 == PIN_HIGH && pin2 == PIN_LOW)
254                                 idx = 1;
255                         else
256                                 idx = 3;
257                 } else {
258                         lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
259                         idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S;
260                 }
261                 addr = buck2_vout_addr[idx];
262                 break;
263         default:
264                 goto err;
265         }
266
267         return addr;
268 err:
269         return INVALID_ADDR;
270 }
271
272 static int lp8788_buck12_set_voltage_sel(struct regulator_dev *rdev,
273                                         unsigned selector)
274 {
275         struct lp8788_buck *buck = rdev_get_drvdata(rdev);
276         enum lp8788_buck_id id = rdev_get_id(rdev);
277         u8 addr;
278
279         if (buck->dvs)
280                 lp8788_set_dvs(buck, id);
281
282         addr = lp8788_select_buck_vout_addr(buck, id);
283         if (!lp8788_is_valid_buck_addr(addr))
284                 return -EINVAL;
285
286         return lp8788_update_bits(buck->lp, addr, LP8788_VOUT_M, selector);
287 }
288
289 static int lp8788_buck12_get_voltage_sel(struct regulator_dev *rdev)
290 {
291         struct lp8788_buck *buck = rdev_get_drvdata(rdev);
292         enum lp8788_buck_id id = rdev_get_id(rdev);
293         int ret;
294         u8 val, addr;
295
296         addr = lp8788_select_buck_vout_addr(buck, id);
297         if (!lp8788_is_valid_buck_addr(addr))
298                 return -EINVAL;
299
300         ret = lp8788_read_byte(buck->lp, addr, &val);
301         if (ret)
302                 return ret;
303
304         return val & LP8788_VOUT_M;
305 }
306
307 static int lp8788_buck_enable_time(struct regulator_dev *rdev)
308 {
309         struct lp8788_buck *buck = rdev_get_drvdata(rdev);
310         enum lp8788_buck_id id = rdev_get_id(rdev);
311         u8 val, addr = LP8788_BUCK1_TIMESTEP + id;
312
313         if (lp8788_read_byte(buck->lp, addr, &val))
314                 return -EINVAL;
315
316         val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;
317
318         return ENABLE_TIME_USEC * val;
319 }
320
321 static int lp8788_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
322 {
323         struct lp8788_buck *buck = rdev_get_drvdata(rdev);
324         enum lp8788_buck_id id = rdev_get_id(rdev);
325         u8 mask, val;
326
327         mask = BUCK_FPWM_MASK(id);
328         switch (mode) {
329         case REGULATOR_MODE_FAST:
330                 val = LP8788_FORCE_PWM << BUCK_FPWM_SHIFT(id);
331                 break;
332         case REGULATOR_MODE_NORMAL:
333                 val = LP8788_AUTO_PWM << BUCK_FPWM_SHIFT(id);
334                 break;
335         default:
336                 return -EINVAL;
337         }
338
339         return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, mask, val);
340 }
341
342 static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev)
343 {
344         struct lp8788_buck *buck = rdev_get_drvdata(rdev);
345         enum lp8788_buck_id id = rdev_get_id(rdev);
346         u8 val;
347         int ret;
348
349         ret = lp8788_read_byte(buck->lp, LP8788_BUCK_PWM, &val);
350         if (ret)
351                 return ret;
352
353         return val & BUCK_FPWM_MASK(id) ?
354                                 REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
355 }
356
357 static struct regulator_ops lp8788_buck12_ops = {
358         .list_voltage = regulator_list_voltage_table,
359         .set_voltage_sel = lp8788_buck12_set_voltage_sel,
360         .get_voltage_sel = lp8788_buck12_get_voltage_sel,
361         .enable = regulator_enable_regmap,
362         .disable = regulator_disable_regmap,
363         .is_enabled = regulator_is_enabled_regmap,
364         .enable_time = lp8788_buck_enable_time,
365         .set_mode = lp8788_buck_set_mode,
366         .get_mode = lp8788_buck_get_mode,
367 };
368
369 static struct regulator_ops lp8788_buck34_ops = {
370         .list_voltage = regulator_list_voltage_table,
371         .set_voltage_sel = regulator_set_voltage_sel_regmap,
372         .get_voltage_sel = regulator_get_voltage_sel_regmap,
373         .enable = regulator_enable_regmap,
374         .disable = regulator_disable_regmap,
375         .is_enabled = regulator_is_enabled_regmap,
376         .enable_time = lp8788_buck_enable_time,
377         .set_mode = lp8788_buck_set_mode,
378         .get_mode = lp8788_buck_get_mode,
379 };
380
381 static struct regulator_desc lp8788_buck_desc[] = {
382         {
383                 .name = "buck1",
384                 .id = BUCK1,
385                 .ops = &lp8788_buck12_ops,
386                 .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
387                 .volt_table = lp8788_buck_vtbl,
388                 .type = REGULATOR_VOLTAGE,
389                 .owner = THIS_MODULE,
390                 .enable_reg = LP8788_EN_BUCK,
391                 .enable_mask = LP8788_EN_BUCK1_M,
392         },
393         {
394                 .name = "buck2",
395                 .id = BUCK2,
396                 .ops = &lp8788_buck12_ops,
397                 .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
398                 .volt_table = lp8788_buck_vtbl,
399                 .type = REGULATOR_VOLTAGE,
400                 .owner = THIS_MODULE,
401                 .enable_reg = LP8788_EN_BUCK,
402                 .enable_mask = LP8788_EN_BUCK2_M,
403         },
404         {
405                 .name = "buck3",
406                 .id = BUCK3,
407                 .ops = &lp8788_buck34_ops,
408                 .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
409                 .volt_table = lp8788_buck_vtbl,
410                 .type = REGULATOR_VOLTAGE,
411                 .owner = THIS_MODULE,
412                 .vsel_reg = LP8788_BUCK3_VOUT,
413                 .vsel_mask = LP8788_VOUT_M,
414                 .enable_reg = LP8788_EN_BUCK,
415                 .enable_mask = LP8788_EN_BUCK3_M,
416         },
417         {
418                 .name = "buck4",
419                 .id = BUCK4,
420                 .ops = &lp8788_buck34_ops,
421                 .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
422                 .volt_table = lp8788_buck_vtbl,
423                 .type = REGULATOR_VOLTAGE,
424                 .owner = THIS_MODULE,
425                 .vsel_reg = LP8788_BUCK4_VOUT,
426                 .vsel_mask = LP8788_VOUT_M,
427                 .enable_reg = LP8788_EN_BUCK,
428                 .enable_mask = LP8788_EN_BUCK4_M,
429         },
430 };
431
432 static int lp8788_dvs_gpio_request(struct platform_device *pdev,
433                                 struct lp8788_buck *buck,
434                                 enum lp8788_buck_id id)
435 {
436         struct lp8788_platform_data *pdata = buck->lp->pdata;
437         char *b1_name = "LP8788_B1_DVS";
438         char *b2_name[] = { "LP8788_B2_DVS1", "LP8788_B2_DVS2" };
439         int i, gpio, ret;
440
441         switch (id) {
442         case BUCK1:
443                 gpio = pdata->buck1_dvs->gpio;
444                 ret = devm_gpio_request_one(&pdev->dev, gpio, DVS_LOW,
445                                             b1_name);
446                 if (ret)
447                         return ret;
448
449                 buck->dvs = pdata->buck1_dvs;
450                 break;
451         case BUCK2:
452                 for (i = 0; i < LP8788_NUM_BUCK2_DVS; i++) {
453                         gpio = pdata->buck2_dvs->gpio[i];
454                         ret = devm_gpio_request_one(&pdev->dev, gpio,
455                                                     DVS_LOW, b2_name[i]);
456                         if (ret)
457                                 return ret;
458                 }
459                 buck->dvs = pdata->buck2_dvs;
460                 break;
461         default:
462                 break;
463         }
464
465         return 0;
466 }
467
468 static int lp8788_init_dvs(struct platform_device *pdev,
469                         struct lp8788_buck *buck, enum lp8788_buck_id id)
470 {
471         struct lp8788_platform_data *pdata = buck->lp->pdata;
472         u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M };
473         u8 val[]  = { LP8788_BUCK1_DVS_PIN, LP8788_BUCK2_DVS_PIN };
474         u8 default_dvs_mode[] = { LP8788_BUCK1_DVS_I2C, LP8788_BUCK2_DVS_I2C };
475
476         /* no dvs for buck3, 4 */
477         if (id == BUCK3 || id == BUCK4)
478                 return 0;
479
480         /* no dvs platform data, then dvs will be selected by I2C registers */
481         if (!pdata)
482                 goto set_default_dvs_mode;
483
484         if ((id == BUCK1 && !pdata->buck1_dvs) ||
485                 (id == BUCK2 && !pdata->buck2_dvs))
486                 goto set_default_dvs_mode;
487
488         if (lp8788_dvs_gpio_request(pdev, buck, id))
489                 goto set_default_dvs_mode;
490
491         return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id],
492                                 val[id]);
493
494 set_default_dvs_mode:
495         return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id],
496                                   default_dvs_mode[id]);
497 }
498
499 static int lp8788_buck_probe(struct platform_device *pdev)
500 {
501         struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
502         int id = pdev->id;
503         struct lp8788_buck *buck;
504         struct regulator_config cfg = { };
505         struct regulator_dev *rdev;
506         int ret;
507
508         buck = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_buck), GFP_KERNEL);
509         if (!buck)
510                 return -ENOMEM;
511
512         buck->lp = lp;
513
514         ret = lp8788_init_dvs(pdev, buck, id);
515         if (ret)
516                 return ret;
517
518         cfg.dev = pdev->dev.parent;
519         cfg.init_data = lp->pdata ? lp->pdata->buck_data[id] : NULL;
520         cfg.driver_data = buck;
521         cfg.regmap = lp->regmap;
522
523         rdev = regulator_register(&lp8788_buck_desc[id], &cfg);
524         if (IS_ERR(rdev)) {
525                 ret = PTR_ERR(rdev);
526                 dev_err(&pdev->dev, "BUCK%d regulator register err = %d\n",
527                                 id + 1, ret);
528                 return ret;
529         }
530
531         buck->regulator = rdev;
532         platform_set_drvdata(pdev, buck);
533
534         return 0;
535 }
536
537 static int lp8788_buck_remove(struct platform_device *pdev)
538 {
539         struct lp8788_buck *buck = platform_get_drvdata(pdev);
540
541         platform_set_drvdata(pdev, NULL);
542         regulator_unregister(buck->regulator);
543
544         return 0;
545 }
546
547 static struct platform_driver lp8788_buck_driver = {
548         .probe = lp8788_buck_probe,
549         .remove = lp8788_buck_remove,
550         .driver = {
551                 .name = LP8788_DEV_BUCK,
552                 .owner = THIS_MODULE,
553         },
554 };
555
556 static int __init lp8788_buck_init(void)
557 {
558         return platform_driver_register(&lp8788_buck_driver);
559 }
560 subsys_initcall(lp8788_buck_init);
561
562 static void __exit lp8788_buck_exit(void)
563 {
564         platform_driver_unregister(&lp8788_buck_driver);
565 }
566 module_exit(lp8788_buck_exit);
567
568 MODULE_DESCRIPTION("TI LP8788 BUCK Driver");
569 MODULE_AUTHOR("Milo Kim");
570 MODULE_LICENSE("GPL");
571 MODULE_ALIAS("platform:lp8788-buck");