blob: 7c632f572d818fc78860f1ee01c8582403e5425a [file] [log] [blame]
Angel Pons30a511c2020-04-03 01:22:09 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +00002
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +00003#include <device/device.h>
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +00004#include <console/console.h>
5#include <arch/smp/mpspec.h>
Uwe Hermann74d1a6e2010-10-12 17:34:08 +00006#include <arch/ioapic.h>
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +00007
8static void *smp_write_config_table(void *v)
9{
Elyes HAOUAS8da96e52016-09-22 21:20:54 +020010 struct mp_config_table *mc;
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +000011 struct device *riser = NULL, *firewire = NULL;
Patrick Georgi5244e1b2010-11-21 14:41:07 +000012 int firewire_bus = 0, riser_bus = 0, isa_bus;
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +000013 int ioapic_id;
14
Elyes HAOUAS8da96e52016-09-22 21:20:54 +020015 mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +000016
Patrick Georgic8feedd2012-02-16 18:43:25 +010017 mptable_init(mc, LOCAL_APIC_ADDR);
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +000018
Elyes HAOUAS8da96e52016-09-22 21:20:54 +020019 smp_write_processors(mc);
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +000020
21 firewire = dev_find_device(0x104c, 0x8023, 0);
22 if (firewire) {
23 firewire_bus = firewire->bus->secondary;
24 printk(BIOS_SPEW, "Firewire device is on bus %x\n",
25 firewire_bus);
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +000026 }
27
28 // If a riser card is used, this riser is detected on bus 4, so its secondary bus is the
29 // highest bus number on the pci bus.
30 riser = dev_find_device(0x3388, 0x0021, 0);
31 if (!riser)
32 riser = dev_find_device(0x3388, 0x0022, 0);
33 if (riser) {
Myles Watson894a3472010-06-09 22:41:35 +000034 riser_bus = riser->link_list->secondary;
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +000035 printk(BIOS_SPEW, "Riser bus is %x\n", riser_bus);
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +000036 }
37
Patrick Georgi5244e1b2010-11-21 14:41:07 +000038 mptable_write_buses(mc, NULL, &isa_bus);
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +000039
40 /* I/O APICs: APIC ID Version State Address */
41 ioapic_id = 2;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080042 smp_write_ioapic(mc, ioapic_id, 0x20, VIO_APIC_VADDR);
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +000043
44 /* Legacy Interrupts */
45
46 /* I/O Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */
47 smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x0, ioapic_id, 0x0);
48 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x1, ioapic_id, 0x1);
49 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x0, ioapic_id, 0x2);
50 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x3, ioapic_id, 0x3);
51 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x4, ioapic_id, 0x4);
52 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, isa_bus, 0x8, ioapic_id, 0x8);
53 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x9, ioapic_id, 0x9);
54 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0xa, ioapic_id, 0xa);
55 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0xb, ioapic_id, 0xb);
56 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0xc, ioapic_id, 0xc);
57 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0xd, ioapic_id, 0xd);
58 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0xe, ioapic_id, 0xe);
59 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0xf, ioapic_id, 0xf);
60
61 /* Builtin devices on Bus 0 */
62 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x4, ioapic_id, 0x10);
63 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x8, ioapic_id, 0x10);
64 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x7d, ioapic_id, 0x13);
65 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x74, ioapic_id, 0x17);
66 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x75, ioapic_id, 0x13);
67 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x76, ioapic_id, 0x12);
68 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x77, ioapic_id, 0x10);
69 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x6c, ioapic_id, 0x10);
70 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x70, ioapic_id, 0x10);
71 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x71, ioapic_id, 0x11);
72
73 /* Internal PCI bus (Firewire, PCI slot) */
74 if (firewire) {
75 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, firewire_bus, 0x0, ioapic_id, 0x10);
76 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, firewire_bus, 0x4, ioapic_id, 0x14);
77 }
78
79 if (riser) {
80 /* Old riser card */
81 // riser slot top 5:8.0
82 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, riser_bus, 0x20, ioapic_id, 0x14);
83 // riser slot middle 5:9.0
84 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, riser_bus, 0x24, ioapic_id, 0x15);
85 // riser slot bottom 5:a.0
86 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, riser_bus, 0x28, ioapic_id, 0x16);
87
88 /* New Riser Card */
89 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, riser_bus, 0x30, ioapic_id, 0x14);
90 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, riser_bus, 0x34, ioapic_id, 0x15);
91 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, riser_bus, 0x38, ioapic_id, 0x16);
92 }
93
94 /* PCIe slot */
95 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x1, 0x0, ioapic_id, 0x10);
96 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x1, 0x1, ioapic_id, 0x11);
97
98 /* Onboard Ethernet */
99 smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x2, 0x0, ioapic_id, 0x10);
100
101 /* Local Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */
Patrick Georgi6eb7a532011-10-07 21:42:52 +0200102 mptable_lintsrc(mc, isa_bus);
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +0000103
104 /* Compute the checksums */
Patrick Georgib0a9c5c2011-10-07 23:01:55 +0200105 return mptable_finalize(mc);
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +0000106}
107
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +0000108unsigned long write_smp_table(unsigned long addr)
109{
110 void *v;
Patrick Georgic75c79b2011-10-07 22:41:07 +0200111 v = smp_write_floating_table(addr, 1);
Bernhard M. Wiedemann6e554de2010-05-30 12:56:17 +0000112 return (unsigned long)smp_write_config_table(v);
113}