[U-Boot] [PATCH] nds32: split common cache access from cpu into lib

This commit does the following updates. 1. Split the common cache access from cpu.c into lib folder. 2. Rename the following cache api to adapt common.h - dcache_flush_rang -> flush_dcache_rang - icache_inval_range -> invalidate_icache_range 3. Add invalidate_dcache_range
Signed-off-by: Macpaul Lin macpaul@gmail.com --- arch/nds32/cpu/n1213/ag101/cpu.c | 112 ------------------------------ arch/nds32/cpu/n1213/ag102/cpu.c | 112 ------------------------------ arch/nds32/lib/Makefile | 2 +- arch/nds32/lib/cache.c | 145 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 225 deletions(-) create mode 100644 arch/nds32/lib/cache.c
diff --git a/arch/nds32/cpu/n1213/ag101/cpu.c b/arch/nds32/cpu/n1213/ag101/cpu.c index c2636b1..a9991e7 100644 --- a/arch/nds32/cpu/n1213/ag101/cpu.c +++ b/arch/nds32/cpu/n1213/ag101/cpu.c @@ -82,115 +82,3 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
/*NOTREACHED*/ } - -static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) -{ - if (cache == ICACHE) - return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \ - >> ICM_CFG_OFF_ISZ) - 1); - else - return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \ - >> DCM_CFG_OFF_DSZ) - 1); -} - -void dcache_flush_range(unsigned long start, unsigned long end) -{ - unsigned long line_size; - - line_size = CACHE_LINE_SIZE(DCACHE); - - while (end > start) { - __asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start)); - __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)); - start += line_size; - } -} - -void icache_inval_range(unsigned long start, unsigned long end) -{ - unsigned long line_size; - - line_size = CACHE_LINE_SIZE(ICACHE); - while (end > start) { - __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start)); - start += line_size; - } -} - -void flush_cache(unsigned long addr, unsigned long size) -{ - dcache_flush_range(addr, addr + size); - icache_inval_range(addr, addr + size); -} - -void icache_enable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "ori $p0, $p0, 0x01\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -void icache_disable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "li $p1, ~0x01\n\t" - "and $p0, $p0, $p1\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -int icache_status(void) -{ - int ret; - - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "andi %0, $p0, 0x01\n\t" - : "=r" (ret) - : - : "memory" - ); - - return ret; -} - -void dcache_enable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "ori $p0, $p0, 0x02\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -void dcache_disable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "li $p1, ~0x02\n\t" - "and $p0, $p0, $p1\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -int dcache_status(void) -{ - int ret; - - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "andi %0, $p0, 0x02\n\t" - : "=r" (ret) - : - : "memory" - ); - - return ret; -} diff --git a/arch/nds32/cpu/n1213/ag102/cpu.c b/arch/nds32/cpu/n1213/ag102/cpu.c index ed88b52..252b69d 100644 --- a/arch/nds32/cpu/n1213/ag102/cpu.c +++ b/arch/nds32/cpu/n1213/ag102/cpu.c @@ -81,115 +81,3 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
/*NOTREACHED*/ } - -static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) -{ - if (cache == ICACHE) - return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \ - >> ICM_CFG_OFF_ISZ) - 1); - else - return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \ - >> DCM_CFG_OFF_DSZ) - 1); -} - -void dcache_flush_range(unsigned long start, unsigned long end) -{ - unsigned long line_size; - - line_size = CACHE_LINE_SIZE(DCACHE); - - while (end > start) { - __asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start)); - __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)); - start += line_size; - } -} - -void icache_inval_range(unsigned long start, unsigned long end) -{ - unsigned long line_size; - - line_size = CACHE_LINE_SIZE(ICACHE); - while (end > start) { - __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start)); - start += line_size; - } -} - -void flush_cache(unsigned long addr, unsigned long size) -{ - dcache_flush_range(addr, addr + size); - icache_inval_range(addr, addr + size); -} - -void icache_enable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "ori $p0, $p0, 0x01\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -void icache_disable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "li $p1, ~0x01\n\t" - "and $p0, $p0, $p1\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -int icache_status(void) -{ - int ret; - - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "andi %0, $p0, 0x01\n\t" - : "=r" (ret) - : - : "memory" - ); - - return ret; -} - -void dcache_enable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "ori $p0, $p0, 0x02\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -void dcache_disable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "li $p1, ~0x02\n\t" - "and $p0, $p0, $p1\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -int dcache_status(void) -{ - int ret; - - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "andi %0, $p0, 0x02\n\t" - : "=r" (ret) - : - : "memory" - ); - - return ret; -} diff --git a/arch/nds32/lib/Makefile b/arch/nds32/lib/Makefile index e5c31c3..581a2e7 100644 --- a/arch/nds32/lib/Makefile +++ b/arch/nds32/lib/Makefile @@ -29,7 +29,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(ARCH).o
-OBJS := board.o bootm.o interrupts.o +OBJS := board.o bootm.o cache.o interrupts.o
all: $(LIB)
diff --git a/arch/nds32/lib/cache.c b/arch/nds32/lib/cache.c new file mode 100644 index 0000000..08af1ef --- /dev/null +++ b/arch/nds32/lib/cache.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2012 Andes Technology Corporation + * Shawn Lin, Andes Technology Corporation nobuhiro@andestech.com + * Macpaul Lin, Andes Technology Corporation macpaul@andestech.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> + +static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) +{ + if (cache == ICACHE) + return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \ + >> ICM_CFG_OFF_ISZ) - 1); + else + return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \ + >> DCM_CFG_OFF_DSZ) - 1); +} + +void flush_dcache_range(unsigned long start, unsigned long end) +{ + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(DCACHE); + + while (end > start) { + __asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start)); + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)); + start += line_size; + } +} + +void invalidate_icache_range(unsigned long start, unsigned long end) +{ + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(ICACHE); + while (end > start) { + __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start)); + start += line_size; + } +} + +void invalidate_dcache_range(unsigned long start, unsigned long end) +{ + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(DCACHE); + while (end > start) { + __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)); + start += line_size; + } +} + +void flush_cache(unsigned long addr, unsigned long size) +{ + flush_dcache_range(addr, addr + size); + invalidate_icache_range(addr, addr + size); +} + +void icache_enable(void) +{ + __asm__ __volatile__ ( + "mfsr $p0, $mr8\n\t" + "ori $p0, $p0, 0x01\n\t" + "mtsr $p0, $mr8\n\t" + "isb\n\t" + ); +} + +void icache_disable(void) +{ + __asm__ __volatile__ ( + "mfsr $p0, $mr8\n\t" + "li $p1, ~0x01\n\t" + "and $p0, $p0, $p1\n\t" + "mtsr $p0, $mr8\n\t" + "isb\n\t" + ); +} + +int icache_status(void) +{ + int ret; + + __asm__ __volatile__ ( + "mfsr $p0, $mr8\n\t" + "andi %0, $p0, 0x01\n\t" + : "=r" (ret) + : + : "memory" + ); + + return ret; +} + +void dcache_enable(void) +{ + __asm__ __volatile__ ( + "mfsr $p0, $mr8\n\t" + "ori $p0, $p0, 0x02\n\t" + "mtsr $p0, $mr8\n\t" + "isb\n\t" + ); +} + +void dcache_disable(void) +{ + __asm__ __volatile__ ( + "mfsr $p0, $mr8\n\t" + "li $p1, ~0x02\n\t" + "and $p0, $p0, $p1\n\t" + "mtsr $p0, $mr8\n\t" + "isb\n\t" + ); +} + +int dcache_status(void) +{ + int ret; + + __asm__ __volatile__ ( + "mfsr $p0, $mr8\n\t" + "andi %0, $p0, 0x02\n\t" + : "=r" (ret) + : + : "memory" + ); + + return ret; +}

Dear Macpaul Lin,
This commit does the following updates.
- Split the common cache access from cpu.c into lib folder.
- Rename the following cache api to adapt common.h
- dcache_flush_rang -> flush_dcache_rang
- icache_inval_range -> invalidate_icache_range
- Add invalidate_dcache_range
So basically this connects it to standard cache api?
[...]
diff --git a/arch/nds32/lib/cache.c b/arch/nds32/lib/cache.c
[...]
+static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) +{
- if (cache == ICACHE)
return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
>> ICM_CFG_OFF_ISZ) - 1);
These crazy macros can be probably done easier and can share some code maybe? Maybe not though, I dunno, just a thought.
- else
return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
>> DCM_CFG_OFF_DSZ) - 1);
+}
+void flush_dcache_range(unsigned long start, unsigned long end) +{
- unsigned long line_size;
- line_size = CACHE_LINE_SIZE(DCACHE);
- while (end > start) {
__asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start));
__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));
You probably want to do those two calls in one asm volatile () block. And this too ... use "asm volatile()" and not "__asm__ volatile" or "asm __volatile__" and similar combinations of these, just a nit ;-)
start += line_size;
- }
+}
+void invalidate_icache_range(unsigned long start, unsigned long end) +{
- unsigned long line_size;
- line_size = CACHE_LINE_SIZE(ICACHE);
- while (end > start) {
__asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start));
start += line_size;
- }
+}
+void invalidate_dcache_range(unsigned long start, unsigned long end) +{
- unsigned long line_size;
- line_size = CACHE_LINE_SIZE(DCACHE);
- while (end > start) {
__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));
start += line_size;
- }
+}
+void flush_cache(unsigned long addr, unsigned long size) +{
- flush_dcache_range(addr, addr + size);
- invalidate_icache_range(addr, addr + size);
You probably want to flush dcache in here and that's it.
+}
+void icache_enable(void) +{
- __asm__ __volatile__ (
See my nit above for the rest ;-) But all in all it's good, we should be applying this around V2-V3 of this patch, for the -next release. Thanks for your patch!

Hi Marek,
2012/7/15 Marek Vasut marex@denx.de:
Dear Macpaul Lin,
This commit does the following updates.
- Split the common cache access from cpu.c into lib folder.
- Rename the following cache api to adapt common.h
- dcache_flush_rang -> flush_dcache_rang
- icache_inval_range -> invalidate_icache_range
- Add invalidate_dcache_range
So basically this connects it to standard cache api?
Yes! Basically this is compatible with all nds32 cpu family if they have cache inside. The cache is configurable by the customer if they used softcore FPGA. This API could help them to figure out the hardware configuration in software level.
[...]
diff --git a/arch/nds32/lib/cache.c b/arch/nds32/lib/cache.c
[...]
+static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) +{
if (cache == ICACHE)
return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
>> ICM_CFG_OFF_ISZ) - 1);
These crazy macros can be probably done easier and can share some code maybe? Maybe not though, I dunno, just a thought.
The macro GET_ICM_CFG() is inside arch/nds32/include/cache.h #define DEFINE_GET_SYS_REG(reg) \ static inline unsigned long GET_##reg(void) \
Since the assembly is really long, rewrite them into macros should be easier to maintain and read. I'll prefer not to modify this function to call CACHE_LINE_SIZE.
+void flush_dcache_range(unsigned long start, unsigned long end)
while (end > start) {
__asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start));
__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));
You probably want to do those two calls in one asm volatile () block. And this too ... use "asm volatile()" and not "__asm__ volatile" or "asm __volatile__" and similar combinations of these, just a nit ;-)
Ok, it will be fixed. :)
+void flush_cache(unsigned long addr, unsigned long size) +{
flush_dcache_range(addr, addr + size);
invalidate_icache_range(addr, addr + size);
You probably want to flush dcache in here and that's it.
+}
+void icache_enable(void) +{
__asm__ __volatile__ (
See my nit above for the rest ;-) But all in all it's good, we should be applying this around V2-V3 of this patch, for the -next release. Thanks for your patch!
It looks like this fix cannot be checkin before this coming rc1 or rc2. But I think it is okay for users to wait until the -next release. :)

This commit does the following updates. 1. Split the common cache access from cpu.c into lib folder. 2. Rename the following cache api to adapt common.h - dcache_flush_rang -> flush_dcache_rang - icache_inval_range -> invalidate_icache_range 3. Add invalidate_dcache_range
Signed-off-by: Macpaul Lin macpaul@gmail.com --- Changes for v2: - flush_dcache_range: merge two asm calls into a single asm volatile() block. - Replace __asm__ __volatile__ block into asm volatile()
arch/nds32/cpu/n1213/ag101/cpu.c | 112 --------------------------- arch/nds32/cpu/n1213/ag102/cpu.c | 112 --------------------------- arch/nds32/lib/Makefile | 2 +- arch/nds32/lib/cache.c | 157 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+), 225 deletions(-) create mode 100644 arch/nds32/lib/cache.c
diff --git a/arch/nds32/cpu/n1213/ag101/cpu.c b/arch/nds32/cpu/n1213/ag101/cpu.c index c2636b1..a9991e7 100644 --- a/arch/nds32/cpu/n1213/ag101/cpu.c +++ b/arch/nds32/cpu/n1213/ag101/cpu.c @@ -82,115 +82,3 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
/*NOTREACHED*/ } - -static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) -{ - if (cache == ICACHE) - return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \ - >> ICM_CFG_OFF_ISZ) - 1); - else - return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \ - >> DCM_CFG_OFF_DSZ) - 1); -} - -void dcache_flush_range(unsigned long start, unsigned long end) -{ - unsigned long line_size; - - line_size = CACHE_LINE_SIZE(DCACHE); - - while (end > start) { - __asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start)); - __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)); - start += line_size; - } -} - -void icache_inval_range(unsigned long start, unsigned long end) -{ - unsigned long line_size; - - line_size = CACHE_LINE_SIZE(ICACHE); - while (end > start) { - __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start)); - start += line_size; - } -} - -void flush_cache(unsigned long addr, unsigned long size) -{ - dcache_flush_range(addr, addr + size); - icache_inval_range(addr, addr + size); -} - -void icache_enable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "ori $p0, $p0, 0x01\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -void icache_disable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "li $p1, ~0x01\n\t" - "and $p0, $p0, $p1\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -int icache_status(void) -{ - int ret; - - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "andi %0, $p0, 0x01\n\t" - : "=r" (ret) - : - : "memory" - ); - - return ret; -} - -void dcache_enable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "ori $p0, $p0, 0x02\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -void dcache_disable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "li $p1, ~0x02\n\t" - "and $p0, $p0, $p1\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -int dcache_status(void) -{ - int ret; - - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "andi %0, $p0, 0x02\n\t" - : "=r" (ret) - : - : "memory" - ); - - return ret; -} diff --git a/arch/nds32/cpu/n1213/ag102/cpu.c b/arch/nds32/cpu/n1213/ag102/cpu.c index ed88b52..252b69d 100644 --- a/arch/nds32/cpu/n1213/ag102/cpu.c +++ b/arch/nds32/cpu/n1213/ag102/cpu.c @@ -81,115 +81,3 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
/*NOTREACHED*/ } - -static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) -{ - if (cache == ICACHE) - return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \ - >> ICM_CFG_OFF_ISZ) - 1); - else - return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \ - >> DCM_CFG_OFF_DSZ) - 1); -} - -void dcache_flush_range(unsigned long start, unsigned long end) -{ - unsigned long line_size; - - line_size = CACHE_LINE_SIZE(DCACHE); - - while (end > start) { - __asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start)); - __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)); - start += line_size; - } -} - -void icache_inval_range(unsigned long start, unsigned long end) -{ - unsigned long line_size; - - line_size = CACHE_LINE_SIZE(ICACHE); - while (end > start) { - __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start)); - start += line_size; - } -} - -void flush_cache(unsigned long addr, unsigned long size) -{ - dcache_flush_range(addr, addr + size); - icache_inval_range(addr, addr + size); -} - -void icache_enable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "ori $p0, $p0, 0x01\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -void icache_disable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "li $p1, ~0x01\n\t" - "and $p0, $p0, $p1\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -int icache_status(void) -{ - int ret; - - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "andi %0, $p0, 0x01\n\t" - : "=r" (ret) - : - : "memory" - ); - - return ret; -} - -void dcache_enable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "ori $p0, $p0, 0x02\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -void dcache_disable(void) -{ - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "li $p1, ~0x02\n\t" - "and $p0, $p0, $p1\n\t" - "mtsr $p0, $mr8\n\t" - "isb\n\t" - ); -} - -int dcache_status(void) -{ - int ret; - - __asm__ __volatile__ ( - "mfsr $p0, $mr8\n\t" - "andi %0, $p0, 0x02\n\t" - : "=r" (ret) - : - : "memory" - ); - - return ret; -} diff --git a/arch/nds32/lib/Makefile b/arch/nds32/lib/Makefile index e5c31c3..581a2e7 100644 --- a/arch/nds32/lib/Makefile +++ b/arch/nds32/lib/Makefile @@ -29,7 +29,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(ARCH).o
-OBJS := board.o bootm.o interrupts.o +OBJS := board.o bootm.o cache.o interrupts.o
all: $(LIB)
diff --git a/arch/nds32/lib/cache.c b/arch/nds32/lib/cache.c new file mode 100644 index 0000000..0f1a886 --- /dev/null +++ b/arch/nds32/lib/cache.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2012 Andes Technology Corporation + * Shawn Lin, Andes Technology Corporation nobuhiro@andestech.com + * Macpaul Lin, Andes Technology Corporation macpaul@andestech.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> + +static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) +{ + if (cache == ICACHE) + return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \ + >> ICM_CFG_OFF_ISZ) - 1); + else + return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \ + >> DCM_CFG_OFF_DSZ) - 1); +} + +void flush_dcache_range(unsigned long start, unsigned long end) +{ + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(DCACHE); + + while (end > start) { + asm volatile ( + "\n\tcctl %0, L1D_VA_WB" + "\n\tcctl %0, L1D_VA_INVAL" + : + : "r" (start) + ); + start += line_size; + } +} + +void invalidate_icache_range(unsigned long start, unsigned long end) +{ + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(ICACHE); + while (end > start) { + asm volatile ( + "\n\tcctl %0, L1I_VA_INVAL" + : + : "r"(start) + ); + start += line_size; + } +} + +void invalidate_dcache_range(unsigned long start, unsigned long end) +{ + unsigned long line_size; + + line_size = CACHE_LINE_SIZE(DCACHE); + while (end > start) { + asm volatile ( + "\n\tcctl %0, L1D_VA_INVAL" + : + : "r"(start) + ); + start += line_size; + } +} + +void flush_cache(unsigned long addr, unsigned long size) +{ + flush_dcache_range(addr, addr + size); + invalidate_icache_range(addr, addr + size); +} + +void icache_enable(void) +{ + asm volatile ( + "mfsr $p0, $mr8\n\t" + "ori $p0, $p0, 0x01\n\t" + "mtsr $p0, $mr8\n\t" + "isb\n\t" + ); +} + +void icache_disable(void) +{ + asm volatile ( + "mfsr $p0, $mr8\n\t" + "li $p1, ~0x01\n\t" + "and $p0, $p0, $p1\n\t" + "mtsr $p0, $mr8\n\t" + "isb\n\t" + ); +} + +int icache_status(void) +{ + int ret; + + asm volatile ( + "mfsr $p0, $mr8\n\t" + "andi %0, $p0, 0x01\n\t" + : "=r" (ret) + : + : "memory" + ); + + return ret; +} + +void dcache_enable(void) +{ + asm volatile ( + "mfsr $p0, $mr8\n\t" + "ori $p0, $p0, 0x02\n\t" + "mtsr $p0, $mr8\n\t" + "isb\n\t" + ); +} + +void dcache_disable(void) +{ + asm volatile ( + "mfsr $p0, $mr8\n\t" + "li $p1, ~0x02\n\t" + "and $p0, $p0, $p1\n\t" + "mtsr $p0, $mr8\n\t" + "isb\n\t" + ); +} + +int dcache_status(void) +{ + int ret; + + asm volatile ( + "mfsr $p0, $mr8\n\t" + "andi %0, $p0, 0x02\n\t" + : "=r" (ret) + : + : "memory" + ); + + return ret; +}

Hi Macpaul,
2012/7/17 Macpaul Lin macpaul@gmail.com
This commit does the following updates.
- Split the common cache access from cpu.c into lib folder.
- Rename the following cache api to adapt common.h
- dcache_flush_rang -> flush_dcache_rang
- icache_inval_range -> invalidate_icache_range
- Add invalidate_dcache_range
Signed-off-by: Macpaul Lin macpaul@gmail.com
Changes for v2:
- flush_dcache_range: merge two asm calls into a single asm volatile() block.
- Replace __asm__ __volatile__ block into asm volatile()
This commit has been applied into u-boot-nds32/master
Thanks!

On Sunday 15 July 2012 04:12:45 Marek Vasut wrote:
Dear Macpaul Lin,
+void flush_cache(unsigned long addr, unsigned long size) +{
- flush_dcache_range(addr, addr + size);
- invalidate_icache_range(addr, addr + size);
You probably want to flush dcache in here and that's it.
i don't think so ... i think that's what flush_dcache_range() is for. and our common/cmd_*.c files assume that flush_cache() will invalidate icache (see the bootm/load funcs that write executable content into memory and then flush the regions). -mike

Hi Mike
2012/7/19 Mike Frysinger vapier@gentoo.org
On Sunday 15 July 2012 04:12:45 Marek Vasut wrote:
Dear Macpaul Lin,
+void flush_cache(unsigned long addr, unsigned long size) +{
- flush_dcache_range(addr, addr + size);
- invalidate_icache_range(addr, addr + size);
You probably want to flush dcache in here and that's it.
i don't think so ... i think that's what flush_dcache_range() is for. and our common/cmd_*.c files assume that flush_cache() will invalidate icache (see the bootm/load funcs that write executable content into memory and then flush the regions). -mike
Thanks for clarification. The patch v2 I've submitted 2 days ago didn't add a dcache flush here. :-)

Dear Mike Frysinger,
On Sunday 15 July 2012 04:12:45 Marek Vasut wrote:
Dear Macpaul Lin,
+void flush_cache(unsigned long addr, unsigned long size) +{
- flush_dcache_range(addr, addr + size);
- invalidate_icache_range(addr, addr + size);
You probably want to flush dcache in here and that's it.
i don't think so ... i think that's what flush_dcache_range() is for. and our common/cmd_*.c files assume that flush_cache() will invalidate icache (see the bootm/load funcs that write executable content into memory and then flush the regions).
Than it's borked on arm926ejs too ... ?
Best regards, Marek Vasut

On Thursday 19 July 2012 05:02:21 Marek Vasut wrote:
Dear Mike Frysinger,
On Sunday 15 July 2012 04:12:45 Marek Vasut wrote:
Dear Macpaul Lin,
+void flush_cache(unsigned long addr, unsigned long size) +{
- flush_dcache_range(addr, addr + size);
- invalidate_icache_range(addr, addr + size);
You probably want to flush dcache in here and that's it.
i don't think so ... i think that's what flush_dcache_range() is for. and our common/cmd_*.c files assume that flush_cache() will invalidate icache (see the bootm/load funcs that write executable content into memory and then flush the regions).
Than it's borked on arm926ejs too ... ?
if it doesn't flush icache in the flush_cache() function, then i would say so
sounds like we should rip all this cache stuff out of common.h and into like cache.h so we can document the API expectations. i think Wolfgang was against this before, but maybe that was just creating a header for one specific cache macro and not all cache stuff ? -mike

Dear Mike Frysinger,
On Thursday 19 July 2012 05:02:21 Marek Vasut wrote:
Dear Mike Frysinger,
On Sunday 15 July 2012 04:12:45 Marek Vasut wrote:
Dear Macpaul Lin,
+void flush_cache(unsigned long addr, unsigned long size) +{
- flush_dcache_range(addr, addr + size);
- invalidate_icache_range(addr, addr + size);
You probably want to flush dcache in here and that's it.
i don't think so ... i think that's what flush_dcache_range() is for. and our common/cmd_*.c files assume that flush_cache() will invalidate icache (see the bootm/load funcs that write executable content into memory and then flush the regions).
Than it's borked on arm926ejs too ... ?
if it doesn't flush icache in the flush_cache() function, then i would say so
sounds like we should rip all this cache stuff out of common.h and into like cache.h so we can document the API expectations. i think Wolfgang was against this before, but maybe that was just creating a header for one specific cache macro and not all cache stuff ?
Certainly this sounds good. We'd also be able to add some nice instrumentation while at that, to detect problematic cases with DEBUG enabled or so. The cache stuff is starting to get really crazy.
Best regards, Marek Vasut

Hi Marek and Mike,
sounds like we should rip all this cache stuff out of common.h and into
like cache.h so we can document the API expectations. i think Wolfgang was against this before, but maybe that was just creating a header for
one
specific cache macro and not all cache stuff ?
Certainly this sounds good. We'd also be able to add some nice instrumentation while at that, to detect problematic cases with DEBUG enabled or so. The cache stuff is starting to get really crazy.
Best regards, Marek Vasut
Since this discussion hasn't been finished, and we haven't decide the final action about the new policy about cache.h and common.h. I'd like to pick this patch v2 for the coming release for fixing build error for board adp-ag102. What do you think? :-)

On Friday 20 July 2012 04:24:55 Macpaul Lin wrote:
Since this discussion hasn't been finished, and we haven't decide the final action about the new policy about cache.h and common.h. I'd like to pick this patch v2 for the coming release for fixing build error for board adp-ag102. What do you think? :-)
i don't think the topic of cleaning up common code impedes you merging your nds32 cache clean ups at all. they're orthogonal issues. -mike
participants (3)
-
Macpaul Lin
-
Marek Vasut
-
Mike Frysinger