From 2a526bdb7eb8304942f4ae5b98d5b15c7fdfa913 Mon Sep 17 00:00:00 2001 From: George Mois Date: Tue, 25 Nov 2025 19:44:36 +0200 Subject: [PATCH 01/14] iio: adc: adrv902x: Initialize local variables Initialize the val local variable to 0. Initialize the rate local variable to 0. Remove redundant blank line. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index 124e29ada05cbf..c2641e2241f503 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -636,8 +636,7 @@ static ssize_t adrv9025_phy_lo_read(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, char *buf) { struct adrv9025_rf_phy *phy = iio_priv(indio_dev); - - u64 val; + u64 val = 0; int ret; mutex_lock(&phy->lock); @@ -1824,7 +1823,7 @@ static int adrv9025_clk_register(struct adrv9025_rf_phy *phy, const char *name, char c_name[ADRV9025_MAX_CLK_NAME + 1], p_name[2][ADRV9025_MAX_CLK_NAME + 1]; const char *_parent_name[2]; - u32 rate; + u32 rate = 0; int ret; /* struct adrv9025_clock assignments */ From badfe04d326ebae3a51dd827639bacc38971313a Mon Sep 17 00:00:00 2001 From: George Mois Date: Tue, 18 Nov 2025 09:44:04 +0200 Subject: [PATCH 02/14] iio: adc: adrv902x: Address/Fix coding style issues Remove variables that are not needed, initialize local variables where required, fix spacing, and remove redundant semicolons and blank lines. No functional change. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 40 ++++++++++++----------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index c2641e2241f503..c08f823a6b4cf2 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -133,7 +133,6 @@ static int adrv9025_RxLinkSamplingRateFind(adi_adrv9025_Device_t *device, adi_adrv9025_FramerSel_e framerSel, u32 *iqRate_kHz) { - int recoveryAction = ADI_COMMON_ACT_NO_ACTION; adi_adrv9025_AdcSampleXbarSel_e conv = ADI_ADRV9025_ADC_RX1_Q; u32 framerIndex = 0; @@ -164,7 +163,7 @@ static int adrv9025_RxLinkSamplingRateFind(adi_adrv9025_Device_t *device, if (adrv9025Init->dataInterface.framer[framerIndex].jesd204M < 1) { *iqRate_kHz = 0; - return recoveryAction; + return ADI_COMMON_ACT_NO_ACTION; } conv = adrv9025Init->dataInterface.framer[framerIndex] @@ -223,7 +222,7 @@ static int adrv9025_RxLinkSamplingRateFind(adi_adrv9025_Device_t *device, ADI_ERROR_RETURN(device->common.error.newAction); } - return recoveryAction; + return ADI_COMMON_ACT_NO_ACTION; } static int adrv9025_TxLinkSamplingRateFind(adi_adrv9025_Device_t *device, @@ -231,7 +230,6 @@ static int adrv9025_TxLinkSamplingRateFind(adi_adrv9025_Device_t *device, adi_adrv9025_DeframerSel_e deframerSel, u32 *iqRate_kHz) { - int recoveryAction = ADI_COMMON_ACT_NO_ACTION; u32 deframerIndex = 0; /* Check device pointer is not null */ @@ -259,7 +257,7 @@ static int adrv9025_TxLinkSamplingRateFind(adi_adrv9025_Device_t *device, if (adrv9025Init->dataInterface.deframer[deframerIndex].jesd204M < 1) { *iqRate_kHz = 0; - return recoveryAction; + return ADI_COMMON_ACT_NO_ACTION; } //Use samplerate of DAC set to use deframer output 0. @@ -295,7 +293,7 @@ static int adrv9025_TxLinkSamplingRateFind(adi_adrv9025_Device_t *device, .profile.txInputRate_kHz; } - return recoveryAction; + return ADI_COMMON_ACT_NO_ACTION; } static void adrv9025_shutdown(struct adrv9025_rf_phy *phy) @@ -1183,9 +1181,9 @@ static int adrv9025_phy_read_raw(struct iio_dev *indio_dev, break; } - ret = adrv9025_gainindex_to_gain(phy, chan->channel, - rxGain.gainIndex, val, - val2); + adrv9025_gainindex_to_gain(phy, chan->channel, + rxGain.gainIndex, val, + val2); } ret = IIO_VAL_INT_PLUS_MICRO_DB; break; @@ -1548,9 +1546,8 @@ static ssize_t adrv9025_debugfs_read(struct file *file, char __user *userbuf, val = *(u64 *)entry->out_value; break; default: - ret = -EINVAL; + return -EINVAL; } - } else if (entry->cmd) { switch (entry->cmd) { case DBGFS_RX0_QEC_STATUS: @@ -1690,7 +1687,7 @@ static ssize_t adrv9025_debugfs_write(struct file *file, *(u64 *)entry->out_value = val; break; default: - ret = -EINVAL; + return -EINVAL; } } @@ -1722,7 +1719,6 @@ static int adrv9025_register_debugfs(struct iio_dev *indio_dev) { struct adrv9025_rf_phy *phy = iio_priv(indio_dev); umode_t mode = 0644; - struct dentry *d; int i; if (!iio_get_debugfs_dentry(indio_dev)) @@ -1751,10 +1747,10 @@ static int adrv9025_register_debugfs(struct iio_dev *indio_dev) for (i = 0; i < phy->adrv9025_debugfs_entry_index; i++) { if (phy->adrv9025_debugfs_entry_index > DBGFS_BIST_TONE) mode = 0400; - d = debugfs_create_file(phy->debugfs_entry[i].propname, mode, - iio_get_debugfs_dentry(indio_dev), - &phy->debugfs_entry[i], - &adrv9025_debugfs_reg_fops); + debugfs_create_file(phy->debugfs_entry[i].propname, mode, + iio_get_debugfs_dentry(indio_dev), + &phy->debugfs_entry[i], + &adrv9025_debugfs_reg_fops); } return 0; } @@ -2074,7 +2070,7 @@ static int adrv9025_jesd204_link_init(struct jesd204_dev *jdev, lnk->jesd_encoder = deframer->enableJesd204C ? JESD204_ENCODER_64B66B : JESD204_ENCODER_8B10B; lnk->subclass = JESD204_SUBCLASS_1; lnk->is_transmit = true; - }; + } return JESD204_STATE_CHANGE_DONE; } @@ -2312,8 +2308,7 @@ static int adrv9025_jesd204_clks_enable(struct jesd204_dev *jdev, priv->link[lnk->link_id].source_id, 0); if (ret) return adrv9025_dev_err(phy); - - }; + } return JESD204_STATE_CHANGE_DONE; } @@ -2368,8 +2363,7 @@ static int adrv9025_jesd204_link_enable(struct jesd204_dev *jdev, priv->link[lnk->link_id].source_id, 1); if (ret) return adrv9025_dev_err(phy); - - }; + } return JESD204_STATE_CHANGE_DONE; } @@ -2445,7 +2439,7 @@ static int adrv9025_jesd204_link_running(struct jesd204_dev *jdev, ADI_ADRV9025_TRACKING_CAL_ENABLE); if (ret) return adrv9025_dev_err(phy); - }; + } return JESD204_STATE_CHANGE_DONE; } From 0da928f05a0fb3cb27dedccc1278093f0964876e Mon Sep 17 00:00:00 2001 From: George Mois Date: Mon, 17 Nov 2025 10:19:58 +0200 Subject: [PATCH 03/14] iio: adc: adrv902x: Use sysfs_emit Use sysfs_emit instead of sprintf. Use safe functions for formatting buffers. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 60 +++++++++++++++++------------ 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index c08f823a6b4cf2..a06e6e07851da4 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -415,8 +415,8 @@ static ssize_t adrv9025_phy_show(struct device *dev, val = this_attr->address >> 8; if (val) - ret = sprintf(buf, "%d\n", - !!(phy->cal_mask.calMask & val)); + ret = sysfs_emit(buf, "%d\n", + !!(phy->cal_mask.calMask & val)); break; case adrv9025_JESD204_FSM_ERROR: if (!phy->jdev) { @@ -441,7 +441,7 @@ static ssize_t adrv9025_phy_show(struct device *dev, break; } } - ret = sprintf(buf, "%d\n", err); + ret = sysfs_emit(buf, "%d\n", err); break; case adrv9025_JESD204_FSM_PAUSED: if (!phy->jdev) { @@ -469,7 +469,7 @@ static ssize_t adrv9025_phy_show(struct device *dev, break; } } - ret = sprintf(buf, "%d\n", paused); + ret = sysfs_emit(buf, "%d\n", paused); break; case adrv9025_JESD204_FSM_STATE: if (!phy->jdev) { @@ -490,7 +490,7 @@ static ssize_t adrv9025_phy_show(struct device *dev, * just get the first link state; we're assuming that all 3 are in sync * and that adrv9025_JESD204_FSM_PAUSED was called before */ - ret = sprintf(buf, "%s\n", jesd204_link_get_state_str(links[0])); + ret = sysfs_emit(buf, "%s\n", jesd204_link_get_state_str(links[0])); break; case adrv9025_JESD204_FSM_CTRL: if (!phy->jdev) { @@ -498,7 +498,7 @@ static ssize_t adrv9025_phy_show(struct device *dev, break; } - ret = sprintf(buf, "%d\n", phy->is_initialized); + ret = sysfs_emit(buf, "%d\n", phy->is_initialized); break; default: ret = -EINVAL; @@ -651,7 +651,7 @@ static ssize_t adrv9025_phy_lo_read(struct iio_dev *indio_dev, } mutex_unlock(&phy->lock); - return ret ? ret : sprintf(buf, "%llu\n", val); + return ret ? ret : sysfs_emit(buf, "%llu\n", val); } #define _ADRV9025_EXT_LO_INFO(_name, _ident) \ @@ -823,8 +823,8 @@ static ssize_t adrv9025_phy_rx_read(struct iio_dev *indio_dev, ret = adi_adrv9025_RxDecPowerGet(phy->madDevice, rxchan, &dec_pwr_mdb); if (ret == 0) - ret = sprintf(buf, "%u.%02u dB\n", dec_pwr_mdb / 1000, - dec_pwr_mdb % 1000); + ret = sysfs_emit(buf, "%u.%02u dB\n", dec_pwr_mdb / 1000, + dec_pwr_mdb % 1000); else ret = adrv9025_dev_err(phy); @@ -833,29 +833,29 @@ static ssize_t adrv9025_phy_rx_read(struct iio_dev *indio_dev, tmask = ADI_ADRV9025_TRACK_RX1_QEC << chan->channel; ret = adi_adrv9025_TrackingCalsEnableGet(phy->madDevice, &mask); if (ret == 0) - ret = sprintf(buf, "%d\n", !!(tmask & mask)); + ret = sysfs_emit(buf, "%d\n", !!(tmask & mask)); break; case RX_HD2: tmask = ADI_ADRV9025_TRACK_RX1_HD2 << chan->channel; ret = adi_adrv9025_TrackingCalsEnableGet(phy->madDevice, &mask); if (ret == 0) - ret = sprintf(buf, "%d\n", !!(tmask & mask)); + ret = sysfs_emit(buf, "%d\n", !!(tmask & mask)); break; case RX_DIG_DC: ret = adi_adrv9025_DigDcOffsetEnableGet(phy->madDevice, &mask16); if (ret == 0) - ret = sprintf(buf, "%d\n", - !!((ADI_ADRV9025_MSHIFT_DC_OFFSET_RX_CH0 << chan->channel) & mask16)); + ret = sysfs_emit(buf, "%d\n", + !!((ADI_ADRV9025_MSHIFT_DC_OFFSET_RX_CH0 << chan->channel) & mask16)); else ret = adrv9025_dev_err(phy); break; case RX_RF_BANDWIDTH: - ret = sprintf(buf, "%u\n", - phy->deviceInitStruct.rx.rxChannelCfg[chan->channel].profile.rfBandwidth_kHz * - 1000); + ret = sysfs_emit(buf, "%u\n", + phy->deviceInitStruct.rx.rxChannelCfg[chan->channel].profile.rfBandwidth_kHz * + 1000); break; default: ret = -EINVAL; @@ -907,7 +907,7 @@ static ssize_t adrv9025_phy_tx_read(struct iio_dev *indio_dev, mutex_unlock(&phy->lock); if (ret == 0) - ret = sprintf(buf, "%d\n", val); + ret = sysfs_emit(buf, "%d\n", val); else return adrv9025_dev_err(phy); @@ -1479,8 +1479,12 @@ static ssize_t adrv9025_rx_qec_status_read(struct adrv9025_rf_phy *phy, if (ret) return adrv9025_dev_err(phy); - return sprintf(buf, "err %d %% %d perf %d iter cnt %d update cnt %d\n", rxQecStatus.errorCode, rxQecStatus.percentComplete, - rxQecStatus.selfcheckIrrDb, rxQecStatus.iterCount, rxQecStatus.updateCount); + return scnprintf(buf, PAGE_SIZE, "err %d %% %d perf %d iter cnt %d update cnt %d\n", + rxQecStatus.errorCode, + rxQecStatus.percentComplete, + rxQecStatus.selfcheckIrrDb, + rxQecStatus.iterCount, + rxQecStatus.updateCount); } static ssize_t adrv9025_tx_qec_status_read(struct adrv9025_rf_phy *phy, @@ -1496,8 +1500,12 @@ static ssize_t adrv9025_tx_qec_status_read(struct adrv9025_rf_phy *phy, if (ret) return adrv9025_dev_err(phy); - return sprintf(buf, "err %d %% %d perf %d iter cnt %d update cnt %d\n", txQecStatus.errorCode, txQecStatus.percentComplete, - txQecStatus.correctionMetric, txQecStatus.iterCount, txQecStatus.updateCount); + return scnprintf(buf, PAGE_SIZE, "err %d %% %d perf %d iter cnt %d update cnt %d\n", + txQecStatus.errorCode, + txQecStatus.percentComplete, + txQecStatus.correctionMetric, + txQecStatus.iterCount, + txQecStatus.updateCount); } static ssize_t adrv9025_tx_lol_status_read(struct adrv9025_rf_phy *phy, @@ -1513,8 +1521,12 @@ static ssize_t adrv9025_tx_lol_status_read(struct adrv9025_rf_phy *phy, if (ret) return adrv9025_dev_err(phy); - return sprintf(buf, "err %d %% %d var %d iter cnt %d update cnt %d\n", txLolStatus.errorCode, txLolStatus.percentComplete, - txLolStatus.varianceMetric, txLolStatus.iterCount, txLolStatus.updateCount); + return scnprintf(buf, PAGE_SIZE, "err %d %% %d var %d iter cnt %d update cnt %d\n", + txLolStatus.errorCode, + txLolStatus.percentComplete, + txLolStatus.varianceMetric, + txLolStatus.iterCount, + txLolStatus.updateCount); } static ssize_t adrv9025_debugfs_read(struct file *file, char __user *userbuf, @@ -1590,7 +1602,7 @@ static ssize_t adrv9025_debugfs_read(struct file *file, char __user *userbuf, } if (!len) - len = snprintf(buf, sizeof(buf), "%llu\n", val); + len = scnprintf(buf, sizeof(buf), "%llu\n", val); return simple_read_from_buffer(userbuf, count, ppos, buf, len); } From ba22e5446b75524b90e4a46b7b5dd571ea02c7cb Mon Sep 17 00:00:00 2001 From: George Mois Date: Wed, 19 Nov 2025 10:34:55 +0200 Subject: [PATCH 04/14] iio: adc: adrv902x: Assure one chan on ORx data path Make sure that only one RF channel (ORx1 or ORx2, and ORx3 or ORx4, respectively) is enabled per ORx data path. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index a06e6e07851da4..9c7f1c8467f2c5 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -1254,6 +1254,8 @@ static int adrv9025_phy_write_raw(struct iio_dev *indio_dev, chan_no += 1; if (val) { rxchan |= (ADI_ADRV9025_RX1 << chan_no); + if (chan_no >= CHAN_OBS_RX1) + rxchan &= ~(ADI_ADRV9025_RX1 << (chan_no + 1)); } else { if (chan_no < CHAN_OBS_RX1) { rxchan &= ~(ADI_ADRV9025_RX1 << chan_no); From 5e4ba36090e020e399ec3dd248c397eee58f9461 Mon Sep 17 00:00:00 2001 From: George Mois Date: Wed, 19 Nov 2025 11:04:18 +0200 Subject: [PATCH 05/14] iio: adc: adrv902x: ORx selection for hardwaregain Select the active ORx RF input for modifying the hardwaregain corresponding to one of the two ORx datapaths. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 66 +++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index 9c7f1c8467f2c5..8ab59d7d6fae10 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -1173,9 +1173,39 @@ static int adrv9025_phy_read_raw(struct iio_dev *indio_dev, } else { adi_adrv9025_RxGain_t rxGain; + chan_no = chan->channel; + + if (chan_no > CHAN_RX4) { + /* For OBS channels, determine which specific channel is enabled */ + ret = adi_adrv9025_RxTxEnableGet(phy->madDevice, &rxchan, &txchan); + if (ret) { + ret = adrv9025_dev_err(phy); + break; + } + + if (chan_no == CHAN_OBS_RX1) { + if ((rxchan & ADI_ADRV9025_ORX1) && !(rxchan & ADI_ADRV9025_ORX2)) { + chan_no = CHAN_OBS_RX1; + } else if (!(rxchan & ADI_ADRV9025_ORX1) && (rxchan & ADI_ADRV9025_ORX2)) { + chan_no = CHAN_OBS_RX2; + } else { + ret = -EINVAL; + break; + } + } else if (chan_no == CHAN_OBS_RX2) { + if ((rxchan & ADI_ADRV9025_ORX3) && !(rxchan & ADI_ADRV9025_ORX4)) { + chan_no = CHAN_OBS_RX3; + } else if (!(rxchan & ADI_ADRV9025_ORX3) && (rxchan & ADI_ADRV9025_ORX4)) { + chan_no = CHAN_OBS_RX4; + } else { + ret = -EINVAL; + break; + } + } + } ret = adi_adrv9025_RxGainGet( - phy->madDevice, 1 << chan->channel, &rxGain); + phy->madDevice, 1 << chan_no, &rxGain); if (ret) { ret = adrv9025_dev_err(phy); break; @@ -1292,14 +1322,44 @@ static int adrv9025_phy_write_raw(struct iio_dev *indio_dev, } else { adi_adrv9025_RxGain_t rxGain; + chan_no = chan->channel; + + if (chan_no > CHAN_RX4) { + ret = adi_adrv9025_RxTxEnableGet(phy->madDevice, &rxchan, + &txchan); + if (ret) { + ret = adrv9025_dev_err(phy); + goto out; + } + + if (chan_no == CHAN_OBS_RX1) { + if (rxchan & ADI_ADRV9025_ORX1 && !(rxchan & ADI_ADRV9025_ORX2)) { + chan_no = CHAN_OBS_RX1; + } else if (!(rxchan & ADI_ADRV9025_ORX1) && (rxchan & ADI_ADRV9025_ORX2)) { + chan_no = CHAN_OBS_RX2; + } else { + ret = -EINVAL; + goto out; + } + } else if (chan_no == CHAN_OBS_RX2) { + if (rxchan & ADI_ADRV9025_ORX3 && !(rxchan & ADI_ADRV9025_ORX4)) { + chan_no = CHAN_OBS_RX3; + } else if (!(rxchan & ADI_ADRV9025_ORX3) && (rxchan & ADI_ADRV9025_ORX4)) { + chan_no = CHAN_OBS_RX4; + } else { + ret = -EINVAL; + goto out; + } + } + } - ret = adrv9025_gain_to_gainindex(phy, chan->channel, + ret = adrv9025_gain_to_gainindex(phy, chan_no, val, val2, &code); if (ret < 0) break; rxGain.gainIndex = code; - rxGain.rxChannelMask = 1 << chan->channel; + rxGain.rxChannelMask = 1 << chan_no; ret = adi_adrv9025_RxGainSet(phy->madDevice, &rxGain, 1); From 31d963b80052d5d6a333968c4738e8d829b574c8 Mon Sep 17 00:00:00 2001 From: George Mois Date: Tue, 2 Sep 2025 09:25:55 +0300 Subject: [PATCH 06/14] iio: adc: adrv902x: Add ORx to Tx mapping Add Orx to Tx mapping setting functionality. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 37 ++++++++++++++++++++++++++++- drivers/iio/adc/adrv902x/adrv9025.h | 4 ++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index 8ab59d7d6fae10..a62be1821176ea 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -1595,10 +1595,11 @@ static ssize_t adrv9025_debugfs_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct adrv9025_debugfs_entry *entry = file->private_data; + adi_adrv9025_TxChannels_e tx_ch = ADI_ADRV9025_TXOFF; struct adrv9025_rf_phy *phy = entry->phy; + ssize_t len = 0; char buf[700]; u64 val = 0; - ssize_t len = 0; u8 chan; int ret; @@ -1624,6 +1625,20 @@ static ssize_t adrv9025_debugfs_read(struct file *file, char __user *userbuf, } } else if (entry->cmd) { switch (entry->cmd) { + case DBGFS_ORX1_TO_TX: + case DBGFS_ORX2_TO_TX: + case DBGFS_ORX3_TO_TX: + case DBGFS_ORX4_TO_TX: + mutex_lock(&phy->lock); + ret = adi_adrv9025_TxToOrxMappingGet(phy->madDevice, + ADI_ADRV9025_ORX1 << (entry->cmd - DBGFS_ORX1_TO_TX), + &tx_ch); + mutex_unlock(&phy->lock); + if (ret) + return adrv9025_dev_err(phy); + + val = (u64)tx_ch; + break; case DBGFS_RX0_QEC_STATUS: case DBGFS_RX1_QEC_STATUS: case DBGFS_RX2_QEC_STATUS: @@ -1738,7 +1753,23 @@ static ssize_t adrv9025_debugfs_write(struct file *file, entry->val = val; return count; + case DBGFS_ORX1_TO_TX: + case DBGFS_ORX2_TO_TX: + case DBGFS_ORX3_TO_TX: + case DBGFS_ORX4_TO_TX: + if (ret != 1) + return -EINVAL; + mutex_lock(&phy->lock); + ret = adi_adrv9025_TxToOrxMappingSet(phy->madDevice, + ADI_ADRV9025_ORX1 << (entry->cmd - DBGFS_ORX1_TO_TX), + val); + mutex_unlock(&phy->lock); + if (ret) + return adrv9025_dev_err(phy); + + entry->val = val; + return count; default: break; } @@ -1803,6 +1834,10 @@ static int adrv9025_register_debugfs(struct iio_dev *indio_dev) adrv9025_add_debugfs_entry(phy, "bist_framer_loopback", DBGFS_BIST_FRAMER_LOOPBACK); adrv9025_add_debugfs_entry(phy, "bist_tone", DBGFS_BIST_TONE); + adrv9025_add_debugfs_entry(phy, "orx1_to_tx_mapping", DBGFS_ORX1_TO_TX); + adrv9025_add_debugfs_entry(phy, "orx2_to_tx_mapping", DBGFS_ORX2_TO_TX); + adrv9025_add_debugfs_entry(phy, "orx3_to_tx_mapping", DBGFS_ORX3_TO_TX); + adrv9025_add_debugfs_entry(phy, "orx4_to_tx_mapping", DBGFS_ORX4_TO_TX); adrv9025_add_debugfs_entry(phy, "rx0_qec_status", DBGFS_RX0_QEC_STATUS); adrv9025_add_debugfs_entry(phy, "rx1_qec_status", DBGFS_RX1_QEC_STATUS); adrv9025_add_debugfs_entry(phy, "rx2_qec_status", DBGFS_RX2_QEC_STATUS); diff --git a/drivers/iio/adc/adrv902x/adrv9025.h b/drivers/iio/adc/adrv902x/adrv9025.h index 9ef9976e0ca5df..ee6b626093b172 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.h +++ b/drivers/iio/adc/adrv902x/adrv9025.h @@ -36,6 +36,10 @@ enum debugfs_cmd { DBGFS_BIST_FRAMER_0_PRBS, DBGFS_BIST_FRAMER_LOOPBACK, DBGFS_BIST_TONE, + DBGFS_ORX1_TO_TX, + DBGFS_ORX2_TO_TX, + DBGFS_ORX3_TO_TX, + DBGFS_ORX4_TO_TX, DBGFS_RX0_QEC_STATUS, DBGFS_RX1_QEC_STATUS, DBGFS_RX2_QEC_STATUS, From 03c3091359a3c936e3490f3817f0633cc63b647d Mon Sep 17 00:00:00 2001 From: George Mois Date: Tue, 2 Sep 2025 09:27:14 +0300 Subject: [PATCH 07/14] iio: adc: adrv902x: Add external path delay calib Add external path delay initial calibration selection. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index a62be1821176ea..fca7e66aa22123 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -529,6 +529,10 @@ static IIO_DEVICE_ATTR(calibrate_tx_lol_ext_en, 0644, ADRV9025_INIT_CAL | (ADI_ADRV9025_TX_LO_LEAKAGE_EXTERNAL << 8)); +static IIO_DEVICE_ATTR(calibrate_ext_path_delay_en, 0644, + adrv9025_phy_show, adrv9025_phy_store, + ADRV9025_INIT_CAL | (ADI_ADRV9025_EXTERNAL_PATH_DELAY << 8)); + static IIO_DEVICE_ATTR(jesd204_fsm_error, 0444, adrv9025_phy_show, NULL, @@ -560,6 +564,7 @@ static struct attribute *adrv9025_phy_attributes[] = { &iio_dev_attr_calibrate_tx_qec_en.dev_attr.attr, &iio_dev_attr_calibrate_tx_lol_en.dev_attr.attr, &iio_dev_attr_calibrate_tx_lol_ext_en.dev_attr.attr, + &iio_dev_attr_calibrate_ext_path_delay_en.dev_attr.attr, &iio_dev_attr_jesd204_fsm_error.dev_attr.attr, &iio_dev_attr_jesd204_fsm_state.dev_attr.attr, &iio_dev_attr_jesd204_fsm_paused.dev_attr.attr, From 6941c230ab79c709c00e2de1c856df482648911c Mon Sep 17 00:00:00 2001 From: George Mois Date: Thu, 4 Sep 2025 12:46:37 +0300 Subject: [PATCH 08/14] iio: adc: adrv902x: Change calibration mask Add an IIO attribute that allows changing the calibration mask. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index fca7e66aa22123..0441bd513dac3b 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -44,6 +44,7 @@ enum adrv9025_iio_dev_attr { ADRV9025_INIT_CAL, + ADRV9025_CAL_MASK, adrv9025_JESD204_FSM_ERROR, adrv9025_JESD204_FSM_PAUSED, adrv9025_JESD204_FSM_STATE, @@ -341,8 +342,9 @@ static ssize_t adrv9025_phy_store(struct device *dev, 60000; /*60 seconds timeout*/ u8 initCalsError = 0; - phy->cal_mask.channelMask = - phy->adrv9025PostMcsInitInst.initCals.channelMask; + if (!phy->cal_mask.channelMask) + phy->cal_mask.channelMask = + phy->adrv9025PostMcsInitInst.initCals.channelMask; /* Run Init Cals */ ret = adi_adrv9025_InitCalsRun(phy->madDevice, @@ -359,6 +361,16 @@ static ssize_t adrv9025_phy_store(struct device *dev, ret = adrv9025_dev_err(phy); } break; + case ADRV9025_CAL_MASK: + ret = kstrtou64(buf, 0, &val); + if (ret) + break; + + if (val <= 0x0F) + phy->cal_mask.channelMask = val; + else + ret = -EINVAL; + break; case adrv9025_JESD204_FSM_RESUME: if (!phy->jdev) { ret = -ENOTSUPP; @@ -418,6 +430,10 @@ static ssize_t adrv9025_phy_show(struct device *dev, ret = sysfs_emit(buf, "%d\n", !!(phy->cal_mask.calMask & val)); break; + case ADRV9025_CAL_MASK: + ret = sysfs_emit(buf, "0x%x\n", + phy->cal_mask.channelMask); + break; case adrv9025_JESD204_FSM_ERROR: if (!phy->jdev) { ret = -ENOTSUPP; @@ -533,6 +549,9 @@ static IIO_DEVICE_ATTR(calibrate_ext_path_delay_en, 0644, adrv9025_phy_show, adrv9025_phy_store, ADRV9025_INIT_CAL | (ADI_ADRV9025_EXTERNAL_PATH_DELAY << 8)); +static IIO_DEVICE_ATTR(calibrate_mask, 0644, adrv9025_phy_show, + adrv9025_phy_store, ADRV9025_CAL_MASK); + static IIO_DEVICE_ATTR(jesd204_fsm_error, 0444, adrv9025_phy_show, NULL, @@ -565,6 +584,7 @@ static struct attribute *adrv9025_phy_attributes[] = { &iio_dev_attr_calibrate_tx_lol_en.dev_attr.attr, &iio_dev_attr_calibrate_tx_lol_ext_en.dev_attr.attr, &iio_dev_attr_calibrate_ext_path_delay_en.dev_attr.attr, + &iio_dev_attr_calibrate_mask.dev_attr.attr, &iio_dev_attr_jesd204_fsm_error.dev_attr.attr, &iio_dev_attr_jesd204_fsm_state.dev_attr.attr, &iio_dev_attr_jesd204_fsm_paused.dev_attr.attr, @@ -3049,6 +3069,8 @@ static int adrv9025_probe(struct spi_device *spi) if (ret) return adrv9025_dev_err(phy); + phy->cal_mask.channelMask = phy->adrv9025PostMcsInitInst.initCals.channelMask; + adrv9025_clk_register(phy, "-rx_sampl_clk", __clk_get_name(phy->dev_clk), NULL, CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED, RX_SAMPL_CLK); From bca86f7b0a2a956ca1d2f36f02ae3c13a5e3953b Mon Sep 17 00:00:00 2001 From: George Mois Date: Thu, 4 Sep 2025 12:49:28 +0300 Subject: [PATCH 09/14] iio: adc: adrv902x: Load DPD model config Add a bin_attribute for loading the data structure to hold Tx DPD Model initialization parameters, without floats. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 159 +++++++++++++++++++++++++++- drivers/iio/adc/adrv902x/adrv9025.h | 3 + 2 files changed, 161 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index 0441bd513dac3b..4b8be2056d77fa 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -2939,6 +2940,155 @@ static int adrv9025_phy_parse_agc_dt(struct iio_dev *iodev, struct device *dev) &phy->agcConfig->agcSlowloopFastGainChangeBlockEnable, 0, 0, 1); } +static int adrv9025_parse_dpd_coef(struct adrv9025_rf_phy *phy, char *data, u32 size) +{ + u8 dpdNumFeatures = 0, i, j, k, lut; + char *ptr = data; + char coef[10]; + char *line; + int ret; + + while ((line = strsep(&ptr, "\n"))) { + /* skip comment lines or blank lines */ + if (line[0] == '#' || !line[0]) + continue; + + if (line >= data + size) + break; + + if (dpdNumFeatures >= ADI_ADRV9025_MAX_DPD_FEATURES) { + dev_err(&phy->spi->dev, + "ERROR: DPD coefficient table exceeds max number of features (%d)\n", + ADI_ADRV9025_MAX_DPD_FEATURES); + break; + } + + ret = sscanf(line, "%hhu %hhu %hhu %hhu %s", &i, &j, &k, &lut, coef); + if (ret != 5) { + dev_err(&phy->spi->dev, + "ERROR: Malformed DPD coefficient table\n"); + return -EINVAL; + } + + if (i == 1 && j == 1 && k == 0) + k = 1; // for 1x1x0, force k to 1 + + phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].i = i; + phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].j = j; + phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].k = k; + phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].lut = lut; + phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].coeffReal_xM = 0; + phy->dpdModelConfig->dpdFeatures[dpdNumFeatures].coeffImaginary_xM = 0; + + dpdNumFeatures++; + } + + phy->dpdModelConfig->txChannelMask = 0; + phy->dpdModelConfig->dpdNumFeatures = dpdNumFeatures; + + return size; +} + +static ssize_t adrv9025_dpd_coef_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); + struct adrv9025_rf_phy *phy = iio_priv(indio_dev); + int ret; + + /* force a one write() call as it simplifies things a lot */ + if (off) { + dev_err(&phy->spi->dev, "Coefficients must be set in one write() call\n"); + return -EINVAL; + } + + mutex_lock(&phy->lock); + ret = adrv9025_parse_dpd_coef(phy, buf, count); + mutex_unlock(&phy->lock); + + return ret ? ret : count; +} + +static ssize_t adrv9025_dpd_coef_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj)); + struct adrv9025_rf_phy *phy = iio_priv(indio_dev); + ssize_t len = 0; + int idx; + int ret; + + mutex_lock(&phy->lock); + if (!phy->dpdModelConfig) { + mutex_unlock(&phy->lock); + return -ENODATA; + } + + char *kbuf __free(kfree) = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!kbuf) { + mutex_unlock(&phy->lock); + return -ENOMEM; + } + + for (idx = 0; idx < phy->dpdModelConfig->dpdNumFeatures; idx++) { + adi_adrv9025_DpdFeature_v2_t *f = &phy->dpdModelConfig->dpdFeatures[idx]; + + ret = scnprintf(kbuf + len, PAGE_SIZE - len, "%u %u %u %u %d %d\n", + f->i, f->j, f->k, f->lut, + f->coeffReal_xM, f->coeffImaginary_xM); + if (ret < 0) + break; + len += ret; + if (len >= PAGE_SIZE) + break; + } + mutex_unlock(&phy->lock); + + ret = memory_read_from_buffer(buf, count, &off, kbuf, len); + + return ret; +} + +static BIN_ATTR(dpd_coef_model, 0644, + adrv9025_dpd_coef_read, + adrv9025_dpd_coef_write, PAGE_SIZE); + +struct adrv9025_bin_attr_drop { + const struct bin_attribute *attr; + struct device *dev; +}; + +static void adrv9025_remove_bin_file(void *data) +{ + struct adrv9025_bin_attr_drop *drop = data; + + device_remove_bin_file(drop->dev, drop->attr); +} + +static int adrv9025_bin_attr_add(struct device *dev, const struct bin_attribute *attr) +{ + struct adrv9025_bin_attr_drop *drop; + int ret; + + drop = devm_kzalloc(dev, sizeof(*drop), GFP_KERNEL); + if (!drop) + return -ENOMEM; + + drop->attr = attr; + drop->dev = dev; + + ret = device_create_bin_file(dev, attr); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, adrv9025_remove_bin_file, drop); +} + +static const struct bin_attribute *adrv9025_bin_attributes = + &bin_attr_dpd_coef_model; + static int adrv9025_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -2976,6 +3126,9 @@ static int adrv9025_probe(struct spi_device *spi) phy->agcConfig = kzalloc(sizeof(adi_adrv9025_AgcCfg_t), GFP_KERNEL); if (!(phy->agcConfig)) return -ENOMEM; + phy->dpdModelConfig = devm_kzalloc(&spi->dev, sizeof(adi_adrv9025_DpdModelConfig_v2_t), GFP_KERNEL); + if (!(phy->dpdModelConfig)) + return -ENOMEM; mutex_init(&phy->lock); ret = adrv9025_phy_parse_agc_dt(indio_dev, &spi->dev); @@ -3062,7 +3215,7 @@ static int adrv9025_probe(struct spi_device *spi) ret = of_property_read_string(np, "adi,init-profile-name", &name); if (ret) { dev_err(&spi->dev, "error missing dt property: adi,init-profile-name\n"); - return -EINVAL; + return adrv9025_dev_err(phy); } ret = adi_adrv9025_UtilityInitFileLoad(phy->madDevice, name, &phy->adrv9025PostMcsInitInst); @@ -3138,6 +3291,10 @@ static int adrv9025_probe(struct spi_device *spi) } } + ret = adrv9025_bin_attr_add(&indio_dev->dev, adrv9025_bin_attributes); + if (ret) + goto out_iio_device_unregister; + adi_adrv9025_ApiVersionGet(phy->madDevice, &apiVersion); adi_adrv9025_Shutdown(phy->madDevice); adi_adrv9025_HwClose(phy->madDevice); diff --git a/drivers/iio/adc/adrv902x/adrv9025.h b/drivers/iio/adc/adrv902x/adrv9025.h index ee6b626093b172..9d4d43f516ad6b 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.h +++ b/drivers/iio/adc/adrv902x/adrv9025.h @@ -162,6 +162,9 @@ struct adrv9025_rf_phy { bool is_initialized; int spi_device_id; + + /* DPD */ + adi_adrv9025_DpdModelConfig_v2_t *dpdModelConfig; }; int adrv9025_hdl_loopback(struct adrv9025_rf_phy *phy, bool enable); From e9ebcbad5ad2b8d5e500fc7a1c9de44e6914a8c1 Mon Sep 17 00:00:00 2001 From: George Mois Date: Thu, 4 Sep 2025 13:55:50 +0300 Subject: [PATCH 10/14] iio: adc: adrv902x: Select Tx DPD mask Add IIO attribute for selecting the target Tx channel for DPD. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 18 ++++++++++++++++++ drivers/iio/adc/adrv902x/adrv9025.h | 1 + 2 files changed, 19 insertions(+) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index 4b8be2056d77fa..a8d61f475e34e3 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -46,6 +46,7 @@ enum adrv9025_iio_dev_attr { ADRV9025_INIT_CAL, ADRV9025_CAL_MASK, + ADRV9025_DPD_TX_MASK, adrv9025_JESD204_FSM_ERROR, adrv9025_JESD204_FSM_PAUSED, adrv9025_JESD204_FSM_STATE, @@ -372,6 +373,16 @@ static ssize_t adrv9025_phy_store(struct device *dev, else ret = -EINVAL; break; + case ADRV9025_DPD_TX_MASK: + ret = kstrtou64(buf, 0, &val); + if (ret) + break; + + if (val <= 0x0F) + phy->dpdTxChannel = (u8)val; + else + ret = -EINVAL; + break; case adrv9025_JESD204_FSM_RESUME: if (!phy->jdev) { ret = -ENOTSUPP; @@ -435,6 +446,9 @@ static ssize_t adrv9025_phy_show(struct device *dev, ret = sysfs_emit(buf, "0x%x\n", phy->cal_mask.channelMask); break; + case ADRV9025_DPD_TX_MASK: + ret = sysfs_emit(buf, "0x%x\n", phy->dpdTxChannel); + break; case adrv9025_JESD204_FSM_ERROR: if (!phy->jdev) { ret = -ENOTSUPP; @@ -553,6 +567,9 @@ static IIO_DEVICE_ATTR(calibrate_ext_path_delay_en, 0644, static IIO_DEVICE_ATTR(calibrate_mask, 0644, adrv9025_phy_show, adrv9025_phy_store, ADRV9025_CAL_MASK); +static IIO_DEVICE_ATTR(dpd_tx_mask, 0644, adrv9025_phy_show, + adrv9025_phy_store, ADRV9025_DPD_TX_MASK); + static IIO_DEVICE_ATTR(jesd204_fsm_error, 0444, adrv9025_phy_show, NULL, @@ -586,6 +603,7 @@ static struct attribute *adrv9025_phy_attributes[] = { &iio_dev_attr_calibrate_tx_lol_ext_en.dev_attr.attr, &iio_dev_attr_calibrate_ext_path_delay_en.dev_attr.attr, &iio_dev_attr_calibrate_mask.dev_attr.attr, + &iio_dev_attr_dpd_tx_mask.dev_attr.attr, &iio_dev_attr_jesd204_fsm_error.dev_attr.attr, &iio_dev_attr_jesd204_fsm_state.dev_attr.attr, &iio_dev_attr_jesd204_fsm_paused.dev_attr.attr, diff --git a/drivers/iio/adc/adrv902x/adrv9025.h b/drivers/iio/adc/adrv902x/adrv9025.h index 9d4d43f516ad6b..327614ffd98d04 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.h +++ b/drivers/iio/adc/adrv902x/adrv9025.h @@ -165,6 +165,7 @@ struct adrv9025_rf_phy { /* DPD */ adi_adrv9025_DpdModelConfig_v2_t *dpdModelConfig; + adi_adrv9025_TxChannels_e dpdTxChannel; }; int adrv9025_hdl_loopback(struct adrv9025_rf_phy *phy, bool enable); From 1e3a7c431edc3214c3c738f44cb2bcb0ea89bcfb Mon Sep 17 00:00:00 2001 From: George Mois Date: Thu, 4 Sep 2025 15:16:18 +0300 Subject: [PATCH 11/14] iio: adc: adrv902x: Enable DPD reset Add IIO attribute for resetting DPD. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index a8d61f475e34e3..3ddb6bcea60bc8 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -47,6 +47,7 @@ enum adrv9025_iio_dev_attr { ADRV9025_INIT_CAL, ADRV9025_CAL_MASK, ADRV9025_DPD_TX_MASK, + ADRV9025_DPD_RESET, adrv9025_JESD204_FSM_ERROR, adrv9025_JESD204_FSM_PAUSED, adrv9025_JESD204_FSM_STATE, @@ -383,6 +384,19 @@ static ssize_t adrv9025_phy_store(struct device *dev, else ret = -EINVAL; break; + case ADRV9025_DPD_RESET: + ret = kstrtobool(buf, &enable); + if (ret) + break; + + if (enable) { + ret = adi_adrv9025_DpdReset(phy->madDevice, + phy->dpdTxChannel, + ADI_ADRV9025_DPD_RESET_FULL); + if (ret) + ret = adrv9025_dev_err(phy); + } + break; case adrv9025_JESD204_FSM_RESUME: if (!phy->jdev) { ret = -ENOTSUPP; @@ -570,6 +584,9 @@ static IIO_DEVICE_ATTR(calibrate_mask, 0644, adrv9025_phy_show, static IIO_DEVICE_ATTR(dpd_tx_mask, 0644, adrv9025_phy_show, adrv9025_phy_store, ADRV9025_DPD_TX_MASK); +static IIO_DEVICE_ATTR(dpd_reset, 0200, NULL, + adrv9025_phy_store, ADRV9025_DPD_RESET); + static IIO_DEVICE_ATTR(jesd204_fsm_error, 0444, adrv9025_phy_show, NULL, @@ -604,6 +621,7 @@ static struct attribute *adrv9025_phy_attributes[] = { &iio_dev_attr_calibrate_ext_path_delay_en.dev_attr.attr, &iio_dev_attr_calibrate_mask.dev_attr.attr, &iio_dev_attr_dpd_tx_mask.dev_attr.attr, + &iio_dev_attr_dpd_reset.dev_attr.attr, &iio_dev_attr_jesd204_fsm_error.dev_attr.attr, &iio_dev_attr_jesd204_fsm_state.dev_attr.attr, &iio_dev_attr_jesd204_fsm_paused.dev_attr.attr, From 4f497d004483daa0dc2f28ba82c6a2ca548458be Mon Sep 17 00:00:00 2001 From: George Mois Date: Thu, 4 Sep 2025 15:50:24 +0300 Subject: [PATCH 12/14] iio: adc: adrv902x: Add DPD status Add DEBUGF attribut for getting DPD status on each of the 4 Tx channels. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 34 +++++++++++++++++++++++++++++ drivers/iio/adc/adrv902x/adrv9025.h | 4 ++++ 2 files changed, 38 insertions(+) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index 3ddb6bcea60bc8..d808d9139d993a 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -1653,6 +1653,26 @@ static ssize_t adrv9025_tx_lol_status_read(struct adrv9025_rf_phy *phy, txLolStatus.updateCount); } +static ssize_t adrv9025_tx_dpd_status_read(struct adrv9025_rf_phy *phy, + adi_adrv9025_TxChannels_e txChannel, + char *buf) +{ + adi_adrv9025_DpdStatus_v2_t txDpdStatus = { 0 }; + int ret; + + mutex_lock(&phy->lock); + ret = adi_adrv9025_DpdStatusGet_v2(phy->madDevice, txChannel, &txDpdStatus); + mutex_unlock(&phy->lock); + if (ret) + return adrv9025_dev_err(phy); + + return scnprintf(buf, PAGE_SIZE, "err %d %% %d iter cnt %d update cnt %d\n", + txDpdStatus.dpdErrorCode, + txDpdStatus.dpdPercentComplete, + txDpdStatus.dpdIterCount, + txDpdStatus.dpdUpdateCount); +} + static ssize_t adrv9025_debugfs_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -1733,6 +1753,16 @@ static ssize_t adrv9025_debugfs_read(struct file *file, char __user *userbuf, return ret; len = ret; break; + case DBGFS_TX0_DPD_STATUS: + case DBGFS_TX1_DPD_STATUS: + case DBGFS_TX2_DPD_STATUS: + case DBGFS_TX3_DPD_STATUS: + chan = ADI_ADRV9025_TX1 << (entry->cmd - DBGFS_TX0_DPD_STATUS); + ret = adrv9025_tx_dpd_status_read(phy, chan, buf); + if (ret < 0) + return ret; + len = ret; + break; default: val = entry->val; } @@ -1914,6 +1944,10 @@ static int adrv9025_register_debugfs(struct iio_dev *indio_dev) adrv9025_add_debugfs_entry(phy, "tx1_lol_status", DBGFS_TX1_LOL_STATUS); adrv9025_add_debugfs_entry(phy, "tx2_lol_status", DBGFS_TX2_LOL_STATUS); adrv9025_add_debugfs_entry(phy, "tx3_lol_status", DBGFS_TX3_LOL_STATUS); + adrv9025_add_debugfs_entry(phy, "tx0_dpd_status", DBGFS_TX0_DPD_STATUS); + adrv9025_add_debugfs_entry(phy, "tx1_dpd_status", DBGFS_TX1_DPD_STATUS); + adrv9025_add_debugfs_entry(phy, "tx2_dpd_status", DBGFS_TX2_DPD_STATUS); + adrv9025_add_debugfs_entry(phy, "tx3_dpd_status", DBGFS_TX3_DPD_STATUS); for (i = 0; i < phy->adrv9025_debugfs_entry_index; i++) { if (phy->adrv9025_debugfs_entry_index > DBGFS_BIST_TONE) diff --git a/drivers/iio/adc/adrv902x/adrv9025.h b/drivers/iio/adc/adrv902x/adrv9025.h index 327614ffd98d04..1aace181917821 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.h +++ b/drivers/iio/adc/adrv902x/adrv9025.h @@ -54,6 +54,10 @@ enum debugfs_cmd { DBGFS_TX1_LOL_STATUS, DBGFS_TX2_LOL_STATUS, DBGFS_TX3_LOL_STATUS, + DBGFS_TX0_DPD_STATUS, + DBGFS_TX1_DPD_STATUS, + DBGFS_TX2_DPD_STATUS, + DBGFS_TX3_DPD_STATUS, }; enum adrv9025_rx_ext_info { From 600b6efde13a65d0474b379c7afabe0fe679cbf3 Mon Sep 17 00:00:00 2001 From: George Mois Date: Thu, 4 Sep 2025 20:03:41 +0300 Subject: [PATCH 13/14] iio: adc: adrv902x: Add tracking config Add tracking configuration settings. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 92 +++++++++++++++++++++++++++++ drivers/iio/adc/adrv902x/adrv9025.h | 1 + 2 files changed, 93 insertions(+) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index d808d9139d993a..aa6fbbe84acb44 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -48,6 +48,7 @@ enum adrv9025_iio_dev_attr { ADRV9025_CAL_MASK, ADRV9025_DPD_TX_MASK, ADRV9025_DPD_RESET, + ADRV9025_DPD_CONFIG_SET, adrv9025_JESD204_FSM_ERROR, adrv9025_JESD204_FSM_PAUSED, adrv9025_JESD204_FSM_STATE, @@ -397,6 +398,20 @@ static ssize_t adrv9025_phy_store(struct device *dev, ret = adrv9025_dev_err(phy); } break; + case ADRV9025_DPD_CONFIG_SET: + ret = kstrtobool(buf, &enable); + if (ret) + break; + + phy->dpdTrackingConfig->txChannelMask = phy->dpdTxChannel; + + if (enable) { + ret = adi_adrv9025_DpdTrackingConfigSet(phy->madDevice, + phy->dpdTrackingConfig); + if (ret) + ret = adrv9025_dev_err(phy); + } + break; case adrv9025_JESD204_FSM_RESUME: if (!phy->jdev) { ret = -ENOTSUPP; @@ -587,6 +602,9 @@ static IIO_DEVICE_ATTR(dpd_tx_mask, 0644, adrv9025_phy_show, static IIO_DEVICE_ATTR(dpd_reset, 0200, NULL, adrv9025_phy_store, ADRV9025_DPD_RESET); +static IIO_DEVICE_ATTR(dpd_tracking_config_set, 0200, NULL, + adrv9025_phy_store, ADRV9025_DPD_CONFIG_SET); + static IIO_DEVICE_ATTR(jesd204_fsm_error, 0444, adrv9025_phy_show, NULL, @@ -622,6 +640,7 @@ static struct attribute *adrv9025_phy_attributes[] = { &iio_dev_attr_calibrate_mask.dev_attr.attr, &iio_dev_attr_dpd_tx_mask.dev_attr.attr, &iio_dev_attr_dpd_reset.dev_attr.attr, + &iio_dev_attr_dpd_tracking_config_set.dev_attr.attr, &iio_dev_attr_jesd204_fsm_error.dev_attr.attr, &iio_dev_attr_jesd204_fsm_state.dev_attr.attr, &iio_dev_attr_jesd204_fsm_paused.dev_attr.attr, @@ -3010,6 +3029,72 @@ static int adrv9025_phy_parse_agc_dt(struct iio_dev *iodev, struct device *dev) &phy->agcConfig->agcSlowloopFastGainChangeBlockEnable, 0, 0, 1); } +static int adrv9025_phy_parse_dpd_config_dt(struct iio_dev *iodev, struct device *dev) +{ + struct adrv9025_rf_phy *phy = iio_priv(iodev); + struct device_node *np = dev->of_node; + int ret; + + ret = ADRV9025_OF_PROP("adi,dpd-indirect-regularization-value", + &phy->dpdTrackingConfig->dpdIndirectRegularizationValue, 20, 0, 63); + if (ret) + return ret; + + ret = ADRV9025_OF_PROP("adi,dpd-direct-regularization-value", + &phy->dpdTrackingConfig->dpdDirectRegularizationValue, 35, 0, 63); + if (ret) + return ret; + + ret = ADRV9025_OF_PROP("adi,dpd-samples", + &phy->dpdTrackingConfig->dpdSamples, 16384, 4096, 61440); + if (ret) + return ret; + + ret = ADRV9025_OF_PROP("adi,dpd-m-threshold", + &phy->dpdTrackingConfig->dpdMThreshold, 2920, 0, 32767); + if (ret) + return ret; + + ret = ADRV9025_OF_PROP("adi,dpd-peak-search-window-size", + &phy->dpdTrackingConfig->dpdPeakSearchWindowSize, 65535, 0, 16777215); + if (ret) + return ret; + + ret = ADRV9025_OF_PROP("adi,dpd-update-mode", + &phy->dpdTrackingConfig->dpdUpdateMode, 0, 0, 2); + if (ret) + return ret; + + ret = ADRV9025_OF_PROP("adi,dpd-min-avg-signal-level", + &phy->dpdTrackingConfig->minAvgSignalLevel, 519, 0, 65535); + if (ret) + return ret; + + ret = ADRV9025_OF_PROP("adi,dpd-mu", + &phy->dpdTrackingConfig->dpdMu, 50, 0, 100); + if (ret) + return ret; + + ret = ADRV9025_OF_PROP("adi,dpd-min-avg-signal-level-orx", + &phy->dpdTrackingConfig->minAvgSignalLevelOrx, 519, 0, 65535); + if (ret) + return ret; + + ret = ADRV9025_OF_PROP("adi,dpd-filter-sel", + &phy->dpdTrackingConfig->dpdFilterSel, 0, 0, 1); + if (ret) + return ret; + + ret = ADRV9025_OF_PROP("adi,dpd-enable-direct-learning", + &phy->dpdTrackingConfig->enableDirectLearning, 0, 0, 1); + if (ret) + return ret; + + return ADRV9025_OF_PROP("adi,dpd-indirect-regularization-low-power-value", + &phy->dpdTrackingConfig->dpdIndirectRegularizationLowPowerValue, + 20, 0, 63); +} + static int adrv9025_parse_dpd_coef(struct adrv9025_rf_phy *phy, char *data, u32 size) { u8 dpdNumFeatures = 0, i, j, k, lut; @@ -3199,12 +3284,19 @@ static int adrv9025_probe(struct spi_device *spi) phy->dpdModelConfig = devm_kzalloc(&spi->dev, sizeof(adi_adrv9025_DpdModelConfig_v2_t), GFP_KERNEL); if (!(phy->dpdModelConfig)) return -ENOMEM; + phy->dpdTrackingConfig = devm_kzalloc(&spi->dev, sizeof(adi_adrv9025_DpdTrackingConfig_t), GFP_KERNEL); + if (!(phy->dpdTrackingConfig)) + return -ENOMEM; mutex_init(&phy->lock); ret = adrv9025_phy_parse_agc_dt(indio_dev, &spi->dev); if (ret) return ret; + ret = adrv9025_phy_parse_dpd_config_dt(indio_dev, &spi->dev); + if (ret) + return ret; + priv = jesd204_dev_priv(jdev); priv->phy = phy; diff --git a/drivers/iio/adc/adrv902x/adrv9025.h b/drivers/iio/adc/adrv902x/adrv9025.h index 1aace181917821..59fe10c7b008df 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.h +++ b/drivers/iio/adc/adrv902x/adrv9025.h @@ -170,6 +170,7 @@ struct adrv9025_rf_phy { /* DPD */ adi_adrv9025_DpdModelConfig_v2_t *dpdModelConfig; adi_adrv9025_TxChannels_e dpdTxChannel; + adi_adrv9025_DpdTrackingConfig_t *dpdTrackingConfig; }; int adrv9025_hdl_loopback(struct adrv9025_rf_phy *phy, bool enable); From 06019018b31f2a556dc67b807cb305c231fda6b0 Mon Sep 17 00:00:00 2001 From: George Mois Date: Thu, 4 Sep 2025 20:07:42 +0300 Subject: [PATCH 14/14] iio: adc: adrv902x: Add DPD enable functionality Add IIO attribute for enabling DPD. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 15 +++++++++++++++ drivers/iio/adc/adrv902x/adrv9025.h | 1 + 2 files changed, 16 insertions(+) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index aa6fbbe84acb44..decf81e39861df 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -976,6 +976,11 @@ static ssize_t adrv9025_phy_tx_read(struct iio_dev *indio_dev, ret = adi_adrv9025_TrackingCalsEnableGet(phy->madDevice, &mask); val = !!(tmask & mask); break; + case TX_DPD: + tmask = ADI_ADRV9025_TRACK_TX1_DPD << chan->channel; + ret = adi_adrv9025_TrackingCalsEnableGet(phy->madDevice, &mask); + val = !!(tmask & mask); + break; case TX_RF_BANDWIDTH: val = phy->deviceInitStruct.tx.txChannelCfg[chan->channel] .profile.rfBandwidth_kHz * @@ -1036,6 +1041,15 @@ static ssize_t adrv9025_phy_tx_write(struct iio_dev *indio_dev, if (ret) ret = adrv9025_dev_err(phy); break; + case TX_DPD: + mask = ADI_ADRV9025_TRACK_TX1_DPD << chan->channel; + + ret = adi_adrv9025_TrackingCalsEnableSet(phy->madDevice, mask, + enable ? ADI_ADRV9025_TRACKING_CAL_ENABLE : + ADI_ADRV9025_TRACKING_CAL_DISABLE); + if (ret) + ret = adrv9025_dev_err(phy); + break; default: ret = -EINVAL; } @@ -1172,6 +1186,7 @@ static struct iio_chan_spec_ext_info adrv9025_phy_tx_ext_info[] = { _ADRV9025_EXT_TX_INFO("quadrature_tracking_en", TX_QEC), _ADRV9025_EXT_TX_INFO("lo_leakage_tracking_en", TX_LOL), _ADRV9025_EXT_TX_INFO("rf_bandwidth", TX_RF_BANDWIDTH), + _ADRV9025_EXT_TX_INFO("dpd_en", TX_DPD), {}, }; static int adrv9025_gainindex_to_gain(struct adrv9025_rf_phy *phy, int channel, diff --git a/drivers/iio/adc/adrv902x/adrv9025.h b/drivers/iio/adc/adrv902x/adrv9025.h index 59fe10c7b008df..9c66193c29c1ae 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.h +++ b/drivers/iio/adc/adrv902x/adrv9025.h @@ -72,6 +72,7 @@ enum adrv9025_tx_ext_info { TX_QEC, TX_LOL, TX_RF_BANDWIDTH, + TX_DPD, }; enum adrv9025_iio_voltage_in {