Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the
0005  *                   original/legacy sleep/PM registers.
0006  *
0007  * Copyright (C) 2000 - 2022, Intel Corp.
0008  *
0009  *****************************************************************************/
0010 
0011 #include <acpi/acpi.h>
0012 #include "accommon.h"
0013 
0014 #define _COMPONENT          ACPI_HARDWARE
0015 ACPI_MODULE_NAME("hwsleep")
0016 
0017 #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
0018 /*******************************************************************************
0019  *
0020  * FUNCTION:    acpi_hw_legacy_sleep
0021  *
0022  * PARAMETERS:  sleep_state         - Which sleep state to enter
0023  *
0024  * RETURN:      Status
0025  *
0026  * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers
0027  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
0028  *
0029  ******************************************************************************/
0030 acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
0031 {
0032     struct acpi_bit_register_info *sleep_type_reg_info;
0033     struct acpi_bit_register_info *sleep_enable_reg_info;
0034     u32 pm1a_control;
0035     u32 pm1b_control;
0036     u32 in_value;
0037     acpi_status status;
0038 
0039     ACPI_FUNCTION_TRACE(hw_legacy_sleep);
0040 
0041     sleep_type_reg_info =
0042         acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
0043     sleep_enable_reg_info =
0044         acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
0045 
0046     /* Clear wake status */
0047 
0048     status = acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS,
0049                      ACPI_CLEAR_STATUS);
0050     if (ACPI_FAILURE(status)) {
0051         return_ACPI_STATUS(status);
0052     }
0053 
0054     /* Disable all GPEs */
0055     status = acpi_hw_disable_all_gpes();
0056     if (ACPI_FAILURE(status)) {
0057         return_ACPI_STATUS(status);
0058     }
0059     status = acpi_hw_clear_acpi_status();
0060     if (ACPI_FAILURE(status)) {
0061         return_ACPI_STATUS(status);
0062     }
0063     acpi_gbl_system_awake_and_running = FALSE;
0064 
0065      /* Enable all wakeup GPEs */
0066     status = acpi_hw_enable_all_wakeup_gpes();
0067     if (ACPI_FAILURE(status)) {
0068         return_ACPI_STATUS(status);
0069     }
0070 
0071     /* Get current value of PM1A control */
0072 
0073     status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
0074                        &pm1a_control);
0075     if (ACPI_FAILURE(status)) {
0076         return_ACPI_STATUS(status);
0077     }
0078     ACPI_DEBUG_PRINT((ACPI_DB_INIT,
0079               "Entering sleep state [S%u]\n", sleep_state));
0080 
0081     /* Clear the SLP_EN and SLP_TYP fields */
0082 
0083     pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
0084               sleep_enable_reg_info->access_bit_mask);
0085     pm1b_control = pm1a_control;
0086 
0087     /* Insert the SLP_TYP bits */
0088 
0089     pm1a_control |=
0090         (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
0091     pm1b_control |=
0092         (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
0093 
0094     /*
0095      * We split the writes of SLP_TYP and SLP_EN to workaround
0096      * poorly implemented hardware.
0097      */
0098 
0099     /* Write #1: write the SLP_TYP data to the PM1 Control registers */
0100 
0101     status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
0102     if (ACPI_FAILURE(status)) {
0103         return_ACPI_STATUS(status);
0104     }
0105 
0106     /* Insert the sleep enable (SLP_EN) bit */
0107 
0108     pm1a_control |= sleep_enable_reg_info->access_bit_mask;
0109     pm1b_control |= sleep_enable_reg_info->access_bit_mask;
0110 
0111     /* Flush caches, as per ACPI specification */
0112 
0113     if (sleep_state < ACPI_STATE_S4) {
0114         ACPI_FLUSH_CPU_CACHE();
0115     }
0116 
0117     status = acpi_os_enter_sleep(sleep_state, pm1a_control, pm1b_control);
0118     if (status == AE_CTRL_TERMINATE) {
0119         return_ACPI_STATUS(AE_OK);
0120     }
0121     if (ACPI_FAILURE(status)) {
0122         return_ACPI_STATUS(status);
0123     }
0124 
0125     /* Write #2: Write both SLP_TYP + SLP_EN */
0126 
0127     status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
0128     if (ACPI_FAILURE(status)) {
0129         return_ACPI_STATUS(status);
0130     }
0131 
0132     if (sleep_state > ACPI_STATE_S3) {
0133         /*
0134          * We wanted to sleep > S3, but it didn't happen (by virtue of the
0135          * fact that we are still executing!)
0136          *
0137          * Wait ten seconds, then try again. This is to get S4/S5 to work on
0138          * all machines.
0139          *
0140          * We wait so long to allow chipsets that poll this reg very slowly
0141          * to still read the right value. Ideally, this block would go
0142          * away entirely.
0143          */
0144         acpi_os_stall(10 * ACPI_USEC_PER_SEC);
0145 
0146         status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
0147                         sleep_enable_reg_info->
0148                         access_bit_mask);
0149         if (ACPI_FAILURE(status)) {
0150             return_ACPI_STATUS(status);
0151         }
0152     }
0153 
0154     /* Wait for transition back to Working State */
0155 
0156     do {
0157         status =
0158             acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
0159         if (ACPI_FAILURE(status)) {
0160             return_ACPI_STATUS(status);
0161         }
0162 
0163     } while (!in_value);
0164 
0165     return_ACPI_STATUS(AE_OK);
0166 }
0167 
0168 /*******************************************************************************
0169  *
0170  * FUNCTION:    acpi_hw_legacy_wake_prep
0171  *
0172  * PARAMETERS:  sleep_state         - Which sleep state we just exited
0173  *
0174  * RETURN:      Status
0175  *
0176  * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
0177  *              sleep.
0178  *              Called with interrupts ENABLED.
0179  *
0180  ******************************************************************************/
0181 
0182 acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state)
0183 {
0184     acpi_status status = AE_OK;
0185     struct acpi_bit_register_info *sleep_type_reg_info;
0186     struct acpi_bit_register_info *sleep_enable_reg_info;
0187     u32 pm1a_control;
0188     u32 pm1b_control;
0189 
0190     ACPI_FUNCTION_TRACE(hw_legacy_wake_prep);
0191 
0192     /*
0193      * Set SLP_TYPE and SLP_EN to state S0.
0194      * This is unclear from the ACPI Spec, but it is required
0195      * by some machines.
0196      */
0197     if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) {
0198         sleep_type_reg_info =
0199             acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
0200         sleep_enable_reg_info =
0201             acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
0202 
0203         /* Get current value of PM1A control */
0204 
0205         status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
0206                            &pm1a_control);
0207         if (ACPI_SUCCESS(status)) {
0208 
0209             /* Clear the SLP_EN and SLP_TYP fields */
0210 
0211             pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
0212                       sleep_enable_reg_info->
0213                       access_bit_mask);
0214             pm1b_control = pm1a_control;
0215 
0216             /* Insert the SLP_TYP bits */
0217 
0218             pm1a_control |= (acpi_gbl_sleep_type_a_s0 <<
0219                      sleep_type_reg_info->bit_position);
0220             pm1b_control |= (acpi_gbl_sleep_type_b_s0 <<
0221                      sleep_type_reg_info->bit_position);
0222 
0223             /* Write the control registers and ignore any errors */
0224 
0225             (void)acpi_hw_write_pm1_control(pm1a_control,
0226                             pm1b_control);
0227         }
0228     }
0229 
0230     return_ACPI_STATUS(status);
0231 }
0232 
0233 /*******************************************************************************
0234  *
0235  * FUNCTION:    acpi_hw_legacy_wake
0236  *
0237  * PARAMETERS:  sleep_state         - Which sleep state we just exited
0238  *
0239  * RETURN:      Status
0240  *
0241  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
0242  *              Called with interrupts ENABLED.
0243  *
0244  ******************************************************************************/
0245 
0246 acpi_status acpi_hw_legacy_wake(u8 sleep_state)
0247 {
0248     acpi_status status;
0249 
0250     ACPI_FUNCTION_TRACE(hw_legacy_wake);
0251 
0252     /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
0253 
0254     acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
0255     acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING);
0256 
0257     /*
0258      * GPEs must be enabled before _WAK is called as GPEs
0259      * might get fired there
0260      *
0261      * Restore the GPEs:
0262      * 1) Disable all GPEs
0263      * 2) Enable all runtime GPEs
0264      */
0265     status = acpi_hw_disable_all_gpes();
0266     if (ACPI_FAILURE(status)) {
0267         return_ACPI_STATUS(status);
0268     }
0269 
0270     status = acpi_hw_enable_all_runtime_gpes();
0271     if (ACPI_FAILURE(status)) {
0272         return_ACPI_STATUS(status);
0273     }
0274 
0275     /*
0276      * Now we can execute _WAK, etc. Some machines require that the GPEs
0277      * are enabled before the wake methods are executed.
0278      */
0279     acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state);
0280 
0281     /*
0282      * Some BIOS code assumes that WAK_STS will be cleared on resume
0283      * and use it to determine whether the system is rebooting or
0284      * resuming. Clear WAK_STS for compatibility.
0285      */
0286     (void)acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS,
0287                       ACPI_CLEAR_STATUS);
0288     acpi_gbl_system_awake_and_running = TRUE;
0289 
0290     /* Enable power button */
0291 
0292     (void)
0293         acpi_write_bit_register(acpi_gbl_fixed_event_info
0294                     [ACPI_EVENT_POWER_BUTTON].
0295                     enable_register_id, ACPI_ENABLE_EVENT);
0296 
0297     (void)
0298         acpi_write_bit_register(acpi_gbl_fixed_event_info
0299                     [ACPI_EVENT_POWER_BUTTON].
0300                     status_register_id, ACPI_CLEAR_STATUS);
0301 
0302     /* Enable sleep button */
0303 
0304     (void)
0305         acpi_write_bit_register(acpi_gbl_fixed_event_info
0306                     [ACPI_EVENT_SLEEP_BUTTON].
0307                     enable_register_id, ACPI_ENABLE_EVENT);
0308 
0309     (void)
0310         acpi_write_bit_register(acpi_gbl_fixed_event_info
0311                     [ACPI_EVENT_SLEEP_BUTTON].
0312                     status_register_id, ACPI_CLEAR_STATUS);
0313 
0314     acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
0315     return_ACPI_STATUS(status);
0316 }
0317 
0318 #endif              /* !ACPI_REDUCED_HARDWARE */