Linux Audio

Check our new training course

Linux kernel drivers training

May 6-19, 2025
Register
Loading...
v6.13.7
  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");
v4.17
 
  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");