MV_STATUS mvCtrlAddrWinInfoGet(MV_UNIT_WIN_INFO *pAddrWinInfo, MV_ULONG physAddr) { MV_CPU_DEC_WIN cpuAddrDecWin; MV_U32 i; MV_TARGET_ATTRIB targetAttrib; MV_STATUS status; for (i = 0; i < MAX_TARGETS; i++) { status = mvCpuIfTargetWinGet(i, &cpuAddrDecWin); if (status != MV_OK) continue; if ((physAddr >= cpuAddrDecWin.addrWin.baseLow) && (physAddr < cpuAddrDecWin.addrWin.baseLow + cpuAddrDecWin.addrWin.size)) { /* Found */ pAddrWinInfo->addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; pAddrWinInfo->addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; pAddrWinInfo->addrWin.size = cpuAddrDecWin.addrWin.size; if (mvCtrlAttribGet(i, &targetAttrib) != MV_OK) { mvOsPrintf("mvCtrlAddrWinMapBuild() - mvCtrlAttribGet() failed.\n"); return MV_ERROR; } pAddrWinInfo->attrib = targetAttrib.attrib; pAddrWinInfo->targetId = targetAttrib.targetId; return MV_OK; } } /* not found */ return MV_NOT_FOUND; }
/******************************************************************************* * 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; }
/******************************************************************************* * mvAudioWinSet - Set AUDIO 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 AUDIO will be able to access the * target within the address window. * * INPUT: * winNum - AUDIO target address decode window number. * pAddrDecWin - AUDIO 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 mvAudioWinSet(int unit, MV_U32 winNum, MV_AUDIO_DEC_WIN *pAddrDecWin) { MV_TARGET_ATTRIB targetAttribs; MV_DEC_REGS decRegs; /* Parameter checking */ if (winNum >= MV_AUDIO_MAX_ADDR_DECODE_WIN) { mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum); return MV_BAD_PARAM; } /* check if address is aligned to the size */ if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) { mvOsPrintf("mvAudioWinSet:Error setting AUDIO window %d to "\ "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", winNum, mvCtrlTargetNameGet(pAddrDecWin->target), pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size); return MV_ERROR; } decRegs.baseReg = 0; decRegs.sizeReg = 0; if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) { mvOsPrintf("%s: mvCtrlAddrDecToReg Failed\n", __FUNCTION__); return MV_ERROR; } mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); /* set attributes */ decRegs.sizeReg &= ~MV_AUDIO_WIN_ATTR_MASK; decRegs.sizeReg |= (targetAttribs.attrib << MV_AUDIO_WIN_ATTR_OFFSET); /* set target ID */ decRegs.sizeReg &= ~MV_AUDIO_WIN_TARGET_MASK; decRegs.sizeReg |= (targetAttribs.targetId << MV_AUDIO_WIN_TARGET_OFFSET); if (pAddrDecWin->enable == MV_TRUE) { decRegs.sizeReg |= MV_AUDIO_WIN_ENABLE_MASK; } else { decRegs.sizeReg &= ~MV_AUDIO_WIN_ENABLE_MASK; } MV_REG_WRITE( MV_AUDIO_WIN_CTRL_REG(unit, winNum), decRegs.sizeReg); MV_REG_WRITE( MV_AUDIO_WIN_BASE_REG(unit, winNum), decRegs.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; MV_TARGET_ATTRIB targetAttrib; MV_STATUS status; /* Check size of CPU address win table */ if (len <= MAX_TARGETS) { mvOsPrintf("mvCtrlAddrWinMapBuild() - Table size too small.\n"); return MV_BAD_PARAM; } /* Fill in the pAddrWinMap fields */ for (i = 0; i < MAX_TARGETS; i++) { 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; }
/* * Straight forward function what returns _only_ the index of the * memory window according to provided SoC target. */ MV_STATUS mvAhbToMbusWinNumByTargetGet(MV_TARGET target, MV_U32 *pWinNum) { MV_TARGET_ATTRIB targetAttribs; MV_U32 winNum, ctrlReg, targetId; if (pWinNum == NULL) { mvOsPrintf("%s: Error: pWinNum is NULL\n", __func__); return MV_FAIL; } if (target >= MAX_TARGETS) { mvOsPrintf("%s: Error: target %d is illegal\n", __func__, target); return MV_FAIL; } if (target == INTER_REGS) { *pWinNum = MV_AHB_TO_MBUS_INTREG_WIN; return MV_OK; } if (mvCtrlAttribGet(target, &targetAttribs) != MV_OK) { mvOsPrintf("%s: Error: mvCtrlAttribGet(target = %d) failed\n", __func__, target); return MV_FAIL; } for (winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS; winNum++) { if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) continue; ctrlReg = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(winNum)); targetId = (ctrlReg & ATMWCR_WIN_TARGET_MASK) >> ATMWCR_WIN_TARGET_OFFS; if (targetId == targetAttribs.targetId) { *pWinNum = winNum; return MV_OK; } } return MV_FAIL; }
/******************************************************************************* * mvDmaWinSet - Set DMA 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 DMA will be able to access the * target within the address window. * * INPUT: * winNum - IDMA to target address decode window number. * pAddrDecWin - IDMA 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 mvDmaWinSet(MV_U32 winNum, MV_DMA_DEC_WIN *pAddrDecWin) { MV_TARGET_ATTRIB targetAttribs; MV_DEC_REGS decRegs; /* Parameter checking */ if (winNum >= IDMA_MAX_ADDR_DEC_WIN) { mvOsPrintf("mvDmaWinSet: ERR. Invalid win num %d\n",winNum); return MV_BAD_PARAM; } /* Check if the requested window overlapps with current windows */ if (MV_TRUE == dmaWinOverlapDetect(winNum, &pAddrDecWin->addrWin)) { mvOsPrintf("mvDmaWinSet: ERR. Window %d overlap\n", winNum); return MV_ERROR; } /* check if address is aligned to the size */ if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) { mvOsPrintf("mvDmaWinSet: Error setting IDMA window %d to "\ "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", winNum, mvCtrlTargetNameGet(pAddrDecWin->target), pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size); return MV_ERROR; } decRegs.baseReg = MV_REG_READ(IDMA_BASE_ADDR_REG(winNum)); decRegs.sizeReg = MV_REG_READ(IDMA_SIZE_REG(winNum)); if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) { mvOsPrintf("mvDmaWinSet: mvCtrlAddrDecToReg Failed\n"); return MV_ERROR; } mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); #if defined(MV_88F5182) || defined(MV_88F5181L) /* See BTS Nastore #19.*/ /* To access Tunit SRAM from IDMA use targetId = 0x5 */ /* To access Tunit SRAM from the CPU use targetId = 0x9 */ if(pAddrDecWin->target == CRYPT_ENG) targetAttribs.targetId = 5; #endif /* defined(MV_88F5182) || defined(MV_88F5181L) */ /* set attributes */ decRegs.baseReg &= ~IDMA_WIN_ATTR_MASK; decRegs.baseReg |= targetAttribs.attrib << IDMA_WIN_ATTR_OFFS; /* set target ID */ decRegs.baseReg &= ~IDMA_WIN_TARGET_MASK; decRegs.baseReg |= targetAttribs.targetId << IDMA_WIN_TARGET_OFFS; /* for the safe side we disable the window before writing the new values */ mvDmaWinEnable(winNum,MV_FALSE); MV_REG_WRITE(IDMA_BASE_ADDR_REG(winNum), decRegs.baseReg); /* Write to address decode Size Register */ MV_REG_WRITE(IDMA_SIZE_REG(winNum), decRegs.sizeReg); /* Enable address decode target window */ if (pAddrDecWin->enable == MV_TRUE) { mvDmaWinEnable(winNum, MV_TRUE); } return MV_OK; }
/******************************************************************************* * mvTsuWinSet * * 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 TSU will be able to access the * target within the address window. * * INPUT: * winNum - TSU to target address decode window number. * pAddrDecWin - TSU 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 mvTsuWinSet(MV_U32 winNum, MV_TSU_DEC_WIN *pAddrDecWin) { MV_TARGET_ATTRIB targetAttribs; MV_DEC_REGS decRegs; /* Parameter checking */ if(winNum >= TSU_MAX_DECODE_WIN) { mvOsPrintf("mvTsuWinSet: ERR. Invalid win num %d\n",winNum); return MV_BAD_PARAM; } /* Check if the requested window overlapps with current windows */ if(MV_TRUE == tsuWinOverlapDetect(winNum, &pAddrDecWin->addrWin)) { mvOsPrintf("mvTsuWinSet: ERR. Window %d overlap\n", winNum); return MV_ERROR; } /* check if address is aligned to the size */ if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow,pAddrDecWin->addrWin.size)) { mvOsPrintf("mvTsuWinSet: Error setting TSU window %d to target " "%s.\nAddress 0x%08x is unaligned to size 0x%x.\n", winNum, mvCtrlTargetNameGet(pAddrDecWin->target), pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size); return MV_ERROR; } decRegs.baseReg = MV_REG_READ(MV_TSU_WIN_BASE_REG(winNum)); decRegs.sizeReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNum)); if(MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) { mvOsPrintf("mvTsuWinSet: mvCtrlAddrDecToReg Failed\n"); return MV_ERROR; } mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); /* set attributes */ decRegs.sizeReg &= ~TSU_WIN_CTRL_ATTR_MASK; decRegs.sizeReg |= targetAttribs.attrib << TSU_WIN_CTRL_ATTR_OFFS; /* set target ID */ decRegs.sizeReg &= ~TSU_WIN_CTRL_TARGET_MASK; decRegs.sizeReg |= targetAttribs.targetId << TSU_WIN_CTRL_TARGET_OFFS; /* for the safe side we disable the window before writing the new */ /* values */ mvTsuWinEnable(winNum, MV_FALSE); MV_REG_WRITE(MV_TSU_WIN_CTRL_REG(winNum),decRegs.sizeReg); /* Write to address decode Size Register */ MV_REG_WRITE(MV_TSU_WIN_BASE_REG(winNum), decRegs.baseReg); /* Enable address decode target window */ if(pAddrDecWin->enable == MV_TRUE) { mvTsuWinEnable(winNum,MV_TRUE); } return MV_OK; }
/******************************************************************************* * mvXorTargetWinSet - Set XOR target address window * * DESCRIPTION: * This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0) * address window. After setting this target window, the XOR will be * able to access the target within the address window. * * INPUT: * winNum - One of the possible XOR memory decode windows. * target - Peripheral target enumerator. * base - Window base address. * size - Window size. * enable - Window enable/disable. * * OUTPUT: * None. * * RETURN: * MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. * *******************************************************************************/ MV_STATUS mvXorTargetWinSet(MV_U32 unit, MV_U32 winNum, MV_XOR_DEC_WIN *pAddrDecWin) { MV_DEC_REGS xorDecRegs; MV_TARGET_ATTRIB targetAttribs; MV_U32 chan; /* Parameter checking */ if (winNum >= XOR_MAX_ADDR_DEC_WIN) { DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum)); return MV_BAD_PARAM; } if (pAddrDecWin == NULL) { DB(mvOsPrintf("%s: ERR. pAddrDecWin is NULL pointer\n", __FUNCTION__ )); return MV_BAD_PTR; } /* Check if the requested window overlaps with current windows */ if (MV_TRUE == xorWinOverlapDetect(unit, winNum, &pAddrDecWin->addrWin)) { DB(mvOsPrintf("%s: ERR. Window %d overlap\n",__FUNCTION__,winNum)); return MV_ERROR; } xorDecRegs.baseReg = MV_REG_READ(XOR_BASE_ADDR_REG(unit,winNum)); xorDecRegs.sizeReg = MV_REG_READ(XOR_SIZE_MASK_REG(unit,winNum)); /* Get Base Address and size registers values */ if(MV_OK != mvCtrlAddrDecToReg(&pAddrDecWin->addrWin, &xorDecRegs)) { DB(mvOsPrintf("%s: ERR. Invalid addr dec window\n",__FUNCTION__)); return MV_BAD_PARAM; } mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); /* set attributes */ xorDecRegs.baseReg &= ~XEBARX_ATTR_MASK; xorDecRegs.baseReg |= targetAttribs.attrib << XEBARX_ATTR_OFFS; /* set target ID */ xorDecRegs.baseReg &= ~XEBARX_TARGET_MASK; xorDecRegs.baseReg |= targetAttribs.targetId << XEBARX_TARGET_OFFS; /* Write to address decode Base Address Register */ MV_REG_WRITE(XOR_BASE_ADDR_REG(unit,winNum), xorDecRegs.baseReg); /* Write to Size Register */ MV_REG_WRITE(XOR_SIZE_MASK_REG(unit,winNum), xorDecRegs.sizeReg); for (chan = 0; chan < MV_XOR_MAX_CHAN; chan++) { if (pAddrDecWin->enable) { MV_REG_BIT_SET(XOR_WINDOW_CTRL_REG(unit,chan), XEXWCR_WIN_EN_MASK(winNum)); } else { MV_REG_BIT_RESET(XOR_WINDOW_CTRL_REG(unit,chan), XEXWCR_WIN_EN_MASK(winNum)); } } return MV_OK; }
/******************************************************************************* * mvAhbToMbusWinSet - Set CPU-to-peripheral winNum address window * * DESCRIPTION: * This function sets * address window, also known as address decode window. * A new address decode window is set for specified winNum address window. * If address decode window parameter structure enables the window, * the routine will also enable the winNum window, allowing CPU to access * the winNum window. * * INPUT: * winNum - Windows number. * pAddrDecWin - CPU winNum window data structure. * * OUTPUT: * N/A * * RETURN: * MV_OK if CPU winNum window was set correctly, MV_ERROR in case of * address window overlapps with other active CPU winNum window or * trying to assign 36bit base address while CPU does not support that. * The function returns MV_NOT_SUPPORTED, if the winNum is unsupported. * *******************************************************************************/ MV_STATUS mvAhbToMbusWinSet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin) { MV_TARGET_ATTRIB targetAttribs; MV_DEC_REGS decRegs; /* Parameter checking */ if (winNum >= MAX_AHB_TO_MBUS_WINS) { mvOsPrintf("mvAhbToMbusWinSet: ERR. Invalid winNum %d\n", winNum); return MV_NOT_SUPPORTED; } /* read base register*/ if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) { decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(winNum)); } else { decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_INTEREG_REG); } /* check if address is aligned to the size */ if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) { mvOsPrintf("mvAhbToMbusWinSet:Error setting AHB to MBUS window %d to "\ "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", winNum, mvCtrlTargetNameGet(pAddrDecWin->target), pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size); return MV_ERROR; } /* read control register*/ if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) { decRegs.sizeReg = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(winNum)); } if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) { mvOsPrintf("mvAhbToMbusWinSet:mvCtrlAddrDecToReg Failed\n"); return MV_ERROR; } /* enable\Disable */ if (MV_TRUE == pAddrDecWin->enable) { decRegs.sizeReg |= ATMWCR_WIN_ENABLE; } else { decRegs.sizeReg &= ~ATMWCR_WIN_ENABLE; } mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); /* set attributes */ decRegs.sizeReg &= ~ATMWCR_WIN_ATTR_MASK; decRegs.sizeReg |= targetAttribs.attrib << ATMWCR_WIN_ATTR_OFFS; /* set target ID */ decRegs.sizeReg &= ~ATMWCR_WIN_TARGET_MASK; decRegs.sizeReg |= targetAttribs.targetId << ATMWCR_WIN_TARGET_OFFS; #if !defined(MV_RUN_FROM_FLASH) /* To be on the safe side we disable the window before writing the */ /* new values. */ if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) { mvAhbToMbusWinEnable(winNum,MV_FALSE); } #endif /* 3) Write to address decode Base Address Register */ if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) { MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(winNum), decRegs.baseReg); } else { MV_REG_WRITE(AHB_TO_MBUS_WIN_INTEREG_REG, decRegs.baseReg); } /* Internal register space have no size */ /* register. Do not perform size register assigment for those targets */ if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) { /* Write to address decode Size Register */ MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum), decRegs.sizeReg); } return MV_OK; }
/******************************************************************************* * mvAhbToMbusWinSet - Set CPU-to-peripheral winNum address window * * DESCRIPTION: * This function sets * address window, also known as address decode window. * A new address decode window is set for specified winNum address window. * If address decode window parameter structure enables the window, * the routine will also enable the winNum window, allowing CPU to access * the winNum window. * * INPUT: * winNum - Windows number. * pAddrDecWin - CPU winNum window data structure. * * OUTPUT: * N/A * * RETURN: * MV_OK if CPU winNum window was set correctly, MV_ERROR in case of * address window overlapps with other active CPU winNum window or * trying to assign 36bit base address while CPU does not support that. * The function returns MV_NOT_SUPPORTED, if the winNum is unsupported. * *******************************************************************************/ MV_STATUS mvAhbToMbusWinSet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin) { MV_TARGET_ATTRIB targetAttribs; MV_DEC_REGS decRegs; MV_U32 sizeToReg; /* Parameter checking */ if (winNum >= MAX_AHB_TO_MBUS_WINS) { mvOsPrintf("mvAhbToMbusWinSet: ERR. Invalid winNum %d\n", winNum); return MV_NOT_SUPPORTED; } /* check if address is aligned to the size */ if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) { mvOsPrintf("mvAhbToMbusWinSet:Error setting AHB to MBUS window %d to " "target %s.\nAddress 0x%08x is unaligned to size 0x%llx.\n", winNum, mvCtrlTargetNameGet(pAddrDecWin->target), pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size); return MV_ERROR; } /* Size parameter validity check. */ if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.size, ATMWCR_WIN_SIZE_ALIGNMENT)) { mvOsPrintf("mvAhbToMbusWinSet: Failed, size not aligned to 0x%x.\n", ATMWCR_WIN_SIZE_ALIGNMENT); return MV_BAD_PARAM; } /* Write to address decode Base Address Register */ decRegs.baseReg = (pAddrDecWin->addrWin.baseLow & ATMWBR_BASE_MASK); /* Get size register value according to window size */ sizeToReg = (pAddrDecWin->addrWin.size / ATMWCR_WIN_SIZE_ALIGNMENT) - 1; /* set size */ decRegs.ctrlReg = (sizeToReg << ATMWCR_WIN_SIZE_OFFS); /* enable\Disable */ if (MV_TRUE == pAddrDecWin->enable) decRegs.ctrlReg |= ATMWCR_WIN_ENABLE; else decRegs.ctrlReg &= ~ATMWCR_WIN_ENABLE; mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); /* set attributes */ decRegs.ctrlReg &= ~ATMWCR_WIN_ATTR_MASK; decRegs.ctrlReg |= targetAttribs.attrib << ATMWCR_WIN_ATTR_OFFS; /* set target ID */ decRegs.ctrlReg &= ~ATMWCR_WIN_TARGET_MASK; decRegs.ctrlReg |= targetAttribs.targetId << ATMWCR_WIN_TARGET_OFFS; #if !defined(MV_RUN_FROM_FLASH) /* To be on the safe side we disable the window before writing the */ /* new values. */ if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) mvAhbToMbusWinEnable(winNum, MV_FALSE); #endif /* 3) Write to address decode Base Address Register */ if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(winNum), decRegs.baseReg); else MV_REG_WRITE(AHB_TO_MBUS_WIN_INTEREG_REG, decRegs.baseReg); /* Internal register space have no size */ /* register. Do not perform size register assigment for those targets */ if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) { /* Write to address decode Size Register */ MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum), decRegs.ctrlReg); } 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; }
/******************************************************************************* * 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; }
* mvTdmWinSet - Set TDM 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 TDM will be able to access the * target within the address window. * * INPUT: * winNum - TDM to target address decode window number. * pAddrDecWin - TDM 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 mvTdmWinSet(MV_U32 winNum, MV_TDM_DEC_WIN *pAddrDecWin) { MV_TARGET_ATTRIB targetAttribs; MV_DEC_REGS decRegs; MV_U32 ctrlReg = 0; /* Parameter checking */ if (winNum >= TDM_MBUS_MAX_WIN) { mvOsPrintf("mvTdmWinSet: ERR. Invalid win num %d\n",winNum); return MV_BAD_PARAM; } /* Check if the requested window overlapps with current windows */ if (MV_TRUE == tdmWinOverlapDetect(winNum, &pAddrDecWin->addrWin)) { mvOsPrintf("mvTdmWinSet: ERR. Window %d overlap\n", winNum); return MV_ERROR; } /* check if address is aligned to the size */ if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) { mvOsPrintf("mvTdmWinSet: Error setting TDM window %d to "\ "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", winNum, mvCtrlTargetNameGet(pAddrDecWin->target), pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size); return MV_ERROR; } decRegs.baseReg = MV_REG_READ(TDM_WIN_BASE_REG(winNum)); decRegs.sizeReg = (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_SIZE_MASK) >> TDM_WIN_SIZE_OFFS; if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) { mvOsPrintf("mvTdmWinSet: mvCtrlAddrDecToReg Failed\n"); return MV_ERROR; } mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); /* for the safe side we disable the window before writing the new values */ mvTdmWinEnable(winNum, MV_FALSE); ctrlReg |= (targetAttribs.attrib << TDM_WIN_ATTRIB_OFFS); ctrlReg |= (targetAttribs.targetId << TDM_WIN_TARGET_OFFS); ctrlReg |= (decRegs.sizeReg & TDM_WIN_SIZE_MASK); /* Write to address base and control registers */ MV_REG_WRITE(TDM_WIN_BASE_REG(winNum), decRegs.baseReg); MV_REG_WRITE(TDM_WIN_CTRL_REG(winNum), ctrlReg); /* Enable address decode target window */ if (pAddrDecWin->enable == MV_TRUE) { mvTdmWinEnable(winNum, MV_TRUE); } return MV_OK; }