| /* |
| * WspiBusDrv.c |
| * |
| * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved. |
| * All rights reserved. |
| * |
| * 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. |
| */ |
| |
| |
| /** \file WspiBusDrv.c |
| * \brief The WSPI bus driver upper layer. Platform independent. |
| * Uses the SpiAdapter API. |
| * Introduces a generic bus-independent API upwards. |
| * |
| * \see BusDrv.h, SpiAdapter.h, SpiAdapter.c |
| */ |
| |
| #include "tidef.h" |
| #include "report.h" |
| #include "osApi.h" |
| #include "wspi.h" |
| #include "BusDrv.h" |
| #include "TxnDefs.h" |
| #define __FILE_ID__ FILE_ID_124 |
| |
| /************************************************************************ |
| * Defines |
| ************************************************************************/ |
| #define WSPI_FIXED_BUSY_LEN 1 |
| #define WSPI_INIT_CMD_MASK 0 |
| |
| |
| /************************************************************************ |
| * Types |
| ************************************************************************/ |
| |
| /* The busDrv module Object */ |
| typedef struct _TBusDrvObj |
| { |
| TI_HANDLE hOs; |
| TI_HANDLE hReport; |
| TI_HANDLE hDriver; |
| TI_HANDLE hWspi; |
| |
| TTxnDoneCb fTxnDoneCb; /* The callback to call upon full transaction completion. */ |
| TI_HANDLE hCbHandle; /* The callback handle */ |
| TTxnStruct * pCurrTxn; /* The transaction currently being processed */ |
| TI_STATUS eCurrTxnStatus; /* COMPLETE, PENDING or ERROR */ |
| TI_UINT32 uCurrTxnBufsCount; |
| TI_BOOL bPendingByte; |
| TTxnDoneCb fTxnConnectDoneCb; /* The callback to call upon full transaction completion. */ |
| |
| |
| } TBusDrvObj; |
| |
| |
| /************************************************************************ |
| * Internal functions prototypes |
| ************************************************************************/ |
| |
| static void asyncEnded_CB(TI_HANDLE hBusTxn, int status); |
| static void ConnectDone_CB(TI_HANDLE hBusDrv, int status); |
| |
| /************************************************************************ |
| * |
| * Module functions implementation |
| * |
| ************************************************************************/ |
| |
| /** |
| * \fn busDrv_Create |
| * \brief Create the module |
| * |
| * Allocate and clear the module's object. |
| * |
| * \note |
| * \param hOs - Handle to Os Abstraction Layer |
| * \return Handle of the allocated object, NULL if allocation failed |
| * \sa busDrv_Destroy |
| */ |
| TI_HANDLE busDrv_Create (TI_HANDLE hOs) |
| { |
| TI_HANDLE hBusDrv; |
| TBusDrvObj *pBusDrv; |
| |
| hBusDrv = os_memoryAlloc(hOs, sizeof(TBusDrvObj)); |
| if (hBusDrv == NULL) |
| return NULL; |
| |
| pBusDrv = (TBusDrvObj *)hBusDrv; |
| |
| os_memoryZero(hOs, hBusDrv, sizeof(TBusDrvObj)); |
| |
| pBusDrv->hOs = hOs; |
| |
| // addapt to WSPI |
| |
| pBusDrv->hWspi= WSPI_Open(hOs); |
| |
| return pBusDrv; |
| } |
| |
| |
| /** |
| * \fn busDrv_Destroy |
| * \brief Destroy the module. |
| * |
| * Close SPI lower bus driver and free the module's object. |
| * |
| * \note |
| * \param The module's object |
| * \return TI_OK on success or TI_NOK on failure |
| * \sa busDrv_Create |
| */ |
| TI_STATUS busDrv_Destroy (TI_HANDLE hBusDrv) |
| { |
| TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv; |
| |
| if (pBusDrv) |
| { |
| // addapt to WSPI |
| WSPI_Close(pBusDrv->hWspi); |
| os_memoryFree (pBusDrv->hOs, pBusDrv, sizeof(TBusDrvObj)); |
| } |
| return TI_OK; |
| } |
| |
| |
| /**************************************************************************** |
| * busDrv_Init |
| **************************************************************************** |
| * DESCRIPTION: config the module. |
| * |
| * INPUTS: hBusDrv - handle to the module context |
| * hReport - handle to report module context that is used when we output debug messages |
| * CBFunc - The callback to call upon transaction complete (calls the tasklet). |
| * CBArg - The handle for the CBFunc. |
| * |
| * OUTPUT: none. |
| * |
| * RETURNS: one of the error codes (0 => TI_OK) |
| ****************************************************************************/ |
| void busDrv_Init (TI_HANDLE hBusDrv, |
| TI_HANDLE hReport) |
| { |
| TBusDrvObj *pBusDrv = (TBusDrvObj*) hBusDrv; |
| |
| |
| |
| pBusDrv->hReport = hReport; |
| |
| |
| |
| } |
| |
| |
| |
| |
| |
| |
| /** |
| * \fn busDrv_ConnectBus |
| * \brief Configure bus driver |
| * |
| * Called by TxnQ. |
| * Configure the bus driver with its connection configuration (such as baud-rate, bus width etc) |
| * and establish the physical connection. |
| * Done once upon init (and not per functional driver startup). |
| * |
| * \note |
| * \param hBusDrv - The module's object |
| * \param pBusDrvCfg - A union used for per-bus specific configuration. |
| * \param fCbFunc - CB function for Async transaction completion (after all txn parts are completed). |
| * \param hCbArg - The CB function handle |
| * \return TI_OK / TI_NOK |
| * \sa |
| */ |
| TI_STATUS busDrv_ConnectBus (TI_HANDLE hBusDrv, |
| TBusDrvCfg *pBusDrvCfg, |
| TBusDrvTxnDoneCb fCbFunc, |
| TI_HANDLE hCbArg, |
| TBusDrvTxnDoneCb fConnectCbFunc |
| ) |
| { |
| TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv; |
| int iStatus; |
| WSPIConfig_t wspi_config; |
| WSPI_CB_T cb; |
| |
| /* Save the parameters (TxnQ callback for TxnDone events) */ |
| pBusDrv->fTxnDoneCb = fCbFunc; |
| pBusDrv->hCbHandle = hCbArg; |
| pBusDrv->fTxnConnectDoneCb = fConnectCbFunc; |
| |
| /* Configure the WSPI driver parameters */ |
| |
| wspi_config.isFixedAddress = TI_FALSE; |
| wspi_config.fixedBusyLength = WSPI_FIXED_BUSY_LEN; |
| wspi_config.mask = WSPI_INIT_CMD_MASK; |
| |
| cb.CBFunc = ConnectDone_CB;/* The BusTxn callback called upon Async transaction end. */ |
| cb.CBArg = hBusDrv; /* The handle for the BusDrv. */ |
| |
| /* Configure the WSPI module */ |
| iStatus = WSPI_Configure(pBusDrv->hWspi, pBusDrv->hReport, &wspi_config, &cb); |
| |
| |
| if ((iStatus == 0) || (iStatus == 1)) |
| { |
| TRACE1 (pBusDrv->hReport, REPORT_SEVERITY_INIT, "busDrv_ConnectBus: called Status %d\n",iStatus); |
| |
| |
| TRACE2 (pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_ConnectBus: Successful Status %d\n",iStatus); |
| return TI_OK; |
| } |
| else |
| { |
| TRACE2(pBusDrv->hReport, REPORT_SEVERITY_ERROR, "busDrv_ConnectBus: Status = %d,\n", iStatus); |
| return TI_NOK; |
| } |
| } |
| /** |
| * \fn busDrv_DisconnectBus |
| * \brief Disconnect SDIO driver |
| * |
| * Called by TxnQ. Disconnect the SDIO driver. |
| * |
| * \note |
| * \param hBusDrv - The module's object |
| * \return TI_OK / TI_NOK |
| * \sa |
| */ |
| TI_STATUS busDrv_DisconnectBus (TI_HANDLE hBusDrv) |
| { |
| return TI_OK; |
| } |
| |
| |
| /** |
| * \fn busDrv_Transact |
| * \brief Process transaction |
| * |
| * Called by the TxnQ module to initiate a new transaction. |
| * Call either write or read functions according to Txn direction field. |
| * |
| * \note It's assumed that this function is called only when idle (i.e. previous Txn is done). |
| * \param hBusDrv - The module's object |
| * \param pTxn - The transaction object |
| * \return COMPLETE if Txn completed in this context, PENDING if not, ERROR if failed |
| * \sa busDrv_PrepareTxnParts, busDrv_SendTxnParts |
| */ |
| ETxnStatus busDrv_Transact (TI_HANDLE hBusDrv, TTxnStruct *pTxn) |
| { |
| TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv; |
| WSPI_CB_T cb; |
| TI_UINT8 * tempReadBuff; |
| TI_UINT8 * tempWriteBuff; |
| pBusDrv->pCurrTxn = pTxn; |
| pBusDrv->eCurrTxnStatus = TXN_STATUS_COMPLETE; /* The Txn is Sync as long as it continues in this context */ |
| cb.CBFunc = asyncEnded_CB; /* The BusTxn callback called upon Async transaction end. */ |
| cb.CBArg = hBusDrv; /* The handle for the BusTxnCB. */ |
| |
| /* If write command */ |
| if (TXN_PARAM_GET_DIRECTION(pTxn) == TXN_DIRECTION_WRITE) |
| { |
| |
| //WLAN_REPORT_INIT(pBusDrv->hReport, TNETW_DRV_MODULE_LOG, |
| // ("busDrv_Transact: Write to pTxn->uHwAddr %x\n", pTxn->uHwAddr )); |
| |
| |
| /*WLAN_REPORT_ERROR(pBusDrv->hReport, BUS_DRV_MODULE_LOG, |
| ("busDrv_Transact: Buff= %x, Len=%d\n", pTxn->aBuf[0], pTxn->aLen[0]));*/ |
| /*1.write memory*/ |
| /* Decrease the data pointer to the beginning of the WSPI padding */ |
| tempWriteBuff = pTxn->aBuf[0]; |
| tempWriteBuff -= WSPI_PAD_LEN_WRITE; |
| |
| /* Write the data to the WSPI in Aync mode (not completed in the current context). */ |
| pBusDrv->eCurrTxnStatus = WSPI_WriteAsync(pBusDrv->hWspi, pTxn->uHwAddr,tempWriteBuff,pTxn->aLen[0], &cb, TI_TRUE, TI_TRUE,TXN_PARAM_GET_FIXED_ADDR(pTxn)); |
| |
| } |
| |
| /* If read command */ |
| else |
| { |
| //WLAN_REPORT_INIT(pBusDrv->hReport, TNETW_DRV_MODULE_LOG, |
| // ("busDrv_Transact: Read from pTxn->uHwAddr %x pTxn %x \n", pTxn->uHwAddr,pTxn)); |
| |
| /*1. Read mem */ |
| /* Decrease the tempReadBuff pointer to the beginning of the WSPI padding */ |
| tempReadBuff = pTxn->aBuf[0]; |
| tempReadBuff -= WSPI_PAD_LEN_READ; |
| /* Read the required data from the WSPI in Aync mode (not completed in the current context). */ |
| pBusDrv->eCurrTxnStatus = WSPI_ReadAsync(pBusDrv->hWspi, pTxn->uHwAddr,tempReadBuff,pTxn->aLen[0], &cb, TI_TRUE, TI_TRUE,TXN_PARAM_GET_FIXED_ADDR(pTxn)); |
| |
| |
| } |
| |
| /* return transaction status - COMPLETE, PENDING or ERROR */ |
| return (pBusDrv->eCurrTxnStatus == WSPI_TXN_COMPLETE ? TXN_STATUS_COMPLETE : |
| (pBusDrv->eCurrTxnStatus == WSPI_TXN_PENDING ? TXN_STATUS_PENDING : TXN_STATUS_ERROR)); |
| |
| |
| } |
| |
| |
| /**************************************************************************** |
| * asyncEnded_CB() |
| **************************************************************************** |
| * DESCRIPTION: |
| * Called back by the WSPI driver from Async transaction end interrupt (ISR context). |
| * Calls the upper layers callback. |
| * |
| * INPUTS: status - |
| * |
| * OUTPUT: None |
| * |
| * RETURNS: None |
| ****************************************************************************/ |
| static void asyncEnded_CB(TI_HANDLE hBusDrv, int status) |
| { |
| TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv; |
| /* If the last transaction failed, call failure CB and exit. */ |
| if (status != 0) |
| { |
| TRACE2(pBusDrv->hReport, REPORT_SEVERITY_ERROR, "asyncEnded_CB : Status = %d, fTxnDoneCb = 0x%x\n", status,pBusDrv->fTxnDoneCb); |
| |
| TXN_PARAM_SET_STATUS(pBusDrv->pCurrTxn, TXN_PARAM_STATUS_ERROR); |
| } |
| else |
| { |
| TRACE2(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION,"asyncEnded_CB: Successful async cb done pBusDrv->pCurrTxn %x\n", pBusDrv->pCurrTxn); |
| } |
| |
| /* Call the upper layer CB */ |
| |
| pBusDrv->fTxnDoneCb(pBusDrv->hCbHandle,pBusDrv->pCurrTxn); |
| } |
| |
| |
| /**************************************************************************** |
| * ConnectDone_CB() |
| **************************************************************************** |
| * DESCRIPTION: |
| * Called back by the WSPI driver from Async transaction end interrupt (ISR context). |
| * Calls the upper layers callback. |
| * |
| * INPUTS: status - |
| * |
| * OUTPUT: None |
| * |
| * RETURNS: None |
| ****************************************************************************/ |
| static void ConnectDone_CB(TI_HANDLE hBusDrv, int status) |
| { |
| TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv; |
| /* If the last transaction failed, call failure CB and exit. */ |
| if (status != 0) |
| { |
| TRACE2(pBusDrv->hReport, REPORT_SEVERITY_ERROR, "ConnectDone_CB : Status = %d, fTxnConnectDoneCb = 0x%x\n", status,pBusDrv->fTxnConnectDoneCb); |
| |
| TXN_PARAM_SET_STATUS(pBusDrv->pCurrTxn, TXN_PARAM_STATUS_ERROR); |
| } |
| else |
| { |
| TRACE1 (pBusDrv->hReport, REPORT_SEVERITY_INIT, "ConnectDone_CB: Successful Connect Async cb done \n"); |
| } |
| |
| /* Call the upper layer CB */ |
| |
| pBusDrv->fTxnConnectDoneCb(pBusDrv->hCbHandle,pBusDrv->pCurrTxn); |
| } |
| |
| |