.../bindings/spi/spi-peripheral-props.yaml | 6 + drivers/mtd/nand/spi/core.c | 14 + drivers/mtd/spi-nor/core.c | 71 +- drivers/spi/spi-cadence-quadspi.c | 2060 ++++++++++++++++- drivers/spi/spi-mem.c | 34 + include/linux/spi/spi-mem.h | 5 + 6 files changed, 2102 insertions(+), 88 deletions(-)
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 the 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
DQS Support:
- Adds optional DQS (Data Strobe) mode for improved timing margins
- Configures read data capture to use dedicated strobe signal
Patch description:
Infrastructure (1-5):
- Patch 1: Add DT binding for spi-has-dqs property
- Patch 2: Implement spi_mem_execute_tuning() API in SPI core
- Patch 3-5: Refactor and integrate tuning in MTD SPI-NAND/NOR layers and call
tuning during probe
Cadence QSPI Implementation (6-12):
- Patch 6-8: Preparatory refactoring and DQS support
- Patch 9: Add PHY tuning infrastructure with placeholders
- Patch 10: Implement complete SDR/DDR tuning algorithms
- Patch 11: Restrict PHY frequency to calibrated operations only
- Patch 12: Enable PHY for direct memory-mapped reads and large writes
Testing:
This series was tested on TI's
AM62A SK with OSPI NAND flash and
AM62P SK with OSPI NOR flash:
Read throughput:
|-------------------------------------|
| | without PHY | with PHY |
|-------------------------------------|
|OSPI NOR | 37.5 MB/s | 216 MB/s |
|-------------------------------------|
|OSPI NAND | 9.2 MB/s | 35.1 MB/s |
|-------------------------------------|
Write throughput:
|-------------------------------------|
| | without PHY | with PHY |
|-------------------------------------|
|OSPI NAND | 6 MB/s | 9.2 MB/s |
|-------------------------------------|
Test log: https://gist.github.com/santhosh21/baab9e1c003c8e685dd6202f5c2f23de
Repo: https://github.com/santhosh21/linux/commits/phy_rfc_v2_review
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@ti.com/
Signed-off-by: Santhosh Kumar K <s-k6@ti.com>
Pratyush Yadav (1):
mtd: spi-nor: extract read operation setup into helper
Santhosh Kumar K (11):
spi: dt-bindings: add spi-has-dqs property
spi: spi-mem: add controller tuning support
mtd: spinand: perform controller tuning during probe
mtd: spi-nor: perform controller tuning during probe
spi: cadence-quadspi: move cqspi_readdata_capture earlier
spi: cadence-quadspi: add DQS support to read data capture
spi: cadence-quadspi: read 'has-dqs' DT property
spi: cadence-quadspi: add PHY tuning infrastructure
spi: cadence-quadspi: implement PHY tuning algorithm
spi: cadence-quadspi: restrict PHY frequency to tuned operations
spi: cadence-quadspi: enable PHY for direct reads and writes
.../bindings/spi/spi-peripheral-props.yaml | 6 +
drivers/mtd/nand/spi/core.c | 14 +
drivers/mtd/spi-nor/core.c | 71 +-
drivers/spi/spi-cadence-quadspi.c | 2060 ++++++++++++++++-
drivers/spi/spi-mem.c | 34 +
include/linux/spi/spi-mem.h | 5 +
6 files changed, 2102 insertions(+), 88 deletions(-)
--
2.34.1
Hi Santhosh, On 13/01/2026 at 19:46:05 +0530, Santhosh Kumar K <s-k6@ti.com> wrote: > 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 the 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 > > DQS Support: > - Adds optional DQS (Data Strobe) mode for improved timing margins > - Configures read data capture to use dedicated strobe signal I am glad to know this signal is useful. I do not consider the DT property as being the correct way to carry this information ATM, so I will investigate a bit a propose a solution that is more uniform with the rest of the chips description we have today. > Patch description: > Infrastructure (1-5): > - Patch 1: Add DT binding for spi-has-dqs property > - Patch 2: Implement spi_mem_execute_tuning() API in SPI core > - Patch 3-5: Refactor and integrate tuning in MTD SPI-NAND/NOR layers and call > tuning during probe > > Cadence QSPI Implementation (6-12): > - Patch 6-8: Preparatory refactoring and DQS support > - Patch 9: Add PHY tuning infrastructure with placeholders > - Patch 10: Implement complete SDR/DDR tuning algorithms > - Patch 11: Restrict PHY frequency to calibrated operations only > - Patch 12: Enable PHY for direct memory-mapped reads and large writes > > Testing: > This series was tested on TI's > AM62A SK with OSPI NAND flash and > AM62P SK with OSPI NOR flash: > > Read throughput: > |-------------------------------------| > | | without PHY | with PHY | > |-------------------------------------| > |OSPI NOR | 37.5 MB/s | 216 MB/s | > |-------------------------------------| > |OSPI NAND | 9.2 MB/s | 35.1 MB/s | > |-------------------------------------| I am surprised by these numbers, I would expect these to get higher for SPI NANDs. I will test the series and report my observations, especially since there is also ODDR SPI NAND support now (in nand/next, should be part of my upcoming merge request to Linus for 6.19+1); > Write throughput: > |-------------------------------------| > | | without PHY | with PHY | > |-------------------------------------| > |OSPI NAND | 6 MB/s | 9.2 MB/s | > |-------------------------------------| Overall I want to say that this series has greatly improved already, I am really looking forward seeing this merged. I have several comments to make, but they are mostly minor improvements which won't be very impacting. The tuning procedure is very well described in the code as well, which is appreciated. Please remove the RFC prefix for v3, it is clearly no longer needed. Thanks, Miquèl
Hi Santhosh, > I am surprised by these numbers, I would expect these to get higher for > SPI NANDs. I will test the series and report my observations, especially > since there is also ODDR SPI NAND support now (in nand/next, should be > part of my upcoming merge request to Linus for 6.19+1); I just tested the series, here are some numbers I grabbed on TI AM62A7 LP SK with a Winbond W35N02 SPI NAND chip (so in the end very close to your report): +-----------------+-----------+------------+ | SPI NAND | no tuning | PHY tuning | | Unit: MiB/s | 25MHz | 166MHz | |-----------------+-----------+------------| | Octal SDR read | 13.8 | 34.2 | | write | 7.2 | 10.2 | |-----------------+-----------+------------| | Octal DTR read | 21.2 | N/A | | write | 9.0 | N/A | +-----------------+-----------+------------+ Please mind I used MiB/s and not MB/s (so kiB / 1024), I don't know which one you used for measuring, as you marked MB, whereas the most common unit seems to be MiB. However PHY tuning failed in Octal DTR mode (your series applied on top of nand/next) with the following logs, can you have a look? [ 2.261647] spi-nand spi0.0: Winbond SPI NAND was found. [ 2.266956] spi-nand spi0.0: 128 MiB, block size: 256 KiB, page size: 4096, OOB size: 128 [ 2.285257] cadence-qspi fc40000.spi: PHY tuning failed: -2 [ 2.290835] spi-nand spi0.0: Failed to execute PHY tuning: -2 The fallback worked well though, the memory was still usable like before, which is a very good point. Thanks, Miquèl
On 05/02/26 21:18, Miquel Raynal wrote: > Hi Santhosh, > >> I am surprised by these numbers, I would expect these to get higher for >> SPI NANDs. I will test the series and report my observations, especially >> since there is also ODDR SPI NAND support now (in nand/next, should be >> part of my upcoming merge request to Linus for 6.19+1); > > I just tested the series, here are some numbers I grabbed on TI AM62A7 > LP SK with a Winbond W35N02 SPI NAND chip (so in the end very close to > your report): > > +-----------------+-----------+------------+ > | SPI NAND | no tuning | PHY tuning | > | Unit: MiB/s | 25MHz | 166MHz | > |-----------------+-----------+------------| > | Octal SDR read | 13.8 | 34.2 | > | write | 7.2 | 10.2 | > |-----------------+-----------+------------| > | Octal DTR read | 21.2 | N/A | > | write | 9.0 | N/A | > +-----------------+-----------+------------+ > > Please mind I used MiB/s and not MB/s (so kiB / 1024), I don't know > which one you used for measuring, as you marked MB, whereas the most > common unit seems to be MiB. > > However PHY tuning failed in Octal DTR mode (your series applied on top > of nand/next) with the following logs, can you have a look? > > [ 2.261647] spi-nand spi0.0: Winbond SPI NAND was found. > [ 2.266956] spi-nand spi0.0: 128 MiB, block size: 256 KiB, page size: 4096, OOB size: 128 > [ 2.285257] cadence-qspi fc40000.spi: PHY tuning failed: -2 > [ 2.290835] spi-nand spi0.0: Failed to execute PHY tuning: -2 Unfortunately, due to a known erratum in the Cadence controller, PHY DDR mode cannot be used with 2-byte addressing. Refer: Errata i2383: OSPI: 2-byte address is not supported in PHY DDR mode [1] As a result, the Cadence controller supports only the following operating modes: - PHY DDR mode with 4-byte addressing - PHY SDR mode - TAP (non-PHY) DDR mode - TAP (non-PHY) SDR mode [1] https://www.ti.com/lit/er/sprz544c/sprz544c.pdf?ts=1770404630843&ref_url=https%253A%252F%252Fwww.google.com%252F Regards, Santhosh. > > The fallback worked well though, the memory was still usable like > before, which is a very good point. > > Thanks, > Miquèl
© 2016 - 2026 Red Hat, Inc.