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

4.104.114.84.9
Last change on this file since 037864f5 was 037864f5, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 4, 2005 at 9:48:17 PM

2005-03-04 Joel Sherrill <joel@…>

  • pci/pci.c, pci/pci.h, startup/bspstart.c: Make PCI initialize function part of the unified PCI API as pci_initialize().
  • Property mode set to 100644
File size: 11.1 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/license/LICENSE.
15 *
16 *  $Id$
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 *
23 */
24#define PCI_MAIN
25
26#include <libcpu/io.h>
27#include <rtems/bspIo.h>            /* printk */
28
29#include <bsp/pci.h>
30#include <bsp/gtreg.h>
31#include <bsp/gtpcireg.h> 
32
33#include <stdio.h>
34#include <string.h>
35
36#define PCI_DEBUG 0
37#define PCI_PRINT 1
38
39#define PCI_INVALID_VENDORDEVICEID      0xffffffff
40#define PCI_MULTI_FUNCTION              0x80
41#define HOSTBRIDGET_ERROR               0xf0000000
42
43typedef unsigned char unchar;
44
45#define MAX_NUM_PCI_DEVICES     20
46
47static int                numPCIDevs=0;
48extern void PCI_interface(), pciAccessInit();
49
50/* Pack RegNum,FuncNum,DevNum,BusNum,and ConfigEnable for
51 * PCI Configuration Address Register
52 */
53#define pciConfigPack(bus,dev,func,offset)\
54(((func&7)<<8)|((dev&0x1f )<<11)|(( bus&0xff)<<16)|(offset&0xfc))|0x80000000
55
56/*
57 * Bit encode for PCI_CONFIG_HEADER_TYPE register
58 */
59unchar ucMaxPCIBus=0;
60
61/* Please note that PCI0 and PCI1 does not correlate with the busNum 0 and 1.
62 */
63int PCIx_read_config_byte(int npci, unchar bus, unchar dev,
64unchar func, unchar offset, unchar *val)
65{
66  *val = 0xff;
67  if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
68  outl(pciConfigPack(bus,dev,func,offset),BSP_pci_config[npci].pci_config_addr);
69  *val = inb(BSP_pci_config[npci].pci_config_data + (offset&3));
70  return PCIBIOS_SUCCESSFUL;
71}
72
73int PCIx_read_config_word(int npci, unchar bus, unchar dev,
74unchar func, unchar offset, unsigned short *val)
75{
76  *val = 0xffff; 
77  if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
78  outl(pciConfigPack(bus,dev,func,offset),BSP_pci_config[npci].pci_config_addr);
79  *val = inw(BSP_pci_config[npci].pci_config_data + (offset&2));
80  return PCIBIOS_SUCCESSFUL;
81}
82
83int PCIx_read_config_dword(int npci, unchar bus, unchar dev,
84unchar func, unchar offset, unsigned int *val) 
85{
86  *val = 0xffffffff; 
87  if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
88#if 0
89  printk("addr %x, data %x, pack %x \n", BSP_pci_config[npci].pci_config_addr,
90    BSP_pci_config[npci].pci_config_data,pciConfigPack(bus,dev,func,offset));
91#endif
92  outl(pciConfigPack(bus,dev,func,offset),BSP_pci_config[npci].pci_config_addr);
93  *val = inl(BSP_pci_config[npci].pci_config_data);
94  return PCIBIOS_SUCCESSFUL;
95}
96
97int PCIx_write_config_byte(int npci, unchar bus, unchar dev,
98unchar func, unchar offset, unchar val) 
99{
100  if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
101
102  outl(pciConfigPack(bus,dev,func,offset),BSP_pci_config[npci].pci_config_addr);
103  outb(val, BSP_pci_config[npci].pci_config_data + (offset&3));
104  return PCIBIOS_SUCCESSFUL;
105}
106
107int PCIx_write_config_word(int npci, unchar bus, unchar dev,
108unchar func, unchar offset, unsigned short val) 
109{
110  if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
111  outl(pciConfigPack(bus,dev,func,offset),BSP_pci_config[npci].pci_config_addr);
112  outw(val, BSP_pci_config[npci].pci_config_data + (offset&3));
113  return PCIBIOS_SUCCESSFUL;
114}
115
116int PCIx_write_config_dword(int npci,unchar bus,unchar dev,
117unchar func, unchar offset, unsigned int val) 
118{
119  if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
120#if 0
121  printk("addr %x, data %x, pack %x \n", BSP_pci_config[npci].pci_config_addr,
122    BSP_pci_config[npci].pci_config_data,pciConfigPack(bus,dev,func,offset));
123#endif
124  outl(pciConfigPack(bus,dev,func,offset),BSP_pci_config[npci].pci_config_addr);
125  outl(val,BSP_pci_config[npci].pci_config_data);
126  return PCIBIOS_SUCCESSFUL;
127}
128
129/* backwards compatible with other PPC board for the vmeUniverse.c */
130int pci_read_config_byte(unchar bus, unchar dev,unchar func,unchar offset,
131unchar *val)
132{
133  return(PCIx_read_config_byte(0, bus, dev, func, offset, val));
134}
135
136int pci_read_config_word(unchar bus, unchar dev,
137unchar func, unchar offset, unsigned short *val)
138{
139  return(PCIx_read_config_word(0, bus, dev, func, offset, val));
140}
141
142int pci_read_config_dword(unchar bus, unchar dev,
143unchar func, unchar offset, unsigned int *val) 
144{
145  return(PCIx_read_config_dword(0, bus, dev, func, offset, val));
146}
147
148int pci_write_config_byte(unchar bus, unchar dev,
149unchar func, unchar offset, unchar val) 
150{
151  return(PCIx_write_config_byte(0, bus, dev, func, offset, val));
152}
153
154int pci_write_config_word(unchar bus, unchar dev,
155unchar func, unchar offset, unsigned short val) 
156{
157  return(PCIx_write_config_word(0, bus, dev, func, offset, val));
158}
159
160int pci_write_config_dword(unchar bus,unchar dev,
161unchar func, unchar offset, unsigned int val) 
162{
163  return(PCIx_write_config_dword(0, bus, dev, func, offset, val));
164}
165
166
167pci_config BSP_pci_config[2] = {
168  {PCI0_CONFIG_ADDR,PCI0_CONFIG_DATA/*,&pci_functions*/},
169       {PCI1_CONFIG_ADDR,PCI1_CONFIG_DATA/*,&pci_functions*/}
170};
171
172/*
173 * This routine determines the maximum bus number in the system
174 */
175void pci_initialize()
176{
177  int PciNumber;
178  unchar ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs;
179  unchar ucMaxSubordinate;
180  unsigned long ulHeader;
181  unsigned int data, datal, datah, pcidata, ulClass, ulDeviceID;
182  unsigned short sdata;
183
184  PCI_interface();
185 
186  /*
187   * Scan PCI0 and PCI1 bus0
188   */
189  for (PciNumber=0; PciNumber < 2; PciNumber++) {
190    pciAccessInit(PciNumber);
191    for (ucBusNumber=0; ucBusNumber< 2; ucBusNumber++) {
192    for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
193      ucFnNumber = 0;
194      PCIx_read_config_dword(PciNumber, ucBusNumber,
195                                ucSlotNumber,
196                                0,
197                                PCI0_VENDOR_ID,
198                                &ulDeviceID);
199
200      if( ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
201        /* This slot is empty */
202        continue;
203      }
204
205      if (++numPCIDevs > MAX_NUM_PCI_DEVICES) {
206         BSP_panic("Too many PCI devices found; increase MAX_NUM_PCI_DEVICES in pcicache.c\n");
207      }
208
209      switch(ulDeviceID) { 
210        case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT6426xAB<<16)):
211#if PCI_PRINT
212          printk("Marvell GT6426xA/B hostbridge detected at PCI%d bus%d slot%d\n",
213                 PciNumber,ucBusNumber,ucSlotNumber);
214#endif
215          ucMaxPCIBus ++;
216          break;
217        case (PCI_VENDOR_ID_PLX2+(PCI_DEVICE_ID_PLX2_PCI6154_HB2<<16)):
218#if PCI_PRINT
219          printk("PLX PCI6154 PCI-PCI bridge detected at PCI%d bus%d slot%d\n",
220                 PciNumber,ucBusNumber,ucSlotNumber);
221#endif
222          ucMaxPCIBus ++;
223          break;
224        case PCI_VENDOR_ID_TUNDRA:
225#if PCI_PRINT
226          printk("TUNDRA PCI-VME bridge detected at PCI%d bus%d slot%d\n",
227                 PciNumber,ucBusNumber,ucSlotNumber);
228#endif
229          ucMaxPCIBus ++;
230          break;
231      case (PCI_VENDOR_ID_INTEL+(PCI_DEVICE_INTEL_82544EI_COPPER<<16)):
232#if PCI_PRINT
233          printk("INTEL 82544EI COPPER network controller detected at PCI%d bus%d slot%d\n",
234                 PciNumber,ucBusNumber,ucSlotNumber);
235#endif
236          ucMaxPCIBus ++;
237          break;
238        default : 
239#if PCI_PRINT
240          printk("PCI%d Bus%d Slot%d DeviceID 0x%x \n",
241             PciNumber,ucBusNumber,ucSlotNumber, ulDeviceID);
242#endif
243          break;
244      }
245#if PCI_DEBUG
246      PCIx_read_config_dword(PciNumber, ucBusNumber,
247                          ucSlotNumber,
248                          0,
249                          PCI0_BASE_ADDRESS_0,
250                          &data);
251      printk("PCI%d_BASE_ADDRESS_0 0x%x \n",PciNumber, data); 
252      PCIx_read_config_dword(PciNumber, ucBusNumber,
253                          ucSlotNumber,
254                          0,
255                          PCI0_BASE_ADDRESS_1,
256                          &data);
257      printk("PCI%d_BASE_ADDRESS_1 0x%x \n",PciNumber, data);
258      PCIx_read_config_dword(PciNumber, ucBusNumber,
259                          ucSlotNumber,
260                          0,
261                          PCI0_BASE_ADDRESS_2,
262                          &data);
263      printk("PCI%d_BASE_ADDRESS_2 0x%x \n",PciNumber, data);
264
265      PCIx_read_config_dword(PciNumber, ucBusNumber,
266                          ucSlotNumber,
267                          0,
268                          PCI0_BASE_ADDRESS_3,
269                          &data);
270      printk("PCI%d_BASE_ADDRESS_3 0x%x \n",PciNumber, data); 
271
272     PCIx_read_config_word(PciNumber, ucBusNumber,
273                          ucSlotNumber,
274                          0,
275                          PCI0_INTERRUPT_LINE,
276                          &sdata);
277      printk("PCI%d_INTERRUPT_LINE 0x%x \n",PciNumber, sdata); 
278
279      /* We always enable internal memory. */
280      PCIx_read_config_dword(PciNumber, ucBusNumber,
281                          ucSlotNumber,
282                          0,
283                          PCI0_MEM_BASE_ADDR,
284                          &pcidata);
285      printk("PCI%d_MEM_BASE_ADDR 0x%x \n", PciNumber,pcidata);
286
287      /* We always enable internal IO. */
288      PCIx_read_config_dword(PciNumber, ucBusNumber,
289                          ucSlotNumber,
290                          0,
291                          PCI0_IO_BASE_ADDR,
292                          &pcidata);
293      printk("PCI%d_IO_BASE_ADDR 0x%x \n", PciNumber,pcidata);
294#endif
295
296      PCIx_read_config_dword(PciNumber, ucBusNumber,
297                          ucSlotNumber,
298                          0,
299                          PCI0_CACHE_LINE_SIZE,
300                          &ulHeader);
301      if ((ulHeader>>16)&PCI_MULTI_FUNCTION)
302         ucNumFuncs=PCI_MAX_FUNCTIONS;
303      else
304         ucNumFuncs=1;
305
306#if PCI_DEBUG
307      printk("PCI%d Slot 0x%x HEADER/LAT/CACHE 0x%x \n",
308             PciNumber,ucSlotNumber, ulHeader);   
309
310      for (ucFnNumber=1;ucFnNumber<ucNumFuncs;ucFnNumber++) {
311          PCIx_read_config_dword(PciNumber, ucBusNumber,
312                                  ucSlotNumber,
313                                  ucFnNumber,
314                                  PCI0_VENDOR_ID,
315                                  &ulDeviceID);
316          if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
317             /* This slot/function is empty */
318             continue;
319          }
320          if (++numPCIDevs > MAX_NUM_PCI_DEVICES) {
321             BSP_panic("Too many PCI devices found; increase MAX_NUM_PCI_DEVICES in pcicache.c\n");
322          }
323
324         /* This slot/function has a device fitted.*/
325         PCIx_read_config_dword(PciNumber, ucBusNumber,
326                                  ucSlotNumber,
327                                  ucFnNumber,
328                                  PCI0_CLASS_REVISION,
329                                  &ulClass);     
330         printk("PCI%d Slot 0x%x Func %d classID 0x%x \n",PciNumber,ucSlotNumber,
331             ucFnNumber, ulClass);
332
333         ulClass >>= 16;
334         if (ulClass == PCI_CLASS_GT6426xAB)
335            printk("GT64260-PCI%d bridge found \n", PciNumber);
336      }
337#endif
338      PCIx_read_config_dword(PciNumber, ucBusNumber,
339                               ucSlotNumber,
340                               0,
341                          PCI0_COMMAND,
342                          &pcidata); 
343#if PCI_DEBUG
344      printk("MOTLoad command staus 0x%x, ", pcidata);
345#endif
346      /* Clear the error on the host bridge */
347      if ( (ucBusNumber==0) && (ucSlotNumber==0))
348        pcidata |= PCI_STATUS_CLRERR_MASK;
349      /* Enable bus,I/O and memory master access. */
350      pcidata |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY);
351      PCIx_write_config_dword(PciNumber, ucBusNumber,
352                               ucSlotNumber,
353                               0,
354                          PCI0_COMMAND,
355                          pcidata);
356
357      PCIx_read_config_dword(PciNumber, ucBusNumber,
358                               ucSlotNumber,
359                               0,
360                          PCI0_COMMAND,
361                          &pcidata); 
362#if PCI_DEBUG     
363      printk("Now command/staus 0x%x\n", pcidata);
364#endif
365 
366    }
367    }
368  } /* PCI number */
369}
370
371/*
372 * Return the number of PCI buses in the system
373 */
374unsigned char BusCountPCI()
375{
376  return(ucMaxPCIBus);
377}
378
Note: See TracBrowser for help on using the repository browser.