Commit | Line | Data |
---|---|---|
1394f032 | 1 | /* |
c250bfb9 | 2 | * arch/blackfin/lib/ins.S - ins{bwl} using hardware loops |
1394f032 | 3 | * |
c250bfb9 MF |
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. | |
1394f032 BW |
7 | */ |
8 | ||
9 | #include <linux/linkage.h> | |
8af10b79 | 10 | #include <asm/blackfin.h> |
1394f032 BW |
11 | |
12 | .align 2 | |
13 | ||
c250bfb9 MF |
14 | #ifdef CONFIG_IPIPE |
15 | # define DO_CLI \ | |
16 | [--sp] = rets; \ | |
17 | [--sp] = (P5:0); \ | |
18 | sp += -12; \ | |
b9c7eb49 | 19 | call ___ipipe_disable_root_irqs_hw; \ |
c250bfb9 MF |
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; \ | |
b9c7eb49 | 31 | call ___ipipe_enable_root_irqs_hw; \ |
c250bfb9 MF |
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 | ||
251383c7 RG |
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 | |
1762275e | 69 | * ../kernel/bfin_dma.c |
25985edc | 70 | * Using the dma related functions are recommended for transferring large |
251383c7 RG |
71 | * buffers in/out of FIFOs. |
72 | */ | |
73 | ||
c250bfb9 MF |
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) | |
8af10b79 | 90 | |
c250bfb9 MF |
91 | COMMON_INS(l, \ |
92 | R0 = [P0]; \ | |
93 | [P1++] = R0; \ | |
94 | ) | |
251383c7 | 95 | |
c250bfb9 MF |
96 | COMMON_INS(w, \ |
97 | R0 = W[P0]; \ | |
98 | W[P1++] = R0; \ | |
99 | ) | |
1394f032 | 100 | |
c250bfb9 MF |
101 | COMMON_INS(w_8, \ |
102 | R0 = W[P0]; \ | |
103 | B[P1++] = R0; \ | |
104 | R0 = R0 >> 8; \ | |
105 | B[P1++] = R0; \ | |
106 | ) | |
59069676 | 107 | |
c250bfb9 MF |
108 | COMMON_INS(b, \ |
109 | R0 = B[P0]; \ | |
110 | B[P1++] = R0; \ | |
111 | ) | |
5c91fb90 | 112 | |
c250bfb9 MF |
113 | COMMON_INS(l_16, \ |
114 | R0 = [P0]; \ | |
115 | W[P1++] = R0; \ | |
116 | R0 = R0 >> 16; \ | |
117 | W[P1++] = R0; \ | |
118 | ) |