Home | History | Annotate | Line # | Download | only in hardware
hwxface.c revision 1.1.1.2
      1 
      2 /******************************************************************************
      3  *
      4  * Module Name: hwxface - Public ACPICA hardware interfaces
      5  *
      6  *****************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2011, Intel Corp.
     10  * All rights reserved.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     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.
     26  *
     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.
     30  *
     31  * NO WARRANTY
     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.
     43  */
     44 
     45 #include "acpi.h"
     46 #include "accommon.h"
     47 #include "acnamesp.h"
     48 
     49 #define _COMPONENT          ACPI_HARDWARE
     50         ACPI_MODULE_NAME    ("hwxface")
     51 
     52 
     53 /******************************************************************************
     54  *
     55  * FUNCTION:    AcpiReset
     56  *
     57  * PARAMETERS:  None
     58  *
     59  * RETURN:      Status
     60  *
     61  * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
     62  *              support reset register in PCI config space, this must be
     63  *              handled separately.
     64  *
     65  ******************************************************************************/
     66 
     67 ACPI_STATUS
     68 AcpiReset (
     69     void)
     70 {
     71     ACPI_GENERIC_ADDRESS    *ResetReg;
     72     ACPI_STATUS             Status;
     73 
     74 
     75     ACPI_FUNCTION_TRACE (AcpiReset);
     76 
     77 
     78     ResetReg = &AcpiGbl_FADT.ResetRegister;
     79 
     80     /* Check if the reset register is supported */
     81 
     82     if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
     83         !ResetReg->Address)
     84     {
     85         return_ACPI_STATUS (AE_NOT_EXIST);
     86     }
     87 
     88     if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
     89     {
     90         /*
     91          * For I/O space, write directly to the OSL. This bypasses the port
     92          * validation mechanism, which may block a valid write to the reset
     93          * register.
     94          */
     95         Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address,
     96                     AcpiGbl_FADT.ResetValue, ResetReg->BitWidth);
     97     }
     98     else
     99     {
    100         /* Write the reset value to the reset register */
    101 
    102         Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg);
    103     }
    104 
    105     return_ACPI_STATUS (Status);
    106 }
    107 
    108 ACPI_EXPORT_SYMBOL (AcpiReset)
    109 
    110 
    111 /******************************************************************************
    112  *
    113  * FUNCTION:    AcpiRead
    114  *
    115  * PARAMETERS:  Value               - Where the value is returned
    116  *              Reg                 - GAS register structure
    117  *
    118  * RETURN:      Status
    119  *
    120  * DESCRIPTION: Read from either memory or IO space.
    121  *
    122  * LIMITATIONS: <These limitations also apply to AcpiWrite>
    123  *      BitWidth must be exactly 8, 16, 32, or 64.
    124  *      SpaceID must be SystemMemory or SystemIO.
    125  *      BitOffset and AccessWidth are currently ignored, as there has
    126  *          not been a need to implement these.
    127  *
    128  ******************************************************************************/
    129 
    130 ACPI_STATUS
    131 AcpiRead (
    132     UINT64                  *ReturnValue,
    133     ACPI_GENERIC_ADDRESS    *Reg)
    134 {
    135     UINT32                  Value;
    136     UINT32                  Width;
    137     UINT64                  Address;
    138     ACPI_STATUS             Status;
    139 
    140 
    141     ACPI_FUNCTION_NAME (AcpiRead);
    142 
    143 
    144     if (!ReturnValue)
    145     {
    146         return (AE_BAD_PARAMETER);
    147     }
    148 
    149     /* Validate contents of the GAS register. Allow 64-bit transfers */
    150 
    151     Status = AcpiHwValidateRegister (Reg, 64, &Address);
    152     if (ACPI_FAILURE (Status))
    153     {
    154         return (Status);
    155     }
    156 
    157     Width = Reg->BitWidth;
    158     if (Width == 64)
    159     {
    160         Width = 32; /* Break into two 32-bit transfers */
    161     }
    162 
    163     /* Initialize entire 64-bit return value to zero */
    164 
    165     *ReturnValue = 0;
    166     Value = 0;
    167 
    168     /*
    169      * Two address spaces supported: Memory or IO. PCI_Config is
    170      * not supported here because the GAS structure is insufficient
    171      */
    172     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
    173     {
    174         Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
    175                     Address, &Value, Width);
    176         if (ACPI_FAILURE (Status))
    177         {
    178             return (Status);
    179         }
    180         *ReturnValue = Value;
    181 
    182         if (Reg->BitWidth == 64)
    183         {
    184             /* Read the top 32 bits */
    185 
    186             Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
    187                         (Address + 4), &Value, 32);
    188             if (ACPI_FAILURE (Status))
    189             {
    190                 return (Status);
    191             }
    192             *ReturnValue |= ((UINT64) Value << 32);
    193         }
    194     }
    195     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
    196     {
    197         Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
    198                     Address, &Value, Width);
    199         if (ACPI_FAILURE (Status))
    200         {
    201             return (Status);
    202         }
    203         *ReturnValue = Value;
    204 
    205         if (Reg->BitWidth == 64)
    206         {
    207             /* Read the top 32 bits */
    208 
    209             Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
    210                         (Address + 4), &Value, 32);
    211             if (ACPI_FAILURE (Status))
    212             {
    213                 return (Status);
    214             }
    215             *ReturnValue |= ((UINT64) Value << 32);
    216         }
    217     }
    218 
    219     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
    220         "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
    221         ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth,
    222         ACPI_FORMAT_UINT64 (Address),
    223         AcpiUtGetRegionName (Reg->SpaceId)));
    224 
    225     return (Status);
    226 }
    227 
    228 ACPI_EXPORT_SYMBOL (AcpiRead)
    229 
    230 
    231 /******************************************************************************
    232  *
    233  * FUNCTION:    AcpiWrite
    234  *
    235  * PARAMETERS:  Value               - Value to be written
    236  *              Reg                 - GAS register structure
    237  *
    238  * RETURN:      Status
    239  *
    240  * DESCRIPTION: Write to either memory or IO space.
    241  *
    242  ******************************************************************************/
    243 
    244 ACPI_STATUS
    245 AcpiWrite (
    246     UINT64                  Value,
    247     ACPI_GENERIC_ADDRESS    *Reg)
    248 {
    249     UINT32                  Width;
    250     UINT64                  Address;
    251     ACPI_STATUS             Status;
    252 
    253 
    254     ACPI_FUNCTION_NAME (AcpiWrite);
    255 
    256 
    257     /* Validate contents of the GAS register. Allow 64-bit transfers */
    258 
    259     Status = AcpiHwValidateRegister (Reg, 64, &Address);
    260     if (ACPI_FAILURE (Status))
    261     {
    262         return (Status);
    263     }
    264 
    265     Width = Reg->BitWidth;
    266     if (Width == 64)
    267     {
    268         Width = 32; /* Break into two 32-bit transfers */
    269     }
    270 
    271     /*
    272      * Two address spaces supported: Memory or IO. PCI_Config is
    273      * not supported here because the GAS structure is insufficient
    274      */
    275     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
    276     {
    277         Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
    278                     Address, ACPI_LODWORD (Value), Width);
    279         if (ACPI_FAILURE (Status))
    280         {
    281             return (Status);
    282         }
    283 
    284         if (Reg->BitWidth == 64)
    285         {
    286             Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
    287                         (Address + 4), ACPI_HIDWORD (Value), 32);
    288             if (ACPI_FAILURE (Status))
    289             {
    290                 return (Status);
    291             }
    292         }
    293     }
    294     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
    295     {
    296         Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
    297                     Address, ACPI_LODWORD (Value), Width);
    298         if (ACPI_FAILURE (Status))
    299         {
    300             return (Status);
    301         }
    302 
    303         if (Reg->BitWidth == 64)
    304         {
    305             Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
    306                         (Address + 4), ACPI_HIDWORD (Value), 32);
    307             if (ACPI_FAILURE (Status))
    308             {
    309                 return (Status);
    310             }
    311         }
    312     }
    313 
    314     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
    315         "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
    316         ACPI_FORMAT_UINT64 (Value), Reg->BitWidth,
    317         ACPI_FORMAT_UINT64 (Address),
    318         AcpiUtGetRegionName (Reg->SpaceId)));
    319 
    320     return (Status);
    321 }
    322 
    323 ACPI_EXPORT_SYMBOL (AcpiWrite)
    324 
    325 
    326 /*******************************************************************************
    327  *
    328  * FUNCTION:    AcpiReadBitRegister
    329  *
    330  * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
    331  *              ReturnValue     - Value that was read from the register,
    332  *                                normalized to bit position zero.
    333  *
    334  * RETURN:      Status and the value read from the specified Register. Value
    335  *              returned is normalized to bit0 (is shifted all the way right)
    336  *
    337  * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
    338  *
    339  * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
    340  *              PM2 Control.
    341  *
    342  * Note: The hardware lock is not required when reading the ACPI bit registers
    343  *       since almost all of them are single bit and it does not matter that
    344  *       the parent hardware register can be split across two physical
    345  *       registers. The only multi-bit field is SLP_TYP in the PM1 control
    346  *       register, but this field does not cross an 8-bit boundary (nor does
    347  *       it make much sense to actually read this field.)
    348  *
    349  ******************************************************************************/
    350 
    351 ACPI_STATUS
    352 AcpiReadBitRegister (
    353     UINT32                  RegisterId,
    354     UINT32                  *ReturnValue)
    355 {
    356     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
    357     UINT32                  RegisterValue;
    358     UINT32                  Value;
    359     ACPI_STATUS             Status;
    360 
    361 
    362     ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId);
    363 
    364 
    365     /* Get the info structure corresponding to the requested ACPI Register */
    366 
    367     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
    368     if (!BitRegInfo)
    369     {
    370         return_ACPI_STATUS (AE_BAD_PARAMETER);
    371     }
    372 
    373     /* Read the entire parent register */
    374 
    375     Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
    376                 &RegisterValue);
    377     if (ACPI_FAILURE (Status))
    378     {
    379         return_ACPI_STATUS (Status);
    380     }
    381 
    382     /* Normalize the value that was read, mask off other bits */
    383 
    384     Value = ((RegisterValue & BitRegInfo->AccessBitMask)
    385                 >> BitRegInfo->BitPosition);
    386 
    387     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
    388         "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
    389         RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value));
    390 
    391     *ReturnValue = Value;
    392     return_ACPI_STATUS (AE_OK);
    393 }
    394 
    395 ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
    396 
    397 
    398 /*******************************************************************************
    399  *
    400  * FUNCTION:    AcpiWriteBitRegister
    401  *
    402  * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
    403  *              Value           - Value to write to the register, in bit
    404  *                                position zero. The bit is automaticallly
    405  *                                shifted to the correct position.
    406  *
    407  * RETURN:      Status
    408  *
    409  * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
    410  *              since most operations require a read/modify/write sequence.
    411  *
    412  * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
    413  *              PM2 Control.
    414  *
    415  * Note that at this level, the fact that there may be actually two
    416  * hardware registers (A and B - and B may not exist) is abstracted.
    417  *
    418  ******************************************************************************/
    419 
    420 ACPI_STATUS
    421 AcpiWriteBitRegister (
    422     UINT32                  RegisterId,
    423     UINT32                  Value)
    424 {
    425     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
    426     ACPI_CPU_FLAGS          LockFlags;
    427     UINT32                  RegisterValue;
    428     ACPI_STATUS             Status = AE_OK;
    429 
    430 
    431     ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId);
    432 
    433 
    434     /* Get the info structure corresponding to the requested ACPI Register */
    435 
    436     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
    437     if (!BitRegInfo)
    438     {
    439         return_ACPI_STATUS (AE_BAD_PARAMETER);
    440     }
    441 
    442     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
    443 
    444     /*
    445      * At this point, we know that the parent register is one of the
    446      * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
    447      */
    448     if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS)
    449     {
    450         /*
    451          * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
    452          *
    453          * Perform a register read to preserve the bits that we are not
    454          * interested in
    455          */
    456         Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
    457                     &RegisterValue);
    458         if (ACPI_FAILURE (Status))
    459         {
    460             goto UnlockAndExit;
    461         }
    462 
    463         /*
    464          * Insert the input bit into the value that was just read
    465          * and write the register
    466          */
    467         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
    468             BitRegInfo->AccessBitMask, Value);
    469 
    470         Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister,
    471                     RegisterValue);
    472     }
    473     else
    474     {
    475         /*
    476          * 2) Case for PM1 Status
    477          *
    478          * The Status register is different from the rest. Clear an event
    479          * by writing 1, writing 0 has no effect. So, the only relevant
    480          * information is the single bit we're interested in, all others
    481          * should be written as 0 so they will be left unchanged.
    482          */
    483         RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value,
    484             BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
    485 
    486         /* No need to write the register if value is all zeros */
    487 
    488         if (RegisterValue)
    489         {
    490             Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
    491                         RegisterValue);
    492         }
    493     }
    494 
    495     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
    496         "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
    497         RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue));
    498 
    499 
    500 UnlockAndExit:
    501 
    502     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
    503     return_ACPI_STATUS (Status);
    504 }
    505 
    506 ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
    507 
    508 
    509 /*******************************************************************************
    510  *
    511  * FUNCTION:    AcpiGetSleepTypeData
    512  *
    513  * PARAMETERS:  SleepState          - Numeric sleep state
    514  *              *SleepTypeA         - Where SLP_TYPa is returned
    515  *              *SleepTypeB         - Where SLP_TYPb is returned
    516  *
    517  * RETURN:      Status - ACPI status
    518  *
    519  * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
    520  *              state.
    521  *
    522  ******************************************************************************/
    523 
    524 ACPI_STATUS
    525 AcpiGetSleepTypeData (
    526     UINT8                   SleepState,
    527     UINT8                   *SleepTypeA,
    528     UINT8                   *SleepTypeB)
    529 {
    530     ACPI_STATUS             Status = AE_OK;
    531     ACPI_EVALUATE_INFO      *Info;
    532 
    533 
    534     ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
    535 
    536 
    537     /* Validate parameters */
    538 
    539     if ((SleepState > ACPI_S_STATES_MAX) ||
    540         !SleepTypeA ||
    541         !SleepTypeB)
    542     {
    543         return_ACPI_STATUS (AE_BAD_PARAMETER);
    544     }
    545 
    546     /* Allocate the evaluation information block */
    547 
    548     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    549     if (!Info)
    550     {
    551         return_ACPI_STATUS (AE_NO_MEMORY);
    552     }
    553 
    554     Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
    555 
    556     /* Evaluate the namespace object containing the values for this state */
    557 
    558     Status = AcpiNsEvaluate (Info);
    559     if (ACPI_FAILURE (Status))
    560     {
    561         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    562             "%s while evaluating SleepState [%s]\n",
    563             AcpiFormatException (Status), Info->Pathname));
    564 
    565         goto Cleanup;
    566     }
    567 
    568     /* Must have a return object */
    569 
    570     if (!Info->ReturnObject)
    571     {
    572         ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
    573             Info->Pathname));
    574         Status = AE_NOT_EXIST;
    575     }
    576 
    577     /* It must be of type Package */
    578 
    579     else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
    580     {
    581         ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
    582         Status = AE_AML_OPERAND_TYPE;
    583     }
    584 
    585     /*
    586      * The package must have at least two elements. NOTE (March 2005): This
    587      * goes against the current ACPI spec which defines this object as a
    588      * package with one encoded DWORD element. However, existing practice
    589      * by BIOS vendors seems to be to have 2 or more elements, at least
    590      * one per sleep type (A/B).
    591      */
    592     else if (Info->ReturnObject->Package.Count < 2)
    593     {
    594         ACPI_ERROR ((AE_INFO,
    595             "Sleep State return package does not have at least two elements"));
    596         Status = AE_AML_NO_OPERAND;
    597     }
    598 
    599     /* The first two elements must both be of type Integer */
    600 
    601     else if (((Info->ReturnObject->Package.Elements[0])->Common.Type
    602                 != ACPI_TYPE_INTEGER) ||
    603              ((Info->ReturnObject->Package.Elements[1])->Common.Type
    604                 != ACPI_TYPE_INTEGER))
    605     {
    606         ACPI_ERROR ((AE_INFO,
    607             "Sleep State return package elements are not both Integers "
    608             "(%s, %s)",
    609             AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
    610             AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
    611         Status = AE_AML_OPERAND_TYPE;
    612     }
    613     else
    614     {
    615         /* Valid _Sx_ package size, type, and value */
    616 
    617         *SleepTypeA = (UINT8)
    618             (Info->ReturnObject->Package.Elements[0])->Integer.Value;
    619         *SleepTypeB = (UINT8)
    620             (Info->ReturnObject->Package.Elements[1])->Integer.Value;
    621     }
    622 
    623     if (ACPI_FAILURE (Status))
    624     {
    625         ACPI_EXCEPTION ((AE_INFO, Status,
    626             "While evaluating SleepState [%s], bad Sleep object %p type %s",
    627             Info->Pathname, Info->ReturnObject,
    628             AcpiUtGetObjectTypeName (Info->ReturnObject)));
    629     }
    630 
    631     AcpiUtRemoveReference (Info->ReturnObject);
    632 
    633 Cleanup:
    634     ACPI_FREE (Info);
    635     return_ACPI_STATUS (Status);
    636 }
    637 
    638 ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
    639