Esempio n. 1
0
void
acpi_ev_restore_acpi_state (void)
{
	u32                     index;


	/* Restore the state of the chipset enable bits. */

	if (acpi_gbl_restore_acpi_chipset == TRUE) {
		/* Restore the fixed events */

		if (acpi_hw_register_read (ACPI_MTX_LOCK, PM1_EN) !=
				acpi_gbl_pm1_enable_register_save)
		{
			acpi_hw_register_write (ACPI_MTX_LOCK, PM1_EN,
				acpi_gbl_pm1_enable_register_save);
		}


		/* Ensure that all status bits are clear */

		acpi_hw_clear_acpi_status ();


		/* Now restore the GPEs */

		for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) {
			if (acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index) !=
					acpi_gbl_gpe0enable_register_save[index])
			{
				acpi_hw_register_write (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index,
					acpi_gbl_gpe0enable_register_save[index]);
			}
		}

		/* GPE 1 present? */

		if (acpi_gbl_FADT->gpe1_blk_len) {
			for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) {
				if (acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index) !=
					acpi_gbl_gpe1_enable_register_save[index])
				{
					acpi_hw_register_write (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index,
						acpi_gbl_gpe1_enable_register_save[index]);
				}
			}
		}

		if (acpi_hw_get_mode() != acpi_gbl_original_mode) {
			acpi_hw_set_mode (acpi_gbl_original_mode);
		}
	}

	return;
}
Esempio n. 2
0
u32 acpi_ev_fixed_event_detect(void)
{
	u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
	u32 fixed_status;
	u32 fixed_enable;
	u32 i;
	acpi_status status;

	ACPI_FUNCTION_NAME(ev_fixed_event_detect);

	/*
	 * Read the fixed feature status and enable registers, as all the cases
	 * depend on their values. Ignore errors here.
	 */
	status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
	status |=
	    acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
	if (ACPI_FAILURE(status)) {
		return (int_status);
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
			  "Fixed Event Block: Enable %08X Status %08X\n",
			  fixed_enable, fixed_status));

	/*
	 * Check for all possible Fixed Events and dispatch those that are active
	 */
	for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {

		/* Both the status and enable bits must be on for this event */

		if ((fixed_status & acpi_gbl_fixed_event_info[i].
		     status_bit_mask)
		    && (fixed_enable & acpi_gbl_fixed_event_info[i].
			enable_bit_mask)) {
			/*
			 * Found an active (signalled) event. Invoke global event
			 * handler if present.
			 */
			acpi_fixed_event_count[i]++;
			if (acpi_gbl_global_event_handler) {
				acpi_gbl_global_event_handler
				    (ACPI_EVENT_TYPE_FIXED, NULL, i,
				     acpi_gbl_global_event_handler_context);
			}

			int_status |= acpi_ev_fixed_event_dispatch(i);
		}
	}

	return (int_status);
}
Esempio n. 3
0
u32
acpi_ev_fixed_event_detect (void)
{
	u32                     int_status = INTERRUPT_NOT_HANDLED;
	u32                     status_register;
	u32                     enable_register;


	PROC_NAME ("Ev_fixed_event_detect");


	/*
	 * Read the fixed feature status and enable registers, as all the cases
	 * depend on their values.
	 */
	status_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
	enable_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN);

	ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
		"Fixed Acpi_event Block: Enable %08X Status %08X\n",
		enable_register, status_register));


	/* power management timer roll over */

	if ((status_register & ACPI_STATUS_PMTIMER) &&
		(enable_register & ACPI_ENABLE_PMTIMER)) {
		int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_PMTIMER);
	}

	/* global event (BIOS wants the global lock) */

	if ((status_register & ACPI_STATUS_GLOBAL) &&
		(enable_register & ACPI_ENABLE_GLOBAL)) {
		int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_GLOBAL);
	}

	/* power button event */

	if ((status_register & ACPI_STATUS_POWER_BUTTON) &&
		(enable_register & ACPI_ENABLE_POWER_BUTTON)) {
		int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_POWER_BUTTON);
	}

	/* sleep button event */

	if ((status_register & ACPI_STATUS_SLEEP_BUTTON) &&
		(enable_register & ACPI_ENABLE_SLEEP_BUTTON)) {
		int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_SLEEP_BUTTON);
	}

	return (int_status);
}
Esempio n. 4
0
acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags)
{
	acpi_status status;
	struct acpi_bit_register_info *sleep_type_reg_info;
	struct acpi_bit_register_info *sleep_enable_reg_info;
	u32 pm1a_control;
	u32 pm1b_control;

	ACPI_FUNCTION_TRACE(hw_legacy_wake_prep);

	/*
	 * Set SLP_TYPE and SLP_EN to state S0.
	 * This is unclear from the ACPI Spec, but it is required
	 * by some machines.
	 */
	status = acpi_get_sleep_type_data(ACPI_STATE_S0,
					  &acpi_gbl_sleep_type_a,
					  &acpi_gbl_sleep_type_b);
	if (ACPI_SUCCESS(status)) {
		sleep_type_reg_info =
		    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
		sleep_enable_reg_info =
		    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);

		/* Get current value of PM1A control */

		status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
					       &pm1a_control);
		if (ACPI_SUCCESS(status)) {

			/* Clear the SLP_EN and SLP_TYP fields */

			pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
					  sleep_enable_reg_info->
					  access_bit_mask);
			pm1b_control = pm1a_control;

			/* Insert the SLP_TYP bits */

			pm1a_control |= (acpi_gbl_sleep_type_a <<
					 sleep_type_reg_info->bit_position);
			pm1b_control |= (acpi_gbl_sleep_type_b <<
					 sleep_type_reg_info->bit_position);

			/* Write the control registers and ignore any errors */

			(void)acpi_hw_write_pm1_control(pm1a_control,
							pm1b_control);
		}
	}

	/* Optionally execute _BFS (Back From Sleep) */

	if (flags & ACPI_EXECUTE_BFS) {
		acpi_hw_execute_sleep_method(METHOD_PATHNAME__BFS, sleep_state);
	}
	return_ACPI_STATUS(status);
}
acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags)
{
	acpi_status status;
	struct acpi_bit_register_info *sleep_type_reg_info;
	struct acpi_bit_register_info *sleep_enable_reg_info;
	u32 pm1a_control;
	u32 pm1b_control;

	ACPI_FUNCTION_TRACE(hw_legacy_wake_prep);

	status = acpi_get_sleep_type_data(ACPI_STATE_S0,
					  &acpi_gbl_sleep_type_a,
					  &acpi_gbl_sleep_type_b);
	if (ACPI_SUCCESS(status)) {
		sleep_type_reg_info =
		    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
		sleep_enable_reg_info =
		    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);

		

		status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
					       &pm1a_control);
		if (ACPI_SUCCESS(status)) {

			

			pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
					  sleep_enable_reg_info->
					  access_bit_mask);
			pm1b_control = pm1a_control;

			

			pm1a_control |= (acpi_gbl_sleep_type_a <<
					 sleep_type_reg_info->bit_position);
			pm1b_control |= (acpi_gbl_sleep_type_b <<
					 sleep_type_reg_info->bit_position);

			

			(void)acpi_hw_write_pm1_control(pm1a_control,
							pm1b_control);
		}
	}

	

	if (flags & ACPI_EXECUTE_BFS) {
		acpi_hw_execute_sleep_method(METHOD_PATHNAME__BFS, sleep_state);
	}
	return_ACPI_STATUS(status);
}
Esempio n. 6
0
static int acpi_get_wake_status(void)
{
    uint32_t val;
    acpi_status status;

    if ( acpi_sinfo.sleep_extended )
    {
        status = acpi_hw_register_read(ACPI_REGISTER_SLEEP_STATUS, &val);

        return ACPI_FAILURE(status) ? 0 : val & ACPI_X_WAKE_STATUS;
    }

    /* Wake status is the 15th bit of PM1 status register. (ACPI spec 3.0) */
    status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &val);
    if ( ACPI_FAILURE(status) )
        return 0;

    val &= ACPI_BITMASK_WAKE_STATUS;
    val >>= ACPI_BITPOSITION_WAKE_STATUS;
    return val;
}
Esempio n. 7
0
u32
acpi_ev_fixed_event_detect (
	void)
{
	u32                             int_status = ACPI_INTERRUPT_NOT_HANDLED;
	u32                             fixed_status;
	u32                             fixed_enable;
	acpi_native_uint                i;


	ACPI_FUNCTION_NAME ("ev_fixed_event_detect");


	/*
	 * Read the fixed feature status and enable registers, as all the cases
	 * depend on their values.  Ignore errors here.
	 */
	(void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, &fixed_status);
	(void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, &fixed_enable);

	ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
		"Fixed Event Block: Enable %08X Status %08X\n",
		fixed_enable, fixed_status));

	/*
	 * Check for all possible Fixed Events and dispatch those that are active
	 */
	for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
		/* Both the status and enable bits must be on for this event */

		if ((fixed_status & acpi_gbl_fixed_event_info[i].status_bit_mask) &&
			(fixed_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) {
			/* Found an active (signalled) event */

			int_status |= acpi_ev_fixed_event_dispatch ((u32) i);
		}
	}

	return (int_status);
}
Esempio n. 8
0
ACPI_STATUS
acpi_hw_enter_c2(
	ACPI_IO_ADDRESS         pblk_address,
	u32                     *pm_timer_ticks)
{
	u32                     timer = 0;


	if (!pblk_address || !pm_timer_ticks) {
		return (AE_BAD_PARAMETER);
	}

	/*
	 * Disable interrupts before all C2/C3 transitions.
	 */
	disable ();

	timer = acpi_hw_pmt_ticks ();

	/*
	 * Enter C2:
	 * ---------
	 * Read from the P_LVL2 (P_BLK+4) register to invoke a C2 transition.
	 */
	acpi_os_in8 ((ACPI_IO_ADDRESS) (pblk_address + 4));

	/*
	 * Perform Dummy Op:
	 * -----------------
	 * We have to do something useless after reading LVL2 because chipsets
	 * cannot guarantee that STPCLK# gets asserted in time to freeze execution.
	 */
	acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);

	/*
	 * Compute Time in C2:
	 * -------------------
	 */
	timer = acpi_hw_pmt_ticks () - timer;

	*pm_timer_ticks = timer;

	/*
	 * Re-enable interrupts after coming out of C2/C3.
	 */
	enable ();

	return (AE_OK);
}
Esempio n. 9
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_enter_sleep_state
 *
 * PARAMETERS:  sleep_state         - Which sleep state to enter
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
 *
 ******************************************************************************/
acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
{
	u32 pm1a_control;
	u32 pm1b_control;
	struct acpi_bit_register_info *sleep_type_reg_info;
	struct acpi_bit_register_info *sleep_enable_reg_info;
	u32 in_value;
	struct acpi_object_list arg_list;
	union acpi_object arg;
	acpi_status status;

	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);

	if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
	    (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
		ACPI_ERROR((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X",
			    acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
	}

	sleep_type_reg_info =
	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
	sleep_enable_reg_info =
	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);

	/* Clear wake status */

	status =
	    acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Clear all fixed and general purpose status bits */

	status = acpi_hw_clear_acpi_status();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * 1) Disable/Clear all GPEs
	 * 2) Enable all wakeup GPEs
	 */
	status = acpi_hw_disable_all_gpes();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}
	acpi_gbl_system_awake_and_running = FALSE;

	status = acpi_hw_enable_all_wakeup_gpes();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	if (gts) {
		/* Execute the _GTS method */

		arg_list.count = 1;
		arg_list.pointer = &arg;
		arg.type = ACPI_TYPE_INTEGER;
		arg.integer.value = sleep_state;

		status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
		if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
			return_ACPI_STATUS(status);
		}
	}

	/* Get current value of PM1A control */

	status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
				       &pm1a_control);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}
	ACPI_DEBUG_PRINT((ACPI_DB_INIT,
			  "Entering sleep state [S%u]\n", sleep_state));

	/* Clear the SLP_EN and SLP_TYP fields */

	pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
			  sleep_enable_reg_info->access_bit_mask);
	pm1b_control = pm1a_control;

	/* Insert the SLP_TYP bits */

	pm1a_control |=
	    (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
	pm1b_control |=
	    (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);


	/* Write #1: write the SLP_TYP data to the PM1 Control registers */

	status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Insert the sleep enable (SLP_EN) bit */

	pm1a_control |= sleep_enable_reg_info->access_bit_mask;
	pm1b_control |= sleep_enable_reg_info->access_bit_mask;

	/* Flush caches, as per ACPI specification */

	ACPI_FLUSH_CPU_CACHE();

	tboot_sleep(sleep_state, pm1a_control, pm1b_control);

	/* Write #2: Write both SLP_TYP + SLP_EN */

	status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	if (sleep_state > ACPI_STATE_S3) {
		/*
		 * We wanted to sleep > S3, but it didn't happen (by virtue of the
		 * fact that we are still executing!)
		 *
		 * Wait ten seconds, then try again. This is to get S4/S5 to work on
		 * all machines.
		 *
		 * We wait so long to allow chipsets that poll this reg very slowly
		 * to still read the right value. Ideally, this block would go
		 * away entirely.
		 */
		acpi_os_stall(10000000);

		status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
						sleep_enable_reg_info->
						access_bit_mask);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	}

	/* Wait until we enter sleep state */

	do {
		status = acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS,
						    &in_value);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

		/* Spin until we wake */

	} while (!in_value);

	return_ACPI_STATUS(AE_OK);
}
Esempio n. 10
0
ACPI_STATUS
acpi_hw_enter_c3(
	ACPI_IO_ADDRESS         pblk_address,
	u32                     *pm_timer_ticks)
{
	u32                     timer = 0;
	u32                     bus_master_status = 0;


	if (!pblk_address || !pm_timer_ticks) {
		return (AE_BAD_PARAMETER);
	}

	/*
	 * Check the BM_STS bit, if it is set, do not enter C3
	 *  but clear the bit (with a write) and exit, telling
	 *  the calling module that we spent zero time in C3.
	 *  If bus mastering continues, this action should
	 *  eventually cause a demotion to C2
	 */
	if (1 == (bus_master_status =
		acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, BM_STS)))
	{
		/*
		 * Clear the BM_STS bit by setting it.
		 */
		acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_STS, 1);
		*pm_timer_ticks = 0;
		return (AE_OK);
	}

	/*
	 * Disable interrupts before all C2/C3 transitions.
	 */
	disable();

	/*
	 * Disable Bus Mastering:
	 * ----------------------
	 * Set the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits.
	 */
	 acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 1);

	/*
	 * Get the timer base before entering C state
	 */
	timer = acpi_hw_pmt_ticks ();

	/*
	 * Enter C3:
	 * ---------
	 * Read from the P_LVL3 (P_BLK+5) register to invoke a C3 transition.
	 */
	acpi_os_in8 ((ACPI_IO_ADDRESS)(pblk_address + 5));

	/*
	 * Perform Dummy Op:
	 * -----------------
	 * We have to do something useless after reading LVL3 because chipsets
	 * cannot guarantee that STPCLK# gets asserted in time to freeze execution.
	 */
	acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
	/*
	 * Immediately compute the time in the C state
	 */
	timer = acpi_hw_pmt_ticks() - timer;

	/*
	 * Re-Enable Bus Mastering:
	 * ------------------------
	 * Clear the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits.
	 */
	acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 0);

	/* TBD: [Unhandled]: Support 24-bit timers (this algorithm assumes 32-bit) */

	*pm_timer_ticks = timer;

	/*
	 * Re-enable interrupts after coming out of C2/C3.
	 */
	enable();

	return (AE_OK);
}
Esempio n. 11
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_enter_sleep_state
 *
 * PARAMETERS:  sleep_state         - Which sleep state to enter
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
 *
 ******************************************************************************/
acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
{
	u32 PM1Acontrol;
	u32 PM1Bcontrol;
	struct acpi_bit_register_info *sleep_type_reg_info;
	struct acpi_bit_register_info *sleep_enable_reg_info;
#if !(defined(CONFIG_XEN) && defined(CONFIG_X86))
	u32 in_value;
#else
	int err;
#endif
	acpi_status status;

	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);

	if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
	    (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
		ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X",
			    acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
	}

	sleep_type_reg_info =
	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A);
	sleep_enable_reg_info =
	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);

	/* Clear wake status */

	status =
	    acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Clear all fixed and general purpose status bits */

	status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * 1) Disable/Clear all GPEs
	 * 2) Enable all wakeup GPEs
	 */
	status = acpi_hw_disable_all_gpes();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}
	acpi_gbl_system_awake_and_running = FALSE;

	status = acpi_hw_enable_all_wakeup_gpes();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Get current value of PM1A control */

	status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
				       ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}
	ACPI_DEBUG_PRINT((ACPI_DB_INIT,
			  "Entering sleep state [S%d]\n", sleep_state));

	/* Clear SLP_EN and SLP_TYP fields */

	PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
			 sleep_enable_reg_info->access_bit_mask);
	PM1Bcontrol = PM1Acontrol;

	/* Insert SLP_TYP bits */

	PM1Acontrol |=
	    (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
	PM1Bcontrol |=
	    (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);

	/*
	 * We split the writes of SLP_TYP and SLP_EN to workaround
	 * poorly implemented hardware.
	 */

	/* Write #1: fill in SLP_TYP data */

	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
					ACPI_REGISTER_PM1A_CONTROL,
					PM1Acontrol);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
					ACPI_REGISTER_PM1B_CONTROL,
					PM1Bcontrol);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Insert SLP_ENABLE bit */

	PM1Acontrol |= sleep_enable_reg_info->access_bit_mask;
	PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask;

	/* Write #2: SLP_TYP + SLP_EN */

	ACPI_FLUSH_CPU_CACHE();

#if !(defined(CONFIG_XEN) && defined(CONFIG_X86))
	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
					ACPI_REGISTER_PM1A_CONTROL,
					PM1Acontrol);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
					ACPI_REGISTER_PM1B_CONTROL,
					PM1Bcontrol);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	if (sleep_state > ACPI_STATE_S3) {
		/*
		 * We wanted to sleep > S3, but it didn't happen (by virtue of the
		 * fact that we are still executing!)
		 *
		 * Wait ten seconds, then try again. This is to get S4/S5 to work on
		 * all machines.
		 *
		 * We wait so long to allow chipsets that poll this reg very slowly to
		 * still read the right value. Ideally, this block would go
		 * away entirely.
		 */
		acpi_os_stall(10000000);

		status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
						ACPI_REGISTER_PM1_CONTROL,
						sleep_enable_reg_info->
						access_bit_mask);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	}

	/* Wait until we enter sleep state */

	do {
		status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value,
					   ACPI_MTX_DO_NOT_LOCK);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

		/* Spin until we wake */

	} while (!in_value);
#else
	/* PV ACPI just need check hypercall return value */
	err = acpi_notify_hypervisor_state(sleep_state,
			PM1Acontrol, PM1Bcontrol);
	if (err) {
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
				  "Hypervisor failure [%d]\n", err));
		return_ACPI_STATUS(AE_ERROR);
	}
#endif

	return_ACPI_STATUS(AE_OK);
}
Esempio n. 12
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_leave_sleep_state
 *
 * PARAMETERS:  sleep_state         - Which sleep state we just exited
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
 *              Called with interrupts ENABLED.
 *
 ******************************************************************************/
acpi_status acpi_leave_sleep_state(u8 sleep_state)
{
	struct acpi_object_list arg_list;
	union acpi_object arg;
	acpi_status status;
	struct acpi_bit_register_info *sleep_type_reg_info;
	struct acpi_bit_register_info *sleep_enable_reg_info;
	u32 PM1Acontrol;
	u32 PM1Bcontrol;

	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);

	/*
	 * Set SLP_TYPE and SLP_EN to state S0.
	 * This is unclear from the ACPI Spec, but it is required
	 * by some machines.
	 */
	status = acpi_get_sleep_type_data(ACPI_STATE_S0,
					  &acpi_gbl_sleep_type_a,
					  &acpi_gbl_sleep_type_b);
	if (ACPI_SUCCESS(status)) {
		sleep_type_reg_info =
		    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A);
		sleep_enable_reg_info =
		    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);

		/* Get current value of PM1A control */

		status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
					       ACPI_REGISTER_PM1_CONTROL,
					       &PM1Acontrol);
		if (ACPI_SUCCESS(status)) {

			/* Clear SLP_EN and SLP_TYP fields */

			PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
					 sleep_enable_reg_info->
					 access_bit_mask);
			PM1Bcontrol = PM1Acontrol;

			/* Insert SLP_TYP bits */

			PM1Acontrol |=
			    (acpi_gbl_sleep_type_a << sleep_type_reg_info->
			     bit_position);
			PM1Bcontrol |=
			    (acpi_gbl_sleep_type_b << sleep_type_reg_info->
			     bit_position);

			/* Just ignore any errors */

			(void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
						     ACPI_REGISTER_PM1A_CONTROL,
						     PM1Acontrol);
			(void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
						     ACPI_REGISTER_PM1B_CONTROL,
						     PM1Bcontrol);
		}
	}

	/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */

	acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;

	/* Setup parameter object */

	arg_list.count = 1;
	arg_list.pointer = &arg;
	arg.type = ACPI_TYPE_INTEGER;

	/* Ignore any errors from these methods */

	arg.integer.value = ACPI_SST_WAKING;
	status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
		ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
	}

	arg.integer.value = sleep_state;
	status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
		ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
	}

	status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
		ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK"));
	}
	/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */

	/*
	 * Restore the GPEs:
	 * 1) Disable/Clear all GPEs
	 * 2) Enable all runtime GPEs
	 */
	status = acpi_hw_disable_all_gpes();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}
	acpi_gbl_system_awake_and_running = TRUE;

	status = acpi_hw_enable_all_runtime_gpes();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Enable power button */

	(void)
	    acpi_set_register(acpi_gbl_fixed_event_info
			      [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1,
			      ACPI_MTX_DO_NOT_LOCK);

	(void)
	    acpi_set_register(acpi_gbl_fixed_event_info
			      [ACPI_EVENT_POWER_BUTTON].status_register_id, 1,
			      ACPI_MTX_DO_NOT_LOCK);

	arg.integer.value = ACPI_SST_WORKING;
	status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
		ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
	}

	return_ACPI_STATUS(status);
}
Esempio n. 13
0
static int 
sm_osl_proc_read_gpe(
	char                    *page,
	char                    **start,
	off_t                   off,
	int                     count,
	int                     *eof,
	void                    *context)
{
	char *str = page;
	int size;
	int length;
	int i;
	u32 addr,data;
	
	if (off) goto out;

	if (acpi_gbl_FADT->V1_gpe0blk) {
		length = acpi_gbl_FADT->gpe0blk_len / 2;

		str += sprintf(str,"GPE0: ");

		for (i = length; i > 0; i--) {
			addr = GPE0_EN_BLOCK | (i - 1);
			data = acpi_hw_register_read(ACPI_MTX_LOCK,addr);
			str += sprintf(str,"%2.2x ",data);
		}
		str += sprintf(str,"\n");

		str += sprintf(str,"Status: ");
		for (i = length; i > 0; i--) {
			addr = GPE0_STS_BLOCK | (i - 1);
			data = acpi_hw_register_read(ACPI_MTX_LOCK,addr);
			str += sprintf(str,"%2.2x ",data);
		}
		str += sprintf(str,"\n");
	}

	if (acpi_gbl_FADT->V1_gpe1_blk) {
		length = acpi_gbl_FADT->gpe1_blk_len / 2;


		str += sprintf(str,"GPE1: ");
		for (i = length; i > 0; i--) {
			addr = GPE1_EN_BLOCK | (i - 1);
			data = acpi_hw_register_read(ACPI_MTX_LOCK,addr);
			str += sprintf(str,"%2.2x",data);
		}
		str += sprintf(str,"\n");

		str += sprintf(str,"Status: ");
		for (i = length; i > 0; i--) {
			addr = GPE1_STS_BLOCK | (i - 1);
			data = acpi_hw_register_read(ACPI_MTX_LOCK,addr);
			str += sprintf(str,"%2.2x",data);
		}
		str += sprintf(str,"\n");
	}
 out:
	size = str - page;
	if (size < count) *eof = 1;
	else if (size > count) size = count;

	if (size < 0) size = 0;
	*start = page;

	return size;
}
Esempio n. 14
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_hw_legacy_sleep
 *
 * PARAMETERS:  sleep_state         - Which sleep state to enter
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers
 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
 *
 ******************************************************************************/
acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
{
	struct acpi_bit_register_info *sleep_type_reg_info;
	struct acpi_bit_register_info *sleep_enable_reg_info;
	u32 pm1a_control;
	u32 pm1b_control;
	u32 in_value;
	acpi_status status;

	ACPI_FUNCTION_TRACE(hw_legacy_sleep);

	sleep_type_reg_info =
	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
	sleep_enable_reg_info =
	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);

	/* Clear wake status */

	status =
	    acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Clear all fixed and general purpose status bits */

	status = acpi_hw_clear_acpi_status();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * 1) Disable/Clear all GPEs
	 * 2) Enable all wakeup GPEs
	 */
	status = acpi_hw_disable_all_gpes();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}
	acpi_gbl_system_awake_and_running = FALSE;

	status = acpi_hw_enable_all_wakeup_gpes();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Get current value of PM1A control */

	status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
				       &pm1a_control);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}
	ACPI_DEBUG_PRINT((ACPI_DB_INIT,
			  "Entering sleep state [S%u]\n", sleep_state));

	/* Clear the SLP_EN and SLP_TYP fields */

	pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
			  sleep_enable_reg_info->access_bit_mask);
	pm1b_control = pm1a_control;

	/* Insert the SLP_TYP bits */

	pm1a_control |=
	    (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
	pm1b_control |=
	    (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);

	/*
	 * We split the writes of SLP_TYP and SLP_EN to workaround
	 * poorly implemented hardware.
	 */

	/* Write #1: write the SLP_TYP data to the PM1 Control registers */

	status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Insert the sleep enable (SLP_EN) bit */

	pm1a_control |= sleep_enable_reg_info->access_bit_mask;
	pm1b_control |= sleep_enable_reg_info->access_bit_mask;

	/* Flush caches, as per ACPI specification */

	ACPI_FLUSH_CPU_CACHE();

	status = acpi_os_prepare_sleep(sleep_state, pm1a_control,
				       pm1b_control);
	if (ACPI_SKIP(status))
		return_ACPI_STATUS(AE_OK);
	if (ACPI_FAILURE(status))
		return_ACPI_STATUS(status);
	/* Write #2: Write both SLP_TYP + SLP_EN */

	status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	if (sleep_state > ACPI_STATE_S3) {
		/*
		 * We wanted to sleep > S3, but it didn't happen (by virtue of the
		 * fact that we are still executing!)
		 *
		 * Wait ten seconds, then try again. This is to get S4/S5 to work on
		 * all machines.
		 *
		 * We wait so long to allow chipsets that poll this reg very slowly
		 * to still read the right value. Ideally, this block would go
		 * away entirely.
		 */
		acpi_os_stall(10000000);

		status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
						sleep_enable_reg_info->
						access_bit_mask);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	}

	/* Wait for transition back to Working State */

	do {
		status =
		    acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

	} while (!in_value);

	return_ACPI_STATUS(AE_OK);
}
Esempio n. 15
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_leave_sleep_state_prep
 *
 * PARAMETERS:  sleep_state         - Which sleep state we are exiting
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
 *              sleep.
 *              Called with interrupts DISABLED.
 *
 ******************************************************************************/
acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
{
	struct acpi_object_list arg_list;
	union acpi_object arg;
	acpi_status status;
	struct acpi_bit_register_info *sleep_type_reg_info;
	struct acpi_bit_register_info *sleep_enable_reg_info;
	u32 pm1a_control;
	u32 pm1b_control;

	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);

	/*
	 * Set SLP_TYPE and SLP_EN to state S0.
	 * This is unclear from the ACPI Spec, but it is required
	 * by some machines.
	 */
	status = acpi_get_sleep_type_data(ACPI_STATE_S0,
					  &acpi_gbl_sleep_type_a,
					  &acpi_gbl_sleep_type_b);
	if (ACPI_SUCCESS(status)) {
		sleep_type_reg_info =
		    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
		sleep_enable_reg_info =
		    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);

		/* Get current value of PM1A control */

		status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
					       &pm1a_control);
		if (ACPI_SUCCESS(status)) {

			/* Clear the SLP_EN and SLP_TYP fields */

			pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
					  sleep_enable_reg_info->
					  access_bit_mask);
			pm1b_control = pm1a_control;

			/* Insert the SLP_TYP bits */

			pm1a_control |= (acpi_gbl_sleep_type_a <<
					 sleep_type_reg_info->bit_position);
			pm1b_control |= (acpi_gbl_sleep_type_b <<
					 sleep_type_reg_info->bit_position);

			/* Write the control registers and ignore any errors */

			(void)acpi_hw_write_pm1_control(pm1a_control,
							pm1b_control);
		}
	}

	if (bfs) {
		/* Execute the _BFS method */

		arg_list.count = 1;
		arg_list.pointer = &arg;
		arg.type = ACPI_TYPE_INTEGER;
		arg.integer.value = sleep_state;

		status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
		if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
			ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
		}
	}
	return_ACPI_STATUS(status);
}
Esempio n. 16
0
acpi_status asmlinkage
acpi_enter_sleep_state (
    u8                              sleep_state)
{
    u32                             PM1Acontrol;
    u32                             PM1Bcontrol;
    struct acpi_bit_register_info   *sleep_type_reg_info;
    struct acpi_bit_register_info   *sleep_enable_reg_info;
    u32                             in_value;
    acpi_status                     status;


    ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state");


    if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
            (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
        ACPI_REPORT_ERROR (("Sleep values out of range: A=%X B=%X\n",
                            acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
        return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
    }

    sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
    sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);

    if (sleep_state != ACPI_STATE_S5) {
        /* Clear wake status */

        status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
        if (ACPI_FAILURE (status)) {
            return_ACPI_STATUS (status);
        }

        status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
        if (ACPI_FAILURE (status)) {
            return_ACPI_STATUS (status);
        }

        /* Disable BM arbitration */

        status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
        if (ACPI_FAILURE (status)) {
            return_ACPI_STATUS (status);
        }
    }

    /*
     * 1) Disable all runtime GPEs
     * 2) Enable all wakeup GPEs
     */
    status = acpi_hw_prepare_gpes_for_sleep ();
    if (ACPI_FAILURE (status)) {
        return_ACPI_STATUS (status);
    }

    /* Get current value of PM1A control */

    status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
    if (ACPI_FAILURE (status)) {
        return_ACPI_STATUS (status);
    }
    ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Entering sleep state [S%d]\n", sleep_state));

    /* Clear SLP_EN and SLP_TYP fields */

    PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | sleep_enable_reg_info->access_bit_mask);
    PM1Bcontrol = PM1Acontrol;

    /* Insert SLP_TYP bits */

    PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
    PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);

    /*
     * We split the writes of SLP_TYP and SLP_EN to workaround
     * poorly implemented hardware.
     */

    /* Write #1: fill in SLP_TYP data */

    status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
    if (ACPI_FAILURE (status)) {
        return_ACPI_STATUS (status);
    }

    status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
    if (ACPI_FAILURE (status)) {
        return_ACPI_STATUS (status);
    }

    /* Insert SLP_ENABLE bit */

    PM1Acontrol |= sleep_enable_reg_info->access_bit_mask;
    PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask;

    /* Write #2: SLP_TYP + SLP_EN */

    ACPI_FLUSH_CPU_CACHE ();

    status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
    if (ACPI_FAILURE (status)) {
        return_ACPI_STATUS (status);
    }

    status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
    if (ACPI_FAILURE (status)) {
        return_ACPI_STATUS (status);
    }

    if (sleep_state > ACPI_STATE_S3) {
        /*
         * We wanted to sleep > S3, but it didn't happen (by virtue of the fact that
         * we are still executing!)
         *
         * Wait ten seconds, then try again. This is to get S4/S5 to work on all machines.
         *
         * We wait so long to allow chipsets that poll this reg very slowly to
         * still read the right value. Ideally, this block would go
         * away entirely.
         */
        acpi_os_stall (10000000);

        status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL,
                                         sleep_enable_reg_info->access_bit_mask);
        if (ACPI_FAILURE (status)) {
            return_ACPI_STATUS (status);
        }
    }

    /* Wait until we enter sleep state */

    do {
        status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value, ACPI_MTX_DO_NOT_LOCK);
        if (ACPI_FAILURE (status)) {
            return_ACPI_STATUS (status);
        }

        /* Spin until we wake */

    } while (!in_value);

    return_ACPI_STATUS (AE_OK);
}
acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags)
{
	struct acpi_bit_register_info *sleep_type_reg_info;
	struct acpi_bit_register_info *sleep_enable_reg_info;
	u32 pm1a_control;
	u32 pm1b_control;
	u32 in_value;
	acpi_status status;

	ACPI_FUNCTION_TRACE(hw_legacy_sleep);

	sleep_type_reg_info =
	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
	sleep_enable_reg_info =
	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);

	

	status =
	    acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	

	status = acpi_hw_clear_acpi_status();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	if (sleep_state != ACPI_STATE_S5) {
		status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
		if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) {
			return_ACPI_STATUS(status);
		}
	}

	status = acpi_hw_disable_all_gpes();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}
	acpi_gbl_system_awake_and_running = FALSE;

	status = acpi_hw_enable_all_wakeup_gpes();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	

	if (flags & ACPI_EXECUTE_GTS) {
		acpi_hw_execute_sleep_method(METHOD_PATHNAME__GTS, sleep_state);
	}

	

	status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
				       &pm1a_control);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}
	ACPI_DEBUG_PRINT((ACPI_DB_INIT,
			  "Entering sleep state [S%u]\n", sleep_state));

	

	pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
			  sleep_enable_reg_info->access_bit_mask);
	pm1b_control = pm1a_control;

	

	pm1a_control |=
	    (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
	pm1b_control |=
	    (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);


	

	status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	

	pm1a_control |= sleep_enable_reg_info->access_bit_mask;
	pm1b_control |= sleep_enable_reg_info->access_bit_mask;

	

	ACPI_FLUSH_CPU_CACHE();

	status = acpi_os_prepare_sleep(sleep_state, pm1a_control,
				       pm1b_control);
	if (ACPI_SKIP(status))
		return_ACPI_STATUS(AE_OK);
	if (ACPI_FAILURE(status))
		return_ACPI_STATUS(status);
	

	status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	if (sleep_state > ACPI_STATE_S3) {
		acpi_os_stall(10000000);

		status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
						sleep_enable_reg_info->
						access_bit_mask);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	}

	

	do {
		status =
		    acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

	} while (!in_value);

	return_ACPI_STATUS(AE_OK);
}
Esempio n. 18
0
acpi_status
acpi_enter_sleep_state (
	u8                  sleep_state)
{
	acpi_status         status;
	acpi_object_list    arg_list;
	acpi_object         arg;
	u8                  type_a;
	u8                  type_b;
	u16                 PM1Acontrol;
	u16                 PM1Bcontrol;


	FUNCTION_TRACE ("Acpi_enter_sleep_state");


	/*
	 * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
	 */
	status = acpi_hw_obtain_sleep_type_register_data (sleep_state, &type_a, &type_b);
	if (!ACPI_SUCCESS (status)) {
		return status;
	}

	/* run the _PTS and _GTS methods */

	MEMSET(&arg_list, 0, sizeof(arg_list));
	arg_list.count = 1;
	arg_list.pointer = &arg;

	MEMSET(&arg, 0, sizeof(arg));
	arg.type = ACPI_TYPE_INTEGER;
	arg.integer.value = sleep_state;

	acpi_evaluate_object (NULL, "\\_PTS", &arg_list, NULL);
	acpi_evaluate_object (NULL, "\\_GTS", &arg_list, NULL);

	/* clear wake status */

	acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1);

	disable ();

	acpi_hw_disable_non_wakeup_gpes();

	PM1Acontrol = (u16) acpi_hw_register_read (ACPI_MTX_LOCK, PM1_CONTROL);

	ACPI_DEBUG_PRINT ((ACPI_DB_OK, "Entering S%d\n", sleep_state));

	/* mask off SLP_EN and SLP_TYP fields */

	PM1Acontrol &= ~(SLP_TYPE_X_MASK | SLP_EN_MASK);
	PM1Bcontrol = PM1Acontrol;

	/* mask in SLP_TYP */

	PM1Acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
	PM1Bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));

	/* write #1: fill in SLP_TYP data */

	acpi_hw_register_write (ACPI_MTX_LOCK, PM1A_CONTROL, PM1Acontrol);
	acpi_hw_register_write (ACPI_MTX_LOCK, PM1B_CONTROL, PM1Bcontrol);

	/* mask in SLP_EN */

	PM1Acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK));
	PM1Bcontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK));

	/* flush caches */

	wbinvd();

	/* write #2: SLP_TYP + SLP_EN */

	acpi_hw_register_write (ACPI_MTX_LOCK, PM1A_CONTROL, PM1Acontrol);
	acpi_hw_register_write (ACPI_MTX_LOCK, PM1B_CONTROL, PM1Bcontrol);

	/*
	 * Wait a second, then try again. This is to get S4/5 to work on all machines.
	 */
	if (sleep_state > ACPI_STATE_S3) {
		acpi_os_stall(1000000);

		acpi_hw_register_write (ACPI_MTX_LOCK, PM1_CONTROL,
			(1 << acpi_hw_get_bit_shift (SLP_EN_MASK)));
	}

	/* wait until we enter sleep state */

	do {
		acpi_os_stall(10000);
	}
	while (!acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, WAK_STS));

	acpi_hw_enable_non_wakeup_gpes();

	enable ();

	return_ACPI_STATUS (AE_OK);
}
Esempio n. 19
0
acpi_status
acpi_hw_initialize (
	void)
{
	acpi_status             status = AE_OK;
	u32                     index;


	FUNCTION_TRACE ("Hw_initialize");


	/* We must have the ACPI tables by the time we get here */

	if (!acpi_gbl_FADT) {
		acpi_gbl_restore_acpi_chipset = FALSE;

		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No FADT!\n"));

		return_ACPI_STATUS (AE_NO_ACPI_TABLES);
	}

	/* Identify current ACPI/legacy mode   */

	switch (acpi_gbl_system_flags & SYS_MODES_MASK) {
	case (SYS_MODE_ACPI):

		acpi_gbl_original_mode = SYS_MODE_ACPI;
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System supports ACPI mode only.\n"));
		break;


	case (SYS_MODE_LEGACY):

		acpi_gbl_original_mode = SYS_MODE_LEGACY;
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
			"Tables loaded from buffer, hardware assumed to support LEGACY mode only.\n"));
		break;


	case (SYS_MODE_ACPI | SYS_MODE_LEGACY):

		if (acpi_hw_get_mode () == SYS_MODE_ACPI) {
			acpi_gbl_original_mode = SYS_MODE_ACPI;
		}
		else {
			acpi_gbl_original_mode = SYS_MODE_LEGACY;
		}

		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
			"System supports both ACPI and LEGACY modes.\n"));

		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
			"System is currently in %s mode.\n",
			(acpi_gbl_original_mode == SYS_MODE_ACPI) ? "ACPI" : "LEGACY"));
		break;
	}


	if (acpi_gbl_system_flags & SYS_MODE_ACPI) {
		/* Target system supports ACPI mode */

		/*
		 * The purpose of this code is to save the initial state
		 * of the ACPI event enable registers. An exit function will be
		 * registered which will restore this state when the application
		 * exits. The exit function will also clear all of the ACPI event
		 * status bits prior to restoring the original mode.
		 *
		 * The location of the PM1a_evt_blk enable registers is defined as the
		 * base of PM1a_evt_blk + DIV_2(PM1a_evt_blk_length). Since the spec further
		 * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset
		 * for the enable registers is always 2 from the base. It is hard
		 * coded here. If this changes in the spec, this code will need to
		 * be modified. The PM1b_evt_blk behaves as expected.
		 */
		acpi_gbl_pm1_enable_register_save = (u16) acpi_hw_register_read (
				   ACPI_MTX_LOCK, PM1_EN);


		/*
		 * The GPEs behave similarly, except that the length of the register
		 * block is not fixed, so the buffer must be allocated with malloc
		 */
		if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) &&
			acpi_gbl_FADT->gpe0blk_len) {
			/* GPE0 specified in FADT  */

			acpi_gbl_gpe0enable_register_save = ACPI_MEM_ALLOCATE (
					   DIV_2 (acpi_gbl_FADT->gpe0blk_len));
			if (!acpi_gbl_gpe0enable_register_save) {
				return_ACPI_STATUS (AE_NO_MEMORY);
			}

			/* Save state of GPE0 enable bits */

			for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) {
				acpi_gbl_gpe0enable_register_save[index] =
					(u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index);
			}
		}

		else {
			acpi_gbl_gpe0enable_register_save = NULL;
		}

		if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) &&
			acpi_gbl_FADT->gpe1_blk_len) {
			/* GPE1 defined */

			acpi_gbl_gpe1_enable_register_save = ACPI_MEM_ALLOCATE (
					   DIV_2 (acpi_gbl_FADT->gpe1_blk_len));
			if (!acpi_gbl_gpe1_enable_register_save) {
				return_ACPI_STATUS (AE_NO_MEMORY);
			}

			/* save state of GPE1 enable bits */

			for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) {
				acpi_gbl_gpe1_enable_register_save[index] =
					(u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index);
			}
		}

		else {
			acpi_gbl_gpe1_enable_register_save = NULL;
		}
	}

	return_ACPI_STATUS (status);
}