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

4.104.114.95
Last change on this file since 32cf3525 was 16fa78e, checked in by Ralf Corsepius <ralf.corsepius@…>, on 08/20/08 at 06:59:04

2008-08-20 Ralf Corsépius <ralf.corsepius@…>

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