File: /usr/src/linux/arch/mips/sgi/kernel/indy_sc.c

1     /*
2      * indy_sc.c: Indy cache management functions.
3      *
4      * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
5      * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com).
6      */
7     #include <linux/init.h>
8     #include <linux/kernel.h>
9     #include <linux/sched.h>
10     #include <linux/mm.h>
11     
12     #include <asm/bcache.h>
13     #include <asm/sgi/sgi.h>
14     #include <asm/sgi/sgimc.h>
15     #include <asm/page.h>
16     #include <asm/pgtable.h>
17     #include <asm/system.h>
18     #include <asm/bootinfo.h>
19     #include <asm/sgialib.h>
20     #include <asm/mmu_context.h>
21     
22     /* Secondary cache size in bytes, if present.  */
23     static unsigned long scache_size;
24     
25     #undef DEBUG_CACHE
26     
27     #define SC_SIZE 0x00080000
28     #define SC_LINE 32
29     #define CI_MASK (SC_SIZE - SC_LINE)
30     #define SC_INDEX(n) ((n) & CI_MASK)
31     
32     static inline void indy_sc_wipe(unsigned long first, unsigned long last)
33     {
34     	unsigned long tmp;
35     
36     	__asm__ __volatile__(
37     	".set\tnoreorder\t\t\t# indy_sc_wipe\n\t"
38     	".set\tmips3\n\t"
39     	".set\tnoat\n\t"
40     	"mfc0\t%2, $12\n\t"
41     	"li\t$1, 0x80\t\t\t# Go 64 bit\n\t"
42     	"mtc0\t$1, $12\n\t"
43     
44     	"dli\t$1, 0x9000000080000000\n\t"
45     	"or\t%0, $1\t\t\t# first line to flush\n\t"
46     	"or\t%1, $1\t\t\t# last line to flush\n\t"
47     	".set\tat\n\t"
48     
49     	"1:\tsw\t$0, 0(%0)\n\t"
50     	"bne\t%0, %1, 1b\n\t"
51     	"daddu\t%0, 32\n\t"
52     
53     	"mtc0\t%2, $12\t\t\t# Back to 32 bit\n\t"
54     	"nop; nop; nop; nop;\n\t"
55     	".set\tmips0\n\t"
56     	".set\treorder"
57     	: "=r" (first), "=r" (last), "=&r" (tmp)
58     	: "0" (first), "1" (last)
59     	: "$1");
60     }
61     
62     static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size)
63     {
64     	unsigned long first_line, last_line;
65     	unsigned int flags;
66     
67     #ifdef DEBUG_CACHE
68     	printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size);
69     #endif
70     
71     	if (!size)
72     		return;
73     
74     	/* Which lines to flush?  */
75     	first_line = SC_INDEX(addr);
76     	last_line = SC_INDEX(addr + size - 1);
77     
78     	__save_and_cli(flags);
79     	if (first_line <= last_line) {
80     		indy_sc_wipe(first_line, last_line);
81     		goto out;
82     	}
83     
84     	indy_sc_wipe(first_line, SC_SIZE - SC_LINE);
85     	indy_sc_wipe(0, last_line);
86     out:
87     	__restore_flags(flags);
88     }
89     
90     static void indy_sc_enable(void)
91     {
92     	unsigned long addr, tmp1, tmp2;
93     
94     	/* This is really cool... */
95     #ifdef DEBUG_CACHE
96     	printk("Enabling R4600 SCACHE\n");
97     #endif
98     	__asm__ __volatile__(
99     	".set\tpush\n\t"
100     	".set\tnoreorder\n\t"
101     	".set\tmips3\n\t"
102     	"mfc0\t%2, $12\n\t"
103     	"nop; nop; nop; nop;\n\t"
104     	"li\t%1, 0x80\n\t"
105     	"mtc0\t%1, $12\n\t"
106     	"nop; nop; nop; nop;\n\t"
107     	"li\t%0, 0x1\n\t"
108     	"dsll\t%0, 31\n\t"
109     	"lui\t%1, 0x9000\n\t"
110     	"dsll32\t%1, 0\n\t"
111     	"or\t%0, %1, %0\n\t"
112     	"sb\t$0, 0(%0)\n\t"
113     	"mtc0\t$0, $12\n\t"
114     	"nop; nop; nop; nop;\n\t"
115     	"mtc0\t%2, $12\n\t"
116     	"nop; nop; nop; nop;\n\t"
117     	".set\tpop"
118     	: "=r" (tmp1), "=r" (tmp2), "=r" (addr));
119     }
120     
121     static void indy_sc_disable(void)
122     {
123     	unsigned long tmp1, tmp2, tmp3;
124     
125     #ifdef DEBUG_CACHE
126     	printk("Disabling R4600 SCACHE\n");
127     #endif
128     	__asm__ __volatile__(
129     	".set\tpush\n\t"
130     	".set\tnoreorder\n\t"
131     	".set\tmips3\n\t"
132     	"li\t%0, 0x1\n\t"
133     	"dsll\t%0, 31\n\t"
134     	"lui\t%1, 0x9000\n\t"
135     	"dsll32\t%1, 0\n\t"
136     	"or\t%0, %1, %0\n\t"
137     	"mfc0\t%2, $12\n\t"
138     	"nop; nop; nop; nop\n\t"
139     	"li\t%1, 0x80\n\t"
140     	"mtc0\t%1, $12\n\t"
141     	"nop; nop; nop; nop\n\t"
142     	"sh\t$0, 0(%0)\n\t"
143     	"mtc0\t$0, $12\n\t"
144     	"nop; nop; nop; nop\n\t"
145     	"mtc0\t%2, $12\n\t"
146     	"nop; nop; nop; nop\n\t"
147     	".set\tpop"
148     	: "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
149     }
150     
151     static inline int __init indy_sc_probe(void)
152     {
153     	volatile unsigned int *cpu_control;
154     	unsigned short cmd = 0xc220;
155     	unsigned long data = 0;
156     	int i, n;
157     
158     #ifdef __MIPSEB__
159     	cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034);
160     #else
161     	cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030);
162     #endif
163     #define DEASSERT(bit) (*(cpu_control) &= (~(bit)))
164     #define ASSERT(bit) (*(cpu_control) |= (bit))
165     #define DELAY  for(n = 0; n < 100000; n++) __asm__ __volatile__("")
166     	DEASSERT(SGIMC_EEPROM_PRE);
167     	DEASSERT(SGIMC_EEPROM_SDATAO);
168     	DEASSERT(SGIMC_EEPROM_SECLOCK);
169     	DEASSERT(SGIMC_EEPROM_PRE);
170     	DELAY;
171     	ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK);
172     	for(i = 0; i < 11; i++) {
173     		if(cmd & (1<<15))
174     			ASSERT(SGIMC_EEPROM_SDATAO);
175     		else
176     			DEASSERT(SGIMC_EEPROM_SDATAO);
177     		DEASSERT(SGIMC_EEPROM_SECLOCK);
178     		ASSERT(SGIMC_EEPROM_SECLOCK);
179     		cmd <<= 1;
180     	}
181     	DEASSERT(SGIMC_EEPROM_SDATAO);
182     	for(i = 0; i < (sizeof(unsigned short) * 8); i++) {
183     		unsigned int tmp;
184     
185     		DEASSERT(SGIMC_EEPROM_SECLOCK);
186     		DELAY;
187     		ASSERT(SGIMC_EEPROM_SECLOCK);
188     		DELAY;
189     		data <<= 1;
190     		tmp = *cpu_control;
191     		if(tmp & SGIMC_EEPROM_SDATAI)
192     			data |= 1;
193     	}
194     	DEASSERT(SGIMC_EEPROM_SECLOCK);
195     	DEASSERT(SGIMC_EEPROM_CSEL);
196     	ASSERT(SGIMC_EEPROM_PRE);
197     	ASSERT(SGIMC_EEPROM_SECLOCK);
198     
199     	data <<= PAGE_SHIFT;
200     	if (data == 0)
201     		return 0;
202     
203     	scache_size = data;
204     
205     	printk("R4600/R5000 SCACHE size %ldK, linesize 32 bytes.\n",
206     	       scache_size >> 10);
207     
208     	return 1;
209     }
210     
211     /* XXX Check with wje if the Indy caches can differenciate between
212        writeback + invalidate and just invalidate.  */
213     struct bcache_ops indy_sc_ops = {
214     	indy_sc_enable,
215     	indy_sc_disable,
216     	indy_sc_wback_invalidate,
217     	indy_sc_wback_invalidate
218     };
219     
220     void __init indy_sc_init(void)
221     {
222     	if (indy_sc_probe()) {
223     		indy_sc_enable();
224     		bcops = &indy_sc_ops;
225     	}
226     }
227