[U-Boot] [PATCH v2 11/31] cros_ec: Support systems with no EC interrupt

Simon Glass sjg at chromium.org
Thu Feb 27 21:26:05 CET 2014


Some systems do not have an EC interrupt. Rather than assuming that the
interrupt is always present, and hanging forever waiting for more input,
handle the missing interrupt. This works by reading key scans only until
we get an identical one. This means the EC keyscan FIFO is empty.

Tested-by: Che-Liang Chiou <clchiou at chromium.org>
Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v2: None

 drivers/input/cros_ec_keyb.c | 34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/drivers/input/cros_ec_keyb.c b/drivers/input/cros_ec_keyb.c
index e8dac23..a2501e0 100644
--- a/drivers/input/cros_ec_keyb.c
+++ b/drivers/input/cros_ec_keyb.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <cros_ec.h>
+#include <errno.h>
 #include <fdtdec.h>
 #include <input.h>
 #include <key_matrix.h>
@@ -39,20 +40,34 @@ static struct keyb {
  * @param config	Keyboard config
  * @param keys		List of keys that we have detected
  * @param max_count	Maximum number of keys to return
- * @return number of pressed keys, 0 for none
+ * @param samep		Set to true if this scan repeats the last, else false
+ * @return number of pressed keys, 0 for none, -EIO on error
  */
 static int check_for_keys(struct keyb *config,
-			   struct key_matrix_key *keys, int max_count)
+			   struct key_matrix_key *keys, int max_count,
+			   bool *samep)
 {
 	struct key_matrix_key *key;
+	static struct mbkp_keyscan last_scan;
+	static bool last_scan_valid;
 	struct mbkp_keyscan scan;
 	unsigned int row, col, bit, data;
 	int num_keys;
 
 	if (cros_ec_scan_keyboard(config->dev, &scan)) {
 		debug("%s: keyboard scan failed\n", __func__);
-		return -1;
+		return -EIO;
 	}
+	*samep = last_scan_valid && !memcmp(&last_scan, &scan, sizeof(scan));
+
+	/*
+	 * This is a bit odd. The EC has no way to tell us that it has run
+	 * out of key scans. It just returns the same scan over and over
+	 * again. So the only way to detect that we have run out is to detect
+	 * that this scan is the same as the last.
+	 */
+	last_scan_valid = true;
+	memcpy(&last_scan, &scan, sizeof(last_scan));
 
 	for (col = num_keys = bit = 0; col < config->matrix.num_cols;
 			col++) {
@@ -112,6 +127,7 @@ int cros_ec_kbc_check(struct input_config *input)
 	int keycodes[KBC_MAX_KEYS];
 	int num_keys, num_keycodes;
 	int irq_pending, sent;
+	bool same = false;
 
 	/*
 	 * Loop until the EC has no more keyscan records, or we have
@@ -125,7 +141,10 @@ int cros_ec_kbc_check(struct input_config *input)
 	do {
 		irq_pending = cros_ec_interrupt_pending(config.dev);
 		if (irq_pending) {
-			num_keys = check_for_keys(&config, keys, KBC_MAX_KEYS);
+			num_keys = check_for_keys(&config, keys, KBC_MAX_KEYS,
+						  &same);
+			if (num_keys < 0)
+				return 0;
 			last_num_keys = num_keys;
 			memcpy(last_keys, keys, sizeof(keys));
 		} else {
@@ -142,6 +161,13 @@ int cros_ec_kbc_check(struct input_config *input)
 		num_keycodes = key_matrix_decode(&config.matrix, keys,
 				num_keys, keycodes, KBC_MAX_KEYS);
 		sent = input_send_keycodes(input, keycodes, num_keycodes);
+
+		/*
+		 * For those ECs without an interrupt, stop scanning when we
+		 * see that the scan is the same as last time.
+		 */
+		if ((irq_pending < 0) && same)
+			break;
 	} while (irq_pending && !sent);
 
 	return 1;
-- 
1.9.0.279.gdc9e3eb



More information about the U-Boot mailing list