Blame view

drivers/regulator/s5m8767.c 25.9 KB
4f3fb2873   Krzysztof Kozlowski   regulator: samsun...
1
2
3
4
  // SPDX-License-Identifier: GPL-2.0+
  //
  // Copyright (c) 2011 Samsung Electronics Co., Ltd
  //              http://www.samsung.com
9767ec7fe   Sangbeom Kim   regulator: Add S5...
5

9767ec7fe   Sangbeom Kim   regulator: Add S5...
6
  #include <linux/err.h>
26aec009f   Amit Daniel Kachhap   regulator: add de...
7
  #include <linux/of_gpio.h>
9ae5cc75c   Linus Walleij   regulator: s5m876...
8
  #include <linux/gpio/consumer.h>
9767ec7fe   Sangbeom Kim   regulator: Add S5...
9
10
11
12
  #include <linux/module.h>
  #include <linux/platform_device.h>
  #include <linux/regulator/driver.h>
  #include <linux/regulator/machine.h>
54227bcf2   Sangbeom Kim   mfd: Modify samsu...
13
14
  #include <linux/mfd/samsung/core.h>
  #include <linux/mfd/samsung/s5m8767.h>
26aec009f   Amit Daniel Kachhap   regulator: add de...
15
  #include <linux/regulator/of_regulator.h>
d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
16
  #include <linux/regmap.h>
26aec009f   Amit Daniel Kachhap   regulator: add de...
17
18
  
  #define S5M8767_OPMODE_NORMAL_MODE 0x1
9767ec7fe   Sangbeom Kim   regulator: Add S5...
19
20
21
  
  struct s5m8767_info {
  	struct device *dev;
63063bfbf   Sangbeom Kim   mfd: Modify samsu...
22
  	struct sec_pmic_dev *iodev;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
23
  	int num_regulators;
63063bfbf   Sangbeom Kim   mfd: Modify samsu...
24
  	struct sec_opmode_data *opmode;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
25
26
27
28
29
30
31
32
33
34
35
36
37
  
  	int ramp_delay;
  	bool buck2_ramp;
  	bool buck3_ramp;
  	bool buck4_ramp;
  
  	bool buck2_gpiodvs;
  	bool buck3_gpiodvs;
  	bool buck4_gpiodvs;
  	u8 buck2_vol[8];
  	u8 buck3_vol[8];
  	u8 buck4_vol[8];
  	int buck_gpios[3];
c848bc853   Sangbeom Kim   regulator: s5m876...
38
  	int buck_ds[3];
9767ec7fe   Sangbeom Kim   regulator: Add S5...
39
40
  	int buck_gpioindex;
  };
63063bfbf   Sangbeom Kim   mfd: Modify samsu...
41
  struct sec_voltage_desc {
9767ec7fe   Sangbeom Kim   regulator: Add S5...
42
43
44
45
  	int max;
  	int min;
  	int step;
  };
63063bfbf   Sangbeom Kim   mfd: Modify samsu...
46
  static const struct sec_voltage_desc buck_voltage_val1 = {
9767ec7fe   Sangbeom Kim   regulator: Add S5...
47
48
49
50
  	.max = 2225000,
  	.min =  650000,
  	.step =   6250,
  };
63063bfbf   Sangbeom Kim   mfd: Modify samsu...
51
  static const struct sec_voltage_desc buck_voltage_val2 = {
9767ec7fe   Sangbeom Kim   regulator: Add S5...
52
53
54
55
  	.max = 1600000,
  	.min =  600000,
  	.step =   6250,
  };
63063bfbf   Sangbeom Kim   mfd: Modify samsu...
56
  static const struct sec_voltage_desc buck_voltage_val3 = {
9767ec7fe   Sangbeom Kim   regulator: Add S5...
57
58
59
60
  	.max = 3000000,
  	.min =  750000,
  	.step =  12500,
  };
63063bfbf   Sangbeom Kim   mfd: Modify samsu...
61
  static const struct sec_voltage_desc ldo_voltage_val1 = {
9767ec7fe   Sangbeom Kim   regulator: Add S5...
62
63
64
65
  	.max = 3950000,
  	.min =  800000,
  	.step =  50000,
  };
63063bfbf   Sangbeom Kim   mfd: Modify samsu...
66
  static const struct sec_voltage_desc ldo_voltage_val2 = {
9767ec7fe   Sangbeom Kim   regulator: Add S5...
67
68
69
70
  	.max = 2375000,
  	.min =  800000,
  	.step =  25000,
  };
63063bfbf   Sangbeom Kim   mfd: Modify samsu...
71
  static const struct sec_voltage_desc *reg_voltage_map[] = {
9767ec7fe   Sangbeom Kim   regulator: Add S5...
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  	[S5M8767_LDO1] = &ldo_voltage_val2,
  	[S5M8767_LDO2] = &ldo_voltage_val2,
  	[S5M8767_LDO3] = &ldo_voltage_val1,
  	[S5M8767_LDO4] = &ldo_voltage_val1,
  	[S5M8767_LDO5] = &ldo_voltage_val1,
  	[S5M8767_LDO6] = &ldo_voltage_val2,
  	[S5M8767_LDO7] = &ldo_voltage_val2,
  	[S5M8767_LDO8] = &ldo_voltage_val2,
  	[S5M8767_LDO9] = &ldo_voltage_val1,
  	[S5M8767_LDO10] = &ldo_voltage_val1,
  	[S5M8767_LDO11] = &ldo_voltage_val1,
  	[S5M8767_LDO12] = &ldo_voltage_val1,
  	[S5M8767_LDO13] = &ldo_voltage_val1,
  	[S5M8767_LDO14] = &ldo_voltage_val1,
  	[S5M8767_LDO15] = &ldo_voltage_val2,
  	[S5M8767_LDO16] = &ldo_voltage_val1,
  	[S5M8767_LDO17] = &ldo_voltage_val1,
  	[S5M8767_LDO18] = &ldo_voltage_val1,
  	[S5M8767_LDO19] = &ldo_voltage_val1,
  	[S5M8767_LDO20] = &ldo_voltage_val1,
  	[S5M8767_LDO21] = &ldo_voltage_val1,
  	[S5M8767_LDO22] = &ldo_voltage_val1,
  	[S5M8767_LDO23] = &ldo_voltage_val1,
  	[S5M8767_LDO24] = &ldo_voltage_val1,
  	[S5M8767_LDO25] = &ldo_voltage_val1,
  	[S5M8767_LDO26] = &ldo_voltage_val1,
  	[S5M8767_LDO27] = &ldo_voltage_val1,
  	[S5M8767_LDO28] = &ldo_voltage_val1,
  	[S5M8767_BUCK1] = &buck_voltage_val1,
  	[S5M8767_BUCK2] = &buck_voltage_val2,
  	[S5M8767_BUCK3] = &buck_voltage_val2,
  	[S5M8767_BUCK4] = &buck_voltage_val2,
  	[S5M8767_BUCK5] = &buck_voltage_val1,
  	[S5M8767_BUCK6] = &buck_voltage_val1,
463616ea3   Krzysztof Kozlowski   regulator: s5m876...
106
107
  	[S5M8767_BUCK7] = &buck_voltage_val3,
  	[S5M8767_BUCK8] = &buck_voltage_val3,
9767ec7fe   Sangbeom Kim   regulator: Add S5...
108
109
  	[S5M8767_BUCK9] = &buck_voltage_val3,
  };
21687b162   Axel Lin   regulator: s5m876...
110
  static const unsigned int s5m8767_opmode_reg[][4] = {
7e44bb83a   Sangbeom Kim   regulator: Add su...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  	/* {OFF, ON, LOWPOWER, SUSPEND} */
  	/* LDO1 ... LDO28 */
  	{0x0, 0x3, 0x2, 0x1}, /* LDO1 */
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x0, 0x0, 0x0},
  	{0x0, 0x3, 0x2, 0x1}, /* LDO5 */
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1}, /* LDO10 */
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1}, /* LDO15 */
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x0, 0x0, 0x0},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1}, /* LDO20 */
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x0, 0x0, 0x0},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1}, /* LDO25 */
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1},
  	{0x0, 0x3, 0x2, 0x1}, /* LDO28 */
  
  	/* BUCK1 ... BUCK9 */
  	{0x0, 0x3, 0x1, 0x1}, /* BUCK1 */
  	{0x0, 0x3, 0x1, 0x1},
  	{0x0, 0x3, 0x1, 0x1},
  	{0x0, 0x3, 0x1, 0x1},
  	{0x0, 0x3, 0x2, 0x1}, /* BUCK5 */
  	{0x0, 0x3, 0x1, 0x1},
  	{0x0, 0x3, 0x1, 0x1},
  	{0x0, 0x3, 0x1, 0x1},
  	{0x0, 0x3, 0x1, 0x1}, /* BUCK9 */
  };
9c4c60554   Axel Lin   regulator: s5m876...
153
154
  static int s5m8767_get_register(struct s5m8767_info *s5m8767, int reg_id,
  				int *reg, int *enable_ctrl)
9767ec7fe   Sangbeom Kim   regulator: Add S5...
155
  {
9c4c60554   Axel Lin   regulator: s5m876...
156
  	int i;
7e44bb83a   Sangbeom Kim   regulator: Add su...
157
  	unsigned int mode;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  
  	switch (reg_id) {
  	case S5M8767_LDO1 ... S5M8767_LDO2:
  		*reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1);
  		break;
  	case S5M8767_LDO3 ... S5M8767_LDO28:
  		*reg = S5M8767_REG_LDO3CTRL + (reg_id - S5M8767_LDO3);
  		break;
  	case S5M8767_BUCK1:
  		*reg = S5M8767_REG_BUCK1CTRL1;
  		break;
  	case S5M8767_BUCK2 ... S5M8767_BUCK4:
  		*reg = S5M8767_REG_BUCK2CTRL + (reg_id - S5M8767_BUCK2) * 9;
  		break;
  	case S5M8767_BUCK5:
  		*reg = S5M8767_REG_BUCK5CTRL1;
  		break;
  	case S5M8767_BUCK6 ... S5M8767_BUCK9:
  		*reg = S5M8767_REG_BUCK6CTRL1 + (reg_id - S5M8767_BUCK6) * 2;
  		break;
  	default:
  		return -EINVAL;
  	}
9bb096ff3   Amit Daniel Kachhap   regulator: s5m876...
181
182
183
184
185
186
  	for (i = 0; i < s5m8767->num_regulators; i++) {
  		if (s5m8767->opmode[i].id == reg_id) {
  			mode = s5m8767->opmode[i].mode;
  			break;
  		}
  	}
e07ff9434   Arnd Bergmann   regulator: s5m876...
187
188
189
190
  	if (i >= s5m8767->num_regulators)
  		return -EINVAL;
  
  	*enable_ctrl = s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
9bb096ff3   Amit Daniel Kachhap   regulator: s5m876...
191

9767ec7fe   Sangbeom Kim   regulator: Add S5...
192
193
  	return 0;
  }
31a932e10   Axel Lin   regulator: s5m876...
194
  static int s5m8767_get_vsel_reg(int reg_id, struct s5m8767_info *s5m8767)
9767ec7fe   Sangbeom Kim   regulator: Add S5...
195
  {
9767ec7fe   Sangbeom Kim   regulator: Add S5...
196
197
198
199
200
201
202
203
204
205
206
207
208
  	int reg;
  
  	switch (reg_id) {
  	case S5M8767_LDO1 ... S5M8767_LDO2:
  		reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1);
  		break;
  	case S5M8767_LDO3 ... S5M8767_LDO28:
  		reg = S5M8767_REG_LDO3CTRL + (reg_id - S5M8767_LDO3);
  		break;
  	case S5M8767_BUCK1:
  		reg = S5M8767_REG_BUCK1CTRL2;
  		break;
  	case S5M8767_BUCK2:
da130ab2d   Amit Daniel Kachhap   regulator: s5m876...
209
  		reg = S5M8767_REG_BUCK2DVS1;
0a41685fd   Axel Lin   regulator: Make s...
210
211
  		if (s5m8767->buck2_gpiodvs)
  			reg += s5m8767->buck_gpioindex;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
212
213
  		break;
  	case S5M8767_BUCK3:
da130ab2d   Amit Daniel Kachhap   regulator: s5m876...
214
  		reg = S5M8767_REG_BUCK3DVS1;
0a41685fd   Axel Lin   regulator: Make s...
215
216
  		if (s5m8767->buck3_gpiodvs)
  			reg += s5m8767->buck_gpioindex;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
217
218
  		break;
  	case S5M8767_BUCK4:
da130ab2d   Amit Daniel Kachhap   regulator: s5m876...
219
  		reg = S5M8767_REG_BUCK4DVS1;
0a41685fd   Axel Lin   regulator: Make s...
220
221
  		if (s5m8767->buck4_gpiodvs)
  			reg += s5m8767->buck_gpioindex;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
222
223
224
225
226
227
228
229
230
231
  		break;
  	case S5M8767_BUCK5:
  		reg = S5M8767_REG_BUCK5CTRL2;
  		break;
  	case S5M8767_BUCK6 ... S5M8767_BUCK9:
  		reg = S5M8767_REG_BUCK6CTRL2 + (reg_id - S5M8767_BUCK6) * 2;
  		break;
  	default:
  		return -EINVAL;
  	}
31a932e10   Axel Lin   regulator: s5m876...
232
  	return reg;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
233
  }
854f73ecb   Axel Lin   regulator: s5m876...
234
235
  static int s5m8767_convert_voltage_to_sel(const struct sec_voltage_desc *desc,
  					  int min_vol)
9767ec7fe   Sangbeom Kim   regulator: Add S5...
236
  {
5b5e977ce   Axel Lin   regulator: Rename...
237
  	int selector = 0;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
238
239
240
  
  	if (desc == NULL)
  		return -EINVAL;
854f73ecb   Axel Lin   regulator: s5m876...
241
  	if (min_vol > desc->max)
9767ec7fe   Sangbeom Kim   regulator: Add S5...
242
  		return -EINVAL;
94e85a3c5   Axel Lin   regulator: s5m876...
243
244
245
246
  	if (min_vol < desc->min)
  		min_vol = desc->min;
  
  	selector = DIV_ROUND_UP(min_vol - desc->min, desc->step);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
247

854f73ecb   Axel Lin   regulator: s5m876...
248
  	if (desc->min + desc->step * selector > desc->max)
9767ec7fe   Sangbeom Kim   regulator: Add S5...
249
  		return -EINVAL;
5b5e977ce   Axel Lin   regulator: Rename...
250
  	return selector;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
251
  }
df2643cfa   Sangbeom Kim   regulator: Replac...
252
  static inline int s5m8767_set_high(struct s5m8767_info *s5m8767)
321d2abac   Axel Lin   regulator: Rework...
253
254
255
256
257
258
  {
  	int temp_index = s5m8767->buck_gpioindex;
  
  	gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
  	gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
  	gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
df2643cfa   Sangbeom Kim   regulator: Replac...
259
260
  
  	return 0;
321d2abac   Axel Lin   regulator: Rework...
261
  }
df2643cfa   Sangbeom Kim   regulator: Replac...
262
  static inline int s5m8767_set_low(struct s5m8767_info *s5m8767)
321d2abac   Axel Lin   regulator: Rework...
263
264
265
266
267
268
  {
  	int temp_index = s5m8767->buck_gpioindex;
  
  	gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
  	gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
  	gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
df2643cfa   Sangbeom Kim   regulator: Replac...
269
270
  
  	return 0;
321d2abac   Axel Lin   regulator: Rework...
271
  }
df2643cfa   Sangbeom Kim   regulator: Replac...
272
273
  static int s5m8767_set_voltage_sel(struct regulator_dev *rdev,
  				   unsigned selector)
9767ec7fe   Sangbeom Kim   regulator: Add S5...
274
275
  {
  	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
20a14b84f   Axel Lin   regulator: Kill s...
276
  	int reg_id = rdev_get_id(rdev);
31a932e10   Axel Lin   regulator: s5m876...
277
  	int old_index, index = 0;
321d2abac   Axel Lin   regulator: Rework...
278
  	u8 *buck234_vol = NULL;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
279
280
281
  
  	switch (reg_id) {
  	case S5M8767_LDO1 ... S5M8767_LDO28:
9767ec7fe   Sangbeom Kim   regulator: Add S5...
282
283
  		break;
  	case S5M8767_BUCK1 ... S5M8767_BUCK6:
321d2abac   Axel Lin   regulator: Rework...
284
285
286
287
288
289
  		if (reg_id == S5M8767_BUCK2 && s5m8767->buck2_gpiodvs)
  			buck234_vol = &s5m8767->buck2_vol[0];
  		else if (reg_id == S5M8767_BUCK3 && s5m8767->buck3_gpiodvs)
  			buck234_vol = &s5m8767->buck3_vol[0];
  		else if (reg_id == S5M8767_BUCK4 && s5m8767->buck4_gpiodvs)
  			buck234_vol = &s5m8767->buck4_vol[0];
9767ec7fe   Sangbeom Kim   regulator: Add S5...
290
291
292
293
  		break;
  	case S5M8767_BUCK7 ... S5M8767_BUCK8:
  		return -EINVAL;
  	case S5M8767_BUCK9:
9767ec7fe   Sangbeom Kim   regulator: Add S5...
294
295
296
297
  		break;
  	default:
  		return -EINVAL;
  	}
321d2abac   Axel Lin   regulator: Rework...
298
299
  	/* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */
  	if (buck234_vol) {
df2643cfa   Sangbeom Kim   regulator: Replac...
300
  		while (*buck234_vol != selector) {
321d2abac   Axel Lin   regulator: Rework...
301
302
303
304
305
306
307
  			buck234_vol++;
  			index++;
  		}
  		old_index = s5m8767->buck_gpioindex;
  		s5m8767->buck_gpioindex = index;
  
  		if (index > old_index)
df2643cfa   Sangbeom Kim   regulator: Replac...
308
  			return s5m8767_set_high(s5m8767);
321d2abac   Axel Lin   regulator: Rework...
309
  		else
df2643cfa   Sangbeom Kim   regulator: Replac...
310
  			return s5m8767_set_low(s5m8767);
321d2abac   Axel Lin   regulator: Rework...
311
  	} else {
31a932e10   Axel Lin   regulator: s5m876...
312
  		return regulator_set_voltage_sel_regmap(rdev, selector);
321d2abac   Axel Lin   regulator: Rework...
313
  	}
9767ec7fe   Sangbeom Kim   regulator: Add S5...
314
  }
9767ec7fe   Sangbeom Kim   regulator: Add S5...
315
316
317
318
319
  static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
  					     unsigned int old_sel,
  					     unsigned int new_sel)
  {
  	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
320

9d88fc0b3   Sangbeom Kim   regulator: Fix th...
321
  	if ((old_sel < new_sel) && s5m8767->ramp_delay)
bf1fc259e   Axel Lin   regulator: s5m876...
322
  		return DIV_ROUND_UP(rdev->desc->uV_step * (new_sel - old_sel),
0f8b9c774   Sangbeom Kim   regulator: Fix s5...
323
  					s5m8767->ramp_delay * 1000);
89e0f0e40   Axel Lin   regulator: Fix th...
324
  	return 0;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
325
  }
8a05eb190   Krzysztof Kozlowski   regulator: s5m876...
326
  static const struct regulator_ops s5m8767_ops = {
e2eb169b1   Axel Lin   regulator: s5m876...
327
  	.list_voltage		= regulator_list_voltage_linear,
9c4c60554   Axel Lin   regulator: s5m876...
328
329
330
  	.is_enabled		= regulator_is_enabled_regmap,
  	.enable			= regulator_enable_regmap,
  	.disable		= regulator_disable_regmap,
31a932e10   Axel Lin   regulator: s5m876...
331
  	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
df2643cfa   Sangbeom Kim   regulator: Replac...
332
  	.set_voltage_sel	= s5m8767_set_voltage_sel,
9767ec7fe   Sangbeom Kim   regulator: Add S5...
333
334
  	.set_voltage_time_sel	= s5m8767_set_voltage_time_sel,
  };
8a05eb190   Krzysztof Kozlowski   regulator: s5m876...
335
  static const struct regulator_ops s5m8767_buck78_ops = {
463616ea3   Krzysztof Kozlowski   regulator: s5m876...
336
  	.list_voltage		= regulator_list_voltage_linear,
9c4c60554   Axel Lin   regulator: s5m876...
337
338
339
  	.is_enabled		= regulator_is_enabled_regmap,
  	.enable			= regulator_enable_regmap,
  	.disable		= regulator_disable_regmap,
463616ea3   Krzysztof Kozlowski   regulator: s5m876...
340
341
  	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
  	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
e2eb169b1   Axel Lin   regulator: s5m876...
342
  };
65896e736   Axel Lin   regulator: Replac...
343
344
345
346
  #define s5m8767_regulator_desc(_name) {		\
  	.name		= #_name,		\
  	.id		= S5M8767_##_name,	\
  	.ops		= &s5m8767_ops,		\
9767ec7fe   Sangbeom Kim   regulator: Add S5...
347
348
349
  	.type		= REGULATOR_VOLTAGE,	\
  	.owner		= THIS_MODULE,		\
  }
e2eb169b1   Axel Lin   regulator: s5m876...
350
351
352
353
354
355
356
  #define s5m8767_regulator_buck78_desc(_name) {	\
  	.name		= #_name,		\
  	.id		= S5M8767_##_name,	\
  	.ops		= &s5m8767_buck78_ops,	\
  	.type		= REGULATOR_VOLTAGE,	\
  	.owner		= THIS_MODULE,		\
  }
9767ec7fe   Sangbeom Kim   regulator: Add S5...
357
  static struct regulator_desc regulators[] = {
65896e736   Axel Lin   regulator: Replac...
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
  	s5m8767_regulator_desc(LDO1),
  	s5m8767_regulator_desc(LDO2),
  	s5m8767_regulator_desc(LDO3),
  	s5m8767_regulator_desc(LDO4),
  	s5m8767_regulator_desc(LDO5),
  	s5m8767_regulator_desc(LDO6),
  	s5m8767_regulator_desc(LDO7),
  	s5m8767_regulator_desc(LDO8),
  	s5m8767_regulator_desc(LDO9),
  	s5m8767_regulator_desc(LDO10),
  	s5m8767_regulator_desc(LDO11),
  	s5m8767_regulator_desc(LDO12),
  	s5m8767_regulator_desc(LDO13),
  	s5m8767_regulator_desc(LDO14),
  	s5m8767_regulator_desc(LDO15),
  	s5m8767_regulator_desc(LDO16),
  	s5m8767_regulator_desc(LDO17),
  	s5m8767_regulator_desc(LDO18),
  	s5m8767_regulator_desc(LDO19),
  	s5m8767_regulator_desc(LDO20),
  	s5m8767_regulator_desc(LDO21),
  	s5m8767_regulator_desc(LDO22),
  	s5m8767_regulator_desc(LDO23),
  	s5m8767_regulator_desc(LDO24),
  	s5m8767_regulator_desc(LDO25),
  	s5m8767_regulator_desc(LDO26),
  	s5m8767_regulator_desc(LDO27),
  	s5m8767_regulator_desc(LDO28),
  	s5m8767_regulator_desc(BUCK1),
  	s5m8767_regulator_desc(BUCK2),
  	s5m8767_regulator_desc(BUCK3),
  	s5m8767_regulator_desc(BUCK4),
  	s5m8767_regulator_desc(BUCK5),
  	s5m8767_regulator_desc(BUCK6),
e2eb169b1   Axel Lin   regulator: s5m876...
392
393
  	s5m8767_regulator_buck78_desc(BUCK7),
  	s5m8767_regulator_buck78_desc(BUCK8),
65896e736   Axel Lin   regulator: Replac...
394
  	s5m8767_regulator_desc(BUCK9),
9767ec7fe   Sangbeom Kim   regulator: Add S5...
395
  };
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  /*
   * Enable GPIO control over BUCK9 in regulator_config for that regulator.
   */
  static void s5m8767_regulator_config_ext_control(struct s5m8767_info *s5m8767,
  		struct sec_regulator_data *rdata,
  		struct regulator_config *config)
  {
  	int i, mode = 0;
  
  	if (rdata->id != S5M8767_BUCK9)
  		return;
  
  	/* Check if opmode for regulator matches S5M8767_ENCTRL_USE_GPIO */
  	for (i = 0; i < s5m8767->num_regulators; i++) {
  		const struct sec_opmode_data *opmode = &s5m8767->opmode[i];
  		if (opmode->id == rdata->id) {
  			mode = s5m8767_opmode_reg[rdata->id][opmode->mode];
  			break;
  		}
  	}
  	if (mode != S5M8767_ENCTRL_USE_GPIO) {
  		dev_warn(s5m8767->dev,
0c9721a5d   Rob Herring   regulator: Conver...
418
419
420
  				"ext-control for %pOFn: mismatched op_mode (%x), ignoring
  ",
  				rdata->reg_node, mode);
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
421
422
  		return;
  	}
9ae5cc75c   Linus Walleij   regulator: s5m876...
423
  	if (!rdata->ext_control_gpiod) {
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
424
  		dev_warn(s5m8767->dev,
0c9721a5d   Rob Herring   regulator: Conver...
425
426
427
  				"ext-control for %pOFn: GPIO not valid, ignoring
  ",
  			 rdata->reg_node);
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
428
429
  		return;
  	}
9ae5cc75c   Linus Walleij   regulator: s5m876...
430
  	config->ena_gpiod = rdata->ext_control_gpiod;
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
431
432
433
434
435
436
437
438
  }
  
  /*
   * Turn on GPIO control over BUCK9.
   */
  static int s5m8767_enable_ext_control(struct s5m8767_info *s5m8767,
  		struct regulator_dev *rdev)
  {
9c4c60554   Axel Lin   regulator: s5m876...
439
  	int id = rdev_get_id(rdev);
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
440
  	int ret, reg, enable_ctrl;
9c4c60554   Axel Lin   regulator: s5m876...
441
  	if (id != S5M8767_BUCK9)
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
442
  		return -EINVAL;
9c4c60554   Axel Lin   regulator: s5m876...
443
  	ret = s5m8767_get_register(s5m8767, id, &reg, &enable_ctrl);
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
444
445
446
447
448
449
450
  	if (ret)
  		return ret;
  
  	return regmap_update_bits(s5m8767->iodev->regmap_pmic,
  			reg, S5M8767_ENCTRL_MASK,
  			S5M8767_ENCTRL_USE_GPIO << S5M8767_ENCTRL_SHIFT);
  }
26aec009f   Amit Daniel Kachhap   regulator: add de...
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
  #ifdef CONFIG_OF
  static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev,
  			struct sec_platform_data *pdata,
  			struct device_node *pmic_np)
  {
  	int i, gpio;
  
  	for (i = 0; i < 3; i++) {
  		gpio = of_get_named_gpio(pmic_np,
  					"s5m8767,pmic-buck-dvs-gpios", i);
  		if (!gpio_is_valid(gpio)) {
  			dev_err(iodev->dev, "invalid gpio[%d]: %d
  ", i, gpio);
  			return -EINVAL;
  		}
  		pdata->buck_gpios[i] = gpio;
  	}
  	return 0;
  }
  
  static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev,
  			struct sec_platform_data *pdata,
  			struct device_node *pmic_np)
  {
  	int i, gpio;
  
  	for (i = 0; i < 3; i++) {
  		gpio = of_get_named_gpio(pmic_np,
  					"s5m8767,pmic-buck-ds-gpios", i);
  		if (!gpio_is_valid(gpio)) {
  			dev_err(iodev->dev, "invalid gpio[%d]: %d
  ", i, gpio);
  			return -EINVAL;
  		}
  		pdata->buck_ds[i] = gpio;
  	}
  	return 0;
  }
cbb0ed495   Axel Lin   regulator: s5m876...
489
  static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
26aec009f   Amit Daniel Kachhap   regulator: add de...
490
491
  					struct sec_platform_data *pdata)
  {
cbb0ed495   Axel Lin   regulator: s5m876...
492
  	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
26aec009f   Amit Daniel Kachhap   regulator: add de...
493
494
495
  	struct device_node *pmic_np, *regulators_np, *reg_np;
  	struct sec_regulator_data *rdata;
  	struct sec_opmode_data *rmode;
04f9f068a   Chanwoo Choi   regulator: s5m876...
496
  	unsigned int i, dvs_voltage_nr = 8, ret;
26aec009f   Amit Daniel Kachhap   regulator: add de...
497
498
499
500
501
502
503
  
  	pmic_np = iodev->dev->of_node;
  	if (!pmic_np) {
  		dev_err(iodev->dev, "could not find pmic sub-node
  ");
  		return -ENODEV;
  	}
4e52c03df   Sachin Kamat   regulator: s5m876...
504
  	regulators_np = of_get_child_by_name(pmic_np, "regulators");
26aec009f   Amit Daniel Kachhap   regulator: add de...
505
506
507
508
509
510
511
  	if (!regulators_np) {
  		dev_err(iodev->dev, "could not find regulators sub-node
  ");
  		return -EINVAL;
  	}
  
  	/* count the number of regulators to be supported in pmic */
1f91b6f6c   Axel Lin   regulator: s5m876...
512
  	pdata->num_regulators = of_get_child_count(regulators_np);
26aec009f   Amit Daniel Kachhap   regulator: add de...
513

a86854d0c   Kees Cook   treewide: devm_kz...
514
515
516
  	rdata = devm_kcalloc(&pdev->dev,
  			     pdata->num_regulators, sizeof(*rdata),
  			     GFP_KERNEL);
4754b4211   Sachin Kamat   regulator: s5m876...
517
  	if (!rdata)
26aec009f   Amit Daniel Kachhap   regulator: add de...
518
  		return -ENOMEM;
26aec009f   Amit Daniel Kachhap   regulator: add de...
519

a86854d0c   Kees Cook   treewide: devm_kz...
520
521
522
  	rmode = devm_kcalloc(&pdev->dev,
  			     pdata->num_regulators, sizeof(*rmode),
  			     GFP_KERNEL);
4754b4211   Sachin Kamat   regulator: s5m876...
523
  	if (!rmode)
26aec009f   Amit Daniel Kachhap   regulator: add de...
524
  		return -ENOMEM;
26aec009f   Amit Daniel Kachhap   regulator: add de...
525
526
527
528
529
  
  	pdata->regulators = rdata;
  	pdata->opmode = rmode;
  	for_each_child_of_node(regulators_np, reg_np) {
  		for (i = 0; i < ARRAY_SIZE(regulators); i++)
c32569e35   Rob Herring   regulator: Use of...
530
  			if (of_node_name_eq(reg_np, regulators[i].name))
26aec009f   Amit Daniel Kachhap   regulator: add de...
531
532
533
534
  				break;
  
  		if (i == ARRAY_SIZE(regulators)) {
  			dev_warn(iodev->dev,
0c9721a5d   Rob Herring   regulator: Conver...
535
536
537
  			"don't know how to configure regulator %pOFn
  ",
  			reg_np);
26aec009f   Amit Daniel Kachhap   regulator: add de...
538
539
  			continue;
  		}
5be0e549e   Dmitry Torokhov   regulator: s5m876...
540
  		rdata->ext_control_gpiod = devm_fwnode_gpiod_get(
63239e4bf   Linus Walleij   regulator: Fetch ...
541
  			&pdev->dev,
5be0e549e   Dmitry Torokhov   regulator: s5m876...
542
543
  			of_fwnode_handle(reg_np),
  			"s5m8767,pmic-ext-control",
63239e4bf   Linus Walleij   regulator: Fetch ...
544
545
  			GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
  			"s5m8767");
025bf3772   Waibel Georg   gpio: Fix return ...
546
547
548
  		if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT)
  			rdata->ext_control_gpiod = NULL;
  		else if (IS_ERR(rdata->ext_control_gpiod))
9ae5cc75c   Linus Walleij   regulator: s5m876...
549
  			return PTR_ERR(rdata->ext_control_gpiod);
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
550

26aec009f   Amit Daniel Kachhap   regulator: add de...
551
552
  		rdata->id = i;
  		rdata->initdata = of_get_regulator_init_data(
072e78b12   Javier Martinez Canillas   regulator: of: Ad...
553
554
  						&pdev->dev, reg_np,
  						&regulators[i]);
26aec009f   Amit Daniel Kachhap   regulator: add de...
555
556
557
558
559
560
  		rdata->reg_node = reg_np;
  		rdata++;
  		rmode->id = i;
  		if (of_property_read_u32(reg_np, "op_mode",
  				&rmode->mode)) {
  			dev_warn(iodev->dev,
f3c7f7b63   Christophe JAILLET   regulator: s5m876...
561
562
  				"no op_mode property at %pOF
  ",
7799167b7   Rob Herring   regulator: Conver...
563
  				reg_np);
26aec009f   Amit Daniel Kachhap   regulator: add de...
564
565
566
567
568
  
  			rmode->mode = S5M8767_OPMODE_NORMAL_MODE;
  		}
  		rmode++;
  	}
b7db01f3b   Sachin Kamat   regulator: s5m876...
569
  	of_node_put(regulators_np);
04f9f068a   Chanwoo Choi   regulator: s5m876...
570
  	if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) {
26aec009f   Amit Daniel Kachhap   regulator: add de...
571
  		pdata->buck2_gpiodvs = true;
04f9f068a   Chanwoo Choi   regulator: s5m876...
572
573
574
575
576
577
578
579
580
581
  		if (of_property_read_u32_array(pmic_np,
  				"s5m8767,pmic-buck2-dvs-voltage",
  				pdata->buck2_voltage, dvs_voltage_nr)) {
  			dev_err(iodev->dev, "buck2 voltages not specified
  ");
  			return -EINVAL;
  		}
  	}
  
  	if (of_get_property(pmic_np, "s5m8767,pmic-buck3-uses-gpio-dvs", NULL)) {
26aec009f   Amit Daniel Kachhap   regulator: add de...
582
  		pdata->buck3_gpiodvs = true;
04f9f068a   Chanwoo Choi   regulator: s5m876...
583
584
585
586
587
588
589
590
591
592
  		if (of_property_read_u32_array(pmic_np,
  				"s5m8767,pmic-buck3-dvs-voltage",
  				pdata->buck3_voltage, dvs_voltage_nr)) {
  			dev_err(iodev->dev, "buck3 voltages not specified
  ");
  			return -EINVAL;
  		}
  	}
  
  	if (of_get_property(pmic_np, "s5m8767,pmic-buck4-uses-gpio-dvs", NULL)) {
26aec009f   Amit Daniel Kachhap   regulator: add de...
593
  		pdata->buck4_gpiodvs = true;
04f9f068a   Chanwoo Choi   regulator: s5m876...
594
595
596
597
598
599
600
601
  		if (of_property_read_u32_array(pmic_np,
  				"s5m8767,pmic-buck4-dvs-voltage",
  				pdata->buck4_voltage, dvs_voltage_nr)) {
  			dev_err(iodev->dev, "buck4 voltages not specified
  ");
  			return -EINVAL;
  		}
  	}
26aec009f   Amit Daniel Kachhap   regulator: add de...
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
  	if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
  						pdata->buck4_gpiodvs) {
  		ret = s5m8767_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
  		if (ret)
  			return -EINVAL;
  
  		if (of_property_read_u32(pmic_np,
  				"s5m8767,pmic-buck-default-dvs-idx",
  				&pdata->buck_default_idx)) {
  			pdata->buck_default_idx = 0;
  		} else {
  			if (pdata->buck_default_idx >= 8) {
  				pdata->buck_default_idx = 0;
  				dev_info(iodev->dev,
  				"invalid value for default dvs index, use 0
  ");
  			}
  		}
26aec009f   Amit Daniel Kachhap   regulator: add de...
620
621
622
623
624
  	}
  
  	ret = s5m8767_pmic_dt_parse_ds_gpio(iodev, pdata, pmic_np);
  	if (ret)
  		return -EINVAL;
033054e86   Chanwoo Choi   regulator: s5m876...
625
626
  	if (of_get_property(pmic_np, "s5m8767,pmic-buck2-ramp-enable", NULL))
  		pdata->buck2_ramp_enable = true;
26aec009f   Amit Daniel Kachhap   regulator: add de...
627

033054e86   Chanwoo Choi   regulator: s5m876...
628
629
  	if (of_get_property(pmic_np, "s5m8767,pmic-buck3-ramp-enable", NULL))
  		pdata->buck3_ramp_enable = true;
26aec009f   Amit Daniel Kachhap   regulator: add de...
630

033054e86   Chanwoo Choi   regulator: s5m876...
631
632
633
634
635
636
637
638
  	if (of_get_property(pmic_np, "s5m8767,pmic-buck4-ramp-enable", NULL))
  		pdata->buck4_ramp_enable = true;
  
  	if (pdata->buck2_ramp_enable || pdata->buck3_ramp_enable
  			|| pdata->buck4_ramp_enable) {
  		if (of_property_read_u32(pmic_np, "s5m8767,pmic-buck-ramp-delay",
  				&pdata->buck_ramp_delay))
  			pdata->buck_ramp_delay = 0;
26aec009f   Amit Daniel Kachhap   regulator: add de...
639
640
641
642
643
  	}
  
  	return 0;
  }
  #else
cbb0ed495   Axel Lin   regulator: s5m876...
644
  static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
26aec009f   Amit Daniel Kachhap   regulator: add de...
645
646
647
648
649
  					struct sec_platform_data *pdata)
  {
  	return 0;
  }
  #endif /* CONFIG_OF */
a5023574d   Bill Pemberton   regulator: remove...
650
  static int s5m8767_pmic_probe(struct platform_device *pdev)
9767ec7fe   Sangbeom Kim   regulator: Add S5...
651
  {
63063bfbf   Sangbeom Kim   mfd: Modify samsu...
652
  	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
26aec009f   Amit Daniel Kachhap   regulator: add de...
653
  	struct sec_platform_data *pdata = iodev->pdata;
c172708d3   Mark Brown   regulator: core: ...
654
  	struct regulator_config config = { };
9767ec7fe   Sangbeom Kim   regulator: Add S5...
655
  	struct s5m8767_info *s5m8767;
0a3ade7ec   Sachin Kamat   regulator: s5m876...
656
  	int i, ret, buck_init;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
657

e81d7bc89   Axel Lin   regulator: s5m876...
658
659
660
661
662
  	if (!pdata) {
  		dev_err(pdev->dev.parent, "Platform data not supplied
  ");
  		return -ENODEV;
  	}
26aec009f   Amit Daniel Kachhap   regulator: add de...
663
  	if (iodev->dev->of_node) {
cbb0ed495   Axel Lin   regulator: s5m876...
664
  		ret = s5m8767_pmic_dt_parse_pdata(pdev, pdata);
26aec009f   Amit Daniel Kachhap   regulator: add de...
665
666
667
  		if (ret)
  			return ret;
  	}
6c4efe247   Axel Lin   regulator: s5m876...
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
  	if (pdata->buck2_gpiodvs) {
  		if (pdata->buck3_gpiodvs || pdata->buck4_gpiodvs) {
  			dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID
  ");
  			return -EINVAL;
  		}
  	}
  
  	if (pdata->buck3_gpiodvs) {
  		if (pdata->buck2_gpiodvs || pdata->buck4_gpiodvs) {
  			dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID
  ");
  			return -EINVAL;
  		}
  	}
  
  	if (pdata->buck4_gpiodvs) {
  		if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs) {
  			dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID
  ");
  			return -EINVAL;
  		}
  	}
9767ec7fe   Sangbeom Kim   regulator: Add S5...
691
692
693
694
  	s5m8767 = devm_kzalloc(&pdev->dev, sizeof(struct s5m8767_info),
  				GFP_KERNEL);
  	if (!s5m8767)
  		return -ENOMEM;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
695
696
  	s5m8767->dev = &pdev->dev;
  	s5m8767->iodev = iodev;
9bb096ff3   Amit Daniel Kachhap   regulator: s5m876...
697
  	s5m8767->num_regulators = pdata->num_regulators;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
698
  	platform_set_drvdata(pdev, s5m8767);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
699
700
701
702
703
704
705
706
  
  	s5m8767->buck_gpioindex = pdata->buck_default_idx;
  	s5m8767->buck2_gpiodvs = pdata->buck2_gpiodvs;
  	s5m8767->buck3_gpiodvs = pdata->buck3_gpiodvs;
  	s5m8767->buck4_gpiodvs = pdata->buck4_gpiodvs;
  	s5m8767->buck_gpios[0] = pdata->buck_gpios[0];
  	s5m8767->buck_gpios[1] = pdata->buck_gpios[1];
  	s5m8767->buck_gpios[2] = pdata->buck_gpios[2];
c848bc853   Sangbeom Kim   regulator: s5m876...
707
708
709
  	s5m8767->buck_ds[0] = pdata->buck_ds[0];
  	s5m8767->buck_ds[1] = pdata->buck_ds[1];
  	s5m8767->buck_ds[2] = pdata->buck_ds[2];
9767ec7fe   Sangbeom Kim   regulator: Add S5...
710
711
712
713
  	s5m8767->ramp_delay = pdata->buck_ramp_delay;
  	s5m8767->buck2_ramp = pdata->buck2_ramp_enable;
  	s5m8767->buck3_ramp = pdata->buck3_ramp_enable;
  	s5m8767->buck4_ramp = pdata->buck4_ramp_enable;
7e44bb83a   Sangbeom Kim   regulator: Add su...
714
  	s5m8767->opmode = pdata->opmode;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
715

c848bc853   Sangbeom Kim   regulator: s5m876...
716
  	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
854f73ecb   Axel Lin   regulator: s5m876...
717
  						   pdata->buck2_init);
c848bc853   Sangbeom Kim   regulator: s5m876...
718

d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
719
720
  	regmap_write(s5m8767->iodev->regmap_pmic, S5M8767_REG_BUCK2DVS2,
  			buck_init);
c848bc853   Sangbeom Kim   regulator: s5m876...
721
722
  
  	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
854f73ecb   Axel Lin   regulator: s5m876...
723
  						   pdata->buck3_init);
c848bc853   Sangbeom Kim   regulator: s5m876...
724

d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
725
726
  	regmap_write(s5m8767->iodev->regmap_pmic, S5M8767_REG_BUCK3DVS2,
  			buck_init);
c848bc853   Sangbeom Kim   regulator: s5m876...
727
728
  
  	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
854f73ecb   Axel Lin   regulator: s5m876...
729
  						   pdata->buck4_init);
c848bc853   Sangbeom Kim   regulator: s5m876...
730

d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
731
732
  	regmap_write(s5m8767->iodev->regmap_pmic, S5M8767_REG_BUCK4DVS2,
  			buck_init);
c848bc853   Sangbeom Kim   regulator: s5m876...
733

9767ec7fe   Sangbeom Kim   regulator: Add S5...
734
735
736
  	for (i = 0; i < 8; i++) {
  		if (s5m8767->buck2_gpiodvs) {
  			s5m8767->buck2_vol[i] =
5b5e977ce   Axel Lin   regulator: Rename...
737
  				s5m8767_convert_voltage_to_sel(
9767ec7fe   Sangbeom Kim   regulator: Add S5...
738
  						&buck_voltage_val2,
854f73ecb   Axel Lin   regulator: s5m876...
739
  						pdata->buck2_voltage[i]);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
740
741
742
743
  		}
  
  		if (s5m8767->buck3_gpiodvs) {
  			s5m8767->buck3_vol[i] =
5b5e977ce   Axel Lin   regulator: Rename...
744
  				s5m8767_convert_voltage_to_sel(
9767ec7fe   Sangbeom Kim   regulator: Add S5...
745
  						&buck_voltage_val2,
854f73ecb   Axel Lin   regulator: s5m876...
746
  						pdata->buck3_voltage[i]);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
747
748
749
750
  		}
  
  		if (s5m8767->buck4_gpiodvs) {
  			s5m8767->buck4_vol[i] =
5b5e977ce   Axel Lin   regulator: Rename...
751
  				s5m8767_convert_voltage_to_sel(
9767ec7fe   Sangbeom Kim   regulator: Add S5...
752
  						&buck_voltage_val2,
854f73ecb   Axel Lin   regulator: s5m876...
753
  						pdata->buck4_voltage[i]);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
754
755
  		}
  	}
76c854d1d   Amit Daniel Kachhap   regulator: s5m876...
756
757
758
759
760
761
762
763
764
765
  	if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
  						pdata->buck4_gpiodvs) {
  
  		if (!gpio_is_valid(pdata->buck_gpios[0]) ||
  			!gpio_is_valid(pdata->buck_gpios[1]) ||
  			!gpio_is_valid(pdata->buck_gpios[2])) {
  			dev_err(&pdev->dev, "GPIO NOT VALID
  ");
  			return -EINVAL;
  		}
5febb3c9d   Axel Lin   regulator: s5m876...
766
767
768
769
770
771
772
773
774
775
776
777
778
779
  		ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[0],
  					"S5M8767 SET1");
  		if (ret)
  			return ret;
  
  		ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[1],
  					"S5M8767 SET2");
  		if (ret)
  			return ret;
  
  		ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[2],
  					"S5M8767 SET3");
  		if (ret)
  			return ret;
c848bc853   Sangbeom Kim   regulator: s5m876...
780
781
782
783
784
785
786
787
788
  		/* SET1 GPIO */
  		gpio_direction_output(pdata->buck_gpios[0],
  				(s5m8767->buck_gpioindex >> 2) & 0x1);
  		/* SET2 GPIO */
  		gpio_direction_output(pdata->buck_gpios[1],
  				(s5m8767->buck_gpioindex >> 1) & 0x1);
  		/* SET3 GPIO */
  		gpio_direction_output(pdata->buck_gpios[2],
  				(s5m8767->buck_gpioindex >> 0) & 0x1);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
789
  	}
5febb3c9d   Axel Lin   regulator: s5m876...
790
791
792
  	ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[0], "S5M8767 DS2");
  	if (ret)
  		return ret;
c848bc853   Sangbeom Kim   regulator: s5m876...
793

5febb3c9d   Axel Lin   regulator: s5m876...
794
795
796
  	ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[1], "S5M8767 DS3");
  	if (ret)
  		return ret;
c848bc853   Sangbeom Kim   regulator: s5m876...
797

5febb3c9d   Axel Lin   regulator: s5m876...
798
799
800
  	ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[2], "S5M8767 DS4");
  	if (ret)
  		return ret;
c848bc853   Sangbeom Kim   regulator: s5m876...
801
802
803
804
805
806
807
808
809
810
  
  	/* DS2 GPIO */
  	gpio_direction_output(pdata->buck_ds[0], 0x0);
  	/* DS3 GPIO */
  	gpio_direction_output(pdata->buck_ds[1], 0x0);
  	/* DS4 GPIO */
  	gpio_direction_output(pdata->buck_ds[2], 0x0);
  
  	if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
  	   pdata->buck4_gpiodvs) {
d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
811
812
813
814
815
816
817
818
819
  		regmap_update_bits(s5m8767->iodev->regmap_pmic,
  				S5M8767_REG_BUCK2CTRL, 1 << 1,
  				(pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1));
  		regmap_update_bits(s5m8767->iodev->regmap_pmic,
  				S5M8767_REG_BUCK3CTRL, 1 << 1,
  				(pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1));
  		regmap_update_bits(s5m8767->iodev->regmap_pmic,
  				S5M8767_REG_BUCK4CTRL, 1 << 1,
  				(pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1));
c848bc853   Sangbeom Kim   regulator: s5m876...
820
  	}
9767ec7fe   Sangbeom Kim   regulator: Add S5...
821
822
823
824
  
  	/* Initialize GPIO DVS registers */
  	for (i = 0; i < 8; i++) {
  		if (s5m8767->buck2_gpiodvs) {
d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
825
826
827
  			regmap_write(s5m8767->iodev->regmap_pmic,
  					S5M8767_REG_BUCK2DVS1 + i,
  					s5m8767->buck2_vol[i]);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
828
829
830
  		}
  
  		if (s5m8767->buck3_gpiodvs) {
d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
831
832
833
  			regmap_write(s5m8767->iodev->regmap_pmic,
  					S5M8767_REG_BUCK3DVS1 + i,
  					s5m8767->buck3_vol[i]);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
834
835
836
  		}
  
  		if (s5m8767->buck4_gpiodvs) {
d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
837
838
839
  			regmap_write(s5m8767->iodev->regmap_pmic,
  					S5M8767_REG_BUCK4DVS1 + i,
  					s5m8767->buck4_vol[i]);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
840
841
  		}
  	}
9767ec7fe   Sangbeom Kim   regulator: Add S5...
842
843
  
  	if (s5m8767->buck2_ramp)
d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
844
845
  		regmap_update_bits(s5m8767->iodev->regmap_pmic,
  				S5M8767_REG_DVSRAMP, 0x08, 0x08);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
846
847
  
  	if (s5m8767->buck3_ramp)
d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
848
849
  		regmap_update_bits(s5m8767->iodev->regmap_pmic,
  				S5M8767_REG_DVSRAMP, 0x04, 0x04);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
850
851
  
  	if (s5m8767->buck4_ramp)
d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
852
853
  		regmap_update_bits(s5m8767->iodev->regmap_pmic,
  				S5M8767_REG_DVSRAMP, 0x02, 0x02);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
854
855
856
  
  	if (s5m8767->buck2_ramp || s5m8767->buck3_ramp
  		|| s5m8767->buck4_ramp) {
f37ff6b6a   Krzysztof Kozlowski   regulator: s5m876...
857
  		unsigned int val;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
858
  		switch (s5m8767->ramp_delay) {
1af142c6f   Sangbeom Kim   regulator: Modify...
859
  		case 5:
f37ff6b6a   Krzysztof Kozlowski   regulator: s5m876...
860
  			val = S5M8767_DVS_BUCK_RAMP_5;
1af142c6f   Sangbeom Kim   regulator: Modify...
861
862
  			break;
  		case 10:
f37ff6b6a   Krzysztof Kozlowski   regulator: s5m876...
863
  			val = S5M8767_DVS_BUCK_RAMP_10;
047ec220a   Axel Lin   regulator: s5m876...
864
  			break;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
865
  		case 25:
f37ff6b6a   Krzysztof Kozlowski   regulator: s5m876...
866
  			val = S5M8767_DVS_BUCK_RAMP_25;
047ec220a   Axel Lin   regulator: s5m876...
867
  			break;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
868
  		case 50:
f37ff6b6a   Krzysztof Kozlowski   regulator: s5m876...
869
  			val = S5M8767_DVS_BUCK_RAMP_50;
047ec220a   Axel Lin   regulator: s5m876...
870
  			break;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
871
  		case 100:
f37ff6b6a   Krzysztof Kozlowski   regulator: s5m876...
872
  			val = S5M8767_DVS_BUCK_RAMP_100;
047ec220a   Axel Lin   regulator: s5m876...
873
  			break;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
874
  		default:
f37ff6b6a   Krzysztof Kozlowski   regulator: s5m876...
875
  			val = S5M8767_DVS_BUCK_RAMP_10;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
876
  		}
d13733f4a   Krzysztof Kozlowski   regulator: s5m876...
877
878
879
880
  		regmap_update_bits(s5m8767->iodev->regmap_pmic,
  					S5M8767_REG_DVSRAMP,
  					S5M8767_DVS_BUCK_RAMP_MASK,
  					val << S5M8767_DVS_BUCK_RAMP_SHIFT);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
881
882
883
  	}
  
  	for (i = 0; i < pdata->num_regulators; i++) {
63063bfbf   Sangbeom Kim   mfd: Modify samsu...
884
  		const struct sec_voltage_desc *desc;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
885
  		int id = pdata->regulators[i].id;
9c4c60554   Axel Lin   regulator: s5m876...
886
  		int enable_reg, enable_val;
e80fb721c   Krzysztof Kozlowski   regulator: s5m876...
887
  		struct regulator_dev *rdev;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
888
889
  
  		desc = reg_voltage_map[id];
e2eb169b1   Axel Lin   regulator: s5m876...
890
  		if (desc) {
9767ec7fe   Sangbeom Kim   regulator: Add S5...
891
892
  			regulators[id].n_voltages =
  				(desc->max - desc->min) / desc->step + 1;
e2eb169b1   Axel Lin   regulator: s5m876...
893
894
  			regulators[id].min_uV = desc->min;
  			regulators[id].uV_step = desc->step;
31a932e10   Axel Lin   regulator: s5m876...
895
896
897
898
899
900
  			regulators[id].vsel_reg =
  				s5m8767_get_vsel_reg(id, s5m8767);
  			if (id < S5M8767_BUCK1)
  				regulators[id].vsel_mask = 0x3f;
  			else
  				regulators[id].vsel_mask = 0xff;
9c4c60554   Axel Lin   regulator: s5m876...
901

e07ff9434   Arnd Bergmann   regulator: s5m876...
902
  			ret = s5m8767_get_register(s5m8767, id, &enable_reg,
9c4c60554   Axel Lin   regulator: s5m876...
903
  					     &enable_val);
e07ff9434   Arnd Bergmann   regulator: s5m876...
904
905
906
907
908
  			if (ret) {
  				dev_err(s5m8767->dev, "error reading registers
  ");
  				return ret;
  			}
9c4c60554   Axel Lin   regulator: s5m876...
909
910
911
  			regulators[id].enable_reg = enable_reg;
  			regulators[id].enable_mask = S5M8767_ENCTRL_MASK;
  			regulators[id].enable_val = enable_val;
e2eb169b1   Axel Lin   regulator: s5m876...
912
  		}
9767ec7fe   Sangbeom Kim   regulator: Add S5...
913

c172708d3   Mark Brown   regulator: core: ...
914
915
916
  		config.dev = s5m8767->dev;
  		config.init_data = pdata->regulators[i].initdata;
  		config.driver_data = s5m8767;
3e1e4a5f3   Krzysztof Kozlowski   mfd/rtc: s5m: fix...
917
  		config.regmap = iodev->regmap_pmic;
26aec009f   Amit Daniel Kachhap   regulator: add de...
918
  		config.of_node = pdata->regulators[i].reg_node;
9ae5cc75c   Linus Walleij   regulator: s5m876...
919
  		config.ena_gpiod = NULL;
1f5163fcf   Linus Walleij   regulator: s5m876...
920
921
  		if (pdata->regulators[i].ext_control_gpiod) {
  			/* Assigns config.ena_gpiod */
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
922
923
  			s5m8767_regulator_config_ext_control(s5m8767,
  					&pdata->regulators[i], &config);
c172708d3   Mark Brown   regulator: core: ...
924

1f5163fcf   Linus Walleij   regulator: s5m876...
925
926
927
928
929
930
  			/*
  			 * Hand the GPIO descriptor management over to the
  			 * regulator core, remove it from devres management.
  			 */
  			devm_gpiod_unhinge(s5m8767->dev, config.ena_gpiod);
  		}
e80fb721c   Krzysztof Kozlowski   regulator: s5m876...
931
  		rdev = devm_regulator_register(&pdev->dev, &regulators[id],
f0db475de   Mark Brown   regulator: s5m876...
932
  						  &config);
e80fb721c   Krzysztof Kozlowski   regulator: s5m876...
933
934
  		if (IS_ERR(rdev)) {
  			ret = PTR_ERR(rdev);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
935
936
937
  			dev_err(s5m8767->dev, "regulator init failed for %d
  ",
  					id);
f0db475de   Mark Brown   regulator: s5m876...
938
  			return ret;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
939
  		}
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
940

9ae5cc75c   Linus Walleij   regulator: s5m876...
941
  		if (pdata->regulators[i].ext_control_gpiod) {
e80fb721c   Krzysztof Kozlowski   regulator: s5m876...
942
  			ret = s5m8767_enable_ext_control(s5m8767, rdev);
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
943
944
945
946
  			if (ret < 0) {
  				dev_err(s5m8767->dev,
  						"failed to enable gpio control over %s: %d
  ",
e80fb721c   Krzysztof Kozlowski   regulator: s5m876...
947
  						rdev->desc->name, ret);
ee1e0994a   Krzysztof Kozlowski   regulator: s5m876...
948
949
950
  				return ret;
  			}
  		}
9767ec7fe   Sangbeom Kim   regulator: Add S5...
951
952
953
  	}
  
  	return 0;
9767ec7fe   Sangbeom Kim   regulator: Add S5...
954
955
956
957
958
959
960
961
962
963
964
  }
  
  static const struct platform_device_id s5m8767_pmic_id[] = {
  	{ "s5m8767-pmic", 0},
  	{ },
  };
  MODULE_DEVICE_TABLE(platform, s5m8767_pmic_id);
  
  static struct platform_driver s5m8767_pmic_driver = {
  	.driver = {
  		.name = "s5m8767-pmic",
9767ec7fe   Sangbeom Kim   regulator: Add S5...
965
966
  	},
  	.probe = s5m8767_pmic_probe,
9767ec7fe   Sangbeom Kim   regulator: Add S5...
967
968
  	.id_table = s5m8767_pmic_id,
  };
8d23b0b8f   Krzysztof Kozlowski   regulator: s5m876...
969
  module_platform_driver(s5m8767_pmic_driver);
9767ec7fe   Sangbeom Kim   regulator: Add S5...
970
971
972
  
  /* Module information */
  MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
fc2b10d13   Krzysztof Kozlowski   regulator: samsun...
973
  MODULE_DESCRIPTION("Samsung S5M8767 Regulator Driver");
9767ec7fe   Sangbeom Kim   regulator: Add S5...
974
  MODULE_LICENSE("GPL");