linux/arch/blackfin/lib/ins.S
<<
>>
Prefs
   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 <linux/linkage.h>
  10#include <asm/blackfin.h>
  11
  12.align 2
  13
  14#ifdef CONFIG_IPIPE
  15# define DO_CLI \
  16        [--sp] = rets; \
  17        [--sp] = (P5:0); \
  18        sp += -12; \
  19        call ___ipipe_disable_root_irqs_hw; \
  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; \
  31        call ___ipipe_enable_root_irqs_hw; \
  32        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
  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
  69 *      ../kernel/bfin_dma_5xx.c
  70 * Using the dma related functions are recommended for transfering large
  71 * buffers in/out of FIFOs.
  72 */
  73
  74#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)
  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