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 May 8, 2009 at 6:22:51 PM

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
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, 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
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(void);
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(void)
219{
220  return(BSP_sysControllerVersion);
221}
222
223BSP_VMEchipTypes BSP_getVMEchipType(void)
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(void)
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_TUNDRA:
290#if PCI_PRINT
291          printk("TUNDRA PCI-VME bridge detected at bus%d slot%d\n",
292                 ucBusNumber,ucSlotNumber);
293#endif
294          break;
295      case (PCI_VENDOR_ID_DEC+(PCI_DEVICE_ID_DEC_21150<<16)):
296#if PCI_PRINT
297          printk("DEC21150 PCI-PCI bridge detected at bus%d slot%d\n",
298                 ucBusNumber,ucSlotNumber);
299#endif
300          break;
301       default : 
302#if PCI_PRINT
303          printk("BSP unlisted vendor, Bus%d Slot%d DeviceID 0x%x \n",
304             ucBusNumber,ucSlotNumber, ulDeviceID);
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
311          break;
312      }
313
314#if PCI_DEBUG
315      pci_read_config_dword(ucBusNumber,
316                          ucSlotNumber,
317                          0,
318                          PCI_BASE_ADDRESS_0,
319                          &data);
320      printk("Bus%d BASE_ADDRESS_0 0x%x \n",ucBusNumber, data); 
321      pci_read_config_dword(ucBusNumber,
322                          ucSlotNumber,
323                          0,
324                          PCI_BASE_ADDRESS_1,
325                          &data);
326      printk("Bus%d BASE_ADDRESS_1 0x%x \n",ucBusNumber, data);
327      pci_read_config_dword(ucBusNumber,
328                          ucSlotNumber,
329                          0,
330                          PCI_BASE_ADDRESS_2,
331                          &data);
332      printk("Bus%d BASE_ADDRESS_2 0x%x \n", ucBusNumber, data);
333
334      pci_read_config_dword(ucBusNumber,
335                          ucSlotNumber,
336                          0,
337                          PCI_BASE_ADDRESS_3,
338                          &data);
339      printk("Bus%d BASE_ADDRESS_3 0x%x \n", ucBusNumber, data); 
340
341      pci_read_config_word(ucBusNumber,
342                          ucSlotNumber,
343                          0,
344                          PCI_INTERRUPT_LINE,
345                          &sdata);
346      printk("Bus%d INTERRUPT_LINE 0x%x \n", ucBusNumber, sdata); 
347
348      /* We always enable internal memory. */
349      pci_read_config_dword(ucBusNumber,
350                          ucSlotNumber,
351                          0,
352                          PCI_MEM_BASE_ADDR,
353                          &pcidata);
354      printk("Bus%d MEM_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
355
356      /* We always enable internal IO. */
357      pci_read_config_dword(ucBusNumber,
358                          ucSlotNumber,
359                          0,
360                          PCI_IO_BASE_ADDR,
361                          &pcidata);
362      printk("Bus%d IO_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
363#endif
364
365      pci_read_config_dword(ucBusNumber,
366                          ucSlotNumber,
367                          0,
368                          PCI_CACHE_LINE_SIZE,
369                          &ulHeader);
370      if ((ulHeader>>16)&PCI_MULTI_FUNCTION)
371         ucNumFuncs=PCI_MAX_FUNCTIONS;
372      else
373         ucNumFuncs=1;
374
375#if PCI_DEBUG
376      printk("Bus%d Slot 0x%x HEADER/LAT/CACHE 0x%x \n",
377             ucBusNumber, ucSlotNumber, ulHeader);   
378#endif
379
380      for (ucFnNumber=1;ucFnNumber<ucNumFuncs;ucFnNumber++) {
381          pci_read_config_dword(ucBusNumber,
382                                  ucSlotNumber,
383                                  ucFnNumber,
384                                  PCI_VENDOR_ID,
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.*/
392         pci_read_config_dword(ucBusNumber,
393                                  ucSlotNumber,
394                                  ucFnNumber,
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,
399             ucFnNumber, ulClass);
400#endif
401
402      }
403    }
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
410  pci_interface(); 
411  return(0);
412}
413
414void FixupPCI( struct _int_map *bspmap, int (*swizzler)(int,int) )
415{
416}
417
418/*
419 * Return the number of PCI buses in the system
420 */
421unsigned char pci_bus_count()
422{
423  return(ucMaxPCIBus);
424}
425
Note: See TracBrowser for help on using the repository browser.