amd/stoneyridge: Put stage cache into TSEG
Add a function to allow an external region to be located in TSEG.
Select the option to use memory outside of cbmem. Increase the size
reserved in TSEG.
Change-Id: Ic1073af04475d862753136c9e14e2b2dde31fe66
Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com>
Reviewed-on: https://review.coreboot.org/23519
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
diff --git a/src/soc/amd/stoneyridge/ramtop.c b/src/soc/amd/stoneyridge/ramtop.c
index e676465..24386ed 100644
--- a/src/soc/amd/stoneyridge/ramtop.c
+++ b/src/soc/amd/stoneyridge/ramtop.c
@@ -20,7 +20,9 @@
#include <arch/io.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/mtrr.h>
+#include <cpu/amd/amdfam15.h>
#include <cbmem.h>
+#include <stage_cache.h>
#include <soc/northbridge.h>
#include <soc/southbridge.h>
@@ -56,12 +58,43 @@
return CONFIG_SMM_TSEG_SIZE;
}
+void stage_cache_external_region(void **base, size_t *size)
+{
+ if (smm_subregion(SMM_SUBREGION_CACHE, base, size)) {
+ printk(BIOS_ERR, "ERROR: No cache SMM subregion.\n");
+ *base = NULL;
+ *size = 0;
+ }
+}
+
void smm_region_info(void **start, size_t *size)
{
*start = (void *)smm_region_start();
*size = smm_region_size();
}
+/*
+ * For data stored in TSEG, ensure TValid is clear so R/W access can reach
+ * the DRAM when not in SMM.
+ */
+static void clear_tvalid(void)
+{
+ msr_t hwcr = rdmsr(HWCR_MSR);
+ msr_t mask = rdmsr(MSR_SMM_MASK);
+ int tvalid = !!(mask.lo & SMM_TSEG_VALID);
+
+ if (hwcr.lo & SMM_LOCK) {
+ if (!tvalid) /* not valid but locked means still accessible */
+ return;
+
+ printk(BIOS_ERR, "Error: can't clear TValid, already locked\n");
+ return;
+ }
+
+ mask.lo &= ~SMM_TSEG_VALID;
+ wrmsr(MSR_SMM_MASK, mask);
+}
+
int smm_subregion(int sub, void **start, size_t *size)
{
uintptr_t sub_base;
@@ -82,6 +115,7 @@
/* External cache is in the middle of TSEG. */
sub_base += sub_size - cache_size;
sub_size = cache_size;
+ clear_tvalid();
break;
default:
return -1;