diff options
Diffstat (limited to 'bsps/shared/dev/spi/xqspipsu_control.c')
-rw-r--r-- | bsps/shared/dev/spi/xqspipsu_control.c | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/bsps/shared/dev/spi/xqspipsu_control.c b/bsps/shared/dev/spi/xqspipsu_control.c new file mode 100644 index 0000000000..af2400bf4c --- /dev/null +++ b/bsps/shared/dev/spi/xqspipsu_control.c @@ -0,0 +1,282 @@ +/****************************************************************************** +* Copyright (C) 2020 - 2022 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + + +/*****************************************************************************/ +/** + * + * @file xqspipsu_control.c + * @addtogroup Overview + * @{ + * + * This file contains intermediate control functions used by functions + * in xqspipsu.c and xqspipsu_options.c files. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- --- -------- ----------------------------------------------- + * 1.11 akm 03/09/20 First release + * 1.13 akm 01/04/21 Fix MISRA-C violations. + * 1.15 akm 10/21/21 Fix MISRA-C violations. + * 1.15 akm 03/03/22 Enable tapdelay settings for applications on + * Microblaze platform. + * </pre> + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xqspipsu_control.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ + +/*****************************************************************************/ +/** + * + * This function writes the GENFIFO entries to transmit the messages requested. + * + * @param InstancePtr is a pointer to the XQspiPsu instance. + * @param Msg is a pointer to the structure containing transfer data. + * + * @return + * - XST_SUCCESS if successful. + * - XST_FAILURE if transfer fails. + * - XST_DEVICE_BUSY if a transfer is already in progress. + * + * @note None. + * + ******************************************************************************/ +void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg) +{ + u32 GenFifoEntry; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Msg != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); +#ifdef DEBUG + xil_printf("\nXQspiPsu_GenFifoEntryData\r\n"); +#endif + + GenFifoEntry = 0x0U; + /* Bus width */ + GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_MODE_MASK; + GenFifoEntry |= XQspiPsu_SelectSpiMode((u8)Msg->BusWidth); + + GenFifoEntry |= InstancePtr->GenFifoCS; + GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_BUS_MASK; + GenFifoEntry |= InstancePtr->GenFifoBus; + + /* Data */ + if (((Msg->Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != (u32)FALSE) { + GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE; + } else { + GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE; + } + /* If Byte Count is less than 8 bytes do the transfer in IO mode */ + if ((Msg->ByteCount < 8U) && + (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA)) { + InstancePtr->ReadMode = XQSPIPSU_READMODE_IO; + XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET, + (XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) & + ~XQSPIPSU_CFG_MODE_EN_MASK)); + InstancePtr->IsUnaligned = 1; + } + + XQspiPsu_TXRXSetup(InstancePtr, Msg, &GenFifoEntry); + + XQspiPsu_GenFifoEntryDataLen(InstancePtr, Msg, &GenFifoEntry); + + /* One dummy GenFifo entry in case of IO mode */ + if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_IO) && + ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) { + GenFifoEntry = 0x0U; +#ifdef DEBUG + xil_printf("\nDummy FifoEntry=%08x\r\n", GenFifoEntry); +#endif + XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry); + } +} + +/*****************************************************************************/ +/** + * + * This function enables the polling functionality of controller + * + * @param InstancePtr is a pointer to the XQspiPsu instance. + * + * + * @param FlashMsg is a pointer to the structure containing transfer data + * + * @return None + * + * @note None. + * + ******************************************************************************/ +void XQspiPsu_PollDataConfig(XQspiPsu *InstancePtr, XQspiPsu_Msg *FlashMsg) +{ + + u32 GenFifoEntry; + u32 Value; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FlashMsg != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); +#ifdef DEBUG + xil_printf("\nXQspiPsu_PollDataConfig\r\n"); +#endif + + Value = XQspiPsu_CreatePollDataConfig(InstancePtr, FlashMsg); + XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPSU_POLL_CFG_OFFSET, Value); + XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPSU_P_TO_OFFSET, FlashMsg->PollTimeout); + + XQspiPsu_GenFifoEntryCSAssert(InstancePtr); + + GenFifoEntry = (u32)0; + GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_TX; + GenFifoEntry |= InstancePtr->GenFifoBus; + GenFifoEntry |= InstancePtr->GenFifoCS; + GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI; + GenFifoEntry |= (u32)FlashMsg->PollStatusCmd; + + XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, + XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry); + + GenFifoEntry = (u32)0; + GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_POLL; + GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_RX; + GenFifoEntry |= InstancePtr->GenFifoBus; + GenFifoEntry |= InstancePtr->GenFifoCS; + GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI; + if (((FlashMsg->Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != (u32)FALSE) { + GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE; + } else { + GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE; + } + XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET, + GenFifoEntry); + + /* One Dummy entry required for IO mode */ + GenFifoEntry = 0x0U; + XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET, + GenFifoEntry); + + InstancePtr->Msg = FlashMsg; + InstancePtr->NumMsg = (s32)1; + InstancePtr->MsgCnt = 0; + + Value = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, + XQSPIPSU_CFG_OFFSET); + Value &= ~XQSPIPSU_CFG_MODE_EN_MASK; + Value |= (XQSPIPSU_CFG_START_GEN_FIFO_MASK | + XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK | + XQSPIPSU_CFG_EN_POLL_TO_MASK); + XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET, + Value); + + /* Enable interrupts */ + Value = ((u32)XQSPIPSU_IER_RXNEMPTY_MASK | + (u32)XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK); + + XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_IER_OFFSET, + Value); + +} + +#if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__) +/*****************************************************************************/ +/** +* +* Configures the clock according to the prescaler passed. +* +* +* @param InstancePtr is a pointer to the XQspiPsu instance. +* @param Prescaler - clock prescaler. +* +* @return +* - XST_SUCCESS if successful. +* - XST_DEVICE_BUSY if the device is currently transferring data. +* The transfer must complete or be aborted before setting Tapdelay. +* +* @note None. +* +******************************************************************************/ +s32 XQspipsu_Calculate_Tapdelay(const XQspiPsu *InstancePtr, u8 Prescaler) +{ + u32 FreqDiv, Divider; + u32 Tapdelay = 0; + u32 LBkModeReg = 0; + u32 delayReg = 0; + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Prescaler <= XQSPIPSU_CR_PRESC_MAXIMUM); + + /* + * Do not allow the slave select to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy == (u32)TRUE) { + Status = (s32)XST_DEVICE_BUSY; + goto END; + } else { + + Divider = (u32)1U << (Prescaler+1U); + + FreqDiv = (InstancePtr->Config.InputClockHz)/Divider; + +#if defined (versal) + if (FreqDiv <= XQSPIPSU_FREQ_37_5MHZ) { +#else + if (FreqDiv <= XQSPIPSU_FREQ_40MHZ) { +#endif + Tapdelay |= (TAPDLY_BYPASS_VALVE_40MHZ << + IOU_TAPDLY_BYPASS_LQSPI_RX_SHIFT); + } else if (FreqDiv <= XQSPIPSU_FREQ_100MHZ) { + Tapdelay |= (TAPDLY_BYPASS_VALVE_100MHZ << + IOU_TAPDLY_BYPASS_LQSPI_RX_SHIFT); + LBkModeReg |= (USE_DLY_LPBK << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT); +#if defined (versal) + delayReg |= (u32)USE_DATA_DLY_ADJ << + XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_SHIFT; +#else + delayReg |= ((u32)USE_DATA_DLY_ADJ << + XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_SHIFT) | + ((u32)DATA_DLY_ADJ_DLY << XQSPIPSU_DATA_DLY_ADJ_DLY_SHIFT); +#endif + } else if (FreqDiv <= XQSPIPSU_FREQ_150MHZ) { +#if defined (versal) + LBkModeReg |= (USE_DLY_LPBK << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT) | + (LPBK_DLY_ADJ_DLY1 << XQSPIPSU_LPBK_DLY_ADJ_DLY1_SHIFT); +#else + LBkModeReg |= USE_DLY_LPBK << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT; +#endif + } else { + Status = (s32)XST_FAILURE; + goto END; + } + + Status = XQspipsu_Set_TapDelay(InstancePtr, Tapdelay, LBkModeReg, delayReg); + } + + END: + return Status; +} +#endif +/** @} */ |