blob: c8239d25d43b52a05a2ce12c3c70a4ee84255a6f [file] [log] [blame]
Eric Biederman2c018fb2003-07-21 20:13:45 +00001#include <console/console.h>
2#include <arch/smp/mpspec.h>
Uwe Hermann74d1a6e2010-10-12 17:34:08 +00003#include <arch/ioapic.h>
Eric Biederman2c018fb2003-07-21 20:13:45 +00004#include <device/pci.h>
5#include <string.h>
6#include <stdint.h>
arch import user (historical)ef03afa2005-07-06 17:15:30 +00007#if CONFIG_LOGICAL_CPUS==1
Stefan Reinauer9a16e3e2010-03-29 14:45:36 +00008#include <cpu/amd/multicore.h>
arch import user (historical)ef03afa2005-07-06 17:15:30 +00009#endif
Eric Biederman2c018fb2003-07-21 20:13:45 +000010
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000011static unsigned node_link_to_bus(unsigned node, unsigned link)
12{
13 device_t dev;
14 unsigned reg;
15
16 dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
17 if (!dev) {
18 return 0;
19 }
20 for(reg = 0xE0; reg < 0xF0; reg += 0x04) {
21 uint32_t config_map;
22 unsigned dst_node;
23 unsigned dst_link;
24 unsigned bus_base;
25 config_map = pci_read_config32(dev, reg);
26 if ((config_map & 3) != 3) {
27 continue;
28 }
29 dst_node = (config_map >> 4) & 7;
30 dst_link = (config_map >> 8) & 3;
31 bus_base = (config_map >> 16) & 0xff;
Stefan Reinauer14e22772010-04-27 06:56:47 +000032#if 0
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000033 printk(BIOS_DEBUG, "node.link=bus: %d.%d=%d 0x%2x->0x%08x\n",
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000034 dst_node, dst_link, bus_base,
35 reg, config_map);
36#endif
37 if ((dst_node == node) && (dst_link == link))
38 {
39 return bus_base;
40 }
41 }
42 return 0;
43}
44
Myles Watson08e0fb82010-03-22 16:33:25 +000045static void *smp_write_config_table(void *v)
Eric Biederman2c018fb2003-07-21 20:13:45 +000046{
Eric Biederman2c018fb2003-07-21 20:13:45 +000047 struct mp_config_table *mc;
Patrick Georgi20979582010-09-24 18:42:56 +000048 int bus_isa;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000049 unsigned char bus_chain_0;
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +000050 unsigned char bus_8131_1;
51 unsigned char bus_8131_2;
52 unsigned char bus_8111_1;
arch import user (historical)ef03afa2005-07-06 17:15:30 +000053 unsigned apicid_base;
54 unsigned apicid_8111;
55 unsigned apicid_8131_1;
56 unsigned apicid_8131_2;
Stefan Reinauer14e22772010-04-27 06:56:47 +000057
Eric Biederman2c018fb2003-07-21 20:13:45 +000058 mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
Eric Biederman2c018fb2003-07-21 20:13:45 +000059
Uwe Hermann55dc2232010-10-25 15:32:07 +000060 mptable_init(mc, "S2880 ", LAPIC_ADDR);
Eric Biederman2c018fb2003-07-21 20:13:45 +000061
Yinghai Lu6a61d6a2004-10-20 05:07:16 +000062 smp_write_processors(mc);
Eric Biederman2c018fb2003-07-21 20:13:45 +000063
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +000064 {
65 device_t dev;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000066
67 /* HT chain 0 */
68 bus_chain_0 = node_link_to_bus(0, 0);
69 if (bus_chain_0 == 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000070 printk(BIOS_DEBUG, "ERROR - cound not find bus for node 0 chain 0, using defaults\n");
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000071 bus_chain_0 = 1;
72 }
Stefan Reinauer14e22772010-04-27 06:56:47 +000073
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +000074 /* 8111 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000075 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x03,0));
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +000076 if (dev) {
77 bus_8111_1 = pci_read_config8(dev, PCI_SECONDARY_BUS);
Stefan Reinauer14e22772010-04-27 06:56:47 +000078 }
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +000079 else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000080 printk(BIOS_DEBUG, "ERROR - could not find PCI 1:03.0, using defaults\n");
Eric Biederman2c018fb2003-07-21 20:13:45 +000081
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +000082 bus_8111_1 = 4;
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +000083 }
84 /* 8131-1 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000085 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x01,0));
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +000086 if (dev) {
87 bus_8131_1 = pci_read_config8(dev, PCI_SECONDARY_BUS);
88
89 }
90 else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000091 printk(BIOS_DEBUG, "ERROR - could not find PCI 1:01.0, using defaults\n");
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +000092
93 bus_8131_1 = 2;
94 }
95 /* 8131-2 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000096 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x02,0));
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +000097 if (dev) {
98 bus_8131_2 = pci_read_config8(dev, PCI_SECONDARY_BUS);
99
100 }
101 else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000102 printk(BIOS_DEBUG, "ERROR - could not find PCI 1:02.0, using defaults\n");
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +0000103
104 bus_8131_2 = 3;
105 }
106 }
107
108/*Bus: Bus ID Type*/
Patrick Georgi20979582010-09-24 18:42:56 +0000109 mptable_write_buses(mc, NULL, &bus_isa);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000110
Eric Biederman2c018fb2003-07-21 20:13:45 +0000111/*I/O APICs: APIC ID Version State Address*/
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000112#if CONFIG_LOGICAL_CPUS==1
113 apicid_base = get_apicid_base(3);
114#else
Stefan Reinauer14e22772010-04-27 06:56:47 +0000115 apicid_base = CONFIG_MAX_PHYSICAL_CPUS;
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000116#endif
Stefan Reinauer14e22772010-04-27 06:56:47 +0000117 apicid_8111 = apicid_base+0;
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000118 apicid_8131_1 = apicid_base+1;
119 apicid_8131_2 = apicid_base+2;
Uwe Hermann74d1a6e2010-10-12 17:34:08 +0000120 smp_write_ioapic(mc, apicid_8111, 0x11, IO_APIC_ADDR);
Eric Biederman2c018fb2003-07-21 20:13:45 +0000121 {
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000122
123 device_t dev;
124 struct resource *res;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000125 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x1,1));
Eric Biederman2c018fb2003-07-21 20:13:45 +0000126 if (dev) {
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000127 res = find_resource(dev, PCI_BASE_ADDRESS_0);
128 if (res) {
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000129 smp_write_ioapic(mc, apicid_8131_1, 0x11, res->base);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000130 }
Eric Biederman2c018fb2003-07-21 20:13:45 +0000131 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000132 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x2,1));
Eric Biederman2c018fb2003-07-21 20:13:45 +0000133 if (dev) {
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000134 res = find_resource(dev, PCI_BASE_ADDRESS_0);
135 if (res) {
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000136 smp_write_ioapic(mc, apicid_8131_2, 0x11, res->base);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000137 }
Eric Biederman2c018fb2003-07-21 20:13:45 +0000138 }
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000139
Eric Biederman2c018fb2003-07-21 20:13:45 +0000140 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000141
Patrick Georgic5b87c82010-05-20 15:28:19 +0000142 mptable_add_isa_interrupts(mc, bus_isa, apicid_8111, 0);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000143
Patrick Georgic5b87c82010-05-20 15:28:19 +0000144/*I/O Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000145 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_chain_0, (4<<2)|0, apicid_8111, 0x13);
Ronald G. Minnich8aa7bcc2003-12-02 03:58:19 +0000146
147
Ronald G. Minnich60e185f2003-08-04 22:13:57 +0000148//On Board AMD USB
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000149 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. Minnich60e185f2003-08-04 22:13:57 +0000150
151//On Board ATI Display Adapter
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000152 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. Minnich60e185f2003-08-04 22:13:57 +0000153
154//Slot 5 PCI 32
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000155 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|0, apicid_8111, 0x10);
156 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|1, apicid_8111, 0x11);
157 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|2, apicid_8111, 0x12); //
158 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|3, apicid_8111, 0x13); //
Ronald G. Minnich60e185f2003-08-04 22:13:57 +0000159
160//On Board Promise Serial ATA
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, (5<<2)|0, apicid_8111, 0x11);
Ronald G. Minnich60e185f2003-08-04 22:13:57 +0000162
163//Slot 3 PCIX 100/66
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000164 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (8<<2)|0, apicid_8131_1, 0x3);
165 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (8<<2)|1, apicid_8131_1, 0x0);
166 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (8<<2)|2, apicid_8131_1, 0x1);//
167 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (8<<2)|3, apicid_8131_1, 0x2);//
Ronald G. Minnich60e185f2003-08-04 22:13:57 +0000168
Stefan Reinauer14e22772010-04-27 06:56:47 +0000169//Slot 4 PCIX 100/66
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000170 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (7<<2)|0, apicid_8131_1, 0x2);
171 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (7<<2)|1, apicid_8131_1, 0x3);//
172 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (7<<2)|2, apicid_8131_1, 0x0);//
173 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (7<<2)|3, apicid_8131_1, 0x1);//
Ronald G. Minnich60e185f2003-08-04 22:13:57 +0000174
175//On Board NIC and LSI scsi
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000176 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (9<<2)|0, apicid_8131_1, 0x0);
177 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (9<<2)|1, apicid_8131_1, 0x1);
178 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (0xa<<2)|0, apicid_8131_1, 0x0);
179 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (0xa<<2)|1, apicid_8131_1, 0x1);
Ronald G. Minnich60e185f2003-08-04 22:13:57 +0000180
181//Slot 1 PCI-X 133/100/66
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000182 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (3<<2)|0, apicid_8131_2, 0x0);
183 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (3<<2)|1, apicid_8131_2, 0x1);
184 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (3<<2)|2, apicid_8131_2, 0x2); //
185 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. Minnich60e185f2003-08-04 22:13:57 +0000186
187//Slot 2 PCI-X 133/100/66
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000188 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (6<<2)|0, apicid_8131_2, 0x1);
189 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (6<<2)|1, apicid_8131_2, 0x2);
190 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (6<<2)|2, apicid_8131_2, 0x3);//
191 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (6<<2)|3, apicid_8131_2, 0x0);//
Ronald G. Minnich60e185f2003-08-04 22:13:57 +0000192
Eric Biederman2c018fb2003-07-21 20:13:45 +0000193/*Local Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN#*/
Tobias Diedrichb907d322010-10-26 22:40:16 +0000194 smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x0);
195 smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x1);
Eric Biederman2c018fb2003-07-21 20:13:45 +0000196 /* There is no extension information... */
197
198 /* Compute the checksums */
199 mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
200 mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000201 printk(BIOS_DEBUG, "Wrote the mp table end at: %p - %p\n",
Eric Biederman2c018fb2003-07-21 20:13:45 +0000202 mc, smp_next_mpe_entry(mc));
203 return smp_next_mpe_entry(mc);
204}
205
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000206unsigned long write_smp_table(unsigned long addr)
Eric Biederman2c018fb2003-07-21 20:13:45 +0000207{
208 void *v;
209 v = smp_write_floating_table(addr);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000210 return (unsigned long)smp_write_config_table(v);
Eric Biederman2c018fb2003-07-21 20:13:45 +0000211}