summaryrefslogtreecommitdiff
path: root/common/keyboard_scan.c
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-10-11 14:53:27 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2013-10-14 23:27:31 +0000
commit193f2298bd1a078f1ac07aacf9dc50132cbb39d3 (patch)
tree77f100d3f4b966ffe57de25bb44d5ec7bf31758e /common/keyboard_scan.c
parent1049bbbad81ab404c48cbc757c015cc8a373049b (diff)
downloadchrome-ec-193f2298bd1a078f1ac07aacf9dc50132cbb39d3.tar.gz
Enforce a minimum number of clocks between keyboard scans
When the EC CPU is running at a decreased clock frequency, frequent keyboard scans can starve other EC tasks of CPU and lead to dropped data or watchdog timeouts. Enforce a minimum number of EC clocks between keyboard scans to prevent this from happening. The default chosen (16000 clocks) is equal to the shortest post-scan delay (1 ms) of any current board when the AP is in S0, so this should have no effect when the AP is in S0. When the AP is in S3 or S5, we don't need to scan the keyboard as frequently anyway. This can be overridden on a per-board basis for future boards if needed. BUG=chrome-os-partner:23247 BRANCH=pit TEST=apshutdown, then hold down a key for 10 seconds. Should not see a watchdog reset. Change-Id: I228f53a32ad4769f6a137a9ab06903111bea115d Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/172895 Reviewed-by: Vic Yang <victoryang@chromium.org>
Diffstat (limited to 'common/keyboard_scan.c')
-rw-r--r--common/keyboard_scan.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/common/keyboard_scan.c b/common/keyboard_scan.c
index 8214d7c415..9641ff6ca9 100644
--- a/common/keyboard_scan.c
+++ b/common/keyboard_scan.c
@@ -6,6 +6,7 @@
/* Keyboard scanner module for Chrome EC */
#include "chipset.h"
+#include "clock.h"
#include "common.h"
#include "console.h"
#include "hooks.h"
@@ -27,6 +28,15 @@
#define SCAN_TIME_COUNT 32 /* Number of last scan times to track */
+#ifndef CONFIG_KEYBOARD_POST_SCAN_CLOCKS
+/*
+ * Default delay in clocks; this was experimentally determined to be long
+ * enough to avoid watchdog warnings or I2C errors on a typical notebook
+ * config on STM32.
+ */
+#define CONFIG_KEYBOARD_POST_SCAN_CLOCKS 16000
+#endif
+
#ifndef CONFIG_KEYBOARD_BOARD_CONFIG
/* Use default keyboard scan config, because board didn't supply one */
struct keyboard_scan_config keyscan_config = {
@@ -62,9 +72,13 @@ static uint8_t simulated_key[KEYBOARD_COLS]; /* Keys simulated-pressed */
static uint32_t scan_time[SCAN_TIME_COUNT]; /* Times of last scans */
static int scan_time_index; /* Current scan_time[] index */
+
/* Index into scan_time[] when each key started debouncing */
static uint8_t scan_edge_index[KEYBOARD_COLS][KEYBOARD_ROWS];
+/* Minimum delay between keyboard scans based on current clock frequency */
+static uint32_t post_scan_clock_us;
+
/*
* Print all keyboard scan state changes? Off by default because it generates
* a lot of debug output, which makes the saved EC console data less useful.
@@ -443,6 +457,13 @@ static enum boot_key check_boot_key(const uint8_t *state)
return BOOT_KEY_OTHER;
}
+static void keyboard_freq_change(void)
+{
+ post_scan_clock_us = (CONFIG_KEYBOARD_POST_SCAN_CLOCKS * 1000) /
+ (clock_get_freq() / 1000);
+}
+DECLARE_HOOK(HOOK_FREQ_CHANGE, keyboard_freq_change, HOOK_PRIO_DEFAULT);
+
/*****************************************************************************/
/* Interface */
@@ -490,6 +511,9 @@ void keyboard_scan_task(void)
keyboard_raw_task_start();
+ /* Set initial clock frequency-based minimum delay between scans */
+ keyboard_freq_change();
+
while (1) {
/* Enable all outputs */
CPRINTF("[%T KB wait]\n");
@@ -534,6 +558,9 @@ void keyboard_scan_task(void)
wait_time =
keyscan_config.min_post_scan_delay_us;
+ if (wait_time < post_scan_clock_us)
+ wait_time = post_scan_clock_us;
+
usleep(wait_time);
}
}