Browse Source

ARMv7 TLB: Fixed TTBR0 and Table Descriptors to allow caching

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>
Bryan Brinsko 9 years ago
parent
commit
97840b5d1f
2 changed files with 51 additions and 0 deletions
  1. 37 0
      arch/arm/include/asm/system.h
  2. 14 0
      arch/arm/lib/cache-cp15.c

+ 37 - 0
arch/arm/include/asm/system.h

@@ -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.
  *

+ 14 - 0
arch/arm/lib/cache-cp15.c

@@ -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));