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