x86: quark: Configure MTRR to enable cache
authorBin Meng <bmeng.cn@gmail.com>
Mon, 14 Sep 2015 07:07:41 +0000 (00:07 -0700)
committerSimon Glass <sjg@chromium.org>
Thu, 17 Sep 2015 01:53:53 +0000 (19:53 -0600)
Quark SoC does not support MSR MTRRs. Fixed and variable range MTRRs
are accessed indirectly via the message port and not the traditional
MSR mechanism. Only UC, WT and WB cache types are supported.

We configure all the fixed range MTRRs with common values (VGA RAM
as UC, others as WB) and 3 variable range MTRRs for ROM/eSRAM/RAM as
WB, which significantly improves the boot time performance.

With this commit, it takes only 2 seconds for U-Boot to boot to shell
on Intel Galileo board. Previously it took about 6 seconds.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
arch/x86/cpu/quark/dram.c
arch/x86/cpu/quark/quark.c
arch/x86/include/asm/arch-quark/quark.h

index 9cac846c693114a9e303234b7979dd7ffe1c7223..1b89376387977fd3b9b4d9acb1c829b5dca16c0b 100644 (file)
@@ -7,8 +7,10 @@
 #include <common.h>
 #include <errno.h>
 #include <fdtdec.h>
+#include <asm/mtrr.h>
 #include <asm/post.h>
 #include <asm/arch/mrc.h>
+#include <asm/arch/msg_port.h>
 #include <asm/arch/quark.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -111,6 +113,14 @@ int dram_init(void)
        gd->ram_size = mrc_params.mem_size;
        post_code(POST_DRAM);
 
+       /* variable range MTRR#2: RAM area */
+       disable_caches();
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_RAM),
+                      0 | MTRR_TYPE_WRBACK);
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_RAM),
+                      (~(gd->ram_size - 1)) | MTRR_PHYS_MASK_VALID);
+       enable_caches();
+
        return 0;
 }
 
index 8b78a867efe3cf8b06e4bc5bf05188cc5a3cad31..77d644a4914937172ffd6645c603386ab5a4afc1 100644 (file)
@@ -8,6 +8,7 @@
 #include <mmc.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/mtrr.h>
 #include <asm/pci.h>
 #include <asm/post.h>
 #include <asm/processor.h>
@@ -34,6 +35,55 @@ static void unprotect_spi_flash(void)
        qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, 0xd8, bc);
 }
 
+static void quark_setup_mtrr(void)
+{
+       u32 base, mask;
+       int i;
+
+       disable_caches();
+
+       /* mark the VGA RAM area as uncacheable */
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_A0000,
+                      MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_B0000,
+                      MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
+
+       /* mark other fixed range areas as cacheable */
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_64K_00000,
+                      MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_64K_40000,
+                      MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_80000,
+                      MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_90000,
+                      MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+       for (i = MTRR_FIX_4K_C0000; i <= MTRR_FIX_4K_FC000; i++)
+               msg_port_write(MSG_PORT_HOST_BRIDGE, i,
+                              MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+
+       /* variable range MTRR#0: ROM area */
+       mask = ~(CONFIG_SYS_MONITOR_LEN - 1);
+       base = CONFIG_SYS_TEXT_BASE & mask;
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_ROM),
+                      base | MTRR_TYPE_WRBACK);
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_ROM),
+                      mask | MTRR_PHYS_MASK_VALID);
+
+       /* variable range MTRR#1: eSRAM area */
+       mask = ~(ESRAM_SIZE - 1);
+       base = CONFIG_ESRAM_BASE & mask;
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_ESRAM),
+                      base | MTRR_TYPE_WRBACK);
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_ESRAM),
+                      mask | MTRR_PHYS_MASK_VALID);
+
+       /* enable both variable and fixed range MTRRs */
+       msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_DEF_TYPE,
+                      MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN);
+
+       enable_caches();
+}
+
 static void quark_setup_bars(void)
 {
        /* GPIO - D31:F0:R44h */
@@ -190,6 +240,13 @@ int arch_cpu_init(void)
        if (ret)
                return ret;
 
+       /*
+        * Quark SoC does not support MSR MTRRs. Fixed and variable range MTRRs
+        * are accessed indirectly via the message port and not the traditional
+        * MSR mechanism. Only UC, WT and WB cache types are supported.
+        */
+       quark_setup_mtrr();
+
        /*
         * Quark SoC has some non-standard BARs (excluding PCI standard BARs)
         * which need be initialized with suggested values
index f6009f67d82e5831e2d40d42139b1a36c328d87c..7a864c7c5308ddb8ca0b7627b3cfa7ca2c5bb804 100644 (file)
 /* Extended Configuration Space */
 #define HEC_REG                        0x09
 
+/* MTRR Registers */
+#define MTRR_CAP               0x40
+#define MTRR_DEF_TYPE          0x41
+
+#define MTRR_FIX_64K_00000     0x42
+#define MTRR_FIX_64K_40000     0x43
+#define MTRR_FIX_16K_80000     0x44
+#define MTRR_FIX_16K_90000     0x45
+#define MTRR_FIX_16K_A0000     0x46
+#define MTRR_FIX_16K_B0000     0x47
+#define MTRR_FIX_4K_C0000      0x48
+#define MTRR_FIX_4K_C4000      0x49
+#define MTRR_FIX_4K_C8000      0x4a
+#define MTRR_FIX_4K_CC000      0x4b
+#define MTRR_FIX_4K_D0000      0x4c
+#define MTRR_FIX_4K_D4000      0x4d
+#define MTRR_FIX_4K_D8000      0x4e
+#define MTRR_FIX_4K_DC000      0x4f
+#define MTRR_FIX_4K_E0000      0x50
+#define MTRR_FIX_4K_E4000      0x51
+#define MTRR_FIX_4K_E8000      0x52
+#define MTRR_FIX_4K_EC000      0x53
+#define MTRR_FIX_4K_F0000      0x54
+#define MTRR_FIX_4K_F4000      0x55
+#define MTRR_FIX_4K_F8000      0x56
+#define MTRR_FIX_4K_FC000      0x57
+
+#define MTRR_SMRR_PHYBASE      0x58
+#define MTRR_SMRR_PHYMASK      0x59
+
+#define MTRR_VAR_PHYBASE(n)    (0x5a + 2 * (n))
+#define MTRR_VAR_PHYMASK(n)    (0x5b + 2 * (n))
+
+#ifndef __ASSEMBLY__
+
+/* variable range MTRR usage */
+enum {
+       MTRR_VAR_ROM,
+       MTRR_VAR_ESRAM,
+       MTRR_VAR_RAM
+};
+
+#endif /* __ASSEMBLY__ */
+
 /* Port 0x04: Remote Management Unit Message Port Registers */
 
 /* ACPI PBLK Base Address Register */