1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * max8907-regulator.c -- support regulators in max8907
4 *
5 * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
6 * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved.
7 *
8 * Portions based on drivers/regulator/tps65910-regulator.c,
9 *     Copyright 2010 Texas Instruments Inc.
10 *     Author: Graeme Gregory <gg@slimlogic.co.uk>
11 *     Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
12 */
13
14#include <linux/err.h>
15#include <linux/init.h>
16#include <linux/mfd/core.h>
17#include <linux/mfd/max8907.h>
18#include <linux/module.h>
19#include <linux/of.h>
20#include <linux/platform_device.h>
21#include <linux/regulator/driver.h>
22#include <linux/regulator/machine.h>
23#include <linux/regulator/of_regulator.h>
24#include <linux/regmap.h>
25#include <linux/slab.h>
26
27#define MAX8907_II2RR_VERSION_MASK	0xF0
28#define MAX8907_II2RR_VERSION_REV_A	0x00
29#define MAX8907_II2RR_VERSION_REV_B	0x10
30#define MAX8907_II2RR_VERSION_REV_C	0x30
31
32struct max8907_regulator {
33	struct regulator_desc desc[MAX8907_NUM_REGULATORS];
34};
35
36#define REG_MBATT() \
37	[MAX8907_MBATT] = { \
38		.name = "MBATT", \
39		.supply_name = "mbatt", \
40		.id = MAX8907_MBATT, \
41		.ops = &max8907_mbatt_ops, \
42		.type = REGULATOR_VOLTAGE, \
43		.owner = THIS_MODULE, \
44	}
45
46#define REG_LDO(ids, supply, base, min, max, step) \
47	[MAX8907_##ids] = { \
48		.name = #ids, \
49		.supply_name = supply, \
50		.id = MAX8907_##ids, \
51		.n_voltages = ((max) - (min)) / (step) + 1, \
52		.ops = &max8907_ldo_ops, \
53		.type = REGULATOR_VOLTAGE, \
54		.owner = THIS_MODULE, \
55		.min_uV = (min), \
56		.uV_step = (step), \
57		.vsel_reg = (base) + MAX8907_VOUT, \
58		.vsel_mask = 0x3f, \
59		.enable_reg = (base) + MAX8907_CTL, \
60		.enable_mask = MAX8907_MASK_LDO_EN, \
61	}
62
63#define REG_FIXED(ids, supply, voltage) \
64	[MAX8907_##ids] = { \
65		.name = #ids, \
66		.supply_name = supply, \
67		.id = MAX8907_##ids, \
68		.n_voltages = 1, \
69		.ops = &max8907_fixed_ops, \
70		.type = REGULATOR_VOLTAGE, \
71		.owner = THIS_MODULE, \
72		.min_uV = (voltage), \
73	}
74
75#define REG_OUT5V(ids, supply, base, voltage) \
76	[MAX8907_##ids] = { \
77		.name = #ids, \
78		.supply_name = supply, \
79		.id = MAX8907_##ids, \
80		.n_voltages = 1, \
81		.ops = &max8907_out5v_ops, \
82		.type = REGULATOR_VOLTAGE, \
83		.owner = THIS_MODULE, \
84		.min_uV = (voltage), \
85		.enable_reg = (base), \
86		.enable_mask = MAX8907_MASK_OUT5V_EN, \
87	}
88
89#define REG_BBAT(ids, supply, base, min, max, step) \
90	[MAX8907_##ids] = { \
91		.name = #ids, \
92		.supply_name = supply, \
93		.id = MAX8907_##ids, \
94		.n_voltages = ((max) - (min)) / (step) + 1, \
95		.ops = &max8907_bbat_ops, \
96		.type = REGULATOR_VOLTAGE, \
97		.owner = THIS_MODULE, \
98		.min_uV = (min), \
99		.uV_step = (step), \
100		.vsel_reg = (base), \
101		.vsel_mask = MAX8907_MASK_VBBATTCV, \
102	}
103
104#define LDO_750_50(id, supply, base) REG_LDO(id, supply, (base), \
105			750000, 3900000, 50000)
106#define LDO_650_25(id, supply, base) REG_LDO(id, supply, (base), \
107			650000, 2225000, 25000)
108
109static const struct regulator_ops max8907_mbatt_ops = {
110};
111
112static const struct regulator_ops max8907_ldo_ops = {
113	.list_voltage = regulator_list_voltage_linear,
114	.set_voltage_sel = regulator_set_voltage_sel_regmap,
115	.get_voltage_sel = regulator_get_voltage_sel_regmap,
116	.enable = regulator_enable_regmap,
117	.disable = regulator_disable_regmap,
118	.is_enabled = regulator_is_enabled_regmap,
119};
120
121static const struct regulator_ops max8907_ldo_hwctl_ops = {
122	.list_voltage = regulator_list_voltage_linear,
123	.set_voltage_sel = regulator_set_voltage_sel_regmap,
124	.get_voltage_sel = regulator_get_voltage_sel_regmap,
125};
126
127static const struct regulator_ops max8907_fixed_ops = {
128	.list_voltage = regulator_list_voltage_linear,
129};
130
131static const struct regulator_ops max8907_out5v_ops = {
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
138static const struct regulator_ops max8907_out5v_hwctl_ops = {
139	.list_voltage = regulator_list_voltage_linear,
140};
141
142static const struct regulator_ops max8907_bbat_ops = {
143	.list_voltage = regulator_list_voltage_linear,
144	.set_voltage_sel = regulator_set_voltage_sel_regmap,
145	.get_voltage_sel = regulator_get_voltage_sel_regmap,
146};
147
148static const struct regulator_desc max8907_regulators[] = {
149	REG_MBATT(),
150	REG_LDO(SD1, "in-v1", MAX8907_REG_SDCTL1, 650000, 2225000, 25000),
151	REG_LDO(SD2, "in-v2", MAX8907_REG_SDCTL2, 637500, 1425000, 12500),
152	REG_LDO(SD3, "in-v3", MAX8907_REG_SDCTL3, 750000, 3900000, 50000),
153	LDO_750_50(LDO1, "in1", MAX8907_REG_LDOCTL1),
154	LDO_650_25(LDO2, "in2", MAX8907_REG_LDOCTL2),
155	LDO_650_25(LDO3, "in3", MAX8907_REG_LDOCTL3),
156	LDO_750_50(LDO4, "in4", MAX8907_REG_LDOCTL4),
157	LDO_750_50(LDO5, "in5", MAX8907_REG_LDOCTL5),
158	LDO_750_50(LDO6, "in6", MAX8907_REG_LDOCTL6),
159	LDO_750_50(LDO7, "in7", MAX8907_REG_LDOCTL7),
160	LDO_750_50(LDO8, "in8", MAX8907_REG_LDOCTL8),
161	LDO_750_50(LDO9, "in9", MAX8907_REG_LDOCTL9),
162	LDO_750_50(LDO10, "in10", MAX8907_REG_LDOCTL10),
163	LDO_750_50(LDO11, "in11", MAX8907_REG_LDOCTL11),
164	LDO_750_50(LDO12, "in12", MAX8907_REG_LDOCTL12),
165	LDO_750_50(LDO13, "in13", MAX8907_REG_LDOCTL13),
166	LDO_750_50(LDO14, "in14", MAX8907_REG_LDOCTL14),
167	LDO_750_50(LDO15, "in15", MAX8907_REG_LDOCTL15),
168	LDO_750_50(LDO16, "in16", MAX8907_REG_LDOCTL16),
169	LDO_650_25(LDO17, "in17", MAX8907_REG_LDOCTL17),
170	LDO_650_25(LDO18, "in18", MAX8907_REG_LDOCTL18),
171	LDO_750_50(LDO19, "in19", MAX8907_REG_LDOCTL19),
172	LDO_750_50(LDO20, "in20", MAX8907_REG_LDOCTL20),
173	REG_OUT5V(OUT5V, "mbatt", MAX8907_REG_OUT5VEN, 5000000),
174	REG_OUT5V(OUT33V, "mbatt",  MAX8907_REG_OUT33VEN, 3300000),
175	REG_BBAT(BBAT, "MBATT", MAX8907_REG_BBAT_CNFG,
176						2400000, 3000000, 200000),
177	REG_FIXED(SDBY, "MBATT", 1200000),
178	REG_FIXED(VRTC, "MBATT", 3300000),
179};
180
181#ifdef CONFIG_OF
182
183#define MATCH(_name, _id) \
184	[MAX8907_##_id] = { \
185		.name = #_name, \
186		.driver_data = (void *)&max8907_regulators[MAX8907_##_id], \
187	}
188
189static struct of_regulator_match max8907_matches[] = {
190	MATCH(mbatt, MBATT),
191	MATCH(sd1, SD1),
192	MATCH(sd2, SD2),
193	MATCH(sd3, SD3),
194	MATCH(ldo1, LDO1),
195	MATCH(ldo2, LDO2),
196	MATCH(ldo3, LDO3),
197	MATCH(ldo4, LDO4),
198	MATCH(ldo5, LDO5),
199	MATCH(ldo6, LDO6),
200	MATCH(ldo7, LDO7),
201	MATCH(ldo8, LDO8),
202	MATCH(ldo9, LDO9),
203	MATCH(ldo10, LDO10),
204	MATCH(ldo11, LDO11),
205	MATCH(ldo12, LDO12),
206	MATCH(ldo13, LDO13),
207	MATCH(ldo14, LDO14),
208	MATCH(ldo15, LDO15),
209	MATCH(ldo16, LDO16),
210	MATCH(ldo17, LDO17),
211	MATCH(ldo18, LDO18),
212	MATCH(ldo19, LDO19),
213	MATCH(ldo20, LDO20),
214	MATCH(out5v, OUT5V),
215	MATCH(out33v, OUT33V),
216	MATCH(bbat, BBAT),
217	MATCH(sdby, SDBY),
218	MATCH(vrtc, VRTC),
219};
220
221static int max8907_regulator_parse_dt(struct platform_device *pdev)
222{
223	struct device_node *np, *regulators;
224	int ret;
225
226	np = pdev->dev.parent->of_node;
227	if (!np)
228		return 0;
229
230	regulators = of_get_child_by_name(np, "regulators");
231	if (!regulators) {
232		dev_err(&pdev->dev, "regulators node not found\n");
233		return -EINVAL;
234	}
235
236	ret = of_regulator_match(&pdev->dev, regulators, max8907_matches,
237				 ARRAY_SIZE(max8907_matches));
238	of_node_put(regulators);
239	if (ret < 0) {
240		dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
241			ret);
242		return ret;
243	}
244
245	return 0;
246}
247
248static inline struct regulator_init_data *match_init_data(int index)
249{
250	return max8907_matches[index].init_data;
251}
252
253static inline struct device_node *match_of_node(int index)
254{
255	return max8907_matches[index].of_node;
256}
257#else
258static int max8907_regulator_parse_dt(struct platform_device *pdev)
259{
260	return 0;
261}
262
263static inline struct regulator_init_data *match_init_data(int index)
264{
265	return NULL;
266}
267
268static inline struct device_node *match_of_node(int index)
269{
270	return NULL;
271}
272#endif
273
274static int max8907_regulator_probe(struct platform_device *pdev)
275{
276	struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
277	struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
278	int ret;
279	struct max8907_regulator *pmic;
280	unsigned int val;
281	int i;
282	struct regulator_config config = {};
283	struct regulator_init_data *idata;
284	const char *mbatt_rail_name = NULL;
285
286	ret = max8907_regulator_parse_dt(pdev);
287	if (ret)
288		return ret;
289
290	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
291	if (!pmic)
292		return -ENOMEM;
293
294	platform_set_drvdata(pdev, pmic);
295
296	memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
297
298	/* Backwards compatibility with MAX8907B; SD1 uses different voltages */
299	ret = regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
300	if (ret)
301		return ret;
302
303	if ((val & MAX8907_II2RR_VERSION_MASK) ==
304	    MAX8907_II2RR_VERSION_REV_B) {
305		pmic->desc[MAX8907_SD1].min_uV = 637500;
306		pmic->desc[MAX8907_SD1].uV_step = 12500;
307		pmic->desc[MAX8907_SD1].n_voltages =
308						(1425000 - 637500) / 12500 + 1;
309	}
310
311	for (i = 0; i < MAX8907_NUM_REGULATORS; i++) {
312		struct regulator_dev *rdev;
313
314		config.dev = pdev->dev.parent;
315		if (pdata)
316			idata = pdata->init_data[i];
317		else
318			idata = match_init_data(i);
319		config.init_data = idata;
320		config.driver_data = pmic;
321		config.regmap = max8907->regmap_gen;
322		config.of_node = match_of_node(i);
323
324		switch (pmic->desc[i].id) {
325		case MAX8907_MBATT:
326			if (idata && idata->constraints.name)
327				mbatt_rail_name = idata->constraints.name;
328			else
329				mbatt_rail_name = pmic->desc[i].name;
330			break;
331		case MAX8907_BBAT:
332		case MAX8907_SDBY:
333		case MAX8907_VRTC:
334			idata->supply_regulator = mbatt_rail_name;
335			break;
336		}
337
338		if (pmic->desc[i].ops == &max8907_ldo_ops) {
339			ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
340				    &val);
341			if (ret)
342				return ret;
343
344			if ((val & MAX8907_MASK_LDO_SEQ) !=
345			    MAX8907_MASK_LDO_SEQ)
346				pmic->desc[i].ops = &max8907_ldo_hwctl_ops;
347		} else if (pmic->desc[i].ops == &max8907_out5v_ops) {
348			ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
349				    &val);
350			if (ret)
351				return ret;
352
353			if ((val & (MAX8907_MASK_OUT5V_VINEN |
354						MAX8907_MASK_OUT5V_ENSRC)) !=
355			    MAX8907_MASK_OUT5V_ENSRC)
356				pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
357		}
358
359		rdev = devm_regulator_register(&pdev->dev,
360						&pmic->desc[i], &config);
361		if (IS_ERR(rdev)) {
362			dev_err(&pdev->dev,
363				"failed to register %s regulator\n",
364				pmic->desc[i].name);
365			return PTR_ERR(rdev);
366		}
367	}
368
369	return 0;
370}
371
372static struct platform_driver max8907_regulator_driver = {
373	.driver = {
374		   .name = "max8907-regulator",
375		   .probe_type = PROBE_PREFER_ASYNCHRONOUS,
376		   },
377	.probe = max8907_regulator_probe,
378};
379
380static int __init max8907_regulator_init(void)
381{
382	return platform_driver_register(&max8907_regulator_driver);
383}
384
385subsys_initcall(max8907_regulator_init);
386
387static void __exit max8907_reg_exit(void)
388{
389	platform_driver_unregister(&max8907_regulator_driver);
390}
391
392module_exit(max8907_reg_exit);
393
394MODULE_DESCRIPTION("MAX8907 regulator driver");
395MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
396MODULE_LICENSE("GPL v2");
397MODULE_ALIAS("platform:max8907-regulator");
398