cache_uniphier.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <common.h>
  7. #include <linux/io.h>
  8. #include <asm/armv7.h>
  9. #include "ssc-regs.h"
  10. #ifdef CONFIG_UNIPHIER_L2CACHE_ON
  11. static void uniphier_cache_sync(void)
  12. {
  13. writel(SSCOPE_CM_SYNC, SSCOPE); /* drain internal buffers */
  14. readl(SSCOPE); /* need a read back to confirm */
  15. }
  16. static void uniphier_cache_maint_all(u32 operation)
  17. {
  18. /* try until the command is successfully set */
  19. do {
  20. writel(SSCOQM_S_ALL | SSCOQM_CE | operation, SSCOQM);
  21. } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
  22. /* wait until the operation is completed */
  23. while (readl(SSCOLPQS) != SSCOLPQS_EF)
  24. ;
  25. /* clear the complete notification flag */
  26. writel(SSCOLPQS_EF, SSCOLPQS);
  27. uniphier_cache_sync();
  28. }
  29. void v7_outer_cache_flush_all(void)
  30. {
  31. uniphier_cache_maint_all(SSCOQM_CM_WB_INV);
  32. }
  33. void v7_outer_cache_inval_all(void)
  34. {
  35. uniphier_cache_maint_all(SSCOQM_CM_INV);
  36. }
  37. static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation)
  38. {
  39. /* try until the command is successfully set */
  40. do {
  41. writel(SSCOQM_S_ADDRESS | SSCOQM_CE | operation, SSCOQM);
  42. writel(start, SSCOQAD);
  43. writel(size, SSCOQSZ);
  44. } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
  45. /* wait until the operation is completed */
  46. while (readl(SSCOLPQS) != SSCOLPQS_EF)
  47. ;
  48. /* clear the complete notification flag */
  49. writel(SSCOLPQS_EF, SSCOLPQS);
  50. }
  51. static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
  52. {
  53. u32 size;
  54. /*
  55. * If start address is not aligned to cache-line,
  56. * do cache operation for the first cache-line
  57. */
  58. start = start & ~(SSC_LINE_SIZE - 1);
  59. size = end - start;
  60. if (unlikely(size >= (u32)(-SSC_LINE_SIZE))) {
  61. /* this means cache operation for all range */
  62. uniphier_cache_maint_all(operation);
  63. return;
  64. }
  65. /*
  66. * If end address is not aligned to cache-line,
  67. * do cache operation for the last cache-line
  68. */
  69. size = ALIGN(size, SSC_LINE_SIZE);
  70. while (size) {
  71. u32 chunk_size = size > SSC_RANGE_OP_MAX_SIZE ?
  72. SSC_RANGE_OP_MAX_SIZE : size;
  73. __uniphier_cache_maint_range(start, chunk_size, operation);
  74. start += chunk_size;
  75. size -= chunk_size;
  76. }
  77. uniphier_cache_sync();
  78. }
  79. void v7_outer_cache_flush_range(u32 start, u32 end)
  80. {
  81. uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV);
  82. }
  83. void v7_outer_cache_inval_range(u32 start, u32 end)
  84. {
  85. if (start & (SSC_LINE_SIZE - 1)) {
  86. start &= ~(SSC_LINE_SIZE - 1);
  87. __uniphier_cache_maint_range(start, SSC_LINE_SIZE,
  88. SSCOQM_CM_WB_INV);
  89. start += SSC_LINE_SIZE;
  90. }
  91. if (start >= end) {
  92. uniphier_cache_sync();
  93. return;
  94. }
  95. if (end & (SSC_LINE_SIZE - 1)) {
  96. end &= ~(SSC_LINE_SIZE - 1);
  97. __uniphier_cache_maint_range(end, SSC_LINE_SIZE,
  98. SSCOQM_CM_WB_INV);
  99. }
  100. if (start >= end) {
  101. uniphier_cache_sync();
  102. return;
  103. }
  104. uniphier_cache_maint_range(start, end, SSCOQM_CM_INV);
  105. }
  106. void v7_outer_cache_enable(void)
  107. {
  108. u32 tmp;
  109. writel(U32_MAX, SSCLPDAWCR); /* activate all ways */
  110. tmp = readl(SSCC);
  111. tmp |= SSCC_ON;
  112. writel(tmp, SSCC);
  113. }
  114. #endif
  115. void v7_outer_cache_disable(void)
  116. {
  117. u32 tmp;
  118. tmp = readl(SSCC);
  119. tmp &= ~SSCC_ON;
  120. writel(tmp, SSCC);
  121. }
  122. void enable_caches(void)
  123. {
  124. dcache_enable();
  125. }