diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 12:50:58 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 15:18:45 +0200 |
commit | 5a4e3dc0a5af631b1723858bc50a9af1545392fb (patch) | |
tree | f2825a86e99fbf1982fc484278483a03728ccc3a /bsps/powerpc/mvme5500/pci/pci.c | |
parent | bsps/sh: Move console.c to bsps (diff) | |
download | rtems-5a4e3dc0a5af631b1723858bc50a9af1545392fb.tar.bz2 |
bsps: Move PCI drivers to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'bsps/powerpc/mvme5500/pci/pci.c')
-rw-r--r-- | bsps/powerpc/mvme5500/pci/pci.c | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/bsps/powerpc/mvme5500/pci/pci.c b/bsps/powerpc/mvme5500/pci/pci.c new file mode 100644 index 0000000000..8ef5876047 --- /dev/null +++ b/bsps/powerpc/mvme5500/pci/pci.c @@ -0,0 +1,420 @@ +/* + * 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 : + * + * <http://www.chorus.com/Documentation/index.html> by following + * the STREAM API Specification Document link. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/rtems/license.html. + * + * Copyright 2004, 2008 Brookhaven National Laboratory and + * Shuchen K. Feng, <feng1@bnl.gov> + * + * - to be consistent with the original pci.c written by Eric Valette + * - added 2nd PCI support for discovery based PCI bridge (e.g. mvme5500/mvme6100) + * - added bus support for the expansion of PMCSpan as per request by Peter + */ +#define PCI_MAIN + +#include <libcpu/io.h> +#include <rtems/bspIo.h> /* printk */ + +#include <bsp/irq.h> +#include <bsp/pci.h> +#include <bsp/gtreg.h> +#include <bsp/gtpcireg.h> +#include <bsp.h> + +#include <stdio.h> +#include <string.h> +#include <inttypes.h> + +#define PCI_DEBUG 0 +#define PCI_PRINT 1 + +/* allow for overriding these definitions */ +#ifndef PCI_CONFIG_ADDR +#define PCI_CONFIG_ADDR 0xcf8 +#endif +#ifndef PCI_CONFIG_DATA +#define PCI_CONFIG_DATA 0xcfc +#endif + +#ifndef PCI1_CONFIG_ADDR +#define PCI1_CONFIG_ADDR 0xc78 +#endif +#ifndef PCI1_CONFIG_DATA +#define PCI1_CONFIG_DATA 0xc7c +#endif + +#define HOSTBRIDGET_ERROR 0xf0000000 + +#define GT64x60_PCI_CONFIG_ADDR GT64x60_REG_BASE + PCI_CONFIG_ADDR +#define GT64x60_PCI_CONFIG_DATA GT64x60_REG_BASE + PCI_CONFIG_DATA + +#define GT64x60_PCI1_CONFIG_ADDR GT64x60_REG_BASE + PCI1_CONFIG_ADDR +#define GT64x60_PCI1_CONFIG_DATA GT64x60_REG_BASE + PCI1_CONFIG_DATA + +static int numPCIDevs=0; +static DiscoveryChipVersion BSP_sysControllerVersion = 0; +static BSP_VMEchipTypes BSP_VMEinterface = 0; +static rtems_pci_config_t BSP_pci[2]={ + {(volatile unsigned char*) (GT64x60_PCI_CONFIG_ADDR), + (volatile unsigned char*) (GT64x60_PCI_CONFIG_DATA), + 0 /* defined at BSP_pci_configuration */}, + {(volatile unsigned char*) (GT64x60_PCI1_CONFIG_ADDR), + (volatile unsigned char*) (GT64x60_PCI1_CONFIG_DATA), + 0 /* defined at BSP_pci_configuration */} +}; + +/* Pack RegNum,FuncNum,DevNum,BusNum,and ConfigEnable for + * PCI Configuration Address Register + */ +#define pciConfigPack(bus,dev,func,offset)\ +((offset&~3)<<24)|(PCI_DEVFN(dev,func)<<16)|(bus<<8)|0x80 + +/* + * Bit encode for PCI_CONFIG_HEADER_TYPE register + */ +static unsigned char ucMaxPCIBus=0; + +/* Please note that PCI0 and PCI1 does not correlate with the busNum 0 and 1. + */ +static int indirect_pci_read_config_byte(unsigned char bus,unsigned char dev,unsigned char func, +unsigned char offset, uint8_t *val) +{ + int n=0; + + if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) { + bus-=BSP_MAX_PCI_BUS_ON_PCI0; + n=1; + } + + *val = 0xff; + if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER; +#if 0 + printk("addr %x, data %x, pack %x \n", BSP_pci[n].pci_config_addr), + BSP_pci[n].config_data,pciConfigPack(bus,dev,func,offset)); +#endif + + out_be32((volatile uint32_t *) BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset)); + *val = in_8(BSP_pci[n].pci_config_data + (offset&3)); + return PCIBIOS_SUCCESSFUL; +} + +static int indirect_pci_read_config_word(unsigned char bus, unsigned char dev, +unsigned char func, unsigned char offset, uint16_t *val) +{ + int n=0; + + if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) { + bus-=BSP_MAX_PCI_BUS_ON_PCI0; + n=1; + } + + *val = 0xffff; + if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER; +#if 0 + printk("addr %x, data %x, pack %x \n", config_addr, + config_data,pciConfigPack(bus,dev,func,offset)); +#endif + out_be32((volatile uint32_t *) BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset)); + *val = in_le16((volatile uint16_t *) (BSP_pci[n].pci_config_data + (offset&2))); + return PCIBIOS_SUCCESSFUL; +} + +static int indirect_pci_read_config_dword(unsigned char bus, unsigned char dev, +unsigned char func, unsigned char offset, uint32_t *val) +{ + int n=0; + + if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) { + bus-=BSP_MAX_PCI_BUS_ON_PCI0; + n=1; + } + + *val = 0xffffffff; + if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER; + + out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset)); + *val = in_le32((volatile uint32_t *)BSP_pci[n].pci_config_data); + return PCIBIOS_SUCCESSFUL; +} + +static int indirect_pci_write_config_byte(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, uint8_t val) +{ + int n=0; + + if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) { + bus-=BSP_MAX_PCI_BUS_ON_PCI0; + n=1; + } + + if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER; + + out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset)); + out_8((volatile uint8_t *) (BSP_pci[n].pci_config_data + (offset&3)), val); + return PCIBIOS_SUCCESSFUL; +} + +static int indirect_pci_write_config_word(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, uint16_t val) +{ + int n=0; + + if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) { + bus-=BSP_MAX_PCI_BUS_ON_PCI0; + n=1; + } + + if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER; + + out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset)); + out_le16((volatile uint16_t *)(BSP_pci[n].pci_config_data + (offset&3)), val); + return PCIBIOS_SUCCESSFUL; +} + +static int indirect_pci_write_config_dword(unsigned char bus,unsigned char dev,unsigned char func, unsigned char offset, uint32_t val) +{ + int n=0; + + if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) { + bus-=BSP_MAX_PCI_BUS_ON_PCI0; + n=1; + } + + if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER; + + out_be32((volatile uint32_t *)BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset)); + out_le32((volatile uint32_t *)BSP_pci[n].pci_config_data, val); + return PCIBIOS_SUCCESSFUL; +} + +const pci_config_access_functions pci_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 +}; + + +rtems_pci_config_t BSP_pci_configuration = { + (volatile unsigned char*) (GT64x60_PCI_CONFIG_ADDR), + (volatile unsigned char*) (GT64x60_PCI_CONFIG_DATA), + &pci_indirect_functions}; + +DiscoveryChipVersion BSP_getDiscoveryChipVersion(void) +{ + return(BSP_sysControllerVersion); +} + +BSP_VMEchipTypes BSP_getVMEchipType(void) +{ + return(BSP_VMEinterface); +} + +/* + * This routine determines the maximum bus number in the system. + * The PCI_SUBORDINATE_BUS is not supported in GT6426xAB. Thus, + * it's not used. + * + */ +int pci_initialize(void) +{ + int deviceFound; + unsigned char ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs, data8; + uint32_t ulHeader, ulClass, ulDeviceID; +#if PCI_DEBUG + uint32_t pcidata; +#endif + + /* + * Scan PCI0 and PCI1 buses + */ + for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ucBusNumber++) { + deviceFound=0; + for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) { + ucFnNumber = 0; + pci_read_config_dword(ucBusNumber, + ucSlotNumber, + 0, + PCI_VENDOR_ID, + &ulDeviceID); + + if( ulDeviceID==PCI_INVALID_VENDORDEVICEID) { + /* This slot is empty */ + continue; + } + + if (++numPCIDevs > PCI_MAX_DEVICES) { + rtems_panic("Too many PCI devices found; increase PCI_MAX_DEVICES in pci.h\n"); + } + + if (!deviceFound) deviceFound=1; + switch(ulDeviceID) { + case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT6426xAB<<16)): + pci_read_config_byte(0,0,0,PCI_REVISION_ID, &data8); + switch(data8) { + case 0x10: + BSP_sysControllerVersion = GT64260A; +#if PCI_PRINT + printk("Marvell GT64260A (Discovery I) hostbridge detected at bus%d slot%d\n", + ucBusNumber,ucSlotNumber); +#endif + break; + case 0x20: + BSP_sysControllerVersion = GT64260B; +#if PCI_PRINT + printk("Marvell GT64260B (Discovery I) hostbridge detected at bus%d slot%d\n", + ucBusNumber,ucSlotNumber); +#endif + break; + default: + printk("Undefined revsion of GT64260 chip\n"); + break; + } + break; + case PCI_VENDOR_ID_TUNDRA: +#if PCI_PRINT + printk("TUNDRA PCI-VME bridge detected at bus%d slot%d\n", + ucBusNumber,ucSlotNumber); +#endif + break; + case (PCI_VENDOR_ID_DEC+(PCI_DEVICE_ID_DEC_21150<<16)): +#if PCI_PRINT + printk("DEC21150 PCI-PCI bridge detected at bus%d slot%d\n", + ucBusNumber,ucSlotNumber); +#endif + break; + default : +#if PCI_PRINT + printk("BSP unlisted vendor, Bus%d Slot%d DeviceID 0x%" PRIx32 "\n", + ucBusNumber,ucSlotNumber, ulDeviceID); +#endif + /* Kate Feng : device not supported by BSP needs to remap the IRQ line on mvme5500/mvme6100 */ + pci_read_config_byte(ucBusNumber,ucSlotNumber,0,PCI_INTERRUPT_LINE,&data8); + if (data8 < BSP_GPP_IRQ_LOWEST_OFFSET) pci_write_config_byte(ucBusNumber, + ucSlotNumber,0,PCI_INTERRUPT_LINE,BSP_GPP_IRQ_LOWEST_OFFSET+data8); + + break; + } + +#if PCI_DEBUG + pci_read_config_dword(ucBusNumber, + ucSlotNumber, + 0, + PCI_BASE_ADDRESS_0, + &data); + printk("Bus%d BASE_ADDRESS_0 0x%x \n",ucBusNumber, data); + pci_read_config_dword(ucBusNumber, + ucSlotNumber, + 0, + PCI_BASE_ADDRESS_1, + &data); + printk("Bus%d BASE_ADDRESS_1 0x%x \n",ucBusNumber, data); + pci_read_config_dword(ucBusNumber, + ucSlotNumber, + 0, + PCI_BASE_ADDRESS_2, + &data); + printk("Bus%d BASE_ADDRESS_2 0x%x \n", ucBusNumber, data); + + pci_read_config_dword(ucBusNumber, + ucSlotNumber, + 0, + PCI_BASE_ADDRESS_3, + &data); + printk("Bus%d BASE_ADDRESS_3 0x%x \n", ucBusNumber, data); + + pci_read_config_word(ucBusNumber, + ucSlotNumber, + 0, + PCI_INTERRUPT_LINE, + &sdata); + printk("Bus%d INTERRUPT_LINE 0x%x \n", ucBusNumber, sdata); + + /* We always enable internal memory. */ + pci_read_config_dword(ucBusNumber, + ucSlotNumber, + 0, + PCI_MEM_BASE_ADDR, + &pcidata); + printk("Bus%d MEM_BASE_ADDR 0x%x \n", ucBusNumber,pcidata); + + /* We always enable internal IO. */ + pci_read_config_dword(ucBusNumber, + ucSlotNumber, + 0, + PCI_IO_BASE_ADDR, + &pcidata); + printk("Bus%d IO_BASE_ADDR 0x%x \n", ucBusNumber,pcidata); +#endif + + pci_read_config_dword(ucBusNumber, + ucSlotNumber, + 0, + PCI_CACHE_LINE_SIZE, + &ulHeader); + if ((ulHeader>>16)&PCI_HEADER_TYPE_MULTI_FUNCTION) + ucNumFuncs=PCI_MAX_FUNCTIONS; + else + ucNumFuncs=1; + +#if PCI_DEBUG + printk("Bus%d Slot 0x%x HEADER/LAT/CACHE 0x%x \n", + ucBusNumber, ucSlotNumber, ulHeader); +#endif + + for (ucFnNumber=1;ucFnNumber<ucNumFuncs;ucFnNumber++) { + pci_read_config_dword(ucBusNumber, + ucSlotNumber, + ucFnNumber, + PCI_VENDOR_ID, + &ulDeviceID); + if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) { + /* This slot/function is empty */ + continue; + } + + /* This slot/function has a device fitted.*/ + pci_read_config_dword(ucBusNumber, + ucSlotNumber, + ucFnNumber, + PCI_CLASS_REVISION, + &ulClass); +#if PCI_DEBUG + printk("Bus%d Slot 0x%x Func %d classID 0x%x \n",ucBusNumber,ucSlotNumber, + ucFnNumber, ulClass); +#endif + + } + } + if (deviceFound) ucMaxPCIBus++; + } /* for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ... */ +#if PCI_DEBUG + printk("number of PCI buses: %d, numPCIDevs %d\n", + pci_bus_count(), numPCIDevs); +#endif + pci_interface(); + return(0); +} + +void FixupPCI( const struct _int_map *bspmap, int (*swizzler)(int,int) ) +{ +} + +/* + * Return the number of PCI buses in the system + */ +unsigned char pci_bus_count() +{ + return(ucMaxPCIBus); +} + |