uboot/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 <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