blob: d60554dce87bc4f94fff3151cdeef747340bfed8 [file] [log] [blame]
Bryan Wu1394f032007-05-06 14:50:22 -07001/*
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:
Michael Hennerich59069672008-05-17 16:38:52 +080010 * Copyright 2004-2008 Analog Devices Inc.
Bryan Wu1394f032007-05-06 14:50:22 -070011 * 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>
Michael Hennerich8af10b72007-05-21 18:09:09 +080032#include <asm/blackfin.h>
Bryan Wu1394f032007-05-06 14:50:22 -070033
34.align 2
35
Robin Getz251383c2008-08-14 15:12:55 +080036/*
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
Bryan Wu1394f032007-05-06 14:50:22 -070056ENTRY(_insl)
Robin Getz251383c2008-08-14 15:12:55 +080057#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
Bryan Wu1394f032007-05-06 14:50:22 -070058 P0 = R0; /* P0 = port */
59 cli R3;
60 P1 = R1; /* P1 = address */
61 P2 = R2; /* P2 = count */
62 SSYNC;
63 LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
Michael Hennerich8af10b72007-05-21 18:09:09 +080064.Llong_loop_s: R0 = [P0];
65 [P1++] = R0;
66 NOP;
67.Llong_loop_e: NOP;
Bryan Wu1394f032007-05-06 14:50:22 -070068 sti R3;
69 RTS;
Robin Getz251383c2008-08-14 15:12:55 +080070#else
71 P0 = R0; /* P0 = port */
72 P1 = R1; /* P1 = address */
73 P2 = R2; /* P2 = count */
74 SSYNC;
75 LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
76.Llong_loop_s:
77 CLI R3;
78 NOP; NOP; NOP;
79 R0 = [P0];
80 [P1++] = R0;
81.Llong_loop_e:
82 STI R3;
83
84 RTS;
85#endif
Mike Frysinger51be24c2007-06-11 15:31:30 +080086ENDPROC(_insl)
Michael Hennerich8af10b72007-05-21 18:09:09 +080087
Bryan Wu1394f032007-05-06 14:50:22 -070088ENTRY(_insw)
Robin Getz251383c2008-08-14 15:12:55 +080089#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
Bryan Wu1394f032007-05-06 14:50:22 -070090 P0 = R0; /* P0 = port */
91 cli R3;
92 P1 = R1; /* P1 = address */
93 P2 = R2; /* P2 = count */
94 SSYNC;
95 LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
Michael Hennerich8af10b72007-05-21 18:09:09 +080096.Lword_loop_s: R0 = W[P0];
97 W[P1++] = R0;
98 NOP;
99.Lword_loop_e: NOP;
Bryan Wu1394f032007-05-06 14:50:22 -0700100 sti R3;
101 RTS;
Robin Getz251383c2008-08-14 15:12:55 +0800102#else
103 P0 = R0; /* P0 = port */
104 P1 = R1; /* P1 = address */
105 P2 = R2; /* P2 = count */
106 SSYNC;
107 LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
108.Lword_loop_s:
109 CLI R3;
110 NOP; NOP; NOP;
111 R0 = W[P0];
112 W[P1++] = R0;
113.Lword_loop_e:
114 STI R3;
115 RTS;
116
117#endif
Mike Frysinger51be24c2007-06-11 15:31:30 +0800118ENDPROC(_insw)
Bryan Wu1394f032007-05-06 14:50:22 -0700119
Michael Hennerich59069672008-05-17 16:38:52 +0800120ENTRY(_insw_8)
Robin Getz251383c2008-08-14 15:12:55 +0800121#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
Michael Hennerich59069672008-05-17 16:38:52 +0800122 P0 = R0; /* P0 = port */
123 cli R3;
124 P1 = R1; /* P1 = address */
125 P2 = R2; /* P2 = count */
126 SSYNC;
127 LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2;
128.Lword8_loop_s: R0 = W[P0];
129 B[P1++] = R0;
130 R0 = R0 >> 8;
131 B[P1++] = R0;
132 NOP;
133.Lword8_loop_e: NOP;
134 sti R3;
135 RTS;
Robin Getz251383c2008-08-14 15:12:55 +0800136#else
137 P0 = R0; /* P0 = port */
138 P1 = R1; /* P1 = address */
139 P2 = R2; /* P2 = count */
140 SSYNC;
141 LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2;
142.Lword8_loop_s:
143 CLI R3;
144 NOP; NOP; NOP;
145 R0 = W[P0];
146 B[P1++] = R0;
147 R0 = R0 >> 8;
148 B[P1++] = R0;
149 NOP;
150.Lword8_loop_e:
151 STI R3;
152
153 RTS;
154#endif
Michael Hennerich59069672008-05-17 16:38:52 +0800155ENDPROC(_insw_8)
156
Bryan Wu1394f032007-05-06 14:50:22 -0700157ENTRY(_insb)
Robin Getz251383c2008-08-14 15:12:55 +0800158#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
Bryan Wu1394f032007-05-06 14:50:22 -0700159 P0 = R0; /* P0 = port */
160 cli R3;
161 P1 = R1; /* P1 = address */
162 P2 = R2; /* P2 = count */
163 SSYNC;
164 LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
Michael Hennerich8af10b72007-05-21 18:09:09 +0800165.Lbyte_loop_s: R0 = B[P0];
166 B[P1++] = R0;
167 NOP;
168.Lbyte_loop_e: NOP;
Bryan Wu1394f032007-05-06 14:50:22 -0700169 sti R3;
170 RTS;
Robin Getz251383c2008-08-14 15:12:55 +0800171#else
172 P0 = R0; /* P0 = port */
173 P1 = R1; /* P1 = address */
174 P2 = R2; /* P2 = count */
175 SSYNC;
176 LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
177.Lbyte_loop_s:
178 CLI R3;
179 NOP; NOP; NOP;
180 R0 = B[P0];
181 B[P1++] = R0;
182.Lbyte_loop_e:
183 STI R3;
184
185 RTS;
186#endif
Mike Frysinger51be24c2007-06-11 15:31:30 +0800187ENDPROC(_insb)
Michael Hennerich5c91fb92007-11-17 23:46:58 +0800188
Michael Hennerich5c91fb92007-11-17 23:46:58 +0800189ENTRY(_insl_16)
Robin Getz251383c2008-08-14 15:12:55 +0800190#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
Michael Hennerich5c91fb92007-11-17 23:46:58 +0800191 P0 = R0; /* P0 = port */
192 cli R3;
193 P1 = R1; /* P1 = address */
194 P2 = R2; /* P2 = count */
195 SSYNC;
196 LSETUP( .Llong16_loop_s, .Llong16_loop_e) LC0 = P2;
197.Llong16_loop_s: R0 = [P0];
198 W[P1++] = R0;
199 R0 = R0 >> 16;
200 W[P1++] = R0;
201 NOP;
202.Llong16_loop_e: NOP;
203 sti R3;
204 RTS;
Robin Getz251383c2008-08-14 15:12:55 +0800205#else
206 P0 = R0; /* P0 = port */
207 P1 = R1; /* P1 = address */
208 P2 = R2; /* P2 = count */
209 SSYNC;
210 LSETUP( .Llong16_loop_s, .Llong16_loop_e) LC0 = P2;
211.Llong16_loop_s:
212 CLI R3;
213 NOP; NOP; NOP;
214 R0 = [P0];
215 W[P1++] = R0;
216 R0 = R0 >> 16;
217 W[P1++] = R0;
218.Llong16_loop_e:
219 STI R3;
220 RTS;
221#endif
Michael Hennerich5c91fb92007-11-17 23:46:58 +0800222ENDPROC(_insl_16)