Staging: wireless drivers Kconfig change
[safe/jmp/linux-2.6] / drivers / regulator / fixed.c
1 /*
2  * fixed.c
3  *
4  * Copyright 2008 Wolfson Microelectronics PLC.
5  *
6  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7  *
8  * Copyright (c) 2009 Nokia Corporation
9  * Roger Quadros <ext-roger.quadros@nokia.com>
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of the
14  * License, or (at your option) any later version.
15  *
16  * This is useful for systems with mixed controllable and
17  * non-controllable regulators, as well as for allowing testing on
18  * systems with no controllable regulators.
19  */
20
21 #include <linux/err.h>
22 #include <linux/mutex.h>
23 #include <linux/platform_device.h>
24 #include <linux/regulator/driver.h>
25 #include <linux/regulator/fixed.h>
26 #include <linux/gpio.h>
27
28 struct fixed_voltage_data {
29         struct regulator_desc desc;
30         struct regulator_dev *dev;
31         int microvolts;
32         int gpio;
33         unsigned enable_high:1;
34         unsigned is_enabled:1;
35 };
36
37 static int fixed_voltage_is_enabled(struct regulator_dev *dev)
38 {
39         struct fixed_voltage_data *data = rdev_get_drvdata(dev);
40
41         return data->is_enabled;
42 }
43
44 static int fixed_voltage_enable(struct regulator_dev *dev)
45 {
46         struct fixed_voltage_data *data = rdev_get_drvdata(dev);
47
48         if (gpio_is_valid(data->gpio)) {
49                 gpio_set_value_cansleep(data->gpio, data->enable_high);
50                 data->is_enabled = 1;
51         }
52
53         return 0;
54 }
55
56 static int fixed_voltage_disable(struct regulator_dev *dev)
57 {
58         struct fixed_voltage_data *data = rdev_get_drvdata(dev);
59
60         if (gpio_is_valid(data->gpio)) {
61                 gpio_set_value_cansleep(data->gpio, !data->enable_high);
62                 data->is_enabled = 0;
63         }
64
65         return 0;
66 }
67
68 static int fixed_voltage_get_voltage(struct regulator_dev *dev)
69 {
70         struct fixed_voltage_data *data = rdev_get_drvdata(dev);
71
72         return data->microvolts;
73 }
74
75 static int fixed_voltage_list_voltage(struct regulator_dev *dev,
76                                       unsigned selector)
77 {
78         struct fixed_voltage_data *data = rdev_get_drvdata(dev);
79
80         if (selector != 0)
81                 return -EINVAL;
82
83         return data->microvolts;
84 }
85
86 static struct regulator_ops fixed_voltage_ops = {
87         .is_enabled = fixed_voltage_is_enabled,
88         .enable = fixed_voltage_enable,
89         .disable = fixed_voltage_disable,
90         .get_voltage = fixed_voltage_get_voltage,
91         .list_voltage = fixed_voltage_list_voltage,
92 };
93
94 static int regulator_fixed_voltage_probe(struct platform_device *pdev)
95 {
96         struct fixed_voltage_config *config = pdev->dev.platform_data;
97         struct fixed_voltage_data *drvdata;
98         int ret;
99
100         drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL);
101         if (drvdata == NULL) {
102                 dev_err(&pdev->dev, "Failed to allocate device data\n");
103                 ret = -ENOMEM;
104                 goto err;
105         }
106
107         drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
108         if (drvdata->desc.name == NULL) {
109                 dev_err(&pdev->dev, "Failed to allocate supply name\n");
110                 ret = -ENOMEM;
111                 goto err;
112         }
113         drvdata->desc.type = REGULATOR_VOLTAGE;
114         drvdata->desc.owner = THIS_MODULE;
115         drvdata->desc.ops = &fixed_voltage_ops;
116         drvdata->desc.n_voltages = 1;
117
118         drvdata->microvolts = config->microvolts;
119         drvdata->gpio = config->gpio;
120
121         if (gpio_is_valid(config->gpio)) {
122                 drvdata->enable_high = config->enable_high;
123
124                 /* FIXME: Remove below print warning
125                  *
126                  * config->gpio must be set to -EINVAL by platform code if
127                  * GPIO control is not required. However, early adopters
128                  * not requiring GPIO control may forget to initialize
129                  * config->gpio to -EINVAL. This will cause GPIO 0 to be used
130                  * for GPIO control.
131                  *
132                  * This warning will be removed once there are a couple of users
133                  * for this driver.
134                  */
135                 if (!config->gpio)
136                         dev_warn(&pdev->dev,
137                                 "using GPIO 0 for regulator enable control\n");
138
139                 ret = gpio_request(config->gpio, config->supply_name);
140                 if (ret) {
141                         dev_err(&pdev->dev,
142                            "Could not obtain regulator enable GPIO %d: %d\n",
143                                                         config->gpio, ret);
144                         goto err_name;
145                 }
146
147                 /* set output direction without changing state
148                  * to prevent glitch
149                  */
150                 drvdata->is_enabled = config->enabled_at_boot;
151                 ret = drvdata->is_enabled ?
152                                 config->enable_high : !config->enable_high;
153
154                 ret = gpio_direction_output(config->gpio, ret);
155                 if (ret) {
156                         dev_err(&pdev->dev,
157                            "Could not configure regulator enable GPIO %d direction: %d\n",
158                                                         config->gpio, ret);
159                         goto err_gpio;
160                 }
161
162         } else {
163                 /* Regulator without GPIO control is considered
164                  * always enabled
165                  */
166                 drvdata->is_enabled = 1;
167         }
168
169         drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
170                                           config->init_data, drvdata);
171         if (IS_ERR(drvdata->dev)) {
172                 ret = PTR_ERR(drvdata->dev);
173                 dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
174                 goto err_gpio;
175         }
176
177         platform_set_drvdata(pdev, drvdata);
178
179         dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name,
180                 drvdata->microvolts);
181
182         return 0;
183
184 err_gpio:
185         if (gpio_is_valid(config->gpio))
186                 gpio_free(config->gpio);
187 err_name:
188         kfree(drvdata->desc.name);
189 err:
190         kfree(drvdata);
191         return ret;
192 }
193
194 static int regulator_fixed_voltage_remove(struct platform_device *pdev)
195 {
196         struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
197
198         regulator_unregister(drvdata->dev);
199         kfree(drvdata->desc.name);
200         kfree(drvdata);
201
202         if (gpio_is_valid(drvdata->gpio))
203                 gpio_free(drvdata->gpio);
204
205         return 0;
206 }
207
208 static struct platform_driver regulator_fixed_voltage_driver = {
209         .probe          = regulator_fixed_voltage_probe,
210         .remove         = regulator_fixed_voltage_remove,
211         .driver         = {
212                 .name           = "reg-fixed-voltage",
213         },
214 };
215
216 static int __init regulator_fixed_voltage_init(void)
217 {
218         return platform_driver_register(&regulator_fixed_voltage_driver);
219 }
220 subsys_initcall(regulator_fixed_voltage_init);
221
222 static void __exit regulator_fixed_voltage_exit(void)
223 {
224         platform_driver_unregister(&regulator_fixed_voltage_driver);
225 }
226 module_exit(regulator_fixed_voltage_exit);
227
228 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
229 MODULE_DESCRIPTION("Fixed voltage regulator");
230 MODULE_LICENSE("GPL");
231 MODULE_ALIAS("platform:reg-fixed-voltage");