aboutsummaryrefslogtreecommitdiffstats
path: root/mpm/lib/rfdc
diff options
context:
space:
mode:
authorLars Amsel <lars.amsel@ni.com>2021-06-04 08:27:50 +0200
committerAaron Rossetto <aaron.rossetto@ni.com>2021-06-10 12:01:53 -0500
commit2a575bf9b5a4942f60e979161764b9e942699e1e (patch)
tree2f0535625c30025559ebd7494a4b9e7122550a73 /mpm/lib/rfdc
parente17916220cc955fa219ae37f607626ba88c4afe3 (diff)
downloaduhd-2a575bf9b5a4942f60e979161764b9e942699e1e.tar.gz
uhd-2a575bf9b5a4942f60e979161764b9e942699e1e.tar.bz2
uhd-2a575bf9b5a4942f60e979161764b9e942699e1e.zip
uhd: Add support for the USRP X410
Co-authored-by: Lars Amsel <lars.amsel@ni.com> Co-authored-by: Michael Auchter <michael.auchter@ni.com> Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Paul Butler <paul.butler@ni.com> Co-authored-by: Cristina Fuentes <cristina.fuentes-curiel@ni.com> Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com> Co-authored-by: Virendra Kakade <virendra.kakade@ni.com> Co-authored-by: Lane Kolbly <lane.kolbly@ni.com> Co-authored-by: Max Köhler <max.koehler@ni.com> Co-authored-by: Andrew Lynch <andrew.lynch@ni.com> Co-authored-by: Grant Meyerhoff <grant.meyerhoff@ni.com> Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com> Co-authored-by: Thomas Vogel <thomas.vogel@ni.com>
Diffstat (limited to 'mpm/lib/rfdc')
-rw-r--r--mpm/lib/rfdc/CMakeLists.txt19
-rw-r--r--mpm/lib/rfdc/README.md6
-rw-r--r--mpm/lib/rfdc/patches/xrfdc.h.patch53
-rw-r--r--mpm/lib/rfdc/patches/xrfdc_sinit.c.patch10
-rw-r--r--mpm/lib/rfdc/rfdc_ctrl.cpp745
-rw-r--r--mpm/lib/rfdc/rfdc_throw.cpp24
-rw-r--r--mpm/lib/rfdc/xrfdc.c5345
-rw-r--r--mpm/lib/rfdc/xrfdc_clock.c1801
-rw-r--r--mpm/lib/rfdc/xrfdc_g.c619
-rw-r--r--mpm/lib/rfdc/xrfdc_intr.c771
-rw-r--r--mpm/lib/rfdc/xrfdc_mb.c786
-rw-r--r--mpm/lib/rfdc/xrfdc_mixer.c1091
-rw-r--r--mpm/lib/rfdc/xrfdc_mts.c1308
-rw-r--r--mpm/lib/rfdc/xrfdc_sinit.c272
14 files changed, 12850 insertions, 0 deletions
diff --git a/mpm/lib/rfdc/CMakeLists.txt b/mpm/lib/rfdc/CMakeLists.txt
new file mode 100644
index 000000000..a7401fd7b
--- /dev/null
+++ b/mpm/lib/rfdc/CMakeLists.txt
@@ -0,0 +1,19 @@
+#
+# Copyright 2019 Ettus Research, National Instruments Brand
+#
+# SPDX-License-Identifier: GPL-3.0
+#
+set(RFDC_SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/rfdc_ctrl.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/rfdc_throw.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/xrfdc_clock.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/xrfdc_g.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/xrfdc_intr.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/xrfdc_mb.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/xrfdc_mixer.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/xrfdc_mts.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/xrfdc_sinit.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/xrfdc.c
+)
+
+USRP_PERIPHS_ADD_OBJECT(rfdc ${RFDC_SOURCES})
diff --git a/mpm/lib/rfdc/README.md b/mpm/lib/rfdc/README.md
new file mode 100644
index 000000000..ecf4fc054
--- /dev/null
+++ b/mpm/lib/rfdc/README.md
@@ -0,0 +1,6 @@
+The `xrfdc*.c` files here (and the files `mpm/include/mpm/rfdc/xrfdc*.h`) are derived from files in the `xilinx-v2019.1` tag of [embeddedsw](https://github.com/Xilinx/embeddedsw/), with the following changes:
+* Include paths
+* `Xil_Assert` macros in `xrfdc.h` were replaced with custom functionality.
+ * See `patches/xrfdc.h.patch` for the patch applied to that file.
+* Call `closedir` in `xrfdc_sinit.c`
+ * See `patches/xrfdc_sinic.c.patch` for the patch
diff --git a/mpm/lib/rfdc/patches/xrfdc.h.patch b/mpm/lib/rfdc/patches/xrfdc.h.patch
new file mode 100644
index 000000000..d2fceb13a
--- /dev/null
+++ b/mpm/lib/rfdc/patches/xrfdc.h.patch
@@ -0,0 +1,53 @@
+--- embeddedsw/XilinxProcessorIPLib/drivers/rfdc/src/xrfdc.h 2020-07-16 16:23:14.839402600 -0500
++++ uhddev/mpm/include/mpm/rfdc/xrfdc.h 2020-08-17 12:31:24.477432400 -0500
+@@ -235,6 +235,7 @@
+
+ /***************************** Include Files *********************************/
+
++#include "rfdc_throw.h"
+ #include <stdlib.h>
+ #include <stdint.h>
+
+@@ -650,24 +651,24 @@
+
+ /***************** Macros (Inline Functions) Definitions *********************/
+
+-#ifndef __BAREMETAL__
+-#define Xil_AssertNonvoid(Expression) \
+-{ \
+- if (!(Expression)) { \
+- while (1); \
+- } \
+-}
+-#define Xil_AssertVoid(Expression) \
+-{ \
+- if (!(Expression)) { \
+- while (1); \
+- } \
+-}
+-#define Xil_AssertVoidAlways() \
+-{ \
+- while (1); \
+-}
+-#endif
++# ifndef __BAREMETAL__
++# define Xil_AssertNonvoid(Expression) \
++ { \
++ if (!(Expression)) { \
++ rfdc_throw(#Expression); \
++ } \
++ }
++# define Xil_AssertVoid(Expression) \
++ { \
++ if (!(Expression)) { \
++ rfdc_throw(#Expression); \
++ } \
++ }
++# define Xil_AssertVoidAlways() \
++ { \
++ rfdc_throw("Assert false"); \
++ }
++# endif
+
+ #define MAX(x,y) (x>y)?x:y
+ #define MIN(x,y) (x<y)?x:y
diff --git a/mpm/lib/rfdc/patches/xrfdc_sinit.c.patch b/mpm/lib/rfdc/patches/xrfdc_sinit.c.patch
new file mode 100644
index 000000000..69a97e5df
--- /dev/null
+++ b/mpm/lib/rfdc/patches/xrfdc_sinit.c.patch
@@ -0,0 +1,10 @@
+--- ../embeddedsw/XilinxProcessorIPLib/drivers/rfdc/src/xrfdc_sinit.c 2021-01-14 10:22:52.195957400 -0600
++++ mpm/lib/rfdc/xrfdc_sinit.c 2021-01-14 10:24:59.611972600 -0600
+@@ -180,6 +180,7 @@
+ metal_device_close(DevicePtr);
+ }
+ }
++ closedir(DirPtr);
+ }
+ return Status;
+ }
diff --git a/mpm/lib/rfdc/rfdc_ctrl.cpp b/mpm/lib/rfdc/rfdc_ctrl.cpp
new file mode 100644
index 000000000..94cd85c73
--- /dev/null
+++ b/mpm/lib/rfdc/rfdc_ctrl.cpp
@@ -0,0 +1,745 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include "mpm/rfdc/rfdc_ctrl.hpp"
+#include <mpm/exception.hpp>
+#include <set>
+
+#define BUS_NAME "platform"
+
+namespace mpm { namespace rfdc {
+
+rfdc_ctrl::rfdc_ctrl()
+{
+ rfdc_inst_ptr = &rfdc_inst;
+ rfdc_inst_ptr->device = nullptr;
+ rfdc_inst_ptr->io = nullptr;
+
+ // Populates default values to the struct
+ XRFdc_MultiConverter_Init(&rfdc_dac_sync_config, nullptr, nullptr);
+ XRFdc_MultiConverter_Init(&rfdc_adc_sync_config, nullptr, nullptr);
+}
+
+rfdc_ctrl::~rfdc_ctrl()
+{
+ if (rfdc_inst_ptr && rfdc_inst_ptr->device) {
+ metal_device_close(rfdc_inst_ptr->device);
+ }
+ if (metal_init_complete) {
+ metal_finish();
+ }
+}
+
+void rfdc_ctrl::init(uint16_t rfdc_device_id)
+{
+ XRFdc_Config* config_ptr;
+ char device_name[NAME_MAX];
+
+ this->rfdc_device_id = rfdc_device_id;
+
+ struct metal_init_params init_param = METAL_INIT_DEFAULTS;
+
+ if (metal_init(&init_param)) {
+ throw mpm::runtime_error("Failed to run metal initialization for rfdc.\n");
+ }
+ metal_init_complete = true;
+
+ /* Get configuration data for te RFdc device */
+ /* config_ptr is an entry of the XRFdc_ConfigTablePtr array managed by xrfdc_sinit.c
+ * This memory is not explicitly freed because we do not have access to
+ * XRFdc_ConfigTablePtr in this scope. */
+ config_ptr = XRFdc_LookupConfig(rfdc_device_id);
+ if (config_ptr == NULL) {
+ throw mpm::runtime_error("Rfdc config lookup failed.\n");
+ }
+
+ /* Initializes the controller with loaded config information */
+ if (XRFdc_CfgInitialize(rfdc_inst_ptr, config_ptr) != XRFDC_SUCCESS) {
+ throw mpm::runtime_error("Rfdc controller init failed.\n");
+ }
+
+ /* Set UpdateMixerScale into valid state. For some reason the
+ XRFdc config functions do not set this value. It will be
+ overwritten when XRFdc_SetMixerSettings is called next. */
+ rfdc_inst_ptr->UpdateMixerScale = 0;
+
+ if (XRFdc_GetDeviceNameByDeviceId(device_name, rfdc_device_id) < 0) {
+ throw mpm::runtime_error("Failed to find rfdc device with device id \n");
+ }
+
+ if (metal_device_open(BUS_NAME, device_name, &rfdc_inst_ptr->device)) {
+ throw mpm::runtime_error("Failed to open device.\n");
+ }
+
+ /* Map RFDC device IO region. 0 is the IO region index on the device. */
+ rfdc_inst_ptr->io = metal_device_io_region(rfdc_inst_ptr->device, 0);
+ if (!rfdc_inst_ptr->io) {
+ throw mpm::runtime_error("Failed to map RFDC regio\n");
+ }
+
+ /* Set all gain threshold stickies to manual clear mode */
+ for (int tile_id = 0; tile_id <= XRFDC_TILE_ID_MAX; tile_id++) {
+ for (int block_id = 0; block_id <= XRFDC_BLOCK_ID_MAX; block_id++) {
+ for (int threshold_id = 0; threshold_id < THRESHOLDS_PER_BLOCK;
+ threshold_id++) {
+ threshold_clr_modes[tile_id][block_id][threshold_id] =
+ THRESHOLD_CLRMD_UNKNOWN;
+ }
+ set_threshold_clr_mode(
+ tile_id, block_id, THRESHOLD_BOTH, THRESHOLD_CLRMD_MANUAL);
+ }
+ }
+}
+
+bool rfdc_ctrl::startup_tile(int tile_id, bool is_dac)
+{
+ return XRFdc_StartUp(rfdc_inst_ptr, is_dac, tile_id) == XRFDC_SUCCESS;
+}
+
+bool rfdc_ctrl::shutdown_tile(int tile_id, bool is_dac)
+{
+ return XRFdc_Shutdown(rfdc_inst_ptr, is_dac, tile_id) == XRFDC_SUCCESS;
+}
+
+bool rfdc_ctrl::reset_tile(int tile_id, bool is_dac)
+{
+ return XRFdc_Reset(rfdc_inst_ptr, is_dac, tile_id) == XRFDC_SUCCESS;
+}
+
+bool rfdc_ctrl::trigger_update_event(
+ uint32_t tile_id, uint32_t block_id, bool is_dac, event_type_options event_type)
+{
+ return XRFdc_UpdateEvent(rfdc_inst_ptr, is_dac, tile_id, block_id, event_type)
+ == XRFDC_SUCCESS;
+}
+
+bool rfdc_ctrl::reset_mixer_settings(uint32_t tile_id, uint32_t block_id, bool is_dac)
+{
+ XRFdc_Mixer_Settings mixer_settings;
+
+ mixer_settings.Freq = 200;
+ mixer_settings.PhaseOffset = 0;
+ mixer_settings.EventSource = XRFDC_EVNT_SRC_SYSREF;
+ mixer_settings.CoarseMixFreq = 16;
+ mixer_settings.MixerMode = is_dac ? MIXER_MODE_C2R : MIXER_MODE_R2C;
+ mixer_settings.FineMixerScale = 0;
+ mixer_settings.MixerType = XRFDC_MIXER_TYPE_FINE;
+
+ return (XRFdc_SetMixerSettings(
+ rfdc_inst_ptr, is_dac, tile_id, block_id, &mixer_settings)
+ == XRFDC_SUCCESS);
+}
+
+bool rfdc_ctrl::set_gain_enable(
+ uint32_t tile_id, uint32_t block_id, bool is_dac, bool enable)
+{
+ XRFdc_QMC_Settings qmc_settings;
+
+ // Get current QMC settings for the values that will not be changed
+ if (XRFdc_GetQMCSettings(rfdc_inst_ptr, is_dac, tile_id, block_id, &qmc_settings)
+ != XRFDC_SUCCESS) {
+ return false;
+ }
+
+ qmc_settings.EnableGain = enable;
+ // Update the setting on a SYSREF trigger
+ qmc_settings.EventSource = XRFDC_EVNT_SRC_SYSREF;
+
+ return (XRFdc_SetQMCSettings(rfdc_inst_ptr, is_dac, tile_id, block_id, &qmc_settings)
+ == XRFDC_SUCCESS);
+}
+
+bool rfdc_ctrl::set_gain(uint32_t tile_id, uint32_t block_id, bool is_dac, double gain)
+{
+ XRFdc_QMC_Settings qmc_settings;
+
+ // Get current QMC settings for the values that will not be changed
+ if (XRFdc_GetQMCSettings(rfdc_inst_ptr, is_dac, tile_id, block_id, &qmc_settings)
+ != XRFDC_SUCCESS) {
+ return false;
+ }
+
+ qmc_settings.EnableGain = 1;
+ qmc_settings.GainCorrectionFactor = gain;
+ // Update the setting on a SYSREF trigger
+ qmc_settings.EventSource = XRFDC_EVNT_SRC_SYSREF;
+
+ return (XRFdc_SetQMCSettings(rfdc_inst_ptr, is_dac, tile_id, block_id, &qmc_settings)
+ == XRFDC_SUCCESS);
+}
+
+bool rfdc_ctrl::set_threshold_settings(uint32_t tile_id,
+ uint32_t block_id,
+ threshold_id_options threshold_id,
+ threshold_mode_options mode,
+ uint32_t average_val,
+ uint32_t under_val,
+ uint32_t over_val)
+{
+ XRFdc_Threshold_Settings threshold_settings;
+
+ // Get current threshold settings for the values that will not be changed
+ if (XRFdc_GetThresholdSettings(rfdc_inst_ptr, tile_id, block_id, &threshold_settings)
+ != XRFDC_SUCCESS) {
+ return false;
+ }
+ threshold_settings.UpdateThreshold = threshold_id;
+
+ // Index 0 and 1 of the threshold settings struct correspond to threshold 0 and 1.
+ if (threshold_id == THRESHOLD_0 || threshold_id == THRESHOLD_BOTH) {
+ threshold_settings.ThresholdMode[0] = mode;
+ threshold_settings.ThresholdAvgVal[0] = average_val;
+ threshold_settings.ThresholdUnderVal[0] = under_val;
+ threshold_settings.ThresholdOverVal[0] = over_val;
+ }
+ if (threshold_id == THRESHOLD_1 || threshold_id == THRESHOLD_BOTH) {
+ threshold_settings.ThresholdMode[1] = mode;
+ threshold_settings.ThresholdAvgVal[1] = average_val;
+ threshold_settings.ThresholdUnderVal[1] = under_val;
+ threshold_settings.ThresholdOverVal[1] = over_val;
+ }
+
+ return XRFdc_SetThresholdSettings(
+ rfdc_inst_ptr, tile_id, block_id, &threshold_settings)
+ == XRFDC_SUCCESS;
+}
+
+bool rfdc_ctrl::clear_threshold_sticky(
+ uint32_t tile_id, uint32_t block_id, threshold_id_options threshold_id)
+{
+ bool result;
+ threshold_clr_mode_options old_clear_mode_0 = THRESHOLD_CLRMD_UNKNOWN,
+ old_clear_mode_1 = THRESHOLD_CLRMD_UNKNOWN;
+
+ // Check current threshold clear mode
+ old_clear_mode_0 = get_threshold_clr_mode(tile_id, block_id, THRESHOLD_0);
+ old_clear_mode_1 = get_threshold_clr_mode(tile_id, block_id, THRESHOLD_1);
+
+ // Set the clear mode to manual
+ if (!set_threshold_clr_mode(
+ tile_id, block_id, threshold_id, THRESHOLD_CLRMD_MANUAL)) {
+ return false;
+ }
+
+ // Clear the sticky
+ // Do not return on a failure as the clear mode still needs to be returned to the
+ // previous value.
+ result = (XRFdc_ThresholdStickyClear(rfdc_inst_ptr, tile_id, block_id, threshold_id)
+ == XRFDC_SUCCESS);
+
+ // Set the threshold clear mode back to the original setting
+ // If the old setting is the same or UNKNOWN this will do nothing.
+ result = result
+ && set_threshold_clr_mode(tile_id, block_id, THRESHOLD_0, old_clear_mode_0);
+ result = result
+ && set_threshold_clr_mode(tile_id, block_id, THRESHOLD_1, old_clear_mode_1);
+ return result;
+}
+
+bool rfdc_ctrl::set_threshold_clr_mode(uint32_t tile_id,
+ uint32_t block_id,
+ threshold_id_options threshold_id,
+ threshold_clr_mode_options clear_mode)
+{
+ bool result;
+ bool mode_matches = false;
+ uint32_t old_clear_mode_0 = THRESHOLD_CLRMD_UNKNOWN,
+ old_clear_mode_1 = THRESHOLD_CLRMD_UNKNOWN;
+
+ if ((tile_id > XRFDC_TILE_ID_MAX) || (block_id > XRFDC_BLOCK_ID_MAX)) {
+ return false;
+ }
+ // Do not change the clear mode to UNKNOWN
+ if (clear_mode == THRESHOLD_CLRMD_UNKNOWN) {
+ return false;
+ }
+
+ // Check current threshold clear mode
+ switch (threshold_id) {
+ case THRESHOLD_0:
+ old_clear_mode_0 = get_threshold_clr_mode(tile_id, block_id, THRESHOLD_0);
+ mode_matches = (old_clear_mode_0 == clear_mode);
+ break;
+ case THRESHOLD_1:
+ old_clear_mode_1 = get_threshold_clr_mode(tile_id, block_id, THRESHOLD_1);
+ mode_matches = (old_clear_mode_1 == clear_mode);
+ break;
+ case THRESHOLD_BOTH:
+ old_clear_mode_0 = get_threshold_clr_mode(tile_id, block_id, THRESHOLD_0);
+ old_clear_mode_1 = get_threshold_clr_mode(tile_id, block_id, THRESHOLD_1);
+ mode_matches =
+ ((old_clear_mode_0 == clear_mode) && (old_clear_mode_1 == clear_mode));
+ break;
+ }
+ // Do not change the clear mode if the new value matches the existing value
+ if (mode_matches) {
+ return true;
+ }
+
+ result = (XRFdc_SetThresholdClrMode(
+ rfdc_inst_ptr, tile_id, block_id, threshold_id, clear_mode)
+ == XRFDC_SUCCESS);
+ // If the setting was not successful, save the clear mode as unknown
+ if (!result) {
+ clear_mode = THRESHOLD_CLRMD_UNKNOWN;
+ }
+
+ // Set the new threshold clear mode
+ switch (threshold_id) {
+ case THRESHOLD_0:
+ threshold_clr_modes[tile_id][block_id][0] = clear_mode;
+ break;
+ case THRESHOLD_1:
+ threshold_clr_modes[tile_id][block_id][1] = clear_mode;
+ break;
+ case THRESHOLD_BOTH:
+ threshold_clr_modes[tile_id][block_id][0] = clear_mode;
+ threshold_clr_modes[tile_id][block_id][1] = clear_mode;
+ break;
+ }
+ return result;
+}
+
+rfdc_ctrl::threshold_clr_mode_options rfdc_ctrl::get_threshold_clr_mode(
+ uint32_t tile_id, uint32_t block_id, threshold_id_options threshold_id)
+{
+ int threshold_index;
+
+ // The XRFdc Threshold ID values (1-2) do not match the array indexes (0-1)
+ if (threshold_id == THRESHOLD_0) {
+ threshold_index = 0;
+ } else if (threshold_id == THRESHOLD_1) {
+ threshold_index = 1;
+ }
+ // An invalid Threshold ID was given
+ else {
+ return THRESHOLD_CLRMD_UNKNOWN;
+ }
+ if ((tile_id > XRFDC_TILE_ID_MAX) || (block_id > XRFDC_BLOCK_ID_MAX)
+ || (threshold_index >= THRESHOLDS_PER_BLOCK)) {
+ return THRESHOLD_CLRMD_UNKNOWN;
+ }
+
+ return threshold_clr_modes[tile_id][block_id][threshold_index];
+}
+
+bool rfdc_ctrl::set_decoder_mode(
+ uint32_t tile_id, uint32_t block_id, decoder_mode_options decoder_mode)
+{
+ return XRFdc_SetDecoderMode(rfdc_inst_ptr, tile_id, block_id, decoder_mode)
+ == XRFDC_SUCCESS;
+}
+
+bool rfdc_ctrl::reset_nco_phase(uint32_t tile_id, uint32_t block_id, bool is_dac)
+{
+ XRFdc_Mixer_Settings mixer_settings;
+
+ // Get current mixer settings for the values that will not be changed
+ if (XRFdc_GetMixerSettings(rfdc_inst_ptr, is_dac, tile_id, block_id, &mixer_settings)
+ != XRFDC_SUCCESS) {
+ return false;
+ }
+
+ // Reset the phase on a SYSREF trigger
+ mixer_settings.EventSource = XRFDC_EVNT_SRC_SYSREF;
+
+ // Set the mixer settings to set the NCO event source
+ if (XRFdc_SetMixerSettings(rfdc_inst_ptr, is_dac, tile_id, block_id, &mixer_settings)
+ != XRFDC_SUCCESS) {
+ return false;
+ }
+
+ return (XRFdc_ResetNCOPhase(rfdc_inst_ptr, is_dac, tile_id, block_id)
+ == XRFDC_SUCCESS);
+}
+
+bool rfdc_ctrl::set_nco_freq(
+ uint32_t tile_id, uint32_t block_id, bool is_dac, double freq)
+{
+ XRFdc_Mixer_Settings mixer_settings;
+
+ // Get current mixer settings for the values that will not be changed
+ if (XRFdc_GetMixerSettings(rfdc_inst_ptr, is_dac, tile_id, block_id, &mixer_settings)
+ != XRFDC_SUCCESS) {
+ return false;
+ }
+
+ // The XRFdc API expects the NCO frequency in MHz
+ mixer_settings.Freq = freq / 1e6;
+ // Only the fine mixer uses an NCO to shift the data frequency
+ mixer_settings.MixerType = XRFDC_MIXER_TYPE_FINE;
+ // Update the setting on a tile-wide event trigger
+ mixer_settings.EventSource = XRFDC_EVNT_SRC_TILE;
+
+ return (XRFdc_SetMixerSettings(
+ rfdc_inst_ptr, is_dac, tile_id, block_id, &mixer_settings)
+ == XRFDC_SUCCESS)
+ && trigger_update_event(tile_id, block_id, is_dac, MIXER_EVENT);
+}
+
+double rfdc_ctrl::get_nco_freq(uint32_t tile_id, uint32_t block_id, bool is_dac)
+{
+ XRFdc_Mixer_Settings mixer_settings;
+
+ if (XRFdc_GetMixerSettings(rfdc_inst_ptr, is_dac, tile_id, block_id, &mixer_settings)
+ != XRFDC_SUCCESS) {
+ throw mpm::runtime_error("Error in RFDC code: Failed to get mixer settings");
+ }
+ // The XRFdc API returns the frequency in MHz
+ return mixer_settings.Freq * 1e6;
+}
+
+bool rfdc_ctrl::set_nco_event_src(uint32_t tile_id, uint32_t block_id, bool is_dac)
+{
+ XRFdc_Mixer_Settings mixer_settings;
+
+ // Get current mixer settings for the values that will not be changed
+ if (XRFdc_GetMixerSettings(rfdc_inst_ptr, is_dac, tile_id, block_id, &mixer_settings)
+ != XRFDC_SUCCESS) {
+ return false;
+ }
+
+ // Reset the phase on a SYSREF trigger
+ mixer_settings.EventSource = XRFDC_EVNT_SRC_SYSREF;
+
+ // Set the mixer settings to set the NCO event source
+ return (XRFdc_SetMixerSettings(rfdc_inst_ptr, is_dac, tile_id, block_id, &mixer_settings)
+ == XRFDC_SUCCESS);
+}
+
+bool rfdc_ctrl::set_mixer_mode(
+ uint32_t tile_id, uint32_t block_id, bool is_dac, mixer_mode_options mixer_mode)
+{
+ XRFdc_Mixer_Settings mixer_settings;
+
+ // Get current mixer settings for the values that will not be changed
+ if (XRFdc_GetMixerSettings(rfdc_inst_ptr, is_dac, tile_id, block_id, &mixer_settings)
+ != XRFDC_SUCCESS) {
+ return false;
+ }
+
+ mixer_settings.MixerMode = mixer_mode;
+ // Update the setting on a tile-wide event trigger
+ mixer_settings.EventSource = XRFDC_EVNT_SRC_TILE;
+
+ return (XRFdc_SetMixerSettings(
+ rfdc_inst_ptr, is_dac, tile_id, block_id, &mixer_settings)
+ == XRFDC_SUCCESS)
+ && trigger_update_event(tile_id, block_id, is_dac, MIXER_EVENT);
+}
+
+bool rfdc_ctrl::set_nyquist_zone(
+ uint32_t tile_id, uint32_t block_id, bool is_dac, nyquist_zone_options nyquist_zone)
+{
+ return XRFdc_SetNyquistZone(rfdc_inst_ptr, is_dac, tile_id, block_id, nyquist_zone)
+ == XRFDC_SUCCESS;
+}
+
+bool rfdc_ctrl::set_calibration_mode(
+ uint32_t tile_id, uint32_t block_id, calibration_mode_options calibration_mode)
+{
+ return XRFdc_SetCalibrationMode(rfdc_inst_ptr, tile_id, block_id, calibration_mode)
+ == XRFDC_SUCCESS;
+}
+
+bool rfdc_ctrl::enable_inverse_sinc_filter(
+ uint32_t tile_id, uint32_t block_id, bool enable)
+{
+ return XRFdc_SetInvSincFIR(rfdc_inst_ptr, tile_id, block_id, enable) == XRFDC_SUCCESS;
+}
+
+bool rfdc_ctrl::set_sample_rate(uint32_t tile_id, bool is_dac, double sample_rate)
+{
+ // The XRFdc API expects the sample rate in MHz
+ double sample_rate_mhz = sample_rate / 1e6;
+ return XRFdc_DynamicPLLConfig(rfdc_inst_ptr,
+ is_dac,
+ tile_id,
+ XRFDC_EXTERNAL_CLK,
+ sample_rate_mhz,
+ sample_rate_mhz)
+ == XRFDC_SUCCESS;
+}
+
+double rfdc_ctrl::get_sample_rate(uint32_t tile_id, uint32_t block_id, bool is_dac)
+{
+ XRFdc_BlockStatus block_status;
+
+ if (XRFdc_GetBlockStatus(rfdc_inst_ptr, is_dac, tile_id, block_id, &block_status)
+ != XRFDC_SUCCESS) {
+ throw mpm::runtime_error("Error in RFDC code: Failed to get Block status");
+ }
+ // The XRFdc API returns the sampling frequency in GHz
+ return block_status.SamplingFreq * 1e9;
+}
+
+bool rfdc_ctrl::set_if(uint32_t tile_id, uint32_t block_id, bool is_dac, double if_freq)
+{
+ nyquist_zone_options nyquist_zone;
+ mixer_mode_options mixer_mode;
+ bool enable_inverse_sinc;
+ double nco_freq;
+
+ double nyquist_cutoff = get_sample_rate(tile_id, block_id, is_dac) / 2;
+
+ if (if_freq <= nyquist_cutoff) { // First Nyquist Zone
+ nyquist_zone = ODD_NYQUIST_ZONE;
+ mixer_mode = is_dac ? MIXER_MODE_C2R : MIXER_MODE_R2C;
+ enable_inverse_sinc = true;
+ } else { // Second Nyquist Zone
+ nyquist_zone = EVEN_NYQUIST_ZONE;
+ mixer_mode = is_dac ? MIXER_MODE_C2R : MIXER_MODE_R2C;
+ enable_inverse_sinc = false;
+ }
+
+ return set_nyquist_zone(tile_id, block_id, is_dac, nyquist_zone)
+ && set_mixer_mode(tile_id, block_id, is_dac, mixer_mode)
+ && (is_dac ? enable_inverse_sinc_filter(tile_id, block_id, enable_inverse_sinc)
+ : true)
+ && set_nco_freq(tile_id, block_id, is_dac, if_freq)
+ && set_nco_event_src(tile_id, block_id, is_dac);
+}
+
+bool rfdc_ctrl::set_decimation_factor(
+ uint32_t tile_id, uint32_t block_id, interp_decim_options decimation_factor)
+{
+ return XRFdc_SetDecimationFactor(rfdc_inst_ptr, tile_id, block_id, decimation_factor)
+ == XRFDC_SUCCESS;
+}
+
+rfdc_ctrl::interp_decim_options rfdc_ctrl::get_decimation_factor(
+ uint32_t tile_id, uint32_t block_id)
+{
+ uint32_t decimation_factor;
+ if (XRFdc_GetDecimationFactor(rfdc_inst_ptr, tile_id, block_id, &decimation_factor)
+ != XRFDC_SUCCESS) {
+ throw mpm::runtime_error("Error in RFDC code: Failed to get decimation factor");
+ }
+ return (interp_decim_options)decimation_factor;
+}
+
+bool rfdc_ctrl::set_interpolation_factor(
+ uint32_t tile_id, uint32_t block_id, interp_decim_options interpolation_factor)
+{
+ return XRFdc_SetInterpolationFactor(
+ rfdc_inst_ptr, tile_id, block_id, interpolation_factor)
+ == XRFDC_SUCCESS;
+}
+
+rfdc_ctrl::interp_decim_options rfdc_ctrl::get_interpolation_factor(
+ uint32_t tile_id, uint32_t block_id)
+{
+ uint32_t interpolation_factor;
+ if (XRFdc_GetInterpolationFactor(
+ rfdc_inst_ptr, tile_id, block_id, &interpolation_factor)
+ != XRFDC_SUCCESS) {
+ throw mpm::runtime_error(
+ "Error in RFDC code: Failed to get interpolation factor");
+ }
+ return (interp_decim_options)interpolation_factor;
+}
+
+bool rfdc_ctrl::set_data_read_rate(
+ uint32_t tile_id, uint32_t block_id, uint32_t valid_read_words)
+{
+ return XRFdc_SetFabRdVldWords(rfdc_inst_ptr, tile_id, block_id, valid_read_words)
+ == XRFDC_SUCCESS;
+}
+
+uint32_t rfdc_ctrl::get_data_read_rate(uint32_t tile_id, uint32_t block_id, bool is_dac)
+{
+ uint32_t valid_read_words;
+ if (XRFdc_GetFabRdVldWords(
+ rfdc_inst_ptr, is_dac, tile_id, block_id, &valid_read_words)
+ != XRFDC_SUCCESS) {
+ throw mpm::runtime_error("Error in RFDC code: Failed to get data read rate");
+ }
+ return valid_read_words;
+}
+
+bool rfdc_ctrl::set_data_write_rate(
+ uint32_t tile_id, uint32_t block_id, uint32_t valid_write_words)
+{
+ return XRFdc_SetFabWrVldWords(rfdc_inst_ptr, tile_id, block_id, valid_write_words)
+ == XRFDC_SUCCESS;
+}
+
+uint32_t rfdc_ctrl::get_data_write_rate(uint32_t tile_id, uint32_t block_id, bool is_dac)
+{
+ uint32_t valid_write_words;
+ if (XRFdc_GetFabWrVldWords(
+ rfdc_inst_ptr, is_dac, tile_id, block_id, &valid_write_words)
+ != XRFDC_SUCCESS) {
+ throw mpm::runtime_error("Error in RFDC code: Failed to get data write rate");
+ }
+ return valid_write_words;
+}
+
+bool rfdc_ctrl::set_fabric_clk_div(
+ uint32_t tile_id, bool is_dac, fabric_clk_div_options divider)
+{
+ return XRFdc_SetFabClkOutDiv(rfdc_inst_ptr, is_dac, tile_id, divider)
+ == XRFDC_SUCCESS;
+}
+
+rfdc_ctrl::fabric_clk_div_options rfdc_ctrl::get_fabric_clk_div(
+ uint32_t tile_id, bool is_dac)
+{
+ uint16_t divider;
+ if (XRFdc_GetFabClkOutDiv(rfdc_inst_ptr, is_dac, tile_id, &divider)
+ != XRFDC_SUCCESS) {
+ throw mpm::runtime_error(
+ "Error in RFDC code: Failed to get fabric clock divider");
+ }
+ return (fabric_clk_div_options)divider;
+}
+
+bool rfdc_ctrl::set_data_fifo_state(uint32_t tile_id, bool is_dac, bool enable)
+{
+ return XRFdc_SetupFIFO(rfdc_inst_ptr, is_dac, tile_id, enable) == XRFDC_SUCCESS;
+}
+
+bool rfdc_ctrl::get_data_fifo_state(uint32_t tile_id, bool is_dac)
+{
+ uint8_t enabled;
+ if (XRFdc_GetFIFOStatus(rfdc_inst_ptr, is_dac, tile_id, &enabled) != XRFDC_SUCCESS) {
+ throw mpm::runtime_error("Error in RFDC code: Failed to get FIFO status");
+ }
+ return (bool)enabled;
+}
+
+void rfdc_ctrl::clear_data_fifo_interrupts(
+ const uint32_t tile_id, const uint32_t block_id, const bool is_dac)
+{
+ if (XRFdc_IntrClr(rfdc_inst_ptr,
+ static_cast<u32>(is_dac),
+ tile_id,
+ block_id,
+ XRFDC_IXR_FIFOUSRDAT_MASK)
+ != XRFDC_SUCCESS) {
+ throw mpm::runtime_error(
+ "Error in RFDC code: Failed to clear data FIFO interrupts");
+ }
+}
+
+bool rfdc_ctrl::sync_tiles(const std::vector<uint32_t>& tiles, bool is_dac, uint32_t latency)
+{
+ XRFdc_MultiConverter_Sync_Config* sync_config = is_dac ? &rfdc_dac_sync_config
+ : &rfdc_adc_sync_config;
+ sync_config->Tiles = 0;
+ sync_config->Target_Latency = latency;
+
+ for (auto tile = tiles.begin(); tile != tiles.end(); ++tile) {
+ // sync_config->Tiles is a bitmask, we need to "bump" each bit (0->1)
+ // that corresponds to the specified indices
+ sync_config->Tiles |= (1 << *tile);
+ }
+
+ return XRFDC_MTS_OK
+ == XRFdc_MultiConverter_Sync(
+ &rfdc_inst, is_dac ? XRFDC_DAC_TILE : XRFDC_ADC_TILE, sync_config);
+}
+
+uint32_t rfdc_ctrl::get_tile_latency(uint32_t tile_index, bool is_dac)
+{
+ XRFdc_MultiConverter_Sync_Config* sync_config = is_dac ? &rfdc_dac_sync_config
+ : &rfdc_adc_sync_config;
+ // If user has called sync with this tile_index, this
+ // attribute should be populated in our sync config
+ if ((1 << tile_index) & sync_config->Tiles) {
+ return sync_config->Latency[tile_index];
+ }
+ if (is_dac) {
+ throw mpm::runtime_error("rfdc_ctrl: Failed to get DAC Tile Latency");
+ } else {
+ throw mpm::runtime_error("rfdc_ctrl: Failed to get ADC Tile Latency");
+ }
+}
+
+uint32_t rfdc_ctrl::get_tile_offset(uint32_t tile_index, bool is_dac)
+{
+ XRFdc_MultiConverter_Sync_Config* sync_config = is_dac ? &rfdc_dac_sync_config
+ : &rfdc_adc_sync_config;
+ // If user has called sync with this tile_index, this
+ // attribute should be populated in our sync config
+ if ((1 << tile_index) & sync_config->Tiles) {
+ return sync_config->Offset[tile_index];
+ }
+ if (is_dac) {
+ throw mpm::runtime_error("rfdc_ctrl: Failed to get DAC Tile Offset");
+ } else {
+ throw mpm::runtime_error("rfdc_ctrl: Failed to get ADC Tile Offset");
+ }
+}
+
+void rfdc_ctrl::set_cal_frozen(
+ const uint32_t tile_id, const uint32_t block_id, const bool frozen)
+{
+ XRFdc_Cal_Freeze_Settings cal_freeze_settings;
+ cal_freeze_settings.CalFrozen = false;
+ cal_freeze_settings.DisableFreezePin = true;
+ cal_freeze_settings.FreezeCalibration = frozen;
+ if (XRFdc_SetCalFreeze(&rfdc_inst, tile_id, block_id, &cal_freeze_settings)
+ != XRFDC_SUCCESS) {
+ throw mpm::runtime_error(
+ "Error in RFDC code: Failed to set calibration freeze status");
+ }
+}
+
+bool rfdc_ctrl::get_cal_frozen(const uint32_t tile_id, const uint32_t block_id)
+{
+ XRFdc_Cal_Freeze_Settings cal_freeze_settings;
+ if (XRFdc_GetCalFreeze(&rfdc_inst, tile_id, block_id, &cal_freeze_settings)
+ != XRFDC_SUCCESS) {
+ throw mpm::runtime_error(
+ "Error in RFDC code: Failed to get calibration freeze status");
+ }
+ return cal_freeze_settings.CalFrozen;
+}
+
+void rfdc_ctrl::set_adc_cal_coefficients(uint32_t tile_id, uint32_t block_id, uint32_t cal_block, std::vector<uint32_t> coefs)
+{
+ if (coefs.size() != 8)
+ {
+ throw mpm::runtime_error("set_adc_cal_coefficients requires that exactly 8 coefficients be passed");
+ }
+
+ XRFdc_Calibration_Coefficients cs;
+ cs.Coeff0 = coefs[0];
+ cs.Coeff1 = coefs[1];
+ cs.Coeff2 = coefs[2];
+ cs.Coeff3 = coefs[3];
+ cs.Coeff4 = coefs[4];
+ cs.Coeff5 = coefs[5];
+ cs.Coeff6 = coefs[6];
+ cs.Coeff7 = coefs[7];
+
+ if (XRFdc_SetCalCoefficients(&rfdc_inst, tile_id, block_id, cal_block, &cs) != XRFDC_SUCCESS) {
+ throw mpm::runtime_error("Error returned from XRFdc_SetCalCoefficients");
+ }
+}
+
+std::vector<uint32_t> rfdc_ctrl::get_adc_cal_coefficients(uint32_t tile_id, uint32_t block_id, uint32_t cal_block)
+{
+ std::vector<uint32_t> result;
+ XRFdc_Calibration_Coefficients cs;
+ if (XRFdc_GetCalCoefficients(&rfdc_inst, tile_id, block_id, cal_block, &cs) != XRFDC_SUCCESS) {
+ throw mpm::runtime_error("Error returned from XRFdc_GetCalCoefficients");
+ }
+
+ result.push_back(cs.Coeff0);
+ result.push_back(cs.Coeff1);
+ result.push_back(cs.Coeff2);
+ result.push_back(cs.Coeff3);
+ result.push_back(cs.Coeff4);
+ result.push_back(cs.Coeff5);
+ result.push_back(cs.Coeff6);
+ result.push_back(cs.Coeff7);
+
+ return result;
+}
+
+}} // namespace mpm::rfdc
diff --git a/mpm/lib/rfdc/rfdc_throw.cpp b/mpm/lib/rfdc/rfdc_throw.cpp
new file mode 100644
index 000000000..a50fe7c96
--- /dev/null
+++ b/mpm/lib/rfdc/rfdc_throw.cpp
@@ -0,0 +1,24 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+extern "C" {
+#include "mpm/rfdc/rfdc_throw.h"
+}
+#include <mpm/exception.hpp>
+#include <string>
+
+/**
+ * A function to throw MPM exceptions from within the Xilinx RFdc API
+ */
+void rfdc_throw(const char* msg)
+{
+ if (msg) {
+ std::string error_msg(msg);
+ throw mpm::assertion_error("Error in RFDC code: " + error_msg);
+ } else {
+ throw mpm::assertion_error("Error in RFDC code.");
+ }
+}
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;
+}
+/** @} */
diff --git a/mpm/lib/rfdc/xrfdc_clock.c b/mpm/lib/rfdc/xrfdc_clock.c
new file mode 100644
index 000000000..73a19fda5
--- /dev/null
+++ b/mpm/lib/rfdc/xrfdc_clock.c
@@ -0,0 +1,1801 @@
+/******************************************************************************
+*
+* Copyright (C) 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_clock.c
+* @addtogroup xrfdc_v6_0
+* @{
+*
+* Contains the interface functions of the Mixer Settings in XRFdc driver.
+* See xrfdc.h for a detailed description of the device and driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- --- -------- -----------------------------------------------
+* 6.0 cog 02/17/19 Initial release.
+* cog 03/12/19 Invert clock detection bits to support IP change.
+* cog 03/12/19 Fix bug where incorrect FS, RefClk and were output
+* divider were being returned.
+* cog 04/09/19 Discriminate between Gen 3 IP and lower for checking
+* if internal PLL is enabled.
+* cog 04/09/19 Fixed issue where tile was not autostarting after PLL
+* rate change.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+#include "mpm/rfdc/xrfdc.h"
+
+/************************** Constant Definitions *****************************/
+static u32 PllTuningMatrix[8][4][2] = {
+ {{0x7F8A, 0x3FFF}, {0x7F9C, 0x3FFF}, {0x7FE2, 0x3FFF} },
+ {{0x7FE9, 0xFFFF}, {0x7F8E, 0xFFFF}, {0x7F9C, 0xFFFF} },
+ {{0x7F95, 0xFFFF}, {0x7F8E, 0xFFFF}, { 0x7F9A, 0xFFFF}, {0x7F8C, 0xFFFF} },
+ {{0x7F95, 0x3FFF}, {0x7FEE, 0x3FFF}, { 0x7F9A, 0xFFFF}, {0x7F9C, 0xFFFF} },
+ {{0x7F95, 0x3FFF}, {0x7FEE, 0x3FFF}, { 0x7F9A, 0xFFFF}, {0x7F9C, 0xFFFF} },
+ {{0x7F95, 0xFFFF}, {0x7F8E, 0xFFFF}, { 0x7FEA, 0xFFFF}, {0x7F9C, 0xFFFF} },
+ {{0x7FE9, 0xFFFF}, {0x7F8E, 0xFFFF}, { 0x7F9A, 0xFFFF}, {0x7F9C, 0xFFFF} },
+ {{0x7FEC, 0xFFFF}, {0x7FEE, 0x3FFF}, { 0x7F9C, 0xFFFF} }
+};
+
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+static u32 XRFdc_CheckClkDistValid(XRFdc *InstancePtr, XRFdc_Distribution_Settings *DistributionSettingsPtr);
+static u32 XRFdc_SetPLLConfig(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ double RefClkFreq, double SamplingRate);
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+/**
+*
+* This function is used to set the clock settings
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type indicates ADC/DAC.
+* @param Tile_Id indicates Tile number (0-3).
+* @param SettingsPtr pointer to set the clock settings
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if no valid distribution found.
+*
+******************************************************************************/
+u32 XRFdc_SetTileClkSettings(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, XRFdc_Tile_Clock_Settings *SettingsPtr)
+{
+ u32 Status;
+ u32 BaseAddr;
+ u16 PLLSource;
+ u16 NetworkCtrlReg;
+ u16 DistCtrlReg;
+ u16 PLLRefDivReg;
+ u16 PLLOpDivReg;
+ u32 TileIndex;
+ u16 DivideMode = 0;
+ u16 DivideValue = 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;
+ }
+
+ TileIndex = (Type == XRFDC_DAC_TILE) ? Tile_Id : Tile_Id + XRFDC_CLK_DST_ADC0;
+ 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 (SettingsPtr->SourceTile > XRFDC_CLK_DST_ADC3) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Parameter Value "
+ "for Source in %s\r\n",
+ __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if (SettingsPtr->DistributedClock > XRFDC_DIST_OUT_OUTDIV) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Parameter Value "
+ "for Distribution Out in %s\r\n",
+ __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if (SettingsPtr->PLLEnable > 1) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Parameter Value "
+ "for PLLEnable in %s\r\n",
+ __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if ((SettingsPtr->PLLEnable == XRFDC_ENABLED) && (SettingsPtr->DivisionFactor < 1)) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid Configuration in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if ((SettingsPtr->DistributedClock == XRFDC_DIST_OUT_OUTDIV) &&
+ ((SettingsPtr->DivisionFactor < 2) && (SettingsPtr->PLLEnable == XRFDC_DISABLED))) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid Configuration in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if ((SettingsPtr->SourceTile != TileIndex) && (SettingsPtr->DistributedClock != XRFDC_DIST_OUT_NONE)) {
+ metal_log(METAL_LOG_ERROR, "\n Cannot Redistribute Clock in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ /*configure PLL & divider or just divider*/
+ if (SettingsPtr->PLLEnable == XRFDC_ENABLED) {
+ metal_log(METAL_LOG_WARNING,
+ "\n Output divider settings may "
+ "be overridden in %s\r\n",
+ __func__);
+ PLLSource = XRFDC_INTERNAL_PLL_CLK;
+ Status = XRFdc_DynamicPLLConfig(InstancePtr, Type, Tile_Id, PLLSource,
+ SettingsPtr->PLLSettings.RefClkFreq,
+ SettingsPtr->PLLSettings.SampleRate);
+ SettingsPtr->DivisionFactor = SettingsPtr->PLLSettings.OutputDivider;
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Could not set up PLL "
+ "in %s\r\n",
+ __func__);
+ goto RETURN_PATH;
+ }
+ } else if (SettingsPtr->DivisionFactor > 1) {
+ if (SettingsPtr->DivisionFactor == 2U) {
+ DivideMode = XRFDC_PLL_OUTDIV_MODE_2;
+ } else if (SettingsPtr->DivisionFactor == 3U) {
+ DivideMode = XRFDC_PLL_OUTDIV_MODE_3;
+ DivideValue = XRFDC_PLL_OUTDIV_MODE_3_VAL;
+ } else if (SettingsPtr->DivisionFactor >= 4U) {
+ DivideMode = XRFDC_PLL_OUTDIV_MODE_N;
+ DivideValue = ((SettingsPtr->DivisionFactor - 4U) >> 1);
+ }
+ XRFdc_ClrSetReg(InstancePtr, XRFDC_DRP_BASE(Type, Tile_Id) + XRFDC_HSCOM_ADDR, XRFDC_PLL_DIVIDER0,
+ XRFDC_PLL_DIVIDER0_MASK, ((DivideMode << XRFDC_PLL_DIVIDER0_SHIFT) | DivideValue));
+ }
+ DistCtrlReg = 0;
+ PLLRefDivReg = 0;
+ PLLOpDivReg = 0;
+ NetworkCtrlReg = 0;
+ if (SettingsPtr->SourceTile == TileIndex) {
+ if (SettingsPtr->DistributedClock == XRFDC_DIST_OUT_NONE) {
+ if (SettingsPtr->PLLEnable == XRFDC_DISABLED) {
+ PLLRefDivReg |= XRFDC_PLLREFDIV_INPUT_OFF;
+ NetworkCtrlReg |= XRFDC_NET_CTRL_CLK_REC_DIST_T1;
+ if (SettingsPtr->DivisionFactor < 2) {
+ /*
+ T1 from Self
+ No PLL
+ Do Not Use PLL Output Divider
+ Do Not Distribute
+ */
+ NetworkCtrlReg |= XRFDC_NET_CTRL_CLK_T1_SRC_LOCAL;
+ DistCtrlReg |= XRFDC_DIST_CTRL_CLK_T1_SRC_LOCAL;
+ } else {
+ /*
+ T1 from Self
+ No PLL
+ Do Not Distribute
+ */
+ PLLOpDivReg |= XRFDC_PLLOPDIV_INPUT_DIST_LOCAL;
+ }
+ } else {
+ /*
+ T1 from Self
+ PLL
+ Use PLL Output Divider
+ Do Not Distribute
+ */
+ NetworkCtrlReg |= XRFDC_NET_CTRL_CLK_REC_PLL;
+ }
+ } else {
+ NetworkCtrlReg |= XRFDC_NET_CTRL_CLK_T1_SRC_DIST;
+ DistCtrlReg |= XRFDC_DIST_CTRL_TO_T1;
+ if (SettingsPtr->PLLEnable == XRFDC_DISABLED) {
+ NetworkCtrlReg |= XRFDC_NET_CTRL_CLK_REC_DIST_T1;
+ PLLRefDivReg |= XRFDC_PLLREFDIV_INPUT_OFF;
+ if (SettingsPtr->DivisionFactor < 2) {
+ /*
+ T1 From Distribution
+ No PLL
+ Do Not Use PLL Output Divider
+ Send to Distribution
+ */
+ DistCtrlReg |= XRFDC_DIST_CTRL_DIST_SRC_LOCAL;
+ } else {
+ /*
+ T1 From Distribution
+ No PLL
+ Use PLL Output Divider
+ Send to Distribution
+ */
+ PLLOpDivReg |= XRFDC_PLLOPDIV_INPUT_DIST_LOCAL;
+ DistCtrlReg |= (SettingsPtr->DistributedClock == XRFDC_DIST_OUT_RX) ?
+ XRFDC_DIST_CTRL_DIST_SRC_LOCAL :
+ XRFDC_DIST_CTRL_DIST_SRC_PLL;
+ }
+
+ } else {
+ /*
+ T1 From Distribution
+ PLL
+ Use PLL Output Divider
+ Send to Distribution
+ */
+ DistCtrlReg |= (SettingsPtr->DistributedClock == XRFDC_DIST_OUT_RX) ?
+ XRFDC_DIST_CTRL_DIST_SRC_LOCAL :
+ XRFDC_DIST_CTRL_DIST_SRC_PLL;
+ NetworkCtrlReg |= XRFDC_NET_CTRL_CLK_REC_PLL;
+ }
+ }
+ } else {
+ if (SettingsPtr->PLLEnable == XRFDC_DISABLED) {
+ PLLRefDivReg |= XRFDC_PLLREFDIV_INPUT_OFF;
+ if (SettingsPtr->DivisionFactor > 1) {
+ /*
+ Source From Distribution
+ No PLL
+ Use PLL Output Divider
+ Do Not Distribute
+ */
+
+ PLLOpDivReg |= XRFDC_PLLOPDIV_INPUT_DIST_LOCAL;
+ NetworkCtrlReg |= XRFDC_NET_CTRL_CLK_INPUT_DIST;
+ DistCtrlReg |= XRFDC_DIST_CTRL_TO_PLL_DIV;
+ } else {
+ /*
+ Source From Distribution
+ No PLL
+ Do Not Use PLL Output Divider
+ Do Not Distribute
+ */
+ NetworkCtrlReg |= XRFDC_NET_CTRL_CLK_T1_SRC_DIST;
+ DistCtrlReg |= XRFDC_DIST_CTRL_TO_T1;
+ }
+ } else {
+ /*
+ Source From Distribution
+ PLL
+ Use PLL Output Divider
+ Do Not Distribute
+ */
+ PLLRefDivReg |= XRFDC_PLLREFDIV_INPUT_DIST;
+ DistCtrlReg |= XRFDC_DIST_CTRL_TO_PLL_DIV;
+ }
+ }
+
+ /*Write to Registers*/
+ if (Type == XRFDC_ADC_TILE) {
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id);
+ } else {
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id);
+ }
+ BaseAddr += XRFDC_HSCOM_ADDR;
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_HSCOM_CLK_DSTR_OFFSET, XRFDC_HSCOM_CLK_DSTR_MASK_ALT, DistCtrlReg);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CLK_NETWORK_CTRL1, XRFDC_HSCOM_NETWORK_CTRL1_MASK, NetworkCtrlReg);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_PLL_REFDIV, XRFDC_PLL_REFDIV_MASK, PLLRefDivReg);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_PLL_DIVIDER0, XRFDC_PLL_DIVIDER0_ALT_MASK, PLLOpDivReg);
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+/*****************************************************************************/
+/**
+*
+* This function is used to check the distribution chosen is valid
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param DistributionSettingsPtr pointer to the distribution settings struct
+*
+* @return
+* - XRFDC_SUCCESS if Valid.
+* - XRFDC_FAILURE if Not Valid.
+*
+******************************************************************************/
+static u32 XRFdc_CheckClkDistValid(XRFdc *InstancePtr, XRFdc_Distribution_Settings *DistributionSettingsPtr)
+{
+ u32 Status;
+ u8 CurrentTile;
+ u8 *Source;
+ u8 Sources[8] = { DistributionSettingsPtr->DAC[0].SourceTile, DistributionSettingsPtr->DAC[1].SourceTile,
+ DistributionSettingsPtr->DAC[2].SourceTile, DistributionSettingsPtr->DAC[3].SourceTile,
+ DistributionSettingsPtr->ADC[0].SourceTile, DistributionSettingsPtr->ADC[1].SourceTile,
+ DistributionSettingsPtr->ADC[2].SourceTile, DistributionSettingsPtr->ADC[3].SourceTile };
+ u8 LowBoundary;
+ u16 EFuse;
+ XRFdc_Distribution *DistributionPtr;
+
+ /*init for first distribution*/
+ DistributionPtr = DistributionSettingsPtr->DistributionStatus;
+ Source = Sources;
+ LowBoundary = DistributionSettingsPtr->DAC[0].SourceTile;
+ DistributionPtr->DistributionSource = DistributionSettingsPtr->DAC[0].SourceTile;
+ DistributionPtr->Enabled = XRFDC_ENABLED;
+ DistributionPtr->LowerBound = 0;
+
+ for (CurrentTile = 0; CurrentTile < XRFDC_DIST_MAX; CurrentTile++, Source++) {
+ if (*Source >= XRFDC_DIST_MAX) {
+ Status = XRFDC_FAILURE; /*out of range*/
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Source "
+ "value in %s - Out of Range\r\n",
+ __func__);
+ goto RETURN_PATH;
+ }
+ if (*Source < LowBoundary) {
+ Status = XRFDC_FAILURE; /*SW: no hopovers*/
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Configuration "
+ "Hopping Over Not Allowed in %s\r\n",
+ __func__);
+ goto RETURN_PATH;
+ }
+ if (Sources[*Source] != *Source) { /*SW: check source is a distributer*/
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Source "
+ "Sourcing from Tile that is not Distributing in %s\r\n",
+ __func__);
+ goto RETURN_PATH;
+ }
+ if ((*Source == XRFDC_CLK_DST_DAC0) &&
+ (InstancePtr->RFdc_Config.DACTile_Config[XRFDC_CLK_DST_DAC0].NumSlices == 2)) { /*HW: only 2 clks*/
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Source "
+ "Sourcing from Tile Without Clock in %s\r\n",
+ __func__);
+ goto RETURN_PATH;
+ }
+ if ((*Source == XRFDC_CLK_DST_DAC2) &&
+ (InstancePtr->RFdc_Config.DACTile_Config[XRFDC_CLK_DST_DAC2].NumSlices == 2)) { /*HW: only 2 clks*/
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Source "
+ "Sourcing from Tile Without Clock in %s\r\n",
+ __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if ((CurrentTile < XRFDC_CLK_DST_ADC0) &&
+ (*Source > XRFDC_CLK_DST_DAC3)) { /*Cut between ADC0 MUX8 && DAC3 STH*/
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Configuration "
+ "DAC Cannot Source from ADC in %s\r\n",
+ __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if (CurrentTile < XRFDC_CLK_DST_ADC0) { /*DAC*/
+ EFuse = XRFdc_ReadReg16(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_DAC_TILE, CurrentTile) + XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_EFUSE_2_OFFSET);
+ } else { /*ADC*/
+ EFuse = XRFdc_ReadReg16(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_ADC_TILE, (CurrentTile - XRFDC_CLK_DST_ADC0)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_EFUSE_2_OFFSET);
+ }
+ /*if PKG <2*/
+
+ if ((DistributionSettingsPtr->DAC[0].SourceTile != DistributionSettingsPtr->DAC[1].SourceTile) ||
+ (DistributionSettingsPtr->DAC[0].SourceTile != DistributionSettingsPtr->DAC[2].SourceTile) ||
+ (DistributionSettingsPtr->DAC[0].SourceTile != DistributionSettingsPtr->DAC[3].SourceTile) ||
+ (DistributionSettingsPtr->DAC[0].SourceTile != DistributionSettingsPtr->ADC[0].SourceTile) ||
+ (DistributionSettingsPtr->DAC[0].SourceTile != DistributionSettingsPtr->ADC[1].SourceTile) ||
+ (DistributionSettingsPtr->DAC[0].SourceTile != DistributionSettingsPtr->ADC[2].SourceTile) ||
+ (DistributionSettingsPtr->DAC[0].SourceTile != DistributionSettingsPtr->ADC[3].SourceTile) ||
+ (DistributionSettingsPtr->DAC[0].PLLEnable != XRFDC_ENABLED) ||
+ (DistributionSettingsPtr->DAC[1].PLLEnable != XRFDC_ENABLED) ||
+ (DistributionSettingsPtr->DAC[2].PLLEnable != XRFDC_ENABLED) ||
+ (DistributionSettingsPtr->DAC[3].PLLEnable != XRFDC_ENABLED) ||
+ (DistributionSettingsPtr->ADC[0].PLLEnable != XRFDC_ENABLED) ||
+ (DistributionSettingsPtr->ADC[1].PLLEnable != XRFDC_ENABLED) ||
+ (DistributionSettingsPtr->ADC[2].PLLEnable != XRFDC_ENABLED) ||
+ (DistributionSettingsPtr->ADC[3].PLLEnable != XRFDC_ENABLED)) { /*special case that is allowed.*/
+
+ /*if PKG <2*/
+ if (EFuse & XRFDC_PREMIUMCTRL_CLKDIST) {
+ if ((CurrentTile > XRFDC_CLK_DST_ADC1) &&
+ (*Source != CurrentTile)) { /*E: no dist past adc1*/
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Configuration "
+ "- Licensing - Not Premium in %s\r\n",
+ __func__);
+ goto RETURN_PATH;
+ }
+ }
+ /*if PKG <1*/
+ if ((EFuse & XRFDC_EXPORTCTRL_CLKDIST) == XRFDC_EXPORTCTRL_CLKDIST) {
+ if ((CurrentTile > XRFDC_CLK_DST_DAC3) && (*Source != CurrentTile)) { /*E: No ADC Dist*/
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Configuration "
+ "- Licensing in %s\r\n",
+ __func__);
+ goto RETURN_PATH;
+ }
+ if ((CurrentTile == XRFDC_CLK_DST_DAC0) &&
+ (*Source != XRFDC_CLK_DST_DAC1)) { /*E: DAC0 must source from DAC1*/
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Configuration "
+ "- Licensing in - Export Control %s\r\n",
+ __func__);
+ goto RETURN_PATH;
+ }
+ if ((CurrentTile == XRFDC_CLK_DST_DAC2) &&
+ (*Source != XRFDC_CLK_DST_DAC3)) { /*E: DAC2 must source from DAC3*/
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Configuration "
+ "- Licensing in %s\r\n",
+ __func__);
+ goto RETURN_PATH;
+ }
+ }
+ }
+
+ if (*Source != DistributionPtr->DistributionSource) { /*i.e. if new distribution*/
+ DistributionPtr->UpperBound = CurrentTile - 1;
+ DistributionPtr++;
+ DistributionPtr->Enabled = XRFDC_ENABLED;
+ LowBoundary = *Source;
+ DistributionPtr->DistributionSource = *Source;
+ DistributionPtr->LowerBound = CurrentTile;
+ }
+ }
+ DistributionPtr->UpperBound = CurrentTile - 1;
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ if (Status == XRFDC_FAILURE) {
+ memset(DistributionSettingsPtr, 0, sizeof(XRFdc_Distribution_Settings));
+ }
+ return Status;
+}
+/*****************************************************************************/
+/**
+*
+* This function is used to set the clock distribution
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param DistributionSettingsPtr pointer to the distribution settings struct
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if could not set distribution.
+*
+******************************************************************************/
+u32 XRFdc_SetClkDistribution(XRFdc *InstancePtr, XRFdc_Distribution_Settings *DistributionSettingsPtr)
+{
+ u32 Status;
+ u8 DelayLeft;
+ u8 DelayRight;
+ s8 Delay;
+ s8 ClkDetItr;
+ u8 *Delays[8];
+ u8 DelayOutSourceLeft;
+ u8 DelayOutSourceRight;
+ XRFdc_Distribution *Distribution;
+ u8 DistributionCount;
+ u16 Reg;
+ u16 ClkDetectReg;
+ u8 FeedBackForInputRight = 0;
+ u8 FeedBackForInputLeft = 0;
+ u8 Tile;
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(DistributionSettingsPtr != 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_CheckClkDistValid(InstancePtr, DistributionSettingsPtr);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Distribution "
+ "in %s\r\n",
+ __func__);
+ goto RETURN_PATH;
+ }
+ Delays[0] = &DistributionSettingsPtr->DAC[0].Delay;
+ Delays[1] = &DistributionSettingsPtr->DAC[1].Delay;
+ Delays[2] = &DistributionSettingsPtr->DAC[2].Delay;
+ Delays[3] = &DistributionSettingsPtr->DAC[3].Delay;
+ Delays[4] = &DistributionSettingsPtr->ADC[0].Delay;
+ Delays[5] = &DistributionSettingsPtr->ADC[1].Delay;
+ Delays[6] = &DistributionSettingsPtr->ADC[2].Delay;
+ Delays[7] = &DistributionSettingsPtr->ADC[3].Delay;
+ Status = XRFdc_Shutdown(InstancePtr, XRFDC_ADC_TILE, -1);
+ if (Status != XRFDC_SUCCESS) {
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ Status = XRFdc_Shutdown(InstancePtr, XRFDC_DAC_TILE, -1);
+ if (Status != XRFDC_SUCCESS) {
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ for (Distribution = DistributionSettingsPtr->DistributionStatus, DistributionCount = 0;
+ DistributionCount < XRFDC_DIST_MAX; Distribution++, DistributionCount++) {
+ if (Distribution->Enabled == XRFDC_DISABLED) {
+ break;
+ }
+ DelayLeft = (-Distribution->LowerBound + Distribution->DistributionSource);
+ DelayRight = (Distribution->UpperBound - Distribution->DistributionSource);
+ DelayOutSourceLeft = 0;
+ DelayOutSourceRight = 0;
+ Distribution->MaxDelay = 0;
+ Distribution->MinDelay = 255;
+ Distribution->IsDelayBalanced = 0;
+ if ((DelayLeft == 0) && (DelayRight == 0)) { /*self contained*/
+ Reg = XRFDC_CLK_DISTR_OFF;
+ } else {
+ Reg = XRFDC_CLK_DISTR_MUX9_SRC_INT;
+ if (DelayLeft == 0) {
+ Reg |= XRFDC_CLK_DISTR_MUX8_SRC_NTH;
+ } else {
+ Reg |= XRFDC_CLK_DISTR_MUX8_SRC_INT;
+ }
+ if (((Distribution->DistributionSource == XRFDC_CLK_DST_DAC3) ||
+ (Distribution->DistributionSource == XRFDC_CLK_DST_ADC3)) &&
+ ((DelayLeft > 1) || (DelayRight > 1))) /*cases for no FB from tile to right*/
+ {
+ Reg |= XRFDC_CLK_DISTR_MUX4A_SRC_INT | XRFDC_CLK_DISTR_MUX6_SRC_INT |
+ XRFDC_CLK_DISTR_MUX7_SRC_INT;
+ FeedBackForInputRight = 0;
+ FeedBackForInputLeft = 0;
+ } else {
+ if (DelayLeft > 1) {
+ Reg |= XRFDC_CLK_DISTR_MUX4A_SRC_STH | XRFDC_CLK_DISTR_MUX6_SRC_NTH |
+ XRFDC_CLK_DISTR_MUX7_SRC_INT;
+ DelayOutSourceRight = 2;
+ FeedBackForInputRight = 0;
+ FeedBackForInputLeft = 1;
+ } else {
+ Reg |= XRFDC_CLK_DISTR_MUX4A_SRC_INT;
+ FeedBackForInputRight = 1;
+ FeedBackForInputLeft = 0;
+ if ((DelayRight > 1) &&
+ (Distribution->DistributionSource != XRFDC_CLK_DST_DAC2)) {
+ Reg |= XRFDC_CLK_DISTR_MUX7_SRC_STH;
+ DelayOutSourceLeft = 2;
+ } else {
+ Reg |= XRFDC_CLK_DISTR_MUX7_SRC_INT;
+ }
+ if (DelayRight == 0) {
+ Reg |= XRFDC_CLK_DISTR_MUX6_SRC_OFF;
+ } else {
+ Reg |= XRFDC_CLK_DISTR_MUX6_SRC_INT;
+ }
+ }
+ }
+ }
+
+ *Delays[Distribution->DistributionSource] =
+ (Reg == XRFDC_CLK_DISTR_OFF) ? 0 : DelayOutSourceLeft + DelayOutSourceRight + 2;
+ Distribution->MaxDelay = MAX(Distribution->MaxDelay, (*Delays[Distribution->DistributionSource]));
+ Distribution->MinDelay = MIN(Distribution->MinDelay, (*Delays[Distribution->DistributionSource]));
+
+ /* setup clk detect register */
+ ClkDetectReg = (XRFDC_CLOCK_DETECT_CLK <<
+ ((XRFDC_CLK_DST_ADC3 - Distribution->DistributionSource) << 1));
+
+ if ((Distribution->DistributionSource) < XRFDC_CLK_DST_ADC0) { /*DAC*/
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_DAC_TILE, (Distribution->DistributionSource)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET, XRFDC_HSCOM_CLK_DSTR_MASK, Reg);
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_CTRL_STS_BASE(XRFDC_DAC_TILE, (Distribution->DistributionSource)),
+ XRFDC_CLOCK_DETECT_OFFSET, XRFDC_CLOCK_DETECT_MASK, ClkDetectReg);
+ } else { /*ADC*/
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_ADC_TILE,
+ (Distribution->DistributionSource - XRFDC_CLK_DST_ADC0)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET, XRFDC_HSCOM_CLK_DSTR_MASK, Reg);
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_CTRL_STS_BASE(XRFDC_ADC_TILE,
+ (Distribution->DistributionSource - XRFDC_CLK_DST_ADC0)),
+ XRFDC_CLOCK_DETECT_OFFSET, XRFDC_CLOCK_DETECT_MASK, ClkDetectReg);
+ }
+ /*Leftmost tile*/
+ if (DelayLeft) {
+ *Delays[Distribution->LowerBound] = DelayOutSourceLeft + (DelayLeft << 1);
+ Distribution->MaxDelay = MAX(Distribution->MaxDelay, (*Delays[Distribution->LowerBound]));
+ Distribution->MinDelay = MIN(Distribution->MinDelay, (*Delays[Distribution->LowerBound]));
+ Reg = XRFDC_CLK_DISTR_MUX4A_SRC_STH | XRFDC_CLK_DISTR_MUX6_SRC_OFF |
+ XRFDC_CLK_DISTR_MUX7_SRC_OFF | XRFDC_CLK_DISTR_MUX8_SRC_NTH |
+ XRFDC_CLK_DISTR_MUX9_SRC_INT;
+
+ /* setup clk detect register */
+ ClkDetectReg = (XRFDC_CLOCK_DETECT_BOTH <<
+ ((XRFDC_CLK_DST_ADC3 - Distribution->DistributionSource) << 1));
+ for (ClkDetItr = DelayLeft - 1; ClkDetItr > 0; ClkDetItr--) {
+ ClkDetectReg |= (XRFDC_CLOCK_DETECT_DIST <<
+ ((XRFDC_CLK_DST_ADC3 - (Distribution->DistributionSource - ClkDetItr)) << 1));
+ }
+
+ if ((Distribution->DistributionSource - DelayLeft) < XRFDC_CLK_DST_ADC0) { /*DAC*/
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_DAC_TILE,
+ (Distribution->DistributionSource - DelayLeft)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET, XRFDC_HSCOM_CLK_DSTR_MASK, Reg);
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_CTRL_STS_BASE(XRFDC_DAC_TILE, (Distribution->DistributionSource - DelayLeft)),
+ XRFDC_CLOCK_DETECT_OFFSET, XRFDC_CLOCK_DETECT_MASK, ClkDetectReg);
+ } else { /*ADC*/
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_ADC_TILE, (Distribution->DistributionSource -
+ DelayLeft - XRFDC_CLK_DST_ADC0)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET, XRFDC_HSCOM_CLK_DSTR_MASK, Reg);
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_CTRL_STS_BASE(XRFDC_ADC_TILE,
+ (Distribution->DistributionSource - DelayLeft - XRFDC_CLK_DST_ADC0)),
+ XRFDC_CLOCK_DETECT_OFFSET, XRFDC_CLOCK_DETECT_MASK, ClkDetectReg);
+ }
+ }
+ /*Rest of tiles left of Distribution->DistributionSource*/
+ for (Delay = 1; Delay < DelayLeft; Delay++) {
+ Reg = XRFDC_CLK_DISTR_MUX6_SRC_OFF | XRFDC_CLK_DISTR_MUX7_SRC_STH |
+ XRFDC_CLK_DISTR_MUX8_SRC_INT | XRFDC_CLK_DISTR_MUX9_SRC_INT;
+ if (FeedBackForInputLeft == 0) {
+ Reg |= XRFDC_CLK_DISTR_MUX4A_SRC_STH;
+ } else {
+ Reg |= XRFDC_CLK_DISTR_MUX4A_SRC_INT;
+ }
+ *Delays[Distribution->DistributionSource - Delay] =
+ DelayOutSourceLeft + ((Delay + FeedBackForInputLeft) << 1);
+ Distribution->MaxDelay =
+ MAX(Distribution->MaxDelay, (*Delays[Distribution->DistributionSource - Delay]));
+ Distribution->MinDelay =
+ MIN(Distribution->MinDelay, (*Delays[Distribution->DistributionSource - Delay]));
+ FeedBackForInputLeft = !FeedBackForInputLeft;
+
+ /* setup clk detect register */
+ ClkDetectReg = (XRFDC_CLOCK_DETECT_BOTH <<
+ ((XRFDC_CLK_DST_ADC3 - Distribution->DistributionSource) << 1));
+ for (ClkDetItr = Delay - 1; ClkDetItr > 0; ClkDetItr--) {
+ ClkDetectReg |= (XRFDC_CLOCK_DETECT_DIST <<
+ ((XRFDC_CLK_DST_ADC3 - (Distribution->DistributionSource - ClkDetItr)) << 1));
+ }
+
+ if ((Distribution->DistributionSource - Delay) < XRFDC_CLK_DST_ADC0) { /*DAC*/
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_DAC_TILE,
+ (Distribution->DistributionSource - Delay)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET, XRFDC_HSCOM_CLK_DSTR_MASK, Reg);
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_CTRL_STS_BASE(XRFDC_DAC_TILE, (Distribution->DistributionSource - Delay)),
+ XRFDC_CLOCK_DETECT_OFFSET, XRFDC_CLOCK_DETECT_MASK, ClkDetectReg);
+ } else { /*ADC*/
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_ADC_TILE, (Distribution->DistributionSource -
+ Delay - XRFDC_CLK_DST_ADC0)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET, XRFDC_HSCOM_CLK_DSTR_MASK, Reg);
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_CTRL_STS_BASE(XRFDC_ADC_TILE,
+ (Distribution->DistributionSource - Delay - XRFDC_CLK_DST_ADC0)),
+ XRFDC_CLOCK_DETECT_OFFSET, XRFDC_CLOCK_DETECT_MASK, ClkDetectReg);
+ }
+ }
+ /*Rightmost tile*/
+ if (DelayRight) {
+ Reg = XRFDC_CLK_DISTR_MUX4A_SRC_INT | XRFDC_CLK_DISTR_MUX6_SRC_OFF |
+ XRFDC_CLK_DISTR_MUX7_SRC_OFF | XRFDC_CLK_DISTR_MUX8_SRC_NTH |
+ XRFDC_CLK_DISTR_MUX9_SRC_NTH;
+ *Delays[Distribution->UpperBound] = DelayOutSourceRight + (DelayRight << 1);
+ Distribution->MaxDelay = MAX(Distribution->MaxDelay, (*Delays[Distribution->UpperBound]));
+ Distribution->MinDelay = MIN(Distribution->MinDelay, (*Delays[Distribution->UpperBound]));
+
+ /* setup clk detect register */
+ ClkDetectReg = (XRFDC_CLOCK_DETECT_BOTH <<
+ ((XRFDC_CLK_DST_ADC3 - Distribution->DistributionSource) << 1));
+ for (ClkDetItr = DelayRight - 1; ClkDetItr > 0; ClkDetItr--) {
+ ClkDetectReg |= (XRFDC_CLOCK_DETECT_DIST <<
+ ((XRFDC_CLK_DST_ADC3 - (Distribution->DistributionSource + ClkDetItr)) << 1));
+ }
+
+ if ((Distribution->DistributionSource + DelayRight) < XRFDC_CLK_DST_ADC0) { /*DAC*/
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_DAC_TILE,
+ (Distribution->DistributionSource + DelayRight)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET, XRFDC_HSCOM_CLK_DSTR_MASK, Reg);
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_CTRL_STS_BASE(XRFDC_DAC_TILE, (Distribution->DistributionSource + DelayRight)),
+ XRFDC_CLOCK_DETECT_OFFSET, XRFDC_CLOCK_DETECT_MASK, ClkDetectReg);
+ } else { /*ADC*/
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_ADC_TILE, (Distribution->DistributionSource +
+ DelayRight - XRFDC_CLK_DST_ADC0)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET, XRFDC_HSCOM_CLK_DSTR_MASK, Reg);
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_CTRL_STS_BASE(XRFDC_ADC_TILE,
+ (Distribution->DistributionSource + DelayRight - XRFDC_CLK_DST_ADC0)),
+ XRFDC_CLOCK_DETECT_OFFSET, XRFDC_CLOCK_DETECT_MASK, ClkDetectReg);
+ }
+ }
+ /*rest of tiles to right*/
+ for (Delay = 1; Delay < DelayRight; Delay++) {
+ if (((Delay + Distribution->DistributionSource) == 3) || (FeedBackForInputRight == 0)) {
+ FeedBackForInputRight = 0;
+ Reg = XRFDC_CLK_DISTR_MUX4A_SRC_INT;
+ *Delays[Distribution->DistributionSource + Delay] = DelayOutSourceRight + (Delay << 1);
+ } else {
+ Reg = XRFDC_CLK_DISTR_MUX4A_SRC_STH;
+ *Delays[Distribution->DistributionSource + Delay] =
+ DelayOutSourceRight + ((Delay + 1) << 1);
+ }
+ Distribution->MaxDelay =
+ MAX(Distribution->MaxDelay, (*Delays[Distribution->DistributionSource + Delay]));
+ Distribution->MinDelay =
+ MIN(Distribution->MinDelay, (*Delays[Distribution->DistributionSource + Delay]));
+ FeedBackForInputRight = !FeedBackForInputRight;
+ Reg |= XRFDC_CLK_DISTR_MUX6_SRC_NTH | XRFDC_CLK_DISTR_MUX7_SRC_OFF |
+ XRFDC_CLK_DISTR_MUX8_SRC_NTH | XRFDC_CLK_DISTR_MUX9_SRC_NTH;
+
+ /* setup clk detect register */
+ ClkDetectReg = (XRFDC_CLOCK_DETECT_BOTH <<
+ ((XRFDC_CLK_DST_ADC3 - Distribution->DistributionSource) << 1));
+ for (ClkDetItr = Delay - 1; ClkDetItr > 0; ClkDetItr--) {
+ ClkDetectReg |= (XRFDC_CLOCK_DETECT_DIST <<
+ ((XRFDC_CLK_DST_ADC3 - (Distribution->DistributionSource + ClkDetItr)) << 1));
+ }
+
+ if ((Distribution->DistributionSource + Delay) < XRFDC_CLK_DST_ADC0) { /*DAC*/
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_DAC_TILE,
+ (Distribution->DistributionSource + Delay)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET, XRFDC_HSCOM_CLK_DSTR_MASK, Reg);
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_CTRL_STS_BASE(XRFDC_DAC_TILE, (Distribution->DistributionSource + Delay)),
+ XRFDC_CLOCK_DETECT_OFFSET, XRFDC_CLOCK_DETECT_MASK, ClkDetectReg);
+ } else { /*ADC*/
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_ADC_TILE, (Distribution->DistributionSource +
+ Delay - XRFDC_CLK_DST_ADC0)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET, XRFDC_HSCOM_CLK_DSTR_MASK, Reg);
+ XRFdc_ClrSetReg(InstancePtr,
+ XRFDC_CTRL_STS_BASE(XRFDC_ADC_TILE,
+ (Distribution->DistributionSource + Delay - XRFDC_CLK_DST_ADC0)),
+ XRFDC_CLOCK_DETECT_OFFSET, XRFDC_CLOCK_DETECT_MASK, ClkDetectReg);
+ }
+ }
+ Distribution->IsDelayBalanced = (Distribution->MaxDelay == Distribution->MinDelay) ? 1 : 0;
+ }
+ for (Tile = 0; Tile < XRFDC_NUM_OF_TILES4; Tile++) {
+ XRFdc_SetTileClkSettings(InstancePtr, XRFDC_ADC_TILE, Tile, &DistributionSettingsPtr->ADC[Tile]);
+ XRFdc_SetTileClkSettings(InstancePtr, XRFDC_DAC_TILE, Tile, &DistributionSettingsPtr->DAC[Tile]);
+ }
+ Status = XRFdc_StartUp(InstancePtr, XRFDC_ADC_TILE, -1);
+ if (Status != XRFDC_SUCCESS) {
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ Status = XRFdc_StartUp(InstancePtr, XRFDC_DAC_TILE, -1);
+ if (Status != XRFDC_SUCCESS) {
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+/*****************************************************************************/
+/**
+*
+* This function is used to get the clock distribution
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param DistributionSettingsPtr pointer to get the distribution settings
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if no valid distribution found.
+*
+******************************************************************************/
+u32 XRFdc_GetClkDistribution(XRFdc *InstancePtr, XRFdc_Distribution_Settings *DistributionSettingsPtr)
+{
+ u32 Status;
+ u16 ReadReg;
+ u8 *Tile[8];
+ u8 CurrentTile;
+ s8 AdjacentTile;
+ u8 DelayOutSourceLeft;
+ u8 DelayOutSourceRight;
+ u8 *Delays[8];
+ XRFdc_Distribution *Distribution;
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(DistributionSettingsPtr != 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;
+ }
+
+ Distribution = DistributionSettingsPtr->DistributionStatus;
+ Delays[0] = &DistributionSettingsPtr->DAC[0].Delay;
+ Delays[1] = &DistributionSettingsPtr->DAC[1].Delay;
+ Delays[2] = &DistributionSettingsPtr->DAC[2].Delay;
+ Delays[3] = &DistributionSettingsPtr->DAC[3].Delay;
+ Delays[4] = &DistributionSettingsPtr->ADC[0].Delay;
+ Delays[5] = &DistributionSettingsPtr->ADC[1].Delay;
+ Delays[6] = &DistributionSettingsPtr->ADC[2].Delay;
+ Delays[7] = &DistributionSettingsPtr->ADC[3].Delay;
+ Tile[0] = &DistributionSettingsPtr->DAC[0].SourceTile;
+ Tile[1] = &DistributionSettingsPtr->DAC[1].SourceTile;
+ Tile[2] = &DistributionSettingsPtr->DAC[2].SourceTile;
+ Tile[3] = &DistributionSettingsPtr->DAC[3].SourceTile;
+ Tile[4] = &DistributionSettingsPtr->ADC[0].SourceTile;
+ Tile[5] = &DistributionSettingsPtr->ADC[1].SourceTile;
+ Tile[6] = &DistributionSettingsPtr->ADC[2].SourceTile;
+ Tile[7] = &DistributionSettingsPtr->ADC[3].SourceTile;
+ memset(DistributionSettingsPtr, XRFDC_CLK_DST_INVALID, sizeof(XRFdc_Distribution_Settings));
+
+ for (CurrentTile = 0; CurrentTile < XRFDC_DIST_MAX; CurrentTile++) {
+ DelayOutSourceLeft = 0;
+ DelayOutSourceRight = 0;
+ if (*Tile[CurrentTile] != XRFDC_CLK_DST_INVALID) {
+ continue;
+ }
+
+ if (CurrentTile < XRFDC_CLK_DST_ADC0) { /*DAC*/
+ ReadReg = XRFdc_ReadReg16(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_DAC_TILE, CurrentTile) + XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET) &
+ XRFDC_HSCOM_CLK_DSTR_MASK;
+ } else { /*ADC*/
+ ReadReg = XRFdc_ReadReg16(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_ADC_TILE, (CurrentTile - XRFDC_CLK_DST_ADC0)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET) &
+ XRFDC_HSCOM_CLK_DSTR_MASK;
+ }
+
+ if (ReadReg == XRFDC_CLK_DISTR_OFF) { /*it is its own source no dist*/
+ *Tile[CurrentTile] = CurrentTile;
+ *Delays[CurrentTile] = 0;
+ Distribution->MaxDelay = 0;
+ Distribution->MinDelay = 0;
+ Distribution->IsDelayBalanced = 1;
+ Distribution++;
+ } else if (ReadReg & (XRFDC_CLK_DISTR_MUX6_SRC_INT |
+ XRFDC_CLK_DISTR_MUX7_SRC_INT)) { /*it is its own source, distributes its clk*/
+ Distribution->MaxDelay = 0;
+ Distribution->MinDelay = 255;
+ Distribution->IsDelayBalanced = 0;
+ *Tile[CurrentTile] = CurrentTile;
+ if (ReadReg & XRFDC_CLK_DISTR_MUX7_SRC_STH) {
+ DelayOutSourceLeft = 2;
+ } else if (ReadReg & XRFDC_CLK_DISTR_MUX6_SRC_NTH) {
+ DelayOutSourceRight = 2;
+ }
+ *Delays[CurrentTile] = DelayOutSourceLeft + DelayOutSourceRight + 2;
+ Distribution->MaxDelay = MAX(Distribution->MaxDelay, (*Delays[CurrentTile]));
+ Distribution->MinDelay = MIN(Distribution->MinDelay, (*Delays[CurrentTile]));
+ /*work right*/
+ for (AdjacentTile = CurrentTile + 1; AdjacentTile <= XRFDC_CLK_DST_ADC3; AdjacentTile++) {
+ if (AdjacentTile < XRFDC_CLK_DST_ADC0) { /*DAC*/
+ ReadReg = XRFdc_ReadReg16(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_DAC_TILE, AdjacentTile) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET) &
+ XRFDC_HSCOM_CLK_DSTR_MASK;
+ } else { /*ADC*/
+ ReadReg = XRFdc_ReadReg16(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_ADC_TILE,
+ (AdjacentTile - XRFDC_CLK_DST_ADC0)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET) &
+ XRFDC_HSCOM_CLK_DSTR_MASK;
+ }
+ if ((ReadReg == XRFDC_CLK_DISTR_CONT_RIGHT_EVEN) &&
+ (AdjacentTile != XRFDC_CLK_DST_DAC3)) {
+ *Tile[AdjacentTile] = CurrentTile;
+ *Delays[AdjacentTile] =
+ DelayOutSourceRight + ((AdjacentTile - CurrentTile) << 1) + 2;
+ Distribution->MaxDelay = MAX(Distribution->MaxDelay, (*Delays[AdjacentTile]));
+ Distribution->MinDelay = MIN(Distribution->MinDelay, (*Delays[AdjacentTile]));
+ } else if (ReadReg == XRFDC_CLK_DISTR_CONT_RIGHT_HWL_ODD) {
+ *Tile[AdjacentTile] = CurrentTile;
+ *Delays[AdjacentTile] =
+ DelayOutSourceRight + ((AdjacentTile - CurrentTile) << 1);
+ Distribution->MaxDelay = MAX(Distribution->MaxDelay, (*Delays[AdjacentTile]));
+ Distribution->MinDelay = MIN(Distribution->MinDelay, (*Delays[AdjacentTile]));
+ } else if (ReadReg == XRFDC_CLK_DISTR_RIGHTMOST_TILE) {
+ *Tile[AdjacentTile] = CurrentTile;
+ *Delays[AdjacentTile] =
+ DelayOutSourceRight + ((AdjacentTile - CurrentTile) << 1);
+ Distribution->MaxDelay = MAX(Distribution->MaxDelay, (*Delays[AdjacentTile]));
+ Distribution->MinDelay = MIN(Distribution->MinDelay, (*Delays[AdjacentTile]));
+ break;
+ } else {
+ break;
+ }
+ }
+ /*work left*/
+ for (AdjacentTile = CurrentTile - 1; AdjacentTile >= XRFDC_CLK_DST_DAC0; AdjacentTile--) {
+ if (*Tile[AdjacentTile] != XRFDC_CLK_DST_INVALID) {
+ break;
+ }
+ if (AdjacentTile < XRFDC_CLK_DST_ADC0) { /*DAC*/
+ ReadReg = XRFdc_ReadReg16(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_DAC_TILE, AdjacentTile) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET) &
+ XRFDC_HSCOM_CLK_DSTR_MASK;
+ } else { /*ADC*/
+ ReadReg = XRFdc_ReadReg16(InstancePtr,
+ XRFDC_DRP_BASE(XRFDC_ADC_TILE,
+ (AdjacentTile - XRFDC_CLK_DST_ADC0)) +
+ XRFDC_HSCOM_ADDR,
+ XRFDC_HSCOM_CLK_DSTR_OFFSET) &
+ XRFDC_HSCOM_CLK_DSTR_MASK;
+ }
+ if (ReadReg == XRFDC_CLK_DISTR_LEFTMOST_TILE) {
+ *Tile[AdjacentTile] = CurrentTile;
+ *Delays[AdjacentTile] =
+ DelayOutSourceLeft + ((CurrentTile - AdjacentTile) << 1);
+ break;
+ } else if (ReadReg == XRFDC_CLK_DISTR_CONT_LEFT_EVEN) {
+ *Tile[AdjacentTile] = CurrentTile;
+ *Delays[AdjacentTile] =
+ DelayOutSourceLeft + ((CurrentTile - AdjacentTile) << 1) + 2;
+ } else if (ReadReg == XRFDC_CLK_DISTR_CONT_LEFT_ODD) {
+ *Delays[AdjacentTile] =
+ DelayOutSourceLeft + ((CurrentTile - AdjacentTile) << 1);
+ *Tile[AdjacentTile] = CurrentTile;
+ } else {
+ break;
+ }
+ Distribution->MaxDelay = MAX(Distribution->MaxDelay, (*Delays[AdjacentTile]));
+ Distribution->MinDelay = MIN(Distribution->MinDelay, (*Delays[AdjacentTile]));
+ }
+ Distribution->IsDelayBalanced = (Distribution->MaxDelay == Distribution->MinDelay) ? 1 : 0;
+ Distribution++;
+ }
+ }
+ Status = XRFdc_CheckClkDistValid(InstancePtr, DistributionSettingsPtr);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Distribution "
+ "in %s\r\n",
+ __func__);
+ goto RETURN_PATH;
+ }
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+/*****************************************************************************/
+/**
+*
+* This function gets Clock source
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type indicates ADC/DAC.
+* @param Tile_Id indicates Tile number (0-3).
+* @param ClockSourcePtr Pointer to return the clock source
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Tile not enabled.
+*
+* @note None.
+*
+******************************************************************************/
+u32 XRFdc_GetClockSource(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 *ClockSourcePtr)
+{
+ u32 BaseAddr;
+ u32 Status;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(ClockSourcePtr != NULL);
+
+ 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;
+
+ *ClockSourcePtr = XRFdc_RDReg(InstancePtr, BaseAddr,
+ XRFDC_CLK_NETWORK_CTRL1, XRFDC_CLK_NETWORK_CTRL1_USE_PLL_MASK);
+
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function gets PLL lock status
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type indicates ADC/DAC.
+* @param Tile_Id indicates Tile number (0-3).
+* @param LockStatusPtr Pointer to return the PLL lock status
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Tile not enabled.
+*
+* @note None.
+*
+******************************************************************************/
+u32 XRFdc_GetPLLLockStatus(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 *LockStatusPtr)
+{
+ u32 BaseAddr;
+ u32 ReadReg;
+ u32 ClkSrc = 0U;
+ u32 Status;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(LockStatusPtr != NULL);
+
+ /*
+ * Get Tile clock source information
+ */
+ if (XRFdc_GetClockSource(InstancePtr, Type, Tile_Id, &ClkSrc)
+ != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR, "\n Get clock source request Tile %d "
+ "failed in %s\r\n", Tile_Id, __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ if (ClkSrc == XRFDC_EXTERNAL_CLK) {
+ metal_log(METAL_LOG_DEBUG, "\n Requested Tile %d "
+ "uses external clock source in %s\r\n", Tile_Id, __func__);
+ *LockStatusPtr = XRFDC_PLL_LOCKED;
+ } else {
+ if (Type == XRFDC_ADC_TILE) {
+ BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ } else {
+ BaseAddr = XRFDC_DAC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ }
+
+ ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_STATUS_OFFSET,
+ XRFDC_PLL_LOCKED_MASK);
+ if (ReadReg != 0U) {
+ *LockStatusPtr = XRFDC_PLL_LOCKED;
+ } else {
+ *LockStatusPtr = XRFDC_PLL_UNLOCKED;
+ }
+ }
+
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function used for configuring the internal PLL registers
+* based on reference clock and sampling rate
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type indicates ADC/DAC.
+* @param Tile_Id indicates Tile number (0-3).
+* @param RefClkFreq Reference Clock Frequency MHz(50MHz - 1.2GHz)
+* @param SamplingRate Sampling Rate in MHz(0.5- 4 GHz)
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Tile not enabled.
+*
+* @note None.
+*
+******************************************************************************/
+static u32 XRFdc_SetPLLConfig(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ double RefClkFreq, double SamplingRate)
+{
+ u32 BaseAddr;
+ u32 Status;
+ u32 FeedbackDiv;
+ u32 OutputDiv;
+ double CalcSamplingRate;
+ double PllFreq;
+ double SamplingError;
+ u32 Best_FeedbackDiv = 0x0U;
+ u32 Best_OutputDiv = 0x2U;
+ double Best_Error = 0xFFFFFFFFU;
+ u32 DivideMode = 0x0U;
+ u32 DivideValue = 0x0U;
+ u32 PllFreqIndex = 0x0U;
+ u32 FbDivIndex = 0x0U;
+ u32 RefClkDiv = 0x1;
+ u16 ReadReg;
+
+ if (Type == XRFDC_ADC_TILE) {
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id);
+ } else {
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id);
+ }
+
+ BaseAddr += XRFDC_HSCOM_ADDR;
+
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, XRFDC_PLL_REFDIV);
+ if (ReadReg & XRFDC_REFCLK_DIV_1_MASK) {
+ RefClkDiv = XRFDC_REF_CLK_DIV_1;
+ } else {
+ switch (ReadReg & XRFDC_REFCLK_DIV_MASK) {
+ case XRFDC_REFCLK_DIV_2_MASK:
+ RefClkDiv = XRFDC_REF_CLK_DIV_2;
+ break;
+ case XRFDC_REFCLK_DIV_3_MASK:
+ RefClkDiv = XRFDC_REF_CLK_DIV_3;
+ break;
+ case XRFDC_REFCLK_DIV_4_MASK:
+ RefClkDiv = XRFDC_REF_CLK_DIV_4;
+ break;
+ default:
+ /*
+ * IP currently supporting 1 to 4 divider values. This
+ * error condition might change in future based on IP update.
+ */
+ metal_log(METAL_LOG_ERROR, "\n Unsupported Reference "
+ "clock Divider value in %s\r\n", __func__);
+ return XRFDC_FAILURE;
+ }
+ }
+
+ RefClkFreq /= RefClkDiv;
+
+ /*
+ * Sweep valid integer values of FeedbackDiv(N) and record a list
+ * of values that fall in the valid VCO range 8.5GHz - 12.8GHz
+ */
+ for (FeedbackDiv = PLL_FPDIV_MIN; FeedbackDiv <= PLL_FPDIV_MAX;
+ FeedbackDiv++) {
+
+ PllFreq = FeedbackDiv * RefClkFreq;
+
+ if ((PllFreq >= VCO_RANGE_MIN) && (PllFreq <= VCO_RANGE_MAX)) {
+ /*
+ * Sweep values of OutputDiv(M) to find the output frequency
+ * that best matches the user requested value
+ */
+
+ for (OutputDiv = PLL_DIVIDER_MIN; OutputDiv <= PLL_DIVIDER_MAX;
+ OutputDiv += 2U) {
+
+ CalcSamplingRate = (PllFreq / OutputDiv);
+
+ if (SamplingRate > CalcSamplingRate) {
+ SamplingError = SamplingRate - CalcSamplingRate;
+ } else {
+ SamplingError = CalcSamplingRate - SamplingRate;
+ }
+
+ if (Best_Error > SamplingError) {
+ Best_FeedbackDiv = FeedbackDiv;
+ Best_OutputDiv = OutputDiv;
+ Best_Error = SamplingError;
+ }
+ }
+
+ OutputDiv = 3U;
+ CalcSamplingRate = (PllFreq / OutputDiv);
+
+ if (SamplingRate > CalcSamplingRate) {
+ SamplingError = SamplingRate - CalcSamplingRate;
+ } else {
+ SamplingError = CalcSamplingRate - SamplingRate;
+ }
+
+ if (Best_Error > SamplingError) {
+ Best_FeedbackDiv = FeedbackDiv;
+ Best_OutputDiv = OutputDiv;
+ Best_Error = SamplingError;
+ }
+ }
+
+ /*
+ * PLL Static configuration
+ */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_SDM_CFG0, 0x80U);
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_SDM_SEED0, 0x111U);
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_SDM_SEED1, 0x11U);
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_VREG, 0x45U);
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_VCO0, 0x5800U);
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_VCO1, 0x08U);
+
+ /*
+ * Set Feedback divisor value
+ */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_FPDIV,
+ Best_FeedbackDiv - 2U);
+
+ /*
+ * Set Output divisor value
+ */
+ if (Best_OutputDiv == 2U) {
+ DivideMode = 0x1U;
+ } else if (Best_OutputDiv == 3U) {
+ DivideMode = 0x2U;
+ DivideValue = 0x1U;
+ } else if (Best_OutputDiv >= 4U) {
+ DivideMode = 0x3U;
+ DivideValue = ((Best_OutputDiv - 4U)/2U);
+ }
+
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_PLL_DIVIDER0,
+ XRFDC_PLL_DIVIDER0_MASK, ((DivideMode << XRFDC_PLL_DIVIDER0_SHIFT) | DivideValue));
+
+ /*
+ * Enable fine sweep
+ */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_CRS2, XRFDC_PLL_CRS2_VAL);
+
+ /*
+ * Set default PLL spare inputs LSB
+ */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_SPARE0, 0x507U);
+
+ /*
+ * Set PLL spare inputs MSB
+ */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_SPARE1, 0x0U);
+
+ PllFreq = RefClkFreq * Best_FeedbackDiv;
+
+ if (PllFreq < 9400U) {
+ PllFreqIndex = 0U;
+ FbDivIndex = 2U;
+ if (Best_FeedbackDiv < 21U) {
+ FbDivIndex = 0U;
+ } else if (Best_FeedbackDiv < 30U) {
+ FbDivIndex = 1U;
+ }
+ } else if (PllFreq < 10070U) {
+ PllFreqIndex = 1U;
+ FbDivIndex = 2U;
+ if (Best_FeedbackDiv < 18U) {
+ FbDivIndex = 0U;
+ } else if (Best_FeedbackDiv < 30U) {
+ FbDivIndex = 1U;
+ }
+ } else if (PllFreq < 10690U) {
+ PllFreqIndex = 2U;
+ FbDivIndex = 3U;
+ if (Best_FeedbackDiv < 18U) {
+ FbDivIndex = 0U;
+ } else if (Best_FeedbackDiv < 25U) {
+ FbDivIndex = 1U;
+ } else if (Best_FeedbackDiv < 35U) {
+ FbDivIndex = 2U;
+ }
+ } else if (PllFreq < 10990U) {
+ PllFreqIndex = 3U;
+ FbDivIndex = 3U;
+ if (Best_FeedbackDiv < 19U) {
+ FbDivIndex = 0U;
+ } else if (Best_FeedbackDiv < 27U) {
+ FbDivIndex = 1U;
+ } else if (Best_FeedbackDiv < 38U) {
+ FbDivIndex = 2U;
+ }
+ } else if (PllFreq < 11430U) {
+ PllFreqIndex = 4U;
+ FbDivIndex = 3U;
+ if (Best_FeedbackDiv < 19U) {
+ FbDivIndex = 0U;
+ } else if (Best_FeedbackDiv < 27U) {
+ FbDivIndex = 1U;
+ } else if (Best_FeedbackDiv < 38U) {
+ FbDivIndex = 2U;
+ }
+ } else if (PllFreq < 12040U) {
+ PllFreqIndex = 5U;
+ FbDivIndex = 3U;
+ if (Best_FeedbackDiv < 20U) {
+ FbDivIndex = 0U;
+ } else if (Best_FeedbackDiv < 28U) {
+ FbDivIndex = 1U;
+ } else if (Best_FeedbackDiv < 40U) {
+ FbDivIndex = 2U;
+ }
+ } else if (PllFreq < 12530U) {
+ PllFreqIndex = 6U;
+ FbDivIndex = 3U;
+ if (Best_FeedbackDiv < 23U) {
+ FbDivIndex = 0U;
+ } else if (Best_FeedbackDiv < 30U) {
+ FbDivIndex = 1U;
+ } else if (Best_FeedbackDiv < 42U) {
+ FbDivIndex = 2U;
+ }
+ } else if (PllFreq < 20000U) {
+ PllFreqIndex = 7U;
+ FbDivIndex = 2U;
+ if (Best_FeedbackDiv < 20U) {
+ FbDivIndex = 0U;
+ /*
+ * Set PLL spare inputs LSB
+ */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_SPARE0, 0x577);
+ } else if (Best_FeedbackDiv < 39U) {
+ FbDivIndex = 1U;
+ }
+ }
+
+ /*
+ * Enable automatic selection of the VCO, this will work with the
+ * IP version 2.0.1 and above and using older version of IP is
+ * not likely to work.
+ */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_PLL_CRS1,
+ XRFDC_PLL_VCO_SEL_AUTO_MASK, XRFDC_PLL_VCO_SEL_AUTO_MASK);
+
+ /*
+ * PLL bits for loop filters LSB
+ */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_LPF0,
+ PllTuningMatrix[PllFreqIndex][FbDivIndex][0]);
+
+ /*
+ * PLL bits for loop filters MSB
+ */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_LPF1, XRFDC_PLL_LPF1_VAL);
+
+ /*
+ * Set PLL bits for charge pumps
+ */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_PLL_CHARGEPUMP,
+ PllTuningMatrix[PllFreqIndex][FbDivIndex][1]);
+ }
+
+ CalcSamplingRate = (Best_FeedbackDiv * RefClkFreq) / Best_OutputDiv;
+ CalcSamplingRate /= XRFDC_MILLI;
+
+ if (Type == XRFDC_ADC_TILE) {
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.SampleRate =
+ CalcSamplingRate;
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.RefClkDivider = RefClkDiv;
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.FeedbackDivider = Best_FeedbackDiv;
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.OutputDivider = Best_OutputDiv;
+ } else {
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.SampleRate =
+ CalcSamplingRate;
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.RefClkDivider = RefClkDiv;
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.FeedbackDivider = Best_FeedbackDiv;
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.OutputDivider = Best_OutputDiv;
+ }
+
+ Status = XRFDC_SUCCESS;
+
+ return Status;
+}
+/*****************************************************************************/
+/**
+*
+* This API is used to get the PLL Configurations.
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type represents ADC or DAC.
+* @param Tile_Id Valid values are 0-3.
+* @param PLLSettings pointer to the XRFdc_PLL_Settings structure to get
+* the PLL configurations
+*
+* @return None
+*
+******************************************************************************/
+u32 XRFdc_GetPLLConfig(XRFdc *InstancePtr, u32 Type,
+ u32 Tile_Id, XRFdc_PLL_Settings *PLLSettings)
+{
+ u32 Status;
+ u32 BaseAddr;
+ u16 ReadReg;
+ double RefClkFreq;
+ double SampleRate;
+ u32 FeedbackDivider;
+ u8 OutputDivider;
+ u32 RefClkDivider;
+ u32 Enabled;
+ u8 DivideMode;
+ u32 PLLFreq;
+ u32 PLLFS;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+ Xil_AssertNonvoid(PLLSettings != NULL);
+
+ 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);
+ PLLFreq = XRFdc_ReadReg(InstancePtr, BaseAddr, XRFDC_PLL_FREQ);
+
+ RefClkFreq = ((double)PLLFreq)/1000;
+ PLLFS = XRFdc_ReadReg(InstancePtr, BaseAddr, XRFDC_PLL_FS);
+ SampleRate = ((double)PLLFS)/1000000;
+ if (PLLFS == 0) {
+ /*This code is here to support the old IPs.*/
+ if (Type == XRFDC_ADC_TILE) {
+ PLLSettings->Enabled =
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.Enabled;
+ PLLSettings->FeedbackDivider =
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.FeedbackDivider;
+ PLLSettings->OutputDivider =
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.OutputDivider;
+ PLLSettings->RefClkDivider =
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.RefClkDivider;
+ PLLSettings->RefClkFreq =
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.RefClkFreq;
+ PLLSettings->SampleRate =
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.SampleRate;
+ Status = XRFDC_SUCCESS;
+ goto RETURN_PATH;
+ } else {
+ PLLSettings->Enabled =
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.Enabled;
+ PLLSettings->FeedbackDivider =
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.FeedbackDivider;
+ PLLSettings->OutputDivider =
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.OutputDivider;
+ PLLSettings->RefClkDivider =
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.RefClkDivider;
+ PLLSettings->RefClkFreq =
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.RefClkFreq;
+ PLLSettings->SampleRate =
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.SampleRate;
+ Status = XRFDC_SUCCESS;
+ goto RETURN_PATH;
+ }
+ } else {
+ if (Type == XRFDC_ADC_TILE) {
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id);
+ } else {
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id);
+ }
+
+ BaseAddr += XRFDC_HSCOM_ADDR;
+
+ FeedbackDivider = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_PLL_FPDIV, 0x00FF) + 2;
+
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, XRFDC_PLL_REFDIV);
+ if (ReadReg & XRFDC_REFCLK_DIV_1_MASK) {
+ RefClkDivider = XRFDC_REF_CLK_DIV_1;
+ } else {
+ switch (ReadReg & XRFDC_REFCLK_DIV_MASK) {
+ case XRFDC_REFCLK_DIV_2_MASK:
+ RefClkDivider = XRFDC_REF_CLK_DIV_2;
+ break;
+ case XRFDC_REFCLK_DIV_3_MASK:
+ RefClkDivider = XRFDC_REF_CLK_DIV_3;
+ break;
+ case XRFDC_REFCLK_DIV_4_MASK:
+ RefClkDivider = XRFDC_REF_CLK_DIV_4;
+ break;
+ default:
+ /*
+ * IP currently supporting 1 to 4 divider values. This
+ * error condition might change in future based on IP update.
+ */
+ metal_log(METAL_LOG_ERROR, "\n Unsupported Reference "
+ "clock Divider value in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ }
+ if (InstancePtr->RFdc_Config.IPType < 2) {
+ if (XRFdc_GetClockSource(InstancePtr, Type, Tile_Id, &Enabled)
+ != XRFDC_SUCCESS) {
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ } else {
+ Enabled = (ReadReg & XRFDC_PLLREFDIV_INPUT_OFF)?XRFDC_DISABLED:XRFDC_ENABLED;
+ }
+
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, XRFDC_PLL_DIVIDER0);
+ DivideMode = (ReadReg & XRFDC_PLL_DIVIDER0_MODE_MASK) >> XRFDC_PLL_DIVIDER0_SHIFT;
+
+ switch(DivideMode) {
+ case XRFDC_PLL_OUTDIV_MODE_1:
+ OutputDivider = 1;
+ break;
+ case XRFDC_PLL_OUTDIV_MODE_2:
+ OutputDivider = 2;
+ break;
+ case XRFDC_PLL_OUTDIV_MODE_3:
+ OutputDivider = 3;
+ break;
+ case XRFDC_PLL_OUTDIV_MODE_N:
+ OutputDivider = ((ReadReg & XRFDC_PLL_DIVIDER0_VALUE_MASK) + 2) << 1;
+ break;
+ default:
+ metal_log(METAL_LOG_ERROR, "\n Unsupported Output "
+ "clock Divider value in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ break;
+ }
+ PLLSettings->Enabled = Enabled;
+ PLLSettings->FeedbackDivider = FeedbackDivider;
+ PLLSettings->OutputDivider = OutputDivider;
+ PLLSettings->RefClkDivider = RefClkDivider;
+ PLLSettings->RefClkFreq = RefClkFreq;
+ PLLSettings->SampleRate = SampleRate;
+ }
+
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function used for dynamically switch between internal PLL and
+* external clcok source and configuring the internal PLL
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type indicates ADC/DAC
+* @param Tile_Id indicates Tile number (0-3)
+* @param Source Clock source internal PLL or external clock source
+* @param RefClkFreq Reference Clock Frequency in MHz(102.40625MHz - 1.2GHz)
+* @param SamplingRate Sampling Rate in MHz(0.1- 6.554GHz for DAC and
+* 0.5/1.0 - 2.058/4.116GHz for ADC based on the device package).
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Tile not enabled.
+*
+* @note This API enables automatic selection of the VCO which will work in
+* IP version 2.0.1 and above. Using older version of IP this API is
+* not likely to work.
+*
+******************************************************************************/
+u32 XRFdc_DynamicPLLConfig(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u8 Source, double RefClkFreq, double SamplingRate)
+{
+ u32 ClkSrc = 0U;
+ u32 Status;
+ u32 BaseAddr;
+ u32 PLLEnable = 0x0;
+ u32 InitialPowerUpState;
+ double MaxSampleRate;
+ double MinSampleRate;
+ u32 PLLFreq;
+ u32 PLLFS;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ if ((Source != XRFDC_INTERNAL_PLL_CLK) &&
+ (Source != XRFDC_EXTERNAL_CLK)) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid Source "
+ "value in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ 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;
+ }
+
+ /*
+ * Get Tile clock source information
+ */
+ if (XRFdc_GetClockSource(InstancePtr, Type, Tile_Id, &ClkSrc)
+ != XRFDC_SUCCESS) {
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ if (XRFdc_GetMaxSampleRate(InstancePtr, Type, Tile_Id, &MaxSampleRate) != XRFDC_SUCCESS) {
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if (XRFdc_GetMinSampleRate(InstancePtr, Type, Tile_Id, &MinSampleRate) != XRFDC_SUCCESS) {
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if ((SamplingRate < MinSampleRate) ||
+ (SamplingRate > MaxSampleRate)) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid sampling "
+ "rate value in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ BaseAddr = XRFDC_CTRL_STS_BASE(Type, Tile_Id);
+
+ if (Source == XRFDC_INTERNAL_PLL_CLK) {
+ if ((RefClkFreq < XRFDC_REFFREQ_MIN) ||
+ (RefClkFreq > XRFDC_REFFREQ_MAX)) {
+ metal_log(METAL_LOG_ERROR, "\n Input reference clock "
+ "frequency does not respect the specifications "
+ "for internal PLL usage. Please use a different "
+ "frequency or bypass the internal PLL", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ }
+
+ PLLFreq = (u32)(RefClkFreq*1000);
+ PLLFS = (u32)(SamplingRate*1000);
+ XRFdc_WriteReg(InstancePtr, BaseAddr, XRFDC_PLL_FREQ, PLLFreq);
+ XRFdc_WriteReg(InstancePtr, BaseAddr, XRFDC_PLL_FS, PLLFS);
+
+ if ((Source != XRFDC_INTERNAL_PLL_CLK) &&
+ (ClkSrc != XRFDC_INTERNAL_PLL_CLK)) {
+ metal_log(METAL_LOG_DEBUG, "\n Requested Tile %d "
+ "uses external clock source in %s\r\n", Tile_Id, __func__);
+ if (Type == XRFDC_ADC_TILE) {
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.SampleRate =
+ (double)(SamplingRate/1000);
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.RefClkFreq = RefClkFreq;
+ } else {
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.SampleRate =
+ (double)(SamplingRate/1000);
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.RefClkFreq = RefClkFreq;
+ }
+ Status = XRFDC_SUCCESS;
+ goto RETURN_PATH;
+ }
+
+ if (Type == XRFDC_ADC_TILE) {
+ BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ InitialPowerUpState = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_STATUS_OFFSET, XRFDC_PWR_UP_STAT_MASK) >> XRFDC_PWR_UP_STAT_SHIFT;
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) + XRFDC_HSCOM_ADDR;
+ } else {
+ BaseAddr = XRFDC_DAC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ InitialPowerUpState = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_STATUS_OFFSET, XRFDC_PWR_UP_STAT_MASK) >> XRFDC_PWR_UP_STAT_SHIFT;
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) + XRFDC_HSCOM_ADDR;
+ }
+
+ /*
+ * Stop the ADC or DAC tile by putting tile in reset state if not stopped already
+ */
+ if (InitialPowerUpState != XRFDC_DISABLED) {
+ Status = XRFdc_Shutdown(InstancePtr, Type, Tile_Id) ;
+ if (Status != XRFDC_SUCCESS) {
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ }
+ if (Source == XRFDC_INTERNAL_PLL_CLK) {
+ PLLEnable = 0x1;
+ /*
+ * Configure the PLL
+ */
+ if (XRFdc_SetPLLConfig(InstancePtr, Type, Tile_Id, RefClkFreq,
+ SamplingRate) != XRFDC_SUCCESS) {
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr,
+ XRFDC_CLK_NETWORK_CTRL1, XRFDC_CLK_NETWORK_CTRL1_USE_PLL_MASK,
+ XRFDC_CLK_NETWORK_CTRL1_USE_PLL_MASK);
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_HSCOM_PWR_STATE_OFFSET,
+ XRFDC_HSCOM_PWR_STATS_PLL);
+ } else {
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_CLK_NETWORK_CTRL1,
+ XRFDC_CLK_NETWORK_CTRL1_USE_PLL_MASK, 0x0);
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_HSCOM_PWR_STATE_OFFSET,
+ XRFDC_HSCOM_PWR_STATS_EXTERNAL);
+ SamplingRate /= XRFDC_MILLI;
+
+ if (Type == XRFDC_ADC_TILE) {
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.SampleRate =
+ SamplingRate;
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.RefClkDivider = 0x0U;
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.FeedbackDivider = 0x0U;
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.OutputDivider = 0x0U;
+ } else {
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.SampleRate =
+ SamplingRate;
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.RefClkDivider = 0x0U;
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.FeedbackDivider = 0x0U;
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.OutputDivider = 0x0U;
+ }
+ }
+
+ /*
+ * Re-start the ADC or DAC tile if tile was shut down in this function
+ */
+ if (InitialPowerUpState != XRFDC_DISABLED) {
+ Status = XRFdc_StartUp(InstancePtr, Type, Tile_Id) ;
+ if (Status != XRFDC_SUCCESS) {
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ }
+
+ if (Type == XRFDC_ADC_TILE) {
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.RefClkFreq = RefClkFreq;
+ InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.Enabled = PLLEnable;
+ } else {
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.RefClkFreq = RefClkFreq;
+ InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.Enabled = PLLEnable;
+ }
+
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+/** @} */
diff --git a/mpm/lib/rfdc/xrfdc_g.c b/mpm/lib/rfdc/xrfdc_g.c
new file mode 100644
index 000000000..857fb1ffd
--- /dev/null
+++ b/mpm/lib/rfdc/xrfdc_g.c
@@ -0,0 +1,619 @@
+/*******************************************************************
+* 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_g.c
+* @addtogroup rfdc_v6_0
+* @{
+*
+* This file contains a configuration table that specifies the configuration of
+* RFdc devices in the system.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- --- -------- -----------------------------------------------
+* 1.0 sk 05/16/17 Initial release
+* 5.1 cog 01/29/19 Added FSMax, NumSlice & IP_Type.
+*
+* </pre>
+*
+******************************************************************************/
+#ifdef __BAREMETAL__
+/***************************** Include Files ********************************/
+#include "xparameters.h"
+#include "mpm/rfdc/xrfdc.h"
+/************************** Constant Definitions ****************************/
+
+/**************************** Type Definitions ******************************/
+
+/***************** Macros (Inline Functions) Definitions ********************/
+
+/************************** Variable Definitions ****************************/
+/**
+ * The configuration table for devices
+ */
+
+XRFdc_Config XRFdc_ConfigTable[XPAR_XRFDC_NUM_INSTANCES] =
+{
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DEVICE_ID,
+ XPAR_USP_RF_DATA_CONVERTER_0_BASEADDR,
+ XPAR_USP_RF_DATA_CONVERTER_0_HIGH_SPEED_ADC,
+ XPAR_USP_RF_DATA_CONVERTER_0_SYSREF_MASTER,
+ XPAR_USP_RF_DATA_CONVERTER_0_SYSREF_MASTER,
+ XPAR_USP_RF_DATA_CONVERTER_0_SYSREF_SOURCE,
+ XPAR_USP_RF_DATA_CONVERTER_0_SYSREF_SOURCE,
+ XPAR_USP_RF_DATA_CONVERTER_0_IP_TYPE,
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC0_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC0_PLL_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC0_SAMPLING_RATE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC0_REFCLK_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC0_FABRIC_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC0_FBDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC0_OUTDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC0_REFCLK_DIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC0_BAND,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC0_FS_MAX,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC0_SLICES,
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE00_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL00,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE00,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE00,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE01_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL01,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE01,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE01,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE02_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL02,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE02,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE02,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE03_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL03,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE03,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE03,
+ },
+ },
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE00,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH00,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE00,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO00_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER00_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE00,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE01,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH01,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE01,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO01_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER01_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE01,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE02,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH02,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE02,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO02_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER02_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE02,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE03,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH03,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE03,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO03_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER03_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE03,
+ },
+ },
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC1_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC1_PLL_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC1_SAMPLING_RATE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC1_REFCLK_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC1_FABRIC_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC1_FBDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC1_OUTDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC1_REFCLK_DIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC1_BAND,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC1_FS_MAX,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC1_SLICES,
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE10_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL10,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE10,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE10,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE11_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL11,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE11,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE11,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE12_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL12,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE12,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE12,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE13_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL13,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE13,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE13,
+ },
+ },
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE10,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH10,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE10,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO10_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER10_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE10,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE11,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH11,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE11,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO11_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER11_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE11,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE12,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH12,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE12,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO12_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER12_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE12,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE13,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH13,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE13,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO13_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER13_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE13,
+ },
+ },
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC2_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC2_PLL_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC2_SAMPLING_RATE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC2_REFCLK_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC2_FABRIC_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC2_FBDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC2_OUTDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC2_REFCLK_DIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC2_BAND,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC2_FS_MAX,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC2_SLICES,
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE20_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL20,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE20,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE20,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE21_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL21,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE21,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE21,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE22_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL22,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE22,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE22,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE23_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL23,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE23,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE23,
+ },
+ },
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE20,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH20,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE20,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO20_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER20_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE20,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE21,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH21,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE21,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO21_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER21_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE21,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE22,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH22,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE22,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO22_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER22_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE22,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE23,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH23,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE23,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO23_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER23_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE23,
+ },
+ },
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC3_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC3_PLL_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC3_SAMPLING_RATE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC3_REFCLK_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC3_FABRIC_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC3_FBDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC3_OUTDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC3_REFCLK_DIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC3_BAND,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC3_FS_MAX,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC3_SLICES,
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE30_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL30,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE30,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE30,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE31_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL31,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE31,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE31,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE32_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL32,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE32,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE32,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_SLICE33_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INVSINC_CTRL33,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_MODE33,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DECODER_MODE33,
+ },
+ },
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE30,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH30,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE30,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO30_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER30_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE30,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE31,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH31,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE31,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO31_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER31_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE31,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE32,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH32,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE32,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO32_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER32_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE32,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_TYPE33,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_DATA_WIDTH33,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_INTERPOLATION_MODE33,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_FIFO33_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_ADDER33_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_DAC_MIXER_TYPE33,
+ },
+ },
+ },
+ },
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC0_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC0_PLL_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC0_SAMPLING_RATE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC0_REFCLK_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC0_FABRIC_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC0_FBDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC0_OUTDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC0_REFCLK_DIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC0_BAND,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC0_FS_MAX,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC0_SLICES,
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE00_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE00,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE01_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE01,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE02_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE02,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE03_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE03,
+ },
+ },
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE00,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH00,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE00,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO00_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE00,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE01,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH01,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE01,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO01_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE01,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE02,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH02,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE02,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO02_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE02,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE03,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH03,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE03,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO03_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE03,
+ },
+ },
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC1_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC1_PLL_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC1_SAMPLING_RATE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC1_REFCLK_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC1_FABRIC_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC1_FBDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC1_OUTDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC1_REFCLK_DIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC1_BAND,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC1_FS_MAX,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC1_SLICES,
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE10_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE10,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE11_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE11,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE12_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE12,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE13_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE13,
+ },
+ },
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE10,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH10,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE10,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO10_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE10,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE11,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH11,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE11,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO11_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE11,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE12,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH12,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE12,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO12_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE12,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE13,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH13,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE13,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO13_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE13,
+ },
+ },
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC2_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC2_PLL_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC2_SAMPLING_RATE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC2_REFCLK_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC2_FABRIC_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC2_FBDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC2_OUTDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC2_REFCLK_DIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC2_BAND,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC2_FS_MAX,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC2_SLICES,
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE20_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE20,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE21_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE21,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE22_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE22,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE23_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE23,
+ },
+ },
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE20,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH20,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE20,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO20_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE20,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE21,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH21,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE21,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO21_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE21,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE22,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH22,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE22,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO22_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE22,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE23,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH23,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE23,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO23_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE23,
+ },
+ },
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC3_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC3_PLL_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC3_SAMPLING_RATE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC3_REFCLK_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC3_FABRIC_FREQ,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC3_FBDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC3_OUTDIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC3_REFCLK_DIV,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC3_BAND,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC3_FS_MAX,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC3_SLICES,
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE30_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE30,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE31_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE31,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE32_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE32,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_SLICE33_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_MODE33,
+ },
+ },
+ {
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE30,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH30,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE30,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO30_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE30,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE31,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH31,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE31,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO31_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE31,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE32,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH32,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE32,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO32_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE32,
+ },
+ {
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_TYPE33,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DATA_WIDTH33,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_DECIMATION_MODE33,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_FIFO33_ENABLE,
+ XPAR_USP_RF_DATA_CONVERTER_0_ADC_MIXER_TYPE33,
+ },
+ },
+ },
+ }
+ }
+};
+#endif
+/** @} */
diff --git a/mpm/lib/rfdc/xrfdc_intr.c b/mpm/lib/rfdc/xrfdc_intr.c
new file mode 100644
index 000000000..7b8bd0927
--- /dev/null
+++ b/mpm/lib/rfdc/xrfdc_intr.c
@@ -0,0 +1,771 @@
+/******************************************************************************
+*
+* Copyright (C) 2017-2019 Xilinx, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* Except as contained in this notice, the name of the Xilinx shall not be used
+* in advertising or otherwise to promote the sale, use or other dealings in
+* this Software without prior written authorization from Xilinx.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xrfdc_intr.c
+* @addtogroup rfdc_v6_0
+* @{
+*
+* This file contains functions related to RFdc interrupt handling.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ----- -------- -----------------------------------------------
+* 1.0 sk 05/16/17 First release
+* 2.1 sk 09/15/17 Remove Libmetal library dependency for MB.
+* 09/18/17 Add API to clear the interrupts.
+* sk 09/21/17 Add support for Over voltage and Over
+* Range interrupts.
+* 2.2 sk 10/18/17 Add support for FIFO and DATA overflow interrupt
+* 5.0 sk 08/24/18 Reorganize the code to improve readability and
+* optimization.
+* 5.1 cog 01/29/19 Replace structure reference ADC checks with
+* function.
+* 6.0 cog 02/20/19 Added handling for new ADC common mode over/under
+* voltage interrupts.
+* cog 02/20/19 XRFdc_GetIntrStatus now populates a pointer with the
+* status and returns an error code.
+* cog 02/20/19 XRFdc_IntrClr, XRFdc_IntrDisable and XRFdc_IntrEnable
+* now return error codes.
+* cog 03/25/19 The new common mode over/under voltage interrupts mask
+* bits were clashing with other interrupt bits.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "mpm/rfdc/xrfdc.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Variable Definitions *****************************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions ****************************/
+
+/****************************************************************************/
+/**
+*
+* This function sets the interrupt mask.
+*
+* @param InstancePtr is a pointer to the XRFdc instance
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3, and -1.
+* @param Block_Id is ADC/DAC block number inside the tile. Valid values
+* are 0-3.
+* @param IntrMask contains the interrupts to be enabled.
+* '1' enables an interrupt, and '0' disables.
+*
+* @return - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not available.
+*
+* @note None.
+*
+*****************************************************************************/
+u32 XRFdc_IntrEnable(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, u32 IntrMask)
+{
+ u32 BaseAddr;
+ u32 ReadReg;
+ u32 Index;
+ u32 NoOfBlocks;
+ u32 Status;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Status = XRFdc_CheckBlockEnabled(InstancePtr, Type, Tile_Id, Block_Id);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR, "\n Requested block not "
+ "available in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ Index = Block_Id;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ NoOfBlocks = XRFDC_NUM_OF_BLKS2;
+ if (Block_Id == XRFDC_BLK_ID1) {
+ Index = XRFDC_BLK_ID2;
+ NoOfBlocks = XRFDC_NUM_OF_BLKS4;
+ }
+ } else {
+ NoOfBlocks = Block_Id + 1U;
+ }
+
+ for (; Index < NoOfBlocks; Index++) {
+ ReadReg = XRFdc_ReadReg16(InstancePtr, 0x0,
+ XRFDC_COMMON_INTR_ENABLE);
+ if (Type == XRFDC_ADC_TILE) {
+ ReadReg |= (1U << (Tile_Id + 4));
+ XRFdc_WriteReg16(InstancePtr, 0x0,
+ XRFDC_COMMON_INTR_ENABLE, ReadReg);
+ BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_INTR_ENABLE,
+ (1U << Index), (1U << Index));
+ /* Enable Converter interrupts */
+ ReadReg = XRFdc_ReadReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_EN(Index));
+ if ((IntrMask & XRFDC_ADC_OVR_VOLTAGE_MASK) != 0U) {
+ ReadReg |= (XRFDC_ADC_OVR_VOLTAGE_MASK >>
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_OVR_RANGE_MASK) != 0U) {
+ ReadReg |= (XRFDC_ADC_OVR_RANGE_MASK >>
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_FIFO_OVR_MASK) != 0U) {
+ ReadReg |=
+ (XRFDC_ADC_FIFO_OVR_MASK >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_DAT_OVR_MASK) != 0U) {
+ ReadReg |=
+ (XRFDC_ADC_DAT_OVR_MASK >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_OVR_MASK) != 0U) {
+ ReadReg |=
+ (XRFDC_ADC_CMODE_OVR_MASK >> XRFDC_ADC_CMODE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_UNDR_MASK) != 0U) {
+ ReadReg |=
+ (XRFDC_ADC_CMODE_UNDR_MASK >> XRFDC_ADC_CMODE_SHIFT);
+ }
+
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_EN(Index), ReadReg);
+
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Index);
+
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_FABRIC_IMR_OFFSET,
+ XRFDC_IXR_FIFOUSRDAT_MASK, ReadReg);
+ }
+ /* Check for SUBADC interrupts */
+ if ((IntrMask & XRFDC_SUBADC_IXR_DCDR_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_SUBADC_IXR_DCDR_MASK) >>
+ XRFDC_ADC_SUBADC_DCDR_SHIFT;
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_DEC_IMR_OFFSET,
+ XRFDC_DEC_IMR_MASK, ReadReg);
+ }
+ /* Check for DataPath interrupts */
+ if ((IntrMask & XRFDC_ADC_IXR_DATAPATH_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_ADC_IXR_DATAPATH_MASK) >>
+ XRFDC_DATA_PATH_SHIFT;
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DATPATH_IMR_OFFSET,
+ XRFDC_ADC_DAT_IMR_MASK, ReadReg);
+ }
+ } else {
+ ReadReg |= (1U << Tile_Id);
+ XRFdc_WriteReg16(InstancePtr, 0x0,
+ XRFDC_COMMON_INTR_ENABLE, ReadReg);
+ BaseAddr = XRFDC_DAC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr,
+ XRFDC_INTR_ENABLE, (1U << Index), (1U << Index));
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Index);
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DAC_FABRIC_IMR_OFFSET,
+ XRFDC_IXR_FIFOUSRDAT_MASK, ReadReg);
+ }
+
+ if ((IntrMask & XRFDC_DAC_IXR_DATAPATH_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_DAC_IXR_DATAPATH_MASK) >>
+ XRFDC_DATA_PATH_SHIFT;
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_DATPATH_IMR_OFFSET,
+ XRFDC_DAC_DAT_IMR_MASK, ReadReg);
+ }
+ }
+ }
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+
+/****************************************************************************/
+/**
+*
+* This function clears the interrupt mask.
+*
+* @param InstancePtr is a pointer to the XRFdc instance
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3, and -1.
+* @param Block_Id is ADC/DAC block number inside the tile. Valid values
+* are 0-3.
+* @param IntrMask contains the interrupts to be disabled.
+* '1' disables an interrupt, and '0' remains no change.
+*
+* @return - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not available.
+*
+* @note None.
+*
+*****************************************************************************/
+u32 XRFdc_IntrDisable(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, u32 IntrMask)
+{
+ u32 BaseAddr;
+ u32 ReadReg;
+ u32 Status;
+ u32 Index;
+ u32 NoOfBlocks;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Status = XRFdc_CheckBlockEnabled(InstancePtr, Type, Tile_Id, Block_Id);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR, "\n Requested block not "
+ "available in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ Index = Block_Id;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ NoOfBlocks = XRFDC_NUM_OF_BLKS2;
+ if (Block_Id == XRFDC_BLK_ID1) {
+ Index = XRFDC_BLK_ID2;
+ NoOfBlocks = XRFDC_NUM_OF_BLKS4;
+ }
+ } else {
+ NoOfBlocks = Block_Id + 1U;
+ }
+
+ for (; Index < NoOfBlocks; Index++) {
+ if (Type == XRFDC_ADC_TILE) {
+ BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ /* Check for Over Voltage and Over Range */
+ ReadReg = XRFdc_ReadReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_EN(Index));
+ if ((IntrMask & XRFDC_ADC_OVR_VOLTAGE_MASK) != 0U) {
+ ReadReg &= ~(XRFDC_ADC_OVR_VOLTAGE_MASK >>
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_OVR_RANGE_MASK) != 0U) {
+ ReadReg &= ~(XRFDC_ADC_OVR_RANGE_MASK >>
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ /* Disable Converter interrupts */
+ if ((IntrMask & XRFDC_ADC_FIFO_OVR_MASK) != 0U) {
+ ReadReg &=
+ ~(XRFDC_ADC_FIFO_OVR_MASK >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_DAT_OVR_MASK) != 0U) {
+ ReadReg &=
+ ~(XRFDC_ADC_DAT_OVR_MASK >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_OVR_MASK) != 0U) {
+ ReadReg &=
+ ~(XRFDC_ADC_CMODE_OVR_MASK >> XRFDC_ADC_CMODE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_UNDR_MASK) != 0U) {
+ ReadReg &=
+ ~(XRFDC_ADC_CMODE_UNDR_MASK >> XRFDC_ADC_CMODE_SHIFT);
+ }
+
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_EN(Index), ReadReg);
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Index);
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ ReadReg = IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK;
+ XRFdc_ClrReg(InstancePtr, BaseAddr, XRFDC_ADC_FABRIC_IMR_OFFSET,
+ ReadReg);
+ }
+ /* Check for SUBADC interrupts */
+ if ((IntrMask & XRFDC_SUBADC_IXR_DCDR_MASK) != 0U) {
+ ReadReg = ((IntrMask & XRFDC_SUBADC_IXR_DCDR_MASK) >>
+ XRFDC_ADC_SUBADC_DCDR_SHIFT);
+ XRFdc_ClrReg(InstancePtr, BaseAddr, XRFDC_ADC_DEC_IMR_OFFSET,
+ ReadReg);
+ }
+ /* Check for DataPath interrupts */
+ if ((IntrMask & XRFDC_ADC_IXR_DATAPATH_MASK) != 0U) {
+ ReadReg = ((IntrMask &
+ XRFDC_ADC_IXR_DATAPATH_MASK) >> XRFDC_DATA_PATH_SHIFT);
+ XRFdc_ClrReg(InstancePtr, BaseAddr, XRFDC_DATPATH_IMR_OFFSET,
+ ReadReg);
+ }
+ } else {
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Index);
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ ReadReg = (IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK);
+ XRFdc_ClrReg(InstancePtr, BaseAddr, XRFDC_DAC_FABRIC_IMR_OFFSET,
+ ReadReg);
+ }
+ /* Check for FIFO DataPath interrupts */
+ if ((IntrMask & XRFDC_DAC_IXR_DATAPATH_MASK) != 0U) {
+ ReadReg = ((IntrMask &
+ XRFDC_DAC_IXR_DATAPATH_MASK) >> XRFDC_DATA_PATH_SHIFT);
+ XRFdc_ClrReg(InstancePtr, BaseAddr, XRFDC_DATPATH_IMR_OFFSET,
+ ReadReg);
+ }
+ }
+ }
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+
+/****************************************************************************/
+/**
+*
+* This function returns the interrupt status read from Interrupt Status
+* Register(ISR).
+*
+* @param InstancePtr is a pointer to the XRFdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3, and -1.
+* @param Block_Id is ADC/DAC block number inside the tile. Valid values
+* are 0-3.
+* @param IntrStsPtr is pointer to a32-bit value representing the contents of
+* the Interrupt Status Registers (FIFO interface, Decoder interface,
+* Data Path Interface).
+*
+* @return - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not available.
+*
+* @note None.
+*
+*****************************************************************************/
+u32 XRFdc_GetIntrStatus(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, u32 *IntrStsPtr)
+{
+ u32 BaseAddr;
+ u32 ReadReg;
+ u32 Status;
+ u32 Block;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(IntrStsPtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Block = Block_Id;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ if ((Block_Id == XRFDC_BLK_ID2) || (Block_Id == XRFDC_BLK_ID3)) {
+ Block = XRFDC_BLK_ID1;
+ }
+ if (Block_Id == XRFDC_BLK_ID1) {
+ Block = XRFDC_BLK_ID0;
+ }
+ }
+ Status = XRFdc_CheckBlockEnabled(InstancePtr, Type, Tile_Id, Block);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR, "\n Requested block not "
+ "available in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ *IntrStsPtr = 0;
+
+ if (Type == XRFDC_ADC_TILE) {
+ BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ /* Check for Over Voltage and Over Range */
+ ReadReg = XRFdc_ReadReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id));
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_OVR_VOLTAGE_MASK) <<
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_OVR_RANGE_MASK) <<
+ XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_FIFO_OVR_MASK) <<
+ XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_DAT_OVR_MASK) <<
+ XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+
+ /* Check for Common Mode Over/Under Voltage */
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_CMODE_OVR_MASK) <<
+ XRFDC_ADC_CMODE_SHIFT);
+ *IntrStsPtr |= ((ReadReg & XRFDC_INTR_CMODE_UNDR_MASK) <<
+ XRFDC_ADC_CMODE_SHIFT);
+
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Block_Id);
+ /* Check for FIFO interface interrupts */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_FABRIC_ISR_OFFSET);
+ *IntrStsPtr |= (ReadReg & XRFDC_IXR_FIFOUSRDAT_MASK);
+ /* Check for SUBADC interrupts */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_DEC_ISR_OFFSET);
+ *IntrStsPtr |= ((ReadReg & XRFDC_DEC_ISR_SUBADC_MASK) <<
+ XRFDC_ADC_SUBADC_DCDR_SHIFT);
+ /* Check for DataPath interrupts */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_DATPATH_ISR_OFFSET);
+ *IntrStsPtr |= ((ReadReg & XRFDC_ADC_DAT_PATH_ISR_MASK) <<
+ XRFDC_DATA_PATH_SHIFT);
+ } else {
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Block_Id);
+ /* Check for FIFO interface interrupts */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_DAC_FABRIC_ISR_OFFSET);
+ *IntrStsPtr |= (ReadReg & XRFDC_IXR_FIFOUSRDAT_MASK);
+ /* Check for DataPath interrupts */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_DATPATH_ISR_OFFSET);
+ *IntrStsPtr |= ((ReadReg & XRFDC_DAC_DAT_PATH_ISR_MASK) <<
+ XRFDC_DATA_PATH_SHIFT);
+ }
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+
+/****************************************************************************/
+/**
+*
+* This function clear the interrupts.
+*
+* @param InstancePtr is a pointer to the XRFdc instance
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3, and -1.
+* @param Block_Id is ADC/DAC block number inside the tile. Valid values
+* are 0-3.
+* @param IntrMask contains the interrupts to be cleared.
+*
+* @return - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not available.
+*
+* @note None.
+*
+*****************************************************************************/
+u32 XRFdc_IntrClr(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, u32 IntrMask)
+{
+ u32 BaseAddr;
+ u32 Status;
+ u32 Block;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Block = Block_Id;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ if ((Block_Id == XRFDC_BLK_ID2) || (Block_Id == XRFDC_BLK_ID3)) {
+ Block = XRFDC_BLK_ID1;
+ }
+ if (Block_Id == XRFDC_BLK_ID1) {
+ Block = XRFDC_BLK_ID0;
+ }
+ }
+ Status = XRFdc_CheckBlockEnabled(InstancePtr, Type, Tile_Id, Block);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR, "\n Requested block not "
+ "available in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ if (Type == XRFDC_ADC_TILE) {
+ /* ADC */
+ BaseAddr = XRFDC_ADC_TILE_CTRL_STATS_ADDR(Tile_Id);
+ /* Check for Converter interrupts */
+ if ((IntrMask & XRFDC_ADC_OVR_VOLTAGE_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_OVR_VOLTAGE_MASK) >> XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_OVR_RANGE_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_OVR_RANGE_MASK) >> XRFDC_ADC_OVR_VOL_RANGE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_FIFO_OVR_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_FIFO_OVR_MASK) >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_DAT_OVR_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_DAT_OVR_MASK) >> XRFDC_ADC_DAT_FIFO_OVR_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_OVR_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_CMODE_OVR_MASK) >> XRFDC_ADC_CMODE_SHIFT);
+ }
+ if ((IntrMask & XRFDC_ADC_CMODE_UNDR_MASK) != 0U) {
+ XRFdc_WriteReg(InstancePtr, BaseAddr,
+ XRFDC_CONV_INTR_STS(Block_Id), (IntrMask &
+ XRFDC_ADC_CMODE_UNDR_MASK) >> XRFDC_ADC_CMODE_SHIFT);
+ }
+ BaseAddr = XRFDC_ADC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Block_Id);
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_FABRIC_ISR_OFFSET,
+ (IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK));
+ }
+ /* Check for SUBADC interrupts */
+ if ((IntrMask & XRFDC_SUBADC_IXR_DCDR_MASK) != 0U) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_DEC_ISR_OFFSET, (u16)((IntrMask &
+ XRFDC_SUBADC_IXR_DCDR_MASK) >> XRFDC_ADC_SUBADC_DCDR_SHIFT));
+ }
+ /* Check for DataPath interrupts */
+ if ((IntrMask & XRFDC_ADC_IXR_DATAPATH_MASK) != 0U) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_DATPATH_ISR_OFFSET, (u16)(IntrMask &
+ XRFDC_ADC_IXR_DATAPATH_MASK) >> XRFDC_DATA_PATH_SHIFT);
+ }
+ } else {
+ /* DAC */
+ BaseAddr = XRFDC_DAC_TILE_DRP_ADDR(Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Block_Id);
+ /* Check for FIFO interface interrupts */
+ if ((IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_DAC_FABRIC_ISR_OFFSET,
+ (u16)(IntrMask & XRFDC_IXR_FIFOUSRDAT_MASK));
+ }
+ /* Check for DataPath interrupts */
+ if ((IntrMask & XRFDC_DAC_IXR_DATAPATH_MASK) != 0U) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_DATPATH_ISR_OFFSET, (u16)(IntrMask &
+ XRFDC_DAC_IXR_DATAPATH_MASK) >> XRFDC_DATA_PATH_SHIFT);
+ }
+ }
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+
+/****************************************************************************/
+/**
+*
+* This function is the interrupt handler for the driver.
+* It must be connected to an interrupt system by the application such that it
+* can be called when an interrupt occurs.
+*
+* @param Vector is interrupt vector number. Libmetal status handler
+* expects two parameters in the handler prototype, hence
+* kept this parameter. This is not used inside
+* the interrupt handler API.
+* @param XRFdcPtr contains a pointer to the driver instance
+*
+* @return None.
+*
+* @note Vector param is not useful inside the interrupt handler, hence
+* typecast with void to remove compilation warning.
+*
+******************************************************************************/
+u32 XRFdc_IntrHandler(u32 Vector, void *XRFdcPtr)
+{
+ XRFdc *InstancePtr = (XRFdc *)XRFdcPtr;
+ u32 Intrsts = 0x0U;
+ u32 Tile_Id = XRFDC_TILE_ID4;
+ u32 Block_Id = XRFDC_BLK_ID4;
+ u32 ReadReg;
+ u16 Type = 0U;
+ u32 BaseAddr;
+ u32 IntrMask = 0x0U;
+ u32 Block;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+
+ (void)Vector;
+ /*
+ * Read the interrupt ID register to determine which
+ * interrupt is active
+ */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, 0x0,
+ XRFDC_COMMON_INTR_STS);
+ if ((ReadReg & XRFDC_EN_INTR_DAC_TILE0_MASK) != 0U) {
+ Type = XRFDC_DAC_TILE;
+ Tile_Id = XRFDC_TILE_ID0;
+ } else if ((ReadReg & XRFDC_EN_INTR_DAC_TILE1_MASK) != 0U) {
+ Type = XRFDC_DAC_TILE;
+ Tile_Id = XRFDC_TILE_ID1;
+ } else if ((ReadReg & XRFDC_EN_INTR_DAC_TILE2_MASK) != 0U) {
+ Type = XRFDC_DAC_TILE;
+ Tile_Id = XRFDC_TILE_ID2;
+ } else if ((ReadReg & XRFDC_EN_INTR_DAC_TILE3_MASK) != 0U) {
+ Type = XRFDC_DAC_TILE;
+ Tile_Id = XRFDC_TILE_ID3;
+ } else if ((ReadReg & XRFDC_EN_INTR_ADC_TILE0_MASK) != 0U) {
+ Type = XRFDC_ADC_TILE;
+ Tile_Id = XRFDC_TILE_ID0;
+ } else if ((ReadReg & XRFDC_EN_INTR_ADC_TILE1_MASK) != 0U) {
+ Type = XRFDC_ADC_TILE;
+ Tile_Id = XRFDC_TILE_ID1;
+ } else if ((ReadReg & XRFDC_EN_INTR_ADC_TILE2_MASK) != 0U) {
+ Type = XRFDC_ADC_TILE;
+ Tile_Id = XRFDC_TILE_ID2;
+ } else if ((ReadReg & XRFDC_EN_INTR_ADC_TILE3_MASK) != 0U) {
+ Type = XRFDC_ADC_TILE;
+ Tile_Id = XRFDC_TILE_ID3;
+ } else {
+ metal_log(METAL_LOG_DEBUG, "\n Invalid Tile_Id \r\n");
+ }
+
+ BaseAddr = XRFDC_CTRL_STS_BASE(Type, Tile_Id);
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr, XRFDC_INTR_STS);
+ if ((ReadReg & XRFDC_EN_INTR_SLICE0_MASK) != 0U) {
+ Block_Id = XRFDC_BLK_ID0;
+ } else if ((ReadReg & XRFDC_EN_INTR_SLICE1_MASK) != 0U) {
+ Block_Id = XRFDC_BLK_ID1;
+ } else if ((ReadReg & XRFDC_EN_INTR_SLICE2_MASK) != 0U) {
+ Block_Id = XRFDC_BLK_ID2;
+ } else if ((ReadReg & XRFDC_EN_INTR_SLICE3_MASK) != 0U) {
+ Block_Id = XRFDC_BLK_ID3;
+ } else {
+ metal_log(METAL_LOG_DEBUG, "\n Invalid ADC Block_Id \r\n");
+ }
+ (void)XRFdc_GetIntrStatus(InstancePtr, Type, Tile_Id, Block_Id, &Intrsts);
+ if (Type == XRFDC_ADC_TILE) {
+ /* ADC */
+ if ((Intrsts & XRFDC_ADC_OVR_VOLTAGE_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_ADC_OVR_VOLTAGE_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC Over Voltage interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_OVR_RANGE_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_ADC_OVR_RANGE_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC Over Range interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_FIFO_OVR_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_ADC_FIFO_OVR_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC FIFO OF interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_DAT_OVR_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_ADC_DAT_OVR_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC DATA OF interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_CMODE_OVR_MASK) != 0U) {
+ IntrMask |= XRFDC_ADC_CMODE_OVR_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC CMODE OV interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_CMODE_UNDR_MASK) != 0U) {
+ IntrMask |= XRFDC_ADC_CMODE_UNDR_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC CMODE UV interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_IXR_FIFOUSRDAT_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n ADC FIFO interface interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_SUBADC_IXR_DCDR_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_SUBADC_IXR_DCDR_MASK;
+ metal_log(METAL_LOG_DEBUG,
+ "\n ADC Decoder interface interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_ADC_IXR_DATAPATH_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_ADC_IXR_DATAPATH_MASK;
+ metal_log(METAL_LOG_DEBUG,
+ "\n ADC Data Path interface interrupt \r\n");
+ }
+ } else {
+ /* DAC */
+ if ((Intrsts & XRFDC_IXR_FIFOUSRDAT_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_IXR_FIFOUSRDAT_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n DAC FIFO interface interrupt \r\n");
+ }
+ if ((Intrsts & XRFDC_DAC_IXR_DATAPATH_MASK) != 0U) {
+ IntrMask |= Intrsts & XRFDC_DAC_IXR_DATAPATH_MASK;
+ metal_log(METAL_LOG_DEBUG, "\n DAC Data Path interface interrupt \r\n");
+ }
+ }
+ Block = Block_Id;
+
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ if ((Block_Id == XRFDC_BLK_ID0) || (Block_Id == XRFDC_BLK_ID1)) {
+ Block = XRFDC_BLK_ID0;
+ } else {
+ Block = XRFDC_BLK_ID1;
+ }
+ }
+ InstancePtr->StatusHandler(InstancePtr->CallBackRef, Type, Tile_Id,
+ Block, IntrMask);
+
+ /* Clear the interrupt */
+ if (Type == XRFDC_ADC_TILE) {
+ /* ADC */
+ XRFdc_IntrClr(InstancePtr, XRFDC_ADC_TILE, Tile_Id, Block_Id, Intrsts);
+
+ } else {
+ /* DAC */
+ XRFdc_IntrClr(InstancePtr, XRFDC_DAC_TILE, Tile_Id, Block_Id, Intrsts);
+ }
+
+ return (u32)METAL_IRQ_HANDLED;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets the status callback function, the status handler, which the
+* driver calls when it encounters conditions that should be reported to the
+* higher layer software. The handler executes in an interrupt context, so
+* the amount of processing should be minimized
+*
+*
+* @param InstancePtr is a pointer to the XRFdc instance.
+* @param CallBackRef is the upper layer callback reference passed back
+* when the callback function is invoked.
+* @param FunctionPtr is the pointer to the callback function.
+*
+* @return None.
+*
+* @note
+*
+* The handler is called within interrupt context, so it should finish its
+* work quickly.
+*
+******************************************************************************/
+void XRFdc_SetStatusHandler(XRFdc *InstancePtr, void *CallBackRef,
+ XRFdc_StatusHandler FunctionPtr)
+{
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(FunctionPtr != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == (u32)XRFDC_COMPONENT_IS_READY);
+
+ InstancePtr->StatusHandler = FunctionPtr;
+ InstancePtr->CallBackRef = CallBackRef;
+}
+
+/** @} */
diff --git a/mpm/lib/rfdc/xrfdc_mb.c b/mpm/lib/rfdc/xrfdc_mb.c
new file mode 100644
index 000000000..c7b563d40
--- /dev/null
+++ b/mpm/lib/rfdc/xrfdc_mb.c
@@ -0,0 +1,786 @@
+/******************************************************************************
+*
+* Copyright (C) 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_mb.c
+* @addtogroup xrfdc_v6_0
+* @{
+*
+* Contains the interface functions of the Mixer Settings in XRFdc driver.
+* See xrfdc.h for a detailed description of the device and driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- --- -------- -----------------------------------------------
+* 6.0 cog 02/17/18 Initial release/handle alternate bound out.
+*
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+#include "mpm/rfdc/xrfdc.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+static void XRFdc_SetSignalFlow(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Mode, u32 DigitalDataPathId, u32 MixerInOutDataType,
+ int ConnectIData, int ConnectQData);
+static void XRFdc_MB_R2C_C2R(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u8 NoOfDataPaths, u32 MixerInOutDataType, u32 Mode,
+ u32 DataPathIndex[], u32 BlockIndex[]);
+static void XRFdc_MB_C2C(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u8 NoOfDataPaths, u32 MixerInOutDataType, u32 Mode,
+ u32 DataPathIndex[], u32 BlockIndex[]);
+static void XRFdc_SB_R2C_C2R(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 MixerInOutDataType, u32 Mode, u32 DataPathIndex[], u32 BlockIndex[]);
+static void XRFdc_SB_C2C(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 MixerInOutDataType, u32 Mode, u32 DataPathIndex[], u32 BlockIndex[]);
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+/**
+*
+* Static API to setup Singleband configuration for C2C MixerInOutDataType
+*
+* @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 MixerInOutDataType is mixer data type, valid values are XRFDC_MB_DATATYPE_*
+* @param Mode is connection mode SB/MB_2X/MB_4X.
+* @param DataPathIndex is the array that represents the blocks enabled in
+* DigitalData Path.
+* @param BlockIndex is the array that represents the blocks enabled in
+* Analog Path(Data Converters).
+*
+* @return
+* - None
+*
+* @note Static API for ADC/DAC blocks
+*
+******************************************************************************/
+static void XRFdc_SB_C2C(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 MixerInOutDataType, u32 Mode, u32 DataPathIndex[], u32 BlockIndex[])
+{
+ u32 Block_Id;
+
+ if ((Type == XRFDC_ADC_TILE) && (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1)) {
+ /* Update ConnectedIData and ConnectedQData for ADC 4GSPS */
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = BlockIndex[1U];
+ Block_Id = (DataPathIndex[0] == 0U ? 1U : 0U);
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[Block_Id].
+ ConnectedIData = -1;
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[Block_Id].
+ ConnectedQData = -1;
+
+ if (DataPathIndex[0] == XRFDC_BLK_ID1) {
+ DataPathIndex[0] = XRFDC_BLK_ID2;
+ }
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0],
+ MixerInOutDataType, BlockIndex[0U], BlockIndex[0U]+1U);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0]+1U,
+ MixerInOutDataType, BlockIndex[1U]+1U, BlockIndex[1U]+2U);
+ Block_Id = (DataPathIndex[0] == XRFDC_BLK_ID2 ? XRFDC_BLK_ID0 :
+ XRFDC_BLK_ID2);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, Block_Id,
+ MixerInOutDataType, -1, -1);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, Block_Id+1U,
+ MixerInOutDataType, -1, -1);
+ } else {
+ DataPathIndex[1] = BlockIndex[0] + BlockIndex[1] - DataPathIndex[0];
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0],
+ MixerInOutDataType, BlockIndex[0], BlockIndex[1]);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[1],
+ MixerInOutDataType, -1, -1);
+
+ /* Update ConnectedIData and ConnectedQData for DAC and ADC 2GSPS */
+ if (Type == XRFDC_ADC_TILE) {
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = BlockIndex[1];
+
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = -1;
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = -1;
+ } else {
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = BlockIndex[1];
+
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = -1;
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = -1;
+ }
+ }
+}
+
+/*****************************************************************************/
+/**
+*
+* Static API to setup Singleband configuration for C2R and R2C MultiBandDataTypes
+*
+* @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 MixerInOutDataType is mixer data type, valid values are XRFDC_MB_DATATYPE_*
+* @param Mode is connection mode SB/MB_2X/MB_4X.
+* @param DataPathIndex is the array that represents the blocks enabled in
+* DigitalData Path.
+* @param BlockIndex is the array that represents the blocks enabled in
+* Analog Path(Data Converters).
+*
+* @return
+* - None
+*
+* @note Static API for ADC/DAC blocks
+*
+******************************************************************************/
+static void XRFdc_SB_R2C_C2R(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 MixerInOutDataType, u32 Mode, u32 DataPathIndex[], u32 BlockIndex[])
+{
+ if (Type == XRFDC_ADC_TILE) {
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = -1;
+ } else {
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = -1;
+ }
+ if ((Type == XRFDC_ADC_TILE) && (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1)) {
+ if (DataPathIndex[0] == XRFDC_BLK_ID1) {
+ DataPathIndex[0] = XRFDC_BLK_ID2;
+ }
+ if (BlockIndex[0] == XRFDC_BLK_ID1) {
+ BlockIndex[0] = XRFDC_BLK_ID2;
+ }
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0]+1U,
+ MixerInOutDataType, BlockIndex[0U]+1U, -1);
+ }
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0],
+ MixerInOutDataType, BlockIndex[0U], -1);
+}
+
+/*****************************************************************************/
+/**
+*
+* Static API to setup Multiband configuration for C2C MixerInOutDataType
+*
+* @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 MixerInOutDataType is mixer data type, valid values are XRFDC_MB_DATATYPE_*
+* @param Mode is connection mode SB/MB_2X/MB_4X.
+* @param DataPathIndex is the array that represents the blocks enabled in
+* DigitalData Path.
+* @param BlockIndex is the array that represents the blocks enabled in
+* Analog Path(Data Converters).
+*
+* @return
+* - None
+*
+* @note Static API for ADC/DAC blocks
+*
+******************************************************************************/
+static void XRFdc_MB_C2C(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u8 NoOfDataPaths, u32 MixerInOutDataType, u32 Mode,
+ u32 DataPathIndex[], u32 BlockIndex[])
+{
+ if ((Type == XRFDC_ADC_TILE) && (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1)) {
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0],
+ MixerInOutDataType, BlockIndex[0U], BlockIndex[0U]+1U);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0]+1U,
+ MixerInOutDataType, BlockIndex[0U]+2U, BlockIndex[0U]+3U);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0]+2U,
+ MixerInOutDataType, BlockIndex[0U], BlockIndex[0U]+1U);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0]+3U,
+ MixerInOutDataType, BlockIndex[0U]+2U, BlockIndex[0U]+3U);
+
+ /* Update ConnectedIData and ConnectedQData for ADC 4GSPS */
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = BlockIndex[1U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = BlockIndex[1U];
+ } else if (NoOfDataPaths == 2U) {
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0],
+ MixerInOutDataType, BlockIndex[0U], BlockIndex[1U]);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[1],
+ MixerInOutDataType, BlockIndex[0U], BlockIndex[1U]);
+
+ /* Update ConnectedIData and ConnectedQData for DAC and ADC 2GSPS */
+ if (Type == XRFDC_ADC_TILE) {
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = BlockIndex[1U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = BlockIndex[1U];
+ } else {
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = BlockIndex[1U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = BlockIndex[1U];
+ }
+ }
+ if (NoOfDataPaths == 4U) {
+ if (Type == XRFDC_ADC_TILE) {
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0],
+ MixerInOutDataType, BlockIndex[0U], BlockIndex[1U]);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[1],
+ MixerInOutDataType, BlockIndex[0U], BlockIndex[1U]);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[2],
+ MixerInOutDataType, BlockIndex[0U], BlockIndex[1U]);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[3],
+ MixerInOutDataType, BlockIndex[0U], BlockIndex[1U]);
+
+ /* Update ConnectedIData and ConnectedQData for ADC 4GSPS */
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = BlockIndex[1U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = BlockIndex[1U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[2]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[2]].
+ ConnectedQData = BlockIndex[1U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[3]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[3]].
+ ConnectedQData = BlockIndex[1U];
+ } else {
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0],
+ MixerInOutDataType, DataPathIndex[0], DataPathIndex[1U]);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[1],
+ MixerInOutDataType, DataPathIndex[0U], DataPathIndex[1U]);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[2],
+ MixerInOutDataType, DataPathIndex[2U], DataPathIndex[3U]);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[3],
+ MixerInOutDataType, DataPathIndex[2U], DataPathIndex[3U]);
+
+ /* Update ConnectedIData and ConnectedQData for DAC and ADC 2GSPS */
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = BlockIndex[1U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = BlockIndex[1U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[2]].
+ ConnectedIData = DataPathIndex[0U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[2]].
+ ConnectedQData = DataPathIndex[1U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[3]].
+ ConnectedIData = DataPathIndex[0U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[3]].
+ ConnectedQData = DataPathIndex[1U];
+ }
+ }
+}
+
+/*****************************************************************************/
+/**
+*
+* Static API to setup Multiband configuration for C2C MixerInOutDataType
+*
+* @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 MixerInOutDataType is mixer data type, valid values are XRFDC_MB_DATATYPE_*
+* @param Mode is connection mode SB/MB_2X/MB_4X.
+* @param DataPathIndex is the array that represents the blocks enabled in
+* DigitalData Path.
+* @param BlockIndex is the array that represents the blocks enabled in
+* Analog Path(Data Converters).
+*
+* @return
+* - None
+*
+* @note Static API for ADC/DAC blocks
+*
+******************************************************************************/
+static void XRFdc_MB_R2C_C2R(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u8 NoOfDataPaths, u32 MixerInOutDataType, u32 Mode,
+ u32 DataPathIndex[], u32 BlockIndex[])
+{
+ if ((Type == XRFDC_ADC_TILE) && (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1)) {
+ /* Update ConnectedIData and ConnectedQData */
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = -1;
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = -1;
+ if (BlockIndex[0] == XRFDC_BLK_ID1) {
+ BlockIndex[0] = XRFDC_BLK_ID2;
+ }
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0],
+ MixerInOutDataType, BlockIndex[0U], -1);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[1],
+ MixerInOutDataType, BlockIndex[0U]+1U, -1);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0]+2U,
+ MixerInOutDataType, BlockIndex[0U], -1);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[1]+2U,
+ MixerInOutDataType, BlockIndex[0U]+1U, -1);
+ } else if (NoOfDataPaths == 2U) {
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0],
+ MixerInOutDataType, BlockIndex[0], -1);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[1],
+ MixerInOutDataType, BlockIndex[0], -1);
+
+ /* Update ConnectedIData and ConnectedQData */
+ if (Type == XRFDC_ADC_TILE) {
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = -1;
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = -1;
+ } else {
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = -1;
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = -1;
+ }
+
+ }
+ if (NoOfDataPaths == 4U) {
+ if (Type == XRFDC_ADC_TILE) {
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0],
+ MixerInOutDataType, BlockIndex[0], -1);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[1],
+ MixerInOutDataType, BlockIndex[0], -1);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[2],
+ MixerInOutDataType, BlockIndex[0], -1);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[3],
+ MixerInOutDataType, BlockIndex[0], -1);
+
+ /* Update ConnectedIData and ConnectedQData */
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = -1;
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = -1;
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[2]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[2]].
+ ConnectedQData = -1;
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[3]].
+ ConnectedIData = BlockIndex[0U];
+ InstancePtr->ADC_Tile[Tile_Id].ADCBlock_Digital_Datapath[DataPathIndex[3]].
+ ConnectedQData = -1;
+
+ } else {
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[0],
+ MixerInOutDataType, DataPathIndex[0], -1);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[1],
+ MixerInOutDataType, DataPathIndex[0], -1);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[2],
+ MixerInOutDataType, DataPathIndex[2], -1);
+ XRFdc_SetSignalFlow(InstancePtr, Type, Tile_Id, Mode, DataPathIndex[3],
+ MixerInOutDataType, DataPathIndex[2], -1);
+
+ /* Update ConnectedIData and ConnectedQData */
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedIData = DataPathIndex[0];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[0]].
+ ConnectedQData = -1;
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedIData = DataPathIndex[0];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[1]].
+ ConnectedQData = -1;
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[2]].
+ ConnectedIData = DataPathIndex[0];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[2]].
+ ConnectedQData = -1;
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[3]].
+ ConnectedIData = DataPathIndex[0];
+ InstancePtr->DAC_Tile[Tile_Id].DACBlock_Digital_Datapath[DataPathIndex[3]].
+ ConnectedQData = -1;
+ }
+ }
+}
+
+/*****************************************************************************/
+/**
+*
+* Static API to update mode and MultibandConfig
+*
+* @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 NoOfDataPaths is number of DataPaths enabled.
+* @param ModePtr is a pointer to connection mode SB/MB_2X/MB_4X.
+* @param DataPathIndex is the array that represents the blocks enabled in
+* DigitalData Path.
+*
+* @return
+* - None
+*
+* @note Static API for ADC/DAC blocks
+*
+******************************************************************************/
+static u32 XRFdc_UpdateMBConfig(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u8 NoOfDataPaths, u32 *ModePtr, u32 DataPathIndex[])
+{
+ u8 MultibandConfig;
+ u32 Status;
+
+ if (Type == XRFDC_ADC_TILE) {
+ MultibandConfig = InstancePtr->ADC_Tile[Tile_Id].MultibandConfig;
+ } else {
+ MultibandConfig = InstancePtr->DAC_Tile[Tile_Id].MultibandConfig;
+ }
+
+ if (NoOfDataPaths == 1U) {
+ *ModePtr = XRFDC_SINGLEBAND_MODE;
+ if (((DataPathIndex[0] == XRFDC_BLK_ID2) ||
+ (DataPathIndex[0] == XRFDC_BLK_ID3)) &&
+ ((MultibandConfig == XRFDC_MB_MODE_2X_BLK01_BLK23) ||
+ (MultibandConfig == XRFDC_MB_MODE_4X))) {
+ MultibandConfig = XRFDC_MB_MODE_2X_BLK01;
+ } else if (((DataPathIndex[0] == XRFDC_BLK_ID0) ||
+ (DataPathIndex[0] == XRFDC_BLK_ID1)) &&
+ ((MultibandConfig == XRFDC_MB_MODE_2X_BLK01_BLK23) ||
+ (MultibandConfig == XRFDC_MB_MODE_4X))) {
+ MultibandConfig = XRFDC_MB_MODE_2X_BLK23;
+ } else if ((MultibandConfig == XRFDC_MB_MODE_2X_BLK01) &&
+ ((DataPathIndex[0] == XRFDC_BLK_ID0) ||
+ (DataPathIndex[0] == XRFDC_BLK_ID1))) {
+ MultibandConfig = XRFDC_MB_MODE_SB;
+ } else if ((MultibandConfig == XRFDC_MB_MODE_2X_BLK23) &&
+ ((DataPathIndex[0] == XRFDC_BLK_ID2) ||
+ (DataPathIndex[0] == XRFDC_BLK_ID3))) {
+ MultibandConfig = XRFDC_MB_MODE_SB;
+ }
+ } else if (NoOfDataPaths == 2U) {
+ *ModePtr = XRFDC_MULTIBAND_MODE_2X;
+ if (((MultibandConfig == XRFDC_MB_MODE_2X_BLK01) &&
+ (DataPathIndex[0] == XRFDC_BLK_ID2) && (DataPathIndex[1] == XRFDC_BLK_ID3)) ||
+ ((MultibandConfig == XRFDC_MB_MODE_2X_BLK23) && (DataPathIndex[0] == XRFDC_BLK_ID0) &&
+ (DataPathIndex[1] == XRFDC_BLK_ID1)) || (MultibandConfig == XRFDC_MB_MODE_4X)) {
+ MultibandConfig = XRFDC_MB_MODE_2X_BLK01_BLK23;
+ } else if (((DataPathIndex[0] == XRFDC_BLK_ID2) && (DataPathIndex[1] == XRFDC_BLK_ID3)) &&
+ (MultibandConfig == XRFDC_MB_MODE_SB)) {
+ MultibandConfig = XRFDC_MB_MODE_2X_BLK23;
+ } else if (((DataPathIndex[0] == XRFDC_BLK_ID0) && (DataPathIndex[1] == XRFDC_BLK_ID1)) &&
+ (MultibandConfig == XRFDC_MB_MODE_SB)) {
+ MultibandConfig = XRFDC_MB_MODE_2X_BLK01;
+ }
+ } else if (NoOfDataPaths == 4U) {
+ *ModePtr = XRFDC_MULTIBAND_MODE_4X;
+ MultibandConfig = XRFDC_MB_MODE_4X;
+ } else {
+ metal_log(METAL_LOG_ERROR, "\n Invalid DigitalDataPathMask "
+ "value in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ /* Update Multiband Config member */
+ if (Type == XRFDC_ADC_TILE) {
+ InstancePtr->ADC_Tile[Tile_Id].MultibandConfig = MultibandConfig;
+ } else {
+ InstancePtr->DAC_Tile[Tile_Id].MultibandConfig = MultibandConfig;
+ }
+
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+/*****************************************************************************/
+/**
+*
+* User-level API to setup multiband configuration.
+*
+* @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 DigitalDataPathMask is the DataPath mask. First 4 bits represent
+* 4 data paths, 1 means enabled and 0 means disabled.
+* @param MixerInOutDataType is mixer data type, valid values are XRFDC_MB_DATATYPE_*
+* @param DataConverterMask is block enabled mask (input/output driving
+* blocks). 1 means enabled and 0 means disabled.
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not enabled.
+*
+* @note Common API for ADC/DAC blocks
+*
+******************************************************************************/
+u32 XRFdc_MultiBand(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u8 DigitalDataPathMask, u32 MixerInOutDataType, u32 DataConverterMask)
+{
+ u32 Status;
+ u32 Block_Id;
+ u8 NoOfDataPaths = 0U;
+ u32 BlockIndex[XRFDC_NUM_OF_BLKS4] = {XRFDC_BLK_ID4};
+ u32 DataPathIndex[XRFDC_NUM_OF_BLKS4] = {XRFDC_BLK_ID4};
+ u32 NoOfDataConverters = 0U;
+ u32 Mode = 0x0;
+ u32 NoOfBlocks = XRFDC_BLK_ID4;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ if ((DigitalDataPathMask == 0U) || (DigitalDataPathMask > 0xFU)) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid DigitalDataPathMask "
+ "value in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ if ((DataConverterMask == 0U) || (DataConverterMask > 0xFU)) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid DataConverterMask "
+ "value in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ if ((MixerInOutDataType != XRFDC_MB_DATATYPE_C2C) &&
+ (MixerInOutDataType != XRFDC_MB_DATATYPE_R2C) &&
+ (MixerInOutDataType != XRFDC_MB_DATATYPE_C2R)) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid MixerInOutDataType "
+ "value in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ NoOfBlocks = XRFDC_BLK_ID2;
+ }
+ /* Identify DataPathIndex and BlockIndex */
+ for (Block_Id = XRFDC_BLK_ID0; Block_Id < NoOfBlocks; Block_Id++) {
+ if ((DataConverterMask & (1U << Block_Id)) != 0U) {
+ BlockIndex[NoOfDataConverters] = Block_Id;
+ NoOfDataConverters += 1U;
+ 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 ((DigitalDataPathMask & (1U << Block_Id)) != 0U) {
+ DataPathIndex[NoOfDataPaths] = Block_Id;
+ NoOfDataPaths += 1U;
+ 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;
+ }
+ }
+ }
+
+ /* rerouting & configuration for alternative bonding. */
+ if ((Type == XRFDC_DAC_TILE) && (DataConverterMask & 0x05) && (MixerInOutDataType == XRFDC_MB_DATATYPE_C2C) &&
+ (InstancePtr->RFdc_Config.DACTile_Config[Tile_Id].NumSlices == 2)) {
+ BlockIndex[XRFDC_BLK_ID1] = XRFDC_BLK_ID1;
+ XRFdc_ClrSetReg(InstancePtr, XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, XRFDC_BLK_ID1),
+ XRFDC_DAC_MB_CFG_OFFSET, XRFDC_ALT_BOND_MASK, XRFDC_ENABLED << XRFDC_ALT_BOND_SHIFT);
+ XRFdc_ClrSetReg(InstancePtr, XRFDC_BLOCK_BASE(XRFDC_DAC_TILE, Tile_Id, XRFDC_BLK_ID2),
+ XRFDC_DAC_MB_CFG_OFFSET, XRFDC_ALT_BOND_MASK, XRFDC_ENABLED << XRFDC_ALT_BOND_SHIFT);
+ }
+
+ if (BlockIndex[0] != DataPathIndex[0]) {
+ metal_log(METAL_LOG_ERROR, "\n Not a valid MB/SB "
+ "combination in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ /* UPdate MultibandConfig in driver instance */
+ Status = XRFdc_UpdateMBConfig(InstancePtr, Type, Tile_Id, NoOfDataPaths, &Mode,
+ DataPathIndex);
+ if (Status != XRFDC_SUCCESS) {
+ goto RETURN_PATH;
+ }
+
+ if ((MixerInOutDataType == XRFDC_MB_DATATYPE_C2C) && (Mode == XRFDC_SINGLEBAND_MODE)) {
+ /* Singleband C2C */
+ XRFdc_SB_C2C(InstancePtr, Type, Tile_Id, MixerInOutDataType, Mode,
+ DataPathIndex, BlockIndex);
+ } else if (((MixerInOutDataType == XRFDC_MB_DATATYPE_R2C) ||
+ (MixerInOutDataType == XRFDC_MB_DATATYPE_C2R)) && (Mode == XRFDC_SINGLEBAND_MODE)) {
+ /* Singleband R2C and C2R */
+ XRFdc_SB_R2C_C2R(InstancePtr, Type, Tile_Id, MixerInOutDataType, Mode,
+ DataPathIndex, BlockIndex);
+ }
+ if ((MixerInOutDataType == XRFDC_MB_DATATYPE_C2C) &&
+ ((Mode == XRFDC_MULTIBAND_MODE_2X) || (Mode == XRFDC_MULTIBAND_MODE_4X))) {
+ /* Multiband C2C */
+ XRFdc_MB_C2C(InstancePtr, Type, Tile_Id, NoOfDataPaths, MixerInOutDataType, Mode,
+ DataPathIndex, BlockIndex);
+ } else if (((MixerInOutDataType == XRFDC_MB_DATATYPE_R2C) || (MixerInOutDataType == XRFDC_MB_DATATYPE_C2R)) &&
+ ((Mode == XRFDC_MULTIBAND_MODE_2X) || (Mode == XRFDC_MULTIBAND_MODE_4X))) {
+ /* Multiband C2R and R2C */
+ XRFdc_MB_R2C_C2R(InstancePtr, Type, Tile_Id, NoOfDataPaths, MixerInOutDataType,
+ Mode, DataPathIndex, BlockIndex);
+ }
+
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+/*****************************************************************************/
+/**
+*
+* Sets up signal flow configuration.
+*
+* @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 Mode is connection mode SB/MB_2X/MB_4X.
+* @param DigitalDataPathId for the requested I or Q data.
+* @param MixerInOutDataType is mixer data type, valid values are XRFDC_MB_DATATYPE_*
+* @param ConnectIData is analog blocks that are connected to
+* DigitalDataPath I.
+* @param ConnectQData is analog blocks that are connected to
+* DigitalDataPath Q.
+*
+* @return None
+*
+* @note static API used internally.
+*
+******************************************************************************/
+static void XRFdc_SetSignalFlow(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Mode, u32 DigitalDataPathId, u32 MixerInOutDataType,
+ int ConnectIData, int ConnectQData)
+{
+ u16 ReadReg;
+ u32 BaseAddr;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, DigitalDataPathId);
+ if (Type == XRFDC_ADC_TILE) {
+ /* ADC */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_SWITCH_MATRX_OFFSET);
+ ReadReg &= ~XRFDC_SWITCH_MTRX_MASK;
+ if (ConnectIData != -1) {
+ ReadReg |= ((u16)ConnectIData) << XRFDC_SEL_CB_TO_MIX0_SHIFT;
+ }
+ if (ConnectQData != -1) {
+ ReadReg |= (u16)ConnectQData;
+ }
+ if ((MixerInOutDataType == XRFDC_MB_DATATYPE_C2C) &&
+ (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1)) {
+ ReadReg |= XRFDC_SEL_CB_TO_QMC_MASK;
+ }
+ if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) {
+ ReadReg |= XRFDC_SEL_CB_TO_DECI_MASK;
+ }
+
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_SWITCH_MATRX_OFFSET, ReadReg);
+ } else {
+ /* DAC */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_DAC_MB_CFG_OFFSET);
+ ReadReg &= ~XRFDC_MB_CFG_MASK;
+ if (Mode == XRFDC_SINGLEBAND_MODE) {
+ if ((u32)ConnectIData == DigitalDataPathId) {
+ if (ConnectQData != -1) {
+ ReadReg |= XRFDC_SB_C2C_BLK0;
+ } else {
+ ReadReg |= XRFDC_SB_C2R;
+ }
+ }
+ if ((ConnectIData == -1) && (ConnectQData == -1)) {
+ ReadReg |= XRFDC_SB_C2C_BLK1;
+ }
+ } else {
+ if (Mode == XRFDC_MULTIBAND_MODE_4X) {
+ ReadReg |= XRFDC_MB_EN_4X_MASK;
+ }
+ if ((u32)ConnectIData == DigitalDataPathId) {
+ if (ConnectQData != -1) {
+ ReadReg |= XRFDC_MB_C2C_BLK0;
+ } else {
+ ReadReg |= XRFDC_MB_C2R_BLK0;
+ }
+ } else {
+ if (ConnectQData != -1) {
+ ReadReg |= XRFDC_MB_C2C_BLK1;
+ } else {
+ ReadReg |= XRFDC_MB_C2R_BLK1;
+ }
+ }
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_DAC_MB_CFG_OFFSET, ReadReg);
+ }
+}
+
+/** @} */ \ No newline at end of file
diff --git a/mpm/lib/rfdc/xrfdc_mixer.c b/mpm/lib/rfdc/xrfdc_mixer.c
new file mode 100644
index 000000000..747e180a4
--- /dev/null
+++ b/mpm/lib/rfdc/xrfdc_mixer.c
@@ -0,0 +1,1091 @@
+/******************************************************************************
+*
+* Copyright (C) 2018-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_mixer.c
+* @addtogroup xrfdc_v6_0
+* @{
+*
+* Contains the interface functions of the Mixer Settings in XRFdc driver.
+* See xrfdc.h for a detailed description of the device and driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- --- -------- -----------------------------------------------
+* 5.0 sk 08/06/18 Initial release
+* 5.1 cog 01/29/19 Replace structure reference ADC checks with
+* function.
+* cog 01/29/19 XRFdc_SetCoarseMixer and MixerRangeCheck now need
+* Tile_id as a parameter.
+* cog 01/29/19 Rename DataType to MixerInputDataType for
+* readability.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+#include "mpm/rfdc/xrfdc.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+static void XRFdc_SetFineMixer(XRFdc *InstancePtr, u32 BaseAddr,
+ XRFdc_Mixer_Settings *MixerSettingsPtr);
+static void XRFdc_SetCoarseMixer(XRFdc *InstancePtr, u32 Type, u32 BaseAddr,
+ u32 Tile_Id, u32 Block_Id, u32 CoarseMixFreq, XRFdc_Mixer_Settings *MixerSettingsPtr);
+static u32 XRFdc_MixerRangeCheck(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ XRFdc_Mixer_Settings *MixerSettingsPtr);
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+/**
+* The API is used to update various mixer settings, fine, coarse, NCO etc.
+* Mixer/NCO 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 MixerSettingsPtr Pointer to the XRFdc_Mixer_Settings structure
+* in which the Mixer/NCO settings are passed.
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not enabled.
+*
+* @note FineMixerScale in Mixer_Settings structure can have 3 values.
+* XRFDC_MIXER_SCALE_* represents the valid values.
+* XRFDC_MIXER_SCALE_AUTO - If mixer mode is R2C, Mixer Scale is
+* set to 1 and for other modes mixer scale is set to 0.7
+* XRFDC_MIXER_SCALE_1P0 - To set fine mixer scale to 1.
+* XRFDC_MIXER_SCALE_0P7 - To set fine mixer scale to 0.7.
+*
+******************************************************************************/
+u32 XRFdc_SetMixerSettings(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, XRFdc_Mixer_Settings *MixerSettingsPtr)
+{
+ u32 Status;
+ u16 ReadReg;
+ u32 BaseAddr;
+ double SamplingRate;
+ s64 Freq;
+ s32 PhaseOffset;
+ u32 NoOfBlocks;
+ u32 Index;
+ XRFdc_Mixer_Settings *MixerConfigPtr;
+ u8 CalibrationMode = 0U;
+ u32 CoarseMixFreq;
+ double NCOFreq;
+ u32 NyquistZone = 0U;
+ u32 Offset;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(MixerSettingsPtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, Type, Tile_Id, Block_Id);
+ if (Status != XRFDC_SUCCESS) {
+ goto RETURN_PATH;
+ }
+
+ Status = XRFdc_MixerRangeCheck(InstancePtr, Type, Tile_Id, MixerSettingsPtr);
+ if (Status != XRFDC_SUCCESS) {
+ 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) {
+ /* ADC */
+ MixerConfigPtr = &InstancePtr->ADC_Tile[Tile_Id].
+ ADCBlock_Digital_Datapath[Index].Mixer_Settings;
+ SamplingRate = InstancePtr->ADC_Tile[Tile_Id].
+ PLL_Settings.SampleRate;
+ } else {
+ /* DAC */
+ MixerConfigPtr = &InstancePtr->DAC_Tile[Tile_Id].
+ DACBlock_Digital_Datapath[Index].Mixer_Settings;
+ SamplingRate = InstancePtr->DAC_Tile[Tile_Id].
+ PLL_Settings.SampleRate;
+ }
+
+ BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Index);
+
+ if (SamplingRate <= 0) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Incorrect Sampling "
+ "rate in %s\r\n", __func__);
+ goto RETURN_PATH;
+ } else {
+ metal_log(METAL_LOG_DEBUG, "\n Sampling "
+ "rate is %2.4f in %s\r\n", SamplingRate, __func__);
+ }
+
+ SamplingRate *= XRFDC_MILLI;
+ /* Set MixerInputDataType for ADC and DAC */
+ if (Type == XRFDC_DAC_TILE) {
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_DAC_ITERP_DATA_OFFSET);
+ ReadReg &= ~XRFDC_DAC_INTERP_DATA_MASK;
+ InstancePtr->DAC_Tile[Tile_Id].
+ DACBlock_Digital_Datapath[Index].MixerInputDataType =
+ XRFDC_DATA_TYPE_REAL;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ ReadReg |= XRFDC_DAC_INTERP_DATA_MASK;
+ InstancePtr->DAC_Tile[Tile_Id].
+ DACBlock_Digital_Datapath[Index].
+ MixerInputDataType = XRFDC_DATA_TYPE_IQ;
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_DAC_ITERP_DATA_OFFSET, ReadReg);
+ } else {
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_DECI_CONFIG_OFFSET);
+ ReadReg &= ~XRFDC_DEC_CFG_MASK;
+ if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) {
+ ReadReg |= XRFDC_DEC_CFG_4GSPS_MASK;
+ } else if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2C)) {
+ ReadReg |= XRFDC_DEC_CFG_IQ_MASK;
+ } else {
+ ReadReg |= XRFDC_DEC_CFG_CHA_MASK;
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_DECI_CONFIG_OFFSET, ReadReg);
+ if (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) {
+ InstancePtr->ADC_Tile[Tile_Id].
+ ADCBlock_Digital_Datapath[Index].
+ MixerInputDataType = XRFDC_DATA_TYPE_IQ;
+ }
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2R)) {
+ InstancePtr->ADC_Tile[Tile_Id].
+ ADCBlock_Digital_Datapath[Index].
+ MixerInputDataType = XRFDC_DATA_TYPE_REAL;
+ }
+ }
+
+ /* Set NCO Phase Mode */
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ if ((Index == XRFDC_BLK_ID0) || (Index == XRFDC_BLK_ID2)) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_PHASE_MOD_OFFSET,
+ XRFDC_NCO_PHASE_MOD_EVEN);
+ } else {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_PHASE_MOD_OFFSET,
+ XRFDC_NCO_PHASE_MODE_ODD);
+ }
+ }
+
+ /* Update NCO, CoarseMix freq based on calibration mode */
+ CoarseMixFreq = MixerSettingsPtr->CoarseMixFreq;
+ NCOFreq = MixerSettingsPtr->Freq;
+ if (Type == XRFDC_ADC_TILE) {
+ Status = XRFdc_GetCalibrationMode(InstancePtr,
+ Tile_Id, Block_Id, &CalibrationMode);
+ if (Status != XRFDC_SUCCESS) {
+ return XRFDC_FAILURE;
+ }
+ if (CalibrationMode == XRFDC_CALIB_MODE1) {
+ switch (CoarseMixFreq) {
+ case XRFDC_COARSE_MIX_BYPASS:
+ CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ break;
+ case XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR:
+ CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ break;
+ case XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO:
+ CoarseMixFreq =
+ XRFDC_COARSE_MIX_BYPASS;
+ break;
+ case XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR:
+ CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ break;
+ default:
+ CoarseMixFreq =
+ XRFDC_COARSE_MIX_OFF;
+ break;
+ }
+ NCOFreq -= SamplingRate / 2.0;
+ }
+ }
+
+ if ((NCOFreq < -(SamplingRate / 2.0)) ||
+ (NCOFreq > (SamplingRate / 2.0))) {
+ Status = XRFdc_GetNyquistZone(InstancePtr, Type,
+ Tile_Id, Block_Id, &NyquistZone);
+ if (Status != XRFDC_SUCCESS) {
+ return XRFDC_FAILURE;
+ }
+ do {
+ if (NCOFreq < -(SamplingRate / 2.0)) {
+ NCOFreq += SamplingRate;
+ }
+ if (NCOFreq > (SamplingRate / 2.0)) {
+ NCOFreq -= SamplingRate;
+ }
+ } while ((NCOFreq < -(SamplingRate / 2.0)) ||
+ (NCOFreq > (SamplingRate / 2.0)));
+
+ if ((NyquistZone == XRFDC_EVEN_NYQUIST_ZONE) &&
+ (NCOFreq != 0)) {
+ NCOFreq *= -1;
+ }
+ }
+
+ /* NCO Frequency */
+ if (NCOFreq < 0) {
+ Freq = ((NCOFreq * XRFDC_NCO_FREQ_MIN_MULTIPLIER) /
+ SamplingRate);
+ } else {
+ Freq = ((NCOFreq * XRFDC_NCO_FREQ_MULTIPLIER) /
+ SamplingRate);
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_LOW_OFFSET, (u16)Freq);
+ ReadReg = (Freq >> XRFDC_NCO_FQWD_MID_SHIFT) & XRFDC_NCO_FQWD_MID_MASK;
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_MID_OFFSET, (u16)ReadReg);
+ ReadReg = (Freq >> XRFDC_NCO_FQWD_UPP_SHIFT) & XRFDC_NCO_FQWD_UPP_MASK;
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_UPP_OFFSET, (u16)ReadReg);
+
+ /* Phase Offset */
+ PhaseOffset = ((MixerSettingsPtr->PhaseOffset *
+ XRFDC_NCO_PHASE_MULTIPLIER) / XRFDC_MIXER_PHASE_OFFSET_UP_LIMIT);
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_NCO_PHASE_LOW_OFFSET,
+ (u16)PhaseOffset);
+
+ ReadReg = (PhaseOffset >> XRFDC_NCO_PHASE_UPP_SHIFT) &
+ XRFDC_NCO_PHASE_UPP_MASK;
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_NCO_PHASE_UPP_OFFSET,
+ ReadReg);
+
+ if (MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_COARSE) {
+ XRFdc_SetCoarseMixer(InstancePtr, Type, BaseAddr, Tile_Id,
+ Index, CoarseMixFreq, MixerSettingsPtr);
+ } else {
+ XRFdc_SetFineMixer(InstancePtr, BaseAddr, MixerSettingsPtr);
+ }
+
+ /* Fine Mixer Scale */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_MXR_MODE_OFFSET);
+ if (MixerSettingsPtr->FineMixerScale == XRFDC_MIXER_SCALE_1P0) {
+ ReadReg |= XRFDC_FINE_MIX_SCALE_MASK;
+ InstancePtr->UpdateMixerScale = 0x1U;
+ } else if (MixerSettingsPtr->FineMixerScale == XRFDC_MIXER_SCALE_0P7) {
+ ReadReg &= ~XRFDC_FINE_MIX_SCALE_MASK;
+ InstancePtr->UpdateMixerScale = 0x1U;
+ } else {
+ InstancePtr->UpdateMixerScale = 0x0U;
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ ReadReg);
+
+ /* Event Source */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_NCO_UPDT_OFFSET,
+ XRFDC_NCO_UPDT_MODE_MASK, MixerSettingsPtr->EventSource);
+ if (MixerSettingsPtr->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_NCO_MASK);
+ }
+
+ /* Update the instance with new values */
+ MixerConfigPtr->EventSource = MixerSettingsPtr->EventSource;
+ MixerConfigPtr->PhaseOffset = MixerSettingsPtr->PhaseOffset;
+ MixerConfigPtr->MixerMode = MixerSettingsPtr->MixerMode;
+ MixerConfigPtr->CoarseMixFreq = MixerSettingsPtr->CoarseMixFreq;
+ MixerConfigPtr->Freq = MixerSettingsPtr->Freq;
+ MixerConfigPtr->MixerType = MixerSettingsPtr->MixerType;
+ }
+
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+
+}
+
+/*****************************************************************************/
+/**
+* Static API used to do the Mixer Settings range check.
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param MixerSettingsPtr Pointer to the XRFdc_Mixer_Settings structure
+* in which the Mixer/NCO settings are passed.
+*
+* @return
+* - XRFDC_SUCCESS if mixer settings are within the range.
+* - XRFDC_FAILURE if mixer settings are not in valid range
+*
+* @note None
+*
+******************************************************************************/
+static u32 XRFdc_MixerRangeCheck(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ XRFdc_Mixer_Settings *MixerSettingsPtr)
+{
+ u32 Status;
+
+ if ((MixerSettingsPtr->PhaseOffset >=
+ XRFDC_MIXER_PHASE_OFFSET_UP_LIMIT) ||
+ (MixerSettingsPtr->PhaseOffset <=
+ XRFDC_MIXER_PHASE_OFFSET_LOW_LIMIT)) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid phase offset value "
+ "in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->EventSource > XRFDC_EVNT_SRC_PL) ||
+ ((MixerSettingsPtr->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 (MixerSettingsPtr->MixerMode > XRFDC_MIXER_MODE_R2R) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid fine mixer mode "
+ "in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->CoarseMixFreq != XRFDC_COARSE_MIX_OFF) &&
+ (MixerSettingsPtr->CoarseMixFreq !=
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO) &&
+ (MixerSettingsPtr->CoarseMixFreq !=
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR) &&
+ (MixerSettingsPtr->CoarseMixFreq !=
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR) &&
+ (MixerSettingsPtr->CoarseMixFreq !=
+ XRFDC_COARSE_MIX_BYPASS)) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid coarse mix "
+ "frequency value in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if (MixerSettingsPtr->FineMixerScale > XRFDC_MIXER_SCALE_0P7) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Mixer Scale in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if (((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2C) &&
+ (Type == XRFDC_DAC_TILE)) ||
+ ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R) &&
+ (Type == XRFDC_ADC_TILE))) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Mixer mode in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->MixerType != XRFDC_MIXER_TYPE_FINE) &&
+ (MixerSettingsPtr->MixerType != XRFDC_MIXER_TYPE_COARSE)) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Mixer Type in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE) &&
+ ((MixerSettingsPtr->EventSource == XRFDC_EVNT_SRC_SLICE) ||
+ (MixerSettingsPtr->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 (((MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_COARSE) &&
+ (MixerSettingsPtr->CoarseMixFreq == XRFDC_COARSE_MIX_OFF)) ||
+ ((MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_FINE) &&
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_OFF))) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Invalid Combination of "
+ "Mixer settings in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_COARSE) &&
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_OFF)) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Invalid Combination of "
+ "Mixer type and Mixer mode in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_FINE) &&
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2R)) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Invalid Combination of "
+ "Mixer type and Mixer mode in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_COARSE) &&
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2R) &&
+ (MixerSettingsPtr->CoarseMixFreq != XRFDC_COARSE_MIX_BYPASS)) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Invalid Combination of "
+ "Mixer type and Mixer mode in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ Status = XRFDC_SUCCESS;
+
+RETURN_PATH:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+* Static API used to set the Fine Mixer.
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param BaseAddr is ADC or DAC base address.
+* @param CoarseMixFreq is ADC or DAC Coarse mixer frequency.
+* @param MixerSettingsPtr Pointer to the XRFdc_Mixer_Settings structure
+* in which the Mixer/NCO settings are passed.
+*
+* @return
+* - None
+*
+* @note Static API
+*
+******************************************************************************/
+static void XRFdc_SetFineMixer(XRFdc *InstancePtr, u32 BaseAddr,
+ XRFdc_Mixer_Settings *MixerSettingsPtr)
+{
+
+ if (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) {
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ (XRFDC_SEL_I_IQ_MASK | XRFDC_SEL_Q_IQ_MASK |
+ XRFDC_EN_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK),
+ (XRFDC_EN_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK |
+ XRFDC_I_IQ_COS_MINSIN | XRFDC_Q_IQ_SIN_COS));
+ } else if (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R) {
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ (XRFDC_EN_I_IQ_MASK | XRFDC_SEL_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK),
+ (XRFDC_EN_I_IQ_MASK | XRFDC_I_IQ_COS_MINSIN));
+ } else if (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2C) {
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ (XRFDC_EN_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK |
+ XRFDC_SEL_I_IQ_MASK | XRFDC_SEL_Q_IQ_MASK |
+ XRFDC_FINE_MIX_SCALE_MASK), (XRFDC_EN_I_IQ | XRFDC_EN_Q_IQ |
+ XRFDC_I_IQ_COS_MINSIN | XRFDC_Q_IQ_SIN_COS |
+ XRFDC_FINE_MIX_SCALE_MASK));
+ } else {
+ /* Fine mixer mode is OFF */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ XRFDC_MIXER_MODE_OFF);
+ }
+
+ /* Coarse Mixer is OFF */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_MXR_CFG0_OFFSET,
+ XRFDC_MIX_CFG0_MASK, XRFDC_CRSE_MIX_OFF);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_MXR_CFG1_OFFSET,
+ XRFDC_MIX_CFG1_MASK, XRFDC_CRSE_MIX_OFF);
+}
+
+/*****************************************************************************/
+/**
+* Static API used to set the Coarse Mixer.
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param BaseAddr is ADC or DAC base address.
+* @param Block_Id is ADC/DAC block number inside the tile.
+* @param CoarseMixFreq is ADC or DAC Coarse mixer frequency.
+* @param MixerSettingsPtr Pointer to the XRFdc_Mixer_Settings structure
+* in which the Mixer/NCO settings are passed.
+*
+* @return
+* - None
+*
+* @note Static API
+*
+******************************************************************************/
+static void XRFdc_SetCoarseMixer(XRFdc *InstancePtr, u32 Type, u32 BaseAddr,
+ u32 Tile_Id, u32 Block_Id, u32 CoarseMixFreq, XRFdc_Mixer_Settings *MixerSettingsPtr)
+{
+ u16 ReadReg;
+
+ if (CoarseMixFreq == XRFDC_COARSE_MIX_BYPASS) {
+ /* Coarse Mix BYPASS */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_MXR_CFG0_OFFSET,
+ XRFDC_MIX_CFG0_MASK, XRFDC_CRSE_MIX_BYPASS);
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG1_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ ReadReg |= XRFDC_CRSE_MIX_BYPASS;
+ } else {
+ ReadReg |= XRFDC_CRSE_MIX_OFF;
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET, (u16)ReadReg);
+ } else if (CoarseMixFreq == XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO) {
+ /* Coarse Mix freq Fs/2 */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG0_MASK;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_I_Q_FSBYTWO;
+ } else {
+ if ((Block_Id % 2U) == 0U) {
+ ReadReg |= XRFDC_CRSE_MIX_BYPASS;
+ } else {
+ ReadReg |= XRFDC_CRSE_4GSPS_ODD_FSBYTWO;
+ }
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET, (u16)ReadReg);
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG1_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_I_Q_FSBYTWO;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_BYPASS :
+ XRFDC_CRSE_4GSPS_ODD_FSBYTWO;
+ }
+ } else {
+ ReadReg |= XRFDC_CRSE_MIX_OFF;
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET, (u16)ReadReg);
+ } else if (CoarseMixFreq == XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR) {
+ /* Coarse Mix freq Fs/4 */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG0_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_I_FSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_I_ODD_FSBYFOUR;
+ }
+ } else {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_R_I_FSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_OFF;
+ }
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET, (u16)ReadReg);
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG1_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_Q_FSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR;
+ }
+ } else {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_R_Q_FSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_OFF :
+ XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR;
+ }
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET, (u16)ReadReg);
+ } else if (CoarseMixFreq == XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR) {
+ /* Coarse Mix freq -Fs/4 */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG0_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_I_MINFSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR;
+ }
+ } else {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_R_I_MINFSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_OFF;
+ }
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET, (u16)ReadReg);
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG1_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_Q_MINFSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_I_ODD_FSBYFOUR;
+ }
+ } else {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_R_Q_MINFSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_OFF :
+ XRFDC_CRSE_MIX_I_ODD_FSBYFOUR;
+ }
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET, (u16)ReadReg);
+ } else if (CoarseMixFreq == XRFDC_COARSE_MIX_OFF) {
+ /* Coarse Mix OFF */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_MXR_CFG0_OFFSET,
+ XRFDC_MIX_CFG0_MASK, XRFDC_CRSE_MIX_OFF);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_MXR_CFG1_OFFSET,
+ XRFDC_MIX_CFG1_MASK, XRFDC_CRSE_MIX_OFF);
+ } else {
+ metal_log(METAL_LOG_ERROR, "\n Invalid Coarse "
+ "Mixer frequency in %s\r\n", __func__);
+ }
+
+ /* Fine mixer mode is OFF */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ XRFDC_MIXER_MODE_OFF);
+}
+
+/*****************************************************************************/
+/**
+*
+* The API returns back Mixer/NCO settings 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 MixerSettingsPtr Pointer to the XRFdc_Mixer_Settings structure
+* in which the Mixer/NCO settings are passed.
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not enabled.
+*
+* @note FineMixerScale in Mixer_Settings structure can have 3 values.
+* XRFDC_MIXER_SCALE_* represents the valid values.
+* XRFDC_MIXER_SCALE_AUTO - If mixer mode is R2C, Mixer Scale is
+* set to 1 and for other modes mixer scale is set to 0.7
+* XRFDC_MIXER_SCALE_1P0 - To set fine mixer scale to 1.
+* XRFDC_MIXER_SCALE_0P7 - To set fine mixer scale to 0.7.
+*
+******************************************************************************/
+u32 XRFdc_GetMixerSettings(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, XRFdc_Mixer_Settings *MixerSettingsPtr)
+{
+ u32 Status;
+ u32 BaseAddr;
+ u64 ReadReg;
+ u64 ReadReg_Mix1;
+ double SamplingRate;
+ s64 Freq;
+ s32 PhaseOffset;
+ u32 Block;
+ u8 CalibrationMode = 0U;
+ XRFdc_Mixer_Settings *MixerConfigPtr;
+ u32 NyquistZone = 0U;
+ double NCOFreq;
+ u32 FineMixerMode;
+ u32 CoarseMixerMode = 0x0;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(MixerSettingsPtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, Type, Tile_Id, Block_Id);
+ if (Status != XRFDC_SUCCESS) {
+ goto RETURN_PATH;
+ }
+
+ Block = Block_Id;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ if (Block_Id == XRFDC_BLK_ID1) {
+ Block_Id = XRFDC_BLK_ID3;
+ }
+ if (Block_Id == XRFDC_BLK_ID0) {
+ Block_Id = XRFDC_BLK_ID1;
+ }
+ }
+
+ if (Type == XRFDC_ADC_TILE) {
+ /* ADC */
+ SamplingRate = InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.
+ SampleRate;
+ MixerConfigPtr = &InstancePtr->ADC_Tile[Tile_Id].
+ ADCBlock_Digital_Datapath[Block_Id].Mixer_Settings;
+ } else {
+ /* DAC */
+ SamplingRate = InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.
+ SampleRate;
+ MixerConfigPtr = &InstancePtr->DAC_Tile[Tile_Id].
+ DACBlock_Digital_Datapath[Block_Id].Mixer_Settings;
+ }
+
+ if (SamplingRate <= 0) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Incorrect Sampling rate "
+ "in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Block_Id);
+ SamplingRate *= XRFDC_MILLI;
+ ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET, XRFDC_MIX_CFG0_MASK);
+ ReadReg_Mix1 = XRFdc_RDReg(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET, XRFDC_MIX_CFG1_MASK);
+ MixerSettingsPtr->CoarseMixFreq = 0x20;
+
+ /* Identify CoarseMixFreq and CoarseMixerMode */
+ if (ReadReg == XRFDC_CRSE_MIX_BYPASS) {
+ if (ReadReg_Mix1 == XRFDC_CRSE_MIX_BYPASS) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_BYPASS;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if (ReadReg_Mix1 == XRFDC_CRSE_MIX_OFF) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_BYPASS;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2R;
+ if (MixerConfigPtr->MixerMode == XRFDC_MIXER_MODE_R2C) {
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+ }
+ }
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ if ((ReadReg_Mix1 == XRFDC_CRSE_MIX_I_Q_FSBYTWO) &&
+ (ReadReg == XRFDC_CRSE_MIX_I_Q_FSBYTWO)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if ((ReadReg_Mix1 == XRFDC_CRSE_MIX_OFF) &&
+ (ReadReg == XRFDC_CRSE_MIX_I_Q_FSBYTWO)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+ } else {
+ if (ReadReg == XRFDC_CRSE_4GSPS_ODD_FSBYTWO) {
+ if (ReadReg_Mix1 == XRFDC_CRSE_4GSPS_ODD_FSBYTWO) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if (ReadReg_Mix1 == XRFDC_CRSE_MIX_OFF) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+ }
+ }
+
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ if ((ReadReg_Mix1 == XRFDC_CRSE_MIX_Q_FSBYFOUR) &&
+ (ReadReg == XRFDC_CRSE_MIX_I_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if ((ReadReg_Mix1 ==
+ XRFDC_CRSE_MIX_R_Q_FSBYFOUR) &&
+ (ReadReg == XRFDC_CRSE_MIX_R_I_MINFSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+ } else {
+ if ((ReadReg == XRFDC_CRSE_MIX_I_ODD_FSBYFOUR) &&
+ (ReadReg_Mix1 == XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if ((ReadReg == XRFDC_CRSE_MIX_OFF) &&
+ (ReadReg_Mix1 == XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+
+ }
+
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ if ((ReadReg_Mix1 == XRFDC_CRSE_MIX_I_FSBYFOUR) &&
+ (ReadReg == XRFDC_CRSE_MIX_Q_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if ((ReadReg_Mix1 == XRFDC_CRSE_MIX_R_Q_MINFSBYFOUR) &&
+ (ReadReg == XRFDC_CRSE_MIX_R_I_MINFSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+ } else {
+ if ((ReadReg == XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR) &&
+ (ReadReg_Mix1 == XRFDC_CRSE_MIX_I_ODD_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if ((ReadReg == XRFDC_CRSE_MIX_OFF) &&
+ (ReadReg_Mix1 == XRFDC_CRSE_MIX_I_ODD_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+
+ }
+
+ if ((ReadReg == XRFDC_CRSE_MIX_OFF) && (ReadReg_Mix1 ==
+ XRFDC_CRSE_MIX_OFF)) {
+ MixerSettingsPtr->CoarseMixFreq = XRFDC_COARSE_MIX_OFF;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ }
+ if (MixerSettingsPtr->CoarseMixFreq == 0x20U) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Coarse mixer settings not match any of the modes %s\r\n",
+ __func__);
+ }
+ if ((MixerConfigPtr->MixerMode == XRFDC_MIXER_MODE_C2R) &&
+ (CoarseMixerMode == XRFDC_MIXER_MODE_C2C)) {
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2R;
+ }
+
+ /* Identify FineMixerMode */
+ ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ (XRFDC_EN_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK));
+ if (ReadReg == 0xFU) {
+ FineMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if (ReadReg == 0x3U) {
+ FineMixerMode = XRFDC_MIXER_MODE_C2R;
+ } else if (ReadReg == 0x5U) {
+ FineMixerMode = XRFDC_MIXER_MODE_R2C;
+ } else {
+ FineMixerMode = XRFDC_MIXER_MODE_OFF;
+ }
+
+ if (FineMixerMode == XRFDC_MIXER_MODE_OFF) {
+ MixerSettingsPtr->MixerType = XRFDC_MIXER_TYPE_COARSE;
+ MixerSettingsPtr->MixerMode = CoarseMixerMode;
+ } else {
+ MixerSettingsPtr->MixerType = XRFDC_MIXER_TYPE_FINE;
+ MixerSettingsPtr->MixerMode = FineMixerMode;
+ }
+
+ /* Identify Fine Mixer Scale */
+ ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr,
+ XRFDC_MXR_MODE_OFFSET, XRFDC_FINE_MIX_SCALE_MASK);
+ if (InstancePtr->UpdateMixerScale == 0x0U) {
+ MixerSettingsPtr->FineMixerScale =
+ XRFDC_MIXER_SCALE_AUTO;
+ } else if ((ReadReg != 0U) &&
+ (InstancePtr->UpdateMixerScale == 0x1U)) {
+ MixerSettingsPtr->FineMixerScale =
+ XRFDC_MIXER_SCALE_1P0;
+ } else if (InstancePtr->UpdateMixerScale == 0x1U) {
+ MixerSettingsPtr->FineMixerScale =
+ XRFDC_MIXER_SCALE_0P7;
+ } else {
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Fine mixer scale in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ /* Phase Offset */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_NCO_PHASE_UPP_OFFSET);
+ PhaseOffset = ReadReg << XRFDC_NCO_PHASE_UPP_SHIFT;
+ PhaseOffset |= XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_NCO_PHASE_LOW_OFFSET);
+ PhaseOffset &= XRFDC_NCO_PHASE_MASK;
+ PhaseOffset = ((PhaseOffset << 14) >> 14);
+ MixerSettingsPtr->PhaseOffset = ((PhaseOffset * 180.0) /
+ XRFDC_NCO_PHASE_MULTIPLIER);
+
+ /* NCO Frequency */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_UPP_OFFSET);
+ Freq = ReadReg << XRFDC_NCO_FQWD_UPP_SHIFT;
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_MID_OFFSET);
+ Freq |= ReadReg << XRFDC_NCO_FQWD_MID_SHIFT;
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_LOW_OFFSET);
+ Freq |= ReadReg;
+ Freq &= XRFDC_NCO_FQWD_MASK;
+ Freq = (Freq << 16) >> 16;
+ if (Freq < 0) {
+ MixerSettingsPtr->Freq = ((Freq * SamplingRate) /
+ XRFDC_NCO_FREQ_MIN_MULTIPLIER);
+ } else {
+ MixerSettingsPtr->Freq = ((Freq * SamplingRate) /
+ XRFDC_NCO_FREQ_MULTIPLIER);
+ }
+
+ /* Event Source */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_NCO_UPDT_OFFSET);
+ MixerSettingsPtr->EventSource = ReadReg & XRFDC_NCO_UPDT_MODE_MASK;
+
+ /* Update NCO, CoarseMix freq based on calibration mode */
+ NCOFreq = MixerConfigPtr->Freq;
+ if (Type == XRFDC_ADC_TILE) {
+ Status = XRFdc_GetCalibrationMode(InstancePtr, Tile_Id,
+ Block, &CalibrationMode);
+ if (Status != XRFDC_SUCCESS) {
+ return XRFDC_FAILURE;
+ }
+
+ if (CalibrationMode == XRFDC_CALIB_MODE1) {
+ switch (MixerSettingsPtr->CoarseMixFreq) {
+ case XRFDC_COARSE_MIX_BYPASS:
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ break;
+ case XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR:
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ break;
+ case XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO:
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_BYPASS;
+ break;
+ case XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR:
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ break;
+ default:
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_OFF;
+ break;
+ }
+ NCOFreq = (MixerConfigPtr->Freq -
+ (SamplingRate / 2.0));
+ }
+ }
+
+ if ((NCOFreq > (SamplingRate / 2.0)) ||
+ (NCOFreq < -(SamplingRate / 2.0))) {
+ Status = XRFdc_GetNyquistZone(InstancePtr,
+ Type, Tile_Id, Block, &NyquistZone);
+ if (Status != XRFDC_SUCCESS) {
+ return XRFDC_FAILURE;
+ }
+
+ if ((NyquistZone == XRFDC_EVEN_NYQUIST_ZONE) &&
+ (MixerSettingsPtr->Freq != 0)) {
+ MixerSettingsPtr->Freq *= -1;
+ }
+
+ do {
+ if (NCOFreq < -(SamplingRate / 2.0)) {
+ NCOFreq += SamplingRate;
+ MixerSettingsPtr->Freq -= SamplingRate;
+ }
+ if (NCOFreq > (SamplingRate / 2.0)) {
+ NCOFreq -= SamplingRate;
+ MixerSettingsPtr->Freq += SamplingRate;
+ }
+ } while ((NCOFreq > (SamplingRate / 2.0)) ||
+ (NCOFreq < -(SamplingRate / 2.0)));
+ }
+ if ((Type == XRFDC_ADC_TILE) &&
+ (CalibrationMode == XRFDC_CALIB_MODE1)) {
+ MixerSettingsPtr->Freq += (SamplingRate / 2.0);
+ }
+
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+
+}
+
+/** @} */
diff --git a/mpm/lib/rfdc/xrfdc_mts.c b/mpm/lib/rfdc/xrfdc_mts.c
new file mode 100644
index 000000000..00a1abc85
--- /dev/null
+++ b/mpm/lib/rfdc/xrfdc_mts.c
@@ -0,0 +1,1308 @@
+/******************************************************************************
+*
+* Copyright (C) 2018-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_mts.c
+* @addtogroup xrfdc_v6_0
+* @{
+*
+* Contains the multi tile sync functions of the XRFdc driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- --- -------- -----------------------------------------------
+* 3.1 jm 01/24/18 Initial release
+* 3.2 jm 03/12/18 Fixed DAC latency calculation.
+* jm 03/12/18 Added support for reloading DTC scans.
+* jm 03/12/18 Add option to configure sysref capture after MTS.
+* 4.0 sk 04/09/18 Added API to enable/disable the sysref.
+* rk 04/17/18 Adjust calculated latency by sysref period, where doing
+* so results in closer alignment to the target latency.
+* 5.0 sk 08/03/18 Fixed MISRAC warnings.
+* sk 08/03/18 Check for Block0 enable for tiles participating in MTS.
+* sk 08/24/18 Reorganize the code to improve readability and
+* optimization.
+* 5.1 cog 01/29/19 Replace structure reference ADC checks with
+* function.
+* 6.0 cog 02/17/19 Added XRFdc_GetMTSEnable API.
+*
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+#include "mpm/rfdc/xrfdc_mts.h"
+
+/************************** Constant Definitions *****************************/
+
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+static void XRFdc_MTS_Sysref_TRx(XRFdc *InstancePtr, u32 Enable);
+static void XRFdc_MTS_Sysref_Ctrl(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Is_PLL, u32 Enable_Cap, u32 Enable_Div_Reset);
+static u32 XRFdc_MTS_Sysref_Dist(XRFdc *InstancePtr, int Num_DAC);
+static u32 XRFdc_MTS_Sysref_Count(XRFdc *InstancePtr, u32 Type, u32 Count_Val);
+static u32 XRFdc_MTS_Dtc_Scan(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ XRFdc_MTS_DTC_Settings *SettingsPtr);
+static u32 XRFdc_MTS_Dtc_Code(XRFdc *InstancePtr, u32 Type, u32 BaseAddr,
+ u32 SRCtrlAddr, u32 DTCAddr, u16 SRctl, u16 SRclr_m, u32 Code);
+static u32 XRFdc_MTS_Dtc_Calc(u32 Type, u32 Tile_Id,
+ XRFdc_MTS_DTC_Settings *SettingsPtr, u8 *FlagsPtr);
+static void XRFdc_MTS_Dtc_Flag_Debug(u8 *FlagsPtr, u32 Type, u32 Tile_Id,
+ u32 Target, u32 Picked);
+static void XRFdc_MTS_FIFOCtrl(XRFdc *InstancePtr, u32 Type, u32 FIFO_Mode,
+ u32 Tiles_To_Clear);
+static u32 XRFdc_MTS_GetMarker(XRFdc *InstancePtr, u32 Type, u32 Tiles,
+ XRFdc_MTS_Marker *MarkersPtr, int Marker_Delay);
+static void XRFdc_MTS_Marker_Read(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 FIFO_Id, u32 *CountPtr, u32 *LocPtr, u32 *DonePtr);
+static u32 XRFdc_MTS_Latency(XRFdc *InstancePtr, u32 Type,
+ XRFdc_MultiConverter_Sync_Config *ConfigPtr, XRFdc_MTS_Marker *MarkersPtr);
+
+/*****************************************************************************/
+/**
+*
+* This API enables the master tile sysref Tx/Rx
+*
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Enable the master tile sysref for Tx/Rx, valid values are 0 and 1.
+*
+* @return
+* - None.
+*
+* @note None
+*
+******************************************************************************/
+static void XRFdc_MTS_Sysref_TRx(XRFdc *InstancePtr, u32 Enable)
+{
+ u32 BaseAddr;
+ u32 Data;
+
+ BaseAddr = XRFDC_DRP_BASE(XRFDC_DAC_TILE, 0) + XRFDC_HSCOM_ADDR;
+ Data = (Enable != 0U) ? 0xFFFFU : 0U;
+
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MTS_SRCAP_T1,
+ XRFDC_MTS_SRCAP_EN_TRX_M, Data);
+}
+
+/*****************************************************************************/
+/**
+*
+* This API Control SysRef Capture Settings
+*
+*
+* @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 Is_PLL Valid values are 0 and 1.
+* @param Enable_Cap Valid values are 0 and 1.
+* @param Enable_Div_Reset Valid values are 0 and 1.
+*
+* @return
+* - None.
+*
+* @note None
+*
+******************************************************************************/
+static void XRFdc_MTS_Sysref_Ctrl(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Is_PLL, u32 Enable_Cap, u32 Enable_Div_Reset)
+{
+ u32 BaseAddr;
+ u16 RegData;
+
+ RegData = 0U;
+ BaseAddr = XRFDC_DRP_BASE(Type, Tile_Id) + XRFDC_HSCOM_ADDR;
+
+ /* Write some bits to ensure sysref is in the right mode */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MTS_SRCAP_T1,
+ XRFDC_MTS_SRCAP_INIT_M, 0U);
+
+ if (Is_PLL != 0U) {
+ /* PLL Cap */
+ RegData = (Enable_Cap != 0U) ? XRFDC_MTS_SRCAP_PLL_M : 0U;
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MTS_SRCAP_PLL,
+ XRFDC_MTS_SRCAP_PLL_M, RegData);
+ } else {
+ /* Analog Cap disable */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MTS_SRCAP_T1,
+ XRFDC_MTS_SRCAP_T1_EN, 0U);
+
+ /* Analog Divider */
+ RegData = (Enable_Div_Reset != 0U) ? 0U : XRFDC_MTS_SRCAP_T1_RST;
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MTS_SRCAP_T1,
+ XRFDC_MTS_SRCAP_T1_RST, RegData);
+
+ /* Digital Divider */
+ RegData = (Enable_Div_Reset != 0U) ? 0U : XRFDC_MTS_SRCAP_DIG_M;
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MTS_SRCAP_DIG,
+ XRFDC_MTS_SRCAP_DIG_M, RegData);
+
+ /* Set SysRef Cap Clear */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MTS_SRCAP_T1,
+ XRFDC_MTS_SRCLR_T1_M, XRFDC_MTS_SRCLR_T1_M);
+
+ /* Analog Cap enable */
+ RegData = (Enable_Cap != 0U) ? XRFDC_MTS_SRCAP_T1_EN : 0U;
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MTS_SRCAP_T1,
+ XRFDC_MTS_SRCAP_T1_EN, RegData);
+
+ /* Unset SysRef Cap Clear */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MTS_SRCAP_T1,
+ XRFDC_MTS_SRCLR_T1_M, 0U);
+ }
+}
+
+/*****************************************************************************/
+/**
+*
+* This API Update SysRef Distribution between tiles
+*
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Num_DAC is number of DAC tiles
+*
+* @return
+* - XRFDC_MTS_OK if successful.
+* - XRFDC_MTS_NOT_SUPPORTED
+*
+* @note None
+*
+******************************************************************************/
+static u32 XRFdc_MTS_Sysref_Dist(XRFdc *InstancePtr, int Num_DAC)
+{
+
+ if (Num_DAC < 0) {
+ /* Auto-detect. Only 2 types Supported - 2GSPS ADCs, 4GSPS ADCs */
+ if (XRFdc_IsHighSpeedADC(InstancePtr,0) != 0U) {
+ Num_DAC = 2;
+ } else {
+ Num_DAC = 4;
+ }
+ }
+
+ if (Num_DAC == XRFDC_NUM_OF_TILES2) {
+ /* 2 DACs, 4ADCs */
+ XRFdc_WriteReg16(InstancePtr, XRFDC_DAC_TILE_DRP_ADDR(0U),
+ XRFDC_MTS_SRDIST, 0xC980U);
+ XRFdc_WriteReg16(InstancePtr, XRFDC_DAC_TILE_DRP_ADDR(1U),
+ XRFDC_MTS_SRDIST, 0x0100U);
+ XRFdc_WriteReg16(InstancePtr, XRFDC_ADC_TILE_DRP_ADDR(3U),
+ XRFDC_MTS_SRDIST, 0x1700U);
+ } else if (Num_DAC == XRFDC_NUM_OF_TILES4) {
+ /* 4 DACs, 4ADCs */
+ XRFdc_WriteReg16(InstancePtr, XRFDC_DAC_TILE_DRP_ADDR(0U),
+ XRFDC_MTS_SRDIST, 0xCA80U);
+ XRFdc_WriteReg16(InstancePtr, XRFDC_DAC_TILE_DRP_ADDR(1U),
+ XRFDC_MTS_SRDIST, 0x2400U);
+ XRFdc_WriteReg16(InstancePtr, XRFDC_DAC_TILE_DRP_ADDR(2U),
+ XRFDC_MTS_SRDIST, 0x0980U);
+ XRFdc_WriteReg16(InstancePtr, XRFDC_DAC_TILE_DRP_ADDR(3U),
+ XRFDC_MTS_SRDIST, 0x0100U);
+ XRFdc_WriteReg16(InstancePtr, XRFDC_ADC_TILE_DRP_ADDR(3U),
+ XRFDC_MTS_SRDIST, 0x0700U);
+ } else {
+ return XRFDC_MTS_NOT_SUPPORTED;
+ }
+
+ XRFdc_WriteReg16(InstancePtr, XRFDC_ADC_TILE_DRP_ADDR(0U),
+ XRFDC_MTS_SRDIST, 0x0280U);
+ XRFdc_WriteReg16(InstancePtr, XRFDC_ADC_TILE_DRP_ADDR(1U),
+ XRFDC_MTS_SRDIST, 0x0600U);
+ XRFdc_WriteReg16(InstancePtr, XRFDC_ADC_TILE_DRP_ADDR(2U),
+ XRFDC_MTS_SRDIST, 0x8880U);
+
+ return XRFDC_MTS_OK;
+}
+
+/*****************************************************************************/
+/**
+*
+* This API Wait for a number of sysref's to be captured
+*
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Count_Val to wait for a number of sysref's to be captured.
+*
+* @return
+* - XRFDC_MTS_OK if successful.
+* - XRFDC_MTS_TIMEOUT if timeout occurs.
+*
+* @note None
+*
+******************************************************************************/
+static u32 XRFdc_MTS_Sysref_Count(XRFdc *InstancePtr, u32 Type, u32 Count_Val)
+{
+ u32 RegData;
+ u32 Timeout;
+ u32 Shift;
+
+ RegData = (Type == XRFDC_DAC_TILE) ? 0x2U : 0x1U;
+ Shift = (Type == XRFDC_DAC_TILE) ? 8U : 0U;
+
+ /* Start counter */
+ XRFdc_WriteReg(InstancePtr, 0U, XRFDC_MTS_SRCOUNT_CTRL, RegData);
+
+ /* Check counter with timeout in case sysref is not active */
+ Timeout = 0U;
+ while (Timeout < XRFDC_MTS_SRCOUNT_TIMEOUT) {
+ RegData = XRFdc_ReadReg(InstancePtr, 0U, XRFDC_MTS_SRCOUNT_VAL);
+ RegData = ((RegData >> Shift) & XRFDC_MTS_SRCOUNT_M);
+ if (RegData >= Count_Val) {
+ break;
+ }
+ Timeout++;
+ }
+
+ if (Timeout >= XRFDC_MTS_SRCOUNT_TIMEOUT) {
+ metal_log(METAL_LOG_ERROR,
+ "PL SysRef Timeout - PL SysRef not active: %d\n in %s\n",
+ Timeout, __func__);
+ return XRFDC_MTS_TIMEOUT;
+ }
+
+ return XRFDC_MTS_OK;
+}
+
+/*****************************************************************************/
+/**
+*
+* This API print the DTC scan results
+*
+*
+* @param FlagsPtr is for internal usage.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3.
+* @param Target is for internal usage.
+* @param Picked is for internal usage.
+*
+* @return None
+*
+* @note None
+*
+******************************************************************************/
+static void XRFdc_MTS_Dtc_Flag_Debug(u8 *FlagsPtr, u32 Type, u32 Tile_Id,
+ u32 Target, u32 Picked)
+{
+ u32 Index;
+ char buf[XRFDC_MTS_NUM_DTC+1];
+
+ for (Index = 0U; Index < XRFDC_MTS_NUM_DTC; Index++) {
+ if (Index == Picked) {
+ buf[Index] = '*';
+ } else if (Index == Target) {
+ buf[Index] = '#';
+ } else {
+ buf[Index] = '0' + FlagsPtr[Index];
+ }
+ }
+ buf[XRFDC_MTS_NUM_DTC] = '\0';
+ metal_log(METAL_LOG_INFO, "%s%d: %s\n",
+ (Type == XRFDC_DAC_TILE) ? "DAC" : "ADC", Tile_Id, buf);
+
+ (void)buf;
+ (void)Type;
+ (void)Tile_Id;
+
+}
+
+/*****************************************************************************/
+/**
+*
+* This API Calculate the best DTC code to use
+*
+*
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3.
+* @param SettingsPtr dtc settings structure.
+* @param FlagsPtr is for internal usage.
+*
+* @return
+* - XRFDC_MTS_OK if successful.
+* - XRFDC_MTS_NOT_SUPPORTED if MTS is not supported.
+*
+* @note None
+*
+******************************************************************************/
+static u32 XRFdc_MTS_Dtc_Calc(u32 Type, u32 Tile_Id,
+ XRFdc_MTS_DTC_Settings *SettingsPtr, u8 *FlagsPtr)
+{
+ u32 Index, Status, Num_Found;
+ int Last, Current_Gap, Max_Overlap, Overlap_Cnt;
+ int Min_Gap, Max_Gap, Diff, Min_Diff, Min_Range, Val, Target;
+ u8 Min_Gap_Allowed;
+ int Codes[XRFDC_MTS_MAX_CODE] = {0};
+
+ Min_Gap_Allowed = (SettingsPtr->IsPLL != 0U) ? XRFDC_MTS_MIN_GAP_PLL :
+ XRFDC_MTS_MIN_GAP_T1;
+ Status = XRFDC_MTS_OK;
+
+ /* Scan the flags and find candidate DTC codes */
+ Num_Found = 0U;
+ Max_Gap = 0;
+ Min_Gap = XRFDC_MTS_NUM_DTC;
+ Max_Overlap = 0;
+ Overlap_Cnt = 0;
+ Last = -1;
+ FlagsPtr[XRFDC_MTS_NUM_DTC] = 1;
+ for (Index = 0U; Index <= XRFDC_MTS_NUM_DTC; Index++) {
+ Current_Gap = Index-Last;
+ if (FlagsPtr[Index] != 0) {
+ if (Current_Gap > Min_Gap_Allowed) {
+ Codes[Num_Found] = Last + (Current_Gap / 2);
+ Num_Found++;
+ /* Record max/min gaps */
+ Current_Gap--;
+ if (Current_Gap > Max_Gap) {
+ Max_Gap = Current_Gap;
+ }
+ if (Current_Gap < Min_Gap) {
+ Min_Gap = Current_Gap;
+ }
+ }
+ Last = Index;
+ }
+ /* check for the longest run of overlapping codes */
+ if (FlagsPtr[Index] == 3U) {
+ Overlap_Cnt++;
+ if (Overlap_Cnt > Max_Overlap) {
+ Max_Overlap = Overlap_Cnt;
+ }
+ } else {
+ Overlap_Cnt = 0;
+ }
+ }
+
+ /* Record some stats */
+ SettingsPtr->Num_Windows[Tile_Id] = Num_Found;
+ SettingsPtr->Max_Gap[Tile_Id] = Max_Gap;
+ SettingsPtr->Min_Gap[Tile_Id] = Min_Gap;
+ SettingsPtr->Max_Overlap[Tile_Id] = Max_Overlap;
+
+ /* Calculate the best code */
+ if (SettingsPtr->Scan_Mode == XRFDC_MTS_SCAN_INIT) {
+ /* Initial scan */
+ if (Tile_Id == SettingsPtr->RefTile) {
+ /* RefTile: Get the code closest to the target */
+ Target = XRFDC_MTS_REF_TARGET;
+ SettingsPtr->Target[Tile_Id] = XRFDC_MTS_REF_TARGET;
+ Min_Diff = XRFDC_MTS_NUM_DTC;
+ /* scan all codes to find the closest */
+ for (Index = 0U; Index < Num_Found; Index++) {
+ Diff = abs(Target - Codes[Index]);
+ if (Diff < Min_Diff) {
+ Min_Diff = Diff;
+ SettingsPtr->DTC_Code[Tile_Id] = Codes[Index];
+ }
+ metal_log(METAL_LOG_DEBUG,
+ "Target %d, DTC Code %d, Diff %d, Min %d\n", Target,
+ Codes[Index], Diff, Min_Diff);
+ }
+ /* set the reference code as the target for the other tiles */
+ for (Index = 0U; Index < 4U; Index++) {
+ if (Index != Tile_Id) {
+ SettingsPtr->Target[Index] = SettingsPtr->DTC_Code[Tile_Id];
+ }
+ }
+ metal_log(METAL_LOG_DEBUG,
+ "RefTile (%d): DTC Code Target %d, Picked %d\n", Tile_Id,
+ Target, SettingsPtr->DTC_Code[Tile_Id]);
+
+ } else {
+ /*
+ * Other Tiles: Get the code that minimises the total range of codes
+ * compute the range of the existing dtc codes
+ */
+ Max_Gap = 0;
+ Min_Gap = XRFDC_MTS_NUM_DTC;
+ for (Index = XRFDC_TILE_ID0; Index < XRFDC_TILE_ID4; Index++) {
+ Val = SettingsPtr->DTC_Code[Index];
+ if ((Val != -1) && (Val > Max_Gap)) {
+ Max_Gap = Val;
+ }
+ if ((Val != -1) && (Val < Min_Gap)) {
+ Min_Gap = Val;
+ }
+ }
+ metal_log(METAL_LOG_DEBUG,
+ "Tile (%d): Max/Min %d/%d, Range %d\n", Tile_Id, Max_Gap,
+ Min_Gap, Max_Gap-Min_Gap);
+ Min_Range = XRFDC_MTS_NUM_DTC;
+ for (Index = 0U; Index < Num_Found; Index++) {
+ Val = Codes[Index];
+ Diff = Max_Gap - Min_Gap;
+ if (Val < Min_Gap) {
+ Diff = Max_Gap - Val;
+ }
+ if (Val > Max_Gap) {
+ Diff = Val - Min_Gap;
+ }
+ if (Diff <= Min_Range) {
+ Min_Range = Diff;
+ SettingsPtr->DTC_Code[Tile_Id] = Val;
+ }
+ metal_log(METAL_LOG_DEBUG,
+ "Tile (%d): Code %d, New-Range: %d, Min-Range: %d\n",
+ Tile_Id, Val, Diff, Min_Range);
+ }
+ metal_log(METAL_LOG_DEBUG,
+ "Tile (%d): Code %d, Range Prev %d, New %d\n", Tile_Id,
+ SettingsPtr->DTC_Code[Tile_Id], Max_Gap-Min_Gap, Min_Range);
+ }
+ } else {
+ /* Reload the results of an initial scan to seed a new scan */
+ if (Tile_Id == SettingsPtr->RefTile) {
+ /* RefTile: Get code closest to the target */
+ Target = SettingsPtr->Target[Tile_Id];
+ } else {
+ Target = SettingsPtr->DTC_Code[SettingsPtr->RefTile] +
+ SettingsPtr->Target[Tile_Id] - SettingsPtr->Target[SettingsPtr->RefTile];
+ }
+ Min_Diff = XRFDC_MTS_NUM_DTC;
+ /* scan all codes to find the closest */
+ for (Index = 0U; Index < Num_Found; Index++) {
+ Diff = abs(Target - Codes[Index]);
+ if (Diff < Min_Diff) {
+ Min_Diff = Diff;
+ SettingsPtr->DTC_Code[Tile_Id] = Codes[Index];
+ }
+ metal_log(METAL_LOG_DEBUG,
+ "Reload Target %d, DTC Code %d, Diff %d, Min %d\n", Target,
+ Codes[Index], Diff, Min_Diff);
+ }
+ }
+
+ /* Print some debug info */
+ XRFdc_MTS_Dtc_Flag_Debug(FlagsPtr, Type, Tile_Id, SettingsPtr->Target[Tile_Id],
+ SettingsPtr->DTC_Code[Tile_Id]);
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This API Set a DTC code and wait for it to be updated. Return early/late
+* flags, if set
+*
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param BaseAddr is for internal usage.
+* @param SRCtrlAddr is for internal usage.
+* @param DTCAddr is for internal usage.
+* @param SRctl is for internal usage.
+* @param SRclr_m is for internal usage.
+* @param Code is for internal usage.
+*
+* @return
+* - XRFDC_MTS_OK if successful.
+* - XRFDC_MTS_TIMEOUT if timeout occurs.
+*
+* @note None
+*
+******************************************************************************/
+static u32 XRFdc_MTS_Dtc_Code(XRFdc *InstancePtr, u32 Type, u32 BaseAddr,
+ u32 SRCtrlAddr, u32 DTCAddr, u16 SRctl, u16 SRclr_m, u32 Code)
+{
+ u32 Status;
+
+ /* set the DTC code */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, DTCAddr, Code);
+
+ /* set sysref cap clear */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, SRCtrlAddr, SRctl | SRclr_m);
+
+ /* unset sysref cap clear */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, SRCtrlAddr, SRctl);
+
+ Status = XRFdc_MTS_Sysref_Count(InstancePtr, Type, XRFDC_MTS_DTC_COUNT);
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This API Scan the DTC codes and determine the optimal capture code for
+* both PLL and T1 cases
+*
+*
+* @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 SettingsPtr dtc settings structure.
+*
+* @return
+* - XRFDC_MTS_OK if successful.
+* - XRFDC_MTS_TIMEOUT if timeout occurs.
+*
+* @note None
+*
+******************************************************************************/
+static u32 XRFdc_MTS_Dtc_Scan (XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ XRFdc_MTS_DTC_Settings *SettingsPtr)
+{
+ u32 Status;
+ u32 BaseAddr;
+ u32 SRCtrlAddr;
+ u32 DTCAddr;
+ u8 Flags[XRFDC_MTS_NUM_DTC+1];
+ u16 SRctl;
+ u16 SRclr_m;
+ u16 Flag_s;
+ u32 Index;
+
+ BaseAddr = XRFDC_DRP_BASE(Type, Tile_Id) + XRFDC_HSCOM_ADDR;
+ Status = XRFDC_MTS_OK;
+
+ /* Enable SysRef Capture and Disable Divide Reset */
+ XRFdc_MTS_Sysref_Ctrl(InstancePtr, Type, Tile_Id, SettingsPtr->IsPLL, 1, 0);
+ SRCtrlAddr = (SettingsPtr->IsPLL != 0U) ? XRFDC_MTS_SRCAP_PLL : XRFDC_MTS_SRCAP_T1;
+ DTCAddr = (SettingsPtr->IsPLL != 0U) ? XRFDC_MTS_SRDTC_PLL : XRFDC_MTS_SRDTC_T1;
+ SRclr_m = (SettingsPtr->IsPLL != 0U) ? XRFDC_MTS_SRCLR_PLL_M : XRFDC_MTS_SRCLR_T1_M;
+ Flag_s = (SettingsPtr->IsPLL != 0U) ? XRFDC_MTS_SRFLAG_PLL : XRFDC_MTS_SRFLAG_T1;
+
+ SRctl = XRFdc_ReadReg16(InstancePtr, BaseAddr, SRCtrlAddr) & ~SRclr_m;
+
+ for (Index = 0U; Index < XRFDC_MTS_NUM_DTC; Index++) {
+ Flags[Index] = 0U;
+ }
+ for (Index = 0U; (Index < XRFDC_MTS_NUM_DTC) && (Status == XRFDC_MTS_OK); Index++) {
+ Status |= XRFdc_MTS_Dtc_Code(InstancePtr, Type, BaseAddr,
+ SRCtrlAddr, DTCAddr, SRctl, SRclr_m, Index);
+ Flags[Index] = (XRFdc_ReadReg16(InstancePtr, BaseAddr, XRFDC_MTS_SRFLAG) >>
+ Flag_s) & 0x3U;
+ }
+
+ /* Calculate the best DTC code */
+ (void)XRFdc_MTS_Dtc_Calc(Type, Tile_Id, SettingsPtr, Flags);
+
+ /* Program the calculated code */
+ if (SettingsPtr->DTC_Code[Tile_Id] == -1) {
+ metal_log(METAL_LOG_ERROR,
+ "Unable to capture analog SysRef safely on %s tile %d\n"
+ , (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC", Tile_Id);
+ Status |= XRFDC_MTS_DTC_INVALID;
+ } else {
+ (void)XRFdc_MTS_Dtc_Code(InstancePtr, Type, BaseAddr, SRCtrlAddr, DTCAddr,
+ SRctl, SRclr_m, SettingsPtr->DTC_Code[Tile_Id]);
+ }
+
+ if (SettingsPtr->IsPLL != 0U) {
+ /* PLL - Disable SysRef Capture */
+ XRFdc_MTS_Sysref_Ctrl(InstancePtr, Type, Tile_Id, 1, 0, 0);
+ } else {
+ /* T1 - Reset Dividers */
+ XRFdc_MTS_Sysref_Ctrl(InstancePtr, Type, Tile_Id, 0, 1, 1);
+ Status |= XRFdc_MTS_Sysref_Count(InstancePtr, Type,
+ XRFDC_MTS_DTC_COUNT);
+ XRFdc_MTS_Sysref_Ctrl(InstancePtr, Type, Tile_Id, 0, 1, 0);
+ }
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This API Control the FIFO enable for the group. If Tiles_to_clear has bits
+* set, the FIFOs of those tiles will have their FIFO flags cleared.
+*
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param FIFO_Mode is fifo mode.
+* @param Tiles_To_Clear bits set, FIFO flags will be cleared for those tiles.
+*
+* @return None
+*
+* @note None
+*
+******************************************************************************/
+static void XRFdc_MTS_FIFOCtrl (XRFdc *InstancePtr, u32 Type, u32 FIFO_Mode,
+ u32 Tiles_To_Clear)
+{
+ u32 RegAddr;
+ u32 BaseAddr;
+ u32 Tile_Id;
+ u32 Block_Id;
+
+ /* Clear the FIFO Flags */
+ RegAddr = (Type == XRFDC_ADC_TILE) ? XRFDC_ADC_FABRIC_ISR_OFFSET :
+ XRFDC_DAC_FABRIC_ISR_OFFSET;
+ for (Tile_Id = XRFDC_TILE_ID0; Tile_Id < XRFDC_TILE_ID4; Tile_Id++) {
+ if (((1U << Tile_Id) & Tiles_To_Clear) != 0U) {
+ for (Block_Id = XRFDC_BLK_ID0; Block_Id < XRFDC_BLK_ID4; Block_Id++) {
+ BaseAddr = XRFDC_DRP_BASE(Type, Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(Block_Id);
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, RegAddr,
+ XRFDC_IXR_FIFOUSRDAT_MASK);
+ }
+ }
+ }
+
+ /* Enable the FIFOs */
+ RegAddr = (Type == XRFDC_ADC_TILE) ? XRFDC_MTS_FIFO_CTRL_ADC :
+ XRFDC_MTS_FIFO_CTRL_DAC;
+ XRFdc_WriteReg(InstancePtr, 0, RegAddr, FIFO_Mode);
+}
+
+/*****************************************************************************/
+/**
+*
+* This API Read-back the marker data for an 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.
+* @param FIFO_Id is FIFO number.
+* @param Count is for internal usage.
+* @param Loc is for internal usage.
+* @param Done is for internal usage.
+*
+* @return
+* - None.
+*
+* @note None
+*
+******************************************************************************/
+static void XRFdc_MTS_Marker_Read(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 FIFO_Id, u32 *CountPtr, u32 *LocPtr, u32 *DonePtr)
+{
+ u32 BaseAddr;
+ u32 RegData = 0x0;
+
+ if (Type == XRFDC_ADC_TILE) {
+ BaseAddr = XRFDC_DRP_BASE(Type, Tile_Id) - 0x2000;
+ RegData = XRFdc_ReadReg(InstancePtr, BaseAddr,
+ XRFDC_MTS_ADC_MARKER_CNT+(FIFO_Id << 2));
+ *CountPtr = XRFDC_MTS_FIELD(RegData, XRFDC_MTS_AMARK_CNT_M, 0);
+ *LocPtr = XRFDC_MTS_FIELD(RegData, XRFDC_MTS_AMARK_LOC_M,
+ XRFDC_MTS_AMARK_LOC_S);
+ *DonePtr = XRFDC_MTS_FIELD(RegData, XRFDC_MTS_AMARK_DONE_M,
+ XRFDC_MTS_AMARK_DONE_S);
+ } else {
+ BaseAddr = XRFDC_DRP_BASE(Type, Tile_Id) +
+ XRFDC_BLOCK_ADDR_OFFSET(FIFO_Id);
+ *CountPtr = XRFdc_ReadReg(InstancePtr, BaseAddr,
+ XRFDC_MTS_DAC_MARKER_CNT);
+ *LocPtr = XRFdc_ReadReg(InstancePtr, BaseAddr,
+ XRFDC_MTS_DAC_MARKER_LOC);
+ *DonePtr = 1;
+ }
+ metal_log(METAL_LOG_DEBUG,
+ "Marker Read Tile %d, FIFO %d - %08X = %04X: count=%d, loc=%d,"
+ "done=%d\n", Tile_Id, FIFO_Id, BaseAddr, RegData, *CountPtr,
+ *LocPtr, *DonePtr);
+}
+
+/*****************************************************************************/
+/**
+*
+* This API Run the marker counter and read the results
+*
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tiles is tiles to get marker
+* @param MarkersPtr mts marker structure.
+* @param Marker_Delay is marker delay.
+*
+* @return
+* - XRFDC_MTS_OK if successful.
+* - XRFDC_MTS_TIMEOUT if timeout occurs.
+* - XRFDC_MTS_MARKER_RUN
+* - XRFDC_MTS_MARKER_MISM
+* -
+*
+* @note None
+*
+******************************************************************************/
+static u32 XRFdc_MTS_GetMarker(XRFdc *InstancePtr, u32 Type, u32 Tiles,
+ XRFdc_MTS_Marker *MarkersPtr, int Marker_Delay)
+{
+ u32 Done;
+ u32 Count;
+ u32 Loc;
+ u32 Tile_Id;
+ u32 Block_Id;
+ u32 Status;
+
+ Status = XRFDC_MTS_OK;
+ if (Type == XRFDC_ADC_TILE) {
+ /* Reset marker counter */
+ XRFdc_WriteReg(InstancePtr, 0, XRFDC_MTS_ADC_MARKER, 1);
+ XRFdc_WriteReg(InstancePtr, 0, XRFDC_MTS_ADC_MARKER, 0);
+ } else {
+ /*
+ * SysRef Capture should be still active from the DTC Scan
+ * but set it anyway to be sure
+ */
+ for (Tile_Id = XRFDC_TILE_ID0; Tile_Id < XRFDC_TILE_ID4; Tile_Id++) {
+ if (((1U << Tile_Id) & Tiles) != 0U) {
+ XRFdc_MTS_Sysref_Ctrl(InstancePtr, XRFDC_DAC_TILE,
+ Tile_Id, 0, 1, 0);
+ }
+ }
+
+ /* Set marker delay */
+ XRFdc_WriteReg(InstancePtr, 0, XRFDC_MTS_DAC_MARKER_CTRL,
+ Marker_Delay);
+ }
+
+ /* Allow the marker counter to run */
+ Status |= XRFdc_MTS_Sysref_Count(InstancePtr, Type,
+ XRFDC_MTS_MARKER_COUNT);
+
+ /* Read master FIFO (FIFO0 in each Tile) */
+ for (Tile_Id = XRFDC_TILE_ID0; Tile_Id < XRFDC_TILE_ID4; Tile_Id++) {
+ if (((1U << Tile_Id) & Tiles) != 0U) {
+ if (Type == XRFDC_DAC_TILE) {
+ /* Disable SysRef Capture before reading it */
+ XRFdc_MTS_Sysref_Ctrl(InstancePtr, XRFDC_DAC_TILE,
+ Tile_Id, 0, 0, 0);
+ Status |= XRFdc_MTS_Sysref_Count(InstancePtr, Type,
+ XRFDC_MTS_MARKER_COUNT);
+ }
+
+ XRFdc_MTS_Marker_Read(InstancePtr, Type, Tile_Id, 0, &Count,
+ &Loc, &Done);
+ MarkersPtr->Count[Tile_Id] = Count;
+ MarkersPtr->Loc[Tile_Id] = Loc;
+ metal_log(METAL_LOG_INFO,
+ "%s%d: Marker: - %d, %d\n", (Type == XRFDC_DAC_TILE) ?
+ "DAC":"ADC", Tile_Id, MarkersPtr->Count[Tile_Id], MarkersPtr->Loc[Tile_Id]);
+
+ if ((!Done) != 0U) {
+ metal_log(METAL_LOG_ERROR, "Analog SysRef timeout,"
+ "SysRef not detected on %s tile %d\n",
+ (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC", Tile_Id);
+ Status |= XRFDC_MTS_MARKER_RUN;
+ }
+
+ /*
+ * Check all enabled FIFOs agree with the master FIFO.
+ * This is optional.
+ */
+ for (Block_Id = XRFDC_BLK_ID0; Block_Id < XRFDC_BLK_ID4; Block_Id++) {
+ if (XRFdc_IsFifoEnabled(InstancePtr, Type, Tile_Id, Block_Id) != 0U) {
+ XRFdc_MTS_Marker_Read(InstancePtr, Type, Tile_Id, Block_Id,
+ &Count, &Loc, &Done);
+ if ((MarkersPtr->Count[Tile_Id] != Count) ||
+ (MarkersPtr->Loc[Tile_Id] != Loc)) {
+ metal_log(METAL_LOG_DEBUG,
+ "Tile %d, FIFO %d Marker != Expected: %d, %d vs"
+ "%d, %d\n", Tile_Id, Block_Id, MarkersPtr->Count[Tile_Id],
+ MarkersPtr->Loc[Tile_Id], Count, Loc);
+ metal_log(METAL_LOG_ERROR,
+ "SysRef capture mismatch on %s tile %d,"
+ " PL SysRef may not have been"
+ " captured synchronously\n",
+ (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC", Block_Id);
+ Status |= XRFDC_MTS_MARKER_MISM;
+
+ }
+ }
+ }
+ }
+ }
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This API Calculate the absoulte/relative latencies
+*
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param ConfigPtr is mts config structure.
+* @param MarkersPtr is mts marker structure.
+*
+* @return
+* - XRFDC_MTS_OK if successful.
+* - XRFDC_MTS_DELAY_OVER
+* - XRFDC_MTS_TARGET_LOW
+* -
+*
+* @note Latency calculation will use Sysref frequency counters
+* logic which will work with IP version 2.0.1 and above.
+*
+******************************************************************************/
+static u32 XRFdc_MTS_Latency(XRFdc *InstancePtr, u32 Type,
+ XRFdc_MultiConverter_Sync_Config *ConfigPtr, XRFdc_MTS_Marker *MarkersPtr)
+{
+ u32 Status, Fifo, Index, BaseAddr, RegAddr;
+ int Count_W, Loc_W, Latency, Offset, Max_Latency, Target, Delta;
+ int I_Part, F_Part, SysRefT1Period, LatencyDiff, LatencyOffset;
+ u32 RegData, SysRefFreqCntrDone;
+ int Target_Latency = -1;
+ int LatencyOffsetDiff;
+ u32 Factor = 1U;
+ u32 Write_Words = 0U;
+ u32 Read_Words = 1U;
+
+ Status = XRFDC_MTS_OK;
+ if (Type == XRFDC_ADC_TILE) {
+ (void)XRFdc_GetDecimationFactor(InstancePtr, ConfigPtr->RefTile, 0, &Factor);
+ } else {
+ (void)XRFdc_GetInterpolationFactor(InstancePtr, ConfigPtr->RefTile, 0, &Factor);
+ (void)XRFdc_GetFabWrVldWords(InstancePtr, Type, ConfigPtr->RefTile, 0, &Write_Words);
+ }
+ (void)XRFdc_GetFabRdVldWords(InstancePtr, Type, ConfigPtr->RefTile, 0, &Read_Words);
+ Count_W = Read_Words * Factor;
+ Loc_W = Factor;
+
+ metal_log(METAL_LOG_DEBUG,
+ "Count_W %d, loc_W %d\n", Count_W, Loc_W);
+
+ /* Find the individual latencies */
+ Max_Latency = 0;
+
+ /* Determine relative SysRef frequency */
+ RegData = XRFdc_ReadReg(InstancePtr, 0, XRFDC_MTS_SRFREQ_VAL);
+ if (Type == XRFDC_ADC_TILE) {
+ /* ADC SysRef frequency information contained in lower 16 bits */
+ RegData = RegData & 0XFFFFU;
+ } else {
+ /* DAC SysRef frequency information contained in upper 16 bits */
+ RegData = (RegData >> 16U) & 0XFFFFU;
+ }
+
+ /*
+ * Ensure SysRef frequency counter has completed.
+ * Sysref frequency counters logic will work with IP version
+ * 2.0.1 and above.
+ */
+ SysRefFreqCntrDone = RegData & 0x1U;
+ if (SysRefFreqCntrDone == 0U) {
+ metal_log(METAL_LOG_ERROR, "Error : %s SysRef frequency counter not yet done\n",
+ (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC");
+ Status |= XRFDC_MTS_SYSREF_FREQ_NDONE;
+ /* Set SysRef period in terms of T1's will not be used */
+ SysRefT1Period = 0;
+ } else {
+ SysRefT1Period = (RegData >> 1) * Count_W;
+ if (Type == XRFDC_DAC_TILE) {
+ /*
+ * DAC marker counter is on the tile clock domain so need
+ * to update SysRef period accordingly
+ */
+ SysRefT1Period = (SysRefT1Period * Write_Words) / Read_Words;
+ }
+ metal_log(METAL_LOG_INFO, "SysRef period in terms of %s T1s = %d\n",
+ (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC", SysRefT1Period);
+ }
+
+ /* Work out the latencies */
+ for (Index = XRFDC_TILE_ID0; Index < XRFDC_TILE_ID4; Index++) {
+ if (((1U << Index) & ConfigPtr->Tiles) != 0U) {
+ Latency = (MarkersPtr->Count[Index] * Count_W) + (MarkersPtr->Loc[Index] * Loc_W);
+ /* Set marker counter target on first tile */
+ if (Target_Latency < 0) {
+ Target_Latency = ConfigPtr->Target_Latency;
+ if (Target_Latency < 0) {
+ Target_Latency = Latency;
+ }
+ metal_log(METAL_LOG_INFO, "%s target latency = %d\n",
+ (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC", Target_Latency);
+ }
+
+ /*
+ * Adjust reported counter values if offsetting by a SysRef
+ * period reduces distance between current and target latencies
+ */
+ LatencyDiff = Target_Latency - Latency;
+ LatencyOffset = (LatencyDiff > 0) ? (Latency + SysRefT1Period) :
+ (Latency - SysRefT1Period);
+ LatencyOffsetDiff = Target_Latency - LatencyOffset;
+ if (abs(LatencyDiff) > abs(LatencyOffsetDiff)) {
+ Latency = LatencyOffset;
+ metal_log(METAL_LOG_INFO, "%s%d latency offset by a SysRef period to %d\n",
+ (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC", Index, Latency);
+ }
+ ConfigPtr->Latency[Index] = Latency;
+ if (Latency > Max_Latency) {
+ Max_Latency = Latency;
+ }
+ metal_log(METAL_LOG_DEBUG, "Tile %d, latency %d, max %d\n",
+ Index, Latency, Max_Latency);
+ }
+ }
+
+ /*
+ * Adjust the latencies to meet the target. Choose max, if it
+ * is not supplied by the user.
+ */
+ Target = (ConfigPtr->Target_Latency < 0) ? Max_Latency :
+ ConfigPtr->Target_Latency;
+
+ if (Target < Max_Latency) {
+ /* Cannot correct for -ve latencies, so default to aligning */
+ Target = Max_Latency;
+ metal_log(METAL_LOG_ERROR, "Error : %s alignment target latency of %d < minimum possible %d\n",
+ (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC", Target, Max_Latency);
+ Status |= XRFDC_MTS_TARGET_LOW;
+ }
+
+ for (Index = XRFDC_TILE_ID0; Index < XRFDC_TILE_ID4; Index++) {
+ if (((1U << Index) & ConfigPtr->Tiles) != 0U) {
+ Delta = Target - ConfigPtr->Latency[Index];
+ if (Delta < 0) {
+ Delta = 0;
+ }
+ I_Part = Delta / Factor;
+ F_Part = Delta % Factor;
+ Offset = I_Part;
+ if (F_Part > (int)(Factor / 2U)) {
+ Offset++;
+ }
+ metal_log(METAL_LOG_DEBUG,
+ "Target %d, Tile %d, delta %d, i/f_part %d/%d, offset %d\n",
+ Target, Index, Delta, I_Part, F_Part, Offset * Factor);
+
+ /* check for excessive delay correction values */
+ if (Offset > (int)XRFDC_MTS_DELAY_MAX) {
+ Offset = (int)XRFDC_MTS_DELAY_MAX;
+ metal_log(METAL_LOG_ERROR,
+ "Alignment correction delay %d"
+ " required exceeds maximum for %s Tile %d\n",
+ Offset, (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC",
+ XRFDC_MTS_DELAY_MAX, Index);
+ Status |= XRFDC_MTS_DELAY_OVER;
+ }
+
+ /* Adjust the latency, write the same value to each FIFO */
+ BaseAddr = XRFDC_DRP_BASE(Type, Index) - 0x2000;
+ for (Fifo = XRFDC_BLK_ID0; Fifo < XRFDC_BLK_ID4; Fifo++) {
+ RegAddr = XRFDC_MTS_DELAY_CTRL + (Fifo << 2);
+ RegData = XRFdc_ReadReg(InstancePtr, BaseAddr, RegAddr);
+ RegData = XRFDC_MTS_RMW(RegData, XRFDC_MTS_DELAY_VAL_M,
+ Offset);
+ XRFdc_WriteReg(InstancePtr, BaseAddr, RegAddr, RegData);
+ }
+
+ /* Report the total latency for this tile */
+ ConfigPtr->Latency[Index] = ConfigPtr->Latency[Index] + (Offset * Factor);
+ ConfigPtr->Offset[Index] = Offset;
+
+ /* Set the Final SysRef Capture Enable state */
+ XRFdc_MTS_Sysref_Ctrl(InstancePtr, Type, Index, 0, ConfigPtr->SysRef_Enable, 0);
+ }
+ }
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This API is used to enable/disable the sysref.
+*
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param DACSyncConfigPtr is pointer to DAC Multi-Tile Sync config structure.
+* @param ADCSyncConfigPtr is pointer to ADC Multi-Tile Sync config structure.
+* @param SysRefEnable valid values are 0(disable) and 1(enable).
+*
+* @return
+* - XRFDC_MTS_OK if successful.
+*
+* @note None
+*
+******************************************************************************/
+u32 XRFdc_MTS_Sysref_Config(XRFdc *InstancePtr,
+ XRFdc_MultiConverter_Sync_Config *DACSyncConfigPtr,
+ XRFdc_MultiConverter_Sync_Config *ADCSyncConfigPtr, u32 SysRefEnable)
+{
+ u32 Tile;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(DACSyncConfigPtr != NULL);
+ Xil_AssertNonvoid(ADCSyncConfigPtr != NULL);
+
+ /* Enable/disable SysRef Capture on all DACs participating in MTS */
+ for (Tile = XRFDC_TILE_ID0; Tile < XRFDC_TILE_ID4; Tile++) {
+ if (((1U << Tile) & DACSyncConfigPtr->Tiles) != 0U) {
+ XRFdc_MTS_Sysref_Ctrl(InstancePtr,
+ XRFDC_DAC_TILE, Tile, 0, SysRefEnable, 0);
+ }
+ }
+
+ /* Enable/Disable SysRef Capture on all ADCs participating in MTS */
+ for (Tile = XRFDC_TILE_ID0; Tile < XRFDC_TILE_ID4; Tile++) {
+ if (((1U << Tile) & ADCSyncConfigPtr->Tiles) != 0U) {
+ XRFdc_MTS_Sysref_Ctrl(InstancePtr,
+ XRFDC_ADC_TILE, Tile, 0, SysRefEnable, 0);
+ }
+ }
+
+ /* Enable/Disable SysRef TRX */
+ XRFdc_MTS_Sysref_TRx(InstancePtr, SysRefEnable);
+
+ return XRFDC_MTS_OK;
+}
+
+/*****************************************************************************/
+/**
+*
+* This API Initializes the multi-tile sync config structures.
+* Optionally allows target codes to be provided for the Pll/T1
+* analog sysref capture
+*
+* @param ConfigPtr pointer to Multi-tile sync config structure.
+* @param PLL_CodesPtr pointer to PLL analog sysref capture.
+* @param T1_CodesPtr pointer to T1 analog sysref capture.
+*
+* @return None
+*
+* @note None
+*
+******************************************************************************/
+void XRFdc_MultiConverter_Init(XRFdc_MultiConverter_Sync_Config *ConfigPtr,
+ int *PLL_CodesPtr, int *T1_CodesPtr)
+{
+ u32 Index;
+
+ Xil_AssertVoid(ConfigPtr != NULL);
+
+ ConfigPtr->RefTile = 0U;
+ ConfigPtr->DTC_Set_PLL.Scan_Mode = (PLL_CodesPtr == NULL) ?
+ XRFDC_MTS_SCAN_INIT : XRFDC_MTS_SCAN_RELOAD;
+ ConfigPtr->DTC_Set_T1.Scan_Mode = (T1_CodesPtr == NULL) ?
+ XRFDC_MTS_SCAN_INIT : XRFDC_MTS_SCAN_RELOAD;
+ ConfigPtr->DTC_Set_PLL.IsPLL = 1U;
+ ConfigPtr->DTC_Set_T1.IsPLL = 0U;
+ ConfigPtr->Target_Latency = -1;
+ ConfigPtr->Marker_Delay = 15;
+ ConfigPtr->SysRef_Enable = 1; /* By default enable Sysref capture after MTS */
+
+ /* Initialize variables per tile */
+ for (Index = XRFDC_TILE_ID0; Index < XRFDC_TILE_ID4; Index++) {
+ if (PLL_CodesPtr != NULL) {
+ ConfigPtr->DTC_Set_PLL.Target[Index] = PLL_CodesPtr[Index];
+ } else {
+ ConfigPtr->DTC_Set_PLL.Target[Index] = 0;
+ }
+ if (T1_CodesPtr != NULL) {
+ ConfigPtr->DTC_Set_T1.Target[Index] = T1_CodesPtr[Index];
+ } else {
+ ConfigPtr->DTC_Set_T1.Target[Index] = 0;
+ }
+
+ ConfigPtr->DTC_Set_PLL.DTC_Code[Index] = -1;
+ ConfigPtr->DTC_Set_T1.DTC_Code[Index] = -1;
+ }
+
+}
+
+/*****************************************************************************/
+/**
+*
+* This is the top level API which will be used for Multi-tile
+* Synchronization.
+*
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param ConfigPtr Multi-tile sync config structure.
+*
+* @return
+* - XRFDC_MTS_OK if successful.
+* - XRFDC_MTS_TIMEOUT if timeout occurs.
+* - XRFDC_MTS_MARKER_RUN
+* - XRFDC_MTS_MARKER_MISM
+* - XRFDC_MTS_NOT_SUPPORTED if MTS is not supported.
+*
+* @note None
+*
+******************************************************************************/
+u32 XRFdc_MultiConverter_Sync(XRFdc *InstancePtr, u32 Type,
+ XRFdc_MultiConverter_Sync_Config *ConfigPtr)
+{
+ u32 Status;
+ u32 Index;
+ u32 RegData;
+ XRFdc_IPStatus IPStatus = {0};
+ XRFdc_MTS_Marker Markers = {0U};
+ u32 BaseAddr;
+ u32 TileState;
+ u32 BlockStatus;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(ConfigPtr != NULL);
+
+ Status = XRFDC_MTS_OK;
+
+ (void)XRFdc_GetIPStatus(InstancePtr, &IPStatus);
+ for (Index = XRFDC_TILE_ID0; Index < XRFDC_TILE_ID4; Index++) {
+ if ((ConfigPtr->Tiles & (1U << Index)) != 0U) {
+ TileState = (Type == XRFDC_DAC_TILE) ?
+ IPStatus.DACTileStatus[Index].TileState :
+ IPStatus.ADCTileStatus[Index].TileState ;
+ if (TileState != 0xFU) {
+ metal_log(METAL_LOG_ERROR,
+ "%s tile %d in Multi-Tile group not started\n",
+ (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC", Index);
+
+ Status |= XRFDC_MTS_IP_NOT_READY;
+ }
+ BaseAddr = XRFDC_DRP_BASE(Type, Index) - XRFDC_TILE_DRP_OFFSET;
+ RegData = XRFdc_ReadReg(InstancePtr, BaseAddr, XRFDC_MTS_DLY_ALIGNER);
+ if (RegData == 0U) {
+ metal_log(METAL_LOG_ERROR, "%s tile %d is not enabled for MTS, check IP configuration\n",
+ (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC", Index);
+ Status |= XRFDC_MTS_NOT_ENABLED;
+ }
+
+ BlockStatus = XRFdc_CheckBlockEnabled(InstancePtr, Type, Index, 0x0U);
+ if (BlockStatus != 0U) {
+ metal_log(METAL_LOG_ERROR, "%s%d block0 is not enabled, check IP configuration\n",
+ (Type == XRFDC_ADC_TILE) ? "ADC" : "DAC", Index);
+ Status |= XRFDC_MTS_NOT_SUPPORTED;
+ }
+ }
+ }
+
+ if (Status != XRFDC_MTS_OK) {
+ return Status;
+ }
+
+ /* Disable the FIFOs */
+ XRFdc_MTS_FIFOCtrl(InstancePtr, Type, XRFDC_MTS_FIFO_DISABLE, 0);
+
+ /* Enable SysRef Rx */
+ XRFdc_MTS_Sysref_TRx(InstancePtr, 1);
+
+ /* Update distribution */
+ Status |= XRFdc_MTS_Sysref_Dist(InstancePtr, -1);
+
+ /* Scan DTCs for each tile */
+ for (Index = XRFDC_TILE_ID0; Index < XRFDC_TILE_ID4; Index++) {
+ if ((ConfigPtr->Tiles & (1U << Index)) != 0U) {
+ /* Run DTC Scan for T1/PLL */
+ BaseAddr = XRFDC_DRP_BASE(Type, Index) + XRFDC_HSCOM_ADDR;
+ RegData = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_MTS_CLKSTAT);
+ if ((RegData & XRFDC_MTS_PLLEN_M) != 0U) {
+ /* DTC Scan PLL */
+ if (Index == 0U) {
+ metal_log(METAL_LOG_INFO, "\nDTC Scan PLL\n", 0);
+ }
+ ConfigPtr->DTC_Set_PLL.RefTile = ConfigPtr->RefTile;
+ Status |= XRFdc_MTS_Dtc_Scan(InstancePtr, Type, Index,
+ &ConfigPtr->DTC_Set_PLL);
+ }
+ }
+ }
+
+ /* Scan DTCs for each tile T1 */
+ metal_log(METAL_LOG_INFO, "\nDTC Scan T1\n", 0);
+ for (Index = XRFDC_TILE_ID0; Index < XRFDC_TILE_ID4; Index++) {
+ if ((ConfigPtr->Tiles & (1U << Index)) != 0U) {
+ ConfigPtr->DTC_Set_T1 .RefTile = ConfigPtr->RefTile;
+ Status |= XRFdc_MTS_Dtc_Scan(InstancePtr, Type, Index,
+ &ConfigPtr->DTC_Set_T1);
+ }
+ }
+
+ /* Enable FIFOs */
+ XRFdc_MTS_FIFOCtrl(InstancePtr, Type, XRFDC_MTS_FIFO_ENABLE,
+ ConfigPtr->Tiles);
+
+ /* Measure latency */
+ Status |= XRFdc_MTS_GetMarker(InstancePtr, Type, ConfigPtr->Tiles,
+ &Markers, ConfigPtr->Marker_Delay);
+
+ /* Calculate latency difference and adjust for it */
+ Status |= XRFdc_MTS_Latency(InstancePtr, Type, ConfigPtr, &Markers);
+
+ return Status;
+}
+/*****************************************************************************/
+/**
+*
+* This is the top level API which will be used to check if Multi-tile
+* is enabled.
+*
+*
+* @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 indicates Tile number (0-3).
+* @param EnablePtr to be filled with the enable state.
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_SUCCESS if error occurs.
+*
+* @note None
+*
+******************************************************************************/
+u32 XRFdc_GetMTSEnable(XRFdc *InstancePtr, u32 Type,u32 Tile_Id, u32 *EnablePtr)
+{
+ u32 RegData;
+ u32 BaseAddr;
+ u32 Status;
+ 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_DRP_BASE(Type, Tile_Id) - XRFDC_TILE_DRP_OFFSET;
+ RegData = XRFdc_ReadReg(InstancePtr, BaseAddr, XRFDC_MTS_DLY_ALIGNER);
+ if (RegData == 0) {
+ *EnablePtr = 0;
+ } else {
+ *EnablePtr = 1;
+ }
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+}
+/** @} */
diff --git a/mpm/lib/rfdc/xrfdc_sinit.c b/mpm/lib/rfdc/xrfdc_sinit.c
new file mode 100644
index 000000000..0fb907859
--- /dev/null
+++ b/mpm/lib/rfdc/xrfdc_sinit.c
@@ -0,0 +1,272 @@
+/******************************************************************************
+*
+* 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_sinit.c
+* @addtogroup rfdc_v6_0
+* @{
+*
+* The implementation of the XRFdc component's static initialization
+* functionality.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- --- -------- -----------------------------------------------
+* 1.0 sk 05/16/17 Initial release
+* 5.0 mus 08/17/18 Updated XRFdc_LookupConfig to make use of device
+* tree instead of xrfdc_g.c, to obtain
+* XRFdc_Config for provided device id.It is being
+* achieved through "param-list" property in RFDC
+* device node, it will be having 1:1 mapping with
+* the XRFdc_Config structure. Said changes
+* have been done, to remove the xparameters.h
+* dependency from RFDC Linux user space driver.
+*
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+#define METAL_INTERNAL
+#include "mpm/rfdc/xrfdc.h"
+#ifdef __BAREMETAL__
+#include "xparameters.h"
+#else
+#include <dirent.h>
+#include <arpa/inet.h>
+#endif
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+#ifdef __BAREMETAL__
+extern XRFdc_Config XRFdc_ConfigTable[];
+#else
+static XRFdc_Config *XRFdc_ConfigTablePtr=NULL;
+#endif
+
+#ifndef __BAREMETAL__
+/*****************************************************************************/
+/**
+*
+* Compare two strings in the reversed order.This function compares only
+* the last "Count" number of characters of Str1Ptr and Str2Ptr.
+*
+* @param Str1Ptr is base address of first string
+* @param Str2Ptr is base address of second string
+* @param Count is number of last characters to be compared between
+* Str1Ptr and Str2Ptr
+*
+* @return
+* 0 if last "Count" number of bytes matches between Str1Ptr and
+* Str2Ptr, else differnce in unmatched character.
+*
+*@note None.
+*
+******************************************************************************/
+static s32 XRFdc_Strrncmp(const char *Str1Ptr, const char *Str2Ptr, size_t Count)
+{
+ u16 Len1 = strlen(Str1Ptr);
+ u16 Len2 = strlen(Str2Ptr);
+ u8 Diff;
+
+ for (; Len1 && Len2; Len1--, Len2--) {
+ if ((Diff = Str1Ptr[Len1 - 1] - Str2Ptr[Len2 - 1]) != 0) {
+ return Diff;
+ }
+ if (--Count == 0) {
+ return 0;
+ }
+ }
+
+ return (Len1 - Len2);
+}
+
+/*****************************************************************************/
+/**
+*
+* Traverse "/sys/bus/platform/device" directory, to find RFDC device entry,
+* corresponding to provided device id. If device entry corresponding to said
+* device id is found, store it in output buffer DevNamePtr.
+*
+* @param DevNamePtr is base address of char array, where device name
+* will be stored
+* @param DevId contains the ID of the device to look up the
+* RFDC device name entry in "/sys/bus/platform/device"
+*
+* @return
+ * - XRFDC_SUCCESS if successful.
+ * - XRFDC_FAILURE if device entry not found for given device id.
+ *
+ *@note None.
+*
+******************************************************************************/
+s32 XRFdc_GetDeviceNameByDeviceId(char *DevNamePtr, u16 DevId)
+{
+ s32 Status = XRFDC_FAILURE;
+ u32 Data = 0;
+ char CompatibleString[NAME_MAX];
+ struct metal_device *DevicePtr;
+ DIR *DirPtr;
+ struct dirent *DirentPtr;
+ char Len = strlen(XRFDC_COMPATIBLE_STRING);
+ char SignLen = strlen(XRFDC_SIGNATURE);
+
+ DirPtr = opendir(XRFDC_PLATFORM_DEVICE_DIR);
+ if (DirPtr) {
+ while ((DirentPtr = readdir(DirPtr)) != NULL) {
+ if (XRFdc_Strrncmp(DirentPtr->d_name,
+ XRFDC_SIGNATURE, SignLen) == 0) {
+ Status = metal_device_open("platform",DirentPtr->d_name,
+ &DevicePtr);
+ if (Status) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to open device %s", DirentPtr->d_name);
+ continue;
+ }
+ Status = metal_linux_get_device_property(DevicePtr,
+ XRFDC_COMPATIBLE_PROPERTY, CompatibleString ,
+ Len);
+ if (Status < 0) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to read device tree property");
+ } else if (strncmp(CompatibleString, \
+ XRFDC_COMPATIBLE_STRING, Len) == 0) {
+ Status = metal_linux_get_device_property(DevicePtr,
+ XRFDC_CONFIG_DATA_PROPERTY,
+ &Data, XRFDC_DEVICE_ID_SIZE);
+ if (Status < 0) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to read device tree property");
+ } else if ( Data == DevId ) {
+ strcpy(DevNamePtr, DirentPtr->d_name);
+ Status = XRFDC_SUCCESS;
+ metal_device_close(DevicePtr);
+ break;
+ }
+ }
+ metal_device_close(DevicePtr);
+ }
+ }
+ closedir(DirPtr);
+ }
+ return Status;
+}
+#endif
+/*****************************************************************************/
+/**
+*
+* Looks up the device configuration based on the unique device ID. A table
+* contains the configuration info for each device in the system.
+*
+* @param DeviceId contains the ID of the device to look up the
+* configuration for.
+*
+* @return
+*
+* A pointer to the configuration found or NULL if the specified device ID was
+* not found. See xrfdc.h for the definition of XRFdc_Config.
+*
+* @note None.
+*
+******************************************************************************/
+XRFdc_Config *XRFdc_LookupConfig(u16 DeviceId)
+{
+ XRFdc_Config *CfgPtr = NULL;
+#ifndef __BAREMETAL__
+ s32 Status=0;
+ u32 NumInstances;
+ struct metal_device *Deviceptr;
+ char DeviceName[NAME_MAX];
+
+ Status = XRFdc_GetDeviceNameByDeviceId(DeviceName, DeviceId);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid device id %d", DeviceId);
+ goto RETURN_PATH2;
+ }
+
+ Status = metal_device_open(XRFDC_BUS_NAME, DeviceName, &Deviceptr);
+ if (Status) {
+ metal_log(METAL_LOG_ERROR, "\n Failed to open device %s", DeviceName);
+ goto RETURN_PATH2;
+ }
+
+ if (XRFdc_ConfigTablePtr == NULL) {
+ Status = metal_linux_get_device_property(Deviceptr,
+ XRFDC_NUM_INSTANCES_PROPERTY,
+ &NumInstances, XRFDC_NUM_INST_SIZE);
+ if (Status < 0) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to read device tree property %s",
+ XRFDC_NUM_INSTANCES_PROPERTY);
+ goto RETURN_PATH1;
+ }
+ XRFdc_ConfigTablePtr = (XRFdc_Config*) malloc(ntohl(NumInstances) * \
+ XRFDC_CONFIG_DATA_SIZE);
+ if (XRFdc_ConfigTablePtr == NULL) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to allocate memory for XRFdc_ConfigTablePtr");
+ goto RETURN_PATH1;
+ }
+ }
+ Status = metal_linux_get_device_property(Deviceptr,
+ XRFDC_CONFIG_DATA_PROPERTY,
+ &XRFdc_ConfigTablePtr[DeviceId],
+ XRFDC_CONFIG_DATA_SIZE);
+ if (Status == XRFDC_SUCCESS) {
+ CfgPtr = &XRFdc_ConfigTablePtr[DeviceId];
+ } else {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to read device tree property %s",
+ XRFDC_CONFIG_DATA_PROPERTY);
+
+ }
+RETURN_PATH1:
+ metal_device_close(Deviceptr);
+RETURN_PATH2:
+#else
+ u32 Index;
+
+ for (Index = 0U; Index < (u32)XPAR_XRFDC_NUM_INSTANCES; Index++) {
+ if (XRFdc_ConfigTable[Index].DeviceId == DeviceId) {
+ CfgPtr = &XRFdc_ConfigTable[Index];
+ break;
+ }
+ }
+#endif
+ return (XRFdc_Config *)CfgPtr;
+}
+/** @} */