Tegra: kbc: Allow keypresses during startup Add support to detect keys pressed before keyboard driver is loaded. BUG=chromium-os:17229 TEST=Built and tested on Seaboard. Reset seaboard keeping any key pressed and verify system enters u-boot console. Change-Id: I7508c901b79bf92be755a6e81a9556ccba4c78b1 Signed-off-by: Rakesh Iyer <riyer@nvidia.com> Reviewed-on: http://gerrit.chromium.org/gerrit/4964 Reviewed-by: Simon Glass <sjg@chromium.org>
diff --git a/drivers/input/tegra-kbc.c b/drivers/input/tegra-kbc.c index 604f7fa..f8e813a 100755 --- a/drivers/input/tegra-kbc.c +++ b/drivers/input/tegra-kbc.c
@@ -61,7 +61,9 @@ #define KBC_RPT_RATE 4 /* kbc globals */ -unsigned int kbc_repoll_time; +static unsigned int kbc_repoll_time; +static unsigned int kbc_init_dly; +static unsigned long kbc_start_time; /* * Use a simple FIFO to convert some keys into escape sequences and to handle @@ -404,8 +406,32 @@ } } +static void kbd_wait_for_fifo_init(void) +{ + unsigned long elapsed_time; + long delay; + static unsigned int kbc_initialized; + + if (kbc_initialized) + return; + /* + * In order to detect keys pressed on boot, wait for the hardware to + * complete scanning the keys. This includes time to transition from + * Wkup mode to Continous polling mode and the repoll time. We can + * deduct the time thats already elapsed. + */ + elapsed_time = timer_get_us() - kbc_start_time; + delay = kbc_init_dly + kbc_repoll_time - elapsed_time; + if (delay > 0) + udelay(delay); + + kbc_initialized = 1; +} + static int kbd_testc(void) { + kbd_wait_for_fifo_init(); + if (kbd_fifo_empty()) kbd_fifo_refill(kbd_fetch_char(1)); @@ -480,21 +506,8 @@ writel(val, &kbc->control); - /* - * Atomically clear out any remaining entries in the key FIFO - * and enable keyboard interrupts. - */ - while (1) { - val = readl(&kbc->interrupt); - val >>= 4; - if (val) { - readl(kbc->kp_ent[0]); - readl(kbc->kp_ent[1]); - } else { - break; - } - } - writel(0x7, &kbc->interrupt); + kbc_init_dly = readl(&kbc->init_dly) * (1000 / KBC_CYCLE_USEC); + kbc_start_time = timer_get_us(); return 0; }