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