diff options
Diffstat (limited to 'drivers/acpi/acpica/hwregs.c')
-rw-r--r-- | drivers/acpi/acpica/hwregs.c | 206 |
1 files changed, 194 insertions, 12 deletions
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); |