LP8758 pre version
[mlp-open-source/kernel.git] / drivers / regulator / lm3631-regulator.c
1 /*
2  * TI LM3631 LDO Regulator Driver
3  *
4  * Copyright 2013 Texas Instruments
5  *
6  * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  */
14 #include <linux/err.h>
15 #include <linux/mfd/lm3631.h>
16 #include <linux/module.h>
17 #include <linux/of.h>
18 #include <linux/platform_device.h>
19 #include <linux/regulator/driver.h>
20 #include <linux/regulator/of_regulator.h>
21 #include <linux/slab.h>
23 #define ENABLE_TIME_USEC                1000
25 enum lm3631_regulator_id {
26         LM3631_REGULATOR_BOOST,
27         LM3631_LDO_CONT,
28         LM3631_LDO_OREF,
29         LM3631_LDO_POS,
30         LM3631_LDO_NEG,
31 };
33 struct lm3631_regulator {
34         struct lm3631 *lm3631;
35         struct regulator_desc *desc;
36         struct regulator_dev *regulator;
37         struct regulator_init_data *init_data;
38 };
40 static const int lm3631_boost_vtbl[] = {
41         4500000, 4550000, 4600000, 4650000, 4700000, 4750000, 4800000, 4850000,
42         4900000, 4950000, 5000000, 5050000, 5100000, 5150000, 5200000, 5250000,
43         5300000, 5350000, 5400000, 5450000, 5500000, 5550000, 5600000, 5650000,
44         5700000, 5750000, 5800000, 5850000, 5900000, 5950000, 6000000, 6050000,
45         6100000, 6150000, 6200000, 6250000, 6300000, 6350000,
46 };
48 static const int lm3631_ldo_cont_vtbl[] = {
49         1800000, 2300000, 2800000, 3300000,
50 };
52 static const int lm3631_ldo_target_vtbl[] = {
53         4000000, 4050000, 4100000, 4150000, 4200000, 4250000, 4300000, 4350000,
54         4400000, 4450000, 4500000, 4550000, 4600000, 4650000, 4700000, 4750000,
55         4800000, 4850000, 4900000, 4950000, 5000000, 5050000, 5100000, 5150000,
56         5200000, 5250000, 5300000, 5350000, 5400000, 5450000, 5500000, 5550000,
57         5600000, 5650000, 5700000, 5750000, 5800000, 5850000, 5900000, 5950000,
58         6000000,
59 };
61 const int ldo_cont_enable_time[] = {
62         0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
63 };
65 static int lm3631_regulator_enable_time(struct regulator_dev *rdev)
66 {
67         struct lm3631_regulator *lm3631_regulator = rdev_get_drvdata(rdev);
68         enum lm3631_regulator_id id = rdev_get_id(rdev);
69         u8 val, addr, mask;
71         switch (id) {
72         case LM3631_LDO_CONT:
73                 addr = LM3631_REG_ENTIME_VCONT;
74                 mask = LM3631_ENTIME_CONT_MASK;
75                 break;
76         case LM3631_LDO_OREF:
77                 addr = LM3631_REG_ENTIME_VOREF;
78                 mask = LM3631_ENTIME_MASK;
79                 break;
80         case LM3631_LDO_POS:
81                 addr = LM3631_REG_ENTIME_VPOS;
82                 mask = LM3631_ENTIME_MASK;
83                 break;
84         case LM3631_LDO_NEG:
85                 addr = LM3631_REG_ENTIME_VNEG;
86                 mask = LM3631_ENTIME_MASK;
87                 break;
88         default:
89                 return -EINVAL;
90         }
92         if (lm3631_read_byte(lm3631_regulator->lm3631, addr, &val))
93                 return -EINVAL;
95         val = (val & mask) >> LM3631_ENTIME_SHIFT;
97         if (id == LM3631_LDO_CONT)
98                 return ldo_cont_enable_time[val];
99         else
100                 return ENABLE_TIME_USEC * val;
103 static struct regulator_ops lm3631_boost_voltage_table_ops = {
104         .list_voltage     = regulator_list_voltage_table,
105         .set_voltage_sel  = regulator_set_voltage_sel_regmap,
106         .get_voltage_sel  = regulator_get_voltage_sel_regmap,
107 };
109 static struct regulator_ops lm3631_regulator_voltage_table_ops = {
110         .list_voltage     = regulator_list_voltage_table,
111         .set_voltage_sel  = regulator_set_voltage_sel_regmap,
112         .get_voltage_sel  = regulator_get_voltage_sel_regmap,
113         .enable           = regulator_enable_regmap,
114         .disable          = regulator_disable_regmap,
115         .is_enabled       = regulator_is_enabled_regmap,
116         .enable_time      = lm3631_regulator_enable_time,
117 };
119 static struct regulator_desc lm3631_regulator_desc[] = {
120         {
121                 .name           = "vboost",
122                 .id             = LM3631_REGULATOR_BOOST,
123                 .ops            = &lm3631_boost_voltage_table_ops,
124                 .n_voltages     = ARRAY_SIZE(lm3631_boost_vtbl),
125                 .volt_table     = lm3631_boost_vtbl,
126                 .type           = REGULATOR_VOLTAGE,
127                 .owner          = THIS_MODULE,
128                 .vsel_reg       = LM3631_REG_VOUT_BOOST,
129                 .vsel_mask      = LM3631_VOUT_MASK,
130         },
131         {
132                 .name           = "ldo_cont",
133                 .id             = LM3631_LDO_CONT,
134                 .ops            = &lm3631_regulator_voltage_table_ops,
135                 .n_voltages     = ARRAY_SIZE(lm3631_ldo_cont_vtbl),
136                 .volt_table     = lm3631_ldo_cont_vtbl,
137                 .type           = REGULATOR_VOLTAGE,
138                 .owner          = THIS_MODULE,
139                 .vsel_reg       = LM3631_REG_VOUT_CONT,
140                 .vsel_mask      = LM3631_VOUT_CONT_MASK,
141                 .enable_reg     = LM3631_REG_LDO_CTRL2,
142                 .enable_mask    = LM3631_EN_CONT_MASK,
143         },
144         {
145                 .name           = "ldo_oref",
146                 .id             = LM3631_LDO_OREF,
147                 .ops            = &lm3631_regulator_voltage_table_ops,
148                 .n_voltages     = ARRAY_SIZE(lm3631_ldo_target_vtbl),
149                 .volt_table     = lm3631_ldo_target_vtbl,
150                 .type           = REGULATOR_VOLTAGE,
151                 .owner          = THIS_MODULE,
152                 .vsel_reg       = LM3631_REG_VOUT_OREF,
153                 .vsel_mask      = LM3631_VOUT_MASK,
154                 .enable_reg     = LM3631_REG_LDO_CTRL1,
155                 .enable_mask    = LM3631_EN_OREF_MASK,
156         },
157         {
158                 .name           = "ldo_vpos",
159                 .id             = LM3631_LDO_POS,
160                 .ops            = &lm3631_regulator_voltage_table_ops,
161                 .n_voltages     = ARRAY_SIZE(lm3631_ldo_target_vtbl),
162                 .volt_table     = lm3631_ldo_target_vtbl,
163                 .type           = REGULATOR_VOLTAGE,
164                 .owner          = THIS_MODULE,
165                 .vsel_reg       = LM3631_REG_VOUT_POS,
166                 .vsel_mask      = LM3631_VOUT_MASK,
167                 .enable_reg     = LM3631_REG_LDO_CTRL1,
168                 .enable_mask    = LM3631_EN_VPOS_MASK,
169         },
170         {
171                 .name           = "ldo_vneg",
172                 .id             = LM3631_LDO_NEG,
173                 .ops            = &lm3631_regulator_voltage_table_ops,
174                 .n_voltages     = ARRAY_SIZE(lm3631_ldo_target_vtbl),
175                 .volt_table     = lm3631_ldo_target_vtbl,
176                 .type           = REGULATOR_VOLTAGE,
177                 .owner          = THIS_MODULE,
178                 .vsel_reg       = LM3631_REG_VOUT_NEG,
179                 .vsel_mask      = LM3631_VOUT_MASK,
180                 .enable_reg     = LM3631_REG_LDO_CTRL1,
181                 .enable_mask    = LM3631_EN_VNEG_MASK,
182         },
183 };
185 static struct of_regulator_match lm3631_regulator_matches[] = {
186         { .name = "vboost", .driver_data = (void *)LM3631_REGULATOR_BOOST, },
187         { .name = "vcont",  .driver_data = (void *)LM3631_LDO_CONT, },
188         { .name = "voref",  .driver_data = (void *)LM3631_LDO_OREF, },
189         { .name = "vpos",   .driver_data = (void *)LM3631_LDO_POS,  },
190         { .name = "vneg",   .driver_data = (void *)LM3631_LDO_NEG,  },
191 };
193 static int lm3631_regulator_parse_dt(struct device *dev,
194                                      struct lm3631_regulator *lm3631_regulator,
195                                      int id)
197         struct device_node *node = dev->of_node;
198         int count;
200         count = of_regulator_match(dev, node, &lm3631_regulator_matches[id], 1);
201         if (count <= 0)
202                 return -ENODEV;
204         lm3631_regulator->init_data = lm3631_regulator_matches[id].init_data;
206         return 0;
209 static int lm3631_regulator_probe(struct platform_device *pdev)
211         struct lm3631 *lm3631 = dev_get_drvdata(pdev->dev.parent);
212         struct lm3631_regulator *lm3631_regulator;
213         struct regulator_config cfg = { };
214         struct regulator_dev *rdev;
215         int id = pdev->id;
216         int ret;
218         lm3631_regulator = devm_kzalloc(&pdev->dev, sizeof(*lm3631_regulator),
219                                         GFP_KERNEL);
220         if (!lm3631_regulator)
221                 return -ENOMEM;
223         lm3631_regulator->lm3631 = lm3631;
225         lm3631_regulator->init_data = lm3631->pdata->regulator_data[id];
226         if (!lm3631_regulator->init_data) {
227                 if (IS_ENABLED(CONFIG_OF))
228                         ret = lm3631_regulator_parse_dt(&pdev->dev,
229                                                         lm3631_regulator, id);
230                 else
231                         ret = -ENODEV;
233                 if (ret)
234                         return ret;
235         }
237         cfg.dev = pdev->dev.parent;
238         cfg.init_data = lm3631_regulator->init_data;
239         cfg.driver_data = lm3631_regulator;
240         cfg.regmap = lm3631->regmap;
242         rdev = regulator_register(&lm3631_regulator_desc[id], &cfg);
243         if (IS_ERR(rdev)) {
244                 ret = PTR_ERR(rdev);
245                 dev_err(&pdev->dev, "[%d] regulator register err: %d\n",
246                         id + 1, ret);
247                 return ret;
248         }
250         lm3631_regulator->regulator = rdev;
251         platform_set_drvdata(pdev, lm3631_regulator);
253         return 0;
256 static int lm3631_regulator_remove(struct platform_device *pdev)
258         struct lm3631_regulator *lm3631_regulator = platform_get_drvdata(pdev);
260         regulator_unregister(lm3631_regulator->regulator);
261         return 0;
264 #ifdef CONFIG_OF
265 static const struct of_device_id lm3631_regulator_of_match[] = {
266         { .compatible = "ti,lm3631-regulator", },
267         { }
268 };
269 MODULE_DEVICE_TABLE(of, lm3631_regulator_of_match);
270 #endif
272 static struct platform_driver lm3631_regulator_driver = {
273         .probe = lm3631_regulator_probe,
274         .remove = lm3631_regulator_remove,
275         .driver = {
276                 .name = "lm3631-regulator",
277                 .owner = THIS_MODULE,
278                 .of_match_table = of_match_ptr(lm3631_regulator_of_match),
279         },
280 };
282 module_platform_driver(lm3631_regulator_driver);
284 MODULE_DESCRIPTION("TI LM3631 Regulator Driver");
285 MODULE_AUTHOR("Milo Kim");
286 MODULE_LICENSE("GPL");
287 MODULE_ALIAS("platform:lm3631-regulator");