From: sashiko-bot@kernel.org
To: "Santhosh Kumar K" <s-k6@ti.com>
Cc: devicetree@vger.kernel.org, "Michael Walle" <mwalle@kernel.org>,
"Pratyush Yadav" <pratyush@kernel.org>,
"Vignesh Raghavendra" <vigneshr@ti.com>,
"Richard Weinberger" <richard@nod.at>,
"Miquel Raynal" <miquel.raynal@bootlin.com>,
"Takahiro Kuwano" <takahiro.kuwano@infineon.com>,
robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v8 11/18] spi: cadence-quadspi: enable PHY for direct reads
Date: Fri, 21 Aug 2026 13:31:06 +0000 [thread overview]
Message-ID: <20260821133106.9DDAD1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260821114822.4040338-12-s-k6@ti.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] The error path in `cqspi_tune_phy` (when `enable` is true) fails to restore the `CQSPI_REG_READCAPTURE` register, leaving the controller in a corrupted state for subsequent non-PHY reads.
- [High] `cqspi_tune_phy` (enable=false) bails out early on idle wait timeout, leaving the PHY permanently enabled, and its return value is ignored by callers, masking the failure.
- [High] A failed DLL resync leaves `CQSPI_REG_PHY_CONFIG` updated, causing subsequent retries to skip the resync and use an unlocked PHY.
Pre-existing issues:
- [High] The PIO fallback path in `cqspi_memcpy_fromio()` causes data corruption on big-endian architectures due to mismatched I/O accessors.
--
--- Patch [11]: [PATCH v8 11/18] spi: cadence-quadspi: enable PHY for direct reads ---
commit b1257269b9ef8a064e84e36b6359dd1d26e31e0d
Author: Santhosh Kumar K <s-k6@ti.com>
Subject: spi: cadence-quadspi: enable PHY for direct reads
This patch adds support for toggling the PHY mode around direct DMA reads in
the Cadence QSPI driver. It introduces cqspi_tune_phy() to configure and
enable the PHY pipeline and reprogram the DLL if necessary. It also adds a
predicate to ensure PHY is only used when the operation frequency matches the
tuned frequency and the transfer is 16-byte aligned.
> diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
> index 99a0ec0e769c5..8903b4cf4f6f5 100644
> --- a/drivers/spi/spi-cadence-quadspi.c
> +++ b/drivers/spi/spi-cadence-quadspi.c
> @@ -1074,6 +1074,102 @@ static int cqspi_resync_dll(struct cqspi_st *cqspi)
> return ret;
> }
>
> +static int cqspi_tune_phy(struct cqspi_flash_pdata *f_pdata, bool enable)
> +{
> + struct cqspi_st *cqspi = f_pdata->cqspi;
> + void __iomem *reg_base = cqspi->iobase;
> + u32 reg;
> + u8 dummy;
> + int ret;
> +
> + ret = cqspi_wait_idle(cqspi);
> + if (ret)
> + return ret;
[Severity: High]
If this cqspi_wait_idle() times out when enable is false, the function returns
early without clearing CQSPI_REG_CONFIG_PHY_EN or restoring the read capture
settings. Does this leave the SPI controller permanently stuck in PHY mode,
which would break subsequent non-PHY communication with the flash?
> +
> + if (enable) {
[ ... ]
> + reg = readl(reg_base + CQSPI_REG_PHY_CONFIG);
> + if (((reg >> CQSPI_REG_PHY_CONFIG_RX_DEL_LSB) &
> + CQSPI_REG_PHY_CONFIG_RX_DEL_MASK) != f_pdata->phy_setting.rx ||
> + ((reg >> CQSPI_REG_PHY_CONFIG_TX_DEL_LSB) &
> + CQSPI_REG_PHY_CONFIG_TX_DEL_MASK) != f_pdata->phy_setting.tx) {
> + cqspi_set_dll(reg_base, f_pdata->phy_setting.rx,
> + f_pdata->phy_setting.tx);
> + ret = cqspi_resync_dll(cqspi);
> + if (ret)
> + return ret;
[Severity: High]
If cqspi_resync_dll() fails, the hardware register CQSPI_REG_PHY_CONFIG
still retains the new settings written by cqspi_set_dll(). On a subsequent
retry, the initial check above will see that the register matches the device's
settings, skipping the resync entirely. Can this lead to operating the PHY
with an unsynced or unlocked DLL?
> + }
> +
> + cqspi_readdata_capture(cqspi, !f_pdata->use_dqs, f_pdata->use_dqs,
> + f_pdata->phy_setting.read_delay);
> +
> + reg = readl(reg_base + CQSPI_REG_CONFIG);
> + reg |= CQSPI_REG_CONFIG_PHY_EN | CQSPI_REG_CONFIG_PHY_PIPELINE;
> + writel(reg, reg_base + CQSPI_REG_CONFIG);
> +
[ ... ]
> + ret = cqspi_wait_idle(cqspi);
> + if (ret) {
> + reg = readl(reg_base + CQSPI_REG_CONFIG);
> + reg &= ~(CQSPI_REG_CONFIG_PHY_EN |
> + CQSPI_REG_CONFIG_PHY_PIPELINE);
> + writel(reg, reg_base + CQSPI_REG_CONFIG);
> + reg = readl(reg_base + CQSPI_REG_RD_INSTR);
> + reg &= ~(CQSPI_REG_RD_INSTR_DUMMY_MASK
> + << CQSPI_REG_RD_INSTR_DUMMY_LSB);
> + reg |= FIELD_PREP(CQSPI_REG_RD_INSTR_DUMMY_MASK
> + << CQSPI_REG_RD_INSTR_DUMMY_LSB,
> + cqspi->phy_saved_dummy);
> + writel(reg, reg_base + CQSPI_REG_RD_INSTR);
> + }
> + return ret;
[Severity: High]
This error path rolls back CQSPI_REG_CONFIG and CQSPI_REG_RD_INSTR, but it
seems to miss reverting CQSPI_REG_READCAPTURE, which was modified earlier
via cqspi_readdata_capture(). Since cqspi_configure() optimizes out
READCAPTURE updates unless the clock frequency or chip-select changes, could
this cause subsequent standard reads to use incorrect PHY capture settings and
corrupt data?
> + }
[ ... ]
> @@ -1629,6 +1733,7 @@ static int cqspi_direct_read_execute(struct cqspi_flash_pdata *f_pdata,
> loff_t from = op->addr.val;
> size_t len = op->data.nbytes;
> u_char *buf = op->data.buf.in;
> + int ret;
>
> if (!cqspi->rx_chan || !virt_addr_valid(buf) ||
> len < CQSPI_PHY_MIN_DIRECT_READ_LEN) {
[ ... ]
> + ret = cqspi_tune_phy(f_pdata, true);
> + if (ret)
> + return ret;
> + ret = cqspi_direct_read_dma(f_pdata, buf, from, len);
> + cqspi_tune_phy(f_pdata, false);
> +
> + return ret;
> }
[Severity: High]
Is it possible this hides a hardware failure from the SPI subsystem since
the return value is still 0 from the DMA read? The return value of
cqspi_tune_phy(f_pdata, false) is ignored here, so if the DMA read succeeds
but disabling the PHY times out during cqspi_wait_idle(), the operation is
reported as a success despite the controller being left in a broken state.
While reviewing this, I also noticed a pre-existing issue in the driver.
[Severity: High]
This is a pre-existing issue, but the PIO fallback path in
cqspi_memcpy_fromio() appears to mix accessors in a way that breaks
big-endian systems:
drivers/spi/spi-cadence-quadspi.c:cqspi_memcpy_fromio() {
...
while (count >= 4) {
put_unaligned_le32(__raw_readl(from), to);
from += 4;
to += 4;
count -= 4;
}
...
}
The __raw_readl() performs a native load without byte-swapping, but
put_unaligned_le32() will apply a byteswap before storing on big-endian
hardware. Can this incorrectly reverse the byte order of the stream in 4-byte
chunks during unaligned DMA transfers that fallback to PIO?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260821114822.4040338-1-s-k6@ti.com?part=11
next prev parent reply other threads:[~2026-08-21 13:31 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-21 11:48 [PATCH v8 00/18] spi: cadence-quadspi: add PHY tuning support Santhosh Kumar K
2026-08-21 11:48 ` [PATCH v8 01/18] spi: dt-bindings: add spi-max-post-config-frequency-hz property Santhosh Kumar K
2026-08-21 11:48 ` [PATCH v8 02/18] spi: dt-bindings: add spi-phy-pattern-partition property Santhosh Kumar K
2026-08-21 11:48 ` [PATCH v8 03/18] spi: parse spi-max-post-config-frequency-hz into post_config_max_speed_hz Santhosh Kumar K
2026-08-21 12:12 ` sashiko-bot
2026-08-21 11:48 ` [PATCH v8 04/18] spi: spi-mem: teach spi_mem_adjust_op_freq() about post-config ops Santhosh Kumar K
2026-08-21 12:23 ` sashiko-bot
2026-08-21 11:48 ` [PATCH v8 05/18] spi: spi-mem: add execute_tuning callback and spi_mem_execute_tuning() Santhosh Kumar K
2026-08-21 11:48 ` [PATCH v8 06/18] spi: cadence-quadspi: move cqspi_readdata_capture earlier Santhosh Kumar K
2026-08-21 11:48 ` [PATCH v8 07/18] spi: cadence-quadspi: add DQS support to read data capture Santhosh Kumar K
2026-08-21 11:48 ` [PATCH v8 08/18] spi: cadence-quadspi: add PHY tuning support Santhosh Kumar K
2026-08-21 12:54 ` sashiko-bot
2026-08-21 11:48 ` [PATCH v8 09/18] spi: cadence-quadspi: skip DDR PHY tuning for 2-byte-address ops (i2383) Santhosh Kumar K
2026-08-21 11:48 ` [PATCH v8 10/18] spi: cadence-quadspi: refactor direct read path for PHY support Santhosh Kumar K
2026-08-21 13:15 ` sashiko-bot
2026-08-21 11:48 ` [PATCH v8 11/18] spi: cadence-quadspi: enable PHY for direct reads Santhosh Kumar K
2026-08-21 13:31 ` sashiko-bot [this message]
2026-08-21 11:48 ` [PATCH v8 12/18] spi: cadence-quadspi: enable PHY for indirect writes Santhosh Kumar K
2026-08-21 13:43 ` sashiko-bot
2026-08-21 11:48 ` [PATCH v8 13/18] spi: cadence-quadspi: reprogram CS timing on every chip-select switch Santhosh Kumar K
2026-08-21 11:48 ` [PATCH v8 14/18] spi: cadence-quadspi: reprogram PHY DLL on runtime resume Santhosh Kumar K
2026-08-21 13:58 ` sashiko-bot
2026-08-21 11:48 ` [PATCH v8 15/18] mtd: spinand: extract variant ranking logic into spinand_op_find_best_variant() Santhosh Kumar K
2026-08-21 11:48 ` [PATCH v8 16/18] mtd: spinand: negotiate optimal controller operating point before dirmap creation Santhosh Kumar K
2026-08-21 14:13 ` sashiko-bot
2026-08-21 11:48 ` [PATCH v8 17/18] mtd: spi-nor: extract read op template construction into helper Santhosh Kumar K
2026-08-21 11:48 ` [PATCH v8 18/18] mtd: spi-nor: run controller optimization before dirmap creation Santhosh Kumar K
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260821133106.9DDAD1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=miquel.raynal@bootlin.com \
--cc=mwalle@kernel.org \
--cc=pratyush@kernel.org \
--cc=richard@nod.at \
--cc=robh@kernel.org \
--cc=s-k6@ti.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=takahiro.kuwano@infineon.com \
--cc=vigneshr@ti.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox