| /******************************************************************************* |
| Copyright (C) Marvell International Ltd. and its affiliates |
| |
| This software file (the "File") is owned and distributed by Marvell |
| International Ltd. and/or its affiliates ("Marvell") under the following |
| alternative licensing terms. Once you have made an election to distribute the |
| File under one of the following license alternatives, please (i) delete this |
| introductory statement regarding license alternatives, (ii) delete the two |
| license alternatives that you have not elected to use and (iii) preserve the |
| Marvell copyright notice above. |
| |
| ******************************************************************************** |
| Marvell Commercial License Option |
| |
| If you received this File from Marvell and you have entered into a commercial |
| license agreement (a "Commercial License") with Marvell, the File is licensed |
| to you under the terms of the applicable Commercial License. |
| |
| ******************************************************************************** |
| Marvell GPL License Option |
| |
| If you received this File from Marvell, you may opt to use, redistribute and/or |
| modify this File in accordance with the terms and conditions of the General |
| Public License Version 2, June 1991 (the "GPL License"), a copy of which is |
| available along with the File in the license.txt file or by writing to the Free |
| Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or |
| on the worldwide web at http://www.gnu.org/licenses/gpl.txt. |
| |
| THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED |
| WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY |
| DISCLAIMED. The GPL License provides additional details about this warranty |
| disclaimer. |
| ******************************************************************************** |
| Marvell BSD License Option |
| |
| If you received this File from Marvell, you may opt to use, redistribute and/or |
| modify this File under the following licensing terms. |
| Redistribution and use in source and binary forms, with or without modification, |
| are permitted provided that the following conditions are met: |
| |
| * Redistributions of source code must retain the above copyright notice, |
| this list of conditions and the following disclaimer. |
| |
| * Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| |
| * Neither the name of Marvell nor the names of its contributors may be |
| used to endorse or promote products derived from this software without |
| specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |
| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| *******************************************************************************/ |
| |
| #include "mvSysPci.h" |
| #include "ddr2_3/mvDramIf.h" |
| |
| /* PCI BARs registers offsets are inconsecutive. This struct describes BAR */ |
| /* register offsets and its function where its is located. */ |
| /* Also, PCI address remap registers offsets are inconsecutive. This struct */ |
| /* describes address remap register offsets */ |
| typedef struct _pciBarRegInfo |
| { |
| MV_U32 funcNum; |
| MV_U32 baseLowRegOffs; |
| MV_U32 baseHighRegOffs; |
| MV_U32 sizeRegOffs; |
| MV_U32 remapLowRegOffs; |
| MV_U32 remapHighRegOffs; |
| }PCI_BAR_REG_INFO; |
| |
| typedef struct _pciBarStatus |
| { |
| MV_PCI_BAR bar; |
| int enable; |
| }PCI_BAR_STATUS; |
| |
| PCI_BAR_STATUS pciBarStatusMap[] = |
| { |
| #if defined(MV_INCLUDE_SDRAM_CS0) |
| {CS0_BAR, EN}, |
| #endif |
| #if defined(MV_INCLUDE_SDRAM_CS1) |
| {CS1_BAR, EN}, |
| #endif |
| #if defined(MV_INCLUDE_SDRAM_CS2) |
| {CS2_BAR, EN}, |
| #endif |
| #if defined(MV_INCLUDE_SDRAM_CS3) |
| {CS3_BAR, EN}, |
| #endif |
| #if defined(MV_INCLUDE_DEVICE_CS0) |
| {DEVCS0_BAR, EN}, |
| #endif |
| #if defined(MV_INCLUDE_DEVICE_CS1) |
| {DEVCS1_BAR, EN}, |
| #endif |
| #if defined(MV_INCLUDE_DEVICE_CS2) |
| {DEVCS2_BAR, EN}, |
| #endif |
| {BOOTCS_BAR, EN}, |
| {MEM_INTER_REGS_BAR, EN}, |
| {IO_INTER_REGS_BAR, EN}, |
| {P2P_MEM0, DIS}, |
| {P2P_IO, DIS}, |
| {TBL_TERM, TBL_TERM} |
| }; |
| |
| /* PCI BAR table. Note that table entry number must match its target */ |
| /* enumerator. For example, table entry '4' must describe Deivce CS0 */ |
| /* target which is represent by DEVICE_CS0 enumerator (4). */ |
| #if 0 |
| MV_PCI_BAR_WIN pciBarMap[] = |
| { |
| /* base low base high size enable/disable */ |
| {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE }, EN}, |
| {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE }, EN}, |
| {{SDRAM_CS2_BASE , 0, SDRAM_CS2_SIZE }, EN}, |
| {{SDRAM_CS3_BASE , 0, SDRAM_CS3_SIZE }, EN}, |
| {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE }, EN}, |
| {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE }, EN}, |
| {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE }, EN}, |
| {{BOOTDEV_CS_BASE, 0, BOOTDEV_CS_SIZE }, EN}, |
| {{INTER_REGS_BASE, 0, INTER_REGS_SIZE }, EN}, |
| {{INTER_REGS_BASE, 0, INTER_REGS_SIZE }, EN}, |
| {{ 0xFFFFFFFF , 0, 0xFFFFFFFF }, DIS}, /* Ignore P2P */ |
| {{ 0xFFFFFFFF , 0, 0xFFFFFFFF }, DIS}, /* Ignore P2P */ |
| /* Table terminator */ |
| {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM} |
| }; |
| #endif |
| |
| /* Locals */ |
| static MV_U32 pciBurstBytes2Reg(MV_U32 size); |
| static MV_U32 pciBurstReg2Bytes(MV_U32 size); |
| |
| static MV_STATUS pciWinOverlapDetect(MV_U32 pciIf, MV_PCI_BAR bar, |
| MV_ADDR_WIN *pAddrWin); |
| |
| static MV_STATUS pciBarRegInfoGet(MV_U32 pciIf, MV_PCI_BAR bar, |
| PCI_BAR_REG_INFO *pBarRegInfo); |
| |
| static MV_STATUS pciWinIsValid(MV_U32 baseLow, MV_U32 size); |
| |
| /* Forward declarations */ |
| const MV_8* pciBarNameGet(MV_PCI_BAR bar); |
| |
| /******************************************************************************* |
| * mvPciInit - Initialize PCI interfaces |
| * |
| * DESCRIPTION: |
| * This function initiate the PCI interface: |
| * 1) Set local bus number. In case of convential PCI it gets the bus |
| * number using mvPciLocalBusNumGet(). In case of PCI-X this |
| * information is read only. |
| * 2) Interface device number. In case of conventional PCI it gets the |
| * device number using mvPciLocalDevNumGet(). In case of PCI-X this |
| * information is read only. |
| * 3) PCI Arbiter if needed. |
| * 4) Enable Master and Slave on PCI interfaces. |
| * 5) Open PCI BARs according to default setting. |
| * Note that PCI bridge (P2P) is NOT initialized. |
| * 6) Enable CPU to PCI ordering. |
| * |
| * INPUT: |
| * |
| * pciIf - PCI interface number. |
| * localBus - Local Bus of the PCI interface to be set |
| * localDev - Local Dev of the PCI interface to be set |
| * bFirstCall - Indicates wether this is the first call of this |
| * function . |
| * |
| * |
| * OUTPUT: |
| * None. |
| * |
| * RETURN: |
| * MV_OK if function success otherwise MV_ERROR or MV_BAD_PARAM |
| * |
| *******************************************************************************/ |
| MV_STATUS mvPciInit(MV_U32 pciIf, MV_PCI_MOD pciIfmod) |
| { |
| MV_PCI_BAR bar, barix=0; |
| MV_PCI_MODE pciMode; |
| MV_PCI_PROT_WIN pciProtWin; |
| MV_PCI_BAR_WIN pciBarMap[PCI_MAX_BARS]; |
| MV_UNIT_WIN_INFO addrWinMap[MAX_TARGETS + 1]; |
| MV_TARGET target; |
| MV_UNIT_WIN_INFO *addrDecWin; |
| |
| /* Parameter checking */ |
| if (pciIf >= mvCtrlPciMaxIfGet()) { |
| mvOsPrintf("mvPciInit: ERR. Invalid PCI interface %d\n", pciIf); |
| return MV_BAD_PARAM; |
| } |
| |
| /* device and bus numbers */ |
| if (MV_OK != mvPciModeGet(pciIf, &pciMode)) { |
| mvOsPrintf("mvPciInit: ERR. mvPciModeGet failed\n"); |
| return MV_ERROR; |
| } |
| |
| /* First disable all PCI target windows */ |
| for (bar = 0; bar < PCI_MAX_BARS; bar++) |
| mvPciTargetWinEnable(pciIf, bar, MV_FALSE); |
| |
| /* WA CQ 4382*/ |
| MV_REG_BIT_SET(PCI_BASE_ADDR_ENABLE_REG(pciIf) ,BIT15); |
| |
| /* Loop over all BARs and copy enabled SDRAM windows only */ |
| if (MV_OK != mvCtrlAddrWinMapBuild(addrWinMap, MAX_TARGETS + 1)){ |
| mvOsPrintf("mvPciInit: ERR. mvCtrlAddrWinMapBuild failed\n"); |
| return MV_ERROR; |
| } |
| |
| for (target = SDRAM_CS0; target <= SDRAM_CS3; target++) { |
| addrDecWin = &addrWinMap[target]; |
| if (addrDecWin->enable == MV_TRUE) { |
| pciBarMap[barix].addrWin.baseLow = addrDecWin->addrWin.baseLow; |
| pciBarMap[barix].addrWin.baseHigh = addrDecWin->addrWin.baseHigh; |
| pciBarMap[barix].addrWin.size = addrDecWin->addrWin.size; |
| pciBarMap[barix].enable = EN; |
| barix++; |
| } |
| } |
| |
| /* Initialize all non used BARs */ |
| for (bar = barix; bar < PCI_MAX_BARS; bar++) { |
| pciBarMap[bar].addrWin.baseLow = 0xFFFFFFFF; |
| pciBarMap[bar].addrWin.baseHigh = 0; |
| pciBarMap[bar].addrWin.size = 0xFFFFFFFF; |
| pciBarMap[bar].enable = DIS; |
| } |
| |
| /* finally fill table with TBL_TERM entry */ |
| bar = PCI_MAX_BARS - 1; |
| pciBarMap[bar].addrWin.baseLow = TBL_TERM; |
| pciBarMap[bar].addrWin.baseHigh = TBL_TERM; |
| pciBarMap[bar].addrWin.size = TBL_TERM; |
| pciBarMap[bar].enable = TBL_TERM; |
| |
| |
| /* Memory Mapped Internal Registers BAR can not be disabled. */ |
| /* Relocate its BAR first to avoid colisions with other BARs (e.g DRAM) */ |
| if (MV_OK != mvPciTargetWinSet(pciIf, MEM_INTER_REGS_BAR, &pciBarMap[MEM_INTER_REGS_BAR])) { |
| mvOsPrintf("mvPciInit: ERR. mvPciTargetWinSet failed\n"); |
| return MV_ERROR; |
| } |
| |
| /* Now, go through all targets in default table until table terminator */ |
| for (bar = 0; pciBarMap[bar].enable != TBL_TERM; bar++) |
| { |
| /* Skip the P2P BARs. They should be configured seperately */ |
| if (0xFFFFFFFF == pciBarMap[bar].addrWin.baseLow) |
| continue; |
| |
| /* check if the size passed is zero ! */ |
| if (0 == pciBarMap[bar].addrWin.size) { |
| /* disable the bar */ |
| mvPciTargetWinEnable(pciIf,bar,MV_FALSE); |
| continue; |
| } |
| |
| if (MV_OK != mvPciTargetWinSet(pciIf, bar, &pciBarMap[bar])) { |
| mvOsPrintf("mvPciInit: ERR. mvPciTargetWinSet %d failed\n", bar); |
| return MV_ERROR; |
| } |
| } |
| |
| MV_REG_BIT_SET(PCI_ADDR_DECODE_CONTROL_REG(pciIf), PADCR_REMAP_REG_WR_DIS); |
| |
| /* configure access control unit 0 to DDR to enhance performance */ |
| pciProtWin.addrWin.baseLow = 0; |
| pciProtWin.addrWin.baseHigh = 0; |
| pciProtWin.addrWin.size = mvDramIfSizeGet(); |
| #ifdef AURORA_IO_CACHE_COHERENCY |
| pciProtWin.attributes.snoop = WT_CACHE_COHER; |
| #else |
| pciProtWin.attributes.snoop = NO_CACHE_COHER; |
| #endif |
| pciProtWin.attributes.access = ALLOWED; |
| pciProtWin.attributes.write = ALLOWED; |
| pciProtWin.attributes.swapType = MV_BYTE_SWAP; |
| pciProtWin.attributes.readMaxBurst = 128; |
| pciProtWin.attributes.readBurst = 256; |
| pciProtWin.attributes.writeMaxBurst = 128; |
| pciProtWin.attributes.pciOrder = MV_FALSE; |
| pciProtWin.enable = MV_TRUE; |
| if( mvPciProtWinSet(pciIf, 0, &pciProtWin) != MV_OK ) { |
| mvOsPrintf("mvPciInit: ERR. mvPciProtWinSet failed\n"); |
| return MV_ERROR; |
| } |
| |
| mvPciHalInit(pciIf, pciIfmod); |
| |
| 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; |
| } |
| |
| /******************************************************************************* |
| * mvPciTargetWinGet - Get PCI to peripheral target address window |
| * |
| * DESCRIPTION: |
| * Get the PCI to peripheral target address window BAR. |
| * |
| * INPUT: |
| * pciIf - PCI interface number. |
| * bar - BAR to be accessed by slave. |
| * |
| * OUTPUT: |
| * pAddrBarWin - PCI target window information data structure. |
| * |
| * RETURN: |
| * MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK |
| * |
| *******************************************************************************/ |
| MV_STATUS mvPciTargetWinGet(MV_U32 pciIf, MV_PCI_BAR bar, |
| MV_PCI_BAR_WIN *pAddrBarWin) |
| { |
| MV_U32 size; |
| MV_U32 baseLow; |
| MV_U32 baseHigh; |
| MV_U32 localBus; |
| MV_U32 localDev; |
| MV_U32 barEnable; |
| PCI_BAR_REG_INFO barRegInfo; |
| |
| /* Parameter checking */ |
| if (pciIf >= mvCtrlPciMaxIfGet()) |
| { |
| mvOsPrintf("mvPciTargetWinGet: ERR. Invalid PCI interface %d\n", pciIf); |
| return MV_BAD_PARAM; |
| } |
| |
| if (bar >= PCI_MAX_BARS ) |
| { |
| mvOsPrintf("mvPciTargetWinGet: ERR. Illigal PCI BAR %d.\n", bar); |
| return MV_BAD_PARAM; |
| } |
| |
| localBus = mvPciLocalBusNumGet(pciIf); |
| localDev = mvPciLocalDevNumGet(pciIf); |
| |
| /* Get BAR register information */ |
| pciBarRegInfoGet(pciIf, bar, &barRegInfo); |
| |
| /* Reading Base Low bar */ |
| baseLow = mvPciConfigRead(pciIf, localBus, localDev, barRegInfo.funcNum, |
| barRegInfo.baseLowRegOffs); |
| |
| baseLow &= PBBLR_BASE_MASK; |
| |
| /* Skip base high if the BAR has only base low (32-bit) */ |
| if (0 != barRegInfo.baseHighRegOffs) |
| { |
| /* Reading Base High */ |
| baseHigh = mvPciConfigRead(pciIf, localBus, localDev, barRegInfo.funcNum, |
| barRegInfo.baseHighRegOffs); |
| } |
| else |
| { |
| baseHigh = 0; |
| } |
| |
| /* Internal register space size have no size register. Do not perform */ |
| /* size register assigment for this slave target */ |
| if (0 != barRegInfo.sizeRegOffs) |
| { |
| /* Reading bar size*/ |
| size = ctrlRegToSize( |
| (MV_REG_READ(barRegInfo.sizeRegOffs) >> PBSR_SIZE_OFFS), |
| PBBLR_BASE_ALIGNMET); |
| } |
| else |
| { |
| size = INTER_REGS_SIZE; |
| } |
| |
| /* Assign value to user struct */ |
| pAddrBarWin->addrWin.baseLow = baseLow; |
| pAddrBarWin->addrWin.baseHigh = baseHigh; |
| pAddrBarWin->addrWin.size = size; |
| |
| /* Check if window is enabled */ |
| barEnable = MV_REG_READ(PCI_BASE_ADDR_ENABLE_REG(pciIf)); |
| |
| if (~barEnable & (BARER_ENABLE(bar))) |
| { |
| pAddrBarWin->enable = MV_TRUE; |
| } |
| else |
| { |
| pAddrBarWin->enable = MV_FALSE; |
| } |
| |
| return MV_OK; |
| } |
| |
| |
| /******************************************************************************* |
| * mvPciTargetWinEnable - Enable/disable a PCI BAR window |
| * |
| * DESCRIPTION: |
| * This function enable/disable a PCI BAR window. |
| * if parameter 'enable' == MV_TRUE the routine will enable the |
| * window, thus enabling PCI accesses for that BAR (before enabling the |
| * window it is tested for overlapping). Otherwise, the window will |
| * be disabled. |
| * |
| * INPUT: |
| * pciIf - PCI interface number. |
| * bar - BAR to be accessed by slave. |
| * enable - Enable/disable parameter. |
| * |
| * OUTPUT: |
| * None. |
| * |
| * RETURN: |
| * MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK |
| * |
| *******************************************************************************/ |
| MV_STATUS mvPciTargetWinEnable(MV_U32 pciIf, MV_PCI_BAR bar, MV_BOOL enable) |
| { |
| MV_PCI_BAR_WIN barWin; |
| |
| /* Parameter checking */ |
| if (pciIf >= mvCtrlPciMaxIfGet()) |
| { |
| mvOsPrintf("mvPciTargetWinEnable: ERR. Invalid PCI interface %d\n", |
| pciIf); |
| return MV_BAD_PARAM; |
| } |
| |
| if (bar >= PCI_MAX_BARS ) |
| { |
| mvOsPrintf("mvPciTargetWinEnable: ERR. Illigal PCI BAR %d\n", bar); |
| return MV_BAD_PARAM; |
| } |
| |
| if (MV_TRUE == enable) |
| { /* First check for overlap with other enabled windows */ |
| /* Get current window */ |
| if (MV_OK != mvPciTargetWinGet(pciIf, bar, &barWin)) |
| { |
| mvOsPrintf("mvPciTargetWinEnable: ERR. targetWinGet fail\n"); |
| return MV_ERROR; |
| } |
| |
| /* Check for overlapping */ |
| if (MV_TRUE == pciWinOverlapDetect(pciIf, bar, &barWin.addrWin)) |
| |
| { /* Overlap detected */ |
| mvOsPrintf("mvPciTargetWinEnable: ERR. Overlap detected\n"); |
| return MV_ERROR; |
| } |
| else |
| { |
| /* No Overlap. Enable address decode target window */ |
| MV_REG_BIT_RESET(PCI_BASE_ADDR_ENABLE_REG(pciIf),BARER_ENABLE(bar)); |
| } |
| } |
| else |
| { |
| /* Disable address decode target window */ |
| MV_REG_BIT_SET(PCI_BASE_ADDR_ENABLE_REG(pciIf), BARER_ENABLE(bar)); |
| } |
| |
| return MV_OK; |
| } |
| |
| |
| /******************************************************************************* |
| * mvPciProtWinSet - Set PCI protection access window |
| * |
| * DESCRIPTION: |
| * This function sets a specified address window with access protection |
| * attributes. If protection structure enables the window the routine will |
| * also enable the protection window. |
| * |
| * INPUT: |
| * pciIf - PCI interface number. |
| * winNum - Protecion window number. |
| * pProtWin - Protection window structure. |
| * |
| * OUTPUT: |
| * N/A |
| * |
| * RETURN: |
| * MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK |
| * |
| *******************************************************************************/ |
| MV_STATUS mvPciProtWinSet(MV_U32 pciIf, |
| MV_U32 winNum, |
| MV_PCI_PROT_WIN *pProtWin) |
| { |
| MV_U32 protBaseLow; |
| MV_U32 protBaseHigh; |
| MV_U32 protSize; |
| |
| /* Parameter checking */ |
| if (pciIf >= mvCtrlPciMaxIfGet()) |
| { |
| mvOsPrintf("mvPciProtWinSet: ERR. Invalid PCI interface %d\n", pciIf); |
| return MV_BAD_PARAM; |
| } |
| if (winNum >= PCI_MAX_PROT_WIN) |
| { |
| mvOsPrintf("mvPciProtWinSet: ERR. Invalid window num %d\n", winNum); |
| return MV_BAD_PARAM; |
| } |
| |
| /* Check if the window complies with PCI spec */ |
| if (MV_TRUE != pciWinIsValid(pProtWin->addrWin.baseLow, |
| pProtWin->addrWin.size)) |
| { |
| mvOsPrintf("mvPciProtWinSet: ERR. Win base 0x%x unaligned to size 0x%llx\n", |
| pProtWin->addrWin.baseLow, pProtWin->addrWin.size); |
| |
| return MV_BAD_PARAM; |
| } |
| |
| if (pProtWin->attributes.swapType >= SWAP_TYPE_MAX) |
| { |
| mvOsPrintf("mvPciProtWinSet: ERR. Swap parameter invalid %d\n", |
| pProtWin->attributes.swapType); |
| return MV_BAD_PARAM; |
| |
| } |
| |
| /* 1) Calculate protection window base low register value */ |
| protBaseLow = pProtWin->addrWin.baseLow; |
| |
| /* Setting the appropriate bits according to the passed values */ |
| if (MV_TRUE == pProtWin->enable) |
| { |
| protBaseLow |= PACBLR_EN; |
| } |
| else |
| { |
| protBaseLow &= ~PACBLR_EN; |
| } |
| |
| /* I/O Cache Coherency */ |
| protBaseLow |= ((MV_U32)pProtWin->attributes.snoop << PACBLR_SNOOP_OFFS); |
| |
| /* Access protect */ |
| if (ALLOWED == pProtWin->attributes.access) |
| { |
| protBaseLow &= ~PACBLR_ACCPROT; |
| } |
| else |
| { |
| protBaseLow |= PACBLR_ACCPROT; |
| } |
| |
| /* Write Protect */ |
| if (ALLOWED == pProtWin->attributes.write) |
| { |
| protBaseLow &= ~PACBLR_WRPROT; |
| } |
| else |
| { |
| protBaseLow |= PACBLR_WRPROT; |
| } |
| |
| /* PCI slave Data Swap Control */ |
| protBaseLow |= (pProtWin->attributes.swapType << PACBLR_PCISWAP_OFFS); |
| |
| |
| /* Read Max Burst */ |
| if (( pciBurstBytes2Reg(pProtWin->attributes.readMaxBurst) << PACBLR_RDMBURST_OFFS) > PACBLR_RDMBURST_128BYTE) |
| { |
| mvOsPrintf("mvPciProtWinSet: ERR illigal read max burst\n"); |
| return MV_ERROR; |
| } |
| protBaseLow |= (pciBurstBytes2Reg(pProtWin->attributes.readMaxBurst) << PACBLR_RDMBURST_OFFS); |
| |
| |
| /* Typical PCI read transaction Size. Only valid for PCI conventional */ |
| if ((pciBurstBytes2Reg(pProtWin->attributes.readBurst) << PACBLR_RDSIZE_OFFS) > PACBLR_RDSIZE_256BYTE ) |
| { |
| mvOsPrintf("mvPciProtWinSet: ERR. illigal read size\n"); |
| return MV_ERROR; |
| } |
| protBaseLow |= (pciBurstBytes2Reg(pProtWin->attributes.readBurst) << PACBLR_RDSIZE_OFFS); |
| |
| |
| /* 2) Calculate protection window base high register value */ |
| protBaseHigh = pProtWin->addrWin.baseHigh; |
| |
| /* 3) Calculate protection window size register value */ |
| protSize = ctrlSizeToReg(pProtWin->addrWin.size, PACSR_SIZE_ALIGNMENT) << PACSR_SIZE_OFFS; |
| |
| |
| /* Write Max Burst */ |
| if ((pciBurstBytes2Reg(pProtWin->attributes.writeMaxBurst) << PACSR_WRMBURST_OFFS) > PACSR_WRMBURST_128BYTE ) |
| { |
| mvOsPrintf("mvPciProtWinSet: ERR illigal write max burst\n"); |
| return MV_ERROR; |
| } |
| protSize |= (pciBurstBytes2Reg(pProtWin->attributes.writeMaxBurst) << PACSR_WRMBURST_OFFS); |
| |
| /* Pci Order */ |
| if (MV_TRUE == pProtWin->attributes.pciOrder) |
| { |
| protSize |= PACSR_PCI_ORDERING; |
| } |
| else |
| { |
| protSize &= ~PACSR_PCI_ORDERING; |
| } |
| |
| /* Writing protection window walues into registers */ |
| MV_REG_WRITE(PCI_ACCESS_CTRL_BASEL_REG(pciIf,winNum), protBaseLow); |
| MV_REG_WRITE(PCI_ACCESS_CTRL_BASEH_REG(pciIf,winNum), protBaseHigh); |
| MV_REG_WRITE(PCI_ACCESS_CTRL_SIZE_REG(pciIf,winNum), protSize); |
| |
| return MV_OK; |
| } |
| /******************************************************************************* |
| * mvPciProtWinGet - Get PCI protection access window |
| * |
| * DESCRIPTION: |
| * This function gets a specified address window and access protection |
| * attributes for a specific protection window . |
| * |
| * INPUT: |
| * pciIf - PCI interface number. |
| * winNum - Protecion window number. |
| * pProtWin - pointer to a Protection window structure. |
| * |
| * OUTPUT: |
| * pProtWin - Protection window structure. |
| * |
| * RETURN: |
| * MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK |
| * |
| *******************************************************************************/ |
| MV_STATUS mvPciProtWinGet(MV_U32 pciIf, |
| MV_U32 winNum, |
| MV_PCI_PROT_WIN *pProtWin) |
| { |
| MV_U32 protBaseLow; |
| MV_U32 protBaseHigh; |
| MV_U32 protSize; |
| |
| /* Parameter checking */ |
| if (pciIf >= mvCtrlPciMaxIfGet()) |
| { |
| mvOsPrintf("mvPciProtWinGet: ERR. Invalid PCI interface %d\n", pciIf); |
| return MV_BAD_PARAM; |
| } |
| if (winNum >= PCI_MAX_PROT_WIN) |
| { |
| mvOsPrintf("mvPciProtWinGet: ERR. Invalid window num %d\n", winNum); |
| return MV_BAD_PARAM; |
| } |
| |
| /* Writing protection window walues into registers */ |
| protBaseLow = MV_REG_READ(PCI_ACCESS_CTRL_BASEL_REG(pciIf,winNum)); |
| protBaseHigh = MV_REG_READ(PCI_ACCESS_CTRL_BASEH_REG(pciIf,winNum)); |
| protSize = MV_REG_READ(PCI_ACCESS_CTRL_SIZE_REG(pciIf,winNum)); |
| |
| |
| /* 1) Get Protection Windows base low */ |
| pProtWin->addrWin.baseLow = protBaseLow & PACBLR_BASE_L_MASK; |
| |
| /* Get the appropriate protection attributes according to register bits*/ |
| |
| /* Is Windows enabled ? */ |
| if (protBaseLow & PACBLR_EN) |
| { |
| pProtWin->enable = MV_TRUE; |
| } |
| else |
| { |
| pProtWin->enable = MV_FALSE; |
| } |
| |
| |
| /* What is access protect ? */ |
| if (protBaseLow & PACBLR_ACCPROT) |
| { |
| pProtWin->attributes.access = FORBIDDEN; |
| } |
| else |
| { |
| pProtWin->attributes.access = ALLOWED; |
| } |
| |
| /* Is write protect ? */ |
| if (protBaseLow & PACBLR_WRPROT) |
| { |
| pProtWin->attributes.write = FORBIDDEN; |
| } |
| else |
| { |
| pProtWin->attributes.write = ALLOWED; |
| } |
| |
| |
| /* PCI slave Data Swap Control */ |
| pProtWin->attributes.swapType = (protBaseLow & PACBLR_PCISWAP_MASK) >> PACBLR_PCISWAP_OFFS; |
| |
| |
| /* Read Max Burst */ |
| pProtWin->attributes.readMaxBurst = pciBurstReg2Bytes((protBaseLow & PACBLR_RDMBURST_MASK) >> PACBLR_RDMBURST_OFFS); |
| |
| /* Typical PCI read transaction Size. */ |
| pProtWin->attributes.readBurst = pciBurstReg2Bytes((protBaseLow & PACBLR_RDSIZE_MASK) >> PACBLR_RDSIZE_OFFS); |
| |
| |
| /* window base high register value */ |
| pProtWin->addrWin.baseHigh = protBaseHigh; |
| |
| /*Calculate protection window size register value */ |
| pProtWin->addrWin.size = ctrlRegToSize(((protSize & PACSR_SIZE_MASK) >> PACSR_SIZE_OFFS),PACSR_SIZE_ALIGNMENT); |
| |
| |
| /* Write Max Burst */ |
| pProtWin->attributes.writeMaxBurst = pciBurstReg2Bytes((protSize & PACSR_WRMBURST_MASK) >> PACSR_WRMBURST_OFFS); |
| |
| /* Pci Order */ |
| if (protSize & PACSR_PCI_ORDERING) |
| { |
| pProtWin->attributes.pciOrder = MV_TRUE; |
| } |
| else |
| { |
| pProtWin->attributes.pciOrder = MV_FALSE; |
| } |
| |
| |
| return MV_OK; |
| } |
| |
| |
| /******************************************************************************* |
| * mvPciProtWinEnable - Enable/disable a PCI protection access window |
| * |
| * DESCRIPTION: |
| * This function enable/disable a PCI protection access window. |
| * if parameter 'enable' == MV_TRUE the routine will enable the |
| * protection window, otherwise, the protection window will be disabled. |
| * |
| * INPUT: |
| * pciIf - PCI interface number. |
| * winNum - Protecion window number. |
| * enable - Enable/disable parameter. |
| * |
| * OUTPUT: |
| * N/A |
| * |
| * RETURN: |
| * MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK |
| * |
| *******************************************************************************/ |
| MV_STATUS mvPciProtWinEnable(MV_U32 pciIf, MV_U32 winNum, MV_BOOL enable) |
| { |
| /* Parameter checking */ |
| if (pciIf >= mvCtrlPciMaxIfGet()) |
| { |
| mvOsPrintf("mvPciProtWinEnable: ERR. Invalid PCI interface %d\n", |
| pciIf); |
| return MV_BAD_PARAM; |
| } |
| |
| if (winNum >= PCI_MAX_PROT_WIN) |
| { |
| mvOsPrintf("mvPciProtWinEnable: ERR. Invalid window num %d\n", winNum); |
| return MV_BAD_PARAM; |
| } |
| |
| if (MV_TRUE == enable) |
| { |
| MV_REG_BIT_SET(PCI_ACCESS_CTRL_BASEL_REG(pciIf,winNum), PACBLR_EN); |
| } |
| else |
| { |
| MV_REG_BIT_RESET(PCI_ACCESS_CTRL_BASEL_REG(pciIf,winNum), PACBLR_EN); |
| } |
| |
| return MV_OK; |
| } |
| |
| |
| /******************************************************************************* |
| * mvPciTargetRemap - Set PCI to target address window remap. |
| * |
| * DESCRIPTION: |
| * The PCI interface supports remap of the BAR original address window. |
| * For each BAR it is possible to define a remap address. For example |
| * an address 0x12345678 that hits BAR 0x10 (SDRAM CS[0]) will be modified |
| * according to remap register but will also be targeted to the |
| * SDRAM CS[0]. |
| * |
| * INPUT: |
| * pciIf - PCI interface number. |
| * bar - Peripheral target enumerator accessed by slave. |
| * pAddrWin - Address window to be checked. |
| * |
| * OUTPUT: |
| * None. |
| * |
| * RETURN: |
| * MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK |
| * |
| *******************************************************************************/ |
| MV_STATUS mvPciTargetRemap(MV_U32 pciIf, |
| MV_PCI_BAR bar, |
| MV_ADDR_WIN *pAddrWin) |
| { |
| PCI_BAR_REG_INFO barRegInfo; |
| |
| /* Parameter checking */ |
| if (pciIf >= mvCtrlPciMaxIfGet()) |
| { |
| mvOsPrintf("mvPciTargetRemap: ERR. Invalid PCI interface num %d\n", |
| pciIf); |
| return MV_BAD_PARAM; |
| } |
| |
| if (MV_IS_NOT_ALIGN(pAddrWin->baseLow, PBARR_REMAP_ALIGNMENT)) |
| { |
| mvOsPrintf("mvPciTargetRemap: Error remapping PCI interface %d bar %s."\ |
| "\nAddress 0x%08x is unaligned to size 0x%llx.\n", |
| pciIf, |
| pciBarNameGet(bar), |
| pAddrWin->baseLow, |
| pAddrWin->size); |
| return MV_ERROR; |
| } |
| |
| pciBarRegInfoGet(pciIf, bar, &barRegInfo); |
| |
| /* Set remap low register value */ |
| MV_REG_WRITE(barRegInfo.remapLowRegOffs, pAddrWin->baseLow); |
| |
| /* Skip base high settings if the BAR has only base low (32-bit) */ |
| if (0 != barRegInfo.remapHighRegOffs) |
| { |
| MV_REG_WRITE(barRegInfo.remapHighRegOffs, pAddrWin->baseHigh); |
| } |
| |
| return MV_OK; |
| } |
| |
| /******************************************************************************* |
| * pciWinOverlapDetect - Detect address windows overlapping |
| * |
| * DESCRIPTION: |
| * This function detects address window overlapping of a given address |
| * window in PCI BARs. |
| * |
| * INPUT: |
| * pAddrWin - Address window to be checked. |
| * bar - BAR to be accessed by slave. |
| * |
| * OUTPUT: |
| * None. |
| * |
| * RETURN: |
| * MV_TRUE if the given address window overlap current address |
| * decode map, MV_FALSE otherwise. |
| * |
| *******************************************************************************/ |
| static MV_BOOL pciWinOverlapDetect(MV_U32 pciIf, MV_PCI_BAR bar, MV_ADDR_WIN *pAddrWin) |
| { |
| MV_U32 barEnableReg; |
| MV_U32 targetBar; |
| MV_PCI_BAR_WIN barAddrWin; |
| |
| /* Read base address enable register. Do not check disabled windows */ |
| barEnableReg = MV_REG_READ(PCI_BASE_ADDR_ENABLE_REG(pciIf)); |
| |
| for(targetBar = 0; targetBar < PCI_MAX_BARS; targetBar++) { |
| /* don't check our target or illegal targets */ |
| if (targetBar == bar) |
| continue; |
| |
| /* Do not check disabled windows */ |
| if (barEnableReg & (BARER_ENABLE(targetBar))) |
| continue; |
| |
| /* Get window parameters */ |
| if (MV_OK != mvPciTargetWinGet(pciIf, targetBar, &barAddrWin)) { |
| mvOsPrintf("pciWinOverlapDetect: ERR. TargetWinGet failed\n"); |
| return MV_ERROR; |
| } |
| |
| /* skip overlapp detect between MEM_INTER_REGS_BAR and IO_INTER_REGS_BAR*/ |
| if (((bar == MEM_INTER_REGS_BAR)&&(targetBar == IO_INTER_REGS_BAR)) || |
| ((bar == IO_INTER_REGS_BAR)&&(targetBar == MEM_INTER_REGS_BAR))) { |
| return MV_FALSE; |
| } else if(MV_TRUE == mvWinOverlapTest(pAddrWin, &barAddrWin.addrWin)) { |
| mvOsPrintf("pciWinOverlapDetect: BAR %d overlap current %d\n", bar, targetBar); |
| return MV_TRUE; |
| } |
| } |
| |
| return MV_FALSE; |
| } |
| |
| /******************************************************************************* |
| * cpuWinIsValid - Check if the given address window is valid |
| * |
| * DESCRIPTION: |
| * PCI spec restrict BAR base to be aligned to BAR size. |
| * This function checks if the given address window is valid. |
| * |
| * INPUT: |
| * baseLow - 32bit low base address. |
| * size - Window size. |
| * |
| * OUTPUT: |
| * None. |
| * |
| * RETURN: |
| * MV_TRUE if the address window is valid, MV_FALSE otherwise. |
| * |
| *******************************************************************************/ |
| static MV_STATUS pciWinIsValid(MV_U32 baseLow, MV_U32 size) |
| { |
| |
| /* PCI spec restrict BAR base to be aligned to BAR size */ |
| if(MV_IS_NOT_ALIGN(baseLow, size)) |
| { |
| return MV_ERROR; |
| } |
| else |
| { |
| return MV_TRUE; |
| } |
| } |
| |
| /******************************************************************************* |
| * pciBarRegInfoGet - Get BAR register information |
| * |
| * DESCRIPTION: |
| * PCI BARs registers offsets are inconsecutive. |
| * This function gets a PCI BAR register information like register offsets |
| * and function location of the BAR. |
| * |
| * INPUT: |
| * pciIf - PCI interface number. |
| * bar - The PCI BAR in question. |
| * |
| * OUTPUT: |
| * pBarRegInfo - BAR register info struct. |
| * |
| * RETURN: |
| * MV_BAD_PARAM when bad parameters ,MV_ERROR on error ,othewise MV_OK |
| * |
| *******************************************************************************/ |
| static MV_STATUS pciBarRegInfoGet(MV_U32 pciIf, |
| MV_PCI_BAR bar, |
| PCI_BAR_REG_INFO *pBarRegInfo) |
| { |
| switch (bar) |
| { |
| /* Function 0 Bars */ |
| #if defined(MV_INCLUDE_SDRAM_CS0) |
| case CS0_BAR: /* SDRAM chip select 0 bar*/ |
| pBarRegInfo->funcNum = 0; |
| pBarRegInfo->baseLowRegOffs = PCI_SCS0_BASE_ADDR_LOW; |
| pBarRegInfo->baseHighRegOffs = PCI_SCS0_BASE_ADDR_HIGH; |
| pBarRegInfo->sizeRegOffs = PCI_CS0_BAR_SIZE_REG(pciIf); |
| pBarRegInfo->remapLowRegOffs = PCI_CS0_ADDR_REMAP_REG(pciIf); |
| pBarRegInfo->remapHighRegOffs = 0; |
| break; |
| #endif |
| #if defined(MV_INCLUDE_SDRAM_CS1) |
| case CS1_BAR: /* SDRAM chip select 1 bar*/ |
| pBarRegInfo->funcNum = 0; |
| pBarRegInfo->baseLowRegOffs = PCI_SCS1_BASE_ADDR_LOW; |
| pBarRegInfo->baseHighRegOffs = PCI_SCS1_BASE_ADDR_HIGH; |
| pBarRegInfo->sizeRegOffs = PCI_CS1_BAR_SIZE_REG(pciIf); |
| pBarRegInfo->remapLowRegOffs = PCI_CS1_ADDR_REMAP_REG(pciIf); |
| pBarRegInfo->remapHighRegOffs = 0; |
| break; |
| #endif |
| case MEM_INTER_REGS_BAR: /* Memory Mapped Internal bar */ |
| pBarRegInfo->funcNum = 0; |
| pBarRegInfo->baseLowRegOffs = PCI_INTER_REG_MEM_MAPPED_BASE_ADDR_L; |
| pBarRegInfo->baseHighRegOffs = PCI_INTER_REG_MEM_MAPPED_BASE_ADDR_H; |
| pBarRegInfo->sizeRegOffs = 0; |
| pBarRegInfo->remapLowRegOffs = 0; |
| pBarRegInfo->remapHighRegOffs = 0; |
| break; |
| |
| /* Function 1 Bars */ |
| #if defined(MV_INCLUDE_SDRAM_CS2) |
| case CS2_BAR: /* SDRAM chip select 2 bar*/ |
| pBarRegInfo->funcNum = 1; |
| pBarRegInfo->baseLowRegOffs = PCI_SCS2_BASE_ADDR_LOW; |
| pBarRegInfo->baseHighRegOffs = PCI_SCS2_BASE_ADDR_HIGH; |
| pBarRegInfo->sizeRegOffs = PCI_CS2_BAR_SIZE_REG(pciIf); |
| pBarRegInfo->remapLowRegOffs = PCI_CS2_ADDR_REMAP_REG(pciIf); |
| pBarRegInfo->remapHighRegOffs = 0; |
| break; |
| #endif |
| #if defined(MV_INCLUDE_SDRAM_CS3) |
| case CS3_BAR: /* SDRAM chip select 3 bar*/ |
| pBarRegInfo->funcNum = 1; |
| pBarRegInfo->baseLowRegOffs = PCI_SCS3_BASE_ADDR_LOW; |
| pBarRegInfo->baseHighRegOffs = PCI_SCS3_BASE_ADDR_HIGH; |
| pBarRegInfo->sizeRegOffs = PCI_CS3_BAR_SIZE_REG(pciIf); |
| pBarRegInfo->remapLowRegOffs = PCI_CS3_ADDR_REMAP_REG(pciIf); |
| pBarRegInfo->remapHighRegOffs = 0; |
| break; |
| #endif |
| #if defined(MV_INCLUDE_DEVICE_CS0) |
| /* Function 2 Bars */ |
| case DEVCS0_BAR: /* Device chip select 0 bar*/ |
| pBarRegInfo->funcNum = 2; |
| pBarRegInfo->baseLowRegOffs = PCI_DEVCS0_BASE_ADDR_LOW; |
| pBarRegInfo->baseHighRegOffs = PCI_DEVCS0_BASE_ADDR_HIGH; |
| pBarRegInfo->sizeRegOffs = PCI_DEVCS0_BAR_SIZE_REG(pciIf); |
| pBarRegInfo->remapLowRegOffs = PCI_DEVCS0_ADDR_REMAP_REG(pciIf); |
| pBarRegInfo->remapHighRegOffs = 0; |
| break; |
| #endif |
| #if defined(MV_INCLUDE_DEVICE_CS1) |
| case DEVCS1_BAR: /* Device chip select 0 bar*/ |
| pBarRegInfo->funcNum = 2; |
| pBarRegInfo->baseLowRegOffs = PCI_DEVCS1_BASE_ADDR_LOW; |
| pBarRegInfo->baseHighRegOffs = PCI_DEVCS1_BASE_ADDR_HIGH; |
| pBarRegInfo->sizeRegOffs = PCI_DEVCS1_BAR_SIZE_REG(pciIf); |
| pBarRegInfo->remapLowRegOffs = PCI_DEVCS1_ADDR_REMAP_REG(pciIf); |
| pBarRegInfo->remapHighRegOffs = 0; |
| break; |
| #endif |
| #if defined(MV_INCLUDE_DEVICE_CS2) |
| case DEVCS2_BAR: /* Device chip select 0 bar*/ |
| pBarRegInfo->funcNum = 2; |
| pBarRegInfo->baseLowRegOffs = PCI_DEVCS2_BASE_ADDR_LOW; |
| pBarRegInfo->baseHighRegOffs = PCI_DEVCS2_BASE_ADDR_HIGH; |
| pBarRegInfo->sizeRegOffs = PCI_DEVCS2_BAR_SIZE_REG(pciIf); |
| pBarRegInfo->remapLowRegOffs = PCI_DEVCS2_ADDR_REMAP_REG(pciIf); |
| pBarRegInfo->remapHighRegOffs = 0; |
| break; |
| #endif |
| case BOOTCS_BAR: /* Boot device chip select bar*/ |
| pBarRegInfo->funcNum = 3; |
| pBarRegInfo->baseLowRegOffs = PCI_BOOTCS_BASE_ADDR_LOW; |
| pBarRegInfo->baseHighRegOffs = PCI_BOOTCS_BASE_ADDR_HIGH; |
| pBarRegInfo->sizeRegOffs = PCI_BOOTCS_BAR_SIZE_REG(pciIf); |
| pBarRegInfo->remapLowRegOffs = PCI_BOOTCS_ADDR_REMAP_REG(pciIf); |
| pBarRegInfo->remapHighRegOffs = 0; |
| break; |
| |
| /* Function 4 Bars */ |
| case P2P_MEM0: /* P2P memory 0 */ |
| pBarRegInfo->funcNum = 4; |
| pBarRegInfo->baseLowRegOffs = PCI_P2P_MEM0_BASE_ADDR_LOW; |
| pBarRegInfo->baseHighRegOffs = PCI_P2P_MEM0_BASE_ADDR_HIGH; |
| pBarRegInfo->sizeRegOffs = PCI_P2P_MEM0_BAR_SIZE_REG(pciIf); |
| pBarRegInfo->remapLowRegOffs = PCI_P2P_MEM0_ADDR_REMAP_LOW_REG(pciIf); |
| pBarRegInfo->remapHighRegOffs = PCI_P2P_MEM0_ADDR_REMAP_HIGH_REG(pciIf); |
| break; |
| case P2P_IO: /* P2P IO */ |
| pBarRegInfo->funcNum = 4; |
| pBarRegInfo->baseLowRegOffs = PCI_P2P_IO_BASE_ADDR; |
| pBarRegInfo->baseHighRegOffs = 0; |
| pBarRegInfo->sizeRegOffs = PCI_P2P_IO_BAR_SIZE_REG(pciIf); |
| pBarRegInfo->remapLowRegOffs = PCI_P2P_IO_ADDR_REMAP_REG(pciIf); |
| pBarRegInfo->remapHighRegOffs = 0; |
| break; |
| case IO_INTER_REGS_BAR: /* IO Mapped Internal bar */ |
| pBarRegInfo->funcNum = 4; |
| pBarRegInfo->baseLowRegOffs = PCI_INTER_REGS_IO_MAPPED_BASE_ADDR; |
| pBarRegInfo->baseHighRegOffs = 0; |
| pBarRegInfo->sizeRegOffs = 0; |
| pBarRegInfo->remapLowRegOffs = 0; |
| pBarRegInfo->remapHighRegOffs = 0; |
| break; |
| |
| |
| default: |
| mvOsPrintf("mvPciTargetWinGet: ERR.non existing target\n"); |
| return MV_ERROR; |
| |
| } |
| |
| return MV_OK; |
| } |
| |
| /******************************************************************************* |
| * pciBarNameGet - Get the string name of PCI BAR. |
| * |
| * DESCRIPTION: |
| * This function get the string name of PCI BAR. |
| * |
| * INPUT: |
| * bar - PCI bar number. |
| * |
| * OUTPUT: |
| * None. |
| * |
| * RETURN: |
| * pointer to the string name of PCI BAR. |
| * |
| *******************************************************************************/ |
| const MV_8* pciBarNameGet( MV_PCI_BAR bar ) |
| { |
| switch( bar ) |
| { |
| #if defined(MV_INCLUDE_SDRAM_CS0) |
| case CS0_BAR: |
| return "CS0_BAR.............."; |
| #endif |
| #if defined(MV_INCLUDE_SDRAM_CS1) |
| case CS1_BAR: |
| return "CS1_BAR.............."; |
| #endif |
| #if defined(MV_INCLUDE_SDRAM_CS2) |
| case CS2_BAR: |
| return "CS2_BAR.............."; |
| #endif |
| #if defined(MV_INCLUDE_SDRAM_CS3) |
| case CS3_BAR: |
| return "CS3_BAR.............."; |
| #endif |
| #if defined(MV_INCLUDE_DEVICE_CS0) |
| case DEVCS0_BAR: |
| return "DEVCS0_BAR..........."; |
| #endif |
| #if defined(MV_INCLUDE_DEVICE_CS1) |
| case DEVCS1_BAR: |
| return "DEVCS1_BAR..........."; |
| #endif |
| #if defined(MV_INCLUDE_DEVICE_CS2) |
| case DEVCS2_BAR: |
| return "DEVCS2_BAR..........."; |
| #endif |
| case BOOTCS_BAR: |
| return "BOOTCS_BAR..........."; |
| case MEM_INTER_REGS_BAR: |
| return "MEM_INTER_REGS_BAR..."; |
| case IO_INTER_REGS_BAR: |
| return "IO_INTER_REGS_BAR...."; |
| case P2P_MEM0: |
| return "P2P_MEM0............."; |
| case P2P_IO: |
| return "P2P_IO..............."; |
| default: |
| return "target unknown"; |
| } |
| } |
| |
| /******************************************************************************* |
| * mvPciAddrDecShow - Print the PCI address decode map (BARs). |
| * |
| * DESCRIPTION: |
| * This function print the PCI address decode map (BARs). |
| * |
| * INPUT: |
| * None. |
| * |
| * OUTPUT: |
| * None. |
| * |
| * RETURN: |
| * None. |
| * |
| *******************************************************************************/ |
| MV_VOID mvPciAddrDecShow(MV_VOID) |
| { |
| MV_PCI_BAR_WIN win; |
| MV_PCI_BAR bar; |
| MV_U32 pciIf; |
| |
| for( pciIf = 0; pciIf < mvCtrlPciMaxIfGet(); pciIf++ ) |
| { |
| mvOsOutput( "\n" ); |
| mvOsOutput( "PCI%d:\n", pciIf ); |
| mvOsOutput( "-----\n" ); |
| |
| for( bar = 0; bar < PCI_MAX_BARS; bar++ ) |
| { |
| memset( &win, 0, sizeof(MV_PCI_BAR_WIN) ); |
| |
| mvOsOutput( "%s ", pciBarNameGet(bar) ); |
| |
| if( mvPciTargetWinGet( pciIf, bar, &win ) == MV_OK ) |
| { |
| if( win.enable ) |
| { |
| mvOsOutput( "base %08x, ", win.addrWin.baseLow ); |
| mvSizePrint( win.addrWin.size ); |
| mvOsOutput( "\n" ); |
| } |
| else |
| mvOsOutput( "disable\n" ); |
| } |
| } |
| } |
| } |
| |
| /* convert burst bytes to register value*/ |
| static MV_U32 pciBurstBytes2Reg(MV_U32 size) |
| { |
| MV_U32 ret; |
| switch(size) |
| { |
| case 32: ret = 0; break; |
| case 64: ret = 1; break; |
| case 128: ret = 2; break; |
| case 256: ret = 3; break; |
| default: ret = 0xF; /* error */ |
| } |
| return ret; |
| } |
| |
| /* convert register value to burst bytes*/ |
| static MV_U32 pciBurstReg2Bytes(MV_U32 size) |
| { |
| MV_U32 ret; |
| switch(size) |
| { |
| case 0: ret = 32; break; |
| case 1: ret = 64; break; |
| case 2: ret = 128; break; |
| case 3: ret = 256; break; |
| default: ret = 0x0; /* error */ |
| } |
| return ret; |
| } |
| |