1231798Sjkim/******************************************************************************
2231798Sjkim *
3231798Sjkim * Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the
4231798Sjkim *                    extended FADT-V5 sleep registers.
5231798Sjkim *
6231798Sjkim *****************************************************************************/
7231798Sjkim
8231798Sjkim/*
9306536Sjkim * Copyright (C) 2000 - 2016, 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
133306536Sjkim    Status = AcpiWrite ((UINT64) ACPI_X_WAKE_STATUS,
134306536Sjkim        &AcpiGbl_FADT.SleepStatus);
135231798Sjkim    if (ACPI_FAILURE (Status))
136231798Sjkim    {
137231798Sjkim        return_ACPI_STATUS (Status);
138231798Sjkim    }
139231798Sjkim
140231798Sjkim    AcpiGbl_SystemAwakeAndRunning = FALSE;
141231798Sjkim
142231798Sjkim    /* Flush caches, as per ACPI specification */
143231798Sjkim
144231798Sjkim    ACPI_FLUSH_CPU_CACHE ();
145231798Sjkim
146231798Sjkim    /*
147231798Sjkim     * Set the SLP_TYP and SLP_EN bits.
148231798Sjkim     *
149231798Sjkim     * Note: We only use the first value returned by the \_Sx method
150231798Sjkim     * (AcpiGbl_SleepTypeA) - As per ACPI specification.
151231798Sjkim     */
152231798Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
153231798Sjkim        "Entering sleep state [S%u]\n", SleepState));
154231798Sjkim
155231798Sjkim    SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) &
156231798Sjkim        ACPI_X_SLEEP_TYPE_MASK);
157231798Sjkim
158234623Sjkim    Status = AcpiWrite ((UINT64) (SleepTypeValue | ACPI_X_SLEEP_ENABLE),
159231798Sjkim        &AcpiGbl_FADT.SleepControl);
160231798Sjkim    if (ACPI_FAILURE (Status))
161231798Sjkim    {
162231798Sjkim        return_ACPI_STATUS (Status);
163231798Sjkim    }
164231798Sjkim
165231798Sjkim    /* Wait for transition back to Working State */
166231798Sjkim
167231798Sjkim    do
168231798Sjkim    {
169231798Sjkim        Status = AcpiRead (&SleepStatus, &AcpiGbl_FADT.SleepStatus);
170231798Sjkim        if (ACPI_FAILURE (Status))
171231798Sjkim        {
172231798Sjkim            return_ACPI_STATUS (Status);
173231798Sjkim        }
174231798Sjkim
175231798Sjkim    } while (!(((UINT8) SleepStatus) & ACPI_X_WAKE_STATUS));
176231798Sjkim
177231798Sjkim    return_ACPI_STATUS (AE_OK);
178231798Sjkim}
179231798Sjkim
180231798Sjkim
181231798Sjkim/*******************************************************************************
182231798Sjkim *
183231798Sjkim * FUNCTION:    AcpiHwExtendedWakePrep
184231798Sjkim *
185231798Sjkim * PARAMETERS:  SleepState          - Which sleep state we just exited
186231798Sjkim *
187231798Sjkim * RETURN:      Status
188231798Sjkim *
189231798Sjkim * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after
190231798Sjkim *              a sleep. Called with interrupts ENABLED.
191231798Sjkim *
192231798Sjkim ******************************************************************************/
193231798Sjkim
194231798SjkimACPI_STATUS
195231798SjkimAcpiHwExtendedWakePrep (
196239340Sjkim    UINT8                   SleepState)
197231798Sjkim{
198231798Sjkim    ACPI_STATUS             Status;
199231798Sjkim    UINT8                   SleepTypeValue;
200231798Sjkim
201231798Sjkim
202231798Sjkim    ACPI_FUNCTION_TRACE (HwExtendedWakePrep);
203231798Sjkim
204231798Sjkim
205231798Sjkim    Status = AcpiGetSleepTypeData (ACPI_STATE_S0,
206306536Sjkim        &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
207231798Sjkim    if (ACPI_SUCCESS (Status))
208231798Sjkim    {
209231798Sjkim        SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) &
210231798Sjkim            ACPI_X_SLEEP_TYPE_MASK);
211231798Sjkim
212234623Sjkim        (void) AcpiWrite ((UINT64) (SleepTypeValue | ACPI_X_SLEEP_ENABLE),
213231798Sjkim            &AcpiGbl_FADT.SleepControl);
214231798Sjkim    }
215231798Sjkim
216231798Sjkim    return_ACPI_STATUS (AE_OK);
217231798Sjkim}
218231798Sjkim
219231798Sjkim
220231798Sjkim/*******************************************************************************
221231798Sjkim *
222231798Sjkim * FUNCTION:    AcpiHwExtendedWake
223231798Sjkim *
224231798Sjkim * PARAMETERS:  SleepState          - Which sleep state we just exited
225231798Sjkim *
226231798Sjkim * RETURN:      Status
227231798Sjkim *
228231798Sjkim * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
229231798Sjkim *              Called with interrupts ENABLED.
230231798Sjkim *
231231798Sjkim ******************************************************************************/
232231798Sjkim
233231798SjkimACPI_STATUS
234231798SjkimAcpiHwExtendedWake (
235239340Sjkim    UINT8                   SleepState)
236231798Sjkim{
237231798Sjkim    ACPI_FUNCTION_TRACE (HwExtendedWake);
238231798Sjkim
239231798Sjkim
240231798Sjkim    /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
241231798Sjkim
242231798Sjkim    AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
243231798Sjkim
244231798Sjkim    /* Execute the wake methods */
245231798Sjkim
246233250Sjkim    AcpiHwExecuteSleepMethod (METHOD_PATHNAME__SST, ACPI_SST_WAKING);
247233250Sjkim    AcpiHwExecuteSleepMethod (METHOD_PATHNAME__WAK, SleepState);
248231798Sjkim
249231798Sjkim    /*
250231798Sjkim     * Some BIOS code assumes that WAK_STS will be cleared on resume
251231798Sjkim     * and use it to determine whether the system is rebooting or
252231798Sjkim     * resuming. Clear WAK_STS for compatibility.
253231798Sjkim     */
254234623Sjkim    (void) AcpiWrite ((UINT64) ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus);
255231798Sjkim    AcpiGbl_SystemAwakeAndRunning = TRUE;
256231798Sjkim
257233250Sjkim    AcpiHwExecuteSleepMethod (METHOD_PATHNAME__SST, ACPI_SST_WORKING);
258231798Sjkim    return_ACPI_STATUS (AE_OK);
259231798Sjkim}
260