ins.S 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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. #include <linux/linkage.h>
  9. #include <asm/blackfin.h>
  10. .align 2
  11. #ifdef CONFIG_IPIPE
  12. # define DO_CLI \
  13. [--sp] = rets; \
  14. [--sp] = (P5:0); \
  15. sp += -12; \
  16. call ___ipipe_disable_root_irqs_hw; \
  17. sp += 12; \
  18. (P5:0) = [sp++];
  19. # define CLI_INNER_NOP
  20. #else
  21. # define DO_CLI cli R3;
  22. # define CLI_INNER_NOP nop; nop; nop;
  23. #endif
  24. #ifdef CONFIG_IPIPE
  25. # define DO_STI \
  26. sp += -12; \
  27. call ___ipipe_enable_root_irqs_hw; \
  28. sp += 12; \
  29. 2: rets = [sp++];
  30. #else
  31. # define DO_STI 2: sti R3;
  32. #endif
  33. #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
  34. # define CLI_OUTER DO_CLI;
  35. # define STI_OUTER DO_STI;
  36. # define CLI_INNER 1:
  37. # if ANOMALY_05000416
  38. # define STI_INNER nop; 2: nop;
  39. # else
  40. # define STI_INNER 2:
  41. # endif
  42. #else
  43. # define CLI_OUTER
  44. # define STI_OUTER
  45. # define CLI_INNER 1: DO_CLI; CLI_INNER_NOP;
  46. # define STI_INNER DO_STI;
  47. #endif
  48. /*
  49. * Reads on the Blackfin are speculative. In Blackfin terms, this means they
  50. * can be interrupted at any time (even after they have been issued on to the
  51. * external bus), and re-issued after the interrupt occurs.
  52. *
  53. * If a FIFO is sitting on the end of the read, it will see two reads,
  54. * when the core only sees one. The FIFO receives the read which is cancelled,
  55. * and not delivered to the core.
  56. *
  57. * To solve this, interrupts are turned off before reads occur to I/O space.
  58. * There are 3 versions of all these functions
  59. * - turns interrupts off every read (higher overhead, but lower latency)
  60. * - turns interrupts off every loop (low overhead, but longer latency)
  61. * - DMA version, which do not suffer from this issue. DMA versions have
  62. * different name (prefixed by dma_ ), and are located in
  63. * ../kernel/bfin_dma.c
  64. * Using the dma related functions are recommended for transferring large
  65. * buffers in/out of FIFOs.
  66. */
  67. #define COMMON_INS(func, ops) \
  68. ENTRY(_ins##func) \
  69. P0 = R0; /* P0 = port */ \
  70. CLI_OUTER; /* 3 instructions before first read access */ \
  71. P1 = R1; /* P1 = address */ \
  72. P2 = R2; /* P2 = count */ \
  73. SSYNC; \
  74. \
  75. LSETUP(1f, 2f) LC0 = P2; \
  76. CLI_INNER; \
  77. ops; \
  78. STI_INNER; \
  79. \
  80. STI_OUTER; \
  81. RTS; \
  82. ENDPROC(_ins##func)
  83. COMMON_INS(l, \
  84. R0 = [P0]; \
  85. [P1++] = R0; \
  86. )
  87. COMMON_INS(w, \
  88. R0 = W[P0]; \
  89. W[P1++] = R0; \
  90. )
  91. COMMON_INS(w_8, \
  92. R0 = W[P0]; \
  93. B[P1++] = R0; \
  94. R0 = R0 >> 8; \
  95. B[P1++] = R0; \
  96. )
  97. COMMON_INS(b, \
  98. R0 = B[P0]; \
  99. B[P1++] = R0; \
  100. )
  101. COMMON_INS(l_16, \
  102. R0 = [P0]; \
  103. W[P1++] = R0; \
  104. R0 = R0 >> 16; \
  105. W[P1++] = R0; \
  106. )