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