xref: /openbmc/linux/drivers/regulator/88pm8607.c (revision d0b73b48)
1 /*
2  * Regulators driver for Marvell 88PM8607
3  *
4  * Copyright (C) 2009 Marvell International Ltd.
5  * 	Haojian Zhuang <haojian.zhuang@marvell.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/err.h>
14 #include <linux/i2c.h>
15 #include <linux/of.h>
16 #include <linux/regulator/of_regulator.h>
17 #include <linux/platform_device.h>
18 #include <linux/regulator/driver.h>
19 #include <linux/regulator/machine.h>
20 #include <linux/mfd/88pm860x.h>
21 #include <linux/module.h>
22 
23 struct pm8607_regulator_info {
24 	struct regulator_desc	desc;
25 	struct pm860x_chip	*chip;
26 	struct regulator_dev	*regulator;
27 	struct i2c_client	*i2c;
28 	struct i2c_client	*i2c_8606;
29 
30 	unsigned int	*vol_table;
31 	unsigned int	*vol_suspend;
32 
33 	int	update_reg;
34 	int	update_bit;
35 	int	slope_double;
36 };
37 
38 static const unsigned int BUCK1_table[] = {
39 	 725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000,
40 	 925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
41 	1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
42 	1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
43 	      0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
44 	 200000,  225000,  250000,  275000,  300000,  325000,  350000,  375000,
45 	 400000,  425000,  450000,  475000,  500000,  525000,  550000,  575000,
46 	 600000,  625000,  650000,  675000,  700000,  725000,  750000,  775000,
47 };
48 
49 static const unsigned int BUCK1_suspend_table[] = {
50 	      0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
51 	 200000,  225000,  250000,  275000,  300000,  325000,  350000,  375000,
52 	 400000,  425000,  450000,  475000,  500000,  525000,  550000,  575000,
53 	 600000,  625000,  650000,  675000,  700000,  725000,  750000,  775000,
54 	 800000,  825000,  850000,  875000,  900000,  925000,  950000,  975000,
55 	1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
56 	1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
57 	1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
58 };
59 
60 static const unsigned int BUCK2_table[] = {
61 	      0,   50000,  100000,  150000,  200000,  250000,  300000,  350000,
62 	 400000,  450000,  500000,  550000,  600000,  650000,  700000,  750000,
63 	 800000,  850000,  900000,  950000, 1000000, 1050000, 1100000, 1150000,
64 	1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
65 	1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000,
66 	2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000,
67 	2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000,
68 	2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000,
69 };
70 
71 static const unsigned int BUCK2_suspend_table[] = {
72 	      0,   50000,  100000,  150000,  200000,  250000,  300000,  350000,
73 	 400000,  450000,  500000,  550000,  600000,  650000,  700000,  750000,
74 	 800000,  850000,  900000,  950000, 1000000, 1050000, 1100000, 1150000,
75 	1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
76 	1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000,
77 	2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000,
78 	2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000,
79 	2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000,
80 };
81 
82 static const unsigned int BUCK3_table[] = {
83               0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
84 	 200000,  225000,  250000,  275000,  300000,  325000,  350000,  375000,
85 	 400000,  425000,  450000,  475000,  500000,  525000,  550000,  575000,
86 	 600000,  625000,  650000,  675000,  700000,  725000,  750000,  775000,
87 	 800000,  825000,  850000,  875000,  900000,  925000,  950000,  975000,
88 	1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
89 	1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
90 	1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
91 };
92 
93 static const unsigned int BUCK3_suspend_table[] = {
94               0,   25000,   50000,   75000,  100000,  125000,  150000,  175000,
95 	 200000,  225000,  250000,  275000,  300000,  325000,  350000,  375000,
96 	 400000,  425000,  450000,  475000,  500000,  525000,  550000,  575000,
97 	 600000,  625000,  650000,  675000,  700000,  725000,  750000,  775000,
98 	 800000,  825000,  850000,  875000,  900000,  925000,  950000,  975000,
99 	1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
100 	1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
101 	1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
102 };
103 
104 static const unsigned int LDO1_table[] = {
105 	1800000, 1200000, 2800000, 0,
106 };
107 
108 static const unsigned int LDO1_suspend_table[] = {
109 	1800000, 1200000, 0, 0,
110 };
111 
112 static const unsigned int LDO2_table[] = {
113 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
114 };
115 
116 static const unsigned int LDO2_suspend_table[] = {
117 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
118 };
119 
120 static const unsigned int LDO3_table[] = {
121 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
122 };
123 
124 static const unsigned int LDO3_suspend_table[] = {
125 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
126 };
127 
128 static const unsigned int LDO4_table[] = {
129 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 3300000,
130 };
131 
132 static const unsigned int LDO4_suspend_table[] = {
133 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 2900000,
134 };
135 
136 static const unsigned int LDO5_table[] = {
137 	2900000, 3000000, 3100000, 3300000,
138 };
139 
140 static const unsigned int LDO5_suspend_table[] = {
141 	2900000, 0, 0, 0,
142 };
143 
144 static const unsigned int LDO6_table[] = {
145 	1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 3300000,
146 };
147 
148 static const unsigned int LDO6_suspend_table[] = {
149 	1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 2900000,
150 };
151 
152 static const unsigned int LDO7_table[] = {
153 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
154 };
155 
156 static const unsigned int LDO7_suspend_table[] = {
157 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
158 };
159 
160 static const unsigned int LDO8_table[] = {
161 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
162 };
163 
164 static const unsigned int LDO8_suspend_table[] = {
165 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
166 };
167 
168 static const unsigned int LDO9_table[] = {
169 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
170 };
171 
172 static const unsigned int LDO9_suspend_table[] = {
173 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
174 };
175 
176 static const unsigned int LDO10_table[] = {
177 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
178 	1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
179 };
180 
181 static const unsigned int LDO10_suspend_table[] = {
182 	1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
183 	1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
184 };
185 
186 static const unsigned int LDO12_table[] = {
187 	1800000, 1900000, 2700000, 2800000, 2900000, 3000000, 3100000, 3300000,
188 	1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
189 };
190 
191 static const unsigned int LDO12_suspend_table[] = {
192 	1800000, 1900000, 2700000, 2800000, 2900000, 2900000, 2900000, 2900000,
193 	1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
194 };
195 
196 static const unsigned int LDO13_table[] = {
197 	1200000, 1300000, 1800000, 2000000, 2500000, 2800000, 3000000, 0,
198 };
199 
200 static const unsigned int LDO13_suspend_table[] = {
201 	0,
202 };
203 
204 static const unsigned int LDO14_table[] = {
205 	1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 3300000,
206 };
207 
208 static const unsigned int LDO14_suspend_table[] = {
209 	1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 2900000,
210 };
211 
212 static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
213 {
214 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
215 	int ret = -EINVAL;
216 
217 	if (info->vol_table && (index < rdev->desc->n_voltages)) {
218 		ret = info->vol_table[index];
219 		if (info->slope_double)
220 			ret <<= 1;
221 	}
222 	return ret;
223 }
224 
225 static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
226 {
227 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
228 	uint8_t val;
229 	int ret;
230 
231 	val = (uint8_t)(selector << (ffs(rdev->desc->vsel_mask) - 1));
232 
233 	ret = pm860x_set_bits(info->i2c, rdev->desc->vsel_reg,
234 			      rdev->desc->vsel_mask, val);
235 	if (ret)
236 		return ret;
237 	switch (info->desc.id) {
238 	case PM8607_ID_BUCK1:
239 	case PM8607_ID_BUCK3:
240 		ret = pm860x_set_bits(info->i2c, info->update_reg,
241 				      1 << info->update_bit,
242 				      1 << info->update_bit);
243 		break;
244 	}
245 	return ret;
246 }
247 
248 static int pm8606_preg_enable(struct regulator_dev *rdev)
249 {
250 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
251 
252 	return pm860x_set_bits(info->i2c, rdev->desc->enable_reg,
253 			       1 << rdev->desc->enable_mask, 0);
254 }
255 
256 static int pm8606_preg_disable(struct regulator_dev *rdev)
257 {
258 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
259 
260 	return pm860x_set_bits(info->i2c, rdev->desc->enable_reg,
261 			       1 << rdev->desc->enable_mask,
262 			       1 << rdev->desc->enable_mask);
263 }
264 
265 static int pm8606_preg_is_enabled(struct regulator_dev *rdev)
266 {
267 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
268 	int ret;
269 
270 	ret = pm860x_reg_read(info->i2c, rdev->desc->enable_reg);
271 	if (ret < 0)
272 		return ret;
273 
274 	return !((unsigned char)ret & (1 << rdev->desc->enable_mask));
275 }
276 
277 static struct regulator_ops pm8607_regulator_ops = {
278 	.list_voltage	= pm8607_list_voltage,
279 	.set_voltage_sel = pm8607_set_voltage_sel,
280 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
281 	.enable = regulator_enable_regmap,
282 	.disable = regulator_disable_regmap,
283 	.is_enabled = regulator_is_enabled_regmap,
284 };
285 
286 static struct regulator_ops pm8606_preg_ops = {
287 	.enable		= pm8606_preg_enable,
288 	.disable	= pm8606_preg_disable,
289 	.is_enabled	= pm8606_preg_is_enabled,
290 };
291 
292 #define PM8606_PREG(ereg, ebit)						\
293 {									\
294 	.desc	= {							\
295 		.name	= "PREG",					\
296 		.ops	= &pm8606_preg_ops,				\
297 		.type	= REGULATOR_CURRENT,				\
298 		.id	= PM8606_ID_PREG,				\
299 		.owner	= THIS_MODULE,					\
300 		.enable_reg = PM8606_##ereg,				\
301 		.enable_mask = (ebit),					\
302 	},								\
303 }
304 
305 #define PM8607_DVC(vreg, ureg, ubit, ereg, ebit)			\
306 {									\
307 	.desc	= {							\
308 		.name	= #vreg,					\
309 		.ops	= &pm8607_regulator_ops,			\
310 		.type	= REGULATOR_VOLTAGE,				\
311 		.id	= PM8607_ID_##vreg,				\
312 		.owner	= THIS_MODULE,					\
313 		.n_voltages = ARRAY_SIZE(vreg##_table),			\
314 		.vsel_reg = PM8607_##vreg,				\
315 		.vsel_mask = ARRAY_SIZE(vreg##_table) - 1,		\
316 		.enable_reg = PM8607_##ereg,				\
317 		.enable_mask = 1 << (ebit),				\
318 	},								\
319 	.update_reg	= PM8607_##ureg,				\
320 	.update_bit	= (ubit),					\
321 	.slope_double	= (0),						\
322 	.vol_table	= (unsigned int *)&vreg##_table,		\
323 	.vol_suspend	= (unsigned int *)&vreg##_suspend_table,	\
324 }
325 
326 #define PM8607_LDO(_id, vreg, shift, ereg, ebit)			\
327 {									\
328 	.desc	= {							\
329 		.name	= "LDO" #_id,					\
330 		.ops	= &pm8607_regulator_ops,			\
331 		.type	= REGULATOR_VOLTAGE,				\
332 		.id	= PM8607_ID_LDO##_id,				\
333 		.owner	= THIS_MODULE,					\
334 		.n_voltages = ARRAY_SIZE(LDO##_id##_table),		\
335 		.vsel_reg = PM8607_##vreg,				\
336 		.vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \
337 		.enable_reg = PM8607_##ereg,				\
338 		.enable_mask = 1 << (ebit),				\
339 	},								\
340 	.slope_double	= (0),						\
341 	.vol_table	= (unsigned int *)&LDO##_id##_table,		\
342 	.vol_suspend	= (unsigned int *)&LDO##_id##_suspend_table,	\
343 }
344 
345 static struct pm8607_regulator_info pm8607_regulator_info[] = {
346 	PM8607_DVC(BUCK1, GO, 0, SUPPLIES_EN11, 0),
347 	PM8607_DVC(BUCK2, GO, 1, SUPPLIES_EN11, 1),
348 	PM8607_DVC(BUCK3, GO, 2, SUPPLIES_EN11, 2),
349 
350 	PM8607_LDO(1,         LDO1, 0, SUPPLIES_EN11, 3),
351 	PM8607_LDO(2,         LDO2, 0, SUPPLIES_EN11, 4),
352 	PM8607_LDO(3,         LDO3, 0, SUPPLIES_EN11, 5),
353 	PM8607_LDO(4,         LDO4, 0, SUPPLIES_EN11, 6),
354 	PM8607_LDO(5,         LDO5, 0, SUPPLIES_EN11, 7),
355 	PM8607_LDO(6,         LDO6, 0, SUPPLIES_EN12, 0),
356 	PM8607_LDO(7,         LDO7, 0, SUPPLIES_EN12, 1),
357 	PM8607_LDO(8,         LDO8, 0, SUPPLIES_EN12, 2),
358 	PM8607_LDO(9,         LDO9, 0, SUPPLIES_EN12, 3),
359 	PM8607_LDO(10,        LDO10, 0, SUPPLIES_EN12, 4),
360 	PM8607_LDO(12,        LDO12, 0, SUPPLIES_EN12, 5),
361 	PM8607_LDO(13, VIBRATOR_SET, 1, VIBRATOR_SET, 0),
362 	PM8607_LDO(14,        LDO14, 0, SUPPLIES_EN12, 6),
363 };
364 
365 static struct pm8607_regulator_info pm8606_regulator_info[] = {
366 	PM8606_PREG(PREREGULATORB, 5),
367 };
368 
369 #ifdef CONFIG_OF
370 static int pm8607_regulator_dt_init(struct platform_device *pdev,
371 				    struct pm8607_regulator_info *info,
372 				    struct regulator_config *config)
373 {
374 	struct device_node *nproot, *np;
375 	nproot = pdev->dev.parent->of_node;
376 	if (!nproot)
377 		return -ENODEV;
378 	nproot = of_find_node_by_name(nproot, "regulators");
379 	if (!nproot) {
380 		dev_err(&pdev->dev, "failed to find regulators node\n");
381 		return -ENODEV;
382 	}
383 	for_each_child_of_node(nproot, np) {
384 		if (!of_node_cmp(np->name, info->desc.name)) {
385 			config->init_data =
386 				of_get_regulator_init_data(&pdev->dev, np);
387 			config->of_node = np;
388 			break;
389 		}
390 	}
391 	return 0;
392 }
393 #else
394 #define pm8607_regulator_dt_init(x, y, z)	(-1)
395 #endif
396 
397 static int pm8607_regulator_probe(struct platform_device *pdev)
398 {
399 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
400 	struct pm8607_regulator_info *info = NULL;
401 	struct regulator_init_data *pdata = pdev->dev.platform_data;
402 	struct regulator_config config = { };
403 	struct resource *res;
404 	int i;
405 
406 	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
407 	if (res) {
408 		/* There're resources in 88PM8607 regulator driver */
409 		for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
410 			info = &pm8607_regulator_info[i];
411 			if (info->desc.vsel_reg == res->start)
412 				break;
413 		}
414 		if (i == ARRAY_SIZE(pm8607_regulator_info)) {
415 			dev_err(&pdev->dev, "Failed to find regulator %llu\n",
416 				(unsigned long long)res->start);
417 			return -EINVAL;
418 		}
419 	} else {
420 		/* There's no resource in 88PM8606 PREG regulator driver */
421 		info = &pm8606_regulator_info[0];
422 		/* i is used to check regulator ID */
423 		i = -1;
424 	}
425 	info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
426 	info->i2c_8606 = (chip->id == CHIP_PM8607) ? chip->companion :
427 			chip->client;
428 	info->chip = chip;
429 
430 	/* check DVC ramp slope double */
431 	if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double)
432 		info->slope_double = 1;
433 
434 	config.dev = &pdev->dev;
435 	config.driver_data = info;
436 
437 	if (pm8607_regulator_dt_init(pdev, info, &config))
438 		if (pdata)
439 			config.init_data = pdata;
440 
441 	if (chip->id == CHIP_PM8607)
442 		config.regmap = chip->regmap;
443 	else
444 		config.regmap = chip->regmap_companion;
445 
446 	info->regulator = regulator_register(&info->desc, &config);
447 	if (IS_ERR(info->regulator)) {
448 		dev_err(&pdev->dev, "failed to register regulator %s\n",
449 			info->desc.name);
450 		return PTR_ERR(info->regulator);
451 	}
452 
453 	platform_set_drvdata(pdev, info);
454 	return 0;
455 }
456 
457 static int pm8607_regulator_remove(struct platform_device *pdev)
458 {
459 	struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
460 
461 	platform_set_drvdata(pdev, NULL);
462 	regulator_unregister(info->regulator);
463 	return 0;
464 }
465 
466 static struct platform_device_id pm8607_regulator_driver_ids[] = {
467 	{
468 		.name	= "88pm860x-regulator",
469 		.driver_data	= 0,
470 	}, {
471 		.name	= "88pm860x-preg",
472 		.driver_data	= 0,
473 	},
474 	{ },
475 };
476 MODULE_DEVICE_TABLE(platform, pm8607_regulator_driver_ids);
477 
478 static struct platform_driver pm8607_regulator_driver = {
479 	.driver		= {
480 		.name	= "88pm860x-regulator",
481 		.owner	= THIS_MODULE,
482 	},
483 	.probe		= pm8607_regulator_probe,
484 	.remove		= pm8607_regulator_remove,
485 	.id_table	= pm8607_regulator_driver_ids,
486 };
487 
488 static int __init pm8607_regulator_init(void)
489 {
490 	return platform_driver_register(&pm8607_regulator_driver);
491 }
492 subsys_initcall(pm8607_regulator_init);
493 
494 static void __exit pm8607_regulator_exit(void)
495 {
496 	platform_driver_unregister(&pm8607_regulator_driver);
497 }
498 module_exit(pm8607_regulator_exit);
499 
500 MODULE_LICENSE("GPL");
501 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
502 MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM8607 PMIC");
503 MODULE_ALIAS("platform:88pm8607-regulator");
504