xref: /linux/drivers/regulator/max77650-regulator.c (revision f858cc9eed5b05cbe38d7ffd2787c21e3718eb7d)
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Copyright (C) 2018 BayLibre SAS
4 // Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
5 //
6 // Regulator driver for MAXIM 77650/77651 charger/power-supply.
7 
8 #include <linux/of.h>
9 #include <linux/mfd/max77650.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/regmap.h>
13 #include <linux/regulator/driver.h>
14 
15 #define MAX77650_REGULATOR_EN_CTRL_MASK		GENMASK(3, 0)
16 #define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \
17 		((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK)
18 #define MAX77650_REGULATOR_ENABLED		GENMASK(2, 1)
19 #define MAX77650_REGULATOR_DISABLED		BIT(2)
20 
21 #define MAX77650_REGULATOR_V_LDO_MASK		GENMASK(6, 0)
22 #define MAX77650_REGULATOR_V_SBB_MASK		GENMASK(5, 0)
23 #define MAX77651_REGULATOR_V_SBB1_MASK		GENMASK(5, 2)
24 #define MAX77651_REGULATOR_V_SBB1_RANGE_MASK	GENMASK(1, 0)
25 
26 #define MAX77650_REGULATOR_AD_MASK		BIT(3)
27 #define MAX77650_REGULATOR_AD_DISABLED		0x00
28 #define MAX77650_REGULATOR_AD_ENABLED		BIT(3)
29 
30 #define MAX77650_REGULATOR_CURR_LIM_MASK	GENMASK(7, 6)
31 
32 enum {
33 	MAX77650_REGULATOR_ID_LDO = 0,
34 	MAX77650_REGULATOR_ID_SBB0,
35 	MAX77650_REGULATOR_ID_SBB1,
36 	MAX77650_REGULATOR_ID_SBB2,
37 	MAX77650_REGULATOR_NUM_REGULATORS,
38 };
39 
40 struct max77650_regulator_desc {
41 	struct regulator_desc desc;
42 	unsigned int regA;
43 	unsigned int regB;
44 };
45 
46 static const unsigned int max77651_sbb1_volt_range_sel[] = {
47 	0x0, 0x1, 0x2, 0x3
48 };
49 
50 static const struct linear_range max77651_sbb1_volt_ranges[] = {
51 	/* range index 0 */
52 	REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000),
53 	/* range index 1 */
54 	REGULATOR_LINEAR_RANGE(3200000, 0x00, 0x0f, 50000),
55 	/* range index 2 */
56 	REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x0f, 50000),
57 	/* range index 3 */
58 	REGULATOR_LINEAR_RANGE(4800000, 0x00, 0x09, 50000),
59 };
60 
61 static const unsigned int max77650_current_limit_table[] = {
62 	1000000, 866000, 707000, 500000,
63 };
64 
65 static int max77650_regulator_is_enabled(struct regulator_dev *rdev)
66 {
67 	const struct max77650_regulator_desc *rdesc;
68 	struct regmap *map;
69 	int val, rv, en;
70 
71 	rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);
72 	map = rdev_get_regmap(rdev);
73 
74 	rv = regmap_read(map, rdesc->regB, &val);
75 	if (rv)
76 		return rv;
77 
78 	en = MAX77650_REGULATOR_EN_CTRL_BITS(val);
79 
80 	return en != MAX77650_REGULATOR_DISABLED;
81 }
82 
83 static int max77650_regulator_enable(struct regulator_dev *rdev)
84 {
85 	const struct max77650_regulator_desc *rdesc;
86 	struct regmap *map;
87 
88 	rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);
89 	map = rdev_get_regmap(rdev);
90 
91 	return regmap_update_bits(map, rdesc->regB,
92 				  MAX77650_REGULATOR_EN_CTRL_MASK,
93 				  MAX77650_REGULATOR_ENABLED);
94 }
95 
96 static int max77650_regulator_disable(struct regulator_dev *rdev)
97 {
98 	const struct max77650_regulator_desc *rdesc;
99 	struct regmap *map;
100 
101 	rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);
102 	map = rdev_get_regmap(rdev);
103 
104 	return regmap_update_bits(map, rdesc->regB,
105 				  MAX77650_REGULATOR_EN_CTRL_MASK,
106 				  MAX77650_REGULATOR_DISABLED);
107 }
108 
109 static const struct regulator_ops max77650_regulator_LDO_ops = {
110 	.is_enabled		= max77650_regulator_is_enabled,
111 	.enable			= max77650_regulator_enable,
112 	.disable		= max77650_regulator_disable,
113 	.list_voltage		= regulator_list_voltage_linear,
114 	.map_voltage		= regulator_map_voltage_linear,
115 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
116 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
117 	.set_active_discharge	= regulator_set_active_discharge_regmap,
118 };
119 
120 static const struct regulator_ops max77650_regulator_SBB_ops = {
121 	.is_enabled		= max77650_regulator_is_enabled,
122 	.enable			= max77650_regulator_enable,
123 	.disable		= max77650_regulator_disable,
124 	.list_voltage		= regulator_list_voltage_linear,
125 	.map_voltage		= regulator_map_voltage_linear,
126 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
127 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
128 	.get_current_limit	= regulator_get_current_limit_regmap,
129 	.set_current_limit	= regulator_set_current_limit_regmap,
130 	.set_active_discharge	= regulator_set_active_discharge_regmap,
131 };
132 
133 /* Special case for max77651 SBB1 - pickable linear-range voltage mapping. */
134 static const struct regulator_ops max77651_SBB1_regulator_ops = {
135 	.is_enabled		= max77650_regulator_is_enabled,
136 	.enable			= max77650_regulator_enable,
137 	.disable		= max77650_regulator_disable,
138 	.list_voltage		= regulator_list_voltage_pickable_linear_range,
139 	.get_voltage_sel	= regulator_get_voltage_sel_pickable_regmap,
140 	.set_voltage_sel	= regulator_set_voltage_sel_pickable_regmap,
141 	.get_current_limit	= regulator_get_current_limit_regmap,
142 	.set_current_limit	= regulator_set_current_limit_regmap,
143 	.set_active_discharge	= regulator_set_active_discharge_regmap,
144 };
145 
146 static const struct max77650_regulator_desc max77650_LDO_desc = {
147 	.desc = {
148 		.name			= "ldo",
149 		.of_match		= of_match_ptr("ldo"),
150 		.regulators_node	= of_match_ptr("regulators"),
151 		.supply_name		= "in-ldo",
152 		.id			= MAX77650_REGULATOR_ID_LDO,
153 		.ops			= &max77650_regulator_LDO_ops,
154 		.min_uV			= 1350000,
155 		.uV_step		= 12500,
156 		.n_voltages		= 128,
157 		.vsel_step		= 1,
158 		.vsel_mask		= MAX77650_REGULATOR_V_LDO_MASK,
159 		.vsel_reg		= MAX77650_REG_CNFG_LDO_A,
160 		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
161 		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
162 		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
163 		.active_discharge_reg	= MAX77650_REG_CNFG_LDO_B,
164 		.enable_time		= 100,
165 		.type			= REGULATOR_VOLTAGE,
166 		.owner			= THIS_MODULE,
167 	},
168 	.regA		= MAX77650_REG_CNFG_LDO_A,
169 	.regB		= MAX77650_REG_CNFG_LDO_B,
170 };
171 
172 static const struct max77650_regulator_desc max77650_SBB0_desc = {
173 	.desc = {
174 		.name			= "sbb0",
175 		.of_match		= of_match_ptr("sbb0"),
176 		.regulators_node	= of_match_ptr("regulators"),
177 		.supply_name		= "in-sbb0",
178 		.id			= MAX77650_REGULATOR_ID_SBB0,
179 		.ops			= &max77650_regulator_SBB_ops,
180 		.min_uV			= 800000,
181 		.uV_step		= 25000,
182 		.n_voltages		= 64,
183 		.vsel_step		= 1,
184 		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
185 		.vsel_reg		= MAX77650_REG_CNFG_SBB0_A,
186 		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
187 		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
188 		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
189 		.active_discharge_reg	= MAX77650_REG_CNFG_SBB0_B,
190 		.enable_time		= 100,
191 		.type			= REGULATOR_VOLTAGE,
192 		.owner			= THIS_MODULE,
193 		.csel_reg		= MAX77650_REG_CNFG_SBB0_A,
194 		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
195 		.curr_table		= max77650_current_limit_table,
196 		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
197 	},
198 	.regA		= MAX77650_REG_CNFG_SBB0_A,
199 	.regB		= MAX77650_REG_CNFG_SBB0_B,
200 };
201 
202 static const struct max77650_regulator_desc max77650_SBB1_desc = {
203 	.desc = {
204 		.name			= "sbb1",
205 		.of_match		= of_match_ptr("sbb1"),
206 		.regulators_node	= of_match_ptr("regulators"),
207 		.supply_name		= "in-sbb1",
208 		.id			= MAX77650_REGULATOR_ID_SBB1,
209 		.ops			= &max77650_regulator_SBB_ops,
210 		.min_uV			= 800000,
211 		.uV_step		= 12500,
212 		.n_voltages		= 64,
213 		.vsel_step		= 1,
214 		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
215 		.vsel_reg		= MAX77650_REG_CNFG_SBB1_A,
216 		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
217 		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
218 		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
219 		.active_discharge_reg	= MAX77650_REG_CNFG_SBB1_B,
220 		.enable_time		= 100,
221 		.type			= REGULATOR_VOLTAGE,
222 		.owner			= THIS_MODULE,
223 		.csel_reg		= MAX77650_REG_CNFG_SBB1_A,
224 		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
225 		.curr_table		= max77650_current_limit_table,
226 		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
227 	},
228 	.regA		= MAX77650_REG_CNFG_SBB1_A,
229 	.regB		= MAX77650_REG_CNFG_SBB1_B,
230 };
231 
232 static const struct max77650_regulator_desc max77651_SBB1_desc = {
233 	.desc = {
234 		.name			= "sbb1",
235 		.of_match		= of_match_ptr("sbb1"),
236 		.regulators_node	= of_match_ptr("regulators"),
237 		.supply_name		= "in-sbb1",
238 		.id			= MAX77650_REGULATOR_ID_SBB1,
239 		.ops			= &max77651_SBB1_regulator_ops,
240 		.linear_range_selectors_bitfield	= max77651_sbb1_volt_range_sel,
241 		.linear_ranges		= max77651_sbb1_volt_ranges,
242 		.n_linear_ranges	= ARRAY_SIZE(max77651_sbb1_volt_ranges),
243 		.n_voltages		= 58,
244 		.vsel_step		= 1,
245 		.vsel_range_mask	= MAX77651_REGULATOR_V_SBB1_RANGE_MASK,
246 		.vsel_range_reg		= MAX77650_REG_CNFG_SBB1_A,
247 		.vsel_mask		= MAX77651_REGULATOR_V_SBB1_MASK,
248 		.vsel_reg		= MAX77650_REG_CNFG_SBB1_A,
249 		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
250 		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
251 		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
252 		.active_discharge_reg	= MAX77650_REG_CNFG_SBB1_B,
253 		.enable_time		= 100,
254 		.type			= REGULATOR_VOLTAGE,
255 		.owner			= THIS_MODULE,
256 		.csel_reg		= MAX77650_REG_CNFG_SBB1_A,
257 		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
258 		.curr_table		= max77650_current_limit_table,
259 		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
260 	},
261 	.regA		= MAX77650_REG_CNFG_SBB1_A,
262 	.regB		= MAX77650_REG_CNFG_SBB1_B,
263 };
264 
265 static const struct max77650_regulator_desc max77650_SBB2_desc = {
266 	.desc = {
267 		.name			= "sbb2",
268 		.of_match		= of_match_ptr("sbb2"),
269 		.regulators_node	= of_match_ptr("regulators"),
270 		.supply_name		= "in-sbb0",
271 		.id			= MAX77650_REGULATOR_ID_SBB2,
272 		.ops			= &max77650_regulator_SBB_ops,
273 		.min_uV			= 800000,
274 		.uV_step		= 50000,
275 		.n_voltages		= 64,
276 		.vsel_step		= 1,
277 		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
278 		.vsel_reg		= MAX77650_REG_CNFG_SBB2_A,
279 		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
280 		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
281 		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
282 		.active_discharge_reg	= MAX77650_REG_CNFG_SBB2_B,
283 		.enable_time		= 100,
284 		.type			= REGULATOR_VOLTAGE,
285 		.owner			= THIS_MODULE,
286 		.csel_reg		= MAX77650_REG_CNFG_SBB2_A,
287 		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
288 		.curr_table		= max77650_current_limit_table,
289 		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
290 	},
291 	.regA		= MAX77650_REG_CNFG_SBB2_A,
292 	.regB		= MAX77650_REG_CNFG_SBB2_B,
293 };
294 
295 static const struct max77650_regulator_desc max77651_SBB2_desc = {
296 	.desc = {
297 		.name			= "sbb2",
298 		.of_match		= of_match_ptr("sbb2"),
299 		.regulators_node	= of_match_ptr("regulators"),
300 		.supply_name		= "in-sbb0",
301 		.id			= MAX77650_REGULATOR_ID_SBB2,
302 		.ops			= &max77650_regulator_SBB_ops,
303 		.min_uV			= 2400000,
304 		.uV_step		= 50000,
305 		.n_voltages		= 64,
306 		.vsel_step		= 1,
307 		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
308 		.vsel_reg		= MAX77650_REG_CNFG_SBB2_A,
309 		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
310 		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
311 		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
312 		.active_discharge_reg	= MAX77650_REG_CNFG_SBB2_B,
313 		.enable_time		= 100,
314 		.type			= REGULATOR_VOLTAGE,
315 		.owner			= THIS_MODULE,
316 		.csel_reg		= MAX77650_REG_CNFG_SBB2_A,
317 		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
318 		.curr_table		= max77650_current_limit_table,
319 		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
320 	},
321 	.regA		= MAX77650_REG_CNFG_SBB2_A,
322 	.regB		= MAX77650_REG_CNFG_SBB2_B,
323 };
324 
325 static int max77650_regulator_probe(struct platform_device *pdev)
326 {
327 	const struct max77650_regulator_desc **rdescs;
328 	const struct max77650_regulator_desc *rdesc;
329 	struct regulator_config config = { };
330 	struct device *dev, *parent;
331 	struct regulator_dev *rdev;
332 	struct regmap *map;
333 	unsigned int val;
334 	int i, rv;
335 
336 	dev = &pdev->dev;
337 	parent = dev->parent;
338 
339 	if (!dev->of_node)
340 		dev->of_node = parent->of_node;
341 
342 	rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS,
343 			      sizeof(*rdescs), GFP_KERNEL);
344 	if (!rdescs)
345 		return -ENOMEM;
346 
347 	map = dev_get_regmap(parent, NULL);
348 	if (!map)
349 		return -ENODEV;
350 
351 	rv = regmap_read(map, MAX77650_REG_CID, &val);
352 	if (rv)
353 		return rv;
354 
355 	rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc;
356 	rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc;
357 
358 	switch (MAX77650_CID_BITS(val)) {
359 	case MAX77650_CID_77650A:
360 	case MAX77650_CID_77650C:
361 		rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc;
362 		rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc;
363 		break;
364 	case MAX77650_CID_77651A:
365 	case MAX77650_CID_77651B:
366 		rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc;
367 		rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc;
368 		break;
369 	default:
370 		return -ENODEV;
371 	}
372 
373 	config.dev = parent;
374 
375 	for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) {
376 		rdesc = rdescs[i];
377 
378 		rdev = devm_regulator_register(dev, &rdesc->desc, &config);
379 		if (IS_ERR(rdev))
380 			return PTR_ERR(rdev);
381 	}
382 
383 	return 0;
384 }
385 
386 static const struct of_device_id max77650_regulator_of_match[] = {
387 	{ .compatible = "maxim,max77650-regulator" },
388 	{ }
389 };
390 MODULE_DEVICE_TABLE(of, max77650_regulator_of_match);
391 
392 static struct platform_driver max77650_regulator_driver = {
393 	.driver = {
394 		.name = "max77650-regulator",
395 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
396 		.of_match_table = max77650_regulator_of_match,
397 	},
398 	.probe = max77650_regulator_probe,
399 };
400 module_platform_driver(max77650_regulator_driver);
401 
402 MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver");
403 MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
404 MODULE_LICENSE("GPL v2");
405 MODULE_ALIAS("platform:max77650-regulator");
406