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

4.104.114.84.95
Last change on this file since e99a41f was e99a41f, checked in by Ralf Corsepius <ralf.corsepius@…>, on 03/31/07 at 04:05:28

Reflect changes to pci-API.

  • 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#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();
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,
79  unsigned char func, unsigned char offset, uint8_t *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,
104  unsigned char func, unsigned char offset, uint16_t *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,
130  unsigned char func, unsigned char offset, uint32_t *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,
156  unsigned char func, unsigned char offset, uint8_t 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(unsigned char bus, unsigned char dev,
182  unsigned char func, unsigned char offset, uint16_t 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,
207  unsigned char func, unsigned char offset, uint32_t val)
208{
209  volatile unsigned char *config_addr, *config_data;
210
211  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
212     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
213     config_addr = (volatile unsigned char *) PCI1_CONFIG_ADDR;
214     config_data = (volatile unsigned char *) PCI1_CONFIG_DATA;
215  }
216  else {
217     config_addr = (volatile unsigned char*) pci.pci_config_addr;
218     config_data = (volatile unsigned char*) pci.pci_config_data;
219  }
220
221  if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
222#if 0
223  printk("addr %x, data %x, pack %x \n", config_addr,
224    config_data,pciConfigPack(bus,dev,func,offset));
225#endif
226  outl(pciConfigPack(bus,dev,func,offset),config_addr);
227  outl(val,config_data);
228  return PCIBIOS_SUCCESSFUL;
229}
230
231const pci_config_access_functions pci_direct_functions = {
232        direct_pci_read_config_byte,
233        direct_pci_read_config_word,
234        direct_pci_read_config_dword,
235        direct_pci_write_config_byte,
236        direct_pci_write_config_word,
237        direct_pci_write_config_dword
238};
239
240
241pci_config BSP_pci_configuration = {(volatile unsigned char*) PCI_CONFIG_ADDR,
242                         (volatile unsigned char*)PCI_CONFIG_DATA,
243                                    &pci_direct_functions};
244
245/*
246 * This routine determines the maximum bus number in the system.
247 * The PCI_SUBORDINATE_BUS is not supported in GT6426xAB. Thus,
248 * it's not used.
249 *
250 */
251int pci_initialize()
252{
253  int deviceFound;
254  unsigned char ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs;
255  uint32_t ulHeader;
256  uint32_t pcidata, ulClass, ulDeviceID;
257
258  pci_interface();
259 
260  /*
261   * Scan PCI0 and PCI1 buses
262   */
263  for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ucBusNumber++) {
264    deviceFound=0;
265    for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
266      ucFnNumber = 0;
267      pci_read_config_dword(ucBusNumber,
268                                ucSlotNumber,
269                                0,
270                                PCI_VENDOR_ID,
271                                &ulDeviceID);
272
273      if( ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
274        /* This slot is empty */
275        continue;
276      }
277
278      if (++numPCIDevs > PCI_MAX_DEVICES) {
279         BSP_panic("Too many PCI devices found; increase PCI_MAX_DEVICES in pci.h\n");
280      }
281
282      if (!deviceFound) deviceFound=1;
283      switch(ulDeviceID) {
284        case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT6426xAB<<16)):
285#if PCI_PRINT
286          printk("Marvell GT6426xA/B hostbridge detected at bus%d slot%d\n",
287                 ucBusNumber,ucSlotNumber);
288#endif
289          break;
290        case (PCI_VENDOR_ID_PLX2+(PCI_DEVICE_ID_PLX2_PCI6154_HB2<<16)):
291#if PCI_PRINT
292          printk("PLX PCI6154 PCI-PCI bridge detected at bus%d slot%d\n",
293                 ucBusNumber,ucSlotNumber);
294#endif
295          break;
296        case PCI_VENDOR_ID_TUNDRA:
297#if PCI_PRINT
298          printk("TUNDRA PCI-VME bridge detected at bus%d slot%d\n",
299                 ucBusNumber,ucSlotNumber);
300#endif
301          break;
302      case (PCI_VENDOR_ID_INTEL+(PCI_DEVICE_INTEL_82544EI_COPPER<<16)):
303#if PCI_PRINT
304          printk("INTEL 82544EI COPPER network controller detected at bus%d slot%d\n",
305                 ucBusNumber,ucSlotNumber);
306#endif
307          break;
308      case (PCI_VENDOR_ID_DEC+(PCI_DEVICE_ID_DEC_21150<<16)):
309 #if PCI_PRINT
310          printk("DEC21150 PCI-PCI bridge detected at bus%d slot%d\n",
311                 ucBusNumber,ucSlotNumber);
312#endif
313          break;
314       default :
315          printk("BSP unlisted vendor, Bus%d Slot%d DeviceID 0x%x \n",
316             ucBusNumber,ucSlotNumber, ulDeviceID);
317          break;
318      }
319
320#if PCI_DEBUG
321      pci_read_config_dword(ucBusNumber,
322                          ucSlotNumber,
323                          0,
324                          PCI_BASE_ADDRESS_0,
325                          &data);
326      printk("Bus%d BASE_ADDRESS_0 0x%x \n",ucBusNumber, data); 
327      pci_read_config_dword(ucBusNumber,
328                          ucSlotNumber,
329                          0,
330                          PCI_BASE_ADDRESS_1,
331                          &data);
332      printk("Bus%d BASE_ADDRESS_1 0x%x \n",ucBusNumber, data);
333      pci_read_config_dword(ucBusNumber,
334                          ucSlotNumber,
335                          0,
336                          PCI_BASE_ADDRESS_2,
337                          &data);
338      printk("Bus%d BASE_ADDRESS_2 0x%x \n", ucBusNumber, data);
339
340      pci_read_config_dword(ucBusNumber,
341                          ucSlotNumber,
342                          0,
343                          PCI_BASE_ADDRESS_3,
344                          &data);
345      printk("Bus%d BASE_ADDRESS_3 0x%x \n", ucBusNumber, data); 
346
347      pci_read_config_word(ucBusNumber,
348                          ucSlotNumber,
349                          0,
350                          PCI_INTERRUPT_LINE,
351                          &sdata);
352      printk("Bus%d INTERRUPT_LINE 0x%x \n", ucBusNumber, sdata); 
353
354      /* We always enable internal memory. */
355      pci_read_config_dword(ucBusNumber,
356                          ucSlotNumber,
357                          0,
358                          PCI_MEM_BASE_ADDR,
359                          &pcidata);
360      printk("Bus%d MEM_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
361
362      /* We always enable internal IO. */
363      pci_read_config_dword(ucBusNumber,
364                          ucSlotNumber,
365                          0,
366                          PCI_IO_BASE_ADDR,
367                          &pcidata);
368      printk("Bus%d IO_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
369#endif
370
371      pci_read_config_dword(ucBusNumber,
372                          ucSlotNumber,
373                          0,
374                          PCI_CACHE_LINE_SIZE,
375                          &ulHeader);
376      if ((ulHeader>>16)&PCI_MULTI_FUNCTION)
377         ucNumFuncs=PCI_MAX_FUNCTIONS;
378      else
379         ucNumFuncs=1;
380
381#if PCI_DEBUG
382      printk("Bus%d Slot 0x%x HEADER/LAT/CACHE 0x%x \n",
383             ucBusNumber, ucSlotNumber, ulHeader);   
384#endif
385
386      for (ucFnNumber=1;ucFnNumber<ucNumFuncs;ucFnNumber++) {
387          pci_read_config_dword(ucBusNumber,
388                                  ucSlotNumber,
389                                  ucFnNumber,
390                                  PCI_VENDOR_ID,
391                                  &ulDeviceID);
392          if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
393             /* This slot/function is empty */
394             continue;
395          }
396
397         /* This slot/function has a device fitted.*/
398         pci_read_config_dword(ucBusNumber,
399                                  ucSlotNumber,
400                                  ucFnNumber,
401                                  PCI_CLASS_REVISION,
402                                  &ulClass);
403#if PCI_DEBUG   
404         printk("Bus%d Slot 0x%x Func %d classID 0x%x \n",ucBusNumber,ucSlotNumber,
405             ucFnNumber, ulClass);
406#endif
407
408      }
409
410      pci_read_config_dword(ucBusNumber,
411                               ucSlotNumber,
412                               0,
413                          PCI_COMMAND,
414                          &pcidata);
415#if PCI_DEBUG
416      printk("MOTLoad command staus 0x%x, ", pcidata);
417#endif
418      /* Clear the error on the host bridge */
419      if ( (ucBusNumber==0) && (ucSlotNumber==0))
420        pcidata |= PCI_STATUS_CLRERR_MASK;
421      /* Enable bus,I/O and memory master access. */
422      pcidata |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY);
423      pci_write_config_dword(ucBusNumber,
424                               ucSlotNumber,
425                               0,
426                          PCI_COMMAND,
427                          pcidata);
428
429      pci_read_config_dword(ucBusNumber,
430                               ucSlotNumber,
431                               0,
432                          PCI_COMMAND,
433                          &pcidata);
434#if PCI_DEBUG     
435      printk("Now command/staus 0x%x\n", pcidata);
436#endif
437    }
438    if (deviceFound) ucMaxPCIBus++;
439  } /* for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ... */
440#if PCI_DEBUG
441  printk("number of PCI buses: %d, numPCIDevs %d\n",
442         pci_bus_count(), numPCIDevs);
443#endif
444  return(0);
445}
446
447void FixupPCI( struct _int_map *bspmap, int (*swizzler)(int,int) )
448{
449}
450
451/*
452 * Return the number of PCI buses in the system
453 */
454unsigned char pci_bus_count()
455{
456  return(ucMaxPCIBus);
457}
458
Note: See TracBrowser for help on using the repository browser.