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

4.104.114.84.9
Last change on this file since 46a6fa91 was 46a6fa91, checked in by Joel Sherrill <joel.sherrill@…>, on Apr 15, 2005 at 8:13:18 PM

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

  • GT64260/GT64260TWSI.c, GT64260/GT64260TWSI.h, irq/GT64260Int.c, network/GT64260eth.c, pci/pci.c, startup/bspclean.c, startup/reboot.c: Fix warnings.
  • 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  unsigned int ulHeader;
180  unsigned int pcidata, ulDeviceID;
181#if PCI_DEBUG
182  unsigned int data, pcidata, ulClass;
183  unsigned short sdata;
184#endif
185
186  PCI_interface();
187 
188  /*
189   * Scan PCI0 and PCI1 bus0
190   */
191  for (PciNumber=0; PciNumber < 2; PciNumber++) {
192    pciAccessInit(PciNumber);
193    for (ucBusNumber=0; ucBusNumber< 2; ucBusNumber++) {
194    for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
195      ucFnNumber = 0;
196      PCIx_read_config_dword(PciNumber, ucBusNumber,
197                                ucSlotNumber,
198                                0,
199                                PCI0_VENDOR_ID,
200                                &ulDeviceID);
201
202      if( ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
203        /* This slot is empty */
204        continue;
205      }
206
207      if (++numPCIDevs > MAX_NUM_PCI_DEVICES) {
208         BSP_panic("Too many PCI devices found; increase MAX_NUM_PCI_DEVICES in pcicache.c\n");
209      }
210
211      switch(ulDeviceID) { 
212        case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT6426xAB<<16)):
213#if PCI_PRINT
214          printk("Marvell GT6426xA/B hostbridge detected at PCI%d bus%d slot%d\n",
215                 PciNumber,ucBusNumber,ucSlotNumber);
216#endif
217          ucMaxPCIBus ++;
218          break;
219        case (PCI_VENDOR_ID_PLX2+(PCI_DEVICE_ID_PLX2_PCI6154_HB2<<16)):
220#if PCI_PRINT
221          printk("PLX PCI6154 PCI-PCI bridge detected at PCI%d bus%d slot%d\n",
222                 PciNumber,ucBusNumber,ucSlotNumber);
223#endif
224          ucMaxPCIBus ++;
225          break;
226        case PCI_VENDOR_ID_TUNDRA:
227#if PCI_PRINT
228          printk("TUNDRA PCI-VME bridge detected at PCI%d bus%d slot%d\n",
229                 PciNumber,ucBusNumber,ucSlotNumber);
230#endif
231          ucMaxPCIBus ++;
232          break;
233      case (PCI_VENDOR_ID_INTEL+(PCI_DEVICE_INTEL_82544EI_COPPER<<16)):
234#if PCI_PRINT
235          printk("INTEL 82544EI COPPER network controller detected at PCI%d bus%d slot%d\n",
236                 PciNumber,ucBusNumber,ucSlotNumber);
237#endif
238          ucMaxPCIBus ++;
239          break;
240        default : 
241#if PCI_PRINT
242          printk("PCI%d Bus%d Slot%d DeviceID 0x%x \n",
243             PciNumber,ucBusNumber,ucSlotNumber, ulDeviceID);
244#endif
245          break;
246      }
247#if PCI_DEBUG
248      PCIx_read_config_dword(PciNumber, ucBusNumber,
249                          ucSlotNumber,
250                          0,
251                          PCI0_BASE_ADDRESS_0,
252                          &data);
253      printk("PCI%d_BASE_ADDRESS_0 0x%x \n",PciNumber, data); 
254      PCIx_read_config_dword(PciNumber, ucBusNumber,
255                          ucSlotNumber,
256                          0,
257                          PCI0_BASE_ADDRESS_1,
258                          &data);
259      printk("PCI%d_BASE_ADDRESS_1 0x%x \n",PciNumber, data);
260      PCIx_read_config_dword(PciNumber, ucBusNumber,
261                          ucSlotNumber,
262                          0,
263                          PCI0_BASE_ADDRESS_2,
264                          &data);
265      printk("PCI%d_BASE_ADDRESS_2 0x%x \n",PciNumber, data);
266
267      PCIx_read_config_dword(PciNumber, ucBusNumber,
268                          ucSlotNumber,
269                          0,
270                          PCI0_BASE_ADDRESS_3,
271                          &data);
272      printk("PCI%d_BASE_ADDRESS_3 0x%x \n",PciNumber, data); 
273
274     PCIx_read_config_word(PciNumber, ucBusNumber,
275                          ucSlotNumber,
276                          0,
277                          PCI0_INTERRUPT_LINE,
278                          &sdata);
279      printk("PCI%d_INTERRUPT_LINE 0x%x \n",PciNumber, sdata); 
280
281      /* We always enable internal memory. */
282      PCIx_read_config_dword(PciNumber, ucBusNumber,
283                          ucSlotNumber,
284                          0,
285                          PCI0_MEM_BASE_ADDR,
286                          &pcidata);
287      printk("PCI%d_MEM_BASE_ADDR 0x%x \n", PciNumber,pcidata);
288
289      /* We always enable internal IO. */
290      PCIx_read_config_dword(PciNumber, ucBusNumber,
291                          ucSlotNumber,
292                          0,
293                          PCI0_IO_BASE_ADDR,
294                          &pcidata);
295      printk("PCI%d_IO_BASE_ADDR 0x%x \n", PciNumber,pcidata);
296#endif
297
298      PCIx_read_config_dword(PciNumber, ucBusNumber,
299                          ucSlotNumber,
300                          0,
301                          PCI0_CACHE_LINE_SIZE,
302                          &ulHeader);
303      if ((ulHeader>>16)&PCI_MULTI_FUNCTION)
304         ucNumFuncs=PCI_MAX_FUNCTIONS;
305      else
306         ucNumFuncs=1;
307
308#if PCI_DEBUG
309      printk("PCI%d Slot 0x%x HEADER/LAT/CACHE 0x%x \n",
310             PciNumber,ucSlotNumber, ulHeader);   
311
312      for (ucFnNumber=1;ucFnNumber<ucNumFuncs;ucFnNumber++) {
313          PCIx_read_config_dword(PciNumber, ucBusNumber,
314                                  ucSlotNumber,
315                                  ucFnNumber,
316                                  PCI0_VENDOR_ID,
317                                  &ulDeviceID);
318          if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
319             /* This slot/function is empty */
320             continue;
321          }
322          if (++numPCIDevs > MAX_NUM_PCI_DEVICES) {
323             BSP_panic("Too many PCI devices found; increase MAX_NUM_PCI_DEVICES in pcicache.c\n");
324          }
325
326         /* This slot/function has a device fitted.*/
327         PCIx_read_config_dword(PciNumber, ucBusNumber,
328                                  ucSlotNumber,
329                                  ucFnNumber,
330                                  PCI0_CLASS_REVISION,
331                                  &ulClass);     
332         printk("PCI%d Slot 0x%x Func %d classID 0x%x \n",PciNumber,ucSlotNumber,
333             ucFnNumber, ulClass);
334
335         ulClass >>= 16;
336         if (ulClass == PCI_CLASS_GT6426xAB)
337            printk("GT64260-PCI%d bridge found \n", PciNumber);
338      }
339#endif
340      PCIx_read_config_dword(PciNumber, ucBusNumber,
341                               ucSlotNumber,
342                               0,
343                          PCI0_COMMAND,
344                          &pcidata); 
345#if PCI_DEBUG
346      printk("MOTLoad command staus 0x%x, ", pcidata);
347#endif
348      /* Clear the error on the host bridge */
349      if ( (ucBusNumber==0) && (ucSlotNumber==0))
350        pcidata |= PCI_STATUS_CLRERR_MASK;
351      /* Enable bus,I/O and memory master access. */
352      pcidata |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY);
353      PCIx_write_config_dword(PciNumber, ucBusNumber,
354                               ucSlotNumber,
355                               0,
356                          PCI0_COMMAND,
357                          pcidata);
358
359      PCIx_read_config_dword(PciNumber, ucBusNumber,
360                               ucSlotNumber,
361                               0,
362                          PCI0_COMMAND,
363                          &pcidata); 
364#if PCI_DEBUG     
365      printk("Now command/staus 0x%x\n", pcidata);
366#endif
367 
368    }
369    }
370  } /* PCI number */
371}
372
373/*
374 * Return the number of PCI buses in the system
375 */
376unsigned char BusCountPCI()
377{
378  return(ucMaxPCIBus);
379}
380
Note: See TracBrowser for help on using the repository browser.