Example #1
0
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);
}
Example #3
0
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);
	}
}
Example #4
0
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;
}
Example #5
0
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);
}
Example #6
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);
}
Example #7
0
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;
}
Example #8
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);
}
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));
}