Timothy Pearson (tpearson@raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12050
-gerrit
commit 8c81ba65420ac8ce3069345a7c5071621224e0a2 Author: Timothy Pearson tpearson@raptorengineeringinc.com Date: Fri Aug 14 15:20:42 2015 -0500
southbridge/amd/sr5650: Add MCFG ACPI table support
Change-Id: I0c4ba74ddcc727cd92b848d5d3240e6f9f392101 Signed-off-by: Timothy Pearson tpearson@raptorengineeringinc.com --- src/northbridge/amd/amdfam10/northbridge.c | 22 +++--- src/southbridge/amd/rs780/rs780.c | 12 ++++ src/southbridge/amd/sb700/lpc.c | 6 -- src/southbridge/amd/sb800/lpc.c | 7 +- src/southbridge/amd/sr5650/Kconfig | 9 +++ src/southbridge/amd/sr5650/ht.c | 107 ++++++++++++++++++++++++++++- src/southbridge/amd/sr5650/sr5650.c | 18 +++++ 7 files changed, 156 insertions(+), 25 deletions(-)
diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c index c8bf8fa..b376171 100644 --- a/src/northbridge/amd/amdfam10/northbridge.c +++ b/src/northbridge/amd/amdfam10/northbridge.c @@ -737,16 +737,18 @@ static void amdfam10_domain_read_resources(device_t dev)
pci_domain_read_resources(dev);
-#if CONFIG_MMCONF_SUPPORT - struct resource *res = new_resource(dev, 0xc0010058); - res->base = CONFIG_MMCONF_BASE_ADDRESS; - res->size = CONFIG_MMCONF_BUS_NUMBER * 4096*256; - res->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | - IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; - - /* Reserve lower DRAM region to force PCI MMIO region to correct location above 0xefffffff */ - ram_resource(dev, 7, 0, rdmsr(TOP_MEM).lo >> 10); -#endif + if (IS_ENABLED(CONFIG_MMCONF_SUPPORT) && !IS_ENABLED(CONFIG_EXT_CONF_SUPPORT)) { + struct resource *res = new_resource(dev, 0xc0010058); + res->base = CONFIG_MMCONF_BASE_ADDRESS; + res->size = CONFIG_MMCONF_BUS_NUMBER * 4096*256; + res->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | + IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; + } + + if (IS_ENABLED(CONFIG_MMCONF_SUPPORT)) { + /* Reserve lower DRAM region to force PCI MMIO region to correct location above 0xefffffff */ + ram_resource(dev, 7, 0, rdmsr(TOP_MEM).lo >> 10); + }
if (is_fam15h()) { enable_cc6 = 0; diff --git a/src/southbridge/amd/rs780/rs780.c b/src/southbridge/amd/rs780/rs780.c index c82a629..6eb4295 100644 --- a/src/southbridge/amd/rs780/rs780.c +++ b/src/southbridge/amd/rs780/rs780.c @@ -15,6 +15,7 @@
#include <console/console.h> #include <arch/io.h> +#include <arch/acpi.h> #include <device/device.h> #include <device/pci.h> #include <device/pci_ids.h> @@ -349,6 +350,17 @@ void rs780_enable(device_t dev) } }
+#if !IS_ENABLED(CONFIG_AMD_SB_CIMX) +unsigned long acpi_fill_mcfg(unsigned long current) +{ + /* FIXME + * Leave table blank until proper contents + * are determined. + */ + return current; +} +#endif + struct chip_operations southbridge_amd_rs780_ops = { CHIP_NAME("ATI RS780") .enable_dev = rs780_enable, diff --git a/src/southbridge/amd/sb700/lpc.c b/src/southbridge/amd/sb700/lpc.c index a71fe1f..78933fa 100644 --- a/src/southbridge/amd/sb700/lpc.c +++ b/src/southbridge/amd/sb700/lpc.c @@ -30,12 +30,6 @@ #include <cpu/amd/powernow.h> #include "sb700.h"
-unsigned long acpi_fill_mcfg(unsigned long current) -{ - /* Just a dummy */ - return current; -} - static void lpc_init(device_t dev) { u8 byte; diff --git a/src/southbridge/amd/sb800/lpc.c b/src/southbridge/amd/sb800/lpc.c index 756a0c4..18d4471 100644 --- a/src/southbridge/amd/sb800/lpc.c +++ b/src/southbridge/amd/sb800/lpc.c @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2010 Advanced Micro Devices, Inc. + * Copyright (C) 2015 Timothy Pearson tpearson@raptorengineeringinc.com, Raptor Engineering * * 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 @@ -25,12 +26,6 @@ #include <arch/acpi.h> #include "sb800.h"
-unsigned long acpi_fill_mcfg(unsigned long current) -{ - /* Just a dummy */ - return current; -} - static void lpc_init(device_t dev) { u8 byte; diff --git a/src/southbridge/amd/sr5650/Kconfig b/src/southbridge/amd/sr5650/Kconfig index 29017c6..f2d12ff 100644 --- a/src/southbridge/amd/sr5650/Kconfig +++ b/src/southbridge/amd/sr5650/Kconfig @@ -15,3 +15,12 @@
config SOUTHBRIDGE_AMD_SR5650 bool + +if SOUTHBRIDGE_AMD_SR5650 +config EXT_CONF_SUPPORT + bool "Enable PCI-E MMCONFIG support" + default n + help + Select to enable PCI-E MMCONFIG support on the SR5650. + +endif diff --git a/src/southbridge/amd/sr5650/ht.c b/src/southbridge/amd/sr5650/ht.c index 6119985..e74d36b 100644 --- a/src/southbridge/amd/sr5650/ht.c +++ b/src/southbridge/amd/sr5650/ht.c @@ -20,7 +20,9 @@ #include <device/pci_ids.h> #include <device/pci_ops.h> #include <arch/ioapic.h> +#include <lib.h> #include "sr5650.h" +#include "cmn.h"
/* Table 6-6 Recommended Interrupt Routing Configuration */ typedef struct _apic_device_info { @@ -154,11 +156,29 @@ static void pcie_init(struct device *dev)
static void sr5690_read_resource(struct device *dev) { + struct resource *res; + + if (IS_ENABLED(CONFIG_EXT_CONF_SUPPORT)) { + printk(BIOS_DEBUG,"%s: %s\n", __func__, dev_path(dev)); + set_nbmisc_enable_bits(dev, 0x0, 1 << 3, 1 << 3); /* Hide BAR3 */ + } + pci_dev_read_resources(dev);
/* rpr6.2.(1). Write the Base Address Register (BAR) */ - pci_write_config32(dev, 0xF8, 0x1); /* set IOAPIC's index as 1 and make sure no one changes it. */ - pci_get_resource(dev, 0xFC); /* APIC located in sr5690 */ + pci_write_config32(dev, 0xf8, 0x1); /* Set IOAPIC's index to 1 and make sure no one changes it */ + pci_get_resource(dev, 0xfc); /* APIC located in sr5690 */ + + if (IS_ENABLED(CONFIG_EXT_CONF_SUPPORT)) { + res = new_resource(dev, 0x1c); /* PCIe MCFG space */ + res->base = EXT_CONF_BASE_ADDRESS; + res->size = CONFIG_MMCONF_BUS_NUMBER * 1024 * 1024; /* Each bus needs 1M */ + res->align = log2(res->size); + res->gran = log2(res->size); + res->limit = 0xffffffffffffffffULL; /* 64-bit location allowed */ + res->flags = IORESOURCE_FIXED | IORESOURCE_MEM | IORESOURCE_PCI64 + | IORESOURCE_ASSIGNED | IORESOURCE_RESERVE | IORESOURCE_BRIDGE; + }
compact_resources(dev); } @@ -166,7 +186,88 @@ static void sr5690_read_resource(struct device *dev) /* If IOAPIC's index changes, we should replace the pci_dev_set_resource(). */ static void sr5690_set_resources(struct device *dev) { - pci_write_config32(dev, 0xF8, 0x1); /* set IOAPIC's index as 1 and make sure no one changes it. */ + pci_write_config32(dev, 0xf8, 0x1); /* Set IOAPIC's index to 1 and make sure no one changes it */ + + if (IS_ENABLED(CONFIG_EXT_CONF_SUPPORT)) { + uint32_t reg; + device_t amd_ht_cfg_dev; + device_t amd_addr_map_dev; + resource_t res_base; + resource_t res_end; + uint32_t base; + uint32_t limit; + struct resource *res; + + printk(BIOS_DEBUG,"%s %s\n", dev_path(dev), __func__); + + res = probe_resource(dev, 0x1c); + if (res) { + /* Find requisite AMD CPU devices */ + amd_ht_cfg_dev = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + amd_addr_map_dev = dev_find_slot(0, PCI_DEVFN(0x18, 1)); + + if (!amd_ht_cfg_dev || !amd_addr_map_dev) { + printk(BIOS_WARNING, "%s: %s Unable to locate CPU control devices\n", __func__, dev_path(dev)); + } + else { + /* Set up MMCONFIG bus range */ + set_nbmisc_enable_bits(dev, 0x0, 1 << 3, 0 << 3); /* Make BAR3 visible */ + set_nbcfg_enable_bits(dev, 0x7c, 1 << 30, 1 << 30); /* Enables writes to the BAR3 register */ + set_nbcfg_enable_bits(dev, 0x84, 7 << 16, 0 << 16); /* Program bus range = 255 busses */ + pci_write_config32(dev, 0x1c, res->base); + + /* Enable MMCONFIG decoding. */ + set_htiu_enable_bits(dev, 0x32, 1 << 28, 1 << 28); /* PCIEMiscInit */ + set_nbcfg_enable_bits(dev, 0x7c, 1 << 30, 0 << 30); /* Disable writes to the BAR3 register */ + set_nbmisc_enable_bits(dev, 0x0, 1 << 3, 1 << 3); /* Hide BAR3 */ + + /* Set up nonposted resource in MMIO space */ + res_base = res->base; /* Get the base address */ + res_end = resource_end(res); /* Get the limit (rounded up) */ + printk(BIOS_DEBUG, "%s: %s[0x1c] base = %0llx limit = %0llx\n", __func__, dev_path(dev), res_base, res_end); + + /* Locate an unused MMIO resource */ + for (reg = 0xb8; reg >= 0x80; reg -= 8) { + base = pci_read_config32(amd_addr_map_dev, reg); + limit = pci_read_config32(amd_addr_map_dev, reg + 4); + if (!(base & 0x3)) + break; /* Unused resource found */ + } + + /* If an unused MMIO resource was available, set up the mapping */ + if (!(base & 0x3)) { + uint32_t sblk; + + /* Remember this resource has been stored. */ + res->flags |= IORESOURCE_STORED; + report_resource_stored(dev, res, " <mmconfig>"); + + /* Get SBLink value (HyperTransport I/O Hub Link ID). */ + sblk = (pci_read_config32(amd_ht_cfg_dev, 0x64) >> 8) & 0x3; + + /* Calculate the MMIO mapping base */ + base &= 0x000000f0; + base |= ((res_base >> 8) & 0xffffff00); + base |= 3; + + /* Calculate the MMIO mapping limit */ + limit &= 0x00000048; + limit |= ((res_end >> 8) & 0xffffff00); + limit |= (sblk << 4); + limit |= (1 << 7); + + /* Configure and enable MMIO mapping */ + printk(BIOS_INFO, "%s: %s <- index %x base %04x limit %04x\n", __func__, dev_path(amd_addr_map_dev), reg, base, limit); + pci_write_config32(amd_addr_map_dev, reg + 4, limit); + pci_write_config32(amd_addr_map_dev, reg, base); + } + else { + printk(BIOS_WARNING, "%s: %s No free MMIO resources available\n", __func__, dev_path(dev)); + } + } + } + } + pci_dev_set_resources(dev); }
diff --git a/src/southbridge/amd/sr5650/sr5650.c b/src/southbridge/amd/sr5650/sr5650.c index 07b4a02..54f0071 100644 --- a/src/southbridge/amd/sr5650/sr5650.c +++ b/src/southbridge/amd/sr5650/sr5650.c @@ -796,6 +796,24 @@ static void add_ivrs_device_entries(struct device *parent, struct device *dev, i free(root_level); }
+unsigned long acpi_fill_mcfg(unsigned long current) +{ + struct resource *res; + resource_t mmconf_base = EXT_CONF_BASE_ADDRESS; + + if (IS_ENABLED(CONFIG_EXT_CONF_SUPPORT)) { + device_t dev = dev_find_slot(0, PCI_DEVFN(0, 0)); + /* Report MMCONF base */ + res = probe_resource(dev, 0x1c); + if (res) + mmconf_base = res->base; + + current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current, mmconf_base, 0x0, 0x0, 0x1f); + } + + return current; +} + static unsigned long acpi_fill_ivrs(acpi_ivrs_t* ivrs, unsigned long current) { uint8_t *p;