This patch tries to make the system stay in a mode where total power consumption is below 100mA until we have determined that it's safe to draw more power. This is work in progress. Don't use it. It makes the following changes: - keeps the system from booting unless we have either good battery power, 500mA from USB, or the wall charger supplying power - flashes the red (AUX) LED during this - defers initialization of the video subsystem until we're about to display something - leaves the LED boost converter turned off until we actually need it Known issues: - still burns way too much power, see http://people.openmoko.org/werner/wait-for-power-try1/usb-batt.html Index: u-boot/board/neo1973/gta02/gta02.c =================================================================== --- u-boot.orig/board/neo1973/gta02/gta02.c +++ u-boot/board/neo1973/gta02/gta02.c @@ -45,6 +45,9 @@ /* That many seconds the power key needs to be pressed to power up */ #define POWER_KEY_SECONDS 2 +/* If the battery voltage is below this, we can't provide stable power */ +#define SAVE_POWER_MILLIVOLT 3600 + #if defined(CONFIG_ARCH_GTA02_v1) //#define M_MDIV 0x7f /* Fout = 405.00MHz */ #define M_MDIV 0x7d /* Fout = 399.00MHz */ @@ -63,6 +66,8 @@ #define U_M_SDIV 2 #endif +extern void smedia3362_lcm_reset(int); + unsigned int neo1973_wakeup_cause; extern unsigned char booted_from_nand; extern unsigned char booted_from_nor; @@ -293,6 +298,42 @@ #endif } +static void poll_charger(void) +{ + if (pcf50633_read_charger_type() == 1000) + pcf50633_usb_maxcurrent(1000); +} + +static void wait_for_power(void) +{ + int seconds = 0; + + while (1) { + /* battery is present -> try to boot */ + if (!(pcf50633_reg_read(PCF50633_REG_BVMCTL) & 1)) + break; +/* + * Consider adding this later to the above condition: + pcf50633_read_battvolt() >= SAVE_POWER_MILLIVOLT) + */ + + poll_charger(); + + /* we have plenty of external power -> try to boot */ + if (pcf50633_usb_last_maxcurrent >= 500) + break; + + if (neo1973_new_second()) + seconds++; + + /* blink the AUX LED */ + neo1973_led(GTA02_LED_AUX_RED, !seconds || (seconds & 1)); + } + + /* switch off the AUX LED */ + neo1973_led(GTA02_LED_AUX_RED, 0); +} + int board_late_init(void) { S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); @@ -300,6 +341,7 @@ char buf[32]; int menu_vote = 0; /* <= 0: no, > 0: yes */ int seconds = 0; + int enter_bootmenu; set_revision(); @@ -310,12 +352,13 @@ int1 = pcf50633_reg_read(PCF50633_REG_INT1); int2 = pcf50633_reg_read(PCF50633_REG_INT2); - /* switch on one of the power led's */ - neo1973_led(GTA02_LED_PWR_ORANGE, 1); + wait_for_power(); /* 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) @@ -377,9 +420,15 @@ neo1973_poweroff(); continue_boot: + enter_bootmenu = menu_vote > 0 || booted_from_nor; + smedia3362_lcm_reset(1); + if (!enter_bootmenu && getenv("splashimage")) + run_command(getenv("splashimage"), 0); jbt6k74_init(); jbt6k74_enter_state(JBT_STATE_NORMAL); jbt6k74_display_onoff(1); + /* switch on the backlight */ + neo1973_backlight(1); #if 0 { @@ -390,7 +439,7 @@ } #endif - if (menu_vote > 0 || booted_from_nor) { + if (enter_bootmenu) { extern struct bootmenu_setup bootmenu_setup; if (booted_from_nand) Index: u-boot/board/neo1973/gta02/pcf50633.c =================================================================== --- u-boot.orig/board/neo1973/gta02/pcf50633.c +++ u-boot/board/neo1973/gta02/pcf50633.c @@ -58,7 +58,7 @@ [PCF50633_REG_MEMLDOENA] = 0x00, [PCF50633_REG_LEDOUT] = 0x2f, /* full backlight power */ - [PCF50633_REG_LEDENA] = 0x02, /* enabled if GPIO1 = HIGH */ + [PCF50633_REG_LEDENA] = 0x00, /* disabled */ [PCF50633_REG_LEDCTL] = 0x05, /* ovp enabled, ocp 500mA */ [PCF50633_REG_LEDDIM] = 0x20, /* dimming curve */ Index: u-boot/drivers/misc/pcf50633.c =================================================================== --- u-boot.orig/drivers/misc/pcf50633.c +++ u-boot/drivers/misc/pcf50633.c @@ -111,18 +111,13 @@ return 0; } -/* figure out our charger situation */ -int pcf50633_read_charger_type(void) +static u_int16_t pcf50633_adc_read(u_int8_t channel, u_int8_t avg) { u_int16_t ret; - /* kill ratiometric, but enable ACCSW biasing */ - pcf50633_reg_write(PCF50633_REG_ADCC2, 0x00); - pcf50633_reg_write(PCF50633_REG_ADCC3, 0x01); - /* start ADC conversion of selected channel */ - pcf50633_reg_write(PCF50633_REG_ADCC1, PCF50633_ADCC1_MUX_ADCIN1 | - PCF50633_ADCC1_AVERAGE_16 | + pcf50633_reg_write(PCF50633_REG_ADCC1, channel | + avg | PCF50633_ADCC1_ADCSTART | PCF50633_ADCC1_RES_10BIT); @@ -135,18 +130,41 @@ (pcf50633_reg_read(PCF50633_REG_ADCS3) & PCF50633_ADCS3_ADCDAT1L_MASK); + return ret; +} + +/* figure out our charger situation */ +int pcf50633_read_charger_type(void) +{ + u_int16_t ret; + + if ((pcf50633_reg_read(PCF50633_REG_MBCS1) & 0x3) != 0x3) + return 0; /* no power, just battery */ + + /* kill ratiometric, but enable ACCSW biasing */ + pcf50633_reg_write(PCF50633_REG_ADCC2, 0x00); + pcf50633_reg_write(PCF50633_REG_ADCC3, 0x01); + + ret = pcf50633_adc_read(PCF50633_ADCC1_MUX_ADCIN1, + PCF50633_ADCC1_AVERAGE_16); + /* well it is nearest to the 1A resistor */ if (ret < ((ADC_NOMINAL_RES_1A + ADC_NOMINAL_RES_NC_R_USB) / 2)) return 1000; - /* ok all we know is there is no resistor, it can be USB pwr or none */ - if ((pcf50633_reg_read(PCF50633_REG_MBCS1) & 0x3) == 0x3) - return 100; /* USB power then */ + /* there is no resistor, so it must be USB pwr */ + return 100; /* USB power then */ - return 0; /* nope, no power, just battery */ } +u_int16_t pcf50633_read_battvolt(void) +{ + u_int16_t ret; + + ret = pcf50633_adc_read(PCF50633_ADCC1_MUX_BATSNS_RES, 0); + return (ret * 6000) / 1024; +} /* initialize PCF50633 register set */ void pcf50633_init(void) @@ -175,10 +193,13 @@ } } +int pcf50633_usb_last_maxcurrent = -1; + void pcf50633_usb_maxcurrent(unsigned int ma) { u_int8_t val; + pcf50633_usb_last_maxcurrent = ma; if (ma < 100) val = PCF50633_MBCC7_USB_SUSPEND; else if (ma < 500) Index: u-boot/drivers/video/smedia3362.c =================================================================== --- u-boot.orig/drivers/video/smedia3362.c +++ u-boot/drivers/video/smedia3362.c @@ -223,7 +223,7 @@ pGD->frameAdrs = CONFIG_GLAMO_BASE + 0x00800000; pGD->memSize = 0x200000; /* 480x640x16bit = 614400 bytes */ -#ifdef CONFIG_GTA02_REVISION +#ifdef CONFIG_GTA02_REVISION_do_this_in_board_late_init /* bring up the LCM */ smedia3362_lcm_reset(1); if (getenv("splashimage")) Index: u-boot/include/pcf50633.h =================================================================== --- u-boot.orig/include/pcf50633.h +++ u-boot/include/pcf50633.h @@ -387,6 +387,8 @@ /* this is to be provided by the board implementation */ extern const u_int8_t pcf50633_initial_regs[__NUM_PCF50633_REGS]; +extern int pcf50633_usb_last_maxcurrent; /* mA or -1 if unknown */ + void pcf50633_reg_write(u_int8_t reg, u_int8_t val); u_int8_t pcf50633_reg_read(u_int8_t reg); @@ -399,5 +401,8 @@ const char *pcf50633_charger_state(void); +int pcf50633_read_charger_type(void); +u_int16_t pcf50633_read_battvolt(void); + #endif /* _PCF50633_H */