Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:57

0001 /*
0002  * pci.c :  this file contains basic PCI Io functions.
0003  *
0004  *  CopyRight (C) 1999 valette@crf.canon.fr
0005  *
0006  *  This code is heavilly inspired by the public specification of STREAM V2
0007  *  that can be found at :
0008  *
0009  *      <http://www.chorus.com/Documentation/index.html> by following
0010  *  the STREAM API Specification Document link.
0011  *
0012  *  The license and distribution terms for this file may be
0013  *  found in the file LICENSE in this distribution or at
0014  *  http://www.rtems.org/rtems/license.html.
0015  *
0016  *  Copyright 2004, 2008 Brookhaven National Laboratory and
0017  *                  Shuchen K. Feng, <feng1@bnl.gov>
0018  *
0019  *   - to be consistent with the original pci.c written by Eric Valette
0020  *   - added 2nd PCI support for discovery based PCI bridge (e.g. mvme5500/mvme6100)
0021  *   - added bus support for the expansion of PMCSpan as per request by Peter
0022  */
0023 #define PCI_MAIN
0024 
0025 #include <libcpu/io.h>
0026 #include <rtems/bspIo.h>        /* printk */
0027 
0028 #include <bsp/irq.h>
0029 #include <bsp/pci.h>
0030 #include <bsp/gtreg.h>
0031 #include <bsp/gtpcireg.h>
0032 #include <bsp.h>
0033 
0034 #include <stdio.h>
0035 #include <string.h>
0036 #include <inttypes.h>
0037 
0038 #define PCI_DEBUG 0
0039 #define PCI_PRINT 1
0040 
0041 /* allow for overriding these definitions */
0042 #ifndef PCI_CONFIG_ADDR
0043 #define PCI_CONFIG_ADDR         0xcf8
0044 #endif
0045 #ifndef PCI_CONFIG_DATA
0046 #define PCI_CONFIG_DATA         0xcfc
0047 #endif
0048 
0049 #ifndef PCI1_CONFIG_ADDR
0050 #define PCI1_CONFIG_ADDR        0xc78
0051 #endif
0052 #ifndef PCI1_CONFIG_DATA
0053 #define PCI1_CONFIG_DATA            0xc7c
0054 #endif
0055 
0056 #define HOSTBRIDGET_ERROR               0xf0000000
0057 
0058 #define GT64x60_PCI_CONFIG_ADDR         GT64x60_REG_BASE + PCI_CONFIG_ADDR
0059 #define GT64x60_PCI_CONFIG_DATA         GT64x60_REG_BASE + PCI_CONFIG_DATA
0060 
0061 #define GT64x60_PCI1_CONFIG_ADDR        GT64x60_REG_BASE + PCI1_CONFIG_ADDR
0062 #define GT64x60_PCI1_CONFIG_DATA        GT64x60_REG_BASE + PCI1_CONFIG_DATA
0063 
0064 static int      numPCIDevs=0;
0065 static DiscoveryChipVersion BSP_sysControllerVersion = 0;
0066 static BSP_VMEchipTypes BSP_VMEinterface = 0;
0067 static rtems_pci_config_t BSP_pci[2]={
0068   {(volatile unsigned char*) (GT64x60_PCI_CONFIG_ADDR),
0069    (volatile unsigned char*) (GT64x60_PCI_CONFIG_DATA),
0070    0 /* defined at BSP_pci_configuration */},
0071   {(volatile unsigned char*) (GT64x60_PCI1_CONFIG_ADDR),
0072    (volatile unsigned char*) (GT64x60_PCI1_CONFIG_DATA),
0073    0 /* defined at BSP_pci_configuration */}
0074 };
0075 
0076 /* Pack RegNum,FuncNum,DevNum,BusNum,and ConfigEnable for
0077  * PCI Configuration Address Register
0078  */
0079 #define pciConfigPack(bus,dev,func,offset)\
0080 ((offset&~3)<<24)|(PCI_DEVFN(dev,func)<<16)|(bus<<8)|0x80
0081 
0082 /*
0083  * Bit encode for PCI_CONFIG_HEADER_TYPE register
0084  */
0085 static unsigned char ucMaxPCIBus=0;
0086 
0087 /* Please note that PCI0 and PCI1 does not correlate with the busNum 0 and 1.
0088  */
0089 static int indirect_pci_read_config_byte(unsigned char bus,unsigned char dev,unsigned char func,
0090 unsigned char offset, uint8_t *val)
0091 {
0092   int n=0;
0093 
0094   if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
0095      bus-=BSP_MAX_PCI_BUS_ON_PCI0;
0096      n=1;
0097   }
0098 
0099   *val = 0xff;
0100   if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
0101 #if 0
0102   printk("addr %x, data %x, pack %x \n", BSP_pci[n].pci_config_addr),
0103     BSP_pci[n].config_data,pciConfigPack(bus,dev,func,offset));
0104 #endif
0105 
0106   out_be32((volatile uint32_t *) BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
0107   *val = in_8(BSP_pci[n].pci_config_data + (offset&3));
0108   return PCIBIOS_SUCCESSFUL;
0109 }
0110 
0111 static int indirect_pci_read_config_word(unsigned char bus, unsigned char dev,
0112 unsigned char func, unsigned char offset, uint16_t *val)
0113 {
0114   int n=0;
0115 
0116   if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
0117      bus-=BSP_MAX_PCI_BUS_ON_PCI0;
0118      n=1;
0119   }
0120 
0121   *val = 0xffff;
0122   if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
0123 #if 0
0124   printk("addr %x, data %x, pack %x \n", config_addr,
0125     config_data,pciConfigPack(bus,dev,func,offset));
0126 #endif
0127   out_be32((volatile uint32_t *) BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
0128   *val = in_le16((volatile uint16_t *) (BSP_pci[n].pci_config_data + (offset&2)));
0129   return PCIBIOS_SUCCESSFUL;
0130 }
0131 
0132 static int indirect_pci_read_config_dword(unsigned char bus, unsigned char dev,
0133 unsigned char func, unsigned char offset, uint32_t *val)
0134 {
0135   int n=0;
0136 
0137   if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
0138      bus-=BSP_MAX_PCI_BUS_ON_PCI0;
0139      n=1;
0140   }
0141 
0142   *val = 0xffffffff;
0143   if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
0144 
0145   out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
0146   *val = in_le32((volatile uint32_t *)BSP_pci[n].pci_config_data);
0147   return PCIBIOS_SUCCESSFUL;
0148 }
0149 
0150 static int indirect_pci_write_config_byte(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, uint8_t val)
0151 {
0152   int n=0;
0153 
0154   if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
0155      bus-=BSP_MAX_PCI_BUS_ON_PCI0;
0156      n=1;
0157   }
0158 
0159   if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
0160 
0161   out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
0162   out_8((volatile uint8_t *) (BSP_pci[n].pci_config_data + (offset&3)), val);
0163   return PCIBIOS_SUCCESSFUL;
0164 }
0165 
0166 static int indirect_pci_write_config_word(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, uint16_t val)
0167 {
0168   int n=0;
0169 
0170   if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
0171      bus-=BSP_MAX_PCI_BUS_ON_PCI0;
0172      n=1;
0173   }
0174 
0175   if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
0176 
0177   out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
0178   out_le16((volatile uint16_t *)(BSP_pci[n].pci_config_data + (offset&3)), val);
0179   return PCIBIOS_SUCCESSFUL;
0180 }
0181 
0182 static int indirect_pci_write_config_dword(unsigned char bus,unsigned char dev,unsigned char func, unsigned char offset, uint32_t val)
0183 {
0184   int n=0;
0185 
0186   if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
0187      bus-=BSP_MAX_PCI_BUS_ON_PCI0;
0188      n=1;
0189   }
0190 
0191   if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
0192 
0193   out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
0194   out_le32((volatile uint32_t *)BSP_pci[n].pci_config_data, val);
0195   return PCIBIOS_SUCCESSFUL;
0196 }
0197 
0198 const pci_config_access_functions pci_indirect_functions = {
0199     indirect_pci_read_config_byte,
0200     indirect_pci_read_config_word,
0201     indirect_pci_read_config_dword,
0202     indirect_pci_write_config_byte,
0203     indirect_pci_write_config_word,
0204     indirect_pci_write_config_dword
0205 };
0206 
0207 
0208 rtems_pci_config_t BSP_pci_configuration = {
0209            (volatile unsigned char*) (GT64x60_PCI_CONFIG_ADDR),
0210        (volatile unsigned char*) (GT64x60_PCI_CONFIG_DATA),
0211        &pci_indirect_functions};
0212 
0213 DiscoveryChipVersion BSP_getDiscoveryChipVersion(void)
0214 {
0215   return(BSP_sysControllerVersion);
0216 }
0217 
0218 BSP_VMEchipTypes BSP_getVMEchipType(void)
0219 {
0220   return(BSP_VMEinterface);
0221 }
0222 
0223 /*
0224  * This routine determines the maximum bus number in the system.
0225  * The PCI_SUBORDINATE_BUS is not supported in GT6426xAB. Thus,
0226  * it's not used.
0227  *
0228  */
0229 int pci_initialize(void)
0230 {
0231   int deviceFound;
0232   unsigned char ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs, data8;
0233   uint32_t ulHeader, ulClass, ulDeviceID;
0234 #if PCI_DEBUG
0235   uint32_t pcidata;
0236 #endif
0237 
0238   /*
0239    * Scan PCI0 and PCI1 buses
0240    */
0241   for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ucBusNumber++) {
0242     deviceFound=0;
0243     for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
0244       ucFnNumber = 0;
0245       pci_read_config_dword(ucBusNumber,
0246                 ucSlotNumber,
0247                 0,
0248                 PCI_VENDOR_ID,
0249                 &ulDeviceID);
0250 
0251       if( ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
0252         /* This slot is empty */
0253         continue;
0254       }
0255 
0256       if (++numPCIDevs > PCI_MAX_DEVICES) {
0257      rtems_panic("Too many PCI devices found; increase PCI_MAX_DEVICES in pci.h\n");
0258       }
0259 
0260       if (!deviceFound) deviceFound=1;
0261       switch(ulDeviceID) {
0262         case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT6426xAB<<16)):
0263           pci_read_config_byte(0,0,0,PCI_REVISION_ID, &data8);
0264           switch(data8) {
0265       case 0x10:
0266         BSP_sysControllerVersion = GT64260A;
0267 #if PCI_PRINT
0268         printk("Marvell GT64260A (Discovery I) hostbridge detected at bus%d slot%d\n",
0269                  ucBusNumber,ucSlotNumber);
0270 #endif
0271         break;
0272           case 0x20:
0273         BSP_sysControllerVersion = GT64260B;
0274 #if PCI_PRINT
0275         printk("Marvell GT64260B (Discovery I) hostbridge detected at bus%d slot%d\n",
0276                  ucBusNumber,ucSlotNumber);
0277 #endif
0278         break;
0279       default:
0280         printk("Undefined revsion of GT64260 chip\n");
0281             break;
0282           }
0283       break;
0284         case PCI_VENDOR_ID_TUNDRA:
0285 #if PCI_PRINT
0286           printk("TUNDRA PCI-VME bridge detected at bus%d slot%d\n",
0287                  ucBusNumber,ucSlotNumber);
0288 #endif
0289           break;
0290       case (PCI_VENDOR_ID_DEC+(PCI_DEVICE_ID_DEC_21150<<16)):
0291 #if PCI_PRINT
0292           printk("DEC21150 PCI-PCI bridge detected at bus%d slot%d\n",
0293                  ucBusNumber,ucSlotNumber);
0294 #endif
0295       break;
0296        default :
0297 #if PCI_PRINT
0298           printk("BSP unlisted vendor, Bus%d Slot%d DeviceID 0x%" PRIx32 "\n",
0299              ucBusNumber,ucSlotNumber, ulDeviceID);
0300 #endif
0301       /* Kate Feng : device not supported by BSP needs to remap the IRQ line on mvme5500/mvme6100 */
0302           pci_read_config_byte(ucBusNumber,ucSlotNumber,0,PCI_INTERRUPT_LINE,&data8);
0303       if (data8 < BSP_GPP_IRQ_LOWEST_OFFSET)  pci_write_config_byte(ucBusNumber,
0304          ucSlotNumber,0,PCI_INTERRUPT_LINE,BSP_GPP_IRQ_LOWEST_OFFSET+data8);
0305 
0306           break;
0307       }
0308 
0309 #if PCI_DEBUG
0310       pci_read_config_dword(ucBusNumber,
0311               ucSlotNumber,
0312               0,
0313               PCI_BASE_ADDRESS_0,
0314                           &data);
0315       printk("Bus%d BASE_ADDRESS_0 0x%x \n",ucBusNumber, data);
0316       pci_read_config_dword(ucBusNumber,
0317               ucSlotNumber,
0318               0,
0319               PCI_BASE_ADDRESS_1,
0320                           &data);
0321       printk("Bus%d BASE_ADDRESS_1 0x%x \n",ucBusNumber, data);
0322       pci_read_config_dword(ucBusNumber,
0323               ucSlotNumber,
0324               0,
0325               PCI_BASE_ADDRESS_2,
0326                           &data);
0327       printk("Bus%d BASE_ADDRESS_2 0x%x \n", ucBusNumber, data);
0328 
0329       pci_read_config_dword(ucBusNumber,
0330               ucSlotNumber,
0331               0,
0332               PCI_BASE_ADDRESS_3,
0333                           &data);
0334       printk("Bus%d BASE_ADDRESS_3 0x%x \n", ucBusNumber, data);
0335 
0336       pci_read_config_word(ucBusNumber,
0337               ucSlotNumber,
0338               0,
0339               PCI_INTERRUPT_LINE,
0340                           &sdata);
0341       printk("Bus%d INTERRUPT_LINE 0x%x \n", ucBusNumber, sdata);
0342 
0343       /* We always enable internal memory. */
0344       pci_read_config_dword(ucBusNumber,
0345               ucSlotNumber,
0346               0,
0347               PCI_MEM_BASE_ADDR,
0348               &pcidata);
0349       printk("Bus%d MEM_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
0350 
0351       /* We always enable internal IO. */
0352       pci_read_config_dword(ucBusNumber,
0353               ucSlotNumber,
0354               0,
0355               PCI_IO_BASE_ADDR,
0356               &pcidata);
0357       printk("Bus%d IO_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
0358 #endif
0359 
0360       pci_read_config_dword(ucBusNumber,
0361               ucSlotNumber,
0362               0,
0363               PCI_CACHE_LINE_SIZE,
0364               &ulHeader);
0365       if ((ulHeader>>16)&PCI_HEADER_TYPE_MULTI_FUNCTION)
0366          ucNumFuncs=PCI_MAX_FUNCTIONS;
0367       else
0368          ucNumFuncs=1;
0369 
0370 #if PCI_DEBUG
0371       printk("Bus%d Slot 0x%x HEADER/LAT/CACHE 0x%x \n",
0372              ucBusNumber, ucSlotNumber, ulHeader);
0373 #endif
0374 
0375       for (ucFnNumber=1;ucFnNumber<ucNumFuncs;ucFnNumber++) {
0376           pci_read_config_dword(ucBusNumber,
0377                   ucSlotNumber,
0378                   ucFnNumber,
0379                   PCI_VENDOR_ID,
0380                   &ulDeviceID);
0381           if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
0382          /* This slot/function is empty */
0383          continue;
0384           }
0385 
0386          /* This slot/function has a device fitted.*/
0387          pci_read_config_dword(ucBusNumber,
0388                   ucSlotNumber,
0389                   ucFnNumber,
0390                   PCI_CLASS_REVISION,
0391                   &ulClass);
0392 #if PCI_DEBUG
0393          printk("Bus%d Slot 0x%x Func %d classID 0x%x \n",ucBusNumber,ucSlotNumber,
0394              ucFnNumber, ulClass);
0395 #endif
0396 
0397       }
0398     }
0399     if (deviceFound) ucMaxPCIBus++;
0400   } /* for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ... */
0401 #if PCI_DEBUG
0402   printk("number of PCI buses: %d, numPCIDevs %d\n",
0403      pci_bus_count(), numPCIDevs);
0404 #endif
0405   pci_interface();
0406   return(0);
0407 }
0408 
0409 void FixupPCI( const struct _int_map *bspmap, int (*swizzler)(int,int) )
0410 {
0411 }
0412 
0413 /*
0414  * Return the number of PCI buses in the system
0415  */
0416 unsigned char pci_bus_count(void)
0417 {
0418   return(ucMaxPCIBus);
0419 }
0420