summaryrefslogtreecommitdiff
path: root/src/southbridge/amd/sr5650
diff options
context:
space:
mode:
Diffstat (limited to 'src/southbridge/amd/sr5650')
-rw-r--r--src/southbridge/amd/sr5650/Kconfig9
-rw-r--r--src/southbridge/amd/sr5650/ht.c89
-rw-r--r--src/southbridge/amd/sr5650/sr5650.c31
-rw-r--r--src/southbridge/amd/sr5650/sr5650.h1
4 files changed, 130 insertions, 0 deletions
diff --git a/src/southbridge/amd/sr5650/Kconfig b/src/southbridge/amd/sr5650/Kconfig
index 29017c612e..85f6b13013 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 y
+ 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 b45099f59c..b79efc28be 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,6 +156,11 @@ static void pcie_init(struct device *dev)
static void sr5690_read_resource(struct device *dev)
{
+ 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) */
@@ -167,6 +174,88 @@ static void sr5690_read_resource(struct device *dev)
static void sr5690_set_resources(struct device *dev)
{
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__);
+
+ /* 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 {
+ res = sr5650_retrieve_cpu_mmio_resource();
+ if (res) {
+ /* 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));
+ }
+ } else {
+ printk(BIOS_WARNING, "%s: %s Unable to locate CPU MMCONF resource\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 07b4a023ec..d4355d6861 100644
--- a/src/southbridge/amd/sr5650/sr5650.c
+++ b/src/southbridge/amd/sr5650/sr5650.c
@@ -34,6 +34,21 @@
extern void set_pcie_dereset(void);
extern void set_pcie_reset(void);
+struct resource * sr5650_retrieve_cpu_mmio_resource() {
+ device_t cpu;
+ struct resource *res;
+
+ for (cpu = all_devices; cpu; cpu = cpu->next) {
+ if (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)
+ continue;
+ res = probe_resource(cpu->bus->dev, 0xc0010058);
+ if (res)
+ return res;
+ }
+
+ return NULL;
+}
+
/* extension registers */
u32 pci_ext_read_config32(device_t nb_dev, device_t dev, u32 reg)
{
@@ -796,6 +811,22 @@ 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)) {
+ res = sr5650_retrieve_cpu_mmio_resource();
+ 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;
diff --git a/src/southbridge/amd/sr5650/sr5650.h b/src/southbridge/amd/sr5650/sr5650.h
index bad3529997..c6db26da5a 100644
--- a/src/southbridge/amd/sr5650/sr5650.h
+++ b/src/southbridge/amd/sr5650/sr5650.h
@@ -131,4 +131,5 @@ void sr5650_iommu_enable_resources(device_t dev);
void sr5650_nb_pci_table(device_t nb_dev);
void init_gen2(device_t nb_dev, device_t dev, u8 port);
void sr56x0_lock_hwinitreg(void);
+struct resource * sr5650_retrieve_cpu_mmio_resource(void);
#endif /* SR5650_H */