Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  GRLIB GRPCI PCI HOST driver.
0004  * 
0005  *  COPYRIGHT (c) 2008.
0006  *  Cobham Gaisler AB.
0007  *
0008  *  Configures the GRPCI core and initialize,
0009  *   - the PCI Library (pci.c)
0010  *   - the general part of the PCI Bus driver (pci_bus.c)
0011  *  
0012  *  System interrupt assigned to PCI interrupt (INTA#..INTD#) is by
0013  *  default taken from Plug and Play, but may be overridden by the 
0014  *  driver resources INTA#..INTD#.
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #include <stdlib.h>
0039 #include <stdio.h>
0040 #include <string.h>
0041 #include <rtems/bspIo.h>
0042 #include <libcpu/byteorder.h>
0043 #include <libcpu/access.h>
0044 #include <pci.h>
0045 #include <pci/cfg.h>
0046 
0047 #include <drvmgr/drvmgr.h>
0048 #include <grlib/ambapp_bus.h>
0049 #include <grlib/ambapp.h>
0050 #include <drvmgr/pci_bus.h>
0051 #include <grlib/grpci.h>
0052 
0053 #define DMAPCI_ADDR 0x80000500
0054 
0055 /* Configuration options */
0056 #define SYSTEM_MAINMEM_START 0x40000000
0057 
0058 /* If defined to 1 - byte twisting is enabled by default */
0059 #define DEFAULT_BT_ENABLED 0
0060 
0061 /* Interrupt assignment. Set to other value than 0xff in order to 
0062  * override defaults and plug&play information
0063  */
0064 #ifndef GRPCI_INTA_SYSIRQ
0065  #define GRPCI_INTA_SYSIRQ 0xff
0066 #endif
0067 #ifndef GRPCI_INTB_SYSIRQ
0068  #define GRPCI_INTB_SYSIRQ 0xff
0069 #endif
0070 #ifndef GRPCI_INTC_SYSIRQ
0071  #define GRPCI_INTC_SYSIRQ 0xff
0072 #endif
0073 #ifndef GRPCI_INTD_SYSIRQ
0074  #define GRPCI_INTD_SYSIRQ 0xff
0075 #endif
0076 
0077 #define PAGE0_BTEN_BIT    0
0078 #define PAGE0_BTEN        (1<<PAGE0_BTEN_BIT)
0079 
0080 #define CFGSTAT_HOST_BIT  13
0081 #define CFGSTAT_HOST      (1<<CFGSTAT_HOST_BIT)
0082 
0083 /*#define DEBUG 1*/
0084 
0085 #ifdef DEBUG
0086 #define DBG(x...) printk(x)
0087 #else
0088 #define DBG(x...) 
0089 #endif
0090 
0091 /*
0092  * Bit encode for PCI_CONFIG_HEADER_TYPE register
0093  */
0094 struct grpci_regs {
0095     volatile unsigned int cfg_stat;
0096     volatile unsigned int bar0;
0097     volatile unsigned int page0;
0098     volatile unsigned int bar1;
0099     volatile unsigned int page1;
0100     volatile unsigned int iomap;
0101     volatile unsigned int stat_cmd;
0102     volatile unsigned int irq;
0103 };
0104 
0105 #define HOST_TGT PCI_DEV(0xff, 0, 0)
0106 
0107 struct grpci_priv *grpcipriv = NULL;
0108 static int grpci_minor = 0;
0109 static unsigned int *pcidma = (unsigned int *)DMAPCI_ADDR;
0110 
0111 /* PCI Interrupt assignment. Connects an PCI interrupt pin (INTA#..INTD#)
0112  * to a system interrupt number.
0113  */
0114 unsigned char grpci_pci_irq_table[4] =
0115 {
0116     /* INTA# */ GRPCI_INTA_SYSIRQ,
0117     /* INTB# */ GRPCI_INTB_SYSIRQ,
0118     /* INTC# */ GRPCI_INTC_SYSIRQ,
0119     /* INTD# */ GRPCI_INTD_SYSIRQ
0120 };
0121 
0122 /* Driver private data struture */
0123 struct grpci_priv {
0124     struct drvmgr_dev   *dev;
0125     struct grpci_regs       *regs;
0126     int             irq;
0127     int             minor;
0128 
0129     uint32_t            bar1_pci_adr;
0130     uint32_t            bar1_size;
0131 
0132     int             bt_enabled;
0133     unsigned int            pci_area;
0134     unsigned int            pci_area_end;
0135     unsigned int            pci_io;    
0136     unsigned int            pci_conf;
0137     unsigned int            pci_conf_end;
0138 
0139     uint32_t            devVend; /* Host PCI Vendor/Device ID */
0140 
0141     struct drvmgr_map_entry maps_up[2];
0142     struct drvmgr_map_entry maps_down[2];
0143     struct pcibus_config    config;
0144 };
0145 
0146 int grpci_init1(struct drvmgr_dev *dev);
0147 
0148 /* GRPCI DRIVER */
0149 
0150 struct drvmgr_drv_ops grpci_ops = 
0151 {
0152     .init = {grpci_init1, NULL, NULL, NULL},
0153     .remove = NULL,
0154     .info = NULL
0155 };
0156 
0157 struct amba_dev_id grpci_ids[] = 
0158 {
0159     {VENDOR_GAISLER, GAISLER_PCIFBRG},
0160     {0, 0}      /* Mark end of table */
0161 };
0162 
0163 struct amba_drv_info grpci_info =
0164 {
0165     {
0166         DRVMGR_OBJ_DRV,         /* Driver */
0167         NULL,               /* Next driver */
0168         NULL,               /* Device list */
0169         DRIVER_AMBAPP_GAISLER_GRPCI_ID, /* Driver ID */
0170         "GRPCI_DRV",            /* Driver Name */
0171         DRVMGR_BUS_TYPE_AMBAPP,     /* Bus Type */
0172         &grpci_ops,
0173         NULL,               /* Funcs */
0174         0,              /* No devices yet */
0175         sizeof(struct grpci_priv),  /* Make drvmgr alloc private */
0176     },
0177     &grpci_ids[0]
0178 };
0179 
0180 void grpci_register_drv(void)
0181 {
0182     DBG("Registering GRPCI driver\n");
0183     drvmgr_drv_register(&grpci_info.general);
0184 }
0185 
0186 static int grpci_cfg_r32(pci_dev_t dev, int ofs, uint32_t *val)
0187 {
0188     struct grpci_priv *priv = grpcipriv;
0189     volatile uint32_t *pci_conf;
0190     uint32_t devfn;
0191     int retval;
0192     int bus = PCI_DEV_BUS(dev);
0193 
0194     if (ofs & 3)
0195         return PCISTS_EINVAL;
0196 
0197     if (PCI_DEV_SLOT(dev) > 15) {
0198         *val = 0xffffffff;
0199         return PCISTS_OK;
0200     }
0201 
0202     /* GRPCI can access "non-standard" devices on bus0 (on AD11.AD16), 
0203      * but we skip them.
0204      */
0205     if (dev == HOST_TGT)
0206         bus = devfn = 0;
0207     else if (bus == 0)
0208         devfn = PCI_DEV_DEVFUNC(dev) + PCI_DEV(0, 6, 0);
0209     else
0210         devfn = PCI_DEV_DEVFUNC(dev);
0211 
0212     /* Select bus */
0213     priv->regs->cfg_stat = (priv->regs->cfg_stat & ~(0xf<<23)) | (bus<<23);
0214 
0215     pci_conf = (volatile uint32_t *)(priv->pci_conf | (devfn << 8) | ofs);
0216 
0217     if (priv->bt_enabled) {
0218         *val =  CPU_swap_u32(*pci_conf);
0219     } else {
0220         *val = *pci_conf;
0221     }
0222 
0223     if (priv->regs->cfg_stat & 0x100) {
0224         *val = 0xffffffff;
0225         retval = PCISTS_MSTABRT;
0226     } else
0227         retval = PCISTS_OK;
0228 
0229     DBG("pci_read: [%x:%x:%x] reg: 0x%x => addr: 0x%x, val: 0x%x\n",
0230         PCI_DEV_EXPAND(dev), ofs, pci_conf, *val);
0231 
0232     return retval;
0233 }
0234 
0235 
0236 static int grpci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *val)
0237 {
0238     uint32_t v;
0239     int retval;
0240 
0241     if (ofs & 1)
0242         return PCISTS_EINVAL;
0243 
0244     retval = grpci_cfg_r32(dev, ofs & ~0x3, &v);
0245     *val = 0xffff & (v >> (8*(ofs & 0x3)));
0246 
0247     return retval;
0248 }
0249 
0250 static int grpci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *val)
0251 {
0252     uint32_t v;
0253     int retval;
0254 
0255     retval = grpci_cfg_r32(dev, ofs & ~0x3, &v);
0256 
0257     *val = 0xff & (v >> (8*(ofs & 3)));
0258 
0259     return retval;
0260 }
0261 
0262 static int grpci_cfg_w32(pci_dev_t dev, int ofs, uint32_t val)
0263 {
0264     struct grpci_priv *priv = grpcipriv;
0265     volatile uint32_t *pci_conf;
0266     uint32_t value, devfn = PCI_DEV_DEVFUNC(dev);
0267     int bus = PCI_DEV_BUS(dev);
0268 
0269     if (ofs & 0x3)
0270         return PCISTS_EINVAL;
0271 
0272     if (PCI_DEV_SLOT(dev) > 15)
0273         return PCISTS_MSTABRT;
0274 
0275     /* GRPCI can access "non-standard" devices on bus0 (on AD11.AD16), 
0276      * but we skip them.
0277      */
0278     if (dev == HOST_TGT)
0279         bus = devfn = 0;
0280     else if (bus == 0)
0281         devfn = PCI_DEV_DEVFUNC(dev) + PCI_DEV(0, 6, 0);
0282     else
0283         devfn = PCI_DEV_DEVFUNC(dev);
0284 
0285     /* Select bus */
0286     priv->regs->cfg_stat = (priv->regs->cfg_stat & ~(0xf<<23)) | (bus<<23);
0287 
0288     pci_conf = (volatile uint32_t *)(priv->pci_conf | (devfn << 8) | ofs);
0289 
0290     if ( priv->bt_enabled ) {
0291         value = CPU_swap_u32(val);
0292     } else {
0293         value = val;
0294     }
0295 
0296     *pci_conf = value;
0297 
0298     DBG("pci_write - [%x:%x:%x] reg: 0x%x => addr: 0x%x, val: 0x%x\n",
0299         PCI_DEV_EXPAND(dev), ofs, pci_conf, value);
0300 
0301     return PCISTS_OK;
0302 }
0303 
0304 static int grpci_cfg_w16(pci_dev_t dev, int ofs, uint16_t val)
0305 {
0306     uint32_t v;
0307     int retval;
0308 
0309     if (ofs & 1)
0310         return PCISTS_EINVAL;
0311 
0312     retval = grpci_cfg_r32(dev, ofs & ~0x3, &v);
0313     if (retval != PCISTS_OK)
0314         return retval;
0315 
0316     v = (v & ~(0xffff << (8*(ofs&3)))) | ((0xffff&val) << (8*(ofs&3)));
0317 
0318     return grpci_cfg_w32(dev, ofs & ~0x3, v);
0319 }
0320 
0321 static int grpci_cfg_w8(pci_dev_t dev, int ofs, uint8_t val)
0322 {
0323     uint32_t v;
0324     int retval;
0325 
0326     retval = grpci_cfg_r32(dev, ofs & ~0x3, &v);
0327     if (retval != PCISTS_OK)
0328         return retval;
0329 
0330     v = (v & ~(0xff << (8*(ofs&3)))) | ((0xff&val) << (8*(ofs&3)));
0331 
0332     return grpci_cfg_w32(dev, ofs & ~0x3, v);
0333 }
0334 
0335 /* Return the assigned system IRQ number that corresponds to the PCI
0336  * "Interrupt Pin" information from configuration space.
0337  *
0338  * The IRQ information is stored in the grpci_pci_irq_table configurable
0339  * by the user.
0340  *
0341  * Returns the "system IRQ" for the PCI INTA#..INTD# pin in irq_pin. Returns
0342  * 0xff if not assigned.
0343  */
0344 static uint8_t grpci_bus0_irq_map(pci_dev_t dev, int irq_pin)
0345 {
0346     uint8_t sysIrqNr = 0; /* not assigned */
0347     int irq_group;
0348 
0349     if ( (irq_pin >= 1) && (irq_pin <= 4) ) {
0350         /* Use default IRQ decoding on PCI BUS0 according slot numbering */
0351         irq_group = PCI_DEV_SLOT(dev) & 0x3;
0352         irq_pin = ((irq_pin - 1) + irq_group) & 0x3;
0353         /* Valid PCI "Interrupt Pin" number */
0354         sysIrqNr = grpci_pci_irq_table[irq_pin];
0355     }
0356     return sysIrqNr;
0357 }
0358 
0359 static int grpci_translate(uint32_t *address, int type, int dir)
0360 {
0361     uint32_t adr;
0362     struct grpci_priv *priv = grpcipriv;
0363 
0364     if (type == 1) {
0365         /* I/O */
0366         if (dir != 0) {
0367             /* The PCI bus can not access the CPU bus from I/O
0368              * because GRPCI core does not support I/O BARs
0369              */
0370             return -1;
0371         }
0372 
0373         /* We have got a PCI BAR address that the CPU want to access...
0374          * Check that it is within the PCI I/O window, I/O adresses
0375          * are mapped 1:1 with GRPCI driver... no translation needed.
0376          */
0377         adr = *(uint32_t *)address;
0378         if (adr < priv->pci_io || adr >= priv->pci_conf)
0379             return -1;
0380     } else {
0381         /* MEMIO and MEM.
0382          * Memory space is mapped 1:1 so no translation is needed.
0383          * Check that address is within accessible windows.
0384          */
0385         adr = *(uint32_t *)address;
0386         if (dir == 0) {
0387             /* PCI BAR to AMBA-CPU address.. check that it is
0388              * located within GRPCI PCI Memory Window
0389              * adr = PCI address.
0390              */
0391             if (adr < priv->pci_area || adr >= priv->pci_area_end)
0392                 return -1;
0393         } else {
0394             /* We have a CPU address and want to get access to it
0395              * from PCI space, typically when doing DMA into CPU
0396              * RAM. The GRPCI core has two target BARs that PCI
0397              * masters can access, we check here that the address
0398              * is accessible from PCI.
0399              * adr = AMBA address.
0400              */
0401             if (adr < priv->bar1_pci_adr ||
0402                 adr >= (priv->bar1_pci_adr + priv->bar1_size))
0403                 return -1;
0404         }
0405     }
0406 
0407     return 0;
0408 }
0409 
0410 extern struct pci_memreg_ops pci_memreg_sparc_le_ops;
0411 extern struct pci_memreg_ops pci_memreg_sparc_be_ops;
0412 
0413 /* GRPCI PCI access routines, default to Little-endian PCI Bus */
0414 struct pci_access_drv grpci_access_drv = {
0415     .cfg =
0416     {
0417         grpci_cfg_r8,
0418         grpci_cfg_r16,
0419         grpci_cfg_r32,
0420         grpci_cfg_w8,
0421         grpci_cfg_w16,
0422         grpci_cfg_w32,
0423     },
0424     .io =
0425     {
0426         _ld8,
0427         _ld_le16,
0428         _ld_le32,
0429         _st8,
0430         _st_le16,
0431         _st_le32,
0432     },
0433     .memreg = &pci_memreg_sparc_le_ops,
0434     .translate = grpci_translate,
0435 };
0436 
0437 struct pci_io_ops grpci_io_ops_be =
0438 {
0439     _ld8,
0440     _ld_be16,
0441     _ld_be32,
0442     _st8,
0443     _st_be16,
0444     _st_be32,
0445 };
0446 
0447 static int grpci_hw_init(struct grpci_priv *priv)
0448 {
0449     volatile unsigned int *mbar0, *page0;
0450     uint32_t data, addr, mbar0size;
0451     pci_dev_t host = HOST_TGT;
0452 
0453     mbar0 = (volatile unsigned int *)priv->pci_area;
0454 
0455     if ( !priv->bt_enabled && ((priv->regs->page0 & PAGE0_BTEN) == PAGE0_BTEN) ) {
0456         /* Byte twisting is on, turn it off */
0457         grpci_cfg_w32(host, PCIR_BAR(0), 0xffffffff);
0458         grpci_cfg_r32(host, PCIR_BAR(0), &addr);
0459         /* Setup bar0 to nonzero value */
0460         grpci_cfg_w32(host, PCIR_BAR(0),
0461                 CPU_swap_u32(0x80000000));
0462         /* page0 is accessed through upper half of bar0 */
0463         addr = (~CPU_swap_u32(addr)+1)>>1;
0464         mbar0size = addr*2;
0465         DBG("GRPCI: Size of MBAR0: 0x%x, MBAR0: 0x%x(lower) 0x%x(upper)\n",mbar0size,((unsigned int)mbar0),((unsigned int)mbar0)+mbar0size/2);
0466         page0 = &mbar0[mbar0size/8];
0467         DBG("GRPCI: PAGE0 reg address: 0x%x (0x%x)\n",((unsigned int)mbar0)+mbar0size/2,page0);
0468         priv->regs->cfg_stat = (priv->regs->cfg_stat & (~0xf0000000)) | 0x80000000;    /* Setup mmap reg so we can reach bar0 */ 
0469         *page0 = 0<<PAGE0_BTEN_BIT;                                         /* Disable bytetwisting ... */
0470     }
0471 
0472     /* Get the GRPCI Host PCI ID */
0473     grpci_cfg_r32(host, PCIR_VENDOR, &priv->devVend);
0474 
0475     /* set 1:1 mapping between AHB -> PCI memory */
0476     priv->regs->cfg_stat = (priv->regs->cfg_stat & 0x0fffffff) | priv->pci_area;
0477 
0478     /* determine size of target BAR1 */
0479     grpci_cfg_w32(host, PCIR_BAR(1), 0xffffffff);
0480     grpci_cfg_r32(host, PCIR_BAR(1), &addr);
0481     priv->bar1_size = (~(addr & ~0xf)) + 1;
0482 
0483     /* and map system RAM at pci address 0x40000000 */
0484     priv->bar1_pci_adr &= ~(priv->bar1_size - 1); /* Fix alignment of BAR1 */
0485     grpci_cfg_w32(host, PCIR_BAR(1), priv->bar1_pci_adr);
0486     priv->regs->page1 = priv->bar1_pci_adr;
0487 
0488     /* Translate I/O accesses 1:1 */
0489     priv->regs->iomap = priv->pci_io & 0xffff0000;
0490 
0491     /* Setup Latency Timer and cache line size. Default cache line
0492      * size will result in poor performance (256 word fetches), 0xff
0493      * will set it according to the max size of the PCI FIFO.
0494      */
0495     grpci_cfg_w8(host, PCIR_CACHELNSZ, 0xff);
0496     grpci_cfg_w8(host, PCIR_LATTIMER, 0x40);
0497 
0498     /* set as bus master and enable pci memory responses */  
0499     grpci_cfg_r32(host, PCIR_COMMAND, &data);
0500     data |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
0501     grpci_cfg_w32(host, PCIR_COMMAND, data);
0502 
0503     /* unmask all PCI interrupts at PCI Core, not all GRPCI cores support
0504      * this
0505      */
0506     priv->regs->irq = 0xf0000;
0507 
0508     /* Successful */
0509     return 0;
0510 }
0511 
0512 /* Initializes the GRPCI core and driver, must be called before calling init_pci() 
0513  *
0514  * Return values
0515  *  0             Successful initalization
0516  *  -1            Error during initialization, for example "PCI core not found".
0517  *  -2            Error PCI controller not HOST (targets not supported)
0518  *  -3            Error due to GRPCI hardware initialization
0519  *  -4            Error registering driver to PCI layer
0520  */
0521 static int grpci_init(struct grpci_priv *priv)
0522 {
0523     struct ambapp_apb_info *apb;
0524     struct ambapp_ahb_info *ahb;
0525     int pin;
0526     union drvmgr_key_value *value;
0527     char keyname[6];
0528     struct amba_dev_info *ainfo = priv->dev->businfo;
0529 
0530     /* Find PCI core from Plug&Play information */
0531     apb = ainfo->info.apb_slv;
0532     ahb = ainfo->info.ahb_slv;
0533 
0534     /* Found PCI core, init private structure */
0535     priv->irq = apb->common.irq;
0536     priv->regs = (struct grpci_regs *)apb->start;
0537     priv->bt_enabled = DEFAULT_BT_ENABLED;
0538 
0539     /* Calculate the PCI windows 
0540      *  AMBA->PCI Window:                       AHB SLAVE AREA0
0541      *  AMBA->PCI I/O cycles Window:            AHB SLAVE AREA1 Lower half
0542      *  AMBA->PCI Configuration cycles Window:  AHB SLAVE AREA1 Upper half
0543      */
0544     priv->pci_area     = ahb->start[0];
0545     priv->pci_area_end = ahb->start[0] + ahb->mask[0];
0546     priv->pci_io       = ahb->start[1];
0547     priv->pci_conf     = ahb->start[1] + (ahb->mask[1] >> 1);
0548     priv->pci_conf_end = ahb->start[1] + ahb->mask[1];
0549 
0550     /* On systems where PCI I/O area and configuration area is apart of the "PCI Window" 
0551      * the PCI Window stops at the start of the PCI I/O area
0552      */
0553     if ( (priv->pci_io > priv->pci_area) && (priv->pci_io < (priv->pci_area_end-1)) ) {
0554         priv->pci_area_end = priv->pci_io;
0555     }
0556 
0557     /* Init PCI interrupt assignment table to all use the interrupt routed through
0558      * the GRPCI core.
0559      */
0560     strcpy(keyname, "INTX#");
0561     for (pin=1; pin<5; pin++) {
0562         if ( grpci_pci_irq_table[pin-1] == 0xff ) {
0563             grpci_pci_irq_table[pin-1] = priv->irq;
0564 
0565             /* User may override Both hardcoded IRQ setup and Plug & Play IRQ */
0566             keyname[3] = 'A' + (pin-1);
0567             value = drvmgr_dev_key_get(priv->dev, keyname, DRVMGR_KT_INT);
0568             if ( value )
0569                 grpci_pci_irq_table[pin-1] = value->i;
0570         }
0571     }
0572 
0573     /* User may override DEFAULT_BT_ENABLED to enable/disable byte twisting */
0574     value = drvmgr_dev_key_get(priv->dev, "byteTwisting", DRVMGR_KT_INT);
0575     if ( value )
0576         priv->bt_enabled = value->i;
0577 
0578     /* Use GRPCI target BAR1 to map CPU RAM to PCI, this is to make it
0579      * possible for PCI peripherals to do DMA directly to CPU memory.
0580      */
0581     value = drvmgr_dev_key_get(priv->dev, "tgtbar1", DRVMGR_KT_INT);
0582     if (value)
0583         priv->bar1_pci_adr = value->i;
0584     else
0585         priv->bar1_pci_adr = SYSTEM_MAINMEM_START; /* default */
0586 
0587     /* This driver only support HOST systems, we check for HOST */
0588     if ( !(priv->regs->cfg_stat & CFGSTAT_HOST) ) {
0589         /* Target not supported */
0590         return -2;
0591     }
0592 
0593     /* Init the PCI Core */
0594     if ( grpci_hw_init(priv) ) {
0595         return -3;
0596     }
0597 
0598     /* Down streams translation table */
0599     priv->maps_down[0].name = "AMBA -> PCI MEM Window";
0600     priv->maps_down[0].size = priv->pci_area_end - priv->pci_area;
0601     priv->maps_down[0].from_adr = (void *)priv->pci_area;
0602     priv->maps_down[0].to_adr = (void *)priv->pci_area;
0603     /* End table */
0604     priv->maps_down[1].size = 0;
0605 
0606     /* Up streams translation table */
0607     priv->maps_up[0].name = "Target BAR1 -> AMBA";
0608     priv->maps_up[0].size = priv->bar1_size;
0609     priv->maps_up[0].from_adr = (void *)priv->bar1_pci_adr;
0610     priv->maps_up[0].to_adr = (void *)priv->bar1_pci_adr;
0611     /* End table */
0612     priv->maps_up[1].size = 0;
0613 
0614     return 0;
0615 }
0616 
0617 /* Called when a core is found with the AMBA device and vendor ID 
0618  * given in grpci_ids[]. IRQ, Console does not work here
0619  */
0620 int grpci_init1(struct drvmgr_dev *dev)
0621 {
0622     int status;
0623     struct grpci_priv *priv;
0624     struct pci_auto_setup grpci_auto_cfg;
0625 
0626     DBG("GRPCI[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0627 
0628     if ( grpci_minor != 0 ) {
0629         DBG("Driver only supports one PCI core\n");
0630         return DRVMGR_FAIL;
0631     }
0632 
0633     if ( (strcmp(dev->parent->dev->drv->name, "AMBAPP_GRLIB_DRV") != 0) && 
0634          (strcmp(dev->parent->dev->drv->name, "AMBAPP_LEON2_DRV") != 0) ) {
0635         /* We only support GRPCI driver on local bus */
0636         return DRVMGR_FAIL;
0637     }
0638 
0639     priv = dev->priv;
0640     if ( !priv )
0641         return DRVMGR_NOMEM;
0642 
0643     priv->dev = dev;
0644     priv->minor = grpci_minor++;
0645 
0646     grpcipriv = priv;
0647     status = grpci_init(priv);
0648     if (status) {
0649         printk("Failed to initialize grpci driver %d\n", status);
0650         return DRVMGR_FAIL;
0651     }
0652 
0653 
0654     /* Register the PCI core at the PCI layers */
0655 
0656     if (priv->bt_enabled == 0) {
0657         /* Host is Big-Endian */
0658         pci_endian = PCI_BIG_ENDIAN;
0659 
0660         memcpy(&grpci_access_drv.io, &grpci_io_ops_be,
0661                         sizeof(grpci_io_ops_be));
0662         grpci_access_drv.memreg = &pci_memreg_sparc_be_ops;
0663     }
0664 
0665     if (pci_access_drv_register(&grpci_access_drv)) {
0666         /* Access routines registration failed */
0667         return DRVMGR_FAIL;
0668     }
0669 
0670     /* Prepare memory MAP */
0671     grpci_auto_cfg.options = 0;
0672     grpci_auto_cfg.mem_start = 0;
0673     grpci_auto_cfg.mem_size = 0;
0674     grpci_auto_cfg.memio_start = priv->pci_area;
0675     grpci_auto_cfg.memio_size = priv->pci_area_end - priv->pci_area;
0676     grpci_auto_cfg.io_start = priv->pci_io;
0677     grpci_auto_cfg.io_size = priv->pci_conf - priv->pci_io;
0678     grpci_auto_cfg.irq_map = grpci_bus0_irq_map;
0679     grpci_auto_cfg.irq_route = NULL; /* use standard routing */
0680     pci_config_register(&grpci_auto_cfg);
0681 
0682     if (pci_config_init()) {
0683         /* PCI configuration failed */
0684         return DRVMGR_FAIL;
0685     }
0686 
0687     priv->config.maps_down = &priv->maps_down[0];
0688     priv->config.maps_up = &priv->maps_up[0];
0689     return pcibus_register(dev, &priv->config);
0690 }
0691 
0692 /* DMA functions which uses GRPCIs optional DMA controller (len in words) */
0693 int grpci_dma_to_pci(
0694     unsigned int ahb_addr,
0695     unsigned int pci_addr,
0696     unsigned int len)
0697 {
0698     int ret = 0;
0699 
0700     pcidma[0] = 0x82;
0701     pcidma[1] = ahb_addr;
0702     pcidma[2] = pci_addr;
0703     pcidma[3] = len;
0704     pcidma[0] = 0x83;        
0705 
0706     while ( (pcidma[0] & 0x4) == 0)
0707         ;
0708 
0709     if (pcidma[0] & 0x8) { /* error */ 
0710         ret = -1;
0711     }
0712 
0713     pcidma[0] |= 0xC; 
0714     return ret;
0715 
0716 }
0717 
0718 int grpci_dma_from_pci(
0719     unsigned int ahb_addr,
0720     unsigned int pci_addr,
0721     unsigned int len)
0722 {
0723     int ret = 0;
0724 
0725     pcidma[0] = 0x80;
0726     pcidma[1] = ahb_addr;
0727     pcidma[2] = pci_addr;
0728     pcidma[3] = len;
0729     pcidma[0] = 0x81;        
0730 
0731     while ( (pcidma[0] & 0x4) == 0)
0732         ;
0733 
0734     if (pcidma[0] & 0x8) { /* error */ 
0735         ret = -1;
0736     }
0737 
0738     pcidma[0] |= 0xC; 
0739     return ret;
0740 
0741 }