1/*
2 * Regulator support for WM8400
3 *
4 * Copyright 2008 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 */
14
15#include <linux/bug.h>
16#include <linux/err.h>
17#include <linux/kernel.h>
18#include <linux/regulator/driver.h>
19#include <linux/mfd/wm8400-private.h>
20
21static int wm8400_ldo_is_enabled(struct regulator_dev *dev)
22{
23	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
24	u16 val;
25
26	val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
27	return (val & WM8400_LDO1_ENA) != 0;
28}
29
30static int wm8400_ldo_enable(struct regulator_dev *dev)
31{
32	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
33
34	return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
35			       WM8400_LDO1_ENA, WM8400_LDO1_ENA);
36}
37
38static int wm8400_ldo_disable(struct regulator_dev *dev)
39{
40	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
41
42	return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
43			       WM8400_LDO1_ENA, 0);
44}
45
46static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
47				   unsigned selector)
48{
49	if (selector > WM8400_LDO1_VSEL_MASK)
50		return -EINVAL;
51
52	if (selector < 15)
53		return 900000 + (selector * 50000);
54	else
55		return 1600000 + ((selector - 14) * 100000);
56}
57
58static int wm8400_ldo_get_voltage(struct regulator_dev *dev)
59{
60	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
61	u16 val;
62
63	val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
64	val &= WM8400_LDO1_VSEL_MASK;
65
66	return wm8400_ldo_list_voltage(dev, val);
67}
68
69static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
70				  int min_uV, int max_uV)
71{
72	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
73	u16 val;
74
75	if (min_uV < 900000 || min_uV > 3300000)
76		return -EINVAL;
77
78	if (min_uV < 1700000) {
79		/* Steps of 50mV from 900mV;  */
80		val = (min_uV - 850001) / 50000;
81
82		if ((val * 50000) + 900000 > max_uV)
83			return -EINVAL;
84		BUG_ON((val * 50000) + 900000 < min_uV);
85	} else {
86		/* Steps of 100mV from 1700mV */
87		val = ((min_uV - 1600001) / 100000);
88
89		if ((val * 100000) + 1700000 > max_uV)
90			return -EINVAL;
91		BUG_ON((val * 100000) + 1700000 < min_uV);
92
93		val += 0xf;
94	}
95
96	return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
97			       WM8400_LDO1_VSEL_MASK, val);
98}
99
100static struct regulator_ops wm8400_ldo_ops = {
101	.is_enabled = wm8400_ldo_is_enabled,
102	.enable = wm8400_ldo_enable,
103	.disable = wm8400_ldo_disable,
104	.list_voltage = wm8400_ldo_list_voltage,
105	.get_voltage = wm8400_ldo_get_voltage,
106	.set_voltage = wm8400_ldo_set_voltage,
107};
108
109static int wm8400_dcdc_is_enabled(struct regulator_dev *dev)
110{
111	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
112	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
113	u16 val;
114
115	val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
116	return (val & WM8400_DC1_ENA) != 0;
117}
118
119static int wm8400_dcdc_enable(struct regulator_dev *dev)
120{
121	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
122	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
123
124	return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
125			       WM8400_DC1_ENA, WM8400_DC1_ENA);
126}
127
128static int wm8400_dcdc_disable(struct regulator_dev *dev)
129{
130	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
131	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
132
133	return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
134			       WM8400_DC1_ENA, 0);
135}
136
137static int wm8400_dcdc_list_voltage(struct regulator_dev *dev,
138				    unsigned selector)
139{
140	if (selector > WM8400_DC1_VSEL_MASK)
141		return -EINVAL;
142
143	return 850000 + (selector * 25000);
144}
145
146static int wm8400_dcdc_get_voltage(struct regulator_dev *dev)
147{
148	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
149	u16 val;
150	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
151
152	val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
153	val &= WM8400_DC1_VSEL_MASK;
154
155	return 850000 + (25000 * val);
156}
157
158static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
159				  int min_uV, int max_uV)
160{
161	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
162	u16 val;
163	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
164
165	if (min_uV < 850000)
166		return -EINVAL;
167
168	val = (min_uV - 825001) / 25000;
169
170	if (850000 + (25000 * val) > max_uV)
171		return -EINVAL;
172	BUG_ON(850000 + (25000 * val) < min_uV);
173
174	return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
175			       WM8400_DC1_VSEL_MASK, val);
176}
177
178static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
179{
180	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
181	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
182	u16 data[2];
183	int ret;
184
185	ret = wm8400_block_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 2,
186				data);
187	if (ret != 0)
188		return 0;
189
190	/* Datasheet: hibernate */
191	if (data[0] & WM8400_DC1_SLEEP)
192		return REGULATOR_MODE_STANDBY;
193
194	/* Datasheet: standby */
195	if (!(data[0] & WM8400_DC1_ACTIVE))
196		return REGULATOR_MODE_IDLE;
197
198	/* Datasheet: active with or without force PWM */
199	if (data[1] & WM8400_DC1_FRC_PWM)
200		return REGULATOR_MODE_FAST;
201	else
202		return REGULATOR_MODE_NORMAL;
203}
204
205static int wm8400_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode)
206{
207	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
208	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
209	int ret;
210
211	switch (mode) {
212	case REGULATOR_MODE_FAST:
213		/* Datasheet: active with force PWM */
214		ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset,
215				      WM8400_DC1_FRC_PWM, WM8400_DC1_FRC_PWM);
216		if (ret != 0)
217			return ret;
218
219		return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
220				       WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
221				       WM8400_DC1_ACTIVE);
222
223	case REGULATOR_MODE_NORMAL:
224		/* Datasheet: active */
225		ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset,
226				      WM8400_DC1_FRC_PWM, 0);
227		if (ret != 0)
228			return ret;
229
230		return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
231				       WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
232				       WM8400_DC1_ACTIVE);
233
234	case REGULATOR_MODE_IDLE:
235		/* Datasheet: standby */
236		ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
237				      WM8400_DC1_ACTIVE, 0);
238		if (ret != 0)
239			return ret;
240		return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
241				       WM8400_DC1_SLEEP, 0);
242
243	default:
244		return -EINVAL;
245	}
246}
247
248static unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev,
249						 int input_uV, int output_uV,
250						 int load_uA)
251{
252	return REGULATOR_MODE_NORMAL;
253}
254
255static struct regulator_ops wm8400_dcdc_ops = {
256	.is_enabled = wm8400_dcdc_is_enabled,
257	.enable = wm8400_dcdc_enable,
258	.disable = wm8400_dcdc_disable,
259	.list_voltage = wm8400_dcdc_list_voltage,
260	.get_voltage = wm8400_dcdc_get_voltage,
261	.set_voltage = wm8400_dcdc_set_voltage,
262	.get_mode = wm8400_dcdc_get_mode,
263	.set_mode = wm8400_dcdc_set_mode,
264	.get_optimum_mode = wm8400_dcdc_get_optimum_mode,
265};
266
267static struct regulator_desc regulators[] = {
268	{
269		.name = "LDO1",
270		.id = WM8400_LDO1,
271		.ops = &wm8400_ldo_ops,
272		.n_voltages = WM8400_LDO1_VSEL_MASK + 1,
273		.type = REGULATOR_VOLTAGE,
274		.owner = THIS_MODULE,
275	},
276	{
277		.name = "LDO2",
278		.id = WM8400_LDO2,
279		.ops = &wm8400_ldo_ops,
280		.n_voltages = WM8400_LDO2_VSEL_MASK + 1,
281		.type = REGULATOR_VOLTAGE,
282		.owner = THIS_MODULE,
283	},
284	{
285		.name = "LDO3",
286		.id = WM8400_LDO3,
287		.ops = &wm8400_ldo_ops,
288		.n_voltages = WM8400_LDO3_VSEL_MASK + 1,
289		.type = REGULATOR_VOLTAGE,
290		.owner = THIS_MODULE,
291	},
292	{
293		.name = "LDO4",
294		.id = WM8400_LDO4,
295		.ops = &wm8400_ldo_ops,
296		.n_voltages = WM8400_LDO4_VSEL_MASK + 1,
297		.type = REGULATOR_VOLTAGE,
298		.owner = THIS_MODULE,
299	},
300	{
301		.name = "DCDC1",
302		.id = WM8400_DCDC1,
303		.ops = &wm8400_dcdc_ops,
304		.n_voltages = WM8400_DC1_VSEL_MASK + 1,
305		.type = REGULATOR_VOLTAGE,
306		.owner = THIS_MODULE,
307	},
308	{
309		.name = "DCDC2",
310		.id = WM8400_DCDC2,
311		.ops = &wm8400_dcdc_ops,
312		.n_voltages = WM8400_DC2_VSEL_MASK + 1,
313		.type = REGULATOR_VOLTAGE,
314		.owner = THIS_MODULE,
315	},
316};
317
318static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
319{
320	struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
321	struct regulator_dev *rdev;
322
323	rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
324				  pdev->dev.platform_data, wm8400);
325
326	if (IS_ERR(rdev))
327		return PTR_ERR(rdev);
328
329	platform_set_drvdata(pdev, rdev);
330
331	return 0;
332}
333
334static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
335{
336	struct regulator_dev *rdev = platform_get_drvdata(pdev);
337
338	platform_set_drvdata(pdev, NULL);
339	regulator_unregister(rdev);
340
341	return 0;
342}
343
344static struct platform_driver wm8400_regulator_driver = {
345	.driver = {
346		.name = "wm8400-regulator",
347	},
348	.probe = wm8400_regulator_probe,
349	.remove = __devexit_p(wm8400_regulator_remove),
350};
351
352/**
353 * wm8400_register_regulator - enable software control of a WM8400 regulator
354 *
355 * This function enables software control of a WM8400 regulator via
356 * the regulator API.  It is intended to be called from the
357 * platform_init() callback of the WM8400 MFD driver.
358 *
359 * @param dev      The WM8400 device to operate on.
360 * @param reg      The regulator to control.
361 * @param initdata Regulator initdata for the regulator.
362 */
363int wm8400_register_regulator(struct device *dev, int reg,
364			      struct regulator_init_data *initdata)
365{
366	struct wm8400 *wm8400 = dev_get_drvdata(dev);
367
368	if (wm8400->regulators[reg].name)
369		return -EBUSY;
370
371	initdata->driver_data = wm8400;
372
373	wm8400->regulators[reg].name = "wm8400-regulator";
374	wm8400->regulators[reg].id = reg;
375	wm8400->regulators[reg].dev.parent = dev;
376	wm8400->regulators[reg].dev.platform_data = initdata;
377
378	return platform_device_register(&wm8400->regulators[reg]);
379}
380EXPORT_SYMBOL_GPL(wm8400_register_regulator);
381
382static int __init wm8400_regulator_init(void)
383{
384	return platform_driver_register(&wm8400_regulator_driver);
385}
386subsys_initcall(wm8400_regulator_init);
387
388static void __exit wm8400_regulator_exit(void)
389{
390	platform_driver_unregister(&wm8400_regulator_driver);
391}
392module_exit(wm8400_regulator_exit);
393
394MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
395MODULE_DESCRIPTION("WM8400 regulator driver");
396MODULE_LICENSE("GPL");
397MODULE_ALIAS("platform:wm8400-regulator");
398