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)