[PATCH 19/30] leon, l2cache: add GR740 L2-Cache driver

Daniel Hellstrom daniel at gaisler.com
Thu Apr 13 19:31:28 UTC 2017


From: Javier Jalle <javier.jalle at gaisler.com>

---
 c/src/lib/libbsp/sparc/Makefile.am          |    4 +
 c/src/lib/libbsp/sparc/leon2/Makefile.am    |    4 +
 c/src/lib/libbsp/sparc/leon2/preinstall.am  |    4 +
 c/src/lib/libbsp/sparc/leon3/Makefile.am    |    4 +
 c/src/lib/libbsp/sparc/leon3/preinstall.am  |    4 +
 c/src/lib/libbsp/sparc/shared/include/l2c.h |  201 +++
 c/src/lib/libbsp/sparc/shared/l2c/l2c.c     | 2109 +++++++++++++++++++++++++++
 cpukit/libdrvmgr/drvmgr_confdefs.h          |    4 +
 8 files changed, 2334 insertions(+)
 create mode 100644 c/src/lib/libbsp/sparc/shared/include/l2c.h
 create mode 100644 c/src/lib/libbsp/sparc/shared/l2c/l2c.c

diff --git a/c/src/lib/libbsp/sparc/Makefile.am b/c/src/lib/libbsp/sparc/Makefile.am
index 0691dd4..43e1d9e 100644
--- a/c/src/lib/libbsp/sparc/Makefile.am
+++ b/c/src/lib/libbsp/sparc/Makefile.am
@@ -95,6 +95,10 @@ EXTRA_DIST += shared/include/grcan.h
 # MEM
 EXTRA_DIST += shared/mem/mctrl.c
 
+# L2CACHE
+EXTRA_DIST += shared/l2c/l2c.c
+EXTRA_DIST += shared/include/l2c.h
+
 # MIL-STD-B1553 (Core1553BRM)
 EXTRA_DIST += shared/1553/b1553brm.c
 EXTRA_DIST += shared/1553/b1553rt.c
diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am
index 8e424d8..29a2ebd 100644
--- a/c/src/lib/libbsp/sparc/leon2/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am
@@ -188,6 +188,10 @@ libbsp_a_SOURCES += ../../sparc/shared/analog/gradcdac.c
 libbsp_a_SOURCES += ../../sparc/shared/mem/mctrl.c
 include_bsp_HEADERS += ../../sparc/shared/include/mctrl.h
 
+# l2cache
+libbsp_a_SOURCES += ../../sparc/shared/l2c/l2c.c
+include_bsp_HEADERS += ../../sparc/shared/include/l2c.h
+
 # timer
 libbsp_a_SOURCES += timer/timer.c
 
diff --git a/c/src/lib/libbsp/sparc/leon2/preinstall.am b/c/src/lib/libbsp/sparc/leon2/preinstall.am
index f249c3c..c37b77a 100644
--- a/c/src/lib/libbsp/sparc/leon2/preinstall.am
+++ b/c/src/lib/libbsp/sparc/leon2/preinstall.am
@@ -253,6 +253,10 @@ $(PROJECT_INCLUDE)/bsp/mctrl.h: ../../sparc/shared/include/mctrl.h $(PROJECT_INC
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/mctrl.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/mctrl.h
 
+$(PROJECT_INCLUDE)/bsp/l2c.h: ../../sparc/shared/include/l2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/l2c.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/l2c.h
+
 $(PROJECT_INCLUDE)/bsp/grtc.h: ../../sparc/shared/include/grtc.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/grtc.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/grtc.h
diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
index fe17bf0..84669b7 100644
--- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
@@ -205,6 +205,10 @@ libbsp_a_SOURCES += ../../sparc/shared/analog/gradcdac.c
 libbsp_a_SOURCES += ../../sparc/shared/mem/mctrl.c
 include_bsp_HEADERS += ../../sparc/shared/include/mctrl.h
 
+# l2cache
+libbsp_a_SOURCES += ../../sparc/shared/l2c/l2c.c
+include_bsp_HEADERS += ../../sparc/shared/include/l2c.h
+
 # timer
 libbsp_a_SOURCES += timer/timer.c
 libbsp_a_SOURCES += timer/watchdog.c
diff --git a/c/src/lib/libbsp/sparc/leon3/preinstall.am b/c/src/lib/libbsp/sparc/leon3/preinstall.am
index b517758..84ec208 100644
--- a/c/src/lib/libbsp/sparc/leon3/preinstall.am
+++ b/c/src/lib/libbsp/sparc/leon3/preinstall.am
@@ -281,6 +281,10 @@ $(PROJECT_INCLUDE)/bsp/mctrl.h: ../../sparc/shared/include/mctrl.h $(PROJECT_INC
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/mctrl.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/mctrl.h
 
+$(PROJECT_INCLUDE)/bsp/l2c.h: ../../sparc/shared/include/l2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/l2c.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/l2c.h
+
 $(PROJECT_INCLUDE)/bsp/watchdog.h: include/watchdog.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/watchdog.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/watchdog.h
diff --git a/c/src/lib/libbsp/sparc/shared/include/l2c.h b/c/src/lib/libbsp/sparc/shared/include/l2c.h
new file mode 100644
index 0000000..52473dd
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/include/l2c.h
@@ -0,0 +1,201 @@
+/*
+ *  GRLIB L2CACHE Driver
+ *
+ *  COPYRIGHT (c) 2017
+ *  Cobham Gaisler AB
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.org/license/LICENSE.
+ *
+ *  OVERVIEW
+ *  ========
+ *  This driver controls the L2CACHE device located 
+ *  at an on-chip AMBA.
+ */
+
+#ifndef __L2CACHE_H__
+#define __L2CACHE_H__
+
+#include <stdint.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void l2cache_register_drv(void);
+
+#define L2CACHE_ERR_OK 0
+#define L2CACHE_ERR_NOINIT -1
+#define L2CACHE_ERR_EINVAL -2
+#define L2CACHE_ERR_TOOMANY -3
+#define L2CACHE_ERR_ERROR -4
+
+/* L2C Flush options */
+#define L2CACHE_OPTIONS_FLUSH_WAIT (0x1 << 2)
+#define L2CACHE_OPTIONS_FLUSH_INVALIDATE (0x3 << 0)
+#define L2CACHE_OPTIONS_FLUSH_WRITEBACK (0x2 << 0)
+#define L2CACHE_OPTIONS_FLUSH_INV_WBACK (0x1 << 0)
+#define L2CACHE_OPTIONS_FLUSH_NONE (0 << 0)
+
+/* L2C Status */
+#define L2CACHE_STATUS_ENABLED 1
+#define L2CACHE_STATUS_SPLIT_ENABLED (0x1 << 1)
+#define L2CACHE_STATUS_EDAC_ENABLED (0x1 << 2)
+#define L2CACHE_STATUS_REPL (0x3 << L2CACHE_STATUS_REPL_BIT)
+#define L2CACHE_STATUS_REPL_BIT 3
+#define L2CACHE_STATUS_WRITETHROUGH (0x1 << 5)
+#define L2CACHE_STATUS_LOCK (0xf << L2CACHE_STATUS_LOCK_BIT)
+#define L2CACHE_STATUS_LOCK_BIT 6
+#define L2CACHE_STATUS_SCRUB_ENABLED (0x1 << 10)
+#define L2CACHE_STATUS_INT (0xf << L2CACHE_STATUS_INT_BIT)
+#define L2CACHE_STATUS_INT_BIT 11
+#define L2CACHE_STATUS_INT_BCKEND (0x1 << 11)
+#define L2CACHE_STATUS_INT_WPHIT (0x1 << 12)
+#define L2CACHE_STATUS_INT_UEE (0x1 << 13)
+#define L2CACHE_STATUS_INT_CEE (0x1 << 14)
+#define L2CACHE_STATUS_SCRUB_DELAY (0xffff << L2CACHE_STATUS_SCRUB_DELAY_BIT)
+#define L2CACHE_STATUS_SCRUB_DELAY_BIT 15
+#define L2CACHE_STATUS_SIGN_BIT 31
+
+/* status helper macros */
+#define L2CACHE_ENABLED(status) (status & L2CACHE_STATUS_ENABLED)
+#define L2CACHE_DISABLED(status) (!(status & L2CACHE_STATUS_ENABLED))
+#define L2CACHE_SPLIT_ENABLED(status) (status & L2CACHE_STATUS_SPLIT_ENABLED)
+#define L2CACHE_SPLIT_DISABLED(status) \
+	(!(status & L2CACHE_STATUS_SPLIT_ENABLED))
+#define L2CACHE_EDAC_ENABLED(status) (status & L2CACHE_STATUS_EDAC_ENABLED)
+#define L2CACHE_EDAC_DISABLED(status) (!(status & L2CACHE_STATUS_EDAC_ENABLED))
+#define L2CACHE_REPL(status) \
+	((status & L2CACHE_STATUS_REPL) >> L2CACHE_STATUS_REPL_BIT)
+#define L2CACHE_WRITETHROUGH(status) (status & L2CACHE_STATUS_WRITETHROUGH)
+#define L2CACHE_WRITEBACK(status) (!(status & L2CACHE_STATUS_WRITETHROUGH))
+#define L2CACHE_LOCKED_WAYS(status) \
+	((status & L2CACHE_STATUS_LOCK) >> L2CACHE_STATUS_LOCK_BIT)
+#define L2CACHE_SCRUB_ENABLED(status) (status & L2CACHE_STATUS_SCRUB_ENABLED)
+#define L2CACHE_SCRUB_DISABLED(status) \
+	(!(status & L2CACHE_STATUS_SCRUB_ENABLED))
+#define L2CACHE_SCRUB_DELAY(status) \
+	((status & L2CACHE_STATUS_SCRUB_DELAY) >> L2CACHE_STATUS_SCRUB_DELAY_BIT)
+#define L2CACHE_INT_ENABLED(status) (status & L2CACHE_STATUS_INT)
+#define L2CACHE_INT_DISABLED(status) (!(status & L2CACHE_STATUS_INT))
+extern int l2cache_status(void);
+
+/* L2C Setup */
+extern int l2cache_enable(int flush);
+extern int l2cache_disable(int flush);
+
+extern int l2cache_split_enable(void);
+extern int l2cache_split_disable(void);
+
+extern int l2cache_edac_enable(int flush);
+extern int l2cache_edac_disable(int flush);
+
+extern int l2cache_scrub_enable(int delay);
+extern int l2cache_scrub_disable(void);
+extern int l2cache_scrub_line(int way, int index);
+
+extern int l2cache_writethrough(int flush);
+extern int l2cache_writeback(int flush);
+
+#define L2CACHE_OPTIONS_REPL_INDEX_WAY_BIT (2)
+#define L2CACHE_OPTIONS_REPL_MASTERIDX_MOD (3 << 0)
+#define L2CACHE_OPTIONS_REPL_MASTERIDX_IDX (2 << 0)
+#define L2CACHE_OPTIONS_REPL_RANDOM (1 << 0)
+#define L2CACHE_OPTIONS_REPL_LRU (0 << 0)
+extern int l2cache_replacement(int options, int flush);
+
+/* L2C Flush */
+extern int l2cache_flush(int flush);
+extern int l2cache_flush_address(uint32_t addr, int size, int flush);
+extern int l2cache_flush_line(int way, int index, int flush);
+extern int l2cache_flush_way(int way, int flush);
+
+/* L2C Lock way */
+#define L2CACHE_OPTIONS_DIRTY (0x1 << 2)
+#define L2CACHE_OPTIONS_VALID (0x1 << 1)
+#define L2CACHE_OPTIONS_FETCH (0x1 << 0)
+#define L2CACHE_OPTIONS_DISABLE 2
+#define L2CACHE_OPTIONS_ENABLE 1
+#define L2CACHE_OPTIONS_NONE 0
+extern int l2cache_lock_way(uint32_t tag, int options, int flush, int enable);
+extern int l2cache_unlock(void);
+
+/* L2C Fill a way */
+extern int l2cache_fill_way(int way, uint32_t tag, int options, int flush);
+
+/* L2C MTRR */
+#define L2CACHE_OPTIONS_MTRR_ACCESS_WRITETHROUGH (0x1 << 2)
+#define L2CACHE_OPTIONS_MTRR_ACCESS_UNCACHED (0x0 << 2)
+#define L2CACHE_OPTIONS_MTRR_WRITEPROT_ENABLE (0x1 << 1)
+#define L2CACHE_OPTIONS_MTRR_WRITEPROT_DISABLE (0x0 << 1)
+extern int l2cache_mtrr_enable(int id, uint32_t addr, uint32_t mask, 
+		int options, int flush);
+extern int l2cache_mtrr_disable(int id);
+
+/* L2C Debug print */
+extern int l2cache_print(void);
+
+/* L2C Interrupts */
+/* Function Interrupt-Code ISR callback prototype.
+ * arg	   - Custom arg provided by user
+ * addr    - Cacheline addr that generated the error
+ * status  - Error status register of the L2CACHE core
+ */
+typedef void (*l2cache_isr_t)(void *arg, uint32_t addr, uint32_t status);
+#define L2CACHE_INTERRUPT_ALL (0xf << 0)
+#define L2CACHE_INTERRUPT_BACKENDERROR (0x1 << 3)
+#define L2CACHE_INTERRUPT_WPROTHIT (0x1 << 2)
+#define L2CACHE_INTERRUPT_UNCORRERROR (0x1 << 1)
+#define L2CACHE_INTERRUPT_CORRERROR (0x1 << 0)
+extern int l2cache_isr_register( l2cache_isr_t isr, void * arg, int options);
+extern int l2cache_isr_unregister(void);
+extern int l2cache_interrupt_mask(int options);
+extern int l2cache_interrupt_unmask(int options);
+
+/* L2C error interface */
+#define L2CACHE_STATUS_MULTIPLEERRORS 2
+#define L2CACHE_STATUS_NEWERROR 1
+#define L2CACHE_STATUS_NOERROR 0
+extern int l2cache_error_status(uint32_t * addr, uint32_t * status);
+
+/*#define TEST_L2CACHE*/
+#ifdef TEST_L2CACHE
+/* Used for internal testing */
+/*
+ * L2CACHE Tag private data struture
+ */
+struct l2cache_tag {
+	uint32_t tag;
+	int valid;
+	int dirty;
+	int lru;
+};
+
+/*
+ * L2CACHE Line private data struture
+ */
+struct l2cache_dataline {
+	uint32_t data[16];
+	int words;
+};
+extern int l2cache_get_index( uint32_t addr);
+extern uint32_t l2cache_get_tag( uint32_t addr);
+
+extern int l2cache_diag_tag( int way, int index, struct l2cache_tag * tag);
+extern int l2cache_diag_line( int way, int index, 
+		struct l2cache_dataline * dataline);
+
+#define L2CACHE_HIT 1
+#define L2CACHE_MISS 0
+extern int l2cache_lookup(uint32_t addr, int * way);
+
+extern int l2cache_error_inject_address( uint32_t addr, uint32_t mask);
+#endif /* TEST_L2CACHE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __L2CACHE_H__ */
diff --git a/c/src/lib/libbsp/sparc/shared/l2c/l2c.c b/c/src/lib/libbsp/sparc/shared/l2c/l2c.c
new file mode 100644
index 0000000..0388a13
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/l2c/l2c.c
@@ -0,0 +1,2109 @@
+/*
+ *  GRLIB L2CACHE Driver
+ *
+ *  COPYRIGHT (c) 2017
+ *  Cobham Gaisler AB
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.org/license/LICENSE.
+ */
+
+#include <stdlib.h>
+#include <drvmgr/drvmgr.h>
+#include <drvmgr/ambapp_bus.h>
+#include <ambapp.h>
+#include <rtems.h>
+#include <rtems/bspIo.h>
+#include <grlib.h>
+#include <bsp.h>
+#include <bsp/l2c.h>
+
+/*#define STATIC*/
+#define STATIC static
+
+/*#define INLINE*/
+#define INLINE inline
+
+#define UNUSED __attribute__((unused))
+
+/*#define DEBUG 1*/
+
+#ifdef DEBUG
+#define DBG(x...) printf(x)
+#else
+#define DBG(x...) 
+#endif
+
+/*
+ * L2CACHE CTRL register fields 
+ */
+#define L2C_CTRL_EN (0x1 << L2C_CTRL_EN_BIT)
+#define L2C_CTRL_EDAC (0x1 << L2C_CTRL_EDAC_BIT)
+#define L2C_CTRL_REPL (0x3 << L2C_CTRL_REPL_BIT)
+#define L2C_CTRL_IWAY (0xf << L2C_CTRL_IWAY_BIT)
+#define L2C_CTRL_LOCK (0xf << L2C_CTRL_LOCK_BIT)
+#define L2C_CTRL_HPRHB (0x1 << L2C_CTRL_HPRHB_BIT)
+#define L2C_CTRL_HPB (0x1 << L2C_CTRL_HPB_BIT)
+#define L2C_CTRL_UC (0x1 << L2C_CTRL_UC_BIT)
+#define L2C_CTRL_HC (0x1 << L2C_CTRL_HC_BIT)
+#define L2C_CTRL_WP (0x1 << L2C_CTRL_WP_BIT)
+#define L2C_CTRL_HP (0x1 << L2C_CTRL_HP_BIT)
+
+#define L2C_CTRL_EN_BIT 31
+#define L2C_CTRL_EDAC_BIT 30
+#define L2C_CTRL_REPL_BIT 28
+#define L2C_CTRL_IWAY_BIT 12
+#define L2C_CTRL_LOCK_BIT 8
+#define L2C_CTRL_HPRHB_BIT 5
+#define L2C_CTRL_HPB_BIT 4
+#define L2C_CTRL_UC_BIT 3
+#define L2C_CTRL_HC_BIT 2
+#define L2C_CTRL_WP_BIT 1
+#define L2C_CTRL_HP_BIT 0
+
+/*
+ * L2CACHE STATUS register fields 
+ */
+#define L2C_STAT_LS (0x1 << L2C_STAT_LS_BIT)
+#define L2C_STAT_AT (0x1 << L2C_STAT_AT_BIT)
+#define L2C_STAT_MP (0x1 << L2C_STAT_MP_BIT)
+#define L2C_STAT_MTRR (0x3f << L2C_STAT_MTRR_BIT)
+#define L2C_STAT_BBUSW (0x7 << L2C_STAT_BBUSW_BIT)
+#define L2C_STAT_WAYSIZE (0x7ff << L2C_STAT_WAYSIZE_BIT)
+#define L2C_STAT_WAY (0x3 << L2C_STAT_WAY_BIT)
+
+#define L2C_STAT_LS_BIT 24
+#define L2C_STAT_AT_BIT 23
+#define L2C_STAT_MP_BIT 22
+#define L2C_STAT_MTRR_BIT 16
+#define L2C_STAT_BBUSW_BIT 13
+#define L2C_STAT_WAYSIZE_BIT 2
+#define L2C_STAT_WAY_BIT 0
+
+/*
+ * L2CACHE MTRR register fields 
+ */
+#define L2C_MTRR_ADDR (0x3fff << L2C_MTRR_ADDR_BIT)
+#define L2C_MTRR_ACC (0x3 << L2C_MTRR_ACC_BIT)
+#define L2C_MTRR_MASK (0x3fff << L2C_MTRR_MASK_BIT)
+#define L2C_MTRR_WP (0x1 << L2C_MTRR_WP_BIT)
+#define L2C_MTRR_AC (0x1 << L2C_MTRR_AC_BIT)
+
+#define L2C_MTRR_ADDR_BIT 18
+#define L2C_MTRR_ACC_BIT 16
+#define L2C_MTRR_MASK_BIT 2
+#define L2C_MTRR_WP_BIT 1
+#define L2C_MTRR_AC_BIT 0
+
+#define L2C_MTRR_UNCACHED 0
+#define L2C_MTRR_WRITETHROUGH (0x1 << L2C_MTRR_ACC_BIT)
+#define L2C_MTRR_WRITEPROT_ENABLE L2C_MTRR_WP
+#define L2C_MTRR_WRITEPROT_DISABLE 0
+#define L2C_MTRR_ACCESSCONTROL_ENABLE L2C_MTRR_AC
+#define L2C_MTRR_ACCESSCONTROL_DISABLE 0
+
+#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val))
+#define REG_READ(addr) (*(volatile unsigned int *)(addr))
+
+/*
+ * L2CACHE FLUSHMEM register fields 
+ */
+#define L2C_FLUSH_ADDR (0x7ffffff << L2C_FLUSH_ADDR_BIT)
+#define L2C_FLUSH_DI (0x1 << L2C_FLUSH_DI_BIT)
+#define L2C_FLUSH_FMODE (0x7 << L2C_FLUSH_FMODE_BIT)
+
+#define L2C_FLUSH_ADDR_BIT 5
+#define L2C_FLUSH_DI_BIT 3
+#define L2C_FLUSH_FMODE_BIT 0
+
+#define L2C_FLUSH_FMODE_INV_ONE (0x1 << L2C_FLUSH_FMODE_BIT)
+#define L2C_FLUSH_FMODE_WB_ONE (0x2 << L2C_FLUSH_FMODE_BIT)
+#define L2C_FLUSH_FMODE_INV_WB_ONE (0x3 << L2C_FLUSH_FMODE_BIT)
+#define L2C_FLUSH_FMODE_INV_ALL (0x5 << L2C_FLUSH_FMODE_BIT)
+#define L2C_FLUSH_FMODE_WB_ALL (0x6 << L2C_FLUSH_FMODE_BIT)
+#define L2C_FLUSH_FMODE_INV_WB_ALL (0x7 << L2C_FLUSH_FMODE_BIT)
+
+/*
+ * L2CACHE FLUSSETINDEX register fields 
+ */
+#define L2C_FLUSHSI_INDEX (0xffff << L2C_FLUSHSI_INDEX_BIT)
+#define L2C_FLUSHSI_TAG (0x3fffff << L2C_FLUSHSI_TAG_BIT)
+#define L2C_FLUSHSI_FL (0x1 << L2C_FLUSHSI_FL_BIT)
+#define L2C_FLUSHSI_VB (0x1 << L2C_FLUSHSI_VB_BIT)
+#define L2C_FLUSHSI_DB (0x1 << L2C_FLUSHSI_DB_BIT)
+#define L2C_FLUSHSI_WAY (0x3 << L2C_FLUSHSI_WAY_BIT)
+#define L2C_FLUSHSI_DI (0x1 << L2C_FLUSHSI_DI_BIT)
+#define L2C_FLUSHSI_WF (0x1 << L2C_FLUSHSI_WF_BIT)
+#define L2C_FLUSHSI_FMODE (0x3 << L2C_FLUSHSI_FMODE_BIT)
+
+#define L2C_FLUSHSI_INDEX_BIT 16
+#define L2C_FLUSHSI_TAG_BIT 10
+#define L2C_FLUSHSI_FL_BIT 9
+#define L2C_FLUSHSI_VB_BIT 8
+#define L2C_FLUSHSI_DB_BIT 7
+#define L2C_FLUSHSI_WAY_BIT 4
+#define L2C_FLUSHSI_DI_BIT 3
+#define L2C_FLUSHSI_WF_BIT 2
+#define L2C_FLUSHSI_FMODE_BIT 0
+
+#define L2C_FLUSHSI_FMODE_SET_INV_ONE (0x1 << L2C_FLUSHSI_FMODE_BIT)
+#define L2C_FLUSHSI_FMODE_SET_WB_ONE (0x2 << L2C_FLUSHSI_FMODE_BIT)
+#define L2C_FLUSHSI_FMODE_SET_INV_WB_ONE (0x3 << L2C_FLUSHSI_FMODE_BIT)
+#define L2C_FLUSHSI_FMODE_WAY_UPDATE (0x1 << L2C_FLUSHSI_FMODE_BIT)
+#define L2C_FLUSHSI_FMODE_WAY_WB (0x2 << L2C_FLUSHSI_FMODE_BIT)
+#define L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL (0x3 << L2C_FLUSHSI_FMODE_BIT)
+
+/*
+ * L2CACHE ERROR register fields 
+ */
+#define L2C_ERROR_AHBM (0xf << L2C_ERROR_AHBM_BIT)
+#define L2C_ERROR_SCRUB (0x1 << L2C_ERROR_SCRUB_BIT)
+#define L2C_ERROR_TYPE (0x7 << L2C_ERROR_TYPE_BIT)
+#define L2C_ERROR_TAG (0x1 << L2C_ERROR_TAG_BIT)
+#define L2C_ERROR_COR (0x1 << L2C_ERROR_COR_BIT)
+#define L2C_ERROR_MULTI (0x1 << L2C_ERROR_MULTI_BIT)
+#define L2C_ERROR_VALID (0x1 << L2C_ERROR_VALID_BIT)
+#define L2C_ERROR_DISERESP (0x1 << L2C_ERROR_DISERESP_BIT)
+#define L2C_ERROR_CEC (0x7 << L2C_ERROR_CEC_BIT)
+#define L2C_ERROR_IRQP (0xf << L2C_ERROR_IRQP_BIT)
+#define L2C_ERROR_IRQM (0xf << L2C_ERROR_IRQM_BIT)
+#define L2C_ERROR_IRQM_BCKEND (0x1 << L2C_ERROR_IRQM_BCKEND_BIT)
+#define L2C_ERROR_IRQM_WPROT (0x1 << L2C_ERROR_IRQM_WPROT_BIT)
+#define L2C_ERROR_IRQM_UNCORR (0x1 << L2C_ERROR_IRQM_UNCORR_BIT)
+#define L2C_ERROR_IRQM_CORR (0x1 << L2C_ERROR_IRQM_CORR_BIT)
+#define L2C_ERROR_SCB (0x3 << L2C_ERROR_SCB_BIT)
+#define L2C_ERROR_STCB (0x3 << L2C_ERROR_STCB_BIT)
+#define L2C_ERROR_XCB (0x1 << L2C_ERROR_XCB_BIT)
+#define L2C_ERROR_RCB (0x1 << L2C_ERROR_RCB_BIT)
+#define L2C_ERROR_COMP (0x1 << L2C_ERROR_COMP_BIT)
+#define L2C_ERROR_RST (0x1 << L2C_ERROR_RST_BIT)
+
+#define L2C_ERROR_AHBM_BIT 28
+#define L2C_ERROR_SCRUB_BIT 27
+#define L2C_ERROR_TYPE_BIT 24
+#define L2C_ERROR_TAG_BIT 23
+#define L2C_ERROR_COR_BIT 22
+#define L2C_ERROR_MULTI_BIT 21
+#define L2C_ERROR_VALID_BIT 20
+#define L2C_ERROR_DISERESP_BIT 19
+#define L2C_ERROR_CEC_BIT 16
+#define L2C_ERROR_IRQP_BIT 12
+#define L2C_ERROR_IRQM_BCKEND_BIT 11
+#define L2C_ERROR_IRQM_WPROT_BIT 10
+#define L2C_ERROR_IRQM_UNCORR_BIT 9
+#define L2C_ERROR_IRQM_CORR_BIT 8
+#define L2C_ERROR_IRQM_BIT 8
+#define L2C_ERROR_SCB_BIT 6
+#define L2C_ERROR_STCB_BIT 4
+#define L2C_ERROR_XCB_BIT 3
+#define L2C_ERROR_RCB_BIT 2
+#define L2C_ERROR_COMP_BIT 1
+#define L2C_ERROR_RST_BIT 0
+
+/*
+ * L2CACHE DATA CHECK BITS register fields 
+ */
+#define L2C_DCB_CB (0xfffffff << L2C_DCB_CB_BIT)
+
+#define L2C_DCB_CB_BIT 0 
+
+/*
+ * L2CACHE SCRUB register fields 
+ */
+#define L2C_SCRUB_INDEX (0xffff << L2C_SCRUB_INDEX_BIT)
+#define L2C_SCRUB_WAY (0x3 << L2C_SCRUB_WAY_BIT)
+#define L2C_SCRUB_PEN (0x1 << L2C_SCRUB_PEN_BIT)
+#define L2C_SCRUB_EN (0x1 << L2C_SCRUB_EN_BIT)
+
+#define L2C_SCRUB_INDEX_BIT 16 
+#define L2C_SCRUB_WAY_BIT 2
+#define L2C_SCRUB_PEN_BIT 1
+#define L2C_SCRUB_EN_BIT 0
+
+/*
+ * L2CACHE SCRUBDELAY register fields 
+ */
+#define L2C_SCRUB_DEL (0xffff << L2C_SCRUB_DEL_BIT)
+
+#define L2C_SCRUB_DEL_BIT 0 
+
+/*
+ * L2CACHE ERROR INJECT register fields 
+ */
+#define L2C_ERRINJ_ADDR (0x3fffffff << L2C_ERRINJ_ADDR_BIT)
+#define L2C_ERRINJ_EN (0x1 << L2C_ERRINJ_EN_BIT)
+
+#define L2C_ERRINJ_ADDR_BIT 2
+#define L2C_ERRINJ_EN_BIT 0
+
+/*
+ * L2CACHE ACCESS CONTROL register fields 
+ */
+#define L2C_ACCCTRL_SPLITQ (0x1 << L2C_ACCCTRL_SPLITQ_BIT)
+#define L2C_ACCCTRL_NHM (0x1 << L2C_ACCCTRL_NHM_BIT)
+#define L2C_ACCCTRL_BERR (0x1 << L2C_ACCCTRL_BERR_BIT)
+#define L2C_ACCCTRL_OAPM (0x1 << L2C_ACCCTRL_OAPM_BIT)
+#define L2C_ACCCTRL_FLINE (0x1 << L2C_ACCCTRL_FLINE_BIT)
+#define L2C_ACCCTRL_DBPF (0x1 << L2C_ACCCTRL_DBPF_BIT)
+#define L2C_ACCCTRL_128WF (0x1 << L2C_ACCCTRL_128WF_BIT)
+#define L2C_ACCCTRL_DBPWS (0x1 << L2C_ACCCTRL_DBPWS_BIT)
+#define L2C_ACCCTRL_SPLIT (0x1 << L2C_ACCCTRL_SPLIT_BIT)
+
+#define L2C_ACCCTRL_SPLITQ_BIT 10
+#define L2C_ACCCTRL_NHM_BIT 9
+#define L2C_ACCCTRL_BERR_BIT 8
+#define L2C_ACCCTRL_OAPM_BIT 7
+#define L2C_ACCCTRL_FLINE_BIT 6
+#define L2C_ACCCTRL_DBPF_BIT 5
+#define L2C_ACCCTRL_128WF_BIT 4
+#define L2C_ACCCTRL_DBPWS_BIT 2
+#define L2C_ACCCTRL_SPLIT_BIT 1
+
+#ifdef TEST_L2CACHE
+/*
+ * L2CACHE TAG fields 
+ */
+#define L2C_TAG_TAG (0xfffffc << L2C_TAG_TAG_BIT)
+#define L2C_TAG_VALID (0x3 << L2C_TAG_VALID_BIT)
+#define L2C_TAG_DIRTY (0x3 << L2C_TAG_DIRTY_BIT)
+#define L2C_TAG_LRU (0x3 << L2C_TAG_LRU_BIT)
+
+#define L2C_TAG_TAG_BIT 10
+#define L2C_TAG_VALID_BIT 8
+#define L2C_TAG_DIRTY_BIT 6
+#define L2C_TAG_LRU_BIT 0
+
+#endif /* TEST_L2CACHE */
+
+#define DEVNAME_LEN 9
+/*
+ * L2CACHE Driver private data struture
+ */
+struct l2cache_priv {
+	struct drvmgr_dev	*dev;
+	char devname[DEVNAME_LEN];
+
+	/* L2CACHE control registers */
+	struct l2c_regs	*regs;
+
+	/* L2CACHE status */
+	int ways;
+	int waysize;
+	int linesize;
+	int index;
+	int mtrr;
+	int ft_support;
+	int split_support;
+
+	/* User defined ISR */
+	l2cache_isr_t isr;
+	void *isr_arg;
+};
+
+/*
+ * L2CACHE internal prototypes 
+ */
+/* -Register access functions */
+STATIC INLINE int l2cache_reg_ctrl_enable(void);
+STATIC INLINE int l2cache_reg_ctrl_disable(void);
+STATIC INLINE int l2cache_reg_ctrl_locked_set(int locked);
+STATIC INLINE int l2cache_reg_ctrl_edac_set(int edac);
+STATIC INLINE int l2cache_reg_ctrl_repl(int policy);
+STATIC INLINE int l2cache_reg_ctrl_iway(int way);
+STATIC INLINE int l2cache_reg_ctrl_writep(int policy);
+STATIC INLINE unsigned int l2cache_reg_ctrl(void);
+STATIC INLINE unsigned int l2cache_reg_status(void);
+STATIC INLINE int l2cache_reg_mtrr_set(int index, unsigned int addr, 
+		unsigned int mask, int options);
+UNUSED STATIC INLINE unsigned int l2cache_reg_mtrr_get(int index);
+STATIC INLINE int l2cache_reg_flushmem(unsigned int addr, int options);
+STATIC INLINE int l2cache_reg_flushline(int way, int index, int options);
+STATIC INLINE int l2cache_reg_flushway(unsigned int tag, int way, int options);
+STATIC INLINE unsigned int l2cache_reg_error(void);
+STATIC INLINE int l2cache_reg_error_reset(void);
+STATIC INLINE int l2cache_reg_error_irqmask(int mask);
+STATIC INLINE unsigned int l2cache_reg_error_addr(void);
+STATIC INLINE unsigned int l2cache_reg_scrub(void);
+STATIC INLINE int l2cache_reg_scrub_enable(int delay);
+STATIC INLINE int l2cache_reg_scrub_disable(void);
+STATIC INLINE unsigned int l2cache_reg_scrub_delay(void);
+STATIC INLINE int l2cache_reg_scrub_line(int way, int index);
+STATIC INLINE unsigned int l2cache_reg_accctrl(void);
+STATIC INLINE int l2cache_reg_accctrl_split_disable(void);
+STATIC INLINE int l2cache_reg_accctrl_split_enable(void);
+#ifdef TEST_L2CACHE
+STATIC INLINE int l2cache_reg_error_dcb(unsigned int cb);
+STATIC INLINE int l2cache_reg_error_inject(unsigned int addr);
+STATIC INLINE unsigned int l2cache_reg_diagtag(int way, int index);
+STATIC INLINE unsigned int l2cache_reg_diagdata(int way, int index, int word);
+STATIC unsigned int log2int(unsigned int v);
+#endif /* TEST_L2CACHE */
+
+/* -Control functions */
+STATIC int l2cache_ctrl_status(void);
+STATIC void l2cache_flushwait(void);
+
+/* -Init function */
+STATIC int l2cache_init(struct l2cache_priv *priv);
+
+/* -Init function called by drvmgr */
+int l2cache_init1(struct drvmgr_dev *dev);
+
+/* -IRQ handler */
+void l2cache_isr(void *arg);
+
+/*
+ * L2CACHE static members 
+ */
+static struct l2cache_priv *l2cachepriv = NULL;
+#ifdef DEBUG
+static char * repl_names[4] = {"LRU","Random","Master-Idx-1","Master-IDx-2"};
+#endif
+
+/* L2CACHE DRIVER */
+
+struct drvmgr_drv_ops l2cache_ops = 
+{
+	.init = {l2cache_init1, NULL, NULL, NULL},
+	.remove = NULL,
+	.info = NULL
+};
+
+struct amba_dev_id l2cache_ids[] = 
+{
+	{VENDOR_GAISLER, GAISLER_L2CACHE},
+	{0, 0}		/* Mark end of table */
+};
+
+struct amba_drv_info l2cache_info =
+{
+	{
+		DRVMGR_OBJ_DRV,					/* Driver */
+		NULL,				/* Next driver */
+		NULL,				/* Device list */
+		DRIVER_AMBAPP_GAISLER_L2CACHE_ID,/* Driver ID */
+		"L2CACHE_DRV",			/* Driver Name */
+		DRVMGR_BUS_TYPE_AMBAPP,		/* Bus Type */
+		&l2cache_ops,
+		NULL,				/* Funcs */
+		0,				/* No devices yet */
+		sizeof(struct l2cache_priv),	/* Make drvmgr alloc private */
+	},
+	&l2cache_ids[0]
+};
+
+void l2cache_register_drv(void)
+{
+	DBG("Registering L2CACHE driver\n");
+	drvmgr_drv_register(&l2cache_info.general);
+}
+
+/* Initializes the L2CACHE core and driver
+ *
+ * Return values
+ *	0			  Successful initalization
+ */
+STATIC int l2cache_init(struct l2cache_priv *priv)
+{
+	struct ambapp_ahb_info *ahb;
+	struct amba_dev_info *ainfo = priv->dev->businfo;
+
+	/* Find L2CACHE core from Plug&Play information */
+	ahb = ainfo->info.ahb_slv;
+
+	/* Found L2CACHE core, init private structure */
+	priv->regs = (struct l2c_regs *)ahb->start[1];
+
+	/* Initialize L2CACHE status */
+	unsigned int status = l2cache_reg_status();
+	priv->ways = (status & L2C_STAT_WAY) + 1;
+	priv->waysize = 
+		((status & L2C_STAT_WAYSIZE) >> L2C_STAT_WAYSIZE_BIT) * 1024;
+	priv->linesize = ((status & L2C_STAT_LS)? 64 : 32);
+	priv->index = ((priv->waysize)/(priv->linesize));
+	priv->mtrr = (status & L2C_STAT_MTRR) >> L2C_STAT_MTRR_BIT;
+	priv->ft_support = (status & L2C_STAT_MP) >> L2C_STAT_MP_BIT;
+
+	/* Probe split support. */
+	int split_old = 0;
+	int split_new = 0;
+	split_old = (l2cache_reg_accctrl() & L2C_ACCCTRL_SPLIT);
+	if (split_old){
+		l2cache_reg_accctrl_split_disable();
+	}else{
+		l2cache_reg_accctrl_split_enable();
+	}
+	split_new = (l2cache_reg_accctrl() & L2C_ACCCTRL_SPLIT);
+	if (split_old){
+		l2cache_reg_accctrl_split_enable();
+	}else{
+		l2cache_reg_accctrl_split_disable();
+	}
+	priv->split_support = 
+		((split_new ^ split_old) >> L2C_ACCCTRL_SPLIT_BIT) & 1;
+
+	DBG("L2CACHE driver initialized\n");
+
+	return 0;
+}
+
+/* Called when a core is found with the AMBA device and vendor ID 
+ * given in l2cache_ids[]. IRQ, Console does not work here
+ */
+int l2cache_init1(struct drvmgr_dev *dev)
+{
+	int status;
+	struct l2cache_priv *priv;
+
+	DBG("L2CACHE[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
+
+	if (l2cachepriv) {
+		DBG("Driver only supports one L2CACHE core\n");
+		return DRVMGR_FAIL;
+	}
+
+	priv = dev->priv;
+	if (!priv)
+		return DRVMGR_NOMEM;
+
+	priv->dev = dev;
+	strncpy(&priv->devname[0], "l2cache0", DEVNAME_LEN);
+	l2cachepriv = priv;
+
+	/* Initialize L2CACHE Hardware */
+	status = l2cache_init(priv);
+	if (status) {
+		printf("Failed to initialize l2cache driver %d\n", status);
+		return -1;
+	}
+
+	return DRVMGR_OK;
+}
+
+STATIC INLINE int l2cache_reg_ctrl_enable(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	unsigned int ctrl = REG_READ(&priv->regs->control);
+	REG_WRITE(&priv->regs->control, (ctrl | L2C_CTRL_EN));
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_ctrl_disable(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	unsigned int ctrl = REG_READ(&priv->regs->control);
+	REG_WRITE(&priv->regs->control, (ctrl & ~(L2C_CTRL_EN)));
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_ctrl_repl(int policy)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	unsigned int ctrl = REG_READ(&priv->regs->control);
+	REG_WRITE(&priv->regs->control, 
+		((ctrl & ~(L2C_CTRL_REPL)) | 
+		 ((policy << L2C_CTRL_REPL_BIT) & L2C_CTRL_REPL))
+	);
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_ctrl_iway(int way)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	unsigned int ctrl = REG_READ(&priv->regs->control);
+	REG_WRITE(&priv->regs->control, 
+		((ctrl & ~(L2C_CTRL_IWAY)) | 
+		 ((way << L2C_CTRL_IWAY_BIT) & L2C_CTRL_IWAY))
+	);
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_ctrl_writep(int policy)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	unsigned int ctrl = REG_READ(&priv->regs->control);
+	REG_WRITE(&priv->regs->control, 
+		((ctrl & ~(L2C_CTRL_WP)) | ((policy << L2C_CTRL_WP_BIT) & L2C_CTRL_WP))
+	);
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_ctrl_locked_set(int locked)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	unsigned int ctrl = REG_READ(&priv->regs->control);
+	ctrl = (ctrl & ~(L2C_CTRL_LOCK));
+	REG_WRITE(&priv->regs->control, 
+			ctrl | 
+			((locked << L2C_CTRL_LOCK_BIT) & L2C_CTRL_LOCK));
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_ctrl_edac_set(int edac)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	unsigned int ctrl = REG_READ(&priv->regs->control);
+	REG_WRITE(&priv->regs->control, 
+			(ctrl & ~(L2C_CTRL_EDAC)) | 
+			(edac? L2C_CTRL_EDAC:0));
+	return 0;
+}
+
+STATIC INLINE unsigned int l2cache_reg_ctrl(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	return REG_READ(&priv->regs->control);
+}
+
+STATIC INLINE unsigned int l2cache_reg_status(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	return REG_READ(&priv->regs->status);
+}
+
+STATIC INLINE int l2cache_reg_mtrr_set(int index, unsigned int addr, 
+		unsigned int mask, int options)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	/* Set mtrr */
+	addr = addr & L2C_MTRR_ADDR;
+	mask = (mask >> 16) & L2C_MTRR_MASK; 
+	options = ((options & ~(L2C_MTRR_ADDR)) & ~(L2C_MTRR_MASK));
+	unsigned int mtrr = 0 | addr | mask | options;
+	REG_WRITE(&priv->regs->mtrr[index], mtrr);
+	return 0;
+}
+
+UNUSED STATIC INLINE unsigned int l2cache_reg_mtrr_get(int index)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	return REG_READ(&priv->regs->mtrr[index]);
+}
+
+STATIC INLINE int l2cache_reg_flushmem(unsigned int addr, int options)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	options = (options & ~(L2C_FLUSH_ADDR));
+	REG_WRITE(&priv->regs->flush_mem_addr, (addr & L2C_FLUSH_ADDR) | options);
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_flushline(int way, int index, int options)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	options = 0 | (options & (L2C_FLUSHSI_FMODE));
+	REG_WRITE(&priv->regs->flush_set_index, 
+			((index << L2C_FLUSHSI_INDEX_BIT) & L2C_FLUSHSI_INDEX) |
+			((way << L2C_FLUSHSI_WAY_BIT) & L2C_FLUSHSI_WAY) | 
+			options
+	);
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_flushway(unsigned int tag, int way, int options)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	options = (options & ~(L2C_FLUSHSI_TAG | L2C_FLUSHSI_WAY)) 
+		| L2C_FLUSHSI_WF;
+	REG_WRITE(&priv->regs->flush_set_index, 
+			(tag & L2C_FLUSHSI_TAG) | 
+			( (way << L2C_FLUSHSI_WAY_BIT) & L2C_FLUSHSI_WAY) | 
+			options);
+	return 0;
+}
+
+STATIC INLINE unsigned int l2cache_reg_error(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	return REG_READ(&priv->regs->error_status_control);
+}
+
+STATIC INLINE int l2cache_reg_error_reset(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	unsigned int ctrl = REG_READ(&priv->regs->error_status_control);
+	REG_WRITE(&priv->regs->error_status_control, ctrl | L2C_ERROR_RST);
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_error_irqmask(int mask)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	unsigned int ctrl = REG_READ(&priv->regs->error_status_control);
+	REG_WRITE(&priv->regs->error_status_control, 
+			(ctrl & ~(L2C_ERROR_IRQM)) | (mask & L2C_ERROR_IRQM));
+	return 0;
+}
+
+STATIC INLINE unsigned int l2cache_reg_error_addr(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	return REG_READ(&priv->regs->error_addr);
+}
+
+STATIC INLINE unsigned int l2cache_reg_scrub(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	return REG_READ(&priv->regs->scrub_control_status);
+}
+
+STATIC INLINE int l2cache_reg_scrub_enable(int delay)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	unsigned int ctrl = REG_READ(&priv->regs->scrub_control_status);
+	REG_WRITE(&priv->regs->scrub_delay, 
+			(delay << L2C_SCRUB_DEL_BIT) & L2C_SCRUB_DEL);
+	REG_WRITE(&priv->regs->scrub_control_status,  ctrl | L2C_SCRUB_EN);
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_scrub_disable(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	unsigned int ctrl = REG_READ(&priv->regs->scrub_control_status);
+	REG_WRITE(&priv->regs->scrub_control_status,  ctrl & ~(L2C_SCRUB_EN));
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_scrub_line(int way, int index)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	REG_WRITE(&priv->regs->scrub_control_status, 
+			((index << L2C_SCRUB_INDEX_BIT) & L2C_SCRUB_INDEX) |
+			((way << L2C_SCRUB_WAY_BIT) & L2C_SCRUB_WAY) |
+			L2C_SCRUB_PEN);
+	return 0;
+}
+
+STATIC INLINE unsigned int l2cache_reg_scrub_delay(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	return REG_READ(&priv->regs->scrub_delay);
+}
+
+STATIC INLINE unsigned int l2cache_reg_accctrl(void){
+	struct l2cache_priv *priv = l2cachepriv;
+
+	return REG_READ(&priv->regs->access_control);
+}
+
+STATIC INLINE int l2cache_reg_accctrl_split_disable(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	/* Disable split */
+	unsigned int ctrl = REG_READ(&priv->regs->access_control);
+	REG_WRITE(&priv->regs->access_control, (ctrl & ~(L2C_ACCCTRL_SPLIT)));
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_accctrl_split_enable(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	/* Enable split */
+	unsigned int ctrl = REG_READ(&priv->regs->access_control);
+	REG_WRITE(&priv->regs->access_control, (ctrl | (L2C_ACCCTRL_SPLIT)));
+	return 0;
+}
+
+STATIC INLINE int l2cache_ctrl_status(void)
+{
+	return ((l2cache_reg_ctrl() >> L2C_CTRL_EN_BIT) & 0x1);
+}
+
+STATIC void l2cache_flushwait(void)
+{
+	/* Read any L2cache register to wait until flush is done */
+	/* The L2 will block any access until the flush is done */
+	/* Force read operation */
+	//asm volatile ("" : : "r" (l2cache_reg_status()));
+	(void) l2cache_reg_status();
+	return;
+}
+
+#ifdef TEST_L2CACHE
+STATIC INLINE int l2cache_reg_error_dcb(unsigned int cb)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	REG_WRITE(&priv->regs->data_check_bit, (cb & L2C_DCB_CB)); 
+	return 0;
+}
+
+STATIC INLINE int l2cache_reg_error_inject(unsigned int addr)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	REG_WRITE(&priv->regs->error_injection, 
+			(addr & L2C_ERRINJ_ADDR) | L2C_ERRINJ_EN); 
+	return 0;
+}
+
+STATIC INLINE unsigned int l2cache_reg_diagtag(int way, int index)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	int offset = (index*8 + way);
+	return REG_READ(&priv->regs->diag_iface_tag[offset]);
+}
+
+STATIC INLINE unsigned int l2cache_reg_diagdata(int way, int index, int word)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	int offset = (index*(priv->linesize/4) + way*0x20000 + word);
+	return REG_READ(&priv->regs->diag_iface_data[offset]);
+}
+
+STATIC unsigned int log2int(unsigned int v)
+{
+	unsigned r = 0;
+	while (v >>= 1) {
+		r++;
+	}
+	return r;
+}
+
+/* Return the index for a given addr */
+int l2cache_get_index( uint32_t addr)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	return (addr % priv->waysize)/(priv->linesize);
+}
+
+/* Return the tag for a given addr */
+uint32_t l2cache_get_tag( uint32_t addr)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	uint32_t tmp;
+	int i = log2int(priv->waysize);
+	tmp = (addr >> i);
+	tmp = (tmp << i);
+	return tmp;
+}
+
+int l2cache_lookup(uint32_t addr, int * way)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int i;
+	struct l2cache_tag gottag;
+	int ret;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	uint32_t exptag = l2cache_get_tag(addr);
+	int index = l2cache_get_index(addr);
+
+	/* Check all tags in the set */ 
+	for(i=0; i< priv->ways; i++){
+		ret = l2cache_diag_tag(i, index, &gottag);
+		if (ret != L2CACHE_ERR_OK){
+			return ret;
+		}
+		/*DBG("L2CACHE gottag: way=%d, valid=%d, tag=0x%08x.\n",
+		 *		i, gottag.valid, gottag.tag);*/
+		/* Check if valid */
+		if (gottag.valid){
+			/* Check if they are the same */
+			if (gottag.tag == exptag){
+				/* HIT! */
+				if (way){
+					*way = i;
+				}
+				DBG("L2CACHE lookup: index=%d, tag=0x%08x HIT way=%d.\n", 
+						index, (unsigned int) exptag, i);
+				return L2CACHE_HIT;
+			}
+		}
+	}
+	DBG("L2CACHE lookup: index=%d, tag=0x%08x MISS.\n", 
+			index, (unsigned int) exptag);
+	/* MISS! */
+	return L2CACHE_MISS;
+}
+
+/* Diagnostic Accesses */
+#define l2cache_tag_valid(val) ((val & L2C_TAG_VALID) >> L2C_TAG_VALID_BIT)
+#define l2cache_tag_dirty(val) ((val & L2C_TAG_DIRTY) >> L2C_TAG_DIRTY_BIT)
+#define l2cache_tag_lru(val) ((val & L2C_TAG_LRU) >> L2C_TAG_LRU_BIT)
+int l2cache_diag_tag( int way, int index, struct l2cache_tag * tag)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (way >= priv->ways){
+		DBG("L2CACHE has only %d ways.\n", priv->ways);
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	if (index >= priv->index){
+		DBG("L2CACHE has only %d lines.\n", priv->index);
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	unsigned int val = l2cache_reg_diagtag(way,index);
+
+	if (tag){
+		tag->tag   = l2cache_get_tag(val);
+		tag->valid = l2cache_tag_valid(val);
+		tag->dirty = l2cache_tag_dirty(val);
+		tag->lru   = l2cache_tag_lru(val);
+	}else{
+		return L2CACHE_ERR_EINVAL;
+	}
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_diag_line( int way, int index, struct l2cache_dataline * dataline)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int i;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (way >= priv->ways){
+		DBG("L2CACHE has only %d ways.\n", priv->ways);
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	if (index >= priv->index){
+		DBG("L2CACHE has only %d lines.\n", priv->index);
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	if (dataline){
+		dataline->words = (priv->linesize/4);
+		for (i=0; i< (priv->linesize/4); i++){
+			dataline->data[i] = l2cache_reg_diagdata(way,index,i);
+		}
+	}else{
+		return L2CACHE_ERR_EINVAL;
+	}
+	return L2CACHE_ERR_OK;
+}
+
+/* Inject an error on a given addr */
+int l2cache_error_inject_address( uint32_t addr, uint32_t mask)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int word;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (!priv->ft_support){
+		DBG("L2CACHE does not have EDAC support.\n");
+		return L2CACHE_ERR_ERROR;
+	}
+
+	if (addr & 0x3){
+		DBG("Address not aligned to 32-bit.\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	/* Get word index */
+	word = (addr % priv->linesize)/4;
+
+	/* Shift mask to proper word */
+	mask = (mask << (7*(priv->ways - word - 1)));
+
+	/* Write DCB mask to XOR */
+	l2cache_reg_error_dcb(mask);
+
+	/* Inject error */
+	l2cache_reg_error_inject(addr);
+
+	DBG("L2CACHE error injected in 0x%08x (0x%08x).\n", 
+			(unsigned int) addr, (unsigned int) mask);
+
+	return L2CACHE_ERR_OK;
+}
+
+#endif /* TEST_L2CACHE */
+
+/* L2CACHE Interrupt handler, called when there may be a L2CACHE interrupt.
+ */
+void l2cache_isr(void *arg)
+{
+	struct l2cache_priv *priv = arg;
+	unsigned int sts = l2cache_reg_error();
+	unsigned int addr = l2cache_reg_error_addr();
+
+	/* Make sure that the interrupt is pending and unmasked,
+	 * otherwise it migth have been other core
+	 * sharing the same interrupt line */
+	if ( ((sts & L2C_ERROR_IRQP) >> L2C_ERROR_IRQP_BIT) &
+			((sts & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT)){
+		/* Reset error status */
+		l2cache_reg_error_reset();
+		/* Execute user IRQ (ther will always be one ISR */
+		/* Give cacheline address */
+		(priv->isr)(priv->isr_arg, (addr & ~(0x1f)), sts);
+	}
+}
+
+/* Enable L2CACHE:
+ */
+int l2cache_enable(int flush)
+{
+	int ret;
+
+	/* Flush checks flus parameter and INIT state */
+	ret = l2cache_flush(flush);
+	if (ret < 0){
+		return ret;
+	}
+
+	l2cache_reg_ctrl_enable();
+
+	DBG("L2CACHE enabled\n");
+	return L2CACHE_ERR_OK;
+}
+
+/* Disable L2CACHE:
+ */
+int l2cache_disable(int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if ((flush < 0) || 
+			(flush > 
+			 (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT))
+			){
+		DBG("L2CACHE wrong flush option.\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	/* Flush & invalidate all cache. Also disable L2C */
+	switch(flush & 0x3){
+		case L2CACHE_OPTIONS_FLUSH_NONE:
+			l2cache_reg_ctrl_disable();
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
+			l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_WB_ALL | L2C_FLUSH_DI);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
+			l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_WB_ALL | L2C_FLUSH_DI);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
+		default:
+			l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_ALL | L2C_FLUSH_DI);
+			break;
+	}
+
+	if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
+		l2cache_flushwait();
+	}
+
+	DBG("L2CACHE disabled\n");
+	return L2CACHE_ERR_OK;
+}
+
+/* Status L2CACHE:
+ */
+int l2cache_status(void)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int status;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	unsigned int ctrl = l2cache_reg_ctrl();
+	int locked = (ctrl & L2C_CTRL_LOCK) >> L2C_CTRL_LOCK_BIT;
+	int enabled = ((ctrl & L2C_CTRL_EN) >> L2C_CTRL_EN_BIT) & 0x1;
+	int edac = (ctrl & L2C_CTRL_EDAC) >> L2C_CTRL_EDAC_BIT;
+	int repl = (ctrl & L2C_CTRL_REPL) >> L2C_CTRL_REPL_BIT;
+	int writep = (ctrl & L2C_CTRL_WP) >> L2C_CTRL_WP_BIT;
+
+	unsigned int acc = l2cache_reg_accctrl();
+	int split = (acc & L2C_ACCCTRL_SPLIT) >> L2C_ACCCTRL_SPLIT_BIT;
+
+	unsigned int err = l2cache_reg_error();
+	int interrupts = (err & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT;
+
+	unsigned int scr = l2cache_reg_scrub();
+	int scrub = (scr & L2C_SCRUB_EN) >> L2C_SCRUB_EN_BIT;
+
+	unsigned int dly = l2cache_reg_scrub_delay();
+	int delay = (dly & L2C_SCRUB_DEL) >> L2C_SCRUB_DEL_BIT;
+
+	status = 0|
+		(enabled? L2CACHE_STATUS_ENABLED: 0) |
+		(split? L2CACHE_STATUS_SPLIT_ENABLED: 0) |
+		(edac? L2CACHE_STATUS_EDAC_ENABLED: 0) |
+		((repl & 0x3) << L2CACHE_STATUS_REPL_BIT) |
+		(writep? L2CACHE_STATUS_WRITETHROUGH: 0) |
+		((locked & 0xf) << L2CACHE_STATUS_LOCK_BIT) |
+		((interrupts & 0xf) << L2CACHE_STATUS_INT_BIT) |
+		(scrub? L2CACHE_STATUS_SCRUB_ENABLED: 0) |
+		((delay & 0xffff) << L2CACHE_STATUS_SCRUB_DELAY_BIT);
+
+	return status;
+}
+
+/* Flush L2CACHE:
+ */
+int l2cache_flush(int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if ((flush < 0) || 
+			(flush > 
+			 (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT))
+			){
+		DBG("L2CACHE wrong flush option.\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	switch(flush & 0x3){
+		case L2CACHE_OPTIONS_FLUSH_NONE:
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
+			l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_WB_ALL);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
+			l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_WB_ALL);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
+		default:
+			l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_ALL);
+			break;
+	}
+
+	if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
+		l2cache_flushwait();
+	}
+
+	DBG("L2CACHE flushed\n");
+	return L2CACHE_ERR_OK;
+}
+
+/* Flush L2CACHE address:
+ */
+int l2cache_flush_address(uint32_t addr, int size, int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	uint32_t endaddr;
+	int options;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if ((flush < 0) || 
+			(flush > 
+			 (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT))
+			){
+		DBG("L2CACHE wrong flush option.\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	if (size <= 0){
+		DBG("L2CACHE wrong size.\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	switch(flush & 0x3){
+		case L2CACHE_OPTIONS_FLUSH_NONE:
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
+			options=L2C_FLUSH_FMODE_INV_WB_ONE;
+			break;
+		case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
+			options=L2C_FLUSH_FMODE_WB_ONE;
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
+		default:
+			options=L2C_FLUSH_FMODE_INV_ONE;
+			break;
+	}
+
+	if ( (flush & 0x3) == L2CACHE_OPTIONS_FLUSH_NONE){
+		return L2CACHE_ERR_OK;
+	}
+
+	/* Get the end address */
+	endaddr = (addr + size);
+
+	/* Start on first cacheline address */
+	addr = addr - (addr % priv->linesize);
+	while( addr < endaddr){
+		/* Flush address */
+		l2cache_reg_flushmem(addr, options);
+		/* Update next line */
+		addr += priv->linesize;
+	}
+
+	if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
+		l2cache_flushwait();
+	}
+	
+	DBG("L2CACHE address range flushed\n");
+	return L2CACHE_ERR_OK;
+}
+
+/* Flush L2CACHE line:
+ */
+int l2cache_flush_line(int way, int index, int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if ((flush < 0) || 
+			(flush > 
+			 (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT))
+			){
+		DBG("L2CACHE wrong flush option.\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	if ((index < 0) || (index >= priv->index)){
+		DBG("L2CACHE only has %d lines.\n", priv->index);
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	if ((way < 0 ) || (way >= priv->ways)){
+		DBG("L2CACHE only has %d ways.\n", priv->ways);
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	switch(flush & 0x3){
+		case L2CACHE_OPTIONS_FLUSH_NONE:
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
+			l2cache_reg_flushline(way, index, 
+					L2C_FLUSHSI_FMODE_SET_INV_WB_ONE);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
+			l2cache_reg_flushline(way, index, L2C_FLUSHSI_FMODE_SET_WB_ONE);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
+		default:
+			l2cache_reg_flushline(way, index, L2C_FLUSHSI_FMODE_SET_INV_ONE);
+			break;
+	}
+
+	if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
+		l2cache_flushwait();
+	}
+
+	DBG("L2CACHE line [%d,%d] flushed\n", way, index);
+	return L2CACHE_ERR_OK;
+}
+
+/* Flush L2CACHE way:
+ */
+int l2cache_flush_way(int way, int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if ((flush < 0) || 
+			(flush > 
+			 (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT))
+			){
+		DBG("L2CACHE wrong flush option.\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	if ((way < 0 ) || (way >= priv->ways)){
+		DBG("L2CACHE only has %d ways.\n", priv->ways);
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	switch(flush & 0x3){
+		case L2CACHE_OPTIONS_FLUSH_NONE:
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
+			l2cache_reg_flushway(0, way, L2C_FLUSHSI_FMODE_WAY_UPDATE);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
+			l2cache_reg_flushway(0, way, L2C_FLUSHSI_FMODE_WAY_WB);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
+		default:
+			l2cache_reg_flushway(0, way, L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL);
+			break;
+	}
+
+	if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
+		l2cache_flushwait();
+	}
+
+	DBG("L2CACHE way [%d] flushed\n",way);
+	return L2CACHE_ERR_OK;
+}
+
+/* Fill L2CACHE way:
+ */
+int l2cache_fill_way(int way, uint32_t tag, int options, int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int flags;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if ((way < 0 ) || (way >= priv->ways)){
+		DBG("L2CACHE only has %d ways.\n", priv->ways);
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	/* Check input parameters */
+	if (tag & 0x000003ff){
+		DBG("Only using bits 31:10 of Addr/Mask\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	/* Perform the Way-flush */
+	flags = ((options & L2CACHE_OPTIONS_FETCH)? L2C_FLUSHSI_FL:0) |
+			 ((options & L2CACHE_OPTIONS_VALID)? L2C_FLUSHSI_VB:0) | 
+			 ((options & L2CACHE_OPTIONS_DIRTY)? L2C_FLUSHSI_DB:0);
+
+	/*DBG("L2CACHE lock way: Locked=%d, way=%d, option=0x%04x\n", 
+	 *		locked, way, flags);*/
+
+	switch(flush & 0x3){
+		case L2CACHE_OPTIONS_FLUSH_NONE:
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
+			l2cache_reg_flushway(tag, way, 
+					flags | L2C_FLUSHSI_FMODE_WAY_UPDATE);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
+			l2cache_reg_flushway(tag, way, flags | L2C_FLUSHSI_FMODE_WAY_WB);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
+		default:
+			l2cache_reg_flushway(tag, way, 
+					flags | L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL);
+			break;
+	}
+
+	if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
+		l2cache_flushwait();
+	}
+
+	DBG("Way[%d] filled with Tag 0x%08x\n", way, (unsigned int) tag);
+
+	return L2CACHE_ERR_OK;
+}
+
+/* Lock L2CACHE way:
+ */
+int l2cache_lock_way(uint32_t tag, int options, int flush, int enable)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int enabled;
+	int way;
+	int locked;
+	int flags;
+	int ret;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	locked = L2CACHE_LOCKED_WAYS(l2cache_status());
+	if (locked >= priv->ways){
+		DBG("L2CACHE only has %d ways.\n", priv->ways);
+		return L2CACHE_ERR_TOOMANY;
+	}
+
+	/* Check input parameters */
+	if (tag & 0x000003ff){
+		DBG("Only using bits 31:10 of Addr/Mask\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	/* Check L2C status */
+	enabled = l2cache_ctrl_status();
+	
+	/* Disable L2C */
+	ret = l2cache_disable(flush);
+	if (ret < 0){
+		return ret;
+	}
+
+	/* Increase number of locked ways */
+	locked++;
+	way = priv->ways - locked;
+	l2cache_reg_ctrl_locked_set(locked);
+
+	/* Perform the Way-flush */
+	flags = ((options & L2CACHE_OPTIONS_FETCH)? L2C_FLUSHSI_FL:0) |
+			 ((options & L2CACHE_OPTIONS_VALID)? L2C_FLUSHSI_VB:0) | 
+			 ((options & L2CACHE_OPTIONS_DIRTY)? L2C_FLUSHSI_DB:0);
+
+	/*DBG("L2CACHE lock way: Locked=%d, way=%d, option=0x%04x\n",
+	 *		locked, way, flags);*/
+
+	switch(flush & 0x3){
+		case L2CACHE_OPTIONS_FLUSH_NONE:
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
+			l2cache_reg_flushway(tag, way, 
+					flags | L2C_FLUSHSI_FMODE_WAY_UPDATE);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
+			l2cache_reg_flushway(tag, way, flags | L2C_FLUSHSI_FMODE_WAY_WB);
+			break;
+		case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
+		default:
+			l2cache_reg_flushway(tag, way, 
+					flags | L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL);
+			break;
+	}
+
+	/* Reenable L2C if required */
+	switch(enable){
+		case L2CACHE_OPTIONS_ENABLE:
+			l2cache_reg_ctrl_enable();
+			break;
+		case L2CACHE_OPTIONS_DISABLE:
+			break;
+		case L2CACHE_OPTIONS_NONE:
+		default:
+			if (enabled) {
+				l2cache_reg_ctrl_enable();
+			}
+			break;
+	}
+
+	if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
+		l2cache_flushwait();
+	}
+
+	DBG("Way[%d] locked with Tag 0x%08x\n", way, (unsigned int) tag);
+
+	return L2CACHE_ERR_OK;
+}
+
+/* Unlock L2CACHE waw:
+ */
+int l2cache_unlock()
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	/* Set number of locked ways to 0*/
+	l2cache_reg_ctrl_locked_set(0);
+
+	DBG("L2CACHE ways unlocked\n");
+
+	return L2CACHE_ERR_OK;
+}
+
+/* Setup L2CACHE:
+ * Parameters:
+ * -options: Can be:  
+ */
+int l2cache_mtrr_enable(int index, uint32_t addr, uint32_t mask, int options, 
+		int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int enabled;
+	int flags;
+	int ret;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (index < 0){
+		DBG("Wrong index\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	if (index >= priv->mtrr){
+		DBG("Not enough MTRR registers\n");
+		return L2CACHE_ERR_TOOMANY;
+	}
+
+	/* Check input parameters */
+	if ((addr & 0x0003ffff) || (mask & 0x0003ffff)){
+		DBG("Only using bits 31:18 of Addr/Mask\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	/* Check L2C status */
+	enabled = l2cache_ctrl_status();
+
+	/* Disable L2C */
+	ret = l2cache_disable(flush);
+	if (ret < 0){
+		return ret;
+	}
+
+	/* Decode options */
+	flags = 0 |
+		(options & L2CACHE_OPTIONS_MTRR_ACCESS_WRITETHROUGH? 
+			L2C_MTRR_WRITETHROUGH	: 
+			L2C_MTRR_UNCACHED)		|
+		(options & L2CACHE_OPTIONS_MTRR_WRITEPROT_ENABLE? 
+			L2C_MTRR_WRITEPROT_ENABLE	: 
+			L2C_MTRR_WRITEPROT_DISABLE) |
+		L2C_MTRR_ACCESSCONTROL_ENABLE;
+
+	/* Configure mtrr */
+	l2cache_reg_mtrr_set(index, addr, mask, flags); 
+
+	/* Enable cache again (if needed) */
+	if (enabled){
+		l2cache_reg_ctrl_enable();
+	}
+
+	DBG("MTRR[%d] succesfully configured for 0x%08x (mask 0x%08x), "
+			"access=%s, wprot=%s\n", 
+		index, (unsigned int) addr, (unsigned int) mask, 
+		(options & L2CACHE_OPTIONS_MTRR_ACCESS_WRITETHROUGH? 
+				"WRITETHROUGH":"UNCACHED"),
+		(options & L2CACHE_OPTIONS_MTRR_WRITEPROT_ENABLE? "ENABLE":"DISABLE")
+		);
+
+	return L2CACHE_ERR_OK;
+}
+
+/* Setup L2CACHE:
+ * Parameters:
+ * -options: Can be:  
+ */
+int l2cache_mtrr_disable(int index)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (index < 0){
+		DBG("Wrong index\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	if (index >= priv->mtrr){
+		DBG("Not enough MTRR registers\n");
+		return L2CACHE_ERR_TOOMANY;
+	}
+
+	/* Configure mtrr */
+	l2cache_reg_mtrr_set(index, 0, 0, L2C_MTRR_ACCESSCONTROL_DISABLE); 
+
+	DBG("MTRR[%d] disabled\n", index);
+
+	return L2CACHE_ERR_OK;
+}
+
+/* Print L2CACHE status
+ * DEBUG function
+ */
+int l2cache_print(void)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	#ifdef DEBUG
+	int status = l2cache_status();
+	if (status < 0){
+		return status;
+	}
+	printf("L2cache: Ways:%d. Waysize:%d, Linesize:%d, Lines:%d\n"
+		   "		 MTRR:%d, FT:%s, Locked:%d, Split:%s\n"
+		   "		 REPL:%s, WP:%s, EDAC:%s, Enabled:%s\n"
+		   "		 Scrub:%s, S-Delay:%d\n",
+		priv->ways, 
+		priv->waysize, 
+		priv->linesize, 
+		(priv->index * priv->ways), 
+		priv->mtrr, 
+		(priv->ft_support? "Available":"N/A"),
+		L2CACHE_LOCKED_WAYS(status),
+		(priv->split_support? (L2CACHE_SPLIT_ENABLED(status)? 
+							   "Enabled":"Disabled"):"N/A"),
+		repl_names[L2CACHE_REPL(status)],
+		(L2CACHE_WRITETHROUGH(status)? "Write-through":"Write-back"),
+		(L2CACHE_EDAC_ENABLED(status)? "Enabled":"Disabled"),
+		(L2CACHE_ENABLED(status)? "Yes":"No"),
+		(L2CACHE_SCRUB_ENABLED(status)? "Enabled":"Disabled"),
+		L2CACHE_SCRUB_DELAY(status)
+	);
+	if (l2cache_ctrl_status()){
+		printf("L2cache enabled.\n");
+	}else{
+		printf("L2cache disabled.\n");
+	}
+	#endif
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_split_enable(void)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (!priv->split_support){
+		DBG("L2CACHE does not have split support.\n");
+		return L2CACHE_ERR_ERROR;
+	}
+
+	l2cache_reg_accctrl_split_enable();
+	DBG("L2CACHE split is now enabled\n");
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_split_disable(void)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (!priv->split_support){
+		DBG("L2CACHE does not have split support.\n");
+		return L2CACHE_ERR_ERROR;
+	}
+
+	l2cache_reg_accctrl_split_disable();
+	DBG("L2CACHE split is now disabled\n");
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_edac_enable(int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int enabled;
+	int ret;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (!priv->ft_support){
+		DBG("L2CACHE does not have EDAC support.\n");
+		return L2CACHE_ERR_ERROR;
+	}
+
+	/* Check that L2C is enabled */
+	enabled = l2cache_ctrl_status();
+
+	/* Disable&Flush L2C */
+	ret = l2cache_disable(flush);
+	if (ret < 0){
+		return ret;
+	}
+
+	/* Clear error register */
+	l2cache_reg_error_reset();
+
+	/* Enable EDAC */
+	l2cache_reg_ctrl_edac_set(1);
+
+	/* Enable cache again */
+	if (enabled){
+		l2cache_reg_ctrl_enable();
+	}
+
+	DBG("L2CACHE EDAC is now enabled\n");
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_edac_disable(int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int enabled;
+	int ret;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (!priv->ft_support){
+		DBG("L2CACHE does not have EDAC support.\n");
+		return L2CACHE_ERR_ERROR;
+	}
+
+	/* Check that L2C is enabled */
+	enabled = l2cache_ctrl_status();
+
+	/* Disable&Flush L2C */
+	ret = l2cache_disable(flush);
+	if (ret < 0){
+		return ret;
+	}
+
+	/* Disable EDAC */
+	l2cache_reg_ctrl_edac_set(0);
+
+	/* Clear error register */
+	l2cache_reg_error_reset();
+
+	/* Enable cache again */
+	if (enabled){
+		l2cache_reg_ctrl_enable();
+	}
+
+	DBG("L2CACHE EDAC is now disabled\n");
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_scrub_enable(int delay)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (!priv->ft_support){
+		DBG("L2CACHE does not have EDAC support.\n");
+		return L2CACHE_ERR_ERROR;
+	}
+
+	/* Enable Scrub */
+	l2cache_reg_scrub_enable(delay);
+
+	DBG("L2CACHE Scrub is now enabled\n");
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_scrub_disable(void)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (!priv->ft_support){
+		DBG("L2CACHE does not have EDAC support.\n");
+		return L2CACHE_ERR_ERROR;
+	}
+
+	/* Disable Scrub */
+	l2cache_reg_scrub_disable();
+
+	DBG("L2CACHE Scrub is now disabled\n");
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_scrub_line(int way, int index)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	unsigned int scrub;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (!priv->ft_support){
+		DBG("L2CACHE does not have EDAC support.\n");
+		return L2CACHE_ERR_ERROR;
+	}
+
+	if ((index < 0) || (index >= priv->index)){
+		DBG("L2CACHE only has %d lines.\n", priv->index);
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	if ((way < 0) || (way >= priv->ways)){
+		DBG("L2CACHE only has %d ways.\n", priv->ways);
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	/* Check pending bit */
+	scrub = l2cache_reg_scrub();
+	if ( (scrub & L2C_SCRUB_PEN) || (scrub & L2C_SCRUB_EN) ){
+		DBG("L2CACHE already scrubbing.\n");
+		return L2CACHE_ERR_ERROR;
+	}
+
+	/* Scrub line */
+	l2cache_reg_scrub_line(way, index);
+
+	DBG("L2CACHE Scrub line [%d,%d]\n",way,index);
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_writethrough(int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int enabled;
+	int ret;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	/* Check that L2C is enabled */
+	enabled = l2cache_ctrl_status();
+
+	/* Disable&Flush L2C */
+	ret = l2cache_disable(flush);
+	if (ret < 0){
+		return ret;
+	}
+
+	/* Configure writethrough */
+	l2cache_reg_ctrl_writep(1);
+
+	/* Enable cache again */
+	if (enabled){
+		l2cache_reg_ctrl_enable();
+	}
+
+	DBG("L2CACHE now is writethrough\n");
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_writeback(int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int enabled;
+	int ret;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	/* Check that L2C is enabled */
+	enabled = l2cache_ctrl_status();
+
+	/* Disable&Flush L2C */
+	ret = l2cache_disable(flush);
+	if (ret < 0){
+		return ret;
+	}
+
+	/* Configure writeback */
+	l2cache_reg_ctrl_writep(0);
+
+	/* Enable cache again */
+	if (enabled){
+		l2cache_reg_ctrl_enable();
+	}
+
+	DBG("L2CACHE now is writeback\n");
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_replacement(int options, int flush)
+{
+	struct l2cache_priv * priv = l2cachepriv;
+	int enabled;
+	int ret;
+	int way;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	/* Check that L2C is enabled */
+	enabled = l2cache_ctrl_status();
+
+	/* Disable&Flush L2C */
+	ret = l2cache_disable(flush);
+	if (ret < 0){
+		return ret;
+	}
+
+	if ( (options & 0x3) == L2CACHE_OPTIONS_REPL_MASTERIDX_IDX){
+		/* Set iway */
+		way = (options >> 2) & 0x3;
+		l2cache_reg_ctrl_iway(way);
+	}
+
+	/* Configure writeback */
+	l2cache_reg_ctrl_repl(options & 0x3);
+
+	/* Enable cache again */
+	if (enabled){
+		l2cache_reg_ctrl_enable();
+	}
+
+	DBG("L2CACHE replacement set to %d\n", (options & 0x3));
+
+	return L2CACHE_ERR_OK;
+
+}
+
+int l2cache_isr_register(l2cache_isr_t isr, void * arg, int options)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+	unsigned int mask;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (isr == NULL){
+		DBG("L2CACHE wrong isr.\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	/* Get mask */
+	mask = 0 |
+		((options & L2CACHE_INTERRUPT_BACKENDERROR)? L2C_ERROR_IRQM_BCKEND:0) |
+		((options & L2CACHE_INTERRUPT_WPROTHIT)? L2C_ERROR_IRQM_WPROT:0) |
+		((options & L2CACHE_INTERRUPT_CORRERROR)? L2C_ERROR_IRQM_CORR:0) |
+		((options & L2CACHE_INTERRUPT_UNCORRERROR)? L2C_ERROR_IRQM_UNCORR:0);
+
+	/* Clear previous interrupts and mask them*/
+	l2cache_reg_error_reset();
+	l2cache_reg_error_irqmask(0);
+
+	/* First time registering an ISR */
+	if (priv->isr == NULL){
+		/* Install and Enable L2CACHE interrupt handler */
+		drvmgr_interrupt_register(priv->dev, 0, priv->devname, l2cache_isr, 
+				priv);
+	}
+
+	/* Install user ISR */
+	priv->isr=isr;
+	priv->isr_arg=arg;
+
+	/* Now it is safe to unmask interrupts */
+	l2cache_reg_error_irqmask(mask);
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_isr_unregister(void)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (priv->isr == NULL){
+		DBG("L2CACHE wrong isr.\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	/* Clear previous interrupts and mask them*/
+	l2cache_reg_error_reset();
+	l2cache_reg_error_irqmask(0);
+
+	/* Uninstall and disable L2CACHE interrupt handler */
+	drvmgr_interrupt_unregister(priv->dev, 0, l2cache_isr, priv);
+
+	/* Uninstall user ISR */
+	priv->isr=NULL;
+	priv->isr_arg=NULL;
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_interrupt_unmask(int options)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+	unsigned int mask, irq;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	if (priv->isr == NULL){
+		DBG("L2CACHE wrong isr.\n");
+		return L2CACHE_ERR_EINVAL;
+	}
+
+	/* Unmask interrupts in  L2CACHE */
+	mask = 0 |
+		((options & L2CACHE_INTERRUPT_BACKENDERROR)? L2C_ERROR_IRQM_BCKEND:0) |
+		((options & L2CACHE_INTERRUPT_WPROTHIT)? L2C_ERROR_IRQM_WPROT:0) |
+		((options & L2CACHE_INTERRUPT_CORRERROR)? L2C_ERROR_IRQM_CORR:0) |
+		((options & L2CACHE_INTERRUPT_UNCORRERROR)? L2C_ERROR_IRQM_UNCORR:0);
+
+	/* Clear previous interrupts*/
+	l2cache_reg_error_reset();
+
+	/* Get previous mask */
+	irq = ((l2cache_reg_error() & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT);
+
+	/* Set new mask */
+	l2cache_reg_error_irqmask(irq | mask);
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_interrupt_mask(int options)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+	unsigned int mask, irq;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	/* Mask interrupts in  L2CACHE */
+	mask = 0 |
+		((options & L2CACHE_INTERRUPT_BACKENDERROR)? L2C_ERROR_IRQM_BCKEND:0) |
+		((options & L2CACHE_INTERRUPT_WPROTHIT)? L2C_ERROR_IRQM_WPROT:0) |
+		((options & L2CACHE_INTERRUPT_CORRERROR)? L2C_ERROR_IRQM_CORR:0) |
+		((options & L2CACHE_INTERRUPT_UNCORRERROR)? L2C_ERROR_IRQM_UNCORR:0);
+
+	/* Clear previous interrupts */
+	l2cache_reg_error_reset();
+
+	/* Get previous mask */
+	irq = ((l2cache_reg_error() & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT);
+
+	/* Set new mask */
+	l2cache_reg_error_irqmask(irq & ~(mask));
+
+	return L2CACHE_ERR_OK;
+}
+
+int l2cache_error_status(uint32_t * addr, uint32_t * status)
+{
+	struct l2cache_priv *priv = l2cachepriv;
+	unsigned int sts;
+	unsigned int erraddr;
+
+	if (priv == NULL){
+		DBG("L2CACHE not initialized.\n");
+		return L2CACHE_ERR_NOINIT;
+	}
+
+	/* Get error register */
+	sts = priv->regs->error_status_control;
+	erraddr = priv->regs->error_addr;
+
+	/* Check if an error occurred */
+	if (sts & L2C_ERROR_VALID){
+		/* Reset error register */
+		l2cache_reg_error_reset();
+
+		/* Update user variables if needed */
+		if (addr != NULL){
+			*addr = (erraddr & ~(0x1f));
+		}
+
+		if(status != NULL){
+			*status = sts;
+		}
+
+		/* Return status */
+		if (sts & L2C_ERROR_MULTI){
+			return L2CACHE_STATUS_MULTIPLEERRORS;
+		}else{
+			return L2CACHE_STATUS_NEWERROR;
+		}
+	}else{
+		/* Return status */
+		return L2CACHE_STATUS_NOERROR;
+	}
+}
diff --git a/cpukit/libdrvmgr/drvmgr_confdefs.h b/cpukit/libdrvmgr/drvmgr_confdefs.h
index 7692650..465f66f 100644
--- a/cpukit/libdrvmgr/drvmgr_confdefs.h
+++ b/cpukit/libdrvmgr/drvmgr_confdefs.h
@@ -47,6 +47,7 @@ extern void grtc_register_drv(void);
 extern void pcif_register_drv(void);
 extern void grpci_register_drv(void);
 extern void mctrl_register_drv(void);
+extern void l2cache_register_drv(void);
 extern void grpci2_register_drv(void);
 extern void spictrl_register_drv(void);
 extern void i2cmst_register_drv(void);
@@ -135,6 +136,9 @@ drvmgr_drv_reg_func drvmgr_drivers[] = {
 #ifdef CONFIGURE_DRIVER_AMBAPP_MCTRL
 	mctrl_register_drv,
 #endif
+#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_L2CACHE
+	l2cache_register_drv,
+#endif
 #ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_SPICTRL
 	spictrl_register_drv,
 #endif
-- 
2.7.4




More information about the devel mailing list