summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/soc/amd/common/block/data_fabric/Kconfig11
-rw-r--r--src/soc/amd/common/block/data_fabric/Makefile.inc6
-rw-r--r--src/soc/amd/common/block/data_fabric/domain.c13
-rw-r--r--src/soc/amd/common/block/data_fabric/pci_segment_multi.c35
-rw-r--r--src/soc/amd/common/block/data_fabric/pci_segment_single.c25
-rw-r--r--src/soc/amd/common/block/include/amdblocks/data_fabric.h3
-rw-r--r--src/soc/amd/glinda/Kconfig1
-rw-r--r--src/soc/amd/phoenix/Kconfig1
8 files changed, 91 insertions, 4 deletions
diff --git a/src/soc/amd/common/block/data_fabric/Kconfig b/src/soc/amd/common/block/data_fabric/Kconfig
index 4c4f7b34e1..ba771c6dce 100644
--- a/src/soc/amd/common/block/data_fabric/Kconfig
+++ b/src/soc/amd/common/block/data_fabric/Kconfig
@@ -13,3 +13,14 @@ config SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN
resource allocator about the MMIO regions configured in the data
fabric registers so that it knows in which regions it can properly
allocate the non-fixed MMIO devices.
+
+config SOC_AMD_COMMON_BLOCK_DATA_FABRIC_MULTI_PCI_SEGMENT
+ bool
+ depends on SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN
+ help
+ Some AMD SoCs support more than one PCI segment with 256 buses. Those
+ SoCs however have a different data fabric register layout for the PCI
+ bus number decoding. SoCs that use a data fabric register pair for
+ the PCI bus number which includes the segment number must select this
+ option; SoCs that use one data fabric register for the PCI bus number
+ which doesn't include a segment number field mustn't select this.
diff --git a/src/soc/amd/common/block/data_fabric/Makefile.inc b/src/soc/amd/common/block/data_fabric/Makefile.inc
index 868df82e1c..f01c70dfb0 100644
--- a/src/soc/amd/common/block/data_fabric/Makefile.inc
+++ b/src/soc/amd/common/block/data_fabric/Makefile.inc
@@ -2,3 +2,9 @@
ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_DATA_FABRIC) += data_fabric_helper.c
ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN) += domain.c
+
+ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_DATA_FABRIC_MULTI_PCI_SEGMENT),y)
+ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN) += pci_segment_multi.c
+else
+ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN) += pci_segment_single.c
+endif # !CONFIG_SOC_AMD_COMMON_BLOCK_APOB_NV_DISABLE
diff --git a/src/soc/amd/common/block/data_fabric/domain.c b/src/soc/amd/common/block/data_fabric/domain.c
index 88b116063b..d693879ce6 100644
--- a/src/soc/amd/common/block/data_fabric/domain.c
+++ b/src/soc/amd/common/block/data_fabric/domain.c
@@ -16,10 +16,15 @@ void amd_pci_domain_scan_bus(struct device *domain)
{
uint8_t bus, limit;
- /* TODO: Systems with more than one PCI root need to read the data fabric registers to
- see which PCI bus numbers get decoded to which PCI root. */
- bus = 0;
- limit = CONFIG_ECAM_MMCONF_BUS_NUMBER - 1;
+ if (data_fabric_get_pci_bus_numbers(domain, &bus, &limit) != CB_SUCCESS) {
+ printk(BIOS_ERR, "No PCI bus numbers decoded to PCI root.\n");
+ return;
+ }
+
+ /* TODO: Check if bus >= CONFIG_ECAM_MMCONF_BUS_NUMBER and return in that case */
+
+ /* Make sure to not report more than CONFIG_ECAM_MMCONF_BUS_NUMBER PCI buses */
+ limit = MIN(limit, CONFIG_ECAM_MMCONF_BUS_NUMBER - 1);
/* Set bus first number of PCI root */
domain->link_list->secondary = bus;
diff --git a/src/soc/amd/common/block/data_fabric/pci_segment_multi.c b/src/soc/amd/common/block/data_fabric/pci_segment_multi.c
new file mode 100644
index 0000000000..67822216cd
--- /dev/null
+++ b/src/soc/amd/common/block/data_fabric/pci_segment_multi.c
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <amdblocks/data_fabric.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <types.h>
+
+enum cb_err data_fabric_get_pci_bus_numbers(struct device *domain, uint8_t *first_bus,
+ uint8_t *last_bus)
+{
+ union df_pci_cfg_base pci_bus_base;
+ union df_pci_cfg_limit pci_bus_limit;
+
+ for (unsigned int i = 0; i < DF_PCI_CFG_MAP_COUNT; i++) {
+ pci_bus_base.raw = data_fabric_broadcast_read32(DF_PCI_CFG_BASE(i));
+ pci_bus_limit.raw = data_fabric_broadcast_read32(DF_PCI_CFG_LIMIT(i));
+
+ /* TODO: Systems with more than one PCI root need to check to which PCI root
+ the PCI bus number range gets decoded to. */
+ if (pci_bus_base.we && pci_bus_base.re) {
+ /* TODO: Implement support for multiple PCI segments in coreboot */
+ if (pci_bus_base.segment_num) {
+ printk(BIOS_ERR, "DF PCI CFG register pair %d uses bus "
+ "segment != 0.\n", i);
+ return CB_ERR;
+ }
+
+ *first_bus = pci_bus_base.bus_num_base;
+ *last_bus = pci_bus_limit.bus_num_limit;
+ return CB_SUCCESS;
+ }
+ }
+
+ return CB_ERR;
+}
diff --git a/src/soc/amd/common/block/data_fabric/pci_segment_single.c b/src/soc/amd/common/block/data_fabric/pci_segment_single.c
new file mode 100644
index 0000000000..5f2152b668
--- /dev/null
+++ b/src/soc/amd/common/block/data_fabric/pci_segment_single.c
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <amdblocks/data_fabric.h>
+#include <device/device.h>
+#include <types.h>
+
+enum cb_err data_fabric_get_pci_bus_numbers(struct device *domain, uint8_t *first_bus,
+ uint8_t *last_bus)
+{
+ union df_pci_cfg_map pci_bus_map;
+
+ for (unsigned int i = 0; i < DF_PCI_CFG_MAP_COUNT; i++) {
+ pci_bus_map.raw = data_fabric_broadcast_read32(DF_PCI_CFG_MAP(i));
+
+ /* TODO: Systems with more than one PCI root need to check to which PCI root
+ the PCI bus number range gets decoded to. */
+ if (pci_bus_map.we && pci_bus_map.re) {
+ *first_bus = pci_bus_map.bus_num_base;
+ *last_bus = pci_bus_map.bus_num_limit;
+ return CB_SUCCESS;
+ }
+ }
+
+ return CB_ERR;
+}
diff --git a/src/soc/amd/common/block/include/amdblocks/data_fabric.h b/src/soc/amd/common/block/include/amdblocks/data_fabric.h
index f1a7c297ff..341bad6415 100644
--- a/src/soc/amd/common/block/include/amdblocks/data_fabric.h
+++ b/src/soc/amd/common/block/include/amdblocks/data_fabric.h
@@ -48,6 +48,9 @@ void data_fabric_disable_mmio_reg(unsigned int reg);
int data_fabric_find_unused_mmio_reg(void);
void data_fabric_set_mmio_np(void);
+enum cb_err data_fabric_get_pci_bus_numbers(struct device *domain, uint8_t *first_bus,
+ uint8_t *last_bus);
+
/* Inform the resource allocator about the usable IO and MMIO regions and PCI bus numbers */
void amd_pci_domain_read_resources(struct device *domain);
void amd_pci_domain_scan_bus(struct device *domain);
diff --git a/src/soc/amd/glinda/Kconfig b/src/soc/amd/glinda/Kconfig
index a241ad10fa..b51cff39e0 100644
--- a/src/soc/amd/glinda/Kconfig
+++ b/src/soc/amd/glinda/Kconfig
@@ -43,6 +43,7 @@ config SOC_AMD_GLINDA
select SOC_AMD_COMMON_BLOCK_CPUFREQ_FAM1AH
select SOC_AMD_COMMON_BLOCK_DATA_FABRIC
select SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN
+ select SOC_AMD_COMMON_BLOCK_DATA_FABRIC_MULTI_PCI_SEGMENT
select SOC_AMD_COMMON_BLOCK_ESPI_EXTENDED_DECODE_RANGES # TODO: Check if this is still correct
select SOC_AMD_COMMON_BLOCK_GRAPHICS # TODO: Check if this is still correct
select SOC_AMD_COMMON_BLOCK_HAS_ESPI # TODO: Check if this is still correct
diff --git a/src/soc/amd/phoenix/Kconfig b/src/soc/amd/phoenix/Kconfig
index b506464928..6bed749731 100644
--- a/src/soc/amd/phoenix/Kconfig
+++ b/src/soc/amd/phoenix/Kconfig
@@ -44,6 +44,7 @@ config SOC_AMD_PHOENIX
select SOC_AMD_COMMON_BLOCK_CPUFREQ_FAM17H_19H
select SOC_AMD_COMMON_BLOCK_DATA_FABRIC
select SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN
+ select SOC_AMD_COMMON_BLOCK_DATA_FABRIC_MULTI_PCI_SEGMENT
select SOC_AMD_COMMON_BLOCK_ESPI_EXTENDED_DECODE_RANGES
select SOC_AMD_COMMON_BLOCK_GRAPHICS # TODO: Check if this is still correct
select SOC_AMD_COMMON_BLOCK_HAS_ESPI