Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1/*
  2 * AXP20x regulators driver.
  3 *
  4 * Copyright (C) 2013 Carlo Caione <carlo@caione.org>
  5 *
  6 * This file is subject to the terms and conditions of the GNU General
  7 * Public License. See the file "COPYING" in the main directory of this
  8 * archive for more details.
  9 *
 10 * This program is distributed in the hope that it will be useful,
 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 13 * GNU General Public License for more details.
 14 */
 15
 16#include <linux/err.h>
 17#include <linux/init.h>
 18#include <linux/module.h>
 19#include <linux/of.h>
 20#include <linux/of_device.h>
 21#include <linux/platform_device.h>
 22#include <linux/regmap.h>
 23#include <linux/mfd/axp20x.h>
 24#include <linux/regulator/driver.h>
 25#include <linux/regulator/of_regulator.h>
 26
 27#define AXP20X_IO_ENABLED		0x03
 28#define AXP20X_IO_DISABLED		0x07
 29
 30#define AXP22X_IO_ENABLED		0x03
 31#define AXP22X_IO_DISABLED		0x04
 32
 33#define AXP20X_WORKMODE_DCDC2_MASK	BIT(2)
 34#define AXP20X_WORKMODE_DCDC3_MASK	BIT(1)
 35#define AXP22X_WORKMODE_DCDCX_MASK(x)	BIT(x)
 36
 37#define AXP20X_FREQ_DCDC_MASK		0x0f
 38
 39#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
 40		    _vmask, _ereg, _emask, _enable_val, _disable_val)		\
 41	[_family##_##_id] = {							\
 42		.name		= (_match),					\
 43		.supply_name	= (_supply),					\
 44		.of_match	= of_match_ptr(_match),				\
 45		.regulators_node = of_match_ptr("regulators"),			\
 46		.type		= REGULATOR_VOLTAGE,				\
 47		.id		= _family##_##_id,				\
 48		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
 49		.owner		= THIS_MODULE,					\
 50		.min_uV		= (_min) * 1000,				\
 51		.uV_step	= (_step) * 1000,				\
 52		.vsel_reg	= (_vreg),					\
 53		.vsel_mask	= (_vmask),					\
 54		.enable_reg	= (_ereg),					\
 55		.enable_mask	= (_emask),					\
 56		.enable_val	= (_enable_val),				\
 57		.disable_val	= (_disable_val),				\
 58		.ops		= &axp20x_ops,					\
 59	}
 60
 61#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
 62		 _vmask, _ereg, _emask) 					\
 63	[_family##_##_id] = {							\
 64		.name		= (_match),					\
 65		.supply_name	= (_supply),					\
 66		.of_match	= of_match_ptr(_match),				\
 67		.regulators_node = of_match_ptr("regulators"),			\
 68		.type		= REGULATOR_VOLTAGE,				\
 69		.id		= _family##_##_id,				\
 70		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
 71		.owner		= THIS_MODULE,					\
 72		.min_uV		= (_min) * 1000,				\
 73		.uV_step	= (_step) * 1000,				\
 74		.vsel_reg	= (_vreg),					\
 75		.vsel_mask	= (_vmask),					\
 76		.enable_reg	= (_ereg),					\
 77		.enable_mask	= (_emask),					\
 78		.ops		= &axp20x_ops,					\
 79	}
 80
 81#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask)		\
 82	[_family##_##_id] = {							\
 83		.name		= (_match),					\
 84		.supply_name	= (_supply),					\
 85		.of_match	= of_match_ptr(_match),				\
 86		.regulators_node = of_match_ptr("regulators"),			\
 87		.type		= REGULATOR_VOLTAGE,				\
 88		.id		= _family##_##_id,				\
 89		.owner		= THIS_MODULE,					\
 90		.enable_reg	= (_ereg),					\
 91		.enable_mask	= (_emask),					\
 92		.ops		= &axp20x_ops_sw,				\
 93	}
 94
 95#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt)			\
 96	[_family##_##_id] = {							\
 97		.name		= (_match),					\
 98		.supply_name	= (_supply),					\
 99		.of_match	= of_match_ptr(_match),				\
100		.regulators_node = of_match_ptr("regulators"),			\
101		.type		= REGULATOR_VOLTAGE,				\
102		.id		= _family##_##_id,				\
103		.n_voltages	= 1,						\
104		.owner		= THIS_MODULE,					\
105		.min_uV		= (_volt) * 1000,				\
106		.ops		= &axp20x_ops_fixed				\
107	}
108
109#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages,	\
110			_vreg, _vmask, _ereg, _emask)				\
111	[_family##_##_id] = {							\
112		.name		= (_match),					\
113		.supply_name	= (_supply),					\
114		.of_match	= of_match_ptr(_match),				\
115		.regulators_node = of_match_ptr("regulators"),			\
116		.type		= REGULATOR_VOLTAGE,				\
117		.id		= _family##_##_id,				\
118		.n_voltages	= (_n_voltages),				\
119		.owner		= THIS_MODULE,					\
120		.vsel_reg	= (_vreg),					\
121		.vsel_mask	= (_vmask),					\
122		.enable_reg	= (_ereg),					\
123		.enable_mask	= (_emask),					\
124		.linear_ranges	= (_ranges),					\
125		.n_linear_ranges = ARRAY_SIZE(_ranges),				\
126		.ops		= &axp20x_ops_range,				\
127	}
128
129static struct regulator_ops axp20x_ops_fixed = {
130	.list_voltage		= regulator_list_voltage_linear,
131};
132
133static struct regulator_ops axp20x_ops_range = {
134	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
135	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
136	.list_voltage		= regulator_list_voltage_linear_range,
137	.enable			= regulator_enable_regmap,
138	.disable		= regulator_disable_regmap,
139	.is_enabled		= regulator_is_enabled_regmap,
140};
141
142static struct regulator_ops axp20x_ops = {
143	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
144	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
145	.list_voltage		= regulator_list_voltage_linear,
146	.enable			= regulator_enable_regmap,
147	.disable		= regulator_disable_regmap,
148	.is_enabled		= regulator_is_enabled_regmap,
149};
150
151static struct regulator_ops axp20x_ops_sw = {
152	.enable			= regulator_enable_regmap,
153	.disable		= regulator_disable_regmap,
154	.is_enabled		= regulator_is_enabled_regmap,
155};
156
157static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
158	REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0),
159	REGULATOR_LINEAR_RANGE(1300000, 0x1, 0x8, 100000),
160	REGULATOR_LINEAR_RANGE(2500000, 0x9, 0x9, 0),
161	REGULATOR_LINEAR_RANGE(2700000, 0xa, 0xb, 100000),
162	REGULATOR_LINEAR_RANGE(3000000, 0xc, 0xf, 100000),
163};
164
165static const struct regulator_desc axp20x_regulators[] = {
166	AXP_DESC(AXP20X, DCDC2, "dcdc2", "vin2", 700, 2275, 25,
167		 AXP20X_DCDC2_V_OUT, 0x3f, AXP20X_PWR_OUT_CTRL, 0x10),
168	AXP_DESC(AXP20X, DCDC3, "dcdc3", "vin3", 700, 3500, 25,
169		 AXP20X_DCDC3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x02),
170	AXP_DESC_FIXED(AXP20X, LDO1, "ldo1", "acin", 1300),
171	AXP_DESC(AXP20X, LDO2, "ldo2", "ldo24in", 1800, 3300, 100,
172		 AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04),
173	AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25,
174		 AXP20X_LDO3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x40),
175	AXP_DESC_RANGES(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_ranges,
176			16, AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL,
177			0x08),
178	AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
179		    AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07,
180		    AXP20X_IO_ENABLED, AXP20X_IO_DISABLED),
181};
182
183static const struct regulator_desc axp22x_regulators[] = {
184	AXP_DESC(AXP22X, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
185		 AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)),
186	AXP_DESC(AXP22X, DCDC2, "dcdc2", "vin2", 600, 1540, 20,
187		 AXP22X_DCDC2_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(2)),
188	AXP_DESC(AXP22X, DCDC3, "dcdc3", "vin3", 600, 1860, 20,
189		 AXP22X_DCDC3_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(3)),
190	AXP_DESC(AXP22X, DCDC4, "dcdc4", "vin4", 600, 1540, 20,
191		 AXP22X_DCDC4_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(4)),
192	AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
193		 AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
194	/* secondary switchable output of DCDC1 */
195	AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
196		    BIT(7)),
197	/* LDO regulator internally chained to DCDC5 */
198	AXP_DESC(AXP22X, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
199		 AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
200	AXP_DESC(AXP22X, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
201		 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(6)),
202	AXP_DESC(AXP22X, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
203		 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
204	AXP_DESC(AXP22X, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
205		 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
206	AXP_DESC(AXP22X, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
207		 AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
208	AXP_DESC(AXP22X, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
209		 AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(4)),
210	AXP_DESC(AXP22X, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
211		 AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
212	AXP_DESC(AXP22X, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
213		 AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
214	AXP_DESC(AXP22X, ELDO1, "eldo1", "eldoin", 700, 3300, 100,
215		 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
216	AXP_DESC(AXP22X, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
217		 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
218	AXP_DESC(AXP22X, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
219		 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
220	/* Note the datasheet only guarantees reliable operation up to
221	 * 3.3V, this needs to be enforced via dts provided constraints */
222	AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 700, 3800, 100,
223		    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
224		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
225	/* Note the datasheet only guarantees reliable operation up to
226	 * 3.3V, this needs to be enforced via dts provided constraints */
227	AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 700, 3800, 100,
228		    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
229		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
230	AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
231};
232
233static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
234{
235	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
236	u32 min, max, def, step;
237
238	switch (axp20x->variant) {
239	case AXP202_ID:
240	case AXP209_ID:
241		min = 750;
242		max = 1875;
243		def = 1500;
244		step = 75;
245		break;
246	case AXP221_ID:
247	case AXP223_ID:
248		min = 1800;
249		max = 4050;
250		def = 3000;
251		step = 150;
252		break;
253	default:
254		dev_err(&pdev->dev,
255			"Setting DCDC frequency for unsupported AXP variant\n");
256		return -EINVAL;
257	}
258
259	if (dcdcfreq == 0)
260		dcdcfreq = def;
261
262	if (dcdcfreq < min) {
263		dcdcfreq = min;
264		dev_warn(&pdev->dev, "DCDC frequency too low. Set to %ukHz\n",
265			 min);
266	}
267
268	if (dcdcfreq > max) {
269		dcdcfreq = max;
270		dev_warn(&pdev->dev, "DCDC frequency too high. Set to %ukHz\n",
271			 max);
272	}
273
274	dcdcfreq = (dcdcfreq - min) / step;
275
276	return regmap_update_bits(axp20x->regmap, AXP20X_DCDC_FREQ,
277				  AXP20X_FREQ_DCDC_MASK, dcdcfreq);
278}
279
280static int axp20x_regulator_parse_dt(struct platform_device *pdev)
281{
282	struct device_node *np, *regulators;
283	int ret;
284	u32 dcdcfreq = 0;
285
286	np = of_node_get(pdev->dev.parent->of_node);
287	if (!np)
288		return 0;
289
290	regulators = of_get_child_by_name(np, "regulators");
291	if (!regulators) {
292		dev_warn(&pdev->dev, "regulators node not found\n");
293	} else {
294		of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
295		ret = axp20x_set_dcdc_freq(pdev, dcdcfreq);
296		if (ret < 0) {
297			dev_err(&pdev->dev, "Error setting dcdc frequency: %d\n", ret);
298			return ret;
299		}
300
301		of_node_put(regulators);
302	}
303
304	return 0;
305}
306
307static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
308{
309	struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
310	unsigned int mask;
311
312	switch (axp20x->variant) {
313	case AXP202_ID:
314	case AXP209_ID:
315		if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
316			return -EINVAL;
317
318		mask = AXP20X_WORKMODE_DCDC2_MASK;
319		if (id == AXP20X_DCDC3)
320			mask = AXP20X_WORKMODE_DCDC3_MASK;
321
322		workmode <<= ffs(mask) - 1;
323		break;
324
325	case AXP221_ID:
326	case AXP223_ID:
327		if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
328			return -EINVAL;
329
330		mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP22X_DCDC1);
331		workmode <<= id - AXP22X_DCDC1;
332		break;
333
334	default:
335		/* should not happen */
336		WARN_ON(1);
337		return -EINVAL;
338	}
339
340	return regmap_update_bits(rdev->regmap, AXP20X_DCDC_MODE, mask, workmode);
341}
342
343static int axp20x_regulator_probe(struct platform_device *pdev)
344{
345	struct regulator_dev *rdev;
346	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
347	const struct regulator_desc *regulators;
348	struct regulator_config config = {
349		.dev = pdev->dev.parent,
350		.regmap = axp20x->regmap,
351		.driver_data = axp20x,
352	};
353	int ret, i, nregulators;
354	u32 workmode;
355	const char *axp22x_dc1_name = axp22x_regulators[AXP22X_DCDC1].name;
356	const char *axp22x_dc5_name = axp22x_regulators[AXP22X_DCDC5].name;
357
358	switch (axp20x->variant) {
359	case AXP202_ID:
360	case AXP209_ID:
361		regulators = axp20x_regulators;
362		nregulators = AXP20X_REG_ID_MAX;
363		break;
364	case AXP221_ID:
365	case AXP223_ID:
366		regulators = axp22x_regulators;
367		nregulators = AXP22X_REG_ID_MAX;
368		break;
369	default:
370		dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
371			axp20x->variant);
372		return -EINVAL;
373	}
374
375	/* This only sets the dcdc freq. Ignore any errors */
376	axp20x_regulator_parse_dt(pdev);
377
378	for (i = 0; i < nregulators; i++) {
379		const struct regulator_desc *desc = &regulators[i];
380		struct regulator_desc *new_desc;
381
382		/*
383		 * Regulators DC1SW and DC5LDO are connected internally,
384		 * so we have to handle their supply names separately.
385		 *
386		 * We always register the regulators in proper sequence,
387		 * so the supply names are correctly read. See the last
388		 * part of this loop to see where we save the DT defined
389		 * name.
390		 */
391		if (regulators == axp22x_regulators) {
392			if (i == AXP22X_DC1SW) {
393				new_desc = devm_kzalloc(&pdev->dev,
394							sizeof(*desc),
395							GFP_KERNEL);
396				*new_desc = regulators[i];
397				new_desc->supply_name = axp22x_dc1_name;
398				desc = new_desc;
399			} else if (i == AXP22X_DC5LDO) {
400				new_desc = devm_kzalloc(&pdev->dev,
401							sizeof(*desc),
402							GFP_KERNEL);
403				*new_desc = regulators[i];
404				new_desc->supply_name = axp22x_dc5_name;
405				desc = new_desc;
406			}
407		}
408
409		rdev = devm_regulator_register(&pdev->dev, desc, &config);
410		if (IS_ERR(rdev)) {
411			dev_err(&pdev->dev, "Failed to register %s\n",
412				regulators[i].name);
413
414			return PTR_ERR(rdev);
415		}
416
417		ret = of_property_read_u32(rdev->dev.of_node,
418					   "x-powers,dcdc-workmode",
419					   &workmode);
420		if (!ret) {
421			if (axp20x_set_dcdc_workmode(rdev, i, workmode))
422				dev_err(&pdev->dev, "Failed to set workmode on %s\n",
423					rdev->desc->name);
424		}
425
426		/*
427		 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
428		 */
429		if (regulators == axp22x_regulators) {
430			/* Can we use rdev->constraints->name instead? */
431			if (i == AXP22X_DCDC1)
432				of_property_read_string(rdev->dev.of_node,
433							"regulator-name",
434							&axp22x_dc1_name);
435			else if (i == AXP22X_DCDC5)
436				of_property_read_string(rdev->dev.of_node,
437							"regulator-name",
438							&axp22x_dc5_name);
439		}
440	}
441
442	return 0;
443}
444
445static struct platform_driver axp20x_regulator_driver = {
446	.probe	= axp20x_regulator_probe,
447	.driver	= {
448		.name		= "axp20x-regulator",
449	},
450};
451
452module_platform_driver(axp20x_regulator_driver);
453
454MODULE_LICENSE("GPL v2");
455MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
456MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC");
457MODULE_ALIAS("platform:axp20x-regulator");