diff options
-rw-r--r-- | board/chell/board.c | 19 | ||||
-rw-r--r-- | board/chell/board.h | 6 | ||||
-rw-r--r-- | chip/mec1322/keyboard_raw.c | 68 | ||||
-rw-r--r-- | common/keyboard_scan.c | 24 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | include/ec_commands.h | 7 | ||||
-rw-r--r-- | include/keyboard_raw.h | 7 | ||||
-rw-r--r-- | util/ectool.c | 21 |
8 files changed, 155 insertions, 0 deletions
diff --git a/board/chell/board.c b/board/chell/board.c index 62701a36b6..dec82b4f1b 100644 --- a/board/chell/board.c +++ b/board/chell/board.c @@ -133,6 +133,25 @@ const enum gpio_signal hibernate_wake_pins[] = { }; const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins); +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +/* + * We have total 28 pins for keyboard connecter, {-1, -1} mean + * the N/A pin that don't consider it and reserve index 0 area + * that we don't have pin 0. + */ +const int keyboard_factory_scan_pins[][2] = { + {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, + {12, 6}, {4, 3}, {4, 2}, {0, 2}, {14, 2}, + {4, 0}, {0, 0}, {-1, -1}, {3, 2}, {10, 3}, + {10, 0}, {12, 5}, {-1, -1}, {10, 2}, {-1, -1}, + {0, 1}, {10, 4}, {-1, -1}, {-1, -1}, {0, 4}, + {10, 7}, {10, 6}, {0, 3}, {0, 5}, +}; + +const int keyboard_factory_scan_pins_used = + ARRAY_SIZE(keyboard_factory_scan_pins); +#endif + struct pi3usb9281_config pi3usb9281_chips[] = { { .i2c_port = I2C_PORT_USB_CHARGER_1, diff --git a/board/chell/board.h b/board/chell/board.h index b28e720bdb..1f735d155e 100644 --- a/board/chell/board.h +++ b/board/chell/board.h @@ -48,6 +48,7 @@ #define CONFIG_I2C_MASTER #define CONFIG_KEYBOARD_PROTOCOL_8042 #define CONFIG_KEYBOARD_COL2_INVERTED +#define CONFIG_KEYBOARD_FACTORY_TEST #define CONFIG_LED_COMMON #define CONFIG_LID_SWITCH #define CONFIG_LOW_POWER_IDLE @@ -205,6 +206,11 @@ enum temp_sensor_id { /* Try to negotiate to 20V since i2c noise problems should be fixed. */ #define PD_MAX_VOLTAGE_MV 20000 +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +extern const int keyboard_factory_scan_pins[][2]; +extern const int keyboard_factory_scan_pins_used; +#endif + /* Reset PD MCU */ void board_reset_pd_mcu(void); diff --git a/chip/mec1322/keyboard_raw.c b/chip/mec1322/keyboard_raw.c index 8569472682..729ab9bda0 100644 --- a/chip/mec1322/keyboard_raw.c +++ b/chip/mec1322/keyboard_raw.c @@ -81,3 +81,71 @@ void keyboard_raw_interrupt(void) task_wake(TASK_ID_KEYSCAN); } DECLARE_IRQ(MEC1322_IRQ_KSC_INT, keyboard_raw_interrupt, 1); + +#ifdef CONFIG_KEYBOARD_FACTORY_TEST + +/* Run keyboard factory testing, scan out KSO/KSI if any shorted. */ +int keyboard_factory_test_scan(void) +{ + int i, j; + uint16_t shorted = 0; + uint32_t port, id, val; + + /* Disable keyboard scan while testing */ + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_CLOSED); + + /* Set all of KSO/KSI pins to internal pull-up and input */ + for (i = 0; i < keyboard_factory_scan_pins_used; i++) { + + if (keyboard_factory_scan_pins[i][0] < 0) + continue; + + port = keyboard_factory_scan_pins[i][0]; + id = keyboard_factory_scan_pins[i][1]; + + gpio_set_alternate_function(port, 1 << id, -1); + gpio_set_flags_by_mask(port, 1 << id, + GPIO_INPUT | GPIO_PULL_UP); + } + + /* + * Set start pin to output low, then check other pins + * going to low level, it indicate the two pins are shorted. + */ + for (i = 0; i < keyboard_factory_scan_pins_used; i++) { + + if (keyboard_factory_scan_pins[i][0] < 0) + continue; + + port = keyboard_factory_scan_pins[i][0]; + id = keyboard_factory_scan_pins[i][1]; + + gpio_set_flags_by_mask(port, 1 << id, GPIO_OUT_LOW); + + for (j = 0; j < i; j++) { + + if (keyboard_factory_scan_pins[j][0] < 0) + continue; + + /* + * Get gpio pin control register, + * bit 24 indicate GPIO input from the pad. + */ + val = MEC1322_GPIO_CTL(keyboard_factory_scan_pins[j][0], + keyboard_factory_scan_pins[j][1]); + + if ((val & (1 << 24)) == 0) { + shorted = i << 8 | j; + goto done; + } + } + gpio_set_flags_by_mask(port, 1 << id, + GPIO_INPUT | GPIO_PULL_UP); + } +done: + gpio_config_module(MODULE_KEYBOARD_SCAN, 1); + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_CLOSED); + + return shorted; +} +#endif diff --git a/common/keyboard_scan.c b/common/keyboard_scan.c index cad5bb559a..cf046b86e4 100644 --- a/common/keyboard_scan.c +++ b/common/keyboard_scan.c @@ -748,6 +748,30 @@ DECLARE_HOST_COMMAND(EC_CMD_MKBP_SIMULATE_KEY, mkbp_command_simulate_key, EC_VER_MASK(0)); +#ifdef CONFIG_KEYBOARD_FACTORY_TEST +static int keyboard_factory_test(struct host_cmd_handler_args *args) +{ + struct ec_response_keyboard_factory_test *r = args->response; + + /* Only available on unlocked systems */ + if (system_is_locked()) + return EC_RES_ACCESS_DENIED; + + if (keyboard_factory_scan_pins_used == 0) + return EC_RES_INVALID_COMMAND; + + r->shorted = keyboard_factory_test_scan(); + + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} + +DECLARE_HOST_COMMAND(EC_CMD_KEYBOARD_FACTORY_TEST, + keyboard_factory_test, + EC_VER_MASK(0)); +#endif + /*****************************************************************************/ /* Console commands */ #ifdef CONFIG_CMD_KEYBOARD diff --git a/include/config.h b/include/config.h index a126055be8..28363da4eb 100644 --- a/include/config.h +++ b/include/config.h @@ -1209,6 +1209,9 @@ /* Compile code for MKBP keyboard protocol */ #undef CONFIG_KEYBOARD_PROTOCOL_MKBP +/* Support keyboard factory test scanning */ +#undef CONFIG_KEYBOARD_FACTORY_TEST + /* * Keyboard config (struct keyboard_scan_config) is in board.c. If this is * not defined, default values from common/keyboard_scan.c will be used. diff --git a/include/ec_commands.h b/include/ec_commands.h index 9434a5df45..a205878bec 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -2481,6 +2481,13 @@ struct ec_response_get_next_event { union ec_response_get_next_data data; } __packed; +/* Run keyboard factory test scanning */ +#define EC_CMD_KEYBOARD_FACTORY_TEST 0x68 + +struct ec_response_keyboard_factory_test { + uint16_t shorted; /* Keyboard pins are shorted */ +} __packed; + /*****************************************************************************/ /* Temperature sensor commands */ diff --git a/include/keyboard_raw.h b/include/keyboard_raw.h index 8591700b47..db13852635 100644 --- a/include/keyboard_raw.h +++ b/include/keyboard_raw.h @@ -71,4 +71,11 @@ void keyboard_raw_gpio_interrupt(enum gpio_signal signal); static inline void keyboard_raw_gpio_interrupt(enum gpio_signal signal) { } #endif /* !HAS_TASK_KEYSCAN */ +/** + * Run keyboard factory test scanning. + * + * @return non-zero if keyboard pins are shorted. + */ +int keyboard_factory_test_scan(void); + #endif /* __CROS_EC_KEYBOARD_RAW_H */ diff --git a/util/ectool.c b/util/ectool.c index d21bb99fe5..59793e21d6 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -121,6 +121,8 @@ const char help_str[] = " Set the delay before going into hibernation\n" " kbpress\n" " Simulate key press\n" + " kbfactorytest\n" + " Scan out keyboard if any pins are shorted\n" " i2cread\n" " Read I2C bus\n" " i2cwrite\n" @@ -4208,6 +4210,24 @@ int cmd_kbpress(int argc, char *argv[]) return 0; } +int cmd_keyboard_factory_test(int argc, char *argv[]) +{ + struct ec_response_keyboard_factory_test r; + int rv; + + rv = ec_command(EC_CMD_KEYBOARD_FACTORY_TEST, 0, + NULL, 0, &r, sizeof(r)); + if (rv < 0) + return rv; + + if (r.shorted != 0) + printf("Keyboard %d and %d pin are shorted.\n", + r.shorted & 0x00ff, r.shorted >> 8); + else + printf("Keyboard factory test passed.\n"); + + return 0; +} static void print_panic_reg(int regnum, const uint32_t *regs, int index) { @@ -6564,6 +6584,7 @@ const struct command commands[] = { {"lightbar", cmd_lightbar}, {"keyconfig", cmd_keyconfig}, {"keyscan", cmd_keyscan}, + {"kbfactorytest", cmd_keyboard_factory_test}, {"motionsense", cmd_motionsense}, {"nextevent", cmd_next_event}, {"panicinfo", cmd_panic_info}, |