Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the
  4.  *                   original/legacy sleep/PM registers.
  5.  *
  6.  *****************************************************************************/
  7.  
  8. /*
  9.  * Copyright (C) 2000 - 2015, Intel Corp.
  10.  * All rights reserved.
  11.  *
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  * 1. Redistributions of source code must retain the above copyright
  16.  *    notice, this list of conditions, and the following disclaimer,
  17.  *    without modification.
  18.  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  19.  *    substantially similar to the "NO WARRANTY" disclaimer below
  20.  *    ("Disclaimer") and any redistribution must be conditioned upon
  21.  *    including a substantially similar Disclaimer requirement for further
  22.  *    binary redistribution.
  23.  * 3. Neither the names of the above-listed copyright holders nor the names
  24.  *    of any contributors may be used to endorse or promote products derived
  25.  *    from this software without specific prior written permission.
  26.  *
  27.  * Alternatively, this software may be distributed under the terms of the
  28.  * GNU General Public License ("GPL") version 2 as published by the Free
  29.  * Software Foundation.
  30.  *
  31.  * NO WARRANTY
  32.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  33.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  34.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  35.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  36.  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  41.  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42.  * POSSIBILITY OF SUCH DAMAGES.
  43.  */
  44.  
  45. #include <acpi/acpi.h>
  46. #include <linux/acpi.h>
  47. #include "accommon.h"
  48.  
  49. #define _COMPONENT          ACPI_HARDWARE
  50. ACPI_MODULE_NAME("hwsleep")
  51.  
  52. #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
  53. /*******************************************************************************
  54.  *
  55.  * FUNCTION:    acpi_hw_legacy_sleep
  56.  *
  57.  * PARAMETERS:  sleep_state         - Which sleep state to enter
  58.  *
  59.  * RETURN:      Status
  60.  *
  61.  * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers
  62.  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  63.  *
  64.  ******************************************************************************/
  65. acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
  66. {
  67.         struct acpi_bit_register_info *sleep_type_reg_info;
  68.         struct acpi_bit_register_info *sleep_enable_reg_info;
  69.         u32 pm1a_control;
  70.         u32 pm1b_control;
  71.         u32 in_value;
  72.         acpi_status status;
  73.  
  74.         ACPI_FUNCTION_TRACE(hw_legacy_sleep);
  75.  
  76.         sleep_type_reg_info =
  77.             acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
  78.         sleep_enable_reg_info =
  79.             acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
  80.  
  81.         /* Clear wake status */
  82.  
  83.         status =
  84.             acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
  85.         if (ACPI_FAILURE(status)) {
  86.                 return_ACPI_STATUS(status);
  87.         }
  88.  
  89.         /* Clear all fixed and general purpose status bits */
  90.  
  91.         status = acpi_hw_clear_acpi_status();
  92.         if (ACPI_FAILURE(status)) {
  93.                 return_ACPI_STATUS(status);
  94.         }
  95.  
  96.         /*
  97.          * 1) Disable/Clear all GPEs
  98.          * 2) Enable all wakeup GPEs
  99.          */
  100.         status = acpi_hw_disable_all_gpes();
  101.         if (ACPI_FAILURE(status)) {
  102.                 return_ACPI_STATUS(status);
  103.         }
  104.         acpi_gbl_system_awake_and_running = FALSE;
  105.  
  106.         status = acpi_hw_enable_all_wakeup_gpes();
  107.         if (ACPI_FAILURE(status)) {
  108.                 return_ACPI_STATUS(status);
  109.         }
  110.  
  111.         /* Get current value of PM1A control */
  112.  
  113.         status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
  114.                                        &pm1a_control);
  115.         if (ACPI_FAILURE(status)) {
  116.                 return_ACPI_STATUS(status);
  117.         }
  118.         ACPI_DEBUG_PRINT((ACPI_DB_INIT,
  119.                           "Entering sleep state [S%u]\n", sleep_state));
  120.  
  121.         /* Clear the SLP_EN and SLP_TYP fields */
  122.  
  123.         pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
  124.                           sleep_enable_reg_info->access_bit_mask);
  125.         pm1b_control = pm1a_control;
  126.  
  127.         /* Insert the SLP_TYP bits */
  128.  
  129.         pm1a_control |=
  130.             (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
  131.         pm1b_control |=
  132.             (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
  133.  
  134.         /*
  135.          * We split the writes of SLP_TYP and SLP_EN to workaround
  136.          * poorly implemented hardware.
  137.          */
  138.  
  139.         /* Write #1: write the SLP_TYP data to the PM1 Control registers */
  140.  
  141.         status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
  142.         if (ACPI_FAILURE(status)) {
  143.                 return_ACPI_STATUS(status);
  144.         }
  145.  
  146.         /* Insert the sleep enable (SLP_EN) bit */
  147.  
  148.         pm1a_control |= sleep_enable_reg_info->access_bit_mask;
  149.         pm1b_control |= sleep_enable_reg_info->access_bit_mask;
  150.  
  151.         /* Flush caches, as per ACPI specification */
  152.  
  153.         ACPI_FLUSH_CPU_CACHE();
  154.  
  155.         status = acpi_os_prepare_sleep(sleep_state, pm1a_control,
  156.                                        pm1b_control);
  157.         if (ACPI_SKIP(status))
  158.                 return_ACPI_STATUS(AE_OK);
  159.         if (ACPI_FAILURE(status))
  160.                 return_ACPI_STATUS(status);
  161.         /* Write #2: Write both SLP_TYP + SLP_EN */
  162.  
  163.         status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
  164.         if (ACPI_FAILURE(status)) {
  165.                 return_ACPI_STATUS(status);
  166.         }
  167.  
  168.         if (sleep_state > ACPI_STATE_S3) {
  169.                 /*
  170.                  * We wanted to sleep > S3, but it didn't happen (by virtue of the
  171.                  * fact that we are still executing!)
  172.                  *
  173.                  * Wait ten seconds, then try again. This is to get S4/S5 to work on
  174.                  * all machines.
  175.                  *
  176.                  * We wait so long to allow chipsets that poll this reg very slowly
  177.                  * to still read the right value. Ideally, this block would go
  178.                  * away entirely.
  179.                  */
  180.                 acpi_os_stall(10 * ACPI_USEC_PER_SEC);
  181.  
  182.                 status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
  183.                                                 sleep_enable_reg_info->
  184.                                                 access_bit_mask);
  185.                 if (ACPI_FAILURE(status)) {
  186.                         return_ACPI_STATUS(status);
  187.                 }
  188.         }
  189.  
  190.         /* Wait for transition back to Working State */
  191.  
  192.         do {
  193.                 status =
  194.                     acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
  195.                 if (ACPI_FAILURE(status)) {
  196.                         return_ACPI_STATUS(status);
  197.                 }
  198.  
  199.         } while (!in_value);
  200.  
  201.         return_ACPI_STATUS(AE_OK);
  202. }
  203.  
  204. /*******************************************************************************
  205.  *
  206.  * FUNCTION:    acpi_hw_legacy_wake_prep
  207.  *
  208.  * PARAMETERS:  sleep_state         - Which sleep state we just exited
  209.  *
  210.  * RETURN:      Status
  211.  *
  212.  * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
  213.  *              sleep.
  214.  *              Called with interrupts ENABLED.
  215.  *
  216.  ******************************************************************************/
  217.  
  218. acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state)
  219. {
  220.         acpi_status status;
  221.         struct acpi_bit_register_info *sleep_type_reg_info;
  222.         struct acpi_bit_register_info *sleep_enable_reg_info;
  223.         u32 pm1a_control;
  224.         u32 pm1b_control;
  225.  
  226.         ACPI_FUNCTION_TRACE(hw_legacy_wake_prep);
  227.  
  228.         /*
  229.          * Set SLP_TYPE and SLP_EN to state S0.
  230.          * This is unclear from the ACPI Spec, but it is required
  231.          * by some machines.
  232.          */
  233.         status = acpi_get_sleep_type_data(ACPI_STATE_S0,
  234.                                           &acpi_gbl_sleep_type_a,
  235.                                           &acpi_gbl_sleep_type_b);
  236.         if (ACPI_SUCCESS(status)) {
  237.                 sleep_type_reg_info =
  238.                     acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
  239.                 sleep_enable_reg_info =
  240.                     acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
  241.  
  242.                 /* Get current value of PM1A control */
  243.  
  244.                 status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
  245.                                                &pm1a_control);
  246.                 if (ACPI_SUCCESS(status)) {
  247.  
  248.                         /* Clear the SLP_EN and SLP_TYP fields */
  249.  
  250.                         pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
  251.                                           sleep_enable_reg_info->
  252.                                           access_bit_mask);
  253.                         pm1b_control = pm1a_control;
  254.  
  255.                         /* Insert the SLP_TYP bits */
  256.  
  257.                         pm1a_control |= (acpi_gbl_sleep_type_a <<
  258.                                          sleep_type_reg_info->bit_position);
  259.                         pm1b_control |= (acpi_gbl_sleep_type_b <<
  260.                                          sleep_type_reg_info->bit_position);
  261.  
  262.                         /* Write the control registers and ignore any errors */
  263.  
  264.                         (void)acpi_hw_write_pm1_control(pm1a_control,
  265.                                                         pm1b_control);
  266.                 }
  267.         }
  268.  
  269.         return_ACPI_STATUS(status);
  270. }
  271.  
  272. /*******************************************************************************
  273.  *
  274.  * FUNCTION:    acpi_hw_legacy_wake
  275.  *
  276.  * PARAMETERS:  sleep_state         - Which sleep state we just exited
  277.  *
  278.  * RETURN:      Status
  279.  *
  280.  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
  281.  *              Called with interrupts ENABLED.
  282.  *
  283.  ******************************************************************************/
  284.  
  285. acpi_status acpi_hw_legacy_wake(u8 sleep_state)
  286. {
  287.         acpi_status status;
  288.  
  289.         ACPI_FUNCTION_TRACE(hw_legacy_wake);
  290.  
  291.         /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
  292.  
  293.         acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
  294.         acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING);
  295.  
  296.         /*
  297.          * GPEs must be enabled before _WAK is called as GPEs
  298.          * might get fired there
  299.          *
  300.          * Restore the GPEs:
  301.          * 1) Disable/Clear all GPEs
  302.          * 2) Enable all runtime GPEs
  303.          */
  304.         status = acpi_hw_disable_all_gpes();
  305.         if (ACPI_FAILURE(status)) {
  306.                 return_ACPI_STATUS(status);
  307.         }
  308.  
  309.         status = acpi_hw_enable_all_runtime_gpes();
  310.         if (ACPI_FAILURE(status)) {
  311.                 return_ACPI_STATUS(status);
  312.         }
  313.  
  314.         /*
  315.          * Now we can execute _WAK, etc. Some machines require that the GPEs
  316.          * are enabled before the wake methods are executed.
  317.          */
  318.         acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state);
  319.  
  320.         /*
  321.          * Some BIOS code assumes that WAK_STS will be cleared on resume
  322.          * and use it to determine whether the system is rebooting or
  323.          * resuming. Clear WAK_STS for compatibility.
  324.          */
  325.         (void)acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS,
  326.                                       ACPI_CLEAR_STATUS);
  327.         acpi_gbl_system_awake_and_running = TRUE;
  328.  
  329.         /* Enable power button */
  330.  
  331.         (void)
  332.             acpi_write_bit_register(acpi_gbl_fixed_event_info
  333.                                     [ACPI_EVENT_POWER_BUTTON].
  334.                                     enable_register_id, ACPI_ENABLE_EVENT);
  335.  
  336.         (void)
  337.             acpi_write_bit_register(acpi_gbl_fixed_event_info
  338.                                     [ACPI_EVENT_POWER_BUTTON].
  339.                                     status_register_id, ACPI_CLEAR_STATUS);
  340.  
  341.         acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
  342.         return_ACPI_STATUS(status);
  343. }
  344.  
  345. #endif                          /* !ACPI_REDUCED_HARDWARE */
  346.