tree: drop last paragraph of GPL copyright header
[coreboot.git] / src / arch / x86 / ioapic.c
blob25fc84c620f1e2989e43684e6eb52796e4d5ae1a
1 /*
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.
16 #include <arch/io.h>
17 #include <arch/ioapic.h>
18 #include <console/console.h>
19 #include <cpu/x86/lapic.h>
21 u32 io_apic_read(void *ioapic_base, u32 reg)
23 write32(ioapic_base, reg);
24 return read32(ioapic_base + 0x10);
27 void io_apic_write(void *ioapic_base, u32 reg, u32 value)
29 write32(ioapic_base, reg);
30 write32(ioapic_base + 0x10, value);
33 static int ioapic_interrupt_count(void *ioapic_base)
35 /* Read the available number of interrupts. */
36 int ioapic_interrupts = (io_apic_read(ioapic_base, 0x01) >> 16) & 0xff;
37 if (ioapic_interrupts == 0xff)
38 ioapic_interrupts = 23;
39 ioapic_interrupts += 1; /* Bits 23-16 specify the maximum redirection
40 entry, which is the number of interrupts
41 minus 1. */
42 printk(BIOS_DEBUG, "IOAPIC: %d interrupts\n", ioapic_interrupts);
44 return ioapic_interrupts;
47 void clear_ioapic(void *ioapic_base)
49 u32 low, high;
50 u32 i, ioapic_interrupts;
52 printk(BIOS_DEBUG, "IOAPIC: Clearing IOAPIC at %p\n", ioapic_base);
54 ioapic_interrupts = ioapic_interrupt_count(ioapic_base);
56 low = DISABLED;
57 high = NONE;
59 for (i = 0; i < ioapic_interrupts; i++) {
60 io_apic_write(ioapic_base, i * 2 + 0x10, low);
61 io_apic_write(ioapic_base, i * 2 + 0x11, high);
63 printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
64 i, high, low);
67 if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
68 printk(BIOS_WARNING, "IOAPIC not responding.\n");
69 return;
73 void set_ioapic_id(void *ioapic_base, u8 ioapic_id)
75 u32 bsp_lapicid = lapicid();
76 int i;
78 printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at 0x%p\n",
79 ioapic_base);
80 printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC = 0x%02x\n",
81 bsp_lapicid);
83 if (ioapic_id) {
84 printk(BIOS_DEBUG, "IOAPIC: ID = 0x%02x\n", ioapic_id);
85 /* Set IOAPIC ID if it has been specified. */
86 io_apic_write(ioapic_base, 0x00,
87 (io_apic_read(ioapic_base, 0x00) & 0xf0ffffff) |
88 (ioapic_id << 24));
91 printk(BIOS_SPEW, "IOAPIC: Dumping registers\n");
92 for (i = 0; i < 3; i++)
93 printk(BIOS_SPEW, " reg 0x%04x: 0x%08x\n", i,
94 io_apic_read(ioapic_base, i));
98 static void load_vectors(void *ioapic_base)
100 u32 bsp_lapicid = lapicid();
101 u32 low, high;
102 u32 i, ioapic_interrupts;
104 ioapic_interrupts = ioapic_interrupt_count(ioapic_base);
106 #if CONFIG_IOAPIC_INTERRUPTS_ON_FSB
108 * For the Pentium 4 and above APICs deliver their interrupts
109 * on the front side bus, enable that.
111 printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on FSB\n");
112 io_apic_write(ioapic_base, 0x03,
113 io_apic_read(ioapic_base, 0x03) | (1 << 0));
114 #endif
115 #if CONFIG_IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
116 printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on APIC serial bus\n");
117 io_apic_write(ioapic_base, 0x03, 0);
118 #endif
120 /* Enable Virtual Wire Mode. */
121 low = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
122 high = bsp_lapicid << (56 - 32);
124 io_apic_write(ioapic_base, 0x10, low);
125 io_apic_write(ioapic_base, 0x11, high);
127 if (io_apic_read(ioapic_base, 0x10) == 0xffffffff) {
128 printk(BIOS_WARNING, "IOAPIC not responding.\n");
129 return;
132 printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
133 0, high, low);
134 low = DISABLED;
135 high = NONE;
136 for (i = 1; i < ioapic_interrupts; i++) {
137 io_apic_write(ioapic_base, i * 2 + 0x10, low);
138 io_apic_write(ioapic_base, i * 2 + 0x11, high);
140 printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
141 i, high, low);
145 void setup_ioapic(void *ioapic_base, u8 ioapic_id)
147 set_ioapic_id(ioapic_base, ioapic_id);
148 load_vectors(ioapic_base);