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 *************************************************************************/
hwInit_Create(TI_HANDLE hOs)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 ***************************************************************************/
hwInit_Destroy(TI_HANDLE hHwInit)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 ***************************************************************************/
hwInit_Init(TI_HANDLE hHwInit,TI_HANDLE hReport,TI_HANDLE hTWD,TI_HANDLE hFinalizeDownload,TFinalizeCb fFinalizeDownload,TEndOfHwInitCb fInitHwCb)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
hwInit_SetNvsImage(TI_HANDLE hHwInit,TI_UINT8 * pbuf,TI_UINT32 length)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
hwInit_SetFwImage(TI_HANDLE hHwInit,TFileInfo * pFileInfo)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 */
hwInit_SetPartition(THwInit * pHwInit,TPartition * pPartition)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 ****************************************************************************/
hwInit_Boot(TI_HANDLE hHwInit)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 ****************************************************************************/
hwInit_BootSm(TI_HANDLE hHwInit)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
hwInit_LoadFw(TI_HANDLE hHwInit)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 ****************************************************************************/
hwInit_FinalizeDownloadSm(TI_HANDLE hHwInit)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 ****************************************************************************/
hwInit_ResetSm(TI_HANDLE hHwInit)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 ****************************************************************************/
hwInit_EepromlessStartBurstSm(TI_HANDLE hHwInit)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
hwInit_LoadFwImageSm(TI_HANDLE hHwInit)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 ****************************************************************************/
hwInit_ReadRadioParamsSm(TI_HANDLE hHwInit)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
hwInit_ReadRadioParams(TI_HANDLE hHwInit)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
hwInit_InitPolarity(TI_HANDLE hHwInit)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 ****************************************************************************/
hwInit_WriteIRQPolarity(TI_HANDLE hHwInit)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
hwInit_InitTopRegisterWrite(TI_HANDLE hHwInit,TI_UINT32 uAddress,TI_UINT32 uValue)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 ****************************************************************************/
hwInit_TopRegisterWrite(TI_HANDLE hHwInit)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
hwInit_InitTopRegisterRead(TI_HANDLE hHwInit,TI_UINT32 uAddress)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 ****************************************************************************/
hwInit_TopRegisterRead(TI_HANDLE hHwInit)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