1 From 97d812a16359f6c9afd2f866176828a7e6e071dc 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] Add gpio chager driver
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
15 diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
16 index 1e5506b..f700b03 100644
17 --- a/drivers/power/Kconfig
18 +++ b/drivers/power/Kconfig
19 @@ -153,4 +153,11 @@ config BATTERY_JZ4740
20 This driver can be build as a module. If so, the module will be
21 called jz4740-battery.
24 + tristate "GPIO charger"
27 + Say Y to include support for chargers indicating their status through
31 diff --git a/drivers/power/Makefile b/drivers/power/Makefile
32 index cf95009..51be41a 100644
33 --- a/drivers/power/Makefile
34 +++ b/drivers/power/Makefile
35 @@ -35,3 +35,4 @@ obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
36 obj-$(CONFIG_BATTERY_Z2) += z2_battery.o
37 obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
38 obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
39 +obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
40 diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
42 index 0000000..b877f74
44 +++ b/drivers/power/gpio-charger.c
47 + * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
48 + * Driver for chargers indicating their status through a GPIO pin
50 + * This program is free software; you can redistribute it and/or modify it
51 + * under the terms of the GNU General Public License as published by the
52 + * Free Software Foundation; either version 2 of the License, or (at your
53 + * option) any later version.
55 + * You should have received a copy of the GNU General Public License along
56 + * with this program; if not, write to the Free Software Foundation, Inc.,
57 + * 675 Mass Ave, Cambridge, MA 02139, USA.
61 +#include <linux/device.h>
62 +#include <linux/gpio.h>
63 +#include <linux/init.h>
64 +#include <linux/interrupt.h>
65 +#include <linux/kernel.h>
66 +#include <linux/module.h>
67 +#include <linux/platform_device.h>
68 +#include <linux/power_supply.h>
69 +#include <linux/slab.h>
70 +#include <linux/types.h>
72 +#include <linux/power/gpio-charger.h>
74 +struct gpio_charger {
75 + const struct gpio_charger_platform_data *pdata;
79 + struct power_supply charger;
82 +static irqreturn_t gpio_charger_irq(int irq, void *devid)
84 + struct power_supply *charger = devid;
85 + power_supply_changed(charger);
90 +static inline struct gpio_charger *psy_to_gpio_charger(struct power_supply *psy)
92 + return container_of(psy, struct gpio_charger, charger);
95 +static int gpio_charger_get_property(struct power_supply *psy,
96 + enum power_supply_property psp, union power_supply_propval *val)
98 + struct gpio_charger *gpio_charger = psy_to_gpio_charger(psy);
99 + const struct gpio_charger_platform_data *pdata = gpio_charger->pdata;
102 + case POWER_SUPPLY_PROP_ONLINE:
103 + val->intval = gpio_get_value(pdata->gpio);
104 + val->intval ^= pdata->gpio_active_low;
113 +static enum power_supply_property gpio_charger_properties[] = {
114 + POWER_SUPPLY_PROP_ONLINE,
117 +static int __devinit gpio_charger_probe(struct platform_device *pdev)
119 + const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data;
120 + struct gpio_charger *gpio_charger;
121 + struct power_supply *charger;
125 + dev_err(&pdev->dev, "No platform data");
129 + gpio_charger = kzalloc(sizeof(*gpio_charger), GFP_KERNEL);
131 + charger = &gpio_charger->charger;
133 + charger->name = pdata->name;
134 + charger->type = pdata->type;
135 + charger->properties = gpio_charger_properties;
136 + charger->num_properties = ARRAY_SIZE(gpio_charger_properties);
137 + charger->get_property = gpio_charger_get_property;
138 + charger->supplied_to = pdata->batteries;
139 + charger->num_supplicants = pdata->num_batteries;
141 + if (gpio_is_valid(pdata->gpio)) {
142 + ret = gpio_request(pdata->gpio, dev_name(&pdev->dev));
144 + dev_err(&pdev->dev, "Failed to request gpio pin: %d\n", ret);
147 + ret = gpio_direction_input(pdata->gpio);
149 + dev_err(&pdev->dev, "Failed to set gpio to input: %d\n", ret);
150 + goto err_gpio_free;
153 + gpio_charger->irq = gpio_to_irq(pdata->gpio);
154 + if (gpio_charger->irq >= 0) {
155 + ret = request_irq(gpio_charger->irq, gpio_charger_irq,
156 + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
157 + dev_name(&pdev->dev), charger);
159 + dev_warn(&pdev->dev, "Failed to request online gpio irq: %d\n", ret);
160 + gpio_charger->irq = -1;
165 + gpio_charger->pdata = pdata;
167 + ret = power_supply_register(&pdev->dev, charger);
169 + dev_err(&pdev->dev, "Failed to register power supply: %d\n", ret);
170 + goto err_gpio_free;
173 + platform_set_drvdata(pdev, gpio_charger);
178 + if (gpio_is_valid(pdata->gpio)) {
179 + if (gpio_charger->irq >= 0)
180 + free_irq(gpio_charger->irq, charger);
181 + gpio_free(pdata->gpio);
187 +static int __devexit gpio_charger_remove(struct platform_device *pdev)
189 + struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);
190 + const struct gpio_charger_platform_data *pdata = gpio_charger->pdata;
192 + power_supply_unregister(&gpio_charger->charger);
194 + if (gpio_is_valid(pdata->gpio)) {
195 + if (gpio_charger->irq >= 0)
196 + free_irq(gpio_charger->irq, &gpio_charger->charger);
197 + gpio_free(pdata->gpio);
200 + platform_set_drvdata(pdev, NULL);
201 + kfree(gpio_charger);
206 +static struct platform_driver gpio_charger_driver = {
207 + .probe = gpio_charger_probe,
208 + .remove = __devexit_p(gpio_charger_remove),
210 + .name = "gpio-charger",
211 + .owner = THIS_MODULE,
215 +static int __init gpio_charger_init(void)
217 + return platform_driver_register(&gpio_charger_driver);
219 +module_init(gpio_charger_init);
221 +static void __exit gpio_charger_exit(void)
223 + platform_driver_unregister(&gpio_charger_driver);
225 +module_exit(gpio_charger_exit);
227 +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
228 +MODULE_DESCRIPTION("Driver for chargers indicating their status through a gpio");
229 +MODULE_LICENSE("GPL");
230 +MODULE_ALIAS("platform:gpio-charger");
231 diff --git a/include/linux/power/gpio-charger.h b/include/linux/power/gpio-charger.h
233 index 0000000..95cdfc3
235 +++ b/include/linux/power/gpio-charger.h
238 + * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
240 + * This program is free software; you can redistribute it and/or modify it
241 + * under the terms of the GNU General Public License as published by the
242 + * Free Software Foundation; either version 2 of the License, or (at your
243 + * option) any later version.
245 + * You should have received a copy of the GNU General Public License along
246 + * with this program; if not, write to the Free Software Foundation, Inc.,
247 + * 675 Mass Ave, Cambridge, MA 02139, USA.
251 +#ifndef __LINUX_POWER_GPIO_CHARGER_H__
252 +#define __LINUX_POWER_GPIO_CHARGER_H__
254 +struct gpio_charger_platform_data {
256 + enum power_supply_type type;
258 + int gpio_active_low;
261 + size_t num_batteries;