xref: /OK3568_Linux_fs/kernel/drivers/regulator/s5m8767.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Copyright (c) 2011 Samsung Electronics Co., Ltd
4*4882a593Smuzhiyun //              http://www.samsung.com
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <linux/err.h>
7*4882a593Smuzhiyun #include <linux/of_gpio.h>
8*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/platform_device.h>
11*4882a593Smuzhiyun #include <linux/regulator/driver.h>
12*4882a593Smuzhiyun #include <linux/regulator/machine.h>
13*4882a593Smuzhiyun #include <linux/mfd/samsung/core.h>
14*4882a593Smuzhiyun #include <linux/mfd/samsung/s5m8767.h>
15*4882a593Smuzhiyun #include <linux/regulator/of_regulator.h>
16*4882a593Smuzhiyun #include <linux/regmap.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #define S5M8767_OPMODE_NORMAL_MODE 0x1
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun struct s5m8767_info {
21*4882a593Smuzhiyun 	struct device *dev;
22*4882a593Smuzhiyun 	struct sec_pmic_dev *iodev;
23*4882a593Smuzhiyun 	int num_regulators;
24*4882a593Smuzhiyun 	struct sec_opmode_data *opmode;
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun 	int ramp_delay;
27*4882a593Smuzhiyun 	bool buck2_ramp;
28*4882a593Smuzhiyun 	bool buck3_ramp;
29*4882a593Smuzhiyun 	bool buck4_ramp;
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 	bool buck2_gpiodvs;
32*4882a593Smuzhiyun 	bool buck3_gpiodvs;
33*4882a593Smuzhiyun 	bool buck4_gpiodvs;
34*4882a593Smuzhiyun 	u8 buck2_vol[8];
35*4882a593Smuzhiyun 	u8 buck3_vol[8];
36*4882a593Smuzhiyun 	u8 buck4_vol[8];
37*4882a593Smuzhiyun 	int buck_gpios[3];
38*4882a593Smuzhiyun 	int buck_ds[3];
39*4882a593Smuzhiyun 	int buck_gpioindex;
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun struct sec_voltage_desc {
43*4882a593Smuzhiyun 	int max;
44*4882a593Smuzhiyun 	int min;
45*4882a593Smuzhiyun 	int step;
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun static const struct sec_voltage_desc buck_voltage_val1 = {
49*4882a593Smuzhiyun 	.max = 2225000,
50*4882a593Smuzhiyun 	.min =  650000,
51*4882a593Smuzhiyun 	.step =   6250,
52*4882a593Smuzhiyun };
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun static const struct sec_voltage_desc buck_voltage_val2 = {
55*4882a593Smuzhiyun 	.max = 1600000,
56*4882a593Smuzhiyun 	.min =  600000,
57*4882a593Smuzhiyun 	.step =   6250,
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun static const struct sec_voltage_desc buck_voltage_val3 = {
61*4882a593Smuzhiyun 	.max = 3000000,
62*4882a593Smuzhiyun 	.min =  750000,
63*4882a593Smuzhiyun 	.step =  12500,
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun static const struct sec_voltage_desc ldo_voltage_val1 = {
67*4882a593Smuzhiyun 	.max = 3950000,
68*4882a593Smuzhiyun 	.min =  800000,
69*4882a593Smuzhiyun 	.step =  50000,
70*4882a593Smuzhiyun };
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun static const struct sec_voltage_desc ldo_voltage_val2 = {
73*4882a593Smuzhiyun 	.max = 2375000,
74*4882a593Smuzhiyun 	.min =  800000,
75*4882a593Smuzhiyun 	.step =  25000,
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun static const struct sec_voltage_desc *reg_voltage_map[] = {
79*4882a593Smuzhiyun 	[S5M8767_LDO1] = &ldo_voltage_val2,
80*4882a593Smuzhiyun 	[S5M8767_LDO2] = &ldo_voltage_val2,
81*4882a593Smuzhiyun 	[S5M8767_LDO3] = &ldo_voltage_val1,
82*4882a593Smuzhiyun 	[S5M8767_LDO4] = &ldo_voltage_val1,
83*4882a593Smuzhiyun 	[S5M8767_LDO5] = &ldo_voltage_val1,
84*4882a593Smuzhiyun 	[S5M8767_LDO6] = &ldo_voltage_val2,
85*4882a593Smuzhiyun 	[S5M8767_LDO7] = &ldo_voltage_val2,
86*4882a593Smuzhiyun 	[S5M8767_LDO8] = &ldo_voltage_val2,
87*4882a593Smuzhiyun 	[S5M8767_LDO9] = &ldo_voltage_val1,
88*4882a593Smuzhiyun 	[S5M8767_LDO10] = &ldo_voltage_val1,
89*4882a593Smuzhiyun 	[S5M8767_LDO11] = &ldo_voltage_val1,
90*4882a593Smuzhiyun 	[S5M8767_LDO12] = &ldo_voltage_val1,
91*4882a593Smuzhiyun 	[S5M8767_LDO13] = &ldo_voltage_val1,
92*4882a593Smuzhiyun 	[S5M8767_LDO14] = &ldo_voltage_val1,
93*4882a593Smuzhiyun 	[S5M8767_LDO15] = &ldo_voltage_val2,
94*4882a593Smuzhiyun 	[S5M8767_LDO16] = &ldo_voltage_val1,
95*4882a593Smuzhiyun 	[S5M8767_LDO17] = &ldo_voltage_val1,
96*4882a593Smuzhiyun 	[S5M8767_LDO18] = &ldo_voltage_val1,
97*4882a593Smuzhiyun 	[S5M8767_LDO19] = &ldo_voltage_val1,
98*4882a593Smuzhiyun 	[S5M8767_LDO20] = &ldo_voltage_val1,
99*4882a593Smuzhiyun 	[S5M8767_LDO21] = &ldo_voltage_val1,
100*4882a593Smuzhiyun 	[S5M8767_LDO22] = &ldo_voltage_val1,
101*4882a593Smuzhiyun 	[S5M8767_LDO23] = &ldo_voltage_val1,
102*4882a593Smuzhiyun 	[S5M8767_LDO24] = &ldo_voltage_val1,
103*4882a593Smuzhiyun 	[S5M8767_LDO25] = &ldo_voltage_val1,
104*4882a593Smuzhiyun 	[S5M8767_LDO26] = &ldo_voltage_val1,
105*4882a593Smuzhiyun 	[S5M8767_LDO27] = &ldo_voltage_val1,
106*4882a593Smuzhiyun 	[S5M8767_LDO28] = &ldo_voltage_val1,
107*4882a593Smuzhiyun 	[S5M8767_BUCK1] = &buck_voltage_val1,
108*4882a593Smuzhiyun 	[S5M8767_BUCK2] = &buck_voltage_val2,
109*4882a593Smuzhiyun 	[S5M8767_BUCK3] = &buck_voltage_val2,
110*4882a593Smuzhiyun 	[S5M8767_BUCK4] = &buck_voltage_val2,
111*4882a593Smuzhiyun 	[S5M8767_BUCK5] = &buck_voltage_val1,
112*4882a593Smuzhiyun 	[S5M8767_BUCK6] = &buck_voltage_val1,
113*4882a593Smuzhiyun 	[S5M8767_BUCK7] = &buck_voltage_val3,
114*4882a593Smuzhiyun 	[S5M8767_BUCK8] = &buck_voltage_val3,
115*4882a593Smuzhiyun 	[S5M8767_BUCK9] = &buck_voltage_val3,
116*4882a593Smuzhiyun };
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun static const unsigned int s5m8767_opmode_reg[][4] = {
119*4882a593Smuzhiyun 	/* {OFF, ON, LOWPOWER, SUSPEND} */
120*4882a593Smuzhiyun 	/* LDO1 ... LDO28 */
121*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1}, /* LDO1 */
122*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
123*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
124*4882a593Smuzhiyun 	{0x0, 0x0, 0x0, 0x0},
125*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1}, /* LDO5 */
126*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
127*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
128*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
129*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
130*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1}, /* LDO10 */
131*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
132*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
133*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
134*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
135*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1}, /* LDO15 */
136*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
137*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
138*4882a593Smuzhiyun 	{0x0, 0x0, 0x0, 0x0},
139*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
140*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1}, /* LDO20 */
141*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
142*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
143*4882a593Smuzhiyun 	{0x0, 0x0, 0x0, 0x0},
144*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
145*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1}, /* LDO25 */
146*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
147*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1},
148*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1}, /* LDO28 */
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	/* BUCK1 ... BUCK9 */
151*4882a593Smuzhiyun 	{0x0, 0x3, 0x1, 0x1}, /* BUCK1 */
152*4882a593Smuzhiyun 	{0x0, 0x3, 0x1, 0x1},
153*4882a593Smuzhiyun 	{0x0, 0x3, 0x1, 0x1},
154*4882a593Smuzhiyun 	{0x0, 0x3, 0x1, 0x1},
155*4882a593Smuzhiyun 	{0x0, 0x3, 0x2, 0x1}, /* BUCK5 */
156*4882a593Smuzhiyun 	{0x0, 0x3, 0x1, 0x1},
157*4882a593Smuzhiyun 	{0x0, 0x3, 0x1, 0x1},
158*4882a593Smuzhiyun 	{0x0, 0x3, 0x1, 0x1},
159*4882a593Smuzhiyun 	{0x0, 0x3, 0x1, 0x1}, /* BUCK9 */
160*4882a593Smuzhiyun };
161*4882a593Smuzhiyun 
s5m8767_get_register(struct s5m8767_info * s5m8767,int reg_id,int * reg,int * enable_ctrl)162*4882a593Smuzhiyun static int s5m8767_get_register(struct s5m8767_info *s5m8767, int reg_id,
163*4882a593Smuzhiyun 				int *reg, int *enable_ctrl)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun 	int i;
166*4882a593Smuzhiyun 	unsigned int mode;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	switch (reg_id) {
169*4882a593Smuzhiyun 	case S5M8767_LDO1 ... S5M8767_LDO2:
170*4882a593Smuzhiyun 		*reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1);
171*4882a593Smuzhiyun 		break;
172*4882a593Smuzhiyun 	case S5M8767_LDO3 ... S5M8767_LDO28:
173*4882a593Smuzhiyun 		*reg = S5M8767_REG_LDO3CTRL + (reg_id - S5M8767_LDO3);
174*4882a593Smuzhiyun 		break;
175*4882a593Smuzhiyun 	case S5M8767_BUCK1:
176*4882a593Smuzhiyun 		*reg = S5M8767_REG_BUCK1CTRL1;
177*4882a593Smuzhiyun 		break;
178*4882a593Smuzhiyun 	case S5M8767_BUCK2 ... S5M8767_BUCK4:
179*4882a593Smuzhiyun 		*reg = S5M8767_REG_BUCK2CTRL + (reg_id - S5M8767_BUCK2) * 9;
180*4882a593Smuzhiyun 		break;
181*4882a593Smuzhiyun 	case S5M8767_BUCK5:
182*4882a593Smuzhiyun 		*reg = S5M8767_REG_BUCK5CTRL1;
183*4882a593Smuzhiyun 		break;
184*4882a593Smuzhiyun 	case S5M8767_BUCK6 ... S5M8767_BUCK9:
185*4882a593Smuzhiyun 		*reg = S5M8767_REG_BUCK6CTRL1 + (reg_id - S5M8767_BUCK6) * 2;
186*4882a593Smuzhiyun 		break;
187*4882a593Smuzhiyun 	default:
188*4882a593Smuzhiyun 		return -EINVAL;
189*4882a593Smuzhiyun 	}
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	for (i = 0; i < s5m8767->num_regulators; i++) {
192*4882a593Smuzhiyun 		if (s5m8767->opmode[i].id == reg_id) {
193*4882a593Smuzhiyun 			mode = s5m8767->opmode[i].mode;
194*4882a593Smuzhiyun 			break;
195*4882a593Smuzhiyun 		}
196*4882a593Smuzhiyun 	}
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	if (i >= s5m8767->num_regulators)
199*4882a593Smuzhiyun 		return -EINVAL;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	*enable_ctrl = s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	return 0;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun 
s5m8767_get_vsel_reg(int reg_id,struct s5m8767_info * s5m8767)206*4882a593Smuzhiyun static int s5m8767_get_vsel_reg(int reg_id, struct s5m8767_info *s5m8767)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun 	int reg;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	switch (reg_id) {
211*4882a593Smuzhiyun 	case S5M8767_LDO1 ... S5M8767_LDO2:
212*4882a593Smuzhiyun 		reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1);
213*4882a593Smuzhiyun 		break;
214*4882a593Smuzhiyun 	case S5M8767_LDO3 ... S5M8767_LDO28:
215*4882a593Smuzhiyun 		reg = S5M8767_REG_LDO3CTRL + (reg_id - S5M8767_LDO3);
216*4882a593Smuzhiyun 		break;
217*4882a593Smuzhiyun 	case S5M8767_BUCK1:
218*4882a593Smuzhiyun 		reg = S5M8767_REG_BUCK1CTRL2;
219*4882a593Smuzhiyun 		break;
220*4882a593Smuzhiyun 	case S5M8767_BUCK2:
221*4882a593Smuzhiyun 		reg = S5M8767_REG_BUCK2DVS1;
222*4882a593Smuzhiyun 		if (s5m8767->buck2_gpiodvs)
223*4882a593Smuzhiyun 			reg += s5m8767->buck_gpioindex;
224*4882a593Smuzhiyun 		break;
225*4882a593Smuzhiyun 	case S5M8767_BUCK3:
226*4882a593Smuzhiyun 		reg = S5M8767_REG_BUCK3DVS1;
227*4882a593Smuzhiyun 		if (s5m8767->buck3_gpiodvs)
228*4882a593Smuzhiyun 			reg += s5m8767->buck_gpioindex;
229*4882a593Smuzhiyun 		break;
230*4882a593Smuzhiyun 	case S5M8767_BUCK4:
231*4882a593Smuzhiyun 		reg = S5M8767_REG_BUCK4DVS1;
232*4882a593Smuzhiyun 		if (s5m8767->buck4_gpiodvs)
233*4882a593Smuzhiyun 			reg += s5m8767->buck_gpioindex;
234*4882a593Smuzhiyun 		break;
235*4882a593Smuzhiyun 	case S5M8767_BUCK5:
236*4882a593Smuzhiyun 		reg = S5M8767_REG_BUCK5CTRL2;
237*4882a593Smuzhiyun 		break;
238*4882a593Smuzhiyun 	case S5M8767_BUCK6 ... S5M8767_BUCK9:
239*4882a593Smuzhiyun 		reg = S5M8767_REG_BUCK6CTRL2 + (reg_id - S5M8767_BUCK6) * 2;
240*4882a593Smuzhiyun 		break;
241*4882a593Smuzhiyun 	default:
242*4882a593Smuzhiyun 		return -EINVAL;
243*4882a593Smuzhiyun 	}
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	return reg;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun 
s5m8767_convert_voltage_to_sel(const struct sec_voltage_desc * desc,int min_vol)248*4882a593Smuzhiyun static int s5m8767_convert_voltage_to_sel(const struct sec_voltage_desc *desc,
249*4882a593Smuzhiyun 					  int min_vol)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun 	int selector = 0;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	if (desc == NULL)
254*4882a593Smuzhiyun 		return -EINVAL;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	if (min_vol > desc->max)
257*4882a593Smuzhiyun 		return -EINVAL;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	if (min_vol < desc->min)
260*4882a593Smuzhiyun 		min_vol = desc->min;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	selector = DIV_ROUND_UP(min_vol - desc->min, desc->step);
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	if (desc->min + desc->step * selector > desc->max)
265*4882a593Smuzhiyun 		return -EINVAL;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	return selector;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
s5m8767_set_high(struct s5m8767_info * s5m8767)270*4882a593Smuzhiyun static inline int s5m8767_set_high(struct s5m8767_info *s5m8767)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	int temp_index = s5m8767->buck_gpioindex;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
275*4882a593Smuzhiyun 	gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
276*4882a593Smuzhiyun 	gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	return 0;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
s5m8767_set_low(struct s5m8767_info * s5m8767)281*4882a593Smuzhiyun static inline int s5m8767_set_low(struct s5m8767_info *s5m8767)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun 	int temp_index = s5m8767->buck_gpioindex;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
286*4882a593Smuzhiyun 	gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
287*4882a593Smuzhiyun 	gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	return 0;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun 
s5m8767_set_voltage_sel(struct regulator_dev * rdev,unsigned selector)292*4882a593Smuzhiyun static int s5m8767_set_voltage_sel(struct regulator_dev *rdev,
293*4882a593Smuzhiyun 				   unsigned selector)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun 	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
296*4882a593Smuzhiyun 	int reg_id = rdev_get_id(rdev);
297*4882a593Smuzhiyun 	int old_index, index = 0;
298*4882a593Smuzhiyun 	u8 *buck234_vol = NULL;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	switch (reg_id) {
301*4882a593Smuzhiyun 	case S5M8767_LDO1 ... S5M8767_LDO28:
302*4882a593Smuzhiyun 		break;
303*4882a593Smuzhiyun 	case S5M8767_BUCK1 ... S5M8767_BUCK6:
304*4882a593Smuzhiyun 		if (reg_id == S5M8767_BUCK2 && s5m8767->buck2_gpiodvs)
305*4882a593Smuzhiyun 			buck234_vol = &s5m8767->buck2_vol[0];
306*4882a593Smuzhiyun 		else if (reg_id == S5M8767_BUCK3 && s5m8767->buck3_gpiodvs)
307*4882a593Smuzhiyun 			buck234_vol = &s5m8767->buck3_vol[0];
308*4882a593Smuzhiyun 		else if (reg_id == S5M8767_BUCK4 && s5m8767->buck4_gpiodvs)
309*4882a593Smuzhiyun 			buck234_vol = &s5m8767->buck4_vol[0];
310*4882a593Smuzhiyun 		break;
311*4882a593Smuzhiyun 	case S5M8767_BUCK7 ... S5M8767_BUCK8:
312*4882a593Smuzhiyun 		return -EINVAL;
313*4882a593Smuzhiyun 	case S5M8767_BUCK9:
314*4882a593Smuzhiyun 		break;
315*4882a593Smuzhiyun 	default:
316*4882a593Smuzhiyun 		return -EINVAL;
317*4882a593Smuzhiyun 	}
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	/* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */
320*4882a593Smuzhiyun 	if (buck234_vol) {
321*4882a593Smuzhiyun 		while (*buck234_vol != selector) {
322*4882a593Smuzhiyun 			buck234_vol++;
323*4882a593Smuzhiyun 			index++;
324*4882a593Smuzhiyun 		}
325*4882a593Smuzhiyun 		old_index = s5m8767->buck_gpioindex;
326*4882a593Smuzhiyun 		s5m8767->buck_gpioindex = index;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 		if (index > old_index)
329*4882a593Smuzhiyun 			return s5m8767_set_high(s5m8767);
330*4882a593Smuzhiyun 		else
331*4882a593Smuzhiyun 			return s5m8767_set_low(s5m8767);
332*4882a593Smuzhiyun 	} else {
333*4882a593Smuzhiyun 		return regulator_set_voltage_sel_regmap(rdev, selector);
334*4882a593Smuzhiyun 	}
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun 
s5m8767_set_voltage_time_sel(struct regulator_dev * rdev,unsigned int old_sel,unsigned int new_sel)337*4882a593Smuzhiyun static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
338*4882a593Smuzhiyun 					     unsigned int old_sel,
339*4882a593Smuzhiyun 					     unsigned int new_sel)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun 	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	if ((old_sel < new_sel) && s5m8767->ramp_delay)
344*4882a593Smuzhiyun 		return DIV_ROUND_UP(rdev->desc->uV_step * (new_sel - old_sel),
345*4882a593Smuzhiyun 					s5m8767->ramp_delay * 1000);
346*4882a593Smuzhiyun 	return 0;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun static const struct regulator_ops s5m8767_ops = {
350*4882a593Smuzhiyun 	.list_voltage		= regulator_list_voltage_linear,
351*4882a593Smuzhiyun 	.is_enabled		= regulator_is_enabled_regmap,
352*4882a593Smuzhiyun 	.enable			= regulator_enable_regmap,
353*4882a593Smuzhiyun 	.disable		= regulator_disable_regmap,
354*4882a593Smuzhiyun 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
355*4882a593Smuzhiyun 	.set_voltage_sel	= s5m8767_set_voltage_sel,
356*4882a593Smuzhiyun 	.set_voltage_time_sel	= s5m8767_set_voltage_time_sel,
357*4882a593Smuzhiyun };
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun static const struct regulator_ops s5m8767_buck78_ops = {
360*4882a593Smuzhiyun 	.list_voltage		= regulator_list_voltage_linear,
361*4882a593Smuzhiyun 	.is_enabled		= regulator_is_enabled_regmap,
362*4882a593Smuzhiyun 	.enable			= regulator_enable_regmap,
363*4882a593Smuzhiyun 	.disable		= regulator_disable_regmap,
364*4882a593Smuzhiyun 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
365*4882a593Smuzhiyun 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
366*4882a593Smuzhiyun };
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun #define s5m8767_regulator_desc(_name) {		\
369*4882a593Smuzhiyun 	.name		= #_name,		\
370*4882a593Smuzhiyun 	.id		= S5M8767_##_name,	\
371*4882a593Smuzhiyun 	.ops		= &s5m8767_ops,		\
372*4882a593Smuzhiyun 	.type		= REGULATOR_VOLTAGE,	\
373*4882a593Smuzhiyun 	.owner		= THIS_MODULE,		\
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun #define s5m8767_regulator_buck78_desc(_name) {	\
377*4882a593Smuzhiyun 	.name		= #_name,		\
378*4882a593Smuzhiyun 	.id		= S5M8767_##_name,	\
379*4882a593Smuzhiyun 	.ops		= &s5m8767_buck78_ops,	\
380*4882a593Smuzhiyun 	.type		= REGULATOR_VOLTAGE,	\
381*4882a593Smuzhiyun 	.owner		= THIS_MODULE,		\
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun static struct regulator_desc regulators[] = {
385*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO1),
386*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO2),
387*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO3),
388*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO4),
389*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO5),
390*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO6),
391*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO7),
392*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO8),
393*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO9),
394*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO10),
395*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO11),
396*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO12),
397*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO13),
398*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO14),
399*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO15),
400*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO16),
401*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO17),
402*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO18),
403*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO19),
404*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO20),
405*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO21),
406*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO22),
407*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO23),
408*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO24),
409*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO25),
410*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO26),
411*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO27),
412*4882a593Smuzhiyun 	s5m8767_regulator_desc(LDO28),
413*4882a593Smuzhiyun 	s5m8767_regulator_desc(BUCK1),
414*4882a593Smuzhiyun 	s5m8767_regulator_desc(BUCK2),
415*4882a593Smuzhiyun 	s5m8767_regulator_desc(BUCK3),
416*4882a593Smuzhiyun 	s5m8767_regulator_desc(BUCK4),
417*4882a593Smuzhiyun 	s5m8767_regulator_desc(BUCK5),
418*4882a593Smuzhiyun 	s5m8767_regulator_desc(BUCK6),
419*4882a593Smuzhiyun 	s5m8767_regulator_buck78_desc(BUCK7),
420*4882a593Smuzhiyun 	s5m8767_regulator_buck78_desc(BUCK8),
421*4882a593Smuzhiyun 	s5m8767_regulator_desc(BUCK9),
422*4882a593Smuzhiyun };
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun /*
425*4882a593Smuzhiyun  * Enable GPIO control over BUCK9 in regulator_config for that regulator.
426*4882a593Smuzhiyun  */
s5m8767_regulator_config_ext_control(struct s5m8767_info * s5m8767,struct sec_regulator_data * rdata,struct regulator_config * config)427*4882a593Smuzhiyun static void s5m8767_regulator_config_ext_control(struct s5m8767_info *s5m8767,
428*4882a593Smuzhiyun 		struct sec_regulator_data *rdata,
429*4882a593Smuzhiyun 		struct regulator_config *config)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun 	int i, mode = 0;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	if (rdata->id != S5M8767_BUCK9)
434*4882a593Smuzhiyun 		return;
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	/* Check if opmode for regulator matches S5M8767_ENCTRL_USE_GPIO */
437*4882a593Smuzhiyun 	for (i = 0; i < s5m8767->num_regulators; i++) {
438*4882a593Smuzhiyun 		const struct sec_opmode_data *opmode = &s5m8767->opmode[i];
439*4882a593Smuzhiyun 		if (opmode->id == rdata->id) {
440*4882a593Smuzhiyun 			mode = s5m8767_opmode_reg[rdata->id][opmode->mode];
441*4882a593Smuzhiyun 			break;
442*4882a593Smuzhiyun 		}
443*4882a593Smuzhiyun 	}
444*4882a593Smuzhiyun 	if (mode != S5M8767_ENCTRL_USE_GPIO) {
445*4882a593Smuzhiyun 		dev_warn(s5m8767->dev,
446*4882a593Smuzhiyun 				"ext-control for %pOFn: mismatched op_mode (%x), ignoring\n",
447*4882a593Smuzhiyun 				rdata->reg_node, mode);
448*4882a593Smuzhiyun 		return;
449*4882a593Smuzhiyun 	}
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	if (!rdata->ext_control_gpiod) {
452*4882a593Smuzhiyun 		dev_warn(s5m8767->dev,
453*4882a593Smuzhiyun 				"ext-control for %pOFn: GPIO not valid, ignoring\n",
454*4882a593Smuzhiyun 			 rdata->reg_node);
455*4882a593Smuzhiyun 		return;
456*4882a593Smuzhiyun 	}
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	config->ena_gpiod = rdata->ext_control_gpiod;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun /*
462*4882a593Smuzhiyun  * Turn on GPIO control over BUCK9.
463*4882a593Smuzhiyun  */
s5m8767_enable_ext_control(struct s5m8767_info * s5m8767,struct regulator_dev * rdev)464*4882a593Smuzhiyun static int s5m8767_enable_ext_control(struct s5m8767_info *s5m8767,
465*4882a593Smuzhiyun 		struct regulator_dev *rdev)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun 	int id = rdev_get_id(rdev);
468*4882a593Smuzhiyun 	int ret, reg, enable_ctrl;
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	if (id != S5M8767_BUCK9)
471*4882a593Smuzhiyun 		return -EINVAL;
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	ret = s5m8767_get_register(s5m8767, id, &reg, &enable_ctrl);
474*4882a593Smuzhiyun 	if (ret)
475*4882a593Smuzhiyun 		return ret;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	return regmap_update_bits(s5m8767->iodev->regmap_pmic,
478*4882a593Smuzhiyun 			reg, S5M8767_ENCTRL_MASK,
479*4882a593Smuzhiyun 			S5M8767_ENCTRL_USE_GPIO << S5M8767_ENCTRL_SHIFT);
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun #ifdef CONFIG_OF
s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev * iodev,struct sec_platform_data * pdata,struct device_node * pmic_np)484*4882a593Smuzhiyun static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev,
485*4882a593Smuzhiyun 			struct sec_platform_data *pdata,
486*4882a593Smuzhiyun 			struct device_node *pmic_np)
487*4882a593Smuzhiyun {
488*4882a593Smuzhiyun 	int i, gpio;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	for (i = 0; i < 3; i++) {
491*4882a593Smuzhiyun 		gpio = of_get_named_gpio(pmic_np,
492*4882a593Smuzhiyun 					"s5m8767,pmic-buck-dvs-gpios", i);
493*4882a593Smuzhiyun 		if (!gpio_is_valid(gpio)) {
494*4882a593Smuzhiyun 			dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
495*4882a593Smuzhiyun 			return -EINVAL;
496*4882a593Smuzhiyun 		}
497*4882a593Smuzhiyun 		pdata->buck_gpios[i] = gpio;
498*4882a593Smuzhiyun 	}
499*4882a593Smuzhiyun 	return 0;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev * iodev,struct sec_platform_data * pdata,struct device_node * pmic_np)502*4882a593Smuzhiyun static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev,
503*4882a593Smuzhiyun 			struct sec_platform_data *pdata,
504*4882a593Smuzhiyun 			struct device_node *pmic_np)
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun 	int i, gpio;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	for (i = 0; i < 3; i++) {
509*4882a593Smuzhiyun 		gpio = of_get_named_gpio(pmic_np,
510*4882a593Smuzhiyun 					"s5m8767,pmic-buck-ds-gpios", i);
511*4882a593Smuzhiyun 		if (!gpio_is_valid(gpio)) {
512*4882a593Smuzhiyun 			dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
513*4882a593Smuzhiyun 			return -EINVAL;
514*4882a593Smuzhiyun 		}
515*4882a593Smuzhiyun 		pdata->buck_ds[i] = gpio;
516*4882a593Smuzhiyun 	}
517*4882a593Smuzhiyun 	return 0;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun 
s5m8767_pmic_dt_parse_pdata(struct platform_device * pdev,struct sec_platform_data * pdata)520*4882a593Smuzhiyun static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
521*4882a593Smuzhiyun 					struct sec_platform_data *pdata)
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
524*4882a593Smuzhiyun 	struct device_node *pmic_np, *regulators_np, *reg_np;
525*4882a593Smuzhiyun 	struct sec_regulator_data *rdata;
526*4882a593Smuzhiyun 	struct sec_opmode_data *rmode;
527*4882a593Smuzhiyun 	unsigned int i, dvs_voltage_nr = 8, ret;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	pmic_np = iodev->dev->of_node;
530*4882a593Smuzhiyun 	if (!pmic_np) {
531*4882a593Smuzhiyun 		dev_err(iodev->dev, "could not find pmic sub-node\n");
532*4882a593Smuzhiyun 		return -ENODEV;
533*4882a593Smuzhiyun 	}
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	regulators_np = of_get_child_by_name(pmic_np, "regulators");
536*4882a593Smuzhiyun 	if (!regulators_np) {
537*4882a593Smuzhiyun 		dev_err(iodev->dev, "could not find regulators sub-node\n");
538*4882a593Smuzhiyun 		return -EINVAL;
539*4882a593Smuzhiyun 	}
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	/* count the number of regulators to be supported in pmic */
542*4882a593Smuzhiyun 	pdata->num_regulators = of_get_child_count(regulators_np);
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 	rdata = devm_kcalloc(&pdev->dev,
545*4882a593Smuzhiyun 			     pdata->num_regulators, sizeof(*rdata),
546*4882a593Smuzhiyun 			     GFP_KERNEL);
547*4882a593Smuzhiyun 	if (!rdata) {
548*4882a593Smuzhiyun 		of_node_put(regulators_np);
549*4882a593Smuzhiyun 		return -ENOMEM;
550*4882a593Smuzhiyun 	}
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	rmode = devm_kcalloc(&pdev->dev,
553*4882a593Smuzhiyun 			     pdata->num_regulators, sizeof(*rmode),
554*4882a593Smuzhiyun 			     GFP_KERNEL);
555*4882a593Smuzhiyun 	if (!rmode) {
556*4882a593Smuzhiyun 		of_node_put(regulators_np);
557*4882a593Smuzhiyun 		return -ENOMEM;
558*4882a593Smuzhiyun 	}
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	pdata->regulators = rdata;
561*4882a593Smuzhiyun 	pdata->opmode = rmode;
562*4882a593Smuzhiyun 	for_each_child_of_node(regulators_np, reg_np) {
563*4882a593Smuzhiyun 		for (i = 0; i < ARRAY_SIZE(regulators); i++)
564*4882a593Smuzhiyun 			if (of_node_name_eq(reg_np, regulators[i].name))
565*4882a593Smuzhiyun 				break;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 		if (i == ARRAY_SIZE(regulators)) {
568*4882a593Smuzhiyun 			dev_warn(iodev->dev,
569*4882a593Smuzhiyun 			"don't know how to configure regulator %pOFn\n",
570*4882a593Smuzhiyun 			reg_np);
571*4882a593Smuzhiyun 			continue;
572*4882a593Smuzhiyun 		}
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 		rdata->ext_control_gpiod = devm_fwnode_gpiod_get(
575*4882a593Smuzhiyun 			&pdev->dev,
576*4882a593Smuzhiyun 			of_fwnode_handle(reg_np),
577*4882a593Smuzhiyun 			"s5m8767,pmic-ext-control",
578*4882a593Smuzhiyun 			GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
579*4882a593Smuzhiyun 			"s5m8767");
580*4882a593Smuzhiyun 		if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT) {
581*4882a593Smuzhiyun 			rdata->ext_control_gpiod = NULL;
582*4882a593Smuzhiyun 		} else if (IS_ERR(rdata->ext_control_gpiod)) {
583*4882a593Smuzhiyun 			of_node_put(reg_np);
584*4882a593Smuzhiyun 			of_node_put(regulators_np);
585*4882a593Smuzhiyun 			return PTR_ERR(rdata->ext_control_gpiod);
586*4882a593Smuzhiyun 		}
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 		rdata->id = i;
589*4882a593Smuzhiyun 		rdata->initdata = of_get_regulator_init_data(
590*4882a593Smuzhiyun 						&pdev->dev, reg_np,
591*4882a593Smuzhiyun 						&regulators[i]);
592*4882a593Smuzhiyun 		rdata->reg_node = reg_np;
593*4882a593Smuzhiyun 		rdata++;
594*4882a593Smuzhiyun 		rmode->id = i;
595*4882a593Smuzhiyun 		if (of_property_read_u32(reg_np, "op_mode",
596*4882a593Smuzhiyun 				&rmode->mode)) {
597*4882a593Smuzhiyun 			dev_warn(iodev->dev,
598*4882a593Smuzhiyun 				"no op_mode property at %pOF\n",
599*4882a593Smuzhiyun 				reg_np);
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 			rmode->mode = S5M8767_OPMODE_NORMAL_MODE;
602*4882a593Smuzhiyun 		}
603*4882a593Smuzhiyun 		rmode++;
604*4882a593Smuzhiyun 	}
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	of_node_put(regulators_np);
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) {
609*4882a593Smuzhiyun 		pdata->buck2_gpiodvs = true;
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 		if (of_property_read_u32_array(pmic_np,
612*4882a593Smuzhiyun 				"s5m8767,pmic-buck2-dvs-voltage",
613*4882a593Smuzhiyun 				pdata->buck2_voltage, dvs_voltage_nr)) {
614*4882a593Smuzhiyun 			dev_err(iodev->dev, "buck2 voltages not specified\n");
615*4882a593Smuzhiyun 			return -EINVAL;
616*4882a593Smuzhiyun 		}
617*4882a593Smuzhiyun 	}
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	if (of_get_property(pmic_np, "s5m8767,pmic-buck3-uses-gpio-dvs", NULL)) {
620*4882a593Smuzhiyun 		pdata->buck3_gpiodvs = true;
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 		if (of_property_read_u32_array(pmic_np,
623*4882a593Smuzhiyun 				"s5m8767,pmic-buck3-dvs-voltage",
624*4882a593Smuzhiyun 				pdata->buck3_voltage, dvs_voltage_nr)) {
625*4882a593Smuzhiyun 			dev_err(iodev->dev, "buck3 voltages not specified\n");
626*4882a593Smuzhiyun 			return -EINVAL;
627*4882a593Smuzhiyun 		}
628*4882a593Smuzhiyun 	}
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	if (of_get_property(pmic_np, "s5m8767,pmic-buck4-uses-gpio-dvs", NULL)) {
631*4882a593Smuzhiyun 		pdata->buck4_gpiodvs = true;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 		if (of_property_read_u32_array(pmic_np,
634*4882a593Smuzhiyun 				"s5m8767,pmic-buck4-dvs-voltage",
635*4882a593Smuzhiyun 				pdata->buck4_voltage, dvs_voltage_nr)) {
636*4882a593Smuzhiyun 			dev_err(iodev->dev, "buck4 voltages not specified\n");
637*4882a593Smuzhiyun 			return -EINVAL;
638*4882a593Smuzhiyun 		}
639*4882a593Smuzhiyun 	}
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
642*4882a593Smuzhiyun 						pdata->buck4_gpiodvs) {
643*4882a593Smuzhiyun 		ret = s5m8767_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
644*4882a593Smuzhiyun 		if (ret)
645*4882a593Smuzhiyun 			return -EINVAL;
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun 		if (of_property_read_u32(pmic_np,
648*4882a593Smuzhiyun 				"s5m8767,pmic-buck-default-dvs-idx",
649*4882a593Smuzhiyun 				&pdata->buck_default_idx)) {
650*4882a593Smuzhiyun 			pdata->buck_default_idx = 0;
651*4882a593Smuzhiyun 		} else {
652*4882a593Smuzhiyun 			if (pdata->buck_default_idx >= 8) {
653*4882a593Smuzhiyun 				pdata->buck_default_idx = 0;
654*4882a593Smuzhiyun 				dev_info(iodev->dev,
655*4882a593Smuzhiyun 				"invalid value for default dvs index, use 0\n");
656*4882a593Smuzhiyun 			}
657*4882a593Smuzhiyun 		}
658*4882a593Smuzhiyun 	}
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun 	ret = s5m8767_pmic_dt_parse_ds_gpio(iodev, pdata, pmic_np);
661*4882a593Smuzhiyun 	if (ret)
662*4882a593Smuzhiyun 		return -EINVAL;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	if (of_get_property(pmic_np, "s5m8767,pmic-buck2-ramp-enable", NULL))
665*4882a593Smuzhiyun 		pdata->buck2_ramp_enable = true;
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun 	if (of_get_property(pmic_np, "s5m8767,pmic-buck3-ramp-enable", NULL))
668*4882a593Smuzhiyun 		pdata->buck3_ramp_enable = true;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	if (of_get_property(pmic_np, "s5m8767,pmic-buck4-ramp-enable", NULL))
671*4882a593Smuzhiyun 		pdata->buck4_ramp_enable = true;
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	if (pdata->buck2_ramp_enable || pdata->buck3_ramp_enable
674*4882a593Smuzhiyun 			|| pdata->buck4_ramp_enable) {
675*4882a593Smuzhiyun 		if (of_property_read_u32(pmic_np, "s5m8767,pmic-buck-ramp-delay",
676*4882a593Smuzhiyun 				&pdata->buck_ramp_delay))
677*4882a593Smuzhiyun 			pdata->buck_ramp_delay = 0;
678*4882a593Smuzhiyun 	}
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 	return 0;
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun #else
s5m8767_pmic_dt_parse_pdata(struct platform_device * pdev,struct sec_platform_data * pdata)683*4882a593Smuzhiyun static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
684*4882a593Smuzhiyun 					struct sec_platform_data *pdata)
685*4882a593Smuzhiyun {
686*4882a593Smuzhiyun 	return 0;
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun #endif /* CONFIG_OF */
689*4882a593Smuzhiyun 
s5m8767_pmic_probe(struct platform_device * pdev)690*4882a593Smuzhiyun static int s5m8767_pmic_probe(struct platform_device *pdev)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
693*4882a593Smuzhiyun 	struct sec_platform_data *pdata = iodev->pdata;
694*4882a593Smuzhiyun 	struct regulator_config config = { };
695*4882a593Smuzhiyun 	struct s5m8767_info *s5m8767;
696*4882a593Smuzhiyun 	int i, ret, buck_init;
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	if (!pdata) {
699*4882a593Smuzhiyun 		dev_err(pdev->dev.parent, "Platform data not supplied\n");
700*4882a593Smuzhiyun 		return -ENODEV;
701*4882a593Smuzhiyun 	}
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun 	if (iodev->dev->of_node) {
704*4882a593Smuzhiyun 		ret = s5m8767_pmic_dt_parse_pdata(pdev, pdata);
705*4882a593Smuzhiyun 		if (ret)
706*4882a593Smuzhiyun 			return ret;
707*4882a593Smuzhiyun 	}
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	if (pdata->buck2_gpiodvs) {
710*4882a593Smuzhiyun 		if (pdata->buck3_gpiodvs || pdata->buck4_gpiodvs) {
711*4882a593Smuzhiyun 			dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n");
712*4882a593Smuzhiyun 			return -EINVAL;
713*4882a593Smuzhiyun 		}
714*4882a593Smuzhiyun 	}
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	if (pdata->buck3_gpiodvs) {
717*4882a593Smuzhiyun 		if (pdata->buck2_gpiodvs || pdata->buck4_gpiodvs) {
718*4882a593Smuzhiyun 			dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n");
719*4882a593Smuzhiyun 			return -EINVAL;
720*4882a593Smuzhiyun 		}
721*4882a593Smuzhiyun 	}
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	if (pdata->buck4_gpiodvs) {
724*4882a593Smuzhiyun 		if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs) {
725*4882a593Smuzhiyun 			dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n");
726*4882a593Smuzhiyun 			return -EINVAL;
727*4882a593Smuzhiyun 		}
728*4882a593Smuzhiyun 	}
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 	s5m8767 = devm_kzalloc(&pdev->dev, sizeof(struct s5m8767_info),
731*4882a593Smuzhiyun 				GFP_KERNEL);
732*4882a593Smuzhiyun 	if (!s5m8767)
733*4882a593Smuzhiyun 		return -ENOMEM;
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	s5m8767->dev = &pdev->dev;
736*4882a593Smuzhiyun 	s5m8767->iodev = iodev;
737*4882a593Smuzhiyun 	s5m8767->num_regulators = pdata->num_regulators;
738*4882a593Smuzhiyun 	platform_set_drvdata(pdev, s5m8767);
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun 	s5m8767->buck_gpioindex = pdata->buck_default_idx;
741*4882a593Smuzhiyun 	s5m8767->buck2_gpiodvs = pdata->buck2_gpiodvs;
742*4882a593Smuzhiyun 	s5m8767->buck3_gpiodvs = pdata->buck3_gpiodvs;
743*4882a593Smuzhiyun 	s5m8767->buck4_gpiodvs = pdata->buck4_gpiodvs;
744*4882a593Smuzhiyun 	s5m8767->buck_gpios[0] = pdata->buck_gpios[0];
745*4882a593Smuzhiyun 	s5m8767->buck_gpios[1] = pdata->buck_gpios[1];
746*4882a593Smuzhiyun 	s5m8767->buck_gpios[2] = pdata->buck_gpios[2];
747*4882a593Smuzhiyun 	s5m8767->buck_ds[0] = pdata->buck_ds[0];
748*4882a593Smuzhiyun 	s5m8767->buck_ds[1] = pdata->buck_ds[1];
749*4882a593Smuzhiyun 	s5m8767->buck_ds[2] = pdata->buck_ds[2];
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	s5m8767->ramp_delay = pdata->buck_ramp_delay;
752*4882a593Smuzhiyun 	s5m8767->buck2_ramp = pdata->buck2_ramp_enable;
753*4882a593Smuzhiyun 	s5m8767->buck3_ramp = pdata->buck3_ramp_enable;
754*4882a593Smuzhiyun 	s5m8767->buck4_ramp = pdata->buck4_ramp_enable;
755*4882a593Smuzhiyun 	s5m8767->opmode = pdata->opmode;
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
758*4882a593Smuzhiyun 						   pdata->buck2_init);
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun 	regmap_write(s5m8767->iodev->regmap_pmic, S5M8767_REG_BUCK2DVS2,
761*4882a593Smuzhiyun 			buck_init);
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
764*4882a593Smuzhiyun 						   pdata->buck3_init);
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun 	regmap_write(s5m8767->iodev->regmap_pmic, S5M8767_REG_BUCK3DVS2,
767*4882a593Smuzhiyun 			buck_init);
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
770*4882a593Smuzhiyun 						   pdata->buck4_init);
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	regmap_write(s5m8767->iodev->regmap_pmic, S5M8767_REG_BUCK4DVS2,
773*4882a593Smuzhiyun 			buck_init);
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
776*4882a593Smuzhiyun 		if (s5m8767->buck2_gpiodvs) {
777*4882a593Smuzhiyun 			s5m8767->buck2_vol[i] =
778*4882a593Smuzhiyun 				s5m8767_convert_voltage_to_sel(
779*4882a593Smuzhiyun 						&buck_voltage_val2,
780*4882a593Smuzhiyun 						pdata->buck2_voltage[i]);
781*4882a593Smuzhiyun 		}
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 		if (s5m8767->buck3_gpiodvs) {
784*4882a593Smuzhiyun 			s5m8767->buck3_vol[i] =
785*4882a593Smuzhiyun 				s5m8767_convert_voltage_to_sel(
786*4882a593Smuzhiyun 						&buck_voltage_val2,
787*4882a593Smuzhiyun 						pdata->buck3_voltage[i]);
788*4882a593Smuzhiyun 		}
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 		if (s5m8767->buck4_gpiodvs) {
791*4882a593Smuzhiyun 			s5m8767->buck4_vol[i] =
792*4882a593Smuzhiyun 				s5m8767_convert_voltage_to_sel(
793*4882a593Smuzhiyun 						&buck_voltage_val2,
794*4882a593Smuzhiyun 						pdata->buck4_voltage[i]);
795*4882a593Smuzhiyun 		}
796*4882a593Smuzhiyun 	}
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 	if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
799*4882a593Smuzhiyun 						pdata->buck4_gpiodvs) {
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun 		if (!gpio_is_valid(pdata->buck_gpios[0]) ||
802*4882a593Smuzhiyun 			!gpio_is_valid(pdata->buck_gpios[1]) ||
803*4882a593Smuzhiyun 			!gpio_is_valid(pdata->buck_gpios[2])) {
804*4882a593Smuzhiyun 			dev_err(&pdev->dev, "GPIO NOT VALID\n");
805*4882a593Smuzhiyun 			return -EINVAL;
806*4882a593Smuzhiyun 		}
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 		ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[0],
809*4882a593Smuzhiyun 					"S5M8767 SET1");
810*4882a593Smuzhiyun 		if (ret)
811*4882a593Smuzhiyun 			return ret;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 		ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[1],
814*4882a593Smuzhiyun 					"S5M8767 SET2");
815*4882a593Smuzhiyun 		if (ret)
816*4882a593Smuzhiyun 			return ret;
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun 		ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[2],
819*4882a593Smuzhiyun 					"S5M8767 SET3");
820*4882a593Smuzhiyun 		if (ret)
821*4882a593Smuzhiyun 			return ret;
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 		/* SET1 GPIO */
824*4882a593Smuzhiyun 		gpio_direction_output(pdata->buck_gpios[0],
825*4882a593Smuzhiyun 				(s5m8767->buck_gpioindex >> 2) & 0x1);
826*4882a593Smuzhiyun 		/* SET2 GPIO */
827*4882a593Smuzhiyun 		gpio_direction_output(pdata->buck_gpios[1],
828*4882a593Smuzhiyun 				(s5m8767->buck_gpioindex >> 1) & 0x1);
829*4882a593Smuzhiyun 		/* SET3 GPIO */
830*4882a593Smuzhiyun 		gpio_direction_output(pdata->buck_gpios[2],
831*4882a593Smuzhiyun 				(s5m8767->buck_gpioindex >> 0) & 0x1);
832*4882a593Smuzhiyun 	}
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 	ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[0], "S5M8767 DS2");
835*4882a593Smuzhiyun 	if (ret)
836*4882a593Smuzhiyun 		return ret;
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[1], "S5M8767 DS3");
839*4882a593Smuzhiyun 	if (ret)
840*4882a593Smuzhiyun 		return ret;
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[2], "S5M8767 DS4");
843*4882a593Smuzhiyun 	if (ret)
844*4882a593Smuzhiyun 		return ret;
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun 	/* DS2 GPIO */
847*4882a593Smuzhiyun 	gpio_direction_output(pdata->buck_ds[0], 0x0);
848*4882a593Smuzhiyun 	/* DS3 GPIO */
849*4882a593Smuzhiyun 	gpio_direction_output(pdata->buck_ds[1], 0x0);
850*4882a593Smuzhiyun 	/* DS4 GPIO */
851*4882a593Smuzhiyun 	gpio_direction_output(pdata->buck_ds[2], 0x0);
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	regmap_update_bits(s5m8767->iodev->regmap_pmic,
854*4882a593Smuzhiyun 			   S5M8767_REG_BUCK2CTRL, 1 << 1,
855*4882a593Smuzhiyun 			   (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1));
856*4882a593Smuzhiyun 	regmap_update_bits(s5m8767->iodev->regmap_pmic,
857*4882a593Smuzhiyun 			   S5M8767_REG_BUCK3CTRL, 1 << 1,
858*4882a593Smuzhiyun 			   (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1));
859*4882a593Smuzhiyun 	regmap_update_bits(s5m8767->iodev->regmap_pmic,
860*4882a593Smuzhiyun 			   S5M8767_REG_BUCK4CTRL, 1 << 1,
861*4882a593Smuzhiyun 			   (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1));
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	/* Initialize GPIO DVS registers */
864*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
865*4882a593Smuzhiyun 		if (s5m8767->buck2_gpiodvs) {
866*4882a593Smuzhiyun 			regmap_write(s5m8767->iodev->regmap_pmic,
867*4882a593Smuzhiyun 					S5M8767_REG_BUCK2DVS1 + i,
868*4882a593Smuzhiyun 					s5m8767->buck2_vol[i]);
869*4882a593Smuzhiyun 		}
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun 		if (s5m8767->buck3_gpiodvs) {
872*4882a593Smuzhiyun 			regmap_write(s5m8767->iodev->regmap_pmic,
873*4882a593Smuzhiyun 					S5M8767_REG_BUCK3DVS1 + i,
874*4882a593Smuzhiyun 					s5m8767->buck3_vol[i]);
875*4882a593Smuzhiyun 		}
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 		if (s5m8767->buck4_gpiodvs) {
878*4882a593Smuzhiyun 			regmap_write(s5m8767->iodev->regmap_pmic,
879*4882a593Smuzhiyun 					S5M8767_REG_BUCK4DVS1 + i,
880*4882a593Smuzhiyun 					s5m8767->buck4_vol[i]);
881*4882a593Smuzhiyun 		}
882*4882a593Smuzhiyun 	}
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 	if (s5m8767->buck2_ramp)
885*4882a593Smuzhiyun 		regmap_update_bits(s5m8767->iodev->regmap_pmic,
886*4882a593Smuzhiyun 				S5M8767_REG_DVSRAMP, 0x08, 0x08);
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun 	if (s5m8767->buck3_ramp)
889*4882a593Smuzhiyun 		regmap_update_bits(s5m8767->iodev->regmap_pmic,
890*4882a593Smuzhiyun 				S5M8767_REG_DVSRAMP, 0x04, 0x04);
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun 	if (s5m8767->buck4_ramp)
893*4882a593Smuzhiyun 		regmap_update_bits(s5m8767->iodev->regmap_pmic,
894*4882a593Smuzhiyun 				S5M8767_REG_DVSRAMP, 0x02, 0x02);
895*4882a593Smuzhiyun 
896*4882a593Smuzhiyun 	if (s5m8767->buck2_ramp || s5m8767->buck3_ramp
897*4882a593Smuzhiyun 		|| s5m8767->buck4_ramp) {
898*4882a593Smuzhiyun 		unsigned int val;
899*4882a593Smuzhiyun 		switch (s5m8767->ramp_delay) {
900*4882a593Smuzhiyun 		case 5:
901*4882a593Smuzhiyun 			val = S5M8767_DVS_BUCK_RAMP_5;
902*4882a593Smuzhiyun 			break;
903*4882a593Smuzhiyun 		case 10:
904*4882a593Smuzhiyun 			val = S5M8767_DVS_BUCK_RAMP_10;
905*4882a593Smuzhiyun 			break;
906*4882a593Smuzhiyun 		case 25:
907*4882a593Smuzhiyun 			val = S5M8767_DVS_BUCK_RAMP_25;
908*4882a593Smuzhiyun 			break;
909*4882a593Smuzhiyun 		case 50:
910*4882a593Smuzhiyun 			val = S5M8767_DVS_BUCK_RAMP_50;
911*4882a593Smuzhiyun 			break;
912*4882a593Smuzhiyun 		case 100:
913*4882a593Smuzhiyun 			val = S5M8767_DVS_BUCK_RAMP_100;
914*4882a593Smuzhiyun 			break;
915*4882a593Smuzhiyun 		default:
916*4882a593Smuzhiyun 			val = S5M8767_DVS_BUCK_RAMP_10;
917*4882a593Smuzhiyun 		}
918*4882a593Smuzhiyun 		regmap_update_bits(s5m8767->iodev->regmap_pmic,
919*4882a593Smuzhiyun 					S5M8767_REG_DVSRAMP,
920*4882a593Smuzhiyun 					S5M8767_DVS_BUCK_RAMP_MASK,
921*4882a593Smuzhiyun 					val << S5M8767_DVS_BUCK_RAMP_SHIFT);
922*4882a593Smuzhiyun 	}
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	for (i = 0; i < pdata->num_regulators; i++) {
925*4882a593Smuzhiyun 		const struct sec_voltage_desc *desc;
926*4882a593Smuzhiyun 		int id = pdata->regulators[i].id;
927*4882a593Smuzhiyun 		int enable_reg, enable_val;
928*4882a593Smuzhiyun 		struct regulator_dev *rdev;
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 		desc = reg_voltage_map[id];
931*4882a593Smuzhiyun 		if (desc) {
932*4882a593Smuzhiyun 			regulators[id].n_voltages =
933*4882a593Smuzhiyun 				(desc->max - desc->min) / desc->step + 1;
934*4882a593Smuzhiyun 			regulators[id].min_uV = desc->min;
935*4882a593Smuzhiyun 			regulators[id].uV_step = desc->step;
936*4882a593Smuzhiyun 			regulators[id].vsel_reg =
937*4882a593Smuzhiyun 				s5m8767_get_vsel_reg(id, s5m8767);
938*4882a593Smuzhiyun 			if (id < S5M8767_BUCK1)
939*4882a593Smuzhiyun 				regulators[id].vsel_mask = 0x3f;
940*4882a593Smuzhiyun 			else
941*4882a593Smuzhiyun 				regulators[id].vsel_mask = 0xff;
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 			ret = s5m8767_get_register(s5m8767, id, &enable_reg,
944*4882a593Smuzhiyun 					     &enable_val);
945*4882a593Smuzhiyun 			if (ret) {
946*4882a593Smuzhiyun 				dev_err(s5m8767->dev, "error reading registers\n");
947*4882a593Smuzhiyun 				return ret;
948*4882a593Smuzhiyun 			}
949*4882a593Smuzhiyun 			regulators[id].enable_reg = enable_reg;
950*4882a593Smuzhiyun 			regulators[id].enable_mask = S5M8767_ENCTRL_MASK;
951*4882a593Smuzhiyun 			regulators[id].enable_val = enable_val;
952*4882a593Smuzhiyun 		}
953*4882a593Smuzhiyun 
954*4882a593Smuzhiyun 		config.dev = s5m8767->dev;
955*4882a593Smuzhiyun 		config.init_data = pdata->regulators[i].initdata;
956*4882a593Smuzhiyun 		config.driver_data = s5m8767;
957*4882a593Smuzhiyun 		config.regmap = iodev->regmap_pmic;
958*4882a593Smuzhiyun 		config.of_node = pdata->regulators[i].reg_node;
959*4882a593Smuzhiyun 		config.ena_gpiod = NULL;
960*4882a593Smuzhiyun 		if (pdata->regulators[i].ext_control_gpiod) {
961*4882a593Smuzhiyun 			/* Assigns config.ena_gpiod */
962*4882a593Smuzhiyun 			s5m8767_regulator_config_ext_control(s5m8767,
963*4882a593Smuzhiyun 					&pdata->regulators[i], &config);
964*4882a593Smuzhiyun 
965*4882a593Smuzhiyun 			/*
966*4882a593Smuzhiyun 			 * Hand the GPIO descriptor management over to the
967*4882a593Smuzhiyun 			 * regulator core, remove it from devres management.
968*4882a593Smuzhiyun 			 */
969*4882a593Smuzhiyun 			devm_gpiod_unhinge(s5m8767->dev, config.ena_gpiod);
970*4882a593Smuzhiyun 		}
971*4882a593Smuzhiyun 		rdev = devm_regulator_register(&pdev->dev, &regulators[id],
972*4882a593Smuzhiyun 						  &config);
973*4882a593Smuzhiyun 		if (IS_ERR(rdev)) {
974*4882a593Smuzhiyun 			ret = PTR_ERR(rdev);
975*4882a593Smuzhiyun 			dev_err(s5m8767->dev, "regulator init failed for %d\n",
976*4882a593Smuzhiyun 					id);
977*4882a593Smuzhiyun 			return ret;
978*4882a593Smuzhiyun 		}
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun 		if (pdata->regulators[i].ext_control_gpiod) {
981*4882a593Smuzhiyun 			ret = s5m8767_enable_ext_control(s5m8767, rdev);
982*4882a593Smuzhiyun 			if (ret < 0) {
983*4882a593Smuzhiyun 				dev_err(s5m8767->dev,
984*4882a593Smuzhiyun 						"failed to enable gpio control over %s: %d\n",
985*4882a593Smuzhiyun 						rdev->desc->name, ret);
986*4882a593Smuzhiyun 				return ret;
987*4882a593Smuzhiyun 			}
988*4882a593Smuzhiyun 		}
989*4882a593Smuzhiyun 	}
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun 	return 0;
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun static const struct platform_device_id s5m8767_pmic_id[] = {
995*4882a593Smuzhiyun 	{ "s5m8767-pmic", 0},
996*4882a593Smuzhiyun 	{ },
997*4882a593Smuzhiyun };
998*4882a593Smuzhiyun MODULE_DEVICE_TABLE(platform, s5m8767_pmic_id);
999*4882a593Smuzhiyun 
1000*4882a593Smuzhiyun static struct platform_driver s5m8767_pmic_driver = {
1001*4882a593Smuzhiyun 	.driver = {
1002*4882a593Smuzhiyun 		.name = "s5m8767-pmic",
1003*4882a593Smuzhiyun 	},
1004*4882a593Smuzhiyun 	.probe = s5m8767_pmic_probe,
1005*4882a593Smuzhiyun 	.id_table = s5m8767_pmic_id,
1006*4882a593Smuzhiyun };
1007*4882a593Smuzhiyun module_platform_driver(s5m8767_pmic_driver);
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun /* Module information */
1010*4882a593Smuzhiyun MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
1011*4882a593Smuzhiyun MODULE_DESCRIPTION("Samsung S5M8767 Regulator Driver");
1012*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1013