Persimmon: Change MPTable to use mainboard IRQ routing
With the addition of the mainboard PCI IRQ routing tables for AMD Persimmon, the MPTables can be set to use this information to accurately reflect the real hardware settings of the system. Additionally, the IOAPIC gets defined before the MPTable gets generated so the settings can be read directly from the IOAPIC registers instead of 'guessing' at them as was done before. Change-Id: I96ec046a2208eddf4b5e442214ff43d2a349ca4d Signed-off-by: Mike Loptien <mike.loptien@se-eng.com> Reviewed-on: http://review.coreboot.org/5878 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com> Reviewed-by: Marc Jones <marc.jones@se-eng.com>
This commit is contained in:
parent
d0167d3ae2
commit
cbc783f3e1
|
@ -25,6 +25,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <cpu/amd/amdfam14.h>
|
||||
#include "agesawrapper.h"
|
||||
#include <arch/ioapic.h>
|
||||
#if CONFIG_AMD_SB_CIMX
|
||||
#include <sb_cimx.h>
|
||||
#endif
|
||||
|
@ -36,6 +37,7 @@
|
|||
u8 bus_isa;
|
||||
u8 bus_sb800[6];
|
||||
u32 apicid_sb800;
|
||||
u32 apicver_sb800;
|
||||
|
||||
/*
|
||||
* Here you only need to set value in pci1234 for HT-IO that could be installed or not
|
||||
|
@ -138,7 +140,14 @@ void get_bus_conf(void)
|
|||
/* I/O APICs: APIC ID Version State Address */
|
||||
bus_isa = 10;
|
||||
apicid_base = CONFIG_MAX_CPUS;
|
||||
apicid_sb800 = apicid_base;
|
||||
|
||||
/*
|
||||
* By the time this function gets called, the IOAPIC registers
|
||||
* have been written so they can be read to get the correct
|
||||
* APIC ID and Version
|
||||
*/
|
||||
apicid_sb800 = (io_apic_read(IO_APIC_ADDR, 0x00) >> 24);
|
||||
apicver_sb800 = (io_apic_read(IO_APIC_ADDR, 0x01) & 0xFF);
|
||||
|
||||
#if CONFIG_AMD_SB_CIMX
|
||||
sb_Late_Post();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2011 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2014 Sage Electronic Engineering, LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -26,124 +27,113 @@
|
|||
#include <stdint.h>
|
||||
#include <cpu/amd/amdfam14.h>
|
||||
#include <SBPLATFORM.h>
|
||||
#include <southbridge/amd/cimx/cimx_util.h>
|
||||
#include <drivers/generic/ioapic/chip.h>
|
||||
#include <arch/ioapic.h>
|
||||
|
||||
extern u8 bus_sb800[6];
|
||||
|
||||
extern u32 apicid_sb800;
|
||||
extern u32 apicver_sb800;
|
||||
|
||||
extern u32 bus_type[256];
|
||||
extern u32 sbdn_sb800;
|
||||
|
||||
u8 intr_data[] = {
|
||||
[0x00] = 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, /* INTA# - INTH# */
|
||||
[0x08] = 0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F, /* Misc-nil,0,1,2, INT from Serial irq */
|
||||
[0x10] = 0x09,0x1F,0x1F,0x10,0x1F,0x12,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x12,0x11,0x12,0x11,0x12,0x11,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x11,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x10,0x11,0x12,0x13
|
||||
};
|
||||
|
||||
static void *smp_write_config_table(void *v)
|
||||
{
|
||||
struct mp_config_table *mc;
|
||||
int bus_isa;
|
||||
|
||||
/* Intialize the MP_Table */
|
||||
mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
|
||||
|
||||
mptable_init(mc, LOCAL_APIC_ADDR);
|
||||
memcpy(mc->mpc_oem, "AMD ", 8);
|
||||
|
||||
/*
|
||||
* Type 0: Processor Entries:
|
||||
* LAPIC ID, LAPIC Version, CPU Flags:EN/BP,
|
||||
* CPU Signature (Stepping, Model, Family),
|
||||
* Feature Flags
|
||||
*/
|
||||
smp_write_processors(mc);
|
||||
|
||||
/* Get Bus Configuration */
|
||||
get_bus_conf();
|
||||
|
||||
/*
|
||||
* Type 1: Bus Entries:
|
||||
* Bus ID, Bus Type
|
||||
*/
|
||||
mptable_write_buses(mc, NULL, &bus_isa);
|
||||
|
||||
/* I/O APICs: APIC ID Version State Address */
|
||||
|
||||
u32 dword;
|
||||
u8 byte;
|
||||
|
||||
ReadPMIO(SB_PMIOA_REG34, AccWidthUint32, &dword);
|
||||
dword &= 0xFFFFFFF0;
|
||||
smp_write_ioapic(mc, apicid_sb800, 0x21, dword);
|
||||
|
||||
for (byte = 0x0; byte < sizeof(intr_data); byte ++) {
|
||||
outb(byte | 0x80, 0xC00);
|
||||
outb(intr_data[byte], 0xC01);
|
||||
}
|
||||
|
||||
/* I/O Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */
|
||||
#define IO_LOCAL_INT(type, intr, apicid, pin) \
|
||||
smp_write_lintsrc(mc, (type), MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, bus_isa, (intr), (apicid), (pin));
|
||||
/*
|
||||
* Type 2: I/O APICs:
|
||||
* APIC ID, Version, APIC Flags:EN, Address
|
||||
*/
|
||||
smp_write_ioapic(mc, apicid_sb800, apicver_sb800, IO_APIC_ADDR);
|
||||
|
||||
/*
|
||||
* Type 3: I/O Interrupt Table Entries:
|
||||
* Int Type, Int Polarity, Int Level, Source Bus ID,
|
||||
* Source Bus IRQ, Dest APIC ID, Dest PIN#
|
||||
*/
|
||||
mptable_add_isa_interrupts(mc, bus_isa, apicid_sb800, 0);
|
||||
|
||||
/* PCI interrupts are level triggered, and are
|
||||
* associated with a specific bus/device/function tuple.
|
||||
*/
|
||||
#if !CONFIG_GENERATE_ACPI_TABLES
|
||||
#define PCI_INT(bus, dev, fn, pin) \
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, (bus), (((dev)<<2)|(fn)), apicid_sb800, (pin))
|
||||
#else
|
||||
#define PCI_INT(bus, dev, fn, pin)
|
||||
#endif
|
||||
|
||||
/* APU Internal Graphic Device*/
|
||||
PCI_INT(0x0, 0x01, 0x0, intr_data[0x02]);
|
||||
PCI_INT(0x0, 0x01, 0x1, intr_data[0x03]);
|
||||
/* APU Internal Graphic Device */
|
||||
PCI_INT(0x0, 0x01, 0x0, intr_data_ptr[PIRQ_C]);
|
||||
PCI_INT(0x0, 0x01, 0x1, intr_data_ptr[PIRQ_D]);
|
||||
|
||||
//PCI_INT(0x0, 0x14, 0x1, 0x11); /* IDE. */
|
||||
PCI_INT(0x0, 0x14, 0x0, 0x10);
|
||||
/* Southbridge HD Audio: */
|
||||
PCI_INT(0x0, 0x14, 0x2, 0x12);
|
||||
/* SMBUS / ACPI */
|
||||
PCI_INT(0x0, 0x14, 0x0, intr_data_ptr[PIRQ_SMBUS]);
|
||||
|
||||
PCI_INT(0x0, 0x12, 0x0, intr_data[0x30]); /* USB */
|
||||
PCI_INT(0x0, 0x12, 0x1, intr_data[0x31]);
|
||||
PCI_INT(0x0, 0x13, 0x0, intr_data[0x32]);
|
||||
PCI_INT(0x0, 0x13, 0x1, intr_data[0x33]);
|
||||
PCI_INT(0x0, 0x16, 0x0, intr_data[0x34]);
|
||||
PCI_INT(0x0, 0x16, 0x1, intr_data[0x35]);
|
||||
/* Southbridge HD Audio */
|
||||
PCI_INT(0x0, 0x14, 0x2, intr_data_ptr[PIRQ_HDA]);
|
||||
|
||||
/* sata */
|
||||
PCI_INT(0x0, 0x11, 0x0, intr_data[0x41]);
|
||||
/* LPC */
|
||||
PCI_INT(0x0, 0x14, 0x3, intr_data_ptr[PIRQ_C]);
|
||||
|
||||
/* on board NIC & Slot PCIE. */
|
||||
/* USB */
|
||||
PCI_INT(0x0, 0x12, 0x0, intr_data_ptr[PIRQ_OHCI1]);
|
||||
PCI_INT(0x0, 0x12, 0x2, intr_data_ptr[PIRQ_EHCI1]);
|
||||
PCI_INT(0x0, 0x13, 0x0, intr_data_ptr[PIRQ_OHCI2]);
|
||||
PCI_INT(0x0, 0x13, 0x2, intr_data_ptr[PIRQ_EHCI2]);
|
||||
PCI_INT(0x0, 0x14, 0x5, intr_data_ptr[PIRQ_OHCI4]);
|
||||
|
||||
/* IDE */
|
||||
PCI_INT(0x0, 0x14, 0x1, intr_data_ptr[PIRQ_IDE]);
|
||||
|
||||
/* SATA */
|
||||
PCI_INT(0x0, 0x11, 0x0, intr_data_ptr[PIRQ_SATA]);
|
||||
|
||||
/* on board NIC & Slot PCIE */
|
||||
PCI_INT(0x1, 0x0, 0x0, intr_data_ptr[PIRQ_E]); /* Use INTE */
|
||||
PCI_INT(0x2, 0x0, 0x0, intr_data_ptr[PIRQ_E]); /* Use INTE */
|
||||
|
||||
/* PCI slots */
|
||||
/* PCI_SLOT 0. */
|
||||
PCI_INT(bus_sb800[1], 0x5, 0x0, 0x14);
|
||||
PCI_INT(bus_sb800[1], 0x5, 0x1, 0x15);
|
||||
PCI_INT(bus_sb800[1], 0x5, 0x2, 0x16);
|
||||
PCI_INT(bus_sb800[1], 0x5, 0x3, 0x17);
|
||||
|
||||
/* PCI_SLOT 1. */
|
||||
PCI_INT(bus_sb800[1], 0x6, 0x0, 0x15);
|
||||
PCI_INT(bus_sb800[1], 0x6, 0x1, 0x16);
|
||||
PCI_INT(bus_sb800[1], 0x6, 0x2, 0x17);
|
||||
PCI_INT(bus_sb800[1], 0x6, 0x3, 0x14);
|
||||
|
||||
/* PCI_SLOT 2. */
|
||||
PCI_INT(bus_sb800[1], 0x7, 0x0, 0x16);
|
||||
PCI_INT(bus_sb800[1], 0x7, 0x1, 0x17);
|
||||
PCI_INT(bus_sb800[1], 0x7, 0x2, 0x14);
|
||||
PCI_INT(bus_sb800[1], 0x7, 0x3, 0x15);
|
||||
|
||||
PCI_INT(bus_sb800[2], 0x0, 0x0, 0x12);
|
||||
PCI_INT(bus_sb800[2], 0x0, 0x1, 0x13);
|
||||
PCI_INT(bus_sb800[2], 0x0, 0x2, 0x14);
|
||||
/* PCI_SLOT 0 */
|
||||
PCI_INT(bus_sb800[1], 0x5, 0x0, intr_data_ptr[PIRQ_E]); /* INTA -> INTE */
|
||||
PCI_INT(bus_sb800[1], 0x5, 0x1, intr_data_ptr[PIRQ_F]); /* INTB -> INTF */
|
||||
PCI_INT(bus_sb800[1], 0x5, 0x2, intr_data_ptr[PIRQ_G]); /* INTC -> INTG */
|
||||
PCI_INT(bus_sb800[1], 0x5, 0x3, intr_data_ptr[PIRQ_H]); /* INTD -> INTH */
|
||||
|
||||
/* PCIe PortA */
|
||||
PCI_INT(0x0, 0x15, 0x0, 0x10);
|
||||
PCI_INT(0x0, 0x15, 0x0, intr_data_ptr[PIRQ_E]); /* INTA -> INTE */
|
||||
/* PCIe PortB */
|
||||
PCI_INT(0x0, 0x15, 0x1, 0x11);
|
||||
PCI_INT(0x0, 0x15, 0x1, intr_data_ptr[PIRQ_F]); /* INTB -> INTF */
|
||||
/* PCIe PortC */
|
||||
PCI_INT(0x0, 0x15, 0x2, 0x12);
|
||||
PCI_INT(0x0, 0x15, 0x2, intr_data_ptr[PIRQ_G]); /* INTC -> INTG */
|
||||
/* PCIe PortD */
|
||||
PCI_INT(0x0, 0x15, 0x3, 0x13);
|
||||
PCI_INT(0x0, 0x15, 0x3, intr_data_ptr[PIRQ_H]); /* INTD -> INTH */
|
||||
|
||||
/*Local Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */
|
||||
#define IO_LOCAL_INT(type, intr, apicid, pin) \
|
||||
smp_write_lintsrc(mc, (type), MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, bus_isa, (intr), (apicid), (pin));
|
||||
|
||||
IO_LOCAL_INT(mp_ExtINT, 0x0, MP_APIC_ALL, 0x0);
|
||||
IO_LOCAL_INT(mp_NMI, 0x0, MP_APIC_ALL, 0x1);
|
||||
/* There is no extension information... */
|
||||
|
@ -155,6 +145,6 @@ static void *smp_write_config_table(void *v)
|
|||
unsigned long write_smp_table(unsigned long addr)
|
||||
{
|
||||
void *v;
|
||||
v = smp_write_floating_table(addr, 0);
|
||||
v = smp_write_floating_table(addr, 0); /* ADDR, Enable Virtual Wire */
|
||||
return (unsigned long)smp_write_config_table(v);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue