From acc25eec35e186abc118b9ca4f097e22fc6b4846 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 2 Dec 1999 14:31:19 +0000 Subject: Merged of mcp750 and mvme2307 BSP by Eric Valette . As part of this effort, the mpc750 libcpu code is now shared with the ppc6xx. --- c/src/lib/libbsp/powerpc/shared/pci/pci.c | 388 ++++++++++++++++++++++++++++++ 1 file changed, 388 insertions(+) create mode 100644 c/src/lib/libbsp/powerpc/shared/pci/pci.c (limited to 'c/src/lib/libbsp/powerpc/shared/pci/pci.c') diff --git a/c/src/lib/libbsp/powerpc/shared/pci/pci.c b/c/src/lib/libbsp/powerpc/shared/pci/pci.c new file mode 100644 index 0000000000..233a2efc00 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/shared/pci/pci.c @@ -0,0 +1,388 @@ +/* + * pci.c : this file contains basic PCI Io functions. + * + * CopyRight (C) 1999 valette@crf.canon.fr + * + * This code is heavilly inspired by the public specification of STREAM V2 + * that can be found at : + * + * by following + * the STREAM API Specification Document link. + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include +#include +#include +#include +#include +#include + +#define PCI_CONFIG_ADDR 0xcf8 +#define PCI_CONFIG_DATA 0xcfc +#define PCI_INVALID_VENDORDEVICEID 0xffffffff +#define PCI_MULTI_FUNCTION 0x80 +#define RAVEN_MPIC_IOSPACE_ENABLE 0x1 +#define RAVEN_MPIC_MEMSPACE_ENABLE 0x2 +#define RAVEN_MASTER_ENABLE 0x4 +#define RAVEN_PARITY_CHECK_ENABLE 0x40 +#define RAVEN_SYSTEM_ERROR_ENABLE 0x100 +#define RAVEN_CLEAR_EVENTS_MASK 0xf9000000 + + +/* + * Bit encode for PCI_CONFIG_HEADER_TYPE register + */ +unsigned char ucMaxPCIBus; + +static int +indirect_pci_read_config_byte(unsigned char bus, unsigned char slot, + unsigned char function, + unsigned char offset, unsigned char *val) { + out_be32((unsigned int*) pci.pci_config_addr, + 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24)); + *val = in_8(pci.pci_config_data + (offset&3)); + return PCIBIOS_SUCCESSFUL; +} + +static int +indirect_pci_read_config_word(unsigned char bus, unsigned char slot, + unsigned char function, + unsigned char offset, unsigned short *val) { + *val = 0xffff; + if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; + out_be32((unsigned int*) pci.pci_config_addr, + 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24)); + *val = in_le16((volatile unsigned short *)(pci.pci_config_data + (offset&3))); + return PCIBIOS_SUCCESSFUL; +} + +static int +indirect_pci_read_config_dword(unsigned char bus, unsigned char slot, + unsigned char function, + unsigned char offset, unsigned int *val) { + *val = 0xffffffff; + if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; + out_be32((unsigned int*) pci.pci_config_addr, + 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|(offset<<24)); + *val = in_le32((volatile unsigned int *)pci.pci_config_data); + return PCIBIOS_SUCCESSFUL; +} + +static int +indirect_pci_write_config_byte(unsigned char bus, unsigned char slot, + unsigned char function, + unsigned char offset, unsigned char val) { + out_be32((unsigned int*) pci.pci_config_addr, + 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24)); + out_8(pci.pci_config_data + (offset&3), val); + return PCIBIOS_SUCCESSFUL; +} + +static int +indirect_pci_write_config_word(unsigned char bus, unsigned char slot, + unsigned char function, + unsigned char offset, unsigned short val) { + if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; + out_be32((unsigned int*) pci.pci_config_addr, + 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24)); + out_le16((volatile unsigned short *)(pci.pci_config_data + (offset&3)), val); + return PCIBIOS_SUCCESSFUL; +} + +static int +indirect_pci_write_config_dword(unsigned char bus, unsigned char slot, + unsigned char function, + unsigned char offset, unsigned int val) { + if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; + out_be32((unsigned int*) pci.pci_config_addr, + 0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|(offset<<24)); + out_le32((volatile unsigned int *)pci.pci_config_data, val); + return PCIBIOS_SUCCESSFUL; +} + +static const pci_config_access_functions indirect_functions = { + indirect_pci_read_config_byte, + indirect_pci_read_config_word, + indirect_pci_read_config_dword, + indirect_pci_write_config_byte, + indirect_pci_write_config_word, + indirect_pci_write_config_dword +}; + +pci_config pci = {(volatile unsigned char*)PCI_CONFIG_ADDR, + (volatile unsigned char*)PCI_CONFIG_DATA, + &indirect_functions}; + +static int +direct_pci_read_config_byte(unsigned char bus, unsigned char slot, + unsigned char function, + unsigned char offset, unsigned char *val) { + if (bus != 0 || (1<DeviceId.Interface==PCIBridgeIndirect) { + pci.pci_functions=&indirect_functions; + /* Should be extracted from residual data, + * indeed MPC106 in CHRP mode is different, + * but we should not use residual data in + * this case anyway. + */ + pci.pci_config_addr = ((volatile unsigned char *) + (ptr_mem_map->io_base+0xcf8)); + pci.pci_config_data = ptr_mem_map->io_base+0xcfc; + } else if(hostbridge->DeviceId.Interface==PCIBridgeDirect) { + pci.pci_functions=&direct_functions; + pci.pci_config_data=(unsigned char *) 0x80800000; + } else { + } + } else { + /* Let us try by experimentation at our own risk! */ + pci.pci_functions = &direct_functions; + /* On all direct bridges I know the host bridge itself + * appears as device 0 function 0. + */ + pci_read_config_dword(0, 0, 0, PCI_VENDOR_ID, &id0); + if (id0==~0U) { + pci.pci_functions = &indirect_functions; + pci.pci_config_addr = ((volatile unsigned char*) + (ptr_mem_map->io_base+0xcf8)); + pci.pci_config_data = ((volatile unsigned char*)ptr_mem_map->io_base+0xcfc); + } + /* Here we should check that the host bridge is actually + * present, but if it not, we are in such a desperate + * situation, that we probably can't even tell it. + */ + } + pci_read_config_dword(0, 0, 0, 0, &id0); + if(id0 == PCI_VENDOR_ID_MOTOROLA + + (PCI_DEVICE_ID_MOTOROLA_RAVEN<<16)) { + /* + * We have a Raven bridge. We will get information about its settings + */ + pci_read_config_dword(0, 0, 0, PCI_COMMAND, &id0); +#ifdef SHOW_RAVEN_SETTING + printk("RAVEN PCI command register = %x\n",id0); +#endif + id0 |= RAVEN_CLEAR_EVENTS_MASK; + pci_write_config_dword(0, 0, 0, PCI_COMMAND, id0); + pci_read_config_dword(0, 0, 0, PCI_COMMAND, &id0); +#ifdef SHOW_RAVEN_SETTING + printk("After error clearing RAVEN PCI command register = %x\n",id0); +#endif + + if (id0 & RAVEN_MPIC_IOSPACE_ENABLE) { + pci_read_config_dword(0, 0, 0,PCI_BASE_ADDRESS_0, &tmp); +#ifdef SHOW_RAVEN_SETTING + printk("Raven MPIC is accessed via IO Space Access at address : %x\n",(tmp & ~0x1)); +#endif + } + if (id0 & RAVEN_MPIC_MEMSPACE_ENABLE) { + pci_read_config_dword(0, 0, 0,PCI_BASE_ADDRESS_1, &tmp); +#ifdef SHOW_RAVEN_SETTING + printk("Raven MPIC is accessed via memory Space Access at address : %x\n", tmp); +#endif + OpenPIC=(volatile struct OpenPIC *) (tmp + PREP_ISA_MEM_BASE); + printk("OpenPIC found at %p.\n", + OpenPIC); + } + } + if (OpenPIC == (volatile struct OpenPIC *)0) { + BSP_panic("OpenPic Not found\n"); + } + +} + +/* + * This routine determines the maximum bus number in the system + */ +void InitializePCI() +{ + unsigned char ucSlotNumber, ucFnNumber, ucNumFuncs; + unsigned char ucHeader; + unsigned char ucMaxSubordinate; + unsigned int ulClass, ulDeviceID; + + detect_host_bridge(); + /* + * Scan PCI bus 0 looking for PCI-PCI bridges + */ + for(ucSlotNumber=0;ucSlotNumber>= 16; + if (ulClass == PCI_CLASS_BRIDGE_PCI) { + /* + * We have found a PCI-PCI bridge + */ + (void)pci_read_config_byte(0, + ucSlotNumber, + ucFnNumber, + PCI_SUBORDINATE_BUS, + &ucMaxSubordinate); + if(ucMaxSubordinate>ucMaxPCIBus) { + ucMaxPCIBus=ucMaxSubordinate; + } + } + } + } +} + +/* + * Return the number of PCI busses in the system + */ +unsigned char BusCountPCI() +{ + return(ucMaxPCIBus+1); +} -- cgit v1.2.3