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
148 static UINT8 WSPI_GenerateCRC7 (UINT8* bits, UINT32 len);
149 #ifndef USE_WRITE_READ_API
150 static void WSPI_WriteCmdCb (TI_HANDLE hWSPI, int status);
151 #endif
152 static void WSPI_ReadDataCb (TI_HANDLE hWSPI, int status);
153 #ifdef USE_SYNC_API
154 #ifdef USE_SYNC_OVER_ASYNC
155 static void WSPI_SyncOverAsyncCb (TI_HANDLE hWSPI, int status);
156 #endif
157 #endif
158 static void WSPI_ReadAsyncCb (TI_HANDLE hWSPI, int status);
159 static 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 */
WSPI_Open(TI_HANDLE hOs)179 TI_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 */
WSPI_Close(TI_HANDLE hWSPI)214 int 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 */
WSPI_Configure(TI_HANDLE hWSPI,TI_HANDLE hReport,const WSPIConfig_t * aConfig,WSPI_CB_T * cb)256 int 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
WSPI_ConfigureResetCb(TI_HANDLE hWSPI,int status)322 static 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 */
WSPI_ReadSync(TI_HANDLE hWSPI,UINT32 address,UINT8 * data,UINT32 length)388 int 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 */
WSPI_ReadAsyncOld(TI_HANDLE hWSPI,UINT32 address,UINT8 * data,UINT32 length,WSPI_CB_T * cb,BOOL bMore,BOOL bSpaceReserved)523 int 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 */
WSPI_WriteSync(TI_HANDLE hWSPI,UINT32 address,UINT8 * data,UINT32 length)630 int 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 */
WSPI_ReadAsync(TI_HANDLE hWSPI,UINT32 address,UINT8 * data,UINT32 length,WSPI_CB_T * cb,BOOL bMore,BOOL bSpaceReserved)734 int 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 */
WSPI_WriteCmdCb(TI_HANDLE hWSPI,int status)850 void 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 */
WSPI_ReadDataCb(TI_HANDLE hWSPI,int status)911 void 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 */
WSPI_ReadDataAfterNotBusyCb(TI_HANDLE hWSPI,int status)962 void 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 */
WSPI_ReadNotBusyAndDataCb(TI_HANDLE hWSPI,int status)1007 void 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 */
WSPI_HandleFixedBusy(TI_HANDLE hWSPI,UINT32 * pRbuf)1063 void 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 */
WSPI_WriteAsyncOld(TI_HANDLE hWSPI,UINT32 address,UINT8 * data,UINT32 length,WSPI_CB_T * cb,BOOL bMore,BOOL bSpaceReserved)1169 int 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 */
WSPI_WriteAsync(TI_HANDLE hWSPI,UINT32 address,UINT8 * data,UINT32 length,WSPI_CB_T * cb,BOOL bMore,BOOL bSpaceReserved)1240 int 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 */
WSPI_GenerateCRC7(UINT8 * bits,UINT32 len)1324 static 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 */
WSPI_ReadAsyncCb(void * hWSPI,int status)1373 static 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
WSPI_SyncOverAsyncCb(void * hWSPI,int status)1411 static 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
WSPI_SetErrLog(void * hWSPI,void (* fErr)(void))1427 void WSPI_SetErrLog (void* hWSPI, void (*fErr)(void))
1428 {
1429 WSPI_t* pWSPI = (WSPI_t*) hWSPI;
1430
1431 pWSPI->fErr = fErr;
1432 }
1433
1434