hwsleep.c revision 82367
1104382Sarchie 2104382Sarchie/****************************************************************************** 3104382Sarchie * 4104382Sarchie * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface 5104382Sarchie * $Revision: 18 $ 6104382Sarchie * 7104382Sarchie *****************************************************************************/ 8104382Sarchie 9104382Sarchie/****************************************************************************** 10104382Sarchie * 11104382Sarchie * 1. Copyright Notice 12104382Sarchie * 13104382Sarchie * Some or all of this work - Copyright (c) 1999, 2000, 2001, Intel Corp. 14104382Sarchie * All rights reserved. 15104382Sarchie * 16104382Sarchie * 2. License 17104382Sarchie * 18104382Sarchie * 2.1. This is your license from Intel Corp. under its intellectual property 19104382Sarchie * rights. You may have additional license terms from the party that provided 20104382Sarchie * you this software, covering your right to use that party's intellectual 21104382Sarchie * property rights. 22104382Sarchie * 23104382Sarchie * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 24104382Sarchie * copy of the source code appearing in this file ("Covered Code") an 25104382Sarchie * irrevocable, perpetual, worldwide license under Intel's copyrights in the 26104382Sarchie * base code distributed originally by Intel ("Original Intel Code") to copy, 27104382Sarchie * make derivatives, distribute, use and display any portion of the Covered 28104382Sarchie * Code in any form, with the right to sublicense such rights; and 29104382Sarchie * 30104382Sarchie * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 31104382Sarchie * license (with the right to sublicense), under only those claims of Intel 32104382Sarchie * patents that are infringed by the Original Intel Code, to make, use, sell, 33104382Sarchie * offer to sell, and import the Covered Code and derivative works thereof 34104382Sarchie * solely to the minimum extent necessary to exercise the above copyright 35104382Sarchie * license, and in no event shall the patent license extend to any additions 36104382Sarchie * to or modifications of the Original Intel Code. No other license or right 37104382Sarchie * is granted directly or by implication, estoppel or otherwise; 38166693Sjulian * 39104382Sarchie * The above copyright and patent license is granted only if the following 40104382Sarchie * conditions are met: 41104382Sarchie * 42104382Sarchie * 3. Conditions 43104382Sarchie * 44104382Sarchie * 3.1. Redistribution of Source with Rights to Further Distribute Source. 45104382Sarchie * Redistribution of source code of any substantial portion of the Covered 46104382Sarchie * Code or modification with rights to further distribute source must include 47104382Sarchie * the above Copyright Notice, the above License, this list of Conditions, 48104382Sarchie * and the following Disclaimer and Export Compliance provision. In addition, 49104382Sarchie * Licensee must cause all Covered Code to which Licensee contributes to 50166692Sjulian * contain a file documenting the changes Licensee made to create that Covered 51104382Sarchie * Code and the date of any change. Licensee must include in that file the 52104382Sarchie * documentation of any changes made by any predecessor Licensee. Licensee 53104382Sarchie * must include a prominent statement that the modification is derived, 54111476Sjulian * directly or indirectly, from Original Intel Code. 55104382Sarchie * 56152751Sru * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 57104382Sarchie * Redistribution of source code of any substantial portion of the Covered 58152751Sru * Code or modification without rights to further distribute source must 59123367Smarcel * include the following Disclaimer and Export Compliance provision in the 60123367Smarcel * documentation and/or other materials provided with distribution. In 61104382Sarchie * addition, Licensee may not authorize further sublicense of source of any 62108028Sru * portion of the Covered Code, and must include terms to the effect that the 63104382Sarchie * license from Licensee to its licensee is limited to the intellectual 64104382Sarchie * property embodied in the software Licensee provides to its licensee, and 65104382Sarchie * not to intellectual property embodied in modifications its licensee may 66104382Sarchie * make. 67104382Sarchie * 68104382Sarchie * 3.3. Redistribution of Executable. Redistribution in executable form of any 69104382Sarchie * substantial portion of the Covered Code or modification must reproduce the 70104382Sarchie * above Copyright Notice, and the following Disclaimer and Export Compliance 71104382Sarchie * provision in the documentation and/or other materials provided with the 72104382Sarchie * distribution. 73104382Sarchie * 74104382Sarchie * 3.4. Intel retains all right, title, and interest in and to the Original 75104382Sarchie * Intel Code. 76104382Sarchie * 77104382Sarchie * 3.5. Neither the name Intel nor any other trademark owned or controlled by 78104382Sarchie * Intel shall be used in advertising or otherwise to promote the sale, use or 79104382Sarchie * other dealings in products derived from or relating to the Covered Code 80104382Sarchie * without prior written authorization from Intel. 81104382Sarchie * 82104382Sarchie * 4. Disclaimer and Export Compliance 83104382Sarchie * 84104382Sarchie * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 85104382Sarchie * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 86104382Sarchie * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 87104382Sarchie * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 88104382Sarchie * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 89104382Sarchie * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 90108309Sjulian * PARTICULAR PURPOSE. 91104382Sarchie * 92104382Sarchie * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 93104382Sarchie * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 94104382Sarchie * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 95104382Sarchie * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 96104382Sarchie * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 97104382Sarchie * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 98104382Sarchie * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 99104382Sarchie * LIMITED REMEDY. 100104382Sarchie * 101104382Sarchie * 4.3. Licensee shall not export, either directly or indirectly, any of this 102104382Sarchie * software or system incorporating such software without first obtaining any 103104382Sarchie * required license or other approval from the U. S. Department of Commerce or 104104382Sarchie * any other agency or department of the United States Government. In the 105104382Sarchie * event Licensee exports any such software from the United States or 106104382Sarchie * re-exports any such software from a foreign destination, Licensee shall 107104382Sarchie * ensure that the distribution and export/re-export of the software is in 108104382Sarchie * compliance with all laws, regulations, orders, or other restrictions of the 109104382Sarchie * U.S. Export Administration Regulations. Licensee agrees that neither it nor 110104382Sarchie * any of its subsidiaries will export/re-export any technical data, process, 111104382Sarchie * software, or service, directly or indirectly, to any country for which the 112104382Sarchie * United States government or any agency thereof requires an export license, 113104382Sarchie * other governmental approval, or letter of assurance, without first obtaining 114104382Sarchie * such license, approval or letter. 115104382Sarchie * 116104382Sarchie *****************************************************************************/ 117104382Sarchie 118104382Sarchie#include "acpi.h" 119104382Sarchie#include "acnamesp.h" 120104382Sarchie#include "achware.h" 121104382Sarchie 122104382Sarchie#define _COMPONENT ACPI_HARDWARE 123166700Sbrueffer MODULE_NAME ("hwsleep") 124166700Sbrueffer 125166692Sjulian 126104382Sarchie/****************************************************************************** 127104382Sarchie * 128104382Sarchie * FUNCTION: AcpiSetFirmwareWakingVector 129104382Sarchie * 130108309Sjulian * PARAMETERS: PhysicalAddress - Physical address of ACPI real mode 131109564Smaxim * entry point. 132108309Sjulian * 133108309Sjulian * RETURN: AE_OK or AE_ERROR 134104382Sarchie * 135104382Sarchie * DESCRIPTION: Access function for dFirmwareWakingVector field in FACS 136108309Sjulian * 137104382Sarchie ******************************************************************************/ 138104382Sarchie 139104382SarchieACPI_STATUS 140104382SarchieAcpiSetFirmwareWakingVector ( 141104382Sarchie ACPI_PHYSICAL_ADDRESS PhysicalAddress) 142104382Sarchie{ 143104382Sarchie 144104382Sarchie FUNCTION_TRACE ("AcpiSetFirmwareWakingVector"); 145108309Sjulian 146108309Sjulian 147104382Sarchie /* Make sure that we have an FACS */ 148104382Sarchie 149104382Sarchie if (!AcpiGbl_FACS) 150104382Sarchie { 151104382Sarchie return_ACPI_STATUS (AE_NO_ACPI_TABLES); 152104382Sarchie } 153104382Sarchie 154104382Sarchie /* Set the vector */ 155104382Sarchie 156104382Sarchie if (AcpiGbl_FACS->VectorWidth == 32) 157104382Sarchie { 158104382Sarchie * (UINT32 *) AcpiGbl_FACS->FirmwareWakingVector = (UINT32) PhysicalAddress; 159104382Sarchie } 160104382Sarchie else 161104382Sarchie { 162166692Sjulian *AcpiGbl_FACS->FirmwareWakingVector = PhysicalAddress; 163166692Sjulian } 164166692Sjulian 165104382Sarchie return_ACPI_STATUS (AE_OK); 166104382Sarchie} 167111447Sru 168166692Sjulian 169104382Sarchie/****************************************************************************** 170104382Sarchie * 171104382Sarchie * FUNCTION: AcpiGetFirmwareWakingVector 172104382Sarchie * 173104382Sarchie * PARAMETERS: *PhysicalAddress - Output buffer where contents of 174104382Sarchie * the FirmwareWakingVector field of 175104382Sarchie * the FACS will be stored. 176104382Sarchie * 177104382Sarchie * RETURN: Status 178104382Sarchie * 179104382Sarchie * DESCRIPTION: Access function for dFirmwareWakingVector field in FACS 180104382Sarchie * 181104382Sarchie ******************************************************************************/ 182104382Sarchie 183104382SarchieACPI_STATUS 184104382SarchieAcpiGetFirmwareWakingVector ( 185104382Sarchie ACPI_PHYSICAL_ADDRESS *PhysicalAddress) 186104382Sarchie{ 187104382Sarchie 188104382Sarchie FUNCTION_TRACE ("AcpiGetFirmwareWakingVector"); 189104382Sarchie 190104382Sarchie 191104382Sarchie if (!PhysicalAddress) 192166692Sjulian { 193104382Sarchie return_ACPI_STATUS (AE_BAD_PARAMETER); 194104382Sarchie } 195104382Sarchie 196104382Sarchie /* Make sure that we have an FACS */ 197104690Sarchie 198166692Sjulian if (!AcpiGbl_FACS) 199104690Sarchie { 200104690Sarchie return_ACPI_STATUS (AE_NO_ACPI_TABLES); 201104690Sarchie } 202166692Sjulian 203104690Sarchie /* Get the vector */ 204104382Sarchie 205104382Sarchie if (AcpiGbl_FACS->VectorWidth == 32) 206104382Sarchie { 207104382Sarchie *PhysicalAddress = * (UINT32 *) AcpiGbl_FACS->FirmwareWakingVector; 208104382Sarchie } 209108028Sru else 210104382Sarchie { 211108028Sru *PhysicalAddress = *AcpiGbl_FACS->FirmwareWakingVector; 212104382Sarchie } 213104382Sarchie 214104382Sarchie return_ACPI_STATUS (AE_OK); 215104382Sarchie} 216166692Sjulian 217166692Sjulian/****************************************************************************** 218166692Sjulian * 219166700Sbrueffer * FUNCTION: AcpiEnterSleepState 220166700Sbrueffer * 221166692Sjulian * PARAMETERS: SleepState - Which sleep state to enter 222166700Sbrueffer * 223166700Sbrueffer * RETURN: Status 224166700Sbrueffer * 225166692Sjulian * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) 226104382Sarchie * 227166692Sjulian ******************************************************************************/ 228104382Sarchie 229104382SarchieACPI_STATUS 230166692SjulianAcpiEnterSleepState ( 231104382Sarchie UINT8 SleepState) 232104382Sarchie{ 233104382Sarchie ACPI_STATUS Status; 234104382Sarchie ACPI_OBJECT_LIST ArgList; 235166692Sjulian ACPI_OBJECT Arg; 236104382Sarchie UINT8 TypeA; 237104382Sarchie UINT8 TypeB; 238108309Sjulian UINT16 PM1AControl; 239108309Sjulian UINT16 PM1BControl; 240104382Sarchie 241166692Sjulian 242104382Sarchie FUNCTION_TRACE ("AcpiEnterSleepState"); 243104382Sarchie 244104382Sarchie 245104382Sarchie /* 246104382Sarchie * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. 247104382Sarchie */ 248104382Sarchie 249104382Sarchie Status = AcpiHwObtainSleepTypeRegisterData (SleepState, &TypeA, &TypeB); 250104382Sarchie if (!ACPI_SUCCESS (Status)) 251104382Sarchie { 252104382Sarchie return Status; 253104382Sarchie } 254104382Sarchie 255108028Sru /* run the _PTS and _GTS methods */ 256104382Sarchie 257108028Sru MEMSET(&ArgList, 0, sizeof(ArgList)); 258104382Sarchie ArgList.Count = 1; 259166692Sjulian ArgList.Pointer = &Arg; 260166692Sjulian 261108309Sjulian MEMSET(&Arg, 0, sizeof(Arg)); 262165117Sjulian Arg.Type = ACPI_TYPE_INTEGER; 263104382Sarchie Arg.Integer.Value = SleepState; 264165117Sjulian 265165117Sjulian AcpiEvaluateObject (NULL, "\\_PTS", &ArgList, NULL); 266104382Sarchie AcpiEvaluateObject (NULL, "\\_GTS", &ArgList, NULL); 267108028Sru 268104382Sarchie /* clear wake status */ 269108028Sru 270104382Sarchie AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1); 271104382Sarchie 272104382Sarchie disable (); 273104382Sarchie 274108309Sjulian /* TODO: disable all non-wake GPEs here */ 275108309Sjulian 276111476Sjulian PM1AControl = (UINT16) AcpiHwRegisterRead (ACPI_MTX_LOCK, PM1_CONTROL); 277104382Sarchie 278104382Sarchie ACPI_DEBUG_PRINT ((ACPI_DB_OK, "Entering S%d\n", SleepState)); 279109562Smaxim 280104382Sarchie /* mask off SLP_EN and SLP_TYP fields */ 281108028Sru 282123367Smarcel PM1AControl &= ~(SLP_TYPE_X_MASK | SLP_EN_MASK); 283123367Smarcel PM1BControl = PM1AControl; 284123367Smarcel 285123367Smarcel /* mask in SLP_TYP */ 286123367Smarcel 287123367Smarcel PM1AControl |= (TypeA << AcpiHwGetBitShift (SLP_TYPE_X_MASK)); 288123367Smarcel PM1BControl |= (TypeB << AcpiHwGetBitShift (SLP_TYPE_X_MASK)); 289123367Smarcel 290123367Smarcel /* write #1: fill in SLP_TYP data */ 291123367Smarcel 292104382Sarchie AcpiHwRegisterWrite (ACPI_MTX_LOCK, PM1A_CONTROL, PM1AControl); 293108028Sru AcpiHwRegisterWrite (ACPI_MTX_LOCK, PM1B_CONTROL, PM1BControl); 294104382Sarchie 295104382Sarchie /* mask in SLP_EN */ 296108309Sjulian 297104382Sarchie PM1AControl |= (1 << AcpiHwGetBitShift (SLP_EN_MASK)); 298104382Sarchie PM1BControl |= (1 << AcpiHwGetBitShift (SLP_EN_MASK)); 299108028Sru 300104382Sarchie /* flush caches */ 301104382Sarchie 302104382Sarchie wbinvd(); 303108087Sru 304104382Sarchie /* write #2: SLP_TYP + SLP_EN */ 305104382Sarchie 306104382Sarchie AcpiHwRegisterWrite (ACPI_MTX_LOCK, PM1A_CONTROL, PM1AControl); 307166692Sjulian AcpiHwRegisterWrite (ACPI_MTX_LOCK, PM1B_CONTROL, PM1BControl); 308104382Sarchie 309108028Sru /* 310104382Sarchie * Wait a second, then try again. This is to get S4/5 to work on all machines. 311108028Sru */ 312104382Sarchie if (SleepState > ACPI_STATE_S3) 313104382Sarchie { 314104382Sarchie AcpiOsStall(1000000); 315104382Sarchie 316104382Sarchie AcpiHwRegisterWrite (ACPI_MTX_LOCK, PM1_CONTROL, 317104382Sarchie (1 << AcpiHwGetBitShift (SLP_EN_MASK))); 318104382Sarchie } 319104382Sarchie 320104382Sarchie /* wait until we enter sleep state */ 321104382Sarchie 322104382Sarchie while (!AcpiHwRegisterBitAccess (ACPI_READ,ACPI_MTX_LOCK,WAK_STS)) 323104382Sarchie { } 324104382Sarchie 325104382Sarchie enable (); 326104382Sarchie 327140081Sru return_ACPI_STATUS (AE_OK); 328136280Sjulian} 329136280Sjulian 330136280Sjulian/****************************************************************************** 331136280Sjulian * 332136280Sjulian * FUNCTION: AcpiLeaveSleepState 333136280Sjulian * 334140081Sru * PARAMETERS: SleepState - Which sleep state we just exited 335140081Sru * 336140081Sru * RETURN: Status 337140081Sru * 338140081Sru * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep 339140081Sru * 340140081Sru ******************************************************************************/ 341136280Sjulian 342140081SruACPI_STATUS 343140081SruAcpiLeaveSleepState ( 344140081Sru UINT8 SleepState) 345136280Sjulian{ 346140081Sru ACPI_OBJECT_LIST ArgList; 347140081Sru ACPI_OBJECT Arg; 348140081Sru 349140081Sru FUNCTION_TRACE ("AcpiLeaveSleepState"); 350136280Sjulian 351136280Sjulian 352140081Sru MEMSET (&ArgList, 0, sizeof(ArgList)); 353140081Sru ArgList.Count = 1; 354136280Sjulian ArgList.Pointer = &Arg; 355136280Sjulian 356140081Sru MEMSET (&Arg, 0, sizeof(Arg)); 357136280Sjulian Arg.Type = ACPI_TYPE_INTEGER; 358140081Sru Arg.Integer.Value = SleepState; 359140081Sru 360140081Sru AcpiEvaluateObject (NULL, "\\_BFS", &ArgList, NULL); 361140081Sru AcpiEvaluateObject (NULL, "\\_WAK", &ArgList, NULL); 362136280Sjulian /* _WAK returns stuff - do we want to look at it? */ 363140081Sru 364140081Sru /* Re-enable GPEs */ 365140081Sru 366136280Sjulian return_ACPI_STATUS (AE_OK); 367140081Sru} 368140081Sru