Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
s2mps11.c
Go to the documentation of this file.
1 /*
2  * s2mps11.c
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd
5  * http://www.samsung.com
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; either version 2 of the License, or (at your
10  * option) any later version.
11  *
12  */
13 
14 #include <linux/bug.h>
15 #include <linux/delay.h>
16 #include <linux/err.h>
17 #include <linux/gpio.h>
18 #include <linux/slab.h>
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <linux/regulator/driver.h>
23 #include <linux/mfd/samsung/core.h>
25 
26 struct s2mps11_info {
28 
35 
36  bool buck6_ramp;
37  bool buck2_ramp;
38  bool buck3_ramp;
39  bool buck4_ramp;
40 };
41 
42 static int get_ramp_delay(int ramp_delay)
43 {
44  unsigned char cnt = 0;
45 
46  ramp_delay /= 6;
47 
48  while (true) {
49  ramp_delay = ramp_delay >> 1;
50  if (ramp_delay == 0)
51  break;
52  cnt++;
53  }
54  return cnt;
55 }
56 
57 static struct regulator_ops s2mps11_ldo_ops = {
58  .list_voltage = regulator_list_voltage_linear,
59  .map_voltage = regulator_map_voltage_linear,
60  .is_enabled = regulator_is_enabled_regmap,
61  .enable = regulator_enable_regmap,
62  .disable = regulator_disable_regmap,
63  .get_voltage_sel = regulator_get_voltage_sel_regmap,
64  .set_voltage_sel = regulator_set_voltage_sel_regmap,
65  .set_voltage_time_sel = regulator_set_voltage_time_sel,
66 };
67 
68 static struct regulator_ops s2mps11_buck_ops = {
69  .list_voltage = regulator_list_voltage_linear,
70  .map_voltage = regulator_map_voltage_linear,
71  .is_enabled = regulator_is_enabled_regmap,
72  .enable = regulator_enable_regmap,
73  .disable = regulator_disable_regmap,
74  .get_voltage_sel = regulator_get_voltage_sel_regmap,
75  .set_voltage_sel = regulator_set_voltage_sel_regmap,
76  .set_voltage_time_sel = regulator_set_voltage_time_sel,
77 };
78 
79 #define regulator_desc_ldo1(num) { \
80  .name = "LDO"#num, \
81  .id = S2MPS11_LDO##num, \
82  .ops = &s2mps11_ldo_ops, \
83  .type = REGULATOR_VOLTAGE, \
84  .owner = THIS_MODULE, \
85  .min_uV = S2MPS11_LDO_MIN, \
86  .uV_step = S2MPS11_LDO_STEP1, \
87  .n_voltages = S2MPS11_LDO_N_VOLTAGES, \
88  .vsel_reg = S2MPS11_REG_L1CTRL + num - 1, \
89  .vsel_mask = S2MPS11_LDO_VSEL_MASK, \
90  .enable_reg = S2MPS11_REG_L1CTRL + num - 1, \
91  .enable_mask = S2MPS11_ENABLE_MASK \
92 }
93 #define regulator_desc_ldo2(num) { \
94  .name = "LDO"#num, \
95  .id = S2MPS11_LDO##num, \
96  .ops = &s2mps11_ldo_ops, \
97  .type = REGULATOR_VOLTAGE, \
98  .owner = THIS_MODULE, \
99  .min_uV = S2MPS11_LDO_MIN, \
100  .uV_step = S2MPS11_LDO_STEP2, \
101  .n_voltages = S2MPS11_LDO_N_VOLTAGES, \
102  .vsel_reg = S2MPS11_REG_L1CTRL + num - 1, \
103  .vsel_mask = S2MPS11_LDO_VSEL_MASK, \
104  .enable_reg = S2MPS11_REG_L1CTRL + num - 1, \
105  .enable_mask = S2MPS11_ENABLE_MASK \
106 }
107 
108 #define regulator_desc_buck1_4(num) { \
109  .name = "BUCK"#num, \
110  .id = S2MPS11_BUCK##num, \
111  .ops = &s2mps11_buck_ops, \
112  .type = REGULATOR_VOLTAGE, \
113  .owner = THIS_MODULE, \
114  .min_uV = S2MPS11_BUCK_MIN1, \
115  .uV_step = S2MPS11_BUCK_STEP1, \
116  .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \
117  .vsel_reg = S2MPS11_REG_B1CTRL2 + (num - 1) * 2, \
118  .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \
119  .enable_reg = S2MPS11_REG_B1CTRL1 + (num - 1) * 2, \
120  .enable_mask = S2MPS11_ENABLE_MASK \
121 }
122 
123 #define regulator_desc_buck5 { \
124  .name = "BUCK5", \
125  .id = S2MPS11_BUCK5, \
126  .ops = &s2mps11_buck_ops, \
127  .type = REGULATOR_VOLTAGE, \
128  .owner = THIS_MODULE, \
129  .min_uV = S2MPS11_BUCK_MIN1, \
130  .uV_step = S2MPS11_BUCK_STEP1, \
131  .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \
132  .vsel_reg = S2MPS11_REG_B5CTRL2, \
133  .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \
134  .enable_reg = S2MPS11_REG_B5CTRL1, \
135  .enable_mask = S2MPS11_ENABLE_MASK \
136 }
137 
138 #define regulator_desc_buck6_8(num) { \
139  .name = "BUCK"#num, \
140  .id = S2MPS11_BUCK##num, \
141  .ops = &s2mps11_buck_ops, \
142  .type = REGULATOR_VOLTAGE, \
143  .owner = THIS_MODULE, \
144  .min_uV = S2MPS11_BUCK_MIN1, \
145  .uV_step = S2MPS11_BUCK_STEP1, \
146  .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \
147  .vsel_reg = S2MPS11_REG_B6CTRL2 + (num - 6) * 2, \
148  .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \
149  .enable_reg = S2MPS11_REG_B6CTRL1 + (num - 6) * 2, \
150  .enable_mask = S2MPS11_ENABLE_MASK \
151 }
152 
153 #define regulator_desc_buck9 { \
154  .name = "BUCK9", \
155  .id = S2MPS11_BUCK9, \
156  .ops = &s2mps11_buck_ops, \
157  .type = REGULATOR_VOLTAGE, \
158  .owner = THIS_MODULE, \
159  .min_uV = S2MPS11_BUCK_MIN3, \
160  .uV_step = S2MPS11_BUCK_STEP3, \
161  .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \
162  .vsel_reg = S2MPS11_REG_B9CTRL2, \
163  .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \
164  .enable_reg = S2MPS11_REG_B9CTRL1, \
165  .enable_mask = S2MPS11_ENABLE_MASK \
166 }
167 
168 #define regulator_desc_buck10 { \
169  .name = "BUCK10", \
170  .id = S2MPS11_BUCK10, \
171  .ops = &s2mps11_buck_ops, \
172  .type = REGULATOR_VOLTAGE, \
173  .owner = THIS_MODULE, \
174  .min_uV = S2MPS11_BUCK_MIN2, \
175  .uV_step = S2MPS11_BUCK_STEP2, \
176  .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \
177  .vsel_reg = S2MPS11_REG_B9CTRL2, \
178  .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \
179  .enable_reg = S2MPS11_REG_B9CTRL1, \
180  .enable_mask = S2MPS11_ENABLE_MASK \
181 }
182 
183 static struct regulator_desc regulators[] = {
232 };
233 
234 static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
235 {
236  struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
237  struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
238  struct regulator_config config = { };
239  struct s2mps11_info *s2mps11;
240  int i, ret;
241  unsigned char ramp_enable, ramp_reg = 0;
242 
243  if (!pdata) {
244  dev_err(pdev->dev.parent, "Platform data not supplied\n");
245  return -ENODEV;
246  }
247 
248  s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
249  GFP_KERNEL);
250  if (!s2mps11)
251  return -ENOMEM;
252 
253  platform_set_drvdata(pdev, s2mps11);
254 
255  s2mps11->ramp_delay2 = pdata->buck2_ramp_delay;
256  s2mps11->ramp_delay34 = pdata->buck34_ramp_delay;
257  s2mps11->ramp_delay5 = pdata->buck5_ramp_delay;
258  s2mps11->ramp_delay16 = pdata->buck16_ramp_delay;
259  s2mps11->ramp_delay7810 = pdata->buck7810_ramp_delay;
260  s2mps11->ramp_delay9 = pdata->buck9_ramp_delay;
261 
262  s2mps11->buck6_ramp = pdata->buck6_ramp_enable;
263  s2mps11->buck2_ramp = pdata->buck2_ramp_enable;
264  s2mps11->buck3_ramp = pdata->buck3_ramp_enable;
265  s2mps11->buck4_ramp = pdata->buck4_ramp_enable;
266 
267  ramp_enable = (s2mps11->buck2_ramp << 3) | (s2mps11->buck3_ramp << 2) |
268  (s2mps11->buck4_ramp << 1) | s2mps11->buck6_ramp ;
269 
270  if (ramp_enable) {
271  if (s2mps11->buck2_ramp)
272  ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6;
273  if (s2mps11->buck3_ramp || s2mps11->buck4_ramp)
274  ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4;
275  sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
276  }
277 
278  ramp_reg &= 0x00;
279  ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6;
280  ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4;
281  ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2;
282  ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
283  sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
284 
285  for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
286 
287  config.dev = &pdev->dev;
288  config.regmap = iodev->regmap;
289  config.init_data = pdata->regulators[i].initdata;
290  config.driver_data = s2mps11;
291 
292  s2mps11->rdev[i] = regulator_register(&regulators[i], &config);
293  if (IS_ERR(s2mps11->rdev[i])) {
294  ret = PTR_ERR(s2mps11->rdev[i]);
295  dev_err(&pdev->dev, "regulator init failed for %d\n",
296  i);
297  s2mps11->rdev[i] = NULL;
298  goto err;
299  }
300  }
301 
302  return 0;
303 err:
304  for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
305  regulator_unregister(s2mps11->rdev[i]);
306 
307  return ret;
308 }
309 
310 static int __devexit s2mps11_pmic_remove(struct platform_device *pdev)
311 {
312  struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
313  int i;
314 
315  for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
316  regulator_unregister(s2mps11->rdev[i]);
317 
318  return 0;
319 }
320 
321 static const struct platform_device_id s2mps11_pmic_id[] = {
322  { "s2mps11-pmic", 0},
323  { },
324 };
325 MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
326 
327 static struct platform_driver s2mps11_pmic_driver = {
328  .driver = {
329  .name = "s2mps11-pmic",
330  .owner = THIS_MODULE,
331  },
332  .probe = s2mps11_pmic_probe,
333  .remove = __devexit_p(s2mps11_pmic_remove),
334  .id_table = s2mps11_pmic_id,
335 };
336 
337 static int __init s2mps11_pmic_init(void)
338 {
339  return platform_driver_register(&s2mps11_pmic_driver);
340 }
341 subsys_initcall(s2mps11_pmic_init);
342 
343 static void __exit s2mps11_pmic_exit(void)
344 {
345  platform_driver_unregister(&s2mps11_pmic_driver);
346 }
347 module_exit(s2mps11_pmic_exit);
348 
349 /* Module information */
350 MODULE_AUTHOR("Sangbeom Kim <[email protected]>");
351 MODULE_DESCRIPTION("SAMSUNG S2MPS11 Regulator Driver");
352 MODULE_LICENSE("GPL");