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

4.104.114.9
Last change on this file since 6771a9e7 was 6771a9e7, checked in by Ralf Corsepius <ralf.corsepius@…>, on Aug 20, 2008 at 9:00:11 AM

Add missing prototypes.

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