Merge git://git.infradead.org/battery-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/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
42 ENTRY(_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;
158 ENDPROC(_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
166 ENTRY(_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;
190 ENDPROC(_cache_lock)
191
192 #endif  /* BLKFIN_CACHE_LOCK */
193
194 /* Return the ILOC bits of IMEM_CONTROL
195  */
196
197 ENTRY(_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;
206 ENDPROC(_read_iloc)