blob: 0fffaf345bec598f363f9ffc4dac8d12cdceb3bb [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>
Marc Jones33eef132017-10-26 16:50:42 -060018#include <cpu/x86/lapic.h>
19#include <cpu/x86/mp.h>
20#include <timer.h>
Richard Spiegel0ad74ac2017-12-08 16:53:29 -070021#include <amdblocks/BiosCallOuts.h>
22#include <amdblocks/agesawrapper.h>
23#include <amdblocks/agesawrapper_call.h>
Nico Huber73c11192018-10-06 18:20:47 +020024#include <amdblocks/reset.h>
Marc Jonesdfeb1c42017-08-07 19:08:24 -060025#include <soc/southbridge.h>
Marc Jones1587dc82017-05-15 18:55:11 -060026
Martin Rothc450fbe2017-10-02 13:46:50 -060027#if ENV_BOOTBLOCK
28const BIOS_CALLOUT_STRUCT BiosCallouts[] = {
29 { AGESA_DO_RESET, agesa_Reset },
30 { AGESA_FCH_OEM_CALLOUT, agesa_fch_initreset },
Richard Spiegela9f49362018-03-05 08:11:50 -070031 { AGESA_HALT_THIS_AP, agesa_HaltThisAp },
Marshall Dawsonc150a572018-04-30 17:59:27 -060032 { AGESA_HEAP_REBASE, agesa_HeapRebase },
Martin Rothc450fbe2017-10-02 13:46:50 -060033 { AGESA_GNB_PCIE_SLOT_RESET, agesa_PcieSlotResetControl }
34};
35#else
36const BIOS_CALLOUT_STRUCT BiosCallouts[] = {
37 /* Required callouts */
Richard Spiegel09a16e62018-04-04 12:40:20 -070038#if ENV_ROMSTAGE
39 { AGESA_HALT_THIS_AP, agesa_HaltThisAp },
40#endif
Martin Rothc450fbe2017-10-02 13:46:50 -060041 { AGESA_ALLOCATE_BUFFER, agesa_AllocateBuffer },
42 { AGESA_DEALLOCATE_BUFFER, agesa_DeallocateBuffer },
43 { AGESA_DO_RESET, agesa_Reset },
44 { AGESA_LOCATE_BUFFER, agesa_LocateBuffer },
45 { AGESA_READ_SPD, agesa_ReadSpd },
Marc Jones33eef132017-10-26 16:50:42 -060046 { AGESA_GNB_PCIE_SLOT_RESET, agesa_PcieSlotResetControl },
Marshall Dawson10b52e02018-05-07 08:51:04 -060047 { AGESA_GET_TEMP_HEAP_BASE, agesa_GetTempHeapBase },
Marshall Dawsonc150a572018-04-30 17:59:27 -060048 { AGESA_HEAP_REBASE, agesa_HeapRebase },
Marc Jones33eef132017-10-26 16:50:42 -060049#if ENV_RAMSTAGE
Martin Rothc450fbe2017-10-02 13:46:50 -060050 { AGESA_RUNFUNC_ONAP, agesa_RunFuncOnAp },
51 { AGESA_RUNFUNC_ON_ALL_APS, agesa_RunFcnOnAllAps },
Martin Rothc450fbe2017-10-02 13:46:50 -060052 { AGESA_WAIT_FOR_ALL_APS, agesa_WaitForAllApsFinished },
53 { AGESA_IDLE_AN_AP, agesa_IdleAnAp },
Marc Jones33eef132017-10-26 16:50:42 -060054#endif /* ENV_RAMSTAGE */
Martin Rothc450fbe2017-10-02 13:46:50 -060055
56 /* Optional callouts */
57 { AGESA_GET_IDS_INIT_DATA, agesa_EmptyIdsInitData },
58 //AgesaHeapRebase - Hook ID?
59 { AGESA_HOOKBEFORE_DRAM_INIT, agesa_NoopUnsupported },
60 { AGESA_HOOKBEFORE_DQS_TRAINING, agesa_NoopUnsupported },
61 { AGESA_EXTERNAL_2D_TRAIN_VREF_CHANGE, agesa_NoopUnsupported },
62 { AGESA_HOOKBEFORE_EXIT_SELF_REF, agesa_NoopUnsupported },
63 { AGESA_GNB_GFX_GET_VBIOS_IMAGE, agesa_GfxGetVbiosImage },
64 { AGESA_FCH_OEM_CALLOUT, agesa_fch_initenv },
65 { AGESA_EXTERNAL_VOLTAGE_ADJUST, agesa_NoopUnsupported },
66 { AGESA_GNB_PCIE_CLK_REQ, agesa_NoopUnsupported },
67
68 /* Deprecated */
69 { AGESA_HOOKBEFORE_DRAM_INIT_RECOVERY, agesa_NoopUnsupported},
70 { AGESA_READ_SPD_RECOVERY, agesa_NoopUnsupported },
71
72};
73#endif
74
75const int BiosCalloutsLen = ARRAY_SIZE(BiosCallouts);
76
Richard Spiegel271b8a52018-11-06 16:32:28 -070077AGESA_STATUS GetBiosCallout(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -060078{
Richard Spiegel271b8a52018-11-06 16:32:28 -070079 uintptr_t i;
Marc Jones1587dc82017-05-15 18:55:11 -060080
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060081 for (i = 0 ; i < BiosCalloutsLen ; i++) {
Marc Jones1587dc82017-05-15 18:55:11 -060082 if (BiosCallouts[i].CalloutName == Func)
83 break;
84 }
Marc Jones7e710e02017-10-12 15:19:51 -060085
86 if (i >= BiosCalloutsLen) {
Marshall Dawson492e4db2018-05-01 11:12:51 -060087 printk(BIOS_ERR, "ERROR: AGESA Callout Not Supported: 0x%x\n",
Marc Jones7e710e02017-10-12 15:19:51 -060088 (u32)Func);
Marc Jones1587dc82017-05-15 18:55:11 -060089 return AGESA_UNSUPPORTED;
Marc Jones7e710e02017-10-12 15:19:51 -060090 }
Marc Jones1587dc82017-05-15 18:55:11 -060091
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060092 return BiosCallouts[i].CalloutPtr(Func, Data, ConfigPtr);
Marc Jones1587dc82017-05-15 18:55:11 -060093}
94
Richard Spiegel271b8a52018-11-06 16:32:28 -070095AGESA_STATUS agesa_NoopUnsupported(uint32_t Func, uintptr_t Data,
96 void *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -060097{
98 return AGESA_UNSUPPORTED;
99}
100
Richard Spiegel271b8a52018-11-06 16:32:28 -0700101AGESA_STATUS agesa_NoopSuccess(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600102{
103 return AGESA_SUCCESS;
104}
105
Richard Spiegel271b8a52018-11-06 16:32:28 -0700106AGESA_STATUS agesa_EmptyIdsInitData(uint32_t Func, uintptr_t Data,
107 void *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600108{
109 IDS_NV_ITEM *IdsPtr = ((IDS_CALLOUT_STRUCT *) ConfigPtr)->IdsNvPtr;
110 if (Data == IDS_CALLOUT_INIT)
111 IdsPtr[0].IdsNvValue = IdsPtr[0].IdsNvId = 0xffff;
112 return AGESA_SUCCESS;
113}
114
Richard Spiegel271b8a52018-11-06 16:32:28 -0700115AGESA_STATUS agesa_Reset(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600116{
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600117 AGESA_STATUS Status;
Richard Spiegel271b8a52018-11-06 16:32:28 -0700118 uintptr_t ResetType;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600119 AMD_CONFIG_PARAMS *StdHeader;
Marc Jones1587dc82017-05-15 18:55:11 -0600120
121 ResetType = Data;
122 StdHeader = ConfigPtr;
123
Marc Jones4f886cc2017-10-11 20:20:49 -0600124 /*
125 * This should perform the RESET based upon the ResetType, but coreboot
126 * doesn't have a reset manager to handle a WHENEVER case. Do all
127 * resets immediately.
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600128 */
Marc Jones1587dc82017-05-15 18:55:11 -0600129 switch (ResetType) {
130 case WARM_RESET_WHENEVER:
Marc Jones1587dc82017-05-15 18:55:11 -0600131 case WARM_RESET_IMMEDIATELY:
Nico Huber73c11192018-10-06 18:20:47 +0200132 warm_reset();
Martin Roth4f92b152017-11-12 10:56:43 -0700133 break;
134
135 case COLD_RESET_WHENEVER:
Marc Jones1587dc82017-05-15 18:55:11 -0600136 case COLD_RESET_IMMEDIATELY:
Nico Huber73c11192018-10-06 18:20:47 +0200137 cold_reset();
Marc Jones1587dc82017-05-15 18:55:11 -0600138 break;
139
140 default:
141 break;
142 }
143
144 Status = 0;
145 return Status;
146}
147
Richard Spiegel271b8a52018-11-06 16:32:28 -0700148AGESA_STATUS agesa_GfxGetVbiosImage(uint32_t Func, uintptr_t FchData,
149 void *ConfigPrt)
Marc Jones1587dc82017-05-15 18:55:11 -0600150{
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600151 GFX_VBIOS_IMAGE_INFO *pVbiosImageInfo;
152
153 pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt;
Marc Jones1587dc82017-05-15 18:55:11 -0600154 pVbiosImageInfo->ImagePtr = cbfs_boot_map_with_leak(
155 "pci"CONFIG_VGA_BIOS_ID".rom",
156 CBFS_TYPE_OPTIONROM, NULL);
Richard Spiegelde332f32018-10-23 14:34:12 -0700157 printk(BIOS_DEBUG, "%s: IMGptr=%p\n", __func__,
158 pVbiosImageInfo->ImagePtr);
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600159 return pVbiosImageInfo->ImagePtr ? AGESA_SUCCESS : AGESA_WARNING;
Marc Jones1587dc82017-05-15 18:55:11 -0600160}
161
Richard Spiegel271b8a52018-11-06 16:32:28 -0700162AGESA_STATUS __weak platform_PcieSlotResetControl(uint32_t Func,
163 uintptr_t Data, void *ConfigPtr)
Marc Jones6e70d672017-10-26 16:42:03 -0600164{
165 printk(BIOS_WARNING, "Warning - AGESA callout: %s not supported\n",
166 __func__);
167 return AGESA_UNSUPPORTED;
168}
169
Richard Spiegel271b8a52018-11-06 16:32:28 -0700170AGESA_STATUS agesa_PcieSlotResetControl(uint32_t Func, uintptr_t Data,
171 void *ConfigPtr)
Martin Rothf80a4312017-09-26 14:45:16 -0600172{
Marc Jones6e70d672017-10-26 16:42:03 -0600173 return platform_PcieSlotResetControl(Func, Data, ConfigPtr);
Martin Rothf80a4312017-09-26 14:45:16 -0600174}
175
Marc Jones33eef132017-10-26 16:50:42 -0600176/*
177 * Application Processor callouts:
178 * agesa_RunFuncOnAp() and agesa_RunFcnOnAllAps() are called after main memory
179 * has been initialized and coreboot has taken control of AP task dispatching.
180 * These functions execute callout_ap_entry() on each AP, which calls the
181 * AmdLateRunApTask() entry point if it is a targeted AP.
182 */
183
184/*
185 * Global data for APs.
186 * Passed from the AGESA_Callout for the agesawrapper_amdlaterunaptask.
187 */
188static struct agesa_data {
Richard Spiegel271b8a52018-11-06 16:32:28 -0700189 uint32_t Func;
190 uintptr_t Data;
191 void *ConfigPtr;
Marc Jones33eef132017-10-26 16:50:42 -0600192} agesadata;
193
194/*
195 * BSP deploys APs to callout_ap_entry(), which calls
196 * agesawrapper_amdlaterunaptask with the agesadata.
197 */
Subrata Banik33374972018-04-24 13:45:30 +0530198static void callout_ap_entry(void *unused)
Marc Jones33eef132017-10-26 16:50:42 -0600199{
200 AGESA_STATUS Status = AGESA_UNSUPPORTED;
201
Elyes HAOUASb0f19882018-06-09 11:59:00 +0200202 printk(BIOS_DEBUG, "%s Func: 0x%x, Data: 0x%lx, Ptr: 0x%p\n",
Marc Jones33eef132017-10-26 16:50:42 -0600203 __func__, agesadata.Func, agesadata.Data, agesadata.ConfigPtr);
204
205 /* Check if this AP should run the function */
206 if (!((agesadata.Func == AGESA_RUNFUNC_ONAP) &&
207 (agesadata.Data == lapicid())))
208 return;
209
210 Status = agesawrapper_amdlaterunaptask(agesadata.Func, agesadata.Data,
211 agesadata.ConfigPtr);
212
213 if (Status)
214 printk(BIOS_DEBUG, "There was a problem with %lx returned %s\n",
215 lapicid(), decodeAGESA_STATUS(Status));
216}
217
Richard Spiegel271b8a52018-11-06 16:32:28 -0700218AGESA_STATUS agesa_RunFuncOnAp(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marc Jones33eef132017-10-26 16:50:42 -0600219{
220 printk(BIOS_DEBUG, "%s\n", __func__);
221
222 agesadata.Func = Func;
223 agesadata.Data = Data;
224 agesadata.ConfigPtr = ConfigPtr;
Subrata Banik8a25cae2018-05-03 18:48:41 +0530225 mp_run_on_aps(callout_ap_entry, NULL, MP_RUN_ON_ALL_CPUS,
226 100 * USECS_PER_MSEC);
Marc Jones33eef132017-10-26 16:50:42 -0600227
228 return AGESA_SUCCESS;
229}
230
Richard Spiegel271b8a52018-11-06 16:32:28 -0700231AGESA_STATUS agesa_RunFcnOnAllAps(uint32_t Func, uintptr_t Data,
232 void *ConfigPtr)
Marc Jones33eef132017-10-26 16:50:42 -0600233{
234 printk(BIOS_DEBUG, "%s\n", __func__);
235
236 agesadata.Func = Func;
237 agesadata.Data = Data;
238 agesadata.ConfigPtr = ConfigPtr;
Subrata Banik8a25cae2018-05-03 18:48:41 +0530239 mp_run_on_aps(callout_ap_entry, NULL, MP_RUN_ON_ALL_CPUS,
240 100 * USECS_PER_MSEC);
Marc Jones33eef132017-10-26 16:50:42 -0600241
242 return AGESA_SUCCESS;
243}
244
Richard Spiegel271b8a52018-11-06 16:32:28 -0700245AGESA_STATUS agesa_WaitForAllApsFinished(uint32_t Func, uintptr_t Data,
246 void *ConfigPtr)
Martin Rothf80a4312017-09-26 14:45:16 -0600247{
Marc Jones33eef132017-10-26 16:50:42 -0600248 printk(BIOS_WARNING, "Warning - AGESA callout: %s not supported\n",
249 __func__);
Martin Rothf80a4312017-09-26 14:45:16 -0600250 AGESA_STATUS Status = AGESA_UNSUPPORTED;
251
252 return Status;
253}
254
Richard Spiegel271b8a52018-11-06 16:32:28 -0700255AGESA_STATUS agesa_IdleAnAp(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Martin Rothf80a4312017-09-26 14:45:16 -0600256{
Marc Jones33eef132017-10-26 16:50:42 -0600257 printk(BIOS_WARNING, "Warning - AGESA callout: %s no supported\n",
258 __func__);
Martin Rothf80a4312017-09-26 14:45:16 -0600259 AGESA_STATUS Status = AGESA_UNSUPPORTED;
260
261 return Status;
262}