1 /******************************************************************************
   2  *
   3  * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 __HWACPI_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 
  49 
  50 #define _COMPONENT          ACPI_HARDWARE
  51         ACPI_MODULE_NAME    ("hwacpi")
  52 
  53 
  54 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
  55 /******************************************************************************
  56  *
  57  * FUNCTION:    AcpiHwSetMode
  58  *
  59  * PARAMETERS:  Mode            - SYS_MODE_ACPI or SYS_MODE_LEGACY
  60  *
  61  * RETURN:      Status
  62  *
  63  * DESCRIPTION: Transitions the system into the requested mode.
  64  *
  65  ******************************************************************************/
  66 
  67 ACPI_STATUS
  68 AcpiHwSetMode (
  69     UINT32                  Mode)
  70 {
  71 
  72     ACPI_STATUS             Status;
  73     UINT32                  Retry;
  74 
  75 
  76     ACPI_FUNCTION_TRACE (HwSetMode);
  77 
  78 
  79     /* If the Hardware Reduced flag is set, machine is always in acpi mode */
  80 
  81     if (AcpiGbl_ReducedHardware)
  82     {
  83         return_ACPI_STATUS (AE_OK);
  84     }
  85 
  86     /*
  87      * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
  88      * system does not support mode transition.
  89      */
  90     if (!AcpiGbl_FADT.SmiCommand)
  91     {
  92         ACPI_ERROR ((AE_INFO, "No SMI_CMD in FADT, mode transition failed"));
  93         return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
  94     }
  95 
  96     /*
  97      * ACPI 2.0 clarified the meaning of ACPI_ENABLE and ACPI_DISABLE
  98      * in FADT: If it is zero, enabling or disabling is not supported.
  99      * As old systems may have used zero for mode transition,
 100      * we make sure both the numbers are zero to determine these
 101      * transitions are not supported.
 102      */
 103     if (!AcpiGbl_FADT.AcpiEnable && !AcpiGbl_FADT.AcpiDisable)
 104     {
 105         ACPI_ERROR ((AE_INFO,
 106             "No ACPI mode transition supported in this system "
 107             "(enable/disable both zero)"));
 108         return_ACPI_STATUS (AE_OK);
 109     }
 110 
 111     switch (Mode)
 112     {
 113     case ACPI_SYS_MODE_ACPI:
 114 
 115         /* BIOS should have disabled ALL fixed and GP events */
 116 
 117         Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
 118                         (UINT32) AcpiGbl_FADT.AcpiEnable, 8);
 119         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n"));
 120         break;
 121 
 122     case ACPI_SYS_MODE_LEGACY:
 123         /*
 124          * BIOS should clear all fixed status bits and restore fixed event
 125          * enable bits to default
 126          */
 127         Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
 128                     (UINT32) AcpiGbl_FADT.AcpiDisable, 8);
 129         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 130                     "Attempting to enable Legacy (non-ACPI) mode\n"));
 131         break;
 132 
 133     default:
 134 
 135         return_ACPI_STATUS (AE_BAD_PARAMETER);
 136     }
 137 
 138     if (ACPI_FAILURE (Status))
 139     {
 140         ACPI_EXCEPTION ((AE_INFO, Status,
 141             "Could not write ACPI mode change"));
 142         return_ACPI_STATUS (Status);
 143     }
 144 
 145     /*
 146      * Some hardware takes a LONG time to switch modes. Give them 3 sec to
 147      * do so, but allow faster systems to proceed more quickly.
 148      */
 149     Retry = 3000;
 150     while (Retry)
 151     {
 152         if (AcpiHwGetMode () == Mode)
 153         {
 154             ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n",
 155                 Mode));
 156             return_ACPI_STATUS (AE_OK);
 157         }
 158         AcpiOsStall (ACPI_USEC_PER_MSEC);
 159         Retry--;
 160     }
 161 
 162     ACPI_ERROR ((AE_INFO, "Hardware did not change modes"));
 163     return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
 164 }
 165 
 166 
 167 /*******************************************************************************
 168  *
 169  * FUNCTION:    AcpiHwGetMode
 170  *
 171  * PARAMETERS:  none
 172  *
 173  * RETURN:      SYS_MODE_ACPI or SYS_MODE_LEGACY
 174  *
 175  * DESCRIPTION: Return current operating state of system. Determined by
 176  *              querying the SCI_EN bit.
 177  *
 178  ******************************************************************************/
 179 
 180 UINT32
 181 AcpiHwGetMode (
 182     void)
 183 {
 184     ACPI_STATUS             Status;
 185     UINT32                  Value;
 186 
 187 
 188     ACPI_FUNCTION_TRACE (HwGetMode);
 189 
 190 
 191     /* If the Hardware Reduced flag is set, machine is always in acpi mode */
 192 
 193     if (AcpiGbl_ReducedHardware)
 194     {
 195         return_UINT32 (ACPI_SYS_MODE_ACPI);
 196     }
 197 
 198     /*
 199      * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
 200      * system does not support mode transition.
 201      */
 202     if (!AcpiGbl_FADT.SmiCommand)
 203     {
 204         return_UINT32 (ACPI_SYS_MODE_ACPI);
 205     }
 206 
 207     Status = AcpiReadBitRegister (ACPI_BITREG_SCI_ENABLE, &Value);
 208     if (ACPI_FAILURE (Status))
 209     {
 210         return_UINT32 (ACPI_SYS_MODE_LEGACY);
 211     }
 212 
 213     if (Value)
 214     {
 215         return_UINT32 (ACPI_SYS_MODE_ACPI);
 216     }
 217     else
 218     {
 219         return_UINT32 (ACPI_SYS_MODE_LEGACY);
 220     }
 221 }
 222 
 223 #endif /* !ACPI_REDUCED_HARDWARE */