blob: beb2d18c2e602c55af19a9e6a744c1a0f267b418 [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>
Marc Jones1587dc82017-05-15 18:55:11 -060021#include <amdlib.h>
Richard Spiegel0ad74ac2017-12-08 16:53:29 -070022#include <amdblocks/BiosCallOuts.h>
23#include <amdblocks/agesawrapper.h>
24#include <amdblocks/agesawrapper_call.h>
Martin Roth4f92b152017-11-12 10:56:43 -070025#include <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 },
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 */
38 { AGESA_ALLOCATE_BUFFER, agesa_AllocateBuffer },
39 { AGESA_DEALLOCATE_BUFFER, agesa_DeallocateBuffer },
40 { AGESA_DO_RESET, agesa_Reset },
41 { AGESA_LOCATE_BUFFER, agesa_LocateBuffer },
42 { AGESA_READ_SPD, agesa_ReadSpd },
Marc Jones33eef132017-10-26 16:50:42 -060043 { AGESA_GNB_PCIE_SLOT_RESET, agesa_PcieSlotResetControl },
44#if ENV_RAMSTAGE
Martin Rothc450fbe2017-10-02 13:46:50 -060045 { AGESA_RUNFUNC_ONAP, agesa_RunFuncOnAp },
46 { AGESA_RUNFUNC_ON_ALL_APS, agesa_RunFcnOnAllAps },
Martin Rothc450fbe2017-10-02 13:46:50 -060047 { AGESA_WAIT_FOR_ALL_APS, agesa_WaitForAllApsFinished },
48 { AGESA_IDLE_AN_AP, agesa_IdleAnAp },
Marc Jones33eef132017-10-26 16:50:42 -060049#endif /* ENV_RAMSTAGE */
Martin Rothc450fbe2017-10-02 13:46:50 -060050
51 /* Optional callouts */
52 { AGESA_GET_IDS_INIT_DATA, agesa_EmptyIdsInitData },
53 //AgesaHeapRebase - Hook ID?
54 { AGESA_HOOKBEFORE_DRAM_INIT, agesa_NoopUnsupported },
55 { AGESA_HOOKBEFORE_DQS_TRAINING, agesa_NoopUnsupported },
56 { AGESA_EXTERNAL_2D_TRAIN_VREF_CHANGE, agesa_NoopUnsupported },
57 { AGESA_HOOKBEFORE_EXIT_SELF_REF, agesa_NoopUnsupported },
58 { AGESA_GNB_GFX_GET_VBIOS_IMAGE, agesa_GfxGetVbiosImage },
59 { AGESA_FCH_OEM_CALLOUT, agesa_fch_initenv },
60 { AGESA_EXTERNAL_VOLTAGE_ADJUST, agesa_NoopUnsupported },
61 { AGESA_GNB_PCIE_CLK_REQ, agesa_NoopUnsupported },
62
63 /* Deprecated */
64 { AGESA_HOOKBEFORE_DRAM_INIT_RECOVERY, agesa_NoopUnsupported},
65 { AGESA_READ_SPD_RECOVERY, agesa_NoopUnsupported },
66
67};
68#endif
69
70const int BiosCalloutsLen = ARRAY_SIZE(BiosCallouts);
71
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060072AGESA_STATUS GetBiosCallout(UINT32 Func, UINTN Data, VOID *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -060073{
74 UINTN i;
75
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060076 for (i = 0 ; i < BiosCalloutsLen ; i++) {
Marc Jones1587dc82017-05-15 18:55:11 -060077 if (BiosCallouts[i].CalloutName == Func)
78 break;
79 }
Marc Jones7e710e02017-10-12 15:19:51 -060080
81 if (i >= BiosCalloutsLen) {
82 printk(BIOS_ERR, "ERROR: AGESA Callout Not Supported: 0x%x",
83 (u32)Func);
Marc Jones1587dc82017-05-15 18:55:11 -060084 return AGESA_UNSUPPORTED;
Marc Jones7e710e02017-10-12 15:19:51 -060085 }
Marc Jones1587dc82017-05-15 18:55:11 -060086
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060087 return BiosCallouts[i].CalloutPtr(Func, Data, ConfigPtr);
Marc Jones1587dc82017-05-15 18:55:11 -060088}
89
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060090AGESA_STATUS agesa_NoopUnsupported(UINT32 Func, UINTN Data, VOID *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -060091{
92 return AGESA_UNSUPPORTED;
93}
94
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -060095AGESA_STATUS agesa_NoopSuccess(UINT32 Func, UINTN Data, VOID *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -060096{
97 return AGESA_SUCCESS;
98}
99
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600100AGESA_STATUS agesa_EmptyIdsInitData(UINT32 Func, UINTN Data, VOID *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600101{
102 IDS_NV_ITEM *IdsPtr = ((IDS_CALLOUT_STRUCT *) ConfigPtr)->IdsNvPtr;
103 if (Data == IDS_CALLOUT_INIT)
104 IdsPtr[0].IdsNvValue = IdsPtr[0].IdsNvId = 0xffff;
105 return AGESA_SUCCESS;
106}
107
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600108AGESA_STATUS agesa_Reset(UINT32 Func, UINTN Data, VOID *ConfigPtr)
Marc Jones1587dc82017-05-15 18:55:11 -0600109{
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600110 AGESA_STATUS Status;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600111 UINTN ResetType;
112 AMD_CONFIG_PARAMS *StdHeader;
Marc Jones1587dc82017-05-15 18:55:11 -0600113
114 ResetType = Data;
115 StdHeader = ConfigPtr;
116
Marc Jones4f886cc2017-10-11 20:20:49 -0600117 /*
118 * This should perform the RESET based upon the ResetType, but coreboot
119 * doesn't have a reset manager to handle a WHENEVER case. Do all
120 * resets immediately.
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600121 */
Marc Jones1587dc82017-05-15 18:55:11 -0600122 switch (ResetType) {
123 case WARM_RESET_WHENEVER:
Marc Jones1587dc82017-05-15 18:55:11 -0600124 case WARM_RESET_IMMEDIATELY:
Martin Roth4f92b152017-11-12 10:56:43 -0700125 do_soft_reset();
126 break;
127
128 case COLD_RESET_WHENEVER:
Marc Jones1587dc82017-05-15 18:55:11 -0600129 case COLD_RESET_IMMEDIATELY:
Martin Roth4f92b152017-11-12 10:56:43 -0700130 do_hard_reset();
Marc Jones1587dc82017-05-15 18:55:11 -0600131 break;
132
133 default:
134 break;
135 }
136
137 Status = 0;
138 return Status;
139}
140
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600141AGESA_STATUS agesa_GfxGetVbiosImage(UINT32 Func, UINTN FchData,
142 VOID *ConfigPrt)
Marc Jones1587dc82017-05-15 18:55:11 -0600143{
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600144 GFX_VBIOS_IMAGE_INFO *pVbiosImageInfo;
145
146 pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt;
Marc Jones1587dc82017-05-15 18:55:11 -0600147 pVbiosImageInfo->ImagePtr = cbfs_boot_map_with_leak(
148 "pci"CONFIG_VGA_BIOS_ID".rom",
149 CBFS_TYPE_OPTIONROM, NULL);
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600150 printk(BIOS_DEBUG, "agesa_GfxGetVbiosImage: IMGptr=%p\n",
151 pVbiosImageInfo->ImagePtr);
152 return pVbiosImageInfo->ImagePtr ? AGESA_SUCCESS : AGESA_WARNING;
Marc Jones1587dc82017-05-15 18:55:11 -0600153}
154
Marc Jones6e70d672017-10-26 16:42:03 -0600155AGESA_STATUS __attribute__((weak)) platform_PcieSlotResetControl(UINT32 Func,
156 UINTN Data, VOID *ConfigPtr)
157{
158 printk(BIOS_WARNING, "Warning - AGESA callout: %s not supported\n",
159 __func__);
160 return AGESA_UNSUPPORTED;
161}
162
Martin Rothf80a4312017-09-26 14:45:16 -0600163AGESA_STATUS agesa_PcieSlotResetControl(UINT32 Func, UINTN Data,
164 VOID *ConfigPtr)
165{
Marc Jones6e70d672017-10-26 16:42:03 -0600166 return platform_PcieSlotResetControl(Func, Data, ConfigPtr);
Martin Rothf80a4312017-09-26 14:45:16 -0600167}
168
Marc Jones33eef132017-10-26 16:50:42 -0600169/*
170 * Application Processor callouts:
171 * agesa_RunFuncOnAp() and agesa_RunFcnOnAllAps() are called after main memory
172 * has been initialized and coreboot has taken control of AP task dispatching.
173 * These functions execute callout_ap_entry() on each AP, which calls the
174 * AmdLateRunApTask() entry point if it is a targeted AP.
175 */
176
177/*
178 * Global data for APs.
179 * Passed from the AGESA_Callout for the agesawrapper_amdlaterunaptask.
180 */
181static struct agesa_data {
182 UINT32 Func;
183 UINTN Data;
184 VOID *ConfigPtr;
185} agesadata;
186
187/*
188 * BSP deploys APs to callout_ap_entry(), which calls
189 * agesawrapper_amdlaterunaptask with the agesadata.
190 */
191static void callout_ap_entry(void)
192{
193 AGESA_STATUS Status = AGESA_UNSUPPORTED;
194
195 printk(BIOS_DEBUG, "%s Func: 0x%x, Data: 0x%lx, Ptr: 0x%p \n",
196 __func__, agesadata.Func, agesadata.Data, agesadata.ConfigPtr);
197
198 /* Check if this AP should run the function */
199 if (!((agesadata.Func == AGESA_RUNFUNC_ONAP) &&
200 (agesadata.Data == lapicid())))
201 return;
202
203 Status = agesawrapper_amdlaterunaptask(agesadata.Func, agesadata.Data,
204 agesadata.ConfigPtr);
205
206 if (Status)
207 printk(BIOS_DEBUG, "There was a problem with %lx returned %s\n",
208 lapicid(), decodeAGESA_STATUS(Status));
209}
210
211AGESA_STATUS agesa_RunFuncOnAp(UINT32 Func, UINTN Data, VOID *ConfigPtr)
212{
213 printk(BIOS_DEBUG, "%s\n", __func__);
214
215 agesadata.Func = Func;
216 agesadata.Data = Data;
217 agesadata.ConfigPtr = ConfigPtr;
218 mp_run_on_aps(callout_ap_entry, 100 * USECS_PER_MSEC);
219
220 return AGESA_SUCCESS;
221}
222
223AGESA_STATUS agesa_RunFcnOnAllAps(UINT32 Func, UINTN Data, VOID *ConfigPtr)
224{
225 printk(BIOS_DEBUG, "%s\n", __func__);
226
227 agesadata.Func = Func;
228 agesadata.Data = Data;
229 agesadata.ConfigPtr = ConfigPtr;
230 mp_run_on_aps(callout_ap_entry, 100 * USECS_PER_MSEC);
231
232 return AGESA_SUCCESS;
233}
234
Martin Rothf80a4312017-09-26 14:45:16 -0600235AGESA_STATUS agesa_WaitForAllApsFinished(UINT32 Func, UINTN Data,
236 VOID *ConfigPtr)
237{
Marc Jones33eef132017-10-26 16:50:42 -0600238 printk(BIOS_WARNING, "Warning - AGESA callout: %s not supported\n",
239 __func__);
Martin Rothf80a4312017-09-26 14:45:16 -0600240 AGESA_STATUS Status = AGESA_UNSUPPORTED;
241
242 return Status;
243}
244
245AGESA_STATUS agesa_IdleAnAp(UINT32 Func, UINTN Data, VOID *ConfigPtr)
246{
Marc Jones33eef132017-10-26 16:50:42 -0600247 printk(BIOS_WARNING, "Warning - AGESA callout: %s no supported\n",
248 __func__);
Martin Rothf80a4312017-09-26 14:45:16 -0600249 AGESA_STATUS Status = AGESA_UNSUPPORTED;
250
251 return Status;
252}