/******************************************************************************* * mvCpuIfPexRemap - Set CPU remap register for address windows. * * DESCRIPTION: * * INPUT: * pexTarget - Peripheral target enumerator. Must be a PEX target. * pAddrDecWin - CPU target window information data structure. * Note that caller has to fill in the base field only. The * size field is ignored. * * OUTPUT: * None. * * RETURN: * MV_ERROR if target is not a PEX one, MV_OK otherwise. * *******************************************************************************/ MV_U32 mvCpuIfPexRemap(MV_TARGET pexTarget, MV_ADDR_WIN *pAddrDecWin) { MV_U32 winNum; /* Check parameters */ if (mvCtrlPexMaxIfGet() > 1) { if ((!MV_TARGET_IS_PEX1(pexTarget))&&(!MV_TARGET_IS_PEX0(pexTarget))) { mvOsPrintf("mvCpuIfPexRemap: target %d is illegal\n",pexTarget); return 0xffffffff; } } else { if (!MV_TARGET_IS_PEX0(pexTarget)) { mvOsPrintf("mvCpuIfPexRemap: target %d is illegal\n",pexTarget); return 0xffffffff; } } /* get the Window number associated with this target */ winNum = mvAhbToMbusWinTargetGet(pexTarget); if (winNum >= MAX_AHB_TO_MBUS_WINS) { mvOsPrintf("mvCpuIfPexRemap: mvAhbToMbusWinTargetGet Failed\n"); return 0xffffffff; } return mvAhbToMbusWinRemap(winNum , pAddrDecWin); }
MV_STATUS mvPexTargetWinRemapEnable(MV_U32 pexIf, MV_U32 winNum, MV_BOOL enable) { PEX_WIN_REG_INFO winRegInfo; /* Parameter checking */ if (pexIf >= mvCtrlPexMaxIfGet()) { mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX interface num %d\n", pexIf); return MV_BAD_PARAM; } if (MV_PEX_WIN_DEFAULT == winNum) { mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX win num %d\n", winNum); return MV_BAD_PARAM; } pexWinRegInfoGet(pexIf, winNum, &winRegInfo); if (enable == MV_TRUE) { MV_REG_BIT_SET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); } else { MV_REG_BIT_RESET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); } return MV_OK; }
MV_STATUS mvPexBarGet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *pAddrWin) { /* check parameters */ if(pexIf >= mvCtrlPexMaxIfGet()) { mvOsPrintf("mvPexBarGet: ERR. Invalid PEX interface %d\n", pexIf); return MV_BAD_PARAM; } if(barNum >= PEX_MAX_BARS) { mvOsPrintf("mvPexBarGet: ERR. Invalid bar number %d\n", barNum); return MV_BAD_PARAM; } /* read base low */ pAddrWin->addrWin.baseLow = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE(barNum))); if (PEX_INTER_REGS_BAR == barNum) { pAddrWin->addrWin.baseLow &= PXBIR_BASE_MASK; } else { pAddrWin->addrWin.baseLow &= PXBR_BASE_MASK; } /* read base high */ pAddrWin->addrWin.baseHigh = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE_HIGH(barNum))); /* Read bar size */ if (PEX_INTER_REGS_BAR != barNum) /* internal registers have no size */ { pAddrWin->addrWin.size = MV_REG_READ(PEX_BAR_CTRL_REG(pexIf,barNum)); /* check if enable or not */ if (pAddrWin->addrWin.size & PXBCR_BAR_EN) { pAddrWin->enable = MV_TRUE; } else { pAddrWin->enable = MV_FALSE; } /* now get the size */ pAddrWin->addrWin.size &= PXBCR_BAR_SIZE_MASK; pAddrWin->addrWin.size >>= PXBCR_BAR_SIZE_OFFS; pAddrWin->addrWin.size = ctrlRegToSize(pAddrWin->addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT); }
/******************************************************************************* * mvPexTargetWinRemap - Set PEX to target address window remap. * * DESCRIPTION: * The PEX interface supports remap of the BAR original address window. * For each BAR it is possible to define a remap address. For example * an address 0x12345678 that hits BAR 0x10 (SDRAM CS[0]) will be modified * according to remap register but will also be targeted to the * SDRAM CS[0]. * * INPUT: * pexIf - PEX interface number. * bar - Peripheral target enumerator accessed by slave. * pAddrWin - Address window to be checked. * * OUTPUT: * None. * * RETURN: * MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK * *******************************************************************************/ MV_STATUS mvPexTargetWinRemap(MV_U32 pexIf, MV_U32 winNum, MV_PEX_REMAP_WIN *pAddrWin) { PEX_WIN_REG_INFO winRegInfo; /* Parameter checking */ if (pexIf >= mvCtrlPexMaxIfGet()) { mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX interface num %d\n", pexIf); return MV_BAD_PARAM; } if (MV_PEX_WIN_DEFAULT == winNum) { mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX win num %d\n", winNum); return MV_BAD_PARAM; } if (MV_IS_NOT_ALIGN(pAddrWin->addrWin.baseLow, PXWRR_REMAP_ALIGNMENT)) { mvOsPrintf("mvPexTargetWinRemap: Error remap PEX interface %d win %d."\ "\nAddress 0x%08x is unaligned to size 0x%x.\n", pexIf, winNum, pAddrWin->addrWin.baseLow, pAddrWin->addrWin.size); return MV_ERROR; } pexWinRegInfoGet(pexIf, winNum, &winRegInfo); /* Set remap low register value */ MV_REG_WRITE(winRegInfo.remapLowRegOffs, pAddrWin->addrWin.baseLow); /* Skip base high settings if the BAR has only base low (32-bit) */ if (0 != winRegInfo.remapHighRegOffs) { MV_REG_WRITE(winRegInfo.remapHighRegOffs, pAddrWin->addrWin.baseHigh); } if (pAddrWin->enable == MV_TRUE) { MV_REG_BIT_SET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); } else { MV_REG_BIT_RESET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); } return MV_OK; }
/******************************************************************************* * mvPexModeGet - Get Pex Mode * * DESCRIPTION: * * INPUT: * pexIf - PEX interface number. * * OUTPUT: * pexMode - Pex mode structure * * RETURN: * MV_OK on success , MV_ERROR otherwise * *******************************************************************************/ MV_U32 mvPexModeGet(MV_U32 pexIf,MV_PEX_MODE *pexMode) { MV_U32 pexData; /* Parameter checking */ if (PEX_DEFAULT_IF != pexIf) { if (pexIf >= mvCtrlPexMaxIfGet()) { mvOsPrintf("mvPexModeGet: ERR. Invalid PEX interface %d\n",pexIf); return MV_ERROR; } } pexData = MV_REG_READ(PEX_CTRL_REG(pexIf)); switch (pexData & PXCR_DEV_TYPE_CTRL_MASK) { case PXCR_DEV_TYPE_CTRL_CMPLX: pexMode->pexType = MV_PEX_ROOT_COMPLEX; break; case PXCR_DEV_TYPE_CTRL_POINT: pexMode->pexType = MV_PEX_END_POINT; break; } /* Check if we have link */ if (MV_REG_READ(PEX_STATUS_REG(pexIf)) & PXSR_DL_DOWN) { pexMode->pexLinkUp = MV_FALSE; /* If there is no link, the auto negotiation data is worthless */ pexMode->pexWidth = MV_PEX_WITDH_INVALID; } else { pexMode->pexLinkUp = MV_TRUE; /* We have link. The link width is now valid */ pexData = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CTRL_STAT_REG)); pexMode->pexWidth = ((pexData & PXLCSR_NEG_LNK_WDTH_MASK) >> PXLCSR_NEG_LNK_WDTH_OFFS); } return MV_OK; }
/******************************************************************************* * mvSysPexInit - Initialize the Pex subsystem * * DESCRIPTION: * * INPUT: * None * OUTPUT: * None * RETURN: * None * *******************************************************************************/ MV_STATUS mvSysPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType) { MV_PEX_HAL_DATA halData; MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1]; MV_STATUS status; status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1); if(status == MV_OK) status = mvPexWinInit(pexIf, pexType, addrWinMap); if(status == MV_OK) { halData.ctrlModel = mvCtrlModelGet(); halData.maxPexIf = mvCtrlPexMaxIfGet(); status = mvPexInit(pexIf, pexType, &halData); } return status; }
/******************************************************************************* * mvSysPexInit - Initialize the Pex subsystem * * DESCRIPTION: * * INPUT: * None * OUTPUT: * None * RETURN: * None * *******************************************************************************/ MV_STATUS mvSysPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType) { MV_PEX_HAL_DATA halData; MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1]; MV_STATUS status; if (MV_FALSE == mvCtrlPwrClckGet(PEX_UNIT_ID, pexIf)) return MV_ERROR; status = mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1); if (status == MV_OK) status = mvPexWinInit(pexIf, pexType, addrWinMap); if (status == MV_OK) { halData.ctrlModel = mvCtrlModelGet(); halData.maxPexIf = mvCtrlPexMaxIfGet(); halData.ctrlFamily=mvCtrlDevFamilyIdGet(halData.ctrlModel); status = mvPexInit(pexIf, pexType, &halData); } return status; }
MV_U32 mvPexHwConfigRead (MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, MV_U32 regOff) { #endif MV_U32 pexData = 0; MV_U32 localDev,localBus; /* Parameter checking */ if (PEX_DEFAULT_IF != pexIf) { if (pexIf >= mvCtrlPexMaxIfGet()) { mvOsPrintf("mvPexConfigRead: ERR. Invalid PEX interface %d\n",pexIf); return 0xFFFFFFFF; } } if (dev >= MAX_PEX_DEVICES) { DB(mvOsPrintf("mvPexConfigRead: ERR. device number illigal %d\n", dev)); return 0xFFFFFFFF; } if (func >= MAX_PEX_FUNCS) { DB(mvOsPrintf("mvPexConfigRead: ERR. function num illigal %d\n", func)); return 0xFFFFFFFF; } if (bus >= MAX_PEX_BUSSES) { DB(mvOsPrintf("mvPexConfigRead: ERR. bus number illigal %d\n", bus)); return MV_ERROR; } DB(mvOsPrintf("mvPexConfigRead: pexIf %d, bus %d, dev %d, func %d, regOff 0x%x\n", pexIf, bus, dev, func, regOff)); localDev = mvPexLocalDevNumGet(pexIf); localBus = mvPexLocalBusNumGet(pexIf); /* Speed up the process. In case on no link, return MV_ERROR */ if ((dev != localDev) || (bus != localBus)) { pexData = MV_REG_READ(PEX_STATUS_REG(pexIf)); if ((pexData & PXSR_DL_DOWN)) { return MV_ERROR; } } /* in PCI Express we have only one device number */ /* and this number is the first number we encounter else that the localDev*/ /* spec pex define return on config read/write on any device */ if (bus == localBus) { if (localDev == 0) { /* if local dev is 0 then the first number we encounter after 0 is 1 */ if ((dev != 1)&&(dev != localDev)) { return MV_ERROR; } } else { /* if local dev is not 0 then the first number we encounter is 0 */ if ((dev != 0)&&(dev != localDev)) { return MV_ERROR; } } if(func != 0 ) /* i.e bridge */ { return MV_ERROR; } } /* Creating PEX address to be passed */ pexData = (bus << PXCAR_BUS_NUM_OFFS); pexData |= (dev << PXCAR_DEVICE_NUM_OFFS); pexData |= (func << PXCAR_FUNC_NUM_OFFS); pexData |= (regOff & PXCAR_REG_NUM_MASK); /* lgacy register space */ /* extended register space */ pexData |=(((regOff & PXCAR_REAL_EXT_REG_NUM_MASK) >> PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS); pexData |= PXCAR_CONFIG_EN; /* Write the address to the PEX configuration address register */ MV_REG_WRITE(PEX_CFG_ADDR_REG(pexIf), pexData); DB(mvOsPrintf("mvPexConfigRead:address pexData=%x ",pexData)); /* In order to let the PEX controller absorbed the address of the read */ /* transaction we perform a validity check that the address was written */ if(pexData != MV_REG_READ(PEX_CFG_ADDR_REG(pexIf))) { return MV_ERROR; } /* cleaning Master Abort */ MV_REG_BIT_SET(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_STATUS_AND_COMMAND), PXSAC_MABORT); #if 0 /* Guideline (GL# PCI Express-1) Erroneous Read Data on Configuration */ /* This guideline is relevant for all devices except of the following devices: 88F5281-BO and above, 88F5181L-A0 and above, 88F1281 A0 and above 88F6183 A0 and above, 88F6183L */ if ( ( (dev != localDev) || (bus != localBus) ) && ( !(MV_5281_DEV_ID == mvCtrlModelGet())&& !((MV_5181_DEV_ID == mvCtrlModelGet())&& (mvCtrlRevGet() >= MV_5181L_A0_REV))&& !(MV_1281_DEV_ID == mvCtrlModelGet())&& !(MV_6183_DEV_ID == mvCtrlModelGet())&& !(MV_6183L_DEV_ID == mvCtrlModelGet())&& !(MV_6281_DEV_ID == mvCtrlModelGet())&& !(MV_6192_DEV_ID == mvCtrlModelGet())&& !(MV_6190_DEV_ID == mvCtrlModelGet())&& !(MV_6180_DEV_ID == mvCtrlModelGet())&& !(MV_78XX0_DEV_ID == mvCtrlModelGet()) )) { /* PCI-Express configuration read work-around */ /* we will use one of the Punit (AHBToMbus) windows to access the xbar and read the data from there */ /* Need to configure the 2 free Punit (AHB to MBus bridge) address decoding windows: Configure the flash Window to handle Configuration space requests for PEX0/1: 1. write 0x7931/0x7941 to the flash window and the size, 79-xbar attr (pci cfg), 3/4-xbar target (pex0/1), 1-WinEn 2. write base to flash window Configuration transactions from the CPU should write/read the data to/from address of the form: addr[31:28] = 0x5 (for PEX0) or 0x6 (for PEX1) addr[27:24] = extended register number addr[23:16] = bus number addr[15:11] = device number addr[10:8] = function number addr[7:0] = register number */ #include "ctrlEnv/sys/mvAhbToMbus.h" { MV_U32 winNum; MV_AHB_TO_MBUS_DEC_WIN originWin; MV_U32 pciAddr=0; MV_U32 remapLow=0,remapHigh=0; /* We will use DEV_CS2\Flash window for this workarround */ winNum = mvAhbToMbusWinTargetGet(PEX_CONFIG_RW_WA_TARGET); /* save remap values if exist */ if ((1 == winNum)||(0 == winNum)) { remapLow = MV_REG_READ(AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum)); remapHigh = MV_REG_READ(AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum)); } /* save the original window values */ mvAhbToMbusWinGet(winNum,&originWin); if (PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES) { /* set the window as xbar window */ if (pexIf) { MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum), (0x7931 | (((originWin.addrWin.size >> 16)-1) ) << 16)); } else { MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum), (0x7941 | (((originWin.addrWin.size >> 16)-1) ) << 16)); } MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(winNum), originWin.addrWin.baseLow); /*pciAddr = originWin.addrWin.baseLow;*/ pciAddr = (MV_U32)CPU_MEMIO_UNCACHED_ADDR( (MV_U32)originWin.addrWin.baseLow); }
MV_STATUS mvPciScan(MV_U32 pciIf, MV_PCI_DEVICE *pPciAgents, MV_U32 *pPciAgentsNum) { MV_U32 devIndex,funcIndex=0,busIndex=0,detectedDevNum=0; MV_U32 localBus=mvPciIfLocalBusNumGet(pciIf); MV_PCI_DEVICE *pPciDevice; MV_PCI_DEVICE *pMainDevice; DB(mvOsPrintf("mvPciScan: PCI interface num %d\n", pciIf)); /* Parameter checking */ if (pciIf >= mvCtrlPexMaxIfGet()) { DB(mvOsPrintf("mvPciScan: ERR. Invalid PCI interface num %d\n", pciIf)); return MV_BAD_PARAM; } if (NULL == pPciAgents) { DB(mvOsPrintf("mvPciScan: ERR. pPciAgents=NULL \n")); return MV_BAD_PARAM; } if (NULL == pPciAgentsNum) { DB(mvOsPrintf("mvPciScan: ERR. pPciAgentsNum=NULL \n")); return MV_BAD_PARAM; } DB(mvOsPrintf("mvPciScan: PCI interface num %d mvPciMasterEnable\n", pciIf)); /* Master enable the MV PCI master */ if (MV_OK != mvPciIfMasterEnable(pciIf,MV_TRUE)) { DB(mvOsPrintf("mvPciScan: ERR. mvPciMasterEnable failed \n")); return MV_ERROR; } DB(mvOsPrintf("mvPciScan: PCI interface num scan%d\n", pciIf)); /* go through all busses */ for (busIndex=localBus ; busIndex < MAX_PCI_BUSSES ; busIndex++) { /* go through all possible devices on the local bus */ for (devIndex=0 ; devIndex < MAX_PCI_DEVICES ; devIndex++) { /* always start with function equal to zero */ funcIndex=0; pPciDevice=&pPciAgents[detectedDevNum]; DB(mvOsPrintf("mvPciScan: PCI interface num scan%d:%d\n", busIndex, devIndex)); if (MV_ERROR == pciDetectDevice(pciIf, busIndex, devIndex, funcIndex, pPciDevice)) { /* no device detected , try the next address */ continue; } /* We are here ! means we have detected a device*/ /* always we start with only one function per device */ pMainDevice = pPciDevice; pPciDevice->funtionsNum = 1; /* move on */ detectedDevNum++; /* check if we have no more room for a new device */ if (detectedDevNum == *pPciAgentsNum) { DB(mvOsPrintf("mvPciScan: ERR. array passed too small \n")); return MV_ERROR; } /* check the detected device if it is a multi functional device then scan all device functions*/ if (pPciDevice->isMultiFunction == MV_TRUE) { /* start with function number 1 because we have already detected function 0 */ for (funcIndex=1; funcIndex<MAX_PCI_FUNCS ; funcIndex++) { pPciDevice=&pPciAgents[detectedDevNum]; if (MV_ERROR == pciDetectDevice(pciIf, busIndex, devIndex, funcIndex, pPciDevice)) { /* no device detected means no more functions !*/ continue; } /* We are here ! means we have detected a device */ /* move on */ pMainDevice->funtionsNum++; detectedDevNum++; /* check if we have no more room for a new device */ if (detectedDevNum == *pPciAgentsNum) { DB(mvOsPrintf("mvPciScan: ERR. Array too small\n")); return MV_ERROR; } } } } } /* return the number of devices actually detected on the bus ! */ *pPciAgentsNum = detectedDevNum; return MV_OK; }
/******************************************************************************* * mvPexTargetWinEnable - Enable/disable a PEX BAR window * * DESCRIPTION: * This function enable/disable a PEX BAR window. * if parameter 'enable' == MV_TRUE the routine will enable the * window, thus enabling PEX accesses for that BAR (before enabling the * window it is tested for overlapping). Otherwise, the window will * be disabled. * * INPUT: * pexIf - PEX interface number. * bar - BAR to be accessed by slave. * enable - Enable/disable parameter. * * OUTPUT: * None. * * RETURN: * MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK * *******************************************************************************/ MV_STATUS mvPexTargetWinEnable(MV_U32 pexIf,MV_U32 winNum, MV_BOOL enable) { PEX_WIN_REG_INFO winRegInfo; MV_PEX_DEC_WIN addrDecWin; /* Parameter checking */ if(pexIf >= mvCtrlPexMaxIfGet()) { mvOsPrintf("mvPexTargetWinEnable: ERR. Invalid PEX If %d\n", pexIf); return MV_BAD_PARAM; } if (winNum >= PEX_MAX_TARGET_WIN) { mvOsPrintf("mvPexTargetWinEnable ERR. Invalid PEX winNum %d\n", winNum); return MV_BAD_PARAM; } /* get the pex Window registers offsets */ pexWinRegInfoGet(pexIf,winNum,&winRegInfo); /* if the address windows is disabled , we only disable the appropriare pex window and ignore other settings */ if (MV_FALSE == enable) { /* this is not relevant to default and expantion rom windows */ if (winRegInfo.sizeRegOffs) { if ((MV_PEX_WIN_DEFAULT != winNum)&& (MV_PEX_WIN_EXP_ROM != winNum)) { MV_REG_BIT_RESET(winRegInfo.sizeRegOffs, PXWCR_WIN_EN); } } } else { if (MV_OK != mvPexTargetWinGet(pexIf,winNum, &addrDecWin)) { mvOsPrintf("mvPexTargetWinEnable: mvPexTargetWinGet Failed\n"); return MV_ERROR; } /* Check if the requested window overlaps with current windows */ if (MV_TRUE == pexWinOverlapDetect(pexIf,winNum, &addrDecWin.addrWin)) { mvOsPrintf("mvPexTargetWinEnable: ERR. Target %d overlap\n", winNum); return MV_BAD_PARAM; } if (MV_FALSE == pexIsWinWithinBar(pexIf,&addrDecWin.addrWin)) { mvOsPrintf("mvPexTargetWinEnable: Win %d should be in bar boundries\n", winNum); return MV_BAD_PARAM; } /* this is not relevant to default and expantion rom windows */ if (winRegInfo.sizeRegOffs) { if ((MV_PEX_WIN_DEFAULT != winNum)&& (MV_PEX_WIN_EXP_ROM != winNum)) { MV_REG_BIT_SET(winRegInfo.sizeRegOffs, PXWCR_WIN_EN); } } } return MV_OK; }
/******************************************************************************* * mvPexTargetWinGet - Get PEX to peripheral target address window * * DESCRIPTION: * Get the PEX to peripheral target address window BAR. * * INPUT: * pexIf - PEX interface number. * bar - BAR to be accessed by slave. * * OUTPUT: * pAddrBarWin - PEX target window information data structure. * * RETURN: * MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK * *******************************************************************************/ MV_STATUS mvPexTargetWinGet(MV_U32 pexIf, MV_U32 winNum, MV_PEX_DEC_WIN *pAddrDecWin) { MV_TARGET_ATTRIB targetAttrib; MV_DEC_REGS decRegs; PEX_WIN_REG_INFO winRegInfo; /* Parameter checking */ if(pexIf >= mvCtrlPexMaxIfGet()) { mvOsPrintf("mvPexTargetWinGet: ERR. Invalid PEX interface %d\n", pexIf); return MV_BAD_PARAM; } if (winNum >= PEX_MAX_TARGET_WIN) { mvOsPrintf("mvPexTargetWinGet: ERR. Invalid PEX winNum %d\n", winNum); return MV_BAD_PARAM; } /* get the pex Window registers offsets */ pexWinRegInfoGet(pexIf,winNum,&winRegInfo); /* read base register*/ if (winRegInfo.baseLowRegOffs) { decRegs.baseReg = MV_REG_READ(winRegInfo.baseLowRegOffs); } else { decRegs.baseReg = 0; } /* read size reg */ if (winRegInfo.sizeRegOffs) { decRegs.sizeReg = MV_REG_READ(winRegInfo.sizeRegOffs); } else { decRegs.sizeReg =0; } if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) { mvOsPrintf("mvPexTargetWinGet: mvCtrlRegToAddrDec Failed \n"); return MV_ERROR; } if (decRegs.sizeReg & PXWCR_WIN_EN) { pAddrDecWin->enable = MV_TRUE; } else { pAddrDecWin->enable = MV_FALSE; } #if 0 if (-1 == pAddrDecWin->addrWin.size) { return MV_ERROR; } #endif /* get target bar */ if ((decRegs.sizeReg & PXWCR_WIN_BAR_MAP_MASK) == PXWCR_WIN_BAR_MAP_BAR1 ) { pAddrDecWin->targetBar = 1; } else if ((decRegs.sizeReg & PXWCR_WIN_BAR_MAP_MASK) == PXWCR_WIN_BAR_MAP_BAR2 ) { pAddrDecWin->targetBar = 2; } /* attrib and targetId */ pAddrDecWin->attrib = (decRegs.sizeReg & PXWCR_ATTRIB_MASK) >> PXWCR_ATTRIB_OFFS; pAddrDecWin->targetId = (decRegs.sizeReg & PXWCR_TARGET_MASK) >> PXWCR_TARGET_OFFS; targetAttrib.attrib = pAddrDecWin->attrib; targetAttrib.targetId = pAddrDecWin->targetId; pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); return MV_OK; }
/******************************************************************************* * mvPexTargetWinSet - Set PEX to peripheral target address window BAR * * DESCRIPTION: * * INPUT: * * OUTPUT: * N/A * * RETURN: * MV_OK if PEX BAR target window was set correctly, * MV_BAD_PARAM on bad params * MV_ERROR otherwise * (e.g. address window overlapps with other active PEX target window). * *******************************************************************************/ MV_STATUS mvPexTargetWinSet(MV_U32 pexIf, MV_U32 winNum, MV_PEX_DEC_WIN *pAddrDecWin) { MV_DEC_REGS decRegs; PEX_WIN_REG_INFO winRegInfo; MV_TARGET_ATTRIB targetAttribs; /* Parameter checking */ if(pexIf >= mvCtrlPexMaxIfGet()) { mvOsPrintf("mvPexTargetWinSet: ERR. Invalid PEX interface %d\n", pexIf); return MV_BAD_PARAM; } if (winNum >= PEX_MAX_TARGET_WIN) { mvOsPrintf("mvPexTargetWinSet: ERR. Invalid PEX winNum %d\n", winNum); return MV_BAD_PARAM; } /* get the pex Window registers offsets */ pexWinRegInfoGet(pexIf,winNum,&winRegInfo); if (MV_TRUE == pAddrDecWin->enable) { /* 2) Check if the requested window overlaps with current windows */ if (MV_TRUE == pexWinOverlapDetect(pexIf,winNum, &pAddrDecWin->addrWin)) { mvOsPrintf("mvPexTargetWinSet: ERR. Target %d overlap\n", winNum); return MV_BAD_PARAM; } /* 2) Check if the requested window overlaps with current windows */ if (MV_FALSE == pexIsWinWithinBar(pexIf,&pAddrDecWin->addrWin)) { mvOsPrintf("mvPexTargetWinSet: Win %d should be in bar boundries\n", winNum); return MV_BAD_PARAM; } } /* read base register*/ if (winRegInfo.baseLowRegOffs) { decRegs.baseReg = MV_REG_READ(winRegInfo.baseLowRegOffs); } else { decRegs.baseReg = 0; } if (winRegInfo.sizeRegOffs) { decRegs.sizeReg = MV_REG_READ(winRegInfo.sizeRegOffs); } else { decRegs.sizeReg =0; } if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) { mvOsPrintf("mvPexTargetWinSet:mvCtrlAddrDecToReg Failed\n"); return MV_ERROR; } /* enable\Disable */ if (MV_TRUE == pAddrDecWin->enable) { decRegs.sizeReg |= PXWCR_WIN_EN; } else { decRegs.sizeReg &= ~PXWCR_WIN_EN; } /* clear bit location */ decRegs.sizeReg &= ~PXWCR_WIN_BAR_MAP_MASK; /* set bar Mapping */ if (pAddrDecWin->targetBar == 1) { decRegs.sizeReg |= PXWCR_WIN_BAR_MAP_BAR1; } else if (pAddrDecWin->targetBar == 2) { decRegs.sizeReg |= PXWCR_WIN_BAR_MAP_BAR2; } mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); /* set attributes */ decRegs.sizeReg &= ~PXWCR_ATTRIB_MASK; decRegs.sizeReg |= targetAttribs.attrib << PXWCR_ATTRIB_OFFS; /* set target ID */ decRegs.sizeReg &= ~PXWCR_TARGET_MASK; decRegs.sizeReg |= targetAttribs.targetId << PXWCR_TARGET_OFFS; /* 3) Write to address decode Base Address Register */ if (winRegInfo.baseLowRegOffs) { MV_REG_WRITE(winRegInfo.baseLowRegOffs, decRegs.baseReg); } /* write size reg */ if (winRegInfo.sizeRegOffs) { if ((MV_PEX_WIN_DEFAULT == winNum)|| (MV_PEX_WIN_EXP_ROM == winNum)) { /* clear size because there is no size field*/ decRegs.sizeReg &= ~PXWCR_SIZE_MASK; /* clear enable because there is no enable field*/ decRegs.sizeReg &= ~PXWCR_WIN_EN; } MV_REG_WRITE(winRegInfo.sizeRegOffs, decRegs.sizeReg); } return MV_OK; }
/******************************************************************************* * mvPexInit - Initialize PEX interfaces * * DESCRIPTION: * * This function is responsible of intialization of the Pex Interface , It * configure the Pex Bars and Windows in the following manner: * * Assumptions : * Bar0 is always internal registers bar * Bar1 is always the DRAM bar * Bar2 is always the Device bar * * 1) Sets the Internal registers bar base by obtaining the base from * the CPU Interface * 2) Sets the DRAM bar base and size by getting the base and size from * the CPU Interface when the size is the sum of all enabled DRAM * chip selects and the base is the base of CS0 . * 3) Sets the Device bar base and size by getting these values from the * CPU Interface when the base is the base of the lowest base of the * Device chip selects, and the * * * INPUT: * * pexIf - PEX interface number. * * * OUTPUT: * None. * * RETURN: * MV_OK if function success otherwise MV_ERROR or MV_BAD_PARAM * *******************************************************************************/ MV_STATUS mvPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType) { MV_U32 bar; MV_U32 winNum; MV_PEX_BAR pexBar; MV_PEX_DEC_WIN pexWin; MV_CPU_DEC_WIN addrDecWin; MV_TARGET target; MV_U32 pexCurrWin=0; MV_U32 status; /* default and exapntion rom are always configured */ #ifndef MV_DISABLE_PEX_DEVICE_BAR MV_U32 winIndex; MV_U32 maxBase=0, sizeOfMaxBase=0; MV_U32 pexStartWindow; #endif /* Parameter checking */ if(pexIf >= mvCtrlPexMaxIfGet()) { mvOsPrintf("mvPexInit: ERR. Invalid PEX interface %d\n", pexIf); return MV_BAD_PARAM; } /* Enabled CPU access to PCI-Express */ mvCpuIfEnablePex(pexIf, pexType); /* Start with bars */ /* First disable all PEX bars*/ for (bar = 0; bar < PEX_MAX_BARS; bar++) { if (PEX_INTER_REGS_BAR != bar) { if (MV_OK != mvPexBarEnable(pexIf, bar, MV_FALSE)) { mvOsPrintf("mvPexInit:mvPexBarEnable bar =%d failed \n",bar); return MV_ERROR; } } } /* and disable all PEX target windows */ for (winNum = 0; winNum < PEX_MAX_TARGET_WIN - 2; winNum++) { if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_FALSE)) { mvOsPrintf("mvPexInit:mvPexTargetWinEnable winNum =%d failed \n", winNum); return MV_ERROR; } } /* Now, go through all bars*/ /******************************************************************************/ /* Internal registers bar */ /******************************************************************************/ bar = PEX_INTER_REGS_BAR; /* we only open the bar , no need to open windows for this bar */ /* first get the CS attribute from the CPU Interface */ if (MV_OK !=mvCpuIfTargetWinGet(INTER_REGS,&addrDecWin)) { mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",INTER_REGS); return MV_ERROR; } pexBar.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; pexBar.addrWin.size = addrDecWin.addrWin.size; pexBar.enable = MV_TRUE; if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) { mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar); return MV_ERROR; } /******************************************************************************/ /* DRAM bar */ /******************************************************************************/ bar = PEX_DRAM_BAR; pexBar.addrWin.size = 0; for (target = SDRAM_CS0;target < MV_DRAM_MAX_CS; target++ ) { status = mvCpuIfTargetWinGet(target,&addrDecWin); if((MV_NO_SUCH == status)&&(target != SDRAM_CS0)) { continue; } /* first get attributes from CPU If */ if (MV_OK != status) { mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",target); return MV_ERROR; } if (addrDecWin.enable == MV_TRUE) { /* the base is the base of DRAM CS0 always */ if (SDRAM_CS0 == target ) { pexBar.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; } /* increment the bar size to be the sum of the size of all DRAM chips selecs */ pexBar.addrWin.size += addrDecWin.addrWin.size; /* set a Pex window for this target ! DRAM CS always will have a Pex Window , and is not a part of the priority table */ pexWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; pexWin.addrWin.baseLow = addrDecWin.addrWin.baseLow; pexWin.addrWin.size = addrDecWin.addrWin.size; /* we disable the windows at first because we are not sure that it is witihin bar boundries */ pexWin.enable =MV_FALSE; pexWin.target = target; pexWin.targetBar = bar; if (MV_OK != mvPexTargetWinSet(pexIf,pexCurrWin++,&pexWin)) { mvOsPrintf("mvPexInit: ERR. mvPexTargetWinSet failed\n"); return MV_ERROR; } } } /* check if the size of the bar is illeggal */ if (-1 == ctrlSizeToReg(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT)) { /* try to get a good size */ pexBar.addrWin.size = ctrlSizeRegRoundUp(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT); } /* check if the size and base are valid */ if (MV_TRUE == pexBarOverlapDetect(pexIf,bar,&pexBar.addrWin)) { mvOsPrintf("mvPexInit:Warning :Bar %d size is illigal\n",bar); mvOsPrintf("it will be disabled\n"); mvOsPrintf("please check Pex and CPU windows configuration\n"); } else { pexBar.enable = MV_TRUE; /* configure the bar */ if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) { mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar); return MV_ERROR; } /* after the bar was configured then we enable the Pex windows*/ for (winNum = 0;winNum < pexCurrWin ;winNum++) { if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_TRUE)) { mvOsPrintf("mvPexInit: Can't enable window =%d\n",winNum); return MV_ERROR; } } } /******************************************************************************/ /* DEVICE bar */ /******************************************************************************/ /* Open the Device BAR for non linux only */ #ifndef MV_DISABLE_PEX_DEVICE_BAR /* then device bar*/ bar = PEX_DEVICE_BAR; /* save the starting window */ pexStartWindow = pexCurrWin; pexBar.addrWin.size = 0; pexBar.addrWin.baseLow = 0xffffffff; pexBar.addrWin.baseHigh = 0; maxBase = 0; for (target = DEV_TO_TARGET(START_DEV_CS);target < DEV_TO_TARGET(MV_DEV_MAX_CS); target++ ) { status = mvCpuIfTargetWinGet(target,&addrDecWin); if (MV_NO_SUCH == status) { continue; } if (MV_OK != status) { mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",target); return MV_ERROR; } if (addrDecWin.enable == MV_TRUE) { /* get the minimum base */ if (addrDecWin.addrWin.baseLow < pexBar.addrWin.baseLow) { pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; } /* get the maximum base */ if (addrDecWin.addrWin.baseLow > maxBase) { maxBase = addrDecWin.addrWin.baseLow; sizeOfMaxBase = addrDecWin.addrWin.size; } /* search in the priority table for this target */ for (winIndex = 0; pexDevBarPrioTable[winIndex] != TBL_TERM; winIndex++) { if (pexDevBarPrioTable[winIndex] != target) { continue; } else if (pexDevBarPrioTable[winIndex] == target) { /*found it */ /* if the index of this target in the prio table is valid then we set the Pex window for this target, a valid index is an index that is lower than the number of the windows that was not configured yet */ /* we subtract 2 always because the default and expantion rom windows are always configured */ if ( pexCurrWin < PEX_MAX_TARGET_WIN - 2) { /* set a Pex window for this target ! */ pexWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; pexWin.addrWin.baseLow = addrDecWin.addrWin.baseLow; pexWin.addrWin.size = addrDecWin.addrWin.size; /* we disable the windows at first because we are not sure that it is witihin bar boundries */ pexWin.enable = MV_FALSE; pexWin.target = target; pexWin.targetBar = bar; if (MV_OK != mvPexTargetWinSet(pexIf,pexCurrWin++, &pexWin)) { mvOsPrintf("mvPexInit: ERR. Window Set failed\n"); return MV_ERROR; } } } } } } pexBar.addrWin.size = maxBase - pexBar.addrWin.baseLow + sizeOfMaxBase; pexBar.enable = MV_TRUE; /* check if the size of the bar is illegal */ if (-1 == ctrlSizeToReg(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT)) { /* try to get a good size */ pexBar.addrWin.size = ctrlSizeRegRoundUp(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT); } /* check if the size and base are valid */ if (MV_TRUE == pexBarOverlapDetect(pexIf,bar,&pexBar.addrWin)) { mvOsPrintf("mvPexInit:Warning :Bar %d size is illigal\n",bar); mvOsPrintf("it will be disabled\n"); mvOsPrintf("please check Pex and CPU windows configuration\n"); } else { if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) { mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar); return MV_ERROR; } /* now enable the windows */ for (winNum = pexStartWindow; winNum < pexCurrWin ; winNum++) { if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_TRUE)) { mvOsPrintf("mvPexInit:mvPexTargetWinEnable winNum =%d failed \n", winNum); return MV_ERROR; } } } #endif return mvPexHalInit(pexIf, pexType); }
/******************************************************************************* * mvPexBarSet - Set PEX bar address and size * * DESCRIPTION: * * INPUT: * * OUTPUT: * None. * * RETURN: * MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK * *******************************************************************************/ MV_STATUS mvPexBarSet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *pAddrWin) { MV_U32 regBaseLow; MV_U32 regSize,sizeToReg; /* check parameters */ if(pexIf >= mvCtrlPexMaxIfGet()) { mvOsPrintf("mvPexBarSet: ERR. Invalid PEX interface %d\n", pexIf); return MV_BAD_PARAM; } if(barNum >= PEX_MAX_BARS) { mvOsPrintf("mvPexBarSet: ERR. Invalid bar number %d\n", barNum); return MV_BAD_PARAM; } if (pAddrWin->addrWin.size == 0) { mvOsPrintf("mvPexBarSet: Size zero is Illigal\n" ); return MV_BAD_PARAM; } /* Check if the window complies with PEX spec */ if (MV_TRUE != pexBarIsValid(pAddrWin->addrWin.baseLow, pAddrWin->addrWin.size)) { mvOsPrintf("mvPexBarSet: ERR. Target %d window invalid\n", barNum); return MV_BAD_PARAM; } /* 2) Check if the requested bar overlaps with current bars */ if (MV_TRUE == pexBarOverlapDetect(pexIf,barNum, &pAddrWin->addrWin)) { mvOsPrintf("mvPexBarSet: ERR. Target %d overlap\n", barNum); return MV_BAD_PARAM; } /* Get size register value according to window size */ sizeToReg = ctrlSizeToReg(pAddrWin->addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT); /* Read bar size */ if (PEX_INTER_REGS_BAR != barNum) /* internal registers have no size */ { regSize = MV_REG_READ(PEX_BAR_CTRL_REG(pexIf,barNum)); /* Size parameter validity check. */ if (-1 == sizeToReg) { mvOsPrintf("mvPexBarSet: ERR. Target BAR %d size invalid.\n",barNum); return MV_BAD_PARAM; } regSize &= ~PXBCR_BAR_SIZE_MASK; regSize |= (sizeToReg << PXBCR_BAR_SIZE_OFFS) ; MV_REG_WRITE(PEX_BAR_CTRL_REG(pexIf,barNum),regSize); } /* set size */ /* Read base address low */ regBaseLow = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_MV_BAR_BASE(barNum))); /* clear current base */ if (PEX_INTER_REGS_BAR == barNum) { regBaseLow &= ~PXBIR_BASE_MASK; regBaseLow |= (pAddrWin->addrWin.baseLow & PXBIR_BASE_MASK); } else { regBaseLow &= ~PXBR_BASE_MASK; regBaseLow |= (pAddrWin->addrWin.baseLow & PXBR_BASE_MASK); } /* if we had a previous value that contain the bar type (MeM\IO), we want to restore it */ regBaseLow |= PEX_BAR_DEFAULT_ATTRIB; /* write base low */ MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE(barNum)), regBaseLow); if (pAddrWin->addrWin.baseHigh != 0) { /* Read base address high */ MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE_HIGH(barNum)), pAddrWin->addrWin.baseHigh); } /* lastly enable the Bar */ if (pAddrWin->enable == MV_TRUE) { if (PEX_INTER_REGS_BAR != barNum) /* internal registers are enabled always */ { MV_REG_BIT_SET(PEX_BAR_CTRL_REG(pexIf,barNum),PXBCR_BAR_EN); } } else if (MV_FALSE == pAddrWin->enable) { if (PEX_INTER_REGS_BAR != barNum) /* internal registers are enabled always */ { MV_REG_BIT_RESET(PEX_BAR_CTRL_REG(pexIf,barNum),PXBCR_BAR_EN); } } return MV_OK; }