aboutsummaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
authorFelix Held <felix-coreboot@felixheld.de>2023-08-04 19:40:02 +0200
committerFelix Held <felix-coreboot@felixheld.de>2023-08-08 19:47:26 +0000
commit4eac0d4d830d0cb85bbc265c58ae5dd91711d72e (patch)
tree33b6b8721689f06d39573c570bb455b99f20cf6c /src/soc
parent3cef7d3f121427f4358755b4efbc375ddb1f7aa8 (diff)
soc/amd/common/data_fabric/domain: read IO decode windows from registers
Before add_io_regions only reported one fixed IO range to the resource allocator that covered the whole IO range from 0x0000 to 0xffff. Instead read the data fabric IO space decode base and limit address register pairs to get the actual IO port decoding from the data fabric registers. This will also help with adding support for multiple PCI root domains to the common data fabric domain code so that Genoa can use it. In that case each PCI root domain will only decode a part of the whole IO port range. Beware that the data fabric IO base and limit fields can contain values that correspond to IO port addresses far outside of the addressable IO port range. In case of Picasso, the IO limit read from the only enabled DF IO range register would be 0x1ffffff after converting the raw data to an IO port address. To not give the resource allocator wrong constraints make sure that the IO limit we report will be at maximum 0xffff. TEST=On Mandolin (Picasso) and Birman (Phoenix) the full range of IO port addresses still gets reported as a domain IO resource producer like before the patch: DOMAIN: 0000 io: base: 0 size: 0 align: 0 gran: 0 limit: ffff done Signed-off-by: Felix Held <felix-coreboot@felixheld.de> Change-Id: I087d96f7bdaae0d7b53089f6abaf0500a4b064e9 Reviewed-on: https://review.coreboot.org/c/coreboot/+/76960 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Martin L Roth <gaumless@gmail.com>
Diffstat (limited to 'src/soc')
-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)