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); }
/** * 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); } }
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); }
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(); }
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); }