source: rtems/bsps/sparc/shared/l2c/l2c.c @ 31720925

Last change on this file since 31720925 was 31720925, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 22, 2018 at 6:13:44 AM

grlib: Move header files

Update #3678.

  • Property mode set to 100644
File size: 50.2 KB
Line 
1/*
2 *  GRLIB L2CACHE Driver
3 *
4 *  COPYRIGHT (c) 2017
5 *  Cobham Gaisler AB
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 */
11
12#include <stdlib.h>
13#include <string.h>
14#include <drvmgr/drvmgr.h>
15#include <grlib/ambapp_bus.h>
16#include <grlib/ambapp.h>
17#include <rtems.h>
18#include <rtems/bspIo.h>
19#include <grlib/grlib.h>
20#include <bsp.h>
21#include <grlib/l2c.h>
22
23/*#define STATIC*/
24#define STATIC static
25
26/*#define INLINE*/
27#define INLINE inline
28
29#define UNUSED __attribute__((unused))
30
31/*#define DEBUG 1*/
32
33#ifdef DEBUG
34#define DBG(x...) printf(x)
35#else
36#define DBG(x...)
37#endif
38
39/*
40 * L2CACHE CTRL register fields
41 */
42#define L2C_CTRL_EN (0x1 << L2C_CTRL_EN_BIT)
43#define L2C_CTRL_EDAC (0x1 << L2C_CTRL_EDAC_BIT)
44#define L2C_CTRL_REPL (0x3 << L2C_CTRL_REPL_BIT)
45#define L2C_CTRL_IWAY (0xf << L2C_CTRL_IWAY_BIT)
46#define L2C_CTRL_LOCK (0xf << L2C_CTRL_LOCK_BIT)
47#define L2C_CTRL_HPRHB (0x1 << L2C_CTRL_HPRHB_BIT)
48#define L2C_CTRL_HPB (0x1 << L2C_CTRL_HPB_BIT)
49#define L2C_CTRL_UC (0x1 << L2C_CTRL_UC_BIT)
50#define L2C_CTRL_HC (0x1 << L2C_CTRL_HC_BIT)
51#define L2C_CTRL_WP (0x1 << L2C_CTRL_WP_BIT)
52#define L2C_CTRL_HP (0x1 << L2C_CTRL_HP_BIT)
53
54#define L2C_CTRL_EN_BIT 31
55#define L2C_CTRL_EDAC_BIT 30
56#define L2C_CTRL_REPL_BIT 28
57#define L2C_CTRL_IWAY_BIT 12
58#define L2C_CTRL_LOCK_BIT 8
59#define L2C_CTRL_HPRHB_BIT 5
60#define L2C_CTRL_HPB_BIT 4
61#define L2C_CTRL_UC_BIT 3
62#define L2C_CTRL_HC_BIT 2
63#define L2C_CTRL_WP_BIT 1
64#define L2C_CTRL_HP_BIT 0
65
66/*
67 * L2CACHE STATUS register fields
68 */
69#define L2C_STAT_LS (0x1 << L2C_STAT_LS_BIT)
70#define L2C_STAT_AT (0x1 << L2C_STAT_AT_BIT)
71#define L2C_STAT_MP (0x1 << L2C_STAT_MP_BIT)
72#define L2C_STAT_MTRR (0x3f << L2C_STAT_MTRR_BIT)
73#define L2C_STAT_BBUSW (0x7 << L2C_STAT_BBUSW_BIT)
74#define L2C_STAT_WAYSIZE (0x7ff << L2C_STAT_WAYSIZE_BIT)
75#define L2C_STAT_WAY (0x3 << L2C_STAT_WAY_BIT)
76
77#define L2C_STAT_LS_BIT 24
78#define L2C_STAT_AT_BIT 23
79#define L2C_STAT_MP_BIT 22
80#define L2C_STAT_MTRR_BIT 16
81#define L2C_STAT_BBUSW_BIT 13
82#define L2C_STAT_WAYSIZE_BIT 2
83#define L2C_STAT_WAY_BIT 0
84
85/*
86 * L2CACHE MTRR register fields
87 */
88#define L2C_MTRR_ADDR (0x3fff << L2C_MTRR_ADDR_BIT)
89#define L2C_MTRR_ACC (0x3 << L2C_MTRR_ACC_BIT)
90#define L2C_MTRR_MASK (0x3fff << L2C_MTRR_MASK_BIT)
91#define L2C_MTRR_WP (0x1 << L2C_MTRR_WP_BIT)
92#define L2C_MTRR_AC (0x1 << L2C_MTRR_AC_BIT)
93
94#define L2C_MTRR_ADDR_BIT 18
95#define L2C_MTRR_ACC_BIT 16
96#define L2C_MTRR_MASK_BIT 2
97#define L2C_MTRR_WP_BIT 1
98#define L2C_MTRR_AC_BIT 0
99
100#define L2C_MTRR_UNCACHED 0
101#define L2C_MTRR_WRITETHROUGH (0x1 << L2C_MTRR_ACC_BIT)
102#define L2C_MTRR_WRITEPROT_ENABLE L2C_MTRR_WP
103#define L2C_MTRR_WRITEPROT_DISABLE 0
104#define L2C_MTRR_ACCESSCONTROL_ENABLE L2C_MTRR_AC
105#define L2C_MTRR_ACCESSCONTROL_DISABLE 0
106
107#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val))
108#define REG_READ(addr) (*(volatile unsigned int *)(addr))
109
110/*
111 * L2CACHE FLUSHMEM register fields
112 */
113#define L2C_FLUSH_ADDR (0x7ffffff << L2C_FLUSH_ADDR_BIT)
114#define L2C_FLUSH_DI (0x1 << L2C_FLUSH_DI_BIT)
115#define L2C_FLUSH_FMODE (0x7 << L2C_FLUSH_FMODE_BIT)
116
117#define L2C_FLUSH_ADDR_BIT 5
118#define L2C_FLUSH_DI_BIT 3
119#define L2C_FLUSH_FMODE_BIT 0
120
121#define L2C_FLUSH_FMODE_INV_ONE (0x1 << L2C_FLUSH_FMODE_BIT)
122#define L2C_FLUSH_FMODE_WB_ONE (0x2 << L2C_FLUSH_FMODE_BIT)
123#define L2C_FLUSH_FMODE_INV_WB_ONE (0x3 << L2C_FLUSH_FMODE_BIT)
124#define L2C_FLUSH_FMODE_INV_ALL (0x5 << L2C_FLUSH_FMODE_BIT)
125#define L2C_FLUSH_FMODE_WB_ALL (0x6 << L2C_FLUSH_FMODE_BIT)
126#define L2C_FLUSH_FMODE_INV_WB_ALL (0x7 << L2C_FLUSH_FMODE_BIT)
127
128/*
129 * L2CACHE FLUSSETINDEX register fields
130 */
131#define L2C_FLUSHSI_INDEX (0xffff << L2C_FLUSHSI_INDEX_BIT)
132#define L2C_FLUSHSI_TAG (0x3fffff << L2C_FLUSHSI_TAG_BIT)
133#define L2C_FLUSHSI_FL (0x1 << L2C_FLUSHSI_FL_BIT)
134#define L2C_FLUSHSI_VB (0x1 << L2C_FLUSHSI_VB_BIT)
135#define L2C_FLUSHSI_DB (0x1 << L2C_FLUSHSI_DB_BIT)
136#define L2C_FLUSHSI_WAY (0x3 << L2C_FLUSHSI_WAY_BIT)
137#define L2C_FLUSHSI_DI (0x1 << L2C_FLUSHSI_DI_BIT)
138#define L2C_FLUSHSI_WF (0x1 << L2C_FLUSHSI_WF_BIT)
139#define L2C_FLUSHSI_FMODE (0x3 << L2C_FLUSHSI_FMODE_BIT)
140
141#define L2C_FLUSHSI_INDEX_BIT 16
142#define L2C_FLUSHSI_TAG_BIT 10
143#define L2C_FLUSHSI_FL_BIT 9
144#define L2C_FLUSHSI_VB_BIT 8
145#define L2C_FLUSHSI_DB_BIT 7
146#define L2C_FLUSHSI_WAY_BIT 4
147#define L2C_FLUSHSI_DI_BIT 3
148#define L2C_FLUSHSI_WF_BIT 2
149#define L2C_FLUSHSI_FMODE_BIT 0
150
151#define L2C_FLUSHSI_FMODE_SET_INV_ONE (0x1 << L2C_FLUSHSI_FMODE_BIT)
152#define L2C_FLUSHSI_FMODE_SET_WB_ONE (0x2 << L2C_FLUSHSI_FMODE_BIT)
153#define L2C_FLUSHSI_FMODE_SET_INV_WB_ONE (0x3 << L2C_FLUSHSI_FMODE_BIT)
154#define L2C_FLUSHSI_FMODE_WAY_UPDATE (0x1 << L2C_FLUSHSI_FMODE_BIT)
155#define L2C_FLUSHSI_FMODE_WAY_WB (0x2 << L2C_FLUSHSI_FMODE_BIT)
156#define L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL (0x3 << L2C_FLUSHSI_FMODE_BIT)
157
158/*
159 * L2CACHE ERROR register fields
160 */
161#define L2C_ERROR_AHBM (0xf << L2C_ERROR_AHBM_BIT)
162#define L2C_ERROR_SCRUB (0x1 << L2C_ERROR_SCRUB_BIT)
163#define L2C_ERROR_TYPE (0x7 << L2C_ERROR_TYPE_BIT)
164#define L2C_ERROR_TAG (0x1 << L2C_ERROR_TAG_BIT)
165#define L2C_ERROR_COR (0x1 << L2C_ERROR_COR_BIT)
166#define L2C_ERROR_MULTI (0x1 << L2C_ERROR_MULTI_BIT)
167#define L2C_ERROR_VALID (0x1 << L2C_ERROR_VALID_BIT)
168#define L2C_ERROR_DISERESP (0x1 << L2C_ERROR_DISERESP_BIT)
169#define L2C_ERROR_CEC (0x7 << L2C_ERROR_CEC_BIT)
170#define L2C_ERROR_IRQP (0xf << L2C_ERROR_IRQP_BIT)
171#define L2C_ERROR_IRQM (0xf << L2C_ERROR_IRQM_BIT)
172#define L2C_ERROR_IRQM_BCKEND (0x1 << L2C_ERROR_IRQM_BCKEND_BIT)
173#define L2C_ERROR_IRQM_WPROT (0x1 << L2C_ERROR_IRQM_WPROT_BIT)
174#define L2C_ERROR_IRQM_UNCORR (0x1 << L2C_ERROR_IRQM_UNCORR_BIT)
175#define L2C_ERROR_IRQM_CORR (0x1 << L2C_ERROR_IRQM_CORR_BIT)
176#define L2C_ERROR_SCB (0x3 << L2C_ERROR_SCB_BIT)
177#define L2C_ERROR_STCB (0x3 << L2C_ERROR_STCB_BIT)
178#define L2C_ERROR_XCB (0x1 << L2C_ERROR_XCB_BIT)
179#define L2C_ERROR_RCB (0x1 << L2C_ERROR_RCB_BIT)
180#define L2C_ERROR_COMP (0x1 << L2C_ERROR_COMP_BIT)
181#define L2C_ERROR_RST (0x1 << L2C_ERROR_RST_BIT)
182
183#define L2C_ERROR_AHBM_BIT 28
184#define L2C_ERROR_SCRUB_BIT 27
185#define L2C_ERROR_TYPE_BIT 24
186#define L2C_ERROR_TAG_BIT 23
187#define L2C_ERROR_COR_BIT 22
188#define L2C_ERROR_MULTI_BIT 21
189#define L2C_ERROR_VALID_BIT 20
190#define L2C_ERROR_DISERESP_BIT 19
191#define L2C_ERROR_CEC_BIT 16
192#define L2C_ERROR_IRQP_BIT 12
193#define L2C_ERROR_IRQM_BCKEND_BIT 11
194#define L2C_ERROR_IRQM_WPROT_BIT 10
195#define L2C_ERROR_IRQM_UNCORR_BIT 9
196#define L2C_ERROR_IRQM_CORR_BIT 8
197#define L2C_ERROR_IRQM_BIT 8
198#define L2C_ERROR_SCB_BIT 6
199#define L2C_ERROR_STCB_BIT 4
200#define L2C_ERROR_XCB_BIT 3
201#define L2C_ERROR_RCB_BIT 2
202#define L2C_ERROR_COMP_BIT 1
203#define L2C_ERROR_RST_BIT 0
204
205/*
206 * L2CACHE DATA CHECK BITS register fields
207 */
208#define L2C_DCB_CB (0xfffffff << L2C_DCB_CB_BIT)
209
210#define L2C_DCB_CB_BIT 0
211
212/*
213 * L2CACHE SCRUB register fields
214 */
215#define L2C_SCRUB_INDEX (0xffff << L2C_SCRUB_INDEX_BIT)
216#define L2C_SCRUB_WAY (0x3 << L2C_SCRUB_WAY_BIT)
217#define L2C_SCRUB_PEN (0x1 << L2C_SCRUB_PEN_BIT)
218#define L2C_SCRUB_EN (0x1 << L2C_SCRUB_EN_BIT)
219
220#define L2C_SCRUB_INDEX_BIT 16
221#define L2C_SCRUB_WAY_BIT 2
222#define L2C_SCRUB_PEN_BIT 1
223#define L2C_SCRUB_EN_BIT 0
224
225/*
226 * L2CACHE SCRUBDELAY register fields
227 */
228#define L2C_SCRUB_DEL (0xffff << L2C_SCRUB_DEL_BIT)
229
230#define L2C_SCRUB_DEL_BIT 0
231
232/*
233 * L2CACHE ERROR INJECT register fields
234 */
235#define L2C_ERRINJ_ADDR (0x3fffffff << L2C_ERRINJ_ADDR_BIT)
236#define L2C_ERRINJ_EN (0x1 << L2C_ERRINJ_EN_BIT)
237
238#define L2C_ERRINJ_ADDR_BIT 2
239#define L2C_ERRINJ_EN_BIT 0
240
241/*
242 * L2CACHE ACCESS CONTROL register fields
243 */
244#define L2C_ACCCTRL_DSC (0x1 << L2C_ACCCTRL_DSC_BIT)
245#define L2C_ACCCTRL_SH (0x1 << L2C_ACCCTRL_SH_BIT)
246#define L2C_ACCCTRL_SPLITQ (0x1 << L2C_ACCCTRL_SPLITQ_BIT)
247#define L2C_ACCCTRL_NHM (0x1 << L2C_ACCCTRL_NHM_BIT)
248#define L2C_ACCCTRL_BERR (0x1 << L2C_ACCCTRL_BERR_BIT)
249#define L2C_ACCCTRL_OAPM (0x1 << L2C_ACCCTRL_OAPM_BIT)
250#define L2C_ACCCTRL_FLINE (0x1 << L2C_ACCCTRL_FLINE_BIT)
251#define L2C_ACCCTRL_DBPF (0x1 << L2C_ACCCTRL_DBPF_BIT)
252#define L2C_ACCCTRL_128WF (0x1 << L2C_ACCCTRL_128WF_BIT)
253#define L2C_ACCCTRL_DBPWS (0x1 << L2C_ACCCTRL_DBPWS_BIT)
254#define L2C_ACCCTRL_SPLIT (0x1 << L2C_ACCCTRL_SPLIT_BIT)
255
256#define L2C_ACCCTRL_DSC_BIT 14
257#define L2C_ACCCTRL_SH_BIT 13
258#define L2C_ACCCTRL_SPLITQ_BIT 10
259#define L2C_ACCCTRL_NHM_BIT 9
260#define L2C_ACCCTRL_BERR_BIT 8
261#define L2C_ACCCTRL_OAPM_BIT 7
262#define L2C_ACCCTRL_FLINE_BIT 6
263#define L2C_ACCCTRL_DBPF_BIT 5
264#define L2C_ACCCTRL_128WF_BIT 4
265#define L2C_ACCCTRL_DBPWS_BIT 2
266#define L2C_ACCCTRL_SPLIT_BIT 1
267
268#ifdef TEST_L2CACHE
269/*
270 * L2CACHE TAG fields
271 */
272#define L2C_TAG_TAG (0xfffffc << L2C_TAG_TAG_BIT)
273#define L2C_TAG_VALID (0x3 << L2C_TAG_VALID_BIT)
274#define L2C_TAG_DIRTY (0x3 << L2C_TAG_DIRTY_BIT)
275#define L2C_TAG_LRU (0x3 << L2C_TAG_LRU_BIT)
276
277#define L2C_TAG_TAG_BIT 10
278#define L2C_TAG_VALID_BIT 8
279#define L2C_TAG_DIRTY_BIT 6
280#define L2C_TAG_LRU_BIT 0
281
282#endif /* TEST_L2CACHE */
283
284#define DEVNAME_LEN 9
285/*
286 * L2CACHE Driver private data struture
287 */
288struct l2cache_priv {
289        struct drvmgr_dev       *dev;
290        char devname[DEVNAME_LEN];
291
292        /* L2CACHE control registers */
293        struct l2c_regs *regs;
294
295        /* L2CACHE status */
296        int ways;
297        int waysize;
298        int linesize;
299        int index;
300        int mtrr;
301        int ft_support;
302        int split_support;
303
304        /* User defined ISR */
305        l2cache_isr_t isr;
306        void *isr_arg;
307};
308
309/*
310 * L2CACHE internal prototypes
311 */
312/* -Register access functions */
313STATIC INLINE int l2cache_reg_ctrl_enable(void);
314STATIC INLINE int l2cache_reg_ctrl_disable(void);
315STATIC INLINE int l2cache_reg_ctrl_locked_set(int locked);
316STATIC INLINE int l2cache_reg_ctrl_edac_set(int edac);
317STATIC INLINE int l2cache_reg_ctrl_repl(int policy);
318STATIC INLINE int l2cache_reg_ctrl_iway(int way);
319STATIC INLINE int l2cache_reg_ctrl_writep(int policy);
320STATIC INLINE unsigned int l2cache_reg_ctrl(void);
321STATIC INLINE unsigned int l2cache_reg_status(void);
322STATIC INLINE int l2cache_reg_mtrr_set(int index, unsigned int addr, 
323                unsigned int mask, int options);
324UNUSED STATIC INLINE unsigned int l2cache_reg_mtrr_get(int index);
325STATIC INLINE int l2cache_reg_flushmem(unsigned int addr, int options);
326STATIC INLINE int l2cache_reg_flushline(int way, int index, int options);
327STATIC INLINE int l2cache_reg_flushway(unsigned int tag, int way, int options);
328STATIC INLINE unsigned int l2cache_reg_error(void);
329STATIC INLINE int l2cache_reg_error_reset(void);
330STATIC INLINE int l2cache_reg_error_irqmask(int mask);
331STATIC INLINE unsigned int l2cache_reg_error_addr(void);
332STATIC INLINE unsigned int l2cache_reg_scrub(void);
333STATIC INLINE int l2cache_reg_scrub_enable(int delay);
334STATIC INLINE int l2cache_reg_scrub_disable(void);
335STATIC INLINE unsigned int l2cache_reg_scrub_delay(void);
336STATIC INLINE int l2cache_reg_scrub_line(int way, int index);
337STATIC INLINE unsigned int l2cache_reg_accctrl(void);
338STATIC INLINE int l2cache_reg_accctrl_split_disable(void);
339STATIC INLINE int l2cache_reg_accctrl_split_enable(void);
340#ifdef TEST_L2CACHE
341STATIC INLINE int l2cache_reg_error_dcb(unsigned int cb);
342STATIC INLINE int l2cache_reg_error_inject(unsigned int addr);
343STATIC INLINE unsigned int l2cache_reg_diagtag(int way, int index);
344STATIC INLINE unsigned int l2cache_reg_diagdata(int way, int index, int word);
345STATIC unsigned int log2int(unsigned int v);
346#endif /* TEST_L2CACHE */
347
348/* -Control functions */
349STATIC int l2cache_ctrl_status(void);
350STATIC void l2cache_flushwait(void);
351
352/* -Init function */
353STATIC int l2cache_init(struct l2cache_priv *priv);
354
355/* -Init function called by drvmgr */
356int l2cache_init1(struct drvmgr_dev *dev);
357
358/* -IRQ handler */
359void l2cache_isr(void *arg);
360
361/*
362 * L2CACHE static members
363 */
364static struct l2cache_priv *l2cachepriv = NULL;
365#ifdef DEBUG
366static char * repl_names[4] = {"LRU","Random","Master-Idx-1","Master-IDx-2"};
367#endif
368
369/* L2CACHE DRIVER */
370
371struct drvmgr_drv_ops l2cache_ops = 
372{
373        .init = {l2cache_init1, NULL, NULL, NULL},
374        .remove = NULL,
375        .info = NULL
376};
377
378struct amba_dev_id l2cache_ids[] = 
379{
380        {VENDOR_GAISLER, GAISLER_L2CACHE},
381        {0, 0}          /* Mark end of table */
382};
383
384struct amba_drv_info l2cache_info =
385{
386        {
387                DRVMGR_OBJ_DRV,                                 /* Driver */
388                NULL,                           /* Next driver */
389                NULL,                           /* Device list */
390                DRIVER_AMBAPP_GAISLER_L2CACHE_ID,/* Driver ID */
391                "L2CACHE_DRV",                  /* Driver Name */
392                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
393                &l2cache_ops,
394                NULL,                           /* Funcs */
395                0,                              /* No devices yet */
396                sizeof(struct l2cache_priv),    /* Make drvmgr alloc private */
397        },
398        &l2cache_ids[0]
399};
400
401void l2cache_register_drv(void)
402{
403        DBG("Registering L2CACHE driver\n");
404        drvmgr_drv_register(&l2cache_info.general);
405}
406
407/* Initializes the L2CACHE core and driver
408 *
409 * Return values
410 *      0                         Successful initalization
411 */
412STATIC int l2cache_init(struct l2cache_priv *priv)
413{
414        struct ambapp_ahb_info *ahb;
415        struct amba_dev_info *ainfo = priv->dev->businfo;
416
417        /* Find L2CACHE core from Plug&Play information */
418        ahb = ainfo->info.ahb_slv;
419
420        /* Found L2CACHE core, init private structure */
421        priv->regs = (struct l2c_regs *)ahb->start[1];
422
423        /* Initialize L2CACHE status */
424        unsigned int status = l2cache_reg_status();
425        priv->ways = (status & L2C_STAT_WAY) + 1;
426        priv->waysize = 
427                ((status & L2C_STAT_WAYSIZE) >> L2C_STAT_WAYSIZE_BIT) * 1024;
428        priv->linesize = ((status & L2C_STAT_LS)? 64 : 32);
429        priv->index = ((priv->waysize)/(priv->linesize));
430        priv->mtrr = (status & L2C_STAT_MTRR) >> L2C_STAT_MTRR_BIT;
431        priv->ft_support = (status & L2C_STAT_MP) >> L2C_STAT_MP_BIT;
432
433        /* Probe split support. */
434        int split_old = 0;
435        int split_new = 0;
436        split_old = (l2cache_reg_accctrl() & L2C_ACCCTRL_SPLIT);
437        if (split_old){
438                l2cache_reg_accctrl_split_disable();
439        }else{
440                l2cache_reg_accctrl_split_enable();
441        }
442        split_new = (l2cache_reg_accctrl() & L2C_ACCCTRL_SPLIT);
443        if (split_old){
444                l2cache_reg_accctrl_split_enable();
445        }else{
446                l2cache_reg_accctrl_split_disable();
447        }
448        priv->split_support = 
449                ((split_new ^ split_old) >> L2C_ACCCTRL_SPLIT_BIT) & 1;
450
451        DBG("L2CACHE driver initialized\n");
452
453        return 0;
454}
455
456/* Called when a core is found with the AMBA device and vendor ID
457 * given in l2cache_ids[]. IRQ, Console does not work here
458 */
459int l2cache_init1(struct drvmgr_dev *dev)
460{
461        int status;
462        struct l2cache_priv *priv;
463
464        DBG("L2CACHE[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
465
466        if (l2cachepriv) {
467                DBG("Driver only supports one L2CACHE core\n");
468                return DRVMGR_FAIL;
469        }
470
471        priv = dev->priv;
472        if (!priv)
473                return DRVMGR_NOMEM;
474
475        priv->dev = dev;
476        strncpy(&priv->devname[0], "l2cache0", DEVNAME_LEN);
477        l2cachepriv = priv;
478
479        /* Initialize L2CACHE Hardware */
480        status = l2cache_init(priv);
481        if (status) {
482                printk("Failed to initialize l2cache driver %d\n", status);
483                return -1;
484        }
485
486        return DRVMGR_OK;
487}
488
489STATIC INLINE int l2cache_reg_ctrl_enable(void)
490{
491        struct l2cache_priv *priv = l2cachepriv;
492
493        unsigned int ctrl = REG_READ(&priv->regs->control);
494        REG_WRITE(&priv->regs->control, (ctrl | L2C_CTRL_EN));
495        return 0;
496}
497
498STATIC INLINE int l2cache_reg_ctrl_disable(void)
499{
500        struct l2cache_priv *priv = l2cachepriv;
501
502        unsigned int ctrl = REG_READ(&priv->regs->control);
503        REG_WRITE(&priv->regs->control, (ctrl & ~(L2C_CTRL_EN)));
504        return 0;
505}
506
507STATIC INLINE int l2cache_reg_ctrl_repl(int policy)
508{
509        struct l2cache_priv *priv = l2cachepriv;
510
511        unsigned int ctrl = REG_READ(&priv->regs->control);
512        REG_WRITE(&priv->regs->control, 
513                ((ctrl & ~(L2C_CTRL_REPL)) | 
514                 ((policy << L2C_CTRL_REPL_BIT) & L2C_CTRL_REPL))
515        );
516        return 0;
517}
518
519STATIC INLINE int l2cache_reg_ctrl_iway(int way)
520{
521        struct l2cache_priv *priv = l2cachepriv;
522
523        unsigned int ctrl = REG_READ(&priv->regs->control);
524        REG_WRITE(&priv->regs->control, 
525                ((ctrl & ~(L2C_CTRL_IWAY)) | 
526                 ((way << L2C_CTRL_IWAY_BIT) & L2C_CTRL_IWAY))
527        );
528        return 0;
529}
530
531STATIC INLINE int l2cache_reg_ctrl_writep(int policy)
532{
533        struct l2cache_priv *priv = l2cachepriv;
534
535        unsigned int ctrl = REG_READ(&priv->regs->control);
536        REG_WRITE(&priv->regs->control, 
537                ((ctrl & ~(L2C_CTRL_WP)) | ((policy << L2C_CTRL_WP_BIT) & L2C_CTRL_WP))
538        );
539        return 0;
540}
541
542STATIC INLINE int l2cache_reg_ctrl_locked_set(int locked)
543{
544        struct l2cache_priv *priv = l2cachepriv;
545
546        unsigned int ctrl = REG_READ(&priv->regs->control);
547        ctrl = (ctrl & ~(L2C_CTRL_LOCK));
548        REG_WRITE(&priv->regs->control, 
549                        ctrl | 
550                        ((locked << L2C_CTRL_LOCK_BIT) & L2C_CTRL_LOCK));
551        return 0;
552}
553
554STATIC INLINE int l2cache_reg_ctrl_edac_set(int edac)
555{
556        struct l2cache_priv *priv = l2cachepriv;
557
558        unsigned int ctrl = REG_READ(&priv->regs->control);
559        REG_WRITE(&priv->regs->control, 
560                        (ctrl & ~(L2C_CTRL_EDAC)) | 
561                        (edac? L2C_CTRL_EDAC:0));
562        return 0;
563}
564
565STATIC INLINE unsigned int l2cache_reg_ctrl(void)
566{
567        struct l2cache_priv *priv = l2cachepriv;
568
569        return REG_READ(&priv->regs->control);
570}
571
572STATIC INLINE unsigned int l2cache_reg_status(void)
573{
574        struct l2cache_priv *priv = l2cachepriv;
575
576        return REG_READ(&priv->regs->status);
577}
578
579STATIC INLINE int l2cache_reg_mtrr_set(int index, unsigned int addr, 
580                unsigned int mask, int options)
581{
582        struct l2cache_priv *priv = l2cachepriv;
583
584        /* Set mtrr */
585        addr = addr & L2C_MTRR_ADDR;
586        mask = (mask >> 16) & L2C_MTRR_MASK; 
587        options = ((options & ~(L2C_MTRR_ADDR)) & ~(L2C_MTRR_MASK));
588        unsigned int mtrr = 0 | addr | mask | options;
589        REG_WRITE(&priv->regs->mtrr[index], mtrr);
590        return 0;
591}
592
593UNUSED STATIC INLINE unsigned int l2cache_reg_mtrr_get(int index)
594{
595        struct l2cache_priv *priv = l2cachepriv;
596
597        return REG_READ(&priv->regs->mtrr[index]);
598}
599
600STATIC INLINE int l2cache_reg_flushmem(unsigned int addr, int options)
601{
602        struct l2cache_priv *priv = l2cachepriv;
603
604        options = (options & ~(L2C_FLUSH_ADDR));
605        REG_WRITE(&priv->regs->flush_mem_addr, (addr & L2C_FLUSH_ADDR) | options);
606        return 0;
607}
608
609STATIC INLINE int l2cache_reg_flushline(int way, int index, int options)
610{
611        struct l2cache_priv *priv = l2cachepriv;
612
613        options = 0 | (options & (L2C_FLUSHSI_FMODE));
614        REG_WRITE(&priv->regs->flush_set_index, 
615                        ((index << L2C_FLUSHSI_INDEX_BIT) & L2C_FLUSHSI_INDEX) |
616                        ((way << L2C_FLUSHSI_WAY_BIT) & L2C_FLUSHSI_WAY) | 
617                        options
618        );
619        return 0;
620}
621
622STATIC INLINE int l2cache_reg_flushway(unsigned int tag, int way, int options)
623{
624        struct l2cache_priv *priv = l2cachepriv;
625
626        options = (options & ~(L2C_FLUSHSI_TAG | L2C_FLUSHSI_WAY)) 
627                | L2C_FLUSHSI_WF;
628        REG_WRITE(&priv->regs->flush_set_index, 
629                        (tag & L2C_FLUSHSI_TAG) | 
630                        ( (way << L2C_FLUSHSI_WAY_BIT) & L2C_FLUSHSI_WAY) | 
631                        options);
632        return 0;
633}
634
635STATIC INLINE unsigned int l2cache_reg_error(void)
636{
637        struct l2cache_priv *priv = l2cachepriv;
638
639        return REG_READ(&priv->regs->error_status_control);
640}
641
642STATIC INLINE int l2cache_reg_error_reset(void)
643{
644        struct l2cache_priv *priv = l2cachepriv;
645
646        unsigned int ctrl = REG_READ(&priv->regs->error_status_control);
647        REG_WRITE(&priv->regs->error_status_control, ctrl | L2C_ERROR_RST);
648        return 0;
649}
650
651STATIC INLINE int l2cache_reg_error_irqmask(int mask)
652{
653        struct l2cache_priv *priv = l2cachepriv;
654
655        unsigned int ctrl = REG_READ(&priv->regs->error_status_control);
656        REG_WRITE(&priv->regs->error_status_control, 
657                        (ctrl & ~(L2C_ERROR_IRQM)) | (mask & L2C_ERROR_IRQM));
658        return 0;
659}
660
661STATIC INLINE unsigned int l2cache_reg_error_addr(void)
662{
663        struct l2cache_priv *priv = l2cachepriv;
664
665        return REG_READ(&priv->regs->error_addr);
666}
667
668STATIC INLINE unsigned int l2cache_reg_scrub(void)
669{
670        struct l2cache_priv *priv = l2cachepriv;
671
672        return REG_READ(&priv->regs->scrub_control_status);
673}
674
675STATIC INLINE int l2cache_reg_scrub_enable(int delay)
676{
677        struct l2cache_priv *priv = l2cachepriv;
678
679        unsigned int accc = REG_READ(&priv->regs->access_control);
680        REG_WRITE(&priv->regs->access_control,
681                        accc | L2C_ACCCTRL_DSC | L2C_ACCCTRL_SH);
682
683        unsigned int ctrl = REG_READ(&priv->regs->scrub_control_status);
684        REG_WRITE(&priv->regs->scrub_delay, 
685                        (delay << L2C_SCRUB_DEL_BIT) & L2C_SCRUB_DEL);
686        REG_WRITE(&priv->regs->scrub_control_status,  ctrl | L2C_SCRUB_EN);
687        return 0;
688}
689
690STATIC INLINE int l2cache_reg_scrub_disable(void)
691{
692        struct l2cache_priv *priv = l2cachepriv;
693
694        unsigned int ctrl = REG_READ(&priv->regs->scrub_control_status);
695        REG_WRITE(&priv->regs->scrub_control_status,  ctrl & ~(L2C_SCRUB_EN));
696        return 0;
697}
698
699STATIC INLINE int l2cache_reg_scrub_line(int way, int index)
700{
701        struct l2cache_priv *priv = l2cachepriv;
702
703        REG_WRITE(&priv->regs->scrub_control_status, 
704                        ((index << L2C_SCRUB_INDEX_BIT) & L2C_SCRUB_INDEX) |
705                        ((way << L2C_SCRUB_WAY_BIT) & L2C_SCRUB_WAY) |
706                        L2C_SCRUB_PEN);
707        return 0;
708}
709
710STATIC INLINE unsigned int l2cache_reg_scrub_delay(void)
711{
712        struct l2cache_priv *priv = l2cachepriv;
713
714        return REG_READ(&priv->regs->scrub_delay);
715}
716
717STATIC INLINE unsigned int l2cache_reg_accctrl(void){
718        struct l2cache_priv *priv = l2cachepriv;
719
720        return REG_READ(&priv->regs->access_control);
721}
722
723STATIC INLINE int l2cache_reg_accctrl_split_disable(void)
724{
725        struct l2cache_priv *priv = l2cachepriv;
726
727        /* Disable split */
728        unsigned int ctrl = REG_READ(&priv->regs->access_control);
729        REG_WRITE(&priv->regs->access_control, (ctrl & ~(L2C_ACCCTRL_SPLIT)));
730        return 0;
731}
732
733STATIC INLINE int l2cache_reg_accctrl_split_enable(void)
734{
735        struct l2cache_priv *priv = l2cachepriv;
736
737        /* Enable split */
738        unsigned int ctrl = REG_READ(&priv->regs->access_control);
739        REG_WRITE(&priv->regs->access_control, (ctrl | (L2C_ACCCTRL_SPLIT)));
740        return 0;
741}
742
743STATIC INLINE int l2cache_ctrl_status(void)
744{
745        return ((l2cache_reg_ctrl() >> L2C_CTRL_EN_BIT) & 0x1);
746}
747
748STATIC void l2cache_flushwait(void)
749{
750        /* Read any L2cache register to wait until flush is done */
751        /* The L2 will block any access until the flush is done */
752        /* Force read operation */
753        //asm volatile ("" : : "r" (l2cache_reg_status()));
754        (void) l2cache_reg_status();
755        return;
756}
757
758#ifdef TEST_L2CACHE
759STATIC INLINE int l2cache_reg_error_dcb(unsigned int cb)
760{
761        struct l2cache_priv *priv = l2cachepriv;
762
763        REG_WRITE(&priv->regs->data_check_bit, (cb & L2C_DCB_CB)); 
764        return 0;
765}
766
767STATIC INLINE int l2cache_reg_error_inject(unsigned int addr)
768{
769        struct l2cache_priv *priv = l2cachepriv;
770
771        REG_WRITE(&priv->regs->error_injection, 
772                        (addr & L2C_ERRINJ_ADDR) | L2C_ERRINJ_EN); 
773        return 0;
774}
775
776STATIC INLINE unsigned int l2cache_reg_diagtag(int way, int index)
777{
778        struct l2cache_priv *priv = l2cachepriv;
779
780        int offset = (index*8 + way);
781        return REG_READ(&priv->regs->diag_iface_tag[offset]);
782}
783
784STATIC INLINE unsigned int l2cache_reg_diagdata(int way, int index, int word)
785{
786        struct l2cache_priv *priv = l2cachepriv;
787
788        int offset = (index*(priv->linesize/4) + way*0x20000 + word);
789        return REG_READ(&priv->regs->diag_iface_data[offset]);
790}
791
792STATIC unsigned int log2int(unsigned int v)
793{
794        unsigned r = 0;
795        while (v >>= 1) {
796                r++;
797        }
798        return r;
799}
800
801/* Return the index for a given addr */
802int l2cache_get_index( uint32_t addr)
803{
804        struct l2cache_priv * priv = l2cachepriv;
805
806        if (priv == NULL){
807                DBG("L2CACHE not initialized.\n");
808                return L2CACHE_ERR_NOINIT;
809        }
810
811        return (addr % priv->waysize)/(priv->linesize);
812}
813
814/* Return the tag for a given addr */
815uint32_t l2cache_get_tag( uint32_t addr)
816{
817        struct l2cache_priv * priv = l2cachepriv;
818
819        if (priv == NULL){
820                DBG("L2CACHE not initialized.\n");
821                return L2CACHE_ERR_NOINIT;
822        }
823
824        uint32_t tmp;
825        int i = log2int(priv->waysize);
826        tmp = (addr >> i);
827        tmp = (tmp << i);
828        return tmp;
829}
830
831int l2cache_lookup(uint32_t addr, int * way)
832{
833        struct l2cache_priv * priv = l2cachepriv;
834        int i;
835        struct l2cache_tag gottag;
836        int ret;
837
838        if (priv == NULL){
839                DBG("L2CACHE not initialized.\n");
840                return L2CACHE_ERR_NOINIT;
841        }
842
843        uint32_t exptag = l2cache_get_tag(addr);
844        int index = l2cache_get_index(addr);
845
846        /* Check all tags in the set */ 
847        for(i=0; i< priv->ways; i++){
848                ret = l2cache_diag_tag(i, index, &gottag);
849                if (ret != L2CACHE_ERR_OK){
850                        return ret;
851                }
852                /*DBG("L2CACHE gottag: way=%d, valid=%d, tag=0x%08x.\n",
853                 *              i, gottag.valid, gottag.tag);*/
854                /* Check if valid */
855                if (gottag.valid){
856                        /* Check if they are the same */
857                        if (gottag.tag == exptag){
858                                /* HIT! */
859                                if (way){
860                                        *way = i;
861                                }
862                                DBG("L2CACHE lookup: index=%d, tag=0x%08x HIT way=%d.\n", 
863                                                index, (unsigned int) exptag, i);
864                                return L2CACHE_HIT;
865                        }
866                }
867        }
868        DBG("L2CACHE lookup: index=%d, tag=0x%08x MISS.\n", 
869                        index, (unsigned int) exptag);
870        /* MISS! */
871        return L2CACHE_MISS;
872}
873
874/* Diagnostic Accesses */
875#define l2cache_tag_valid(val) ((val & L2C_TAG_VALID) >> L2C_TAG_VALID_BIT)
876#define l2cache_tag_dirty(val) ((val & L2C_TAG_DIRTY) >> L2C_TAG_DIRTY_BIT)
877#define l2cache_tag_lru(val) ((val & L2C_TAG_LRU) >> L2C_TAG_LRU_BIT)
878int l2cache_diag_tag( int way, int index, struct l2cache_tag * tag)
879{
880        struct l2cache_priv * priv = l2cachepriv;
881
882        if (priv == NULL){
883                DBG("L2CACHE not initialized.\n");
884                return L2CACHE_ERR_NOINIT;
885        }
886
887        if (way >= priv->ways){
888                DBG("L2CACHE has only %d ways.\n", priv->ways);
889                return L2CACHE_ERR_EINVAL;
890        }
891
892        if (index >= priv->index){
893                DBG("L2CACHE has only %d lines.\n", priv->index);
894                return L2CACHE_ERR_EINVAL;
895        }
896
897        unsigned int val = l2cache_reg_diagtag(way,index);
898
899        if (tag){
900                tag->tag   = l2cache_get_tag(val);
901                tag->valid = l2cache_tag_valid(val);
902                tag->dirty = l2cache_tag_dirty(val);
903                tag->lru   = l2cache_tag_lru(val);
904        }else{
905                return L2CACHE_ERR_EINVAL;
906        }
907        return L2CACHE_ERR_OK;
908}
909
910int l2cache_diag_line( int way, int index, struct l2cache_dataline * dataline)
911{
912        struct l2cache_priv * priv = l2cachepriv;
913        int i;
914
915        if (priv == NULL){
916                DBG("L2CACHE not initialized.\n");
917                return L2CACHE_ERR_NOINIT;
918        }
919
920        if (way >= priv->ways){
921                DBG("L2CACHE has only %d ways.\n", priv->ways);
922                return L2CACHE_ERR_EINVAL;
923        }
924
925        if (index >= priv->index){
926                DBG("L2CACHE has only %d lines.\n", priv->index);
927                return L2CACHE_ERR_EINVAL;
928        }
929
930        if (dataline){
931                dataline->words = (priv->linesize/4);
932                for (i=0; i< (priv->linesize/4); i++){
933                        dataline->data[i] = l2cache_reg_diagdata(way,index,i);
934                }
935        }else{
936                return L2CACHE_ERR_EINVAL;
937        }
938        return L2CACHE_ERR_OK;
939}
940
941/* Inject an error on a given addr */
942int l2cache_error_inject_address( uint32_t addr, uint32_t mask)
943{
944        struct l2cache_priv * priv = l2cachepriv;
945        int word;
946
947        if (priv == NULL){
948                DBG("L2CACHE not initialized.\n");
949                return L2CACHE_ERR_NOINIT;
950        }
951
952        if (!priv->ft_support){
953                DBG("L2CACHE does not have EDAC support.\n");
954                return L2CACHE_ERR_ERROR;
955        }
956
957        if (addr & 0x3){
958                DBG("Address not aligned to 32-bit.\n");
959                return L2CACHE_ERR_EINVAL;
960        }
961
962        /* Get word index */
963        word = (addr % priv->linesize)/4;
964
965        /* Shift mask to proper word */
966        mask = (mask << (7*(priv->ways - word - 1)));
967
968        /* Write DCB mask to XOR */
969        l2cache_reg_error_dcb(mask);
970
971        /* Inject error */
972        l2cache_reg_error_inject(addr);
973
974        DBG("L2CACHE error injected in 0x%08x (0x%08x).\n", 
975                        (unsigned int) addr, (unsigned int) mask);
976
977        return L2CACHE_ERR_OK;
978}
979
980#endif /* TEST_L2CACHE */
981
982/* L2CACHE Interrupt handler, called when there may be a L2CACHE interrupt.
983 */
984void l2cache_isr(void *arg)
985{
986        struct l2cache_priv *priv = arg;
987        unsigned int sts = l2cache_reg_error();
988        unsigned int addr = l2cache_reg_error_addr();
989
990        /* Make sure that the interrupt is pending and unmasked,
991         * otherwise it migth have been other core
992         * sharing the same interrupt line */
993        if ( ((sts & L2C_ERROR_IRQP) >> L2C_ERROR_IRQP_BIT) &
994                        ((sts & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT)){
995                /* Reset error status */
996                l2cache_reg_error_reset();
997                /* Execute user IRQ (ther will always be one ISR */
998                /* Give cacheline address */
999                (priv->isr)(priv->isr_arg, (addr & ~(0x1f)), sts);
1000        }
1001}
1002
1003/* Enable L2CACHE:
1004 */
1005int l2cache_enable(int flush)
1006{
1007        int ret;
1008
1009        /* Flush checks flus parameter and INIT state */
1010        ret = l2cache_flush(flush);
1011        if (ret < 0){
1012                return ret;
1013        }
1014
1015        l2cache_reg_ctrl_enable();
1016
1017        DBG("L2CACHE enabled\n");
1018        return L2CACHE_ERR_OK;
1019}
1020
1021/* Disable L2CACHE:
1022 */
1023int l2cache_disable(int flush)
1024{
1025        struct l2cache_priv * priv = l2cachepriv;
1026
1027        if (priv == NULL){
1028                DBG("L2CACHE not initialized.\n");
1029                return L2CACHE_ERR_NOINIT;
1030        }
1031
1032        if ((flush < 0) || 
1033                        (flush > 
1034                         (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT))
1035                        ){
1036                DBG("L2CACHE wrong flush option.\n");
1037                return L2CACHE_ERR_EINVAL;
1038        }
1039
1040        /* Flush & invalidate all cache. Also disable L2C */
1041        switch(flush & 0x3){
1042                case L2CACHE_OPTIONS_FLUSH_NONE:
1043                        l2cache_reg_ctrl_disable();
1044                        break;
1045                case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
1046                        l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_WB_ALL | L2C_FLUSH_DI);
1047                        break;
1048                case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
1049                        l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_WB_ALL | L2C_FLUSH_DI);
1050                        break;
1051                case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
1052                default:
1053                        l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_ALL | L2C_FLUSH_DI);
1054                        break;
1055        }
1056
1057        if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
1058                l2cache_flushwait();
1059        }
1060
1061        DBG("L2CACHE disabled\n");
1062        return L2CACHE_ERR_OK;
1063}
1064
1065/* Status L2CACHE:
1066 */
1067int l2cache_status(void)
1068{
1069        struct l2cache_priv * priv = l2cachepriv;
1070        int status;
1071
1072        if (priv == NULL){
1073                DBG("L2CACHE not initialized.\n");
1074                return L2CACHE_ERR_NOINIT;
1075        }
1076
1077        unsigned int ctrl = l2cache_reg_ctrl();
1078        int locked = (ctrl & L2C_CTRL_LOCK) >> L2C_CTRL_LOCK_BIT;
1079        int enabled = ((ctrl & L2C_CTRL_EN) >> L2C_CTRL_EN_BIT) & 0x1;
1080        int edac = (ctrl & L2C_CTRL_EDAC) >> L2C_CTRL_EDAC_BIT;
1081        int repl = (ctrl & L2C_CTRL_REPL) >> L2C_CTRL_REPL_BIT;
1082        int writep = (ctrl & L2C_CTRL_WP) >> L2C_CTRL_WP_BIT;
1083
1084        unsigned int acc = l2cache_reg_accctrl();
1085        int split = (acc & L2C_ACCCTRL_SPLIT) >> L2C_ACCCTRL_SPLIT_BIT;
1086
1087        unsigned int err = l2cache_reg_error();
1088        int interrupts = (err & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT;
1089
1090        unsigned int scr = l2cache_reg_scrub();
1091        int scrub = (scr & L2C_SCRUB_EN) >> L2C_SCRUB_EN_BIT;
1092
1093        unsigned int dly = l2cache_reg_scrub_delay();
1094        int delay = (dly & L2C_SCRUB_DEL) >> L2C_SCRUB_DEL_BIT;
1095
1096        status = 0|
1097                (enabled? L2CACHE_STATUS_ENABLED: 0) |
1098                (split? L2CACHE_STATUS_SPLIT_ENABLED: 0) |
1099                (edac? L2CACHE_STATUS_EDAC_ENABLED: 0) |
1100                ((repl & 0x3) << L2CACHE_STATUS_REPL_BIT) |
1101                (writep? L2CACHE_STATUS_WRITETHROUGH: 0) |
1102                ((locked & 0xf) << L2CACHE_STATUS_LOCK_BIT) |
1103                ((interrupts & 0xf) << L2CACHE_STATUS_INT_BIT) |
1104                (scrub? L2CACHE_STATUS_SCRUB_ENABLED: 0) |
1105                ((delay & 0xffff) << L2CACHE_STATUS_SCRUB_DELAY_BIT);
1106
1107        return status;
1108}
1109
1110/* Flush L2CACHE:
1111 */
1112int l2cache_flush(int flush)
1113{
1114        struct l2cache_priv * priv = l2cachepriv;
1115
1116        if (priv == NULL){
1117                DBG("L2CACHE not initialized.\n");
1118                return L2CACHE_ERR_NOINIT;
1119        }
1120
1121        if ((flush < 0) || 
1122                        (flush > 
1123                         (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT))
1124                        ){
1125                DBG("L2CACHE wrong flush option.\n");
1126                return L2CACHE_ERR_EINVAL;
1127        }
1128
1129        switch(flush & 0x3){
1130                case L2CACHE_OPTIONS_FLUSH_NONE:
1131                        break;
1132                case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
1133                        l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_WB_ALL);
1134                        break;
1135                case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
1136                        l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_WB_ALL);
1137                        break;
1138                case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
1139                default:
1140                        l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_ALL);
1141                        break;
1142        }
1143
1144        if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
1145                l2cache_flushwait();
1146        }
1147
1148        DBG("L2CACHE flushed\n");
1149        return L2CACHE_ERR_OK;
1150}
1151
1152/* Flush L2CACHE address:
1153 */
1154int l2cache_flush_address(uint32_t addr, int size, int flush)
1155{
1156        struct l2cache_priv * priv = l2cachepriv;
1157        uint32_t endaddr;
1158        int options;
1159
1160        if (priv == NULL){
1161                DBG("L2CACHE not initialized.\n");
1162                return L2CACHE_ERR_NOINIT;
1163        }
1164
1165        if ((flush < 0) || 
1166                        (flush > 
1167                         (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT))
1168                        ){
1169                DBG("L2CACHE wrong flush option.\n");
1170                return L2CACHE_ERR_EINVAL;
1171        }
1172
1173        if (size <= 0){
1174                DBG("L2CACHE wrong size.\n");
1175                return L2CACHE_ERR_EINVAL;
1176        }
1177
1178        switch(flush & 0x3){
1179                case L2CACHE_OPTIONS_FLUSH_NONE:
1180                        break;
1181                case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
1182                        options=L2C_FLUSH_FMODE_INV_WB_ONE;
1183                        break;
1184                case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
1185                        options=L2C_FLUSH_FMODE_WB_ONE;
1186                        break;
1187                case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
1188                default:
1189                        options=L2C_FLUSH_FMODE_INV_ONE;
1190                        break;
1191        }
1192
1193        if ( (flush & 0x3) == L2CACHE_OPTIONS_FLUSH_NONE){
1194                return L2CACHE_ERR_OK;
1195        }
1196
1197        /* Get the end address */
1198        endaddr = (addr + size);
1199
1200        /* Start on first cacheline address */
1201        addr = addr - (addr % priv->linesize);
1202        while( addr < endaddr){
1203                /* Flush address */
1204                l2cache_reg_flushmem(addr, options);
1205                /* Update next line */
1206                addr += priv->linesize;
1207        }
1208
1209        if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
1210                l2cache_flushwait();
1211        }
1212       
1213        DBG("L2CACHE address range flushed\n");
1214        return L2CACHE_ERR_OK;
1215}
1216
1217/* Flush L2CACHE line:
1218 */
1219int l2cache_flush_line(int way, int index, int flush)
1220{
1221        struct l2cache_priv * priv = l2cachepriv;
1222
1223        if (priv == NULL){
1224                DBG("L2CACHE not initialized.\n");
1225                return L2CACHE_ERR_NOINIT;
1226        }
1227
1228        if ((flush < 0) || 
1229                        (flush > 
1230                         (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT))
1231                        ){
1232                DBG("L2CACHE wrong flush option.\n");
1233                return L2CACHE_ERR_EINVAL;
1234        }
1235
1236        if ((index < 0) || (index >= priv->index)){
1237                DBG("L2CACHE only has %d lines.\n", priv->index);
1238                return L2CACHE_ERR_EINVAL;
1239        }
1240
1241        if ((way < 0 ) || (way >= priv->ways)){
1242                DBG("L2CACHE only has %d ways.\n", priv->ways);
1243                return L2CACHE_ERR_EINVAL;
1244        }
1245
1246        switch(flush & 0x3){
1247                case L2CACHE_OPTIONS_FLUSH_NONE:
1248                        break;
1249                case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
1250                        l2cache_reg_flushline(way, index, 
1251                                        L2C_FLUSHSI_FMODE_SET_INV_WB_ONE);
1252                        break;
1253                case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
1254                        l2cache_reg_flushline(way, index, L2C_FLUSHSI_FMODE_SET_WB_ONE);
1255                        break;
1256                case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
1257                default:
1258                        l2cache_reg_flushline(way, index, L2C_FLUSHSI_FMODE_SET_INV_ONE);
1259                        break;
1260        }
1261
1262        if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
1263                l2cache_flushwait();
1264        }
1265
1266        DBG("L2CACHE line [%d,%d] flushed\n", way, index);
1267        return L2CACHE_ERR_OK;
1268}
1269
1270/* Flush L2CACHE way:
1271 */
1272int l2cache_flush_way(int way, int flush)
1273{
1274        struct l2cache_priv * priv = l2cachepriv;
1275
1276        if (priv == NULL){
1277                DBG("L2CACHE not initialized.\n");
1278                return L2CACHE_ERR_NOINIT;
1279        }
1280
1281        if ((flush < 0) || 
1282                        (flush > 
1283                         (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT))
1284                        ){
1285                DBG("L2CACHE wrong flush option.\n");
1286                return L2CACHE_ERR_EINVAL;
1287        }
1288
1289        if ((way < 0 ) || (way >= priv->ways)){
1290                DBG("L2CACHE only has %d ways.\n", priv->ways);
1291                return L2CACHE_ERR_EINVAL;
1292        }
1293
1294        switch(flush & 0x3){
1295                case L2CACHE_OPTIONS_FLUSH_NONE:
1296                        break;
1297                case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
1298                        l2cache_reg_flushway(0, way, L2C_FLUSHSI_FMODE_WAY_UPDATE);
1299                        break;
1300                case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
1301                        l2cache_reg_flushway(0, way, L2C_FLUSHSI_FMODE_WAY_WB);
1302                        break;
1303                case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
1304                default:
1305                        l2cache_reg_flushway(0, way, L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL);
1306                        break;
1307        }
1308
1309        if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
1310                l2cache_flushwait();
1311        }
1312
1313        DBG("L2CACHE way [%d] flushed\n",way);
1314        return L2CACHE_ERR_OK;
1315}
1316
1317/* Fill L2CACHE way:
1318 */
1319int l2cache_fill_way(int way, uint32_t tag, int options, int flush)
1320{
1321        struct l2cache_priv * priv = l2cachepriv;
1322        int flags;
1323
1324        if (priv == NULL){
1325                DBG("L2CACHE not initialized.\n");
1326                return L2CACHE_ERR_NOINIT;
1327        }
1328
1329        if ((way < 0 ) || (way >= priv->ways)){
1330                DBG("L2CACHE only has %d ways.\n", priv->ways);
1331                return L2CACHE_ERR_EINVAL;
1332        }
1333
1334        /* Check input parameters */
1335        if (tag & 0x000003ff){
1336                DBG("Only using bits 31:10 of Addr/Mask\n");
1337                return L2CACHE_ERR_EINVAL;
1338        }
1339
1340        /* Perform the Way-flush */
1341        flags = ((options & L2CACHE_OPTIONS_FETCH)? L2C_FLUSHSI_FL:0) |
1342                         ((options & L2CACHE_OPTIONS_VALID)? L2C_FLUSHSI_VB:0) | 
1343                         ((options & L2CACHE_OPTIONS_DIRTY)? L2C_FLUSHSI_DB:0);
1344
1345        /*DBG("L2CACHE lock way: Locked=%d, way=%d, option=0x%04x\n",
1346         *              locked, way, flags);*/
1347
1348        switch(flush & 0x3){
1349                case L2CACHE_OPTIONS_FLUSH_NONE:
1350                        break;
1351                case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
1352                        l2cache_reg_flushway(tag, way, 
1353                                        flags | L2C_FLUSHSI_FMODE_WAY_UPDATE);
1354                        break;
1355                case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
1356                        l2cache_reg_flushway(tag, way, flags | L2C_FLUSHSI_FMODE_WAY_WB);
1357                        break;
1358                case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
1359                default:
1360                        l2cache_reg_flushway(tag, way, 
1361                                        flags | L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL);
1362                        break;
1363        }
1364
1365        if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
1366                l2cache_flushwait();
1367        }
1368
1369        DBG("Way[%d] filled with Tag 0x%08x\n", way, (unsigned int) tag);
1370
1371        return L2CACHE_ERR_OK;
1372}
1373
1374/* Lock L2CACHE way:
1375 */
1376int l2cache_lock_way(uint32_t tag, int options, int flush, int enable)
1377{
1378        struct l2cache_priv * priv = l2cachepriv;
1379        int enabled;
1380        int way;
1381        int locked;
1382        int flags;
1383        int ret;
1384
1385        if (priv == NULL){
1386                DBG("L2CACHE not initialized.\n");
1387                return L2CACHE_ERR_NOINIT;
1388        }
1389
1390        locked = L2CACHE_LOCKED_WAYS(l2cache_status());
1391        if (locked >= priv->ways){
1392                DBG("L2CACHE only has %d ways.\n", priv->ways);
1393                return L2CACHE_ERR_TOOMANY;
1394        }
1395
1396        /* Check input parameters */
1397        if (tag & 0x000003ff){
1398                DBG("Only using bits 31:10 of Addr/Mask\n");
1399                return L2CACHE_ERR_EINVAL;
1400        }
1401
1402        /* Check L2C status */
1403        enabled = l2cache_ctrl_status();
1404       
1405        /* Disable L2C */
1406        ret = l2cache_disable(flush);
1407        if (ret < 0){
1408                return ret;
1409        }
1410
1411        /* Increase number of locked ways */
1412        locked++;
1413        way = priv->ways - locked;
1414        l2cache_reg_ctrl_locked_set(locked);
1415
1416        /* Perform the Way-flush */
1417        flags = ((options & L2CACHE_OPTIONS_FETCH)? L2C_FLUSHSI_FL:0) |
1418                         ((options & L2CACHE_OPTIONS_VALID)? L2C_FLUSHSI_VB:0) | 
1419                         ((options & L2CACHE_OPTIONS_DIRTY)? L2C_FLUSHSI_DB:0);
1420
1421        /*DBG("L2CACHE lock way: Locked=%d, way=%d, option=0x%04x\n",
1422         *              locked, way, flags);*/
1423
1424        switch(flush & 0x3){
1425                case L2CACHE_OPTIONS_FLUSH_NONE:
1426                        break;
1427                case L2CACHE_OPTIONS_FLUSH_INVALIDATE:
1428                        l2cache_reg_flushway(tag, way, 
1429                                        flags | L2C_FLUSHSI_FMODE_WAY_UPDATE);
1430                        break;
1431                case L2CACHE_OPTIONS_FLUSH_WRITEBACK:
1432                        l2cache_reg_flushway(tag, way, flags | L2C_FLUSHSI_FMODE_WAY_WB);
1433                        break;
1434                case L2CACHE_OPTIONS_FLUSH_INV_WBACK:
1435                default:
1436                        l2cache_reg_flushway(tag, way, 
1437                                        flags | L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL);
1438                        break;
1439        }
1440
1441        /* Reenable L2C if required */
1442        switch(enable){
1443                case L2CACHE_OPTIONS_ENABLE:
1444                        l2cache_reg_ctrl_enable();
1445                        break;
1446                case L2CACHE_OPTIONS_DISABLE:
1447                        break;
1448                case L2CACHE_OPTIONS_NONE:
1449                default:
1450                        if (enabled) {
1451                                l2cache_reg_ctrl_enable();
1452                        }
1453                        break;
1454        }
1455
1456        if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){
1457                l2cache_flushwait();
1458        }
1459
1460        DBG("Way[%d] locked with Tag 0x%08x\n", way, (unsigned int) tag);
1461
1462        return L2CACHE_ERR_OK;
1463}
1464
1465/* Unlock L2CACHE waw:
1466 */
1467int l2cache_unlock()
1468{
1469        struct l2cache_priv * priv = l2cachepriv;
1470
1471        if (priv == NULL){
1472                DBG("L2CACHE not initialized.\n");
1473                return L2CACHE_ERR_NOINIT;
1474        }
1475
1476        /* Set number of locked ways to 0*/
1477        l2cache_reg_ctrl_locked_set(0);
1478
1479        DBG("L2CACHE ways unlocked\n");
1480
1481        return L2CACHE_ERR_OK;
1482}
1483
1484/* Setup L2CACHE:
1485 * Parameters:
1486 * -options: Can be: 
1487 */
1488int l2cache_mtrr_enable(int index, uint32_t addr, uint32_t mask, int options, 
1489                int flush)
1490{
1491        struct l2cache_priv * priv = l2cachepriv;
1492        int enabled;
1493        int flags;
1494        int ret;
1495
1496        if (priv == NULL){
1497                DBG("L2CACHE not initialized.\n");
1498                return L2CACHE_ERR_NOINIT;
1499        }
1500
1501        if (index < 0){
1502                DBG("Wrong index\n");
1503                return L2CACHE_ERR_EINVAL;
1504        }
1505
1506        if (index >= priv->mtrr){
1507                DBG("Not enough MTRR registers\n");
1508                return L2CACHE_ERR_TOOMANY;
1509        }
1510
1511        /* Check input parameters */
1512        if ((addr & 0x0003ffff) || (mask & 0x0003ffff)){
1513                DBG("Only using bits 31:18 of Addr/Mask\n");
1514                return L2CACHE_ERR_EINVAL;
1515        }
1516
1517        /* Check L2C status */
1518        enabled = l2cache_ctrl_status();
1519
1520        /* Disable L2C */
1521        ret = l2cache_disable(flush);
1522        if (ret < 0){
1523                return ret;
1524        }
1525
1526        /* Decode options */
1527        flags = 0 |
1528                (options & L2CACHE_OPTIONS_MTRR_ACCESS_WRITETHROUGH? 
1529                        L2C_MTRR_WRITETHROUGH   : 
1530                        L2C_MTRR_UNCACHED)              |
1531                (options & L2CACHE_OPTIONS_MTRR_WRITEPROT_ENABLE? 
1532                        L2C_MTRR_WRITEPROT_ENABLE       : 
1533                        L2C_MTRR_WRITEPROT_DISABLE) |
1534                L2C_MTRR_ACCESSCONTROL_ENABLE;
1535
1536        /* Configure mtrr */
1537        l2cache_reg_mtrr_set(index, addr, mask, flags); 
1538
1539        /* Enable cache again (if needed) */
1540        if (enabled){
1541                l2cache_reg_ctrl_enable();
1542        }
1543
1544        DBG("MTRR[%d] succesfully configured for 0x%08x (mask 0x%08x), "
1545                        "access=%s, wprot=%s\n", 
1546                index, (unsigned int) addr, (unsigned int) mask, 
1547                (options & L2CACHE_OPTIONS_MTRR_ACCESS_WRITETHROUGH? 
1548                                "WRITETHROUGH":"UNCACHED"),
1549                (options & L2CACHE_OPTIONS_MTRR_WRITEPROT_ENABLE? "ENABLE":"DISABLE")
1550                );
1551
1552        return L2CACHE_ERR_OK;
1553}
1554
1555/* Setup L2CACHE:
1556 * Parameters:
1557 * -options: Can be: 
1558 */
1559int l2cache_mtrr_disable(int index)
1560{
1561        struct l2cache_priv * priv = l2cachepriv;
1562
1563        if (priv == NULL){
1564                DBG("L2CACHE not initialized.\n");
1565                return L2CACHE_ERR_NOINIT;
1566        }
1567
1568        if (index < 0){
1569                DBG("Wrong index\n");
1570                return L2CACHE_ERR_EINVAL;
1571        }
1572
1573        if (index >= priv->mtrr){
1574                DBG("Not enough MTRR registers\n");
1575                return L2CACHE_ERR_TOOMANY;
1576        }
1577
1578        /* Configure mtrr */
1579        l2cache_reg_mtrr_set(index, 0, 0, L2C_MTRR_ACCESSCONTROL_DISABLE); 
1580
1581        DBG("MTRR[%d] disabled\n", index);
1582
1583        return L2CACHE_ERR_OK;
1584}
1585
1586/* Print L2CACHE status
1587 * DEBUG function
1588 */
1589int l2cache_print(void)
1590{
1591        struct l2cache_priv * priv = l2cachepriv;
1592
1593        if (priv == NULL){
1594                DBG("L2CACHE not initialized.\n");
1595                return L2CACHE_ERR_NOINIT;
1596        }
1597
1598        #ifdef DEBUG
1599        int status = l2cache_status();
1600        if (status < 0){
1601                return status;
1602        }
1603        printf("L2cache: Ways:%d. Waysize:%d, Linesize:%d, Lines:%d\n"
1604                   "             MTRR:%d, FT:%s, Locked:%d, Split:%s\n"
1605                   "             REPL:%s, WP:%s, EDAC:%s, Enabled:%s\n"
1606                   "             Scrub:%s, S-Delay:%d\n",
1607                priv->ways, 
1608                priv->waysize, 
1609                priv->linesize, 
1610                (priv->index * priv->ways), 
1611                priv->mtrr, 
1612                (priv->ft_support? "Available":"N/A"),
1613                L2CACHE_LOCKED_WAYS(status),
1614                (priv->split_support? (L2CACHE_SPLIT_ENABLED(status)? 
1615                                                           "Enabled":"Disabled"):"N/A"),
1616                repl_names[L2CACHE_REPL(status)],
1617                (L2CACHE_WRITETHROUGH(status)? "Write-through":"Write-back"),
1618                (L2CACHE_EDAC_ENABLED(status)? "Enabled":"Disabled"),
1619                (L2CACHE_ENABLED(status)? "Yes":"No"),
1620                (L2CACHE_SCRUB_ENABLED(status)? "Enabled":"Disabled"),
1621                L2CACHE_SCRUB_DELAY(status)
1622        );
1623        if (l2cache_ctrl_status()){
1624                printf("L2cache enabled.\n");
1625        }else{
1626                printf("L2cache disabled.\n");
1627        }
1628        #endif
1629        return L2CACHE_ERR_OK;
1630}
1631
1632int l2cache_split_enable(void)
1633{
1634        struct l2cache_priv * priv = l2cachepriv;
1635
1636        if (priv == NULL){
1637                DBG("L2CACHE not initialized.\n");
1638                return L2CACHE_ERR_NOINIT;
1639        }
1640
1641        if (!priv->split_support){
1642                DBG("L2CACHE does not have split support.\n");
1643                return L2CACHE_ERR_ERROR;
1644        }
1645
1646        l2cache_reg_accctrl_split_enable();
1647        DBG("L2CACHE split is now enabled\n");
1648
1649        return L2CACHE_ERR_OK;
1650}
1651
1652int l2cache_split_disable(void)
1653{
1654        struct l2cache_priv * priv = l2cachepriv;
1655
1656        if (priv == NULL){
1657                DBG("L2CACHE not initialized.\n");
1658                return L2CACHE_ERR_NOINIT;
1659        }
1660
1661        if (!priv->split_support){
1662                DBG("L2CACHE does not have split support.\n");
1663                return L2CACHE_ERR_ERROR;
1664        }
1665
1666        l2cache_reg_accctrl_split_disable();
1667        DBG("L2CACHE split is now disabled\n");
1668
1669        return L2CACHE_ERR_OK;
1670}
1671
1672int l2cache_edac_enable(int flush)
1673{
1674        struct l2cache_priv * priv = l2cachepriv;
1675        int enabled;
1676        int ret;
1677
1678        if (priv == NULL){
1679                DBG("L2CACHE not initialized.\n");
1680                return L2CACHE_ERR_NOINIT;
1681        }
1682
1683        if (!priv->ft_support){
1684                DBG("L2CACHE does not have EDAC support.\n");
1685                return L2CACHE_ERR_ERROR;
1686        }
1687
1688        /* Check that L2C is enabled */
1689        enabled = l2cache_ctrl_status();
1690
1691        /* Disable&Flush L2C */
1692        ret = l2cache_disable(flush);
1693        if (ret < 0){
1694                return ret;
1695        }
1696
1697        /* Clear error register */
1698        l2cache_reg_error_reset();
1699
1700        /* Enable EDAC */
1701        l2cache_reg_ctrl_edac_set(1);
1702
1703        /* Enable cache again */
1704        if (enabled){
1705                l2cache_reg_ctrl_enable();
1706        }
1707
1708        DBG("L2CACHE EDAC is now enabled\n");
1709
1710        return L2CACHE_ERR_OK;
1711}
1712
1713int l2cache_edac_disable(int flush)
1714{
1715        struct l2cache_priv * priv = l2cachepriv;
1716        int enabled;
1717        int ret;
1718
1719        if (priv == NULL){
1720                DBG("L2CACHE not initialized.\n");
1721                return L2CACHE_ERR_NOINIT;
1722        }
1723
1724        if (!priv->ft_support){
1725                DBG("L2CACHE does not have EDAC support.\n");
1726                return L2CACHE_ERR_ERROR;
1727        }
1728
1729        /* Check that L2C is enabled */
1730        enabled = l2cache_ctrl_status();
1731
1732        /* Disable&Flush L2C */
1733        ret = l2cache_disable(flush);
1734        if (ret < 0){
1735                return ret;
1736        }
1737
1738        /* Disable EDAC */
1739        l2cache_reg_ctrl_edac_set(0);
1740
1741        /* Clear error register */
1742        l2cache_reg_error_reset();
1743
1744        /* Enable cache again */
1745        if (enabled){
1746                l2cache_reg_ctrl_enable();
1747        }
1748
1749        DBG("L2CACHE EDAC is now disabled\n");
1750
1751        return L2CACHE_ERR_OK;
1752}
1753
1754int l2cache_scrub_enable(int delay)
1755{
1756        struct l2cache_priv * priv = l2cachepriv;
1757
1758        if (priv == NULL){
1759                DBG("L2CACHE not initialized.\n");
1760                return L2CACHE_ERR_NOINIT;
1761        }
1762
1763        if (!priv->ft_support){
1764                DBG("L2CACHE does not have EDAC support.\n");
1765                return L2CACHE_ERR_ERROR;
1766        }
1767
1768        /* Enable Scrub */
1769        l2cache_reg_scrub_enable(delay);
1770
1771        DBG("L2CACHE Scrub is now enabled\n");
1772
1773        return L2CACHE_ERR_OK;
1774}
1775
1776int l2cache_scrub_disable(void)
1777{
1778        struct l2cache_priv * priv = l2cachepriv;
1779
1780        if (priv == NULL){
1781                DBG("L2CACHE not initialized.\n");
1782                return L2CACHE_ERR_NOINIT;
1783        }
1784
1785        if (!priv->ft_support){
1786                DBG("L2CACHE does not have EDAC support.\n");
1787                return L2CACHE_ERR_ERROR;
1788        }
1789
1790        /* Disable Scrub */
1791        l2cache_reg_scrub_disable();
1792
1793        DBG("L2CACHE Scrub is now disabled\n");
1794
1795        return L2CACHE_ERR_OK;
1796}
1797
1798int l2cache_scrub_line(int way, int index)
1799{
1800        struct l2cache_priv * priv = l2cachepriv;
1801        unsigned int scrub;
1802
1803        if (priv == NULL){
1804                DBG("L2CACHE not initialized.\n");
1805                return L2CACHE_ERR_NOINIT;
1806        }
1807
1808        if (!priv->ft_support){
1809                DBG("L2CACHE does not have EDAC support.\n");
1810                return L2CACHE_ERR_ERROR;
1811        }
1812
1813        if ((index < 0) || (index >= priv->index)){
1814                DBG("L2CACHE only has %d lines.\n", priv->index);
1815                return L2CACHE_ERR_EINVAL;
1816        }
1817
1818        if ((way < 0) || (way >= priv->ways)){
1819                DBG("L2CACHE only has %d ways.\n", priv->ways);
1820                return L2CACHE_ERR_EINVAL;
1821        }
1822
1823        /* Check pending bit */
1824        scrub = l2cache_reg_scrub();
1825        if ( (scrub & L2C_SCRUB_PEN) || (scrub & L2C_SCRUB_EN) ){
1826                DBG("L2CACHE already scrubbing.\n");
1827                return L2CACHE_ERR_ERROR;
1828        }
1829
1830        /* Scrub line */
1831        l2cache_reg_scrub_line(way, index);
1832
1833        DBG("L2CACHE Scrub line [%d,%d]\n",way,index);
1834
1835        return L2CACHE_ERR_OK;
1836}
1837
1838int l2cache_writethrough(int flush)
1839{
1840        struct l2cache_priv * priv = l2cachepriv;
1841        int enabled;
1842        int ret;
1843
1844        if (priv == NULL){
1845                DBG("L2CACHE not initialized.\n");
1846                return L2CACHE_ERR_NOINIT;
1847        }
1848
1849        /* Check that L2C is enabled */
1850        enabled = l2cache_ctrl_status();
1851
1852        /* Disable&Flush L2C */
1853        ret = l2cache_disable(flush);
1854        if (ret < 0){
1855                return ret;
1856        }
1857
1858        /* Configure writethrough */
1859        l2cache_reg_ctrl_writep(1);
1860
1861        /* Enable cache again */
1862        if (enabled){
1863                l2cache_reg_ctrl_enable();
1864        }
1865
1866        DBG("L2CACHE now is writethrough\n");
1867
1868        return L2CACHE_ERR_OK;
1869}
1870
1871int l2cache_writeback(int flush)
1872{
1873        struct l2cache_priv * priv = l2cachepriv;
1874        int enabled;
1875        int ret;
1876
1877        if (priv == NULL){
1878                DBG("L2CACHE not initialized.\n");
1879                return L2CACHE_ERR_NOINIT;
1880        }
1881
1882        /* Check that L2C is enabled */
1883        enabled = l2cache_ctrl_status();
1884
1885        /* Disable&Flush L2C */
1886        ret = l2cache_disable(flush);
1887        if (ret < 0){
1888                return ret;
1889        }
1890
1891        /* Configure writeback */
1892        l2cache_reg_ctrl_writep(0);
1893
1894        /* Enable cache again */
1895        if (enabled){
1896                l2cache_reg_ctrl_enable();
1897        }
1898
1899        DBG("L2CACHE now is writeback\n");
1900
1901        return L2CACHE_ERR_OK;
1902}
1903
1904int l2cache_replacement(int options, int flush)
1905{
1906        struct l2cache_priv * priv = l2cachepriv;
1907        int enabled;
1908        int ret;
1909        int way;
1910
1911        if (priv == NULL){
1912                DBG("L2CACHE not initialized.\n");
1913                return L2CACHE_ERR_NOINIT;
1914        }
1915
1916        /* Check that L2C is enabled */
1917        enabled = l2cache_ctrl_status();
1918
1919        /* Disable&Flush L2C */
1920        ret = l2cache_disable(flush);
1921        if (ret < 0){
1922                return ret;
1923        }
1924
1925        if ( (options & 0x3) == L2CACHE_OPTIONS_REPL_MASTERIDX_IDX){
1926                /* Set iway */
1927                way = (options >> 2) & 0x3;
1928                l2cache_reg_ctrl_iway(way);
1929        }
1930
1931        /* Configure writeback */
1932        l2cache_reg_ctrl_repl(options & 0x3);
1933
1934        /* Enable cache again */
1935        if (enabled){
1936                l2cache_reg_ctrl_enable();
1937        }
1938
1939        DBG("L2CACHE replacement set to %d\n", (options & 0x3));
1940
1941        return L2CACHE_ERR_OK;
1942
1943}
1944
1945int l2cache_isr_register(l2cache_isr_t isr, void * arg, int options)
1946{
1947        struct l2cache_priv *priv = l2cachepriv;
1948        unsigned int mask;
1949
1950        if (priv == NULL){
1951                DBG("L2CACHE not initialized.\n");
1952                return L2CACHE_ERR_NOINIT;
1953        }
1954
1955        if (isr == NULL){
1956                DBG("L2CACHE wrong isr.\n");
1957                return L2CACHE_ERR_EINVAL;
1958        }
1959
1960        /* Get mask */
1961        mask = 0 |
1962                ((options & L2CACHE_INTERRUPT_BACKENDERROR)? L2C_ERROR_IRQM_BCKEND:0) |
1963                ((options & L2CACHE_INTERRUPT_WPROTHIT)? L2C_ERROR_IRQM_WPROT:0) |
1964                ((options & L2CACHE_INTERRUPT_CORRERROR)? L2C_ERROR_IRQM_CORR:0) |
1965                ((options & L2CACHE_INTERRUPT_UNCORRERROR)? L2C_ERROR_IRQM_UNCORR:0);
1966
1967        /* Clear previous interrupts and mask them*/
1968        l2cache_reg_error_reset();
1969        l2cache_reg_error_irqmask(0);
1970
1971        /* First time registering an ISR */
1972        if (priv->isr == NULL){
1973                /* Install and Enable L2CACHE interrupt handler */
1974                drvmgr_interrupt_register(priv->dev, 0, priv->devname, l2cache_isr, 
1975                                priv);
1976        }
1977
1978        /* Install user ISR */
1979        priv->isr=isr;
1980        priv->isr_arg=arg;
1981
1982        /* Now it is safe to unmask interrupts */
1983        l2cache_reg_error_irqmask(mask);
1984
1985        return L2CACHE_ERR_OK;
1986}
1987
1988int l2cache_isr_unregister(void)
1989{
1990        struct l2cache_priv *priv = l2cachepriv;
1991
1992        if (priv == NULL){
1993                DBG("L2CACHE not initialized.\n");
1994                return L2CACHE_ERR_NOINIT;
1995        }
1996
1997        if (priv->isr == NULL){
1998                DBG("L2CACHE wrong isr.\n");
1999                return L2CACHE_ERR_EINVAL;
2000        }
2001
2002        /* Clear previous interrupts and mask them*/
2003        l2cache_reg_error_reset();
2004        l2cache_reg_error_irqmask(0);
2005
2006        /* Uninstall and disable L2CACHE interrupt handler */
2007        drvmgr_interrupt_unregister(priv->dev, 0, l2cache_isr, priv);
2008
2009        /* Uninstall user ISR */
2010        priv->isr=NULL;
2011        priv->isr_arg=NULL;
2012
2013        return L2CACHE_ERR_OK;
2014}
2015
2016int l2cache_interrupt_unmask(int options)
2017{
2018        struct l2cache_priv *priv = l2cachepriv;
2019        unsigned int mask, irq;
2020
2021        if (priv == NULL){
2022                DBG("L2CACHE not initialized.\n");
2023                return L2CACHE_ERR_NOINIT;
2024        }
2025
2026        if (priv->isr == NULL){
2027                DBG("L2CACHE wrong isr.\n");
2028                return L2CACHE_ERR_EINVAL;
2029        }
2030
2031        /* Unmask interrupts in  L2CACHE */
2032        mask = 0 |
2033                ((options & L2CACHE_INTERRUPT_BACKENDERROR)? L2C_ERROR_IRQM_BCKEND:0) |
2034                ((options & L2CACHE_INTERRUPT_WPROTHIT)? L2C_ERROR_IRQM_WPROT:0) |
2035                ((options & L2CACHE_INTERRUPT_CORRERROR)? L2C_ERROR_IRQM_CORR:0) |
2036                ((options & L2CACHE_INTERRUPT_UNCORRERROR)? L2C_ERROR_IRQM_UNCORR:0);
2037
2038        /* Clear previous interrupts*/
2039        l2cache_reg_error_reset();
2040
2041        /* Get previous mask */
2042        irq = ((l2cache_reg_error() & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT);
2043
2044        /* Set new mask */
2045        l2cache_reg_error_irqmask(irq | mask);
2046
2047        return L2CACHE_ERR_OK;
2048}
2049
2050int l2cache_interrupt_mask(int options)
2051{
2052        struct l2cache_priv *priv = l2cachepriv;
2053        unsigned int mask, irq;
2054
2055        if (priv == NULL){
2056                DBG("L2CACHE not initialized.\n");
2057                return L2CACHE_ERR_NOINIT;
2058        }
2059
2060        /* Mask interrupts in  L2CACHE */
2061        mask = 0 |
2062                ((options & L2CACHE_INTERRUPT_BACKENDERROR)? L2C_ERROR_IRQM_BCKEND:0) |
2063                ((options & L2CACHE_INTERRUPT_WPROTHIT)? L2C_ERROR_IRQM_WPROT:0) |
2064                ((options & L2CACHE_INTERRUPT_CORRERROR)? L2C_ERROR_IRQM_CORR:0) |
2065                ((options & L2CACHE_INTERRUPT_UNCORRERROR)? L2C_ERROR_IRQM_UNCORR:0);
2066
2067        /* Clear previous interrupts */
2068        l2cache_reg_error_reset();
2069
2070        /* Get previous mask */
2071        irq = ((l2cache_reg_error() & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT);
2072
2073        /* Set new mask */
2074        l2cache_reg_error_irqmask(irq & ~(mask));
2075
2076        return L2CACHE_ERR_OK;
2077}
2078
2079int l2cache_error_status(uint32_t * addr, uint32_t * status)
2080{
2081        struct l2cache_priv *priv = l2cachepriv;
2082        unsigned int sts;
2083        unsigned int erraddr;
2084
2085        if (priv == NULL){
2086                DBG("L2CACHE not initialized.\n");
2087                return L2CACHE_ERR_NOINIT;
2088        }
2089
2090        /* Get error register */
2091        sts = priv->regs->error_status_control;
2092        erraddr = priv->regs->error_addr;
2093
2094        /* Check if an error occurred */
2095        if (sts & L2C_ERROR_VALID){
2096                /* Reset error register */
2097                l2cache_reg_error_reset();
2098
2099                /* Update user variables if needed */
2100                if (addr != NULL){
2101                        *addr = (erraddr & ~(0x1f));
2102                }
2103
2104                if(status != NULL){
2105                        *status = sts;
2106                }
2107
2108                /* Return status */
2109                if (sts & L2C_ERROR_MULTI){
2110                        return L2CACHE_STATUS_MULTIPLEERRORS;
2111                }else{
2112                        return L2CACHE_STATUS_NEWERROR;
2113                }
2114        }else{
2115                /* Return status */
2116                return L2CACHE_STATUS_NOERROR;
2117        }
2118}
Note: See TracBrowser for help on using the repository browser.