The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Marek Vasut <marex@nabladev.com>
To: linux-spi@vger.kernel.org
Cc: Marek Vasut <marex@nabladev.com>, Fedor Ross <fedor.ross@ifm.com>,
	Frank Li <Frank.Li@nxp.com>, Mark Brown <broonie@kernel.org>,
	imx@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: [PATCH] spi: spi-fsl-lpspi: Handle clock polarity and phase
Date: Tue, 27 Jan 2026 23:23:22 +0100	[thread overview]
Message-ID: <20260127222353.1452003-1-marex@nabladev.com> (raw)

The LPSPI driver currently does not support setting SPI bus clock
polarity and phase, add support for it.

It is important to configure correct initial clock polarity and phase
before the GPIO chipselect toggles, otherwise a chip attached to the
bus might recognize the first change of clock signal as the first
clock cycle and get confused.

In order to set up the correct polarity and phase on the clock signal
before the GPIO chipselects get configured by the SPI core, the
controller has to be briefly brought up in fsl_lpspi_prepare_message().
The fsl_lpspi_prepare_message() behaves like a zero-length transfer
which always uses PIO and never DMA, and which leaves the clock signal
in the correct state at the end of such transfer, which happens before
the GPIO chipselect toggles.

Signed-off-by: Marek Vasut <marex@nabladev.com>
---
Cc: Fedor Ross <fedor.ross@ifm.com>
Cc: Frank Li <Frank.Li@nxp.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: imx@lists.linux.dev
Cc: linux-kernel@vger.kernel.org
Cc: linux-spi@vger.kernel.org
---
 drivers/spi/spi-fsl-lpspi.c | 54 ++++++++++++++++++++++++++++++++++---
 1 file changed, 50 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 6c692568bdf58..b361c1bb3e431 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -281,7 +281,8 @@ static void fsl_lpspi_read_rx_fifo(struct fsl_lpspi_data *fsl_lpspi)
 		fsl_lpspi->rx(fsl_lpspi);
 }
 
-static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi)
+static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi,
+			      struct spi_device *spi)
 {
 	u32 temp = 0;
 
@@ -303,6 +304,13 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi)
 				temp |= TCR_CONTC;
 		}
 	}
+
+	if (spi->mode & SPI_CPOL)
+		temp |= TCR_CPOL;
+
+	if (spi->mode & SPI_CPHA)
+		temp |= TCR_CPHA;
+
 	writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
 
 	dev_dbg(fsl_lpspi->dev, "TCR=0x%x\n", temp);
@@ -488,12 +496,45 @@ static int fsl_lpspi_setup_transfer(struct spi_controller *controller,
 
 	fsl_lpspi->watermark = min(fsl_lpspi->txfifosize, t->len);
 
+	return fsl_lpspi_config(fsl_lpspi);
+}
+
+static int fsl_lpspi_prepare_message(struct spi_controller *controller,
+				     struct spi_message *msg)
+{
+	struct fsl_lpspi_data *fsl_lpspi =
+				spi_controller_get_devdata(controller);
+	struct spi_device *spi = msg->spi;
+	struct spi_transfer *t;
+	int ret;
+
+	t = list_first_entry_or_null(&msg->transfers, struct spi_transfer,
+				     transfer_list);
+	if (!t)
+		return 0;
+
+	fsl_lpspi->is_first_byte = true;
+	fsl_lpspi->usedma = false;
+	ret = fsl_lpspi_setup_transfer(controller, spi, t);
+
 	if (fsl_lpspi_can_dma(controller, spi, t))
 		fsl_lpspi->usedma = true;
 	else
 		fsl_lpspi->usedma = false;
 
-	return fsl_lpspi_config(fsl_lpspi);
+	if (ret < 0)
+		return ret;
+
+	fsl_lpspi_set_cmd(fsl_lpspi, spi);
+
+	/* No IRQs */
+	writel(0, fsl_lpspi->base + IMX7ULP_IER);
+
+	/* Controller disable, clear FIFOs, clear status */
+	writel(CR_RRF | CR_RTF, fsl_lpspi->base + IMX7ULP_CR);
+	writel(SR_CLEAR_MASK, fsl_lpspi->base + IMX7ULP_SR);
+
+	return 0;
 }
 
 static int fsl_lpspi_target_abort(struct spi_controller *controller)
@@ -753,14 +794,18 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller,
 					spi_controller_get_devdata(controller);
 	int ret;
 
-	fsl_lpspi->is_first_byte = true;
+	if (fsl_lpspi_can_dma(controller, spi, t))
+		fsl_lpspi->usedma = true;
+	else
+		fsl_lpspi->usedma = false;
+
 	ret = fsl_lpspi_setup_transfer(controller, spi, t);
 	if (ret < 0)
 		return ret;
 
 	t->effective_speed_hz = fsl_lpspi->config.effective_speed_hz;
 
-	fsl_lpspi_set_cmd(fsl_lpspi);
+	fsl_lpspi_set_cmd(fsl_lpspi, spi);
 	fsl_lpspi->is_first_byte = false;
 
 	if (fsl_lpspi->usedma)
@@ -944,6 +989,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
 	}
 
 	controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
+	controller->prepare_message = fsl_lpspi_prepare_message;
 	controller->transfer_one = fsl_lpspi_transfer_one;
 	controller->prepare_transfer_hardware = lpspi_prepare_xfer_hardware;
 	controller->unprepare_transfer_hardware = lpspi_unprepare_xfer_hardware;
-- 
2.51.0


             reply	other threads:[~2026-01-27 22:24 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-27 22:23 Marek Vasut [this message]
2026-01-28 15:36 ` [PATCH] spi: spi-fsl-lpspi: Handle clock polarity and phase Frank Li
2026-01-28 22:19 ` Mark Brown

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=20260127222353.1452003-1-marex@nabladev.com \
    --to=marex@nabladev.com \
    --cc=Frank.Li@nxp.com \
    --cc=broonie@kernel.org \
    --cc=fedor.ross@ifm.com \
    --cc=imx@lists.linux.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-spi@vger.kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox