cregit-Linux how code gets into the kernel

Release 4.18 drivers/acpi/acpica/hwsleep.c

// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
/******************************************************************************
 *
 * Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the
 *                   original/legacy sleep/PM registers.
 *
 * Copyright (C) 2000 - 2018, Intel Corp.
 *
 *****************************************************************************/

#include <acpi/acpi.h>
#include "accommon.h"


#define _COMPONENT          ACPI_HARDWARE
ACPI_MODULE_NAME("hwsleep")

#if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
/*******************************************************************************
 *
 * FUNCTION:    acpi_hw_legacy_sleep
 *
 * PARAMETERS:  sleep_state         - Which sleep state to enter
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers
 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
 *
 ******************************************************************************/

acpi_status acpi_hw_legacy_sleep(u8 sleep_state) { struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; u32 pm1a_control; u32 pm1b_control; u32 in_value; acpi_status status; ACPI_FUNCTION_TRACE(hw_legacy_sleep); sleep_type_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); sleep_enable_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); /* Clear wake status */ status = acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Disable all GPEs */ status = acpi_hw_disable_all_gpes(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * If the target sleep state is S5, clear all GPEs and fixed events too */ if (sleep_state == ACPI_STATE_S5) { status = acpi_hw_clear_acpi_status(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } acpi_gbl_system_awake_and_running = FALSE; /* Enable all wakeup GPEs */ status = acpi_hw_enable_all_wakeup_gpes(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Get current value of PM1A control */ status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &pm1a_control); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Entering sleep state [S%u]\n", sleep_state)); /* Clear the SLP_EN and SLP_TYP fields */ pm1a_control &= ~(sleep_type_reg_info->access_bit_mask | sleep_enable_reg_info->access_bit_mask); pm1b_control = pm1a_control; /* Insert the SLP_TYP bits */ pm1a_control |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); pm1b_control |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); /* * We split the writes of SLP_TYP and SLP_EN to workaround * poorly implemented hardware. */ /* Write #1: write the SLP_TYP data to the PM1 Control registers */ status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Insert the sleep enable (SLP_EN) bit */ pm1a_control |= sleep_enable_reg_info->access_bit_mask; pm1b_control |= sleep_enable_reg_info->access_bit_mask; /* Flush caches, as per ACPI specification */ ACPI_FLUSH_CPU_CACHE(); status = acpi_os_enter_sleep(sleep_state, pm1a_control, pm1b_control); if (status == AE_CTRL_TERMINATE) { return_ACPI_STATUS(AE_OK); } if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Write #2: Write both SLP_TYP + SLP_EN */ status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (sleep_state > ACPI_STATE_S3) { /* * We wanted to sleep > S3, but it didn't happen (by virtue of the * fact that we are still executing!) * * Wait ten seconds, then try again. This is to get S4/S5 to work on * all machines. * * We wait so long to allow chipsets that poll this reg very slowly * to still read the right value. Ideally, this block would go * away entirely. */ acpi_os_stall(10 * ACPI_USEC_PER_SEC); status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, sleep_enable_reg_info-> access_bit_mask); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* Wait for transition back to Working State */ do { status = acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } while (!in_value); return_ACPI_STATUS(AE_OK); }

Contributors

PersonTokensPropCommitsCommitProp
Andy Grover18245.05%519.23%
Robert Moore6716.58%934.62%
Linus Torvalds6516.09%519.23%
Rafael J. Wysocki4912.13%27.69%
Len Brown266.44%311.54%
Joseph Cihula81.98%13.85%
Lv Zheng71.73%13.85%
Total404100.00%26100.00%

/******************************************************************************* * * FUNCTION: acpi_hw_legacy_wake_prep * * PARAMETERS: sleep_state - Which sleep state we just exited * * RETURN: Status * * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a * sleep. * Called with interrupts ENABLED. * ******************************************************************************/
acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) { acpi_status status; struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; u32 pm1a_control; u32 pm1b_control; ACPI_FUNCTION_TRACE(hw_legacy_wake_prep); /* * Set SLP_TYPE and SLP_EN to state S0. * This is unclear from the ACPI Spec, but it is required * by some machines. */ status = acpi_get_sleep_type_data(ACPI_STATE_S0, &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b); if (ACPI_SUCCESS(status)) { sleep_type_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); sleep_enable_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); /* Get current value of PM1A control */ status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &pm1a_control); if (ACPI_SUCCESS(status)) { /* Clear the SLP_EN and SLP_TYP fields */ pm1a_control &= ~(sleep_type_reg_info->access_bit_mask | sleep_enable_reg_info-> access_bit_mask); pm1b_control = pm1a_control; /* Insert the SLP_TYP bits */ pm1a_control |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); pm1b_control |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); /* Write the control registers and ignore any errors */ (void)acpi_hw_write_pm1_control(pm1a_control, pm1b_control); } } return_ACPI_STATUS(status); }

Contributors

PersonTokensPropCommitsCommitProp
Len Brown10975.69%337.50%
Robert Moore2315.97%337.50%
Linus Torvalds85.56%112.50%
Andy Grover42.78%112.50%
Total144100.00%8100.00%

/******************************************************************************* * * FUNCTION: acpi_hw_legacy_wake * * PARAMETERS: sleep_state - Which sleep state we just exited * * RETURN: Status * * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep * Called with interrupts ENABLED. * ******************************************************************************/
acpi_status acpi_hw_legacy_wake(u8 sleep_state) { acpi_status status; ACPI_FUNCTION_TRACE(hw_legacy_wake); /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING); /* * GPEs must be enabled before _WAK is called as GPEs * might get fired there * * Restore the GPEs: * 1) Disable all GPEs * 2) Enable all runtime GPEs */ status = acpi_hw_disable_all_gpes(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } status = acpi_hw_enable_all_runtime_gpes(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * Now we can execute _WAK, etc. Some machines require that the GPEs * are enabled before the wake methods are executed. */ acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state); /* * Some BIOS code assumes that WAK_STS will be cleared on resume * and use it to determine whether the system is rebooting or * resuming. Clear WAK_STS for compatibility. */ (void)acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); acpi_gbl_system_awake_and_running = TRUE; /* Enable power button */ (void) acpi_write_bit_register(acpi_gbl_fixed_event_info [ACPI_EVENT_POWER_BUTTON]. enable_register_id, ACPI_ENABLE_EVENT); (void) acpi_write_bit_register(acpi_gbl_fixed_event_info [ACPI_EVENT_POWER_BUTTON]. status_register_id, ACPI_CLEAR_STATUS); acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING); return_ACPI_STATUS(status); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Moore11183.46%337.50%
Len Brown75.26%112.50%
Rafael J. Wysocki64.51%112.50%
Linus Torvalds43.01%112.50%
Lv Zheng43.01%112.50%
Erik Schmauss10.75%112.50%
Total133100.00%8100.00%

#endif /* !ACPI_REDUCED_HARDWARE */

Overall Contributors

PersonTokensPropCommitsCommitProp
Robert Moore21330.00%1435.90%
Andy Grover18726.34%512.82%
Len Brown14520.42%615.38%
Linus Torvalds8612.11%512.82%
Rafael J. Wysocki557.75%25.13%
Lv Zheng111.55%25.13%
Joseph Cihula81.13%12.56%
Erik Schmauss30.42%25.13%
Patrick Mochel10.14%12.56%
Tang Liang10.14%12.56%
Total710100.00%39100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.