LP8758 pre version
[mlp-open-source/kernel.git] / drivers / regulator / lm3632-regulator.c
1 /*
2  * TI LM3632 LDO Regulator Driver
3  *
4  * Copyright 2015 Texas Instruments
5  *
6  * Author: Milo 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/lm3632.h>
16 #include <linux/module.h>
17 #include <linux/of.h>
18 #include <linux/of_gpio.h>
19 #include <linux/platform_device.h>
20 #include <linux/regulator/driver.h>
21 #include <linux/regulator/of_regulator.h>
22 #include <linux/slab.h>
24 enum lm3632_regulator_id {
25         LM3632_REGULATOR_BOOST,
26         LM3632_LDO_POS,
27         LM3632_LDO_NEG,
28 };
30 struct lm3632_regulator {
31         int ena_gpio;
32         struct lm3632 *lm3632;
33         struct regulator_desc *desc;
34         struct regulator_dev *regulator;
35         struct regulator_init_data *init_data;
36 };
38 static const int lm3632_boost_vtbl[] = {
39         4500000, 4550000, 4600000, 4650000, 4700000, 4750000, 4800000, 4850000,
40         4900000, 4950000, 5000000, 5050000, 5100000, 5150000, 5200000, 5250000,
41         5300000, 5350000, 5400000, 5450000, 5500000, 5550000, 5600000, 5650000,
42         5700000, 5750000, 5800000, 5850000, 5900000, 5950000, 6000000, 6050000,
43         6100000, 6150000, 6200000, 6250000, 6300000, 6350000, 6400000,
44 };
46 static const int lm3632_ldo_vtbl[] = {
47         4000000, 4050000, 4100000, 4150000, 4200000, 4250000, 4300000, 4350000,
48         4400000, 4450000, 4500000, 4550000, 4600000, 4650000, 4700000, 4750000,
49         4800000, 4850000, 4900000, 4950000, 5000000, 5050000, 5100000, 5150000,
50         5200000, 5250000, 5300000, 5350000, 5400000, 5450000, 5500000, 5550000,
51         5600000, 5650000, 5700000, 5750000, 5800000, 5850000, 5900000, 5950000,
52         6000000,
53 };
55 static struct regulator_ops lm3632_boost_voltage_table_ops = {
56         .list_voltage     = regulator_list_voltage_table,
57         .set_voltage_sel  = regulator_set_voltage_sel_regmap,
58         .get_voltage_sel  = regulator_get_voltage_sel_regmap,
59 };
61 static struct regulator_ops lm3632_regulator_voltage_table_ops = {
62         .list_voltage     = regulator_list_voltage_table,
63         .set_voltage_sel  = regulator_set_voltage_sel_regmap,
64         .get_voltage_sel  = regulator_get_voltage_sel_regmap,
65         .enable           = regulator_enable_regmap,
66         .disable          = regulator_disable_regmap,
67         .is_enabled       = regulator_is_enabled_regmap,
68 };
70 static struct regulator_desc lm3632_regulator_desc[] = {
71         {
72                 .name           = "vboost",
73                 .id             = LM3632_REGULATOR_BOOST,
74                 .ops            = &lm3632_boost_voltage_table_ops,
75                 .n_voltages     = ARRAY_SIZE(lm3632_boost_vtbl),
76                 .volt_table     = lm3632_boost_vtbl,
77                 .type           = REGULATOR_VOLTAGE,
78                 .owner          = THIS_MODULE,
79                 .vsel_reg       = LM3632_REG_VOUT_BOOST,
80                 .vsel_mask      = LM3632_VOUT_MASK,
81         },
82         {
83                 .name           = "ldo_vpos",
84                 .id             = LM3632_LDO_POS,
85                 .ops            = &lm3632_regulator_voltage_table_ops,
86                 .n_voltages     = ARRAY_SIZE(lm3632_ldo_vtbl),
87                 .volt_table     = lm3632_ldo_vtbl,
88                 .type           = REGULATOR_VOLTAGE,
89                 .owner          = THIS_MODULE,
90                 .vsel_reg       = LM3632_REG_VOUT_POS,
91                 .vsel_mask      = LM3632_VOUT_MASK,
92                 .enable_reg     = LM3632_REG_BIAS_CONFIG,
93                 .enable_mask    = LM3632_EN_VPOS_MASK,
94         },
95         {
96                 .name           = "ldo_vneg",
97                 .id             = LM3632_LDO_NEG,
98                 .ops            = &lm3632_regulator_voltage_table_ops,
99                 .n_voltages     = ARRAY_SIZE(lm3632_ldo_vtbl),
100                 .volt_table     = lm3632_ldo_vtbl,
101                 .type           = REGULATOR_VOLTAGE,
102                 .owner          = THIS_MODULE,
103                 .vsel_reg       = LM3632_REG_VOUT_NEG,
104                 .vsel_mask      = LM3632_VOUT_MASK,
105                 .enable_reg     = LM3632_REG_BIAS_CONFIG,
106                 .enable_mask    = LM3632_EN_VNEG_MASK,
107         },
108 };
110 static struct of_regulator_match lm3632_regulator_matches[] = {
111         { .name = "vboost", .driver_data = (void *)LM3632_REGULATOR_BOOST, },
112         { .name = "vpos",   .driver_data = (void *)LM3632_LDO_POS,  },
113         { .name = "vneg",   .driver_data = (void *)LM3632_LDO_NEG,  },
114 };
116 static int lm3632_regulator_parse_dt(struct device *dev,
117                                      struct lm3632_regulator *lm3632_regulator,
118                                      int id)
120         struct device_node *node = dev->of_node;
121         int count;
122         int gpio;
124         count = of_regulator_match(dev, node, &lm3632_regulator_matches[id], 1);
125         if (count <= 0)
126                 return -ENODEV;
128         lm3632_regulator->init_data = lm3632_regulator_matches[id].init_data;
130         /*
131          * Check LCM_EN1/2_GPIO is configured.
132          * Those pins are used for enabling VPOS/VNEG LDOs.
133          */
134         if (id == LM3632_LDO_POS) {
135                 gpio = of_get_named_gpio(node, "ti,lcm-en1-gpio", 0);
136                 if (gpio > 0)
137                         lm3632_regulator->ena_gpio = gpio;
138         } else if (id == LM3632_LDO_NEG) {
139                 gpio = of_get_named_gpio(node, "ti,lcm-en2-gpio", 0);
140                 if (gpio > 0)
141                         lm3632_regulator->ena_gpio = gpio;
142         }
144         return 0;
147 static int lm3632_regulator_probe(struct platform_device *pdev)
149         struct lm3632 *lm3632 = dev_get_drvdata(pdev->dev.parent);
150         struct lm3632_regulator *lm3632_regulator;
151         struct regulator_config cfg = { };
152         struct regulator_dev *rdev;
153         int id = pdev->id;
154         int ret;
156         lm3632_regulator = devm_kzalloc(&pdev->dev, sizeof(*lm3632_regulator),
157                                         GFP_KERNEL);
158         if (!lm3632_regulator)
159                 return -ENOMEM;
161         lm3632_regulator->ena_gpio = 0;
162         lm3632_regulator->lm3632 = lm3632;
163         lm3632_regulator->init_data = lm3632->pdata->regulator_data[id];
164         if (!lm3632_regulator->init_data) {
165                 if (IS_ENABLED(CONFIG_OF))
166                         ret = lm3632_regulator_parse_dt(&pdev->dev,
167                                                         lm3632_regulator, id);
168                 else
169                         ret = -ENODEV;
171                 if (ret)
172                         return ret;
173         }
175         cfg.dev = pdev->dev.parent;
176         cfg.init_data = lm3632_regulator->init_data;
177         cfg.driver_data = lm3632_regulator;
178         cfg.regmap = lm3632->regmap;
180         /* Update register value if external enable pin is used */
181         if (lm3632_regulator->ena_gpio > 0) {
182                 cfg.ena_gpio = lm3632_regulator->ena_gpio;
183                 cfg.ena_gpio_flags = GPIOF_OUT_INIT_LOW;
185                 ret = lm3632_update_bits(lm3632_regulator->lm3632,
186                                          LM3632_REG_BIAS_CONFIG,
187                                          LM3632_EXT_EN_MASK,
188                                          LM3632_EXT_EN_MASK);
189                 if (ret) {
190                         dev_err(&pdev->dev, "external pin err: %d\n", ret);
191                         return ret;
192                 }
193         }
195         rdev = regulator_register(&lm3632_regulator_desc[id], &cfg);
196         if (IS_ERR(rdev)) {
197                 ret = PTR_ERR(rdev);
198                 dev_err(&pdev->dev, "[%d] regulator register err: %d\n",
199                         id, ret);
200                 return ret;
201         }
203         lm3632_regulator->regulator = rdev;
204         platform_set_drvdata(pdev, lm3632_regulator);
206         return 0;
209 static int lm3632_regulator_remove(struct platform_device *pdev)
211         struct lm3632_regulator *lm3632_regulator = platform_get_drvdata(pdev);
213         regulator_unregister(lm3632_regulator->regulator);
214         return 0;
217 #ifdef CONFIG_OF
218 static const struct of_device_id lm3632_regulator_of_match[] = {
219         { .compatible = "ti,lm3632-regulator", },
220         { }
221 };
222 MODULE_DEVICE_TABLE(of, lm3632_regulator_of_match);
223 #endif
225 static struct platform_driver lm3632_regulator_driver = {
226         .probe = lm3632_regulator_probe,
227         .remove = lm3632_regulator_remove,
228         .driver = {
229                 .name = "lm3632-regulator",
230                 .owner = THIS_MODULE,
231                 .of_match_table = of_match_ptr(lm3632_regulator_of_match),
232         },
233 };
235 module_platform_driver(lm3632_regulator_driver);
237 MODULE_DESCRIPTION("TI LM3632 Regulator Driver");
238 MODULE_AUTHOR("Milo Kim");
239 MODULE_LICENSE("GPL");
240 MODULE_ALIAS("platform:lm3632-regulator");