summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/amd/common/block/s3/s3_resume.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/src/soc/amd/common/block/s3/s3_resume.c b/src/soc/amd/common/block/s3/s3_resume.c
index 04414e8a2e..eb0148f964 100644
--- a/src/soc/amd/common/block/s3/s3_resume.c
+++ b/src/soc/amd/common/block/s3/s3_resume.c
@@ -16,28 +16,44 @@
#include <stage_cache.h>
#include <mrc_cache.h>
+#include <reset.h>
#include <console/console.h>
+#include <soc/southbridge.h>
#include <amdblocks/s3_resume.h>
/* Training data versioning is not supported or tracked. */
#define DEFAULT_MRC_VERSION 0
+static void reboot_from_resume(const char *message) /* Does not return */
+{
+ printk(BIOS_ERR, "%s", message);
+ set_pm1cnt_s5();
+ board_reset();
+}
+
void get_s3nv_info(void **base, size_t *size)
{
struct region_device rdev;
if (mrc_cache_get_current(MRC_TRAINING_DATA, DEFAULT_MRC_VERSION,
- &rdev)) {
- printk(BIOS_ERR, "mrc_cache_get_current returned error\n");
- return;
- }
+ &rdev))
+ reboot_from_resume("mrc_cache_get_current error, rebooting.\n");
+
*base = rdev_mmap_full(&rdev);
*size = region_device_sz(&rdev);
if (!*base || !*size)
- printk(BIOS_ERR, "Error: S3 NV data not found\n");
- else
- printk(BIOS_SPEW, "S3 NV data @0x%p 0x%0zx total bytes\n",
- *base, *size);
+ reboot_from_resume("Error: S3 NV data not found, rebooting.\n");
+
+ /* Read 16 bytes to infer if the NV has been erased from flash. */
+ int i;
+ uint32_t erased = 0xffffffff;
+ for (i = 0; i < 4; i++)
+ erased &= read32((uint32_t *)*base + i);
+
+ if (erased == 0xffffffff)
+ reboot_from_resume("Error: S3 NV data invalid, rebooting.\n");
+
+ printk(BIOS_SPEW, "S3 NV data @0x%p, 0x%0zx bytes\n", *base, *size);
}
void get_s3vol_info(void **base, size_t *size)