diff options
Diffstat (limited to 'mpm/lib/rfdc/xrfdc_intr.c')
-rw-r--r-- | mpm/lib/rfdc/xrfdc_intr.c | 771 |
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; +} + +/** @} */ |