summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/rtkload/cache.c
blob: 8e4ca57d8b978a799c63454a20623568ffd91f69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 1994 - 1999 by Ralf Baechle
 * Modified for R3000 by Paul M. Antoine, 1995, 1996
 * Complete output from die() by Ulf Carlsson, 1998
 * Copyright (C) 1999 Silicon Graphics, Inc.
 */
//#include <linux/config.h>
#include <linux/autoconf.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
//#include <asm/mipsregs.h>
#include <asm/rlxregs.h>
#include <asm/addrspace.h>
//#include <asm/system.h>

#if defined(CONFIG_RTL_819X)
/* For Realtek RTL865XC Network platform series */
#define _ICACHE_SIZE		(16 * 1024)		/* 16K bytes */
#define _DCACHE_SIZE		(8 * 1024)		/* 8K bytes */
#define _CACHE_LINE_SIZE	4			/* 4 words */
#endif

#define PROM_DEBUG

#ifdef PROM_DEBUG
extern int prom_printf(char *, ...);
#endif

/*Cyrus Tsai*/
void flush_cache(void);
void flush_icache(unsigned int start, unsigned int end);
void flush_dcache(unsigned int start, unsigned int end);
/*Cyrus Tsai*/


void flush_cache(void)
{
#ifdef 	CONFIG_RTL_EB8186
	flush_dcache(0,0);		
	flush_icache(0,0);	
#endif	
#if defined(CONFIG_RTL_819X)
	flush_dcache(KSEG0, KSEG0+_DCACHE_SIZE);		
	flush_icache(KSEG0, KSEG0+_ICACHE_SIZE);	
#endif
}


/*Cyrus Tsai*/
void flush_icache(unsigned int start, unsigned int end)
{
#if defined(CONFIG_RTL_819X)
	/*
		Flush data cache at first in write-back platform.

		Ghhuang (2007/3/9):

		RD-Center suggest that we need to flush D-cache entries which
		might match to same address as I-cache ... when we flush
		I-cache.
		( Maybe some data is treated as data/instruction, both. )
	*/
	flush_dcache(start, end);

	/*Invalidate I-Cache*/
	__asm__ volatile(
		"mtc0 $0,$20\n\t"
		"nop\n\t"
		"li $8,2\n\t"
		"mtc0 $8,$20\n\t"
		"nop\n\t"
		"nop\n\t"
		"mtc0 $0,$20\n\t"
		"nop"
		: /* no output */
		: /* no input */
			);

#endif

#ifdef CONFIG_RTL_EB8186
   unsigned long flags;
   volatile unsigned int reg;
    save_flags(flags);cli();
   reg=read_32bit_cp0_register(CP0_XCONTEXT);
   __asm__ volatile("nop");   
    __asm__ volatile("nop");
   write_32bit_cp0_register(CP0_XCONTEXT, (reg &(~0x2))); //write '0' to bit 0,1
   __asm__ volatile("nop");
   __asm__ volatile("nop");    
   write_32bit_cp0_register(CP0_XCONTEXT, (reg | 0x2)); //wirte '1' to bit 0, 1
   __asm__ volatile("nop");  
    __asm__ volatile("nop");
    restore_flags(flags);
#endif
}

void flush_dcache(unsigned int start, unsigned int end)
{
#ifdef CONFIG_RTL_EB8186
   unsigned long flags;
   volatile unsigned int reg;
    save_flags(flags);cli();
    reg=read_32bit_cp0_register(CP0_XCONTEXT);
    __asm__ volatile("nop");
    __asm__ volatile("nop");
    write_32bit_cp0_register(CP0_XCONTEXT, (reg & (~0x1))); //write '0' to bit 0,1
    __asm__ volatile("nop");
    __asm__ volatile("nop");
    write_32bit_cp0_register(CP0_XCONTEXT, (reg | 0x1)); //wirte '1' to bit 0, 1
    __asm__ volatile("nop");
    __asm__ volatile("nop");
    restore_flags(flags);
#endif    
    
#if defined(CONFIG_RTL_819X)
	/* Flush D-Cache using its range */
	unsigned char *p;
	unsigned int size;
	unsigned int flags;
	unsigned int i;
   
	size = end - start;
   
	/* correctness check : flush all if any parameter is illegal */
// david	
//	if (	(size >= dcache_size) ||
	if ((size >= _DCACHE_SIZE) ||	(KSEGX(start) != KSEG0)	)
	{
		/*
		 *	ghhguang
		 *		=> For Realtek Lextra CPU,
		 *		   the cache would NOT be flushed only if the Address to-be-flushed
		 *		   is the EXPLICIT address ( which is really stored in that cache line ).
		 *		   For the aliasd addresses, the cache entry would NOT be flushed even
		 *		   it matchs same cache-index.
		 *
		 *		   => This is different from traditional MIPS-based CPU's configuration.
		 *		      So if we want to flush ALL-cache entries, we would need to use "mtc0"
		 *		      instruction instead of simply modifying the "size" to "dcache_size"
		 *		      and "start" to "KSEG0".
		 *
		 */
		__asm__ volatile(
			"mtc0 $0,$20\n\t"
			"nop\n\t"
			"li $8,512\n\t"
			"mtc0 $8,$20\n\t"
			"nop\n\t"
			"nop\n\t"
			"mtc0 $0,$20\n\t"
			"nop"
			: /* no output */
			: /* no input */
				);
	} 
#if 1	
	else
	{
		/* Start to isolate cache space */
		p = (char *)start;
   
		flags = read_c0_status();
   
		/* isolate cache space */
		write_c0_status( (ST0_ISC | flags) &~ ST0_IEC );
   
		for (i = 0; i < size; i += 0x040)
		{
			asm ( 	
			#ifdef OPEN_RSDK_RTL865x
				".word 0xbc750000\n\t"
				".word 0xbc750010\n\t"
				".word 0xbc750020\n\t"
				".word 0xbc750030\n\t"
			#endif
				"cache 0x15, 0x000(%0)\n\t"
			 	"cache 0x15, 0x010(%0)\n\t"
			 	"cache 0x15, 0x020(%0)\n\t"
			 	"cache 0x15, 0x030(%0)\n\t"
				:		/* No output registers */
				:"r"(p)		/* input : 'p' as %0 */
				);
			p += 0x040;
		}
   
		write_c0_status(flags);
	}    
#endif
#endif    
   
}
/*Cyrus Tsai*/