/* * Cache control for MicroBlaze cache memories * * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> * Copyright (C) 2007-2009 PetaLogix * Copyright (C) 2007-2009 John Williams <john.williams@petalogix.com> * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this * archive for more details. */ #include <asm/cacheflush.h>#include <linux/cache.h>#include <asm/cpuinfo.h>#include <asm/pvr.h> static inline void __enable_icache_msr(void){ __asm__ __volatile__ (" msrset r0, %0;" \ "nop;" \ : : "i" (MSR_ICE) : "memory");} static inline void __disable_icache_msr(void){ __asm__ __volatile__ (" msrclr r0, %0;" \ "nop;" \ : : "i" (MSR_ICE) : "memory");} static inline void __enable_dcache_msr(void){ __asm__ __volatile__ (" msrset r0, %0;" \ "nop;" \ : : "i" (MSR_DCE) : "memory");} static inline void __disable_dcache_msr(void){ __asm__ __volatile__ (" msrclr r0, %0;" \ "nop; " \ : : "i" (MSR_DCE) : "memory");} static inline void __enable_icache_nomsr(void){ __asm__ __volatile__ (" mfs r12, rmsr;" \ "nop;" \ "ori r12, r12, %0;" \ "mts rmsr, r12;" \ "nop;" \ : : "i" (MSR_ICE) : "memory", "r12");} static inline void __disable_icache_nomsr(void){ __asm__ __volatile__ (" mfs r12, rmsr;" \ "nop;" \ "andi r12, r12, ~%0;" \ "mts rmsr, r12;" \ "nop;" \ : : "i" (MSR_ICE) : "memory", "r12");} static inline void __enable_dcache_nomsr(void){ __asm__ __volatile__ (" mfs r12, rmsr;" \ "nop;" \ "ori r12, r12, %0;" \ "mts rmsr, r12;" \ "nop;" \ : : "i" (MSR_DCE) : "memory", "r12");} static inline void __disable_dcache_nomsr(void){ __asm__ __volatile__ (" mfs r12, rmsr;" \ "nop;" \ "andi r12, r12, ~%0;" \ "mts rmsr, r12;" \ "nop;" \ : : "i" (MSR_DCE) : "memory", "r12");} /* Helper macro for computing the limits of cache range loops * * End address can be unaligned which is OK for C implementation. * ASM implementation align it in ASM macros */#define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size) \do { \ int align = ~(cache_line_length - 1); \ end = min(start + cache_size, end); \ start &= align; \} while (0) /* * Helper macro to loop over the specified cache_size/line_length and * execute 'op' on that cacheline */#define CACHE_ALL_LOOP(cache_size, line_length, op) \do { \ unsigned int len = cache_size - line_length; \ int step = -line_length; \ WARN_ON(step >= 0); \ \ __asm__ __volatile__ (" 1: " #op " %0, r0;" \ "bgtid %0, 1b;" \ "addk %0, %0, %1;" \ : : "r" (len), "r" (step) \ : "memory"); \} while (0) /* Used for wdc.flush/clear which can use rB for offset which is not possible * to use for simple wdc or wic. * * start address is cache aligned * end address is not aligned, if end is aligned then I have to subtract * cacheline length because I can't flush/invalidate the next cacheline. * If is not, I align it because I will flush/invalidate whole line. */#define CACHE_RANGE_LOOP_2(start, end, line_length, op) \do { \ int step = -line_length; \ int align = ~(line_length - 1); \ int count; \ end = ((end & align) == end) ? end - line_length : end & align; \ count = end - start; \ WARN_ON(count < 0); \ \ __asm__ __volatile__ (" 1: " #op " %0, %1;" \ "bgtid %1, 1b;" \ "addk %1, %1, %2;" \ : : "r" (start), "r" (count), \ "r" (step) : "memory"); \} while (0) /* It is used only first parameter for OP - for wic, wdc */#define CACHE_RANGE_LOOP_1(start, end, line_length, op) \do { \ unsigned int volatile temp = 0; \ unsigned int align = ~(line_length - 1); \ end = ((end & align) == end) ? end - line_length : end & align; \ WARN_ON(end < start); \ \ __asm__ __volatile__ (" 1: " #op " %1, r0;" \ "cmpu %0, %1, %2;" \ "bgtid %0, 1b;" \ "addk %1, %1, %3;" \ : : "r" (temp), "r" (start), "r" (end), \ "r" (line_length) : "memory"); \} while (0) #define ASM_LOOP static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end){ unsigned long flags;#ifndef ASM_LOOP int i;#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.icache_line_length, cpuinfo.icache_size); local_irq_save(flags); __disable_icache_msr(); #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);#else for (i = start; i < end; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i));#endif __enable_icache_msr(); local_irq_restore(flags);} static void __flush_icache_range_nomsr_irq(unsigned long start, unsigned long end){ unsigned long flags;#ifndef ASM_LOOP int i;#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.icache_line_length, cpuinfo.icache_size); local_irq_save(flags); __disable_icache_nomsr(); #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);#else for (i = start; i < end; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i));#endif __enable_icache_nomsr(); local_irq_restore(flags);} static void __flush_icache_range_noirq(unsigned long start, unsigned long end){#ifndef ASM_LOOP int i;#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.icache_line_length, cpuinfo.icache_size);#ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);#else for (i = start; i < end; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i));#endif} static void __flush_icache_all_msr_irq(void){ unsigned long flags;#ifndef ASM_LOOP int i;#endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_icache_msr();#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);#else for (i = 0; i < cpuinfo.icache_size; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i));#endif __enable_icache_msr(); local_irq_restore(flags);} static void __flush_icache_all_nomsr_irq(void){ unsigned long flags;#ifndef ASM_LOOP int i;#endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_icache_nomsr();#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);#else for (i = 0; i < cpuinfo.icache_size; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i));#endif __enable_icache_nomsr(); local_irq_restore(flags);} static void __flush_icache_all_noirq(void){#ifndef ASM_LOOP int i;#endif pr_debug("%s\n", __func__);#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);#else for (i = 0; i < cpuinfo.icache_size; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i));#endif} static void __invalidate_dcache_all_msr_irq(void){ unsigned long flags;#ifndef ASM_LOOP int i;#endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_dcache_msr();#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);#else for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i));#endif __enable_dcache_msr(); local_irq_restore(flags);} static void __invalidate_dcache_all_nomsr_irq(void){ unsigned long flags;#ifndef ASM_LOOP int i;#endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_dcache_nomsr();#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);#else for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i));#endif __enable_dcache_nomsr(); local_irq_restore(flags);} static void __invalidate_dcache_all_noirq_wt(void){#ifndef ASM_LOOP int i;#endif pr_debug("%s\n", __func__);#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);#else for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i));#endif} /* * FIXME It is blindly invalidation as is expected * but can't be called on noMMU in microblaze_cache_init below * * MS: noMMU kernel won't boot if simple wdc is used * The reason should be that there are discared data which kernel needs */static void __invalidate_dcache_all_wb(void){#ifndef ASM_LOOP int i;#endif pr_debug("%s\n", __func__);#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);#else for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i));#endif} static void __invalidate_dcache_range_wb(unsigned long start, unsigned long end){#ifndef ASM_LOOP int i;#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size);#ifdef ASM_LOOP CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear);#else for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc.clear %0, r0;" \ : : "r" (i));#endif} static void __invalidate_dcache_range_nomsr_wt(unsigned long start, unsigned long end){#ifndef ASM_LOOP int i;#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size); #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);#else for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i));#endif} static void __invalidate_dcache_range_msr_irq_wt(unsigned long start, unsigned long end){ unsigned long flags;#ifndef ASM_LOOP int i;#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size); local_irq_save(flags); __disable_dcache_msr(); #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);#else for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i));#endif __enable_dcache_msr(); local_irq_restore(flags);} static void __invalidate_dcache_range_nomsr_irq(unsigned long start, unsigned long end){ unsigned long flags;#ifndef ASM_LOOP int i;#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size); local_irq_save(flags); __disable_dcache_nomsr(); #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);#else for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i));#endif __enable_dcache_nomsr(); local_irq_restore(flags);} static void __flush_dcache_all_wb(void){#ifndef ASM_LOOP int i;#endif pr_debug("%s\n", __func__);#ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc.flush);#else for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc.flush %0, r0;" \ : : "r" (i));#endif} static void __flush_dcache_range_wb(unsigned long start, unsigned long end){#ifndef ASM_LOOP int i;#endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size);#ifdef ASM_LOOP CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush);#elseLines 1–500 of 655. Load more
/* * Cache control for MicroBlaze cache memories * * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> * Copyright (C) 2007-2009 PetaLogix * Copyright (C) 2007-2009 John Williams <john.williams@petalogix.com> * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this * archive for more details. */ #include <asm/cacheflush.h> #include <linux/cache.h> #include <asm/cpuinfo.h> #include <asm/pvr.h> static inline void __enable_icache_msr(void) { __asm__ __volatile__ (" msrset r0, %0;" \ "nop;" \ : : "i" (MSR_ICE) : "memory"); } static inline void __disable_icache_msr(void) { __asm__ __volatile__ (" msrclr r0, %0;" \ "nop;" \ : : "i" (MSR_ICE) : "memory"); } static inline void __enable_dcache_msr(void) { __asm__ __volatile__ (" msrset r0, %0;" \ "nop;" \ : : "i" (MSR_DCE) : "memory"); } static inline void __disable_dcache_msr(void) { __asm__ __volatile__ (" msrclr r0, %0;" \ "nop; " \ : : "i" (MSR_DCE) : "memory"); } static inline void __enable_icache_nomsr(void) { __asm__ __volatile__ (" mfs r12, rmsr;" \ "nop;" \ "ori r12, r12, %0;" \ "mts rmsr, r12;" \ "nop;" \ : : "i" (MSR_ICE) : "memory", "r12"); } static inline void __disable_icache_nomsr(void) { __asm__ __volatile__ (" mfs r12, rmsr;" \ "nop;" \ "andi r12, r12, ~%0;" \ "mts rmsr, r12;" \ "nop;" \ : : "i" (MSR_ICE) : "memory", "r12"); } static inline void __enable_dcache_nomsr(void) { __asm__ __volatile__ (" mfs r12, rmsr;" \ "nop;" \ "ori r12, r12, %0;" \ "mts rmsr, r12;" \ "nop;" \ : : "i" (MSR_DCE) : "memory", "r12"); } static inline void __disable_dcache_nomsr(void) { __asm__ __volatile__ (" mfs r12, rmsr;" \ "nop;" \ "andi r12, r12, ~%0;" \ "mts rmsr, r12;" \ "nop;" \ : : "i" (MSR_DCE) : "memory", "r12"); } /* Helper macro for computing the limits of cache range loops * * End address can be unaligned which is OK for C implementation. * ASM implementation align it in ASM macros */ #define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size) \ do { \ int align = ~(cache_line_length - 1); \ end = min(start + cache_size, end); \ start &= align; \ } while (0) /* * Helper macro to loop over the specified cache_size/line_length and * execute 'op' on that cacheline */ #define CACHE_ALL_LOOP(cache_size, line_length, op) \ do { \ unsigned int len = cache_size - line_length; \ int step = -line_length; \ WARN_ON(step >= 0); \ \ __asm__ __volatile__ (" 1: " #op " %0, r0;" \ "bgtid %0, 1b;" \ "addk %0, %0, %1;" \ : : "r" (len), "r" (step) \ : "memory"); \ } while (0) /* Used for wdc.flush/clear which can use rB for offset which is not possible * to use for simple wdc or wic. * * start address is cache aligned * end address is not aligned, if end is aligned then I have to subtract * cacheline length because I can't flush/invalidate the next cacheline. * If is not, I align it because I will flush/invalidate whole line. */ #define CACHE_RANGE_LOOP_2(start, end, line_length, op) \ do { \ int step = -line_length; \ int align = ~(line_length - 1); \ int count; \ end = ((end & align) == end) ? end - line_length : end & align; \ count = end - start; \ WARN_ON(count < 0); \ \ __asm__ __volatile__ (" 1: " #op " %0, %1;" \ "bgtid %1, 1b;" \ "addk %1, %1, %2;" \ : : "r" (start), "r" (count), \ "r" (step) : "memory"); \ } while (0) /* It is used only first parameter for OP - for wic, wdc */ #define CACHE_RANGE_LOOP_1(start, end, line_length, op) \ do { \ unsigned int volatile temp = 0; \ unsigned int align = ~(line_length - 1); \ end = ((end & align) == end) ? end - line_length : end & align; \ WARN_ON(end < start); \ \ __asm__ __volatile__ (" 1: " #op " %1, r0;" \ "cmpu %0, %1, %2;" \ "bgtid %0, 1b;" \ "addk %1, %1, %3;" \ : : "r" (temp), "r" (start), "r" (end), \ "r" (line_length) : "memory"); \ } while (0) #define ASM_LOOP static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end) { unsigned long flags; #ifndef ASM_LOOP int i; #endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.icache_line_length, cpuinfo.icache_size); local_irq_save(flags); __disable_icache_msr(); #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); #else for (i = start; i < end; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i)); #endif __enable_icache_msr(); local_irq_restore(flags); } static void __flush_icache_range_nomsr_irq(unsigned long start, unsigned long end) { unsigned long flags; #ifndef ASM_LOOP int i; #endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.icache_line_length, cpuinfo.icache_size); local_irq_save(flags); __disable_icache_nomsr(); #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); #else for (i = start; i < end; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i)); #endif __enable_icache_nomsr(); local_irq_restore(flags); } static void __flush_icache_range_noirq(unsigned long start, unsigned long end) { #ifndef ASM_LOOP int i; #endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.icache_line_length, cpuinfo.icache_size); #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); #else for (i = start; i < end; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i)); #endif } static void __flush_icache_all_msr_irq(void) { unsigned long flags; #ifndef ASM_LOOP int i; #endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_icache_msr(); #ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); #else for (i = 0; i < cpuinfo.icache_size; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i)); #endif __enable_icache_msr(); local_irq_restore(flags); } static void __flush_icache_all_nomsr_irq(void) { unsigned long flags; #ifndef ASM_LOOP int i; #endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_icache_nomsr(); #ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); #else for (i = 0; i < cpuinfo.icache_size; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i)); #endif __enable_icache_nomsr(); local_irq_restore(flags); } static void __flush_icache_all_noirq(void) { #ifndef ASM_LOOP int i; #endif pr_debug("%s\n", __func__); #ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); #else for (i = 0; i < cpuinfo.icache_size; i += cpuinfo.icache_line_length) __asm__ __volatile__ ("wic %0, r0;" \ : : "r" (i)); #endif } static void __invalidate_dcache_all_msr_irq(void) { unsigned long flags; #ifndef ASM_LOOP int i; #endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_dcache_msr(); #ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); #else for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i)); #endif __enable_dcache_msr(); local_irq_restore(flags); } static void __invalidate_dcache_all_nomsr_irq(void) { unsigned long flags; #ifndef ASM_LOOP int i; #endif pr_debug("%s\n", __func__); local_irq_save(flags); __disable_dcache_nomsr(); #ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); #else for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i)); #endif __enable_dcache_nomsr(); local_irq_restore(flags); } static void __invalidate_dcache_all_noirq_wt(void) { #ifndef ASM_LOOP int i; #endif pr_debug("%s\n", __func__); #ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); #else for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i)); #endif } /* * FIXME It is blindly invalidation as is expected * but can't be called on noMMU in microblaze_cache_init below * * MS: noMMU kernel won't boot if simple wdc is used * The reason should be that there are discared data which kernel needs */ static void __invalidate_dcache_all_wb(void) { #ifndef ASM_LOOP int i; #endif pr_debug("%s\n", __func__); #ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); #else for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i)); #endif } static void __invalidate_dcache_range_wb(unsigned long start, unsigned long end) { #ifndef ASM_LOOP int i; #endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size); #ifdef ASM_LOOP CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear); #else for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc.clear %0, r0;" \ : : "r" (i)); #endif } static void __invalidate_dcache_range_nomsr_wt(unsigned long start, unsigned long end) { #ifndef ASM_LOOP int i; #endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size); #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); #else for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i)); #endif } static void __invalidate_dcache_range_msr_irq_wt(unsigned long start, unsigned long end) { unsigned long flags; #ifndef ASM_LOOP int i; #endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size); local_irq_save(flags); __disable_dcache_msr(); #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); #else for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i)); #endif __enable_dcache_msr(); local_irq_restore(flags); } static void __invalidate_dcache_range_nomsr_irq(unsigned long start, unsigned long end) { unsigned long flags; #ifndef ASM_LOOP int i; #endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size); local_irq_save(flags); __disable_dcache_nomsr(); #ifdef ASM_LOOP CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); #else for (i = start; i < end; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc %0, r0;" \ : : "r" (i)); #endif __enable_dcache_nomsr(); local_irq_restore(flags); } static void __flush_dcache_all_wb(void) { #ifndef ASM_LOOP int i; #endif pr_debug("%s\n", __func__); #ifdef ASM_LOOP CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc.flush); #else for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) __asm__ __volatile__ ("wdc.flush %0, r0;" \ : : "r" (i)); #endif } static void __flush_dcache_range_wb(unsigned long start, unsigned long end) { #ifndef ASM_LOOP int i; #endif pr_debug("%s: start 0x%x, end 0x%x\n", __func__, (unsigned int)start, (unsigned int) end); CACHE_LOOP_LIMITS(start, end, cpuinfo.dcache_line_length, cpuinfo.dcache_size); #ifdef ASM_LOOP CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush); #else