blob: 3abaee1efb3e143db27ad1863ed95e06a127c039 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
#include <FCH/Common/FchCommonCfg.h>
#include <RcMgr/DfX/RcManager4-api.h>
#include <amdblocks/reset.h>
#include <bootstate.h>
#include <cbmem.h>
#include <cpu/cpu.h>
#include <device/device.h>
#include <soc/soc_chip.h>
#include <xSIM-api.h>
#include "opensil_console.h"
static void SIL_STATUS_report(const char *function, const int status)
{
const int log_level = status == SilPass ? BIOS_DEBUG : BIOS_ERR;
const char *error_string = "Unkown error";
const struct error_string_entry {
SIL_STATUS status;
const char *string;
} errors[] = {
{SilPass, "SilPass"},
{SilUnsupportedHardware, "SilUnsupportedHardware"},
{SilUnsupported, "SilUnsupported"},
{SilInvalidParameter, "SilInvalidParameter"},
{SilAborted, "SilAborted"},
{SilOutOfResources, "SilOutOfResources"},
{SilNotFound, "SilNotFound"},
{SilOutOfBounds, "SilOutOfBounds"},
{SilDeviceError, "SilDeviceError"},
{SilResetRequestColdImm, "SilResetRequestColdImm"},
{SilResetRequestColdDef, "SilResetRequestColdDef"},
{SilResetRequestWarmImm, "SilResetRequestWarmImm"},
{SilResetRequestWarmDef, "SilResetRequestWarmDef"},
};
int i;
for (i = 0; i < ARRAY_SIZE(errors); i++) {
if (errors[i].status == status)
error_string = errors[i].string;
}
printk(log_level, "%s returned %d (%s)\n", function, status, error_string);
}
static void setup_rc_manager_default(void)
{
DFX_RCMGR_INPUT_BLK *rc_mgr_input_block = SilFindStructure(SilId_RcManager, 0);
/* Let openSIL distribute the resources to the different PCI roots */
rc_mgr_input_block->SetRcBasedOnNv = false;
/* Currently 1P is the only supported configuration */
rc_mgr_input_block->SocketNumber = 1;
rc_mgr_input_block->RbsPerSocket = 4; /* PCI root bridges per socket */
rc_mgr_input_block->McptEnable = true;
rc_mgr_input_block->PciExpressBaseAddress = CONFIG_ECAM_MMCONF_BASE_ADDRESS;
rc_mgr_input_block->BottomMmioReservedForPrimaryRb = 4ull * GiB - 32 * MiB;
rc_mgr_input_block->MmioSizePerRbForNonPciDevice = 16 * MiB;
/* MmioAbove4GLimit will be adjusted down in openSIL */
rc_mgr_input_block->MmioAbove4GLimit = POWER_OF_2(cpu_phys_address_size());
rc_mgr_input_block->Above4GMmioSizePerRbForNonPciDevice = 0;
}
#define NUM_XHCI_CONTROLLERS 2
static void configure_usb(void)
{
const struct soc_amd_genoa_config *soc_config = config_of_soc();
const struct soc_usb_config *usb = &soc_config->usb;
FCHUSB_INPUT_BLK *fch_usb_data = SilFindStructure(SilId_FchUsb, 0);
fch_usb_data->Xhci0Enable = usb->xhci0_enable;
fch_usb_data->Xhci1Enable = usb->xhci1_enable;
fch_usb_data->Xhci2Enable = false; /* there's no XHCI2 on this SoC */
for (int i = 0; i < NUM_XHCI_CONTROLLERS; i++) {
memcpy(&fch_usb_data->XhciOCpinSelect[i].Usb20OcPin, &usb->usb2_oc_pins[i],
sizeof(fch_usb_data->XhciOCpinSelect[i].Usb20OcPin));
memcpy(&fch_usb_data->XhciOCpinSelect[i].Usb31OcPin, &usb->usb3_oc_pins[i],
sizeof(fch_usb_data->XhciOCpinSelect[i].Usb31OcPin));
}
fch_usb_data->XhciOcPolarityCfgLow = usb->polarity_cfg_low;
fch_usb_data->Usb3PortForceGen1 = usb->usb3_force_gen1.raw;
/* Instead of overwriting the whole OemUsbConfigurationTable, only copy the relevant
fields to the pre-populated data structure */
fch_usb_data->OemUsbConfigurationTable.Usb31PhyEnable = usb->usb31_phy_enable;
if (usb->usb31_phy_enable)
memcpy(&fch_usb_data->OemUsbConfigurationTable.Usb31PhyPort, usb->usb31_phy,
sizeof(fch_usb_data->OemUsbConfigurationTable.Usb31PhyPort));
fch_usb_data->OemUsbConfigurationTable.Usb31PhyEnable = usb->s1_usb31_phy_enable;
if (usb->s1_usb31_phy_enable)
memcpy(&fch_usb_data->OemUsbConfigurationTable.S1Usb31PhyPort, usb->s1_usb31_phy,
sizeof(fch_usb_data->OemUsbConfigurationTable.S1Usb31PhyPort));
}
static void setup_opensil(void *unused)
{
const SIL_STATUS debug_ret = SilDebugSetup(HostDebugService);
SIL_STATUS_report("SilDebugSetup", debug_ret);
const size_t mem_req = xSimQueryMemoryRequirements();
void *buf = cbmem_add(CBMEM_ID_AMD_OPENSIL, mem_req);
assert(buf);
/* We run all openSIL timepoints in the same stage so using TP1 as argument is fine. */
const SIL_STATUS assign_mem_ret = xSimAssignMemoryTp1(buf, mem_req);
SIL_STATUS_report("xSimAssignMemory", assign_mem_ret);
setup_rc_manager_default();
configure_usb();
}
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_ENTRY, setup_opensil, NULL);
static void opensil_entry(void *timepoint)
{
SIL_STATUS ret;
SIL_TIMEPOINT tp = (uintptr_t)timepoint;
switch (tp) {
case SIL_TP1:
ret = InitializeSiTp1();
break;
case SIL_TP2:
ret = InitializeSiTp2();
break;
case SIL_TP3:
ret = InitializeSiTp3();
break;
default:
printk(BIOS_ERR, "Unknown opensil timepoint\n");
return;
}
char opensil_function[16];
snprintf(opensil_function, sizeof(opensil_function), "InitializeSiTp%d", tp);
SIL_STATUS_report(opensil_function, ret);
if (ret == SilResetRequestColdImm || ret == SilResetRequestColdDef) {
printk(BIOS_INFO, "openSil requested a cold reset");
do_cold_reset();
} else if (ret == SilResetRequestWarmImm || ret == SilResetRequestWarmDef) {
printk(BIOS_INFO, "openSil requested a warm reset");
do_warm_reset();
}
}
/* TODO: look into calling these functions from some SoC device operations instead of using
* BOOT_STATE_INIT_ENTRY */
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, opensil_entry, (void *)SIL_TP1);
/* TODO add other timepoints later. Are they NOOP? */