Messages in this thread |  | | Subject | Re: [PATCH v1] spi: qcom-geni: Fix cs_change handling on the last transfer | | From | Jonathan Marek <> | | Date | Fri, 5 Jun 2026 12:24:34 -0400 |
| |
should have another Fixes tag for the GSI xfer fix, otherwise LTGM
Reviewed-by: Jonathan Marek <jonathan@marek.ca>
On 5/28/26 3:03 PM, Viken Dadhaniya wrote: > Commit b99181cdf9fa ("spi-geni-qcom: remove manual CS control") introduced > 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 > the message completes. Since GENI SPI controls CS through FRAGMENTATION, > set FRAGMENTATION for this case as well as for non-last transfers where > 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 in > the GPI TRE regardless of the cs_change logic. Store 1 instead. > > Without these fixes, TPM TIS SPI transfers deassert CS between > 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 -110 > > Update both setup_se_xfer() and setup_gsi_xfer() to handle this condition. > > Fixes: b99181cdf9fa ("spi-geni-qcom: remove manual CS control") > Cc: stable@vger.kernel.org > Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com> > --- > 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 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) > + */ > + 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@oss.qualcomm.com> >
|  |