diff options
| -rw-r--r-- | drivers/acpi/acpica/hwregs.c | 146 |
1 files changed, 9 insertions, 137 deletions
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index daceb80022b0..3b7fb99362b6 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c | |||
| @@ -306,12 +306,6 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) | |||
| 306 | acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) | 306 | acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) |
| 307 | { | 307 | { |
| 308 | u64 address; | 308 | u64 address; |
| 309 | u8 access_width; | ||
| 310 | u32 bit_width; | ||
| 311 | u8 bit_offset; | ||
| 312 | u64 value64; | ||
| 313 | u32 new_value32, old_value32; | ||
| 314 | u8 index; | ||
| 315 | acpi_status status; | 309 | acpi_status status; |
| 316 | 310 | ||
| 317 | ACPI_FUNCTION_NAME(hw_write); | 311 | ACPI_FUNCTION_NAME(hw_write); |
| @@ -323,145 +317,23 @@ acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) | |||
| 323 | return (status); | 317 | return (status); |
| 324 | } | 318 | } |
| 325 | 319 | ||
| 326 | /* Convert access_width into number of bits based */ | ||
| 327 | |||
| 328 | access_width = acpi_hw_get_access_bit_width(reg, 32); | ||
| 329 | bit_width = reg->bit_offset + reg->bit_width; | ||
| 330 | bit_offset = reg->bit_offset; | ||
| 331 | |||
| 332 | /* | 320 | /* |
| 333 | * Two address spaces supported: Memory or IO. PCI_Config is | 321 | * Two address spaces supported: Memory or IO. PCI_Config is |
| 334 | * not supported here because the GAS structure is insufficient | 322 | * not supported here because the GAS structure is insufficient |
| 335 | */ | 323 | */ |
| 336 | index = 0; | 324 | if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
| 337 | while (bit_width) { | 325 | status = acpi_os_write_memory((acpi_physical_address) |
| 338 | /* | 326 | address, (u64)value, |
| 339 | * Use offset style bit reads because "Index * AccessWidth" is | 327 | reg->bit_width); |
| 340 | * ensured to be less than 32-bits by acpi_hw_validate_register(). | 328 | } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ |
| 341 | */ | 329 | |
| 342 | new_value32 = ACPI_GET_BITS(&value, index * access_width, | 330 | status = acpi_hw_write_port((acpi_io_address) |
| 343 | ACPI_MASK_BITS_ABOVE_32 | 331 | address, value, reg->bit_width); |
| 344 | (access_width)); | ||
| 345 | |||
| 346 | if (bit_offset >= access_width) { | ||
| 347 | bit_offset -= access_width; | ||
| 348 | } else { | ||
| 349 | /* | ||
| 350 | * Use offset style bit masks because access_width is ensured | ||
| 351 | * to be less than 32-bits by acpi_hw_validate_register() and | ||
| 352 | * bit_offset/bit_width is less than access_width here. | ||
| 353 | */ | ||
| 354 | if (bit_offset) { | ||
| 355 | new_value32 &= ACPI_MASK_BITS_BELOW(bit_offset); | ||
| 356 | } | ||
| 357 | if (bit_width < access_width) { | ||
| 358 | new_value32 &= ACPI_MASK_BITS_ABOVE(bit_width); | ||
| 359 | } | ||
| 360 | |||
| 361 | if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { | ||
| 362 | if (bit_offset || bit_width < access_width) { | ||
| 363 | /* | ||
| 364 | * Read old values in order not to modify the bits that | ||
| 365 | * are beyond the register bit_width/bit_offset setting. | ||
| 366 | */ | ||
| 367 | status = | ||
| 368 | acpi_os_read_memory((acpi_physical_address) | ||
| 369 | address + | ||
| 370 | index * | ||
| 371 | ACPI_DIV_8 | ||
| 372 | (access_width), | ||
| 373 | &value64, | ||
| 374 | access_width); | ||
| 375 | old_value32 = (u32)value64; | ||
| 376 | |||
| 377 | /* | ||
| 378 | * Use offset style bit masks because access_width is | ||
| 379 | * ensured to be less than 32-bits by | ||
| 380 | * acpi_hw_validate_register() and bit_offset/bit_width is | ||
| 381 | * less than access_width here. | ||
| 382 | */ | ||
| 383 | if (bit_offset) { | ||
| 384 | old_value32 &= | ||
| 385 | ACPI_MASK_BITS_ABOVE | ||
| 386 | (bit_offset); | ||
| 387 | bit_offset = 0; | ||
| 388 | } | ||
| 389 | if (bit_width < access_width) { | ||
| 390 | old_value32 &= | ||
| 391 | ACPI_MASK_BITS_BELOW | ||
| 392 | (bit_width); | ||
| 393 | } | ||
| 394 | |||
| 395 | new_value32 |= old_value32; | ||
| 396 | } | ||
| 397 | |||
| 398 | value64 = (u64)new_value32; | ||
| 399 | status = | ||
| 400 | acpi_os_write_memory((acpi_physical_address) | ||
| 401 | address + | ||
| 402 | index * | ||
| 403 | ACPI_DIV_8 | ||
| 404 | (access_width), | ||
| 405 | value64, access_width); | ||
| 406 | } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ | ||
| 407 | |||
| 408 | if (bit_offset || bit_width < access_width) { | ||
| 409 | /* | ||
| 410 | * Read old values in order not to modify the bits that | ||
| 411 | * are beyond the register bit_width/bit_offset setting. | ||
| 412 | */ | ||
| 413 | status = | ||
| 414 | acpi_hw_read_port((acpi_io_address) | ||
| 415 | address + | ||
| 416 | index * | ||
| 417 | ACPI_DIV_8 | ||
| 418 | (access_width), | ||
| 419 | &old_value32, | ||
| 420 | access_width); | ||
| 421 | |||
| 422 | /* | ||
| 423 | * Use offset style bit masks because access_width is | ||
| 424 | * ensured to be less than 32-bits by | ||
| 425 | * acpi_hw_validate_register() and bit_offset/bit_width is | ||
| 426 | * less than access_width here. | ||
| 427 | */ | ||
| 428 | if (bit_offset) { | ||
| 429 | old_value32 &= | ||
| 430 | ACPI_MASK_BITS_ABOVE | ||
| 431 | (bit_offset); | ||
| 432 | bit_offset = 0; | ||
| 433 | } | ||
| 434 | if (bit_width < access_width) { | ||
| 435 | old_value32 &= | ||
| 436 | ACPI_MASK_BITS_BELOW | ||
| 437 | (bit_width); | ||
| 438 | } | ||
| 439 | |||
| 440 | new_value32 |= old_value32; | ||
| 441 | } | ||
| 442 | |||
| 443 | status = acpi_hw_write_port((acpi_io_address) | ||
| 444 | address + | ||
| 445 | index * | ||
| 446 | ACPI_DIV_8 | ||
| 447 | (access_width), | ||
| 448 | new_value32, | ||
| 449 | access_width); | ||
| 450 | } | ||
| 451 | } | ||
| 452 | |||
| 453 | /* | ||
| 454 | * Index * access_width is ensured to be less than 32-bits by | ||
| 455 | * acpi_hw_validate_register(). | ||
| 456 | */ | ||
| 457 | bit_width -= | ||
| 458 | bit_width > access_width ? access_width : bit_width; | ||
| 459 | index++; | ||
| 460 | } | 332 | } |
| 461 | 333 | ||
| 462 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | 334 | ACPI_DEBUG_PRINT((ACPI_DB_IO, |
| 463 | "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", | 335 | "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", |
| 464 | value, access_width, ACPI_FORMAT_UINT64(address), | 336 | value, reg->bit_width, ACPI_FORMAT_UINT64(address), |
| 465 | acpi_ut_get_region_name(reg->space_id))); | 337 | acpi_ut_get_region_name(reg->space_id))); |
| 466 | 338 | ||
| 467 | return (status); | 339 | return (status); |
