aboutsummaryrefslogtreecommitdiffstats
path: root/mpm/lib/rfdc/xrfdc_intr.c
diff options
context:
space:
mode:
Diffstat (limited to 'mpm/lib/rfdc/xrfdc_intr.c')
-rw-r--r--mpm/lib/rfdc/xrfdc_intr.c771
1 files changed, 771 insertions, 0 deletions
diff --git a/mpm/lib/rfdc/xrfdc_intr.c b/mpm/lib/rfdc/xrfdc_intr.c
new file mode 100644
index 000000000..7b8bd0927
--- /dev/null
+++ b/mpm/lib/rfdc/xrfdc_intr.c
@@ -0,0 +1,771 @@
+/******************************************************************************
+*
+* Copyright (C) 2017-2019 Xilinx, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* Except as contained in this notice, the name of the Xilinx shall not be used
+* in advertising or otherwise to promote the sale, use or other dealings in
+* this Software without prior written authorization from Xilinx.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xrfdc_intr.c
+* @addtogroup rfdc_v6_0
+* @{
+*
+* This file contains functions related to RFdc interrupt handling.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ----- -------- -----------------------------------------------
+* 1.0 sk 05/16/17 First release
+* 2.1 sk 09/15/17 Remove Libmetal library dependency for MB.
+* 09/18/17 Add API to clear the interrupts.
+* sk 09/21/17 Add support for Over voltage and Over
+* Range interrupts.
+* 2.2 sk 10/18/17 Add support for FIFO and DATA overflow interrupt
+* 5.0 sk 08/24/18 Reorganize the code to improve readability and
+* optimization.
+* 5.1 cog 01/29/19 Replace structure reference ADC checks with
+* function.
+* 6.0 cog 02/20/19 Added handling for new ADC common mode over/under
+* voltage interrupts.
+* cog 02/20/19 XRFdc_GetIntrStatus now populates a pointer with the
+* status and returns an error code.
+* cog 02/20/19 XRFdc_IntrClr, XRFdc_IntrDisable and XRFdc_IntrEnable
+* now return error codes.
+* cog 03/25/19 The new common mode over/under voltage interrupts mask
+* bits were clashing with other interrupt bits.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "mpm/rfdc/xrfdc.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Variable Definitions *****************************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions ****************************/
+
+/****************************************************************************/
+/**
+*
+* This function sets the interrupt mask.
+*
+* @param InstancePtr is a pointer to the XRFdc instance
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3, and -1.
+* @param Block_Id is ADC/DAC block number inside the tile. Valid values
+* are 0-3.
+* @param IntrMask contains the interrupts to be enabled.
+* '1' enables an interrupt, and '0' disables.
+*
+* @return - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not available.
+*
+* @note None.
+*
+*****************************************************************************/
+u32 XRFdc_IntrEnable(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, u32 IntrMask)
+{
+ u32 BaseAddr;
+ u32 ReadReg;
+ u32 Index;
+ u32 NoOfBlocks;
+ u32 Status;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Status = XRFdc_CheckBlockEnabled(InstancePtr, Type, Tile_Id, Block_Id);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR, "\n Requested block not "
+ "available in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ Index = Block_Id;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ NoOfBlocks = XRFDC_NUM_OF_BLKS2;
+ if (Block_Id == XRFDC_BLK_ID1) {
+ Index = XRFDC_BLK_ID2;
+ NoOfBlocks = XRFDC_NUM_OF_BLKS4;
+ }
+ } else {
+ NoOfBlocks = Block_Id + 1U;
+ }
+
+ for (; Index < NoOfBlocks; Index++) {
+ ReadReg = XRFdc_ReadReg16(InstancePtr, 0x0,
+ XRFDC_COMMON_INTR_ENABLE);
+ if (Type == XRFDC_ADC_TILE) {
+ ReadReg |= (1U << (Tile_Id + 4));
+ XRFdc_WriteReg16(InstancePtr, 0x0,
+ XRFDC_COMMON_INTR_ENABLE, ReadReg);
+ BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_INTR_ENABLE,
+ (1U << Index), (1U << Index));
+ /* Enable Converter interrupts */
+ ReadReg = XRFdc_ReadReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_EN(Index));
+ if ((IntrMask & XRFDC_ADC_OVR_VOLTAGE_MASK) != 0U) {
+ ReadReg |= (XRFDC_ADC_OVR_VOLTAGE_MASK >>
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_OVR_RANGE_MASK) != 0U) {
+ ReadReg |= (XRFDC_ADC_OVR_RANGE_MASK >>
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_FIFO_OVR_MASK) != 0U) {
+ ReadReg |=
+ (XRFDC_ADC_FIFO_OVR_MASK >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_DAT_OVR_MASK) != 0U) {
+ ReadReg |=
+ (XRFDC_ADC_DAT_OVR_MASK >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_OVR_MASK) != 0U) {
+ ReadReg |=
+ (XRFDC_ADC_CMODE_OVR_MASK >> XRFDC_ADC_CMODE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_UNDR_MASK) != 0U) {
+ ReadReg |=
+ (XRFDC_ADC_CMODE_UNDR_MASK >> XRFDC_ADC_CMODE_SHIFT);
+ }
+
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_EN(Index), ReadReg);
+
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Index);
+
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_FABRIC_IMR_OFFSET,
+ XRFDC_IXR_FIFOUSRDAT_MASK, ReadReg);
+ }
+ /* Check for SUBADC interrupts */
+ if ((IntrMask & XRFDC_SUBADC_IXR_DCDR_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_SUBADC_IXR_DCDR_MASK) >>
+ XRFDC_ADC_SUBADC_DCDR_SHIFT;
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_DEC_IMR_OFFSET,
+ XRFDC_DEC_IMR_MASK, ReadReg);
+ }
+ /* Check for DataPath interrupts */
+ if ((IntrMask & XRFDC_ADC_IXR_DATAPATH_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_ADC_IXR_DATAPATH_MASK) >>
+ XRFDC_DATA_PATH_SHIFT;
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DATPATH_IMR_OFFSET,
+ XRFDC_ADC_DAT_IMR_MASK, ReadReg);
+ }
+ } else {
+ ReadReg |= (1U << Tile_Id);
+ XRFdc_WriteReg16(InstancePtr, 0x0,
+ XRFDC_COMMON_INTR_ENABLE, ReadReg);
+ BaseAddr = XRFDC_DAC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr,
+ XRFDC_INTR_ENABLE, (1U << Index), (1U << Index));
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Index);
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DAC_FABRIC_IMR_OFFSET,
+ XRFDC_IXR_FIFOUSRDAT_MASK, ReadReg);
+ }
+
+ if ((IntrMask & XRFDC_DAC_IXR_DATAPATH_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_DAC_IXR_DATAPATH_MASK) >>
+ XRFDC_DATA_PATH_SHIFT;
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DATPATH_IMR_OFFSET,
+ XRFDC_DAC_DAT_IMR_MASK, ReadReg);
+ }
+ }
+ }
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+
+/****************************************************************************/
+/**
+*
+* This function clears the interrupt mask.
+*
+* @param InstancePtr is a pointer to the XRFdc instance
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3, and -1.
+* @param Block_Id is ADC/DAC block number inside the tile. Valid values
+* are 0-3.
+* @param IntrMask contains the interrupts to be disabled.
+* '1' disables an interrupt, and '0' remains no change.
+*
+* @return - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not available.
+*
+* @note None.
+*
+*****************************************************************************/
+u32 XRFdc_IntrDisable(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, u32 IntrMask)
+{
+ u32 BaseAddr;
+ u32 ReadReg;
+ u32 Status;
+ u32 Index;
+ u32 NoOfBlocks;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Status = XRFdc_CheckBlockEnabled(InstancePtr, Type, Tile_Id, Block_Id);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR, "\n Requested block not "
+ "available in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ Index = Block_Id;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ NoOfBlocks = XRFDC_NUM_OF_BLKS2;
+ if (Block_Id == XRFDC_BLK_ID1) {
+ Index = XRFDC_BLK_ID2;
+ NoOfBlocks = XRFDC_NUM_OF_BLKS4;
+ }
+ } else {
+ NoOfBlocks = Block_Id + 1U;
+ }
+
+ for (; Index < NoOfBlocks; Index++) {
+ if (Type == XRFDC_ADC_TILE) {
+ BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ /* Check for Over Voltage and Over Range */
+ ReadReg = XRFdc_ReadReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_EN(Index));
+ if ((IntrMask & XRFDC_ADC_OVR_VOLTAGE_MASK) != 0U) {
+ ReadReg &= ~(XRFDC_ADC_OVR_VOLTAGE_MASK >>
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_OVR_RANGE_MASK) != 0U) {
+ ReadReg &= ~(XRFDC_ADC_OVR_RANGE_MASK >>
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ /* Disable Converter interrupts */
+ if ((IntrMask & XRFDC_ADC_FIFO_OVR_MASK) != 0U) {
+ ReadReg &=
+ ~(XRFDC_ADC_FIFO_OVR_MASK >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_DAT_OVR_MASK) != 0U) {
+ ReadReg &=
+ ~(XRFDC_ADC_DAT_OVR_MASK >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_OVR_MASK) != 0U) {
+ ReadReg &=
+ ~(XRFDC_ADC_CMODE_OVR_MASK >> XRFDC_ADC_CMODE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_UNDR_MASK) != 0U) {
+ ReadReg &=
+ ~(XRFDC_ADC_CMODE_UNDR_MASK >> XRFDC_ADC_CMODE_SHIFT);
+ }
+
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_EN(Index), ReadReg);
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Index);
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ ReadReg = IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK;
+ XRFdc_ClrReg(InstancePtr, BaseAddr, XRFDC_ADC_FABRIC_IMR_OFFSET,
+ ReadReg);
+ }
+ /* Check for SUBADC interrupts */
+ if ((IntrMask & XRFDC_SUBADC_IXR_DCDR_MASK) != 0U) {
+ ReadReg = ((IntrMask & XRFDC_SUBADC_IXR_DCDR_MASK) >>
+ XRFDC_ADC_SUBADC_DCDR_SHIFT);
+ XRFdc_ClrReg(InstancePtr, BaseAddr, XRFDC_ADC_DEC_IMR_OFFSET,
+ ReadReg);
+ }
+ /* Check for DataPath interrupts */
+ if ((IntrMask & XRFDC_ADC_IXR_DATAPATH_MASK) != 0U) {
+ ReadReg = ((IntrMask &
+ XRFDC_ADC_IXR_DATAPATH_MASK) >> XRFDC_DATA_PATH_SHIFT);
+ XRFdc_ClrReg(InstancePtr, BaseAddr, XRFDC_DATPATH_IMR_OFFSET,
+ ReadReg);
+ }
+ } else {
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Index);
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK);
+ XRFdc_ClrReg(InstancePtr, BaseAddr, XRFDC_DAC_FABRIC_IMR_OFFSET,
+ ReadReg);
+ }
+ /* Check for FIFO DataPath interrupts */
+ if ((IntrMask & XRFDC_DAC_IXR_DATAPATH_MASK) != 0U) {
+ ReadReg = ((IntrMask &
+ XRFDC_DAC_IXR_DATAPATH_MASK) >> XRFDC_DATA_PATH_SHIFT);
+ XRFdc_ClrReg(InstancePtr, BaseAddr, XRFDC_DATPATH_IMR_OFFSET,
+ ReadReg);
+ }
+ }
+ }
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+
+/****************************************************************************/
+/**
+*
+* This function returns the interrupt status read from Interrupt Status
+* Register(ISR).
+*
+* @param InstancePtr is a pointer to the XRFdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3, and -1.
+* @param Block_Id is ADC/DAC block number inside the tile. Valid values
+* are 0-3.
+* @param IntrStsPtr is pointer to a32-bit value representing the contents of
+* the Interrupt Status Registers (FIFO interface, Decoder interface,
+* Data Path Interface).
+*
+* @return - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not available.
+*
+* @note None.
+*
+*****************************************************************************/
+u32 XRFdc_GetIntrStatus(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, u32 *IntrStsPtr)
+{
+ u32 BaseAddr;
+ u32 ReadReg;
+ u32 Status;
+ u32 Block;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(IntrStsPtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Block = Block_Id;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ if ((Block_Id == XRFDC_BLK_ID2) || (Block_Id == XRFDC_BLK_ID3)) {
+ Block = XRFDC_BLK_ID1;
+ }
+ if (Block_Id == XRFDC_BLK_ID1) {
+ Block = XRFDC_BLK_ID0;
+ }
+ }
+ Status = XRFdc_CheckBlockEnabled(InstancePtr, Type, Tile_Id, Block);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR, "\n Requested block not "
+ "available in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ *IntrStsPtr = 0;
+
+ if (Type == XRFDC_ADC_TILE) {
+ BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ /* Check for Over Voltage and Over Range */
+ ReadReg = XRFdc_ReadReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id));
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_OVR_VOLTAGE_MASK) <<
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_OVR_RANGE_MASK) <<
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_FIFO_OVR_MASK) <<
+ XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_DAT_OVR_MASK) <<
+ XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+
+ /* Check for Common Mode Over/Under Voltage */
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_CMODE_OVR_MASK) <<
+ XRFDC_ADC_CMODE_SHIFT);
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_CMODE_UNDR_MASK) <<
+ XRFDC_ADC_CMODE_SHIFT);
+
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Block_Id);
+ /* Check for FIFO interface interrupts */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_FABRIC_ISR_OFFSET);
+ *IntrStsPtr |= (ReadReg & XRFDC_IXR_FIFOUSRDAT_MASK);
+ /* Check for SUBADC interrupts */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_DEC_ISR_OFFSET);
+ *IntrStsPtr |= ((ReadReg & XRFDC_DEC_ISR_SUBADC_MASK) <<
+ XRFDC_ADC_SUBADC_DCDR_SHIFT);
+ /* Check for DataPath interrupts */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_DATPATH_ISR_OFFSET);
+ *IntrStsPtr |= ((ReadReg & XRFDC_ADC_DAT_PATH_ISR_MASK) <<
+ XRFDC_DATA_PATH_SHIFT);
+ } else {
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Block_Id);
+ /* Check for FIFO interface interrupts */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_DAC_FABRIC_ISR_OFFSET);
+ *IntrStsPtr |= (ReadReg & XRFDC_IXR_FIFOUSRDAT_MASK);
+ /* Check for DataPath interrupts */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_DATPATH_ISR_OFFSET);
+ *IntrStsPtr |= ((ReadReg & XRFDC_DAC_DAT_PATH_ISR_MASK) <<
+ XRFDC_DATA_PATH_SHIFT);
+ }
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+
+/****************************************************************************/
+/**
+*
+* This function clear the interrupts.
+*
+* @param InstancePtr is a pointer to the XRFdc instance
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3, and -1.
+* @param Block_Id is ADC/DAC block number inside the tile. Valid values
+* are 0-3.
+* @param IntrMask contains the interrupts to be cleared.
+*
+* @return - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not available.
+*
+* @note None.
+*
+*****************************************************************************/
+u32 XRFdc_IntrClr(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, u32 IntrMask)
+{
+ u32 BaseAddr;
+ u32 Status;
+ u32 Block;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Block = Block_Id;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ if ((Block_Id == XRFDC_BLK_ID2) || (Block_Id == XRFDC_BLK_ID3)) {
+ Block = XRFDC_BLK_ID1;
+ }
+ if (Block_Id == XRFDC_BLK_ID1) {
+ Block = XRFDC_BLK_ID0;
+ }
+ }
+ Status = XRFdc_CheckBlockEnabled(InstancePtr, Type, Tile_Id, Block);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR, "\n Requested block not "
+ "available in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ if (Type == XRFDC_ADC_TILE) {
+ /* ADC */
+ BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ /* Check for Converter interrupts */
+ if ((IntrMask & XRFDC_ADC_OVR_VOLTAGE_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_OVR_VOLTAGE_MASK) >> XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_OVR_RANGE_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_OVR_RANGE_MASK) >> XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_FIFO_OVR_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_FIFO_OVR_MASK) >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_DAT_OVR_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_DAT_OVR_MASK) >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_OVR_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_CMODE_OVR_MASK) >> XRFDC_ADC_CMODE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_UNDR_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_CMODE_UNDR_MASK) >> XRFDC_ADC_CMODE_SHIFT);
+ }
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Block_Id);
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_FABRIC_ISR_OFFSET,
+ (IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK));
+ }
+ /* Check for SUBADC interrupts */
+ if ((IntrMask & XRFDC_SUBADC_IXR_DCDR_MASK) != 0U) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_DEC_ISR_OFFSET, (u16)((IntrMask &
+ XRFDC_SUBADC_IXR_DCDR_MASK) >> XRFDC_ADC_SUBADC_DCDR_SHIFT));
+ }
+ /* Check for DataPath interrupts */
+ if ((IntrMask & XRFDC_ADC_IXR_DATAPATH_MASK) != 0U) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_DATPATH_ISR_OFFSET, (u16)(IntrMask &
+ XRFDC_ADC_IXR_DATAPATH_MASK) >> XRFDC_DATA_PATH_SHIFT);
+ }
+ } else {
+ /* DAC */
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Block_Id);
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_DAC_FABRIC_ISR_OFFSET,
+ (u16)(IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK));
+ }
+ /* Check for DataPath interrupts */
+ if ((IntrMask & XRFDC_DAC_IXR_DATAPATH_MASK) != 0U) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_DATPATH_ISR_OFFSET, (u16)(IntrMask &
+ XRFDC_DAC_IXR_DATAPATH_MASK) >> XRFDC_DATA_PATH_SHIFT);
+ }
+ }
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+
+/****************************************************************************/
+/**
+*
+* This function is the interrupt handler for the driver.
+* It must be connected to an interrupt system by the application such that it
+* can be called when an interrupt occurs.
+*
+* @param Vector is interrupt vector number. Libmetal status handler
+* expects two parameters in the handler prototype, hence
+* kept this parameter. This is not used inside
+* the interrupt handler API.
+* @param XRFdcPtr contains a pointer to the driver instance
+*
+* @return None.
+*
+* @note Vector param is not useful inside the interrupt handler, hence
+* typecast with void to remove compilation warning.
+*
+******************************************************************************/
+u32 XRFdc_IntrHandler(u32 Vector, void *XRFdcPtr)
+{
+ XRFdc *InstancePtr = (XRFdc *)XRFdcPtr;
+ u32 Intrsts = 0x0U;
+ u32 Tile_Id = XRFDC_TILE_ID4;
+ u32 Block_Id = XRFDC_BLK_ID4;
+ u32 ReadReg;
+ u16 Type = 0U;
+ u32 BaseAddr;
+ u32 IntrMask = 0x0U;
+ u32 Block;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+
+ (void)Vector;
+ /*
+ * Read the interrupt ID register to determine which
+ * interrupt is active
+ */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, 0x0,
+ XRFDC_COMMON_INTR_STS);
+ if ((ReadReg & XRFDC_EN_INTR_DAC_TILE0_MASK) != 0U) {
+ Type = XRFDC_DAC_TILE;
+ Tile_Id = XRFDC_TILE_ID0;
+ } else if ((ReadReg & XRFDC_EN_INTR_DAC_TILE1_MASK) != 0U) {
+ Type = XRFDC_DAC_TILE;
+ Tile_Id = XRFDC_TILE_ID1;
+ } else if ((ReadReg & XRFDC_EN_INTR_DAC_TILE2_MASK) != 0U) {
+ Type = XRFDC_DAC_TILE;
+ Tile_Id = XRFDC_TILE_ID2;
+ } else if ((ReadReg & XRFDC_EN_INTR_DAC_TILE3_MASK) != 0U) {
+ Type = XRFDC_DAC_TILE;
+ Tile_Id = XRFDC_TILE_ID3;
+ } else if ((ReadReg & XRFDC_EN_INTR_ADC_TILE0_MASK) != 0U) {
+ Type = XRFDC_ADC_TILE;
+ Tile_Id = XRFDC_TILE_ID0;
+ } else if ((ReadReg & XRFDC_EN_INTR_ADC_TILE1_MASK) != 0U) {
+ Type = XRFDC_ADC_TILE;
+ Tile_Id = XRFDC_TILE_ID1;
+ } else if ((ReadReg & XRFDC_EN_INTR_ADC_TILE2_MASK) != 0U) {
+ Type = XRFDC_ADC_TILE;
+ Tile_Id = XRFDC_TILE_ID2;
+ } else if ((ReadReg & XRFDC_EN_INTR_ADC_TILE3_MASK) != 0U) {
+ Type = XRFDC_ADC_TILE;
+ Tile_Id = XRFDC_TILE_ID3;
+ } else {
+ metal_log(METAL_LOG_DEBUG, "\n Invalid Tile_Id \r\n");
+ }
+
+ BaseAddr = XRFDC_CTRL_STS_BASE(Type, Tile_Id);
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, XRFDC_INTR_STS);
+ if ((ReadReg & XRFDC_EN_INTR_SLICE0_MASK) != 0U) {
+ Block_Id = XRFDC_BLK_ID0;
+ } else if ((ReadReg & XRFDC_EN_INTR_SLICE1_MASK) != 0U) {
+ Block_Id = XRFDC_BLK_ID1;
+ } else if ((ReadReg & XRFDC_EN_INTR_SLICE2_MASK) != 0U) {
+ Block_Id = XRFDC_BLK_ID2;
+ } else if ((ReadReg & XRFDC_EN_INTR_SLICE3_MASK) != 0U) {
+ Block_Id = XRFDC_BLK_ID3;
+ } else {
+ metal_log(METAL_LOG_DEBUG, "\n Invalid ADC Block_Id \r\n");
+ }
+ (void)XRFdc_GetIntrStatus(InstancePtr, Type, Tile_Id, Block_Id, &Intrsts);
+ if (Type == XRFDC_ADC_TILE) {
+ /* ADC */
+ if ((Intrsts & XRFDC_ADC_OVR_VOLTAGE_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_ADC_OVR_VOLTAGE_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC Over Voltage interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_OVR_RANGE_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_ADC_OVR_RANGE_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC Over Range interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_FIFO_OVR_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_ADC_FIFO_OVR_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC FIFO OF interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_DAT_OVR_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_ADC_DAT_OVR_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC DATA OF interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_CMODE_OVR_MASK) != 0U) {
+ IntrMask |= XRFDC_ADC_CMODE_OVR_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC CMODE OV interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_CMODE_UNDR_MASK) != 0U) {
+ IntrMask |= XRFDC_ADC_CMODE_UNDR_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC CMODE UV interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_IXR_FIFOUSRDAT_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC FIFO interface interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_SUBADC_IXR_DCDR_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_SUBADC_IXR_DCDR_MASK;
+ metal_log(METAL_LOG_DEBUG,
+ "\n ADC Decoder interface interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_IXR_DATAPATH_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_ADC_IXR_DATAPATH_MASK;
+ metal_log(METAL_LOG_DEBUG,
+ "\n ADC Data Path interface interrupt \r\n");
+ }
+ } else {
+ /* DAC */
+ if ((Intrsts & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_IXR_FIFOUSRDAT_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n DAC FIFO interface interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_DAC_IXR_DATAPATH_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_DAC_IXR_DATAPATH_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n DAC Data Path interface interrupt \r\n");
+ }
+ }
+ Block = Block_Id;
+
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ if ((Block_Id == XRFDC_BLK_ID0) || (Block_Id == XRFDC_BLK_ID1)) {
+ Block = XRFDC_BLK_ID0;
+ } else {
+ Block = XRFDC_BLK_ID1;
+ }
+ }
+ InstancePtr->StatusHandler(InstancePtr->CallBackRef, Type, Tile_Id,
+ Block, IntrMask);
+
+ /* Clear the interrupt */
+ if (Type == XRFDC_ADC_TILE) {
+ /* ADC */
+ XRFdc_IntrClr(InstancePtr, XRFDC_ADC_TILE, Tile_Id, Block_Id, Intrsts);
+
+ } else {
+ /* DAC */
+ XRFdc_IntrClr(InstancePtr, XRFDC_DAC_TILE, Tile_Id, Block_Id, Intrsts);
+ }
+
+ return (u32)METAL_IRQ_HANDLED;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets the status callback function, the status handler, which the
+* driver calls when it encounters conditions that should be reported to the
+* higher layer software. The handler executes in an interrupt context, so
+* the amount of processing should be minimized
+*
+*
+* @param InstancePtr is a pointer to the XRFdc instance.
+* @param CallBackRef is the upper layer callback reference passed back
+* when the callback function is invoked.
+* @param FunctionPtr is the pointer to the callback function.
+*
+* @return None.
+*
+* @note
+*
+* The handler is called within interrupt context, so it should finish its
+* work quickly.
+*
+******************************************************************************/
+void XRFdc_SetStatusHandler(XRFdc *InstancePtr, void *CallBackRef,
+ XRFdc_StatusHandler FunctionPtr)
+{
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(FunctionPtr != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == (u32)XRFDC_COMPONENT_IS_READY);
+
+ InstancePtr->StatusHandler = FunctionPtr;
+ InstancePtr->CallBackRef = CallBackRef;
+}
+
+/** @} */