diff options
| author | Bob Moore <robert.moore@intel.com> | 2009-06-23 21:44:06 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2009-08-27 10:17:14 -0400 |
| commit | c6b5774caafa4c12b6019366e2fdaaff117e95a4 (patch) | |
| tree | 04a9439010ba84fd2ab787d6d43dbcebe2020a1e | |
| parent | f8d80cdf40fe4d2393159012b38ce9f85a488686 (diff) | |
ACPICA: Add 64-bit support to acpi_read and acpi_write
Needed by drivers for new ACPi tables. Internal versions of
these functions still use 32-bit max transfers, in order to
minimize disruption and stack use for the standard ACPI registers
(FADT-based).
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | drivers/acpi/acpica/achware.h | 8 | ||||
| -rw-r--r-- | drivers/acpi/acpica/evgpe.c | 8 | ||||
| -rw-r--r-- | drivers/acpi/acpica/evgpeblk.c | 4 | ||||
| -rw-r--r-- | drivers/acpi/acpica/hwgpe.c | 34 | ||||
| -rw-r--r-- | drivers/acpi/acpica/hwregs.c | 206 | ||||
| -rw-r--r-- | drivers/acpi/acpica/hwtimer.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/acpica/hwxface.c | 166 | ||||
| -rw-r--r-- | include/acpi/acpixf.h | 4 |
8 files changed, 327 insertions, 105 deletions
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 4afa3d8e0efb..36192f142fbb 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h | |||
| @@ -62,6 +62,14 @@ u32 acpi_hw_get_mode(void); | |||
| 62 | /* | 62 | /* |
| 63 | * hwregs - ACPI Register I/O | 63 | * hwregs - ACPI Register I/O |
| 64 | */ | 64 | */ |
| 65 | acpi_status | ||
| 66 | acpi_hw_validate_register(struct acpi_generic_address *reg, | ||
| 67 | u8 max_bit_width, u64 *address); | ||
| 68 | |||
| 69 | acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg); | ||
| 70 | |||
| 71 | acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg); | ||
| 72 | |||
| 65 | struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id); | 73 | struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id); |
| 66 | 74 | ||
| 67 | acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control); | 75 | acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control); |
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index b9d8ee69ca6c..afacf4416c73 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c | |||
| @@ -424,8 +424,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) | |||
| 424 | /* Read the Status Register */ | 424 | /* Read the Status Register */ |
| 425 | 425 | ||
| 426 | status = | 426 | status = |
| 427 | acpi_read(&status_reg, | 427 | acpi_hw_read(&status_reg, |
| 428 | &gpe_register_info->status_address); | 428 | &gpe_register_info->status_address); |
| 429 | if (ACPI_FAILURE(status)) { | 429 | if (ACPI_FAILURE(status)) { |
| 430 | goto unlock_and_exit; | 430 | goto unlock_and_exit; |
| 431 | } | 431 | } |
| @@ -433,8 +433,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) | |||
| 433 | /* Read the Enable Register */ | 433 | /* Read the Enable Register */ |
| 434 | 434 | ||
| 435 | status = | 435 | status = |
| 436 | acpi_read(&enable_reg, | 436 | acpi_hw_read(&enable_reg, |
| 437 | &gpe_register_info->enable_address); | 437 | &gpe_register_info->enable_address); |
| 438 | if (ACPI_FAILURE(status)) { | 438 | if (ACPI_FAILURE(status)) { |
| 439 | goto unlock_and_exit; | 439 | goto unlock_and_exit; |
| 440 | } | 440 | } |
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 7b3463639422..a60aaa7635f3 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c | |||
| @@ -843,14 +843,14 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) | |||
| 843 | 843 | ||
| 844 | /* Disable all GPEs within this register */ | 844 | /* Disable all GPEs within this register */ |
| 845 | 845 | ||
| 846 | status = acpi_write(0x00, &this_register->enable_address); | 846 | status = acpi_hw_write(0x00, &this_register->enable_address); |
| 847 | if (ACPI_FAILURE(status)) { | 847 | if (ACPI_FAILURE(status)) { |
| 848 | goto error_exit; | 848 | goto error_exit; |
| 849 | } | 849 | } |
| 850 | 850 | ||
| 851 | /* Clear any pending GPE events within this register */ | 851 | /* Clear any pending GPE events within this register */ |
| 852 | 852 | ||
| 853 | status = acpi_write(0xFF, &this_register->status_address); | 853 | status = acpi_hw_write(0xFF, &this_register->status_address); |
| 854 | if (ACPI_FAILURE(status)) { | 854 | if (ACPI_FAILURE(status)) { |
| 855 | goto error_exit; | 855 | goto error_exit; |
| 856 | } | 856 | } |
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index d3b7e37c9eed..c28c41b3180b 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c | |||
| @@ -82,7 +82,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
| 82 | 82 | ||
| 83 | /* Get current value of the enable register that contains this GPE */ | 83 | /* Get current value of the enable register that contains this GPE */ |
| 84 | 84 | ||
| 85 | status = acpi_read(&enable_mask, &gpe_register_info->enable_address); | 85 | status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address); |
| 86 | if (ACPI_FAILURE(status)) { | 86 | if (ACPI_FAILURE(status)) { |
| 87 | return (status); | 87 | return (status); |
| 88 | } | 88 | } |
| @@ -95,7 +95,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
| 95 | 95 | ||
| 96 | /* Write the updated enable mask */ | 96 | /* Write the updated enable mask */ |
| 97 | 97 | ||
| 98 | status = acpi_write(enable_mask, &gpe_register_info->enable_address); | 98 | status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address); |
| 99 | return (status); | 99 | return (status); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| @@ -130,8 +130,8 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info) | |||
| 130 | 130 | ||
| 131 | /* Write the entire GPE (runtime) enable register */ | 131 | /* Write the entire GPE (runtime) enable register */ |
| 132 | 132 | ||
| 133 | status = acpi_write(gpe_register_info->enable_for_run, | 133 | status = acpi_hw_write(gpe_register_info->enable_for_run, |
| 134 | &gpe_register_info->enable_address); | 134 | &gpe_register_info->enable_address); |
| 135 | 135 | ||
| 136 | return (status); | 136 | return (status); |
| 137 | } | 137 | } |
| @@ -163,8 +163,8 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) | |||
| 163 | * Write a one to the appropriate bit in the status register to | 163 | * Write a one to the appropriate bit in the status register to |
| 164 | * clear this GPE. | 164 | * clear this GPE. |
| 165 | */ | 165 | */ |
| 166 | status = acpi_write(register_bit, | 166 | status = acpi_hw_write(register_bit, |
| 167 | &gpe_event_info->register_info->status_address); | 167 | &gpe_event_info->register_info->status_address); |
| 168 | 168 | ||
| 169 | return (status); | 169 | return (status); |
| 170 | } | 170 | } |
| @@ -222,7 +222,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, | |||
| 222 | 222 | ||
| 223 | /* GPE currently active (status bit == 1)? */ | 223 | /* GPE currently active (status bit == 1)? */ |
| 224 | 224 | ||
| 225 | status = acpi_read(&in_byte, &gpe_register_info->status_address); | 225 | status = acpi_hw_read(&in_byte, &gpe_register_info->status_address); |
| 226 | if (ACPI_FAILURE(status)) { | 226 | if (ACPI_FAILURE(status)) { |
| 227 | goto unlock_and_exit; | 227 | goto unlock_and_exit; |
| 228 | } | 228 | } |
| @@ -266,8 +266,8 @@ acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 266 | /* Disable all GPEs in this register */ | 266 | /* Disable all GPEs in this register */ |
| 267 | 267 | ||
| 268 | status = | 268 | status = |
| 269 | acpi_write(0x00, | 269 | acpi_hw_write(0x00, |
| 270 | &gpe_block->register_info[i].enable_address); | 270 | &gpe_block->register_info[i].enable_address); |
| 271 | if (ACPI_FAILURE(status)) { | 271 | if (ACPI_FAILURE(status)) { |
| 272 | return (status); | 272 | return (status); |
| 273 | } | 273 | } |
| @@ -303,8 +303,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 303 | /* Clear status on all GPEs in this register */ | 303 | /* Clear status on all GPEs in this register */ |
| 304 | 304 | ||
| 305 | status = | 305 | status = |
| 306 | acpi_write(0xFF, | 306 | acpi_hw_write(0xFF, |
| 307 | &gpe_block->register_info[i].status_address); | 307 | &gpe_block->register_info[i].status_address); |
| 308 | if (ACPI_FAILURE(status)) { | 308 | if (ACPI_FAILURE(status)) { |
| 309 | return (status); | 309 | return (status); |
| 310 | } | 310 | } |
| @@ -345,9 +345,9 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 345 | 345 | ||
| 346 | /* Enable all "runtime" GPEs in this register */ | 346 | /* Enable all "runtime" GPEs in this register */ |
| 347 | 347 | ||
| 348 | status = acpi_write(gpe_block->register_info[i].enable_for_run, | 348 | status = |
| 349 | &gpe_block->register_info[i]. | 349 | acpi_hw_write(gpe_block->register_info[i].enable_for_run, |
| 350 | enable_address); | 350 | &gpe_block->register_info[i].enable_address); |
| 351 | if (ACPI_FAILURE(status)) { | 351 | if (ACPI_FAILURE(status)) { |
| 352 | return (status); | 352 | return (status); |
| 353 | } | 353 | } |
| @@ -387,9 +387,9 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 387 | 387 | ||
| 388 | /* Enable all "wake" GPEs in this register */ | 388 | /* Enable all "wake" GPEs in this register */ |
| 389 | 389 | ||
| 390 | status = acpi_write(gpe_block->register_info[i].enable_for_wake, | 390 | status = |
| 391 | &gpe_block->register_info[i]. | 391 | acpi_hw_write(gpe_block->register_info[i].enable_for_wake, |
| 392 | enable_address); | 392 | &gpe_block->register_info[i].enable_address); |
| 393 | if (ACPI_FAILURE(status)) { | 393 | if (ACPI_FAILURE(status)) { |
| 394 | return (status); | 394 | return (status); |
| 395 | } | 395 | } |
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 23d5505cb1f7..15c9ed2be853 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c | |||
| @@ -62,6 +62,184 @@ acpi_hw_write_multiple(u32 value, | |||
| 62 | struct acpi_generic_address *register_a, | 62 | struct acpi_generic_address *register_a, |
| 63 | struct acpi_generic_address *register_b); | 63 | struct acpi_generic_address *register_b); |
| 64 | 64 | ||
| 65 | /****************************************************************************** | ||
| 66 | * | ||
| 67 | * FUNCTION: acpi_hw_validate_register | ||
| 68 | * | ||
| 69 | * PARAMETERS: Reg - GAS register structure | ||
| 70 | * max_bit_width - Max bit_width supported (32 or 64) | ||
| 71 | * Address - Pointer to where the gas->address | ||
| 72 | * is returned | ||
| 73 | * | ||
| 74 | * RETURN: Status | ||
| 75 | * | ||
| 76 | * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS | ||
| 77 | * pointer, Address, space_id, bit_width, and bit_offset. | ||
| 78 | * | ||
| 79 | ******************************************************************************/ | ||
| 80 | |||
| 81 | acpi_status | ||
| 82 | acpi_hw_validate_register(struct acpi_generic_address *reg, | ||
| 83 | u8 max_bit_width, u64 *address) | ||
| 84 | { | ||
| 85 | |||
| 86 | /* Must have a valid pointer to a GAS structure */ | ||
| 87 | |||
| 88 | if (!reg) { | ||
| 89 | return (AE_BAD_PARAMETER); | ||
| 90 | } | ||
| 91 | |||
| 92 | /* | ||
| 93 | * Copy the target address. This handles possible alignment issues. | ||
| 94 | * Address must not be null. A null address also indicates an optional | ||
| 95 | * ACPI register that is not supported, so no error message. | ||
| 96 | */ | ||
| 97 | ACPI_MOVE_64_TO_64(address, ®->address); | ||
| 98 | if (!(*address)) { | ||
| 99 | return (AE_BAD_ADDRESS); | ||
| 100 | } | ||
| 101 | |||
| 102 | /* Validate the space_iD */ | ||
| 103 | |||
| 104 | if ((reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && | ||
| 105 | (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { | ||
| 106 | ACPI_ERROR((AE_INFO, | ||
| 107 | "Unsupported address space: 0x%X", reg->space_id)); | ||
| 108 | return (AE_SUPPORT); | ||
| 109 | } | ||
| 110 | |||
| 111 | /* Validate the bit_width */ | ||
| 112 | |||
| 113 | if ((reg->bit_width != 8) && | ||
| 114 | (reg->bit_width != 16) && | ||
| 115 | (reg->bit_width != 32) && (reg->bit_width != max_bit_width)) { | ||
| 116 | ACPI_ERROR((AE_INFO, | ||
| 117 | "Unsupported register bit width: 0x%X", | ||
| 118 | reg->bit_width)); | ||
| 119 | return (AE_SUPPORT); | ||
| 120 | } | ||
| 121 | |||
| 122 | /* Validate the bit_offset. Just a warning for now. */ | ||
| 123 | |||
| 124 | if (reg->bit_offset != 0) { | ||
| 125 | ACPI_WARNING((AE_INFO, | ||
| 126 | "Unsupported register bit offset: 0x%X", | ||
| 127 | reg->bit_offset)); | ||
| 128 | } | ||
| 129 | |||
| 130 | return (AE_OK); | ||
| 131 | } | ||
| 132 | |||
| 133 | /****************************************************************************** | ||
| 134 | * | ||
| 135 | * FUNCTION: acpi_hw_read | ||
| 136 | * | ||
| 137 | * PARAMETERS: Value - Where the value is returned | ||
| 138 | * Reg - GAS register structure | ||
| 139 | * | ||
| 140 | * RETURN: Status | ||
| 141 | * | ||
| 142 | * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max | ||
| 143 | * version of acpi_read, used internally since the overhead of | ||
| 144 | * 64-bit values is not needed. | ||
| 145 | * | ||
| 146 | * LIMITATIONS: <These limitations also apply to acpi_hw_write> | ||
| 147 | * bit_width must be exactly 8, 16, or 32. | ||
| 148 | * space_iD must be system_memory or system_iO. | ||
| 149 | * bit_offset and access_width are currently ignored, as there has | ||
| 150 | * not been a need to implement these. | ||
| 151 | * | ||
| 152 | ******************************************************************************/ | ||
| 153 | |||
| 154 | acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) | ||
| 155 | { | ||
| 156 | u64 address; | ||
| 157 | acpi_status status; | ||
| 158 | |||
| 159 | ACPI_FUNCTION_NAME(hw_read); | ||
| 160 | |||
| 161 | /* Validate contents of the GAS register */ | ||
| 162 | |||
| 163 | status = acpi_hw_validate_register(reg, 32, &address); | ||
| 164 | if (ACPI_FAILURE(status)) { | ||
| 165 | return (status); | ||
| 166 | } | ||
| 167 | |||
| 168 | /* Initialize entire 32-bit return value to zero */ | ||
| 169 | |||
| 170 | *value = 0; | ||
| 171 | |||
| 172 | /* | ||
| 173 | * Two address spaces supported: Memory or IO. PCI_Config is | ||
| 174 | * not supported here because the GAS structure is insufficient | ||
| 175 | */ | ||
| 176 | if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { | ||
| 177 | status = acpi_os_read_memory((acpi_physical_address) | ||
| 178 | address, value, reg->bit_width); | ||
| 179 | } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ | ||
| 180 | |||
| 181 | status = acpi_hw_read_port((acpi_io_address) | ||
| 182 | address, value, reg->bit_width); | ||
| 183 | } | ||
| 184 | |||
| 185 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | ||
| 186 | "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", | ||
| 187 | *value, reg->bit_width, ACPI_FORMAT_UINT64(address), | ||
| 188 | acpi_ut_get_region_name(reg->space_id))); | ||
| 189 | |||
| 190 | return (status); | ||
| 191 | } | ||
| 192 | |||
| 193 | /****************************************************************************** | ||
| 194 | * | ||
| 195 | * FUNCTION: acpi_hw_write | ||
| 196 | * | ||
| 197 | * PARAMETERS: Value - Value to be written | ||
| 198 | * Reg - GAS register structure | ||
| 199 | * | ||
| 200 | * RETURN: Status | ||
| 201 | * | ||
| 202 | * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max | ||
| 203 | * version of acpi_write, used internally since the overhead of | ||
| 204 | * 64-bit values is not needed. | ||
| 205 | * | ||
| 206 | ******************************************************************************/ | ||
| 207 | |||
| 208 | acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) | ||
| 209 | { | ||
| 210 | u64 address; | ||
| 211 | acpi_status status; | ||
| 212 | |||
| 213 | ACPI_FUNCTION_NAME(hw_write); | ||
| 214 | |||
| 215 | /* Validate contents of the GAS register */ | ||
| 216 | |||
| 217 | status = acpi_hw_validate_register(reg, 32, &address); | ||
| 218 | if (ACPI_FAILURE(status)) { | ||
| 219 | return (status); | ||
| 220 | } | ||
| 221 | |||
| 222 | /* | ||
| 223 | * Two address spaces supported: Memory or IO. PCI_Config is | ||
| 224 | * not supported here because the GAS structure is insufficient | ||
| 225 | */ | ||
| 226 | if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { | ||
| 227 | status = acpi_os_write_memory((acpi_physical_address) | ||
| 228 | address, value, reg->bit_width); | ||
| 229 | } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ | ||
| 230 | |||
| 231 | status = acpi_hw_write_port((acpi_io_address) | ||
| 232 | address, value, reg->bit_width); | ||
| 233 | } | ||
| 234 | |||
| 235 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | ||
| 236 | "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", | ||
| 237 | value, reg->bit_width, ACPI_FORMAT_UINT64(address), | ||
| 238 | acpi_ut_get_region_name(reg->space_id))); | ||
| 239 | |||
| 240 | return (status); | ||
| 241 | } | ||
| 242 | |||
| 65 | /******************************************************************************* | 243 | /******************************************************************************* |
| 66 | * | 244 | * |
| 67 | * FUNCTION: acpi_hw_clear_acpi_status | 245 | * FUNCTION: acpi_hw_clear_acpi_status |
| @@ -152,15 +330,16 @@ acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control) | |||
| 152 | 330 | ||
| 153 | ACPI_FUNCTION_TRACE(hw_write_pm1_control); | 331 | ACPI_FUNCTION_TRACE(hw_write_pm1_control); |
| 154 | 332 | ||
| 155 | status = acpi_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block); | 333 | status = |
| 334 | acpi_hw_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block); | ||
| 156 | if (ACPI_FAILURE(status)) { | 335 | if (ACPI_FAILURE(status)) { |
| 157 | return_ACPI_STATUS(status); | 336 | return_ACPI_STATUS(status); |
| 158 | } | 337 | } |
| 159 | 338 | ||
| 160 | if (acpi_gbl_FADT.xpm1b_control_block.address) { | 339 | if (acpi_gbl_FADT.xpm1b_control_block.address) { |
| 161 | status = | 340 | status = |
| 162 | acpi_write(pm1b_control, | 341 | acpi_hw_write(pm1b_control, |
| 163 | &acpi_gbl_FADT.xpm1b_control_block); | 342 | &acpi_gbl_FADT.xpm1b_control_block); |
| 164 | } | 343 | } |
| 165 | return_ACPI_STATUS(status); | 344 | return_ACPI_STATUS(status); |
| 166 | } | 345 | } |
| @@ -218,12 +397,13 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) | |||
| 218 | 397 | ||
| 219 | case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ | 398 | case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ |
| 220 | 399 | ||
| 221 | status = acpi_read(&value, &acpi_gbl_FADT.xpm2_control_block); | 400 | status = |
| 401 | acpi_hw_read(&value, &acpi_gbl_FADT.xpm2_control_block); | ||
| 222 | break; | 402 | break; |
| 223 | 403 | ||
| 224 | case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ | 404 | case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ |
| 225 | 405 | ||
| 226 | status = acpi_read(&value, &acpi_gbl_FADT.xpm_timer_block); | 406 | status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm_timer_block); |
| 227 | break; | 407 | break; |
| 228 | 408 | ||
| 229 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ | 409 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ |
| @@ -340,7 +520,8 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) | |||
| 340 | * as per the ACPI spec. | 520 | * as per the ACPI spec. |
| 341 | */ | 521 | */ |
| 342 | status = | 522 | status = |
| 343 | acpi_read(&read_value, &acpi_gbl_FADT.xpm2_control_block); | 523 | acpi_hw_read(&read_value, |
| 524 | &acpi_gbl_FADT.xpm2_control_block); | ||
| 344 | if (ACPI_FAILURE(status)) { | 525 | if (ACPI_FAILURE(status)) { |
| 345 | goto exit; | 526 | goto exit; |
| 346 | } | 527 | } |
| @@ -350,12 +531,13 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) | |||
| 350 | ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS, | 531 | ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS, |
| 351 | read_value); | 532 | read_value); |
| 352 | 533 | ||
| 353 | status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block); | 534 | status = |
| 535 | acpi_hw_write(value, &acpi_gbl_FADT.xpm2_control_block); | ||
| 354 | break; | 536 | break; |
| 355 | 537 | ||
| 356 | case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ | 538 | case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ |
| 357 | 539 | ||
| 358 | status = acpi_write(value, &acpi_gbl_FADT.xpm_timer_block); | 540 | status = acpi_hw_write(value, &acpi_gbl_FADT.xpm_timer_block); |
| 359 | break; | 541 | break; |
| 360 | 542 | ||
| 361 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ | 543 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ |
| @@ -401,7 +583,7 @@ acpi_hw_read_multiple(u32 *value, | |||
| 401 | 583 | ||
| 402 | /* The first register is always required */ | 584 | /* The first register is always required */ |
| 403 | 585 | ||
| 404 | status = acpi_read(&value_a, register_a); | 586 | status = acpi_hw_read(&value_a, register_a); |
| 405 | if (ACPI_FAILURE(status)) { | 587 | if (ACPI_FAILURE(status)) { |
| 406 | return (status); | 588 | return (status); |
| 407 | } | 589 | } |
| @@ -409,7 +591,7 @@ acpi_hw_read_multiple(u32 *value, | |||
| 409 | /* Second register is optional */ | 591 | /* Second register is optional */ |
| 410 | 592 | ||
| 411 | if (register_b->address) { | 593 | if (register_b->address) { |
| 412 | status = acpi_read(&value_b, register_b); | 594 | status = acpi_hw_read(&value_b, register_b); |
| 413 | if (ACPI_FAILURE(status)) { | 595 | if (ACPI_FAILURE(status)) { |
| 414 | return (status); | 596 | return (status); |
| 415 | } | 597 | } |
| @@ -452,7 +634,7 @@ acpi_hw_write_multiple(u32 value, | |||
| 452 | 634 | ||
| 453 | /* The first register is always required */ | 635 | /* The first register is always required */ |
| 454 | 636 | ||
| 455 | status = acpi_write(value, register_a); | 637 | status = acpi_hw_write(value, register_a); |
| 456 | if (ACPI_FAILURE(status)) { | 638 | if (ACPI_FAILURE(status)) { |
| 457 | return (status); | 639 | return (status); |
| 458 | } | 640 | } |
| @@ -470,7 +652,7 @@ acpi_hw_write_multiple(u32 value, | |||
| 470 | * and writes have no side effects" | 652 | * and writes have no side effects" |
| 471 | */ | 653 | */ |
| 472 | if (register_b->address) { | 654 | if (register_b->address) { |
| 473 | status = acpi_write(value, register_b); | 655 | status = acpi_hw_write(value, register_b); |
| 474 | } | 656 | } |
| 475 | 657 | ||
| 476 | return (status); | 658 | return (status); |
diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index b7f522c8f023..6b282e85d039 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c | |||
| @@ -100,7 +100,7 @@ acpi_status acpi_get_timer(u32 * ticks) | |||
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | status = | 102 | status = |
| 103 | acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT.xpm_timer_block); | 103 | acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block); |
| 104 | 104 | ||
| 105 | return_ACPI_STATUS(status); | 105 | return_ACPI_STATUS(status); |
| 106 | } | 106 | } |
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 9829979f2bdd..4ead85f29215 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c | |||
| @@ -80,7 +80,7 @@ acpi_status acpi_reset(void) | |||
| 80 | 80 | ||
| 81 | /* Write the reset value to the reset register */ | 81 | /* Write the reset value to the reset register */ |
| 82 | 82 | ||
| 83 | status = acpi_write(acpi_gbl_FADT.reset_value, reset_reg); | 83 | status = acpi_hw_write(acpi_gbl_FADT.reset_value, reset_reg); |
| 84 | return_ACPI_STATUS(status); | 84 | return_ACPI_STATUS(status); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| @@ -97,67 +97,92 @@ ACPI_EXPORT_SYMBOL(acpi_reset) | |||
| 97 | * | 97 | * |
| 98 | * DESCRIPTION: Read from either memory or IO space. | 98 | * DESCRIPTION: Read from either memory or IO space. |
| 99 | * | 99 | * |
| 100 | * LIMITATIONS: <These limitations also apply to acpi_write> | ||
| 101 | * bit_width must be exactly 8, 16, 32, or 64. | ||
| 102 | * space_iD must be system_memory or system_iO. | ||
| 103 | * bit_offset and access_width are currently ignored, as there has | ||
| 104 | * not been a need to implement these. | ||
| 105 | * | ||
| 100 | ******************************************************************************/ | 106 | ******************************************************************************/ |
| 101 | acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) | 107 | acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) |
| 102 | { | 108 | { |
| 109 | u32 value; | ||
| 103 | u32 width; | 110 | u32 width; |
| 104 | u64 address; | 111 | u64 address; |
| 105 | acpi_status status; | 112 | acpi_status status; |
| 106 | 113 | ||
| 107 | ACPI_FUNCTION_NAME(acpi_read); | 114 | ACPI_FUNCTION_NAME(acpi_read); |
| 108 | 115 | ||
| 109 | /* | 116 | if (!return_value) { |
| 110 | * Must have a valid pointer to a GAS structure, and a non-zero address | ||
| 111 | * within. | ||
| 112 | */ | ||
| 113 | if (!reg) { | ||
| 114 | return (AE_BAD_PARAMETER); | 117 | return (AE_BAD_PARAMETER); |
| 115 | } | 118 | } |
| 116 | 119 | ||
| 117 | /* Get a local copy of the address. Handles possible alignment issues */ | 120 | /* Validate contents of the GAS register. Allow 64-bit transfers */ |
| 118 | 121 | ||
| 119 | ACPI_MOVE_64_TO_64(&address, ®->address); | 122 | status = acpi_hw_validate_register(reg, 64, &address); |
| 120 | if (!address) { | 123 | if (ACPI_FAILURE(status)) { |
| 121 | return (AE_BAD_ADDRESS); | 124 | return (status); |
| 122 | } | 125 | } |
| 123 | 126 | ||
| 124 | /* Supported widths are 8/16/32 */ | ||
| 125 | |||
| 126 | width = reg->bit_width; | 127 | width = reg->bit_width; |
| 127 | if ((width != 8) && (width != 16) && (width != 32)) { | 128 | if (width == 64) { |
| 128 | return (AE_SUPPORT); | 129 | width = 32; /* Break into two 32-bit transfers */ |
| 129 | } | 130 | } |
| 130 | 131 | ||
| 131 | /* Initialize entire 32-bit return value to zero */ | 132 | /* Initialize entire 64-bit return value to zero */ |
| 132 | 133 | ||
| 133 | *value = 0; | 134 | *return_value = 0; |
| 135 | value = 0; | ||
| 134 | 136 | ||
| 135 | /* | 137 | /* |
| 136 | * Two address spaces supported: Memory or IO. PCI_Config is | 138 | * Two address spaces supported: Memory or IO. PCI_Config is |
| 137 | * not supported here because the GAS structure is insufficient | 139 | * not supported here because the GAS structure is insufficient |
| 138 | */ | 140 | */ |
| 139 | switch (reg->space_id) { | 141 | if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
| 140 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | 142 | status = acpi_os_read_memory((acpi_physical_address) |
| 143 | address, &value, width); | ||
| 144 | if (ACPI_FAILURE(status)) { | ||
| 145 | return (status); | ||
| 146 | } | ||
| 147 | *return_value = value; | ||
| 148 | |||
| 149 | if (reg->bit_width == 64) { | ||
| 141 | 150 | ||
| 142 | status = acpi_os_read_memory((acpi_physical_address) address, | 151 | /* Read the top 32 bits */ |
| 143 | value, width); | ||
| 144 | break; | ||
| 145 | 152 | ||
| 146 | case ACPI_ADR_SPACE_SYSTEM_IO: | 153 | status = acpi_os_read_memory((acpi_physical_address) |
| 154 | (address + 4), &value, 32); | ||
| 155 | if (ACPI_FAILURE(status)) { | ||
| 156 | return (status); | ||
| 157 | } | ||
| 158 | *return_value |= ((u64)value << 32); | ||
| 159 | } | ||
| 160 | } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ | ||
| 147 | 161 | ||
| 148 | status = | 162 | status = acpi_hw_read_port((acpi_io_address) |
| 149 | acpi_hw_read_port((acpi_io_address) address, value, width); | 163 | address, &value, width); |
| 150 | break; | 164 | if (ACPI_FAILURE(status)) { |
| 165 | return (status); | ||
| 166 | } | ||
| 167 | *return_value = value; | ||
| 151 | 168 | ||
| 152 | default: | 169 | if (reg->bit_width == 64) { |
| 153 | ACPI_ERROR((AE_INFO, | 170 | |
| 154 | "Unsupported address space: %X", reg->space_id)); | 171 | /* Read the top 32 bits */ |
| 155 | return (AE_BAD_PARAMETER); | 172 | |
| 173 | status = acpi_hw_read_port((acpi_io_address) | ||
| 174 | (address + 4), &value, 32); | ||
| 175 | if (ACPI_FAILURE(status)) { | ||
| 176 | return (status); | ||
| 177 | } | ||
| 178 | *return_value |= ((u64)value << 32); | ||
| 179 | } | ||
| 156 | } | 180 | } |
| 157 | 181 | ||
| 158 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | 182 | ACPI_DEBUG_PRINT((ACPI_DB_IO, |
| 159 | "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", | 183 | "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", |
| 160 | *value, width, ACPI_FORMAT_UINT64(address), | 184 | ACPI_FORMAT_UINT64(*return_value), reg->bit_width, |
| 185 | ACPI_FORMAT_UINT64(address), | ||
| 161 | acpi_ut_get_region_name(reg->space_id))); | 186 | acpi_ut_get_region_name(reg->space_id))); |
| 162 | 187 | ||
| 163 | return (status); | 188 | return (status); |
| @@ -169,7 +194,7 @@ ACPI_EXPORT_SYMBOL(acpi_read) | |||
| 169 | * | 194 | * |
| 170 | * FUNCTION: acpi_write | 195 | * FUNCTION: acpi_write |
| 171 | * | 196 | * |
| 172 | * PARAMETERS: Value - To be written | 197 | * PARAMETERS: Value - Value to be written |
| 173 | * Reg - GAS register structure | 198 | * Reg - GAS register structure |
| 174 | * | 199 | * |
| 175 | * RETURN: Status | 200 | * RETURN: Status |
| @@ -177,7 +202,7 @@ ACPI_EXPORT_SYMBOL(acpi_read) | |||
| 177 | * DESCRIPTION: Write to either memory or IO space. | 202 | * DESCRIPTION: Write to either memory or IO space. |
| 178 | * | 203 | * |
| 179 | ******************************************************************************/ | 204 | ******************************************************************************/ |
| 180 | acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) | 205 | acpi_status acpi_write(u64 value, struct acpi_generic_address *reg) |
| 181 | { | 206 | { |
| 182 | u32 width; | 207 | u32 width; |
| 183 | u64 address; | 208 | u64 address; |
| @@ -185,54 +210,61 @@ acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) | |||
| 185 | 210 | ||
| 186 | ACPI_FUNCTION_NAME(acpi_write); | 211 | ACPI_FUNCTION_NAME(acpi_write); |
| 187 | 212 | ||
| 188 | /* | 213 | /* Validate contents of the GAS register. Allow 64-bit transfers */ |
| 189 | * Must have a valid pointer to a GAS structure, and a non-zero address | ||
| 190 | * within. | ||
| 191 | */ | ||
| 192 | if (!reg) { | ||
| 193 | return (AE_BAD_PARAMETER); | ||
| 194 | } | ||
| 195 | 214 | ||
| 196 | /* Get a local copy of the address. Handles possible alignment issues */ | 215 | status = acpi_hw_validate_register(reg, 64, &address); |
| 197 | 216 | if (ACPI_FAILURE(status)) { | |
| 198 | ACPI_MOVE_64_TO_64(&address, ®->address); | 217 | return (status); |
| 199 | if (!address) { | ||
| 200 | return (AE_BAD_ADDRESS); | ||
| 201 | } | 218 | } |
| 202 | 219 | ||
| 203 | /* Supported widths are 8/16/32 */ | ||
| 204 | |||
| 205 | width = reg->bit_width; | 220 | width = reg->bit_width; |
| 206 | if ((width != 8) && (width != 16) && (width != 32)) { | 221 | if (width == 64) { |
| 207 | return (AE_SUPPORT); | 222 | width = 32; /* Break into two 32-bit transfers */ |
| 208 | } | 223 | } |
| 209 | 224 | ||
| 210 | /* | 225 | /* |
| 211 | * Two address spaces supported: Memory or IO. | 226 | * Two address spaces supported: Memory or IO. PCI_Config is |
| 212 | * PCI_Config is not supported here because the GAS struct is insufficient | 227 | * not supported here because the GAS structure is insufficient |
| 213 | */ | 228 | */ |
| 214 | switch (reg->space_id) { | 229 | if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
| 215 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | 230 | status = acpi_os_write_memory((acpi_physical_address) |
| 216 | 231 | address, ACPI_LODWORD(value), | |
| 217 | status = acpi_os_write_memory((acpi_physical_address) address, | 232 | width); |
| 218 | value, width); | 233 | if (ACPI_FAILURE(status)) { |
| 219 | break; | 234 | return (status); |
| 235 | } | ||
| 220 | 236 | ||
| 221 | case ACPI_ADR_SPACE_SYSTEM_IO: | 237 | if (reg->bit_width == 64) { |
| 238 | status = acpi_os_write_memory((acpi_physical_address) | ||
| 239 | (address + 4), | ||
| 240 | ACPI_HIDWORD(value), 32); | ||
| 241 | if (ACPI_FAILURE(status)) { | ||
| 242 | return (status); | ||
| 243 | } | ||
| 244 | } | ||
| 245 | } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ | ||
| 222 | 246 | ||
| 223 | status = acpi_hw_write_port((acpi_io_address) address, value, | 247 | status = acpi_hw_write_port((acpi_io_address) |
| 248 | address, ACPI_LODWORD(value), | ||
| 224 | width); | 249 | width); |
| 225 | break; | 250 | if (ACPI_FAILURE(status)) { |
| 251 | return (status); | ||
| 252 | } | ||
| 226 | 253 | ||
| 227 | default: | 254 | if (reg->bit_width == 64) { |
| 228 | ACPI_ERROR((AE_INFO, | 255 | status = acpi_hw_write_port((acpi_io_address) |
| 229 | "Unsupported address space: %X", reg->space_id)); | 256 | (address + 4), |
| 230 | return (AE_BAD_PARAMETER); | 257 | ACPI_HIDWORD(value), 32); |
| 258 | if (ACPI_FAILURE(status)) { | ||
| 259 | return (status); | ||
| 260 | } | ||
| 261 | } | ||
| 231 | } | 262 | } |
| 232 | 263 | ||
| 233 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | 264 | ACPI_DEBUG_PRINT((ACPI_DB_IO, |
| 234 | "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", | 265 | "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", |
| 235 | value, width, ACPI_FORMAT_UINT64(address), | 266 | ACPI_FORMAT_UINT64(value), reg->bit_width, |
| 267 | ACPI_FORMAT_UINT64(address), | ||
| 236 | acpi_ut_get_region_name(reg->space_id))); | 268 | acpi_ut_get_region_name(reg->space_id))); |
| 237 | 269 | ||
| 238 | return (status); | 270 | return (status); |
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 2aecaa5cc06c..b450a195319a 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h | |||
| @@ -360,9 +360,9 @@ acpi_status acpi_set_firmware_waking_vector(u32 physical_address); | |||
| 360 | acpi_status acpi_set_firmware_waking_vector64(u64 physical_address); | 360 | acpi_status acpi_set_firmware_waking_vector64(u64 physical_address); |
| 361 | #endif | 361 | #endif |
| 362 | 362 | ||
| 363 | acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg); | 363 | acpi_status acpi_read(u64 *value, struct acpi_generic_address *reg); |
| 364 | 364 | ||
| 365 | acpi_status acpi_write(u32 value, struct acpi_generic_address *reg); | 365 | acpi_status acpi_write(u64 value, struct acpi_generic_address *reg); |
| 366 | 366 | ||
| 367 | acpi_status | 367 | acpi_status |
| 368 | acpi_get_sleep_type_data(u8 sleep_state, u8 * slp_typ_a, u8 * slp_typ_b); | 368 | acpi_get_sleep_type_data(u8 sleep_state, u8 * slp_typ_a, u8 * slp_typ_b); |
