1 /* 2 * HwInit.c 3 * 4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name Texas Instruments nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 35 36 /*******************************************************************************/ 37 /* */ 38 /* MODULE: HwInit.c */ 39 /* PURPOSE: HwInit module manages the init process of the TNETW, included */ 40 /* firmware download process. It shall perform Hard Reset the chip */ 41 /* if possible (this will require a Reset line to be connected to */ 42 /* the host); Start InterfaceCtrl; Download NVS and FW */ 43 /* */ 44 /* */ 45 /*******************************************************************************/ 46 47 #define __FILE_ID__ FILE_ID_105 48 #include "tidef.h" 49 #include "osApi.h" 50 #include "report.h" 51 #include "HwInit_api.h" 52 #include "FwEvent_api.h" 53 #include "TwIf.h" 54 #include "TWDriver.h" 55 #include "TWDriverInternal.h" 56 #include "eventMbox_api.h" 57 #include "CmdBld.h" 58 #include "CmdMBox_api.h" 59 #ifdef TI_RANDOM_DEFAULT_MAC 60 #include <linux/random.h> 61 #include <linux/jiffies.h> 62 #endif 63 64 /* remove the chipID check when WL6-PG1.0 becomes obsolete (temporary global variable!!) */ 65 TI_BOOL bChipIs1273Pg10 = TI_TRUE; 66 67 68 extern void TWD_FinalizeOnFailure (TI_HANDLE hTWD); 69 extern void cmdBld_FinalizeDownload (TI_HANDLE hCmdBld, TBootAttr *pBootAttr, FwStaticData_t *pFwInfo); 70 71 72 /************************************************************************ 73 * Defines 74 ************************************************************************/ 75 76 /* Download phase partition */ 77 #define PARTITION_DOWN_MEM_ADDR 0 78 #define PARTITION_DOWN_MEM_SIZE 0x177C0 79 #define PARTITION_DOWN_REG_ADDR REGISTERS_BASE 80 #define PARTITION_DOWN_REG_SIZE 0x8800 81 82 /* Working phase partition */ 83 #define PARTITION_WORK_MEM_ADDR1 0x40000 84 #define PARTITION_WORK_MEM_SIZE1 0x14FC0 85 #define PARTITION_WORK_MEM_ADDR2 REGISTERS_BASE 86 #define PARTITION_WORK_MEM_SIZE2 0xA000 87 #define PARTITION_WORK_MEM_ADDR3 0x3004F8 88 #define PARTITION_WORK_MEM_SIZE3 0x4 89 #define PARTITION_WORK_MEM_ADDR4 0x40404 90 91 /* DRPW setting partition */ 92 #define PARTITION_DRPW_MEM_ADDR 0x40000 93 #define PARTITION_DRPW_MEM_SIZE 0x14FC0 94 #define PARTITION_DRPW_REG_ADDR DRPW_BASE 95 #define PARTITION_DRPW_REG_SIZE 0x6000 96 97 /* Total range of bus addresses range */ 98 #define PARTITION_TOTAL_ADDR_RANGE 0x1FFC0 99 100 /* Maximal block size in a single SDIO transfer --> Firmware image load chunk size */ 101 #ifdef _VLCT_ 102 #define MAX_SDIO_BLOCK (4000) 103 #else 104 #define MAX_SDIO_BLOCK (500) 105 #endif 106 107 #define ACX_EEPROMLESS_IND_REG (SCR_PAD4) 108 #define USE_EEPROM (0) 109 #define SOFT_RESET_MAX_TIME (1000000) 110 #define SOFT_RESET_STALL_TIME (1000) 111 #define NVS_DATA_BUNDARY_ALIGNMENT (4) 112 113 #define MAX_HW_INIT_CONSECUTIVE_TXN 15 114 115 #define WORD_SIZE 4 116 #define WORD_ALIGNMENT_MASK 0x3 117 #define DEF_NVS_SIZE ((NVS_PRE_PARAMETERS_LENGTH) + (NVS_TX_TYPE_INDEX) + 4) 118 119 #define RADIO_SM_WAIT_LOOP 32 120 121 #define FREF_CLK_FREQ_MASK 0x7 122 #define FREF_CLK_TYPE_MASK BIT_3 123 #define FREF_CLK_POLARITY_MASK BIT_4 124 125 #define FREF_CLK_TYPE_BITS 0xfffffe7f 126 #define CLK_REQ_PRCM 0x100 127 128 #define FREF_CLK_POLARITY_BITS 0xfffff8ff 129 #define CLK_REQ_OUTN_SEL 0x700 130 131 /************************************************************************ 132 * Macros 133 ************************************************************************/ 134 135 #define SET_DEF_NVS(aNVS) aNVS[0]=0x01; aNVS[1]=0x6d; aNVS[2]=0x54; aNVS[3]=0x56; aNVS[4]=0x34; \ 136 aNVS[5]=0x12; aNVS[6]=0x28; aNVS[7]=0x01; aNVS[8]=0x71; aNVS[9]=0x54; \ 137 aNVS[10]=0x00; aNVS[11]=0x08; aNVS[12]=0x00; aNVS[13]=0x00; aNVS[14]=0x00; \ 138 aNVS[15]=0x00; aNVS[16]=0x00; aNVS[17]=0x00; aNVS[18]=0x00; aNVS[19]=0x00; \ 139 aNVS[20]=0x00; aNVS[21]=0x00; aNVS[22]=0x00; aNVS[23]=0x00; aNVS[24]=eNVS_NON_FILE;\ 140 aNVS[25]=0x00; aNVS[26]=0x00; aNVS[27]=0x00; 141 142 143 #define SET_PARTITION(pPartition,uAddr1,uMemSize1,uAddr2,uMemSize2,uAddr3,uMemSize3,uAddr4) \ 144 ((TPartition*)pPartition)[0].uMemAdrr = uAddr1; \ 145 ((TPartition*)pPartition)[0].uMemSize = uMemSize1; \ 146 ((TPartition*)pPartition)[1].uMemAdrr = uAddr2; \ 147 ((TPartition*)pPartition)[1].uMemSize = uMemSize2; \ 148 ((TPartition*)pPartition)[2].uMemAdrr = uAddr3; \ 149 ((TPartition*)pPartition)[2].uMemSize = uMemSize3; \ 150 ((TPartition*)pPartition)[3].uMemAdrr = uAddr4; 151 152 #define HW_INIT_PTXN_SET(pHwInit, pTxn) pTxn = (TTxnStruct*)&(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].tTxnStruct); 153 154 #define BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, uAddr, uVal, uSize, direction, fCB, hCB) \ 155 HW_INIT_PTXN_SET(pHwInit, pTxn) \ 156 TXN_PARAM_SET_DIRECTION(pTxn, direction); \ 157 pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData = (TI_UINT32)uVal; \ 158 BUILD_TTxnStruct(pTxn, uAddr, &(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData), uSize, fCB, hCB) 159 160 #define BUILD_HW_INIT_FW_STATIC_TXN(pHwInit, pTxn, uAddr, fCB, hCB) \ 161 HW_INIT_PTXN_SET(pHwInit, pTxn) \ 162 TXN_PARAM_SET_DIRECTION(pTxn, TXN_DIRECTION_READ); \ 163 BUILD_TTxnStruct(pTxn, uAddr, &(pHwInit->tFwStaticTxn.tFwStaticInfo), sizeof(FwStaticData_t), fCB, hCB) 164 165 #define BUILD_HW_INIT_FW_DL_TXN(pHwInit, pTxn, uAddr, uVal, uSize, direction, fCB, hCB) \ 166 HW_INIT_PTXN_SET(pHwInit, pTxn) \ 167 TXN_PARAM_SET_DIRECTION(pTxn, direction); \ 168 BUILD_TTxnStruct(pTxn, uAddr, uVal, uSize, fCB, hCB) 169 170 171 #define SET_DRP_PARTITION(pPartition)\ 172 SET_PARTITION(pPartition, PARTITION_DRPW_MEM_ADDR, PARTITION_DRPW_MEM_SIZE, PARTITION_DRPW_REG_ADDR, PARTITION_DRPW_REG_SIZE, 0, 0, 0) 173 174 #define SET_FW_LOAD_PARTITION(pPartition,uFwAddress)\ 175 SET_PARTITION(pPartition,uFwAddress,PARTITION_DOWN_MEM_SIZE, PARTITION_DOWN_REG_ADDR, PARTITION_DOWN_REG_SIZE,0,0,0) 176 177 #define SET_WORK_PARTITION(pPartition)\ 178 SET_PARTITION(pPartition,PARTITION_WORK_MEM_ADDR1, PARTITION_WORK_MEM_SIZE1, PARTITION_WORK_MEM_ADDR2, PARTITION_WORK_MEM_SIZE2, PARTITION_WORK_MEM_ADDR3, PARTITION_WORK_MEM_SIZE3, PARTITION_WORK_MEM_ADDR4) 179 180 /* Handle return status inside a state machine */ 181 #define EXCEPT(phwinit,status) \ 182 switch (status) { \ 183 case TI_OK: \ 184 case TXN_STATUS_OK: \ 185 case TXN_STATUS_COMPLETE: \ 186 break; \ 187 case TXN_STATUS_PENDING: \ 188 return TXN_STATUS_PENDING; \ 189 default: \ 190 TWD_FinalizeOnFailure (phwinit->hTWD); \ 191 return TXN_STATUS_ERROR; \ 192 } 193 194 195 /* Handle return status inside an init sequence state machine */ 196 #define EXCEPT_I(phwinit,status) \ 197 switch (status) { \ 198 case TI_OK: \ 199 case TXN_STATUS_COMPLETE: \ 200 break; \ 201 case TXN_STATUS_PENDING: \ 202 phwinit->uInitSeqStatus = status; \ 203 return TXN_STATUS_PENDING; \ 204 default: \ 205 TWD_FinalizeOnFailure (phwinit->hTWD); \ 206 return TXN_STATUS_ERROR; \ 207 } 208 209 210 /* Handle return status inside a load image state machine */ 211 #define EXCEPT_L(phwinit,status) \ 212 switch (status) { \ 213 case TXN_STATUS_OK: \ 214 case TXN_STATUS_COMPLETE: \ 215 break; \ 216 case TXN_STATUS_PENDING: \ 217 phwinit->DownloadStatus = status; \ 218 return TXN_STATUS_PENDING; \ 219 default: \ 220 phwinit->DownloadStatus = status; \ 221 TWD_FinalizeOnFailure (phwinit->hTWD); \ 222 return TXN_STATUS_ERROR; \ 223 } 224 225 226 /************************************************************************ 227 * Types 228 ************************************************************************/ 229 230 enum 231 { 232 REF_FREQ_19_2 = 0, 233 REF_FREQ_26_0 = 1, 234 REF_FREQ_38_4 = 2, 235 REF_FREQ_40_0 = 3, 236 REF_FREQ_33_6 = 4, 237 REF_FREQ_NUM = 5 238 }; 239 240 enum 241 { 242 LUT_PARAM_INTEGER_DIVIDER = 0, 243 LUT_PARAM_FRACTIONAL_DIVIDER = 1, 244 LUT_PARAM_ATTN_BB = 2, 245 LUT_PARAM_ALPHA_BB = 3, 246 LUT_PARAM_STOP_TIME_BB = 4, 247 LUT_PARAM_BB_PLL_LOOP_FILTER = 5, 248 LUT_PARAM_NUM = 6 249 }; 250 251 typedef struct 252 { 253 TTxnStruct tTxnStruct; 254 TI_UINT32 uData; 255 256 } THwInitTxn; 257 258 typedef struct 259 { 260 TTxnStruct tTxnStruct; 261 FwStaticData_t tFwStaticInfo; 262 263 } TFwStaticTxn; 264 265 266 /* The HW Init module object */ 267 typedef struct 268 { 269 /* Handles */ 270 TI_HANDLE hOs; 271 TI_HANDLE hReport; 272 TI_HANDLE hTWD; 273 TI_HANDLE hBusTxn; 274 TI_HANDLE hTwIf; 275 276 TI_HANDLE hFileInfo; /* holds parameters of FW Image Portion - for DW Download */ 277 TEndOfHwInitCb fInitHwCb; 278 279 /* Firmware image ptr */ 280 TI_UINT8 *pFwBuf; 281 /* Firmware image length */ 282 TI_UINT32 uFwLength; 283 TI_UINT32 uFwAddress; 284 TI_UINT32 bFwBufLast; 285 TI_UINT32 uFwLastAddr; 286 /* EEPROM image ptr */ 287 TI_UINT8 *pEEPROMBuf; 288 /* EEPROM image length */ 289 TI_UINT32 uEEPROMLen; 290 291 TI_UINT8 *pEEPROMCurPtr; 292 TI_UINT32 uEEPROMCurLen; 293 TBootAttr tBootAttr; 294 TI_HANDLE hHwCtrl; 295 ETxnStatus DownloadStatus; 296 /* Upper module callback for the init stage */ 297 fnotify_t fCb; 298 /* Upper module handle for the init stage */ 299 TI_HANDLE hCb; 300 /* Init stage */ 301 TI_UINT32 uInitStage; 302 /* Reset statge */ 303 TI_UINT32 uResetStage; 304 /* EEPROM burst stage */ 305 TI_UINT32 uEEPROMStage; 306 /* Init state machine temporary data */ 307 TI_UINT32 uInitData; 308 /* ELP command image */ 309 TI_UINT32 uElpCmd; 310 /* Chip ID */ 311 TI_UINT32 uChipId; 312 /* Boot state machine temporary data */ 313 TI_UINT32 uBootData; 314 TI_UINT32 uSelfClearTime; 315 TI_UINT8 uEEPROMBurstLen; 316 TI_UINT8 uEEPROMBurstLoop; 317 TI_UINT32 uEEPROMRegAddr; 318 TI_STATUS uEEPROMStatus; 319 TI_UINT32 uNVSStartAddr; 320 TI_UINT32 uNVSNumChar; 321 TI_UINT32 uNVSNumByte; 322 TI_STATUS uNVSStatus; 323 TI_UINT32 uScrPad6; 324 TI_UINT32 uRefFreq; 325 TI_UINT32 uInitSeqStage; 326 TI_STATUS uInitSeqStatus; 327 TI_UINT32 uLoadStage; 328 TI_UINT32 uBlockReadNum; 329 TI_UINT32 uBlockWriteNum; 330 TI_UINT32 uPartitionLimit; 331 TI_UINT32 uFinStage; 332 TI_UINT32 uFinData; 333 TI_UINT32 uFinLoop; 334 TI_UINT32 uRegStage; 335 TI_UINT32 uRegLoop; 336 TI_UINT32 uRegSeqStage; 337 TI_UINT32 uRegData; 338 339 /* Top register Read/Write SM temporary data*/ 340 TI_UINT32 uTopRegAddr; 341 TI_UINT32 uTopRegValue; 342 TI_UINT32 uTopRegMask; 343 TI_UINT32 uTopRegUpdateValue; 344 TI_UINT32 uTopStage; 345 346 TI_UINT8 auFwTmpBuf [WSPI_PAD_LEN_WRITE + MAX_SDIO_BLOCK]; 347 348 TFinalizeCb fFinalizeDownload; 349 TI_HANDLE hFinalizeDownload; 350 /* Size of the Fw image, retrieved from the image itself */ 351 TI_UINT32 uFwDataLen; 352 TI_UINT8 aDefaultNVS[DEF_NVS_SIZE]; 353 TI_UINT8 uTxnIndex; 354 THwInitTxn aHwInitTxn[MAX_HW_INIT_CONSECUTIVE_TXN]; 355 TFwStaticTxn tFwStaticTxn; 356 357 TI_UINT32 uSavedDataForWspiHdr; /* For saving the 4 bytes before the NVS data for WSPI case 358 where they are overrun by the WSPI BusDrv */ 359 TPartition aPartition[NUM_OF_PARTITION]; 360 } THwInit; 361 362 363 /************************************************************************ 364 * Local Functions Prototypes 365 ************************************************************************/ 366 static void hwInit_SetPartition (THwInit *pHwInit, 367 TPartition *pPartition); 368 static TI_STATUS hwInit_BootSm (TI_HANDLE hHwInit); 369 static TI_STATUS hwInit_ResetSm (TI_HANDLE hHwInit); 370 static TI_STATUS hwInit_EepromlessStartBurstSm (TI_HANDLE hHwInit); 371 static TI_STATUS hwInit_LoadFwImageSm (TI_HANDLE hHwInit); 372 static TI_STATUS hwInit_FinalizeDownloadSm (TI_HANDLE hHwInit); 373 static TI_STATUS hwInit_TopRegisterRead(TI_HANDLE hHwInit); 374 static TI_STATUS hwInit_InitTopRegisterRead(TI_HANDLE hHwInit, TI_UINT32 uAddress); 375 static TI_STATUS hwInit_TopRegisterWrite(TI_HANDLE hHwInit); 376 static TI_STATUS hwInit_InitTopRegisterWrite(TI_HANDLE hHwInit, TI_UINT32 uAddress, TI_UINT32 uValue); 377 378 379 380 381 /******************************************************************************* 382 * PUBLIC FUNCTIONS IMPLEMENTATION * 383 ********************************************************************************/ 384 385 386 /************************************************************************* 387 * hwInit_Create * 388 ************************************************************************** 389 * DESCRIPTION: This function initializes the HwInit module. 390 * 391 * INPUT: hOs - handle to Os Abstraction Layer 392 * 393 * RETURN: Handle to the allocated HwInit module 394 *************************************************************************/ 395 TI_HANDLE hwInit_Create (TI_HANDLE hOs) 396 { 397 THwInit *pHwInit; 398 399 /* Allocate HwInit module */ 400 pHwInit = os_memoryAlloc (hOs, sizeof(THwInit)); 401 402 if (pHwInit == NULL) 403 { 404 WLAN_OS_REPORT(("Error allocating the HwInit Module\n")); 405 return NULL; 406 } 407 408 /* Reset HwInit module */ 409 os_memoryZero (hOs, pHwInit, sizeof(THwInit)); 410 411 pHwInit->hOs = hOs; 412 413 return (TI_HANDLE)pHwInit; 414 } 415 416 417 /*************************************************************************** 418 * hwInit_Destroy * 419 **************************************************************************** 420 * DESCRIPTION: This function unload the HwInit module. 421 * 422 * INPUTS: hHwInit - the object 423 * 424 * OUTPUT: 425 * 426 * RETURNS: TI_OK - Unload succesfull 427 * TI_NOK - Unload unsuccesfull 428 ***************************************************************************/ 429 TI_STATUS hwInit_Destroy (TI_HANDLE hHwInit) 430 { 431 THwInit *pHwInit = (THwInit *)hHwInit; 432 433 /* Free HwInit Module */ 434 os_memoryFree (pHwInit->hOs, pHwInit, sizeof(THwInit)); 435 436 return TI_OK; 437 } 438 439 440 /*************************************************************************** 441 * hwInit_Init * 442 **************************************************************************** 443 * DESCRIPTION: This function configures the hwInit module 444 * 445 * RETURNS: TI_OK - Configuration successful 446 * TI_NOK - Configuration unsuccessful 447 ***************************************************************************/ 448 TI_STATUS hwInit_Init (TI_HANDLE hHwInit, 449 TI_HANDLE hReport, 450 TI_HANDLE hTWD, 451 TI_HANDLE hFinalizeDownload, 452 TFinalizeCb fFinalizeDownload, 453 TEndOfHwInitCb fInitHwCb) 454 { 455 THwInit *pHwInit = (THwInit *)hHwInit; 456 TTxnStruct* pTxn; 457 #ifdef TI_RANDOM_DEFAULT_MAC 458 u32 rand_mac; 459 #endif 460 461 /* Configure modules handles */ 462 pHwInit->hReport = hReport; 463 pHwInit->hTWD = hTWD; 464 pHwInit->hTwIf = ((TTwd *)hTWD)->hTwIf; 465 pHwInit->hOs = ((TTwd *)hTWD)->hOs; 466 pHwInit->fInitHwCb = fInitHwCb; 467 pHwInit->fFinalizeDownload = fFinalizeDownload; 468 pHwInit->hFinalizeDownload = hFinalizeDownload; 469 470 SET_DEF_NVS(pHwInit->aDefaultNVS) 471 #ifdef TI_RANDOM_DEFAULT_MAC 472 /* Create random MAC address: offset 3, 4 and 5 */ 473 srandom32((u32)jiffies); 474 rand_mac = random32(); 475 pHwInit->aDefaultNVS[3] = (u8)rand_mac; 476 pHwInit->aDefaultNVS[4] = (u8)(rand_mac >> 8); 477 pHwInit->aDefaultNVS[5] = (u8)(rand_mac >> 16); 478 #endif 479 480 for (pHwInit->uTxnIndex=0;pHwInit->uTxnIndex<MAX_HW_INIT_CONSECUTIVE_TXN;pHwInit->uTxnIndex++) 481 { 482 HW_INIT_PTXN_SET(pHwInit, pTxn) 483 /* Setting write as default transaction */ 484 TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) 485 } 486 487 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT, ".....HwInit configured successfully\n"); 488 489 return TI_OK; 490 } 491 492 493 TI_STATUS hwInit_SetNvsImage (TI_HANDLE hHwInit, TI_UINT8 *pbuf, TI_UINT32 length) 494 { 495 THwInit *pHwInit = (THwInit *)hHwInit; 496 497 pHwInit->pEEPROMBuf = pbuf; 498 pHwInit->uEEPROMLen = length; 499 500 return TI_OK; 501 } 502 503 504 TI_STATUS hwInit_SetFwImage (TI_HANDLE hHwInit, TFileInfo *pFileInfo) 505 { 506 THwInit *pHwInit = (THwInit *)hHwInit; 507 508 if ((hHwInit == NULL) || (pFileInfo == NULL)) 509 { 510 return TI_NOK; 511 } 512 513 pHwInit->pFwBuf = pFileInfo->pBuffer; 514 pHwInit->uFwLength = pFileInfo->uLength; 515 pHwInit->uFwAddress = pFileInfo->uAddress; 516 pHwInit->bFwBufLast = pFileInfo->bLast; 517 518 return TI_OK; 519 } 520 521 522 /** 523 * \fn hwInit_SetPartition 524 * \brief Set HW addresses partition 525 * 526 * Set the HW address ranges for download or working memory and registers access. 527 * Generate and configure the bus access address mapping table. 528 * The partition is split between register (fixed partition of 24KB size, exists in all modes), 529 * and memory (dynamically changed during init and gets constant value in run-time, 104KB size). 530 * The TwIf configures the memory mapping table on the device by issuing write transaction to 531 * table address (note that the TxnQ and bus driver see this as a regular transaction). 532 * 533 * \note In future versions, a specific bus may not support partitioning (as in wUART), 534 * In this case the HwInit module shall not call this function (will learn the bus 535 * configuration from the INI file). 536 * 537 * \param pHwInit - The module's object 538 * \param pPartition - all partition base address 539 * \return void 540 * \sa 541 */ 542 static void hwInit_SetPartition (THwInit *pHwInit, 543 TPartition *pPartition) 544 { 545 TRACE7(pHwInit->hReport, REPORT_SEVERITY_INFORMATION, "hwInit_SetPartition: uMemAddr1=0x%x, MemSize1=0x%x uMemAddr2=0x%x, MemSize2=0x%x, uMemAddr3=0x%x, MemSize3=0x%x, uMemAddr4=0x%x, MemSize4=0x%x\n",pPartition[0].uMemAdrr, pPartition[0].uMemSize,pPartition[1].uMemAdrr, pPartition[1].uMemSize,pPartition[2].uMemAdrr, pPartition[2].uMemSize,pPartition[3].uMemAdrr ); 546 547 /* Prepare partition Txn data and send to HW */ 548 twIf_SetPartition (pHwInit->hTwIf,pPartition); 549 } 550 551 552 /**************************************************************************** 553 * hwInit_Boot() 554 **************************************************************************** 555 * DESCRIPTION: Start HW init sequence which writes and reads some HW registers 556 * that are needed prior to FW download. 557 * 558 * INPUTS: None 559 * 560 * OUTPUT: None 561 * 562 * RETURNS: TI_OK or TI_NOK 563 ****************************************************************************/ 564 TI_STATUS hwInit_Boot (TI_HANDLE hHwInit) 565 { 566 THwInit *pHwInit = (THwInit *)hHwInit; 567 TTwd *pTWD = (TTwd *)pHwInit->hTWD; 568 TWlanParams *pWlanParams = &DB_WLAN(pTWD->hCmdBld); 569 TBootAttr tBootAttr; 570 571 tBootAttr.MacClock = pWlanParams->MacClock; 572 tBootAttr.ArmClock = pWlanParams->ArmClock; 573 574 /* 575 * Initialize the status of download to pending 576 * It will be set to TXN_STATUS_COMPLETE at the FinalizeDownload function 577 */ 578 pHwInit->DownloadStatus = TXN_STATUS_PENDING; 579 580 /* Call the boot sequence state machine */ 581 pHwInit->uInitStage = 0; 582 583 os_memoryCopy (pHwInit->hOs, &pHwInit->tBootAttr, &tBootAttr, sizeof(TBootAttr)); 584 585 hwInit_BootSm (hHwInit); 586 587 /* 588 * If it returns the status of the StartInstance only then we can here query for the download status 589 * and then return the status up to the TNETW_Driver. 590 * This return value will go back up to the TNETW Driver layer so that the init from OS will know 591 * if to wait for the InitComplte or not in case of TXN_STATUS_ERROR. 592 * This value will always be pending since the SPI is ASYNC 593 * and in SDIOa timer is set so it will be ASync also in anyway. 594 */ 595 return pHwInit->DownloadStatus; 596 } 597 598 599 /**************************************************************************** 600 * DESCRIPTION: Firmware boot state machine 601 * 602 * INPUTS: 603 * 604 * OUTPUT: None 605 * 606 * RETURNS: TI_OK 607 ****************************************************************************/ 608 static TI_STATUS hwInit_BootSm (TI_HANDLE hHwInit) 609 { 610 THwInit *pHwInit = (THwInit *)hHwInit; 611 TI_STATUS status = 0; 612 TTxnStruct *pTxn; 613 TI_UINT32 uData; 614 TTwd *pTWD = (TTwd *) pHwInit->hTWD; 615 IniFileGeneralParam *pGenParams = &DB_GEN(pTWD->hCmdBld); 616 TI_UINT32 clkVal = 0x3; 617 618 switch (pHwInit->uInitStage) 619 { 620 case 0: 621 pHwInit->uInitStage++; 622 pHwInit->uTxnIndex = 0; 623 624 /* Set the bus addresses partition to its "running" mode */ 625 SET_WORK_PARTITION(pHwInit->aPartition) 626 hwInit_SetPartition (pHwInit,pHwInit->aPartition); 627 628 #ifdef _VLCT_ 629 /* Set FW to test mode */ 630 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, SCR_PAD8, 0xBABABABE, 631 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 632 twIf_Transact(pHwInit->hTwIf, pTxn); 633 pHwInit->uTxnIndex++; 634 #endif 635 636 if (( 0 == (pGenParams->RefClk & FREF_CLK_FREQ_MASK)) || (2 == (pGenParams->RefClk & FREF_CLK_FREQ_MASK)) 637 || (4 == (pGenParams->RefClk & FREF_CLK_FREQ_MASK))) 638 {/* ref clk: 19.2/38.4/38.4-XTAL */ 639 clkVal = 0x3; 640 } 641 if ((1 == (pGenParams->RefClk & FREF_CLK_FREQ_MASK)) || (3 == (pGenParams->RefClk & FREF_CLK_FREQ_MASK))) 642 {/* ref clk: 26/52 */ 643 clkVal = 0x5; 644 } 645 646 WLAN_OS_REPORT(("CHIP VERSION... set 1273 chip top registers\n")); 647 648 /* set the reference clock freq' to be used (pll_selinpfref field) */ 649 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, PLL_PARAMETERS, clkVal, 650 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 651 twIf_Transact(pHwInit->hTwIf, pTxn); 652 653 pHwInit->uTxnIndex++; 654 655 /* read the PAUSE value to highest threshold */ 656 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, PLL_PARAMETERS, 0, 657 REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_BootSm, hHwInit) 658 status = twIf_Transact(pHwInit->hTwIf, pTxn); 659 660 EXCEPT (pHwInit, status) 661 662 case 1: 663 pHwInit->uInitStage ++; 664 /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */ 665 uData = pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData; 666 uData &= ~(0x3ff); 667 668 /* Now we can zero the index */ 669 pHwInit->uTxnIndex = 0; 670 671 /* set the the PAUSE value to highest threshold */ 672 uData |= WU_COUNTER_PAUSE_VAL; 673 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, WU_COUNTER_PAUSE, uData, 674 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 675 twIf_Transact(pHwInit->hTwIf, pTxn); 676 677 pHwInit->uTxnIndex++; 678 679 /* Continue the ELP wake up sequence */ 680 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL, 681 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 682 twIf_Transact(pHwInit->hTwIf, pTxn); 683 684 /* Wait 500uS */ 685 os_StalluSec (pHwInit->hOs, 500); 686 687 /* Set the bus addresses partition to DRPw registers region */ 688 SET_DRP_PARTITION(pHwInit->aPartition) 689 hwInit_SetPartition (pHwInit,pHwInit->aPartition); 690 691 pHwInit->uTxnIndex++; 692 693 /* Read-modify-write DRPW_SCRATCH_START register (see next state) to be used by DRPw FW. 694 The RTRIM value will be added by the FW before taking DRPw out of reset */ 695 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, DRPW_SCRATCH_START, 0, 696 REGISTER_SIZE, TXN_DIRECTION_READ,(TTxnDoneCb)hwInit_BootSm, hHwInit) 697 status = twIf_Transact(pHwInit->hTwIf, pTxn); 698 699 EXCEPT (pHwInit, status) 700 701 case 2: 702 pHwInit->uInitStage ++; 703 704 /* multiply fref value by 2, so that {0,1,2,3} values will become {0,2,4,6} */ 705 /* Then, move it 4 places to the right, to alter Fref relevant bits in register 0x2c */ 706 clkVal = pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData; 707 pHwInit->uTxnIndex = 0; /* Reset index only after getting the last read value! */ 708 clkVal |= (pGenParams->RefClk << 1) << 4; 709 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, DRPW_SCRATCH_START, clkVal, 710 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 711 twIf_Transact(pHwInit->hTwIf, pTxn); 712 713 pHwInit->uTxnIndex++; 714 715 716 /* Set the bus addresses partition back to its "running" mode */ 717 SET_WORK_PARTITION(pHwInit->aPartition) 718 hwInit_SetPartition (pHwInit,pHwInit->aPartition); 719 720 /* 721 * end of CHIP init seq. 722 */ 723 724 /* Disable interrupts */ 725 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_INTERRUPT_MASK, ACX_INTR_ALL, 726 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 727 twIf_Transact(pHwInit->hTwIf, pTxn); 728 729 pHwInit->uTxnIndex++; 730 731 /* Read the CHIP ID to get an indication that the bus is TI_OK */ 732 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, CHIP_ID, 0, 733 REGISTER_SIZE, TXN_DIRECTION_READ,(TTxnDoneCb)hwInit_BootSm, hHwInit) 734 status = twIf_Transact(pHwInit->hTwIf, pTxn); 735 736 EXCEPT (pHwInit, status) 737 738 case 3: 739 pHwInit->uInitStage ++; 740 741 /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */ 742 pHwInit->uChipId = pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData; 743 744 /* This is only sanity check that the HW exists, we can continue and fail on FwLoad */ 745 if (pHwInit->uChipId == CHIP_ID_1273_PG10) 746 { 747 WLAN_OS_REPORT(("Working on a 1273 PG 1.0 board.\n")); 748 bChipIs1273Pg10 = TI_TRUE; 749 } 750 else if (pHwInit->uChipId == CHIP_ID_1273_PG20) 751 { 752 WLAN_OS_REPORT(("Working on a 1273 PG 2.0 board.\n")); 753 bChipIs1273Pg10 = TI_FALSE; 754 } 755 else 756 { 757 WLAN_OS_REPORT (("Error!! Found unknown Chip Id = 0x%x\n", pHwInit->uChipId)); 758 bChipIs1273Pg10 = TI_FALSE; 759 760 /* 761 * NOTE: no exception because of forward compatibility 762 */ 763 } 764 765 /* 766 * Soft reset 767 */ 768 pHwInit->uResetStage = 0; 769 pHwInit->uSelfClearTime = 0; 770 pHwInit->uBootData = 0; 771 status = hwInit_ResetSm (pHwInit); 772 773 EXCEPT (pHwInit, status) 774 775 case 4: 776 pHwInit->uInitStage ++; 777 778 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "TNET SOFT-RESET\n"); 779 780 WLAN_OS_REPORT(("Starting to process NVS...\n")); 781 782 /* 783 * Start EEPROM/NVS burst 784 */ 785 786 if (pHwInit->pEEPROMBuf) 787 { 788 /* NVS file exists (EEPROM-less support) */ 789 pHwInit->uEEPROMCurLen = pHwInit->uEEPROMLen; 790 791 TRACE2(pHwInit->hReport, REPORT_SEVERITY_INIT , "EEPROM Image addr=0x%x, EEPROM Len=0x0x%x\n", pHwInit->pEEPROMBuf, pHwInit->uEEPROMLen); 792 WLAN_OS_REPORT (("NVS found, EEPROM Image addr=0x%x, EEPROM Len=0x0x%x\n", 793 pHwInit->pEEPROMBuf, pHwInit->uEEPROMLen)); 794 } 795 else 796 { 797 WLAN_OS_REPORT (("No Nvs, Setting default MAC address\n")); 798 pHwInit->uEEPROMCurLen = DEF_NVS_SIZE; 799 pHwInit->pEEPROMBuf = (TI_UINT8*)(&pHwInit->aDefaultNVS[0]); 800 WLAN_OS_REPORT (("pHwInit->uEEPROMCurLen: %x\n", pHwInit->uEEPROMCurLen)); 801 WLAN_OS_REPORT (("ERROR: If you are not calibating the device, you will soon get errors !!!\n")); 802 803 } 804 805 pHwInit->pEEPROMCurPtr = pHwInit->pEEPROMBuf; 806 pHwInit->uEEPROMStage = 0; 807 status = hwInit_EepromlessStartBurstSm (hHwInit); 808 809 EXCEPT (pHwInit, status) 810 811 case 5: 812 pHwInit->uInitStage ++; 813 pHwInit->uTxnIndex = 0; 814 815 if (pHwInit->pEEPROMBuf) 816 { 817 /* Signal FW that we are eeprom less */ 818 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG, 819 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 820 twIf_Transact(pHwInit->hTwIf, pTxn); 821 822 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "DRIVER NVS BURST-READ\n"); 823 } 824 else 825 { 826 /* 1273 - EEPROM is not support by FPGA yet */ 827 /* 828 * Start ACX EEPROM 829 */ 830 /*pHwInit->uRegister = START_EEPROM_MGR; 831 TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) 832 BUILD_TTxnStruct(pTxn, ACX_REG_EE_START, &pHwInit->uRegister, REGISTER_SIZE, 0, NULL, NULL) 833 twIf_Transact(pHwInit->hTwIf, pTxn);*/ 834 835 /* 836 * The stall is needed so the EEPROM NVS burst read will complete 837 */ 838 os_StalluSec (pHwInit->hOs, 40000); 839 840 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_EEPROMLESS_IND_REG, USE_EEPROM, 841 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 842 twIf_Transact(pHwInit->hTwIf, pTxn); 843 844 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "STARTING EEPROM NVS BURST-READ\n"); 845 } 846 847 pHwInit->uTxnIndex++; 848 849 /* Read Chip ID */ 850 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, CHIP_ID, 0, 851 REGISTER_SIZE, TXN_DIRECTION_READ,(TTxnDoneCb)hwInit_BootSm, hHwInit) 852 status = twIf_Transact(pHwInit->hTwIf, pTxn); 853 854 EXCEPT (pHwInit, status) 855 856 case 6: 857 pHwInit->uInitStage ++; 858 /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */ 859 pHwInit->uBootData = pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData; 860 /* Now we can zero the index */ 861 pHwInit->uTxnIndex = 0; 862 863 WLAN_OS_REPORT(("Chip ID is 0x%X.\n", pHwInit->uBootData)); 864 /* if the WLAN_EN is ON but MainClock is problamtic the chip-id will be zero*/ 865 if (pHwInit->uBootData == 0) 866 { 867 WLAN_OS_REPORT(("Cannot read ChipID stopping\n", pHwInit->uBootData)); 868 TWD_FinalizeOnFailure (pHwInit->hTWD); 869 return TXN_STATUS_ERROR; 870 } 871 872 873 874 /* Read Scr2 to verify that the HW is ready */ 875 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, SCR_PAD2, 0, 876 REGISTER_SIZE, TXN_DIRECTION_READ,(TTxnDoneCb)hwInit_BootSm, hHwInit) 877 status = twIf_Transact(pHwInit->hTwIf, pTxn); 878 EXCEPT (pHwInit, status) 879 880 case 7: 881 pHwInit->uInitStage ++; 882 /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */ 883 pHwInit->uBootData = pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData; 884 885 if (pHwInit->uBootData == 0xffffffff) 886 { 887 TRACE0(pHwInit->hReport, REPORT_SEVERITY_FATAL_ERROR , "Error in SCR_PAD2 register\n"); 888 EXCEPT (pHwInit, TXN_STATUS_ERROR) 889 } 890 891 /* Call the restart sequence */ 892 pHwInit->uInitSeqStage = 0; 893 pHwInit->uInitSeqStatus = TXN_STATUS_COMPLETE; 894 895 EXCEPT (pHwInit, status) 896 897 case 8: 898 pHwInit->uInitStage++; 899 if ((pGenParams->RefClk & FREF_CLK_TYPE_MASK) != 0x0) 900 { 901 status = hwInit_InitTopRegisterRead(hHwInit, 0x448); 902 EXCEPT (pHwInit, status) 903 } 904 905 case 9: 906 pHwInit->uInitStage++; 907 908 if ((pGenParams->RefClk & FREF_CLK_TYPE_MASK) != 0x0) 909 { 910 pHwInit->uTopRegValue &= FREF_CLK_TYPE_BITS; 911 pHwInit->uTopRegValue |= CLK_REQ_PRCM; 912 status = hwInit_InitTopRegisterWrite( hHwInit, 0x448, pHwInit->uTopRegValue); 913 EXCEPT (pHwInit, status) 914 } 915 916 case 10: 917 pHwInit->uInitStage++; 918 if ((pGenParams->RefClk & FREF_CLK_POLARITY_MASK) == 0x0) 919 { 920 status = hwInit_InitTopRegisterRead(hHwInit, 0xCB2); 921 EXCEPT (pHwInit, status) 922 } 923 924 case 11: 925 pHwInit->uInitStage++; 926 if ((pGenParams->RefClk & FREF_CLK_POLARITY_MASK) == 0x0) 927 { 928 pHwInit->uTopRegValue &= FREF_CLK_POLARITY_BITS; 929 pHwInit->uTopRegValue |= CLK_REQ_OUTN_SEL; 930 status = hwInit_InitTopRegisterWrite( hHwInit, 0xCB2, pHwInit->uTopRegValue); 931 EXCEPT (pHwInit, status) 932 } 933 934 case 12: 935 pHwInit->uInitStage = 0; 936 937 /* Set the Download Status to COMPLETE */ 938 pHwInit->DownloadStatus = TXN_STATUS_COMPLETE; 939 940 /* Call upper layer callback */ 941 if (pHwInit->fInitHwCb) 942 { 943 (*pHwInit->fInitHwCb) (pHwInit->hTWD); 944 } 945 946 return TI_OK; 947 } 948 949 return TI_OK; 950 } 951 952 953 TI_STATUS hwInit_LoadFw (TI_HANDLE hHwInit) 954 { 955 THwInit *pHwInit = (THwInit *)hHwInit; 956 TI_STATUS status; 957 958 /* check parameters */ 959 if (hHwInit == NULL) 960 { 961 EXCEPT (pHwInit, TXN_STATUS_ERROR) 962 } 963 964 if (pHwInit->pFwBuf) 965 { 966 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "CPU halt -> download code\n"); 967 968 /* Load firmware image */ 969 pHwInit->uLoadStage = 0; 970 status = hwInit_LoadFwImageSm (pHwInit); 971 972 switch (status) 973 { 974 case TI_OK: 975 case TXN_STATUS_OK: 976 case TXN_STATUS_COMPLETE: 977 WLAN_OS_REPORT (("Firmware successfully downloaded.\n")); 978 break; 979 case TXN_STATUS_PENDING: 980 WLAN_OS_REPORT (("Starting to download firmware...\n")); 981 break; 982 default: 983 TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Firmware download failed!\n"); 984 break; 985 } 986 987 EXCEPT (pHwInit, status); 988 } 989 else 990 { 991 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "Firmware not downloaded...\n"); 992 993 EXCEPT (pHwInit, TXN_STATUS_ERROR) 994 } 995 996 WLAN_OS_REPORT (("FW download OK...\n")); 997 return TI_OK; 998 } 999 1000 1001 /**************************************************************************** 1002 * hwInit_FinalizeDownloadSm() 1003 **************************************************************************** 1004 * DESCRIPTION: Run the Hardware firmware 1005 * Wait for Init Complete 1006 * Configure the Bus Access with Addresses available on the scratch pad register 1007 * Change the SDIO/SPI partitions to be able to see all the memory addresses 1008 * 1009 * INPUTS: None 1010 * 1011 * OUTPUT: None 1012 * 1013 * RETURNS: None 1014 ****************************************************************************/ 1015 static TI_STATUS hwInit_FinalizeDownloadSm (TI_HANDLE hHwInit) 1016 { 1017 THwInit *pHwInit = (THwInit *)hHwInit; 1018 TTwd *pTWD = (TTwd *)pHwInit->hTWD; 1019 TI_STATUS status = TI_OK; 1020 TI_UINT32 uIntVect; 1021 TTxnStruct* pTxn; 1022 1023 #ifdef _VLCT_ 1024 #define FIN_LOOP 10 1025 #else 1026 #define FIN_LOOP 20000 1027 #endif 1028 1029 while (TI_TRUE) 1030 { 1031 switch (pHwInit->uFinStage) 1032 { 1033 case 0: 1034 pHwInit->uFinStage = 1; 1035 pHwInit->uTxnIndex = 0; 1036 /* 1037 * Run the firmware (I) - Read current value from ECPU Control Reg. 1038 */ 1039 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_ECPU_CONTROL, 0, 1040 REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_FinalizeDownloadSm, hHwInit) 1041 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1042 1043 EXCEPT (pHwInit, status) 1044 1045 case 1: 1046 pHwInit->uFinStage ++; 1047 /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */ 1048 pHwInit->uFinData = pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData; 1049 /* Now we can zero the index */ 1050 pHwInit->uTxnIndex = 0; 1051 1052 /* 1053 * Run the firmware (II) - Take HW out of reset (write ECPU_CONTROL_HALT to ECPU Control Reg.) 1054 */ 1055 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_ECPU_CONTROL, (pHwInit->uFinData | ECPU_CONTROL_HALT), 1056 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1057 twIf_Transact(pHwInit->hTwIf, pTxn); 1058 1059 WLAN_OS_REPORT (("Firmware running.\n")); 1060 1061 /* 1062 * CHIP ID Debug 1063 */ 1064 1065 pHwInit->uTxnIndex++; 1066 1067 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, CHIP_ID, 0, 1068 REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_FinalizeDownloadSm, hHwInit) 1069 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1070 1071 EXCEPT (pHwInit, status) 1072 1073 case 2: 1074 pHwInit->uFinStage ++; 1075 pHwInit->uFinLoop = 0; 1076 1077 /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */ 1078 pHwInit->uFinData = pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData; 1079 1080 TRACE1(pHwInit->hReport, REPORT_SEVERITY_INIT , "CHIP ID IS %x\n", pHwInit->uFinData); 1081 1082 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "Wait init complete\n"); 1083 1084 case 3: 1085 pHwInit->uTxnIndex = 0; 1086 1087 /* 1088 * Wait for init complete 1089 */ 1090 if (pHwInit->uFinLoop < FIN_LOOP) 1091 { 1092 pHwInit->uFinStage = 4; 1093 1094 os_StalluSec (pHwInit->hOs, 50); 1095 1096 /* Read interrupt status register */ 1097 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_INTERRUPT_NO_CLEAR, 0, 1098 REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_FinalizeDownloadSm, hHwInit) 1099 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1100 1101 EXCEPT (pHwInit, status) 1102 } 1103 else 1104 { 1105 pHwInit->uFinStage = 5; 1106 } 1107 continue; 1108 1109 case 4: 1110 /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */ 1111 pHwInit->uFinData = pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData; 1112 /* Now we can zero the index */ 1113 pHwInit->uTxnIndex = 0; 1114 1115 if (pHwInit->uFinData == 0xffffffff) /* error */ 1116 { 1117 TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Error reading hardware complete init indication\n"); 1118 1119 pHwInit->DownloadStatus = TXN_STATUS_ERROR; 1120 EXCEPT (pHwInit, TXN_STATUS_ERROR) 1121 } 1122 1123 if (IS_MASK_ON (pHwInit->uFinData, ACX_INTR_INIT_COMPLETE)) 1124 { 1125 pHwInit->uFinStage = 5; 1126 1127 /* Interrupt ACK */ 1128 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_INTERRUPT_ACK, ACX_INTR_INIT_COMPLETE, 1129 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1130 twIf_Transact(pHwInit->hTwIf, pTxn); 1131 1132 break; 1133 } 1134 else 1135 { 1136 pHwInit->uFinStage = 3; 1137 pHwInit->uFinLoop ++; 1138 } 1139 continue; 1140 1141 case 5: 1142 pHwInit->uFinStage++; 1143 1144 if (pHwInit->uFinLoop >= FIN_LOOP) 1145 { 1146 TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Timeout waiting for the hardware to complete initialization\n"); 1147 1148 pHwInit->DownloadStatus = TXN_STATUS_ERROR; 1149 EXCEPT (pHwInit, TXN_STATUS_ERROR); 1150 } 1151 1152 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "Firmware init complete...\n"); 1153 1154 /* 1155 * There are valid addresses of the command and event mailbox 1156 * on the scratch pad registers 1157 */ 1158 /* Hardware config command mail box */ 1159 status = cmdMbox_ConfigHw (pTWD->hCmdMbox, 1160 (fnotify_t)hwInit_FinalizeDownloadSm, 1161 hHwInit); 1162 EXCEPT (pHwInit, status) 1163 1164 case 6: 1165 pHwInit->uFinStage++; 1166 1167 /* Hardware config event mail box */ 1168 status = eventMbox_InitMboxAddr (pTWD->hEventMbox, 1169 (fnotify_t)hwInit_FinalizeDownloadSm, 1170 hHwInit); 1171 EXCEPT (pHwInit, status); 1172 1173 case 7: 1174 pHwInit->uFinStage++; 1175 pHwInit->uTxnIndex = 0; 1176 1177 SET_WORK_PARTITION(pHwInit->aPartition) 1178 /* Set the bus addresses partition to its "running" mode */ 1179 SET_WORK_PARTITION(pHwInit->aPartition) 1180 hwInit_SetPartition (pHwInit,pHwInit->aPartition); 1181 1182 /* 1183 * In case of full asynchronous mode the firmware event must be ready 1184 * to receive event from the command mailbox, so enable FW interrupts. 1185 */ 1186 1187 /* Clear the FW interrupt sources needed for init phase */ 1188 uIntVect = fwEvent_GetInitMask (pTWD->hFwEvent); 1189 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_INTERRUPT_MASK, (~uIntVect), 1190 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1191 twIf_Transact(pHwInit->hTwIf, pTxn); 1192 pHwInit->uTxnIndex++; 1193 1194 /* Read static FW information from Cmd-Mbox */ 1195 BUILD_HW_INIT_FW_STATIC_TXN(pHwInit, pTxn, cmdMbox_GetMboxAddress (pTWD->hCmdMbox), 1196 (TTxnDoneCb)hwInit_FinalizeDownloadSm, hHwInit) 1197 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1198 1199 EXCEPT (pHwInit, status); 1200 continue; 1201 1202 case 8: 1203 1204 pHwInit->uFinStage = 0; 1205 1206 cmdBld_FinalizeDownload (pTWD->hCmdBld, &pHwInit->tBootAttr, &(pHwInit->tFwStaticTxn.tFwStaticInfo)); 1207 1208 /* Set the Download Status to COMPLETE */ 1209 pHwInit->DownloadStatus = TXN_STATUS_COMPLETE; 1210 1211 return TXN_STATUS_COMPLETE; 1212 1213 } /* End switch */ 1214 1215 } /* End while */ 1216 1217 } 1218 1219 1220 /**************************************************************************** 1221 * hwInit_ResetSm() 1222 **************************************************************************** 1223 * DESCRIPTION: Reset hardware state machine 1224 * 1225 * INPUTS: None 1226 * 1227 * OUTPUT: None 1228 * 1229 * RETURNS: TI_OK or TI_NOK 1230 ****************************************************************************/ 1231 static TI_STATUS hwInit_ResetSm (TI_HANDLE hHwInit) 1232 { 1233 THwInit *pHwInit = (THwInit *)hHwInit; 1234 TI_STATUS status = TI_OK; 1235 TTxnStruct* pTxn; 1236 1237 pHwInit->uTxnIndex = 0; 1238 1239 /* Disable Rx/Tx */ 1240 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, REG_ENABLE_TX_RX, 0x0, 1241 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1242 twIf_Transact(pHwInit->hTwIf, pTxn); 1243 1244 pHwInit->uTxnIndex++; 1245 1246 /* Disable auto calibration on start */ 1247 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, SPARE_A2, 0xFFFF, 1248 REGISTER_SIZE, TXN_DIRECTION_WRITE,(TTxnDoneCb)hwInit_BootSm, hHwInit) 1249 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1250 1251 return status; 1252 } 1253 1254 1255 /**************************************************************************** 1256 * hwInit_EepromlessStartBurstSm() 1257 **************************************************************************** 1258 * DESCRIPTION: prepare eepromless configuration before boot 1259 * 1260 * INPUTS: 1261 * 1262 * OUTPUT: 1263 * 1264 * RETURNS: 1265 ****************************************************************************/ 1266 static TI_STATUS hwInit_EepromlessStartBurstSm (TI_HANDLE hHwInit) 1267 { 1268 THwInit *pHwInit = (THwInit *)hHwInit; 1269 TI_STATUS status = TI_OK; 1270 TI_UINT8 *uAddr; 1271 TI_UINT32 uDeltaLength; 1272 TTxnStruct* pTxn; 1273 1274 pHwInit->uTxnIndex = 0; 1275 1276 while (TI_TRUE) 1277 { 1278 switch (pHwInit->uEEPROMStage) 1279 { 1280 /* 1281 * Stages 0, 1 handles the eeprom format parameters: 1282 * ------------------------------------------------ 1283 * Length - 8bit --> The length is counted in 32bit words 1284 * Address - 16bit 1285 * Data - (Length * 4) bytes 1286 * 1287 * Note: The nvs is in big endian format and we need to change it to little endian 1288 */ 1289 case 0: 1290 /* Check if address LSB = 1 --> Register address */ 1291 if ((pHwInit->uEEPROMRegAddr = pHwInit->pEEPROMCurPtr[1]) & 1) 1292 { 1293 /* Mask the register's address LSB before writing to it */ 1294 pHwInit->uEEPROMRegAddr &= 0xfe; 1295 /* Change the address's endian */ 1296 pHwInit->uEEPROMRegAddr |= (TI_UINT32)pHwInit->pEEPROMCurPtr[2] << 8; 1297 /* Length of burst data */ 1298 pHwInit->uEEPROMBurstLen = pHwInit->pEEPROMCurPtr[0]; 1299 pHwInit->pEEPROMCurPtr += 3; 1300 pHwInit->uEEPROMBurstLoop = 0; 1301 /* 1302 * We've finished reading the burst information. 1303 * Go to stage 1 in order to write it 1304 */ 1305 pHwInit->uEEPROMStage = 1; 1306 } 1307 /* If address LSB = 0 --> We're not in the burst section */ 1308 else 1309 { 1310 /* End of Burst transaction: we should see 7 zeroed bytes */ 1311 if (pHwInit->pEEPROMCurPtr[0] == 0) 1312 { 1313 pHwInit->pEEPROMCurPtr += 7; 1314 } 1315 pHwInit->uEEPROMCurLen -= (pHwInit->pEEPROMCurPtr - pHwInit->pEEPROMBuf + 1); 1316 pHwInit->uEEPROMCurLen = (pHwInit->uEEPROMCurLen + NVS_DATA_BUNDARY_ALIGNMENT - 1) & 0xfffffffc; 1317 /* End of Burst transaction, go to TLV section */ 1318 pHwInit->uEEPROMStage = 2; 1319 } 1320 continue; 1321 1322 case 1: 1323 if (pHwInit->uEEPROMBurstLoop < pHwInit->uEEPROMBurstLen) 1324 { 1325 /* Change the data's endian */ 1326 TI_UINT32 val = (pHwInit->pEEPROMCurPtr[0] | 1327 (pHwInit->pEEPROMCurPtr[1] << 8) | 1328 (pHwInit->pEEPROMCurPtr[2] << 16) | 1329 (pHwInit->pEEPROMCurPtr[3] << 24)); 1330 1331 TRACE2(pHwInit->hReport, REPORT_SEVERITY_INIT , "NVS::BurstRead: *(%08x) = %x\n", pHwInit->uEEPROMRegAddr, val); 1332 1333 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, (REGISTERS_BASE+pHwInit->uEEPROMRegAddr), val, 1334 REGISTER_SIZE, TXN_DIRECTION_WRITE, (TTxnDoneCb)hwInit_EepromlessStartBurstSm, hHwInit) 1335 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1336 1337 pHwInit->uEEPROMStatus = status; 1338 pHwInit->uEEPROMRegAddr += WORD_SIZE; 1339 pHwInit->pEEPROMCurPtr += WORD_SIZE; 1340 /* While not end of burst, we stay in stage 1 */ 1341 pHwInit->uEEPROMStage = 1; 1342 pHwInit->uEEPROMBurstLoop ++; 1343 1344 EXCEPT (pHwInit, status); 1345 } 1346 else 1347 { 1348 /* If end of burst return to stage 0 to read the next one */ 1349 pHwInit->uEEPROMStage = 0; 1350 } 1351 1352 continue; 1353 1354 case 2: 1355 1356 1357 pHwInit->uEEPROMStage = 3; 1358 1359 /* Set the bus addresses partition to its "running" mode */ 1360 SET_WORK_PARTITION(pHwInit->aPartition) 1361 hwInit_SetPartition (pHwInit,pHwInit->aPartition); 1362 continue; 1363 1364 case 3: 1365 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "Reached TLV section\n"); 1366 1367 /* Align the host address */ 1368 if (((TI_UINT32)pHwInit->pEEPROMCurPtr & WORD_ALIGNMENT_MASK) && (pHwInit->uEEPROMCurLen > 0) ) 1369 { 1370 uAddr = (TI_UINT8*)(((TI_UINT32)pHwInit->pEEPROMCurPtr & 0xFFFFFFFC)+WORD_SIZE); 1371 uDeltaLength = uAddr - pHwInit->pEEPROMCurPtr + 1; 1372 1373 pHwInit->pEEPROMCurPtr = uAddr; 1374 pHwInit->uEEPROMCurLen-= uDeltaLength; 1375 } 1376 1377 TRACE2(pHwInit->hReport, REPORT_SEVERITY_INIT , "NVS::WriteTLV: pEEPROMCurPtr= %x, Length=%d\n", pHwInit->pEEPROMCurPtr, pHwInit->uEEPROMCurLen); 1378 1379 if (pHwInit->uEEPROMCurLen) 1380 { 1381 /* Save the 4 bytes before the NVS data for WSPI case where they are overrun by the WSPI BusDrv */ 1382 pHwInit->uSavedDataForWspiHdr = *(TI_UINT32 *)(pHwInit->pEEPROMCurPtr - WSPI_PAD_LEN_WRITE); 1383 1384 /* Prepare the Txn structure for the NVS transaction to the CMD_MBOX */ 1385 HW_INIT_PTXN_SET(pHwInit, pTxn) 1386 TXN_PARAM_SET_DIRECTION(pTxn, TXN_DIRECTION_WRITE); 1387 BUILD_TTxnStruct(pTxn, CMD_MBOX_ADDRESS, pHwInit->pEEPROMCurPtr, pHwInit->uEEPROMCurLen, 1388 (TTxnDoneCb)hwInit_EepromlessStartBurstSm, hHwInit) 1389 1390 /* Transact the NVS data to the CMD_MBOX */ 1391 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1392 1393 pHwInit->uEEPROMCurLen = 0; 1394 pHwInit->uNVSStatus = status; 1395 1396 EXCEPT (pHwInit, status); 1397 } 1398 else 1399 { 1400 /* Restore the 4 bytes before the NVS data for WSPI case were they are overrun by the WSPI BusDrv */ 1401 *(TI_UINT32 *)(pHwInit->pEEPROMCurPtr - WSPI_PAD_LEN_WRITE) = pHwInit->uSavedDataForWspiHdr; 1402 1403 /* Call the upper level state machine */ 1404 if (pHwInit->uEEPROMStatus == TXN_STATUS_PENDING || 1405 pHwInit->uNVSStatus == TXN_STATUS_PENDING) 1406 { 1407 hwInit_BootSm (hHwInit); 1408 } 1409 1410 return TXN_STATUS_COMPLETE; 1411 } 1412 } /* End switch */ 1413 1414 } /* End while */ 1415 } 1416 1417 /**************************************************************************** 1418 * hwInit_LoadFwImageSm() 1419 **************************************************************************** 1420 * DESCRIPTION: Load image from the host and download into the hardware 1421 * 1422 * INPUTS: None 1423 * 1424 * OUTPUT: None 1425 * 1426 * RETURNS: TI_OK or TI_NOK 1427 ****************************************************************************/ 1428 1429 1430 #define ADDRESS_SIZE (sizeof(TI_INT32)) 1431 1432 static TI_STATUS hwInit_LoadFwImageSm (TI_HANDLE hHwInit) 1433 { 1434 THwInit *pHwInit = (THwInit *)hHwInit; 1435 TI_STATUS status = TI_OK; 1436 ETxnStatus TxnStatus; 1437 TI_UINT32 uMaxPartitionSize = PARTITION_DOWN_MEM_SIZE; 1438 TTxnStruct* pTxn; 1439 1440 pHwInit->uTxnIndex = 0; 1441 1442 while (TI_TRUE) 1443 { 1444 switch (pHwInit->uLoadStage) 1445 { 1446 case 0: 1447 pHwInit->uLoadStage = 1; 1448 1449 /* Check the Downloaded FW alignment */ 1450 if ((pHwInit->uFwLength % ADDRESS_SIZE) != 0) 1451 { 1452 TRACE1(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Length of downloaded Portion (%d) is not aligned\n",pHwInit->uFwLength); 1453 EXCEPT_L (pHwInit, TXN_STATUS_ERROR); 1454 } 1455 1456 TRACE2(pHwInit->hReport, REPORT_SEVERITY_INIT , "Image addr=0x%x, Len=0x%x\n", pHwInit->pFwBuf, pHwInit->uFwLength); 1457 1458 /* Set bus memory partition to current download area */ 1459 SET_FW_LOAD_PARTITION(pHwInit->aPartition,pHwInit->uFwAddress) 1460 hwInit_SetPartition (pHwInit,pHwInit->aPartition); 1461 status = TI_OK; 1462 break; 1463 1464 case 1: 1465 1466 pHwInit->uLoadStage = 2; 1467 /* if initial size is smaller than MAX_SDIO_BLOCK - go strait to stage 4 to write partial block */ 1468 if (pHwInit->uFwLength < MAX_SDIO_BLOCK) 1469 { 1470 pHwInit->uLoadStage = 4; 1471 } 1472 1473 pHwInit->uBlockReadNum = 0; 1474 pHwInit->uBlockWriteNum = 0; 1475 pHwInit->uPartitionLimit = pHwInit->uFwAddress + uMaxPartitionSize; 1476 1477 continue; 1478 1479 case 2: 1480 1481 /* Load firmware by blocks */ 1482 if (pHwInit->uBlockReadNum < (pHwInit->uFwLength / MAX_SDIO_BLOCK)) 1483 { 1484 pHwInit->uLoadStage = 3; 1485 1486 /* Change partition */ 1487 /* The +2 is for the last block and the block remainder */ 1488 if ( ((pHwInit->uBlockWriteNum + 2) * MAX_SDIO_BLOCK + pHwInit->uFwAddress) > pHwInit->uPartitionLimit) 1489 { 1490 pHwInit->uFwAddress += pHwInit->uBlockWriteNum * MAX_SDIO_BLOCK; 1491 /* update uPartitionLimit */ 1492 pHwInit->uPartitionLimit = pHwInit->uFwAddress + uMaxPartitionSize; 1493 /* Set bus memory partition to current download area */ 1494 SET_FW_LOAD_PARTITION(pHwInit->aPartition,pHwInit->uFwAddress) 1495 hwInit_SetPartition (pHwInit,pHwInit->aPartition); 1496 TxnStatus = TXN_STATUS_OK; 1497 pHwInit->uBlockWriteNum = 0; 1498 TRACE1(pHwInit->hReport, REPORT_SEVERITY_INIT , "Change partition to address offset = 0x%x\n", pHwInit->uFwAddress + pHwInit->uBlockWriteNum * MAX_SDIO_BLOCK); 1499 EXCEPT_L (pHwInit, TxnStatus); 1500 } 1501 } 1502 else 1503 { 1504 pHwInit->uLoadStage = 4; 1505 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "Load firmware with Portions\n"); 1506 } 1507 continue; 1508 1509 case 3: 1510 pHwInit->uLoadStage = 2; 1511 1512 pHwInit->uTxnIndex = 0; 1513 1514 /* Copy image block to temporary buffer */ 1515 os_memoryCopy (pHwInit->hOs, 1516 (void *)&pHwInit->auFwTmpBuf[WSPI_PAD_LEN_WRITE], 1517 (void *)(pHwInit->pFwBuf + pHwInit->uBlockReadNum * MAX_SDIO_BLOCK), 1518 MAX_SDIO_BLOCK); 1519 1520 /* Load the block. Save WSPI_PAD_LEN_WRITE space for WSPI bus command */ 1521 BUILD_HW_INIT_FW_DL_TXN(pHwInit, pTxn, (pHwInit->uFwAddress + pHwInit->uBlockWriteNum * MAX_SDIO_BLOCK), 1522 (pHwInit->auFwTmpBuf + WSPI_PAD_LEN_WRITE), MAX_SDIO_BLOCK, TXN_DIRECTION_WRITE, 1523 (TTxnDoneCb)hwInit_LoadFwImageSm, hHwInit) 1524 TxnStatus = twIf_Transact(pHwInit->hTwIf, pTxn); 1525 1526 /* Log ERROR if the transaction returned ERROR */ 1527 if (TxnStatus == TXN_STATUS_ERROR) 1528 { 1529 TRACE1(pHwInit->hReport, REPORT_SEVERITY_ERROR , "hwInit_LoadFwImageSm: twIf_Transact retruned status=0x%x\n", TxnStatus); 1530 } 1531 1532 pHwInit->uBlockWriteNum ++; 1533 pHwInit->uBlockReadNum ++; 1534 EXCEPT_L (pHwInit, TxnStatus); 1535 continue; 1536 1537 case 4: 1538 pHwInit->uLoadStage = 5; 1539 1540 pHwInit->uTxnIndex = 0; 1541 1542 /* If No Last block to write */ 1543 if ( pHwInit->uFwLength % MAX_SDIO_BLOCK == 0 ) 1544 { 1545 continue; 1546 } 1547 1548 1549 /* Copy the last image block */ 1550 os_memoryCopy (pHwInit->hOs, 1551 (void *)&pHwInit->auFwTmpBuf[WSPI_PAD_LEN_WRITE], 1552 (void *)(pHwInit->pFwBuf + pHwInit->uBlockReadNum * MAX_SDIO_BLOCK), 1553 pHwInit->uFwLength % MAX_SDIO_BLOCK); 1554 1555 /* Load the last block */ 1556 BUILD_HW_INIT_FW_DL_TXN(pHwInit, pTxn, (pHwInit->uFwAddress + pHwInit->uBlockWriteNum * MAX_SDIO_BLOCK), 1557 (pHwInit->auFwTmpBuf + WSPI_PAD_LEN_WRITE), (pHwInit->uFwLength % MAX_SDIO_BLOCK), TXN_DIRECTION_WRITE, 1558 (TTxnDoneCb)hwInit_LoadFwImageSm, hHwInit) 1559 TxnStatus = twIf_Transact(pHwInit->hTwIf, pTxn); 1560 1561 if (TxnStatus == TXN_STATUS_ERROR) 1562 { 1563 TRACE1(pHwInit->hReport, REPORT_SEVERITY_ERROR , "hwInit_LoadFwImageSm: last block retruned status=0x%x\n", TxnStatus); 1564 } 1565 1566 EXCEPT_L (pHwInit, TxnStatus); 1567 continue; 1568 1569 case 5: 1570 pHwInit->uLoadStage = 0; 1571 1572 /*If end of overall FW Download Process: Finalize download (run firmware)*/ 1573 if ( pHwInit->bFwBufLast == TI_TRUE ) 1574 { 1575 /* The download has completed */ 1576 WLAN_OS_REPORT (("Finished downloading firmware.\n")); 1577 status = hwInit_FinalizeDownloadSm (hHwInit); 1578 } 1579 /* Have to wait to more FW Portions */ 1580 else 1581 { 1582 /* Call the upper layer callback */ 1583 if ( pHwInit->fFinalizeDownload != NULL ) 1584 { 1585 (pHwInit->fFinalizeDownload) (pHwInit->hFinalizeDownload); 1586 } 1587 1588 status = TI_OK; 1589 } 1590 return status; 1591 1592 } /* End switch */ 1593 1594 } /* End while */ 1595 1596 } /* hwInit_LoadFwImageSm() */ 1597 1598 #define READ_TOP_REG_LOOP 32 1599 1600 /**************************************************************************** 1601 * hwInit_ReadRadioParamsSm () 1602 **************************************************************************** 1603 * DESCRIPTION: hwInit_ReadRadioParamsSm 1604 * INPUTS: None 1605 * 1606 * OUTPUT: None 1607 * 1608 * RETURNS: TI_OK or TI_NOK 1609 ****************************************************************************/ 1610 TI_STATUS hwInit_ReadRadioParamsSm (TI_HANDLE hHwInit) 1611 { 1612 THwInit *pHwInit = (THwInit *)hHwInit; 1613 TTwd *pTWD = (TTwd *)pHwInit->hTWD; 1614 IniFileGeneralParam *pGenParams = &DB_GEN(pTWD->hCmdBld); 1615 TI_UINT32 val= 0, value; 1616 TI_UINT32 add = FUNC7_SEL; 1617 TI_UINT32 retAddress; 1618 TTxnStruct *pTxn; 1619 TI_STATUS status = 0; 1620 1621 1622 while (TI_TRUE) 1623 { 1624 switch (pHwInit->uRegStage) 1625 { 1626 case 0: 1627 pHwInit->uRegStage = 1; 1628 pHwInit->uTxnIndex++; 1629 1630 /* 1631 * Select GPIO over Debug for BT_FUNC7 clear bit 17 1632 */ 1633 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, GPIO_SELECT, 0, 1634 REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_ReadRadioParamsSm, hHwInit) 1635 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1636 1637 EXCEPT (pHwInit, status) 1638 1639 case 1: 1640 pHwInit->uRegStage ++; 1641 pHwInit->uRegLoop = 0; 1642 1643 /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */ 1644 val = (pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData); 1645 val &= 0xFFFDFFFF; /*clear bit 17*/ 1646 /* Now we can zero the index */ 1647 pHwInit->uTxnIndex = 0; 1648 1649 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, GPIO_SELECT, val, 1650 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1651 1652 twIf_Transact(pHwInit->hTwIf, pTxn); 1653 1654 pHwInit->uTxnIndex++; 1655 1656 pHwInit->uRegData = FUNC7_SEL; 1657 1658 continue; 1659 1660 case 2: 1661 1662 pHwInit->uRegStage ++; 1663 add = pHwInit->uRegData; 1664 1665 1666 /* Select GPIO over Debug for BT_FUNC7*/ 1667 retAddress = (TI_UINT32)(add / 2); 1668 val = (retAddress & 0x7FF); 1669 val |= BIT_16 | BIT_17; 1670 1671 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, val, 1672 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1673 twIf_Transact(pHwInit->hTwIf, pTxn); 1674 1675 pHwInit->uTxnIndex++; 1676 1677 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x2, 1678 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1679 twIf_Transact(pHwInit->hTwIf, pTxn); 1680 1681 continue; 1682 1683 case 3: 1684 1685 pHwInit->uRegStage ++; 1686 pHwInit->uTxnIndex++; 1687 1688 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_DATA_RD, 0, 1689 REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_ReadRadioParamsSm, hHwInit) 1690 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1691 1692 EXCEPT (pHwInit, status) 1693 1694 1695 case 4: 1696 1697 val = (pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData); 1698 1699 pHwInit->uTxnIndex = 0; 1700 if (val & BIT_18) 1701 { 1702 if ((val & BIT_16) && (!(val & BIT_17))) 1703 { 1704 pHwInit->uRegStage ++; 1705 pHwInit->uRegLoop = 0; 1706 1707 } 1708 else 1709 { 1710 TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "can't writing bt_func7_sel\n"); 1711 1712 TWD_FinalizeFEMRead(pHwInit->hTWD); 1713 1714 return TI_NOK; 1715 } 1716 } 1717 else 1718 { 1719 if (pHwInit->uRegLoop < READ_TOP_REG_LOOP) 1720 { 1721 pHwInit->uRegStage = 3; 1722 pHwInit->uRegLoop++; 1723 } 1724 else 1725 { 1726 1727 TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Timeout waiting for writing bt_func7_sel\n"); 1728 1729 TWD_FinalizeFEMRead(pHwInit->hTWD); 1730 1731 return TI_NOK; 1732 1733 } 1734 } 1735 1736 continue; 1737 1738 case 5: 1739 pHwInit->uRegStage ++; 1740 add = pHwInit->uRegData; 1741 retAddress = (TI_UINT32)(add / 2); 1742 value = (retAddress & 0x7FF); 1743 value |= BIT_16 | BIT_17; 1744 1745 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, value, 1746 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1747 twIf_Transact(pHwInit->hTwIf, pTxn); 1748 1749 pHwInit->uTxnIndex++; 1750 1751 if (pHwInit->uRegSeqStage == 0) 1752 { 1753 if (pHwInit->uRegData == FUNC7_SEL) 1754 value = (val | 0x600); 1755 else 1756 value = (val | 0x1000); 1757 } 1758 else 1759 { 1760 if (pHwInit->uRegData == FUNC7_SEL) 1761 value = (val & 0xF8FF); 1762 else 1763 value = (val & 0xCFFF); 1764 1765 } 1766 1767 value &= 0xFFFF; 1768 1769 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_WDATA, value, 1770 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1771 twIf_Transact(pHwInit->hTwIf, pTxn); 1772 1773 pHwInit->uTxnIndex++; 1774 1775 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x1, 1776 REGISTER_SIZE, TXN_DIRECTION_WRITE, (TTxnDoneCb)hwInit_ReadRadioParamsSm, hHwInit) 1777 1778 /*BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, INDIRECT_REG5, 0x1, 1779 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) */ 1780 1781 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1782 1783 pHwInit->uTxnIndex++; 1784 1785 if ((pHwInit->uRegData == FUNC7_SEL)&& (pHwInit->uRegSeqStage == 0)) 1786 { 1787 pHwInit->uRegData = FUNC7_PULL; 1788 pHwInit->uRegStage = 2; 1789 } 1790 else 1791 { 1792 if ((pHwInit->uRegData == FUNC7_PULL)&& (pHwInit->uRegSeqStage == 1)) 1793 { 1794 pHwInit->uRegData = FUNC7_SEL; 1795 pHwInit->uRegStage = 2; 1796 } 1797 } 1798 1799 EXCEPT (pHwInit, status) 1800 continue; 1801 1802 case 6: 1803 1804 if (pHwInit->uRegSeqStage == 1) 1805 { 1806 pHwInit->uRegStage = 8; 1807 } 1808 else 1809 { 1810 pHwInit->uRegStage ++; 1811 pHwInit->uTxnIndex++; 1812 1813 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, GPIO_OE_RADIO, 0, 1814 REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_ReadRadioParamsSm, hHwInit) 1815 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1816 EXCEPT (pHwInit, status) 1817 } 1818 continue; 1819 1820 case 7: 1821 pHwInit->uRegStage ++; 1822 1823 /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */ 1824 val = (pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData); 1825 val |= 0x00020000; 1826 1827 pHwInit->uTxnIndex = 0; 1828 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, GPIO_OE_RADIO, val, 1829 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1830 twIf_Transact(pHwInit->hTwIf, pTxn); 1831 1832 pHwInit->uTxnIndex++; 1833 1834 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, GPIO_IN, 0, 1835 REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_ReadRadioParamsSm, hHwInit) 1836 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1837 1838 EXCEPT (pHwInit, status) 1839 1840 1841 case 8: 1842 if (pHwInit->uRegSeqStage == 0) 1843 { 1844 val = (pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData); 1845 val &= 0x20000; 1846 if(val) 1847 { 1848 pGenParams->TXBiPFEMManufacturer = FEM_TRIQUINT_TYPE_E; 1849 } 1850 else 1851 { 1852 pGenParams->TXBiPFEMManufacturer = FEM_RFMD_TYPE_E; 1853 } 1854 WLAN_OS_REPORT (("FEM Type %d \n",pGenParams->TXBiPFEMManufacturer)); 1855 pHwInit->uTxnIndex = 0; 1856 pHwInit->uRegSeqStage = 1; 1857 pHwInit->uRegStage = 2; 1858 pHwInit->uRegData = FUNC7_PULL; 1859 continue; 1860 } 1861 else 1862 { 1863 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INFORMATION, "hwInit_ReadRadioParamsSm Ended Successfully\n"); 1864 1865 TWD_FinalizeFEMRead(pHwInit->hTWD); 1866 1867 return TI_OK; 1868 1869 } 1870 1871 } /* End switch */ 1872 1873 } /* End while */ 1874 1875 } 1876 1877 1878 /**************************************************************************** 1879 * hwInit_ReadRadioParams() 1880 **************************************************************************** 1881 * DESCRIPTION: hwInit_ReadRadioParamsSm 1882 * initalizie hwInit_ReadRadioParamsSm parmaeters 1883 ****************************************************************************/ 1884 1885 TI_STATUS hwInit_ReadRadioParams (TI_HANDLE hHwInit) 1886 { 1887 THwInit *pHwInit = (THwInit *)hHwInit; 1888 1889 pHwInit->uRegStage = 0; 1890 pHwInit->uRegSeqStage = 0; 1891 1892 return hwInit_ReadRadioParamsSm (hHwInit); 1893 } 1894 1895 /**************************************************************************** 1896 * hwInit_InitPoalrity() 1897 **************************************************************************** 1898 * DESCRIPTION: hwInit_ReadRadioParamsSm 1899 * initalizie hwInit_ReadRadioParamsSm parmaeters 1900 ****************************************************************************/ 1901 1902 TI_STATUS hwInit_InitPolarity(TI_HANDLE hHwInit) 1903 { 1904 THwInit *pHwInit = (THwInit *)hHwInit; 1905 1906 pHwInit->uRegStage = 0; 1907 pHwInit->uRegSeqStage = 0; 1908 1909 return hwInit_WriteIRQPolarity (hHwInit); 1910 } 1911 1912 1913 1914 /**************************************************************************** 1915 * hwInit_WriteIRQPolarity () 1916 **************************************************************************** 1917 * DESCRIPTION: hwInit_WriteIRQPolarity 1918 * INPUTS: None 1919 * 1920 * OUTPUT: None 1921 * 1922 * RETURNS: TI_OK or TI_NOK 1923 ****************************************************************************/ 1924 TI_STATUS hwInit_WriteIRQPolarity(TI_HANDLE hHwInit) 1925 { 1926 THwInit *pHwInit = (THwInit *)hHwInit; 1927 TI_UINT32 Address,value; 1928 TI_UINT32 val=0; 1929 TTxnStruct *pTxn; 1930 TI_STATUS status = 0; 1931 1932 /* To write to a top level address from the WLAN IP: 1933 Write the top level address to the OCP_POR_CTR register. 1934 Divide the top address by 2, and add 0x30000 to the result for example for top address 0xC00, write to the OCP_POR_CTR 0x30600 1935 Write the data to the OCP_POR_WDATA register 1936 Write 0x1 to the OCP_CMD register. 1937 1938 To read from a top level address: 1939 Write the top level address to the OCP_POR_CTR register. 1940 Divide the top address by 2, and add 0x30000 to the result for example for top address 0xC00, write to the OCP_POR_CTR 0x30600 1941 Write 0x2 to the OCP_CMD register. 1942 Poll bit [18] of OCP_DATA_RD for data valid indication 1943 Check bits 17:16 of OCP_DATA_RD: 1944 00 no response 1945 01 data valid / accept 1946 10 request failed 1947 11 response error 1948 Read the data from the OCP_DATA_RD register 1949 */ 1950 1951 while (TI_TRUE) 1952 { 1953 switch (pHwInit->uRegStage) 1954 { 1955 case 0: 1956 1957 pHwInit->uRegStage = 1; 1958 pHwInit->uTxnIndex++; 1959 pHwInit->uRegLoop = 0; 1960 1961 /* first read the IRQ Polarity register*/ 1962 Address = (TI_UINT32)(FN0_CCCR_REG_32 / 2); 1963 val = (Address & 0x7FF); 1964 val |= BIT_16 | BIT_17; 1965 1966 /* Write IRQ Polarity address register to OCP_POR_CTR*/ 1967 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, val, 1968 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1969 1970 twIf_Transact(pHwInit->hTwIf, pTxn); 1971 1972 pHwInit->uTxnIndex++; 1973 1974 /* Write read (2)command to the OCP_CMD register. */ 1975 1976 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x2, 1977 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 1978 twIf_Transact(pHwInit->hTwIf, pTxn); 1979 1980 continue; 1981 1982 case 1: 1983 1984 pHwInit->uRegStage ++; 1985 pHwInit->uTxnIndex++; 1986 1987 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_DATA_RD, 0, 1988 REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_WriteIRQPolarity, hHwInit) 1989 status = twIf_Transact(pHwInit->hTwIf, pTxn); 1990 1991 EXCEPT (pHwInit, status) 1992 1993 1994 case 2: 1995 /* get the value from IRQ Polarity register*/ 1996 val = pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData; 1997 1998 pHwInit->uTxnIndex = 0; 1999 2000 /*Poll bit 18 of OCP_DATA_RD for data valid indication*/ 2001 if (val & BIT_18) 2002 { 2003 if ((val & BIT_16) && (!(val & BIT_17))) 2004 { 2005 pHwInit->uRegStage ++; 2006 pHwInit->uRegLoop = 0; 2007 2008 } 2009 else 2010 { 2011 TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "can't writing bt_func7_sel\n"); 2012 TWD_FinalizePolarityRead(pHwInit->hTWD); 2013 2014 return TI_NOK; 2015 } 2016 } 2017 else 2018 { 2019 if (pHwInit->uRegLoop < READ_TOP_REG_LOOP) 2020 { 2021 pHwInit->uRegStage = 1; 2022 pHwInit->uRegLoop++; 2023 } 2024 else 2025 { 2026 2027 TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Timeout waiting for writing bt_func7_sel\n"); 2028 TWD_FinalizePolarityRead(pHwInit->hTWD); 2029 2030 return TI_NOK; 2031 2032 } 2033 } 2034 2035 continue; 2036 2037 2038 case 3: 2039 /* second, write new value of IRQ polarity due to complation flag 1 - active low, 0 - active high*/ 2040 pHwInit->uRegStage ++; 2041 Address = (TI_UINT32)(FN0_CCCR_REG_32 / 2); 2042 value = (Address & 0x7FF); 2043 value |= BIT_16 | BIT_17; 2044 2045 /* Write IRQ Polarity address register to OCP_POR_CTR*/ 2046 2047 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, value, 2048 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 2049 2050 twIf_Transact(pHwInit->hTwIf, pTxn); 2051 2052 pHwInit->uTxnIndex++; 2053 2054 #ifdef USE_IRQ_ACTIVE_HIGH 2055 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INFORMATION , "Hwinit IRQ polarity active high\n"); 2056 val |= 0x0<<1; 2057 2058 #else 2059 TRACE0(pHwInit->hReport, REPORT_SEVERITY_INFORMATION , "Hwinit IRQ polarity active low\n"); 2060 val |= 0x01<<1; 2061 #endif 2062 2063 /* Write the new IRQ polarity value to the OCP_POR_WDATA register */ 2064 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_WDATA, val, 2065 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 2066 twIf_Transact(pHwInit->hTwIf, pTxn); 2067 2068 pHwInit->uTxnIndex++; 2069 2070 /* Write write (1)command to the OCP_CMD register. */ 2071 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x1, 2072 REGISTER_SIZE, TXN_DIRECTION_WRITE, (TTxnDoneCb)hwInit_WriteIRQPolarity, hHwInit) 2073 status = twIf_Transact(pHwInit->hTwIf, pTxn); 2074 2075 pHwInit->uTxnIndex++; 2076 2077 EXCEPT (pHwInit, status) 2078 continue; 2079 2080 case 4: 2081 2082 TWD_FinalizePolarityRead(pHwInit->hTWD); 2083 2084 return TI_OK; 2085 2086 2087 } /* End switch */ 2088 2089 } /* End while */ 2090 2091 } 2092 2093 2094 /**************************************************************************** 2095 * hwInit_InitTopRegisterWrite() 2096 **************************************************************************** 2097 * DESCRIPTION: hwInit_InitTopRegisterWrite 2098 * initalizie hwInit_TopRegisterWrite SM parmaeters 2099 ****************************************************************************/ 2100 2101 TI_STATUS hwInit_InitTopRegisterWrite(TI_HANDLE hHwInit, TI_UINT32 uAddress, TI_UINT32 uValue) 2102 { 2103 THwInit *pHwInit = (THwInit *)hHwInit; 2104 2105 pHwInit->uTopStage = 0; 2106 uAddress = (TI_UINT32)(uAddress / 2); 2107 uAddress = (uAddress & 0x7FF); 2108 uAddress|= BIT_16 | BIT_17; 2109 pHwInit->uTopRegAddr = uAddress; 2110 pHwInit->uTopRegValue = uValue & 0xffff; 2111 return hwInit_TopRegisterWrite (hHwInit); 2112 } 2113 2114 2115 /**************************************************************************** 2116 * hwInit_WriteTopRegister () 2117 **************************************************************************** 2118 * DESCRIPTION: Generic function that writes to the top registers area 2119 * INPUTS: None 2120 * 2121 * OUTPUT: None 2122 * 2123 * RETURNS: TI_OK or TI_NOK 2124 ****************************************************************************/ 2125 TI_STATUS hwInit_TopRegisterWrite(TI_HANDLE hHwInit) 2126 { 2127 /* To write to a top level address from the WLAN IP: 2128 Write the top level address to the OCP_POR_CTR register. 2129 Divide the top address by 2, and add 0x30000 to the result for example for top address 0xC00, write to the OCP_POR_CTR 0x30600 2130 Write the data to the OCP_POR_WDATA register 2131 Write 0x1 to the OCP_CMD register. 2132 */ 2133 THwInit *pHwInit = (THwInit *)hHwInit; 2134 TTxnStruct *pTxn; 2135 TI_STATUS status = 0; 2136 2137 while (TI_TRUE) 2138 { 2139 switch (pHwInit->uTopStage) 2140 { 2141 case 0: 2142 pHwInit->uTopStage = 1; 2143 2144 pHwInit->uTxnIndex++; 2145 /* Write the address to OCP_POR_CTR*/ 2146 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, pHwInit->uTopRegAddr, 2147 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 2148 twIf_Transact(pHwInit->hTwIf, pTxn); 2149 2150 pHwInit->uTxnIndex++; 2151 /* Write the new value to the OCP_POR_WDATA register */ 2152 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_WDATA, pHwInit->uTopRegValue, 2153 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 2154 twIf_Transact(pHwInit->hTwIf, pTxn); 2155 2156 pHwInit->uTxnIndex++; 2157 /* Write write (1)command to the OCP_CMD register. */ 2158 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x1, 2159 REGISTER_SIZE, TXN_DIRECTION_WRITE, (TTxnDoneCb)hwInit_TopRegisterWrite, hHwInit) 2160 status = twIf_Transact(pHwInit->hTwIf, pTxn); 2161 2162 pHwInit->uTxnIndex++; 2163 2164 EXCEPT (pHwInit, status) 2165 continue; 2166 2167 case 1: 2168 2169 pHwInit->uTxnIndex = 0; 2170 2171 return TI_OK; 2172 2173 } /* End switch */ 2174 2175 } /* End while */ 2176 2177 } 2178 2179 2180 /**************************************************************************** 2181 * hwInit_InitTopRegisterWrite() 2182 **************************************************************************** 2183 * DESCRIPTION: hwInit_InitTopRegisterWrite 2184 * initalizie hwInit_TopRegisterWrite SM parmaeters 2185 ****************************************************************************/ 2186 2187 TI_STATUS hwInit_InitTopRegisterRead(TI_HANDLE hHwInit, TI_UINT32 uAddress) 2188 { 2189 THwInit *pHwInit = (THwInit *)hHwInit; 2190 2191 pHwInit->uTopStage = 0; 2192 uAddress = (TI_UINT32)(uAddress / 2); 2193 uAddress = (uAddress & 0x7FF); 2194 uAddress|= BIT_16 | BIT_17; 2195 pHwInit->uTopRegAddr = uAddress; 2196 return hwInit_TopRegisterRead (hHwInit); 2197 } 2198 2199 2200 /**************************************************************************** 2201 * hwInit_WriteTopRegister () 2202 **************************************************************************** 2203 * DESCRIPTION: Generic function that writes to the top registers area 2204 * INPUTS: None 2205 * 2206 * OUTPUT: None 2207 * 2208 * RETURNS: TI_OK or TI_NOK 2209 ****************************************************************************/ 2210 TI_STATUS hwInit_TopRegisterRead(TI_HANDLE hHwInit) 2211 { 2212 /* 2213 To read from a top level address: 2214 Write the top level address to the OCP_POR_CTR register. 2215 Divide the top address by 2, and add 0x30000 to the result for example for top address 0xC00, write to the OCP_POR_CTR 0x30600 2216 Write 0x2 to the OCP_CMD register. 2217 Poll bit [18] of OCP_DATA_RD for data valid indication 2218 Check bits 17:16 of OCP_DATA_RD: 2219 00 no response 2220 01 data valid / accept 2221 10 request failed 2222 11 response error 2223 Read the data from the OCP_DATA_RD register 2224 */ 2225 2226 THwInit *pHwInit = (THwInit *)hHwInit; 2227 TTxnStruct *pTxn; 2228 TI_STATUS status = 0; 2229 2230 while (TI_TRUE) 2231 { 2232 switch (pHwInit->uTopStage) 2233 { 2234 case 0: 2235 pHwInit->uTopStage = 1; 2236 pHwInit->uTxnIndex++; 2237 pHwInit->uRegLoop = 0; 2238 2239 /* Write the address to OCP_POR_CTR*/ 2240 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, pHwInit->uTopRegAddr, 2241 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 2242 twIf_Transact(pHwInit->hTwIf, pTxn); 2243 2244 pHwInit->uTxnIndex++; 2245 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x2, 2246 REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL) 2247 twIf_Transact(pHwInit->hTwIf, pTxn); 2248 2249 continue; 2250 2251 case 1: 2252 pHwInit->uTopStage ++; 2253 pHwInit->uTxnIndex++; 2254 2255 BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_DATA_RD, 0, 2256 REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_TopRegisterRead, hHwInit) 2257 status = twIf_Transact(pHwInit->hTwIf, pTxn); 2258 2259 EXCEPT (pHwInit, status) 2260 2261 case 2: 2262 /* get the value from IRQ Polarity register*/ 2263 pHwInit->uTopRegValue = pHwInit->aHwInitTxn[pHwInit->uTxnIndex].uData; 2264 2265 pHwInit->uTxnIndex = 0; 2266 2267 /*Poll bit 18 of OCP_DATA_RD for data valid indication*/ 2268 if (pHwInit->uTopRegValue & BIT_18) 2269 { 2270 if ((pHwInit->uTopRegValue & BIT_16) && (!(pHwInit->uTopRegValue & BIT_17))) 2271 { 2272 pHwInit->uTopRegValue &= 0xffff; 2273 pHwInit->uTxnIndex = 0; 2274 pHwInit->uRegLoop = 0; 2275 return TI_OK; 2276 } 2277 else 2278 { 2279 TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "can't writing bt_func7_sel\n"); 2280 return TI_NOK; 2281 } 2282 } 2283 else 2284 { 2285 if (pHwInit->uRegLoop < READ_TOP_REG_LOOP) 2286 { 2287 pHwInit->uTopStage = 1; 2288 pHwInit->uRegLoop++; 2289 } 2290 else 2291 { 2292 TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Timeout waiting for writing bt_func7_sel\n"); 2293 return TI_NOK; 2294 } 2295 } 2296 2297 continue; 2298 2299 } /* End switch */ 2300 2301 } /* End while */ 2302 2303 } 2304