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);
37 void clear_ioapic(u32 ioapic_base)
40 u32 i, ioapic_interrupts;
42 printk(BIOS_DEBUG, "IOAPIC: Clearing IOAPIC at 0x%08x\n", ioapic_base);
44 /* Read the available number of interrupts. */
45 ioapic_interrupts = (io_apic_read(ioapic_base, 0x01) >> 16) & 0xff;
46 if (!ioapic_interrupts || ioapic_interrupts == 0xff)
47 ioapic_interrupts = 24;
48 printk(BIOS_DEBUG, "IOAPIC: %d interrupts\n", ioapic_interrupts);
53 for (i = 0; i < ioapic_interrupts; i++) {
54 io_apic_write(ioapic_base, i * 2 + 0x10, low);
55 io_apic_write(ioapic_base, i * 2 + 0x11, high);
57 printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
61 if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
62 printk(BIOS_WARNING, "IOAPIC 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",
75 printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC = 0x%02x\n",
79 printk(BIOS_DEBUG, "IOAPIC: ID = 0x%02x\n", ioapic_id);
80 /* Set IOAPIC ID if it has been specified. */
81 io_apic_write(ioapic_base, 0x00,
82 (io_apic_read(ioapic_base, 0x00) & 0xfff0ffff) |
86 /* Read the available number of interrupts. */
87 ioapic_interrupts = (io_apic_read(ioapic_base, 0x01) >> 16) & 0xff;
88 if (!ioapic_interrupts || ioapic_interrupts == 0xff)
89 ioapic_interrupts = 24;
90 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
102 * For the Pentium 4 and above APICs deliver their interrupts
103 * on the front side bus, enable that.
105 printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on FSB\n");
106 io_apic_write(ioapic_base, 0x03,
107 io_apic_read(ioapic_base, 0x03) | (1 << 0));
109 #ifdef IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
110 printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on APIC serial bus\n");
111 io_apic_write(ioapic_base, 0x03, 0);
114 /* Enable Virtual Wire Mode. */
115 low = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
116 high = bsp_lapicid << (56 - 32);
118 io_apic_write(ioapic_base, 0x10, low);
119 io_apic_write(ioapic_base, 0x11, high);
121 if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
122 printk(BIOS_WARNING, "IOAPIC not responding.\n");
126 printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
132 for (i = 1; i < ioapic_interrupts; i++) {
133 io_apic_write(ioapic_base, i * 2 + 0x10, low);
134 io_apic_write(ioapic_base, i * 2 + 0x11, high);
136 printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",