/******************************************************************************* * mvCpuIfTargetWinGet - Get CPU-to-peripheral target address window * * DESCRIPTION: * Get the CPU peripheral target address window. * * INPUT: * target - Peripheral target enumerator * * OUTPUT: * pAddrDecWin - CPU target window information data structure. * * RETURN: * MV_OK if target exist, MV_ERROR otherwise. * *******************************************************************************/ MV_STATUS mvCpuIfTargetWinGet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin) { MV_U32 winNum=0xffffffff; MV_AHB_TO_MBUS_DEC_WIN decWin; MV_DRAM_DEC_WIN addrDecWin; target = MV_CHANGE_BOOT_CS(target); /* Check parameters */ if (target >= MAX_TARGETS) { mvOsPrintf("mvCpuIfTargetWinGet: target %d is illegal\n", target); return MV_ERROR; } if (MV_TARGET_IS_DRAM(target)) { if (mvDramIfWinGet(target,&addrDecWin) != MV_OK) { mvOsPrintf("mvCpuIfTargetWinGet: Failed to get window target %d\n", target); return MV_ERROR; } /* copy relevant data to MV_CPU_DEC_WIN structure */ pAddrDecWin->addrWin.baseLow = addrDecWin.addrWin.baseLow; pAddrDecWin->addrWin.baseHigh = addrDecWin.addrWin.baseHigh; pAddrDecWin->addrWin.size = addrDecWin.addrWin.size; pAddrDecWin->enable = addrDecWin.enable; pAddrDecWin->winNum = 0xffffffff; } else { /* get the Window number associated with this target */ winNum = mvAhbToMbusWinTargetGet(target); if (winNum >= MAX_AHB_TO_MBUS_WINS) { return MV_NO_SUCH; } if (mvAhbToMbusWinGet(winNum , &decWin) != MV_OK) { mvOsPrintf("%s: mvAhbToMbusWinGet Failed at winNum = %d\n", __FUNCTION__, winNum); return MV_ERROR; } /* copy relevant data to MV_CPU_DEC_WIN structure */ pAddrDecWin->addrWin.baseLow = decWin.addrWin.baseLow; pAddrDecWin->addrWin.baseHigh = decWin.addrWin.baseHigh; pAddrDecWin->addrWin.size = decWin.addrWin.size; pAddrDecWin->enable = decWin.enable; pAddrDecWin->winNum = winNum; } return MV_OK; }
/******************************************************************************* * mvDramIfBankSizeGet - Get DRAM interface bank size. * * DESCRIPTION: * This function returns the size of a given DRAM bank. * * INPUT: * bankNum - Bank number. * * OUTPUT: * None. * * RETURN: * DRAM bank size. If bank is disabled the function return '0'. In case * or paramter is invalid, the function returns -1. * *******************************************************************************/ MV_U32 mvDramIfBankSizeGet(MV_U32 bankNum) { MV_DRAM_DEC_WIN addrDecWin; /* Check parameters */ if (!MV_TARGET_IS_DRAM(bankNum)) { mvOsPrintf("mvDramIfBankBaseGet: bankNum %d is invalid\n", bankNum); return -1; } /* Get window parameters */ if (MV_OK != mvDramIfWinGet(bankNum, &addrDecWin)) { mvOsPrintf("sdramIfWinOverlap: ERR. TargetWinGet failed\n"); return -1; } if (MV_TRUE == addrDecWin.enable) { return addrDecWin.addrWin.size; } else { return 0; } }
/******************************************************************************* * mvCpuIfTargetWinEnable - Enable/disable a CPU address decode window * * DESCRIPTION: * This function enable/disable a CPU address decode window. * if parameter 'enable' == MV_TRUE the routine will enable the * window, thus enabling CPU accesses (before enabling the window it is * tested for overlapping). Otherwise, the window will be disabled. * * INPUT: * target - Peripheral target enumerator. * enable - Enable/disable parameter. * * OUTPUT: * N/A * * RETURN: * MV_ERROR if protection window number was wrong, or the window * overlapps other target window. * *******************************************************************************/ MV_STATUS mvCpuIfTargetWinEnable(MV_TARGET target,MV_BOOL enable) { MV_U32 winNum, temp; MV_CPU_DEC_WIN addrDecWin; /* Check parameters */ if (target >= MAX_TARGETS) { mvOsPrintf("mvCpuIfTargetWinEnable: target %d is Illigal\n", target); return MV_ERROR; } /* get the window and check if it exist */ temp = mvCpuIfTargetWinGet(target, &addrDecWin); if (MV_NO_SUCH == temp) { return (enable? MV_ERROR: MV_OK); } else if( MV_OK != temp) { mvOsPrintf("%s: ERR. Getting target %d failed.\n",__FUNCTION__, target); return MV_ERROR; } /* check overlap */ if (MV_TRUE == enable) { if (MV_TRUE == cpuTargetWinOverlap(target, &addrDecWin.addrWin)) { DB(mvOsPrintf("%s: ERR. Target %d overlap\n",__FUNCTION__, target)); return MV_ERROR; } } if (!MV_TARGET_IS_DRAM(target)) { /* get the Window number associated with this target */ winNum = mvAhbToMbusWinTargetGet(target); if (winNum >= MAX_AHB_TO_MBUS_WINS) { return (enable? MV_ERROR: MV_OK); } if (mvAhbToMbusWinEnable(winNum , enable) != MV_OK) { mvOsPrintf("mvCpuIfTargetWinGet: Failed to enable window = %d\n", winNum); return MV_ERROR; } } return MV_OK; }
/******************************************************************************* * mvDramIfWinGet - Get DRAM interface address decode window * * DESCRIPTION: * This function gets DRAM interface address decode window. * * INPUT: * target - System target. Use only SDRAM targets. * * OUTPUT: * pAddrDecWin - SDRAM address window structure. * * RETURN: * MV_BAD_PARAM if parameters are invalid or window is invalid, MV_OK * otherwise. *******************************************************************************/ MV_STATUS mvDramIfWinGet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin) { MV_U32 baseReg,sizeReg; MV_U32 sizeRegVal; /* Check parameters */ if (!MV_TARGET_IS_DRAM(target)) { mvOsPrintf("mvDramIfWinGet: target %d is Illigal\n", target); return MV_ERROR; } /* Read base and size registers */ sizeReg = MV_REG_READ(SDRAM_SIZE_REG(target)); baseReg = MV_REG_READ(SDRAM_BASE_ADDR_REG(target)); sizeRegVal = (sizeReg & SCSR_SIZE_MASK) >> SCSR_SIZE_OFFS; pAddrDecWin->addrWin.size = ctrlRegToSize(sizeRegVal, SCSR_SIZE_ALIGNMENT); /* Check if ctrlRegToSize returned OK */ if (-1 == pAddrDecWin->addrWin.size) { mvOsPrintf("mvDramIfWinGet: size of target %d is Illigal\n", target); return MV_ERROR; } /* Extract base address */ /* Base register [31:16] ==> baseLow[31:16] */ pAddrDecWin->addrWin.baseLow = baseReg & SCBAR_BASE_MASK; pAddrDecWin->addrWin.baseHigh = 0; if (sizeReg & SCSR_WIN_EN) { pAddrDecWin->enable = MV_TRUE; } else { pAddrDecWin->enable = MV_FALSE; } return MV_OK; }
/******************************************************************************* * mvDramIfWinEnable - Enable/Disable SDRAM address decode window * * DESCRIPTION: * This function enable/Disable SDRAM address decode window. * * INPUT: * target - System target. Use only SDRAM targets. * * OUTPUT: * None. * * RETURN: * MV_ERROR in case function parameter are invalid, MV_OK otherewise. * *******************************************************************************/ MV_STATUS mvDramIfWinEnable(MV_TARGET target,MV_BOOL enable) { MV_DRAM_DEC_WIN addrDecWin; /* Check parameters */ if (!MV_TARGET_IS_DRAM(target)) { mvOsPrintf("mvDramIfWinEnable: target %d is Illigal\n", target); return MV_ERROR; } if (enable == MV_TRUE) { /* First check for overlap with other enabled windows */ if (MV_OK != mvDramIfWinGet(target, &addrDecWin)) { mvOsPrintf("mvDramIfWinEnable:ERR. Getting target %d failed.\n", target); return MV_ERROR; } /* Check for overlapping */ if (MV_FALSE == sdramIfWinOverlap(target, &(addrDecWin.addrWin))) { /* No Overlap. Enable address decode winNum window */ MV_REG_BIT_SET(SDRAM_SIZE_REG(target), SCSR_WIN_EN); } else { /* Overlap detected */ mvOsPrintf("mvDramIfWinEnable: ERR. Target %d overlap detect\n", target); return MV_ERROR; } } else { /* Disable address decode winNum window */ MV_REG_BIT_RESET(SDRAM_SIZE_REG(target), SCSR_WIN_EN); } return MV_OK; }
/******************************************************************************* * 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; }
/******************************************************************************* * mvCpuIfInit - Initialize Controller CPU interface * * DESCRIPTION: * This function initialize Controller CPU interface: * 1. Set CPU interface configuration registers. * 2. Set CPU master Pizza arbiter control according to static * configuration described in configuration file. * 3. Opens CPU address decode windows. DRAM windows are assumed to be * already set (auto detection). * * INPUT: * None. * * OUTPUT: * None. * * RETURN: * None. * *******************************************************************************/ MV_STATUS mvCpuIfInit(MV_CPU_DEC_WIN *cpuAddrWinMap) { MV_U32 regVal; MV_TARGET target; MV_ADDR_WIN addrWin; int ii; if (cpuAddrWinMap == NULL) { DB(mvOsPrintf("mvCpuIfInit:ERR. cpuAddrWinMap == NULL\n")); return MV_ERROR; } /* Set ARM Configuration register */ regVal = MV_REG_READ(CPU_CONFIG_REG); regVal &= ~CPU_CONFIG_DEFAULT_MASK; /* regVal |= CPU_CONFIG_DEFAULT; Note: not needed */ MV_REG_WRITE(CPU_CONFIG_REG,regVal); /* First disable all CPU target windows */ for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) { if ((MV_TARGET_IS_DRAM(target))||(target == INTER_REGS)) { continue; } #if defined(MV_MEM_OVER_PCI_WA) || defined(MV_UART_OVER_PCI_WA) /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ if (MV_TARGET_IS_PCI(target)) { continue; } #endif #if defined(MV_MEM_OVER_PEX_WA) || defined(MV_UART_OVER_PEX_WA) /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ if (MV_TARGET_IS_PEX(target)) { continue; } #endif #if defined(MV_RUN_FROM_FLASH) /* Don't disable the boot device. */ if (target == DEV_BOOCS) { continue; } #endif /* MV_RUN_FROM_FLASH */ mvCpuIfTargetWinEnable(MV_CHANGE_BOOT_CS(target),MV_FALSE); } /* TODO */ for (ii = 0; ii < 8; ii++) MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(ii), 0); #if defined(MV_RUN_FROM_FLASH) /* Resize the bootcs windows before other windows, because this */ /* window is enabled and will cause an overlap if not resized. */ target = DEV_BOOCS; if (MV_OK != mvCpuIfTargetWinSet(target, &cpuAddrWinMap[target])) { DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n")); return MV_ERROR; } addrWin.baseLow = cpuAddrWinMap[target].addrWin.baseLow; addrWin.baseHigh = cpuAddrWinMap[target].addrWin.baseHigh; if (0xffffffff == mvAhbToMbusWinRemap(cpuAddrWinMap[target].winNum ,&addrWin)) { DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n", cpuAddrWinMap[target].winNum)); } #endif /* MV_RUN_FROM_FLASH */ /* Go through all targets in user table until table terminator */ for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) { #if defined(MV_RUN_FROM_FLASH) if (target == DEV_BOOCS) { continue; } #endif /* MV_RUN_FROM_FLASH */ /* if DRAM auto sizing is used do not initialized DRAM target windows, */ /* assuming this already has been done earlier. */ #ifdef MV_DRAM_AUTO_SIZE if (MV_TARGET_IS_DRAM(target)) { continue; } #endif #if defined(MV_MEM_OVER_PCI_WA) || defined(MV_UART_OVER_PCI_WA) /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ if (MV_TARGET_IS_PCI(target)) { continue; } #endif #if defined(MV_MEM_OVER_PEX_WA) || defined(MV_UART_OVER_PEX_WA) /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ if (MV_TARGET_IS_PEX(target)) { continue; } #endif /* If the target attribute is the same as the boot device attribute */ /* then it's stays disable */ if (MV_TARGET_IS_AS_BOOT(target)) { continue; } if((0 == cpuAddrWinMap[target].addrWin.size) || (DIS == cpuAddrWinMap[target].enable)) { if (MV_OK != mvCpuIfTargetWinEnable(target, MV_FALSE)) { DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinEnable fail\n")); return MV_ERROR; } } else { if (MV_OK != mvCpuIfTargetWinSet(target, &cpuAddrWinMap[target])) { DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n")); return MV_ERROR; } addrWin.baseLow = cpuAddrWinMap[target].addrWin.baseLow; addrWin.baseHigh = cpuAddrWinMap[target].addrWin.baseHigh; if (0xffffffff == mvAhbToMbusWinRemap(cpuAddrWinMap[target].winNum ,&addrWin)) { DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n", cpuAddrWinMap[target].winNum)); } } } #ifdef MV_INCLUDE_PEX mvCpuIfEnablePex(); #endif #ifdef MV_INCLUDE_PMU mvCpuIfEnablePmu(); #endif return MV_OK; }
/******************************************************************************* * mvCpuIfInit - Initialize Controller CPU interface * * DESCRIPTION: * This function initialize Controller CPU interface: * 1. Set CPU interface configuration registers. * 2. Set CPU master Pizza arbiter control according to static * configuration described in configuration file. * 3. Opens CPU address decode windows. DRAM windows are assumed to be * already set (auto detection). * * INPUT: * None. * * OUTPUT: * None. * * RETURN: * None. * *******************************************************************************/ MV_STATUS mvCpuIfInit(MV_CPU_DEC_WIN *cpuAddrWinMap) { MV_U32 regVal; MV_TARGET target; MV_ADDR_WIN addrWin; if (cpuAddrWinMap == NULL) { DB(mvOsPrintf("mvCpuIfInit:ERR. cpuAddrWinMap == NULL\n")); return MV_ERROR; } /*Initialize the boot target array according to device type*/ if(mvCtrlModelGet() == MV_6180_DEV_ID || mvCtrlModelGet() == MV_6280_DEV_ID) sampleAtResetTargetArray = sampleAtResetTargetArray6180P; else sampleAtResetTargetArray = sampleAtResetTargetArrayP; /* Set ARM Configuration register */ regVal = MV_REG_READ(CPU_CONFIG_REG); regVal &= ~CPU_CONFIG_DEFAULT_MASK; regVal |= CPU_CONFIG_DEFAULT; MV_REG_WRITE(CPU_CONFIG_REG,regVal); /* First disable all CPU target windows */ for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) { if ((MV_TARGET_IS_DRAM(target))||(target == INTER_REGS)) { continue; } #if defined(MV_MEM_OVER_PCI_WA) || defined(MV_UART_OVER_PCI_WA) /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ if (MV_TARGET_IS_PCI(target)) { continue; } #endif #if defined(MV_MEM_OVER_PEX_WA) || defined(MV_UART_OVER_PEX_WA) /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ if (MV_TARGET_IS_PEX(target)) { continue; } #endif #if defined(MV_RUN_FROM_FLASH) /* Don't disable the boot device. */ if (target == DEV_BOOCS) { continue; } #endif /* MV_RUN_FROM_FLASH */ /* Only MV88F6282 have 2 PCIe interfaces */ if((mvCtrlModelGet() != MV_6282_DEV_ID) && MV_TARGET_IS_PEX1(target)) continue; mvCpuIfTargetWinEnable(MV_CHANGE_BOOT_CS(target),MV_FALSE); } #if defined(MV_RUN_FROM_FLASH) /* Resize the bootcs windows before other windows, because this */ /* window is enabled and will cause an overlap if not resized. */ target = DEV_BOOCS; if (MV_OK != mvCpuIfTargetWinSet(target, &cpuAddrWinMap[target])) { DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n")); return MV_ERROR; } addrWin.baseLow = cpuAddrWinMap[target].addrWin.baseLow; addrWin.baseHigh = cpuAddrWinMap[target].addrWin.baseHigh; if (0xffffffff == mvAhbToMbusWinRemap(cpuAddrWinMap[target].winNum ,&addrWin)) { DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n", cpuAddrWinMap[target].winNum)); } #endif /* MV_RUN_FROM_FLASH */ /* Go through all targets in user table until table terminator */ for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) { #if defined(MV_RUN_FROM_FLASH) if (target == DEV_BOOCS) { continue; } #endif /* MV_RUN_FROM_FLASH */ /* if DRAM auto sizing is used do not initialized DRAM target windows, */ /* assuming this already has been done earlier. */ #ifdef MV_DRAM_AUTO_SIZE if (MV_TARGET_IS_DRAM(target)) { continue; } #endif #if defined(MV_MEM_OVER_PCI_WA) || defined(MV_UART_OVER_PCI_WA) /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ if (MV_TARGET_IS_PCI(target)) { continue; } #endif #if defined(MV_MEM_OVER_PEX_WA) || defined(MV_UART_OVER_PEX_WA) /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ if (MV_TARGET_IS_PEX(target)) { continue; } #endif /* If the target attribute is the same as the boot device attribute */ /* then it's stays disable */ if (MV_TARGET_IS_AS_BOOT(target)) { continue; } /* Only MV88F6282 have 2 PCIe interfaces */ if((mvCtrlModelGet() != MV_6282_DEV_ID) && MV_TARGET_IS_PEX1(target)) continue; if((0 == cpuAddrWinMap[target].addrWin.size) || (DIS == cpuAddrWinMap[target].enable)) { if (MV_OK != mvCpuIfTargetWinEnable(target, MV_FALSE)) { DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinEnable fail\n")); return MV_ERROR; } } else { if (MV_OK != mvCpuIfTargetWinSet(target, &cpuAddrWinMap[target])) { DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n")); return MV_ERROR; } addrWin.baseLow = cpuAddrWinMap[target].addrWin.baseLow; addrWin.baseHigh = cpuAddrWinMap[target].addrWin.baseHigh; if (0xffffffff == mvAhbToMbusWinRemap(cpuAddrWinMap[target].winNum ,&addrWin)) { DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n", cpuAddrWinMap[target].winNum)); } } } return MV_OK; }
/******************************************************************************* * mvCpuIfTargetWinGet - Get CPU-to-peripheral target address window * * DESCRIPTION: * Get the CPU peripheral target address window. * * INPUT: * target - Peripheral target enumerator * * OUTPUT: * pAddrDecWin - CPU target window information data structure. * * RETURN: * MV_OK if target exist, MV_ERROR otherwise. * *******************************************************************************/ MV_STATUS mvCpuIfTargetWinGet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin) { MV_U32 winNum = 0xffffffff; MV_AHB_TO_MBUS_DEC_WIN decWin; MV_DRAM_DEC_WIN addrDecWin; MV_U32 dramEn = 0; MV_TARGET i; target = MV_CHANGE_BOOT_CS(target); /* Check parameters */ if (target >= MAX_TARGETS) { mvOsPrintf("mvCpuIfTargetWinGet: target %d is illegal\n", target); return MV_ERROR; } if (MV_TARGET_IS_DRAM(target)) { /* If none of the DRAM windows is enabled, then the CPU DRAM ** access is going through the XBAR. */ for (i = SDRAM_CS0; i < SDRAM_CS3; i++) { if (mvDramIfWinGet(target, &addrDecWin) != MV_OK) { mvOsPrintf("mvCpuIfTargetWinGet: Failed to get window target %d\n", i); return MV_ERROR; } if (addrDecWin.enable == MV_TRUE) dramEn = 1; } } if ((dramEn == 1) && (MV_TARGET_IS_DRAM(target))) { if (mvDramIfWinGet(target, &addrDecWin) != MV_OK) { mvOsPrintf("mvCpuIfTargetWinGet: Failed to get window target %d\n", target); return MV_ERROR; } /* copy relevant data to MV_CPU_DEC_WIN structure */ pAddrDecWin->addrWin.baseLow = addrDecWin.addrWin.baseLow; pAddrDecWin->addrWin.baseHigh = addrDecWin.addrWin.baseHigh; pAddrDecWin->addrWin.size = addrDecWin.addrWin.size; pAddrDecWin->enable = addrDecWin.enable; pAddrDecWin->winNum = 0xffffffff; } else { /* get the Window number associated with this target */ winNum = mvAhbToMbusWinTargetGet(target); if (winNum >= MAX_AHB_TO_MBUS_WINS) return MV_NO_SUCH; if (mvAhbToMbusWinGet(winNum, &decWin) != MV_OK) { mvOsPrintf("%s: mvAhbToMbusWinGet Failed at winNum = %d\n", __func__, winNum); return MV_ERROR; } /* copy relevant data to MV_CPU_DEC_WIN structure */ pAddrDecWin->addrWin.baseLow = decWin.addrWin.baseLow; pAddrDecWin->addrWin.baseHigh = decWin.addrWin.baseHigh; pAddrDecWin->addrWin.size = decWin.addrWin.size; pAddrDecWin->enable = decWin.enable; pAddrDecWin->winNum = winNum; } return MV_OK; }
/******************************************************************************* * mvCpuIfInit - Initialize Controller CPU interface * * DESCRIPTION: * This function initialize Controller CPU interface: * 1. Set CPU interface configuration registers. * 2. Set CPU master Pizza arbiter control according to static * configuration described in configuration file. * 3. Opens CPU address decode windows. DRAM windows are assumed to be * already set (auto detection). * * INPUT: * None. * * OUTPUT: * None. * * RETURN: * None. * *******************************************************************************/ MV_STATUS mvCpuIfInit(void) { MV_U32 regVal; MV_TARGET target; MV_ADDR_WIN addrWin; /* Set ARM Configuration register */ regVal = MV_REG_READ(CPU_CONFIG_REG); regVal &= ~CPU_CONFIG_DEFAULT_MASK; regVal |= CPU_CONFIG_DEFAULT; MV_REG_WRITE(CPU_CONFIG_REG,regVal); /* Set ARM Control and Status register */ regVal = MV_REG_READ(CPU_CTRL_STAT_REG); regVal &= ~CPU_CTRL_STAT_DEFAULT_MASK; regVal |= CPU_CTRL_STAT_DEFAULT; MV_REG_WRITE(CPU_CTRL_STAT_REG,regVal); /* First disable all CPU target windows */ for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) { if ((MV_TARGET_IS_DRAM(target))||(target == INTER_REGS)) { continue; } mvCpuIfTargetWinEnable(target,MV_FALSE); } /* Go through all targets in user table until table terminator */ for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) { /* if DRAM auto sizing is used do not initialized DRAM target windows, */ /* assuming this already has been done earlier. */ #ifdef MV_DRAM_AUTO_SIZE if (MV_TARGET_IS_DRAM(target)) { continue; } #endif if((0 == cpuAddrWinMap[target].addrWin.size) || (MV_FALSE == cpuAddrWinMap[target].enable)) { if (MV_OK != mvCpuIfTargetWinEnable(target, MV_FALSE)) { DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinEnable fail\n")); return MV_ERROR; } } else { if (MV_OK != mvCpuIfTargetWinSet(target, &cpuAddrWinMap[target])) { DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n")); return MV_ERROR; } addrWin.baseLow = cpuAddrWinMap[target].addrWin.baseLow; addrWin.baseHigh = cpuAddrWinMap[target].addrWin.baseHigh; if (0xffffffff == mvAhbToMbusWinRemap(cpuAddrWinMap[target].winNum ,&addrWin)) { DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n", cpuAddrWinMap[target].winNum)); } } } return MV_OK; }
/******************************************************************************* * mvUsbWinSet - Set USB target address window * * DESCRIPTION: * This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0) * address window, also known as address decode window. * After setting this target window, the USB will be able to access the * target within the address window. * * INPUT: * winNum - USB target address decode window number. * pAddrDecWin - USB target window data structure. * * OUTPUT: * None. * * RETURN: * MV_ERROR if address window overlapps with other address decode windows. * MV_BAD_PARAM if base address is invalid parameter or target is * unknown. * *******************************************************************************/ MV_STATUS mvUsbWinSet(int dev, MV_U32 winNum, MV_DEC_WIN *pDecWin) { MV_DEC_WIN_PARAMS winParams; MV_U32 sizeReg, baseReg; /* Parameter checking */ if (winNum >= MV_USB_MAX_ADDR_DECODE_WIN) { mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum); return MV_BAD_PARAM; } /* Check if the requested window overlapps with current windows */ if (MV_TRUE == usbWinOverlapDetect(dev, winNum, &pDecWin->addrWin)) { mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, winNum); return MV_ERROR; } /* check if address is aligned to the size */ if(MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) { mvOsPrintf("mvUsbWinSet:Error setting USB window %d to "\ "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", winNum, mvCtrlTargetNameGet(pDecWin->target), pDecWin->addrWin.baseLow, pDecWin->addrWin.size); return MV_ERROR; } if(MV_OK != mvCtrlAddrDecToParams(pDecWin, &winParams)) { mvOsPrintf("%s: mvCtrlAddrDecToParams Failed\n", __FUNCTION__); return MV_ERROR; } /* set Size, Attributes and TargetID */ sizeReg = (((winParams.targetId << MV_USB_WIN_TARGET_OFFSET) & MV_USB_WIN_TARGET_MASK) | ((winParams.attrib << MV_USB_WIN_ATTR_OFFSET) & MV_USB_WIN_ATTR_MASK) | ((winParams.size << MV_USB_WIN_SIZE_OFFSET) & MV_USB_WIN_SIZE_MASK)); #if defined(MV645xx) || defined(MV646xx) /* If window is DRAM with HW cache coherency, make sure bit2 is set */ sizeReg &= ~MV_USB_WIN_BURST_WR_LIMIT_MASK; if((MV_TARGET_IS_DRAM(pDecWin->target)) && (pDecWin->addrWinAttr.cachePolicy != NO_COHERENCY)) { sizeReg |= MV_USB_WIN_BURST_WR_32BIT_LIMIT; } else { sizeReg |= MV_USB_WIN_BURST_WR_NO_LIMIT; } #endif /* MV645xx || MV646xx */ if (pDecWin->enable == MV_TRUE) { sizeReg |= MV_USB_WIN_ENABLE_MASK; } else { sizeReg &= ~MV_USB_WIN_ENABLE_MASK; } /* Update Base value */ baseReg = (winParams.baseAddr & MV_USB_WIN_BASE_MASK); MV_REG_WRITE( MV_USB_WIN_CTRL_REG(dev, winNum), sizeReg); MV_REG_WRITE( MV_USB_WIN_BASE_REG(dev, winNum), baseReg); 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; }
/******************************************************************************* * mvUsbWinWrite - Set USB target address window * * DESCRIPTION: * This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0) * address window, also known as address decode window. * After setting this target window, the USB will be able to access the * target within the address window. * * INPUT: * winNum - USB target address decode window number. * pAddrDecWin - USB target window data structure. * * OUTPUT: * None. * * RETURN: * MV_ERROR if address window overlapps with other address decode windows. * MV_BAD_PARAM if base address is invalid parameter or target is * unknown. * *******************************************************************************/ MV_STATUS mvUsbWinWrite(MV_U32 dev, MV_U32 winNum, MV_UNIT_WIN_INFO *pDecWin) { MV_U32 sizeReg, baseReg; MV_U32 size; /* Parameter checking */ if (winNum >= MV_USB_MAX_ADDR_DECODE_WIN) { mvOsPrintf("%s: ERR. Invalid win num %d\n", __func__, winNum); return MV_BAD_PARAM; } /* Check if the requested window overlapps with current windows */ if (MV_TRUE == usbWinOverlapDetect(dev, winNum, &pDecWin->addrWin)) { mvOsPrintf("%s: ERR. Window %d overlap\n", __func__, winNum); return MV_ERROR; } /* check if address is aligned to the size */ if (MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) { mvOsPrintf("mvUsbWinWrite:Error setting USB window %d.\n" "Address 0x%08x is unaligned to size 0x%x.\n", winNum, pDecWin->addrWin.baseLow, pDecWin->addrWin.size); return MV_ERROR; } if (!MV_IS_POWER_OF_2(pDecWin->addrWin.size)) { mvOsPrintf("mvUsbWinWrite: Bad windows size.\n"); return MV_BAD_PARAM; } size = pDecWin->addrWin.size / MV_USB_WIN_SIZE_ALIGN - 1; /* set Size, Attributes and TargetID */ sizeReg = (((pDecWin->targetId << MV_USB_WIN_TARGET_OFFSET) & MV_USB_WIN_TARGET_MASK) | ((pDecWin->attrib << MV_USB_WIN_ATTR_OFFSET) & MV_USB_WIN_ATTR_MASK) | ((size << MV_USB_WIN_SIZE_OFFSET) & MV_USB_WIN_SIZE_MASK)); #if defined(MV645xx) || defined(MV646xx) /* If window is DRAM with HW cache coherency, make sure bit2 is set */ sizeReg &= ~MV_USB_WIN_BURST_WR_LIMIT_MASK; if ((MV_TARGET_IS_DRAM(pDecWin->target)) && (pDecWin->addrWinAttr.cachePolicy != NO_COHERENCY)) sizeReg |= MV_USB_WIN_BURST_WR_32BIT_LIMIT; else sizeReg |= MV_USB_WIN_BURST_WR_NO_LIMIT; #endif /* MV645xx || MV646xx */ if (pDecWin->enable == MV_TRUE) sizeReg |= MV_USB_WIN_ENABLE_MASK; else sizeReg &= ~MV_USB_WIN_ENABLE_MASK; /* Update Base value */ baseReg = (pDecWin->addrWin.baseLow & MV_USB_WIN_BASE_MASK); MV_REG_WRITE(MV_USB_WIN_CTRL_REG(dev, winNum), sizeReg); MV_REG_WRITE(MV_USB_WIN_BASE_REG(dev, winNum), baseReg); return MV_OK; }
/******************************************************************************* * mvCtrlAddrWinMapBuild * * DESCRIPTION: * Build the windows address decoding table, to be used for initializing * the unit's address decoding windows. * * INPUT: * pAddrWinMap: An array to hold the address decoding windows parameters. * len: Number of entries in pAddrWinMap. * * OUTPUT: * pAddrWinMap: Address window information. * * RETURN: * MV_BAD_PARAM: input array is smaller than needed to store all window * addresses. * MV_ERROR: Otherwise. * *******************************************************************************/ MV_STATUS mvCtrlAddrWinMapBuild(MV_UNIT_WIN_INFO *pAddrWinMap, MV_U32 len) { MV_CPU_DEC_WIN cpuAddrDecWin; MV_U32 i, j; MV_TARGET_ATTRIB targetAttrib; MV_STATUS status; MV_U64 startAddr, endAddr; MV_UNIT_WIN_INFO ioDdrWin[MV_DRAM_MAX_CS]; MV_U32 base; MV_U64 size; /* Check size of CPU address win table */ if (len <= MAX_TARGETS) { mvOsPrintf("mvCtrlAddrWinMapBuild() - Table size too small.\n"); return MV_BAD_PARAM; } /* Prepare an array of DRAM info */ base = 0x0; j = 0; for (i = SDRAM_CS0; i <= SDRAM_CS3; i++) { status = mvCpuIfTargetWinGet(i, &cpuAddrDecWin); if (status != MV_OK) { if (status == MV_NO_SUCH) { ioDdrWin[i].enable = MV_FALSE; continue; } else { mvOsPrintf("mvCtrlAddrWinMapBuild() - mvCpuIfTargetWinGet() failed.\n"); return MV_ERROR; } } /* As all IO address decode windows support only 32-bit ** addresses, limit the DRAM base / size to 4GB max. */ startAddr = (MV_U64)((((MV_U64)cpuAddrDecWin.addrWin.baseHigh << 32ll)) + (MV_U64)cpuAddrDecWin.addrWin.baseLow); endAddr = (MV_U64)(startAddr + (MV_U64)cpuAddrDecWin.addrWin.size) - 1; if (endAddr > 0xFFFFFFFFll) { if (startAddr <= 0xFFFFFFFFll) cpuAddrDecWin.addrWin.size = (0x100000000ll - cpuAddrDecWin.addrWin.baseLow); else cpuAddrDecWin.enable = MV_FALSE; } if (cpuAddrDecWin.enable == MV_FALSE) continue; /* If the endAddr passes minBase, then we need to split ** this window to several windows up to minBase. ** For example: minBase=0xE0000000, and CS0=2, CS1=2G, ** Then we need to split the windwos as follows: ** Win0: CS-0, 2GB (Base 0x0) ** win1: CS-1, 1GB (Base 0x80000000) ** Win2: CS-1, 0.5GB (Base 0xC0000000) */ if (endAddr > MV_DRAM_IO_RESERVE_BASE) /* Need to cut down this CS to IO reserve base ** address. */ size = MV_DRAM_IO_RESERVE_BASE - cpuAddrDecWin.addrWin.baseLow; else size = cpuAddrDecWin.addrWin.size; if (mvCtrlAttribGet(i, &targetAttrib) != MV_OK) { mvOsPrintf("mvCtrlAddrWinMapBuild() - " "mvCtrlAttribGet() failed.\n"); return MV_ERROR; } /* Now, spread the last CS into several windows, and make sure ** that each of has a power-of-2 size. */ while (size != 0) { ioDdrWin[j].enable = MV_TRUE; ioDdrWin[j].attrib = targetAttrib.attrib; ioDdrWin[j].targetId = targetAttrib.targetId; ioDdrWin[j].addrWin.baseHigh = 0; if (MV_IS_POWER_OF_2(size)) ioDdrWin[j].addrWin.size = size; else ioDdrWin[j].addrWin.size = (MV_U64)(1ll << (MV_U64)mvLog2(size)); size -= ioDdrWin[j].addrWin.size; ioDdrWin[j].addrWin.baseLow = base; base += ioDdrWin[j].addrWin.size; j++; } /* Support only up to 4 DRAM address decode windows in the ** units. */ if (j == MV_DRAM_MAX_CS) break; } for (; j < MV_DRAM_MAX_CS; j++) ioDdrWin[j].enable = MV_FALSE; /* Fill in the pAddrWinMap fields */ for (i = 0; i < MAX_TARGETS; i++) { if (MV_TARGET_IS_DRAM(i)) { pAddrWinMap[i].addrWin.baseLow = ioDdrWin[i].addrWin.baseLow; pAddrWinMap[i].addrWin.baseHigh = ioDdrWin[i].addrWin.baseHigh; pAddrWinMap[i].addrWin.size = ioDdrWin[i].addrWin.size; pAddrWinMap[i].enable = ioDdrWin[i].enable; pAddrWinMap[i].attrib = ioDdrWin[i].attrib; pAddrWinMap[i].targetId = ioDdrWin[i].targetId; } else { status = mvCpuIfTargetWinGet(i, &cpuAddrDecWin); if (status != MV_OK) { if (status == MV_NO_SUCH) { pAddrWinMap[i].enable = MV_FALSE; continue; } else { mvOsPrintf("mvCtrlAddrWinMapBuild()" " - mvCpuIfTargetWinGet() failed.\n"); return MV_ERROR; } } pAddrWinMap[i].addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; pAddrWinMap[i].addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; pAddrWinMap[i].addrWin.size = cpuAddrDecWin.addrWin.size; pAddrWinMap[i].enable = cpuAddrDecWin.enable; if (mvCtrlAttribGet(i, &targetAttrib) != MV_OK) { mvOsPrintf("mvCtrlAddrWinMapBuild() - " "mvCtrlAttribGet() failed.\n"); return MV_ERROR; } pAddrWinMap[i].attrib = targetAttrib.attrib; pAddrWinMap[i].targetId = targetAttrib.targetId; } } pAddrWinMap[i].addrWin.baseLow = TBL_TERM; pAddrWinMap[i].addrWin.baseHigh = TBL_TERM; pAddrWinMap[i].addrWin.size = TBL_TERM; pAddrWinMap[i].enable = TBL_TERM; pAddrWinMap[i].attrib = TBL_TERM; pAddrWinMap[i].targetId = TBL_TERM; return MV_OK; }