1/* 2 * WspiBusDrv.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/** \file WspiBusDrv.c 36 * \brief The WSPI bus driver upper layer. Platform independent. 37 * Uses the SpiAdapter API. 38 * Introduces a generic bus-independent API upwards. 39 * 40 * \see BusDrv.h, SpiAdapter.h, SpiAdapter.c 41 */ 42 43#include "tidef.h" 44#include "report.h" 45#include "osApi.h" 46#include "wspi.h" 47#include "BusDrv.h" 48#include "TxnDefs.h" 49#define __FILE_ID__ FILE_ID_124 50 51/************************************************************************ 52 * Defines 53 ************************************************************************/ 54#define WSPI_FIXED_BUSY_LEN 1 55#define WSPI_INIT_CMD_MASK 0 56 57 58/************************************************************************ 59 * Types 60 ************************************************************************/ 61 62/* The busDrv module Object */ 63typedef struct _TBusDrvObj 64{ 65 TI_HANDLE hOs; 66 TI_HANDLE hReport; 67 TI_HANDLE hDriver; 68 TI_HANDLE hWspi; 69 70 TTxnDoneCb fTxnDoneCb; /* The callback to call upon full transaction completion. */ 71 TI_HANDLE hCbHandle; /* The callback handle */ 72 TTxnStruct * pCurrTxn; /* The transaction currently being processed */ 73 TI_STATUS eCurrTxnStatus; /* COMPLETE, PENDING or ERROR */ 74 TI_UINT32 uCurrTxnBufsCount; 75 TI_BOOL bPendingByte; 76 TTxnDoneCb fTxnConnectDoneCb; /* The callback to call upon full transaction completion. */ 77 78 79} TBusDrvObj; 80 81 82/************************************************************************ 83 * Internal functions prototypes 84 ************************************************************************/ 85 86static void asyncEnded_CB(TI_HANDLE hBusTxn, int status); 87static void ConnectDone_CB(TI_HANDLE hBusDrv, int status); 88 89/************************************************************************ 90 * 91 * Module functions implementation 92 * 93 ************************************************************************/ 94 95/** 96 * \fn busDrv_Create 97 * \brief Create the module 98 * 99 * Allocate and clear the module's object. 100 * 101 * \note 102 * \param hOs - Handle to Os Abstraction Layer 103 * \return Handle of the allocated object, NULL if allocation failed 104 * \sa busDrv_Destroy 105 */ 106TI_HANDLE busDrv_Create (TI_HANDLE hOs) 107{ 108 TI_HANDLE hBusDrv; 109 TBusDrvObj *pBusDrv; 110 111 hBusDrv = os_memoryAlloc(hOs, sizeof(TBusDrvObj)); 112 if (hBusDrv == NULL) 113 return NULL; 114 115 pBusDrv = (TBusDrvObj *)hBusDrv; 116 117 os_memoryZero(hOs, hBusDrv, sizeof(TBusDrvObj)); 118 119 pBusDrv->hOs = hOs; 120 121 // addapt to WSPI 122 123 pBusDrv->hWspi= WSPI_Open(hOs); 124 125 return pBusDrv; 126} 127 128 129/** 130 * \fn busDrv_Destroy 131 * \brief Destroy the module. 132 * 133 * Close SPI lower bus driver and free the module's object. 134 * 135 * \note 136 * \param The module's object 137 * \return TI_OK on success or TI_NOK on failure 138 * \sa busDrv_Create 139 */ 140TI_STATUS busDrv_Destroy (TI_HANDLE hBusDrv) 141{ 142 TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv; 143 144 if (pBusDrv) 145 { 146 // addapt to WSPI 147 WSPI_Close(pBusDrv->hWspi); 148 os_memoryFree (pBusDrv->hOs, pBusDrv, sizeof(TBusDrvObj)); 149 } 150 return TI_OK; 151} 152 153 154/**************************************************************************** 155 * busDrv_Init 156 **************************************************************************** 157 * DESCRIPTION: config the module. 158 * 159 * INPUTS: hBusDrv - handle to the module context 160 * hReport - handle to report module context that is used when we output debug messages 161 * CBFunc - The callback to call upon transaction complete (calls the tasklet). 162 * CBArg - The handle for the CBFunc. 163 * 164 * OUTPUT: none. 165 * 166 * RETURNS: one of the error codes (0 => TI_OK) 167 ****************************************************************************/ 168void busDrv_Init (TI_HANDLE hBusDrv, 169 TI_HANDLE hReport) 170{ 171 TBusDrvObj *pBusDrv = (TBusDrvObj*) hBusDrv; 172 173 174 175 pBusDrv->hReport = hReport; 176 177 178 179} 180 181 182 183 184 185 186/** 187 * \fn busDrv_ConnectBus 188 * \brief Configure bus driver 189 * 190 * Called by TxnQ. 191 * Configure the bus driver with its connection configuration (such as baud-rate, bus width etc) 192 * and establish the physical connection. 193 * Done once upon init (and not per functional driver startup). 194 * 195 * \note 196 * \param hBusDrv - The module's object 197 * \param pBusDrvCfg - A union used for per-bus specific configuration. 198 * \param fCbFunc - CB function for Async transaction completion (after all txn parts are completed). 199 * \param hCbArg - The CB function handle 200 * \return TI_OK / TI_NOK 201 * \sa 202 */ 203TI_STATUS busDrv_ConnectBus (TI_HANDLE hBusDrv, 204 TBusDrvCfg *pBusDrvCfg, 205 TBusDrvTxnDoneCb fCbFunc, 206 TI_HANDLE hCbArg, 207 TBusDrvTxnDoneCb fConnectCbFunc 208 ) 209{ 210 TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv; 211 int iStatus; 212 WSPIConfig_t wspi_config; 213 WSPI_CB_T cb; 214 215 /* Save the parameters (TxnQ callback for TxnDone events) */ 216 pBusDrv->fTxnDoneCb = fCbFunc; 217 pBusDrv->hCbHandle = hCbArg; 218 pBusDrv->fTxnConnectDoneCb = fConnectCbFunc; 219 220 /* Configure the WSPI driver parameters */ 221 222 wspi_config.isFixedAddress = TI_FALSE; 223 wspi_config.fixedBusyLength = WSPI_FIXED_BUSY_LEN; 224 wspi_config.mask = WSPI_INIT_CMD_MASK; 225 226 cb.CBFunc = ConnectDone_CB;/* The BusTxn callback called upon Async transaction end. */ 227 cb.CBArg = hBusDrv; /* The handle for the BusDrv. */ 228 229 /* Configure the WSPI module */ 230 iStatus = WSPI_Configure(pBusDrv->hWspi, pBusDrv->hReport, &wspi_config, &cb); 231 232 233 if ((iStatus == 0) || (iStatus == 1)) 234 { 235 TRACE1 (pBusDrv->hReport, REPORT_SEVERITY_INIT, "busDrv_ConnectBus: called Status %d\n",iStatus); 236 237 238 TRACE2 (pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_ConnectBus: Successful Status %d\n",iStatus); 239 return TI_OK; 240 } 241 else 242 { 243 TRACE2(pBusDrv->hReport, REPORT_SEVERITY_ERROR, "busDrv_ConnectBus: Status = %d,\n", iStatus); 244 return TI_NOK; 245 } 246} 247/** 248 * \fn busDrv_DisconnectBus 249 * \brief Disconnect SDIO driver 250 * 251 * Called by TxnQ. Disconnect the SDIO driver. 252 * 253 * \note 254 * \param hBusDrv - The module's object 255 * \return TI_OK / TI_NOK 256 * \sa 257 */ 258TI_STATUS busDrv_DisconnectBus (TI_HANDLE hBusDrv) 259{ 260 return TI_OK; 261} 262 263 264/** 265 * \fn busDrv_Transact 266 * \brief Process transaction 267 * 268 * Called by the TxnQ module to initiate a new transaction. 269 * Call either write or read functions according to Txn direction field. 270 * 271 * \note It's assumed that this function is called only when idle (i.e. previous Txn is done). 272 * \param hBusDrv - The module's object 273 * \param pTxn - The transaction object 274 * \return COMPLETE if Txn completed in this context, PENDING if not, ERROR if failed 275 * \sa busDrv_PrepareTxnParts, busDrv_SendTxnParts 276 */ 277ETxnStatus busDrv_Transact (TI_HANDLE hBusDrv, TTxnStruct *pTxn) 278{ 279 TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv; 280 WSPI_CB_T cb; 281 TI_UINT8 * tempReadBuff; 282 TI_UINT8 * tempWriteBuff; 283 pBusDrv->pCurrTxn = pTxn; 284 pBusDrv->eCurrTxnStatus = TXN_STATUS_COMPLETE; /* The Txn is Sync as long as it continues in this context */ 285 cb.CBFunc = asyncEnded_CB; /* The BusTxn callback called upon Async transaction end. */ 286 cb.CBArg = hBusDrv; /* The handle for the BusTxnCB. */ 287 288 /* If write command */ 289 if (TXN_PARAM_GET_DIRECTION(pTxn) == TXN_DIRECTION_WRITE) 290 { 291 292 //WLAN_REPORT_INIT(pBusDrv->hReport, TNETW_DRV_MODULE_LOG, 293 // ("busDrv_Transact: Write to pTxn->uHwAddr %x\n", pTxn->uHwAddr )); 294 295 296 /*WLAN_REPORT_ERROR(pBusDrv->hReport, BUS_DRV_MODULE_LOG, 297 ("busDrv_Transact: Buff= %x, Len=%d\n", pTxn->aBuf[0], pTxn->aLen[0]));*/ 298 /*1.write memory*/ 299 /* Decrease the data pointer to the beginning of the WSPI padding */ 300 tempWriteBuff = pTxn->aBuf[0]; 301 tempWriteBuff -= WSPI_PAD_LEN_WRITE; 302 303 /* Write the data to the WSPI in Aync mode (not completed in the current context). */ 304 pBusDrv->eCurrTxnStatus = WSPI_WriteAsync(pBusDrv->hWspi, pTxn->uHwAddr,tempWriteBuff,pTxn->aLen[0], &cb, TI_TRUE, TI_TRUE,TXN_PARAM_GET_FIXED_ADDR(pTxn)); 305 306 } 307 308 /* If read command */ 309 else 310 { 311 //WLAN_REPORT_INIT(pBusDrv->hReport, TNETW_DRV_MODULE_LOG, 312 // ("busDrv_Transact: Read from pTxn->uHwAddr %x pTxn %x \n", pTxn->uHwAddr,pTxn)); 313 314 /*1. Read mem */ 315 /* Decrease the tempReadBuff pointer to the beginning of the WSPI padding */ 316 tempReadBuff = pTxn->aBuf[0]; 317 tempReadBuff -= WSPI_PAD_LEN_READ; 318 /* Read the required data from the WSPI in Aync mode (not completed in the current context). */ 319 pBusDrv->eCurrTxnStatus = WSPI_ReadAsync(pBusDrv->hWspi, pTxn->uHwAddr,tempReadBuff,pTxn->aLen[0], &cb, TI_TRUE, TI_TRUE,TXN_PARAM_GET_FIXED_ADDR(pTxn)); 320 321 322 } 323 324 /* return transaction status - COMPLETE, PENDING or ERROR */ 325 return (pBusDrv->eCurrTxnStatus == WSPI_TXN_COMPLETE ? TXN_STATUS_COMPLETE : 326 (pBusDrv->eCurrTxnStatus == WSPI_TXN_PENDING ? TXN_STATUS_PENDING : TXN_STATUS_ERROR)); 327 328 329} 330 331 332/**************************************************************************** 333 * asyncEnded_CB() 334 **************************************************************************** 335 * DESCRIPTION: 336 * Called back by the WSPI driver from Async transaction end interrupt (ISR context). 337 * Calls the upper layers callback. 338 * 339 * INPUTS: status - 340 * 341 * OUTPUT: None 342 * 343 * RETURNS: None 344 ****************************************************************************/ 345static void asyncEnded_CB(TI_HANDLE hBusDrv, int status) 346{ 347 TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv; 348 /* If the last transaction failed, call failure CB and exit. */ 349 if (status != 0) 350 { 351 TRACE2(pBusDrv->hReport, REPORT_SEVERITY_ERROR, "asyncEnded_CB : Status = %d, fTxnDoneCb = 0x%x\n", status,pBusDrv->fTxnDoneCb); 352 353 TXN_PARAM_SET_STATUS(pBusDrv->pCurrTxn, TXN_PARAM_STATUS_ERROR); 354 } 355 else 356 { 357 TRACE2(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION,"asyncEnded_CB: Successful async cb done pBusDrv->pCurrTxn %x\n", pBusDrv->pCurrTxn); 358 } 359 360 /* Call the upper layer CB */ 361 362 pBusDrv->fTxnDoneCb(pBusDrv->hCbHandle,pBusDrv->pCurrTxn); 363} 364 365 366/**************************************************************************** 367 * ConnectDone_CB() 368 **************************************************************************** 369 * DESCRIPTION: 370 * Called back by the WSPI driver from Async transaction end interrupt (ISR context). 371 * Calls the upper layers callback. 372 * 373 * INPUTS: status - 374 * 375 * OUTPUT: None 376 * 377 * RETURNS: None 378 ****************************************************************************/ 379static void ConnectDone_CB(TI_HANDLE hBusDrv, int status) 380{ 381 TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv; 382 /* If the last transaction failed, call failure CB and exit. */ 383 if (status != 0) 384 { 385 TRACE2(pBusDrv->hReport, REPORT_SEVERITY_ERROR, "ConnectDone_CB : Status = %d, fTxnConnectDoneCb = 0x%x\n", status,pBusDrv->fTxnConnectDoneCb); 386 387 TXN_PARAM_SET_STATUS(pBusDrv->pCurrTxn, TXN_PARAM_STATUS_ERROR); 388 } 389 else 390 { 391 TRACE1 (pBusDrv->hReport, REPORT_SEVERITY_INIT, "ConnectDone_CB: Successful Connect Async cb done \n"); 392 } 393 394 /* Call the upper layer CB */ 395 396 pBusDrv->fTxnConnectDoneCb(pBusDrv->hCbHandle,pBusDrv->pCurrTxn); 397} 398 399 400