blob: 3abaee1efb3e143db27ad1863ed95e06a127c039 [file] [log] [blame]
Arthur Heymansadee6a62023-07-14 19:42:40 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2
Martin Rothf643a4d2023-09-27 16:46:46 -06003#include <FCH/Common/FchCommonCfg.h>
Arthur Heymans81ceea12023-07-14 19:56:03 +02004#include <RcMgr/DfX/RcManager4-api.h>
Arthur Heymansadee6a62023-07-14 19:42:40 +02005#include <amdblocks/reset.h>
6#include <bootstate.h>
7#include <cbmem.h>
Arthur Heymans81ceea12023-07-14 19:56:03 +02008#include <cpu/cpu.h>
Martin Rothf643a4d2023-09-27 16:46:46 -06009#include <device/device.h>
10#include <soc/soc_chip.h>
Arthur Heymansadee6a62023-07-14 19:42:40 +020011#include <xSIM-api.h>
12#include "opensil_console.h"
13
14static void SIL_STATUS_report(const char *function, const int status)
15{
16 const int log_level = status == SilPass ? BIOS_DEBUG : BIOS_ERR;
17 const char *error_string = "Unkown error";
18
19 const struct error_string_entry {
20 SIL_STATUS status;
21 const char *string;
22 } errors[] = {
23 {SilPass, "SilPass"},
24 {SilUnsupportedHardware, "SilUnsupportedHardware"},
25 {SilUnsupported, "SilUnsupported"},
26 {SilInvalidParameter, "SilInvalidParameter"},
27 {SilAborted, "SilAborted"},
28 {SilOutOfResources, "SilOutOfResources"},
29 {SilNotFound, "SilNotFound"},
30 {SilOutOfBounds, "SilOutOfBounds"},
31 {SilDeviceError, "SilDeviceError"},
32 {SilResetRequestColdImm, "SilResetRequestColdImm"},
33 {SilResetRequestColdDef, "SilResetRequestColdDef"},
34 {SilResetRequestWarmImm, "SilResetRequestWarmImm"},
35 {SilResetRequestWarmDef, "SilResetRequestWarmDef"},
36 };
37
38 int i;
39 for (i = 0; i < ARRAY_SIZE(errors); i++) {
40 if (errors[i].status == status)
41 error_string = errors[i].string;
42 }
43 printk(log_level, "%s returned %d (%s)\n", function, status, error_string);
44}
45
Arthur Heymans81ceea12023-07-14 19:56:03 +020046static void setup_rc_manager_default(void)
47{
48 DFX_RCMGR_INPUT_BLK *rc_mgr_input_block = SilFindStructure(SilId_RcManager, 0);
49 /* Let openSIL distribute the resources to the different PCI roots */
50 rc_mgr_input_block->SetRcBasedOnNv = false;
51
52 /* Currently 1P is the only supported configuration */
53 rc_mgr_input_block->SocketNumber = 1;
54 rc_mgr_input_block->RbsPerSocket = 4; /* PCI root bridges per socket */
55 rc_mgr_input_block->McptEnable = true;
56 rc_mgr_input_block->PciExpressBaseAddress = CONFIG_ECAM_MMCONF_BASE_ADDRESS;
57 rc_mgr_input_block->BottomMmioReservedForPrimaryRb = 4ull * GiB - 32 * MiB;
58 rc_mgr_input_block->MmioSizePerRbForNonPciDevice = 16 * MiB;
59 /* MmioAbove4GLimit will be adjusted down in openSIL */
60 rc_mgr_input_block->MmioAbove4GLimit = POWER_OF_2(cpu_phys_address_size());
61 rc_mgr_input_block->Above4GMmioSizePerRbForNonPciDevice = 0;
62}
63
Martin Rothf643a4d2023-09-27 16:46:46 -060064#define NUM_XHCI_CONTROLLERS 2
65static void configure_usb(void)
66{
67 const struct soc_amd_genoa_config *soc_config = config_of_soc();
68 const struct soc_usb_config *usb = &soc_config->usb;
69
70 FCHUSB_INPUT_BLK *fch_usb_data = SilFindStructure(SilId_FchUsb, 0);
71 fch_usb_data->Xhci0Enable = usb->xhci0_enable;
72 fch_usb_data->Xhci1Enable = usb->xhci1_enable;
73 fch_usb_data->Xhci2Enable = false; /* there's no XHCI2 on this SoC */
74 for (int i = 0; i < NUM_XHCI_CONTROLLERS; i++) {
75 memcpy(&fch_usb_data->XhciOCpinSelect[i].Usb20OcPin, &usb->usb2_oc_pins[i],
76 sizeof(fch_usb_data->XhciOCpinSelect[i].Usb20OcPin));
77 memcpy(&fch_usb_data->XhciOCpinSelect[i].Usb31OcPin, &usb->usb3_oc_pins[i],
78 sizeof(fch_usb_data->XhciOCpinSelect[i].Usb31OcPin));
79 }
80 fch_usb_data->XhciOcPolarityCfgLow = usb->polarity_cfg_low;
81 fch_usb_data->Usb3PortForceGen1 = usb->usb3_force_gen1.raw;
82
83 /* Instead of overwriting the whole OemUsbConfigurationTable, only copy the relevant
84 fields to the pre-populated data structure */
85 fch_usb_data->OemUsbConfigurationTable.Usb31PhyEnable = usb->usb31_phy_enable;
86 if (usb->usb31_phy_enable)
87 memcpy(&fch_usb_data->OemUsbConfigurationTable.Usb31PhyPort, usb->usb31_phy,
88 sizeof(fch_usb_data->OemUsbConfigurationTable.Usb31PhyPort));
89 fch_usb_data->OemUsbConfigurationTable.Usb31PhyEnable = usb->s1_usb31_phy_enable;
90 if (usb->s1_usb31_phy_enable)
91 memcpy(&fch_usb_data->OemUsbConfigurationTable.S1Usb31PhyPort, usb->s1_usb31_phy,
92 sizeof(fch_usb_data->OemUsbConfigurationTable.S1Usb31PhyPort));
93}
94
Arthur Heymansadee6a62023-07-14 19:42:40 +020095static void setup_opensil(void *unused)
96{
97 const SIL_STATUS debug_ret = SilDebugSetup(HostDebugService);
98 SIL_STATUS_report("SilDebugSetup", debug_ret);
99 const size_t mem_req = xSimQueryMemoryRequirements();
100 void *buf = cbmem_add(CBMEM_ID_AMD_OPENSIL, mem_req);
101 assert(buf);
102 /* We run all openSIL timepoints in the same stage so using TP1 as argument is fine. */
103 const SIL_STATUS assign_mem_ret = xSimAssignMemoryTp1(buf, mem_req);
104 SIL_STATUS_report("xSimAssignMemory", assign_mem_ret);
Arthur Heymans81ceea12023-07-14 19:56:03 +0200105
106 setup_rc_manager_default();
Martin Rothf643a4d2023-09-27 16:46:46 -0600107 configure_usb();
Arthur Heymansadee6a62023-07-14 19:42:40 +0200108}
109
110BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_ENTRY, setup_opensil, NULL);
111
112static void opensil_entry(void *timepoint)
113{
114 SIL_STATUS ret;
115 SIL_TIMEPOINT tp = (uintptr_t)timepoint;
116
117 switch (tp) {
118 case SIL_TP1:
119 ret = InitializeSiTp1();
120 break;
121 case SIL_TP2:
122 ret = InitializeSiTp2();
123 break;
124 case SIL_TP3:
125 ret = InitializeSiTp3();
126 break;
127 default:
128 printk(BIOS_ERR, "Unknown opensil timepoint\n");
129 return;
130 }
131 char opensil_function[16];
132 snprintf(opensil_function, sizeof(opensil_function), "InitializeSiTp%d", tp);
133 SIL_STATUS_report(opensil_function, ret);
134 if (ret == SilResetRequestColdImm || ret == SilResetRequestColdDef) {
135 printk(BIOS_INFO, "openSil requested a cold reset");
136 do_cold_reset();
137 } else if (ret == SilResetRequestWarmImm || ret == SilResetRequestWarmDef) {
138 printk(BIOS_INFO, "openSil requested a warm reset");
139 do_warm_reset();
140 }
141}
142
143/* TODO: look into calling these functions from some SoC device operations instead of using
144 * BOOT_STATE_INIT_ENTRY */
145BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, opensil_entry, (void *)SIL_TP1);
146/* TODO add other timepoints later. Are they NOOP? */