summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/iommu/griommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/iommu/griommu.c')
-rw-r--r--c/src/lib/libbsp/sparc/shared/iommu/griommu.c1455
1 files changed, 0 insertions, 1455 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/iommu/griommu.c b/c/src/lib/libbsp/sparc/shared/iommu/griommu.c
deleted file mode 100644
index c70219a944..0000000000
--- a/c/src/lib/libbsp/sparc/shared/iommu/griommu.c
+++ /dev/null
@@ -1,1455 +0,0 @@
-/*
- * GRIOMMU Driver Interface
- *
- * COPYRIGHT (c) 2017
- * Cobham Gaisler AB
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <drvmgr/drvmgr.h>
-#include <drvmgr/ambapp_bus.h>
-#include <ambapp.h>
-#include <rtems.h>
-#include <bsp.h>
-#include <bsp/griommu.h>
-
-/*#define STATIC*/
-#define STATIC static
-
-/*#define INLINE*/
-#define INLINE inline
-
-#define UNUSED __attribute__((unused))
-
-/*#define DEBUG 1*/
-
-#ifdef DEBUG
-#define DBG(x...) printf(x)
-#else
-#define DBG(x...)
-#endif
-
-/*
- * GRIOMMU CAP0 register fields
- */
-#define CAP0_A (0x1 << CAP0_A_BIT)
-#define CAP0_AC (0x1 << CAP0_AC_BIT)
-#define CAP0_CA (0x1 << CAP0_CA_BIT)
-#define CAP0_CP (0x1 << CAP0_CP_BIT)
-#define CAP0_NARB (0xf << CAP0_NARB_BIT)
-#define CAP0_CS (0x1 << CAP0_CS_BIT)
-#define CAP0_FT (0x3 << CAP0_FT_BIT)
-#define CAP0_ST (0x1 << CAP0_ST_BIT)
-#define CAP0_I (0x1 << CAP0_I_BIT)
-#define CAP0_IT (0x1 << CAP0_IT_BIT)
-#define CAP0_IA (0x1 << CAP0_IA_BIT)
-#define CAP0_IP (0x1 << CAP0_IP_BIT)
-#define CAP0_MB (0x1 << CAP0_MB_BIT)
-#define CAP0_GRPS (0xf << CAP0_GRPS_BIT)
-#define CAP0_MSTS (0xf << CAP0_MSTS_BIT)
-
-#define CAP0_A_BIT 31
-#define CAP0_AC_BIT 30
-#define CAP0_CA_BIT 29
-#define CAP0_CP_BIT 28
-#define CAP0_NARB_BIT 20
-#define CAP0_CS_BIT 19
-#define CAP0_FT_BIT 17
-#define CAP0_ST_BIT 16
-#define CAP0_I_BIT 15
-#define CAP0_IT_BIT 14
-#define CAP0_IA_BIT 13
-#define CAP0_IP_BIT 12
-#define CAP0_MB_BIT 8
-#define CAP0_GRPS_BIT 4
-#define CAP0_MSTS_BIT 0
-
-/*
- * GRIOMMU CAP1 register fields
- */
-#define CAP1_CADDR (0xfff << CAP1_CADDR_BIT)
-#define CAP1_CMASK (0xf << CAP1_CMASK_BIT)
-#define CAP1_CTAGBITS (0xff << CAP1_CTAGBITS_BIT)
-#define CAP1_CISIZE (0x7 << CAP1_CISIZE_BIT)
-#define CAP1_CLINES (0x1f << CAP1_CLINES_BIT)
-
-#define CAP1_CADDR_BIT 20
-#define CAP1_CMASK_BIT 16
-#define CAP1_CTAGBITS_BIT 8
-#define CAP1_CISIZE_BIT 5
-#define CAP1_CLINES_BIT 0
-
-/*
- * GRIOMMU CTRL register fields
- * DEFINED IN HEADER FILE
- */
-
-/*
- * GRIOMMU FLUSH register fields
- */
-#define FLUSH_FGRP (0xf << FLUSH_FGRP_BIT)
-#define FLUSH_GF (0x1 << FLUSH_GF_BIT)
-#define FLUSH_F (0x1 << FLUSH_F_BIT)
-
-#define FLUSH_FGRP_BIT 4
-#define FLUSH_GF_BIT 1
-#define FLUSH_F_BIT 0
-
-/*
- * GRIOMMU STATUS register fields
- */
-#define STS_PE (0x1 << STS_PE_BIT)
-#define STS_DE (0x1 << STS_DE_BIT)
-#define STS_FC (0x1 << STS_FC_BIT)
-#define STS_FL (0x1 << STS_FL_BIT)
-#define STS_AD (0x1 << STS_AD_BIT)
-#define STS_TE (0x1 << STS_TE_BIT)
-#define STS_ALL (STS_PE | STS_DE | STS_FC | STS_FL | STS_AD | STS_TE)
-
-#define STS_PE_BIT 5
-#define STS_DE_BIT 4
-#define STS_FC_BIT 3
-#define STS_FL_BIT 2
-#define STS_AD_BIT 1
-#define STS_TE_BIT 0
-
-/*
- * GRIOMMU IMASK register fields
- */
-#define IMASK_PEI (0x1 << IMASK_PEI_BIT)
-#define IMASK_FCI (0x1 << IMASK_FCI_BIT)
-#define IMASK_FLI (0x1 << IMASK_FLI_BIT)
-#define IMASK_ADI (0x1 << IMASK_ADI_BIT)
-#define IMASK_TEI (0x1 << IMASK_TEI_BIT)
-#define IMASK_ALL (IMASK_PEI | IMASK_FCI | IMASK_FLI | IMASK_ADI | IMASK_TEI)
-
-#define IMASK_PEI_BIT 5
-#define IMASK_FCI_BIT 3
-#define IMASK_FLI_BIT 2
-#define IMASK_ADI_BIT 1
-#define IMASK_TEI_BIT 0
-
-/*
- * GRIOMMU MASTER register fields
- */
-/* DEFINED IN HEADER FILE
-#define MASTER_VENDOR (0xff << MASTER_VENDOR_BIT)
-#define MASTER_DEVICE (0xfff << MASTER_DEVICE_BIT)
-#define MASTER_BS (0x1 << MASTER_BS_BIT)
-#define MASTER_GROUP (0xf << MASTER_GROUP_BIT)
-
-#define MASTER_VENDOR_BIT 24
-#define MASTER_DEVICE_BIT 12
-#define MASTER_BS_BIT 4
-#define MASTER_GROUP_BIT 0
-*/
-
-#define MASTER_BS_BUS0 0
-#define MASTER_BS_BUS1 MASTER_BS
-
-/*
- * GRIOMMU GROUP register fields
- */
-#define GRP_BASE (0xfffffff << GRP_BASE_BIT)
-#define GRP_P (0x1 << GRP_P_BIT)
-#define GRP_AG (0x1 << GRP_AG_BIT)
-
-#define GRP_BASE_BIT 4
-#define GRP_P_BIT 1
-#define GRP_AG_BIT 0
-
-
-#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val))
-#define REG_READ(addr) (*(volatile unsigned int *)(addr))
-
-/*
- * GRIOMMU APB Register MAP
- */
-struct griommu_regs {
- volatile unsigned int cap0; /* 0x00 - Capability 0 */
- volatile unsigned int cap1; /* 0x04 - Capability 1 */
- volatile unsigned int cap2; /* 0x08 - Capability 2 */
- volatile unsigned int resv1; /* 0x0c - Reserved */
- volatile unsigned int ctrl; /* 0x10 - Control */
- volatile unsigned int flush; /* 0x14 - TLB/cache flush */
- volatile unsigned int status; /* 0x18 - Status */
- volatile unsigned int imask; /* 0x1c - Interrupt mask */
- volatile unsigned int ahbstat; /* 0x20 - AHB Failing Access */
- volatile unsigned int resv2[7]; /* 0x24-0x3c - Reserved. No access */
- volatile unsigned int master[16]; /* 0x40-0x7c - Master configuration */
- volatile unsigned int grp_ctrl[16]; /* 0x80-0xbc - Group control */
- volatile unsigned int diag_ca; /* 0xc0 - Diagnostic cache access */
- volatile unsigned int diag_cad[8]; /* 0xc4-0xe0 - Diagnostic cache data */
- volatile unsigned int diag_cat; /* 0xe4 - Diagnostic cache tag */
- volatile unsigned int ei_data; /* 0xe8 - Data RAM error injection */
- volatile unsigned int ei_tag; /* 0xec - Tag RAM error injection */
- volatile unsigned int resv3[4]; /* 0xf0-0xfc - Reserved. No access */
- volatile unsigned int asmpctrl[16]; /* 0x100-0x13c - ASMP access control */
-};
-
-#define DEVNAME_LEN 9
-/*
- * GRIOMMU Driver private data struture
- */
-struct griommu_priv {
- struct drvmgr_dev *dev;
- char devname[DEVNAME_LEN];
- /* GRIOMMU control registers */
- struct griommu_regs *regs;
-
- /* GRIOMMU capabilities */
- int apv;
- int apv_cache;
- int apv_cache_addr;
- int conf_pagesize;
-
- int groups;
- int masters;
-
- /* GRIOMMU page size */
- int pagesize;
-
- /* GRIOMMU APV cache */
- int cache_enabled;
- int group_addressing;
-
- /* User defined ISR */
- griommu_isr_t isr;
- void *isr_arg;
-};
-
-/*
- * GRIOMMU internal prototypes
- */
-/* -Register access functions */
-STATIC INLINE unsigned int griommu_reg_cap0(void);
-STATIC INLINE unsigned int griommu_reg_cap1(void);
-STATIC INLINE unsigned int griommu_reg_ctrl(void);
-STATIC INLINE int griommu_reg_ctrl_set(unsigned int val);
-STATIC INLINE int griommu_reg_flush_set(unsigned int val);
-STATIC INLINE unsigned int griommu_reg_status(void);
-STATIC INLINE int griommu_reg_status_clear(unsigned int val);
-STATIC INLINE unsigned int griommu_reg_imask(void);
-STATIC INLINE int griommu_reg_imask_set(int mask);
-STATIC INLINE unsigned int griommu_reg_ahbfas(void);
-STATIC INLINE unsigned int griommu_reg_master(int master);
-STATIC INLINE int griommu_reg_master_set(int master, unsigned int val);
-STATIC INLINE unsigned int griommu_reg_group(int group);
-STATIC INLINE int griommu_reg_group_set(int group, unsigned int val);
-
-/* APV helper functions */
-STATIC void griommu_apv_set_word(unsigned int * wordptr, int startbitidx,
- int nbits, unsigned int val);
-STATIC int griommu_apv_set(void * apv, int index, int size, unsigned int val);
-
-/* -Init function called by drvmgr */
-int griommu_init1(struct drvmgr_dev *dev);
-STATIC int griommu_init(struct griommu_priv *priv);
-
-
-/* -IRQ handler */
-void griommu_isr(void *arg);
-
-/*
- * GRIOMMU static members
- */
-static struct griommu_priv *griommupriv = NULL;
-
-/* GRIOMMU DRIVER */
-
-struct drvmgr_drv_ops griommu_ops =
-{
- .init = {griommu_init1, NULL, NULL, NULL},
- .remove = NULL,
- .info = NULL
-};
-
-struct amba_dev_id griommu_ids[] =
-{
- {VENDOR_GAISLER, GAISLER_GRIOMMU},
- {0, 0} /* Mark end of table */
-};
-
-struct amba_drv_info griommu_info =
-{
- {
- DRVMGR_OBJ_DRV, /* Driver */
- NULL, /* Next driver */
- NULL, /* Device list */
- DRIVER_AMBAPP_GAISLER_GRIOMMU_ID,/* Driver ID */
- "GRIOMMU_DRV", /* Driver Name */
- DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */
- &griommu_ops,
- NULL, /* Funcs */
- 0, /* No devices yet */
- sizeof(struct griommu_priv), /* Make drvmgr alloc private */
- },
- &griommu_ids[0]
-};
-
-void griommu_register_drv(void)
-{
- DBG("Registering GRIOMMU driver\n");
- drvmgr_drv_register(&griommu_info.general);
-}
-
-/* Initializes the GRIOMMU core and driver
- *
- * Return values
- * 0 Successful initalization
- */
-STATIC int griommu_init(struct griommu_priv *priv)
-{
- struct ambapp_ahb_info *ahb;
- struct amba_dev_info *ainfo = priv->dev->businfo;
-
- /* Find GRIOMMU core from Plug&Play information */
- ahb = ainfo->info.ahb_slv;
-
- /* Found GRIOMMU core, init private structure */
- priv->regs = (struct griommu_regs *)ahb->start[0];
-
- /* Mask all interrupts */
- griommu_reg_imask_set(0);
-
- /* Initialize GRIOMMU capabilities */
- uint32_t cap0 = griommu_reg_cap0();
- priv->apv = (cap0 & CAP0_A) >> CAP0_A_BIT;
- priv->apv_cache = (cap0 & CAP0_AC) >> CAP0_AC_BIT;
- priv->apv_cache_addr = (cap0 & CAP0_CA) >> CAP0_CA_BIT;
- priv->conf_pagesize = (cap0 & CAP0_CS) >> CAP0_CS_BIT;
- priv->groups = ((cap0 & CAP0_GRPS) >> CAP0_GRPS_BIT) + 1;
- priv->masters = ((cap0 & CAP0_MSTS) >> CAP0_MSTS_BIT) + 1;
-
- /* Get GRIOMMU pagesize */
- uint32_t ctrl = griommu_reg_ctrl();
- if (priv->conf_pagesize){
- priv->pagesize = (4*1024 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT));
- }else{
- priv->pagesize = 4*1024;
- }
- priv->cache_enabled = (ctrl & CTRL_CE);
- priv->group_addressing = (ctrl & CTRL_GS);
-
- DBG("GRIOMMU Capabilities: APV=%d, APVC=%d, APVCA=%d, CS=%d, "
- "GRPS=%d, MSTS=%d\n",
- priv->apv, priv->apv_cache, priv->apv_cache_addr,
- priv->conf_pagesize, priv->groups, priv->masters);
- DBG("GRIOMMU driver initialized\n");
-
- return 0;
-}
-
-/* Called when a core is found with the AMBA device and vendor ID
- * given in griommu_ids[]. IRQ, Console does not work here
- */
-int griommu_init1(struct drvmgr_dev *dev)
-{
- int status;
- struct griommu_priv *priv;
-
- DBG("GRIOMMU[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
-
- if (griommupriv) {
- DBG("Driver only supports one GRIOMMU core\n");
- return DRVMGR_FAIL;
- }
-
- priv = dev->priv;
- if (!priv)
- return DRVMGR_NOMEM;
-
- priv->dev = dev;
- strncpy(&priv->devname[0], "griommu0", DEVNAME_LEN);
- griommupriv = priv;
-
- /* Initialize GRIOMMU Hardware */
- status = griommu_init(priv);
- if (status) {
- printf("Failed to initialize griommu driver %d\n", status);
- return -1;
- }
-
- return DRVMGR_OK;
-}
-
-STATIC INLINE unsigned int griommu_reg_cap0(void)
-{
- struct griommu_priv *priv = griommupriv;
-
- return REG_READ(&priv->regs->cap0);
-}
-
-STATIC INLINE unsigned int griommu_reg_cap1(void)
-{
- struct griommu_priv *priv = griommupriv;
-
- return REG_READ(&priv->regs->cap1);
-}
-
-STATIC INLINE unsigned int griommu_reg_ctrl(void)
-{
- struct griommu_priv *priv = griommupriv;
-
- return REG_READ(&priv->regs->ctrl);
-}
-
-STATIC INLINE int griommu_reg_ctrl_set(unsigned int val)
-{
- struct griommu_priv *priv = griommupriv;
-
- REG_WRITE(&priv->regs->ctrl, val);
- return 0;
-}
-
-STATIC INLINE int griommu_reg_flush_set(unsigned int val)
-{
- struct griommu_priv *priv = griommupriv;
-
- REG_WRITE(&priv->regs->flush, val);
- return 0;
-}
-
-STATIC INLINE unsigned int griommu_reg_status(void)
-{
- struct griommu_priv *priv = griommupriv;
-
- return REG_READ(&priv->regs->status);
-}
-
-STATIC INLINE int griommu_reg_status_clear(unsigned int val)
-{
- struct griommu_priv *priv = griommupriv;
-
- /* Clear errors */
- REG_WRITE(&priv->regs->status, (val & STS_ALL));
- return 0;
-}
-
-STATIC INLINE unsigned int griommu_reg_imask(void)
-{
- struct griommu_priv *priv = griommupriv;
-
- return REG_READ(&priv->regs->imask);
-}
-
-STATIC INLINE int griommu_reg_imask_set(int mask)
-{
- struct griommu_priv *priv = griommupriv;
-
- /* Clear errors */
- REG_WRITE(&priv->regs->imask, (mask & IMASK_ALL));
- return 0;
-}
-
-STATIC INLINE unsigned int griommu_reg_ahbfas(void)
-{
- struct griommu_priv *priv = griommupriv;
-
- return REG_READ(&priv->regs->ahbstat);
-}
-
-STATIC INLINE int griommu_reg_master_set(int master, unsigned int val)
-{
- struct griommu_priv *priv = griommupriv;
-
- /* Change master conf */
- REG_WRITE(&priv->regs->master[master], val);
- return 0;
-}
-
-STATIC INLINE unsigned int griommu_reg_master(int master)
-{
- struct griommu_priv *priv = griommupriv;
-
- return REG_READ(&priv->regs->master[master]);
-}
-
-STATIC INLINE unsigned int griommu_reg_group(int group)
-{
- struct griommu_priv *priv = griommupriv;
-
- return REG_READ(&priv->regs->grp_ctrl[group]);
-}
-
-STATIC INLINE int griommu_reg_group_set(int group, unsigned int val)
-{
- struct griommu_priv *priv = griommupriv;
-
- REG_WRITE(&priv->regs->grp_ctrl[group], val);
- return 0;
-}
-
-STATIC void griommu_apv_set_word(unsigned int * wordptr, int startbitidx,
- int nbits, unsigned int val)
-{
- unsigned int mask;
- unsigned int word = *wordptr;
- int endbitidx = startbitidx + nbits - 1;
-
- /* Set initial mask */
- mask = 0xffffffff;
-
- /* Adjust mask for the starting bit */
- mask >>= startbitidx;
-
- /* Adjust mask for the end bit */
- mask >>= (31 - endbitidx);
- mask <<= (31 - endbitidx);
-
- DBG("Setting word: startbitdx=%d, endbitidx=%d, mask=0x%02x",
- startbitidx, endbitidx, (unsigned int) mask);
-
- /* Clear written bits with mask */
- word &= ~(mask);
-
- /* Set bits in val with mask */
- mask &= val;
- word |= mask;
-
- DBG(", old word=0x%08x, new word=0x%08x\n",*wordptr, word);
-
- /* Write word */
- *wordptr=word;
-}
-
-/* Set certains bits of the APV to val */
-STATIC int griommu_apv_set(void * apv, int index, int size, unsigned int val)
-{
- unsigned int * words = (unsigned int *) apv;
- int len = size;
- int wordidx = (index/32);
- int startbit = (index % 32);
- int nbits;
- int nwords;
-
- /* First incomplete word is a special case */
- if (startbit != 0){
- /* Get how many bits are we changing in this word */
- if (startbit + len < 32){
- nbits = len;
- }else{
- nbits = 32 - startbit;
- }
- griommu_apv_set_word(&words[wordidx], startbit, nbits, val);
- DBG("First word: wordidx=%d, startbit=%d, bits=%d, val=0x%08x\n",
- wordidx, startbit, nbits, words[wordidx]);
-
- /* Update wordidx and len */
- len = len - nbits;
- wordidx++;
- }
-
- /* Write all complete full words */
- if (len != 0){
- nwords = (len/32);
- memset((void *) &words[wordidx], val, nwords*4);
- DBG("Middle words: wordidx=%d, nwords=%d\n", wordidx, nwords);
- /* Update wordidx and len*/
- wordidx = wordidx + nwords;
- len = len - nwords*32;
- }
-
- /* Last word is a special case */
- if (len != 0){
- nbits = len;
- griommu_apv_set_word(&words[wordidx], 0, nbits, val);
- DBG("First word: wordidx=%d, startbit=%d, bits=%d, val=0x%08x\n",
- wordidx, 0, nbits, words[wordidx]);
- /* Update len */
- len = len - (nbits);
- }
-
- return GRIOMMU_ERR_OK;
-}
-
-/* GRIOMMU Interrupt handler, called when there may be a GRIOMMU interrupt.
- */
-void griommu_isr(void *arg)
-{
- struct griommu_priv *priv = arg;
- unsigned int sts = griommu_reg_status();
- unsigned int mask = griommu_reg_imask();
- unsigned int access = griommu_reg_ahbfas();
-
- /* Make sure that the interrupt is pending and unmasked,
- * otherwise it migth have been other core
- * sharing the same interrupt line */
- if ((sts & STS_ALL) & (mask & IMASK_ALL)){
- /* Reset error status */
- griommu_reg_status_clear(sts);
- /* Execute user IRQ (ther will always be one ISR */
- (priv->isr)(priv->isr_arg, access, sts);
- }
-}
-
-/* Setup IOMMU master:
- */
-int griommu_master_setup(int master, int group, int options)
-{
- struct griommu_priv * priv = griommupriv;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if ((master < 0) || (master >= priv->masters)){
- DBG("Wrong master id.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- if ((group < 0) || (group >= priv->groups)){
- DBG("Wrong group id.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- griommu_reg_master_set(master,
- ((options & GRIOMMU_OPTIONS_BUS1)? MASTER_BS_BUS1: MASTER_BS_BUS0)|
- ((group << MASTER_GROUP_BIT) & MASTER_GROUP)
- );
-
- DBG("IOMMU master setup: master %d, traffic routed %s, group %d\n",
- master,
- (options & GRIOMMU_OPTIONS_BUS1) ?
- "to Secondary bus":"to Primary bus",
- group);
-
- return GRIOMMU_ERR_OK;
-}
-
-
-/* Get IOMMU master info:
- */
-int griommu_master_info(int master, uint32_t * info)
-{
- struct griommu_priv * priv = griommupriv;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if ((master < 0) || (master >= priv->masters)){
- DBG("Wrong master id.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- if (info == NULL){
- DBG("Wrong pointer.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Get master */
- *info = griommu_reg_master(master);
-
- return GRIOMMU_ERR_OK;
-}
-
-/* Find IOMMU master:
- */
-int griommu_master_find(int vendor, int device, int instance)
-{
- struct griommu_priv * priv = griommupriv;
- int i, gotvendor, gotdevice;
- unsigned int master;
- int found;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- /* Find which master */
- found=0;
- for (i=0; i< priv->masters; i++){
- master = griommu_reg_master(i);
- gotvendor = (master & MASTER_VENDOR) >> MASTER_VENDOR_BIT;
- gotdevice = (master & MASTER_DEVICE) >> MASTER_DEVICE_BIT;
- if ((gotvendor == vendor) && (gotdevice == device)){
- if(found == instance){
- DBG("Found master %d: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), "
- "Instance=%d\n",
- i,
- ambapp_vendor_id2str(vendor), vendor,
- ambapp_device_id2str(vendor,device), device, instance
- );
- return i;
- }
- found++;
- }
- }
-
- DBG("Master not found: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), "
- "Instance=%d\n",
- ambapp_vendor_id2str(vendor), vendor,
- ambapp_device_id2str(vendor,device), device, instance
- );
- return GRIOMMU_ERR_NOTFOUND;
-}
-
-/* Setup IOMMU:
- */
-int griommu_setup(int options)
-{
- struct griommu_priv * priv = griommupriv;
- unsigned int ctrl;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- /* Check Cache */
- if (options & GRIOMMU_OPTIONS_CACHE_ENABLE) {
- if (priv->apv_cache){
- /* Flush cache */
- griommu_reg_flush_set(FLUSH_F);
- priv->cache_enabled = 1;
- }else{
- DBG("GRIOMMU APV cache not supported.\n");
- return GRIOMMU_ERR_IMPLEMENTED;
- }
- }else{
- priv->cache_enabled = 0;
- }
-
- /* Check group addressing */
- if (options & GRIOMMU_OPTIONS_GROUPADDRESSING_ENABLE){
- if (priv->apv_cache_addr){
- priv->group_addressing = 1;
- }else{
- DBG("GRIOMMU APV cache group addressing not supported.\n");
- return GRIOMMU_ERR_IMPLEMENTED;
- }
- }else{
- priv->group_addressing = 0;
- }
-
- /* Check pagesize */
- if ((options & CTRL_PGSZ) != GRIOMMU_OPTIONS_PAGESIZE_4KIB){
- if (priv->conf_pagesize == 0){
- DBG("GRIOMMU Configurable pagesize not supported.\n");
- return GRIOMMU_ERR_IMPLEMENTED;
- }
- }
-
- /* Get CTRL IOMMU */
- ctrl = griommu_reg_ctrl();
-
- /* Clear used fields */
- ctrl &= ~(CTRL_CE | CTRL_GS | CTRL_PGSZ | CTRL_LB |
- CTRL_DP | CTRL_AU | CTRL_WP);
-
- /* Clear not used fields */
- options &= (CTRL_CE | CTRL_GS | CTRL_PGSZ | CTRL_LB |
- CTRL_DP | CTRL_AU | CTRL_WP);
-
- /* Set new values */
- ctrl |= options;
-
- /* Set CTRL IOMMU */
- griommu_reg_ctrl_set(ctrl);
-
- DBG("IOMMU setup: prefetching %s, cache %s, groupaddr %s, "
- "lookup bus %s, ahb update %s,\nwprot only %s, pagesize %d KiB\n",
- ((options & GRIOMMU_OPTIONS_PREFETCH_DISABLE)?
- "disabled":"enabled"),
- ((options & GRIOMMU_OPTIONS_CACHE_ENABLE)? "enabled":"disabled"),
- ((options & GRIOMMU_OPTIONS_GROUPADDRESSING_ENABLE)?
- "enabled":"disabled"),
- ((options & GRIOMMU_OPTIONS_LOOKUPBUS_BUS1)? "bus1":"bus0"),
- ((options & GRIOMMU_OPTIONS_AHBUPDATE_ENABLE)?
- "enabled":"disabled"),
- ((options & GRIOMMU_OPTIONS_WPROTONLY_ENABLE)?
- "enabled":"disabled"),
- (4 << ((options & GRIOMMU_OPTIONS_PAGESIZE_512KIB) >> 18))
- );
-
- return GRIOMMU_ERR_OK;
-}
-
-/* Status IOMMU:
- */
-int griommu_status(void)
-{
- struct griommu_priv * priv = griommupriv;
- unsigned int ctrl;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- /* Get CTRL IOMMU */
- ctrl = griommu_reg_ctrl();
-
- DBG("IOMMU status: prefetching %s, cache %s, groupaddr %s, "
- "lookup bus %s, ahb update %s,\nwprot only %s, pagesize %d KiB\n",
- ((ctrl & CTRL_DP)? "disabled":"enabled"),
- ((ctrl & CTRL_CE)? "enabled":"disabled"),
- ((ctrl & CTRL_GS)? "enabled":"disabled"),
- ((ctrl & CTRL_LB)? "bus1":"bus0"),
- ((ctrl & CTRL_AU)? "enabled":"disabled"),
- ((ctrl & CTRL_WP)? "enabled":"disabled"),
- (4 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT))
- );
-
- return ctrl;
-}
-
-int griommu_isr_register(griommu_isr_t isr, void * arg, int options)
-{
- struct griommu_priv *priv = griommupriv;
- unsigned int mask;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if (isr == NULL){
- DBG("GRIOMMU wrong isr.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Get mask */
- mask = 0 |
- ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) |
- ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) |
- ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) |
- ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) |
- ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0);
-
- /* Clear previous interrupts and mask them*/
- griommu_reg_status_clear(STS_ALL);
- griommu_reg_imask_set(0);
-
- /* First time registering an ISR */
- if (priv->isr == NULL){
- /* Install and Enable GRIOMMU interrupt handler */
- drvmgr_interrupt_register(priv->dev, 0, priv->devname, griommu_isr,
- priv);
- }
-
- /* Install user ISR */
- priv->isr=isr;
- priv->isr_arg=arg;
-
- /* Now it is safe to unmask interrupts */
- griommu_reg_imask_set(mask);
-
- return GRIOMMU_ERR_OK;
-}
-
-int griommu_isr_unregister(void)
-{
- struct griommu_priv *priv = griommupriv;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if (priv->isr == NULL){
- DBG("GRIOMMU wrong isr.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Clear previous interrupts and mask them*/
- griommu_reg_status_clear(STS_ALL);
- griommu_reg_imask_set(0);
-
- /* Uninstall and disable GRIOMMU interrupt handler */
- drvmgr_interrupt_unregister(priv->dev, 0, griommu_isr, priv);
-
- /* Uninstall user ISR */
- priv->isr=NULL;
- priv->isr_arg=NULL;
-
- return GRIOMMU_ERR_OK;
-}
-
-int griommu_interrupt_unmask(int options)
-{
- struct griommu_priv *priv = griommupriv;
- unsigned int mask, irq;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if (priv->isr == NULL){
- DBG("GRIOMMU wrong isr.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Unmask interrupts in GRIOMMU */
- mask = 0 |
- ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) |
- ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) |
- ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) |
- ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) |
- ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0);
-
- /* Clear previous interrupts*/
- griommu_reg_status_clear(STS_ALL);
-
- /* Get previous mask */
- irq = griommu_reg_imask() & IMASK_ALL;
-
- /* Set new mask */
- griommu_reg_imask_set(irq | mask);
-
- return GRIOMMU_ERR_OK;
-}
-
-int griommu_interrupt_mask(int options)
-{
- struct griommu_priv *priv = griommupriv;
- unsigned int mask, irq;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if (priv->isr == NULL){
- DBG("GRIOMMU wrong isr.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Mask interrupts in GRIOMMU */
- mask = 0 |
- ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) |
- ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) |
- ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) |
- ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) |
- ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0);
-
- /* Clear previous interrupts*/
- griommu_reg_status_clear(STS_ALL);
-
- /* Get previous mask */
- irq = griommu_reg_imask() & IMASK_ALL;
-
- /* Set new mask */
- griommu_reg_imask_set(irq & ~(mask));
-
- return GRIOMMU_ERR_OK;
-}
-
-int griommu_error_status(uint32_t * access)
-{
- struct griommu_priv *priv = griommupriv;
- int status;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- /* Get status mask */
- status = griommu_reg_status();
-
- if (status != 0){
- /* Update pointed value */
- if (access != NULL){
- *access = griommu_reg_ahbfas();
- }
- /* Clear errors */
- griommu_reg_status_clear(status);
- }
-
- return status;
-}
-
-/* Print IOMMU masters
- * DEBUG function
- */
-int griommu_print(void)
-{
- #ifdef DEBUG
- struct griommu_priv * priv = griommupriv;
- unsigned int ctrl;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- /* Print IOMMU status */
- ctrl = griommu_reg_ctrl();
-
- printf("IOMMU status: prefetching %s, lookup bus %s, ahb update %s,\n"
- "wprot only %s, pagesize %d KiB\n",
- ((ctrl & CTRL_DP)? "disabled":"enabled"),
- ((ctrl & CTRL_LB)? "bus1":"bus0"),
- ((ctrl & CTRL_AU)? "enabled":"disabled"),
- ((ctrl & CTRL_WP)? "enabled":"disabled"),
- (4 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT))
- );
-
- /* Print each master configuration */
- int i, vendor, device, routing;
- unsigned int master;
- for (i=0; i < priv->masters; i++){
- master = griommu_reg_master(i);
- vendor = (master & MASTER_VENDOR) >> MASTER_VENDOR_BIT;
- device = (master & MASTER_DEVICE) >> MASTER_DEVICE_BIT;
- routing = (master & MASTER_BS);
- printf("IOMMU master %d: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), "
- "BS=%s\n",
- i,
- ambapp_vendor_id2str(vendor), vendor,
- ambapp_device_id2str(vendor,device), device,
- (routing == MASTER_BS_BUS0? "Primary bus" : "Secondary bus")
- );
- }
- #endif
- return GRIOMMU_ERR_OK;
-}
-
-void * griommu_apv_new(void)
-{
- struct griommu_priv * priv = griommupriv;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return NULL;
- }
-
- /* Allocate APV */
- unsigned int * orig_ptr = (unsigned int *) malloc(
- (GRIOMMU_APV_SIZE/priv->pagesize) + GRIOMMU_APV_ALIGN);
- if (orig_ptr == NULL) return NULL;
-
- /* Get the aligned pointer */
- unsigned int aligned_ptr = (
- ((unsigned int) orig_ptr + GRIOMMU_APV_ALIGN) &
- ~(GRIOMMU_APV_ALIGN - 1));
-
- /* Save the original pointer before the aligned pointer */
- unsigned int ** tmp_ptr =
- (unsigned int **) (aligned_ptr - sizeof(orig_ptr));
- *tmp_ptr= orig_ptr;
-
- /* Return aligned pointer */
- return (void *) aligned_ptr;
-}
-
-void griommu_apv_delete(void * apv)
-{
- /* Recover orignal pointer placed just before the aligned pointer */
- unsigned int * orig_ptr;
- unsigned int ** tmp_ptr = (unsigned int **) (apv - sizeof(orig_ptr));
- orig_ptr = *tmp_ptr;
-
- /* Deallocate memory */
- free(orig_ptr);
-}
-
-int griommu_enable(int mode)
-{
- struct griommu_priv * priv = griommupriv;
- unsigned int ctrl;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- switch (mode){
- case GRIOMMU_MODE_IOMMU:
- default:
- DBG("IOMMU mode not implemented in driver.\n");
- return GRIOMMU_ERR_EINVAL;
- break;
- case GRIOMMU_MODE_GROUPAPV:
- if (priv->apv == 0){
- DBG("IOMMU APV not supported.\n");
- return GRIOMMU_ERR_IMPLEMENTED;
- }
- /* Enable IOMMU */
- ctrl = (griommu_reg_ctrl() & ~(CTRL_PM));
- griommu_reg_ctrl_set(ctrl | CTRL_PM_APV | CTRL_EN);
-
- /* Wait until change has effect */
- while((griommu_reg_ctrl() & CTRL_EN)==0){};
-
- DBG("IOMMU enabled.\n");
- return GRIOMMU_ERR_OK;
- break;
- }
- return GRIOMMU_ERR_OK;
-}
-
-int griommu_disable(void)
-{
- struct griommu_priv * priv = griommupriv;
- unsigned int ctrl;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- /* Disable IOMMU */
- ctrl = (griommu_reg_ctrl() & ~(CTRL_EN));
- griommu_reg_ctrl_set(ctrl);
-
- /* Wait until change has effect */
- while(griommu_reg_ctrl() & CTRL_EN){};
-
- return GRIOMMU_ERR_OK;
-}
-
-int griommu_group_setup(int group, void * apv, int options)
-{
- struct griommu_priv * priv = griommupriv;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if ((group < 0) || (group >= priv->groups)){
- DBG("Wrong group id.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- if ((options < 0) || (options > GRIOMMU_OPTIONS_GROUP_PASSTHROUGH)){
- DBG("Wrong options.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- if (options == GRIOMMU_OPTIONS_GROUP_DISABLE){
- if ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1)){
- DBG("Wrong pointer.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Disable GROUP */
- griommu_reg_group_set(group, (((unsigned int) apv) & GRP_BASE) | 0);
- DBG("GROUP[%d] DISABLED.\n", group);
- return GRIOMMU_ERR_OK;
- }else if (options == GRIOMMU_OPTIONS_GROUP_PASSTHROUGH){
- if ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1)){
- DBG("Wrong pointer.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Group in passthrough */
- griommu_reg_group_set(group,
- (((unsigned int) apv) & GRP_BASE) | GRP_P | GRP_AG);
- DBG("GROUP[%d] set to PASSTHROUGH.\n", group);
- return GRIOMMU_ERR_OK;
- }else{
- if (priv->apv == 0){
- DBG("IOMMU APV not supported.\n");
- return GRIOMMU_ERR_IMPLEMENTED;
- }
-
- if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
- DBG("Wrong pointer.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Set up base and enable */
- griommu_reg_group_set(group,
- (((unsigned int) apv) & GRP_BASE) | GRP_AG);
- DBG("GROUP[%d] set to APV (0x%08x).\n", group, (unsigned int) apv);
- return GRIOMMU_ERR_OK;
- }
-}
-
-int griommu_group_apv_init(int group, int options)
-{
- struct griommu_priv * priv = griommupriv;
- void * apv;
- int val;
- int ret;
- size_t len;
-
- /* Flush APV cache if needed.
- * This function checks for priv and group being valid.*/
- ret = griommu_group_apv_flush(group);
- if (ret < 0){
- return ret;
- }
-
- /* Get APV group */
- apv = (void *) (griommu_reg_group(group) & GRP_BASE);
-
- if (apv == NULL){
- DBG("Wrong pointer.\n");
- return GRIOMMU_ERR_NOTFOUND;
- }
-
- /* Get init value (is a char) */
- if (options == GRIOMMU_OPTIONS_APV_ALLOW){
- val = 0x00;
- }else{
- val = 0xff;
- }
-
- /* Get APV length */
- len = GRIOMMU_APV_SIZE/priv->pagesize;
-
- /* Initialize structure */
- memset(apv, val, len);
-
- return GRIOMMU_ERR_OK;
-}
-
-int griommu_group_apv_page_set(int group, int index, int size, int options)
-{
- void * apv;
- unsigned int val;
- int ret;
-
- /* Flush APV cache if needed.
- * This function checks for priv and group being valid.*/
- ret = griommu_group_apv_flush(group);
- if (ret < 0){
- return ret;
- }
-
- /* Get APV group */
- apv = (void *) (griommu_reg_group(group) & GRP_BASE);
-
- if (apv == NULL){
- DBG("Wrong pointer.\n");
- return GRIOMMU_ERR_NOTFOUND;
- }
-
- /* Get init value */
- if (options == GRIOMMU_OPTIONS_APV_ALLOW){
- val = 0x0;
- }else{
- val = 0xffffffff;
- }
-
- return griommu_apv_set(apv, index, size, val);
-}
-
-int griommu_group_apv_address_set(int group, uint32_t addr, int size,
- int options)
-{
- struct griommu_priv * priv = griommupriv;
- void * apv;
- unsigned int val;
- int ret;
- int startpage;
- int endpage;
- int npages;
-
- /* Flush APV cache if needed.
- * This function checks for priv and group being valid.*/
- ret = griommu_group_apv_flush(group);
- if (ret < 0){
- return ret;
- }
-
- /* Get APV group */
- apv = (void *) (griommu_reg_group(group) & GRP_BASE);
-
- if (apv == NULL){
- DBG("Wrong pointer.\n");
- return GRIOMMU_ERR_NOTFOUND;
- }
-
- /* Get init value */
- if (options == GRIOMMU_OPTIONS_APV_ALLOW){
- val = 0x0;
- }else{
- val = 0xffffffff;
- }
-
- /* Get start page */
- startpage = (addr / priv->pagesize);
-
- /* Get end page */
- endpage = ((addr + size)/ priv->pagesize);
-
- /* Get number of pages */
- npages = endpage - startpage + 1;
-
- return griommu_apv_set(apv, startpage, npages, val);
-}
-
-int griommu_apv_init(void * apv, int options)
-{
- struct griommu_priv * priv = griommupriv;
- int val;
- size_t len;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
- DBG("Wrong pointer.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Get init value (is a char) */
- if (options == GRIOMMU_OPTIONS_APV_ALLOW){
- val = 0x00;
- }else{
- val = 0xff;
- }
-
- /* Get APV length */
- len = GRIOMMU_APV_SIZE/priv->pagesize;
-
- /* Initialize structure */
- memset(apv, val, len);
-
- return GRIOMMU_ERR_OK;
-}
-
-int griommu_apv_page_set(void * apv, int index, int size, int options)
-{
- struct griommu_priv * priv = griommupriv;
- unsigned int val;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
- DBG("Wrong pointer.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Get init value */
- if (options == GRIOMMU_OPTIONS_APV_ALLOW){
- val = 0x0;
- }else{
- val = 0xffffffff;
- }
-
- return griommu_apv_set(apv, index, size, val);
-}
-
-int griommu_apv_address_set(void * apv, uint32_t addr, int size, int options)
-{
- struct griommu_priv * priv = griommupriv;
- unsigned int val;
- int startpage;
- int endpage;
- int npages;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
- DBG("Wrong pointer.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Get init value */
- if (options == GRIOMMU_OPTIONS_APV_ALLOW){
- val = 0x0;
- }else{
- val = 0xffffffff;
- }
-
- /* Get start page */
- startpage = (addr / priv->pagesize);
-
- /* Get end page */
- endpage = ((addr + size)/ priv->pagesize);
-
- /* Get number of pages */
- npages = endpage - startpage + 1;
-
- return griommu_apv_set(apv, startpage, npages, val);
-}
-
-int griommu_group_info(int group, uint32_t * info)
-{
- struct griommu_priv * priv = griommupriv;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if ((group < 0) || (group >= priv->groups)){
- DBG("Wrong group id.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- if (info == NULL){
- DBG("Wrong pointer.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Get group */
- *info = griommu_reg_group(group);
-
- return GRIOMMU_ERR_OK;
-}
-
-/* Flush APV cache group:
- */
-int griommu_group_apv_flush(int group)
-{
- struct griommu_priv * priv = griommupriv;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- if ((group < 0) || (group >= priv->groups)){
- DBG("Wrong group id.\n");
- return GRIOMMU_ERR_EINVAL;
- }
-
- /* Flush cache */
- if (priv->cache_enabled){
- if (priv->group_addressing){
- griommu_reg_flush_set(((group << FLUSH_FGRP_BIT) & FLUSH_FGRP) |
- FLUSH_GF | FLUSH_F);
- }else{
- griommu_reg_flush_set(FLUSH_F);
- }
- DBG("GRIOMMU APV cache flushed.\n");
- }
-
- return GRIOMMU_ERR_OK;
-}
-
-/* Flush APV cache:
- */
-int griommu_apv_flush(void)
-{
- struct griommu_priv * priv = griommupriv;
-
- if (priv == NULL){
- DBG("GRIOMMU not initialized.\n");
- return GRIOMMU_ERR_NOINIT;
- }
-
- /* Flush cache */
- if (priv->cache_enabled){
- griommu_reg_flush_set(FLUSH_F);
- DBG("GRIOMMU APV cache flushed.\n");
- }
-
- return GRIOMMU_ERR_OK;
-}
-