acpi_status asmlinkage acpi_enter_sleep_state_s4bios ( void) { u32 in_value; acpi_status status; ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state_s4bios"); 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); } /* * 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); } ACPI_FLUSH_CPU_CACHE (); status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, (u32) acpi_gbl_FADT->S4bios_req, 8); do { acpi_os_stall(1000); status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value, ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } while (!in_value); return_ACPI_STATUS (AE_OK); }
acpi_status acpi_ev_release_global_lock ( void) { u8 pending = FALSE; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE ("ev_release_global_lock"); if (!acpi_gbl_global_lock_thread_count) { ACPI_REPORT_WARNING(( "Cannot release HW Global Lock, it has not been acquired\n")); return_ACPI_STATUS (AE_NOT_ACQUIRED); } /* One fewer thread has the global lock */ acpi_gbl_global_lock_thread_count--; if (acpi_gbl_global_lock_thread_count) { /* There are still some threads holding the lock, cannot release */ return_ACPI_STATUS (AE_OK); } /* * No more threads holding lock, we can do the actual hardware * release */ ACPI_RELEASE_GLOBAL_LOCK (acpi_gbl_common_fACS.global_lock, pending); acpi_gbl_global_lock_acquired = FALSE; /* * If the pending bit was set, we must write GBL_RLS to the control * register */ if (pending) { status = acpi_set_register (ACPI_BITREG_GLOBAL_LOCK_RELEASE, 1, ACPI_MTX_LOCK); } return_ACPI_STATUS (status); }
/** * acpi_idle_bm_check - checks if bus master activity was detected */ static int acpi_idle_bm_check(void) { u32 bm_status = 0; acpi_get_register_unlocked(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); if (bm_status) acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); /* * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect * the true state of bus mastering activity; forcing us to * manually check the BMIDEA bit of each IDE channel. */ else if (errata.piix4.bmisx) { if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01) || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01)) bm_status = 1; } return bm_status; }
/******************************************************************************* * * FUNCTION: acpi_enable_event * * PARAMETERS: Event - The fixed eventto be enabled * Flags - Reserved * * RETURN: Status * * DESCRIPTION: Enable an ACPI event (fixed) * ******************************************************************************/ acpi_status acpi_enable_event(u32 event, u32 flags) { acpi_status status = AE_OK; u32 value; ACPI_FUNCTION_TRACE(acpi_enable_event); /* Decode the Fixed Event */ if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * Enable the requested fixed event (by writing a one to the * enable register bit) */ status = acpi_set_register(acpi_gbl_fixed_event_info[event]. enable_register_id, 1); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Make sure that the hardware responded */ status = acpi_get_register(acpi_gbl_fixed_event_info[event]. enable_register_id, &value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (value != 1) { ACPI_ERROR((AE_INFO, "Could not enable %s event", acpi_ut_get_event_name(event))); return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); } return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_disable_event * * PARAMETERS: Event - The fixed eventto be enabled * Flags - Reserved * * RETURN: Status * * DESCRIPTION: Disable an ACPI event (fixed) * ******************************************************************************/ acpi_status acpi_disable_event(u32 event, u32 flags) { acpi_status status = AE_OK; u32 value; ACPI_FUNCTION_TRACE(acpi_disable_event); /* Decode the Fixed Event */ if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * Disable the requested fixed event (by writing a zero to the * enable register bit) */ status = acpi_set_register(acpi_gbl_fixed_event_info[event]. enable_register_id, 0, ACPI_MTX_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } status = acpi_get_register(acpi_gbl_fixed_event_info[event]. enable_register_id, &value, ACPI_MTX_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (value != 0) { ACPI_ERROR((AE_INFO, "Could not disable %s events", acpi_ut_get_event_name(event))); return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); } return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_clear_event * * PARAMETERS: Event - The fixed event to be cleared * * RETURN: Status * * DESCRIPTION: Clear an ACPI event (fixed) * ******************************************************************************/ acpi_status acpi_clear_event(u32 event) { acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(acpi_clear_event); /* Decode the Fixed Event */ if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * Clear the requested fixed event (By writing a one to the * status register bit) */ status = acpi_set_register(acpi_gbl_fixed_event_info[event]. status_register_id, 1); return_ACPI_STATUS(status); }
static void acpi_processor_idle(void) { struct acpi_processor_power *power = processor_powers[smp_processor_id()]; struct acpi_processor_cx *cx = NULL; int next_state; uint64_t t1, t2 = 0; u32 exp = 0, pred = 0; u32 irq_traced[4] = { 0 }; if ( max_cstate > 0 && power && !sched_has_urgent_vcpu() && (next_state = cpuidle_current_governor->select(power)) > 0 ) { cx = &power->states[next_state]; if ( power->flags.bm_check && acpi_idle_bm_check() && cx->type == ACPI_STATE_C3 ) cx = power->safe_state; if ( cx->idx > max_cstate ) cx = &power->states[max_cstate]; menu_get_trace_data(&exp, &pred); } if ( !cx ) { if ( pm_idle_save ) pm_idle_save(); else safe_halt(); return; } cpufreq_dbs_timer_suspend(); sched_tick_suspend(); /* sched_tick_suspend() can raise TIMER_SOFTIRQ. Process it now. */ process_pending_softirqs(); /* * Interrupts must be disabled during bus mastering calculations and * for C2/C3 transitions. */ local_irq_disable(); if ( !cpu_is_haltable(smp_processor_id()) ) { local_irq_enable(); sched_tick_resume(); cpufreq_dbs_timer_resume(); return; } if ( (cx->type == ACPI_STATE_C3) && errata_c6_eoi_workaround() ) cx = power->safe_state; power->last_state = cx; /* * Sleep: * ------ * Invoke the current Cx state to put the processor to sleep. */ switch ( cx->type ) { case ACPI_STATE_C1: case ACPI_STATE_C2: if ( cx->type == ACPI_STATE_C1 || local_apic_timer_c2_ok ) { /* Get start time (ticks) */ t1 = get_tick(); /* Trace cpu idle entry */ TRACE_4D(TRC_PM_IDLE_ENTRY, cx->idx, t1, exp, pred); /* Invoke C2 */ acpi_idle_do_entry(cx); /* Get end time (ticks) */ t2 = get_tick(); trace_exit_reason(irq_traced); /* Trace cpu idle exit */ TRACE_6D(TRC_PM_IDLE_EXIT, cx->idx, t2, irq_traced[0], irq_traced[1], irq_traced[2], irq_traced[3]); /* Update statistics */ acpi_update_idle_stats(power, cx, ticks_elapsed(t1, t2)); /* Re-enable interrupts */ local_irq_enable(); break; } case ACPI_STATE_C3: /* * Before invoking C3, be aware that TSC/APIC timer may be * stopped by H/W. Without carefully handling of TSC/APIC stop issues, * deep C state can't work correctly. */ /* preparing APIC stop */ lapic_timer_off(); /* Get start time (ticks) */ t1 = get_tick(); /* Trace cpu idle entry */ TRACE_4D(TRC_PM_IDLE_ENTRY, cx->idx, t1, exp, pred); /* * disable bus master * bm_check implies we need ARB_DIS * !bm_check implies we need cache flush * bm_control implies whether we can do ARB_DIS * * That leaves a case where bm_check is set and bm_control is * not set. In that case we cannot do much, we enter C3 * without doing anything. */ if ( cx->type != ACPI_STATE_C3 ) /* nothing to be done here */; else if ( power->flags.bm_check && power->flags.bm_control ) { spin_lock(&c3_cpu_status.lock); if ( ++c3_cpu_status.count == num_online_cpus() ) { /* * All CPUs are trying to go to C3 * Disable bus master arbitration */ acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); } spin_unlock(&c3_cpu_status.lock); } else if ( !power->flags.bm_check ) { /* SMP with no shared cache... Invalidate cache */ ACPI_FLUSH_CPU_CACHE(); } /* Invoke C3 */ acpi_idle_do_entry(cx); if ( (cx->type == ACPI_STATE_C3) && power->flags.bm_check && power->flags.bm_control ) { /* Enable bus master arbitration */ spin_lock(&c3_cpu_status.lock); acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); c3_cpu_status.count--; spin_unlock(&c3_cpu_status.lock); } /* Get end time (ticks) */ t2 = get_tick(); /* recovering TSC */ cstate_restore_tsc(); trace_exit_reason(irq_traced); /* Trace cpu idle exit */ TRACE_6D(TRC_PM_IDLE_EXIT, cx->idx, t2, irq_traced[0], irq_traced[1], irq_traced[2], irq_traced[3]); /* Update statistics */ acpi_update_idle_stats(power, cx, ticks_elapsed(t1, t2)); /* Re-enable interrupts */ local_irq_enable(); /* recovering APIC */ lapic_timer_on(); break; default: /* Now in C0 */ power->last_state = &power->states[0]; local_irq_enable(); sched_tick_resume(); cpufreq_dbs_timer_resume(); return; } /* Now in C0 */ power->last_state = &power->states[0]; sched_tick_resume(); cpufreq_dbs_timer_resume(); if ( cpuidle_current_governor->reflect ) cpuidle_current_governor->reflect(power); }
/******************************************************************************* * * 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); }
/******************************************************************************* * * 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); }
static int acpi_system_write_alarm ( struct file *file, const char *buffer, unsigned long count, void *data) { int result = 0; char alarm_string[30] = {'\0'}; char *p = alarm_string; u32 sec, min, hr, day, mo, yr; int adjust = 0; unsigned char rtc_control = 0; ACPI_FUNCTION_TRACE("acpi_system_write_alarm"); if (count > sizeof(alarm_string) - 1) return_VALUE(-EINVAL); if (copy_from_user(alarm_string, buffer, count)) return_VALUE(-EFAULT); alarm_string[count] = '\0'; /* check for time adjustment */ if (alarm_string[0] == '+') { p++; adjust = 1; } if ((result = get_date_field(&p, &yr))) goto end; if ((result = get_date_field(&p, &mo))) goto end; if ((result = get_date_field(&p, &day))) goto end; if ((result = get_date_field(&p, &hr))) goto end; if ((result = get_date_field(&p, &min))) goto end; if ((result = get_date_field(&p, &sec))) goto end; if (sec > 59) { min += 1; sec -= 60; } if (min > 59) { hr += 1; min -= 60; } if (hr > 23) { day += 1; hr -= 24; } if (day > 31) { mo += 1; day -= 31; } if (mo > 12) { yr += 1; mo -= 12; } spin_lock_irq(&rtc_lock); rtc_control = CMOS_READ(RTC_CONTROL); if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BIN_TO_BCD(yr); BIN_TO_BCD(mo); BIN_TO_BCD(day); BIN_TO_BCD(hr); BIN_TO_BCD(min); BIN_TO_BCD(sec); } if (adjust) { yr += CMOS_READ(RTC_YEAR); mo += CMOS_READ(RTC_MONTH); day += CMOS_READ(RTC_DAY_OF_MONTH); hr += CMOS_READ(RTC_HOURS); min += CMOS_READ(RTC_MINUTES); sec += CMOS_READ(RTC_SECONDS); } spin_unlock_irq(&rtc_lock); if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BCD_TO_BIN(yr); BCD_TO_BIN(mo); BCD_TO_BIN(day); BCD_TO_BIN(hr); BCD_TO_BIN(min); BCD_TO_BIN(sec); } if (sec > 59) { min++; sec -= 60; } if (min > 59) { hr++; min -= 60; } if (hr > 23) { day++; hr -= 24; } if (day > 31) { mo++; day -= 31; } if (mo > 12) { yr++; mo -= 12; } if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BIN_TO_BCD(yr); BIN_TO_BCD(mo); BIN_TO_BCD(day); BIN_TO_BCD(hr); BIN_TO_BCD(min); BIN_TO_BCD(sec); } spin_lock_irq(&rtc_lock); /* write the fields the rtc knows about */ CMOS_WRITE(hr, RTC_HOURS_ALARM); CMOS_WRITE(min, RTC_MINUTES_ALARM); CMOS_WRITE(sec, RTC_SECONDS_ALARM); /* * If the system supports an enhanced alarm it will have non-zero * offsets into the CMOS RAM here -- which for some reason are pointing * to the RTC area of memory. */ #if 0 if (acpi_gbl_FADT->day_alrm) CMOS_WRITE(day, acpi_gbl_FADT->day_alrm); if (acpi_gbl_FADT->mon_alrm) CMOS_WRITE(mo, acpi_gbl_FADT->mon_alrm); if (acpi_gbl_FADT->century) CMOS_WRITE(yr/100, acpi_gbl_FADT->century); #endif /* enable the rtc alarm interrupt */ if (!(rtc_control & RTC_AIE)) { rtc_control |= RTC_AIE; CMOS_WRITE(rtc_control,RTC_CONTROL); CMOS_READ(RTC_INTR_FLAGS); } spin_unlock_irq(&rtc_lock); acpi_set_register(ACPI_BITREG_RT_CLOCK_ENABLE, 1, ACPI_MTX_LOCK); file->f_pos += count; result = 0; end: return_VALUE(result ? result : count); }
/** * acpi_idle_enter_bm - enters C3 with proper BM handling * @dev: the target CPU * @state: the state data * * If BM is detected, the deepest non-C3 idle state is entered instead. */ static int acpi_idle_enter_bm(struct cpuidle_device *dev, struct cpuidle_state *state) { struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); u32 t1, t2; int sleep_ticks = 0; pr = __get_cpu_var(processors); if (unlikely(!pr)) return 0; if (acpi_idle_suspend) return(acpi_idle_enter_c1(dev, state)); if (acpi_idle_bm_check()) { if (dev->safe_state) { dev->last_state = dev->safe_state; return dev->safe_state->enter(dev, dev->safe_state); } else { local_irq_disable(); acpi_safe_halt(); local_irq_enable(); return 0; } } local_irq_disable(); current_thread_info()->status &= ~TS_POLLING; /* * TS_POLLING-cleared state must be visible before we test * NEED_RESCHED: */ smp_mb(); if (unlikely(need_resched())) { current_thread_info()->status |= TS_POLLING; local_irq_enable(); return 0; } acpi_unlazy_tlb(smp_processor_id()); /* Tell the scheduler that we are going deep-idle: */ sched_clock_idle_sleep_event(); /* * Must be done before busmaster disable as we might need to * access HPET ! */ acpi_state_timer_broadcast(pr, cx, 1); /* * disable bus master * bm_check implies we need ARB_DIS * !bm_check implies we need cache flush * bm_control implies whether we can do ARB_DIS * * That leaves a case where bm_check is set and bm_control is * not set. In that case we cannot do much, we enter C3 * without doing anything. */ if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); c3_cpu_count++; /* Disable bus master arbitration when all CPUs are in C3 */ if (c3_cpu_count == num_online_cpus()) acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); spin_unlock(&c3_lock); } else if (!pr->flags.bm_check) { ACPI_FLUSH_CPU_CACHE(); } t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); /* Re-enable bus master arbitration */ if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); c3_cpu_count--; spin_unlock(&c3_lock); } #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) /* TSC could halt in idle, so notify users */ if (tsc_halts_in_c(ACPI_STATE_C3)) mark_tsc_unstable("TSC halts in idle"); #endif sleep_ticks = ticks_elapsed(t1, t2); /* Tell the scheduler how much we idled: */ sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); local_irq_enable(); current_thread_info()->status |= TS_POLLING; cx->usage++; acpi_state_timer_broadcast(pr, cx, 0); cx->time += sleep_ticks; return ticks_elapsed_in_us(t1, t2); }
static void acpi_processor_power_verify_c3(struct acpi_processor *pr, struct acpi_processor_cx *cx) { static int bm_check_flag; if (!cx->address) return; /* * C3 latency must be less than or equal to 1000 * microseconds. */ else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "latency too large [%d]\n", cx->latency)); return; } /* * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) * DMA transfers are used by any ISA device to avoid livelock. * Note that we could disable Type-F DMA (as recommended by * the erratum), but this is known to disrupt certain ISA * devices thus we take the conservative approach. */ else if (errata.piix4.fdma) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "C3 not supported on PIIX4 with Type-F DMA\n")); return; } /* All the logic here assumes flags.bm_check is same across all CPUs */ if (!bm_check_flag) { /* Determine whether bm_check is needed based on CPU */ acpi_processor_power_init_bm_check(&(pr->flags), pr->id); bm_check_flag = pr->flags.bm_check; } else { pr->flags.bm_check = bm_check_flag; } if (pr->flags.bm_check) { if (!pr->flags.bm_control) { if (pr->flags.has_cst != 1) { /* bus mastering control is necessary */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "C3 support requires BM control\n")); return; } else { /* Here we enter C3 without bus mastering */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "C3 support without BM control\n")); } } } else { /* * WBINVD should be set in fadt, for C3 state to be * supported on when bm_check is not required. */ if (!(acpi_gbl_FADT.flags & ACPI_FADT_WBINVD)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cache invalidation should work properly" " for C3 to be enabled on SMP systems\n")); return; } } /* * Otherwise we've met all of our C3 requirements. * Normalize the C3 latency to expidite policy. Enable * checking of bus mastering status (bm_check) so we can * use this in our C3 policy */ cx->valid = 1; cx->latency_ticks = cx->latency; /* * On older chipsets, BM_RLD needs to be set * in order for Bus Master activity to wake the * system from C3. Newer chipsets handle DMA * during C3 automatically and BM_RLD is a NOP. * In either case, the proper way to * handle BM_RLD is to set it and leave it set. */ acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1); return; }
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); }