summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2014-04-03 16:42:06 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-04-04 04:55:02 +0000
commit671b5646235374c664791acc80b6a01b87941656 (patch)
treec8c01b73256961a3bfe2041093c25e891e2f8cde
parenta3b41f1ebcd5d279d9b989ca3f341a1b6a6eb47b (diff)
downloadchrome-ec-671b5646235374c664791acc80b6a01b87941656.tar.gz
lm4: Ensure falling edges on outputs to edge-sensitive host inputs
The KBD_IRQ#, SMI#, and SCI# lines on the host are sensitive to falling edges. When generating an interrupt, wait long enough to make sure the lines are high before pulling them low, so that it reliably generates a falling edge. This solves a problem where calling the IRQ-generation function twice in rapid succession could cause two low pulses without an intervening logic-high as seen by the host (and thus not a falling edge as seen by the host). This is most visible on the keyboard line, because it can generate back-to-back events on multi-byte scan codes. Once the keyboard mailbox is full, the EC will never attempt to fill it, and thus it also won't attempt to generate another keyboard IRQ. And since the host missed the IRQ, it doesn't know it needs to empty the mailbox. It could theoretically happen for the other lines, so fix them now just to be safe. This change should be low-impact and free from side effects. 4 usec is a very small additional delay. Even 65 usec added delay for SCI/SMI is small, given that SCI/SMI events are typically much less frequent (if they're happening very frequently, something else is tragically wrong with the system...) BUG=chrome-os-partner:27222 BRANCH=rambi TEST=Bang on the keyboard like a monkey. Keyboard shouldn't get stuck. Orig-Change-Id: Id4e6de793b1f007f713bac8aa195ddd78feeea3e Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/193173 Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-by: Benson Leung <bleung@chromium.org> (cherry picked from commit 569651b82e309ddd86b9c165d131e34cb7f7b2b5) Change-Id: I62a9ad0fa85121b3345c057f0e3fc6b3cc29e97e Reviewed-on: https://chromium-review.googlesource.com/193174 Commit-Queue: Randall Spangler <rspangler@chromium.org> Tested-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-by: Benson Leung <bleung@chromium.org>
-rw-r--r--chip/lm4/lpc.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c
index f2fd650016..e59b0a9fb6 100644
--- a/chip/lm4/lpc.c
+++ b/chip/lm4/lpc.c
@@ -86,9 +86,18 @@ static void wait_irq_sent(void)
#ifdef CONFIG_KEYBOARD_IRQ_GPIO
static void keyboard_irq_assert(void)
{
- /* Negative edge-triggered keyboard interrupt. */
+ /*
+ * Enforce signal-high for long enough for the signal to be pulled high
+ * by the external pullup resistor. This ensures the host will see the
+ * following falling edge, regardless of the line state before this
+ * function call.
+ */
+ gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1);
+ udelay(4);
+ /* Generate a falling edge */
gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 0);
- wait_irq_sent();
+ udelay(4);
+ /* Set signal high, now that we've generated the edge */
gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1);
}
#else
@@ -139,8 +148,13 @@ static inline void keyboard_irq_assert(void)
*/
static void lpc_generate_smi(void)
{
+ /* Enforce signal-high for long enough to debounce high */
+ gpio_set_level(GPIO_PCH_SMI_L, 1);
+ udelay(65);
+ /* Generate a falling edge */
gpio_set_level(GPIO_PCH_SMI_L, 0);
udelay(65);
+ /* Set signal high, now that we've generated the edge */
gpio_set_level(GPIO_PCH_SMI_L, 1);
if (host_events & event_mask[LPC_HOST_EVENT_SMI])
@@ -154,8 +168,13 @@ static void lpc_generate_smi(void)
static void lpc_generate_sci(void)
{
#ifdef CONFIG_SCI_GPIO
+ /* Enforce signal-high for long enough to debounce high */
+ gpio_set_level(CONFIG_SCI_GPIO, 1);
+ udelay(65);
+ /* Generate a falling edge */
gpio_set_level(CONFIG_SCI_GPIO, 0);
udelay(65);
+ /* Set signal high, now that we've generated the edge */
gpio_set_level(CONFIG_SCI_GPIO, 1);
#else
LM4_LPC_LPCCTL |= LM4_LPC_SCI_START;