diff options
Diffstat (limited to 'resources/libreboot/patch/kgpe-d16/0113-southbridge-amd-sr5650-Add-IOMMU-support.patch')
-rw-r--r-- | resources/libreboot/patch/kgpe-d16/0113-southbridge-amd-sr5650-Add-IOMMU-support.patch | 804 |
1 files changed, 0 insertions, 804 deletions
diff --git a/resources/libreboot/patch/kgpe-d16/0113-southbridge-amd-sr5650-Add-IOMMU-support.patch b/resources/libreboot/patch/kgpe-d16/0113-southbridge-amd-sr5650-Add-IOMMU-support.patch deleted file mode 100644 index 959e57fe..00000000 --- a/resources/libreboot/patch/kgpe-d16/0113-southbridge-amd-sr5650-Add-IOMMU-support.patch +++ /dev/null @@ -1,804 +0,0 @@ -From f44168ba86f534ca12566ba7d38ff5f99c6c7e9c Mon Sep 17 00:00:00 2001 -From: Timothy Pearson <tpearson@raptorengineeringinc.com> -Date: Tue, 11 Aug 2015 17:49:06 -0500 -Subject: [PATCH 113/143] southbridge/amd/sr5650: Add IOMMU support - -Change-Id: I2083d0c5653515c27d4626c62a6499b850f7547b -Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com> ---- - src/include/device/pci_ids.h | 1 + - src/mainboard/asus/kgpe-d16/acpi_tables.c | 37 ++ - src/mainboard/supermicro/h8scm_fam10/acpi_tables.c | 37 ++ - src/southbridge/amd/sr5650/cmn.h | 3 + - src/southbridge/amd/sr5650/early_setup.c | 50 +- - src/southbridge/amd/sr5650/sr5650.c | 479 +++++++++++++++++++- - src/southbridge/amd/sr5650/sr5650.h | 14 + - 7 files changed, 611 insertions(+), 10 deletions(-) - -diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h -index 664ac49..72f1ece 100644 ---- a/src/include/device/pci_ids.h -+++ b/src/include/device/pci_ids.h -@@ -429,6 +429,7 @@ - #define PCI_DEVICE_ID_AMD_SR5650_PCIE_DEV12 0x5A20 - #define PCI_DEVICE_ID_AMD_SR5650_PCIE_DEV13 0x5A1E - #define PCI_DEVICE_ID_AMD_SR5650_PCIE_DEV8 0x5A21 -+#define PCI_DEVICE_ID_AMD_SR5650_IOMMU 0x5A23 - - #define PCI_DEVICE_ID_AMD_CZ_HDA 0x157A - #define PCI_DEVICE_ID_AMD_CZ_LPC 0x790E -diff --git a/src/mainboard/asus/kgpe-d16/acpi_tables.c b/src/mainboard/asus/kgpe-d16/acpi_tables.c -index 4e98dfe..3f8650b 100644 ---- a/src/mainboard/asus/kgpe-d16/acpi_tables.c -+++ b/src/mainboard/asus/kgpe-d16/acpi_tables.c -@@ -73,3 +73,40 @@ unsigned long acpi_fill_madt(unsigned long current) - - return current; - } -+ -+unsigned long acpi_fill_ivrs_ioapic(acpi_ivrs_t* ivrs, unsigned long current) -+{ -+ uint8_t *p; -+ -+ uint32_t apicid_sp5100; -+ uint32_t apicid_sr5650; -+ -+ apicid_sp5100 = 0x20; -+ apicid_sr5650 = apicid_sp5100 + 1; -+ -+ /* Describe NB IOAPIC */ -+ p = (uint8_t *)current; -+ p[0] = 0x48; /* Entry type */ -+ p[1] = 0; /* Device */ -+ p[2] = 0; /* Bus */ -+ p[3] = 0x0; /* Data */ -+ p[4] = apicid_sr5650; /* IOAPIC ID */ -+ p[5] = 0x1; /* Device 0 Function 1 */ -+ p[6] = 0x0; /* Northbridge bus */ -+ p[7] = 0x1; /* Variety */ -+ current += 8; -+ -+ /* Describe SB IOAPIC */ -+ p = (uint8_t *)current; -+ p[0] = 0x48; /* Entry type */ -+ p[1] = 0; /* Device */ -+ p[2] = 0; /* Bus */ -+ p[3] = 0xd7; /* Data */ -+ p[4] = apicid_sp5100; /* IOAPIC ID */ -+ p[5] = 0x14 << 3; /* Device 0x14 Function 0 */ -+ p[6] = 0x0; /* Southbridge bus */ -+ p[7] = 0x1; /* Variety */ -+ current += 8; -+ -+ return current; -+} -\ No newline at end of file -diff --git a/src/mainboard/supermicro/h8scm_fam10/acpi_tables.c b/src/mainboard/supermicro/h8scm_fam10/acpi_tables.c -index 61d16d7..14bd9ed 100644 ---- a/src/mainboard/supermicro/h8scm_fam10/acpi_tables.c -+++ b/src/mainboard/supermicro/h8scm_fam10/acpi_tables.c -@@ -66,3 +66,40 @@ unsigned long acpi_fill_madt(unsigned long current) - - return current; - } -+ -+unsigned long acpi_fill_ivrs_ioapic(acpi_ivrs_t* ivrs, unsigned long current) -+{ -+ uint8_t *p; -+ -+ uint32_t apicid_sp5100; -+ uint32_t apicid_sr5650; -+ -+ apicid_sp5100 = 0x20; -+ apicid_sr5650 = apicid_sp5100 + 1; -+ -+ /* Describe NB IOAPIC */ -+ p = (uint8_t *)current; -+ p[0] = 0x48; /* Entry type */ -+ p[1] = 0; /* Device */ -+ p[2] = 0; /* Bus */ -+ p[3] = 0x0; /* Data */ -+ p[4] = apicid_sr5650; /* IOAPIC ID */ -+ p[5] = 0x1; /* Device 0 Function 1 */ -+ p[6] = 0x0; /* Northbridge bus */ -+ p[7] = 0x1; /* Variety */ -+ current += 8; -+ -+ /* Describe SB IOAPIC */ -+ p = (uint8_t *)current; -+ p[0] = 0x48; /* Entry type */ -+ p[1] = 0; /* Device */ -+ p[2] = 0; /* Bus */ -+ p[3] = 0xd7; /* Data */ -+ p[4] = apicid_sp5100; /* IOAPIC ID */ -+ p[5] = 0x14 << 3; /* Device 0x14 Function 0 */ -+ p[6] = 0x0; /* Southbridge bus */ -+ p[7] = 0x1; /* Variety */ -+ current += 8; -+ -+ return current; -+} -diff --git a/src/southbridge/amd/sr5650/cmn.h b/src/southbridge/amd/sr5650/cmn.h -index 23d25d5..a54bdc5 100644 ---- a/src/southbridge/amd/sr5650/cmn.h -+++ b/src/southbridge/amd/sr5650/cmn.h -@@ -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 -@@ -26,6 +27,8 @@ - #define NBHTIU_INDEX 0x94 /* Note: It is different with RS690, whose HTIU index is 0xA8 */ - #define NBMC_INDEX 0xE8 - #define NBPCIE_INDEX 0xE0 -+#define L2CFG_INDEX 0xF0 -+#define L1CFG_INDEX 0xF8 - #define EXT_CONF_BASE_ADDRESS CONFIG_MMCONF_BASE_ADDRESS - #define TEMP_MMIO_BASE_ADDRESS 0xC0000000 - -diff --git a/src/southbridge/amd/sr5650/early_setup.c b/src/southbridge/amd/sr5650/early_setup.c -index 62b0dab..e7cca06 100644 ---- a/src/southbridge/amd/sr5650/early_setup.c -+++ b/src/southbridge/amd/sr5650/early_setup.c -@@ -24,6 +24,8 @@ - #include <arch/io.h> - #include <console/console.h> - #include <cpu/x86/msr.h> -+#include <option.h> -+#include <reset.h> - #include "sr5650.h" - #include "cmn.h" - -@@ -271,6 +273,34 @@ void sr5650_htinit(void) - /* HT Buffer Allocation for Ganged Links!!! */ - #endif /* CONFIG_NORTHBRIDGE_AMD_AMDFAM10 || CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY10 */ - } -+ -+} -+ -+/* Must be run immediately after HT setup is complete and first warm reset has occurred (if applicable) -+ * Attempting to switch the NB into isochronous mode before the CPUs have engaged isochronous mode -+ * will cause a system hard lockup... -+ */ -+void sr5650_htinit_dect_and_enable_isochronous_link(void) -+{ -+ device_t sr5650_f0; -+ unsigned char iommu; -+ -+ sr5650_f0 = PCI_DEV(0, 0, 0); -+ -+ iommu = 1; -+ get_option(&iommu, "iommu"); -+ -+ if (iommu) { -+ /* Enable isochronous mode */ -+ set_nbcfg_enable_bits(sr5650_f0, 0xc8, 1 << 12, 1 << 12); -+ -+ /* Apply pending changes */ -+ if (!((pci_read_config32(sr5650_f0, 0xc8) >> 12) & 0x1)) { -+ printk(BIOS_INFO, "...WARM RESET...\n\n\n"); -+ soft_reset(); -+ die("After soft_reset_x - shouldn't see this message!!!\n"); -+ } -+ } - } - - #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 || CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY10 /* save some spaces */ -@@ -335,8 +365,21 @@ static void sr5650_por_pcicfg_init(device_t nb_dev) - *****************************************/ - static void sr5650_por_misc_index_init(device_t nb_dev) - { -- /* disable IOMMU */ -- set_nbmisc_enable_bits(nb_dev, 0x75, 0x1, 0x0); -+ unsigned char iommu; -+ -+ iommu = 1; -+ get_option(&iommu, "iommu"); -+ -+ if (iommu) { -+ /* enable IOMMU */ -+ printk(BIOS_DEBUG, "Enabling IOMMU\n"); -+ set_nbmisc_enable_bits(nb_dev, 0x75, 0x1, 0x1); -+ } else { -+ /* disable IOMMU */ -+ printk(BIOS_DEBUG, "Disabling IOMMU\n"); -+ set_nbmisc_enable_bits(nb_dev, 0x75, 0x1, 0x0); -+ } -+ - /* NBMISCIND:0x75[29]= 1 Device ID for hotplug and PME message */ - set_nbmisc_enable_bits(nb_dev, 0x75, 1 << 29, 1 << 29); - set_nbmisc_enable_bits(nb_dev, 0x75, 1 << 9, 1 << 9); /* no doc reference, comply with BTS */ -@@ -374,10 +417,11 @@ static void sr5650_por_misc_index_init(device_t nb_dev) - * HIDE_NB_AGP_CAP ([0], default=1)HIDE - * HIDE_P2P_AGP_CAP ([1], default=1)HIDE - * HIDE_NB_GART_BAR ([2], default=1)HIDE -+ * HIDE_MMCFG_BAR ([3], default=1)SHOW - * AGPMODE30 ([4], default=0)DISABLE - * AGP30ENCHANCED ([5], default=0)DISABLE - * HIDE_AGP_CAP ([8], default=1)ENABLE */ -- set_nbmisc_enable_bits(nb_dev, 0x00, 0x0000FFFF, 0 << 0 | 1 << 1 | 1 << 2 | 0 << 6); -+ set_nbmisc_enable_bits(nb_dev, 0x00, 0x0000FFFF, 0 << 0 | 1 << 1 | 1 << 2 | 0 << 3 | 0 << 6); - - /* IOC_LAT_PERF_CNTR_CNTL */ - set_nbmisc_enable_bits(nb_dev, 0x30, 0xFF, 0x00); -diff --git a/src/southbridge/amd/sr5650/sr5650.c b/src/southbridge/amd/sr5650/sr5650.c -index 6db1eb1..b296c47 100644 ---- a/src/southbridge/amd/sr5650/sr5650.c -+++ b/src/southbridge/amd/sr5650/sr5650.c -@@ -26,7 +26,9 @@ - #include <device/pci_ops.h> - #include <cpu/x86/msr.h> - #include <cpu/amd/mtrr.h> -+#include <stdlib.h> - #include <delay.h> -+#include <option.h> - #include "sr5650.h" - #include "cmn.h" - -@@ -87,6 +89,26 @@ void nbpcie_ind_write_index(device_t nb_dev, u32 index, u32 data) - nb_write_index((nb_dev), NBPCIE_INDEX, (index), (data)); - } - -+uint32_t l2cfg_ind_read_index(device_t nb_dev, uint32_t index) -+{ -+ return nb_read_index((nb_dev), L2CFG_INDEX, (index)); -+} -+ -+void l2cfg_ind_write_index(device_t nb_dev, uint32_t index, uint32_t data) -+{ -+ nb_write_index((nb_dev), L2CFG_INDEX | (0x1 << 8), (index), (data)); -+} -+ -+uint32_t l1cfg_ind_read_index(device_t nb_dev, uint32_t index) -+{ -+ return nb_read_index((nb_dev), L1CFG_INDEX, (index)); -+} -+ -+void l1cfg_ind_write_index(device_t nb_dev, uint32_t index, uint32_t data) -+{ -+ nb_write_index((nb_dev), L1CFG_INDEX | (0x1 << 31), (index), (data)); -+} -+ - /*********************************************************** - * To access bar3 we need to program PCI MMIO 7 in K8. - * in_out: -@@ -286,6 +308,240 @@ u32 get_vid_did(device_t dev) - return pci_read_config32(dev, 0); - } - -+void detect_and_enable_iommu(device_t iommu_dev) { -+ uint32_t dword; -+ uint8_t l1_target; -+ unsigned char iommu; -+ void * mmio_base; -+ -+ iommu = 1; -+ get_option(&iommu, "iommu"); -+ -+ if (iommu) { -+ printk(BIOS_DEBUG, "Initializing IOMMU\n"); -+ -+ device_t nb_dev = dev_find_slot(0, PCI_DEVFN(0, 0)); -+ -+ if (!nb_dev) { -+ printk(BIOS_WARNING, "Unable to find SR5690 device! IOMMU NOT initialized\n"); -+ return; -+ } -+ -+ mmio_base = (void*)(pci_read_config32(iommu_dev, 0x44) & 0xffffc000); -+ -+ // if (get_nb_rev(nb_dev) == REV_SR5650_A11) { -+ // dword = pci_read_config32(iommu_dev, 0x6c); -+ // dword &= ~(0x1 << 8); -+ // pci_write_config32(iommu_dev, 0x6c, dword); -+ // } -+ -+ dword = pci_read_config32(iommu_dev, 0x50); -+ dword &= ~(0x1 << 22); -+ pci_write_config32(iommu_dev, 0x50, dword); -+ -+ dword = pci_read_config32(iommu_dev, 0x44); -+ dword |= 0x1; -+ pci_write_config32(iommu_dev, 0x44, dword); -+ -+ write32((void*)(mmio_base + 0x8), 0x0); -+ write32((void*)(mmio_base + 0xc), 0x08000000); -+ write32((void*)(mmio_base + 0x10), 0x0); -+ write32((void*)(mmio_base + 0x2008), 0x0); -+ write32((void*)(mmio_base + 0x2010), 0x0); -+ -+ /* IOMMU L1 initialization */ -+ for (l1_target = 0; l1_target < 6; l1_target++) { -+ dword = l1cfg_ind_read_index(nb_dev, (l1_target << 16) + 0xc); -+ dword |= (0x7 << 28); -+ l1cfg_ind_write_index(nb_dev, (l1_target << 16) + 0xc, dword); -+ -+ dword = l1cfg_ind_read_index(nb_dev, (l1_target << 16) + 0x7); -+ dword |= (0x1 << 5); -+ l1cfg_ind_write_index(nb_dev, (l1_target << 16) + 0x7, dword); -+ } -+ -+ /* IOMMU L2 initialization */ -+ dword = l2cfg_ind_read_index(nb_dev, 0xc); -+ dword |= (0x7 << 29); -+ l2cfg_ind_write_index(nb_dev, 0xc, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x10); -+ dword &= ~(0x3 << 8); -+ dword |= (0x2 << 8); -+ l2cfg_ind_write_index(nb_dev, 0x10, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x14); -+ dword &= ~(0x3 << 8); -+ dword |= (0x2 << 8); -+ l2cfg_ind_write_index(nb_dev, 0x14, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x18); -+ dword &= ~(0x3 << 8); -+ dword |= (0x2 << 8); -+ l2cfg_ind_write_index(nb_dev, 0x18, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x1c); -+ dword &= ~(0x3 << 8); -+ dword |= (0x2 << 8); -+ l2cfg_ind_write_index(nb_dev, 0x1c, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x50); -+ dword &= ~(0x3 << 8); -+ dword |= (0x2 << 8); -+ l2cfg_ind_write_index(nb_dev, 0x50, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x10); -+ dword |= (0x1 << 4); -+ l2cfg_ind_write_index(nb_dev, 0x10, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x14); -+ dword |= (0x1 << 4); -+ l2cfg_ind_write_index(nb_dev, 0x14, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x18); -+ dword |= (0x1 << 4); -+ l2cfg_ind_write_index(nb_dev, 0x18, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x1c); -+ dword |= (0x1 << 4); -+ l2cfg_ind_write_index(nb_dev, 0x1c, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x50); -+ dword |= (0x1 << 4); -+ l2cfg_ind_write_index(nb_dev, 0x50, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x6); -+ dword |= (0x1 << 7); -+ l2cfg_ind_write_index(nb_dev, 0x6, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x44); -+ dword |= (0x1 << 0); -+ l2cfg_ind_write_index(nb_dev, 0x44, dword); -+ -+// if (get_nb_rev(nb_dev) == REV_SR5650_A21) { -+ dword = l2cfg_ind_read_index(nb_dev, 0x7); -+ dword |= (0x1 << 1); -+ l2cfg_ind_write_index(nb_dev, 0x7, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x44); -+ dword |= (0x1 << 1); -+ l2cfg_ind_write_index(nb_dev, 0x44, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x7); -+ dword |= (0x1 << 2); -+ l2cfg_ind_write_index(nb_dev, 0x7, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x7); -+ dword |= (0x1 << 3); -+ l2cfg_ind_write_index(nb_dev, 0x7, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x44); -+ dword |= (0x1 << 3); -+ l2cfg_ind_write_index(nb_dev, 0x44, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x7); -+ dword |= (0x1 << 4); -+ l2cfg_ind_write_index(nb_dev, 0x7, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x6); -+ dword |= (0x1 << 5); -+ l2cfg_ind_write_index(nb_dev, 0x6, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x6); -+ dword |= (0x1 << 6); -+ l2cfg_ind_write_index(nb_dev, 0x6, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x7); -+ dword |= (0x1 << 5); -+ l2cfg_ind_write_index(nb_dev, 0x7, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x44); -+ dword |= (0x1 << 4); -+ l2cfg_ind_write_index(nb_dev, 0x44, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x7); -+ dword |= (0x1 << 6); -+ l2cfg_ind_write_index(nb_dev, 0x7, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x7); -+ dword |= (0x1 << 7); -+ l2cfg_ind_write_index(nb_dev, 0x7, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x6); -+ dword |= (0x1 << 8); -+ l2cfg_ind_write_index(nb_dev, 0x6, dword); -+// } -+ -+ l2cfg_ind_write_index(nb_dev, 0x52, 0xf0000002); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x80); -+ dword |= (0x1 << 0); -+ l2cfg_ind_write_index(nb_dev, 0x80, dword); -+ -+ dword = l2cfg_ind_read_index(nb_dev, 0x30); -+ dword |= (0x1 << 0); -+ l2cfg_ind_write_index(nb_dev, 0x30, dword); -+ } -+} -+ -+void sr5650_iommu_read_resources(device_t dev) -+{ -+ unsigned char iommu; -+ struct resource *res; -+ -+ iommu = 1; -+ get_option(&iommu, "iommu"); -+ -+ /* Get the normal pci resources of this device */ -+ pci_dev_read_resources(dev); -+ -+ if (iommu) { -+ /* Request MMIO range allocation */ -+ res = new_resource(dev, 0x44); /* IOMMU */ -+ res->base = 0x0; -+ res->size = 0x4000; -+ res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */ -+ res->align = 14; /* 16k alignment */ -+ res->gran = 14; -+ res->flags = IORESOURCE_MEM | IORESOURCE_RESERVE; -+ } -+ -+ compact_resources(dev); -+} -+ -+void sr5650_iommu_set_resources(device_t dev) -+{ -+ unsigned char iommu; -+ struct resource *res; -+ -+ iommu = 1; -+ get_option(&iommu, "iommu"); -+ -+ /* Get the normal pci resources of this device */ -+ pci_dev_read_resources(dev); -+ -+ if (iommu) { -+ /* Get the allocated range */ -+ res = find_resource(dev, 0x44); -+ -+ if (res->base == 0) { -+ printk(BIOS_WARNING, "Unable to allocate MMIO range to IOMMU\n"); -+ } -+ -+ /* Assign the range to hardware */ -+ pci_write_config32(dev, 0x44, res->base & 0xffffc000); -+ pci_write_config32(dev, 0x48, 0x0); -+ } -+ -+ /* Run standard resource set routine */ -+ pci_dev_set_resources(dev); -+} -+ -+void sr5650_iommu_enable_resources(device_t dev) -+{ -+ detect_and_enable_iommu(dev); -+} -+ - void sr5650_nb_pci_table(device_t nb_dev) - { /* NBPOR_InitPOR function. */ - u8 temp8; -@@ -365,13 +621,23 @@ void sr5650_enable(device_t dev) - dev_ind = dev->path.pci.devfn >> 3; - switch (dev_ind) { - case 0: /* bus0, dev0, fun0; */ -- printk(BIOS_INFO, "Bus-0, Dev-0, Fun-0.\n"); -- enable_pcie_bar3(nb_dev); /* PCIEMiscInit */ -- -- config_gpp_core(nb_dev, sb_dev); -- sr5650_gpp_sb_init(nb_dev, sb_dev, 8); -- -- sr5650_nb_pci_table(nb_dev); -+ switch (dev->path.pci.devfn & 0x7) { -+ case 0: -+ printk(BIOS_INFO, "Bus-0, Dev-0, Fun-0.\n"); -+ enable_pcie_bar3(nb_dev); /* PCIEMiscInit */ -+ -+ config_gpp_core(nb_dev, sb_dev); -+ sr5650_gpp_sb_init(nb_dev, sb_dev, 8); -+ -+ sr5650_nb_pci_table(nb_dev); -+ break; -+ case 1: -+ printk(BIOS_INFO, "Bus-0, Dev-0, Fun-1.\n"); -+ break; -+ case 2: -+ printk(BIOS_INFO, "Bus-0, Dev-0, Fun-2.\n"); -+ break; -+ } - break; - - case 2: /* bus0, dev2,3 GPP1 */ -@@ -438,6 +704,205 @@ void sr5650_enable(device_t dev) - } - } - -+static void add_ivrs_device_entries(struct device *parent, struct device *dev, int depth, int linknum, int8_t *root_level, unsigned long *current, uint16_t *length) -+{ -+ uint8_t *p; -+ struct device *sibling; -+ struct bus *link; -+ -+ if (!root_level) { -+ root_level = malloc(sizeof(int8_t)); -+ *root_level = -1; -+ } -+ -+ if (dev->path.type == DEVICE_PATH_PCI) { -+ if ((dev->bus->secondary == 0x0) && (dev->path.pci.devfn == 0x0)) -+ *root_level = depth; -+ -+ if (*root_level != -1) { -+ if (depth >= *root_level) { -+ if (dev->enabled) { -+ if (depth == *root_level) { -+ if (dev->path.pci.devfn < (0x1 << 3)) { -+ /* SR5690 control device */ -+ } else if ((dev->path.pci.devfn >= (0x1 << 3)) && (dev->path.pci.devfn < (0xe << 3))) { -+ /* SR5690 PCIe bridge device */ -+ } else { -+ if (dev->path.pci.devfn == (0x14 << 3)) { -+ /* SMBUS controller */ -+ p = (uint8_t *) *current; -+ p[0] = 0x2; /* Entry type */ -+ p[1] = dev->path.pci.devfn; /* Device */ -+ p[2] = dev->bus->secondary; /* Bus */ -+ p[3] = 0x97; /* Data */ -+ p[4] = 0x0; /* Padding */ -+ p[5] = 0x0; /* Padding */ -+ p[6] = 0x0; /* Padding */ -+ p[7] = 0x0; /* Padding */ -+ *length += 8; -+ *current += 8; -+ } else { -+ /* Other southbridge device */ -+ p = (uint8_t *) *current; -+ p[0] = 0x2; /* Entry type */ -+ p[1] = dev->path.pci.devfn; /* Device */ -+ p[2] = dev->bus->secondary; /* Bus */ -+ p[3] = 0x0; /* Data */ -+ p[4] = 0x0; /* Padding */ -+ p[5] = 0x0; /* Padding */ -+ p[6] = 0x0; /* Padding */ -+ p[7] = 0x0; /* Padding */ -+ *length += 8; -+ *current += 8; -+ } -+ } -+ } else { -+ if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) { -+ /* Device behind bridge */ -+ if (pci_find_capability(dev, PCI_CAP_ID_PCIE)) { -+ /* Device is PCIe */ -+ p = (uint8_t *) *current; -+ p[0] = 0x2; /* Entry type */ -+ p[1] = dev->path.pci.devfn; /* Device */ -+ p[2] = dev->bus->secondary; /* Bus */ -+ p[3] = 0x0; /* Data */ -+ p[4] = 0x0; /* Padding */ -+ p[5] = 0x0; /* Padding */ -+ p[6] = 0x0; /* Padding */ -+ p[7] = 0x0; /* Padding */ -+ *length += 8; -+ *current += 8; -+ } else { -+ /* Device is legacy PCI or PCI-X */ -+ p = (uint8_t *) *current; -+ p[0] = 0x42; /* Entry type */ -+ p[1] = dev->path.pci.devfn; /* Device */ -+ p[2] = dev->bus->secondary; /* Bus */ -+ p[3] = 0x0; /* Data */ -+ p[4] = 0x0; /* Reserved */ -+ p[5] = parent->path.pci.devfn; /* Device */ -+ p[6] = parent->bus->secondary; /* Bus */ -+ p[7] = 0x0; /* Reserved */ -+ *length += 8; -+ *current += 8; -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ -+ for (link = dev->link_list; link; link = link->next) -+ for (sibling = link->children; sibling; sibling = sibling->sibling) -+ add_ivrs_device_entries(dev, sibling, depth + 1, depth, root_level, current, length); -+ -+ free(root_level); -+} -+ -+static unsigned long acpi_fill_ivrs(acpi_ivrs_t* ivrs, unsigned long current) -+{ -+ uint8_t *p; -+ -+ device_t nb_dev = dev_find_slot(0, PCI_DEVFN(0, 0)); -+ if (!nb_dev) { -+ printk(BIOS_WARNING, "acpi_fill_ivrs: Unable to locate SR5650 device! IVRS table not generated...\n"); -+ return (unsigned long)ivrs; -+ } -+ -+ device_t iommu_dev = dev_find_slot(0, PCI_DEVFN(0, 2)); -+ if (!iommu_dev) { -+ printk(BIOS_WARNING, "acpi_fill_ivrs: Unable to locate SR5650 IOMMU device! IVRS table not generated...\n"); -+ return (unsigned long)ivrs; -+ } -+ -+ ivrs->iv_info = 0x0; -+ ivrs->iv_info |= (0x40 << 15); /* Maximum supported virtual address size */ -+ ivrs->iv_info |= (0x34 << 8); /* Maximum supported physical address size */ -+ -+ ivrs->ivhd.type = 0x10; -+ ivrs->ivhd.flags = 0x0e; -+ // if (get_nb_rev(nb_dev) != REV_SR5650_A11) { -+ ivrs->ivhd.flags |= 0x10; /* Enable ATS support on all revisions except A11 */ -+ // } -+ ivrs->ivhd.length = sizeof(struct acpi_ivrs_ivhd); -+ ivrs->ivhd.device_id = 0x2 | (nb_dev->bus->secondary << 8); /* BDF <bus>:00.2 */ -+ ivrs->ivhd.capability_offset = 0x40; /* Capability block 0x40 (type 0xf, "Secure device") */ -+ ivrs->ivhd.iommu_base_low = pci_read_config32(iommu_dev, 0x44) & 0xffffc000; -+ ivrs->ivhd.iommu_base_high = pci_read_config32(iommu_dev, 0x48); -+ ivrs->ivhd.pci_segment_group = 0x0; -+ ivrs->ivhd.iommu_info = 0x0; -+ ivrs->ivhd.iommu_info |= (0x14 << 8); -+ ivrs->ivhd.efr = 0x0; -+ -+ /* Describe HPET */ -+ p = (uint8_t *)current; -+ p[0] = 0x48; /* Entry type */ -+ p[1] = 0; /* Device */ -+ p[2] = 0; /* Bus */ -+ p[3] = 0xd7; /* Data */ -+ p[4] = 0x0; /* HPET number */ -+ p[5] = 0x14 << 3; /* HPET device */ -+ p[6] = nb_dev->bus->secondary; /* HPET bus */ -+ p[7] = 0x2; /* Variety */ -+ ivrs->ivhd.length += 8; -+ current += 8; -+ -+ /* Describe PCI devices */ -+ add_ivrs_device_entries(NULL, all_devices, 0, -1, NULL, ¤t, &ivrs->ivhd.length); -+ -+ /* Describe IOAPICs */ -+ unsigned long prev_current = current; -+ current = acpi_fill_ivrs_ioapic(ivrs, current); -+ ivrs->ivhd.length += (current - prev_current); -+ -+ return current; -+} -+ -+unsigned long southbridge_write_acpi_tables(device_t device, -+ unsigned long current, -+ struct acpi_rsdp *rsdp) -+{ -+ unsigned char iommu; -+ -+ iommu = 1; -+ get_option(&iommu, "iommu"); -+ -+ if (iommu) { -+ acpi_ivrs_t *ivrs; -+ -+ /* IVRS */ -+ current = ALIGN(current, 8); -+ printk(BIOS_DEBUG, "ACPI: * IVRS at %lx\n", current); -+ ivrs = (acpi_ivrs_t *) current; -+ acpi_create_ivrs(ivrs, acpi_fill_ivrs); -+ current += ivrs->header.length; -+ acpi_add_table(rsdp, ivrs); -+ } -+ -+ return current; -+} -+ -+static struct pci_operations iommu_ops_pci = { -+ .set_subsystem = pci_dev_set_subsystem, -+}; -+ -+static struct device_operations iommu_ops = { -+ .read_resources = sr5650_iommu_read_resources, -+ .set_resources = sr5650_iommu_set_resources, -+ .enable_resources = sr5650_iommu_enable_resources, -+ .write_acpi_tables = southbridge_write_acpi_tables, -+ .init = 0, -+ .scan_bus = 0, -+ .ops_pci = &iommu_ops_pci, -+}; -+ -+static const struct pci_driver ht_driver_sr5690 __pci_driver = { -+ .ops = &iommu_ops, -+ .vendor = PCI_VENDOR_ID_ATI, -+ .device = PCI_DEVICE_ID_AMD_SR5650_IOMMU, -+}; -+ - struct chip_operations southbridge_amd_sr5650_ops = { - CHIP_NAME("ATI SR5650") - .enable_dev = sr5650_enable, -diff --git a/src/southbridge/amd/sr5650/sr5650.h b/src/southbridge/amd/sr5650/sr5650.h -index ebbde41..a3518fb 100644 ---- a/src/southbridge/amd/sr5650/sr5650.h -+++ b/src/southbridge/amd/sr5650/sr5650.h -@@ -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 -@@ -21,6 +22,7 @@ - #define __SR5650_H__ - - #include <stdint.h> -+#include <arch/acpi.h> - #include <device/pci_ids.h> - #include "chip.h" - #include "rev.h" -@@ -95,16 +97,24 @@ u32 nbpcie_p_read_index(device_t dev, u32 index); - void nbpcie_p_write_index(device_t dev, u32 index, u32 data); - u32 nbpcie_ind_read_index(device_t nb_dev, u32 index); - void nbpcie_ind_write_index(device_t nb_dev, u32 index, u32 data); -+uint32_t l2cfg_ind_read_index(device_t nb_dev, uint32_t index); -+void l2cfg_ind_write_index(device_t nb_dev, uint32_t index, uint32_t data); -+uint32_t l1cfg_ind_read_index(device_t nb_dev, uint32_t index); -+void l1cfg_ind_write_index(device_t nb_dev, uint32_t index, uint32_t data); - u32 pci_ext_read_config32(device_t nb_dev, device_t dev, u32 reg); - void pci_ext_write_config32(device_t nb_dev, device_t dev, u32 reg, u32 mask, u32 val); - void sr5650_set_tom(device_t nb_dev); - -+unsigned long southbridge_write_acpi_tables(device_t device, unsigned long current, -+ struct acpi_rsdp *rsdp); -+ - void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add); - void enable_pcie_bar3(device_t nb_dev); - void disable_pcie_bar3(device_t nb_dev); - - void enable_sr5650_dev8(void); - void sr5650_htinit(void); -+void sr5650_htinit_dect_and_enable_isochronous_link(void); - void sr5650_early_setup(void); - void sr5650_before_pci_init(void); - void sr5650_enable(device_t dev); -@@ -118,6 +128,10 @@ void pcie_config_misc_clk(device_t nb_dev); - void fam10_optimization(void); - void sr5650_disable_pcie_bridge(void); - u32 get_vid_did(device_t dev); -+void detect_and_enable_iommu(device_t iommu_dev); -+void sr5650_iommu_read_resources(device_t dev); -+void sr5650_iommu_set_resources(device_t dev); -+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); --- -1.7.9.5 - |