aboutsummaryrefslogblamecommitdiffstats
path: root/arch/microblaze/kernel/cpu/cache.c
blob: 4b7d8a3f4aef453570a1a0b9aea6c02122ecb0ed (plain) (tree)
1
2
3
4
5
6




                                                          
                                                                      








                                                                      
                    
 
                                            
 

















                                                         
                                            

 
                                             
 



                                                         
                                            










                                                         
                                                   

 
                                               
 







                                                         

 
                                              
 






                                                         
                                                   

 
                                               
 






                                                         
                                                   

 
 




                                                                 




                                                                         







                                                                         
                                                                         
                                                                         
                                                                         







                                                                         



                                                                             
                                                                        


                                                                        


                                                                         
                                                                         
                                                                         
                                                                         
                                                                         
                                                                         
                                                                         


                                                                         






                                                                         
                                                                         


                                                                         
                                                                         
                                                                         




                                                                          

            

                
                                                                                
 
                            


                








                                                                         
               
                                                                        




                                                                 

                                 

 

                                                               
 
                            


                

                                                                         
 

                                                                         
 


                                 
               
                                                                        




                                                                 


                                 

 

                                                           
 


                




                                                                         
               
                                                                        




                                                                 




                                            


                



                                   
               
                                                                             





                                                                  






                                              


                



                                   
               
                                                                             





                                                                  

                                 

 
                                          
 


                
                                   
               
                                                                             





                                                                  

 
                                                 
 
                            


                



                                   
               
                                                                             





                                                                  

                                 

 
                                                   
 
                            


                



                                   
               
                                                                             





                                                                  

                                 

 
                                                  
 


                
                                   
               
                                                                            





                                                                  

 





                                                                       
                                            
 


                
                                   
               

                                                                       


                                                 
                                                                  

                                                     




                                                                  


                




                                                                         
               
                                                                              
     
                                                                 


                                                                         




                                                                          


                




                                                                         
               
                                                                        
     
                                                                 


                                                                 

 

                                                                          
 
                            


                







                                                                         
               
                                                                        
     
                                                                 


                                                                 








                                                                          


                








                                                                         
               
                                                                        
     
                                                                 


                                                                 






                                       


                
                                   
               

                                                                       





                                                                          

 
                                                                           
 


                




                                                                         
               
                                                                              
     
                                                                 


                                                                         





                                            
                                     














                                                          
                                       














                                                              
                                     













                                                     
                                       














                                                      
                                           













                                                   
                                             

















                                                                            
                                                   






                                                       
                                                                















                                                                               
                                                                












                                                                               




                                                                        



                            
 
/*
 * 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 {									\
	int volatile temp;						\
	int align = ~(line_length - 1);					\
	end = ((end & align) == end) ? end - line_length : end & align;	\
	WARN_ON(end - start < 0);					\
									\
	__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
	for (i = start; i < end; i += cpuinfo.dcache_line_length)
		__asm__ __volatile__ ("wdc.flush	%0, r0;"	\
				: : "r" (i));
#endif
}

/* struct for wb caches and for wt caches */
struct scache *mbc;

/* new wb cache model */
static const struct scache wb_msr = {
	.ie = __enable_icache_msr,
	.id = __disable_icache_msr,
	.ifl = __flush_icache_all_noirq,
	.iflr = __flush_icache_range_noirq,
	.iin = __flush_icache_all_noirq,
	.iinr = __flush_icache_range_noirq,
	.de = __enable_dcache_msr,
	.dd = __disable_dcache_msr,
	.dfl = __flush_dcache_all_wb,
	.dflr = __flush_dcache_range_wb,
	.din = __invalidate_dcache_all_wb,
	.dinr = __invalidate_dcache_range_wb,
};

/* There is only difference in ie, id, de, dd functions */
static const struct scache wb_nomsr = {
	.ie = __enable_icache_nomsr,
	.id = __disable_icache_nomsr,
	.ifl = __flush_icache_all_noirq,
	.iflr = __flush_icache_range_noirq,
	.iin = __flush_icache_all_noirq,
	.iinr = __flush_icache_range_noirq,
	.de = __enable_dcache_nomsr,
	.dd = __disable_dcache_nomsr,
	.dfl = __flush_dcache_all_wb,
	.dflr = __flush_dcache_range_wb,
	.din = __invalidate_dcache_all_wb,
	.dinr = __invalidate_dcache_range_wb,
};

/* Old wt cache model with disabling irq and turn off cache */
static const struct scache wt_msr = {
	.ie = __enable_icache_msr,
	.id = __disable_icache_msr,
	.ifl = __flush_icache_all_msr_irq,
	.iflr = __flush_icache_range_msr_irq,
	.iin = __flush_icache_all_msr_irq,
	.iinr = __flush_icache_range_msr_irq,
	.de = __enable_dcache_msr,
	.dd = __disable_dcache_msr,
	.dfl = __invalidate_dcache_all_msr_irq,
	.dflr = __invalidate_dcache_range_msr_irq_wt,
	.din = __invalidate_dcache_all_msr_irq,
	.dinr = __invalidate_dcache_range_msr_irq_wt,
};

static const struct scache wt_nomsr = {
	.ie = __enable_icache_nomsr,
	.id = __disable_icache_nomsr,
	.ifl = __flush_icache_all_nomsr_irq,
	.iflr = __flush_icache_range_nomsr_irq,
	.iin = __flush_icache_all_nomsr_irq,
	.iinr = __flush_icache_range_nomsr_irq,
	.de = __enable_dcache_nomsr,
	.dd = __disable_dcache_nomsr,
	.dfl = __invalidate_dcache_all_nomsr_irq,
	.dflr = __invalidate_dcache_range_nomsr_irq,
	.din = __invalidate_dcache_all_nomsr_irq,
	.dinr = __invalidate_dcache_range_nomsr_irq,
};

/* New wt cache model for newer Microblaze versions */
static const struct scache wt_msr_noirq = {
	.ie = __enable_icache_msr,
	.id = __disable_icache_msr,
	.ifl = __flush_icache_all_noirq,
	.iflr = __flush_icache_range_noirq,
	.iin = __flush_icache_all_noirq,
	.iinr = __flush_icache_range_noirq,
	.de = __enable_dcache_msr,
	.dd = __disable_dcache_msr,
	.dfl = __invalidate_dcache_all_noirq_wt,
	.dflr = __invalidate_dcache_range_nomsr_wt,
	.din = __invalidate_dcache_all_noirq_wt,
	.dinr = __invalidate_dcache_range_nomsr_wt,
};

static const struct scache wt_nomsr_noirq = {
	.ie = __enable_icache_nomsr,
	.id = __disable_icache_nomsr,
	.ifl = __flush_icache_all_noirq,
	.iflr = __flush_icache_range_noirq,
	.iin = __flush_icache_all_noirq,
	.iinr = __flush_icache_range_noirq,
	.de = __enable_dcache_nomsr,
	.dd = __disable_dcache_nomsr,
	.dfl = __invalidate_dcache_all_noirq_wt,
	.dflr = __invalidate_dcache_range_nomsr_wt,
	.din = __invalidate_dcache_all_noirq_wt,
	.dinr = __invalidate_dcache_range_nomsr_wt,
};

/* CPU version code for 7.20.c - see arch/microblaze/kernel/cpu/cpuinfo.c */
#define CPUVER_7_20_A	0x0c
#define CPUVER_7_20_D	0x0f

#define INFO(s)	printk(KERN_INFO "cache: " s "\n");

void microblaze_cache_init(void)
{
	if (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) {
		if (cpuinfo.dcache_wb) {
			INFO("wb_msr");
			mbc = (struct scache *)&wb_msr;
			if (cpuinfo.ver_code <= CPUVER_7_20_D) {
				/* MS: problem with signal handling - hw bug */
				INFO("WB won't work properly");
			}
		} else {
			if (cpuinfo.ver_code >= CPUVER_7_20_A) {
				INFO("wt_msr_noirq");
				mbc = (struct scache *)&wt_msr_noirq;
			} else {
				INFO("wt_msr");
				mbc = (struct scache *)&wt_msr;
			}
		}
	} else {
		if (cpuinfo.dcache_wb) {
			INFO("wb_nomsr");
			mbc = (struct scache *)&wb_nomsr;
			if (cpuinfo.ver_code <= CPUVER_7_20_D) {
				/* MS: problem with signal handling - hw bug */
				INFO("WB won't work properly");
			}
		} else {
			if (cpuinfo.ver_code >= CPUVER_7_20_A) {
				INFO("wt_nomsr_noirq");
				mbc = (struct scache *)&wt_nomsr_noirq;
			} else {
				INFO("wt_nomsr");
				mbc = (struct scache *)&wt_nomsr;
			}
		}
	}
/* FIXME Invalidation is done in U-BOOT
 * WT cache: Data is already written to main memory
 * WB cache: Discard data on noMMU which caused that kernel doesn't boot
 */
	/* invalidate_dcache(); */
	enable_dcache();

	invalidate_icache();
	enable_icache();
}