source: rtems/bsps/shared/grlib/l2c/l2c.c

Last change on this file was 5d5b9ee, checked in by Daniel Cederman <cederman@…>, on 11/14/22 at 09:59:08

bsps/shared/grlib: Change license to BSD-2 for files with Gaisler copyright

This patch changes the license to BSD-2 for all source files where the
copyright is held by Aeroflex Gaisler, Cobham Gaisler, or Gaisler Research.
Some files also includes copyright right statements from OAR and/or
embedded Brains in addition to Gaisler.

Updates #3053.

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