I have been experimenting with deeply-discharged batteries on my
Freerunner. When the battery was very low (but not low enough to trigger
the battery's internal cutoff) I was not able to boot reliably when
plugged into the wall charger. I was more successful when using a USB
cable connected to my PC.
I found a problem in u-boot where wait_for_power() was not properly
setting the 1000mA current limit - it would set it, but then immediately
put the PMU into "USB suspend" mode based on the value of
udc_usb_maxcurrent (at least I think that's what was happening).
The first attached patch improves this situation, but it is not yet
ready to be applied to the stable tree. I changed the udc callback to
set a udc_usb_maxcurrent of 100mA rather than 0 when connected to an
unpowered usb hub, but I don't know if there are situations where
udc_usb_maxcurrent is actually supposed to be 0mA. Also the patch is
resetting a bit in PCF50633_REG_OOCSHDWN but I do not know yet why this
is necessary.
The second patch is debugging code that flashes the power LEDs to
indicate the status of the battery and the USB current limit. It may be
useful to others who are investigating this problem.
Comments are welcome.
>From 46190e934ee1f772d55a0b45dc919bd1c252f014 Mon Sep 17 00:00:00 2001
From: Mike Montour <[EMAIL PROTECTED]>
Date: Mon, 25 Aug 2008 00:30:42 -0700
Subject: [PATCH] lowbat-usb-power-levels
This patch fixes the 100/500/1000 mA USB detection in the u-boot function
that handles booting with a low battery voltage. This version of the patch
is not yet suitable for merging into the stable tree.
diff --git a/board/neo1973/common/udc.c b/board/neo1973/common/udc.c
index d547cb8..fe146ee 100644
--- a/board/neo1973/common/udc.c
+++ b/board/neo1973/common/udc.c
@@ -5,7 +5,7 @@
#include <pcf50606.h>
#include <pcf50633.h>
-int udc_usb_maxcurrent = 0;
+int udc_usb_maxcurrent = 100;
void udc_ctrl(enum usbd_event event, int param)
{
@@ -39,7 +39,7 @@ void udc_ctrl(enum usbd_event event, int param)
if (param)
udc_usb_maxcurrent = 500;
else
- udc_usb_maxcurrent = 0;
+ udc_usb_maxcurrent = 100;
#endif
break;
default:
diff --git a/board/neo1973/gta02/gta02.c b/board/neo1973/gta02/gta02.c
index 6db164e..2369d95 100644
--- a/board/neo1973/gta02/gta02.c
+++ b/board/neo1973/gta02/gta02.c
@@ -320,12 +320,6 @@ static void set_revision(void)
#endif
}
-static void poll_charger(void)
-{
- if (pcf50633_read_charger_type() == 1000)
- pcf50633_usb_maxcurrent(1000);
-}
-
static int have_int(uint8_t mask1, uint8_t mask2);
static void clear_pmu_int(void)
@@ -395,11 +389,13 @@ static void wait_for_power(void)
int led_cycle = 1;
while (1) {
- poll_charger();
-
/* track what the time-critical udc callback allows us */
- if (pcf50633_usb_last_maxcurrent != udc_usb_maxcurrent)
- pcf50633_usb_maxcurrent(udc_usb_maxcurrent);
+ int new_max = udc_usb_maxcurrent;
+ if(pcf50633_read_charger_type() == 1000)
+ new_max = 1000;
+
+ if (pcf50633_usb_last_maxcurrent != new_max)
+ pcf50633_usb_maxcurrent(new_max);
/* we have plenty of external power -> try to boot */
if (pcf50633_usb_last_maxcurrent >= 500)
@@ -421,16 +417,30 @@ static void wait_for_power(void)
if (led_cycle && battery_is_good())
break;
seconds++;
+
+ /* TEMPORARY - Reset the 8s timeout counter which would
otherwise
+ * shut us down. Should handle this in some other
manner, e.g.
+ * masking interrupts or only resetting for some of the
possible
+ * shutdown reasons.
+ */
+ pcf50633_reg_set_bit_mask(PCF50633_REG_OOCSHDWN, 0x04,
0x04);
}
led_cycle = !seconds || (seconds & 1);
/*
* Blink the AUX LED, unless it's broken (which is the case in
- * GTA02v5 it is) and draws excessive current, which we just
+ * some GTA02v5) and draws excessive current, which we just
* can't afford in this delicate situation.
+ *
*/
+#if 0
+ /* For prototype GTA02v5 */
if (gta02_revision > 5)
+#else
+ /* For mass-production GTA02v5 with LED rework*/
+ if (gta02_revision >= 5)
+#endif
neo1973_led(GTA02_LED_AUX_RED, led_cycle);
/* alternate LED and charger cycles */
--
1.5.2.4
>From db3d9776804324f4922b562f5fbc03a61d155669 Mon Sep 17 00:00:00 2001
From: Mike Montour <[EMAIL PROTECTED]>
Date: Mon, 25 Aug 2008 00:33:36 -0700
Subject: [PATCH] charger-dbg-blinkenlights
This patch holds u-boot in wait_for_power() until the Aux key is pressed,
and indicates battery charge and USB current limit via the Power LEDs.
diff --git a/board/neo1973/gta02/gta02.c b/board/neo1973/gta02/gta02.c
index 2369d95..a0a56fa 100644
--- a/board/neo1973/gta02/gta02.c
+++ b/board/neo1973/gta02/gta02.c
@@ -398,7 +398,7 @@ static void wait_for_power(void)
pcf50633_usb_maxcurrent(new_max);
/* we have plenty of external power -> try to boot */
- if (pcf50633_usb_last_maxcurrent >= 500)
+ if (neo1973_aux_key_pressed() && pcf50633_usb_last_maxcurrent
>= 500)
break;
/* cpu_idle sits with interrupts off destroying USB operation
@@ -414,7 +414,7 @@ static void wait_for_power(void)
* 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())
+ if (neo1973_aux_key_pressed() && led_cycle &&
battery_is_good())
break;
seconds++;
@@ -443,6 +443,20 @@ static void wait_for_power(void)
#endif
neo1973_led(GTA02_LED_AUX_RED, led_cycle);
+ if (pcf50633_reg_read(PCF50633_REG_BVMCTL) & 1)
+ neo1973_led(GTA02_LED_PWR_BLUE, 1);
+ else if (pcf50633_read_battvolt() < SAFE_POWER_MILLIVOLT)
+ neo1973_led(GTA02_LED_PWR_BLUE, led_cycle);
+ else
+ neo1973_led(GTA02_LED_PWR_BLUE, 0);
+
+ if (pcf50633_usb_last_maxcurrent == 1000)
+ neo1973_led(GTA02_LED_PWR_ORANGE, 1);
+ else if (pcf50633_usb_last_maxcurrent == 500)
+ neo1973_led(GTA02_LED_PWR_ORANGE, !led_cycle);
+ else
+ neo1973_led(GTA02_LED_PWR_ORANGE, 0);
+
/* alternate LED and charger cycles */
pcf50633_reg_set_bit_mask(PCF50633_REG_MBCC1, 1, !led_cycle);
}
--
1.5.2.4