Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-nls.dts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@

adi,device-profile-name = "ActiveUseCase_NLS.profile";

/*
* ORx_CTRL pins for dual-channel 4-pin mode (orxEnableMode=4).
* HDL index + 78: A=54->132, B=53->131, C=52->130, D=51->129.
* A/C = side-A/side-B enable, B/D = side-A/side-B channel select.
*/
orx-ctrl-a-gpios = <&gpio 132 0>;
orx-ctrl-b-gpios = <&gpio 131 0>;
orx-ctrl-c-gpios = <&gpio 130 0>;
orx-ctrl-d-gpios = <&gpio 129 0>;

Comment thread
stefpopa marked this conversation as resolved.
jesd204-device;
#jesd204-cells = <2>;
jesd204-top-device = <0>; /* This is the TOP device */
Expand Down
148 changes: 143 additions & 5 deletions drivers/iio/adc/adrv902x/adrv9025.c
Original file line number Diff line number Diff line change
Expand Up @@ -1081,17 +1081,69 @@
}

static const char * const adrv9025_obs1_rx_port[] = {
"OFF", "ORX1_ON_ORX2_OFF", "ORX1_OFF_ORX2_ON",
"ORX1_ON_ORX2_OFF", "ORX1_OFF_ORX2_ON",
};

static const char * const adrv9025_obs2_rx_port[] = {
"OFF", "ORX3_ON_ORX4_OFF", "ORX3_OFF_ORX4_ON",
"ORX3_ON_ORX4_OFF", "ORX3_OFF_ORX4_ON",
};

static const u8 ad9371_obs_rx_port_lut[] = {
0x00, BIT(4), BIT(5)
BIT(4), BIT(5)
};

/*
* True when the device is configured for dual-channel 4-pin ORx mode
* (orxEnableMode=4) AND the ORX_CTRL pins are wired in the device tree. In
* this mode ORx enable/select is driven by the ORX_CTRL pins (A/C = side-A/
* side-B enable, B/D = side-A/side-B channel select), not the 0x106 SPI
* enable. The enable mode comes from the init profile cached at probe.
*/
static bool adrv9025_orx_dual_4pin(struct adrv9025_rf_phy *phy)
{
return phy->orx_ctrl_a_gpio && phy->orx_ctrl_c_gpio &&
phy->adrv9025PostMcsInitInst.radioCtrlInit.radioCtrlModeCfg
.orxRadioCtrlModeCfg.orxEnableMode ==
ADI_ADRV9025_ORX_EN_DUAL_CH_4PIN_MODE;
}

/*
* Re-assert the framer-1 ADC sample crossbar to split routing. The on-chip
* stream processor collapses it on every ORx enable edge, so this must run
* AFTER the enable change. conv0/1 = side-A I/Q, conv2/3 = side-B I/Q.
*/
static int adrv9025_orx_xbar_reassert(struct adrv9025_rf_phy *phy)
{
int ret;

ret = adi_adrv9025_SpiFieldWrite(phy->madDevice, 0x7000,
ADI_ADRV9025_ADC_ORX1_I, 0x7F, 0);
if (ret)
return ret;

ret = adi_adrv9025_SpiFieldWrite(phy->madDevice, 0x7001,
ADI_ADRV9025_ADC_ORX1_Q, 0x7F, 0);
if (ret)
return ret;

ret = adi_adrv9025_SpiFieldWrite(phy->madDevice, 0x7002,
ADI_ADRV9025_ADC_ORX2_I, 0x7F, 0);
if (ret)
return ret;

ret = adi_adrv9025_SpiFieldWrite(phy->madDevice, 0x7003,
ADI_ADRV9025_ADC_ORX2_Q, 0x7F, 0);
return ret;
}

/*
* rf_port_select for the obs channels. In dual-channel 4-pin mode this is
* SELECT-ONLY: it drives the side's channel-select pin (B for side-A, D for
* side-B) to pick which ORx of the pair is observed. It does NOT enable the
* side - enable is owned by the _en attribute (write_raw). mode is the enum
* index: 0 = first ORx of the pair (sel low), 1 = second ORx (sel high).
* On boards without the ORX_CTRL pins it falls back to legacy SPI selection.
*/
static int adrv9025_set_obs_rx_path(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, u32 mode)
{
Expand All @@ -1101,6 +1153,24 @@
u32 val = 0;
int ret;

if (adrv9025_orx_dual_4pin(phy)) {
struct gpio_desc *sel_gpio = (chan->channel > CHAN_OBS_RX1) ?
phy->orx_ctrl_d_gpio :
phy->orx_ctrl_b_gpio;

/* select line: mode 1 = second ORx of the pair => assert */
if (sel_gpio)
gpiod_set_value_cansleep(sel_gpio, mode ? 1 : 0);

/* selecting changes routing; re-assert the split crossbar */
ret = adrv9025_orx_xbar_reassert(phy);
if (ret)
return adrv9025_dev_err(phy);

return 0;
}

/* Legacy SPI-mode select+enable (boards without ORX_CTRL pins). */
ret = adi_adrv9025_RxTxEnableGet(phy->madDevice, &rxchan,
&txchan);
if (ret)
Expand All @@ -1127,8 +1197,22 @@
struct adrv9025_rf_phy *phy = iio_priv(indio_dev);
u32 rxchan = 0, txchan = 0;
int shift_right = CHAN_OBS_RX1;
int pair;
Comment thread
stefpopa marked this conversation as resolved.
int ret;

/*
* In dual-4-pin mode selection is held by the channel-select pin, so
* read it back directly. The output gpio returns the last value set.
* 0 = first ORx of the pair, 1 = second ORx (matches the 2-item enum).
*/
if (adrv9025_orx_dual_4pin(phy)) {
struct gpio_desc *sel_gpio = (chan->channel > CHAN_OBS_RX1) ?
phy->orx_ctrl_d_gpio :
phy->orx_ctrl_b_gpio;

return (sel_gpio && gpiod_get_value_cansleep(sel_gpio)) ? 1 : 0;
}

ret = adi_adrv9025_RxTxEnableGet(phy->madDevice, &rxchan,
&txchan);
if (ret)
Expand All @@ -1137,7 +1221,16 @@
if (chan->channel > CHAN_OBS_RX1)
shift_right = CHAN_OBS_RX3;

return rxchan >> shift_right & 0x3;
/*
* Each ORx pair occupies two adjacent enable bits (lower/upper). The
* rf_port_select enum is now SELECT-only with two items: index 0 =
* lower ORx, index 1 = upper ORx. Map the upper enable bit to index 1
* and everything else (lower-on or disabled) to index 0 so the read
* always lands on a valid enum item.
*/
pair = rxchan >> shift_right & 0x3;

return (pair & 0x2) ? 1 : 0;
}

static const struct iio_enum adrv9025_rf_obs1_rx_port_available = {
Expand Down Expand Up @@ -1267,7 +1360,17 @@
if (chan->output)
*val = !!(txchan & (ADI_ADRV9025_TX1 << chan->channel));
else
if (chan->channel >= CHAN_OBS_RX1) {
if (chan->channel >= CHAN_OBS_RX1 &&
adrv9025_orx_dual_4pin(phy)) {
/* enable is held by the side ENABLE pin (A/C) */
struct gpio_desc *en_gpio =
(chan->channel > CHAN_OBS_RX1) ?
phy->orx_ctrl_c_gpio :
phy->orx_ctrl_a_gpio;

*val = en_gpio ?
!!gpiod_get_value_cansleep(en_gpio) : 0;
} else if (chan->channel >= CHAN_OBS_RX1) {
chan_no = chan->channel;
if (chan_no == CHAN_OBS_RX2)
chan_no += 1;
Expand Down Expand Up @@ -1402,6 +1505,28 @@
txchan |= (ADI_ADRV9025_TX1 << chan->channel);
else
txchan &= ~(ADI_ADRV9025_TX1 << chan->channel);
} else if (chan->channel >= CHAN_OBS_RX1 &&
adrv9025_orx_dual_4pin(phy)) {
/*
* Dual-channel 4-pin mode: the ORx side ENABLE is owned
* by the ORX_CTRL pin (A for side-A/obs1, C for side-B/
* obs2), not the 0x106 SPI enable. _en drives the pin;
* which ORx of the pair is picked by rf_port_select (the
* select pin). Re-assert the split crossbar after the
* enable edge (the stream collapses it on that edge).
*/
struct gpio_desc *en_gpio =
(chan->channel > CHAN_OBS_RX1) ?
phy->orx_ctrl_c_gpio : phy->orx_ctrl_a_gpio;

gpiod_set_value_cansleep(en_gpio, val ? 1 : 0);

if (val) {
ret = adrv9025_orx_xbar_reassert(phy);
if (ret)
ret = adrv9025_dev_err(phy);
}
break;
} else {
chan_no = chan->channel;
if (chan_no == CHAN_OBS_RX2)
Expand Down Expand Up @@ -2317,7 +2442,7 @@
static long adrv9025_bb_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct adrv9025_clock *clk_priv = to_clk_priv(hw);

Check warning on line 2445 in drivers/iio/adc/adrv902x/adrv9025.c

View workflow job for this annotation

GitHub Actions / build_llvm_x86_64 / build

clang_analyzer: Value stored to 'clk_priv' during its initialization is never read [deadcode.DeadStores] 2445 | struct adrv9025_clock *clk_priv = to_clk_priv(hw); | ^~~~~~~~ ~~~~~~~~~~~~~~~

dev_dbg(&clk_priv->spi->dev, "%s: Rate %lu Hz", __func__, rate);

Expand Down Expand Up @@ -2455,7 +2580,7 @@
static int adrv9025_jesd204_link_pre_setup(struct jesd204_dev *jdev,
enum jesd204_state_op_reason reason)
{
struct device *dev = jesd204_dev_to_device(jdev);

Check warning on line 2583 in drivers/iio/adc/adrv902x/adrv9025.c

View workflow job for this annotation

GitHub Actions / build_llvm_x86_64 / build

clang_analyzer: Value stored to 'dev' during its initialization is never read [deadcode.DeadStores] 2583 | struct device *dev = jesd204_dev_to_device(jdev); | ^~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct adrv9025_jesd204_priv *priv = jesd204_dev_priv(jdev);
struct adrv9025_rf_phy *phy = priv->phy;
long dev_clk;
Expand Down Expand Up @@ -2490,7 +2615,7 @@
enum jesd204_state_op_reason reason,
struct jesd204_link *lnk)
{
struct device *dev = jesd204_dev_to_device(jdev);

Check warning on line 2618 in drivers/iio/adc/adrv902x/adrv9025.c

View workflow job for this annotation

GitHub Actions / build_llvm_x86_64 / build

clang_analyzer: Value stored to 'dev' during its initialization is never read [deadcode.DeadStores] 2618 | struct device *dev = jesd204_dev_to_device(jdev); | ^~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct adrv9025_jesd204_priv *priv = jesd204_dev_priv(jdev);
struct adrv9025_rf_phy *phy = priv->phy;
adi_adrv9025_FrmCfg_t *framer = NULL;
Expand Down Expand Up @@ -2600,7 +2725,7 @@
static int adrv9025_jesd204_link_setup(struct jesd204_dev *jdev,
enum jesd204_state_op_reason reason)
{
struct device *dev = jesd204_dev_to_device(jdev);

Check warning on line 2728 in drivers/iio/adc/adrv902x/adrv9025.c

View workflow job for this annotation

GitHub Actions / build_llvm_x86_64 / build

clang_analyzer: Value stored to 'dev' during its initialization is never read [deadcode.DeadStores] 2728 | struct device *dev = jesd204_dev_to_device(jdev); | ^~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct adrv9025_jesd204_priv *priv = jesd204_dev_priv(jdev);
struct adrv9025_rf_phy *phy = priv->phy;
int ret;
Expand Down Expand Up @@ -2658,7 +2783,7 @@
static int adrv9025_jesd204_setup_stage1(struct jesd204_dev *jdev,
enum jesd204_state_op_reason reason)
{
struct device *dev = jesd204_dev_to_device(jdev);

Check warning on line 2786 in drivers/iio/adc/adrv902x/adrv9025.c

View workflow job for this annotation

GitHub Actions / build_llvm_x86_64 / build

clang_analyzer: Value stored to 'dev' during its initialization is never read [deadcode.DeadStores] 2786 | struct device *dev = jesd204_dev_to_device(jdev); | ^~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct adrv9025_jesd204_priv *priv = jesd204_dev_priv(jdev);
struct adrv9025_rf_phy *phy = priv->phy;
int ret, i;
Expand Down Expand Up @@ -2697,7 +2822,7 @@
static int adrv9025_jesd204_setup_stage2(struct jesd204_dev *jdev,
enum jesd204_state_op_reason reason)
{
struct device *dev = jesd204_dev_to_device(jdev);

Check warning on line 2825 in drivers/iio/adc/adrv902x/adrv9025.c

View workflow job for this annotation

GitHub Actions / build_llvm_x86_64 / build

clang_analyzer: Value stored to 'dev' during its initialization is never read [deadcode.DeadStores] 2825 | struct device *dev = jesd204_dev_to_device(jdev); | ^~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct adrv9025_jesd204_priv *priv = jesd204_dev_priv(jdev);
struct adrv9025_rf_phy *phy = priv->phy;
int ret;
Expand Down Expand Up @@ -2731,7 +2856,7 @@
enum jesd204_state_op_reason reason,
struct jesd204_link *lnk)
{
struct device *dev = jesd204_dev_to_device(jdev);

Check warning on line 2859 in drivers/iio/adc/adrv902x/adrv9025.c

View workflow job for this annotation

GitHub Actions / build_llvm_x86_64 / build

clang_analyzer: Value stored to 'dev' during its initialization is never read [deadcode.DeadStores] 2859 | struct device *dev = jesd204_dev_to_device(jdev); | ^~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct adrv9025_jesd204_priv *priv = jesd204_dev_priv(jdev);
struct adrv9025_rf_phy *phy = priv->phy;
int ret;
Expand Down Expand Up @@ -2839,7 +2964,7 @@
enum jesd204_state_op_reason reason,
struct jesd204_link *lnk)
{
struct device *dev = jesd204_dev_to_device(jdev);

Check warning on line 2967 in drivers/iio/adc/adrv902x/adrv9025.c

View workflow job for this annotation

GitHub Actions / build_llvm_x86_64 / build

clang_analyzer: Value stored to 'dev' during its initialization is never read [deadcode.DeadStores] 2967 | struct device *dev = jesd204_dev_to_device(jdev); | ^~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct adrv9025_jesd204_priv *priv = jesd204_dev_priv(jdev);
struct adrv9025_rf_phy *phy = priv->phy;
int ret;
Expand Down Expand Up @@ -2894,7 +3019,7 @@
enum jesd204_state_op_reason reason,
struct jesd204_link *lnk)
{
struct device *dev = jesd204_dev_to_device(jdev);

Check warning on line 3022 in drivers/iio/adc/adrv902x/adrv9025.c

View workflow job for this annotation

GitHub Actions / build_llvm_x86_64 / build

clang_analyzer: Value stored to 'dev' during its initialization is never read [deadcode.DeadStores] 3022 | struct device *dev = jesd204_dev_to_device(jdev); | ^~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct adrv9025_jesd204_priv *priv = jesd204_dev_priv(jdev);
struct adrv9025_rf_phy *phy = priv->phy;
int ret;
Expand Down Expand Up @@ -2969,7 +3094,7 @@
static int adrv9025_jesd204_post_running_stage(struct jesd204_dev *jdev,
enum jesd204_state_op_reason reason)
{
struct device *dev = jesd204_dev_to_device(jdev);

Check warning on line 3097 in drivers/iio/adc/adrv902x/adrv9025.c

View workflow job for this annotation

GitHub Actions / build_llvm_x86_64 / build

clang_analyzer: Value stored to 'dev' during its initialization is never read [deadcode.DeadStores] 3097 | struct device *dev = jesd204_dev_to_device(jdev); | ^~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct adrv9025_jesd204_priv *priv = jesd204_dev_priv(jdev);
struct adrv9025_rf_phy *phy = priv->phy;
int ret;
Expand Down Expand Up @@ -3644,6 +3769,19 @@
phy->linux_hal.reset_gpio =
devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW);

/*
* Optional ORx_CTRL pins for dual-channel 4-pin mode (orxEnableMode=4).
* Absent on boards/profiles using SPI or single-channel ORx modes.
*/
phy->orx_ctrl_a_gpio =
devm_gpiod_get_optional(&spi->dev, "orx-ctrl-a", GPIOD_OUT_LOW);
phy->orx_ctrl_b_gpio =
devm_gpiod_get_optional(&spi->dev, "orx-ctrl-b", GPIOD_OUT_LOW);
phy->orx_ctrl_c_gpio =
devm_gpiod_get_optional(&spi->dev, "orx-ctrl-c", GPIOD_OUT_LOW);
phy->orx_ctrl_d_gpio =
devm_gpiod_get_optional(&spi->dev, "orx-ctrl-d", GPIOD_OUT_LOW);

ret = clk_prepare_enable(phy->dev_clk);
if (ret)
return ret;
Expand Down
9 changes: 9 additions & 0 deletions drivers/iio/adc/adrv902x/adrv9025.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,15 @@ struct adrv9025_rf_phy {

struct gpio_desc *sysref_req_gpio;

/*
* ORx_CTRL pins for dual-channel 4-pin mode (orxEnableMode=4):
* A/C = side-A/side-B enable, B/D = side-A/side-B channel select.
*/
struct gpio_desc *orx_ctrl_a_gpio;
struct gpio_desc *orx_ctrl_b_gpio;
struct gpio_desc *orx_ctrl_c_gpio;
struct gpio_desc *orx_ctrl_d_gpio;

u8 device_id;

u32 adrv9025_debugfs_entry_index;
Expand Down
2 changes: 1 addition & 1 deletion firmware/ActiveUtilInit.profile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"rxChannelMask": 255
},
"orxRadioCtrlModeCfg": {
"orxEnableMode": 0,
"orxEnableMode": 4,
Comment thread
RaulGeo289 marked this conversation as resolved.
"orxPinSelectSettlingDelay_armClkCycles": 0,
"singleChannel1PinModeOrxSel": 0,
"singleChannel2PinModeLowOrxSel": 0,
Expand Down
Loading