1231798Sjkim/******************************************************************************
2231798Sjkim *
3231798Sjkim * Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the
4231798Sjkim *                    extended FADT-V5 sleep registers.
5231798Sjkim *
6231798Sjkim *****************************************************************************/
7231798Sjkim
8231798Sjkim/*
9245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
10231798Sjkim * All rights reserved.
11231798Sjkim *
12231798Sjkim * Redistribution and use in source and binary forms, with or without
13231798Sjkim * modification, are permitted provided that the following conditions
14231798Sjkim * are met:
15231798Sjkim * 1. Redistributions of source code must retain the above copyright
16231798Sjkim *    notice, this list of conditions, and the following disclaimer,
17231798Sjkim *    without modification.
18231798Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19231798Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
20231798Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
21231798Sjkim *    including a substantially similar Disclaimer requirement for further
22231798Sjkim *    binary redistribution.
23231798Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
24231798Sjkim *    of any contributors may be used to endorse or promote products derived
25231798Sjkim *    from this software without specific prior written permission.
26231798Sjkim *
27231798Sjkim * Alternatively, this software may be distributed under the terms of the
28231798Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
29231798Sjkim * Software Foundation.
30231798Sjkim *
31231798Sjkim * NO WARRANTY
32231798Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33231798Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34231798Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35231798Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36231798Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37231798Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38231798Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39231798Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40231798Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41231798Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42231798Sjkim * POSSIBILITY OF SUCH DAMAGES.
43231798Sjkim */
44231798Sjkim
45231844Sjkim#include <contrib/dev/acpica/include/acpi.h>
46231844Sjkim#include <contrib/dev/acpica/include/accommon.h>
47231798Sjkim
48231798Sjkim#define _COMPONENT          ACPI_HARDWARE
49231798Sjkim        ACPI_MODULE_NAME    ("hwesleep")
50231798Sjkim
51231798Sjkim
52231798Sjkim/*******************************************************************************
53231798Sjkim *
54231798Sjkim * FUNCTION:    AcpiHwExecuteSleepMethod
55231798Sjkim *
56233250Sjkim * PARAMETERS:  MethodPathname      - Pathname of method to execute
57231798Sjkim *              IntegerArgument     - Argument to pass to the method
58231798Sjkim *
59231798Sjkim * RETURN:      None
60231798Sjkim *
61231798Sjkim * DESCRIPTION: Execute a sleep/wake related method with one integer argument
62231798Sjkim *              and no return value.
63231798Sjkim *
64231798Sjkim ******************************************************************************/
65231798Sjkim
66231798Sjkimvoid
67231798SjkimAcpiHwExecuteSleepMethod (
68233250Sjkim    char                    *MethodPathname,
69231798Sjkim    UINT32                  IntegerArgument)
70231798Sjkim{
71231798Sjkim    ACPI_OBJECT_LIST        ArgList;
72231798Sjkim    ACPI_OBJECT             Arg;
73231798Sjkim    ACPI_STATUS             Status;
74231798Sjkim
75231798Sjkim
76231798Sjkim    ACPI_FUNCTION_TRACE (HwExecuteSleepMethod);
77231798Sjkim
78231798Sjkim
79231798Sjkim    /* One argument, IntegerArgument; No return value expected */
80231798Sjkim
81231798Sjkim    ArgList.Count = 1;
82231798Sjkim    ArgList.Pointer = &Arg;
83231798Sjkim    Arg.Type = ACPI_TYPE_INTEGER;
84231798Sjkim    Arg.Integer.Value = (UINT64) IntegerArgument;
85231798Sjkim
86233250Sjkim    Status = AcpiEvaluateObject (NULL, MethodPathname, &ArgList, NULL);
87231798Sjkim    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
88231798Sjkim    {
89231798Sjkim        ACPI_EXCEPTION ((AE_INFO, Status, "While executing method %s",
90233250Sjkim            MethodPathname));
91231798Sjkim    }
92231798Sjkim
93231798Sjkim    return_VOID;
94231798Sjkim}
95231798Sjkim
96231798Sjkim
97231798Sjkim/*******************************************************************************
98231798Sjkim *
99231798Sjkim * FUNCTION:    AcpiHwExtendedSleep
100231798Sjkim *
101231798Sjkim * PARAMETERS:  SleepState          - Which sleep state to enter
102231798Sjkim *
103231798Sjkim * RETURN:      Status
104231798Sjkim *
105231798Sjkim * DESCRIPTION: Enter a system sleep state via the extended FADT sleep
106231798Sjkim *              registers (V5 FADT).
107231798Sjkim *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
108231798Sjkim *
109231798Sjkim ******************************************************************************/
110231798Sjkim
111231798SjkimACPI_STATUS
112231798SjkimAcpiHwExtendedSleep (
113239340Sjkim    UINT8                   SleepState)
114231798Sjkim{
115231798Sjkim    ACPI_STATUS             Status;
116231798Sjkim    UINT8                   SleepTypeValue;
117231798Sjkim    UINT64                  SleepStatus;
118231798Sjkim
119231798Sjkim
120231798Sjkim    ACPI_FUNCTION_TRACE (HwExtendedSleep);
121231798Sjkim
122231798Sjkim
123231798Sjkim    /* Extended sleep registers must be valid */
124231798Sjkim
125231798Sjkim    if (!AcpiGbl_FADT.SleepControl.Address ||
126231798Sjkim        !AcpiGbl_FADT.SleepStatus.Address)
127231798Sjkim    {
128231798Sjkim        return_ACPI_STATUS (AE_NOT_EXIST);
129231798Sjkim    }
130231798Sjkim
131231798Sjkim    /* Clear wake status (WAK_STS) */
132231798Sjkim
133234623Sjkim    Status = AcpiWrite ((UINT64) ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus);
134231798Sjkim    if (ACPI_FAILURE (Status))
135231798Sjkim    {
136231798Sjkim        return_ACPI_STATUS (Status);
137231798Sjkim    }
138231798Sjkim
139231798Sjkim    AcpiGbl_SystemAwakeAndRunning = FALSE;
140231798Sjkim
141231798Sjkim    /* Flush caches, as per ACPI specification */
142231798Sjkim
143231798Sjkim    ACPI_FLUSH_CPU_CACHE ();
144231798Sjkim
145231798Sjkim    /*
146231798Sjkim     * Set the SLP_TYP and SLP_EN bits.
147231798Sjkim     *
148231798Sjkim     * Note: We only use the first value returned by the \_Sx method
149231798Sjkim     * (AcpiGbl_SleepTypeA) - As per ACPI specification.
150231798Sjkim     */
151231798Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
152231798Sjkim        "Entering sleep state [S%u]\n", SleepState));
153231798Sjkim
154231798Sjkim    SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) &
155231798Sjkim        ACPI_X_SLEEP_TYPE_MASK);
156231798Sjkim
157234623Sjkim    Status = AcpiWrite ((UINT64) (SleepTypeValue | ACPI_X_SLEEP_ENABLE),
158231798Sjkim        &AcpiGbl_FADT.SleepControl);
159231798Sjkim    if (ACPI_FAILURE (Status))
160231798Sjkim    {
161231798Sjkim        return_ACPI_STATUS (Status);
162231798Sjkim    }
163231798Sjkim
164231798Sjkim    /* Wait for transition back to Working State */
165231798Sjkim
166231798Sjkim    do
167231798Sjkim    {
168231798Sjkim        Status = AcpiRead (&SleepStatus, &AcpiGbl_FADT.SleepStatus);
169231798Sjkim        if (ACPI_FAILURE (Status))
170231798Sjkim        {
171231798Sjkim            return_ACPI_STATUS (Status);
172231798Sjkim        }
173231798Sjkim
174231798Sjkim    } while (!(((UINT8) SleepStatus) & ACPI_X_WAKE_STATUS));
175231798Sjkim
176231798Sjkim    return_ACPI_STATUS (AE_OK);
177231798Sjkim}
178231798Sjkim
179231798Sjkim
180231798Sjkim/*******************************************************************************
181231798Sjkim *
182231798Sjkim * FUNCTION:    AcpiHwExtendedWakePrep
183231798Sjkim *
184231798Sjkim * PARAMETERS:  SleepState          - Which sleep state we just exited
185231798Sjkim *
186231798Sjkim * RETURN:      Status
187231798Sjkim *
188231798Sjkim * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after
189231798Sjkim *              a sleep. Called with interrupts ENABLED.
190231798Sjkim *
191231798Sjkim ******************************************************************************/
192231798Sjkim
193231798SjkimACPI_STATUS
194231798SjkimAcpiHwExtendedWakePrep (
195239340Sjkim    UINT8                   SleepState)
196231798Sjkim{
197231798Sjkim    ACPI_STATUS             Status;
198231798Sjkim    UINT8                   SleepTypeValue;
199231798Sjkim
200231798Sjkim
201231798Sjkim    ACPI_FUNCTION_TRACE (HwExtendedWakePrep);
202231798Sjkim
203231798Sjkim
204231798Sjkim    Status = AcpiGetSleepTypeData (ACPI_STATE_S0,
205231798Sjkim                    &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
206231798Sjkim    if (ACPI_SUCCESS (Status))
207231798Sjkim    {
208231798Sjkim        SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) &
209231798Sjkim            ACPI_X_SLEEP_TYPE_MASK);
210231798Sjkim
211234623Sjkim        (void) AcpiWrite ((UINT64) (SleepTypeValue | ACPI_X_SLEEP_ENABLE),
212231798Sjkim            &AcpiGbl_FADT.SleepControl);
213231798Sjkim    }
214231798Sjkim
215231798Sjkim    return_ACPI_STATUS (AE_OK);
216231798Sjkim}
217231798Sjkim
218231798Sjkim
219231798Sjkim/*******************************************************************************
220231798Sjkim *
221231798Sjkim * FUNCTION:    AcpiHwExtendedWake
222231798Sjkim *
223231798Sjkim * PARAMETERS:  SleepState          - Which sleep state we just exited
224231798Sjkim *
225231798Sjkim * RETURN:      Status
226231798Sjkim *
227231798Sjkim * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
228231798Sjkim *              Called with interrupts ENABLED.
229231798Sjkim *
230231798Sjkim ******************************************************************************/
231231798Sjkim
232231798SjkimACPI_STATUS
233231798SjkimAcpiHwExtendedWake (
234239340Sjkim    UINT8                   SleepState)
235231798Sjkim{
236231798Sjkim    ACPI_FUNCTION_TRACE (HwExtendedWake);
237231798Sjkim
238231798Sjkim
239231798Sjkim    /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
240231798Sjkim
241231798Sjkim    AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
242231798Sjkim
243231798Sjkim    /* Execute the wake methods */
244231798Sjkim
245233250Sjkim    AcpiHwExecuteSleepMethod (METHOD_PATHNAME__SST, ACPI_SST_WAKING);
246233250Sjkim    AcpiHwExecuteSleepMethod (METHOD_PATHNAME__WAK, SleepState);
247231798Sjkim
248231798Sjkim    /*
249231798Sjkim     * Some BIOS code assumes that WAK_STS will be cleared on resume
250231798Sjkim     * and use it to determine whether the system is rebooting or
251231798Sjkim     * resuming. Clear WAK_STS for compatibility.
252231798Sjkim     */
253234623Sjkim    (void) AcpiWrite ((UINT64) ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus);
254231798Sjkim    AcpiGbl_SystemAwakeAndRunning = TRUE;
255231798Sjkim
256233250Sjkim    AcpiHwExecuteSleepMethod (METHOD_PATHNAME__SST, ACPI_SST_WORKING);
257231798Sjkim    return_ACPI_STATUS (AE_OK);
258231798Sjkim}
259