--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/TWD/FW_Transfer/HwInit.c Tue Jun 29 12:34:26 2010 +0100
@@ -0,0 +1,2422 @@
+/*
+ * HwInit.c
+ *
+ * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved.
+ * All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 or BSD License which accompanies
+ * this distribution. The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html and the BSD License is as below.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Texas Instruments nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+/*******************************************************************************/
+/* */
+/* MODULE: HwInit.c */
+/* PURPOSE: HwInit module manages the init process of the TNETW, included */
+/* firmware download process. It shall perform Hard Reset the chip */
+/* if possible (this will require a Reset line to be connected to */
+/* the host); Start InterfaceCtrl; Download NVS and FW */
+/* */
+/* */
+/*******************************************************************************/
+
+#define __FILE_ID__ FILE_ID_105
+#include "tidef.h"
+#include "osApi.h"
+#include "report.h"
+#include "HwInit_api.h"
+#include "FwEvent_api.h"
+#include "TwIf.h"
+#include "TWDriver.h"
+#include "TWDriverInternal.h"
+#include "eventMbox_api.h"
+#include "CmdBld.h"
+#include "CmdMBox_api.h"
+
+
+
+extern void TWD_FinalizeOnFailure (TI_HANDLE hTWD);
+extern void cmdBld_FinalizeDownload (TI_HANDLE hCmdBld, TBootAttr *pBootAttr, FwStaticData_t *pFwInfo);
+
+
+/************************************************************************
+ * Defines
+ ************************************************************************/
+
+/* Download phase partition */
+#define PARTITION_DOWN_MEM_ADDR 0
+#define PARTITION_DOWN_MEM_SIZE 0x177C0
+#define PARTITION_DOWN_REG_ADDR REGISTERS_BASE
+#define PARTITION_DOWN_REG_SIZE 0x8800
+
+/* Working phase partition */
+#define PARTITION_WORK_MEM_ADDR1 0x40000
+#define PARTITION_WORK_MEM_SIZE1 0x14FC0
+#define PARTITION_WORK_MEM_ADDR2 REGISTERS_BASE
+#define PARTITION_WORK_MEM_SIZE2 0xA000
+#define PARTITION_WORK_MEM_ADDR3 0x3004F8
+#define PARTITION_WORK_MEM_SIZE3 0x4
+#define PARTITION_WORK_MEM_ADDR4 0x40404
+
+/* DRPW setting partition */
+#define PARTITION_DRPW_MEM_ADDR 0x40000
+#define PARTITION_DRPW_MEM_SIZE 0x14FC0
+#define PARTITION_DRPW_REG_ADDR DRPW_BASE
+#define PARTITION_DRPW_REG_SIZE 0x6000
+
+/* Total range of bus addresses range */
+#define PARTITION_TOTAL_ADDR_RANGE 0x1FFC0
+
+/* Maximal block size in a single SDIO transfer --> Firmware image load chunk size */
+#ifdef _VLCT_
+#define MAX_SDIO_BLOCK (4000)
+#else
+#define MAX_SDIO_BLOCK (500)
+#endif
+
+#define ACX_EEPROMLESS_IND_REG (SCR_PAD4)
+#define USE_EEPROM (0)
+#define SOFT_RESET_MAX_TIME (1000000)
+#define SOFT_RESET_STALL_TIME (1000)
+#define NVS_DATA_BUNDARY_ALIGNMENT (4)
+
+#define MAX_HW_INIT_CONSECUTIVE_TXN 15
+
+#define WORD_SIZE 4
+#define WORD_ALIGNMENT_MASK 0x3
+#define DEF_NVS_SIZE (NVS_TOTAL_LENGTH)
+
+#define RADIO_SM_WAIT_LOOP 32
+
+#define FREF_CLK_FREQ_MASK 0x7
+#define FREF_CLK_TYPE_MASK BIT_3
+#define FREF_CLK_POLARITY_MASK BIT_4
+
+#define FREF_CLK_TYPE_BITS 0xfffffe7f
+#define CLK_REQ_PRCM 0x100
+
+#define FREF_CLK_POLARITY_BITS 0xfffff8ff
+#define CLK_REQ_OUTN_SEL 0x700
+
+/* time to wait till we check if fw is running */
+#define STALL_TIMEOUT 10
+#define FIN_LOOP 10
+
+/************************************************************************
+ * Macros
+ ************************************************************************/
+
+#define SET_DEF_NVS(aNVS) aNVS[0]=0x01; aNVS[1]=0x6d; aNVS[2]=0x54; aNVS[3]=0x56; aNVS[4]=0x34; \
+ aNVS[5]=0x12; aNVS[6]=0x28; aNVS[7]=0x01; aNVS[8]=0x71; aNVS[9]=0x54; \
+ aNVS[10]=0x00; aNVS[11]=0x08; aNVS[12]=0x00; aNVS[13]=0x00; aNVS[14]=0x00; \
+ aNVS[15]=0x00; aNVS[16]=0x00; aNVS[17]=0x00; aNVS[18]=0x00; aNVS[19]=0x00; \
+ aNVS[20]=0x00; aNVS[21]=0x00; aNVS[22]=0x00; aNVS[23]=0x00; aNVS[24]=eNVS_NON_FILE;\
+ aNVS[25]=0x00; aNVS[26]=0x00; aNVS[27]=0x00;
+
+
+#define SET_PARTITION(pPartition,uAddr1,uMemSize1,uAddr2,uMemSize2,uAddr3,uMemSize3,uAddr4) \
+ ((TPartition*)pPartition)[0].uMemAdrr = uAddr1; \
+ ((TPartition*)pPartition)[0].uMemSize = uMemSize1; \
+ ((TPartition*)pPartition)[1].uMemAdrr = uAddr2; \
+ ((TPartition*)pPartition)[1].uMemSize = uMemSize2; \
+ ((TPartition*)pPartition)[2].uMemAdrr = uAddr3; \
+ ((TPartition*)pPartition)[2].uMemSize = uMemSize3; \
+ ((TPartition*)pPartition)[3].uMemAdrr = uAddr4;
+
+#define HW_INIT_PTXN_SET(pHwInit, pTxn) pTxn = (TTxnStruct*)&(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].tTxnStruct);
+
+#define BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, uAddr, uVal, uSize, direction, fCB, hCB) \
+ HW_INIT_PTXN_SET(pHwInit, pTxn) \
+ TXN_PARAM_SET_DIRECTION(pTxn, direction); \
+ *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData)) = (TI_UINT32)uVal; \
+ BUILD_TTxnStruct(pTxn, uAddr, pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData, uSize, fCB, hCB)
+
+#define BUILD_HW_INIT_FW_STATIC_TXN(pHwInit, pTxn, uAddr, fCB, hCB) \
+ HW_INIT_PTXN_SET(pHwInit, pTxn) \
+ TXN_PARAM_SET_DIRECTION(pTxn, TXN_DIRECTION_READ); \
+ BUILD_TTxnStruct(pTxn, uAddr, pHwInit->tFwStaticTxn.pFwStaticInfo, sizeof(FwStaticData_t), fCB, hCB)
+
+#define BUILD_HW_INIT_FW_DL_TXN(pHwInit, pTxn, uAddr, uVal, uSize, direction, fCB, hCB) \
+ HW_INIT_PTXN_SET(pHwInit, pTxn) \
+ TXN_PARAM_SET_DIRECTION(pTxn, direction); \
+ BUILD_TTxnStruct(pTxn, uAddr, uVal, uSize, fCB, hCB)
+
+
+#define SET_DRP_PARTITION(pPartition)\
+ SET_PARTITION(pPartition, PARTITION_DRPW_MEM_ADDR, PARTITION_DRPW_MEM_SIZE, PARTITION_DRPW_REG_ADDR, PARTITION_DRPW_REG_SIZE, 0, 0, 0)
+
+#define SET_FW_LOAD_PARTITION(pPartition,uFwAddress)\
+ SET_PARTITION(pPartition,uFwAddress,PARTITION_DOWN_MEM_SIZE, PARTITION_DOWN_REG_ADDR, PARTITION_DOWN_REG_SIZE,0,0,0)
+
+#define SET_WORK_PARTITION(pPartition)\
+ 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)
+
+/* Handle return status inside a state machine */
+#define EXCEPT(phwinit,status) \
+ switch (status) { \
+ case TI_OK: \
+ case TXN_STATUS_OK: \
+ case TXN_STATUS_COMPLETE: \
+ break; \
+ case TXN_STATUS_PENDING: \
+ return TXN_STATUS_PENDING; \
+ default: \
+ phwinit->DownloadStatus = TXN_STATUS_ERROR; \
+ TWD_FinalizeOnFailure (phwinit->hTWD); \
+ return TXN_STATUS_ERROR; \
+ }
+
+
+/* Handle return status inside an init sequence state machine */
+#define EXCEPT_I(phwinit,status) \
+ switch (status) { \
+ case TI_OK: \
+ case TXN_STATUS_COMPLETE: \
+ break; \
+ case TXN_STATUS_PENDING: \
+ phwinit->uInitSeqStatus = status; \
+ return TXN_STATUS_PENDING; \
+ default: \
+ TWD_FinalizeOnFailure (phwinit->hTWD); \
+ return TXN_STATUS_ERROR; \
+ }
+
+
+/* Handle return status inside a load image state machine */
+#define EXCEPT_L(phwinit,status) \
+ switch (status) { \
+ case TXN_STATUS_OK: \
+ case TXN_STATUS_COMPLETE: \
+ break; \
+ case TXN_STATUS_PENDING: \
+ phwinit->DownloadStatus = status; \
+ return TXN_STATUS_PENDING; \
+ default: \
+ phwinit->DownloadStatus = status; \
+ TWD_FinalizeOnFailure (phwinit->hTWD); \
+ return TXN_STATUS_ERROR; \
+ }
+
+
+/************************************************************************
+ * Types
+ ************************************************************************/
+
+enum
+{
+ REF_FREQ_19_2 = 0,
+ REF_FREQ_26_0 = 1,
+ REF_FREQ_38_4 = 2,
+ REF_FREQ_40_0 = 3,
+ REF_FREQ_33_6 = 4,
+ REF_FREQ_NUM = 5
+};
+
+enum
+{
+ LUT_PARAM_INTEGER_DIVIDER = 0,
+ LUT_PARAM_FRACTIONAL_DIVIDER = 1,
+ LUT_PARAM_ATTN_BB = 2,
+ LUT_PARAM_ALPHA_BB = 3,
+ LUT_PARAM_STOP_TIME_BB = 4,
+ LUT_PARAM_BB_PLL_LOOP_FILTER = 5,
+ LUT_PARAM_NUM = 6
+};
+
+typedef struct
+{
+ TTxnStruct tTxnStruct;
+ TI_UINT8 *pData;
+
+} THwInitTxn;
+
+typedef struct
+{
+ TTxnStruct tTxnStruct;
+ TI_UINT8 *pFwStaticInfo;
+
+} TFwStaticTxn;
+
+
+/* The HW Init module object */
+typedef struct
+{
+ /* Handles */
+ TI_HANDLE hOs;
+ TI_HANDLE hReport;
+ TI_HANDLE hTWD;
+ TI_HANDLE hBusTxn;
+ TI_HANDLE hTwIf;
+
+ TI_HANDLE hFileInfo; /* holds parameters of FW Image Portion - for DW Download */
+ TEndOfHwInitCb fInitHwCb;
+
+ /* Firmware image ptr */
+ TI_UINT8 *pFwBuf;
+ /* Firmware image length */
+ TI_UINT32 uFwLength;
+ TI_UINT32 uFwAddress;
+ TI_UINT32 bFwBufLast;
+ TI_UINT32 uFwLastAddr;
+ /* EEPROM image ptr */
+ TI_UINT8 *pEEPROMBuf;
+ /* EEPROM image length */
+ TI_UINT32 uEEPROMLen;
+
+ TI_UINT8 *pEEPROMCurPtr;
+ TI_UINT32 uEEPROMCurLen;
+ TBootAttr tBootAttr;
+ TI_HANDLE hHwCtrl;
+ ETxnStatus DownloadStatus;
+ /* Upper module callback for the init stage */
+ fnotify_t fCb;
+ /* Upper module handle for the init stage */
+ TI_HANDLE hCb;
+ /* Init stage */
+ TI_UINT32 uInitStage;
+ /* Reset statge */
+ TI_UINT32 uResetStage;
+ /* EEPROM burst stage */
+ TI_UINT32 uEEPROMStage;
+ /* Init state machine temporary data */
+ TI_UINT32 uInitData;
+ /* ELP command image */
+ TI_UINT32 uElpCmd;
+ /* Chip ID */
+ TI_UINT32 uChipId;
+ /* Boot state machine temporary data */
+ TI_UINT32 uBootData;
+ TI_UINT32 uSelfClearTime;
+ TI_UINT8 uEEPROMBurstLen;
+ TI_UINT8 uEEPROMBurstLoop;
+ TI_UINT32 uEEPROMRegAddr;
+ TI_STATUS uEEPROMStatus;
+ TI_UINT32 uNVSStartAddr;
+ TI_UINT32 uNVSNumChar;
+ TI_UINT32 uNVSNumByte;
+ TI_STATUS uNVSStatus;
+ TI_UINT32 uScrPad6;
+ TI_UINT32 uRefFreq;
+ TI_UINT32 uInitSeqStage;
+ TI_STATUS uInitSeqStatus;
+ TI_UINT32 uLoadStage;
+ TI_UINT32 uBlockReadNum;
+ TI_UINT32 uBlockWriteNum;
+ TI_UINT32 uPartitionLimit;
+ TI_UINT32 uFinStage;
+ TI_UINT32 uFinData;
+ TI_UINT32 uFinLoop;
+ TI_UINT32 uRegStage;
+ TI_UINT32 uRegLoop;
+ TI_UINT32 uRegSeqStage;
+ TI_UINT32 uRegData;
+ #ifndef _VLCT_
+ TI_HANDLE hStallTimer;
+ #endif
+
+ /* Top register Read/Write SM temporary data*/
+ TI_UINT32 uTopRegAddr;
+ TI_UINT32 uTopRegValue;
+ TI_UINT32 uTopRegMask;
+ TI_UINT32 uTopRegUpdateValue;
+ TI_UINT32 uTopStage;
+ TI_STATUS uTopStatus;
+
+ TI_UINT8 *puFwTmpBuf;
+
+ TFinalizeCb fFinalizeDownload;
+ TI_HANDLE hFinalizeDownload;
+ /* Size of the Fw image, retrieved from the image itself */
+ TI_UINT32 uFwDataLen;
+ TI_UINT8 aDefaultNVS[DEF_NVS_SIZE];
+ TI_UINT8 uTxnIndex;
+ THwInitTxn aHwInitTxn[MAX_HW_INIT_CONSECUTIVE_TXN];
+ TFwStaticTxn tFwStaticTxn;
+
+ TI_UINT32 uSavedDataForWspiHdr; /* For saving the 4 bytes before the NVS data for WSPI case
+ where they are overrun by the WSPI BusDrv */
+ TPartition aPartition[NUM_OF_PARTITION];
+} THwInit;
+
+
+/************************************************************************
+ * Local Functions Prototypes
+ ************************************************************************/
+static void hwInit_SetPartition (THwInit *pHwInit,
+ TPartition *pPartition);
+static TI_STATUS hwInit_BootSm (TI_HANDLE hHwInit);
+static TI_STATUS hwInit_ResetSm (TI_HANDLE hHwInit);
+static TI_STATUS hwInit_EepromlessStartBurstSm (TI_HANDLE hHwInit);
+static TI_STATUS hwInit_LoadFwImageSm (TI_HANDLE hHwInit);
+static TI_STATUS hwInit_FinalizeDownloadSm (TI_HANDLE hHwInit);
+static TI_STATUS hwInit_TopRegisterRead(TI_HANDLE hHwInit);
+static TI_STATUS hwInit_InitTopRegisterRead(TI_HANDLE hHwInit, TI_UINT32 uAddress);
+static TI_STATUS hwInit_TopRegisterWrite(TI_HANDLE hHwInit);
+static TI_STATUS hwInit_InitTopRegisterWrite(TI_HANDLE hHwInit, TI_UINT32 uAddress, TI_UINT32 uValue);
+#ifndef _VLCT_
+ static void hwInit_StallTimerCb (TI_HANDLE hHwInit);
+#endif
+
+
+/*******************************************************************************
+* PUBLIC FUNCTIONS IMPLEMENTATION *
+********************************************************************************/
+
+
+/*************************************************************************
+* hwInit_Create *
+**************************************************************************
+* DESCRIPTION: This function initializes the HwInit module.
+*
+* INPUT: hOs - handle to Os Abstraction Layer
+*
+* RETURN: Handle to the allocated HwInit module
+*************************************************************************/
+TI_HANDLE hwInit_Create (TI_HANDLE hOs)
+{
+ THwInit *pHwInit;
+ int i;
+
+ /* Allocate HwInit module */
+ pHwInit = os_memoryAlloc (hOs, sizeof(THwInit),MemoryNormal);
+
+ if (pHwInit == NULL)
+ {
+ WLAN_OS_REPORT(("Error allocating the HwInit Module\n"));
+ return NULL;
+ }
+
+ /* Reset HwInit module */
+ os_memoryZero (hOs, pHwInit, sizeof(THwInit));
+
+ /* Allocate Register buffer */
+ for (i = 0; i < MAX_HW_INIT_CONSECUTIVE_TXN; i++)
+ {
+ pHwInit->aHwInitTxn[i].pData = os_memoryAlloc (hOs, sizeof(TI_UINT32) + WSPI_PAD_LEN_READ,MemoryDMA);
+ if (pHwInit->aHwInitTxn[i].pData == NULL)
+ {
+ return NULL;
+ }
+ os_memoryZero (hOs, pHwInit->aHwInitTxn[i].pData, sizeof(TI_UINT32) + WSPI_PAD_LEN_READ);
+ pHwInit->aHwInitTxn[i].pData += WSPI_PAD_LEN_READ;
+ }
+
+ pHwInit->tFwStaticTxn.pFwStaticInfo = os_memoryAlloc (hOs, sizeof (FwStaticData_t) + WSPI_PAD_LEN_READ,MemoryDMA);
+ if (pHwInit->tFwStaticTxn.pFwStaticInfo == NULL)
+ {
+ return NULL;
+ }
+ os_memoryZero (hOs, pHwInit->tFwStaticTxn.pFwStaticInfo, sizeof (FwStaticData_t) + WSPI_PAD_LEN_READ);
+ pHwInit->tFwStaticTxn.pFwStaticInfo += WSPI_PAD_LEN_READ;
+
+
+
+ pHwInit->puFwTmpBuf = os_memoryAlloc (hOs, WSPI_PAD_LEN_READ + MAX_SDIO_BLOCK,MemoryDMA);
+ if (pHwInit->puFwTmpBuf == NULL)
+ {
+ return NULL;
+ }
+ os_memoryZero (hOs, pHwInit->puFwTmpBuf, WSPI_PAD_LEN_READ + MAX_SDIO_BLOCK);
+ pHwInit->puFwTmpBuf += WSPI_PAD_LEN_READ;
+
+ pHwInit->hOs = hOs;
+
+ return (TI_HANDLE)pHwInit;
+}
+
+
+/***************************************************************************
+* hwInit_Destroy *
+****************************************************************************
+* DESCRIPTION: This function unload the HwInit module.
+*
+* INPUTS: hHwInit - the object
+*
+* OUTPUT:
+*
+* RETURNS: TI_OK - Unload succesfull
+* TI_NOK - Unload unsuccesfull
+***************************************************************************/
+TI_STATUS hwInit_Destroy (TI_HANDLE hHwInit)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ int i;
+
+ for (i = 0; i < MAX_HW_INIT_CONSECUTIVE_TXN; i++)
+ {
+ if (pHwInit->aHwInitTxn[i].pData)
+ {
+ os_memoryFree (pHwInit->hOs, pHwInit->aHwInitTxn[i].pData - WSPI_PAD_LEN_READ, sizeof(TI_UINT32) + WSPI_PAD_LEN_READ);
+ }
+ }
+
+ if (pHwInit->puFwTmpBuf)
+ {
+
+ os_memoryFree (pHwInit->hOs, pHwInit->puFwTmpBuf - WSPI_PAD_LEN_READ, WSPI_PAD_LEN_READ + MAX_SDIO_BLOCK);
+ }
+
+ if (pHwInit->pEEPROMBuf)
+ {
+ os_memoryFree (pHwInit->hOs, pHwInit->pEEPROMBuf, pHwInit->uEEPROMLen);
+ }
+
+ if (pHwInit->tFwStaticTxn.pFwStaticInfo)
+ {
+ os_memoryFree (pHwInit->hOs, pHwInit->tFwStaticTxn.pFwStaticInfo - WSPI_PAD_LEN_READ, sizeof (FwStaticData_t) + WSPI_PAD_LEN_READ);
+ }
+
+ #ifndef _VLCT_
+ if (pHwInit->hStallTimer)
+ {
+ os_timerDestroy(pHwInit->hOs, pHwInit->hStallTimer);
+ }
+ #endif
+
+ /* Free HwInit Module */
+ os_memoryFree (pHwInit->hOs, pHwInit, sizeof(THwInit));
+
+ return TI_OK;
+}
+
+
+/***************************************************************************
+* hwInit_Init *
+****************************************************************************
+* DESCRIPTION: This function configures the hwInit module
+*
+* RETURNS: TI_OK - Configuration successful
+* TI_NOK - Configuration unsuccessful
+***************************************************************************/
+TI_STATUS hwInit_Init (TI_HANDLE hHwInit,
+ TI_HANDLE hReport,
+ TI_HANDLE hTWD,
+ TI_HANDLE hFinalizeDownload,
+ TFinalizeCb fFinalizeDownload,
+ TEndOfHwInitCb fInitHwCb)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TTxnStruct* pTxn;
+
+ /* Configure modules handles */
+ pHwInit->hReport = hReport;
+ pHwInit->hTWD = hTWD;
+ pHwInit->hTwIf = ((TTwd *)hTWD)->hTwIf;
+ pHwInit->hOs = ((TTwd *)hTWD)->hOs;
+ pHwInit->fInitHwCb = fInitHwCb;
+ pHwInit->fFinalizeDownload = fFinalizeDownload;
+ pHwInit->hFinalizeDownload = hFinalizeDownload;
+
+ SET_DEF_NVS(pHwInit->aDefaultNVS)
+
+ for (pHwInit->uTxnIndex=0;pHwInit->uTxnIndex<MAX_HW_INIT_CONSECUTIVE_TXN;pHwInit->uTxnIndex++)
+ {
+ HW_INIT_PTXN_SET(pHwInit, pTxn)
+ /* Setting write as default transaction */
+ TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
+ }
+
+ #ifndef _VLCT_
+ pHwInit->hStallTimer = os_timerCreate (pHwInit->hOs, hwInit_StallTimerCb, hHwInit);
+ if (pHwInit->hStallTimer == NULL)
+ {
+ return TI_NOK;
+ }
+ #endif
+
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT, ".....HwInit configured successfully\n");
+
+ return TI_OK;
+}
+
+
+TI_STATUS hwInit_SetNvsImage (TI_HANDLE hHwInit, TI_UINT8 *pbuf, TI_UINT32 length)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+
+ if (length == 0) {
+ TRACE0 (pHwInit->hReport, REPORT_SEVERITY_WARNING,"NVS File Length iz zero");
+ pHwInit->pEEPROMBuf = NULL;
+ return TI_OK;
+ }
+ /* We need to guarantee that the NVS buffer will be DMA'ble (physically continous) */
+ pHwInit->pEEPROMBuf = os_memoryAlloc (pHwInit->hOs, length, MemoryDMA);
+
+ if (pHwInit->pEEPROMBuf == NULL)
+ {
+ return TI_NOK;
+ }
+
+ os_memoryCopy(pHwInit->hOs, pHwInit->pEEPROMBuf, pbuf, length);
+
+ pHwInit->uEEPROMLen = length;
+
+ return TI_OK;
+}
+
+
+TI_STATUS hwInit_SetFwImage (TI_HANDLE hHwInit, TFileInfo *pFileInfo)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+
+ if ((hHwInit == NULL) || (pFileInfo == NULL))
+ {
+ return TI_NOK;
+ }
+
+ pHwInit->pFwBuf = pFileInfo->pBuffer;
+ pHwInit->uFwLength = pFileInfo->uLength;
+ pHwInit->uFwAddress = pFileInfo->uAddress;
+ pHwInit->bFwBufLast = pFileInfo->bLast;
+
+ return TI_OK;
+}
+
+
+/**
+ * \fn hwInit_SetPartition
+ * \brief Set HW addresses partition
+ *
+ * Set the HW address ranges for download or working memory and registers access.
+ * Generate and configure the bus access address mapping table.
+ * The partition is split between register (fixed partition of 24KB size, exists in all modes),
+ * and memory (dynamically changed during init and gets constant value in run-time, 104KB size).
+ * The TwIf configures the memory mapping table on the device by issuing write transaction to
+ * table address (note that the TxnQ and bus driver see this as a regular transaction).
+ *
+ * \note In future versions, a specific bus may not support partitioning (as in wUART),
+ * In this case the HwInit module shall not call this function (will learn the bus
+ * configuration from the INI file).
+ *
+ * \param pHwInit - The module's object
+ * \param uMemAddr - The memory partition base address
+ * \param uMemSize - The memory partition size
+ * \param uRegAddr - The registers partition base address
+ * \param uRegSize - The register partition size
+ * \return void
+ * \sa
+ */
+static void hwInit_SetPartition (THwInit *pHwInit,
+ TPartition *pPartition)
+{
+ 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 );
+
+ /* Prepare partition Txn data and send to HW */
+ twIf_SetPartition (pHwInit->hTwIf,pPartition);
+}
+
+
+/****************************************************************************
+ * hwInit_Boot()
+ ****************************************************************************
+ * DESCRIPTION: Start HW init sequence which writes and reads some HW registers
+ * that are needed prior to FW download.
+ *
+ * INPUTS: None
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: TI_OK or TI_NOK
+ ****************************************************************************/
+TI_STATUS hwInit_Boot (TI_HANDLE hHwInit)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TTwd *pTWD = (TTwd *)pHwInit->hTWD;
+ TWlanParams *pWlanParams = &DB_WLAN(pTWD->hCmdBld);
+ TBootAttr tBootAttr;
+
+ tBootAttr.MacClock = pWlanParams->MacClock;
+ tBootAttr.ArmClock = pWlanParams->ArmClock;
+
+ /*
+ * Initialize the status of download to pending
+ * It will be set to TXN_STATUS_COMPLETE at the FinalizeDownload function
+ */
+ pHwInit->DownloadStatus = TXN_STATUS_PENDING;
+
+ /* Call the boot sequence state machine */
+ pHwInit->uInitStage = 0;
+
+ os_memoryCopy (pHwInit->hOs, &pHwInit->tBootAttr, &tBootAttr, sizeof(TBootAttr));
+
+ hwInit_BootSm (hHwInit);
+
+ /*
+ * If it returns the status of the StartInstance only then we can here query for the download status
+ * and then return the status up to the TNETW_Driver.
+ * This return value will go back up to the TNETW Driver layer so that the init from OS will know
+ * if to wait for the InitComplte or not in case of TXN_STATUS_ERROR.
+ * This value will always be pending since the SPI is ASYNC
+ * and in SDIOa timer is set so it will be ASync also in anyway.
+ */
+ return pHwInit->DownloadStatus;
+}
+
+
+ /****************************************************************************
+ * DESCRIPTION: Firmware boot state machine
+ *
+ * INPUTS:
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: TI_OK
+ ****************************************************************************/
+static TI_STATUS hwInit_BootSm (TI_HANDLE hHwInit)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TI_STATUS status = 0;
+ TTxnStruct *pTxn;
+ TI_UINT32 uData;
+ TTwd *pTWD = (TTwd *) pHwInit->hTWD;
+ IniFileGeneralParam *pGenParams = &DB_GEN(pTWD->hCmdBld);
+ TI_UINT32 clkVal = 0x3;
+
+ switch (pHwInit->uInitStage)
+ {
+ case 0:
+ pHwInit->uInitStage++;
+ pHwInit->uTxnIndex = 0;
+ SET_WORK_PARTITION(pHwInit->aPartition)
+
+ /* Set the bus addresses partition to its "running" mode */
+ hwInit_SetPartition (pHwInit,pHwInit->aPartition);
+
+#ifdef _VLCT_
+ /* Set FW to test mode */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, SCR_PAD8, 0xBABABABE,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+ pHwInit->uTxnIndex++;
+#endif
+
+ if (( 0 == (pGenParams->RefClk & FREF_CLK_FREQ_MASK)) || (2 == (pGenParams->RefClk & FREF_CLK_FREQ_MASK))
+ || (4 == (pGenParams->RefClk & FREF_CLK_FREQ_MASK)))
+ {/* ref clk: 19.2/38.4/38.4-XTAL */
+ clkVal = 0x3;
+ }
+ if ((1 == (pGenParams->RefClk & FREF_CLK_FREQ_MASK)) || (3 == (pGenParams->RefClk & FREF_CLK_FREQ_MASK)))
+ {/* ref clk: 26/52 */
+ clkVal = 0x5;
+ }
+
+ WLAN_OS_REPORT(("CHIP VERSION... set 1273 chip top registers\n"));
+
+ /* set the reference clock freq' to be used (pll_selinpfref field) */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, PLL_PARAMETERS, clkVal,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ /* read the PAUSE value to highest threshold */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, PLL_PARAMETERS, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_BootSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+
+ case 1:
+ pHwInit->uInitStage ++;
+ /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */
+ uData = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+ if (uData == 0xFFFFFFFF)
+ {
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "hwInit_BootSm: Failed to read PLL parameters\n");
+ pHwInit->DownloadStatus = TXN_STATUS_ERROR;
+ TWD_FinalizeOnFailure (pHwInit->hTWD);
+ return TXN_STATUS_ERROR;
+ }
+ else
+ {
+ uData &= ~(0x3ff);
+ }
+
+ /* Now we can zero the index */
+ pHwInit->uTxnIndex = 0;
+
+ /* set the the PAUSE value to highest threshold */
+ uData |= WU_COUNTER_PAUSE_VAL;
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, WU_COUNTER_PAUSE, uData,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ /* Continue the ELP wake up sequence */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ /* Wait 500uS */
+ os_StalluSec (pHwInit->hOs, 500);
+
+ SET_DRP_PARTITION(pHwInit->aPartition)
+ /* Set the bus addresses partition to DRPw registers region */
+ hwInit_SetPartition (pHwInit,pHwInit->aPartition);
+
+ pHwInit->uTxnIndex++;
+
+ /* Read-modify-write DRPW_SCRATCH_START register (see next state) to be used by DRPw FW.
+ The RTRIM value will be added by the FW before taking DRPw out of reset */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, DRPW_SCRATCH_START, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ,(TTxnDoneCb)hwInit_BootSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+
+ case 2:
+ pHwInit->uInitStage ++;
+
+ /* multiply fref value by 2, so that {0,1,2,3} values will become {0,2,4,6} */
+ /* Then, move it 4 places to the right, to alter Fref relevant bits in register 0x2c */
+ clkVal = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+ pHwInit->uTxnIndex = 0; /* Reset index only after getting the last read value! */
+ clkVal |= (pGenParams->RefClk << 1) << 4;
+
+ /* Disable LPD mode */
+ clkVal &= 0xf9ffffff;
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, DRPW_SCRATCH_START, clkVal,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ SET_WORK_PARTITION(pHwInit->aPartition)
+ /* Set the bus addresses partition back to its "running" mode */
+ hwInit_SetPartition (pHwInit,pHwInit->aPartition);
+
+ /*
+ * end of CHIP init seq.
+ */
+
+ /* Disable interrupts */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_INTERRUPT_MASK, ACX_INTR_ALL,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ /* Read the CHIP ID to get an indication that the bus is TI_OK */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, CHIP_ID, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ,(TTxnDoneCb)hwInit_BootSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+
+ case 3:
+ pHwInit->uInitStage ++;
+
+ /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */
+ pHwInit->uChipId = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+
+ /* This is only sanity check that the HW exists, we can continue and fail on FwLoad */
+ if (pHwInit->uChipId == CHIP_ID_1273_PG10)
+ {
+ WLAN_OS_REPORT(("Working on a 1273 PG 1.0 board.\n"));
+ }
+ else if (pHwInit->uChipId == CHIP_ID_1273_PG20)
+ {
+ WLAN_OS_REPORT(("Working on a 1273 PG 2.0 board.\n"));
+ }
+ else
+ {
+ WLAN_OS_REPORT (("Error!! Found unknown Chip Id = 0x%x\n", pHwInit->uChipId));
+
+ /*
+ * NOTE: no exception because of forward compatibility
+ */
+ }
+
+ /*
+ * Soft reset
+ */
+ pHwInit->uResetStage = 0;
+ pHwInit->uSelfClearTime = 0;
+ pHwInit->uBootData = 0;
+ status = hwInit_ResetSm (pHwInit);
+
+ EXCEPT (pHwInit, status)
+
+ case 4:
+ pHwInit->uInitStage ++;
+
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "TNET SOFT-RESET\n");
+
+ WLAN_OS_REPORT(("Starting to process NVS...\n"));
+
+ /*
+ * Start EEPROM/NVS burst
+ */
+
+ if (pHwInit->pEEPROMBuf)
+ {
+ /* NVS file exists (EEPROM-less support) */
+ pHwInit->uEEPROMCurLen = pHwInit->uEEPROMLen;
+
+ TRACE2(pHwInit->hReport, REPORT_SEVERITY_INIT , "EEPROM Image addr=0x%x, EEPROM Len=0x0x%x\n", pHwInit->pEEPROMBuf, pHwInit->uEEPROMLen);
+ WLAN_OS_REPORT (("NVS found, EEPROM Image addr=0x%x, EEPROM Len=0x0x%x\n",
+ pHwInit->pEEPROMBuf, pHwInit->uEEPROMLen));
+ }
+ else
+ {
+ WLAN_OS_REPORT (("No Nvs, Setting default MAC address\n"));
+ pHwInit->uEEPROMCurLen = DEF_NVS_SIZE;
+ pHwInit->pEEPROMBuf = (TI_UINT8*)(&pHwInit->aDefaultNVS[0]);
+ WLAN_OS_REPORT (("pHwInit->uEEPROMCurLen: %x\n", pHwInit->uEEPROMCurLen));
+ WLAN_OS_REPORT (("ERROR: If you are not calibating the device, you will soon get errors !!!\n"));
+
+ }
+
+ pHwInit->pEEPROMCurPtr = pHwInit->pEEPROMBuf;
+ pHwInit->uEEPROMStage = 0;
+ status = hwInit_EepromlessStartBurstSm (hHwInit);
+
+ EXCEPT (pHwInit, status)
+
+ case 5:
+ pHwInit->uInitStage ++;
+ pHwInit->uTxnIndex = 0;
+
+ if (pHwInit->pEEPROMBuf)
+ {
+ /* Signal FW that we are eeprom less */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "DRIVER NVS BURST-READ\n");
+ }
+ else
+ {
+ /* 1273 - EEPROM is not support by FPGA yet */
+ /*
+ * Start ACX EEPROM
+ */
+ /*pHwInit->uRegister = START_EEPROM_MGR;
+ TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
+ BUILD_TTxnStruct(pTxn, ACX_REG_EE_START, &pHwInit->uRegister, REGISTER_SIZE, 0, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);*/
+
+ /*
+ * The stall is needed so the EEPROM NVS burst read will complete
+ */
+ os_StalluSec (pHwInit->hOs, 40000);
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_EEPROMLESS_IND_REG, USE_EEPROM,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "STARTING EEPROM NVS BURST-READ\n");
+ }
+
+ pHwInit->uTxnIndex++;
+
+ /* Read Chip ID */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, CHIP_ID, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ,(TTxnDoneCb)hwInit_BootSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+
+ case 6:
+ pHwInit->uInitStage ++;
+ /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */
+ pHwInit->uBootData = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+ /* Now we can zero the index */
+ pHwInit->uTxnIndex = 0;
+
+ WLAN_OS_REPORT(("Chip ID is 0x%X.\n", pHwInit->uBootData));
+
+ /* Read Scr2 to verify that the HW is ready */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, SCR_PAD2, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ,(TTxnDoneCb)hwInit_BootSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+ EXCEPT (pHwInit, status)
+
+ case 7:
+ pHwInit->uInitStage ++;
+
+ /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */
+ pHwInit->uBootData = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+
+ if (pHwInit->uBootData == 0xffffffff)
+ {
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_FATAL_ERROR , "Error in SCR_PAD2 register\n");
+ EXCEPT (pHwInit, TXN_STATUS_ERROR)
+ }
+
+ /* Call the restart sequence */
+ pHwInit->uInitSeqStage = 0;
+ pHwInit->uInitSeqStatus = TXN_STATUS_COMPLETE;
+
+ EXCEPT (pHwInit, status)
+
+
+ case 8:
+ pHwInit->uInitStage++;
+
+ if ((pGenParams->RefClk & FREF_CLK_TYPE_MASK) != 0x0)
+ {
+ status = hwInit_InitTopRegisterRead(hHwInit, 0x448);
+ EXCEPT (pHwInit, status)
+ }
+
+ case 9:
+ pHwInit->uInitStage++;
+
+ if ((pGenParams->RefClk & FREF_CLK_TYPE_MASK) != 0x0)
+ {
+ pHwInit->uTopRegValue &= FREF_CLK_TYPE_BITS;
+ pHwInit->uTopRegValue |= CLK_REQ_PRCM;
+
+ status = hwInit_InitTopRegisterWrite( hHwInit, 0x448, pHwInit->uTopRegValue);
+ EXCEPT (pHwInit, status)
+ }
+
+ case 10:
+ pHwInit->uInitStage++;
+
+ if ((pGenParams->RefClk & FREF_CLK_POLARITY_MASK) == 0x0)
+ {
+ status = hwInit_InitTopRegisterRead(hHwInit, 0xCB2);
+ EXCEPT (pHwInit, status)
+ }
+
+ case 11:
+ pHwInit->uInitStage++;
+ if ((pGenParams->RefClk & FREF_CLK_POLARITY_MASK) == 0x0)
+ {
+ pHwInit->uTopRegValue &= FREF_CLK_POLARITY_BITS;
+ pHwInit->uTopRegValue |= CLK_REQ_OUTN_SEL;
+
+ status = hwInit_InitTopRegisterWrite( hHwInit, 0xCB2, pHwInit->uTopRegValue);
+ EXCEPT (pHwInit, status)
+ }
+
+ case 12:
+ pHwInit->uInitStage = 0;
+
+ /* Set the Download Status to COMPLETE */
+ pHwInit->DownloadStatus = TXN_STATUS_COMPLETE;
+
+ /* Call upper layer callback */
+ if (pHwInit->fInitHwCb)
+ {
+ (*pHwInit->fInitHwCb) (pHwInit->hTWD);
+ }
+
+ return TI_OK;
+ }
+
+ return TI_OK;
+}
+
+
+TI_STATUS hwInit_LoadFw (TI_HANDLE hHwInit)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TI_STATUS status;
+
+ /* check parameters */
+ if (hHwInit == NULL)
+ {
+ EXCEPT (pHwInit, TXN_STATUS_ERROR)
+ }
+
+ if (pHwInit->pFwBuf)
+ {
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "CPU halt -> download code\n");
+
+ /* Load firmware image */
+ pHwInit->uLoadStage = 0;
+ status = hwInit_LoadFwImageSm (pHwInit);
+
+ switch (status)
+ {
+ case TI_OK:
+ case TXN_STATUS_OK:
+ case TXN_STATUS_COMPLETE:
+ WLAN_OS_REPORT (("Firmware successfully downloaded.\n"));
+ break;
+ case TXN_STATUS_PENDING:
+ WLAN_OS_REPORT (("Starting to download firmware...\n"));
+ break;
+ default:
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Firmware download failed!\n");
+ break;
+ }
+
+ EXCEPT (pHwInit, status);
+ }
+ else
+ {
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "Firmware not downloaded...\n");
+
+ EXCEPT (pHwInit, TXN_STATUS_ERROR)
+ }
+
+ WLAN_OS_REPORT (("FW download OK...\n"));
+ return TI_OK;
+}
+
+
+/****************************************************************************
+ * hwInit_FinalizeDownloadSm()
+ ****************************************************************************
+ * DESCRIPTION: Run the Hardware firmware
+ * Wait for Init Complete
+ * Configure the Bus Access with Addresses available on the scratch pad register
+ * Change the SDIO/SPI partitions to be able to see all the memory addresses
+ *
+ * INPUTS: None
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: None
+ ****************************************************************************/
+static TI_STATUS hwInit_FinalizeDownloadSm (TI_HANDLE hHwInit)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TTwd *pTWD = (TTwd *)pHwInit->hTWD;
+ TI_STATUS status = TI_OK;
+ TI_UINT32 uIntVect;
+ TTxnStruct* pTxn;
+
+ while (TI_TRUE)
+ {
+ switch (pHwInit->uFinStage)
+ {
+ case 0:
+ pHwInit->uFinStage = 1;
+ pHwInit->uTxnIndex = 0;
+ /*
+ * Run the firmware (I) - Read current value from ECPU Control Reg.
+ */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_ECPU_CONTROL, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_FinalizeDownloadSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+
+ case 1:
+ pHwInit->uFinStage ++;
+ /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */
+ pHwInit->uFinData = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+ /* Now we can zero the index */
+ pHwInit->uTxnIndex = 0;
+
+ /*
+ * Run the firmware (II) - Take HW out of reset (write ECPU_CONTROL_HALT to ECPU Control Reg.)
+ */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_ECPU_CONTROL, (pHwInit->uFinData | ECPU_CONTROL_HALT),
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ WLAN_OS_REPORT (("Firmware running.\n"));
+
+ /*
+ * CHIP ID Debug
+ */
+
+ pHwInit->uTxnIndex++;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, CHIP_ID, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_FinalizeDownloadSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+
+ case 2:
+ pHwInit->uFinStage ++;
+ pHwInit->uFinLoop = 0;
+
+ /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */
+ pHwInit->uFinData = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+
+ TRACE1(pHwInit->hReport, REPORT_SEVERITY_INIT , "CHIP ID IS %x\n", pHwInit->uFinData);
+
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "Wait init complete\n");
+
+ case 3:
+ pHwInit->uTxnIndex = 0;
+
+ /*
+ * Wait for init complete
+ */
+ if (pHwInit->uFinLoop < FIN_LOOP)
+ {
+ pHwInit->uFinStage = 4;
+
+ #ifdef _VLCT_
+ os_StalluSec (pHwInit->hOs, 50);*/
+ #endif
+
+ /* Read interrupt status register */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_INTERRUPT_NO_CLEAR, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_FinalizeDownloadSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+ }
+ else
+ {
+ pHwInit->uFinStage = 5;
+ }
+ continue;
+
+ case 4:
+ /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */
+ pHwInit->uFinData = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+ /* Now we can zero the index */
+ pHwInit->uTxnIndex = 0;
+
+ if (pHwInit->uFinData == 0xffffffff) /* error */
+ {
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Error reading hardware complete init indication\n");
+
+ pHwInit->DownloadStatus = TXN_STATUS_ERROR;
+ EXCEPT (pHwInit, TXN_STATUS_ERROR)
+ }
+
+ if (IS_MASK_ON (pHwInit->uFinData, ACX_INTR_INIT_COMPLETE))
+ {
+ pHwInit->uFinStage = 5;
+
+ /* Interrupt ACK */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_INTERRUPT_ACK, ACX_INTR_INIT_COMPLETE,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ break;
+ }
+ else
+ {
+ pHwInit->uFinStage = 3;
+ pHwInit->uFinLoop ++;
+
+ #ifndef _VLCT_
+ os_timerStart (pHwInit->hOs, pHwInit->hStallTimer, STALL_TIMEOUT);
+ return TI_PENDING;
+ #endif
+ }
+ #ifdef _VLCT_
+ continue;
+ #endif
+
+ case 5:
+ pHwInit->uFinStage++;
+
+ if (pHwInit->uFinLoop >= FIN_LOOP)
+ {
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Timeout waiting for the hardware to complete initialization\n");
+
+ pHwInit->DownloadStatus = TXN_STATUS_ERROR;
+ EXCEPT (pHwInit, TXN_STATUS_ERROR);
+ }
+
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "Firmware init complete...\n");
+
+ /*
+ * There are valid addresses of the command and event mailbox
+ * on the scratch pad registers
+ */
+ /* Hardware config command mail box */
+ status = cmdMbox_ConfigHw (pTWD->hCmdMbox,
+ (fnotify_t)hwInit_FinalizeDownloadSm,
+ hHwInit);
+ EXCEPT (pHwInit, status)
+
+ case 6:
+ pHwInit->uFinStage++;
+
+ /* Hardware config event mail box */
+ status = eventMbox_InitMboxAddr (pTWD->hEventMbox,
+ (fnotify_t)hwInit_FinalizeDownloadSm,
+ hHwInit);
+ EXCEPT (pHwInit, status);
+
+ case 7:
+ pHwInit->uFinStage++;
+ pHwInit->uTxnIndex = 0;
+
+ SET_WORK_PARTITION(pHwInit->aPartition)
+ /* Set the bus addresses partition to its "running" mode */
+ hwInit_SetPartition (pHwInit,pHwInit->aPartition);
+
+ /*
+ * In case of full asynchronous mode the firmware event must be ready
+ * to receive event from the command mailbox
+ */
+
+ uIntVect = fwEvent_GetInitMask (pTWD->hFwEvent);
+
+ /* Clearing all the interrupt status register sources */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, ACX_REG_INTERRUPT_MASK, (~uIntVect),
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+
+ pHwInit->uTxnIndex++;
+
+ BUILD_HW_INIT_FW_STATIC_TXN(pHwInit, pTxn, cmdMbox_GetMboxAddress (pTWD->hCmdMbox),
+ (TTxnDoneCb)hwInit_FinalizeDownloadSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status);
+ continue;
+
+ case 8:
+
+ pHwInit->uFinStage = 0;
+
+ cmdBld_FinalizeDownload (pTWD->hCmdBld, &pHwInit->tBootAttr, (FwStaticData_t *)(pHwInit->tFwStaticTxn.pFwStaticInfo));
+
+ /* Set the Download Status to COMPLETE */
+ pHwInit->DownloadStatus = TXN_STATUS_COMPLETE;
+
+ return TXN_STATUS_COMPLETE;
+
+ } /* End switch */
+
+ } /* End while */
+
+}
+
+
+/****************************************************************************
+ * hwInit_ResetSm()
+ ****************************************************************************
+ * DESCRIPTION: Reset hardware state machine
+ *
+ * INPUTS: None
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: TI_OK or TI_NOK
+ ****************************************************************************/
+static TI_STATUS hwInit_ResetSm (TI_HANDLE hHwInit)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TI_STATUS status = TI_OK;
+ TTxnStruct* pTxn;
+
+ pHwInit->uTxnIndex = 0;
+
+ /* Disable Rx/Tx */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, REG_ENABLE_TX_RX, 0x0,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ /* Disable auto calibration on start */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, SPARE_A2, 0xFFFF,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE,(TTxnDoneCb)hwInit_BootSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ return status;
+}
+
+
+/****************************************************************************
+ * hwInit_EepromlessStartBurstSm()
+ ****************************************************************************
+ * DESCRIPTION: prepare eepromless configuration before boot
+ *
+ * INPUTS:
+ *
+ * OUTPUT:
+ *
+ * RETURNS:
+ ****************************************************************************/
+static TI_STATUS hwInit_EepromlessStartBurstSm (TI_HANDLE hHwInit)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TI_STATUS status = TI_OK;
+ TI_UINT8 *uAddr;
+ TI_UINT32 uDeltaLength;
+ TTxnStruct* pTxn;
+
+ pHwInit->uTxnIndex = 0;
+
+ while (TI_TRUE)
+ {
+ switch (pHwInit->uEEPROMStage)
+ {
+ /*
+ * Stages 0, 1 handles the eeprom format parameters:
+ * ------------------------------------------------
+ * Length - 8bit --> The length is counted in 32bit words
+ * Address - 16bit
+ * Data - (Length * 4) bytes
+ *
+ * Note: The nvs is in big endian format and we need to change it to little endian
+ */
+ case 0:
+ /* Check if address LSB = 1 --> Register address */
+ if ((pHwInit->uEEPROMRegAddr = pHwInit->pEEPROMCurPtr[1]) & 1)
+ {
+ /* Mask the register's address LSB before writing to it */
+ pHwInit->uEEPROMRegAddr &= 0xfe;
+ /* Change the address's endian */
+ pHwInit->uEEPROMRegAddr |= (TI_UINT32)pHwInit->pEEPROMCurPtr[2] << 8;
+ /* Length of burst data */
+ pHwInit->uEEPROMBurstLen = pHwInit->pEEPROMCurPtr[0];
+ pHwInit->pEEPROMCurPtr += 3;
+ pHwInit->uEEPROMBurstLoop = 0;
+ /*
+ * We've finished reading the burst information.
+ * Go to stage 1 in order to write it
+ */
+ pHwInit->uEEPROMStage = 1;
+ }
+ /* If address LSB = 0 --> We're not in the burst section */
+ else
+ {
+ /* End of Burst transaction: we should see 7 zeroed bytes */
+ if (pHwInit->pEEPROMCurPtr[0] == 0)
+ {
+ pHwInit->pEEPROMCurPtr += 7;
+ }
+ pHwInit->uEEPROMCurLen -= (pHwInit->pEEPROMCurPtr - pHwInit->pEEPROMBuf + 1);
+ pHwInit->uEEPROMCurLen = (pHwInit->uEEPROMCurLen + NVS_DATA_BUNDARY_ALIGNMENT - 1) & 0xfffffffc;
+ /* End of Burst transaction, go to TLV section */
+ pHwInit->uEEPROMStage = 2;
+ }
+ continue;
+
+ case 1:
+ if (pHwInit->uEEPROMBurstLoop < pHwInit->uEEPROMBurstLen)
+ {
+ /* Change the data's endian */
+ TI_UINT32 val = (pHwInit->pEEPROMCurPtr[0] |
+ (pHwInit->pEEPROMCurPtr[1] << 8) |
+ (pHwInit->pEEPROMCurPtr[2] << 16) |
+ (pHwInit->pEEPROMCurPtr[3] << 24));
+
+ TRACE2(pHwInit->hReport, REPORT_SEVERITY_INIT , "NVS::BurstRead: *(%08x) = %x\n", pHwInit->uEEPROMRegAddr, val);
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, (REGISTERS_BASE+pHwInit->uEEPROMRegAddr), val,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, (TTxnDoneCb)hwInit_EepromlessStartBurstSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uEEPROMStatus = status;
+ pHwInit->uEEPROMRegAddr += WORD_SIZE;
+ pHwInit->pEEPROMCurPtr += WORD_SIZE;
+ /* While not end of burst, we stay in stage 1 */
+ pHwInit->uEEPROMStage = 1;
+ pHwInit->uEEPROMBurstLoop ++;
+
+ EXCEPT (pHwInit, status);
+ }
+ else
+ {
+ /* If end of burst return to stage 0 to read the next one */
+ pHwInit->uEEPROMStage = 0;
+ }
+
+ continue;
+
+ case 2:
+
+
+ pHwInit->uEEPROMStage = 3;
+
+ SET_WORK_PARTITION(pHwInit->aPartition)
+ /* Set the bus addresses partition to its "running" mode */
+ hwInit_SetPartition (pHwInit,pHwInit->aPartition);
+ continue;
+
+ case 3:
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "Reached TLV section\n");
+
+ /* Align the host address */
+ if (((TI_UINT32)pHwInit->pEEPROMCurPtr & WORD_ALIGNMENT_MASK) && (pHwInit->uEEPROMCurLen > 0) )
+ {
+ uAddr = (TI_UINT8*)(((TI_UINT32)pHwInit->pEEPROMCurPtr & 0xFFFFFFFC)+WORD_SIZE);
+ uDeltaLength = uAddr - pHwInit->pEEPROMCurPtr + 1;
+
+ pHwInit->pEEPROMCurPtr = uAddr;
+ pHwInit->uEEPROMCurLen-= uDeltaLength;
+ }
+
+ TRACE2(pHwInit->hReport, REPORT_SEVERITY_INIT , "NVS::WriteTLV: pEEPROMCurPtr= %x, Length=%d\n", pHwInit->pEEPROMCurPtr, pHwInit->uEEPROMCurLen);
+
+ if (pHwInit->uEEPROMCurLen)
+ {
+ /* Save the 4 bytes before the NVS data for WSPI case where they are overrun by the WSPI BusDrv */
+ pHwInit->uSavedDataForWspiHdr = *(TI_UINT32 *)(pHwInit->pEEPROMCurPtr - WSPI_PAD_LEN_WRITE);
+
+ /* Prepare the Txn structure for the NVS transaction to the CMD_MBOX */
+ HW_INIT_PTXN_SET(pHwInit, pTxn)
+ TXN_PARAM_SET_DIRECTION(pTxn, TXN_DIRECTION_WRITE);
+ BUILD_TTxnStruct(pTxn, CMD_MBOX_ADDRESS, pHwInit->pEEPROMCurPtr, pHwInit->uEEPROMCurLen,
+ (TTxnDoneCb)hwInit_EepromlessStartBurstSm, hHwInit)
+
+ /* Transact the NVS data to the CMD_MBOX */
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uEEPROMCurLen = 0;
+ pHwInit->uNVSStatus = status;
+
+ EXCEPT (pHwInit, status);
+ }
+ else
+ {
+ /* Restore the 4 bytes before the NVS data for WSPI case were they are overrun by the WSPI BusDrv */
+ *(TI_UINT32 *)(pHwInit->pEEPROMCurPtr - WSPI_PAD_LEN_WRITE) = pHwInit->uSavedDataForWspiHdr;
+
+ /* Call the upper level state machine */
+ if (pHwInit->uEEPROMStatus == TXN_STATUS_PENDING ||
+ pHwInit->uNVSStatus == TXN_STATUS_PENDING)
+ {
+ hwInit_BootSm (hHwInit);
+ }
+
+ return TXN_STATUS_COMPLETE;
+ }
+ } /* End switch */
+
+ } /* End while */
+}
+
+/****************************************************************************
+ * hwInit_LoadFwImageSm()
+ ****************************************************************************
+ * DESCRIPTION: Load image from the host and download into the hardware
+ *
+ * INPUTS: None
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: TI_OK or TI_NOK
+ ****************************************************************************/
+
+
+#define ADDRESS_SIZE (sizeof(TI_INT32))
+
+static TI_STATUS hwInit_LoadFwImageSm (TI_HANDLE hHwInit)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TI_STATUS status = TI_OK;
+ ETxnStatus TxnStatus;
+ TI_UINT32 uMaxPartitionSize = PARTITION_DOWN_MEM_SIZE;
+ TTxnStruct* pTxn;
+
+ pHwInit->uTxnIndex = 0;
+
+ while (TI_TRUE)
+ {
+ switch (pHwInit->uLoadStage)
+ {
+ case 0:
+ pHwInit->uLoadStage = 1;
+
+ /* Check the Downloaded FW alignment */
+ if ((pHwInit->uFwLength % ADDRESS_SIZE) != 0)
+ {
+ TRACE1(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Length of downloaded Portion (%d) is not aligned\n",pHwInit->uFwLength);
+ EXCEPT_L (pHwInit, TXN_STATUS_ERROR);
+ }
+
+ TRACE2(pHwInit->hReport, REPORT_SEVERITY_INIT , "Image addr=0x%x, Len=0x%x\n", pHwInit->pFwBuf, pHwInit->uFwLength);
+
+ SET_FW_LOAD_PARTITION(pHwInit->aPartition,pHwInit->uFwAddress)
+ /* Set bus memory partition to current download area */
+ hwInit_SetPartition (pHwInit,pHwInit->aPartition);
+ status = TI_OK;
+ break;
+
+ case 1:
+
+ pHwInit->uLoadStage = 2;
+ /* if initial size is smaller than MAX_SDIO_BLOCK - go strait to stage 4 to write partial block */
+ if (pHwInit->uFwLength < MAX_SDIO_BLOCK)
+ {
+ pHwInit->uLoadStage = 4;
+ }
+
+ pHwInit->uBlockReadNum = 0;
+ pHwInit->uBlockWriteNum = 0;
+ pHwInit->uPartitionLimit = pHwInit->uFwAddress + uMaxPartitionSize;
+
+ break;
+
+ case 2:
+
+ /* Load firmware by blocks */
+ if (pHwInit->uBlockReadNum < (pHwInit->uFwLength / MAX_SDIO_BLOCK))
+ {
+ pHwInit->uLoadStage = 3;
+
+ /* Change partition */
+ /* The +2 is for the last block and the block remainder */
+ if ( ((pHwInit->uBlockWriteNum + 2) * MAX_SDIO_BLOCK + pHwInit->uFwAddress) > pHwInit->uPartitionLimit)
+ {
+ pHwInit->uFwAddress += pHwInit->uBlockWriteNum * MAX_SDIO_BLOCK;
+ /* update uPartitionLimit */
+ pHwInit->uPartitionLimit = pHwInit->uFwAddress + uMaxPartitionSize;
+ SET_FW_LOAD_PARTITION(pHwInit->aPartition,pHwInit->uFwAddress)
+ /* Set bus memory partition to current download area */
+ hwInit_SetPartition (pHwInit,pHwInit->aPartition);
+ TxnStatus = TXN_STATUS_OK;
+ pHwInit->uBlockWriteNum = 0;
+ TRACE1(pHwInit->hReport, REPORT_SEVERITY_INIT , "Change partition to address offset = 0x%x\n", pHwInit->uFwAddress + pHwInit->uBlockWriteNum * MAX_SDIO_BLOCK);
+ EXCEPT_L (pHwInit, TxnStatus);
+ }
+ }
+ else
+ {
+ pHwInit->uLoadStage = 4;
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_INIT , "Load firmware with Portions\n");
+ }
+ break;
+
+ case 3:
+ pHwInit->uLoadStage = 2;
+
+ pHwInit->uTxnIndex = 0;
+
+ /* Copy image block to temporary buffer */
+
+ os_memoryCopy (pHwInit->hOs,
+ (void *)pHwInit->puFwTmpBuf,
+ (void *)(pHwInit->pFwBuf + pHwInit->uBlockReadNum * MAX_SDIO_BLOCK),
+ MAX_SDIO_BLOCK);
+
+ /* Load the block. Save WSPI_PAD_LEN_WRITE space for WSPI bus command */
+ BUILD_HW_INIT_FW_DL_TXN(pHwInit, pTxn, (pHwInit->uFwAddress + pHwInit->uBlockWriteNum * MAX_SDIO_BLOCK),
+ pHwInit->puFwTmpBuf, MAX_SDIO_BLOCK, TXN_DIRECTION_WRITE,
+ (TTxnDoneCb)hwInit_LoadFwImageSm, hHwInit)
+ TxnStatus = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ /* Log ERROR if the transaction returned ERROR */
+ if (TxnStatus == TXN_STATUS_ERROR)
+ {
+ TRACE1(pHwInit->hReport, REPORT_SEVERITY_ERROR , "hwInit_LoadFwImageSm: twIf_Transact retruned status=0x%x\n", TxnStatus);
+ }
+
+ pHwInit->uBlockWriteNum ++;
+ pHwInit->uBlockReadNum ++;
+ EXCEPT_L (pHwInit, TxnStatus);
+ break;
+
+ case 4:
+ pHwInit->uLoadStage = 5;
+
+ pHwInit->uTxnIndex = 0;
+
+ /* If No Last block to write */
+ if ( pHwInit->uFwLength % MAX_SDIO_BLOCK == 0 )
+ {
+ break;
+ }
+
+
+ /* Copy the last image block */
+
+ os_memoryCopy (pHwInit->hOs,
+ (void *)pHwInit->puFwTmpBuf,
+ (void *)(pHwInit->pFwBuf + pHwInit->uBlockReadNum * MAX_SDIO_BLOCK),
+ pHwInit->uFwLength % MAX_SDIO_BLOCK);
+
+ /* Load the last block */
+ BUILD_HW_INIT_FW_DL_TXN(pHwInit, pTxn, (pHwInit->uFwAddress + pHwInit->uBlockWriteNum * MAX_SDIO_BLOCK),
+ pHwInit->puFwTmpBuf, (pHwInit->uFwLength % MAX_SDIO_BLOCK), TXN_DIRECTION_WRITE,
+ (TTxnDoneCb)hwInit_LoadFwImageSm, hHwInit)
+ TxnStatus = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ if (TxnStatus == TXN_STATUS_ERROR)
+ {
+ TRACE1(pHwInit->hReport, REPORT_SEVERITY_ERROR , "hwInit_LoadFwImageSm: last block retruned status=0x%x\n", TxnStatus);
+ }
+
+ EXCEPT_L (pHwInit, TxnStatus);
+ break;
+
+ case 5:
+ pHwInit->uLoadStage = 0;
+
+ /*If end of overall FW Download Process: Finalize download (run firmware)*/
+ if ( pHwInit->bFwBufLast == TI_TRUE )
+ {
+ /* The download has completed */
+ WLAN_OS_REPORT (("Finished downloading firmware.\n"));
+ status = hwInit_FinalizeDownloadSm (hHwInit);
+ }
+ /* Have to wait to more FW Portions */
+ else
+ {
+ /* Call the upper layer callback */
+ if ( pHwInit->fFinalizeDownload != NULL )
+ {
+ (pHwInit->fFinalizeDownload) (pHwInit->hFinalizeDownload);
+ }
+
+ status = TI_OK;
+ }
+ return status;
+
+ } /* End switch */
+
+ } /* End while */
+
+} /* hwInit_LoadFwImageSm() */
+
+#define READ_TOP_REG_LOOP 32
+
+/****************************************************************************
+ * hwInit_ReadRadioParamsSm ()
+ ****************************************************************************
+ * DESCRIPTION: hwInit_ReadRadioParamsSm
+ * INPUTS: None
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: TI_OK or TI_NOK
+ ****************************************************************************/
+TI_STATUS hwInit_ReadRadioParamsSm (TI_HANDLE hHwInit)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TTwd *pTWD = (TTwd *)pHwInit->hTWD;
+ IniFileGeneralParam *pGenParams = &DB_GEN(pTWD->hCmdBld);
+ TI_UINT32 val= 0, value;
+ TI_UINT32 add = FUNC7_SEL;
+ TI_UINT32 retAddress;
+ TTxnStruct *pTxn;
+ TI_STATUS status = 0;
+
+ while (TI_TRUE)
+ {
+ switch (pHwInit->uRegStage)
+ {
+ case 0:
+ pHwInit->uRegStage = 1;
+ pHwInit->uTxnIndex++;
+
+ /*
+ * Select GPIO over Debug for BT_FUNC7 clear bit 17
+ */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, GPIO_SELECT, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_ReadRadioParamsSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+
+ case 1:
+ pHwInit->uRegStage ++;
+ pHwInit->uRegLoop = 0;
+
+ /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */
+ val = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+ val &= 0xFFFDFFFF; /*clear bit 17*/
+ /* Now we can zero the index */
+ pHwInit->uTxnIndex = 0;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, GPIO_SELECT, val,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ pHwInit->uRegData = FUNC7_SEL;
+
+ continue;
+
+ case 2:
+ pHwInit->uRegStage ++;
+ add = pHwInit->uRegData;
+
+ /* Select GPIO over Debug for BT_FUNC7*/
+ retAddress = (TI_UINT32)(add / 2);
+ val = (retAddress & 0x7FF);
+ val |= BIT_16 | BIT_17;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, val,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x2,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ continue;
+
+ case 3:
+ pHwInit->uRegStage ++;
+ pHwInit->uTxnIndex++;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_DATA_RD, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_ReadRadioParamsSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+
+
+ case 4:
+ val = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+ pHwInit->uTxnIndex = 0;
+ if (val & BIT_18)
+ {
+ if ((val & BIT_16) && (!(val & BIT_17)))
+ {
+ pHwInit->uRegStage ++;
+ pHwInit->uRegLoop = 0;
+
+ }
+ else
+ {
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "hwInit_ReadRadioParamsSm: can't writing bt_func7_sel\n");
+ TWD_FinalizeFEMRead(pHwInit->hTWD);
+
+ return TI_NOK;
+ }
+ }
+ else
+ {
+ if (pHwInit->uRegLoop < READ_TOP_REG_LOOP)
+ {
+ pHwInit->uRegStage = 3;
+ pHwInit->uRegLoop++;
+ }
+ else
+ {
+
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Timeout waiting for writing bt_func7_sel\n");
+ TWD_FinalizeFEMRead(pHwInit->hTWD);
+
+ return TI_NOK;
+
+ }
+ }
+
+ continue;
+
+ case 5:
+
+ pHwInit->uRegStage ++;
+ add = pHwInit->uRegData;
+ retAddress = (TI_UINT32)(add / 2);
+ value = (retAddress & 0x7FF);
+ value |= BIT_16 | BIT_17;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, value,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ if (pHwInit->uRegSeqStage == 0)
+ {
+ if (pHwInit->uRegData == FUNC7_SEL)
+ value = (val | 0x600);
+ else
+ value = (val | 0x1000);
+ }
+ else
+ {
+ if (pHwInit->uRegData == FUNC7_SEL)
+ value = (val & 0xF8FF);
+ else
+ value = (val & 0xCFFF);
+
+ }
+
+ value &= 0xFFFF;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_WDATA, value,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x1,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, (TTxnDoneCb)hwInit_ReadRadioParamsSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ if ((pHwInit->uRegData == FUNC7_SEL)&& (pHwInit->uRegSeqStage == 0))
+ {
+ pHwInit->uRegData = FUNC7_PULL;
+ pHwInit->uRegStage = 2;
+ }
+ else
+ {
+ if ((pHwInit->uRegData == FUNC7_PULL)&& (pHwInit->uRegSeqStage == 1))
+ {
+ pHwInit->uRegData = FUNC7_SEL;
+ pHwInit->uRegStage = 2;
+ }
+ }
+
+ EXCEPT (pHwInit, status)
+ continue;
+
+ case 6:
+
+ if (pHwInit->uRegSeqStage == 1)
+ {
+ pHwInit->uRegStage = 8;
+ }
+ else
+ {
+ pHwInit->uRegStage ++;
+ pHwInit->uTxnIndex++;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, GPIO_OE_RADIO, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_ReadRadioParamsSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+ }
+ continue;
+
+ case 7:
+
+ pHwInit->uRegStage ++;
+
+ /* We don't zero pHwInit->uTxnIndex at the begining because we need it's value to the next transaction */
+ val = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+ val |= 0x00020000;
+
+ pHwInit->uTxnIndex = 0;
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, GPIO_OE_RADIO, val,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, GPIO_IN, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_ReadRadioParamsSm, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+
+
+ case 8:
+
+ if (pHwInit->uRegSeqStage == 0)
+ {
+ val = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+ val &= 0x20000;
+ if(val)
+ {
+ pGenParams->TXBiPFEMManufacturer = FEM_TRIQUINT_TYPE_E;
+ }
+ else
+ {
+ pGenParams->TXBiPFEMManufacturer = FEM_RFMD_TYPE_E;
+ }
+ WLAN_OS_REPORT (("hwInit_ReadRadioParamsSm FEM Type %d \n",pGenParams->TXBiPFEMManufacturer));
+ pHwInit->uTxnIndex = 0;
+ pHwInit->uRegSeqStage = 1;
+ pHwInit->uRegStage = 2;
+ pHwInit->uRegData = FUNC7_PULL;
+ continue;
+ }
+ else
+ {
+
+ WLAN_OS_REPORT (("hwInit_ReadRadioParamsSm Ended Successfully\n"));
+
+ TWD_FinalizeFEMRead(pHwInit->hTWD);
+
+ return TI_OK;
+
+ }
+
+ } /* End switch */
+
+ } /* End while */
+
+}
+
+
+/****************************************************************************
+ * hwInit_ReadRadioParams()
+ ****************************************************************************
+ * DESCRIPTION: hwInit_ReadRadioParamsSm
+ * initalizie hwInit_ReadRadioParamsSm parmaeters
+ ****************************************************************************/
+
+TI_STATUS hwInit_ReadRadioParams (TI_HANDLE hHwInit)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+
+ pHwInit->uRegStage = 0;
+ pHwInit->uRegSeqStage = 0;
+
+ return hwInit_ReadRadioParamsSm (hHwInit);
+}
+
+/****************************************************************************
+ * hwInit_InitPoalrity()
+ ****************************************************************************
+ * DESCRIPTION: hwInit_ReadRadioParamsSm
+ * initalizie hwInit_ReadRadioParamsSm parmaeters
+ ****************************************************************************/
+
+TI_STATUS hwInit_InitPolarity(TI_HANDLE hHwInit)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+
+ pHwInit->uRegStage = 0;
+ pHwInit->uRegSeqStage = 0;
+
+ return hwInit_WriteIRQPolarity (hHwInit);
+}
+
+
+
+/****************************************************************************
+ * hwInit_WriteIRQPolarity ()
+ ****************************************************************************
+ * DESCRIPTION: hwInit_WriteIRQPolarity
+ * INPUTS: None
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: TI_OK or TI_NOK
+ ****************************************************************************/
+ TI_STATUS hwInit_WriteIRQPolarity(TI_HANDLE hHwInit)
+ {
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TI_UINT32 Address = 0,val = 0,value = 0;
+ TTxnStruct *pTxn;
+ TI_STATUS status = 0;
+
+ /* To write to a top level address from the WLAN IP:
+ Write the top level address to the OCP_POR_CTR register.
+ 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
+ Write the data to the OCP_POR_WDATA register
+ Write 0x1 to the OCP_CMD register.
+
+ To read from a top level address:
+ Write the top level address to the OCP_POR_CTR register.
+ 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
+ Write 0x2 to the OCP_CMD register.
+ Poll bit [18] of OCP_DATA_RD for data valid indication
+ Check bits 17:16 of OCP_DATA_RD:
+ 00 – no response
+ 01 – data valid / accept
+ 10 – request failed
+ 11 – response error
+ Read the data from the OCP_DATA_RD register
+ */
+
+ while (TI_TRUE)
+ {
+ switch (pHwInit->uRegStage)
+ {
+ case 0:
+ pHwInit->uRegStage = 1;
+ pHwInit->uTxnIndex++;
+ pHwInit->uRegLoop = 0;
+
+ /* first read the IRQ Polarity register*/
+ Address = (TI_UINT32)(FN0_CCCR_REG_32 / 2);
+ val = (Address & 0x7FF);
+ val |= BIT_16 | BIT_17;
+
+ /* Write IRQ Polarity address register to OCP_POR_CTR*/
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, val,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ /* Write read (2)command to the OCP_CMD register. */
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x2,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ continue;
+
+ case 1:
+ pHwInit->uRegStage ++;
+ pHwInit->uTxnIndex++;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_DATA_RD, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_WriteIRQPolarity, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, status)
+
+
+ case 2:
+ /* get the value from IRQ Polarity register*/
+ val = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+
+ pHwInit->uTxnIndex = 0;
+
+ /*Poll bit 18 of OCP_DATA_RD for data valid indication*/
+ if (val & BIT_18)
+ {
+ if ((val & BIT_16) && (!(val & BIT_17)))
+ {
+ pHwInit->uRegStage ++;
+ pHwInit->uRegLoop = 0;
+
+ }
+ else
+ {
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "can't writing bt_func7_sel\n");
+ TWD_FinalizePolarityRead(pHwInit->hTWD);
+
+ return TI_NOK;
+ }
+ }
+ else
+ {
+ if (pHwInit->uRegLoop < READ_TOP_REG_LOOP)
+ {
+ pHwInit->uRegStage = 1;
+ pHwInit->uRegLoop++;
+ }
+ else
+ {
+
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Timeout waiting for writing bt_func7_sel\n");
+ TWD_FinalizePolarityRead(pHwInit->hTWD);
+
+ return TI_NOK;
+
+ }
+ }
+
+ continue;
+
+
+ case 3:
+ /* second, write new value of IRQ polarity due to complation flag 1 - active low, 0 - active high*/
+ pHwInit->uRegStage ++;
+ Address = (TI_UINT32)(FN0_CCCR_REG_32 / 2);
+ value = (Address & 0x7FF);
+ value |= BIT_16 | BIT_17;
+
+ /* Write IRQ Polarity address register to OCP_POR_CTR*/
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, value,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+#ifdef USE_IRQ_ACTIVE_HIGH
+ val |= 0x0<<1;
+
+#else
+ val |= 0x01<<1;
+#endif
+
+ /* Write the new IRQ polarity value to the OCP_POR_WDATA register */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_WDATA, val,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ /* Write write (1)command to the OCP_CMD register. */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x1,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, (TTxnDoneCb)hwInit_WriteIRQPolarity, hHwInit)
+ status = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ EXCEPT (pHwInit, status)
+ continue;
+
+ case 4:
+
+ TWD_FinalizePolarityRead(pHwInit->hTWD);
+
+ return TI_OK;
+
+
+
+ } /* End switch */
+
+ } /* End while */
+
+ }
+
+
+/****************************************************************************
+ * hwInit_InitTopRegisterWrite()
+ ****************************************************************************
+ * DESCRIPTION: hwInit_InitTopRegisterWrite
+ * initalizie hwInit_TopRegisterWrite SM parmaeters
+ ****************************************************************************/
+
+TI_STATUS hwInit_InitTopRegisterWrite(TI_HANDLE hHwInit, TI_UINT32 uAddress, TI_UINT32 uValue)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+
+ pHwInit->uTopStage = 0;
+ uAddress = (TI_UINT32)(uAddress / 2);
+ uAddress = (uAddress & 0x7FF);
+ uAddress|= BIT_16 | BIT_17;
+ pHwInit->uTopRegAddr = uAddress;
+ pHwInit->uTopRegValue = uValue & 0xffff;
+
+ return hwInit_TopRegisterWrite (hHwInit);
+}
+
+
+/****************************************************************************
+ * hwInit_WriteTopRegister ()
+ ****************************************************************************
+ * DESCRIPTION: Generic function that writes to the top registers area
+ * INPUTS: None
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: TI_OK or TI_NOK
+ ****************************************************************************/
+ TI_STATUS hwInit_TopRegisterWrite(TI_HANDLE hHwInit)
+ {
+ /* To write to a top level address from the WLAN IP:
+ Write the top level address to the OCP_POR_CTR register.
+ 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
+ Write the data to the OCP_POR_WDATA register
+ Write 0x1 to the OCP_CMD register.
+ */
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TTxnStruct *pTxn;
+
+ while (TI_TRUE)
+ {
+ switch (pHwInit->uTopStage)
+ {
+ case 0:
+ pHwInit->uTopStage = 1;
+
+ pHwInit->uTxnIndex++;
+ /* Write the address to OCP_POR_CTR*/
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, pHwInit->uTopRegAddr,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+ /* Write the new value to the OCP_POR_WDATA register */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_WDATA, pHwInit->uTopRegValue,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+ /* Write write (1)command to the OCP_CMD register. */
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x1,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, (TTxnDoneCb)hwInit_TopRegisterWrite, hHwInit)
+ pHwInit->uTopStatus = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+
+ EXCEPT (pHwInit, pHwInit->uTopStatus)
+ continue;
+
+ case 1:
+
+ pHwInit->uTxnIndex = 0;
+
+ if (pHwInit->uTopStatus == TXN_STATUS_PENDING) {
+ hwInit_BootSm (hHwInit);
+ }
+
+ return TI_OK;
+
+ } /* End switch */
+
+ } /* End while */
+
+ }
+
+
+ /****************************************************************************
+ * hwInit_InitTopRegisterRead()
+ ****************************************************************************
+ * DESCRIPTION: hwInit_InitTopRegisterRead
+ * initalizie hwInit_InitTopRegisterRead SM parmaeters
+ ****************************************************************************/
+
+TI_STATUS hwInit_InitTopRegisterRead(TI_HANDLE hHwInit, TI_UINT32 uAddress)
+{
+ THwInit *pHwInit = (THwInit *)hHwInit;
+
+ pHwInit->uTopStage = 0;
+ uAddress = (TI_UINT32)(uAddress / 2);
+ uAddress = (uAddress & 0x7FF);
+ uAddress|= BIT_16 | BIT_17;
+ pHwInit->uTopRegAddr = uAddress;
+
+ return hwInit_TopRegisterRead (hHwInit);
+}
+
+
+/****************************************************************************
+ * hwInit_TopRegisterRead ()
+ ****************************************************************************
+ * DESCRIPTION: Generic function that reads to the top registers area
+ * INPUTS: None
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: TI_OK or TI_NOK
+ ****************************************************************************/
+ TI_STATUS hwInit_TopRegisterRead(TI_HANDLE hHwInit)
+ {
+ /*
+ To read from a top level address:
+ Write the top level address to the OCP_POR_CTR register.
+ 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
+ Write 0x2 to the OCP_CMD register.
+ Poll bit [18] of OCP_DATA_RD for data valid indication
+ Check bits 17:16 of OCP_DATA_RD:
+ 00 – no response
+ 01 – data valid / accept
+ 10 – request failed
+ 11 – response error
+ Read the data from the OCP_DATA_RD register
+ */
+
+ THwInit *pHwInit = (THwInit *)hHwInit;
+ TTxnStruct *pTxn;
+
+ while (TI_TRUE)
+ {
+ switch (pHwInit->uTopStage)
+ {
+ case 0:
+ pHwInit->uTopStage = 1;
+ pHwInit->uTxnIndex++;
+ pHwInit->uRegLoop = 0;
+
+ /* Write the address to OCP_POR_CTR*/
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_POR_CTR, pHwInit->uTopRegAddr,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ pHwInit->uTxnIndex++;
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_CMD, 0x2,
+ REGISTER_SIZE, TXN_DIRECTION_WRITE, NULL, NULL)
+ twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ continue;
+
+ case 1:
+ pHwInit->uTopStage ++;
+ pHwInit->uTxnIndex++;
+
+ BUILD_HW_INIT_TXN_DATA(pHwInit, pTxn, OCP_DATA_RD, 0,
+ REGISTER_SIZE, TXN_DIRECTION_READ, (TTxnDoneCb)hwInit_TopRegisterRead, hHwInit)
+ pHwInit->uTopStatus = twIf_Transact(pHwInit->hTwIf, pTxn);
+
+ EXCEPT (pHwInit, pHwInit->uTopStatus)
+
+ case 2:
+ /* get the value from IRQ Polarity register*/
+ pHwInit->uTopRegValue = *((TI_UINT32*)(pHwInit->aHwInitTxn[pHwInit->uTxnIndex].pData));
+
+ pHwInit->uTxnIndex = 0;
+
+ /*Poll bit 18 of OCP_DATA_RD for data valid indication*/
+ if (pHwInit->uTopRegValue & BIT_18)
+ {
+ if ((pHwInit->uTopRegValue & BIT_16) && (!(pHwInit->uTopRegValue & BIT_17)))
+ {
+ pHwInit->uTopRegValue &= 0xffff;
+
+ pHwInit->uTxnIndex = 0;
+ pHwInit->uRegLoop = 0;
+ if (pHwInit->uTopStatus == TXN_STATUS_PENDING) {
+ hwInit_BootSm (hHwInit);
+ }
+ return TI_OK;
+ }
+ else
+ {
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "can't writing bt_func7_sel\n");
+ if (pHwInit->uTopStatus == TXN_STATUS_PENDING) {
+ hwInit_BootSm (hHwInit);
+ }
+ return TI_NOK;
+ }
+ }
+ else
+ {
+ if (pHwInit->uRegLoop < READ_TOP_REG_LOOP)
+ {
+ pHwInit->uTopStage = 1;
+ pHwInit->uRegLoop++;
+ }
+ else
+ {
+ TRACE0(pHwInit->hReport, REPORT_SEVERITY_ERROR , "Timeout waiting for writing bt_func7_sel\n");
+ if (pHwInit->uTopStatus == TXN_STATUS_PENDING) {
+ hwInit_BootSm (hHwInit);
+ }
+ return TI_NOK;
+ }
+ }
+
+ continue;
+
+ } /* End switch */
+
+ } /* End while */
+
+ }
+
+
+#ifndef _VLCT_
+ /****************************************************************************
+ * hwInit_StallTimerCb ()
+ ****************************************************************************
+ * DESCRIPTION: CB timer function in fTimerFunction format that calls hwInit_StallTimerCb
+ * INPUTS: TI_HANDLE hHwInit
+ *
+ * OUTPUT: None
+ *
+ * RETURNS: None
+ ****************************************************************************/
+ static void hwInit_StallTimerCb (TI_HANDLE hHwInit)
+ {
+ hwInit_FinalizeDownloadSm(hHwInit);
+ }
+#endif