blob: 2119c0f20cec99bda8b98a3b584464d0ef90b151 [file] [log] [blame]
Stefan Reinauer2ab88d12004-04-24 23:01:33 +00001#include <console/console.h>
2#include <arch/smp/mpspec.h>
Uwe Hermann74d1a6e2010-10-12 17:34:08 +00003#include <arch/ioapic.h>
Stefan Reinauer2ab88d12004-04-24 23:01:33 +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 Reinauer2ab88d12004-04-24 23:01:33 +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)
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000046{
Stefan Reinauer2ab88d12004-04-24 23:01:33 +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;
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000050 unsigned char bus_8111_1;
51 unsigned char bus_8151_1;
arch import user (historical)ef03afa2005-07-06 17:15:30 +000052 unsigned apicid_base;
53 unsigned apicid_8111;
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000054
55 mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000056
Uwe Hermann55dc2232010-10-25 15:32:07 +000057 mptable_init(mc, "S2875 ", LAPIC_ADDR);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000058
Yinghai Lu6a61d6a2004-10-20 05:07:16 +000059 smp_write_processors(mc);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000060
arch import user (historical)ef03afa2005-07-06 17:15:30 +000061 {
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000062 device_t dev;
63
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000064 /* HT chain 0 */
65 bus_chain_0 = node_link_to_bus(0, 0);
66 if (bus_chain_0 == 0) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000067 printk(BIOS_DEBUG, "ERROR - cound not find bus for node 0 chain 0, using defaults\n");
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000068 bus_chain_0 = 1;
69 }
70
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000071 /* 8111 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000072 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x04,0));
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000073 if (dev) {
74 bus_8111_1 = pci_read_config8(dev, PCI_SECONDARY_BUS);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000075 }
76 else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000077 printk(BIOS_DEBUG, "ERROR - could not find PCI 1:03.0, using defaults\n");
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000078
79 bus_8111_1 = 3;
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000080 }
81 /* 8151 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000082 dev = dev_find_slot(bus_chain_0, PCI_DEVFN(0x02,0));
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000083 if (dev) {
84 bus_8151_1 = pci_read_config8(dev, PCI_SECONDARY_BUS);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000085 printk(BIOS_DEBUG, "bus_8151_1=%d\n",bus_8151_1);
Stefan Reinauer14e22772010-04-27 06:56:47 +000086
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000087 }
88 else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000089 printk(BIOS_DEBUG, "ERROR - could not find PCI 1:02.0, using defaults\n");
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000090
91 bus_8151_1 = 2;
92 }
Stefan Reinauer14e22772010-04-27 06:56:47 +000093
94
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000095 }
96
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000097/*Bus: Bus ID Type*/
Patrick Georgi20979582010-09-24 18:42:56 +000098 mptable_write_buses(mc, NULL, &bus_isa);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +000099
100/*I/O APICs: APIC ID Version State Address*/
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000101#if CONFIG_LOGICAL_CPUS==1
102 apicid_base = get_apicid_base(1);
103#else
Stefan Reinauer14e22772010-04-27 06:56:47 +0000104 apicid_base = CONFIG_MAX_PHYSICAL_CPUS;
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000105#endif
Stefan Reinauer14e22772010-04-27 06:56:47 +0000106 apicid_8111 = apicid_base+0;
Uwe Hermann74d1a6e2010-10-12 17:34:08 +0000107 smp_write_ioapic(mc, apicid_8111, 0x11, IO_APIC_ADDR);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000108
Patrick Georgic5b87c82010-05-20 15:28:19 +0000109 mptable_add_isa_interrupts(mc, bus_isa, apicid_8111, 0);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000110
Patrick Georgic5b87c82010-05-20 15:28:19 +0000111/*I/O Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000112//??? What
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000113 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_chain_0, (5<<2)|3, apicid_8111, 0x13);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000114//Onboard AMD AC97 Audio ???
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000115 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_chain_0, (5<<2)|1, apicid_8111, 0x11);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000116// Onboard AMD USB
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000117 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0<<2)|3, apicid_8111, 0x13);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000118
119// AGP Display Adapter
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000120 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8151_1, 0x0, apicid_8111, 0x10);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000121
Stefan Reinauer14e22772010-04-27 06:56:47 +0000122// Onboard Serial ATA
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000123 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x05<<2)|0, apicid_8111, 0x13);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000124//Onboard Firewire
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000125 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x0a<<2)|0, apicid_8111, 0x11);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000126//Onboard Broadcom NIC
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000127 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x03<<2)|0, apicid_8111, 0x12);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000128
129//Onboard VIA USB 1.1
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000130 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x0b<<2)|0, apicid_8111, 0x11);
131 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x0b<<2)|1, apicid_8111, 0x12);
132 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x0b<<2)|2, apicid_8111, 0x13);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000133
134//Slot 1
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000135 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x06<<2)|0, apicid_8111, 0x12);
136 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x06<<2)|1, apicid_8111, 0x13);
137 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x06<<2)|2, apicid_8111, 0x10); //
138 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x06<<2)|3, apicid_8111, 0x11); //
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000139
140//Slot 2
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000141 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x08<<2)|0, apicid_8111, 0x11);
142 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x08<<2)|1, apicid_8111, 0x12);
143 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x08<<2)|2, apicid_8111, 0x13); //
144 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x08<<2)|3, apicid_8111, 0x10); //
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000145
146//Slot 3
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000147 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x09<<2)|0, apicid_8111, 0x10);
148 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x09<<2)|1, apicid_8111, 0x11);
149 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x09<<2)|2, apicid_8111, 0x12); //
150 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x09<<2)|3, apicid_8111, 0x13); //
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000151
152//Slot 4
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000153 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x07<<2)|0, apicid_8111, 0x13);
154 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x07<<2)|1, apicid_8111, 0x10);
155 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x07<<2)|2, apicid_8111, 0x11); //
156 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x07<<2)|3, apicid_8111, 0x12); //
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000157
158
159//Slot 5
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000160 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x04<<2)|0, apicid_8111, 0x10);
161 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x04<<2)|1, apicid_8111, 0x11);
162 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x04<<2)|2, apicid_8111, 0x12); //
163 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, bus_8111_1, (0x04<<2)|3, apicid_8111, 0x13); //
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000164
165
166
167/*Local Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN#*/
Tobias Diedrichb907d322010-10-26 22:40:16 +0000168 smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x0);
169 smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, bus_isa, 0x0, MP_APIC_ALL, 0x1);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000170 /* There is no extension information... */
171
172 /* Compute the checksums */
173 mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
174 mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000175 printk(BIOS_DEBUG, "Wrote the mp table end at: %p - %p\n",
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000176 mc, smp_next_mpe_entry(mc));
177 return smp_next_mpe_entry(mc);
178}
179
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000180unsigned long write_smp_table(unsigned long addr)
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000181{
182 void *v;
183 v = smp_write_floating_table(addr);
Yinghai Lu6a61d6a2004-10-20 05:07:16 +0000184 return (unsigned long)smp_write_config_table(v);
Stefan Reinauer2ab88d12004-04-24 23:01:33 +0000185}