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; }
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); }
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); }
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); }
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; }
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); }
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); }
/******************************************************************************* * * 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); }
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); }
/******************************************************************************* * * 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); }
/******************************************************************************* * * 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); }
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; }
/******************************************************************************* * * 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); }
/******************************************************************************* * * 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); }
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); }
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); }
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); }