xref: /aosp_15_r20/external/coreboot/src/soc/amd/common/pi/agesawrapper.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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