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