xref: /OK3568_Linux_fs/kernel/drivers/regulator/lp8788-ldo.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * TI LP8788 MFD - ldo regulator driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright 2012 Texas Instruments
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/err.h>
13*4882a593Smuzhiyun #include <linux/platform_device.h>
14*4882a593Smuzhiyun #include <linux/regulator/driver.h>
15*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
16*4882a593Smuzhiyun #include <linux/mfd/lp8788.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun /* register address */
19*4882a593Smuzhiyun #define LP8788_EN_LDO_A			0x0D	/* DLDO 1 ~ 8 */
20*4882a593Smuzhiyun #define LP8788_EN_LDO_B			0x0E	/* DLDO 9 ~ 12, ALDO 1 ~ 4 */
21*4882a593Smuzhiyun #define LP8788_EN_LDO_C			0x0F	/* ALDO 5 ~ 10 */
22*4882a593Smuzhiyun #define LP8788_EN_SEL			0x10
23*4882a593Smuzhiyun #define LP8788_DLDO1_VOUT		0x2E
24*4882a593Smuzhiyun #define LP8788_DLDO2_VOUT		0x2F
25*4882a593Smuzhiyun #define LP8788_DLDO3_VOUT		0x30
26*4882a593Smuzhiyun #define LP8788_DLDO4_VOUT		0x31
27*4882a593Smuzhiyun #define LP8788_DLDO5_VOUT		0x32
28*4882a593Smuzhiyun #define LP8788_DLDO6_VOUT		0x33
29*4882a593Smuzhiyun #define LP8788_DLDO7_VOUT		0x34
30*4882a593Smuzhiyun #define LP8788_DLDO8_VOUT		0x35
31*4882a593Smuzhiyun #define LP8788_DLDO9_VOUT		0x36
32*4882a593Smuzhiyun #define LP8788_DLDO10_VOUT		0x37
33*4882a593Smuzhiyun #define LP8788_DLDO11_VOUT		0x38
34*4882a593Smuzhiyun #define LP8788_DLDO12_VOUT		0x39
35*4882a593Smuzhiyun #define LP8788_ALDO1_VOUT		0x3A
36*4882a593Smuzhiyun #define LP8788_ALDO2_VOUT		0x3B
37*4882a593Smuzhiyun #define LP8788_ALDO3_VOUT		0x3C
38*4882a593Smuzhiyun #define LP8788_ALDO4_VOUT		0x3D
39*4882a593Smuzhiyun #define LP8788_ALDO5_VOUT		0x3E
40*4882a593Smuzhiyun #define LP8788_ALDO6_VOUT		0x3F
41*4882a593Smuzhiyun #define LP8788_ALDO7_VOUT		0x40
42*4882a593Smuzhiyun #define LP8788_ALDO8_VOUT		0x41
43*4882a593Smuzhiyun #define LP8788_ALDO9_VOUT		0x42
44*4882a593Smuzhiyun #define LP8788_ALDO10_VOUT		0x43
45*4882a593Smuzhiyun #define LP8788_DLDO1_TIMESTEP		0x44
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /* mask/shift bits */
48*4882a593Smuzhiyun #define LP8788_EN_DLDO1_M		BIT(0)	/* Addr 0Dh ~ 0Fh */
49*4882a593Smuzhiyun #define LP8788_EN_DLDO2_M		BIT(1)
50*4882a593Smuzhiyun #define LP8788_EN_DLDO3_M		BIT(2)
51*4882a593Smuzhiyun #define LP8788_EN_DLDO4_M		BIT(3)
52*4882a593Smuzhiyun #define LP8788_EN_DLDO5_M		BIT(4)
53*4882a593Smuzhiyun #define LP8788_EN_DLDO6_M		BIT(5)
54*4882a593Smuzhiyun #define LP8788_EN_DLDO7_M		BIT(6)
55*4882a593Smuzhiyun #define LP8788_EN_DLDO8_M		BIT(7)
56*4882a593Smuzhiyun #define LP8788_EN_DLDO9_M		BIT(0)
57*4882a593Smuzhiyun #define LP8788_EN_DLDO10_M		BIT(1)
58*4882a593Smuzhiyun #define LP8788_EN_DLDO11_M		BIT(2)
59*4882a593Smuzhiyun #define LP8788_EN_DLDO12_M		BIT(3)
60*4882a593Smuzhiyun #define LP8788_EN_ALDO1_M		BIT(4)
61*4882a593Smuzhiyun #define LP8788_EN_ALDO2_M		BIT(5)
62*4882a593Smuzhiyun #define LP8788_EN_ALDO3_M		BIT(6)
63*4882a593Smuzhiyun #define LP8788_EN_ALDO4_M		BIT(7)
64*4882a593Smuzhiyun #define LP8788_EN_ALDO5_M		BIT(0)
65*4882a593Smuzhiyun #define LP8788_EN_ALDO6_M		BIT(1)
66*4882a593Smuzhiyun #define LP8788_EN_ALDO7_M		BIT(2)
67*4882a593Smuzhiyun #define LP8788_EN_ALDO8_M		BIT(3)
68*4882a593Smuzhiyun #define LP8788_EN_ALDO9_M		BIT(4)
69*4882a593Smuzhiyun #define LP8788_EN_ALDO10_M		BIT(5)
70*4882a593Smuzhiyun #define LP8788_EN_SEL_DLDO911_M		BIT(0)	/* Addr 10h */
71*4882a593Smuzhiyun #define LP8788_EN_SEL_DLDO7_M		BIT(1)
72*4882a593Smuzhiyun #define LP8788_EN_SEL_ALDO7_M		BIT(2)
73*4882a593Smuzhiyun #define LP8788_EN_SEL_ALDO5_M		BIT(3)
74*4882a593Smuzhiyun #define LP8788_EN_SEL_ALDO234_M		BIT(4)
75*4882a593Smuzhiyun #define LP8788_EN_SEL_ALDO1_M		BIT(5)
76*4882a593Smuzhiyun #define LP8788_VOUT_5BIT_M		0x1F	/* Addr 2Eh ~ 43h */
77*4882a593Smuzhiyun #define LP8788_VOUT_4BIT_M		0x0F
78*4882a593Smuzhiyun #define LP8788_VOUT_3BIT_M		0x07
79*4882a593Smuzhiyun #define LP8788_VOUT_1BIT_M		0x01
80*4882a593Smuzhiyun #define LP8788_STARTUP_TIME_M		0xF8	/* Addr 44h ~ 59h */
81*4882a593Smuzhiyun #define LP8788_STARTUP_TIME_S		3
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun #define ENABLE_TIME_USEC		32
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun enum lp8788_ldo_id {
86*4882a593Smuzhiyun 	DLDO1,
87*4882a593Smuzhiyun 	DLDO2,
88*4882a593Smuzhiyun 	DLDO3,
89*4882a593Smuzhiyun 	DLDO4,
90*4882a593Smuzhiyun 	DLDO5,
91*4882a593Smuzhiyun 	DLDO6,
92*4882a593Smuzhiyun 	DLDO7,
93*4882a593Smuzhiyun 	DLDO8,
94*4882a593Smuzhiyun 	DLDO9,
95*4882a593Smuzhiyun 	DLDO10,
96*4882a593Smuzhiyun 	DLDO11,
97*4882a593Smuzhiyun 	DLDO12,
98*4882a593Smuzhiyun 	ALDO1,
99*4882a593Smuzhiyun 	ALDO2,
100*4882a593Smuzhiyun 	ALDO3,
101*4882a593Smuzhiyun 	ALDO4,
102*4882a593Smuzhiyun 	ALDO5,
103*4882a593Smuzhiyun 	ALDO6,
104*4882a593Smuzhiyun 	ALDO7,
105*4882a593Smuzhiyun 	ALDO8,
106*4882a593Smuzhiyun 	ALDO9,
107*4882a593Smuzhiyun 	ALDO10,
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun struct lp8788_ldo {
111*4882a593Smuzhiyun 	struct lp8788 *lp;
112*4882a593Smuzhiyun 	struct regulator_desc *desc;
113*4882a593Smuzhiyun 	struct regulator_dev *regulator;
114*4882a593Smuzhiyun 	struct gpio_desc *ena_gpiod;
115*4882a593Smuzhiyun };
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun /* DLDO 1, 2, 3, 9 voltage table */
118*4882a593Smuzhiyun static const int lp8788_dldo1239_vtbl[] = {
119*4882a593Smuzhiyun 	1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
120*4882a593Smuzhiyun 	2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
121*4882a593Smuzhiyun 	2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
122*4882a593Smuzhiyun 	2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
123*4882a593Smuzhiyun };
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun /* DLDO 4 voltage table */
126*4882a593Smuzhiyun static const int lp8788_dldo4_vtbl[] = { 1800000, 3000000 };
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun /* DLDO 5, 7, 8 and ALDO 6 voltage table */
129*4882a593Smuzhiyun static const int lp8788_dldo578_aldo6_vtbl[] = {
130*4882a593Smuzhiyun 	1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
131*4882a593Smuzhiyun 	2600000, 2700000, 2800000, 2900000, 3000000, 3000000, 3000000, 3000000,
132*4882a593Smuzhiyun };
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun /* DLDO 6 voltage table */
135*4882a593Smuzhiyun static const int lp8788_dldo6_vtbl[] = {
136*4882a593Smuzhiyun 	3000000, 3100000, 3200000, 3300000, 3400000, 3500000, 3600000, 3600000,
137*4882a593Smuzhiyun };
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun /* DLDO 10, 11 voltage table */
140*4882a593Smuzhiyun static const int lp8788_dldo1011_vtbl[] = {
141*4882a593Smuzhiyun 	1100000, 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000,
142*4882a593Smuzhiyun 	1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000,
143*4882a593Smuzhiyun };
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun /* ALDO 1 voltage table */
146*4882a593Smuzhiyun static const int lp8788_aldo1_vtbl[] = { 1800000, 2850000 };
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun /* ALDO 7 voltage table */
149*4882a593Smuzhiyun static const int lp8788_aldo7_vtbl[] = {
150*4882a593Smuzhiyun 	1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000,
151*4882a593Smuzhiyun };
152*4882a593Smuzhiyun 
lp8788_ldo_enable_time(struct regulator_dev * rdev)153*4882a593Smuzhiyun static int lp8788_ldo_enable_time(struct regulator_dev *rdev)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
156*4882a593Smuzhiyun 	enum lp8788_ldo_id id = rdev_get_id(rdev);
157*4882a593Smuzhiyun 	u8 val, addr = LP8788_DLDO1_TIMESTEP + id;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	if (lp8788_read_byte(ldo->lp, addr, &val))
160*4882a593Smuzhiyun 		return -EINVAL;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	return ENABLE_TIME_USEC * val;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun static const struct regulator_ops lp8788_ldo_voltage_table_ops = {
168*4882a593Smuzhiyun 	.list_voltage = regulator_list_voltage_table,
169*4882a593Smuzhiyun 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
170*4882a593Smuzhiyun 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
171*4882a593Smuzhiyun 	.enable = regulator_enable_regmap,
172*4882a593Smuzhiyun 	.disable = regulator_disable_regmap,
173*4882a593Smuzhiyun 	.is_enabled = regulator_is_enabled_regmap,
174*4882a593Smuzhiyun 	.enable_time = lp8788_ldo_enable_time,
175*4882a593Smuzhiyun };
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun static const struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
178*4882a593Smuzhiyun 	.list_voltage = regulator_list_voltage_linear,
179*4882a593Smuzhiyun 	.enable = regulator_enable_regmap,
180*4882a593Smuzhiyun 	.disable = regulator_disable_regmap,
181*4882a593Smuzhiyun 	.is_enabled = regulator_is_enabled_regmap,
182*4882a593Smuzhiyun 	.enable_time = lp8788_ldo_enable_time,
183*4882a593Smuzhiyun };
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun static const struct regulator_desc lp8788_dldo_desc[] = {
186*4882a593Smuzhiyun 	{
187*4882a593Smuzhiyun 		.name = "dldo1",
188*4882a593Smuzhiyun 		.id = DLDO1,
189*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
190*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
191*4882a593Smuzhiyun 		.volt_table = lp8788_dldo1239_vtbl,
192*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
193*4882a593Smuzhiyun 		.owner = THIS_MODULE,
194*4882a593Smuzhiyun 		.vsel_reg = LP8788_DLDO1_VOUT,
195*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_5BIT_M,
196*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_A,
197*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO1_M,
198*4882a593Smuzhiyun 	},
199*4882a593Smuzhiyun 	{
200*4882a593Smuzhiyun 		.name = "dldo2",
201*4882a593Smuzhiyun 		.id = DLDO2,
202*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
203*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
204*4882a593Smuzhiyun 		.volt_table = lp8788_dldo1239_vtbl,
205*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
206*4882a593Smuzhiyun 		.owner = THIS_MODULE,
207*4882a593Smuzhiyun 		.vsel_reg = LP8788_DLDO2_VOUT,
208*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_5BIT_M,
209*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_A,
210*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO2_M,
211*4882a593Smuzhiyun 	},
212*4882a593Smuzhiyun 	{
213*4882a593Smuzhiyun 		.name = "dldo3",
214*4882a593Smuzhiyun 		.id = DLDO3,
215*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
216*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
217*4882a593Smuzhiyun 		.volt_table = lp8788_dldo1239_vtbl,
218*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
219*4882a593Smuzhiyun 		.owner = THIS_MODULE,
220*4882a593Smuzhiyun 		.vsel_reg = LP8788_DLDO3_VOUT,
221*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_5BIT_M,
222*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_A,
223*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO3_M,
224*4882a593Smuzhiyun 	},
225*4882a593Smuzhiyun 	{
226*4882a593Smuzhiyun 		.name = "dldo4",
227*4882a593Smuzhiyun 		.id = DLDO4,
228*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
229*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo4_vtbl),
230*4882a593Smuzhiyun 		.volt_table = lp8788_dldo4_vtbl,
231*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
232*4882a593Smuzhiyun 		.owner = THIS_MODULE,
233*4882a593Smuzhiyun 		.vsel_reg = LP8788_DLDO4_VOUT,
234*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_1BIT_M,
235*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_A,
236*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO4_M,
237*4882a593Smuzhiyun 	},
238*4882a593Smuzhiyun 	{
239*4882a593Smuzhiyun 		.name = "dldo5",
240*4882a593Smuzhiyun 		.id = DLDO5,
241*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
242*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
243*4882a593Smuzhiyun 		.volt_table = lp8788_dldo578_aldo6_vtbl,
244*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
245*4882a593Smuzhiyun 		.owner = THIS_MODULE,
246*4882a593Smuzhiyun 		.vsel_reg = LP8788_DLDO5_VOUT,
247*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_4BIT_M,
248*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_A,
249*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO5_M,
250*4882a593Smuzhiyun 	},
251*4882a593Smuzhiyun 	{
252*4882a593Smuzhiyun 		.name = "dldo6",
253*4882a593Smuzhiyun 		.id = DLDO6,
254*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
255*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo6_vtbl),
256*4882a593Smuzhiyun 		.volt_table = lp8788_dldo6_vtbl,
257*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
258*4882a593Smuzhiyun 		.owner = THIS_MODULE,
259*4882a593Smuzhiyun 		.vsel_reg = LP8788_DLDO6_VOUT,
260*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_3BIT_M,
261*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_A,
262*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO6_M,
263*4882a593Smuzhiyun 	},
264*4882a593Smuzhiyun 	{
265*4882a593Smuzhiyun 		.name = "dldo7",
266*4882a593Smuzhiyun 		.id = DLDO7,
267*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
268*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
269*4882a593Smuzhiyun 		.volt_table = lp8788_dldo578_aldo6_vtbl,
270*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
271*4882a593Smuzhiyun 		.owner = THIS_MODULE,
272*4882a593Smuzhiyun 		.vsel_reg = LP8788_DLDO7_VOUT,
273*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_4BIT_M,
274*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_A,
275*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO7_M,
276*4882a593Smuzhiyun 	},
277*4882a593Smuzhiyun 	{
278*4882a593Smuzhiyun 		.name = "dldo8",
279*4882a593Smuzhiyun 		.id = DLDO8,
280*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
281*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
282*4882a593Smuzhiyun 		.volt_table = lp8788_dldo578_aldo6_vtbl,
283*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
284*4882a593Smuzhiyun 		.owner = THIS_MODULE,
285*4882a593Smuzhiyun 		.vsel_reg = LP8788_DLDO8_VOUT,
286*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_4BIT_M,
287*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_A,
288*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO8_M,
289*4882a593Smuzhiyun 	},
290*4882a593Smuzhiyun 	{
291*4882a593Smuzhiyun 		.name = "dldo9",
292*4882a593Smuzhiyun 		.id = DLDO9,
293*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
294*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
295*4882a593Smuzhiyun 		.volt_table = lp8788_dldo1239_vtbl,
296*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
297*4882a593Smuzhiyun 		.owner = THIS_MODULE,
298*4882a593Smuzhiyun 		.vsel_reg = LP8788_DLDO9_VOUT,
299*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_5BIT_M,
300*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_B,
301*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO9_M,
302*4882a593Smuzhiyun 	},
303*4882a593Smuzhiyun 	{
304*4882a593Smuzhiyun 		.name = "dldo10",
305*4882a593Smuzhiyun 		.id = DLDO10,
306*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
307*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl),
308*4882a593Smuzhiyun 		.volt_table = lp8788_dldo1011_vtbl,
309*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
310*4882a593Smuzhiyun 		.owner = THIS_MODULE,
311*4882a593Smuzhiyun 		.vsel_reg = LP8788_DLDO10_VOUT,
312*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_4BIT_M,
313*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_B,
314*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO10_M,
315*4882a593Smuzhiyun 	},
316*4882a593Smuzhiyun 	{
317*4882a593Smuzhiyun 		.name = "dldo11",
318*4882a593Smuzhiyun 		.id = DLDO11,
319*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
320*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl),
321*4882a593Smuzhiyun 		.volt_table = lp8788_dldo1011_vtbl,
322*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
323*4882a593Smuzhiyun 		.owner = THIS_MODULE,
324*4882a593Smuzhiyun 		.vsel_reg = LP8788_DLDO11_VOUT,
325*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_4BIT_M,
326*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_B,
327*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO11_M,
328*4882a593Smuzhiyun 	},
329*4882a593Smuzhiyun 	{
330*4882a593Smuzhiyun 		.name = "dldo12",
331*4882a593Smuzhiyun 		.id = DLDO12,
332*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_fixed_ops,
333*4882a593Smuzhiyun 		.n_voltages = 1,
334*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
335*4882a593Smuzhiyun 		.owner = THIS_MODULE,
336*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_B,
337*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_DLDO12_M,
338*4882a593Smuzhiyun 		.min_uV = 2500000,
339*4882a593Smuzhiyun 	},
340*4882a593Smuzhiyun };
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun static const struct regulator_desc lp8788_aldo_desc[] = {
343*4882a593Smuzhiyun 	{
344*4882a593Smuzhiyun 		.name = "aldo1",
345*4882a593Smuzhiyun 		.id = ALDO1,
346*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
347*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_aldo1_vtbl),
348*4882a593Smuzhiyun 		.volt_table = lp8788_aldo1_vtbl,
349*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
350*4882a593Smuzhiyun 		.owner = THIS_MODULE,
351*4882a593Smuzhiyun 		.vsel_reg = LP8788_ALDO1_VOUT,
352*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_1BIT_M,
353*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_B,
354*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_ALDO1_M,
355*4882a593Smuzhiyun 	},
356*4882a593Smuzhiyun 	{
357*4882a593Smuzhiyun 		.name = "aldo2",
358*4882a593Smuzhiyun 		.id = ALDO2,
359*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_fixed_ops,
360*4882a593Smuzhiyun 		.n_voltages = 1,
361*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
362*4882a593Smuzhiyun 		.owner = THIS_MODULE,
363*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_B,
364*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_ALDO2_M,
365*4882a593Smuzhiyun 		.min_uV = 2850000,
366*4882a593Smuzhiyun 	},
367*4882a593Smuzhiyun 	{
368*4882a593Smuzhiyun 		.name = "aldo3",
369*4882a593Smuzhiyun 		.id = ALDO3,
370*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_fixed_ops,
371*4882a593Smuzhiyun 		.n_voltages = 1,
372*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
373*4882a593Smuzhiyun 		.owner = THIS_MODULE,
374*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_B,
375*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_ALDO3_M,
376*4882a593Smuzhiyun 		.min_uV = 2850000,
377*4882a593Smuzhiyun 	},
378*4882a593Smuzhiyun 	{
379*4882a593Smuzhiyun 		.name = "aldo4",
380*4882a593Smuzhiyun 		.id = ALDO4,
381*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_fixed_ops,
382*4882a593Smuzhiyun 		.n_voltages = 1,
383*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
384*4882a593Smuzhiyun 		.owner = THIS_MODULE,
385*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_B,
386*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_ALDO4_M,
387*4882a593Smuzhiyun 		.min_uV = 2850000,
388*4882a593Smuzhiyun 	},
389*4882a593Smuzhiyun 	{
390*4882a593Smuzhiyun 		.name = "aldo5",
391*4882a593Smuzhiyun 		.id = ALDO5,
392*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_fixed_ops,
393*4882a593Smuzhiyun 		.n_voltages = 1,
394*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
395*4882a593Smuzhiyun 		.owner = THIS_MODULE,
396*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_C,
397*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_ALDO5_M,
398*4882a593Smuzhiyun 		.min_uV = 2850000,
399*4882a593Smuzhiyun 	},
400*4882a593Smuzhiyun 	{
401*4882a593Smuzhiyun 		.name = "aldo6",
402*4882a593Smuzhiyun 		.id = ALDO6,
403*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
404*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
405*4882a593Smuzhiyun 		.volt_table = lp8788_dldo578_aldo6_vtbl,
406*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
407*4882a593Smuzhiyun 		.owner = THIS_MODULE,
408*4882a593Smuzhiyun 		.vsel_reg = LP8788_ALDO6_VOUT,
409*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_4BIT_M,
410*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_C,
411*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_ALDO6_M,
412*4882a593Smuzhiyun 	},
413*4882a593Smuzhiyun 	{
414*4882a593Smuzhiyun 		.name = "aldo7",
415*4882a593Smuzhiyun 		.id = ALDO7,
416*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_table_ops,
417*4882a593Smuzhiyun 		.n_voltages = ARRAY_SIZE(lp8788_aldo7_vtbl),
418*4882a593Smuzhiyun 		.volt_table = lp8788_aldo7_vtbl,
419*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
420*4882a593Smuzhiyun 		.owner = THIS_MODULE,
421*4882a593Smuzhiyun 		.vsel_reg = LP8788_ALDO7_VOUT,
422*4882a593Smuzhiyun 		.vsel_mask = LP8788_VOUT_3BIT_M,
423*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_C,
424*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_ALDO7_M,
425*4882a593Smuzhiyun 	},
426*4882a593Smuzhiyun 	{
427*4882a593Smuzhiyun 		.name = "aldo8",
428*4882a593Smuzhiyun 		.id = ALDO8,
429*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_fixed_ops,
430*4882a593Smuzhiyun 		.n_voltages = 1,
431*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
432*4882a593Smuzhiyun 		.owner = THIS_MODULE,
433*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_C,
434*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_ALDO8_M,
435*4882a593Smuzhiyun 		.min_uV = 2500000,
436*4882a593Smuzhiyun 	},
437*4882a593Smuzhiyun 	{
438*4882a593Smuzhiyun 		.name = "aldo9",
439*4882a593Smuzhiyun 		.id = ALDO9,
440*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_fixed_ops,
441*4882a593Smuzhiyun 		.n_voltages = 1,
442*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
443*4882a593Smuzhiyun 		.owner = THIS_MODULE,
444*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_C,
445*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_ALDO9_M,
446*4882a593Smuzhiyun 		.min_uV = 2500000,
447*4882a593Smuzhiyun 	},
448*4882a593Smuzhiyun 	{
449*4882a593Smuzhiyun 		.name = "aldo10",
450*4882a593Smuzhiyun 		.id = ALDO10,
451*4882a593Smuzhiyun 		.ops = &lp8788_ldo_voltage_fixed_ops,
452*4882a593Smuzhiyun 		.n_voltages = 1,
453*4882a593Smuzhiyun 		.type = REGULATOR_VOLTAGE,
454*4882a593Smuzhiyun 		.owner = THIS_MODULE,
455*4882a593Smuzhiyun 		.enable_reg = LP8788_EN_LDO_C,
456*4882a593Smuzhiyun 		.enable_mask = LP8788_EN_ALDO10_M,
457*4882a593Smuzhiyun 		.min_uV = 1100000,
458*4882a593Smuzhiyun 	},
459*4882a593Smuzhiyun };
460*4882a593Smuzhiyun 
lp8788_config_ldo_enable_mode(struct platform_device * pdev,struct lp8788_ldo * ldo,enum lp8788_ldo_id id)461*4882a593Smuzhiyun static int lp8788_config_ldo_enable_mode(struct platform_device *pdev,
462*4882a593Smuzhiyun 					struct lp8788_ldo *ldo,
463*4882a593Smuzhiyun 					enum lp8788_ldo_id id)
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun 	struct lp8788 *lp = ldo->lp;
466*4882a593Smuzhiyun 	enum lp8788_ext_ldo_en_id enable_id;
467*4882a593Smuzhiyun 	static const u8 en_mask[] = {
468*4882a593Smuzhiyun 		[EN_ALDO1]   = LP8788_EN_SEL_ALDO1_M,
469*4882a593Smuzhiyun 		[EN_ALDO234] = LP8788_EN_SEL_ALDO234_M,
470*4882a593Smuzhiyun 		[EN_ALDO5]   = LP8788_EN_SEL_ALDO5_M,
471*4882a593Smuzhiyun 		[EN_ALDO7]   = LP8788_EN_SEL_ALDO7_M,
472*4882a593Smuzhiyun 		[EN_DLDO7]   = LP8788_EN_SEL_DLDO7_M,
473*4882a593Smuzhiyun 		[EN_DLDO911] = LP8788_EN_SEL_DLDO911_M,
474*4882a593Smuzhiyun 	};
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	switch (id) {
477*4882a593Smuzhiyun 	case DLDO7:
478*4882a593Smuzhiyun 		enable_id = EN_DLDO7;
479*4882a593Smuzhiyun 		break;
480*4882a593Smuzhiyun 	case DLDO9:
481*4882a593Smuzhiyun 	case DLDO11:
482*4882a593Smuzhiyun 		enable_id = EN_DLDO911;
483*4882a593Smuzhiyun 		break;
484*4882a593Smuzhiyun 	case ALDO1:
485*4882a593Smuzhiyun 		enable_id = EN_ALDO1;
486*4882a593Smuzhiyun 		break;
487*4882a593Smuzhiyun 	case ALDO2 ... ALDO4:
488*4882a593Smuzhiyun 		enable_id = EN_ALDO234;
489*4882a593Smuzhiyun 		break;
490*4882a593Smuzhiyun 	case ALDO5:
491*4882a593Smuzhiyun 		enable_id = EN_ALDO5;
492*4882a593Smuzhiyun 		break;
493*4882a593Smuzhiyun 	case ALDO7:
494*4882a593Smuzhiyun 		enable_id = EN_ALDO7;
495*4882a593Smuzhiyun 		break;
496*4882a593Smuzhiyun 	default:
497*4882a593Smuzhiyun 		return 0;
498*4882a593Smuzhiyun 	}
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	/*
501*4882a593Smuzhiyun 	 * Do not use devm* here: the regulator core takes over the
502*4882a593Smuzhiyun 	 * lifecycle management of the GPIO descriptor.
503*4882a593Smuzhiyun 	 * FIXME: check default mode for GPIO here: high or low?
504*4882a593Smuzhiyun 	 */
505*4882a593Smuzhiyun 	ldo->ena_gpiod = gpiod_get_index_optional(&pdev->dev,
506*4882a593Smuzhiyun 					       "enable",
507*4882a593Smuzhiyun 					       enable_id,
508*4882a593Smuzhiyun 					       GPIOD_OUT_HIGH |
509*4882a593Smuzhiyun 					       GPIOD_FLAGS_BIT_NONEXCLUSIVE);
510*4882a593Smuzhiyun 	if (IS_ERR(ldo->ena_gpiod))
511*4882a593Smuzhiyun 		return PTR_ERR(ldo->ena_gpiod);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	/* if no GPIO for ldo pin, then set default enable mode */
514*4882a593Smuzhiyun 	if (!ldo->ena_gpiod)
515*4882a593Smuzhiyun 		goto set_default_ldo_enable_mode;
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	return 0;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun set_default_ldo_enable_mode:
520*4882a593Smuzhiyun 	return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id], 0);
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun 
lp8788_dldo_probe(struct platform_device * pdev)523*4882a593Smuzhiyun static int lp8788_dldo_probe(struct platform_device *pdev)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
526*4882a593Smuzhiyun 	int id = pdev->id;
527*4882a593Smuzhiyun 	struct lp8788_ldo *ldo;
528*4882a593Smuzhiyun 	struct regulator_config cfg = { };
529*4882a593Smuzhiyun 	struct regulator_dev *rdev;
530*4882a593Smuzhiyun 	int ret;
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	ldo = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_ldo), GFP_KERNEL);
533*4882a593Smuzhiyun 	if (!ldo)
534*4882a593Smuzhiyun 		return -ENOMEM;
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	ldo->lp = lp;
537*4882a593Smuzhiyun 	ret = lp8788_config_ldo_enable_mode(pdev, ldo, id);
538*4882a593Smuzhiyun 	if (ret)
539*4882a593Smuzhiyun 		return ret;
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	if (ldo->ena_gpiod)
542*4882a593Smuzhiyun 		cfg.ena_gpiod = ldo->ena_gpiod;
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 	cfg.dev = pdev->dev.parent;
545*4882a593Smuzhiyun 	cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL;
546*4882a593Smuzhiyun 	cfg.driver_data = ldo;
547*4882a593Smuzhiyun 	cfg.regmap = lp->regmap;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	rdev = devm_regulator_register(&pdev->dev, &lp8788_dldo_desc[id], &cfg);
550*4882a593Smuzhiyun 	if (IS_ERR(rdev)) {
551*4882a593Smuzhiyun 		ret = PTR_ERR(rdev);
552*4882a593Smuzhiyun 		dev_err(&pdev->dev, "DLDO%d regulator register err = %d\n",
553*4882a593Smuzhiyun 				id + 1, ret);
554*4882a593Smuzhiyun 		return ret;
555*4882a593Smuzhiyun 	}
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	ldo->regulator = rdev;
558*4882a593Smuzhiyun 	platform_set_drvdata(pdev, ldo);
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	return 0;
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun static struct platform_driver lp8788_dldo_driver = {
564*4882a593Smuzhiyun 	.probe = lp8788_dldo_probe,
565*4882a593Smuzhiyun 	.driver = {
566*4882a593Smuzhiyun 		.name = LP8788_DEV_DLDO,
567*4882a593Smuzhiyun 	},
568*4882a593Smuzhiyun };
569*4882a593Smuzhiyun 
lp8788_aldo_probe(struct platform_device * pdev)570*4882a593Smuzhiyun static int lp8788_aldo_probe(struct platform_device *pdev)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
573*4882a593Smuzhiyun 	int id = pdev->id;
574*4882a593Smuzhiyun 	struct lp8788_ldo *ldo;
575*4882a593Smuzhiyun 	struct regulator_config cfg = { };
576*4882a593Smuzhiyun 	struct regulator_dev *rdev;
577*4882a593Smuzhiyun 	int ret;
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	ldo = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_ldo), GFP_KERNEL);
580*4882a593Smuzhiyun 	if (!ldo)
581*4882a593Smuzhiyun 		return -ENOMEM;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	ldo->lp = lp;
584*4882a593Smuzhiyun 	ret = lp8788_config_ldo_enable_mode(pdev, ldo, id + ALDO1);
585*4882a593Smuzhiyun 	if (ret)
586*4882a593Smuzhiyun 		return ret;
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	if (ldo->ena_gpiod)
589*4882a593Smuzhiyun 		cfg.ena_gpiod = ldo->ena_gpiod;
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 	cfg.dev = pdev->dev.parent;
592*4882a593Smuzhiyun 	cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL;
593*4882a593Smuzhiyun 	cfg.driver_data = ldo;
594*4882a593Smuzhiyun 	cfg.regmap = lp->regmap;
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	rdev = devm_regulator_register(&pdev->dev, &lp8788_aldo_desc[id], &cfg);
597*4882a593Smuzhiyun 	if (IS_ERR(rdev)) {
598*4882a593Smuzhiyun 		ret = PTR_ERR(rdev);
599*4882a593Smuzhiyun 		dev_err(&pdev->dev, "ALDO%d regulator register err = %d\n",
600*4882a593Smuzhiyun 				id + 1, ret);
601*4882a593Smuzhiyun 		return ret;
602*4882a593Smuzhiyun 	}
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	ldo->regulator = rdev;
605*4882a593Smuzhiyun 	platform_set_drvdata(pdev, ldo);
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	return 0;
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun static struct platform_driver lp8788_aldo_driver = {
611*4882a593Smuzhiyun 	.probe = lp8788_aldo_probe,
612*4882a593Smuzhiyun 	.driver = {
613*4882a593Smuzhiyun 		.name = LP8788_DEV_ALDO,
614*4882a593Smuzhiyun 	},
615*4882a593Smuzhiyun };
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun static struct platform_driver * const drivers[] = {
618*4882a593Smuzhiyun 	&lp8788_dldo_driver,
619*4882a593Smuzhiyun 	&lp8788_aldo_driver,
620*4882a593Smuzhiyun };
621*4882a593Smuzhiyun 
lp8788_ldo_init(void)622*4882a593Smuzhiyun static int __init lp8788_ldo_init(void)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun 	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun subsys_initcall(lp8788_ldo_init);
627*4882a593Smuzhiyun 
lp8788_ldo_exit(void)628*4882a593Smuzhiyun static void __exit lp8788_ldo_exit(void)
629*4882a593Smuzhiyun {
630*4882a593Smuzhiyun 	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun module_exit(lp8788_ldo_exit);
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun MODULE_DESCRIPTION("TI LP8788 LDO Driver");
635*4882a593Smuzhiyun MODULE_AUTHOR("Milo Kim");
636*4882a593Smuzhiyun MODULE_LICENSE("GPL");
637*4882a593Smuzhiyun MODULE_ALIAS("platform:lp8788-dldo");
638*4882a593Smuzhiyun MODULE_ALIAS("platform:lp8788-aldo");
639