/******************************************************************************* * mvCpuIfTargetWinSet - Set CPU-to-peripheral target address window * * DESCRIPTION: * This function sets a peripheral target (e.g. SDRAM bank0, PCI0_MEM0) * address window, also known as address decode window. * A new address decode 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 CPU to access * the target window. * * INPUT: * target - Peripheral target enumerator. * pAddrDecWin - CPU target window data structure. * * OUTPUT: * N/A * * RETURN: * MV_OK if CPU target window was set correctly, MV_ERROR in case of * address window overlapps with other active CPU target window or * trying to assign 36bit base address while CPU does not support that. * The function returns MV_NOT_SUPPORTED, if the target is unsupported. * *******************************************************************************/ MV_STATUS mvCpuIfTargetWinSet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin) { MV_AHB_TO_MBUS_DEC_WIN decWin; MV_U32 existingWinNum; MV_DRAM_DEC_WIN addrDecWin; target = MV_CHANGE_BOOT_CS(target); /* Check parameters */ if (target >= MAX_TARGETS) { mvOsPrintf("mvCpuIfTargetWinSet: target %d is illegal\n", target); return MV_ERROR; } /* 2) Check if the requested window overlaps with current windows */ if (MV_TRUE == cpuTargetWinOverlap(target, &pAddrDecWin->addrWin)) { mvOsPrintf("mvCpuIfTargetWinSet: ERR. Target %d overlap\n", target); return MV_BAD_PARAM; } if (MV_TARGET_IS_DRAM(target)) { /* copy relevant data to MV_DRAM_DEC_WIN structure */ addrDecWin.addrWin.baseHigh = pAddrDecWin->addrWin.baseHigh; addrDecWin.addrWin.baseLow = pAddrDecWin->addrWin.baseLow; addrDecWin.addrWin.size = pAddrDecWin->addrWin.size; addrDecWin.enable = pAddrDecWin->enable; if (mvDramIfWinSet(target,&addrDecWin) != MV_OK); { mvOsPrintf("mvCpuIfTargetWinSet: mvDramIfWinSet Failed\n"); return MV_ERROR; } } else { /* copy relevant data to MV_AHB_TO_MBUS_DEC_WIN structure */ decWin.addrWin.baseLow = pAddrDecWin->addrWin.baseLow; decWin.addrWin.baseHigh = pAddrDecWin->addrWin.baseHigh; decWin.addrWin.size = pAddrDecWin->addrWin.size; decWin.enable = pAddrDecWin->enable; decWin.target = target; existingWinNum = mvAhbToMbusWinTargetGet(target); /* check if there is already another Window configured for this target */ if ((existingWinNum < MAX_AHB_TO_MBUS_WINS )&& (existingWinNum != pAddrDecWin->winNum)) { /* if we want to enable the new winow number passed by the user , then the old one should be disabled */ if (MV_TRUE == pAddrDecWin->enable) { /* be sure it is disabled */ mvAhbToMbusWinEnable(existingWinNum , MV_FALSE); } } if (mvAhbToMbusWinSet(pAddrDecWin->winNum,&decWin) != MV_OK) { mvOsPrintf("mvCpuIfTargetWinSet: mvAhbToMbusWinSet Failed\n"); return MV_ERROR; } } 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; }