summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/amd/stoneyridge/Kconfig3
-rw-r--r--src/soc/amd/stoneyridge/ramtop.c34
2 files changed, 36 insertions, 1 deletions
diff --git a/src/soc/amd/stoneyridge/Kconfig b/src/soc/amd/stoneyridge/Kconfig
index 148ca3ff04..79755239d8 100644
--- a/src/soc/amd/stoneyridge/Kconfig
+++ b/src/soc/amd/stoneyridge/Kconfig
@@ -55,6 +55,7 @@ config CPU_SPECIFIC_OPTIONS
select BOOTBLOCK_CONSOLE
select BOOT_DEVICE_SUPPORTS_WRITES if BOOT_DEVICE_SPI_FLASH
select RELOCATABLE_MODULES
+ select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM
select PARALLEL_MP
select PARALLEL_MP_AP_WORK
select HAVE_SMI_HANDLER
@@ -295,7 +296,7 @@ config SMM_TSEG_SIZE
config SMM_RESERVED_SIZE
hex
- default 0x100000
+ default 0x140000
config ACPI_CPU_STRING
string
diff --git a/src/soc/amd/stoneyridge/ramtop.c b/src/soc/amd/stoneyridge/ramtop.c
index e676465ce7..24386edba3 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 @@ static size_t smm_region_size(void)
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 @@ int smm_subregion(int sub, void **start, size_t *size)
/* External cache is in the middle of TSEG. */
sub_base += sub_size - cache_size;
sub_size = cache_size;
+ clear_tvalid();
break;
default:
return -1;