Skip to content

Commit 2dbfe69

Browse files
committed
fix(adrv937x): align DT with Kuiper reference (capture still deferred)
Align ``ADRV937xBuilder``'s output for ``zc706+adrv9371`` with the working SD-card devicetree shipped by Kuiper so the AD9528, axi-adxcvr, axi-jesd204, and AD9371 drivers all probe and reach JESD ``opt_post_running_stage`` cleanly on real hardware. Full state progression verified on bq via hw CI: before → after -------------------------------------------------------------- RESET Failed → reset succeeds Requesting device clock 122.88 MHz → AD9528 drives dev_clk failed got 0 (channel@13 / FMC_CLK) jesd204 link_pre_setup -ENODEV → opt_post_running_stage cycling clean on all 3 links axi-adxcvr / axi-jesd204-rx → both probe (``AXI- deferred probe pending JESD204-RX (1.07.a) at 0x44AA0000...``) cf_axi_adc probe stuck → probed ADC AD9371 MASTER AD9371 ARM uninitialized → Firmware 5.2.2 API 1.5.2.3566 initialized JESD clocks 245.76 / 122.88 → 122.88 / 122.88 match mismatch measured Changes: - ``adidt/xsa/builders/adrv937x.py``: - Emit AD9528 ``channel@{1,3,12,13}`` with correct divider + signal-source + extended-name (DEV_CLK, FMC_CLK, DEV_SYSREF, FMC_SYSREF). - Wire AD9528 ``reset-gpios = <&gpio0 113 0>``. - Mark AD9528 as ``jesd204-device`` / ``#jesd204-cells = <2>`` / ``jesd204-sysref-provider`` / ``adi,jesd204-max-sysref- frequency-hz`` — required for the Mykonos driver's ``opt_post_running_stage`` callback to find the sysref provider in the graph. - Correct AD9371 GPIO pins: ``trx_reset_gpio`` 130 → 106, ``trx_sysref_req_gpio`` 136 → 112, new ``ad9528_reset_gpio`` = 113. - Add AD9528 as link-2 input on the AD9371's ``jesd204-inputs``. - Add the three ``adi,{sys,out}-clk-select`` + ``adi,use-lpm-enable`` props on ``axi-adxcvr`` — without these the platform driver defers probe indefinitely. - Drop emission of ``_DEFAULT_MYKONOS_PROFILE_PROPS`` as a builder-level constant. Move the profile values into ``adidt/xsa/profiles/adrv937x_zc706.json`` as a ``trx_profile_props`` list, keeping the builder default empty. The profile has to match the HDL's compile-time ``TX_JESD_*`` / ``RX_JESD_*`` knobs (see ``analogdevicesinc/hdl/projects/adrv937x/zc706/README``), which is board-build-specific. - ``adidt/xsa/profiles/adrv937x_zc706.json``: - ``trx_reset_gpio`` → 106, ``trx_sysref_req_gpio`` → 112, new ``ad9528_reset_gpio`` → 113. - ``misc_clk_hz`` 245_760_000 → 122_880_000 (physical FMC clock on this board; the wrong 245.76 MHz declared rate triggered the JESD link-clock measured/reported mismatch that kept the link disabled). - New ``trx_profile_props`` list carrying 51 Mykonos ``adi,{rx,obs,tx,sniffer}-profile-*`` + ``adi,clocks-*`` lines copied verbatim from bq's working SD-card DT. - ``adidt/xsa/profiles.py``: accept ``ad9528_reset_gpio`` + ``ad9528_jesd204_max_sysref_hz`` in the ``adrv9009_board`` schema allowlist so JSON loads don't reject the new keys. - ``adidt/devices/clocks/ad952x.py``: optional ``jesd204_sysref_provider`` + ``jesd204_max_sysref_hz`` fields on ``AD9528_1`` that ``extra_dt_lines`` emits when set. Opt-in so the ADRV9009/ZCU102 path is unaffected. - ``adidt/eval/adrv937x_fmc.py``: System-API side GPIO sync (130/136 → 106/112) to keep the dts-parity test green. - ``test/devices/fixtures/adrv9371_zc706_xsa_reference.dts``: regenerated from the new builder output. Still-open blocker (documented in the hw test's TODO): ad9371 spi1.1: ILAS mismatch: c7f8 ILAS {lanes per converter, scrambling, octets per frame, frames per multiframe, number of converters, sample resolution, control bits per sample} did not match Our ``axi-jesd204-{tx,rx}`` overlays already emit the exact framing (M=4 L=4 F=2 / M=4 L=2 F=4, Np=16, CS=2) that the HDL README documents as default, and the same builder path works on ADRV9009/ZCU102 — so the remaining gap is that the ``trx_profile_props`` shipped in the profile JSON (copied from the SD-card DT as a starting point) implies a different JESD framing than the XSA's HDL bitstream compiles in. Pairing the profile to the HDL is the single-file drop-in fix that closes this out; flagged in the TODO with concrete next steps (iio- oscilloscope regeneration vs ``trx_profile_props`` JSON override). Unit tests: 449 passed, 13 skipped, 4 xfailed.
1 parent 252bd3c commit 2dbfe69

7 files changed

Lines changed: 402 additions & 19 deletions

File tree

adidt/devices/clocks/ad952x.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,20 @@ def extra_dt_lines(self, context: dict | None = None) -> list[str]:
121121
lines: list[str] = []
122122
for gl in self.gpio_lines:
123123
lines.append(f"{gl.prop} = <&{gl.controller} {int(gl.index)} 0>;")
124+
if self.jesd204_sysref_provider:
125+
lines.append("jesd204-device;")
126+
lines.append("#jesd204-cells = <2>;")
127+
lines.append("jesd204-sysref-provider;")
128+
if self.jesd204_max_sysref_hz is not None:
129+
lines.append(
130+
f"adi,jesd204-max-sysref-frequency-hz = <{int(self.jesd204_max_sysref_hz)}>;"
131+
)
124132
return lines
125133

126134
# Both device families share these fields:
127135
gpio_lines: Annotated[list[_GpioLine], DtSkip()] = Field(default_factory=list)
136+
jesd204_sysref_provider: Annotated[bool, DtSkip()] = False
137+
jesd204_max_sysref_hz: Annotated[int | None, DtSkip()] = None
128138

129139

130140
class AD9523_1(_AD952xBase):

adidt/eval/adrv937x_fmc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ def __init__(self, *, reference_frequency: int = 122_880_000) -> None:
4242
label="trx0_ad9371",
4343
node_name_base="ad9371-phy",
4444
compatible_strings=["adi,ad9371"],
45-
reset_gpio=130,
46-
sysref_req_gpio=136,
45+
reset_gpio=106,
46+
sysref_req_gpio=112,
4747
)
4848

4949
def _named(self, name: str) -> ClockOutput:

adidt/xsa/builders/adrv937x.py

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,48 @@
1616
JesdLinkModel,
1717
)
1818
from ...devices.clocks import AD9528_1
19+
from ...devices.clocks.ad952x import AD9528_1Channel, _GpioLine
1920
from ...devices.fpga_ip import build_jesd204_overlay_ctx
2021
from ...model.renderer import BoardModelRenderer
2122
from ..topology import XsaTopology
2223

2324
_ADRV937X_KEYWORDS = ("ad9371", "adrv937")
2425

2526

27+
# Default Mykonos (AD9371) initial device profile — baked into the DT
28+
# as ``adi,*-profile-*`` / ``adi,clocks-*`` properties on
29+
# ``ad9371-phy@1`` when the caller doesn't supply a per-profile
30+
# override.
31+
#
32+
# The AD9371 driver consumes these at probe to configure the Mykonos
33+
# ARM before userspace ever sees the chip; the values must encode a
34+
# configuration whose JESD framing (M, L, F, K, Np, CS, CF) matches
35+
# the FPGA's compiled-in ``axi-jesd204-{tx,rx}`` overlays, otherwise
36+
# the deframer reports an ILAS mismatch at link-up and the TPL DMA
37+
# sits idle. Because "matching" is HDL-build-specific (see the
38+
# ``TX_JESD_*`` / ``RX_JESD_*`` knobs in
39+
# ``analogdevicesinc/hdl/projects/adrv937x/zc706/README.md``), this
40+
# module ships an empty default and expects the per-board profile
41+
# JSON (e.g. ``adidt/xsa/profiles/adrv937x_zc706.json``) to supply a
42+
# full ``trx_profile_props`` list. Callers without a profile JSON
43+
# can still override via ``board_cfg["trx_profile_props"]``.
44+
_DEFAULT_MYKONOS_PROFILE_PROPS: tuple[str, ...] = ()
45+
46+
47+
# AD9528 output-channel map baked into the DT so the clock distributor
48+
# driver configures dividers + signal sources before the Mykonos driver
49+
# requests ``dev_clk`` at 122.88 MHz. Each AD9528_1Channel renders to
50+
# an ``adi,channels/channel@N`` subnode. Values mirror the Kuiper
51+
# zc706-adrv9371 reference DT.
52+
def _default_ad9528_channels() -> dict[int, AD9528_1Channel]:
53+
return {
54+
13: AD9528_1Channel(id=13, name="DEV_CLK", divider=10, signal_source=0),
55+
1: AD9528_1Channel(id=1, name="FMC_CLK", divider=10, signal_source=0),
56+
12: AD9528_1Channel(id=12, name="DEV_SYSREF", divider=10, signal_source=2),
57+
3: AD9528_1Channel(id=3, name="FMC_SYSREF", divider=10, signal_source=2),
58+
}
59+
60+
2661
def _is_adrv937x_name(value: str) -> bool:
2762
lower = value.lower()
2863
return any(key in lower for key in _ADRV937X_KEYWORDS)
@@ -186,8 +221,14 @@ def build_model(
186221
spi_bus = str(board_cfg.get("spi_bus", "spi0"))
187222
clk_cs = int(board_cfg.get("clk_cs", 0))
188223
trx_cs = int(board_cfg.get("trx_cs", 1))
189-
trx_reset_gpio = int(board_cfg.get("trx_reset_gpio", 130))
190-
trx_sysref_req_gpio = int(board_cfg.get("trx_sysref_req_gpio", 136))
224+
# GPIO defaults match the Kuiper ``zc706-adrv9371`` reference DT
225+
# (EMIO pin numbering relative to Zynq GPIO controller base=54):
226+
# - AD9371 reset = 106 (``trx_reset_gpio``)
227+
# - AD9371 sysref = 112 (``trx_sysref_req_gpio``)
228+
# - AD9528 reset = 113 (``ad9528_reset_gpio``)
229+
trx_reset_gpio = int(board_cfg.get("trx_reset_gpio", 106))
230+
trx_sysref_req_gpio = int(board_cfg.get("trx_sysref_req_gpio", 112))
231+
ad9528_reset_gpio = int(board_cfg.get("ad9528_reset_gpio", 113))
191232
trx_spi_max_frequency = int(board_cfg.get("trx_spi_max_frequency", 25000000))
192233
ad9528_vcxo_freq = int(board_cfg.get("ad9528_vcxo_freq", 122880000))
193234

@@ -208,6 +249,23 @@ def build_model(
208249
label=clock_chip_label,
209250
spi_max_hz=10_000_000,
210251
vcxo_hz=ad9528_vcxo_freq,
252+
channels=_default_ad9528_channels(),
253+
gpio_lines=[
254+
_GpioLine(
255+
prop="reset-gpios",
256+
controller=gpio_label,
257+
index=ad9528_reset_gpio,
258+
),
259+
],
260+
# Mark AD9528 as the JESD204 topology's SYSREF provider.
261+
# Without this the AD9371 driver's
262+
# ``opt_post_running_stage`` callback can't find a sysref
263+
# source in the jesd204 graph and rolls back with -EFAULT.
264+
# Matches the Kuiper zc706-adrv9371 reference DT.
265+
jesd204_sysref_provider=True,
266+
jesd204_max_sysref_hz=int(
267+
board_cfg.get("ad9528_jesd204_max_sysref_hz", 78125)
268+
),
211269
)
212270
clock_component = ComponentModel(
213271
role="clock",
@@ -234,16 +292,27 @@ def build_model(
234292
trx_clock_names_value = (
235293
'"dev_clk", "fmc_clk", "sysref_dev_clk", "sysref_fmc_clk"'
236294
)
237-
trx_link_ids_value = f"{rx_link_id} {tx_link_id}"
295+
# Add the AD9528 sysref-provider link to jesd204-link-ids and
296+
# jesd204-inputs so the AD9371 driver's post-running verify
297+
# sees a full RX / TX / sysref topology. Matches the working
298+
# Kuiper zc706-adrv9371 reference (RX=1, TX=0, SYSREF=2).
299+
ad9528_sysref_link_id = 2
300+
trx_link_ids_value = f"{rx_link_id} {tx_link_id} {ad9528_sysref_link_id}"
238301
trx_inputs_value = (
239-
f"<&{rx_xcvr_label} 0 {rx_link_id}>, <&{tx_xcvr_label} 0 {tx_link_id}>"
302+
f"<&{rx_xcvr_label} 0 {rx_link_id}>, "
303+
f"<&{tx_xcvr_label} 0 {tx_link_id}>, "
304+
f"<&{clock_chip_label} 0 {ad9528_sysref_link_id}>"
305+
)
306+
profile_props = tuple(
307+
board_cfg.get("trx_profile_props", _DEFAULT_MYKONOS_PROFILE_PROPS)
240308
)
241309
phy_context = {
242310
"gpio_label": gpio_label,
243311
"clocks_value": trx_clocks_value,
244312
"clock_names_value": trx_clock_names_value,
245313
"link_ids": trx_link_ids_value,
246314
"jesd204_inputs": trx_inputs_value,
315+
"profile_props": profile_props,
247316
}
248317
phy_component = ComponentModel(
249318
role="transceiver",
@@ -315,13 +384,25 @@ def build_model(
315384
]
316385

317386
# --- Raw XCVR overlay nodes ---
387+
# The ``adi,sys-clk-select = <0>`` + ``adi,out-clk-select =
388+
# <3>`` + ``adi,use-lpm-enable`` triplet is required by the
389+
# axi-adxcvr driver to bind — without them the platform
390+
# device sits in deferred probe on this build. Clocks are
391+
# kept pointing at the clkgen (through-path) and the
392+
# ``div40`` shape is preserved to minimise risk of a kernel
393+
# hang (the direct-AD9528 rewire attempted in commit 607663b
394+
# did match the reference DT structurally but hung the
395+
# kernel post-JESD).
318396
rx_xcvr_node = (
319397
f"\t&{rx_xcvr_label} {{\n"
320398
'\t\tcompatible = "adi,axi-adxcvr-1.0";\n'
321399
f"\t\tclocks = {rx_xcvr_conv_clk_ref}, {rx_xcvr_div40_ref};\n"
322400
'\t\tclock-names = "conv", "div40";\n'
323401
"\t\t#clock-cells = <1>;\n"
324402
'\t\tclock-output-names = "rx_gt_clk", "rx_out_clk";\n'
403+
"\t\tadi,sys-clk-select = <0>;\n"
404+
"\t\tadi,out-clk-select = <3>;\n"
405+
"\t\tadi,use-lpm-enable;\n"
325406
"\t\tjesd204-device;\n"
326407
"\t\t#jesd204-cells = <2>;\n"
327408
"\t};"
@@ -333,6 +414,9 @@ def build_model(
333414
'\t\tclock-names = "conv", "div40";\n'
334415
"\t\t#clock-cells = <1>;\n"
335416
'\t\tclock-output-names = "tx_gt_clk", "tx_out_clk";\n'
417+
"\t\tadi,sys-clk-select = <0>;\n"
418+
"\t\tadi,out-clk-select = <3>;\n"
419+
"\t\tadi,use-lpm-enable;\n"
336420
"\t\tjesd204-device;\n"
337421
"\t\t#jesd204-cells = <2>;\n"
338422
"\t};"

adidt/xsa/profiles.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
"trx_sysref_req_gpio",
3131
"trx_spi_max_frequency",
3232
"ad9528_vcxo_freq",
33+
"ad9528_reset_gpio",
34+
"ad9528_jesd204_max_sysref_hz",
3335
"rx_link_id",
3436
"rx_os_link_id",
3537
"tx_link_id",
@@ -154,6 +156,8 @@
154156
"trx_sysref_req_gpio",
155157
"trx_spi_max_frequency",
156158
"ad9528_vcxo_freq",
159+
"ad9528_reset_gpio",
160+
"ad9528_jesd204_max_sysref_hz",
157161
"rx_link_id",
158162
"rx_os_link_id",
159163
"tx_link_id",

adidt/xsa/profiles/adrv937x_zc706.json

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,73 @@
22
"name": "adrv937x_zc706",
33
"defaults": {
44
"adrv9009_board": {
5-
"misc_clk_hz": 245760000,
5+
"misc_clk_hz": 122880000,
66
"spi_bus": "spi0",
77
"clk_cs": 0,
88
"trx_cs": 1,
9-
"trx_reset_gpio": 130,
10-
"trx_sysref_req_gpio": 136,
9+
"trx_reset_gpio": 106,
10+
"trx_sysref_req_gpio": 112,
11+
"ad9528_reset_gpio": 113,
1112
"trx_spi_max_frequency": 25000000,
1213
"ad9528_vcxo_freq": 122880000,
1314
"rx_link_id": 1,
1415
"rx_os_link_id": 2,
1516
"tx_link_id": 0,
1617
"tx_octets_per_frame": 2,
17-
"rx_os_octets_per_frame": 2
18+
"rx_os_octets_per_frame": 2,
19+
"trx_profile_props": [
20+
"adi,clocks-clk-pll-vco-freq_khz = <0x960000>;",
21+
"adi,clocks-device-clock_khz = <0x1e000>;",
22+
"adi,clocks-clk-pll-hs-div = <0x04>;",
23+
"adi,clocks-clk-pll-vco-div = <0x02>;",
24+
"adi,jesd204-obs-framer-over-sample = <0x00>;",
25+
"adi,rx-profile-adc-div = <0x01>;",
26+
"adi,rx-profile-en-high-rej-dec5 = <0x01>;",
27+
"adi,rx-profile-iq-rate_khz = <0x1e000>;",
28+
"adi,rx-profile-rf-bandwidth_hz = <0x5f5e100>;",
29+
"adi,rx-profile-rhb1-decimation = <0x01>;",
30+
"adi,rx-profile-rx-bbf-3db-corner_khz = <0x186a0>;",
31+
"adi,rx-profile-rx-dec5-decimation = <0x05>;",
32+
"adi,rx-profile-rx-fir-decimation = <0x02>;",
33+
"adi,rx-profile-rx-fir-gain_db = <0xfffffffa>;",
34+
"adi,rx-profile-rx-fir-num-fir-coefs = <0x30>;",
35+
"adi,rx-profile-rx-fir-coefs = <0xfffbffe6 0x200033 0xffbdff8c 0x8c00d4 0xff04fe91 0x1ad0253 0xfd50fc5d 0x4300593 0xf98ef774 0xa340da8 0xed3ee259 0x25b87e3d 0x7e3d25b8 0xe259ed3e 0xda80a34 0xf774f98e 0x5930430 0xfc5dfd50 0x25301ad 0xfe91ff04 0xd4008c 0xff8cffbd 0x330020 0xffe6fffb>;",
36+
"adi,rx-profile-custom-adc-profile = <0x2160182 0xc90062 0x50001eb 0x6370117 0x51a0068 0x318001c 0x300027 0x1700bb>;",
37+
"adi,obs-profile-adc-div = <0x01>;",
38+
"adi,obs-profile-en-high-rej-dec5 = <0x01>;",
39+
"adi,obs-profile-iq-rate_khz = <0x3c000>;",
40+
"adi,obs-profile-rf-bandwidth_hz = <0xbebc200>;",
41+
"adi,obs-profile-rhb1-decimation = <0x01>;",
42+
"adi,obs-profile-rx-bbf-3db-corner_khz = <0x186a0>;",
43+
"adi,obs-profile-rx-dec5-decimation = <0x05>;",
44+
"adi,obs-profile-rx-fir-decimation = <0x01>;",
45+
"adi,obs-profile-rx-fir-gain_db = <0x06>;",
46+
"adi,obs-profile-rx-fir-num-fir-coefs = <0x18>;",
47+
"adi,obs-profile-rx-fir-coefs = <0xfedf0051 0xffe9ffaa 0xe5fe9e 0x18dff17 0xfd6f06a3 0xefb459e2 0xefb406a3 0xfd6fff17 0x18dfe9e 0xe5ffaa 0xffe90051 0xfedf0000>;",
48+
"adi,obs-profile-custom-adc-profile = <0x1c2015d 0xc90062 0x50002da 0x65a0332 0x5c402dc 0x3420014 0x290024 0x1800c8>;",
49+
"adi,obs-settings-custom-loopback-adc-profile = <0x2390171 0xc90062 0x5000123 0x6050095 0x528003a 0x3270022 0x300028 0x1700bd>;",
50+
"adi,tx-profile-dac-div = <0x01>;",
51+
"adi,tx-profile-iq-rate_khz = <0x3c000>;",
52+
"adi,tx-profile-primary-sig-bandwidth_hz = <0x47868c0>;",
53+
"adi,tx-profile-rf-bandwidth_hz = <0xbebc200>;",
54+
"adi,tx-profile-thb1-interpolation = <0x02>;",
55+
"adi,tx-profile-thb2-interpolation = <0x01>;",
56+
"adi,tx-profile-tx-bbf-3db-corner_khz = <0x186a0>;",
57+
"adi,tx-profile-tx-dac-3db-corner_khz = <0x2da78>;",
58+
"adi,tx-profile-tx-fir-interpolation = <0x01>;",
59+
"adi,tx-profile-tx-input-hb-interpolation = <0x01>;",
60+
"adi,tx-profile-tx-fir-gain_db = <0x06>;",
61+
"adi,tx-profile-tx-fir-num-fir-coefs = <0x10>;",
62+
"adi,tx-profile-tx-fir-coefs = <0x6fef2 0xcbff58 0xffac03d7 0xf36a5297 0xf36a03d7 0xffacff58 0xcbfef2 0x60000>;",
63+
"adi,sniffer-profile-adc-div = <0x01>;",
64+
"adi,sniffer-profile-en-high-rej-dec5 = <0x00>;",
65+
"adi,sniffer-profile-iq-rate_khz = <0x7800>;",
66+
"adi,sniffer-profile-rf-bandwidth_hz = <0x1312d00>;",
67+
"adi,sniffer-profile-rhb1-decimation = <0x02>;",
68+
"adi,sniffer-profile-rx-bbf-3db-corner_khz = <0x186a0>;",
69+
"adi,sniffer-profile-rx-dec5-decimation = <0x05>;",
70+
"adi,sniffer-profile-rx-fir-decimation = <0x04>;"
71+
]
1872
}
1973
}
2074
}

0 commit comments

Comments
 (0)