summaryrefslogtreecommitdiff
path: root/src/cpu/amd/mtrr
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/amd/mtrr')
-rw-r--r--src/cpu/amd/mtrr/Config.lb2
-rw-r--r--src/cpu/amd/mtrr/amd_earlymtrr.c46
-rw-r--r--src/cpu/amd/mtrr/amd_mtrr.c85
3 files changed, 133 insertions, 0 deletions
diff --git a/src/cpu/amd/mtrr/Config.lb b/src/cpu/amd/mtrr/Config.lb
new file mode 100644
index 0000000000..eab703c6c0
--- /dev/null
+++ b/src/cpu/amd/mtrr/Config.lb
@@ -0,0 +1,2 @@
+dir /cpu/x86/mtrr
+object amd_mtrr.c \ No newline at end of file
diff --git a/src/cpu/amd/mtrr/amd_earlymtrr.c b/src/cpu/amd/mtrr/amd_earlymtrr.c
new file mode 100644
index 0000000000..ca19a57faa
--- /dev/null
+++ b/src/cpu/amd/mtrr/amd_earlymtrr.c
@@ -0,0 +1,46 @@
+#ifndef AMD_EARLYMTRR_C
+#define AMD_EARLYMTRR_C
+#include <cpu/x86/mtrr.h>
+#include <cpu/amd/mtrr.h>
+#include "cpu/x86/mtrr/earlymtrr.c"
+
+
+static void amd_early_mtrr_init(void)
+{
+ static const unsigned long mtrr_msrs[] = {
+ /* fixed mtrr */
+ 0x250, 0x258, 0x259,
+ 0x268, 0x269, 0x26A,
+ 0x26B, 0x26C, 0x26D,
+ 0x26E, 0x26F,
+ /* var mtrr */
+ 0x200, 0x201, 0x202, 0x203,
+ 0x204, 0x205, 0x206, 0x207,
+ 0x208, 0x209, 0x20A, 0x20B,
+ 0x20C, 0x20D, 0x20E, 0x20F,
+ /* var iorr */
+ 0xC0010016, 0xC0010017, 0xC0010018, 0xC0010019,
+ /* mem top */
+ 0xC001001A, 0xC001001D,
+ /* NULL end of table */
+ 0
+ };
+ msr_t msr;
+
+ disable_cache();
+ do_early_mtrr_init(mtrr_msrs);
+
+ /* Enable memory access for 0 - 1MB using top_mem */
+ msr.hi = 0;
+ msr.lo = (((CONFIG_LB_MEM_TOPK << 10) + TOP_MEM_MASK) & ~TOP_MEM_MASK);
+ wrmsr(TOP_MEM, msr);
+
+ /* Enable the MTRRs in SYSCFG */
+ msr = rdmsr(SYSCFG_MSR);
+ msr.lo |= SYSCFG_MSR_MtrrVarDramEn;
+ wrmsr(SYSCFG_MSR, msr);
+
+ enable_cache();
+}
+
+#endif /* AMD_EARLYMTRR_C */
diff --git a/src/cpu/amd/mtrr/amd_mtrr.c b/src/cpu/amd/mtrr/amd_mtrr.c
new file mode 100644
index 0000000000..7c8d50ae68
--- /dev/null
+++ b/src/cpu/amd/mtrr/amd_mtrr.c
@@ -0,0 +1,85 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/amd/mtrr.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/msr.h>
+
+static unsigned long resk(uint64_t value)
+{
+ unsigned long resultk;
+ if (value < (1ULL << 42)) {
+ resultk = value >> 10;
+ }
+ else {
+ resultk = 0xffffffff;
+ }
+ return resultk;
+}
+
+void amd_setup_mtrrs(void)
+{
+ unsigned long mmio_basek, tomk;
+ unsigned long i;
+ device_t dev;
+ msr_t msr;
+
+ x86_setup_mtrrs();
+
+ /* Except for the PCI MMIO hole just before 4GB there are no
+ * significant holes in the address space, so just account
+ * for those two and move on.
+ */
+ mmio_basek = tomk = 0;
+ for(dev = all_devices; dev; dev = dev->next) {
+ struct resource *res, *last;
+ last = &dev->resource[dev->resources];
+ for(res = &dev->resource[0]; res < last; res++) {
+ unsigned long topk;
+ if (!(res->flags & IORESOURCE_MEM) ||
+ (!(res->flags & IORESOURCE_CACHEABLE))) {
+ continue;
+ }
+ topk = resk(res->base + res->size);
+ if (tomk < topk) {
+ tomk = topk;
+ }
+ if ((topk < 4*1024*1024) && (mmio_basek < topk)) {
+ mmio_basek = topk;
+ }
+ }
+ }
+ if (mmio_basek > tomk) {
+ mmio_basek = tomk;
+ }
+ /* Round mmio_basek down to the nearst size that will fit in TOP_MEM */
+ mmio_basek = mmio_basek & ~TOP_MEM_MASK_KB;
+ /* Round tomk up to the next greater size that will fit in TOP_MEM */
+ tomk = (tomk + TOP_MEM_MASK_KB) & ~TOP_MEM_MASK_KB;
+
+ disable_cache();
+
+ /* Setup TOP_MEM */
+ msr.hi = mmio_basek >> 22;
+ msr.lo = mmio_basek << 10;
+ wrmsr(TOP_MEM, msr);
+
+ /* Setup TOP_MEM2 */
+ msr.hi = tomk >> 22;
+ msr.lo = tomk << 10;
+ wrmsr(TOP_MEM2, msr);
+
+ /* zero the IORR's before we enable to prevent
+ * undefined side effects.
+ */
+ msr.lo = msr.hi = 0;
+ for(i = IORR_FIRST; i <= IORR_LAST; i++) {
+ wrmsr(i, msr);
+ }
+
+ msr = rdmsr(SYSCFG_MSR);
+ msr.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_TOM2En;
+ wrmsr(SYSCFG_MSR, msr);
+
+ enable_cache();
+}