We define IO_APIC_ADDR in <arch/ioapic.h>, let's use it.
[coreboot.git] / src / mainboard / intel / xe7501devkit / mptable.c
1 #include <console/console.h>
2 #include <arch/smp/mpspec.h>
3 #include <arch/ioapic.h>
4 #include <device/pci.h>
5 #include <string.h>
6 #include <stdint.h>
7 #include <assert.h>
8 #include "bus.h"
9 #include "ioapic.h"
10
11 // Generate MP-table IRQ numbers for PCI devices.
12 #define INT_A   0
13 #define INT_B   1
14 #define INT_C   2
15 #define INT_D   3
16 #define PCI_IRQ(dev, intLine)   (((dev)<<2) | intLine)
17
18
19 static void xe7501devkit_register_buses(struct mp_config_table *mc)
20 {
21         // Bus ID, Bus Type
22         smp_write_bus(mc, PCI_BUS_CHIPSET,      BUSTYPE_PCI);
23         smp_write_bus(mc, PCI_BUS_E7501_HI_B,   BUSTYPE_PCI);
24         smp_write_bus(mc, PCI_BUS_P64H2_2_B,    BUSTYPE_PCI);
25         smp_write_bus(mc, PCI_BUS_P64H2_2_A,    BUSTYPE_PCI);
26         smp_write_bus(mc, PCI_BUS_E7501_HI_D,   BUSTYPE_PCI);
27         smp_write_bus(mc, PCI_BUS_P64H2_1_B,    BUSTYPE_PCI);
28         smp_write_bus(mc, PCI_BUS_P64H2_1_A,    BUSTYPE_PCI);
29         smp_write_bus(mc, PCI_BUS_ICH3,         BUSTYPE_PCI);
30         smp_write_bus(mc, SUPERIO_BUS,          BUSTYPE_ISA);
31 }
32
33 static void xe7501devkit_register_ioapics(struct mp_config_table *mc)
34 {
35         device_t dev;
36         struct resource *res;
37
38         // TODO: Gack. This is REALLY ugly.
39
40         // Southbridge IOAPIC
41         smp_write_ioapic(mc, IOAPIC_ICH3, 0x20, IO_APIC_ADDR);  // APIC ID, Version, Address
42
43         // P64H2#2 Bus A IOAPIC
44         dev = dev_find_slot(PCI_BUS_E7501_HI_B, PCI_DEVFN(30, 0));
45         if (!dev)
46                 BUG();          // Config.lb error?
47         res = find_resource(dev, PCI_BASE_ADDRESS_0);
48         smp_write_ioapic(mc, IOAPIC_P64H2_2_BUS_A, P64H2_IOAPIC_VERSION, res->base);
49
50         // P64H2#2 Bus B IOAPIC
51         dev = dev_find_slot(PCI_BUS_E7501_HI_B, PCI_DEVFN(28, 0));
52         if (!dev)
53                 BUG();          // Config.lb error?
54         res = find_resource(dev, PCI_BASE_ADDRESS_0);
55         smp_write_ioapic(mc, IOAPIC_P64H2_2_BUS_B, P64H2_IOAPIC_VERSION, res->base);
56
57
58         // P64H2#1 Bus A IOAPIC
59         dev = dev_find_slot(PCI_BUS_E7501_HI_D, PCI_DEVFN(30, 0));
60         if (!dev)
61                 BUG();          // Config.lb error?
62         res = find_resource(dev, PCI_BASE_ADDRESS_0);
63         smp_write_ioapic(mc, IOAPIC_P64H2_1_BUS_A, P64H2_IOAPIC_VERSION, res->base);
64
65         // P64H2#1 Bus B IOAPIC
66         dev = dev_find_slot(PCI_BUS_E7501_HI_D, PCI_DEVFN(28, 0));
67         if (!dev)
68                 BUG();          // Config.lb error?
69         res = find_resource(dev, PCI_BASE_ADDRESS_0);
70         smp_write_ioapic(mc, IOAPIC_P64H2_1_BUS_B, P64H2_IOAPIC_VERSION, res->base);
71 }
72
73 static void xe7501devkit_register_interrupts(struct mp_config_table *mc)
74 {
75         // Chipset PCI bus
76         //                                       Type           Trigger | Polarity                                                      Bus ID                          IRQ                                     APIC ID                                 PIN#
77         smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      PCI_BUS_CHIPSET,        0,                                      MP_APIC_ALL,                     0);
78         smp_write_intsrc(mc, mp_NMI,    MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH,      PCI_BUS_CHIPSET,        0,                                      MP_APIC_ALL,                     1);
79         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(29, INT_A), IOAPIC_ICH3,                        16);    // USB 1.1 Controller #1
80         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(31, INT_B),     IOAPIC_ICH3,                    17);    // SMBus
81         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(29, INT_C), IOAPIC_ICH3,                        18);    // USB 1.1 Controller #3
82         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(31, INT_C), IOAPIC_ICH3,                        18);    // IDE
83         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_CHIPSET,        PCI_IRQ(29, INT_D), IOAPIC_ICH3,                        19);    // USB 1.1 Controller #2
84
85         // P64H2#2 Bus B
86         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_2_BUS_B,    0);    // Slot 2A (J23)
87         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_B),      IOAPIC_P64H2_2_BUS_B,    1);    // Slot 2A (J23)
88         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_C),      IOAPIC_P64H2_2_BUS_B,    2);    // Slot 2A (J23)
89         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(1, INT_D),      IOAPIC_P64H2_2_BUS_B,    3);    // Slot 2A (J23)
90         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_A),      IOAPIC_P64H2_2_BUS_B,    4);    // Slot 2B (J24)
91         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_B),      IOAPIC_P64H2_2_BUS_B,    5);    // Slot 2B (J24)
92         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_C),      IOAPIC_P64H2_2_BUS_B,    6);    // Slot 2B (J24)
93         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(2, INT_D),      IOAPIC_P64H2_2_BUS_B,    7);    // Slot 2B (J24)
94         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_A),      IOAPIC_P64H2_2_BUS_B,    8);    // Slot 2C (J25)
95         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_B),      IOAPIC_P64H2_2_BUS_B,    9);    // Slot 2C (J25)
96         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_C),      IOAPIC_P64H2_2_BUS_B,   10);    // Slot 2C (J25)
97         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(3, INT_D),      IOAPIC_P64H2_2_BUS_B,   11);    // Slot 2C (J25)
98         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_A),      IOAPIC_P64H2_2_BUS_B,   12);    // Slot 2D (J12)
99         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_B),      IOAPIC_P64H2_2_BUS_B,   13);    // Slot 2D (J12)
100         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_C),      IOAPIC_P64H2_2_BUS_B,   14);    // Slot 2D (J12)
101         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_B,      PCI_IRQ(4, INT_D),      IOAPIC_P64H2_2_BUS_B,   15);    // Slot 2D (J12)
102
103         // P64H2#2 Bus A
104         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_A,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_2_BUS_A,    0);    // SCSI
105         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_2_A,      PCI_IRQ(1, INT_B),      IOAPIC_P64H2_2_BUS_A,    1);    // SCSI
106
107         // P64H2#1 Bus B
108         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_1_BUS_B,    0);    // GB Ethernet
109         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_A),      IOAPIC_P64H2_1_BUS_B,    4);    // Slot 1B (J21)
110         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_B),      IOAPIC_P64H2_1_BUS_B,    5);    // Slot 1B (J21)
111         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_C),      IOAPIC_P64H2_1_BUS_B,    6);    // Slot 1B (J21)
112         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_B,      PCI_IRQ(2, INT_D),      IOAPIC_P64H2_1_BUS_B,    7);    // Slot 1B (J21)
113
114         // P64H2#1 Bus A
115         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_A),      IOAPIC_P64H2_1_BUS_A,    0);    // Slot 1A (J20)
116         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_B),      IOAPIC_P64H2_1_BUS_A,    1);    // Slot 1A (J20)
117         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_C),      IOAPIC_P64H2_1_BUS_A,    2);    // Slot 1A (J20)
118         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_P64H2_1_A,      PCI_IRQ(1, INT_D),      IOAPIC_P64H2_1_BUS_A,    3);    // Slot 1A (J20)
119
120         // ICH-3
121
122         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(0, INT_A),      IOAPIC_ICH3,                    16);    // Video
123         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_A),      IOAPIC_ICH3,                    18);    // Debug slot (J11)
124         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_B),      IOAPIC_ICH3,                    19);    // Debug slot (J11)
125         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_C),      IOAPIC_ICH3,                    16);    // Debug slot (J11)
126         smp_write_intsrc(mc, mp_INT,    MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,       PCI_BUS_ICH3,           PCI_IRQ(2, INT_D),      IOAPIC_ICH3,                    17);    // Debug slot (J11)
127
128         // TODO: Not sure how to handle BT_INTR# signals from the P64H2s. Do we even need to, in APIC mode?
129
130         mptable_add_isa_interrupts(mc, SUPERIO_BUS, IOAPIC_ICH3, 0);
131 }
132
133 static void *smp_write_config_table(void* v)
134 {
135         static const char sig[4] = MPC_SIGNATURE;
136         static const char oem[8] = "COREBOOT";
137         static const char productid[12] = "XE7501DEVKIT";
138         struct mp_config_table *mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
139         memset(mc, 0, sizeof(*mc));
140
141         memcpy(mc->mpc_signature, sig, sizeof(sig));
142         memcpy(mc->mpc_oem, oem, sizeof(oem));
143         memcpy(mc->mpc_productid, productid, sizeof(productid));
144
145         mc->mpc_length = sizeof(*mc);   // initially just the header
146         mc->mpc_spec = 0x04;            // Multiprocessing Spec V1.4
147         mc->mpc_lapic = LAPIC_ADDR;
148
149         smp_write_processors(mc);
150
151         xe7501devkit_register_buses(mc);
152         xe7501devkit_register_ioapics(mc);
153         xe7501devkit_register_interrupts(mc);
154
155         /* Compute the checksums */
156         mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
157         mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
158         printk(BIOS_DEBUG, "Wrote the mp table end at: %p - %p\n", mc, smp_next_mpe_entry(mc));
159
160         return smp_next_mpe_entry(mc);
161 }
162
163 unsigned long write_smp_table(unsigned long addr)
164 {
165         void *v;
166         v = smp_write_floating_table(addr);
167         return (unsigned long)smp_write_config_table(v);
168 }