2 * This file is part of the coreboot project.
4 * Copyright (C) 2010 coresystems GmbH
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <arch/ioapic.h>
22 #include <console/console.h>
23 #include <cpu/x86/lapic.h>
25 static u32 io_apic_read(u32 ioapic_base, u32 reg)
27 write32(ioapic_base, reg);
28 return read32(ioapic_base + 0x10);
31 static void io_apic_write(u32 ioapic_base, u32 reg, u32 value)
33 write32(ioapic_base, reg);
34 write32(ioapic_base + 0x10, value);
38 void clear_ioapic(u32 ioapic_base)
41 u32 i, ioapic_interrupts;
43 printk(BIOS_DEBUG, "IOAPIC: Clearing IOAPIC at 0x%08x\n", ioapic_base);
45 /* Read the available number of interrupts */
46 ioapic_interrupts = (io_apic_read(ioapic_base, 1) >> 16) & 0xff;
47 if (!ioapic_interrupts || ioapic_interrupts == 0xff)
48 ioapic_interrupts = 24;
49 printk(BIOS_DEBUG, "IOAPIC: %d interrupts\n", ioapic_interrupts);
54 for (i = 0; i < ioapic_interrupts; i++) {
55 io_apic_write(ioapic_base, i * 2 + 0x10, low);
56 io_apic_write(ioapic_base, i * 2 + 0x11, high);
58 printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n", i, high, low);
61 if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
62 printk(BIOS_WARNING, "IO APIC not responding.\n");
67 void setup_ioapic(u32 ioapic_base, u8 ioapic_id)
69 u32 bsp_lapicid = lapicid();
71 u32 i, ioapic_interrupts;
73 printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at 0x%08x\n", ioapic_base);
74 printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC = %02x\n",
78 printk(BIOS_DEBUG, "IOAPIC: ID = 0x%02x\n", ioapic_id);
79 /* Set IOAPIC ID if it has been specified */
80 io_apic_write(ioapic_base, 0x00,
81 (io_apic_read(ioapic_base, 0x00) & 0xfff0ffff) |
85 /* Read the available number of interrupts */
86 ioapic_interrupts = (io_apic_read(ioapic_base, 1) >> 16) & 0xff;
87 if (!ioapic_interrupts || ioapic_interrupts == 0xff)
88 ioapic_interrupts = 24;
89 printk(BIOS_DEBUG, "IOAPIC: %d interrupts\n", ioapic_interrupts);
92 // XXX this decision should probably be made elsewhere, and
93 // it's the C3, not the EPIA this depends on.
94 #if defined(CONFIG_EPIA_VT8237R_INIT) && CONFIG_EPIA_VT8237R_INIT
95 #define IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
97 #define IOAPIC_INTERRUPTS_ON_FSB
100 #ifdef IOAPIC_INTERRUPTS_ON_FSB
101 /* For the Pentium 4 and above APICs deliver their interrupts
102 * on the front side bus, enable that.
104 printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on FSB\n");
105 io_apic_write(ioapic_base, 0x03, io_apic_read(ioapic_base, 0x03) | (1 << 0));
107 #ifdef IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
108 printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on APIC serial bus\n");
109 io_apic_write(ioapic_base, 0x03, 0);
112 /* Enable Virtual Wire Mode */
113 low = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
114 high = bsp_lapicid << (56 - 32);
116 io_apic_write(ioapic_base, 0x10, low);
117 io_apic_write(ioapic_base, 0x11, high);
119 if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
120 printk(BIOS_WARNING, "IO APIC not responding.\n");
124 printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n", 0, high, low);
129 for (i = 1; i < ioapic_interrupts; i++) {
130 io_apic_write(ioapic_base, i * 2 + 0x10, low);
131 io_apic_write(ioapic_base, i * 2 + 0x11, high);
133 printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n", i, high, low);