root/drivers/acpi/acpica/hwregs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_hw_validate_register
  3. acpi_hw_read
  4. acpi_hw_write
  5. acpi_hw_clear_acpi_status
  6. acpi_hw_get_bit_register_info
  7. acpi_hw_write_pm1_control
  8. acpi_hw_register_read
  9. acpi_hw_register_write
  10. acpi_hw_read_multiple
  11. acpi_hw_write_multiple

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /*******************************************************************************
   3  *
   4  * Module Name: hwregs - Read/write access functions for the various ACPI
   5  *                       control and status registers.
   6  *
   7  ******************************************************************************/
   8 
   9 #include <acpi/acpi.h>
  10 #include "accommon.h"
  11 #include "acevents.h"
  12 
  13 #define _COMPONENT          ACPI_HARDWARE
  14 ACPI_MODULE_NAME("hwregs")
  15 
  16 #if (!ACPI_REDUCED_HARDWARE)
  17 /* Local Prototypes */
  18 static u8
  19 acpi_hw_get_access_bit_width(u64 address,
  20                              struct acpi_generic_address *reg,
  21                              u8 max_bit_width);
  22 
  23 static acpi_status
  24 acpi_hw_read_multiple(u32 *value,
  25                       struct acpi_generic_address *register_a,
  26                       struct acpi_generic_address *register_b);
  27 
  28 static acpi_status
  29 acpi_hw_write_multiple(u32 value,
  30                        struct acpi_generic_address *register_a,
  31                        struct acpi_generic_address *register_b);
  32 
  33 #endif                          /* !ACPI_REDUCED_HARDWARE */
  34 
  35 /******************************************************************************
  36  *
  37  * FUNCTION:    acpi_hw_get_access_bit_width
  38  *
  39  * PARAMETERS:  address             - GAS register address
  40  *              reg                 - GAS register structure
  41  *              max_bit_width       - Max bit_width supported (32 or 64)
  42  *
  43  * RETURN:      Status
  44  *
  45  * DESCRIPTION: Obtain optimal access bit width
  46  *
  47  ******************************************************************************/
  48 
  49 static u8
  50 acpi_hw_get_access_bit_width(u64 address,
  51                              struct acpi_generic_address *reg, u8 max_bit_width)
  52 {
  53         u8 access_bit_width;
  54 
  55         /*
  56          * GAS format "register", used by FADT:
  57          *  1. Detected if bit_offset is 0 and bit_width is 8/16/32/64;
  58          *  2. access_size field is ignored and bit_width field is used for
  59          *     determining the boundary of the IO accesses.
  60          * GAS format "region", used by APEI registers:
  61          *  1. Detected if bit_offset is not 0 or bit_width is not 8/16/32/64;
  62          *  2. access_size field is used for determining the boundary of the
  63          *     IO accesses;
  64          *  3. bit_offset/bit_width fields are used to describe the "region".
  65          *
  66          * Note: This algorithm assumes that the "Address" fields should always
  67          *       contain aligned values.
  68          */
  69         if (!reg->bit_offset && reg->bit_width &&
  70             ACPI_IS_POWER_OF_TWO(reg->bit_width) &&
  71             ACPI_IS_ALIGNED(reg->bit_width, 8)) {
  72                 access_bit_width = reg->bit_width;
  73         } else if (reg->access_width) {
  74                 access_bit_width = ACPI_ACCESS_BIT_WIDTH(reg->access_width);
  75         } else {
  76                 access_bit_width =
  77                     ACPI_ROUND_UP_POWER_OF_TWO_8(reg->bit_offset +
  78                                                  reg->bit_width);
  79                 if (access_bit_width <= 8) {
  80                         access_bit_width = 8;
  81                 } else {
  82                         while (!ACPI_IS_ALIGNED(address, access_bit_width >> 3)) {
  83                                 access_bit_width >>= 1;
  84                         }
  85                 }
  86         }
  87 
  88         /* Maximum IO port access bit width is 32 */
  89 
  90         if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
  91                 max_bit_width = 32;
  92         }
  93 
  94         /*
  95          * Return access width according to the requested maximum access bit width,
  96          * as the caller should know the format of the register and may enforce
  97          * a 32-bit accesses.
  98          */
  99         if (access_bit_width < max_bit_width) {
 100                 return (access_bit_width);
 101         }
 102         return (max_bit_width);
 103 }
 104 
 105 /******************************************************************************
 106  *
 107  * FUNCTION:    acpi_hw_validate_register
 108  *
 109  * PARAMETERS:  reg                 - GAS register structure
 110  *              max_bit_width       - Max bit_width supported (32 or 64)
 111  *              address             - Pointer to where the gas->address
 112  *                                    is returned
 113  *
 114  * RETURN:      Status
 115  *
 116  * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
 117  *              pointer, Address, space_id, bit_width, and bit_offset.
 118  *
 119  ******************************************************************************/
 120 
 121 acpi_status
 122 acpi_hw_validate_register(struct acpi_generic_address *reg,
 123                           u8 max_bit_width, u64 *address)
 124 {
 125         u8 bit_width;
 126         u8 access_width;
 127 
 128         /* Must have a valid pointer to a GAS structure */
 129 
 130         if (!reg) {
 131                 return (AE_BAD_PARAMETER);
 132         }
 133 
 134         /*
 135          * Copy the target address. This handles possible alignment issues.
 136          * Address must not be null. A null address also indicates an optional
 137          * ACPI register that is not supported, so no error message.
 138          */
 139         ACPI_MOVE_64_TO_64(address, &reg->address);
 140         if (!(*address)) {
 141                 return (AE_BAD_ADDRESS);
 142         }
 143 
 144         /* Validate the space_ID */
 145 
 146         if ((reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
 147             (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
 148                 ACPI_ERROR((AE_INFO,
 149                             "Unsupported address space: 0x%X", reg->space_id));
 150                 return (AE_SUPPORT);
 151         }
 152 
 153         /* Validate the access_width */
 154 
 155         if (reg->access_width > 4) {
 156                 ACPI_ERROR((AE_INFO,
 157                             "Unsupported register access width: 0x%X",
 158                             reg->access_width));
 159                 return (AE_SUPPORT);
 160         }
 161 
 162         /* Validate the bit_width, convert access_width into number of bits */
 163 
 164         access_width =
 165             acpi_hw_get_access_bit_width(*address, reg, max_bit_width);
 166         bit_width =
 167             ACPI_ROUND_UP(reg->bit_offset + reg->bit_width, access_width);
 168         if (max_bit_width < bit_width) {
 169                 ACPI_WARNING((AE_INFO,
 170                               "Requested bit width 0x%X is smaller than register bit width 0x%X",
 171                               max_bit_width, bit_width));
 172                 return (AE_SUPPORT);
 173         }
 174 
 175         return (AE_OK);
 176 }
 177 
 178 /******************************************************************************
 179  *
 180  * FUNCTION:    acpi_hw_read
 181  *
 182  * PARAMETERS:  value               - Where the value is returned
 183  *              reg                 - GAS register structure
 184  *
 185  * RETURN:      Status
 186  *
 187  * DESCRIPTION: Read from either memory or IO space. This is a 64-bit max
 188  *              version of acpi_read.
 189  *
 190  * LIMITATIONS: <These limitations also apply to acpi_hw_write>
 191  *      space_ID must be system_memory or system_IO.
 192  *
 193  ******************************************************************************/
 194 
 195 acpi_status acpi_hw_read(u64 *value, struct acpi_generic_address *reg)
 196 {
 197         u64 address;
 198         u8 access_width;
 199         u32 bit_width;
 200         u8 bit_offset;
 201         u64 value64;
 202         u32 value32;
 203         u8 index;
 204         acpi_status status;
 205 
 206         ACPI_FUNCTION_NAME(hw_read);
 207 
 208         /* Validate contents of the GAS register */
 209 
 210         status = acpi_hw_validate_register(reg, 64, &address);
 211         if (ACPI_FAILURE(status)) {
 212                 return (status);
 213         }
 214 
 215         /*
 216          * Initialize entire 64-bit return value to zero, convert access_width
 217          * into number of bits based
 218          */
 219         *value = 0;
 220         access_width = acpi_hw_get_access_bit_width(address, reg, 64);
 221         bit_width = reg->bit_offset + reg->bit_width;
 222         bit_offset = reg->bit_offset;
 223 
 224         /*
 225          * Two address spaces supported: Memory or IO. PCI_Config is
 226          * not supported here because the GAS structure is insufficient
 227          */
 228         index = 0;
 229         while (bit_width) {
 230                 if (bit_offset >= access_width) {
 231                         value64 = 0;
 232                         bit_offset -= access_width;
 233                 } else {
 234                         if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
 235                                 status =
 236                                     acpi_os_read_memory((acpi_physical_address)
 237                                                         address +
 238                                                         index *
 239                                                         ACPI_DIV_8
 240                                                         (access_width),
 241                                                         &value64, access_width);
 242                         } else {        /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
 243 
 244                                 status = acpi_hw_read_port((acpi_io_address)
 245                                                            address +
 246                                                            index *
 247                                                            ACPI_DIV_8
 248                                                            (access_width),
 249                                                            &value32,
 250                                                            access_width);
 251                                 value64 = (u64)value32;
 252                         }
 253                 }
 254 
 255                 /*
 256                  * Use offset style bit writes because "Index * AccessWidth" is
 257                  * ensured to be less than 64-bits by acpi_hw_validate_register().
 258                  */
 259                 ACPI_SET_BITS(value, index * access_width,
 260                               ACPI_MASK_BITS_ABOVE_64(access_width), value64);
 261 
 262                 bit_width -=
 263                     bit_width > access_width ? access_width : bit_width;
 264                 index++;
 265         }
 266 
 267         ACPI_DEBUG_PRINT((ACPI_DB_IO,
 268                           "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
 269                           ACPI_FORMAT_UINT64(*value), access_width,
 270                           ACPI_FORMAT_UINT64(address),
 271                           acpi_ut_get_region_name(reg->space_id)));
 272 
 273         return (status);
 274 }
 275 
 276 /******************************************************************************
 277  *
 278  * FUNCTION:    acpi_hw_write
 279  *
 280  * PARAMETERS:  value               - Value to be written
 281  *              reg                 - GAS register structure
 282  *
 283  * RETURN:      Status
 284  *
 285  * DESCRIPTION: Write to either memory or IO space. This is a 64-bit max
 286  *              version of acpi_write.
 287  *
 288  ******************************************************************************/
 289 
 290 acpi_status acpi_hw_write(u64 value, struct acpi_generic_address *reg)
 291 {
 292         u64 address;
 293         u8 access_width;
 294         u32 bit_width;
 295         u8 bit_offset;
 296         u64 value64;
 297         u8 index;
 298         acpi_status status;
 299 
 300         ACPI_FUNCTION_NAME(hw_write);
 301 
 302         /* Validate contents of the GAS register */
 303 
 304         status = acpi_hw_validate_register(reg, 64, &address);
 305         if (ACPI_FAILURE(status)) {
 306                 return (status);
 307         }
 308 
 309         /* Convert access_width into number of bits based */
 310 
 311         access_width = acpi_hw_get_access_bit_width(address, reg, 64);
 312         bit_width = reg->bit_offset + reg->bit_width;
 313         bit_offset = reg->bit_offset;
 314 
 315         /*
 316          * Two address spaces supported: Memory or IO. PCI_Config is
 317          * not supported here because the GAS structure is insufficient
 318          */
 319         index = 0;
 320         while (bit_width) {
 321                 /*
 322                  * Use offset style bit reads because "Index * AccessWidth" is
 323                  * ensured to be less than 64-bits by acpi_hw_validate_register().
 324                  */
 325                 value64 = ACPI_GET_BITS(&value, index * access_width,
 326                                         ACPI_MASK_BITS_ABOVE_64(access_width));
 327 
 328                 if (bit_offset >= access_width) {
 329                         bit_offset -= access_width;
 330                 } else {
 331                         if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
 332                                 status =
 333                                     acpi_os_write_memory((acpi_physical_address)
 334                                                          address +
 335                                                          index *
 336                                                          ACPI_DIV_8
 337                                                          (access_width),
 338                                                          value64, access_width);
 339                         } else {        /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
 340 
 341                                 status = acpi_hw_write_port((acpi_io_address)
 342                                                             address +
 343                                                             index *
 344                                                             ACPI_DIV_8
 345                                                             (access_width),
 346                                                             (u32)value64,
 347                                                             access_width);
 348                         }
 349                 }
 350 
 351                 /*
 352                  * Index * access_width is ensured to be less than 32-bits by
 353                  * acpi_hw_validate_register().
 354                  */
 355                 bit_width -=
 356                     bit_width > access_width ? access_width : bit_width;
 357                 index++;
 358         }
 359 
 360         ACPI_DEBUG_PRINT((ACPI_DB_IO,
 361                           "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
 362                           ACPI_FORMAT_UINT64(value), access_width,
 363                           ACPI_FORMAT_UINT64(address),
 364                           acpi_ut_get_region_name(reg->space_id)));
 365 
 366         return (status);
 367 }
 368 
 369 #if (!ACPI_REDUCED_HARDWARE)
 370 /*******************************************************************************
 371  *
 372  * FUNCTION:    acpi_hw_clear_acpi_status
 373  *
 374  * PARAMETERS:  None
 375  *
 376  * RETURN:      Status
 377  *
 378  * DESCRIPTION: Clears all fixed and general purpose status bits
 379  *
 380  ******************************************************************************/
 381 
 382 acpi_status acpi_hw_clear_acpi_status(void)
 383 {
 384         acpi_status status;
 385         acpi_cpu_flags lock_flags = 0;
 386 
 387         ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
 388 
 389         ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
 390                           ACPI_BITMASK_ALL_FIXED_STATUS,
 391                           ACPI_FORMAT_UINT64(acpi_gbl_xpm1a_status.address)));
 392 
 393         lock_flags = acpi_os_acquire_raw_lock(acpi_gbl_hardware_lock);
 394 
 395         /* Clear the fixed events in PM1 A/B */
 396 
 397         status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
 398                                         ACPI_BITMASK_ALL_FIXED_STATUS);
 399 
 400         acpi_os_release_raw_lock(acpi_gbl_hardware_lock, lock_flags);
 401 
 402         if (ACPI_FAILURE(status)) {
 403                 goto exit;
 404         }
 405 
 406         /* Clear the GPE Bits in all GPE registers in all GPE blocks */
 407 
 408         status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
 409 
 410 exit:
 411         return_ACPI_STATUS(status);
 412 }
 413 
 414 /*******************************************************************************
 415  *
 416  * FUNCTION:    acpi_hw_get_bit_register_info
 417  *
 418  * PARAMETERS:  register_id         - Index of ACPI Register to access
 419  *
 420  * RETURN:      The bitmask to be used when accessing the register
 421  *
 422  * DESCRIPTION: Map register_id into a register bitmask.
 423  *
 424  ******************************************************************************/
 425 
 426 struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
 427 {
 428         ACPI_FUNCTION_ENTRY();
 429 
 430         if (register_id > ACPI_BITREG_MAX) {
 431                 ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: 0x%X",
 432                             register_id));
 433                 return (NULL);
 434         }
 435 
 436         return (&acpi_gbl_bit_register_info[register_id]);
 437 }
 438 
 439 /******************************************************************************
 440  *
 441  * FUNCTION:    acpi_hw_write_pm1_control
 442  *
 443  * PARAMETERS:  pm1a_control        - Value to be written to PM1A control
 444  *              pm1b_control        - Value to be written to PM1B control
 445  *
 446  * RETURN:      Status
 447  *
 448  * DESCRIPTION: Write the PM1 A/B control registers. These registers are
 449  *              different than than the PM1 A/B status and enable registers
 450  *              in that different values can be written to the A/B registers.
 451  *              Most notably, the SLP_TYP bits can be different, as per the
 452  *              values returned from the _Sx predefined methods.
 453  *
 454  ******************************************************************************/
 455 
 456 acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control)
 457 {
 458         acpi_status status;
 459 
 460         ACPI_FUNCTION_TRACE(hw_write_pm1_control);
 461 
 462         status =
 463             acpi_hw_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block);
 464         if (ACPI_FAILURE(status)) {
 465                 return_ACPI_STATUS(status);
 466         }
 467 
 468         if (acpi_gbl_FADT.xpm1b_control_block.address) {
 469                 status =
 470                     acpi_hw_write(pm1b_control,
 471                                   &acpi_gbl_FADT.xpm1b_control_block);
 472         }
 473         return_ACPI_STATUS(status);
 474 }
 475 
 476 /******************************************************************************
 477  *
 478  * FUNCTION:    acpi_hw_register_read
 479  *
 480  * PARAMETERS:  register_id         - ACPI Register ID
 481  *              return_value        - Where the register value is returned
 482  *
 483  * RETURN:      Status and the value read.
 484  *
 485  * DESCRIPTION: Read from the specified ACPI register
 486  *
 487  ******************************************************************************/
 488 acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value)
 489 {
 490         u32 value = 0;
 491         u64 value64;
 492         acpi_status status;
 493 
 494         ACPI_FUNCTION_TRACE(hw_register_read);
 495 
 496         switch (register_id) {
 497         case ACPI_REGISTER_PM1_STATUS:  /* PM1 A/B: 16-bit access each */
 498 
 499                 status = acpi_hw_read_multiple(&value,
 500                                                &acpi_gbl_xpm1a_status,
 501                                                &acpi_gbl_xpm1b_status);
 502                 break;
 503 
 504         case ACPI_REGISTER_PM1_ENABLE:  /* PM1 A/B: 16-bit access each */
 505 
 506                 status = acpi_hw_read_multiple(&value,
 507                                                &acpi_gbl_xpm1a_enable,
 508                                                &acpi_gbl_xpm1b_enable);
 509                 break;
 510 
 511         case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
 512 
 513                 status = acpi_hw_read_multiple(&value,
 514                                                &acpi_gbl_FADT.
 515                                                xpm1a_control_block,
 516                                                &acpi_gbl_FADT.
 517                                                xpm1b_control_block);
 518 
 519                 /*
 520                  * Zero the write-only bits. From the ACPI specification, "Hardware
 521                  * Write-Only Bits": "Upon reads to registers with write-only bits,
 522                  * software masks out all write-only bits."
 523                  */
 524                 value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
 525                 break;
 526 
 527         case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
 528 
 529                 status =
 530                     acpi_hw_read(&value64, &acpi_gbl_FADT.xpm2_control_block);
 531                 if (ACPI_SUCCESS(status)) {
 532                         value = (u32)value64;
 533                 }
 534                 break;
 535 
 536         case ACPI_REGISTER_PM_TIMER:    /* 32-bit access */
 537 
 538                 status = acpi_hw_read(&value64, &acpi_gbl_FADT.xpm_timer_block);
 539                 if (ACPI_SUCCESS(status)) {
 540                         value = (u32)value64;
 541                 }
 542 
 543                 break;
 544 
 545         case ACPI_REGISTER_SMI_COMMAND_BLOCK:   /* 8-bit access */
 546 
 547                 status =
 548                     acpi_hw_read_port(acpi_gbl_FADT.smi_command, &value, 8);
 549                 break;
 550 
 551         default:
 552 
 553                 ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id));
 554                 status = AE_BAD_PARAMETER;
 555                 break;
 556         }
 557 
 558         if (ACPI_SUCCESS(status)) {
 559                 *return_value = (u32)value;
 560         }
 561 
 562         return_ACPI_STATUS(status);
 563 }
 564 
 565 /******************************************************************************
 566  *
 567  * FUNCTION:    acpi_hw_register_write
 568  *
 569  * PARAMETERS:  register_id         - ACPI Register ID
 570  *              value               - The value to write
 571  *
 572  * RETURN:      Status
 573  *
 574  * DESCRIPTION: Write to the specified ACPI register
 575  *
 576  * NOTE: In accordance with the ACPI specification, this function automatically
 577  * preserves the value of the following bits, meaning that these bits cannot be
 578  * changed via this interface:
 579  *
 580  * PM1_CONTROL[0] = SCI_EN
 581  * PM1_CONTROL[9]
 582  * PM1_STATUS[11]
 583  *
 584  * ACPI References:
 585  * 1) Hardware Ignored Bits: When software writes to a register with ignored
 586  *      bit fields, it preserves the ignored bit fields
 587  * 2) SCI_EN: OSPM always preserves this bit position
 588  *
 589  ******************************************************************************/
 590 
 591 acpi_status acpi_hw_register_write(u32 register_id, u32 value)
 592 {
 593         acpi_status status;
 594         u32 read_value;
 595         u64 read_value64;
 596 
 597         ACPI_FUNCTION_TRACE(hw_register_write);
 598 
 599         switch (register_id) {
 600         case ACPI_REGISTER_PM1_STATUS:  /* PM1 A/B: 16-bit access each */
 601                 /*
 602                  * Handle the "ignored" bit in PM1 Status. According to the ACPI
 603                  * specification, ignored bits are to be preserved when writing.
 604                  * Normally, this would mean a read/modify/write sequence. However,
 605                  * preserving a bit in the status register is different. Writing a
 606                  * one clears the status, and writing a zero preserves the status.
 607                  * Therefore, we must always write zero to the ignored bit.
 608                  *
 609                  * This behavior is clarified in the ACPI 4.0 specification.
 610                  */
 611                 value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
 612 
 613                 status = acpi_hw_write_multiple(value,
 614                                                 &acpi_gbl_xpm1a_status,
 615                                                 &acpi_gbl_xpm1b_status);
 616                 break;
 617 
 618         case ACPI_REGISTER_PM1_ENABLE:  /* PM1 A/B: 16-bit access each */
 619 
 620                 status = acpi_hw_write_multiple(value,
 621                                                 &acpi_gbl_xpm1a_enable,
 622                                                 &acpi_gbl_xpm1b_enable);
 623                 break;
 624 
 625         case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
 626                 /*
 627                  * Perform a read first to preserve certain bits (per ACPI spec)
 628                  * Note: This includes SCI_EN, we never want to change this bit
 629                  */
 630                 status = acpi_hw_read_multiple(&read_value,
 631                                                &acpi_gbl_FADT.
 632                                                xpm1a_control_block,
 633                                                &acpi_gbl_FADT.
 634                                                xpm1b_control_block);
 635                 if (ACPI_FAILURE(status)) {
 636                         goto exit;
 637                 }
 638 
 639                 /* Insert the bits to be preserved */
 640 
 641                 ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
 642                                  read_value);
 643 
 644                 /* Now we can write the data */
 645 
 646                 status = acpi_hw_write_multiple(value,
 647                                                 &acpi_gbl_FADT.
 648                                                 xpm1a_control_block,
 649                                                 &acpi_gbl_FADT.
 650                                                 xpm1b_control_block);
 651                 break;
 652 
 653         case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
 654                 /*
 655                  * For control registers, all reserved bits must be preserved,
 656                  * as per the ACPI spec.
 657                  */
 658                 status =
 659                     acpi_hw_read(&read_value64,
 660                                  &acpi_gbl_FADT.xpm2_control_block);
 661                 if (ACPI_FAILURE(status)) {
 662                         goto exit;
 663                 }
 664                 read_value = (u32)read_value64;
 665 
 666                 /* Insert the bits to be preserved */
 667 
 668                 ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS,
 669                                  read_value);
 670 
 671                 status =
 672                     acpi_hw_write(value, &acpi_gbl_FADT.xpm2_control_block);
 673                 break;
 674 
 675         case ACPI_REGISTER_PM_TIMER:    /* 32-bit access */
 676 
 677                 status = acpi_hw_write(value, &acpi_gbl_FADT.xpm_timer_block);
 678                 break;
 679 
 680         case ACPI_REGISTER_SMI_COMMAND_BLOCK:   /* 8-bit access */
 681 
 682                 /* SMI_CMD is currently always in IO space */
 683 
 684                 status =
 685                     acpi_hw_write_port(acpi_gbl_FADT.smi_command, value, 8);
 686                 break;
 687 
 688         default:
 689 
 690                 ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id));
 691                 status = AE_BAD_PARAMETER;
 692                 break;
 693         }
 694 
 695 exit:
 696         return_ACPI_STATUS(status);
 697 }
 698 
 699 /******************************************************************************
 700  *
 701  * FUNCTION:    acpi_hw_read_multiple
 702  *
 703  * PARAMETERS:  value               - Where the register value is returned
 704  *              register_a           - First ACPI register (required)
 705  *              register_b           - Second ACPI register (optional)
 706  *
 707  * RETURN:      Status
 708  *
 709  * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
 710  *
 711  ******************************************************************************/
 712 
 713 static acpi_status
 714 acpi_hw_read_multiple(u32 *value,
 715                       struct acpi_generic_address *register_a,
 716                       struct acpi_generic_address *register_b)
 717 {
 718         u32 value_a = 0;
 719         u32 value_b = 0;
 720         u64 value64;
 721         acpi_status status;
 722 
 723         /* The first register is always required */
 724 
 725         status = acpi_hw_read(&value64, register_a);
 726         if (ACPI_FAILURE(status)) {
 727                 return (status);
 728         }
 729         value_a = (u32)value64;
 730 
 731         /* Second register is optional */
 732 
 733         if (register_b->address) {
 734                 status = acpi_hw_read(&value64, register_b);
 735                 if (ACPI_FAILURE(status)) {
 736                         return (status);
 737                 }
 738                 value_b = (u32)value64;
 739         }
 740 
 741         /*
 742          * OR the two return values together. No shifting or masking is necessary,
 743          * because of how the PM1 registers are defined in the ACPI specification:
 744          *
 745          * "Although the bits can be split between the two register blocks (each
 746          * register block has a unique pointer within the FADT), the bit positions
 747          * are maintained. The register block with unimplemented bits (that is,
 748          * those implemented in the other register block) always returns zeros,
 749          * and writes have no side effects"
 750          */
 751         *value = (value_a | value_b);
 752         return (AE_OK);
 753 }
 754 
 755 /******************************************************************************
 756  *
 757  * FUNCTION:    acpi_hw_write_multiple
 758  *
 759  * PARAMETERS:  value               - The value to write
 760  *              register_a           - First ACPI register (required)
 761  *              register_b           - Second ACPI register (optional)
 762  *
 763  * RETURN:      Status
 764  *
 765  * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
 766  *
 767  ******************************************************************************/
 768 
 769 static acpi_status
 770 acpi_hw_write_multiple(u32 value,
 771                        struct acpi_generic_address *register_a,
 772                        struct acpi_generic_address *register_b)
 773 {
 774         acpi_status status;
 775 
 776         /* The first register is always required */
 777 
 778         status = acpi_hw_write(value, register_a);
 779         if (ACPI_FAILURE(status)) {
 780                 return (status);
 781         }
 782 
 783         /*
 784          * Second register is optional
 785          *
 786          * No bit shifting or clearing is necessary, because of how the PM1
 787          * registers are defined in the ACPI specification:
 788          *
 789          * "Although the bits can be split between the two register blocks (each
 790          * register block has a unique pointer within the FADT), the bit positions
 791          * are maintained. The register block with unimplemented bits (that is,
 792          * those implemented in the other register block) always returns zeros,
 793          * and writes have no side effects"
 794          */
 795         if (register_b->address) {
 796                 status = acpi_hw_write(value, register_b);
 797         }
 798 
 799         return (status);
 800 }
 801 
 802 #endif                          /* !ACPI_REDUCED_HARDWARE */

/* [<][>][^][v][top][bottom][index][help] */