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