xref: /linux/drivers/regulator/s2mpa01.c (revision 06ed6aa56ffac9241e03a24649e8d048f8f1b10c)
1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // Copyright (c) 2013 Samsung Electronics Co., Ltd
4 //		http://www.samsung.com
5 
6 #include <linux/bug.h>
7 #include <linux/err.h>
8 #include <linux/gpio.h>
9 #include <linux/slab.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/regmap.h>
13 #include <linux/platform_device.h>
14 #include <linux/regulator/driver.h>
15 #include <linux/regulator/machine.h>
16 #include <linux/regulator/of_regulator.h>
17 #include <linux/mfd/samsung/core.h>
18 #include <linux/mfd/samsung/s2mpa01.h>
19 
20 struct s2mpa01_info {
21 	int ramp_delay24;
22 	int ramp_delay3;
23 	int ramp_delay5;
24 	int ramp_delay16;
25 	int ramp_delay7;
26 	int ramp_delay8910;
27 };
28 
29 static int get_ramp_delay(int ramp_delay)
30 {
31 	unsigned char cnt = 0;
32 
33 	ramp_delay /= 6250;
34 
35 	while (true) {
36 		ramp_delay = ramp_delay >> 1;
37 		if (ramp_delay == 0)
38 			break;
39 		cnt++;
40 	}
41 
42 	if (cnt > 3)
43 		cnt = 3;
44 
45 	return cnt;
46 }
47 
48 static int s2mpa01_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
49 				   unsigned int old_selector,
50 				   unsigned int new_selector)
51 {
52 	struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev);
53 	unsigned int ramp_delay = 0;
54 	int old_volt, new_volt;
55 
56 	switch (rdev_get_id(rdev)) {
57 	case S2MPA01_BUCK2:
58 	case S2MPA01_BUCK4:
59 		ramp_delay = s2mpa01->ramp_delay24;
60 		break;
61 	case S2MPA01_BUCK3:
62 		ramp_delay = s2mpa01->ramp_delay3;
63 		break;
64 	case S2MPA01_BUCK5:
65 		ramp_delay = s2mpa01->ramp_delay5;
66 		break;
67 	case S2MPA01_BUCK1:
68 	case S2MPA01_BUCK6:
69 		ramp_delay = s2mpa01->ramp_delay16;
70 		break;
71 	case S2MPA01_BUCK7:
72 		ramp_delay = s2mpa01->ramp_delay7;
73 		break;
74 	case S2MPA01_BUCK8:
75 	case S2MPA01_BUCK9:
76 	case S2MPA01_BUCK10:
77 		ramp_delay = s2mpa01->ramp_delay8910;
78 		break;
79 	}
80 
81 	if (ramp_delay == 0)
82 		ramp_delay = rdev->desc->ramp_delay;
83 
84 	old_volt = rdev->desc->min_uV + (rdev->desc->uV_step * old_selector);
85 	new_volt = rdev->desc->min_uV + (rdev->desc->uV_step * new_selector);
86 
87 	return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
88 }
89 
90 static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
91 {
92 	struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev);
93 	unsigned int ramp_val, ramp_shift, ramp_reg = S2MPA01_REG_RAMP2;
94 	unsigned int ramp_enable = 1, enable_shift = 0;
95 	int ret;
96 
97 	switch (rdev_get_id(rdev)) {
98 	case S2MPA01_BUCK1:
99 		enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT;
100 		if (!ramp_delay) {
101 			ramp_enable = 0;
102 			break;
103 		}
104 
105 		if (ramp_delay > s2mpa01->ramp_delay16)
106 			s2mpa01->ramp_delay16 = ramp_delay;
107 		else
108 			ramp_delay = s2mpa01->ramp_delay16;
109 
110 		ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT;
111 		break;
112 	case S2MPA01_BUCK2:
113 		enable_shift = S2MPA01_BUCK2_RAMP_EN_SHIFT;
114 		if (!ramp_delay) {
115 			ramp_enable = 0;
116 			break;
117 		}
118 
119 		if (ramp_delay > s2mpa01->ramp_delay24)
120 			s2mpa01->ramp_delay24 = ramp_delay;
121 		else
122 			ramp_delay = s2mpa01->ramp_delay24;
123 
124 		ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT;
125 		ramp_reg = S2MPA01_REG_RAMP1;
126 		break;
127 	case S2MPA01_BUCK3:
128 		enable_shift = S2MPA01_BUCK3_RAMP_EN_SHIFT;
129 		if (!ramp_delay) {
130 			ramp_enable = 0;
131 			break;
132 		}
133 
134 		s2mpa01->ramp_delay3 = ramp_delay;
135 		ramp_shift = S2MPA01_BUCK3_RAMP_SHIFT;
136 		ramp_reg = S2MPA01_REG_RAMP1;
137 		break;
138 	case S2MPA01_BUCK4:
139 		enable_shift = S2MPA01_BUCK4_RAMP_EN_SHIFT;
140 		if (!ramp_delay) {
141 			ramp_enable = 0;
142 			break;
143 		}
144 
145 		if (ramp_delay > s2mpa01->ramp_delay24)
146 			s2mpa01->ramp_delay24 = ramp_delay;
147 		else
148 			ramp_delay = s2mpa01->ramp_delay24;
149 
150 		ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT;
151 		ramp_reg = S2MPA01_REG_RAMP1;
152 		break;
153 	case S2MPA01_BUCK5:
154 		s2mpa01->ramp_delay5 = ramp_delay;
155 		ramp_shift = S2MPA01_BUCK5_RAMP_SHIFT;
156 		break;
157 	case S2MPA01_BUCK6:
158 		if (ramp_delay > s2mpa01->ramp_delay16)
159 			s2mpa01->ramp_delay16 = ramp_delay;
160 		else
161 			ramp_delay = s2mpa01->ramp_delay16;
162 
163 		ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT;
164 		break;
165 	case S2MPA01_BUCK7:
166 		s2mpa01->ramp_delay7 = ramp_delay;
167 		ramp_shift = S2MPA01_BUCK7_RAMP_SHIFT;
168 		break;
169 	case S2MPA01_BUCK8:
170 	case S2MPA01_BUCK9:
171 	case S2MPA01_BUCK10:
172 		if (ramp_delay > s2mpa01->ramp_delay8910)
173 			s2mpa01->ramp_delay8910 = ramp_delay;
174 		else
175 			ramp_delay = s2mpa01->ramp_delay8910;
176 
177 		ramp_shift = S2MPA01_BUCK8910_RAMP_SHIFT;
178 		break;
179 	default:
180 		return 0;
181 	}
182 
183 	if (!ramp_enable)
184 		goto ramp_disable;
185 
186 	/* Ramp delay can be enabled/disabled only for buck[1234] */
187 	if (rdev_get_id(rdev) >= S2MPA01_BUCK1 &&
188 			rdev_get_id(rdev) <= S2MPA01_BUCK4) {
189 		ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1,
190 					 1 << enable_shift, 1 << enable_shift);
191 		if (ret) {
192 			dev_err(&rdev->dev, "failed to enable ramp rate\n");
193 			return ret;
194 		}
195 	}
196 
197 	ramp_val = get_ramp_delay(ramp_delay);
198 
199 	return regmap_update_bits(rdev->regmap, ramp_reg, 0x3 << ramp_shift,
200 				  ramp_val << ramp_shift);
201 
202 ramp_disable:
203 	return regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1,
204 				  1 << enable_shift, 0);
205 }
206 
207 static const struct regulator_ops s2mpa01_ldo_ops = {
208 	.list_voltage		= regulator_list_voltage_linear,
209 	.map_voltage		= regulator_map_voltage_linear,
210 	.is_enabled		= regulator_is_enabled_regmap,
211 	.enable			= regulator_enable_regmap,
212 	.disable		= regulator_disable_regmap,
213 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
214 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
215 	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
216 };
217 
218 static const struct regulator_ops s2mpa01_buck_ops = {
219 	.list_voltage		= regulator_list_voltage_linear,
220 	.map_voltage		= regulator_map_voltage_linear,
221 	.is_enabled		= regulator_is_enabled_regmap,
222 	.enable			= regulator_enable_regmap,
223 	.disable		= regulator_disable_regmap,
224 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
225 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
226 	.set_voltage_time_sel	= s2mpa01_regulator_set_voltage_time_sel,
227 	.set_ramp_delay		= s2mpa01_set_ramp_delay,
228 };
229 
230 #define regulator_desc_ldo(num, step) {			\
231 	.name		= "LDO"#num,			\
232 	.of_match	= of_match_ptr("LDO"#num),	\
233 	.regulators_node = of_match_ptr("regulators"),	\
234 	.id		= S2MPA01_LDO##num,		\
235 	.ops		= &s2mpa01_ldo_ops,		\
236 	.type		= REGULATOR_VOLTAGE,		\
237 	.owner		= THIS_MODULE,			\
238 	.min_uV		= MIN_800_MV,			\
239 	.uV_step	= step,				\
240 	.n_voltages	= S2MPA01_LDO_N_VOLTAGES,	\
241 	.vsel_reg	= S2MPA01_REG_L1CTRL + num - 1,	\
242 	.vsel_mask	= S2MPA01_LDO_VSEL_MASK,	\
243 	.enable_reg	= S2MPA01_REG_L1CTRL + num - 1,	\
244 	.enable_mask	= S2MPA01_ENABLE_MASK		\
245 }
246 
247 #define regulator_desc_buck1_4(num)	{			\
248 	.name		= "BUCK"#num,				\
249 	.of_match	= of_match_ptr("BUCK"#num),		\
250 	.regulators_node = of_match_ptr("regulators"),		\
251 	.id		= S2MPA01_BUCK##num,			\
252 	.ops		= &s2mpa01_buck_ops,			\
253 	.type		= REGULATOR_VOLTAGE,			\
254 	.owner		= THIS_MODULE,				\
255 	.min_uV		= MIN_600_MV,				\
256 	.uV_step	= STEP_6_25_MV,				\
257 	.n_voltages	= S2MPA01_BUCK_N_VOLTAGES,		\
258 	.ramp_delay	= S2MPA01_RAMP_DELAY,			\
259 	.vsel_reg	= S2MPA01_REG_B1CTRL2 + (num - 1) * 2,	\
260 	.vsel_mask	= S2MPA01_BUCK_VSEL_MASK,		\
261 	.enable_reg	= S2MPA01_REG_B1CTRL1 + (num - 1) * 2,	\
262 	.enable_mask	= S2MPA01_ENABLE_MASK			\
263 }
264 
265 #define regulator_desc_buck5	{				\
266 	.name		= "BUCK5",				\
267 	.of_match	= of_match_ptr("BUCK5"),		\
268 	.regulators_node = of_match_ptr("regulators"),		\
269 	.id		= S2MPA01_BUCK5,			\
270 	.ops		= &s2mpa01_buck_ops,			\
271 	.type		= REGULATOR_VOLTAGE,			\
272 	.owner		= THIS_MODULE,				\
273 	.min_uV		= MIN_800_MV,				\
274 	.uV_step	= STEP_6_25_MV,				\
275 	.n_voltages	= S2MPA01_BUCK_N_VOLTAGES,		\
276 	.ramp_delay	= S2MPA01_RAMP_DELAY,			\
277 	.vsel_reg	= S2MPA01_REG_B5CTRL2,			\
278 	.vsel_mask	= S2MPA01_BUCK_VSEL_MASK,		\
279 	.enable_reg	= S2MPA01_REG_B5CTRL1,			\
280 	.enable_mask	= S2MPA01_ENABLE_MASK			\
281 }
282 
283 #define regulator_desc_buck6_10(num, min, step) {			\
284 	.name		= "BUCK"#num,				\
285 	.of_match	= of_match_ptr("BUCK"#num),		\
286 	.regulators_node = of_match_ptr("regulators"),		\
287 	.id		= S2MPA01_BUCK##num,			\
288 	.ops		= &s2mpa01_buck_ops,			\
289 	.type		= REGULATOR_VOLTAGE,			\
290 	.owner		= THIS_MODULE,				\
291 	.min_uV		= min,					\
292 	.uV_step	= step,					\
293 	.n_voltages	= S2MPA01_BUCK_N_VOLTAGES,		\
294 	.ramp_delay	= S2MPA01_RAMP_DELAY,			\
295 	.vsel_reg	= S2MPA01_REG_B6CTRL2 + (num - 6) * 2,	\
296 	.vsel_mask	= S2MPA01_BUCK_VSEL_MASK,		\
297 	.enable_reg	= S2MPA01_REG_B6CTRL1 + (num - 6) * 2,	\
298 	.enable_mask	= S2MPA01_ENABLE_MASK			\
299 }
300 
301 static const struct regulator_desc regulators[] = {
302 	regulator_desc_ldo(1, STEP_25_MV),
303 	regulator_desc_ldo(2, STEP_50_MV),
304 	regulator_desc_ldo(3, STEP_50_MV),
305 	regulator_desc_ldo(4, STEP_50_MV),
306 	regulator_desc_ldo(5, STEP_25_MV),
307 	regulator_desc_ldo(6, STEP_25_MV),
308 	regulator_desc_ldo(7, STEP_50_MV),
309 	regulator_desc_ldo(8, STEP_50_MV),
310 	regulator_desc_ldo(9, STEP_50_MV),
311 	regulator_desc_ldo(10, STEP_50_MV),
312 	regulator_desc_ldo(11, STEP_50_MV),
313 	regulator_desc_ldo(12, STEP_50_MV),
314 	regulator_desc_ldo(13, STEP_50_MV),
315 	regulator_desc_ldo(14, STEP_50_MV),
316 	regulator_desc_ldo(15, STEP_50_MV),
317 	regulator_desc_ldo(16, STEP_50_MV),
318 	regulator_desc_ldo(17, STEP_50_MV),
319 	regulator_desc_ldo(18, STEP_50_MV),
320 	regulator_desc_ldo(19, STEP_50_MV),
321 	regulator_desc_ldo(20, STEP_50_MV),
322 	regulator_desc_ldo(21, STEP_50_MV),
323 	regulator_desc_ldo(22, STEP_50_MV),
324 	regulator_desc_ldo(23, STEP_50_MV),
325 	regulator_desc_ldo(24, STEP_50_MV),
326 	regulator_desc_ldo(25, STEP_50_MV),
327 	regulator_desc_ldo(26, STEP_25_MV),
328 	regulator_desc_buck1_4(1),
329 	regulator_desc_buck1_4(2),
330 	regulator_desc_buck1_4(3),
331 	regulator_desc_buck1_4(4),
332 	regulator_desc_buck5,
333 	regulator_desc_buck6_10(6, MIN_600_MV, STEP_6_25_MV),
334 	regulator_desc_buck6_10(7, MIN_600_MV, STEP_6_25_MV),
335 	regulator_desc_buck6_10(8, MIN_800_MV, STEP_12_5_MV),
336 	regulator_desc_buck6_10(9, MIN_1500_MV, STEP_12_5_MV),
337 	regulator_desc_buck6_10(10, MIN_1000_MV, STEP_12_5_MV),
338 };
339 
340 static int s2mpa01_pmic_probe(struct platform_device *pdev)
341 {
342 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
343 	struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
344 	struct regulator_config config = { };
345 	struct s2mpa01_info *s2mpa01;
346 	int i;
347 
348 	s2mpa01 = devm_kzalloc(&pdev->dev, sizeof(*s2mpa01), GFP_KERNEL);
349 	if (!s2mpa01)
350 		return -ENOMEM;
351 
352 	config.dev = iodev->dev;
353 	config.regmap = iodev->regmap_pmic;
354 	config.driver_data = s2mpa01;
355 
356 	for (i = 0; i < S2MPA01_REGULATOR_MAX; i++) {
357 		struct regulator_dev *rdev;
358 
359 		if (pdata)
360 			config.init_data = pdata->regulators[i].initdata;
361 
362 		rdev = devm_regulator_register(&pdev->dev,
363 						&regulators[i], &config);
364 		if (IS_ERR(rdev)) {
365 			dev_err(&pdev->dev, "regulator init failed for %d\n",
366 				i);
367 			return PTR_ERR(rdev);
368 		}
369 	}
370 
371 	return 0;
372 }
373 
374 static const struct platform_device_id s2mpa01_pmic_id[] = {
375 	{ "s2mpa01-pmic", 0},
376 	{ },
377 };
378 MODULE_DEVICE_TABLE(platform, s2mpa01_pmic_id);
379 
380 static struct platform_driver s2mpa01_pmic_driver = {
381 	.driver = {
382 		.name = "s2mpa01-pmic",
383 	},
384 	.probe = s2mpa01_pmic_probe,
385 	.id_table = s2mpa01_pmic_id,
386 };
387 
388 module_platform_driver(s2mpa01_pmic_driver);
389 
390 /* Module information */
391 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
392 MODULE_AUTHOR("Sachin Kamat <sachin.kamat@samsung.com>");
393 MODULE_DESCRIPTION("Samsung S2MPA01 Regulator Driver");
394 MODULE_LICENSE("GPL");
395