source: trunk/libs/newlib/src/libgloss/sparc/cache.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 3.5 KB
Line 
1/* Cache code for SPARClite
2 *
3 * Copyright (c) 1998 Cygnus Support
4 *
5 * The authors hereby grant permission to use, copy, modify, distribute,
6 * and license this software and its documentation for any purpose, provided
7 * that existing copyright notices are retained in all copies and that this
8 * notice is included verbatim in any distributions. No written agreement,
9 * license, or royalty fee is required for any of the authorized uses.
10 * Modifications to this software may be copyrighted by their authors
11 * and need not follow the licensing terms described here, provided that
12 * the new terms are clearly indicated on the first page of each file where
13 * they apply.
14 */
15
16#include "sparclite.h"
17
18/* Ancillary registers on the DANlite */
19
20#define DIAG 30
21#define ICCR 31
22
23/* Bits in the DIAG register */
24
25#define ICD 0x40000000          /* ICACHE disable */
26#define DCD 0x20000000          /* DCACHE disable */
27
28/* Bits in the ICCR register */
29
30#define CE 1                    /* cache enable*/
31
32
33/* Forward declarations. */
34
35void flush_i_cache ();
36
37
38/* Determine if this is a DANlite (MB8686x), as opposed to an earlier
39   SPARClite (MB8683x).  This is done by examining the impl and ver
40   fields in the PSR:
41
42   MB8683x: impl(bit31-28)=0x0; ver(bit27-24)=0xf;
43   MB8686x: impl(bit31-28)=0x1; ver(bit27-24)=0xe;
44*/
45
46static int
47is_danlite ()
48{
49  static int checked = 0;
50  static int danlite = 0;
51 
52  if (!checked)
53    {
54      int psr = read_psr ();
55      danlite = (psr & 0xff000000) == 0x1e000000;
56      checked = 1;
57    }
58  return danlite;
59}
60
61/* This cache code is known to work on both the 930 & 932 processors.  It just
62   cheats and clears the all of the address space that could contain tags, as
63   opposed to striding the tags at 8 or 16 word intervals, or using the cache
64   flush registers, which don't exist on all processors.  */
65
66void
67cache_off ()
68{
69  if (is_danlite ())
70    {
71      /* Disable the ICACHE.  Disabling the DCACHE crashes the machine. */
72      unsigned int diag = read_asr (DIAG);
73      write_asr (DIAG, diag | ICD);
74    }
75  else
76    {
77      write_asi (1, 0, 0);
78    }
79}
80
81void
82cache_on ()
83{
84  if (is_danlite ())
85    {
86      unsigned int diag;
87
88      /* Flush the caches. */
89      flush_i_cache ();
90
91      /* Enable the ICACHE and DCACHE */
92      diag = read_asr (DIAG);
93      write_asr (DIAG, diag & ~ (ICD | DCD));
94    }
95  else
96    {
97      unsigned long addr;
98
99      cache_off ();                     /* Make sure the cache is off */
100
101      /* Reset all of the cache line valid bits */
102
103      for (addr = 0; addr < 0x1000; addr += 8)
104        {
105          write_asi (0xc, addr, 0);     /* Clear bank 1, icache */
106          write_asi (0xc, addr + 0x80000000, 0); /* Clear bank 2, icache */
107
108          write_asi (0xe, addr, 0);     /* Clear bank 1, dcache */
109          write_asi (0xe, addr + 0x80000000, 0); /* Clear bank 2, dcache */
110        }
111
112      /* turn on the cache */
113
114      write_asi (1, 0, 0x35);   /* Write buf ena, prefetch buf ena, data
115                                       & inst caches enab */
116    }
117}
118
119/* Flush the instruction cache.  We need to do this for the debugger stub so
120   that breakpoints, et. al. become visible to the instruction stream after
121   storing them in memory.
122 */
123
124void
125flush_i_cache ()
126{
127  if (is_danlite ())
128    {
129      write_asi (0x31, 0, 0);   /* Flush entire i/d caches */
130    }
131  else
132    {
133      int cache_reg;
134      unsigned long addr;
135
136      cache_reg = read_asi (1, 0);      /* Read cache/bus interface reg */
137
138      if (!(cache_reg & 1))
139        return;                 /* Just return if cache is already off */
140
141      for (addr = 0; addr < 0x1000; addr += 8)
142        {
143          write_asi (0xc, addr, 0);     /* Clear bank 1, icache */
144          write_asi (0xc, addr + 0x80000000, 0); /* Clear bank 2, icache */
145        }
146    }
147}
Note: See TracBrowser for help on using the repository browser.