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

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

ACPICA: Split out PM1 status registers from the FADT



Add new globals for the PM1 status registers (A/B), similar to the
way the PM1 enable registers are handled. Instead of overloading
the FADT Event Register blocks. This makes the code clearer and
less prone to error.

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 6fc69d8b
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -148,9 +148,12 @@ ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list;
ACPI_EXTERN struct acpi_table_fadt acpi_gbl_FADT;
ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS;

/* These addresses are calculated from FADT address values */
/* These addresses are calculated from the FADT Event Block addresses */

ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_status;
ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable;

ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_status;
ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable;

/*
+10 −8
Original line number Diff line number Diff line
@@ -72,21 +72,23 @@ acpi_status acpi_hw_clear_acpi_status(void)

	ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
			  ACPI_BITMASK_ALL_FIXED_STATUS,
			  (u16) acpi_gbl_FADT.xpm1a_event_block.address));
			  (u16) acpi_gbl_xpm1a_status.address));

	lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);

	/* Clear the fixed events */

	status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
					ACPI_BITMASK_ALL_FIXED_STATUS);
	if (ACPI_FAILURE(status)) {
		goto unlock_and_exit;
	}

	/* Clear the fixed events */
	/* Write PM1B register if present */

	if (acpi_gbl_FADT.xpm1b_event_block.address) {
	if (acpi_gbl_xpm1b_status.address) {
		status = acpi_write(ACPI_BITMASK_ALL_FIXED_STATUS,
				    &acpi_gbl_FADT.xpm1b_event_block);
				    &acpi_gbl_xpm1b_status);
		if (ACPI_FAILURE(status)) {
			goto unlock_and_exit;
		}
@@ -150,14 +152,14 @@ acpi_hw_register_read(u32 register_id, u32 * return_value)
	switch (register_id) {
	case ACPI_REGISTER_PM1_STATUS:	/* 16-bit access */

		status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_event_block);
		status = acpi_read(&value1, &acpi_gbl_xpm1a_status);
		if (ACPI_FAILURE(status)) {
			goto exit;
		}

		/* PM1B is optional */

		status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_event_block);
		status = acpi_read(&value2, &acpi_gbl_xpm1b_status);
		value1 |= value2;
		break;

@@ -267,14 +269,14 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value)

		/* Now we can write the data */

		status = acpi_write(value, &acpi_gbl_FADT.xpm1a_event_block);
		status = acpi_write(value, &acpi_gbl_xpm1a_status);
		if (ACPI_FAILURE(status)) {
			goto exit;
		}

		/* PM1B is optional */

		status = acpi_write(value, &acpi_gbl_FADT.xpm1b_event_block);
		status = acpi_write(value, &acpi_gbl_xpm1b_status);
		break;

	case ACPI_REGISTER_PM1_ENABLE:	/* 16-bit access */
+133 −113
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ static void acpi_tb_convert_fadt(void);

static void acpi_tb_validate_fadt(void);

static void acpi_tb_setup_fadt_registers(void);

/* Table for conversion of FADT to common internal format and FADT validation */

typedef struct acpi_fadt_info {
@@ -132,6 +134,35 @@ static struct acpi_fadt_info fadt_info_table[] = {

#define ACPI_FADT_INFO_ENTRIES        (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info))

/* Table used to split Event Blocks into separate status/enable registers */

typedef struct acpi_fadt_pm_info {
	struct acpi_generic_address *target;
	u8 source;
	u8 register_num;

} acpi_fadt_pm_info;

static struct acpi_fadt_pm_info fadt_pm_info_table[] = {
	{&acpi_gbl_xpm1a_status,
	 ACPI_FADT_OFFSET(xpm1a_event_block),
	 0},

	{&acpi_gbl_xpm1a_enable,
	 ACPI_FADT_OFFSET(xpm1a_event_block),
	 1},

	{&acpi_gbl_xpm1b_status,
	 ACPI_FADT_OFFSET(xpm1b_event_block),
	 0},

	{&acpi_gbl_xpm1b_enable,
	 ACPI_FADT_OFFSET(xpm1b_event_block),
	 1}
};

#define ACPI_FADT_PM_INFO_ENTRIES   (sizeof (fadt_pm_info_table) / sizeof (struct acpi_fadt_pm_info))

/*******************************************************************************
 *
 * FUNCTION:    acpi_tb_init_generic_address
@@ -207,7 +238,7 @@ void acpi_tb_parse_fadt(u32 table_index)
	 */
	(void)acpi_tb_verify_checksum(table, length);

	/* Obtain a local copy of the FADT in common ACPI 2.0+ format */
	/* Create a local copy of the FADT in common ACPI 2.0+ format */

	acpi_tb_create_local_fadt(table, length);

@@ -265,11 +296,17 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
	ACPI_MEMCPY(&acpi_gbl_FADT, table,
		    ACPI_MIN(length, sizeof(struct acpi_table_fadt)));

	/*
	 * 1) Convert the local copy of the FADT to the common internal format
	 * 2) Validate some of the important values within the FADT
	 */
	/* Convert the local copy of the FADT to the common internal format */

	acpi_tb_convert_fadt();

	/* Validate FADT values now, before we make any changes */

	acpi_tb_validate_fadt();

	/* Initialize the global ACPI register structures */

	acpi_tb_setup_fadt_registers();
}

/*******************************************************************************
@@ -303,8 +340,6 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)

static void acpi_tb_convert_fadt(void)
{
	u8 pm1_register_bit_width;
	u8 pm1_register_byte_width;
	struct acpi_generic_address *target64;
	u32 i;

@@ -379,112 +414,6 @@ static void acpi_tb_convert_fadt(void)
									  address32));
		}
	}

	/* Validate FADT values now, before we make any changes */

	acpi_tb_validate_fadt();

	/*
	 * Optionally check all register lengths against the default values and
	 * update them if they are incorrect.
	 */
	if (acpi_gbl_use_default_register_widths) {
		for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
			target64 =
			    ACPI_ADD_PTR(struct acpi_generic_address,
					 &acpi_gbl_FADT,
					 fadt_info_table[i].address64);

			/*
			 * If a valid register (Address != 0) and the (default_length > 0)
			 * (Not a GPE register), then check the width against the default.
			 */
			if ((target64->address) &&
			    (fadt_info_table[i].default_length > 0) &&
			    (fadt_info_table[i].default_length !=
			     target64->bit_width)) {
				ACPI_WARNING((AE_INFO,
					      "Invalid length for %s: %d, using default %d",
					      fadt_info_table[i].name,
					      target64->bit_width,
					      fadt_info_table[i].
					      default_length));

				/* Incorrect size, set width to the default */

				target64->bit_width =
				    fadt_info_table[i].default_length;
			}
		}
	}

	/*
	 * Get the length of the individual PM1 registers (enable and status).
	 * Each register is defined to be (event block length / 2).
	 */
	pm1_register_bit_width =
	    (u8)ACPI_DIV_2(acpi_gbl_FADT.xpm1a_event_block.bit_width);
	pm1_register_byte_width = (u8)ACPI_DIV_8(pm1_register_bit_width);

	/*
	 * Adjust the lengths of the PM1 Event Blocks so that they can be used to
	 * access the PM1 status register(s). Use (width / 2)
	 */
	acpi_gbl_FADT.xpm1a_event_block.bit_width = pm1_register_bit_width;
	acpi_gbl_FADT.xpm1b_event_block.bit_width = pm1_register_bit_width;

	/*
	 * Calculate separate GAS structs for the PM1 Enable registers.
	 * These addresses do not appear (directly) in the FADT, so it is
	 * useful to calculate them once, here.
	 *
	 * The PM event blocks are split into two register blocks, first is the
	 * PM Status Register block, followed immediately by the PM Enable
	 * Register block. Each is of length (xpm1x_event_block.bit_width/2).
	 *
	 * On various systems the v2 fields (and particularly the bit widths)
	 * cannot be relied upon, though. Hence resort to using the v1 length
	 * here (and warn about the inconsistency).
	 */
	if (acpi_gbl_FADT.xpm1a_event_block.bit_width
	    != acpi_gbl_FADT.pm1_event_length * 8)
		printk(KERN_WARNING "FADT: "
		       "X_PM1a_EVT_BLK.bit_width (%u) does not match"
		       " PM1_EVT_LEN (%u)\n",
		       acpi_gbl_FADT.xpm1a_event_block.bit_width,
		       acpi_gbl_FADT.pm1_event_length);

	/* The PM1A register block is required */

	acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
				     acpi_gbl_FADT.xpm1a_event_block.space_id,
				     pm1_register_byte_width,
				     (acpi_gbl_FADT.xpm1a_event_block.address +
				      pm1_register_byte_width));
	/* Don't forget to copy space_id of the GAS */
	acpi_gbl_xpm1a_enable.space_id =
	    acpi_gbl_FADT.xpm1a_event_block.space_id;

	/* The PM1B register block is optional, ignore if not present */

	if (acpi_gbl_FADT.xpm1b_event_block.address) {
		if (acpi_gbl_FADT.xpm1b_event_block.bit_width
		    != acpi_gbl_FADT.pm1_event_length * 8)
			printk(KERN_WARNING "FADT: "
			       "X_PM1b_EVT_BLK.bit_width (%u) does not match"
			       " PM1_EVT_LEN (%u)\n",
			       acpi_gbl_FADT.xpm1b_event_block.bit_width,
			       acpi_gbl_FADT.pm1_event_length);
		acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
					     acpi_gbl_FADT.xpm1b_event_block.space_id,
					     pm1_register_byte_width,
					     (acpi_gbl_FADT.xpm1b_event_block.
					      address + pm1_register_byte_width));
		/* Don't forget to copy space_id of the GAS */
		acpi_gbl_xpm1b_enable.space_id =
		    acpi_gbl_FADT.xpm1b_event_block.space_id;

	}
}

/******************************************************************************
@@ -607,3 +536,94 @@ static void acpi_tb_validate_fadt(void)
		}
	}
}

/******************************************************************************
 *
 * FUNCTION:    acpi_tb_setup_fadt_registers
 *
 * PARAMETERS:  None, uses acpi_gbl_FADT.
 *
 * RETURN:      None
 *
 * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally,
 *              force FADT register definitions to their default lengths.
 *
 ******************************************************************************/

static void acpi_tb_setup_fadt_registers(void)
{
	struct acpi_generic_address *target64;
	struct acpi_generic_address *source64;
	u8 pm1_register_byte_width;
	u32 i;

	/*
	 * Optionally check all register lengths against the default values and
	 * update them if they are incorrect.
	 */
	if (acpi_gbl_use_default_register_widths) {
		for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
			target64 =
			    ACPI_ADD_PTR(struct acpi_generic_address,
					 &acpi_gbl_FADT,
					 fadt_info_table[i].address64);

			/*
			 * If a valid register (Address != 0) and the (default_length > 0)
			 * (Not a GPE register), then check the width against the default.
			 */
			if ((target64->address) &&
			    (fadt_info_table[i].default_length > 0) &&
			    (fadt_info_table[i].default_length !=
			     target64->bit_width)) {
				ACPI_WARNING((AE_INFO,
					      "Invalid length for %s: %d, using default %d",
					      fadt_info_table[i].name,
					      target64->bit_width,
					      fadt_info_table[i].
					      default_length));

				/* Incorrect size, set width to the default */

				target64->bit_width =
				    fadt_info_table[i].default_length;
			}
		}
	}

	/*
	 * Get the length of the individual PM1 registers (enable and status).
	 * Each register is defined to be (event block length / 2). Extra divide
	 * by 8 converts bits to bytes.
	 */
	pm1_register_byte_width =
	    (u8)ACPI_DIV_16(acpi_gbl_FADT.xpm1a_event_block.bit_width);

	/*
	 * Calculate separate GAS structs for the PM1x (A/B) Status and Enable
	 * registers. These addresses do not appear (directly) in the FADT, so it
	 * is useful to pre-calculate them from the PM1 Event Block definitions.
	 *
	 * The PM event blocks are split into two register blocks, first is the
	 * PM Status Register block, followed immediately by the PM Enable
	 * Register block. Each is of length (pm1_event_length/2)
	 *
	 * Note: The PM1A event block is required by the ACPI specification.
	 * However, the PM1B event block is optional and is rarely, if ever,
	 * used.
	 */

	for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++) {
		source64 =
		    ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT,
				 fadt_pm_info_table[i].source);

		acpi_tb_init_generic_address(fadt_pm_info_table[i].target,
					     source64->space_id,
					     pm1_register_byte_width,
					     source64->address +
					     (fadt_pm_info_table[i].
					      register_num *
					      pm1_register_byte_width));
	}
}