Blackfin arch: merge adeos blackfin part to arch/blackfin/
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / blackfin / lib / ins.S
1 /*
2 * File: arch/blackfin/lib/ins.S
3 * Based on:
4 * Author: Bas Vermeulen <bas@buyways.nl>
5 *
6 * Created: Tue Mar 22 15:27:24 CEST 2005
7 * Description: Implementation of ins{bwl} for BlackFin processors using zero overhead loops.
8 *
9 * Modified:
10 * Copyright 2004-2008 Analog Devices Inc.
11 * Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl>
12 *
13 * Bugs: Enter bugs at http://blackfin.uclinux.org/
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, see the file COPYING, or write
27 * to the Free Software Foundation, Inc.,
28 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30
31 #include <linux/linkage.h>
32 #include <asm/blackfin.h>
33
34 .align 2
35
36 /*
37 * Reads on the Blackfin are speculative. In Blackfin terms, this means they
38 * can be interrupted at any time (even after they have been issued on to the
39 * external bus), and re-issued after the interrupt occurs.
40 *
41 * If a FIFO is sitting on the end of the read, it will see two reads,
42 * when the core only sees one. The FIFO receives the read which is cancelled,
43 * and not delivered to the core.
44 *
45 * To solve this, interrupts are turned off before reads occur to I/O space.
46 * There are 3 versions of all these functions
47 * - turns interrupts off every read (higher overhead, but lower latency)
48 * - turns interrupts off every loop (low overhead, but longer latency)
49 * - DMA version, which do not suffer from this issue. DMA versions have
50 * different name (prefixed by dma_ ), and are located in
51 * ../kernel/bfin_dma_5xx.c
52 * Using the dma related functions are recommended for transfering large
53 * buffers in/out of FIFOs.
54 */
55
56 ENTRY(_insl)
57 #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
58 P0 = R0; /* P0 = port */
59 #ifdef CONFIG_IPIPE
60 [--sp] = rets
61 [--sp] = (P5:0);
62 sp += -12
63 call ___ipipe_stall_root_raw
64 sp += 12
65 (P5:0) = [sp++];
66 #else
67 cli R3;
68 #endif
69 P1 = R1; /* P1 = address */
70 P2 = R2; /* P2 = count */
71 SSYNC;
72 LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
73 .Llong_loop_s: R0 = [P0];
74 [P1++] = R0;
75 NOP;
76 .Llong_loop_e: NOP;
77 #ifdef CONFIG_IPIPE
78 sp += -12
79 call ___ipipe_unstall_root_raw
80 sp += 12
81 rets = [sp++]
82 #else
83 sti R3;
84 #endif
85 RTS;
86 #else
87 P0 = R0; /* P0 = port */
88 P1 = R1; /* P1 = address */
89 P2 = R2; /* P2 = count */
90 SSYNC;
91 LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
92 .Llong_loop_s:
93 #ifdef CONFIG_IPIPE
94 [--sp] = rets
95 [--sp] = (P5:0);
96 sp += -12
97 call ___ipipe_stall_root_raw
98 sp += 12
99 (P5:0) = [sp++];
100 #else
101 CLI R3;
102 #endif
103 NOP; NOP; NOP;
104 R0 = [P0];
105 [P1++] = R0;
106 .Llong_loop_e:
107 #ifdef CONFIG_IPIPE
108 sp += -12
109 call ___ipipe_unstall_root_raw
110 sp += 12
111 rets = [sp++]
112 #else
113 STI R3;
114 #endif
115 RTS;
116 #endif
117 ENDPROC(_insl)
118
119 ENTRY(_insw)
120 #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
121 P0 = R0; /* P0 = port */
122 #ifdef CONFIG_IPIPE
123 [--sp] = rets
124 [--sp] = (P5:0);
125 sp += -12
126 call ___ipipe_stall_root_raw
127 sp += 12
128 (P5:0) = [sp++];
129 #else
130 cli R3;
131 #endif
132 P1 = R1; /* P1 = address */
133 P2 = R2; /* P2 = count */
134 SSYNC;
135 LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
136 .Lword_loop_s: R0 = W[P0];
137 W[P1++] = R0;
138 NOP;
139 .Lword_loop_e: NOP;
140 #ifdef CONFIG_IPIPE
141 sp += -12
142 call ___ipipe_unstall_root_raw
143 sp += 12
144 rets = [sp++]
145 #else
146 sti R3;
147 #endif
148 RTS;
149 #else
150 P0 = R0; /* P0 = port */
151 P1 = R1; /* P1 = address */
152 P2 = R2; /* P2 = count */
153 SSYNC;
154 LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
155 .Lword_loop_s:
156 #ifdef CONFIG_IPIPE
157 [--sp] = rets
158 [--sp] = (P5:0);
159 sp += -12
160 call ___ipipe_stall_root_raw
161 sp += 12
162 (P5:0) = [sp++];
163 #else
164 CLI R3;
165 #endif
166 NOP; NOP; NOP;
167 R0 = W[P0];
168 W[P1++] = R0;
169 .Lword_loop_e:
170 #ifdef CONFIG_IPIPE
171 sp += -12
172 call ___ipipe_unstall_root_raw
173 sp += 12
174 rets = [sp++]
175 #else
176 STI R3;
177 #endif
178 RTS;
179
180 #endif
181 ENDPROC(_insw)
182
183 ENTRY(_insw_8)
184 #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
185 P0 = R0; /* P0 = port */
186 #ifdef CONFIG_IPIPE
187 [--sp] = rets
188 [--sp] = (P5:0);
189 sp += -12
190 call ___ipipe_stall_root_raw
191 sp += 12
192 (P5:0) = [sp++];
193 #else
194 cli R3;
195 #endif
196 P1 = R1; /* P1 = address */
197 P2 = R2; /* P2 = count */
198 SSYNC;
199 LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2;
200 .Lword8_loop_s: R0 = W[P0];
201 B[P1++] = R0;
202 R0 = R0 >> 8;
203 B[P1++] = R0;
204 NOP;
205 .Lword8_loop_e: NOP;
206 #ifdef CONFIG_IPIPE
207 sp += -12
208 call ___ipipe_unstall_root_raw
209 sp += 12
210 rets = [sp++]
211 #else
212 sti R3;
213 #endif
214 RTS;
215 #else
216 P0 = R0; /* P0 = port */
217 P1 = R1; /* P1 = address */
218 P2 = R2; /* P2 = count */
219 SSYNC;
220 LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2;
221 .Lword8_loop_s:
222 #ifdef CONFIG_IPIPE
223 [--sp] = rets
224 [--sp] = (P5:0);
225 sp += -12
226 call ___ipipe_stall_root_raw
227 sp += 12
228 (P5:0) = [sp++];
229 #else
230 CLI R3;
231 #endif
232 NOP; NOP; NOP;
233 R0 = W[P0];
234 B[P1++] = R0;
235 R0 = R0 >> 8;
236 B[P1++] = R0;
237 NOP;
238 .Lword8_loop_e:
239 #ifdef CONFIG_IPIPE
240 sp += -12
241 call ___ipipe_unstall_root_raw
242 sp += 12
243 rets = [sp++]
244 #else
245 STI R3;
246 #endif
247 RTS;
248 #endif
249 ENDPROC(_insw_8)
250
251 ENTRY(_insb)
252 #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
253 P0 = R0; /* P0 = port */
254 #ifdef CONFIG_IPIPE
255 [--sp] = rets
256 [--sp] = (P5:0);
257 sp += -12
258 call ___ipipe_stall_root_raw
259 sp += 12
260 (P5:0) = [sp++];
261 #else
262 cli R3;
263 #endif
264 P1 = R1; /* P1 = address */
265 P2 = R2; /* P2 = count */
266 SSYNC;
267 LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
268 .Lbyte_loop_s: R0 = B[P0];
269 B[P1++] = R0;
270 NOP;
271 .Lbyte_loop_e: NOP;
272 #ifdef CONFIG_IPIPE
273 sp += -12
274 call ___ipipe_unstall_root_raw
275 sp += 12
276 rets = [sp++]
277 #else
278 sti R3;
279 #endif
280 RTS;
281 #else
282 P0 = R0; /* P0 = port */
283 P1 = R1; /* P1 = address */
284 P2 = R2; /* P2 = count */
285 SSYNC;
286 LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
287 .Lbyte_loop_s:
288 #ifdef CONFIG_IPIPE
289 [--sp] = rets
290 [--sp] = (P5:0);
291 sp += -12
292 call ___ipipe_stall_root_raw
293 sp += 12
294 (P5:0) = [sp++];
295 #else
296 CLI R3;
297 #endif
298 NOP; NOP; NOP;
299 R0 = B[P0];
300 B[P1++] = R0;
301 .Lbyte_loop_e:
302 #ifdef CONFIG_IPIPE
303 sp += -12
304 call ___ipipe_unstall_root_raw
305 sp += 12
306 rets = [sp++]
307 #else
308 STI R3;
309 #endif
310 RTS;
311 #endif
312 ENDPROC(_insb)
313
314 ENTRY(_insl_16)
315 #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
316 P0 = R0; /* P0 = port */
317 #ifdef CONFIG_IPIPE
318 [--sp] = rets
319 [--sp] = (P5:0);
320 sp += -12
321 call ___ipipe_stall_root_raw
322 sp += 12
323 (P5:0) = [sp++];
324 #else
325 cli R3;
326 #endif
327 P1 = R1; /* P1 = address */
328 P2 = R2; /* P2 = count */
329 SSYNC;
330 LSETUP( .Llong16_loop_s, .Llong16_loop_e) LC0 = P2;
331 .Llong16_loop_s: R0 = [P0];
332 W[P1++] = R0;
333 R0 = R0 >> 16;
334 W[P1++] = R0;
335 NOP;
336 .Llong16_loop_e: NOP;
337 #ifdef CONFIG_IPIPE
338 sp += -12
339 call ___ipipe_unstall_root_raw
340 sp += 12
341 rets = [sp++]
342 #else
343 sti R3;
344 #endif
345 RTS;
346 #else
347 P0 = R0; /* P0 = port */
348 P1 = R1; /* P1 = address */
349 P2 = R2; /* P2 = count */
350 SSYNC;
351 LSETUP( .Llong16_loop_s, .Llong16_loop_e) LC0 = P2;
352 .Llong16_loop_s:
353 #ifdef CONFIG_IPIPE
354 [--sp] = rets
355 [--sp] = (P5:0);
356 sp += -12
357 call ___ipipe_stall_root_raw
358 sp += 12
359 (P5:0) = [sp++];
360 #else
361 CLI R3;
362 #endif
363 NOP; NOP; NOP;
364 R0 = [P0];
365 W[P1++] = R0;
366 R0 = R0 >> 16;
367 W[P1++] = R0;
368 .Llong16_loop_e:
369 #ifdef CONFIG_IPIPE
370 sp += -12
371 call ___ipipe_unstall_root_raw
372 sp += 12
373 rets = [sp++]
374 #else
375 STI R3;
376 #endif
377 RTS;
378 #endif
379 ENDPROC(_insl_16)