From ae0b0ca3fdde5e1b471bcf9b8e8c0f559d7e4098 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 29 Mar 2015 13:09:22 -0600 Subject: [PATCH] SAMV7/Cortex-M7: Add support for write through D-Cache. SAMV7 Ethernet look like it needs this --- arch/arm/src/armv7-m/Kconfig | 5 ++ arch/arm/src/armv7-m/arch_clean_dcache.c | 4 +- arch/arm/src/armv7-m/arch_clean_dcache_all.c | 4 +- arch/arm/src/armv7-m/arch_flush_dcache.c | 4 +- arch/arm/src/armv7-m/arch_flush_dcache_all.c | 4 +- arch/arm/src/armv7-m/cache.h | 49 +++++++++++++++++++- arch/arm/src/samv7/Kconfig | 9 ++++ arch/arm/src/samv7/Make.defs | 4 +- arch/arm/src/samv7/sam_start.c | 1 + 9 files changed, 73 insertions(+), 11 deletions(-) diff --git a/arch/arm/src/armv7-m/Kconfig b/arch/arm/src/armv7-m/Kconfig index df4b152007..b4fd21f5ec 100644 --- a/arch/arm/src/armv7-m/Kconfig +++ b/arch/arm/src/armv7-m/Kconfig @@ -23,6 +23,11 @@ config ARMV7M_DCACHE default n depends on ARMV7M_HAVE_DCACHE +config ARMV7M_DCACHE_WRITETHROUGH + bool "D-Cache Write-Through" + default n + depends on ARMV7M_DCACHE + config ARMV7M_HAVE_ITCM bool default n diff --git a/arch/arm/src/armv7-m/arch_clean_dcache.c b/arch/arm/src/armv7-m/arch_clean_dcache.c index 7813e0cc36..735623b4cd 100644 --- a/arch/arm/src/armv7-m/arch_clean_dcache.c +++ b/arch/arm/src/armv7-m/arch_clean_dcache.c @@ -46,7 +46,7 @@ #include "cache.h" -#ifdef CONFIG_ARMV7M_DCACHE +#if defined(CONFIG_ARMV7M_DCACHE) && !defined(CONFIG_ARMV7M_DCACHE_WRITETHROUGH) /**************************************************************************** * Pre-processor Definitions @@ -146,4 +146,4 @@ void arch_clean_dcache(uintptr_t start, uintptr_t end) ARM_ISB(); } -#endif /* CONFIG_ARMV7M_DCACHE */ +#endif /* CONFIG_ARMV7M_DCACHE && !CONFIG_ARMV7M_DCACHE_WRITETHROUGH */ diff --git a/arch/arm/src/armv7-m/arch_clean_dcache_all.c b/arch/arm/src/armv7-m/arch_clean_dcache_all.c index f3d3ef6029..296780bee5 100644 --- a/arch/arm/src/armv7-m/arch_clean_dcache_all.c +++ b/arch/arm/src/armv7-m/arch_clean_dcache_all.c @@ -46,7 +46,7 @@ #include "cache.h" -#ifdef CONFIG_ARMV7M_DCACHE +#if defined(CONFIG_ARMV7M_DCACHE) && !defined(CONFIG_ARMV7M_DCACHE_WRITETHROUGH) /**************************************************************************** * Pre-processor Definitions @@ -126,4 +126,4 @@ void arch_clean_dcache_all(void) ARM_ISB(); } -#endif /* CONFIG_ARMV7M_DCACHE */ +#endif /* CONFIG_ARMV7M_DCACHE && !CONFIG_ARMV7M_DCACHE_WRITETHROUGH */ diff --git a/arch/arm/src/armv7-m/arch_flush_dcache.c b/arch/arm/src/armv7-m/arch_flush_dcache.c index 07fbae6245..c884eec041 100644 --- a/arch/arm/src/armv7-m/arch_flush_dcache.c +++ b/arch/arm/src/armv7-m/arch_flush_dcache.c @@ -46,7 +46,7 @@ #include "cache.h" -#ifdef CONFIG_ARMV7M_DCACHE +#if defined(CONFIG_ARMV7M_DCACHE) && !defined(CONFIG_ARMV7M_DCACHE_WRITETHROUGH) /**************************************************************************** * Pre-processor Definitions @@ -146,4 +146,4 @@ void arch_flush_dcache(uintptr_t start, uintptr_t end) ARM_ISB(); } -#endif /* CONFIG_ARMV7M_DCACHE */ +#endif /* CONFIG_ARMV7M_DCACHE && !CONFIG_ARMV7M_DCACHE_WRITETHROUGH */ diff --git a/arch/arm/src/armv7-m/arch_flush_dcache_all.c b/arch/arm/src/armv7-m/arch_flush_dcache_all.c index c25e665123..33f80b85ba 100644 --- a/arch/arm/src/armv7-m/arch_flush_dcache_all.c +++ b/arch/arm/src/armv7-m/arch_flush_dcache_all.c @@ -46,7 +46,7 @@ #include "cache.h" -#ifdef CONFIG_ARMV7M_DCACHE +#if defined(CONFIG_ARMV7M_DCACHE) && !defined(CONFIG_ARMV7M_DCACHE_WRITETHROUGH) /**************************************************************************** * Pre-processor Definitions @@ -125,4 +125,4 @@ void arch_flush_dcache_all(void) ARM_ISB(); } -#endif /* CONFIG_ARMV7M_DCACHE */ +#endif /* CONFIG_ARMV7M_DCACHE && !CONFIG_ARMV7M_DCACHE_WRITETHROUGH */ diff --git a/arch/arm/src/armv7-m/cache.h b/arch/arm/src/armv7-m/cache.h index 333c3ed5f0..16fc0bdf2a 100644 --- a/arch/arm/src/armv7-m/cache.h +++ b/arch/arm/src/armv7-m/cache.h @@ -211,6 +211,31 @@ static inline void arch_invalidate_icache_all(void) #endif } +/**************************************************************************** + * Name: arch_dcache_writethrough + * + * Description: + * Configure the D-Cache for Write-Through operation. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_ARMV7M_DCACHE) && defined(CONFIG_ARMV7M_DCACHE_WRITETHROUGH) +static inline void arch_dcache_writethrough(void) +{ + uint32_t regval = getreg32(NVIC_CACR); + regval |= NVIC_CACR_FORCEWT; + putreg32(regval, NVIC_CACR); +} +#else +# define arch_dcache_writethrough() +#endif + /**************************************************************************** * Public Variables ****************************************************************************/ @@ -322,6 +347,9 @@ void arch_invalidate_dcache_all(void); * Clean the data cache within the specified region by flushing the * contents of the data cache to memory. * + * NOTE: This operation is un-necessary if the DCACHE is configured in + * write-through mode. + * * Input Parameters: * start - virtual start address of region * end - virtual end address of region + 1 @@ -336,7 +364,7 @@ void arch_invalidate_dcache_all(void); * ****************************************************************************/ -#ifdef CONFIG_ARMV7M_DCACHE +#if defined(CONFIG_ARMV7M_DCACHE) && !defined(CONFIG_ARMV7M_DCACHE_WRITETHROUGH) void arch_clean_dcache(uintptr_t start, uintptr_t end); #else # define arch_clean_dcache(s,e) @@ -349,6 +377,9 @@ void arch_clean_dcache(uintptr_t start, uintptr_t end); * Clean the entire data cache within the specified region by flushing the * contents of the data cache to memory. * + * NOTE: This operation is un-necessary if the DCACHE is configured in + * write-through mode. + * * Input Parameters: * None * @@ -362,7 +393,7 @@ void arch_clean_dcache(uintptr_t start, uintptr_t end); * ****************************************************************************/ -#ifdef CONFIG_ARMV7M_DCACHE +#if defined(CONFIG_ARMV7M_DCACHE) && !defined(CONFIG_ARMV7M_DCACHE_WRITETHROUGH) void arch_clean_dcache_all(void); #else # define arch_clean_dcache_all() @@ -375,6 +406,9 @@ void arch_clean_dcache_all(void); * Flush the data cache within the specified region by cleaning and * invalidating the D cache. * + * NOTE: If DCACHE write-through is configured, then this operation is the + * same as arch_invalidate_cache(). + * * Input Parameters: * start - virtual start address of region * end - virtual end address of region + 1 @@ -390,7 +424,11 @@ void arch_clean_dcache_all(void); ****************************************************************************/ #ifdef CONFIG_ARMV7M_DCACHE +#ifdef CONFIG_ARMV7M_DCACHE_WRITETHROUGH +# define arch_flush_dcache(s,e) arch_invalidate_dcache(s,e) +#else void arch_flush_dcache(uintptr_t start, uintptr_t end); +#endif #else # define arch_flush_dcache(s,e) #endif @@ -401,6 +439,9 @@ void arch_flush_dcache(uintptr_t start, uintptr_t end); * Description: * Flush the entire data cache by cleaning and invalidating the D cache. * + * NOTE: If DCACHE write-through is configured, then this operation is the + * same as arch_invalidate_cache_all(). + * * Input Parameters: * None * @@ -415,7 +456,11 @@ void arch_flush_dcache(uintptr_t start, uintptr_t end); ****************************************************************************/ #ifdef CONFIG_ARMV7M_DCACHE +#ifdef CONFIG_ARMV7M_DCACHE_WRITETHROUGH +# define arch_flush_dcache_all() arch_invalidate_dcache_all() +#else void arch_flush_dcache_all(void); +#endif #else # define arch_flush_dcache_all() #endif diff --git a/arch/arm/src/samv7/Kconfig b/arch/arm/src/samv7/Kconfig index e761bd355f..41e40b5df1 100644 --- a/arch/arm/src/samv7/Kconfig +++ b/arch/arm/src/samv7/Kconfig @@ -117,6 +117,15 @@ config SAMV7_HAVE_EBI config SAMV7_EMAC bool default n + select ARMV7M_DCACHE_WRITETHROUGH if ARMV7M_DCACHE + ---help--- + NOTE that write-through caching is automatically selected. This is + to work around issues with the RX and TX descriptors with are 8-bits + in size. But the D-Cache cache line size is 32-bytes. That means + that you cannot reload, clean or invalidate a descriptor without also + effecting three neighboring desciptors. Setting write through mode + eliminates the need for cleaning. If only reloading and invalidating + are done, then there is no problem. config SAMV7_HSMCI bool diff --git a/arch/arm/src/samv7/Make.defs b/arch/arm/src/samv7/Make.defs index c0db385179..24ca048820 100644 --- a/arch/arm/src/samv7/Make.defs +++ b/arch/arm/src/samv7/Make.defs @@ -66,9 +66,11 @@ endif ifeq ($(CONFIG_ARMV7M_DCACHE),y) CMN_CSRCS += arch_enable_dcache.c arch_disable_dcache.c +CMN_CSRCS += arch_invalidate_dcache.c arch_invalidate_dcache_all.c +ifneq ($(CONFIG_ARMV7M_DCACHE_WRITETHROUGH),y) CMN_CSRCS += arch_clean_dcache.c arch_clean_dcache_all.c CMN_CSRCS += arch_flush_dcache.c arch_flush_dcache_all.c -CMN_CSRCS += arch_invalidate_dcache.c arch_invalidate_dcache_all.c +endif endif ifeq ($(CONFIG_ARCH_FPU),y) diff --git a/arch/arm/src/samv7/sam_start.c b/arch/arm/src/samv7/sam_start.c index 0892a0e110..7649c9d462 100644 --- a/arch/arm/src/samv7/sam_start.c +++ b/arch/arm/src/samv7/sam_start.c @@ -380,6 +380,7 @@ void __start(void) /* Enable I- and D-Caches */ + arch_dcache_writethrough(); arch_enable_icache(); arch_enable_dcache();