xref: /aosp_15_r20/external/coreboot/src/soc/amd/common/pi/s3_resume.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <stage_cache.h>
5 #include <mrc_cache.h>
6 #include <reset.h>
7 #include <console/console.h>
8 #include <soc/southbridge.h>
9 #include <amdblocks/s3_resume.h>
10 #include <amdblocks/acpi.h>
11 
12 /* Training data versioning is not supported or tracked. */
13 #define DEFAULT_MRC_VERSION 0
14 
reboot_from_resume(const char * message)15 static void __noreturn reboot_from_resume(const char *message)
16 {
17 	printk(BIOS_ERR, "%s", message);
18 	set_pm1cnt_s5();
19 	board_reset();
20 }
21 
OemInitResume(S3_DATA_BLOCK * dataBlock)22 AGESA_STATUS OemInitResume(S3_DATA_BLOCK *dataBlock)
23 {
24 	void *base;
25 	size_t size;
26 	int i;
27 	uint32_t erased = 0xffffffff;
28 
29 	base = mrc_cache_current_mmap_leak(MRC_TRAINING_DATA,
30 					   DEFAULT_MRC_VERSION,
31 					   &size);
32 	if (!base || !size)
33 		reboot_from_resume("Error: S3 NV data not found, rebooting.\n");
34 
35 	/* Read 16 bytes to infer if the NV has been erased from flash. */
36 	for (i = 0; i < 4; i++)
37 		erased &= read32((uint32_t *)base + i);
38 	if (erased == 0xffffffff)
39 		reboot_from_resume("Error: S3 NV data invalid, rebooting.\n");
40 
41 	dataBlock->NvStorage = base;
42 	dataBlock->NvStorageSize = size;
43 	printk(BIOS_SPEW, "S3 NV data @%p, 0x%0zx bytes\n",
44 		dataBlock->NvStorage, (size_t)dataBlock->NvStorageSize);
45 
46 	return AGESA_SUCCESS;
47 }
48 
OemS3LateRestore(S3_DATA_BLOCK * dataBlock)49 AGESA_STATUS OemS3LateRestore(S3_DATA_BLOCK *dataBlock)
50 {
51 	void *base = NULL;
52 	size_t size = 0;
53 
54 	stage_cache_get_raw(STAGE_S3_DATA, &base, &size);
55 	if (!base || !size) {
56 		printk(BIOS_ERR, "S3 volatile data not found\n");
57 		return AGESA_FATAL;
58 	}
59 
60 	dataBlock->VolatileStorage = base;
61 	dataBlock->VolatileStorageSize = size;
62 	printk(BIOS_SPEW, "S3 volatile data @%p, 0x%0zx bytes\n",
63 		dataBlock->VolatileStorage, (size_t)dataBlock->VolatileStorageSize);
64 
65 	return AGESA_SUCCESS;
66 }
67 
OemS3Save(S3_DATA_BLOCK * dataBlock)68 AGESA_STATUS OemS3Save(S3_DATA_BLOCK *dataBlock)
69 {
70 	if (mrc_cache_stash_data(MRC_TRAINING_DATA, DEFAULT_MRC_VERSION,
71 			dataBlock->NvStorage, dataBlock->NvStorageSize) < 0) {
72 		printk(BIOS_ERR, "Failed to stash MRC data\n");
73 		return AGESA_CRITICAL;
74 	}
75 
76 	stage_cache_add_raw(STAGE_S3_DATA, dataBlock->VolatileStorage,
77 		dataBlock->VolatileStorageSize);
78 
79 	return AGESA_SUCCESS;
80 }
81