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 */
63 typedef 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
86 static void asyncEnded_CB(TI_HANDLE hBusTxn, int status);
87 static 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 */
busDrv_Create(TI_HANDLE hOs)106 TI_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 */
busDrv_Destroy(TI_HANDLE hBusDrv)140 TI_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 ****************************************************************************/
busDrv_Init(TI_HANDLE hBusDrv,TI_HANDLE hReport)168 void 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 */
busDrv_ConnectBus(TI_HANDLE hBusDrv,TBusDrvCfg * pBusDrvCfg,TBusDrvTxnDoneCb fCbFunc,TI_HANDLE hCbArg,TBusDrvTxnDoneCb fConnectCbFunc)203 TI_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 */
busDrv_DisconnectBus(TI_HANDLE hBusDrv)258 TI_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 */
busDrv_Transact(TI_HANDLE hBusDrv,TTxnStruct * pTxn)277 ETxnStatus 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 ****************************************************************************/
asyncEnded_CB(TI_HANDLE hBusDrv,int status)345 static 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 ****************************************************************************/
ConnectDone_CB(TI_HANDLE hBusDrv,int status)379 static 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