diff options
author | Bob Moore <robert.moore@intel.com> | 2009-02-18 03:01:04 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-03-26 16:38:31 -0400 |
commit | 88dcb04a813265e1a5a1bc74af2db7efa7d62ee6 (patch) | |
tree | 47d2d657b9d4c555c7566a06f2b40b2272ab3932 /drivers/acpi/acpica/hwxface.c | |
parent | 50ffba1bd3120b069617455545bc27bcf3cf7579 (diff) |
ACPICA: Restructure bit register access functions
Update code for acpi_read_bit_register and acpi_write_bit_register.
Simplified code path, condensed duplicate code.
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/hwxface.c')
-rw-r--r-- | drivers/acpi/acpica/hwxface.c | 177 |
1 files changed, 62 insertions, 115 deletions
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 529251c7f911..caad51680bd6 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c | |||
@@ -133,8 +133,8 @@ acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) | |||
133 | *value = 0; | 133 | *value = 0; |
134 | 134 | ||
135 | /* | 135 | /* |
136 | * Two address spaces supported: Memory or IO. | 136 | * Two address spaces supported: Memory or IO. PCI_Config is |
137 | * PCI_Config is not supported here because the GAS struct is insufficient | 137 | * not supported here because the GAS structure is insufficient |
138 | */ | 138 | */ |
139 | switch (reg->space_id) { | 139 | switch (reg->space_id) { |
140 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | 140 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: |
@@ -266,11 +266,12 @@ ACPI_EXPORT_SYMBOL(acpi_write) | |||
266 | ******************************************************************************/ | 266 | ******************************************************************************/ |
267 | acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value) | 267 | acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value) |
268 | { | 268 | { |
269 | u32 register_value = 0; | ||
270 | struct acpi_bit_register_info *bit_reg_info; | 269 | struct acpi_bit_register_info *bit_reg_info; |
270 | u32 register_value; | ||
271 | u32 value; | ||
271 | acpi_status status; | 272 | acpi_status status; |
272 | 273 | ||
273 | ACPI_FUNCTION_TRACE(acpi_read_bit_register); | 274 | ACPI_FUNCTION_TRACE_U32(acpi_read_bit_register, register_id); |
274 | 275 | ||
275 | /* Get the info structure corresponding to the requested ACPI Register */ | 276 | /* Get the info structure corresponding to the requested ACPI Register */ |
276 | 277 | ||
@@ -283,23 +284,22 @@ acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value) | |||
283 | 284 | ||
284 | status = acpi_hw_register_read(bit_reg_info->parent_register, | 285 | status = acpi_hw_register_read(bit_reg_info->parent_register, |
285 | ®ister_value); | 286 | ®ister_value); |
287 | if (ACPI_FAILURE(status)) { | ||
288 | return_ACPI_STATUS(status); | ||
289 | } | ||
286 | 290 | ||
287 | if (ACPI_SUCCESS(status)) { | 291 | /* Normalize the value that was read, mask off other bits */ |
288 | |||
289 | /* Normalize the value that was read */ | ||
290 | |||
291 | register_value = | ||
292 | ((register_value & bit_reg_info->access_bit_mask) | ||
293 | >> bit_reg_info->bit_position); | ||
294 | 292 | ||
295 | *return_value = register_value; | 293 | value = ((register_value & bit_reg_info->access_bit_mask) |
294 | >> bit_reg_info->bit_position); | ||
296 | 295 | ||
297 | ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read value %8.8X register %X\n", | 296 | ACPI_DEBUG_PRINT((ACPI_DB_IO, |
298 | register_value, | 297 | "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n", |
299 | bit_reg_info->parent_register)); | 298 | register_id, bit_reg_info->parent_register, |
300 | } | 299 | register_value, value)); |
301 | 300 | ||
302 | return_ACPI_STATUS(status); | 301 | *return_value = value; |
302 | return_ACPI_STATUS(AE_OK); | ||
303 | } | 303 | } |
304 | 304 | ||
305 | ACPI_EXPORT_SYMBOL(acpi_read_bit_register) | 305 | ACPI_EXPORT_SYMBOL(acpi_read_bit_register) |
@@ -321,13 +321,16 @@ ACPI_EXPORT_SYMBOL(acpi_read_bit_register) | |||
321 | * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and | 321 | * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and |
322 | * PM2 Control. | 322 | * PM2 Control. |
323 | * | 323 | * |
324 | * Note that at this level, the fact that there may be actually two | ||
325 | * hardware registers (A and B - and B may not exist) is abstracted. | ||
326 | * | ||
324 | ******************************************************************************/ | 327 | ******************************************************************************/ |
325 | acpi_status acpi_write_bit_register(u32 register_id, u32 value) | 328 | acpi_status acpi_write_bit_register(u32 register_id, u32 value) |
326 | { | 329 | { |
327 | u32 register_value = 0; | ||
328 | struct acpi_bit_register_info *bit_reg_info; | 330 | struct acpi_bit_register_info *bit_reg_info; |
329 | acpi_status status; | ||
330 | acpi_cpu_flags lock_flags; | 331 | acpi_cpu_flags lock_flags; |
332 | u32 register_value; | ||
333 | acpi_status status = AE_OK; | ||
331 | 334 | ||
332 | ACPI_FUNCTION_TRACE_U32(acpi_write_bit_register, register_id); | 335 | ACPI_FUNCTION_TRACE_U32(acpi_write_bit_register, register_id); |
333 | 336 | ||
@@ -335,127 +338,71 @@ acpi_status acpi_write_bit_register(u32 register_id, u32 value) | |||
335 | 338 | ||
336 | bit_reg_info = acpi_hw_get_bit_register_info(register_id); | 339 | bit_reg_info = acpi_hw_get_bit_register_info(register_id); |
337 | if (!bit_reg_info) { | 340 | if (!bit_reg_info) { |
338 | ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X", | ||
339 | register_id)); | ||
340 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 341 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
341 | } | 342 | } |
342 | 343 | ||
343 | lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); | 344 | lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); |
344 | 345 | ||
345 | /* Always do a register read first so we can insert the new bits */ | ||
346 | |||
347 | status = acpi_hw_register_read(bit_reg_info->parent_register, | ||
348 | ®ister_value); | ||
349 | if (ACPI_FAILURE(status)) { | ||
350 | goto unlock_and_exit; | ||
351 | } | ||
352 | |||
353 | /* | 346 | /* |
354 | * Decode the Register ID | 347 | * At this point, we know that the parent register is one of the |
355 | * Register ID = [Register block ID] | [bit ID] | 348 | * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control |
356 | * | ||
357 | * Check bit ID to fine locate Register offset. | ||
358 | * Check Mask to determine Register offset, and then read-write. | ||
359 | */ | 349 | */ |
360 | switch (bit_reg_info->parent_register) { | 350 | if (bit_reg_info->parent_register != ACPI_REGISTER_PM1_STATUS) { |
361 | case ACPI_REGISTER_PM1_STATUS: | ||
362 | |||
363 | /* | ||
364 | * Status Registers are different from the rest. Clear by | ||
365 | * writing 1, and writing 0 has no effect. So, the only relevant | ||
366 | * information is the single bit we're interested in, all others should | ||
367 | * be written as 0 so they will be left unchanged. | ||
368 | */ | ||
369 | value = ACPI_REGISTER_PREPARE_BITS(value, | ||
370 | bit_reg_info->bit_position, | ||
371 | bit_reg_info-> | ||
372 | access_bit_mask); | ||
373 | if (value) { | ||
374 | status = | ||
375 | acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, | ||
376 | (u16) value); | ||
377 | register_value = 0; | ||
378 | } | ||
379 | break; | ||
380 | |||
381 | case ACPI_REGISTER_PM1_ENABLE: | ||
382 | |||
383 | ACPI_REGISTER_INSERT_VALUE(register_value, | ||
384 | bit_reg_info->bit_position, | ||
385 | bit_reg_info->access_bit_mask, | ||
386 | value); | ||
387 | |||
388 | status = acpi_hw_register_write(ACPI_REGISTER_PM1_ENABLE, | ||
389 | (u16) register_value); | ||
390 | break; | ||
391 | |||
392 | case ACPI_REGISTER_PM1_CONTROL: | ||
393 | |||
394 | /* | 351 | /* |
395 | * Write the PM1 Control register. | 352 | * 1) Case for PM1 Enable, PM1 Control, and PM2 Control |
396 | * Note that at this level, the fact that there are actually TWO | 353 | * |
397 | * registers (A and B - and B may not exist) is abstracted. | 354 | * Perform a register read to preserve the bits that we are not |
355 | * interested in | ||
398 | */ | 356 | */ |
399 | ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM1 control: Read %X\n", | 357 | status = acpi_hw_register_read(bit_reg_info->parent_register, |
400 | register_value)); | ||
401 | |||
402 | ACPI_REGISTER_INSERT_VALUE(register_value, | ||
403 | bit_reg_info->bit_position, | ||
404 | bit_reg_info->access_bit_mask, | ||
405 | value); | ||
406 | |||
407 | status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, | ||
408 | (u16) register_value); | ||
409 | break; | ||
410 | |||
411 | case ACPI_REGISTER_PM2_CONTROL: | ||
412 | |||
413 | status = acpi_hw_register_read(ACPI_REGISTER_PM2_CONTROL, | ||
414 | ®ister_value); | 358 | ®ister_value); |
415 | if (ACPI_FAILURE(status)) { | 359 | if (ACPI_FAILURE(status)) { |
416 | goto unlock_and_exit; | 360 | goto unlock_and_exit; |
417 | } | 361 | } |
418 | 362 | ||
419 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | 363 | /* |
420 | "PM2 control: Read %X from %8.8X%8.8X\n", | 364 | * Insert the input bit into the value that was just read |
421 | register_value, | 365 | * and write the register |
422 | ACPI_FORMAT_UINT64(acpi_gbl_FADT. | 366 | */ |
423 | xpm2_control_block. | ||
424 | address))); | ||
425 | |||
426 | ACPI_REGISTER_INSERT_VALUE(register_value, | 367 | ACPI_REGISTER_INSERT_VALUE(register_value, |
427 | bit_reg_info->bit_position, | 368 | bit_reg_info->bit_position, |
428 | bit_reg_info->access_bit_mask, | 369 | bit_reg_info->access_bit_mask, |
429 | value); | 370 | value); |
430 | 371 | ||
431 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | 372 | status = acpi_hw_register_write(bit_reg_info->parent_register, |
432 | "About to write %4.4X to %8.8X%8.8X\n", | 373 | register_value); |
433 | register_value, | 374 | } else { |
434 | ACPI_FORMAT_UINT64(acpi_gbl_FADT. | 375 | /* |
435 | xpm2_control_block. | 376 | * 2) Case for PM1 Status |
436 | address))); | 377 | * |
378 | * The Status register is different from the rest. Clear an event | ||
379 | * by writing 1, writing 0 has no effect. So, the only relevant | ||
380 | * information is the single bit we're interested in, all others | ||
381 | * should be written as 0 so they will be left unchanged. | ||
382 | */ | ||
383 | register_value = ACPI_REGISTER_PREPARE_BITS(value, | ||
384 | bit_reg_info-> | ||
385 | bit_position, | ||
386 | bit_reg_info-> | ||
387 | access_bit_mask); | ||
437 | 388 | ||
438 | status = acpi_hw_register_write(ACPI_REGISTER_PM2_CONTROL, | 389 | /* No need to write the register if value is all zeros */ |
439 | (u8) (register_value)); | ||
440 | break; | ||
441 | 390 | ||
442 | default: | 391 | if (register_value) { |
443 | break; | 392 | status = |
393 | acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, | ||
394 | register_value); | ||
395 | } | ||
444 | } | 396 | } |
445 | 397 | ||
446 | unlock_and_exit: | 398 | ACPI_DEBUG_PRINT((ACPI_DB_IO, |
447 | 399 | "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n", | |
448 | acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); | 400 | register_id, bit_reg_info->parent_register, value, |
449 | 401 | register_value)); | |
450 | /* Normalize the value that was read */ | ||
451 | 402 | ||
452 | ACPI_DEBUG_EXEC(register_value = | 403 | unlock_and_exit: |
453 | ((register_value & bit_reg_info->access_bit_mask) >> | ||
454 | bit_reg_info->bit_position)); | ||
455 | 404 | ||
456 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | 405 | acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); |
457 | "Set bits: %8.8X actual %8.8X register %X\n", value, | ||
458 | register_value, bit_reg_info->parent_register)); | ||
459 | return_ACPI_STATUS(status); | 406 | return_ACPI_STATUS(status); |
460 | } | 407 | } |
461 | 408 | ||