diff options
Diffstat (limited to 'mpm/lib/rfdc/xrfdc.c')
-rw-r--r-- | mpm/lib/rfdc/xrfdc.c | 5345 |
1 files changed, 5345 insertions, 0 deletions
diff --git a/mpm/lib/rfdc/xrfdc.c b/mpm/lib/rfdc/xrfdc.c new file mode 100644 index 000000000..6261db774 --- /dev/null +++ b/mpm/lib/rfdc/xrfdc.c @@ -0,0 +1,5345 @@ +/****************************************************************************** +* +* 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.c +* @addtogroup xrfdc_v6_0 +* @{ +* +* Contains the interface functions of the XRFdc driver. +* See xrfdc.h for a detailed description of the device and driver. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- --- -------- ----------------------------------------------- +* 1.0 sk 05/16/17 Initial release +* 2.0 sk 08/09/17 Fixed coarse Mixer configuration settings +* CR# 977266, 977872. +* Return error for Slice Event on 4G ADC Block. +* 08/16/17 Add support for SYSREF and PL event sources. +* 08/18/17 Add API to enable and disable FIFO. +* 08/23/17 Add API to configure Nyquist zone. +* 08/30/17 Add additional info to BlockStatus. +* 08/30/17 Add support for Coarse Mixer BYPASS mode. +* 08/31/17 Removed Tile Reset Assert and Deassert. +* 09/07/17 Add support for negative NCO freq. +* 09/15/17 Fixed NCO freq precision issue. +* 09/15/17 Fixed Immediate Event source issue and also +* updated the Immediate Macro value to 0. +* 2.1 sk 09/15/17 Remove Libmetal library dependency for MB. +* sk 09/25/17 Modified XRFdc_GetBlockStatus API to give +* correct information and also updates the +* description for Vector Param in intr handler +* Add API to get Output current and removed +* GetTermVoltage and GetOutputCurr inline functions. +* 2.2 sk 10/05/17 Fixed XRFdc_GetNoOfADCBlocks API for 4GSPS. +* Enable the decoder clock based on decoder mode. +* Add API to get the current FIFO status. +* Updated XRFdc_DumpRegs API for better readability +* of output register dump. +* Add support for 4GSPS CoarseMixer frequency. +* 10/11/17 Modify float types to double to increase precision. +* 10/12/17 Update BlockStatus API to give current status. +* In BYPASS mode, input datatype can be Real or IQ, +* hence checked both while reading the mixer mode. +* 10/17/17 Fixed Set Threshold API Issue. +* 2.3 sk 11/06/17 Fixed PhaseOffset truncation issue. +* Provide user configurability for FineMixerScale. +* 11/08/17 Return error for DAC R2C mode and ADC C2R mode. +* 11/20/17 Fixed StartUp, Shutdown and Reset API for Tile_Id -1. +* 11/20/17 Remove unwanted ADC block checks in 4GSPS mode. +* 3.0 sk 12/11/17 Added DDC and DUC support. +* 12/13/17 Add CoarseMixMode field in Mixer_Settings structure. +* 12/15/17 Add support to switch calibration modes. +* 12/15/17 Add support for mixer frequencies > Fs/2 and < -Fs/2. +* sg 13/01/18 Added PLL and external clock switch support. +* Added API to get PLL lock status. +* Added API to get clock source. +* 3.1 jm 01/24/18 Add Multi-tile sync support. +* sk 01/25/18 Updated Set and Get Interpolation/Decimation factor +* API's to consider the actual factor value. +* 3.2 sk 02/02/18 Add API's to configure inverse-sinc. +* sk 02/27/18 Add API's to configure Multiband. +* sk 03/09/18 Update PLL structure in XRFdc_DynamicPLLConfig API. +* sk 03/09/18 Update ADC and DAC datatypes in Mixer API and use +* input datatype for ADC in threshold and QMC APIs. +* sk 03/09/18 Removed FIFO disable check in DDC and DUC APIs. +* sk 03/09/18 Add support for Marker event source for DAC block. +* sk 03/22/18 Updated PLL settings based on latest IP values. +* 4.0 sk 04/17/18 Corrected Set/Get MixerSettings API description for +* FineMixerScale parameter. +* sk 04/19/18 Enable VCO Auto selection while configuring the clock. +* sk 04/24/18 Add API to get PLL Configurations. +* sk 04/24/18 Add API to get the Link Coupling mode. +* sk 04/28/18 Implement timeouts for PLL Lock, Startup and shutdown. +* sk 05/30/18 Removed CalibrationMode check for DAC. +* sk 06/05/18 Updated minimum Ref clock value to 102.40625MHz. +* 5.0 sk 06/25/18 Update DAC min sampling rate to 500MHz and also update +* VCO Range, PLL_DIVIDER and PLL_FPDIV ranges. +* sk 06/25/18 Add XRFdc_GetFabClkOutDiv() API to read fabric clk div. +* Add Inline APIs XRFdc_CheckBlockEnabled(), +* XRFdc_CheckTileEnabled(). +* sk 07/06/18 Add support to dump HSCOM regs in XRFdc_DumpRegs() API +* sk 07/12/18 Fixed Multiband crossbar settings in C2C mode. +* sk 07/19/18 Add MixerType member to MixerSettings structure and +* Update Mixer Settings APIs to consider the MixerType +* variable. +* sk 07/19/18 Add XRFdc_GetMultibandConfig() API to read Multiband +* configuration. +* sk 07/20/18 Update the APIs to check the corresponding section +* (Digital/Analog)enable/disable. +* sk 07/26/18 Fixed Doxygen, coverity warnings. +* sk 08/03/18 Fixed MISRAC warnings. +* sk 08/24/18 Move mixer related APIs to xrfdc_mixer.c file. +* Define asserts for Linux, Re-arranged XRFdc_RestartIPSM, +* XRFdc_CfgInitialize() and XRFdc_MultiBand() APIs. +* Reorganize the code to improve readability and +* optimization. +* sk 09/24/18 Update powerup-state value based on PLL mode in +* XRFdc_DynamicPLLConfig() API. +* sk 10/10/18 Check for DigitalPath enable in XRFdc_GetNyquistZone() +* and XRFdc_GetCalibrationMode() APIs for Multiband. +* sk 10/13/18 Add support to read the REFCLKDIV param from design. +* Update XRFdc_SetPLLConfig() API to support range of +* REF_CLK_DIV values(1 to 4). +* 5.1 cog 01/29/19 Replace structure reference ADC checks with +* function. +* cog 01/29/19 Added XRFdc_SetDither() and XRFdc_GetDither() APIs. +* cog 01/29/19 Rename DataType for mixer input to MixerInputDataType +* for readability. +* cog 01/29/19 Refactoring of interpolation and decimation APIs and +* changed fabric rate for decimation X8 for non-high speed ADCs. +* cog 01/29/19 New inline functions to determine max & min sampling rates +* rates in PLL range checking. +* 6.0 cog 02/17/19 Added decimation & interpolation modes +* 02/17/19 Added Inverse-Sinc Second Nyquist Zone Support +* cog 02/17/19 Added new clock Distribution functionality. +* cog 02/17/19 Refactored to improve delay balancing in clock +* distribution. +* cog 02/17/19 Added delay calculation & metal log messages. +* cog 02/17/19 Added intratile clock settings. +* cog 02/17/19 Moved multiband to a new file xrfdc_mb.c +* cog 02/17/19 Moved clocking functionality to a new file xrfdc_clock.c +* cog 02/17/19 Added XRFdc_SetIMRPassMode() and XRFdc_SetIMRPassMode() APIs +* cog 02/17/19 Added XRFdc_SetDACMode() and XRFdc_GetDACMode() APIs +* cog 02/17/19 Added XRFdc_SetSignalDetector() and XRFdc_GetSignalDetector() APIs. +* cog 02/17/19 Added XRFdc_DisableCoefficientsOverride(), XRFdc_SetCalCoefficients +* and XRFdc_GetCalCoefficients APIs. +* cog 02/21/19 Added XRFdc_SetCalFreeze() and XRFdc_GetCalFreeze() APIs. +* cog 04/09/19 Changed Calibrtation coefficient override control register for OCB1. +* cog 04/15/19 Rename XRFdc_SetDACMode() and XRFdc_GetDACMode() APIs to +* XRFdc_SetDataPathMode() and XRFdc_GetDataPathMode() respectively. +* cog 04/30/19 Made Changes to the bypass calibration functionality to support Gen2 +* and below. +* +* </pre> +* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "mpm/rfdc/xrfdc.h" + +/************************** Constant Definitions *****************************/ +#define XRFDC_PLL_LOCK_DLY_CNT 1000U + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +static u32 XRFdc_RestartIPSM(XRFdc *InstancePtr, u32 Type, int Tile_Id, + u32 Start, u32 End); +static void StubHandler(void *CallBackRefPtr, u32 Type, u32 Tile_Id, + u32 Block_Id, u32 StatusEvent); +static void XRFdc_ADCInitialize(XRFdc *InstancePtr); +static void XRFdc_DACInitialize(XRFdc *InstancePtr); +static void XRFdc_DACMBConfigInit(XRFdc *InstancePtr, u32 Tile_Id, + u32 Block_Id); +static void XRFdc_ADCMBConfigInit(XRFdc *InstancePtr, u32 Tile_Id, + u32 Block_Id); +static void XRFdc_UpdatePLLStruct(XRFdc *InstancePtr, u32 Type, u32 Tile_Id); +static u32 XRFdc_GetADCBlockStatus(XRFdc *InstancePtr, u32 BaseAddr, + u32 Tile_Id, u32 Block_Id, XRFdc_BlockStatus *BlockStatusPtr); +static u32 XRFdc_GetDACBlockStatus(XRFdc *InstancePtr, u32 BaseAddr, + u32 Tile_Id, u32 Block_Id, XRFdc_BlockStatus *BlockStatusPtr); +static void XRFdc_DumpHSCOMRegs(XRFdc *InstancePtr, u32 Type, int Tile_Id); +static void XRFdc_DumpDACRegs(XRFdc *InstancePtr, int Tile_Id); +static void XRFdc_DumpADCRegs(XRFdc *InstancePtr, int Tile_Id); +static u32 XRFdc_WaitForRestartClr(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 BaseAddr, u32 End); + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* Initializes a specific XRFdc instance such that the driver is ready to use. +* +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param ConfigPtr is a reference to a structure containing information +* about xrfdc. This function initializes an InstancePtr object +* for a specific device specified by the contents of Config. +* +* @return +* - XRFDC_SUCCESS if successful. +* +* @note The user needs to first call the XRFdc_LookupConfig() API +* which returns the Configuration structure pointer which is +* passed as a parameter to the XRFdc_CfgInitialize() API. +* +******************************************************************************/ +u32 XRFdc_CfgInitialize(XRFdc *InstancePtr, XRFdc_Config *ConfigPtr) +{ + u32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + InstancePtr->io = (struct metal_io_region *) + metal_allocate_memory(sizeof(struct metal_io_region)); + metal_io_init(InstancePtr->io, (void *)(metal_phys_addr_t)ConfigPtr->BaseAddr, + &ConfigPtr->BaseAddr, XRFDC_REGION_SIZE, (unsigned)(-1), 0, NULL); + + /* + * Set the values read from the device config and the base address. + */ + InstancePtr->BaseAddr = ConfigPtr->BaseAddr; + InstancePtr->RFdc_Config = *ConfigPtr; + InstancePtr->ADC4GSPS = ConfigPtr->ADCType; + InstancePtr->StatusHandler = StubHandler; + + /* Initialize ADC */ + XRFdc_ADCInitialize(InstancePtr); + + /* Initialize DAC */ + XRFdc_DACInitialize(InstancePtr); + + /* + * Indicate the instance is now ready to use and + * initialized without error. + */ + InstancePtr->IsReady = XRFDC_COMPONENT_IS_READY; + + Status = XRFDC_SUCCESS; + return Status; +} + +/*****************************************************************************/ +/** +* +* Initialize ADC Tiles. +* +* +* @param InstancePtr is a pointer to the XRfdc instance. +* +* @return +* - None. +* +* @note Static API used to initialize ADC Tiles +* +******************************************************************************/ +static void XRFdc_ADCInitialize(XRFdc *InstancePtr) +{ + u32 Tile_Id; + u32 Block_Id; + u8 MixerType; + + for (Tile_Id = XRFDC_TILE_ID0; Tile_Id < XRFDC_TILE_ID4; Tile_Id++) { + InstancePtr->ADC_Tile[Tile_Id].NumOfADCBlocks = 0U; + for (Block_Id = XRFDC_BLK_ID0; Block_Id < XRFDC_BLK_ID4; Block_Id++) { + if (XRFdc_IsADCBlockEnabled(InstancePtr, Tile_Id, Block_Id) != 0U) { + InstancePtr->ADC_Tile[Tile_Id].NumOfADCBlocks += 1U; + InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Analog_Datapath[Block_Id]. + AnalogPathEnabled = XRFDC_ANALOGPATH_ENABLE; + } + /* Initialize Data Type */ + if (InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id]. + ADCBlock_Analog_Config[Block_Id].MixMode == XRFDC_MIXER_MODE_BYPASS) { + InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[Block_Id].MixerInputDataType = + InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id].ADCBlock_Digital_Config[Block_Id].MixerInputDataType; + } else { + InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[Block_Id].MixerInputDataType = + InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id]. + ADCBlock_Analog_Config[Block_Id].MixMode; + } + /* Initialize MixerType */ + MixerType = InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id]. + ADCBlock_Digital_Config[Block_Id].MixerType; + InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Block_Id].Mixer_Settings.MixerType = MixerType; + + InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Block_Id].ConnectedIData = -1; + InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Block_Id].ConnectedQData = -1; + InstancePtr->ADC_Tile[Tile_Id].MultibandConfig = + InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id].MultibandConfig; + if (XRFdc_IsADCDigitalPathEnabled(InstancePtr, Tile_Id, Block_Id) != 0U) { + InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[Block_Id].DigitalPathAvailable = + XRFDC_DIGITALPATH_ENABLE; + InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[Block_Id].DigitalPathEnabled = + XRFDC_DIGITALPATH_ENABLE; + /* Initialize ConnectedI/QData, MB Config */ + XRFdc_ADCMBConfigInit(InstancePtr, Tile_Id, Block_Id); + } + } + + /* Initialize PLL Structure */ + XRFdc_UpdatePLLStruct(InstancePtr, XRFDC_ADC_TILE, Tile_Id); + } +} + +/*****************************************************************************/ +/** +* +* Initialize DAC Tiles. +* +* +* @param InstancePtr is a pointer to the XRfdc instance. +* +* @return +* - None. +* +* @note Static API used to initialize DAC Tiles +* +******************************************************************************/ +static void XRFdc_DACInitialize(XRFdc *InstancePtr) +{ + u32 Tile_Id; + u32 Block_Id; + u8 MixerType; + + for (Tile_Id = XRFDC_TILE_ID0; Tile_Id < XRFDC_TILE_ID4; Tile_Id++) { + InstancePtr->DAC_Tile[Tile_Id].NumOfDACBlocks = 0U; + for (Block_Id = XRFDC_BLK_ID0; Block_Id < XRFDC_BLK_ID4; Block_Id++) { + if (XRFdc_IsDACBlockEnabled(InstancePtr, Tile_Id, Block_Id) != 0U) { + InstancePtr->DAC_Tile[Tile_Id].NumOfDACBlocks += 1U; + InstancePtr->DAC_Tile[Tile_Id].DACBlock_Analog_Datapath[Block_Id].AnalogPathEnabled = + XRFDC_ANALOGPATH_ENABLE; + } + /* Initialize Data Type */ + if (InstancePtr->RFdc_Config.DACTile_Config[Tile_Id]. + DACBlock_Analog_Config[Block_Id].MixMode == XRFDC_MIXER_MODE_BYPASS) { + InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[Block_Id].MixerInputDataType = + InstancePtr->RFdc_Config.DACTile_Config[Tile_Id].DACBlock_Digital_Config[Block_Id].MixerInputDataType; + } else { + InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[Block_Id].MixerInputDataType = + XRFDC_DATA_TYPE_IQ; + } + /* Initialize MixerType */ + MixerType = InstancePtr->RFdc_Config.DACTile_Config[Tile_Id]. + DACBlock_Digital_Config[Block_Id].MixerType; + InstancePtr->DAC_Tile[Tile_Id]. + DACBlock_Digital_Datapath[Block_Id].Mixer_Settings.MixerType = MixerType; + + InstancePtr->DAC_Tile[Tile_Id]. + DACBlock_Digital_Datapath[Block_Id].ConnectedIData = -1; + InstancePtr->DAC_Tile[Tile_Id]. + DACBlock_Digital_Datapath[Block_Id].ConnectedQData = -1; + InstancePtr->DAC_Tile[Tile_Id].MultibandConfig = + InstancePtr->RFdc_Config.DACTile_Config[Tile_Id].MultibandConfig; + if (XRFdc_IsDACDigitalPathEnabled(InstancePtr, Tile_Id, Block_Id) != 0U) { + InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[Block_Id].DigitalPathAvailable = + XRFDC_DIGITALPATH_ENABLE; + InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[Block_Id].DigitalPathEnabled = + XRFDC_DIGITALPATH_ENABLE; + /* Initialize ConnectedI/QData, MB Config */ + XRFdc_DACMBConfigInit(InstancePtr, Tile_Id, Block_Id); + } + } + /* Initialize PLL Structure */ + XRFdc_UpdatePLLStruct(InstancePtr, XRFDC_DAC_TILE, Tile_Id); + } +} + +/*****************************************************************************/ +/** +* +* Initialize Multiband Configuration for DAC Tiles. +* +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3, and -1. +* @param Block_Id is DAC block number inside the tile. Valid values +* are 0-3. +* +* @return +* - None. +* +* @note Static API used to initialize DAC MB Config +* +******************************************************************************/ +static void XRFdc_DACMBConfigInit(XRFdc *InstancePtr, u32 Tile_Id, + u32 Block_Id) +{ + if (InstancePtr->RFdc_Config.DACTile_Config[Tile_Id]. + DACBlock_Analog_Config[Block_Id].MixMode == XRFDC_MIXER_MODE_C2C) { + /* Mixer Mode is C2C */ + switch (InstancePtr->DAC_Tile[Tile_Id].MultibandConfig) { + case XRFDC_MB_MODE_4X: + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID0, XRFDC_BLK_ID1); + break; + case XRFDC_MB_MODE_2X_BLK01_BLK23: + case XRFDC_MB_MODE_2X_BLK01: + case XRFDC_MB_MODE_2X_BLK23: + if ((Block_Id == XRFDC_BLK_ID0) || (Block_Id == XRFDC_BLK_ID1)) { + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID0, XRFDC_BLK_ID1); + } else { + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID2, XRFDC_BLK_ID3); + } + break; + default: + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id, Block_Id, Block_Id + 1U); + break; + } + } else if (InstancePtr->RFdc_Config.DACTile_Config[Tile_Id]. + DACBlock_Analog_Config[Block_Id].MixMode == 0x0) { + /* Mixer Mode is C2R */ + switch (InstancePtr->DAC_Tile[Tile_Id].MultibandConfig) { + case XRFDC_MB_MODE_4X: + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID0, -1); + break; + case XRFDC_MB_MODE_2X_BLK01_BLK23: + case XRFDC_MB_MODE_2X_BLK01: + case XRFDC_MB_MODE_2X_BLK23: + if ((Block_Id == XRFDC_BLK_ID0) || (Block_Id == XRFDC_BLK_ID1)) { + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID0, -1); + } else { + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID2, -1); + } + break; + default: + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id, Block_Id, -1); + break; + } + } else { + /* Mixer Mode is BYPASS */ + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id, Block_Id, -1); + } +} +/*****************************************************************************/ +/** +* +* Initialize Multiband Configuration for ADC Tiles. +* +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3, and -1. +* @param Block_Id is ADC block number inside the tile. Valid values +* are 0-3. +* +* @return +* - None. +* +* @note Static API used to initialize ADC MB Config +* +******************************************************************************/ +static void XRFdc_ADCMBConfigInit(XRFdc *InstancePtr, u32 Tile_Id, + u32 Block_Id) +{ + if (InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id]. + ADCBlock_Analog_Config[Block_Id].MixMode == XRFDC_MIXER_MODE_C2C) { + /* Mixer mode is C2C */ + switch (InstancePtr->ADC_Tile[Tile_Id].MultibandConfig) { + case XRFDC_MB_MODE_4X: + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID0, XRFDC_BLK_ID1); + break; + case XRFDC_MB_MODE_2X_BLK01_BLK23: + case XRFDC_MB_MODE_2X_BLK01: + case XRFDC_MB_MODE_2X_BLK23: + if ((Block_Id == XRFDC_BLK_ID0) || (Block_Id == XRFDC_BLK_ID1)) { + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID0, XRFDC_BLK_ID1); + } else { + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID2, XRFDC_BLK_ID3); + } + break; + default: + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id, Block_Id, Block_Id + 1U); + break; + } + } else if (InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id]. + ADCBlock_Analog_Config[Block_Id].MixMode == 0x0) { + /* Mixer mode is R2C */ + switch (InstancePtr->ADC_Tile[Tile_Id].MultibandConfig) { + case XRFDC_MB_MODE_4X: + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID0, -1); + break; + case XRFDC_MB_MODE_2X_BLK01_BLK23: + case XRFDC_MB_MODE_2X_BLK01: + case XRFDC_MB_MODE_2X_BLK23: + if ((Block_Id == XRFDC_BLK_ID0) || (Block_Id == XRFDC_BLK_ID1)) { + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID0, -1); + } else { + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id, XRFDC_BLK_ID2, -1); + } + break; + default: + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id, Block_Id, -1); + break; + } + } else { + /* Mixer mode is BYPASS */ + XRFdc_SetConnectedIQData(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id, Block_Id, -1); + } +} + +/*****************************************************************************/ +/** +* +* This API updates PLL Structure. +* +* +* @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. +* +* @return +* - None. +* +* @note Static API used to initialize PLL Settings for ADC and DAC +* +******************************************************************************/ +static void XRFdc_UpdatePLLStruct(XRFdc *InstancePtr, u32 Type, u32 Tile_Id) +{ + if (Type == XRFDC_ADC_TILE) { + InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.SampleRate = + InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id].SamplingRate; + InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.RefClkFreq = + InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id].RefClkFreq; + InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.Enabled = + InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id].PLLEnable; + InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.FeedbackDivider = + InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id].FeedbackDiv; + InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.OutputDivider = + InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id].OutputDiv; + InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.RefClkDivider = + InstancePtr->RFdc_Config.ADCTile_Config[Tile_Id].RefClkDiv; + } else { + InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.SampleRate = + InstancePtr->RFdc_Config.DACTile_Config[Tile_Id].SamplingRate; + InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.RefClkFreq = + InstancePtr->RFdc_Config.DACTile_Config[Tile_Id].RefClkFreq; + InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.Enabled = + InstancePtr->RFdc_Config.DACTile_Config[Tile_Id].PLLEnable; + InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.FeedbackDivider = + InstancePtr->RFdc_Config.DACTile_Config[Tile_Id].FeedbackDiv; + InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.OutputDivider = + InstancePtr->RFdc_Config.DACTile_Config[Tile_Id].OutputDiv; + InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.RefClkDivider = + InstancePtr->RFdc_Config.DACTile_Config[Tile_Id].RefClkDiv; + } +} + +/*****************************************************************************/ +/** +* +* The API Restarts the requested tile. It can restart a single tile and +* alternatively can restart all the tiles. Existing register settings are not +* lost or altered in the process. It just starts the requested tile(s). +* +* @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. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if tile is not enabled or available +* +* @note None +* +******************************************************************************/ +u32 XRFdc_StartUp(XRFdc *InstancePtr, u32 Type, int Tile_Id) +{ + u32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_RestartIPSM(InstancePtr, Type, Tile_Id, XRFDC_SM_STATE1, + XRFDC_SM_STATE15); + return Status; + +} + +/*****************************************************************************/ +/** +* +* The API stops the tile as requested. It can also stop all the tiles if +* asked for. It does not clear any of the existing register settings. It just +* stops the requested tile(s). +* +* @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. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if tile is not enabled or available +* +* @note None +* +******************************************************************************/ +u32 XRFdc_Shutdown(XRFdc *InstancePtr, u32 Type, int Tile_Id) +{ + u32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_RestartIPSM(InstancePtr, Type, Tile_Id, XRFDC_SM_STATE1, + XRFDC_SM_STATE1); + return Status; + +} + +/*****************************************************************************/ +/** +* +* The API resets the requested tile. It can reset all the tiles as well. In +* the process, all existing register settings are cleared and are replaced +* with the settings initially configured (through the GUI). +* +* +* @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. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if tile is not enabled or available +* +* @note None +******************************************************************************/ +u32 XRFdc_Reset(XRFdc *InstancePtr, u32 Type, int Tile_Id) +{ + u32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_RestartIPSM(InstancePtr, Type, Tile_Id, XRFDC_SM_STATE0, + XRFDC_SM_STATE15); + return Status; + +} + +/*****************************************************************************/ +/** +* +* This Static API will be used to wait for restart bit clears and also check +* for PLL Lock if clock source is internal PLL. +* +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param End is end state of State Machine. +* +* @return - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if timeout occurs. +* +* @note None +* +******************************************************************************/ +static u32 XRFdc_WaitForRestartClr(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 BaseAddr, u32 End) +{ + u32 ClkSrc = 0U; + u32 DelayCount; + u32 LockStatus = 0U; + u32 Status; + + /* + * Get Tile clock source information + */ + if (XRFdc_GetClockSource(InstancePtr, Type, Tile_Id, &ClkSrc) + != XRFDC_SUCCESS) { + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + if ((ClkSrc == XRFDC_INTERNAL_PLL_CLK) && (End == XRFDC_SM_STATE15)) { + /* + * Wait for internal PLL to lock + */ + if (XRFdc_GetPLLLockStatus(InstancePtr, Type, Tile_Id, + &LockStatus) != XRFDC_SUCCESS) { + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + DelayCount = 0U; + while (LockStatus != XRFDC_PLL_LOCKED) { + if (DelayCount == XRFDC_PLL_LOCK_DLY_CNT) { + metal_log(METAL_LOG_ERROR, "\n PLL Lock timeout " + "error in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } else { + /* Wait for 1 msec */ +#ifdef __BAREMETAL__ + usleep(1000); +#else + metal_sleep_usec(1000); +#endif + DelayCount++; + (void)XRFdc_GetPLLLockStatus(InstancePtr, Type, Tile_Id, + &LockStatus); + } + } + } + + /* Wait till restart bit clear */ + DelayCount = 0U; + while (XRFdc_ReadReg16(InstancePtr, BaseAddr, XRFDC_RESTART_OFFSET) != 0U) { + if (DelayCount == XRFDC_PLL_LOCK_DLY_CNT) { + metal_log(METAL_LOG_ERROR, "\n Failed to clear " + "the restart bit in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } else { + /* Wait for 1 msec */ +#ifdef __BAREMETAL__ + usleep(1000); +#else + metal_sleep_usec(1000); +#endif + DelayCount++; + } + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} +/*****************************************************************************/ +/** +* +* Restarts a requested the tile and ensures that starts from a defined start +* state and reaches the requested or defined end state. +* +* +* @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 Start is start state of State Machine +* @param End is end state of State Machine. +* +* @return - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if tile is not enabled or available +* +* @note None +* +******************************************************************************/ +static u32 XRFdc_RestartIPSM(XRFdc *InstancePtr, u32 Type, int Tile_Id, + u32 Start, u32 End) +{ + u32 Status; + u32 BaseAddr; + u16 NoOfTiles; + u16 Index; + + /* An input tile if of -1 selects all tiles */ + if (Tile_Id == XRFDC_SELECT_ALL_TILES) { + NoOfTiles = XRFDC_NUM_OF_TILES4; + Index = XRFDC_TILE_ID0; + } else { + NoOfTiles = Tile_Id + 1; + Index = Tile_Id; + } + + for (; Index < NoOfTiles; Index++) { + BaseAddr = XRFDC_CTRL_STS_BASE(Type, Index); + Status = XRFdc_CheckTileEnabled(InstancePtr, Type, Index); + if ((Status != XRFDC_SUCCESS) && (Tile_Id != XRFDC_SELECT_ALL_TILES)) { + metal_log(METAL_LOG_ERROR, "\n Requested tile%d not " + "available in %s\r\n", Index, __func__); + goto RETURN_PATH; + } else if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_DEBUG, "\n Tile%d not " + "available in %s\r\n", Index, __func__); + continue; + } else { + /* Write Start and End states */ + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_RESTART_STATE_OFFSET, + XRFDC_PWR_STATE_MASK, (Start << XRFDC_RSR_START_SHIFT) | End); + + /* Trigger restart */ + XRFdc_WriteReg(InstancePtr, BaseAddr, XRFDC_RESTART_OFFSET, + XRFDC_RESTART_MASK); + + /* Wait for restart bit clear */ + Status = XRFdc_WaitForRestartClr(InstancePtr, Type, Index, + BaseAddr, End); + if (Status != XRFDC_SUCCESS) { + goto RETURN_PATH; + } + } + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* The API returns the IP status. +* +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param IPStatusPtr Pointer to the XRFdc_IPStatus structure through +* which the status is returned. +* +* @return +* - XRFDC_SUCCESS if successful. +* +* @note None. +* +******************************************************************************/ +u32 XRFdc_GetIPStatus(XRFdc *InstancePtr, XRFdc_IPStatus *IPStatusPtr) +{ + u32 Tile_Id; + u32 Block_Id; + u32 BaseAddr; + u16 ReadReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(IPStatusPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + for (Tile_Id = XRFDC_TILE_ID0; Tile_Id < XRFDC_TILE_ID4; Tile_Id++) { + IPStatusPtr->ADCTileStatus[Tile_Id].BlockStatusMask = 0x0; + IPStatusPtr->DACTileStatus[Tile_Id].BlockStatusMask = 0x0; + for (Block_Id = XRFDC_BLK_ID0; Block_Id < XRFDC_BLK_ID4; Block_Id++) { + if (XRFdc_IsADCBlockEnabled(InstancePtr, Tile_Id, + Block_Id) != 0U) { + IPStatusPtr->ADCTileStatus[Tile_Id].IsEnabled = 1; + IPStatusPtr->ADCTileStatus[Tile_Id].BlockStatusMask |= + (1U << Block_Id); + BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id); + ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_STATUS_OFFSET); + IPStatusPtr->ADCTileStatus[Tile_Id].PowerUpState = (ReadReg & + XRFDC_PWR_UP_STAT_MASK) >> XRFDC_PWR_UP_STAT_SHIFT; + IPStatusPtr->ADCTileStatus[Tile_Id].PLLState = (ReadReg & + XRFDC_PLL_LOCKED_MASK) >> XRFDC_PLL_LOCKED_SHIFT; + IPStatusPtr->ADCTileStatus[Tile_Id].TileState = + XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_CURRENT_STATE_OFFSET); + } + if (XRFdc_IsDACBlockEnabled(InstancePtr, Tile_Id, + Block_Id) != 0U) { + IPStatusPtr->DACTileStatus[Tile_Id].IsEnabled = 1; + IPStatusPtr->DACTileStatus[Tile_Id].BlockStatusMask |= + (1U << Block_Id); + BaseAddr = XRFDC_DAC_TILE_CTRL_STATS_ADDR(Tile_Id); + IPStatusPtr->DACTileStatus[Tile_Id].TileState = + XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_CURRENT_STATE_OFFSET); + ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_STATUS_OFFSET); + IPStatusPtr->DACTileStatus[Tile_Id].PowerUpState = (ReadReg & + XRFDC_PWR_UP_STAT_MASK) >> XRFDC_PWR_UP_STAT_SHIFT; + IPStatusPtr->DACTileStatus[Tile_Id].PLLState = (ReadReg & + XRFDC_PLL_LOCKED_MASK) >> XRFDC_PLL_LOCKED_SHIFT; + } + } + } + + /*TODO IP state*/ + + return XRFDC_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* The API returns the requested block status. +* +* +* @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. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. XRFdc_BlockStatus. +* @param BlockStatusPtr is Pointer to the XRFdc_BlockStatus structure through +* which the ADC/DAC block status is returned. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Common API for ADC/DAC blocks. +* +******************************************************************************/ +u32 XRFdc_GetBlockStatus(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 Block_Id, XRFdc_BlockStatus *BlockStatusPtr) +{ + u32 Status; + u32 Block; + u16 ReadReg; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BlockStatusPtr != 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; + } + + Block = Block_Id; + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Block_Id == XRFDC_BLK_ID1) && (Type == XRFDC_ADC_TILE)) { + Block_Id = XRFDC_BLK_ID2; + } + + BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Block_Id); + if (Type == XRFDC_ADC_TILE) { + Status = XRFdc_GetADCBlockStatus(InstancePtr, BaseAddr, Tile_Id, + Block, BlockStatusPtr); + } else { + Status = XRFdc_GetDACBlockStatus(InstancePtr, BaseAddr, Tile_Id, + Block, BlockStatusPtr); + } + if (Status != XRFDC_SUCCESS) { + goto RETURN_PATH; + } + + ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CLK_EN_OFFSET, + XRFDC_DAT_CLK_EN_MASK); + if (ReadReg == XRFDC_DAT_CLK_EN_MASK) { + BlockStatusPtr->DataPathClocksStatus = 0x1U; + } else { + BlockStatusPtr->DataPathClocksStatus = 0x0U; + } + + Status = XRFDC_SUCCESS; + +RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* +* The API returns the requested block status for ADC block +* +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. XRFdc_BlockStatus. +* @param BlockStatus is Pointer to the XRFdc_BlockStatus structure through +* which the ADC/DAC block status is returned. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Static API for ADC blocks. +* +******************************************************************************/ +static u32 XRFdc_GetADCBlockStatus(XRFdc *InstancePtr, u32 BaseAddr, + u32 Tile_Id, u32 Block_Id, XRFdc_BlockStatus *BlockStatusPtr) +{ + u8 FIFOEnable = 0U; + u32 DecimationFactor = 0U; + u8 MixerMode; + u16 ReadReg; + u32 Status; + + BlockStatusPtr->SamplingFreq = InstancePtr->ADC_Tile[Tile_Id]. + PLL_Settings.SampleRate; + + /* DigitalDataPathStatus */ + (void)XRFdc_GetFIFOStatus(InstancePtr, XRFDC_ADC_TILE, + Tile_Id, &FIFOEnable); + BlockStatusPtr->DigitalDataPathStatus = FIFOEnable; + (void)XRFdc_GetDecimationFactor(InstancePtr, Tile_Id, + Block_Id, &DecimationFactor); + BlockStatusPtr->DigitalDataPathStatus |= + (DecimationFactor << XRFDC_DIGI_ANALOG_SHIFT4); + + ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET, + (XRFDC_EN_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK)); + switch (ReadReg) { + case XRFDC_MIXER_MODE_C2C_MASK: + MixerMode = XRFDC_MIXER_MODE_C2C; + break; + case XRFDC_MIXER_MODE_R2C_MASK: + MixerMode = XRFDC_MIXER_MODE_R2C; + break; + case XRFDC_MIXER_MODE_OFF_MASK: + MixerMode = XRFDC_MIXER_MODE_OFF; + break; + default: + metal_log(METAL_LOG_ERROR, "\n Invalid MixerMode " + "for ADC in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + BlockStatusPtr->DigitalDataPathStatus |= + (MixerMode << XRFDC_DIGI_ANALOG_SHIFT8); + + /* + * Checking ADC block enable for ADC AnalogPath. + * This can be changed later, + */ + BlockStatusPtr->AnalogDataPathStatus = + XRFdc_IsADCBlockEnabled(InstancePtr, Tile_Id, Block_Id); + BlockStatusPtr->IsFIFOFlagsEnabled = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_FABRIC_IMR_OFFSET, XRFDC_FAB_IMR_USRDAT_MASK); + BlockStatusPtr->IsFIFOFlagsAsserted = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_FABRIC_ISR_OFFSET, XRFDC_FAB_ISR_USRDAT_MASK); + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* The API returns the requested block status for DAC block +* +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. XRFdc_BlockStatus. +* @param BlockStatus is Pointer to the XRFdc_BlockStatus structure through +* which the DAC block status is returned. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Static API for DAC blocks. +* +******************************************************************************/ +static u32 XRFdc_GetDACBlockStatus(XRFdc *InstancePtr, u32 BaseAddr, + u32 Tile_Id, u32 Block_Id, XRFdc_BlockStatus *BlockStatusPtr) +{ + u32 InterpolationFactor = 0U; + u32 DecoderMode = 0U; + u8 MixerMode; + u16 ReadReg; + u32 Status; + u8 FIFOEnable = 0U; + + BlockStatusPtr->SamplingFreq = InstancePtr->DAC_Tile[Tile_Id]. + PLL_Settings.SampleRate; + + /* DigitalDataPathStatus */ + (void)XRFdc_GetFIFOStatus(InstancePtr, XRFDC_DAC_TILE, + Tile_Id, &FIFOEnable); + BlockStatusPtr->DigitalDataPathStatus = FIFOEnable; + (void)XRFdc_GetInterpolationFactor(InstancePtr, Tile_Id, + Block_Id, &InterpolationFactor); + BlockStatusPtr->DigitalDataPathStatus |= + (InterpolationFactor << XRFDC_DIGI_ANALOG_SHIFT4); + /* Adder Enable */ + ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_DAC_MB_CFG_OFFSET, XRFDC_EN_MB_MASK); + ReadReg = ReadReg >> XRFDC_EN_MB_SHIFT; + BlockStatusPtr->DigitalDataPathStatus |= + (ReadReg << XRFDC_DIGI_ANALOG_SHIFT8); + ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET, + (XRFDC_EN_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK)); + switch (ReadReg) { + case XRFDC_MIXER_MODE_C2C_MASK: + MixerMode = XRFDC_MIXER_MODE_C2C; + break; + case XRFDC_MIXER_MODE_C2R_MASK: + MixerMode = XRFDC_MIXER_MODE_C2R; + break; + case XRFDC_MIXER_MODE_OFF_MASK: + MixerMode = XRFDC_MIXER_MODE_OFF; + break; + default: + metal_log(METAL_LOG_ERROR, "\n Invalid MixerMode " + "for ADC in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + BlockStatusPtr->DigitalDataPathStatus |= + (MixerMode << XRFDC_DIGI_ANALOG_SHIFT12); + + /* AnalogDataPathStatus */ + BlockStatusPtr->AnalogDataPathStatus = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_DAC_INVSINC_OFFSET, (InstancePtr->RFdc_Config.IPType < 2)?XRFDC_EN_INVSINC_MASK:XRFDC_MODE_INVSINC_MASK); + (void)XRFdc_GetDecoderMode(InstancePtr, Tile_Id, Block_Id, + &DecoderMode); + BlockStatusPtr->AnalogDataPathStatus |= + (DecoderMode << XRFDC_DIGI_ANALOG_SHIFT4); + + /* FIFO Flags status */ + BlockStatusPtr->IsFIFOFlagsEnabled = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_DAC_FABRIC_IMR_OFFSET, XRFDC_FAB_IMR_USRDAT_MASK); + BlockStatusPtr->IsFIFOFlagsAsserted = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_DAC_FABRIC_ISR_OFFSET, XRFDC_FAB_ISR_USRDAT_MASK); + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* This API is used to update various QMC settings, eg gain, phase, offset etc. +* QMC settings passed are used to update the corresponding +* block level registers. Driver structure is updated with the new values. +* +* @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. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param QMCSettingsPtr is Pointer to the XRFdc_QMC_Settings structure +* in which the QMC settings are passed. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note None +* +******************************************************************************/ +u32 XRFdc_SetQMCSettings(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 Block_Id, XRFdc_QMC_Settings *QMCSettingsPtr) +{ + u32 Status; + XRFdc_QMC_Settings *QMCConfigPtr; + u32 BaseAddr; + s32 PhaseCorrectionFactor; + u32 GainCorrectionFactor; + u32 Index; + u32 NoOfBlocks; + u32 Offset; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(QMCSettingsPtr != 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; + } + if (InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[Index]. + MixerInputDataType == XRFDC_DATA_TYPE_IQ) { + Index = Block_Id; + NoOfBlocks = XRFDC_NUM_OF_BLKS3; + if (Block_Id == XRFDC_BLK_ID1) { + NoOfBlocks = XRFDC_NUM_OF_BLKS4; + } + } + } else { + NoOfBlocks = Block_Id + 1U; + } + + for (; Index < NoOfBlocks;) { + if (Type == XRFDC_ADC_TILE) { + /* ADC */ + QMCConfigPtr = &InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Analog_Datapath[Index].QMC_Settings; + } else { + QMCConfigPtr = &InstancePtr->DAC_Tile[Tile_Id]. + DACBlock_Analog_Datapath[Index].QMC_Settings; + } + + BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Index); + + if ((QMCSettingsPtr->EnableGain != 0U) && + (QMCSettingsPtr->EnableGain != 1U)) { + metal_log(METAL_LOG_ERROR, "\n Invalid QMC gain option " + "in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + if ((QMCSettingsPtr->EnablePhase != 0U) && + (QMCSettingsPtr->EnablePhase != 1U)) { + metal_log(METAL_LOG_ERROR, "\n Invalid QMC phase option " + "in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + if ((QMCSettingsPtr->PhaseCorrectionFactor <= XRFDC_MIN_PHASE_CORR_FACTOR) || + (QMCSettingsPtr->PhaseCorrectionFactor >= XRFDC_MAX_PHASE_CORR_FACTOR)) { + metal_log(METAL_LOG_ERROR, "\n Invalid QMC Phase Correction " + "factor in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + if ((QMCSettingsPtr->GainCorrectionFactor < XRFDC_MIN_GAIN_CORR_FACTOR) || + (QMCSettingsPtr->GainCorrectionFactor >= XRFDC_MAX_GAIN_CORR_FACTOR)) { + metal_log(METAL_LOG_ERROR, "\n Invalid QMC Gain Correction " + "factor in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + if ((QMCSettingsPtr->EventSource > XRFDC_EVNT_SRC_PL) || + ((QMCSettingsPtr->EventSource == XRFDC_EVNT_SRC_MARKER) && + (Type == XRFDC_ADC_TILE))) { + metal_log(METAL_LOG_ERROR, "\n Invalid event source selection " + "in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Type == XRFDC_ADC_TILE) && + ((QMCSettingsPtr->EventSource == XRFDC_EVNT_SRC_SLICE) || + (QMCSettingsPtr->EventSource == + XRFDC_EVNT_SRC_IMMEDIATE))) { + metal_log(METAL_LOG_ERROR, "\n Invalid Event Source, " + "event source is not supported in 4GSPS ADC %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_QMC_CFG_OFFSET, + XRFDC_QMC_CFG_EN_GAIN_MASK, QMCSettingsPtr->EnableGain); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_QMC_CFG_OFFSET, + XRFDC_QMC_CFG_EN_PHASE_MASK, + (QMCSettingsPtr->EnablePhase << XRFDC_QMC_CFG_PHASE_SHIFT)); + + /* Phase Correction factor is applicable to ADC/DAC IQ mode only */ + if (((Type == XRFDC_ADC_TILE) && + (InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[Index]. + MixerInputDataType == XRFDC_DATA_TYPE_IQ)) || + ((Type == XRFDC_DAC_TILE) && + (InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[Index]. + MixerInputDataType == XRFDC_DATA_TYPE_IQ))) { + PhaseCorrectionFactor = + ((QMCSettingsPtr->PhaseCorrectionFactor / XRFDC_MAX_PHASE_CORR_FACTOR) * + XRFDC_QMC_PHASE_MULT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_QMC_PHASE_OFFSET, + XRFDC_QMC_PHASE_CRCTN_MASK, PhaseCorrectionFactor); + } + + /* Gain Correction factor */ + GainCorrectionFactor = ((QMCSettingsPtr->GainCorrectionFactor * + XRFDC_QMC_GAIN_MULT) / XRFDC_MAX_GAIN_CORR_FACTOR); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_QMC_GAIN_OFFSET, + XRFDC_QMC_GAIN_CRCTN_MASK, GainCorrectionFactor); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_QMC_OFF_OFFSET, + XRFDC_QMC_OFFST_CRCTN_MASK, QMCSettingsPtr->OffsetCorrectionFactor); + + /* Event Source */ + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_QMC_UPDT_OFFSET, + XRFDC_QMC_UPDT_MODE_MASK, QMCSettingsPtr->EventSource); + + if (QMCSettingsPtr->EventSource == XRFDC_EVNT_SRC_IMMEDIATE) { + if (Type == XRFDC_ADC_TILE) { + Offset = XRFDC_ADC_UPDATE_DYN_OFFSET; + } else { + Offset = XRFDC_DAC_UPDATE_DYN_OFFSET; + } + XRFdc_ClrSetReg(InstancePtr, BaseAddr, Offset, + XRFDC_UPDT_EVNT_MASK, XRFDC_UPDT_EVNT_QMC_MASK); + } + /* Update the instance with new values */ + QMCConfigPtr->EventSource = QMCSettingsPtr->EventSource; + QMCConfigPtr->PhaseCorrectionFactor = + QMCSettingsPtr->PhaseCorrectionFactor; + QMCConfigPtr->GainCorrectionFactor = + QMCSettingsPtr->GainCorrectionFactor; + QMCConfigPtr->OffsetCorrectionFactor = + QMCSettingsPtr->OffsetCorrectionFactor; + QMCConfigPtr->EnablePhase = QMCSettingsPtr->EnablePhase; + QMCConfigPtr->EnableGain = QMCSettingsPtr->EnableGain; + if ((Type == XRFDC_ADC_TILE) && + (InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Index].MixerInputDataType == + XRFDC_DATA_TYPE_IQ) && (XRFdc_IsHighSpeedADC(InstancePtr, + Tile_Id) == 1)) { + Index += XRFDC_BLK_ID2; + } else { + Index += XRFDC_BLK_ID1; + } + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* QMC settings are returned back to the caller through this API. +* +* @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. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param QMCSettingsPtr Pointer to the XRFdc_QMC_Settings structure +* in which the QMC settings are passed. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note None +* +******************************************************************************/ +u32 XRFdc_GetQMCSettings(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 Block_Id, XRFdc_QMC_Settings *QMCSettingsPtr) +{ + u32 Status; + u32 BaseAddr; + s32 PhaseCorrectionFactor; + u32 GainCorrectionFactor; + s32 OffsetCorrectionFactor; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(QMCSettingsPtr != 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; + } + + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Block_Id == XRFDC_BLK_ID1) && (Type == XRFDC_ADC_TILE) && + (InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Block_Id].MixerInputDataType != + XRFDC_DATA_TYPE_IQ)) { + Block_Id = XRFDC_BLK_ID2; + } + + BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Block_Id); + + QMCSettingsPtr->EnableGain = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_QMC_CFG_OFFSET, XRFDC_QMC_CFG_EN_GAIN_MASK); + QMCSettingsPtr->EnablePhase = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_QMC_CFG_OFFSET, XRFDC_QMC_CFG_EN_PHASE_MASK) >> + XRFDC_QMC_CFG_PHASE_SHIFT; + + /* Phase Correction factor */ + if (((Type == XRFDC_ADC_TILE) && + (InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[Block_Id]. + MixerInputDataType == XRFDC_DATA_TYPE_IQ)) || + ((Type == XRFDC_DAC_TILE) && + (InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[Block_Id]. + MixerInputDataType == XRFDC_DATA_TYPE_IQ))) { + PhaseCorrectionFactor = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_QMC_PHASE_OFFSET, XRFDC_QMC_PHASE_CRCTN_MASK); + PhaseCorrectionFactor = (PhaseCorrectionFactor >> + 11) == 0 ? PhaseCorrectionFactor : + ((-1 ^ 0xFFF) | PhaseCorrectionFactor); + QMCSettingsPtr->PhaseCorrectionFactor = + ((PhaseCorrectionFactor * XRFDC_MAX_PHASE_CORR_FACTOR) / + XRFDC_QMC_PHASE_MULT); + } else { + QMCSettingsPtr->PhaseCorrectionFactor = 0U; + } + + /* Gain Correction factor */ + GainCorrectionFactor = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_QMC_GAIN_OFFSET, XRFDC_QMC_GAIN_CRCTN_MASK); + QMCSettingsPtr->GainCorrectionFactor = ((GainCorrectionFactor * + XRFDC_MAX_GAIN_CORR_FACTOR) / XRFDC_QMC_GAIN_MULT); + OffsetCorrectionFactor = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_QMC_OFF_OFFSET, XRFDC_QMC_OFFST_CRCTN_MASK); + QMCSettingsPtr->OffsetCorrectionFactor = + (OffsetCorrectionFactor >> 11) == 0 ? OffsetCorrectionFactor : + ((-1 ^ 0xFFF) | OffsetCorrectionFactor); + + /* Event Source */ + QMCSettingsPtr->EventSource = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_QMC_UPDT_OFFSET, XRFDC_QMC_UPDT_MODE_MASK); + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Coarse delay settings passed are used to update the corresponding +* block level registers. Driver structure is updated with the new values. +* +* @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. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param CoarseDelaySettingsPtr is Pointer to the XRFdc_CoarseDelay_Settings +* structure in which the CoarseDelay settings are passed. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note None +* +******************************************************************************/ +u32 XRFdc_SetCoarseDelaySettings(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 Block_Id, XRFdc_CoarseDelay_Settings *CoarseDelaySettingsPtr) +{ + u32 Status; + u32 BaseAddr; + u32 Index; + u32 NoOfBlocks; + u16 Mask; + u16 MaxDelay; + XRFdc_CoarseDelay_Settings *CoarseDelayConfigPtr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CoarseDelaySettingsPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Mask = (InstancePtr->RFdc_Config.IPType < 2)?XRFDC_CRSE_DLY_CFG_MASK:XRFDC_CRSE_DLY_CFG_MASK_EXT; + MaxDelay = (InstancePtr->RFdc_Config.IPType < 2)?XRFDC_CRSE_DLY_MAX:XRFDC_CRSE_DLY_MAX_EXT; + 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) { + CoarseDelayConfigPtr = &InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Analog_Datapath[Index]. + CoarseDelay_Settings; + } else { + CoarseDelayConfigPtr = &InstancePtr->DAC_Tile[Tile_Id]. + DACBlock_Analog_Datapath[Index]. + CoarseDelay_Settings; + } + + BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Index); + + if (CoarseDelaySettingsPtr->CoarseDelay > MaxDelay) { + metal_log(METAL_LOG_ERROR, "\n Requested coarse " + "delay not valid in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + if ((CoarseDelaySettingsPtr->EventSource > XRFDC_EVNT_SRC_PL) || + ((CoarseDelaySettingsPtr->EventSource == XRFDC_EVNT_SRC_MARKER) && + (Type == XRFDC_ADC_TILE))) { + metal_log(METAL_LOG_ERROR, "\n Invalid event " + "source selection in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Type == XRFDC_ADC_TILE) && + ((CoarseDelaySettingsPtr->EventSource == + XRFDC_EVNT_SRC_SLICE) || + (CoarseDelaySettingsPtr->EventSource == + XRFDC_EVNT_SRC_IMMEDIATE))) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, "\n Invalid Event " + "Source, event source is not supported in " + "4GSPS ADC %s\r\n", __func__); + goto RETURN_PATH; + } + if (Type == XRFDC_ADC_TILE) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_CRSE_DLY_CFG_OFFSET, Mask, CoarseDelaySettingsPtr->CoarseDelay); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_ADC_CRSE_DLY_UPDT_OFFSET, XRFDC_QMC_UPDT_MODE_MASK, + CoarseDelaySettingsPtr->EventSource); + if (CoarseDelaySettingsPtr->EventSource == + XRFDC_EVNT_SRC_IMMEDIATE) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_ADC_UPDATE_DYN_OFFSET, XRFDC_UPDT_EVNT_MASK, + XRFDC_ADC_UPDT_CRSE_DLY_MASK); + } + } else { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_DAC_CRSE_DLY_CFG_OFFSET, Mask, + CoarseDelaySettingsPtr->CoarseDelay); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_DAC_CRSE_DLY_UPDT_OFFSET, XRFDC_QMC_UPDT_MODE_MASK, + CoarseDelaySettingsPtr->EventSource); + if (CoarseDelaySettingsPtr->EventSource == + XRFDC_EVNT_SRC_IMMEDIATE) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_DAC_UPDATE_DYN_OFFSET, XRFDC_UPDT_EVNT_MASK, + XRFDC_DAC_UPDT_CRSE_DLY_MASK); + } + } + /* Update the instance with new values */ + CoarseDelayConfigPtr->CoarseDelay = + CoarseDelaySettingsPtr->CoarseDelay; + CoarseDelayConfigPtr->EventSource = + CoarseDelaySettingsPtr->EventSource; + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Coarse delay settings are returned back to the caller. +* +* @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. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param CoarseDelaySettingsPtr Pointer to the XRFdc_CoarseDelay_Settings +* structure in which the Coarse Delay settings are passed. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note None. +* +******************************************************************************/ +u32 XRFdc_GetCoarseDelaySettings(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 Block_Id, XRFdc_CoarseDelay_Settings *CoarseDelaySettingsPtr) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CoarseDelaySettingsPtr != 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; + } + + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Block_Id == XRFDC_BLK_ID1) && (Type == XRFDC_ADC_TILE)) { + Block_Id = XRFDC_BLK_ID2; + } + + BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Block_Id); + + if (Type == XRFDC_ADC_TILE) { + CoarseDelaySettingsPtr->CoarseDelay = + XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_ADC_CRSE_DLY_CFG_OFFSET); + CoarseDelaySettingsPtr->EventSource = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_CRSE_DLY_UPDT_OFFSET, XRFDC_QMC_UPDT_MODE_MASK); + } else { + CoarseDelaySettingsPtr->CoarseDelay = + XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_DAC_CRSE_DLY_CFG_OFFSET); + CoarseDelaySettingsPtr->EventSource = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_DAC_CRSE_DLY_UPDT_OFFSET, XRFDC_QMC_UPDT_MODE_MASK); + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function will trigger the update event for an event. +* +* @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. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param Event is for which dynamic update event will trigger. +* XRFDC_EVENT_* defines the different events. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Common API for ADC/DAC blocks +* +******************************************************************************/ +u32 XRFdc_UpdateEvent(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, u32 Block_Id, + u32 Event) +{ + u32 Status; + u32 BaseAddr; + u32 EventSource; + u32 NoOfBlocks; + u32 Index; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + 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; + } + if ((Event == XRFDC_EVENT_QMC) && (InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Index].MixerInputDataType == + XRFDC_DATA_TYPE_IQ)) { + Index = Block_Id; + NoOfBlocks = XRFDC_NUM_OF_BLKS3; + if (Block_Id == XRFDC_BLK_ID1) { + NoOfBlocks = XRFDC_NUM_OF_BLKS4; + } + } + } else { + NoOfBlocks = Block_Id + 1U; + } + + if ((Event != XRFDC_EVENT_MIXER) && (Event != XRFDC_EVENT_QMC) && + (Event != XRFDC_EVENT_CRSE_DLY)) { + metal_log(METAL_LOG_ERROR, "\n Invalid Event " + "value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + for (; Index < NoOfBlocks;) { + /* Identify the Event Source */ + BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Index); + if (Event == XRFDC_EVENT_MIXER) { + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, Type, + Tile_Id, Block_Id); + EventSource = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_NCO_UPDT_OFFSET, XRFDC_NCO_UPDT_MODE_MASK); + } else if (Event == XRFDC_EVENT_CRSE_DLY) { + Status = XRFdc_CheckBlockEnabled(InstancePtr, Type, + Tile_Id, Block_Id); + EventSource = XRFdc_RDReg(InstancePtr, BaseAddr, + (Type == XRFDC_ADC_TILE) ? XRFDC_ADC_CRSE_DLY_UPDT_OFFSET : + XRFDC_DAC_CRSE_DLY_UPDT_OFFSET, XRFDC_QMC_UPDT_MODE_MASK); + } else { + Status = XRFdc_CheckBlockEnabled(InstancePtr, Type, + Tile_Id, Block_Id); + EventSource = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_QMC_UPDT_OFFSET, XRFDC_QMC_UPDT_MODE_MASK); + } + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block not " + "available in %s\r\n", __func__); + goto RETURN_PATH; + } + + if ((EventSource == XRFDC_EVNT_SRC_SYSREF) || + (EventSource == XRFDC_EVNT_SRC_PL) || + (EventSource == XRFDC_EVNT_SRC_MARKER)) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, "\n Invalid Event " + "Source, this should be issued external to " + "the driver %s\r\n", __func__); + goto RETURN_PATH; + } + if (Type == XRFDC_ADC_TILE) { + if (EventSource == XRFDC_EVNT_SRC_SLICE) { + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_ADC_UPDATE_DYN_OFFSET, 0x1); + } else { + BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) + + XRFDC_HSCOM_ADDR; + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_HSCOM_UPDT_DYN_OFFSET, 0x1); + } + } else { + if (EventSource == XRFDC_EVNT_SRC_SLICE) { + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_DAC_UPDATE_DYN_OFFSET, 0x1); + } else { + BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) + + XRFDC_HSCOM_ADDR; + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_HSCOM_UPDT_DYN_OFFSET, 0x1); + } + } + if ((Event == XRFDC_EVENT_QMC) && (InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Index].MixerInputDataType == + XRFDC_DATA_TYPE_IQ) && (XRFdc_IsHighSpeedADC(InstancePtr, + Tile_Id) == 1) && (Type == XRFDC_ADC_TILE)) { + Index += XRFDC_BLK_ID2; + } else { + Index += XRFDC_BLK_ID1; + } + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is to set the decimation factor and also update the FIFO write +* words w.r.t to decimation factor. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param DecimationFactor to be set for DAC block. +* XRFDC_INTERP_DECIM_* defines the valid values. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only ADC blocks +* +******************************************************************************/ +u32 XRFdc_SetDecimationFactor(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 DecimationFactor) +{ + u32 Status; + u32 BaseAddr; + u32 Index; + u32 NoOfBlocks; + u16 FabricRate; + u8 DataType; + u32 Factor; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block digital path not " + "enabled in %s\r\n", __func__); + goto RETURN_PATH; + } + + if ((DecimationFactor != XRFDC_INTERP_DECIM_OFF) && + (DecimationFactor != XRFDC_INTERP_DECIM_1X) && + (DecimationFactor != XRFDC_INTERP_DECIM_2X) && + (DecimationFactor != XRFDC_INTERP_DECIM_4X) && + (DecimationFactor != XRFDC_INTERP_DECIM_8X) && + ((InstancePtr->RFdc_Config.IPType < 2) || + ((DecimationFactor != XRFDC_INTERP_DECIM_3X) && + (DecimationFactor != XRFDC_INTERP_DECIM_5X) && + (DecimationFactor != XRFDC_INTERP_DECIM_6X) && + (DecimationFactor != XRFDC_INTERP_DECIM_10X) && + (DecimationFactor != XRFDC_INTERP_DECIM_12X) && + (DecimationFactor != XRFDC_INTERP_DECIM_16X) && + (DecimationFactor != XRFDC_INTERP_DECIM_20X) && + (DecimationFactor != XRFDC_INTERP_DECIM_24X) && + (DecimationFactor != XRFDC_INTERP_DECIM_40X)))) { + metal_log(METAL_LOG_ERROR, "\n Invalid Decimation factor " + "value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + Index = Block_Id; + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + 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++) { + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Index); + DataType = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_DECI_CONFIG_OFFSET, XRFDC_DEC_CFG_MASK); + + /* Decimation factor */ + Factor = DecimationFactor; + if (InstancePtr->RFdc_Config.IPType < 2) { + if (DecimationFactor == XRFDC_INTERP_DECIM_4X) { + Factor = 0x3; + } + if (DecimationFactor == XRFDC_INTERP_DECIM_8X) { + Factor = 0x4; + } + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_DECI_MODE_OFFSET, + XRFDC_DEC_MOD_MASK, Factor); + } else { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_DECI_MODE_OFFSET, + XRFDC_DEC_MOD_MASK_EXT, Factor); + } + + + + /* Fabric rate */ + FabricRate = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_FABRIC_RATE_OFFSET, XRFDC_ADC_FAB_RATE_WR_MASK); + if ((DataType == XRFDC_DECIM_2G_IQ_DATA_TYPE) || + (DataType == XRFDC_DECIM_4G_DATA_TYPE) || + (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1)) { + switch (DecimationFactor) { + case XRFDC_INTERP_DECIM_1X: + FabricRate = XRFDC_FAB_RATE_8; + break; + case XRFDC_INTERP_DECIM_2X: + case XRFDC_INTERP_DECIM_3X: + FabricRate = XRFDC_FAB_RATE_4; + break; + case XRFDC_INTERP_DECIM_4X: + case XRFDC_INTERP_DECIM_5X: + case XRFDC_INTERP_DECIM_6X: + FabricRate = XRFDC_FAB_RATE_2; + break; + case XRFDC_INTERP_DECIM_10X: + case XRFDC_INTERP_DECIM_12X: + case XRFDC_INTERP_DECIM_8X: + FabricRate = XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) ? + XRFDC_FAB_RATE_1:XRFDC_FAB_RATE_2; + break; + case XRFDC_INTERP_DECIM_16X: + case XRFDC_INTERP_DECIM_20X: + case XRFDC_INTERP_DECIM_24X: + case XRFDC_INTERP_DECIM_40X: + FabricRate = XRFDC_FAB_RATE_1; + break; + default: + metal_log(METAL_LOG_DEBUG, "\n Decimation block " + "is OFF in %s\r\n", __func__); + break; + } + } else { + switch (DecimationFactor) { + case XRFDC_INTERP_DECIM_1X: + FabricRate = XRFDC_FAB_RATE_4; + break; + case XRFDC_INTERP_DECIM_2X: + case XRFDC_INTERP_DECIM_3X: + FabricRate = XRFDC_FAB_RATE_2; + break; + case XRFDC_INTERP_DECIM_4X: + case XRFDC_INTERP_DECIM_8X: + case XRFDC_INTERP_DECIM_5X: + case XRFDC_INTERP_DECIM_6X: + case XRFDC_INTERP_DECIM_10X: + case XRFDC_INTERP_DECIM_12X: + case XRFDC_INTERP_DECIM_16X: + case XRFDC_INTERP_DECIM_20X: + case XRFDC_INTERP_DECIM_24X: + case XRFDC_INTERP_DECIM_40X: + FabricRate = XRFDC_FAB_RATE_1; + break; + default: + metal_log(METAL_LOG_DEBUG, "\n Decimation block " + "is OFF in %s\r\n", __func__); + break; + } + } + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_FABRIC_RATE_OFFSET, + XRFDC_ADC_FAB_RATE_WR_MASK, FabricRate); + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is to set the divider for clock fabric out. +* +* @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. +* @param FabClkDiv to be set for a tile. +* XRFDC_FAB_CLK_* defines the valid divider values. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note ADC and DAC Tiles +* +******************************************************************************/ +u32 XRFdc_SetFabClkOutDiv(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u16 FabClkDiv) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckTileEnabled(InstancePtr, Type, Tile_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested tile not " + "available in %s\r\n", __func__); + goto RETURN_PATH; + } + + if ((FabClkDiv != XRFDC_FAB_CLK_DIV1) && + (FabClkDiv != XRFDC_FAB_CLK_DIV2) && + (FabClkDiv != XRFDC_FAB_CLK_DIV4) && + (FabClkDiv != XRFDC_FAB_CLK_DIV8) && + (FabClkDiv != XRFDC_FAB_CLK_DIV16)) { + metal_log(METAL_LOG_ERROR, "\n Invalid Fabric clock out " + "divider value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + BaseAddr = XRFDC_DRP_BASE(Type, Tile_Id) + XRFDC_HSCOM_ADDR; + + if ((Type == XRFDC_ADC_TILE) && + (FabClkDiv == XRFDC_FAB_CLK_DIV1)) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, "\n Invalid clock divider " + "in %s \r\n", __func__); + goto RETURN_PATH; + } else { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_HSCOM_CLK_DIV_OFFSET, + XRFDC_FAB_CLK_DIV_MASK, FabClkDiv); + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is to get the divider for clock fabric out. +* +* @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. +* @param FabClkDivPtr is a pointer to get fabric clock for a tile. +* XRFDC_FAB_CLK_* defines the valid divider values. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note API is applicable for both ADC and DAC Tiles +* +******************************************************************************/ +u32 XRFdc_GetFabClkOutDiv(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u16 *FabClkDivPtr) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(FabClkDivPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckTileEnabled(InstancePtr, Type, Tile_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested tile not " + "available in %s\r\n", __func__); + goto RETURN_PATH; + } + + BaseAddr = XRFDC_DRP_BASE(Type, Tile_Id) + XRFDC_HSCOM_ADDR; + + *FabClkDivPtr = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_HSCOM_CLK_DIV_OFFSET, XRFDC_FAB_CLK_DIV_MASK); + + if ((*FabClkDivPtr < XRFDC_FAB_CLK_DIV1) || + (*FabClkDivPtr > XRFDC_FAB_CLK_DIV16)) { + *FabClkDivPtr = XRFDC_FAB_CLK_DIV16; + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is to set the interpolation factor and also update the FIFO read +* words w.r.t to interpolation factor. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param InterpolationFactor to be set for DAC block. +* XRFDC_INTERP_DECIM_* defines the valid values. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only DAC blocks +* +******************************************************************************/ +u32 XRFdc_SetInterpolationFactor(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 InterpolationFactor) +{ + u32 Status; + u32 BaseAddr; + u16 FabricRate; + u8 DataType; + u32 Factor; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block digital path not " + "enabled in %s\r\n", __func__); + goto RETURN_PATH; + } + + if ((InterpolationFactor != XRFDC_INTERP_DECIM_OFF) && + (InterpolationFactor != XRFDC_INTERP_DECIM_1X) && + (InterpolationFactor != XRFDC_INTERP_DECIM_2X) && + (InterpolationFactor != XRFDC_INTERP_DECIM_4X) && + (InterpolationFactor != XRFDC_INTERP_DECIM_8X) && + ((InstancePtr->RFdc_Config.IPType < 2) || + ((InterpolationFactor != XRFDC_INTERP_DECIM_3X) && + (InterpolationFactor != XRFDC_INTERP_DECIM_5X) && + (InterpolationFactor != XRFDC_INTERP_DECIM_6X) && + (InterpolationFactor != XRFDC_INTERP_DECIM_10X) && + (InterpolationFactor != XRFDC_INTERP_DECIM_12X) && + (InterpolationFactor != XRFDC_INTERP_DECIM_16X) && + (InterpolationFactor != XRFDC_INTERP_DECIM_20X) && + (InterpolationFactor != XRFDC_INTERP_DECIM_24X) && + (InterpolationFactor != XRFDC_INTERP_DECIM_40X)))) { + metal_log(METAL_LOG_ERROR, "\n Invalid Interpolation factor " + "divider value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + + DataType = XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_DAC_ITERP_DATA_OFFSET); + if ((DataType == XRFDC_ADC_MIXER_MODE_IQ) && + (InterpolationFactor == + XRFDC_INTERP_DECIM_1X)) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, "\n Invalid interpolation " + "factor in %s\r\n", __func__); + goto RETURN_PATH; + } + + /* Interpolation factor */ + Factor = InterpolationFactor; + + if (InstancePtr->RFdc_Config.IPType < 2) { + if (InterpolationFactor == XRFDC_INTERP_DECIM_4X) { + Factor = 0x3; + } + if (InterpolationFactor == XRFDC_INTERP_DECIM_8X) { + Factor = 0x4; + } + } + if (DataType == XRFDC_ADC_MIXER_MODE_IQ) { + Factor |= Factor << ((InstancePtr->RFdc_Config.IPType < 2)?XRFDC_INTERP_MODE_Q_SHIFT:XRFDC_INTERP_MODE_Q_SHIFT_EXT); + } + + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DAC_INTERP_CTRL_OFFSET, + (InstancePtr->RFdc_Config.IPType < 2)?XRFDC_INTERP_MODE_MASK:XRFDC_INTERP_MODE_MASK_EXT, Factor); + + /* Fabric rate */ + FabricRate = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_FABRIC_RATE_OFFSET, XRFDC_FAB_RATE_RD_MASK); + FabricRate = FabricRate >> XRFDC_FAB_RATE_RD_SHIFT; + if (DataType == XRFDC_ADC_MIXER_MODE_IQ) { + switch (InterpolationFactor) { + case XRFDC_INTERP_DECIM_2X: + case XRFDC_INTERP_DECIM_3X: + FabricRate = XRFDC_FAB_RATE_8; + break; + case XRFDC_INTERP_DECIM_4X: + case XRFDC_INTERP_DECIM_5X: + case XRFDC_INTERP_DECIM_6X: + FabricRate = XRFDC_FAB_RATE_4; + break; + case XRFDC_INTERP_DECIM_8X: + case XRFDC_INTERP_DECIM_10X: + case XRFDC_INTERP_DECIM_12X: + FabricRate = XRFDC_FAB_RATE_2; + break; + case XRFDC_INTERP_DECIM_16X: + case XRFDC_INTERP_DECIM_20X: + case XRFDC_INTERP_DECIM_24X: + case XRFDC_INTERP_DECIM_40X: + FabricRate = XRFDC_FAB_RATE_1; + break; + default: + metal_log(METAL_LOG_DEBUG, "\n Interpolation block " + "is OFF in %s\r\n", __func__); + break; + } + } else { + switch (InterpolationFactor) { + case XRFDC_INTERP_DECIM_1X: + FabricRate = XRFDC_FAB_RATE_8; + break; + case XRFDC_INTERP_DECIM_2X: + case XRFDC_INTERP_DECIM_3X: + FabricRate = XRFDC_FAB_RATE_4; + break; + case XRFDC_INTERP_DECIM_4X: + case XRFDC_INTERP_DECIM_5X: + case XRFDC_INTERP_DECIM_6X: + FabricRate = XRFDC_FAB_RATE_2; + break; + case XRFDC_INTERP_DECIM_8X: + case XRFDC_INTERP_DECIM_10X: + case XRFDC_INTERP_DECIM_12X: + case XRFDC_INTERP_DECIM_16X: + case XRFDC_INTERP_DECIM_20X: + case XRFDC_INTERP_DECIM_24X: + case XRFDC_INTERP_DECIM_40X: + FabricRate = XRFDC_FAB_RATE_1; + break; + default: + metal_log(METAL_LOG_DEBUG, "\n Interpolation block " + "is OFF in %s\r\n", __func__); + break; + } + } + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_FABRIC_RATE_OFFSET, + XRFDC_FAB_RATE_RD_MASK, (FabricRate << XRFDC_FAB_RATE_RD_SHIFT)); + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Interpolation factor are returned back to the caller. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param InterpolationFactorPtr Pointer to return the interpolation factor +* for DAC blocks. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only for DAC blocks +* +******************************************************************************/ +u32 XRFdc_GetInterpolationFactor(XRFdc *InstancePtr, u32 Tile_Id, + u32 Block_Id, u32 *InterpolationFactorPtr) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InterpolationFactorPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block digital path not " + "enabled in %s\r\n", __func__); + goto RETURN_PATH; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + + if (InstancePtr->RFdc_Config.IPType < 2) { + *InterpolationFactorPtr = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_DAC_INTERP_CTRL_OFFSET, XRFDC_INTERP_MODE_I_MASK); + if (*InterpolationFactorPtr == 0x3U) { + *InterpolationFactorPtr = XRFDC_INTERP_DECIM_4X; + } else if (*InterpolationFactorPtr == 0x4U) { + *InterpolationFactorPtr = XRFDC_INTERP_DECIM_8X; + } + } else { + *InterpolationFactorPtr = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_DAC_INTERP_CTRL_OFFSET, XRFDC_INTERP_MODE_I_MASK_EXT); + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Decimation factor are returned back to the caller. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param DecimationFactorPtr Pointer to return the Decimation factor +* for DAC blocks. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_GetDecimationFactor(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 *DecimationFactorPtr) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(DecimationFactorPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block digital path not " + "enabled in %s\r\n", __func__); + goto RETURN_PATH; + } + + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Block_Id == XRFDC_BLK_ID1)) { + Block_Id = XRFDC_BLK_ID2; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Block_Id); + + + + if (InstancePtr->RFdc_Config.IPType < 2) { + *DecimationFactorPtr = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_DECI_MODE_OFFSET, XRFDC_DEC_MOD_MASK); + if (*DecimationFactorPtr == 0x3U) { + *DecimationFactorPtr = XRFDC_INTERP_DECIM_4X; + } else if (*DecimationFactorPtr == 0x4U) { + *DecimationFactorPtr = XRFDC_INTERP_DECIM_8X; + } + } else { + *DecimationFactorPtr = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_DECI_MODE_OFFSET, XRFDC_DEC_MOD_MASK_EXT); + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Fabric data rate for the requested DAC block is set by writing to the +* corresponding register. The function writes the number of valid write words +* for the requested DAC block. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param FabricWrVldWords is write fabric rate to be set for DAC block. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only for DAC blocks +* +******************************************************************************/ +u32 XRFdc_SetFabWrVldWords(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 FabricWrVldWords) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, XRFDC_DAC_TILE, Tile_Id, + Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block digital path not " + "enabled in %s\r\n", __func__); + goto RETURN_PATH; + } + + if (FabricWrVldWords > XRFDC_DAC_MAX_WR_FAB_RATE) { + metal_log(METAL_LOG_ERROR, "\n Requested write valid words " + "is Invalid in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_FABRIC_RATE_OFFSET, + XRFDC_DAC_FAB_RATE_WR_MASK, FabricWrVldWords); + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* +* Fabric data rate for the requested ADC block is set by writing to the +* corresponding register. The function writes the number of valid read words +* for the requested ADC block. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC block number inside the tile. Valid values +* are 0-3. +* @param FabricRdVldWords is Read fabric rate to be set for ADC block. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_SetFabRdVldWords(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 FabricRdVldWords) +{ + u32 Status; + u32 BaseAddr; + u32 Index; + u32 NoOfBlocks; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, XRFDC_ADC_TILE, Tile_Id, + Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block digital path not " + "enabled in %s\r\n", __func__); + goto RETURN_PATH; + } + + if (FabricRdVldWords > XRFDC_ADC_MAX_RD_FAB_RATE) { + metal_log(METAL_LOG_ERROR, "\n Requested read " + "valid words is Invalid in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + Index = Block_Id; + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + 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++) { + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Index); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_ADC_FABRIC_RATE_OFFSET, XRFDC_FAB_RATE_RD_MASK, + (FabricRdVldWords << XRFDC_FAB_RATE_RD_SHIFT)); + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; + +} + +/*****************************************************************************/ +/** +* +* This API returns the the number of fabric write valid words requested +* for the block. +* +* @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. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param FabricWrVldWordsPtr Pointer to return the fabric data rate for +* DAC block +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note ADC/DAC blocks +* +******************************************************************************/ +u32 XRFdc_GetFabWrVldWords(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 Block_Id, u32 *FabricWrVldWordsPtr) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(FabricWrVldWordsPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, Type, Tile_Id, Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block digital path not " + "enabled in %s\r\n", __func__); + goto RETURN_PATH; + } + + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Block_Id == XRFDC_BLK_ID1) && (Type == XRFDC_ADC_TILE)) { + Block_Id = XRFDC_BLK_ID2; + } + + BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Block_Id); + + *FabricWrVldWordsPtr = XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_ADC_FABRIC_RATE_OFFSET); + if (Type == XRFDC_ADC_TILE) { + *FabricWrVldWordsPtr &= XRFDC_ADC_FAB_RATE_WR_MASK; + } else { + *FabricWrVldWordsPtr &= XRFDC_DAC_FAB_RATE_WR_MASK; + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This API returns the the number of fabric read valid words requested +* for the block. +* +* @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. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param FabricRdVldWordsPtr Pointer to return the fabric data rate for +* ADC/DAC block +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note ADC/DAC blocks +* +******************************************************************************/ +u32 XRFdc_GetFabRdVldWords(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 Block_Id, u32 *FabricRdVldWordsPtr) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(FabricRdVldWordsPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, Type, Tile_Id, Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block digital path not " + "enabled in %s\r\n", __func__); + goto RETURN_PATH; + } + + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Block_Id == XRFDC_BLK_ID1) && (Type == XRFDC_ADC_TILE)) { + Block_Id = XRFDC_BLK_ID2; + } + BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Block_Id); + + *FabricRdVldWordsPtr = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_FABRIC_RATE_OFFSET, XRFDC_FAB_RATE_RD_MASK); + *FabricRdVldWordsPtr = (*FabricRdVldWordsPtr) >> XRFDC_FAB_RATE_RD_SHIFT; + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is to clear the Sticky bit in threshold config registers. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param ThresholdToUpdate Select which Threshold (Threshold0 or +* Threshold1 or both) to update. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only ADC blocks +* +******************************************************************************/ +u32 XRFdc_ThresholdStickyClear(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 ThresholdToUpdate) +{ + u32 Status; + u32 BaseAddr; + u32 Index; + u32 NoOfBlocks; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + + if ((ThresholdToUpdate != XRFDC_UPDATE_THRESHOLD_0) && + (ThresholdToUpdate != XRFDC_UPDATE_THRESHOLD_1) && + (ThresholdToUpdate != XRFDC_UPDATE_THRESHOLD_BOTH)) { + metal_log(METAL_LOG_ERROR, "\n Invalid ThresholdToUpdate " + "value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + Index = Block_Id; + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + NoOfBlocks = XRFDC_NUM_OF_BLKS2; + if (Block_Id == XRFDC_BLK_ID1) { + Index = XRFDC_BLK_ID2; + NoOfBlocks = XRFDC_NUM_OF_BLKS4; + } + if (InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Index].MixerInputDataType == + XRFDC_DATA_TYPE_IQ) { + Index = Block_Id; + NoOfBlocks = XRFDC_NUM_OF_BLKS3; + if (Block_Id == XRFDC_BLK_ID1) { + NoOfBlocks = XRFDC_NUM_OF_BLKS4; + } + } + } else { + NoOfBlocks = Block_Id + 1U; + } + + for (; Index < NoOfBlocks;) { + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Index); + /* Update for Threshold0 */ + if ((ThresholdToUpdate == XRFDC_UPDATE_THRESHOLD_0) || + (ThresholdToUpdate == XRFDC_UPDATE_THRESHOLD_BOTH)) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD0_CFG_OFFSET, XRFDC_TRSHD0_STIKY_CLR_MASK, + XRFDC_TRSHD0_STIKY_CLR_MASK); + } + /* Update for Threshold1 */ + if ((ThresholdToUpdate == XRFDC_UPDATE_THRESHOLD_1) || + (ThresholdToUpdate == XRFDC_UPDATE_THRESHOLD_BOTH)) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD1_CFG_OFFSET, XRFDC_TRSHD1_STIKY_CLR_MASK, + XRFDC_TRSHD1_STIKY_CLR_MASK); + } + + if ((InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Index].MixerInputDataType == + XRFDC_DATA_TYPE_IQ) && (XRFdc_IsHighSpeedADC(InstancePtr, + Tile_Id) == 1)) { + Index += XRFDC_BLK_ID2; + } else { + Index += XRFDC_BLK_ID1; + } + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This API sets the threshold clear mode. The clear mode can be through +* explicit DRP access (manual) or auto clear (QMC gain update event). +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADCC block number inside the tile. Valid values +* are 0-3. +* @param ThresholdToUpdate Select which Threshold (Threshold0 or +* Threshold1 or both) to update. +* @param ClrMode can be DRP access (manual) or auto clear (QMC gain +* update event). +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only ADC blocks +* +******************************************************************************/ +u32 XRFdc_SetThresholdClrMode(XRFdc *InstancePtr, u32 Tile_Id, + u32 Block_Id, u32 ThresholdToUpdate, u32 ClrMode) +{ + u32 Status; + u16 ReadReg; + u32 BaseAddr; + u32 Index; + u32 NoOfBlocks; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + + if ((ThresholdToUpdate != XRFDC_UPDATE_THRESHOLD_0) && + (ThresholdToUpdate != XRFDC_UPDATE_THRESHOLD_1) && + (ThresholdToUpdate != XRFDC_UPDATE_THRESHOLD_BOTH)) { + metal_log(METAL_LOG_ERROR, "\n Invalid ThresholdToUpdate " + "value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + if ((ClrMode != XRFDC_THRESHOLD_CLRMD_MANUAL_CLR) && + (ClrMode != XRFDC_THRESHOLD_CLRMD_AUTO_CLR)) { + metal_log(METAL_LOG_ERROR, "\n Invalid Clear mode " + "value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + Index = Block_Id; + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + NoOfBlocks = XRFDC_NUM_OF_BLKS2; + if (Block_Id == XRFDC_BLK_ID1) { + Index = XRFDC_BLK_ID2; + NoOfBlocks = XRFDC_NUM_OF_BLKS4; + } + if (InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Index].MixerInputDataType == + XRFDC_DATA_TYPE_IQ) { + Index = Block_Id; + NoOfBlocks = XRFDC_NUM_OF_BLKS3; + if (Block_Id == XRFDC_BLK_ID1) { + NoOfBlocks = XRFDC_NUM_OF_BLKS4; + } + } + } else { + NoOfBlocks = Block_Id + 1U; + } + + for (; Index < NoOfBlocks;) { + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Index); + /* Update for Threshold0 */ + if ((ThresholdToUpdate == XRFDC_UPDATE_THRESHOLD_0) || + (ThresholdToUpdate == XRFDC_UPDATE_THRESHOLD_BOTH)) { + ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD0_CFG_OFFSET); + if (ClrMode == XRFDC_THRESHOLD_CLRMD_MANUAL_CLR) { + ReadReg &= ~XRFDC_TRSHD0_CLR_MOD_MASK; + } else { + ReadReg |= XRFDC_TRSHD0_CLR_MOD_MASK; + } + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD0_CFG_OFFSET, ReadReg); + } + /* Update for Threshold1 */ + if ((ThresholdToUpdate == XRFDC_UPDATE_THRESHOLD_1) || + (ThresholdToUpdate == XRFDC_UPDATE_THRESHOLD_BOTH)) { + ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD1_CFG_OFFSET); + if (ClrMode == XRFDC_THRESHOLD_CLRMD_MANUAL_CLR) { + ReadReg &= ~XRFDC_TRSHD1_CLR_MOD_MASK; + } else { + ReadReg |= XRFDC_TRSHD1_CLR_MOD_MASK; + } + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD1_CFG_OFFSET, ReadReg); + } + if ((InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Index].MixerInputDataType == + XRFDC_DATA_TYPE_IQ) && (XRFdc_IsHighSpeedADC(InstancePtr, + Tile_Id) == 1)) { + Index += XRFDC_BLK_ID2; + } else { + Index += XRFDC_BLK_ID1; + } + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Threshold settings are updated into the relevant registers. Driver structure +* is updated with the new values. There can be two threshold settings: +* threshold0 and threshold1. Both of them are independent of each other. +* The function returns the requested threshold (which can be threshold0, +* threshold1, or both. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param ThresholdSettingsPtr Pointer through which the register settings for +* thresholds are passed to the API. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only ADC blocks +* +******************************************************************************/ +u32 XRFdc_SetThresholdSettings(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + XRFdc_Threshold_Settings *ThresholdSettingsPtr) +{ + u32 Status; + u32 BaseAddr; + u32 Index; + u32 NoOfBlocks; + XRFdc_Threshold_Settings *ThresholdConfigPtr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ThresholdSettingsPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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) { + NoOfBlocks = XRFDC_NUM_OF_BLKS2; + if (Block_Id == XRFDC_BLK_ID1) { + Index = XRFDC_BLK_ID2; + NoOfBlocks = XRFDC_NUM_OF_BLKS4; + } + if (InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Index].MixerInputDataType == + XRFDC_DATA_TYPE_IQ) { + Index = Block_Id; + NoOfBlocks = XRFDC_NUM_OF_BLKS3; + if (Block_Id == XRFDC_BLK_ID1) { + NoOfBlocks = XRFDC_NUM_OF_BLKS4; + } + } + } else { + NoOfBlocks = Block_Id + 1U; + } + + for (; Index < NoOfBlocks;) { + ThresholdConfigPtr = &InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Analog_Datapath[Index].Threshold_Settings; + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Index); + + if ((ThresholdSettingsPtr->UpdateThreshold != XRFDC_UPDATE_THRESHOLD_0) && + (ThresholdSettingsPtr->UpdateThreshold != XRFDC_UPDATE_THRESHOLD_1) && + (ThresholdSettingsPtr->UpdateThreshold != XRFDC_UPDATE_THRESHOLD_BOTH)) { + metal_log(METAL_LOG_ERROR, "\n Invalid UpdateThreshold " + "value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + if (((ThresholdSettingsPtr->UpdateThreshold == + XRFDC_UPDATE_THRESHOLD_0) || + (ThresholdSettingsPtr->UpdateThreshold == + XRFDC_UPDATE_THRESHOLD_BOTH)) && + (ThresholdSettingsPtr->ThresholdMode[0] > XRFDC_TRSHD_HYSTERISIS)) { + metal_log(METAL_LOG_ERROR, "\n Requested threshold " + "mode for threshold0 is invalid " + "in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + if (((ThresholdSettingsPtr->UpdateThreshold == + XRFDC_UPDATE_THRESHOLD_1) || + (ThresholdSettingsPtr->UpdateThreshold == + XRFDC_UPDATE_THRESHOLD_BOTH)) && + (ThresholdSettingsPtr->ThresholdMode[1] > XRFDC_TRSHD_HYSTERISIS)) { + metal_log(METAL_LOG_ERROR, "\n Requested threshold " + "mode for threshold1 is invalid " + "in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + /* Update for Threshold0 */ + if ((ThresholdSettingsPtr->UpdateThreshold == + XRFDC_UPDATE_THRESHOLD_0) || + (ThresholdSettingsPtr->UpdateThreshold == + XRFDC_UPDATE_THRESHOLD_BOTH)) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_TRSHD0_CFG_OFFSET, + XRFDC_TRSHD0_EN_MOD_MASK, + ThresholdSettingsPtr->ThresholdMode[0]); + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD0_AVG_LO_OFFSET, + (u16)ThresholdSettingsPtr->ThresholdAvgVal[0]); + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD0_AVG_UP_OFFSET, + (u16)(ThresholdSettingsPtr->ThresholdAvgVal[0] >> + XRFDC_TRSHD0_AVG_UPP_SHIFT)); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD0_UNDER_OFFSET, XRFDC_TRSHD0_UNDER_MASK, + ThresholdSettingsPtr->ThresholdUnderVal[0]); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD0_OVER_OFFSET, XRFDC_TRSHD0_OVER_MASK, + ThresholdSettingsPtr->ThresholdOverVal[0]); + + ThresholdConfigPtr->ThresholdMode[0] = + ThresholdSettingsPtr->ThresholdMode[0]; + ThresholdConfigPtr->ThresholdAvgVal[0] = + ThresholdSettingsPtr->ThresholdAvgVal[0]; + ThresholdConfigPtr->ThresholdUnderVal[0] = + ThresholdSettingsPtr->ThresholdUnderVal[0]; + ThresholdConfigPtr->ThresholdOverVal[0] = + ThresholdSettingsPtr->ThresholdOverVal[0]; + } + + /* Update for Threshold1 */ + if ((ThresholdSettingsPtr->UpdateThreshold == + XRFDC_UPDATE_THRESHOLD_1) || + (ThresholdSettingsPtr->UpdateThreshold == + XRFDC_UPDATE_THRESHOLD_BOTH)) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD1_CFG_OFFSET, XRFDC_TRSHD1_EN_MOD_MASK, + ThresholdSettingsPtr->ThresholdMode[1]); + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD1_AVG_LO_OFFSET, + (u16)ThresholdSettingsPtr->ThresholdAvgVal[1]); + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD1_AVG_UP_OFFSET, + (u16)(ThresholdSettingsPtr->ThresholdAvgVal[1] >> + XRFDC_TRSHD1_AVG_UPP_SHIFT)); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD1_UNDER_OFFSET, XRFDC_TRSHD1_UNDER_MASK, + ThresholdSettingsPtr->ThresholdUnderVal[1]); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD1_OVER_OFFSET, XRFDC_TRSHD1_OVER_MASK, + ThresholdSettingsPtr->ThresholdOverVal[1]); + + ThresholdConfigPtr->ThresholdMode[1] = + ThresholdSettingsPtr->ThresholdMode[1]; + ThresholdConfigPtr->ThresholdAvgVal[1] = + ThresholdSettingsPtr->ThresholdAvgVal[1]; + ThresholdConfigPtr->ThresholdUnderVal[1] = + ThresholdSettingsPtr->ThresholdUnderVal[1]; + ThresholdConfigPtr->ThresholdOverVal[1] = + ThresholdSettingsPtr->ThresholdOverVal[1]; + } + if ((InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Index].MixerInputDataType == + XRFDC_DATA_TYPE_IQ) && (XRFdc_IsHighSpeedADC(InstancePtr, + Tile_Id) == 1)) { + Index += XRFDC_BLK_ID2; + } else { + Index += XRFDC_BLK_ID1; + } + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Threshold settings are read from the corresponding registers and are passed +* back to the caller. There can be two threshold settings: +* threshold0 and threshold1. Both of them are independent of each other. +* The function returns the requested threshold (which can be threshold0, +* threshold1, or both. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param ThresholdSettingsPtr Pointer through which the register settings +* for thresholds are passed back.. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_GetThresholdSettings(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + XRFdc_Threshold_Settings *ThresholdSettingsPtr) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ThresholdSettingsPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Block_Id == XRFDC_BLK_ID1) && (InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Digital_Datapath[Block_Id].MixerInputDataType != + XRFDC_DATA_TYPE_IQ)) { + Block_Id = XRFDC_BLK_ID2; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Block_Id); + + /* Threshold mode */ + ThresholdSettingsPtr->UpdateThreshold = XRFDC_UPDATE_THRESHOLD_BOTH; + ThresholdSettingsPtr->ThresholdMode[0] = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD0_CFG_OFFSET, XRFDC_TRSHD0_EN_MOD_MASK); + ThresholdSettingsPtr->ThresholdMode[1] = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_TRSHD1_CFG_OFFSET, XRFDC_TRSHD1_EN_MOD_MASK); + + /* Threshold Average Value */ + ThresholdSettingsPtr->ThresholdAvgVal[0] = XRFdc_ReadReg16(InstancePtr, + BaseAddr, XRFDC_ADC_TRSHD0_AVG_LO_OFFSET); + ThresholdSettingsPtr->ThresholdAvgVal[0] |= (XRFdc_ReadReg16(InstancePtr, + BaseAddr, XRFDC_ADC_TRSHD0_AVG_UP_OFFSET) << + XRFDC_TRSHD0_AVG_UPP_SHIFT); + ThresholdSettingsPtr->ThresholdAvgVal[1] = XRFdc_ReadReg16(InstancePtr, + BaseAddr, XRFDC_ADC_TRSHD1_AVG_LO_OFFSET); + ThresholdSettingsPtr->ThresholdAvgVal[1] |= (XRFdc_ReadReg16(InstancePtr, + BaseAddr, XRFDC_ADC_TRSHD1_AVG_UP_OFFSET) << + XRFDC_TRSHD1_AVG_UPP_SHIFT); + + /* Threshold Under Value */ + ThresholdSettingsPtr->ThresholdUnderVal[0] = XRFdc_RDReg(InstancePtr, + BaseAddr, XRFDC_ADC_TRSHD0_UNDER_OFFSET, XRFDC_TRSHD0_UNDER_MASK); + ThresholdSettingsPtr->ThresholdUnderVal[1] = XRFdc_RDReg(InstancePtr, + BaseAddr, XRFDC_ADC_TRSHD1_UNDER_OFFSET, XRFDC_TRSHD1_UNDER_MASK); + + /* Threshold Over Value */ + ThresholdSettingsPtr->ThresholdOverVal[0] = XRFdc_RDReg(InstancePtr, + BaseAddr, XRFDC_ADC_TRSHD0_OVER_OFFSET, XRFDC_TRSHD0_OVER_MASK); + ThresholdSettingsPtr->ThresholdOverVal[1] = XRFdc_RDReg(InstancePtr, + BaseAddr, XRFDC_ADC_TRSHD1_OVER_OFFSET, XRFDC_TRSHD1_OVER_MASK); + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Decoder mode is updated into the relevant registers. Driver structure is +* updated with the new values. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is DAC block number inside the tile. Valid values +* are 0-3. +* @param DecoderMode Valid values are 1 (Maximum SNR, for non- +* randomized decoder), 2 (Maximum Linearity, for randomized decoder) +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only DAC blocks +* +******************************************************************************/ +u32 XRFdc_SetDecoderMode(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 DecoderMode) +{ + u32 Status; + u32 *DecoderModeConfigPtr; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_DAC_TILE, 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; + } + + DecoderModeConfigPtr = &InstancePtr->DAC_Tile[Tile_Id]. + DACBlock_Analog_Datapath[Block_Id].DecoderMode; + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + + if ((DecoderMode != XRFDC_DECODER_MAX_SNR_MODE) && + (DecoderMode != XRFDC_DECODER_MAX_LINEARITY_MODE)) { + metal_log(METAL_LOG_ERROR, "\n Invalid decoder mode " + "in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DAC_DECODER_CTRL_OFFSET, + XRFDC_DEC_CTRL_MODE_MASK, DecoderMode); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DAC_DECODER_CLK_OFFSET, + XRFDC_DEC_CTRL_MODE_MASK, DecoderMode); + *DecoderModeConfigPtr = DecoderMode; + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Decoder mode is read and returned back. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is DAC block number inside the tile. Valid values +* are 0-3. +* @param DecoderModePtr Valid values are 1 (Maximum SNR, for non-randomized +* decoder), 2 (Maximum Linearity, for randomized decoder) +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only for DAC blocks +* +******************************************************************************/ +u32 XRFdc_GetDecoderMode(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 *DecoderModePtr) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(DecoderModePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_DAC_TILE, 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; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + *DecoderModePtr = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_DAC_DECODER_CTRL_OFFSET, XRFDC_DEC_CTRL_MODE_MASK); + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Resets the NCO phase of the current block phase accumulator. +* +* @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. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note None +* +******************************************************************************/ +u32 XRFdc_ResetNCOPhase(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 Block_Id) +{ + u32 Status; + u32 BaseAddr; + u32 Index; + u32 NoOfBlocks; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, Type, Tile_Id, + Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block digital path not " + "enabled 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++) { + BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Index); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_NCO_RST_OFFSET, + XRFDC_NCO_PHASE_RST_MASK, XRFDC_NCO_PHASE_RST_MASK); + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; + +} +/*****************************************************************************/ +/** +* +* Enable and Disable the ADC/DAC FIFO. +* +* @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. +* @param Enable valid values are 1 (FIFO enable) and 0 (FIFO Disable) +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Common API for ADC/DAC blocks +* +******************************************************************************/ +u32 XRFdc_SetupFIFO(XRFdc *InstancePtr, u32 Type, int Tile_Id, u8 Enable) +{ + u32 Status; + u32 BaseAddr; + u16 NoOfTiles; + u16 Index; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + if ((Enable != 0U) && (Enable != 1U)) { + metal_log(METAL_LOG_ERROR, "\n Invalid enable " + "value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + + /* An input tile if of -1 selects all tiles */ + if (Tile_Id == XRFDC_SELECT_ALL_TILES) { + NoOfTiles = XRFDC_NUM_OF_TILES4; + Index = XRFDC_TILE_ID0; + } else { + NoOfTiles = Tile_Id + 1; + Index = Tile_Id; + } + + for (; Index < NoOfTiles; Index++) { + BaseAddr = XRFDC_CTRL_STS_BASE(Type, Index); + + Status = XRFdc_CheckTileEnabled(InstancePtr, Type, Index); + if ((Status != XRFDC_SUCCESS) && (Tile_Id != XRFDC_SELECT_ALL_TILES)) { + metal_log(METAL_LOG_ERROR, "\n Requested tile%d not " + "available in %s\r\n", Index, __func__); + goto RETURN_PATH; + } else if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_DEBUG, "\n Tile%d not " + "available in %s\r\n", Index, __func__); + continue; + } else { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_FIFO_ENABLE, + XRFDC_FIFO_EN_MASK, (!Enable)); + } + } + Status = XRFDC_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Current status of ADC/DAC FIFO. +* +* @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. +* @param EnablePtr valid values are 1 (FIFO enable) and 0 (FIFO Disable) +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Common API for ADC/DAC blocks +* +******************************************************************************/ +u32 XRFdc_GetFIFOStatus(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u8 *EnablePtr) +{ + u32 Status; + u32 BaseAddr; + u32 ReadReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(EnablePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckTileEnabled(InstancePtr, Type, Tile_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested tile not " + "available in %s\r\n", __func__); + goto RETURN_PATH; + } + + BaseAddr = XRFDC_CTRL_STS_BASE(Type, Tile_Id); + + ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_FIFO_ENABLE, XRFDC_FIFO_EN_MASK); + *EnablePtr = (!ReadReg); + + Status = XRFDC_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Get Output Current for DAC block. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param OutputCurrPtr pointer to return the output current. +* +* @return +* - Return Output Current for DAC block +* +******************************************************************************/ +u32 XRFdc_GetOutputCurr(XRFdc *InstancePtr, u32 Tile_Id, + u32 Block_Id, u32 *OutputCurrPtr) +{ + u32 Status; + u32 BaseAddr; + u16 ReadReg_Cfg2; + u16 ReadReg_Cfg3; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(OutputCurrPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_DAC_TILE, 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; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + + ReadReg_Cfg2 = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_DAC_MC_CFG2_OFFSET, XRFDC_DAC_MC_CFG2_OPCSCAS_MASK); + ReadReg_Cfg3 = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_DAC_MC_CFG3_OFFSET, XRFDC_DAC_MC_CFG3_CSGAIN_MASK); + if ((ReadReg_Cfg2 == XRFDC_DAC_MC_CFG2_OPCSCAS_32MA) && + (ReadReg_Cfg3 == XRFDC_DAC_MC_CFG3_CSGAIN_32MA)) { + *OutputCurrPtr = XRFDC_OUTPUT_CURRENT_32MA; + } else if ((ReadReg_Cfg2 == XRFDC_DAC_MC_CFG2_OPCSCAS_20MA) && + (ReadReg_Cfg3 == XRFDC_DAC_MC_CFG3_CSGAIN_20MA)) { + *OutputCurrPtr = XRFDC_OUTPUT_CURRENT_20MA; + } else if ((ReadReg_Cfg2 == 0x0) && (ReadReg_Cfg3 == 0x0)) { + *OutputCurrPtr = 0x0; + } else { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, "\n Invalid output " + "current value %s\r\n", __func__); + goto RETURN_PATH; + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Set the Nyquist zone. +* +* @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. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param NyquistZone valid values are 1 (Odd),2 (Even). +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Common API for ADC/DAC blocks +* +******************************************************************************/ +u32 XRFdc_SetNyquistZone(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 Block_Id, u32 NyquistZone) +{ + u32 Status; + u16 ReadReg; + u32 BaseAddr; + u32 Index; + u32 NoOfBlocks; + u8 CalibrationMode = 0U; + + 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; + } + + if ((NyquistZone != XRFDC_ODD_NYQUIST_ZONE) && + (NyquistZone != XRFDC_EVEN_NYQUIST_ZONE)) { + metal_log(METAL_LOG_ERROR, "\n Invalid NyquistZone " + "value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + 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++) { + BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Index); + if (Type == XRFDC_ADC_TILE) { + /* Identify calibration mode */ + Status = XRFdc_GetCalibrationMode(InstancePtr, + Tile_Id, Block_Id, &CalibrationMode); + if (Status != XRFDC_SUCCESS) { + return XRFDC_FAILURE; + } + + if (CalibrationMode == XRFDC_CALIB_MODE1) { + if (NyquistZone == + XRFDC_ODD_NYQUIST_ZONE) { + NyquistZone = + XRFDC_EVEN_NYQUIST_ZONE; + } else { + NyquistZone = + XRFDC_ODD_NYQUIST_ZONE; + } + } + ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TI_TISK_CRL0_OFFSET); + if ((NyquistZone % 2U) == 0U) { + ReadReg |= XRFDC_TI_TISK_ZONE_MASK; + } else { + ReadReg &= ~XRFDC_TI_TISK_ZONE_MASK; + } + + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TI_TISK_CRL0_OFFSET, ReadReg); + InstancePtr->ADC_Tile[Tile_Id]. + ADCBlock_Analog_Datapath[Index]. + NyquistZone = NyquistZone; + } else { + ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_DAC_MC_CFG0_OFFSET); + if ((NyquistZone % 2U) == 0U) { + ReadReg |= XRFDC_MC_CFG0_MIX_MODE_MASK; + } else { + ReadReg &= ~XRFDC_MC_CFG0_MIX_MODE_MASK; + } + + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_DAC_MC_CFG0_OFFSET, ReadReg); + InstancePtr->DAC_Tile[Tile_Id]. + DACBlock_Analog_Datapath[Index]. + NyquistZone = NyquistZone; + } + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Get the Nyquist zone. +* +* @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. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param NyquistZonePtr Pointer to return the Nyquist zone. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Common API for ADC/DAC blocks +* +******************************************************************************/ +u32 XRFdc_GetNyquistZone(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, + u32 Block_Id, u32 *NyquistZonePtr) +{ + u32 Status; + u16 ReadReg; + u32 BaseAddr; + u32 Block; + u8 CalibrationMode = 0U; + u8 MultibandConfig; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(NyquistZonePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + if (Type == XRFDC_ADC_TILE) { + MultibandConfig = InstancePtr->ADC_Tile[Tile_Id].MultibandConfig; + } else { + MultibandConfig = InstancePtr->DAC_Tile[Tile_Id].MultibandConfig; + } + + if (MultibandConfig != XRFDC_MB_MODE_SB) { + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, Type, + Tile_Id, Block_Id); + } else { + 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; + } + + Block = Block_Id; + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Block_Id == XRFDC_BLK_ID1) && (Type == XRFDC_ADC_TILE)) { + Block_Id = XRFDC_BLK_ID2; + } + + BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Block_Id); + + if (Type == XRFDC_ADC_TILE) { + /* Identify calibration mode */ + Status = XRFdc_GetCalibrationMode(InstancePtr, Tile_Id, + Block, &CalibrationMode); + if (Status != XRFDC_SUCCESS) { + return XRFDC_FAILURE; + } + ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_TI_TISK_CRL0_OFFSET, XRFDC_TI_TISK_ZONE_MASK); + *NyquistZonePtr = (ReadReg >> XRFDC_TISK_ZONE_SHIFT); + } else { + ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_DAC_MC_CFG0_OFFSET, XRFDC_MC_CFG0_MIX_MODE_MASK); + *NyquistZonePtr = (ReadReg >> XRFDC_MC_CFG0_MIX_MODE_SHIFT); + } + if (*NyquistZonePtr == 0U) { + *NyquistZonePtr = XRFDC_ODD_NYQUIST_ZONE; + } else { + *NyquistZonePtr = XRFDC_EVEN_NYQUIST_ZONE; + } + + if ((Type == XRFDC_ADC_TILE) && + (CalibrationMode == XRFDC_CALIB_MODE1)) { + if (*NyquistZonePtr == XRFDC_EVEN_NYQUIST_ZONE) { + *NyquistZonePtr = XRFDC_ODD_NYQUIST_ZONE; + } else { + *NyquistZonePtr = XRFDC_EVEN_NYQUIST_ZONE; + } + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is to set the DAC Datapath mode. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param Mode valid values are 0-3. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled / out of range. +* +* @note Only for DAC blocks +* +******************************************************************************/ +u32 XRFdc_SetDataPathMode(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 Mode) +{ + u32 Status = XRFDC_SUCCESS; + u32 BaseAddr; + u32 NyquistZone; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_DAC_TILE, Tile_Id, Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block not " + "available in %s\r\n", __func__); + return Status; + } + + if (Mode > XRFDC_DAC_MODE_MAX) { + metal_log(METAL_LOG_ERROR, "\n Invalid Mode " + "value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + return Status; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DAC_DATAPATH_OFFSET, + XRFDC_DATAPATH_MODE_MASK, Mode); + + NyquistZone = (Mode == XRFDC_DAC_MODE_7G_NQ2) ? + XRFDC_EVEN_NYQUIST_ZONE : XRFDC_ODD_NYQUIST_ZONE; + XRFdc_SetNyquistZone(InstancePtr, XRFDC_DAC_TILE, Tile_Id, Block_Id, NyquistZone); + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is to get the DAC Datapath mode. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param ModePtr pointer used to return value. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Only for DAC blocks +* +******************************************************************************/ +u32 XRFdc_GetDataPathMode(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 *ModePtr) +{ + u32 Status = XRFDC_SUCCESS; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + Xil_AssertNonvoid(ModePtr != NULL); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_DAC_TILE, Tile_Id, Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block not " + "available in %s\r\n", __func__); + return Status; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + *ModePtr = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_DAC_DATAPATH_OFFSET, + XRFDC_DATAPATH_MODE_MASK); + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is to set the DAC Image Reject Filter Pass mode. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param Mode valid values are 0 (for low pass) 1 (for high pass). +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled / bad parameter passed +* +* @note Only for DAC blocks +* +******************************************************************************/ +u32 XRFdc_SetIMRPassMode(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 Mode) +{ + u32 Status = XRFDC_SUCCESS; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_DAC_TILE, Tile_Id, Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block not " + "available in %s\r\n", __func__); + return Status; + } + + if (Mode > XRFDC_DAC_IMR_MODE_MAX) { + metal_log(METAL_LOG_ERROR, "\n Invalid Mode " + "value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + return Status; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DAC_DATAPATH_OFFSET, + XRFDC_DATAPATH_IMR_MASK, Mode << 2); + + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is to get the DAC Image Reject Filter Pass mode. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param ModePtr pointer used to return value. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Only for DAC blocks +* +******************************************************************************/ +u32 XRFdc_GetIMRPassMode(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 *ModePtr) +{ + u32 Status = XRFDC_SUCCESS; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + Xil_AssertNonvoid(ModePtr != NULL); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_DAC_TILE, Tile_Id, Block_Id); + if (Status != XRFDC_SUCCESS) { + metal_log(METAL_LOG_ERROR, "\n Requested block not " + "available in %s\r\n", __func__); + return Status; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + *ModePtr = (XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_DAC_DATAPATH_OFFSET, + XRFDC_DATAPATH_IMR_MASK)) >> 2; + return Status; +} +/*****************************************************************************/ +/** +* +* This API is to set the Calibration mode. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param CalibrationMode valid values are 1 and 2. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_SetCalibrationMode(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u8 CalibrationMode) +{ + u32 Status; + u16 ReadReg; + u32 BaseAddr; + u32 Index; + u32 NoOfBlocks; + XRFdc_Mixer_Settings Mixer_Settings = {0}; + u32 NyquistZone = 0U; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + if ((CalibrationMode != XRFDC_CALIB_MODE1) && + (CalibrationMode != XRFDC_CALIB_MODE2)) { + metal_log(METAL_LOG_ERROR, "\n Invalid Calibration mode " + "value in %s\r\n", __func__); + return XRFDC_FAILURE; + } + + Index = Block_Id; + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + 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; + } + + /* Get Mixer Configurations */ + Status = XRFdc_GetMixerSettings(InstancePtr, XRFDC_ADC_TILE, + Tile_Id, Block_Id, &Mixer_Settings); + if (Status != XRFDC_SUCCESS) { + return XRFDC_FAILURE; + } + + /* Get Nyquist Zone */ + Status = XRFdc_GetNyquistZone(InstancePtr, XRFDC_ADC_TILE, + Tile_Id, Block_Id, &NyquistZone); + if (Status != XRFDC_SUCCESS) { + return XRFDC_FAILURE; + } + + for (; Index < NoOfBlocks; Index++) { + BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) + + XRFDC_BLOCK_ADDR_OFFSET(Index); + ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TI_DCB_CRL0_OFFSET); + ReadReg &= ~XRFDC_TI_DCB_MODE_MASK; + if (CalibrationMode == XRFDC_CALIB_MODE1) { + if (((Index % 2U) != 0U) && + (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1)) { + ReadReg |= XRFDC_TI_DCB_MODE1_4GSPS; + } else if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) { + ReadReg |= XRFDC_TI_DCB_MODE1_2GSPS; + } + } + XRFdc_WriteReg16(InstancePtr, BaseAddr, + XRFDC_ADC_TI_DCB_CRL0_OFFSET, ReadReg); + InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Analog_Datapath[Index]. + CalibrationMode = CalibrationMode; + } + + /* Set Nyquist Zone */ + Status = XRFdc_SetNyquistZone(InstancePtr, XRFDC_ADC_TILE, + Tile_Id, Block_Id, NyquistZone); + if (Status != XRFDC_SUCCESS) { + return XRFDC_FAILURE; + } + + /* Set Mixer Configurations */ + Status = XRFdc_SetMixerSettings(InstancePtr, XRFDC_ADC_TILE, + Tile_Id, Block_Id, &Mixer_Settings); + if (Status != XRFDC_SUCCESS) { + return XRFDC_FAILURE; + } + + Status = XRFDC_SUCCESS; + + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is to get the Calibration mode. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is ADC/DAC block number inside the tile. Valid values +* are 0-3. +* @param CalibrationModePtr pointer to get the calibration mode. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_GetCalibrationMode(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u8 *CalibrationModePtr) +{ + u32 Status; + u16 ReadReg; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CalibrationModePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + if (InstancePtr->ADC_Tile[Tile_Id].MultibandConfig != XRFDC_MB_MODE_SB) { + Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, XRFDC_ADC_TILE, + Tile_Id, Block_Id); + } else { + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, + 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; + } + + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + if (Block_Id == XRFDC_BLK_ID1) { + Block_Id = XRFDC_BLK_ID3; + } + if (Block_Id == XRFDC_BLK_ID0) { + Block_Id = XRFDC_BLK_ID1; + } + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Block_Id); + ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_TI_DCB_CRL0_OFFSET, XRFDC_TI_DCB_MODE_MASK); + if (ReadReg != 0U) { + *CalibrationModePtr = XRFDC_CALIB_MODE1; + } else { + *CalibrationModePtr = XRFDC_CALIB_MODE2; + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is used to set the mode for the Inverse-Sinc filter. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is DAC block number inside the tile. Valid values +* are 0-3. +* @param Mode valid values are 0(disable), 1(1st Nyquist zone) + and 2(2nd Nyquist zone). +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled/invalid mode. +* +* @note Only DAC blocks +* +******************************************************************************/ +u32 XRFdc_SetInvSincFIR(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u16 Mode) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + if (Mode > ((InstancePtr->RFdc_Config.IPType < 2)?XRFDC_INV_SYNC_EN_MAX:XRFDC_INV_SYNC_MODE_MAX)) { + metal_log(METAL_LOG_ERROR, "\n Invalid mode " + "value in %s\r\n", __func__); + Status = XRFDC_FAILURE; + goto RETURN_PATH; + } + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_DAC_TILE, 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; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DAC_INVSINC_OFFSET, + (InstancePtr->RFdc_Config.IPType < 2)?XRFDC_EN_INVSINC_MASK:XRFDC_MODE_INVSINC_MASK, Mode); + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This API is used to get the Inverse-Sinc filter mode. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3. +* @param Block_Id is DAC block number inside the tile. Valid values +* are 0-3. +* @param ModePtr is a pointer to get the inv-sinc status. valid values +* are 0(disable), 1(1st Nyquist zone) and 2(2nd Nyquist zone). +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Block not enabled. +* +* @note Only DAC blocks +* +******************************************************************************/ +u32 XRFdc_GetInvSincFIR(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u16 *ModePtr) +{ + u32 Status; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + Xil_AssertNonvoid(ModePtr != NULL); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_DAC_TILE, 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; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, Block_Id); + *ModePtr = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_DAC_INVSINC_OFFSET, (InstancePtr->RFdc_Config.IPType < 2)?XRFDC_EN_INVSINC_MASK:XRFDC_MODE_INVSINC_MASK); + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Static API to dump ADC registers. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3, and -1. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XRFdc_DumpADCRegs(XRFdc *InstancePtr, int Tile_Id) +{ + u32 BlockId; + u32 Block; + u32 IsBlockAvail; + u32 Offset; + u32 BaseAddr; + u32 ReadReg = 0U; + + for (BlockId = XRFDC_BLK_ID0; BlockId < XRFDC_BLK_ID4; BlockId++) { + Block = BlockId; + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + if (BlockId == XRFDC_BLK_ID1) { + Block = XRFDC_BLK_ID0; + } + if ((BlockId == XRFDC_BLK_ID3) || (BlockId == XRFDC_BLK_ID2)) { + Block = XRFDC_BLK_ID1; + } + } + IsBlockAvail = XRFdc_IsADCBlockEnabled(InstancePtr, Tile_Id, + Block); + if (IsBlockAvail == 0U) { + IsBlockAvail = XRFdc_IsADCDigitalPathEnabled(InstancePtr, Tile_Id, + Block); + if (IsBlockAvail == 0U) { + continue; + } + } + metal_log(METAL_LOG_DEBUG, "\n ADC%d%d:: \r\n", Tile_Id, BlockId); + BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) + + XRFDC_BLOCK_ADDR_OFFSET(BlockId); + for (Offset = 0x0U; Offset <= 0x284U; Offset += 0x4U) { + if ((Offset >= 0x24U && Offset <= 0x2CU) || + (Offset >= 0x48U && Offset <= 0x7CU) || + (Offset >= 0xACU && Offset <= 0xC4U) || + (Offset >= 0x114U && Offset <= 0x13CU) || + (Offset >= 0x188U && Offset <= 0x194U) || + (Offset >= 0x1B8U && Offset <= 0x1BCU) || + (Offset >= 0x1D8U && Offset <= 0x1FCU) || + (Offset >= 0x240U && Offset <= 0x27CU)) { + continue; + } + ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, Offset); + metal_log(METAL_LOG_DEBUG, + "\n offset = 0x%x and Value = 0x%x \t", + Offset, ReadReg); + } + } + (void)ReadReg; +} + +/*****************************************************************************/ +/** +* +* Static API to dump DAC registers. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id Valid values are 0-3, and -1. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XRFdc_DumpDACRegs(XRFdc *InstancePtr, int Tile_Id) +{ + u32 BlockId; + u32 IsBlockAvail; + u32 Offset; + u32 BaseAddr; + u32 ReadReg = 0U; + + for (BlockId = XRFDC_BLK_ID0; BlockId < XRFDC_BLK_ID4; BlockId++) { + IsBlockAvail = XRFdc_IsDACBlockEnabled(InstancePtr, Tile_Id, + BlockId); + if (IsBlockAvail == 0U) { + IsBlockAvail = XRFdc_IsDACDigitalPathEnabled(InstancePtr, Tile_Id, + BlockId); + if (IsBlockAvail == 0U) { + continue; + } + } + metal_log(METAL_LOG_DEBUG, "\n DAC%d%d:: \r\n", Tile_Id, BlockId); + BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) + + XRFDC_BLOCK_ADDR_OFFSET(BlockId); + for (Offset = 0x0U; Offset <= 0x24CU; Offset += 0x4U) { + if ((Offset >= 0x28U && Offset <= 0x34U) || + (Offset >= 0x48U && Offset <= 0x7CU) || + (Offset >= 0xA8U && Offset <= 0xBCU) || + (Offset >= 0xE4U && Offset <= 0xFCU) || + (Offset >= 0x16CU && Offset <= 0x17CU) || + (Offset >= 0x198U && Offset <= 0x1BCU) || + (Offset >= 0x1ECU && Offset <= 0x1FCU) || + (Offset >= 0x204U && Offset <= 0x23CU)) { + continue; + } + ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, Offset); + metal_log(METAL_LOG_DEBUG, + "\n offset = 0x%x and Value = 0x%x \t", + Offset, ReadReg); + } + } + (void)ReadReg; +} + +/*****************************************************************************/ +/** +* +* Static API to dump HSCOM registers. +* +* @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. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XRFdc_DumpHSCOMRegs(XRFdc *InstancePtr, u32 Type, int Tile_Id) +{ + u32 Offset; + u32 BaseAddr; + u32 ReadReg = 0U; + + if (Type == XRFDC_ADC_TILE) { + metal_log(METAL_LOG_DEBUG, "\n ADC%d HSCOM:: \r\n", Tile_Id); + BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) + XRFDC_HSCOM_ADDR; + + } else { + metal_log(METAL_LOG_DEBUG, "\n DAC%d HSCOM:: \r\n", Tile_Id); + BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) + XRFDC_HSCOM_ADDR; + } + metal_log(METAL_LOG_DEBUG, "\n Offset\tValue \r\n"); + for (Offset = 0x0U; Offset <= 0x148U; Offset += 0x4U) { + if ((Offset >= 0x60U && Offset <= 0x88U) || + (Offset == 0xBCU) || + (Offset >= 0xC4U && Offset <= 0xFCU) || + (Offset >= 0x110U && Offset <= 0x11CU) || + (Offset >= 0x12CU && Offset <= 0x13CU)) { + continue; + } + ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, Offset); + metal_log(METAL_LOG_DEBUG, "\n 0x%x \t 0x%x \t", + Offset, ReadReg); + } + (void)ReadReg; +} + +/*****************************************************************************/ +/** +* +* This Prints the offset of the register along with the content. This API is +* meant to be used for debug purposes. It prints to the console the contents +* of registers for the passed Tile_Id. If -1 is passed, it prints the contents +* of the registers for all the tiles for the respective ADC or DAC +* +* @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. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +void XRFdc_DumpRegs(XRFdc *InstancePtr, u32 Type, int Tile_Id) +{ + u16 NoOfTiles; + u16 Index; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + if (Tile_Id == XRFDC_SELECT_ALL_TILES) { + NoOfTiles = XRFDC_NUM_OF_TILES4; + } else { + NoOfTiles = XRFDC_NUM_OF_TILES1; + } + for (Index = XRFDC_TILE_ID0; Index < NoOfTiles; Index++) { + if (NoOfTiles == XRFDC_NUM_OF_TILES4) { + Tile_Id = Index; + } + if (Type == XRFDC_ADC_TILE) { + XRFdc_DumpADCRegs(InstancePtr, Tile_Id); + } else { + XRFdc_DumpDACRegs(InstancePtr, Tile_Id); + } + XRFdc_DumpHSCOMRegs(InstancePtr, Type, Tile_Id); + } +} + +/*****************************************************************************/ +/** +* +* This is a stub for the status callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRefPtr is a pointer to the upper layer callback reference. +* @param Type indicates ADC/DAC. +* @param Tile_Id indicates Tile number (0-3). +* @param Block_Id indicates Block number (0-3). +* @param StatusEvent indicates one or more interrupt occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubHandler(void *CallBackRefPtr, u32 Type, u32 Tile_Id, + u32 Block_Id, u32 StatusEvent) +{ + (void) ((void *)CallBackRefPtr); + (void) Type; + (void) Tile_Id; + (void) Block_Id; + (void) StatusEvent; + + Xil_AssertVoidAlways(); + +} +/*****************************************************************************/ +/** +* +* This function is used to get the Link Coupling mode. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id indicates Tile number (0-3). +* @param Block_Id indicates Block number(0-3 for 2G, 0-1 for 4G). +* @param ModePtr pointer to get link coupling mode. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_GetLinkCoupling(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 *ModePtr) +{ + u32 Status; + u16 ReadReg; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ModePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Block_Id == XRFDC_BLK_ID1)) { + Block_Id = XRFDC_BLK_ID2; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Block_Id); + + ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_RXPR_MC_CFG0_OFFSET, XRFDC_RX_MC_CFG0_CM_MASK); + if (ReadReg != 0U) { + *ModePtr = XRFDC_LINK_COUPLING_AC; + } else { + *ModePtr = XRFDC_LINK_COUPLING_DC; + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function is used to set the IM3 Dither mode. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id indicates Tile number (0-3). +* @param Block_Id indicates Block number(0-3 for LS, 0-1 for HS). +* @param Mode 0: Disable +* 1: Enable +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_SetDither(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 Mode) +{ + u32 Status; + u32 BaseAddr; + u32 Index; + u32 NoOfBlocks; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + + if (Mode > XRFDC_DITH_ENABLE) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, "\n Invalid Dither Mode " + "in %s\r\n", __func__); + goto RETURN_PATH; + } + Index = Block_Id; + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + 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++) { + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Index); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, + XRFDC_ADC_DAC_MC_CFG0_OFFSET, XRFDC_RX_MC_CFG0_IM3_DITH_MASK, + (Mode << XRFDC_RX_MC_CFG0_IM3_DITH_SHIFT)); + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function is used to get the IM3 Dither mode. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id indicates Tile number (0-3). +* @param Block_Id indicates Block number(0-3 for LS, 0-1 for HS). +* @param ModePtr pointer to get link coupling mode. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_GetDither(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, + u32 *ModePtr) +{ + u32 Status; + u16 ReadReg; + u32 BaseAddr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ModePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && + (Block_Id == XRFDC_BLK_ID1)) { + Block_Id = XRFDC_BLK_ID2; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Block_Id); + + ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, + XRFDC_ADC_DAC_MC_CFG0_OFFSET, XRFDC_RX_MC_CFG0_IM3_DITH_MASK); + if (ReadReg != 0U) { + *ModePtr = XRFDC_DITH_ENABLE; + } else { + *ModePtr = XRFDC_DITH_DISABLE; + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} +/*****************************************************************************/ +/** +* +* This function is used to set the ADC Signal Detector Settings. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id indicates Tile number (0-3). +* @param Block_Id indicates Block number(0-3 for LS, 0-1 for HS). +* @param SettingsPtr pointer to the XRFdc_Signal_Detector_Settings structure +* to set the signal detector configurations +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled, or invaid values. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_SetSignalDetector(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, XRFdc_Signal_Detector_Settings *SettingsPtr) +{ + u32 Status; + u32 BaseAddr; + u32 Index; + u32 NoOfBlocks; + u16 SignalDetCtrlReg = 0; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SettingsPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + if (InstancePtr->RFdc_Config.IPType < 2) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Requested fuctionality not " + "available for this IP in %s\r\n", + __func__); + goto RETURN_PATH; + } + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + if (SettingsPtr->Mode > XRFDC_SIGDET_MODE_RNDM) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Invalid Signal Detector " + "Mode in %s\r\n", + __func__); + goto RETURN_PATH; + } + if (SettingsPtr->EnableIntegrator > XRFDC_ENABLED) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Invalid Signal Detector " + "Integrator Enable in %s\r\n", + __func__); + goto RETURN_PATH; + } + if (SettingsPtr->HysteresisEnable > XRFDC_ENABLED) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Invalid Signal Detector " + "Hysteresis Enable in %s\r\n", + __func__); + goto RETURN_PATH; + } + if (SettingsPtr->Flush > XRFDC_ENABLED) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Invalid Signal Detector " + "Flush Option in %s\r\n", + __func__); + goto RETURN_PATH; + } + if (SettingsPtr->TimeConstant > XRFDC_SIGDET_TC_2_18) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Invalid Signal Detector " + "Time Constant in %s\r\n", + __func__); + goto RETURN_PATH; + } + SignalDetCtrlReg |= SettingsPtr->EnableIntegrator << XRFDC_ADC_SIG_DETECT_INTG_SHIFT; + SignalDetCtrlReg |= SettingsPtr->Flush << XRFDC_ADC_SIG_DETECT_FLUSH_SHIFT; + SignalDetCtrlReg |= SettingsPtr->TimeConstant << XRFDC_ADC_SIG_DETECT_TCONST_SHIFT; + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + SignalDetCtrlReg |= ((SettingsPtr->Mode << 1) | 1) << XRFDC_ADC_SIG_DETECT_MODE_WRITE_SHIFT; + } else { + SignalDetCtrlReg |= (SettingsPtr->Mode << 1) << XRFDC_ADC_SIG_DETECT_MODE_WRITE_SHIFT; + } + SignalDetCtrlReg |= SettingsPtr->HysteresisEnable << XRFDC_ADC_SIG_DETECT_HYST_SHIFT; + + Index = Block_Id; + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + 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++) { + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Index); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_SIG_DETECT_CTRL_OFFSET, XRFDC_ADC_SIG_DETECT_MASK, + SignalDetCtrlReg); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_SIG_DETECT_THRESHOLD0_LEVEL_OFFSET, + XRFDC_ADC_SIG_DETECT_THRESH_MASK, SettingsPtr->HighThreshold); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_SIG_DETECT_THRESHOLD1_LEVEL_OFFSET, + XRFDC_ADC_SIG_DETECT_THRESH_MASK, SettingsPtr->LowThreshold); + } + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function is used to get the ADC Signal Detector Settings. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id indicates Tile number (0-3). +* @param Block_Id indicates Block number(0-3 for LS, 0-1 for HS). +* @param SettingsPtr pointer to the XRFdc_Signal_Detector_Settings structure +* to get the signal detector configurations +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if Tile not enabled. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_GetSignalDetector(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, XRFdc_Signal_Detector_Settings *SettingsPtr) +{ + u32 Status; + u32 BaseAddr; + u16 SignalDetCtrlReg = 0; + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SettingsPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + if (InstancePtr->RFdc_Config.IPType < 2) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Requested functionality not " + "available for this IP in %s\r\n", + __func__); + goto RETURN_PATH; + } + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + + if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) && (Block_Id == XRFDC_BLK_ID1)) { + Block_Id = XRFDC_BLK_ID2; + } + + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Block_Id); + + SignalDetCtrlReg = + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_ADC_SIG_DETECT_CTRL_OFFSET, XRFDC_ADC_SIG_DETECT_MASK); + SettingsPtr->EnableIntegrator = + (SignalDetCtrlReg & XRFDC_ADC_SIG_DETECT_INTG_MASK) >> XRFDC_ADC_SIG_DETECT_INTG_SHIFT; + SettingsPtr->Flush = (SignalDetCtrlReg & XRFDC_ADC_SIG_DETECT_FLUSH_MASK) >> XRFDC_ADC_SIG_DETECT_FLUSH_SHIFT; + SettingsPtr->TimeConstant = + (SignalDetCtrlReg & XRFDC_ADC_SIG_DETECT_TCONST_MASK) >> XRFDC_ADC_SIG_DETECT_TCONST_SHIFT; + SettingsPtr->Mode = (SignalDetCtrlReg & XRFDC_ADC_SIG_DETECT_MODE_MASK) >> XRFDC_ADC_SIG_DETECT_MODE_READ_SHIFT; + + SettingsPtr->HysteresisEnable = + (SignalDetCtrlReg & XRFDC_ADC_SIG_DETECT_HYST_MASK) >> XRFDC_ADC_SIG_DETECT_HYST_SHIFT; + SettingsPtr->HighThreshold = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_ADC_SIG_DETECT_THRESHOLD0_LEVEL_OFFSET, + XRFDC_ADC_SIG_DETECT_THRESH_MASK); + SettingsPtr->LowThreshold = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_ADC_SIG_DETECT_THRESHOLD1_LEVEL_OFFSET, + XRFDC_ADC_SIG_DETECT_THRESH_MASK); + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} +/*****************************************************************************/ +/** +* +* This function is used to disable Calibration Coefficients override. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id indicates Tile number (0-3). +* @param Block_Id indicates Block number(0-3 for LS, 0-1 for HS). +* @param CalibrationBlock indicates the calibration block. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if error occurs. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_DisableCoefficientsOverride(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, u32 CalibrationBlock) +{ + u32 BaseAddr; + u32 Status; + u32 Index; + u32 NoOfBlocks; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + + if ((InstancePtr->RFdc_Config.IPType < 2) && (CalibrationBlock == XRFDC_CAL_BLOCK_OCB1)) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Requested functionality not " + "available for this IP in %s\r\n", + __func__); + goto RETURN_PATH; + } + + Index = Block_Id; + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + 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++) { + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Index); + switch (CalibrationBlock) { + case XRFDC_CAL_BLOCK_OCB1: + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_TI_DCB_CRL1_OFFSET, XRFDC_CAL_OCB_EN_MASK, + XRFDC_DISABLED); + break; + case XRFDC_CAL_BLOCK_OCB2: + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_TI_DCB_CRL3_OFFSET, XRFDC_CAL_OCB_EN_MASK, + XRFDC_DISABLED); + break; + case XRFDC_CAL_BLOCK_GCB: + if (InstancePtr->RFdc_Config.IPType < 2) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_TI_DCB_CRL1_OFFSET, + XRFDC_CAL_GCB_ENFL_MASK, XRFDC_CAL_GCB_ACEN_MASK); + /*Clear IP Override Coeffs*/ + XRFdc_ClrSetReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF0_FAB(Index), XRFDC_CAL_GCB_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF1_FAB(Index), XRFDC_CAL_GCB_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF2_FAB(Index), XRFDC_CAL_GCB_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF3_FAB(Index), XRFDC_CAL_GCB_MASK, XRFDC_DISABLED); + } else { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_TI_DCB_CRL2_OFFSET, + XRFDC_CAL_GCB_EN_MASK, XRFDC_DISABLED); + } + break; + case XRFDC_CAL_BLOCK_TSCB: + if (InstancePtr->RFdc_Config.IPType < 2) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF0_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF1_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF2_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF3_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF4_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF5_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF6_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF7_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + } else { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF0, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF1, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF2, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF3, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF4, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF5, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF6, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF7, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_DISABLED); + } + break; + default: + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Invalid Calibration " + "Mode in %s\r\n", + __func__); + goto RETURN_PATH; + } + } + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} +/*****************************************************************************/ +/** +* +* This function is used to set the ADC Calibration Coefficients. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id indicates Tile number (0-3). +* @param Block_Id indicates Block number(0-3 for LS, 0-1 for HS). +* @param CalibrationBlock indicates the block to be written to. +* @param CoeffPtr is pointer to the XRFdc_Calibration_Coefficients structure +* to set the calibration coefficients. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if error occurs. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_SetCalCoefficients(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, u32 CalibrationBlock, + XRFdc_Calibration_Coefficients *CoeffPtr) +{ + u32 BaseAddr; + u32 Status; + u32 Index; + u32 NoOfBlocks; + u32 HighSpeed; + u32 Shift; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CoeffPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + if ((InstancePtr->RFdc_Config.IPType < 2) && (CalibrationBlock == XRFDC_CAL_BLOCK_OCB1)) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Requested functionality not " + "available for this IP in %s\r\n", + __func__); + goto RETURN_PATH; + } + + if (CalibrationBlock == XRFDC_CAL_BLOCK_GCB) { + if ((CoeffPtr->Coeff0 | CoeffPtr->Coeff1 | CoeffPtr->Coeff2 | CoeffPtr->Coeff3) & + ~(XRFDC_CAL_GCB_MASK | (XRFDC_CAL_GCB_MASK << XRFDC_CAL_SLICE_SHIFT))) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Bad Coefficient " + "available for this IP in %s\r\n", + __func__); + goto RETURN_PATH; + } + } + + if (CalibrationBlock == XRFDC_CAL_BLOCK_TSCB) { + if ((CoeffPtr->Coeff0 | CoeffPtr->Coeff1 | CoeffPtr->Coeff2 | CoeffPtr->Coeff3 | CoeffPtr->Coeff4 | + CoeffPtr->Coeff5 | CoeffPtr->Coeff6 | CoeffPtr->Coeff7) & + ~(XRFDC_CAL_TSCB_MASK | (XRFDC_CAL_TSCB_MASK << XRFDC_CAL_SLICE_SHIFT))) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Bad Coefficient " + "available for this IP in %s\r\n", + __func__); + goto RETURN_PATH; + } + } + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + HighSpeed = XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id); + if (HighSpeed == XRFDC_ENABLED) { + 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++) { + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Index); + Shift = HighSpeed ? XRFDC_CAL_SLICE_SHIFT * (Index % 2) : 0; + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Index); + switch (CalibrationBlock) { + case XRFDC_CAL_BLOCK_OCB1: + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_TI_DCB_CRL1_OFFSET, XRFDC_CAL_OCB_EN_MASK, + XRFDC_ENABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB1_OFFSET_COEFF0, XRFDC_CAL_OCB_MASK, + CoeffPtr->Coeff0 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB1_OFFSET_COEFF1, XRFDC_CAL_OCB_MASK, + CoeffPtr->Coeff1 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB1_OFFSET_COEFF2, XRFDC_CAL_OCB_MASK, + CoeffPtr->Coeff2 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB1_OFFSET_COEFF3, XRFDC_CAL_OCB_MASK, + CoeffPtr->Coeff3 >> Shift); + break; + case XRFDC_CAL_BLOCK_OCB2: + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_TI_DCB_CRL3_OFFSET, XRFDC_CAL_OCB_EN_MASK, + XRFDC_ENABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB2_OFFSET_COEFF0, XRFDC_CAL_OCB_MASK, + CoeffPtr->Coeff0 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB2_OFFSET_COEFF1, XRFDC_CAL_OCB_MASK, + CoeffPtr->Coeff1 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB2_OFFSET_COEFF2, XRFDC_CAL_OCB_MASK, + CoeffPtr->Coeff2 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB2_OFFSET_COEFF3, XRFDC_CAL_OCB_MASK, + CoeffPtr->Coeff3 >> Shift); + break; + case XRFDC_CAL_BLOCK_GCB: + + if (InstancePtr->RFdc_Config.IPType < 2) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_TI_DCB_CRL1_OFFSET, + XRFDC_CAL_GCB_ACEN_MASK, XRFDC_DISABLED); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_TI_DCB_CRL1_OFFSET, + XRFDC_CAL_GCB_FLSH_MASK, XRFDC_ENABLED << XRFDC_CAL_GCB_FLSH_SHIFT); + XRFdc_ClrSetReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF0_FAB(Index), XRFDC_CAL_GCB_MASK, + CoeffPtr->Coeff0 >> Shift); + XRFdc_ClrSetReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF1_FAB(Index), XRFDC_CAL_GCB_MASK, + CoeffPtr->Coeff1 >> Shift); + XRFdc_ClrSetReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF2_FAB(Index), XRFDC_CAL_GCB_MASK, + CoeffPtr->Coeff2 >> Shift); + XRFdc_ClrSetReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF3_FAB(Index), XRFDC_CAL_GCB_MASK, + CoeffPtr->Coeff3 >> Shift); + } else { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_TI_DCB_CRL2_OFFSET, + XRFDC_CAL_GCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_GCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF0, XRFDC_CAL_GCB_MASK, + CoeffPtr->Coeff0 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF1, XRFDC_CAL_GCB_MASK, + CoeffPtr->Coeff1 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF2, XRFDC_CAL_GCB_MASK, + CoeffPtr->Coeff2 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF3, XRFDC_CAL_GCB_MASK, + CoeffPtr->Coeff3 >> Shift); + } + break; + case XRFDC_CAL_BLOCK_TSCB: + if (InstancePtr->RFdc_Config.IPType < 2) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF0_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF1_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF2_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF3_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF4_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF5_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF6_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF7_ALT, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF0_ALT, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff0 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF1_ALT, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff1); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF2_ALT, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff2 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF3_ALT, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff3 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF4_ALT, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff4 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF5_ALT, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff5 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF6_ALT, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff6 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF7_ALT, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff7 >> Shift); + } else { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF0, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF1, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF2, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF3, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF4, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF5, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF6, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF7, + XRFDC_CAL_TSCB_EN_MASK, XRFDC_ENABLED << XRFDC_CAL_TSCB_EN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF0, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff0 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF1, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff1 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF2, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff2 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF3, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff3 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF4, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff4 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF5, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff5 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF6, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff6 >> Shift); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF7, + XRFDC_CAL_TSCB_MASK, CoeffPtr->Coeff7 >> Shift); + } + break; + default: + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Invalid Calibration " + "Mode in %s\r\n", + __func__); + goto RETURN_PATH; + } + } + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} +/*****************************************************************************/ +/** +* +* This function is used to get the ADC Calibration Coefficients. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id indicates Tile number (0-3). +* @param Block_Id indicates Block number(0-3 for LS, 0-1 for HS). +* @param CalibrationBlock indicates the block to be read from +* @param CoeffPtr is pointer to the XRFdc_Calibration_Coefficients structure +* to get the calibration coefficients. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if error occurs. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_GetCalCoefficients(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, u32 CalibrationBlock, + XRFdc_Calibration_Coefficients *CoeffPtr) +{ + u32 BaseAddr; + u32 Status; + u32 Index; + u32 HighSpeed; + u32 Shift; + u32 NoOfBlocks; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CoeffPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + + memset(CoeffPtr, 0, sizeof(XRFdc_Calibration_Coefficients)); + Index = Block_Id; + HighSpeed = XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id); + if (HighSpeed == XRFDC_ENABLED) { + 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++) { + BaseAddr = XRFDC_BLOCK_BASE(XRFDC_ADC_TILE, Tile_Id, Index); + Shift = HighSpeed ? XRFDC_CAL_SLICE_SHIFT * (Index % 2) : 0; + switch (CalibrationBlock) { + case XRFDC_CAL_BLOCK_OCB1: + CoeffPtr->Coeff0 |= + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB1_OFFSET_COEFF0, XRFDC_CAL_OCB_MASK) + << Shift; + CoeffPtr->Coeff1 |= + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB1_OFFSET_COEFF1, XRFDC_CAL_OCB_MASK) + << Shift; + CoeffPtr->Coeff2 |= + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB1_OFFSET_COEFF2, XRFDC_CAL_OCB_MASK) + << Shift; + CoeffPtr->Coeff3 |= + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB1_OFFSET_COEFF3, XRFDC_CAL_OCB_MASK) + << Shift; + break; + case XRFDC_CAL_BLOCK_OCB2: + CoeffPtr->Coeff0 |= + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB2_OFFSET_COEFF0, XRFDC_CAL_OCB_MASK) + << Shift; + CoeffPtr->Coeff1 |= + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB2_OFFSET_COEFF1, XRFDC_CAL_OCB_MASK) + << Shift; + CoeffPtr->Coeff2 |= + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB2_OFFSET_COEFF2, XRFDC_CAL_OCB_MASK) + << Shift; + CoeffPtr->Coeff3 |= + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_OCB2_OFFSET_COEFF3, XRFDC_CAL_OCB_MASK) + << Shift; + break; + case XRFDC_CAL_BLOCK_GCB: + if (InstancePtr->RFdc_Config.IPType < 2) { + if (XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_ADC_TI_DCB_CRL1_OFFSET, + XRFDC_CAL_GCB_FLSH_MASK) == XRFDC_DISABLED) { + CoeffPtr->Coeff0 |= + (XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF0_ALT, + XRFDC_CAL_GCB_FAB_MASK) >> + 4) + << Shift; + CoeffPtr->Coeff1 |= + (XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF1_ALT, + XRFDC_CAL_GCB_FAB_MASK) >> + 4) + << Shift; + CoeffPtr->Coeff2 |= + (XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF2_ALT, + XRFDC_CAL_GCB_FAB_MASK) >> + 4) + << Shift; + CoeffPtr->Coeff3 |= + (XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF3_ALT, + XRFDC_CAL_GCB_FAB_MASK) >> + 4) + << Shift; + } else { + CoeffPtr->Coeff0 |= + XRFdc_RDReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF0_FAB(Block_Id), XRFDC_CAL_GCB_MASK) + << Shift; + CoeffPtr->Coeff1 |= + XRFdc_RDReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF1_FAB(Block_Id), XRFDC_CAL_GCB_MASK) + << Shift; + CoeffPtr->Coeff2 |= + XRFdc_RDReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF2_FAB(Block_Id), XRFDC_CAL_GCB_MASK) + << Shift; + CoeffPtr->Coeff3 |= + XRFdc_RDReg(InstancePtr, XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id), + XRFDC_CAL_GCB_COEFF3_FAB(Block_Id), XRFDC_CAL_GCB_MASK) + << Shift; + } + } else { + CoeffPtr->Coeff0 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF0, + XRFDC_CAL_GCB_MASK) + << Shift; + CoeffPtr->Coeff1 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF1, + XRFDC_CAL_GCB_MASK) + << Shift; + CoeffPtr->Coeff2 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF2, + XRFDC_CAL_GCB_MASK) + << Shift; + CoeffPtr->Coeff3 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_GCB_OFFSET_COEFF3, + XRFDC_CAL_GCB_MASK) + << Shift; + } + break; + case XRFDC_CAL_BLOCK_TSCB: + if (InstancePtr->RFdc_Config.IPType < 2) { + CoeffPtr->Coeff0 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF0_ALT, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff1 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF1_ALT, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff2 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF2_ALT, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff3 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF3_ALT, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff4 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF4_ALT, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff5 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF5_ALT, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff6 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF6_ALT, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff7 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF7_ALT, + XRFDC_CAL_TSCB_MASK) + << Shift; + } else { + CoeffPtr->Coeff0 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF0, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff1 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF1, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff2 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF2, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff3 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF3, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff4 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF4, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff5 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF5, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff6 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF6, + XRFDC_CAL_TSCB_MASK) + << Shift; + CoeffPtr->Coeff7 |= XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CAL_TSCB_OFFSET_COEFF7, + XRFDC_CAL_TSCB_MASK) + << Shift; + } + break; + default: + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Invalid Calibration " + "Mode in %s\r\n", + __func__); + goto RETURN_PATH; + } + } + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} +/*****************************************************************************/ +/** +* +* This function is used to set calibration freeze settings. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id indicates Tile number (0-3). +* @param Block_Id indicates Block number(0-3 for LS, 0-1 for HS). +* @param CalFreezePtr pointer to the settings to be applied. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if error occurs. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_SetCalFreeze(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, XRFdc_Cal_Freeze_Settings *CalFreezePtr) +{ + u32 BaseAddr; + u32 Status; + u32 Index; + u32 NoOfBlocks; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CalFreezePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + if (CalFreezePtr->FreezeCalibration > XRFDC_CAL_FREEZE_CALIB) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Invalid FreezeCalibration " + "option in %s\r\n", + __func__); + goto RETURN_PATH; + } + + if (CalFreezePtr->DisableFreezePin > XRFDC_CAL_FRZ_PIN_DISABLE) { + Status = XRFDC_FAILURE; + metal_log(METAL_LOG_ERROR, + "\n Invalid DisableFreezePin " + "option in %s\r\n", + __func__); + goto RETURN_PATH; + } + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + + BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id); + + Index = Block_Id; + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + 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++) { + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CONV_CAL_STGS(Index), XRFDC_CAL_FREEZE_PIN_MASK, + CalFreezePtr->DisableFreezePin << XRFDC_CAL_FREEZE_PIN_SHIFT); + XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CONV_CAL_STGS(Index), XRFDC_CAL_FREEZE_CAL_MASK, + CalFreezePtr->FreezeCalibration << XRFDC_CAL_FREEZE_CAL_SHIFT); + } + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} +/*****************************************************************************/ +/** +* +* This function is used to get calibration freeze settings and status. +* +* @param InstancePtr is a pointer to the XRfdc instance. +* @param Tile_Id indicates Tile number (0-3). +* @param Block_Id indicates Block number(0-3 for LS, 0-1 for HS). +* @param CalFreezePtr pointer to be filled the settings/status. +* +* @return +* - XRFDC_SUCCESS if successful. +* - XRFDC_FAILURE if error occurs. +* +* @note Only for ADC blocks +* +******************************************************************************/ +u32 XRFdc_GetCalFreeze(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, XRFdc_Cal_Freeze_Settings *CalFreezePtr) +{ + u32 BaseAddr; + u32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CalFreezePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY); + + Status = XRFdc_CheckBlockEnabled(InstancePtr, XRFDC_ADC_TILE, 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; + } + + BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id); + + if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) { + if (Block_Id == XRFDC_BLK_ID1) { + Block_Id = XRFDC_BLK_ID2; + } + } + CalFreezePtr->CalFrozen = + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CONV_CAL_STGS(Block_Id), XRFDC_CAL_FREEZE_STS_MASK) >> + XRFDC_CAL_FREEZE_STS_SHIFT; + CalFreezePtr->DisableFreezePin = + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CONV_CAL_STGS(Block_Id), XRFDC_CAL_FREEZE_PIN_MASK) >> + XRFDC_CAL_FREEZE_PIN_SHIFT; + CalFreezePtr->FreezeCalibration = + XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_CONV_CAL_STGS(Block_Id), XRFDC_CAL_FREEZE_CAL_MASK) >> + XRFDC_CAL_FREEZE_CAL_SHIFT; + + Status = XRFDC_SUCCESS; +RETURN_PATH: + return Status; +} +/** @} */ |