cache.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * (C) Copyright 2003
  3. * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <asm/cacheops.h>
  9. #include <asm/mipsregs.h>
  10. #ifdef CONFIG_SYS_CACHELINE_SIZE
  11. static inline unsigned long icache_line_size(void)
  12. {
  13. return CONFIG_SYS_CACHELINE_SIZE;
  14. }
  15. static inline unsigned long dcache_line_size(void)
  16. {
  17. return CONFIG_SYS_CACHELINE_SIZE;
  18. }
  19. #else /* !CONFIG_SYS_CACHELINE_SIZE */
  20. static inline unsigned long icache_line_size(void)
  21. {
  22. unsigned long conf1, il;
  23. conf1 = read_c0_config1();
  24. il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF;
  25. if (!il)
  26. return 0;
  27. return 2 << il;
  28. }
  29. static inline unsigned long dcache_line_size(void)
  30. {
  31. unsigned long conf1, dl;
  32. conf1 = read_c0_config1();
  33. dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF;
  34. if (!dl)
  35. return 0;
  36. return 2 << dl;
  37. }
  38. #endif /* !CONFIG_SYS_CACHELINE_SIZE */
  39. void flush_cache(ulong start_addr, ulong size)
  40. {
  41. unsigned long ilsize = icache_line_size();
  42. unsigned long dlsize = dcache_line_size();
  43. const void *addr, *aend;
  44. /* aend will be miscalculated when size is zero, so we return here */
  45. if (size == 0)
  46. return;
  47. addr = (const void *)(start_addr & ~(dlsize - 1));
  48. aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1));
  49. if (ilsize == dlsize) {
  50. /* flush I-cache & D-cache simultaneously */
  51. while (1) {
  52. mips_cache(HIT_WRITEBACK_INV_D, addr);
  53. mips_cache(HIT_INVALIDATE_I, addr);
  54. if (addr == aend)
  55. break;
  56. addr += dlsize;
  57. }
  58. return;
  59. }
  60. /* flush D-cache */
  61. while (1) {
  62. mips_cache(HIT_WRITEBACK_INV_D, addr);
  63. if (addr == aend)
  64. break;
  65. addr += dlsize;
  66. }
  67. /* flush I-cache */
  68. addr = (const void *)(start_addr & ~(ilsize - 1));
  69. aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1));
  70. while (1) {
  71. mips_cache(HIT_INVALIDATE_I, addr);
  72. if (addr == aend)
  73. break;
  74. addr += ilsize;
  75. }
  76. }
  77. void flush_dcache_range(ulong start_addr, ulong stop)
  78. {
  79. unsigned long lsize = dcache_line_size();
  80. const void *addr = (const void *)(start_addr & ~(lsize - 1));
  81. const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
  82. /* aend will be miscalculated when size is zero, so we return here */
  83. if (start_addr == stop)
  84. return;
  85. while (1) {
  86. mips_cache(HIT_WRITEBACK_INV_D, addr);
  87. if (addr == aend)
  88. break;
  89. addr += lsize;
  90. }
  91. }
  92. void invalidate_dcache_range(ulong start_addr, ulong stop)
  93. {
  94. unsigned long lsize = dcache_line_size();
  95. const void *addr = (const void *)(start_addr & ~(lsize - 1));
  96. const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
  97. /* aend will be miscalculated when size is zero, so we return here */
  98. if (start_addr == stop)
  99. return;
  100. while (1) {
  101. mips_cache(HIT_INVALIDATE_D, addr);
  102. if (addr == aend)
  103. break;
  104. addr += lsize;
  105. }
  106. }