Beispiel #1
0
static int
acpi_ec_wait (
	struct acpi_ec		*ec,
	u8			event)
{
	u32			acpi_ec_status = 0;
	u32			i = ACPI_EC_UDELAY_COUNT;

	if (!ec)
		return -EINVAL;

	/* Poll the EC status register waiting for the event to occur. */
	switch (event) {
	case ACPI_EC_EVENT_OBF:
		do {
			acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr);
			if (acpi_ec_status & ACPI_EC_FLAG_OBF)
				return 0;
			udelay(ACPI_EC_UDELAY);
		} while (--i>0);
		break;
	case ACPI_EC_EVENT_IBE:
		do {
			acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr);
			if (!(acpi_ec_status & ACPI_EC_FLAG_IBF))
				return 0;
			udelay(ACPI_EC_UDELAY);
		} while (--i>0);
		break;
	default:
		return -EINVAL;
	}

	return -ETIME;
}
Beispiel #2
0
acpi_status
acpi_hw_enable_gpe (
	struct acpi_gpe_event_info      *gpe_event_info)
{
	u32                             in_byte;
	acpi_status                     status;


	ACPI_FUNCTION_ENTRY ();


	/*
	 * Read the current value of the register, set the appropriate bit
	 * to enable the GPE, and write out the new register.
	 */
	status = acpi_hw_low_level_read (8, &in_byte,
			  &gpe_event_info->register_info->enable_address);
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	/* Write with the new GPE bit enabled */

	status = acpi_hw_low_level_write (8, (in_byte | gpe_event_info->bit_mask),
			  &gpe_event_info->register_info->enable_address);

	return (status);
}
Beispiel #3
0
acpi_status
acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
		       acpi_event_status * event_status)
{
	u32 in_byte;
	u8 register_bit;
	struct acpi_gpe_register_info *gpe_register_info;
	acpi_status status;
	acpi_event_status local_event_status = 0;

	ACPI_FUNCTION_ENTRY();

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

	/* Get the info block for the entire GPE register */

	gpe_register_info = gpe_event_info->register_info;

	/* Get the register bitmask for this GPE */

	register_bit = (u8)
	    (1 <<
	     (gpe_event_info->gpe_number -
	      gpe_event_info->register_info->base_gpe_number));

	/* GPE currently enabled? (enabled for runtime?) */

	if (register_bit & gpe_register_info->enable_for_run) {
		local_event_status |= ACPI_EVENT_FLAG_ENABLED;
	}

	/* GPE enabled for wake? */

	if (register_bit & gpe_register_info->enable_for_wake) {
		local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
	}

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

	status =
	    acpi_hw_low_level_read(8, &in_byte,
				   &gpe_register_info->status_address);
	if (ACPI_FAILURE(status)) {
		goto unlock_and_exit;
	}

	if (register_bit & in_byte) {
		local_event_status |= ACPI_EVENT_FLAG_SET;
	}

	/* Set return value */

	(*event_status) = local_event_status;

      unlock_and_exit:
	return (status);
}
Beispiel #4
0
static int
acpi_ec_read (
	struct acpi_ec		*ec,
	u8			address,
	u32			*data)
{
	acpi_status		status = AE_OK;
	int			result = 0;
	unsigned long		flags = 0;
	u32			glk = 0;

	ACPI_FUNCTION_TRACE("acpi_ec_read");

	if (!ec || !data)
		return_VALUE(-EINVAL);

	*data = 0;

	if (ec->global_lock) {
		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
		if (ACPI_FAILURE(status))
			return_VALUE(-ENODEV);
	}
	
	spin_lock_irqsave(&ec->lock, flags);

	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr);
	result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
	if (result)
		goto end;

	acpi_hw_low_level_write(8, address, &ec->data_addr);
	result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
	if (result)
		goto end;


	acpi_hw_low_level_read(8, data, &ec->data_addr);

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
		*data, address));

end:
	spin_unlock_irqrestore(&ec->lock, flags);

	if (ec->global_lock)
		acpi_release_global_lock(glk);

	return_VALUE(result);
}
Beispiel #5
0
/******************************************************************************
 *
 * FUNCTION:    acpi_get_timer
 *
 * PARAMETERS:  Ticks               - Where the timer value is returned
 *
 * RETURN:      Status and current timer value (ticks)
 *
 * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
 *
 ******************************************************************************/
acpi_status acpi_get_timer(u32 * ticks)
{
	acpi_status status;

	ACPI_FUNCTION_TRACE(acpi_get_timer);

	if (!ticks) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	status =
	    acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT.xpm_timer_block);

	return_ACPI_STATUS(status);
}
Beispiel #6
0
static int
acpi_ec_query (
	struct acpi_ec		*ec,
	u32			*data)
{
	int			result = 0;
	acpi_status		status = AE_OK;
	unsigned long		flags = 0;
	u32			glk = 0;

	ACPI_FUNCTION_TRACE("acpi_ec_query");

	if (!ec || !data)
		return_VALUE(-EINVAL);

	*data = 0;

	if (ec->global_lock) {
		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
		if (ACPI_FAILURE(status))
			return_VALUE(-ENODEV);
	}

	/*
	 * Query the EC to find out which _Qxx method we need to evaluate.
	 * Note that successful completion of the query causes the ACPI_EC_SCI
	 * bit to be cleared (and thus clearing the interrupt source).
	 */
	spin_lock_irqsave(&ec->lock, flags);

	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr);
	result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
	if (result)
		goto end;
	
	acpi_hw_low_level_read(8, data, &ec->data_addr);
	if (!*data)
		result = -ENODATA;

end:
	spin_unlock_irqrestore(&ec->lock, flags);

	if (ec->global_lock)
		acpi_release_global_lock(glk);

	return_VALUE(result);
}
Beispiel #7
0
static acpi_status
acpi_hw_disable_non_wakeup_gpe_block (
	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
	struct acpi_gpe_block_info      *gpe_block)
{
	u32                             i;
	struct acpi_gpe_register_info   *gpe_register_info;
	u32                             in_value;
	acpi_status                     status;


	/* Get the register info for the entire GPE block */

	gpe_register_info = gpe_block->register_info;

	/* Examine each GPE Register within the block */

	for (i = 0; i < gpe_block->register_count; i++) {
		/*
		 * Read the enabled status of all GPEs. We
		 * will be using it to restore all the GPEs later.
		 */
		status = acpi_hw_low_level_read (8, &in_value,
				 &gpe_register_info->enable_address);
		if (ACPI_FAILURE (status)) {
			return (status);
		}

		gpe_register_info->enable = (u8) in_value;

		/*
		 * Disable all GPEs except wakeup GPEs.
		 */
		status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable,
				&gpe_register_info->enable_address);
		if (ACPI_FAILURE (status)) {
			return (status);
		}

		gpe_register_info++;
	}

	return (AE_OK);
}
Beispiel #8
0
acpi_status
acpi_hw_disable_gpe (
	struct acpi_gpe_event_info      *gpe_event_info)
{
	u32                             in_byte;
	acpi_status                     status;
	struct acpi_gpe_register_info   *gpe_register_info;


	ACPI_FUNCTION_ENTRY ();


	/* Get the info block for the entire GPE register */

	gpe_register_info = gpe_event_info->register_info;
	if (!gpe_register_info) {
		return (AE_BAD_PARAMETER);
	}

	/*
	 * Read the current value of the register, clear the appropriate bit,
	 * and write out the new register value to disable the GPE.
	 */
	status = acpi_hw_low_level_read (8, &in_byte,
			  &gpe_register_info->enable_address);
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	/* Write the byte with this GPE bit cleared */

	status = acpi_hw_low_level_write (8, (in_byte & ~(gpe_event_info->bit_mask)),
			  &gpe_register_info->enable_address);
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
	return (AE_OK);
}
Beispiel #9
0
u32
acpi_ev_gpe_detect (
	struct acpi_gpe_xrupt_info      *gpe_xrupt_list)
{
	u32                             int_status = ACPI_INTERRUPT_NOT_HANDLED;
	u8                              enabled_status_byte;
	struct acpi_gpe_register_info   *gpe_register_info;
	u32                             status_reg;
	u32                             enable_reg;
	acpi_status                     status;
	struct acpi_gpe_block_info      *gpe_block;
	acpi_native_uint                i;
	acpi_native_uint                j;


	ACPI_FUNCTION_NAME ("ev_gpe_detect");

	/* Check for the case where there are no GPEs */

	if (!gpe_xrupt_list) {
		return (int_status);
	}

	/* Examine all GPE blocks attached to this interrupt level */

	acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR);
	gpe_block = gpe_xrupt_list->gpe_block_list_head;
	while (gpe_block) {
		/*
		 * Read all of the 8-bit GPE status and enable registers
		 * in this GPE block, saving all of them.
		 * Find all currently active GP events.
		 */
		for (i = 0; i < gpe_block->register_count; i++) {
			/* Get the next status/enable pair */

			gpe_register_info = &gpe_block->register_info[i];

			/* Read the Status Register */

			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &status_reg,
					 &gpe_register_info->status_address);
			if (ACPI_FAILURE (status)) {
				goto unlock_and_exit;
			}

			/* Read the Enable Register */

			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &enable_reg,
					 &gpe_register_info->enable_address);
			if (ACPI_FAILURE (status)) {
				goto unlock_and_exit;
			}

			ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
				"GPE pair: Status %8.8X%8.8X = %02X, Enable %8.8X%8.8X = %02X\n",
				ACPI_FORMAT_UINT64 (
					gpe_register_info->status_address.address),
					status_reg,
				ACPI_FORMAT_UINT64 (
					gpe_register_info->enable_address.address),
					enable_reg));

			/* First check if there is anything active at all in this register */

			enabled_status_byte = (u8) (status_reg & enable_reg);
			if (!enabled_status_byte) {
				/* No active GPEs in this register, move on */

				continue;
			}

			/* Now look at the individual GPEs in this byte register */

			for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
				/* Examine one GPE bit */

				if (enabled_status_byte & acpi_gbl_decode_to8bit[j]) {
					/*
					 * Found an active GPE. Dispatch the event to a handler
					 * or method.
					 */
					int_status |= acpi_ev_gpe_dispatch (
							  &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j],
							  (u32) j + gpe_register_info->base_gpe_number);
				}
			}
		}

		gpe_block = gpe_block->next;
	}

unlock_and_exit:

	acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
	return (int_status);
}
Beispiel #10
0
acpi_status
acpi_hw_get_gpe_status (
	struct acpi_gpe_event_info      *gpe_event_info,
	acpi_event_status               *event_status)
{
	u32                             in_byte;
	u8                              bit_mask;
	struct acpi_gpe_register_info   *gpe_register_info;
	acpi_status                     status;
	acpi_event_status               local_event_status = 0;


	ACPI_FUNCTION_ENTRY ();


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

	/* Get the info block for the entire GPE register */

	gpe_register_info = gpe_event_info->register_info;

	/* Get the register bitmask for this GPE */

	bit_mask = gpe_event_info->bit_mask;

	/* GPE Enabled? */

	status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address);
	if (ACPI_FAILURE (status)) {
		goto unlock_and_exit;
	}

	if (bit_mask & in_byte) {
		local_event_status |= ACPI_EVENT_FLAG_ENABLED;
	}

	/* GPE Enabled for wake? */

	if (bit_mask & gpe_register_info->wake_enable) {
		local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
	}

	/* GPE active (set)? */

	status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address);
	if (ACPI_FAILURE (status)) {
		goto unlock_and_exit;
	}

	if (bit_mask & in_byte) {
		local_event_status |= ACPI_EVENT_FLAG_SET;
	}

	/* Set return value */

	(*event_status) = local_event_status;


unlock_and_exit:
	return (status);
}
Beispiel #11
0
u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
{
	acpi_status status;
	struct acpi_gpe_block_info *gpe_block;
	struct acpi_gpe_register_info *gpe_register_info;
	u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
	u8 enabled_status_byte;
	u32 status_reg;
	u32 enable_reg;
	acpi_cpu_flags flags;
	acpi_native_uint i;
	acpi_native_uint j;

	ACPI_FUNCTION_NAME(ev_gpe_detect);

	/* Check for the case where there are no GPEs */

	if (!gpe_xrupt_list) {
		return (int_status);
	}

	/*
	 * We need to obtain the GPE lock for both the data structs and registers
	 * Note: Not necessary to obtain the hardware lock, since the GPE registers
	 * are owned by the gpe_lock.
	 */
	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);

	/* Examine all GPE blocks attached to this interrupt level */

	gpe_block = gpe_xrupt_list->gpe_block_list_head;
	while (gpe_block) {
		/*
		 * Read all of the 8-bit GPE status and enable registers
		 * in this GPE block, saving all of them.
		 * Find all currently active GP events.
		 */
		for (i = 0; i < gpe_block->register_count; i++) {

			/* Get the next status/enable pair */

			gpe_register_info = &gpe_block->register_info[i];

			/* Read the Status Register */

			status =
			    acpi_hw_low_level_read(ACPI_GPE_REGISTER_WIDTH,
						   &status_reg,
						   &gpe_register_info->
						   status_address);
			if (ACPI_FAILURE(status)) {
				goto unlock_and_exit;
			}

			/* Read the Enable Register */

			status =
			    acpi_hw_low_level_read(ACPI_GPE_REGISTER_WIDTH,
						   &enable_reg,
						   &gpe_register_info->
						   enable_address);
			if (ACPI_FAILURE(status)) {
				goto unlock_and_exit;
			}

			ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
					  "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
					  gpe_register_info->base_gpe_number,
					  status_reg, enable_reg));

			/* Check if there is anything active at all in this register */

			enabled_status_byte = (u8) (status_reg & enable_reg);
			if (!enabled_status_byte) {

				/* No active GPEs in this register, move on */

				continue;
			}

			/* Now look at the individual GPEs in this byte register */

			for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {

				/* Examine one GPE bit */

				if (enabled_status_byte & (1 << j)) {
					/*
					 * Found an active GPE. Dispatch the event to a handler
					 * or method.
					 */
					int_status |=
					    acpi_ev_gpe_dispatch(&gpe_block->
								 event_info[(i *
									     ACPI_GPE_REGISTER_WIDTH)
									    +
									    j],
								 (u32) j +
								 gpe_register_info->
								 base_gpe_number);
				}
			}
		}

		gpe_block = gpe_block->next;
	}

      unlock_and_exit:

	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
	return (int_status);
}
Beispiel #12
0
u32
acpi_ev_gpe_detect (
	struct acpi_gpe_xrupt_info      *gpe_xrupt_list)
{
	u32                             int_status = ACPI_INTERRUPT_NOT_HANDLED;
	u8                              enabled_status_byte;
	u8                              bit_mask;
	struct acpi_gpe_register_info   *gpe_register_info;
	u32                             in_value;
	acpi_status                     status;
	struct acpi_gpe_block_info      *gpe_block;
	u32                             gpe_number;
	u32                             i;
	u32                             j;


	ACPI_FUNCTION_NAME ("ev_gpe_detect");


	/* Examine all GPE blocks attached to this interrupt level */

	acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR);
	gpe_block = gpe_xrupt_list->gpe_block_list_head;
	while (gpe_block) {
		/*
		 * Read all of the 8-bit GPE status and enable registers
		 * in this GPE block, saving all of them.
		 * Find all currently active GP events.
		 */
		for (i = 0; i < gpe_block->register_count; i++) {
			/* Get the next status/enable pair */

			gpe_register_info = &gpe_block->register_info[i];

			/* Read the Status Register */

			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
					 &gpe_register_info->status_address);
			gpe_register_info->status = (u8) in_value;
			if (ACPI_FAILURE (status)) {
				goto unlock_and_exit;
			}

			/* Read the Enable Register */

			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
					 &gpe_register_info->enable_address);
			gpe_register_info->enable = (u8) in_value;
			if (ACPI_FAILURE (status)) {
				goto unlock_and_exit;
			}

			ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
				"GPE pair: Status %8.8X%8.8X = %02X, Enable %8.8X%8.8X = %02X\n",
				ACPI_HIDWORD (gpe_register_info->status_address.address),
				ACPI_LODWORD (gpe_register_info->status_address.address),
				gpe_register_info->status,
				ACPI_HIDWORD (gpe_register_info->enable_address.address),
				ACPI_LODWORD (gpe_register_info->enable_address.address),
				gpe_register_info->enable));

			/* First check if there is anything active at all in this register */

			enabled_status_byte = (u8) (gpe_register_info->status &
					   gpe_register_info->enable);
			if (!enabled_status_byte) {
				/* No active GPEs in this register, move on */

				continue;
			}

			/* Now look at the individual GPEs in this byte register */

			for (j = 0, bit_mask = 1; j < ACPI_GPE_REGISTER_WIDTH; j++, bit_mask <<= 1) {
				/* Examine one GPE bit */

				if (enabled_status_byte & bit_mask) {
					/*
					 * Found an active GPE. Dispatch the event to a handler
					 * or method.
					 */
					gpe_number = (i * ACPI_GPE_REGISTER_WIDTH) + j;

					int_status |= acpi_ev_gpe_dispatch (
							  &gpe_block->event_info[gpe_number],
							  gpe_number + gpe_block->register_info[gpe_number].base_gpe_number);
				}
			}
		}

		gpe_block = gpe_block->next;
	}

unlock_and_exit:

	acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
	return (int_status);
}