xref: /OK3568_Linux_fs/kernel/drivers/regulator/lp872x.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright 2012 Texas Instruments
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/slab.h>
10*4882a593Smuzhiyun #include <linux/i2c.h>
11*4882a593Smuzhiyun #include <linux/regmap.h>
12*4882a593Smuzhiyun #include <linux/err.h>
13*4882a593Smuzhiyun #include <linux/gpio.h>
14*4882a593Smuzhiyun #include <linux/delay.h>
15*4882a593Smuzhiyun #include <linux/regulator/lp872x.h>
16*4882a593Smuzhiyun #include <linux/regulator/driver.h>
17*4882a593Smuzhiyun #include <linux/platform_device.h>
18*4882a593Smuzhiyun #include <linux/of.h>
19*4882a593Smuzhiyun #include <linux/of_gpio.h>
20*4882a593Smuzhiyun #include <linux/regulator/of_regulator.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun /* Registers : LP8720/8725 shared */
23*4882a593Smuzhiyun #define LP872X_GENERAL_CFG		0x00
24*4882a593Smuzhiyun #define LP872X_LDO1_VOUT		0x01
25*4882a593Smuzhiyun #define LP872X_LDO2_VOUT		0x02
26*4882a593Smuzhiyun #define LP872X_LDO3_VOUT		0x03
27*4882a593Smuzhiyun #define LP872X_LDO4_VOUT		0x04
28*4882a593Smuzhiyun #define LP872X_LDO5_VOUT		0x05
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun /* Registers : LP8720 */
31*4882a593Smuzhiyun #define LP8720_BUCK_VOUT1		0x06
32*4882a593Smuzhiyun #define LP8720_BUCK_VOUT2		0x07
33*4882a593Smuzhiyun #define LP8720_ENABLE			0x08
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun /* Registers : LP8725 */
36*4882a593Smuzhiyun #define LP8725_LILO1_VOUT		0x06
37*4882a593Smuzhiyun #define LP8725_LILO2_VOUT		0x07
38*4882a593Smuzhiyun #define LP8725_BUCK1_VOUT1		0x08
39*4882a593Smuzhiyun #define LP8725_BUCK1_VOUT2		0x09
40*4882a593Smuzhiyun #define LP8725_BUCK2_VOUT1		0x0A
41*4882a593Smuzhiyun #define LP8725_BUCK2_VOUT2		0x0B
42*4882a593Smuzhiyun #define LP8725_BUCK_CTRL		0x0C
43*4882a593Smuzhiyun #define LP8725_LDO_CTRL			0x0D
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun /* Mask/shift : LP8720/LP8725 shared */
46*4882a593Smuzhiyun #define LP872X_VOUT_M			0x1F
47*4882a593Smuzhiyun #define LP872X_START_DELAY_M		0xE0
48*4882a593Smuzhiyun #define LP872X_START_DELAY_S		5
49*4882a593Smuzhiyun #define LP872X_EN_LDO1_M		BIT(0)
50*4882a593Smuzhiyun #define LP872X_EN_LDO2_M		BIT(1)
51*4882a593Smuzhiyun #define LP872X_EN_LDO3_M		BIT(2)
52*4882a593Smuzhiyun #define LP872X_EN_LDO4_M		BIT(3)
53*4882a593Smuzhiyun #define LP872X_EN_LDO5_M		BIT(4)
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun /* Mask/shift : LP8720 */
56*4882a593Smuzhiyun #define LP8720_TIMESTEP_S		0		/* Addr 00h */
57*4882a593Smuzhiyun #define LP8720_TIMESTEP_M		BIT(0)
58*4882a593Smuzhiyun #define LP8720_EXT_DVS_M		BIT(2)
59*4882a593Smuzhiyun #define LP8720_BUCK_FPWM_S		5		/* Addr 07h */
60*4882a593Smuzhiyun #define LP8720_BUCK_FPWM_M		BIT(5)
61*4882a593Smuzhiyun #define LP8720_EN_BUCK_M		BIT(5)		/* Addr 08h */
62*4882a593Smuzhiyun #define LP8720_DVS_SEL_M		BIT(7)
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /* Mask/shift : LP8725 */
65*4882a593Smuzhiyun #define LP8725_TIMESTEP_M		0xC0		/* Addr 00h */
66*4882a593Smuzhiyun #define LP8725_TIMESTEP_S		6
67*4882a593Smuzhiyun #define LP8725_BUCK1_EN_M		BIT(0)
68*4882a593Smuzhiyun #define LP8725_DVS1_M			BIT(2)
69*4882a593Smuzhiyun #define LP8725_DVS2_M			BIT(3)
70*4882a593Smuzhiyun #define LP8725_BUCK2_EN_M		BIT(4)
71*4882a593Smuzhiyun #define LP8725_BUCK_CL_M		0xC0		/* Addr 09h, 0Bh */
72*4882a593Smuzhiyun #define LP8725_BUCK_CL_S		6
73*4882a593Smuzhiyun #define LP8725_BUCK1_FPWM_S		1		/* Addr 0Ch */
74*4882a593Smuzhiyun #define LP8725_BUCK1_FPWM_M		BIT(1)
75*4882a593Smuzhiyun #define LP8725_BUCK2_FPWM_S		5
76*4882a593Smuzhiyun #define LP8725_BUCK2_FPWM_M		BIT(5)
77*4882a593Smuzhiyun #define LP8725_EN_LILO1_M		BIT(5)		/* Addr 0Dh */
78*4882a593Smuzhiyun #define LP8725_EN_LILO2_M		BIT(6)
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun /* PWM mode */
81*4882a593Smuzhiyun #define LP872X_FORCE_PWM		1
82*4882a593Smuzhiyun #define LP872X_AUTO_PWM			0
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #define LP8720_NUM_REGULATORS		6
85*4882a593Smuzhiyun #define LP8725_NUM_REGULATORS		9
86*4882a593Smuzhiyun #define EXTERN_DVS_USED			0
87*4882a593Smuzhiyun #define MAX_DELAY			6
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /* Default DVS Mode */
90*4882a593Smuzhiyun #define LP8720_DEFAULT_DVS		0
91*4882a593Smuzhiyun #define LP8725_DEFAULT_DVS		BIT(2)
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun /* dump registers in regmap-debugfs */
94*4882a593Smuzhiyun #define MAX_REGISTERS			0x0F
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun enum lp872x_id {
97*4882a593Smuzhiyun 	LP8720,
98*4882a593Smuzhiyun 	LP8725,
99*4882a593Smuzhiyun };
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun struct lp872x {
102*4882a593Smuzhiyun 	struct regmap *regmap;
103*4882a593Smuzhiyun 	struct device *dev;
104*4882a593Smuzhiyun 	enum lp872x_id chipid;
105*4882a593Smuzhiyun 	struct lp872x_platform_data *pdata;
106*4882a593Smuzhiyun 	int num_regulators;
107*4882a593Smuzhiyun 	enum lp872x_dvs_state dvs_pin;
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun /* LP8720/LP8725 shared voltage table for LDOs */
111*4882a593Smuzhiyun static const unsigned int lp872x_ldo_vtbl[] = {
112*4882a593Smuzhiyun 	1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
113*4882a593Smuzhiyun 	1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 2000000,
114*4882a593Smuzhiyun 	2100000, 2200000, 2300000, 2400000, 2500000, 2600000, 2650000, 2700000,
115*4882a593Smuzhiyun 	2750000, 2800000, 2850000, 2900000, 2950000, 3000000, 3100000, 3300000,
116*4882a593Smuzhiyun };
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun /* LP8720 LDO4 voltage table */
119*4882a593Smuzhiyun static const unsigned int lp8720_ldo4_vtbl[] = {
120*4882a593Smuzhiyun 	 800000,  850000,  900000, 1000000, 1100000, 1200000, 1250000, 1300000,
121*4882a593Smuzhiyun 	1350000, 1400000, 1450000, 1500000, 1550000, 1600000, 1650000, 1700000,
122*4882a593Smuzhiyun 	1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000,
123*4882a593Smuzhiyun 	2400000, 2500000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000,
124*4882a593Smuzhiyun };
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun /* LP8725 LILO(Low Input Low Output) voltage table */
127*4882a593Smuzhiyun static const unsigned int lp8725_lilo_vtbl[] = {
128*4882a593Smuzhiyun 	 800000,  850000,  900000,  950000, 1000000, 1050000, 1100000, 1150000,
129*4882a593Smuzhiyun 	1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000,
130*4882a593Smuzhiyun 	1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
131*4882a593Smuzhiyun 	2600000, 2700000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000,
132*4882a593Smuzhiyun };
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun /* LP8720 BUCK voltage table */
135*4882a593Smuzhiyun #define EXT_R		0	/* external resistor divider */
136*4882a593Smuzhiyun static const unsigned int lp8720_buck_vtbl[] = {
137*4882a593Smuzhiyun 	  EXT_R,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000,
138*4882a593Smuzhiyun 	1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
139*4882a593Smuzhiyun 	1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
140*4882a593Smuzhiyun 	1950000, 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000,
141*4882a593Smuzhiyun };
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun /* LP8725 BUCK voltage table */
144*4882a593Smuzhiyun static const unsigned int lp8725_buck_vtbl[] = {
145*4882a593Smuzhiyun 	 800000,  850000,  900000,  950000, 1000000, 1050000, 1100000, 1150000,
146*4882a593Smuzhiyun 	1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000,
147*4882a593Smuzhiyun 	1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000,
148*4882a593Smuzhiyun 	2400000, 2500000, 2600000, 2700000, 2800000, 2850000, 2900000, 3000000,
149*4882a593Smuzhiyun };
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun /* LP8725 BUCK current limit */
152*4882a593Smuzhiyun static const unsigned int lp8725_buck_uA[] = {
153*4882a593Smuzhiyun 	460000, 780000, 1050000, 1370000,
154*4882a593Smuzhiyun };
155*4882a593Smuzhiyun 
lp872x_read_byte(struct lp872x * lp,u8 addr,u8 * data)156*4882a593Smuzhiyun static int lp872x_read_byte(struct lp872x *lp, u8 addr, u8 *data)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	int ret;
159*4882a593Smuzhiyun 	unsigned int val;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	ret = regmap_read(lp->regmap, addr, &val);
162*4882a593Smuzhiyun 	if (ret < 0) {
163*4882a593Smuzhiyun 		dev_err(lp->dev, "failed to read 0x%.2x\n", addr);
164*4882a593Smuzhiyun 		return ret;
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	*data = (u8)val;
168*4882a593Smuzhiyun 	return 0;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun 
lp872x_write_byte(struct lp872x * lp,u8 addr,u8 data)171*4882a593Smuzhiyun static inline int lp872x_write_byte(struct lp872x *lp, u8 addr, u8 data)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	return regmap_write(lp->regmap, addr, data);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
lp872x_update_bits(struct lp872x * lp,u8 addr,unsigned int mask,u8 data)176*4882a593Smuzhiyun static inline int lp872x_update_bits(struct lp872x *lp, u8 addr,
177*4882a593Smuzhiyun 				unsigned int mask, u8 data)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	return regmap_update_bits(lp->regmap, addr, mask, data);
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun 
lp872x_get_timestep_usec(struct lp872x * lp)182*4882a593Smuzhiyun static int lp872x_get_timestep_usec(struct lp872x *lp)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun 	enum lp872x_id chip = lp->chipid;
185*4882a593Smuzhiyun 	u8 val, mask, shift;
186*4882a593Smuzhiyun 	int *time_usec, size, ret;
187*4882a593Smuzhiyun 	int lp8720_time_usec[] = { 25, 50 };
188*4882a593Smuzhiyun 	int lp8725_time_usec[] = { 32, 64, 128, 256 };
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	switch (chip) {
191*4882a593Smuzhiyun 	case LP8720:
192*4882a593Smuzhiyun 		mask = LP8720_TIMESTEP_M;
193*4882a593Smuzhiyun 		shift = LP8720_TIMESTEP_S;
194*4882a593Smuzhiyun 		time_usec = &lp8720_time_usec[0];
195*4882a593Smuzhiyun 		size = ARRAY_SIZE(lp8720_time_usec);
196*4882a593Smuzhiyun 		break;
197*4882a593Smuzhiyun 	case LP8725:
198*4882a593Smuzhiyun 		mask = LP8725_TIMESTEP_M;
199*4882a593Smuzhiyun 		shift = LP8725_TIMESTEP_S;
200*4882a593Smuzhiyun 		time_usec = &lp8725_time_usec[0];
201*4882a593Smuzhiyun 		size = ARRAY_SIZE(lp8725_time_usec);
202*4882a593Smuzhiyun 		break;
203*4882a593Smuzhiyun 	default:
204*4882a593Smuzhiyun 		return -EINVAL;
205*4882a593Smuzhiyun 	}
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val);
208*4882a593Smuzhiyun 	if (ret)
209*4882a593Smuzhiyun 		return ret;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	val = (val & mask) >> shift;
212*4882a593Smuzhiyun 	if (val >= size)
213*4882a593Smuzhiyun 		return -EINVAL;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	return *(time_usec + val);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun 
lp872x_regulator_enable_time(struct regulator_dev * rdev)218*4882a593Smuzhiyun static int lp872x_regulator_enable_time(struct regulator_dev *rdev)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun 	struct lp872x *lp = rdev_get_drvdata(rdev);
221*4882a593Smuzhiyun 	enum lp872x_regulator_id rid = rdev_get_id(rdev);
222*4882a593Smuzhiyun 	int time_step_us = lp872x_get_timestep_usec(lp);
223*4882a593Smuzhiyun 	int ret;
224*4882a593Smuzhiyun 	u8 addr, val;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	if (time_step_us < 0)
227*4882a593Smuzhiyun 		return time_step_us;
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	switch (rid) {
230*4882a593Smuzhiyun 	case LP8720_ID_LDO1 ... LP8720_ID_BUCK:
231*4882a593Smuzhiyun 		addr = LP872X_LDO1_VOUT + rid;
232*4882a593Smuzhiyun 		break;
233*4882a593Smuzhiyun 	case LP8725_ID_LDO1 ... LP8725_ID_BUCK1:
234*4882a593Smuzhiyun 		addr = LP872X_LDO1_VOUT + rid - LP8725_ID_BASE;
235*4882a593Smuzhiyun 		break;
236*4882a593Smuzhiyun 	case LP8725_ID_BUCK2:
237*4882a593Smuzhiyun 		addr = LP8725_BUCK2_VOUT1;
238*4882a593Smuzhiyun 		break;
239*4882a593Smuzhiyun 	default:
240*4882a593Smuzhiyun 		return -EINVAL;
241*4882a593Smuzhiyun 	}
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	ret = lp872x_read_byte(lp, addr, &val);
244*4882a593Smuzhiyun 	if (ret)
245*4882a593Smuzhiyun 		return ret;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	val = (val & LP872X_START_DELAY_M) >> LP872X_START_DELAY_S;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	return val > MAX_DELAY ? 0 : val * time_step_us;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
lp872x_set_dvs(struct lp872x * lp,enum lp872x_dvs_sel dvs_sel,int gpio)252*4882a593Smuzhiyun static void lp872x_set_dvs(struct lp872x *lp, enum lp872x_dvs_sel dvs_sel,
253*4882a593Smuzhiyun 			int gpio)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun 	enum lp872x_dvs_state state;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	state = dvs_sel == SEL_V1 ? DVS_HIGH : DVS_LOW;
258*4882a593Smuzhiyun 	gpio_set_value(gpio, state);
259*4882a593Smuzhiyun 	lp->dvs_pin = state;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun 
lp872x_select_buck_vout_addr(struct lp872x * lp,enum lp872x_regulator_id buck)262*4882a593Smuzhiyun static u8 lp872x_select_buck_vout_addr(struct lp872x *lp,
263*4882a593Smuzhiyun 				enum lp872x_regulator_id buck)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun 	u8 val, addr;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	if (lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val))
268*4882a593Smuzhiyun 		return 0;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	switch (buck) {
271*4882a593Smuzhiyun 	case LP8720_ID_BUCK:
272*4882a593Smuzhiyun 		if (val & LP8720_EXT_DVS_M) {
273*4882a593Smuzhiyun 			addr = (lp->dvs_pin == DVS_HIGH) ?
274*4882a593Smuzhiyun 				LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2;
275*4882a593Smuzhiyun 		} else {
276*4882a593Smuzhiyun 			if (lp872x_read_byte(lp, LP8720_ENABLE, &val))
277*4882a593Smuzhiyun 				return 0;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 			addr = val & LP8720_DVS_SEL_M ?
280*4882a593Smuzhiyun 				LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2;
281*4882a593Smuzhiyun 		}
282*4882a593Smuzhiyun 		break;
283*4882a593Smuzhiyun 	case LP8725_ID_BUCK1:
284*4882a593Smuzhiyun 		if (val & LP8725_DVS1_M)
285*4882a593Smuzhiyun 			addr = LP8725_BUCK1_VOUT1;
286*4882a593Smuzhiyun 		else
287*4882a593Smuzhiyun 			addr = (lp->dvs_pin == DVS_HIGH) ?
288*4882a593Smuzhiyun 				LP8725_BUCK1_VOUT1 : LP8725_BUCK1_VOUT2;
289*4882a593Smuzhiyun 		break;
290*4882a593Smuzhiyun 	case LP8725_ID_BUCK2:
291*4882a593Smuzhiyun 		addr =  val & LP8725_DVS2_M ?
292*4882a593Smuzhiyun 			LP8725_BUCK2_VOUT1 : LP8725_BUCK2_VOUT2;
293*4882a593Smuzhiyun 		break;
294*4882a593Smuzhiyun 	default:
295*4882a593Smuzhiyun 		return 0;
296*4882a593Smuzhiyun 	}
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	return addr;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun 
lp872x_is_valid_buck_addr(u8 addr)301*4882a593Smuzhiyun static bool lp872x_is_valid_buck_addr(u8 addr)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun 	switch (addr) {
304*4882a593Smuzhiyun 	case LP8720_BUCK_VOUT1:
305*4882a593Smuzhiyun 	case LP8720_BUCK_VOUT2:
306*4882a593Smuzhiyun 	case LP8725_BUCK1_VOUT1:
307*4882a593Smuzhiyun 	case LP8725_BUCK1_VOUT2:
308*4882a593Smuzhiyun 	case LP8725_BUCK2_VOUT1:
309*4882a593Smuzhiyun 	case LP8725_BUCK2_VOUT2:
310*4882a593Smuzhiyun 		return true;
311*4882a593Smuzhiyun 	default:
312*4882a593Smuzhiyun 		return false;
313*4882a593Smuzhiyun 	}
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun 
lp872x_buck_set_voltage_sel(struct regulator_dev * rdev,unsigned selector)316*4882a593Smuzhiyun static int lp872x_buck_set_voltage_sel(struct regulator_dev *rdev,
317*4882a593Smuzhiyun 					unsigned selector)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	struct lp872x *lp = rdev_get_drvdata(rdev);
320*4882a593Smuzhiyun 	enum lp872x_regulator_id buck = rdev_get_id(rdev);
321*4882a593Smuzhiyun 	u8 addr, mask = LP872X_VOUT_M;
322*4882a593Smuzhiyun 	struct lp872x_dvs *dvs = lp->pdata ? lp->pdata->dvs : NULL;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	if (dvs && gpio_is_valid(dvs->gpio))
325*4882a593Smuzhiyun 		lp872x_set_dvs(lp, dvs->vsel, dvs->gpio);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	addr = lp872x_select_buck_vout_addr(lp, buck);
328*4882a593Smuzhiyun 	if (!lp872x_is_valid_buck_addr(addr))
329*4882a593Smuzhiyun 		return -EINVAL;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	return lp872x_update_bits(lp, addr, mask, selector);
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun 
lp872x_buck_get_voltage_sel(struct regulator_dev * rdev)334*4882a593Smuzhiyun static int lp872x_buck_get_voltage_sel(struct regulator_dev *rdev)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun 	struct lp872x *lp = rdev_get_drvdata(rdev);
337*4882a593Smuzhiyun 	enum lp872x_regulator_id buck = rdev_get_id(rdev);
338*4882a593Smuzhiyun 	u8 addr, val;
339*4882a593Smuzhiyun 	int ret;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	addr = lp872x_select_buck_vout_addr(lp, buck);
342*4882a593Smuzhiyun 	if (!lp872x_is_valid_buck_addr(addr))
343*4882a593Smuzhiyun 		return -EINVAL;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	ret = lp872x_read_byte(lp, addr, &val);
346*4882a593Smuzhiyun 	if (ret)
347*4882a593Smuzhiyun 		return ret;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	return val & LP872X_VOUT_M;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun 
lp872x_buck_set_mode(struct regulator_dev * rdev,unsigned int mode)352*4882a593Smuzhiyun static int lp872x_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun 	struct lp872x *lp = rdev_get_drvdata(rdev);
355*4882a593Smuzhiyun 	enum lp872x_regulator_id buck = rdev_get_id(rdev);
356*4882a593Smuzhiyun 	u8 addr, mask, shift, val;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	switch (buck) {
359*4882a593Smuzhiyun 	case LP8720_ID_BUCK:
360*4882a593Smuzhiyun 		addr = LP8720_BUCK_VOUT2;
361*4882a593Smuzhiyun 		mask = LP8720_BUCK_FPWM_M;
362*4882a593Smuzhiyun 		shift = LP8720_BUCK_FPWM_S;
363*4882a593Smuzhiyun 		break;
364*4882a593Smuzhiyun 	case LP8725_ID_BUCK1:
365*4882a593Smuzhiyun 		addr = LP8725_BUCK_CTRL;
366*4882a593Smuzhiyun 		mask = LP8725_BUCK1_FPWM_M;
367*4882a593Smuzhiyun 		shift = LP8725_BUCK1_FPWM_S;
368*4882a593Smuzhiyun 		break;
369*4882a593Smuzhiyun 	case LP8725_ID_BUCK2:
370*4882a593Smuzhiyun 		addr = LP8725_BUCK_CTRL;
371*4882a593Smuzhiyun 		mask = LP8725_BUCK2_FPWM_M;
372*4882a593Smuzhiyun 		shift = LP8725_BUCK2_FPWM_S;
373*4882a593Smuzhiyun 		break;
374*4882a593Smuzhiyun 	default:
375*4882a593Smuzhiyun 		return -EINVAL;
376*4882a593Smuzhiyun 	}
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	if (mode == REGULATOR_MODE_FAST)
379*4882a593Smuzhiyun 		val = LP872X_FORCE_PWM << shift;
380*4882a593Smuzhiyun 	else if (mode == REGULATOR_MODE_NORMAL)
381*4882a593Smuzhiyun 		val = LP872X_AUTO_PWM << shift;
382*4882a593Smuzhiyun 	else
383*4882a593Smuzhiyun 		return -EINVAL;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	return lp872x_update_bits(lp, addr, mask, val);
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun 
lp872x_buck_get_mode(struct regulator_dev * rdev)388*4882a593Smuzhiyun static unsigned int lp872x_buck_get_mode(struct regulator_dev *rdev)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun 	struct lp872x *lp = rdev_get_drvdata(rdev);
391*4882a593Smuzhiyun 	enum lp872x_regulator_id buck = rdev_get_id(rdev);
392*4882a593Smuzhiyun 	u8 addr, mask, val;
393*4882a593Smuzhiyun 	int ret;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	switch (buck) {
396*4882a593Smuzhiyun 	case LP8720_ID_BUCK:
397*4882a593Smuzhiyun 		addr = LP8720_BUCK_VOUT2;
398*4882a593Smuzhiyun 		mask = LP8720_BUCK_FPWM_M;
399*4882a593Smuzhiyun 		break;
400*4882a593Smuzhiyun 	case LP8725_ID_BUCK1:
401*4882a593Smuzhiyun 		addr = LP8725_BUCK_CTRL;
402*4882a593Smuzhiyun 		mask = LP8725_BUCK1_FPWM_M;
403*4882a593Smuzhiyun 		break;
404*4882a593Smuzhiyun 	case LP8725_ID_BUCK2:
405*4882a593Smuzhiyun 		addr = LP8725_BUCK_CTRL;
406*4882a593Smuzhiyun 		mask = LP8725_BUCK2_FPWM_M;
407*4882a593Smuzhiyun 		break;
408*4882a593Smuzhiyun 	default:
409*4882a593Smuzhiyun 		return -EINVAL;
410*4882a593Smuzhiyun 	}
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	ret = lp872x_read_byte(lp, addr, &val);
413*4882a593Smuzhiyun 	if (ret)
414*4882a593Smuzhiyun 		return ret;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	return val & mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun static const struct regulator_ops lp872x_ldo_ops = {
420*4882a593Smuzhiyun 	.list_voltage = regulator_list_voltage_table,
421*4882a593Smuzhiyun 	.map_voltage = regulator_map_voltage_ascend,
422*4882a593Smuzhiyun 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
423*4882a593Smuzhiyun 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
424*4882a593Smuzhiyun 	.enable = regulator_enable_regmap,
425*4882a593Smuzhiyun 	.disable = regulator_disable_regmap,
426*4882a593Smuzhiyun 	.is_enabled = regulator_is_enabled_regmap,
427*4882a593Smuzhiyun 	.enable_time = lp872x_regulator_enable_time,
428*4882a593Smuzhiyun };
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun static const struct regulator_ops lp8720_buck_ops = {
431*4882a593Smuzhiyun 	.list_voltage = regulator_list_voltage_table,
432*4882a593Smuzhiyun 	.map_voltage = regulator_map_voltage_ascend,
433*4882a593Smuzhiyun 	.set_voltage_sel = lp872x_buck_set_voltage_sel,
434*4882a593Smuzhiyun 	.get_voltage_sel = lp872x_buck_get_voltage_sel,
435*4882a593Smuzhiyun 	.enable = regulator_enable_regmap,
436*4882a593Smuzhiyun 	.disable = regulator_disable_regmap,
437*4882a593Smuzhiyun 	.is_enabled = regulator_is_enabled_regmap,
438*4882a593Smuzhiyun 	.enable_time = lp872x_regulator_enable_time,
439*4882a593Smuzhiyun 	.set_mode = lp872x_buck_set_mode,
440*4882a593Smuzhiyun 	.get_mode = lp872x_buck_get_mode,
441*4882a593Smuzhiyun };
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun static const struct regulator_ops lp8725_buck_ops = {
444*4882a593Smuzhiyun 	.list_voltage = regulator_list_voltage_table,
445*4882a593Smuzhiyun 	.map_voltage = regulator_map_voltage_ascend,
446*4882a593Smuzhiyun 	.set_voltage_sel = lp872x_buck_set_voltage_sel,
447*4882a593Smuzhiyun 	.get_voltage_sel = lp872x_buck_get_voltage_sel,
448*4882a593Smuzhiyun 	.enable = regulator_enable_regmap,
449*4882a593Smuzhiyun 	.disable = regulator_disable_regmap,
450*4882a593Smuzhiyun 	.is_enabled = regulator_is_enabled_regmap,
451*4882a593Smuzhiyun 	.enable_time = lp872x_regulator_enable_time,
452*4882a593Smuzhiyun 	.set_mode = lp872x_buck_set_mode,
453*4882a593Smuzhiyun 	.get_mode = lp872x_buck_get_mode,
454*4882a593Smuzhiyun 	.set_current_limit = regulator_set_current_limit_regmap,
455*4882a593Smuzhiyun 	.get_current_limit = regulator_get_current_limit_regmap,
456*4882a593Smuzhiyun };
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun static const struct regulator_desc lp8720_regulator_desc[] = {
459*4882a593Smuzhiyun 	{
460*4882a593Smuzhiyun 		.name = "ldo1",
461*4882a593Smuzhiyun 		.of_match = of_match_ptr("ldo1"),
462*4882a593Smuzhiyun 		.id = LP8720_ID_LDO1,
463*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
464*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
465*4882a593Smuzhiyun 		.volt_table = lp872x_ldo_vtbl,
466*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
467*4882a593Smuzhiyun 		.owner = THIS_MODULE,
468*4882a593Smuzhiyun 		.vsel_reg = LP872X_LDO1_VOUT,
469*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
470*4882a593Smuzhiyun 		.enable_reg = LP8720_ENABLE,
471*4882a593Smuzhiyun 		.enable_mask = LP872X_EN_LDO1_M,
472*4882a593Smuzhiyun 	},
473*4882a593Smuzhiyun 	{
474*4882a593Smuzhiyun 		.name = "ldo2",
475*4882a593Smuzhiyun 		.of_match = of_match_ptr("ldo2"),
476*4882a593Smuzhiyun 		.id = LP8720_ID_LDO2,
477*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
478*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
479*4882a593Smuzhiyun 		.volt_table = lp872x_ldo_vtbl,
480*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
481*4882a593Smuzhiyun 		.owner = THIS_MODULE,
482*4882a593Smuzhiyun 		.vsel_reg = LP872X_LDO2_VOUT,
483*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
484*4882a593Smuzhiyun 		.enable_reg = LP8720_ENABLE,
485*4882a593Smuzhiyun 		.enable_mask = LP872X_EN_LDO2_M,
486*4882a593Smuzhiyun 	},
487*4882a593Smuzhiyun 	{
488*4882a593Smuzhiyun 		.name = "ldo3",
489*4882a593Smuzhiyun 		.of_match = of_match_ptr("ldo3"),
490*4882a593Smuzhiyun 		.id = LP8720_ID_LDO3,
491*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
492*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
493*4882a593Smuzhiyun 		.volt_table = lp872x_ldo_vtbl,
494*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
495*4882a593Smuzhiyun 		.owner = THIS_MODULE,
496*4882a593Smuzhiyun 		.vsel_reg = LP872X_LDO3_VOUT,
497*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
498*4882a593Smuzhiyun 		.enable_reg = LP8720_ENABLE,
499*4882a593Smuzhiyun 		.enable_mask = LP872X_EN_LDO3_M,
500*4882a593Smuzhiyun 	},
501*4882a593Smuzhiyun 	{
502*4882a593Smuzhiyun 		.name = "ldo4",
503*4882a593Smuzhiyun 		.of_match = of_match_ptr("ldo4"),
504*4882a593Smuzhiyun 		.id = LP8720_ID_LDO4,
505*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
506*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8720_ldo4_vtbl),
507*4882a593Smuzhiyun 		.volt_table = lp8720_ldo4_vtbl,
508*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
509*4882a593Smuzhiyun 		.owner = THIS_MODULE,
510*4882a593Smuzhiyun 		.vsel_reg = LP872X_LDO4_VOUT,
511*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
512*4882a593Smuzhiyun 		.enable_reg = LP8720_ENABLE,
513*4882a593Smuzhiyun 		.enable_mask = LP872X_EN_LDO4_M,
514*4882a593Smuzhiyun 	},
515*4882a593Smuzhiyun 	{
516*4882a593Smuzhiyun 		.name = "ldo5",
517*4882a593Smuzhiyun 		.of_match = of_match_ptr("ldo5"),
518*4882a593Smuzhiyun 		.id = LP8720_ID_LDO5,
519*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
520*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
521*4882a593Smuzhiyun 		.volt_table = lp872x_ldo_vtbl,
522*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
523*4882a593Smuzhiyun 		.owner = THIS_MODULE,
524*4882a593Smuzhiyun 		.vsel_reg = LP872X_LDO5_VOUT,
525*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
526*4882a593Smuzhiyun 		.enable_reg = LP8720_ENABLE,
527*4882a593Smuzhiyun 		.enable_mask = LP872X_EN_LDO5_M,
528*4882a593Smuzhiyun 	},
529*4882a593Smuzhiyun 	{
530*4882a593Smuzhiyun 		.name = "buck",
531*4882a593Smuzhiyun 		.of_match = of_match_ptr("buck"),
532*4882a593Smuzhiyun 		.id = LP8720_ID_BUCK,
533*4882a593Smuzhiyun 		.ops = &lp8720_buck_ops,
534*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8720_buck_vtbl),
535*4882a593Smuzhiyun 		.volt_table = lp8720_buck_vtbl,
536*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
537*4882a593Smuzhiyun 		.owner = THIS_MODULE,
538*4882a593Smuzhiyun 		.enable_reg = LP8720_ENABLE,
539*4882a593Smuzhiyun 		.enable_mask = LP8720_EN_BUCK_M,
540*4882a593Smuzhiyun 	},
541*4882a593Smuzhiyun };
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun static const struct regulator_desc lp8725_regulator_desc[] = {
544*4882a593Smuzhiyun 	{
545*4882a593Smuzhiyun 		.name = "ldo1",
546*4882a593Smuzhiyun 		.of_match = of_match_ptr("ldo1"),
547*4882a593Smuzhiyun 		.id = LP8725_ID_LDO1,
548*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
549*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
550*4882a593Smuzhiyun 		.volt_table = lp872x_ldo_vtbl,
551*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
552*4882a593Smuzhiyun 		.owner = THIS_MODULE,
553*4882a593Smuzhiyun 		.vsel_reg = LP872X_LDO1_VOUT,
554*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
555*4882a593Smuzhiyun 		.enable_reg = LP8725_LDO_CTRL,
556*4882a593Smuzhiyun 		.enable_mask = LP872X_EN_LDO1_M,
557*4882a593Smuzhiyun 	},
558*4882a593Smuzhiyun 	{
559*4882a593Smuzhiyun 		.name = "ldo2",
560*4882a593Smuzhiyun 		.of_match = of_match_ptr("ldo2"),
561*4882a593Smuzhiyun 		.id = LP8725_ID_LDO2,
562*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
563*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
564*4882a593Smuzhiyun 		.volt_table = lp872x_ldo_vtbl,
565*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
566*4882a593Smuzhiyun 		.owner = THIS_MODULE,
567*4882a593Smuzhiyun 		.vsel_reg = LP872X_LDO2_VOUT,
568*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
569*4882a593Smuzhiyun 		.enable_reg = LP8725_LDO_CTRL,
570*4882a593Smuzhiyun 		.enable_mask = LP872X_EN_LDO2_M,
571*4882a593Smuzhiyun 	},
572*4882a593Smuzhiyun 	{
573*4882a593Smuzhiyun 		.name = "ldo3",
574*4882a593Smuzhiyun 		.of_match = of_match_ptr("ldo3"),
575*4882a593Smuzhiyun 		.id = LP8725_ID_LDO3,
576*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
577*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
578*4882a593Smuzhiyun 		.volt_table = lp872x_ldo_vtbl,
579*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
580*4882a593Smuzhiyun 		.owner = THIS_MODULE,
581*4882a593Smuzhiyun 		.vsel_reg = LP872X_LDO3_VOUT,
582*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
583*4882a593Smuzhiyun 		.enable_reg = LP8725_LDO_CTRL,
584*4882a593Smuzhiyun 		.enable_mask = LP872X_EN_LDO3_M,
585*4882a593Smuzhiyun 	},
586*4882a593Smuzhiyun 	{
587*4882a593Smuzhiyun 		.name = "ldo4",
588*4882a593Smuzhiyun 		.of_match = of_match_ptr("ldo4"),
589*4882a593Smuzhiyun 		.id = LP8725_ID_LDO4,
590*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
591*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
592*4882a593Smuzhiyun 		.volt_table = lp872x_ldo_vtbl,
593*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
594*4882a593Smuzhiyun 		.owner = THIS_MODULE,
595*4882a593Smuzhiyun 		.vsel_reg = LP872X_LDO4_VOUT,
596*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
597*4882a593Smuzhiyun 		.enable_reg = LP8725_LDO_CTRL,
598*4882a593Smuzhiyun 		.enable_mask = LP872X_EN_LDO4_M,
599*4882a593Smuzhiyun 	},
600*4882a593Smuzhiyun 	{
601*4882a593Smuzhiyun 		.name = "ldo5",
602*4882a593Smuzhiyun 		.of_match = of_match_ptr("ldo5"),
603*4882a593Smuzhiyun 		.id = LP8725_ID_LDO5,
604*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
605*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
606*4882a593Smuzhiyun 		.volt_table = lp872x_ldo_vtbl,
607*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
608*4882a593Smuzhiyun 		.owner = THIS_MODULE,
609*4882a593Smuzhiyun 		.vsel_reg = LP872X_LDO5_VOUT,
610*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
611*4882a593Smuzhiyun 		.enable_reg = LP8725_LDO_CTRL,
612*4882a593Smuzhiyun 		.enable_mask = LP872X_EN_LDO5_M,
613*4882a593Smuzhiyun 	},
614*4882a593Smuzhiyun 	{
615*4882a593Smuzhiyun 		.name = "lilo1",
616*4882a593Smuzhiyun 		.of_match = of_match_ptr("lilo1"),
617*4882a593Smuzhiyun 		.id = LP8725_ID_LILO1,
618*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
619*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
620*4882a593Smuzhiyun 		.volt_table = lp8725_lilo_vtbl,
621*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
622*4882a593Smuzhiyun 		.owner = THIS_MODULE,
623*4882a593Smuzhiyun 		.vsel_reg = LP8725_LILO1_VOUT,
624*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
625*4882a593Smuzhiyun 		.enable_reg = LP8725_LDO_CTRL,
626*4882a593Smuzhiyun 		.enable_mask = LP8725_EN_LILO1_M,
627*4882a593Smuzhiyun 	},
628*4882a593Smuzhiyun 	{
629*4882a593Smuzhiyun 		.name = "lilo2",
630*4882a593Smuzhiyun 		.of_match = of_match_ptr("lilo2"),
631*4882a593Smuzhiyun 		.id = LP8725_ID_LILO2,
632*4882a593Smuzhiyun 		.ops = &lp872x_ldo_ops,
633*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
634*4882a593Smuzhiyun 		.volt_table = lp8725_lilo_vtbl,
635*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
636*4882a593Smuzhiyun 		.owner = THIS_MODULE,
637*4882a593Smuzhiyun 		.vsel_reg = LP8725_LILO2_VOUT,
638*4882a593Smuzhiyun 		.vsel_mask = LP872X_VOUT_M,
639*4882a593Smuzhiyun 		.enable_reg = LP8725_LDO_CTRL,
640*4882a593Smuzhiyun 		.enable_mask = LP8725_EN_LILO2_M,
641*4882a593Smuzhiyun 	},
642*4882a593Smuzhiyun 	{
643*4882a593Smuzhiyun 		.name = "buck1",
644*4882a593Smuzhiyun 		.of_match = of_match_ptr("buck1"),
645*4882a593Smuzhiyun 		.id = LP8725_ID_BUCK1,
646*4882a593Smuzhiyun 		.ops = &lp8725_buck_ops,
647*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
648*4882a593Smuzhiyun 		.volt_table = lp8725_buck_vtbl,
649*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
650*4882a593Smuzhiyun 		.owner = THIS_MODULE,
651*4882a593Smuzhiyun 		.enable_reg = LP872X_GENERAL_CFG,
652*4882a593Smuzhiyun 		.enable_mask = LP8725_BUCK1_EN_M,
653*4882a593Smuzhiyun 		.curr_table = lp8725_buck_uA,
654*4882a593Smuzhiyun 		.n_current_limits = ARRAY_SIZE(lp8725_buck_uA),
655*4882a593Smuzhiyun 		.csel_reg = LP8725_BUCK1_VOUT2,
656*4882a593Smuzhiyun 		.csel_mask = LP8725_BUCK_CL_M,
657*4882a593Smuzhiyun 	},
658*4882a593Smuzhiyun 	{
659*4882a593Smuzhiyun 		.name = "buck2",
660*4882a593Smuzhiyun 		.of_match = of_match_ptr("buck2"),
661*4882a593Smuzhiyun 		.id = LP8725_ID_BUCK2,
662*4882a593Smuzhiyun 		.ops = &lp8725_buck_ops,
663*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
664*4882a593Smuzhiyun 		.volt_table = lp8725_buck_vtbl,
665*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
666*4882a593Smuzhiyun 		.owner = THIS_MODULE,
667*4882a593Smuzhiyun 		.enable_reg = LP872X_GENERAL_CFG,
668*4882a593Smuzhiyun 		.enable_mask = LP8725_BUCK2_EN_M,
669*4882a593Smuzhiyun 		.curr_table = lp8725_buck_uA,
670*4882a593Smuzhiyun 		.n_current_limits = ARRAY_SIZE(lp8725_buck_uA),
671*4882a593Smuzhiyun 		.csel_reg = LP8725_BUCK2_VOUT2,
672*4882a593Smuzhiyun 		.csel_mask = LP8725_BUCK_CL_M,
673*4882a593Smuzhiyun 	},
674*4882a593Smuzhiyun };
675*4882a593Smuzhiyun 
lp872x_init_dvs(struct lp872x * lp)676*4882a593Smuzhiyun static int lp872x_init_dvs(struct lp872x *lp)
677*4882a593Smuzhiyun {
678*4882a593Smuzhiyun 	int ret, gpio;
679*4882a593Smuzhiyun 	struct lp872x_dvs *dvs = lp->pdata ? lp->pdata->dvs : NULL;
680*4882a593Smuzhiyun 	enum lp872x_dvs_state pinstate;
681*4882a593Smuzhiyun 	u8 mask[] = { LP8720_EXT_DVS_M, LP8725_DVS1_M | LP8725_DVS2_M };
682*4882a593Smuzhiyun 	u8 default_dvs_mode[] = { LP8720_DEFAULT_DVS, LP8725_DEFAULT_DVS };
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	if (!dvs)
685*4882a593Smuzhiyun 		goto set_default_dvs_mode;
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun 	gpio = dvs->gpio;
688*4882a593Smuzhiyun 	if (!gpio_is_valid(gpio))
689*4882a593Smuzhiyun 		goto set_default_dvs_mode;
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	pinstate = dvs->init_state;
692*4882a593Smuzhiyun 	ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS");
693*4882a593Smuzhiyun 	if (ret) {
694*4882a593Smuzhiyun 		dev_err(lp->dev, "gpio request err: %d\n", ret);
695*4882a593Smuzhiyun 		return ret;
696*4882a593Smuzhiyun 	}
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	lp->dvs_pin = pinstate;
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun 	return 0;
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun set_default_dvs_mode:
703*4882a593Smuzhiyun 	return lp872x_update_bits(lp, LP872X_GENERAL_CFG, mask[lp->chipid],
704*4882a593Smuzhiyun 				default_dvs_mode[lp->chipid]);
705*4882a593Smuzhiyun }
706*4882a593Smuzhiyun 
lp872x_hw_enable(struct lp872x * lp)707*4882a593Smuzhiyun static int lp872x_hw_enable(struct lp872x *lp)
708*4882a593Smuzhiyun {
709*4882a593Smuzhiyun 	int ret, gpio;
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 	if (!lp->pdata)
712*4882a593Smuzhiyun 		return -EINVAL;
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	gpio = lp->pdata->enable_gpio;
715*4882a593Smuzhiyun 	if (!gpio_is_valid(gpio))
716*4882a593Smuzhiyun 		return 0;
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	/* Always set enable GPIO high. */
719*4882a593Smuzhiyun 	ret = devm_gpio_request_one(lp->dev, gpio, GPIOF_OUT_INIT_HIGH, "LP872X EN");
720*4882a593Smuzhiyun 	if (ret) {
721*4882a593Smuzhiyun 		dev_err(lp->dev, "gpio request err: %d\n", ret);
722*4882a593Smuzhiyun 		return ret;
723*4882a593Smuzhiyun 	}
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	/* Each chip has a different enable delay. */
726*4882a593Smuzhiyun 	if (lp->chipid == LP8720)
727*4882a593Smuzhiyun 		usleep_range(LP8720_ENABLE_DELAY, 1.5 * LP8720_ENABLE_DELAY);
728*4882a593Smuzhiyun 	else
729*4882a593Smuzhiyun 		usleep_range(LP8725_ENABLE_DELAY, 1.5 * LP8725_ENABLE_DELAY);
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	return 0;
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun 
lp872x_config(struct lp872x * lp)734*4882a593Smuzhiyun static int lp872x_config(struct lp872x *lp)
735*4882a593Smuzhiyun {
736*4882a593Smuzhiyun 	struct lp872x_platform_data *pdata = lp->pdata;
737*4882a593Smuzhiyun 	int ret;
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	if (!pdata || !pdata->update_config)
740*4882a593Smuzhiyun 		goto init_dvs;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	ret = lp872x_write_byte(lp, LP872X_GENERAL_CFG, pdata->general_config);
743*4882a593Smuzhiyun 	if (ret)
744*4882a593Smuzhiyun 		return ret;
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun init_dvs:
747*4882a593Smuzhiyun 	return lp872x_init_dvs(lp);
748*4882a593Smuzhiyun }
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun static struct regulator_init_data
lp872x_find_regulator_init_data(int id,struct lp872x * lp)751*4882a593Smuzhiyun *lp872x_find_regulator_init_data(int id, struct lp872x *lp)
752*4882a593Smuzhiyun {
753*4882a593Smuzhiyun 	struct lp872x_platform_data *pdata = lp->pdata;
754*4882a593Smuzhiyun 	int i;
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	if (!pdata)
757*4882a593Smuzhiyun 		return NULL;
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	for (i = 0; i < lp->num_regulators; i++) {
760*4882a593Smuzhiyun 		if (pdata->regulator_data[i].id == id)
761*4882a593Smuzhiyun 			return pdata->regulator_data[i].init_data;
762*4882a593Smuzhiyun 	}
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	return NULL;
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun 
lp872x_regulator_register(struct lp872x * lp)767*4882a593Smuzhiyun static int lp872x_regulator_register(struct lp872x *lp)
768*4882a593Smuzhiyun {
769*4882a593Smuzhiyun 	const struct regulator_desc *desc;
770*4882a593Smuzhiyun 	struct regulator_config cfg = { };
771*4882a593Smuzhiyun 	struct regulator_dev *rdev;
772*4882a593Smuzhiyun 	int i;
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	for (i = 0; i < lp->num_regulators; i++) {
775*4882a593Smuzhiyun 		desc = (lp->chipid == LP8720) ? &lp8720_regulator_desc[i] :
776*4882a593Smuzhiyun 						&lp8725_regulator_desc[i];
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun 		cfg.dev = lp->dev;
779*4882a593Smuzhiyun 		cfg.init_data = lp872x_find_regulator_init_data(desc->id, lp);
780*4882a593Smuzhiyun 		cfg.driver_data = lp;
781*4882a593Smuzhiyun 		cfg.regmap = lp->regmap;
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 		rdev = devm_regulator_register(lp->dev, desc, &cfg);
784*4882a593Smuzhiyun 		if (IS_ERR(rdev)) {
785*4882a593Smuzhiyun 			dev_err(lp->dev, "regulator register err");
786*4882a593Smuzhiyun 			return PTR_ERR(rdev);
787*4882a593Smuzhiyun 		}
788*4882a593Smuzhiyun 	}
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	return 0;
791*4882a593Smuzhiyun }
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun static const struct regmap_config lp872x_regmap_config = {
794*4882a593Smuzhiyun 	.reg_bits = 8,
795*4882a593Smuzhiyun 	.val_bits = 8,
796*4882a593Smuzhiyun 	.max_register = MAX_REGISTERS,
797*4882a593Smuzhiyun };
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun #ifdef CONFIG_OF
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun #define LP872X_VALID_OPMODE	(REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL)
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun static struct of_regulator_match lp8720_matches[] = {
804*4882a593Smuzhiyun 	{ .name = "ldo1", .driver_data = (void *)LP8720_ID_LDO1, },
805*4882a593Smuzhiyun 	{ .name = "ldo2", .driver_data = (void *)LP8720_ID_LDO2, },
806*4882a593Smuzhiyun 	{ .name = "ldo3", .driver_data = (void *)LP8720_ID_LDO3, },
807*4882a593Smuzhiyun 	{ .name = "ldo4", .driver_data = (void *)LP8720_ID_LDO4, },
808*4882a593Smuzhiyun 	{ .name = "ldo5", .driver_data = (void *)LP8720_ID_LDO5, },
809*4882a593Smuzhiyun 	{ .name = "buck", .driver_data = (void *)LP8720_ID_BUCK, },
810*4882a593Smuzhiyun };
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun static struct of_regulator_match lp8725_matches[] = {
813*4882a593Smuzhiyun 	{ .name = "ldo1", .driver_data = (void *)LP8725_ID_LDO1, },
814*4882a593Smuzhiyun 	{ .name = "ldo2", .driver_data = (void *)LP8725_ID_LDO2, },
815*4882a593Smuzhiyun 	{ .name = "ldo3", .driver_data = (void *)LP8725_ID_LDO3, },
816*4882a593Smuzhiyun 	{ .name = "ldo4", .driver_data = (void *)LP8725_ID_LDO4, },
817*4882a593Smuzhiyun 	{ .name = "ldo5", .driver_data = (void *)LP8725_ID_LDO5, },
818*4882a593Smuzhiyun 	{ .name = "lilo1", .driver_data = (void *)LP8725_ID_LILO1, },
819*4882a593Smuzhiyun 	{ .name = "lilo2", .driver_data = (void *)LP8725_ID_LILO2, },
820*4882a593Smuzhiyun 	{ .name = "buck1", .driver_data = (void *)LP8725_ID_BUCK1, },
821*4882a593Smuzhiyun 	{ .name = "buck2", .driver_data = (void *)LP8725_ID_BUCK2, },
822*4882a593Smuzhiyun };
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun static struct lp872x_platform_data
lp872x_populate_pdata_from_dt(struct device * dev,enum lp872x_id which)825*4882a593Smuzhiyun *lp872x_populate_pdata_from_dt(struct device *dev, enum lp872x_id which)
826*4882a593Smuzhiyun {
827*4882a593Smuzhiyun 	struct device_node *np = dev->of_node;
828*4882a593Smuzhiyun 	struct lp872x_platform_data *pdata;
829*4882a593Smuzhiyun 	struct of_regulator_match *match;
830*4882a593Smuzhiyun 	int num_matches;
831*4882a593Smuzhiyun 	int count;
832*4882a593Smuzhiyun 	int i;
833*4882a593Smuzhiyun 	u8 dvs_state;
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
836*4882a593Smuzhiyun 	if (!pdata)
837*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	of_property_read_u8(np, "ti,general-config", &pdata->general_config);
840*4882a593Smuzhiyun 	if (of_find_property(np, "ti,update-config", NULL))
841*4882a593Smuzhiyun 		pdata->update_config = true;
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun 	pdata->dvs = devm_kzalloc(dev, sizeof(struct lp872x_dvs), GFP_KERNEL);
844*4882a593Smuzhiyun 	if (!pdata->dvs)
845*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 	pdata->dvs->gpio = of_get_named_gpio(np, "ti,dvs-gpio", 0);
848*4882a593Smuzhiyun 	of_property_read_u8(np, "ti,dvs-vsel", (u8 *)&pdata->dvs->vsel);
849*4882a593Smuzhiyun 	of_property_read_u8(np, "ti,dvs-state", &dvs_state);
850*4882a593Smuzhiyun 	pdata->dvs->init_state = dvs_state ? DVS_HIGH : DVS_LOW;
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 	pdata->enable_gpio = of_get_named_gpio(np, "enable-gpios", 0);
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun 	if (of_get_child_count(np) == 0)
855*4882a593Smuzhiyun 		goto out;
856*4882a593Smuzhiyun 
857*4882a593Smuzhiyun 	switch (which) {
858*4882a593Smuzhiyun 	case LP8720:
859*4882a593Smuzhiyun 		match = lp8720_matches;
860*4882a593Smuzhiyun 		num_matches = ARRAY_SIZE(lp8720_matches);
861*4882a593Smuzhiyun 		break;
862*4882a593Smuzhiyun 	case LP8725:
863*4882a593Smuzhiyun 		match = lp8725_matches;
864*4882a593Smuzhiyun 		num_matches = ARRAY_SIZE(lp8725_matches);
865*4882a593Smuzhiyun 		break;
866*4882a593Smuzhiyun 	default:
867*4882a593Smuzhiyun 		goto out;
868*4882a593Smuzhiyun 	}
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 	count = of_regulator_match(dev, np, match, num_matches);
871*4882a593Smuzhiyun 	if (count <= 0)
872*4882a593Smuzhiyun 		goto out;
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 	for (i = 0; i < num_matches; i++) {
875*4882a593Smuzhiyun 		pdata->regulator_data[i].id =
876*4882a593Smuzhiyun 				(enum lp872x_regulator_id)match[i].driver_data;
877*4882a593Smuzhiyun 		pdata->regulator_data[i].init_data = match[i].init_data;
878*4882a593Smuzhiyun 	}
879*4882a593Smuzhiyun out:
880*4882a593Smuzhiyun 	return pdata;
881*4882a593Smuzhiyun }
882*4882a593Smuzhiyun #else
883*4882a593Smuzhiyun static struct lp872x_platform_data
lp872x_populate_pdata_from_dt(struct device * dev,enum lp872x_id which)884*4882a593Smuzhiyun *lp872x_populate_pdata_from_dt(struct device *dev, enum lp872x_id which)
885*4882a593Smuzhiyun {
886*4882a593Smuzhiyun 	return NULL;
887*4882a593Smuzhiyun }
888*4882a593Smuzhiyun #endif
889*4882a593Smuzhiyun 
lp872x_probe(struct i2c_client * cl,const struct i2c_device_id * id)890*4882a593Smuzhiyun static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
891*4882a593Smuzhiyun {
892*4882a593Smuzhiyun 	struct lp872x *lp;
893*4882a593Smuzhiyun 	struct lp872x_platform_data *pdata;
894*4882a593Smuzhiyun 	int ret;
895*4882a593Smuzhiyun 	const int lp872x_num_regulators[] = {
896*4882a593Smuzhiyun 		[LP8720] = LP8720_NUM_REGULATORS,
897*4882a593Smuzhiyun 		[LP8725] = LP8725_NUM_REGULATORS,
898*4882a593Smuzhiyun 	};
899*4882a593Smuzhiyun 
900*4882a593Smuzhiyun 	if (cl->dev.of_node) {
901*4882a593Smuzhiyun 		pdata = lp872x_populate_pdata_from_dt(&cl->dev,
902*4882a593Smuzhiyun 					      (enum lp872x_id)id->driver_data);
903*4882a593Smuzhiyun 		if (IS_ERR(pdata))
904*4882a593Smuzhiyun 			return PTR_ERR(pdata);
905*4882a593Smuzhiyun 	} else {
906*4882a593Smuzhiyun 		pdata = dev_get_platdata(&cl->dev);
907*4882a593Smuzhiyun 	}
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 	lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL);
910*4882a593Smuzhiyun 	if (!lp)
911*4882a593Smuzhiyun 		return -ENOMEM;
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun 	lp->num_regulators = lp872x_num_regulators[id->driver_data];
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun 	lp->regmap = devm_regmap_init_i2c(cl, &lp872x_regmap_config);
916*4882a593Smuzhiyun 	if (IS_ERR(lp->regmap)) {
917*4882a593Smuzhiyun 		ret = PTR_ERR(lp->regmap);
918*4882a593Smuzhiyun 		dev_err(&cl->dev, "regmap init i2c err: %d\n", ret);
919*4882a593Smuzhiyun 		return ret;
920*4882a593Smuzhiyun 	}
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun 	lp->dev = &cl->dev;
923*4882a593Smuzhiyun 	lp->pdata = pdata;
924*4882a593Smuzhiyun 	lp->chipid = id->driver_data;
925*4882a593Smuzhiyun 	i2c_set_clientdata(cl, lp);
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun 	ret = lp872x_hw_enable(lp);
928*4882a593Smuzhiyun 	if (ret)
929*4882a593Smuzhiyun 		return ret;
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun 	ret = lp872x_config(lp);
932*4882a593Smuzhiyun 	if (ret)
933*4882a593Smuzhiyun 		return ret;
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun 	return lp872x_regulator_register(lp);
936*4882a593Smuzhiyun }
937*4882a593Smuzhiyun 
938*4882a593Smuzhiyun static const struct of_device_id lp872x_dt_ids[] = {
939*4882a593Smuzhiyun 	{ .compatible = "ti,lp8720", },
940*4882a593Smuzhiyun 	{ .compatible = "ti,lp8725", },
941*4882a593Smuzhiyun 	{ }
942*4882a593Smuzhiyun };
943*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, lp872x_dt_ids);
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun static const struct i2c_device_id lp872x_ids[] = {
946*4882a593Smuzhiyun 	{"lp8720", LP8720},
947*4882a593Smuzhiyun 	{"lp8725", LP8725},
948*4882a593Smuzhiyun 	{ }
949*4882a593Smuzhiyun };
950*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, lp872x_ids);
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun static struct i2c_driver lp872x_driver = {
953*4882a593Smuzhiyun 	.driver = {
954*4882a593Smuzhiyun 		.name = "lp872x",
955*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(lp872x_dt_ids),
956*4882a593Smuzhiyun 	},
957*4882a593Smuzhiyun 	.probe = lp872x_probe,
958*4882a593Smuzhiyun 	.id_table = lp872x_ids,
959*4882a593Smuzhiyun };
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun module_i2c_driver(lp872x_driver);
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun MODULE_DESCRIPTION("TI/National Semiconductor LP872x PMU Regulator Driver");
964*4882a593Smuzhiyun MODULE_AUTHOR("Milo Kim");
965*4882a593Smuzhiyun MODULE_LICENSE("GPL");
966