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

4.8
Last change on this file since d7196bf was d7196bf, checked in by Joel Sherrill <joel.sherrill@…>, on 05/04/09 at 20:06:43

2009-04-20 Kate Feng <feng1@…>

1396/bsps

  • 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.
  • network/if_1GHz/if_wm.c : fixed some bugs in the 1GHz driver.
  • irq/BSP_irq.c : added supports for shared IRQ.
  • 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()
  • Property mode set to 100644
File size: 12.9 KB
Line 
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
14 *  http://www.rtems.com/rtems/license.html.
15 *
16 *  pci.c,v 1.2 2002/05/14 17:10:16 joel Exp
17 *
18 *  Copyright 2004, Brookhaven National Laboratory and
19 *                  Shuchen K. Feng, <feng1@bnl.gov>, 2004, 2008
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
24 */
25#define PCI_MAIN
26
27#include <libcpu/io.h>
28#include <rtems/bspIo.h>            /* printk */
29
30#include <bsp/irq.h>
31#include <bsp/pci.h>
32#include <bsp/gtreg.h>
33#include <bsp/gtpcireg.h>
34#include <bsp.h>
35
36#include <stdio.h>
37#include <string.h>
38
39#define PCI_DEBUG 0
40#define PCI_PRINT 1
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
56
57#define PCI_INVALID_VENDORDEVICEID      0xffffffff
58#define PCI_MULTI_FUNCTION              0x80
59#define HOSTBRIDGET_ERROR               0xf0000000
60
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};
78
79extern void pci_interface();
80
81/* Pack RegNum,FuncNum,DevNum,BusNum,and ConfigEnable for
82 * PCI Configuration Address Register
83 */
84#define pciConfigPack(bus,dev,func,offset)\
85((offset&~3)<<24)|(PCI_DEVFN(dev,func)<<16)|(bus<<8)|0x80
86
87/*
88 * Bit encode for PCI_CONFIG_HEADER_TYPE register
89 */
90unsigned char ucMaxPCIBus=0;
91
92/* Please note that PCI0 and PCI1 does not correlate with the busNum 0 and 1.
93 */
94static int indirect_pci_read_config_byte(unsigned char bus,unsigned char dev,unsigned char func,
95unsigned char offset,unsigned char *val)
96{
97  int n=0;
98
99  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
100     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
101     n=1;
102  }
103
104  *val = 0xff;
105  if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
106#if 0
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));
109#endif
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));
113  return PCIBIOS_SUCCESSFUL;
114}
115
116static int indirect_pci_read_config_word(unsigned char bus, unsigned char dev,
117unsigned char func, unsigned char offset, unsigned short *val)
118{
119  int n=0;
120
121  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
122     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
123     n=1;
124  }
125
126  *val = 0xffff;
127  if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
128#if 0
129  printk("addr %x, data %x, pack %x \n", config_addr,
130    config_data,pciConfigPack(bus,dev,func,offset));
131#endif
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));
134  return PCIBIOS_SUCCESSFUL;
135}
136
137static int indirect_pci_read_config_dword(unsigned char bus, unsigned char dev,
138unsigned char func, unsigned char offset, unsigned int *val)
139{
140  int n=0;
141
142  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
143     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
144     n=1;
145  }
146
147  *val = 0xffffffff;
148  if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
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);
152  return PCIBIOS_SUCCESSFUL;
153}
154
155static int indirect_pci_write_config_byte(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, unsigned char val)
156{
157  int n=0;
158
159  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
160     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
161     n=1;
162  }
163
164  if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
165
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);
168  return PCIBIOS_SUCCESSFUL;
169}
170
171static int indirect_pci_write_config_word(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, unsigned short val)
172{
173  int n=0;
174
175  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
176     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
177     n=1;
178  }
179
180  if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
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);
184  return PCIBIOS_SUCCESSFUL;
185}
186
187static int indirect_pci_write_config_dword(unsigned char bus,unsigned char dev,unsigned char func, unsigned char offset, unsigned int val)
188{
189  int n=0;
190
191  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
192     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
193     n=1;
194  }
195
196  if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
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);
200  return PCIBIOS_SUCCESSFUL;
201}
202
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
210};
211
212
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()
219{
220  return(BSP_sysControllerVersion);
221}
222
223BSP_VMEchipTypes BSP_getVMEchipType()
224{
225  return(BSP_VMEinterface);
226}
227
228/*
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 *
233 */
234int pci_initialize()
235{
236  int deviceFound;
237  unsigned char ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs, data8;
238  uint32_t ulHeader, ulClass, ulDeviceID;
239#if PCI_DEBUG
240  uint32_t pcidata;
241#endif
242
243  /*
244   * Scan PCI0 and PCI1 buses
245   */
246  for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ucBusNumber++) {
247    deviceFound=0;
248    for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
249      ucFnNumber = 0;
250      pci_read_config_dword(ucBusNumber,
251                                ucSlotNumber,
252                                0,
253                                PCI_VENDOR_ID,
254                                &ulDeviceID);
255
256      if( ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
257        /* This slot is empty */
258        continue;
259      }
260
261      if (++numPCIDevs > PCI_MAX_DEVICES) {
262         BSP_panic("Too many PCI devices found; increase PCI_MAX_DEVICES in pci.h\n");
263      }
264
265      if (!deviceFound) deviceFound=1;
266      switch(ulDeviceID) {
267        case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT6426xAB<<16)):
268          pci_read_config_byte(0,0,0,PCI_REVISION_ID, &data8);
269          switch(data8) {
270          case 0x10:
271            BSP_sysControllerVersion = GT64260A;
272#if PCI_PRINT
273            printk("Marvell GT64260A (Discovery I) hostbridge detected at bus%d slot%d\n",
274                 ucBusNumber,ucSlotNumber);
275#endif
276            break;
277          case 0x20:
278            BSP_sysControllerVersion = GT64260B;
279#if PCI_PRINT
280            printk("Marvell GT64260B (Discovery I) hostbridge detected at bus%d slot%d\n",
281                 ucBusNumber,ucSlotNumber);
282#endif
283            break;
284          default:
285            printk("Undefined revsion of GT64260 chip\n");
286            break;
287          }
288          break;
289        case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT64360<<16)):
290          BSP_sysControllerVersion = MV64360;
291#if PCI_PRINT
292          printk("Marvell GT64360 (Discovery II) hostbridge detected at bus%d slot%d\n",
293                 ucBusNumber,ucSlotNumber);
294#endif
295          break;
296        case (PCI_VENDOR_ID_PLX2+(PCI_DEVICE_ID_PLX2_PCI6154_HB2<<16)):
297          BSP_VMEinterface = UNIVERSE2;
298#if PCI_PRINT
299          printk("PLX PCI6154 PCI-PCI bridge detected at bus%d slot%d\n",
300                 ucBusNumber,ucSlotNumber);
301#endif
302          break;
303        case PCI_VENDOR_ID_TUNDRA:
304#if PCI_PRINT
305          printk("TUNDRA PCI-VME bridge detected at bus%d slot%d\n",
306                 ucBusNumber,ucSlotNumber);
307#endif
308          break;
309        case (PCI_VENDOR_ID_TUNDRA+(PCI_DEVICE_ID_TUNDRA_TSI148<<16)):
310          BSP_VMEinterface = TSI148;
311#if PCI_PRINT
312          printk("TUNDRA Tsi148 PCI/X-VME bridge detected at bus%d slot%d\n",
313                 ucBusNumber,ucSlotNumber);
314#endif
315          break;
316      case (PCI_VENDOR_ID_INTEL+(PCI_DEVICE_INTEL_82544EI_COPPER<<16)):
317#if PCI_PRINT
318          printk("INTEL 82544EI COPPER network controller detected at bus%d slot%d\n",
319                 ucBusNumber,ucSlotNumber);
320#endif
321          break;
322      case (PCI_VENDOR_ID_DEC+(PCI_DEVICE_ID_DEC_21150<<16)):
323#if PCI_PRINT
324          printk("DEC21150 PCI-PCI bridge detected at bus%d slot%d\n",
325                 ucBusNumber,ucSlotNumber);
326#endif
327          break;
328       default :
329#if PCI_PRINT
330          printk("BSP unlisted vendor, Bus%d Slot%d DeviceID 0x%x \n",
331             ucBusNumber,ucSlotNumber, ulDeviceID);
332#endif
333          /* Kate Feng : device not supported by BSP needs to remap the IRQ line on mvme5500/mvme6100 */
334          pci_read_config_byte(ucBusNumber,ucSlotNumber,0,PCI_INTERRUPT_LINE,&data8);
335          if (data8 < BSP_GPP_IRQ_LOWEST_OFFSET)  pci_write_config_byte(ucBusNumber,
336             ucSlotNumber,0,PCI_INTERRUPT_LINE,BSP_GPP_IRQ_LOWEST_OFFSET+data8);
337
338          break;
339      }
340
341#if PCI_DEBUG
342      pci_read_config_dword(ucBusNumber,
343                          ucSlotNumber,
344                          0,
345                          PCI_BASE_ADDRESS_0,
346                          &data);
347      printk("Bus%d BASE_ADDRESS_0 0x%x \n",ucBusNumber, data); 
348      pci_read_config_dword(ucBusNumber,
349                          ucSlotNumber,
350                          0,
351                          PCI_BASE_ADDRESS_1,
352                          &data);
353      printk("Bus%d BASE_ADDRESS_1 0x%x \n",ucBusNumber, data);
354      pci_read_config_dword(ucBusNumber,
355                          ucSlotNumber,
356                          0,
357                          PCI_BASE_ADDRESS_2,
358                          &data);
359      printk("Bus%d BASE_ADDRESS_2 0x%x \n", ucBusNumber, data);
360
361      pci_read_config_dword(ucBusNumber,
362                          ucSlotNumber,
363                          0,
364                          PCI_BASE_ADDRESS_3,
365                          &data);
366      printk("Bus%d BASE_ADDRESS_3 0x%x \n", ucBusNumber, data); 
367
368      pci_read_config_word(ucBusNumber,
369                          ucSlotNumber,
370                          0,
371                          PCI_INTERRUPT_LINE,
372                          &sdata);
373      printk("Bus%d INTERRUPT_LINE 0x%x \n", ucBusNumber, sdata); 
374
375      /* We always enable internal memory. */
376      pci_read_config_dword(ucBusNumber,
377                          ucSlotNumber,
378                          0,
379                          PCI_MEM_BASE_ADDR,
380                          &pcidata);
381      printk("Bus%d MEM_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
382
383      /* We always enable internal IO. */
384      pci_read_config_dword(ucBusNumber,
385                          ucSlotNumber,
386                          0,
387                          PCI_IO_BASE_ADDR,
388                          &pcidata);
389      printk("Bus%d IO_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
390#endif
391
392      pci_read_config_dword(ucBusNumber,
393                          ucSlotNumber,
394                          0,
395                          PCI_CACHE_LINE_SIZE,
396                          &ulHeader);
397      if ((ulHeader>>16)&PCI_MULTI_FUNCTION)
398         ucNumFuncs=PCI_MAX_FUNCTIONS;
399      else
400         ucNumFuncs=1;
401
402#if PCI_DEBUG
403      printk("Bus%d Slot 0x%x HEADER/LAT/CACHE 0x%x \n",
404             ucBusNumber, ucSlotNumber, ulHeader);   
405#endif
406
407      for (ucFnNumber=1;ucFnNumber<ucNumFuncs;ucFnNumber++) {
408          pci_read_config_dword(ucBusNumber,
409                                  ucSlotNumber,
410                                  ucFnNumber,
411                                  PCI_VENDOR_ID,
412                                  &ulDeviceID);
413          if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
414             /* This slot/function is empty */
415             continue;
416          }
417
418         /* This slot/function has a device fitted.*/
419         pci_read_config_dword(ucBusNumber,
420                                  ucSlotNumber,
421                                  ucFnNumber,
422                                  PCI_CLASS_REVISION,
423                                  &ulClass);
424#if PCI_DEBUG   
425         printk("Bus%d Slot 0x%x Func %d classID 0x%x \n",ucBusNumber,ucSlotNumber,
426             ucFnNumber, ulClass);
427#endif
428
429      }
430    }
431    if (deviceFound) ucMaxPCIBus++;
432  } /* for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ... */
433#if PCI_DEBUG
434  printk("number of PCI buses: %d, numPCIDevs %d\n",
435         pci_bus_count(), numPCIDevs);
436#endif
437  pci_interface(BSP_sysControllerVersion);
438  return(0);
439}
440
441void FixupPCI( struct _int_map *bspmap, int (*swizzler)(int,int) )
442{
443}
444
445/*
446 * Return the number of PCI buses in the system
447 */
448unsigned char pci_bus_count()
449{
450  return(ucMaxPCIBus);
451}
452
Note: See TracBrowser for help on using the repository browser.