ins.S 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /*
  2. * File: arch/blackfin/lib/ins.S
  3. * Based on:
  4. * Author: Bas Vermeulen <bas@buyways.nl>
  5. *
  6. * Created: Tue Mar 22 15:27:24 CEST 2005
  7. * Description: Implementation of ins{bwl} for BlackFin processors using zero overhead loops.
  8. *
  9. * Modified:
  10. * Copyright 2004-2008 Analog Devices Inc.
  11. * Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl>
  12. *
  13. * Bugs: Enter bugs at http://blackfin.uclinux.org/
  14. *
  15. * This program is free software; you can redistribute it and/or modify
  16. * it under the terms of the GNU General Public License as published by
  17. * the Free Software Foundation; either version 2 of the License, or
  18. * (at your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, see the file COPYING, or write
  27. * to the Free Software Foundation, Inc.,
  28. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  29. */
  30. #include <linux/linkage.h>
  31. #include <asm/blackfin.h>
  32. .align 2
  33. /*
  34. * Reads on the Blackfin are speculative. In Blackfin terms, this means they
  35. * can be interrupted at any time (even after they have been issued on to the
  36. * external bus), and re-issued after the interrupt occurs.
  37. *
  38. * If a FIFO is sitting on the end of the read, it will see two reads,
  39. * when the core only sees one. The FIFO receives the read which is cancelled,
  40. * and not delivered to the core.
  41. *
  42. * To solve this, interrupts are turned off before reads occur to I/O space.
  43. * There are 3 versions of all these functions
  44. * - turns interrupts off every read (higher overhead, but lower latency)
  45. * - turns interrupts off every loop (low overhead, but longer latency)
  46. * - DMA version, which do not suffer from this issue. DMA versions have
  47. * different name (prefixed by dma_ ), and are located in
  48. * ../kernel/bfin_dma_5xx.c
  49. * Using the dma related functions are recommended for transfering large
  50. * buffers in/out of FIFOs.
  51. */
  52. ENTRY(_insl)
  53. #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
  54. P0 = R0; /* P0 = port */
  55. #ifdef CONFIG_IPIPE
  56. [--sp] = rets
  57. [--sp] = (P5:0);
  58. sp += -12
  59. call ___ipipe_stall_root_raw
  60. sp += 12
  61. (P5:0) = [sp++];
  62. #else
  63. cli R3;
  64. #endif
  65. P1 = R1; /* P1 = address */
  66. P2 = R2; /* P2 = count */
  67. SSYNC;
  68. LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
  69. .Llong_loop_s: R0 = [P0];
  70. [P1++] = R0;
  71. NOP;
  72. .Llong_loop_e: NOP;
  73. #ifdef CONFIG_IPIPE
  74. sp += -12
  75. call ___ipipe_unstall_root_raw
  76. sp += 12
  77. rets = [sp++]
  78. #else
  79. sti R3;
  80. #endif
  81. RTS;
  82. #else
  83. P0 = R0; /* P0 = port */
  84. P1 = R1; /* P1 = address */
  85. P2 = R2; /* P2 = count */
  86. SSYNC;
  87. LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
  88. .Llong_loop_s:
  89. #ifdef CONFIG_IPIPE
  90. [--sp] = rets
  91. [--sp] = (P5:0);
  92. sp += -12
  93. call ___ipipe_stall_root_raw
  94. sp += 12
  95. (P5:0) = [sp++];
  96. #else
  97. CLI R3;
  98. #endif
  99. NOP; NOP; NOP;
  100. R0 = [P0];
  101. [P1++] = R0;
  102. .Llong_loop_e:
  103. #ifdef CONFIG_IPIPE
  104. sp += -12
  105. call ___ipipe_unstall_root_raw
  106. sp += 12
  107. rets = [sp++]
  108. #else
  109. STI R3;
  110. #endif
  111. RTS;
  112. #endif
  113. ENDPROC(_insl)
  114. ENTRY(_insw)
  115. #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
  116. P0 = R0; /* P0 = port */
  117. #ifdef CONFIG_IPIPE
  118. [--sp] = rets
  119. [--sp] = (P5:0);
  120. sp += -12
  121. call ___ipipe_stall_root_raw
  122. sp += 12
  123. (P5:0) = [sp++];
  124. #else
  125. cli R3;
  126. #endif
  127. P1 = R1; /* P1 = address */
  128. P2 = R2; /* P2 = count */
  129. SSYNC;
  130. LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
  131. .Lword_loop_s: R0 = W[P0];
  132. W[P1++] = R0;
  133. NOP;
  134. .Lword_loop_e: NOP;
  135. #ifdef CONFIG_IPIPE
  136. sp += -12
  137. call ___ipipe_unstall_root_raw
  138. sp += 12
  139. rets = [sp++]
  140. #else
  141. sti R3;
  142. #endif
  143. RTS;
  144. #else
  145. P0 = R0; /* P0 = port */
  146. P1 = R1; /* P1 = address */
  147. P2 = R2; /* P2 = count */
  148. SSYNC;
  149. LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
  150. .Lword_loop_s:
  151. #ifdef CONFIG_IPIPE
  152. [--sp] = rets
  153. [--sp] = (P5:0);
  154. sp += -12
  155. call ___ipipe_stall_root_raw
  156. sp += 12
  157. (P5:0) = [sp++];
  158. #else
  159. CLI R3;
  160. #endif
  161. NOP; NOP; NOP;
  162. R0 = W[P0];
  163. W[P1++] = R0;
  164. .Lword_loop_e:
  165. #ifdef CONFIG_IPIPE
  166. sp += -12
  167. call ___ipipe_unstall_root_raw
  168. sp += 12
  169. rets = [sp++]
  170. #else
  171. STI R3;
  172. #endif
  173. RTS;
  174. #endif
  175. ENDPROC(_insw)
  176. ENTRY(_insw_8)
  177. #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
  178. P0 = R0; /* P0 = port */
  179. #ifdef CONFIG_IPIPE
  180. [--sp] = rets
  181. [--sp] = (P5:0);
  182. sp += -12
  183. call ___ipipe_stall_root_raw
  184. sp += 12
  185. (P5:0) = [sp++];
  186. #else
  187. cli R3;
  188. #endif
  189. P1 = R1; /* P1 = address */
  190. P2 = R2; /* P2 = count */
  191. SSYNC;
  192. LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2;
  193. .Lword8_loop_s: R0 = W[P0];
  194. B[P1++] = R0;
  195. R0 = R0 >> 8;
  196. B[P1++] = R0;
  197. NOP;
  198. .Lword8_loop_e: NOP;
  199. #ifdef CONFIG_IPIPE
  200. sp += -12
  201. call ___ipipe_unstall_root_raw
  202. sp += 12
  203. rets = [sp++]
  204. #else
  205. sti R3;
  206. #endif
  207. RTS;
  208. #else
  209. P0 = R0; /* P0 = port */
  210. P1 = R1; /* P1 = address */
  211. P2 = R2; /* P2 = count */
  212. SSYNC;
  213. LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2;
  214. .Lword8_loop_s:
  215. #ifdef CONFIG_IPIPE
  216. [--sp] = rets
  217. [--sp] = (P5:0);
  218. sp += -12
  219. call ___ipipe_stall_root_raw
  220. sp += 12
  221. (P5:0) = [sp++];
  222. #else
  223. CLI R3;
  224. #endif
  225. NOP; NOP; NOP;
  226. R0 = W[P0];
  227. B[P1++] = R0;
  228. R0 = R0 >> 8;
  229. B[P1++] = R0;
  230. NOP;
  231. .Lword8_loop_e:
  232. #ifdef CONFIG_IPIPE
  233. sp += -12
  234. call ___ipipe_unstall_root_raw
  235. sp += 12
  236. rets = [sp++]
  237. #else
  238. STI R3;
  239. #endif
  240. RTS;
  241. #endif
  242. ENDPROC(_insw_8)
  243. ENTRY(_insb)
  244. #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
  245. P0 = R0; /* P0 = port */
  246. #ifdef CONFIG_IPIPE
  247. [--sp] = rets
  248. [--sp] = (P5:0);
  249. sp += -12
  250. call ___ipipe_stall_root_raw
  251. sp += 12
  252. (P5:0) = [sp++];
  253. #else
  254. cli R3;
  255. #endif
  256. P1 = R1; /* P1 = address */
  257. P2 = R2; /* P2 = count */
  258. SSYNC;
  259. LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
  260. .Lbyte_loop_s: R0 = B[P0];
  261. B[P1++] = R0;
  262. NOP;
  263. .Lbyte_loop_e: NOP;
  264. #ifdef CONFIG_IPIPE
  265. sp += -12
  266. call ___ipipe_unstall_root_raw
  267. sp += 12
  268. rets = [sp++]
  269. #else
  270. sti R3;
  271. #endif
  272. RTS;
  273. #else
  274. P0 = R0; /* P0 = port */
  275. P1 = R1; /* P1 = address */
  276. P2 = R2; /* P2 = count */
  277. SSYNC;
  278. LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
  279. .Lbyte_loop_s:
  280. #ifdef CONFIG_IPIPE
  281. [--sp] = rets
  282. [--sp] = (P5:0);
  283. sp += -12
  284. call ___ipipe_stall_root_raw
  285. sp += 12
  286. (P5:0) = [sp++];
  287. #else
  288. CLI R3;
  289. #endif
  290. NOP; NOP; NOP;
  291. R0 = B[P0];
  292. B[P1++] = R0;
  293. .Lbyte_loop_e:
  294. #ifdef CONFIG_IPIPE
  295. sp += -12
  296. call ___ipipe_unstall_root_raw
  297. sp += 12
  298. rets = [sp++]
  299. #else
  300. STI R3;
  301. #endif
  302. RTS;
  303. #endif
  304. ENDPROC(_insb)
  305. ENTRY(_insl_16)
  306. #ifdef CONFIG_BFIN_INS_LOWOVERHEAD
  307. P0 = R0; /* P0 = port */
  308. #ifdef CONFIG_IPIPE
  309. [--sp] = rets
  310. [--sp] = (P5:0);
  311. sp += -12
  312. call ___ipipe_stall_root_raw
  313. sp += 12
  314. (P5:0) = [sp++];
  315. #else
  316. cli R3;
  317. #endif
  318. P1 = R1; /* P1 = address */
  319. P2 = R2; /* P2 = count */
  320. SSYNC;
  321. LSETUP( .Llong16_loop_s, .Llong16_loop_e) LC0 = P2;
  322. .Llong16_loop_s: R0 = [P0];
  323. W[P1++] = R0;
  324. R0 = R0 >> 16;
  325. W[P1++] = R0;
  326. NOP;
  327. .Llong16_loop_e: NOP;
  328. #ifdef CONFIG_IPIPE
  329. sp += -12
  330. call ___ipipe_unstall_root_raw
  331. sp += 12
  332. rets = [sp++]
  333. #else
  334. sti R3;
  335. #endif
  336. RTS;
  337. #else
  338. P0 = R0; /* P0 = port */
  339. P1 = R1; /* P1 = address */
  340. P2 = R2; /* P2 = count */
  341. SSYNC;
  342. LSETUP( .Llong16_loop_s, .Llong16_loop_e) LC0 = P2;
  343. .Llong16_loop_s:
  344. #ifdef CONFIG_IPIPE
  345. [--sp] = rets
  346. [--sp] = (P5:0);
  347. sp += -12
  348. call ___ipipe_stall_root_raw
  349. sp += 12
  350. (P5:0) = [sp++];
  351. #else
  352. CLI R3;
  353. #endif
  354. NOP; NOP; NOP;
  355. R0 = [P0];
  356. W[P1++] = R0;
  357. R0 = R0 >> 16;
  358. W[P1++] = R0;
  359. .Llong16_loop_e:
  360. #ifdef CONFIG_IPIPE
  361. sp += -12
  362. call ___ipipe_unstall_root_raw
  363. sp += 12
  364. rets = [sp++]
  365. #else
  366. STI R3;
  367. #endif
  368. RTS;
  369. #endif
  370. ENDPROC(_insl_16)