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