summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/image/lzma-loader/src/cache.c
blob: 6ecb07071200c01505e9c8658470d172c8031699 (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
/*
 * LZMA compressed kernel loader for Realtek rtl819xx
 *
 * Copyright (C) 2013 Roman Yeryomin <roman@advem.lv>
 *
 * The cache manipulation routines has been taken from
 * Realtek SDK (rtlkoad utility).
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 *
 */
#include <linux/autoconf.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
#include <asm/rlxregs.h>
#include <asm/addrspace.h>

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

void flush_cache(void);
static void flush_icache(unsigned int start, unsigned int end);
static void flush_dcache(unsigned int start, unsigned int end);

void flush_cache(void)
{

	flush_dcache(KSEG0, KSEG0+_DCACHE_SIZE);
	flush_icache(KSEG0, KSEG0+_ICACHE_SIZE);

}

static  void flush_icache(unsigned int start, unsigned int end)
{
	/*
	 * 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 */
			);

}

static void flush_dcache(unsigned int start, unsigned int end)
{
	/* 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 Lexra 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 aliased addresses, the cache entry would NOT be flushed even
	 * if 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 */
				);
	} 
	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);
	}    
}