cache.S 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. * Blackfin cache control code
  3. *
  4. * Copyright 2004-2008 Analog Devices Inc.
  5. *
  6. * Licensed under the GPL-2 or later.
  7. */
  8. #include <linux/linkage.h>
  9. #include <asm/blackfin.h>
  10. #include <asm/cache.h>
  11. #include <asm/page.h>
  12. #ifdef CONFIG_CACHE_FLUSH_L1
  13. .section .l1.text
  14. #else
  15. .text
  16. #endif
  17. /* 05000443 - IFLUSH cannot be last instruction in hardware loop */
  18. #if ANOMALY_05000443
  19. # define BROK_FLUSH_INST "IFLUSH"
  20. #else
  21. # define BROK_FLUSH_INST "no anomaly! yeah!"
  22. #endif
  23. /* Since all L1 caches work the same way, we use the same method for flushing
  24. * them. Only the actual flush instruction differs. We write this in asm as
  25. * GCC can be hard to coax into writing nice hardware loops.
  26. *
  27. * Also, we assume the following register setup:
  28. * R0 = start address
  29. * R1 = end address
  30. */
  31. .macro do_flush flushins:req label
  32. R2 = -L1_CACHE_BYTES;
  33. /* start = (start & -L1_CACHE_BYTES) */
  34. R0 = R0 & R2;
  35. /* end = ((end - 1) & -L1_CACHE_BYTES) + L1_CACHE_BYTES; */
  36. R1 += -1;
  37. R1 = R1 & R2;
  38. R1 += L1_CACHE_BYTES;
  39. /* count = (end - start) >> L1_CACHE_SHIFT */
  40. R2 = R1 - R0;
  41. R2 >>= L1_CACHE_SHIFT;
  42. P1 = R2;
  43. .ifnb \label
  44. \label :
  45. .endif
  46. P0 = R0;
  47. LSETUP (1f, 2f) LC1 = P1;
  48. 1:
  49. .ifeqs "\flushins", BROK_FLUSH_INST
  50. \flushins [P0++];
  51. 2: nop;
  52. .else
  53. 2: \flushins [P0++];
  54. .endif
  55. RTS;
  56. .endm
  57. /* Invalidate all instruction cache lines assocoiated with this memory area */
  58. ENTRY(_blackfin_icache_flush_range)
  59. do_flush IFLUSH
  60. ENDPROC(_blackfin_icache_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)