From mboxrd@z Thu Jan 1 00:00:00 1970 From: Albert ARIBAUD Date: Fri, 10 Feb 2012 21:38:50 +0100 Subject: [U-Boot] [PATCH 10/17] arm: Add control over cachability of memory regions In-Reply-To: <1326588449-1794-11-git-send-email-sjg@chromium.org> References: <1326588449-1794-1-git-send-email-sjg@chromium.org> <1326588449-1794-11-git-send-email-sjg@chromium.org> Message-ID: <4F35805A.6060103@aribaud.net> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Simon, Le 15/01/2012 01:47, Simon Glass a ?crit : > Add support for adjusting the cachability of an L1 section by updating > the MMU. The mmu_set_region_dcache() function allows drivers to make > these changes after the MMU is set up. > > It is implemented only for ARMv7 at present. > > This is needed for LCD support, where we want to make the LCD frame buffer > write-through (or off) rather than write-back. > > Signed-off-by: Simon Glass > --- > arch/arm/cpu/armv7/cache_v7.c | 11 +++++++ > arch/arm/include/asm/system.h | 30 ++++++++++++++++++++ > arch/arm/lib/cache-cp15.c | 62 +++++++++++++++++++++++++++++++++------- > 3 files changed, 92 insertions(+), 11 deletions(-) > > diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c > index 1b4e808..5f6d039 100644 > --- a/arch/arm/cpu/armv7/cache_v7.c > +++ b/arch/arm/cpu/armv7/cache_v7.c > @@ -297,6 +297,12 @@ void arm_init_before_mmu(void) > v7_inval_tlb(); > } > > +void mmu_page_table_flush(unsigned long start, unsigned long stop) > +{ > + flush_dcache_range(start, stop); > + v7_inval_tlb(); If that means "invalidate", then spell it out. > +} > + > /* > * Flush range from all levels of d-cache/unified-cache used: > * Affects the range [start, start + size - 1] > @@ -329,6 +335,11 @@ void arm_init_before_mmu(void) > void flush_cache(unsigned long start, unsigned long size) > { > } > + > +void mmu_page_table_flush(unsigned long start, unsigned long stop) > +{ > +} > + > #endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ > > #ifndef CONFIG_SYS_ICACHE_OFF > diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h > index 2b28a26..f52a4fc 100644 > --- a/arch/arm/include/asm/system.h > +++ b/arch/arm/include/asm/system.h > @@ -75,6 +75,36 @@ static inline void set_cr(unsigned int val) > isb(); > } > > +/* options available for data cache on each page */ > +enum dcache_option { > + DCACHE_OFF, > + DCACHE_WRITETHROUGH, > + DCACHE_WRITEBACK, > +}; > + > +/* Size of an MMU section */ > +enum { > + MMU_SECTION_SHIFT = 20, > + MMU_SECTION_SIZE = 1<< MMU_SECTION_SHIFT, > +}; > + > +/** > + * Change the cache settings for a region. > + * > + * \param start start address of memory region to change > + * \param size size of memory region to change > + * \param option dcache option to select > + */ > +void mmu_set_region_dcache(u32 start, int size, enum dcache_option option); > + > +/** > + * Register an update to the page tables, and flush the TLB > + * > + * \param start start address of update in page table > + * \param stop stop address of update in page table > + */ > +void mmu_page_table_flush(unsigned long start, unsigned long stop); > + > #endif /* __ASSEMBLY__ */ > > #define arch_align_stack(x) (x) > diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c > index e6c3eae..facb1a7 100644 > --- a/arch/arm/lib/cache-cp15.c > +++ b/arch/arm/lib/cache-cp15.c > @@ -26,12 +26,6 @@ > > #if !(defined(CONFIG_SYS_ICACHE_OFF)&& defined(CONFIG_SYS_DCACHE_OFF)) > > -#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) > -#define CACHE_SETUP 0x1a > -#else > -#define CACHE_SETUP 0x1e > -#endif > - > DECLARE_GLOBAL_DATA_PTR; > > void __arm_init_before_mmu(void) > @@ -50,9 +44,52 @@ static void cp_delay (void) > asm volatile("" : : : "memory"); > } > > -static inline void dram_bank_mmu_setup(int bank) > +void set_section_dcache(int section, enum dcache_option option) > { > + u32 value = section<< MMU_SECTION_SHIFT | (3<< 10); > u32 *page_table = (u32 *)gd->tlb_addr; > + > + switch (option) { > + case DCACHE_WRITETHROUGH: > + value |= 0x1a; > + break; > + > + case DCACHE_WRITEBACK: > + value |= 0x1e; > + break; > + > + case DCACHE_OFF: > + value |= 0x12; > + break; > + } > + > + page_table[section] = value; > +} > + > +void __mmu_page_table_flush(unsigned long start, unsigned long stop) > +{ > + debug("%s: Warning: not implemented\n", __func__); > +} > + > +void mmu_page_table_flush(unsigned long start, unsigned long stop) > + __attribute__((weak, alias("__mmu_page_table_flush"))); > + > +void mmu_set_region_dcache(u32 start, int size, enum dcache_option option) > +{ > + u32 *page_table = (u32 *)gd->tlb_addr; > + u32 upto, end; > + > + end = ALIGN(start + size, MMU_SECTION_SIZE)>> MMU_SECTION_SHIFT; > + start = start>> MMU_SECTION_SHIFT; > + debug("mmu_set_region_dcache start=%x, size=%x, option=%d\n", > + start, size, option); > + for (upto = start; upto< end; upto++) > + set_section_dcache(upto, option); > + mmu_page_table_flush((u32)&page_table[start], (u32)&page_table[end]); > +} > + > +static inline void dram_bank_mmu_setup(int bank) > +{ > bd_t *bd = gd->bd; > int i; > > @@ -60,21 +97,24 @@ static inline void dram_bank_mmu_setup(int bank) > for (i = bd->bi_dram[bank].start>> 20; > i< (bd->bi_dram[bank].start + bd->bi_dram[bank].size)>> 20; > i++) { > - page_table[i] = i<< 20 | (3<< 10) | CACHE_SETUP; > +#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) > + set_section_dcache(i, DCACHE_WRITETHROUGH); > +#else > + set_section_dcache(i, DCACHE_WRITEBACK); > +#endif > } > } > > /* to activate the MMU we need to set up virtual memory: use 1M areas */ > static inline void mmu_setup(void) > { > - u32 *page_table = (u32 *)gd->tlb_addr; > int i; > u32 reg; > > arm_init_before_mmu(); > /* Set up an identity-mapping for all 4GB, rw for everyone */ > for (i = 0; i< 4096; i++) > - page_table[i] = i<< 20 | (3<< 10) | 0x12; Maybe give names to some of the magic numbers here (and in other places where they appear). > + set_section_dcache(i, DCACHE_OFF); > > for (i = 0; i< CONFIG_NR_DRAM_BANKS; i++) { > dram_bank_mmu_setup(i); > @@ -82,7 +122,7 @@ static inline void mmu_setup(void) > > /* Copy the page table address to cp15 */ > asm volatile("mcr p15, 0, %0, c2, c0, 0" > - : : "r" (page_table) : "memory"); > + : : "r" (gd->tlb_addr) : "memory"); > /* Set the access control to all-supervisor */ > asm volatile("mcr p15, 0, %0, c3, c0, 0" > : : "r" (~0)); Amicalement, -- Albert.