Beispiel #1
0
void disconnect_bsp_APIC(int virt_wire_setup)
{
	/* Go back to Virtual Wire compatibility mode */
	unsigned long value;

	/* For the spurious interrupt use vector F, and enable it */
	value = apic_read(APIC_SPIV);
	value &= ~APIC_VECTOR_MASK;
	value |= APIC_SPIV_APIC_ENABLED;
	value |= 0xf;
	apic_write(APIC_SPIV, value);

	if (!virt_wire_setup) {
		/* For LVT0 make it edge triggered, active high, external and enabled */
		value = apic_read(APIC_LVT0);
		value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
			APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
		value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
		value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
		apic_write(APIC_LVT0, value);
	} else {
		/* Disable LVT0 */
		apic_write(APIC_LVT0, APIC_LVT_MASKED);
	}

	/* For LVT1 make it edge triggered, active high, nmi and enabled */
	value = apic_read(APIC_LVT1);
	value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
			APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
	value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
	value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
	apic_write(APIC_LVT1, value);
}
Beispiel #2
0
/**
 * disconnect_bsp_APIC - detach the APIC from the interrupt system
 * @virt_wire_setup:	indicates, whether virtual wire mode is selected
 *
 * Virtual wire mode is necessary to deliver legacy interrupts even when the
 * APIC is disabled.
 */
void disconnect_bsp_APIC(int virt_wire_setup)
{
	if (pic_mode) {
		/*
		 * Put the board back into PIC mode (has an effect only on
		 * certain older boards).  Note that APIC interrupts, including
		 * IPIs, won't work beyond this point!  The only exception are
		 * INIT IPIs.
		 */
		apic_printk(APIC_VERBOSE, "disabling APIC mode, "
				"entering PIC mode.\n");
		outb(0x70, 0x22);
		outb(0x00, 0x23);
	} else {
		/* Go back to Virtual Wire compatibility mode */
		unsigned long value;

		/* For the spurious interrupt use vector F, and enable it */
		value = apic_read(APIC_SPIV);
		value &= ~APIC_VECTOR_MASK;
		value |= APIC_SPIV_APIC_ENABLED;
		value |= 0xf;
		apic_write_around(APIC_SPIV, value);

		if (!virt_wire_setup) {
			/*
			 * For LVT0 make it edge triggered, active high,
			 * external and enabled
			 */
			value = apic_read(APIC_LVT0);
			value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
				APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
				APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
			value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
			value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
			apic_write_around(APIC_LVT0, value);
		} else {
			/* Disable LVT0 */
			apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
		}

		/*
		 * For LVT1 make it edge triggered, active high, nmi and
		 * enabled
		 */
		value = apic_read(APIC_LVT1);
		value &= ~(
			APIC_MODE_MASK | APIC_SEND_PENDING |
			APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
		value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
		value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
		apic_write_around(APIC_LVT1, value);
	}
}
Beispiel #3
0
void disconnect_bsp_APIC(int virt_wire_setup)
{
    unsigned int value;

#ifdef CONFIG_X86_32
    if (pic_mode) {

        apic_printk(APIC_VERBOSE, "disabling APIC mode, "
                    "entering PIC mode.\n");
        imcr_apic_to_pic();
        return;
    }
#endif




    value = apic_read(APIC_SPIV);
    value &= ~APIC_VECTOR_MASK;
    value |= APIC_SPIV_APIC_ENABLED;
    value |= 0xf;
    apic_write(APIC_SPIV, value);

    if (!virt_wire_setup) {

        value = apic_read(APIC_LVT0);
        value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
                   APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
                   APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
        value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
        value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
        apic_write(APIC_LVT0, value);
    } else {

        apic_write(APIC_LVT0, APIC_LVT_MASKED);
    }


    value = apic_read(APIC_LVT1);
    value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
               APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
               APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
    value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
    value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
    apic_write(APIC_LVT1, value);
}
Beispiel #4
0
static void __init do_apic_setup(void)
{
	uint val;

	local_irq_disable();

	val = APIC_LVT_LEVEL_TRIGGER;
	val = SET_APIC_DELIVERY_MODE(val, APIC_MODE_EXINT);
	apic_write(APIC_LVT0, val);

	/* edge triggered, IA 7.4.11 */
	val = SET_APIC_DELIVERY_MODE(0, APIC_MODE_NMI);
	apic_write(APIC_LVT1, val);

	/* clear error register */
	/* IA32 V3, 7.4.17 */
	/* PHE must be cleared after unmasking by a back-to-back write,
	 * but it is probably ok because we mask only, the ESR is not
	 * updated is this a real problem ? */
	apic_write(APIC_ESR, 0);

	/* mask error interrupt */
	/* IA32 V3, Figure 7.8 */
	val = apic_read(APIC_LVTERR);
	val |= APIC_LVT_MASKED;
	apic_write(APIC_LVTERR, val);

	/* setup timer vector */
	/* IA32 V3, 7.4.8 */
	apic_write(APIC_LVTT, APIC_SEND_PENDING | 0x31);

	/* Divide configuration register */
	/* PHE the apic clock is based on the FSB. This should only
	 * changed with a calibration method.  */
	val = APIC_TDR_DIV_1;
	apic_write(APIC_TDCR, val);

	local_irq_enable();
}
Beispiel #5
0
void __init lvtpc_apic_setup(void * dummy)
{
	uint val;

	/* set up LVTPC as we need it */
	/* IA32 V3, Figure 7.8 */
	val = apic_read(APIC_LVTPC);
	saved_lvtpc[op_cpu_id()] = val;
	/* allow PC overflow interrupts */
	val &= ~APIC_LVT_MASKED;
	/* set delivery to NMI */
	val = SET_APIC_DELIVERY_MODE(val, APIC_MODE_NMI);
	apic_write(APIC_LVTPC, val);
}