xref: /titanic_44/usr/src/uts/intel/io/acpica/hardware/hwxface.c (revision cb56572868bfc488bbd3ab847b09db2a25554d44)
1aa2aa9a6SDana Myers /******************************************************************************
2aa2aa9a6SDana Myers  *
3aa2aa9a6SDana Myers  * Module Name: hwxface - Public ACPICA hardware interfaces
4aa2aa9a6SDana Myers  *
5aa2aa9a6SDana Myers  *****************************************************************************/
6aa2aa9a6SDana Myers 
726f3cdf0SGordon Ross /*
8*cb565728SJerry Jelinek  * Copyright (C) 2000 - 2016, Intel Corp.
9aa2aa9a6SDana Myers  * All rights reserved.
10aa2aa9a6SDana Myers  *
1126f3cdf0SGordon Ross  * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross  * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross  * are met:
1426f3cdf0SGordon Ross  * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross  *    notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross  *    without modification.
1726f3cdf0SGordon Ross  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross  *    substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross  *    ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross  *    including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross  *    binary redistribution.
2226f3cdf0SGordon Ross  * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross  *    of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross  *    from this software without specific prior written permission.
25aa2aa9a6SDana Myers  *
2626f3cdf0SGordon Ross  * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross  * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross  * Software Foundation.
29aa2aa9a6SDana Myers  *
3026f3cdf0SGordon Ross  * NO WARRANTY
3126f3cdf0SGordon Ross  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross  * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross  */
43aa2aa9a6SDana Myers 
44*cb565728SJerry Jelinek #define EXPORT_ACPI_INTERFACES
45*cb565728SJerry Jelinek 
46aa2aa9a6SDana Myers #include "acpi.h"
47aa2aa9a6SDana Myers #include "accommon.h"
48aa2aa9a6SDana Myers #include "acnamesp.h"
49aa2aa9a6SDana Myers 
50aa2aa9a6SDana Myers #define _COMPONENT          ACPI_HARDWARE
51aa2aa9a6SDana Myers         ACPI_MODULE_NAME    ("hwxface")
52aa2aa9a6SDana Myers 
53aa2aa9a6SDana Myers 
54aa2aa9a6SDana Myers /******************************************************************************
55aa2aa9a6SDana Myers  *
56aa2aa9a6SDana Myers  * FUNCTION:    AcpiReset
57aa2aa9a6SDana Myers  *
58aa2aa9a6SDana Myers  * PARAMETERS:  None
59aa2aa9a6SDana Myers  *
60aa2aa9a6SDana Myers  * RETURN:      Status
61aa2aa9a6SDana Myers  *
62aa2aa9a6SDana Myers  * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
63aa2aa9a6SDana Myers  *              support reset register in PCI config space, this must be
64aa2aa9a6SDana Myers  *              handled separately.
65aa2aa9a6SDana Myers  *
66aa2aa9a6SDana Myers  ******************************************************************************/
67aa2aa9a6SDana Myers 
68aa2aa9a6SDana Myers ACPI_STATUS
AcpiReset(void)69aa2aa9a6SDana Myers AcpiReset (
70aa2aa9a6SDana Myers     void)
71aa2aa9a6SDana Myers {
72aa2aa9a6SDana Myers     ACPI_GENERIC_ADDRESS    *ResetReg;
73aa2aa9a6SDana Myers     ACPI_STATUS             Status;
74aa2aa9a6SDana Myers 
75aa2aa9a6SDana Myers 
76aa2aa9a6SDana Myers     ACPI_FUNCTION_TRACE (AcpiReset);
77aa2aa9a6SDana Myers 
78aa2aa9a6SDana Myers 
79aa2aa9a6SDana Myers     ResetReg = &AcpiGbl_FADT.ResetRegister;
80aa2aa9a6SDana Myers 
81aa2aa9a6SDana Myers     /* Check if the reset register is supported */
82aa2aa9a6SDana Myers 
83aa2aa9a6SDana Myers     if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
84aa2aa9a6SDana Myers         !ResetReg->Address)
85aa2aa9a6SDana Myers     {
86aa2aa9a6SDana Myers         return_ACPI_STATUS (AE_NOT_EXIST);
87aa2aa9a6SDana Myers     }
88aa2aa9a6SDana Myers 
894cf02d40SSaurabh Misra     if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
904cf02d40SSaurabh Misra     {
914cf02d40SSaurabh Misra         /*
924cf02d40SSaurabh Misra          * For I/O space, write directly to the OSL. This bypasses the port
934cf02d40SSaurabh Misra          * validation mechanism, which may block a valid write to the reset
944cf02d40SSaurabh Misra          * register.
95*cb565728SJerry Jelinek          *
96*cb565728SJerry Jelinek          * NOTE:
97*cb565728SJerry Jelinek          * The ACPI spec requires the reset register width to be 8, so we
98*cb565728SJerry Jelinek          * hardcode it here and ignore the FADT value. This maintains
99*cb565728SJerry Jelinek          * compatibility with other ACPI implementations that have allowed
100*cb565728SJerry Jelinek          * BIOS code with bad register width values to go unnoticed.
1014cf02d40SSaurabh Misra          */
1024cf02d40SSaurabh Misra         Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address,
103*cb565728SJerry Jelinek             AcpiGbl_FADT.ResetValue, ACPI_RESET_REGISTER_WIDTH);
1044cf02d40SSaurabh Misra     }
1054cf02d40SSaurabh Misra     else
1064cf02d40SSaurabh Misra     {
107aa2aa9a6SDana Myers         /* Write the reset value to the reset register */
108aa2aa9a6SDana Myers 
1094cf02d40SSaurabh Misra         Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg);
1104cf02d40SSaurabh Misra     }
1114cf02d40SSaurabh Misra 
112aa2aa9a6SDana Myers     return_ACPI_STATUS (Status);
113aa2aa9a6SDana Myers }
114aa2aa9a6SDana Myers 
ACPI_EXPORT_SYMBOL(AcpiReset)115aa2aa9a6SDana Myers ACPI_EXPORT_SYMBOL (AcpiReset)
116aa2aa9a6SDana Myers 
117aa2aa9a6SDana Myers 
118aa2aa9a6SDana Myers /******************************************************************************
119aa2aa9a6SDana Myers  *
120aa2aa9a6SDana Myers  * FUNCTION:    AcpiRead
121aa2aa9a6SDana Myers  *
122aa2aa9a6SDana Myers  * PARAMETERS:  Value               - Where the value is returned
123aa2aa9a6SDana Myers  *              Reg                 - GAS register structure
124aa2aa9a6SDana Myers  *
125aa2aa9a6SDana Myers  * RETURN:      Status
126aa2aa9a6SDana Myers  *
127aa2aa9a6SDana Myers  * DESCRIPTION: Read from either memory or IO space.
128aa2aa9a6SDana Myers  *
12957190917SDana Myers  * LIMITATIONS: <These limitations also apply to AcpiWrite>
13057190917SDana Myers  *      BitWidth must be exactly 8, 16, 32, or 64.
13157190917SDana Myers  *      SpaceID must be SystemMemory or SystemIO.
13257190917SDana Myers  *      BitOffset and AccessWidth are currently ignored, as there has
13357190917SDana Myers  *          not been a need to implement these.
13457190917SDana Myers  *
135aa2aa9a6SDana Myers  ******************************************************************************/
136aa2aa9a6SDana Myers 
137aa2aa9a6SDana Myers ACPI_STATUS
138aa2aa9a6SDana Myers AcpiRead (
13957190917SDana Myers     UINT64                  *ReturnValue,
140aa2aa9a6SDana Myers     ACPI_GENERIC_ADDRESS    *Reg)
141aa2aa9a6SDana Myers {
142*cb565728SJerry Jelinek     UINT32                  ValueLo;
143*cb565728SJerry Jelinek     UINT32                  ValueHi;
144aa2aa9a6SDana Myers     UINT32                  Width;
145aa2aa9a6SDana Myers     UINT64                  Address;
146aa2aa9a6SDana Myers     ACPI_STATUS             Status;
147aa2aa9a6SDana Myers 
148aa2aa9a6SDana Myers 
149aa2aa9a6SDana Myers     ACPI_FUNCTION_NAME (AcpiRead);
150aa2aa9a6SDana Myers 
151aa2aa9a6SDana Myers 
15257190917SDana Myers     if (!ReturnValue)
153aa2aa9a6SDana Myers     {
154aa2aa9a6SDana Myers         return (AE_BAD_PARAMETER);
155aa2aa9a6SDana Myers     }
156aa2aa9a6SDana Myers 
15757190917SDana Myers     /* Validate contents of the GAS register. Allow 64-bit transfers */
158aa2aa9a6SDana Myers 
15957190917SDana Myers     Status = AcpiHwValidateRegister (Reg, 64, &Address);
16057190917SDana Myers     if (ACPI_FAILURE (Status))
161aa2aa9a6SDana Myers     {
16257190917SDana Myers         return (Status);
163aa2aa9a6SDana Myers     }
164aa2aa9a6SDana Myers 
165*cb565728SJerry Jelinek     /*
166*cb565728SJerry Jelinek      * Two address spaces supported: Memory or I/O. PCI_Config is
167*cb565728SJerry Jelinek      * not supported here because the GAS structure is insufficient
168*cb565728SJerry Jelinek      */
169*cb565728SJerry Jelinek     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
170*cb565728SJerry Jelinek     {
171*cb565728SJerry Jelinek         Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
172*cb565728SJerry Jelinek             Address, ReturnValue, Reg->BitWidth);
173*cb565728SJerry Jelinek         if (ACPI_FAILURE (Status))
174*cb565728SJerry Jelinek         {
175*cb565728SJerry Jelinek             return (Status);
176*cb565728SJerry Jelinek         }
177*cb565728SJerry Jelinek     }
178*cb565728SJerry Jelinek     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
179*cb565728SJerry Jelinek     {
180*cb565728SJerry Jelinek         ValueLo = 0;
181*cb565728SJerry Jelinek         ValueHi = 0;
182*cb565728SJerry Jelinek 
183aa2aa9a6SDana Myers         Width = Reg->BitWidth;
18457190917SDana Myers         if (Width == 64)
185aa2aa9a6SDana Myers         {
18657190917SDana Myers             Width = 32; /* Break into two 32-bit transfers */
187aa2aa9a6SDana Myers         }
188aa2aa9a6SDana Myers 
18957190917SDana Myers         Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
190*cb565728SJerry Jelinek             Address, &ValueLo, Width);
19157190917SDana Myers         if (ACPI_FAILURE (Status))
19257190917SDana Myers         {
19357190917SDana Myers             return (Status);
19457190917SDana Myers         }
195aa2aa9a6SDana Myers 
19657190917SDana Myers         if (Reg->BitWidth == 64)
19757190917SDana Myers         {
19857190917SDana Myers             /* Read the top 32 bits */
199aa2aa9a6SDana Myers 
20057190917SDana Myers             Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
201*cb565728SJerry Jelinek                 (Address + 4), &ValueHi, 32);
20257190917SDana Myers             if (ACPI_FAILURE (Status))
20357190917SDana Myers             {
20457190917SDana Myers                 return (Status);
20557190917SDana Myers             }
20657190917SDana Myers         }
207*cb565728SJerry Jelinek 
208*cb565728SJerry Jelinek         /* Set the return value only if status is AE_OK */
209*cb565728SJerry Jelinek 
210*cb565728SJerry Jelinek         *ReturnValue = (ValueLo | ((UINT64) ValueHi << 32));
211aa2aa9a6SDana Myers     }
212aa2aa9a6SDana Myers 
213aa2aa9a6SDana Myers     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
21457190917SDana Myers         "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
21557190917SDana Myers         ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth,
21657190917SDana Myers         ACPI_FORMAT_UINT64 (Address),
217aa2aa9a6SDana Myers         AcpiUtGetRegionName (Reg->SpaceId)));
218aa2aa9a6SDana Myers 
219*cb565728SJerry Jelinek     return (AE_OK);
220aa2aa9a6SDana Myers }
221aa2aa9a6SDana Myers 
ACPI_EXPORT_SYMBOL(AcpiRead)222aa2aa9a6SDana Myers ACPI_EXPORT_SYMBOL (AcpiRead)
223aa2aa9a6SDana Myers 
224aa2aa9a6SDana Myers 
225aa2aa9a6SDana Myers /******************************************************************************
226aa2aa9a6SDana Myers  *
227aa2aa9a6SDana Myers  * FUNCTION:    AcpiWrite
228aa2aa9a6SDana Myers  *
22957190917SDana Myers  * PARAMETERS:  Value               - Value to be written
230aa2aa9a6SDana Myers  *              Reg                 - GAS register structure
231aa2aa9a6SDana Myers  *
232aa2aa9a6SDana Myers  * RETURN:      Status
233aa2aa9a6SDana Myers  *
234aa2aa9a6SDana Myers  * DESCRIPTION: Write to either memory or IO space.
235aa2aa9a6SDana Myers  *
236aa2aa9a6SDana Myers  ******************************************************************************/
237aa2aa9a6SDana Myers 
238aa2aa9a6SDana Myers ACPI_STATUS
239aa2aa9a6SDana Myers AcpiWrite (
24057190917SDana Myers     UINT64                  Value,
241aa2aa9a6SDana Myers     ACPI_GENERIC_ADDRESS    *Reg)
242aa2aa9a6SDana Myers {
243aa2aa9a6SDana Myers     UINT32                  Width;
244aa2aa9a6SDana Myers     UINT64                  Address;
245aa2aa9a6SDana Myers     ACPI_STATUS             Status;
246aa2aa9a6SDana Myers 
247aa2aa9a6SDana Myers 
248aa2aa9a6SDana Myers     ACPI_FUNCTION_NAME (AcpiWrite);
249aa2aa9a6SDana Myers 
250aa2aa9a6SDana Myers 
25157190917SDana Myers     /* Validate contents of the GAS register. Allow 64-bit transfers */
25257190917SDana Myers 
25357190917SDana Myers     Status = AcpiHwValidateRegister (Reg, 64, &Address);
25457190917SDana Myers     if (ACPI_FAILURE (Status))
255aa2aa9a6SDana Myers     {
25657190917SDana Myers         return (Status);
257aa2aa9a6SDana Myers     }
258aa2aa9a6SDana Myers 
259aa2aa9a6SDana Myers     /*
26057190917SDana Myers      * Two address spaces supported: Memory or IO. PCI_Config is
26157190917SDana Myers      * not supported here because the GAS structure is insufficient
262aa2aa9a6SDana Myers      */
26357190917SDana Myers     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
264aa2aa9a6SDana Myers     {
26557190917SDana Myers         Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
266*cb565728SJerry Jelinek             Address, Value, Reg->BitWidth);
26757190917SDana Myers         if (ACPI_FAILURE (Status))
26857190917SDana Myers         {
26957190917SDana Myers             return (Status);
27057190917SDana Myers         }
27157190917SDana Myers     }
27257190917SDana Myers     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
27357190917SDana Myers     {
274*cb565728SJerry Jelinek         Width = Reg->BitWidth;
275*cb565728SJerry Jelinek         if (Width == 64)
276*cb565728SJerry Jelinek         {
277*cb565728SJerry Jelinek             Width = 32; /* Break into two 32-bit transfers */
278*cb565728SJerry Jelinek         }
279*cb565728SJerry Jelinek 
28057190917SDana Myers         Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
28157190917SDana Myers             Address, ACPI_LODWORD (Value), Width);
28257190917SDana Myers         if (ACPI_FAILURE (Status))
28357190917SDana Myers         {
28457190917SDana Myers             return (Status);
28557190917SDana Myers         }
286aa2aa9a6SDana Myers 
28757190917SDana Myers         if (Reg->BitWidth == 64)
28857190917SDana Myers         {
28957190917SDana Myers             Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
29057190917SDana Myers                 (Address + 4), ACPI_HIDWORD (Value), 32);
29157190917SDana Myers             if (ACPI_FAILURE (Status))
29257190917SDana Myers             {
29357190917SDana Myers                 return (Status);
29457190917SDana Myers             }
29557190917SDana Myers         }
296aa2aa9a6SDana Myers     }
297aa2aa9a6SDana Myers 
298aa2aa9a6SDana Myers     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
29957190917SDana Myers         "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
30057190917SDana Myers         ACPI_FORMAT_UINT64 (Value), Reg->BitWidth,
30157190917SDana Myers         ACPI_FORMAT_UINT64 (Address),
302aa2aa9a6SDana Myers         AcpiUtGetRegionName (Reg->SpaceId)));
303aa2aa9a6SDana Myers 
304aa2aa9a6SDana Myers     return (Status);
305aa2aa9a6SDana Myers }
306aa2aa9a6SDana Myers 
ACPI_EXPORT_SYMBOL(AcpiWrite)307aa2aa9a6SDana Myers ACPI_EXPORT_SYMBOL (AcpiWrite)
308aa2aa9a6SDana Myers 
309aa2aa9a6SDana Myers 
310*cb565728SJerry Jelinek #if (!ACPI_REDUCED_HARDWARE)
311aa2aa9a6SDana Myers /*******************************************************************************
312aa2aa9a6SDana Myers  *
313aa2aa9a6SDana Myers  * FUNCTION:    AcpiReadBitRegister
314aa2aa9a6SDana Myers  *
315aa2aa9a6SDana Myers  * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
316aa2aa9a6SDana Myers  *              ReturnValue     - Value that was read from the register,
317aa2aa9a6SDana Myers  *                                normalized to bit position zero.
318aa2aa9a6SDana Myers  *
319aa2aa9a6SDana Myers  * RETURN:      Status and the value read from the specified Register. Value
320aa2aa9a6SDana Myers  *              returned is normalized to bit0 (is shifted all the way right)
321aa2aa9a6SDana Myers  *
322aa2aa9a6SDana Myers  * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
323aa2aa9a6SDana Myers  *
324aa2aa9a6SDana Myers  * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
325aa2aa9a6SDana Myers  *              PM2 Control.
326aa2aa9a6SDana Myers  *
327aa2aa9a6SDana Myers  * Note: The hardware lock is not required when reading the ACPI bit registers
328aa2aa9a6SDana Myers  *       since almost all of them are single bit and it does not matter that
329aa2aa9a6SDana Myers  *       the parent hardware register can be split across two physical
330aa2aa9a6SDana Myers  *       registers. The only multi-bit field is SLP_TYP in the PM1 control
331aa2aa9a6SDana Myers  *       register, but this field does not cross an 8-bit boundary (nor does
332aa2aa9a6SDana Myers  *       it make much sense to actually read this field.)
333aa2aa9a6SDana Myers  *
334aa2aa9a6SDana Myers  ******************************************************************************/
335aa2aa9a6SDana Myers 
336aa2aa9a6SDana Myers ACPI_STATUS
337aa2aa9a6SDana Myers AcpiReadBitRegister (
338aa2aa9a6SDana Myers     UINT32                  RegisterId,
339aa2aa9a6SDana Myers     UINT32                  *ReturnValue)
340aa2aa9a6SDana Myers {
341aa2aa9a6SDana Myers     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
342aa2aa9a6SDana Myers     UINT32                  RegisterValue;
343aa2aa9a6SDana Myers     UINT32                  Value;
344aa2aa9a6SDana Myers     ACPI_STATUS             Status;
345aa2aa9a6SDana Myers 
346aa2aa9a6SDana Myers 
347aa2aa9a6SDana Myers     ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId);
348aa2aa9a6SDana Myers 
349aa2aa9a6SDana Myers 
350aa2aa9a6SDana Myers     /* Get the info structure corresponding to the requested ACPI Register */
351aa2aa9a6SDana Myers 
352aa2aa9a6SDana Myers     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
353aa2aa9a6SDana Myers     if (!BitRegInfo)
354aa2aa9a6SDana Myers     {
355aa2aa9a6SDana Myers         return_ACPI_STATUS (AE_BAD_PARAMETER);
356aa2aa9a6SDana Myers     }
357aa2aa9a6SDana Myers 
358aa2aa9a6SDana Myers     /* Read the entire parent register */
359aa2aa9a6SDana Myers 
360aa2aa9a6SDana Myers     Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
361aa2aa9a6SDana Myers         &RegisterValue);
362aa2aa9a6SDana Myers     if (ACPI_FAILURE (Status))
363aa2aa9a6SDana Myers     {
364aa2aa9a6SDana Myers         return_ACPI_STATUS (Status);
365aa2aa9a6SDana Myers     }
366aa2aa9a6SDana Myers 
367aa2aa9a6SDana Myers     /* Normalize the value that was read, mask off other bits */
368aa2aa9a6SDana Myers 
369aa2aa9a6SDana Myers     Value = ((RegisterValue & BitRegInfo->AccessBitMask)
370aa2aa9a6SDana Myers         >> BitRegInfo->BitPosition);
371aa2aa9a6SDana Myers 
372aa2aa9a6SDana Myers     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
373aa2aa9a6SDana Myers         "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
374aa2aa9a6SDana Myers         RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value));
375aa2aa9a6SDana Myers 
376aa2aa9a6SDana Myers     *ReturnValue = Value;
377aa2aa9a6SDana Myers     return_ACPI_STATUS (AE_OK);
378aa2aa9a6SDana Myers }
379aa2aa9a6SDana Myers 
ACPI_EXPORT_SYMBOL(AcpiReadBitRegister)380aa2aa9a6SDana Myers ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
381aa2aa9a6SDana Myers 
382aa2aa9a6SDana Myers 
383aa2aa9a6SDana Myers /*******************************************************************************
384aa2aa9a6SDana Myers  *
385aa2aa9a6SDana Myers  * FUNCTION:    AcpiWriteBitRegister
386aa2aa9a6SDana Myers  *
387aa2aa9a6SDana Myers  * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
388aa2aa9a6SDana Myers  *              Value           - Value to write to the register, in bit
389*cb565728SJerry Jelinek  *                                position zero. The bit is automatically
390aa2aa9a6SDana Myers  *                                shifted to the correct position.
391aa2aa9a6SDana Myers  *
392aa2aa9a6SDana Myers  * RETURN:      Status
393aa2aa9a6SDana Myers  *
394aa2aa9a6SDana Myers  * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
395aa2aa9a6SDana Myers  *              since most operations require a read/modify/write sequence.
396aa2aa9a6SDana Myers  *
397aa2aa9a6SDana Myers  * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
398aa2aa9a6SDana Myers  *              PM2 Control.
399aa2aa9a6SDana Myers  *
400aa2aa9a6SDana Myers  * Note that at this level, the fact that there may be actually two
401aa2aa9a6SDana Myers  * hardware registers (A and B - and B may not exist) is abstracted.
402aa2aa9a6SDana Myers  *
403aa2aa9a6SDana Myers  ******************************************************************************/
404aa2aa9a6SDana Myers 
405aa2aa9a6SDana Myers ACPI_STATUS
406aa2aa9a6SDana Myers AcpiWriteBitRegister (
407aa2aa9a6SDana Myers     UINT32                  RegisterId,
408aa2aa9a6SDana Myers     UINT32                  Value)
409aa2aa9a6SDana Myers {
410aa2aa9a6SDana Myers     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
411aa2aa9a6SDana Myers     ACPI_CPU_FLAGS          LockFlags;
412aa2aa9a6SDana Myers     UINT32                  RegisterValue;
413aa2aa9a6SDana Myers     ACPI_STATUS             Status = AE_OK;
414aa2aa9a6SDana Myers 
415aa2aa9a6SDana Myers 
416aa2aa9a6SDana Myers     ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId);
417aa2aa9a6SDana Myers 
418aa2aa9a6SDana Myers 
419aa2aa9a6SDana Myers     /* Get the info structure corresponding to the requested ACPI Register */
420aa2aa9a6SDana Myers 
421aa2aa9a6SDana Myers     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
422aa2aa9a6SDana Myers     if (!BitRegInfo)
423aa2aa9a6SDana Myers     {
424aa2aa9a6SDana Myers         return_ACPI_STATUS (AE_BAD_PARAMETER);
425aa2aa9a6SDana Myers     }
426aa2aa9a6SDana Myers 
427aa2aa9a6SDana Myers     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
428aa2aa9a6SDana Myers 
429aa2aa9a6SDana Myers     /*
430aa2aa9a6SDana Myers      * At this point, we know that the parent register is one of the
431aa2aa9a6SDana Myers      * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
432aa2aa9a6SDana Myers      */
433aa2aa9a6SDana Myers     if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS)
434aa2aa9a6SDana Myers     {
435aa2aa9a6SDana Myers         /*
436aa2aa9a6SDana Myers          * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
437aa2aa9a6SDana Myers          *
438aa2aa9a6SDana Myers          * Perform a register read to preserve the bits that we are not
439aa2aa9a6SDana Myers          * interested in
440aa2aa9a6SDana Myers          */
441aa2aa9a6SDana Myers         Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
442aa2aa9a6SDana Myers             &RegisterValue);
443aa2aa9a6SDana Myers         if (ACPI_FAILURE (Status))
444aa2aa9a6SDana Myers         {
445aa2aa9a6SDana Myers             goto UnlockAndExit;
446aa2aa9a6SDana Myers         }
447aa2aa9a6SDana Myers 
448aa2aa9a6SDana Myers         /*
449aa2aa9a6SDana Myers          * Insert the input bit into the value that was just read
450aa2aa9a6SDana Myers          * and write the register
451aa2aa9a6SDana Myers          */
452aa2aa9a6SDana Myers         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
453aa2aa9a6SDana Myers             BitRegInfo->AccessBitMask, Value);
454aa2aa9a6SDana Myers 
455aa2aa9a6SDana Myers         Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister,
456aa2aa9a6SDana Myers             RegisterValue);
457aa2aa9a6SDana Myers     }
458aa2aa9a6SDana Myers     else
459aa2aa9a6SDana Myers     {
460aa2aa9a6SDana Myers         /*
461aa2aa9a6SDana Myers          * 2) Case for PM1 Status
462aa2aa9a6SDana Myers          *
463aa2aa9a6SDana Myers          * The Status register is different from the rest. Clear an event
464aa2aa9a6SDana Myers          * by writing 1, writing 0 has no effect. So, the only relevant
465aa2aa9a6SDana Myers          * information is the single bit we're interested in, all others
466aa2aa9a6SDana Myers          * should be written as 0 so they will be left unchanged.
467aa2aa9a6SDana Myers          */
468aa2aa9a6SDana Myers         RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value,
469aa2aa9a6SDana Myers             BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
470aa2aa9a6SDana Myers 
471aa2aa9a6SDana Myers         /* No need to write the register if value is all zeros */
472aa2aa9a6SDana Myers 
473aa2aa9a6SDana Myers         if (RegisterValue)
474aa2aa9a6SDana Myers         {
475aa2aa9a6SDana Myers             Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
476aa2aa9a6SDana Myers                 RegisterValue);
477aa2aa9a6SDana Myers         }
478aa2aa9a6SDana Myers     }
479aa2aa9a6SDana Myers 
480aa2aa9a6SDana Myers     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
481aa2aa9a6SDana Myers         "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
482aa2aa9a6SDana Myers         RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue));
483aa2aa9a6SDana Myers 
484aa2aa9a6SDana Myers 
485aa2aa9a6SDana Myers UnlockAndExit:
486aa2aa9a6SDana Myers 
487aa2aa9a6SDana Myers     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
488aa2aa9a6SDana Myers     return_ACPI_STATUS (Status);
489aa2aa9a6SDana Myers }
490aa2aa9a6SDana Myers 
ACPI_EXPORT_SYMBOL(AcpiWriteBitRegister)491aa2aa9a6SDana Myers ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
492aa2aa9a6SDana Myers 
493*cb565728SJerry Jelinek #endif /* !ACPI_REDUCED_HARDWARE */
494*cb565728SJerry Jelinek 
495aa2aa9a6SDana Myers 
496aa2aa9a6SDana Myers /*******************************************************************************
497aa2aa9a6SDana Myers  *
498aa2aa9a6SDana Myers  * FUNCTION:    AcpiGetSleepTypeData
499aa2aa9a6SDana Myers  *
500aa2aa9a6SDana Myers  * PARAMETERS:  SleepState          - Numeric sleep state
501aa2aa9a6SDana Myers  *              *SleepTypeA         - Where SLP_TYPa is returned
502aa2aa9a6SDana Myers  *              *SleepTypeB         - Where SLP_TYPb is returned
503aa2aa9a6SDana Myers  *
504*cb565728SJerry Jelinek  * RETURN:      Status
505aa2aa9a6SDana Myers  *
506*cb565728SJerry Jelinek  * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested
507*cb565728SJerry Jelinek  *              sleep state via the appropriate \_Sx object.
508*cb565728SJerry Jelinek  *
509*cb565728SJerry Jelinek  *  The sleep state package returned from the corresponding \_Sx_ object
510*cb565728SJerry Jelinek  *  must contain at least one integer.
511*cb565728SJerry Jelinek  *
512*cb565728SJerry Jelinek  *  March 2005:
513*cb565728SJerry Jelinek  *  Added support for a package that contains two integers. This
514*cb565728SJerry Jelinek  *  goes against the ACPI specification which defines this object as a
515*cb565728SJerry Jelinek  *  package with one encoded DWORD integer. However, existing practice
516*cb565728SJerry Jelinek  *  by many BIOS vendors is to return a package with 2 or more integer
517*cb565728SJerry Jelinek  *  elements, at least one per sleep type (A/B).
518*cb565728SJerry Jelinek  *
519*cb565728SJerry Jelinek  *  January 2013:
520*cb565728SJerry Jelinek  *  Therefore, we must be prepared to accept a package with either a
521*cb565728SJerry Jelinek  *  single integer or multiple integers.
522*cb565728SJerry Jelinek  *
523*cb565728SJerry Jelinek  *  The single integer DWORD format is as follows:
524*cb565728SJerry Jelinek  *      BYTE 0 - Value for the PM1A SLP_TYP register
525*cb565728SJerry Jelinek  *      BYTE 1 - Value for the PM1B SLP_TYP register
526*cb565728SJerry Jelinek  *      BYTE 2-3 - Reserved
527*cb565728SJerry Jelinek  *
528*cb565728SJerry Jelinek  *  The dual integer format is as follows:
529*cb565728SJerry Jelinek  *      Integer 0 - Value for the PM1A SLP_TYP register
530*cb565728SJerry Jelinek  *      Integer 1 - Value for the PM1A SLP_TYP register
531aa2aa9a6SDana Myers  *
532aa2aa9a6SDana Myers  ******************************************************************************/
533aa2aa9a6SDana Myers 
534aa2aa9a6SDana Myers ACPI_STATUS
535aa2aa9a6SDana Myers AcpiGetSleepTypeData (
536aa2aa9a6SDana Myers     UINT8                   SleepState,
537aa2aa9a6SDana Myers     UINT8                   *SleepTypeA,
538aa2aa9a6SDana Myers     UINT8                   *SleepTypeB)
539aa2aa9a6SDana Myers {
540*cb565728SJerry Jelinek     ACPI_STATUS             Status;
541aa2aa9a6SDana Myers     ACPI_EVALUATE_INFO      *Info;
542*cb565728SJerry Jelinek     ACPI_OPERAND_OBJECT     **Elements;
543aa2aa9a6SDana Myers 
544aa2aa9a6SDana Myers 
545aa2aa9a6SDana Myers     ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
546aa2aa9a6SDana Myers 
547aa2aa9a6SDana Myers 
548aa2aa9a6SDana Myers     /* Validate parameters */
549aa2aa9a6SDana Myers 
550aa2aa9a6SDana Myers     if ((SleepState > ACPI_S_STATES_MAX) ||
551*cb565728SJerry Jelinek         !SleepTypeA || !SleepTypeB)
552aa2aa9a6SDana Myers     {
553aa2aa9a6SDana Myers         return_ACPI_STATUS (AE_BAD_PARAMETER);
554aa2aa9a6SDana Myers     }
555aa2aa9a6SDana Myers 
556aa2aa9a6SDana Myers     /* Allocate the evaluation information block */
557aa2aa9a6SDana Myers 
558aa2aa9a6SDana Myers     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
559aa2aa9a6SDana Myers     if (!Info)
560aa2aa9a6SDana Myers     {
561aa2aa9a6SDana Myers         return_ACPI_STATUS (AE_NO_MEMORY);
562aa2aa9a6SDana Myers     }
563aa2aa9a6SDana Myers 
564*cb565728SJerry Jelinek     /*
565*cb565728SJerry Jelinek      * Evaluate the \_Sx namespace object containing the register values
566*cb565728SJerry Jelinek      * for this state
567*cb565728SJerry Jelinek      */
568*cb565728SJerry Jelinek     Info->RelativePathname = AcpiGbl_SleepStateNames[SleepState];
569aa2aa9a6SDana Myers 
570aa2aa9a6SDana Myers     Status = AcpiNsEvaluate (Info);
571aa2aa9a6SDana Myers     if (ACPI_FAILURE (Status))
572aa2aa9a6SDana Myers     {
573*cb565728SJerry Jelinek         if (Status == AE_NOT_FOUND)
574*cb565728SJerry Jelinek         {
575*cb565728SJerry Jelinek             /* The _Sx states are optional, ignore NOT_FOUND */
576aa2aa9a6SDana Myers 
577*cb565728SJerry Jelinek             goto FinalCleanup;
578*cb565728SJerry Jelinek         }
579*cb565728SJerry Jelinek 
580*cb565728SJerry Jelinek         goto WarningCleanup;
581aa2aa9a6SDana Myers     }
582aa2aa9a6SDana Myers 
583aa2aa9a6SDana Myers     /* Must have a return object */
584aa2aa9a6SDana Myers 
585aa2aa9a6SDana Myers     if (!Info->ReturnObject)
586aa2aa9a6SDana Myers     {
587aa2aa9a6SDana Myers         ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
588*cb565728SJerry Jelinek             Info->RelativePathname));
589*cb565728SJerry Jelinek         Status = AE_AML_NO_RETURN_VALUE;
590*cb565728SJerry Jelinek         goto WarningCleanup;
591aa2aa9a6SDana Myers     }
592aa2aa9a6SDana Myers 
593*cb565728SJerry Jelinek     /* Return object must be of type Package */
594aa2aa9a6SDana Myers 
595*cb565728SJerry Jelinek     if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
596aa2aa9a6SDana Myers     {
597aa2aa9a6SDana Myers         ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
598aa2aa9a6SDana Myers         Status = AE_AML_OPERAND_TYPE;
599*cb565728SJerry Jelinek         goto ReturnValueCleanup;
600aa2aa9a6SDana Myers     }
601aa2aa9a6SDana Myers 
602aa2aa9a6SDana Myers     /*
603*cb565728SJerry Jelinek      * Any warnings about the package length or the object types have
604*cb565728SJerry Jelinek      * already been issued by the predefined name module -- there is no
605*cb565728SJerry Jelinek      * need to repeat them here.
606aa2aa9a6SDana Myers      */
607*cb565728SJerry Jelinek     Elements = Info->ReturnObject->Package.Elements;
608*cb565728SJerry Jelinek     switch (Info->ReturnObject->Package.Count)
609aa2aa9a6SDana Myers     {
610*cb565728SJerry Jelinek     case 0:
611aa2aa9a6SDana Myers 
612*cb565728SJerry Jelinek         Status = AE_AML_PACKAGE_LIMIT;
613*cb565728SJerry Jelinek         break;
614aa2aa9a6SDana Myers 
615*cb565728SJerry Jelinek     case 1:
616*cb565728SJerry Jelinek 
617*cb565728SJerry Jelinek         if (Elements[0]->Common.Type != ACPI_TYPE_INTEGER)
618aa2aa9a6SDana Myers         {
619aa2aa9a6SDana Myers             Status = AE_AML_OPERAND_TYPE;
620*cb565728SJerry Jelinek             break;
621aa2aa9a6SDana Myers         }
622*cb565728SJerry Jelinek 
623*cb565728SJerry Jelinek         /* A valid _Sx_ package with one integer */
624*cb565728SJerry Jelinek 
625*cb565728SJerry Jelinek         *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
626*cb565728SJerry Jelinek         *SleepTypeB = (UINT8) (Elements[0]->Integer.Value >> 8);
627*cb565728SJerry Jelinek         break;
628*cb565728SJerry Jelinek 
629*cb565728SJerry Jelinek     case 2:
630*cb565728SJerry Jelinek     default:
631*cb565728SJerry Jelinek 
632*cb565728SJerry Jelinek         if ((Elements[0]->Common.Type != ACPI_TYPE_INTEGER) ||
633*cb565728SJerry Jelinek             (Elements[1]->Common.Type != ACPI_TYPE_INTEGER))
634aa2aa9a6SDana Myers         {
635*cb565728SJerry Jelinek             Status = AE_AML_OPERAND_TYPE;
636*cb565728SJerry Jelinek             break;
637aa2aa9a6SDana Myers         }
638aa2aa9a6SDana Myers 
639*cb565728SJerry Jelinek         /* A valid _Sx_ package with two integers */
640*cb565728SJerry Jelinek 
641*cb565728SJerry Jelinek         *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
642*cb565728SJerry Jelinek         *SleepTypeB = (UINT8) Elements[1]->Integer.Value;
643*cb565728SJerry Jelinek         break;
644*cb565728SJerry Jelinek     }
645*cb565728SJerry Jelinek 
646*cb565728SJerry Jelinek ReturnValueCleanup:
647*cb565728SJerry Jelinek     AcpiUtRemoveReference (Info->ReturnObject);
648*cb565728SJerry Jelinek 
649*cb565728SJerry Jelinek WarningCleanup:
650aa2aa9a6SDana Myers     if (ACPI_FAILURE (Status))
651aa2aa9a6SDana Myers     {
652aa2aa9a6SDana Myers         ACPI_EXCEPTION ((AE_INFO, Status,
653*cb565728SJerry Jelinek             "While evaluating Sleep State [%s]",
654*cb565728SJerry Jelinek             Info->RelativePathname));
655aa2aa9a6SDana Myers     }
656aa2aa9a6SDana Myers 
657*cb565728SJerry Jelinek FinalCleanup:
658aa2aa9a6SDana Myers     ACPI_FREE (Info);
659aa2aa9a6SDana Myers     return_ACPI_STATUS (Status);
660aa2aa9a6SDana Myers }
661aa2aa9a6SDana Myers 
662aa2aa9a6SDana Myers ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
663