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