1/******************************************************************************* 2Copyright (C) Marvell International Ltd. and its affiliates 3 4This software file (the "File") is owned and distributed by Marvell 5International Ltd. and/or its affiliates ("Marvell") under the following 6alternative licensing terms. Once you have made an election to distribute the 7File under one of the following license alternatives, please (i) delete this 8introductory statement regarding license alternatives, (ii) delete the two 9license alternatives that you have not elected to use and (iii) preserve the 10Marvell copyright notice above. 11 12******************************************************************************** 13Marvell Commercial License Option 14 15If you received this File from Marvell and you have entered into a commercial 16license agreement (a "Commercial License") with Marvell, the File is licensed 17to you under the terms of the applicable Commercial License. 18 19******************************************************************************** 20Marvell GPL License Option 21 22If you received this File from Marvell, you may opt to use, redistribute and/or 23modify this File in accordance with the terms and conditions of the General 24Public License Version 2, June 1991 (the "GPL License"), a copy of which is 25available along with the File in the license.txt file or by writing to the Free 26Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 27on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 28 29THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 30WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 31DISCLAIMED. The GPL License provides additional details about this warranty 32disclaimer. 33******************************************************************************** 34Marvell BSD License Option 35 36If you received this File from Marvell, you may opt to use, redistribute and/or 37modify this File under the following licensing terms. 38Redistribution and use in source and binary forms, with or without modification, 39are permitted provided that the following conditions are met: 40 41 * Redistributions of source code must retain the above copyright notice, 42 this list of conditions and the following disclaimer. 43 44 * Redistributions in binary form must reproduce the above copyright 45 notice, this list of conditions and the following disclaimer in the 46 documentation and/or other materials provided with the distribution. 47 48 * Neither the name of Marvell nor the names of its contributors may be 49 used to endorse or promote products derived from this software without 50 specific prior written permission. 51 52THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 53ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 54WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 55DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 56ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 57(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 58LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 59ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 61SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 63*******************************************************************************/ 64 65 66#include "ctrlEnv/sys/mvSysGbe.h" 67 68 69 70typedef struct _mvEthDecWin 71{ 72 MV_TARGET target; 73 MV_ADDR_WIN addrWin; /* An address window*/ 74 MV_BOOL enable; /* Address decode window is enabled/disabled */ 75 76}MV_ETH_DEC_WIN; 77 78MV_TARGET ethAddrDecPrioTap[] = 79{ 80#if defined(MV_INCLUDE_SDRAM_CS0) 81 SDRAM_CS0, 82#endif 83#if defined(MV_INCLUDE_SDRAM_CS1) 84 SDRAM_CS1, 85#endif 86#if defined(MV_INCLUDE_SDRAM_CS2) 87 SDRAM_CS2, 88#endif 89#if defined(MV_INCLUDE_SDRAM_CS3) 90 SDRAM_CS3, 91#endif 92#if defined(MV_INCLUDE_DEVICE_CS0) 93 DEVICE_CS0, 94#endif 95#if defined(MV_INCLUDE_DEVICE_CS1) 96 DEVICE_CS1, 97#endif 98#if defined(MV_INCLUDE_DEVICE_CS2) 99 DEVICE_CS2, 100#endif 101#if defined(MV_INCLUDE_DEVICE_CS3) 102 DEVICE_CS3, 103#endif 104#if defined(MV_INCLUDE_PEX) 105 PEX0_IO, 106#endif 107 TBL_TERM 108}; 109 110static MV_STATUS ethWinOverlapDetect(int port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin); 111static MV_STATUS mvEthWinSet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin); 112static MV_STATUS mvEthWinGet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin); 113 114 115/******************************************************************************* 116* mvEthWinInit - Initialize ETH address decode windows 117* 118* DESCRIPTION: 119* This function initialize ETH window decode unit. It set the 120* default address decode windows of the unit. 121* 122* INPUT: 123* None. 124* 125* OUTPUT: 126* None. 127* 128* RETURN: 129* MV_ERROR if setting fail. 130*******************************************************************************/ 131/* Configure EthDrv memory map registes. */ 132MV_STATUS mvEthWinInit (int port) 133{ 134 MV_U32 winNum, status, winPrioIndex=0, i, regVal=0; 135 MV_ETH_DEC_WIN ethWin; 136 MV_CPU_DEC_WIN cpuAddrDecWin; 137 static MV_U32 accessProtReg = 0; 138 139#if (MV_ETH_VERSION <= 1) 140 static MV_BOOL isFirst = MV_TRUE; 141 142 if(isFirst == MV_FALSE) 143 { 144 MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(port), accessProtReg); 145 return MV_OK; 146 } 147 isFirst = MV_FALSE; 148#endif /* MV_GIGA_ETH_VERSION */ 149 150 /* Initiate Ethernet address decode */ 151 152 /* First disable all address decode windows */ 153 for(winNum=0; winNum<ETH_MAX_DECODE_WIN; winNum++) 154 { 155 regVal |= MV_BIT_MASK(winNum); 156 } 157 MV_REG_WRITE(ETH_BASE_ADDR_ENABLE_REG(port), regVal); 158 159 /* Go through all windows in user table until table terminator */ 160 for (winNum=0; ((ethAddrDecPrioTap[winPrioIndex] != TBL_TERM) && 161 (winNum < ETH_MAX_DECODE_WIN)); ) 162 { 163 /* first get attributes from CPU If */ 164 status = mvCpuIfTargetWinGet(ethAddrDecPrioTap[winPrioIndex], 165 &cpuAddrDecWin); 166 167 if(MV_NO_SUCH == status) 168 { 169 winPrioIndex++; 170 continue; 171 } 172 if (MV_OK != status) 173 { 174 mvOsPrintf("mvEthWinInit: ERR. mvCpuIfTargetWinGet failed\n"); 175 return MV_ERROR; 176 } 177 178 if (cpuAddrDecWin.enable == MV_TRUE) 179 { 180 ethWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; 181 ethWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; 182 ethWin.addrWin.size = cpuAddrDecWin.addrWin.size; 183 ethWin.enable = MV_TRUE; 184 ethWin.target = ethAddrDecPrioTap[winPrioIndex]; 185 186 if(MV_OK != mvEthWinSet(port, winNum, ðWin)) 187 { 188 mvOsPrintf("mvEthWinInit: ERR. mvEthWinSet failed winNum=%d\n", 189 winNum); 190 return MV_ERROR; 191 } 192 winNum++; 193 } 194 winPrioIndex ++; 195 } 196 197 /* set full access to all windows. */ 198 for(i=0; i<winNum; i++) 199 { 200 accessProtReg |= (FULL_ACCESS << (i*2)); 201 } 202 MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(port), accessProtReg); 203 204 return MV_OK; 205} 206 207/******************************************************************************* 208* mvEthWinSet - Set ETH target address window 209* 210* DESCRIPTION: 211* This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0) 212* address window, also known as address decode window. 213* After setting this target window, the ETH will be able to access the 214* target within the address window. 215* 216* INPUT: 217* winNum - ETH to target address decode window number. 218* pAddrDecWin - ETH target window data structure. 219* 220* OUTPUT: 221* None. 222* 223* RETURN: 224* MV_ERROR if address window overlapps with other address decode windows. 225* MV_BAD_PARAM if base address is invalid parameter or target is 226* unknown. 227* 228*******************************************************************************/ 229MV_STATUS mvEthWinSet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin) 230{ 231 MV_TARGET_ATTRIB targetAttribs; 232 MV_DEC_REGS decRegs; 233 234 /* Parameter checking */ 235 if (winNum >= ETH_MAX_DECODE_WIN) 236 { 237 mvOsPrintf("mvEthWinSet: ERR. Invalid win num %d\n",winNum); 238 return MV_BAD_PARAM; 239 } 240 241 /* Check if the requested window overlapps with current windows */ 242 if (MV_TRUE == ethWinOverlapDetect(port, winNum, &pAddrDecWin->addrWin)) 243 { 244 mvOsPrintf("mvEthWinSet: ERR. Window %d overlap\n", winNum); 245 return MV_ERROR; 246 } 247 248 /* check if address is aligned to the size */ 249 if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) 250 { 251 mvOsPrintf("mvEthWinSet: Error setting Ethernet window %d to "\ 252 "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", 253 winNum, 254 mvCtrlTargetNameGet(pAddrDecWin->target), 255 pAddrDecWin->addrWin.baseLow, 256 pAddrDecWin->addrWin.size); 257 return MV_ERROR; 258 } 259 260 261 decRegs.baseReg = MV_REG_READ(ETH_WIN_BASE_REG(port, winNum)); 262 decRegs.sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum)); 263 264 if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) 265 { 266 mvOsPrintf("mvEthWinSet:mvCtrlAddrDecToReg Failed\n"); 267 return MV_ERROR; 268 } 269 270 mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); 271 272 /* set attributes */ 273 decRegs.baseReg &= ~ETH_WIN_ATTR_MASK; 274 decRegs.baseReg |= targetAttribs.attrib << ETH_WIN_ATTR_OFFS; 275 /* set target ID */ 276 decRegs.baseReg &= ~ETH_WIN_TARGET_MASK; 277 decRegs.baseReg |= targetAttribs.targetId << ETH_WIN_TARGET_OFFS; 278 279 /* for the safe side we disable the window before writing the new 280 values */ 281 mvEthWinEnable(port, winNum, MV_FALSE); 282 MV_REG_WRITE(ETH_WIN_BASE_REG(port, winNum), decRegs.baseReg); 283 284 /* Write to address decode Size Register */ 285 MV_REG_WRITE(ETH_WIN_SIZE_REG(port, winNum), decRegs.sizeReg); 286 287 /* Enable address decode target window */ 288 if (pAddrDecWin->enable == MV_TRUE) 289 { 290 mvEthWinEnable(port, winNum, MV_TRUE); 291 } 292 293 return MV_OK; 294} 295 296/******************************************************************************* 297* mvETHWinGet - Get dma peripheral target address window. 298* 299* DESCRIPTION: 300* Get ETH peripheral target address window. 301* 302* INPUT: 303* winNum - ETH to target address decode window number. 304* 305* OUTPUT: 306* pAddrDecWin - ETH target window data structure. 307* 308* RETURN: 309* MV_ERROR if register parameters are invalid. 310* 311*******************************************************************************/ 312MV_STATUS mvEthWinGet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin) 313{ 314 MV_DEC_REGS decRegs; 315 MV_TARGET_ATTRIB targetAttrib; 316 317 /* Parameter checking */ 318 if (winNum >= ETH_MAX_DECODE_WIN) 319 { 320 mvOsPrintf("mvEthWinGet: ERR. Invalid winNum %d\n", winNum); 321 return MV_NOT_SUPPORTED; 322 } 323 324 decRegs.baseReg = MV_REG_READ(ETH_WIN_BASE_REG(port, winNum)); 325 decRegs.sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum)); 326 327 if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) 328 { 329 mvOsPrintf("mvAhbToMbusWinGet: mvCtrlRegToAddrDec Failed \n"); 330 return MV_ERROR; 331 } 332 333 /* attrib and targetId */ 334 targetAttrib.attrib = 335 (decRegs.baseReg & ETH_WIN_ATTR_MASK) >> ETH_WIN_ATTR_OFFS; 336 targetAttrib.targetId = 337 (decRegs.baseReg & ETH_WIN_TARGET_MASK) >> ETH_WIN_TARGET_OFFS; 338 339 pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); 340 341 /* Check if window is enabled */ 342 if (~(MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port))) & (1 << winNum) ) 343 { 344 pAddrDecWin->enable = MV_TRUE; 345 } 346 else 347 { 348 pAddrDecWin->enable = MV_FALSE; 349 } 350 351 return MV_OK; 352} 353 354/******************************************************************************* 355* mvEthWinEnable - Enable/disable a ETH to target address window 356* 357* DESCRIPTION: 358* This function enable/disable a ETH to target address window. 359* According to parameter 'enable' the routine will enable the 360* window, thus enabling ETH accesses (before enabling the window it is 361* tested for overlapping). Otherwise, the window will be disabled. 362* 363* INPUT: 364* winNum - ETH to target address decode window number. 365* enable - Enable/disable parameter. 366* 367* OUTPUT: 368* N/A 369* 370* RETURN: 371* MV_ERROR if decode window number was wrong or enabled window overlapps. 372* 373*******************************************************************************/ 374MV_STATUS mvEthWinEnable(int port, MV_U32 winNum,MV_BOOL enable) 375{ 376 MV_ETH_DEC_WIN addrDecWin; 377 378 /* Parameter checking */ 379 if (winNum >= ETH_MAX_DECODE_WIN) 380 { 381 mvOsPrintf("mvEthTargetWinEnable:ERR. Invalid winNum%d\n",winNum); 382 return MV_ERROR; 383 } 384 385 if (enable == MV_TRUE) 386 { /* First check for overlap with other enabled windows */ 387 /* Get current window */ 388 if (MV_OK != mvEthWinGet(port, winNum, &addrDecWin)) 389 { 390 mvOsPrintf("mvEthTargetWinEnable:ERR. targetWinGet fail\n"); 391 return MV_ERROR; 392 } 393 /* Check for overlapping */ 394 if (MV_FALSE == ethWinOverlapDetect(port, winNum, &(addrDecWin.addrWin))) 395 { 396 /* No Overlap. Enable address decode target window */ 397 MV_REG_BIT_RESET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum)); 398 } 399 else 400 { /* Overlap detected */ 401 mvOsPrintf("mvEthTargetWinEnable:ERR. Overlap detected\n"); 402 return MV_ERROR; 403 } 404 } 405 else 406 { /* Disable address decode target window */ 407 MV_REG_BIT_SET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum)); 408 } 409 return MV_OK; 410} 411 412/******************************************************************************* 413* mvEthWinTargetGet - Get Window number associated with target 414* 415* DESCRIPTION: 416* 417* INPUT: 418* 419* OUTPUT: 420* 421* RETURN: 422* window number 423* 424*******************************************************************************/ 425MV_U32 mvEthWinTargetGet(int port, MV_TARGET target) 426{ 427 MV_ETH_DEC_WIN decWin; 428 MV_U32 winNum; 429 430 /* Check parameters */ 431 if (target >= MAX_TARGETS) 432 { 433 mvOsPrintf("mvAhbToMbusWinTargetGet: target %d is Illigal\n", target); 434 return 0xffffffff; 435 } 436 437 for (winNum=0; winNum<ETH_MAX_DECODE_WIN; winNum++) 438 { 439 if (mvEthWinGet(port, winNum,&decWin) != MV_OK) 440 { 441 mvOsPrintf("mvAhbToMbusWinTargetGet: window returned error\n"); 442 return 0xffffffff; 443 } 444 445 if (decWin.enable == MV_TRUE) 446 { 447 if (decWin.target == target) 448 { 449 return winNum; 450 } 451 } 452 } 453 return 0xFFFFFFFF; 454} 455 456/******************************************************************************* 457* mvEthProtWinSet - Set access protection of Ethernet to target window. 458* 459* DESCRIPTION: 460* Each Ethernet port can be configured with access attributes for each 461* of the Ethenret to target windows (address decode windows). This 462* function sets access attributes to a given window for the given channel. 463* 464* INPUTS: 465* ethPort - ETH channel number. See MV_ETH_CHANNEL enumerator. 466* winNum - IETH to target address decode window number. 467* access - IETH access rights. See MV_ACCESS_RIGHTS enumerator. 468* 469* OUTPUT: 470* None. 471* 472* RETURN: 473* MV_ERROR in case window number is invalid or access right reserved. 474* 475*******************************************************************************/ 476MV_STATUS mvEthProtWinSet(MV_U32 portNo, MV_U32 winNum, MV_ACCESS_RIGHTS access) 477{ 478 MV_U32 protReg; 479 480 /* Parameter checking */ 481 if(portNo >= mvCtrlEthMaxPortGet()) 482 { 483 mvOsPrintf("mvEthProtWinSet:ERR. Invalid port number %d\n", portNo); 484 return MV_ERROR; 485 } 486 487 if (winNum >= ETH_MAX_DECODE_WIN) 488 { 489 mvOsPrintf("mvEthProtWinSet:ERR. Invalid winNum%d\n",winNum); 490 return MV_ERROR; 491 } 492 493 if((access == ACC_RESERVED) || (access >= MAX_ACC_RIGHTS)) 494 { 495 mvOsPrintf("mvEthProtWinSet:ERR. Inv access param %d\n", access); 496 return MV_ERROR; 497 } 498 /* Read current protection register */ 499 protReg = MV_REG_READ(ETH_ACCESS_PROTECT_REG(portNo)); 500 501 /* Clear protection window field */ 502 protReg &= ~(ETH_PROT_WIN_MASK(winNum)); 503 504 /* Set new protection field value */ 505 protReg |= (access << (ETH_PROT_WIN_OFFS(winNum))); 506 507 /* Write protection register back */ 508 MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(portNo), protReg); 509 510 return MV_OK; 511} 512 513/******************************************************************************* 514* ethWinOverlapDetect - Detect ETH address windows overlapping 515* 516* DESCRIPTION: 517* An unpredicted behaviur is expected in case ETH address decode 518* windows overlapps. 519* This function detects ETH address decode windows overlapping of a 520* specified window. The function does not check the window itself for 521* overlapping. The function also skipps disabled address decode windows. 522* 523* INPUT: 524* winNum - address decode window number. 525* pAddrDecWin - An address decode window struct. 526* 527* OUTPUT: 528* None. 529* 530* RETURN: 531* MV_TRUE if the given address window overlap current address 532* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data 533* from registers. 534* 535*******************************************************************************/ 536static MV_STATUS ethWinOverlapDetect(int port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin) 537{ 538 MV_U32 baseAddrEnableReg; 539 MV_U32 winNumIndex; 540 MV_ETH_DEC_WIN addrDecWin; 541 542 /* Read base address enable register. Do not check disabled windows */ 543 baseAddrEnableReg = MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port)); 544 545 for (winNumIndex=0; winNumIndex<ETH_MAX_DECODE_WIN; winNumIndex++) 546 { 547 /* Do not check window itself */ 548 if (winNumIndex == winNum) 549 { 550 continue; 551 } 552 553 /* Do not check disabled windows */ 554 if (baseAddrEnableReg & (1 << winNumIndex)) 555 { 556 continue; 557 } 558 559 /* Get window parameters */ 560 if (MV_OK != mvEthWinGet(port, winNumIndex, &addrDecWin)) 561 { 562 mvOsPrintf("ethWinOverlapDetect: ERR. TargetWinGet failed\n"); 563 return MV_ERROR; 564 } 565/* 566 mvOsPrintf("ethWinOverlapDetect:\n 567 winNumIndex =%d baseHigh =0x%x baseLow=0x%x size=0x%x enable=0x%x\n", 568 winNumIndex, 569 addrDecWin.addrWin.baseHigh, 570 addrDecWin.addrWin.baseLow, 571 addrDecWin.addrWin.size, 572 addrDecWin.enable); 573*/ 574 if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin))) 575 { 576 return MV_TRUE; 577 } 578 } 579 return MV_FALSE; 580} 581 582/******************************************************************************* 583* mvEthAddrDecShow - Print the Etherent address decode map. 584* 585* DESCRIPTION: 586* This function print the Etherent address decode map. 587* 588* INPUT: 589* None. 590* 591* OUTPUT: 592* None. 593* 594* RETURN: 595* None. 596* 597*******************************************************************************/ 598void mvEthPortAddrDecShow(int port) 599{ 600 MV_ETH_DEC_WIN win; 601 int i; 602 603 mvOsOutput( "\n" ); 604 mvOsOutput( "ETH %d:\n", port ); 605 mvOsOutput( "----\n" ); 606 607 for( i = 0; i < ETH_MAX_DECODE_WIN; i++ ) 608 { 609 memset( &win, 0, sizeof(ETH_MAX_DECODE_WIN) ); 610 611 mvOsOutput( "win%d - ", i ); 612 613 if( mvEthWinGet(port, i, &win ) == MV_OK ) 614 { 615 if( win.enable ) 616 { 617 mvOsOutput( "%s base %08x, ", 618 mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); 619 mvOsOutput( "...." ); 620 mvSizePrint( win.addrWin.size ); 621 622 mvOsOutput( "\n" ); 623 } 624 else 625 mvOsOutput( "disable\n" ); 626 } 627 } 628 return; 629} 630 631void mvEthAddrDecShow(void) 632{ 633 int port; 634 635 for(port=0; port<mvCtrlEthMaxPortGet(); port++) 636 { 637 if (MV_FALSE == mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port)) continue; 638 639 mvEthPortAddrDecShow(port); 640 } 641} 642 643 644void mvEthInit(void) 645{ 646 MV_U32 port; 647 648 /* Power down all existing ports */ 649 for(port=0; port<mvCtrlEthMaxPortGet(); port++) 650 { 651 if (MV_FALSE == mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port)) 652 continue; 653 654 mvEthPortPowerUp(port); 655 mvEthWinInit(port); 656 } 657 mvEthHalInit(); 658} 659