1 /**
2 * \file SPI_v1.c
3 *
4 * \brief MCSPI IP V1 specific driver implementation.
5 *
6 * This file contains the driver APIs for SPI.
7 */
9 /*
10 * Copyright (c) 2014-2019, Texas Instruments Incorporated
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * * Neither the name of Texas Instruments Incorporated nor the names of
25 * its contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
30 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
32 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
35 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
37 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
38 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
41 #include <string.h>
42 #include <stdint.h>
43 #include <stdbool.h>
44 #include <ti/drv/spi/MCSPI.h>
45 #include <ti/drv/spi/soc/SPI_v1.h>
46 #include <ti/csl/src/ip/mcspi/V0/mcspi.h>
47 #include <ti/csl/src/ip/mcspi/V0/hw_mcspi.h>
48 #include <ti/drv/spi/src/SPI_osal.h>
50 #ifdef __GNUC__
51 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
52 #endif
54 #define SPI_PARAMS_SIZE (32U)
56 #define MCSPI_TX_RX_FIFO_OFFSET (4U)
58 #define MCSPI_POLLING_TIMEOUT_LOOP (1000U)
60 /* SPI functions */
61 static void SPI_close_v1(SPI_Handle handle);
62 static void SPI_init_v1(SPI_Handle handle);
63 static SPI_Handle SPI_open_v1(SPI_Handle handle, const SPI_Params *params);
64 static bool SPI_transfer_v1(SPI_Handle handle,
65 SPI_Transaction *transaction);
66 static void SPI_transferCancel_v1(SPI_Handle handle);
67 static int32_t SPI_control_v1(SPI_Handle handle, uint32_t cmd, const void *arg);
69 /* MCSPI functions */
70 static void MCSPI_close_v1(MCSPI_Handle mcHandle);
71 static void MCSPI_init_v1(MCSPI_Handle mcHandle);
72 static MCSPI_Handle MCSPI_open_v1(MCSPI_Handle mcHandle, const MCSPI_Params *params);
73 static bool MCSPI_transfer_v1(MCSPI_Handle mcHandle,
74 SPI_Transaction *transaction);
75 static void MCSPI_transferCancel_v1(MCSPI_Handle mcHandle);
76 static int32_t MCSPI_control_v1(MCSPI_Handle mcHandle, uint32_t cmd, const void *arg);
78 static MCSPI_Handle MCSPI_get_handle(SPI_Handle handle);
79 static void MCSPI_get_params(const SPI_Params *params, MCSPI_Params *mcParams);
81 /* SPI function table for SPI_v1 implementation */
82 const SPI_FxnTable SPI_FxnTable_v1 = {
83 &SPI_close_v1,
84 &SPI_control_v1,
85 &SPI_init_v1,
86 &SPI_open_v1,
87 &SPI_transfer_v1,
88 &SPI_transferCancel_v1,
89 NULL
90 };
92 /* MCSPI function table for MCSPI_v1 implementation */
93 const MCSPI_FxnTable MCSPI_FxnTable_v1 =
94 {
95 &MCSPI_close_v1,
96 &MCSPI_control_v1,
97 &MCSPI_init_v1,
98 &MCSPI_open_v1,
99 &MCSPI_transfer_v1,
100 &MCSPI_transferCancel_v1
101 };
103 /*
104 * ======== MCSPI_get_handle ========
105 * @pre Function assumes that the handle is not NULL
106 */
107 static MCSPI_Handle MCSPI_get_handle(SPI_Handle handle)
108 {
109 MCSPI_Handle mcHandle = NULL;
110 SPI_v1_HWAttrs const *hwAttrs;
111 uint32_t chNum;
112 uint32_t i;
114 hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
115 chNum = hwAttrs->chNum;
117 for (i = 0; i < MCSPI_MAX_NUM_INSTANCES; i++)
118 {
119 if(MCSPI_config[i][chNum].handle == handle)
120 {
121 mcHandle = (MCSPI_Handle)&(MCSPI_config[i][chNum]);
122 break;
123 }
124 }
126 return (mcHandle);
127 }
129 /*
130 * ======== SPI_close_v1 ========
131 * @pre Function assumes that the handle is not NULL
132 */
133 static void SPI_close_v1(SPI_Handle handle)
134 {
135 SPI_v1_Object *object;
137 /* Input parameter validation */
138 if (handle != NULL)
139 {
140 /* Get the pointer to the object */
141 object = (SPI_v1_Object*)handle->object;
143 MCSPI_close_v1(object->mcHandle);
145 object->mcHandle = NULL;
146 }
147 }
149 /*
150 * ======== SPI_init_v1 ========
151 * @pre Function assumes that the handle is not NULL
152 */
153 static void SPI_init_v1(SPI_Handle handle)
154 {
155 MCSPI_Handle mcHandle;
156 SPI_v1_Object *object;
158 /* Input parameter validation */
159 if (handle != NULL)
160 {
161 object = (SPI_v1_Object*)handle->object;
163 /* Get multi-channel handle */
164 mcHandle = MCSPI_get_handle(handle);
165 if (mcHandle != NULL)
166 {
167 MCSPI_init_v1(mcHandle);
168 }
170 /* initialize object varibles */
171 object->hwi = NULL;
172 object->mutex = NULL;
173 object->transferComplete = NULL;
174 object->transferCallbackFxn = NULL;
175 object->chOpenedCnt = 0;
176 }
177 }
179 /*
180 * ======== SPI_open_v1 ========
181 * @pre Function assumes that the handle is not NULL
182 */
183 static SPI_Handle SPI_open_v1(SPI_Handle handle, const SPI_Params *params)
184 {
185 MCSPI_Handle mcHandle;
186 MCSPI_Params mcParams;
187 SPI_v1_Object *object;
189 /* Input parameter validation */
190 if (handle != NULL)
191 {
192 /* Get the pointer to the object */
193 object = (SPI_v1_Object*)handle->object;
195 /* Get multi-channel handle */
196 mcHandle = MCSPI_get_handle(handle);
197 if (mcHandle != NULL)
198 {
199 if (params != NULL)
200 {
201 /* covert SPI_Params to MCSPI_Params */
202 MCSPI_get_params(params, &mcParams);
204 /* save the transferCallbackFxn in SPI_Params */
205 object->transferCallbackFxn = params->transferCallbackFxn;
206 }
207 mcHandle = MCSPI_open_v1(mcHandle, &mcParams);
208 if (mcHandle != NULL)
209 {
210 object->mcHandle = mcHandle;
211 }
212 else
213 {
214 object->mcHandle = NULL;
215 }
216 }
217 }
219 return (handle);
220 }
222 /*
223 * ======== SPI_transfer_v1 ========
224 * @pre Function assumes that handle and transaction is not NULL
225 */
226 static bool SPI_transfer_v1(SPI_Handle handle, SPI_Transaction *transaction)
227 {
228 MCSPI_Handle mcHandle;
229 bool ret_val = (bool)false;
231 /* Input parameter validation */
232 if ((handle != NULL) && (transaction != NULL))
233 {
234 /* Get multi-channel handle */
235 mcHandle = MCSPI_get_handle(handle);
236 if (mcHandle != NULL)
237 {
238 ret_val = MCSPI_transfer_v1(mcHandle, transaction);
239 }
240 }
242 return (ret_val);
243 }
246 /*
247 * ======== SPI_transferCancel_v1 ========
248 */
249 static void SPI_transferCancel_v1(SPI_Handle handle)
250 {
251 MCSPI_Handle mcHandle;
253 /* Input parameter validation */
254 if (handle != NULL)
255 {
256 /* Get multi-channel handle */
257 mcHandle = MCSPI_get_handle(handle);
258 if (mcHandle != NULL)
259 {
260 MCSPI_transferCancel_v1(mcHandle);
261 }
262 }
263 return;
264 }
266 /*
267 * ======== SPI_control_v1 ========
268 */
269 static int32_t SPI_control_v1(SPI_Handle handle, uint32_t cmd, const void *arg)
270 {
271 MCSPI_Handle mcHandle;
272 int32_t ret_val = SPI_STATUS_ERROR;
274 /* Input parameter validation */
275 if (handle != NULL)
276 {
277 /* Get multi-channel handle */
278 mcHandle = MCSPI_get_handle(handle);
279 if (mcHandle != NULL)
280 {
281 ret_val = MCSPI_control_v1(mcHandle, cmd, arg);
282 }
283 }
285 return ret_val;
286 }
288 /*
289 * ======== MCSPI_get_params ========
290 * @pre Function assumes that params and mcParams are not NULL
291 */
292 static void MCSPI_get_params(const SPI_Params *params, MCSPI_Params *mcParams)
293 {
294 mcParams->transferMode = params->transferMode;
295 mcParams->transferTimeout = params->transferTimeout;
296 mcParams->transferCallbackFxn = NULL;
297 mcParams->mode = params->mode;
298 mcParams->bitRate = params->bitRate;
299 mcParams->dataSize = params->dataSize;
300 mcParams->frameFormat = params->frameFormat;
301 mcParams->custom = params->custom;
303 return;
304 }
306 /*
307 * ======== MCSPI_close_v1 ========
308 * @pre Function assumes that the handle is not NULL
309 */
310 static void MCSPI_close_v1(MCSPI_Handle mcHandle)
311 {
312 SPI_Handle handle;
313 SPI_v1_Object *object;
314 SPI_v1_HWAttrs const *hwAttrs;
315 SPI_v1_chObject *chObj;
316 uint32_t chNum;
318 /* Input parameter validation */
319 if (mcHandle != NULL)
320 {
321 /* Get SPI handle and channel */
322 handle = mcHandle->handle;
323 chNum = mcHandle->chnNum;
324 hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
326 /* Get the pointer to the instance object and channel object */
327 object = (SPI_v1_Object*)handle->object;
328 chObj = &(object->chObject[chNum]);
330 MCSPI_init_v1(mcHandle);
332 object->chOpenedCnt--;
333 if (object->chOpenedCnt == 0U)
334 {
335 if(object->transferComplete != NULL)
336 {
337 /* Destruct the semaphore */
338 (void)SPI_osalDeleteBlockingLock(object->transferComplete);
339 object->transferComplete = NULL;
340 }
342 /* All the channels closed */
343 if(object->hwi != NULL)
344 {
345 /* Destruct the Hwi */
346 (void)SPI_osalHardwareIntDestruct(object->hwi, (int32_t)hwAttrs->eventId);
347 object->hwi = NULL;
348 }
350 if(object->mutex != NULL)
351 {
352 /* Destruct the instance lock */
353 (void)SPI_osalDeleteBlockingLock(object->mutex);
354 object->mutex = NULL;
355 }
357 object->mcHandle = NULL;
358 object->transferCallbackFxn = NULL;
359 }
361 #ifdef SPI_DMA_ENABLE
362 if (hwAttrs->dmaMode == (bool)true)
363 {
364 MCSPI_dmaFreeChannel(mcHandle);
365 }
366 #endif
368 chObj->isOpen = (bool)false;
369 }
370 }
371 /* Get recieved data from the RX FIFO based on the data size */
373 /*
374 * ======== MCSPI_receiveData_v1 ========
375 *
376 * Get recieved data words from the RX FIFO based on the data size
377 *
378 * if dataSize <= 8 bits, read 8-bit word from RX FIFO,
379 * if 8 bits < dataSize <= 16 bits, read 16-bit word from RX FIFO,
380 * if 16 bits < dataSize <= 32 bits, read 32-bit word from RX FIFO,
381 */
382 static void *MCSPI_receiveData_v1 (uint32_t baseAddr, uint32_t dataSize, void *dataBuf, uint32_t chNum); /*for misra warnings*/
383 static void *MCSPI_receiveData_v1 (uint32_t baseAddr, uint32_t dataSize, void *dataBuf, uint32_t chNum)
384 {
385 void *dataPtr;
387 if (dataSize <= 8U)
388 {
389 *(uint8_t *)dataBuf = (uint8_t)McSPIReceiveData(baseAddr, chNum);
390 dataPtr = (void *)(((uint8_t *)dataBuf) + 1U);
391 }
392 else if (dataSize <= 16U)
393 {
394 *(uint16_t *)dataBuf = (uint16_t)McSPIReceiveData(baseAddr, chNum);
395 dataPtr = (void *)(((uint8_t *)dataBuf) + 2U);
396 }
397 else
398 {
399 *(uint32_t *)dataBuf = (uint32_t)McSPIReceiveData(baseAddr, chNum);
400 dataPtr = (void *)(((uint8_t *)dataBuf) + 4U);
401 }
403 return (dataPtr);
404 }
406 /*
407 * ======== MCSPI_transmitData_v1 ========
408 *
409 * Put data to the TX FIFO based on the data size (in # of bits)
410 *
411 * if dataSize <= 8 bits, write 8-bit word to TX FIFO,
412 * if 8 bits < dataSize <= 16 bits, write 16-bit word to TX FIFO,
413 * if 16 bits < dataSize <= 32 bits, write 32-bit word to TX FIFO,
414 */
415 void *MCSPI_transmitData_v1 (uint32_t baseAddr, uint32_t dataSize, void *dataBuf, uint32_t chNum); /*for misra warnings*/
416 void *MCSPI_transmitData_v1 (uint32_t baseAddr, uint32_t dataSize, void *dataBuf, uint32_t chNum)
417 {
418 void *dataPtr;
420 if (dataSize <= 8U)
421 {
422 McSPITransmitData(baseAddr, (uint32_t)(*(uint8_t *)dataBuf), chNum);
423 dataPtr = (void *)(((uint8_t *)dataBuf) + 1U);
424 }
425 else if (dataSize <= 16U)
426 {
427 McSPITransmitData(baseAddr, (uint32_t)(*(uint16_t *)dataBuf), chNum);
428 dataPtr = (void *)(((uint8_t *)dataBuf) + 2U);
429 }
430 else
431 {
432 McSPITransmitData(baseAddr, *(uint32_t *)dataBuf, chNum);
433 dataPtr = (void *)(((uint8_t *)dataBuf) + 4U);
434 }
436 return (dataPtr);
437 }
439 /*
440 * ======== MCSPI_xferSetup_v1 ========
441 * This functions configures the transfer mode (RX/TX, RX only or TX only)
442 * and setup the TX/RX FIFO trigger level when FIFO mode is enabled
443 */
444 void MCSPI_xferSetup_v1(MCSPI_Handle mcHandle, SPI_Transaction *transaction); /*for misra warnings*/
445 void MCSPI_xferSetup_v1(MCSPI_Handle mcHandle, SPI_Transaction *transaction)
446 {
447 SPI_Handle handle;
448 SPI_v1_Object *object;
449 SPI_v1_chObject *chObj;
450 uint32_t chNum;
451 SPI_v1_HWAttrs const *hwAttrs;
452 SPI_v1_ChnCfg const *chnCfg;
453 uint32_t transBytes=0;
454 uint32_t txFifo;
455 uint32_t rxFifo;
456 uint32_t countIndex;
457 uint32_t wordCount;
459 /* Get the pointer to the object and hwAttrs */
460 handle = mcHandle->handle;
461 chNum = mcHandle->chnNum;
462 object = (SPI_v1_Object *)handle->object;
463 chObj = &(object->chObject[chNum]);
464 hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
465 chnCfg = &(hwAttrs->chnCfg[chNum]);
467 if (chnCfg->trMode == MCSPI_RX_ONLY_MODE)
468 {
469 chObj->writeBufIdx = NULL;
470 chObj->writeCountIdx = 0;
471 }
472 else
473 {
474 chObj->writeBufIdx = (void *)transaction->txBuf;
475 if (chObj->writeBufIdx != NULL)
476 {
477 chObj->writeCountIdx = (uint32_t)transaction->count;
478 }
479 else
480 {
481 chObj->writeCountIdx = 0;
482 }
483 }
485 if (chnCfg->trMode == MCSPI_TX_ONLY_MODE)
486 {
487 chObj->readBufIdx = NULL;
488 chObj->readCountIdx = 0;
489 }
490 else
491 {
492 chObj->readBufIdx = (void *)transaction->rxBuf;
493 if (chObj->readBufIdx != NULL)
494 {
495 chObj->readCountIdx = (uint32_t)transaction->count;
496 }
497 else
498 {
499 chObj->readCountIdx = 0;
500 }
501 }
503 /* Enable FIFO's dependent on which mode of operation is chosen */
504 if (chnCfg->trMode == MCSPI_TX_RX_MODE)
505 {
506 if ((hwAttrs->txTrigLvl == 0U) || (hwAttrs->rxTrigLvl == 0U))
507 {
508 txFifo = MCSPI_TX_FIFO_DISABLE;
509 rxFifo = MCSPI_RX_FIFO_DISABLE;
510 object->fifoSize = 0;
511 }
512 else
513 {
514 txFifo = MCSPI_TX_FIFO_ENABLE;
515 rxFifo = MCSPI_RX_FIFO_ENABLE;
516 object->fifoSize = MCSPI_RX_TX_FIFO_SIZE;
517 }
518 }
519 else if (chnCfg->trMode == MCSPI_TX_ONLY_MODE)
520 {
521 /* TX_ONLY Mode */
522 if (hwAttrs->txTrigLvl == 0U)
523 {
524 txFifo = MCSPI_TX_FIFO_DISABLE;
525 object->fifoSize = 0;
526 }
527 else
528 {
529 txFifo = MCSPI_TX_FIFO_ENABLE;
530 object->fifoSize = MCSPI_FULL_FIFO_SIZE;
531 }
532 rxFifo = MCSPI_RX_FIFO_DISABLE;
533 }
534 else
535 {
536 /* RX_ONLY Mode */
537 txFifo = MCSPI_TX_FIFO_DISABLE;
538 if (hwAttrs->rxTrigLvl == 0U)
539 {
540 rxFifo = MCSPI_RX_FIFO_DISABLE;
541 object->fifoSize = 0;
542 }
543 else
544 {
545 rxFifo = MCSPI_RX_FIFO_ENABLE;
546 object->fifoSize = MCSPI_FULL_FIFO_SIZE;
547 }
548 }
549 McSPITxFIFOConfig(hwAttrs->baseAddr, txFifo, chNum);
550 McSPIRxFIFOConfig(hwAttrs->baseAddr, rxFifo, chNum);
552 if (object->fifoSize > 0U)
553 {
554 /* FIFO mode is enabled */
556 /* Set FIFO XFER levels */
557 transBytes = (uint32_t)transaction->count << chObj->wordLenShift;
559 if (transBytes <= object->fifoSize)
560 {
561 /* Transaction fits entirely in FIFO */
562 object->rxTrigLvl = transBytes;
563 object->txTrigLvl = transBytes;
564 }
565 else
566 {
567 /*
568 * Transaction count is more than FIFO size
569 */
570 object->rxTrigLvl = hwAttrs->rxTrigLvl;
571 object->txTrigLvl = hwAttrs->txTrigLvl;
573 #ifdef SPI_DMA_ENABLE
574 if (hwAttrs->dmaMode == (bool)true)
575 {
576 /*
577 * In DMA mode, update the transaction count to be
578 * multiple of FIFO trigger level size
579 */
580 if (chnCfg->trMode == MCSPI_RX_ONLY_MODE)
581 {
582 transBytes = (transBytes / object->rxTrigLvl) * object->rxTrigLvl;
583 }
584 else
585 {
586 transBytes = (transBytes / object->txTrigLvl) * object->txTrigLvl;
587 }
588 transaction->count = (uint32_t)(transBytes >> chObj->wordLenShift);
589 }
590 else
591 #endif
592 {
593 /*
594 * In non-DMA mode, if the RX trigger level equals to the FIFO size,
595 * set the RX trigger level less than the FIFO size, so that TX FIFO
596 * will not under run.
597 */
598 if ((chnCfg->trMode == MCSPI_TX_RX_MODE) &&
599 (object->rxTrigLvl == object->fifoSize))
600 {
601 object->rxTrigLvl -= MCSPI_TX_RX_FIFO_OFFSET;
602 }
603 }
604 }
605 McSPIFIFOTrigLvlSet(hwAttrs->baseAddr, (uint8_t)object->rxTrigLvl,
606 (uint8_t)object->txTrigLvl, chnCfg->trMode);
607 }
609 /*
610 * convert trigger level (in bytes) to word count
611 * based on the word length
612 */
613 if (object->fifoSize > 0U)
614 {
615 #ifdef SPI_DMA_ENABLE
616 if (hwAttrs->dmaMode == (bool)true)
617 {
618 wordCount = object->txTrigLvl >> chObj->wordLenShift;
619 }
620 else
621 #endif
622 {
623 if (transBytes > MCSPI_RX_TX_FIFO_SIZE)
624 {
625 wordCount = (uint32_t)MCSPI_RX_TX_FIFO_SIZE >> (chObj->wordLenShift);
626 }
627 else
628 {
629 wordCount = transBytes >> chObj->wordLenShift;
630 }
631 }
632 }
633 else
634 {
635 wordCount = 1U;
636 }
637 /* Set number of words to be transmitted */
638 McSPIWordCountSet(hwAttrs->baseAddr, (uint16_t)transaction->count);
640 if ((SPI_SLAVE == chObj->spiParams.mode) && (chObj->writeCountIdx != 0U))
641 {
642 #ifdef SPI_DMA_ENABLE
643 if (hwAttrs->dmaMode == (bool)false)
644 {
645 for (countIndex = 0; countIndex < wordCount; countIndex++)
646 {
647 chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
648 chObj->spiParams.dataSize,
649 chObj->writeBufIdx,
650 chNum);
651 chObj->writeCountIdx--;
652 }
653 }
654 #else
655 for (countIndex = 0; countIndex < wordCount; countIndex++)
656 {
657 chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
658 chObj->spiParams.dataSize,
659 chObj->writeBufIdx,
660 chNum);
661 chObj->writeCountIdx--;
662 }
663 #endif
664 }
665 }
667 static bool MCSPI_pollingXferTimeout_v1(uint32_t *timeout, uint32_t *timeoutLoop, uint32_t timeoutVal);
668 static bool MCSPI_pollingXferTimeout_v1(uint32_t *timeout, uint32_t *timeoutLoop, uint32_t timeoutVal)
669 {
670 bool timeoutFlag = (bool)false;
672 if (*timeout > 0U)
673 {
674 *timeout -= 1U;
675 if (*timeout == 0U)
676 {
677 if (*timeoutLoop > 0U)
678 {
679 *timeoutLoop -= 1U;
680 *timeout = timeoutVal;
681 }
682 }
683 }
684 else
685 {
686 if (*timeoutLoop == 0U)
687 {
688 /* Polling transfer timed out */
689 timeoutFlag = (bool)true;
690 }
691 }
693 return (timeoutFlag);
694 }
696 /*
697 * ======== MCSPI_primeTransfer_v1 ========
698 * This functions configures the transmit and receive channels for a given
699 * MCSPI_Handle and SPI_Transaction.
700 *
701 * Slave driver needs to pre-fill the TX trigger level size data to TX FIFO first before
702 * the channel is enabled. If the transfer size is less than the FIFO size (32 bytes), the
703 * TX/RX trigger level is set to the transfer size. If the transfer size is greater than
704 * or equal to the FIFO size, the TX/RX trigger level is set to the FIFO size. The pre-filling
705 * is required to ensure the TX data is available for master to receive when the channel is
706 * enabled.
707 *
708 * In polling mode, master driver continuously writes 1 byte TX data to TX FIFO followed
709 * by reading 1 byte RX data from the RX FIFO until all the data are transfered. slave driver
710 * continuously reads 1 byte data from the RX FIFO followed by writing 1 byte TX data to TX
711 * FIFO until all the data are transfered.
712 *
713 * In interrupt mode, master driver enables TX empty, RX full and end of word count interrupts.
714 * slave driver enabls RX full interrupt. The TX/RX data are handled in the ISR.
715 *
716 * @pre Function assumes that the handle and transaction is not NULL
717 */
718 static void MCSPI_primeTransfer_v1(MCSPI_Handle mcHandle, SPI_Transaction *transaction); /* for misra warnings */
719 static void MCSPI_primeTransfer_v1(MCSPI_Handle mcHandle, SPI_Transaction *transaction)
720 {
721 SPI_Handle handle;
722 SPI_v1_Object *object;
723 SPI_v1_chObject *chObj;
724 uint32_t chNum;
725 SPI_v1_HWAttrs const *hwAttrs;
726 SPI_v1_ChnCfg const *chnCfg;
727 uint32_t channelStatus = 0;
728 uint32_t intStatus;
729 uint32_t timeout;
730 uint32_t timeoutLoop;
731 bool timeoutFlag;
733 /* Get the pointer to the object and hwAttrs */
734 handle = mcHandle->handle;
735 chNum = mcHandle->chnNum;
736 object = (SPI_v1_Object *)handle->object;
737 chObj = &(object->chObject[chNum]);
738 hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
739 chnCfg = &(hwAttrs->chnCfg[chNum]);
741 /* Enable the McSPI channel for communication */
742 McSPIChannelEnable(hwAttrs->baseAddr, chNum);
744 /* setup transfer mode and FIFO trigger levels */
745 MCSPI_xferSetup_v1(mcHandle, transaction);
747 /* Interrupt Mode */
748 if(chObj->operMode != (uint32_t)SPI_OPER_MODE_POLLING)
749 {
750 intStatus = MCSPI_INT_EOWKE;
751 if (chnCfg->trMode == MCSPI_TX_ONLY_MODE)
752 {
753 intStatus |= (uint32_t)MCSPI_INT_TX_EMPTY(chNum);
754 }
755 else if (chnCfg->trMode == MCSPI_RX_ONLY_MODE)
756 {
757 intStatus |= (uint32_t)(MCSPI_INT_RX_FULL(chNum));
758 }
759 else
760 {
761 intStatus |= (uint32_t)(MCSPI_INT_RX_FULL(chNum)) | (uint32_t)(MCSPI_INT_TX_EMPTY(chNum));
762 }
763 McSPIIntStatusClear(hwAttrs->baseAddr, intStatus);
765 if(SPI_MASTER == chObj->spiParams.mode)
766 {
767 McSPIIntEnable(hwAttrs->baseAddr, intStatus);
769 if (hwAttrs->chMode == MCSPI_SINGLE_CH)
770 {
771 /* Assert un-used chip select (Force SPIEN) */
772 McSPICSAssert(hwAttrs->baseAddr, chNum);
773 }
774 }
775 else
776 {
777 McSPIIntEnable(hwAttrs->baseAddr, (uint32_t)(MCSPI_INT_RX_FULL(chNum)));
778 }
779 }
780 /* Polling mode */
781 else
782 {
783 if ((SPI_MASTER == chObj->spiParams.mode) &&
784 (hwAttrs->chMode == MCSPI_SINGLE_CH))
785 {
786 /* SPIEN line is forced to low state.*/
787 McSPICSAssert(hwAttrs->baseAddr, chNum);
788 }
790 /* Initialize the timeout value and loop count in polling mode */
791 timeout = chObj->spiParams.transferTimeout;
792 timeoutLoop = MCSPI_POLLING_TIMEOUT_LOOP;
793 timeoutFlag = (bool)false;
795 /* Polling mode transfer */
796 while (((chObj->readCountIdx != 0U) || (chObj->writeCountIdx != 0U)) &&
797 (timeoutFlag == (bool)false))
798 {
799 channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
800 if ((SPI_MASTER == chObj->spiParams.mode) && (chObj->writeCountIdx != 0U))
801 {
802 while (0U == (channelStatus & CSL_MCSPI_CH0STAT_TXS_MASK))
803 {
804 channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
805 timeoutFlag = MCSPI_pollingXferTimeout_v1(&timeout,
806 &timeoutLoop,
807 chObj->spiParams.transferTimeout);
808 if (timeoutFlag == (bool)true)
809 {
810 break;
811 }
812 }
813 if (timeoutFlag == (bool)false)
814 {
815 chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
816 chObj->spiParams.dataSize,
817 chObj->writeBufIdx,
818 chNum);
819 chObj->writeCountIdx--;
820 }
821 }
823 if ((chObj->readCountIdx != 0U) && (timeoutFlag == (bool)false))
824 {
825 while (0U == (channelStatus & CSL_MCSPI_CH0STAT_RXS_MASK))
826 {
827 channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
828 timeoutFlag = MCSPI_pollingXferTimeout_v1(&timeout,
829 &timeoutLoop,
830 chObj->spiParams.transferTimeout);
831 if (timeoutFlag == (bool)true)
832 {
833 break;
834 }
835 }
836 if (timeoutFlag == (bool)false)
837 {
838 chObj->readBufIdx = MCSPI_receiveData_v1(hwAttrs->baseAddr,
839 chObj->spiParams.dataSize,
840 chObj->readBufIdx,
841 chNum);
842 chObj->readCountIdx--;
843 }
844 }
846 if ((SPI_SLAVE == chObj->spiParams.mode) &&
847 (chObj->writeCountIdx != 0U) &&
848 (timeoutFlag == (bool)false))
849 {
850 chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
851 chObj->spiParams.dataSize,
852 chObj->writeBufIdx,
853 chNum);
855 chObj->writeCountIdx--;
856 }
858 if ((chObj->readCountIdx != 0U) || (chObj->writeCountIdx != 0U))
859 {
860 timeoutFlag = MCSPI_pollingXferTimeout_v1(&timeout,
861 &timeoutLoop,
862 chObj->spiParams.transferTimeout);
863 if (timeoutFlag == (bool)true)
864 {
865 /* Transfer timeout */
866 transaction->status=SPI_TRANSFER_TIMEOUT;
867 }
868 }
869 else
870 {
871 /* Transfer completed successfully */
872 transaction->status=SPI_TRANSFER_COMPLETED;
873 }
874 }
876 if ((SPI_MASTER == chObj->spiParams.mode) &&
877 (hwAttrs->chMode == MCSPI_SINGLE_CH))
878 {
879 /* Force SPIEN line to the inactive state.*/
880 McSPICSDeAssert(hwAttrs->baseAddr, chNum);
881 }
883 /* Disable the McSPI channel.*/
884 McSPIChannelDisable(hwAttrs->baseAddr, chNum);
886 chObj->transaction = NULL;
887 }
888 }
890 /*
891 * ======== MCSPI_v1_hwiFxn ========
892 * ISR for the MCSPI in master and slave mode
893 *
894 * For both TX and RX enabled mode, the following interrupts are enabled:
895 *
896 * TX empty interrupt (master only)
897 * RX full interrupt
898 * End of word count interrupt (master only)
899 *
900 * When TX empty interrupt happens, ISR will continuously write TX data
901 * to TX FIFO until the FIFO is full or all the TX data is sent out.
902 *
903 * When RX full interrupt happens, ISR will continuously read 1 byte
904 * RX data from RX FIFO followed by writing 1 byte TX data to TX FIFO
905 * until the RX FIFO is empty. When all the bytes are transfered or
906 * end of word count interrupt happens (master only), ISR
907 * will disable all the interrupts and call back to the application
908 * in callback mode or release the semaphore in blocking mode.
909 *
910 * If the remaining RX count is less than the RX FIFO size,
911 * ISR will set the RX trigger level to the remaing RX count.
912 *
913 * To prevent TX FIFO underrun, RX FIFO trigger level is set less
914 * than the max TX FIFO size
915 */
916 static void MCSPI_v1_hwiFxn (uintptr_t arg); /* for misra warnings */
917 static void MCSPI_v1_hwiFxn (uintptr_t arg)
918 {
919 MCSPI_Handle mcHandle;
920 SPI_Handle handle;
921 SPI_v1_Object *object;
922 SPI_v1_chObject *chObj;
923 uint32_t chNum;
924 SPI_v1_HWAttrs const *hwAttrs;
925 SPI_v1_ChnCfg const *chnCfg;
926 uint32_t intCode = 0;
927 bool trigLvlChg = (bool)false;
928 uint32_t rdBytes;
929 uint32_t wrBytes;
930 uint32_t chnStatus;
931 bool loopFlag = (bool)true;
932 uint32_t masterTxCnt = 0;
934 /* Get the pointer to the object and hwAttrs */
935 mcHandle = (MCSPI_Handle)arg;
936 handle = mcHandle->handle;
937 chNum = mcHandle->chnNum;
938 object = (SPI_v1_Object *)handle->object;
939 chObj = &(object->chObject[chNum]);
940 hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
941 chnCfg = &(hwAttrs->chnCfg[chNum]);
943 intCode = McSPIIntStatusGet(hwAttrs->baseAddr);
945 while (((chObj->readCountIdx != 0U) || (chObj->writeCountIdx != 0U)) &&
946 (loopFlag == (bool)true))
947 {
948 chnStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
949 if (SPI_MASTER == chObj->spiParams.mode)
950 {
951 if (chObj->writeCountIdx != 0U)
952 {
953 if (0U == (chnStatus & CSL_MCSPI_CH0STAT_TXFFF_MASK))
954 {
955 /* TX FIFO is not full */
956 chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
957 chObj->spiParams.dataSize,
958 chObj->writeBufIdx,
959 chNum);
960 chObj->writeCountIdx--;
961 masterTxCnt++;
962 }
963 else
964 {
965 loopFlag = (bool)false;
966 }
967 }
968 else
969 {
970 loopFlag = (bool)false;
971 }
972 }
974 if (chObj->readCountIdx != 0U)
975 {
976 if ((0U == (chnStatus & CSL_MCSPI_CH0STAT_RXFFE_MASK)) ||
977 (0U != (chnStatus & CSL_MCSPI_CH0STAT_RXS_MASK)))
978 {
979 /* RX FIFO is not empty or RX register is full */
980 chObj->readBufIdx = MCSPI_receiveData_v1(hwAttrs->baseAddr,
981 chObj->spiParams.dataSize,
982 chObj->readBufIdx,
983 chNum);
984 chObj->readCountIdx--;
985 loopFlag = (bool)true;
986 }
987 else
988 {
989 if (SPI_MASTER != chObj->spiParams.mode)
990 {
991 loopFlag = (bool)false;
992 }
993 }
994 }
995 else
996 {
997 if (SPI_MASTER != chObj->spiParams.mode)
998 {
999 loopFlag = (bool)false;
1000 }
1001 }
1003 if ((SPI_SLAVE == chObj->spiParams.mode) &&
1004 (chObj->writeCountIdx != 0U))
1005 {
1006 if (0U == (chnStatus & CSL_MCSPI_CH0STAT_TXFFF_MASK))
1007 {
1008 /* TX FIFO is not full */
1009 chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
1010 chObj->spiParams.dataSize,
1011 chObj->writeBufIdx,
1012 chNum);
1013 chObj->writeCountIdx--;
1014 loopFlag = (bool)true;
1015 }
1016 }
1017 if (masterTxCnt == object->txTrigLvl)
1018 {
1019 loopFlag = (bool)false;
1020 }
1021 }
1023 /* Update the TX trigger level */
1024 if (chObj->writeCountIdx != 0U)
1025 {
1026 wrBytes = chObj->writeCountIdx << chObj->wordLenShift;
1027 if (wrBytes < object->txTrigLvl)
1028 {
1029 object->txTrigLvl = wrBytes;
1030 trigLvlChg = (bool)true;
1031 }
1032 }
1034 /* Update the RX trigger level */
1035 if (chObj->readCountIdx > 1U)
1036 {
1037 rdBytes = chObj->readCountIdx << chObj->wordLenShift;
1038 if (rdBytes < object->rxTrigLvl)
1039 {
1040 object->rxTrigLvl = rdBytes;
1041 if (chObj->writeCountIdx == 0U)
1042 {
1043 object->txTrigLvl = object->fifoSize;
1044 }
1045 trigLvlChg = (bool)true;
1046 }
1047 }
1049 if (trigLvlChg == (bool)true)
1050 {
1051 McSPIFIFOTrigLvlSet(hwAttrs->baseAddr, (uint8_t)object->rxTrigLvl,
1052 (uint8_t)object->txTrigLvl, chnCfg->trMode);
1053 }
1055 /*if (MCSPI_INT_EOWKE == (intCode & MCSPI_INT_EOWKE))*/
1056 if ((MCSPI_INT_EOWKE == (intCode & MCSPI_INT_EOWKE)) ||
1057 ((chObj->writeCountIdx == 0U) && (chObj->readCountIdx <= 1U) && (chnCfg->trMode != MCSPI_TX_ONLY_MODE)))
1058 {
1059 chnStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
1060 while ((0U == (chnStatus & CSL_MCSPI_CH0STAT_EOT_MASK)))
1061 {
1062 chnStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
1063 }
1064 if (chObj->readCountIdx != 0U)
1065 {
1066 /* Read final RX byte */
1067 chObj->readBufIdx = MCSPI_receiveData_v1(hwAttrs->baseAddr,
1068 chObj->spiParams.dataSize,
1069 chObj->readBufIdx,
1070 chNum);
1071 chObj->readCountIdx--;
1072 }
1073 /* Transaction Done */
1074 intCode = (uint32_t)(MCSPI_INT_RX_FULL(chNum)) |
1075 (uint32_t)(MCSPI_INT_TX_EMPTY(chNum)) |
1076 MCSPI_INT_EOWKE;
1077 McSPIIntDisable(hwAttrs->baseAddr,intCode);
1078 McSPIIntStatusClear(hwAttrs->baseAddr, intCode);
1079 if ((SPI_MASTER == chObj->spiParams.mode) &&
1080 (hwAttrs->chMode == MCSPI_SINGLE_CH))
1081 {
1082 McSPICSDeAssert(hwAttrs->baseAddr, chNum);
1083 }
1084 McSPIChannelDisable(hwAttrs->baseAddr, chNum);
1085 chObj->transaction->status=SPI_TRANSFER_COMPLETED;
1086 MCSPI_transferCallback_v1((MCSPI_Handle)arg, chObj->transaction);
1087 }
1089 McSPIIntStatusClear(hwAttrs->baseAddr, intCode);
1090 }
1092 /*
1093 * ======== MCSPI_init_v1 ========
1094 * @pre Function assumes that the handle is not NULL
1095 */
1096 static void MCSPI_init_v1(MCSPI_Handle mcHandle)
1097 {
1098 SPI_Handle handle;
1099 SPI_v1_Object *object;
1100 SPI_v1_chObject *chObj;
1101 uint32_t chNum;
1103 /* Input parameter validation */
1104 if (mcHandle != NULL)
1105 {
1106 /* Get the pointer to the object and hwAttrs */
1107 handle = mcHandle->handle;
1108 object = (SPI_v1_Object*)handle->object;
1109 for(chNum = MCSPI_CHANNEL_0; chNum < MCSPI_MAX_NUM_CHANNELS; chNum++)
1110 {
1111 chObj = &(object->chObject[chNum]);
1112 /* reset channel object */
1113 (void)memset(chObj, 0, sizeof(SPI_v1_chObject));
1114 chObj->isOpen = (bool)false;
1115 }
1116 }
1117 }
1119 /*
1120 * ======== MCSPI_open_v1 ========
1121 * @pre Function assumes that the mcHandle is not NULL
1122 */
1123 static MCSPI_Handle MCSPI_open_v1(MCSPI_Handle mcHandle,
1124 const MCSPI_Params *params)
1125 {
1126 SPI_Handle handle;
1127 MCSPI_Handle retMcHandle = mcHandle;
1128 const MCSPI_Params *pParams = params;
1129 SemaphoreP_Params semParams;
1130 SPI_v1_Object *object;
1131 SPI_v1_chObject *chObj;
1132 uint32_t chNum;
1133 SPI_v1_HWAttrs const *hwAttrs;
1134 SPI_v1_ChnCfg const *chnCfg;
1135 OsalRegisterIntrParams_t interruptRegParams;
1136 uint32_t ret_flag = 0u;
1138 /* Input parameter validation */
1139 if (mcHandle != NULL)
1140 {
1141 /* Get the pointer to the object and hwAttrs */
1142 handle = mcHandle->handle;
1143 chNum = mcHandle->chnNum;
1144 object = (SPI_v1_Object *)handle->object;
1145 chObj = &(object->chObject[chNum]);
1146 hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
1147 chnCfg = &(hwAttrs->chnCfg[chNum]);
1149 /* Determine if the device index was already opened */
1150 if(chObj->isOpen == (bool)true) {
1151 retMcHandle = NULL;
1152 }
1153 else
1154 {
1155 /* Mark the channel handle as being used */
1156 chObj->isOpen = (bool)true;
1158 /* Store the SPI parameters */
1159 if (pParams == NULL)
1160 {
1161 /* No params passed in, so use the defaults */
1162 MCSPI_Params_init(&(chObj->spiParams));
1163 pParams = &(chObj->spiParams);
1164 }
1165 else
1166 {
1167 chObj->spiParams = *pParams;
1168 }
1170 if (pParams->dataSize < 4U)
1171 {
1172 /* wrong data size param */
1173 retMcHandle = NULL;
1174 ret_flag = 1U;
1175 }
1176 else if (pParams->dataSize <= 8U)
1177 {
1178 chObj->wordLenShift = 0U;
1179 }
1180 else if (pParams->dataSize <= 16U)
1181 {
1182 chObj->wordLenShift = 1U;
1183 }
1184 else if (pParams->dataSize <= 32U)
1185 {
1186 chObj->wordLenShift = 2U;
1187 }
1188 else
1189 {
1190 /* wrong data size param */
1191 retMcHandle = NULL;
1192 ret_flag = 1U;
1193 }
1195 /* Store the current mode. Extract operating mode from hwAttrs and params */
1196 if(SPI_MODE_BLOCKING == pParams->transferMode)
1197 {
1198 if ((bool)true == hwAttrs->enableIntr)
1199 {
1200 chObj->operMode = (uint32_t)SPI_OPER_MODE_BLOCKING;
1201 }
1202 #ifdef SPI_DMA_ENABLE
1203 else if ((bool)true == hwAttrs->dmaMode)
1204 {
1205 chObj->operMode = (uint32_t)SPI_OPER_MODE_BLOCKING;
1206 }
1207 #endif
1208 else
1209 {
1210 chObj->operMode = (uint32_t)SPI_OPER_MODE_POLLING;
1211 }
1212 }
1213 else
1214 {
1215 chObj->operMode = (uint32_t)SPI_OPER_MODE_CALLBACK;
1216 /* Check to see if a callback function was defined for async mode */
1217 if ((pParams->transferCallbackFxn == NULL) &&
1218 (object->transferCallbackFxn == NULL))
1219 {
1220 retMcHandle = NULL;
1221 ret_flag = 1U;
1222 }
1223 }
1225 if ((chObj->operMode != (uint32_t)SPI_OPER_MODE_POLLING) &&
1226 (object->hwi == NULL))
1227 {
1228 /* register interrrupt when the 1st
1229 channel of the instance is opened */
1230 Osal_RegisterInterrupt_initParams(&interruptRegParams);
1232 interruptRegParams.corepacConfig.name=NULL;
1233 #ifdef __TI_ARM_V7R4__
1234 interruptRegParams.corepacConfig.priority=0x8U;
1235 #else
1236 interruptRegParams.corepacConfig.priority=0x20U;
1237 #endif
1238 interruptRegParams.corepacConfig.corepacEventNum = (int32_t)hwAttrs->eventId;
1239 interruptRegParams.corepacConfig.intVecNum = (int32_t)hwAttrs->intNum; /* Host Interrupt vector */
1240 interruptRegParams.corepacConfig.isrRoutine = (void (*)(uintptr_t))(&MCSPI_v1_hwiFxn);
1241 interruptRegParams.corepacConfig.arg = (uintptr_t)mcHandle;
1243 (void)SPI_osalRegisterInterrupt(&interruptRegParams,&(object->hwi));
1245 if(object->hwi == NULL)
1246 {
1247 MCSPI_close_v1(mcHandle);
1248 ret_flag = 1u;
1249 retMcHandle = NULL;
1250 }
1251 }
1253 if(ret_flag == 0u)
1254 {
1255 /*
1256 * Construct thread safe handles for this SPI peripheral
1257 * Semaphore to provide exclusive access to the SPI peripheral
1258 */
1259 if (object->mutex == NULL)
1260 {
1261 SPI_osalSemParamsInit(&semParams);
1262 semParams.mode = SemaphoreP_Mode_BINARY;
1263 object->mutex = SPI_osalCreateBlockingLock(1U, &semParams);
1264 }
1266 if (chObj->operMode == (uint32_t)SPI_OPER_MODE_BLOCKING)
1267 {
1268 /*
1269 * Construct a semaphore to block task execution for the duration of the
1270 * SPI transfer
1271 */
1272 if (object->transferComplete == NULL)
1273 {
1274 SPI_osalSemParamsInit(&semParams);
1275 semParams.mode = SemaphoreP_Mode_BINARY;
1276 object->transferComplete = SPI_osalCreateBlockingLock(0U, &semParams);
1277 }
1278 }
1280 chObj->transaction = NULL;
1282 /* Extract clock mode from the frame format */
1283 switch(pParams->frameFormat)
1284 {
1285 case SPI_POL0_PHA0:
1286 chObj->clockMode = MCSPI_CLK_MODE_0;
1287 break;
1289 case SPI_POL0_PHA1:
1290 chObj->clockMode = MCSPI_CLK_MODE_1;
1291 break;
1293 case SPI_POL1_PHA0:
1294 chObj->clockMode = MCSPI_CLK_MODE_2;
1295 break;
1297 case SPI_POL1_PHA1:
1298 chObj->clockMode = MCSPI_CLK_MODE_3;
1299 break;
1301 default:
1302 chObj->clockMode = MCSPI_CLK_MODE_2;
1303 break;
1304 }
1306 if (object->chOpenedCnt == 0U)
1307 {
1308 #ifdef SPI_DMA_ENABLE
1309 if (hwAttrs->dmaMode == (bool)true)
1310 {
1311 /* DMA Configuration */
1312 if(SPI_STATUS_SUCCESS == MCSPI_dmaConfig(mcHandle))
1313 {
1314 McSPIDMADisable(hwAttrs->baseAddr,
1315 ((uint32_t) MCSPI_DMA_RX_EVENT | (uint32_t) MCSPI_DMA_TX_EVENT),
1316 chNum);
1317 }
1318 else
1319 {
1320 ret_flag = 1u;
1321 retMcHandle = NULL;
1322 }
1323 }
1324 #endif
1325 if(ret_flag == 0u)
1326 {
1327 /* Reset SPI Peripheral */
1328 McSPIReset(hwAttrs->baseAddr);
1330 MCSPISysConfigSetup(hwAttrs->baseAddr, MCSPI_CLOCKS_OCP_ON_FUNC_ON,
1331 MCSPI_SIDLEMODE_NO, MCSPI_WAKEUP_DISABLE,
1332 MCSPI_AUTOIDLE_OFF);
1334 if (hwAttrs->chMode == MCSPI_SINGLE_CH)
1335 {
1336 /* Configure 3 pin or 4 pin mode */
1337 if((uint32_t)SPI_PINMODE_3_PIN == hwAttrs->pinMode)
1338 {
1339 /* Disable chip select pin.*/
1340 McSPICSDisable(hwAttrs->baseAddr);
1341 }
1342 else
1343 {
1344 /* Enable chip select pin.*/
1345 McSPICSEnable(hwAttrs->baseAddr);
1346 }
1347 }
1348 }
1349 }
1351 if ((object->chOpenedCnt != 0U) &&
1352 ((pParams->mode != SPI_MASTER) || (object->mode != SPI_MASTER)))
1353 {
1355 /*
1356 * McSPI supports multiple master channels or single slave channel per instance:
1357 *
1358 * 1. if an instance has already had a channle opened in SPI_MASTER mode,
1359 * the new channel being opened should have the same SPI mode as the previous
1360 * channel opened.
1361 *
1362 * 2. if an instance has already had a channle opened in SPI_SLAVE mode,
1363 * no new channel can be opened.
1364 */
1365 ret_flag = 1u;
1366 retMcHandle = NULL;
1367 }
1369 if(ret_flag == 0U)
1370 {
1371 if(SPI_MASTER == pParams->mode)
1372 {
1373 if (object->chOpenedCnt == 0U)
1374 {
1375 /*
1376 * first channel opened in this instance,
1377 * enable SPI Master
1378 */
1379 McSPIMasterModeEnable(hwAttrs->baseAddr);
1380 object->mode = SPI_MASTER;
1381 }
1383 /* Configure the peripheral as single channel SPI Master */
1384 (void)McSPIMasterModeConfig(hwAttrs->baseAddr,
1385 hwAttrs->chMode,
1386 chnCfg->trMode,
1387 chnCfg->dataLineCommMode,
1388 chNum);
1389 /* Clock configuration */
1390 McSPIClkConfig(hwAttrs->baseAddr,
1391 hwAttrs->inputClkFreq,
1392 pParams->bitRate,
1393 chNum,
1394 chObj->clockMode);
1396 /* configure initial SPI delay only in signle master mode */
1397 if ((hwAttrs->chMode == MCSPI_SINGLE_CH) && (object->chOpenedCnt == 0U))
1398 {
1399 McSPIInitDelayConfig(hwAttrs->baseAddr, hwAttrs->initDelay);
1400 }
1401 }
1402 else
1403 {
1404 if (object->chOpenedCnt == 0U)
1405 {
1406 /*
1407 * first channel opened in this instance,
1408 * enable SPI Slave
1409 */
1410 McSPISlaveModeEnable(hwAttrs->baseAddr);
1411 object->mode = SPI_SLAVE;
1412 }
1414 /* Clock configuration */
1415 McSPIClkConfig(hwAttrs->baseAddr,
1416 hwAttrs->inputClkFreq,
1417 pParams->bitRate,
1418 chNum,
1419 chObj->clockMode);
1421 /* Set pin direction. */
1422 (void)MCSPIPinDirSet(hwAttrs->baseAddr,
1423 chnCfg->trMode,
1424 chnCfg->dataLineCommMode,
1425 chNum);
1426 }
1428 /* Set word length for corresponding channel */
1429 McSPIWordLengthSet(hwAttrs->baseAddr,
1430 MCSPI_WORD_LENGTH(pParams->dataSize),
1431 chNum);
1433 /* Set polarity of SPIEN to low.*/
1434 McSPICSPolarityConfig(hwAttrs->baseAddr,
1435 chnCfg->csPolarity,
1436 chNum);
1437 }
1438 }
1440 if(ret_flag == 0U)
1441 {
1442 if(SPI_MASTER == pParams->mode)
1443 {
1444 /* Configure chip-select time control */
1445 McSPICSTimeControlSet(hwAttrs->baseAddr, chnCfg->tcs, chNum);
1446 }
1448 /* increment the channel opened count */
1449 object->chOpenedCnt++;
1450 }
1451 }
1452 }
1454 return (retMcHandle);
1455 }
1457 /*
1458 * ======== MCSPI_transfer_v1 ========
1459 * @pre Function assumes that mcHandle and transaction is not NULL
1460 */
1461 static bool MCSPI_transfer_v1(MCSPI_Handle mcHandle, SPI_Transaction *transaction)
1462 {
1463 SPI_Handle handle;
1464 SPI_v1_Object *object;
1465 SPI_v1_chObject *chObj;
1466 SPI_v1_HWAttrs const *hwAttrs;
1467 uint32_t chNum, clrInt = 0U;;
1468 bool ret_val = (bool)false;
1469 SemaphoreP_Status semStatus = SemaphoreP_OK;
1471 /* Input parameter validation */
1472 if ((mcHandle != NULL) && (transaction != NULL))
1473 {
1474 /* Get the pointer to the object and hwAttrs */
1475 handle = mcHandle->handle;
1476 chNum = mcHandle->chnNum;
1477 object = (SPI_v1_Object *)handle->object;
1478 chObj = &(object->chObject[chNum]);
1479 hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
1481 /* Acquire the lock for the SPI transfer on this instance */
1482 (void)SPI_osalPendLock(object->mutex, SemaphoreP_WAIT_FOREVER);
1483 if (chObj->spiParams.transferTimeout == 0U)
1484 {
1485 /* timeout cannot be NO_WAIT, set it to default value */
1486 chObj->spiParams.transferTimeout = SPI_WAIT_FOREVER;
1487 }
1489 if ((uint32_t)transaction->count != 0U)
1490 {
1491 transaction->status = SPI_TRANSFER_STARTED;
1493 /* Check if a transfer is in progress */
1494 if (chObj->transaction != NULL)
1495 {
1496 transaction->status = SPI_TRANSFER_CANCELED;
1498 /* transfer is in progress */
1499 ret_val = (bool)false;
1500 }
1501 else
1502 {
1503 /* Save the pointer to the transaction */
1504 chObj->transaction = transaction;
1506 #ifdef SPI_DMA_ENABLE
1507 if (hwAttrs->dmaMode == (bool)true)
1508 {
1509 MCSPI_dmaTransfer(mcHandle, transaction);
1510 }
1511 else
1512 #endif
1513 {
1514 MCSPI_primeTransfer_v1(mcHandle, transaction);
1515 }
1517 if (chObj->operMode == (uint32_t)SPI_OPER_MODE_BLOCKING)
1518 {
1519 semStatus = SPI_osalPendLock(object->transferComplete, chObj->spiParams.transferTimeout);
1520 }
1521 if (semStatus == SemaphoreP_TIMEOUT)
1522 {
1523 /* clear the interrupts */
1524 clrInt = (uint32_t)((MCSPI_INT_TX_EMPTY(chNum) | MCSPI_INT_RX_FULL(chNum)
1525 | MCSPI_INT_EOWKE));
1526 if(SPI_MASTER == chObj->spiParams.mode)
1527 {
1528 McSPIIntDisable(hwAttrs->baseAddr, clrInt);
1529 }
1530 else
1531 {
1532 McSPIIntDisable(hwAttrs->baseAddr, (uint32_t)(MCSPI_INT_RX_FULL(chNum)));
1533 }
1534 McSPIIntStatusClear(hwAttrs->baseAddr, clrInt);
1535 if ((SPI_MASTER == chObj->spiParams.mode) &&
1536 (hwAttrs->chMode == MCSPI_SINGLE_CH))
1537 {
1538 McSPICSDeAssert(hwAttrs->baseAddr, chNum);
1539 }
1540 McSPIChannelDisable(hwAttrs->baseAddr, chNum);
1542 /*
1543 * Interrupt/dma (timeout) transaction
1544 * returns timeout status
1545 */
1546 transaction->status=SPI_TRANSFER_TIMEOUT;
1547 chObj->transaction = NULL;
1548 ret_val = (bool)false;
1549 }
1550 else
1551 {
1552 if (chObj->operMode == (uint32_t)SPI_OPER_MODE_POLLING)
1553 {
1554 /*
1555 * Polling transaction status is set in MCSPI_primeTransfer_v1
1556 */
1557 if (transaction->status == SPI_TRANSFER_COMPLETED)
1558 {
1559 ret_val = (bool)true;
1560 }
1561 else
1562 {
1563 ret_val = (bool)false;
1564 }
1565 }
1566 else
1567 {
1568 /*
1569 * Callback transaction or interrupt/dma (no timeout) transaction
1570 * returns completed status
1571 */
1572 transaction->status = SPI_TRANSFER_COMPLETED;
1573 ret_val = (bool)true;
1574 }
1575 }
1576 }
1577 }
1578 else
1579 {
1580 transaction->status=SPI_TRANSFER_CANCELED;
1581 }
1583 /* Release the lock for the SPI transfer on this instance */
1584 (void)SPI_osalPostLock(object->mutex);
1585 }
1587 return (ret_val);
1588 }
1590 /*
1591 * ======== MCSPI_transferCallback_v1 ========
1592 * Callback function for when the SPI is in SPI_MODE_BLOCKING
1593 *
1594 * @pre Function assumes that the handle is not NULL
1595 */
1596 void MCSPI_transferCallback_v1(MCSPI_Handle mcHandle,
1597 SPI_Transaction *transaction)
1598 {
1599 SPI_Handle handle;
1600 SPI_v1_Object *object;
1601 SPI_v1_chObject *chObj;
1602 uint32_t chNum;
1604 if (mcHandle != NULL)
1605 {
1606 /* Get the pointer to the channel object */
1607 handle = mcHandle->handle;
1608 chNum = mcHandle->chnNum;
1609 object = (SPI_v1_Object*)handle->object;
1610 chObj = &(object->chObject[chNum]);
1612 if (chObj->operMode == (uint32_t)SPI_OPER_MODE_CALLBACK)
1613 {
1614 if (object->transferCallbackFxn != NULL)
1615 {
1616 /* Single channel mode callback */
1617 object->transferCallbackFxn(handle, transaction);
1618 }
1619 else
1620 {
1621 /* multi channel mode callback */
1622 chObj->spiParams.transferCallbackFxn(mcHandle, transaction);
1623 }
1624 }
1625 else
1626 {
1627 (void)SPI_osalPostLock(object->transferComplete);
1628 }
1630 chObj->transaction = NULL;
1631 }
1632 }
1634 /*
1635 * ======== MCSPI_transferCancel_v1 ========
1636 */
1637 static void MCSPI_transferCancel_v1(MCSPI_Handle mcHandle)
1638 {
1639 SPI_Handle handle;
1640 SPI_v1_Object *object;
1641 SPI_v1_chObject *chObj;
1642 SPI_v1_HWAttrs const *hwAttrs;
1643 uint32_t chNum;
1644 uint32_t intCode;
1646 /* Get the pointer to the channel object */
1647 handle = mcHandle->handle;
1648 chNum = mcHandle->chnNum;
1649 object = (SPI_v1_Object*)handle->object;
1650 chObj = &(object->chObject[chNum]);
1651 hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
1653 if(true == hwAttrs->enableIntr)
1654 {
1655 intCode = (uint32_t)(MCSPI_INT_RX_FULL(chNum)) |
1656 (uint32_t)(MCSPI_INT_TX_EMPTY(chNum)) |
1657 MCSPI_INT_EOWKE;
1658 McSPIIntDisable(hwAttrs->baseAddr,intCode);
1659 McSPIIntStatusClear(hwAttrs->baseAddr, intCode);
1660 }
1662 if ((SPI_MASTER == chObj->spiParams.mode) &&
1663 (hwAttrs->chMode == MCSPI_SINGLE_CH))
1664 {
1665 McSPICSDeAssert(hwAttrs->baseAddr, chNum);
1666 }
1667 McSPIChannelDisable(hwAttrs->baseAddr, chNum);
1669 chObj->transaction->status = SPI_TRANSFER_CANCELED;
1670 MCSPI_transferCallback_v1(mcHandle, chObj->transaction);
1672 return;
1673 }
1675 /*
1676 * ======== MCSPI_control_v1 ========
1677 */
1678 static int32_t MCSPI_control_v1(MCSPI_Handle mcHandle, uint32_t cmd, const void *arg)
1679 {
1680 (void)mcHandle;
1681 (void)cmd;
1682 arg = arg;
1683 return SPI_STATUS_UNDEFINEDCMD;
1684 }
1686 /**
1687 * \brief function is used to clear the channel specific interrupt status
1688 */
1689 void MCSPI_clearIntStatus(MCSPI_Handle mcHandle)
1690 {
1691 SPI_Handle handle;
1692 SPI_v1_HWAttrs const *hwAttrs;
1693 uint32_t chNum;
1694 uint32_t clrIntr = (uint32_t) 0;
1696 /* Get the pointer to the hwAttrs */
1697 handle = mcHandle->handle;
1698 chNum = mcHandle->chnNum;
1699 hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
1701 switch (chNum)
1702 {
1703 case MCSPI_CHANNEL_0:
1704 /* clear all channel '0' interrupts */
1705 clrIntr = (uint32_t) 0;
1707 clrIntr = (CSL_MCSPI_IRQSTATUS_TX0_EMPTY_MASK |
1708 CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK |
1709 CSL_MCSPI_IRQSTATUS_RX0_FULL_MASK);
1711 McSPIIntStatusClear((uint32_t) hwAttrs->baseAddr, clrIntr);
1713 break;
1715 case MCSPI_CHANNEL_1:
1716 /* Enable all channel '1' interrupts */
1717 clrIntr = (uint32_t) 0;
1718 clrIntr = (CSL_MCSPI_IRQSTATUS_TX1_EMPTY_MASK |
1719 CSL_MCSPI_IRQSTATUS_TX1_UNDERFLOW_MASK |
1720 CSL_MCSPI_IRQSTATUS_RX1_FULL_MASK);
1722 McSPIIntStatusClear((uint32_t) hwAttrs->baseAddr, clrIntr);
1724 break;
1726 case MCSPI_CHANNEL_2:
1727 /* Enable all channel '2' interrupts */
1728 clrIntr = (uint32_t) 0;
1729 clrIntr = (CSL_MCSPI_IRQSTATUS_TX2_EMPTY_MASK |
1730 CSL_MCSPI_IRQSTATUS_TX2_UNDERFLOW_MASK |
1731 CSL_MCSPI_IRQSTATUS_RX2_FULL_MASK);
1733 McSPIIntStatusClear((uint32_t) hwAttrs->baseAddr, clrIntr);
1735 break;
1737 case MCSPI_CHANNEL_3:
1738 /* Enable all channel '3' interrupts */
1739 clrIntr = (uint32_t) 0;
1740 clrIntr = (CSL_MCSPI_IRQSTATUS_TX3_EMPTY_MASK |
1741 CSL_MCSPI_IRQSTATUS_TX3_UNDERFLOW_MASK |
1742 CSL_MCSPI_IRQSTATUS_RX3_FULL_MASK);
1744 McSPIIntStatusClear((uint32_t) hwAttrs->baseAddr, clrIntr);
1746 break;
1748 default:
1749 break;
1750 }
1751 }
1753 /**
1754 * \brief function is used to clear the channel specific interrupt error status
1755 */
1756 void MCSPI_clearIntErrStatus(MCSPI_Handle mcHandle, uint32_t intStatus)
1757 {
1758 SPI_Handle handle;
1759 uint32_t chNum;
1760 SPI_v1_HWAttrs const *hwAttrs;
1762 /* Get the pointer to the hwAttrs */
1763 handle = mcHandle->handle;
1764 chNum = mcHandle->chnNum;
1765 hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
1767 /* check Timeout interrupt */
1768 switch (chNum)
1769 {
1770 case MCSPI_CHANNEL_0:
1772 if ((uint32_t) CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK ==
1773 (intStatus & (uint32_t) CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK))
1774 {
1775 McSPIIntStatusClear(
1776 (uint32_t) hwAttrs->baseAddr,
1777 (uint32_t) CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK);
1778 }
1779 break;
1781 case MCSPI_CHANNEL_1:
1783 if ((uint32_t) CSL_MCSPI_IRQSTATUS_TX1_UNDERFLOW_MASK ==
1784 (intStatus & (uint32_t) CSL_MCSPI_IRQSTATUS_TX1_UNDERFLOW_MASK))
1785 {
1786 McSPIIntStatusClear(
1787 (uint32_t) hwAttrs->baseAddr,
1788 (uint32_t) CSL_MCSPI_IRQSTATUS_TX1_UNDERFLOW_MASK);
1789 }
1790 break;
1792 case MCSPI_CHANNEL_2:
1793 if ((uint32_t) CSL_MCSPI_IRQSTATUS_TX2_UNDERFLOW_MASK ==
1794 (intStatus & (uint32_t) CSL_MCSPI_IRQSTATUS_TX2_UNDERFLOW_MASK))
1795 {
1796 McSPIIntStatusClear(
1797 (uint32_t) hwAttrs->baseAddr,
1798 (uint32_t) CSL_MCSPI_IRQSTATUS_TX2_UNDERFLOW_MASK);
1799 }
1800 break;
1802 case MCSPI_CHANNEL_3:
1804 if ((uint32_t) CSL_MCSPI_IRQSTATUS_TX3_UNDERFLOW_MASK ==
1805 (intStatus & (uint32_t) CSL_MCSPI_IRQSTATUS_TX3_UNDERFLOW_MASK))
1806 {
1807 McSPIIntStatusClear(
1808 (uint32_t) hwAttrs->baseAddr,
1809 (uint32_t) CSL_MCSPI_IRQSTATUS_TX3_UNDERFLOW_MASK);
1810 }
1811 break;
1813 default:
1814 break;
1815 }
1816 }