Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:05

0001 /******************************************************************************
0002 * Copyright (C) 2020 - 2022 Xilinx, Inc.  All rights reserved.
0003 * SPDX-License-Identifier: MIT
0004 ******************************************************************************/
0005 
0006 
0007 /*****************************************************************************/
0008 /**
0009  *
0010  * @file xqspipsu_control.c
0011  * @addtogroup Overview
0012  * @{
0013  *
0014  * This file contains intermediate control functions used by functions
0015  * in xqspipsu.c and xqspipsu_options.c files.
0016  *
0017  * <pre>
0018  * MODIFICATION HISTORY:
0019  *
0020  * Ver   Who Date     Changes
0021  * ----- --- -------- -----------------------------------------------
0022  * 1.11   akm  03/09/20 First release
0023  * 1.13   akm  01/04/21 Fix MISRA-C violations.
0024  * 1.15   akm  10/21/21 Fix MISRA-C violations.
0025  * 1.15   akm  03/03/22 Enable tapdelay settings for applications on
0026  *           Microblaze platform.
0027  * </pre>
0028  *
0029  ******************************************************************************/
0030 
0031 /***************************** Include Files *********************************/
0032 
0033 #include "xqspipsu_control.h"
0034 
0035 /************************** Constant Definitions *****************************/
0036 
0037 /**************************** Type Definitions *******************************/
0038 
0039 /***************** Macros (Inline Functions) Definitions *********************/
0040 
0041 /************************** Function Prototypes ******************************/
0042 
0043 /************************** Variable Definitions *****************************/
0044 
0045 /*****************************************************************************/
0046 
0047 /*****************************************************************************/
0048 /**
0049  *
0050  * This function writes the GENFIFO entries to transmit the messages requested.
0051  *
0052  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0053  * @param   Msg is a pointer to the structure containing transfer data.
0054  *
0055  * @return
0056  *      - XST_SUCCESS if successful.
0057  *      - XST_FAILURE if transfer fails.
0058  *      - XST_DEVICE_BUSY if a transfer is already in progress.
0059  *
0060  * @note    None.
0061  *
0062  ******************************************************************************/
0063 void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
0064 {
0065     u32 GenFifoEntry;
0066 
0067     Xil_AssertVoid(InstancePtr != NULL);
0068     Xil_AssertVoid(Msg != NULL);
0069     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0070 #ifdef DEBUG
0071     xil_printf("\nXQspiPsu_GenFifoEntryData\r\n");
0072 #endif
0073 
0074     GenFifoEntry = 0x0U;
0075     /* Bus width */
0076     GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_MODE_MASK;
0077     GenFifoEntry |= XQspiPsu_SelectSpiMode((u8)Msg->BusWidth);
0078 
0079     GenFifoEntry |= InstancePtr->GenFifoCS;
0080     GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_BUS_MASK;
0081     GenFifoEntry |= InstancePtr->GenFifoBus;
0082 
0083     /* Data */
0084     if (((Msg->Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != (u32)FALSE) {
0085         GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE;
0086     } else {
0087         GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
0088     }
0089     /* If Byte Count is less than 8 bytes do the transfer in IO mode */
0090     if ((Msg->ByteCount < 8U) &&
0091         (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA)) {
0092         InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
0093         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
0094             (XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) &
0095                     ~XQSPIPSU_CFG_MODE_EN_MASK));
0096         InstancePtr->IsUnaligned = 1;
0097     }
0098 
0099     XQspiPsu_TXRXSetup(InstancePtr, Msg, &GenFifoEntry);
0100 
0101     XQspiPsu_GenFifoEntryDataLen(InstancePtr, Msg, &GenFifoEntry);
0102 
0103     /* One dummy GenFifo entry in case of IO mode */
0104     if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_IO) &&
0105             ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
0106         GenFifoEntry = 0x0U;
0107 #ifdef DEBUG
0108         xil_printf("\nDummy FifoEntry=%08x\r\n", GenFifoEntry);
0109 #endif
0110         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
0111     }
0112 }
0113 
0114 /*****************************************************************************/
0115 /**
0116  *
0117  * This function enables the polling functionality of controller
0118  *
0119  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0120  *
0121  *
0122  * @param   FlashMsg is a pointer to the structure containing transfer data
0123  *
0124  * @return  None
0125  *
0126  * @note    None.
0127  *
0128  ******************************************************************************/
0129 void XQspiPsu_PollDataConfig(XQspiPsu *InstancePtr, XQspiPsu_Msg *FlashMsg)
0130 {
0131 
0132     u32 GenFifoEntry;
0133     u32 Value;
0134 
0135     Xil_AssertVoid(InstancePtr != NULL);
0136     Xil_AssertVoid(FlashMsg != NULL);
0137     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0138 #ifdef DEBUG
0139     xil_printf("\nXQspiPsu_PollDataConfig\r\n");
0140 #endif
0141 
0142     Value = XQspiPsu_CreatePollDataConfig(InstancePtr, FlashMsg);
0143     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0144             XQSPIPSU_POLL_CFG_OFFSET, Value);
0145     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0146             XQSPIPSU_P_TO_OFFSET, FlashMsg->PollTimeout);
0147 
0148     XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
0149 
0150     GenFifoEntry = (u32)0;
0151     GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_TX;
0152     GenFifoEntry |= InstancePtr->GenFifoBus;
0153     GenFifoEntry |= InstancePtr->GenFifoCS;
0154     GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI;
0155     GenFifoEntry |= (u32)FlashMsg->PollStatusCmd;
0156 
0157     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0158         XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
0159 
0160     GenFifoEntry = (u32)0;
0161     GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_POLL;
0162     GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_RX;
0163     GenFifoEntry |= InstancePtr->GenFifoBus;
0164     GenFifoEntry |= InstancePtr->GenFifoCS;
0165     GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI;
0166     if (((FlashMsg->Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != (u32)FALSE) {
0167         GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE;
0168     } else {
0169         GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
0170     }
0171     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
0172             GenFifoEntry);
0173 
0174     /* One Dummy entry required for IO mode */
0175     GenFifoEntry = 0x0U;
0176     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
0177             GenFifoEntry);
0178 
0179     InstancePtr->Msg = FlashMsg;
0180     InstancePtr->NumMsg = (s32)1;
0181     InstancePtr->MsgCnt = 0;
0182 
0183     Value = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0184             XQSPIPSU_CFG_OFFSET);
0185     Value &= ~XQSPIPSU_CFG_MODE_EN_MASK;
0186     Value |= (XQSPIPSU_CFG_START_GEN_FIFO_MASK |
0187             XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK |
0188             XQSPIPSU_CFG_EN_POLL_TO_MASK);
0189     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
0190             Value);
0191 
0192     /* Enable interrupts */
0193     Value = ((u32)XQSPIPSU_IER_RXNEMPTY_MASK |
0194         (u32)XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK);
0195 
0196     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_IER_OFFSET,
0197             Value);
0198 
0199 }
0200 
0201 #if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__)
0202 /*****************************************************************************/
0203 /**
0204 *
0205 * Configures the clock according to the prescaler passed.
0206 *
0207 *
0208 * @param    InstancePtr is a pointer to the XQspiPsu instance.
0209 * @param    Prescaler - clock prescaler.
0210 *
0211 * @return
0212 *       - XST_SUCCESS if successful.
0213 *       - XST_DEVICE_BUSY if the device is currently transferring data.
0214 *       The transfer must complete or be aborted before setting Tapdelay.
0215 *
0216 * @note     None.
0217 *
0218 ******************************************************************************/
0219 s32 XQspipsu_Calculate_Tapdelay(const XQspiPsu *InstancePtr, u8 Prescaler)
0220 {
0221     u32 FreqDiv, Divider;
0222     u32 Tapdelay = 0;
0223     u32 LBkModeReg = 0;
0224     u32 delayReg = 0;
0225     s32 Status;
0226 
0227     Xil_AssertNonvoid(InstancePtr != NULL);
0228     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0229     Xil_AssertNonvoid(Prescaler <= XQSPIPSU_CR_PRESC_MAXIMUM);
0230 
0231     /*
0232      * Do not allow the slave select to change while a transfer is in
0233      * progress. Not thread-safe.
0234      */
0235     if (InstancePtr->IsBusy == (u32)TRUE) {
0236         Status = (s32)XST_DEVICE_BUSY;
0237         goto END;
0238     } else {
0239 
0240         Divider = (u32)1U << (Prescaler+1U);
0241 
0242         FreqDiv = (InstancePtr->Config.InputClockHz)/Divider;
0243 
0244 #if defined (versal)
0245         if (FreqDiv <= XQSPIPSU_FREQ_37_5MHZ) {
0246 #else
0247         if (FreqDiv <= XQSPIPSU_FREQ_40MHZ) {
0248 #endif
0249             Tapdelay |= (TAPDLY_BYPASS_VALVE_40MHZ <<
0250                      IOU_TAPDLY_BYPASS_LQSPI_RX_SHIFT);
0251         } else if (FreqDiv <= XQSPIPSU_FREQ_100MHZ) {
0252             Tapdelay |= (TAPDLY_BYPASS_VALVE_100MHZ <<
0253                      IOU_TAPDLY_BYPASS_LQSPI_RX_SHIFT);
0254             LBkModeReg |= (USE_DLY_LPBK << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT);
0255 #if defined (versal)
0256             delayReg |= (u32)USE_DATA_DLY_ADJ  <<
0257                     XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_SHIFT;
0258 #else
0259             delayReg |= ((u32)USE_DATA_DLY_ADJ  <<
0260                     XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_SHIFT) |
0261                             ((u32)DATA_DLY_ADJ_DLY  << XQSPIPSU_DATA_DLY_ADJ_DLY_SHIFT);
0262 #endif
0263         } else if (FreqDiv <= XQSPIPSU_FREQ_150MHZ) {
0264 #if defined (versal)
0265             LBkModeReg |= (USE_DLY_LPBK  << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT) |
0266                     (LPBK_DLY_ADJ_DLY1 << XQSPIPSU_LPBK_DLY_ADJ_DLY1_SHIFT);
0267 #else
0268             LBkModeReg |= USE_DLY_LPBK  << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT;
0269 #endif
0270         } else {
0271             Status = (s32)XST_FAILURE;
0272             goto END;
0273         }
0274 
0275         Status =  XQspipsu_Set_TapDelay(InstancePtr, Tapdelay, LBkModeReg, delayReg);
0276     }
0277 
0278     END:
0279     return Status;
0280 }
0281 #endif
0282 /** @} */