diff --git a/src/soc/amd/common/block/data_fabric/Kconfig b/src/soc/amd/common/block/data_fabric/Kconfig index ba771c6dce..add2374b18 100644 --- a/src/soc/amd/common/block/data_fabric/Kconfig +++ b/src/soc/amd/common/block/data_fabric/Kconfig @@ -24,3 +24,12 @@ config SOC_AMD_COMMON_BLOCK_DATA_FABRIC_MULTI_PCI_SEGMENT 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. + +config SOC_AMD_COMMON_BLOCK_DATA_FABRIC_EXTENDED_MMIO + bool + depends on SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN + help + Some AMD SoCs support more than 48 bit MMIO addresses. In order to + have enough bits for this, the MMIO address extension register is + introduced. SoCs that have this register must select this option in + order for the MMIO regions to be reported correctly. diff --git a/src/soc/amd/common/block/data_fabric/Makefile.inc b/src/soc/amd/common/block/data_fabric/Makefile.inc index bf0a21fddb..55a4d3f311 100644 --- a/src/soc/amd/common/block/data_fabric/Makefile.inc +++ b/src/soc/amd/common/block/data_fabric/Makefile.inc @@ -8,3 +8,9 @@ ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN) += pci_segment_multi. else ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN) += pci_segment_single.c endif + +ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_DATA_FABRIC_EXTENDED_MMIO),y) +ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN) += extended_mmio.c +else +ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_DATA_FABRIC_DOMAIN) += mmio.c +endif diff --git a/src/soc/amd/common/block/data_fabric/domain.c b/src/soc/amd/common/block/data_fabric/domain.c index 680d8d8c49..ca685b2fde 100644 --- a/src/soc/amd/common/block/data_fabric/domain.c +++ b/src/soc/amd/common/block/data_fabric/domain.c @@ -36,17 +36,6 @@ void amd_pci_domain_scan_bus(struct device *domain) pci_domain_scan_bus(domain); } -/* Read the registers and return normalized values */ -static void data_fabric_get_mmio_base_size(unsigned int reg, - resource_t *mmio_base, resource_t *mmio_limit) -{ - const uint32_t base_reg = data_fabric_broadcast_read32(DF_MMIO_BASE(reg)); - const uint32_t limit_reg = data_fabric_broadcast_read32(DF_MMIO_LIMIT(reg)); - /* The raw register values are bits 47..16 of the actual address */ - *mmio_base = (resource_t)base_reg << DF_MMIO_SHIFT; - *mmio_limit = (((resource_t)limit_reg + 1) << DF_MMIO_SHIFT) - 1; -} - static void print_df_mmio_outside_of_cpu_mmio_error(unsigned int reg) { printk(BIOS_WARNING, "DF MMIO register %u outside of CPU MMIO region.\n", reg); diff --git a/src/soc/amd/common/block/data_fabric/extended_mmio.c b/src/soc/amd/common/block/data_fabric/extended_mmio.c new file mode 100644 index 0000000000..d0c3d9f051 --- /dev/null +++ b/src/soc/amd/common/block/data_fabric/extended_mmio.c @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include + +/* Read the registers and return normalized values */ +void data_fabric_get_mmio_base_size(unsigned int reg, resource_t *mmio_base, + resource_t *mmio_limit) +{ + const uint32_t base_reg = data_fabric_broadcast_read32(DF_MMIO_BASE(reg)); + const uint32_t limit_reg = data_fabric_broadcast_read32(DF_MMIO_LIMIT(reg)); + const union df_mmio_addr_ext ext_reg.raw = + data_fabric_broadcast_read32(DF_MMIO_ADDR_EXT(reg)); + /* The raw register values in the base and limit registers are bits 47..16 of the + actual address. The MMIO address extension register contains the extended MMIO base + and limit bits starting with bit 48 of the actual address. */ + *mmio_base = (resource_t)ext_reg.base_ext << DF_MMIO_EXT_ADDR_SHIFT | + (resource_t)base_reg << DF_MMIO_SHIFT; + *mmio_limit = (resource_t)ext_reg.limit_ext << DF_MMIO_EXT_ADDR_SHIFT | + (((resource_t)limit_reg + 1) << DF_MMIO_SHIFT) - 1; +} diff --git a/src/soc/amd/common/block/data_fabric/mmio.c b/src/soc/amd/common/block/data_fabric/mmio.c new file mode 100644 index 0000000000..f7f31037c7 --- /dev/null +++ b/src/soc/amd/common/block/data_fabric/mmio.c @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include + +/* Read the registers and return normalized values */ +void data_fabric_get_mmio_base_size(unsigned int reg, resource_t *mmio_base, + resource_t *mmio_limit) +{ + const uint32_t base_reg = data_fabric_broadcast_read32(DF_MMIO_BASE(reg)); + const uint32_t limit_reg = data_fabric_broadcast_read32(DF_MMIO_LIMIT(reg)); + /* The raw register values are bits 47..16 of the actual address */ + *mmio_base = (resource_t)base_reg << DF_MMIO_SHIFT; + *mmio_limit = (((resource_t)limit_reg + 1) << DF_MMIO_SHIFT) - 1; +} 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 341bad6415..6fdd3f9a27 100644 --- a/src/soc/amd/common/block/include/amdblocks/data_fabric.h +++ b/src/soc/amd/common/block/include/amdblocks/data_fabric.h @@ -22,6 +22,9 @@ #define DF_MMIO_BASE(reg) (DF_MMIO_BASE0 + DF_MMIO_REG_OFFSET(reg)) #define DF_MMIO_LIMIT(reg) (DF_MMIO_LIMIT0 + DF_MMIO_REG_OFFSET(reg)) #define DF_MMIO_CONTROL(reg) (DF_MMIO_CTRL0 + DF_MMIO_REG_OFFSET(reg)) +#if CONFIG(SOC_AMD_COMMON_BLOCK_DATA_FABRIC_EXTENDED_MMIO) +#define DF_MMIO_ADDR_EXT(reg) (DF_MMIO_ADDR_EXT0 + DF_MMIO_REG_OFFSET(reg)) +#endif /* Last 12GB of the usable address space are reserved */ #define DF_RESERVED_TOP_12GB_MMIO_SIZE (12ULL * GiB) @@ -51,6 +54,9 @@ 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); +void data_fabric_get_mmio_base_size(unsigned int reg, resource_t *mmio_base, + resource_t *mmio_limit); + /* 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);