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 <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) \ 74.section .text._ins##func; \ 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) 90 91COMMON_INS(l, \ 92 R0 = [P0]; \ 93 [P1++] = R0; \ 94) 95 96COMMON_INS(w, \ 97 R0 = W[P0]; \ 98 W[P1++] = R0; \ 99) 100 101COMMON_INS(w_8, \ 102 R0 = W[P0]; \ 103 B[P1++] = R0; \ 104 R0 = R0 >> 8; \ 105 B[P1++] = R0; \ 106) 107 108COMMON_INS(b, \ 109 R0 = B[P0]; \ 110 B[P1++] = R0; \ 111) 112 113COMMON_INS(l_16, \ 114 R0 = [P0]; \ 115 W[P1++] = R0; \ 116 R0 = R0 >> 16; \ 117 W[P1++] = R0; \ 118) 119