source: rtems/bsps/powerpc/mvme5500/pci/pci.c @ a72419b

Last change on this file since a72419b was caccc5b, checked in by Sebastian Huber <sebastian.huber@…>, on 07/24/18 at 09:35:09

bsps: Fix function declaration warnings

  • Property mode set to 100644
File size: 11.9 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.org/rtems/license.html.
15 *
16 *  Copyright 2004, 2008 Brookhaven National Laboratory and
17 *                  Shuchen K. Feng, <feng1@bnl.gov>
18 *
19 *   - to be consistent with the original pci.c written by Eric Valette
20 *   - added 2nd PCI support for discovery based PCI bridge (e.g. mvme5500/mvme6100)
21 *   - added bus support for the expansion of PMCSpan as per request by Peter
22 */
23#define PCI_MAIN
24
25#include <libcpu/io.h>
26#include <rtems/bspIo.h>            /* printk */
27
28#include <bsp/irq.h>
29#include <bsp/pci.h>
30#include <bsp/gtreg.h>
31#include <bsp/gtpcireg.h>
32#include <bsp.h>
33
34#include <stdio.h>
35#include <string.h>
36#include <inttypes.h>
37
38#define PCI_DEBUG 0
39#define PCI_PRINT 1
40
41/* allow for overriding these definitions */
42#ifndef PCI_CONFIG_ADDR
43#define PCI_CONFIG_ADDR                 0xcf8
44#endif
45#ifndef PCI_CONFIG_DATA
46#define PCI_CONFIG_DATA                 0xcfc
47#endif
48
49#ifndef PCI1_CONFIG_ADDR
50#define PCI1_CONFIG_ADDR                0xc78
51#endif
52#ifndef PCI1_CONFIG_DATA
53#define PCI1_CONFIG_DATA                0xc7c
54#endif
55
56#define HOSTBRIDGET_ERROR               0xf0000000
57
58#define GT64x60_PCI_CONFIG_ADDR         GT64x60_REG_BASE + PCI_CONFIG_ADDR
59#define GT64x60_PCI_CONFIG_DATA         GT64x60_REG_BASE + PCI_CONFIG_DATA
60
61#define GT64x60_PCI1_CONFIG_ADDR        GT64x60_REG_BASE + PCI1_CONFIG_ADDR
62#define GT64x60_PCI1_CONFIG_DATA        GT64x60_REG_BASE + PCI1_CONFIG_DATA
63
64static int      numPCIDevs=0;
65static DiscoveryChipVersion BSP_sysControllerVersion = 0;
66static BSP_VMEchipTypes BSP_VMEinterface = 0;
67static rtems_pci_config_t BSP_pci[2]={
68  {(volatile unsigned char*) (GT64x60_PCI_CONFIG_ADDR),
69   (volatile unsigned char*) (GT64x60_PCI_CONFIG_DATA),
70   0 /* defined at BSP_pci_configuration */},
71  {(volatile unsigned char*) (GT64x60_PCI1_CONFIG_ADDR),
72   (volatile unsigned char*) (GT64x60_PCI1_CONFIG_DATA),
73   0 /* defined at BSP_pci_configuration */}
74};
75
76/* Pack RegNum,FuncNum,DevNum,BusNum,and ConfigEnable for
77 * PCI Configuration Address Register
78 */
79#define pciConfigPack(bus,dev,func,offset)\
80((offset&~3)<<24)|(PCI_DEVFN(dev,func)<<16)|(bus<<8)|0x80
81
82/*
83 * Bit encode for PCI_CONFIG_HEADER_TYPE register
84 */
85static unsigned char ucMaxPCIBus=0;
86
87/* Please note that PCI0 and PCI1 does not correlate with the busNum 0 and 1.
88 */
89static int indirect_pci_read_config_byte(unsigned char bus,unsigned char dev,unsigned char func,
90unsigned char offset, uint8_t *val)
91{
92  int n=0;
93
94  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
95     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
96     n=1;
97  }
98
99  *val = 0xff;
100  if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
101#if 0
102  printk("addr %x, data %x, pack %x \n", BSP_pci[n].pci_config_addr),
103    BSP_pci[n].config_data,pciConfigPack(bus,dev,func,offset));
104#endif
105
106  out_be32((volatile uint32_t *) BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
107  *val = in_8(BSP_pci[n].pci_config_data + (offset&3));
108  return PCIBIOS_SUCCESSFUL;
109}
110
111static int indirect_pci_read_config_word(unsigned char bus, unsigned char dev,
112unsigned char func, unsigned char offset, uint16_t *val)
113{
114  int n=0;
115
116  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
117     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
118     n=1;
119  }
120
121  *val = 0xffff;
122  if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
123#if 0
124  printk("addr %x, data %x, pack %x \n", config_addr,
125    config_data,pciConfigPack(bus,dev,func,offset));
126#endif
127  out_be32((volatile uint32_t *) BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
128  *val = in_le16((volatile uint16_t *) (BSP_pci[n].pci_config_data + (offset&2)));
129  return PCIBIOS_SUCCESSFUL;
130}
131
132static int indirect_pci_read_config_dword(unsigned char bus, unsigned char dev,
133unsigned char func, unsigned char offset, uint32_t *val)
134{
135  int n=0;
136
137  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
138     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
139     n=1;
140  }
141
142  *val = 0xffffffff;
143  if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
144
145  out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
146  *val = in_le32((volatile uint32_t *)BSP_pci[n].pci_config_data);
147  return PCIBIOS_SUCCESSFUL;
148}
149
150static int indirect_pci_write_config_byte(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, uint8_t val)
151{
152  int n=0;
153
154  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
155     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
156     n=1;
157  }
158
159  if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
160
161  out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
162  out_8((volatile uint8_t *) (BSP_pci[n].pci_config_data + (offset&3)), val);
163  return PCIBIOS_SUCCESSFUL;
164}
165
166static int indirect_pci_write_config_word(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, uint16_t val)
167{
168  int n=0;
169
170  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
171     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
172     n=1;
173  }
174
175  if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
176
177  out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
178  out_le16((volatile uint16_t *)(BSP_pci[n].pci_config_data + (offset&3)), val);
179  return PCIBIOS_SUCCESSFUL;
180}
181
182static int indirect_pci_write_config_dword(unsigned char bus,unsigned char dev,unsigned char func, unsigned char offset, uint32_t val)
183{
184  int n=0;
185
186  if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
187     bus-=BSP_MAX_PCI_BUS_ON_PCI0;
188     n=1;
189  }
190
191  if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
192
193  out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
194  out_le32((volatile uint32_t *)BSP_pci[n].pci_config_data, val);
195  return PCIBIOS_SUCCESSFUL;
196}
197
198const pci_config_access_functions pci_indirect_functions = {
199        indirect_pci_read_config_byte,
200        indirect_pci_read_config_word,
201        indirect_pci_read_config_dword,
202        indirect_pci_write_config_byte,
203        indirect_pci_write_config_word,
204        indirect_pci_write_config_dword
205};
206
207
208rtems_pci_config_t BSP_pci_configuration = {
209           (volatile unsigned char*) (GT64x60_PCI_CONFIG_ADDR),
210           (volatile unsigned char*) (GT64x60_PCI_CONFIG_DATA),
211           &pci_indirect_functions};
212
213DiscoveryChipVersion BSP_getDiscoveryChipVersion(void)
214{
215  return(BSP_sysControllerVersion);
216}
217
218BSP_VMEchipTypes BSP_getVMEchipType(void)
219{
220  return(BSP_VMEinterface);
221}
222
223/*
224 * This routine determines the maximum bus number in the system.
225 * The PCI_SUBORDINATE_BUS is not supported in GT6426xAB. Thus,
226 * it's not used.
227 *
228 */
229int pci_initialize(void)
230{
231  int deviceFound;
232  unsigned char ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs, data8;
233  uint32_t ulHeader, ulClass, ulDeviceID;
234#if PCI_DEBUG
235  uint32_t pcidata;
236#endif
237
238  /*
239   * Scan PCI0 and PCI1 buses
240   */
241  for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ucBusNumber++) {
242    deviceFound=0;
243    for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
244      ucFnNumber = 0;
245      pci_read_config_dword(ucBusNumber,
246                                ucSlotNumber,
247                                0,
248                                PCI_VENDOR_ID,
249                                &ulDeviceID);
250
251      if( ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
252        /* This slot is empty */
253        continue;
254      }
255
256      if (++numPCIDevs > PCI_MAX_DEVICES) {
257         rtems_panic("Too many PCI devices found; increase PCI_MAX_DEVICES in pci.h\n");
258      }
259
260      if (!deviceFound) deviceFound=1;
261      switch(ulDeviceID) {
262        case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT6426xAB<<16)):
263          pci_read_config_byte(0,0,0,PCI_REVISION_ID, &data8);
264          switch(data8) {
265          case 0x10:
266            BSP_sysControllerVersion = GT64260A;
267#if PCI_PRINT
268            printk("Marvell GT64260A (Discovery I) hostbridge detected at bus%d slot%d\n",
269                 ucBusNumber,ucSlotNumber);
270#endif
271            break;
272          case 0x20:
273            BSP_sysControllerVersion = GT64260B;
274#if PCI_PRINT
275            printk("Marvell GT64260B (Discovery I) hostbridge detected at bus%d slot%d\n",
276                 ucBusNumber,ucSlotNumber);
277#endif
278            break;
279          default:
280            printk("Undefined revsion of GT64260 chip\n");
281            break;
282          }
283          break;
284        case PCI_VENDOR_ID_TUNDRA:
285#if PCI_PRINT
286          printk("TUNDRA PCI-VME bridge detected at bus%d slot%d\n",
287                 ucBusNumber,ucSlotNumber);
288#endif
289          break;
290      case (PCI_VENDOR_ID_DEC+(PCI_DEVICE_ID_DEC_21150<<16)):
291#if PCI_PRINT
292          printk("DEC21150 PCI-PCI bridge detected at bus%d slot%d\n",
293                 ucBusNumber,ucSlotNumber);
294#endif
295          break;
296       default :
297#if PCI_PRINT
298          printk("BSP unlisted vendor, Bus%d Slot%d DeviceID 0x%" PRIx32 "\n",
299             ucBusNumber,ucSlotNumber, ulDeviceID);
300#endif
301          /* Kate Feng : device not supported by BSP needs to remap the IRQ line on mvme5500/mvme6100 */
302          pci_read_config_byte(ucBusNumber,ucSlotNumber,0,PCI_INTERRUPT_LINE,&data8);
303          if (data8 < BSP_GPP_IRQ_LOWEST_OFFSET)  pci_write_config_byte(ucBusNumber,
304             ucSlotNumber,0,PCI_INTERRUPT_LINE,BSP_GPP_IRQ_LOWEST_OFFSET+data8);
305
306          break;
307      }
308
309#if PCI_DEBUG
310      pci_read_config_dword(ucBusNumber,
311                          ucSlotNumber,
312                          0,
313                          PCI_BASE_ADDRESS_0,
314                          &data);
315      printk("Bus%d BASE_ADDRESS_0 0x%x \n",ucBusNumber, data);
316      pci_read_config_dword(ucBusNumber,
317                          ucSlotNumber,
318                          0,
319                          PCI_BASE_ADDRESS_1,
320                          &data);
321      printk("Bus%d BASE_ADDRESS_1 0x%x \n",ucBusNumber, data);
322      pci_read_config_dword(ucBusNumber,
323                          ucSlotNumber,
324                          0,
325                          PCI_BASE_ADDRESS_2,
326                          &data);
327      printk("Bus%d BASE_ADDRESS_2 0x%x \n", ucBusNumber, data);
328
329      pci_read_config_dword(ucBusNumber,
330                          ucSlotNumber,
331                          0,
332                          PCI_BASE_ADDRESS_3,
333                          &data);
334      printk("Bus%d BASE_ADDRESS_3 0x%x \n", ucBusNumber, data);
335
336      pci_read_config_word(ucBusNumber,
337                          ucSlotNumber,
338                          0,
339                          PCI_INTERRUPT_LINE,
340                          &sdata);
341      printk("Bus%d INTERRUPT_LINE 0x%x \n", ucBusNumber, sdata);
342
343      /* We always enable internal memory. */
344      pci_read_config_dword(ucBusNumber,
345                          ucSlotNumber,
346                          0,
347                          PCI_MEM_BASE_ADDR,
348                          &pcidata);
349      printk("Bus%d MEM_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
350
351      /* We always enable internal IO. */
352      pci_read_config_dword(ucBusNumber,
353                          ucSlotNumber,
354                          0,
355                          PCI_IO_BASE_ADDR,
356                          &pcidata);
357      printk("Bus%d IO_BASE_ADDR 0x%x \n", ucBusNumber,pcidata);
358#endif
359
360      pci_read_config_dword(ucBusNumber,
361                          ucSlotNumber,
362                          0,
363                          PCI_CACHE_LINE_SIZE,
364                          &ulHeader);
365      if ((ulHeader>>16)&PCI_HEADER_TYPE_MULTI_FUNCTION)
366         ucNumFuncs=PCI_MAX_FUNCTIONS;
367      else
368         ucNumFuncs=1;
369
370#if PCI_DEBUG
371      printk("Bus%d Slot 0x%x HEADER/LAT/CACHE 0x%x \n",
372             ucBusNumber, ucSlotNumber, ulHeader);
373#endif
374
375      for (ucFnNumber=1;ucFnNumber<ucNumFuncs;ucFnNumber++) {
376          pci_read_config_dword(ucBusNumber,
377                                  ucSlotNumber,
378                                  ucFnNumber,
379                                  PCI_VENDOR_ID,
380                                  &ulDeviceID);
381          if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
382             /* This slot/function is empty */
383             continue;
384          }
385
386         /* This slot/function has a device fitted.*/
387         pci_read_config_dword(ucBusNumber,
388                                  ucSlotNumber,
389                                  ucFnNumber,
390                                  PCI_CLASS_REVISION,
391                                  &ulClass);
392#if PCI_DEBUG
393         printk("Bus%d Slot 0x%x Func %d classID 0x%x \n",ucBusNumber,ucSlotNumber,
394             ucFnNumber, ulClass);
395#endif
396
397      }
398    }
399    if (deviceFound) ucMaxPCIBus++;
400  } /* for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ... */
401#if PCI_DEBUG
402  printk("number of PCI buses: %d, numPCIDevs %d\n",
403         pci_bus_count(), numPCIDevs);
404#endif
405  pci_interface();
406  return(0);
407}
408
409void FixupPCI( const struct _int_map *bspmap, int (*swizzler)(int,int) )
410{
411}
412
413/*
414 * Return the number of PCI buses in the system
415 */
416unsigned char pci_bus_count(void)
417{
418  return(ucMaxPCIBus);
419}
420
Note: See TracBrowser for help on using the repository browser.