source: rtems/bsps/shared/grlib/iommu/griommu.c @ 7eb606d3

Last change on this file since 7eb606d3 was 7eb606d3, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 22, 2018 at 5:31:04 PM

grlib: Move source files

Update #3678.

  • Property mode set to 100644
File size: 33.6 KB
Line 
1/*
2 *  GRIOMMU Driver Interface
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 <bsp.h>
20#include <grlib/griommu.h>
21
22#include <grlib/grlib_impl.h>
23
24/*#define STATIC*/
25#define STATIC static
26
27/*#define INLINE*/
28#define INLINE inline
29
30#define UNUSED __attribute__((unused))
31
32/*#define DEBUG 1*/
33
34#ifdef DEBUG
35#define DBG(x...) printf(x)
36#else
37#define DBG(x...)
38#endif
39
40/*
41 * GRIOMMU CAP0 register fields
42 */
43#define CAP0_A (0x1 << CAP0_A_BIT)
44#define CAP0_AC (0x1 << CAP0_AC_BIT)
45#define CAP0_CA (0x1 << CAP0_CA_BIT)
46#define CAP0_CP (0x1 << CAP0_CP_BIT)
47#define CAP0_NARB (0xf << CAP0_NARB_BIT)
48#define CAP0_CS (0x1 << CAP0_CS_BIT)
49#define CAP0_FT (0x3 << CAP0_FT_BIT)
50#define CAP0_ST (0x1 << CAP0_ST_BIT)
51#define CAP0_I (0x1 << CAP0_I_BIT)
52#define CAP0_IT (0x1 << CAP0_IT_BIT)
53#define CAP0_IA (0x1 << CAP0_IA_BIT)
54#define CAP0_IP (0x1 << CAP0_IP_BIT)
55#define CAP0_MB (0x1 << CAP0_MB_BIT)
56#define CAP0_GRPS (0xf << CAP0_GRPS_BIT)
57#define CAP0_MSTS (0xf << CAP0_MSTS_BIT)
58
59#define CAP0_A_BIT 31
60#define CAP0_AC_BIT 30
61#define CAP0_CA_BIT 29
62#define CAP0_CP_BIT 28
63#define CAP0_NARB_BIT 20
64#define CAP0_CS_BIT 19
65#define CAP0_FT_BIT 17
66#define CAP0_ST_BIT 16
67#define CAP0_I_BIT 15
68#define CAP0_IT_BIT 14
69#define CAP0_IA_BIT 13
70#define CAP0_IP_BIT 12
71#define CAP0_MB_BIT 8
72#define CAP0_GRPS_BIT 4
73#define CAP0_MSTS_BIT 0
74
75/*
76 * GRIOMMU CAP1 register fields
77 */
78#define CAP1_CADDR (0xfff << CAP1_CADDR_BIT)
79#define CAP1_CMASK (0xf << CAP1_CMASK_BIT)
80#define CAP1_CTAGBITS (0xff << CAP1_CTAGBITS_BIT)
81#define CAP1_CISIZE (0x7 << CAP1_CISIZE_BIT)
82#define CAP1_CLINES (0x1f << CAP1_CLINES_BIT)
83
84#define CAP1_CADDR_BIT 20
85#define CAP1_CMASK_BIT 16
86#define CAP1_CTAGBITS_BIT 8
87#define CAP1_CISIZE_BIT 5
88#define CAP1_CLINES_BIT 0
89
90/*
91 * GRIOMMU CTRL register fields
92 * DEFINED IN HEADER FILE
93 */
94
95/*
96 * GRIOMMU FLUSH register fields
97 */
98#define FLUSH_FGRP (0xf << FLUSH_FGRP_BIT)
99#define FLUSH_GF (0x1 << FLUSH_GF_BIT)
100#define FLUSH_F (0x1 << FLUSH_F_BIT)
101
102#define FLUSH_FGRP_BIT 4
103#define FLUSH_GF_BIT 1
104#define FLUSH_F_BIT 0
105
106/*
107 * GRIOMMU STATUS register fields
108 */
109#define STS_PE (0x1 << STS_PE_BIT)
110#define STS_DE (0x1 << STS_DE_BIT)
111#define STS_FC (0x1 << STS_FC_BIT)
112#define STS_FL (0x1 << STS_FL_BIT)
113#define STS_AD (0x1 << STS_AD_BIT)
114#define STS_TE (0x1 << STS_TE_BIT)
115#define STS_ALL (STS_PE | STS_DE | STS_FC | STS_FL | STS_AD | STS_TE)
116
117#define STS_PE_BIT 5
118#define STS_DE_BIT 4
119#define STS_FC_BIT 3
120#define STS_FL_BIT 2
121#define STS_AD_BIT 1
122#define STS_TE_BIT 0
123
124/*
125 * GRIOMMU IMASK register fields
126 */
127#define IMASK_PEI (0x1 << IMASK_PEI_BIT)
128#define IMASK_FCI (0x1 << IMASK_FCI_BIT)
129#define IMASK_FLI (0x1 << IMASK_FLI_BIT)
130#define IMASK_ADI (0x1 << IMASK_ADI_BIT)
131#define IMASK_TEI (0x1 << IMASK_TEI_BIT)
132#define IMASK_ALL (IMASK_PEI | IMASK_FCI | IMASK_FLI | IMASK_ADI | IMASK_TEI)
133
134#define IMASK_PEI_BIT 5
135#define IMASK_FCI_BIT 3
136#define IMASK_FLI_BIT 2
137#define IMASK_ADI_BIT 1
138#define IMASK_TEI_BIT 0
139
140/*
141 * GRIOMMU MASTER register fields
142 */
143/* DEFINED IN HEADER FILE
144#define MASTER_VENDOR (0xff << MASTER_VENDOR_BIT)
145#define MASTER_DEVICE (0xfff << MASTER_DEVICE_BIT)
146#define MASTER_BS (0x1 << MASTER_BS_BIT)
147#define MASTER_GROUP (0xf << MASTER_GROUP_BIT)
148
149#define MASTER_VENDOR_BIT 24
150#define MASTER_DEVICE_BIT 12
151#define MASTER_BS_BIT 4
152#define MASTER_GROUP_BIT 0
153*/
154
155#define MASTER_BS_BUS0 0
156#define MASTER_BS_BUS1 MASTER_BS
157
158/*
159 * GRIOMMU GROUP register fields
160 */
161#define GRP_BASE (0xfffffff << GRP_BASE_BIT)
162#define GRP_P (0x1 << GRP_P_BIT)
163#define GRP_AG (0x1 << GRP_AG_BIT)
164
165#define GRP_BASE_BIT 4
166#define GRP_P_BIT 1
167#define GRP_AG_BIT 0
168
169
170#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val))
171#define REG_READ(addr) (*(volatile unsigned int *)(addr))
172
173/*
174 * GRIOMMU APB Register MAP
175 */
176struct griommu_regs {
177        volatile unsigned int cap0;                     /* 0x00 - Capability 0 */
178        volatile unsigned int cap1;                     /* 0x04 - Capability 1 */
179        volatile unsigned int cap2;                     /* 0x08 - Capability 2 */
180        volatile unsigned int resv1;            /* 0x0c - Reserved */
181        volatile unsigned int ctrl;                     /* 0x10 - Control */
182        volatile unsigned int flush;            /* 0x14 - TLB/cache flush */
183        volatile unsigned int status;           /* 0x18 - Status */
184        volatile unsigned int imask;            /* 0x1c - Interrupt mask */
185        volatile unsigned int ahbstat;          /* 0x20 - AHB Failing Access */
186        volatile unsigned int resv2[7];         /* 0x24-0x3c - Reserved. No access */
187        volatile unsigned int master[16];       /* 0x40-0x7c - Master configuration */
188        volatile unsigned int grp_ctrl[16]; /* 0x80-0xbc - Group control */
189        volatile unsigned int diag_ca;          /* 0xc0 - Diagnostic cache access */
190        volatile unsigned int diag_cad[8];      /* 0xc4-0xe0 - Diagnostic cache data */
191        volatile unsigned int diag_cat;         /* 0xe4 - Diagnostic cache tag */
192        volatile unsigned int ei_data;          /* 0xe8 - Data RAM error injection */
193        volatile unsigned int ei_tag;           /* 0xec - Tag RAM error injection */
194        volatile unsigned int resv3[4];         /* 0xf0-0xfc - Reserved. No access */
195        volatile unsigned int asmpctrl[16]; /* 0x100-0x13c - ASMP access control */
196};
197
198#define DEVNAME_LEN 9
199/*
200 * GRIOMMU Driver private data struture
201 */
202struct griommu_priv {
203        struct drvmgr_dev       *dev;
204        char devname[DEVNAME_LEN];
205        /* GRIOMMU control registers */
206        struct griommu_regs     *regs;
207
208        /* GRIOMMU capabilities */
209        int apv;
210        int apv_cache;
211        int apv_cache_addr;
212        int conf_pagesize;
213
214        int groups;
215        int masters;
216
217        /* GRIOMMU page size */
218        int pagesize;
219
220        /* GRIOMMU APV cache */
221        int cache_enabled;
222        int group_addressing;
223
224        /* User defined ISR */
225        griommu_isr_t isr;
226        void *isr_arg;
227};
228
229/*
230 * GRIOMMU internal prototypes
231 */
232/* -Register access functions */
233STATIC INLINE unsigned int griommu_reg_cap0(void);
234STATIC INLINE unsigned int griommu_reg_cap1(void);
235STATIC INLINE unsigned int griommu_reg_ctrl(void);
236STATIC INLINE int griommu_reg_ctrl_set(unsigned int val);
237STATIC INLINE int griommu_reg_flush_set(unsigned int val);
238STATIC INLINE unsigned int griommu_reg_status(void);
239STATIC INLINE int griommu_reg_status_clear(unsigned int val);
240STATIC INLINE unsigned int griommu_reg_imask(void);
241STATIC INLINE int griommu_reg_imask_set(int mask);
242STATIC INLINE unsigned int griommu_reg_ahbfas(void);
243STATIC INLINE unsigned int griommu_reg_master(int master);
244STATIC INLINE int griommu_reg_master_set(int master, unsigned int val);
245STATIC INLINE unsigned int griommu_reg_group(int group);
246STATIC INLINE int griommu_reg_group_set(int group, unsigned int val);
247
248/* APV helper functions */
249STATIC void griommu_apv_set_word(unsigned int * wordptr, int startbitidx, 
250                int nbits, unsigned int val);
251STATIC int griommu_apv_set(void * apv, int index, int size, unsigned int val);
252
253/* -Init function called by drvmgr */
254int griommu_init1(struct drvmgr_dev *dev);
255STATIC int griommu_init(struct griommu_priv *priv);
256
257
258/* -IRQ handler */
259void griommu_isr(void *arg);
260
261/*
262 * GRIOMMU static members
263 */
264static struct griommu_priv *griommupriv = NULL;
265
266/* GRIOMMU DRIVER */
267
268struct drvmgr_drv_ops griommu_ops = 
269{
270        .init = {griommu_init1, NULL, NULL, NULL},
271        .remove = NULL,
272        .info = NULL
273};
274
275struct amba_dev_id griommu_ids[] = 
276{
277        {VENDOR_GAISLER, GAISLER_GRIOMMU},
278        {0, 0}          /* Mark end of table */
279};
280
281struct amba_drv_info griommu_info =
282{
283        {
284                DRVMGR_OBJ_DRV,                                 /* Driver */
285                NULL,                           /* Next driver */
286                NULL,                           /* Device list */
287                DRIVER_AMBAPP_GAISLER_GRIOMMU_ID,/* Driver ID */
288                "GRIOMMU_DRV",                  /* Driver Name */
289                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
290                &griommu_ops,
291                NULL,                           /* Funcs */
292                0,                              /* No devices yet */
293                sizeof(struct griommu_priv),    /* Make drvmgr alloc private */
294        },
295        &griommu_ids[0]
296};
297
298void griommu_register_drv(void)
299{
300        DBG("Registering GRIOMMU driver\n");
301        drvmgr_drv_register(&griommu_info.general);
302}
303
304/* Initializes the GRIOMMU core and driver
305 *
306 * Return values
307 *      0                         Successful initalization
308 */
309STATIC int griommu_init(struct griommu_priv *priv)
310{
311        struct ambapp_ahb_info *ahb;
312        struct amba_dev_info *ainfo = priv->dev->businfo;
313
314        /* Find GRIOMMU core from Plug&Play information */
315        ahb = ainfo->info.ahb_slv;
316
317        /* Found GRIOMMU core, init private structure */
318        priv->regs = (struct griommu_regs *)ahb->start[0];
319
320        /* Mask all interrupts */
321        griommu_reg_imask_set(0);
322
323        /* Initialize GRIOMMU capabilities */
324        uint32_t cap0 = griommu_reg_cap0();
325        priv->apv = (cap0 & CAP0_A) >> CAP0_A_BIT;
326        priv->apv_cache = (cap0 & CAP0_AC) >> CAP0_AC_BIT;
327        priv->apv_cache_addr = (cap0 & CAP0_CA) >> CAP0_CA_BIT;
328        priv->conf_pagesize = (cap0 & CAP0_CS) >> CAP0_CS_BIT;
329        priv->groups = ((cap0 & CAP0_GRPS) >> CAP0_GRPS_BIT) + 1;
330        priv->masters = ((cap0 & CAP0_MSTS) >> CAP0_MSTS_BIT) + 1;
331
332        /* Get GRIOMMU pagesize */
333        uint32_t ctrl = griommu_reg_ctrl();
334        if (priv->conf_pagesize){
335                priv->pagesize = (4*1024 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT));
336        }else{
337                priv->pagesize = 4*1024;
338        }
339        priv->cache_enabled = (ctrl & CTRL_CE);
340        priv->group_addressing = (ctrl & CTRL_GS);
341
342        DBG("GRIOMMU Capabilities: APV=%d, APVC=%d, APVCA=%d, CS=%d, "
343                        "GRPS=%d, MSTS=%d\n",
344                        priv->apv, priv->apv_cache, priv->apv_cache_addr, 
345                        priv->conf_pagesize, priv->groups, priv->masters);
346        DBG("GRIOMMU driver initialized\n");
347
348        return 0;
349}
350
351/* Called when a core is found with the AMBA device and vendor ID
352 * given in griommu_ids[]. IRQ, Console does not work here
353 */
354int griommu_init1(struct drvmgr_dev *dev)
355{
356        int status;
357        struct griommu_priv *priv;
358
359        DBG("GRIOMMU[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
360
361        if (griommupriv) {
362                DBG("Driver only supports one GRIOMMU core\n");
363                return DRVMGR_FAIL;
364        }
365
366        priv = dev->priv;
367        if (!priv)
368                return DRVMGR_NOMEM;
369
370        priv->dev = dev;
371        strncpy(&priv->devname[0], "griommu0", DEVNAME_LEN);
372        griommupriv = priv;
373
374        /* Initialize GRIOMMU Hardware */
375        status = griommu_init(priv);
376        if (status) {
377                printk("Failed to initialize griommu driver %d\n", status);
378                return -1;
379        }
380
381        return DRVMGR_OK;
382}
383
384STATIC INLINE unsigned int griommu_reg_cap0(void)
385{
386        struct griommu_priv *priv = griommupriv;
387
388        return REG_READ(&priv->regs->cap0);
389}
390
391STATIC INLINE unsigned int griommu_reg_cap1(void)
392{
393        struct griommu_priv *priv = griommupriv;
394
395        return REG_READ(&priv->regs->cap1);
396}
397
398STATIC INLINE unsigned int griommu_reg_ctrl(void)
399{
400        struct griommu_priv *priv = griommupriv;
401
402        return REG_READ(&priv->regs->ctrl);
403}
404
405STATIC INLINE int griommu_reg_ctrl_set(unsigned int val)
406{
407        struct griommu_priv *priv = griommupriv;
408
409        REG_WRITE(&priv->regs->ctrl, val);
410        return 0;
411}
412
413STATIC INLINE int griommu_reg_flush_set(unsigned int val)
414{
415        struct griommu_priv *priv = griommupriv;
416
417        REG_WRITE(&priv->regs->flush, val);
418        return 0;
419}
420
421STATIC INLINE unsigned int griommu_reg_status(void)
422{
423        struct griommu_priv *priv = griommupriv;
424
425   return REG_READ(&priv->regs->status);
426}
427
428STATIC INLINE int griommu_reg_status_clear(unsigned int val)
429{
430        struct griommu_priv *priv = griommupriv;
431
432        /* Clear errors */
433        REG_WRITE(&priv->regs->status, (val & STS_ALL));
434        return 0;
435}
436
437STATIC INLINE unsigned int griommu_reg_imask(void)
438{
439        struct griommu_priv *priv = griommupriv;
440
441   return REG_READ(&priv->regs->imask);
442}
443
444STATIC INLINE int griommu_reg_imask_set(int mask)
445{
446        struct griommu_priv *priv = griommupriv;
447
448        /* Clear errors */
449        REG_WRITE(&priv->regs->imask, (mask & IMASK_ALL));
450        return 0;
451}
452
453STATIC INLINE unsigned int griommu_reg_ahbfas(void)
454{
455        struct griommu_priv *priv = griommupriv;
456
457   return REG_READ(&priv->regs->ahbstat);
458}
459
460STATIC INLINE int griommu_reg_master_set(int master, unsigned int val)
461{
462        struct griommu_priv *priv = griommupriv;
463
464        /* Change master conf */
465        REG_WRITE(&priv->regs->master[master], val);
466        return 0;
467}
468
469STATIC INLINE unsigned int griommu_reg_master(int master)
470{
471        struct griommu_priv *priv = griommupriv;
472
473        return REG_READ(&priv->regs->master[master]);
474}
475
476STATIC INLINE unsigned int griommu_reg_group(int group)
477{
478        struct griommu_priv *priv = griommupriv;
479
480        return REG_READ(&priv->regs->grp_ctrl[group]);
481}
482
483STATIC INLINE int griommu_reg_group_set(int group, unsigned int val)
484{
485        struct griommu_priv *priv = griommupriv;
486
487        REG_WRITE(&priv->regs->grp_ctrl[group], val);
488        return 0;
489}
490
491STATIC void griommu_apv_set_word(unsigned int * wordptr, int startbitidx, 
492                int nbits, unsigned int val)
493{
494        unsigned int mask;
495        unsigned int word = *wordptr;
496        int endbitidx = startbitidx + nbits - 1;
497
498        /* Set initial mask */
499        mask = 0xffffffff;
500
501        /* Adjust mask for the starting bit */
502        mask >>= startbitidx;
503
504        /* Adjust mask for the end bit */
505        mask >>= (31 - endbitidx);
506        mask <<= (31 - endbitidx);
507
508        DBG("Setting word: startbitdx=%d, endbitidx=%d, mask=0x%02x",
509                        startbitidx, endbitidx, (unsigned int) mask);
510
511        /* Clear written bits with mask */
512        word &= ~(mask);
513
514        /* Set bits in val with mask */
515        mask &= val;
516        word |= mask;
517
518        DBG(", old word=0x%08x, new word=0x%08x\n",*wordptr, word);
519
520        /* Write word */
521        *wordptr=word;
522}
523
524/* Set certains bits of the APV to val */
525STATIC int griommu_apv_set(void * apv, int index, int size, unsigned int val)
526{
527        unsigned int * words = (unsigned int *) apv;
528        int len = size;
529        int wordidx = (index/32);
530        int startbit = (index % 32);
531        int nbits;
532        int nwords;
533
534        /* First incomplete word is a special case */
535        if (startbit != 0){
536                /* Get how many bits are we changing in this word */
537                if (startbit + len  < 32){
538                        nbits = len;
539                }else{
540                        nbits = 32 - startbit;
541                }
542                griommu_apv_set_word(&words[wordidx], startbit, nbits, val);
543                DBG("First word: wordidx=%d, startbit=%d, bits=%d, val=0x%08x\n", 
544                                wordidx, startbit, nbits, words[wordidx]);
545
546                /* Update wordidx and len */
547                len = len - nbits;
548                wordidx++;
549        }
550
551        /* Write all complete full words */
552        if (len != 0){
553                nwords = (len/32);
554                memset((void *) &words[wordidx], val, nwords*4);
555                DBG("Middle words: wordidx=%d, nwords=%d\n", wordidx, nwords);
556                /* Update wordidx and len*/
557                wordidx = wordidx + nwords;
558                len = len - nwords*32;
559        }
560
561        /* Last word is a special case */
562        if (len != 0){
563                nbits = len;
564                griommu_apv_set_word(&words[wordidx], 0, nbits, val);
565                DBG("First word: wordidx=%d, startbit=%d, bits=%d, val=0x%08x\n", 
566                                wordidx, 0, nbits, words[wordidx]);
567                /* Update len */
568                len = len - (nbits);
569        }
570
571        return GRIOMMU_ERR_OK;
572}
573
574/* GRIOMMU Interrupt handler, called when there may be a GRIOMMU interrupt.
575 */
576void griommu_isr(void *arg)
577{
578        struct griommu_priv *priv = arg;
579        unsigned int sts = griommu_reg_status();
580        unsigned int mask = griommu_reg_imask();
581        unsigned int access = griommu_reg_ahbfas();
582
583        /* Make sure that the interrupt is pending and unmasked,
584         * otherwise it migth have been other core
585         * sharing the same interrupt line */
586        if ((sts & STS_ALL) & (mask & IMASK_ALL)){
587                /* Reset error status */
588                griommu_reg_status_clear(sts);
589                /* Execute user IRQ (ther will always be one ISR */
590                (priv->isr)(priv->isr_arg, access, sts);
591        }
592}
593
594/* Setup IOMMU master:
595 */
596int griommu_master_setup(int master, int group, int options)
597{
598        struct griommu_priv * priv = griommupriv;
599
600        if (priv == NULL){
601                DBG("GRIOMMU not initialized.\n");
602                return GRIOMMU_ERR_NOINIT;
603        }
604
605        if ((master < 0) || (master >= priv->masters)){
606                DBG("Wrong master id.\n");
607                return GRIOMMU_ERR_EINVAL;
608        }
609
610        if ((group < 0) || (group >= priv->groups)){
611                DBG("Wrong group id.\n");
612                return GRIOMMU_ERR_EINVAL;
613        }
614
615        griommu_reg_master_set(master,
616                        ((options & GRIOMMU_OPTIONS_BUS1)? MASTER_BS_BUS1: MASTER_BS_BUS0)|
617                        ((group << MASTER_GROUP_BIT) & MASTER_GROUP)
618                        );
619
620        DBG("IOMMU master setup: master %d, traffic routed %s, group %d\n",
621                        master,
622                        (options & GRIOMMU_OPTIONS_BUS1) ? 
623                                        "to Secondary bus":"to Primary bus",
624                        group);
625
626        return GRIOMMU_ERR_OK;
627}
628
629
630/* Get IOMMU master info:
631 */
632int griommu_master_info(int master, uint32_t * info)
633{
634        struct griommu_priv * priv = griommupriv;
635
636        if (priv == NULL){
637                DBG("GRIOMMU not initialized.\n");
638                return GRIOMMU_ERR_NOINIT;
639        }
640
641        if ((master < 0) || (master >= priv->masters)){
642                DBG("Wrong master id.\n");
643                return GRIOMMU_ERR_EINVAL;
644        }
645
646        if (info == NULL){
647                DBG("Wrong pointer.\n");
648                return GRIOMMU_ERR_EINVAL;
649        }
650
651        /* Get master */
652        *info = griommu_reg_master(master);
653
654        return GRIOMMU_ERR_OK;
655}
656
657/* Find IOMMU master:
658 */
659int griommu_master_find(int vendor, int device, int instance)
660{
661        struct griommu_priv * priv = griommupriv;
662        int i, gotvendor, gotdevice;
663        unsigned int master;
664        int found;
665
666        if (priv == NULL){
667                DBG("GRIOMMU not initialized.\n");
668                return GRIOMMU_ERR_NOINIT;
669        }
670
671        /* Find which master */
672        found=0;
673        for (i=0; i< priv->masters; i++){
674                master = griommu_reg_master(i);
675                gotvendor = (master & MASTER_VENDOR) >> MASTER_VENDOR_BIT;
676                gotdevice = (master & MASTER_DEVICE) >> MASTER_DEVICE_BIT;
677                if ((gotvendor == vendor) && (gotdevice == device)){
678                        if(found == instance){
679                                DBG("Found master %d: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), "
680                                        "Instance=%d\n",
681                                        i,
682                                        ambapp_vendor_id2str(vendor), vendor,
683                                        ambapp_device_id2str(vendor,device), device, instance
684                                        );
685                                return i;
686                        }
687                        found++;
688                }
689        }
690
691        DBG("Master not found: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), "
692                "Instance=%d\n",
693                ambapp_vendor_id2str(vendor), vendor,
694                ambapp_device_id2str(vendor,device), device, instance
695                );
696        return GRIOMMU_ERR_NOTFOUND;
697}
698
699/* Setup IOMMU:
700 */
701int griommu_setup(int options)
702{
703        struct griommu_priv * priv = griommupriv;
704        unsigned int ctrl;
705
706        if (priv == NULL){
707                DBG("GRIOMMU not initialized.\n");
708                return GRIOMMU_ERR_NOINIT;
709        }
710
711        /* Check Cache */
712        if (options & GRIOMMU_OPTIONS_CACHE_ENABLE) {
713                if (priv->apv_cache){
714                        /* Flush cache */
715                        griommu_reg_flush_set(FLUSH_F);
716                        priv->cache_enabled = 1;
717                }else{
718                        DBG("GRIOMMU APV cache not supported.\n");
719                        return GRIOMMU_ERR_IMPLEMENTED;
720                }
721        }else{
722                priv->cache_enabled = 0;
723        }
724
725        /* Check group addressing */
726        if (options & GRIOMMU_OPTIONS_GROUPADDRESSING_ENABLE){
727                if (priv->apv_cache_addr){
728                        priv->group_addressing = 1;
729                }else{
730                        DBG("GRIOMMU APV cache group addressing not supported.\n");
731                        return GRIOMMU_ERR_IMPLEMENTED;
732                }
733        }else{
734                priv->group_addressing = 0;
735        }
736
737        /* Check pagesize */
738        if ((options & CTRL_PGSZ) != GRIOMMU_OPTIONS_PAGESIZE_4KIB){
739                if (priv->conf_pagesize == 0){
740                        DBG("GRIOMMU Configurable pagesize not supported.\n");
741                        return GRIOMMU_ERR_IMPLEMENTED;
742                }
743        }
744
745        /* Get CTRL IOMMU */
746        ctrl = griommu_reg_ctrl();
747
748        /* Clear used fields */
749        ctrl &= ~(CTRL_CE | CTRL_GS | CTRL_PGSZ | CTRL_LB | 
750                        CTRL_DP | CTRL_AU | CTRL_WP);
751
752        /* Clear not used fields */
753        options &= (CTRL_CE | CTRL_GS | CTRL_PGSZ | CTRL_LB | 
754                        CTRL_DP | CTRL_AU | CTRL_WP);
755
756        /* Set new values */
757        ctrl |= options;
758
759        /* Set CTRL IOMMU */
760        griommu_reg_ctrl_set(ctrl);
761
762        DBG("IOMMU setup: prefetching %s, cache %s, groupaddr %s, "
763                "lookup bus %s, ahb update %s,\nwprot only %s, pagesize %d KiB\n",
764                        ((options & GRIOMMU_OPTIONS_PREFETCH_DISABLE)? 
765                                        "disabled":"enabled"),
766                        ((options & GRIOMMU_OPTIONS_CACHE_ENABLE)? "enabled":"disabled"),
767                        ((options & GRIOMMU_OPTIONS_GROUPADDRESSING_ENABLE)? 
768                                        "enabled":"disabled"),
769                        ((options & GRIOMMU_OPTIONS_LOOKUPBUS_BUS1)? "bus1":"bus0"),
770                        ((options & GRIOMMU_OPTIONS_AHBUPDATE_ENABLE)? 
771                                        "enabled":"disabled"),
772                        ((options & GRIOMMU_OPTIONS_WPROTONLY_ENABLE)? 
773                                        "enabled":"disabled"),
774                        (4 << ((options & GRIOMMU_OPTIONS_PAGESIZE_512KIB) >> 18))
775                );
776
777        return GRIOMMU_ERR_OK;
778}
779
780/* Status IOMMU:
781 */
782int griommu_status(void)
783{
784        struct griommu_priv * priv = griommupriv;
785        unsigned int ctrl;
786
787        if (priv == NULL){
788                DBG("GRIOMMU not initialized.\n");
789                return GRIOMMU_ERR_NOINIT;
790        }
791
792        /* Get CTRL IOMMU */
793        ctrl = griommu_reg_ctrl();
794
795        DBG("IOMMU status: prefetching %s, cache %s, groupaddr %s, "
796                "lookup bus %s, ahb update %s,\nwprot only %s, pagesize %d KiB\n",
797                        ((ctrl & CTRL_DP)? "disabled":"enabled"),
798                        ((ctrl & CTRL_CE)? "enabled":"disabled"),
799                        ((ctrl & CTRL_GS)? "enabled":"disabled"),
800                        ((ctrl & CTRL_LB)? "bus1":"bus0"),
801                        ((ctrl & CTRL_AU)? "enabled":"disabled"),
802                        ((ctrl & CTRL_WP)? "enabled":"disabled"),
803                        (4 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT))
804                );
805
806        return ctrl;
807}
808
809int griommu_isr_register(griommu_isr_t isr, void * arg, int options)
810{
811        struct griommu_priv *priv = griommupriv;
812        unsigned int mask;
813
814        if (priv == NULL){
815                DBG("GRIOMMU not initialized.\n");
816                return GRIOMMU_ERR_NOINIT;
817        }
818
819        if (isr == NULL){
820                DBG("GRIOMMU wrong isr.\n");
821                return GRIOMMU_ERR_EINVAL;
822        }
823
824        /* Get mask */
825        mask = 0 |
826                ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) |
827                ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) |
828                ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) |
829                ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) |
830                ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0);
831
832        /* Clear previous interrupts and mask them*/
833        griommu_reg_status_clear(STS_ALL);
834        griommu_reg_imask_set(0);
835
836        /* First time registering an ISR */
837        if (priv->isr == NULL){
838                /* Install and Enable GRIOMMU interrupt handler */
839                drvmgr_interrupt_register(priv->dev, 0, priv->devname, griommu_isr, 
840                                priv);
841        }
842
843        /* Install user ISR */
844        priv->isr=isr;
845        priv->isr_arg=arg;
846
847        /* Now it is safe to unmask interrupts */
848        griommu_reg_imask_set(mask);
849
850        return GRIOMMU_ERR_OK;
851}
852
853int griommu_isr_unregister(void)
854{
855        struct griommu_priv *priv = griommupriv;
856
857        if (priv == NULL){
858                DBG("GRIOMMU not initialized.\n");
859                return GRIOMMU_ERR_NOINIT;
860        }
861
862        if (priv->isr == NULL){
863                DBG("GRIOMMU wrong isr.\n");
864                return GRIOMMU_ERR_EINVAL;
865        }
866
867        /* Clear previous interrupts and mask them*/
868        griommu_reg_status_clear(STS_ALL);
869        griommu_reg_imask_set(0);
870
871        /* Uninstall and disable GRIOMMU interrupt handler */
872        drvmgr_interrupt_unregister(priv->dev, 0, griommu_isr, priv);
873
874        /* Uninstall user ISR */
875        priv->isr=NULL;
876        priv->isr_arg=NULL;
877
878        return GRIOMMU_ERR_OK;
879}
880
881int griommu_interrupt_unmask(int options)
882{
883        struct griommu_priv *priv = griommupriv;
884        unsigned int mask, irq;
885
886        if (priv == NULL){
887                DBG("GRIOMMU not initialized.\n");
888                return GRIOMMU_ERR_NOINIT;
889        }
890
891        if (priv->isr == NULL){
892                DBG("GRIOMMU wrong isr.\n");
893                return GRIOMMU_ERR_EINVAL;
894        }
895
896        /* Unmask interrupts in GRIOMMU */
897        mask = 0 |
898                ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) |
899                ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) |
900                ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) |
901                ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) |
902                ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0);
903
904        /* Clear previous interrupts*/
905        griommu_reg_status_clear(STS_ALL);
906
907        /* Get previous mask */
908        irq = griommu_reg_imask() & IMASK_ALL;
909
910        /* Set new mask */
911        griommu_reg_imask_set(irq | mask);
912
913        return GRIOMMU_ERR_OK;
914}
915
916int griommu_interrupt_mask(int options)
917{
918        struct griommu_priv *priv = griommupriv;
919        unsigned int mask, irq;
920
921        if (priv == NULL){
922                DBG("GRIOMMU not initialized.\n");
923                return GRIOMMU_ERR_NOINIT;
924        }
925
926        if (priv->isr == NULL){
927                DBG("GRIOMMU wrong isr.\n");
928                return GRIOMMU_ERR_EINVAL;
929        }
930
931        /* Mask interrupts in GRIOMMU */
932        mask = 0 |
933                ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) |
934                ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) |
935                ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) |
936                ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) |
937                ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0);
938
939        /* Clear previous interrupts*/
940        griommu_reg_status_clear(STS_ALL);
941
942        /* Get previous mask */
943        irq = griommu_reg_imask() & IMASK_ALL;
944
945        /* Set new mask */
946        griommu_reg_imask_set(irq & ~(mask));
947
948        return GRIOMMU_ERR_OK;
949}
950
951int griommu_error_status(uint32_t * access)
952{
953        struct griommu_priv *priv = griommupriv;
954        int status;
955
956        if (priv == NULL){
957                DBG("GRIOMMU not initialized.\n");
958                return GRIOMMU_ERR_NOINIT;
959        }
960
961        /* Get status mask */
962        status = griommu_reg_status();
963
964        if (status != 0){
965                /* Update pointed value */
966                if (access != NULL){
967                        *access = griommu_reg_ahbfas();
968                }
969                /* Clear errors */
970                griommu_reg_status_clear(status);
971        }
972
973        return status;
974}
975
976/* Print IOMMU masters
977 * DEBUG function
978 */
979int griommu_print(void)
980{
981        #ifdef DEBUG
982        struct griommu_priv * priv = griommupriv;
983        unsigned int ctrl;
984
985        if (priv == NULL){
986                DBG("GRIOMMU not initialized.\n");
987                return GRIOMMU_ERR_NOINIT;
988        }
989
990        /* Print IOMMU status */
991        ctrl = griommu_reg_ctrl();
992
993        printf("IOMMU status: prefetching %s, lookup bus %s, ahb update %s,\n"
994                        "wprot only %s, pagesize %d KiB\n",
995                        ((ctrl & CTRL_DP)? "disabled":"enabled"),
996                        ((ctrl & CTRL_LB)? "bus1":"bus0"),
997                        ((ctrl & CTRL_AU)? "enabled":"disabled"),
998                        ((ctrl & CTRL_WP)? "enabled":"disabled"),
999                        (4 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT))
1000                );
1001
1002        /* Print each master configuration */
1003        int i, vendor, device, routing;
1004        unsigned int master;
1005        for (i=0; i < priv->masters; i++){
1006                master = griommu_reg_master(i);
1007                vendor = (master & MASTER_VENDOR) >> MASTER_VENDOR_BIT;
1008                device = (master & MASTER_DEVICE) >> MASTER_DEVICE_BIT;
1009                routing = (master & MASTER_BS);
1010                printf("IOMMU master %d: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), "
1011                                "BS=%s\n",
1012                                i,
1013                                ambapp_vendor_id2str(vendor), vendor,
1014                                ambapp_device_id2str(vendor,device), device,
1015                                (routing == MASTER_BS_BUS0? "Primary bus" : "Secondary bus")
1016                                );
1017        }
1018        #endif
1019        return GRIOMMU_ERR_OK;
1020}
1021
1022void * griommu_apv_new(void)
1023{
1024        struct griommu_priv * priv = griommupriv;
1025
1026        if (priv == NULL){
1027                DBG("GRIOMMU not initialized.\n");
1028                return NULL;
1029        }
1030
1031        /* Allocate APV */
1032        unsigned int * orig_ptr = grlib_malloc(
1033                        (GRIOMMU_APV_SIZE/priv->pagesize) + GRIOMMU_APV_ALIGN);
1034        if (orig_ptr == NULL) return NULL;
1035
1036        /* Get the aligned pointer */
1037        unsigned int aligned_ptr = (
1038                ((unsigned int) orig_ptr + GRIOMMU_APV_ALIGN) &
1039                ~(GRIOMMU_APV_ALIGN - 1));
1040
1041        /* Save the original pointer before the aligned pointer */
1042        unsigned int ** tmp_ptr = 
1043                (unsigned int **) (aligned_ptr - sizeof(orig_ptr));
1044        *tmp_ptr= orig_ptr;
1045
1046        /* Return aligned pointer */
1047        return (void *) aligned_ptr;
1048}
1049
1050void griommu_apv_delete(void * apv)
1051{
1052        /* Recover orignal pointer placed just before the aligned pointer */
1053        unsigned int * orig_ptr;
1054        unsigned int ** tmp_ptr =  (unsigned int **) (apv - sizeof(orig_ptr));
1055        orig_ptr = *tmp_ptr;
1056
1057        /* Deallocate memory */
1058        free(orig_ptr);
1059}
1060
1061int griommu_enable(int mode)
1062{
1063        struct griommu_priv * priv = griommupriv;
1064        unsigned int ctrl;
1065
1066        if (priv == NULL){
1067                DBG("GRIOMMU not initialized.\n");
1068                return GRIOMMU_ERR_NOINIT;
1069        }
1070
1071        switch (mode){
1072                case GRIOMMU_MODE_IOMMU:
1073                default:
1074                        DBG("IOMMU mode not implemented in driver.\n");
1075                        return GRIOMMU_ERR_EINVAL;
1076                        break;
1077                case GRIOMMU_MODE_GROUPAPV:
1078                        if (priv->apv == 0){
1079                                DBG("IOMMU APV not supported.\n");
1080                                return GRIOMMU_ERR_IMPLEMENTED;
1081                        }
1082                        /* Enable IOMMU */
1083                        ctrl = (griommu_reg_ctrl() & ~(CTRL_PM));
1084                        griommu_reg_ctrl_set(ctrl | CTRL_PM_APV | CTRL_EN);
1085
1086                        /* Wait until change has effect */
1087                        while((griommu_reg_ctrl() & CTRL_EN)==0){};
1088
1089                        DBG("IOMMU enabled.\n");
1090                        return GRIOMMU_ERR_OK;
1091                        break;
1092        }
1093        return GRIOMMU_ERR_OK;
1094}
1095
1096int griommu_disable(void)
1097{
1098        struct griommu_priv * priv = griommupriv;
1099        unsigned int ctrl;
1100
1101        if (priv == NULL){
1102                DBG("GRIOMMU not initialized.\n");
1103                return GRIOMMU_ERR_NOINIT;
1104        }
1105
1106        /* Disable IOMMU */
1107        ctrl = (griommu_reg_ctrl() & ~(CTRL_EN));
1108        griommu_reg_ctrl_set(ctrl);
1109
1110        /* Wait until change has effect */
1111        while(griommu_reg_ctrl() & CTRL_EN){};
1112
1113        return GRIOMMU_ERR_OK;
1114}
1115
1116int griommu_group_setup(int group, void * apv, int options)
1117{
1118        struct griommu_priv * priv = griommupriv;
1119
1120        if (priv == NULL){
1121                DBG("GRIOMMU not initialized.\n");
1122                return GRIOMMU_ERR_NOINIT;
1123        }
1124
1125        if ((group < 0) || (group >= priv->groups)){
1126                DBG("Wrong group id.\n");
1127                return GRIOMMU_ERR_EINVAL;
1128        }
1129
1130        if ((options < 0) || (options > GRIOMMU_OPTIONS_GROUP_PASSTHROUGH)){
1131                DBG("Wrong options.\n");
1132                return GRIOMMU_ERR_EINVAL;
1133        }
1134
1135        if (options == GRIOMMU_OPTIONS_GROUP_DISABLE){
1136                if ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1)){
1137                        DBG("Wrong pointer.\n");
1138                        return GRIOMMU_ERR_EINVAL;
1139                }
1140
1141                /* Disable GROUP */
1142                griommu_reg_group_set(group, (((unsigned int) apv) & GRP_BASE) | 0);
1143                DBG("GROUP[%d] DISABLED.\n", group);
1144                return GRIOMMU_ERR_OK;
1145        }else if (options == GRIOMMU_OPTIONS_GROUP_PASSTHROUGH){
1146                if ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1)){
1147                        DBG("Wrong pointer.\n");
1148                        return GRIOMMU_ERR_EINVAL;
1149                }
1150
1151                /* Group in passthrough */
1152                griommu_reg_group_set(group, 
1153                                (((unsigned int) apv) & GRP_BASE) | GRP_P | GRP_AG);
1154                DBG("GROUP[%d] set to PASSTHROUGH.\n", group);
1155                return GRIOMMU_ERR_OK;
1156        }else{
1157                if (priv->apv == 0){
1158                        DBG("IOMMU APV not supported.\n");
1159                        return GRIOMMU_ERR_IMPLEMENTED;
1160                }
1161
1162                if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
1163                        DBG("Wrong pointer.\n");
1164                        return GRIOMMU_ERR_EINVAL;
1165                }
1166
1167                /* Set up base and enable */
1168                griommu_reg_group_set(group, 
1169                                (((unsigned int) apv) & GRP_BASE) | GRP_AG);
1170                DBG("GROUP[%d] set to APV (0x%08x).\n", group, (unsigned int) apv);
1171                return GRIOMMU_ERR_OK;
1172        }
1173}
1174
1175int griommu_group_apv_init(int group, int options)
1176{
1177        struct griommu_priv * priv = griommupriv;
1178        void * apv;
1179        int val;
1180        int ret;
1181        size_t len;
1182
1183        /* Flush APV cache if needed.
1184         * This function checks for priv and group being valid.*/
1185        ret = griommu_group_apv_flush(group);
1186        if (ret < 0){
1187                return ret;
1188        }
1189
1190        /* Get APV group */
1191        apv = (void *) (griommu_reg_group(group) & GRP_BASE);
1192
1193        if (apv == NULL){
1194                DBG("Wrong pointer.\n");
1195                return GRIOMMU_ERR_NOTFOUND;
1196        }
1197
1198        /* Get init value (is a char) */
1199        if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1200                val = 0x00;
1201        }else{
1202                val = 0xff;
1203        }
1204
1205        /* Get APV length */
1206        len = GRIOMMU_APV_SIZE/priv->pagesize;
1207
1208        /* Initialize structure */
1209        memset(apv, val, len);
1210
1211        return GRIOMMU_ERR_OK;
1212}
1213
1214int griommu_group_apv_page_set(int group, int index, int size, int options)
1215{
1216        void * apv;
1217        unsigned int val;
1218        int ret;
1219
1220        /* Flush APV cache if needed.
1221         * This function checks for priv and group being valid.*/
1222        ret = griommu_group_apv_flush(group);
1223        if (ret < 0){
1224                return ret;
1225        }
1226
1227        /* Get APV group */
1228        apv = (void *) (griommu_reg_group(group) & GRP_BASE);
1229
1230        if (apv == NULL){
1231                DBG("Wrong pointer.\n");
1232                return GRIOMMU_ERR_NOTFOUND;
1233        }
1234
1235        /* Get init value */
1236        if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1237                val = 0x0;
1238        }else{
1239                val = 0xffffffff;
1240        }
1241
1242        return griommu_apv_set(apv, index, size, val);
1243}
1244
1245int griommu_group_apv_address_set(int group, uint32_t addr, int size, 
1246                int options)
1247{
1248        struct griommu_priv * priv = griommupriv;
1249        void * apv;
1250        unsigned int val;
1251        int ret;
1252        int startpage;
1253        int endpage;
1254        int npages;
1255
1256        /* Flush APV cache if needed.
1257         * This function checks for priv and group being valid.*/
1258        ret = griommu_group_apv_flush(group);
1259        if (ret < 0){
1260                return ret;
1261        }
1262
1263        /* Get APV group */
1264        apv = (void *) (griommu_reg_group(group) & GRP_BASE);
1265
1266        if (apv == NULL){
1267                DBG("Wrong pointer.\n");
1268                return GRIOMMU_ERR_NOTFOUND;
1269        }
1270
1271        /* Get init value */
1272        if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1273                val = 0x0;
1274        }else{
1275                val = 0xffffffff;
1276        }
1277
1278        /* Get start page */
1279        startpage = (addr / priv->pagesize);
1280
1281        /* Get end page */
1282        endpage = ((addr + size)/ priv->pagesize);
1283
1284        /* Get number of pages */
1285        npages = endpage - startpage + 1;
1286
1287        return griommu_apv_set(apv, startpage, npages, val);
1288}
1289
1290int griommu_apv_init(void * apv, int options)
1291{
1292        struct griommu_priv * priv = griommupriv;
1293        int val;
1294        size_t len;
1295
1296        if (priv == NULL){
1297                DBG("GRIOMMU not initialized.\n");
1298                return GRIOMMU_ERR_NOINIT;
1299        }
1300
1301        if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
1302                DBG("Wrong pointer.\n");
1303                return GRIOMMU_ERR_EINVAL;
1304        }
1305
1306        /* Get init value (is a char) */
1307        if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1308                val = 0x00;
1309        }else{
1310                val = 0xff;
1311        }
1312
1313        /* Get APV length */
1314        len = GRIOMMU_APV_SIZE/priv->pagesize;
1315
1316        /* Initialize structure */
1317        memset(apv, val, len);
1318
1319        return GRIOMMU_ERR_OK;
1320}
1321
1322int griommu_apv_page_set(void * apv, int index, int size, int options)
1323{
1324        struct griommu_priv * priv = griommupriv;
1325        unsigned int val;
1326
1327        if (priv == NULL){
1328                DBG("GRIOMMU not initialized.\n");
1329                return GRIOMMU_ERR_NOINIT;
1330        }
1331
1332        if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
1333                DBG("Wrong pointer.\n");
1334                return GRIOMMU_ERR_EINVAL;
1335        }
1336
1337        /* Get init value */
1338        if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1339                val = 0x0;
1340        }else{
1341                val = 0xffffffff;
1342        }
1343
1344        return griommu_apv_set(apv, index, size, val);
1345}
1346
1347int griommu_apv_address_set(void * apv, uint32_t addr, int size, int options)
1348{
1349        struct griommu_priv * priv = griommupriv;
1350        unsigned int val;
1351        int startpage;
1352        int endpage;
1353        int npages;
1354
1355        if (priv == NULL){
1356                DBG("GRIOMMU not initialized.\n");
1357                return GRIOMMU_ERR_NOINIT;
1358        }
1359
1360        if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
1361                DBG("Wrong pointer.\n");
1362                return GRIOMMU_ERR_EINVAL;
1363        }
1364
1365        /* Get init value */
1366        if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1367                val = 0x0;
1368        }else{
1369                val = 0xffffffff;
1370        }
1371
1372        /* Get start page */
1373        startpage = (addr / priv->pagesize);
1374
1375        /* Get end page */
1376        endpage = ((addr + size)/ priv->pagesize);
1377
1378        /* Get number of pages */
1379        npages = endpage - startpage + 1;
1380
1381        return griommu_apv_set(apv, startpage, npages, val);
1382}
1383
1384int griommu_group_info(int group, uint32_t * info)
1385{
1386        struct griommu_priv * priv = griommupriv;
1387
1388        if (priv == NULL){
1389                DBG("GRIOMMU not initialized.\n");
1390                return GRIOMMU_ERR_NOINIT;
1391        }
1392
1393        if ((group < 0) || (group >= priv->groups)){
1394                DBG("Wrong group id.\n");
1395                return GRIOMMU_ERR_EINVAL;
1396        }
1397
1398        if (info == NULL){
1399                DBG("Wrong pointer.\n");
1400                return GRIOMMU_ERR_EINVAL;
1401        }
1402
1403        /* Get group */
1404        *info = griommu_reg_group(group);
1405
1406        return GRIOMMU_ERR_OK;
1407}
1408
1409/* Flush APV cache group:
1410 */
1411int griommu_group_apv_flush(int group)
1412{
1413        struct griommu_priv * priv = griommupriv;
1414
1415        if (priv == NULL){
1416                DBG("GRIOMMU not initialized.\n");
1417                return GRIOMMU_ERR_NOINIT;
1418        }
1419
1420        if ((group < 0) || (group >= priv->groups)){
1421                DBG("Wrong group id.\n");
1422                return GRIOMMU_ERR_EINVAL;
1423        }
1424
1425        /* Flush cache  */
1426        if (priv->cache_enabled){
1427                if (priv->group_addressing){
1428                        griommu_reg_flush_set(((group << FLUSH_FGRP_BIT) & FLUSH_FGRP) | 
1429                                        FLUSH_GF | FLUSH_F);
1430                }else{
1431                        griommu_reg_flush_set(FLUSH_F);
1432                }
1433                DBG("GRIOMMU APV cache flushed.\n");
1434        }
1435
1436        return GRIOMMU_ERR_OK;
1437}
1438
1439/* Flush APV cache:
1440 */
1441int griommu_apv_flush(void)
1442{
1443        struct griommu_priv * priv = griommupriv;
1444
1445        if (priv == NULL){
1446                DBG("GRIOMMU not initialized.\n");
1447                return GRIOMMU_ERR_NOINIT;
1448        }
1449
1450        /* Flush cache  */
1451        if (priv->cache_enabled){
1452                griommu_reg_flush_set(FLUSH_F);
1453                DBG("GRIOMMU APV cache flushed.\n");
1454        }
1455
1456        return GRIOMMU_ERR_OK;
1457}
1458
Note: See TracBrowser for help on using the repository browser.