xref: /linux/drivers/regulator/db8500-prcmu.c (revision cff4fa8415a3224a5abdd2b1dd7f431e4ea49366)
1 /*
2  * Copyright (C) ST-Ericsson SA 2010
3  *
4  * License Terms: GNU General Public License v2
5  * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
6  *          Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
7  *
8  * Power domain regulators on DB8500
9  */
10 
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/err.h>
14 #include <linux/spinlock.h>
15 #include <linux/platform_device.h>
16 #include <linux/mfd/db8500-prcmu.h>
17 #include <linux/regulator/driver.h>
18 #include <linux/regulator/machine.h>
19 #include <linux/regulator/db8500-prcmu.h>
20 
21 /*
22  * power state reference count
23  */
24 static int power_state_active_cnt; /* will initialize to zero */
25 static DEFINE_SPINLOCK(power_state_active_lock);
26 
27 static void power_state_active_enable(void)
28 {
29 	unsigned long flags;
30 
31 	spin_lock_irqsave(&power_state_active_lock, flags);
32 	power_state_active_cnt++;
33 	spin_unlock_irqrestore(&power_state_active_lock, flags);
34 }
35 
36 static int power_state_active_disable(void)
37 {
38 	int ret = 0;
39 	unsigned long flags;
40 
41 	spin_lock_irqsave(&power_state_active_lock, flags);
42 	if (power_state_active_cnt <= 0) {
43 		pr_err("power state: unbalanced enable/disable calls\n");
44 		ret = -EINVAL;
45 		goto out;
46 	}
47 
48 	power_state_active_cnt--;
49 out:
50 	spin_unlock_irqrestore(&power_state_active_lock, flags);
51 	return ret;
52 }
53 
54 /*
55  * Exported interface for CPUIdle only. This function is called when interrupts
56  * are turned off. Hence, no locking.
57  */
58 int power_state_active_is_enabled(void)
59 {
60 	return (power_state_active_cnt > 0);
61 }
62 
63 /**
64  * struct db8500_regulator_info - db8500 regulator information
65  * @dev: device pointer
66  * @desc: regulator description
67  * @rdev: regulator device pointer
68  * @is_enabled: status of the regulator
69  * @epod_id: id for EPOD (power domain)
70  * @is_ramret: RAM retention switch for EPOD (power domain)
71  * @operating_point: operating point (only for vape, to be removed)
72  *
73  */
74 struct db8500_regulator_info {
75 	struct device *dev;
76 	struct regulator_desc desc;
77 	struct regulator_dev *rdev;
78 	bool is_enabled;
79 	u16 epod_id;
80 	bool is_ramret;
81 	bool exclude_from_power_state;
82 	unsigned int operating_point;
83 };
84 
85 static int db8500_regulator_enable(struct regulator_dev *rdev)
86 {
87 	struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
88 
89 	if (info == NULL)
90 		return -EINVAL;
91 
92 	dev_vdbg(rdev_get_dev(rdev), "regulator-%s-enable\n",
93 		info->desc.name);
94 
95 	info->is_enabled = true;
96 	if (!info->exclude_from_power_state)
97 		power_state_active_enable();
98 
99 	return 0;
100 }
101 
102 static int db8500_regulator_disable(struct regulator_dev *rdev)
103 {
104 	struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
105 	int ret = 0;
106 
107 	if (info == NULL)
108 		return -EINVAL;
109 
110 	dev_vdbg(rdev_get_dev(rdev), "regulator-%s-disable\n",
111 		info->desc.name);
112 
113 	info->is_enabled = false;
114 	if (!info->exclude_from_power_state)
115 		ret = power_state_active_disable();
116 
117 	return ret;
118 }
119 
120 static int db8500_regulator_is_enabled(struct regulator_dev *rdev)
121 {
122 	struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
123 
124 	if (info == NULL)
125 		return -EINVAL;
126 
127 	dev_vdbg(rdev_get_dev(rdev), "regulator-%s-is_enabled (is_enabled):"
128 		" %i\n", info->desc.name, info->is_enabled);
129 
130 	return info->is_enabled;
131 }
132 
133 /* db8500 regulator operations */
134 static struct regulator_ops db8500_regulator_ops = {
135 	.enable			= db8500_regulator_enable,
136 	.disable		= db8500_regulator_disable,
137 	.is_enabled		= db8500_regulator_is_enabled,
138 };
139 
140 /*
141  * EPOD control
142  */
143 static bool epod_on[NUM_EPOD_ID];
144 static bool epod_ramret[NUM_EPOD_ID];
145 
146 static int enable_epod(u16 epod_id, bool ramret)
147 {
148 	int ret;
149 
150 	if (ramret) {
151 		if (!epod_on[epod_id]) {
152 			ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
153 			if (ret < 0)
154 				return ret;
155 		}
156 		epod_ramret[epod_id] = true;
157 	} else {
158 		ret = prcmu_set_epod(epod_id, EPOD_STATE_ON);
159 		if (ret < 0)
160 			return ret;
161 		epod_on[epod_id] = true;
162 	}
163 
164 	return 0;
165 }
166 
167 static int disable_epod(u16 epod_id, bool ramret)
168 {
169 	int ret;
170 
171 	if (ramret) {
172 		if (!epod_on[epod_id]) {
173 			ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
174 			if (ret < 0)
175 				return ret;
176 		}
177 		epod_ramret[epod_id] = false;
178 	} else {
179 		if (epod_ramret[epod_id]) {
180 			ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
181 			if (ret < 0)
182 				return ret;
183 		} else {
184 			ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
185 			if (ret < 0)
186 				return ret;
187 		}
188 		epod_on[epod_id] = false;
189 	}
190 
191 	return 0;
192 }
193 
194 /*
195  * Regulator switch
196  */
197 static int db8500_regulator_switch_enable(struct regulator_dev *rdev)
198 {
199 	struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
200 	int ret;
201 
202 	if (info == NULL)
203 		return -EINVAL;
204 
205 	dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-enable\n",
206 		info->desc.name);
207 
208 	ret = enable_epod(info->epod_id, info->is_ramret);
209 	if (ret < 0) {
210 		dev_err(rdev_get_dev(rdev),
211 			"regulator-switch-%s-enable: prcmu call failed\n",
212 			info->desc.name);
213 		goto out;
214 	}
215 
216 	info->is_enabled = true;
217 out:
218 	return ret;
219 }
220 
221 static int db8500_regulator_switch_disable(struct regulator_dev *rdev)
222 {
223 	struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
224 	int ret;
225 
226 	if (info == NULL)
227 		return -EINVAL;
228 
229 	dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-disable\n",
230 		info->desc.name);
231 
232 	ret = disable_epod(info->epod_id, info->is_ramret);
233 	if (ret < 0) {
234 		dev_err(rdev_get_dev(rdev),
235 			"regulator_switch-%s-disable: prcmu call failed\n",
236 			info->desc.name);
237 		goto out;
238 	}
239 
240 	info->is_enabled = 0;
241 out:
242 	return ret;
243 }
244 
245 static int db8500_regulator_switch_is_enabled(struct regulator_dev *rdev)
246 {
247 	struct db8500_regulator_info *info = rdev_get_drvdata(rdev);
248 
249 	if (info == NULL)
250 		return -EINVAL;
251 
252 	dev_vdbg(rdev_get_dev(rdev),
253 		"regulator-switch-%s-is_enabled (is_enabled): %i\n",
254 		info->desc.name, info->is_enabled);
255 
256 	return info->is_enabled;
257 }
258 
259 static struct regulator_ops db8500_regulator_switch_ops = {
260 	.enable			= db8500_regulator_switch_enable,
261 	.disable		= db8500_regulator_switch_disable,
262 	.is_enabled		= db8500_regulator_switch_is_enabled,
263 };
264 
265 /*
266  * Regulator information
267  */
268 static struct db8500_regulator_info
269 db8500_regulator_info[DB8500_NUM_REGULATORS] = {
270 	[DB8500_REGULATOR_VAPE] = {
271 		.desc = {
272 			.name	= "db8500-vape",
273 			.id	= DB8500_REGULATOR_VAPE,
274 			.ops	= &db8500_regulator_ops,
275 			.type	= REGULATOR_VOLTAGE,
276 			.owner	= THIS_MODULE,
277 		},
278 	},
279 	[DB8500_REGULATOR_VARM] = {
280 		.desc = {
281 			.name	= "db8500-varm",
282 			.id	= DB8500_REGULATOR_VARM,
283 			.ops	= &db8500_regulator_ops,
284 			.type	= REGULATOR_VOLTAGE,
285 			.owner	= THIS_MODULE,
286 		},
287 	},
288 	[DB8500_REGULATOR_VMODEM] = {
289 		.desc = {
290 			.name	= "db8500-vmodem",
291 			.id	= DB8500_REGULATOR_VMODEM,
292 			.ops	= &db8500_regulator_ops,
293 			.type	= REGULATOR_VOLTAGE,
294 			.owner	= THIS_MODULE,
295 		},
296 	},
297 	[DB8500_REGULATOR_VPLL] = {
298 		.desc = {
299 			.name	= "db8500-vpll",
300 			.id	= DB8500_REGULATOR_VPLL,
301 			.ops	= &db8500_regulator_ops,
302 			.type	= REGULATOR_VOLTAGE,
303 			.owner	= THIS_MODULE,
304 		},
305 	},
306 	[DB8500_REGULATOR_VSMPS1] = {
307 		.desc = {
308 			.name	= "db8500-vsmps1",
309 			.id	= DB8500_REGULATOR_VSMPS1,
310 			.ops	= &db8500_regulator_ops,
311 			.type	= REGULATOR_VOLTAGE,
312 			.owner	= THIS_MODULE,
313 		},
314 	},
315 	[DB8500_REGULATOR_VSMPS2] = {
316 		.desc = {
317 			.name	= "db8500-vsmps2",
318 			.id	= DB8500_REGULATOR_VSMPS2,
319 			.ops	= &db8500_regulator_ops,
320 			.type	= REGULATOR_VOLTAGE,
321 			.owner	= THIS_MODULE,
322 		},
323 		.exclude_from_power_state = true,
324 	},
325 	[DB8500_REGULATOR_VSMPS3] = {
326 		.desc = {
327 			.name	= "db8500-vsmps3",
328 			.id	= DB8500_REGULATOR_VSMPS3,
329 			.ops	= &db8500_regulator_ops,
330 			.type	= REGULATOR_VOLTAGE,
331 			.owner	= THIS_MODULE,
332 		},
333 	},
334 	[DB8500_REGULATOR_VRF1] = {
335 		.desc = {
336 			.name	= "db8500-vrf1",
337 			.id	= DB8500_REGULATOR_VRF1,
338 			.ops	= &db8500_regulator_ops,
339 			.type	= REGULATOR_VOLTAGE,
340 			.owner	= THIS_MODULE,
341 		},
342 	},
343 	[DB8500_REGULATOR_SWITCH_SVAMMDSP] = {
344 		.desc = {
345 			.name	= "db8500-sva-mmdsp",
346 			.id	= DB8500_REGULATOR_SWITCH_SVAMMDSP,
347 			.ops	= &db8500_regulator_switch_ops,
348 			.type	= REGULATOR_VOLTAGE,
349 			.owner	= THIS_MODULE,
350 		},
351 		.epod_id = EPOD_ID_SVAMMDSP,
352 	},
353 	[DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = {
354 		.desc = {
355 			.name	= "db8500-sva-mmdsp-ret",
356 			.id	= DB8500_REGULATOR_SWITCH_SVAMMDSPRET,
357 			.ops	= &db8500_regulator_switch_ops,
358 			.type	= REGULATOR_VOLTAGE,
359 			.owner	= THIS_MODULE,
360 		},
361 		.epod_id = EPOD_ID_SVAMMDSP,
362 		.is_ramret = true,
363 	},
364 	[DB8500_REGULATOR_SWITCH_SVAPIPE] = {
365 		.desc = {
366 			.name	= "db8500-sva-pipe",
367 			.id	= DB8500_REGULATOR_SWITCH_SVAPIPE,
368 			.ops	= &db8500_regulator_switch_ops,
369 			.type	= REGULATOR_VOLTAGE,
370 			.owner	= THIS_MODULE,
371 		},
372 		.epod_id = EPOD_ID_SVAPIPE,
373 	},
374 	[DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
375 		.desc = {
376 			.name	= "db8500-sia-mmdsp",
377 			.id	= DB8500_REGULATOR_SWITCH_SIAMMDSP,
378 			.ops	= &db8500_regulator_switch_ops,
379 			.type	= REGULATOR_VOLTAGE,
380 			.owner	= THIS_MODULE,
381 		},
382 		.epod_id = EPOD_ID_SIAMMDSP,
383 	},
384 	[DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = {
385 		.desc = {
386 			.name	= "db8500-sia-mmdsp-ret",
387 			.id	= DB8500_REGULATOR_SWITCH_SIAMMDSPRET,
388 			.ops	= &db8500_regulator_switch_ops,
389 			.type	= REGULATOR_VOLTAGE,
390 			.owner	= THIS_MODULE,
391 		},
392 		.epod_id = EPOD_ID_SIAMMDSP,
393 		.is_ramret = true,
394 	},
395 	[DB8500_REGULATOR_SWITCH_SIAPIPE] = {
396 		.desc = {
397 			.name	= "db8500-sia-pipe",
398 			.id	= DB8500_REGULATOR_SWITCH_SIAPIPE,
399 			.ops	= &db8500_regulator_switch_ops,
400 			.type	= REGULATOR_VOLTAGE,
401 			.owner	= THIS_MODULE,
402 		},
403 		.epod_id = EPOD_ID_SIAPIPE,
404 	},
405 	[DB8500_REGULATOR_SWITCH_SGA] = {
406 		.desc = {
407 			.name	= "db8500-sga",
408 			.id	= DB8500_REGULATOR_SWITCH_SGA,
409 			.ops	= &db8500_regulator_switch_ops,
410 			.type	= REGULATOR_VOLTAGE,
411 			.owner	= THIS_MODULE,
412 		},
413 		.epod_id = EPOD_ID_SGA,
414 	},
415 	[DB8500_REGULATOR_SWITCH_B2R2_MCDE] = {
416 		.desc = {
417 			.name	= "db8500-b2r2-mcde",
418 			.id	= DB8500_REGULATOR_SWITCH_B2R2_MCDE,
419 			.ops	= &db8500_regulator_switch_ops,
420 			.type	= REGULATOR_VOLTAGE,
421 			.owner	= THIS_MODULE,
422 		},
423 		.epod_id = EPOD_ID_B2R2_MCDE,
424 	},
425 	[DB8500_REGULATOR_SWITCH_ESRAM12] = {
426 		.desc = {
427 			.name	= "db8500-esram12",
428 			.id	= DB8500_REGULATOR_SWITCH_ESRAM12,
429 			.ops	= &db8500_regulator_switch_ops,
430 			.type	= REGULATOR_VOLTAGE,
431 			.owner	= THIS_MODULE,
432 		},
433 		.epod_id	= EPOD_ID_ESRAM12,
434 		.is_enabled	= true,
435 	},
436 	[DB8500_REGULATOR_SWITCH_ESRAM12RET] = {
437 		.desc = {
438 			.name	= "db8500-esram12-ret",
439 			.id	= DB8500_REGULATOR_SWITCH_ESRAM12RET,
440 			.ops	= &db8500_regulator_switch_ops,
441 			.type	= REGULATOR_VOLTAGE,
442 			.owner	= THIS_MODULE,
443 		},
444 		.epod_id = EPOD_ID_ESRAM12,
445 		.is_ramret = true,
446 	},
447 	[DB8500_REGULATOR_SWITCH_ESRAM34] = {
448 		.desc = {
449 			.name	= "db8500-esram34",
450 			.id	= DB8500_REGULATOR_SWITCH_ESRAM34,
451 			.ops	= &db8500_regulator_switch_ops,
452 			.type	= REGULATOR_VOLTAGE,
453 			.owner	= THIS_MODULE,
454 		},
455 		.epod_id	= EPOD_ID_ESRAM34,
456 		.is_enabled	= true,
457 	},
458 	[DB8500_REGULATOR_SWITCH_ESRAM34RET] = {
459 		.desc = {
460 			.name	= "db8500-esram34-ret",
461 			.id	= DB8500_REGULATOR_SWITCH_ESRAM34RET,
462 			.ops	= &db8500_regulator_switch_ops,
463 			.type	= REGULATOR_VOLTAGE,
464 			.owner	= THIS_MODULE,
465 		},
466 		.epod_id = EPOD_ID_ESRAM34,
467 		.is_ramret = true,
468 	},
469 };
470 
471 static int __devinit db8500_regulator_probe(struct platform_device *pdev)
472 {
473 	struct regulator_init_data *db8500_init_data =
474 					dev_get_platdata(&pdev->dev);
475 	int i, err;
476 
477 	/* register all regulators */
478 	for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) {
479 		struct db8500_regulator_info *info;
480 		struct regulator_init_data *init_data = &db8500_init_data[i];
481 
482 		/* assign per-regulator data */
483 		info = &db8500_regulator_info[i];
484 		info->dev = &pdev->dev;
485 
486 		/* register with the regulator framework */
487 		info->rdev = regulator_register(&info->desc, &pdev->dev,
488 				init_data, info);
489 		if (IS_ERR(info->rdev)) {
490 			err = PTR_ERR(info->rdev);
491 			dev_err(&pdev->dev, "failed to register %s: err %i\n",
492 				info->desc.name, err);
493 
494 			/* if failing, unregister all earlier regulators */
495 			while (--i >= 0) {
496 				info = &db8500_regulator_info[i];
497 				regulator_unregister(info->rdev);
498 			}
499 			return err;
500 		}
501 
502 		dev_dbg(rdev_get_dev(info->rdev),
503 			"regulator-%s-probed\n", info->desc.name);
504 	}
505 
506 	return 0;
507 }
508 
509 static int __exit db8500_regulator_remove(struct platform_device *pdev)
510 {
511 	int i;
512 
513 	for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) {
514 		struct db8500_regulator_info *info;
515 		info = &db8500_regulator_info[i];
516 
517 		dev_vdbg(rdev_get_dev(info->rdev),
518 			"regulator-%s-remove\n", info->desc.name);
519 
520 		regulator_unregister(info->rdev);
521 	}
522 
523 	return 0;
524 }
525 
526 static struct platform_driver db8500_regulator_driver = {
527 	.driver = {
528 		.name = "db8500-prcmu-regulators",
529 		.owner = THIS_MODULE,
530 	},
531 	.probe = db8500_regulator_probe,
532 	.remove = __exit_p(db8500_regulator_remove),
533 };
534 
535 static int __init db8500_regulator_init(void)
536 {
537 	return platform_driver_register(&db8500_regulator_driver);
538 }
539 
540 static void __exit db8500_regulator_exit(void)
541 {
542 	platform_driver_unregister(&db8500_regulator_driver);
543 }
544 
545 arch_initcall(db8500_regulator_init);
546 module_exit(db8500_regulator_exit);
547 
548 MODULE_AUTHOR("STMicroelectronics/ST-Ericsson");
549 MODULE_DESCRIPTION("DB8500 regulator driver");
550 MODULE_LICENSE("GPL v2");
551