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