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