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