Linux Audio

Check our new training course

Loading...
v3.1
  1/* NXP PCF50633 PMIC Driver
  2 *
  3 * (C) 2006-2008 by Openmoko, Inc.
  4 * Author: Balaji Rao <balajirrao@openmoko.org>
  5 * All rights reserved.
  6 *
  7 * Broken down from monstrous PCF50633 driver mainly by
  8 * Harald Welte and Andy Green and Werner Almesberger
  9 *
 10 *  This program is free software; you can redistribute  it and/or modify it
 11 *  under  the terms of  the GNU General  Public License as published by the
 12 *  Free Software Foundation;  either version 2 of the  License, or (at your
 13 *  option) any later version.
 14 *
 15 */
 16
 17#include <linux/kernel.h>
 18#include <linux/module.h>
 19#include <linux/init.h>
 20#include <linux/device.h>
 21#include <linux/err.h>
 22#include <linux/platform_device.h>
 23
 24#include <linux/mfd/pcf50633/core.h>
 25#include <linux/mfd/pcf50633/pmic.h>
 26
 27#define PCF50633_REGULATOR(_name, _id, _n) 		\
 28	{					\
 29		.name = _name, 			\
 30		.id = _id,			\
 31		.ops = &pcf50633_regulator_ops,	\
 32		.n_voltages = _n, \
 33		.type = REGULATOR_VOLTAGE, 	\
 34		.owner = THIS_MODULE, 		\
 
 
 
 
 
 
 
 35	}
 36
 37static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = {
 38	[PCF50633_REGULATOR_AUTO]	= PCF50633_REG_AUTOOUT,
 39	[PCF50633_REGULATOR_DOWN1]	= PCF50633_REG_DOWN1OUT,
 40	[PCF50633_REGULATOR_DOWN2]	= PCF50633_REG_DOWN2OUT,
 41	[PCF50633_REGULATOR_MEMLDO]	= PCF50633_REG_MEMLDOOUT,
 42	[PCF50633_REGULATOR_LDO1]	= PCF50633_REG_LDO1OUT,
 43	[PCF50633_REGULATOR_LDO2]	= PCF50633_REG_LDO2OUT,
 44	[PCF50633_REGULATOR_LDO3]	= PCF50633_REG_LDO3OUT,
 45	[PCF50633_REGULATOR_LDO4]	= PCF50633_REG_LDO4OUT,
 46	[PCF50633_REGULATOR_LDO5]	= PCF50633_REG_LDO5OUT,
 47	[PCF50633_REGULATOR_LDO6]	= PCF50633_REG_LDO6OUT,
 48	[PCF50633_REGULATOR_HCLDO]	= PCF50633_REG_HCLDOOUT,
 49};
 50
 51/* Bits from voltage value */
 52static u8 auto_voltage_bits(unsigned int millivolts)
 53{
 54	if (millivolts < 1800)
 55		return 0;
 56	if (millivolts > 3800)
 57		return 0xff;
 58
 59	millivolts -= 625;
 60
 61	return millivolts / 25;
 62}
 63
 64static u8 down_voltage_bits(unsigned int millivolts)
 65{
 66	if (millivolts < 625)
 67		return 0;
 68	else if (millivolts > 3000)
 69		return 0xff;
 70
 71	millivolts -= 625;
 72
 73	return millivolts / 25;
 74}
 75
 76static u8 ldo_voltage_bits(unsigned int millivolts)
 77{
 78	if (millivolts < 900)
 79		return 0;
 80	else if (millivolts > 3600)
 81		return 0x1f;
 82
 83	millivolts -= 900;
 84	return millivolts / 100;
 85}
 86
 87/* Obtain voltage value from bits */
 88static unsigned int auto_voltage_value(u8 bits)
 89{
 90	if (bits < 0x2f)
 91		return 0;
 92
 93	return 625 + (bits * 25);
 94}
 95
 96
 97static unsigned int down_voltage_value(u8 bits)
 98{
 99	return 625 + (bits * 25);
100}
101
102
103static unsigned int ldo_voltage_value(u8 bits)
104{
105	bits &= 0x1f;
106
107	return 900 + (bits * 100);
108}
109
110static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
111					  int min_uV, int max_uV,
112					  unsigned *selector)
113{
114	struct pcf50633 *pcf;
115	int regulator_id, millivolts;
116	u8 volt_bits, regnr;
117
118	pcf = rdev_get_drvdata(rdev);
119
120	regulator_id = rdev_get_id(rdev);
121	if (regulator_id >= PCF50633_NUM_REGULATORS)
122		return -EINVAL;
123
124	millivolts = min_uV / 1000;
125
126	regnr = pcf50633_regulator_registers[regulator_id];
127
128	switch (regulator_id) {
129	case PCF50633_REGULATOR_AUTO:
130		volt_bits = auto_voltage_bits(millivolts);
131		break;
132	case PCF50633_REGULATOR_DOWN1:
133		volt_bits = down_voltage_bits(millivolts);
134		break;
135	case PCF50633_REGULATOR_DOWN2:
136		volt_bits = down_voltage_bits(millivolts);
137		break;
138	case PCF50633_REGULATOR_LDO1:
139	case PCF50633_REGULATOR_LDO2:
140	case PCF50633_REGULATOR_LDO3:
141	case PCF50633_REGULATOR_LDO4:
142	case PCF50633_REGULATOR_LDO5:
143	case PCF50633_REGULATOR_LDO6:
144	case PCF50633_REGULATOR_HCLDO:
145		volt_bits = ldo_voltage_bits(millivolts);
146		break;
147	default:
148		return -EINVAL;
149	}
150
151	*selector = volt_bits;
152
153	return pcf50633_reg_write(pcf, regnr, volt_bits);
154}
155
156static int pcf50633_regulator_voltage_value(enum pcf50633_regulator_id id,
157						u8 bits)
158{
159	int millivolts;
160
161	switch (id) {
162	case PCF50633_REGULATOR_AUTO:
163		millivolts = auto_voltage_value(bits);
164		break;
165	case PCF50633_REGULATOR_DOWN1:
166		millivolts = down_voltage_value(bits);
167		break;
168	case PCF50633_REGULATOR_DOWN2:
169		millivolts = down_voltage_value(bits);
170		break;
171	case PCF50633_REGULATOR_LDO1:
172	case PCF50633_REGULATOR_LDO2:
173	case PCF50633_REGULATOR_LDO3:
174	case PCF50633_REGULATOR_LDO4:
175	case PCF50633_REGULATOR_LDO5:
176	case PCF50633_REGULATOR_LDO6:
177	case PCF50633_REGULATOR_HCLDO:
178		millivolts = ldo_voltage_value(bits);
179		break;
180	default:
181		return -EINVAL;
182	}
183
184	return millivolts * 1000;
185}
186
187static int pcf50633_regulator_get_voltage(struct regulator_dev *rdev)
188{
189	struct pcf50633 *pcf;
190	int regulator_id;
191	u8 volt_bits, regnr;
192
193	pcf = rdev_get_drvdata(rdev);
194
195	regulator_id = rdev_get_id(rdev);
196	if (regulator_id >= PCF50633_NUM_REGULATORS)
197		return -EINVAL;
198
199	regnr = pcf50633_regulator_registers[regulator_id];
200
201	volt_bits = pcf50633_reg_read(pcf, regnr);
202
203	return pcf50633_regulator_voltage_value(regulator_id, volt_bits);
204}
205
206static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
207						unsigned int index)
208{
209	struct pcf50633 *pcf;
210	int regulator_id;
211
212	pcf = rdev_get_drvdata(rdev);
213
214	regulator_id = rdev_get_id(rdev);
215
216	switch (regulator_id) {
217	case PCF50633_REGULATOR_AUTO:
218		index += 0x2f;
219		break;
220	case PCF50633_REGULATOR_HCLDO:
221		index += 0x01;
222		break;
223	default:
224		break;
225	}
226
227	return pcf50633_regulator_voltage_value(regulator_id, index);
228}
229
230static int pcf50633_regulator_enable(struct regulator_dev *rdev)
231{
232	struct pcf50633 *pcf = rdev_get_drvdata(rdev);
233	int regulator_id;
234	u8 regnr;
235
236	regulator_id = rdev_get_id(rdev);
237	if (regulator_id >= PCF50633_NUM_REGULATORS)
238		return -EINVAL;
239
240	/* The *ENA register is always one after the *OUT register */
241	regnr = pcf50633_regulator_registers[regulator_id] + 1;
242
243	return pcf50633_reg_set_bit_mask(pcf, regnr, PCF50633_REGULATOR_ON,
244						       PCF50633_REGULATOR_ON);
245}
246
247static int pcf50633_regulator_disable(struct regulator_dev *rdev)
248{
249	struct pcf50633 *pcf = rdev_get_drvdata(rdev);
250	int regulator_id;
251	u8 regnr;
252
253	regulator_id = rdev_get_id(rdev);
254	if (regulator_id >= PCF50633_NUM_REGULATORS)
255		return -EINVAL;
256
257	/* the *ENA register is always one after the *OUT register */
258	regnr = pcf50633_regulator_registers[regulator_id] + 1;
259
260	return pcf50633_reg_set_bit_mask(pcf, regnr,
261					PCF50633_REGULATOR_ON, 0);
262}
263
264static int pcf50633_regulator_is_enabled(struct regulator_dev *rdev)
265{
266	struct pcf50633 *pcf = rdev_get_drvdata(rdev);
267	int regulator_id = rdev_get_id(rdev);
268	u8 regnr;
269
270	regulator_id = rdev_get_id(rdev);
271	if (regulator_id >= PCF50633_NUM_REGULATORS)
272		return -EINVAL;
273
274	/* the *ENA register is always one after the *OUT register */
275	regnr = pcf50633_regulator_registers[regulator_id] + 1;
276
277	return pcf50633_reg_read(pcf, regnr) & PCF50633_REGULATOR_ON;
278}
279
280static struct regulator_ops pcf50633_regulator_ops = {
281	.set_voltage = pcf50633_regulator_set_voltage,
282	.get_voltage = pcf50633_regulator_get_voltage,
283	.list_voltage = pcf50633_regulator_list_voltage,
284	.enable = pcf50633_regulator_enable,
285	.disable = pcf50633_regulator_disable,
286	.is_enabled = pcf50633_regulator_is_enabled,
 
287};
288
289static struct regulator_desc regulators[] = {
290	[PCF50633_REGULATOR_AUTO] =
291		PCF50633_REGULATOR("auto", PCF50633_REGULATOR_AUTO, 80),
292	[PCF50633_REGULATOR_DOWN1] =
293		PCF50633_REGULATOR("down1", PCF50633_REGULATOR_DOWN1, 95),
294	[PCF50633_REGULATOR_DOWN2] =
295		PCF50633_REGULATOR("down2", PCF50633_REGULATOR_DOWN2, 95),
296	[PCF50633_REGULATOR_LDO1] =
297		PCF50633_REGULATOR("ldo1", PCF50633_REGULATOR_LDO1, 27),
298	[PCF50633_REGULATOR_LDO2] =
299		PCF50633_REGULATOR("ldo2", PCF50633_REGULATOR_LDO2, 27),
300	[PCF50633_REGULATOR_LDO3] =
301		PCF50633_REGULATOR("ldo3", PCF50633_REGULATOR_LDO3, 27),
302	[PCF50633_REGULATOR_LDO4] =
303		PCF50633_REGULATOR("ldo4", PCF50633_REGULATOR_LDO4, 27),
304	[PCF50633_REGULATOR_LDO5] =
305		PCF50633_REGULATOR("ldo5", PCF50633_REGULATOR_LDO5, 27),
306	[PCF50633_REGULATOR_LDO6] =
307		PCF50633_REGULATOR("ldo6", PCF50633_REGULATOR_LDO6, 27),
308	[PCF50633_REGULATOR_HCLDO] =
309		PCF50633_REGULATOR("hcldo", PCF50633_REGULATOR_HCLDO, 26),
310	[PCF50633_REGULATOR_MEMLDO] =
311		PCF50633_REGULATOR("memldo", PCF50633_REGULATOR_MEMLDO, 0),
312};
313
314static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
315{
316	struct regulator_dev *rdev;
317	struct pcf50633 *pcf;
 
318
319	/* Already set by core driver */
320	pcf = dev_to_pcf50633(pdev->dev.parent);
321
322	rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
323				  pdev->dev.platform_data, pcf);
 
 
 
 
 
324	if (IS_ERR(rdev))
325		return PTR_ERR(rdev);
326
327	platform_set_drvdata(pdev, rdev);
328
329	if (pcf->pdata->regulator_registered)
330		pcf->pdata->regulator_registered(pcf, pdev->id);
331
332	return 0;
333}
334
335static int __devexit pcf50633_regulator_remove(struct platform_device *pdev)
336{
337	struct regulator_dev *rdev = platform_get_drvdata(pdev);
338
339	platform_set_drvdata(pdev, NULL);
340	regulator_unregister(rdev);
341
342	return 0;
343}
344
345static struct platform_driver pcf50633_regulator_driver = {
346	.driver = {
347		.name = "pcf50633-regltr",
348	},
349	.probe = pcf50633_regulator_probe,
350	.remove = __devexit_p(pcf50633_regulator_remove),
351};
352
353static int __init pcf50633_regulator_init(void)
354{
355	return platform_driver_register(&pcf50633_regulator_driver);
356}
357subsys_initcall(pcf50633_regulator_init);
358
359static void __exit pcf50633_regulator_exit(void)
360{
361	platform_driver_unregister(&pcf50633_regulator_driver);
362}
363module_exit(pcf50633_regulator_exit);
364
365MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
366MODULE_DESCRIPTION("PCF50633 regulator driver");
367MODULE_LICENSE("GPL");
368MODULE_ALIAS("platform:pcf50633-regulator");
v4.6
  1/* NXP PCF50633 PMIC Driver
  2 *
  3 * (C) 2006-2008 by Openmoko, Inc.
  4 * Author: Balaji Rao <balajirrao@openmoko.org>
  5 * All rights reserved.
  6 *
  7 * Broken down from monstrous PCF50633 driver mainly by
  8 * Harald Welte and Andy Green and Werner Almesberger
  9 *
 10 *  This program is free software; you can redistribute  it and/or modify it
 11 *  under  the terms of  the GNU General  Public License as published by the
 12 *  Free Software Foundation;  either version 2 of the  License, or (at your
 13 *  option) any later version.
 14 *
 15 */
 16
 17#include <linux/kernel.h>
 18#include <linux/module.h>
 19#include <linux/init.h>
 20#include <linux/device.h>
 21#include <linux/err.h>
 22#include <linux/platform_device.h>
 23
 24#include <linux/mfd/pcf50633/core.h>
 25#include <linux/mfd/pcf50633/pmic.h>
 26
 27#define PCF50633_REGULATOR(_name, _id, _min_uV, _uV_step, _min_sel, _n) \
 28	{							\
 29		.name = _name,					\
 30		.id = PCF50633_REGULATOR_##_id,			\
 31		.ops = &pcf50633_regulator_ops,			\
 32		.n_voltages = _n,				\
 33		.min_uV = _min_uV,				\
 34		.uV_step = _uV_step,				\
 35		.linear_min_sel = _min_sel,			\
 36		.type = REGULATOR_VOLTAGE,			\
 37		.owner = THIS_MODULE,				\
 38		.vsel_reg = PCF50633_REG_##_id##OUT,		\
 39		.vsel_mask = 0xff,				\
 40		.enable_reg = PCF50633_REG_##_id##OUT + 1,	\
 41		.enable_mask = PCF50633_REGULATOR_ON,		\
 42	}
 43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 44static struct regulator_ops pcf50633_regulator_ops = {
 45	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 46	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 47	.list_voltage = regulator_list_voltage_linear,
 48	.map_voltage = regulator_map_voltage_linear,
 49	.enable = regulator_enable_regmap,
 50	.disable = regulator_disable_regmap,
 51	.is_enabled = regulator_is_enabled_regmap,
 52};
 53
 54static const struct regulator_desc regulators[] = {
 55	[PCF50633_REGULATOR_AUTO] =
 56		PCF50633_REGULATOR("auto", AUTO, 1800000, 25000, 0x2f, 128),
 57	[PCF50633_REGULATOR_DOWN1] =
 58		PCF50633_REGULATOR("down1", DOWN1, 625000, 25000, 0, 96),
 59	[PCF50633_REGULATOR_DOWN2] =
 60		PCF50633_REGULATOR("down2", DOWN2, 625000, 25000, 0, 96),
 61	[PCF50633_REGULATOR_LDO1] =
 62		PCF50633_REGULATOR("ldo1", LDO1, 900000, 100000, 0, 28),
 63	[PCF50633_REGULATOR_LDO2] =
 64		PCF50633_REGULATOR("ldo2", LDO2, 900000, 100000, 0, 28),
 65	[PCF50633_REGULATOR_LDO3] =
 66		PCF50633_REGULATOR("ldo3", LDO3, 900000, 100000, 0, 28),
 67	[PCF50633_REGULATOR_LDO4] =
 68		PCF50633_REGULATOR("ldo4", LDO4, 900000, 100000, 0, 28),
 69	[PCF50633_REGULATOR_LDO5] =
 70		PCF50633_REGULATOR("ldo5", LDO5, 900000, 100000, 0, 28),
 71	[PCF50633_REGULATOR_LDO6] =
 72		PCF50633_REGULATOR("ldo6", LDO6, 900000, 100000, 0, 28),
 73	[PCF50633_REGULATOR_HCLDO] =
 74		PCF50633_REGULATOR("hcldo", HCLDO, 900000, 100000, 0, 28),
 75	[PCF50633_REGULATOR_MEMLDO] =
 76		PCF50633_REGULATOR("memldo", MEMLDO, 900000, 100000, 0, 28),
 77};
 78
 79static int pcf50633_regulator_probe(struct platform_device *pdev)
 80{
 81	struct regulator_dev *rdev;
 82	struct pcf50633 *pcf;
 83	struct regulator_config config = { };
 84
 85	/* Already set by core driver */
 86	pcf = dev_to_pcf50633(pdev->dev.parent);
 87
 88	config.dev = &pdev->dev;
 89	config.init_data = dev_get_platdata(&pdev->dev);
 90	config.driver_data = pcf;
 91	config.regmap = pcf->regmap;
 92
 93	rdev = devm_regulator_register(&pdev->dev, &regulators[pdev->id],
 94				       &config);
 95	if (IS_ERR(rdev))
 96		return PTR_ERR(rdev);
 97
 98	platform_set_drvdata(pdev, rdev);
 99
100	if (pcf->pdata->regulator_registered)
101		pcf->pdata->regulator_registered(pcf, pdev->id);
102
103	return 0;
104}
105
 
 
 
 
 
 
 
 
 
 
106static struct platform_driver pcf50633_regulator_driver = {
107	.driver = {
108		.name = "pcf50633-regulator",
109	},
110	.probe = pcf50633_regulator_probe,
 
111};
112
113static int __init pcf50633_regulator_init(void)
114{
115	return platform_driver_register(&pcf50633_regulator_driver);
116}
117subsys_initcall(pcf50633_regulator_init);
118
119static void __exit pcf50633_regulator_exit(void)
120{
121	platform_driver_unregister(&pcf50633_regulator_driver);
122}
123module_exit(pcf50633_regulator_exit);
124
125MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
126MODULE_DESCRIPTION("PCF50633 regulator driver");
127MODULE_LICENSE("GPL");
128MODULE_ALIAS("platform:pcf50633-regulator");