diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/soc/amd/common/block/data_fabric/Kconfig | 11 | ||||
-rw-r--r-- | src/soc/amd/common/block/data_fabric/Makefile.inc | 6 | ||||
-rw-r--r-- | src/soc/amd/common/block/data_fabric/domain.c | 13 | ||||
-rw-r--r-- | src/soc/amd/common/block/data_fabric/pci_segment_multi.c | 35 | ||||
-rw-r--r-- | src/soc/amd/common/block/data_fabric/pci_segment_single.c | 25 | ||||
-rw-r--r-- | src/soc/amd/common/block/include/amdblocks/data_fabric.h | 3 | ||||
-rw-r--r-- | src/soc/amd/glinda/Kconfig | 1 | ||||
-rw-r--r-- | src/soc/amd/phoenix/Kconfig | 1 |
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 |