diff options
Diffstat (limited to 'drivers/acpi/acpica/hwregs.c')
-rw-r--r-- | drivers/acpi/acpica/hwregs.c | 322 |
1 files changed, 223 insertions, 99 deletions
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 4dc43b018517..7b2fb602b5cb 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c | |||
@@ -51,6 +51,17 @@ | |||
51 | #define _COMPONENT ACPI_HARDWARE | 51 | #define _COMPONENT ACPI_HARDWARE |
52 | ACPI_MODULE_NAME("hwregs") | 52 | ACPI_MODULE_NAME("hwregs") |
53 | 53 | ||
54 | /* Local Prototypes */ | ||
55 | static acpi_status | ||
56 | acpi_hw_read_multiple(u32 *value, | ||
57 | struct acpi_generic_address *register_a, | ||
58 | struct acpi_generic_address *register_b); | ||
59 | |||
60 | static acpi_status | ||
61 | acpi_hw_write_multiple(u32 value, | ||
62 | struct acpi_generic_address *register_a, | ||
63 | struct acpi_generic_address *register_b); | ||
64 | |||
54 | /******************************************************************************* | 65 | /******************************************************************************* |
55 | * | 66 | * |
56 | * FUNCTION: acpi_hw_clear_acpi_status | 67 | * FUNCTION: acpi_hw_clear_acpi_status |
@@ -60,9 +71,9 @@ ACPI_MODULE_NAME("hwregs") | |||
60 | * RETURN: Status | 71 | * RETURN: Status |
61 | * | 72 | * |
62 | * DESCRIPTION: Clears all fixed and general purpose status bits | 73 | * DESCRIPTION: Clears all fixed and general purpose status bits |
63 | * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED | ||
64 | * | 74 | * |
65 | ******************************************************************************/ | 75 | ******************************************************************************/ |
76 | |||
66 | acpi_status acpi_hw_clear_acpi_status(void) | 77 | acpi_status acpi_hw_clear_acpi_status(void) |
67 | { | 78 | { |
68 | acpi_status status; | 79 | acpi_status status; |
@@ -70,28 +81,20 @@ acpi_status acpi_hw_clear_acpi_status(void) | |||
70 | 81 | ||
71 | ACPI_FUNCTION_TRACE(hw_clear_acpi_status); | 82 | ACPI_FUNCTION_TRACE(hw_clear_acpi_status); |
72 | 83 | ||
73 | ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n", | 84 | ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %0llX\n", |
74 | ACPI_BITMASK_ALL_FIXED_STATUS, | 85 | ACPI_BITMASK_ALL_FIXED_STATUS, |
75 | (u16) acpi_gbl_FADT.xpm1a_event_block.address)); | 86 | acpi_gbl_xpm1a_status.address)); |
76 | 87 | ||
77 | lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); | 88 | lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); |
78 | 89 | ||
90 | /* Clear the fixed events in PM1 A/B */ | ||
91 | |||
79 | status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, | 92 | status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, |
80 | ACPI_BITMASK_ALL_FIXED_STATUS); | 93 | ACPI_BITMASK_ALL_FIXED_STATUS); |
81 | if (ACPI_FAILURE(status)) { | 94 | if (ACPI_FAILURE(status)) { |
82 | goto unlock_and_exit; | 95 | goto unlock_and_exit; |
83 | } | 96 | } |
84 | 97 | ||
85 | /* Clear the fixed events */ | ||
86 | |||
87 | if (acpi_gbl_FADT.xpm1b_event_block.address) { | ||
88 | status = acpi_write(ACPI_BITMASK_ALL_FIXED_STATUS, | ||
89 | &acpi_gbl_FADT.xpm1b_event_block); | ||
90 | if (ACPI_FAILURE(status)) { | ||
91 | goto unlock_and_exit; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | /* Clear the GPE Bits in all GPE registers in all GPE blocks */ | 98 | /* Clear the GPE Bits in all GPE registers in all GPE blocks */ |
96 | 99 | ||
97 | status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL); | 100 | status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL); |
@@ -128,6 +131,42 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) | |||
128 | 131 | ||
129 | /****************************************************************************** | 132 | /****************************************************************************** |
130 | * | 133 | * |
134 | * FUNCTION: acpi_hw_write_pm1_control | ||
135 | * | ||
136 | * PARAMETERS: pm1a_control - Value to be written to PM1A control | ||
137 | * pm1b_control - Value to be written to PM1B control | ||
138 | * | ||
139 | * RETURN: Status | ||
140 | * | ||
141 | * DESCRIPTION: Write the PM1 A/B control registers. These registers are | ||
142 | * different than than the PM1 A/B status and enable registers | ||
143 | * in that different values can be written to the A/B registers. | ||
144 | * Most notably, the SLP_TYP bits can be different, as per the | ||
145 | * values returned from the _Sx predefined methods. | ||
146 | * | ||
147 | ******************************************************************************/ | ||
148 | |||
149 | acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control) | ||
150 | { | ||
151 | acpi_status status; | ||
152 | |||
153 | ACPI_FUNCTION_TRACE(hw_write_pm1_control); | ||
154 | |||
155 | status = acpi_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block); | ||
156 | if (ACPI_FAILURE(status)) { | ||
157 | return_ACPI_STATUS(status); | ||
158 | } | ||
159 | |||
160 | if (acpi_gbl_FADT.xpm1b_control_block.address) { | ||
161 | status = | ||
162 | acpi_write(pm1b_control, | ||
163 | &acpi_gbl_FADT.xpm1b_control_block); | ||
164 | } | ||
165 | return_ACPI_STATUS(status); | ||
166 | } | ||
167 | |||
168 | /****************************************************************************** | ||
169 | * | ||
131 | * FUNCTION: acpi_hw_register_read | 170 | * FUNCTION: acpi_hw_register_read |
132 | * | 171 | * |
133 | * PARAMETERS: register_id - ACPI Register ID | 172 | * PARAMETERS: register_id - ACPI Register ID |
@@ -141,64 +180,56 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) | |||
141 | acpi_status | 180 | acpi_status |
142 | acpi_hw_register_read(u32 register_id, u32 * return_value) | 181 | acpi_hw_register_read(u32 register_id, u32 * return_value) |
143 | { | 182 | { |
144 | u32 value1 = 0; | 183 | u32 value = 0; |
145 | u32 value2 = 0; | ||
146 | acpi_status status; | 184 | acpi_status status; |
147 | 185 | ||
148 | ACPI_FUNCTION_TRACE(hw_register_read); | 186 | ACPI_FUNCTION_TRACE(hw_register_read); |
149 | 187 | ||
150 | switch (register_id) { | 188 | switch (register_id) { |
151 | case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ | 189 | case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ |
152 | |||
153 | status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_event_block); | ||
154 | if (ACPI_FAILURE(status)) { | ||
155 | goto exit; | ||
156 | } | ||
157 | |||
158 | /* PM1B is optional */ | ||
159 | 190 | ||
160 | status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_event_block); | 191 | status = acpi_hw_read_multiple(&value, |
161 | value1 |= value2; | 192 | &acpi_gbl_xpm1a_status, |
193 | &acpi_gbl_xpm1b_status); | ||
162 | break; | 194 | break; |
163 | 195 | ||
164 | case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ | 196 | case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ |
165 | 197 | ||
166 | status = acpi_read(&value1, &acpi_gbl_xpm1a_enable); | 198 | status = acpi_hw_read_multiple(&value, |
167 | if (ACPI_FAILURE(status)) { | 199 | &acpi_gbl_xpm1a_enable, |
168 | goto exit; | 200 | &acpi_gbl_xpm1b_enable); |
169 | } | ||
170 | |||
171 | /* PM1B is optional */ | ||
172 | |||
173 | status = acpi_read(&value2, &acpi_gbl_xpm1b_enable); | ||
174 | value1 |= value2; | ||
175 | break; | 201 | break; |
176 | 202 | ||
177 | case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ | 203 | case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ |
178 | 204 | ||
179 | status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_control_block); | 205 | status = acpi_hw_read_multiple(&value, |
180 | if (ACPI_FAILURE(status)) { | 206 | &acpi_gbl_FADT. |
181 | goto exit; | 207 | xpm1a_control_block, |
182 | } | 208 | &acpi_gbl_FADT. |
209 | xpm1b_control_block); | ||
183 | 210 | ||
184 | status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_control_block); | 211 | /* |
185 | value1 |= value2; | 212 | * Zero the write-only bits. From the ACPI specification, "Hardware |
213 | * Write-Only Bits": "Upon reads to registers with write-only bits, | ||
214 | * software masks out all write-only bits." | ||
215 | */ | ||
216 | value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS; | ||
186 | break; | 217 | break; |
187 | 218 | ||
188 | case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ | 219 | case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ |
189 | 220 | ||
190 | status = acpi_read(&value1, &acpi_gbl_FADT.xpm2_control_block); | 221 | status = acpi_read(&value, &acpi_gbl_FADT.xpm2_control_block); |
191 | break; | 222 | break; |
192 | 223 | ||
193 | case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ | 224 | case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ |
194 | 225 | ||
195 | status = acpi_read(&value1, &acpi_gbl_FADT.xpm_timer_block); | 226 | status = acpi_read(&value, &acpi_gbl_FADT.xpm_timer_block); |
196 | break; | 227 | break; |
197 | 228 | ||
198 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ | 229 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ |
199 | 230 | ||
200 | status = | 231 | status = |
201 | acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8); | 232 | acpi_hw_read_port(acpi_gbl_FADT.smi_command, &value, 8); |
202 | break; | 233 | break; |
203 | 234 | ||
204 | default: | 235 | default: |
@@ -207,10 +238,8 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) | |||
207 | break; | 238 | break; |
208 | } | 239 | } |
209 | 240 | ||
210 | exit: | ||
211 | |||
212 | if (ACPI_SUCCESS(status)) { | 241 | if (ACPI_SUCCESS(status)) { |
213 | *return_value = value1; | 242 | *return_value = value; |
214 | } | 243 | } |
215 | 244 | ||
216 | return_ACPI_STATUS(status); | 245 | return_ACPI_STATUS(status); |
@@ -250,52 +279,42 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) | |||
250 | ACPI_FUNCTION_TRACE(hw_register_write); | 279 | ACPI_FUNCTION_TRACE(hw_register_write); |
251 | 280 | ||
252 | switch (register_id) { | 281 | switch (register_id) { |
253 | case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ | 282 | case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ |
254 | 283 | /* | |
255 | /* Perform a read first to preserve certain bits (per ACPI spec) */ | 284 | * Handle the "ignored" bit in PM1 Status. According to the ACPI |
256 | 285 | * specification, ignored bits are to be preserved when writing. | |
257 | status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, | 286 | * Normally, this would mean a read/modify/write sequence. However, |
258 | &read_value); | 287 | * preserving a bit in the status register is different. Writing a |
259 | if (ACPI_FAILURE(status)) { | 288 | * one clears the status, and writing a zero preserves the status. |
260 | goto exit; | 289 | * Therefore, we must always write zero to the ignored bit. |
261 | } | 290 | * |
262 | 291 | * This behavior is clarified in the ACPI 4.0 specification. | |
263 | /* Insert the bits to be preserved */ | 292 | */ |
264 | 293 | value &= ~ACPI_PM1_STATUS_PRESERVED_BITS; | |
265 | ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS, | ||
266 | read_value); | ||
267 | |||
268 | /* Now we can write the data */ | ||
269 | |||
270 | status = acpi_write(value, &acpi_gbl_FADT.xpm1a_event_block); | ||
271 | if (ACPI_FAILURE(status)) { | ||
272 | goto exit; | ||
273 | } | ||
274 | |||
275 | /* PM1B is optional */ | ||
276 | 294 | ||
277 | status = acpi_write(value, &acpi_gbl_FADT.xpm1b_event_block); | 295 | status = acpi_hw_write_multiple(value, |
296 | &acpi_gbl_xpm1a_status, | ||
297 | &acpi_gbl_xpm1b_status); | ||
278 | break; | 298 | break; |
279 | 299 | ||
280 | case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ | 300 | case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access */ |
281 | 301 | ||
282 | status = acpi_write(value, &acpi_gbl_xpm1a_enable); | 302 | status = acpi_hw_write_multiple(value, |
283 | if (ACPI_FAILURE(status)) { | 303 | &acpi_gbl_xpm1a_enable, |
284 | goto exit; | 304 | &acpi_gbl_xpm1b_enable); |
285 | } | ||
286 | |||
287 | /* PM1B is optional */ | ||
288 | |||
289 | status = acpi_write(value, &acpi_gbl_xpm1b_enable); | ||
290 | break; | 305 | break; |
291 | 306 | ||
292 | case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ | 307 | case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ |
293 | 308 | ||
294 | /* | 309 | /* |
295 | * Perform a read first to preserve certain bits (per ACPI spec) | 310 | * Perform a read first to preserve certain bits (per ACPI spec) |
311 | * Note: This includes SCI_EN, we never want to change this bit | ||
296 | */ | 312 | */ |
297 | status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, | 313 | status = acpi_hw_read_multiple(&read_value, |
298 | &read_value); | 314 | &acpi_gbl_FADT. |
315 | xpm1a_control_block, | ||
316 | &acpi_gbl_FADT. | ||
317 | xpm1b_control_block); | ||
299 | if (ACPI_FAILURE(status)) { | 318 | if (ACPI_FAILURE(status)) { |
300 | goto exit; | 319 | goto exit; |
301 | } | 320 | } |
@@ -307,25 +326,29 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) | |||
307 | 326 | ||
308 | /* Now we can write the data */ | 327 | /* Now we can write the data */ |
309 | 328 | ||
310 | status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block); | 329 | status = acpi_hw_write_multiple(value, |
311 | if (ACPI_FAILURE(status)) { | 330 | &acpi_gbl_FADT. |
312 | goto exit; | 331 | xpm1a_control_block, |
313 | } | 332 | &acpi_gbl_FADT. |
314 | 333 | xpm1b_control_block); | |
315 | status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block); | ||
316 | break; | 334 | break; |
317 | 335 | ||
318 | case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ | 336 | case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ |
319 | |||
320 | status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block); | ||
321 | break; | ||
322 | 337 | ||
323 | case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ | 338 | /* |
339 | * For control registers, all reserved bits must be preserved, | ||
340 | * as per the ACPI spec. | ||
341 | */ | ||
342 | status = | ||
343 | acpi_read(&read_value, &acpi_gbl_FADT.xpm2_control_block); | ||
344 | if (ACPI_FAILURE(status)) { | ||
345 | goto exit; | ||
346 | } | ||
324 | 347 | ||
325 | status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block); | 348 | /* Insert the bits to be preserved */ |
326 | break; | ||
327 | 349 | ||
328 | case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ | 350 | ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS, |
351 | read_value); | ||
329 | 352 | ||
330 | status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block); | 353 | status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block); |
331 | break; | 354 | break; |
@@ -340,10 +363,11 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) | |||
340 | /* SMI_CMD is currently always in IO space */ | 363 | /* SMI_CMD is currently always in IO space */ |
341 | 364 | ||
342 | status = | 365 | status = |
343 | acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8); | 366 | acpi_hw_write_port(acpi_gbl_FADT.smi_command, value, 8); |
344 | break; | 367 | break; |
345 | 368 | ||
346 | default: | 369 | default: |
370 | ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id)); | ||
347 | status = AE_BAD_PARAMETER; | 371 | status = AE_BAD_PARAMETER; |
348 | break; | 372 | break; |
349 | } | 373 | } |
@@ -351,3 +375,103 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) | |||
351 | exit: | 375 | exit: |
352 | return_ACPI_STATUS(status); | 376 | return_ACPI_STATUS(status); |
353 | } | 377 | } |
378 | |||
379 | /****************************************************************************** | ||
380 | * | ||
381 | * FUNCTION: acpi_hw_read_multiple | ||
382 | * | ||
383 | * PARAMETERS: Value - Where the register value is returned | ||
384 | * register_a - First ACPI register (required) | ||
385 | * register_b - Second ACPI register (optional) | ||
386 | * | ||
387 | * RETURN: Status | ||
388 | * | ||
389 | * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B) | ||
390 | * | ||
391 | ******************************************************************************/ | ||
392 | |||
393 | static acpi_status | ||
394 | acpi_hw_read_multiple(u32 *value, | ||
395 | struct acpi_generic_address *register_a, | ||
396 | struct acpi_generic_address *register_b) | ||
397 | { | ||
398 | u32 value_a = 0; | ||
399 | u32 value_b = 0; | ||
400 | acpi_status status; | ||
401 | |||
402 | /* The first register is always required */ | ||
403 | |||
404 | status = acpi_read(&value_a, register_a); | ||
405 | if (ACPI_FAILURE(status)) { | ||
406 | return (status); | ||
407 | } | ||
408 | |||
409 | /* Second register is optional */ | ||
410 | |||
411 | if (register_b->address) { | ||
412 | status = acpi_read(&value_b, register_b); | ||
413 | if (ACPI_FAILURE(status)) { | ||
414 | return (status); | ||
415 | } | ||
416 | } | ||
417 | |||
418 | /* | ||
419 | * OR the two return values together. No shifting or masking is necessary, | ||
420 | * because of how the PM1 registers are defined in the ACPI specification: | ||
421 | * | ||
422 | * "Although the bits can be split between the two register blocks (each | ||
423 | * register block has a unique pointer within the FADT), the bit positions | ||
424 | * are maintained. The register block with unimplemented bits (that is, | ||
425 | * those implemented in the other register block) always returns zeros, | ||
426 | * and writes have no side effects" | ||
427 | */ | ||
428 | *value = (value_a | value_b); | ||
429 | return (AE_OK); | ||
430 | } | ||
431 | |||
432 | /****************************************************************************** | ||
433 | * | ||
434 | * FUNCTION: acpi_hw_write_multiple | ||
435 | * | ||
436 | * PARAMETERS: Value - The value to write | ||
437 | * register_a - First ACPI register (required) | ||
438 | * register_b - Second ACPI register (optional) | ||
439 | * | ||
440 | * RETURN: Status | ||
441 | * | ||
442 | * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B) | ||
443 | * | ||
444 | ******************************************************************************/ | ||
445 | |||
446 | static acpi_status | ||
447 | acpi_hw_write_multiple(u32 value, | ||
448 | struct acpi_generic_address *register_a, | ||
449 | struct acpi_generic_address *register_b) | ||
450 | { | ||
451 | acpi_status status; | ||
452 | |||
453 | /* The first register is always required */ | ||
454 | |||
455 | status = acpi_write(value, register_a); | ||
456 | if (ACPI_FAILURE(status)) { | ||
457 | return (status); | ||
458 | } | ||
459 | |||
460 | /* | ||
461 | * Second register is optional | ||
462 | * | ||
463 | * No bit shifting or clearing is necessary, because of how the PM1 | ||
464 | * registers are defined in the ACPI specification: | ||
465 | * | ||
466 | * "Although the bits can be split between the two register blocks (each | ||
467 | * register block has a unique pointer within the FADT), the bit positions | ||
468 | * are maintained. The register block with unimplemented bits (that is, | ||
469 | * those implemented in the other register block) always returns zeros, | ||
470 | * and writes have no side effects" | ||
471 | */ | ||
472 | if (register_b->address) { | ||
473 | status = acpi_write(value, register_b); | ||
474 | } | ||
475 | |||
476 | return (status); | ||
477 | } | ||