diff options
Diffstat (limited to 'drivers/acpi/acpica/hwregs.c')
-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); |