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/mvSysTs.h" 67 68 69typedef struct _mvTsuDecWin 70{ 71 MV_TARGET target; 72 MV_ADDR_WIN addrWin; /* An address window*/ 73 MV_BOOL enable; /* Address decode window is enabled/disabled */ 74 75}MV_TSU_DEC_WIN; 76 77 78MV_TARGET tsuAddrDecPrioTap[] = 79{ 80#if defined(MV_INCLUDE_PEX) 81 PEX0_MEM, 82#endif 83#if defined(MV_INCLUDE_PCI) 84 PCI0_MEM, 85#endif 86#if defined(MV_INCLUDE_SDRAM_CS0) 87 SDRAM_CS0, 88#endif 89#if defined(MV_INCLUDE_SDRAM_CS1) 90 SDRAM_CS1, 91#endif 92#if defined(MV_INCLUDE_SDRAM_CS2) 93 SDRAM_CS2, 94#endif 95#if defined(MV_INCLUDE_SDRAM_CS3) 96 SDRAM_CS3, 97#endif 98#if defined(MV_INCLUDE_DEVICE_CS0) 99 DEVICE_CS0, 100#endif 101#if defined(MV_INCLUDE_DEVICE_CS1) 102 DEVICE_CS1, 103#endif 104#if defined(MV_INCLUDE_DEVICE_CS2) 105 DEVICE_CS2, 106#endif 107#if defined(MV_INCLUDE_DEVICE_CS3) 108 DEVICE_CS3, 109#endif 110#if defined(MV_INCLUDE_PEX) 111 PEX0_IO, 112#endif 113#if defined(MV_INCLUDE_PCI) 114 PCI0_IO, 115#endif 116 TBL_TERM 117}; 118 119static MV_STATUS tsuWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin); 120static MV_STATUS mvTsuWinSet(MV_U32 winNum, MV_TSU_DEC_WIN *pAddrDecWin); 121static MV_STATUS mvTsuWinGet(MV_U32 winNum, MV_TSU_DEC_WIN *pAddrDecWin); 122MV_STATUS mvTsuWinEnable(MV_U32 winNum,MV_BOOL enable); 123 124/******************************************************************************* 125* mvTsuWinInit 126* 127* DESCRIPTION: 128* Initialize the TSU unit address decode windows. 129* 130* INPUT: 131* None. 132* OUTPUT: 133* None. 134* RETURN: 135* MV_OK - on success, 136* 137*******************************************************************************/ 138MV_STATUS mvTsuWinInit(void) 139{ 140 MV_U32 winNum, status, winPrioIndex=0; 141 MV_TSU_DEC_WIN tsuWin; 142 MV_CPU_DEC_WIN cpuAddrDecWin; 143 144 /* First disable all address decode windows */ 145 for(winNum = 0; winNum < TSU_MAX_DECODE_WIN; winNum++) 146 { 147 MV_REG_BIT_RESET(MV_TSU_WIN_CTRL_REG(winNum), 148 TSU_WIN_CTRL_EN_MASK); 149 } 150 151 /* Go through all windows in user table until table terminator */ 152 for(winNum = 0; ((tsuAddrDecPrioTap[winPrioIndex] != TBL_TERM) && 153 (winNum < TSU_MAX_DECODE_WIN));) 154 { 155 /* first get attributes from CPU If */ 156 status = mvCpuIfTargetWinGet(tsuAddrDecPrioTap[winPrioIndex], 157 &cpuAddrDecWin); 158 159 if(MV_NO_SUCH == status) 160 { 161 winPrioIndex++; 162 continue; 163 } 164 if(MV_OK != status) 165 { 166 mvOsPrintf("mvTsuWinInit: ERR. mvCpuIfTargetWinGet failed\n"); 167 return MV_ERROR; 168 } 169 170 if (cpuAddrDecWin.enable == MV_TRUE) 171 { 172 tsuWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; 173 tsuWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; 174 tsuWin.addrWin.size = cpuAddrDecWin.addrWin.size; 175 tsuWin.enable = MV_TRUE; 176 tsuWin.target = tsuAddrDecPrioTap[winPrioIndex]; 177 178 if(MV_OK != mvTsuWinSet(winNum, &tsuWin)) 179 { 180 mvOsPrintf("mvTsuWinInit: ERR. mvTsuWinSet failed winNum=%d\n", 181 winNum); 182 return MV_ERROR; 183 } 184 winNum++; 185 } 186 winPrioIndex ++; 187 } 188 189 return MV_OK; 190} 191 192 193/******************************************************************************* 194* mvTsuWinSet 195* 196* DESCRIPTION: 197* This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0) 198* address window, also known as address decode window. 199* After setting this target window, the TSU will be able to access the 200* target within the address window. 201* 202* INPUT: 203* winNum - TSU to target address decode window number. 204* pAddrDecWin - TSU target window data structure. 205* 206* OUTPUT: 207* None. 208* 209* RETURN: 210* MV_ERROR - if address window overlapps with other address decode 211* windows. 212* MV_BAD_PARAM - if base address is invalid parameter or target is 213* unknown. 214* 215*******************************************************************************/ 216MV_STATUS mvTsuWinSet(MV_U32 winNum, MV_TSU_DEC_WIN *pAddrDecWin) 217{ 218 MV_TARGET_ATTRIB targetAttribs; 219 MV_DEC_REGS decRegs; 220 221 /* Parameter checking */ 222 if(winNum >= TSU_MAX_DECODE_WIN) 223 { 224 mvOsPrintf("mvTsuWinSet: ERR. Invalid win num %d\n",winNum); 225 return MV_BAD_PARAM; 226 } 227 228 /* Check if the requested window overlapps with current windows */ 229 if(MV_TRUE == tsuWinOverlapDetect(winNum, &pAddrDecWin->addrWin)) 230 { 231 mvOsPrintf("mvTsuWinSet: ERR. Window %d overlap\n", winNum); 232 return MV_ERROR; 233 } 234 235 /* check if address is aligned to the size */ 236 if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow,pAddrDecWin->addrWin.size)) 237 { 238 mvOsPrintf("mvTsuWinSet: Error setting TSU window %d to target " 239 "%s.\nAddress 0x%08x is unaligned to size 0x%x.\n", 240 winNum, mvCtrlTargetNameGet(pAddrDecWin->target), 241 pAddrDecWin->addrWin.baseLow, 242 pAddrDecWin->addrWin.size); 243 return MV_ERROR; 244 } 245 246 decRegs.baseReg = MV_REG_READ(MV_TSU_WIN_BASE_REG(winNum)); 247 decRegs.sizeReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNum)); 248 249 if(MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) 250 { 251 mvOsPrintf("mvTsuWinSet: mvCtrlAddrDecToReg Failed\n"); 252 return MV_ERROR; 253 } 254 255 mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); 256 257 /* set attributes */ 258 decRegs.sizeReg &= ~TSU_WIN_CTRL_ATTR_MASK; 259 decRegs.sizeReg |= targetAttribs.attrib << TSU_WIN_CTRL_ATTR_OFFS; 260 /* set target ID */ 261 decRegs.sizeReg &= ~TSU_WIN_CTRL_TARGET_MASK; 262 decRegs.sizeReg |= targetAttribs.targetId << TSU_WIN_CTRL_TARGET_OFFS; 263 264 /* for the safe side we disable the window before writing the new */ 265 /* values */ 266 mvTsuWinEnable(winNum, MV_FALSE); 267 MV_REG_WRITE(MV_TSU_WIN_CTRL_REG(winNum),decRegs.sizeReg); 268 269 /* Write to address decode Size Register */ 270 MV_REG_WRITE(MV_TSU_WIN_BASE_REG(winNum), decRegs.baseReg); 271 272 /* Enable address decode target window */ 273 if(pAddrDecWin->enable == MV_TRUE) 274 { 275 mvTsuWinEnable(winNum,MV_TRUE); 276 } 277 278 return MV_OK; 279} 280 281 282/******************************************************************************* 283* mvTsuWinGet 284* 285* DESCRIPTION: 286* Get TSU peripheral target address window. 287* 288* INPUT: 289* winNum - TSU to target address decode window number. 290* 291* OUTPUT: 292* pAddrDecWin - TSU target window data structure. 293* 294* RETURN: 295* MV_ERROR if register parameters are invalid. 296* 297*******************************************************************************/ 298MV_STATUS mvTsuWinGet(MV_U32 winNum, MV_TSU_DEC_WIN *pAddrDecWin) 299{ 300 MV_DEC_REGS decRegs; 301 MV_TARGET_ATTRIB targetAttrib; 302 303 /* Parameter checking */ 304 if(winNum >= TSU_MAX_DECODE_WIN) 305 { 306 mvOsPrintf("mvTsuWinGet: ERR. Invalid winNum %d\n", winNum); 307 return MV_NOT_SUPPORTED; 308 } 309 310 decRegs.baseReg = MV_REG_READ(MV_TSU_WIN_BASE_REG(winNum)); 311 decRegs.sizeReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNum)); 312 313 if(MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) 314 { 315 mvOsPrintf("mvTsuWinGet: mvCtrlRegToAddrDec Failed \n"); 316 return MV_ERROR; 317 } 318 319 /* attrib and targetId */ 320 targetAttrib.attrib = 321 (decRegs.sizeReg & TSU_WIN_CTRL_ATTR_MASK) >> TSU_WIN_CTRL_ATTR_OFFS; 322 targetAttrib.targetId = 323 (decRegs.sizeReg & TSU_WIN_CTRL_TARGET_MASK) >> TSU_WIN_CTRL_TARGET_OFFS; 324 325 pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); 326 327 /* Check if window is enabled */ 328 if((MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNum)) & TSU_WIN_CTRL_EN_MASK)) 329 { 330 pAddrDecWin->enable = MV_TRUE; 331 } 332 else 333 { 334 pAddrDecWin->enable = MV_FALSE; 335 } 336 337 return MV_OK; 338} 339 340 341/******************************************************************************* 342* mvTsuWinEnable 343* 344* DESCRIPTION: 345* This function enable/disable a TSU to target address window. 346* According to parameter 'enable' the routine will enable the 347* window, thus enabling TSU accesses (before enabling the window it is 348* tested for overlapping). Otherwise, the window will be disabled. 349* 350* INPUT: 351* winNum - TSU to target address decode window number. 352* enable - Enable / disable parameter. 353* 354* OUTPUT: 355* N/A 356* 357* RETURN: 358* MV_ERROR if decode window number was wrong or enabled window overlapps. 359* 360*******************************************************************************/ 361MV_STATUS mvTsuWinEnable(MV_U32 winNum,MV_BOOL enable) 362{ 363 MV_TSU_DEC_WIN addrDecWin; 364 365 /* Parameter checking */ 366 if(winNum >= TSU_MAX_DECODE_WIN) 367 { 368 mvOsPrintf("mvTsuWinEnable: ERR. Invalid winNum%d\n",winNum); 369 return MV_ERROR; 370 } 371 372 if(enable == MV_TRUE) 373 { 374 /* First check for overlap with other enabled windows */ 375 /* Get current window. */ 376 if(MV_OK != mvTsuWinGet(winNum,&addrDecWin)) 377 { 378 mvOsPrintf("mvTsuWinEnable: ERR. targetWinGet fail\n"); 379 return MV_ERROR; 380 } 381 /* Check for overlapping. */ 382 if(MV_FALSE == tsuWinOverlapDetect(winNum,&(addrDecWin.addrWin))) 383 { 384 /* No Overlap. Enable address decode target window */ 385 MV_REG_BIT_SET(MV_TSU_WIN_CTRL_REG(winNum), 386 TSU_WIN_CTRL_EN_MASK); 387 } 388 else 389 { 390 /* Overlap detected */ 391 mvOsPrintf("mvTsuWinEnable: ERR. Overlap detected\n"); 392 return MV_ERROR; 393 } 394 } 395 else 396 { 397 /* Disable address decode target window */ 398 MV_REG_BIT_RESET(MV_TSU_WIN_CTRL_REG(winNum), 399 TSU_WIN_CTRL_EN_MASK); 400 } 401 return MV_OK; 402} 403 404/******************************************************************************* 405* mvTsuWinTargetGet 406* 407* DESCRIPTION: 408* Get Window number associated with target 409* 410* INPUT: 411* target - Target ID to get the window number for. 412* OUTPUT: 413* 414* RETURN: 415* window number or 0xFFFFFFFF on error. 416* 417*******************************************************************************/ 418MV_U32 mvTsuWinTargetGet(MV_TARGET target) 419{ 420 MV_TSU_DEC_WIN decWin; 421 MV_U32 winNum; 422 423 /* Check parameters */ 424 if(target >= MAX_TARGETS) 425 { 426 mvOsPrintf("mvTsuWinTargetGet: target %d is Illigal\n", target); 427 return 0xffffffff; 428 } 429 430 for(winNum = 0; winNum < TSU_MAX_DECODE_WIN; winNum++) 431 { 432 if(mvTsuWinGet(winNum,&decWin) != MV_OK) 433 { 434 mvOsPrintf("mvTsuWinGet: window returned error\n"); 435 return 0xffffffff; 436 } 437 438 if (decWin.enable == MV_TRUE) 439 { 440 if(decWin.target == target) 441 { 442 return winNum; 443 } 444 } 445 } 446 return 0xFFFFFFFF; 447} 448 449 450/******************************************************************************* 451* tsuWinOverlapDetect 452* 453* DESCRIPTION: 454* Detect TSU address windows overlapping 455* An unpredicted behaviur is expected in case TSU address decode 456* windows overlapps. 457* This function detects TSU address decode windows overlapping of a 458* specified window. The function does not check the window itself for 459* overlapping. The function also skipps disabled address decode windows. 460* 461* INPUT: 462* winNum - address decode window number. 463* pAddrDecWin - An address decode window struct. 464* 465* OUTPUT: 466* None. 467* 468* RETURN: 469* MV_TRUE if the given address window overlap current address 470* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data 471* from registers. 472* 473*******************************************************************************/ 474static MV_STATUS tsuWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) 475{ 476 MV_U32 ctrlReg; 477 MV_U32 winNumIndex; 478 MV_TSU_DEC_WIN addrDecWin; 479 480 for(winNumIndex = 0; winNumIndex < TSU_MAX_DECODE_WIN; winNumIndex++) 481 { 482 /* Do not check window itself */ 483 if(winNumIndex == winNum) 484 { 485 continue; 486 } 487 488 /* Do not check disabled windows */ 489 ctrlReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNumIndex)); 490 if((ctrlReg & TSU_WIN_CTRL_EN_MASK) == 0) 491 { 492 continue; 493 } 494 495 /* Get window parameters */ 496 if (MV_OK != mvTsuWinGet(winNumIndex, &addrDecWin)) 497 { 498 mvOsPrintf("tsuWinOverlapDetect: ERR. mvTsuWinGet failed\n"); 499 return MV_ERROR; 500 } 501 502 if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin))) 503 { 504 return MV_TRUE; 505 } 506 } 507 return MV_FALSE; 508} 509 510 511/******************************************************************************* 512* mvTsuAddrDecShow 513* 514* DESCRIPTION: 515* Print the TSU address decode map. 516* 517* INPUT: 518* None. 519* 520* OUTPUT: 521* None. 522* 523* RETURN: 524* None. 525* 526*******************************************************************************/ 527void mvTsuAddrDecShow(void) 528{ 529 MV_TSU_DEC_WIN win; 530 int i; 531 532 if (MV_FALSE == mvCtrlPwrClckGet(TS_UNIT_ID, 0)) 533 return; 534 535 mvOsOutput( "\n" ); 536 mvOsOutput( "TSU:\n"); 537 mvOsOutput( "----\n" ); 538 539 for(i = 0; i < TSU_MAX_DECODE_WIN; i++) 540 { 541 memset(&win, 0, sizeof(TSU_MAX_DECODE_WIN)); 542 mvOsOutput( "win%d - ", i ); 543 544 if(mvTsuWinGet(i, &win ) == MV_OK ) 545 { 546 if(win.enable == MV_TRUE) 547 { 548 mvOsOutput("%s base %08x, ", 549 mvCtrlTargetNameGet(win.target), 550 win.addrWin.baseLow); 551 mvOsOutput( "...." ); 552 mvSizePrint(win.addrWin.size ); 553 mvOsOutput( "\n" ); 554 } 555 else 556 { 557 mvOsOutput( "disable\n" ); 558 } 559 } 560 } 561 return; 562} 563 564 565/******************************************************************************* 566* mvTsuInit 567* 568* DESCRIPTION: 569* Initialize the TSU unit, and get unit out of reset. 570* 571* INPUT: 572* coreClock - The core clock at which the TSU should operate. 573* mode - The mode on configure the unit into (serial/parallel). 574* memHandle - Memory handle used for memory allocations. 575* OUTPUT: 576* None. 577* RETURN: 578* MV_OK - on success, 579* 580*******************************************************************************/ 581MV_STATUS mvTsuInit(MV_TSU_CORE_CLOCK coreClock, MV_TSU_PORTS_MODE mode, 582 void *osHandle) 583{ 584 MV_STATUS status; 585 586 status = mvTsuWinInit(); 587 if(status == MV_OK) 588 status = mvTsuHalInit(coreClock,mode,osHandle); 589 590 return status; 591} 592