1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <console/console.h>
4 #include <timestamp.h>
5 #include <amdblocks/biosram.h>
6 #include <amdblocks/s3_resume.h>
7 #include <amdblocks/agesawrapper.h>
8 #include <amdblocks/BiosCallOuts.h>
9 #include <amdblocks/ioapic.h>
10 #include <soc/pci_devs.h>
11 #include <soc/northbridge.h>
12 #include <soc/cpu.h>
13 #include <string.h>
14
SetMemParams(AMD_POST_PARAMS * PostParams)15 void __weak SetMemParams(AMD_POST_PARAMS *PostParams) {}
OemPostParams(AMD_POST_PARAMS * PostParams)16 void __weak OemPostParams(AMD_POST_PARAMS *PostParams) {}
17
18 /* ACPI table pointers returned by AmdInitLate */
19 static void *DmiTable;
20 static void *AcpiPstate;
21 static void *AcpiSrat;
22 static void *AcpiSlit;
23
24 static void *AcpiWheaMce;
25 static void *AcpiWheaCmc;
26 static void *AcpiAlib;
27 static void *AcpiIvrs;
28 static void *AcpiCrat;
29
module_dispatch(AGESA_STRUCT_NAME func,AMD_CONFIG_PARAMS * StdHeader)30 static AGESA_STATUS module_dispatch(AGESA_STRUCT_NAME func,
31 AMD_CONFIG_PARAMS *StdHeader)
32 {
33 MODULE_ENTRY dispatcher = agesa_get_dispatcher();
34
35 if (!dispatcher)
36 return AGESA_UNSUPPORTED;
37
38 StdHeader->Func = func;
39 return dispatcher(StdHeader);
40 }
41
amd_dispatch(void * Params)42 static AGESA_STATUS amd_dispatch(void *Params)
43 {
44 AMD_CONFIG_PARAMS *StdHeader = Params;
45 return module_dispatch(StdHeader->Func, StdHeader);
46 }
47
amd_late_run_ap_task(AP_EXE_PARAMS * ApExeParams)48 AGESA_STATUS amd_late_run_ap_task(AP_EXE_PARAMS *ApExeParams)
49 {
50 AMD_CONFIG_PARAMS *StdHeader = (void *)ApExeParams;
51 return module_dispatch(AMD_LATE_RUN_AP_TASK, StdHeader);
52 }
53
amd_create_struct(AMD_INTERFACE_PARAMS * aip,AGESA_STRUCT_NAME func,void * buf,size_t len)54 static AGESA_STATUS amd_create_struct(AMD_INTERFACE_PARAMS *aip,
55 AGESA_STRUCT_NAME func, void *buf, size_t len)
56 {
57 AGESA_STATUS status;
58
59 /* Should clone entire StdHeader here. */
60 memset(aip, 0, sizeof(*aip));
61 aip->StdHeader.CalloutPtr = &GetBiosCallout;
62
63 /* If we provide the buffer, API expects it to have
64 StdHeader already filled. */
65 if (buf != NULL && len >= sizeof(aip->StdHeader)) {
66 memcpy(buf, &aip->StdHeader, sizeof(aip->StdHeader));
67 aip->AllocationMethod = ByHost;
68 aip->NewStructPtr = buf;
69 aip->NewStructSize = len;
70 } else {
71 if (ENV_RAMINIT)
72 aip->AllocationMethod = PreMemHeap;
73 if (ENV_RAMSTAGE)
74 aip->AllocationMethod = PostMemDram;
75 }
76
77 aip->AgesaFunctionName = func;
78 status = module_dispatch(AMD_CREATE_STRUCT, &aip->StdHeader);
79
80 if (status != AGESA_SUCCESS) {
81 printk(BIOS_ERR, "AmdCreateStruct() for 0x%x returned 0x%x. "
82 "Proper system initialization may not be possible.\n",
83 aip->AgesaFunctionName, status);
84 }
85
86 if (!aip->NewStructPtr)
87 die("No AGESA structure created");
88
89 return status;
90 }
91
amd_release_struct(AMD_INTERFACE_PARAMS * aip)92 static AGESA_STATUS amd_release_struct(AMD_INTERFACE_PARAMS *aip)
93 {
94 return module_dispatch(AMD_RELEASE_STRUCT, &aip->StdHeader);
95 }
96
amd_init_reset(AMD_RESET_PARAMS * ResetParams)97 static AGESA_STATUS amd_init_reset(AMD_RESET_PARAMS *ResetParams)
98 {
99 AGESA_STATUS status;
100
101 SetFchResetParams(&ResetParams->FchInterface);
102
103 timestamp_add_now(TS_AGESA_INIT_RESET_START);
104 status = amd_dispatch(ResetParams);
105 timestamp_add_now(TS_AGESA_INIT_RESET_END);
106
107 return status;
108 }
109
amd_init_early(AMD_EARLY_PARAMS * EarlyParams)110 static AGESA_STATUS amd_init_early(AMD_EARLY_PARAMS *EarlyParams)
111 {
112 AGESA_STATUS status;
113
114 soc_customize_init_early(EarlyParams);
115 OemCustomizeInitEarly(EarlyParams);
116
117 timestamp_add_now(TS_AGESA_INIT_EARLY_START);
118 status = amd_dispatch(EarlyParams);
119 timestamp_add_now(TS_AGESA_INIT_EARLY_END);
120
121 return status;
122 }
123
print_init_post_settings(AMD_POST_PARAMS * parms)124 static void print_init_post_settings(AMD_POST_PARAMS *parms)
125 {
126 u64 syslimit, bottomio, uma_size, uma_start;
127 const char *mode;
128
129 switch (parms->MemConfig.UmaMode) {
130 case UMA_AUTO:
131 mode = "UMA_AUTO";
132 break;
133 case UMA_SPECIFIED:
134 mode = "UMA_SPECIFIED";
135 break;
136 case UMA_NONE:
137 mode = "UMA_NONE";
138 break;
139 default:
140 mode = "unknown!";
141 break;
142 }
143
144 syslimit = (u64)(parms->MemConfig.SysLimit + 1) * 64 * KiB - 1;
145 bottomio = (u64)parms->MemConfig.BottomIo * 64 * KiB;
146
147 uma_size = (u64)parms->MemConfig.UmaSize * 64 * KiB;
148 uma_start = (u64)parms->MemConfig.UmaBase * 64 * KiB;
149
150 printk(BIOS_SPEW, "AGESA set: umamode %s\n", mode);
151 printk(BIOS_SPEW, " : syslimit 0x%llx, bottomio 0x%08llx\n",
152 syslimit, bottomio);
153 printk(BIOS_SPEW, " : uma size %lluMB, uma start 0x%08llx\n",
154 uma_size / MiB, uma_start);
155 }
156
amd_init_post(AMD_POST_PARAMS * PostParams)157 static AGESA_STATUS amd_init_post(AMD_POST_PARAMS *PostParams)
158 {
159 AGESA_STATUS status;
160
161 PostParams->MemConfig.UmaMode = CONFIG(GFXUMA) ? UMA_AUTO : UMA_NONE;
162 PostParams->MemConfig.UmaSize = 0;
163 PostParams->MemConfig.BottomIo = (uint16_t)
164 (CONFIG_BOTTOMIO_POSITION >> 24);
165
166 SetMemParams(PostParams);
167 OemPostParams(PostParams);
168 printk(BIOS_SPEW, "DRAM clear on reset: %s\n",
169 (PostParams->MemConfig.EnableMemClr == FALSE) ? "Keep" :
170 (PostParams->MemConfig.EnableMemClr == TRUE) ? "Clear" :
171 "unknown"
172 );
173
174 timestamp_add_now(TS_AGESA_INIT_POST_START);
175 status = amd_dispatch(PostParams);
176 timestamp_add_now(TS_AGESA_INIT_POST_END);
177
178 /*
179 * AGESA passes back the base and size of UMA. This is the only
180 * opportunity to get and save these settings to be used in resource
181 * allocation. We also need to allocate the top of low memory.
182 * If UMA is below 4GiB, UMA base is the top of low memory, otherwise
183 * Sub4GCachetop is the top of low memory.
184 * With UMA_NONE we see UmaBase==0.
185 */
186 uintptr_t top;
187 if (PostParams->MemConfig.UmaBase &&
188 (PostParams->MemConfig.UmaBase < ((4ull * GiB) >> 16)))
189 top = PostParams->MemConfig.UmaBase << 16;
190 else
191 top = PostParams->MemConfig.Sub4GCacheTop;
192 backup_top_of_low_cacheable(top);
193
194 save_uma_size(PostParams->MemConfig.UmaSize * 64 * KiB);
195 save_uma_base((u64)PostParams->MemConfig.UmaBase * 64 * KiB);
196
197 print_init_post_settings(PostParams);
198
199 return status;
200 }
201
amd_init_env(AMD_ENV_PARAMS * EnvParams)202 static AGESA_STATUS amd_init_env(AMD_ENV_PARAMS *EnvParams)
203 {
204 AGESA_STATUS status;
205
206 SetFchEnvParams(&EnvParams->FchInterface);
207 SetNbEnvParams(&EnvParams->GnbEnvConfiguration);
208
209 timestamp_add_now(TS_AGESA_INIT_ENV_START);
210 status = amd_dispatch(EnvParams);
211 timestamp_add_now(TS_AGESA_INIT_ENV_END);
212
213 return status;
214 }
215
agesawrapper_getlateinitptr(int pick)216 void *agesawrapper_getlateinitptr(int pick)
217 {
218 switch (pick) {
219 case PICK_DMI:
220 return DmiTable;
221 case PICK_PSTATE:
222 return AcpiPstate;
223 case PICK_SRAT:
224 return AcpiSrat;
225 case PICK_SLIT:
226 return AcpiSlit;
227 case PICK_WHEA_MCE:
228 return AcpiWheaMce;
229 case PICK_WHEA_CMC:
230 return AcpiWheaCmc;
231 case PICK_ALIB:
232 return AcpiAlib;
233 case PICK_IVRS:
234 return AcpiIvrs;
235 case PICK_CRAT:
236 return AcpiCrat;
237 default:
238 return NULL;
239 }
240 }
241
amd_init_mid(AMD_MID_PARAMS * MidParams)242 static AGESA_STATUS amd_init_mid(AMD_MID_PARAMS *MidParams)
243 {
244 AGESA_STATUS status;
245
246 /* Enable MMIO on AMD CPU Address Map Controller */
247 amd_initcpuio();
248
249 SetFchMidParams(&MidParams->FchInterface);
250 SetNbMidParams(&MidParams->GnbMidConfiguration);
251
252 timestamp_add_now(TS_AGESA_INIT_MID_START);
253 status = amd_dispatch(MidParams);
254 timestamp_add_now(TS_AGESA_INIT_MID_END);
255
256 return status;
257 }
258
amd_init_late(AMD_LATE_PARAMS * LateParams)259 static AGESA_STATUS amd_init_late(AMD_LATE_PARAMS *LateParams)
260 {
261 AGESA_STATUS Status;
262
263 if (is_dev_enabled(DEV_PTR(iommu))) {
264 LateParams->GnbLateConfiguration.GnbIoapicId = GNB_IOAPIC_ID;
265 LateParams->GnbLateConfiguration.FchIoapicId = FCH_IOAPIC_ID;
266 }
267
268 /* Make binaryPI use \_SB_ as processor object scope in PSTATE SSDT */
269 LateParams->PlatformConfig.ProcessorScopeInSb = true;
270
271 timestamp_add_now(TS_AGESA_INIT_LATE_START);
272 Status = amd_dispatch(LateParams);
273 timestamp_add_now(TS_AGESA_INIT_LATE_END);
274
275 DmiTable = LateParams->DmiTable;
276 AcpiPstate = LateParams->AcpiPState;
277
278 AcpiWheaMce = LateParams->AcpiWheaMce;
279 AcpiWheaCmc = LateParams->AcpiWheaCmc;
280 AcpiAlib = LateParams->AcpiAlib;
281 AcpiIvrs = LateParams->AcpiIvrs;
282 AcpiCrat = LateParams->AcpiCrat;
283
284 printk(BIOS_DEBUG, "DmiTable:%p, AcpiPstatein: %p, AcpiSrat:%p,"
285 "AcpiSlit:%p, Mce:%p, Cmc:%p,"
286 "Alib:%p, AcpiIvrs:%p in %s\n",
287 DmiTable, AcpiPstate, AcpiSrat,
288 AcpiSlit, AcpiWheaMce, AcpiWheaCmc,
289 AcpiAlib, AcpiIvrs, __func__);
290
291 return Status;
292 }
293
amd_init_rtb(AMD_RTB_PARAMS * RtbParams)294 static AGESA_STATUS amd_init_rtb(AMD_RTB_PARAMS *RtbParams)
295 {
296 AGESA_STATUS Status;
297
298 timestamp_add_now(TS_AGESA_INIT_RTB_START);
299 Status = amd_dispatch(RtbParams);
300 timestamp_add_now(TS_AGESA_INIT_RTB_END);
301
302 if (Status != AGESA_SUCCESS)
303 return Status;
304
305 if (OemS3Save(&RtbParams->S3DataBlock) != AGESA_SUCCESS)
306 printk(BIOS_ERR, "S3 data not saved, resuming impossible\n");
307
308 return Status;
309 }
310
amd_init_resume(AMD_RESUME_PARAMS * InitResumeParams)311 static AGESA_STATUS amd_init_resume(AMD_RESUME_PARAMS *InitResumeParams)
312 {
313 AGESA_STATUS status;
314
315 OemInitResume(&InitResumeParams->S3DataBlock);
316
317 timestamp_add_now(TS_AGESA_INIT_RESUME_START);
318 status = amd_dispatch(InitResumeParams);
319 timestamp_add_now(TS_AGESA_INIT_RESUME_END);
320
321 return status;
322 }
323
amd_s3late_restore(AMD_S3LATE_PARAMS * S3LateParams)324 static AGESA_STATUS amd_s3late_restore(AMD_S3LATE_PARAMS *S3LateParams)
325 {
326 AGESA_STATUS Status;
327
328 amd_initcpuio();
329
330 OemS3LateRestore(&S3LateParams->S3DataBlock);
331
332 timestamp_add_now(TS_AGESA_S3_LATE_START);
333 Status = amd_dispatch(S3LateParams);
334 timestamp_add_now(TS_AGESA_S3_LATE_END);
335
336 return Status;
337 }
338
amd_s3final_restore(AMD_S3FINAL_PARAMS * S3FinalParams)339 static AGESA_STATUS amd_s3final_restore(AMD_S3FINAL_PARAMS *S3FinalParams)
340 {
341 AGESA_STATUS Status;
342
343 OemS3LateRestore(&S3FinalParams->S3DataBlock);
344
345 timestamp_add_now(TS_AGESA_S3_FINAL_START);
346 Status = amd_dispatch(S3FinalParams);
347 timestamp_add_now(TS_AGESA_S3_FINAL_END);
348
349 return Status;
350 }
351
romstage_dispatch(AMD_CONFIG_PARAMS * StdHeader)352 static AGESA_STATUS romstage_dispatch(AMD_CONFIG_PARAMS *StdHeader)
353 {
354 void *Params = StdHeader;
355
356 switch (StdHeader->Func) {
357 case AMD_INIT_RESET:
358 return amd_init_reset(Params);
359 case AMD_INIT_EARLY:
360 return amd_init_early(Params);
361 case AMD_INIT_POST:
362 return amd_init_post(Params);
363 case AMD_INIT_RESUME:
364 return amd_init_resume(Params);
365 default:
366 return AGESA_UNSUPPORTED;
367 }
368 }
369
ramstage_dispatch(AMD_CONFIG_PARAMS * StdHeader)370 static AGESA_STATUS ramstage_dispatch(AMD_CONFIG_PARAMS *StdHeader)
371 {
372 void *Params = StdHeader;
373
374 switch (StdHeader->Func) {
375 case AMD_INIT_ENV:
376 return amd_init_env(Params);
377 case AMD_INIT_MID:
378 return amd_init_mid(Params);
379 case AMD_INIT_LATE:
380 return amd_init_late(Params);
381 case AMD_INIT_RTB:
382 return amd_init_rtb(Params);
383 case AMD_S3LATE_RESTORE:
384 return amd_s3late_restore(Params);
385 case AMD_S3FINAL_RESTORE:
386 return amd_s3final_restore(Params);
387 default:
388 return AGESA_UNSUPPORTED;
389 }
390 }
391
agesa_execute_state(AGESA_STRUCT_NAME func)392 AGESA_STATUS agesa_execute_state(AGESA_STRUCT_NAME func)
393 {
394 AGESA_STATUS status = AGESA_UNSUPPORTED;
395 AMD_CONFIG_PARAMS template = {};
396 AMD_CONFIG_PARAMS *StdHeader = &template;
397 AMD_INTERFACE_PARAMS AmdParamStruct;
398 AMD_INTERFACE_PARAMS *aip = &AmdParamStruct;
399 union {
400 AMD_RESET_PARAMS ResetParams;
401 AMD_S3LATE_PARAMS S3LateParams;
402 AMD_S3FINAL_PARAMS S3FinalParams;
403 } sp;
404
405 if ((func == AMD_INIT_RESET) || (func == AMD_S3LATE_RESTORE) ||
406 (func == AMD_S3FINAL_RESTORE)) {
407 memset(&sp, 0, sizeof(sp));
408 amd_create_struct(aip, func, &sp, sizeof(sp));
409 } else {
410 amd_create_struct(aip, func, NULL, 0);
411 }
412
413 StdHeader = aip->NewStructPtr;
414 StdHeader->Func = func;
415
416 if (ENV_RAMINIT)
417 status = romstage_dispatch(StdHeader);
418 if (ENV_RAMSTAGE)
419 status = ramstage_dispatch(StdHeader);
420
421 amd_release_struct(aip);
422 return status;
423 }
424