source: rtems/c/src/lib/libbsp/powerpc/mvme5500/pci/pci.c @ cf599996

4.9
Last change on this file since cf599996 was cf599996, checked in by Joel Sherrill <joel.sherrill@…>, on 05/08/09 at 18:22:51

2009-05-08 Kate Feng <feng1@…>

PR1395/bsps

  • Updated the changes from RTEMS-4.8.0, which were made since Oct. 2007.
  • network/if_1GHz/if_wm.c: fixed some bugs in the 1GHz driver.
  • pci/pci_interface.c: + Enabled PCI "Read", "Read Line", and "Read Multiple" + Agressive Prefetch to improve the performance of the PCI based

applications (e.g. 1GHz NIC).

  • irq/BSP_irq.c : Replaced the irq/irq.c, and used GT_GPP_Value register to monitor the cause of the level sensitive interrupts. This unique solution solves various bugs in the 1GHz network drivers Fixed bugs in compute_pic_masks_from_prio()
  • pci/pci.c : Updated it to be consistent with the original pci.c
  • written by Eric Valette. There is no change in its function.
  • irq/irq_init.c : set defaultIrq->next_handler to be 0
  • for BSP_SHARED_HANDLER_SUPPORT.
  • Property mode set to 100644
File size: 11.8 KB
RevLine 
[7be6ad9]1/*
2 * pci.c :  this file contains basic PCI Io functions.
3 *
4 *  CopyRight (C) 1999 valette@crf.canon.fr
5 *
6 *  This code is heavilly inspired by the public specification of STREAM V2
7 *  that can be found at :
8 *
9 *      <http://www.chorus.com/Documentation/index.html> by following
10 *  the STREAM API Specification Document link.
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
[54cb48f]14 *  http://www.rtems.com/rtems/license.html.
[7be6ad9]15 *
[cf599996]16 *  pci.c,v 1.2 2002/05/14 17:10:16 joel Exp
[16fa78e]17 *
[cf599996]18 *  Copyright 2004, 2008 Brookhaven National Laboratory and
19 *                  Shuchen K. Feng, <feng1@bnl.gov>
20 *   
21 *   - to be consistent with the original pci.c written by Eric Valette
22 *   - added 2nd PCI support for discovery based PCI bridge (e.g. mvme5500/mvme6100)
23 *   - added bus support for the expansion of PMCSpan as per request by Peter
[7be6ad9]24 */
25#define PCI_MAIN
26
27#include <libcpu/io.h>
28#include <rtems/bspIo.h>            /* printk */
29
[cf599996]30#include <bsp/irq.h>
[7be6ad9]31#include <bsp/pci.h>
32#include <bsp/gtreg.h>
33#include <bsp/gtpcireg.h>
[cf599996]34#include <bsp.h>
[7be6ad9]35
36#include <stdio.h>
37#include <string.h>
38
[ee732739]39#define PCI_DEBUG 0
[cf599996]40#define PCI_PRINT 1
[54cb48f]41
42/* allow for overriding these definitions */
43#ifndef PCI_CONFIG_ADDR
44#define PCI_CONFIG_ADDR                 0xcf8
45#endif
46#ifndef PCI_CONFIG_DATA
47#define PCI_CONFIG_DATA                 0xcfc
48#endif
49
50#ifndef PCI1_CONFIG_ADDR
51#define PCI1_CONFIG_ADDR                0xc78
52#endif
53#ifndef PCI1_CONFIG_DATA
54#define PCI1_CONFIG_DATA                0xc7c
55#endif
[7be6ad9]56
57#define PCI_INVALID_VENDORDEVICEID      0xffffffff
58#define PCI_MULTI_FUNCTION              0x80
59#define HOSTBRIDGET_ERROR               0xf0000000
60
[cf599996]61#define GT64x60_PCI_CONFIG_ADDR         GT64x60_REG_BASE + PCI_CONFIG_ADDR
62#define GT64x60_PCI_CONFIG_DATA         GT64x60_REG_BASE + PCI_CONFIG_DATA
63
64#define GT64x60_PCI1_CONFIG_ADDR        GT64x60_REG_BASE + PCI1_CONFIG_ADDR
65#define GT64x60_PCI1_CONFIG_DATA        GT64x60_REG_BASE + PCI1_CONFIG_DATA
66
67static int      numPCIDevs=0;
68static DiscoveryChipVersion BSP_sysControllerVersion = 0;
69static BSP_VMEchipTypes BSP_VMEinterface = 0;
70static pci_config BSP_pci[2]={
71  {(volatile unsigned char*) (GT64x60_PCI_CONFIG_ADDR),
72   (volatile unsigned char*) (GT64x60_PCI_CONFIG_DATA),
73   0 /* defined at BSP_pci_configuration */},
74  {(volatile unsigned char*) (GT64x60_PCI1_CONFIG_ADDR),
75   (volatile unsigned char*) (GT64x60_PCI1_CONFIG_DATA),
76   0 /* defined at BSP_pci_configuration */}
77};
[7be6ad9]78
[6771a9e7]79extern void pci_interface(void);
[7be6ad9]80
81/* Pack RegNum,FuncNum,DevNum,BusNum,and ConfigEnable for
82 * PCI Configuration Address Register
83 */
84#define pciConfigPack(bus,dev,func,offset)\
[cf599996]85((offset&~3)<<24)|(PCI_DEVFN(dev,func)<<16)|(bus<<8)|0x80
[7be6ad9]86
87/*
88 * Bit encode for PCI_CONFIG_HEADER_TYPE register
89 */
[ea6c5d8]90unsigned char ucMaxPCIBus=0;
[7be6ad9]91
92/* Please note that PCI0 and PCI1 does not correlate with the busNum 0 and 1.
93 */
[cf599996]94static int indirect_pci_read_config_byte(unsigned char bus,unsigned char dev,unsigned char func,
[ee732739]95unsigned char offset,unsigned char *val)
[7be6ad9]96{
[cf599996]97  int n=0;
[54cb48f]98
99  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
100     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
[cf599996]101     n=1;
[54cb48f]102  }
[cf599996]103
[7be6ad9]104  *val = 0xff;
105  if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
[54cb48f]106#if 0
[cf599996]107  printk("addr %x, data %x, pack %x \n", BSP_pci[n].pci_config_addr),
108    BSP_pci[n].config_data,pciConfigPack(bus,dev,func,offset));
[54cb48f]109#endif
[cf599996]110
111  out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
112  *val = in_8(BSP_pci[n].pci_config_data + (offset&3));
[7be6ad9]113  return PCIBIOS_SUCCESSFUL;
114}
115
[cf599996]116static int indirect_pci_read_config_word(unsigned char bus, unsigned char dev,
[ee732739]117unsigned char func, unsigned char offset, unsigned short *val)
[7be6ad9]118{
[cf599996]119  int n=0;
[54cb48f]120
121  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
122     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
[cf599996]123     n=1;
[54cb48f]124  }
125
[7be6ad9]126  *val = 0xffff;
127  if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
[54cb48f]128#if 0
129  printk("addr %x, data %x, pack %x \n", config_addr,
130    config_data,pciConfigPack(bus,dev,func,offset));
131#endif
[cf599996]132  out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
133  *val = in_le16(BSP_pci[n].pci_config_data + (offset&2));
[7be6ad9]134  return PCIBIOS_SUCCESSFUL;
135}
136
[cf599996]137static int indirect_pci_read_config_dword(unsigned char bus, unsigned char dev,
[ee732739]138unsigned char func, unsigned char offset, unsigned int *val)
[7be6ad9]139{
[cf599996]140  int n=0;
[54cb48f]141
142  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
143     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
[cf599996]144     n=1;
[54cb48f]145  }
146
[7be6ad9]147  *val = 0xffffffff;
148  if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
[cf599996]149
150  out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
151  *val = in_le32(BSP_pci[n].pci_config_data);
[7be6ad9]152  return PCIBIOS_SUCCESSFUL;
153}
154
[cf599996]155static int indirect_pci_write_config_byte(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, unsigned char val)
[7be6ad9]156{
[cf599996]157  int n=0;
[54cb48f]158
159  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
160     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
[cf599996]161     n=1;
[54cb48f]162  }
163
[7be6ad9]164  if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
165
[cf599996]166  out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
167  out_8(BSP_pci[n].pci_config_data + (offset&3), val);
[7be6ad9]168  return PCIBIOS_SUCCESSFUL;
169}
170
[cf599996]171static int indirect_pci_write_config_word(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, unsigned short val)
[7be6ad9]172{
[cf599996]173  int n=0;
[54cb48f]174
175  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
176     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
[cf599996]177     n=1;
[54cb48f]178  }
179
[7be6ad9]180  if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
[cf599996]181
182  out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
183  out_le16(BSP_pci[n].pci_config_data + (offset&3), val);
[7be6ad9]184  return PCIBIOS_SUCCESSFUL;
185}
186
[cf599996]187static int indirect_pci_write_config_dword(unsigned char bus,unsigned char dev,unsigned char func, unsigned char offset, unsigned int val)
[7be6ad9]188{
[cf599996]189  int n=0;
[54cb48f]190
191  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
192     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
[cf599996]193     n=1;
[54cb48f]194  }
195
[7be6ad9]196  if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
[cf599996]197
198  out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
199  out_le32(BSP_pci[n].pci_config_data, val);
[7be6ad9]200  return PCIBIOS_SUCCESSFUL;
201}
202
[cf599996]203const pci_config_access_functions pci_indirect_functions = {
204        indirect_pci_read_config_byte,
205        indirect_pci_read_config_word,
206        indirect_pci_read_config_dword,
207        indirect_pci_write_config_byte,
208        indirect_pci_write_config_word,
209        indirect_pci_write_config_dword
[54cb48f]210};
[7be6ad9]211
212
[cf599996]213pci_config BSP_pci_configuration = {
214           (volatile unsigned char*) (GT64x60_PCI_CONFIG_ADDR),
215           (volatile unsigned char*) (GT64x60_PCI_CONFIG_DATA),
216           &pci_indirect_functions};
217
218DiscoveryChipVersion BSP_getDiscoveryChipVersion(void)
219{
220  return(BSP_sysControllerVersion);
221}
222
223BSP_VMEchipTypes BSP_getVMEchipType(void)
224{
225  return(BSP_VMEinterface);
226}
[7be6ad9]227
228/*
[54cb48f]229 * This routine determines the maximum bus number in the system.
230 * The PCI_SUBORDINATE_BUS is not supported in GT6426xAB. Thus,
231 * it's not used.
232 *
[7be6ad9]233 */
[6771a9e7]234int pci_initialize(void)
[7be6ad9]235{
[54cb48f]236  int deviceFound;
[cf599996]237  unsigned char ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs, data8;
238  uint32_t ulHeader, ulClass, ulDeviceID;
239#if PCI_DEBUG
240  uint32_t pcidata;
241#endif
[7be6ad9]242
243  /*
[54cb48f]244   * Scan PCI0 and PCI1 buses
[7be6ad9]245   */
[54cb48f]246  for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ucBusNumber++) {
247    deviceFound=0;
[7be6ad9]248    for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
249      ucFnNumber = 0;
[54cb48f]250      pci_read_config_dword(ucBusNumber,
[7be6ad9]251                                ucSlotNumber,
252                                0,
[54cb48f]253                                PCI_VENDOR_ID,
[7be6ad9]254                                &ulDeviceID);
255
256      if( ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
257        /* This slot is empty */
258        continue;
259      }
260
[54cb48f]261      if (++numPCIDevs > PCI_MAX_DEVICES) {
262         BSP_panic("Too many PCI devices found; increase PCI_MAX_DEVICES in pci.h\n");
[7be6ad9]263      }
264
[54cb48f]265      if (!deviceFound) deviceFound=1;
[7be6ad9]266      switch(ulDeviceID) {
267        case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT6426xAB<<16)):
[cf599996]268          pci_read_config_byte(0,0,0,PCI_REVISION_ID, &data8);
269          switch(data8) {
270          case 0x10:
271            BSP_sysControllerVersion = GT64260A;
[7be6ad9]272#if PCI_PRINT
[cf599996]273            printk("Marvell GT64260A (Discovery I) hostbridge detected at bus%d slot%d\n",
[54cb48f]274                 ucBusNumber,ucSlotNumber);
[7be6ad9]275#endif
[cf599996]276            break;
277          case 0x20:
278            BSP_sysControllerVersion = GT64260B;
[7be6ad9]279#if PCI_PRINT
[cf599996]280            printk("Marvell GT64260B (Discovery I) hostbridge detected at bus%d slot%d\n",
[54cb48f]281                 ucBusNumber,ucSlotNumber);
[7be6ad9]282#endif
[cf599996]283            break;
284          default:
285            printk("Undefined revsion of GT64260 chip\n");
286            break;
287          }
288          break;
[7be6ad9]289        case PCI_VENDOR_ID_TUNDRA:
290#if PCI_PRINT
[54cb48f]291          printk("TUNDRA PCI-VME bridge detected at bus%d slot%d\n",
292                 ucBusNumber,ucSlotNumber);
[7be6ad9]293#endif
294          break;
[54cb48f]295      case (PCI_VENDOR_ID_DEC+(PCI_DEVICE_ID_DEC_21150<<16)):
[cf599996]296#if PCI_PRINT
[54cb48f]297          printk("DEC21150 PCI-PCI bridge detected at bus%d slot%d\n",
298                 ucBusNumber,ucSlotNumber);
[7be6ad9]299#endif
[54cb48f]300          break;
301       default :
[cf599996]302#if PCI_PRINT
[54cb48f]303          printk("BSP unlisted vendor, Bus%d Slot%d DeviceID 0x%x \n",
304             ucBusNumber,ucSlotNumber, ulDeviceID);
[cf599996]305#endif
306          /* Kate Feng : device not supported by BSP needs to remap the IRQ line on mvme5500/mvme6100 */
307          pci_read_config_byte(ucBusNumber,ucSlotNumber,0,PCI_INTERRUPT_LINE,&data8);
308          if (data8 < BSP_GPP_IRQ_LOWEST_OFFSET)  pci_write_config_byte(ucBusNumber,
309             ucSlotNumber,0,PCI_INTERRUPT_LINE,BSP_GPP_IRQ_LOWEST_OFFSET+data8);
310
[7be6ad9]311          break;
312      }
[54cb48f]313
[7be6ad9]314#if PCI_DEBUG
[54cb48f]315      pci_read_config_dword(ucBusNumber,
[7be6ad9]316                          ucSlotNumber,
317                          0,
[54cb48f]318                          PCI_BASE_ADDRESS_0,
[7be6ad9]319                          &data);
[54cb48f]320      printk("Bus%d BASE_ADDRESS_0 0x%x \n",ucBusNumber, data); 
321      pci_read_config_dword(ucBusNumber,
[7be6ad9]322                          ucSlotNumber,
323                          0,
[54cb48f]324                          PCI_BASE_ADDRESS_1,
[7be6ad9]325                          &data);
[54cb48f]326      printk("Bus%d BASE_ADDRESS_1 0x%x \n",ucBusNumber, data);
327      pci_read_config_dword(ucBusNumber,
[7be6ad9]328                          ucSlotNumber,
329                          0,
[54cb48f]330                          PCI_BASE_ADDRESS_2,
[7be6ad9]331                          &data);
[54cb48f]332      printk("Bus%d BASE_ADDRESS_2 0x%x \n", ucBusNumber, data);
[7be6ad9]333
[54cb48f]334      pci_read_config_dword(ucBusNumber,
[7be6ad9]335                          ucSlotNumber,
336                          0,
[54cb48f]337                          PCI_BASE_ADDRESS_3,
[7be6ad9]338                          &data);
[54cb48f]339      printk("Bus%d BASE_ADDRESS_3 0x%x \n", ucBusNumber, data); 
[7be6ad9]340
[54cb48f]341      pci_read_config_word(ucBusNumber,
[7be6ad9]342                          ucSlotNumber,
343                          0,
[54cb48f]344                          PCI_INTERRUPT_LINE,
[7be6ad9]345                          &sdata);
[54cb48f]346      printk("Bus%d INTERRUPT_LINE 0x%x \n", ucBusNumber, sdata); 
[7be6ad9]347
348      /* We always enable internal memory. */
[54cb48f]349      pci_read_config_dword(ucBusNumber,
[7be6ad9]350                          ucSlotNumber,
351                          0,
[54cb48f]352                          PCI_MEM_BASE_ADDR,
[7be6ad9]353                          &pcidata);
[54cb48f]354      printk("Bus%d MEM_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
[7be6ad9]355
356      /* We always enable internal IO. */
[54cb48f]357      pci_read_config_dword(ucBusNumber,
[7be6ad9]358                          ucSlotNumber,
359                          0,
[54cb48f]360                          PCI_IO_BASE_ADDR,
[7be6ad9]361                          &pcidata);
[54cb48f]362      printk("Bus%d IO_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
[7be6ad9]363#endif
364
[54cb48f]365      pci_read_config_dword(ucBusNumber,
[7be6ad9]366                          ucSlotNumber,
367                          0,
[54cb48f]368                          PCI_CACHE_LINE_SIZE,
[7be6ad9]369                          &ulHeader);
370      if ((ulHeader>>16)&PCI_MULTI_FUNCTION)
371         ucNumFuncs=PCI_MAX_FUNCTIONS;
372      else
373         ucNumFuncs=1;
374
375#if PCI_DEBUG
[54cb48f]376      printk("Bus%d Slot 0x%x HEADER/LAT/CACHE 0x%x \n",
377             ucBusNumber, ucSlotNumber, ulHeader);   
378#endif
[7be6ad9]379
380      for (ucFnNumber=1;ucFnNumber<ucNumFuncs;ucFnNumber++) {
[54cb48f]381          pci_read_config_dword(ucBusNumber,
[7be6ad9]382                                  ucSlotNumber,
383                                  ucFnNumber,
[54cb48f]384                                  PCI_VENDOR_ID,
[7be6ad9]385                                  &ulDeviceID);
386          if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
387             /* This slot/function is empty */
388             continue;
389          }
390
391         /* This slot/function has a device fitted.*/
[54cb48f]392         pci_read_config_dword(ucBusNumber,
[7be6ad9]393                                  ucSlotNumber,
394                                  ucFnNumber,
[54cb48f]395                                  PCI_CLASS_REVISION,
396                                  &ulClass);
397#if PCI_DEBUG   
398         printk("Bus%d Slot 0x%x Func %d classID 0x%x \n",ucBusNumber,ucSlotNumber,
[7be6ad9]399             ucFnNumber, ulClass);
[54cb48f]400#endif
[7be6ad9]401
402      }
403    }
[54cb48f]404    if (deviceFound) ucMaxPCIBus++;
405  } /* for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ... */
406#if PCI_DEBUG
407  printk("number of PCI buses: %d, numPCIDevs %d\n",
408         pci_bus_count(), numPCIDevs);
409#endif
[cf599996]410  pci_interface();
[54cb48f]411  return(0);
412}
[3bfb6ef]413
[54cb48f]414void FixupPCI( struct _int_map *bspmap, int (*swizzler)(int,int) )
415{
[7be6ad9]416}
417
418/*
419 * Return the number of PCI buses in the system
420 */
[4cbb57da]421unsigned char pci_bus_count()
[7be6ad9]422{
423  return(ucMaxPCIBus);
424}
425
Note: See TracBrowser for help on using the repository browser.