1 /*******************************************************************************
3 * Module Name: hwregs - Read/write access functions for the various ACPI
4 * control and status registers.
6 ******************************************************************************/
9 * Copyright (C) 2000 - 2015, Intel Corp.
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
49 #define _COMPONENT ACPI_HARDWARE
50 ACPI_MODULE_NAME ("hwregs")
53 #if (!ACPI_REDUCED_HARDWARE)
55 /* Local Prototypes */
60 ACPI_GENERIC_ADDRESS
*RegisterA
,
61 ACPI_GENERIC_ADDRESS
*RegisterB
);
66 ACPI_GENERIC_ADDRESS
*RegisterA
,
67 ACPI_GENERIC_ADDRESS
*RegisterB
);
69 #endif /* !ACPI_REDUCED_HARDWARE */
72 /******************************************************************************
74 * FUNCTION: AcpiHwValidateRegister
76 * PARAMETERS: Reg - GAS register structure
77 * MaxBitWidth - Max BitWidth supported (32 or 64)
78 * Address - Pointer to where the gas->address
83 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
84 * pointer, Address, SpaceId, BitWidth, and BitOffset.
86 ******************************************************************************/
89 AcpiHwValidateRegister (
90 ACPI_GENERIC_ADDRESS
*Reg
,
95 /* Must have a valid pointer to a GAS structure */
99 return (AE_BAD_PARAMETER
);
103 * Copy the target address. This handles possible alignment issues.
104 * Address must not be null. A null address also indicates an optional
105 * ACPI register that is not supported, so no error message.
107 ACPI_MOVE_64_TO_64 (Address
, &Reg
->Address
);
110 return (AE_BAD_ADDRESS
);
113 /* Validate the SpaceID */
115 if ((Reg
->SpaceId
!= ACPI_ADR_SPACE_SYSTEM_MEMORY
) &&
116 (Reg
->SpaceId
!= ACPI_ADR_SPACE_SYSTEM_IO
))
118 ACPI_ERROR ((AE_INFO
,
119 "Unsupported address space: 0x%X", Reg
->SpaceId
));
123 /* Validate the BitWidth */
125 if ((Reg
->BitWidth
!= 8) &&
126 (Reg
->BitWidth
!= 16) &&
127 (Reg
->BitWidth
!= 32) &&
128 (Reg
->BitWidth
!= MaxBitWidth
))
130 ACPI_ERROR ((AE_INFO
,
131 "Unsupported register bit width: 0x%X", Reg
->BitWidth
));
135 /* Validate the BitOffset. Just a warning for now. */
137 if (Reg
->BitOffset
!= 0)
139 ACPI_WARNING ((AE_INFO
,
140 "Unsupported register bit offset: 0x%X", Reg
->BitOffset
));
147 /******************************************************************************
149 * FUNCTION: AcpiHwRead
151 * PARAMETERS: Value - Where the value is returned
152 * Reg - GAS register structure
156 * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
157 * version of AcpiRead, used internally since the overhead of
158 * 64-bit values is not needed.
160 * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
161 * BitWidth must be exactly 8, 16, or 32.
162 * SpaceID must be SystemMemory or SystemIO.
163 * BitOffset and AccessWidth are currently ignored, as there has
164 * not been a need to implement these.
166 ******************************************************************************/
171 ACPI_GENERIC_ADDRESS
*Reg
)
178 ACPI_FUNCTION_NAME (HwRead
);
181 /* Validate contents of the GAS register */
183 Status
= AcpiHwValidateRegister (Reg
, 32, &Address
);
184 if (ACPI_FAILURE (Status
))
189 /* Initialize entire 32-bit return value to zero */
194 * Two address spaces supported: Memory or IO. PCI_Config is
195 * not supported here because the GAS structure is insufficient
197 if (Reg
->SpaceId
== ACPI_ADR_SPACE_SYSTEM_MEMORY
)
199 Status
= AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS
)
200 Address
, &Value64
, Reg
->BitWidth
);
202 *Value
= (UINT32
) Value64
;
204 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
206 Status
= AcpiHwReadPort ((ACPI_IO_ADDRESS
)
207 Address
, Value
, Reg
->BitWidth
);
210 ACPI_DEBUG_PRINT ((ACPI_DB_IO
,
211 "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
212 *Value
, Reg
->BitWidth
, ACPI_FORMAT_UINT64 (Address
),
213 AcpiUtGetRegionName (Reg
->SpaceId
)));
219 /******************************************************************************
221 * FUNCTION: AcpiHwWrite
223 * PARAMETERS: Value - Value to be written
224 * Reg - GAS register structure
228 * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max
229 * version of AcpiWrite, used internally since the overhead of
230 * 64-bit values is not needed.
232 ******************************************************************************/
237 ACPI_GENERIC_ADDRESS
*Reg
)
243 ACPI_FUNCTION_NAME (HwWrite
);
246 /* Validate contents of the GAS register */
248 Status
= AcpiHwValidateRegister (Reg
, 32, &Address
);
249 if (ACPI_FAILURE (Status
))
255 * Two address spaces supported: Memory or IO. PCI_Config is
256 * not supported here because the GAS structure is insufficient
258 if (Reg
->SpaceId
== ACPI_ADR_SPACE_SYSTEM_MEMORY
)
260 Status
= AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS
)
261 Address
, (UINT64
) Value
, Reg
->BitWidth
);
263 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
265 Status
= AcpiHwWritePort ((ACPI_IO_ADDRESS
)
266 Address
, Value
, Reg
->BitWidth
);
269 ACPI_DEBUG_PRINT ((ACPI_DB_IO
,
270 "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
271 Value
, Reg
->BitWidth
, ACPI_FORMAT_UINT64 (Address
),
272 AcpiUtGetRegionName (Reg
->SpaceId
)));
278 #if (!ACPI_REDUCED_HARDWARE)
279 /*******************************************************************************
281 * FUNCTION: AcpiHwClearAcpiStatus
287 * DESCRIPTION: Clears all fixed and general purpose status bits
289 ******************************************************************************/
292 AcpiHwClearAcpiStatus (
296 ACPI_CPU_FLAGS LockFlags
= 0;
299 ACPI_FUNCTION_TRACE (HwClearAcpiStatus
);
302 ACPI_DEBUG_PRINT ((ACPI_DB_IO
, "About to write %04X to %8.8X%8.8X\n",
303 ACPI_BITMASK_ALL_FIXED_STATUS
,
304 ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus
.Address
)));
306 LockFlags
= AcpiOsAcquireLock (AcpiGbl_HardwareLock
);
308 /* Clear the fixed events in PM1 A/B */
310 Status
= AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS
,
311 ACPI_BITMASK_ALL_FIXED_STATUS
);
313 AcpiOsReleaseLock (AcpiGbl_HardwareLock
, LockFlags
);
315 if (ACPI_FAILURE (Status
))
320 /* Clear the GPE Bits in all GPE registers in all GPE blocks */
322 Status
= AcpiEvWalkGpeList (AcpiHwClearGpeBlock
, NULL
);
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
);
434 case ACPI_REGISTER_PM1_ENABLE
: /* PM1 A/B: 16-bit access each */
436 Status
= AcpiHwReadMultiple (&Value
,
437 &AcpiGbl_XPm1aEnable
,
438 &AcpiGbl_XPm1bEnable
);
441 case ACPI_REGISTER_PM1_CONTROL
: /* PM1 A/B: 16-bit access each */
443 Status
= AcpiHwReadMultiple (&Value
,
444 &AcpiGbl_FADT
.XPm1aControlBlock
,
445 &AcpiGbl_FADT
.XPm1bControlBlock
);
448 * Zero the write-only bits. From the ACPI specification, "Hardware
449 * Write-Only Bits": "Upon reads to registers with write-only bits,
450 * software masks out all write-only bits."
452 Value
&= ~ACPI_PM1_CONTROL_WRITEONLY_BITS
;
455 case ACPI_REGISTER_PM2_CONTROL
: /* 8-bit access */
457 Status
= AcpiHwRead (&Value
, &AcpiGbl_FADT
.XPm2ControlBlock
);
460 case ACPI_REGISTER_PM_TIMER
: /* 32-bit access */
462 Status
= AcpiHwRead (&Value
, &AcpiGbl_FADT
.XPmTimerBlock
);
465 case ACPI_REGISTER_SMI_COMMAND_BLOCK
: /* 8-bit access */
467 Status
= AcpiHwReadPort (AcpiGbl_FADT
.SmiCommand
, &Value
, 8);
472 ACPI_ERROR ((AE_INFO
, "Unknown Register ID: 0x%X",
474 Status
= AE_BAD_PARAMETER
;
478 if (ACPI_SUCCESS (Status
))
480 *ReturnValue
= Value
;
483 return_ACPI_STATUS (Status
);
487 /******************************************************************************
489 * FUNCTION: AcpiHwRegisterWrite
491 * PARAMETERS: RegisterId - ACPI Register ID
492 * Value - The value to write
496 * DESCRIPTION: Write to the specified ACPI register
498 * NOTE: In accordance with the ACPI specification, this function automatically
499 * preserves the value of the following bits, meaning that these bits cannot be
500 * changed via this interface:
502 * PM1_CONTROL[0] = SCI_EN
507 * 1) Hardware Ignored Bits: When software writes to a register with ignored
508 * bit fields, it preserves the ignored bit fields
509 * 2) SCI_EN: OSPM always preserves this bit position
511 ******************************************************************************/
514 AcpiHwRegisterWrite (
522 ACPI_FUNCTION_TRACE (HwRegisterWrite
);
527 case ACPI_REGISTER_PM1_STATUS
: /* PM1 A/B: 16-bit access each */
529 * Handle the "ignored" bit in PM1 Status. According to the ACPI
530 * specification, ignored bits are to be preserved when writing.
531 * Normally, this would mean a read/modify/write sequence. However,
532 * preserving a bit in the status register is different. Writing a
533 * one clears the status, and writing a zero preserves the status.
534 * Therefore, we must always write zero to the ignored bit.
536 * This behavior is clarified in the ACPI 4.0 specification.
538 Value
&= ~ACPI_PM1_STATUS_PRESERVED_BITS
;
540 Status
= AcpiHwWriteMultiple (Value
,
541 &AcpiGbl_XPm1aStatus
,
542 &AcpiGbl_XPm1bStatus
);
545 case ACPI_REGISTER_PM1_ENABLE
: /* PM1 A/B: 16-bit access each */
547 Status
= AcpiHwWriteMultiple (Value
,
548 &AcpiGbl_XPm1aEnable
,
549 &AcpiGbl_XPm1bEnable
);
552 case ACPI_REGISTER_PM1_CONTROL
: /* PM1 A/B: 16-bit access each */
554 * Perform a read first to preserve certain bits (per ACPI spec)
555 * Note: This includes SCI_EN, we never want to change this bit
557 Status
= AcpiHwReadMultiple (&ReadValue
,
558 &AcpiGbl_FADT
.XPm1aControlBlock
,
559 &AcpiGbl_FADT
.XPm1bControlBlock
);
560 if (ACPI_FAILURE (Status
))
565 /* Insert the bits to be preserved */
567 ACPI_INSERT_BITS (Value
, ACPI_PM1_CONTROL_PRESERVED_BITS
, ReadValue
);
569 /* Now we can write the data */
571 Status
= AcpiHwWriteMultiple (Value
,
572 &AcpiGbl_FADT
.XPm1aControlBlock
,
573 &AcpiGbl_FADT
.XPm1bControlBlock
);
576 case ACPI_REGISTER_PM2_CONTROL
: /* 8-bit access */
578 * For control registers, all reserved bits must be preserved,
579 * as per the ACPI spec.
581 Status
= AcpiHwRead (&ReadValue
, &AcpiGbl_FADT
.XPm2ControlBlock
);
582 if (ACPI_FAILURE (Status
))
587 /* Insert the bits to be preserved */
589 ACPI_INSERT_BITS (Value
, ACPI_PM2_CONTROL_PRESERVED_BITS
, ReadValue
);
591 Status
= AcpiHwWrite (Value
, &AcpiGbl_FADT
.XPm2ControlBlock
);
594 case ACPI_REGISTER_PM_TIMER
: /* 32-bit access */
596 Status
= AcpiHwWrite (Value
, &AcpiGbl_FADT
.XPmTimerBlock
);
599 case ACPI_REGISTER_SMI_COMMAND_BLOCK
: /* 8-bit access */
601 /* SMI_CMD is currently always in IO space */
603 Status
= AcpiHwWritePort (AcpiGbl_FADT
.SmiCommand
, Value
, 8);
608 ACPI_ERROR ((AE_INFO
, "Unknown Register ID: 0x%X",
610 Status
= AE_BAD_PARAMETER
;
615 return_ACPI_STATUS (Status
);
619 /******************************************************************************
621 * FUNCTION: AcpiHwReadMultiple
623 * PARAMETERS: Value - Where the register value is returned
624 * RegisterA - First ACPI register (required)
625 * RegisterB - Second ACPI register (optional)
629 * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
631 ******************************************************************************/
636 ACPI_GENERIC_ADDRESS
*RegisterA
,
637 ACPI_GENERIC_ADDRESS
*RegisterB
)
644 /* The first register is always required */
646 Status
= AcpiHwRead (&ValueA
, RegisterA
);
647 if (ACPI_FAILURE (Status
))
652 /* Second register is optional */
654 if (RegisterB
->Address
)
656 Status
= AcpiHwRead (&ValueB
, RegisterB
);
657 if (ACPI_FAILURE (Status
))
664 * OR the two return values together. No shifting or masking is necessary,
665 * because of how the PM1 registers are defined in the ACPI specification:
667 * "Although the bits can be split between the two register blocks (each
668 * register block has a unique pointer within the FADT), the bit positions
669 * are maintained. The register block with unimplemented bits (that is,
670 * those implemented in the other register block) always returns zeros,
671 * and writes have no side effects"
673 *Value
= (ValueA
| ValueB
);
678 /******************************************************************************
680 * FUNCTION: AcpiHwWriteMultiple
682 * PARAMETERS: Value - The value to write
683 * RegisterA - First ACPI register (required)
684 * RegisterB - Second ACPI register (optional)
688 * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
690 ******************************************************************************/
693 AcpiHwWriteMultiple (
695 ACPI_GENERIC_ADDRESS
*RegisterA
,
696 ACPI_GENERIC_ADDRESS
*RegisterB
)
701 /* The first register is always required */
703 Status
= AcpiHwWrite (Value
, RegisterA
);
704 if (ACPI_FAILURE (Status
))
710 * Second register is optional
712 * No bit shifting or clearing is necessary, because of how the PM1
713 * registers are defined in the ACPI specification:
715 * "Although the bits can be split between the two register blocks (each
716 * register block has a unique pointer within the FADT), the bit positions
717 * are maintained. The register block with unimplemented bits (that is,
718 * those implemented in the other register block) always returns zeros,
719 * and writes have no side effects"
721 if (RegisterB
->Address
)
723 Status
= AcpiHwWrite (Value
, RegisterB
);
729 #endif /* !ACPI_REDUCED_HARDWARE */