Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
max8907-regulator.c
Go to the documentation of this file.
1 /*
2  * max8907-regulator.c -- support regulators in max8907
3  *
4  * Copyright (C) 2010 Gyungoh Yoo <[email protected]>
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 <[email protected]>
10  * Author: Jorge Eduardo Candelaria <[email protected]>
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>
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 
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.parent, regulators,
241  max8907_matches,
242  ARRAY_SIZE(max8907_matches));
243  if (ret < 0) {
244  dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
245  ret);
246  return ret;
247  }
248 
249  return 0;
250 }
251 
252 static inline struct regulator_init_data *match_init_data(int index)
253 {
254  return max8907_matches[index].init_data;
255 }
256 
257 static inline struct device_node *match_of_node(int index)
258 {
259  return max8907_matches[index].of_node;
260 }
261 #else
262 static int max8907_regulator_parse_dt(struct platform_device *pdev)
263 {
264  return 0;
265 }
266 
267 static inline struct regulator_init_data *match_init_data(int index)
268 {
269  return NULL;
270 }
271 
272 static inline struct device_node *match_of_node(int index)
273 {
274  return NULL;
275 }
276 #endif
277 
278 static __devinit int max8907_regulator_probe(struct platform_device *pdev)
279 {
280  struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
281  struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
282  int ret;
283  struct max8907_regulator *pmic;
284  unsigned int val;
285  int i;
286  struct regulator_config config = {};
287  struct regulator_init_data *idata;
288  const char *mbatt_rail_name = NULL;
289 
290  ret = max8907_regulator_parse_dt(pdev);
291  if (ret)
292  return ret;
293 
294  pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
295  if (!pmic) {
296  dev_err(&pdev->dev, "Failed to alloc pmic\n");
297  return -ENOMEM;
298  }
299  platform_set_drvdata(pdev, pmic);
300 
301  memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
302 
303  /* Backwards compatibility with MAX8907B; SD1 uses different voltages */
304  regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
305  if ((val & MAX8907_II2RR_VERSION_MASK) ==
307  pmic->desc[MAX8907_SD1].min_uV = 637500;
308  pmic->desc[MAX8907_SD1].uV_step = 12500;
309  pmic->desc[MAX8907_SD1].n_voltages =
310  (1425000 - 637500) / 12500 + 1;
311  }
312 
313  for (i = 0; i < MAX8907_NUM_REGULATORS; i++) {
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 |
350  pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
351  }
352 
353  pmic->rdev[i] = regulator_register(&pmic->desc[i], &config);
354  if (IS_ERR(pmic->rdev[i])) {
355  dev_err(&pdev->dev,
356  "failed to register %s regulator\n",
357  pmic->desc[i].name);
358  ret = PTR_ERR(pmic->rdev[i]);
359  goto err_unregister_regulator;
360  }
361  }
362 
363  return 0;
364 
365 err_unregister_regulator:
366  while (--i >= 0)
367  regulator_unregister(pmic->rdev[i]);
368  return ret;
369 }
370 
371 static __devexit int max8907_regulator_remove(struct platform_device *pdev)
372 {
373  struct max8907_regulator *pmic = platform_get_drvdata(pdev);
374  int i;
375 
376  for (i = 0; i < MAX8907_NUM_REGULATORS; i++)
377  regulator_unregister(pmic->rdev[i]);
378 
379  return 0;
380 }
381 
382 static struct platform_driver max8907_regulator_driver = {
383  .driver = {
384  .name = "max8907-regulator",
385  .owner = THIS_MODULE,
386  },
387  .probe = max8907_regulator_probe,
388  .remove = __devexit_p(max8907_regulator_remove),
389 };
390 
391 static int __init max8907_regulator_init(void)
392 {
393  return platform_driver_register(&max8907_regulator_driver);
394 }
395 
396 subsys_initcall(max8907_regulator_init);
397 
398 static void __exit max8907_reg_exit(void)
399 {
400  platform_driver_unregister(&max8907_regulator_driver);
401 }
402 
403 module_exit(max8907_reg_exit);
404 
405 MODULE_DESCRIPTION("MAX8907 regulator driver");
406 MODULE_AUTHOR("Gyungoh Yoo <[email protected]>");
407 MODULE_LICENSE("GPL v2");
408 MODULE_ALIAS("platform:max8907-regulator");