255 lines · 5.1 KB · C
RawDownload
/* * Cache control for MicroBlaze cache memories * * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> * Copyright (C) 2007-2009 PetaLogix * Copyright (C) 2007 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> /* 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();}