From mboxrd@z Thu Jan 1 00:00:00 1970 From: Simon Glass Date: Sat, 3 Mar 2012 22:20:54 -0800 Subject: [U-Boot] [PATCH 10/17] arm: Add control over cachability of memory regions In-Reply-To: <4F35805A.6060103@aribaud.net> References: <1326588449-1794-1-git-send-email-sjg@chromium.org> <1326588449-1794-11-git-send-email-sjg@chromium.org> <4F35805A.6060103@aribaud.net> Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Albert, On Fri, Feb 10, 2012 at 12:38 PM, Albert ARIBAUD wrote: > 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. Are you asking for a patch to rename v7_inval_tlb()? That is an existing function - I agree it is a bit cryptic. > >> +} >> + >> ?/* >> ? * 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). OK - this line is actually being removed but I will add constants for the values in set_section_dcache(). > > >> + ? ? ? ? ? ? ? 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. Regards, Simon