blob: facd5f8c0f07cea5e562c5efebcff2a5b91a79e8 [file] [log] [blame]
Marc Jones1587dc82017-05-15 18:55:11 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 Advanced Micro Devices, Inc.
5 * Copyright (C) 2013 Sage Electronic Engineering, LLC
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <cbfs.h>
Elyes HAOUAS20eaef02019-03-29 17:45:28 +010018#include <console/console.h>
Marc Jones33eef132017-10-26 16:50:42 -060019#include <cpu/x86/lapic.h>
20#include <cpu/x86/mp.h>
21#include <timer.h>
Richard Spiegel0ad74ac2017-12-08 16:53:29 -070022#include <amdblocks/BiosCallOuts.h>
23#include <amdblocks/agesawrapper.h>
24#include <amdblocks/agesawrapper_call.h>
Nico Huber73c11192018-10-06 18:20:47 +020025#include <amdblocks/reset.h>
Marc Jonesdfeb1c42017-08-07 19:08:24 -060026#include <soc/southbridge.h>
Marc Jones1587dc82017-05-15 18:55:11 -060027
Martin Rothc450fbe2017-10-02 13:46:50 -060028#if ENV_BOOTBLOCK
29const BIOS_CALLOUT_STRUCT BiosCallouts[] = {
30 { AGESA_DO_RESET, agesa_Reset },
31 { AGESA_FCH_OEM_CALLOUT, agesa_fch_initreset },
Richard Spiegela9f49362018-03-05 08:11:50 -070032 { AGESA_HALT_THIS_AP, agesa_HaltThisAp },
Marshall Dawsonc150a572018-04-30 17:59:27 -060033 { AGESA_HEAP_REBASE, agesa_HeapRebase },
Martin Rothc450fbe2017-10-02 13:46:50 -060034 { AGESA_GNB_PCIE_SLOT_RESET, agesa_PcieSlotResetControl }
35};
36#else
37const BIOS_CALLOUT_STRUCT BiosCallouts[] = {
38 /* Required callouts */
Richard Spiegel09a16e62018-04-04 12:40:20 -070039#if ENV_ROMSTAGE
40 { AGESA_HALT_THIS_AP, agesa_HaltThisAp },
41#endif
Martin Rothc450fbe2017-10-02 13:46:50 -060042 { AGESA_ALLOCATE_BUFFER, agesa_AllocateBuffer },
43 { AGESA_DEALLOCATE_BUFFER, agesa_DeallocateBuffer },
44 { AGESA_DO_RESET, agesa_Reset },
45 { AGESA_LOCATE_BUFFER, agesa_LocateBuffer },
46 { AGESA_READ_SPD, agesa_ReadSpd },
Marc Jones33eef132017-10-26 16:50:42 -060047 { AGESA_GNB_PCIE_SLOT_RESET, agesa_PcieSlotResetControl },
Marshall Dawson10b52e02018-05-07 08:51:04 -060048 { AGESA_GET_TEMP_HEAP_BASE, agesa_GetTempHeapBase },
Marshall Dawsonc150a572018-04-30 17:59:27 -060049 { AGESA_HEAP_REBASE, agesa_HeapRebase },
Marc Jones33eef132017-10-26 16:50:42 -060050#if ENV_RAMSTAGE
Martin Rothc450fbe2017-10-02 13:46:50 -060051 { AGESA_RUNFUNC_ONAP, agesa_RunFuncOnAp },
52 { AGESA_RUNFUNC_ON_ALL_APS, agesa_RunFcnOnAllAps },
Martin Rothc450fbe2017-10-02 13:46:50 -060053 { AGESA_WAIT_FOR_ALL_APS, agesa_WaitForAllApsFinished },
54 { AGESA_IDLE_AN_AP, agesa_IdleAnAp },
Marc Jones33eef132017-10-26 16:50:42 -060055#endif /* ENV_RAMSTAGE */
Martin Rothc450fbe2017-10-02 13:46:50 -060056
57 /* Optional callouts */
58 { AGESA_GET_IDS_INIT_DATA, agesa_EmptyIdsInitData },
59 //AgesaHeapRebase - Hook ID?
60 { AGESA_HOOKBEFORE_DRAM_INIT, agesa_NoopUnsupported },
61 { AGESA_HOOKBEFORE_DQS_TRAINING, agesa_NoopUnsupported },
62 { AGESA_EXTERNAL_2D_TRAIN_VREF_CHANGE, agesa_NoopUnsupported },
63 { AGESA_HOOKBEFORE_EXIT_SELF_REF, agesa_NoopUnsupported },
64 { AGESA_GNB_GFX_GET_VBIOS_IMAGE, agesa_GfxGetVbiosImage },
65 { AGESA_FCH_OEM_CALLOUT, agesa_fch_initenv },
66 { AGESA_EXTERNAL_VOLTAGE_ADJUST, agesa_NoopUnsupported },
67 { AGESA_GNB_PCIE_CLK_REQ, agesa_NoopUnsupported },
68
69 /* Deprecated */
70 { AGESA_HOOKBEFORE_DRAM_INIT_RECOVERY, agesa_NoopUnsupported},
71 { AGESA_READ_SPD_RECOVERY, agesa_NoopUnsupported },
72
73};
74#endif
75
76const int BiosCalloutsLen = ARRAY_SIZE(BiosCallouts);
77
Richard Spiegel271b8a52018-11-06 16:32:28 -070078AGESA_STATUS GetBiosCallout(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -060079{
Richard Spiegel271b8a52018-11-06 16:32:28 -070080 uintptr_t i;
Marc Jones1587dc82017-05-15 18:55:11 -060081
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060082 for (i = 0 ; i < BiosCalloutsLen ; i++) {
Marc Jones1587dc82017-05-15 18:55:11 -060083 if (BiosCallouts[i].CalloutName == Func)
84 break;
85 }
Marc Jones7e710e02017-10-12 15:19:51 -060086
87 if (i >= BiosCalloutsLen) {
Marshall Dawson492e4db2018-05-01 11:12:51 -060088 printk(BIOS_ERR, "ERROR: AGESA Callout Not Supported: 0x%x\n",
Marc Jones7e710e02017-10-12 15:19:51 -060089 (u32)Func);
Marc Jones1587dc82017-05-15 18:55:11 -060090 return AGESA_UNSUPPORTED;
Marc Jones7e710e02017-10-12 15:19:51 -060091 }
Marc Jones1587dc82017-05-15 18:55:11 -060092
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060093 return BiosCallouts[i].CalloutPtr(Func, Data, ConfigPtr);
Marc Jones1587dc82017-05-15 18:55:11 -060094}
95
Richard Spiegel271b8a52018-11-06 16:32:28 -070096AGESA_STATUS agesa_NoopUnsupported(uint32_t Func, uintptr_t Data,
97 void *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -060098{
99 return AGESA_UNSUPPORTED;
100}
101
Richard Spiegel271b8a52018-11-06 16:32:28 -0700102AGESA_STATUS agesa_NoopSuccess(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600103{
104 return AGESA_SUCCESS;
105}
106
Richard Spiegel271b8a52018-11-06 16:32:28 -0700107AGESA_STATUS agesa_EmptyIdsInitData(uint32_t Func, uintptr_t Data,
108 void *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600109{
110 IDS_NV_ITEM *IdsPtr = ((IDS_CALLOUT_STRUCT *) ConfigPtr)->IdsNvPtr;
111 if (Data == IDS_CALLOUT_INIT)
112 IdsPtr[0].IdsNvValue = IdsPtr[0].IdsNvId = 0xffff;
113 return AGESA_SUCCESS;
114}
115
Richard Spiegel271b8a52018-11-06 16:32:28 -0700116AGESA_STATUS agesa_Reset(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600117{
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600118 AGESA_STATUS Status;
Richard Spiegel271b8a52018-11-06 16:32:28 -0700119 uintptr_t ResetType;
Marc Jones1587dc82017-05-15 18:55:11 -0600120
121 ResetType = Data;
Marc Jones1587dc82017-05-15 18:55:11 -0600122
Marc Jones4f886cc2017-10-11 20:20:49 -0600123 /*
124 * This should perform the RESET based upon the ResetType, but coreboot
125 * doesn't have a reset manager to handle a WHENEVER case. Do all
126 * resets immediately.
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600127 */
Marc Jones1587dc82017-05-15 18:55:11 -0600128 switch (ResetType) {
129 case WARM_RESET_WHENEVER:
Marc Jones1587dc82017-05-15 18:55:11 -0600130 case WARM_RESET_IMMEDIATELY:
Nico Huber73c11192018-10-06 18:20:47 +0200131 warm_reset();
Martin Roth4f92b152017-11-12 10:56:43 -0700132 break;
133
134 case COLD_RESET_WHENEVER:
Marc Jones1587dc82017-05-15 18:55:11 -0600135 case COLD_RESET_IMMEDIATELY:
Nico Huber73c11192018-10-06 18:20:47 +0200136 cold_reset();
Marc Jones1587dc82017-05-15 18:55:11 -0600137 break;
138
139 default:
140 break;
141 }
142
143 Status = 0;
144 return Status;
145}
146
Richard Spiegel271b8a52018-11-06 16:32:28 -0700147AGESA_STATUS agesa_GfxGetVbiosImage(uint32_t Func, uintptr_t FchData,
148 void *ConfigPrt)
Marc Jones1587dc82017-05-15 18:55:11 -0600149{
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600150 GFX_VBIOS_IMAGE_INFO *pVbiosImageInfo;
151
152 pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt;
Marc Jones1587dc82017-05-15 18:55:11 -0600153 pVbiosImageInfo->ImagePtr = cbfs_boot_map_with_leak(
154 "pci"CONFIG_VGA_BIOS_ID".rom",
155 CBFS_TYPE_OPTIONROM, NULL);
Richard Spiegelde332f32018-10-23 14:34:12 -0700156 printk(BIOS_DEBUG, "%s: IMGptr=%p\n", __func__,
157 pVbiosImageInfo->ImagePtr);
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600158 return pVbiosImageInfo->ImagePtr ? AGESA_SUCCESS : AGESA_WARNING;
Marc Jones1587dc82017-05-15 18:55:11 -0600159}
160
Richard Spiegel271b8a52018-11-06 16:32:28 -0700161AGESA_STATUS __weak platform_PcieSlotResetControl(uint32_t Func,
162 uintptr_t Data, void *ConfigPtr)
Marc Jones6e70d672017-10-26 16:42:03 -0600163{
164 printk(BIOS_WARNING, "Warning - AGESA callout: %s not supported\n",
165 __func__);
166 return AGESA_UNSUPPORTED;
167}
168
Richard Spiegel271b8a52018-11-06 16:32:28 -0700169AGESA_STATUS agesa_PcieSlotResetControl(uint32_t Func, uintptr_t Data,
170 void *ConfigPtr)
Martin Rothf80a4312017-09-26 14:45:16 -0600171{
Marc Jones6e70d672017-10-26 16:42:03 -0600172 return platform_PcieSlotResetControl(Func, Data, ConfigPtr);
Martin Rothf80a4312017-09-26 14:45:16 -0600173}
174
Marc Jones33eef132017-10-26 16:50:42 -0600175/*
176 * Application Processor callouts:
177 * agesa_RunFuncOnAp() and agesa_RunFcnOnAllAps() are called after main memory
178 * has been initialized and coreboot has taken control of AP task dispatching.
179 * These functions execute callout_ap_entry() on each AP, which calls the
180 * AmdLateRunApTask() entry point if it is a targeted AP.
181 */
182
183/*
184 * Global data for APs.
185 * Passed from the AGESA_Callout for the agesawrapper_amdlaterunaptask.
186 */
187static struct agesa_data {
Richard Spiegel271b8a52018-11-06 16:32:28 -0700188 uint32_t Func;
189 uintptr_t Data;
Kyösti Mälkki423d03c2018-06-28 21:18:12 +0300190 AP_EXE_PARAMS *ConfigPtr;
Marc Jones33eef132017-10-26 16:50:42 -0600191} agesadata;
192
193/*
194 * BSP deploys APs to callout_ap_entry(), which calls
195 * agesawrapper_amdlaterunaptask with the agesadata.
196 */
Subrata Banik33374972018-04-24 13:45:30 +0530197static void callout_ap_entry(void *unused)
Marc Jones33eef132017-10-26 16:50:42 -0600198{
199 AGESA_STATUS Status = AGESA_UNSUPPORTED;
200
Julius Werner540a9802019-12-09 13:03:29 -0800201 printk(BIOS_DEBUG, "%s Func: 0x%x, Data: 0x%lx, Ptr: %p\n",
Marc Jones33eef132017-10-26 16:50:42 -0600202 __func__, agesadata.Func, agesadata.Data, agesadata.ConfigPtr);
203
204 /* Check if this AP should run the function */
205 if (!((agesadata.Func == AGESA_RUNFUNC_ONAP) &&
206 (agesadata.Data == lapicid())))
207 return;
208
Kyösti Mälkki423d03c2018-06-28 21:18:12 +0300209 Status = amd_late_run_ap_task(agesadata.ConfigPtr);
Marc Jones33eef132017-10-26 16:50:42 -0600210
211 if (Status)
212 printk(BIOS_DEBUG, "There was a problem with %lx returned %s\n",
213 lapicid(), decodeAGESA_STATUS(Status));
214}
215
Richard Spiegel271b8a52018-11-06 16:32:28 -0700216AGESA_STATUS agesa_RunFuncOnAp(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marc Jones33eef132017-10-26 16:50:42 -0600217{
218 printk(BIOS_DEBUG, "%s\n", __func__);
219
220 agesadata.Func = Func;
221 agesadata.Data = Data;
222 agesadata.ConfigPtr = ConfigPtr;
Patrick Rudolphbe207b12019-07-26 14:22:09 +0200223 if (mp_run_on_aps(callout_ap_entry, NULL, MP_RUN_ON_ALL_CPUS, 100 * USECS_PER_MSEC))
224 return AGESA_ERROR;
Marc Jones33eef132017-10-26 16:50:42 -0600225
226 return AGESA_SUCCESS;
227}
228
Richard Spiegel271b8a52018-11-06 16:32:28 -0700229AGESA_STATUS agesa_RunFcnOnAllAps(uint32_t Func, uintptr_t Data,
230 void *ConfigPtr)
Marc Jones33eef132017-10-26 16:50:42 -0600231{
232 printk(BIOS_DEBUG, "%s\n", __func__);
233
234 agesadata.Func = Func;
235 agesadata.Data = Data;
236 agesadata.ConfigPtr = ConfigPtr;
Patrick Rudolphbe207b12019-07-26 14:22:09 +0200237 if (mp_run_on_aps(callout_ap_entry, NULL, MP_RUN_ON_ALL_CPUS, 100 * USECS_PER_MSEC))
238 return AGESA_ERROR;
Marc Jones33eef132017-10-26 16:50:42 -0600239
240 return AGESA_SUCCESS;
241}
242
Richard Spiegel271b8a52018-11-06 16:32:28 -0700243AGESA_STATUS agesa_WaitForAllApsFinished(uint32_t Func, uintptr_t Data,
244 void *ConfigPtr)
Martin Rothf80a4312017-09-26 14:45:16 -0600245{
Marc Jones33eef132017-10-26 16:50:42 -0600246 printk(BIOS_WARNING, "Warning - AGESA callout: %s not supported\n",
247 __func__);
Martin Rothf80a4312017-09-26 14:45:16 -0600248 AGESA_STATUS Status = AGESA_UNSUPPORTED;
249
250 return Status;
251}
252
Richard Spiegel271b8a52018-11-06 16:32:28 -0700253AGESA_STATUS agesa_IdleAnAp(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Martin Rothf80a4312017-09-26 14:45:16 -0600254{
Marc Jones33eef132017-10-26 16:50:42 -0600255 printk(BIOS_WARNING, "Warning - AGESA callout: %s no supported\n",
256 __func__);
Martin Rothf80a4312017-09-26 14:45:16 -0600257 AGESA_STATUS Status = AGESA_UNSUPPORTED;
258
259 return Status;
260}