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
0032
0033
0034
0035
0036
0037 #include <inttypes.h>
0038 #include <stdio.h>
0039 #include <stdlib.h>
0040 #include <string.h>
0041 #include <sys/types.h>
0042 #include <sys/stat.h>
0043
0044 #include <bsp.h>
0045 #include <rtems/bspIo.h>
0046 #include <pci.h>
0047 #include <pci/access.h>
0048
0049 #include <grlib/ambapp.h>
0050
0051 #include <grlib/ambapp.h>
0052 #include <drvmgr/drvmgr.h>
0053 #include <grlib/ambapp_bus.h>
0054 #include <drvmgr/pci_bus.h>
0055 #include <grlib/bspcommon.h>
0056 #include <grlib/genirq.h>
0057
0058 #include <grlib/gr_701.h>
0059
0060 #include <grlib/grlib_impl.h>
0061
0062
0063 #define AHB1_BASE_ADDR 0x80000000
0064 #define AHB1_IOAREA_BASE_ADDR 0x80100000
0065
0066
0067
0068 #ifdef DEBUG
0069 #define DBG(x...) printk(x)
0070 #else
0071 #define DBG(x...)
0072 #endif
0073
0074 int gr701_init1(struct drvmgr_dev *dev);
0075 int gr701_init2(struct drvmgr_dev *dev);
0076 void gr701_interrupt(void *arg);
0077
0078 #define READ_REG(address) (*(volatile unsigned int *)address)
0079
0080
0081 struct amba_bridge_regs {
0082 volatile unsigned int bar0;
0083 volatile unsigned int bar1;
0084 volatile unsigned int bar2;
0085 volatile unsigned int bar3;
0086 volatile unsigned int bar4;
0087
0088 volatile unsigned int unused[4*3-1];
0089
0090 volatile unsigned int ambabars[1];
0091 };
0092
0093
0094 struct pci_bridge_regs {
0095 volatile unsigned int bar0;
0096 volatile unsigned int bar1;
0097 volatile unsigned int bar2;
0098 volatile unsigned int bar3;
0099 volatile unsigned int bar4;
0100
0101 volatile unsigned int ilevel;
0102 volatile unsigned int ipend;
0103 volatile unsigned int iforce;
0104 volatile unsigned int istatus;
0105 volatile unsigned int iclear;
0106 volatile unsigned int imask;
0107 };
0108
0109
0110 struct gr701_priv {
0111
0112 struct drvmgr_dev *dev;
0113 char prefix[16];
0114 SPIN_DECLARE(devlock);
0115
0116 struct pci_bridge_regs *pcib;
0117 struct amba_bridge_regs *ambab;
0118
0119
0120 pci_dev_t pcidev;
0121 struct pci_dev_info *devinfo;
0122
0123
0124 genirq_t genirq;
0125 int interrupt_cnt;
0126
0127
0128 struct drvmgr_map_entry bus_maps_up[2];
0129 struct drvmgr_map_entry bus_maps_down[2];
0130
0131
0132 struct ambapp_bus abus;
0133 struct ambapp_mmap amba_maps[3];
0134 struct ambapp_config config;
0135 };
0136
0137 int ambapp_gr701_int_register(
0138 struct drvmgr_dev *dev,
0139 int irq,
0140 const char *info,
0141 drvmgr_isr handler,
0142 void *arg);
0143 int ambapp_gr701_int_unregister(
0144 struct drvmgr_dev *dev,
0145 int irq,
0146 drvmgr_isr isr,
0147 void *arg);
0148 int ambapp_gr701_int_unmask(
0149 struct drvmgr_dev *dev,
0150 int irq);
0151 int ambapp_gr701_int_mask(
0152 struct drvmgr_dev *dev,
0153 int irq);
0154 int ambapp_gr701_int_clear(
0155 struct drvmgr_dev *dev,
0156 int irq);
0157 int ambapp_gr701_get_params(
0158 struct drvmgr_dev *dev,
0159 struct drvmgr_bus_params *params);
0160
0161 struct ambapp_ops ambapp_gr701_ops = {
0162 .int_register = ambapp_gr701_int_register,
0163 .int_unregister = ambapp_gr701_int_unregister,
0164 .int_unmask = ambapp_gr701_int_unmask,
0165 .int_mask = ambapp_gr701_int_mask,
0166 .int_clear = ambapp_gr701_int_clear,
0167 .get_params = ambapp_gr701_get_params
0168 };
0169
0170 struct drvmgr_drv_ops gr701_ops =
0171 {
0172 .init = {gr701_init1, gr701_init2, NULL, NULL},
0173 .remove = NULL,
0174 .info = NULL
0175 };
0176
0177 struct pci_dev_id_match gr701_ids[] =
0178 {
0179 PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_701),
0180 PCIID_END_TABLE
0181 };
0182
0183 struct pci_drv_info gr701_info =
0184 {
0185 {
0186 DRVMGR_OBJ_DRV,
0187 NULL,
0188 NULL,
0189 DRIVER_PCI_GAISLER_GR701_ID,
0190 "GR-701_DRV",
0191 DRVMGR_BUS_TYPE_PCI,
0192 &gr701_ops,
0193 NULL,
0194 0,
0195 0,
0196 },
0197 &gr701_ids[0]
0198 };
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 struct drvmgr_bus_res *gr701_resources[] __attribute__((weak)) =
0211 {
0212 NULL
0213 };
0214
0215 void gr701_register_drv(void)
0216 {
0217 DBG("Registering GR-701 PCI driver\n");
0218 drvmgr_drv_register(&gr701_info.general);
0219 }
0220
0221 void gr701_interrupt(void *arg)
0222 {
0223 struct gr701_priv *priv = arg;
0224 unsigned int status;
0225 int irq = 0;
0226 SPIN_ISR_IRQFLAGS(irqflags);
0227
0228 SPIN_LOCK(&priv->devlock, irqflags);
0229 while ( (status=priv->pcib->istatus) != 0 ) {
0230 priv->interrupt_cnt++;
0231 irq = status;
0232 genirq_doirq(priv->genirq, irq);
0233
0234 priv->pcib->istatus = 0;
0235 }
0236 SPIN_UNLOCK(&priv->devlock, irqflags);
0237
0238
0239 if ( irq )
0240 drvmgr_interrupt_clear(priv->dev, 0);
0241 }
0242
0243 static int gr701_hw_init(struct gr701_priv *priv)
0244 {
0245 uint32_t com1;
0246 struct pci_bridge_regs *pcib;
0247 struct amba_bridge_regs *ambab;
0248 int mst;
0249 unsigned int pci_freq_hz;
0250 pci_dev_t pcidev = priv->pcidev;
0251 struct pci_dev_info *devinfo = priv->devinfo;
0252
0253
0254 priv->pcib = pcib = (void *)devinfo->resources[0].address;
0255 pcib->bar0 = 0xfc000000;
0256
0257
0258 priv->ambab = ambab = (struct amba_bridge_regs *)(
0259 devinfo->resources[1].address + 0x400);
0260
0261
0262 for (mst=0; mst<16; mst++) {
0263 ambab->ambabars[mst] = 0x40000000;
0264 if (READ_REG(&ambab->ambabars[mst]) != 0x40000000)
0265 break;
0266 }
0267
0268
0269
0270
0271
0272 priv->amba_maps[0].size = 0x04000000;
0273 priv->amba_maps[0].local_adr = devinfo->resources[1].address;
0274 priv->amba_maps[0].remote_adr = 0xfc000000;
0275
0276
0277 priv->amba_maps[1].size=0;
0278 priv->amba_maps[1].local_adr = 0;
0279 priv->amba_maps[1].remote_adr = 0;
0280
0281
0282 priv->bus_maps_down[0].name = "PCI BAR1 -> AMBA";
0283 priv->bus_maps_down[0].size = priv->amba_maps[0].size;
0284 priv->bus_maps_down[0].from_adr = (void *)devinfo->resources[1].address;
0285 priv->bus_maps_down[0].to_adr = (void *)0xfc000000;
0286
0287
0288 priv->bus_maps_up[0].name = "AMBA PCIF Window";
0289 priv->bus_maps_up[0].size = 0x10000000;
0290 priv->bus_maps_up[0].from_adr = (void *)0xe0000000;
0291 priv->bus_maps_up[0].to_adr = (void *)0x40000000;
0292
0293
0294 priv->bus_maps_down[1].size = 0;
0295 priv->bus_maps_up[1].size = 0;
0296
0297
0298 pci_cfg_r32(pcidev, PCIR_COMMAND, &com1);
0299 com1 |= PCIM_CMD_PORTEN | PCIM_CMD_MEMEN;
0300 pci_cfg_w32(pcidev, PCIR_COMMAND, com1);
0301
0302
0303 ambapp_scan(&priv->abus, devinfo->resources[1].address + 0x3f00000,
0304 NULL, &priv->amba_maps[0]);
0305
0306
0307 drvmgr_freq_get(priv->dev, 0, &pci_freq_hz);
0308
0309
0310 ambapp_freq_init(&priv->abus, NULL, pci_freq_hz);
0311
0312
0313 pcib->imask = 0x0000;
0314 pcib->ipend = 0;
0315 pcib->iclear = 0xffff;
0316 pcib->iforce = 0;
0317 pcib->ilevel = 0x0;
0318
0319
0320 return 0;
0321 }
0322
0323 static void gr701_hw_init2(struct gr701_priv *priv)
0324 {
0325
0326 pci_master_enable(priv->pcidev);
0327 }
0328
0329
0330
0331
0332 int gr701_init1(struct drvmgr_dev *dev)
0333 {
0334 struct gr701_priv *priv;
0335 struct pci_dev_info *devinfo;
0336 uint32_t bar0, bar1, bar0_size, bar1_size;
0337 int resources_cnt;
0338 int sc;
0339
0340 priv = grlib_calloc(1, sizeof(*priv));
0341 if ( !priv )
0342 return DRVMGR_NOMEM;
0343
0344 dev->priv = priv;
0345 priv->dev = dev;
0346
0347
0348 resources_cnt = get_resarray_count(gr701_resources);
0349
0350
0351 strcpy(priv->prefix, "/dev/gr701_0");
0352 priv->prefix[11] += dev->minor_drv;
0353 sc = mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO);
0354 _Assert_Unused_variable_equals(sc, 0);
0355 priv->prefix[12] = '/';
0356 priv->prefix[13] = '\0';
0357
0358 priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo;
0359 priv->pcidev = devinfo->pcidev;
0360 bar0 = devinfo->resources[0].address;
0361 bar0_size = devinfo->resources[0].size;
0362 bar1 = devinfo->resources[1].address;
0363 bar1_size = devinfo->resources[1].size;
0364 printk("\n\n--- GR-701[%d] ---\n", dev->minor_drv);
0365 printk(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n",
0366 PCI_DEV_EXPAND(priv->pcidev));
0367 printk(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n\n\n",
0368 devinfo->id.vendor, devinfo->id.device);
0369 printk(" PCI BAR[0]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
0370 bar0, bar0 + bar0_size - 1);
0371 printk(" PCI BAR[1]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
0372 bar1, bar1 + bar1_size - 1);
0373 printk(" IRQ: %d\n\n\n", devinfo->irq);
0374
0375
0376 if ((bar0_size == 0) || (bar1_size == 0))
0377 return DRVMGR_ENORES;
0378
0379
0380
0381
0382
0383 SPIN_INIT(&priv->devlock, priv->prefix);
0384
0385 priv->genirq = genirq_init(16);
0386 if ( priv->genirq == NULL ) {
0387 free(priv);
0388 dev->priv = NULL;
0389 return DRVMGR_FAIL;
0390 }
0391
0392 if ( gr701_hw_init(priv) ) {
0393 genirq_destroy(priv->genirq);
0394 free(priv);
0395 dev->priv = NULL;
0396 printk(" Failed to initialize GR-701 HW\n");
0397 return DRVMGR_FAIL;
0398 }
0399
0400
0401 priv->config.abus = &priv->abus;
0402 priv->config.ops = &ambapp_gr701_ops;
0403 priv->config.maps_up = &priv->bus_maps_up[0];
0404 priv->config.maps_down = &priv->bus_maps_down[0];
0405 if ( priv->dev->minor_drv < resources_cnt ) {
0406 priv->config.resources = gr701_resources[priv->dev->minor_drv];
0407 } else {
0408 priv->config.resources = NULL;
0409 }
0410
0411
0412 return ambapp_bus_register(dev, &priv->config);
0413 }
0414
0415
0416
0417
0418 int gr701_init2(struct drvmgr_dev *dev)
0419 {
0420 struct gr701_priv *priv = dev->priv;
0421
0422
0423 drvmgr_interrupt_clear(dev, 0);
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433 drvmgr_interrupt_register(dev, 0, "gr701", gr701_interrupt, priv);
0434
0435 gr701_hw_init2(priv);
0436
0437 return DRVMGR_OK;
0438 }
0439
0440 int ambapp_gr701_int_register(
0441 struct drvmgr_dev *dev,
0442 int irq,
0443 const char *info,
0444 drvmgr_isr handler,
0445 void *arg)
0446 {
0447 struct gr701_priv *priv = dev->parent->dev->priv;
0448 SPIN_IRQFLAGS(irqflags);
0449 int status;
0450 void *h;
0451
0452 h = genirq_alloc_handler(handler, arg);
0453 if ( h == NULL )
0454 return DRVMGR_FAIL;
0455
0456 SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0457
0458 status = genirq_register(priv->genirq, irq, h);
0459 if ( status == 0 ) {
0460
0461 priv->pcib->iclear = (1<<irq);
0462 } else if ( status == 1 )
0463 status = 0;
0464
0465 if (status != 0) {
0466 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0467 genirq_free_handler(h);
0468 return DRVMGR_FAIL;
0469 }
0470
0471 status = genirq_enable(priv->genirq, irq, handler, arg);
0472 if ( status == 0 ) {
0473
0474 priv->pcib->imask |= (1<<irq);
0475 } else if ( status == 1 )
0476 status = DRVMGR_OK;
0477
0478 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0479
0480 return status;
0481 }
0482
0483 int ambapp_gr701_int_unregister(
0484 struct drvmgr_dev *dev,
0485 int irq,
0486 drvmgr_isr isr,
0487 void *arg)
0488 {
0489 struct gr701_priv *priv = dev->parent->dev->priv;
0490 SPIN_IRQFLAGS(irqflags);
0491 int status;
0492 void *handler;
0493
0494 SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0495
0496 status = genirq_disable(priv->genirq, irq, isr, arg);
0497 if ( status == 0 ) {
0498
0499 priv->pcib->imask &= ~(1<<irq);
0500 }
0501
0502 handler = genirq_unregister(priv->genirq, irq, isr, arg);
0503 if ( handler == NULL )
0504 status = DRVMGR_FAIL;
0505 else
0506 status = DRVMGR_OK;
0507
0508 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0509
0510 if (handler)
0511 genirq_free_handler(handler);
0512
0513 return status;
0514 }
0515
0516 int ambapp_gr701_int_unmask(
0517 struct drvmgr_dev *dev,
0518 int irq)
0519 {
0520 struct gr701_priv *priv = dev->parent->dev->priv;
0521 SPIN_IRQFLAGS(irqflags);
0522
0523 DBG("GR-701 IRQ %d: enable\n", irq);
0524
0525 if ( genirq_check(priv->genirq, irq) )
0526 return DRVMGR_FAIL;
0527
0528 SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0529
0530
0531 priv->pcib->imask |= (1<<irq);
0532
0533 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0534
0535 return DRVMGR_OK;
0536 }
0537
0538 int ambapp_gr701_int_mask(
0539 struct drvmgr_dev *dev,
0540 int irq)
0541 {
0542 struct gr701_priv *priv = dev->parent->dev->priv;
0543 SPIN_IRQFLAGS(irqflags);
0544
0545 DBG("GR-701 IRQ %d: disable\n", irq);
0546
0547 if ( genirq_check(priv->genirq, irq) )
0548 return DRVMGR_FAIL;
0549
0550 SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0551
0552
0553 priv->pcib->imask &= ~(1<<irq);
0554
0555 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0556
0557 return DRVMGR_OK;
0558 }
0559
0560 int ambapp_gr701_int_clear(
0561 struct drvmgr_dev *dev,
0562 int irq)
0563 {
0564 struct gr701_priv *priv = dev->parent->dev->priv;
0565
0566 if ( genirq_check(priv->genirq, irq) )
0567 return DRVMGR_FAIL;
0568
0569 priv->pcib->iclear = (1<<irq);
0570
0571 return DRVMGR_OK;
0572 }
0573
0574 int ambapp_gr701_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
0575 {
0576 struct gr701_priv *priv = dev->parent->dev->priv;
0577
0578
0579 params->dev_prefix = &priv->prefix[5];
0580
0581 return 0;
0582 }
0583
0584 void gr701_print_dev(struct drvmgr_dev *dev, int options)
0585 {
0586 struct gr701_priv *priv = dev->priv;
0587 struct pci_dev_info *devinfo = priv->devinfo;
0588 unsigned int freq_hz;
0589 uint32_t bar0, bar1, bar0_size, bar1_size;
0590
0591
0592 printf("--- GR-701 [bus 0x%x, dev 0x%x, fun 0x%x] ---\n",
0593 PCI_DEV_EXPAND(priv->pcidev));
0594 bar0 = devinfo->resources[0].address;
0595 bar0_size = devinfo->resources[0].size;
0596 bar1 = devinfo->resources[1].address;
0597 bar1_size = devinfo->resources[1].size;
0598
0599 printf(" PCI BAR[0]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
0600 bar0, bar0 + bar0_size - 1);
0601 printf(" PCI BAR[1]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
0602 bar1, bar1 + bar1_size - 1);
0603 printf(" IRQ: %d\n", devinfo->irq);
0604
0605
0606 drvmgr_freq_get(dev, 0, &freq_hz);
0607
0608 printf(" FREQ: %u Hz\n", freq_hz);
0609 printf(" IMASK: 0x%08x\n", priv->pcib->imask);
0610 printf(" IPEND: 0x%08x\n", priv->pcib->ipend);
0611
0612
0613 if ( options & GR701_OPTIONS_AMBA ) {
0614 ambapp_print(&priv->abus, 10);
0615 }
0616
0617 #if 0
0618
0619 if ( options & GR701_OPTIONS_IRQ ) {
0620 int i;
0621 for(i=0; i<16; i++) {
0622 printf(" IRQ[%02d]: 0x%x, arg: 0x%x\n",
0623 i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg);
0624 }
0625 }
0626 #endif
0627 }
0628
0629 void gr701_print(int options)
0630 {
0631 struct pci_drv_info *drv = &gr701_info;
0632 struct drvmgr_dev *dev;
0633
0634 dev = drv->general.dev;
0635 while(dev) {
0636 gr701_print_dev(dev, options);
0637 dev = dev->next_in_drv;
0638 }
0639 }