231 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			231 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * File      : cache.c
							 | 
						||
| 
								 | 
							
								 * This file is part of RT-Thread RTOS
							 | 
						||
| 
								 | 
							
								 * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The license and distribution terms for this file may be
							 | 
						||
| 
								 | 
							
								 * found in the file LICENSE in this distribution or at
							 | 
						||
| 
								 | 
							
								 * http://www.rt-thread.org/license/LICENSE
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Change Logs:
							 | 
						||
| 
								 | 
							
								 * Date           Author       Notes
							 | 
						||
| 
								 | 
							
								 * 2010-07-09     Bernard      first version
							 | 
						||
| 
								 | 
							
								 * 2011-08-08     lgnq         modified for LS1B
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								#include <rtthread.h>
							 | 
						||
| 
								 | 
							
								#include "../common/mipsregs.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define K0BASE			0x80000000
							 | 
						||
| 
								 | 
							
								#define PRID_LS1B		0x4220
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								extern void Clear_TagLo (void);
							 | 
						||
| 
								 | 
							
								extern void Invalidate_Icache_Ls1b(unsigned int);
							 | 
						||
| 
								 | 
							
								extern void Invalidate_Dcache_ClearTag_Ls1b(unsigned int);
							 | 
						||
| 
								 | 
							
								extern void Invalidate_Dcache_Fill_Ls1b(unsigned int);
							 | 
						||
| 
								 | 
							
								extern void Writeback_Invalidate_Dcache(unsigned int);
							 | 
						||
| 
								 | 
							
								extern void enable_cpu_cache(void);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct cacheinfo_t 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									unsigned int	icache_size;
							 | 
						||
| 
								 | 
							
									unsigned int	dcache_size;
							 | 
						||
| 
								 | 
							
									unsigned int	icacheline_size;
							 | 
						||
| 
								 | 
							
									unsigned int	dcacheline_size;
							 | 
						||
| 
								 | 
							
								} cacheinfo_t ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct cacheop_t 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									void (*Clear_TagLo) (void);
							 | 
						||
| 
								 | 
							
									void (*Invalidate_Icache) (unsigned int);
							 | 
						||
| 
								 | 
							
									void (*Invalidate_Dcache_Fill) (unsigned int);
							 | 
						||
| 
								 | 
							
									void (*Invalidate_Dcache_ClearTag) (unsigned int);
							 | 
						||
| 
								 | 
							
									void (*Init_Cache)(void);
							 | 
						||
| 
								 | 
							
								} cacheop_t ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static cacheop_t cacheop, *pcacheop;
							 | 
						||
| 
								 | 
							
								static cacheinfo_t cacheinfo, *pcacheinfo;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int identify_cpu(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    unsigned int cpu_id;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    pcacheop = &cacheop;
							 | 
						||
| 
								 | 
							
								    pcacheinfo = &cacheinfo;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									rt_kprintf("CPU configure: 0x%08x\n", read_c0_config());
							 | 
						||
| 
								 | 
							
								    cpu_id = read_c0_prid();
							 | 
						||
| 
								 | 
							
								    switch (cpu_id)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									case PRID_LS1B:       
							 | 
						||
| 
								 | 
							
									    rt_kprintf("CPU:LS1B\n");
							 | 
						||
| 
								 | 
							
									    pcacheop->Clear_TagLo = Clear_TagLo;
							 | 
						||
| 
								 | 
							
									    pcacheop->Invalidate_Icache = Invalidate_Icache_Ls1b;
							 | 
						||
| 
								 | 
							
									    pcacheop->Invalidate_Dcache_Fill = Invalidate_Dcache_Fill_Ls1b;
							 | 
						||
| 
								 | 
							
									    pcacheop->Invalidate_Dcache_ClearTag = Invalidate_Dcache_ClearTag_Ls1b;
							 | 
						||
| 
								 | 
							
									    break;
							 | 
						||
| 
								 | 
							
									default:
							 | 
						||
| 
								 | 
							
									    rt_kprintf("Unknown CPU type, system halted!\n");
							 | 
						||
| 
								 | 
							
									    while (1) 
							 | 
						||
| 
								 | 
							
									    {
							 | 
						||
| 
								 | 
							
									    	;
							 | 
						||
| 
								 | 
							
									    }
							 | 
						||
| 
								 | 
							
									    break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void probe_cache(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    unsigned int config1 = read_c0_config1();
							 | 
						||
| 
								 | 
							
								    unsigned int icache_size, icache_line_size, icache_sets, icache_ways;
							 | 
						||
| 
								 | 
							
								    unsigned int dcache_size, dcache_line_size, dcache_sets, dcache_ways;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ((icache_line_size = ((config1 >> 19) & 7)))
							 | 
						||
| 
								 | 
							
								        icache_line_size = 2 << icache_line_size;
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								        icache_line_size = icache_line_size;
							 | 
						||
| 
								 | 
							
								    icache_sets = 64 << ((config1 >> 22) & 7);
							 | 
						||
| 
								 | 
							
								    icache_ways = 1 + ((config1 >> 16) & 7);
							 | 
						||
| 
								 | 
							
								    icache_size = icache_sets * icache_ways * icache_line_size;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    if ((dcache_line_size = ((config1 >> 10) & 7)))
							 | 
						||
| 
								 | 
							
								        dcache_line_size = 2 << dcache_line_size;
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								        dcache_line_size = dcache_line_size;
							 | 
						||
| 
								 | 
							
								    dcache_sets = 64 << ((config1 >> 13) & 7);
							 | 
						||
| 
								 | 
							
								    dcache_ways = 1 + ((config1 >> 7) & 7);
							 | 
						||
| 
								 | 
							
								    dcache_size = dcache_sets * dcache_ways * dcache_line_size;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    rt_kprintf("DCache %2dkb, linesize %d bytes.\n", dcache_size >> 10, dcache_line_size);
							 | 
						||
| 
								 | 
							
								    rt_kprintf("ICache %2dkb, linesize %d bytes.\n", icache_size >> 10, icache_line_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    pcacheinfo->icache_size = icache_size;
							 | 
						||
| 
								 | 
							
								    pcacheinfo->dcache_size = dcache_size;
							 | 
						||
| 
								 | 
							
								    pcacheinfo->icacheline_size = icache_line_size;
							 | 
						||
| 
								 | 
							
								    pcacheinfo->dcacheline_size = dcache_line_size;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return ;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void invalidate_writeback_dcache_all(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									unsigned int start = K0BASE;
							 | 
						||
| 
								 | 
							
									unsigned int end = (start + pcacheinfo->dcache_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									while (start < end) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										Writeback_Invalidate_Dcache(start);  //hit writeback invalidate 
							 | 
						||
| 
								 | 
							
										start += pcacheinfo->dcacheline_size;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void invalidate_writeback_dcache(unsigned long addr, int size)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									unsigned long start, end;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
									start = (addr +pcacheinfo->dcacheline_size -1) & (- pcacheinfo->dcacheline_size);
							 | 
						||
| 
								 | 
							
									end = (end + size + pcacheinfo->dcacheline_size -1) & ( -pcacheinfo->dcacheline_size);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									while (start <end)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										Writeback_Invalidate_Dcache(start);
							 | 
						||
| 
								 | 
							
										start += pcacheinfo->dcacheline_size;
							 | 
						||
| 
								 | 
							
									}		
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void invalidate_icache_all(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									unsigned int start = K0BASE;
							 | 
						||
| 
								 | 
							
									unsigned int end = (start + pcacheinfo->icache_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									while (start < end) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										pcacheop->Invalidate_Icache(start); 
							 | 
						||
| 
								 | 
							
										start += pcacheinfo->icacheline_size;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void invalidate_dcache_all(void)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
									unsigned int start = K0BASE;
							 | 
						||
| 
								 | 
							
									unsigned int end  = (start + pcacheinfo->dcache_size);
							 | 
						||
| 
								 | 
							
									while (start <end)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										Invalidate_Dcache_Fill_Ls1b(start);
							 | 
						||
| 
								 | 
							
										start += pcacheinfo->icacheline_size;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//with cache disabled
							 | 
						||
| 
								 | 
							
								void init_dcache(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									unsigned int start = K0BASE;
							 | 
						||
| 
								 | 
							
									unsigned int end = (start + pcacheinfo->dcache_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									while (start < end)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										pcacheop->Invalidate_Dcache_ClearTag(start);
							 | 
						||
| 
								 | 
							
										start += pcacheinfo->dcacheline_size;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void rt_hw_cache_init(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    unsigned int start, end;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									/* 1. identify cpu and probe cache */
							 | 
						||
| 
								 | 
							
									identify_cpu();
							 | 
						||
| 
								 | 
							
									probe_cache();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									start = K0BASE;
							 | 
						||
| 
								 | 
							
									end = (start + pcacheinfo->icache_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     *	2. clear CP0 taglo/taghi register;
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    pcacheop->Clear_TagLo();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/*
							 | 
						||
| 
								 | 
							
								     *	3. invalidate instruction cache;
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    while (start < end) 
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
										pcacheop->Invalidate_Icache(start); //index invalidate icache 
							 | 
						||
| 
								 | 
							
										start += pcacheinfo->icacheline_size;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     *	4. invalidate data cache;
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    start = K0BASE;
							 | 
						||
| 
								 | 
							
								    end = (start + pcacheinfo->dcache_size);
							 | 
						||
| 
								 | 
							
								    while(start < end) 
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
										pcacheop->Invalidate_Dcache_ClearTag(start); 
							 | 
						||
| 
								 | 
							
										start += pcacheinfo->dcacheline_size;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    start = K0BASE;
							 | 
						||
| 
								 | 
							
								    while(start < end) 
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
										pcacheop->Invalidate_Dcache_Fill(start);  //index invalidate dcache
							 | 
						||
| 
								 | 
							
										start += pcacheinfo->dcacheline_size;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    start = K0BASE;
							 | 
						||
| 
								 | 
							
								    while(start < end) 
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
										pcacheop->Invalidate_Dcache_ClearTag(start); 
							 | 
						||
| 
								 | 
							
										start += pcacheinfo->dcacheline_size;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* enable cache */
							 | 
						||
| 
								 | 
							
									enable_cpu_cache();
							 | 
						||
| 
								 | 
							
									rt_kprintf("enable cpu cache done\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return ;
							 | 
						||
| 
								 | 
							
								}
							 |