xref: /linux/drivers/regulator/axp20x-regulator.c (revision 4949009eb8d40a441dcddcd96e101e77d31cf1b2)
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 AXP20X_WORKMODE_DCDC2_MASK	BIT(2)
31 #define AXP20X_WORKMODE_DCDC3_MASK	BIT(1)
32 
33 #define AXP20X_FREQ_DCDC_MASK		0x0f
34 
35 #define AXP20X_DESC_IO(_id, _supply, _min, _max, _step, _vreg, _vmask, _ereg,   \
36 		       _emask, _enable_val, _disable_val)			\
37 	[AXP20X_##_id] = {							\
38 		.name		= #_id,						\
39 		.supply_name	= (_supply),					\
40 		.type		= REGULATOR_VOLTAGE,				\
41 		.id		= AXP20X_##_id,					\
42 		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
43 		.owner		= THIS_MODULE,					\
44 		.min_uV		= (_min) * 1000,				\
45 		.uV_step	= (_step) * 1000,				\
46 		.vsel_reg	= (_vreg),					\
47 		.vsel_mask	= (_vmask),					\
48 		.enable_reg	= (_ereg),					\
49 		.enable_mask	= (_emask),					\
50 		.enable_val	= (_enable_val),				\
51 		.disable_val	= (_disable_val),				\
52 		.ops		= &axp20x_ops,					\
53 	}
54 
55 #define AXP20X_DESC(_id, _supply, _min, _max, _step, _vreg, _vmask, _ereg,	\
56 		    _emask) 							\
57 	[AXP20X_##_id] = {							\
58 		.name		= #_id,						\
59 		.supply_name	= (_supply),					\
60 		.type		= REGULATOR_VOLTAGE,				\
61 		.id		= AXP20X_##_id,					\
62 		.n_voltages	= (((_max) - (_min)) / (_step) + 1),		\
63 		.owner		= THIS_MODULE,					\
64 		.min_uV		= (_min) * 1000,				\
65 		.uV_step	= (_step) * 1000,				\
66 		.vsel_reg	= (_vreg),					\
67 		.vsel_mask	= (_vmask),					\
68 		.enable_reg	= (_ereg),					\
69 		.enable_mask	= (_emask),					\
70 		.ops		= &axp20x_ops,					\
71 	}
72 
73 #define AXP20X_DESC_FIXED(_id, _supply, _volt)					\
74 	[AXP20X_##_id] = {							\
75 		.name		= #_id,						\
76 		.supply_name	= (_supply),					\
77 		.type		= REGULATOR_VOLTAGE,				\
78 		.id		= AXP20X_##_id,					\
79 		.n_voltages	= 1,						\
80 		.owner		= THIS_MODULE,					\
81 		.min_uV		= (_volt) * 1000,				\
82 		.ops		= &axp20x_ops_fixed				\
83 	}
84 
85 #define AXP20X_DESC_TABLE(_id, _supply, _table, _vreg, _vmask, _ereg, _emask)	\
86 	[AXP20X_##_id] = {							\
87 		.name		= #_id,						\
88 		.supply_name	= (_supply),					\
89 		.type		= REGULATOR_VOLTAGE,				\
90 		.id		= AXP20X_##_id,					\
91 		.n_voltages	= ARRAY_SIZE(_table),				\
92 		.owner		= THIS_MODULE,					\
93 		.vsel_reg	= (_vreg),					\
94 		.vsel_mask	= (_vmask),					\
95 		.enable_reg	= (_ereg),					\
96 		.enable_mask	= (_emask),					\
97 		.volt_table	= (_table),					\
98 		.ops		= &axp20x_ops_table,				\
99 	}
100 
101 static const int axp20x_ldo4_data[] = { 1250000, 1300000, 1400000, 1500000, 1600000,
102 					1700000, 1800000, 1900000, 2000000, 2500000,
103 					2700000, 2800000, 3000000, 3100000, 3200000,
104 					3300000 };
105 
106 static struct regulator_ops axp20x_ops_fixed = {
107 	.list_voltage		= regulator_list_voltage_linear,
108 };
109 
110 static struct regulator_ops axp20x_ops_table = {
111 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
112 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
113 	.list_voltage		= regulator_list_voltage_table,
114 	.map_voltage		= regulator_map_voltage_ascend,
115 	.enable			= regulator_enable_regmap,
116 	.disable		= regulator_disable_regmap,
117 	.is_enabled		= regulator_is_enabled_regmap,
118 };
119 
120 static struct regulator_ops axp20x_ops = {
121 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
122 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
123 	.list_voltage		= regulator_list_voltage_linear,
124 	.enable			= regulator_enable_regmap,
125 	.disable		= regulator_disable_regmap,
126 	.is_enabled		= regulator_is_enabled_regmap,
127 };
128 
129 static const struct regulator_desc axp20x_regulators[] = {
130 	AXP20X_DESC(DCDC2, "vin2", 700, 2275, 25, AXP20X_DCDC2_V_OUT, 0x3f,
131 		    AXP20X_PWR_OUT_CTRL, 0x10),
132 	AXP20X_DESC(DCDC3, "vin3", 700, 3500, 25, AXP20X_DCDC3_V_OUT, 0x7f,
133 		    AXP20X_PWR_OUT_CTRL, 0x02),
134 	AXP20X_DESC_FIXED(LDO1, "acin", 1300),
135 	AXP20X_DESC(LDO2, "ldo24in", 1800, 3300, 100, AXP20X_LDO24_V_OUT, 0xf0,
136 		    AXP20X_PWR_OUT_CTRL, 0x04),
137 	AXP20X_DESC(LDO3, "ldo3in", 700, 3500, 25, AXP20X_LDO3_V_OUT, 0x7f,
138 		    AXP20X_PWR_OUT_CTRL, 0x40),
139 	AXP20X_DESC_TABLE(LDO4, "ldo24in", axp20x_ldo4_data, AXP20X_LDO24_V_OUT, 0x0f,
140 			  AXP20X_PWR_OUT_CTRL, 0x08),
141 	AXP20X_DESC_IO(LDO5, "ldo5in", 1800, 3300, 100, AXP20X_LDO5_V_OUT, 0xf0,
142 		       AXP20X_GPIO0_CTRL, 0x07, AXP20X_IO_ENABLED,
143 		       AXP20X_IO_DISABLED),
144 };
145 
146 #define AXP_MATCH(_name, _id) \
147 	[AXP20X_##_id] = { \
148 		.name		= #_name, \
149 		.driver_data	= (void *) &axp20x_regulators[AXP20X_##_id], \
150 	}
151 
152 static struct of_regulator_match axp20x_matches[] = {
153 	AXP_MATCH(dcdc2, DCDC2),
154 	AXP_MATCH(dcdc3, DCDC3),
155 	AXP_MATCH(ldo1, LDO1),
156 	AXP_MATCH(ldo2, LDO2),
157 	AXP_MATCH(ldo3, LDO3),
158 	AXP_MATCH(ldo4, LDO4),
159 	AXP_MATCH(ldo5, LDO5),
160 };
161 
162 static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
163 {
164 	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
165 
166 	if (dcdcfreq < 750) {
167 		dcdcfreq = 750;
168 		dev_warn(&pdev->dev, "DCDC frequency too low. Set to 750kHz\n");
169 	}
170 
171 	if (dcdcfreq > 1875) {
172 		dcdcfreq = 1875;
173 		dev_warn(&pdev->dev, "DCDC frequency too high. Set to 1875kHz\n");
174 	}
175 
176 	dcdcfreq = (dcdcfreq - 750) / 75;
177 
178 	return regmap_update_bits(axp20x->regmap, AXP20X_DCDC_FREQ,
179 				  AXP20X_FREQ_DCDC_MASK, dcdcfreq);
180 }
181 
182 static int axp20x_regulator_parse_dt(struct platform_device *pdev)
183 {
184 	struct device_node *np, *regulators;
185 	int ret;
186 	u32 dcdcfreq;
187 
188 	np = of_node_get(pdev->dev.parent->of_node);
189 	if (!np)
190 		return 0;
191 
192 	regulators = of_get_child_by_name(np, "regulators");
193 	if (!regulators) {
194 		dev_warn(&pdev->dev, "regulators node not found\n");
195 	} else {
196 		ret = of_regulator_match(&pdev->dev, regulators, axp20x_matches,
197 					 ARRAY_SIZE(axp20x_matches));
198 		if (ret < 0) {
199 			dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret);
200 			return ret;
201 		}
202 
203 		dcdcfreq = 1500;
204 		of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
205 		ret = axp20x_set_dcdc_freq(pdev, dcdcfreq);
206 		if (ret < 0) {
207 			dev_err(&pdev->dev, "Error setting dcdc frequency: %d\n", ret);
208 			return ret;
209 		}
210 
211 		of_node_put(regulators);
212 	}
213 
214 	return 0;
215 }
216 
217 static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
218 {
219 	unsigned int mask = AXP20X_WORKMODE_DCDC2_MASK;
220 
221 	if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
222 		return -EINVAL;
223 
224 	if (id == AXP20X_DCDC3)
225 		mask = AXP20X_WORKMODE_DCDC3_MASK;
226 
227 	workmode <<= ffs(mask) - 1;
228 
229 	return regmap_update_bits(rdev->regmap, AXP20X_DCDC_MODE, mask, workmode);
230 }
231 
232 static int axp20x_regulator_probe(struct platform_device *pdev)
233 {
234 	struct regulator_dev *rdev;
235 	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
236 	struct regulator_config config = { };
237 	struct regulator_init_data *init_data;
238 	int ret, i;
239 	u32 workmode;
240 
241 	ret = axp20x_regulator_parse_dt(pdev);
242 	if (ret)
243 		return ret;
244 
245 	for (i = 0; i < AXP20X_REG_ID_MAX; i++) {
246 		init_data = axp20x_matches[i].init_data;
247 
248 		config.dev = pdev->dev.parent;
249 		config.init_data = init_data;
250 		config.regmap = axp20x->regmap;
251 		config.of_node = axp20x_matches[i].of_node;
252 
253 		rdev = devm_regulator_register(&pdev->dev, &axp20x_regulators[i],
254 					       &config);
255 		if (IS_ERR(rdev)) {
256 			dev_err(&pdev->dev, "Failed to register %s\n",
257 				axp20x_regulators[i].name);
258 
259 			return PTR_ERR(rdev);
260 		}
261 
262 		ret = of_property_read_u32(axp20x_matches[i].of_node, "x-powers,dcdc-workmode",
263 					   &workmode);
264 		if (!ret) {
265 			if (axp20x_set_dcdc_workmode(rdev, i, workmode))
266 				dev_err(&pdev->dev, "Failed to set workmode on %s\n",
267 					axp20x_regulators[i].name);
268 		}
269 	}
270 
271 	return 0;
272 }
273 
274 static struct platform_driver axp20x_regulator_driver = {
275 	.probe	= axp20x_regulator_probe,
276 	.driver	= {
277 		.name		= "axp20x-regulator",
278 	},
279 };
280 
281 module_platform_driver(axp20x_regulator_driver);
282 
283 MODULE_LICENSE("GPL v2");
284 MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
285 MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC");
286