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