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