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

4.104.114.84.95
Last change on this file since 3bfb6ef was 3bfb6ef, checked in by Jennifer Averett <Jennifer.Averett@…>, on 05/10/05 at 18:24:35

2005-05-10 Jennifer Averett <jennifer.averett@…>

  • network/GT64260eth.c: Fixed warning.
  • pci/pci.c, pci/pci.h: Modified to depend upon rtems/pci.h
  • Property mode set to 100644
File size: 11.3 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
130 * Note: We must override the default with these in pci.h
131 */
132int pci_bsp_read_config_byte(unchar bus, unchar dev,unchar func,unchar offset,
133unchar *val)
134{
135  return(PCIx_read_config_byte(0, bus, dev, func, offset, val));
136}
137
138int pci_bsp_read_config_word(unchar bus, unchar dev,
139unchar func, unchar offset, unsigned short *val)
140{
141  return(PCIx_read_config_word(0, bus, dev, func, offset, val));
142}
143
144int pci_bsp_read_config_dword(unchar bus, unchar dev,
145unchar func, unchar offset, unsigned int *val)
146{
147  return(PCIx_read_config_dword(0, bus, dev, func, offset, val));
148}
149
150int pci_bsp_write_config_byte(unchar bus, unchar dev,
151unchar func, unchar offset, unchar val)
152{
153  return(PCIx_write_config_byte(0, bus, dev, func, offset, val));
154}
155
156int pci_bsp_write_config_word(unchar bus, unchar dev,
157unchar func, unchar offset, unsigned short val)
158{
159  return(PCIx_write_config_word(0, bus, dev, func, offset, val));
160}
161
162int pci_bsp_write_config_dword(unchar bus,unchar dev,
163unchar func, unchar offset, unsigned int val)
164{
165  return(PCIx_write_config_dword(0, bus, dev, func, offset, val));
166}
167
168
169pci_bsp_config BSP_pci_config[2] = {
170  {PCI0_CONFIG_ADDR,PCI0_CONFIG_DATA/*,&pci_functions*/},
171       {PCI1_CONFIG_ADDR,PCI1_CONFIG_DATA/*,&pci_functions*/}
172};
173
174/*
175 * This routine determines the maximum bus number in the system
176 */
177int pci_initialize()
178{
179  int PciNumber;
180  unchar ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs;
181  unsigned int ulHeader;
182  unsigned int pcidata, ulDeviceID;
183#if PCI_DEBUG
184  unsigned int data, pcidata, ulClass;
185  unsigned short sdata;
186#endif
187
188  PCI_interface();
189 
190  /*
191   * Scan PCI0 and PCI1 bus0
192   */
193  for (PciNumber=0; PciNumber < 2; PciNumber++) {
194    pciAccessInit(PciNumber);
195    for (ucBusNumber=0; ucBusNumber< 2; ucBusNumber++) {
196    for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
197      ucFnNumber = 0;
198      PCIx_read_config_dword(PciNumber, ucBusNumber,
199                                ucSlotNumber,
200                                0,
201                                PCI0_VENDOR_ID,
202                                &ulDeviceID);
203
204      if( ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
205        /* This slot is empty */
206        continue;
207      }
208
209      if (++numPCIDevs > MAX_NUM_PCI_DEVICES) {
210         BSP_panic("Too many PCI devices found; increase MAX_NUM_PCI_DEVICES in pcicache.c\n");
211      }
212
213      switch(ulDeviceID) {
214        case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT6426xAB<<16)):
215#if PCI_PRINT
216          printk("Marvell GT6426xA/B hostbridge detected at PCI%d bus%d slot%d\n",
217                 PciNumber,ucBusNumber,ucSlotNumber);
218#endif
219          ucMaxPCIBus ++;
220          break;
221        case (PCI_VENDOR_ID_PLX2+(PCI_DEVICE_ID_PLX2_PCI6154_HB2<<16)):
222#if PCI_PRINT
223          printk("PLX PCI6154 PCI-PCI bridge detected at PCI%d bus%d slot%d\n",
224                 PciNumber,ucBusNumber,ucSlotNumber);
225#endif
226          ucMaxPCIBus ++;
227          break;
228        case PCI_VENDOR_ID_TUNDRA:
229#if PCI_PRINT
230          printk("TUNDRA PCI-VME bridge detected at PCI%d bus%d slot%d\n",
231                 PciNumber,ucBusNumber,ucSlotNumber);
232#endif
233          ucMaxPCIBus ++;
234          break;
235      case (PCI_VENDOR_ID_INTEL+(PCI_DEVICE_INTEL_82544EI_COPPER<<16)):
236#if PCI_PRINT
237          printk("INTEL 82544EI COPPER network controller detected at PCI%d bus%d slot%d\n",
238                 PciNumber,ucBusNumber,ucSlotNumber);
239#endif
240          ucMaxPCIBus ++;
241          break;
242        default :
243#if PCI_PRINT
244          printk("PCI%d Bus%d Slot%d DeviceID 0x%x \n",
245             PciNumber,ucBusNumber,ucSlotNumber, ulDeviceID);
246#endif
247          break;
248      }
249#if PCI_DEBUG
250      PCIx_read_config_dword(PciNumber, ucBusNumber,
251                          ucSlotNumber,
252                          0,
253                          PCI0_BASE_ADDRESS_0,
254                          &data);
255      printk("PCI%d_BASE_ADDRESS_0 0x%x \n",PciNumber, data); 
256      PCIx_read_config_dword(PciNumber, ucBusNumber,
257                          ucSlotNumber,
258                          0,
259                          PCI0_BASE_ADDRESS_1,
260                          &data);
261      printk("PCI%d_BASE_ADDRESS_1 0x%x \n",PciNumber, data);
262      PCIx_read_config_dword(PciNumber, ucBusNumber,
263                          ucSlotNumber,
264                          0,
265                          PCI0_BASE_ADDRESS_2,
266                          &data);
267      printk("PCI%d_BASE_ADDRESS_2 0x%x \n",PciNumber, data);
268
269      PCIx_read_config_dword(PciNumber, ucBusNumber,
270                          ucSlotNumber,
271                          0,
272                          PCI0_BASE_ADDRESS_3,
273                          &data);
274      printk("PCI%d_BASE_ADDRESS_3 0x%x \n",PciNumber, data); 
275
276     PCIx_read_config_word(PciNumber, ucBusNumber,
277                          ucSlotNumber,
278                          0,
279                          PCI0_INTERRUPT_LINE,
280                          &sdata);
281      printk("PCI%d_INTERRUPT_LINE 0x%x \n",PciNumber, sdata); 
282
283      /* We always enable internal memory. */
284      PCIx_read_config_dword(PciNumber, ucBusNumber,
285                          ucSlotNumber,
286                          0,
287                          PCI0_MEM_BASE_ADDR,
288                          &pcidata);
289      printk("PCI%d_MEM_BASE_ADDR 0x%x \n", PciNumber,pcidata);
290
291      /* We always enable internal IO. */
292      PCIx_read_config_dword(PciNumber, ucBusNumber,
293                          ucSlotNumber,
294                          0,
295                          PCI0_IO_BASE_ADDR,
296                          &pcidata);
297      printk("PCI%d_IO_BASE_ADDR 0x%x \n", PciNumber,pcidata);
298#endif
299
300      PCIx_read_config_dword(PciNumber, ucBusNumber,
301                          ucSlotNumber,
302                          0,
303                          PCI0_CACHE_LINE_SIZE,
304                          &ulHeader);
305      if ((ulHeader>>16)&PCI_MULTI_FUNCTION)
306         ucNumFuncs=PCI_MAX_FUNCTIONS;
307      else
308         ucNumFuncs=1;
309
310#if PCI_DEBUG
311      printk("PCI%d Slot 0x%x HEADER/LAT/CACHE 0x%x \n",
312             PciNumber,ucSlotNumber, ulHeader);   
313
314      for (ucFnNumber=1;ucFnNumber<ucNumFuncs;ucFnNumber++) {
315          PCIx_read_config_dword(PciNumber, ucBusNumber,
316                                  ucSlotNumber,
317                                  ucFnNumber,
318                                  PCI0_VENDOR_ID,
319                                  &ulDeviceID);
320          if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
321             /* This slot/function is empty */
322             continue;
323          }
324          if (++numPCIDevs > MAX_NUM_PCI_DEVICES) {
325             BSP_panic("Too many PCI devices found; increase MAX_NUM_PCI_DEVICES in pcicache.c\n");
326          }
327
328         /* This slot/function has a device fitted.*/
329         PCIx_read_config_dword(PciNumber, ucBusNumber,
330                                  ucSlotNumber,
331                                  ucFnNumber,
332                                  PCI0_CLASS_REVISION,
333                                  &ulClass);     
334         printk("PCI%d Slot 0x%x Func %d classID 0x%x \n",PciNumber,ucSlotNumber,
335             ucFnNumber, ulClass);
336
337         ulClass >>= 16;
338         if (ulClass == PCI_CLASS_GT6426xAB)
339            printk("GT64260-PCI%d bridge found \n", PciNumber);
340      }
341#endif
342      PCIx_read_config_dword(PciNumber, ucBusNumber,
343                               ucSlotNumber,
344                               0,
345                          PCI0_COMMAND,
346                          &pcidata);
347#if PCI_DEBUG
348      printk("MOTLoad command staus 0x%x, ", pcidata);
349#endif
350      /* Clear the error on the host bridge */
351      if ( (ucBusNumber==0) && (ucSlotNumber==0))
352        pcidata |= PCI_STATUS_CLRERR_MASK;
353      /* Enable bus,I/O and memory master access. */
354      pcidata |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY);
355      PCIx_write_config_dword(PciNumber, ucBusNumber,
356                               ucSlotNumber,
357                               0,
358                          PCI0_COMMAND,
359                          pcidata);
360
361      PCIx_read_config_dword(PciNumber, ucBusNumber,
362                               ucSlotNumber,
363                               0,
364                          PCI0_COMMAND,
365                          &pcidata);
366#if PCI_DEBUG     
367      printk("Now command/staus 0x%x\n", pcidata);
368#endif
369 
370    }
371    }
372  } /* PCI number */
373
374  return PCIB_ERR_SUCCESS;
375}
376
377/*
378 * Return the number of PCI buses in the system
379 */
380unsigned char pci_bus_count()
381{
382  return(ucMaxPCIBus);
383}
384
Note: See TracBrowser for help on using the repository browser.