blob: d90da754d89f2bf9006f6c6a8353e38ede543db3 [file] [log] [blame]
Stefan Reinauer01f887d2004-03-25 09:31:10 +00001#include <console/console.h>
2#include <arch/smp/mpspec.h>
Uwe Hermann74d1a6e2010-10-12 17:34:08 +00003#include <arch/ioapic.h>
Stefan Reinauer01f887d2004-03-25 09:31:10 +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
Stefan Reinauer01f887d2004-03-25 09:31:10 +000010
Stefan Reinauer373511b2005-12-02 23:16:01 +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",
Stefan Reinauer373511b2005-12-02 23:16:01 +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)
Stefan Reinauer01f887d2004-03-25 09:31:10 +000046{
Stefan Reinauer01f887d2004-03-25 09:31:10 +000047 struct mp_config_table *mc;
Patrick Georgi20979582010-09-24 18:42:56 +000048 int bus_isa;
Stefan Reinauer373511b2005-12-02 23:16:01 +000049 unsigned char bus_chain_0;
Stefan Reinauer01f887d2004-03-25 09:31:10 +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
Stefan Reinauer01f887d2004-03-25 09:31:10 +000058 mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
Stefan Reinauer01f887d2004-03-25 09:31:10 +000059
Uwe Hermann55dc2232010-10-25 15:32:07 +000060 mptable_init(mc, "S4882 ", LAPIC_ADDR);
Stefan Reinauer01f887d2004-03-25 09:31:10 +000061
Yinghai Lu6a61d6a2004-10-20 05:07:16 +000062 smp_write_processors(mc);
Stefan Reinauer01f887d2004-03-25 09:31:10 +000063
Stefan Reinauer01f887d2004-03-25 09:31:10 +000064 {
65 device_t dev;
Stefan Reinauer14e22772010-04-27 06:56:47 +000066
Stefan Reinauer373511b2005-12-02 23:16:01 +000067 /* HT chain 0 */
68 bus_chain_0 = node_link_to_bus(0, 1);
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");
Stefan Reinauer373511b2005-12-02 23:16:01 +000071 bus_chain_0 = 1;
72 }
Stefan Reinauer14e22772010-04-27 06:56:47 +000073
Stefan Reinauer01f887d2004-03-25 09:31:10 +000074 /* 8111 */
Stefan Reinauer373511b2005-12-02 23:16:01 +000075 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x03,0));
Stefan Reinauer01f887d2004-03-25 09:31:10 +000076 if (dev) {
77 bus_8111_1 = pci_read_config8(dev, PCI_SECONDARY_BUS);
Stefan Reinauer14e22772010-04-27 06:56:47 +000078 }
Stefan Reinauer01f887d2004-03-25 09:31:10 +000079 else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000080 printk(BIOS_DEBUG, "ERROR - could not find PCI 1:03.0, using defaults\n");
Stefan Reinauer01f887d2004-03-25 09:31:10 +000081
82 bus_8111_1 = 4;
Stefan Reinauer01f887d2004-03-25 09:31:10 +000083 }
84 /* 8131-1 */
Stefan Reinauer373511b2005-12-02 23:16:01 +000085 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x01,0));
Stefan Reinauer01f887d2004-03-25 09:31:10 +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");
Stefan Reinauer01f887d2004-03-25 09:31:10 +000092
93 bus_8131_1 = 2;
94 }
95 /* 8131-2 */
Stefan Reinauer373511b2005-12-02 23:16:01 +000096 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x02,0));
Stefan Reinauer01f887d2004-03-25 09:31:10 +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");
Stefan Reinauer01f887d2004-03-25 09:31:10 +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
Stefan Reinauer01f887d2004-03-25 09:31:10 +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);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000114#else
115 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);
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000121 {
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000122 device_t dev;
123 struct resource *res;
Stefan Reinauer373511b2005-12-02 23:16:01 +0000124 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x1,1));
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000125 if (dev) {
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000126 res = find_resource(dev, PCI_BASE_ADDRESS_0);
127 if (res) {
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000128 smp_write_ioapic(mc, apicid_8131_1, 0x11, res->base);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000129 }
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000130 }
Stefan Reinauer373511b2005-12-02 23:16:01 +0000131 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x2,1));
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000132 if (dev) {
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000133 res = find_resource(dev, PCI_BASE_ADDRESS_0);
134 if (res) {
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000135 smp_write_ioapic(mc, apicid_8131_2, 0x11, res->base);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000136 }
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000137 }
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000138
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000139 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000140
Patrick Georgic5b87c82010-05-20 15:28:19 +0000141 mptable_add_isa_interrupts(mc, bus_isa, apicid_8111, 0);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000142
Patrick Georgic5b87c82010-05-20 15:28:19 +0000143/*I/O Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */
Stefan Reinauer373511b2005-12-02 23:16:01 +0000144 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_chain_0, (4<<2)|0, apicid_8111, 0x13);
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000145
146
147//On Board AMD USB
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000148 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0<<2)|3, apicid_8111, 0x13);
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000149
150//On Board Via USB 1.1 and 2
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000151 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (3<<2)|0, apicid_8111, 0x11); //1.1
152 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (3<<2)|1, apicid_8111, 0x10); //1.1
153 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (3<<2)|2, apicid_8111, 0x12); //2
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000154
155//Slot 5 PCI 32
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000156 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|0, apicid_8111, 0x10);
157 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|1, apicid_8111, 0x11);
158 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|2, apicid_8111, 0x12); //
159 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (4<<2)|3, apicid_8111, 0x13); //
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000160
161
162//On Board SI Serial ATA
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000163 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (5<<2)|0, apicid_8111, 0x13);
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000164//On Board ATI Display Adapter
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, (6<<2)|0, apicid_8111, 0x12);
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000166
167
168//Slot 4 PCIX 100/66
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000169 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (3<<2)|0, apicid_8131_1, 0x3);
170 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (3<<2)|1, apicid_8131_1, 0x0);
171 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (3<<2)|2, apicid_8131_1, 0x1);//
172 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (3<<2)|3, apicid_8131_1, 0x2);//
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000173
Stefan Reinauer14e22772010-04-27 06:56:47 +0000174//Slot 3 PCIX 100/66
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_8131_1, (2<<2)|0, apicid_8131_1, 0x2);
176 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (2<<2)|1, apicid_8131_1, 0x3);//
177 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (2<<2)|2, apicid_8131_1, 0x0);//
178 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (2<<2)|3, apicid_8131_1, 0x1);//
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000179
180//On Board LSI scsi and NIC
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000181 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (4<<2)|0, apicid_8131_1, 0x0);
182 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (4<<2)|1, apicid_8131_1, 0x1);
183 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (9<<2)|0, apicid_8131_1, 0x0);
184 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_1, (9<<2)|1, apicid_8131_1, 0x1);
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000185
186//Slot 2 PCI-X 133/100/66
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000187 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (3<<2)|0, apicid_8131_2, 0x0);
188 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (3<<2)|1, apicid_8131_2, 0x1);
189 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (3<<2)|2, apicid_8131_2, 0x2); //
190 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (3<<2)|3, apicid_8131_2, 0x3); //
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000191
192//Slot 1 PCI-X 133/100/66
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_2, (1<<2)|0, apicid_8131_2, 0x1);
194 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (1<<2)|1, apicid_8131_2, 0x2);
195 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (1<<2)|2, apicid_8131_2, 0x3);//
196 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8131_2, (1<<2)|3, apicid_8131_2, 0x0);//
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000197
198/*Local Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN#*/
Tobias Diedrichb907d322010-10-26 22:40:16 +0000199 smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x0);
200 smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x1);
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000201 /* There is no extension information... */
202
203 /* Compute the checksums */
204 mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
205 mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000206 printk(BIOS_DEBUG, "Wrote the mp table end at: %p - %p\n",
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000207 mc, smp_next_mpe_entry(mc));
208 return smp_next_mpe_entry(mc);
209}
210
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000211unsigned long write_smp_table(unsigned long addr)
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000212{
213 void *v;
214 v = smp_write_floating_table(addr);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000215 return (unsigned long)smp_write_config_table(v);
Stefan Reinauer01f887d2004-03-25 09:31:10 +0000216}