/* * Cache control for MicroBlaze cache memories * * Copyright (C) 2007-2009 Michal Simek * Copyright (C) 2007-2009 PetaLogix * Copyright (C) 2007 John Williams * * 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 #include #include /* Exported functions */ void _enable_icache(void) { if (cpuinfo.use_icache) { #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR __asm__ __volatile__ (" \ msrset r0, %0; \ nop; " \ : \ : "i" (MSR_ICE) \ : "memory"); #else __asm__ __volatile__ (" \ mfs r12, rmsr; \ nop; \ ori r12, r12, %0; \ mts rmsr, r12; \ nop; " \ : \ : "i" (MSR_ICE) \ : "memory", "r12"); #endif } } void _disable_icache(void) { if (cpuinfo.use_icache) { #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR __asm__ __volatile__ (" \ msrclr r0, %0; \ nop; " \ : \ : "i" (MSR_ICE) \ : "memory"); #else __asm__ __volatile__ (" \ mfs r12, rmsr; \ nop; \ andi r12, r12, ~%0; \ mts rmsr, r12; \ nop; " \ : \ : "i" (MSR_ICE) \ : "memory", "r12"); #endif } } void _invalidate_icache(unsigned int addr) { if (cpuinfo.use_icache) { __asm__ __volatile__ (" \ wic %0, r0" \ : \ : "r" (addr)); } } void _enable_dcache(void) { if (cpuinfo.use_dcache) { #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR __asm__ __volatile__ (" \ msrset r0, %0; \ nop; " \ : \ : "i" (MSR_DCE) \ : "memory"); #else __asm__ __volatile__ (" \ mfs r12, rmsr; \ nop; \ ori r12, r12, %0; \ mts rmsr, r12; \ nop; " \ : \ : "i" (MSR_DCE) \ : "memory", "r12"); #endif } } void _disable_dcache(void) { #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR __asm__ __volatile__ (" \ msrclr r0, %0; \ nop; " \ : \ : "i" (MSR_DCE) \ : "memory"); #else __asm__ __volatile__ (" \ mfs r12, rmsr; \ nop; \ andi r12, r12, ~%0; \ mts rmsr, r12; \ nop; " \ : \ : "i" (MSR_DCE) \ : "memory", "r12"); #endif } void _invalidate_dcache(unsigned int addr) { __asm__ __volatile__ (" \ wdc %0, r0" \ : \ : "r" (addr)); } void __invalidate_icache_all(void) { unsigned int i; unsigned flags; if (cpuinfo.use_icache) { local_irq_save(flags); __disable_icache(); /* Just loop through cache size and invalidate, no need to add CACHE_BASE address */ for (i = 0; i < cpuinfo.icache_size; i += cpuinfo.icache_line) __invalidate_icache(i); __enable_icache(); local_irq_restore(flags); } } void __invalidate_icache_range(unsigned long start, unsigned long end) { unsigned int i; unsigned flags; unsigned int align; if (cpuinfo.use_icache) { /* * No need to cover entire cache range, * just cover cache footprint */ end = min(start + cpuinfo.icache_size, end); align = ~(cpuinfo.icache_line - 1); start &= align; /* Make sure we are aligned */ /* Push end up to the next cache line */ end = ((end & align) + cpuinfo.icache_line); local_irq_save(flags); __disable_icache(); for (i = start; i < end; i += cpuinfo.icache_line) __invalidate_icache(i); __enable_icache(); local_irq_restore(flags); } } void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page) { __invalidate_icache_all(); } void __invalidate_icache_user_range(struct vm_area_struct *vma, struct page *page, unsigned long adr, int len) { __invalidate_icache_all(); } void __invalidate_cache_sigtramp(unsigned long addr) { __invalidate_icache_range(addr, addr + 8); } void __invalidate_dcache_all(void) { unsigned int i; unsigned flags; if (cpuinfo.use_dcache) { local_irq_save(flags); __disable_dcache(); /* * Just loop through cache size and invalidate, * no need to add CACHE_BASE address */ for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line) __invalidate_dcache(i); __enable_dcache(); local_irq_restore(flags); } } void __invalidate_dcache_range(unsigned long start, unsigned long end) { unsigned int i; unsigned flags; unsigned int align; if (cpuinfo.use_dcache) { /* * No need to cover entire cache range, * just cover cache footprint */ end = min(start + cpuinfo.dcache_size, end); align = ~(cpuinfo.dcache_line - 1); start &= align; /* Make sure we are aligned */ /* Push end up to the next cache line */ end = ((end & align) + cpuinfo.dcache_line); local_irq_save(flags); __disable_dcache(); for (i = start; i < end; i += cpuinfo.dcache_line) __invalidate_dcache(i); __enable_dcache(); local_irq_restore(flags); } } void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page) { __invalidate_dcache_all(); } void __invalidate_dcache_user_range(struct vm_area_struct *vma, struct page *page, unsigned long adr, int len) { __invalidate_dcache_all(); }