summaryrefslogtreecommitdiff
path: root/target/linux/s3c24xx/patches-2.6.24/1242-fix-bq27000-charger-state-tracking.patch.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.24/1242-fix-bq27000-charger-state-tracking.patch.patch')
-rw-r--r--target/linux/s3c24xx/patches-2.6.24/1242-fix-bq27000-charger-state-tracking.patch.patch280
1 files changed, 280 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.24/1242-fix-bq27000-charger-state-tracking.patch.patch b/target/linux/s3c24xx/patches-2.6.24/1242-fix-bq27000-charger-state-tracking.patch.patch
new file mode 100644
index 0000000..20442ad
--- /dev/null
+++ b/target/linux/s3c24xx/patches-2.6.24/1242-fix-bq27000-charger-state-tracking.patch.patch
@@ -0,0 +1,280 @@
+From 46159c9a3fba291d106625092fd62358548894e0 Mon Sep 17 00:00:00 2001
+From: Andy Green <andy@openmoko.com>
+Date: Tue, 22 Jul 2008 13:16:16 +0100
+Subject: [PATCH] fix-bq27000-charger-state-tracking.patch
+
+Charger trigger stuff goes and asks for POWER_SUPPLY_PROP_STATUS
+to figure out what the charger state is. But until now, we only
+reported there what we found out from HDQ, and the HDQ registers
+are not updated very often in the coulomb counter, it can be 4
+or more second lag before it tells us about what it experiences.
+
+When we react to USB insertion and only after 500ms debounce tell
+power_supply stuff that something changed, it most times will
+see old pre-USB-insertion state from bq27000 over HDQ at that time
+and will report it ain't charging, buggering up the LED trigger
+tracking.
+
+This patch maintains distance between bq27000 and pcf50633 by
+having platform callbacks in bq27000 that it can use to ask about
+definitive charger "online" presence and "activity", whether the
+charger says it is charging. If these callbacks are implemented
+(and we implement them in this patch up in mach_gta02.c) then
+this information is used in preference to what is found from
+HDQ.
+
+Result is if you set the LED trigger like this:
+
+echo bat-charging > /sys/devices/platform/gta02-led.0/leds/gta02-aux:red/trigger
+
+then it lights up properly on USB insertion now, goes away on
+removal properly, as as far as I saw, when charging stops too.
+
+Signed-off-by: Andy Green <andy@openmoko.com>
+---
+ arch/arm/mach-s3c2440/mach-gta02.c | 32 +++++++++++++++--
+ drivers/power/bq27000_battery.c | 65 ++++++++++++++++++++++++-----------
+ include/linux/bq27000_battery.h | 2 +
+ 3 files changed, 74 insertions(+), 25 deletions(-)
+
+diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
+index 59ba890..1fcd3fd 100644
+--- a/arch/arm/mach-s3c2440/mach-gta02.c
++++ b/arch/arm/mach-s3c2440/mach-gta02.c
+@@ -96,6 +96,9 @@ struct resume_dependency resume_dep_jbt_glamo;
+ struct resume_dependency resume_dep_glamo_mci_pcf;
+
+
++static int gta02_charger_online_status;
++static int gta02_charger_active_status;
++
+ /* define FIQ IPC struct */
+ /*
+ * contains stuff FIQ ISR modifies and normal kernel code can see and use
+@@ -457,12 +460,25 @@ static struct s3c2410_uartcfg gta02_uartcfgs[] = {
+
+ /* BQ27000 Battery */
+
++static int gta02_get_charger_online_status(void)
++{
++ return gta02_charger_online_status;
++}
++
++static int gta02_get_charger_active_status(void)
++{
++ return gta02_charger_active_status;
++}
++
++
+ struct bq27000_platform_data bq27000_pdata = {
+ .name = "bat",
+ .rsense_mohms = 20,
+ .hdq_read = gta02hdq_read,
+ .hdq_write = gta02hdq_write,
+ .hdq_initialized = gta02hdq_initialized,
++ .get_charger_online_status = gta02_get_charger_online_status,
++ .get_charger_active_status = gta02_get_charger_active_status
+ };
+
+ struct platform_device bq27000_battery_device = {
+@@ -481,12 +497,20 @@ static int pmu_callback(struct device *dev, unsigned int feature,
+ switch (feature) {
+ case PCF50633_FEAT_MBC:
+ switch (event) {
+- case PMU_EVT_USB_INSERT:
+- case PMU_EVT_USB_REMOVE:
+ case PMU_EVT_CHARGER_IDLE:
++ gta02_charger_active_status = 0;
++ break;
+ case PMU_EVT_CHARGER_ACTIVE:
+- case PMU_EVT_INSERT: /* adapter */
+- case PMU_EVT_REMOVE: /* adapter */
++ gta02_charger_active_status = 1;
++ break;
++ case PMU_EVT_USB_INSERT:
++ gta02_charger_online_status = 1;
++ break;
++ case PMU_EVT_USB_REMOVE:
++ gta02_charger_online_status = 0;
++ break;
++ case PMU_EVT_INSERT: /* adapter is unsused */
++ case PMU_EVT_REMOVE: /* adapter is unused */
+ break;
+ default:
+ break;
+diff --git a/drivers/power/bq27000_battery.c b/drivers/power/bq27000_battery.c
+index 4855d5a..7020608 100644
+--- a/drivers/power/bq27000_battery.c
++++ b/drivers/power/bq27000_battery.c
+@@ -113,12 +113,7 @@ enum bq27000_status_flags {
+ struct bq27000_device_info {
+ struct device *dev;
+ struct power_supply bat;
+-
+- int rsense_mohms; /* from platform */
+-
+- int (*hdq_initialized)(void); /* from platform */
+- int (*hdq_read)(int); /* from platform */
+- int (*hdq_write)(int, u8); /* from platform */
++ struct bq27000_platform_data *pdata;
+ };
+
+ /*
+@@ -136,16 +131,16 @@ static int hdq_read16(struct bq27000_device_info *di, int address)
+
+ while (retries--) {
+
+- high = (di->hdq_read)(address + 1); /* high part */
++ high = (di->pdata->hdq_read)(address + 1); /* high part */
+
+ if (high < 0)
+ return high;
+- acc = (di->hdq_read)(address);
++ acc = (di->pdata->hdq_read)(address);
+ if (acc < 0)
+ return acc;
+
+ /* confirm high didn't change between reading it and low */
+- if (high == (di->hdq_read)(address + 1))
++ if (high == (di->pdata->hdq_read)(address + 1))
+ return (high << 8) | acc;
+ }
+
+@@ -170,12 +165,36 @@ static int bq27000_battery_get_property(struct power_supply *psy,
+ int v, n;
+ struct bq27000_device_info *di = to_bq27000_device_info(psy);
+
+- if (!(di->hdq_initialized)())
++ if (!(di->pdata->hdq_initialized)())
+ return -EINVAL;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
++
++ if (!di->pdata->get_charger_online_status)
++ goto use_bat;
++ if ((di->pdata->get_charger_online_status)()) {
++ /*
++ * charger is definitively present
++ * we report our state in terms of what it says it
++ * is doing
++ */
++ if (!di->pdata->get_charger_active_status)
++ goto use_bat;
++ if ((di->pdata->get_charger_active_status)())
++ val->intval = POWER_SUPPLY_STATUS_CHARGING;
++ else
++ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
++ break;
++ }
++use_bat:
++ /*
++ * either the charger is not connected, or the
++ * platform doesn't give info about charger, use battery state
++ * but... battery state can be out of date by 4 seconds or
++ * so... use the platform callbacks if possible.
++ */
+ v = hdq_read16(di, BQ27000_AI_L);
+ if (v < 0)
+ return v;
+@@ -189,7 +208,7 @@ static int bq27000_battery_get_property(struct power_supply *psy,
+ break;
+ }
+ /* power is actually going in or out... */
+- v = (di->hdq_read)(BQ27000_FLAGS);
++ v = (di->pdata->hdq_read)(BQ27000_FLAGS);
+ if (v < 0)
+ return v;
+ if (v & BQ27000_STATUS_CHGS)
+@@ -205,7 +224,7 @@ static int bq27000_battery_get_property(struct power_supply *psy,
+ val->intval = v * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+- v = (di->hdq_read)(BQ27000_FLAGS);
++ v = (di->pdata->hdq_read)(BQ27000_FLAGS);
+ if (v < 0)
+ return v;
+ if (v & BQ27000_STATUS_CHGS)
+@@ -215,13 +234,13 @@ static int bq27000_battery_get_property(struct power_supply *psy,
+ v = hdq_read16(di, BQ27000_AI_L);
+ if (v < 0)
+ return v;
+- val->intval = (v * n) / di->rsense_mohms;
++ val->intval = (v * n) / di->pdata->rsense_mohms;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ v = hdq_read16(di, BQ27000_LMD_L);
+ if (v < 0)
+ return v;
+- val->intval = (v * 3570) / di->rsense_mohms;
++ val->intval = (v * 3570) / di->pdata->rsense_mohms;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ v = hdq_read16(di, BQ27000_TEMP_L);
+@@ -235,12 +254,12 @@ static int bq27000_battery_get_property(struct power_supply *psy,
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+- val->intval = (di->hdq_read)(BQ27000_RSOC);
++ val->intval = (di->pdata->hdq_read)(BQ27000_RSOC);
+ if (val->intval < 0)
+ return val->intval;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+- v = (di->hdq_read)(BQ27000_RSOC);
++ v = (di->pdata->hdq_read)(BQ27000_RSOC);
+ val->intval = !(v < 0);
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+@@ -255,6 +274,12 @@ static int bq27000_battery_get_property(struct power_supply *psy,
+ return v;
+ val->intval = 60 * v;
+ break;
++ case POWER_SUPPLY_PROP_ONLINE:
++ if (di->pdata->get_charger_online_status)
++ val->intval = (di->pdata->get_charger_online_status)();
++ else
++ return -EINVAL;
++ break;
+ default:
+ return -EINVAL;
+ }
+@@ -272,7 +297,8 @@ static enum power_supply_property bq27000_battery_props[] = {
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+- POWER_SUPPLY_PROP_CAPACITY
++ POWER_SUPPLY_PROP_CAPACITY,
++ POWER_SUPPLY_PROP_ONLINE
+ };
+
+ static int bq27000_battery_probe(struct platform_device *pdev)
+@@ -302,10 +328,7 @@ static int bq27000_battery_probe(struct platform_device *pdev)
+ di->bat.external_power_changed =
+ bq27000_battery_external_power_changed;
+ di->bat.use_for_apm = 1;
+- di->hdq_read = pdata->hdq_read;
+- di->hdq_write = pdata->hdq_write;
+- di->rsense_mohms = pdata->rsense_mohms;
+- di->hdq_initialized = pdata->hdq_initialized;
++ di->pdata = pdata;
+
+ retval = power_supply_register(&pdev->dev, &di->bat);
+ if (retval) {
+diff --git a/include/linux/bq27000_battery.h b/include/linux/bq27000_battery.h
+index fed4287..a617466 100644
+--- a/include/linux/bq27000_battery.h
++++ b/include/linux/bq27000_battery.h
+@@ -9,6 +9,8 @@ struct bq27000_platform_data {
+ int (*hdq_read)(int);
+ int (*hdq_write)(int, u8);
+ int (*hdq_initialized)(void);
++ int (*get_charger_online_status)(void);
++ int (*get_charger_active_status)(void);
+ };
+
+ #endif
+--
+1.5.6.5
+