hwacpi.c revision 246849
1219019Sgabor/******************************************************************************
2219019Sgabor *
3219019Sgabor * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
4219019Sgabor *
5219019Sgabor *****************************************************************************/
6219019Sgabor
7219019Sgabor/*
8219019Sgabor * Copyright (C) 2000 - 2013, Intel Corp.
9219019Sgabor * All rights reserved.
10219019Sgabor *
11219019Sgabor * Redistribution and use in source and binary forms, with or without
12219019Sgabor * modification, are permitted provided that the following conditions
13219019Sgabor * are met:
14219019Sgabor * 1. Redistributions of source code must retain the above copyright
15219019Sgabor *    notice, this list of conditions, and the following disclaimer,
16219019Sgabor *    without modification.
17219019Sgabor * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18219019Sgabor *    substantially similar to the "NO WARRANTY" disclaimer below
19219019Sgabor *    ("Disclaimer") and any redistribution must be conditioned upon
20219019Sgabor *    including a substantially similar Disclaimer requirement for further
21219019Sgabor *    binary redistribution.
22219019Sgabor * 3. Neither the names of the above-listed copyright holders nor the names
23219019Sgabor *    of any contributors may be used to endorse or promote products derived
24219019Sgabor *    from this software without specific prior written permission.
25219019Sgabor *
26219019Sgabor * Alternatively, this software may be distributed under the terms of the
27219019Sgabor * GNU General Public License ("GPL") version 2 as published by the Free
28219019Sgabor * Software Foundation.
29219019Sgabor *
30219019Sgabor * NO WARRANTY
31219019Sgabor * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32219019Sgabor * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33219019Sgabor * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34219019Sgabor * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35219019Sgabor * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36219019Sgabor * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37219019Sgabor * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38219019Sgabor * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39219019Sgabor * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40219019Sgabor * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41219019Sgabor * POSSIBILITY OF SUCH DAMAGES.
42219019Sgabor */
43219019Sgabor
44219019Sgabor#define __HWACPI_C__
45219019Sgabor
46219019Sgabor#include <contrib/dev/acpica/include/acpi.h>
47219019Sgabor#include <contrib/dev/acpica/include/accommon.h>
48219019Sgabor
49219019Sgabor
50219019Sgabor#define _COMPONENT          ACPI_HARDWARE
51219019Sgabor        ACPI_MODULE_NAME    ("hwacpi")
52219019Sgabor
53219019Sgabor
54219019Sgabor#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
55219019Sgabor/******************************************************************************
56219019Sgabor *
57219019Sgabor * FUNCTION:    AcpiHwSetMode
58219019Sgabor *
59219019Sgabor * PARAMETERS:  Mode            - SYS_MODE_ACPI or SYS_MODE_LEGACY
60219019Sgabor *
61219019Sgabor * RETURN:      Status
62219019Sgabor *
63219019Sgabor * DESCRIPTION: Transitions the system into the requested mode.
64219019Sgabor *
65219019Sgabor ******************************************************************************/
66219019Sgabor
67219019SgaborACPI_STATUS
68219019SgaborAcpiHwSetMode (
69219019Sgabor    UINT32                  Mode)
70219019Sgabor{
71219019Sgabor
72219019Sgabor    ACPI_STATUS             Status;
73219019Sgabor    UINT32                  Retry;
74219019Sgabor
75219019Sgabor
76219019Sgabor    ACPI_FUNCTION_TRACE (HwSetMode);
77219019Sgabor
78219019Sgabor
79219019Sgabor    /* If the Hardware Reduced flag is set, machine is always in acpi mode */
80219019Sgabor
81219019Sgabor    if (AcpiGbl_ReducedHardware)
82219019Sgabor    {
83219019Sgabor        return_ACPI_STATUS (AE_OK);
84219019Sgabor    }
85219019Sgabor
86219019Sgabor    /*
87219019Sgabor     * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
88219019Sgabor     * system does not support mode transition.
89219019Sgabor     */
90219019Sgabor    if (!AcpiGbl_FADT.SmiCommand)
91219019Sgabor    {
92219019Sgabor        ACPI_ERROR ((AE_INFO, "No SMI_CMD in FADT, mode transition failed"));
93219019Sgabor        return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
94219019Sgabor    }
95219019Sgabor
96219019Sgabor    /*
97219019Sgabor     * ACPI 2.0 clarified the meaning of ACPI_ENABLE and ACPI_DISABLE
98219019Sgabor     * in FADT: If it is zero, enabling or disabling is not supported.
99219019Sgabor     * As old systems may have used zero for mode transition,
100219019Sgabor     * we make sure both the numbers are zero to determine these
101219019Sgabor     * transitions are not supported.
102219019Sgabor     */
103219019Sgabor    if (!AcpiGbl_FADT.AcpiEnable && !AcpiGbl_FADT.AcpiDisable)
104219019Sgabor    {
105219019Sgabor        ACPI_ERROR ((AE_INFO,
106219019Sgabor            "No ACPI mode transition supported in this system "
107219019Sgabor            "(enable/disable both zero)"));
108219019Sgabor        return_ACPI_STATUS (AE_OK);
109219019Sgabor    }
110219019Sgabor
111219019Sgabor    switch (Mode)
112219019Sgabor    {
113219019Sgabor    case ACPI_SYS_MODE_ACPI:
114219019Sgabor
115219019Sgabor        /* BIOS should have disabled ALL fixed and GP events */
116219019Sgabor
117219019Sgabor        Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
118219019Sgabor                        (UINT32) AcpiGbl_FADT.AcpiEnable, 8);
119219019Sgabor        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n"));
120219019Sgabor        break;
121219019Sgabor
122219019Sgabor    case ACPI_SYS_MODE_LEGACY:
123219019Sgabor
124219019Sgabor        /*
125219019Sgabor         * BIOS should clear all fixed status bits and restore fixed event
126219019Sgabor         * enable bits to default
127219019Sgabor         */
128219019Sgabor        Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
129219019Sgabor                    (UINT32) AcpiGbl_FADT.AcpiDisable, 8);
130219019Sgabor        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
131219019Sgabor                    "Attempting to enable Legacy (non-ACPI) mode\n"));
132219019Sgabor        break;
133219019Sgabor
134219019Sgabor    default:
135219019Sgabor        return_ACPI_STATUS (AE_BAD_PARAMETER);
136219019Sgabor    }
137219019Sgabor
138219019Sgabor    if (ACPI_FAILURE (Status))
139219019Sgabor    {
140219019Sgabor        ACPI_EXCEPTION ((AE_INFO, Status,
141219019Sgabor            "Could not write ACPI mode change"));
142219019Sgabor        return_ACPI_STATUS (Status);
143219019Sgabor    }
144219019Sgabor
145219019Sgabor    /*
146219019Sgabor     * Some hardware takes a LONG time to switch modes. Give them 3 sec to
147219019Sgabor     * do so, but allow faster systems to proceed more quickly.
148219019Sgabor     */
149219019Sgabor    Retry = 3000;
150219019Sgabor    while (Retry)
151219019Sgabor    {
152219019Sgabor        if (AcpiHwGetMode () == Mode)
153219019Sgabor        {
154219019Sgabor            ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n",
155219019Sgabor                Mode));
156219019Sgabor            return_ACPI_STATUS (AE_OK);
157219019Sgabor        }
158219019Sgabor        AcpiOsStall (ACPI_USEC_PER_MSEC);
159219019Sgabor        Retry--;
160219019Sgabor    }
161219019Sgabor
162219019Sgabor    ACPI_ERROR ((AE_INFO, "Hardware did not change modes"));
163219019Sgabor    return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
164219019Sgabor}
165219019Sgabor
166219019Sgabor
167219019Sgabor/*******************************************************************************
168219019Sgabor *
169219019Sgabor * FUNCTION:    AcpiHwGetMode
170219019Sgabor *
171219019Sgabor * PARAMETERS:  none
172219019Sgabor *
173219019Sgabor * RETURN:      SYS_MODE_ACPI or SYS_MODE_LEGACY
174219019Sgabor *
175219019Sgabor * DESCRIPTION: Return current operating state of system. Determined by
176219019Sgabor *              querying the SCI_EN bit.
177219019Sgabor *
178219019Sgabor ******************************************************************************/
179219019Sgabor
180219019SgaborUINT32
181219019SgaborAcpiHwGetMode (
182219019Sgabor    void)
183219019Sgabor{
184219019Sgabor    ACPI_STATUS             Status;
185219019Sgabor    UINT32                  Value;
186219019Sgabor
187219019Sgabor
188219019Sgabor    ACPI_FUNCTION_TRACE (HwGetMode);
189219019Sgabor
190219019Sgabor
191219019Sgabor    /* If the Hardware Reduced flag is set, machine is always in acpi mode */
192219019Sgabor
193219019Sgabor    if (AcpiGbl_ReducedHardware)
194219019Sgabor    {
195219019Sgabor        return_UINT32 (ACPI_SYS_MODE_ACPI);
196219019Sgabor    }
197219019Sgabor
198219019Sgabor    /*
199219019Sgabor     * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
200219019Sgabor     * system does not support mode transition.
201219019Sgabor     */
202219019Sgabor    if (!AcpiGbl_FADT.SmiCommand)
203219019Sgabor    {
204219019Sgabor        return_UINT32 (ACPI_SYS_MODE_ACPI);
205219019Sgabor    }
206219019Sgabor
207219019Sgabor    Status = AcpiReadBitRegister (ACPI_BITREG_SCI_ENABLE, &Value);
208219019Sgabor    if (ACPI_FAILURE (Status))
209219019Sgabor    {
210219019Sgabor        return_UINT32 (ACPI_SYS_MODE_LEGACY);
211219019Sgabor    }
212219019Sgabor
213219019Sgabor    if (Value)
214219019Sgabor    {
215219019Sgabor        return_UINT32 (ACPI_SYS_MODE_ACPI);
216219019Sgabor    }
217219019Sgabor    else
218219019Sgabor    {
219219019Sgabor        return_UINT32 (ACPI_SYS_MODE_LEGACY);
220219019Sgabor    }
221219019Sgabor}
222219019Sgabor
223219019Sgabor#endif /* !ACPI_REDUCED_HARDWARE */
224219019Sgabor