Blackfin arch: cleanup and unify the ins functions
[linux-2.6.git] / arch / blackfin / lib / ins.S
1 /*
2  * arch/blackfin/lib/ins.S - ins{bwl} using hardware loops
3  *
4  * Copyright 2004-2008 Analog Devices Inc.
5  * Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl>
6  * Licensed under the GPL-2 or later.
7  */
8
9 #include <linux/linkage.h>
10 #include <asm/blackfin.h>
11
12 .align 2
13
14 #ifdef CONFIG_IPIPE
15 # define DO_CLI \
16         [--sp] = rets; \
17         [--sp] = (P5:0); \
18         sp += -12; \
19         call ___ipipe_stall_root_raw; \
20         sp += 12; \
21         (P5:0) = [sp++];
22 # define CLI_INNER_NOP
23 #else
24 # define DO_CLI cli R3;
25 # define CLI_INNER_NOP nop; nop; nop;
26 #endif
27
28 #ifdef CONFIG_IPIPE
29 # define DO_STI \
30         sp += -12; \
31         call ___ipipe_unstall_root_raw; \
32         sp += 12; \
33 2:      rets = [sp++];
34 #else
35 # define DO_STI 2: sti R3;
36 #endif
37
38 #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
39 # define CLI_OUTER DO_CLI;
40 # define STI_OUTER DO_STI;
41 # define CLI_INNER 1:
42 # if ANOMALY_05000416
43 #  define STI_INNER nop; 2: nop;
44 # else
45 #  define STI_INNER 2:
46 # endif
47 #else
48 # define CLI_OUTER
49 # define STI_OUTER
50 # define CLI_INNER 1: DO_CLI; CLI_INNER_NOP;
51 # define STI_INNER DO_STI;
52 #endif
53
54 /*
55  * Reads on the Blackfin are speculative. In Blackfin terms, this means they
56  * can be interrupted at any time (even after they have been issued on to the
57  * external bus), and re-issued after the interrupt occurs.
58  *
59  * If a FIFO is sitting on the end of the read, it will see two reads,
60  * when the core only sees one. The FIFO receives the read which is cancelled,
61  * and not delivered to the core.
62  *
63  * To solve this, interrupts are turned off before reads occur to I/O space.
64  * There are 3 versions of all these functions
65  *  - turns interrupts off every read (higher overhead, but lower latency)
66  *  - turns interrupts off every loop (low overhead, but longer latency)
67  *  - DMA version, which do not suffer from this issue. DMA versions have
68  *      different name (prefixed by dma_ ), and are located in
69  *      ../kernel/bfin_dma_5xx.c
70  * Using the dma related functions are recommended for transfering large
71  * buffers in/out of FIFOs.
72  */
73
74 #define COMMON_INS(func, ops) \
75 ENTRY(_ins##func) \
76         P0 = R0;        /* P0 = port */ \
77         CLI_OUTER;      /* 3 instructions before first read access */ \
78         P1 = R1;        /* P1 = address */ \
79         P2 = R2;        /* P2 = count */ \
80         SSYNC; \
81  \
82         LSETUP(1f, 2f) LC0 = P2; \
83         CLI_INNER; \
84         ops; \
85         STI_INNER; \
86  \
87         STI_OUTER; \
88         RTS; \
89 ENDPROC(_ins##func)
90
91 COMMON_INS(l, \
92         R0 = [P0]; \
93         [P1++] = R0; \
94 )
95
96 COMMON_INS(w, \
97         R0 = W[P0]; \
98         W[P1++] = R0; \
99 )
100
101 COMMON_INS(w_8, \
102         R0 = W[P0]; \
103         B[P1++] = R0; \
104         R0 = R0 >> 8; \
105         B[P1++] = R0; \
106 )
107
108 COMMON_INS(b, \
109         R0 = B[P0]; \
110         B[P1++] = R0; \
111 )
112
113 COMMON_INS(l_16, \
114         R0 = [P0]; \
115         W[P1++] = R0; \
116         R0 = R0 >> 16; \
117         W[P1++] = R0; \
118 )