diff options
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.24/1324-gta01-battery-driver.patch.patch')
-rw-r--r-- | target/linux/s3c24xx/patches-2.6.24/1324-gta01-battery-driver.patch.patch | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.24/1324-gta01-battery-driver.patch.patch b/target/linux/s3c24xx/patches-2.6.24/1324-gta01-battery-driver.patch.patch new file mode 100644 index 000000000..c98373c8a --- /dev/null +++ b/target/linux/s3c24xx/patches-2.6.24/1324-gta01-battery-driver.patch.patch @@ -0,0 +1,326 @@ +From 8aefbe43a7864e611dca9821daec3e10009e7171 Mon Sep 17 00:00:00 2001 +From: Mike Westerhof <mwester@dls.net> +Date: Thu, 13 Nov 2008 20:50:55 +0000 +Subject: [PATCH] gta01-battery-driver.patch + +Adds a simple pass-through battery driver module for the GTA01. +This will simplify user-space by providing the same sysfs API +on both GTA01 and GTA02, and is a first step towards eliminating +the need for APM emulation. + +Signed-off-by: Mike Westerhof <mwester@dls.net> +--- + arch/arm/configs/gta02-moredrivers-defconfig | 1 + + defconfig-gta01 | 1 + + defconfig-gta02 | 1 + + drivers/i2c/chips/pcf50606.c | 96 +++++++++++++++++++++++++ + drivers/power/Kconfig | 6 ++ + drivers/power/Makefile | 1 + + drivers/power/gta01_battery.c | 97 ++++++++++++++++++++++++++ + 7 files changed, 203 insertions(+), 0 deletions(-) + create mode 100644 drivers/power/gta01_battery.c + +diff --git a/arch/arm/configs/gta02-moredrivers-defconfig b/arch/arm/configs/gta02-moredrivers-defconfig +index 113eaec..5e1547e 100644 +--- a/arch/arm/configs/gta02-moredrivers-defconfig ++++ b/arch/arm/configs/gta02-moredrivers-defconfig +@@ -1060,6 +1060,7 @@ CONFIG_POWER_SUPPLY_DEBUG=y + CONFIG_PDA_POWER=y + CONFIG_APM_POWER=y + # CONFIG_BATTERY_DS2760 is not set ++# CONFIG_BATTERY_GTA01 is not set + CONFIG_BATTERY_BQ27000_HDQ=y + CONFIG_GTA02_HDQ=y + CONFIG_HWMON=y +diff --git a/defconfig-gta01 b/defconfig-gta01 +index cecb57f..e2e4330 100644 +--- a/defconfig-gta01 ++++ b/defconfig-gta01 +@@ -1021,6 +1021,7 @@ CONFIG_POWER_SUPPLY=y + # CONFIG_PDA_POWER is not set + # CONFIG_APM_POWER is not set + # CONFIG_BATTERY_DS2760 is not set ++CONFIG_BATTERY_GTA01=y + CONFIG_BATTERY_BQ27000_HDQ=y + CONFIG_GTA02_HDQ=y + # CONFIG_HWMON is not set +diff --git a/defconfig-gta02 b/defconfig-gta02 +index 619f7f2..2a6e398 100644 +--- a/defconfig-gta02 ++++ b/defconfig-gta02 +@@ -1021,6 +1021,7 @@ CONFIG_POWER_SUPPLY=y + # CONFIG_PDA_POWER is not set + CONFIG_APM_POWER=y + # CONFIG_BATTERY_DS2760 is not set ++# CONFIG_BATTERY_GTA01 is not set + CONFIG_BATTERY_BQ27000_HDQ=y + CONFIG_GTA02_HDQ=y + # CONFIG_HWMON is not set +diff --git a/drivers/i2c/chips/pcf50606.c b/drivers/i2c/chips/pcf50606.c +index 706ce6d..f585013 100644 +--- a/drivers/i2c/chips/pcf50606.c ++++ b/drivers/i2c/chips/pcf50606.c +@@ -50,6 +50,7 @@ + #include <linux/platform_device.h> + #include <linux/pcf50606.h> + #include <linux/apm-emulation.h> ++#include <linux/power_supply.h> + + #include <asm/mach-types.h> + #include <asm/arch/gta01.h> +@@ -141,6 +142,12 @@ struct pcf50606_data { + + static struct i2c_driver pcf50606_driver; + ++/* This global is set by the pcf50606 driver to the correct callback ++ * for the gta01 battery driver. */ ++int (*pmu_bat_get_property)(struct power_supply *, enum power_supply_property, ++ union power_supply_propval *); ++EXPORT_SYMBOL(pmu_bat_get_property); ++ + /* This is an ugly construct on how to access the (currently single/global) + * pcf50606 handle from other code in the kernel. I didn't really come up with + * a more decent method of dynamically resolving this */ +@@ -1270,6 +1277,92 @@ static void pcf50606_get_power_status(struct apm_power_info *info) + } + + /*********************************************************************** ++ * Battery driver interface ++ ***********************************************************************/ ++static int pcf50606_bat_get_property(struct power_supply *psy, ++ enum power_supply_property psp, ++ union power_supply_propval *val) ++{ ++ u_int16_t adc, adc_adcin1; ++ u_int8_t mbcc1, chgmod; ++ struct pcf50606_data *pcf = pcf50606_global; ++ int ret = 0; ++ ++ switch (psp) { ++ ++ case POWER_SUPPLY_PROP_STATUS: ++ if (!(reg_read(pcf, PCF50606_REG_OOCS) & PCF50606_OOCS_EXTON)) { ++ /* No charger, clearly we're discharging then */ ++ val->intval = POWER_SUPPLY_STATUS_DISCHARGING; ++ } else { ++ ++ /* We have a charger present, get charge mode */ ++ mbcc1 = reg_read(pcf, PCF50606_REG_MBCC1); ++ chgmod = (mbcc1 & PCF50606_MBCC1_CHGMOD_MASK); ++ switch (chgmod) { ++ ++ /* TODO: How to determine POWER_SUPPLY_STATUS_FULL? */ ++ ++ case PCF50606_MBCC1_CHGMOD_QUAL: ++ case PCF50606_MBCC1_CHGMOD_PRE: ++ case PCF50606_MBCC1_CHGMOD_IDLE: ++ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; ++ break; ++ ++ case PCF50606_MBCC1_CHGMOD_TRICKLE: ++ case PCF50606_MBCC1_CHGMOD_FAST_CCCV: ++ case PCF50606_MBCC1_CHGMOD_FAST_NOCC: ++ case PCF50606_MBCC1_CHGMOD_FAST_NOCV: ++ case PCF50606_MBCC1_CHGMOD_FAST_SW: ++ val->intval = POWER_SUPPLY_STATUS_CHARGING; ++ break; ++ ++ default: ++ val->intval = POWER_SUPPLY_STATUS_UNKNOWN; ++ break; ++ ++ } ++ } ++ ++ case POWER_SUPPLY_PROP_PRESENT: ++ val->intval = 1; /* Must be, or the magic smoke comes out */ ++ break; ++ ++ case POWER_SUPPLY_PROP_ONLINE: ++ val->intval = !!(reg_read(pcf, PCF50606_REG_OOCS) & ++ PCF50606_OOCS_EXTON); ++ break; ++ ++ case POWER_SUPPLY_PROP_VOLTAGE_NOW: ++ adc = adc_read(pcf, PCF50606_ADCMUX_BATVOLT_RES, NULL); ++ /* (adc * 6000000) / 1024 == (adc * 46875) / 8 */ ++ val->intval = (adc * 46875) / 8; ++ break; ++ ++ case POWER_SUPPLY_PROP_CURRENT_NOW: ++ adc = adc_read(pcf, PCF50606_ADCMUX_BATVOLT_ADCIN1, ++ &adc_adcin1); ++ val->intval = adc_to_chg_milliamps(pcf, adc_adcin1, adc) * 1000; ++ break; ++ ++ case POWER_SUPPLY_PROP_TEMP: ++ adc = adc_read(pcf, PCF50606_ADCMUX_BATTEMP, NULL); ++ val->intval = rntc_to_temp(adc_to_rntc(pcf, adc)) * 10; ++ break; ++ ++ case POWER_SUPPLY_PROP_CAPACITY: ++ val->intval = battvolt_scale(pcf50606_battvolt(pcf)); ++ break; ++ ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++/*********************************************************************** + * RTC + ***********************************************************************/ + +@@ -1900,6 +1993,7 @@ static int pcf50606_detect(struct i2c_adapter *adapter, int address, int kind) + } + + apm_get_power_status = pcf50606_get_power_status; ++ pmu_bat_get_property = pcf50606_bat_get_property; + + #ifdef CONFIG_MACH_NEO1973_GTA01 + if (machine_is_neo1973_gta01()) { +@@ -1962,6 +2056,8 @@ static int pcf50606_detach_client(struct i2c_client *client) + struct pcf50606_data *pcf = i2c_get_clientdata(client); + + apm_get_power_status = NULL; ++ pmu_bat_get_property = NULL; ++ + input_unregister_device(pcf->input_dev); + + if (pcf->pdata->used_features & PCF50606_FEAT_PWM_BL) +diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig +index 8c50ecb..470e08c 100644 +--- a/drivers/power/Kconfig ++++ b/drivers/power/Kconfig +@@ -62,5 +62,11 @@ config GTA02_HDQ + on the Neo Freerunner. You probably want to select + at least BATTERY_BQ27000_HDQ as well + ++config BATTERY_GTA01 ++ tristate "Neo GTA01 battery" ++ depends on MACH_NEO1973_GTA01 ++ help ++ Say Y to enable support for the battery on the Neo GTA01 ++ + endif # POWER_SUPPLY + +diff --git a/drivers/power/Makefile b/drivers/power/Makefile +index d7e87ad..2013e89 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_BQ27000_HDQ) += bq27000_battery.o ++obj-$(CONFIG_BATTERY_GTA01) += gta01_battery.o + + obj-$(CONFIG_GTA02_HDQ) += gta02_hdq.o +diff --git a/drivers/power/gta01_battery.c b/drivers/power/gta01_battery.c +new file mode 100644 +index 0000000..5acb45c +--- /dev/null ++++ b/drivers/power/gta01_battery.c +@@ -0,0 +1,97 @@ ++/* ++ * Battery driver for the Openmoko GTA01 device, using the pcf50606 chip. ++ * ++ * This is nothing more than a write-thru interface to the real logic, ++ * which is part of the pcf50606.c multifunction chip driver. ++ * Copyright © 2008 Mike Westerhof <mwester@dls.net> ++ * ++ * ++ * Portions liberally borrowed from olpc_battery.c, copyright below: ++ * Copyright © 2006 David Woodhouse <dwmw2@infradead.org> ++ * ++ * 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/module.h> ++#include <linux/err.h> ++#include <linux/platform_device.h> ++#include <linux/power_supply.h> ++#include <linux/jiffies.h> ++#include <linux/sched.h> ++ ++/********************************************************************* ++ * This global is set by the pcf50606 driver to the correct callback ++ *********************************************************************/ ++ ++extern int (*pmu_bat_get_property)(struct power_supply *, ++ enum power_supply_property, ++ union power_supply_propval *); ++ ++ ++/********************************************************************* ++ * Battery properties ++ *********************************************************************/ ++static int gta01_bat_get_property(struct power_supply *psy, ++ enum power_supply_property psp, ++ union power_supply_propval *val) ++{ ++ if (pmu_bat_get_property) ++ return (pmu_bat_get_property)(psy, psp, val); ++ else ++ return -ENODEV; ++} ++ ++static enum power_supply_property gta01_bat_props[] = { ++ POWER_SUPPLY_PROP_STATUS, ++ POWER_SUPPLY_PROP_PRESENT, ++ POWER_SUPPLY_PROP_ONLINE, ++ POWER_SUPPLY_PROP_VOLTAGE_NOW, ++ POWER_SUPPLY_PROP_CURRENT_NOW, ++ POWER_SUPPLY_PROP_TEMP, ++ POWER_SUPPLY_PROP_CAPACITY, ++}; ++ ++/********************************************************************* ++ * Initialisation ++ *********************************************************************/ ++ ++static struct platform_device *bat_pdev; ++ ++static struct power_supply gta01_bat = { ++ .properties = gta01_bat_props, ++ .num_properties = ARRAY_SIZE(gta01_bat_props), ++ .get_property = gta01_bat_get_property, ++ .use_for_apm = 0, /* pcf50606 driver has its own apm driver */ ++}; ++ ++static int __init gta01_bat_init(void) ++{ ++ int ret; ++ ++ bat_pdev = platform_device_register_simple("gta01-battery", 0, NULL, 0); ++ if (IS_ERR(bat_pdev)) ++ return PTR_ERR(bat_pdev); ++ ++ gta01_bat.name = bat_pdev->name; ++ ++ ret = power_supply_register(&bat_pdev->dev, >a01_bat); ++ if (ret) ++ platform_device_unregister(bat_pdev); ++ ++ return ret; ++} ++ ++static void __exit gta01_bat_exit(void) ++{ ++ power_supply_unregister(>a01_bat); ++ platform_device_unregister(bat_pdev); ++} ++ ++module_init(gta01_bat_init); ++module_exit(gta01_bat_exit); ++ ++MODULE_AUTHOR("Mike Westerhof <mwester@dls.net>"); ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Battery driver for GTA01"); +-- +1.5.6.5 + |