Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/* NXP PCF50633 PMIC Driver
  3 *
  4 * (C) 2006-2008 by Openmoko, Inc.
  5 * Author: Balaji Rao <balajirrao@openmoko.org>
  6 * All rights reserved.
  7 *
  8 * Broken down from monstrous PCF50633 driver mainly by
  9 * Harald Welte and Andy Green and Werner Almesberger
 
 
 
 
 
 
 10 */
 11
 12#include <linux/kernel.h>
 13#include <linux/module.h>
 14#include <linux/init.h>
 15#include <linux/device.h>
 16#include <linux/err.h>
 17#include <linux/platform_device.h>
 18
 19#include <linux/mfd/pcf50633/core.h>
 20#include <linux/mfd/pcf50633/pmic.h>
 21
 22#define PCF50633_REGULATOR(_name, _id, _min_uV, _uV_step, _min_sel, _n) \
 23	{							\
 24		.name = _name,					\
 25		.id = PCF50633_REGULATOR_##_id,			\
 26		.ops = &pcf50633_regulator_ops,			\
 27		.n_voltages = _n,				\
 28		.min_uV = _min_uV,				\
 29		.uV_step = _uV_step,				\
 30		.linear_min_sel = _min_sel,			\
 31		.type = REGULATOR_VOLTAGE,			\
 32		.owner = THIS_MODULE,				\
 33		.vsel_reg = PCF50633_REG_##_id##OUT,		\
 34		.vsel_mask = 0xff,				\
 35		.enable_reg = PCF50633_REG_##_id##OUT + 1,	\
 36		.enable_mask = PCF50633_REGULATOR_ON,		\
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 37	}
 38
 39static const struct regulator_ops pcf50633_regulator_ops = {
 40	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 41	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 42	.list_voltage = regulator_list_voltage_linear,
 43	.map_voltage = regulator_map_voltage_linear,
 44	.enable = regulator_enable_regmap,
 45	.disable = regulator_disable_regmap,
 46	.is_enabled = regulator_is_enabled_regmap,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 47};
 48
 49static const struct regulator_desc regulators[] = {
 50	[PCF50633_REGULATOR_AUTO] =
 51		PCF50633_REGULATOR("auto", AUTO, 1800000, 25000, 0x2f, 128),
 52	[PCF50633_REGULATOR_DOWN1] =
 53		PCF50633_REGULATOR("down1", DOWN1, 625000, 25000, 0, 96),
 54	[PCF50633_REGULATOR_DOWN2] =
 55		PCF50633_REGULATOR("down2", DOWN2, 625000, 25000, 0, 96),
 56	[PCF50633_REGULATOR_LDO1] =
 57		PCF50633_REGULATOR("ldo1", LDO1, 900000, 100000, 0, 28),
 58	[PCF50633_REGULATOR_LDO2] =
 59		PCF50633_REGULATOR("ldo2", LDO2, 900000, 100000, 0, 28),
 60	[PCF50633_REGULATOR_LDO3] =
 61		PCF50633_REGULATOR("ldo3", LDO3, 900000, 100000, 0, 28),
 62	[PCF50633_REGULATOR_LDO4] =
 63		PCF50633_REGULATOR("ldo4", LDO4, 900000, 100000, 0, 28),
 64	[PCF50633_REGULATOR_LDO5] =
 65		PCF50633_REGULATOR("ldo5", LDO5, 900000, 100000, 0, 28),
 66	[PCF50633_REGULATOR_LDO6] =
 67		PCF50633_REGULATOR("ldo6", LDO6, 900000, 100000, 0, 28),
 68	[PCF50633_REGULATOR_HCLDO] =
 69		PCF50633_REGULATOR("hcldo", HCLDO, 900000, 100000, 0, 28),
 70	[PCF50633_REGULATOR_MEMLDO] =
 71		PCF50633_REGULATOR("memldo", MEMLDO, 900000, 100000, 0, 28),
 72};
 73
 74static int pcf50633_regulator_probe(struct platform_device *pdev)
 75{
 76	struct regulator_dev *rdev;
 77	struct pcf50633 *pcf;
 78	struct regulator_config config = { };
 79
 80	/* Already set by core driver */
 81	pcf = dev_to_pcf50633(pdev->dev.parent);
 82
 83	config.dev = &pdev->dev;
 84	config.init_data = dev_get_platdata(&pdev->dev);
 85	config.driver_data = pcf;
 86	config.regmap = pcf->regmap;
 87
 88	rdev = devm_regulator_register(&pdev->dev, &regulators[pdev->id],
 89				       &config);
 90	if (IS_ERR(rdev))
 91		return PTR_ERR(rdev);
 92
 93	platform_set_drvdata(pdev, rdev);
 94
 95	if (pcf->pdata->regulator_registered)
 96		pcf->pdata->regulator_registered(pcf, pdev->id);
 97
 98	return 0;
 99}
100
 
 
 
 
 
 
 
 
 
 
101static struct platform_driver pcf50633_regulator_driver = {
102	.driver = {
103		.name = "pcf50633-regulator",
104	},
105	.probe = pcf50633_regulator_probe,
 
106};
107
108static int __init pcf50633_regulator_init(void)
109{
110	return platform_driver_register(&pcf50633_regulator_driver);
111}
112subsys_initcall(pcf50633_regulator_init);
113
114static void __exit pcf50633_regulator_exit(void)
115{
116	platform_driver_unregister(&pcf50633_regulator_driver);
117}
118module_exit(pcf50633_regulator_exit);
119
120MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
121MODULE_DESCRIPTION("PCF50633 regulator driver");
122MODULE_LICENSE("GPL");
123MODULE_ALIAS("platform:pcf50633-regulator");
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");