soc/amd/common/data_fabric: read PCI bus decoding from DF registers

The data fabric also controls which PCI bus numbers get decoded to the
PCI root. In order for the resource allocator to know how the hardware
is configured, read the corresponding data fabric registers to get the
information that then gets passed to the allocator.

Picasso, Cezanne, Mendocino and Rembrandt only support one PCI segment
with 256 buses while the Phoenix and Glinda data fabric hardware has
support for more PCI segments. Due to this change, the register layout
is different and incompatible between those two, so introduce the
SOC_AMD_COMMON_BLOCK_DATA_FABRIC_MULTI_PCI_SEGMENT Kconfig option for a
SoC to specify which implementation is needed. At the moment, coreboot
doesn't have support for multiple PCI segments and the code doesn't
support PCI segments other than segment 0.

On Picasso the PCI bus number limit read back from the data fabric
register is 255 even though CONFIG_ECAM_MMCONF_BUS_NUMBER is set to 64,
so also make sure that the bus and limit returned by
data_fabric_get_pci_bus_numbers is within the expected limits.

TEST=PCI bus allocation still works on Mandolin (Picasso) and Birman
(Phoenix). Picasso has 64 PCI buses. coreboot puts this info into the
resource producer in _SB\PCI0\_CRS which the Linux kernel reads:
* coreboot:  PCI0 _CRS: adding busses [0-3f]
* Linux:     pci_bus 0000:00: root bus resource [bus 00-3f]
This matches the information in the ACPI MCFG table.

Signed-off-by: Felix Held <felix-coreboot@felixheld.de>
Change-Id: Ide5fa9b3e95cfd59232048910cc8feacb6dbdb94
Reviewed-on: https://review.coreboot.org/c/coreboot/+/77080
Reviewed-by: Martin L Roth <gaumless@gmail.com>
Reviewed-by: Eric Lai <eric_lai@quanta.corp-partner.google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Felix Held 2023-08-08 02:55:09 +02:00
parent d53137a536
commit ea83139345
8 changed files with 91 additions and 4 deletions

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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