Merge commit '6bb27d7349db51b50c40534710fe164ca0d58902' into omap-timer-for-v3.10
[deliverable/linux.git] / drivers / regulator / max8907-regulator.c
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
35 struct max8907_regulator {
36 struct regulator_desc desc[MAX8907_NUM_REGULATORS];
37 struct regulator_dev *rdev[MAX8907_NUM_REGULATORS];
38 };
39
40 #define REG_MBATT() \
41 [MAX8907_MBATT] = { \
42 .name = "MBATT", \
43 .supply_name = "mbatt", \
44 .id = MAX8907_MBATT, \
45 .ops = &max8907_mbatt_ops, \
46 .type = REGULATOR_VOLTAGE, \
47 .owner = THIS_MODULE, \
48 }
49
50 #define REG_LDO(ids, supply, base, min, max, step) \
51 [MAX8907_##ids] = { \
52 .name = #ids, \
53 .supply_name = supply, \
54 .id = MAX8907_##ids, \
55 .n_voltages = ((max) - (min)) / (step) + 1, \
56 .ops = &max8907_ldo_ops, \
57 .type = REGULATOR_VOLTAGE, \
58 .owner = THIS_MODULE, \
59 .min_uV = (min), \
60 .uV_step = (step), \
61 .vsel_reg = (base) + MAX8907_VOUT, \
62 .vsel_mask = 0x3f, \
63 .enable_reg = (base) + MAX8907_CTL, \
64 .enable_mask = MAX8907_MASK_LDO_EN, \
65 }
66
67 #define REG_FIXED(ids, supply, voltage) \
68 [MAX8907_##ids] = { \
69 .name = #ids, \
70 .supply_name = supply, \
71 .id = MAX8907_##ids, \
72 .n_voltages = 1, \
73 .ops = &max8907_fixed_ops, \
74 .type = REGULATOR_VOLTAGE, \
75 .owner = THIS_MODULE, \
76 .min_uV = (voltage), \
77 }
78
79 #define REG_OUT5V(ids, supply, base, voltage) \
80 [MAX8907_##ids] = { \
81 .name = #ids, \
82 .supply_name = supply, \
83 .id = MAX8907_##ids, \
84 .n_voltages = 1, \
85 .ops = &max8907_out5v_ops, \
86 .type = REGULATOR_VOLTAGE, \
87 .owner = THIS_MODULE, \
88 .min_uV = (voltage), \
89 .enable_reg = (base), \
90 .enable_mask = MAX8907_MASK_OUT5V_EN, \
91 }
92
93 #define REG_BBAT(ids, supply, base, min, max, step) \
94 [MAX8907_##ids] = { \
95 .name = #ids, \
96 .supply_name = supply, \
97 .id = MAX8907_##ids, \
98 .n_voltages = ((max) - (min)) / (step) + 1, \
99 .ops = &max8907_bbat_ops, \
100 .type = REGULATOR_VOLTAGE, \
101 .owner = THIS_MODULE, \
102 .min_uV = (min), \
103 .uV_step = (step), \
104 .vsel_reg = (base), \
105 .vsel_mask = MAX8907_MASK_VBBATTCV, \
106 }
107
108 #define LDO_750_50(id, supply, base) REG_LDO(id, supply, (base), \
109 750000, 3900000, 50000)
110 #define LDO_650_25(id, supply, base) REG_LDO(id, supply, (base), \
111 650000, 2225000, 25000)
112
113 static struct regulator_ops max8907_mbatt_ops = {
114 };
115
116 static struct regulator_ops max8907_ldo_ops = {
117 .list_voltage = regulator_list_voltage_linear,
118 .set_voltage_sel = regulator_set_voltage_sel_regmap,
119 .get_voltage_sel = regulator_get_voltage_sel_regmap,
120 .enable = regulator_enable_regmap,
121 .disable = regulator_disable_regmap,
122 .is_enabled = regulator_is_enabled_regmap,
123 };
124
125 static struct regulator_ops max8907_ldo_hwctl_ops = {
126 .list_voltage = regulator_list_voltage_linear,
127 .set_voltage_sel = regulator_set_voltage_sel_regmap,
128 .get_voltage_sel = regulator_get_voltage_sel_regmap,
129 };
130
131 static struct regulator_ops max8907_fixed_ops = {
132 .list_voltage = regulator_list_voltage_linear,
133 };
134
135 static struct regulator_ops max8907_out5v_ops = {
136 .list_voltage = regulator_list_voltage_linear,
137 .enable = regulator_enable_regmap,
138 .disable = regulator_disable_regmap,
139 .is_enabled = regulator_is_enabled_regmap,
140 };
141
142 static struct regulator_ops max8907_out5v_hwctl_ops = {
143 .list_voltage = regulator_list_voltage_linear,
144 };
145
146 static struct regulator_ops max8907_bbat_ops = {
147 .list_voltage = regulator_list_voltage_linear,
148 .set_voltage_sel = regulator_set_voltage_sel_regmap,
149 .get_voltage_sel = regulator_get_voltage_sel_regmap,
150 };
151
152 static struct regulator_desc max8907_regulators[] = {
153 REG_MBATT(),
154 REG_LDO(SD1, "in-v1", MAX8907_REG_SDCTL1, 650000, 2225000, 25000),
155 REG_LDO(SD2, "in-v2", MAX8907_REG_SDCTL2, 637500, 1425000, 12500),
156 REG_LDO(SD3, "in-v3", MAX8907_REG_SDCTL3, 750000, 3900000, 50000),
157 LDO_750_50(LDO1, "in1", MAX8907_REG_LDOCTL1),
158 LDO_650_25(LDO2, "in2", MAX8907_REG_LDOCTL2),
159 LDO_650_25(LDO3, "in3", MAX8907_REG_LDOCTL3),
160 LDO_750_50(LDO4, "in4", MAX8907_REG_LDOCTL4),
161 LDO_750_50(LDO5, "in5", MAX8907_REG_LDOCTL5),
162 LDO_750_50(LDO6, "in6", MAX8907_REG_LDOCTL6),
163 LDO_750_50(LDO7, "in7", MAX8907_REG_LDOCTL7),
164 LDO_750_50(LDO8, "in8", MAX8907_REG_LDOCTL8),
165 LDO_750_50(LDO9, "in9", MAX8907_REG_LDOCTL9),
166 LDO_750_50(LDO10, "in10", MAX8907_REG_LDOCTL10),
167 LDO_750_50(LDO11, "in11", MAX8907_REG_LDOCTL11),
168 LDO_750_50(LDO12, "in12", MAX8907_REG_LDOCTL12),
169 LDO_750_50(LDO13, "in13", MAX8907_REG_LDOCTL13),
170 LDO_750_50(LDO14, "in14", MAX8907_REG_LDOCTL14),
171 LDO_750_50(LDO15, "in15", MAX8907_REG_LDOCTL15),
172 LDO_750_50(LDO16, "in16", MAX8907_REG_LDOCTL16),
173 LDO_650_25(LDO17, "in17", MAX8907_REG_LDOCTL17),
174 LDO_650_25(LDO18, "in18", MAX8907_REG_LDOCTL18),
175 LDO_750_50(LDO19, "in19", MAX8907_REG_LDOCTL19),
176 LDO_750_50(LDO20, "in20", MAX8907_REG_LDOCTL20),
177 REG_OUT5V(OUT5V, "mbatt", MAX8907_REG_OUT5VEN, 5000000),
178 REG_OUT5V(OUT33V, "mbatt", MAX8907_REG_OUT33VEN, 3300000),
179 REG_BBAT(BBAT, "MBATT", MAX8907_REG_BBAT_CNFG,
180 2400000, 3000000, 200000),
181 REG_FIXED(SDBY, "MBATT", 1200000),
182 REG_FIXED(VRTC, "MBATT", 3300000),
183 };
184
185 #ifdef CONFIG_OF
186
187 #define MATCH(_name, _id) \
188 [MAX8907_##_id] = { \
189 .name = #_name, \
190 .driver_data = (void *)&max8907_regulators[MAX8907_##_id], \
191 }
192
193 static struct of_regulator_match max8907_matches[] = {
194 MATCH(mbatt, MBATT),
195 MATCH(sd1, SD1),
196 MATCH(sd2, SD2),
197 MATCH(sd3, SD3),
198 MATCH(ldo1, LDO1),
199 MATCH(ldo2, LDO2),
200 MATCH(ldo3, LDO3),
201 MATCH(ldo4, LDO4),
202 MATCH(ldo5, LDO5),
203 MATCH(ldo6, LDO6),
204 MATCH(ldo7, LDO7),
205 MATCH(ldo8, LDO8),
206 MATCH(ldo9, LDO9),
207 MATCH(ldo10, LDO10),
208 MATCH(ldo11, LDO11),
209 MATCH(ldo12, LDO12),
210 MATCH(ldo13, LDO13),
211 MATCH(ldo14, LDO14),
212 MATCH(ldo15, LDO15),
213 MATCH(ldo16, LDO16),
214 MATCH(ldo17, LDO17),
215 MATCH(ldo18, LDO18),
216 MATCH(ldo19, LDO19),
217 MATCH(ldo20, LDO20),
218 MATCH(out5v, OUT5V),
219 MATCH(out33v, OUT33V),
220 MATCH(bbat, BBAT),
221 MATCH(sdby, SDBY),
222 MATCH(vrtc, VRTC),
223 };
224
225 static int max8907_regulator_parse_dt(struct platform_device *pdev)
226 {
227 struct device_node *np = pdev->dev.parent->of_node;
228 struct device_node *regulators;
229 int ret;
230
231 if (!pdev->dev.parent->of_node)
232 return 0;
233
234 regulators = of_find_node_by_name(np, "regulators");
235 if (!regulators) {
236 dev_err(&pdev->dev, "regulators node not found\n");
237 return -EINVAL;
238 }
239
240 ret = of_regulator_match(&pdev->dev, regulators, max8907_matches,
241 ARRAY_SIZE(max8907_matches));
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
251 static inline struct regulator_init_data *match_init_data(int index)
252 {
253 return max8907_matches[index].init_data;
254 }
255
256 static inline struct device_node *match_of_node(int index)
257 {
258 return max8907_matches[index].of_node;
259 }
260 #else
261 static int max8907_regulator_parse_dt(struct platform_device *pdev)
262 {
263 return 0;
264 }
265
266 static inline struct regulator_init_data *match_init_data(int index)
267 {
268 return NULL;
269 }
270
271 static inline struct device_node *match_of_node(int index)
272 {
273 return NULL;
274 }
275 #endif
276
277 static 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 dev_err(&pdev->dev, "Failed to alloc pmic\n");
296 return -ENOMEM;
297 }
298 platform_set_drvdata(pdev, pmic);
299
300 memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
301
302 /* Backwards compatibility with MAX8907B; SD1 uses different voltages */
303 regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
304 if ((val & MAX8907_II2RR_VERSION_MASK) ==
305 MAX8907_II2RR_VERSION_REV_B) {
306 pmic->desc[MAX8907_SD1].min_uV = 637500;
307 pmic->desc[MAX8907_SD1].uV_step = 12500;
308 pmic->desc[MAX8907_SD1].n_voltages =
309 (1425000 - 637500) / 12500 + 1;
310 }
311
312 for (i = 0; i < MAX8907_NUM_REGULATORS; i++) {
313 config.dev = pdev->dev.parent;
314 if (pdata)
315 idata = pdata->init_data[i];
316 else
317 idata = match_init_data(i);
318 config.init_data = idata;
319 config.driver_data = pmic;
320 config.regmap = max8907->regmap_gen;
321 config.of_node = match_of_node(i);
322
323 switch (pmic->desc[i].id) {
324 case MAX8907_MBATT:
325 if (idata && idata->constraints.name)
326 mbatt_rail_name = idata->constraints.name;
327 else
328 mbatt_rail_name = pmic->desc[i].name;
329 break;
330 case MAX8907_BBAT:
331 case MAX8907_SDBY:
332 case MAX8907_VRTC:
333 idata->supply_regulator = mbatt_rail_name;
334 break;
335 }
336
337 if (pmic->desc[i].ops == &max8907_ldo_ops) {
338 regmap_read(config.regmap, pmic->desc[i].enable_reg,
339 &val);
340 if ((val & MAX8907_MASK_LDO_SEQ) !=
341 MAX8907_MASK_LDO_SEQ)
342 pmic->desc[i].ops = &max8907_ldo_hwctl_ops;
343 } else if (pmic->desc[i].ops == &max8907_out5v_ops) {
344 regmap_read(config.regmap, pmic->desc[i].enable_reg,
345 &val);
346 if ((val & (MAX8907_MASK_OUT5V_VINEN |
347 MAX8907_MASK_OUT5V_ENSRC)) !=
348 MAX8907_MASK_OUT5V_ENSRC)
349 pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
350 }
351
352 pmic->rdev[i] = regulator_register(&pmic->desc[i], &config);
353 if (IS_ERR(pmic->rdev[i])) {
354 dev_err(&pdev->dev,
355 "failed to register %s regulator\n",
356 pmic->desc[i].name);
357 ret = PTR_ERR(pmic->rdev[i]);
358 goto err_unregister_regulator;
359 }
360 }
361
362 return 0;
363
364 err_unregister_regulator:
365 while (--i >= 0)
366 regulator_unregister(pmic->rdev[i]);
367 return ret;
368 }
369
370 static int max8907_regulator_remove(struct platform_device *pdev)
371 {
372 struct max8907_regulator *pmic = platform_get_drvdata(pdev);
373 int i;
374
375 for (i = 0; i < MAX8907_NUM_REGULATORS; i++)
376 regulator_unregister(pmic->rdev[i]);
377
378 return 0;
379 }
380
381 static struct platform_driver max8907_regulator_driver = {
382 .driver = {
383 .name = "max8907-regulator",
384 .owner = THIS_MODULE,
385 },
386 .probe = max8907_regulator_probe,
387 .remove = max8907_regulator_remove,
388 };
389
390 static int __init max8907_regulator_init(void)
391 {
392 return platform_driver_register(&max8907_regulator_driver);
393 }
394
395 subsys_initcall(max8907_regulator_init);
396
397 static void __exit max8907_reg_exit(void)
398 {
399 platform_driver_unregister(&max8907_regulator_driver);
400 }
401
402 module_exit(max8907_reg_exit);
403
404 MODULE_DESCRIPTION("MAX8907 regulator driver");
405 MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
406 MODULE_LICENSE("GPL v2");
407 MODULE_ALIAS("platform:max8907-regulator");
This page took 0.041002 seconds and 6 git commands to generate.