/** * Check for some event triggering the shutdown. * * It can be either a long power button press or a shutdown triggered from the * AP and detected by reading POWER_GOOD. * * @return non-zero if a shutdown should happen, 0 if not */ static int check_for_power_off_event(void) { timestamp_t now; int pressed = 0; int ret = 0; /* * Check for power button press. */ if (power_button_is_pressed()) { pressed = 1; } else if (power_request == POWER_REQ_OFF) { power_request = POWER_REQ_NONE; return 4; /* return non-zero for shudown down */ } #ifdef HAS_TASK_KEYSCAN /* Dis/Enable keyboard scanning when the power button state changes */ if (!pressed || pressed != power_button_was_pressed) keyboard_scan_enable(!pressed, KB_SCAN_DISABLE_POWER_BUTTON); #endif now = get_time(); if (pressed) { if (!power_button_was_pressed) { power_off_deadline.val = now.val + DELAY_FORCE_SHUTDOWN; CPRINTS("power waiting for long press %u", power_off_deadline.le.lo); /* Ensure we will wake up to check the power key */ timer_arm(power_off_deadline, TASK_ID_CHIPSET); } else if (timestamp_expired(power_off_deadline, &now)) { power_off_deadline.val = 0; CPRINTS("power off after long press now=%u, %u", now.le.lo, power_off_deadline.le.lo); return 2; } } else if (power_button_was_pressed) { CPRINTS("power off cancel"); timer_cancel(TASK_ID_CHIPSET); } /* POWER_GOOD released by AP : shutdown immediately */ if (!power_has_signals(IN_POWER_GOOD)) { if (power_button_was_pressed) timer_cancel(TASK_ID_CHIPSET); ret = 3; } power_button_was_pressed = pressed; return ret; }
/** * Handle debounced power button changing state. */ static void power_button_change_deferred(void) { const int new_pressed = raw_power_button_pressed(); /* Re-enable keyboard scanning if power button is no longer pressed */ if (!new_pressed) keyboard_scan_enable(1, KB_SCAN_DISABLE_POWER_BUTTON); /* If power button hasn't changed state, nothing to do */ if (new_pressed == debounced_power_pressed) { power_button_is_stable = 1; return; } debounced_power_pressed = new_pressed; power_button_is_stable = 1; CPRINTS("power button %s", new_pressed ? "pressed" : "released"); /* Call hooks */ hook_notify(HOOK_POWER_BUTTON_CHANGE); /* Notify host if power button has been pressed */ if (new_pressed) host_set_single_event(EC_HOST_EVENT_POWER_BUTTON); }
void power_button_interrupt(enum gpio_signal signal) { /* * If power button is pressed, disable the matrix scan as soon as * possible to reduce the risk of false-reboot triggered by those keys * on the same column with refresh key. */ if (raw_power_button_pressed()) keyboard_scan_enable(0, KB_SCAN_DISABLE_POWER_BUTTON); /* Reset power button debounce time */ power_button_is_stable = 0; hook_call_deferred(power_button_change_deferred, PWRBTN_DEBOUNCE_US); }
/* Enable or disable input devices, based upon chipset state and tablet mode */ static void enable_input_devices(void) { int kb_enable = 1; int tp_enable = 1; /* Disable both TP and KB in tablet mode */ if (!gpio_get_level(GPIO_TABLET_MODE_L)) kb_enable = tp_enable = 0; /* Disable TP if chipset is off */ else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) tp_enable = 0; keyboard_scan_enable(kb_enable, KB_SCAN_DISABLE_LID_ANGLE); gpio_set_level(GPIO_ENABLE_TOUCHPAD, tp_enable); }
/* Enable or disable input devices, based upon chipset state and tablet mode */ static void enable_input_devices(void) { int kb_enable = 1; int tp_enable = 1; /* Disable KB & TP if chipset is off */ if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { kb_enable = 0; tp_enable = 0; } keyboard_scan_enable(kb_enable, KB_SCAN_DISABLE_LID_ANGLE); gpio_set_level(GPIO_EN_P3300_TRACKPAD_ODL, !tp_enable); }
/* 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; }