148 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Cache code for SPARClite
 | |
|  *
 | |
|  * Copyright (c) 1998 Cygnus Support
 | |
|  *
 | |
|  * The authors hereby grant permission to use, copy, modify, distribute,
 | |
|  * and license this software and its documentation for any purpose, provided
 | |
|  * that existing copyright notices are retained in all copies and that this
 | |
|  * notice is included verbatim in any distributions. No written agreement,
 | |
|  * license, or royalty fee is required for any of the authorized uses.
 | |
|  * Modifications to this software may be copyrighted by their authors
 | |
|  * and need not follow the licensing terms described here, provided that
 | |
|  * the new terms are clearly indicated on the first page of each file where
 | |
|  * they apply.
 | |
|  */
 | |
| 
 | |
| #include "sparclite.h"
 | |
| 
 | |
| /* Ancillary registers on the DANlite */
 | |
| 
 | |
| #define DIAG 30
 | |
| #define ICCR 31
 | |
| 
 | |
| /* Bits in the DIAG register */
 | |
| 
 | |
| #define ICD 0x40000000		/* ICACHE disable */
 | |
| #define DCD 0x20000000		/* DCACHE disable */
 | |
| 
 | |
| /* Bits in the ICCR register */
 | |
| 
 | |
| #define CE 1			/* cache enable*/
 | |
| 
 | |
| 
 | |
| /* Forward declarations. */
 | |
| 
 | |
| void flush_i_cache ();
 | |
| 
 | |
| 
 | |
| /* Determine if this is a DANlite (MB8686x), as opposed to an earlier
 | |
|    SPARClite (MB8683x).  This is done by examining the impl and ver
 | |
|    fields in the PSR:
 | |
| 
 | |
|    MB8683x: impl(bit31-28)=0x0; ver(bit27-24)=0xf;
 | |
|    MB8686x: impl(bit31-28)=0x1; ver(bit27-24)=0xe;
 | |
| */
 | |
| 
 | |
| static int
 | |
| is_danlite ()
 | |
| {
 | |
|   static int checked = 0;
 | |
|   static int danlite = 0;
 | |
|   
 | |
|   if (!checked)
 | |
|     {
 | |
|       int psr = read_psr ();
 | |
|       danlite = (psr & 0xff000000) == 0x1e000000;
 | |
|       checked = 1;
 | |
|     }
 | |
|   return danlite;
 | |
| }
 | |
| 
 | |
| /* This cache code is known to work on both the 930 & 932 processors.  It just
 | |
|    cheats and clears the all of the address space that could contain tags, as
 | |
|    opposed to striding the tags at 8 or 16 word intervals, or using the cache
 | |
|    flush registers, which don't exist on all processors.  */
 | |
| 
 | |
| void
 | |
| cache_off ()
 | |
| {
 | |
|   if (is_danlite ())
 | |
|     {
 | |
|       /* Disable the ICACHE.  Disabling the DCACHE crashes the machine. */
 | |
|       unsigned int diag = read_asr (DIAG);
 | |
|       write_asr (DIAG, diag | ICD);
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       write_asi (1, 0, 0);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| cache_on ()
 | |
| {
 | |
|   if (is_danlite ())
 | |
|     {
 | |
|       unsigned int diag;
 | |
| 
 | |
|       /* Flush the caches. */
 | |
|       flush_i_cache ();
 | |
| 
 | |
|       /* Enable the ICACHE and DCACHE */
 | |
|       diag = read_asr (DIAG);
 | |
|       write_asr (DIAG, diag & ~ (ICD | DCD));
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       unsigned long addr;
 | |
| 
 | |
|       cache_off ();			/* Make sure the cache is off */
 | |
| 
 | |
|       /* Reset all of the cache line valid bits */
 | |
| 
 | |
|       for (addr = 0; addr < 0x1000; addr += 8)
 | |
| 	{
 | |
| 	  write_asi (0xc, addr, 0);	/* Clear bank 1, icache */
 | |
| 	  write_asi (0xc, addr + 0x80000000, 0); /* Clear bank 2, icache */
 | |
| 
 | |
| 	  write_asi (0xe, addr, 0);	/* Clear bank 1, dcache */
 | |
| 	  write_asi (0xe, addr + 0x80000000, 0); /* Clear bank 2, dcache */
 | |
| 	}
 | |
| 
 | |
|       /* turn on the cache */
 | |
| 
 | |
|       write_asi (1, 0, 0x35);	/* Write buf ena, prefetch buf ena, data
 | |
| 				       & inst caches enab */
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* Flush the instruction cache.  We need to do this for the debugger stub so
 | |
|    that breakpoints, et. al. become visible to the instruction stream after
 | |
|    storing them in memory.
 | |
|  */
 | |
| 
 | |
| void
 | |
| flush_i_cache ()
 | |
| {
 | |
|   if (is_danlite ())
 | |
|     {
 | |
|       write_asi (0x31, 0, 0);	/* Flush entire i/d caches */
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       int cache_reg;
 | |
|       unsigned long addr;
 | |
| 
 | |
|       cache_reg = read_asi (1, 0);	/* Read cache/bus interface reg */
 | |
| 
 | |
|       if (!(cache_reg & 1))
 | |
| 	return;			/* Just return if cache is already off */
 | |
| 
 | |
|       for (addr = 0; addr < 0x1000; addr += 8)
 | |
| 	{
 | |
| 	  write_asi (0xc, addr, 0);	/* Clear bank 1, icache */
 | |
| 	  write_asi (0xc, addr + 0x80000000, 0); /* Clear bank 2, icache */
 | |
| 	}
 | |
|     }
 | |
| }
 |