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