From daeade92cf96e2a8453ad17441ce70c912df8f53 Mon Sep 17 00:00:00 2001 From: mokopatches Date: Fri, 11 Apr 2008 14:27:37 +0100 Subject: [PATCH] wait-for-power.patch 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 --- board/neo1973/gta02/gta02.c | 55 +++++++++++++++++++++++++++++++++++++++--- board/neo1973/gta02/pcf50633.c | 2 +- drivers/misc/pcf50633.c | 45 +++++++++++++++++++++++++--------- drivers/video/smedia3362.c | 2 +- include/pcf50633.h | 5 ++++ 5 files changed, 92 insertions(+), 17 deletions(-) diff --git a/board/neo1973/gta02/gta02.c b/board/neo1973/gta02/gta02.c index 4cc21601..16722d9c 100644 --- a/board/neo1973/gta02/gta02.c +++ b/board/neo1973/gta02/gta02.c @@ -45,6 +45,9 @@ DECLARE_GLOBAL_DATA_PTR; /* That many seconds the power key needs to be pressed to power up */ #define POWER_KEY_SECONDS 1 +/* 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 @@ DECLARE_GLOBAL_DATA_PTR; #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 @@ static void set_revision(void) #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 @@ int board_late_init(void) char buf[32]; int menu_vote = 0; /* <= 0: no, > 0: yes */ int seconds = 0; + int enter_bootmenu; set_revision(); @@ -310,12 +352,13 @@ int board_late_init(void) 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 @@ woken_by_reset: 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 @@ continue_boot: } #endif - if (menu_vote > 0 || booted_from_nor) { + if (enter_bootmenu) { extern struct bootmenu_setup bootmenu_setup; if (booted_from_nand) diff --git a/board/neo1973/gta02/pcf50633.c b/board/neo1973/gta02/pcf50633.c index a7afcf92..7a047264 100644 --- a/board/neo1973/gta02/pcf50633.c +++ b/board/neo1973/gta02/pcf50633.c @@ -58,7 +58,7 @@ const u_int8_t pcf50633_initial_regs[__NUM_PCF50633_REGS] = { [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 */ diff --git a/drivers/misc/pcf50633.c b/drivers/misc/pcf50633.c index ca025875..9d423082 100644 --- a/drivers/misc/pcf50633.c +++ b/drivers/misc/pcf50633.c @@ -111,18 +111,13 @@ static int reg_is_invalid(u_int8_t reg) 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 @@ int pcf50633_read_charger_type(void) (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 @@ void pcf50633_init(void) } } +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) diff --git a/drivers/video/smedia3362.c b/drivers/video/smedia3362.c index 170723fa..5511a91d 100644 --- a/drivers/video/smedia3362.c +++ b/drivers/video/smedia3362.c @@ -223,7 +223,7 @@ void * video_hw_init(void) 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")) diff --git a/include/pcf50633.h b/include/pcf50633.h index 6d2d557e..57e9d0a3 100644 --- a/include/pcf50633.h +++ b/include/pcf50633.h @@ -387,6 +387,8 @@ enum pcf50633_reg_mbcs3 { /* 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 @@ void pcf50633_usb_maxcurrent(unsigned int ma); const char *pcf50633_charger_state(void); +int pcf50633_read_charger_type(void); +u_int16_t pcf50633_read_battvolt(void); + #endif /* _PCF50633_H */ -- 2.11.4.GIT