1/****************************************************************************
2**+-----------------------------------------------------------------------+**
3**|                                                                       |**
4**| Copyright(c) 1998 - 2008 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
36
37/****************************************************************************
38 *
39 *   MODULE:  wspi.c
40 *   PURPOSE:
41 *
42 ****************************************************************************/
43
44
45#include "osTIType.h"
46#include "osApi.h"
47#include "whalCommon.h"
48#include "spi_api.h"
49#include "wspi.h"
50
51/* WSPI INIT CMD
52-----------------------------------------------------------------
53| start |  tx   |                command                        |
54-----------------------------------------------------------------
55    47      46      45                                      40
56
57-----------------------------------------------------------------
58|                           reserve                             |
59-----------------------------------------------------------------
60    39                                                      32
61
62-----------------------------------------------------------------
63|                           reserve                             |
64-----------------------------------------------------------------
65    31                                                      24
66
67-----------------------------------------------------------------
68|           reserve              |  1250 |   fixed busy length  |
69-----------------------------------------------------------------
70    23                                                      16
71
72-----------------------------------------------------------------
73| fixed |       |       |       |       |       |       |       |
74| busy  | iod   |   ip  |   cs  |   ws  |   bs  |  de   | wspi  |
75| enable|       |       |       |       |       |       |       |
76-----------------------------------------------------------------
77    15      14      13      12      11      10      9       8
78
79-----------------------------------------------------------------
80|                         CRC7                            | end |
81-----------------------------------------------------------------
82    7                                               1        0
83*/
84
85#define WSPI_SIZEOF_UINT32          sizeof (UINT32)
86
87#define WSPI_INIT_CMD_CRC_LEN       5
88
89#define WSPI_INIT_CMD_START         0x00
90#define WSPI_INIT_CMD_TX            0x40
91#define WSPI_INIT_CMD_BYPASS_BIT    0x80 /* the extra bypass bit is sampled by the TNET as '1' */
92#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07
93#define WSPI_INIT_CMD_EN_FIXEDBUSY  0x80
94#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00
95#define WSPI_INIT_CMD_IOD           0x40
96#define WSPI_INIT_CMD_IP            0x20
97#define WSPI_INIT_CMD_CS            0x10
98#define WSPI_INIT_CMD_WS            0x08
99#define WSPI_INIT_CMD_WSPI          0x01
100#define WSPI_INIT_CMD_END           0x01
101#define WSPI_INIT_CMD_CRC_INPUT_LEN 40
102
103#define PRINT_TEST_REGION_SIZE      100
104#define PRINT_TEST_REGION_START     0x305674 /* the device ID register */
105#define PRINT_TEST_SIZE_REG         0x1FFC0
106#define PRINT_TEST_ADDR_REG         0x1FFC4
107
108
109/* WSPI CMD
110-----------------------------------------------------------------
111| start |  tx   | fixed |         byte length                   |
112-----------------------------------------------------------------
113    31      30      29      28                              24
114
115-----------------------------------------------------------------
116|                           byte length                 |   a16 |
117-----------------------------------------------------------------
118    23                                              17      16
119
120-----------------------------------------------------------------
121|                           byte address                        |
122-----------------------------------------------------------------
123    15                                                      8
124
125-----------------------------------------------------------------
126|                           byte address                        |
127-----------------------------------------------------------------
128    7                                                       0
129*/
130
131
132/* The 31's bit in the WSPI cmd is read bit */
133#define WSPI_CMD_READ                 0x40000000
134#define WSPI_CMD_WRITE                0x00000000
135#define WSPI_CMD_FIXED                0x20000000
136#define WSPI_CMD_BYTE_LENGTH          0x1FFE0000
137#define WSPI_CMD_BYTE_LENGTH_OFFSET   17
138#define WSPI_CMD_BYTE_ADDR            0x0001FFFF
139
140
141#define WSPI_FIXED_BUSY_TIMEOUT       100
142#define WSPI_SYNC_OVER_ASYNC_TIMEOUT  100
143
144
145/* For FixedBusy Handle */
146#define NOT_IN_USE					  0
147
148static UINT8 WSPI_GenerateCRC7 (UINT8* bits, UINT32 len);
149#ifndef USE_WRITE_READ_API
150static void  WSPI_WriteCmdCb      (TI_HANDLE hWSPI, int status);
151#endif
152static void  WSPI_ReadDataCb      (TI_HANDLE hWSPI, int status);
153#ifdef USE_SYNC_API
154#ifdef USE_SYNC_OVER_ASYNC
155static void  WSPI_SyncOverAsyncCb (TI_HANDLE hWSPI, int status);
156#endif
157#endif
158static void  WSPI_ReadAsyncCb      (TI_HANDLE hWSPI, int status);
159static void  WSPI_ConfigureResetCb (TI_HANDLE hWSPI, int status);
160
161#ifdef TI_DBG
162	int DebugFixedBusy[10];
163#endif
164
165
166/*
167 * ----------------------------------------------------------------------------
168 * Function :   WSPI_Open
169 *
170 * Input    :   none
171 *
172 * Output   :   void**  phWSPI - a pointer to the handle of the WSPI
173 *
174 * ReturnVal:   one of the error codes (zero is success)
175 *
176 * Note(s)  :   allocates the WSPI driver context and creates the SPI sublayer
177 * -----------------------------------------------------------------------------
178 */
179TI_HANDLE WSPI_Open (TI_HANDLE hOs)
180{
181    WSPI_t* pWSPI;
182
183    /* Allocate WSPI memory */
184    pWSPI = (WSPI_t *) os_memoryAlloc (hOs, sizeof(WSPI_t));
185    if (pWSPI == NULL)
186    {
187        return NULL;
188    }
189
190    pWSPI->hOs = hOs;
191    pWSPI->pTempBuf = 0;
192	pWSPI->pExtraFixedBusyBuf = 0;
193
194    /* Call to SPI_Open */
195    pWSPI->hSPI = SPI_Open ();
196
197    return (TI_HANDLE)pWSPI;
198}
199
200
201/*
202 * ----------------------------------------------------------------------------
203 * Function :   WSPI_Close
204 *
205 * Input    :   void* hWSPI - the WSPI handle
206 *
207 * Output   :   none
208 *
209 * ReturnVal:   one of the error codes (zero is success)
210 *
211 * Note(s)  :   frees the WSPI driver context and closes the SPI sublayer
212 * -----------------------------------------------------------------------------
213 */
214int WSPI_Close (TI_HANDLE hWSPI)
215{
216    WSPI_t* pWSPI = (WSPI_t*)hWSPI;
217
218    /* Call SPI_Close */
219    SPI_Close (pWSPI->hSPI);
220
221    /* Free temporary buffer */
222    if (pWSPI->pTempBuf)
223    {
224        os_memoryFree (pWSPI->hOs, pWSPI->pTempBuf, WSPI_NO_EXTRA_ALLOC_SIZE + pWSPI->uFixedBusyBytes);
225    }
226
227
228	if (pWSPI->pExtraFixedBusyBuf)
229    {
230        os_memoryFree (pWSPI->hOs, pWSPI->pExtraFixedBusyBuf, WSPI_EXTRA_BUFFER_ALLOC_SIZE);
231    }
232
233    /* Free allocated memory */
234    os_memoryFree (pWSPI->hOs, hWSPI, sizeof(WSPI_t));
235
236    return WSPI_OK;
237}
238
239
240/*
241 * ----------------------------------------------------------------------------
242 * Function :   WSPI_Configure
243 *
244 * Input    :   void* hWSPI - the WSPI handle
245 *              const WSPIConfig_t* aConfig -  a structure that holds the configuration data
246                WSPI_CB_T* cb - callback
247 *
248 * Output   :
249 *
250 * ReturnVal:   one of the error codes (zero is success)
251 *
252 * Note(s)  :   1. configures the SPI sublayer
253 *              2. sends the WSPI init word
254 * -----------------------------------------------------------------------------
255 */
256int WSPI_Configure (TI_HANDLE hWSPI, TI_HANDLE hReport, const WSPIConfig_t* aConfig, WSPI_CB_T* cb)
257{
258    WSPI_t *pWSPI = (WSPI_t*)hWSPI;
259    int i;
260
261	#ifdef TI_DBG
262		for (i=0;i<10;i++)
263		{
264			DebugFixedBusy[i] = 0;
265		}
266	#endif
267
268    /*
269     * This function is called during initialization and recovery. In recovery,
270     * The old values are used, so there's no need to re-configure everything again.
271     */
272    if (NULL != aConfig)
273    {
274    /* Set WSPI_t parameters */
275    pWSPI->uConfigMask = aConfig->mask;
276    pWSPI->bFixedAddr = aConfig->isFixedAddress;
277    pWSPI->uFixedBusyLen = aConfig->fixedBusyLength;
278    pWSPI->uFixedBusyBytes = pWSPI->uFixedBusyLen * 4 + 4;
279    /* Will be set to TRUE only when no extra bytes were allocated */
280    pWSPI->bUseTempBuf = FALSE;
281    pWSPI->fErr = 0;
282    pWSPI->hReport = hReport;
283    /* Save CB for the WSPI_ConfigureResetCb() */
284    pWSPI->fCb = cb->CBFunc;
285    pWSPI->pCb = cb->CBArg;
286
287    /* Allocate the temporary buffer that will hold buffers with no extra room */
288    if (pWSPI->uFixedBusyLen != 0)
289    {
290        if ((pWSPI->pTempBuf = os_memoryAlloc (pWSPI->hOs, WSPI_NO_EXTRA_ALLOC_SIZE + pWSPI->uFixedBusyBytes)) == NULL)
291        {
292            return WSPI_ERR_ALLOC_MEM;
293        }
294    }
295    }
296
297	/* Allocate the temporary buffer that will hold buffers with no extra room */
298	if ((pWSPI->pExtraFixedBusyBuf = os_memoryAlloc (pWSPI->hOs, WSPI_EXTRA_BUFFER_ALLOC_SIZE)) == NULL)
299    {
300        return WSPI_ERR_ALLOC_MEM;
301    }
302	pWSPI->ExtraBufLength = 0;
303
304    /* This CMD is used to reset the HW SM */
305    for (i = 0; i < WSPI_INIT_CMD_LEN; i++)
306    {
307        pWSPI->auInitCmd[i] = 0xff;
308    }
309
310    /* Write the reset CMD */
311    pWSPI->returnStatus =  SPI_Write (pWSPI->hSPI, pWSPI->auInitCmd, WSPI_INIT_CMD_LEN, (request_callback_t)WSPI_ConfigureResetCb, hWSPI, 1);
312    if (pWSPI->returnStatus == SPI_TXN_COMPLETE)
313    {
314		/* Note that in the next function call, pWSPI->returnStatus is going to be changed */
315        WSPI_ConfigureResetCb(hWSPI, OK);
316    }
317
318    return (pWSPI->returnStatus == SPI_TXN_COMPLETE ? WSPI_TXN_COMPLETE :
319			(pWSPI->returnStatus == SPI_TXN_PENDING ? WSPI_TXN_PENDING : WSPI_ERR_UNKNOWN));
320}
321
322static void WSPI_ConfigureResetCb (TI_HANDLE hWSPI, int status)
323{
324    WSPI_t *pWSPI = (WSPI_t*)hWSPI;
325    UINT8   auCRCBuffer [WSPI_INIT_CMD_CRC_LEN];
326
327    /*
328     * Set WSPI_INIT_COMMAND
329     * the data is being send from the MSB to LSB
330     */
331    pWSPI->auInitCmd[2] = 0xff;
332    pWSPI->auInitCmd[3] = 0xff;
333    pWSPI->auInitCmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
334    pWSPI->auInitCmd[0] = 0;
335    pWSPI->auInitCmd[7] = 0;
336    pWSPI->auInitCmd[6] =
337        (pWSPI->uConfigMask << 3) | (pWSPI->uFixedBusyLen & WSPI_INIT_CMD_FIXEDBUSY_LEN);
338    pWSPI->auInitCmd[5] =
339        ((pWSPI->uFixedBusyLen == 0) ?
340            WSPI_INIT_CMD_DIS_FIXEDBUSY :
341            WSPI_INIT_CMD_EN_FIXEDBUSY)
342        | WSPI_INIT_CMD_IOD
343        | WSPI_INIT_CMD_IP
344        | WSPI_INIT_CMD_CS
345       #ifndef SPI_16_BIT
346        | WSPI_INIT_CMD_WS
347       #endif
348        | WSPI_INIT_CMD_WSPI;
349
350    auCRCBuffer[0] = pWSPI->auInitCmd[1];
351    auCRCBuffer[1] = pWSPI->auInitCmd[0];
352    auCRCBuffer[2] = pWSPI->auInitCmd[7];
353    auCRCBuffer[3] = pWSPI->auInitCmd[6];
354    auCRCBuffer[4] = pWSPI->auInitCmd[5];
355
356    pWSPI->auInitCmd[4] =
357        (WSPI_GenerateCRC7 (auCRCBuffer, WSPI_INIT_CMD_CRC_INPUT_LEN) << 1)
358        | WSPI_INIT_CMD_END;
359
360    pWSPI->returnStatus = SPI_Write (pWSPI->hSPI, pWSPI->auInitCmd, WSPI_INIT_CMD_LEN, pWSPI->fCb, pWSPI->pCb, 1);
361}
362
363
364/*
365 * ----------------------------------------------------------------------------
366 * Function :   WSPI_ReadSync
367 *
368 * Input    :   void* hWSPI    - the WSPI handle
369 *              UINT32 address - the address (in bytes) in the firmware to read the data from
370 *              UINT32 length  - the number of bytes to read
371 *              WSPI_CB_T cb   - callback parameters
372 *              BOOL bMore     - more read/write transaction will follow
373 *
374 * Output   :   UINT8* data - the buffer to put the read data
375 *
376 * ReturnVal:   one of the error codes (zero is success)
377 *
378 * Note(s)  :   1. set the WSPI cammand+address word
379 *              2. send the WSPIcammand+address word
380 *              3. read the fixed busy
381 *              4. read the data
382 *              5. check that the fixed busy was OK
383 *
384 *              because of the TNET state machine the data is always sent and only after
385 *              we read it we validate that it's OK
386 * -----------------------------------------------------------------------------
387 */
388int WSPI_ReadSync (TI_HANDLE hWSPI, UINT32 address, UINT8* data, UINT32 length)
389{
390  #ifdef USE_SYNC_OVER_ASYNC
391
392    WSPI_t    *pWSPI = (WSPI_t*)hWSPI;
393    WSPI_CB_T  cb = { (request_callback_t)WSPI_SyncOverAsyncCb, hWSPI };
394    UINT32        i, timeout;
395
396    if (length == 0)
397    {
398        return WSPI_ERR_WRONG_LENGTH;
399    }
400
401    /* Set the sync flag */
402    pWSPI->bSyncFlag = 0;
403
404    WSPI_ReadAsync (hWSPI, address, data, length, &cb, 1, 0);
405
406    /* Wait to end of the asynchronous read */
407    timeout = WSPI_SYNC_OVER_ASYNC_TIMEOUT * length;
408    for (i = 0; i < timeout; i++)
409    {
410        if (pWSPI->bSyncFlag)
411        {
412            break;
413        }
414    }
415    if (i == timeout)
416    {
417        /* Reached the timeout criteria without ending the asynchronous read */
418        WLAN_REPORT_ERROR (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG, ("WSPI ASYNC READ DIDN'T FINISH\n"));
419
420        return  WSPI_ERR_ASYNC_TIMEOUT;
421    }
422
423    return WSPI_OK;
424
425  #else /* USE_SYNC_OVER_ASYNC */
426
427    WSPI_t* pWSPI = (WSPI_t*)hWSPI;
428    UINT32     i;
429    UINT32  uFixedBusy;
430    int     ret = WSPI_OK;
431
432    if (length == 0)
433    {
434        return WSPI_ERR_WRONG_LENGTH;
435    }
436
437    /*****************************/
438    /* Write the command+address */
439    /*****************************/
440    pWSPI->uCmd = WSPI_CMD_READ;
441
442    /* Set bFixedAddr */
443    if (pWSPI->bFixedAddr)
444    {
445        pWSPI->uCmd |= WSPI_CMD_FIXED;
446    }
447
448    /* Set length */
449    pWSPI->uCmd |= (length << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
450    /* Set address */
451    pWSPI->uCmd |= address & WSPI_CMD_BYTE_ADDR;
452
453    /* Write command+address */
454    ret |= SPI_WriteSync (pWSPI->hSPI, (UINT8*)&pWSPI->uCmd, WSPI_SIZEOF_UINT32);
455
456    if (pWSPI->uFixedBusyLen == 0)
457    {
458        /* 1150 */
459        /* For 1150 read until we get the not-busy word */
460        for (i = 0; i < WSPI_FIXED_BUSY_TIMEOUT; i++)
461        {
462            ret |= SPI_ReadSync (pWSPI->hSPI, (UINT8*)&uFixedBusy, WSPI_SIZEOF_UINT32);
463            if ((uFixedBusy & 0x1) != 0)
464            {
465                break;
466            }
467        }
468
469        if (i == WSPI_FIXED_BUSY_TIMEOUT)
470        {
471            WLAN_REPORT_ERROR (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG, ("WSPI FIXED BUSY (SYNC)\n"));
472
473            return WSPI_ERR_BUS_BUSY;
474        }
475    }
476    else
477    {
478        /* 1251 */
479        /* For 1251 read the predefined number of busy words and at the end the not-busy word */
480        for (i = 0; i < pWSPI->uFixedBusyLen; i++)
481            ret |= SPI_ReadSync (pWSPI->hSPI, (UINT8*)&uFixedBusy, WSPI_SIZEOF_UINT32);
482        ret |= SPI_ReadSync (pWSPI->hSPI, (UINT8*)&uFixedBusy, WSPI_SIZEOF_UINT32);
483    }
484
485    /* Read data */
486    ret |= SPI_ReadSync (pWSPI->hSPI, data, length);
487
488    if (pWSPI->uFixedBusyLen)
489    {
490        /* 1251 */
491        /* Check the fixed busy */
492        if (!(uFixedBusy & 0x1))
493        {
494            WLAN_REPORT_ERROR (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG, ("WSPI FIXED BUSY (SYNC)\n"));
495
496            ret = WSPI_ERR_BUS_BUSY;
497        }
498    }
499
500    return ret;
501  #endif
502}
503
504
505/*
506 * ----------------------------------------------------------------------------
507 * Function :   WSPI_ReadAsync
508 *
509 * Input    :   void* hWSPI    - the WSPI handle
510 *              UINT32 address - the address (in bytes) in the firmware to read the data from
511 *              UINT32 length  - the number of bytes to read
512 *              WSPI_CB_T cb   - callback parameters
513 *              BOOL bMore     - more read/write transaction will follow
514 *              BOOL bSpaceReserved
515 *                             - extra space padding has been reserved by an upper layer
516 *
517 * Output   :   UINT8* data    - the buffer to put the read data
518 *
519 * ReturnVal:   one of the error codes (zero is success)
520 *
521 * -----------------------------------------------------------------------------
522 */
523int WSPI_ReadAsyncOld (TI_HANDLE hWSPI, UINT32 address, UINT8* data, UINT32 length, WSPI_CB_T* cb, BOOL bMore, BOOL bSpaceReserved)
524{
525    WSPI_t       *pWSPI = (WSPI_t*)hWSPI;
526    int           ret = WSPI_OK;
527
528    if (length == 0)
529    {
530        return WSPI_ERR_WRONG_LENGTH;
531    }
532
533    /*
534     * Pass to the CB function of the read data also the fixed busy response so
535     * to put all the required data in subsequent places in the buffer of the WSPI context
536     * first the fixed busy, second the CBFunc, third the CBArg
537     * here we guarantee that the data will be sequential
538     */
539
540    /*****************************/
541    /* Write the command+address */
542    /*****************************/
543    pWSPI->uCmd = WSPI_CMD_READ;
544
545    /* Set bFixedAddr */
546    if (pWSPI->bFixedAddr)
547    {
548        pWSPI->uCmd |= WSPI_CMD_FIXED;
549    }
550
551    /* Set the length */
552    pWSPI->uCmd |= (length << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
553    /* Set the address */
554    pWSPI->uCmd |= address & WSPI_CMD_BYTE_ADDR;
555
556    /* Write command+address */
557    ret |= SPI_WriteSync (pWSPI->hSPI, (UINT8*)&pWSPI->uCmd, WSPI_SIZEOF_UINT32);
558
559    if (pWSPI->uFixedBusyLen == 0)
560    {
561        UINT32 uFixedBusy, i;
562        /* 1150 */
563        /* For 1150 read until we get the not-busy word */
564        for (i = 0; i < WSPI_FIXED_BUSY_TIMEOUT; i++)
565        {
566            ret |= SPI_ReadSync (pWSPI->hSPI, (UINT8*)&uFixedBusy, WSPI_SIZEOF_UINT32);
567            if ((uFixedBusy & 0x1) != 0)
568            {
569                break;
570            }
571        }
572
573        if (i == WSPI_FIXED_BUSY_TIMEOUT)
574        {
575            WLAN_REPORT_ERROR (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG, ("WSPI FIXED BUSY (ASYNC)\n"));
576
577            if (pWSPI->fErr)
578            {
579                (*pWSPI->fErr) ();
580            }
581
582            return WSPI_ERR_BUS_BUSY;
583        }
584    }
585    else
586    {
587        UINT32 uFixedBusy, i;
588        /* 1251 */
589        /* For 1251 read the predefined number of busy words and at the end the not-busy word */
590        for (i = 0; i < pWSPI->uFixedBusyLen; i++)
591            ret |= SPI_ReadSync (pWSPI->hSPI, (UINT8*)&uFixedBusy, WSPI_SIZEOF_UINT32);
592        ret |= SPI_ReadSync (pWSPI->hSPI, (UINT8*)&pWSPI->uFixedBusy, WSPI_SIZEOF_UINT32);
593    }
594
595    /* Read the data */
596    pWSPI->fCb = cb->CBFunc;
597    pWSPI->pCb = cb->CBArg;
598
599    /* Tell the lower machine to start executing after this submission */
600    ret |= SPI_Read (pWSPI->hSPI,
601                     data + bSpaceReserved * pWSPI->uFixedBusyBytes,
602                     length,
603                     WSPI_ReadAsyncCb,
604                     pWSPI,
605                     1);
606
607    return ret;
608}
609
610
611/*
612 * ----------------------------------------------------------------------------
613 * Function :   WSPI_WriteSync
614 *
615 * Input    :   void* hWSPI - the WSPI handle
616 *              UINT32 address - the address (in bytes) in the firmware to read the data from
617 *              UINT8* data - the buffer that holds the data to write
618 *              UINT32 length - the number of bytes to read
619 *
620 * Output   :   none
621 *
622 * ReturnVal:   one of the error codes (zero is success)
623 *
624 * Note(s)  :   1. set the WSPI cammand+address word
625 *              2. send the WSPIcammand+address word
626 *              3. send the data
627 *
628 * -----------------------------------------------------------------------------
629 */
630int WSPI_WriteSync (TI_HANDLE hWSPI, UINT32 address, UINT8* data, UINT32 length)
631{
632  #ifdef USE_SYNC_OVER_ASYNC
633
634    WSPI_t*   pWSPI = (WSPI_t*)hWSPI;
635    WSPI_CB_T cb = { (request_callback_t)WSPI_SyncOverAsyncCb, hWSPI };
636    int       i, timeout;
637
638    if (length == 0)
639    {
640        return WSPI_ERR_WRONG_LENGTH;
641    }
642
643    /* Set the sync flag */
644    pWSPI->bSyncFlag = 0;
645
646    WSPI_WriteAsync (hWSPI, address, data, length, &cb, 1, 0);
647
648    /* Wait to end of the asynchronous write */
649    timeout = WSPI_SYNC_OVER_ASYNC_TIMEOUT * length;
650    for (i = 0; i < timeout; i++)
651    {
652        if (pWSPI->bSyncFlag)
653        {
654            break;
655        }
656    }
657    if (i == timeout)
658    {
659        /* Reached the timeout criteria without ending the asynchronous write */
660        WLAN_REPORT_ERROR (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG, ("WSPI ASYNC WRITE DIDN'T END\n"));
661
662        return  WSPI_ERR_ASYNC_TIMEOUT;
663    }
664
665    return WSPI_OK;
666
667  #else
668
669    WSPI_t* pWSPI = (WSPI_t*)hWSPI;
670    int     ret = WSPI_OK;
671
672    if (length == 0)
673    {
674        return WSPI_ERR_WRONG_LENGTH;
675    }
676
677    /*****************************/
678    /* Write the command+address */
679    /*****************************/
680    pWSPI->uCmd = WSPI_CMD_WRITE;
681
682    /* Set bFixedAddr */
683    if (pWSPI->bFixedAddr)
684    {
685        pWSPI->uCmd |= WSPI_CMD_FIXED;
686    }
687
688    /* Set length */
689    pWSPI->uCmd |= ((UINT32)length << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
690    /* Set address */
691    pWSPI->uCmd |= address & WSPI_CMD_BYTE_ADDR;
692
693    /* Write */
694    ret |= SPI_WriteSync (pWSPI->hSPI, (UINT8*)&pWSPI->uCmd, WSPI_SIZEOF_UINT32);
695
696    /**************/
697    /* Write data */
698    /**************/
699    ret |= SPI_WriteSync (pWSPI->hSPI, data, length);
700
701    return ret;
702
703  #endif
704}
705
706
707/*
708 * ----------------------------------------------------------------------------
709 * Function :   WSPI_ReadAsync
710 *
711 * Input    :   void* hWSPI    - the WSPI handle
712 *              UINT32 address - the address (in bytes) in the firmware to read the data from
713 *              UINT32 length  - the number of bytes to read
714 *              WSPI_CB_T cb   - callback parameters
715 *              BOOL bMore     - more read/write transaction will follow
716 *              BOOL bSpaceReserved
717 *                             - extra space padding has been reserved by an upper layer
718 *
719 * Output   :   UINT8* data    - the buffer to put the read data
720 *
721 * ReturnVal:   one of the error codes (zero is success)
722 *
723 * Note(s)  :   1. set the WSPI cammand+address word
724 *              2. set the command+address request struct
725 *              3. submit the request
726 *              4. set the read fixed busy request struct
727 *              5. submit the request
728 *              6. set the read data request struct
729 *              7. submit the request with execute flag
730 *
731 *              the fixed response is read into the buffer of the WSPI context
732 * -----------------------------------------------------------------------------
733 */
734int WSPI_ReadAsync (TI_HANDLE hWSPI, UINT32 address, UINT8* data, UINT32 length, WSPI_CB_T* cb, BOOL bMore, BOOL bSpaceReserved)
735{
736    WSPI_t       *pWSPI = (WSPI_t*)hWSPI;
737    int           status;
738
739    if (length == 0)
740    {
741        return WSPI_ERR_WRONG_LENGTH;
742    }
743
744    /* Save parameters */
745    pWSPI->length = (UINT32)length;
746    pWSPI->data = data;
747    pWSPI->bMore = bMore;
748    pWSPI->bSpaceReserved = bSpaceReserved;
749    pWSPI->fCb = cb->CBFunc;
750    pWSPI->pCb = cb->CBArg;
751
752    /**********************************/
753    /* Prepare the CMD for the SM use */
754    /**********************************/
755    pWSPI->uCmd = WSPI_CMD_READ;
756
757    /* Set bFixedAddr */
758    if (pWSPI->bFixedAddr)
759    {
760        pWSPI->uCmd |= WSPI_CMD_FIXED;
761    }
762
763    /* Set length */
764    pWSPI->uCmd |= ((UINT32)length << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
765    /* Set address */
766    pWSPI->uCmd |= address & WSPI_CMD_BYTE_ADDR;
767
768  #ifdef USE_WRITE_READ_API
769
770    if (bSpaceReserved)
771    {
772        /* Indicate that that the temporary buffer is NOT used */
773        pWSPI->bUseTempBuf = 0;
774    }
775
776    else
777    {
778        if (pWSPI->length <= WSPI_NO_EXTRA_ALLOC_SIZE)
779        {
780            /* Indicate that that the temporary buffer is used */
781            data = pWSPI->pTempBuf;
782            pWSPI->bUseTempBuf = 1;
783        }
784        else
785        {
786            WLAN_REPORT_ERROR (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG, ("No space reserved for command\n"));
787
788            return WSPI_ERR_UNKNOWN;
789        }
790    }
791
792    status = SPI_WriteRead (pWSPI->hSPI,
793                            (UINT8*)&pWSPI->uCmd,
794                            WSPI_SIZEOF_CMD,
795                            data,
796                            length + pWSPI->uFixedBusyBytes,
797                            WSPI_ReadDataCb,
798                            pWSPI,
799                            bMore);
800
801    /* In case of synchronous transaction completion call read callback explicitly */
802    if (SPI_TXN_COMPLETE == status)
803    {
804        pWSPI->fCb = NULL;
805        WSPI_ReadDataCb (hWSPI, status);
806    }
807
808    return status;
809
810  #else
811
812    /* Write command and indicate that more is ON */
813    status = SPI_Write (pWSPI->hSPI,
814                        (UINT8*)&pWSPI->uCmd,
815                        WSPI_SIZEOF_CMD,
816                        WSPI_WriteCmdCb,
817                        hWSPI,
818                        1);
819
820    /* Don't pend, call directly to the callback */
821    if (SPI_TXN_COMPLETE == status)
822    {
823        WSPI_WriteCmdCb (hWSPI, WSPI_OK);
824        /* WSPI_WriteCmdCb updates the pWSPI->status */
825        return pWSPI->status;
826    }
827
828    return status;
829
830  #endif
831}
832
833
834#ifndef USE_WRITE_READ_API
835/*
836 * ----------------------------------------------------------------------------
837 * Function :   WSPI_WriteCmdCb
838 *
839 * Input    :   void* hWSPI - the WSPI handle
840 *              int status  - SPI request status
841 *
842 * Note(s)  :   CB from writing CMD in WSPI_ReadAsync().
843 *              Read the data according to bSpaceReserved (indicates whether extra bytes were allocated
844 *              in the buffer for the FixedBusyWord).
845 *              if (!bSpaceReserved) but the length is short (WSPI_NO_EXTRA_ALLOC_SIZE) than copy it to
846 *              temporary file and read the data
847 *              else - ERROR !
848 * -----------------------------------------------------------------------------
849 */
850void WSPI_WriteCmdCb (TI_HANDLE hWSPI, int status)
851{
852    WSPI_t *pWSPI = (WSPI_t*)hWSPI;
853
854    /* Extra room was saved - set the pointer as is */
855    if (pWSPI->bSpaceReserved)
856    {
857        /* Indicate that that the temporary buffer is NOT used */
858        pWSPI->bUseTempBuf = 0;
859
860        /* Execute read with extra fixed busy bytes */
861        pWSPI->status = SPI_Read (pWSPI->hSPI,
862                                  pWSPI->data,
863                                  pWSPI->length + pWSPI->uFixedBusyBytes,
864                                  WSPI_ReadDataCb,
865                                  hWSPI,
866                                  pWSPI->bMore);
867    }
868
869    /*
870     * This case is used for handling buffers which have no extra room for the fixed busy words.
871     * Use a temporary buffer and than copy the results
872     */
873    else if (pWSPI->length <= WSPI_NO_EXTRA_ALLOC_SIZE)
874    {
875        /* Indicate that that the temporary buffer is used */
876        pWSPI->bUseTempBuf = 1;
877
878        /* Read fixed busy words and a data in one transaction */
879        pWSPI->status = SPI_Read (pWSPI->hSPI,
880                                  pWSPI->pTempBuf,
881                                  pWSPI->length + pWSPI->uFixedBusyBytes,
882                                  WSPI_ReadDataCb,
883                                  hWSPI,
884                                  pWSPI->bMore);
885    }
886    else
887    {
888        WLAN_REPORT_ERROR (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG, ("No space reserved command\n"));
889    }
890
891    /* Check the return status; if not pending - call directly */
892    if (SPI_TXN_COMPLETE == pWSPI->status)
893    {
894        WSPI_ReadDataCb (hWSPI, WSPI_OK);
895    }
896}
897#endif
898
899
900/*
901 * ----------------------------------------------------------------------------
902 * Function :   WSPI_ReadDataCb
903 *
904 * Input    :   void* hWSPI - the WSPI handle
905 *              int status  - SPI request status
906 *
907 * Note(s)  :   CB from WSPI_WriteCmdCb().
908 *              Copy the data if needed and call original CB
909 * -----------------------------------------------------------------------------
910 */
911void WSPI_ReadDataCb (TI_HANDLE hWSPI, int status)
912{
913    WSPI_t *pWSPI = (WSPI_t*)hWSPI;
914    UINT32 *pRbuf;
915
916    /* If we are using the temp buffer and its fixedBusyWord is OK */
917    pRbuf = (pWSPI->bUseTempBuf) ? (UINT32 *)pWSPI->pTempBuf
918                                 : (UINT32 *)pWSPI->data;
919
920    /* No fixed busy */
921    if ((pRbuf[pWSPI->uFixedBusyLen] & 0x1) != 0)
922    {
923        /* Copy data to the original buffer */
924        if (pWSPI->bUseTempBuf)
925        {
926          #if WSPI_NO_EXTRA_ALLOC_SIZE == 4 /* used for optimization */
927            /* In case the data size is 4 bytes copy it directly from the temp buffer */
928            *((UINT32*)pWSPI->data) = pRbuf[pWSPI->uFixedBusyLen + 1];
929          #else
930            os_memoryCopy (pWSPI->hOs, pWSPI->data, &pRbuf[pWSPI->uFixedBusyLen + 1], pWSPI->length);
931          #endif
932        }
933
934        /* Call user callback */
935        if (pWSPI->fCb != NULL)
936        {
937            pWSPI->fCb (pWSPI->pCb, 0);
938        }
939    }
940    /* Handle fixed busy */
941    else
942    {
943		WLAN_REPORT_WARNING (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG,
944			("WSPI FIXED BUSY (READ CALLBACK) Cmd = 0x%x, data pointer = %p data = 0x%x length = %d\n",
945			pWSPI->uCmd, pRbuf, pRbuf[pWSPI->uFixedBusyLen + 1], pWSPI->length));
946
947		WSPI_HandleFixedBusy(hWSPI, pRbuf);
948    }
949}
950
951/*
952* ----------------------------------------------------------------------------
953* Function :   WSPI_ReadDataAfterNotBusyCb
954*
955* Input    :   void* hWSPI - the WSPI handle
956*              int status  - Not in use.
957*
958* Note(s)  :   Called from WSPI_HandleFixedBusy after the last read operation had the ~busy
959*				word, but some of the data is missing
960* -----------------------------------------------------------------------------
961*/
962void WSPI_ReadDataAfterNotBusyCb (TI_HANDLE hWSPI, int status)
963{
964	WSPI_t  *pWSPI = (WSPI_t*)hWSPI;
965	UINT32 *pRbuf;
966	UINT32 iExtraBufByteLength = pWSPI->ExtraBufLength*WSPI_SIZEOF_UINT32;
967	UINT32 iTotalLength		   = pWSPI->length + pWSPI->uFixedBusyBytes;
968
969	/* If we are using the temp buffer and its fixedBusyWord is OK */
970	pRbuf = (pWSPI->bUseTempBuf) ? (UINT32 *)pWSPI->pTempBuf : (UINT32 *)pWSPI->data;
971
972	if (pWSPI->bUseTempBuf)
973	{
974	   #if WSPI_NO_EXTRA_ALLOC_SIZE == 4 /* used for optimization */
975		/* In case the data size is 4 bytes copy it directly from the temp buffer */
976		*((UINT32*)pWSPI->data) = *((UINT32*)pWSPI->pExtraFixedBusyBuf);
977	   #else
978		os_memoryCopy (pWSPI->hOs, pWSPI->data, &(pRbuf[pWSPI->uFixedBusyLen + 1 + pWSPI->ExtraBufLength]), pWSPI->length - iExtraBufByteLength);
979		os_memoryCopy (pWSPI->hOs, &(pWSPI->data[pWSPI->length - iExtraBufByteLength]), pWSPI->pExtraFixedBusyBuf, iExtraBufByteLength);
980	   #endif
981	}
982	else
983	{
984		os_memoryCopy(pWSPI->hOs, pRbuf,  &(pRbuf[pWSPI->ExtraBufLength]),iTotalLength - iExtraBufByteLength);
985		pWSPI->data = (UINT8*)pRbuf;
986		os_memoryCopy (pWSPI->hOs, &(pWSPI->data[iTotalLength - iExtraBufByteLength]), pWSPI->pExtraFixedBusyBuf, iExtraBufByteLength);
987	}
988
989	/* Call user callback */
990	if (pWSPI->fCb != NULL)
991	{
992		pWSPI->fCb (pWSPI->pCb, 0);
993	}
994}
995
996/*
997* ----------------------------------------------------------------------------
998* Function :   WSPI_ReadNotBusyAndDataCb
999*
1000* Input    :   void* hWSPI - the WSPI handle
1001*              int status  - Not in use.
1002*
1003* Note(s)  :   Called from WSPI_HandleFixedBusy after the last read operation had no response
1004*			    from the CHIP. i.e. the ~busy word is missing too
1005* -----------------------------------------------------------------------------
1006*/
1007void WSPI_ReadNotBusyAndDataCb (TI_HANDLE hWSPI, int status)
1008{
1009	WSPI_t  *pWSPI = (WSPI_t*)hWSPI;
1010	int i = 0;
1011
1012	if ( pWSPI->bUseTempBuf )
1013	{
1014		while (i < (WSPI_EXTRA_READ_AFTER_NO_RESPONSE) )
1015		{
1016			/* Check if this is the ~busy word */
1017			if ( (*(UINT32*)(pWSPI->pExtraFixedBusyBuf + i)) & 0x1 )
1018			{
1019				/* we have reached the fixed busy word */
1020			   #if WSPI_NO_EXTRA_ALLOC_SIZE == 4 /* used for optimization */
1021				/* In case the data size is 4 bytes copy it directly from the temp buffer */
1022				*((UINT32*)pWSPI->data) = *((UINT32*)(pWSPI->pExtraFixedBusyBuf+i+4));
1023			   #else
1024				os_memoryCopy (pWSPI->hOs, pWSPI->data, &(pWSPI->pTempBuf[pWSPI->uFixedBusyLen + 1 + pWSPI->ExtraBufLength]), pWSPI->length - iExtraBufByteLength);
1025				os_memoryCopy (pWSPI->hOs, &(pWSPI->data[pWSPI->length - iExtraBufByteLength]), pWSPI->pExtraFixedBusyBuf, iExtraBufByteLength);
1026			   #endif
1027
1028				if (pWSPI->fCb != NULL)
1029				{
1030					pWSPI->fCb (pWSPI->pCb, 0);
1031				}
1032				return;
1033			}
1034			i+=4;
1035		}
1036	}
1037	/* Oh boy, We couldn't find the ~Busy word */
1038	WLAN_REPORT_ERROR (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG,
1039		("WSPI FIXED BUSY (READ CALLBACK) Cmd = 0x%x, length = %d\n",
1040		pWSPI->uCmd,pWSPI->length));
1041
1042	if (pWSPI->fErr)
1043	{
1044		(*pWSPI->fErr) ();
1045	}
1046	if (pWSPI->fCb != NULL)
1047	{
1048		pWSPI->fCb (pWSPI->pCb, WSPI_ERR_BUS_BUSY);
1049	}
1050}
1051
1052/*
1053 * ----------------------------------------------------------------------------
1054 * Function :   WSPI_HandleFixedBusy
1055 *
1056 * Input    :   void* hWSPI - the WSPI handle
1057 *              UINT32 *pRbuf  - The temp read buffer
1058 *
1059 * Note(s)  :   Called from WSPI_ReadDataCb() when a Fixed_Busy error accurse.
1060 *              Shifting the data to the expected place and reading the missing data
1061 * -----------------------------------------------------------------------------
1062 */
1063void WSPI_HandleFixedBusy(TI_HANDLE hWSPI, UINT32 *pRbuf)
1064{
1065	WSPI_t  *pWSPI = (WSPI_t*)hWSPI;
1066    UINT8   iTotalLength = pWSPI->length + pWSPI->uFixedBusyBytes;
1067	UINT8   iExtraBufByteLength = 0;
1068	int		status;
1069
1070	pWSPI->ExtraBufLength = 0;
1071
1072	/* Find the Data beginning */
1073	while (((pRbuf[pWSPI->uFixedBusyLen + pWSPI->ExtraBufLength] & 0x1) == 0) &&
1074		   ((pWSPI->uFixedBusyBytes + (pWSPI->ExtraBufLength * WSPI_SIZEOF_UINT32))  < iTotalLength) &&
1075		   ((pWSPI->ExtraBufLength * WSPI_SIZEOF_UINT32 ) < WSPI_EXTRA_BUFFER_ALLOC_SIZE ))
1076	{
1077		pWSPI->ExtraBufLength++;
1078	}
1079
1080	#ifdef TI_DBG
1081		if (pWSPI->ExtraBufLength > 0)
1082		{
1083			DebugFixedBusy[pWSPI->ExtraBufLength - 1]++;
1084		}
1085	#endif
1086
1087	/* if we had less then WSPI_EXTRA_BUFFER_ALLOC_SIZE FixedBusy words */
1088	if ((pRbuf[pWSPI->uFixedBusyLen + pWSPI->ExtraBufLength] & 0x1) != 0)
1089	{
1090		iExtraBufByteLength = pWSPI->ExtraBufLength*WSPI_SIZEOF_UINT32;
1091
1092		/* Execute read with extra fixed busy bytes and without CMD*/
1093		status = SPI_WriteRead(pWSPI->hSPI,
1094								NULL,
1095								0,
1096								pWSPI->pExtraFixedBusyBuf,
1097								iExtraBufByteLength,
1098								WSPI_ReadDataAfterNotBusyCb,
1099								pWSPI,
1100								1);
1101        /* In case of synchronous transaction call the handling function implicitly */
1102		if (SPI_TXN_COMPLETE == status)
1103		{
1104			WSPI_ReadDataAfterNotBusyCb(hWSPI, OK);
1105		}
1106	}
1107	/* In the next case we try to read again even though the SPI line doesn't indicate any response  */
1108	else if ( pWSPI->bUseTempBuf )
1109	{	/* This case is handled for TempBuf only */
1110		/* Execute read without CMD */
1111		status = SPI_WriteRead(pWSPI->hSPI,
1112								NULL,
1113								0,
1114								pWSPI->pExtraFixedBusyBuf,
1115								WSPI_EXTRA_READ_AFTER_NO_RESPONSE,
1116								WSPI_ReadNotBusyAndDataCb,
1117								pWSPI,
1118								1);
1119		/* In case of synchronous transaction call the handling function implicitly */
1120		if (SPI_TXN_COMPLETE == status)
1121		{
1122			WSPI_ReadNotBusyAndDataCb(hWSPI, OK);
1123		}
1124	}
1125	else	/* Recovery from this one can be done by adjusting the length */
1126	{
1127		WLAN_REPORT_ERROR (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG,
1128			("WSPI FIXED BUSY (READ CALLBACK) Cmd = 0x%x, data pointer = %p data = 0x%x length = %d\n",
1129			pWSPI->uCmd, pRbuf, pRbuf[pWSPI->uFixedBusyLen + 1],pWSPI->length));
1130
1131        if (pWSPI->fErr)
1132        {
1133            (*pWSPI->fErr) ();
1134        }
1135
1136        if (pWSPI->fCb != NULL)
1137        {
1138            pWSPI->fCb (pWSPI->pCb, WSPI_ERR_BUS_BUSY);
1139        }
1140    }
1141}
1142
1143
1144/*
1145 * ----------------------------------------------------------------------------
1146 * Function :   WSPI_WriteAsync
1147 *
1148 * Input    :   void* hWSPI    - the WSPI handle
1149 *              UINT32 address - the address (in bytes) in the firmware to read the data from
1150 *              UINT8* data    - the buffer that holds the data to write
1151 *              UINT32 length  - the number of bytes to read
1152 *              WSPI_CB_T cb   - callback parameters
1153 *              BOOL bMore     - more read/write transaction will follow
1154 *              BOOL bSpaceReserved
1155                               - extra space padding has been reserved by an upper layer
1156 *
1157 * Output   :   none
1158 *
1159 * ReturnVal:   WSPI_Status_e
1160 *
1161 * Note(s)  :   1. set the WSPI cammand+address word
1162 *              2. set the command+address request struct
1163 *              3. submit the request
1164 *              4. set the write data request struct
1165 *              5. submit the request with execute flag
1166 *
1167 * -----------------------------------------------------------------------------
1168 */
1169int WSPI_WriteAsyncOld (TI_HANDLE hWSPI, UINT32 address, UINT8* data, UINT32 length, WSPI_CB_T* cb, BOOL bMore, BOOL bSpaceReserved)
1170{
1171    WSPI_t       *pWSPI = (WSPI_t*) hWSPI;
1172    int           ret = WSPI_OK;
1173
1174    if (length == 0)
1175    {
1176        return WSPI_ERR_WRONG_LENGTH;
1177    }
1178
1179    /*****************************/
1180    /* Write the command+address */
1181    /*****************************/
1182    pWSPI->uCmd = WSPI_CMD_WRITE;
1183
1184    /* Set bFixedAddr */
1185    if (pWSPI->bFixedAddr)
1186    {
1187        pWSPI->uCmd |= WSPI_CMD_FIXED;
1188    }
1189
1190    /* Set the length */
1191    pWSPI->uCmd |= ((UINT32)length << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
1192    /* Set the address */
1193    pWSPI->uCmd |= address & WSPI_CMD_BYTE_ADDR;
1194
1195    /* Write */
1196    ret |= SPI_WriteSync (pWSPI->hSPI, (UINT8*)&pWSPI->uCmd, WSPI_SIZEOF_UINT32);
1197
1198    /******************/
1199    /* Write the data */
1200    /******************/
1201
1202    /* Tell the lower machine to start executing after this submission */
1203    ret |= SPI_Write (pWSPI->hSPI,
1204                      data + bSpaceReserved * WSPI_SIZEOF_CMD,
1205                      length,
1206                      cb->CBFunc,
1207                      cb->CBArg,
1208                      1);
1209
1210    return ret;
1211}
1212
1213
1214/*
1215 * ----------------------------------------------------------------------------
1216 * Function :   WSPI_WriteAsync
1217 *
1218 * Input    :   void* hWSPI    - the WSPI handle
1219 *              UINT32 address - the address (in bytes) in the firmware to read the data from
1220 *              UINT8* data    - the buffer that holds the data to write
1221 *              UINT32 length  - the number of bytes to read
1222 *              WSPI_CB_T cb   - callback parameters
1223 *              BOOL bMore     - more read/write transaction will follow
1224 *              BOOL bSpaceReserved
1225                               - extra space padding has been reserved by an upper layer
1226 *
1227 * Output   :   none
1228 *
1229 * ReturnVal:   WSPI_Status_e
1230 *
1231 * Note(s)  :   3 options are checked in this function:
1232 *              1) (bSpaceReserved == TRUE)
1233 *                  write the command and the data in one chunk
1234 *              2) else (length <= WSPI_NO_EXTRA_ALLOC_SIZE)
1235 *                  copy Command + data to tempBuffer and write it in one chunk
1236 *              3) else - error !!!
1237 *
1238 * -----------------------------------------------------------------------------
1239 */
1240int WSPI_WriteAsync (TI_HANDLE hWSPI, UINT32 address, UINT8* data, UINT32 length, WSPI_CB_T* cb, BOOL bMore, BOOL bSpaceReserved)
1241{
1242    WSPI_t       *pWSPI = (WSPI_t*) hWSPI;
1243    int           status;
1244
1245    if (length == 0)
1246    {
1247        return WSPI_ERR_WRONG_LENGTH;
1248    }
1249
1250    /*****************************/
1251    /* Write the command+address */
1252    /*****************************/
1253    pWSPI->uCmd = WSPI_CMD_WRITE;
1254
1255    /* Set bFixedAddr */
1256    if (pWSPI->bFixedAddr)
1257    {
1258        pWSPI->uCmd |= WSPI_CMD_FIXED;
1259    }
1260
1261    /* Set the length */
1262    pWSPI->uCmd |= (length << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
1263    /* Set the address */
1264    pWSPI->uCmd |= address & WSPI_CMD_BYTE_ADDR;
1265
1266    if (bSpaceReserved)
1267    {
1268        /* If extra place was saved, transfer command and data in one transaction */
1269        *(UINT32*)data = pWSPI->uCmd;
1270
1271         status = SPI_Write (pWSPI->hSPI,
1272                             data,
1273                             length + WSPI_SIZEOF_CMD,
1274                             cb->CBFunc,
1275                             cb->CBArg,
1276                             bMore);
1277    }
1278
1279    /* If extra room was not saved for the command use temporary buffer */
1280    else if (length <= WSPI_NO_EXTRA_ALLOC_SIZE)
1281    {
1282      #if WSPI_NO_EXTRA_ALLOC_SIZE == 4 /* used for optimization */
1283        /* Copy data to the temporary buffer */
1284        *((UINT32*)(pWSPI->pTempBuf + WSPI_SIZEOF_CMD)) = *((UINT32*)data);
1285      #else
1286        os_memoryCopy (pWSPI->hOs, pWSPI->pTempBuf + WSPI_SIZEOF_CMD, data, length);
1287      #endif
1288
1289        /* Put the command at the beginning of the temporary buffer */
1290        *((UINT32*)pWSPI->pTempBuf) = pWSPI->uCmd;
1291
1292        status = SPI_Write (pWSPI->hSPI,
1293                            pWSPI->pTempBuf,
1294                            length + WSPI_SIZEOF_CMD,
1295                            cb->CBFunc,
1296                            cb->CBArg,
1297                            bMore);
1298    }
1299    else
1300    {
1301        WLAN_REPORT_ERROR (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG, ("No space reserved for command\n"));
1302
1303        return WSPI_ERR_UNKNOWN;
1304    }
1305
1306    return status;
1307}
1308
1309
1310/*
1311 * ----------------------------------------------------------------------------
1312 * Function :   WSPI_GenerateCRC7
1313 *
1314 * Input    :   UINT8* bits - a string that holds the bits, in the order from the first to last
1315 *              UINT32 len - the number of bits
1316 *
1317 * Output   :   none
1318 *
1319 * ReturnVal:   UINT8 - the CRC word
1320 *
1321 * Note(s)  :   calculates the CRC7 for the WSPI init command
1322 * -----------------------------------------------------------------------------
1323 */
1324static UINT8 WSPI_GenerateCRC7 (UINT8* bits, UINT32 len)
1325{
1326    UINT8 CRC, CRC0, CRC1, CRC2, CRC3, CRC4, CRC5, CRC6;
1327    UINT8 bit, temp;
1328    UINT32   i;
1329
1330    CRC0 = CRC1 = CRC2 = CRC3 = CRC4 = CRC5 = CRC6 = 0;
1331
1332    /* Calculate the CRC with the formula : G(x) = x^7 + x^3 + 1 */
1333    for (i = 0; i < len; i++)
1334    {
1335        bit = (bits[i / 8] & (1 << (7 - (i % 8)))) >> (7 - (i % 8));
1336        temp = CRC6;
1337        CRC6 = CRC5;
1338        CRC5 = CRC4;
1339        CRC4 = CRC3;
1340        CRC3 = CRC2;
1341        CRC2 = CRC1;
1342        CRC1 = CRC0;
1343        CRC0 = temp ^ bit;
1344        CRC3 = CRC0 ^ CRC3;
1345    }
1346
1347    CRC = CRC0;
1348    CRC |= CRC1 << 1;
1349    CRC |= CRC2 << 2;
1350    CRC |= CRC3 << 3;
1351    CRC |= CRC4 << 4;
1352    CRC |= CRC5 << 5;
1353    CRC |= CRC6 << 6;
1354
1355    return CRC;
1356}
1357
1358
1359/*
1360 * ----------------------------------------------------------------------------
1361 * Function :   WSPI_ReadAsyncCb
1362 *
1363 * Input    :   void* handle - a handle that was passed to the asynchronous request (usually the WSPI handle)
1364 *              int status - the status of the SPI request
1365 *
1366 * Output   :   none
1367 *
1368 * ReturnVal:   none
1369 *
1370 * Note(s)  :   this is a temp function for passing as a CB function to the SPI layer for checking the async mechanism
1371 * -----------------------------------------------------------------------------
1372 */
1373static void WSPI_ReadAsyncCb (void* hWSPI, int status)
1374{
1375    WSPI_t *pWSPI = (WSPI_t*) hWSPI;
1376    /* Check the fixed busy word */
1377    if ((pWSPI->uFixedBusy & 0x1) != 0)
1378    {
1379        pWSPI->fCb (pWSPI->pCb, 0);
1380    }
1381    else
1382    {
1383        WLAN_REPORT_ERROR (pWSPI->hReport, HAL_HW_CTRL_MODULE_LOG, ("WSPI FIXED BUSY (CALLBACK)\n"));
1384
1385        if (pWSPI->fErr)
1386        {
1387            (*pWSPI->fErr) ();
1388        }
1389
1390        pWSPI->fCb (pWSPI->pCb, -1);
1391    }
1392}
1393
1394
1395/*
1396 * ----------------------------------------------------------------------------
1397 * Function :   WSPI_SyncOverAsyncCb
1398 *
1399 * Input    :   void* handle - a handle that was passed to the asynchronous request
1400 *              int status - the status that the SPI request ended
1401 *
1402 * Output   :   none
1403 *
1404 * ReturnVal:   none
1405 *
1406 * Note(s)  :   this function just sets a flag so the sync SPI read/write function
1407 *              can return
1408 * -----------------------------------------------------------------------------
1409 */
1410#ifdef USE_SYNC_OVER_ASYNC
1411static void WSPI_SyncOverAsyncCb (void* hWSPI, int status)
1412{
1413    WSPI_t* pWSPI = (WSPI_t*) hWSPI;
1414
1415  #ifdef USE_SPI_DEBUG
1416    {
1417        SPI_t *pSPI = (SPI_t*) pWSPI->hSPI;
1418        pSPI->stat.uNumOfSyncOverAsync ++;
1419    }
1420  #endif
1421
1422    pWSPI->bSyncFlag = 1;
1423}
1424#endif
1425
1426
1427void WSPI_SetErrLog (void* hWSPI, void (*fErr)(void))
1428{
1429    WSPI_t* pWSPI = (WSPI_t*) hWSPI;
1430
1431    pWSPI->fErr = fErr;
1432}
1433
1434