Skip to content

Commit

Permalink
Merge git://git.infradead.org/battery-2.6
Browse files Browse the repository at this point in the history
* git://git.infradead.org/battery-2.6: (21 commits)
  power_supply: Add MAX17042 Fuel Gauge Driver
  olpc_battery: Fix up XO-1.5 properties list
  olpc_battery: Add support for CURRENT_NOW and VOLTAGE_NOW
  olpc_battery: Add support for CHARGE_NOW
  olpc_battery: Add support for CHARGE_FULL_DESIGN
  olpc_battery: Ambient temperature is not available on XO-1.5
  jz4740-battery: Should include linux/io.h
  s3c_adc_battery: Add gpio_inverted field to pdata
  power_supply: Don't use flush_scheduled_work()
  power_supply: Fix use after free and memory leak
  gpio-charger: Fix potential race between irq handler and probe/remove
  gpio-charger: Provide default name for the power_supply
  gpio-charger: Check result of kzalloc
  jz4740-battery: Check if platform_data is supplied
  isp1704_charger: Detect charger after probe
  isp1704_charger: Set isp->dev before anything needs it
  isp1704_charger: Detect HUB/Host chargers
  isp1704_charger: Correct length for storing model
  power_supply: Add gpio charger driver
  jz4740-battery: Protect against concurrent battery readings
  ...
  • Loading branch information
Linus Torvalds committed Jan 14, 2011
2 parents 0ad53ee + 359ab9f commit 5957e33
Show file tree
Hide file tree
Showing 18 changed files with 838 additions and 69 deletions.
20 changes: 20 additions & 0 deletions drivers/power/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,16 @@ config BATTERY_MAX17040
in handheld and portable equipment. The MAX17040 is configured
to operate with a single lithium cell

config BATTERY_MAX17042
tristate "Maxim MAX17042/8997/8966 Fuel Gauge"
depends on I2C
help
MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries
in handheld and portable equipment. The MAX17042 is configured
to operate with a single lithium cell. MAX8997 and MAX8966 are
multi-function devices that include fuel gauages that are compatible
with MAX17042.

config BATTERY_Z2
tristate "Z2 battery driver"
depends on I2C && MACH_ZIPIT2
Expand Down Expand Up @@ -185,4 +195,14 @@ config CHARGER_TWL4030
help
Say Y here to enable support for TWL4030 Battery Charge Interface.

config CHARGER_GPIO
tristate "GPIO charger"
depends on GPIOLIB
help
Say Y to include support for chargers which report their online status
through a GPIO pin.

This driver can be build as a module. If so, the module will be
called gpio-charger.

endif # POWER_SUPPLY
2 changes: 2 additions & 0 deletions drivers/power/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ obj-$(CONFIG_BATTERY_BQ20Z75) += bq20z75.o
obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
obj-$(CONFIG_BATTERY_Z2) += z2_battery.o
obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o
obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
13 changes: 6 additions & 7 deletions drivers/power/collie_battery.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ static struct {
static int collie_bat_suspend(struct ucb1x00_dev *dev, pm_message_t state)
{
/* flush all pending status updates */
flush_scheduled_work();
flush_work_sync(&bat_work);
return 0;
}

Expand Down Expand Up @@ -362,7 +362,7 @@ static int __devinit collie_bat_probe(struct ucb1x00_dev *dev)
err_psy_reg_main:

/* see comment in collie_bat_remove */
flush_scheduled_work();
cancel_work_sync(&bat_work);

i--;
err_gpio:
Expand All @@ -382,12 +382,11 @@ static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
power_supply_unregister(&collie_bat_main.psy);

/*
* now flush all pending work.
* we won't get any more schedules, since all
* sources (isr and external_power_changed)
* are unregistered now.
* Now cancel the bat_work. We won't get any more schedules,
* since all sources (isr and external_power_changed) are
* unregistered now.
*/
flush_scheduled_work();
cancel_work_sync(&bat_work);

for (i = ARRAY_SIZE(gpios) - 1; i >= 0; i--)
gpio_free(gpios[i].gpio);
Expand Down
2 changes: 1 addition & 1 deletion drivers/power/ds2760_battery.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di)
if (di->rem_capacity > 100)
di->rem_capacity = 100;

if (di->current_uA >= 100L)
if (di->current_uA < -100L)
di->life_sec = -((di->accum_current_uAh - di->empty_uAh) * 36L)
/ (di->current_uA / 100L);
else
Expand Down
188 changes: 188 additions & 0 deletions drivers/power/gpio-charger.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/*
* Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
* Driver for chargers which report their online status through a GPIO pin
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/

#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/slab.h>

#include <linux/power/gpio-charger.h>

struct gpio_charger {
const struct gpio_charger_platform_data *pdata;
unsigned int irq;

struct power_supply charger;
};

static irqreturn_t gpio_charger_irq(int irq, void *devid)
{
struct power_supply *charger = devid;

power_supply_changed(charger);

return IRQ_HANDLED;
}

static inline struct gpio_charger *psy_to_gpio_charger(struct power_supply *psy)
{
return container_of(psy, struct gpio_charger, charger);
}

static int gpio_charger_get_property(struct power_supply *psy,
enum power_supply_property psp, union power_supply_propval *val)
{
struct gpio_charger *gpio_charger = psy_to_gpio_charger(psy);
const struct gpio_charger_platform_data *pdata = gpio_charger->pdata;

switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
val->intval = gpio_get_value(pdata->gpio);
val->intval ^= pdata->gpio_active_low;
break;
default:
return -EINVAL;
}

return 0;
}

static enum power_supply_property gpio_charger_properties[] = {
POWER_SUPPLY_PROP_ONLINE,
};

static int __devinit gpio_charger_probe(struct platform_device *pdev)
{
const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data;
struct gpio_charger *gpio_charger;
struct power_supply *charger;
int ret;
int irq;

if (!pdata) {
dev_err(&pdev->dev, "No platform data\n");
return -EINVAL;
}

if (!gpio_is_valid(pdata->gpio)) {
dev_err(&pdev->dev, "Invalid gpio pin\n");
return -EINVAL;
}

gpio_charger = kzalloc(sizeof(*gpio_charger), GFP_KERNEL);
if (!gpio_charger) {
dev_err(&pdev->dev, "Failed to alloc driver structure\n");
return -ENOMEM;
}

charger = &gpio_charger->charger;

charger->name = pdata->name ? pdata->name : "gpio-charger";
charger->type = pdata->type;
charger->properties = gpio_charger_properties;
charger->num_properties = ARRAY_SIZE(gpio_charger_properties);
charger->get_property = gpio_charger_get_property;
charger->supplied_to = pdata->supplied_to;
charger->num_supplicants = pdata->num_supplicants;

ret = gpio_request(pdata->gpio, dev_name(&pdev->dev));
if (ret) {
dev_err(&pdev->dev, "Failed to request gpio pin: %d\n", ret);
goto err_free;
}
ret = gpio_direction_input(pdata->gpio);
if (ret) {
dev_err(&pdev->dev, "Failed to set gpio to input: %d\n", ret);
goto err_gpio_free;
}

gpio_charger->pdata = pdata;

ret = power_supply_register(&pdev->dev, charger);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register power supply: %d\n",
ret);
goto err_gpio_free;
}

irq = gpio_to_irq(pdata->gpio);
if (irq > 0) {
ret = request_any_context_irq(irq, gpio_charger_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
dev_name(&pdev->dev), charger);
if (ret)
dev_warn(&pdev->dev, "Failed to request irq: %d\n", ret);
else
gpio_charger->irq = irq;
}

platform_set_drvdata(pdev, gpio_charger);

return 0;

err_gpio_free:
gpio_free(pdata->gpio);
err_free:
kfree(gpio_charger);
return ret;
}

static int __devexit gpio_charger_remove(struct platform_device *pdev)
{
struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);

if (gpio_charger->irq)
free_irq(gpio_charger->irq, &gpio_charger->charger);

power_supply_unregister(&gpio_charger->charger);

gpio_free(gpio_charger->pdata->gpio);

platform_set_drvdata(pdev, NULL);
kfree(gpio_charger);

return 0;
}

static struct platform_driver gpio_charger_driver = {
.probe = gpio_charger_probe,
.remove = __devexit_p(gpio_charger_remove),
.driver = {
.name = "gpio-charger",
.owner = THIS_MODULE,
},
};

static int __init gpio_charger_init(void)
{
return platform_driver_register(&gpio_charger_driver);
}
module_init(gpio_charger_init);

static void __exit gpio_charger_exit(void)
{
platform_driver_unregister(&gpio_charger_driver);
}
module_exit(gpio_charger_exit);

MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Driver for chargers which report their online status through a GPIO");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio-charger");
2 changes: 1 addition & 1 deletion drivers/power/intel_mid_battery.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ static int __devexit platform_pmic_battery_remove(struct platform_device *pdev)
power_supply_unregister(&pbi->usb);
power_supply_unregister(&pbi->batt);

flush_scheduled_work();
cancel_work_sync(&pbi->handler);
kfree(pbi);
return 0;
}
Expand Down
Loading

0 comments on commit 5957e33

Please sign in to comment.