From 89a8a082b13aa33d1352b94804fbe5885ea7fcf9 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Mon, 5 Mar 2012 12:07:50 -0800 Subject: [PATCH] Update switch positions in EC mapped data Note that this only handles lid and power button; see crosbug.com/p/8325 for write protect. Signed-off-by: Randall Spangler BUG=chrome-os-partner:8185 TEST=manual 1. Check state with lid open localhost ~ # ectool switches Current switches: 0x01 Lid switch: OPEN Power button: UP Write protect: ENABLED 2. Press power button localhost ~ # ectool switches Current switches: 0x03 Lid switch: OPEN Power button: DOWN Write protect: ENABLED 3. Release power button and close lid localhost ~ # ectool switches Current switches: 0x00 Lid switch: CLOSED Power button: UP Write protect: ENABLED Change-Id: I25f2fa3dfeac004dde9b10a4243ee235875f1b6e --- chip/lm4/power_button.c | 35 +++++++++++++++++++++++++++++------ include/lpc_commands.h | 7 ++++++- util/ectool.c | 18 ++++++++++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/chip/lm4/power_button.c b/chip/lm4/power_button.c index 238ba2081f..65e3824e40 100644 --- a/chip/lm4/power_button.c +++ b/chip/lm4/power_button.c @@ -58,6 +58,8 @@ static uint64_t tnext_state; static uint64_t tdebounce_lid; static uint64_t tdebounce_pwr; +static uint8_t *memmap_switches; + static void set_pwrbtn_to_pch(int high) { @@ -109,12 +111,14 @@ static void power_button_changed(uint64_t tnow) if (!gpio_get_level(GPIO_POWER_BUTTONn)) { /* pressed */ pwrbtn_state = PWRBTN_STATE_START; + *memmap_switches |= EC_LPC_SWITCH_POWER_BUTTON_PRESSED; keyboard_set_power_button(1); lpc_set_host_events( EC_LPC_HOST_EVENT_MASK(EC_LPC_HOST_EVENT_POWER_BUTTON)); } else { /* released */ pwrbtn_state = PWRBTN_STATE_STOPPING; + *memmap_switches &= ~EC_LPC_SWITCH_POWER_BUTTON_PRESSED; keyboard_set_power_button(0); } tnext_state = tnow; /* Trigger next state transition now */ @@ -134,12 +138,20 @@ static void lid_switch_changed(uint64_t tnow) lpc_set_host_events(EC_LPC_HOST_EVENT_MASK((v ? EC_LPC_HOST_EVENT_LID_OPEN : EC_LPC_HOST_EVENT_LID_CLOSED))); - /* If the lid has opened and the chipset is is soft-off, send a power - * button pulse to wake up the chipset. */ - if (v && chipset_in_state(CHIPSET_STATE_SOFT_OFF)) { - set_pwrbtn_to_pch(0); - pwrbtn_state = PWRBTN_STATE_STOPPING; - tnext_state = tnow + LID_PWRBTN_US; + if (v) { + /* Lid open */ + *memmap_switches |= EC_LPC_SWITCH_LID_OPEN; + + /* If the chipset is is soft-off, send a power button pulse to + * wake up the chipset. */ + if (chipset_in_state(CHIPSET_STATE_SOFT_OFF)) { + set_pwrbtn_to_pch(0); + pwrbtn_state = PWRBTN_STATE_STOPPING; + tnext_state = tnow + LID_PWRBTN_US; + } + } else { + /* Lid closed */ + *memmap_switches &= ~EC_LPC_SWITCH_LID_OPEN; } } @@ -163,6 +175,14 @@ void power_button_interrupt(enum gpio_signal signal) int power_button_init(void) { + /* Set up memory-mapped switch positions */ + memmap_switches = lpc_get_memmap_range() + EC_LPC_MEMMAP_SWITCHES; + *memmap_switches = 0; + if (gpio_get_level(GPIO_POWER_BUTTONn) == 0) + *memmap_switches |= EC_LPC_SWITCH_POWER_BUTTON_PRESSED; + if (gpio_get_level(GPIO_PCH_LID_SWITCHn) != 0) + *memmap_switches |= EC_LPC_SWITCH_LID_OPEN; + /* Copy initial switch states to PCH */ gpio_set_level(GPIO_PCH_PWRBTNn, gpio_get_level(GPIO_POWER_BUTTONn)); gpio_set_level(GPIO_PCH_LID_SWITCHn, gpio_get_level(GPIO_LID_SWITCHn)); @@ -235,6 +255,9 @@ static int command_powerbtn(int argc, char **argv) } } + /* Note that this only simulates the raw power button signal to the + * PCH. It does not simulate the full state machine which sends SMIs + * and other events to other parts of the EC and chipset. */ uart_printf("Simulating %d ms power button press.\n", ms); set_pwrbtn_to_pch(0); usleep(ms * 1000); diff --git a/include/lpc_commands.h b/include/lpc_commands.h index 86a10c0a6f..6ffa1253c1 100644 --- a/include/lpc_commands.h +++ b/include/lpc_commands.h @@ -40,13 +40,18 @@ #define EC_LPC_MEMMAP_SWITCHES 0x30 #define EC_LPC_MEMMAP_HOST_EVENTS 0x34 -/* The battery bit flags. */ +/* Battery bit flags at EC_LPC_MEMMAP_BATT_FLAG. */ #define EC_BATT_FLAG_AC_PRESENT 0x01 #define EC_BATT_FLAG_BATT_PRESENT 0x02 #define EC_BATT_FLAG_DISCHARGING 0x04 #define EC_BATT_FLAG_CHARGING 0x08 #define EC_BATT_FLAG_LEVEL_CRITICAL 0x10 +/* Switch flags at EC_LPC_MEMMAP_SWITCHES */ +#define EC_LPC_SWITCH_LID_OPEN 0x01 +#define EC_LPC_SWITCH_POWER_BUTTON_PRESSED 0x02 +#define EC_LPC_SWITCH_WRITE_PROTECT_DISABLED 0x04 + /* The offset of temperature value stored in mapped memory. * This allows reporting a temperature range of * 200K to 454K = -73C to 181C. diff --git a/util/ectool.c b/util/ectool.c index a9f80c482d..d8f36531b8 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -52,6 +52,8 @@ const char help_str[] = " Reads a pattern from the EC via LPC\n" " sertest\n" " Serial output test for COM2\n" + " switches\n" + " Prints current EC switch positions\n" " version\n" " Prints EC version\n" " temps \n" @@ -1030,6 +1032,21 @@ int cmd_host_event_clear(int argc, char *argv[]) } +int cmd_switches(int argc, char *argv[]) +{ + uint8_t s = read_mapped_mem8(EC_LPC_MEMMAP_SWITCHES); + printf("Current switches: 0x%02x\n", s); + printf("Lid switch: %s\n", + (s & EC_LPC_SWITCH_LID_OPEN ? "OPEN" : "CLOSED")); + printf("Power button: %s\n", + (s & EC_LPC_SWITCH_POWER_BUTTON_PRESSED ? "DOWN" : "UP")); + printf("Write protect: %sABLED\n", + (s & EC_LPC_SWITCH_WRITE_PROTECT_DISABLED ? "DIS" : "EN")); + + return 0; +} + + struct command { const char *name; int (*handler)(int argc, char *argv[]); @@ -1059,6 +1076,7 @@ const struct command commands[] = { {"queryec", cmd_acpi_query_ec}, {"readtest", cmd_read_test}, {"sertest", cmd_serial_test}, + {"switches", cmd_switches}, {"temps", cmd_temperature}, {"thermalget", cmd_thermal_get_threshold}, {"thermalset", cmd_thermal_set_threshold},