Ejemplo n.º 1
0
int
ykbec_suspend()
{
	struct ykbec_softc *sc = ykbec_sc;
	int ctrl;

	/*
	 * Set up wakeup sources: currently only the internal keyboard.
	 */
	loongson_set_isa_imr(1 << 1);

	/* USB */
	DPRINTF(("USB\n"));
	ykbec_write(sc, REG_USB0, USB_FLAG_OFF); 
	ykbec_write(sc, REG_USB1, USB_FLAG_OFF); 
	ykbec_write(sc, REG_USB2, USB_FLAG_OFF); 

	/* EC */
	DPRINTF(("REG_PMUCFG\n"));
	ctrl = PMUCFG_SCI_WAKEUP | PMUCFG_WDT_WAKEUP | PMUCFG_GPWU_WAKEUP |
	    PMUCFG_LPC_WAKEUP | PMUCFG_STOP_MODE | PMUCFG_RESET_8051;
	ykbec_write(sc, REG_PMUCFG, ctrl);

	/* FAN */
	DPRINTF(("FAN\n"));
	ykbec_write(sc, REG_FAN_CONTROL, REG_FAN_OFF);

	/* CPU */
	DPRINTF(("CPU\n"));
	ykbec_chip_config = REGVAL(LOONGSON_CHIP_CONFIG0);
	enableintr();
	REGVAL(LOONGSON_CHIP_CONFIG0) = ykbec_chip_config & ~0x7;
	(void)REGVAL(LOONGSON_CHIP_CONFIG0);

	/*
	 * When a resume interrupt fires, we will enter the interrupt
	 * dispatcher, which will do nothing because we are at splhigh,
	 * and execution flow will return here and continue.
	 */
	(void)disableintr();

	return 0;
}
Ejemplo n.º 2
0
/*
 * Process legacy interrupts.
 *
 * XXX On 2F, ISA interrupts only occur on LOONGSON_INTR_INT0, but since
 * XXX the other LOONGSON_INTR_INT# are unmaskable, bad things will happen
 * XXX if they ever are triggered...
 */
uint32_t
lemote_isa_intr(uint32_t hwpend, struct trap_frame *frame)
{
	uint64_t imr, isr, mask;
	int bit;
	struct intrhand *ih;
	int rc;

	isr = lemote_get_isa_isr();
	imr = lemote_get_isa_imr();

	isr &= imr;
	isr &= ~(1 << 2);	/* cascade */
#ifdef DEBUG
	printf("isa interrupt: imr %04x isr %04x\n", imr, isr);
#endif
	if (isr == 0)
		return 0;	/* not for us */

	/*
	 * Mask all pending interrupts.
	 */

	loongson_set_isa_imr(imr & ~isr);

	/*
	 * If interrupts are spl-masked, mask them and wait for splx()
	 * to reenable them when necessary.
	 */
	if ((mask = isr & (BONITO_ISA_MASK(bonito_imask[frame->ipl]))) != 0) {
		isr &= ~mask;
		imr &= ~mask;
	}

	/*
	 * Now process allowed interrupts.
	 */
	if (isr != 0) {
		int lvl, bitno, ret;
		uint64_t tmpisr;

		/* Service higher level interrupts first */
		bit = BONITO_NISA - 1;
		for (lvl = IPL_HIGH - 1; lvl != IPL_NONE; lvl--) {
			tmpisr = isr & BONITO_ISA_MASK(bonito_imask[lvl] ^
			    bonito_imask[lvl - 1]);
			if (tmpisr == 0)
				continue;
			for (bitno = bit, mask = 1UL << bitno; mask != 0;
			    bitno--, mask >>= 1) {
				if ((tmpisr & mask) == 0)
					continue;

				rc = 0;
				for (ih = bonito_intrhand[BONITO_ISA_IRQ(bitno)];
				    ih != NULL; ih = ih->ih_next) {
					splraise(ih->ih_level);
					ret = (*ih->ih_fun)(ih->ih_arg);
					if (ret) {
						rc = 1;
						ih->ih_count.ec_count++;
					}
					__asm__ (".set noreorder\n");
					curcpu()->ci_ipl = frame->ipl;
					__asm__ ("sync\n\t.set reorder\n");
					if (ret == 1)
						break;
				}
				if (rc == 0)
					printf("spurious isa interrupt %d\n",
					    bitno);

				loongson_isa_specific_eoi(bitno);

				if ((isr ^= mask) == 0)
					goto done;
				if ((tmpisr ^= mask) == 0)
					break;
			}
		}
done:

		/*
		 * Reenable interrupts which have been serviced.
		 */
		loongson_set_isa_imr(imr);
	}