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 */
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 |