Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5957e33d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 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
  ...
parents 0ad53eee 359ab9f5
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -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
@@ -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 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ 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
@@ -32,3 +33,4 @@ 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
+6 −7
Original line number Diff line number Diff line
@@ -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;
}

@@ -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:
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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
+188 −0
Original line number Diff line number Diff line
/*
 *  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");
Loading