[PATCH 9/10] deadbat-alternate.patch

Werner Almesberger werner at openmoko.org
Tue Jul 15 13:05:20 CEST 2008


When there is no battery or the battery is in its cut-off state, even the
slightest charge (once the capacitors on the battery rail are filled) will
drive the battery voltage up to VB_SYS.

The battery voltage monitor therefore only reports garbage. We work around
this problem by alternating the LED with the charger, so that the battery
only gets charged half of the time. We then measure right at the end of a
LED cycle, i.e., when the battery voltage has had time to return to the
level that really represents the battery state.

(Note: battery voltage drops quickly, so giving it one whole second to
drain is very much on the safe side.)

Signed-off-by: Werner Almesberger <werner at openmoko.org>

Index: u-boot/board/neo1973/gta02/gta02.c
===================================================================
--- u-boot.orig/board/neo1973/gta02/gta02.c	2008-07-14 21:41:12.000000000 -0300
+++ u-boot/board/neo1973/gta02/gta02.c	2008-07-14 22:11:31.000000000 -0300
@@ -374,19 +374,22 @@
 	local_irq_restore(flags);
 }
 
-static void wait_for_power(void)
+static int battery_is_good(void)
 {
-	int seconds = 0;
-
-	while (1) {
-		/* battery is present -> try to boot */
-		if (!(pcf50633_reg_read(PCF50633_REG_BVMCTL) & 1))
-			break;
+	/* battery is present -> try to boot */
+	return !(pcf50633_reg_read(PCF50633_REG_BVMCTL) & 1);
 /*
  * Consider adding this later to the above condition:
-		    pcf50633_read_battvolt() >= SAVE_POWER_MILLIVOLT)
+	    pcf50633_read_battvolt() >= SAVE_POWER_MILLIVOLT)
  */
+}
 
+static void wait_for_power(void)
+{
+	int seconds = 0;
+	int led_cycle = 1;
+
+	while (1) {
 		poll_charger();
 
 		/* we have plenty of external power -> try to boot */
@@ -395,8 +398,17 @@
 
 		cpu_idle();
 
-		if (neo1973_new_second())
+		if (neo1973_new_second()) {
+			/*
+			 * Probe the battery only if the current LED cycle is
+			 * about to end, so that it had time to discharge.
+			 */
+			if (led_cycle && battery_is_good())
+				break;
 			seconds++;
+		}
+
+		led_cycle = !seconds || (seconds & 1);
 
 		/*
 		 * Blink the AUX LED, unless it's broken (which is the case in
@@ -404,8 +416,10 @@
 		 * can't afford in this delicate situation.
 		 */
 		if (gta02_revision > 5)
-			neo1973_led(GTA02_LED_AUX_RED,
-			    !seconds || (seconds & 1));
+			neo1973_led(GTA02_LED_AUX_RED, led_cycle);
+
+		/* alternate LED and charger cycles */
+		pcf50633_reg_set_bit_mask(PCF50633_REG_MBCC1, 1, !led_cycle);
 	}
 
 	/* switch off the AUX LED */
@@ -428,6 +442,8 @@
 	pcf50633_reg_write(PCF50633_REG_LDO6ENA, recent);
 
 	pcf50633_reg_write(PCF50633_REG_MBCC5, 0xff); /* 1A USB fast charge */
+
+	pcf50633_reg_set_bit_mask(PCF50633_REG_MBCC1, 1, 1); /* charge ! */
 }
 
 int board_late_init(void)




More information about the openmoko-kernel mailing list