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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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