Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6 into lvs-next-2.6
[linux-2.6] / arch / blackfin / mach-common / lock.S
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/blackfin.h>
32
33 .text
34
35 /* When you come here, it is assumed that
36  * R0 - Which way to be locked
37  */
38
39 ENTRY(_cache_grab_lock)
40
41         [--SP]=( R7:0,P5:0 );
42
43         P1.H = HI(IMEM_CONTROL);
44         P1.L = LO(IMEM_CONTROL);
45         P5.H = HI(ICPLB_ADDR0);
46         P5.L = LO(ICPLB_ADDR0);
47         P4.H = HI(ICPLB_DATA0);
48         P4.L = LO(ICPLB_DATA0);
49         R7 = R0;
50
51         /* If the code of interest already resides in the cache
52          * invalidate the entire cache itself.
53          * invalidate_entire_icache;
54          */
55
56         SP += -12;
57         [--SP] = RETS;
58         CALL _invalidate_entire_icache;
59         RETS = [SP++];
60         SP += 12;
61
62         /* Disable the Interrupts*/
63
64         CLI R3;
65
66 .LLOCK_WAY:
67
68         /* Way0 - 0xFFA133E0
69          * Way1 - 0xFFA137E0
70          * Way2 - 0xFFA13BE0    Total Way Size = 4K
71          * Way3 - 0xFFA13FE0
72          */
73
74         /* Procedure Ex. -Set the locks for other ways by setting ILOC[3:1]
75          * Only Way0 of the instruction cache can now be
76          * replaced by a new code
77          */
78
79         R5 = R7;
80         CC = BITTST(R7,0);
81         IF CC JUMP .LCLEAR1;
82         R7 = 0;
83         BITSET(R7,0);
84         JUMP .LDONE1;
85
86 .LCLEAR1:
87         R7 = 0;
88         BITCLR(R7,0);
89 .LDONE1:        R4 = R7 << 3;
90         R7 = [P1];
91         R7 = R7 | R4;
92         SSYNC;          /* SSYNC required writing to IMEM_CONTROL. */
93         .align 8;
94         [P1] = R7;
95         SSYNC;
96
97         R7 = R5;
98         CC = BITTST(R7,1);
99         IF CC JUMP .LCLEAR2;
100         R7 = 0;
101         BITSET(R7,1);
102         JUMP .LDONE2;
103
104 .LCLEAR2:
105         R7 = 0;
106         BITCLR(R7,1);
107 .LDONE2:        R4 = R7 << 3;
108         R7 = [P1];
109         R7 = R7 | R4;
110         SSYNC;          /* SSYNC required writing to IMEM_CONTROL. */
111         .align 8;
112         [P1] = R7;
113         SSYNC;
114
115         R7 = R5;
116         CC = BITTST(R7,2);
117         IF CC JUMP .LCLEAR3;
118         R7 = 0;
119         BITSET(R7,2);
120         JUMP .LDONE3;
121 .LCLEAR3:
122         R7 = 0;
123         BITCLR(R7,2);
124 .LDONE3:        R4 = R7 << 3;
125         R7 = [P1];
126         R7 = R7 | R4;
127         SSYNC;          /* SSYNC required writing to IMEM_CONTROL. */
128         .align 8;
129         [P1] = R7;
130         SSYNC;
131
132
133         R7 = R5;
134         CC = BITTST(R7,3);
135         IF CC JUMP .LCLEAR4;
136         R7 = 0;
137         BITSET(R7,3);
138         JUMP .LDONE4;
139 .LCLEAR4:
140         R7 = 0;
141         BITCLR(R7,3);
142 .LDONE4:        R4 = R7 << 3;
143         R7 = [P1];
144         R7 = R7 | R4;
145         SSYNC;          /* SSYNC required writing to IMEM_CONTROL. */
146         .align 8;
147         [P1] = R7;
148         SSYNC;
149
150         STI R3;
151
152         ( R7:0,P5:0 ) = [SP++];
153
154         RTS;
155 ENDPROC(_cache_grab_lock)
156
157 /* After the execution of critical code, the code is now locked into
158  * the cache way. Now we need to set ILOC.
159  *
160  * R0 - Which way to be locked
161  */
162
163 ENTRY(_cache_lock)
164
165         [--SP]=( R7:0,P5:0 );
166
167         P1.H = HI(IMEM_CONTROL);
168         P1.L = LO(IMEM_CONTROL);
169
170         /* Disable the Interrupts*/
171         CLI R3;
172
173         R7 = [P1];
174         R2 = ~(0x78) (X);       /* mask out ILOC */
175         R7 = R7 & R2;
176         R0 = R0 << 3;
177         R7 = R0 | R7;
178         SSYNC;          /* SSYNC required writing to IMEM_CONTROL. */
179         .align 8;
180         [P1] = R7;
181         SSYNC;
182         /* Renable the Interrupts */
183         STI R3;
184
185         ( R7:0,P5:0 ) = [SP++];
186         RTS;
187 ENDPROC(_cache_lock)
188
189 /* Invalidate the Entire Instruction cache by
190  * disabling IMC bit
191  */
192 ENTRY(_invalidate_entire_icache)
193         [--SP] = ( R7:5);
194
195         P0.L = LO(IMEM_CONTROL);
196         P0.H = HI(IMEM_CONTROL);
197         R7 = [P0];
198
199         /* Clear the IMC bit , All valid bits in the instruction
200          * cache are set to the invalid state
201          */
202         BITCLR(R7,IMC_P);
203         CLI R6;
204         SSYNC;          /* SSYNC required before invalidating cache. */
205         .align 8;
206         [P0] = R7;
207         SSYNC;
208         STI R6;
209
210         /* Configures the instruction cache agian */
211         R6 = (IMC | ENICPLB);
212         R7 = R7 | R6;
213
214         CLI R6;
215         SSYNC;          /* SSYNC required before writing to IMEM_CONTROL. */
216         .align 8;
217         [P0] = R7;
218         SSYNC;
219         STI R6;
220
221         ( R7:5) = [SP++];
222         RTS;
223 ENDPROC(_invalidate_entire_icache)