source: rtems/c/src/lib/libbsp/powerpc/shared/pci/pci.c @ acc25ee

4.104.114.84.95
Last change on this file since acc25ee was acc25ee, checked in by Joel Sherrill <joel.sherrill@…>, on Dec 2, 1999 at 2:31:19 PM

Merged of mcp750 and mvme2307 BSP by Eric Valette <valette@…>.
As part of this effort, the mpc750 libcpu code is now shared with the
ppc6xx.

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