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); |