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:
parent
d53137a536
commit
ea83139345
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue