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. /* clear the complete notification flag */
  19. writel(SSCOLPQS_EF, SSCOLPQS);
  20. /* try until the command is successfully set */
  21. do {
  22. writel(SSCOQM_S_ALL | SSCOQM_CE | operation, SSCOQM);
  23. } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
  24. /* wait until the operation is completed */
  25. while (readl(SSCOLPQS) != SSCOLPQS_EF)
  26. ;
  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. /* clear the complete notification flag */
  40. writel(SSCOLPQS_EF, SSCOLPQS);
  41. /* try until the command is successfully set */
  42. do {
  43. writel(SSCOQM_S_ADDRESS | SSCOQM_CE | operation, SSCOQM);
  44. writel(start, SSCOQAD);
  45. writel(size, SSCOQSZ);
  46. } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
  47. /* wait until the operation is completed */
  48. while (readl(SSCOLPQS) != SSCOLPQS_EF)
  49. ;
  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. }