|
@@ -169,6 +169,16 @@ DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
|
|
#define CACHE_LINE_MASK (~(gd->arch.l1_line_sz - 1))
|
|
|
|
|
|
+/*
|
|
|
+ * We don't want to use '__always_inline' macro here as it can be redefined
|
|
|
+ * to simple 'inline' in some cases which breaks stuff. See [ NOTE 1 ] for more
|
|
|
+ * details about the reasons we need to use always_inline functions.
|
|
|
+ */
|
|
|
+#define inlined_cachefunc inline __attribute__((always_inline))
|
|
|
+
|
|
|
+static inlined_cachefunc void __ic_entire_invalidate(void);
|
|
|
+static inlined_cachefunc void __dc_entire_op(const int cacheop);
|
|
|
+
|
|
|
static inline bool pae_exists(void)
|
|
|
{
|
|
|
/* TODO: should we compare mmu version from BCR and from CONFIG? */
|
|
@@ -184,7 +194,7 @@ static inline bool pae_exists(void)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-static inline bool icache_exists(void)
|
|
|
+static inlined_cachefunc bool icache_exists(void)
|
|
|
{
|
|
|
union bcr_di_cache ibcr;
|
|
|
|
|
@@ -192,7 +202,7 @@ static inline bool icache_exists(void)
|
|
|
return !!ibcr.fields.ver;
|
|
|
}
|
|
|
|
|
|
-static inline bool icache_enabled(void)
|
|
|
+static inlined_cachefunc bool icache_enabled(void)
|
|
|
{
|
|
|
if (!icache_exists())
|
|
|
return false;
|
|
@@ -200,7 +210,7 @@ static inline bool icache_enabled(void)
|
|
|
return !(read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE);
|
|
|
}
|
|
|
|
|
|
-static inline bool dcache_exists(void)
|
|
|
+static inlined_cachefunc bool dcache_exists(void)
|
|
|
{
|
|
|
union bcr_di_cache dbcr;
|
|
|
|
|
@@ -208,7 +218,7 @@ static inline bool dcache_exists(void)
|
|
|
return !!dbcr.fields.ver;
|
|
|
}
|
|
|
|
|
|
-static inline bool dcache_enabled(void)
|
|
|
+static inlined_cachefunc bool dcache_enabled(void)
|
|
|
{
|
|
|
if (!dcache_exists())
|
|
|
return false;
|
|
@@ -216,7 +226,7 @@ static inline bool dcache_enabled(void)
|
|
|
return !(read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE);
|
|
|
}
|
|
|
|
|
|
-static inline bool slc_exists(void)
|
|
|
+static inlined_cachefunc bool slc_exists(void)
|
|
|
{
|
|
|
if (is_isa_arcv2()) {
|
|
|
union bcr_generic sbcr;
|
|
@@ -228,7 +238,7 @@ static inline bool slc_exists(void)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-static inline bool slc_data_bypass(void)
|
|
|
+static inlined_cachefunc bool slc_data_bypass(void)
|
|
|
{
|
|
|
/*
|
|
|
* If L1 data cache is disabled SL$ is bypassed and all load/store
|
|
@@ -261,7 +271,7 @@ static inline bool ioc_enabled(void)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-static void __slc_entire_op(const int op)
|
|
|
+static inlined_cachefunc void __slc_entire_op(const int op)
|
|
|
{
|
|
|
unsigned int ctrl;
|
|
|
|
|
@@ -469,13 +479,17 @@ void icache_enable(void)
|
|
|
|
|
|
void icache_disable(void)
|
|
|
{
|
|
|
- if (icache_exists())
|
|
|
- write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
|
|
|
- IC_CTRL_CACHE_DISABLE);
|
|
|
+ if (!icache_exists())
|
|
|
+ return;
|
|
|
+
|
|
|
+ __ic_entire_invalidate();
|
|
|
+
|
|
|
+ write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
|
|
|
+ IC_CTRL_CACHE_DISABLE);
|
|
|
}
|
|
|
|
|
|
/* IC supports only invalidation */
|
|
|
-static inline void __ic_entire_invalidate(void)
|
|
|
+static inlined_cachefunc void __ic_entire_invalidate(void)
|
|
|
{
|
|
|
if (!icache_enabled())
|
|
|
return;
|
|
@@ -525,6 +539,17 @@ void dcache_disable(void)
|
|
|
if (!dcache_exists())
|
|
|
return;
|
|
|
|
|
|
+ __dc_entire_op(OP_FLUSH_N_INV);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * As SLC will be bypassed for data after L1 D$ disable we need to
|
|
|
+ * flush it first before L1 D$ disable. Also we invalidate SLC to
|
|
|
+ * avoid any inconsistent data problems after enabling L1 D$ again with
|
|
|
+ * dcache_enable function.
|
|
|
+ */
|
|
|
+ if (is_isa_arcv2())
|
|
|
+ __slc_entire_op(OP_FLUSH_N_INV);
|
|
|
+
|
|
|
write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
|
|
|
DC_CTRL_CACHE_DISABLE);
|
|
|
}
|
|
@@ -553,7 +578,7 @@ static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void __before_dc_op(const int op)
|
|
|
+static inlined_cachefunc void __before_dc_op(const int op)
|
|
|
{
|
|
|
unsigned int ctrl;
|
|
|
|
|
@@ -568,13 +593,13 @@ static void __before_dc_op(const int op)
|
|
|
write_aux_reg(ARC_AUX_DC_CTRL, ctrl);
|
|
|
}
|
|
|
|
|
|
-static void __after_dc_op(const int op)
|
|
|
+static inlined_cachefunc void __after_dc_op(const int op)
|
|
|
{
|
|
|
if (op & OP_FLUSH) /* flush / flush-n-inv both wait */
|
|
|
while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS);
|
|
|
}
|
|
|
|
|
|
-static inline void __dc_entire_op(const int cacheop)
|
|
|
+static inlined_cachefunc void __dc_entire_op(const int cacheop)
|
|
|
{
|
|
|
int aux;
|
|
|
|