summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/amd/common/block/data_fabric/domain.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/src/soc/amd/common/block/data_fabric/domain.c b/src/soc/amd/common/block/data_fabric/domain.c
index cfd4e0fe68..7328fc62da 100644
--- a/src/soc/amd/common/block/data_fabric/domain.c
+++ b/src/soc/amd/common/block/data_fabric/domain.c
@@ -152,10 +152,40 @@ static void report_data_fabric_io(struct device *domain, unsigned int idx,
/* Tell the resource allocator about the usable I/O space */
static void add_data_fabric_io_regions(struct device *domain, unsigned int *idx)
{
- /* TODO: Systems with more than one PCI root need to read the data fabric registers to
- see which IO ranges get decoded to which PCI root. */
+ union df_io_base base_reg;
+ union df_io_limit limit_reg;
+ resource_t io_base;
+ resource_t io_limit;
+
+ for (unsigned int i = 0; i < DF_IO_REG_COUNT; i++) {
+ base_reg.raw = data_fabric_broadcast_read32(DF_IO_BASE(i));
+
+ /* Relevant IO regions need to have both reads and writes enabled */
+ if (!base_reg.we || !base_reg.re)
+ continue;
+
+ limit_reg.raw = data_fabric_broadcast_read32(DF_IO_LIMIT(i));
+
+ /* TODO: Systems with more than one PCI root need to check to which PCI root
+ the IO range gets decoded to. */
+
+ io_base = base_reg.io_base << DF_IO_ADDR_SHIFT;
+ io_limit = ((limit_reg.io_limit + 1) << DF_IO_ADDR_SHIFT) - 1;
+
+ /* Beware that the lower 25 bits of io_base and io_limit can be non-zero
+ despite there only being 16 bits worth of IO port address space. */
+ if (io_base > 0xffff) {
+ printk(BIOS_WARNING, "DF IO base register %d value outside of valid "
+ "IO port address range.\n", i);
+ continue;
+ }
+ /* If only the IO limit is outside of the valid 16 bit IO port range, report
+ the limit as 0xffff, so that the resource allcator won't put IO BARs outside
+ of the 16 bit IO port address range. */
+ io_limit = MIN(io_limit, 0xffff);
- report_data_fabric_io(domain, (*idx)++, 0, 0xffff);
+ report_data_fabric_io(domain, (*idx)++, io_base, io_limit);
+ }
}
void amd_pci_domain_read_resources(struct device *domain)