ARMv7 TLB: Fixed TTBR0 and Table Descriptors to allow caching
authorBryan Brinsko <bryan.brinsko@rockwellcollins.com>
Tue, 24 Mar 2015 16:25:12 +0000 (11:25 -0500)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Thu, 16 Apr 2015 12:59:33 +0000 (14:59 +0200)
The TTBR0 register and Table Descriptors of the ARMv7 TLB weren't being
properly set to allow for the configuration specified caching modes to
be active over DRAM. This commit fixes those issues.

Signed-off-by: Bryan Brinsko <bryan.brinsko@rockwellcollins.com>
arch/arm/include/asm/system.h
arch/arm/lib/cache-cp15.c

index 2a5bed2e46b67b7adacddc1ed43a395e34c3d9f8..9cd2f1e592c566863e9733ebfed7876d0ac8de8d 100644 (file)
@@ -196,6 +196,28 @@ static inline void set_dacr(unsigned int val)
        isb();
 }
 
+#ifdef CONFIG_ARMV7
+/* Short-Descriptor Translation Table Level 1 Bits */
+#define TTB_SECT_NS_MASK       (1 << 19)
+#define TTB_SECT_NG_MASK       (1 << 17)
+#define TTB_SECT_S_MASK                (1 << 16)
+/* Note: TTB AP bits are set elsewhere */
+#define TTB_SECT_TEX(x)                ((x & 0x7) << 12)
+#define TTB_SECT_DOMAIN(x)     ((x & 0xf) << 5)
+#define TTB_SECT_XN_MASK       (1 << 4)
+#define TTB_SECT_C_MASK                (1 << 3)
+#define TTB_SECT_B_MASK                (1 << 2)
+#define TTB_SECT                       (2 << 0)
+
+/* options available for data cache on each page */
+enum dcache_option {
+       DCACHE_OFF = TTB_SECT_S_MASK | TTB_SECT_DOMAIN(0) |
+                                       TTB_SECT_XN_MASK | TTB_SECT,
+       DCACHE_WRITETHROUGH = DCACHE_OFF | TTB_SECT_C_MASK,
+       DCACHE_WRITEBACK = DCACHE_WRITETHROUGH | TTB_SECT_B_MASK,
+       DCACHE_WRITEALLOC = DCACHE_WRITEBACK | TTB_SECT_TEX(1),
+};
+#else
 /* options available for data cache on each page */
 enum dcache_option {
        DCACHE_OFF = 0x12,
@@ -203,6 +225,7 @@ enum dcache_option {
        DCACHE_WRITEBACK = 0x1e,
        DCACHE_WRITEALLOC = 0x16,
 };
+#endif
 
 /* Size of an MMU section */
 enum {
@@ -210,6 +233,20 @@ enum {
        MMU_SECTION_SIZE        = 1 << MMU_SECTION_SHIFT,
 };
 
+#ifdef CONFIG_ARMV7
+/* TTBR0 bits */
+#define TTBR0_BASE_ADDR_MASK   0xFFFFC000
+#define TTBR0_RGN_NC                   (0 << 3)
+#define TTBR0_RGN_WBWA                 (1 << 3)
+#define TTBR0_RGN_WT                   (2 << 3)
+#define TTBR0_RGN_WB                   (3 << 3)
+/* TTBR0[6] is IRGN[0] and TTBR[0] is IRGN[1] */
+#define TTBR0_IRGN_NC                  (0 << 0 | 0 << 6)
+#define TTBR0_IRGN_WBWA                        (0 << 0 | 1 << 6)
+#define TTBR0_IRGN_WT                  (1 << 0 | 0 << 6)
+#define TTBR0_IRGN_WB                  (1 << 0 | 1 << 6)
+#endif
+
 /**
  * Change the cache settings for a region.
  *
index 0291afa7bd531088f441808e9f9767cceb4d774b..c65e068857a2737f58d3ec70535dbb156af3d468 100644 (file)
@@ -96,9 +96,23 @@ static inline void mmu_setup(void)
                dram_bank_mmu_setup(i);
        }
 
+#ifdef CONFIG_ARMV7
+       /* Set TTBR0 */
+       reg = gd->arch.tlb_addr & TTBR0_BASE_ADDR_MASK;
+#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
+       reg |= TTBR0_RGN_WT | TTBR0_IRGN_WT;
+#elif defined(CONFIG_SYS_ARM_CACHE_WRITEALLOC)
+       reg |= TTBR0_RGN_WBWA | TTBR0_IRGN_WBWA;
+#else
+       reg |= TTBR0_RGN_WB | TTBR0_IRGN_WB;
+#endif
+       asm volatile("mcr p15, 0, %0, c2, c0, 0"
+                    : : "r" (reg) : "memory");
+#else
        /* Copy the page table address to cp15 */
        asm volatile("mcr p15, 0, %0, c2, c0, 0"
                     : : "r" (gd->arch.tlb_addr) : "memory");
+#endif
        /* Set the access control to all-supervisor */
        asm volatile("mcr p15, 0, %0, c3, c0, 0"
                     : : "r" (~0));