source: rtems/c/src/lib/libbsp/powerpc/mcp750/pci/pci.c @ fcee56c0

4.104.114.84.95
Last change on this file since fcee56c0 was fcee56c0, checked in by Joel Sherrill <joel.sherrill@…>, on 07/01/99 at 23:39:13

Patch from Eric Valette <valette@…> to clean up the
previous submission.

  • 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 found in the file LICENSE in this distribution or at
14 *  http://www.OARcorp.com/rtems/license.html.
15 *
16 *  $Id$
17 */
18
19#include <bsp/consoleIo.h>
20#include <libcpu/io.h>
21#include <bsp/pci.h>
22#include <bsp/residual.h>
23#include <bsp/openpic.h>
24
25#define PCI_CONFIG_ADDR                 0xcf8
26#define PCI_CONFIG_DATA                 0xcfc
27#define PCI_INVALID_VENDORDEVICEID      0xffffffff
28#define PCI_MULTI_FUNCTION              0x80
29#define RAVEN_MPIC_IOSPACE_ENABLE       0x1
30#define RAVEN_MPIC_MEMSPACE_ENABLE      0x2
31#define RAVEN_MASTER_ENABLE             0x4
32#define RAVEN_PARITY_CHECK_ENABLE       0x40
33#define RAVEN_SYSTEM_ERROR_ENABLE       0x100
34#define RAVEN_CLEAR_EVENTS_MASK         0xf9000000
35
36
37/*
38 * Bit encode for PCI_CONFIG_HEADER_TYPE register
39 */
40unsigned char ucMaxPCIBus;
41
42static int
43indirect_pci_read_config_byte(unsigned char bus, unsigned char slot,
44                              unsigned char function,
45                              unsigned char offset, unsigned char *val) {
46        out_be32((unsigned int*) pci.pci_config_addr,
47                 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
48        *val = in_8(pci.pci_config_data + (offset&3));
49        return PCIBIOS_SUCCESSFUL;
50}
51
52static int
53indirect_pci_read_config_word(unsigned char bus, unsigned char slot,
54                              unsigned char function,
55                              unsigned char offset, unsigned short *val) {
56        *val = 0xffff;
57        if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
58        out_be32((unsigned int*) pci.pci_config_addr,
59                 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
60        *val = in_le16((volatile unsigned short *)(pci.pci_config_data + (offset&3)));
61        return PCIBIOS_SUCCESSFUL;
62}
63
64static int
65indirect_pci_read_config_dword(unsigned char bus, unsigned char slot,
66                              unsigned char function,
67                              unsigned char offset, unsigned int *val) {
68        *val = 0xffffffff;
69        if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
70        out_be32((unsigned int*) pci.pci_config_addr,
71                 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|(offset<<24));
72        *val = in_le32((volatile unsigned int *)pci.pci_config_data);
73        return PCIBIOS_SUCCESSFUL;
74}
75
76static int
77indirect_pci_write_config_byte(unsigned char bus, unsigned char slot,
78                               unsigned char function,
79                               unsigned char offset, unsigned char val) {
80        out_be32((unsigned int*) pci.pci_config_addr,
81                 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
82        out_8(pci.pci_config_data + (offset&3), val);
83        return PCIBIOS_SUCCESSFUL;
84}
85
86static int
87indirect_pci_write_config_word(unsigned char bus, unsigned char slot,
88                               unsigned char function,
89                               unsigned char offset, unsigned short val) {
90        if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
91        out_be32((unsigned int*) pci.pci_config_addr,
92                 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
93        out_le16((volatile unsigned short *)(pci.pci_config_data + (offset&3)), val);
94        return PCIBIOS_SUCCESSFUL;
95}
96
97static int
98indirect_pci_write_config_dword(unsigned char bus, unsigned char slot,
99                                unsigned char function,
100                                unsigned char offset, unsigned int val) {
101        if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
102        out_be32((unsigned int*) pci.pci_config_addr,
103                 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|(offset<<24));
104        out_le32((volatile unsigned int *)pci.pci_config_data, val);
105        return PCIBIOS_SUCCESSFUL;
106}
107
108static const pci_config_access_functions indirect_functions = {
109        indirect_pci_read_config_byte,
110        indirect_pci_read_config_word,
111        indirect_pci_read_config_dword,
112        indirect_pci_write_config_byte,
113        indirect_pci_write_config_word,
114        indirect_pci_write_config_dword
115};
116
117pci_config pci = {(volatile unsigned char*)PCI_CONFIG_ADDR,
118                         (volatile unsigned char*)PCI_CONFIG_DATA,
119                         &indirect_functions};
120
121static int
122direct_pci_read_config_byte(unsigned char bus, unsigned char slot,
123                            unsigned char function,
124                            unsigned char offset, unsigned char *val) {
125        if (bus != 0 || (1<<slot & 0xff8007fe)) {
126                *val=0xff;
127                return PCIBIOS_DEVICE_NOT_FOUND;
128        }
129        *val=in_8(pci.pci_config_data + ((1<<slot)&~1)
130                  + (function<<8) + offset);
131        return PCIBIOS_SUCCESSFUL;
132}
133
134static int
135direct_pci_read_config_word(unsigned char bus, unsigned char slot,
136                            unsigned char function,
137                            unsigned char offset, unsigned short *val) {
138        *val = 0xffff;
139        if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
140        if (bus != 0 || (1<<slot & 0xff8007fe)) {
141                return PCIBIOS_DEVICE_NOT_FOUND;
142        }
143        *val=in_le16((volatile unsigned short *)
144                     (pci.pci_config_data + ((1<<slot)&~1)
145                      + (function<<8) + offset));
146        return PCIBIOS_SUCCESSFUL;
147}
148
149static int
150direct_pci_read_config_dword(unsigned char bus, unsigned char slot,
151                             unsigned char function,
152                             unsigned char offset, unsigned int *val) {
153        *val = 0xffffffff;
154        if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
155        if (bus != 0 || (1<<slot & 0xff8007fe)) {
156                return PCIBIOS_DEVICE_NOT_FOUND;
157        }
158        *val=in_le32((volatile unsigned int *)
159                     (pci.pci_config_data + ((1<<slot)&~1)
160                      + (function<<8) + offset));
161        return PCIBIOS_SUCCESSFUL;
162}
163
164static int
165direct_pci_write_config_byte(unsigned char bus, unsigned char slot,
166                             unsigned char function,
167                             unsigned char offset, unsigned char val) {
168        if (bus != 0 || (1<<slot & 0xff8007fe)) {
169                return PCIBIOS_DEVICE_NOT_FOUND;
170        }
171        out_8(pci.pci_config_data + ((1<<slot)&~1)
172              + (function<<8) + offset,
173              val);
174        return PCIBIOS_SUCCESSFUL;
175}
176
177static int
178direct_pci_write_config_word(unsigned char bus, unsigned char slot,
179                             unsigned char function,
180                             unsigned char offset, unsigned short val) {
181        if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
182        if (bus != 0 || (1<<slot & 0xff8007fe)) {
183                return PCIBIOS_DEVICE_NOT_FOUND;
184        }
185        out_le16((volatile unsigned short *)
186                 (pci.pci_config_data + ((1<<slot)&~1)
187                  + (function<<8) + offset),
188                 val);
189        return PCIBIOS_SUCCESSFUL;
190}
191
192static int
193direct_pci_write_config_dword(unsigned char bus, unsigned char slot,
194                              unsigned char function,
195                              unsigned char offset, unsigned int val) {
196        if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
197        if (bus != 0 || (1<<slot & 0xff8007fe)) {
198                return PCIBIOS_DEVICE_NOT_FOUND;
199        }
200        out_le32((volatile unsigned int *)
201                 (pci.pci_config_data + ((1<<slot)&~1)
202                  + (function<<8) + offset),
203                 val);
204        return PCIBIOS_SUCCESSFUL;
205}
206
207static const pci_config_access_functions direct_functions = {
208        direct_pci_read_config_byte,
209        direct_pci_read_config_word,
210        direct_pci_read_config_dword,
211        direct_pci_write_config_byte,
212        direct_pci_write_config_word,
213        direct_pci_write_config_dword
214};
215
216
217void detect_host_bridge()
218{
219  PPC_DEVICE *hostbridge;
220  unsigned int id0;
221  unsigned int tmp;
222 
223  /*
224   * This code assumes that the host bridge is located at
225   * bus 0, dev 0, func 0 AND that the old pre PCI 2.1
226   * standart devices detection mecahnism that was used on PC
227   * (still used in BSD source code) works.
228   */
229  hostbridge=residual_find_device(&residualCopy, PROCESSORDEVICE, NULL,
230                                  BridgeController,
231                                  PCIBridge, -1, 0);
232  if (hostbridge) {
233    if (hostbridge->DeviceId.Interface==PCIBridgeIndirect) {
234      pci.pci_functions=&indirect_functions;
235      /* Should be extracted from residual data,
236       * indeed MPC106 in CHRP mode is different,
237       * but we should not use residual data in
238       * this case anyway.
239       */
240      pci.pci_config_addr = ((volatile unsigned char *)
241                              (ptr_mem_map->io_base+0xcf8));
242      pci.pci_config_data = ptr_mem_map->io_base+0xcfc;
243    } else if(hostbridge->DeviceId.Interface==PCIBridgeDirect) {
244      pci.pci_functions=&direct_functions;
245      pci.pci_config_data=(unsigned char *) 0x80800000;
246    } else {
247    }
248  } else {
249    /* Let us try by experimentation at our own risk! */
250    pci.pci_functions = &direct_functions;
251    /* On all direct bridges I know the host bridge itself
252     * appears as device 0 function 0.
253                 */
254    pci_read_config_dword(0, 0, 0, PCI_VENDOR_ID, &id0);
255    if (id0==~0U) {
256      pci.pci_functions = &indirect_functions;
257      pci.pci_config_addr = ((volatile unsigned char*)
258                              (ptr_mem_map->io_base+0xcf8));
259      pci.pci_config_data = ((volatile unsigned char*)ptr_mem_map->io_base+0xcfc);
260    }
261    /* Here we should check that the host bridge is actually
262     * present, but if it not, we are in such a desperate
263     * situation, that we probably can't even tell it.
264     */
265  }
266  pci_read_config_dword(0, 0, 0, 0, &id0);
267  if(id0 == PCI_VENDOR_ID_MOTOROLA +
268     (PCI_DEVICE_ID_MOTOROLA_RAVEN<<16)) {
269    /*
270     * We have a Raven bridge. We will get information about its settings
271     */
272    pci_read_config_dword(0, 0, 0, PCI_COMMAND, &id0);
273    printk("RAVEN PCI command register = %x\n",id0);
274    id0 |= RAVEN_CLEAR_EVENTS_MASK;
275    pci_write_config_dword(0, 0, 0, PCI_COMMAND, id0);
276    pci_read_config_dword(0, 0, 0, PCI_COMMAND, &id0);
277    printk("After error clearing RAVEN PCI command register = %x\n",id0);
278   
279    if (id0 & RAVEN_MPIC_IOSPACE_ENABLE) {
280      pci_read_config_dword(0, 0, 0,PCI_BASE_ADDRESS_0, &tmp);
281      printk("Raven MPIC is accessed via IO Space Access at address : %x\n",(tmp & ~0x1));
282    }
283    if (id0 & RAVEN_MPIC_MEMSPACE_ENABLE) {
284      pci_read_config_dword(0, 0, 0,PCI_BASE_ADDRESS_1, &tmp);
285      printk("Raven MPIC is accessed via memory Space Access at address : %x\n", tmp);
286      OpenPIC=(volatile struct OpenPIC *) (tmp + PREP_ISA_MEM_BASE);
287      printk("OpenPIC found at %p.\n",
288             OpenPIC);
289    }
290  }
291  else {
292    BSP_panic("OpenPic Not found\n");
293  }
294
295}
296
297/*
298 * This routine determines the maximum bus number in the system
299 */
300void InitializePCI()
301{
302  unsigned char ucSlotNumber, ucFnNumber, ucNumFuncs;
303  unsigned char ucHeader;
304  unsigned char ucMaxSubordinate;
305  unsigned int  ulClass, ulDeviceID;
306
307  detect_host_bridge();
308  /*
309   * Scan PCI bus 0 looking for PCI-PCI bridges
310   */
311  for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
312    (void)pci_read_config_dword(0,
313                                ucSlotNumber,
314                                0,
315                                PCI_VENDOR_ID,
316                                &ulDeviceID);
317    if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
318      /*
319       * This slot is empty
320       */
321      continue;
322    }
323    (void)pci_read_config_byte(0,
324                               ucSlotNumber,
325                               0,
326                               PCI_HEADER_TYPE,
327                               &ucHeader);
328    if(ucHeader&PCI_MULTI_FUNCTION)     {
329      ucNumFuncs=PCI_MAX_FUNCTIONS;
330    }
331    else {
332      ucNumFuncs=1;
333    }
334    for(ucFnNumber=0;ucFnNumber<ucNumFuncs;ucFnNumber++) {
335      (void)pci_read_config_dword(0,
336                                  ucSlotNumber,
337                                  ucFnNumber,
338                                  PCI_VENDOR_ID,
339                                  &ulDeviceID);
340      if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
341                                /*
342                                 * This slot/function is empty
343                                 */
344        continue;
345      }
346
347      /*
348       * This slot/function has a device fitted.
349       */
350      (void)pci_read_config_dword(0,
351                                  ucSlotNumber,
352                                  ucFnNumber,
353                                  PCI_CLASS_REVISION,
354                                  &ulClass);
355      ulClass >>= 16;
356      if (ulClass == PCI_CLASS_BRIDGE_PCI) {
357                                /*
358                                 * We have found a PCI-PCI bridge
359                                 */
360        (void)pci_read_config_byte(0,
361                                   ucSlotNumber,
362                                   ucFnNumber,
363                                   PCI_SUBORDINATE_BUS,
364                                   &ucMaxSubordinate);
365        if(ucMaxSubordinate>ucMaxPCIBus) {
366          ucMaxPCIBus=ucMaxSubordinate;
367        }
368      }
369    }
370  }
371}
372
373/*
374 * Return the number of PCI busses in the system
375 */
376unsigned char BusCountPCI()
377{
378  return(ucMaxPCIBus+1);
379}
Note: See TracBrowser for help on using the repository browser.