13446Smrj 23446Smrj /******************************************************************************* 33446Smrj * 43446Smrj * Module Name: hwregs - Read/write access functions for the various ACPI 53446Smrj * control and status registers. 63446Smrj * 73446Smrj ******************************************************************************/ 83446Smrj 93446Smrj /****************************************************************************** 103446Smrj * 113446Smrj * 1. Copyright Notice 123446Smrj * 139980SDana.Myers@Sun.COM * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp. 143446Smrj * All rights reserved. 153446Smrj * 163446Smrj * 2. License 173446Smrj * 183446Smrj * 2.1. This is your license from Intel Corp. under its intellectual property 193446Smrj * rights. You may have additional license terms from the party that provided 203446Smrj * you this software, covering your right to use that party's intellectual 213446Smrj * property rights. 223446Smrj * 233446Smrj * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 243446Smrj * copy of the source code appearing in this file ("Covered Code") an 253446Smrj * irrevocable, perpetual, worldwide license under Intel's copyrights in the 263446Smrj * base code distributed originally by Intel ("Original Intel Code") to copy, 273446Smrj * make derivatives, distribute, use and display any portion of the Covered 283446Smrj * Code in any form, with the right to sublicense such rights; and 293446Smrj * 303446Smrj * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 313446Smrj * license (with the right to sublicense), under only those claims of Intel 323446Smrj * patents that are infringed by the Original Intel Code, to make, use, sell, 333446Smrj * offer to sell, and import the Covered Code and derivative works thereof 343446Smrj * solely to the minimum extent necessary to exercise the above copyright 353446Smrj * license, and in no event shall the patent license extend to any additions 363446Smrj * to or modifications of the Original Intel Code. No other license or right 373446Smrj * is granted directly or by implication, estoppel or otherwise; 383446Smrj * 393446Smrj * The above copyright and patent license is granted only if the following 403446Smrj * conditions are met: 413446Smrj * 423446Smrj * 3. Conditions 433446Smrj * 443446Smrj * 3.1. Redistribution of Source with Rights to Further Distribute Source. 453446Smrj * Redistribution of source code of any substantial portion of the Covered 463446Smrj * Code or modification with rights to further distribute source must include 473446Smrj * the above Copyright Notice, the above License, this list of Conditions, 483446Smrj * and the following Disclaimer and Export Compliance provision. In addition, 493446Smrj * Licensee must cause all Covered Code to which Licensee contributes to 503446Smrj * contain a file documenting the changes Licensee made to create that Covered 513446Smrj * Code and the date of any change. Licensee must include in that file the 523446Smrj * documentation of any changes made by any predecessor Licensee. Licensee 533446Smrj * must include a prominent statement that the modification is derived, 543446Smrj * directly or indirectly, from Original Intel Code. 553446Smrj * 563446Smrj * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 573446Smrj * Redistribution of source code of any substantial portion of the Covered 583446Smrj * Code or modification without rights to further distribute source must 593446Smrj * include the following Disclaimer and Export Compliance provision in the 603446Smrj * documentation and/or other materials provided with distribution. In 613446Smrj * addition, Licensee may not authorize further sublicense of source of any 623446Smrj * portion of the Covered Code, and must include terms to the effect that the 633446Smrj * license from Licensee to its licensee is limited to the intellectual 643446Smrj * property embodied in the software Licensee provides to its licensee, and 653446Smrj * not to intellectual property embodied in modifications its licensee may 663446Smrj * make. 673446Smrj * 683446Smrj * 3.3. Redistribution of Executable. Redistribution in executable form of any 693446Smrj * substantial portion of the Covered Code or modification must reproduce the 703446Smrj * above Copyright Notice, and the following Disclaimer and Export Compliance 713446Smrj * provision in the documentation and/or other materials provided with the 723446Smrj * distribution. 733446Smrj * 743446Smrj * 3.4. Intel retains all right, title, and interest in and to the Original 753446Smrj * Intel Code. 763446Smrj * 773446Smrj * 3.5. Neither the name Intel nor any other trademark owned or controlled by 783446Smrj * Intel shall be used in advertising or otherwise to promote the sale, use or 793446Smrj * other dealings in products derived from or relating to the Covered Code 803446Smrj * without prior written authorization from Intel. 813446Smrj * 823446Smrj * 4. Disclaimer and Export Compliance 833446Smrj * 843446Smrj * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 853446Smrj * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 863446Smrj * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 873446Smrj * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 883446Smrj * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 893446Smrj * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 903446Smrj * PARTICULAR PURPOSE. 913446Smrj * 923446Smrj * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 933446Smrj * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 943446Smrj * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 953446Smrj * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 963446Smrj * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 973446Smrj * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 983446Smrj * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 993446Smrj * LIMITED REMEDY. 1003446Smrj * 1013446Smrj * 4.3. Licensee shall not export, either directly or indirectly, any of this 1023446Smrj * software or system incorporating such software without first obtaining any 1033446Smrj * required license or other approval from the U. S. Department of Commerce or 1043446Smrj * any other agency or department of the United States Government. In the 1053446Smrj * event Licensee exports any such software from the United States or 1063446Smrj * re-exports any such software from a foreign destination, Licensee shall 1073446Smrj * ensure that the distribution and export/re-export of the software is in 1083446Smrj * compliance with all laws, regulations, orders, or other restrictions of the 1093446Smrj * U.S. Export Administration Regulations. Licensee agrees that neither it nor 1103446Smrj * any of its subsidiaries will export/re-export any technical data, process, 1113446Smrj * software, or service, directly or indirectly, to any country for which the 1123446Smrj * United States government or any agency thereof requires an export license, 1133446Smrj * other governmental approval, or letter of assurance, without first obtaining 1143446Smrj * such license, approval or letter. 1153446Smrj * 1163446Smrj *****************************************************************************/ 1173446Smrj 1183446Smrj #define __HWREGS_C__ 1193446Smrj 1203446Smrj #include "acpi.h" 1219980SDana.Myers@Sun.COM #include "accommon.h" 1223446Smrj #include "acevents.h" 1233446Smrj 1243446Smrj #define _COMPONENT ACPI_HARDWARE 1253446Smrj ACPI_MODULE_NAME ("hwregs") 1263446Smrj 1273446Smrj 1289980SDana.Myers@Sun.COM /* Local Prototypes */ 1299980SDana.Myers@Sun.COM 1309980SDana.Myers@Sun.COM static ACPI_STATUS 1319980SDana.Myers@Sun.COM AcpiHwReadMultiple ( 1329980SDana.Myers@Sun.COM UINT32 *Value, 1339980SDana.Myers@Sun.COM ACPI_GENERIC_ADDRESS *RegisterA, 1349980SDana.Myers@Sun.COM ACPI_GENERIC_ADDRESS *RegisterB); 1359980SDana.Myers@Sun.COM 1369980SDana.Myers@Sun.COM static ACPI_STATUS 1379980SDana.Myers@Sun.COM AcpiHwWriteMultiple ( 1389980SDana.Myers@Sun.COM UINT32 Value, 1399980SDana.Myers@Sun.COM ACPI_GENERIC_ADDRESS *RegisterA, 1409980SDana.Myers@Sun.COM ACPI_GENERIC_ADDRESS *RegisterB); 1419980SDana.Myers@Sun.COM 1429980SDana.Myers@Sun.COM 143*10457SSaurabh.Mishra@Sun.COM 144*10457SSaurabh.Mishra@Sun.COM /****************************************************************************** 145*10457SSaurabh.Mishra@Sun.COM * 146*10457SSaurabh.Mishra@Sun.COM * FUNCTION: AcpiHwValidateRegister 147*10457SSaurabh.Mishra@Sun.COM * 148*10457SSaurabh.Mishra@Sun.COM * PARAMETERS: Reg - GAS register structure 149*10457SSaurabh.Mishra@Sun.COM * MaxBitWidth - Max BitWidth supported (32 or 64) 150*10457SSaurabh.Mishra@Sun.COM * Address - Pointer to where the gas->address 151*10457SSaurabh.Mishra@Sun.COM * is returned 152*10457SSaurabh.Mishra@Sun.COM * 153*10457SSaurabh.Mishra@Sun.COM * RETURN: Status 154*10457SSaurabh.Mishra@Sun.COM * 155*10457SSaurabh.Mishra@Sun.COM * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS 156*10457SSaurabh.Mishra@Sun.COM * pointer, Address, SpaceId, BitWidth, and BitOffset. 157*10457SSaurabh.Mishra@Sun.COM * 158*10457SSaurabh.Mishra@Sun.COM ******************************************************************************/ 159*10457SSaurabh.Mishra@Sun.COM 160*10457SSaurabh.Mishra@Sun.COM ACPI_STATUS 161*10457SSaurabh.Mishra@Sun.COM AcpiHwValidateRegister ( 162*10457SSaurabh.Mishra@Sun.COM ACPI_GENERIC_ADDRESS *Reg, 163*10457SSaurabh.Mishra@Sun.COM UINT8 MaxBitWidth, 164*10457SSaurabh.Mishra@Sun.COM UINT64 *Address) 165*10457SSaurabh.Mishra@Sun.COM { 166*10457SSaurabh.Mishra@Sun.COM 167*10457SSaurabh.Mishra@Sun.COM /* Must have a valid pointer to a GAS structure */ 168*10457SSaurabh.Mishra@Sun.COM 169*10457SSaurabh.Mishra@Sun.COM if (!Reg) 170*10457SSaurabh.Mishra@Sun.COM { 171*10457SSaurabh.Mishra@Sun.COM return (AE_BAD_PARAMETER); 172*10457SSaurabh.Mishra@Sun.COM } 173*10457SSaurabh.Mishra@Sun.COM 174*10457SSaurabh.Mishra@Sun.COM /* 175*10457SSaurabh.Mishra@Sun.COM * Copy the target address. This handles possible alignment issues. 176*10457SSaurabh.Mishra@Sun.COM * Address must not be null. A null address also indicates an optional 177*10457SSaurabh.Mishra@Sun.COM * ACPI register that is not supported, so no error message. 178*10457SSaurabh.Mishra@Sun.COM */ 179*10457SSaurabh.Mishra@Sun.COM ACPI_MOVE_64_TO_64 (Address, &Reg->Address); 180*10457SSaurabh.Mishra@Sun.COM if (!(*Address)) 181*10457SSaurabh.Mishra@Sun.COM { 182*10457SSaurabh.Mishra@Sun.COM return (AE_BAD_ADDRESS); 183*10457SSaurabh.Mishra@Sun.COM } 184*10457SSaurabh.Mishra@Sun.COM 185*10457SSaurabh.Mishra@Sun.COM /* Validate the SpaceID */ 186*10457SSaurabh.Mishra@Sun.COM 187*10457SSaurabh.Mishra@Sun.COM if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 188*10457SSaurabh.Mishra@Sun.COM (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) 189*10457SSaurabh.Mishra@Sun.COM { 190*10457SSaurabh.Mishra@Sun.COM ACPI_ERROR ((AE_INFO, 191*10457SSaurabh.Mishra@Sun.COM "Unsupported address space: 0x%X", Reg->SpaceId)); 192*10457SSaurabh.Mishra@Sun.COM return (AE_SUPPORT); 193*10457SSaurabh.Mishra@Sun.COM } 194*10457SSaurabh.Mishra@Sun.COM 195*10457SSaurabh.Mishra@Sun.COM /* Validate the BitWidth */ 196*10457SSaurabh.Mishra@Sun.COM 197*10457SSaurabh.Mishra@Sun.COM if ((Reg->BitWidth != 8) && 198*10457SSaurabh.Mishra@Sun.COM (Reg->BitWidth != 16) && 199*10457SSaurabh.Mishra@Sun.COM (Reg->BitWidth != 32) && 200*10457SSaurabh.Mishra@Sun.COM (Reg->BitWidth != MaxBitWidth)) 201*10457SSaurabh.Mishra@Sun.COM { 202*10457SSaurabh.Mishra@Sun.COM ACPI_ERROR ((AE_INFO, 203*10457SSaurabh.Mishra@Sun.COM "Unsupported register bit width: 0x%X", Reg->BitWidth)); 204*10457SSaurabh.Mishra@Sun.COM return (AE_SUPPORT); 205*10457SSaurabh.Mishra@Sun.COM } 206*10457SSaurabh.Mishra@Sun.COM 207*10457SSaurabh.Mishra@Sun.COM /* Validate the BitOffset. Just a warning for now. */ 208*10457SSaurabh.Mishra@Sun.COM 209*10457SSaurabh.Mishra@Sun.COM if (Reg->BitOffset != 0) 210*10457SSaurabh.Mishra@Sun.COM { 211*10457SSaurabh.Mishra@Sun.COM ACPI_WARNING ((AE_INFO, 212*10457SSaurabh.Mishra@Sun.COM "Unsupported register bit offset: 0x%X", Reg->BitOffset)); 213*10457SSaurabh.Mishra@Sun.COM } 214*10457SSaurabh.Mishra@Sun.COM 215*10457SSaurabh.Mishra@Sun.COM return (AE_OK); 216*10457SSaurabh.Mishra@Sun.COM } 217*10457SSaurabh.Mishra@Sun.COM 218*10457SSaurabh.Mishra@Sun.COM 219*10457SSaurabh.Mishra@Sun.COM /****************************************************************************** 220*10457SSaurabh.Mishra@Sun.COM * 221*10457SSaurabh.Mishra@Sun.COM * FUNCTION: AcpiHwWrite 222*10457SSaurabh.Mishra@Sun.COM * 223*10457SSaurabh.Mishra@Sun.COM * PARAMETERS: Value - Value to be written 224*10457SSaurabh.Mishra@Sun.COM * Reg - GAS register structure 225*10457SSaurabh.Mishra@Sun.COM * 226*10457SSaurabh.Mishra@Sun.COM * RETURN: Status 227*10457SSaurabh.Mishra@Sun.COM * 228*10457SSaurabh.Mishra@Sun.COM * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max 229*10457SSaurabh.Mishra@Sun.COM * version of AcpiWrite, used internally since the overhead of 230*10457SSaurabh.Mishra@Sun.COM * 64-bit values is not needed. 231*10457SSaurabh.Mishra@Sun.COM * 232*10457SSaurabh.Mishra@Sun.COM ******************************************************************************/ 233*10457SSaurabh.Mishra@Sun.COM 234*10457SSaurabh.Mishra@Sun.COM ACPI_STATUS 235*10457SSaurabh.Mishra@Sun.COM AcpiHwWrite ( 236*10457SSaurabh.Mishra@Sun.COM UINT32 Value, 237*10457SSaurabh.Mishra@Sun.COM ACPI_GENERIC_ADDRESS *Reg) 238*10457SSaurabh.Mishra@Sun.COM { 239*10457SSaurabh.Mishra@Sun.COM UINT64 Address; 240*10457SSaurabh.Mishra@Sun.COM ACPI_STATUS Status; 241*10457SSaurabh.Mishra@Sun.COM 242*10457SSaurabh.Mishra@Sun.COM 243*10457SSaurabh.Mishra@Sun.COM ACPI_FUNCTION_NAME (HwWrite); 244*10457SSaurabh.Mishra@Sun.COM 245*10457SSaurabh.Mishra@Sun.COM 246*10457SSaurabh.Mishra@Sun.COM /* Validate contents of the GAS register */ 247*10457SSaurabh.Mishra@Sun.COM 248*10457SSaurabh.Mishra@Sun.COM Status = AcpiHwValidateRegister (Reg, 32, &Address); 249*10457SSaurabh.Mishra@Sun.COM if (ACPI_FAILURE (Status)) 250*10457SSaurabh.Mishra@Sun.COM { 251*10457SSaurabh.Mishra@Sun.COM return (Status); 252*10457SSaurabh.Mishra@Sun.COM } 253*10457SSaurabh.Mishra@Sun.COM 254*10457SSaurabh.Mishra@Sun.COM /* 255*10457SSaurabh.Mishra@Sun.COM * Two address spaces supported: Memory or IO. PCI_Config is 256*10457SSaurabh.Mishra@Sun.COM * not supported here because the GAS structure is insufficient 257*10457SSaurabh.Mishra@Sun.COM */ 258*10457SSaurabh.Mishra@Sun.COM if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 259*10457SSaurabh.Mishra@Sun.COM { 260*10457SSaurabh.Mishra@Sun.COM Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) 261*10457SSaurabh.Mishra@Sun.COM Address, Value, Reg->BitWidth); 262*10457SSaurabh.Mishra@Sun.COM } 263*10457SSaurabh.Mishra@Sun.COM else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 264*10457SSaurabh.Mishra@Sun.COM { 265*10457SSaurabh.Mishra@Sun.COM Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 266*10457SSaurabh.Mishra@Sun.COM Address, Value, Reg->BitWidth); 267*10457SSaurabh.Mishra@Sun.COM } 268*10457SSaurabh.Mishra@Sun.COM 269*10457SSaurabh.Mishra@Sun.COM ACPI_DEBUG_PRINT ((ACPI_DB_IO, 270*10457SSaurabh.Mishra@Sun.COM "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", 271*10457SSaurabh.Mishra@Sun.COM Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address), 272*10457SSaurabh.Mishra@Sun.COM AcpiUtGetRegionName (Reg->SpaceId))); 273*10457SSaurabh.Mishra@Sun.COM 274*10457SSaurabh.Mishra@Sun.COM return (Status); 275*10457SSaurabh.Mishra@Sun.COM } 276*10457SSaurabh.Mishra@Sun.COM 277*10457SSaurabh.Mishra@Sun.COM 2783446Smrj /******************************************************************************* 2793446Smrj * 2803446Smrj * FUNCTION: AcpiHwClearAcpiStatus 2813446Smrj * 2827851SDana.Myers@Sun.COM * PARAMETERS: None 2833446Smrj * 2849980SDana.Myers@Sun.COM * RETURN: Status 2853446Smrj * 2863446Smrj * DESCRIPTION: Clears all fixed and general purpose status bits 2873446Smrj * 2883446Smrj ******************************************************************************/ 2893446Smrj 2903446Smrj ACPI_STATUS 2913446Smrj AcpiHwClearAcpiStatus ( 2927851SDana.Myers@Sun.COM void) 2933446Smrj { 2943446Smrj ACPI_STATUS Status; 2953446Smrj ACPI_CPU_FLAGS LockFlags = 0; 2963446Smrj 2973446Smrj 2983446Smrj ACPI_FUNCTION_TRACE (HwClearAcpiStatus); 2993446Smrj 3003446Smrj 3019980SDana.Myers@Sun.COM ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n", 3023446Smrj ACPI_BITMASK_ALL_FIXED_STATUS, 3039980SDana.Myers@Sun.COM ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address))); 3043446Smrj 3053446Smrj LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 3063446Smrj 3079980SDana.Myers@Sun.COM /* Clear the fixed events in PM1 A/B */ 3089980SDana.Myers@Sun.COM 3097851SDana.Myers@Sun.COM Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, 3103446Smrj ACPI_BITMASK_ALL_FIXED_STATUS); 3113446Smrj if (ACPI_FAILURE (Status)) 3123446Smrj { 3133446Smrj goto UnlockAndExit; 3143446Smrj } 3153446Smrj 3163446Smrj /* Clear the GPE Bits in all GPE registers in all GPE blocks */ 3173446Smrj 3189980SDana.Myers@Sun.COM Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); 3193446Smrj 3203446Smrj UnlockAndExit: 3213446Smrj AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 3223446Smrj return_ACPI_STATUS (Status); 3233446Smrj } 3243446Smrj 3253446Smrj 3263446Smrj /******************************************************************************* 3273446Smrj * 3283446Smrj * FUNCTION: AcpiHwGetRegisterBitMask 3293446Smrj * 3303446Smrj * PARAMETERS: RegisterId - Index of ACPI Register to access 3313446Smrj * 3323446Smrj * RETURN: The bitmask to be used when accessing the register 3333446Smrj * 3343446Smrj * DESCRIPTION: Map RegisterId into a register bitmask. 3353446Smrj * 3363446Smrj ******************************************************************************/ 3373446Smrj 3383446Smrj ACPI_BIT_REGISTER_INFO * 3393446Smrj AcpiHwGetBitRegisterInfo ( 3403446Smrj UINT32 RegisterId) 3413446Smrj { 3423446Smrj ACPI_FUNCTION_ENTRY (); 3433446Smrj 3443446Smrj 3453446Smrj if (RegisterId > ACPI_BITREG_MAX) 3463446Smrj { 3473446Smrj ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: %X", RegisterId)); 3483446Smrj return (NULL); 3493446Smrj } 3503446Smrj 3513446Smrj return (&AcpiGbl_BitRegisterInfo[RegisterId]); 3523446Smrj } 3533446Smrj 3543446Smrj 3559980SDana.Myers@Sun.COM /****************************************************************************** 3563446Smrj * 3579980SDana.Myers@Sun.COM * FUNCTION: AcpiHwWritePm1Control 3587851SDana.Myers@Sun.COM * 3599980SDana.Myers@Sun.COM * PARAMETERS: Pm1aControl - Value to be written to PM1A control 3609980SDana.Myers@Sun.COM * Pm1bControl - Value to be written to PM1B control 3613446Smrj * 3623446Smrj * RETURN: Status 3633446Smrj * 3649980SDana.Myers@Sun.COM * DESCRIPTION: Write the PM1 A/B control registers. These registers are 3659980SDana.Myers@Sun.COM * different than than the PM1 A/B status and enable registers 3669980SDana.Myers@Sun.COM * in that different values can be written to the A/B registers. 3679980SDana.Myers@Sun.COM * Most notably, the SLP_TYP bits can be different, as per the 3689980SDana.Myers@Sun.COM * values returned from the _Sx predefined methods. 3693446Smrj * 3703446Smrj ******************************************************************************/ 3713446Smrj 3723446Smrj ACPI_STATUS 3739980SDana.Myers@Sun.COM AcpiHwWritePm1Control ( 3749980SDana.Myers@Sun.COM UINT32 Pm1aControl, 3759980SDana.Myers@Sun.COM UINT32 Pm1bControl) 3763446Smrj { 3773446Smrj ACPI_STATUS Status; 3783446Smrj 3793446Smrj 3809980SDana.Myers@Sun.COM ACPI_FUNCTION_TRACE (HwWritePm1Control); 3813446Smrj 3823446Smrj 3839980SDana.Myers@Sun.COM Status = AcpiWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock); 3849980SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 3859980SDana.Myers@Sun.COM { 3869980SDana.Myers@Sun.COM return_ACPI_STATUS (Status); 3873446Smrj } 3883446Smrj 3899980SDana.Myers@Sun.COM if (AcpiGbl_FADT.XPm1bControlBlock.Address) 3909980SDana.Myers@Sun.COM { 3919980SDana.Myers@Sun.COM Status = AcpiWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock); 3929980SDana.Myers@Sun.COM } 3933446Smrj return_ACPI_STATUS (Status); 3943446Smrj } 3953446Smrj 3963446Smrj 3973446Smrj /****************************************************************************** 3983446Smrj * 3993446Smrj * FUNCTION: AcpiHwRegisterRead 4003446Smrj * 4017851SDana.Myers@Sun.COM * PARAMETERS: RegisterId - ACPI Register ID 4023446Smrj * ReturnValue - Where the register value is returned 4033446Smrj * 4043446Smrj * RETURN: Status and the value read. 4053446Smrj * 4063446Smrj * DESCRIPTION: Read from the specified ACPI register 4073446Smrj * 4083446Smrj ******************************************************************************/ 4093446Smrj 4103446Smrj ACPI_STATUS 4113446Smrj AcpiHwRegisterRead ( 4123446Smrj UINT32 RegisterId, 4133446Smrj UINT32 *ReturnValue) 4143446Smrj { 4159980SDana.Myers@Sun.COM UINT32 Value = 0; 4163446Smrj ACPI_STATUS Status; 4173446Smrj 4183446Smrj 4193446Smrj ACPI_FUNCTION_TRACE (HwRegisterRead); 4203446Smrj 4213446Smrj 4223446Smrj switch (RegisterId) 4233446Smrj { 4249980SDana.Myers@Sun.COM case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ 4253446Smrj 4269980SDana.Myers@Sun.COM Status = AcpiHwReadMultiple (&Value, 4279980SDana.Myers@Sun.COM &AcpiGbl_XPm1aStatus, 4289980SDana.Myers@Sun.COM &AcpiGbl_XPm1bStatus); 4293446Smrj break; 4303446Smrj 4313446Smrj 4329980SDana.Myers@Sun.COM case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ 4333446Smrj 4349980SDana.Myers@Sun.COM Status = AcpiHwReadMultiple (&Value, 4359980SDana.Myers@Sun.COM &AcpiGbl_XPm1aEnable, 4369980SDana.Myers@Sun.COM &AcpiGbl_XPm1bEnable); 4373446Smrj break; 4383446Smrj 4393446Smrj 4409980SDana.Myers@Sun.COM case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ 4419980SDana.Myers@Sun.COM 4429980SDana.Myers@Sun.COM Status = AcpiHwReadMultiple (&Value, 4439980SDana.Myers@Sun.COM &AcpiGbl_FADT.XPm1aControlBlock, 4449980SDana.Myers@Sun.COM &AcpiGbl_FADT.XPm1bControlBlock); 4453446Smrj 4469980SDana.Myers@Sun.COM /* 4479980SDana.Myers@Sun.COM * Zero the write-only bits. From the ACPI specification, "Hardware 4489980SDana.Myers@Sun.COM * Write-Only Bits": "Upon reads to registers with write-only bits, 4499980SDana.Myers@Sun.COM * software masks out all write-only bits." 4509980SDana.Myers@Sun.COM */ 4519980SDana.Myers@Sun.COM Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS; 4523446Smrj break; 4533446Smrj 4543446Smrj 4553446Smrj case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 4563446Smrj 4579980SDana.Myers@Sun.COM Status = AcpiRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock); 4583446Smrj break; 4593446Smrj 4603446Smrj 4613446Smrj case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 4623446Smrj 4639980SDana.Myers@Sun.COM Status = AcpiRead (&Value, &AcpiGbl_FADT.XPmTimerBlock); 4643446Smrj break; 4653446Smrj 4669980SDana.Myers@Sun.COM 4673446Smrj case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 4683446Smrj 4699980SDana.Myers@Sun.COM Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8); 4703446Smrj break; 4713446Smrj 4729980SDana.Myers@Sun.COM 4733446Smrj default: 4743446Smrj ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X", 4753446Smrj RegisterId)); 4763446Smrj Status = AE_BAD_PARAMETER; 4773446Smrj break; 4783446Smrj } 4793446Smrj 4803446Smrj if (ACPI_SUCCESS (Status)) 4813446Smrj { 4829980SDana.Myers@Sun.COM *ReturnValue = Value; 4833446Smrj } 4843446Smrj 4853446Smrj return_ACPI_STATUS (Status); 4863446Smrj } 4873446Smrj 4883446Smrj 4893446Smrj /****************************************************************************** 4903446Smrj * 4913446Smrj * FUNCTION: AcpiHwRegisterWrite 4923446Smrj * 4937851SDana.Myers@Sun.COM * PARAMETERS: RegisterId - ACPI Register ID 4943446Smrj * Value - The value to write 4953446Smrj * 4963446Smrj * RETURN: Status 4973446Smrj * 4983446Smrj * DESCRIPTION: Write to the specified ACPI register 4993446Smrj * 5003446Smrj * NOTE: In accordance with the ACPI specification, this function automatically 5013446Smrj * preserves the value of the following bits, meaning that these bits cannot be 5023446Smrj * changed via this interface: 5033446Smrj * 5043446Smrj * PM1_CONTROL[0] = SCI_EN 5053446Smrj * PM1_CONTROL[9] 5063446Smrj * PM1_STATUS[11] 5073446Smrj * 5083446Smrj * ACPI References: 5093446Smrj * 1) Hardware Ignored Bits: When software writes to a register with ignored 5103446Smrj * bit fields, it preserves the ignored bit fields 5113446Smrj * 2) SCI_EN: OSPM always preserves this bit position 5123446Smrj * 5133446Smrj ******************************************************************************/ 5143446Smrj 5153446Smrj ACPI_STATUS 5163446Smrj AcpiHwRegisterWrite ( 5173446Smrj UINT32 RegisterId, 5183446Smrj UINT32 Value) 5193446Smrj { 5203446Smrj ACPI_STATUS Status; 5213446Smrj UINT32 ReadValue; 5223446Smrj 5233446Smrj 5243446Smrj ACPI_FUNCTION_TRACE (HwRegisterWrite); 5253446Smrj 5263446Smrj 5273446Smrj switch (RegisterId) 5283446Smrj { 5299980SDana.Myers@Sun.COM case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ 5309980SDana.Myers@Sun.COM /* 5319980SDana.Myers@Sun.COM * Handle the "ignored" bit in PM1 Status. According to the ACPI 5329980SDana.Myers@Sun.COM * specification, ignored bits are to be preserved when writing. 5339980SDana.Myers@Sun.COM * Normally, this would mean a read/modify/write sequence. However, 5349980SDana.Myers@Sun.COM * preserving a bit in the status register is different. Writing a 5359980SDana.Myers@Sun.COM * one clears the status, and writing a zero preserves the status. 5369980SDana.Myers@Sun.COM * Therefore, we must always write zero to the ignored bit. 5379980SDana.Myers@Sun.COM * 5389980SDana.Myers@Sun.COM * This behavior is clarified in the ACPI 4.0 specification. 5399980SDana.Myers@Sun.COM */ 5409980SDana.Myers@Sun.COM Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS; 5413446Smrj 5429980SDana.Myers@Sun.COM Status = AcpiHwWriteMultiple (Value, 5439980SDana.Myers@Sun.COM &AcpiGbl_XPm1aStatus, 5449980SDana.Myers@Sun.COM &AcpiGbl_XPm1bStatus); 5453446Smrj break; 5463446Smrj 5473446Smrj 5489980SDana.Myers@Sun.COM case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ 5493446Smrj 5509980SDana.Myers@Sun.COM Status = AcpiHwWriteMultiple (Value, 5519980SDana.Myers@Sun.COM &AcpiGbl_XPm1aEnable, 5529980SDana.Myers@Sun.COM &AcpiGbl_XPm1bEnable); 5533446Smrj break; 5543446Smrj 5553446Smrj 5569980SDana.Myers@Sun.COM case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ 5573446Smrj 5583446Smrj /* 5593446Smrj * Perform a read first to preserve certain bits (per ACPI spec) 5603446Smrj * Note: This includes SCI_EN, we never want to change this bit 5613446Smrj */ 5629980SDana.Myers@Sun.COM Status = AcpiHwReadMultiple (&ReadValue, 5639980SDana.Myers@Sun.COM &AcpiGbl_FADT.XPm1aControlBlock, 5649980SDana.Myers@Sun.COM &AcpiGbl_FADT.XPm1bControlBlock); 5653446Smrj if (ACPI_FAILURE (Status)) 5663446Smrj { 5677851SDana.Myers@Sun.COM goto Exit; 5683446Smrj } 5693446Smrj 5703446Smrj /* Insert the bits to be preserved */ 5713446Smrj 5723446Smrj ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue); 5733446Smrj 5743446Smrj /* Now we can write the data */ 5753446Smrj 5769980SDana.Myers@Sun.COM Status = AcpiHwWriteMultiple (Value, 5779980SDana.Myers@Sun.COM &AcpiGbl_FADT.XPm1aControlBlock, 5789980SDana.Myers@Sun.COM &AcpiGbl_FADT.XPm1bControlBlock); 5799980SDana.Myers@Sun.COM break; 5809980SDana.Myers@Sun.COM 5819980SDana.Myers@Sun.COM 5829980SDana.Myers@Sun.COM case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 5839980SDana.Myers@Sun.COM 5849980SDana.Myers@Sun.COM /* 5859980SDana.Myers@Sun.COM * For control registers, all reserved bits must be preserved, 5869980SDana.Myers@Sun.COM * as per the ACPI spec. 5879980SDana.Myers@Sun.COM */ 5889980SDana.Myers@Sun.COM Status = AcpiRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock); 5893446Smrj if (ACPI_FAILURE (Status)) 5903446Smrj { 5917851SDana.Myers@Sun.COM goto Exit; 5923446Smrj } 5933446Smrj 5949980SDana.Myers@Sun.COM /* Insert the bits to be preserved */ 5953446Smrj 5969980SDana.Myers@Sun.COM ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue); 5973446Smrj 5989980SDana.Myers@Sun.COM Status = AcpiWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock); 5993446Smrj break; 6003446Smrj 6013446Smrj 6023446Smrj case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 6033446Smrj 6049980SDana.Myers@Sun.COM Status = AcpiWrite (Value, &AcpiGbl_FADT.XPmTimerBlock); 6053446Smrj break; 6063446Smrj 6073446Smrj 6083446Smrj case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 6093446Smrj 6103446Smrj /* SMI_CMD is currently always in IO space */ 6113446Smrj 6129980SDana.Myers@Sun.COM Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8); 6133446Smrj break; 6143446Smrj 6153446Smrj 6163446Smrj default: 6179980SDana.Myers@Sun.COM ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X", 6189980SDana.Myers@Sun.COM RegisterId)); 6193446Smrj Status = AE_BAD_PARAMETER; 6203446Smrj break; 6213446Smrj } 6223446Smrj 6237851SDana.Myers@Sun.COM Exit: 6243446Smrj return_ACPI_STATUS (Status); 6253446Smrj } 6263446Smrj 6273446Smrj 6283446Smrj /****************************************************************************** 6293446Smrj * 6309980SDana.Myers@Sun.COM * FUNCTION: AcpiHwReadMultiple 6313446Smrj * 6329980SDana.Myers@Sun.COM * PARAMETERS: Value - Where the register value is returned 6339980SDana.Myers@Sun.COM * RegisterA - First ACPI register (required) 6349980SDana.Myers@Sun.COM * RegisterB - Second ACPI register (optional) 6353446Smrj * 6363446Smrj * RETURN: Status 6373446Smrj * 6389980SDana.Myers@Sun.COM * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B) 6393446Smrj * 6403446Smrj ******************************************************************************/ 6413446Smrj 6429980SDana.Myers@Sun.COM static ACPI_STATUS 6439980SDana.Myers@Sun.COM AcpiHwReadMultiple ( 6443446Smrj UINT32 *Value, 6459980SDana.Myers@Sun.COM ACPI_GENERIC_ADDRESS *RegisterA, 6469980SDana.Myers@Sun.COM ACPI_GENERIC_ADDRESS *RegisterB) 6473446Smrj { 6489980SDana.Myers@Sun.COM UINT32 ValueA = 0; 6499980SDana.Myers@Sun.COM UINT32 ValueB = 0; 6503446Smrj ACPI_STATUS Status; 6513446Smrj 6523446Smrj 6539980SDana.Myers@Sun.COM /* The first register is always required */ 6543446Smrj 6559980SDana.Myers@Sun.COM Status = AcpiRead (&ValueA, RegisterA); 6569980SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 6573446Smrj { 6589980SDana.Myers@Sun.COM return (Status); 6593446Smrj } 6603446Smrj 6619980SDana.Myers@Sun.COM /* Second register is optional */ 6623446Smrj 6639980SDana.Myers@Sun.COM if (RegisterB->Address) 6643446Smrj { 6659980SDana.Myers@Sun.COM Status = AcpiRead (&ValueB, RegisterB); 6669980SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 6679980SDana.Myers@Sun.COM { 6689980SDana.Myers@Sun.COM return (Status); 6699980SDana.Myers@Sun.COM } 6703446Smrj } 6713446Smrj 6723446Smrj /* 6739980SDana.Myers@Sun.COM * OR the two return values together. No shifting or masking is necessary, 6749980SDana.Myers@Sun.COM * because of how the PM1 registers are defined in the ACPI specification: 6759980SDana.Myers@Sun.COM * 6769980SDana.Myers@Sun.COM * "Although the bits can be split between the two register blocks (each 6779980SDana.Myers@Sun.COM * register block has a unique pointer within the FADT), the bit positions 6789980SDana.Myers@Sun.COM * are maintained. The register block with unimplemented bits (that is, 6799980SDana.Myers@Sun.COM * those implemented in the other register block) always returns zeros, 6809980SDana.Myers@Sun.COM * and writes have no side effects" 6813446Smrj */ 6829980SDana.Myers@Sun.COM *Value = (ValueA | ValueB); 6839980SDana.Myers@Sun.COM return (AE_OK); 6843446Smrj } 6853446Smrj 6863446Smrj 6873446Smrj /****************************************************************************** 6883446Smrj * 6899980SDana.Myers@Sun.COM * FUNCTION: AcpiHwWriteMultiple 6903446Smrj * 6919980SDana.Myers@Sun.COM * PARAMETERS: Value - The value to write 6929980SDana.Myers@Sun.COM * RegisterA - First ACPI register (required) 6939980SDana.Myers@Sun.COM * RegisterB - Second ACPI register (optional) 6943446Smrj * 6953446Smrj * RETURN: Status 6963446Smrj * 6979980SDana.Myers@Sun.COM * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B) 6983446Smrj * 6993446Smrj ******************************************************************************/ 7003446Smrj 7019980SDana.Myers@Sun.COM static ACPI_STATUS 7029980SDana.Myers@Sun.COM AcpiHwWriteMultiple ( 7033446Smrj UINT32 Value, 7049980SDana.Myers@Sun.COM ACPI_GENERIC_ADDRESS *RegisterA, 7059980SDana.Myers@Sun.COM ACPI_GENERIC_ADDRESS *RegisterB) 7063446Smrj { 7073446Smrj ACPI_STATUS Status; 7083446Smrj 7093446Smrj 7109980SDana.Myers@Sun.COM /* The first register is always required */ 7113446Smrj 7129980SDana.Myers@Sun.COM Status = AcpiWrite (Value, RegisterA); 7139980SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 7143446Smrj { 7159980SDana.Myers@Sun.COM return (Status); 7163446Smrj } 7173446Smrj 7183446Smrj /* 7199980SDana.Myers@Sun.COM * Second register is optional 7209980SDana.Myers@Sun.COM * 7219980SDana.Myers@Sun.COM * No bit shifting or clearing is necessary, because of how the PM1 7229980SDana.Myers@Sun.COM * registers are defined in the ACPI specification: 7239980SDana.Myers@Sun.COM * 7249980SDana.Myers@Sun.COM * "Although the bits can be split between the two register blocks (each 7259980SDana.Myers@Sun.COM * register block has a unique pointer within the FADT), the bit positions 7269980SDana.Myers@Sun.COM * are maintained. The register block with unimplemented bits (that is, 7279980SDana.Myers@Sun.COM * those implemented in the other register block) always returns zeros, 7289980SDana.Myers@Sun.COM * and writes have no side effects" 7293446Smrj */ 7309980SDana.Myers@Sun.COM if (RegisterB->Address) 7313446Smrj { 7329980SDana.Myers@Sun.COM Status = AcpiWrite (Value, RegisterB); 7333446Smrj } 7343446Smrj 7353446Smrj return (Status); 7363446Smrj } 7379980SDana.Myers@Sun.COM 738