Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces
  4.  *
  5.  *****************************************************************************/
  6.  
  7. /*
  8.  * Copyright (C) 2000 - 2015, Intel Corp.
  9.  * All rights reserved.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without
  12.  * modification, are permitted provided that the following conditions
  13.  * are met:
  14.  * 1. Redistributions of source code must retain the above copyright
  15.  *    notice, this list of conditions, and the following disclaimer,
  16.  *    without modification.
  17.  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18.  *    substantially similar to the "NO WARRANTY" disclaimer below
  19.  *    ("Disclaimer") and any redistribution must be conditioned upon
  20.  *    including a substantially similar Disclaimer requirement for further
  21.  *    binary redistribution.
  22.  * 3. Neither the names of the above-listed copyright holders nor the names
  23.  *    of any contributors may be used to endorse or promote products derived
  24.  *    from this software without specific prior written permission.
  25.  *
  26.  * Alternatively, this software may be distributed under the terms of the
  27.  * GNU General Public License ("GPL") version 2 as published by the Free
  28.  * Software Foundation.
  29.  *
  30.  * NO WARRANTY
  31.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35.  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40.  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41.  * POSSIBILITY OF SUCH DAMAGES.
  42.  */
  43.  
  44. #define EXPORT_ACPI_INTERFACES
  45.  
  46. #include <acpi/acpi.h>
  47. #include "accommon.h"
  48.  
  49. #define _COMPONENT          ACPI_HARDWARE
  50. ACPI_MODULE_NAME("hwxfsleep")
  51.  
  52. /* Local prototypes */
  53. #if (!ACPI_REDUCED_HARDWARE)
  54. static acpi_status
  55. acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs,
  56.                                     acpi_physical_address physical_address,
  57.                                     acpi_physical_address physical_address64);
  58. #endif
  59.  
  60. static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
  61.  
  62. /*
  63.  * Dispatch table used to efficiently branch to the various sleep
  64.  * functions.
  65.  */
  66. #define ACPI_SLEEP_FUNCTION_ID         0
  67. #define ACPI_WAKE_PREP_FUNCTION_ID     1
  68. #define ACPI_WAKE_FUNCTION_ID          2
  69.  
  70. /* Legacy functions are optional, based upon ACPI_REDUCED_HARDWARE */
  71.  
  72. static struct acpi_sleep_functions acpi_sleep_dispatch[] = {
  73.         {ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_sleep),
  74.          acpi_hw_extended_sleep},
  75.         {ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake_prep),
  76.          acpi_hw_extended_wake_prep},
  77.         {ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake), acpi_hw_extended_wake}
  78. };
  79.  
  80. /*
  81.  * These functions are removed for the ACPI_REDUCED_HARDWARE case:
  82.  *      acpi_set_firmware_waking_vectors
  83.  *      acpi_set_firmware_waking_vector
  84.  *      acpi_set_firmware_waking_vector64
  85.  *      acpi_enter_sleep_state_s4bios
  86.  */
  87.  
  88. #if (!ACPI_REDUCED_HARDWARE)
  89. /*******************************************************************************
  90.  *
  91.  * FUNCTION:    acpi_hw_set_firmware_waking_vectors
  92.  *
  93.  * PARAMETERS:  facs                - Pointer to FACS table
  94.  *              physical_address    - 32-bit physical address of ACPI real mode
  95.  *                                    entry point.
  96.  *              physical_address64  - 64-bit physical address of ACPI protected
  97.  *                                    mode entry point.
  98.  *
  99.  * RETURN:      Status
  100.  *
  101.  * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS
  102.  *
  103.  ******************************************************************************/
  104.  
  105. static acpi_status
  106. acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs,
  107.                                     acpi_physical_address physical_address,
  108.                                     acpi_physical_address physical_address64)
  109. {
  110.         ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vectors);
  111.  
  112.  
  113.         /*
  114.          * According to the ACPI specification 2.0c and later, the 64-bit
  115.          * waking vector should be cleared and the 32-bit waking vector should
  116.          * be used, unless we want the wake-up code to be called by the BIOS in
  117.          * Protected Mode.  Some systems (for example HP dv5-1004nr) are known
  118.          * to fail to resume if the 64-bit vector is used.
  119.          */
  120.  
  121.         /* Set the 32-bit vector */
  122.  
  123.         facs->firmware_waking_vector = (u32)physical_address;
  124.  
  125.         if (facs->length > 32) {
  126.                 if (facs->version >= 1) {
  127.  
  128.                         /* Set the 64-bit vector */
  129.  
  130.                         facs->xfirmware_waking_vector = physical_address64;
  131.                 } else {
  132.                         /* Clear the 64-bit vector if it exists */
  133.  
  134.                         facs->xfirmware_waking_vector = 0;
  135.                 }
  136.         }
  137.  
  138.         return_ACPI_STATUS(AE_OK);
  139. }
  140.  
  141. /*******************************************************************************
  142.  *
  143.  * FUNCTION:    acpi_set_firmware_waking_vectors
  144.  *
  145.  * PARAMETERS:  physical_address    - 32-bit physical address of ACPI real mode
  146.  *                                    entry point.
  147.  *              physical_address64  - 64-bit physical address of ACPI protected
  148.  *                                    mode entry point.
  149.  *
  150.  * RETURN:      Status
  151.  *
  152.  * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS
  153.  *
  154.  ******************************************************************************/
  155.  
  156. acpi_status
  157. acpi_set_firmware_waking_vectors(acpi_physical_address physical_address,
  158.                                  acpi_physical_address physical_address64)
  159. {
  160.  
  161.         ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vectors);
  162.  
  163.         if (acpi_gbl_FACS) {
  164.                 (void)acpi_hw_set_firmware_waking_vectors(acpi_gbl_FACS,
  165.                                                           physical_address,
  166.                                                           physical_address64);
  167.         }
  168.  
  169.         return_ACPI_STATUS(AE_OK);
  170. }
  171.  
  172. ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vectors)
  173.  
  174. /*******************************************************************************
  175.  *
  176.  * FUNCTION:    acpi_set_firmware_waking_vector
  177.  *
  178.  * PARAMETERS:  physical_address    - 32-bit physical address of ACPI real mode
  179.  *                                    entry point.
  180.  *
  181.  * RETURN:      Status
  182.  *
  183.  * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS
  184.  *
  185.  ******************************************************************************/
  186. acpi_status acpi_set_firmware_waking_vector(u32 physical_address)
  187. {
  188.         acpi_status status;
  189.  
  190.         ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
  191.  
  192.         status = acpi_set_firmware_waking_vectors((acpi_physical_address)
  193.                                                   physical_address, 0);
  194.  
  195.         return_ACPI_STATUS(status);
  196. }
  197.  
  198. ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
  199.  
  200. #if ACPI_MACHINE_WIDTH == 64
  201. /*******************************************************************************
  202.  *
  203.  * FUNCTION:    acpi_set_firmware_waking_vector64
  204.  *
  205.  * PARAMETERS:  physical_address    - 64-bit physical address of ACPI protected
  206.  *                                    mode entry point.
  207.  *
  208.  * RETURN:      Status
  209.  *
  210.  * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if
  211.  *              it exists in the table. This function is intended for use with
  212.  *              64-bit host operating systems.
  213.  *
  214.  ******************************************************************************/
  215. acpi_status acpi_set_firmware_waking_vector64(u64 physical_address)
  216. {
  217.         acpi_status status;
  218.  
  219.         ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64);
  220.  
  221.         status = acpi_set_firmware_waking_vectors(0,
  222.                                                   (acpi_physical_address)
  223.                                                   physical_address);
  224.  
  225.         return_ACPI_STATUS(status);
  226. }
  227.  
  228. ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64)
  229. #endif
  230. /*******************************************************************************
  231.  *
  232.  * FUNCTION:    acpi_enter_sleep_state_s4bios
  233.  *
  234.  * PARAMETERS:  None
  235.  *
  236.  * RETURN:      Status
  237.  *
  238.  * DESCRIPTION: Perform a S4 bios request.
  239.  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  240.  *
  241.  ******************************************************************************/
  242. acpi_status acpi_enter_sleep_state_s4bios(void)
  243. {
  244.         u32 in_value;
  245.         acpi_status status;
  246.  
  247.         ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios);
  248.  
  249.         /* Clear the wake status bit (PM1) */
  250.  
  251.         status =
  252.             acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
  253.         if (ACPI_FAILURE(status)) {
  254.                 return_ACPI_STATUS(status);
  255.         }
  256.  
  257.         status = acpi_hw_clear_acpi_status();
  258.         if (ACPI_FAILURE(status)) {
  259.                 return_ACPI_STATUS(status);
  260.         }
  261.  
  262.         /*
  263.          * 1) Disable/Clear all GPEs
  264.          * 2) Enable all wakeup GPEs
  265.          */
  266.         status = acpi_hw_disable_all_gpes();
  267.         if (ACPI_FAILURE(status)) {
  268.                 return_ACPI_STATUS(status);
  269.         }
  270.         acpi_gbl_system_awake_and_running = FALSE;
  271.  
  272.         status = acpi_hw_enable_all_wakeup_gpes();
  273.         if (ACPI_FAILURE(status)) {
  274.                 return_ACPI_STATUS(status);
  275.         }
  276.  
  277.         ACPI_FLUSH_CPU_CACHE();
  278.  
  279.         status = acpi_hw_write_port(acpi_gbl_FADT.smi_command,
  280.                                     (u32)acpi_gbl_FADT.s4_bios_request, 8);
  281.  
  282.         do {
  283.                 acpi_os_stall(ACPI_USEC_PER_MSEC);
  284.                 status =
  285.                     acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
  286.                 if (ACPI_FAILURE(status)) {
  287.                         return_ACPI_STATUS(status);
  288.                 }
  289.         } while (!in_value);
  290.  
  291.         return_ACPI_STATUS(AE_OK);
  292. }
  293.  
  294. ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
  295. #endif                          /* !ACPI_REDUCED_HARDWARE */
  296. /*******************************************************************************
  297.  *
  298.  * FUNCTION:    acpi_hw_sleep_dispatch
  299.  *
  300.  * PARAMETERS:  sleep_state         - Which sleep state to enter/exit
  301.  *              function_id         - Sleep, wake_prep, or Wake
  302.  *
  303.  * RETURN:      Status from the invoked sleep handling function.
  304.  *
  305.  * DESCRIPTION: Dispatch a sleep/wake request to the appropriate handling
  306.  *              function.
  307.  *
  308.  ******************************************************************************/
  309. static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id)
  310. {
  311.         acpi_status status;
  312.         struct acpi_sleep_functions *sleep_functions =
  313.             &acpi_sleep_dispatch[function_id];
  314.  
  315. #if (!ACPI_REDUCED_HARDWARE)
  316.         /*
  317.          * If the Hardware Reduced flag is set (from the FADT), we must
  318.          * use the extended sleep registers (FADT). Note: As per the ACPI
  319.          * specification, these extended registers are to be used for HW-reduced
  320.          * platforms only. They are not general-purpose replacements for the
  321.          * legacy PM register sleep support.
  322.          */
  323.         if (acpi_gbl_reduced_hardware) {
  324.                 status = sleep_functions->extended_function(sleep_state);
  325.         } else {
  326.                 /* Legacy sleep */
  327.  
  328.                 status = sleep_functions->legacy_function(sleep_state);
  329.         }
  330.  
  331.         return (status);
  332.  
  333. #else
  334.         /*
  335.          * For the case where reduced-hardware-only code is being generated,
  336.          * we know that only the extended sleep registers are available
  337.          */
  338.         status = sleep_functions->extended_function(sleep_state);
  339.         return (status);
  340.  
  341. #endif                          /* !ACPI_REDUCED_HARDWARE */
  342. }
  343.  
  344. /*******************************************************************************
  345.  *
  346.  * FUNCTION:    acpi_enter_sleep_state_prep
  347.  *
  348.  * PARAMETERS:  sleep_state         - Which sleep state to enter
  349.  *
  350.  * RETURN:      Status
  351.  *
  352.  * DESCRIPTION: Prepare to enter a system sleep state.
  353.  *              This function must execute with interrupts enabled.
  354.  *              We break sleeping into 2 stages so that OSPM can handle
  355.  *              various OS-specific tasks between the two steps.
  356.  *
  357.  ******************************************************************************/
  358.  
  359. acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
  360. {
  361.         acpi_status status;
  362.         struct acpi_object_list arg_list;
  363.         union acpi_object arg;
  364.         u32 sst_value;
  365.  
  366.         ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep);
  367.  
  368.         status = acpi_get_sleep_type_data(sleep_state,
  369.                                           &acpi_gbl_sleep_type_a,
  370.                                           &acpi_gbl_sleep_type_b);
  371.         if (ACPI_FAILURE(status)) {
  372.                 return_ACPI_STATUS(status);
  373.         }
  374.  
  375.         /* Execute the _PTS method (Prepare To Sleep) */
  376.  
  377.         arg_list.count = 1;
  378.         arg_list.pointer = &arg;
  379.         arg.type = ACPI_TYPE_INTEGER;
  380.         arg.integer.value = sleep_state;
  381.  
  382.         status =
  383.             acpi_evaluate_object(NULL, METHOD_PATHNAME__PTS, &arg_list, NULL);
  384.         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
  385.                 return_ACPI_STATUS(status);
  386.         }
  387.  
  388.         /* Setup the argument to the _SST method (System STatus) */
  389.  
  390.         switch (sleep_state) {
  391.         case ACPI_STATE_S0:
  392.  
  393.                 sst_value = ACPI_SST_WORKING;
  394.                 break;
  395.  
  396.         case ACPI_STATE_S1:
  397.         case ACPI_STATE_S2:
  398.         case ACPI_STATE_S3:
  399.  
  400.                 sst_value = ACPI_SST_SLEEPING;
  401.                 break;
  402.  
  403.         case ACPI_STATE_S4:
  404.  
  405.                 sst_value = ACPI_SST_SLEEP_CONTEXT;
  406.                 break;
  407.  
  408.         default:
  409.  
  410.                 sst_value = ACPI_SST_INDICATOR_OFF;     /* Default is off */
  411.                 break;
  412.         }
  413.  
  414.         /*
  415.          * Set the system indicators to show the desired sleep state.
  416.          * _SST is an optional method (return no error if not found)
  417.          */
  418.         acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, sst_value);
  419.         return_ACPI_STATUS(AE_OK);
  420. }
  421.  
  422. ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
  423.  
  424. /*******************************************************************************
  425.  *
  426.  * FUNCTION:    acpi_enter_sleep_state
  427.  *
  428.  * PARAMETERS:  sleep_state         - Which sleep state to enter
  429.  *
  430.  * RETURN:      Status
  431.  *
  432.  * DESCRIPTION: Enter a system sleep state
  433.  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  434.  *
  435.  ******************************************************************************/
  436. acpi_status acpi_enter_sleep_state(u8 sleep_state)
  437. {
  438.         acpi_status status;
  439.  
  440.         ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
  441.  
  442.         if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
  443.             (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
  444.                 ACPI_ERROR((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X",
  445.                             acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
  446.                 return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
  447.         }
  448.  
  449.         status = acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID);
  450.         return_ACPI_STATUS(status);
  451. }
  452.  
  453. ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
  454.  
  455. /*******************************************************************************
  456.  *
  457.  * FUNCTION:    acpi_leave_sleep_state_prep
  458.  *
  459.  * PARAMETERS:  sleep_state         - Which sleep state we are exiting
  460.  *
  461.  * RETURN:      Status
  462.  *
  463.  * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
  464.  *              sleep. Called with interrupts DISABLED.
  465.  *              We break wake/resume into 2 stages so that OSPM can handle
  466.  *              various OS-specific tasks between the two steps.
  467.  *
  468.  ******************************************************************************/
  469. acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
  470. {
  471.         acpi_status status;
  472.  
  473.         ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
  474.  
  475.         status =
  476.             acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_PREP_FUNCTION_ID);
  477.         return_ACPI_STATUS(status);
  478. }
  479.  
  480. ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state_prep)
  481.  
  482. /*******************************************************************************
  483.  *
  484.  * FUNCTION:    acpi_leave_sleep_state
  485.  *
  486.  * PARAMETERS:  sleep_state         - Which sleep state we are exiting
  487.  *
  488.  * RETURN:      Status
  489.  *
  490.  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
  491.  *              Called with interrupts ENABLED.
  492.  *
  493.  ******************************************************************************/
  494. acpi_status acpi_leave_sleep_state(u8 sleep_state)
  495. {
  496.         acpi_status status;
  497.  
  498.         ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
  499.  
  500.         status = acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_FUNCTION_ID);
  501.         return_ACPI_STATUS(status);
  502. }
  503.  
  504. ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)
  505.