cache.S 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. R2 = -L1_CACHE_BYTES;
  25. /* start = (start & -L1_CACHE_BYTES) */
  26. R0 = R0 & R2;
  27. /* end = ((end - 1) & -L1_CACHE_BYTES) + L1_CACHE_BYTES; */
  28. R1 += -1;
  29. R1 = R1 & R2;
  30. R1 += L1_CACHE_BYTES;
  31. /* count = (end - start) >> L1_CACHE_SHIFT */
  32. R2 = R1 - R0;
  33. R2 >>= L1_CACHE_SHIFT;
  34. P1 = R2;
  35. .ifnb \label
  36. \label :
  37. .endif
  38. P0 = R0;
  39. LSETUP (1f, 2f) LC1 = P1;
  40. 1:
  41. .ifnb \optflushins
  42. \optflushins [P0];
  43. .endif
  44. .ifb \optnopins
  45. 2:
  46. .endif
  47. \flushins [P0++];
  48. .ifnb \optnopins
  49. 2: \optnopins;
  50. .endif
  51. RTS;
  52. .endm
  53. /* Invalidate all instruction cache lines assocoiated with this memory area */
  54. ENTRY(_blackfin_icache_flush_range)
  55. do_flush IFLUSH, , nop
  56. ENDPROC(_blackfin_icache_flush_range)
  57. /* Flush all cache lines assocoiated with this area of memory. */
  58. ENTRY(_blackfin_icache_dcache_flush_range)
  59. do_flush FLUSH, IFLUSH
  60. ENDPROC(_blackfin_icache_dcache_flush_range)
  61. /* Throw away all D-cached data in specified region without any obligation to
  62. * write them back. Since the Blackfin ISA does not have an "invalidate"
  63. * instruction, we use flush/invalidate. Perhaps as a speed optimization we
  64. * could bang on the DTEST MMRs ...
  65. */
  66. ENTRY(_blackfin_dcache_invalidate_range)
  67. do_flush FLUSHINV
  68. ENDPROC(_blackfin_dcache_invalidate_range)
  69. /* Flush all data cache lines assocoiated with this memory area */
  70. ENTRY(_blackfin_dcache_flush_range)
  71. do_flush FLUSH, , , .Ldfr
  72. ENDPROC(_blackfin_dcache_flush_range)
  73. /* Our headers convert the page structure to an address, so just need to flush
  74. * its contents like normal. We know the start address is page aligned (which
  75. * greater than our cache alignment), as is the end address. So just jump into
  76. * the middle of the dcache flush function.
  77. */
  78. ENTRY(_blackfin_dflush_page)
  79. P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT);
  80. jump .Ldfr;
  81. ENDPROC(_blackfin_dflush_page)