Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6b5774c authored by Bob Moore's avatar Bob Moore Committed by Len Brown
Browse files

ACPICA: Add 64-bit support to acpi_read and acpi_write



Needed by drivers for new ACPi tables.  Internal versions of
these functions still use 32-bit max transfers, in order to
minimize disruption and stack use for the standard ACPI registers
(FADT-based).

Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent f8d80cdf
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -62,6 +62,14 @@ u32 acpi_hw_get_mode(void);
/*
 * hwregs - ACPI Register I/O
 */
acpi_status
acpi_hw_validate_register(struct acpi_generic_address *reg,
			  u8 max_bit_width, u64 *address);

acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg);

acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg);

struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id);

acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control);
+4 −4
Original line number Diff line number Diff line
@@ -424,7 +424,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
			/* Read the Status Register */

			status =
			    acpi_read(&status_reg,
			    acpi_hw_read(&status_reg,
					 &gpe_register_info->status_address);
			if (ACPI_FAILURE(status)) {
				goto unlock_and_exit;
@@ -433,7 +433,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
			/* Read the Enable Register */

			status =
			    acpi_read(&enable_reg,
			    acpi_hw_read(&enable_reg,
					 &gpe_register_info->enable_address);
			if (ACPI_FAILURE(status)) {
				goto unlock_and_exit;
+2 −2
Original line number Diff line number Diff line
@@ -843,14 +843,14 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)

		/* Disable all GPEs within this register */

		status = acpi_write(0x00, &this_register->enable_address);
		status = acpi_hw_write(0x00, &this_register->enable_address);
		if (ACPI_FAILURE(status)) {
			goto error_exit;
		}

		/* Clear any pending GPE events within this register */

		status = acpi_write(0xFF, &this_register->status_address);
		status = acpi_hw_write(0xFF, &this_register->status_address);
		if (ACPI_FAILURE(status)) {
			goto error_exit;
		}
+17 −17
Original line number Diff line number Diff line
@@ -82,7 +82,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)

	/* Get current value of the enable register that contains this GPE */

	status = acpi_read(&enable_mask, &gpe_register_info->enable_address);
	status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
	if (ACPI_FAILURE(status)) {
		return (status);
	}
@@ -95,7 +95,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)

	/* Write the updated enable mask */

	status = acpi_write(enable_mask, &gpe_register_info->enable_address);
	status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
	return (status);
}

@@ -130,7 +130,7 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)

	/* Write the entire GPE (runtime) enable register */

	status = acpi_write(gpe_register_info->enable_for_run,
	status = acpi_hw_write(gpe_register_info->enable_for_run,
			       &gpe_register_info->enable_address);

	return (status);
@@ -163,7 +163,7 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
	 * Write a one to the appropriate bit in the status register to
	 * clear this GPE.
	 */
	status = acpi_write(register_bit,
	status = acpi_hw_write(register_bit,
			       &gpe_event_info->register_info->status_address);

	return (status);
@@ -222,7 +222,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,

	/* GPE currently active (status bit == 1)? */

	status = acpi_read(&in_byte, &gpe_register_info->status_address);
	status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
	if (ACPI_FAILURE(status)) {
		goto unlock_and_exit;
	}
@@ -266,7 +266,7 @@ acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
		/* Disable all GPEs in this register */

		status =
		    acpi_write(0x00,
		    acpi_hw_write(0x00,
				  &gpe_block->register_info[i].enable_address);
		if (ACPI_FAILURE(status)) {
			return (status);
@@ -303,7 +303,7 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
		/* Clear status on all GPEs in this register */

		status =
		    acpi_write(0xFF,
		    acpi_hw_write(0xFF,
				  &gpe_block->register_info[i].status_address);
		if (ACPI_FAILURE(status)) {
			return (status);
@@ -345,9 +345,9 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,

		/* Enable all "runtime" GPEs in this register */

		status = acpi_write(gpe_block->register_info[i].enable_for_run,
				    &gpe_block->register_info[i].
				    enable_address);
		status =
		    acpi_hw_write(gpe_block->register_info[i].enable_for_run,
				  &gpe_block->register_info[i].enable_address);
		if (ACPI_FAILURE(status)) {
			return (status);
		}
@@ -387,9 +387,9 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,

		/* Enable all "wake" GPEs in this register */

		status = acpi_write(gpe_block->register_info[i].enable_for_wake,
				    &gpe_block->register_info[i].
				    enable_address);
		status =
		    acpi_hw_write(gpe_block->register_info[i].enable_for_wake,
				  &gpe_block->register_info[i].enable_address);
		if (ACPI_FAILURE(status)) {
			return (status);
		}
+194 −12
Original line number Diff line number Diff line
@@ -62,6 +62,184 @@ acpi_hw_write_multiple(u32 value,
		       struct acpi_generic_address *register_a,
		       struct acpi_generic_address *register_b);

/******************************************************************************
 *
 * FUNCTION:    acpi_hw_validate_register
 *
 * PARAMETERS:  Reg                 - GAS register structure
 *              max_bit_width       - Max bit_width supported (32 or 64)
 *              Address             - Pointer to where the gas->address
 *                                    is returned
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
 *              pointer, Address, space_id, bit_width, and bit_offset.
 *
 ******************************************************************************/

acpi_status
acpi_hw_validate_register(struct acpi_generic_address *reg,
			  u8 max_bit_width, u64 *address)
{

	/* Must have a valid pointer to a GAS structure */

	if (!reg) {
		return (AE_BAD_PARAMETER);
	}

	/*
	 * Copy the target address. This handles possible alignment issues.
	 * Address must not be null. A null address also indicates an optional
	 * ACPI register that is not supported, so no error message.
	 */
	ACPI_MOVE_64_TO_64(address, &reg->address);
	if (!(*address)) {
		return (AE_BAD_ADDRESS);
	}

	/* Validate the space_iD */

	if ((reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
	    (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
		ACPI_ERROR((AE_INFO,
			    "Unsupported address space: 0x%X", reg->space_id));
		return (AE_SUPPORT);
	}

	/* Validate the bit_width */

	if ((reg->bit_width != 8) &&
	    (reg->bit_width != 16) &&
	    (reg->bit_width != 32) && (reg->bit_width != max_bit_width)) {
		ACPI_ERROR((AE_INFO,
			    "Unsupported register bit width: 0x%X",
			    reg->bit_width));
		return (AE_SUPPORT);
	}

	/* Validate the bit_offset. Just a warning for now. */

	if (reg->bit_offset != 0) {
		ACPI_WARNING((AE_INFO,
			      "Unsupported register bit offset: 0x%X",
			      reg->bit_offset));
	}

	return (AE_OK);
}

/******************************************************************************
 *
 * FUNCTION:    acpi_hw_read
 *
 * PARAMETERS:  Value               - Where the value is returned
 *              Reg                 - GAS register structure
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
 *              version of acpi_read, used internally since the overhead of
 *              64-bit values is not needed.
 *
 * LIMITATIONS: <These limitations also apply to acpi_hw_write>
 *      bit_width must be exactly 8, 16, or 32.
 *      space_iD must be system_memory or system_iO.
 *      bit_offset and access_width are currently ignored, as there has
 *          not been a need to implement these.
 *
 ******************************************************************************/

acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
{
	u64 address;
	acpi_status status;

	ACPI_FUNCTION_NAME(hw_read);

	/* Validate contents of the GAS register */

	status = acpi_hw_validate_register(reg, 32, &address);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	/* Initialize entire 32-bit return value to zero */

	*value = 0;

	/*
	 * Two address spaces supported: Memory or IO. PCI_Config is
	 * not supported here because the GAS structure is insufficient
	 */
	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
		status = acpi_os_read_memory((acpi_physical_address)
					     address, value, reg->bit_width);
	} else {		/* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */

		status = acpi_hw_read_port((acpi_io_address)
					   address, value, reg->bit_width);
	}

	ACPI_DEBUG_PRINT((ACPI_DB_IO,
			  "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
			  *value, reg->bit_width, ACPI_FORMAT_UINT64(address),
			  acpi_ut_get_region_name(reg->space_id)));

	return (status);
}

/******************************************************************************
 *
 * FUNCTION:    acpi_hw_write
 *
 * PARAMETERS:  Value               - Value to be written
 *              Reg                 - GAS register structure
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max
 *              version of acpi_write, used internally since the overhead of
 *              64-bit values is not needed.
 *
 ******************************************************************************/

acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
{
	u64 address;
	acpi_status status;

	ACPI_FUNCTION_NAME(hw_write);

	/* Validate contents of the GAS register */

	status = acpi_hw_validate_register(reg, 32, &address);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	/*
	 * Two address spaces supported: Memory or IO. PCI_Config is
	 * not supported here because the GAS structure is insufficient
	 */
	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
		status = acpi_os_write_memory((acpi_physical_address)
					      address, value, reg->bit_width);
	} else {		/* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */

		status = acpi_hw_write_port((acpi_io_address)
					    address, value, reg->bit_width);
	}

	ACPI_DEBUG_PRINT((ACPI_DB_IO,
			  "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
			  value, reg->bit_width, ACPI_FORMAT_UINT64(address),
			  acpi_ut_get_region_name(reg->space_id)));

	return (status);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_hw_clear_acpi_status
@@ -152,14 +330,15 @@ acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control)

	ACPI_FUNCTION_TRACE(hw_write_pm1_control);

	status = acpi_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block);
	status =
	    acpi_hw_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	if (acpi_gbl_FADT.xpm1b_control_block.address) {
		status =
		    acpi_write(pm1b_control,
		    acpi_hw_write(pm1b_control,
				  &acpi_gbl_FADT.xpm1b_control_block);
	}
	return_ACPI_STATUS(status);
@@ -218,12 +397,13 @@ acpi_hw_register_read(u32 register_id, u32 * return_value)

	case ACPI_REGISTER_PM2_CONTROL:	/* 8-bit access */

		status = acpi_read(&value, &acpi_gbl_FADT.xpm2_control_block);
		status =
		    acpi_hw_read(&value, &acpi_gbl_FADT.xpm2_control_block);
		break;

	case ACPI_REGISTER_PM_TIMER:	/* 32-bit access */

		status = acpi_read(&value, &acpi_gbl_FADT.xpm_timer_block);
		status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm_timer_block);
		break;

	case ACPI_REGISTER_SMI_COMMAND_BLOCK:	/* 8-bit access */
@@ -340,7 +520,8 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value)
		 * as per the ACPI spec.
		 */
		status =
		    acpi_read(&read_value, &acpi_gbl_FADT.xpm2_control_block);
		    acpi_hw_read(&read_value,
				 &acpi_gbl_FADT.xpm2_control_block);
		if (ACPI_FAILURE(status)) {
			goto exit;
		}
@@ -350,12 +531,13 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value)
		ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS,
				 read_value);

		status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block);
		status =
		    acpi_hw_write(value, &acpi_gbl_FADT.xpm2_control_block);
		break;

	case ACPI_REGISTER_PM_TIMER:	/* 32-bit access */

		status = acpi_write(value, &acpi_gbl_FADT.xpm_timer_block);
		status = acpi_hw_write(value, &acpi_gbl_FADT.xpm_timer_block);
		break;

	case ACPI_REGISTER_SMI_COMMAND_BLOCK:	/* 8-bit access */
@@ -401,7 +583,7 @@ acpi_hw_read_multiple(u32 *value,

	/* The first register is always required */

	status = acpi_read(&value_a, register_a);
	status = acpi_hw_read(&value_a, register_a);
	if (ACPI_FAILURE(status)) {
		return (status);
	}
@@ -409,7 +591,7 @@ acpi_hw_read_multiple(u32 *value,
	/* Second register is optional */

	if (register_b->address) {
		status = acpi_read(&value_b, register_b);
		status = acpi_hw_read(&value_b, register_b);
		if (ACPI_FAILURE(status)) {
			return (status);
		}
@@ -452,7 +634,7 @@ acpi_hw_write_multiple(u32 value,

	/* The first register is always required */

	status = acpi_write(value, register_a);
	status = acpi_hw_write(value, register_a);
	if (ACPI_FAILURE(status)) {
		return (status);
	}
@@ -470,7 +652,7 @@ acpi_hw_write_multiple(u32 value,
	 * and writes have no side effects"
	 */
	if (register_b->address) {
		status = acpi_write(value, register_b);
		status = acpi_hw_write(value, register_b);
	}

	return (status);
Loading