aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2009-06-23 21:44:06 -0400
committerLen Brown <len.brown@intel.com>2009-08-27 10:17:14 -0400
commitc6b5774caafa4c12b6019366e2fdaaff117e95a4 (patch)
tree04a9439010ba84fd2ab787d6d43dbcebe2020a1e /drivers/acpi/acpica
parentf8d80cdf40fe4d2393159012b38ce9f85a488686 (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>
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r--drivers/acpi/acpica/achware.h8
-rw-r--r--drivers/acpi/acpica/evgpe.c8
-rw-r--r--drivers/acpi/acpica/evgpeblk.c4
-rw-r--r--drivers/acpi/acpica/hwgpe.c34
-rw-r--r--drivers/acpi/acpica/hwregs.c206
-rw-r--r--drivers/acpi/acpica/hwtimer.c2
-rw-r--r--drivers/acpi/acpica/hwxface.c166
7 files changed, 325 insertions, 103 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 */
65acpi_status
66acpi_hw_validate_register(struct acpi_generic_address *reg,
67 u8 max_bit_width, u64 *address);
68
69acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg);
70
71acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg);
72
65struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id); 73struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id);
66 74
67acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control); 75acpi_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
81acpi_status
82acpi_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, &reg->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
154acpi_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
208acpi_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 ******************************************************************************/
101acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) 107acpi_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, &reg->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 ******************************************************************************/
180acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) 205acpi_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, &reg->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);