8dd9b0358b3135e9afae1dc942d7b39b1ffdb069
[linux-2.6.git] / drivers / regulator / bq2419x-regulator.c
1 /*
2  * bq2419x-regulator.c --  bq2419x
3  *
4  * Regulator driver for BQ2419X charger.
5  *
6  * Copyright (c) 2012-2013, NVIDIA Corporation.
7  *
8  * Author: Laxman Dewangan <ldewangan@nvidia.com>
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation version 2.
13  *
14  * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
15  * whether express or implied; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22  * 02111-1307, USA
23  */
24
25 #include <linux/err.h>
26 #include <linux/gpio.h>
27 #include <linux/i2c.h>
28 #include <linux/init.h>
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/platform_device.h>
32 #include <linux/regmap.h>
33 #include <linux/regulator/driver.h>
34 #include <linux/regulator/machine.h>
35 #include <linux/mfd/bq2419x.h>
36 #include <linux/slab.h>
37
38 struct bq2419x_regulator_info {
39         struct device *dev;
40         struct regulator_desc desc;
41         struct regulator_dev *rdev;
42         struct bq2419x_chip *chip;
43         int gpio_otg_iusb;
44         struct mutex mutex;
45         int shutdown_complete;
46 };
47
48 static int bq2419x_regulator_enable_time(struct regulator_dev *rdev)
49 {
50         return 500000;
51 }
52
53 static int bq2419x_dcdc_enable(struct regulator_dev *rdev)
54 {
55         struct bq2419x_regulator_info *bq = rdev_get_drvdata(rdev);
56         int ret;
57
58         dev_info(bq->dev, "%s called\n", __func__);
59         if (gpio_is_valid(bq->gpio_otg_iusb))
60                 gpio_set_value(bq->gpio_otg_iusb, 1);
61
62         mutex_lock(&bq->mutex);
63         if (bq && bq->shutdown_complete) {
64                 mutex_unlock(&bq->mutex);
65                 return -ENODEV;
66         }
67
68         /* Clear EN_HIZ */
69         ret = regmap_update_bits(bq->chip->regmap,
70                         BQ2419X_INPUT_SRC_REG, BQ2419X_EN_HIZ, 0);
71         if (ret < 0) {
72                 dev_err(bq->dev, "error reading reg: 0x%x\n",
73                         BQ2419X_INPUT_SRC_REG);
74                 return ret;
75         }
76
77         ret = regmap_update_bits(bq->chip->regmap, BQ2419X_OTG,
78                         BQ2419X_OTG_ENABLE_MASK, BQ2419X_OTG_ENABLE);
79         if (ret < 0) {
80                 dev_err(bq->dev, "register %d update failed with err %d",
81                          BQ2419X_OTG, ret);
82                 mutex_unlock(&bq->mutex);
83                 return ret;
84         }
85         mutex_unlock(&bq->mutex);
86         return ret;
87 }
88
89 static int bq2419x_dcdc_disable(struct regulator_dev *rdev)
90 {
91         struct bq2419x_regulator_info *bq = rdev_get_drvdata(rdev);
92         int ret = 0;
93
94         dev_info(bq->dev, "%s called\n", __func__);
95         mutex_lock(&bq->mutex);
96         if (bq && bq->shutdown_complete) {
97                 mutex_unlock(&bq->mutex);
98                 return -ENODEV;
99         }
100
101         ret = regmap_update_bits(bq->chip->regmap, BQ2419X_OTG,
102                                         BQ2419X_OTG_ENABLE_MASK, 0x10);
103         if (ret < 0) {
104                 dev_err(bq->dev, "register %d update failed with err %d",
105                         BQ2419X_OTG, ret);
106                 mutex_unlock(&bq->mutex);
107                 return ret;
108         }
109
110         if (gpio_is_valid(bq->gpio_otg_iusb))
111                 gpio_set_value(bq->gpio_otg_iusb, 0);
112
113         mutex_unlock(&bq->mutex);
114         return ret;
115 }
116
117 static int bq2419x_dcdc_is_enabled(struct regulator_dev *rdev)
118 {
119         struct bq2419x_regulator_info *bq = rdev_get_drvdata(rdev);
120         int ret;
121         unsigned int data;
122
123         mutex_lock(&bq->mutex);
124         if (bq && bq->shutdown_complete) {
125                 mutex_unlock(&bq->mutex);
126                 return -ENODEV;
127         }
128         ret = regmap_read(bq->chip->regmap, BQ2419X_OTG, &data);
129         if (ret < 0) {
130                 dev_err(bq->dev, "register %d read failed with err %d",
131                         BQ2419X_OTG, ret);
132                 mutex_unlock(&bq->mutex);
133                 return ret;
134         }
135         mutex_unlock(&bq->mutex);
136         return (data & BQ2419X_OTG_ENABLE_MASK) == BQ2419X_OTG_ENABLE;
137 }
138
139 static struct regulator_ops bq2419x_dcdc_ops = {
140         .enable                 = bq2419x_dcdc_enable,
141         .disable                = bq2419x_dcdc_disable,
142         .is_enabled             = bq2419x_dcdc_is_enabled,
143         .enable_time            = bq2419x_regulator_enable_time,
144 };
145
146 static void bq2419x_regulator_shutdown(struct platform_device *pdev)
147 {
148         struct bq2419x_regulator_info *bq = platform_get_drvdata(pdev);
149
150         mutex_lock(&bq->mutex);
151         bq->shutdown_complete = 1;
152         mutex_unlock(&bq->mutex);
153 }
154
155 static int __devinit bq2419x_regulator_probe(struct platform_device *pdev)
156 {
157         struct bq2419x_regulator_platform_data *pdata = NULL;
158         struct bq2419x_platform_data *chip_pdata;
159         struct regulator_dev *rdev;
160         struct bq2419x_regulator_info *bq;
161         int ret;
162
163         chip_pdata = dev_get_platdata(pdev->dev.parent);
164         if (chip_pdata)
165                 pdata = chip_pdata->reg_pdata;
166
167         if (!pdata) {
168                 dev_err(&pdev->dev, "No Platform data");
169                 return -EIO;
170         }
171
172         bq = devm_kzalloc(&pdev->dev, sizeof(*bq), GFP_KERNEL);
173         if (!bq) {
174                 dev_err(&pdev->dev, "Memory allocation failed\n");
175                 return -ENOMEM;
176         }
177
178         bq->dev = &pdev->dev;
179         bq->chip = dev_get_drvdata(pdev->dev.parent);
180
181         bq->gpio_otg_iusb = pdata->gpio_otg_iusb;
182         bq->desc.name = "bq2419x-vbus";
183         bq->desc.id = 0;
184         bq->desc.ops = &bq2419x_dcdc_ops;
185         bq->desc.type = REGULATOR_VOLTAGE;
186         bq->desc.owner = THIS_MODULE;
187         bq->shutdown_complete = 0;
188         mutex_init(&bq->mutex);
189
190         platform_set_drvdata(pdev, bq);
191
192         if (gpio_is_valid(bq->gpio_otg_iusb)) {
193                 ret = gpio_request(bq->gpio_otg_iusb, dev_name(&pdev->dev));
194                 if (ret < 0) {
195                         dev_err(&pdev->dev,
196                                 "gpio request failed, err = %d\n", ret);
197                         return ret;
198                 }
199                 gpio_direction_output(bq->gpio_otg_iusb, 0);
200         }
201
202         /* Register the regulators */
203         rdev = regulator_register(&bq->desc, &pdev->dev,
204                         pdata->reg_init_data, bq, NULL);
205         if (IS_ERR(rdev)) {
206                 ret = PTR_ERR(rdev);
207                 dev_err(bq->dev, "regulator register failed, err %d\n", ret);
208                 goto err_init;
209         }
210
211         bq->rdev = rdev;
212
213         ret = regmap_update_bits(bq->chip->regmap, BQ2419X_OTG,
214                                         BQ2419X_OTG_ENABLE_MASK, 0x10);
215         if (ret < 0) {
216                 dev_err(bq->dev, "register %d update failed with err %d",
217                         BQ2419X_OTG, ret);
218                 goto err_reg_update;
219         }
220         return 0;
221
222 err_reg_update:
223         regulator_unregister(bq->rdev);
224 err_init:
225         if (gpio_is_valid(bq->gpio_otg_iusb))
226                 gpio_free(bq->gpio_otg_iusb);
227         mutex_destroy(&bq->mutex);
228         return ret;
229 }
230
231 static int __devexit bq2419x_regulator_remove(struct platform_device *pdev)
232 {
233         struct bq2419x_regulator_info *bq = platform_get_drvdata(pdev);
234
235         mutex_destroy(&bq->mutex);
236         regulator_unregister(bq->rdev);
237         if (gpio_is_valid(bq->gpio_otg_iusb))
238                 gpio_free(bq->gpio_otg_iusb);
239         return 0;
240 }
241
242 static struct platform_driver bq2419x_regulator_driver = {
243         .driver = {
244                 .name = "bq2419x-pmic",
245                 .owner = THIS_MODULE,
246         },
247         .probe = bq2419x_regulator_probe,
248         .shutdown = bq2419x_regulator_shutdown,
249         .remove = __devexit_p(bq2419x_regulator_remove),
250 };
251
252 static int __init bq2419x_init(void)
253 {
254         return platform_driver_register(&bq2419x_regulator_driver);
255 }
256 subsys_initcall(bq2419x_init);
257
258 static void __exit bq2419x_cleanup(void)
259 {
260         platform_driver_unregister(&bq2419x_regulator_driver);
261 }
262 module_exit(bq2419x_cleanup);
263
264 MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
265 MODULE_DESCRIPTION("BQ2419X voltage regulator driver");
266 MODULE_LICENSE("GPL v2");