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