cache.S 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * Blackfin cache control code
  3. *
  4. * Copyright 2004-2008 Analog Devices Inc.
  5. *
  6. * Enter bugs at http://blackfin.uclinux.org/
  7. *
  8. * Licensed under the GPL-2 or later.
  9. */
  10. #include <linux/linkage.h>
  11. #include <asm/blackfin.h>
  12. #include <asm/cache.h>
  13. #include <asm/page.h>
  14. .text
  15. /* Since all L1 caches work the same way, we use the same method for flushing
  16. * them. Only the actual flush instruction differs. We write this in asm as
  17. * GCC can be hard to coax into writing nice hardware loops.
  18. *
  19. * Also, we assume the following register setup:
  20. * R0 = start address
  21. * R1 = end address
  22. */
  23. .macro do_flush flushins:req optflushins optnopins label
  24. /* end = ((end - 1) & -L1_CACHE_BYTES) + L1_CACHE_BYTES; */
  25. R1 += -1;
  26. R2 = -L1_CACHE_BYTES;
  27. R1 = R1 & R2;
  28. R1 += L1_CACHE_BYTES;
  29. /* count = (end - start) >> L1_CACHE_SHIFT */
  30. R2 = R1 - R0;
  31. R2 >>= L1_CACHE_SHIFT;
  32. P1 = R2;
  33. .ifnb \label
  34. \label :
  35. .endif
  36. P0 = R0;
  37. LSETUP (1f, 2f) LC1 = P1;
  38. 1:
  39. .ifnb \optflushins
  40. \optflushins [P0];
  41. .endif
  42. .ifb \optnopins
  43. 2:
  44. .endif
  45. \flushins [P0++];
  46. .ifnb \optnopins
  47. 2: \optnopins;
  48. .endif
  49. RTS;
  50. .endm
  51. /* Invalidate all instruction cache lines assocoiated with this memory area */
  52. ENTRY(_blackfin_icache_flush_range)
  53. do_flush IFLUSH, , nop
  54. ENDPROC(_blackfin_icache_flush_range)
  55. /* Flush all cache lines assocoiated with this area of memory. */
  56. ENTRY(_blackfin_icache_dcache_flush_range)
  57. do_flush IFLUSH, FLUSH
  58. ENDPROC(_blackfin_icache_dcache_flush_range)
  59. /* Throw away all D-cached data in specified region without any obligation to
  60. * write them back. Since the Blackfin ISA does not have an "invalidate"
  61. * instruction, we use flush/invalidate. Perhaps as a speed optimization we
  62. * could bang on the DTEST MMRs ...
  63. */
  64. ENTRY(_blackfin_dcache_invalidate_range)
  65. do_flush FLUSHINV
  66. ENDPROC(_blackfin_dcache_invalidate_range)
  67. /* Flush all data cache lines assocoiated with this memory area */
  68. ENTRY(_blackfin_dcache_flush_range)
  69. do_flush FLUSH, , , .Ldfr
  70. ENDPROC(_blackfin_dcache_flush_range)
  71. /* Our headers convert the page structure to an address, so just need to flush
  72. * its contents like normal. We know the start address is page aligned (which
  73. * greater than our cache alignment), as is the end address. So just jump into
  74. * the middle of the dcache flush function.
  75. */
  76. ENTRY(_blackfin_dflush_page)
  77. P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT);
  78. jump .Ldfr;
  79. ENDPROC(_blackfin_dflush_page)