1 2 /****************************************************************************** 3 * 4 * Module Name: hwxface - Public ACPICA hardware interfaces 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2012, 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 <contrib/dev/acpica/include/acpi.h> 46 #include <contrib/dev/acpica/include/accommon.h> 47 #include <contrib/dev/acpica/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 /* Initialize entire 64-bit return value to zero */ 158 159 *ReturnValue = 0; 160 Value = 0; 161 162 /* 163 * Two address spaces supported: Memory or IO. PCI_Config is 164 * not supported here because the GAS structure is insufficient 165 */ 166 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 167 { 168 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) 169 Address, ReturnValue, Reg->BitWidth); 170 if (ACPI_FAILURE (Status)) 171 { 172 return (Status); 173 } 174 } 175 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 176 { 177 Width = Reg->BitWidth; 178 if (Width == 64) 179 { 180 Width = 32; /* Break into two 32-bit transfers */ 181 } 182 183 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 184 Address, &Value, Width); 185 if (ACPI_FAILURE (Status)) 186 { 187 return (Status); 188 } 189 *ReturnValue = Value; 190 191 if (Reg->BitWidth == 64) 192 { 193 /* Read the top 32 bits */ 194 195 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 196 (Address + 4), &Value, 32); 197 if (ACPI_FAILURE (Status)) 198 { 199 return (Status); 200 } 201 *ReturnValue |= ((UINT64) Value << 32); 202 } 203 } 204 205 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 206 "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", 207 ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth, 208 ACPI_FORMAT_UINT64 (Address), 209 AcpiUtGetRegionName (Reg->SpaceId))); 210 211 return (Status); 212 } 213 214 ACPI_EXPORT_SYMBOL (AcpiRead) 215 216 217 /****************************************************************************** 218 * 219 * FUNCTION: AcpiWrite 220 * 221 * PARAMETERS: Value - Value to be written 222 * Reg - GAS register structure 223 * 224 * RETURN: Status 225 * 226 * DESCRIPTION: Write to either memory or IO space. 227 * 228 ******************************************************************************/ 229 230 ACPI_STATUS 231 AcpiWrite ( 232 UINT64 Value, 233 ACPI_GENERIC_ADDRESS *Reg) 234 { 235 UINT32 Width; 236 UINT64 Address; 237 ACPI_STATUS Status; 238 239 240 ACPI_FUNCTION_NAME (AcpiWrite); 241 242 243 /* Validate contents of the GAS register. Allow 64-bit transfers */ 244 245 Status = AcpiHwValidateRegister (Reg, 64, &Address); 246 if (ACPI_FAILURE (Status)) 247 { 248 return (Status); 249 } 250 251 /* 252 * Two address spaces supported: Memory or IO. PCI_Config is 253 * not supported here because the GAS structure is insufficient 254 */ 255 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 256 { 257 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) 258 Address, Value, Reg->BitWidth); 259 if (ACPI_FAILURE (Status)) 260 { 261 return (Status); 262 } 263 } 264 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 265 { 266 Width = Reg->BitWidth; 267 if (Width == 64) 268 { 269 Width = 32; /* Break into two 32-bit transfers */ 270 } 271 272 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 273 Address, ACPI_LODWORD (Value), Width); 274 if (ACPI_FAILURE (Status)) 275 { 276 return (Status); 277 } 278 279 if (Reg->BitWidth == 64) 280 { 281 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 282 (Address + 4), ACPI_HIDWORD (Value), 32); 283 if (ACPI_FAILURE (Status)) 284 { 285 return (Status); 286 } 287 } 288 } 289 290 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 291 "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", 292 ACPI_FORMAT_UINT64 (Value), Reg->BitWidth, 293 ACPI_FORMAT_UINT64 (Address), 294 AcpiUtGetRegionName (Reg->SpaceId))); 295 296 return (Status); 297 } 298 299 ACPI_EXPORT_SYMBOL (AcpiWrite) 300 301 302 #if (!ACPI_REDUCED_HARDWARE) 303 /******************************************************************************* 304 * 305 * FUNCTION: AcpiReadBitRegister 306 * 307 * PARAMETERS: RegisterId - ID of ACPI Bit Register to access 308 * ReturnValue - Value that was read from the register, 309 * normalized to bit position zero. 310 * 311 * RETURN: Status and the value read from the specified Register. Value 312 * returned is normalized to bit0 (is shifted all the way right) 313 * 314 * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock. 315 * 316 * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and 317 * PM2 Control. 318 * 319 * Note: The hardware lock is not required when reading the ACPI bit registers 320 * since almost all of them are single bit and it does not matter that 321 * the parent hardware register can be split across two physical 322 * registers. The only multi-bit field is SLP_TYP in the PM1 control 323 * register, but this field does not cross an 8-bit boundary (nor does 324 * it make much sense to actually read this field.) 325 * 326 ******************************************************************************/ 327 328 ACPI_STATUS 329 AcpiReadBitRegister ( 330 UINT32 RegisterId, 331 UINT32 *ReturnValue) 332 { 333 ACPI_BIT_REGISTER_INFO *BitRegInfo; 334 UINT32 RegisterValue; 335 UINT32 Value; 336 ACPI_STATUS Status; 337 338 339 ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId); 340 341 342 /* Get the info structure corresponding to the requested ACPI Register */ 343 344 BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 345 if (!BitRegInfo) 346 { 347 return_ACPI_STATUS (AE_BAD_PARAMETER); 348 } 349 350 /* Read the entire parent register */ 351 352 Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, 353 &RegisterValue); 354 if (ACPI_FAILURE (Status)) 355 { 356 return_ACPI_STATUS (Status); 357 } 358 359 /* Normalize the value that was read, mask off other bits */ 360 361 Value = ((RegisterValue & BitRegInfo->AccessBitMask) 362 >> BitRegInfo->BitPosition); 363 364 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 365 "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n", 366 RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value)); 367 368 *ReturnValue = Value; 369 return_ACPI_STATUS (AE_OK); 370 } 371 372 ACPI_EXPORT_SYMBOL (AcpiReadBitRegister) 373 374 375 /******************************************************************************* 376 * 377 * FUNCTION: AcpiWriteBitRegister 378 * 379 * PARAMETERS: RegisterId - ID of ACPI Bit Register to access 380 * Value - Value to write to the register, in bit 381 * position zero. The bit is automaticallly 382 * shifted to the correct position. 383 * 384 * RETURN: Status 385 * 386 * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock 387 * since most operations require a read/modify/write sequence. 388 * 389 * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and 390 * PM2 Control. 391 * 392 * Note that at this level, the fact that there may be actually two 393 * hardware registers (A and B - and B may not exist) is abstracted. 394 * 395 ******************************************************************************/ 396 397 ACPI_STATUS 398 AcpiWriteBitRegister ( 399 UINT32 RegisterId, 400 UINT32 Value) 401 { 402 ACPI_BIT_REGISTER_INFO *BitRegInfo; 403 ACPI_CPU_FLAGS LockFlags; 404 UINT32 RegisterValue; 405 ACPI_STATUS Status = AE_OK; 406 407 408 ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId); 409 410 411 /* Get the info structure corresponding to the requested ACPI Register */ 412 413 BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 414 if (!BitRegInfo) 415 { 416 return_ACPI_STATUS (AE_BAD_PARAMETER); 417 } 418 419 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 420 421 /* 422 * At this point, we know that the parent register is one of the 423 * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control 424 */ 425 if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS) 426 { 427 /* 428 * 1) Case for PM1 Enable, PM1 Control, and PM2 Control 429 * 430 * Perform a register read to preserve the bits that we are not 431 * interested in 432 */ 433 Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, 434 &RegisterValue); 435 if (ACPI_FAILURE (Status)) 436 { 437 goto UnlockAndExit; 438 } 439 440 /* 441 * Insert the input bit into the value that was just read 442 * and write the register 443 */ 444 ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 445 BitRegInfo->AccessBitMask, Value); 446 447 Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister, 448 RegisterValue); 449 } 450 else 451 { 452 /* 453 * 2) Case for PM1 Status 454 * 455 * The Status register is different from the rest. Clear an event 456 * by writing 1, writing 0 has no effect. So, the only relevant 457 * information is the single bit we're interested in, all others 458 * should be written as 0 so they will be left unchanged. 459 */ 460 RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value, 461 BitRegInfo->BitPosition, BitRegInfo->AccessBitMask); 462 463 /* No need to write the register if value is all zeros */ 464 465 if (RegisterValue) 466 { 467 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, 468 RegisterValue); 469 } 470 } 471 472 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 473 "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n", 474 RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue)); 475 476 477 UnlockAndExit: 478 479 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 480 return_ACPI_STATUS (Status); 481 } 482 483 ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister) 484 485 #endif /* !ACPI_REDUCED_HARDWARE */ 486 487 488 /******************************************************************************* 489 * 490 * FUNCTION: AcpiGetSleepTypeData 491 * 492 * PARAMETERS: SleepState - Numeric sleep state 493 * *SleepTypeA - Where SLP_TYPa is returned 494 * *SleepTypeB - Where SLP_TYPb is returned 495 * 496 * RETURN: Status - ACPI status 497 * 498 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep 499 * state. 500 * 501 ******************************************************************************/ 502 503 ACPI_STATUS 504 AcpiGetSleepTypeData ( 505 UINT8 SleepState, 506 UINT8 *SleepTypeA, 507 UINT8 *SleepTypeB) 508 { 509 ACPI_STATUS Status = AE_OK; 510 ACPI_EVALUATE_INFO *Info; 511 512 513 ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData); 514 515 516 /* Validate parameters */ 517 518 if ((SleepState > ACPI_S_STATES_MAX) || 519 !SleepTypeA || 520 !SleepTypeB) 521 { 522 return_ACPI_STATUS (AE_BAD_PARAMETER); 523 } 524 525 /* Allocate the evaluation information block */ 526 527 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 528 if (!Info) 529 { 530 return_ACPI_STATUS (AE_NO_MEMORY); 531 } 532 533 Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]); 534 535 /* Evaluate the namespace object containing the values for this state */ 536 537 Status = AcpiNsEvaluate (Info); 538 if (ACPI_FAILURE (Status)) 539 { 540 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 541 "%s while evaluating SleepState [%s]\n", 542 AcpiFormatException (Status), Info->Pathname)); 543 544 goto Cleanup; 545 } 546 547 /* Must have a return object */ 548 549 if (!Info->ReturnObject) 550 { 551 ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]", 552 Info->Pathname)); 553 Status = AE_NOT_EXIST; 554 } 555 556 /* It must be of type Package */ 557 558 else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) 559 { 560 ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package")); 561 Status = AE_AML_OPERAND_TYPE; 562 } 563 564 /* 565 * The package must have at least two elements. NOTE (March 2005): This 566 * goes against the current ACPI spec which defines this object as a 567 * package with one encoded DWORD element. However, existing practice 568 * by BIOS vendors seems to be to have 2 or more elements, at least 569 * one per sleep type (A/B). 570 */ 571 else if (Info->ReturnObject->Package.Count < 2) 572 { 573 ACPI_ERROR ((AE_INFO, 574 "Sleep State return package does not have at least two elements")); 575 Status = AE_AML_NO_OPERAND; 576 } 577 578 /* The first two elements must both be of type Integer */ 579 580 else if (((Info->ReturnObject->Package.Elements[0])->Common.Type 581 != ACPI_TYPE_INTEGER) || 582 ((Info->ReturnObject->Package.Elements[1])->Common.Type 583 != ACPI_TYPE_INTEGER)) 584 { 585 ACPI_ERROR ((AE_INFO, 586 "Sleep State return package elements are not both Integers " 587 "(%s, %s)", 588 AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]), 589 AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1]))); 590 Status = AE_AML_OPERAND_TYPE; 591 } 592 else 593 { 594 /* Valid _Sx_ package size, type, and value */ 595 596 *SleepTypeA = (UINT8) 597 (Info->ReturnObject->Package.Elements[0])->Integer.Value; 598 *SleepTypeB = (UINT8) 599 (Info->ReturnObject->Package.Elements[1])->Integer.Value; 600 } 601 602 if (ACPI_FAILURE (Status)) 603 { 604 ACPI_EXCEPTION ((AE_INFO, Status, 605 "While evaluating SleepState [%s], bad Sleep object %p type %s", 606 Info->Pathname, Info->ReturnObject, 607 AcpiUtGetObjectTypeName (Info->ReturnObject))); 608 } 609 610 AcpiUtRemoveReference (Info->ReturnObject); 611 612 Cleanup: 613 ACPI_FREE (Info); 614 return_ACPI_STATUS (Status); 615 } 616 617 ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData) 618