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:
Mike Loptien 2014-06-06 15:21:28 -06:00
parent d0167d3ae2
commit cbc783f3e1
2 changed files with 75 additions and 76 deletions

View File

@ -25,6 +25,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <cpu/amd/amdfam14.h> #include <cpu/amd/amdfam14.h>
#include "agesawrapper.h" #include "agesawrapper.h"
#include <arch/ioapic.h>
#if CONFIG_AMD_SB_CIMX #if CONFIG_AMD_SB_CIMX
#include <sb_cimx.h> #include <sb_cimx.h>
#endif #endif
@ -36,6 +37,7 @@
u8 bus_isa; u8 bus_isa;
u8 bus_sb800[6]; u8 bus_sb800[6];
u32 apicid_sb800; u32 apicid_sb800;
u32 apicver_sb800;
/* /*
* Here you only need to set value in pci1234 for HT-IO that could be installed or not * 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 */ /* I/O APICs: APIC ID Version State Address */
bus_isa = 10; bus_isa = 10;
apicid_base = CONFIG_MAX_CPUS; 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 #if CONFIG_AMD_SB_CIMX
sb_Late_Post(); sb_Late_Post();

View File

@ -2,6 +2,7 @@
* This file is part of the coreboot project. * This file is part of the coreboot project.
* *
* Copyright (C) 2011 Advanced Micro Devices, Inc. * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -26,124 +27,113 @@
#include <stdint.h> #include <stdint.h>
#include <cpu/amd/amdfam14.h> #include <cpu/amd/amdfam14.h>
#include <SBPLATFORM.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 u8 bus_sb800[6];
extern u32 apicid_sb800; extern u32 apicid_sb800;
extern u32 apicver_sb800;
extern u32 bus_type[256]; extern u32 bus_type[256];
extern u32 sbdn_sb800; 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) static void *smp_write_config_table(void *v)
{ {
struct mp_config_table *mc; struct mp_config_table *mc;
int bus_isa; int bus_isa;
/* Intialize the MP_Table */
mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN); mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
mptable_init(mc, LOCAL_APIC_ADDR); 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); smp_write_processors(mc);
/* Get Bus Configuration */
get_bus_conf(); get_bus_conf();
/*
* Type 1: Bus Entries:
* Bus ID, Bus Type
*/
mptable_write_buses(mc, NULL, &bus_isa); mptable_write_buses(mc, NULL, &bus_isa);
/* I/O APICs: APIC ID Version State Address */ /*
* Type 2: I/O APICs:
u32 dword; * APIC ID, Version, APIC Flags:EN, Address
u8 byte; */
smp_write_ioapic(mc, apicid_sb800, apicver_sb800, IO_APIC_ADDR);
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 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); mptable_add_isa_interrupts(mc, bus_isa, apicid_sb800, 0);
/* PCI interrupts are level triggered, and are /* PCI interrupts are level triggered, and are
* associated with a specific bus/device/function tuple. * associated with a specific bus/device/function tuple.
*/ */
#if !CONFIG_GENERATE_ACPI_TABLES
#define PCI_INT(bus, dev, fn, pin) \ #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)) 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*/ /* APU Internal Graphic Device */
PCI_INT(0x0, 0x01, 0x0, intr_data[0x02]); PCI_INT(0x0, 0x01, 0x0, intr_data_ptr[PIRQ_C]);
PCI_INT(0x0, 0x01, 0x1, intr_data[0x03]); PCI_INT(0x0, 0x01, 0x1, intr_data_ptr[PIRQ_D]);
//PCI_INT(0x0, 0x14, 0x1, 0x11); /* IDE. */ /* SMBUS / ACPI */
PCI_INT(0x0, 0x14, 0x0, 0x10); PCI_INT(0x0, 0x14, 0x0, intr_data_ptr[PIRQ_SMBUS]);
/* Southbridge HD Audio: */
PCI_INT(0x0, 0x14, 0x2, 0x12);
PCI_INT(0x0, 0x12, 0x0, intr_data[0x30]); /* USB */ /* Southbridge HD Audio */
PCI_INT(0x0, 0x12, 0x1, intr_data[0x31]); PCI_INT(0x0, 0x14, 0x2, intr_data_ptr[PIRQ_HDA]);
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]);
/* sata */ /* LPC */
PCI_INT(0x0, 0x11, 0x0, intr_data[0x41]); 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 slots */
/* PCI_SLOT 0. */ /* PCI_SLOT 0 */
PCI_INT(bus_sb800[1], 0x5, 0x0, 0x14); PCI_INT(bus_sb800[1], 0x5, 0x0, intr_data_ptr[PIRQ_E]); /* INTA -> INTE */
PCI_INT(bus_sb800[1], 0x5, 0x1, 0x15); PCI_INT(bus_sb800[1], 0x5, 0x1, intr_data_ptr[PIRQ_F]); /* INTB -> INTF */
PCI_INT(bus_sb800[1], 0x5, 0x2, 0x16); PCI_INT(bus_sb800[1], 0x5, 0x2, intr_data_ptr[PIRQ_G]); /* INTC -> INTG */
PCI_INT(bus_sb800[1], 0x5, 0x3, 0x17); PCI_INT(bus_sb800[1], 0x5, 0x3, intr_data_ptr[PIRQ_H]); /* INTD -> INTH */
/* 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);
/* PCIe PortA */ /* PCIe PortA */
PCI_INT(0x0, 0x15, 0x0, 0x10); PCI_INT(0x0, 0x15, 0x0, intr_data_ptr[PIRQ_E]); /* INTA -> INTE */
/* PCIe PortB */ /* PCIe PortB */
PCI_INT(0x0, 0x15, 0x1, 0x11); PCI_INT(0x0, 0x15, 0x1, intr_data_ptr[PIRQ_F]); /* INTB -> INTF */
/* PCIe PortC */ /* PCIe PortC */
PCI_INT(0x0, 0x15, 0x2, 0x12); PCI_INT(0x0, 0x15, 0x2, intr_data_ptr[PIRQ_G]); /* INTC -> INTG */
/* PCIe PortD */ /* 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# */ /*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_ExtINT, 0x0, MP_APIC_ALL, 0x0);
IO_LOCAL_INT(mp_NMI, 0x0, MP_APIC_ALL, 0x1); IO_LOCAL_INT(mp_NMI, 0x0, MP_APIC_ALL, 0x1);
/* There is no extension information... */ /* 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) unsigned long write_smp_table(unsigned long addr)
{ {
void *v; 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); return (unsigned long)smp_write_config_table(v);
} }