]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/pdk.git/blob - packages/ti/drv/spi/src/v1/QSPI_v1.c
Add build support for awr294x
[processor-sdk/pdk.git] / packages / ti / drv / spi / src / v1 / QSPI_v1.c
1 /**
2  *  \file   QSPI_v1.c
3  *
4  *  \brief  QSPI IP Version 1 specific driver APIs implementation.
5  *
6  *   This file contains the driver APIs for QSPI controller.
7  */
9 /*
10  * Copyright (C) 2014-2019 Texas Instruments Incorporated - http://www.ti.com/
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  *
16  * Redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer.
18  *
19  * Redistributions in binary form must reproduce the above copyright
20  * notice, this list of conditions and the following disclaimer in the
21  * documentation and/or other materials provided with the
22  * 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
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *
40  */
42 #include <stdint.h>
43 #include <stddef.h>
44 #include <stdbool.h>
45 #include <ti/drv/spi/SPI.h>
46 #include <ti/drv/spi/soc/QSPI_v1.h>
47 #include <ti/csl/src/ip/qspi/V1/qspi.h>
48 #include <ti/csl/src/ip/qspi/V1/hw_qspi.h>
49 #include <ti/drv/spi/src/SPI_osal.h>
51 /*#define WORD_INTERRUPT*/
53 /* QSPI AM57x functions */
54 static void       QSPI_close_v1(SPI_Handle handle);
55 static void       QSPI_init_v1(SPI_Handle handle);
56 static SPI_Handle QSPI_open_v1(SPI_Handle handle, const SPI_Params *params);
57 static bool       QSPI_transfer_v1(SPI_Handle handle,
58                                       SPI_Transaction *transaction);
59 static void       QSPI_primeTransfer_v1(SPI_Handle handle,
60                                           const SPI_Transaction *transaction);
61 static void       QSPI_transferCallback_v1(SPI_Handle handle,
62                                               SPI_Transaction *msg);
63 static int32_t QSPI_control_v1(SPI_Handle handle, uint32_t cmd, const void *arg);
64 static void QSPI_transferCancel_v1(SPI_Handle handle);
65 static void QSPI_hwiFxn_v1(uintptr_t arg);
66 static void QSPI_read_v1(SPI_Handle handle, const SPI_Transaction *transaction);
67 static void QSPI_write_v1(SPI_Handle handle, const SPI_Transaction *transaction);
68 static void QSPI_mmap_mode_write_v1(SPI_Handle handle,
69                                     const SPI_Transaction *transaction);
70 static void QSPI_cmd_mode_write_v1(SPI_Handle handle,
71                                    const SPI_Transaction *transaction);
72 static void QSPI_cmd_mode_read_v1(SPI_Handle handle,
73                                   const SPI_Transaction *transaction);
74 static void QSPI_mmap_mode_read_v1(SPI_Handle handle,
75                                    const SPI_Transaction *transaction);
76 static void QSPIMmapCsEnable(uint32_t baseAddr, uint32_t chipSelect);
78 typedef enum QSPI_intrPollMode_s {
79     SPI_OPER_MODE_BLOCKING = 0U,  /*! Interrupt based blocking mode */
80     SPI_OPER_MODE_POLLING,        /*! Non interrupt based blocking mode */
81     SPI_OPER_MODE_CALLBACK        /*! Interrupt based call back mode */
82 } QSPI_intrPollMode;
86 /* SPI function table for QSPI AM57x implementation */
87 const SPI_FxnTable QSPI_FxnTable_v1 = {
88     &QSPI_close_v1,
89     &QSPI_control_v1,
90     &QSPI_init_v1,
91     &QSPI_open_v1,
92     &QSPI_transfer_v1,
93     &QSPI_transferCancel_v1,
94     NULL
95 };
97 #define   CTRL_CORE_CONTROL_IO_2       (0x4A002558U)
98 #define   QSPI_MMAP_CS_SHIFT           (0x8U)
100 /*
101  *  ======== QSPI_close_v1 ========
102  */
103 static void QSPI_close_v1(SPI_Handle handle)
105     QSPI_v1_Object      *object = NULL;
106     QSPI_HwAttrs const  *hwAttrs = NULL;
108     /* Input parameter validation */
109     if (handle != NULL)
110     {
111         /* Get the pointer to the object and hwAttrs */
112         object = (QSPI_v1_Object*)handle->object;
113         hwAttrs = (const QSPI_HwAttrs *)handle->hwAttrs;
115         /* Mask I2C interrupts */
116         QSPIintDisable(hwAttrs->baseAddr,
117             (QSPI_INTR_MASK_FRAME | QSPI_INTR_MASK_WORD));
119         /* Destruct the Hwi */
120         if ((SPI_OPER_MODE_BLOCKING == object->intrPollMode) && (true == hwAttrs->intrEnable))
121         {
122             SPI_osalHardwareIntDestruct(object->hwi, hwAttrs->eventId);
123         }
125         /* Destruct the instance lock */
126         SPI_osalDeleteBlockingLock(object->mutex);
128         /* Destruct the transfer completion lock */
129         if(SPI_OPER_MODE_BLOCKING == object->intrPollMode)
130         {
131             SPI_osalDeleteBlockingLock(object->transferComplete);
132         }
134     #ifdef SPI_DMA_ENABLE
135         if (hwAttrs->dmaEnable == true)
136         {
137             QSPI_dmaFreeChannel(handle);
138         }
139     #endif
141         /* Open flag is set false */
142         object->isOpen = (bool)false;
143     }
145     return;
148 /*
149  *  ======== QSPI_hwiFxn_v1 ========
150  *  Hwi interrupt handler to service the QSPI peripheral
151  *
152  *  The handler is a generic handler for a QSPI object.
153  */
154 static void QSPI_hwiFxn_v1(uintptr_t arg)
156     uint32_t            intrStatus;
157     QSPI_v1_Object      *object = NULL;
158     QSPI_HwAttrs const  *hwAttrs = NULL;
160     /* Get the pointer to the object and hwAttrs */
161     object = (QSPI_v1_Object*)(((SPI_Handle)arg)->object);
162     hwAttrs = (const QSPI_HwAttrs *)(((SPI_Handle)arg)->hwAttrs);
164     /* Read the interrupt status register */
165     intrStatus = QSPIintStatus(hwAttrs->baseAddr);
167     /* If word count interrupt */
168     if(intrStatus & QSPI_INTR_MASK_WORD)
169     {
170         /* Clear interrupt status */
171         QSPIintClear(hwAttrs->baseAddr, QSPI_INTR_MASK_WORD);
173         /* Call the call back function */
174         object->transaction->status = SPI_TRANSFER_COMPLETED;
175         object->qspiParams.transferCallbackFxn((SPI_Handle)arg, NULL);
176     }
178     /* If word count interrupt */
179     if(intrStatus & QSPI_INTR_MASK_FRAME)
180     {
181         /* Clear interrupt status */
182         QSPIintClear(hwAttrs->baseAddr, QSPI_INTR_MASK_FRAME);
184         /* Call the call back function */
185         object->transaction->status = SPI_TRANSFER_COMPLETED;
186         object->qspiParams.transferCallbackFxn((SPI_Handle)arg, NULL);
187     }
189     return;
192 /*
193  *  ======== QSPI_init_v1 ========
194  */
195 static void QSPI_init_v1(SPI_Handle handle)
197     /* Input parameter validation */
198     if (handle != NULL)
199     {
200         /* Mark the object as available */
201         ((QSPI_v1_Object *)(handle->object))->isOpen = (bool)false;
202     }
206 /*
207  *  ======== QSPI_open_v1 ========
208  */
209 static SPI_Handle QSPI_open_v1(SPI_Handle handle, const SPI_Params *params)
211     SemaphoreP_Params     semParams;
212     uint32_t       key;
213     QSPI_v1_Object   *object = NULL;
214     QSPI_HwAttrs const  *hwAttrs = NULL;
215     OsalRegisterIntrParams_t interruptRegParams;
216     uint8_t ret_flag = 0u;
217     uint32_t clkDiv;
219     /* Input parameter validation */
220     if (handle != NULL)
221     {
222     /* Get the pointer to the object and hwAttrs */
223     object = (QSPI_v1_Object*)handle->object;
224     hwAttrs = (const QSPI_HwAttrs *)handle->hwAttrs;
226     /* Determine if the device index was already opened */
227     key = SPI_osalHardwareIntDisable();
228     if(object->isOpen == (bool)true) {
229         SPI_osalHardwareIntRestore(key);
230         handle = NULL;
231     }
232     else
233     {
234       /* Mark the handle as being used */
235       object->isOpen = (bool)true;
236       SPI_osalHardwareIntRestore(key);
238       /* Store the I2C parameters */
239       if (params == NULL) {
240         /* No params passed in, so use the defaults */
241         SPI_Params_init(&(object->qspiParams));
242       }
243       else {
244         /* Copy the params contents */
245         object->qspiParams = *params;
246       }
248       /* Copy the controller mode from hardware attributes to object */
249       object->qspiMode = hwAttrs->operMode;
250       object->rxLines  = hwAttrs->rxLines;
252       /* Extract QSPI operating mode based on hwAttrs and input parameters */
253       if(SPI_MODE_BLOCKING == object->qspiParams.transferMode)
254       {
255           if(true == hwAttrs->intrEnable)
256           {
257               object->intrPollMode = SPI_OPER_MODE_BLOCKING;
258           }
259 #ifdef SPI_DMA_ENABLE
260           else if (true == hwAttrs->dmaEnable)
261           {
262               object->intrPollMode = SPI_OPER_MODE_BLOCKING;
263           }
264 #endif
265           else
266           {
267               object->intrPollMode = SPI_OPER_MODE_POLLING;
268           }
269       }
270       else
271       {
272         object->intrPollMode = SPI_OPER_MODE_CALLBACK;
273       }
276       /* Extract the polling mode from hardware attributes. */
277       if ((SPI_OPER_MODE_BLOCKING == object->intrPollMode) && (true == hwAttrs->intrEnable))
278       {
279                 /* register interrrupt when the 1st channel of the instance is opened */
280         Osal_RegisterInterrupt_initParams(&interruptRegParams);             
282         interruptRegParams.corepacConfig.name=NULL;
283         interruptRegParams.corepacConfig.priority = 0x20;
284         interruptRegParams.corepacConfig.corepacEventNum = hwAttrs->eventId;
285         interruptRegParams.corepacConfig.intVecNum=hwAttrs->intrNum; /* Host Interrupt vector */
286         interruptRegParams.corepacConfig.isrRoutine  = (void (*)(uintptr_t))(&QSPI_hwiFxn_v1);
287 #if defined(SOC_TPR12) || defined (SOC_AWR294X) /* All TPR12 interrupts are pulse and not level */
288         interruptRegParams.corepacConfig.triggerSensitivity = OSAL_ARM_GIC_TRIG_TYPE_EDGE;
289 #endif
290         interruptRegParams.corepacConfig.arg         = (uintptr_t)handle;
292         SPI_osalRegisterInterrupt(&interruptRegParams,&(object->hwi));
294         if(object->hwi == NULL) {
295             QSPI_close_v1(handle);
296             ret_flag = 1u;
297             handle = NULL;
298         }
299       }
301       if(ret_flag == 0u)
302       {
303         /*
304          * Construct thread safe handles for this QSPI peripheral
305          * Semaphore to provide exclusive access to the QSPI peripheral
306          */
307         SPI_osalSemParamsInit(&semParams);
308         semParams.mode = SemaphoreP_Mode_BINARY;
309         object->mutex = SPI_osalCreateBlockingLock(1U, &semParams);
311         /*
312          * Store a callback function that posts the transfer complete
313          * semaphore for synchronous mode
314          */
315         if (object->intrPollMode == SPI_OPER_MODE_BLOCKING) {
316           /*
317            * Semaphore to cause the waiting task to block for the QSPI
318            * to finish
319            */
320           object->transferComplete = SPI_osalCreateBlockingLock(0, &semParams);
322           /* Store internal callback function */
323           object->qspiParams.transferCallbackFxn = &QSPI_transferCallback_v1;
324         }
325         if(object->intrPollMode == SPI_OPER_MODE_CALLBACK){
326           /* Check to see if a callback function was defined for async mode */
327           OSAL_Assert(object->qspiParams.transferCallbackFxn == NULL);
328         }
330 #ifdef SPI_DMA_ENABLE
331         if (hwAttrs->dmaEnable == true)
332         {
333             /* DMA Configuration */
334             QSPI_dmaConfig(handle);
335         }
336 #endif
337         /* Setting IDLE mode for QSPI controller */
338         QSPIconfigIdleMode(hwAttrs->baseAddr, QSPI_SYSCONFIG_IDLE_MODE_NO_IDLE);
340         /* Set clock mode in mode 3 */
341         QSPISetClkMode(hwAttrs->baseAddr, hwAttrs->chipSelect, hwAttrs->frmFmt);
342         QSPISetCsPol(hwAttrs->baseAddr, hwAttrs->chipSelect, hwAttrs->csPol);
343         QSPISetDataDelay(hwAttrs->baseAddr, hwAttrs->chipSelect,
344                           hwAttrs->dataDelay);
346         /* Enable clock and set divider value */
347         if (hwAttrs->clkDiv > 0U)
348         {
349             /* use SoC specific clock divider if configured */
350             clkDiv = hwAttrs->clkDiv;
351         }
352         else
353         {
354             /*
355              * if SoC specific clock divider not configured
356              * calculate the clock divider using QSPI clock and baud rate
357              */
358             clkDiv = hwAttrs->funcClk / object->qspiParams.bitRate;
359         }
361         if (clkDiv > 0U)
362         {
363             clkDiv--;
364         }
365         QSPISetPreScaler(hwAttrs->baseAddr, clkDiv);
367         /* Clear the interrupts and interrupt status */
368         QSPIintDisable(hwAttrs->baseAddr,
369             (QSPI_INTR_MASK_FRAME | QSPI_INTR_MASK_WORD)) ;
370         QSPIintClear(hwAttrs->baseAddr,
371             (QSPI_INTR_MASK_FRAME | QSPI_INTR_MASK_WORD));
373         QSPISetMemMapNumAddrBytes(hwAttrs->baseAddr,
374                       hwAttrs->chipSelect,
375                       QSPI_MEM_MAP_NUM_ADDR_BYTES_THREE);
377         /* Enable memory mapped port by default */
378         QSPISetMemAddrSpace(hwAttrs->baseAddr,
379                 hwAttrs->chipSelect,
380                 QSPI_MEM_MAP_PORT_SEL_MEM_MAP_PORT);
383         QSPIMmapCsEnable(hwAttrs->baseAddr, hwAttrs->chipSelect);
385         /* Return the address of the spiObjectArray[i] configuration structure */
386       }
387     }
388     }
389     return(handle);
392 static void QSPIMmapCsEnable(uint32_t baseAddr, uint32_t chipSelect)
394 #if !(defined(SOC_AM437x) || defined(SOC_TPR12) || defined (SOC_AWR294X))
395     uint32_t regVal;
397     regVal = HW_RD_REG32(CTRL_CORE_CONTROL_IO_2);
398     regVal |= ((chipSelect + 1U) << QSPI_MMAP_CS_SHIFT);
399     HW_WR_REG32(CTRL_CORE_CONTROL_IO_2, regVal);
400 #endif
403 /*
404  *  ======== QSPI_primeTransfer_v1 =======
405  */
406 static void QSPI_primeTransfer_v1(SPI_Handle handle,
407                                   const SPI_Transaction *transaction)
409     QSPI_v1_Object  *object = NULL;
410     QSPI_HwAttrs const  *hwAttrs = NULL;
412     /* Get the pointer to the object and hwAttrs */
413     object = (QSPI_v1_Object*)handle->object;
414     hwAttrs = (const QSPI_HwAttrs *)handle->hwAttrs;
416     /* Store the new internal counters and pointers */
417     object->writeBufIdx = (uint8_t*)transaction->txBuf;
418     object->writeCountIdx = transaction->count;
420     object->readBufIdx = (uint8_t*)transaction->rxBuf;
421     object->readCountIdx = transaction->count;
424     /* Interrupt mode */
425     if ((SPI_OPER_MODE_BLOCKING == object->intrPollMode) && (true == hwAttrs->intrEnable))
426     {
427 #ifdef WORD_INTERRUPT
428         /* Enable the word count interrupt */
429         QSPIintEnable(hwAttrs->baseAddr, QSPI_INTR_MASK_WORD);
430 #else
431         /* Enable the frame count interrupt */
432         QSPIintEnable(hwAttrs->baseAddr, QSPI_INTR_MASK_FRAME);
433 #endif
434     }
436     /* Identify the direction of transfer (whether read/write) */
437     if(SPI_TRANSACTION_TYPE_READ == object->transactionType)
438     {
439         QSPI_read_v1(handle, transaction);
440     }
442     if(SPI_TRANSACTION_TYPE_WRITE == object->transactionType)
443     {
444         QSPI_write_v1(handle, transaction);
445     }
449 static void QSPI_mmap_mode_read_v1(SPI_Handle handle,
450                                    const SPI_Transaction *transaction)
452     QSPI_HwAttrs const  *hwAttrs = NULL;
453     uint8_t *pDst = NULL;
454     uint8_t *pSrc = NULL;
455     uint32_t count;
456     uint32_t mmapReadCmd = 0U;
457     QSPI_v1_Object  *object;
458     uintptr_t offset;
460     /* Get the pointer to the object and hwAttrs */
461     hwAttrs = (const QSPI_HwAttrs *)handle->hwAttrs;
462     object = (QSPI_v1_Object*)handle->object;
464     /* get flash offset */
465     offset = (uintptr_t)transaction->txBuf;
467     /* Extract memory map mode read command */
468     mmapReadCmd = (uint32_t)object->transferCmd;
470     /* Set the number of address bytes to three */
471     QSPISetMemMapNumAddrBytes(hwAttrs->baseAddr, hwAttrs->chipSelect,
472         QSPI_MEM_MAP_NUM_ADDR_BYTES_THREE);
474     /* 4 byte addressing mode */
475     if(offset > (uintptr_t)0xFFFFFF)
476     {
477         /* Enable 4 byte addressing mode */
478         QSPISetMemMapNumAddrBytes(hwAttrs->baseAddr, hwAttrs->chipSelect,
479             QSPI_MEM_MAP_NUM_ADDR_BYTES_FOUR);
480     }
482     switch(object->rxLines)
483     {
484         case QSPI_RX_LINES_SINGLE:
485         {
486             QSPISetMemMapReadCmd(hwAttrs->baseAddr, hwAttrs->chipSelect,
487                 mmapReadCmd);
488             QSPISetMemMapReadType(hwAttrs->baseAddr, hwAttrs->chipSelect,
489                 QSPI_MEM_MAP_READ_TYPE_NORMAL);
490             QSPISetMemMapNumDummyBits(hwAttrs->baseAddr, hwAttrs->chipSelect,
491                 0x0U);
492             break;
493         }
495         case QSPI_RX_LINES_DUAL:
496         {
497             QSPISetMemMapReadCmd(hwAttrs->baseAddr, hwAttrs->chipSelect,
498                 mmapReadCmd);
499             QSPISetMemMapReadType(hwAttrs->baseAddr, hwAttrs->chipSelect,
500                 QSPI_MEM_MAP_READ_TYPE_DUAL);
501             QSPISetMemMapNumDummyBits(hwAttrs->baseAddr, hwAttrs->chipSelect,
502                 0x8U);
503             break;
504         }
506         case QSPI_RX_LINES_QUAD:
507         {
508             QSPISetMemMapReadCmd(hwAttrs->baseAddr, hwAttrs->chipSelect,
509                 mmapReadCmd);
510             QSPISetMemMapReadType(hwAttrs->baseAddr, hwAttrs->chipSelect,
511                 QSPI_MEM_MAP_READ_TYPE_QUAD);
512             QSPISetMemMapNumDummyBits(hwAttrs->baseAddr, hwAttrs->chipSelect,
513                 0x8U);
514             break;
515         }
517         default:
518         break;
519     }
521 #ifdef SPI_DMA_ENABLE
522     if (hwAttrs->dmaEnable == true)
523     {
524         QSPI_dmaTransfer(handle, (SPI_Transaction *)transaction);
525     }
526     else
527 #endif
528     {
529         uintptr_t temp_addr = ((uintptr_t)hwAttrs->memMappedBaseAddr + (uintptr_t)transaction->txBuf);
530         pSrc = ((uint8_t *)(temp_addr));
531         pDst = (uint8_t *)transaction->rxBuf;
532         count = transaction->count;
534         while(count)
535         {
536             /* Do the normal memory to memory transfer. Copy will be in bytes */
537             *pDst = *pSrc;
538             pDst++;
539             pSrc++;
540             count--;
541         }
542     }
544     /* 4 byte addressing mode */
545     if(offset > (uint32_t)0xFFFFFF)
546     {
547         /*
548          * After the transfer switch back to 3 byte addressing mode.
549          * This is the default mode.
550          */
551         QSPISetMemMapNumAddrBytes(hwAttrs->baseAddr, hwAttrs->chipSelect,
552             QSPI_MEM_MAP_NUM_ADDR_BYTES_THREE);
553     }
557 static void QSPI_cmd_mode_read_v1(SPI_Handle handle,
558                                   const SPI_Transaction *transaction)
560     QSPI_v1_Object  *object;         /* QSPI object */
561     QSPI_HwAttrs const  *hwAttrs;    /* QSPI hardware attributes */
562     uint32_t count = 0U;         /* transfer length in bytes */
563     uint32_t wordLenBytes = 0U;  /* Word length in number of bytes */
564     uint32_t cmd = 0;           /* transmit command */
565     uint32_t dataVal[4] = {0U, 0U, 0U, 0U};  /* data to be written */
566     uint32_t idx, idx1, idx2, idx3;  /* indexes */
567     uint32_t numWords = 0U;          /* number of words */
568     uint8_t *dstAddr;              /* destination address */
570     /* Get the pointer to the object and hwAttrs */
571     object = (QSPI_v1_Object*)handle->object;
572     hwAttrs = (const QSPI_HwAttrs *)handle->hwAttrs;
574     dstAddr = object->readBufIdx;
576     /*formulate the command */
577     HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_FLEN, (object->frmLength - 1));
578     HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_WLEN, (object->qspiParams.dataSize - 1));
579     HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_CSNUM, hwAttrs->chipSelect);
581     switch(object->rxLines)
582     {
583         case QSPI_RX_LINES_SINGLE:
584         {
585             HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_CMD,
586                 QSPI_SPI_CMD_REG_CMD_FOUR_PIN_READ_SINGLE);
587             break;
588         }
589         case QSPI_RX_LINES_DUAL:
590         {
591             HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_CMD,
592                 QSPI_SPI_CMD_REG_CMD_FOUR_PIN_READ_DUAL);
593             break;
594         }
595         case QSPI_RX_LINES_QUAD:
596         {
597             HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_CMD,
598                 QSPI_SPI_CMD_REG_CMD_SIX_PIN_READ_QUAD);
599             break;
600         }
602         default:
603         break;
604     }
606     /* Enable interrupts in the polling mode */
607     if ((SPI_OPER_MODE_BLOCKING == object->intrPollMode) && (true == hwAttrs->intrEnable))
608     {
609 #ifdef WORD_INTERRUPT
610         /* Enable word count interrupt */
611         HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_WIRQ, true);
612 #else
613         /* Enable frame count interrupt */
614         HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_FIRQ, true);
615 #endif
617     }
618     else
619     {
620         /* Disable word count interrupt */
621         HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_WIRQ, false);
622         HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_FIRQ, false);
623     }
625     /* Extract frame length in bytes */
626     count = transaction->count;
628     /* Extract word length in number of bytes */
629     wordLenBytes = (object->qspiParams.dataSize >> 3U);
631     /* Write the data into shift registers */
632     while(count)
633     {
634         /* Write tx command to command register */
635         QSPIsetCommandReg(hwAttrs->baseAddr, cmd);
637 #ifdef WORD_INTERRUPT
638         /* interrupt mode */
639         if ((SPI_OPER_MODE_BLOCKING == object->intrPollMode) && (true == hwAttrs->intrEnable))
640         {
641             /* wait for the lock posted form the word completion interrupt */
642             SPI_osalPendLock(object->transferComplete, SemaphoreP_WAIT_FOREVER);
643         }
645         if(SPI_OPER_MODE_POLLING == object->intrPollMode)
646         {
647             /* Wait for the QSPI busy status */
648             QSPIWaitIdle(hwAttrs->baseAddr);
649         }
650 #else
652             /* Wait for the QSPI busy status */
653             QSPIWaitIdle(hwAttrs->baseAddr);
654 #endif
657         if(wordLenBytes <= 4U)
658         {
659             numWords = 1U;
661             /* Read data from the data registers */
662             QSPIreadData(hwAttrs->baseAddr, &dataVal[0], (int32_t)numWords);
664             /* Write the extracted data into receive buffer */
665             for(idx = 0U; idx < wordLenBytes; idx++)
666             {
667                 *dstAddr = (uint8_t)((dataVal[0] >> (8U - (8U * (idx + 1U)))) &
668                     (0x000000FFU));
669                 dstAddr++;
670             }
671         }
672         else if((wordLenBytes > 4U) && (wordLenBytes <= 8U))
673         {
674             numWords = 2U;
676             /* Read data from the data registers */
677             QSPIreadData(hwAttrs->baseAddr, &dataVal[0], (int32_t)numWords);
679             /* Formulate the 32 bit word to write to data register */
680             for(idx = 0U; idx < 4U; idx++)
681             {
682                 *dstAddr = (uint8_t)((dataVal[0] >> (8U - (8U * (idx + 1U)))) &
683                     (0x000000FFU));
684                 dstAddr++;
685             }
687             for(idx1 = 4U; idx1 < wordLenBytes; idx1++)
688             {
689                 *dstAddr = (uint8_t)((dataVal[1] >> (8U - (8U * (idx1 + 1U)))) &
690                     (0x000000FFU));
691                 dstAddr++;
692             }
693         }
694         else if((wordLenBytes > 8U) && (wordLenBytes <= 12U))
695         {
696             numWords = 3U;
698             /* Read data from the data registers */
699             QSPIreadData(hwAttrs->baseAddr, &dataVal[0], (int32_t)numWords);
701             /* Formulate the 32 bit word to write to data register */
702             for(idx = 0U; idx < 4U; idx++)
703             {
704                 *dstAddr = (uint8_t)((dataVal[0] >> (8U - (8U * (idx + 1U)))) &
705                     (0x000000FFU));
706                 dstAddr++;
707             }
709             for(idx1 = 4U; idx1 < 8U; idx1++)
710             {
711                 *dstAddr = (uint8_t)((dataVal[1] >> (8U - (8U * (idx1 + 1U)))) &
712                     (0x000000FFU));
713                 dstAddr++;
714             }
716             for(idx2 = 8U; idx2 < 12U; idx2++)
717             {
718                 *dstAddr = (uint8_t)((dataVal[2] >> (8U - (8U * (idx2 + 1U)))) &
719                     (0x000000FFU));
720                 dstAddr++;
721             }
722         }
723         else if((wordLenBytes > 12U) && (wordLenBytes <= 16U))
724         {
725             numWords = 4U;
727             /* Read data from the data registers */
728             QSPIreadData(hwAttrs->baseAddr, &dataVal[0], (int32_t)numWords);
730             /* Formulate the 32 bit word to write to data register */
731             for(idx = 0U; idx < 4U; idx++)
732             {
733                 *dstAddr = (uint8_t)((dataVal[0] >> (8U - (8U * (idx + 1U)))) &
734                     (0x000000FFU));
735                 dstAddr++;
736             }
738             for(idx1 = 4U; idx1 < 8U; idx1++)
739             {
740                 *dstAddr = (uint8_t)((dataVal[1] >> (8U - (8U * (idx1 + 1U)))) &
741                     (0x000000FFU));
742                 dstAddr++;
743             }
745             for(idx2 = 8U; idx2 < 12U; idx2++)
746             {
747                 *dstAddr = (uint8_t)((dataVal[2] >> (8U - (8U * (idx2 + 1U)))) &
748                     (0x000000FFU));
749                 dstAddr++;
750             }
752             for(idx3 = 12U; idx3 < 16U; idx3++)
753             {
754                 *dstAddr = (uint8_t)((dataVal[3] >> (8U - (8U * (idx3 + 1U)))) &
755                     (0x000000FFU));
756                 dstAddr++;
757             }
758         }
759         else
760         {
761             /* Not supported */
762         }
764         /* Update the number of bytes to be transmitted */
765         count -= wordLenBytes;
766     }
768     /* Update read buffer index in the object */
769     object->readBufIdx = dstAddr;
773 static void QSPI_read_v1(SPI_Handle handle, const SPI_Transaction *transaction)
775     QSPI_v1_Object  *object = NULL;
777     object = (QSPI_v1_Object*)handle->object;
779     if(QSPI_OPER_MODE_MMAP == object->qspiMode)
780     {
781         QSPI_mmap_mode_read_v1(handle, transaction);
782     }
784     if(QSPI_OPER_MODE_CFG == object->qspiMode)
785     {
786         QSPI_cmd_mode_read_v1(handle, transaction);
787     }
792 static void QSPI_mmap_mode_write_v1(SPI_Handle handle,
793                                     const SPI_Transaction *transaction)
795     QSPI_HwAttrs const  *hwAttrs;          /* QSPI hardware attributes */
796     uint32_t mmapWriteCmd = 0U;        /* Mmap command */
797     uint32_t count = 0U;               /* transaction length */
798     uint8_t *pSrc;                   /* Source address */
799     uint8_t *pDst;                   /* Destination address */
800     QSPI_v1_Object  *object;               /* QSPI object */
801     uintptr_t offset;
803     /* Get the pointer to the object and hwAttrs */
804     hwAttrs = (const QSPI_HwAttrs *)handle->hwAttrs;
805     object = (QSPI_v1_Object*)handle->object;
807     offset = (uintptr_t)transaction->txBuf;
809     /* Extract memory map mode command */
810     mmapWriteCmd = (uint32_t)object->transferCmd;
812     QSPISetMemMapWriteCmd(hwAttrs->baseAddr, hwAttrs->chipSelect, mmapWriteCmd);
813     QSPISetMemMapNumAddrBytes(hwAttrs->baseAddr, hwAttrs->chipSelect,
814         QSPI_MEM_MAP_NUM_ADDR_BYTES_THREE);
815     QSPISetMemAddrSpace(hwAttrs->baseAddr, hwAttrs->chipSelect,
816         QSPI_MEM_MAP_PORT_SEL_MEM_MAP_PORT);
818     QSPIMmapCsEnable(hwAttrs->baseAddr, hwAttrs->chipSelect);
820     /* 4 byte addressing mode. */
821     if(offset > (uint32_t)0xFFFFFF)
822     {
823         /* Switch to four byte addressing mode */
824         QSPISetMemMapNumAddrBytes(hwAttrs->baseAddr, hwAttrs->chipSelect,
825             QSPI_MEM_MAP_NUM_ADDR_BYTES_FOUR);
826     }
828 #ifdef SPI_DMA_ENABLE
829     if (hwAttrs->dmaEnable == true)
830     {
831         QSPI_dmaTransfer(handle, transaction);
832     }
833     else
834 #endif
835     {
836         pSrc = (uint8_t*)transaction->rxBuf;
837         /* Compute the flash destination address */
838         uintptr_t temp_addr = ((uintptr_t)hwAttrs->memMappedBaseAddr + (uintptr_t)transaction->txBuf);
839         pDst = ((uint8_t *)(temp_addr));
840         count = transaction->count;
842         while(count)
843         {
844             *pDst = *pSrc;
845             pDst++;
846             pSrc++;
847             count--;
848         }
849     }
851     /* 4 byte addressing mode. */
852     if(offset > (uintptr_t)0xFFFFFF)
853     {
854         /* Switch back to three byte addressing mode. */
855         QSPISetMemMapNumAddrBytes(hwAttrs->baseAddr, hwAttrs->chipSelect,
856             QSPI_MEM_MAP_NUM_ADDR_BYTES_FOUR);
857     }
861 static void QSPI_cmd_mode_write_v1(SPI_Handle handle,
862                                    const SPI_Transaction *transaction)
864     QSPI_v1_Object  *object;         /* QSPI object */
865     QSPI_HwAttrs const  *hwAttrs;    /* QSPI hardware attributes */
866     uint32_t count = 0U;         /* transfer length in bytes */
867     uint32_t wordLenBytes = 0U;  /* Word length in number of bytes */
868     uint32_t cmd = 0;           /* transmit command */
869     uint32_t dataVal[4] = {0U, 0U, 0U, 0U};  /* data to be written */
870     uint32_t idx, idx1, idx2, idx3;          /* indexes */
871     uint32_t numWords = 0U;                  /* number of words */
872     uint8_t *srcAddr;                      /* Source address */
874     /* Get the pointer to the object and hwAttrs */
875     object = (QSPI_v1_Object*)handle->object;
876     hwAttrs = (const QSPI_HwAttrs *)handle->hwAttrs;
878     srcAddr = object->writeBufIdx;
880     /* formulate the command */
881     HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_FLEN, (object->frmLength - 1));
882     HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_WLEN, (object->qspiParams.dataSize - 1));
883     HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_CSNUM, hwAttrs->chipSelect);
884     HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_CMD,
885         QSPI_SPI_CMD_REG_CMD_FOUR_PIN_WRITE_SINGLE);
888     /* Enable interrupts in the polling mode */
889     if ((SPI_OPER_MODE_BLOCKING == object->intrPollMode) && (true == hwAttrs->intrEnable))
890     {
891 #ifdef WORD_INTERRUPT
892         /* Enable word count interrupt */
893         HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_WIRQ, true);
894 #else
895         /* Enable frame count interrupt */
896         HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_FIRQ, true);
897 #endif
899     }
900     else
901     {
902         /* Disable word count interrupt */
903         HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_WIRQ, false);
904         HW_SET_FIELD32(cmd, QSPI_SPI_CMD_REG_FIRQ, false);
905     }
908     /* Extract frame length in bytes */
909     count = transaction->count;
911     /* Extract word length in number of bytes */
912     wordLenBytes = (object->qspiParams.dataSize >> 3U);
914     /* Write the data into shift registers */
915     while(count)
916     {
917         dataVal[0] = 0;
918         dataVal[1] = 0;
919         dataVal[2] = 0;
920         dataVal[3] = 0;
922         if(wordLenBytes <= 4U)
923         {
924             /* Formulate the 32 bit word to write to data register */
925             for(idx = 0U; idx < wordLenBytes; idx++)
926             {
927                 dataVal[0] |= (((uint32_t)(*srcAddr) << (8u - (8u * (idx + 1u)))));
928                 srcAddr++;
929             }
931             numWords = 1U;
932         }
933         else if((wordLenBytes > 4U) && (wordLenBytes <= 8U))
934         {
935             /* Formulate the 32 bit word to write to data register */
936             for(idx = 0U; idx < 4U; idx++)
937             {
938                 dataVal[0] |= (((uint32_t)(*srcAddr) << (8u - (8u * (idx + 1u)))));
939                 srcAddr++;
940             }
942             for(idx1 = 4U; idx1 < wordLenBytes; idx1++)
943             {
944                 dataVal[1] |= (((uint32_t)(*srcAddr) << (8u - (8u * (idx + 1u)))));
945                 srcAddr++;
946             }
948             numWords = 2U;
949         }
950         else if((wordLenBytes > 8U) && (wordLenBytes <= 12U))
951         {
952             /* Formulate the 32 bit word to write to data register */
953             for(idx = 0U; idx < 4U; idx++)
954             {
955                 dataVal[0] |= (((uint32_t)(*srcAddr) << (8u - (8u * (idx + 1u)))));
956                 srcAddr++;
957             }
959             for(idx1 = 4U; idx1 < 8U; idx1++)
960             {
961                 dataVal[1] |= (((uint32_t)(*srcAddr) << (8u - (8u * (idx + 1u)))));
962                 srcAddr++;
963             }
965             for(idx2 = 8U; idx2 < 12U; idx2++)
966             {
967                 dataVal[2] |= (((uint32_t)(*srcAddr) << (8u - (8u * (idx + 1u)))));
968                 srcAddr++;
969             }
971             numWords = 3U;
972         }
973         else if((wordLenBytes > 12U) && (wordLenBytes <= 16U))
974         {
975             /* Formulate the 32 bit word to write to data register */
976             for(idx = 0U; idx < 4U; idx++)
977             {
978                 dataVal[0] |= (((uint32_t)(*srcAddr) << (8u - (8u * (idx + 1u)))));
979                 srcAddr++;
980             }
982             for(idx1 = 4U; idx1 < 8U; idx1++)
983             {
984                 dataVal[1] |= (((uint32_t)(*srcAddr) << (8u - (8u * (idx + 1u)))));
985                 srcAddr++;
986             }
988             for(idx2 = 8U; idx2 < 12U; idx2++)
989             {
990                 dataVal[2] |= (((uint32_t)(*srcAddr) << (8u - (8u * (idx + 1u)))));
991                 srcAddr++;
992             }
994             for(idx3 = 12U; idx3 < 16U; idx3++)
995             {
996                 dataVal[3] |= (((uint32_t)(*srcAddr) << (8u - (8u * (idx + 1u)))));
997                 srcAddr++;
998             }
1000             numWords = 4U;
1001         }
1002         else
1003         {
1004             /* Not supported */
1005         }
1007         /* Write data to data registers */
1008         QSPIwriteData(hwAttrs->baseAddr, &dataVal[0], (int32_t)numWords);
1010         /* Write tx command to command register */
1011         QSPIsetCommandReg(hwAttrs->baseAddr, cmd);
1013 #ifdef WORD_INTERRUPT
1014         /* interrupt mode */
1015         if ((SPI_OPER_MODE_BLOCKING == object->intrPollMode) && (true == hwAttrs->intrEnable))
1016         {
1017             /* wait for the lock posted form the word completion interrupt */
1018             SPI_osalPendLock(object->transferComplete, SemaphoreP_WAIT_FOREVER);
1019         }
1021         if(SPI_OPER_MODE_POLLING == object->intrPollMode)
1022         {
1023             /* Wait for the QSPI busy status */
1024             QSPIWaitIdle(hwAttrs->baseAddr);
1025         }
1026 #else
1028         /* Wait for the QSPI busy status */
1029         QSPIWaitIdle(hwAttrs->baseAddr);
1030 #endif
1033         /* Update the number of bytes to be transmitted */
1034         count -= wordLenBytes;
1035     }
1037     /* Update write buffer index in the object */
1038     object->writeBufIdx = srcAddr;
1042 static void QSPI_write_v1(SPI_Handle handle, const SPI_Transaction *transaction)
1044     QSPI_v1_Object  *object = NULL;         /* QSPI object */
1046     /* Get the pointer to the object and hwAttrs */
1047     object = (QSPI_v1_Object*)handle->object;
1049     if(QSPI_OPER_MODE_MMAP == object->qspiMode)
1050     {
1051         QSPI_mmap_mode_write_v1(handle, transaction);
1052     }
1054     if(QSPI_OPER_MODE_CFG == object->qspiMode)
1055     {
1056         QSPI_cmd_mode_write_v1(handle, transaction);
1057     }
1061 /*
1062  *  ======== i2c_am57x_transfer ========
1063  */
1064 static bool QSPI_transfer_v1(SPI_Handle handle, SPI_Transaction *transaction)
1066     bool  ret = false;                /* return value */
1067     QSPI_v1_Object   *object;         /* QSPI object */
1068     QSPI_HwAttrs const  *hwAttrs;     /* QSPI hardware attributes */
1070     /* Input parameter validation */
1071     if ((handle != NULL) && (transaction != NULL))
1072     {
1073     /* Get the pointer to the object and hwAttrs */
1074     object = (QSPI_v1_Object*)handle->object;
1075     hwAttrs = (const QSPI_HwAttrs *)handle->hwAttrs;
1077     /* Check if anything needs to be written or read */
1078     if (0 != transaction->count)
1079     {
1080         transaction->status=SPI_TRANSFER_STARTED;
1081                 /* Acquire the lock for this particular I2C handle */
1082         SPI_osalPendLock(object->mutex, SemaphoreP_WAIT_FOREVER);
1084         /* Book keeping of transmit and receive buffers. */
1085         object->writeBufIdx = (uint8_t *)transaction->txBuf;
1086         object->writeCountIdx = transaction->count;
1087         object->readBufIdx =  (uint8_t *)transaction->rxBuf;
1088         object->readCountIdx = transaction->count;
1089         object->transaction = transaction;
1091          /*
1092          * QSPI_primeTransfer_v1 is a longer process and
1093          * protection is needed from the QSPI interrupt
1094          */
1095         if ((SPI_OPER_MODE_BLOCKING == object->intrPollMode) && (true == hwAttrs->intrEnable))
1096         {
1097             SPI_osalHardwareIntrEnable(hwAttrs->eventId,hwAttrs->intrNum);
1098         }
1100         QSPI_primeTransfer_v1(handle, transaction);
1102         if (object->intrPollMode == SPI_OPER_MODE_BLOCKING) {
1103 #ifdef SPI_DMA_ENABLE
1104             if ((hwAttrs->dmaEnable == true) && (QSPI_OPER_MODE_MMAP == object->qspiMode))
1105             {
1106                 SPI_osalPendLock(object->transferComplete, SemaphoreP_WAIT_FOREVER);
1107             }
1108 #endif
1109             /* transfer is completed and semaphore is posted. */
1110             ret = (bool)true;
1111         }
1112         else {
1113             /* Always return true if in Asynchronous mode */
1114             ret = (bool)true;
1115         }
1117         /* Release the lock for this particular I2C handle */
1118         SPI_osalPostLock(object->mutex);
1119     } else {
1120            transaction->status=SPI_TRANSFER_CANCELED;
1121         }
1122     }
1124     /* Return the number of bytes transferred by the I2C */
1125     return (ret);
1128 /*
1129  *  ======== QSPI_transferCallback_v1 ========
1130  */
1131 static void QSPI_transferCallback_v1(SPI_Handle handle, SPI_Transaction *msg)
1133     QSPI_v1_Object   *object;            /* QSPI object */
1135     /* Get the pointer to the object */
1136     object = (QSPI_v1_Object*)handle->object;
1138         /* Indicate transfer complete */
1139     SPI_osalPostLock(object->transferComplete);
1142 /*
1143  *  ======== QSPI_control_v1 ========
1144  */
1145 static int32_t QSPI_control_v1(SPI_Handle handle, uint32_t cmd, const void *arg)
1147     QSPI_v1_Object   *object;            /* QSPI object */
1148     int32_t retVal = SPI_STATUS_ERROR;
1150     /* Input parameter validation */
1151     if (handle != NULL)
1152     {
1153     /* Get the pointer to the object */
1154     object = (QSPI_v1_Object*)handle->object;
1156     switch (cmd)
1157     {
1158         case SPI_V1_CMD_SETFRAMELENGTH:
1159         {
1160             object->frmLength = *(uint32_t *)arg;
1161             retVal = SPI_STATUS_SUCCESS;
1162             break;
1163         }
1165         case SPI_V1_CMD_MMAP_TRANSFER_CMD:
1166         {
1167             object->transferCmd = *(uint8_t *)arg;
1168             retVal = SPI_STATUS_SUCCESS;
1169             break;
1170         }
1172         case SPI_V1_CMD_TRANSFERMODE_RW:
1173         {
1174             object->transactionType = *(uint32_t *)arg;
1175             retVal = SPI_STATUS_SUCCESS;
1176             break;
1177         }
1179         case SPI_V1_CMD_SETCONFIGMODE:
1180         {
1181             object->qspiMode = QSPI_OPER_MODE_CFG;
1182             retVal = SPI_STATUS_SUCCESS;
1183             break;
1184         }
1186         case SPI_V1_CMD_SETRXLINES:
1187         {
1188             object->rxLines = *(uint32_t *)arg;
1189             retVal = SPI_STATUS_SUCCESS;
1190             break;
1191         }
1193         case SPI_V1_CMD_SETMEMMORYMAPMODE:
1194         {
1195             object->qspiMode = QSPI_OPER_MODE_MMAP;
1196             retVal = SPI_STATUS_SUCCESS;
1197             break;
1198         }
1200         default:
1201         retVal = SPI_STATUS_UNDEFINEDCMD;
1202         break;
1203     }
1204     }
1206     return retVal;
1210 /*
1211  *  ======== QSPI_transferCancel_v1 ========
1212  */
1213 static void QSPI_transferCancel_v1(SPI_Handle handle)
1215     return;