blob: 0afa82517d2492cd836e828a387b96e0877455f8 [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>
Aaron Durbin64031672018-04-21 14:45:32 -060018#include <compiler.h>
Marc Jones33eef132017-10-26 16:50:42 -060019#include <cpu/x86/lapic.h>
20#include <cpu/x86/mp.h>
21#include <timer.h>
Marc Jones1587dc82017-05-15 18:55:11 -060022#include <amdlib.h>
Richard Spiegel0ad74ac2017-12-08 16:53:29 -070023#include <amdblocks/BiosCallOuts.h>
24#include <amdblocks/agesawrapper.h>
25#include <amdblocks/agesawrapper_call.h>
Martin Roth4f92b152017-11-12 10:56:43 -070026#include <reset.h>
Marc Jonesdfeb1c42017-08-07 19:08:24 -060027#include <soc/southbridge.h>
Marc Jones1587dc82017-05-15 18:55:11 -060028
Martin Rothc450fbe2017-10-02 13:46:50 -060029#if ENV_BOOTBLOCK
30const BIOS_CALLOUT_STRUCT BiosCallouts[] = {
31 { AGESA_DO_RESET, agesa_Reset },
32 { AGESA_FCH_OEM_CALLOUT, agesa_fch_initreset },
Richard Spiegela9f49362018-03-05 08:11:50 -070033 { AGESA_HALT_THIS_AP, agesa_HaltThisAp },
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 },
48#if ENV_RAMSTAGE
Martin Rothc450fbe2017-10-02 13:46:50 -060049 { AGESA_RUNFUNC_ONAP, agesa_RunFuncOnAp },
50 { AGESA_RUNFUNC_ON_ALL_APS, agesa_RunFcnOnAllAps },
Martin Rothc450fbe2017-10-02 13:46:50 -060051 { AGESA_WAIT_FOR_ALL_APS, agesa_WaitForAllApsFinished },
52 { AGESA_IDLE_AN_AP, agesa_IdleAnAp },
Marc Jones33eef132017-10-26 16:50:42 -060053#endif /* ENV_RAMSTAGE */
Martin Rothc450fbe2017-10-02 13:46:50 -060054
55 /* Optional callouts */
56 { AGESA_GET_IDS_INIT_DATA, agesa_EmptyIdsInitData },
57 //AgesaHeapRebase - Hook ID?
58 { AGESA_HOOKBEFORE_DRAM_INIT, agesa_NoopUnsupported },
59 { AGESA_HOOKBEFORE_DQS_TRAINING, agesa_NoopUnsupported },
60 { AGESA_EXTERNAL_2D_TRAIN_VREF_CHANGE, agesa_NoopUnsupported },
61 { AGESA_HOOKBEFORE_EXIT_SELF_REF, agesa_NoopUnsupported },
62 { AGESA_GNB_GFX_GET_VBIOS_IMAGE, agesa_GfxGetVbiosImage },
63 { AGESA_FCH_OEM_CALLOUT, agesa_fch_initenv },
64 { AGESA_EXTERNAL_VOLTAGE_ADJUST, agesa_NoopUnsupported },
65 { AGESA_GNB_PCIE_CLK_REQ, agesa_NoopUnsupported },
66
67 /* Deprecated */
68 { AGESA_HOOKBEFORE_DRAM_INIT_RECOVERY, agesa_NoopUnsupported},
69 { AGESA_READ_SPD_RECOVERY, agesa_NoopUnsupported },
70
71};
72#endif
73
74const int BiosCalloutsLen = ARRAY_SIZE(BiosCallouts);
75
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060076AGESA_STATUS GetBiosCallout(UINT32 Func, UINTN Data, VOID *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -060077{
78 UINTN i;
79
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060080 for (i = 0 ; i < BiosCalloutsLen ; i++) {
Marc Jones1587dc82017-05-15 18:55:11 -060081 if (BiosCallouts[i].CalloutName == Func)
82 break;
83 }
Marc Jones7e710e02017-10-12 15:19:51 -060084
85 if (i >= BiosCalloutsLen) {
Marshall Dawson492e4db2018-05-01 11:12:51 -060086 printk(BIOS_ERR, "ERROR: AGESA Callout Not Supported: 0x%x\n",
Marc Jones7e710e02017-10-12 15:19:51 -060087 (u32)Func);
Marc Jones1587dc82017-05-15 18:55:11 -060088 return AGESA_UNSUPPORTED;
Marc Jones7e710e02017-10-12 15:19:51 -060089 }
Marc Jones1587dc82017-05-15 18:55:11 -060090
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060091 return BiosCallouts[i].CalloutPtr(Func, Data, ConfigPtr);
Marc Jones1587dc82017-05-15 18:55:11 -060092}
93
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060094AGESA_STATUS agesa_NoopUnsupported(UINT32 Func, UINTN Data, VOID *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -060095{
96 return AGESA_UNSUPPORTED;
97}
98
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060099AGESA_STATUS agesa_NoopSuccess(UINT32 Func, UINTN Data, VOID *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600100{
101 return AGESA_SUCCESS;
102}
103
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600104AGESA_STATUS agesa_EmptyIdsInitData(UINT32 Func, UINTN Data, VOID *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600105{
106 IDS_NV_ITEM *IdsPtr = ((IDS_CALLOUT_STRUCT *) ConfigPtr)->IdsNvPtr;
107 if (Data == IDS_CALLOUT_INIT)
108 IdsPtr[0].IdsNvValue = IdsPtr[0].IdsNvId = 0xffff;
109 return AGESA_SUCCESS;
110}
111
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600112AGESA_STATUS agesa_Reset(UINT32 Func, UINTN Data, VOID *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600113{
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600114 AGESA_STATUS Status;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600115 UINTN ResetType;
116 AMD_CONFIG_PARAMS *StdHeader;
Marc Jones1587dc82017-05-15 18:55:11 -0600117
118 ResetType = Data;
119 StdHeader = ConfigPtr;
120
Marc Jones4f886cc2017-10-11 20:20:49 -0600121 /*
122 * This should perform the RESET based upon the ResetType, but coreboot
123 * doesn't have a reset manager to handle a WHENEVER case. Do all
124 * resets immediately.
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600125 */
Marc Jones1587dc82017-05-15 18:55:11 -0600126 switch (ResetType) {
127 case WARM_RESET_WHENEVER:
Marc Jones1587dc82017-05-15 18:55:11 -0600128 case WARM_RESET_IMMEDIATELY:
Martin Roth4f92b152017-11-12 10:56:43 -0700129 do_soft_reset();
130 break;
131
132 case COLD_RESET_WHENEVER:
Marc Jones1587dc82017-05-15 18:55:11 -0600133 case COLD_RESET_IMMEDIATELY:
Martin Roth4f92b152017-11-12 10:56:43 -0700134 do_hard_reset();
Marc Jones1587dc82017-05-15 18:55:11 -0600135 break;
136
137 default:
138 break;
139 }
140
141 Status = 0;
142 return Status;
143}
144
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600145AGESA_STATUS agesa_GfxGetVbiosImage(UINT32 Func, UINTN FchData,
146 VOID *ConfigPrt)
Marc Jones1587dc82017-05-15 18:55:11 -0600147{
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600148 GFX_VBIOS_IMAGE_INFO *pVbiosImageInfo;
149
150 pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt;
Marc Jones1587dc82017-05-15 18:55:11 -0600151 pVbiosImageInfo->ImagePtr = cbfs_boot_map_with_leak(
152 "pci"CONFIG_VGA_BIOS_ID".rom",
153 CBFS_TYPE_OPTIONROM, NULL);
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600154 printk(BIOS_DEBUG, "agesa_GfxGetVbiosImage: IMGptr=%p\n",
155 pVbiosImageInfo->ImagePtr);
156 return pVbiosImageInfo->ImagePtr ? AGESA_SUCCESS : AGESA_WARNING;
Marc Jones1587dc82017-05-15 18:55:11 -0600157}
158
Aaron Durbin64031672018-04-21 14:45:32 -0600159AGESA_STATUS __weak platform_PcieSlotResetControl(UINT32 Func,
Marc Jones6e70d672017-10-26 16:42:03 -0600160 UINTN Data, VOID *ConfigPtr)
161{
162 printk(BIOS_WARNING, "Warning - AGESA callout: %s not supported\n",
163 __func__);
164 return AGESA_UNSUPPORTED;
165}
166
Martin Rothf80a4312017-09-26 14:45:16 -0600167AGESA_STATUS agesa_PcieSlotResetControl(UINT32 Func, UINTN Data,
168 VOID *ConfigPtr)
169{
Marc Jones6e70d672017-10-26 16:42:03 -0600170 return platform_PcieSlotResetControl(Func, Data, ConfigPtr);
Martin Rothf80a4312017-09-26 14:45:16 -0600171}
172
Marc Jones33eef132017-10-26 16:50:42 -0600173/*
174 * Application Processor callouts:
175 * agesa_RunFuncOnAp() and agesa_RunFcnOnAllAps() are called after main memory
176 * has been initialized and coreboot has taken control of AP task dispatching.
177 * These functions execute callout_ap_entry() on each AP, which calls the
178 * AmdLateRunApTask() entry point if it is a targeted AP.
179 */
180
181/*
182 * Global data for APs.
183 * Passed from the AGESA_Callout for the agesawrapper_amdlaterunaptask.
184 */
185static struct agesa_data {
186 UINT32 Func;
187 UINTN Data;
188 VOID *ConfigPtr;
189} agesadata;
190
191/*
192 * BSP deploys APs to callout_ap_entry(), which calls
193 * agesawrapper_amdlaterunaptask with the agesadata.
194 */
Subrata Banik33374972018-04-24 13:45:30 +0530195static void callout_ap_entry(void *unused)
Marc Jones33eef132017-10-26 16:50:42 -0600196{
197 AGESA_STATUS Status = AGESA_UNSUPPORTED;
198
199 printk(BIOS_DEBUG, "%s Func: 0x%x, Data: 0x%lx, Ptr: 0x%p \n",
200 __func__, agesadata.Func, agesadata.Data, agesadata.ConfigPtr);
201
202 /* Check if this AP should run the function */
203 if (!((agesadata.Func == AGESA_RUNFUNC_ONAP) &&
204 (agesadata.Data == lapicid())))
205 return;
206
207 Status = agesawrapper_amdlaterunaptask(agesadata.Func, agesadata.Data,
208 agesadata.ConfigPtr);
209
210 if (Status)
211 printk(BIOS_DEBUG, "There was a problem with %lx returned %s\n",
212 lapicid(), decodeAGESA_STATUS(Status));
213}
214
215AGESA_STATUS agesa_RunFuncOnAp(UINT32 Func, UINTN Data, VOID *ConfigPtr)
216{
217 printk(BIOS_DEBUG, "%s\n", __func__);
218
219 agesadata.Func = Func;
220 agesadata.Data = Data;
221 agesadata.ConfigPtr = ConfigPtr;
Subrata Banik33374972018-04-24 13:45:30 +0530222 mp_run_on_aps(callout_ap_entry, NULL, 100 * USECS_PER_MSEC);
Marc Jones33eef132017-10-26 16:50:42 -0600223
224 return AGESA_SUCCESS;
225}
226
227AGESA_STATUS agesa_RunFcnOnAllAps(UINT32 Func, UINTN Data, VOID *ConfigPtr)
228{
229 printk(BIOS_DEBUG, "%s\n", __func__);
230
231 agesadata.Func = Func;
232 agesadata.Data = Data;
233 agesadata.ConfigPtr = ConfigPtr;
Subrata Banik33374972018-04-24 13:45:30 +0530234 mp_run_on_aps(callout_ap_entry, NULL, 100 * USECS_PER_MSEC);
Marc Jones33eef132017-10-26 16:50:42 -0600235
236 return AGESA_SUCCESS;
237}
238
Martin Rothf80a4312017-09-26 14:45:16 -0600239AGESA_STATUS agesa_WaitForAllApsFinished(UINT32 Func, UINTN Data,
240 VOID *ConfigPtr)
241{
Marc Jones33eef132017-10-26 16:50:42 -0600242 printk(BIOS_WARNING, "Warning - AGESA callout: %s not supported\n",
243 __func__);
Martin Rothf80a4312017-09-26 14:45:16 -0600244 AGESA_STATUS Status = AGESA_UNSUPPORTED;
245
246 return Status;
247}
248
249AGESA_STATUS agesa_IdleAnAp(UINT32 Func, UINTN Data, VOID *ConfigPtr)
250{
Marc Jones33eef132017-10-26 16:50:42 -0600251 printk(BIOS_WARNING, "Warning - AGESA callout: %s no supported\n",
252 __func__);
Martin Rothf80a4312017-09-26 14:45:16 -0600253 AGESA_STATUS Status = AGESA_UNSUPPORTED;
254
255 return Status;
256}