diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-09-12 16:45:18 -0700 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-09-17 12:16:01 -0700 |
commit | c0a2d9befb9863f4569c302b5137e6a666722436 (patch) | |
tree | b9031f2c68f787dd9c6e4c1a9912baa206b68f20 | |
parent | 78474d4eeb29537e7fd0ca071cf0a78a464e5f90 (diff) | |
download | chrome-ec-c0a2d9befb9863f4569c302b5137e6a666722436.tar.gz |
Reset LPC from-host channel status on LPC reset
This works around a LM4 bug where the LPC module stops triggering
interrupts for a channel if bytes are written too rapidly to that
channel. This should only affect port 80 because other channels use
busy-status-handshaking to avoid flooding the EC.
BUG=chrome-os-partner:12349
BRANCH=link
TEST=manual
1. From a root shell: ectool port80flood
2. Repeat until the EC console stops showing port 80 codes coming in
3. From a root shell: reboot
4. Port 80 codes should be printed by EC as the BIOS boots
Change-Id: I3b3463ce668727cad9900b576fdeb531986a415e
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/33142
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r-- | chip/lm4/lpc.c | 14 | ||||
-rw-r--r-- | chip/lm4/registers.h | 1 | ||||
-rw-r--r-- | util/ectool.c | 12 |
3 files changed, 25 insertions, 2 deletions
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c index 74c31ebd97..34929285a2 100644 --- a/chip/lm4/lpc.c +++ b/chip/lm4/lpc.c @@ -573,10 +573,20 @@ static void lpc_interrupt(void) /* Debugging: print changes to LPC0RESET */ if (mis & (1 << 31)) { - /* Store port 80 event so we know where reset happened */ - if (LM4_LPC_LPCSTS & (1 << 10)) + if (LM4_LPC_LPCSTS & (1 << 10)) { + int i; + + /* Store port 80 reset event */ port_80_write(PORT_80_EVENT_RESET); + /* + * Workaround for crosbug.com/p/12349; clear all FRMH + * bits so host writes will trigger interrupts. + */ + for (i = 0; i < 8; i++) + LM4_LPC_ST(i) &= ~LM4_LPC_ST_FRMH; + } + CPRINTF("[%T LPC RESET# %sasserted]\n", (LM4_LPC_LPCSTS & (1<<10)) ? "" : "de"); } diff --git a/chip/lm4/registers.h b/chip/lm4/registers.h index 2a481abe2b..f351bb2814 100644 --- a/chip/lm4/registers.h +++ b/chip/lm4/registers.h @@ -119,6 +119,7 @@ static inline int lm4_lpc_addr(int ch, int offset) #define LM4_LPC_CTL(ch) LM4LPCREG(ch, 0x000) #define LM4_LPC_ST(ch) LM4LPCREG(ch, 0x004) #define LM4_LPC_ST_TOH (1 << 0) /* TO Host bit */ +#define LM4_LPC_ST_FRMH (1 << 1) /* FRoM Host bit */ #define LM4_LPC_ST_CMD (1 << 3) /* Last from-host byte was command */ #define LM4_LPC_ST_PRESENT (1 << 8) #define LM4_LPC_ST_SCI (1 << 9) diff --git a/util/ectool.c b/util/ectool.c index 4fbc6ce781..b4e9dd20a0 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -92,6 +92,8 @@ const char help_str[] = " Write I2C bus\n" " lightbar [CMDS]\n" " Various lightbar control commands\n" + " port80flood\n" + " Rapidly write bytes to port 80\n" " pstoreinfo\n" " Prints information on the EC host persistent storage\n" " pstoreread <offset> <size> <outfile>\n" @@ -2190,6 +2192,15 @@ int cmd_console(int argc, char *argv[]) return 0; } +/* Flood port 80 with byte writes */ +int cmd_port_80_flood(int argc, char *argv[]) +{ + int i; + + for (i = 0; i < 256; i++) + outb(i, 0x80); + return 0; +} struct command { const char *name; @@ -2243,6 +2254,7 @@ const struct command commands[] = { {"rtcget", cmd_rtc_get}, {"rtcset", cmd_rtc_set}, {"sertest", cmd_serial_test}, + {"port80flood", cmd_port_80_flood}, {"switches", cmd_switches}, {"temps", cmd_temperature}, {"tempsinfo", cmd_temp_sensor_info}, |