/*1* arch/blackfin/lib/ins.S - ins{bwl} using hardware loops2*3* Copyright 2004-2008 Analog Devices Inc.4* Copyright (C) 2005 Bas Vermeulen, BuyWays BV <[email protected]>5* Licensed under the GPL-2 or later.6*/78#include <linux/linkage.h>9#include <asm/blackfin.h>1011.align 21213#ifdef CONFIG_IPIPE14# define DO_CLI \15[--sp] = rets; \16[--sp] = (P5:0); \17sp += -12; \18call ___ipipe_disable_root_irqs_hw; \19sp += 12; \20(P5:0) = [sp++];21# define CLI_INNER_NOP22#else23# define DO_CLI cli R3;24# define CLI_INNER_NOP nop; nop; nop;25#endif2627#ifdef CONFIG_IPIPE28# define DO_STI \29sp += -12; \30call ___ipipe_enable_root_irqs_hw; \31sp += 12; \322: rets = [sp++];33#else34# define DO_STI 2: sti R3;35#endif3637#ifdef CONFIG_BFIN_INS_LOWOVERHEAD38# define CLI_OUTER DO_CLI;39# define STI_OUTER DO_STI;40# define CLI_INNER 1:41# if ANOMALY_0500041642# define STI_INNER nop; 2: nop;43# else44# define STI_INNER 2:45# endif46#else47# define CLI_OUTER48# define STI_OUTER49# define CLI_INNER 1: DO_CLI; CLI_INNER_NOP;50# define STI_INNER DO_STI;51#endif5253/*54* Reads on the Blackfin are speculative. In Blackfin terms, this means they55* can be interrupted at any time (even after they have been issued on to the56* 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 functions64* - 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 have67* different name (prefixed by dma_ ), and are located in68* ../kernel/bfin_dma_5xx.c69* Using the dma related functions are recommended for transferring large70* buffers in/out of FIFOs.71*/7273#define COMMON_INS(func, ops) \74ENTRY(_ins##func) \75P0 = R0; /* P0 = port */ \76CLI_OUTER; /* 3 instructions before first read access */ \77P1 = R1; /* P1 = address */ \78P2 = R2; /* P2 = count */ \79SSYNC; \80\81LSETUP(1f, 2f) LC0 = P2; \82CLI_INNER; \83ops; \84STI_INNER; \85\86STI_OUTER; \87RTS; \88ENDPROC(_ins##func)8990COMMON_INS(l, \91R0 = [P0]; \92[P1++] = R0; \93)9495COMMON_INS(w, \96R0 = W[P0]; \97W[P1++] = R0; \98)99100COMMON_INS(w_8, \101R0 = W[P0]; \102B[P1++] = R0; \103R0 = R0 >> 8; \104B[P1++] = R0; \105)106107COMMON_INS(b, \108R0 = B[P0]; \109B[P1++] = R0; \110)111112COMMON_INS(l_16, \113R0 = [P0]; \114W[P1++] = R0; \115R0 = R0 >> 16; \116W[P1++] = R0; \117)118119120