📄 mot82xxpci.c
字号:
/* mot82xxPci.c - Motorola ads 82xx PCI Bridge functions *//* * Copyright (c) 2003-2005 Wind River Systems, Inc. * * The right to copy, distribute or otherwise make use of this software * may be licensed only pursuant to the terms of an applicable Wind River * license agreement. No license to Wind River intellectual property rights * is granted herein. All rights not licensed by Wind River are reserved * by Wind River. */ #include "copyright_wrs.h"/*modification history--------------------01e,08sep05,dtr Remove write to SIUMCR as now done in sysHwInit.01d,25mar05,mdo Documentation fixes for apigen01c,01oct03,dee changed structure element names for all dma buffer descriptors01b,08jan03,dtr Added support for PCI DMA and Error Handling. Implemented workaround for PCI Bridge read errata.01a,04jul02,dtr File created.*//*DESCRIPTIONThis file is the PCI Host Bridge setup File.INCLUDE FILES:*/#include "vxWorks.h"#include "config.h"#include "sysLib.h"#include "drv/pci/pciConfigLib.h" #include "drv/pci/pciIntLib.h" #include "drv/pci/pciAutoConfigLib.h" #include "sysBusPci.h"#include "drv/mem/m8260Memc.h"#include "drv/intrCtl/m8260IntrCtl.h"#include "drv/mem/m8260Siu.h"#include "mot82xxPci.h"#ifdef PCI_BRIDGE_READ_ERRATA_WORKAROUND/* Anything above 0x3ffffff can be handled by IDMA */ #define PCI_ACCESS_MASK 0xfc000000 /* Global function called in sysLib.c */ void pciBridgeIdmaInit();IMPORT USHORT sysWord(int);IMPORT UCHAR sysByte(int);IMPORT ULONG sysLong(int);#endif /* PCI_BRIDGE_READ_ERRATA_WORKAROUND */#ifdef INCLUDE_PCI_DMASTATUS pciDmaTransfer(char*,char*,UINT32,UINT32 );LOCAL void pciDmaHandler();#endif/* These three arrays are for convenience and speed *//* Each interrupt line is wire OR'd to another on another slot * Hence for first 4 bits - 8 is slot 0 INT A * links second - 4 is slot 1 INT B * links third - 2 is slot 2 INT C * All are the same interrupt effectively linked but they all * need to be cleared/masked in the interrupt register. * Refer to the ADS8266 PCI Board Users Manual. */ LOCAL UINT32 pciSlotIntDisableMask[MAX_NUM_VECTORS] = {0x84200000, /* Slot 0 */ 0x18400000, /* Slot 1 */ 0x21800000}; /* Slot 2 */LOCAL UINT32 pciSlotIntEnableMask[MAX_NUM_VECTORS] = {0x7bd00000, 0xe7b00000, 0xde700000};LOCAL UINT32 pciSlotIntClearMask[MAX_NUM_VECTORS] = {0x7bdfffff, 0xe7bfffff, 0xde7fffff};LOCAL INTR_HANDLER pciDeviceIntTable[MAX_NUM_VECTORS] = { {NULL,0}, {NULL,0}, {NULL,0} };BOOL firstTime = TRUE;LOCAL void pciDeviceIntHandler(void);STATUS pciDeviceIntConnect(int vector,VOIDFUNCPTR *handler,int arg);STATUS pciDeviceIntDisconnect(int vector,VOIDFUNCPTR *handler);STATUS pciDeviceIntEnable(int);STATUS pciDeviceIntDisable(int);LOCAL void pciMultiInterruptHandler();LOCAL void pciErrorHandler();LOCAL UINT32 pciIntEnabled = 0;VOIDFUNCPTR _func_pciDmaUserHandler[] = {NULL,NULL,NULL,NULL};typedef struct { UINT32 nmi; /* 60x error original initiated for PCI */ UINT32 ira; /* Illegal register access */ UINT32 i2o_ipqo; /* I2O Error queue overflow inbound */ UINT32 i2o_ofqo; /* I2O Error queue overflow outbound*/ UINT32 perr_wr; /* PCI Error Parity Error on write */ UINT32 perr_rd; /* PCI Error Parity Error on read */ UINT32 serr; /* PCI Error System error */ UINT32 tar_abt; /* PCI Error configuration access device isn't available */ UINT32 no_rsp; /* PCI Error no response */ UINT32 datapar_rd; /* PCI Error data parity error on read */ UINT32 datapar_wr; /* PCI Error data parity error on write */ UINT32 addrpar; /* PCI Error address parity error */} PCI_ERROR_COUNT;LOCAL PCI_ERROR_COUNT pciErrorCount; IMPORT UINT32 vxImmrGet (void);IMPORT USHORT sysPciInWord(int);LOCAL UINT32 immrVal = INTERNAL_MEM_MAP_ADDR;#ifdef PCI_BRIDGE_READ_ERRATA_WORKAROUNDLOCAL BD_DMA *idmaBd;LOCAL IDMA_PARAM *pIdmaParam;#endif /* PCI_BRIDGE_READ_ERRATA_WORKAROUND *//************************************************************************** * mot82xxBridgeInit - initialize the PCI Bridge** This function performs all the initialisation required for the * Bridge/Interrupts/PCI Bus to function. It does some low level processor * initialisation which might normally be done in romInit as it is optional * to do use this and shows what the core changes required to bring up the * bridge.* * RETURNS: N/A** ERRNO*/void mot82xxBridgeInit(void) { STATUS result; immrVal = (UINT32)vxImmrGet(); /* Make PCI lowest priority */ /* Each 4 bits is a device bus request and the MS 4bits is highest priority */ /* Bus 4bit value --- ---------- CPM high 0b0000 CPM middle 0b0001 CPM low 0b0010 PCI request 0b0011 Reserved 0b0100 Reserved 0b0101 Internal Core 0b0110 External Master 1 0b0111 External Master 2 0b1000 External Master 3 0b1001 The rest are reserved */ *M8260_PPC_ALRH (INTERNAL_MEM_MAP_ADDR) = 0x61207893; /* Park bus on core while modifying PCI Bus accesses */ *M8260_PPC_ACR (INTERNAL_MEM_MAP_ADDR) = PPC_ACR_BUS_PARK_CORE; /* Standard GPCM */ *(VUINT32*) M8260_OR3(INTERNAL_MEM_MAP_ADDR) = PCI_INT_MEM_OR8_SETTING; *(VUINT32*) M8260_BR3(INTERNAL_MEM_MAP_ADDR) = PCI_INT_MEM_BR8_SETTING; /* Set outbound translation window addresses */ sysPciOutLong((UINT32*)(PCI_OUTBOUND_BASE_ADRS_REG0(immrVal)), (CPU_PCI_MEM_ADRS>>12) & 0xfffff); sysPciOutLong((UINT32*)(PCI_OUTBOUND_TRANS_ADRS_REG0(immrVal)), (PCI_MEM_ADRS>>12) & 0xfffff); sysPciOutLong((UINT32*)(PCI_OUTBOUND_BASE_ADRS_REG1(immrVal)), (CPU_PCI_MEMIO_ADRS>>12) & 0xfffff); sysPciOutLong((UINT32*)(PCI_OUTBOUND_TRANS_ADRS_REG1(immrVal)), (PCI_MEMIO_ADRS>>12) & 0xfffff); sysPciOutLong((UINT32*)(PCI_OUTBOUND_BASE_ADRS_REG2(immrVal)), (CPU_PCI_IO_ADRS>>12) & 0xfffff); sysPciOutLong((UINT32*)(PCI_OUTBOUND_TRANS_ADRS_REG2(immrVal)), (PCI_IO_ADRS>>12) & 0xfffff); *(VUINT32*) PCIMSK_REG0 (INTERNAL_MEM_MAP_ADDR) = PCIMSK0_SETTING; /* set mask for 128KBytes */ *(VUINT32*) PCIMSK_REG1 (INTERNAL_MEM_MAP_ADDR) = PCIMSK1_SETTING; /* set start addresses and enable window*/ *(VUINT32*) PCIBR_REG0 (INTERNAL_MEM_MAP_ADDR) = PCIBR0_SETTING; *(VUINT32*) PCIBR_REG1 (INTERNAL_MEM_MAP_ADDR) = PCIBR1_SETTING; /* Switch on the outbound translation windows */ sysPciOutLong((UINT32*)(PCI_OUTBOUND_COMP_MASK_REG0(immrVal)), PCI_WINDOW_ENABLE_BIT | PCI_MEM_SIZE_MASK); sysPciOutLong((UINT32*)(PCI_OUTBOUND_COMP_MASK_REG1(immrVal)), PCI_WINDOW_ENABLE_BIT | PCI_MEMIO_SIZE_MASK); /* Set the PCI reset line high to switch on PCI bus */ sysPciOutLong((UINT32*)(immrVal| PCI_GCR_REG) , 0); sysPciOutLong((UINT32*)(immrVal| PCI_GCR_REG) , EXTERNAL_PCI_BUS_ENABLE); sysMsDelay(1); /* the bridge registers need to be accessed as little endian */ /* Set up inbound address translation registers */ /* Translation address is the locally mapped address */ sysPciOutLong((UINT32*)(immrVal| PCI_INBOUND_TRANS_ADRS_REG0), (PCI_LOCAL_MEM_BUS>>12) & 0xfffff); /* Base Address is the PCI address */ sysPciOutLong((UINT32*)(immrVal| PCI_INBOUND_BASE_ADRS_REG0), (PCI_MSTR_MEM_BUS>>12) & 0xfffff); /* This initialises the size of the window and enables it */ sysPciOutLong((UINT32*)(immrVal |PCI_INBOUND_COMP_MASK_REG0), PCI_MSTR_MEM_SIZE_MASK | PCI_WINDOW_ENABLE_BIT | PCI_SNOOP_ENABLE | PCI_PREFETCHABLE); /* See above for description - puts PCI request as highest priority */ *M8260_PPC_ALRH (INTERNAL_MEM_MAP_ADDR) = 0x30126745; /* Park the bus on the PCI */ *M8260_PPC_ACR (INTERNAL_MEM_MAP_ADDR) = PPC_ACR_BUS_PARK_PCI; /* Setup The PIMMR PCI Base address */ result = sysPciConfigWrite(0,0,0, PIMMR_BASE_ADRS_REGISTER_OFFSET, PIMMR_BASE_ADRS_REGISTER_WIDTH, PCI_BRIDGE_PIMMR_BASE_ADRS); result = sysPciConfigWrite(0,0,0, CLASS_OFFSET, CLASS_WIDTH, BRIDGE_CLASS_TYPE); /* configure the bridge as bus master */ result = sysPciConfigWrite(0,0,0, COMMAND_REGISTER_OFFSET, COMMAND_REGISTER_WIDTH, (BUS_MASTER_ENABLE_BIT|MEMORY_SPACE_ACCESS_ENABLE_BIT)); }/************************************************************************** * pciDeviceIntConnect - connect PCI interrupt to a handler** This function connects a interrupt handler to the pci interrupt and * PCI interrupt vector. It disables the interrupt vector via the PCI * interrupt mask register prior to initialisation in order to get it to * a known state assuming the interrupt should be at this point. ** RETURNS: OK or ERROR** ERRNO*/STATUS pciDeviceIntConnect ( int vector, VOIDFUNCPTR *handler, int arg ) { if (vector>=MAX_NUM_VECTORS) return (ERROR); pciDeviceIntDisable(vector); if (firstTime==TRUE) { (void)_func_intConnectRtn((VOIDFUNCPTR *)INUM_IRQ2, (VOIDFUNCPTR)pciDeviceIntHandler,0); /* Initialise Interrupt Mask */ firstTime=FALSE; } pciDeviceIntTable[vector].vec = (VOIDFUNCPTR)handler; pciDeviceIntTable[vector].arg = arg; (void)m8260IntEnable(INUM_IRQ2); return OK; }/************************************************************************** * pciDeviceIntDisconnect - disconnect interrupt handler to PCI interrupt ** This function disconnects the device interrupt handler from the PCI * interrupt and disables the relevant PCI interrupt.** RETURNS: OK or ERROR** ERRNO*/STATUS pciDeviceIntDisconnect ( int vector, VOIDFUNCPTR *handler ) { if (vector>=MAX_NUM_VECTORS) return (ERROR); (void)pciDeviceIntDisable(vector); pciDeviceIntTable[vector].vec = NULL; pciDeviceIntTable[vector].arg = 0;#ifdef PCI_DEBUG logMsg("PCI Interrupt disconnected %d\n",vector,0,0,0,0,0);#endif firstTime=TRUE; return OK; }/**************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -