2 * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
4 * SPDX-License-Identifier: GPL-2.0+
13 #ifdef CONFIG_UNIPHIER_L2CACHE_ON
14 static void uniphier_cache_sync(void)
16 writel(SSCOPE_CM_SYNC, SSCOPE); /* drain internal buffers */
17 readl(SSCOPE); /* need a read back to confirm */
20 static void uniphier_cache_maint_all(u32 operation)
22 /* try until the command is successfully set */
24 writel(SSCOQM_S_ALL | SSCOQM_CE | operation, SSCOQM);
25 } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
27 /* wait until the operation is completed */
28 while (readl(SSCOLPQS) != SSCOLPQS_EF)
31 /* clear the complete notification flag */
32 writel(SSCOLPQS_EF, SSCOLPQS);
34 uniphier_cache_sync();
37 void v7_outer_cache_flush_all(void)
39 uniphier_cache_maint_all(SSCOQM_CM_WB_INV);
42 void v7_outer_cache_inval_all(void)
44 uniphier_cache_maint_all(SSCOQM_CM_INV);
47 static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation)
49 /* try until the command is successfully set */
51 writel(SSCOQM_S_ADDRESS | SSCOQM_CE | operation, SSCOQM);
52 writel(start, SSCOQAD);
53 writel(size, SSCOQSZ);
55 } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
57 /* wait until the operation is completed */
58 while (readl(SSCOLPQS) != SSCOLPQS_EF)
61 /* clear the complete notification flag */
62 writel(SSCOLPQS_EF, SSCOLPQS);
65 static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
70 * If start address is not aligned to cache-line,
71 * do cache operation for the first cache-line
73 start = start & ~(SSC_LINE_SIZE - 1);
77 if (unlikely(size >= (u32)(-SSC_LINE_SIZE))) {
78 /* this means cache operation for all range */
79 uniphier_cache_maint_all(operation);
84 * If end address is not aligned to cache-line,
85 * do cache operation for the last cache-line
87 size = ALIGN(size, SSC_LINE_SIZE);
90 u32 chunk_size = size > SSC_RANGE_OP_MAX_SIZE ?
91 SSC_RANGE_OP_MAX_SIZE : size;
92 __uniphier_cache_maint_range(start, chunk_size, operation);
98 uniphier_cache_sync();
101 void v7_outer_cache_flush_range(u32 start, u32 end)
103 uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV);
106 void v7_outer_cache_inval_range(u32 start, u32 end)
108 if (start & (SSC_LINE_SIZE - 1)) {
109 start &= ~(SSC_LINE_SIZE - 1);
110 __uniphier_cache_maint_range(start, SSC_LINE_SIZE,
112 start += SSC_LINE_SIZE;
116 uniphier_cache_sync();
120 if (end & (SSC_LINE_SIZE - 1)) {
121 end &= ~(SSC_LINE_SIZE - 1);
122 __uniphier_cache_maint_range(end, SSC_LINE_SIZE,
127 uniphier_cache_sync();
131 uniphier_cache_maint_range(start, end, SSCOQM_CM_INV);
134 void v7_outer_cache_enable(void)
138 writel(U32_MAX, SSCLPDAWCR); /* activate all ways */
145 void v7_outer_cache_disable(void)
153 void enable_caches(void)