From: Michal Simek <michal.simek@amd.com>
To: Suraj Kakade <suraj.hanumantkakade@amd.com>,
u-boot@lists.u-boot-project.org
Cc: git@amd.com, padmarao.begari@amd.com,
Tom Rini <trini@konsulko.com>, Jagan Teki <jagan@openedev.com>,
Siva Durga Prasad Paladugu <siva.durga.prasad.paladugu@amd.com>
Subject: Re: [PATCH] spi: xilinx_spi: fix premature transfer termination at low SCK
Date: Fri, 4 Sep 2026 14:43:46 +0200 [thread overview]
Message-ID: <e3473f7c-a36a-4607-9945-22363959ca55@amd.com> (raw)
In-Reply-To: <20260813120718.1707573-1-suraj.hanumantkakade@amd.com>
On 8/13/26 14:06, Suraj Kakade wrote:
> start_transfer() asserts SPICR_MASTER_INHIBIT as soon as SPISR_TX_EMPTY
> is seen. SPISR_TX_EMPTY only indicates that the TX FIFO has drained;
> the final byte may still be in the shift pipeline and actively
> transmitting on the SPI bus. At low SCK frequencies the gap between
> FIFO-empty and the last bit finishing its shift-out becomes wide
> enough that MASTER_INHIBIT gets asserted before the transfer actually
> completes, truncating the last byte and leaving the clock generation
> logic in an error state.
>
> Switch to polling IPISR_DTR_EMPTY instead, which is only set once the
> last byte has genuinely finished shifting out to the slave, and only
> assert MASTER_INHIBIT afterwards. Clear any stale DTR_EMPTY before
> starting a transfer and after detecting completion, since IPISR is
> toggle-on-write. This fix works correctly at both high and low SCK
> frequencies.
>
> Fixes: 0c0de58f7b30 ("spi: xilinx_spi: Modify transfer logic xilinx_spi_xfer() function")
> Signed-off-by: Padmarao Begari <padmarao.begari@amd.com>
> Signed-off-by: Suraj Kakade <suraj.hanumantkakade@amd.com>
> ---
> drivers/spi/xilinx_spi.c | 21 ++++++++++++++++++++-
> 1 file changed, 20 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
> index b2af17ebae9..011bbc93076 100644
> --- a/drivers/spi/xilinx_spi.c
> +++ b/drivers/spi/xilinx_spi.c
> @@ -53,6 +53,8 @@
> #define SPISR_RX_FULL BIT(1)
> #define SPISR_RX_EMPTY BIT(0)
>
> +#define IPISR_DTR_EMPTY BIT(2)
> +
> /* SPI Data Transmit Register (spidtr), [1] p12, [2] p12 */
> #define SPIDTR_8BIT_MASK GENMASK(7, 0)
> #define SPIDTR_16BIT_MASK GENMASK(15, 0)
> @@ -256,6 +258,13 @@ static int start_transfer(struct udevice *dev, const void *dout, void *din, u32
> reg = readl(®s->spicr) | SPICR_MASTER_INHIBIT;
> writel(reg, ®s->spicr);
> count = xilinx_spi_fill_txfifo(bus, txp, txbytes);
> + /*
> + * Clear any stale DTR_EMPTY before starting. IPISR is
> + * toggle-on-write, so only write (toggle) the bit when it is
> + * actually set, otherwise the write would spuriously set it.
> + */
> + if (readl(®s->ipisr) & IPISR_DTR_EMPTY)
> + writel(IPISR_DTR_EMPTY, ®s->ipisr);
> /* Enable master transaction */
> reg = readl(®s->spicr) & ~SPICR_MASTER_INHIBIT;
> writel(reg, ®s->spicr);
> @@ -263,12 +272,22 @@ static int start_transfer(struct udevice *dev, const void *dout, void *din, u32
> if (txp)
> txp += count;
>
> - ret = wait_for_bit_le32(®s->spisr, SPISR_TX_EMPTY, true,
> + /*
> + * Wait for the transfer to fully complete before inhibiting
> + * the master. The final byte may still be in the shift
> + * pipeline. Poll IPISR_DTR_EMPTY, which is set only once the
> + * last byte has been shifted out to the slave. Asserting
> + * MASTER_INHIBIT before this stops SCK and truncates the last
> + * byte, which is observable at low SCK frequencies.
> + */
> + ret = wait_for_bit_le32(®s->ipisr, IPISR_DTR_EMPTY, true,
> XILINX_SPISR_TIMEOUT, false);
> if (ret < 0) {
> printf("XILSPI error: Xfer timeout\n");
> return ret;
> }
> + /* IPISR is toggle-on-write; write 1 to clear DTR_EMPTY */
> + writel(IPISR_DTR_EMPTY, ®s->ipisr);
>
> reg = readl(®s->spicr) | SPICR_MASTER_INHIBIT;
> writel(reg, ®s->spicr);
Applied.
M
prev parent reply other threads:[~2026-09-04 12:44 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-13 12:06 [PATCH] spi: xilinx_spi: fix premature transfer termination at low SCK Suraj Kakade
2026-09-04 12:43 ` Michal Simek [this message]
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=e3473f7c-a36a-4607-9945-22363959ca55@amd.com \
--to=michal.simek@amd.com \
--cc=git@amd.com \
--cc=jagan@openedev.com \
--cc=padmarao.begari@amd.com \
--cc=siva.durga.prasad.paladugu@amd.com \
--cc=suraj.hanumantkakade@amd.com \
--cc=trini@konsulko.com \
--cc=u-boot@lists.u-boot-project.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.