MV_STATUS mvCtrlAddrDecToParams(MV_DEC_WIN *pAddrDecWin, MV_DEC_WIN_PARAMS *pWinParam) { MV_U32 baseToReg=0, sizeToReg=0; /* BaseLow[31:16] => base register [31:16] */ baseToReg = pAddrDecWin->addrWin.baseLow & CTRL_DEC_BASE_MASK; /* Write to address decode Base Address Register */ pWinParam->baseAddr &= ~CTRL_DEC_BASE_MASK; pWinParam->baseAddr |= baseToReg; /* Get size register value according to window size */ sizeToReg = ctrlSizeToReg(pAddrDecWin->addrWin.size, CTRL_DEC_SIZE_ALIGNMENT); /* Size parameter validity check. */ if (-1 == sizeToReg) { mvOsPrintf("mvCtrlAddrDecToParams: ERR. ctrlSizeToReg failed.\n"); return MV_BAD_PARAM; } pWinParam->size = sizeToReg; pWinParam->attrib = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(pAddrDecWin->target)].attrib; pWinParam->targetId = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(pAddrDecWin->target)].targetId; return MV_OK; }
/******************************************************************************* * mvCtrlAddrDecToParams - Get address decode register format values * * DESCRIPTION: * This function returns the given address window information in the * format of address decode base and size registers. * * INPUT: * pAddrDecWin - Target window data structure. * * OUTPUT: * pWinParam - Address decode window parameters. * * RETURN: * MV_BAD_PARAM if base address is invalid parameter or target is * unknown. * *******************************************************************************/ MV_STATUS mvCtrlAddrDecToParams(MV_DEC_WIN *pAddrDecWin, MV_DEC_WIN_PARAMS *pWinParam) { MV_TARGET_ATTRIB targetAttrib; MV_U32 size; /* Holds BAR size */ /* 2) Initialize Size register */ /* 2.1 Get address decode size register value to given size */ size = ctrlSizeToReg(pAddrDecWin->addrWin.size, BAR_SIZE_ALIGNMENT); /* Size parameter validity check. */ if (-1 == size) { DB(mvOsPrintf("mvCtrlAddrDecToParams: ERR. addrDecSizeToReg failed.\n")); return MV_BAD_PARAM; } /* Write the size register value */ pWinParam->size = size; /* Base address */ pWinParam->baseAddr = pAddrDecWin->addrWin.baseLow; /* attrib and targetId */ mvCtrlAttribGet(pAddrDecWin->target, &targetAttrib); pWinParam->attrib = targetAttrib.attrib; pWinParam->targetId = targetAttrib.targetId; return MV_OK; }
/******************************************************************************* * mvCtrlAddrDecToReg - Get address decode register format values * * DESCRIPTION: * * INPUT: * * OUTPUT: * * RETURN: * *******************************************************************************/ MV_STATUS mvCtrlAddrDecToReg(MV_ADDR_WIN *pAddrDecWin, MV_DEC_REGS *pAddrDecRegs) { MV_U32 baseToReg=0 , sizeToReg=0; /* BaseLow[31:16] => base register [31:16] */ baseToReg = pAddrDecWin->baseLow & CTRL_DEC_BASE_MASK; /* Write to address decode Base Address Register */ pAddrDecRegs->baseReg &= ~CTRL_DEC_BASE_MASK; pAddrDecRegs->baseReg |= baseToReg; /* Get size register value according to window size */ sizeToReg = ctrlSizeToReg(pAddrDecWin->size, CTRL_DEC_SIZE_ALIGNMENT); /* Size parameter validity check. */ if (-1 == sizeToReg) { return MV_BAD_PARAM; } /* set size */ pAddrDecRegs->sizeReg &= ~CTRL_DEC_SIZE_MASK; pAddrDecRegs->sizeReg |= (sizeToReg << CTRL_DEC_SIZE_OFFS); return MV_OK; }
/******************************************************************************* * mvPciTargetWinSet - Set PCI to peripheral target address window BAR * * DESCRIPTION: * This function sets an address window from PCI to a peripheral * target (e.g. SDRAM bank0, PCI_MEM0), also known as BARs. * A new PCI BAR window is set for specified target address window. * If address decode window parameter structure enables the window, * the routine will also enable the target window, allowing PCI to access * the target window. * * INPUT: * pciIf - PCI interface number. * bar - BAR to be accessed by slave. * pAddrBarWin - PCI target window information data structure. * * OUTPUT: * N/A * * RETURN: * MV_OK if PCI BAR target window was set correctly, MV_BAD_PARAM on bad params * MV_ERROR otherwise * (e.g. address window overlapps with other active PCI target window). * *******************************************************************************/ MV_STATUS mvPciTargetWinSet(MV_U32 pciIf, MV_PCI_BAR bar, MV_PCI_BAR_WIN *pAddrBarWin) { MV_U32 pciData; MV_U32 sizeToReg; MV_U32 size; MV_U32 baseLow; MV_U32 baseHigh; MV_U32 localBus; MV_U32 localDev; PCI_BAR_REG_INFO barRegInfo; size = pAddrBarWin->addrWin.size; baseLow = pAddrBarWin->addrWin.baseLow; baseHigh = pAddrBarWin->addrWin.baseHigh; /* Parameter checking */ if(pciIf >= mvCtrlPciMaxIfGet()) { mvOsPrintf("mvPciTargetWinSet: ERR. Invalid PCI interface %d\n", pciIf); return MV_BAD_PARAM; } if(bar >= PCI_MAX_BARS ) { mvOsPrintf("mvPciTargetWinSet: ERR. Illigal PCI BAR %d\n", bar); return MV_BAD_PARAM; } /* if the address windows is disabled , we only disable the appropriare pci bar and ignore other settings */ if (MV_FALSE == pAddrBarWin->enable) { MV_REG_BIT_SET(PCI_BASE_ADDR_ENABLE_REG(pciIf), BARER_ENABLE(bar)); return MV_OK; } if (0 == pAddrBarWin->addrWin.size) { mvOsPrintf("mvPciTargetWinSet: ERR. Target %d can't be zero!\n",bar); return MV_BAD_PARAM; } /* Check if the window complies with PCI spec */ if (MV_TRUE != pciWinIsValid(baseLow, size)) { mvOsPrintf("mvPciTargetWinSet: ERR. Target %d window invalid\n", bar); return MV_BAD_PARAM; } /* 2) Check if the requested window overlaps with current windows */ if(MV_TRUE == pciWinOverlapDetect(pciIf, bar, &pAddrBarWin->addrWin)) { mvOsPrintf("mvPciTargetWinSet: ERR. Overlap detected for target %d\n", bar); return MV_BAD_PARAM; } /* Get size register value according to window size */ sizeToReg = ctrlSizeToReg(size, PBBLR_BASE_ALIGNMET); /* Size parameter validity check. */ if (-1 == sizeToReg) { mvOsPrintf("mvPciTargetWinSet: ERR. Target BAR %d size invalid.\n",bar); return MV_BAD_PARAM; } localBus = mvPciLocalBusNumGet(pciIf); localDev = mvPciLocalDevNumGet(pciIf); /* Get BAR register information */ pciBarRegInfoGet(pciIf, bar, &barRegInfo); /* Internal register space size have no size register. Do not perform */ /* size register assigment for this slave target */ if (0 != barRegInfo.sizeRegOffs) { /* Update size register */ MV_REG_WRITE(barRegInfo.sizeRegOffs, (sizeToReg << BAR_SIZE_OFFS)); } /* Read current address */ pciData = mvPciConfigRead(pciIf, localBus, localDev, barRegInfo.funcNum, barRegInfo.baseLowRegOffs); /* Clear current address */ pciData &= ~PBBLR_BASE_MASK; pciData |= (baseLow & PBBLR_BASE_MASK); /* Write new address */ mvPciConfigWrite(pciIf, localBus, localDev, barRegInfo.funcNum, barRegInfo.baseLowRegOffs, pciData); /* Skip base high settings if the BAR has only base low (32-bit) */ if (0 != barRegInfo.baseHighRegOffs) { mvPciConfigWrite(pciIf, localBus, localDev, barRegInfo.funcNum, barRegInfo.baseHighRegOffs, baseHigh); } /* Enable/disable the BAR */ if (MV_TRUE == pAddrBarWin->enable) { MV_REG_BIT_RESET(PCI_BASE_ADDR_ENABLE_REG(pciIf), BARER_ENABLE(bar)); } else { MV_REG_BIT_SET(PCI_BASE_ADDR_ENABLE_REG(pciIf), BARER_ENABLE(bar)); } 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; }
/******************************************************************************* * mvDramIfWinSet - Set DRAM interface address decode window * * DESCRIPTION: * This function sets DRAM interface address decode window. * * INPUT: * target - System target. Use only SDRAM targets. * pAddrDecWin - SDRAM address window structure. * * OUTPUT: * None * * RETURN: * MV_BAD_PARAM if parameters are invalid or window is invalid, MV_OK * otherwise. *******************************************************************************/ MV_STATUS mvDramIfWinSet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin) { MV_U32 baseReg=0,sizeReg=0; MV_U32 baseToReg=0 , sizeToReg=0; /* Check parameters */ if (!MV_TARGET_IS_DRAM(target)) { mvOsPrintf("mvDramIfWinSet: target %d is not SDRAM\n", target); return MV_BAD_PARAM; } /* Check if the requested window overlaps with current enabled windows */ if (MV_TRUE == sdramIfWinOverlap(target, &pAddrDecWin->addrWin)) { mvOsPrintf("mvDramIfWinSet: ERR. Target %d overlaps\n", target); return MV_BAD_PARAM; } /* check if address is aligned to the size */ if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) { mvOsPrintf("mvDramIfWinSet:Error setting DRAM interface window %d."\ "\nAddress 0x%08x is unaligned to size 0x%x.\n", target, pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size); return MV_ERROR; } /* read base register*/ baseReg = MV_REG_READ(SDRAM_BASE_ADDR_REG(target)); /* read size register */ sizeReg = MV_REG_READ(SDRAM_SIZE_REG(target)); /* BaseLow[31:16] => base register [31:16] */ baseToReg = pAddrDecWin->addrWin.baseLow & SCBAR_BASE_MASK; /* Write to address decode Base Address Register */ baseReg &= ~SCBAR_BASE_MASK; baseReg |= baseToReg; /* Translate the given window size to register format */ sizeToReg = ctrlSizeToReg(pAddrDecWin->addrWin.size, SCSR_SIZE_ALIGNMENT); /* Size parameter validity check. */ if (-1 == sizeToReg) { mvOsPrintf("mvCtrlAddrDecToReg: ERR. Win %d size invalid.\n",target); return MV_BAD_PARAM; } /* set size */ sizeReg &= ~SCSR_SIZE_MASK; /* Size is located at upper 16 bits */ sizeReg |= (sizeToReg << SCSR_SIZE_OFFS); /* enable/Disable */ if (MV_TRUE == pAddrDecWin->enable) { sizeReg |= SCSR_WIN_EN; } else { sizeReg &= ~SCSR_WIN_EN; } /* 3) Write to address decode Base Address Register */ MV_REG_WRITE(SDRAM_BASE_ADDR_REG(target), baseReg); /* Write to address decode Size Register */ MV_REG_WRITE(SDRAM_SIZE_REG(target), sizeReg); return MV_OK; }
/******************************************************************************* * mvDramIfDetect - Prepare DRAM interface configuration values. * * DESCRIPTION: * This function implements the full DRAM detection and timing * configuration for best system performance. * Since this routine runs from a ROM device (Boot Flash), its stack * resides on RAM, that might be the system DRAM. Changing DRAM * configuration values while keeping vital data in DRAM is risky. That * is why the function does not preform the configuration setting but * prepare those in predefined 32bit registers (in this case IDMA * registers are used) for other routine to perform the settings. * The function will call for board DRAM SPD information for each DRAM * chip select. The function will then analyze those SPD parameters of * all DRAM banks in order to decide on DRAM configuration compatible * for all DRAM banks. * The function will set the CPU DRAM address decode registers. * Note: This routine prepares values that will overide configuration of * mvDramBasicAsmInit(). * * INPUT: * forcedCl - Forced CAL Latency. If equal to zero, do not force. * * OUTPUT: * None. * * RETURN: * None. * *******************************************************************************/ MV_STATUS mvDramIfDetect(MV_U32 forcedCl) { MV_U32 retVal = MV_OK; /* return value */ MV_DRAM_BANK_INFO bankInfo[MV_DRAM_MAX_CS]; MV_U32 busClk, size, base = 0, i, temp, deviceW, dimmW; MV_U8 minCas; MV_DRAM_DEC_WIN dramDecWin; dramDecWin.addrWin.baseHigh = 0; busClk = mvBoardSysClkGet(); if (0 == busClk) { mvOsPrintf("Dram: ERR. Can't detect system clock! \n"); return MV_ERROR; } /* Close DRAM banks except bank 0 (in case code is excecuting from it...) */ for(i= SDRAM_CS1; i <= SDRAM_CS3; i++) mvCpuIfTargetWinEnable(i, MV_FALSE); /* we will use bank 0 as the representative of the all the DRAM banks, */ /* since bank 0 must exist. */ for(i = 0; i < MV_DRAM_MAX_CS; i++) { /* if Bank exist */ if(MV_OK == mvDramBankInfoGet(i, &bankInfo[i])) { /* check it isn't SDRAM */ if(bankInfo[i].memoryType == MEM_TYPE_SDRAM) { mvOsPrintf("Dram: ERR. SDRAM type not supported !!!\n"); return MV_ERROR; } /* All banks must support registry in order to activate it */ if(bankInfo[i].registeredAddrAndControlInputs != bankInfo[0].registeredAddrAndControlInputs) { mvOsPrintf("Dram: ERR. different Registered settings !!!\n"); return MV_ERROR; } /* Init the CPU window decode */ /* Note that the size in Bank info is in MB units */ /* Note that the Dimm width might be different then the device DRAM width */ temp = MV_REG_READ(SDRAM_CONFIG_REG); deviceW = ((temp & SDRAM_DWIDTH_MASK) == SDRAM_DWIDTH_16BIT )? 16 : 32; dimmW = bankInfo[0].dataWidth - (bankInfo[0].dataWidth % 16); size = ((bankInfo[i].size << 20) / (dimmW/deviceW)); /* We can not change DRAM window settings while excecuting */ /* code from it. That is why we skip the DRAM CS[0], saving */ /* it to the ROM configuration routine */ if(i == SDRAM_CS0) { MV_U32 sizeToReg; /* Translate the given window size to register format */ sizeToReg = ctrlSizeToReg(size, SCSR_SIZE_ALIGNMENT); /* Size parameter validity check. */ if (-1 == sizeToReg) { mvOsPrintf("mvCtrlAddrDecToReg: ERR. Win %d size invalid.\n" ,i); return MV_BAD_PARAM; } /* Size is located at upper 16 bits */ sizeToReg <<= SCSR_SIZE_OFFS; /* enable it */ sizeToReg |= SCSR_WIN_EN; MV_REG_WRITE(DRAM_BUF_REG0, sizeToReg); } else { dramDecWin.addrWin.baseLow = base; dramDecWin.addrWin.size = size; dramDecWin.enable = MV_TRUE; if (MV_OK != mvDramIfWinSet(SDRAM_CS0 + i, &dramDecWin)) { mvOsPrintf("Dram: ERR. Fail to set bank %d!!!\n", SDRAM_CS0 + i); return MV_ERROR; } } base += size; /* update the suportedCasLatencies mask */ bankInfo[0].suportedCasLatencies &= bankInfo[i].suportedCasLatencies; } else { if( i == 0 ) /* bank 0 doesn't exist */ { mvOsPrintf("Dram: ERR. Fail to detect bank 0 !!!\n"); return MV_ERROR; } else { DB(mvOsPrintf("Dram: Could not find bank %d\n", i)); bankInfo[i].size = 0; /* Mark this bank as non exist */ } } } /* calculate minimum CAS */ minCas = minCasCalc(&bankInfo[0], busClk, forcedCl); if (0 == minCas) { mvOsOutput("Dram: Warn: Could not find CAS compatible to SysClk %dMhz\n", (busClk / 1000000)); if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) { minCas = DDR2_CL_4; /* Continue with this CAS */ mvOsPrintf("Set default CAS latency 4\n"); } else { minCas = DDR1_CL_3; /* Continue with this CAS */ mvOsPrintf("Set default CAS latency 3\n"); } } /* calc SDRAM_CONFIG_REG and save it to temp register */ temp = sdramConfigRegCalc(&bankInfo[0], busClk); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramConfigRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG1, temp); /* calc SDRAM_MODE_REG and save it to temp register */ temp = sdramModeRegCalc(minCas); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramModeRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG2, temp); /* calc SDRAM_EXTENDED_MODE_REG and save it to temp register */ temp = sdramExtModeRegCalc(&bankInfo[0]); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramModeRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG10, temp); /* calc D_UNIT_CONTROL_LOW and save it to temp register */ temp = dunitCtrlLowRegCalc(&bankInfo[0], minCas); if(-1 == temp) { mvOsPrintf("Dram: ERR. dunitCtrlLowRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG3, temp); /* calc SDRAM_ADDR_CTRL_REG and save it to temp register */ temp = sdramAddrCtrlRegCalc(&bankInfo[0]); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramAddrCtrlRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG4, temp); /* calc SDRAM_TIMING_CTRL_LOW_REG and save it to temp register */ temp = sdramTimeCtrlLowRegCalc(&bankInfo[0], minCas, busClk); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramTimeCtrlLowRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG5, temp); /* calc SDRAM_TIMING_CTRL_HIGH_REG and save it to temp register */ temp = sdramTimeCtrlHighRegCalc(&bankInfo[0], busClk); if(-1 == temp) { mvOsPrintf("Dram: ERR. sdramTimeCtrlHighRegCalc failed !!!\n"); return MV_ERROR; } MV_REG_WRITE(DRAM_BUF_REG6, temp); /* Config DDR2 On Die Termination (ODT) registers */ if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) { sdramDDr2OdtConfig(bankInfo); } /* Note that DDR SDRAM Address/Control and Data pad calibration */ /* settings is done in mvSdramIfConfig.s */ return retVal; }