u-boot fix to charge empty battery

Andy Green andy at openmoko.com
Thu Oct 9 18:28:28 CEST 2008


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Somebody in the thread at some point said:
| Ok, I do now have a patch ready that fixes most low-power issues:
|
| * Always wait until battery is charged enough before continuing the boot
| process
| -> but still allow boot to continue if no battery is present
| * Cancel the shutdown timer during charging
| * Make sure 1A charger charges with 1A
| * Detect if power button has been pressed for long enough at the
| beginning of the startup sequence
| * Only pulse vibrator and LED when startup is initiated
| * Keep CPU @200Mhz  until charging is complete
| -> I hope I didn't break USB ;-)
| * Abort charging if no USB power is present

I sent your patch here for ease of review...

I added it to the current tree, it starts up a fresh A6 here OK.

I also put a small patch on top of it to tidy one or two things up
(copied here after yours).

USB wasn't broken at least when I tried it.

Thanks for taking the time to look at these problems.

- -Andy


diff --git a/board/neo1973/gta02/gta02.c b/board/neo1973/gta02/gta02.c
index 6db164e..be39ae0 100644
- --- a/board/neo1973/gta02/gta02.c
+++ b/board/neo1973/gta02/gta02.c
@@ -324,6 +324,9 @@ static void poll_charger(void)
~ {
~ 	if (pcf50633_read_charger_type() == 1000)
~ 		pcf50633_usb_maxcurrent(1000);
+	else /* track what the time-critical udc callback allows us */
+		if (pcf50633_usb_last_maxcurrent != udc_usb_maxcurrent)
+		pcf50633_usb_maxcurrent(udc_usb_maxcurrent);
~ }

~ static int have_int(uint8_t mask1, uint8_t mask2);
@@ -376,6 +379,24 @@ static void cpu_idle(void)
~ 	local_irq_restore(flags);
~ }

+static int charger_is_present(void)
+{
+	/* is charger or power adapter present? */
+	if (pcf50633_reg_read(PCF50633_REG_MBCS1) & 3)
+		return 1;
+
+	return 0;
+}
+
+static int battery_is_present(void)
+{
+	/* battery is absent -> don't boot */
+	if (pcf50633_reg_read(PCF50633_REG_BVMCTL) & 1)
+		return 0;
+
+	return 1;
+}
+
~ static int battery_is_good(void)
~ {
~ 	/* battery is absent -> don't boot */
@@ -389,20 +410,22 @@ static int battery_is_good(void)
~ 	return 1;
~ }

- -static void wait_for_power(void)
+static int wait_for_power(void)
~ {
+	/*
+	 * TODO: this function should also check if charger is still attached
+	 * it makes no sense to wait otherwise.
+	*/
+
~ 	int seconds = 0;
~ 	int led_cycle = 1;
+	int power = 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);
- -
- -		/* we have plenty of external power -> try to boot */
- -		if (pcf50633_usb_last_maxcurrent >= 500)
+		/* we have plenty of external power but no battery -> try to boot */
+		if (!battery_is_present() && (pcf50633_usb_last_maxcurrent >= 500))
~ 			break;

~ 		/* cpu_idle sits with interrupts off destroying USB operation
@@ -420,6 +443,13 @@ static void wait_for_power(void)
~ 			 */
~ 			if (led_cycle && battery_is_good())
~ 				break;
+
+			/* check if charger is present, otherwise stop start up */
+			if (!charger_is_present())
+			{
+				power = 0;
+				break;
+			}
~ 			seconds++;
~ 		}

@@ -435,10 +465,16 @@ static void wait_for_power(void)

~ 		/* alternate LED and charger cycles */
~ 		pcf50633_reg_set_bit_mask(PCF50633_REG_MBCC1, 1, !led_cycle);
+
+                /* cancel shutdown timer to keep charging */
+                pcf50633_reg_write(PCF50633_REG_OOCSHDWN, 4);
~ 	}

~ 	/* switch off the AUX LED */
~ 	neo1973_led(GTA02_LED_AUX_RED, 0);
+
+	/* do we have power now? */
+	return power;
~ }

~ static void pcf50633_late_init(void)
@@ -480,26 +516,6 @@ int board_late_init(void)
~ 	int1 = pcf50633_reg_read(PCF50633_REG_INT1);
~ 	int2 = pcf50633_reg_read(PCF50633_REG_INT2);

- -	wait_for_power();
- -	pcf50633_late_init();
- -	cpu_speed(M_MDIV, M_PDIV, M_SDIV, 5); /* 400MHZ, 1:4:8 */
- -
- -	/* issue a short pulse with the vibrator */
- -	neo1973_led(GTA02_LED_AUX_RED, 1);
- -	neo1973_vibrator(1);
- -	udelay(20000);
- -	neo1973_led(GTA02_LED_AUX_RED, 0);
- -	neo1973_vibrator(0);
- -
- -#if defined(CONFIG_ARCH_GTA02_v1)
- -	/* Glamo3362 reset and power cycle */
- -	gpio->GPJDAT &= ~0x000000001;	/* GTA02v1_GPIO_3D_RESET */
- -	pcf50633_reg_write(PCF50633_REG_DOWN2ENA, 0);
- -	udelay(50*1000);
- -	pcf50633_reg_write(PCF50633_REG_DOWN2ENA, 0x2);
- -	gpio->GPJDAT |= 0x000000001;	/* GTA02v1_GPIO_3D_RESET */
- -#endif
- -
~ 	/* if there's no other reason, must be regular reset */
~ 	neo1973_wakeup_cause = NEO1973_WAKEUP_RESET;

@@ -551,6 +567,29 @@ woken_by_reset:
~ 	neo1973_poweroff();

~ continue_boot:
+	/* Power off if no battery is present and only 100mA is available */
+	if (!wait_for_power())
+		neo1973_poweroff();
+
+	pcf50633_late_init();
+	cpu_speed(M_MDIV, M_PDIV, M_SDIV, 5); /* 400MHZ, 1:4:8 */
+
+	/* issue a short pulse with the vibrator */
+	neo1973_led(GTA02_LED_AUX_RED, 1);
+	neo1973_vibrator(1);
+	udelay(20000);
+	neo1973_led(GTA02_LED_AUX_RED, 0);
+	neo1973_vibrator(0);
+
+#if defined(CONFIG_ARCH_GTA02_v1)
+	/* Glamo3362 reset and power cycle */
+	gpio->GPJDAT &= ~0x000000001;	/* GTA02v1_GPIO_3D_RESET */
+	pcf50633_reg_write(PCF50633_REG_DOWN2ENA, 0);
+	udelay(50*1000);
+	pcf50633_reg_write(PCF50633_REG_DOWN2ENA, 0x2);
+	gpio->GPJDAT |= 0x000000001;	/* GTA02v1_GPIO_3D_RESET */
+#endif
+
~ 	env_stop_in_menu = getenv("stop_in_menu");
~ 	/* If the stop_in_menu environment variable is set, enter the
~ 	 * boot menu */


u-boot-clean-batt-charge-patch.patch

From: Andy Green <andy at openmoko.com>

Signed-off-by: Andy Green <andy at openmoko.com>
- ---

~ board/neo1973/gta02/gta02.c |   27 ++++++++++++---------------
~ 1 files changed, 12 insertions(+), 15 deletions(-)


diff --git a/board/neo1973/gta02/gta02.c b/board/neo1973/gta02/gta02.c
index be39ae0..a59a513 100644
- --- a/board/neo1973/gta02/gta02.c
+++ b/board/neo1973/gta02/gta02.c
@@ -326,7 +326,7 @@ static void poll_charger(void)
~ 		pcf50633_usb_maxcurrent(1000);
~ 	else /* track what the time-critical udc callback allows us */
~ 		if (pcf50633_usb_last_maxcurrent != udc_usb_maxcurrent)
- -		pcf50633_usb_maxcurrent(udc_usb_maxcurrent);
+			pcf50633_usb_maxcurrent(udc_usb_maxcurrent);
~ }

~ static int have_int(uint8_t mask1, uint8_t mask2);
@@ -382,25 +382,19 @@ static void cpu_idle(void)
~ static int charger_is_present(void)
~ {
~ 	/* is charger or power adapter present? */
- -	if (pcf50633_reg_read(PCF50633_REG_MBCS1) & 3)
- -		return 1;
- -
- -	return 0;
+	return  !!(pcf50633_reg_read(PCF50633_REG_MBCS1) & 3);
~ }

~ static int battery_is_present(void)
~ {
- -	/* battery is absent -> don't boot */
- -	if (pcf50633_reg_read(PCF50633_REG_BVMCTL) & 1)
- -		return 0;
- -
- -	return 1;
+	/* battery less than bvmlvl -> don't boot */
+	return !(pcf50633_reg_read(PCF50633_REG_BVMCTL) & 1);
~ }

~ static int battery_is_good(void)
~ {
~ 	/* battery is absent -> don't boot */
- -	if (pcf50633_reg_read(PCF50633_REG_BVMCTL) & 1)
+	if (!battery_is_present())
~ 		return 0;

~ 	/* we could try to boot, but we'll probably die on the way */
@@ -424,7 +418,8 @@ static int wait_for_power(void)
~ 	while (1) {
~ 		poll_charger();

- -		/* we have plenty of external power but no battery -> try to boot */
+		/* we have plenty of external power but no visible battery ->
+		 * don't hang around trying to charge, try to boot */
~ 		if (!battery_is_present() && (pcf50633_usb_last_maxcurrent >= 500))
~ 			break;

@@ -445,8 +440,7 @@ static int wait_for_power(void)
~ 				break;

~ 			/* check if charger is present, otherwise stop start up */
- -			if (!charger_is_present())
- -			{
+			if (!charger_is_present()) {
~ 				power = 0;
~ 				break;
~ 			}
@@ -466,7 +460,10 @@ static int wait_for_power(void)
~ 		/* alternate LED and charger cycles */
~ 		pcf50633_reg_set_bit_mask(PCF50633_REG_MBCC1, 1, !led_cycle);

- -                /* cancel shutdown timer to keep charging */
+                /* cancel shutdown timer to keep charging
+		 * it can get triggered by lowvsys along the way but if it
+		 * didn't kill us then don't let it kill us later
+		 */
~                 pcf50633_reg_write(PCF50633_REG_OOCSHDWN, 4);
~ 	}


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkjuMSYACgkQOjLpvpq7dMoN2QCeI0pjlTsyVFIMr590H0u5Cmda
tbYAnii30AX5C+0NJyq3q2WKS30rzHVa
=ptBD
-----END PGP SIGNATURE-----



More information about the devel mailing list