<commit_before>/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* Power button and lid switch module for Chrome EC */

#include "chipset.h"
#include "console.h"
#include "eoption.h"
#include "gpio.h"
#include "keyboard.h"
#include "keyboard_scan.h"
#include "lpc.h"
#include "lpc_commands.h"
#include "power_button.h"
#include "system.h"
#include "task.h"
#include "timer.h"
#include "uart.h"
#include "util.h"

/* Power button state machine.
 *
 *   PWRBTN#   ---                      ----
 *     to EC     |______________________|
 *
 *
 *   PWRBTN#   ---  ---------           ----
 *    to PCH     |__|       |___________|
 *                t0    t1    held down
 *
 *   scan code   |                      |
 *    to host    v                      v
 *     @S0   make code             break code
 */
#define PWRBTN_DEBOUNCE_US 30000  /* Debounce time for power button */
#define PWRBTN_DELAY_T0    32000  /* 32ms (PCH requires >16ms) */
#define PWRBTN_DELAY_T1    (4000000 - PWRBTN_DELAY_T0)  /* 4 secs - t0 */
#define PWRBTN_RECOVERY_US 200000 /* Length of time to simulate power button
				   * press when booting into
				   * keyboard-controlled recovery mode */

#define LID_DEBOUNCE_US    30000  /* Debounce time for lid switch */
#define LID_PWRBTN_US      PWRBTN_DELAY_T0 /* Length of time to simulate power
					    * button press on lid open */

enum power_button_state {
	PWRBTN_STATE_STOPPED = 0,
	PWRBTN_STATE_START,
	PWRBTN_STATE_T0,
	PWRBTN_STATE_T1,
	PWRBTN_STATE_HELD_DOWN,
	PWRBTN_STATE_STOPPING,
	PWRBTN_STATE_BOOT_RESET,
	PWRBTN_STATE_BOOT_RECOVERY,
};
static enum power_button_state pwrbtn_state = PWRBTN_STATE_STOPPED;

/* Time for next state transition of power button state machine, or 0 if the
 * state doesn't have a timeout. */
static uint64_t tnext_state;

/* Debounce timeouts for power button and lid switch.  0 means the signal is
 * stable (not being debounced). */
static uint64_t tdebounce_lid;
static uint64_t tdebounce_pwr;

static uint8_t *memmap_switches;


/* Update status of non-debounced switches */
static void update_other_switches(void)
{
	if (gpio_get_level(GPIO_WRITE_PROTECT) == 0)
		*memmap_switches |= EC_LPC_SWITCH_WRITE_PROTECT_DISABLED;
	else
		*memmap_switches &= ~EC_LPC_SWITCH_WRITE_PROTECT_DISABLED;

	if (keyboard_scan_recovery_pressed())
		*memmap_switches |= EC_LPC_SWITCH_KEYBOARD_RECOVERY;
	else
		*memmap_switches &= ~EC_LPC_SWITCH_KEYBOARD_RECOVERY;

	if (gpio_get_level(GPIO_RECOVERYn) == 0)
		*memmap_switches |= EC_LPC_SWITCH_DEDICATED_RECOVERY;
	else
		*memmap_switches &= ~EC_LPC_SWITCH_DEDICATED_RECOVERY;

#ifdef CONFIG_FAKE_DEV_SWITCH
	if (eoption_get_bool(EOPTION_BOOL_FAKE_DEV))
		*memmap_switches |= EC_LPC_SWITCH_FAKE_DEVELOPER;
	else
		*memmap_switches &= ~EC_LPC_SWITCH_FAKE_DEVELOPER;
#endif
}


static void set_pwrbtn_to_pch(int high)
{
	uart_printf("[%T PB PCH pwrbtn=%s]\n", high ? "HIGH" : "LOW");
	gpio_set_level(GPIO_PCH_PWRBTNn, high);
}


/* Return 1 if power button is pressed, 0 if not pressed. */
static int get_power_button_pressed(void)
{
	return gpio_get_level(GPIO_POWER_BUTTONn) ? 0 : 1;
}


/* Power button state machine.  Passed current time from usec counter. */
static void state_machine(uint64_t tnow)
{
	/* Not the time to move onto next state */
	if (tnow < tnext_state)
		return;

	/* States last forever unless otherwise specified */
	tnext_state = 0;

	switch (pwrbtn_state) {
	case PWRBTN_STATE_START:
		tnext_state = tnow + PWRBTN_DELAY_T0;
		pwrbtn_state = PWRBTN_STATE_T0;
		set_pwrbtn_to_pch(0);
		break;
	case PWRBTN_STATE_T0:
		tnext_state = tnow + PWRBTN_DELAY_T1;
		pwrbtn_state = PWRBTN_STATE_T1;
		set_pwrbtn_to_pch(1);
		break;
	case PWRBTN_STATE_T1:
		pwrbtn_state = PWRBTN_STATE_HELD_DOWN;
		set_pwrbtn_to_pch(0);
		break;
	case PWRBTN_STATE_STOPPING:
		set_pwrbtn_to_pch(1);
		pwrbtn_state = PWRBTN_STATE_STOPPED;
		break;
	case PWRBTN_STATE_BOOT_RECOVERY:
		set_pwrbtn_to_pch(1);
		pwrbtn_state = PWRBTN_STATE_BOOT_RESET;
		break;
	case PWRBTN_STATE_STOPPED:
	case PWRBTN_STATE_HELD_DOWN:
	case PWRBTN_STATE_BOOT_RESET:
		/* Do nothing */
		break;<commit_msg>Fix power button turning system back on after 4 sec<commit_after>/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* Power button and lid switch module for Chrome EC */

#include "chipset.h"
#include "console.h"
#include "eoption.h"
#include "gpio.h"
#include "keyboard.h"
#include "keyboard_scan.h"
#include "lpc.h"
#include "lpc_commands.h"
#include "power_button.h"
#include "system.h"
#include "task.h"
#include "timer.h"
#include "uart.h"
#include "util.h"

/* Power button state machine.
 *
 *   PWRBTN#   ---                      ----
 *     to EC     |______________________|
 *
 *
 *   PWRBTN#   ---  ---------           ----
 *    to PCH     |__|       |___________|
 *                t0    t1    held down
 *
 *   scan code   |                      |
 *    to host    v                      v
 *     @S0   make code             break code
 */
#define PWRBTN_DEBOUNCE_US 30000  /* Debounce time for power button */
#define PWRBTN_DELAY_T0    32000  /* 32ms (PCH requires >16ms) */
#define PWRBTN_DELAY_T1    (4000000 - PWRBTN_DELAY_T0)  /* 4 secs - t0 */
#define PWRBTN_RECOVERY_US 200000 /* Length of time to simulate power button
				   * press when booting into
				   * keyboard-controlled recovery mode */

#define LID_DEBOUNCE_US    30000  /* Debounce time for lid switch */
#define LID_PWRBTN_US      PWRBTN_DELAY_T0 /* Length of time to simulate power
					    * button press on lid open */

enum power_button_state {
	PWRBTN_STATE_STOPPED = 0,
	PWRBTN_STATE_START,
	PWRBTN_STATE_T0,
	PWRBTN_STATE_T1,
	PWRBTN_STATE_HELD_DOWN,
	PWRBTN_STATE_STOPPING,
	PWRBTN_STATE_BOOT_RESET,
	PWRBTN_STATE_BOOT_RECOVERY,
};
static enum power_button_state pwrbtn_state = PWRBTN_STATE_STOPPED;

/* Time for next state transition of power button state machine, or 0 if the
 * state doesn't have a timeout. */
static uint64_t tnext_state;

/* Debounce timeouts for power button and lid switch.  0 means the signal is
 * stable (not being debounced). */
static uint64_t tdebounce_lid;
static uint64_t tdebounce_pwr;

static uint8_t *memmap_switches;


/* Update status of non-debounced switches */
static void update_other_switches(void)
{
	if (gpio_get_level(GPIO_WRITE_PROTECT) == 0)
		*memmap_switches |= EC_LPC_SWITCH_WRITE_PROTECT_DISABLED;
	else
		*memmap_switches &= ~EC_LPC_SWITCH_WRITE_PROTECT_DISABLED;

	if (keyboard_scan_recovery_pressed())
		*memmap_switches |= EC_LPC_SWITCH_KEYBOARD_RECOVERY;
	else
		*memmap_switches &= ~EC_LPC_SWITCH_KEYBOARD_RECOVERY;

	if (gpio_get_level(GPIO_RECOVERYn) == 0)
		*memmap_switches |= EC_LPC_SWITCH_DEDICATED_RECOVERY;
	else
		*memmap_switches &= ~EC_LPC_SWITCH_DEDICATED_RECOVERY;

#ifdef CONFIG_FAKE_DEV_SWITCH
	if (eoption_get_bool(EOPTION_BOOL_FAKE_DEV))
		*memmap_switches |= EC_LPC_SWITCH_FAKE_DEVELOPER;
	else
		*memmap_switches &= ~EC_LPC_SWITCH_FAKE_DEVELOPER;
#endif
}


static void set_pwrbtn_to_pch(int high)
{
	uart_printf("[%T PB PCH pwrbtn=%s]\n", high ? "HIGH" : "LOW");
	gpio_set_level(GPIO_PCH_PWRBTNn, high);
}


/* Return 1 if power button is pressed, 0 if not pressed. */
static int get_power_button_pressed(void)
{
	return gpio_get_level(GPIO_POWER_BUTTONn) ? 0 : 1;
}


/* Power button state machine.  Passed current time from usec counter. */
static void state_machine(uint64_t tnow)
{
	/* Not the time to move onto next state */
	if (tnow < tnext_state)
		return;

	/* States last forever unless otherwise specified */
	tnext_state = 0;

	switch (pwrbtn_state) {
	case PWRBTN_STATE_START:
		if (chipset_in_state(CHIPSET_STATE_SOFT_OFF)) {
			/* Chipset is off, so just pass the true power button
			 * state to the chipset. */
			pwrbtn_state = PWRBTN_STATE_HELD_DOWN;
		} else {
			/* Chipset is on, so send the chipset a pulse */
			tnext_state = tnow + PWRBTN_DELAY_T0;
			pwrbtn_state = PWRBTN_STATE_T0;
		}
		set_pwrbtn_to_pch(0);
		break;
	case PWRBTN_STATE_T0:
		tnext_state = tnow + PWRBTN_DELAY_T1;
		pwrbtn_state = PWRBTN_STATE_T1;
		set_pwrbtn_to_pch(1);
		break;
	case PWRBTN_STATE_T1:
		/* If the chipset is already off, don't tell it the power
		 * button is down; it'll just cause the chipset to turn on
		 * again. */
		if (!chipset_in_state(CHIPSET_STATE_SOFT_OFF))
			set_pwrbtn_to_pch(0);
		else
			uart_printf("[%T PB chipset already off]\n");
		pwrbtn_state = PWRBTN_STATE_HELD_DOWN;
		break;
	case PWRBTN_STATE_STOPPING:
		set_pwrbtn_to_pch(1);
		pwrbtn_state = PWRBTN_STATE_STOPPED;
		break;
	case PWRBTN_STATE_BOOT_RECOVERY:
		set_pwrbtn_to_pch(1);
		pwrbtn_state = PWRBTN_STATE_BOOT_RESET;
		break;
	case PWRBTN_STATE_STOPPED:
	case PWRBTN_STATE_HELD_DOWN:
	case PWRBTN_STATE_BOOT_RESET:
		/* Do nothing */
		break;
{'fraction_non_alphanumeric': 0.09147771696637999, 'fraction_numerical': 0.01731263263710488, 'mean_word_length': 3.7450980392156863, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5180831', 'n_tokens_mistral': 3754, 'n_tokens_neox': 3489, 'n_words': 807}