Browse Source

Seperate charger logic from battery driver

SVN-Revision: 19504
Lars-Peter Clausen 15 years ago
parent
commit
27a0d8478d

+ 1 - 0
target/linux/xburst/config-2.6.32

@@ -24,6 +24,7 @@ CONFIG_BITREVERSE=y
 # CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
 # CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
 CONFIG_CFG80211_DEFAULT_PS_VALUE=0
+CONFIG_CHARGER_GPIO=y
 CONFIG_CONSOLE_TRANSLATIONS=y
 # CONFIG_CPU_BIG_ENDIAN is not set
 # CONFIG_CPU_CAVIUM_OCTEON is not set

+ 22 - 2
target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-qi_lb60.c

@@ -28,6 +28,7 @@
 #include <linux/spi/spi_gpio.h>
 #include <linux/power_supply.h>
 #include <linux/power/jz4740-battery.h>
+#include <linux/power/gpio-charger.h>
 #include <linux/mmc/jz4740_mmc.h>
 
 
@@ -286,8 +287,6 @@ static struct spi_board_info qi_lb60_spi_board_info[] = {
 
 /* Battery */
 static struct jz_batt_info qi_lb60_battery_pdata = {
-	.dc_dect_gpio	= GPIO_DC_DETE_N,
-	.usb_dect_gpio	= GPIO_USB_DETE,
 	.charg_stat_gpio  = GPIO_CHARG_STAT_N,
 
 	.min_voltag	= 3600000,
@@ -295,6 +294,26 @@ static struct jz_batt_info qi_lb60_battery_pdata = {
 	.batt_tech	= POWER_SUPPLY_TECHNOLOGY_LIPO,
 };
 
+static char *qi_lb60_batteries[] = {
+	"battery",
+};
+
+static struct gpio_charger_platform_data qi_lb60_charger_pdata = {
+	.name = "USB",
+	.type = POWER_SUPPLY_TYPE_USB,
+	.gpio = GPIO_USB_DETE,
+	.gpio_active_low = 1,
+	.batteries = qi_lb60_batteries,
+	.num_batteries = ARRAY_SIZE(qi_lb60_batteries),
+};
+
+static struct platform_device qi_lb60_charger_device = {
+	.name = "gpio-charger",
+	.dev = {
+		.platform_data = &qi_lb60_charger_pdata,
+	},
+};
+
 /* GPIO Key: power */
 static struct gpio_keys_button qi_lb60_gpio_keys_buttons[] = {
 	[0] = {
@@ -340,6 +359,7 @@ static struct platform_device *jz_platform_devices[] __initdata = {
 	&jz4740_adc_device,
 	&jz4740_battery_device,
 	&qi_lb60_gpio_keys,
+	&qi_lb60_charger_device,
 };
 
 static void __init board_gpio_setup(void)

+ 184 - 0
target/linux/xburst/files-2.6.32/drivers/power/gpio-charger.c

@@ -0,0 +1,184 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <[email protected]>
+ *  	Driver for chargers indicating their 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+
+#include <linux/power/gpio-charger.h>
+
+struct gpio_charger {
+	const struct gpio_charger_platform_data *pdata;
+
+	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;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform data");
+		return -EINVAL;
+	}
+
+	gpio_charger = kzalloc(sizeof(*gpio_charger), GFP_KERNEL);
+
+	charger = &gpio_charger->charger;
+
+	charger->name = pdata->name;
+	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->batteries;
+	charger->num_supplicants = pdata->num_batteries;
+
+	if (gpio_is_valid(pdata->gpio)) {
+		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;
+		}
+		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->irq = gpio_to_irq(pdata->gpio);
+		if (gpio_charger->irq >= 0) {
+			ret = request_irq(gpio_charger->irq, gpio_charger_irq,
+			IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+			dev_name(&pdev->dev), charger);
+			if (ret) {
+				dev_warn(&pdev->dev, "Failed to request online gpio irq: %d\n", ret);
+				gpio_charger->irq = -1;
+			}
+		}
+	}
+
+	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;
+	}
+
+	gpio_charger->pdata = pdata;
+	platform_set_drvdata(pdev, gpio_charger);
+
+	return 0;
+
+err_gpio_free:
+	if (gpio_is_valid(pdata->gpio)) {
+		if (gpio_charger->irq >= 0)
+			free_irq(gpio_charger->irq, charger);
+		gpio_free(pdata->gpio);
+	}
+err:
+	return ret;
+}
+
+static int __devexit gpio_charger_remove(struct platform_device *pdev)
+{
+	struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);
+	const struct gpio_charger_platform_data *pdata = gpio_charger->pdata;
+
+	power_supply_unregister(&gpio_charger->charger);
+
+	if (gpio_is_valid(pdata->gpio)) {
+		if (gpio_charger->irq >= 0)
+			free_irq(gpio_charger->irq, &gpio_charger->charger);
+		gpio_free(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 gpio_charger_exit(void)
+{
+	platform_driver_unregister(&gpio_charger_driver);
+}
+module_exit(gpio_charger_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <[email protected]>");
+MODULE_DESCRIPTION("Driver for chargers indicating their status through a gpio");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-charger");

+ 7 - 146
target/linux/xburst/files-2.6.32/drivers/power/jz4740-battery.c

@@ -24,9 +24,7 @@
 #include <linux/jz4740-adc.h>
 
 struct jz_battery_info {
-	struct power_supply usb;
 	struct power_supply bat;
-	struct power_supply ac;
 	int bat_status;
 	struct jz_batt_info *pdata;
 	struct mutex work_lock;
@@ -36,74 +34,6 @@ struct jz_battery_info {
 
 #define ps_to_jz_battery(x) container_of((x), struct jz_battery_info, bat);
 
-/*********************************************************************
- *		Power
- *********************************************************************/
-
-
-static int jz_get_power_prop(struct jz_battery_info *bat_info,
-			     struct power_supply *psy,
-			     enum power_supply_property psp,
-			     union power_supply_propval *val)
-{
-	int gpio;
-	
-	if (bat_info == 0 || bat_info->pdata == 0)
-		return -EINVAL;
-	gpio = (psy->type == POWER_SUPPLY_TYPE_MAINS) ?
-		bat_info->pdata->dc_dect_gpio :
-		bat_info->pdata->usb_dect_gpio;
-	if (!gpio_is_valid(gpio))
-		return -EINVAL;
-	switch (psp) {
-	case POWER_SUPPLY_PROP_ONLINE:
-		val->intval = !gpio_get_value(gpio);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int jz_usb_get_power_prop(struct power_supply *psy,
-				 enum power_supply_property psp,
-				 union power_supply_propval *val)
-{
-	struct jz_battery_info *bat_info = container_of(psy, struct jz_battery_info, usb);
-	return jz_get_power_prop(bat_info, psy, psp, val);
-}
-
-static int jz_ac_get_power_prop(struct power_supply *psy,
-				 enum power_supply_property psp,
-				 union power_supply_propval *val)
-{
-	struct jz_battery_info *bat_info = container_of(psy, struct jz_battery_info, ac);
-	return jz_get_power_prop(bat_info, psy, psp, val);
-}
-
-
-static enum power_supply_property jz_power_props[] = {
-	POWER_SUPPLY_PROP_ONLINE,
-};
-
-static struct power_supply jz_ac = {
-	.name = "ac",
-	.type = POWER_SUPPLY_TYPE_MAINS,
-	.properties = jz_power_props,
-	.num_properties = ARRAY_SIZE(jz_power_props),
-	.get_property = jz_ac_get_power_prop,
-};
-
-static struct power_supply jz_usb = {
-	.name = "usb",
-	.type = POWER_SUPPLY_TYPE_USB,
-	.properties = jz_power_props,
-	.num_properties = ARRAY_SIZE(jz_power_props),
-	.get_property = jz_usb_get_power_prop,
-};
-
-
 /*********************************************************************
  *		Battery properties
  *********************************************************************/
@@ -307,58 +237,24 @@ static int jz_bat_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct jz_battery_info *bat_info;
-	
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "Please set battery info\n");
+		return -EINVAL;
+	}
+
 	bat_info = kzalloc(sizeof(struct jz_battery_info), GFP_KERNEL);
 
 	if (!bat_info) {
 		return -ENOMEM;
 	}
 
-	if (!pdev->dev.platform_data) {
-		dev_err(&pdev->dev, "Please set battery info\n");
-		ret = -EINVAL;
-		goto err_platform_data;
-	}
 	platform_set_drvdata(pdev, bat_info);
 	bat_info->pdata = pdev->dev.platform_data;
 	bat_info->bat = bat_ps;
-	bat_info->usb = jz_usb;
-	bat_info->ac =  jz_ac;
 	mutex_init(&bat_info->work_lock);
 	INIT_DELAYED_WORK(&bat_info->bat_work, jz_bat_work);
 
-	if (gpio_is_valid(bat_info->pdata->dc_dect_gpio)) {
-		ret = gpio_request(bat_info->pdata->dc_dect_gpio, "AC/DC DECT");
-		if (ret) {
-			dev_err(&pdev->dev, "ac/dc dect gpio request failed.\n");
-
-			goto err_dc_gpio_request;
-		}
-		ret = gpio_direction_input(bat_info->pdata->dc_dect_gpio);
-		if (ret) {
-			dev_err(&pdev->dev, "ac/dc dect gpio direction failed.\n");
-
-			goto err_dc_gpio_direction;
-		}
-	}
-
-	if (gpio_is_valid(bat_info->pdata->usb_dect_gpio)) {
-		ret = gpio_request(bat_info->pdata->usb_dect_gpio, "USB DECT");
-		if (ret) {
-			dev_err(&pdev->dev, "usb dect gpio request failed.\n");
-
-			goto err_usb_gpio_request;
-		}
-		ret = gpio_direction_input(bat_info->pdata->usb_dect_gpio);
-		if (ret) {
-			dev_err(&pdev->dev, "usb dect gpio set direction failed.\n");
-			goto err_usb_gpio_direction;
-		}
-
-		jz_gpio_disable_pullup(bat_info->pdata->usb_dect_gpio);
-		/* TODO: Use generic gpio is better */
-	}
-
 	if (gpio_is_valid(bat_info->pdata->charg_stat_gpio)) {
 		ret = gpio_request(bat_info->pdata->charg_stat_gpio, "CHARG STAT");
 		if (ret) {
@@ -370,25 +266,7 @@ static int jz_bat_probe(struct platform_device *pdev)
 			dev_err(&pdev->dev, "charger state gpio set direction failed.\n");
 			goto err_charg_gpio_direction;
 		}
-	}
-	
-	if (gpio_is_valid(bat_info->pdata->dc_dect_gpio)) {
-		ret = power_supply_register(&pdev->dev, &bat_info->ac);
-		if (ret) {
-			dev_err(&pdev->dev, "power supply ac/dc register failed.\n");
-			goto err_power_register_ac;
-		}
-	}
-
-	if (gpio_is_valid(bat_info->pdata->usb_dect_gpio)) {
-		ret = power_supply_register(&pdev->dev, &bat_info->usb);
-		if (ret) {
-			dev_err(&pdev->dev, "power supply usb register failed.\n");
-			goto err_power_register_usb;
-		}
-	}
 
-	if (gpio_is_valid(bat_info->pdata->charg_stat_gpio)) {
 		ret = power_supply_register(&pdev->dev, &bat_info->bat);
 		if (ret) {
 			dev_err(&pdev->dev, "power supply battery register failed.\n");
@@ -405,20 +283,9 @@ static int jz_bat_probe(struct platform_device *pdev)
 	return ret;
 
 err_power_register_bat:
-	power_supply_unregister(&bat_info->usb);
-err_power_register_usb:
-	power_supply_unregister(&bat_info->ac);
-err_power_register_ac:
 err_charg_gpio_direction:
 	gpio_free(bat_info->pdata->charg_stat_gpio);
 err_charg_gpio_request:
-err_usb_gpio_direction:
-	gpio_free(bat_info->pdata->usb_dect_gpio);
-err_usb_gpio_request:
-err_dc_gpio_direction:
-	gpio_free(bat_info->pdata->dc_dect_gpio);
-err_dc_gpio_request:
-err_platform_data:
 	kfree(bat_info);
 	return ret;
 }
@@ -426,19 +293,13 @@ err_platform_data:
 static int jz_bat_remove(struct platform_device *pdev)
 {
 	struct jz_battery_info *bat_info = platform_get_drvdata(pdev);
-		
+
 	if (bat_info->pdata) {
-		if (gpio_is_valid(bat_info->pdata->dc_dect_gpio))
-			gpio_free(bat_info->pdata->dc_dect_gpio);
-		if (gpio_is_valid(bat_info->pdata->usb_dect_gpio))
-			gpio_free(bat_info->pdata->usb_dect_gpio);
 		if (gpio_is_valid(bat_info->pdata->charg_stat_gpio))
 			gpio_free(bat_info->pdata->charg_stat_gpio);
 	}
 
 	power_supply_unregister(&bat_ps);
-	power_supply_unregister(&jz_ac);
-	power_supply_unregister(&jz_usb);
 
 	return 0;
 }

+ 28 - 0
target/linux/xburst/files-2.6.32/include/linux/power/gpio-charger.h

@@ -0,0 +1,28 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <[email protected]>
+ *
+ *  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.
+ *
+ */
+
+#ifndef __LINUX_POWER_GPIO_CHARGER_H__
+#define __LINUX_POWER_GPIO_CHARGER_H__
+
+struct gpio_charger_platform_data {
+	const char *name;
+	enum power_supply_type type;
+	int gpio;
+	int gpio_active_low;
+
+	char **batteries;
+	size_t num_batteries;
+};
+
+#endif

+ 0 - 2
target/linux/xburst/files-2.6.32/include/linux/power/jz4740-battery.h

@@ -16,8 +16,6 @@
 #define __JZ4740_BATTERY_H
 
 struct jz_batt_info {
-	int dc_dect_gpio;	/* GPIO port of DC charger detection */
-	int usb_dect_gpio;	/* GPIO port of USB charger detection */
 	int charg_stat_gpio;	/* GPIO port of Charger state */
 
 	int min_voltag;		/* Mininal battery voltage in uV */

+ 21 - 0
target/linux/xburst/patches-2.6.32/106-gpio-charger.patch

@@ -0,0 +1,21 @@
+--- a/drivers/power/Makefile	2010-02-03 13:16:32.000000000 +0100
++++ b/drivers/power/Makefile	2010-02-01 14:55:46.000000000 +0100
+@@ -30,3 +30,4 @@
+ obj-$(CONFIG_BATTERY_MAX17040)	+= max17040_battery.o
+ obj-$(CONFIG_CHARGER_PCF50633)	+= pcf50633-charger.o
+ obj-$(CONFIG_BATTERY_JZ4740)	+= jz4740-battery.o
++obj-$(CONFIG_CHARGER_GPIO)	+= gpio-charger.o
+--- a/drivers/power/Kconfig	2010-02-03 13:16:32.000000000 +0100
++++ b/drivers/power/Kconfig	2010-02-01 14:58:24.000000000 +0100
+@@ -121,4 +121,11 @@
+ 	  This driver can be build as a module. If so, the module will be
+ 	  called jz4740-battery.
+ 
++config CHARGER_GPIO
++	tristate "GPIO charger"
++	depends on GPIOLIB
++	help
++	  Say Y to include support for chargers indicating their status through
++	  a GPIO pin.
++
+ endif # POWER_SUPPLY