blob: 9279b8485d5f553cc0081a8b0255140c8e3e1500 [file] [log] [blame]
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +00001#include <console/console.h>
2#include <arch/smp/mpspec.h>
Uwe Hermann74d1a6e2010-10-12 17:34:08 +00003#include <arch/ioapic.h>
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +00004#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
Stefan Reinauer0b2f1852010-03-30 21:43:15 +000018static void xe7501devkit_register_buses(struct mp_config_table *mc)
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000019{
20 // Bus ID, Bus Type
Stefan Reinauer0b2f1852010-03-30 21:43:15 +000021 smp_write_bus(mc, PCI_BUS_CHIPSET, BUSTYPE_PCI);
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000022 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);
Stefan Reinauer0b2f1852010-03-30 21:43:15 +000028 smp_write_bus(mc, PCI_BUS_ICH3, BUSTYPE_PCI);
29 smp_write_bus(mc, SUPERIO_BUS, BUSTYPE_ISA);
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000030}
31
Stefan Reinauer0b2f1852010-03-30 21:43:15 +000032static void xe7501devkit_register_ioapics(struct mp_config_table *mc)
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000033{
34 device_t dev;
Stefan Reinauer0b2f1852010-03-30 21:43:15 +000035 struct resource *res;
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000036
37 // TODO: Gack. This is REALLY ugly.
38
39 // Southbridge IOAPIC
Uwe Hermann74d1a6e2010-10-12 17:34:08 +000040 smp_write_ioapic(mc, IOAPIC_ICH3, 0x20, IO_APIC_ADDR); // APIC ID, Version, Address
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000041
42 // P64H2#2 Bus A IOAPIC
Stefan Reinauer14e22772010-04-27 06:56:47 +000043 dev = dev_find_slot(PCI_BUS_E7501_HI_B, PCI_DEVFN(30, 0));
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000044 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
Stefan Reinauer14e22772010-04-27 06:56:47 +000050 dev = dev_find_slot(PCI_BUS_E7501_HI_B, PCI_DEVFN(28, 0));
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000051 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
Stefan Reinauer14e22772010-04-27 06:56:47 +000058 dev = dev_find_slot(PCI_BUS_E7501_HI_D, PCI_DEVFN(30, 0));
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000059 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
Stefan Reinauer14e22772010-04-27 06:56:47 +000065 dev = dev_find_slot(PCI_BUS_E7501_HI_D, PCI_DEVFN(28, 0));
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000066 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
Stefan Reinauerc02c34e2010-04-07 02:30:57 +000072static void xe7501devkit_register_interrupts(struct mp_config_table *mc)
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000073{
74 // Chipset PCI bus
75 // Type Trigger | Polarity Bus ID IRQ APIC ID PIN#
Tobias Diedrichb907d322010-10-26 22:40:16 +000076 smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH, PCI_BUS_CHIPSET, 0, MP_APIC_ALL, 0);
77 smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE |MP_IRQ_POLARITY_HIGH, PCI_BUS_CHIPSET, 0, MP_APIC_ALL, 1);
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +000078 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)
Stefan Reinauer14e22772010-04-27 06:56:47 +0000101
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +0000102 // 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
Stefan Reinauer14e22772010-04-27 06:56:47 +0000105
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +0000106 // 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
Stefan Reinauer14e22772010-04-27 06:56:47 +0000120
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +0000121 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)
Stefan Reinauer14e22772010-04-27 06:56:47 +0000126
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +0000127 // TODO: Not sure how to handle BT_INTR# signals from the P64H2s. Do we even need to, in APIC mode?
128
Patrick Georgic5b87c82010-05-20 15:28:19 +0000129 mptable_add_isa_interrupts(mc, SUPERIO_BUS, IOAPIC_ICH3, 0);
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +0000130}
131
Myles Watson08e0fb82010-03-22 16:33:25 +0000132static void *smp_write_config_table(void* v)
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +0000133{
Uwe Hermann55dc2232010-10-25 15:32:07 +0000134 struct mp_config_table *mc;
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +0000135
Uwe Hermann55dc2232010-10-25 15:32:07 +0000136 mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +0000137
Uwe Hermann55dc2232010-10-25 15:32:07 +0000138 mptable_init(mc, "XE7501DEVKIT", LAPIC_ADDR);
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +0000139
140 smp_write_processors(mc);
141
142 xe7501devkit_register_buses(mc);
143 xe7501devkit_register_ioapics(mc);
144 xe7501devkit_register_interrupts(mc);
145
146 /* Compute the checksums */
147 mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
148 mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000149 printk(BIOS_DEBUG, "Wrote the mp table end at: %p - %p\n", mc, smp_next_mpe_entry(mc));
Stefan Reinauerbbbfd9d2005-12-03 23:48:17 +0000150
151 return smp_next_mpe_entry(mc);
152}
153
154unsigned long write_smp_table(unsigned long addr)
155{
156 void *v;
157 v = smp_write_floating_table(addr);
158 return (unsigned long)smp_write_config_table(v);
159}