Re: [PATCH v1] spi: qcom-geni: Fix cs_change handling on the last transfer
From: Mukesh Savaliya
Date: Wed Jun 03 2026 - 07:19:49 EST
On 5/29/2026 12:33 AM, Viken Dadhaniya wrote:
Commit b99181cdf9fa ("spi-geni-qcom: remove manual CS control") introducedPlease make it clear if cs_change = 1 or true ? for CS assertion ?
automatic CS control via the FRAGMENTATION bit, but missed the case where
cs_change is set on the last transfer in a message.
For the last transfer, cs_change means that CS should remain asserted after
This is to make it understandable for anyone.
the message completes. Since GENI SPI controls CS through FRAGMENTATION,Please provide FRAGMENTION bit information to know what it does when set to 1 and 0 ? Same for better clarity.
set FRAGMENTATION for this case as well as for non-last transfers whereWriting 4 ?
cs_change is not set.
Additionally, setup_gsi_xfer() was storing FRAGMENTATION (BIT(2) = 4) in
peripheral.fragmentation, which is a boolean field consumed by
gpi_create_spi_tre() via u32_encode_bits(..., TRE_SPI_GO_FRAG). Storing 4
causes u32_encode_bits to mask it to 0, silently disabling the FRAG bit inconfusing to understand.
the GPI TRE regardless of the cs_change logic. Store 1 instead.
Without these fixes, TPM TIS SPI transfers deassert CS betweencan we also mention scenario like TPM client controls the CS separately on its own. so it becomes clear to understand requirement also.
single-transfer messages that use cs_change to keep CS asserted across the
header, wait-state, and data phases, breaking TCG SPI flow control:
tpm_tis_spi: probe of spi11.0 failed with error -110Seems typo, should be keep CS de-deasserted between....
Update both setup_se_xfer() and setup_gsi_xfer() to handle this condition.
Fixes: b99181cdf9fa ("spi-geni-qcom: remove manual CS control")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@xxxxxxxxxxxxxxxx>
---
drivers/spi/spi-geni-qcom.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index a04cdc1e5ad4..0618f6bd7878 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -449,10 +449,15 @@ static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas
return ret;
}
- if (!xfer->cs_change) {
- if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))
- peripheral.fragmentation = FRAGMENTATION;
- }
+ /*
+ * Set fragmentation to keep CS asserted after this transfer when:
+ * - non-last transfer with cs_change=0: keep CS between chained transfers
+ * - last transfer with cs_change=1: keep CS asserted after the messagem_params |= FRAGMENTATION ?
+ * (e.g. TPM TIS SPI uses cs_change=1 on single-transfer messages to
+ * keep CS asserted across header, wait-state and data phases)
+ */
+ peripheral.fragmentation = list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers) ?
+ xfer->cs_change : !xfer->cs_change;
if (peripheral.cmd & SPI_RX) {
dmaengine_slave_config(mas->rx, &config);
@@ -858,10 +863,16 @@ static int setup_se_xfer(struct spi_transfer *xfer,
mas->cur_xfer_mode = GENI_SE_DMA;
geni_se_select_mode(se, mas->cur_xfer_mode);
- if (!xfer->cs_change) {
- if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))
- m_params = FRAGMENTATION;
- }
+ /*
+ * Set FRAGMENTATION to keep CS asserted after this transfer when:
+ * - non-last transfer with cs_change=0: keep CS between chained transfers
+ * - last transfer with cs_change=1: keep CS asserted after the message
+ * (e.g. TPM TIS SPI uses cs_change=1 on single-transfer messages to
+ * keep CS asserted across header, wait-state and data phases)
+ */
+ if (list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers) ?
+ xfer->cs_change : !xfer->cs_change)
+ m_params = FRAGMENTATION;
/*
* Lock around right before we start the transfer since our
---
base-commit: e7d700e14934e68f86338c5610cf2ae76798b663
change-id: 20260528-fix-spi-fragmentation-bit-logic-880394337ff9
Best regards,
--
Viken Dadhaniya <viken.dadhaniya@xxxxxxxxxxxxxxxx>