diff options
Diffstat (limited to 'packages/linux/linux-2.6.28/collie/0018-collie-add-battery-driver.patch')
-rw-r--r-- | packages/linux/linux-2.6.28/collie/0018-collie-add-battery-driver.patch | 473 |
1 files changed, 0 insertions, 473 deletions
diff --git a/packages/linux/linux-2.6.28/collie/0018-collie-add-battery-driver.patch b/packages/linux/linux-2.6.28/collie/0018-collie-add-battery-driver.patch deleted file mode 100644 index b28db63d87..0000000000 --- a/packages/linux/linux-2.6.28/collie/0018-collie-add-battery-driver.patch +++ /dev/null @@ -1,473 +0,0 @@ -From a2cf77eaf64b201a00b9682c25596ef0bcda8dc4 Mon Sep 17 00:00:00 2001 -From: Thomas Kunze <thommycheck@gmx.de> -Date: Tue, 10 Feb 2009 18:16:03 +0100 -Subject: [PATCH 18/23] collie: add battery driver - -This driver is based on tosa_battery.c. - -Conflicts: - - drivers/power/Makefile ---- - drivers/power/Kconfig | 7 + - drivers/power/Makefile | 1 + - drivers/power/collie_battery.c | 418 ++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 426 insertions(+), 0 deletions(-) - create mode 100644 drivers/power/collie_battery.c - -diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig -index 8e0c2b4..a945046 100644 ---- a/drivers/power/Kconfig -+++ b/drivers/power/Kconfig -@@ -56,6 +56,13 @@ config BATTERY_TOSA - Say Y to enable support for the battery on the Sharp Zaurus - SL-6000 (tosa) models. - -+config BATTERY_COLLIE -+ tristate "Sharp SL-5500 (collie) battery" -+ depends on SA1100_COLLIE && MCP_UCB1200 -+ help -+ Say Y to enable support for the battery on the Sharp Zaurus -+ SL-5500 (collie) models. -+ - config BATTERY_WM97XX - bool "WM97xx generic battery driver" - depends on TOUCHSCREEN_WM97XX=y -diff --git a/drivers/power/Makefile b/drivers/power/Makefile -index e8f1ece..51a7263 100644 ---- a/drivers/power/Makefile -+++ b/drivers/power/Makefile -@@ -21,5 +21,6 @@ obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o - obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o - obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o - obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o -+obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o - obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o - obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o -diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c -new file mode 100644 -index 0000000..039f41a ---- /dev/null -+++ b/drivers/power/collie_battery.c -@@ -0,0 +1,418 @@ -+/* -+ * Battery and Power Management code for the Sharp SL-5x00 -+ * -+ * Copyright (C) 2009 Thomas Kunze -+ * -+ * based on tosa_battery.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/power_supply.h> -+#include <linux/delay.h> -+#include <linux/spinlock.h> -+#include <linux/interrupt.h> -+#include <linux/gpio.h> -+#include <linux/mfd/ucb1x00.h> -+ -+#include <asm/mach/sharpsl_param.h> -+#include <asm/mach-types.h> -+#include <mach/collie.h> -+ -+static DEFINE_MUTEX(bat_lock); /* protects gpio pins */ -+static struct work_struct bat_work; -+static struct ucb1x00 *ucb; -+ -+struct collie_bat { -+ int status; -+ struct power_supply psy; -+ int full_chrg; -+ -+ struct mutex work_lock; /* protects data */ -+ -+ bool (*is_present)(struct collie_bat *bat); -+ int gpio_full; -+ int gpio_charge_on; -+ -+ int technology; -+ -+ int gpio_bat; -+ int adc_bat; -+ int adc_bat_divider; -+ int bat_max; -+ int bat_min; -+ -+ int gpio_temp; -+ int adc_temp; -+ int adc_temp_divider; -+}; -+ -+static struct collie_bat collie_bat_main; -+ -+static unsigned long collie_read_bat(struct collie_bat *bat) -+{ -+ unsigned long value = 0; -+ -+ if (bat->gpio_bat < 0 || bat->adc_bat < 0) -+ return 0; -+ mutex_lock(&bat_lock); -+ gpio_set_value(bat->gpio_bat, 1); -+ msleep(5); -+ ucb1x00_adc_enable(ucb); -+ value = ucb1x00_adc_read(ucb, bat->adc_bat, UCB_SYNC); -+ ucb1x00_adc_disable(ucb); -+ gpio_set_value(bat->gpio_bat, 0); -+ mutex_unlock(&bat_lock); -+ value = value * 1000000 / bat->adc_bat_divider; -+ -+ return value; -+} -+ -+static unsigned long collie_read_temp(struct collie_bat *bat) -+{ -+ unsigned long value = 0; -+ if (bat->gpio_temp < 0 || bat->adc_temp < 0) -+ return 0; -+ -+ mutex_lock(&bat_lock); -+ gpio_set_value(bat->gpio_temp, 1); -+ msleep(5); -+ ucb1x00_adc_enable(ucb); -+ value = ucb1x00_adc_read(ucb, bat->adc_temp, UCB_SYNC); -+ ucb1x00_adc_disable(ucb); -+ gpio_set_value(bat->gpio_temp, 0); -+ mutex_unlock(&bat_lock); -+ -+ value = value * 10000 / bat->adc_temp_divider; -+ -+ return value; -+} -+ -+static int collie_bat_get_property(struct power_supply *psy, -+ enum power_supply_property psp, -+ union power_supply_propval *val) -+{ -+ int ret = 0; -+ struct collie_bat *bat = container_of(psy, struct collie_bat, psy); -+ -+ if (bat->is_present && !bat->is_present(bat) -+ && psp != POWER_SUPPLY_PROP_PRESENT) { -+ return -ENODEV; -+ } -+ -+ switch (psp) { -+ case POWER_SUPPLY_PROP_STATUS: -+ val->intval = bat->status; -+ break; -+ case POWER_SUPPLY_PROP_TECHNOLOGY: -+ val->intval = bat->technology; -+ break; -+ case POWER_SUPPLY_PROP_VOLTAGE_NOW: -+ val->intval = collie_read_bat(bat); -+ break; -+ case POWER_SUPPLY_PROP_VOLTAGE_MAX: -+ if (bat->full_chrg == -1) -+ val->intval = bat->bat_max; -+ else -+ val->intval = bat->full_chrg; -+ break; -+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: -+ val->intval = bat->bat_max; -+ break; -+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: -+ val->intval = bat->bat_min; -+ break; -+ case POWER_SUPPLY_PROP_TEMP: -+ val->intval = collie_read_temp(bat); -+ break; -+ case POWER_SUPPLY_PROP_PRESENT: -+ val->intval = bat->is_present ? bat->is_present(bat) : 1; -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ return ret; -+} -+ -+static void collie_bat_external_power_changed(struct power_supply *psy) -+{ -+ schedule_work(&bat_work); -+} -+ -+static irqreturn_t collie_bat_gpio_isr(int irq, void *data) -+{ -+ pr_info("collie_bat_gpio irq: %d\n", gpio_get_value(irq_to_gpio(irq))); -+ schedule_work(&bat_work); -+ return IRQ_HANDLED; -+} -+ -+static void collie_bat_update(struct collie_bat *bat) -+{ -+ int old; -+ struct power_supply *psy = &bat->psy; -+ -+ mutex_lock(&bat->work_lock); -+ -+ old = bat->status; -+ -+ if (bat->is_present && !bat->is_present(bat)) { -+ printk(KERN_NOTICE "%s not present\n", psy->name); -+ bat->status = POWER_SUPPLY_STATUS_UNKNOWN; -+ bat->full_chrg = -1; -+ } else if (power_supply_am_i_supplied(psy)) { -+ if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING) { -+ gpio_set_value(bat->gpio_charge_on, 1); -+ mdelay(15); -+ } -+ -+ if (gpio_get_value(bat->gpio_full)) { -+ if (old == POWER_SUPPLY_STATUS_CHARGING || -+ bat->full_chrg == -1) -+ bat->full_chrg = collie_read_bat(bat); -+ -+ gpio_set_value(bat->gpio_charge_on, 0); -+ bat->status = POWER_SUPPLY_STATUS_FULL; -+ } else { -+ gpio_set_value(bat->gpio_charge_on, 1); -+ bat->status = POWER_SUPPLY_STATUS_CHARGING; -+ } -+ } else { -+ gpio_set_value(bat->gpio_charge_on, 0); -+ bat->status = POWER_SUPPLY_STATUS_DISCHARGING; -+ } -+ -+ if (old != bat->status) -+ power_supply_changed(psy); -+ -+ mutex_unlock(&bat->work_lock); -+} -+ -+static void collie_bat_work(struct work_struct *work) -+{ -+ collie_bat_update(&collie_bat_main); -+} -+ -+ -+static enum power_supply_property collie_bat_main_props[] = { -+ POWER_SUPPLY_PROP_STATUS, -+ POWER_SUPPLY_PROP_TECHNOLOGY, -+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, -+ POWER_SUPPLY_PROP_VOLTAGE_NOW, -+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, -+ POWER_SUPPLY_PROP_VOLTAGE_MAX, -+ POWER_SUPPLY_PROP_PRESENT, -+ POWER_SUPPLY_PROP_TEMP, -+}; -+ -+static enum power_supply_property collie_bat_bu_props[] = { -+ POWER_SUPPLY_PROP_STATUS, -+ POWER_SUPPLY_PROP_TECHNOLOGY, -+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, -+ POWER_SUPPLY_PROP_VOLTAGE_NOW, -+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, -+ POWER_SUPPLY_PROP_VOLTAGE_MAX, -+ POWER_SUPPLY_PROP_PRESENT, -+}; -+ -+static struct collie_bat collie_bat_main = { -+ .status = POWER_SUPPLY_STATUS_DISCHARGING, -+ .full_chrg = -1, -+ .psy = { -+ .name = "main-battery", -+ .type = POWER_SUPPLY_TYPE_BATTERY, -+ .properties = collie_bat_main_props, -+ .num_properties = ARRAY_SIZE(collie_bat_main_props), -+ .get_property = collie_bat_get_property, -+ .external_power_changed = collie_bat_external_power_changed, -+ .use_for_apm = 1, -+ }, -+ -+ .gpio_full = COLLIE_GPIO_CO, -+ .gpio_charge_on = COLLIE_GPIO_CHARGE_ON, -+ -+ .technology = POWER_SUPPLY_TECHNOLOGY_LIPO, -+ -+ .gpio_bat = COLLIE_GPIO_MBAT_ON, -+ .adc_bat = UCB_ADC_INP_AD1, -+ .adc_bat_divider = 155, -+ .bat_max = 4310000, -+ .bat_min = 1551 * 1000000 / 414, -+ -+ .gpio_temp = COLLIE_GPIO_TMP_ON, -+ .adc_temp = UCB_ADC_INP_AD0, -+ .adc_temp_divider = 10000, -+}; -+ -+static struct collie_bat collie_bat_bu = { -+ .status = POWER_SUPPLY_STATUS_UNKNOWN, -+ .full_chrg = -1, -+ -+ .psy = { -+ .name = "backup-battery", -+ .type = POWER_SUPPLY_TYPE_BATTERY, -+ .properties = collie_bat_bu_props, -+ .num_properties = ARRAY_SIZE(collie_bat_bu_props), -+ .get_property = collie_bat_get_property, -+ .external_power_changed = collie_bat_external_power_changed, -+ }, -+ -+ .gpio_full = -1, -+ .gpio_charge_on = -1, -+ -+ .technology = POWER_SUPPLY_TECHNOLOGY_LiMn, -+ -+ .gpio_bat = COLLIE_GPIO_BBAT_ON, -+ .adc_bat = UCB_ADC_INP_AD1, -+ .adc_bat_divider = 155, -+ .bat_max = 3000000, -+ .bat_min = 1900000, -+ -+ .gpio_temp = -1, -+ .adc_temp = -1, -+ .adc_temp_divider = -1, -+}; -+ -+static struct { -+ int gpio; -+ char *name; -+ bool output; -+ int value; -+} gpios[] = { -+ { COLLIE_GPIO_CO, "main battery full", 0, 0 }, -+ { COLLIE_GPIO_MAIN_BAT_LOW, "main battery low", 0, 0 }, -+ { COLLIE_GPIO_CHARGE_ON, "main charge on", 1, 0 }, -+ { COLLIE_GPIO_MBAT_ON, "main battery", 1, 0 }, -+ { COLLIE_GPIO_TMP_ON, "main battery temp", 1, 0 }, -+ { COLLIE_GPIO_BBAT_ON, "backup battery", 1, 0 }, -+}; -+ -+#ifdef CONFIG_PM -+static int collie_bat_suspend(struct ucb1x00_dev *dev, pm_message_t state) -+{ -+ /* flush all pending status updates */ -+ flush_scheduled_work(); -+ return 0; -+} -+ -+static int collie_bat_resume(struct ucb1x00_dev *dev) -+{ -+ /* things may have changed while we were away */ -+ schedule_work(&bat_work); -+ return 0; -+} -+#else -+#define collie_bat_suspend NULL -+#define collie_bat_resume NULL -+#endif -+ -+static int __devinit collie_bat_probe(struct ucb1x00_dev *dev) -+{ -+ int ret; -+ int i; -+ -+ if (!machine_is_collie()) -+ return -ENODEV; -+ -+ ucb = dev->ucb; -+ -+ for (i = 0; i < ARRAY_SIZE(gpios); i++) { -+ ret = gpio_request(gpios[i].gpio, gpios[i].name); -+ if (ret) { -+ i--; -+ goto err_gpio; -+ } -+ -+ if (gpios[i].output) -+ ret = gpio_direction_output(gpios[i].gpio, -+ gpios[i].value); -+ else -+ ret = gpio_direction_input(gpios[i].gpio); -+ -+ if (ret) -+ goto err_gpio; -+ } -+ -+ mutex_init(&collie_bat_main.work_lock); -+ -+ INIT_WORK(&bat_work, collie_bat_work); -+ -+ ret = power_supply_register(&dev->ucb->dev, &collie_bat_main.psy); -+ if (ret) -+ goto err_psy_reg_main; -+ ret = power_supply_register(&dev->ucb->dev, &collie_bat_bu.psy); -+ if (ret) -+ goto err_psy_reg_bu; -+ -+ ret = request_irq(gpio_to_irq(COLLIE_GPIO_CO), -+ collie_bat_gpio_isr, -+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, -+ "main full", &collie_bat_main); -+ if (!ret) { -+ schedule_work(&bat_work); -+ return 0; -+ } -+ power_supply_unregister(&collie_bat_bu.psy); -+err_psy_reg_bu: -+ power_supply_unregister(&collie_bat_main.psy); -+err_psy_reg_main: -+ -+ /* see comment in collie_bat_remove */ -+ flush_scheduled_work(); -+ -+ i--; -+err_gpio: -+ for (; i >= 0; i--) -+ gpio_free(gpios[i].gpio); -+ -+ return ret; -+} -+ -+static void __devexit collie_bat_remove(struct ucb1x00_dev *dev) -+{ -+ int i; -+ -+ free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main); -+ -+ power_supply_unregister(&collie_bat_bu.psy); -+ 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. -+ */ -+ flush_scheduled_work(); -+ -+ for (i = ARRAY_SIZE(gpios) - 1; i >= 0; i--) -+ gpio_free(gpios[i].gpio); -+} -+ -+static struct ucb1x00_driver collie_bat_driver = { -+ .add = collie_bat_probe, -+ .remove = __devexit_p(collie_bat_remove), -+ .suspend = collie_bat_suspend, -+ .resume = collie_bat_resume, -+}; -+ -+static int __init collie_bat_init(void) -+{ -+ return ucb1x00_register_driver(&collie_bat_driver); -+} -+ -+static void __exit collie_bat_exit(void) -+{ -+ ucb1x00_unregister_driver(&collie_bat_driver); -+} -+ -+module_init(collie_bat_init); -+module_exit(collie_bat_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Thomas Kunze"); -+MODULE_DESCRIPTION("Collie battery driver"); --- -1.5.6.5 - |