xburst: switch to 3.3 and add broken flag
[openwrt.git] / target / linux / xburst / patches-2.6.37 / 102-gpio-charger.patch
1 From 27681cf969174af00e63d572f257e2155bb914be Mon Sep 17 00:00:00 2001
2 From: Lars-Peter Clausen <lars@metafoo.de>
3 Date: Sat, 24 Apr 2010 12:29:31 +0200
4 Subject: [PATCH 04/23] Add gpio chager driver
5
6 ---
7  drivers/power/Kconfig              |    7 ++
8  drivers/power/Makefile             |    1 +
9  drivers/power/gpio-charger.c       |  185 ++++++++++++++++++++++++++++++++++++
10  include/linux/power/gpio-charger.h |   28 ++++++
11  4 files changed, 221 insertions(+), 0 deletions(-)
12  create mode 100644 drivers/power/gpio-charger.c
13  create mode 100644 include/linux/power/gpio-charger.h
14
15 --- a/drivers/power/Kconfig
16 +++ b/drivers/power/Kconfig
17 @@ -185,4 +185,11 @@ config CHARGER_TWL4030
18         help
19           Say Y here to enable support for TWL4030 Battery Charge Interface.
20  
21 +config CHARGER_GPIO
22 +       tristate "GPIO charger"
23 +       depends on GPIOLIB
24 +       help
25 +         Say Y to include support for chargers indicating their status through
26 +         a GPIO pin.
27 +
28  endif # POWER_SUPPLY
29 --- a/drivers/power/Makefile
30 +++ b/drivers/power/Makefile
31 @@ -32,3 +32,4 @@ obj-$(CONFIG_BATTERY_JZ4740)  += jz4740-b
32  obj-$(CONFIG_BATTERY_INTEL_MID)        += intel_mid_battery.o
33  obj-$(CONFIG_CHARGER_ISP1704)  += isp1704_charger.o
34  obj-$(CONFIG_CHARGER_TWL4030)  += twl4030_charger.o
35 +obj-$(CONFIG_CHARGER_GPIO)     += gpio-charger.o
36 --- /dev/null
37 +++ b/drivers/power/gpio-charger.c
38 @@ -0,0 +1,185 @@
39 +/*
40 + *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
41 + *  Driver for chargers indicating their status through a GPIO pin
42 + *
43 + *  This program is free software; you can redistribute         it and/or modify it
44 + *  under  the terms of         the GNU General  Public License as published by the
45 + *  Free Software Foundation;  either version 2 of the License, or (at your
46 + *  option) any later version.
47 + *
48 + *  You should have received a copy of the  GNU General Public License along
49 + *  with this program; if not, write  to the Free Software Foundation, Inc.,
50 + *  675 Mass Ave, Cambridge, MA 02139, USA.
51 + *
52 + */
53 +
54 +#include <linux/device.h>
55 +#include <linux/gpio.h>
56 +#include <linux/init.h>
57 +#include <linux/interrupt.h>
58 +#include <linux/kernel.h>
59 +#include <linux/module.h>
60 +#include <linux/platform_device.h>
61 +#include <linux/power_supply.h>
62 +#include <linux/slab.h>
63 +#include <linux/types.h>
64 +
65 +#include <linux/power/gpio-charger.h>
66 +
67 +struct gpio_charger {
68 +       const struct gpio_charger_platform_data *pdata;
69 +
70 +       int irq;
71 +
72 +       struct power_supply charger;
73 +};
74 +
75 +static irqreturn_t gpio_charger_irq(int irq, void *devid)
76 +{
77 +       struct power_supply *charger = devid;
78 +       power_supply_changed(charger);
79 +
80 +       return IRQ_HANDLED;
81 +}
82 +
83 +static inline struct gpio_charger *psy_to_gpio_charger(struct power_supply *psy)
84 +{
85 +       return container_of(psy, struct gpio_charger, charger);
86 +}
87 +
88 +static int gpio_charger_get_property(struct power_supply *psy,
89 +       enum power_supply_property psp, union power_supply_propval *val)
90 +{
91 +       struct gpio_charger *gpio_charger = psy_to_gpio_charger(psy);
92 +       const struct gpio_charger_platform_data *pdata = gpio_charger->pdata;
93 +
94 +       switch (psp) {
95 +       case POWER_SUPPLY_PROP_ONLINE:
96 +               val->intval = gpio_get_value(pdata->gpio);
97 +               val->intval ^= pdata->gpio_active_low;
98 +               break;
99 +       default:
100 +               return -EINVAL;
101 +       }
102 +
103 +       return 0;
104 +}
105 +
106 +static enum power_supply_property gpio_charger_properties[] = {
107 +       POWER_SUPPLY_PROP_ONLINE,
108 +};
109 +
110 +static int __devinit gpio_charger_probe(struct platform_device *pdev)
111 +{
112 +       const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data;
113 +       struct gpio_charger *gpio_charger;
114 +       struct power_supply *charger;
115 +       int ret;
116 +
117 +       if (!pdata) {
118 +               dev_err(&pdev->dev, "No platform data");
119 +               return -EINVAL;
120 +       }
121 +
122 +       gpio_charger = kzalloc(sizeof(*gpio_charger), GFP_KERNEL);
123 +
124 +       charger = &gpio_charger->charger;
125 +
126 +       charger->name = pdata->name;
127 +       charger->type = pdata->type;
128 +       charger->properties = gpio_charger_properties;
129 +       charger->num_properties = ARRAY_SIZE(gpio_charger_properties);
130 +       charger->get_property  = gpio_charger_get_property;
131 +       charger->supplied_to = pdata->batteries;
132 +       charger->num_supplicants = pdata->num_batteries;
133 +
134 +       if (gpio_is_valid(pdata->gpio)) {
135 +               ret = gpio_request(pdata->gpio, dev_name(&pdev->dev));
136 +               if (ret) {
137 +                       dev_err(&pdev->dev, "Failed to request gpio pin: %d\n", ret);
138 +                       goto err;
139 +               }
140 +               ret = gpio_direction_input(pdata->gpio);
141 +               if (ret) {
142 +                       dev_err(&pdev->dev, "Failed to set gpio to input: %d\n", ret);
143 +                       goto err_gpio_free;
144 +               }
145 +
146 +               gpio_charger->irq = gpio_to_irq(pdata->gpio);
147 +               if (gpio_charger->irq >= 0) {
148 +                       ret = request_irq(gpio_charger->irq, gpio_charger_irq,
149 +                       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
150 +                       dev_name(&pdev->dev), charger);
151 +                       if (ret) {
152 +                               dev_warn(&pdev->dev, "Failed to request online gpio irq: %d\n", ret);
153 +                               gpio_charger->irq = -1;
154 +                       }
155 +               }
156 +       }
157 +
158 +       gpio_charger->pdata = pdata;
159 +
160 +       ret = power_supply_register(&pdev->dev, charger);
161 +       if (ret < 0) {
162 +               dev_err(&pdev->dev, "Failed to register power supply: %d\n", ret);
163 +               goto err_gpio_free;
164 +       }
165 +
166 +       platform_set_drvdata(pdev, gpio_charger);
167 +
168 +       return 0;
169 +
170 +err_gpio_free:
171 +       if (gpio_is_valid(pdata->gpio)) {
172 +               if (gpio_charger->irq >= 0)
173 +                       free_irq(gpio_charger->irq, charger);
174 +               gpio_free(pdata->gpio);
175 +       }
176 +err:
177 +       return ret;
178 +}
179 +
180 +static int __devexit gpio_charger_remove(struct platform_device *pdev)
181 +{
182 +       struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);
183 +       const struct gpio_charger_platform_data *pdata = gpio_charger->pdata;
184 +
185 +       power_supply_unregister(&gpio_charger->charger);
186 +
187 +       if (gpio_is_valid(pdata->gpio)) {
188 +               if (gpio_charger->irq >= 0)
189 +                       free_irq(gpio_charger->irq, &gpio_charger->charger);
190 +               gpio_free(pdata->gpio);
191 +       }
192 +
193 +       platform_set_drvdata(pdev, NULL);
194 +       kfree(gpio_charger);
195 +
196 +       return 0;
197 +}
198 +
199 +static struct platform_driver  gpio_charger_driver = {
200 +       .probe = gpio_charger_probe,
201 +       .remove = __devexit_p(gpio_charger_remove),
202 +       .driver = {
203 +               .name = "gpio-charger",
204 +               .owner = THIS_MODULE,
205 +       },
206 +};
207 +
208 +static int __init gpio_charger_init(void)
209 +{
210 +       return platform_driver_register(&gpio_charger_driver);
211 +}
212 +module_init(gpio_charger_init);
213 +
214 +static void __exit gpio_charger_exit(void)
215 +{
216 +       platform_driver_unregister(&gpio_charger_driver);
217 +}
218 +module_exit(gpio_charger_exit);
219 +
220 +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
221 +MODULE_DESCRIPTION("Driver for chargers indicating their status through a gpio");
222 +MODULE_LICENSE("GPL");
223 +MODULE_ALIAS("platform:gpio-charger");
224 --- /dev/null
225 +++ b/include/linux/power/gpio-charger.h
226 @@ -0,0 +1,28 @@
227 +/*
228 + *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
229 + *
230 + *  This program is free software; you can redistribute         it and/or modify it
231 + *  under  the terms of         the GNU General  Public License as published by the
232 + *  Free Software Foundation;  either version 2 of the License, or (at your
233 + *  option) any later version.
234 + *
235 + *  You should have received a copy of the  GNU General Public License along
236 + *  with this program; if not, write  to the Free Software Foundation, Inc.,
237 + *  675 Mass Ave, Cambridge, MA 02139, USA.
238 + *
239 + */
240 +
241 +#ifndef __LINUX_POWER_GPIO_CHARGER_H__
242 +#define __LINUX_POWER_GPIO_CHARGER_H__
243 +
244 +struct gpio_charger_platform_data {
245 +       const char *name;
246 +       enum power_supply_type type;
247 +       int gpio;
248 +       int gpio_active_low;
249 +
250 +       char **batteries;
251 +       size_t num_batteries;
252 +};
253 +
254 +#endif