1/*
2 * File:         arch/blackfin/mach-common/lock.S
3 * Based on:
4 * Author:       LG Soft India
5 *
6 * Created:      ?
7 * Description:  kernel locks
8 *
9 * Modified:
10 *               Copyright 2004-2006 Analog Devices Inc.
11 *
12 * Bugs:         Enter bugs at http://blackfin.uclinux.org/
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see the file COPYING, or write
26 * to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
28 */
29
30#include <linux/linkage.h>
31#include <asm/cplb.h>
32#include <asm/blackfin.h>
33
34.text
35
36#ifdef CONFIG_BLKFIN_CACHE_LOCK
37
38/* When you come here, it is assumed that
39 * R0 - Which way to be locked
40 */
41
42ENTRY(_cache_grab_lock)
43
44	[--SP]=( R7:0,P5:0 );
45
46	P1.H = (IMEM_CONTROL >> 16);
47	P1.L = (IMEM_CONTROL & 0xFFFF);
48	P5.H = (ICPLB_ADDR0 >> 16);
49	P5.L = (ICPLB_ADDR0 & 0xFFFF);
50	P4.H = (ICPLB_DATA0 >> 16);
51	P4.L = (ICPLB_DATA0 & 0xFFFF);
52	R7 = R0;
53
54	/* If the code of interest already resides in the cache
55	 * invalidate the entire cache itself.
56	 * invalidate_entire_icache;
57	 */
58
59	SP += -12;
60	[--SP] = RETS;
61	CALL _invalidate_entire_icache;
62	RETS = [SP++];
63	SP += 12;
64
65	/* Disable the Interrupts*/
66
67	CLI R3;
68
69.LLOCK_WAY:
70
71	/* Way0 - 0xFFA133E0
72	 * Way1 - 0xFFA137E0
73	 * Way2 - 0xFFA13BE0	Total Way Size = 4K
74	 * Way3 - 0xFFA13FE0
75	 */
76
77	/* Procedure Ex. -Set the locks for other ways by setting ILOC[3:1]
78	 * Only Way0 of the instruction cache can now be
79	 * replaced by a new code
80	 */
81
82	R5 = R7;
83	CC = BITTST(R7,0);
84	IF CC JUMP .LCLEAR1;
85	R7 = 0;
86	BITSET(R7,0);
87	JUMP .LDONE1;
88
89.LCLEAR1:
90	R7 = 0;
91	BITCLR(R7,0);
92.LDONE1:	R4 = R7 << 3;
93	R7 = [P1];
94	R7 = R7 | R4;
95	SSYNC;		/* SSYNC required writing to IMEM_CONTROL. */
96	.align 8;
97	[P1] = R7;
98	SSYNC;
99
100	R7 = R5;
101	CC = BITTST(R7,1);
102	IF CC JUMP .LCLEAR2;
103	R7 = 0;
104	BITSET(R7,1);
105	JUMP .LDONE2;
106
107.LCLEAR2:
108	R7 = 0;
109	BITCLR(R7,1);
110.LDONE2:	R4 = R7 << 3;
111	R7 = [P1];
112	R7 = R7 | R4;
113	SSYNC;		/* SSYNC required writing to IMEM_CONTROL. */
114	.align 8;
115	[P1] = R7;
116	SSYNC;
117
118	R7 = R5;
119	CC = BITTST(R7,2);
120	IF CC JUMP .LCLEAR3;
121	R7 = 0;
122	BITSET(R7,2);
123	JUMP .LDONE3;
124.LCLEAR3:
125	R7 = 0;
126	BITCLR(R7,2);
127.LDONE3:	R4 = R7 << 3;
128	R7 = [P1];
129	R7 = R7 | R4;
130	SSYNC;		/* SSYNC required writing to IMEM_CONTROL. */
131	.align 8;
132	[P1] = R7;
133	SSYNC;
134
135
136	R7 = R5;
137	CC = BITTST(R7,3);
138	IF CC JUMP .LCLEAR4;
139	R7 = 0;
140	BITSET(R7,3);
141	JUMP .LDONE4;
142.LCLEAR4:
143	R7 = 0;
144	BITCLR(R7,3);
145.LDONE4:	R4 = R7 << 3;
146	R7 = [P1];
147	R7 = R7 | R4;
148	SSYNC;		/* SSYNC required writing to IMEM_CONTROL. */
149	.align 8;
150	[P1] = R7;
151	SSYNC;
152
153	STI R3;
154
155	( R7:0,P5:0 ) = [SP++];
156
157	RTS;
158ENDPROC(_cache_grab_lock)
159
160/* After the execution of critical code, the code is now locked into
161 * the cache way. Now we need to set ILOC.
162 *
163 * R0 - Which way to be locked
164 */
165
166ENTRY(_cache_lock)
167
168	[--SP]=( R7:0,P5:0 );
169
170	P1.H = (IMEM_CONTROL >> 16);
171	P1.L = (IMEM_CONTROL & 0xFFFF);
172
173	/* Disable the Interrupts*/
174	CLI R3;
175
176	R7 = [P1];
177	R2 = 0xFFFFFF87 (X);
178	R7 = R7 & R2;
179	R0 = R0 << 3;
180	R7 = R0 | R7;
181	SSYNC;		/* SSYNC required writing to IMEM_CONTROL. */
182	.align 8;
183	[P1] = R7;
184	SSYNC;
185	/* Renable the Interrupts */
186	STI R3;
187
188	( R7:0,P5:0 ) = [SP++];
189	RTS;
190ENDPROC(_cache_lock)
191
192#endif	/* BLKFIN_CACHE_LOCK */
193
194/* Return the ILOC bits of IMEM_CONTROL
195 */
196
197ENTRY(_read_iloc)
198	P1.H = (IMEM_CONTROL >> 16);
199	P1.L = (IMEM_CONTROL & 0xFFFF);
200	R1 = 0xF;
201	R0 = [P1];
202	R0 = R0 >> 3;
203	R0 = R0 & R1;
204
205	RTS;
206ENDPROC(_read_iloc)
207