blob: 43981146585ef904532dcca904a03e570cb43c55 [file] [log] [blame]
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +09001/*
Masahiro Yamada663a23f2015-05-29 17:30:00 +09002 * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +09003 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7#include <common.h>
Masahiro Yamada663a23f2015-05-29 17:30:00 +09008#include <linux/io.h>
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +09009#include <asm/armv7.h>
Masahiro Yamadaefdf3402016-01-09 01:51:13 +090010
11#include "ssc-regs.h"
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +090012
13#ifdef CONFIG_UNIPHIER_L2CACHE_ON
Masahiro Yamadaa0150f82016-01-17 10:13:17 +090014static void uniphier_cache_sync(void)
15{
16 writel(SSCOPE_CM_SYNC, SSCOPE); /* drain internal buffers */
17 readl(SSCOPE); /* need a read back to confirm */
18}
19
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +090020static void uniphier_cache_maint_all(u32 operation)
21{
22 /* try until the command is successfully set */
23 do {
24 writel(SSCOQM_S_ALL | SSCOQM_CE | operation, SSCOQM);
25 } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
26
27 /* wait until the operation is completed */
28 while (readl(SSCOLPQS) != SSCOLPQS_EF)
29 ;
30
31 /* clear the complete notification flag */
32 writel(SSCOLPQS_EF, SSCOLPQS);
33
Masahiro Yamadaa0150f82016-01-17 10:13:17 +090034 uniphier_cache_sync();
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +090035}
36
37void v7_outer_cache_flush_all(void)
38{
39 uniphier_cache_maint_all(SSCOQM_CM_WB_INV);
40}
41
42void v7_outer_cache_inval_all(void)
43{
44 uniphier_cache_maint_all(SSCOQM_CM_INV);
45}
46
47static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation)
48{
49 /* try until the command is successfully set */
50 do {
51 writel(SSCOQM_S_ADDRESS | SSCOQM_CE | operation, SSCOQM);
52 writel(start, SSCOQAD);
53 writel(size, SSCOQSZ);
54
55 } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
56
57 /* wait until the operation is completed */
58 while (readl(SSCOLPQS) != SSCOLPQS_EF)
59 ;
60
61 /* clear the complete notification flag */
62 writel(SSCOLPQS_EF, SSCOLPQS);
63}
64
65static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
66{
67 u32 size;
68
69 /*
70 * If start address is not aligned to cache-line,
71 * do cache operation for the first cache-line
72 */
73 start = start & ~(SSC_LINE_SIZE - 1);
74
Masahiro Yamada81533fc2016-01-17 10:13:16 +090075 size = end - start;
76
77 if (unlikely(size >= (u32)(-SSC_LINE_SIZE))) {
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +090078 /* this means cache operation for all range */
79 uniphier_cache_maint_all(operation);
80 return;
81 }
82
83 /*
84 * If end address is not aligned to cache-line,
85 * do cache operation for the last cache-line
86 */
Masahiro Yamada81533fc2016-01-17 10:13:16 +090087 size = ALIGN(size, SSC_LINE_SIZE);
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +090088
89 while (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);
93
94 start += chunk_size;
95 size -= chunk_size;
96 }
97
Masahiro Yamadaa0150f82016-01-17 10:13:17 +090098 uniphier_cache_sync();
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +090099}
100
101void v7_outer_cache_flush_range(u32 start, u32 end)
102{
103 uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV);
104}
105
106void v7_outer_cache_inval_range(u32 start, u32 end)
107{
Masahiro Yamada4de74d52016-01-17 10:13:18 +0900108 if (start & (SSC_LINE_SIZE - 1)) {
109 start &= ~(SSC_LINE_SIZE - 1);
110 __uniphier_cache_maint_range(start, SSC_LINE_SIZE,
111 SSCOQM_CM_WB_INV);
112 start += SSC_LINE_SIZE;
113 }
114
115 if (start >= end) {
116 uniphier_cache_sync();
117 return;
118 }
119
120 if (end & (SSC_LINE_SIZE - 1)) {
121 end &= ~(SSC_LINE_SIZE - 1);
122 __uniphier_cache_maint_range(end, SSC_LINE_SIZE,
123 SSCOQM_CM_WB_INV);
124 }
125
126 if (start >= end) {
127 uniphier_cache_sync();
128 return;
129 }
130
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +0900131 uniphier_cache_maint_range(start, end, SSCOQM_CM_INV);
132}
133
134void v7_outer_cache_enable(void)
135{
136 u32 tmp;
Masahiro Yamadab12256c2016-01-17 10:13:19 +0900137
138 writel(U32_MAX, SSCLPDAWCR); /* activate all ways */
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +0900139 tmp = readl(SSCC);
140 tmp |= SSCC_ON;
141 writel(tmp, SSCC);
142}
143#endif
144
145void v7_outer_cache_disable(void)
146{
147 u32 tmp;
148 tmp = readl(SSCC);
149 tmp &= ~SSCC_ON;
150 writel(tmp, SSCC);
151}
152
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +0900153void enable_caches(void)
154{
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +0900155 dcache_enable();
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +0900156}