RE: [PATCH v4 00/16] spi: cadence-quadspi: add PHY tuning support
From: Mahapatra, Amit Kumar
Date: Mon Jun 22 2026 - 00:31:40 EST
AMD General
Hello Santosh,
> -----Original Message-----
> From: Santhosh Kumar K <s-k6@xxxxxx>
> Sent: Thursday, June 18, 2026 1:07 PM
> To: broonie@xxxxxxxxxx; robh@xxxxxxxxxx; krzk+dt@xxxxxxxxxx;
> conor+dt@xxxxxxxxxx; miquel.raynal@xxxxxxxxxxx; richard@xxxxxx;
> vigneshr@xxxxxx; pratyush@xxxxxxxxxx; mwalle@xxxxxxxxxx;
> takahiro.kuwano@xxxxxxxxxxxx
> Cc: linux-spi@xxxxxxxxxxxxxxx; devicetree@xxxxxxxxxxxxxxx; linux-
> kernel@xxxxxxxxxxxxxxx; linux-mtd@xxxxxxxxxxxxxxxxxxx; praneeth@xxxxxx; u-
> kumar1@xxxxxx; a-dutta@xxxxxx; s-k6@xxxxxx
> Subject: [PATCH v4 00/16] spi: cadence-quadspi: add PHY tuning support
>
> This series implements PHY tuning support for the Cadence QSPI controller to
> enable reliable high-speed operations. Without PHY tuning, controllers use
> conservative timing that limits performance. PHY tuning calibrates RX/TX delay lines
> to find optimal data capture timing windows, enabling operation up to the controller's
> maximum frequency.
>
> Background:
> High-speed SPI memory controllers require precise timing calibration for reliable
> operation. At higher frequencies, board-to-board variations make fixed timing
> parameters inadequate. The Cadence QSPI controller includes a PHY interface with
> programmable delay lines (0-127 taps) for RX and TX paths, but these require
> runtime calibration to find the valid timing window.
>
> Approach:
> Add SDR/DDR PHY tuning algorithms for the Cadence controller:
>
> SDR Mode Tuning (1D search):
> - Searches for two consecutive valid RX delay windows
> - Selects the larger window and uses its midpoint for maximum margin
> - TX delay fixed at maximum (127) as it's less critical in SDR
>
> DDR Mode Tuning (2D search):
> - Finds RX boundaries (rxlow/rxhigh) using TX window sweeps
> - Finds TX boundaries (txlow/txhigh) at fixed RX positions
> - Defines valid region corners and detects gaps via binary search
> - Applies temperature compensation for optimal point selection
> - Handles single or dual passing regions with different strategies
Thank you for this series. I had a question regarding the Virtual Concat
driver patch series [1]. Now that it has been merged into the kernel and
enables support for multiple flash devices connected in stacked mode-where
each flash device is probed and configured independently-if both flash
parts are required to operate in DDR mode, each device would need to
perform tuning and store its tuning data separately.
Given this, should we consider this use case and adapt the tuning
architecture to support it?
I'd appreciate your thoughts on this.
[1] https://lore.kernel.org/all/20260204-mtd-virt-concat-v17-0-5e98239bb55b@xxxxxxxxxxx/
Regards,
Amit
>
> Patch description:
> Infrastructure (1-5):
> - Patch 1: Add spi-max-post-config-frequency to describe maximum
> frequency achievable post controller configuration
> - Patch 2: Add spi-phy-pattern-partition phandle for
> NOR flash PHY tuning pattern location
> - Patch 3: Parse spi-max-post-config-frequency in spi.c; adds
> spi_device.post_config_max_speed_hz (0 when not set
> keeping all existing DT fully compatible)
> - Patch 4: Extend spi_mem_adjust_op_freq() with a bypass: if
> op->max_freq equals post_config_max_speed_hz, return
> immediately leaving op->max_freq unchanged. All other
> ops are capped to max_speed_hz
> - Patch 5: Add execute_tuning callback to spi_controller_mem_ops and
> spi_mem_execute_tuning() wrapper in SPI-MEM core
>
> Cadence QSPI Implementation (6-12):
> - Patch 6: Move cqspi_readdata_capture() earlier (preparatory)
> - Patch 7: Add DQS bit to cqspi_readdata_capture() (preparatory)
> - Patch 8: Add complete PHY tuning support: DLL management, pattern
> verification (NOR via spi-phy-pattern-partition phandle,
> NAND via write-to-cache), SDR 1D and DDR 2D search
> algorithms with temperature compensation, AM654-specific
> execute_tuning entry point;
> - Patch 9: Reject 2-byte-address DDR operations via a new
> CQSPI_NO_2BYTE_ADDR_PHY_DDR quirk flag to work around
> AM654 OSPI erratum i2383
> - Patch 10: Refactor direct read path for PHY support (preparatory)
> - Patch 11: Enable PHY for direct reads, split the transfer into an
> unaligned head, a 16-byte-aligned middle section with PHY
> active, and an unaligned tail
> - Patch 12: Enable PHY for indirect writes of at least
> CQSPI_PHY_MIN_INDIRECT_WRITE_LEN bytes
>
> MTD core (13-16):
> - Patch 13: Extract spinand_select_op_variant() into a shared helper
> spinand_op_find_best() with a skip_mask
> - Patch 14: Negotiate optimal PHY operating point before dirmap
> creation
> - Patch 15: Extract spi_nor_spimem_get_read_op() helper (preparatory)
> - Patch 16: Execute PHY tuning in spi_nor_probe() before creating
> dirmaps
>
> Testing:
> This series was tested on TI's
> AM62Ax SK with OSPI NAND flash and
> AM62Px SK with OSPI NOR flash:
>
> Read throughput:
> |----------------------------------------|
> | | non-PHY | PHY |
> |----------------------------------------|
> | OSPI NOR (8D) | 37.5 MB/s | 216 MB/s |
> |----------------------------------------|
> | OSPI NAND (8S) | 9.2 MB/s | 35.1 MB/s |
> |----------------------------------------|
>
> Write throughput:
> |----------------------------------------|
> | | non-PHY | PHY |
> |----------------------------------------|
> | OSPI NAND (8S) | 6 MB/s | 9.2 MB/s |
> |----------------------------------------|
>
> Test log: https://gist.github.com/santhosh21/fe98754e52970287eb9011154100b62d
> Repo: https://github.com/santhosh21/linux/commits/phy_tuning_v4/
>
> Changes in v4:
> - Add spi-max-post-config-frequency instead of extending spi-max-frequency
> to accept an optional second value
> - Replace spi_mem_apply_base_freq_cap() with spi_mem_adjust_op_freq()
> extension
> - For SPI NOR/NAND, execute PHY tuning before the dirmap creation
> - For SPI NAND, execute PHY tuning across all operation variants available,
> perform duration comparison, and select the best resulting variant
> by taking controller-specific restrictions into account
> - Move i2383 check from cqspi_supports_mem_op() to
> cqspi_am654_ospi_execute_tuning()
> - Rename cdns,phy-pattern-partition to spi-phy-pattern-partition,
> cqspi_phy_enable to cqspi_tune_phy and f_pdata->use_phy to use_tuned_phy
> - Remove redundant spi-max-frequency parsing in driver cqspi_of_get_flash_pdata()
> - Extract DMA refactoring into a preparatory patch
> - Rebase on v7.1
> - Collect tags from Miquel
> - Link to v3: https://lore.kernel.org/linux-spi/20260527175527.2247679-1-s-
> k6@xxxxxx/
>
> Changes in v3:
> - Drop spi-has-dqs DT property; DQS is now enabled automatically when
> the selected read operation uses DDR signalling (dtr flags in the op)
> - Extend spi-max-frequency to accept an optional second value forming a
> [base-freq, max-freq] pair; the presence of two values signals PHY
> tuning intent and encodes both the conservative base speed and the
> calibration target in one property
> - Add base_speed_hz to struct spi_device (spi.c/spi.h) and parse the
> two-element array there; single-value DT is fully backward-compatible
> - Move frequency enforcement from the cadence driver to core: new
> spi_mem_apply_base_freq_cap() called from spi_mem_exec_op() replaces
> the per-driver cqspi_op_matches_tuned() and non_phy_clk_rate field
> - Propagate the tuned max_freq to dirmap op templates after
> execute_tuning() succeeds; store persistent op templates in
> spi_nor.max_read_op and spinand.{max_read,max_write}_op so the
> frequency writeback survives across the probe call
> - Replace NOR pattern partition lookup by name with a
> cdns,phy-pattern-partition DT phandle pointing directly to the
> partition node
> - Add CQSPI_NO_2BYTE_ADDR_PHY_DDR quirk and reject 2-byte-address DDR
> ops in cqspi_supports_mem_op() to work around AM654 erratum i2383
> - Remove RFC tag
> - Rebase on v7.1-rc5
> - Collect tags from Miquel
> - Link to v2: https://lore.kernel.org/linux-spi/20260113141617.1905039-1-s-
> k6@xxxxxx/
>
> Changes in v2:
> - Restructure the .execute_tuning() call from spi-mem clients instead
> of mtdcore with best read_op and write_op (optional) passed
> - Add compatible-specific .execute_tuning() call which can be called by
> spi_mem_execute_tuning() if exists
> - Handle tuning requirement check by controller instead of spi-mem
> clients
> - Add support to write the phy_pattern to cache if relevant write_op
> is passed or get the partition offset which contains the phy_pattern
> - Add tuning algorithm for DDR mode
> - Add support for DQS
> - Restrict PHY frequency to tuned operations
> - Link to v1: https://lore.kernel.org/linux-spi/20250811193219.731851-1-s-
> k6@xxxxxx/
>
> Signed-off-by: Santhosh Kumar K <s-k6@xxxxxx>
>
> Pratyush Yadav (1):
> mtd: spi-nor: extract read op template construction into helper
>
> Santhosh Kumar K (15):
> spi: dt-bindings: add spi-max-post-config-frequency property
> spi: dt-bindings: add spi-phy-pattern-partition property
> spi: parse spi-max-post-config-frequency into post_config_max_speed_hz
> spi: spi-mem: teach spi_mem_adjust_op_freq() about post-config ops
> spi: spi-mem: add execute_tuning callback and spi_mem_execute_tuning()
> spi: cadence-quadspi: move cqspi_readdata_capture earlier
> spi: cadence-quadspi: add DQS support to read data capture
> spi: cadence-quadspi: add PHY tuning support
> spi: cadence-quadspi: skip DDR PHY tuning for 2-byte-address ops
> (i2383)
> spi: cadence-quadspi: refactor direct read path for PHY support
> spi: cadence-quadspi: enable PHY for direct reads
> spi: cadence-quadspi: enable PHY for indirect writes
> mtd: spinand: extract variant ranking logic into
> spinand_op_find_best()
> mtd: spinand: negotiate optimal PHY operating point before dirmap
> creation
> mtd: spi-nor: run PHY tuning after init and update dirmap frequency
>
> .../bindings/spi/cdns,qspi-nor.yaml | 19 +
> .../bindings/spi/spi-peripheral-props.yaml | 13 +
> drivers/mtd/nand/spi/core.c | 246 +-
> drivers/mtd/spi-nor/core.c | 80 +-
> drivers/spi/spi-cadence-quadspi.c | 2265 +++++++++++++++--
> drivers/spi/spi-mem.c | 40 +
> drivers/spi/spi.c | 2 +
> include/linux/mtd/spi-nor.h | 3 +
> include/linux/mtd/spinand.h | 11 +
> include/linux/spi/spi-mem.h | 14 +
> include/linux/spi/spi.h | 3 +
> 11 files changed, 2493 insertions(+), 203 deletions(-)
>
> --
> 2.34.1