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

4.104.114.84.95
Last change on this file since 54cb48f was 54cb48f, checked in by Jennifer Averett <Jennifer.Averett@…>, on 05/12/05 at 18:25:29

2005-05-12 Jennifer Averett <jennifer.averett@…>

  • README.VME, include/bsp.h, irq/irq.h, network/GT64260eth.c, pci/detect_host_bridge.c, pci/gtpcireg.h, pci/pci.c, pci/pci.h, pci/pci_interface.c, pci/pcifinddevice.c: Submitted by Kate Feng <feng1@…> as RTEMS-MVME5500 BSP v1.1 release. Modifications made to merge this release with the current tree.
  • Property mode set to 100644
File size: 13.0 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
20 *   - modified and added support for MVME5500 board
21 *   - added 2nd PCI support for the mvme5500/GT64260 PCI bridge
22 *   - added bus support for the expansion of PMCSpan, thanks to
23 *     Peter Dufault (dufault@hda.com) for inputs.
24 */
25#define PCI_MAIN
26
27#include <libcpu/io.h>
28#include <rtems/bspIo.h>            /* printk */
29
30#include <bsp/pci.h>
31#include <bsp/gtreg.h>
32#include <bsp/gtpcireg.h>
33
34#include <stdio.h>
35#include <string.h>
36
37#define PCI_DEBUG 0
38#define PCI_PRINT 0
39
40/* allow for overriding these definitions */
41#ifndef PCI_CONFIG_ADDR
42#define PCI_CONFIG_ADDR                 0xcf8
43#endif
44#ifndef PCI_CONFIG_DATA
45#define PCI_CONFIG_DATA                 0xcfc
46#endif
47
48#ifndef PCI1_CONFIG_ADDR
49#define PCI1_CONFIG_ADDR                0xc78
50#endif
51#ifndef PCI1_CONFIG_DATA
52#define PCI1_CONFIG_DATA                0xc7c
53#endif
54
55#define PCI_INVALID_VENDORDEVICEID      0xffffffff
56#define PCI_MULTI_FUNCTION              0x80
57#define HOSTBRIDGET_ERROR               0xf0000000
58
59/* define a shortcut */
60#define pci     BSP_pci_configuration
61
62typedef unsigned char unchar;
63static int                numPCIDevs=0;
64extern void pci_interface();
65
66/* Pack RegNum,FuncNum,DevNum,BusNum,and ConfigEnable for
67 * PCI Configuration Address Register
68 */
69#define pciConfigPack(bus,dev,func,offset)\
70(((func&7)<<8)|((dev&0x1f )<<11)|(( bus&0xff)<<16)|(offset&0xfc))|0x80000000
71
72/*
73 * Bit encode for PCI_CONFIG_HEADER_TYPE register
74 */
75unchar ucMaxPCIBus=0;
76
77/* Please note that PCI0 and PCI1 does not correlate with the busNum 0 and 1.
78 */
79static int direct_pci_read_config_byte(unchar bus,unchar dev,unchar func,
80unchar offset,unchar *val)
81{
82  volatile unsigned char *config_addr, *config_data;
83
84  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
85     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
86     config_addr = (volatile unsigned char*) PCI1_CONFIG_ADDR;
87     config_data = (volatile unsigned char*) PCI1_CONFIG_DATA;
88  }
89  else {
90     config_addr = pci.pci_config_addr;
91     config_data = pci.pci_config_data;
92  }
93  *val = 0xff;
94  if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
95#if 0
96  printk("addr %x, data %x, pack %x \n", config_addr,
97    config_data,pciConfigPack(bus,dev,func,offset));
98#endif
99  outl(pciConfigPack(bus,dev,func,offset),config_addr);
100  *val = inb(config_data + (offset&3));
101  return PCIBIOS_SUCCESSFUL;
102}
103
104static int direct_pci_read_config_word(unchar bus, unchar dev,
105unchar func, unchar offset, unsigned short *val)
106{
107  volatile unsigned char *config_addr, *config_data;
108
109  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
110     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
111     config_addr = (volatile unsigned char*) PCI1_CONFIG_ADDR;
112     config_data = (volatile unsigned char*) PCI1_CONFIG_DATA;
113  }
114  else {
115     config_addr = (volatile unsigned char*) pci.pci_config_addr;
116     config_data = (volatile unsigned char*) pci.pci_config_data;
117  }
118
119  *val = 0xffff;
120  if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
121#if 0
122  printk("addr %x, data %x, pack %x \n", config_addr,
123    config_data,pciConfigPack(bus,dev,func,offset));
124#endif
125  outl(pciConfigPack(bus,dev,func,offset),config_addr);
126  *val = inw(config_data + (offset&2));
127  return PCIBIOS_SUCCESSFUL;
128}
129
130static int direct_pci_read_config_dword(unchar bus, unchar dev,
131unchar func, unchar offset, unsigned int *val)
132{
133  volatile unsigned char *config_addr, *config_data;
134
135  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
136     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
137     config_addr = (volatile unsigned char*) PCI1_CONFIG_ADDR;
138     config_data = (volatile unsigned char*) PCI1_CONFIG_DATA;
139  }
140  else {
141     config_addr = (volatile unsigned char*) pci.pci_config_addr;
142     config_data = (volatile unsigned char*) pci.pci_config_data;
143  }
144
145  *val = 0xffffffff;
146  if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
147#if 0
148  printk("addr %x, data %x, pack %x \n", config_addr,
149    pci.pci_config_data,pciConfigPack(bus,dev,func,offset));
150#endif
151  outl(pciConfigPack(bus,dev,func,offset),config_addr);
152  *val = inl(config_data);
153  return PCIBIOS_SUCCESSFUL;
154}
155
156static int direct_pci_write_config_byte(unchar bus, unchar dev,unchar func, unchar offset, unchar val)
157{
158  volatile unsigned char *config_addr, *config_data;
159
160  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
161     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
162     config_addr = (volatile unsigned char*) PCI1_CONFIG_ADDR;
163     config_data = (volatile unsigned char*) PCI1_CONFIG_DATA;
164  }
165  else {
166     config_addr = pci.pci_config_addr;
167     config_data = pci.pci_config_data;
168  }
169
170  if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
171#if 0
172  printk("addr %x, data %x, pack %x \n", config_addr,
173    config_data,pciConfigPack(bus,dev,func,offset));
174#endif
175
176  outl(pciConfigPack(bus,dev,func,offset), config_addr);
177  outb(val, config_data + (offset&3));
178  return PCIBIOS_SUCCESSFUL;
179}
180
181static int direct_pci_write_config_word(unchar bus, unchar dev,unchar func, unchar offset, unsigned short val)
182{
183  volatile unsigned char *config_addr, *config_data;
184
185  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
186     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
187     config_addr = (volatile unsigned char*) PCI1_CONFIG_ADDR;
188     config_data = (volatile unsigned char*) PCI1_CONFIG_DATA;
189  }
190  else {
191     config_addr = (volatile unsigned char*) pci.pci_config_addr;
192     config_data = (volatile unsigned char*) pci.pci_config_data;
193  }
194
195  if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
196#if 0
197  printk("addr %x, data %x, pack %x \n", config_addr,
198    config_data,pciConfigPack(bus,dev,func,offset));
199#endif
200  outl(pciConfigPack(bus,dev,func,offset),config_addr);
201  outw(val, config_data + (offset&3));
202  return PCIBIOS_SUCCESSFUL;
203}
204
205static int direct_pci_write_config_dword(unchar bus,unchar dev,unchar func, unchar offset, unsigned int val)
206{
207  volatile unsigned char *config_addr, *config_data;
208
209  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
210     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
211     config_addr = (volatile unsigned char *) PCI1_CONFIG_ADDR;
212     config_data = (volatile unsigned char *) PCI1_CONFIG_DATA;
213  }
214  else {
215     config_addr = (volatile unsigned char*) pci.pci_config_addr;
216     config_data = (volatile unsigned char*) pci.pci_config_data;
217  }
218
219  if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
220#if 0
221  printk("addr %x, data %x, pack %x \n", config_addr,
222    config_data,pciConfigPack(bus,dev,func,offset));
223#endif
224  outl(pciConfigPack(bus,dev,func,offset),config_addr);
225  outl(val,config_data);
226  return PCIBIOS_SUCCESSFUL;
227}
228
229const pci_config_access_functions pci_direct_functions = {
230        direct_pci_read_config_byte,
231        direct_pci_read_config_word,
232        direct_pci_read_config_dword,
233        direct_pci_write_config_byte,
234        direct_pci_write_config_word,
235        direct_pci_write_config_dword
236};
237
238
239pci_config BSP_pci_configuration = {(volatile unsigned char*) PCI_CONFIG_ADDR,
240                         (volatile unsigned char*)PCI_CONFIG_DATA,
241                                    &pci_direct_functions};
242
243/*
244 * This routine determines the maximum bus number in the system.
245 * The PCI_SUBORDINATE_BUS is not supported in GT6426xAB. Thus,
246 * it's not used.
247 *
248 */
249int pci_initialize()
250{
251  int deviceFound;
252  unchar ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs;
253  unsigned int ulHeader;
254  unsigned int pcidata, ulClass, ulDeviceID;
255
256  pci_interface();
257 
258  /*
259   * Scan PCI0 and PCI1 buses
260   */
261  for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ucBusNumber++) {
262    deviceFound=0;
263    for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
264      ucFnNumber = 0;
265      pci_read_config_dword(ucBusNumber,
266                                ucSlotNumber,
267                                0,
268                                PCI_VENDOR_ID,
269                                &ulDeviceID);
270
271      if( ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
272        /* This slot is empty */
273        continue;
274      }
275
276      if (++numPCIDevs > PCI_MAX_DEVICES) {
277         BSP_panic("Too many PCI devices found; increase PCI_MAX_DEVICES in pci.h\n");
278      }
279
280      if (!deviceFound) deviceFound=1;
281      switch(ulDeviceID) {
282        case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT6426xAB<<16)):
283#if PCI_PRINT
284          printk("Marvell GT6426xA/B hostbridge detected at bus%d slot%d\n",
285                 ucBusNumber,ucSlotNumber);
286#endif
287          break;
288        case (PCI_VENDOR_ID_PLX2+(PCI_DEVICE_ID_PLX2_PCI6154_HB2<<16)):
289#if PCI_PRINT
290          printk("PLX PCI6154 PCI-PCI bridge detected at bus%d slot%d\n",
291                 ucBusNumber,ucSlotNumber);
292#endif
293          break;
294        case PCI_VENDOR_ID_TUNDRA:
295#if PCI_PRINT
296          printk("TUNDRA PCI-VME bridge detected at bus%d slot%d\n",
297                 ucBusNumber,ucSlotNumber);
298#endif
299          break;
300      case (PCI_VENDOR_ID_INTEL+(PCI_DEVICE_INTEL_82544EI_COPPER<<16)):
301#if PCI_PRINT
302          printk("INTEL 82544EI COPPER network controller detected at bus%d slot%d\n",
303                 ucBusNumber,ucSlotNumber);
304#endif
305          break;
306      case (PCI_VENDOR_ID_DEC+(PCI_DEVICE_ID_DEC_21150<<16)):
307 #if PCI_PRINT
308          printk("DEC21150 PCI-PCI bridge detected at bus%d slot%d\n",
309                 ucBusNumber,ucSlotNumber);
310#endif
311          break;
312       default :
313          printk("BSP unlisted vendor, Bus%d Slot%d DeviceID 0x%x \n",
314             ucBusNumber,ucSlotNumber, ulDeviceID);
315          break;
316      }
317
318#if PCI_DEBUG
319      pci_read_config_dword(ucBusNumber,
320                          ucSlotNumber,
321                          0,
322                          PCI_BASE_ADDRESS_0,
323                          &data);
324      printk("Bus%d BASE_ADDRESS_0 0x%x \n",ucBusNumber, data); 
325      pci_read_config_dword(ucBusNumber,
326                          ucSlotNumber,
327                          0,
328                          PCI_BASE_ADDRESS_1,
329                          &data);
330      printk("Bus%d BASE_ADDRESS_1 0x%x \n",ucBusNumber, data);
331      pci_read_config_dword(ucBusNumber,
332                          ucSlotNumber,
333                          0,
334                          PCI_BASE_ADDRESS_2,
335                          &data);
336      printk("Bus%d BASE_ADDRESS_2 0x%x \n", ucBusNumber, data);
337
338      pci_read_config_dword(ucBusNumber,
339                          ucSlotNumber,
340                          0,
341                          PCI_BASE_ADDRESS_3,
342                          &data);
343      printk("Bus%d BASE_ADDRESS_3 0x%x \n", ucBusNumber, data); 
344
345      pci_read_config_word(ucBusNumber,
346                          ucSlotNumber,
347                          0,
348                          PCI_INTERRUPT_LINE,
349                          &sdata);
350      printk("Bus%d INTERRUPT_LINE 0x%x \n", ucBusNumber, sdata); 
351
352      /* We always enable internal memory. */
353      pci_read_config_dword(ucBusNumber,
354                          ucSlotNumber,
355                          0,
356                          PCI_MEM_BASE_ADDR,
357                          &pcidata);
358      printk("Bus%d MEM_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
359
360      /* We always enable internal IO. */
361      pci_read_config_dword(ucBusNumber,
362                          ucSlotNumber,
363                          0,
364                          PCI_IO_BASE_ADDR,
365                          &pcidata);
366      printk("Bus%d IO_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
367#endif
368
369      pci_read_config_dword(ucBusNumber,
370                          ucSlotNumber,
371                          0,
372                          PCI_CACHE_LINE_SIZE,
373                          &ulHeader);
374      if ((ulHeader>>16)&PCI_MULTI_FUNCTION)
375         ucNumFuncs=PCI_MAX_FUNCTIONS;
376      else
377         ucNumFuncs=1;
378
379#if PCI_DEBUG
380      printk("Bus%d Slot 0x%x HEADER/LAT/CACHE 0x%x \n",
381             ucBusNumber, ucSlotNumber, ulHeader);   
382#endif
383
384      for (ucFnNumber=1;ucFnNumber<ucNumFuncs;ucFnNumber++) {
385          pci_read_config_dword(ucBusNumber,
386                                  ucSlotNumber,
387                                  ucFnNumber,
388                                  PCI_VENDOR_ID,
389                                  &ulDeviceID);
390          if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
391             /* This slot/function is empty */
392             continue;
393          }
394
395         /* This slot/function has a device fitted.*/
396         pci_read_config_dword(ucBusNumber,
397                                  ucSlotNumber,
398                                  ucFnNumber,
399                                  PCI_CLASS_REVISION,
400                                  &ulClass);
401#if PCI_DEBUG   
402         printk("Bus%d Slot 0x%x Func %d classID 0x%x \n",ucBusNumber,ucSlotNumber,
403             ucFnNumber, ulClass);
404#endif
405
406      }
407
408      pci_read_config_dword(ucBusNumber,
409                               ucSlotNumber,
410                               0,
411                          PCI_COMMAND,
412                          &pcidata);
413#if PCI_DEBUG
414      printk("MOTLoad command staus 0x%x, ", pcidata);
415#endif
416      /* Clear the error on the host bridge */
417      if ( (ucBusNumber==0) && (ucSlotNumber==0))
418        pcidata |= PCI_STATUS_CLRERR_MASK;
419      /* Enable bus,I/O and memory master access. */
420      pcidata |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY);
421      pci_write_config_dword(ucBusNumber,
422                               ucSlotNumber,
423                               0,
424                          PCI_COMMAND,
425                          pcidata);
426
427      pci_read_config_dword(ucBusNumber,
428                               ucSlotNumber,
429                               0,
430                          PCI_COMMAND,
431                          &pcidata);
432#if PCI_DEBUG     
433      printk("Now command/staus 0x%x\n", pcidata);
434#endif
435    }
436    if (deviceFound) ucMaxPCIBus++;
437  } /* for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ... */
438#if PCI_DEBUG
439  printk("number of PCI buses: %d, numPCIDevs %d\n",
440         pci_bus_count(), numPCIDevs);
441#endif
442  return(0);
443}
444
445void FixupPCI( struct _int_map *bspmap, int (*swizzler)(int,int) )
446{
447}
448
449/*
450 * Return the number of PCI buses in the system
451 */
452unsigned char pci_bus_count()
453{
454  return(ucMaxPCIBus);
455}
456
Note: See TracBrowser for help on using the repository browser.