File indexing completed on 2025-05-11 08:24:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <stdlib.h>
0032 #include <string.h>
0033 #include <drvmgr/drvmgr.h>
0034 #include <grlib/ambapp_bus.h>
0035 #include <grlib/ambapp.h>
0036 #include <rtems.h>
0037 #include <rtems/bspIo.h>
0038 #include <bsp.h>
0039 #include <grlib/griommu.h>
0040
0041 #include <grlib/grlib_impl.h>
0042
0043
0044 #define STATIC static
0045
0046
0047 #define INLINE inline
0048
0049 #define UNUSED __attribute__((unused))
0050
0051
0052
0053 #ifdef DEBUG
0054 #define DBG(x...) printf(x)
0055 #else
0056 #define DBG(x...)
0057 #endif
0058
0059
0060
0061
0062 #define CAP0_A (0x1 << CAP0_A_BIT)
0063 #define CAP0_AC (0x1 << CAP0_AC_BIT)
0064 #define CAP0_CA (0x1 << CAP0_CA_BIT)
0065 #define CAP0_CP (0x1 << CAP0_CP_BIT)
0066 #define CAP0_NARB (0xf << CAP0_NARB_BIT)
0067 #define CAP0_CS (0x1 << CAP0_CS_BIT)
0068 #define CAP0_FT (0x3 << CAP0_FT_BIT)
0069 #define CAP0_ST (0x1 << CAP0_ST_BIT)
0070 #define CAP0_I (0x1 << CAP0_I_BIT)
0071 #define CAP0_IT (0x1 << CAP0_IT_BIT)
0072 #define CAP0_IA (0x1 << CAP0_IA_BIT)
0073 #define CAP0_IP (0x1 << CAP0_IP_BIT)
0074 #define CAP0_MB (0x1 << CAP0_MB_BIT)
0075 #define CAP0_GRPS (0xf << CAP0_GRPS_BIT)
0076 #define CAP0_MSTS (0xf << CAP0_MSTS_BIT)
0077
0078 #define CAP0_A_BIT 31
0079 #define CAP0_AC_BIT 30
0080 #define CAP0_CA_BIT 29
0081 #define CAP0_CP_BIT 28
0082 #define CAP0_NARB_BIT 20
0083 #define CAP0_CS_BIT 19
0084 #define CAP0_FT_BIT 17
0085 #define CAP0_ST_BIT 16
0086 #define CAP0_I_BIT 15
0087 #define CAP0_IT_BIT 14
0088 #define CAP0_IA_BIT 13
0089 #define CAP0_IP_BIT 12
0090 #define CAP0_MB_BIT 8
0091 #define CAP0_GRPS_BIT 4
0092 #define CAP0_MSTS_BIT 0
0093
0094
0095
0096
0097 #define CAP1_CADDR (0xfff << CAP1_CADDR_BIT)
0098 #define CAP1_CMASK (0xf << CAP1_CMASK_BIT)
0099 #define CAP1_CTAGBITS (0xff << CAP1_CTAGBITS_BIT)
0100 #define CAP1_CISIZE (0x7 << CAP1_CISIZE_BIT)
0101 #define CAP1_CLINES (0x1f << CAP1_CLINES_BIT)
0102
0103 #define CAP1_CADDR_BIT 20
0104 #define CAP1_CMASK_BIT 16
0105 #define CAP1_CTAGBITS_BIT 8
0106 #define CAP1_CISIZE_BIT 5
0107 #define CAP1_CLINES_BIT 0
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 #define FLUSH_FGRP (0xf << FLUSH_FGRP_BIT)
0118 #define FLUSH_GF (0x1 << FLUSH_GF_BIT)
0119 #define FLUSH_F (0x1 << FLUSH_F_BIT)
0120
0121 #define FLUSH_FGRP_BIT 4
0122 #define FLUSH_GF_BIT 1
0123 #define FLUSH_F_BIT 0
0124
0125
0126
0127
0128 #define STS_PE (0x1 << STS_PE_BIT)
0129 #define STS_DE (0x1 << STS_DE_BIT)
0130 #define STS_FC (0x1 << STS_FC_BIT)
0131 #define STS_FL (0x1 << STS_FL_BIT)
0132 #define STS_AD (0x1 << STS_AD_BIT)
0133 #define STS_TE (0x1 << STS_TE_BIT)
0134 #define STS_ALL (STS_PE | STS_DE | STS_FC | STS_FL | STS_AD | STS_TE)
0135
0136 #define STS_PE_BIT 5
0137 #define STS_DE_BIT 4
0138 #define STS_FC_BIT 3
0139 #define STS_FL_BIT 2
0140 #define STS_AD_BIT 1
0141 #define STS_TE_BIT 0
0142
0143
0144
0145
0146 #define IMASK_PEI (0x1 << IMASK_PEI_BIT)
0147 #define IMASK_FCI (0x1 << IMASK_FCI_BIT)
0148 #define IMASK_FLI (0x1 << IMASK_FLI_BIT)
0149 #define IMASK_ADI (0x1 << IMASK_ADI_BIT)
0150 #define IMASK_TEI (0x1 << IMASK_TEI_BIT)
0151 #define IMASK_ALL (IMASK_PEI | IMASK_FCI | IMASK_FLI | IMASK_ADI | IMASK_TEI)
0152
0153 #define IMASK_PEI_BIT 5
0154 #define IMASK_FCI_BIT 3
0155 #define IMASK_FLI_BIT 2
0156 #define IMASK_ADI_BIT 1
0157 #define IMASK_TEI_BIT 0
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 #define MASTER_BS_BUS0 0
0175 #define MASTER_BS_BUS1 MASTER_BS
0176
0177
0178
0179
0180 #define GRP_BASE (0xfffffff << GRP_BASE_BIT)
0181 #define GRP_P (0x1 << GRP_P_BIT)
0182 #define GRP_AG (0x1 << GRP_AG_BIT)
0183
0184 #define GRP_BASE_BIT 4
0185 #define GRP_P_BIT 1
0186 #define GRP_AG_BIT 0
0187
0188
0189 #define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val))
0190 #define REG_READ(addr) (*(volatile unsigned int *)(addr))
0191
0192
0193
0194
0195 struct griommu_regs {
0196 volatile unsigned int cap0;
0197 volatile unsigned int cap1;
0198 volatile unsigned int cap2;
0199 volatile unsigned int resv1;
0200 volatile unsigned int ctrl;
0201 volatile unsigned int flush;
0202 volatile unsigned int status;
0203 volatile unsigned int imask;
0204 volatile unsigned int ahbstat;
0205 volatile unsigned int resv2[7];
0206 volatile unsigned int master[16];
0207 volatile unsigned int grp_ctrl[16];
0208 volatile unsigned int diag_ca;
0209 volatile unsigned int diag_cad[8];
0210 volatile unsigned int diag_cat;
0211 volatile unsigned int ei_data;
0212 volatile unsigned int ei_tag;
0213 volatile unsigned int resv3[4];
0214 volatile unsigned int asmpctrl[16];
0215 };
0216
0217 #define DEVNAME_LEN 9
0218
0219
0220
0221 struct griommu_priv {
0222 struct drvmgr_dev *dev;
0223 char devname[DEVNAME_LEN];
0224
0225 struct griommu_regs *regs;
0226
0227
0228 int apv;
0229 int apv_cache;
0230 int apv_cache_addr;
0231 int conf_pagesize;
0232
0233 int groups;
0234 int masters;
0235
0236
0237 int pagesize;
0238
0239
0240 int cache_enabled;
0241 int group_addressing;
0242
0243
0244 griommu_isr_t isr;
0245 void *isr_arg;
0246 };
0247
0248
0249
0250
0251
0252 STATIC INLINE unsigned int griommu_reg_cap0(void);
0253 STATIC INLINE unsigned int griommu_reg_cap1(void);
0254 STATIC INLINE unsigned int griommu_reg_ctrl(void);
0255 STATIC INLINE int griommu_reg_ctrl_set(unsigned int val);
0256 STATIC INLINE int griommu_reg_flush_set(unsigned int val);
0257 STATIC INLINE unsigned int griommu_reg_status(void);
0258 STATIC INLINE int griommu_reg_status_clear(unsigned int val);
0259 STATIC INLINE unsigned int griommu_reg_imask(void);
0260 STATIC INLINE int griommu_reg_imask_set(int mask);
0261 STATIC INLINE unsigned int griommu_reg_ahbfas(void);
0262 STATIC INLINE unsigned int griommu_reg_master(int master);
0263 STATIC INLINE int griommu_reg_master_set(int master, unsigned int val);
0264 STATIC INLINE unsigned int griommu_reg_group(int group);
0265 STATIC INLINE int griommu_reg_group_set(int group, unsigned int val);
0266
0267
0268 STATIC void griommu_apv_set_word(unsigned int * wordptr, int startbitidx,
0269 int nbits, unsigned int val);
0270 STATIC int griommu_apv_set(void * apv, int index, int size, unsigned int val);
0271
0272
0273 int griommu_init1(struct drvmgr_dev *dev);
0274 STATIC int griommu_init(struct griommu_priv *priv);
0275
0276
0277
0278 void griommu_isr(void *arg);
0279
0280
0281
0282
0283 static struct griommu_priv *griommupriv = NULL;
0284
0285
0286
0287 struct drvmgr_drv_ops griommu_ops =
0288 {
0289 .init = {griommu_init1, NULL, NULL, NULL},
0290 .remove = NULL,
0291 .info = NULL
0292 };
0293
0294 struct amba_dev_id griommu_ids[] =
0295 {
0296 {VENDOR_GAISLER, GAISLER_GRIOMMU},
0297 {0, 0}
0298 };
0299
0300 struct amba_drv_info griommu_info =
0301 {
0302 {
0303 DRVMGR_OBJ_DRV,
0304 NULL,
0305 NULL,
0306 DRIVER_AMBAPP_GAISLER_GRIOMMU_ID,
0307 "GRIOMMU_DRV",
0308 DRVMGR_BUS_TYPE_AMBAPP,
0309 &griommu_ops,
0310 NULL,
0311 0,
0312 sizeof(struct griommu_priv),
0313 },
0314 &griommu_ids[0]
0315 };
0316
0317 void griommu_register_drv(void)
0318 {
0319 DBG("Registering GRIOMMU driver\n");
0320 drvmgr_drv_register(&griommu_info.general);
0321 }
0322
0323
0324
0325
0326
0327
0328 STATIC int griommu_init(struct griommu_priv *priv)
0329 {
0330 struct ambapp_ahb_info *ahb;
0331 struct amba_dev_info *ainfo = priv->dev->businfo;
0332
0333
0334 ahb = ainfo->info.ahb_slv;
0335
0336
0337 priv->regs = (struct griommu_regs *)ahb->start[0];
0338
0339
0340 griommu_reg_imask_set(0);
0341
0342
0343 uint32_t cap0 = griommu_reg_cap0();
0344 priv->apv = (cap0 & CAP0_A) >> CAP0_A_BIT;
0345 priv->apv_cache = (cap0 & CAP0_AC) >> CAP0_AC_BIT;
0346 priv->apv_cache_addr = (cap0 & CAP0_CA) >> CAP0_CA_BIT;
0347 priv->conf_pagesize = (cap0 & CAP0_CS) >> CAP0_CS_BIT;
0348 priv->groups = ((cap0 & CAP0_GRPS) >> CAP0_GRPS_BIT) + 1;
0349 priv->masters = ((cap0 & CAP0_MSTS) >> CAP0_MSTS_BIT) + 1;
0350
0351
0352 uint32_t ctrl = griommu_reg_ctrl();
0353 if (priv->conf_pagesize){
0354 priv->pagesize = (4*1024 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT));
0355 }else{
0356 priv->pagesize = 4*1024;
0357 }
0358 priv->cache_enabled = (ctrl & CTRL_CE);
0359 priv->group_addressing = (ctrl & CTRL_GS);
0360
0361 DBG("GRIOMMU Capabilities: APV=%d, APVC=%d, APVCA=%d, CS=%d, "
0362 "GRPS=%d, MSTS=%d\n",
0363 priv->apv, priv->apv_cache, priv->apv_cache_addr,
0364 priv->conf_pagesize, priv->groups, priv->masters);
0365 DBG("GRIOMMU driver initialized\n");
0366
0367 return 0;
0368 }
0369
0370
0371
0372
0373 int griommu_init1(struct drvmgr_dev *dev)
0374 {
0375 int status;
0376 struct griommu_priv *priv;
0377
0378 DBG("GRIOMMU[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0379
0380 if (griommupriv) {
0381 DBG("Driver only supports one GRIOMMU core\n");
0382 return DRVMGR_FAIL;
0383 }
0384
0385 priv = dev->priv;
0386 if (!priv)
0387 return DRVMGR_NOMEM;
0388
0389 priv->dev = dev;
0390 strncpy(&priv->devname[0], "griommu0", DEVNAME_LEN);
0391 griommupriv = priv;
0392
0393
0394 status = griommu_init(priv);
0395 if (status) {
0396 printk("Failed to initialize griommu driver %d\n", status);
0397 return -1;
0398 }
0399
0400 return DRVMGR_OK;
0401 }
0402
0403 STATIC INLINE unsigned int griommu_reg_cap0(void)
0404 {
0405 struct griommu_priv *priv = griommupriv;
0406
0407 return REG_READ(&priv->regs->cap0);
0408 }
0409
0410 STATIC INLINE unsigned int griommu_reg_cap1(void)
0411 {
0412 struct griommu_priv *priv = griommupriv;
0413
0414 return REG_READ(&priv->regs->cap1);
0415 }
0416
0417 STATIC INLINE unsigned int griommu_reg_ctrl(void)
0418 {
0419 struct griommu_priv *priv = griommupriv;
0420
0421 return REG_READ(&priv->regs->ctrl);
0422 }
0423
0424 STATIC INLINE int griommu_reg_ctrl_set(unsigned int val)
0425 {
0426 struct griommu_priv *priv = griommupriv;
0427
0428 REG_WRITE(&priv->regs->ctrl, val);
0429 return 0;
0430 }
0431
0432 STATIC INLINE int griommu_reg_flush_set(unsigned int val)
0433 {
0434 struct griommu_priv *priv = griommupriv;
0435
0436 REG_WRITE(&priv->regs->flush, val);
0437 return 0;
0438 }
0439
0440 STATIC INLINE unsigned int griommu_reg_status(void)
0441 {
0442 struct griommu_priv *priv = griommupriv;
0443
0444 return REG_READ(&priv->regs->status);
0445 }
0446
0447 STATIC INLINE int griommu_reg_status_clear(unsigned int val)
0448 {
0449 struct griommu_priv *priv = griommupriv;
0450
0451
0452 REG_WRITE(&priv->regs->status, (val & STS_ALL));
0453 return 0;
0454 }
0455
0456 STATIC INLINE unsigned int griommu_reg_imask(void)
0457 {
0458 struct griommu_priv *priv = griommupriv;
0459
0460 return REG_READ(&priv->regs->imask);
0461 }
0462
0463 STATIC INLINE int griommu_reg_imask_set(int mask)
0464 {
0465 struct griommu_priv *priv = griommupriv;
0466
0467
0468 REG_WRITE(&priv->regs->imask, (mask & IMASK_ALL));
0469 return 0;
0470 }
0471
0472 STATIC INLINE unsigned int griommu_reg_ahbfas(void)
0473 {
0474 struct griommu_priv *priv = griommupriv;
0475
0476 return REG_READ(&priv->regs->ahbstat);
0477 }
0478
0479 STATIC INLINE int griommu_reg_master_set(int master, unsigned int val)
0480 {
0481 struct griommu_priv *priv = griommupriv;
0482
0483
0484 REG_WRITE(&priv->regs->master[master], val);
0485 return 0;
0486 }
0487
0488 STATIC INLINE unsigned int griommu_reg_master(int master)
0489 {
0490 struct griommu_priv *priv = griommupriv;
0491
0492 return REG_READ(&priv->regs->master[master]);
0493 }
0494
0495 STATIC INLINE unsigned int griommu_reg_group(int group)
0496 {
0497 struct griommu_priv *priv = griommupriv;
0498
0499 return REG_READ(&priv->regs->grp_ctrl[group]);
0500 }
0501
0502 STATIC INLINE int griommu_reg_group_set(int group, unsigned int val)
0503 {
0504 struct griommu_priv *priv = griommupriv;
0505
0506 REG_WRITE(&priv->regs->grp_ctrl[group], val);
0507 return 0;
0508 }
0509
0510 STATIC void griommu_apv_set_word(unsigned int * wordptr, int startbitidx,
0511 int nbits, unsigned int val)
0512 {
0513 unsigned int mask;
0514 unsigned int word = *wordptr;
0515 int endbitidx = startbitidx + nbits - 1;
0516
0517
0518 mask = 0xffffffff;
0519
0520
0521 mask >>= startbitidx;
0522
0523
0524 mask >>= (31 - endbitidx);
0525 mask <<= (31 - endbitidx);
0526
0527 DBG("Setting word: startbitdx=%d, endbitidx=%d, mask=0x%02x",
0528 startbitidx, endbitidx, (unsigned int) mask);
0529
0530
0531 word &= ~(mask);
0532
0533
0534 mask &= val;
0535 word |= mask;
0536
0537 DBG(", old word=0x%08x, new word=0x%08x\n",*wordptr, word);
0538
0539
0540 *wordptr=word;
0541 }
0542
0543
0544 STATIC int griommu_apv_set(void * apv, int index, int size, unsigned int val)
0545 {
0546 unsigned int * words = (unsigned int *) apv;
0547 int len = size;
0548 int wordidx = (index/32);
0549 int startbit = (index % 32);
0550 int nbits;
0551 int nwords;
0552
0553
0554 if (startbit != 0){
0555
0556 if (startbit + len < 32){
0557 nbits = len;
0558 }else{
0559 nbits = 32 - startbit;
0560 }
0561 griommu_apv_set_word(&words[wordidx], startbit, nbits, val);
0562 DBG("First word: wordidx=%d, startbit=%d, bits=%d, val=0x%08x\n",
0563 wordidx, startbit, nbits, words[wordidx]);
0564
0565
0566 len = len - nbits;
0567 wordidx++;
0568 }
0569
0570
0571 if (len != 0){
0572 nwords = (len/32);
0573 memset((void *) &words[wordidx], val, nwords*4);
0574 DBG("Middle words: wordidx=%d, nwords=%d\n", wordidx, nwords);
0575
0576 wordidx = wordidx + nwords;
0577 len = len - nwords*32;
0578 }
0579
0580
0581 if (len != 0){
0582 nbits = len;
0583 griommu_apv_set_word(&words[wordidx], 0, nbits, val);
0584 DBG("First word: wordidx=%d, startbit=%d, bits=%d, val=0x%08x\n",
0585 wordidx, 0, nbits, words[wordidx]);
0586
0587 len = len - (nbits);
0588 }
0589
0590 return GRIOMMU_ERR_OK;
0591 }
0592
0593
0594
0595 void griommu_isr(void *arg)
0596 {
0597 struct griommu_priv *priv = arg;
0598 unsigned int sts = griommu_reg_status();
0599 unsigned int mask = griommu_reg_imask();
0600 unsigned int access = griommu_reg_ahbfas();
0601
0602
0603
0604
0605 if ((sts & STS_ALL) & (mask & IMASK_ALL)){
0606
0607 griommu_reg_status_clear(sts);
0608
0609 (priv->isr)(priv->isr_arg, access, sts);
0610 }
0611 }
0612
0613
0614
0615 int griommu_master_setup(int master, int group, int options)
0616 {
0617 struct griommu_priv * priv = griommupriv;
0618
0619 if (priv == NULL){
0620 DBG("GRIOMMU not initialized.\n");
0621 return GRIOMMU_ERR_NOINIT;
0622 }
0623
0624 if ((master < 0) || (master >= priv->masters)){
0625 DBG("Wrong master id.\n");
0626 return GRIOMMU_ERR_EINVAL;
0627 }
0628
0629 if ((group < 0) || (group >= priv->groups)){
0630 DBG("Wrong group id.\n");
0631 return GRIOMMU_ERR_EINVAL;
0632 }
0633
0634 griommu_reg_master_set(master,
0635 ((options & GRIOMMU_OPTIONS_BUS1)? MASTER_BS_BUS1: MASTER_BS_BUS0)|
0636 ((group << MASTER_GROUP_BIT) & MASTER_GROUP)
0637 );
0638
0639 DBG("IOMMU master setup: master %d, traffic routed %s, group %d\n",
0640 master,
0641 (options & GRIOMMU_OPTIONS_BUS1) ?
0642 "to Secondary bus":"to Primary bus",
0643 group);
0644
0645 return GRIOMMU_ERR_OK;
0646 }
0647
0648
0649
0650
0651 int griommu_master_info(int master, uint32_t * info)
0652 {
0653 struct griommu_priv * priv = griommupriv;
0654
0655 if (priv == NULL){
0656 DBG("GRIOMMU not initialized.\n");
0657 return GRIOMMU_ERR_NOINIT;
0658 }
0659
0660 if ((master < 0) || (master >= priv->masters)){
0661 DBG("Wrong master id.\n");
0662 return GRIOMMU_ERR_EINVAL;
0663 }
0664
0665 if (info == NULL){
0666 DBG("Wrong pointer.\n");
0667 return GRIOMMU_ERR_EINVAL;
0668 }
0669
0670
0671 *info = griommu_reg_master(master);
0672
0673 return GRIOMMU_ERR_OK;
0674 }
0675
0676
0677
0678 int griommu_master_find(int vendor, int device, int instance)
0679 {
0680 struct griommu_priv * priv = griommupriv;
0681 int i, gotvendor, gotdevice;
0682 unsigned int master;
0683 int found;
0684
0685 if (priv == NULL){
0686 DBG("GRIOMMU not initialized.\n");
0687 return GRIOMMU_ERR_NOINIT;
0688 }
0689
0690
0691 found=0;
0692 for (i=0; i< priv->masters; i++){
0693 master = griommu_reg_master(i);
0694 gotvendor = (master & MASTER_VENDOR) >> MASTER_VENDOR_BIT;
0695 gotdevice = (master & MASTER_DEVICE) >> MASTER_DEVICE_BIT;
0696 if ((gotvendor == vendor) && (gotdevice == device)){
0697 if(found == instance){
0698 DBG("Found master %d: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), "
0699 "Instance=%d\n",
0700 i,
0701 ambapp_vendor_id2str(vendor), vendor,
0702 ambapp_device_id2str(vendor,device), device, instance
0703 );
0704 return i;
0705 }
0706 found++;
0707 }
0708 }
0709
0710 DBG("Master not found: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), "
0711 "Instance=%d\n",
0712 ambapp_vendor_id2str(vendor), vendor,
0713 ambapp_device_id2str(vendor,device), device, instance
0714 );
0715 return GRIOMMU_ERR_NOTFOUND;
0716 }
0717
0718
0719
0720 int griommu_setup(int options)
0721 {
0722 struct griommu_priv * priv = griommupriv;
0723 unsigned int ctrl;
0724
0725 if (priv == NULL){
0726 DBG("GRIOMMU not initialized.\n");
0727 return GRIOMMU_ERR_NOINIT;
0728 }
0729
0730
0731 if (options & GRIOMMU_OPTIONS_CACHE_ENABLE) {
0732 if (priv->apv_cache){
0733
0734 griommu_reg_flush_set(FLUSH_F);
0735 priv->cache_enabled = 1;
0736 }else{
0737 DBG("GRIOMMU APV cache not supported.\n");
0738 return GRIOMMU_ERR_IMPLEMENTED;
0739 }
0740 }else{
0741 priv->cache_enabled = 0;
0742 }
0743
0744
0745 if (options & GRIOMMU_OPTIONS_GROUPADDRESSING_ENABLE){
0746 if (priv->apv_cache_addr){
0747 priv->group_addressing = 1;
0748 }else{
0749 DBG("GRIOMMU APV cache group addressing not supported.\n");
0750 return GRIOMMU_ERR_IMPLEMENTED;
0751 }
0752 }else{
0753 priv->group_addressing = 0;
0754 }
0755
0756
0757 if ((options & CTRL_PGSZ) != GRIOMMU_OPTIONS_PAGESIZE_4KIB){
0758 if (priv->conf_pagesize == 0){
0759 DBG("GRIOMMU Configurable pagesize not supported.\n");
0760 return GRIOMMU_ERR_IMPLEMENTED;
0761 }
0762 }
0763
0764
0765 ctrl = griommu_reg_ctrl();
0766
0767
0768 ctrl &= ~(CTRL_CE | CTRL_GS | CTRL_PGSZ | CTRL_LB |
0769 CTRL_DP | CTRL_AU | CTRL_WP);
0770
0771
0772 options &= (CTRL_CE | CTRL_GS | CTRL_PGSZ | CTRL_LB |
0773 CTRL_DP | CTRL_AU | CTRL_WP);
0774
0775
0776 ctrl |= options;
0777
0778
0779 griommu_reg_ctrl_set(ctrl);
0780
0781 DBG("IOMMU setup: prefetching %s, cache %s, groupaddr %s, "
0782 "lookup bus %s, ahb update %s,\nwprot only %s, pagesize %d KiB\n",
0783 ((options & GRIOMMU_OPTIONS_PREFETCH_DISABLE)?
0784 "disabled":"enabled"),
0785 ((options & GRIOMMU_OPTIONS_CACHE_ENABLE)? "enabled":"disabled"),
0786 ((options & GRIOMMU_OPTIONS_GROUPADDRESSING_ENABLE)?
0787 "enabled":"disabled"),
0788 ((options & GRIOMMU_OPTIONS_LOOKUPBUS_BUS1)? "bus1":"bus0"),
0789 ((options & GRIOMMU_OPTIONS_AHBUPDATE_ENABLE)?
0790 "enabled":"disabled"),
0791 ((options & GRIOMMU_OPTIONS_WPROTONLY_ENABLE)?
0792 "enabled":"disabled"),
0793 (4 << ((options & GRIOMMU_OPTIONS_PAGESIZE_512KIB) >> 18))
0794 );
0795
0796 return GRIOMMU_ERR_OK;
0797 }
0798
0799
0800
0801 int griommu_status(void)
0802 {
0803 struct griommu_priv * priv = griommupriv;
0804 unsigned int ctrl;
0805
0806 if (priv == NULL){
0807 DBG("GRIOMMU not initialized.\n");
0808 return GRIOMMU_ERR_NOINIT;
0809 }
0810
0811
0812 ctrl = griommu_reg_ctrl();
0813
0814 DBG("IOMMU status: prefetching %s, cache %s, groupaddr %s, "
0815 "lookup bus %s, ahb update %s,\nwprot only %s, pagesize %d KiB\n",
0816 ((ctrl & CTRL_DP)? "disabled":"enabled"),
0817 ((ctrl & CTRL_CE)? "enabled":"disabled"),
0818 ((ctrl & CTRL_GS)? "enabled":"disabled"),
0819 ((ctrl & CTRL_LB)? "bus1":"bus0"),
0820 ((ctrl & CTRL_AU)? "enabled":"disabled"),
0821 ((ctrl & CTRL_WP)? "enabled":"disabled"),
0822 (4 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT))
0823 );
0824
0825 return ctrl;
0826 }
0827
0828 int griommu_isr_register(griommu_isr_t isr, void * arg, int options)
0829 {
0830 struct griommu_priv *priv = griommupriv;
0831 unsigned int mask;
0832
0833 if (priv == NULL){
0834 DBG("GRIOMMU not initialized.\n");
0835 return GRIOMMU_ERR_NOINIT;
0836 }
0837
0838 if (isr == NULL){
0839 DBG("GRIOMMU wrong isr.\n");
0840 return GRIOMMU_ERR_EINVAL;
0841 }
0842
0843
0844 mask = 0 |
0845 ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) |
0846 ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) |
0847 ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) |
0848 ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) |
0849 ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0);
0850
0851
0852 griommu_reg_status_clear(STS_ALL);
0853 griommu_reg_imask_set(0);
0854
0855
0856 if (priv->isr == NULL){
0857
0858 drvmgr_interrupt_register(priv->dev, 0, priv->devname, griommu_isr,
0859 priv);
0860 }
0861
0862
0863 priv->isr=isr;
0864 priv->isr_arg=arg;
0865
0866
0867 griommu_reg_imask_set(mask);
0868
0869 return GRIOMMU_ERR_OK;
0870 }
0871
0872 int griommu_isr_unregister(void)
0873 {
0874 struct griommu_priv *priv = griommupriv;
0875
0876 if (priv == NULL){
0877 DBG("GRIOMMU not initialized.\n");
0878 return GRIOMMU_ERR_NOINIT;
0879 }
0880
0881 if (priv->isr == NULL){
0882 DBG("GRIOMMU wrong isr.\n");
0883 return GRIOMMU_ERR_EINVAL;
0884 }
0885
0886
0887 griommu_reg_status_clear(STS_ALL);
0888 griommu_reg_imask_set(0);
0889
0890
0891 drvmgr_interrupt_unregister(priv->dev, 0, griommu_isr, priv);
0892
0893
0894 priv->isr=NULL;
0895 priv->isr_arg=NULL;
0896
0897 return GRIOMMU_ERR_OK;
0898 }
0899
0900 int griommu_interrupt_unmask(int options)
0901 {
0902 struct griommu_priv *priv = griommupriv;
0903 unsigned int mask, irq;
0904
0905 if (priv == NULL){
0906 DBG("GRIOMMU not initialized.\n");
0907 return GRIOMMU_ERR_NOINIT;
0908 }
0909
0910 if (priv->isr == NULL){
0911 DBG("GRIOMMU wrong isr.\n");
0912 return GRIOMMU_ERR_EINVAL;
0913 }
0914
0915
0916 mask = 0 |
0917 ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) |
0918 ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) |
0919 ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) |
0920 ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) |
0921 ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0);
0922
0923
0924 griommu_reg_status_clear(STS_ALL);
0925
0926
0927 irq = griommu_reg_imask() & IMASK_ALL;
0928
0929
0930 griommu_reg_imask_set(irq | mask);
0931
0932 return GRIOMMU_ERR_OK;
0933 }
0934
0935 int griommu_interrupt_mask(int options)
0936 {
0937 struct griommu_priv *priv = griommupriv;
0938 unsigned int mask, irq;
0939
0940 if (priv == NULL){
0941 DBG("GRIOMMU not initialized.\n");
0942 return GRIOMMU_ERR_NOINIT;
0943 }
0944
0945 if (priv->isr == NULL){
0946 DBG("GRIOMMU wrong isr.\n");
0947 return GRIOMMU_ERR_EINVAL;
0948 }
0949
0950
0951 mask = 0 |
0952 ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) |
0953 ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) |
0954 ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) |
0955 ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) |
0956 ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0);
0957
0958
0959 griommu_reg_status_clear(STS_ALL);
0960
0961
0962 irq = griommu_reg_imask() & IMASK_ALL;
0963
0964
0965 griommu_reg_imask_set(irq & ~(mask));
0966
0967 return GRIOMMU_ERR_OK;
0968 }
0969
0970 int griommu_error_status(uint32_t * access)
0971 {
0972 struct griommu_priv *priv = griommupriv;
0973 int status;
0974
0975 if (priv == NULL){
0976 DBG("GRIOMMU not initialized.\n");
0977 return GRIOMMU_ERR_NOINIT;
0978 }
0979
0980
0981 status = griommu_reg_status();
0982
0983 if (status != 0){
0984
0985 if (access != NULL){
0986 *access = griommu_reg_ahbfas();
0987 }
0988
0989 griommu_reg_status_clear(status);
0990 }
0991
0992 return status;
0993 }
0994
0995
0996
0997
0998 int griommu_print(void)
0999 {
1000 #ifdef DEBUG
1001 struct griommu_priv * priv = griommupriv;
1002 unsigned int ctrl;
1003
1004 if (priv == NULL){
1005 DBG("GRIOMMU not initialized.\n");
1006 return GRIOMMU_ERR_NOINIT;
1007 }
1008
1009
1010 ctrl = griommu_reg_ctrl();
1011
1012 printf("IOMMU status: prefetching %s, lookup bus %s, ahb update %s,\n"
1013 "wprot only %s, pagesize %d KiB\n",
1014 ((ctrl & CTRL_DP)? "disabled":"enabled"),
1015 ((ctrl & CTRL_LB)? "bus1":"bus0"),
1016 ((ctrl & CTRL_AU)? "enabled":"disabled"),
1017 ((ctrl & CTRL_WP)? "enabled":"disabled"),
1018 (4 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT))
1019 );
1020
1021
1022 int i, vendor, device, routing;
1023 unsigned int master;
1024 for (i=0; i < priv->masters; i++){
1025 master = griommu_reg_master(i);
1026 vendor = (master & MASTER_VENDOR) >> MASTER_VENDOR_BIT;
1027 device = (master & MASTER_DEVICE) >> MASTER_DEVICE_BIT;
1028 routing = (master & MASTER_BS);
1029 printf("IOMMU master %d: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), "
1030 "BS=%s\n",
1031 i,
1032 ambapp_vendor_id2str(vendor), vendor,
1033 ambapp_device_id2str(vendor,device), device,
1034 (routing == MASTER_BS_BUS0? "Primary bus" : "Secondary bus")
1035 );
1036 }
1037 #endif
1038 return GRIOMMU_ERR_OK;
1039 }
1040
1041 void * griommu_apv_new(void)
1042 {
1043 struct griommu_priv * priv = griommupriv;
1044
1045 if (priv == NULL){
1046 DBG("GRIOMMU not initialized.\n");
1047 return NULL;
1048 }
1049
1050
1051 unsigned int * orig_ptr = grlib_malloc(
1052 (GRIOMMU_APV_SIZE/priv->pagesize) + GRIOMMU_APV_ALIGN);
1053 if (orig_ptr == NULL) return NULL;
1054
1055
1056 unsigned int aligned_ptr = (
1057 ((unsigned int) orig_ptr + GRIOMMU_APV_ALIGN) &
1058 ~(GRIOMMU_APV_ALIGN - 1));
1059
1060
1061 unsigned int ** tmp_ptr =
1062 (unsigned int **) (aligned_ptr - sizeof(orig_ptr));
1063 *tmp_ptr= orig_ptr;
1064
1065
1066 return (void *) aligned_ptr;
1067 }
1068
1069 void griommu_apv_delete(void * apv)
1070 {
1071
1072 unsigned int * orig_ptr;
1073 unsigned int ** tmp_ptr = (unsigned int **) (apv - sizeof(orig_ptr));
1074 orig_ptr = *tmp_ptr;
1075
1076
1077 free(orig_ptr);
1078 }
1079
1080 int griommu_enable(int mode)
1081 {
1082 struct griommu_priv * priv = griommupriv;
1083 unsigned int ctrl;
1084
1085 if (priv == NULL){
1086 DBG("GRIOMMU not initialized.\n");
1087 return GRIOMMU_ERR_NOINIT;
1088 }
1089
1090 switch (mode){
1091 case GRIOMMU_MODE_IOMMU:
1092 default:
1093 DBG("IOMMU mode not implemented in driver.\n");
1094 return GRIOMMU_ERR_EINVAL;
1095 break;
1096 case GRIOMMU_MODE_GROUPAPV:
1097 if (priv->apv == 0){
1098 DBG("IOMMU APV not supported.\n");
1099 return GRIOMMU_ERR_IMPLEMENTED;
1100 }
1101
1102 ctrl = (griommu_reg_ctrl() & ~(CTRL_PM));
1103 griommu_reg_ctrl_set(ctrl | CTRL_PM_APV | CTRL_EN);
1104
1105
1106 while((griommu_reg_ctrl() & CTRL_EN)==0){};
1107
1108 DBG("IOMMU enabled.\n");
1109 return GRIOMMU_ERR_OK;
1110 break;
1111 }
1112 return GRIOMMU_ERR_OK;
1113 }
1114
1115 int griommu_disable(void)
1116 {
1117 struct griommu_priv * priv = griommupriv;
1118 unsigned int ctrl;
1119
1120 if (priv == NULL){
1121 DBG("GRIOMMU not initialized.\n");
1122 return GRIOMMU_ERR_NOINIT;
1123 }
1124
1125
1126 ctrl = (griommu_reg_ctrl() & ~(CTRL_EN));
1127 griommu_reg_ctrl_set(ctrl);
1128
1129
1130 while(griommu_reg_ctrl() & CTRL_EN){};
1131
1132 return GRIOMMU_ERR_OK;
1133 }
1134
1135 int griommu_group_setup(int group, void * apv, int options)
1136 {
1137 struct griommu_priv * priv = griommupriv;
1138
1139 if (priv == NULL){
1140 DBG("GRIOMMU not initialized.\n");
1141 return GRIOMMU_ERR_NOINIT;
1142 }
1143
1144 if ((group < 0) || (group >= priv->groups)){
1145 DBG("Wrong group id.\n");
1146 return GRIOMMU_ERR_EINVAL;
1147 }
1148
1149 if ((options < 0) || (options > GRIOMMU_OPTIONS_GROUP_PASSTHROUGH)){
1150 DBG("Wrong options.\n");
1151 return GRIOMMU_ERR_EINVAL;
1152 }
1153
1154 if (options == GRIOMMU_OPTIONS_GROUP_DISABLE){
1155 if ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1)){
1156 DBG("Wrong pointer.\n");
1157 return GRIOMMU_ERR_EINVAL;
1158 }
1159
1160
1161 griommu_reg_group_set(group, (((unsigned int) apv) & GRP_BASE) | 0);
1162 DBG("GROUP[%d] DISABLED.\n", group);
1163 return GRIOMMU_ERR_OK;
1164 }else if (options == GRIOMMU_OPTIONS_GROUP_PASSTHROUGH){
1165 if ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1)){
1166 DBG("Wrong pointer.\n");
1167 return GRIOMMU_ERR_EINVAL;
1168 }
1169
1170
1171 griommu_reg_group_set(group,
1172 (((unsigned int) apv) & GRP_BASE) | GRP_P | GRP_AG);
1173 DBG("GROUP[%d] set to PASSTHROUGH.\n", group);
1174 return GRIOMMU_ERR_OK;
1175 }else{
1176 if (priv->apv == 0){
1177 DBG("IOMMU APV not supported.\n");
1178 return GRIOMMU_ERR_IMPLEMENTED;
1179 }
1180
1181 if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
1182 DBG("Wrong pointer.\n");
1183 return GRIOMMU_ERR_EINVAL;
1184 }
1185
1186
1187 griommu_reg_group_set(group,
1188 (((unsigned int) apv) & GRP_BASE) | GRP_AG);
1189 DBG("GROUP[%d] set to APV (0x%08x).\n", group, (unsigned int) apv);
1190 return GRIOMMU_ERR_OK;
1191 }
1192 }
1193
1194 int griommu_group_apv_init(int group, int options)
1195 {
1196 struct griommu_priv * priv = griommupriv;
1197 void * apv;
1198 int val;
1199 int ret;
1200 size_t len;
1201
1202
1203
1204 ret = griommu_group_apv_flush(group);
1205 if (ret < 0){
1206 return ret;
1207 }
1208
1209
1210 apv = (void *) (griommu_reg_group(group) & GRP_BASE);
1211
1212 if (apv == NULL){
1213 DBG("Wrong pointer.\n");
1214 return GRIOMMU_ERR_NOTFOUND;
1215 }
1216
1217
1218 if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1219 val = 0x00;
1220 }else{
1221 val = 0xff;
1222 }
1223
1224
1225 len = GRIOMMU_APV_SIZE/priv->pagesize;
1226
1227
1228 memset(apv, val, len);
1229
1230 return GRIOMMU_ERR_OK;
1231 }
1232
1233 int griommu_group_apv_page_set(int group, int index, int size, int options)
1234 {
1235 void * apv;
1236 unsigned int val;
1237 int ret;
1238
1239
1240
1241 ret = griommu_group_apv_flush(group);
1242 if (ret < 0){
1243 return ret;
1244 }
1245
1246
1247 apv = (void *) (griommu_reg_group(group) & GRP_BASE);
1248
1249 if (apv == NULL){
1250 DBG("Wrong pointer.\n");
1251 return GRIOMMU_ERR_NOTFOUND;
1252 }
1253
1254
1255 if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1256 val = 0x0;
1257 }else{
1258 val = 0xffffffff;
1259 }
1260
1261 return griommu_apv_set(apv, index, size, val);
1262 }
1263
1264 int griommu_group_apv_address_set(int group, uint32_t addr, int size,
1265 int options)
1266 {
1267 struct griommu_priv * priv = griommupriv;
1268 void * apv;
1269 unsigned int val;
1270 int ret;
1271 int startpage;
1272 int endpage;
1273 int npages;
1274
1275
1276
1277 ret = griommu_group_apv_flush(group);
1278 if (ret < 0){
1279 return ret;
1280 }
1281
1282
1283 apv = (void *) (griommu_reg_group(group) & GRP_BASE);
1284
1285 if (apv == NULL){
1286 DBG("Wrong pointer.\n");
1287 return GRIOMMU_ERR_NOTFOUND;
1288 }
1289
1290
1291 if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1292 val = 0x0;
1293 }else{
1294 val = 0xffffffff;
1295 }
1296
1297
1298 startpage = (addr / priv->pagesize);
1299
1300
1301 endpage = ((addr + size)/ priv->pagesize);
1302
1303
1304 npages = endpage - startpage + 1;
1305
1306 return griommu_apv_set(apv, startpage, npages, val);
1307 }
1308
1309 int griommu_apv_init(void * apv, int options)
1310 {
1311 struct griommu_priv * priv = griommupriv;
1312 int val;
1313 size_t len;
1314
1315 if (priv == NULL){
1316 DBG("GRIOMMU not initialized.\n");
1317 return GRIOMMU_ERR_NOINIT;
1318 }
1319
1320 if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
1321 DBG("Wrong pointer.\n");
1322 return GRIOMMU_ERR_EINVAL;
1323 }
1324
1325
1326 if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1327 val = 0x00;
1328 }else{
1329 val = 0xff;
1330 }
1331
1332
1333 len = GRIOMMU_APV_SIZE/priv->pagesize;
1334
1335
1336 memset(apv, val, len);
1337
1338 return GRIOMMU_ERR_OK;
1339 }
1340
1341 int griommu_apv_page_set(void * apv, int index, int size, int options)
1342 {
1343 struct griommu_priv * priv = griommupriv;
1344 unsigned int val;
1345
1346 if (priv == NULL){
1347 DBG("GRIOMMU not initialized.\n");
1348 return GRIOMMU_ERR_NOINIT;
1349 }
1350
1351 if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
1352 DBG("Wrong pointer.\n");
1353 return GRIOMMU_ERR_EINVAL;
1354 }
1355
1356
1357 if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1358 val = 0x0;
1359 }else{
1360 val = 0xffffffff;
1361 }
1362
1363 return griommu_apv_set(apv, index, size, val);
1364 }
1365
1366 int griommu_apv_address_set(void * apv, uint32_t addr, int size, int options)
1367 {
1368 struct griommu_priv * priv = griommupriv;
1369 unsigned int val;
1370 int startpage;
1371 int endpage;
1372 int npages;
1373
1374 if (priv == NULL){
1375 DBG("GRIOMMU not initialized.\n");
1376 return GRIOMMU_ERR_NOINIT;
1377 }
1378
1379 if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){
1380 DBG("Wrong pointer.\n");
1381 return GRIOMMU_ERR_EINVAL;
1382 }
1383
1384
1385 if (options == GRIOMMU_OPTIONS_APV_ALLOW){
1386 val = 0x0;
1387 }else{
1388 val = 0xffffffff;
1389 }
1390
1391
1392 startpage = (addr / priv->pagesize);
1393
1394
1395 endpage = ((addr + size)/ priv->pagesize);
1396
1397
1398 npages = endpage - startpage + 1;
1399
1400 return griommu_apv_set(apv, startpage, npages, val);
1401 }
1402
1403 int griommu_group_info(int group, uint32_t * info)
1404 {
1405 struct griommu_priv * priv = griommupriv;
1406
1407 if (priv == NULL){
1408 DBG("GRIOMMU not initialized.\n");
1409 return GRIOMMU_ERR_NOINIT;
1410 }
1411
1412 if ((group < 0) || (group >= priv->groups)){
1413 DBG("Wrong group id.\n");
1414 return GRIOMMU_ERR_EINVAL;
1415 }
1416
1417 if (info == NULL){
1418 DBG("Wrong pointer.\n");
1419 return GRIOMMU_ERR_EINVAL;
1420 }
1421
1422
1423 *info = griommu_reg_group(group);
1424
1425 return GRIOMMU_ERR_OK;
1426 }
1427
1428
1429
1430 int griommu_group_apv_flush(int group)
1431 {
1432 struct griommu_priv * priv = griommupriv;
1433
1434 if (priv == NULL){
1435 DBG("GRIOMMU not initialized.\n");
1436 return GRIOMMU_ERR_NOINIT;
1437 }
1438
1439 if ((group < 0) || (group >= priv->groups)){
1440 DBG("Wrong group id.\n");
1441 return GRIOMMU_ERR_EINVAL;
1442 }
1443
1444
1445 if (priv->cache_enabled){
1446 if (priv->group_addressing){
1447 griommu_reg_flush_set(((group << FLUSH_FGRP_BIT) & FLUSH_FGRP) |
1448 FLUSH_GF | FLUSH_F);
1449 }else{
1450 griommu_reg_flush_set(FLUSH_F);
1451 }
1452 DBG("GRIOMMU APV cache flushed.\n");
1453 }
1454
1455 return GRIOMMU_ERR_OK;
1456 }
1457
1458
1459
1460 int griommu_apv_flush(void)
1461 {
1462 struct griommu_priv * priv = griommupriv;
1463
1464 if (priv == NULL){
1465 DBG("GRIOMMU not initialized.\n");
1466 return GRIOMMU_ERR_NOINIT;
1467 }
1468
1469
1470 if (priv->cache_enabled){
1471 griommu_reg_flush_set(FLUSH_F);
1472 DBG("GRIOMMU APV cache flushed.\n");
1473 }
1474
1475 return GRIOMMU_ERR_OK;
1476 }
1477