mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
common: Add new recovery mode button combination
This adds new key combination (Left_Shift+Esc+Refresh+Power) that triggers recovery mode by setting a new host event EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT. This host event can be used whenever user wants to request entry into recovery mode by reinitializing all the hardware state (e.g. memory retraining). BUG=chrome-os-partner:56643,chrome-os-partner:59352 BRANCH=None TEST=Verified that device retrains memory in recovery mode with (Left_Shift+Esc+Refresh+Power) on reef. Change-Id: I2e08997acfd9e22270b8ce7a5b589cd5630645f8 Signed-off-by: Furquan Shaikh <furquan@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/407827 Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
committed by
chrome-bot
parent
bf4e1db093
commit
2fc7ba9df1
@@ -70,12 +70,13 @@ struct boot_key_entry {
|
||||
uint8_t mask_index;
|
||||
uint8_t mask_value;
|
||||
};
|
||||
|
||||
static const struct boot_key_entry boot_key_list[] = {
|
||||
{0, 0x00}, /* (none) */
|
||||
{KEYBOARD_COL_ESC, KEYBOARD_MASK_ESC}, /* Esc */
|
||||
{KEYBOARD_COL_DOWN, KEYBOARD_MASK_DOWN}, /* Down-arrow */
|
||||
{KEYBOARD_COL_LEFT_SHIFT, KEYBOARD_MASK_LEFT_SHIFT}, /* Left-Shift */
|
||||
};
|
||||
static enum boot_key boot_key_value = BOOT_KEY_OTHER;
|
||||
static uint32_t boot_key_value = BOOT_KEY_NONE;
|
||||
|
||||
/* Debounced key matrix */
|
||||
static uint8_t __bss_slow debounced_state[KEYBOARD_COLS];
|
||||
@@ -516,21 +517,18 @@ static int check_keys_changed(uint8_t *state)
|
||||
}
|
||||
|
||||
/*
|
||||
* Return non-zero if the specified key is pressed, with at most the keys used
|
||||
* Returns mask of the boot keys that are pressed, with at most the keys used
|
||||
* for keyboard-controlled reset also pressed.
|
||||
*/
|
||||
static int check_key(const uint8_t *state, int index, int mask)
|
||||
static uint32_t check_key_list(const uint8_t *state)
|
||||
{
|
||||
uint8_t allowed_mask[KEYBOARD_COLS] = {0};
|
||||
uint8_t curr_state[KEYBOARD_COLS];
|
||||
int c;
|
||||
uint32_t boot_key_mask = BOOT_KEY_NONE;
|
||||
const struct boot_key_entry *k;
|
||||
|
||||
/* Check for the key */
|
||||
if (mask && !(state[index] & mask))
|
||||
return 0;
|
||||
|
||||
/* Check for other allowed keys */
|
||||
allowed_mask[index] |= mask;
|
||||
allowed_mask[KEYBOARD_COL_REFRESH] |= KEYBOARD_MASK_REFRESH;
|
||||
/* Make copy of current debounced state. */
|
||||
memcpy(curr_state, state, sizeof(curr_state));
|
||||
|
||||
#ifdef CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2
|
||||
/*
|
||||
@@ -539,19 +537,31 @@ static int check_key(const uint8_t *state, int index, int mask)
|
||||
*/
|
||||
for (c = 0; c < KEYBOARD_COLS; c++)
|
||||
if ((keyscan_config.actual_key_mask[c] & KEYBOARD_MASK_KSI2) &&
|
||||
!(state[c] & KEYBOARD_MASK_KSI2))
|
||||
!(curr_state[c] & KEYBOARD_MASK_KSI2))
|
||||
break;
|
||||
|
||||
if (c == KEYBOARD_COLS)
|
||||
for (c = 0; c < KEYBOARD_COLS; c++)
|
||||
allowed_mask[c] |= KEYBOARD_MASK_KSI2;
|
||||
curr_state[c] &= ~KEYBOARD_MASK_KSI2;
|
||||
#endif
|
||||
|
||||
for (c = 0; c < KEYBOARD_COLS; c++) {
|
||||
if (state[c] & ~allowed_mask[c])
|
||||
return 0; /* Disallowed key pressed */
|
||||
/* Update mask with all boot keys that were pressed. */
|
||||
k = boot_key_list;
|
||||
for (c = 0; c < ARRAY_SIZE(boot_key_list); c++, k++) {
|
||||
if (curr_state[k->mask_index] & k->mask_value) {
|
||||
boot_key_mask |= (1 << c);
|
||||
curr_state[k->mask_index] &= ~k->mask_value;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
/* If any other key was pressed, ignore all boot keys. */
|
||||
for (c = 0; c < KEYBOARD_COLS; c++) {
|
||||
if (curr_state[c])
|
||||
return BOOT_KEY_NONE;
|
||||
}
|
||||
|
||||
CPRINTS("KB boot key mask %x", boot_key_mask);
|
||||
return boot_key_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -559,37 +569,26 @@ static int check_key(const uint8_t *state, int index, int mask)
|
||||
*
|
||||
* @param state Keyboard state at boot.
|
||||
*
|
||||
* @return the key which is down, or BOOT_KEY_OTHER if an unrecognized
|
||||
* @return the key which is down, or BOOT_KEY_NONE if an unrecognized
|
||||
* key combination is down or this isn't the right type of boot to look at
|
||||
* boot keys.
|
||||
*/
|
||||
static enum boot_key check_boot_key(const uint8_t *state)
|
||||
static uint32_t check_boot_key(const uint8_t *state)
|
||||
{
|
||||
const struct boot_key_entry *k = boot_key_list;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* If we jumped to this image, ignore boot keys. This prevents
|
||||
* re-triggering events in RW firmware that were already processed by
|
||||
* RO firmware.
|
||||
*/
|
||||
if (system_jumped_to_this_image())
|
||||
return BOOT_KEY_OTHER;
|
||||
return BOOT_KEY_NONE;
|
||||
|
||||
/* If reset was not caused by reset pin, refresh must be held down */
|
||||
if (!(system_get_reset_flags() & RESET_FLAG_RESET_PIN) &&
|
||||
!(state[KEYBOARD_COL_REFRESH] & KEYBOARD_MASK_REFRESH))
|
||||
return BOOT_KEY_OTHER;
|
||||
return BOOT_KEY_NONE;
|
||||
|
||||
/* Check what single key is down */
|
||||
for (i = 0; i < ARRAY_SIZE(boot_key_list); i++, k++) {
|
||||
if (check_key(state, k->mask_index, k->mask_value)) {
|
||||
CPRINTS("KB boot key %d", i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return BOOT_KEY_OTHER;
|
||||
return check_key_list(state);
|
||||
}
|
||||
|
||||
static void keyboard_freq_change(void)
|
||||
@@ -607,7 +606,7 @@ struct keyboard_scan_config *keyboard_scan_get_config(void)
|
||||
return &keyscan_config;
|
||||
}
|
||||
|
||||
enum boot_key keyboard_scan_get_boot_key(void)
|
||||
uint32_t keyboard_scan_get_boot_keys(void)
|
||||
{
|
||||
return boot_key_value;
|
||||
}
|
||||
@@ -632,9 +631,19 @@ void keyboard_scan_init(void)
|
||||
/* Check for keys held down at boot */
|
||||
boot_key_value = check_boot_key(debounced_state);
|
||||
|
||||
/* Trigger event if recovery key was pressed */
|
||||
if (boot_key_value == BOOT_KEY_ESC)
|
||||
/*
|
||||
* If any key other than Esc or Left_Shift was pressed, do not trigger
|
||||
* recovery.
|
||||
*/
|
||||
if (boot_key_value & ~(BOOT_KEY_ESC | BOOT_KEY_LEFT_SHIFT))
|
||||
return;
|
||||
|
||||
if (boot_key_value & BOOT_KEY_ESC) {
|
||||
host_set_single_event(EC_HOST_EVENT_KEYBOARD_RECOVERY);
|
||||
if (boot_key_value & BOOT_KEY_LEFT_SHIFT)
|
||||
host_set_single_event(
|
||||
EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT);
|
||||
}
|
||||
}
|
||||
|
||||
void keyboard_scan_task(void)
|
||||
|
||||
@@ -208,7 +208,7 @@ static void set_initial_pwrbtn_state(void)
|
||||
CPRINTS("PB init-jumped");
|
||||
}
|
||||
} else if ((reset_flags & RESET_FLAG_AP_OFF) ||
|
||||
(keyboard_scan_get_boot_key() == BOOT_KEY_DOWN_ARROW)) {
|
||||
(keyboard_scan_get_boot_keys() == BOOT_KEY_DOWN_ARROW)) {
|
||||
/*
|
||||
* Reset triggered by keyboard-controlled reset, and down-arrow
|
||||
* was held down. Or reset flags request AP off.
|
||||
|
||||
@@ -548,6 +548,9 @@ enum host_event_code {
|
||||
/* TABLET/LAPTOP mode event*/
|
||||
EC_HOST_EVENT_MODE_CHANGE = 29,
|
||||
|
||||
/* Keyboard recovery combo with hardware reinitialization */
|
||||
EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT = 30,
|
||||
|
||||
/*
|
||||
* The high bit of the event mask is not used as a host event code. If
|
||||
* it reads back as set, then the entire event mask should be
|
||||
|
||||
@@ -60,5 +60,8 @@
|
||||
#define KEYBOARD_ROW_KEY_2 6
|
||||
#define KEYBOARD_MASK_KEY_2 KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_KEY_2)
|
||||
#define KEYBOARD_MASK_KSI2 KEYBOARD_ROW_TO_MASK(2)
|
||||
#define KEYBOARD_COL_LEFT_SHIFT 7
|
||||
#define KEYBOARD_ROW_LEFT_SHIFT 5
|
||||
#define KEYBOARD_MASK_LEFT_SHIFT KEYBOARD_ROW_TO_MASK(KEYBOARD_ROW_LEFT_SHIFT)
|
||||
|
||||
#endif /* __CROS_EC_KEYBOARD_CONFIG_H */
|
||||
|
||||
@@ -49,21 +49,28 @@ extern struct keyboard_scan_config keyscan_config;
|
||||
|
||||
/* Key held down at keyboard-controlled reset boot time. */
|
||||
enum boot_key {
|
||||
BOOT_KEY_NONE, /* No keys other than keyboard-controlled reset keys */
|
||||
BOOT_KEY_ESC,
|
||||
BOOT_KEY_DOWN_ARROW,
|
||||
BOOT_KEY_OTHER = -1, /* None of the above */
|
||||
/* No keys other than keyboard-controlled reset keys */
|
||||
BOOT_KEY_NONE = 0,
|
||||
BOOT_KEY_ESC = (1 << 0),
|
||||
BOOT_KEY_DOWN_ARROW = (1 << 1),
|
||||
BOOT_KEY_LEFT_SHIFT = (1 << 2),
|
||||
};
|
||||
|
||||
#ifdef HAS_TASK_KEYSCAN
|
||||
/**
|
||||
* Return the key held down at boot time in addition to the keyboard-controlled
|
||||
* reset keys. Returns BOOT_KEY_OTHER if none of the keys specifically checked
|
||||
* was pressed, or reset was not caused by a keyboard-controlled reset.
|
||||
* Returns mask of all the keys held down at boot time in addition to the
|
||||
* keyboard-controlled reset keys. If more than one boot key is held, mask bits
|
||||
* will be set for each of those keys. Since more than one bit can be set,
|
||||
* caller needs to ensure that boot keys match as intended.
|
||||
*
|
||||
* Returns BOOT_NONE if no additional key is held or if none of the keys
|
||||
* specifically checked was pressed, or reset was not caused by a
|
||||
* keyboard-controlled reset or if any key *other* than boot keys, power, or
|
||||
* refresh is also pressed.
|
||||
*/
|
||||
enum boot_key keyboard_scan_get_boot_key(void);
|
||||
uint32_t keyboard_scan_get_boot_keys(void);
|
||||
#else
|
||||
static inline enum boot_key keyboard_scan_get_boot_key(void)
|
||||
static inline uint32_t keyboard_scan_get_boot_keys(void)
|
||||
{
|
||||
return BOOT_KEY_NONE;
|
||||
}
|
||||
|
||||
@@ -350,12 +350,12 @@ static int lid_test(void)
|
||||
|
||||
static int test_check_boot_esc(void)
|
||||
{
|
||||
TEST_CHECK(keyboard_scan_get_boot_key() == BOOT_KEY_ESC);
|
||||
TEST_CHECK(keyboard_scan_get_boot_keys() == BOOT_KEY_ESC);
|
||||
}
|
||||
|
||||
static int test_check_boot_down(void)
|
||||
{
|
||||
TEST_CHECK(keyboard_scan_get_boot_key() == BOOT_KEY_DOWN_ARROW);
|
||||
TEST_CHECK(keyboard_scan_get_boot_keys() == BOOT_KEY_DOWN_ARROW);
|
||||
}
|
||||
|
||||
void test_init(void)
|
||||
|
||||
Reference in New Issue
Block a user