summaryrefslogtreecommitdiff
path: root/arch/arc/lib
diff options
context:
space:
mode:
authorEugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>2018-03-21 15:59:01 +0300
committerAlexey Brodkin <abrodkin@synopsys.com>2018-03-21 17:06:54 +0300
commit95336738f1cf2d4fabfc9bfc4981fa14714efc30 (patch)
tree765031cfd5fec7bff551f623508e1f20aab0e45f /arch/arc/lib
parentc75eeb0bcbd5596f2b4e2b81eaa572675f019906 (diff)
downloadu-boot-95336738f1cf2d4fabfc9bfc4981fa14714efc30.tar.xz
ARC: Cache: Fix SLC operations when SLC is bypassed for data
If L1 D$ is disabled SLC is bypassed for data and all load/store requests are sent directly to main memory. If L1 I$ is disabled SLC is NOT bypassed for instructions and all instruction requests are fetched through SLC. Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Diffstat (limited to 'arch/arc/lib')
-rw-r--r--arch/arc/lib/cache.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c
index 7052895bb7..a5aae3d232 100644
--- a/arch/arc/lib/cache.c
+++ b/arch/arc/lib/cache.c
@@ -168,6 +168,15 @@ static inline bool slc_exists(void)
return false;
}
+static inline bool slc_data_bypass(void)
+{
+ /*
+ * If L1 data cache is disabled SL$ is bypassed and all load/store
+ * requests are sent directly to main memory.
+ */
+ return !dcache_enabled();
+}
+
static inline bool ioc_exists(void)
{
if (is_isa_arcv2()) {
@@ -412,7 +421,13 @@ void invalidate_icache_all(void)
{
__ic_entire_invalidate();
- if (is_isa_arcv2())
+ /*
+ * If SL$ is bypassed for data it is used only for instructions,
+ * so we need to invalidate it too.
+ * TODO: HS 3.0 supports SLC disable so we need to check slc
+ * enable/disable status here.
+ */
+ if (is_isa_arcv2() && slc_data_bypass())
__slc_entire_op(OP_INV);
}
@@ -520,14 +535,15 @@ void invalidate_dcache_range(unsigned long start, unsigned long end)
return;
/*
- * ARCv1 -> call __dc_line_op
- * ARCv2 && no IOC -> call __dc_line_op; call __slc_rgn_op
- * ARCv2 && IOC enabled -> nothing
+ * ARCv1 -> call __dc_line_op
+ * ARCv2 && L1 D$ disabled -> nothing
+ * ARCv2 && L1 D$ enabled && IOC enabled -> nothing
+ * ARCv2 && L1 D$ enabled && no IOC -> call __dc_line_op; call __slc_rgn_op
*/
if (!is_isa_arcv2() || !ioc_enabled())
__dc_line_op(start, end - start, OP_INV);
- if (is_isa_arcv2() && !ioc_enabled())
+ if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass())
__slc_rgn_op(start, end - start, OP_INV);
}
@@ -537,14 +553,15 @@ void flush_dcache_range(unsigned long start, unsigned long end)
return;
/*
- * ARCv1 -> call __dc_line_op
- * ARCv2 && no IOC -> call __dc_line_op; call __slc_rgn_op
- * ARCv2 && IOC enabled -> nothing
+ * ARCv1 -> call __dc_line_op
+ * ARCv2 && L1 D$ disabled -> nothing
+ * ARCv2 && L1 D$ enabled && IOC enabled -> nothing
+ * ARCv2 && L1 D$ enabled && no IOC -> call __dc_line_op; call __slc_rgn_op
*/
if (!is_isa_arcv2() || !ioc_enabled())
__dc_line_op(start, end - start, OP_FLUSH);
- if (is_isa_arcv2() && !ioc_enabled())
+ if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass())
__slc_rgn_op(start, end - start, OP_FLUSH);
}
@@ -563,7 +580,7 @@ void flush_n_invalidate_dcache_all(void)
{
__dc_entire_op(OP_FLUSH_N_INV);
- if (is_isa_arcv2())
+ if (is_isa_arcv2() && !slc_data_bypass())
__slc_entire_op(OP_FLUSH_N_INV);
}
@@ -571,6 +588,6 @@ void flush_dcache_all(void)
{
__dc_entire_op(OP_FLUSH);
- if (is_isa_arcv2())
+ if (is_isa_arcv2() && !slc_data_bypass())
__slc_entire_op(OP_FLUSH);
}