static u32 acpi_ev_sci_handler (void *context) { u32 interrupt_handled = INTERRUPT_NOT_HANDLED; FUNCTION_TRACE("Ev_sci_handler"); /* * Make sure that ACPI is enabled by checking SCI_EN. Note that we are * required to treat the SCI interrupt as sharable, level, active low. */ if (!acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_DO_NOT_LOCK, SCI_EN)) { /* ACPI is not enabled; this interrupt cannot be for us */ return_VALUE (INTERRUPT_NOT_HANDLED); } /* * Fixed Acpi_events: * ------------- * Check for and dispatch any Fixed Acpi_events that have occurred */ interrupt_handled |= acpi_ev_fixed_event_detect (); /* * GPEs: * ----- * Check for and dispatch any GPEs that have occurred */ interrupt_handled |= acpi_ev_gpe_detect (); return_VALUE (interrupt_handled); }
acpi_status acpi_ev_fixed_event_initialize(void) { int i = 0; /* Initialize the structure that keeps track of fixed event handlers */ for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { acpi_gbl_fixed_event_handlers[i].handler = NULL; acpi_gbl_fixed_event_handlers[i].context = NULL; } acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, TMR_EN, 0); acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, GBL_EN, 0); acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, PWRBTN_EN, 0); acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, SLPBTN_EN, 0); acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, RTC_EN, 0); return (AE_OK); }
u32 acpi_hw_get_mode (void) { FUNCTION_TRACE ("Hw_get_mode"); if (acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, SCI_EN)) { return_VALUE (SYS_MODE_ACPI); } else { return_VALUE (SYS_MODE_LEGACY); } }
static int sm_osl_proc_write_gpe ( struct file *file, const char *buffer, unsigned long count, void *data) { char buf[256]; char *str = buf; char *next; int error = -EINVAL; u32 addr,value = 0; if (count > sizeof(buf) + 1) return -EINVAL; if (copy_from_user(str,buffer,count)) return -EFAULT; str[count] = '\0'; /* set addr to which block to refer to */ if (!strncmp(str,"GPE0 ",5)) addr = GPE0_EN_BLOCK; else if (!strncmp(str,"GPE1 ",5)) addr = GPE1_EN_BLOCK; else goto out; str += 5; /* set low order bits to index of bit to set */ addr |= simple_strtoul(str,&next,0); if (next == str) goto out; if (next) { str = ++next; value = simple_strtoul(str,&next,0); if (next == str) value = 1; } value = acpi_hw_register_bit_access(ACPI_WRITE,ACPI_MTX_LOCK,addr,(value ? 1 : 0)); error = 0; out: return error ? error : count; }
ACPI_STATUS acpi_hw_set_cx ( u32 cx_state) { /* * Supported State? * ---------------- */ if ((cx_state < 1) || (cx_state > 3)) { return (AE_BAD_PARAMETER); } if (!acpi_hw_cx_handlers[cx_state]) { return (AE_SUPPORT); } /* * New Cx State? * ------------- * We only care when moving from one state to another... */ if (acpi_hw_active_cx_state == cx_state) { return (AE_OK); } /* * Prepare to Use New State: * ------------------------- * If the new Cx_state is C3, the BM_RLD bit must be set to allow * the generation of a bus master requets to cause the processor * in the C3 state to transition to the C0 state. */ switch (cx_state) { case 3: acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 1); break; } /* * Clean up from Old State: * ------------------------ * If the old Cx_state was C3, the BM_RLD bit is reset. When the * bit is reset, the generation of a bus master request does not * effect any processor in the C3 state. */ switch (acpi_hw_active_cx_state) { case 3: acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 0); break; } /* * Enable: * ------- */ acpi_hw_active_cx_state = cx_state; return (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); }
int sm_osl_proc_write_alarm ( struct file *file, const char *buffer, unsigned long count, void *data) { char buf[30]; char *str = buf; u32 sec,min,hr; u32 day,mo,yr; int adjust = 0; unsigned char rtc_control; int error = -EINVAL; if (count > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(str,buffer,count)) return -EFAULT; str[count] = '\0'; /* check for time adjustment */ if (str[0] == '+') { str++; adjust = 1; } if ((error = get_date_field(&str,&yr))) goto out; if ((error = get_date_field(&str,&mo))) goto out; if ((error = get_date_field(&str,&day))) goto out; if ((error = get_date_field(&str,&hr))) goto out; if ((error = get_date_field(&str,&min))) goto out; if ((error = get_date_field(&str,&sec))) goto out; 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); } /* unlock the lock on the rtc now that we're done with it */ spin_unlock_irq(&rtc_lock); acpi_hw_register_bit_access(ACPI_WRITE,ACPI_MTX_LOCK, RTC_EN, 1); file->f_pos += count; error = 0; out: return error ? error : count; }
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); }
u32 acpi_ev_fixed_event_dispatch ( u32 event) { u32 register_id; FUNCTION_ENTRY (); /* Clear the status bit */ switch (event) { case ACPI_EVENT_PMTIMER: register_id = TMR_STS; break; case ACPI_EVENT_GLOBAL: register_id = GBL_STS; break; case ACPI_EVENT_POWER_BUTTON: register_id = PWRBTN_STS; break; case ACPI_EVENT_SLEEP_BUTTON: register_id = SLPBTN_STS; break; case ACPI_EVENT_RTC: register_id = RTC_STS; break; default: return 0; break; } acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, register_id, 1); /* * Make sure we've got a handler. If not, report an error. * The event is disabled to prevent further interrupts. */ if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { register_id = (PM1_EN | REGISTER_BIT_ID(register_id)); acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, register_id, 0); REPORT_ERROR ( ("Ev_gpe_dispatch: No installed handler for fixed event [%08X]\n", event)); return (INTERRUPT_NOT_HANDLED); } /* Invoke the handler */ return ((acpi_gbl_fixed_event_handlers[event].handler)( acpi_gbl_fixed_event_handlers[event].context)); }