blob: 5ee995c2a993fce9b6f1aea7f46292cae4ddc590 [file] [log] [blame]
Ronald G. Minnichfa2df752003-08-27 14:33:13 +00001#include <console/console.h>
2#include <arch/smp/mpspec.h>
Uwe Hermann74d1a6e2010-10-12 17:34:08 +00003#include <arch/ioapic.h>
Ronald G. Minnichfa2df752003-08-27 14:33:13 +00004#include <device/pci.h>
Yinghai Lu6a61d6a2004-10-20 05:07:16 +00005#include <device/pci_ids.h>
Ronald G. Minnichfa2df752003-08-27 14:33:13 +00006#include <string.h>
7#include <stdint.h>
arch import user (historical)ef03afa2005-07-06 17:15:30 +00008#if CONFIG_LOGICAL_CPUS==1
Stefan Reinauer9a16e3e2010-03-29 14:45:36 +00009#include <cpu/amd/multicore.h>
arch import user (historical)ef03afa2005-07-06 17:15:30 +000010#endif
Ronald G. Minnichfa2df752003-08-27 14:33:13 +000011
arch import user (historical)59140cc2005-07-06 18:17:35 +000012static unsigned node_link_to_bus(unsigned node, unsigned link)
13{
14 device_t dev;
15 unsigned reg;
16
17 dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
18 if (!dev) {
19 return 0;
20 }
21 for(reg = 0xE0; reg < 0xF0; reg += 0x04) {
22 uint32_t config_map;
23 unsigned dst_node;
24 unsigned dst_link;
25 unsigned bus_base;
26 config_map = pci_read_config32(dev, reg);
27 if ((config_map & 3) != 3) {
28 continue;
29 }
30 dst_node = (config_map >> 4) & 7;
31 dst_link = (config_map >> 8) & 3;
32 bus_base = (config_map >> 16) & 0xff;
Stefan Reinauer14e22772010-04-27 06:56:47 +000033#if 0
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000034 printk(BIOS_DEBUG, "node.link=bus: %d.%d=%d 0x%2x->0x%08x\n",
arch import user (historical)59140cc2005-07-06 18:17:35 +000035 dst_node, dst_link, bus_base,
36 reg, config_map);
37#endif
38 if ((dst_node == node) && (dst_link == link))
39 {
40 return bus_base;
41 }
42 }
43 return 0;
44}
Yinghai Lu6a61d6a2004-10-20 05:07:16 +000045
Myles Watson08e0fb82010-03-22 16:33:25 +000046static void *smp_write_config_table(void *v)
Ronald G. Minnichfa2df752003-08-27 14:33:13 +000047{
Ronald G. Minnichfa2df752003-08-27 14:33:13 +000048 struct mp_config_table *mc;
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +000049 unsigned char bus_num;
50 unsigned char bus_isa;
arch import user (historical)59140cc2005-07-06 18:17:35 +000051 unsigned char bus_chain_0;
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +000052 unsigned char bus_8131_1;
53 unsigned char bus_8131_2;
54 unsigned char bus_8111_1;
arch import user (historical)ef03afa2005-07-06 17:15:30 +000055 unsigned apicid_base;
56 unsigned apicid_8111;
57 unsigned apicid_8131_1;
58 unsigned apicid_8131_2;
Stefan Reinauer14e22772010-04-27 06:56:47 +000059
arch import user (historical)ef03afa2005-07-06 17:15:30 +000060 mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
Ronald G. Minnichfa2df752003-08-27 14:33:13 +000061
Uwe Hermann55dc2232010-10-25 15:32:07 +000062 mptable_init(mc, "S2882 ", LAPIC_ADDR);
Ronald G. Minnichfa2df752003-08-27 14:33:13 +000063
Yinghai Lu6a61d6a2004-10-20 05:07:16 +000064 smp_write_processors(mc);
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +000065 {
66 device_t dev;
67
arch import user (historical)59140cc2005-07-06 18:17:35 +000068 /* HT chain 0 */
69 bus_chain_0 = node_link_to_bus(0, 0);
70 if (bus_chain_0 == 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000071 printk(BIOS_DEBUG, "ERROR - cound not find bus for node 0 chain 0, using defaults\n");
arch import user (historical)59140cc2005-07-06 18:17:35 +000072 bus_chain_0 = 1;
73 }
74
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +000075 /* 8111 */
arch import user (historical)59140cc2005-07-06 18:17:35 +000076 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x03,0));
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +000077 if (dev) {
78 bus_8111_1 = pci_read_config8(dev, PCI_SECONDARY_BUS);
79 bus_isa = pci_read_config8(dev, PCI_SUBORDINATE_BUS);
80 bus_isa++;
Stefan Reinauer14e22772010-04-27 06:56:47 +000081 }
82 else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000083 printk(BIOS_DEBUG, "ERROR - could not find PCI 1:03.0, using defaults\n");
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +000084
85 bus_8111_1 = 4;
86 bus_isa = 5;
87 }
88 /* 8131-1 */
arch import user (historical)59140cc2005-07-06 18:17:35 +000089 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x01,0));
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +000090 if (dev) {
91 bus_8131_1 = pci_read_config8(dev, PCI_SECONDARY_BUS);
92
93 }
94 else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000095 printk(BIOS_DEBUG, "ERROR - could not find PCI 1:01.0, using defaults\n");
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +000096
97 bus_8131_1 = 2;
98 }
99 /* 8131-2 */
arch import user (historical)59140cc2005-07-06 18:17:35 +0000100 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x02,0));
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +0000101 if (dev) {
102 bus_8131_2 = pci_read_config8(dev, PCI_SECONDARY_BUS);
103
104 }
105 else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000106 printk(BIOS_DEBUG, "ERROR - could not find PCI 1:02.0, using defaults\n");
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +0000107
108 bus_8131_2 = 3;
109 }
110 }
111/*Bus: Bus ID Type*/
112 /* define bus and isa numbers */
113 for(bus_num = 0; bus_num < bus_isa; bus_num++) {
114 smp_write_bus(mc, bus_num, "PCI ");
115 }
116 smp_write_bus(mc, bus_isa, "ISA ");
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000117
118
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000119/*I/O APICs: APIC ID Version State Address*/
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000120#if CONFIG_LOGICAL_CPUS==1
121 apicid_base = get_apicid_base(3);
122#else
Stefan Reinauer14e22772010-04-27 06:56:47 +0000123 apicid_base = CONFIG_MAX_PHYSICAL_CPUS;
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000124#endif
Stefan Reinauer14e22772010-04-27 06:56:47 +0000125 apicid_8111 = apicid_base+0;
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000126 apicid_8131_1 = apicid_base+1;
127 apicid_8131_2 = apicid_base+2;
128
Uwe Hermann74d1a6e2010-10-12 17:34:08 +0000129 smp_write_ioapic(mc, apicid_8111, 0x11, IO_APIC_ADDR);
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000130 {
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000131 device_t dev;
132 struct resource *res;
arch import user (historical)59140cc2005-07-06 18:17:35 +0000133 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x1,1));
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000134 if (dev) {
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000135 res = find_resource(dev, PCI_BASE_ADDRESS_0);
136 if (res) {
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000137 smp_write_ioapic(mc, apicid_8131_1, 0x11, res->base);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000138 }
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000139 }
arch import user (historical)59140cc2005-07-06 18:17:35 +0000140 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x2,1));
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000141 if (dev) {
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000142 res = find_resource(dev, PCI_BASE_ADDRESS_0);
143 if (res) {
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000144 smp_write_ioapic(mc, apicid_8131_2, 0x11, res->base);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000145 }
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000146 }
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000147
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000148 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000149
Patrick Georgic5b87c82010-05-20 15:28:19 +0000150 mptable_add_isa_interrupts(mc, bus_isa, apicid_8111, 0);
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +0000151
Patrick Georgic5b87c82010-05-20 15:28:19 +0000152/*I/O Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */
arch import user (historical)59140cc2005-07-06 18:17:35 +0000153 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_chain_0, (4<<2)|3, apicid_8111, 0x13);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000154
Stefan Reinauer14e22772010-04-27 06:56:47 +0000155
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000156//On Board AMD USB
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000157 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0<<2)|3, apicid_8111, 0x13);
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000158
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000159
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000160//On Board ATI Display Adapter
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000161 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (6<<2)|0, apicid_8111, 0x12);
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +0000162
163#if 1
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000164//Slot 5 PCI 32
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000165 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|0, apicid_8111, 0x10);
166 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|1, apicid_8111, 0x11);
167 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|2, apicid_8111, 0x12); //
168 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|3, apicid_8111, 0x13); //
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000169
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000170#endif
171//Onboard SI Serial ATA
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000172 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (5<<2)|0, apicid_8111, 0x13);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000173
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +0000174//Onboard Intel 82551 10/100M NIC
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000175 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (8<<2)|0, apicid_8111, 0x12);
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +0000176
Ronald G. Minnichb56ef072003-10-15 20:05:11 +0000177#if 1
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000178//Slot 3 PCIX 100/66
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000179 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (3<<2)|0, apicid_8131_1, 0x3);
180 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (3<<2)|1, apicid_8131_1, 0x0);
181 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (3<<2)|2, apicid_8131_1, 0x1);//
182 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (3<<2)|3, apicid_8131_1, 0x2);//
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000183
Stefan Reinauer14e22772010-04-27 06:56:47 +0000184//Slot 4 PCIX 100/66
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000185 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (2<<2)|0, apicid_8131_1, 0x2);
186 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (2<<2)|1, apicid_8131_1, 0x3);//
187 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (2<<2)|2, apicid_8131_1, 0x0);//
188 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (2<<2)|3, apicid_8131_1, 0x1);//
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000189
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000190
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000191#endif
192//Onboard adaptec scsi
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000193 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (6<<2)|0, apicid_8131_1, 0x0);
194 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (6<<2)|1, apicid_8131_1, 0x1);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000195
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000196//On Board NIC
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000197 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (9<<2)|0, apicid_8131_1, 0x0);
198 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (9<<2)|1, apicid_8131_1, 0x1);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000199
200
Ronald G. Minnichb56ef072003-10-15 20:05:11 +0000201#if 1
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000202//Slot 1 PCI-X 133/100/66
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000203 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (3<<2)|0, apicid_8131_2, 0x0);
204 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (3<<2)|1, apicid_8131_2, 0x1);
205 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (3<<2)|2, apicid_8131_2, 0x2); //
206 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (3<<2)|3, apicid_8131_2, 0x3); //
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000207
208//Slot 2 PCI-X 133/100/66
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000209 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (1<<2)|0, apicid_8131_2, 0x1);
210 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (1<<2)|1, apicid_8131_2, 0x2);
211 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (1<<2)|2, apicid_8131_2, 0x3);//
212 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (1<<2)|3, apicid_8131_2, 0x0);//
Ronald G. Minniche4fc0ab2004-03-12 15:13:38 +0000213
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000214#endif
215/*Local Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN#*/
Tobias Diedrichb907d322010-10-26 22:40:16 +0000216 smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x0);
217 smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x1);
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000218 /* There is no extension information... */
219
220 /* Compute the checksums */
221 mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
222 mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000223 printk(BIOS_DEBUG, "Wrote the mp table end at: %p - %p\n",
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000224 mc, smp_next_mpe_entry(mc));
225 return smp_next_mpe_entry(mc);
226}
227
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000228unsigned long write_smp_table(unsigned long addr)
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000229{
230 void *v;
231 v = smp_write_floating_table(addr);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000232 return (unsigned long)smp_write_config_table(v);
Ronald G. Minnichfa2df752003-08-27 14:33:13 +0000233}