Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  General part of a AMBA Plug & Play bus driver.
0004  *
0005  *  COPYRIGHT (c) 2008.
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  *  This is the general part of the different AMBA Plug & Play
0030  *  drivers. The drivers are wrappers around this driver, making
0031  *  the code size smaller for systems with multiple AMBA Plug & 
0032  *  Play buses.
0033  *
0034  *  The BSP define APBUART_INFO_AVAIL in order to add the info routine
0035  *  used for debugging.
0036  */
0037 
0038 #include <stdio.h>
0039 #include <stdlib.h>
0040 #include <string.h>
0041 
0042 #include <drvmgr/drvmgr.h>
0043 #include <grlib/ambapp_bus.h>
0044 
0045 #include <bsp.h>
0046 #include <grlib/ambapp.h>
0047 #include <rtems/bspIo.h>
0048 
0049 /*#define DEBUG 1*/
0050 #define DBG(args...)
0051 /*#define DBG(args...) printk(args)*/
0052 
0053 struct grlib_gptimer_regs {
0054     volatile unsigned int scaler_value;   /* common timer registers */
0055     volatile unsigned int scaler_reload;
0056     volatile unsigned int status;
0057     volatile unsigned int notused;
0058 };
0059 
0060 /* AMBA IMPLEMENTATION */
0061 
0062 static int ambapp_bus_init1(struct drvmgr_bus *bus);
0063 static int ambapp_bus_remove(struct drvmgr_bus *bus);
0064 static int ambapp_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev);
0065 static int ambapp_int_register(
0066     struct drvmgr_dev *dev,
0067     int index,
0068     const char *info,
0069     drvmgr_isr isr,
0070     void *arg);
0071 static int ambapp_int_unregister(
0072     struct drvmgr_dev *dev,
0073     int index,
0074     drvmgr_isr isr,
0075     void *arg);
0076 static int ambapp_int_clear(struct drvmgr_dev *dev, int index);
0077 static int ambapp_int_mask(struct drvmgr_dev *dev, int index);
0078 static int ambapp_int_unmask(struct drvmgr_dev *dev, int index);
0079 static int ambapp_get_params(
0080     struct drvmgr_dev *dev,
0081     struct drvmgr_bus_params *params);
0082 static int ambapp_bus_freq_get(
0083     struct drvmgr_dev *dev,
0084     int options,
0085     unsigned int *freq_hz);
0086 #ifdef AMBAPPBUS_INFO_AVAIL
0087 static void ambapp_dev_info(
0088     struct drvmgr_dev *,
0089     void (*print)(void *p, char *str),
0090     void *p);
0091 #endif
0092 
0093 #ifdef RTEMS_SMP
0094 static int ambapp_int_set_affinity(
0095     struct drvmgr_dev *dev,
0096     int index,
0097     const Processor_mask *cpus);
0098 #endif
0099 
0100 static struct drvmgr_bus_ops ambapp_bus_ops =
0101 {
0102     .init       = 
0103     {
0104         /* init1 */ ambapp_bus_init1,
0105         /* init2 */ NULL,
0106         /* init3 */ NULL,
0107         /* init4 */ NULL
0108     },
0109     .remove     = ambapp_bus_remove,
0110     .unite      = ambapp_unite,
0111     .int_register   = ambapp_int_register,
0112     .int_unregister = ambapp_int_unregister,
0113     .int_clear  = ambapp_int_clear,
0114     .int_mask   = ambapp_int_mask,
0115 #ifdef RTEMS_SMP
0116     .int_set_affinity = ambapp_int_set_affinity,
0117 #endif
0118     .int_unmask = ambapp_int_unmask,
0119     .get_params = ambapp_get_params,
0120     .get_freq   = ambapp_bus_freq_get,
0121 #ifdef AMBAPPBUS_INFO_AVAIL
0122     .get_info_dev   = ambapp_dev_info,
0123 #endif
0124 };
0125 
0126 struct ambapp_priv {
0127     struct ambapp_config        *config;
0128 };
0129 
0130 static int ambapp_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev)
0131 {
0132     struct amba_drv_info *adrv;
0133     struct amba_dev_id *id;
0134     struct amba_dev_info *amba;
0135 
0136     if ( !drv || !dev || !dev->parent )
0137         return 0;
0138 
0139     if ( ! (((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP)) ||
0140            ((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP)) ||
0141            ((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST)))
0142        ) {
0143         return 0;
0144     }
0145 
0146     amba = (struct amba_dev_info *)dev->businfo;
0147     if ( !amba )
0148         return 0;
0149 
0150     adrv = (struct amba_drv_info *)drv;
0151     id = adrv->ids;
0152     if ( !id )
0153         return 0;
0154     while( id->vendor != 0 ) {
0155         if ( (id->vendor == amba->id.vendor) &&
0156               (id->device == amba->id.device) ) {
0157             /* Unite device and driver */
0158             DBG("DRV 0x%x and DEV 0x%x united\n", (unsigned int)drv, (unsigned int)dev);
0159             return 1;
0160         }
0161         id++;
0162     }
0163 
0164     return 0;
0165 }
0166 
0167 static int ambapp_int_get(struct drvmgr_dev *dev, int index)
0168 {
0169     int irq;
0170 
0171     /* Relative (positive) or absolute (negative) IRQ number */
0172     if ( index >= 0 ) {
0173         /* IRQ Index relative to Cores base IRQ */
0174 
0175         /* Get Base IRQ */
0176         irq = ((struct amba_dev_info *)dev->businfo)->info.irq;
0177         if ( irq < 0 )
0178             return -1;
0179         irq += index;
0180     } else {
0181         /* Absolute IRQ number */
0182         irq = -index;
0183     }
0184     return irq;
0185 }
0186 
0187 static int ambapp_int_register(
0188     struct drvmgr_dev *dev,
0189     int index,
0190     const char *info,
0191     drvmgr_isr isr,
0192     void *arg)
0193 {
0194     struct ambapp_priv *priv;
0195     int irq;
0196 
0197     priv = dev->parent->priv;
0198 
0199     /* Get IRQ number from index and device information */
0200     irq = ambapp_int_get(dev, index);
0201     if ( irq < 0 ) 
0202         return DRVMGR_EINVAL;
0203 
0204     DBG("Register interrupt on 0x%x for dev 0x%x (IRQ: %d)\n",
0205         (unsigned int)dev->parent->dev, (unsigned int)dev, irq);
0206 
0207     if ( priv->config->ops->int_register ) {
0208         /* Let device override driver default */
0209         return priv->config->ops->int_register(dev, irq, info, isr, arg);
0210     } else {
0211         return DRVMGR_ENOSYS;
0212     }
0213 }
0214 
0215 static int ambapp_int_unregister(
0216     struct drvmgr_dev *dev,
0217     int index,
0218     drvmgr_isr isr,
0219     void *arg)
0220 {
0221     struct ambapp_priv *priv;
0222     int irq;
0223 
0224     priv = dev->parent->priv;
0225 
0226     /* Get IRQ number from index and device information */
0227     irq = ambapp_int_get(dev, index);
0228     if ( irq < 0 ) 
0229         return DRVMGR_EINVAL;
0230 
0231     DBG("Unregister interrupt on 0x%x for dev 0x%x (IRQ: %d)\n",
0232         (unsigned int)dev->parent->dev, (unsigned int)dev, irq);
0233 
0234     if ( priv->config->ops->int_unregister ) {
0235         /* Let device override driver default */
0236         return priv->config->ops->int_unregister(dev, irq, isr, arg);
0237     } else {
0238         return DRVMGR_ENOSYS;
0239     }
0240 }
0241 
0242 static int ambapp_int_clear(
0243     struct drvmgr_dev *dev,
0244     int index)
0245 {
0246     struct ambapp_priv *priv;
0247     int irq;
0248 
0249     priv = dev->parent->priv;
0250 
0251     /* Get IRQ number from index and device information */
0252     irq = ambapp_int_get(dev, index);
0253     if ( irq < 0 ) 
0254         return -1;
0255 
0256     DBG("Clear interrupt on 0x%x for dev 0x%x (IRQ: %d)\n",
0257         (unsigned int)dev->parent->dev, (unsigned int)dev, irq);
0258 
0259     if ( priv->config->ops->int_clear ) {
0260         /* Let device override driver default */
0261         return priv->config->ops->int_clear(dev, irq);
0262     } else {
0263         return DRVMGR_ENOSYS;
0264     }
0265 }
0266 
0267 static int ambapp_int_mask(
0268     struct drvmgr_dev *dev,
0269     int index)
0270 {
0271     struct ambapp_priv *priv;
0272     int irq;
0273 
0274     priv = dev->parent->priv;
0275 
0276     /* Get IRQ number from index and device information */
0277     irq = ambapp_int_get(dev, index);
0278     if ( irq < 0 ) 
0279         return -1;
0280 
0281     DBG("MASK interrupt on 0x%x for dev 0x%x (IRQ: %d)\n",
0282         (unsigned int)dev->parent->dev, (unsigned int)dev, irq);
0283 
0284     if ( priv->config->ops->int_mask ) {
0285         /* Let device override driver default */
0286         return priv->config->ops->int_mask(dev, irq);
0287     } else {
0288         return DRVMGR_ENOSYS;
0289     }
0290 }
0291 
0292 static int ambapp_int_unmask(
0293     struct drvmgr_dev *dev,
0294     int index)
0295 {
0296     struct ambapp_priv *priv;
0297     int irq;
0298 
0299     priv = dev->parent->priv;
0300 
0301     /* Get IRQ number from index and device information */
0302     irq = ambapp_int_get(dev, index);
0303     if ( irq < 0 ) 
0304         return DRVMGR_EINVAL;
0305 
0306     DBG("UNMASK interrupt on 0x%x for dev 0x%x (IRQ: %d)\n",
0307         (unsigned int)dev->parent->dev, (unsigned int)dev, irq);
0308 
0309     if ( priv->config->ops->int_unmask ) {
0310         /* Let device override driver default */
0311         return priv->config->ops->int_unmask(dev, irq);
0312     } else {
0313         return DRVMGR_ENOSYS;
0314     }
0315 }
0316 
0317 /* Assign frequency to an AMBA Bus */
0318 void ambapp_bus_freq_register(
0319     struct drvmgr_dev *dev,
0320     int amba_interface,
0321     unsigned int freq_hz
0322     )
0323 {
0324     struct ambapp_priv *priv = (struct ambapp_priv *)dev->parent->priv;
0325     struct ambapp_dev *adev;
0326     struct amba_dev_info *pnp = dev->businfo;
0327 
0328     if ( freq_hz == 0 )
0329         return;
0330 
0331     if ( amba_interface == DEV_AHB_MST ) {
0332         adev = (struct ambapp_dev *)
0333             ((unsigned int)pnp->info.ahb_mst -
0334                 sizeof(struct ambapp_dev));
0335     } else if ( amba_interface == DEV_AHB_SLV ) {
0336         adev = (struct ambapp_dev *)
0337             ((unsigned int)pnp->info.ahb_slv -
0338                 sizeof(struct ambapp_dev));
0339     } else if ( amba_interface == DEV_APB_SLV ) {
0340         adev = (struct ambapp_dev *)
0341             ((unsigned int)pnp->info.apb_slv -
0342                 sizeof(struct ambapp_dev));
0343     } else {
0344         return;
0345     }
0346 
0347     /* Calculate Top bus frequency from lower part. The frequency comes
0348      * from some kind of hardware able to report local bus frequency.
0349      */
0350     ambapp_freq_init(priv->config->abus, adev, freq_hz);
0351 }
0352 
0353 static int ambapp_bus_freq_get(
0354     struct drvmgr_dev *dev,
0355     int options,
0356     unsigned int *freq_hz)
0357 {
0358     struct ambapp_priv *priv = (struct ambapp_priv *)dev->parent->priv;
0359     struct ambapp_dev *adev;
0360     struct amba_dev_info *pnp = dev->businfo;
0361 
0362     if ( options == DEV_AHB_MST ) {
0363         adev = (struct ambapp_dev *)
0364             ((unsigned int)pnp->info.ahb_mst -
0365                 sizeof(struct ambapp_dev));
0366     } else if ( options == DEV_AHB_SLV ) {
0367         adev = (struct ambapp_dev *)
0368             ((unsigned int)pnp->info.ahb_slv -
0369                 sizeof(struct ambapp_dev));
0370     } else if ( options == DEV_APB_SLV ) {
0371         adev = (struct ambapp_dev *)
0372             ((unsigned int)pnp->info.apb_slv -
0373                 sizeof(struct ambapp_dev));
0374     } else {
0375         *freq_hz = 0;
0376         return -1;
0377     }
0378 
0379     /* Calculate core/bus frequency from top most bus frequency. */
0380     *freq_hz = ambapp_freq_get(priv->config->abus, adev);
0381     if ( *freq_hz == 0 )
0382         return -1;
0383     return 0;
0384 }
0385 
0386 static int ambapp_get_params(
0387     struct drvmgr_dev *dev,
0388     struct drvmgr_bus_params *params)
0389 {
0390     struct ambapp_priv *priv = dev->parent->priv;
0391 
0392     if ( priv->config->ops->get_params ) {
0393         /* Let device override driver default */
0394         return priv->config->ops->get_params(dev, params);
0395     } else {
0396         return -1;
0397     }
0398 }
0399 
0400 #ifdef AMBAPPBUS_INFO_AVAIL
0401 static void ambapp_dev_info(
0402     struct drvmgr_dev *dev,
0403     void (*print_line)(void *p, char *str),
0404     void *p)
0405 {
0406     struct amba_dev_info *devinfo;
0407     struct ambapp_core *core;
0408     char buf[64];
0409     int ver, i;
0410     char *str1, *str2, *str3;
0411     unsigned int ahbmst_freq, ahbslv_freq, apbslv_freq;
0412 
0413     if (!dev)
0414         return;
0415 
0416     devinfo = (struct amba_dev_info *)dev->businfo;
0417     if (!devinfo)
0418         return;
0419     core = &devinfo->info;
0420 
0421     print_line(p, "AMBA PnP DEVICE");
0422 
0423     str1 = ambapp_vendor_id2str(devinfo->id.vendor);
0424     if (str1 == NULL)
0425         str1 = "unknown";
0426     sprintf(buf, "VENDOR ID:   0x%04x  (%s)", devinfo->id.vendor, str1);
0427     print_line(p, buf);
0428 
0429     str1 = ambapp_device_id2str(devinfo->id.vendor, devinfo->id.device);
0430     if (str1 == NULL)
0431         str1 = "unknown";
0432     sprintf(buf, "DEVICE ID:   0x%04x  (%s)", devinfo->id.device, str1);
0433     print_line(p, buf);
0434 
0435     ahbmst_freq = ahbslv_freq = apbslv_freq = 0;
0436     ver = 0;
0437     str1 = str2 = str3 = "";
0438     if (core->ahb_mst) {
0439         str1 = "AHBMST ";
0440         ver = core->ahb_mst->common.ver;
0441         ambapp_bus_freq_get(dev, DEV_AHB_MST, &ahbmst_freq);
0442     }
0443     if (core->ahb_slv) {
0444         str2 = "AHBSLV ";
0445         ver = core->ahb_slv->common.ver;
0446         ambapp_bus_freq_get(dev, DEV_AHB_SLV, &ahbslv_freq);
0447     }
0448     if (core->apb_slv) {
0449         str3 = "APBSLV";
0450         ver = core->apb_slv->common.ver;
0451         ambapp_bus_freq_get(dev, DEV_APB_SLV, &apbslv_freq);
0452     }
0453 
0454     sprintf(buf, "IRQ:         %d", ambapp_int_get(dev, 0));
0455     print_line(p, buf);
0456 
0457     sprintf(buf, "VERSION:     0x%x", ver);
0458     print_line(p, buf);
0459 
0460     sprintf(buf, "ambapp_core: %p", core);
0461     print_line(p, buf);
0462 
0463     sprintf(buf, "interfaces:  %s%s%s", str1, str2, str3);
0464     print_line(p, buf);
0465 
0466     if (ahbmst_freq != 0) {
0467         sprintf(buf, "AHBMST FREQ: %dkHz", ahbmst_freq/1000);
0468         print_line(p, buf);
0469     }
0470 
0471     if (ahbslv_freq != 0) {
0472         sprintf(buf, "AHBSLV FREQ: %dkHz", ahbslv_freq/1000);
0473         print_line(p, buf);
0474     }
0475 
0476     if (apbslv_freq != 0) {
0477         sprintf(buf, "APBSLV FREQ: %dkHz", apbslv_freq/1000);
0478         print_line(p, buf);
0479     }
0480 
0481     if (core->ahb_slv) {
0482         for(i=0; i<4; i++) {
0483             if (core->ahb_slv->type[i] == AMBA_TYPE_AHBIO)
0484                 str1 = " ahbio";
0485             else if (core->ahb_slv->type[i] == AMBA_TYPE_MEM)
0486                 str1 = "ahbmem";
0487             else
0488                 continue;
0489             sprintf(buf, " %s[%d]:  0x%08x-0x%08x", str1, i,
0490                 core->ahb_slv->start[i],
0491                 core->ahb_slv->start[i]+core->ahb_slv->mask[i]-1);
0492             print_line(p, buf);
0493         }
0494     }
0495     if (core->apb_slv) {
0496         sprintf(buf, "       apb:  0x%08x-0x%08x",
0497             core->apb_slv->start,
0498             core->apb_slv->start + core->apb_slv->mask - 1);
0499         print_line(p, buf);
0500     }
0501 }
0502 #endif
0503 
0504 /* Fix device in last stage and/or register additional devices.
0505  * Function returns:
0506  *  0  Register device as normal
0507  *  1  Fixup function handles registration
0508  */
0509 static int ambapp_dev_fixup(struct drvmgr_dev *dev, struct amba_dev_info *pnp)
0510 {
0511     /* OCCAN speciality:
0512      *  Mulitple cores are supported through the same amba AHB interface.
0513      *  The number of "sub cores" can be detected by decoding the AMBA
0514      *  Plug&Play version information. verion = ncores. A maximum of 8
0515      *  sub cores are supported, each separeated with 0x100 inbetween.
0516      *
0517      *  Now, lets detect sub cores.
0518      */
0519     if ( (pnp->info.device == GAISLER_CANAHB) &&
0520          (pnp->info.vendor == VENDOR_GAISLER) ) {
0521         struct drvmgr_dev *newdev, *devs_to_register[8];
0522         struct amba_dev_info *pnpinfo;
0523         int subcores;
0524         int core;
0525 
0526         devs_to_register[0] = dev;
0527         subcores = (pnp->info.ahb_slv->common.ver & 0x7) + 1;
0528         for(core = 1; core < subcores; core++) {
0529             drvmgr_alloc_dev(&newdev, sizeof(*pnpinfo));
0530             memcpy(newdev, dev, sizeof(*newdev));
0531             pnpinfo = (struct amba_dev_info *)(newdev+1);
0532             memcpy(pnpinfo, pnp, sizeof(*pnp));
0533             pnpinfo->info.index = core;
0534             pnpinfo->info.irq += core;
0535             newdev->businfo = (void *)pnpinfo;
0536 
0537             devs_to_register[core] = newdev;
0538         }
0539         /* Register all CAN devices */
0540         for(core = 0; core < subcores; core++)
0541             drvmgr_dev_register(devs_to_register[core]);
0542         return 1;
0543     } else if ( (pnp->info.device == GAISLER_GPIO) &&
0544             (pnp->info.vendor == VENDOR_GAISLER) ) {
0545         /* PIO[N] is connected to IRQ[N]. */
0546         pnp->info.irq = 0;
0547     }
0548     return 0;
0549 }
0550 
0551 struct ambapp_dev_reg_struct {
0552     struct ambapp_bus   *abus;
0553     struct drvmgr_bus   *bus;
0554     struct ambapp_dev   *ahb_mst;
0555     struct ambapp_dev   *ahb_slv;
0556     struct ambapp_dev   *apb_slv;
0557 };
0558 
0559 static void ambapp_core_register(
0560     struct ambapp_dev   *ahb_mst,
0561     struct ambapp_dev   *ahb_slv,
0562     struct ambapp_dev   *apb_slv,
0563     struct ambapp_dev_reg_struct *arg
0564     )
0565 {
0566     struct drvmgr_dev *newdev;
0567     struct amba_dev_info *pnpinfo;
0568     unsigned short device;
0569     unsigned char vendor;
0570     int namelen;
0571     char buf[64];
0572 
0573     if ( ahb_mst ) {
0574         device = ahb_mst->device;
0575         vendor = ahb_mst->vendor;
0576     }else if ( ahb_slv ) {
0577         device = ahb_slv->device;
0578         vendor = ahb_slv->vendor;
0579     }else if( apb_slv ) {
0580         device = apb_slv->device;
0581         vendor = apb_slv->vendor;
0582     } else {
0583         DBG("NO DEV!\n");
0584         return;
0585     }
0586 
0587     DBG("CORE REGISTER DEV [%x:%x] MST: 0x%x, SLV: 0x%x, APB: 0x%x\n", vendor, device, (unsigned int)ahb_mst, (unsigned int)ahb_slv, (unsigned int)apb_slv);
0588 
0589     /* Get unique device name from AMBA data base by combining VENDOR and
0590      * DEVICE short names
0591      */
0592     namelen = ambapp_vendev_id2str(vendor, device, buf);
0593 
0594     /* Allocate a device */     
0595     drvmgr_alloc_dev(&newdev, sizeof(struct amba_dev_info) + namelen);
0596     pnpinfo = (struct amba_dev_info *)(newdev + 1);
0597     newdev->parent = arg->bus; /* Ourselfs */
0598     newdev->minor_drv = 0;
0599     newdev->minor_bus = 0;
0600     newdev->priv = NULL;
0601     newdev->drv = NULL;
0602     if (namelen > 0) {
0603         newdev->name = (char *)(pnpinfo + 1);
0604         strcpy(newdev->name, buf);
0605     } else {
0606         newdev->name = NULL;
0607     }
0608     newdev->next_in_drv = NULL;
0609     newdev->bus = NULL;
0610 
0611     /* Init PnP information, Assign Core interfaces with this device */
0612     pnpinfo->id.vendor = vendor;
0613     pnpinfo->id.device = device;
0614     pnpinfo->info.vendor = vendor;
0615     pnpinfo->info.device = device;
0616     pnpinfo->info.index = 0;
0617     if ( ahb_mst ) {
0618         pnpinfo->info.ahb_mst = (struct ambapp_ahb_info *)
0619                         ahb_mst->devinfo;
0620         ambapp_alloc_dev(ahb_mst, (void *)newdev);
0621         if ( pnpinfo->info.ahb_mst->common.irq )
0622             pnpinfo->info.irq = pnpinfo->info.ahb_mst->common.irq;
0623     }
0624     if ( ahb_slv ) {
0625         pnpinfo->info.ahb_slv = (struct ambapp_ahb_info *)
0626                     ahb_slv->devinfo;
0627         ambapp_alloc_dev(ahb_slv, (void *)newdev);
0628         if ( pnpinfo->info.ahb_slv->common.irq )
0629             pnpinfo->info.irq = pnpinfo->info.ahb_slv->common.irq;
0630     }
0631     if ( apb_slv ) {
0632         pnpinfo->info.apb_slv = (struct ambapp_apb_info *)
0633                     apb_slv->devinfo;
0634         ambapp_alloc_dev(apb_slv, (void *)newdev);
0635         if ( pnpinfo->info.apb_slv->common.irq )
0636             pnpinfo->info.irq = pnpinfo->info.apb_slv->common.irq;
0637     }
0638     if ( pnpinfo->info.irq == 0 )
0639         pnpinfo->info.irq = -1; /* indicate no IRQ */
0640 
0641     /* Connect device with PnP information */
0642     newdev->businfo = (void *)pnpinfo;
0643 
0644     if ( ambapp_dev_fixup(newdev, pnpinfo) == 0 )
0645         drvmgr_dev_register(newdev); /* Register New Device */
0646 }
0647 
0648 /* Fix device registration.
0649  * Function returns:
0650  *  0  Register device as normal
0651  *  1  Fixup function handles registration
0652  */
0653 static int ambapp_dev_register_fixup(struct ambapp_dev *dev, struct ambapp_dev_reg_struct *p)
0654 {
0655     /* GR740 GRPCI2 speciality:
0656      * - In the GR740 the APB_SLV is detected before the AHB_SLV
0657      *   which makes the registration incorrect. We deal with it in 
0658      *   this function. */
0659     if (    (dev->dev_type == DEV_APB_SLV) &&
0660             (dev->device == GAISLER_GRPCI2) &&
0661             (dev->vendor == VENDOR_GAISLER) &&
0662             (p->ahb_slv == NULL) ) {
0663         DBG("GRPCI2 APB_SLV detected before AHB_SLV. Skipping APB_SLV registration.\n");
0664         return 1;
0665     }
0666     return 0;
0667 }
0668 
0669 /* Register one AMBA device */
0670 static int ambapp_dev_register(struct ambapp_dev *dev, int index, void *arg)
0671 {
0672     struct ambapp_dev_reg_struct *p = arg;
0673 
0674 #ifdef DEBUG
0675     char *type;
0676 
0677     if ( dev->dev_type == DEV_AHB_MST )
0678         type = "AHB MST";
0679     else if ( dev->dev_type == DEV_AHB_SLV )
0680         type = "AHB SLV";
0681     else if ( dev->dev_type == DEV_APB_SLV )
0682         type = "APB SLV";
0683     
0684     DBG("Found [%d:%x:%x], %s\n", index, dev->vendor, dev->device, type);
0685 #endif
0686 
0687     /* Fixup for device registration */
0688     if (ambapp_dev_register_fixup(dev, p)){
0689         return 0;
0690     }
0691 
0692     if ( dev->dev_type == DEV_AHB_MST ) {
0693         if ( p->ahb_mst ) {
0694             /* This should not happen */
0695             printk("ambapp_dev_register: ahb_mst not NULL!\n");
0696             exit(1);
0697         }
0698 
0699         /* Remember AHB Master */
0700         p->ahb_mst = dev;
0701 
0702         /* Find AHB Slave and APB slave for this Core */
0703         ambapp_for_each(p->abus, (OPTIONS_AHB_SLVS|OPTIONS_APB_SLVS|OPTIONS_FREE), dev->vendor, dev->device, ambapp_dev_register, p);
0704 
0705         ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
0706         p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
0707         return 0;
0708 
0709     } else if ( dev->dev_type == DEV_AHB_SLV ) {
0710         if ( p->ahb_slv ) {
0711             /* Already got our AHB Slave interface */
0712             return 0;
0713         }
0714 
0715         /* Remember AHB Slave */
0716         p->ahb_slv = dev;
0717 
0718         if ( p->ahb_mst ) {
0719             /* Continue searching for APB Slave */
0720             return 0;
0721         } else {
0722             /* Find APB Slave interface for this Core */
0723             ambapp_for_each(p->abus, (OPTIONS_APB_SLVS|OPTIONS_FREE), dev->vendor, dev->device, ambapp_dev_register, p);
0724 
0725             ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
0726             p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
0727             return 0;
0728         }
0729     } else if ( dev->dev_type == DEV_APB_SLV ) {
0730         if ( p->apb_slv ) {
0731             /* This should not happen */
0732             printk("ambapp_dev_register: apb_slv not NULL!\n");
0733             exit(1);
0734         }
0735         /* Remember APB Slave */
0736         p->apb_slv = dev;
0737 
0738         if ( p->ahb_mst || p->ahb_slv ) {
0739             /* Stop scanning */
0740             return 1;
0741         } else {
0742             ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
0743             p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
0744             return 0;
0745         }
0746     }
0747 
0748     return 0;
0749 }
0750 
0751 /* Register all AMBA devices available on the AMBAPP bus */
0752 static int ambapp_ids_register(struct drvmgr_bus *bus)
0753 {
0754     struct ambapp_priv *priv = bus->priv;
0755     struct ambapp_bus *abus;
0756     struct ambapp_dev_reg_struct arg;
0757 
0758     DBG("ambapp_ids_register:\n");
0759 
0760     memset(&arg, 0, sizeof(arg));
0761 
0762     abus = priv->config->abus;
0763     arg.abus = abus;
0764     arg.bus = bus;
0765 
0766     /* Combine the AHB MST, AHB SLV and APB SLV interfaces of a core. A core has often more than
0767      * one interface. A core can not have more than one interface of the same type.
0768      */
0769     ambapp_for_each(abus, (OPTIONS_ALL_DEVS|OPTIONS_FREE), -1, -1, ambapp_dev_register, &arg);
0770 
0771 #ifdef DEBUG
0772     ambapp_print(abus->root, 1);
0773 #endif
0774 
0775     return DRVMGR_OK;
0776 }
0777 
0778 /*** DEVICE FUNCTIONS ***/
0779 
0780 int ambapp_bus_register(struct drvmgr_dev *dev, struct ambapp_config *config)
0781 {
0782     struct ambapp_priv *priv;
0783 
0784     if ( !config || !config->ops )
0785         return DRVMGR_OK;
0786 
0787     DBG("AMBAPP BUS: initializing\n");
0788 
0789     /* Register BUS */
0790     drvmgr_alloc_bus(&dev->bus, sizeof(struct ambapp_priv));
0791     priv = (struct ambapp_priv *)(dev->bus + 1);
0792     priv->config = config;
0793     if ( priv->config->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST )
0794         dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP_DIST;
0795     else if ( priv->config->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP )
0796         dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP_RMAP;
0797     else
0798         dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP;
0799     dev->bus->next = NULL;
0800     dev->bus->dev = dev;
0801     dev->bus->priv = priv;
0802     dev->bus->children = NULL;
0803     dev->bus->ops = &ambapp_bus_ops;
0804     dev->bus->funcs = config->funcs;
0805     dev->bus->dev_cnt = 0;
0806     dev->bus->reslist = NULL;
0807     dev->bus->maps_up = config->maps_up;
0808     dev->bus->maps_down = config->maps_down;
0809 
0810     /* Add resource configuration */
0811     if ( priv->config->resources )
0812         drvmgr_bus_res_add(dev->bus, priv->config->resources);
0813 
0814     drvmgr_bus_register(dev->bus);
0815 
0816     return DRVMGR_OK;
0817 }
0818 
0819 /*** BUS INITIALIZE FUNCTIONS ***/
0820 
0821 /* Initialize the bus, register devices on this bus */
0822 static int ambapp_bus_init1(struct drvmgr_bus *bus)
0823 {
0824     /* Initialize the bus, register devices on this bus */
0825     return ambapp_ids_register(bus);
0826 }
0827 
0828 static int ambapp_bus_remove(struct drvmgr_bus *bus)
0829 {
0830     return DRVMGR_OK;
0831 }
0832 
0833 #ifdef RTEMS_SMP
0834 static int ambapp_int_set_affinity(
0835     struct drvmgr_dev *dev,
0836     int index,
0837     const Processor_mask *cpus)
0838 {
0839     struct ambapp_priv *priv;
0840     int irq;
0841 
0842     priv = dev->parent->priv;
0843 
0844     /* Get IRQ number from index and device information */
0845     irq = ambapp_int_get(dev, index);
0846     if (irq < 0)
0847         return DRVMGR_EINVAL;
0848 
0849     DBG("Set interrupt affinity on 0x%x for dev 0x%x (IRQ: %d)\n",
0850         (unsigned int)dev->parent->dev, (unsigned int)dev, irq);
0851 
0852     if (priv->config->ops->int_set_affinity) {
0853         /* Let device override driver default */
0854         return priv->config->ops->int_set_affinity(dev, irq, cpus);
0855     } else {
0856         return DRVMGR_ENOSYS;
0857     }
0858 }
0859 #endif