diff options
author | Louis Yung-Chieh Lo <yjlou@chromium.org> | 2012-02-03 11:12:30 +0800 |
---|---|---|
committer | Louis Yung-Chieh Lo <yjlou@chromium.org> | 2012-02-03 12:38:42 +0800 |
commit | 088b79f285fe2dcfac2babb3b1fca6c27a4e2bf6 (patch) | |
tree | 07bce9ac50027263eb7d52aeb7b4293995447995 /chip | |
parent | 54f36995a4b626280b868f1efe6049591f3fc53c (diff) | |
download | chrome-ec-088b79f285fe2dcfac2babb3b1fca6c27a4e2bf6.tar.gz |
Use udelay for more stable manual IRQ firing.
Original code tests SND bit, but it is not reliable to indicate the
SERIRQ frame has been sent out because the EC always clears it
immediately. Unfortunately the SIRQRIS is always asserted in
continuous mode so that we cannot rely on it.
So, the udelay(4us) method is the best way we can use now.
Note: the quiet mode? Forget it. My EC never sends out further frames
after the first has been sent.
BUG=none
TEST=on bds board.
Change-Id: Ica79b463f3dbe7435fe75f3db4cef00ad7ad5ec0
Diffstat (limited to 'chip')
-rw-r--r-- | chip/lm4/lpc.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c index fae068343f..e7841576ec 100644 --- a/chip/lm4/lpc.c +++ b/chip/lm4/lpc.c @@ -14,6 +14,7 @@ #include "port80.h" #include "registers.h" #include "task.h" +#include "timer.h" #include "uart.h" @@ -37,6 +38,17 @@ static void configure_gpio(void) } +static void wait_send_serirq(uint32_t lpcirqctl) { + LM4_LPC_LPCIRQCTL = lpcirqctl; + + /* TODO: udelay() is not graceful. Since the SIRQRIS is almost not + * cleared in continuous mode and EC has problem to file + * more than 1 frame in the quiet mode, this is the best way + * we can do right now. */ + udelay(4); /* 4 us is the time of 2 SERIRQ frames, which is long + * enough to guarantee the IRQ has been sent out. */ +} + /* Manually generates an IRQ to host (edge-trigger). * * For SERIRQ quite mode, we need to set LM4_LPC_LPCIRQCTL twice. @@ -51,13 +63,11 @@ void lpc_manual_irq(int irq_num) { 0x00000002 | /* ONCHG - for quiet mode */ 0x00000001; /* SND - send immediately */ - while (LM4_LPC_LPCIRQCTL & 1); /* wait until SND is cleared */ - LM4_LPC_LPCIRQCTL = (1 << (irq_num + 16)) | common_bits; + /* send out the IRQ first. */ + wait_send_serirq((1 << (irq_num + 16)) | common_bits); - while (LM4_LPC_LPCIRQCTL & 1); /* wait until SND is cleared */ - LM4_LPC_LPCIRQCTL = common_bits; /* generate a all-high frame to - * simulate a rising edge. */ - while (LM4_LPC_LPCIRQCTL & 1); /* wait until SND is cleared */ + /* generate a all-high frame to simulate a rising edge. */ + wait_send_serirq(common_bits); } @@ -174,7 +184,7 @@ void lpc_send_host_response(int slot, int status) /* Return true if the TOH is still set */ -int lpc_keyboard_has_char() { +int lpc_keyboard_has_char(void) { return (LM4_LPC_ST(LPC_CH_KEYBOARD) & (1 << 0 /* TOH */)) ? 1 : 0; } |