diff mbox

[U-Boot] nds32: split common cache access from cpu into lib

Message ID 1342324924-3282-1-git-send-email-macpaul@gmail.com
State Superseded
Delegated to: Macpaul Lin
Headers show

Commit Message

Macpaul Lin July 15, 2012, 4:02 a.m. UTC
This commit does the following updates.
1. Split the common cache access from cpu.c into lib folder.
2. Rename the following cache api to adapt common.h
 - dcache_flush_rang -> flush_dcache_rang
 - icache_inval_range -> invalidate_icache_range
3. Add invalidate_dcache_range

Signed-off-by: Macpaul Lin <macpaul@gmail.com>
---
 arch/nds32/cpu/n1213/ag101/cpu.c | 112 ------------------------------
 arch/nds32/cpu/n1213/ag102/cpu.c | 112 ------------------------------
 arch/nds32/lib/Makefile          |   2 +-
 arch/nds32/lib/cache.c           | 145 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 146 insertions(+), 225 deletions(-)
 create mode 100644 arch/nds32/lib/cache.c

Comments

Marek Vasut July 15, 2012, 8:12 a.m. UTC | #1
Dear Macpaul Lin,

> This commit does the following updates.
> 1. Split the common cache access from cpu.c into lib folder.
> 2. Rename the following cache api to adapt common.h
>  - dcache_flush_rang -> flush_dcache_rang
>  - icache_inval_range -> invalidate_icache_range
> 3. Add invalidate_dcache_range

So basically this connects it to standard cache api?

[...]
> diff --git a/arch/nds32/lib/cache.c b/arch/nds32/lib/cache.c
[...]
> +static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
> +{
> +	if (cache == ICACHE)
> +		return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
> +					>> ICM_CFG_OFF_ISZ) - 1);


These crazy macros can be probably done easier and can share some code maybe? 
Maybe not though, I dunno, just a thought.

> +	else
> +		return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
> +					>> DCM_CFG_OFF_DSZ) - 1);
> +}
> +
> +void flush_dcache_range(unsigned long start, unsigned long end)
> +{
> +	unsigned long line_size;
> +
> +	line_size = CACHE_LINE_SIZE(DCACHE);
> +
> +	while (end > start) {
> +		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start));
> +		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));

You probably want to do those two calls in one asm volatile () block. And this 
too ... use "asm volatile()" and not "__asm__ volatile" or "asm __volatile__" 
and similar combinations of these, just a nit ;-)

> +		start += line_size;
> +	}
> +}
> +
> +void invalidate_icache_range(unsigned long start, unsigned long end)
> +{
> +	unsigned long line_size;
> +
> +	line_size = CACHE_LINE_SIZE(ICACHE);
> +	while (end > start) {
> +		__asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start));
> +		start += line_size;
> +	}
> +}
> +
> +void invalidate_dcache_range(unsigned long start, unsigned long end)
> +{
> +	unsigned long line_size;
> +
> +	line_size = CACHE_LINE_SIZE(DCACHE);
> +	while (end > start) {
> +		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));
> +		start += line_size;
> +	}
> +}
> +
> +void flush_cache(unsigned long addr, unsigned long size)
> +{
> +	flush_dcache_range(addr, addr + size);
> +	invalidate_icache_range(addr, addr + size);

You probably want to flush dcache in here and that's it.

> +}
> +
> +void icache_enable(void)
> +{
> +	__asm__ __volatile__ (

See my nit above for the rest ;-) But all in all it's good, we should be 
applying this around V2-V3 of this patch, for the -next release. Thanks for your 
patch!
Macpaul Lin July 16, 2012, 2:23 a.m. UTC | #2
Hi Marek,

2012/7/15 Marek Vasut <marex@denx.de>:
> Dear Macpaul Lin,
>
>> This commit does the following updates.
>> 1. Split the common cache access from cpu.c into lib folder.
>> 2. Rename the following cache api to adapt common.h
>>  - dcache_flush_rang -> flush_dcache_rang
>>  - icache_inval_range -> invalidate_icache_range
>> 3. Add invalidate_dcache_range
>
> So basically this connects it to standard cache api?

Yes! Basically this is compatible with all nds32 cpu family if they
have cache inside.
The cache is configurable by the customer if they used softcore FPGA.
This API could help them to figure out the hardware configuration in
software level.

> [...]
>> diff --git a/arch/nds32/lib/cache.c b/arch/nds32/lib/cache.c
> [...]
>> +static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
>> +{
>> +     if (cache == ICACHE)
>> +             return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
>> +                                     >> ICM_CFG_OFF_ISZ) - 1);
>
> These crazy macros can be probably done easier and can share some code maybe?
> Maybe not though, I dunno, just a thought.
>

The macro GET_ICM_CFG() is inside arch/nds32/include/cache.h
#define DEFINE_GET_SYS_REG(reg) \
        static inline unsigned long GET_##reg(void)             \

Since the assembly is really long, rewrite them into macros should be
easier to maintain and read.
I'll prefer not to modify this function to call CACHE_LINE_SIZE.

>> +void flush_dcache_range(unsigned long start, unsigned long end)
>> +     while (end > start) {
>> +             __asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start));
>> +             __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));
>
> You probably want to do those two calls in one asm volatile () block. And this
> too ... use "asm volatile()" and not "__asm__ volatile" or "asm __volatile__"
> and similar combinations of these, just a nit ;-)

Ok, it will be fixed. :)

>> +void flush_cache(unsigned long addr, unsigned long size)
>> +{
>> +     flush_dcache_range(addr, addr + size);
>> +     invalidate_icache_range(addr, addr + size);
>
> You probably want to flush dcache in here and that's it.
>
>> +}
>> +
>> +void icache_enable(void)
>> +{
>> +     __asm__ __volatile__ (
>
> See my nit above for the rest ;-) But all in all it's good, we should be
> applying this around V2-V3 of this patch, for the -next release. Thanks for your
> patch!

It looks like this fix cannot be checkin before this coming rc1 or rc2.
But I think it is okay for users to wait until the -next release. :)
Mike Frysinger July 19, 2012, 4:37 a.m. UTC | #3
On Sunday 15 July 2012 04:12:45 Marek Vasut wrote:
> Dear Macpaul Lin,
> > +void flush_cache(unsigned long addr, unsigned long size)
> > +{
> > +	flush_dcache_range(addr, addr + size);
> > +	invalidate_icache_range(addr, addr + size);
> 
> You probably want to flush dcache in here and that's it.

i don't think so ... i think that's what flush_dcache_range() is for.  and our 
common/cmd_*.c files assume that flush_cache() will invalidate icache (see the 
bootm/load funcs that write executable content into memory and then flush the 
regions).
-mike
Macpaul Lin July 19, 2012, 4:51 a.m. UTC | #4
Hi Mike

2012/7/19 Mike Frysinger <vapier@gentoo.org>

> On Sunday 15 July 2012 04:12:45 Marek Vasut wrote:
> > Dear Macpaul Lin,
> > > +void flush_cache(unsigned long addr, unsigned long size)
> > > +{
> > > +   flush_dcache_range(addr, addr + size);
> > > +   invalidate_icache_range(addr, addr + size);
> >
> > You probably want to flush dcache in here and that's it.
>
> i don't think so ... i think that's what flush_dcache_range() is for.  and
> our
> common/cmd_*.c files assume that flush_cache() will invalidate icache (see
> the
> bootm/load funcs that write executable content into memory and then flush
> the
> regions).
> -mike
>

Thanks for clarification.
The patch v2 I've submitted 2 days ago didn't add a dcache flush here. :-)
Marek Vasut July 19, 2012, 9:02 a.m. UTC | #5
Dear Mike Frysinger,

> On Sunday 15 July 2012 04:12:45 Marek Vasut wrote:
> > Dear Macpaul Lin,
> > 
> > > +void flush_cache(unsigned long addr, unsigned long size)
> > > +{
> > > +	flush_dcache_range(addr, addr + size);
> > > +	invalidate_icache_range(addr, addr + size);
> > 
> > You probably want to flush dcache in here and that's it.
> 
> i don't think so ... i think that's what flush_dcache_range() is for.  and
> our common/cmd_*.c files assume that flush_cache() will invalidate icache
> (see the bootm/load funcs that write executable content into memory and
> then flush the regions).

Than it's borked on arm926ejs too ... ?

Best regards,
Marek Vasut
Mike Frysinger July 19, 2012, 1:48 p.m. UTC | #6
On Thursday 19 July 2012 05:02:21 Marek Vasut wrote:
> Dear Mike Frysinger,
> > On Sunday 15 July 2012 04:12:45 Marek Vasut wrote:
> > > Dear Macpaul Lin,
> > > > +void flush_cache(unsigned long addr, unsigned long size)
> > > > +{
> > > > +	flush_dcache_range(addr, addr + size);
> > > > +	invalidate_icache_range(addr, addr + size);
> > > 
> > > You probably want to flush dcache in here and that's it.
> > 
> > i don't think so ... i think that's what flush_dcache_range() is for. 
> > and our common/cmd_*.c files assume that flush_cache() will invalidate
> > icache (see the bootm/load funcs that write executable content into
> > memory and then flush the regions).
> 
> Than it's borked on arm926ejs too ... ?

if it doesn't flush icache in the flush_cache() function, then i would say so

sounds like we should rip all this cache stuff out of common.h and into like 
cache.h so we can document the API expectations.  i think Wolfgang was against 
this before, but maybe that was just creating a header for one specific cache 
macro and not all cache stuff ?
-mike
Marek Vasut July 19, 2012, 2:02 p.m. UTC | #7
Dear Mike Frysinger,

> On Thursday 19 July 2012 05:02:21 Marek Vasut wrote:
> > Dear Mike Frysinger,
> > 
> > > On Sunday 15 July 2012 04:12:45 Marek Vasut wrote:
> > > > Dear Macpaul Lin,
> > > > 
> > > > > +void flush_cache(unsigned long addr, unsigned long size)
> > > > > +{
> > > > > +	flush_dcache_range(addr, addr + size);
> > > > > +	invalidate_icache_range(addr, addr + size);
> > > > 
> > > > You probably want to flush dcache in here and that's it.
> > > 
> > > i don't think so ... i think that's what flush_dcache_range() is for.
> > > and our common/cmd_*.c files assume that flush_cache() will invalidate
> > > icache (see the bootm/load funcs that write executable content into
> > > memory and then flush the regions).
> > 
> > Than it's borked on arm926ejs too ... ?
> 
> if it doesn't flush icache in the flush_cache() function, then i would say
> so
> 
> sounds like we should rip all this cache stuff out of common.h and into
> like cache.h so we can document the API expectations.  i think Wolfgang
> was against this before, but maybe that was just creating a header for one
> specific cache macro and not all cache stuff ?

Certainly this sounds good. We'd also be able to add some nice instrumentation 
while at that, to detect problematic cases with DEBUG enabled or so. The cache 
stuff is starting to get really crazy.

Best regards,
Marek Vasut
Macpaul Lin July 20, 2012, 8:24 a.m. UTC | #8
Hi Marek and Mike,

> sounds like we should rip all this cache stuff out of common.h and into
> > like cache.h so we can document the API expectations.  i think Wolfgang
> > was against this before, but maybe that was just creating a header for
> one
> > specific cache macro and not all cache stuff ?
>
> Certainly this sounds good. We'd also be able to add some nice
> instrumentation
> while at that, to detect problematic cases with DEBUG enabled or so. The
> cache
> stuff is starting to get really crazy.
>
> Best regards,
> Marek Vasut
>

Since this discussion hasn't been finished,
and we haven't decide the final action about the new policy about cache.h
and common.h.
I'd like to pick this patch v2 for the coming release for fixing build
error for board adp-ag102.
What do you think? :-)
Mike Frysinger July 20, 2012, 2:41 p.m. UTC | #9
On Friday 20 July 2012 04:24:55 Macpaul Lin wrote:
> Since this discussion hasn't been finished,
> and we haven't decide the final action about the new policy about cache.h
> and common.h.
> I'd like to pick this patch v2 for the coming release for fixing build
> error for board adp-ag102.
> What do you think? :-)

i don't think the topic of cleaning up common code impedes you merging your 
nds32 cache clean ups at all.  they're orthogonal issues.
-mike
diff mbox

Patch

diff --git a/arch/nds32/cpu/n1213/ag101/cpu.c b/arch/nds32/cpu/n1213/ag101/cpu.c
index c2636b1..a9991e7 100644
--- a/arch/nds32/cpu/n1213/ag101/cpu.c
+++ b/arch/nds32/cpu/n1213/ag101/cpu.c
@@ -82,115 +82,3 @@  int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	/*NOTREACHED*/
 }
-
-static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
-{
-	if (cache == ICACHE)
-		return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
-					>> ICM_CFG_OFF_ISZ) - 1);
-	else
-		return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
-					>> DCM_CFG_OFF_DSZ) - 1);
-}
-
-void dcache_flush_range(unsigned long start, unsigned long end)
-{
-	unsigned long line_size;
-
-	line_size = CACHE_LINE_SIZE(DCACHE);
-
-	while (end > start) {
-		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start));
-		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));
-		start += line_size;
-	}
-}
-
-void icache_inval_range(unsigned long start, unsigned long end)
-{
-	unsigned long line_size;
-
-	line_size = CACHE_LINE_SIZE(ICACHE);
-	while (end > start) {
-		__asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start));
-		start += line_size;
-	}
-}
-
-void flush_cache(unsigned long addr, unsigned long size)
-{
-	dcache_flush_range(addr, addr + size);
-	icache_inval_range(addr, addr + size);
-}
-
-void icache_enable(void)
-{
-	__asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"ori	$p0, $p0, 0x01\n\t"
-		"mtsr	$p0, $mr8\n\t"
-		"isb\n\t"
-	);
-}
-
-void icache_disable(void)
-{
-	__asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"li	$p1, ~0x01\n\t"
-		"and	$p0, $p0, $p1\n\t"
-		"mtsr	$p0, $mr8\n\t"
-		"isb\n\t"
-	);
-}
-
-int icache_status(void)
-{
-	int ret;
-
-	 __asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"andi	%0,  $p0, 0x01\n\t"
-		: "=r" (ret)
-		:
-		: "memory"
-	);
-
-	 return ret;
-}
-
-void dcache_enable(void)
-{
-	 __asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"ori	$p0, $p0, 0x02\n\t"
-		"mtsr	$p0, $mr8\n\t"
-		"isb\n\t"
-	);
-}
-
-void dcache_disable(void)
-{
-	 __asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"li	$p1, ~0x02\n\t"
-		"and	$p0, $p0, $p1\n\t"
-		"mtsr	$p0, $mr8\n\t"
-		"isb\n\t"
-	);
-}
-
-int dcache_status(void)
-{
-	int ret;
-
-	__asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"andi	%0, $p0, 0x02\n\t"
-		: "=r" (ret)
-		:
-		: "memory"
-	 );
-
-	 return ret;
-}
diff --git a/arch/nds32/cpu/n1213/ag102/cpu.c b/arch/nds32/cpu/n1213/ag102/cpu.c
index ed88b52..252b69d 100644
--- a/arch/nds32/cpu/n1213/ag102/cpu.c
+++ b/arch/nds32/cpu/n1213/ag102/cpu.c
@@ -81,115 +81,3 @@  int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	/*NOTREACHED*/
 }
-
-static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
-{
-	if (cache == ICACHE)
-		return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
-					>> ICM_CFG_OFF_ISZ) - 1);
-	else
-		return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
-					>> DCM_CFG_OFF_DSZ) - 1);
-}
-
-void dcache_flush_range(unsigned long start, unsigned long end)
-{
-	unsigned long line_size;
-
-	line_size = CACHE_LINE_SIZE(DCACHE);
-
-	while (end > start) {
-		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start));
-		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));
-		start += line_size;
-	}
-}
-
-void icache_inval_range(unsigned long start, unsigned long end)
-{
-	unsigned long line_size;
-
-	line_size = CACHE_LINE_SIZE(ICACHE);
-	while (end > start) {
-		__asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start));
-		start += line_size;
-	}
-}
-
-void flush_cache(unsigned long addr, unsigned long size)
-{
-	dcache_flush_range(addr, addr + size);
-	icache_inval_range(addr, addr + size);
-}
-
-void icache_enable(void)
-{
-	__asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"ori	$p0, $p0, 0x01\n\t"
-		"mtsr	$p0, $mr8\n\t"
-		"isb\n\t"
-	);
-}
-
-void icache_disable(void)
-{
-	__asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"li	$p1, ~0x01\n\t"
-		"and	$p0, $p0, $p1\n\t"
-		"mtsr	$p0, $mr8\n\t"
-		"isb\n\t"
-	);
-}
-
-int icache_status(void)
-{
-	int ret;
-
-	 __asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"andi	%0,  $p0, 0x01\n\t"
-		: "=r" (ret)
-		:
-		: "memory"
-	);
-
-	 return ret;
-}
-
-void dcache_enable(void)
-{
-	 __asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"ori	$p0, $p0, 0x02\n\t"
-		"mtsr	$p0, $mr8\n\t"
-		"isb\n\t"
-	);
-}
-
-void dcache_disable(void)
-{
-	 __asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"li	$p1, ~0x02\n\t"
-		"and	$p0, $p0, $p1\n\t"
-		"mtsr	$p0, $mr8\n\t"
-		"isb\n\t"
-	);
-}
-
-int dcache_status(void)
-{
-	int ret;
-
-	__asm__ __volatile__ (
-		"mfsr	$p0, $mr8\n\t"
-		"andi	%0, $p0, 0x02\n\t"
-		: "=r" (ret)
-		:
-		: "memory"
-	 );
-
-	 return ret;
-}
diff --git a/arch/nds32/lib/Makefile b/arch/nds32/lib/Makefile
index e5c31c3..581a2e7 100644
--- a/arch/nds32/lib/Makefile
+++ b/arch/nds32/lib/Makefile
@@ -29,7 +29,7 @@  include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(ARCH).o
 
-OBJS	:= board.o bootm.o interrupts.o
+OBJS	:= board.o bootm.o cache.o interrupts.o
 
 all:	$(LIB)
 
diff --git a/arch/nds32/lib/cache.c b/arch/nds32/lib/cache.c
new file mode 100644
index 0000000..08af1ef
--- /dev/null
+++ b/arch/nds32/lib/cache.c
@@ -0,0 +1,145 @@ 
+/*
+ * Copyright (C) 2012 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
+ * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
+ *
+ */
+
+#include <common.h>
+
+static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
+{
+	if (cache == ICACHE)
+		return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
+					>> ICM_CFG_OFF_ISZ) - 1);
+	else
+		return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
+					>> DCM_CFG_OFF_DSZ) - 1);
+}
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+
+	line_size = CACHE_LINE_SIZE(DCACHE);
+
+	while (end > start) {
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start));
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));
+		start += line_size;
+	}
+}
+
+void invalidate_icache_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+
+	line_size = CACHE_LINE_SIZE(ICACHE);
+	while (end > start) {
+		__asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start));
+		start += line_size;
+	}
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+
+	line_size = CACHE_LINE_SIZE(DCACHE);
+	while (end > start) {
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));
+		start += line_size;
+	}
+}
+
+void flush_cache(unsigned long addr, unsigned long size)
+{
+	flush_dcache_range(addr, addr + size);
+	invalidate_icache_range(addr, addr + size);
+}
+
+void icache_enable(void)
+{
+	__asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"ori	$p0, $p0, 0x01\n\t"
+		"mtsr	$p0, $mr8\n\t"
+		"isb\n\t"
+	);
+}
+
+void icache_disable(void)
+{
+	__asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"li	$p1, ~0x01\n\t"
+		"and	$p0, $p0, $p1\n\t"
+		"mtsr	$p0, $mr8\n\t"
+		"isb\n\t"
+	);
+}
+
+int icache_status(void)
+{
+	int ret;
+
+	 __asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"andi	%0,  $p0, 0x01\n\t"
+		: "=r" (ret)
+		:
+		: "memory"
+	);
+
+	 return ret;
+}
+
+void dcache_enable(void)
+{
+	 __asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"ori	$p0, $p0, 0x02\n\t"
+		"mtsr	$p0, $mr8\n\t"
+		"isb\n\t"
+	);
+}
+
+void dcache_disable(void)
+{
+	 __asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"li	$p1, ~0x02\n\t"
+		"and	$p0, $p0, $p1\n\t"
+		"mtsr	$p0, $mr8\n\t"
+		"isb\n\t"
+	);
+}
+
+int dcache_status(void)
+{
+	int ret;
+
+	__asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"andi	%0, $p0, 0x02\n\t"
+		: "=r" (ret)
+		:
+		: "memory"
+	 );
+
+	 return ret;
+}