Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:06

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  GR-RASTA-ADCDAC PCI Target driver.
0004  * 
0005  *  COPYRIGHT (c) 2008.
0006  *  Cobham Gaisler AB.
0007  *
0008  *  Configures the GR-RASTA-ADCDAC interface PCI board.
0009  *  This driver provides a AMBA PnP bus by using the general part
0010  *  of the AMBA PnP bus driver (ambapp_bus.c).
0011  *
0012  *  Driver resources for the AMBA PnP bus provided can be set using
0013  *  gr_rasta_adcdac_set_resources().
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
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 
0048 #include <grlib/ambapp.h>
0049 #include <grlib/grlib.h>
0050 #include <drvmgr/drvmgr.h>
0051 #include <grlib/ambapp_bus.h>
0052 #include <drvmgr/pci_bus.h>
0053 #include <grlib/bspcommon.h>
0054 #include <grlib/genirq.h>
0055 
0056 #include <grlib/gr_rasta_adcdac.h>
0057 
0058 #include <grlib/grlib_impl.h>
0059 
0060 /*#define DEBUG 1*/
0061 
0062 #ifdef DEBUG
0063 #define DBG(x...) printk(x)
0064 #else
0065 #define DBG(x...) 
0066 #endif
0067 
0068 /* Determines which PCI address the AHB masters will access, it should be
0069  * set so that the masters can access the CPU RAM. Default is base of CPU RAM,
0070  * CPU RAM is mapped 1:1 to PCI space.
0071  */
0072 extern unsigned int _RAM_START;
0073 #define AHBMST2PCIADR (((unsigned int)&_RAM_START) & 0xf0000000)
0074 
0075 /* PCI ID */
0076 #define PCIID_VENDOR_GAISLER        0x1AC8
0077 #define PCIID_DEVICE_GR_RASTA_ADCDAC    0x0014
0078 
0079 int gr_rasta_adcdac_init1(struct drvmgr_dev *dev);
0080 int gr_rasta_adcdac_init2(struct drvmgr_dev *dev);
0081 void gr_rasta_adcdac_isr (void *arg);
0082 
0083 struct grpci_regs {
0084     volatile unsigned int cfg_stat;
0085     volatile unsigned int bar0;
0086     volatile unsigned int page0;
0087     volatile unsigned int bar1;
0088     volatile unsigned int page1;
0089     volatile unsigned int iomap;
0090     volatile unsigned int stat_cmd;
0091 };
0092 
0093 struct gr_rasta_adcdac_ver {
0094     const unsigned int  amba_freq_hz;   /* The frequency */
0095     const unsigned int  amba_ioarea;    /* The address where the PnP IOAREA starts at */
0096 };
0097 
0098 /* Private data structure for driver */
0099 struct gr_rasta_adcdac_priv {
0100     /* Driver management */
0101     struct drvmgr_dev       *dev;
0102     char                prefix[20];
0103     SPIN_DECLARE(devlock);
0104 
0105     /* PCI */
0106     pci_dev_t           pcidev;
0107     struct pci_dev_info     *devinfo;
0108     uint32_t            ahbmst2pci_map;
0109 
0110     /* IRQ */
0111     genirq_t            genirq;
0112 
0113     /* GR-RASTA-ADCDAC */
0114     struct gr_rasta_adcdac_ver  *version;
0115     struct irqmp_regs       *irq;
0116     struct grpci_regs       *grpci;
0117     struct drvmgr_map_entry     bus_maps_down[3];
0118     struct drvmgr_map_entry     bus_maps_up[2];
0119 
0120     /* AMBA Plug&Play information on GR-RASTA-ADCDAC */
0121     struct ambapp_bus       abus;
0122     struct ambapp_mmap      amba_maps[4];
0123         struct ambapp_config        config;
0124 };
0125 
0126 struct gr_rasta_adcdac_ver gr_rasta_adcdac_ver0 = {
0127     .amba_freq_hz       = 50000000,
0128     .amba_ioarea        = 0x80100000,
0129 };
0130 
0131 int ambapp_rasta_adcdac_int_register(
0132     struct drvmgr_dev *dev,
0133     int irq,
0134     const char *info,
0135     drvmgr_isr handler,
0136     void *arg);
0137 int ambapp_rasta_adcdac_int_unregister(
0138     struct drvmgr_dev *dev,
0139     int irq,
0140     drvmgr_isr isr,
0141     void *arg);
0142 int ambapp_rasta_adcdac_int_unmask(
0143     struct drvmgr_dev *dev,
0144     int irq);
0145 int ambapp_rasta_adcdac_int_mask(
0146     struct drvmgr_dev *dev,
0147     int irq);
0148 int ambapp_rasta_adcdac_int_clear(
0149     struct drvmgr_dev *dev,
0150     int irq);
0151 int ambapp_rasta_adcdac_get_params(
0152     struct drvmgr_dev *dev,
0153     struct drvmgr_bus_params *params);
0154 
0155 struct ambapp_ops ambapp_rasta_adcdac_ops = {
0156     .int_register = ambapp_rasta_adcdac_int_register,
0157     .int_unregister = ambapp_rasta_adcdac_int_unregister,
0158     .int_unmask = ambapp_rasta_adcdac_int_unmask,
0159     .int_mask = ambapp_rasta_adcdac_int_mask,
0160     .int_clear = ambapp_rasta_adcdac_int_clear,
0161     .get_params = ambapp_rasta_adcdac_get_params
0162 };
0163 
0164 struct drvmgr_drv_ops gr_rasta_adcdac_ops = 
0165 {   .init = {gr_rasta_adcdac_init1, gr_rasta_adcdac_init2, NULL, NULL},
0166     .remove = NULL,
0167     .info = NULL
0168 };
0169 
0170 struct pci_dev_id_match gr_rasta_adcdac_ids[] = 
0171 {
0172     PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_ADCDAC),
0173     PCIID_END_TABLE /* Mark end of table */
0174 };
0175 
0176 struct pci_drv_info gr_rasta_adcdac_info =
0177 {
0178     {
0179         DRVMGR_OBJ_DRV,         /* Driver */
0180         NULL,               /* Next driver */
0181         NULL,               /* Device list */
0182         DRIVER_PCI_GAISLER_RASTAADCDAC_ID,/* Driver ID */
0183         "GR-RASTA-ADCDAC_DRV",      /* Driver Name */
0184         DRVMGR_BUS_TYPE_PCI,        /* Bus Type */
0185         &gr_rasta_adcdac_ops,
0186         NULL,               /* Funcs */
0187         0,              /* No devices yet */
0188         0,
0189     },
0190     &gr_rasta_adcdac_ids[0]
0191 };
0192 
0193 /* Driver resources configuration for the AMBA bus on the GR-RASTA-ADCDAC board.
0194  * It is declared weak so that the user may override it from the project file,
0195  * if the default settings are not enough.
0196  *
0197  * The configuration consists of an array of configuration pointers, each
0198  * pointer determine the configuration of one GR-RASTA-ADCDAC board. Pointer
0199  * zero is for board0, pointer 1 for board1 and so on.
0200  *
0201  * The array must end with a NULL pointer.
0202  */
0203 struct drvmgr_bus_res *gr_rasta_adcdac_resources[] __attribute__((weak)) =
0204 {
0205     NULL
0206 };
0207 
0208 void gr_rasta_adcdac_register_drv(void)
0209 {
0210     DBG("Registering GR-RASTA-ADCDAC PCI driver\n");
0211     drvmgr_drv_register(&gr_rasta_adcdac_info.general);
0212 }
0213 
0214 void gr_rasta_adcdac_isr (void *arg)
0215 {
0216     struct gr_rasta_adcdac_priv *priv = arg;
0217     unsigned int status, tmp;
0218     int irq;
0219     SPIN_ISR_IRQFLAGS(irqflags);
0220 
0221     tmp = status = priv->irq->ipend;
0222 
0223     /* DBG("GR-RASTA-ADCDAC: IRQ 0x%x\n",status); */
0224 
0225     SPIN_LOCK(&priv->devlock, irqflags);
0226     for(irq=0; irq<16; irq++) {
0227         if ( status & (1<<irq) ) {
0228             genirq_doirq(priv->genirq, irq);
0229             priv->irq->iclear = (1<<irq);
0230             status &= ~(1<<irq);
0231             if ( status == 0 )
0232                 break;
0233         }
0234     }
0235     SPIN_UNLOCK(&priv->devlock, irqflags);
0236 
0237     /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */
0238     if ( tmp )
0239         drvmgr_interrupt_clear(priv->dev, 0);
0240 
0241     DBG("RASTA-ADCDAC-IRQ: 0x%x\n", tmp);
0242 }
0243 
0244 static int gr_rasta_adcdac_hw_init1(struct gr_rasta_adcdac_priv *priv)
0245 {
0246     uint32_t data;
0247     unsigned int *page0 = NULL;
0248     struct ambapp_dev *tmp;
0249     struct ambapp_ahb_info *ahb;
0250     struct pci_dev_info *devinfo = priv->devinfo;
0251     uint32_t bar0, bar0_size;
0252 
0253     /* Select version of GR-RASTA-ADCDAC board */
0254     switch (devinfo->rev) {
0255         case 0:
0256             priv->version = &gr_rasta_adcdac_ver0;
0257             break;
0258         default:
0259             return -2;
0260     }
0261 
0262     bar0 = devinfo->resources[0].address;
0263     bar0_size = devinfo->resources[0].size;
0264     page0 = (unsigned int *)(bar0 + bar0_size/2); 
0265 
0266     /* Point PAGE0 to start of Plug and Play information */
0267     *page0 = priv->version->amba_ioarea & 0xf0000000;
0268 
0269     /* set parity error response */
0270     pci_cfg_r32(priv->pcidev, PCIR_COMMAND, &data);
0271     pci_cfg_w32(priv->pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN));
0272 
0273     /* Setup cache line size. Default cache line size will result in
0274      * poor performance (256 word fetches), 0xff will set it according
0275      * to the max size of the PCI FIFO.
0276      */
0277     pci_cfg_w8(priv->pcidev, PCIR_CACHELNSZ, 0xff);
0278 
0279     /* Scan AMBA Plug&Play */
0280 
0281     /* AMBA MAP bar0 (in CPU) ==> 0x80000000(remote amba address) */
0282     priv->amba_maps[0].size = bar0_size/2;
0283     priv->amba_maps[0].local_adr = bar0;
0284     priv->amba_maps[0].remote_adr = 0x80000000;
0285 
0286     /* AMBA MAP bar1 (in CPU) ==> 0x40000000(remote amba address) */
0287     priv->amba_maps[1].size = devinfo->resources[1].size;
0288     priv->amba_maps[1].local_adr = devinfo->resources[1].address;
0289     priv->amba_maps[1].remote_adr = 0x40000000;
0290 
0291     /* Addresses not matching with map be untouched */
0292     priv->amba_maps[2].size = 0xfffffff0;
0293     priv->amba_maps[2].local_adr = 0;
0294     priv->amba_maps[2].remote_adr = 0;
0295 
0296     /* Mark end of table */
0297     priv->amba_maps[3].size=0;
0298     priv->amba_maps[3].local_adr = 0;
0299     priv->amba_maps[3].remote_adr = 0;
0300 
0301     /* Start AMBA PnP scan at first AHB bus */
0302     /*ambapp_scan(priv->bar0 + (priv->version->amba_ioarea & ~0xf0000000),
0303         NULL, &priv->amba_maps[0], NULL, &priv->abus.root, NULL);*/
0304     ambapp_scan(&priv->abus,
0305         bar0 + (priv->version->amba_ioarea & ~0xf0000000),
0306         NULL, &priv->amba_maps[0]);
0307 
0308     /* Initialize Frequency of AMBA bus */
0309     ambapp_freq_init(&priv->abus, NULL, priv->version->amba_freq_hz);
0310 
0311     /* Point PAGE0 to start of APB area */
0312     *page0 = 0x80000000;    
0313 
0314     /* Find GRPCI controller */
0315     tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
0316                     (OPTIONS_ALL|OPTIONS_APB_SLVS),
0317                     VENDOR_GAISLER, GAISLER_PCIFBRG,
0318                     ambapp_find_by_idx, NULL);
0319     if ( !tmp ) {
0320         return -3;
0321     }
0322     priv->grpci = (struct grpci_regs *)((struct ambapp_apb_info *)tmp->devinfo)->start;
0323 
0324     /* Set GRPCI mmap so that AMBA masters can access CPU-RAM over
0325      * the PCI window.
0326      */
0327     priv->grpci->cfg_stat = (priv->grpci->cfg_stat & 0x0fffffff) |
0328                 (priv->ahbmst2pci_map & 0xf0000000);
0329     priv->grpci->page1 = 0x40000000;
0330 
0331     /* Find IRQ controller */
0332     tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
0333                     (OPTIONS_ALL|OPTIONS_APB_SLVS),
0334                     VENDOR_GAISLER, GAISLER_IRQMP,
0335                     ambapp_find_by_idx, NULL);
0336     if ( !tmp ) {
0337         return -4;
0338     }
0339     priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start;
0340     /* Set up GR-RASTA-ADCDAC irq controller */
0341     priv->irq->iclear = 0xffff;
0342     priv->irq->ilevel = 0;
0343     priv->irq->mask[0] = 0;
0344 
0345     /* DOWN streams translation table */
0346     priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA";
0347     priv->bus_maps_down[0].size = priv->amba_maps[0].size;
0348     priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr;
0349     priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr;
0350 
0351     priv->bus_maps_down[1].name = "PCI BAR1 -> AMBA";
0352     priv->bus_maps_down[1].size = priv->amba_maps[1].size;
0353     priv->bus_maps_down[1].from_adr = (void *)priv->amba_maps[1].local_adr;
0354     priv->bus_maps_down[1].to_adr = (void *)priv->amba_maps[1].remote_adr;
0355 
0356     /* Mark end of translation table */
0357     priv->bus_maps_down[2].size = 0;
0358 
0359     /* Find GRPCI controller AHB Slave interface */
0360     tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
0361                     (OPTIONS_ALL|OPTIONS_AHB_SLVS),
0362                     VENDOR_GAISLER, GAISLER_PCIFBRG,
0363                     ambapp_find_by_idx, NULL);
0364     if ( !tmp ) {
0365         return -5;
0366     }
0367     ahb = (struct ambapp_ahb_info *)tmp->devinfo;
0368 
0369     /* UP streams translation table */
0370     priv->bus_maps_up[0].name = "AMBA GRPCI Window";
0371     priv->bus_maps_up[0].size = ahb->mask[0]; /* AMBA->PCI Window on GR-RASTA-ADCDAC board */
0372     priv->bus_maps_up[0].from_adr = (void *)ahb->start[0];
0373     priv->bus_maps_up[0].to_adr = (void *)
0374                     (priv->ahbmst2pci_map & 0xf0000000);
0375 
0376     /* Mark end of translation table */
0377     priv->bus_maps_up[1].size = 0;
0378 
0379     /* Successfully registered the RASTA board */
0380     return 0;
0381 }
0382 
0383 static int gr_rasta_adcdac_hw_init2(struct gr_rasta_adcdac_priv *priv)
0384 {
0385     /* Enable DMA by enabling PCI target as master */
0386     pci_master_enable(priv->pcidev);
0387 
0388     return DRVMGR_OK;
0389 }
0390 
0391 /* Called when a PCI target is found with the PCI device and vendor ID 
0392  * given in gr_rasta_adcdac_ids[].
0393  */
0394 int gr_rasta_adcdac_init1(struct drvmgr_dev *dev)
0395 {
0396     struct gr_rasta_adcdac_priv *priv;
0397     struct pci_dev_info *devinfo;
0398     int status;
0399     uint32_t bar0, bar1, bar0_size, bar1_size;
0400     union drvmgr_key_value *value;
0401     int resources_cnt;
0402     int sc;
0403 
0404     priv = grlib_calloc(1, sizeof(*priv));
0405     if ( !priv )
0406         return DRVMGR_NOMEM;
0407 
0408     dev->priv = priv;
0409     priv->dev = dev;
0410 
0411     /* Determine number of configurations */
0412     resources_cnt = get_resarray_count(gr_rasta_adcdac_resources);
0413 
0414     /* Generate Device prefix */
0415 
0416     strcpy(priv->prefix, "/dev/rastaadcdac0");
0417     priv->prefix[16] += dev->minor_drv;
0418     sc = mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO);
0419     _Assert_Unused_variable_equals(sc, 0);
0420     priv->prefix[17] = '/';
0421     priv->prefix[18] = '\0';
0422 
0423     priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo;
0424     priv->pcidev = devinfo->pcidev;
0425     bar0 = devinfo->resources[0].address;
0426     bar0_size = devinfo->resources[0].size;
0427     bar1 = devinfo->resources[1].address;
0428     bar1_size = devinfo->resources[1].size;
0429     printk("\n\n--- GR-RASTA-ADCDAC[%d] ---\n", dev->minor_drv);
0430     printk(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n",
0431         PCI_DEV_EXPAND(priv->pcidev));
0432     printk(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n",
0433         devinfo->id.vendor, devinfo->id.device);
0434     printk(" PCI BAR[0]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
0435         bar0, bar0 + bar0_size - 1);
0436     printk(" PCI BAR[1]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
0437         bar1, bar1 + bar1_size - 1);
0438     printk(" IRQ: %d\n\n\n", devinfo->irq);
0439 
0440     /* all neccessary space assigned to GR-RASTA-ADCDAC target? */
0441     if ((bar0_size == 0) || (bar1_size == 0))
0442         return DRVMGR_ENORES;
0443 
0444     /* Initialize spin-lock for this PCI perihperal device. This is to
0445      * protect the Interrupt Controller Registers. The genirq layer is
0446          * protecting its own internals and ISR dispatching.
0447          */
0448     SPIN_INIT(&priv->devlock, priv->prefix);
0449 
0450     /* Let user override which PCI address the AHB masters of the
0451      * RASTA-ADCDAC board access when doing DMA to CPU RAM. The AHB masters
0452      * access the PCI Window of the AMBA bus, the MSB 4-bits of that address
0453      * is translated according this config option before the address
0454      * goes out on the PCI bus.
0455      * Only the 4 MSB bits have an effect;
0456      */
0457     value = drvmgr_dev_key_get(priv->dev, "ahbmst2pci", DRVMGR_KT_INT);
0458     if (value)
0459         priv->ahbmst2pci_map = value->i;
0460     else
0461         priv->ahbmst2pci_map = AHBMST2PCIADR; /* default */
0462 
0463     priv->genirq = genirq_init(16);
0464     if ( priv->genirq == NULL ) {
0465         free(priv);
0466         dev->priv = NULL;
0467         return DRVMGR_FAIL;
0468     }
0469 
0470     if ( (status = gr_rasta_adcdac_hw_init1(priv)) != 0 ) {
0471         genirq_destroy(priv->genirq);
0472         free(priv);
0473         dev->priv = NULL;
0474         printk(" Failed to initialize GR-RASTA-ADCDAC HW: %d\n", status);
0475         return DRVMGR_FAIL;
0476     }
0477 
0478     /* Init amba bus */
0479     priv->config.abus = &priv->abus;
0480     priv->config.ops = &ambapp_rasta_adcdac_ops;
0481     priv->config.maps_up = &priv->bus_maps_up[0];
0482     priv->config.maps_down = &priv->bus_maps_down[0];
0483     if ( priv->dev->minor_drv < resources_cnt ) {
0484         priv->config.resources = gr_rasta_adcdac_resources[priv->dev->minor_drv];
0485     } else {
0486         priv->config.resources = NULL;
0487     }
0488 
0489     /* Create and register AMBA PnP bus. */
0490     return ambapp_bus_register(dev, &priv->config);
0491 }
0492 
0493 int gr_rasta_adcdac_init2(struct drvmgr_dev *dev)
0494 {
0495     struct gr_rasta_adcdac_priv *priv = dev->priv;
0496 
0497     /* Clear any old interrupt requests */
0498     drvmgr_interrupt_clear(dev, 0);
0499 
0500     /* Enable System IRQ so that GR-RASTA-ADCDAC PCI target interrupt 
0501      * goes through.
0502      *
0503      * It is important to enable it in stage init2. If interrupts were
0504      * enabled in init1 this might hang the system when more than one 
0505      * PCI board is connected, this is because PCI interrupts might 
0506      * be shared and PCI board 2 have not initialized and might
0507      * therefore drive interrupt already when entering init1().
0508      */
0509     drvmgr_interrupt_register(
0510         dev,
0511         0,
0512         "gr_rasta_adcdac",
0513         gr_rasta_adcdac_isr, 
0514         (void *)priv);
0515 
0516     return gr_rasta_adcdac_hw_init2(priv);
0517 }
0518 
0519 int ambapp_rasta_adcdac_int_register(
0520     struct drvmgr_dev *dev,
0521     int irq,
0522     const char *info,
0523     drvmgr_isr handler,
0524     void *arg)
0525 {
0526     struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
0527     SPIN_IRQFLAGS(irqflags);
0528     int status;
0529     void *h;
0530 
0531     h = genirq_alloc_handler(handler, arg);
0532     if ( h == NULL )
0533         return DRVMGR_FAIL;
0534 
0535     SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0536 
0537     status = genirq_register(priv->genirq, irq, h);
0538     if ( status == 0 ) {
0539         /* Clear IRQ for first registered handler */
0540         priv->irq->iclear = (1<<irq);
0541     } else if ( status == 1 )
0542         status = 0;
0543 
0544     if (status != 0) {
0545         SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0546         genirq_free_handler(h);
0547         return DRVMGR_FAIL;
0548     }
0549 
0550     status = genirq_enable(priv->genirq, irq, handler, arg);
0551     if ( status == 0 ) {
0552         /* Enable IRQ for first enabled handler only */
0553         priv->irq->mask[0] |= (1<<irq); /* unmask interrupt source */
0554     } else if ( status == 1 )
0555         status = 0;
0556 
0557     SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0558 
0559     return status;
0560 }
0561 
0562 int ambapp_rasta_adcdac_int_unregister(
0563     struct drvmgr_dev *dev,
0564     int irq,
0565     drvmgr_isr isr,
0566     void *arg)
0567 {
0568     struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
0569     SPIN_IRQFLAGS(irqflags);
0570     int status;
0571     void *handler;
0572 
0573     SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0574 
0575     status = genirq_disable(priv->genirq, irq, isr, arg);
0576     if ( status == 0 ) {
0577         /* Disable IRQ only when no enabled handler exists */
0578         priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
0579     }
0580 
0581     handler = genirq_unregister(priv->genirq, irq, isr, arg);
0582     if ( handler == NULL )
0583         status = DRVMGR_FAIL;
0584     else
0585         status = DRVMGR_OK;
0586 
0587     SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0588 
0589     if (handler)
0590         genirq_free_handler(handler);
0591 
0592     return status;
0593 }
0594 
0595 int ambapp_rasta_adcdac_int_unmask(
0596     struct drvmgr_dev *dev,
0597     int irq)
0598 {
0599     struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
0600     SPIN_IRQFLAGS(irqflags);
0601 
0602     DBG("RASTA-ADCDAC IRQ %d: unmask\n", irq);
0603 
0604     if ( genirq_check(priv->genirq, irq) )
0605         return DRVMGR_EINVAL;
0606 
0607     SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0608 
0609     /* Enable IRQ for first enabled handler only */
0610     priv->irq->mask[0] |= (1<<irq); /* unmask interrupt source */
0611 
0612     SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0613 
0614     return DRVMGR_OK;
0615 }
0616 
0617 int ambapp_rasta_adcdac_int_mask(
0618     struct drvmgr_dev *dev,
0619     int irq)
0620 {
0621     struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
0622     SPIN_IRQFLAGS(irqflags);
0623 
0624     DBG("RASTA-ADCDAC IRQ %d: mask\n", irq);
0625 
0626     if ( genirq_check(priv->genirq, irq) )
0627         return DRVMGR_EINVAL;
0628 
0629     SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0630 
0631     /* Disable/mask IRQ */
0632     priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
0633 
0634     SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0635 
0636     return DRVMGR_OK;
0637 }
0638 
0639 int ambapp_rasta_adcdac_int_clear(
0640     struct drvmgr_dev *dev,
0641     int irq)
0642 {
0643     struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
0644 
0645     if ( genirq_check(priv->genirq, irq) )
0646         return DRVMGR_FAIL;
0647 
0648     priv->irq->iclear = (1<<irq);
0649 
0650     return DRVMGR_OK;
0651 }
0652 
0653 int ambapp_rasta_adcdac_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
0654 {
0655     struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
0656 
0657     /* Device name prefix pointer, skip /dev */
0658     params->dev_prefix = &priv->prefix[5];
0659 
0660     return 0;
0661 }
0662 
0663 void gr_rasta_adcdac_print_dev(struct drvmgr_dev *dev, int options)
0664 {
0665     struct gr_rasta_adcdac_priv *priv = dev->priv;
0666     struct pci_dev_info *devinfo = priv->devinfo;
0667     uint32_t bar0, bar1, bar0_size, bar1_size;
0668 
0669     /* Print */
0670     printf("--- GR-RASTA-ADCDAC [bus 0x%x, dev 0x%x, fun 0x%x] ---\n",
0671         PCI_DEV_EXPAND(priv->pcidev));
0672 
0673     bar0 = devinfo->resources[0].address;
0674     bar0_size = devinfo->resources[0].size;
0675     bar1 = devinfo->resources[1].address;
0676     bar1_size = devinfo->resources[1].size;
0677 
0678     printf(" PCI BAR[0]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
0679         bar0, bar0 + bar0_size - 1);
0680     printf(" PCI BAR[1]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
0681         bar1, bar1 + bar1_size - 1);
0682     printf(" IRQ REGS:        0x%" PRIxPTR "\n", (uintptr_t)priv->irq);
0683     printf(" IRQ:             %d\n", devinfo->irq);
0684     printf(" PCI REVISION:    %d\n", devinfo->rev);
0685     printf(" FREQ:            %d Hz\n", priv->version->amba_freq_hz);
0686     printf(" IMASK:           0x%08x\n", priv->irq->mask[0]);
0687     printf(" IPEND:           0x%08x\n", priv->irq->ipend);
0688 
0689     /* Print amba config */
0690     if ( options & RASTA_ADCDAC_OPTIONS_AMBA ) {
0691         ambapp_print(&priv->abus, 10);
0692     }
0693 #if 0
0694     /* Print IRQ handlers and their arguments */
0695     if ( options & RASTA_ADCDAC_OPTIONS_IRQ ) {
0696         int i;
0697         for(i=0; i<16; i++) {
0698             printf(" IRQ[%02d]:         0x%x, arg: 0x%x\n", 
0699                 i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg);
0700         }
0701     }
0702 #endif
0703 }
0704 
0705 void gr_rasta_adcdac_print(int options)
0706 {
0707     struct pci_drv_info *drv = &gr_rasta_adcdac_info;
0708     struct drvmgr_dev *dev;
0709 
0710     dev = drv->general.dev;
0711     while(dev) {
0712         gr_rasta_adcdac_print_dev(dev, options);
0713         dev = dev->next_in_drv;
0714     }
0715 }