blob: d59608deccc161fa50f5311e218c55c519a0844e [file] [log] [blame]
Bryan Wu1394f032007-05-06 14:50:22 -07001/*
Mike Frysingerc250bfb2009-01-07 23:14:38 +08002 * arch/blackfin/lib/ins.S - ins{bwl} using hardware loops
Bryan Wu1394f032007-05-06 14:50:22 -07003 *
Mike Frysingerc250bfb2009-01-07 23:14:38 +08004 * 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.
Bryan Wu1394f032007-05-06 14:50:22 -07007 */
8
9#include <linux/linkage.h>
Michael Hennerich8af10b72007-05-21 18:09:09 +080010#include <asm/blackfin.h>
Bryan Wu1394f032007-05-06 14:50:22 -070011
12.align 2
13
Mike Frysingerc250bfb2009-01-07 23:14:38 +080014#ifdef CONFIG_IPIPE
15# define DO_CLI \
16 [--sp] = rets; \
17 [--sp] = (P5:0); \
18 sp += -12; \
Philippe Gerumb9c7eb42009-06-22 18:22:48 +020019 call ___ipipe_disable_root_irqs_hw; \
Mike Frysingerc250bfb2009-01-07 23:14:38 +080020 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; \
Philippe Gerumb9c7eb42009-06-22 18:22:48 +020031 call ___ipipe_enable_root_irqs_hw; \
Mike Frysingerc250bfb2009-01-07 23:14:38 +080032 sp += 12; \
332: 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
Robin Getz251383c2008-08-14 15:12:55 +080054/*
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
Sonic Zhang17622752011-08-03 15:16:15 +080069 * ../kernel/bfin_dma.c
Lucas De Marchi25985ed2011-03-30 22:57:33 -030070 * Using the dma related functions are recommended for transferring large
Robin Getz251383c2008-08-14 15:12:55 +080071 * buffers in/out of FIFOs.
72 */
73
Mike Frysingerc250bfb2009-01-07 23:14:38 +080074#define COMMON_INS(func, ops) \
75ENTRY(_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; \
89ENDPROC(_ins##func)
Michael Hennerich8af10b72007-05-21 18:09:09 +080090
Mike Frysingerc250bfb2009-01-07 23:14:38 +080091COMMON_INS(l, \
92 R0 = [P0]; \
93 [P1++] = R0; \
94)
Robin Getz251383c2008-08-14 15:12:55 +080095
Mike Frysingerc250bfb2009-01-07 23:14:38 +080096COMMON_INS(w, \
97 R0 = W[P0]; \
98 W[P1++] = R0; \
99)
Bryan Wu1394f032007-05-06 14:50:22 -0700100
Mike Frysingerc250bfb2009-01-07 23:14:38 +0800101COMMON_INS(w_8, \
102 R0 = W[P0]; \
103 B[P1++] = R0; \
104 R0 = R0 >> 8; \
105 B[P1++] = R0; \
106)
Michael Hennerich59069672008-05-17 16:38:52 +0800107
Mike Frysingerc250bfb2009-01-07 23:14:38 +0800108COMMON_INS(b, \
109 R0 = B[P0]; \
110 B[P1++] = R0; \
111)
Michael Hennerich5c91fb92007-11-17 23:46:58 +0800112
Mike Frysingerc250bfb2009-01-07 23:14:38 +0800113COMMON_INS(l_16, \
114 R0 = [P0]; \
115 W[P1++] = R0; \
116 R0 = R0 >> 16; \
117 W[P1++] = R0; \
118)