2 /*******************************************************************************
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 * control and status registers.
7 ******************************************************************************/
10 * Copyright (C) 2000 - 2012, Intel Corp.
11 * All rights reserved.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions, and the following disclaimer,
18 * without modification.
19 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
20 * substantially similar to the "NO WARRANTY" disclaimer below
21 * ("Disclaimer") and any redistribution must be conditioned upon
22 * including a substantially similar Disclaimer requirement for further
23 * binary redistribution.
24 * 3. Neither the names of the above-listed copyright holders nor the names
25 * of any contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
28 * Alternatively, this software may be distributed under the terms of the
29 * GNU General Public License ("GPL") version 2 as published by the Free
30 * Software Foundation.
33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
34 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
35 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
36 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
42 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 * POSSIBILITY OF SUCH DAMAGES.
52 #define _COMPONENT ACPI_HARDWARE
53 ACPI_MODULE_NAME ("hwregs")
56 #if (!ACPI_REDUCED_HARDWARE)
58 /* Local Prototypes */
63 ACPI_GENERIC_ADDRESS *RegisterA,
64 ACPI_GENERIC_ADDRESS *RegisterB);
69 ACPI_GENERIC_ADDRESS *RegisterA,
70 ACPI_GENERIC_ADDRESS *RegisterB);
72 #endif /* !ACPI_REDUCED_HARDWARE */
74 /******************************************************************************
76 * FUNCTION: AcpiHwValidateRegister
78 * PARAMETERS: Reg - GAS register structure
79 * MaxBitWidth - Max BitWidth supported (32 or 64)
80 * Address - Pointer to where the gas->address
85 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
86 * pointer, Address, SpaceId, BitWidth, and BitOffset.
88 ******************************************************************************/
91 AcpiHwValidateRegister (
92 ACPI_GENERIC_ADDRESS *Reg,
97 /* Must have a valid pointer to a GAS structure */
101 return (AE_BAD_PARAMETER);
105 * Copy the target address. This handles possible alignment issues.
106 * Address must not be null. A null address also indicates an optional
107 * ACPI register that is not supported, so no error message.
109 ACPI_MOVE_64_TO_64 (Address, &Reg->Address);
112 return (AE_BAD_ADDRESS);
115 /* Validate the SpaceID */
117 if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
118 (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
120 ACPI_ERROR ((AE_INFO,
121 "Unsupported address space: 0x%X", Reg->SpaceId));
125 /* Validate the BitWidth */
127 if ((Reg->BitWidth != 8) &&
128 (Reg->BitWidth != 16) &&
129 (Reg->BitWidth != 32) &&
130 (Reg->BitWidth != MaxBitWidth))
132 ACPI_ERROR ((AE_INFO,
133 "Unsupported register bit width: 0x%X", Reg->BitWidth));
137 /* Validate the BitOffset. Just a warning for now. */
139 if (Reg->BitOffset != 0)
141 ACPI_WARNING ((AE_INFO,
142 "Unsupported register bit offset: 0x%X", Reg->BitOffset));
149 /******************************************************************************
151 * FUNCTION: AcpiHwRead
153 * PARAMETERS: Value - Where the value is returned
154 * Reg - GAS register structure
158 * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
159 * version of AcpiRead, used internally since the overhead of
160 * 64-bit values is not needed.
162 * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
163 * BitWidth must be exactly 8, 16, or 32.
164 * SpaceID must be SystemMemory or SystemIO.
165 * BitOffset and AccessWidth are currently ignored, as there has
166 * not been a need to implement these.
168 ******************************************************************************/
173 ACPI_GENERIC_ADDRESS *Reg)
180 ACPI_FUNCTION_NAME (HwRead);
183 /* Validate contents of the GAS register */
185 Status = AcpiHwValidateRegister (Reg, 32, &Address);
186 if (ACPI_FAILURE (Status))
191 /* Initialize entire 32-bit return value to zero */
196 * Two address spaces supported: Memory or IO. PCI_Config is
197 * not supported here because the GAS structure is insufficient
199 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
201 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
202 Address, &Value64, Reg->BitWidth);
204 *Value = (UINT32) Value64;
206 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
208 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
209 Address, Value, Reg->BitWidth);
212 ACPI_DEBUG_PRINT ((ACPI_DB_IO,
213 "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
214 *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
215 AcpiUtGetRegionName (Reg->SpaceId)));
221 /******************************************************************************
223 * FUNCTION: AcpiHwWrite
225 * PARAMETERS: Value - Value to be written
226 * Reg - GAS register structure
230 * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max
231 * version of AcpiWrite, used internally since the overhead of
232 * 64-bit values is not needed.
234 ******************************************************************************/
239 ACPI_GENERIC_ADDRESS *Reg)
245 ACPI_FUNCTION_NAME (HwWrite);
248 /* Validate contents of the GAS register */
250 Status = AcpiHwValidateRegister (Reg, 32, &Address);
251 if (ACPI_FAILURE (Status))
257 * Two address spaces supported: Memory or IO. PCI_Config is
258 * not supported here because the GAS structure is insufficient
260 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
262 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
263 Address, (UINT64) Value, Reg->BitWidth);
265 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
267 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
268 Address, Value, Reg->BitWidth);
271 ACPI_DEBUG_PRINT ((ACPI_DB_IO,
272 "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
273 Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
274 AcpiUtGetRegionName (Reg->SpaceId)));
280 #if (!ACPI_REDUCED_HARDWARE)
281 /*******************************************************************************
283 * FUNCTION: AcpiHwClearAcpiStatus
289 * DESCRIPTION: Clears all fixed and general purpose status bits
291 ******************************************************************************/
294 AcpiHwClearAcpiStatus (
298 ACPI_CPU_FLAGS LockFlags = 0;
301 ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
304 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
305 ACPI_BITMASK_ALL_FIXED_STATUS,
306 ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address)));
308 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
310 /* Clear the fixed events in PM1 A/B */
312 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
313 ACPI_BITMASK_ALL_FIXED_STATUS);
314 if (ACPI_FAILURE (Status))
319 /* Clear the GPE Bits in all GPE registers in all GPE blocks */
321 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
324 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
325 return_ACPI_STATUS (Status);
329 /*******************************************************************************
331 * FUNCTION: AcpiHwGetBitRegisterInfo
333 * PARAMETERS: RegisterId - Index of ACPI Register to access
335 * RETURN: The bitmask to be used when accessing the register
337 * DESCRIPTION: Map RegisterId into a register bitmask.
339 ******************************************************************************/
341 ACPI_BIT_REGISTER_INFO *
342 AcpiHwGetBitRegisterInfo (
345 ACPI_FUNCTION_ENTRY ();
348 if (RegisterId > ACPI_BITREG_MAX)
350 ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
354 return (&AcpiGbl_BitRegisterInfo[RegisterId]);
358 /******************************************************************************
360 * FUNCTION: AcpiHwWritePm1Control
362 * PARAMETERS: Pm1aControl - Value to be written to PM1A control
363 * Pm1bControl - Value to be written to PM1B control
367 * DESCRIPTION: Write the PM1 A/B control registers. These registers are
368 * different than than the PM1 A/B status and enable registers
369 * in that different values can be written to the A/B registers.
370 * Most notably, the SLP_TYP bits can be different, as per the
371 * values returned from the _Sx predefined methods.
373 ******************************************************************************/
376 AcpiHwWritePm1Control (
383 ACPI_FUNCTION_TRACE (HwWritePm1Control);
386 Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock);
387 if (ACPI_FAILURE (Status))
389 return_ACPI_STATUS (Status);
392 if (AcpiGbl_FADT.XPm1bControlBlock.Address)
394 Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock);
396 return_ACPI_STATUS (Status);
400 /******************************************************************************
402 * FUNCTION: AcpiHwRegisterRead
404 * PARAMETERS: RegisterId - ACPI Register ID
405 * ReturnValue - Where the register value is returned
407 * RETURN: Status and the value read.
409 * DESCRIPTION: Read from the specified ACPI register
411 ******************************************************************************/
422 ACPI_FUNCTION_TRACE (HwRegisterRead);
427 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
429 Status = AcpiHwReadMultiple (&Value,
430 &AcpiGbl_XPm1aStatus,
431 &AcpiGbl_XPm1bStatus);
435 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
437 Status = AcpiHwReadMultiple (&Value,
438 &AcpiGbl_XPm1aEnable,
439 &AcpiGbl_XPm1bEnable);
443 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
445 Status = AcpiHwReadMultiple (&Value,
446 &AcpiGbl_FADT.XPm1aControlBlock,
447 &AcpiGbl_FADT.XPm1bControlBlock);
450 * Zero the write-only bits. From the ACPI specification, "Hardware
451 * Write-Only Bits": "Upon reads to registers with write-only bits,
452 * software masks out all write-only bits."
454 Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
458 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
460 Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock);
464 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
466 Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPmTimerBlock);
470 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
472 Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
477 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
479 Status = AE_BAD_PARAMETER;
483 if (ACPI_SUCCESS (Status))
485 *ReturnValue = Value;
488 return_ACPI_STATUS (Status);
492 /******************************************************************************
494 * FUNCTION: AcpiHwRegisterWrite
496 * PARAMETERS: RegisterId - ACPI Register ID
497 * Value - The value to write
501 * DESCRIPTION: Write to the specified ACPI register
503 * NOTE: In accordance with the ACPI specification, this function automatically
504 * preserves the value of the following bits, meaning that these bits cannot be
505 * changed via this interface:
507 * PM1_CONTROL[0] = SCI_EN
512 * 1) Hardware Ignored Bits: When software writes to a register with ignored
513 * bit fields, it preserves the ignored bit fields
514 * 2) SCI_EN: OSPM always preserves this bit position
516 ******************************************************************************/
519 AcpiHwRegisterWrite (
527 ACPI_FUNCTION_TRACE (HwRegisterWrite);
532 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
534 * Handle the "ignored" bit in PM1 Status. According to the ACPI
535 * specification, ignored bits are to be preserved when writing.
536 * Normally, this would mean a read/modify/write sequence. However,
537 * preserving a bit in the status register is different. Writing a
538 * one clears the status, and writing a zero preserves the status.
539 * Therefore, we must always write zero to the ignored bit.
541 * This behavior is clarified in the ACPI 4.0 specification.
543 Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
545 Status = AcpiHwWriteMultiple (Value,
546 &AcpiGbl_XPm1aStatus,
547 &AcpiGbl_XPm1bStatus);
551 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
553 Status = AcpiHwWriteMultiple (Value,
554 &AcpiGbl_XPm1aEnable,
555 &AcpiGbl_XPm1bEnable);
559 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
562 * Perform a read first to preserve certain bits (per ACPI spec)
563 * Note: This includes SCI_EN, we never want to change this bit
565 Status = AcpiHwReadMultiple (&ReadValue,
566 &AcpiGbl_FADT.XPm1aControlBlock,
567 &AcpiGbl_FADT.XPm1bControlBlock);
568 if (ACPI_FAILURE (Status))
573 /* Insert the bits to be preserved */
575 ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
577 /* Now we can write the data */
579 Status = AcpiHwWriteMultiple (Value,
580 &AcpiGbl_FADT.XPm1aControlBlock,
581 &AcpiGbl_FADT.XPm1bControlBlock);
585 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
588 * For control registers, all reserved bits must be preserved,
589 * as per the ACPI spec.
591 Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock);
592 if (ACPI_FAILURE (Status))
597 /* Insert the bits to be preserved */
599 ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
601 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
605 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
607 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
611 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
613 /* SMI_CMD is currently always in IO space */
615 Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
620 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
622 Status = AE_BAD_PARAMETER;
627 return_ACPI_STATUS (Status);
631 /******************************************************************************
633 * FUNCTION: AcpiHwReadMultiple
635 * PARAMETERS: Value - Where the register value is returned
636 * RegisterA - First ACPI register (required)
637 * RegisterB - Second ACPI register (optional)
641 * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
643 ******************************************************************************/
648 ACPI_GENERIC_ADDRESS *RegisterA,
649 ACPI_GENERIC_ADDRESS *RegisterB)
656 /* The first register is always required */
658 Status = AcpiHwRead (&ValueA, RegisterA);
659 if (ACPI_FAILURE (Status))
664 /* Second register is optional */
666 if (RegisterB->Address)
668 Status = AcpiHwRead (&ValueB, RegisterB);
669 if (ACPI_FAILURE (Status))
676 * OR the two return values together. No shifting or masking is necessary,
677 * because of how the PM1 registers are defined in the ACPI specification:
679 * "Although the bits can be split between the two register blocks (each
680 * register block has a unique pointer within the FADT), the bit positions
681 * are maintained. The register block with unimplemented bits (that is,
682 * those implemented in the other register block) always returns zeros,
683 * and writes have no side effects"
685 *Value = (ValueA | ValueB);
690 /******************************************************************************
692 * FUNCTION: AcpiHwWriteMultiple
694 * PARAMETERS: Value - The value to write
695 * RegisterA - First ACPI register (required)
696 * RegisterB - Second ACPI register (optional)
700 * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
702 ******************************************************************************/
705 AcpiHwWriteMultiple (
707 ACPI_GENERIC_ADDRESS *RegisterA,
708 ACPI_GENERIC_ADDRESS *RegisterB)
713 /* The first register is always required */
715 Status = AcpiHwWrite (Value, RegisterA);
716 if (ACPI_FAILURE (Status))
722 * Second register is optional
724 * No bit shifting or clearing is necessary, because of how the PM1
725 * registers are defined in the ACPI specification:
727 * "Although the bits can be split between the two register blocks (each
728 * register block has a unique pointer within the FADT), the bit positions
729 * are maintained. The register block with unimplemented bits (that is,
730 * those implemented in the other register block) always returns zeros,
731 * and writes have no side effects"
733 if (RegisterB->Address)
735 Status = AcpiHwWrite (Value, RegisterB);
741 #endif /* !ACPI_REDUCED_HARDWARE */