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