linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] spi: a3700: Add improvements and full-duplex transfers
@ 2018-01-17 16:15 Maxime Chevallier
  2018-01-17 16:15 ` [PATCH 1/4] spi: a3700: Clear DATA_OUT when performing a read Maxime Chevallier
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Maxime Chevallier @ 2018-01-17 16:15 UTC (permalink / raw)
  To: broonie
  Cc: linux-spi, linux-kernel, linux-arm-kernel, gregory.clement,
	Maxime Chevallier

This patchset adds some improvements on the existing Armada 3700 SPI
driver, the biggest being adding support for full-duplex transfers.

The first patch fixes an undocumented (to my knowledge, I might have
missed something) behaviour where some of the content of the last
write transfer is shifted out during a read half-duplex operation.

The second one sets the correct limits on the SPI max and min
frequencies, based on the source clock rate.

The last 2 patches enable full-duplex transfers. On this controller,
full-duplex transfers cannot use the hardware FIFOs and have to be
performed either 1 or 4 bytes at a time. Because this is more
CPU intensive, and a bit slower than FIFO mode, we only use the
full-duplex way of transferring data when necessary.

Maxime Chevallier (4):
  spi: a3700: Clear DATA_OUT when performing a read
  spi: a3700: Set frequency limits at startup
  spi: a3700: Allow to enable or disable FIFO mode
  spi: a3700: Add full-duplex support

 drivers/spi/spi-armada-3700.c | 106 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 91 insertions(+), 15 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/4] spi: a3700: Clear DATA_OUT when performing a read
  2018-01-17 16:15 [PATCH 0/4] spi: a3700: Add improvements and full-duplex transfers Maxime Chevallier
@ 2018-01-17 16:15 ` Maxime Chevallier
  2018-01-18 11:24   ` Applied "spi: a3700: Clear DATA_OUT when performing a read" to the spi tree Mark Brown
  2018-01-17 16:15 ` [PATCH 2/4] spi: a3700: Set frequency limits at startup Maxime Chevallier
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Maxime Chevallier @ 2018-01-17 16:15 UTC (permalink / raw)
  To: broonie
  Cc: linux-spi, linux-kernel, linux-arm-kernel, gregory.clement,
	Maxime Chevallier

When performing a read using FIFO mode, the spi controller shifts out
the last 2 bytes that were written in a previous transfer on MOSI.

This undocumented behaviour can cause devices to misinterpret the
transfer, so we explicitly clear the WFIFO before each read.

This behaviour was noticed on EspressoBin.

Signed-off-by: Maxime Chevallier <maxime.chevallier@smile.fr>
---
 drivers/spi/spi-armada-3700.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c
index d653453..c11ea6c 100644
--- a/drivers/spi/spi-armada-3700.c
+++ b/drivers/spi/spi-armada-3700.c
@@ -615,6 +615,11 @@ static int a3700_spi_transfer_one(struct spi_master *master,
 	a3700_spi_header_set(a3700_spi);
 
 	if (xfer->rx_buf) {
+		/* Clear WFIFO, since it's last 2 bytes are shifted out during
+		 * a read operation
+		 */
+		spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, 0);
+
 		/* Set read data length */
 		spireg_write(a3700_spi, A3700_SPI_IF_DIN_CNT_REG,
 			     a3700_spi->buf_len);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/4] spi: a3700: Set frequency limits at startup
  2018-01-17 16:15 [PATCH 0/4] spi: a3700: Add improvements and full-duplex transfers Maxime Chevallier
  2018-01-17 16:15 ` [PATCH 1/4] spi: a3700: Clear DATA_OUT when performing a read Maxime Chevallier
@ 2018-01-17 16:15 ` Maxime Chevallier
  2018-01-18 11:23   ` Applied "spi: a3700: Set frequency limits at startup" to the spi tree Mark Brown
  2018-01-17 16:15 ` [PATCH 3/4] spi: a3700: Allow to enable or disable FIFO mode Maxime Chevallier
  2018-01-17 16:15 ` [PATCH 4/4] spi: a3700: Add full-duplex support Maxime Chevallier
  3 siblings, 1 reply; 9+ messages in thread
From: Maxime Chevallier @ 2018-01-17 16:15 UTC (permalink / raw)
  To: broonie
  Cc: linux-spi, linux-kernel, linux-arm-kernel, gregory.clement,
	Maxime Chevallier

Armada 3700 SPI controller has an internal clock divider which can
divide the parent clock frequency by up to 30.

This patch sets the limits in the spi_controller fields so that we can
detect when a non-supported frequency is requested by a device for a
transfer.

Signed-off-by: Maxime Chevallier <maxime.chevallier@smile.fr>
---
 drivers/spi/spi-armada-3700.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c
index c11ea6c..8048468 100644
--- a/drivers/spi/spi-armada-3700.c
+++ b/drivers/spi/spi-armada-3700.c
@@ -27,6 +27,8 @@
 
 #define DRIVER_NAME			"armada_3700_spi"
 
+#define A3700_SPI_MAX_SPEED_HZ		100000000
+#define A3700_SPI_MAX_PRESCALE		30
 #define A3700_SPI_TIMEOUT		10
 
 /* SPI Register Offest */
@@ -823,6 +825,11 @@ static int a3700_spi_probe(struct platform_device *pdev)
 		goto error;
 	}
 
+	master->max_speed_hz = min_t(unsigned long, A3700_SPI_MAX_SPEED_HZ,
+					clk_get_rate(spi->clk));
+	master->min_speed_hz = DIV_ROUND_UP(clk_get_rate(spi->clk),
+						A3700_SPI_MAX_PRESCALE);
+
 	ret = a3700_spi_init(spi);
 	if (ret)
 		goto error_clk;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/4] spi: a3700: Allow to enable or disable FIFO mode
  2018-01-17 16:15 [PATCH 0/4] spi: a3700: Add improvements and full-duplex transfers Maxime Chevallier
  2018-01-17 16:15 ` [PATCH 1/4] spi: a3700: Clear DATA_OUT when performing a read Maxime Chevallier
  2018-01-17 16:15 ` [PATCH 2/4] spi: a3700: Set frequency limits at startup Maxime Chevallier
@ 2018-01-17 16:15 ` Maxime Chevallier
  2018-01-18 11:23   ` Applied "spi: a3700: Allow to enable or disable FIFO mode" to the spi tree Mark Brown
  2018-01-17 16:15 ` [PATCH 4/4] spi: a3700: Add full-duplex support Maxime Chevallier
  3 siblings, 1 reply; 9+ messages in thread
From: Maxime Chevallier @ 2018-01-17 16:15 UTC (permalink / raw)
  To: broonie
  Cc: linux-spi, linux-kernel, linux-arm-kernel, gregory.clement,
	Maxime Chevallier

The armada 3700 SPI controller allows to make transfers without using
the 32 bytes RFIFO and WFIFO.

This commit enable switching between FIFO and non-FIFO mode, which is
necessary to implement full-duplex transfers.

Signed-off-by: Maxime Chevallier <maxime.chevallier@smile.fr>
---
 drivers/spi/spi-armada-3700.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c
index 8048468..b387309 100644
--- a/drivers/spi/spi-armada-3700.c
+++ b/drivers/spi/spi-armada-3700.c
@@ -186,12 +186,15 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
 	return 0;
 }
 
-static void a3700_spi_fifo_mode_set(struct a3700_spi *a3700_spi)
+static void a3700_spi_fifo_mode_set(struct a3700_spi *a3700_spi, bool enable)
 {
 	u32 val;
 
 	val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG);
-	val |= A3700_SPI_FIFO_MODE;
+	if (enable)
+		val |= A3700_SPI_FIFO_MODE;
+	else
+		val &= ~A3700_SPI_FIFO_MODE;
 	spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val);
 }
 
@@ -299,7 +302,7 @@ static int a3700_spi_init(struct a3700_spi *a3700_spi)
 		a3700_spi_deactivate_cs(a3700_spi, i);
 
 	/* Enable FIFO mode */
-	a3700_spi_fifo_mode_set(a3700_spi);
+	a3700_spi_fifo_mode_set(a3700_spi, true);
 
 	/* Set SPI mode */
 	a3700_spi_mode_set(a3700_spi, master->mode_bits);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/4] spi: a3700: Add full-duplex support
  2018-01-17 16:15 [PATCH 0/4] spi: a3700: Add improvements and full-duplex transfers Maxime Chevallier
                   ` (2 preceding siblings ...)
  2018-01-17 16:15 ` [PATCH 3/4] spi: a3700: Allow to enable or disable FIFO mode Maxime Chevallier
@ 2018-01-17 16:15 ` Maxime Chevallier
  2018-01-18 11:23   ` Applied "spi: a3700: Add full-duplex support" to the spi tree Mark Brown
  3 siblings, 1 reply; 9+ messages in thread
From: Maxime Chevallier @ 2018-01-17 16:15 UTC (permalink / raw)
  To: broonie
  Cc: linux-spi, linux-kernel, linux-arm-kernel, gregory.clement,
	Maxime Chevallier

The armada 3700 SPI controller has support for full-duplex transfers,
but it can only be done without using the hardware FIFOs.

A full duplex transfer is done by shifting 4 bytes at a time, or even
one byte at a time for transfers less than 4 bytes long.

While this method is perfectly suitable for small transfers, it is still
slower than using the FIFOs.

This commit implement full-duplex support, making sure that half-duplex
transfers are still done using the FIFOs with the existing method.

Some setup functions were moved around to make sure the controller is
properly configured before beginning each transfer.

This was tested on EspressoBin with a logical analyser, and a simple
setup where MISO is connected on MOSI. Transfers were made from
userspace using spidev and spi-pipe from the spi-tools project

Signed-off-by: Maxime Chevallier <maxime.chevallier@smile.fr>
---
 drivers/spi/spi-armada-3700.c | 85 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 73 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c
index b387309..a8576c8 100644
--- a/drivers/spi/spi-armada-3700.c
+++ b/drivers/spi/spi-armada-3700.c
@@ -421,15 +421,20 @@ static void a3700_spi_transfer_setup(struct spi_device *spi,
 				     struct spi_transfer *xfer)
 {
 	struct a3700_spi *a3700_spi;
-	unsigned int byte_len;
 
 	a3700_spi = spi_master_get_devdata(spi->master);
 
 	a3700_spi_clock_set(a3700_spi, xfer->speed_hz);
 
-	byte_len = xfer->bits_per_word >> 3;
+	/* Use 4 bytes long transfers. Each transfer method has its way to deal
+	 * with the remaining bytes for non 4-bytes aligned transfers.
+	 */
+	a3700_spi_bytelen_set(a3700_spi, 4);
 
-	a3700_spi_fifo_thres_set(a3700_spi, byte_len);
+	/* Initialize the working buffers */
+	a3700_spi->tx_buf  = xfer->tx_buf;
+	a3700_spi->rx_buf  = xfer->rx_buf;
+	a3700_spi->buf_len = xfer->len;
 }
 
 static void a3700_spi_set_cs(struct spi_device *spi, bool enable)
@@ -584,27 +589,26 @@ static int a3700_spi_prepare_message(struct spi_master *master,
 	if (ret)
 		return ret;
 
-	a3700_spi_bytelen_set(a3700_spi, 4);
-
 	a3700_spi_mode_set(a3700_spi, spi->mode);
 
 	return 0;
 }
 
-static int a3700_spi_transfer_one(struct spi_master *master,
+static int a3700_spi_transfer_one_fifo(struct spi_master *master,
 				  struct spi_device *spi,
 				  struct spi_transfer *xfer)
 {
 	struct a3700_spi *a3700_spi = spi_master_get_devdata(master);
 	int ret = 0, timeout = A3700_SPI_TIMEOUT;
-	unsigned int nbits = 0;
+	unsigned int nbits = 0, byte_len;
 	u32 val;
 
-	a3700_spi_transfer_setup(spi, xfer);
+	/* Make sure we use FIFO mode */
+	a3700_spi_fifo_mode_set(a3700_spi, true);
 
-	a3700_spi->tx_buf  = xfer->tx_buf;
-	a3700_spi->rx_buf  = xfer->rx_buf;
-	a3700_spi->buf_len = xfer->len;
+	/* Configure FIFO thresholds */
+	byte_len = xfer->bits_per_word >> 3;
+	a3700_spi_fifo_thres_set(a3700_spi, byte_len);
 
 	if (xfer->tx_buf)
 		nbits = xfer->tx_nbits;
@@ -739,6 +743,64 @@ static int a3700_spi_transfer_one(struct spi_master *master,
 	return ret;
 }
 
+static int a3700_spi_transfer_one_full_duplex(struct spi_master *master,
+				  struct spi_device *spi,
+				  struct spi_transfer *xfer)
+{
+	struct a3700_spi *a3700_spi = spi_master_get_devdata(master);
+	u32 val_in, val_out;
+
+	/* Disable FIFO mode */
+	a3700_spi_fifo_mode_set(a3700_spi, false);
+
+	while (a3700_spi->buf_len) {
+
+		/* When we have less than 4 bytes to transfer, switch to 1 byte
+		 * mode. This is reset after each transfer
+		 */
+		if (a3700_spi->buf_len < 4)
+			a3700_spi_bytelen_set(a3700_spi, 1);
+
+		if (a3700_spi->byte_len == 1)
+			val_out = *a3700_spi->tx_buf;
+		else
+			val_out = cpu_to_le32(*(u32 *)a3700_spi->tx_buf);
+
+		spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val_out);
+
+		/* Wait for all the data to be shifted in / out */
+		while (!(spireg_read(a3700_spi, A3700_SPI_IF_CTRL_REG) &
+				A3700_SPI_XFER_DONE))
+			cpu_relax();
+
+		val_in = le32_to_cpu(spireg_read(a3700_spi,
+						 A3700_SPI_DATA_IN_REG));
+
+		memcpy(a3700_spi->rx_buf, &val_in, a3700_spi->byte_len);
+
+		a3700_spi->buf_len -= a3700_spi->byte_len;
+		a3700_spi->tx_buf += a3700_spi->byte_len;
+		a3700_spi->rx_buf += a3700_spi->byte_len;
+
+	}
+
+	spi_finalize_current_transfer(master);
+
+	return 0;
+}
+
+static int a3700_spi_transfer_one(struct spi_master *master,
+				  struct spi_device *spi,
+				  struct spi_transfer *xfer)
+{
+	a3700_spi_transfer_setup(spi, xfer);
+
+	if (xfer->tx_buf && xfer->rx_buf)
+		return a3700_spi_transfer_one_full_duplex(master, spi, xfer);
+
+	return a3700_spi_transfer_one_fifo(master, spi, xfer);
+}
+
 static int a3700_spi_unprepare_message(struct spi_master *master,
 				       struct spi_message *message)
 {
@@ -788,7 +850,6 @@ static int a3700_spi_probe(struct platform_device *pdev)
 	master->transfer_one = a3700_spi_transfer_one;
 	master->unprepare_message = a3700_spi_unprepare_message;
 	master->set_cs = a3700_spi_set_cs;
-	master->flags = SPI_MASTER_HALF_DUPLEX;
 	master->mode_bits |= (SPI_RX_DUAL | SPI_TX_DUAL |
 			      SPI_RX_QUAD | SPI_TX_QUAD);
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Applied "spi: a3700: Add full-duplex support" to the spi tree
  2018-01-17 16:15 ` [PATCH 4/4] spi: a3700: Add full-duplex support Maxime Chevallier
@ 2018-01-18 11:23   ` Mark Brown
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2018-01-18 11:23 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: Mark Brown, broonie, linux-spi, linux-kernel, linux-arm-kernel,
	gregory.clement, linux-spi

The patch

   spi: a3700: Add full-duplex support

has been applied to the spi tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From f68a7dcb91b7957c5bb1c3e347775332af719519 Mon Sep 17 00:00:00 2001
From: Maxime Chevallier <maxime.chevallier@smile.fr>
Date: Wed, 17 Jan 2018 17:15:28 +0100
Subject: [PATCH] spi: a3700: Add full-duplex support

The armada 3700 SPI controller has support for full-duplex transfers,
but it can only be done without using the hardware FIFOs.

A full duplex transfer is done by shifting 4 bytes at a time, or even
one byte at a time for transfers less than 4 bytes long.

While this method is perfectly suitable for small transfers, it is still
slower than using the FIFOs.

This commit implement full-duplex support, making sure that half-duplex
transfers are still done using the FIFOs with the existing method.

Some setup functions were moved around to make sure the controller is
properly configured before beginning each transfer.

This was tested on EspressoBin with a logical analyser, and a simple
setup where MISO is connected on MOSI. Transfers were made from
userspace using spidev and spi-pipe from the spi-tools project

Signed-off-by: Maxime Chevallier <maxime.chevallier@smile.fr>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/spi/spi-armada-3700.c | 85 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 73 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c
index 97938c6d6267..fdc35dabcda2 100644
--- a/drivers/spi/spi-armada-3700.c
+++ b/drivers/spi/spi-armada-3700.c
@@ -413,15 +413,20 @@ static void a3700_spi_transfer_setup(struct spi_device *spi,
 				     struct spi_transfer *xfer)
 {
 	struct a3700_spi *a3700_spi;
-	unsigned int byte_len;
 
 	a3700_spi = spi_master_get_devdata(spi->master);
 
 	a3700_spi_clock_set(a3700_spi, xfer->speed_hz);
 
-	byte_len = xfer->bits_per_word >> 3;
+	/* Use 4 bytes long transfers. Each transfer method has its way to deal
+	 * with the remaining bytes for non 4-bytes aligned transfers.
+	 */
+	a3700_spi_bytelen_set(a3700_spi, 4);
 
-	a3700_spi_fifo_thres_set(a3700_spi, byte_len);
+	/* Initialize the working buffers */
+	a3700_spi->tx_buf  = xfer->tx_buf;
+	a3700_spi->rx_buf  = xfer->rx_buf;
+	a3700_spi->buf_len = xfer->len;
 }
 
 static void a3700_spi_set_cs(struct spi_device *spi, bool enable)
@@ -576,27 +581,26 @@ static int a3700_spi_prepare_message(struct spi_master *master,
 	if (ret)
 		return ret;
 
-	a3700_spi_bytelen_set(a3700_spi, 4);
-
 	a3700_spi_mode_set(a3700_spi, spi->mode);
 
 	return 0;
 }
 
-static int a3700_spi_transfer_one(struct spi_master *master,
+static int a3700_spi_transfer_one_fifo(struct spi_master *master,
 				  struct spi_device *spi,
 				  struct spi_transfer *xfer)
 {
 	struct a3700_spi *a3700_spi = spi_master_get_devdata(master);
 	int ret = 0, timeout = A3700_SPI_TIMEOUT;
-	unsigned int nbits = 0;
+	unsigned int nbits = 0, byte_len;
 	u32 val;
 
-	a3700_spi_transfer_setup(spi, xfer);
+	/* Make sure we use FIFO mode */
+	a3700_spi_fifo_mode_set(a3700_spi, true);
 
-	a3700_spi->tx_buf  = xfer->tx_buf;
-	a3700_spi->rx_buf  = xfer->rx_buf;
-	a3700_spi->buf_len = xfer->len;
+	/* Configure FIFO thresholds */
+	byte_len = xfer->bits_per_word >> 3;
+	a3700_spi_fifo_thres_set(a3700_spi, byte_len);
 
 	if (xfer->tx_buf)
 		nbits = xfer->tx_nbits;
@@ -731,6 +735,64 @@ static int a3700_spi_transfer_one(struct spi_master *master,
 	return ret;
 }
 
+static int a3700_spi_transfer_one_full_duplex(struct spi_master *master,
+				  struct spi_device *spi,
+				  struct spi_transfer *xfer)
+{
+	struct a3700_spi *a3700_spi = spi_master_get_devdata(master);
+	u32 val_in, val_out;
+
+	/* Disable FIFO mode */
+	a3700_spi_fifo_mode_set(a3700_spi, false);
+
+	while (a3700_spi->buf_len) {
+
+		/* When we have less than 4 bytes to transfer, switch to 1 byte
+		 * mode. This is reset after each transfer
+		 */
+		if (a3700_spi->buf_len < 4)
+			a3700_spi_bytelen_set(a3700_spi, 1);
+
+		if (a3700_spi->byte_len == 1)
+			val_out = *a3700_spi->tx_buf;
+		else
+			val_out = cpu_to_le32(*(u32 *)a3700_spi->tx_buf);
+
+		spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val_out);
+
+		/* Wait for all the data to be shifted in / out */
+		while (!(spireg_read(a3700_spi, A3700_SPI_IF_CTRL_REG) &
+				A3700_SPI_XFER_DONE))
+			cpu_relax();
+
+		val_in = le32_to_cpu(spireg_read(a3700_spi,
+						 A3700_SPI_DATA_IN_REG));
+
+		memcpy(a3700_spi->rx_buf, &val_in, a3700_spi->byte_len);
+
+		a3700_spi->buf_len -= a3700_spi->byte_len;
+		a3700_spi->tx_buf += a3700_spi->byte_len;
+		a3700_spi->rx_buf += a3700_spi->byte_len;
+
+	}
+
+	spi_finalize_current_transfer(master);
+
+	return 0;
+}
+
+static int a3700_spi_transfer_one(struct spi_master *master,
+				  struct spi_device *spi,
+				  struct spi_transfer *xfer)
+{
+	a3700_spi_transfer_setup(spi, xfer);
+
+	if (xfer->tx_buf && xfer->rx_buf)
+		return a3700_spi_transfer_one_full_duplex(master, spi, xfer);
+
+	return a3700_spi_transfer_one_fifo(master, spi, xfer);
+}
+
 static int a3700_spi_unprepare_message(struct spi_master *master,
 				       struct spi_message *message)
 {
@@ -780,7 +842,6 @@ static int a3700_spi_probe(struct platform_device *pdev)
 	master->transfer_one = a3700_spi_transfer_one;
 	master->unprepare_message = a3700_spi_unprepare_message;
 	master->set_cs = a3700_spi_set_cs;
-	master->flags = SPI_MASTER_HALF_DUPLEX;
 	master->mode_bits |= (SPI_RX_DUAL | SPI_TX_DUAL |
 			      SPI_RX_QUAD | SPI_TX_QUAD);
 
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Applied "spi: a3700: Allow to enable or disable FIFO mode" to the spi tree
  2018-01-17 16:15 ` [PATCH 3/4] spi: a3700: Allow to enable or disable FIFO mode Maxime Chevallier
@ 2018-01-18 11:23   ` Mark Brown
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2018-01-18 11:23 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: Mark Brown, broonie, linux-spi, linux-kernel, linux-arm-kernel,
	gregory.clement, linux-spi

The patch

   spi: a3700: Allow to enable or disable FIFO mode

has been applied to the spi tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From a456c9320d997fdb26bfab496dd9e37f155cc788 Mon Sep 17 00:00:00 2001
From: Maxime Chevallier <maxime.chevallier@smile.fr>
Date: Wed, 17 Jan 2018 17:15:27 +0100
Subject: [PATCH] spi: a3700: Allow to enable or disable FIFO mode

The armada 3700 SPI controller allows to make transfers without using
the 32 bytes RFIFO and WFIFO.

This commit enable switching between FIFO and non-FIFO mode, which is
necessary to implement full-duplex transfers.

Signed-off-by: Maxime Chevallier <maxime.chevallier@smile.fr>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/spi/spi-armada-3700.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c
index 07f227e3c834..97938c6d6267 100644
--- a/drivers/spi/spi-armada-3700.c
+++ b/drivers/spi/spi-armada-3700.c
@@ -185,12 +185,15 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
 	return 0;
 }
 
-static void a3700_spi_fifo_mode_set(struct a3700_spi *a3700_spi)
+static void a3700_spi_fifo_mode_set(struct a3700_spi *a3700_spi, bool enable)
 {
 	u32 val;
 
 	val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG);
-	val |= A3700_SPI_FIFO_MODE;
+	if (enable)
+		val |= A3700_SPI_FIFO_MODE;
+	else
+		val &= ~A3700_SPI_FIFO_MODE;
 	spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val);
 }
 
@@ -291,7 +294,7 @@ static int a3700_spi_init(struct a3700_spi *a3700_spi)
 		a3700_spi_deactivate_cs(a3700_spi, i);
 
 	/* Enable FIFO mode */
-	a3700_spi_fifo_mode_set(a3700_spi);
+	a3700_spi_fifo_mode_set(a3700_spi, true);
 
 	/* Set SPI mode */
 	a3700_spi_mode_set(a3700_spi, master->mode_bits);
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Applied "spi: a3700: Set frequency limits at startup" to the spi tree
  2018-01-17 16:15 ` [PATCH 2/4] spi: a3700: Set frequency limits at startup Maxime Chevallier
@ 2018-01-18 11:23   ` Mark Brown
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2018-01-18 11:23 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: Mark Brown, broonie, linux-spi, linux-kernel, linux-arm-kernel,
	gregory.clement, linux-spi

The patch

   spi: a3700: Set frequency limits at startup

has been applied to the spi tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From abf3a49e50967bd67cff67f289690f76436f461f Mon Sep 17 00:00:00 2001
From: Maxime Chevallier <maxime.chevallier@smile.fr>
Date: Wed, 17 Jan 2018 17:15:26 +0100
Subject: [PATCH] spi: a3700: Set frequency limits at startup

Armada 3700 SPI controller has an internal clock divider which can
divide the parent clock frequency by up to 30.

This patch sets the limits in the spi_controller fields so that we can
detect when a non-supported frequency is requested by a device for a
transfer.

Signed-off-by: Maxime Chevallier <maxime.chevallier@smile.fr>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/spi/spi-armada-3700.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c
index 4857b0119556..07f227e3c834 100644
--- a/drivers/spi/spi-armada-3700.c
+++ b/drivers/spi/spi-armada-3700.c
@@ -27,6 +27,8 @@
 
 #define DRIVER_NAME			"armada_3700_spi"
 
+#define A3700_SPI_MAX_SPEED_HZ		100000000
+#define A3700_SPI_MAX_PRESCALE		30
 #define A3700_SPI_TIMEOUT		10
 
 /* SPI Register Offest */
@@ -815,6 +817,11 @@ static int a3700_spi_probe(struct platform_device *pdev)
 		goto error;
 	}
 
+	master->max_speed_hz = min_t(unsigned long, A3700_SPI_MAX_SPEED_HZ,
+					clk_get_rate(spi->clk));
+	master->min_speed_hz = DIV_ROUND_UP(clk_get_rate(spi->clk),
+						A3700_SPI_MAX_PRESCALE);
+
 	ret = a3700_spi_init(spi);
 	if (ret)
 		goto error_clk;
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Applied "spi: a3700: Clear DATA_OUT when performing a read" to the spi tree
  2018-01-17 16:15 ` [PATCH 1/4] spi: a3700: Clear DATA_OUT when performing a read Maxime Chevallier
@ 2018-01-18 11:24   ` Mark Brown
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2018-01-18 11:24 UTC (permalink / raw)
  To: Maxime Chevallier
  Cc: Mark Brown, broonie, linux-spi, linux-kernel, linux-arm-kernel,
	gregory.clement, linux-spi

The patch

   spi: a3700: Clear DATA_OUT when performing a read

has been applied to the spi tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 44a5f423e70374e5b42cecd85e78f2d79334e0f2 Mon Sep 17 00:00:00 2001
From: Maxime Chevallier <maxime.chevallier@smile.fr>
Date: Wed, 17 Jan 2018 17:15:25 +0100
Subject: [PATCH] spi: a3700: Clear DATA_OUT when performing a read

When performing a read using FIFO mode, the spi controller shifts out
the last 2 bytes that were written in a previous transfer on MOSI.

This undocumented behaviour can cause devices to misinterpret the
transfer, so we explicitly clear the WFIFO before each read.

This behaviour was noticed on EspressoBin.

Signed-off-by: Maxime Chevallier <maxime.chevallier@smile.fr>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/spi/spi-armada-3700.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c
index 77fe55ce790c..4857b0119556 100644
--- a/drivers/spi/spi-armada-3700.c
+++ b/drivers/spi/spi-armada-3700.c
@@ -607,6 +607,11 @@ static int a3700_spi_transfer_one(struct spi_master *master,
 	a3700_spi_header_set(a3700_spi);
 
 	if (xfer->rx_buf) {
+		/* Clear WFIFO, since it's last 2 bytes are shifted out during
+		 * a read operation
+		 */
+		spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, 0);
+
 		/* Set read data length */
 		spireg_write(a3700_spi, A3700_SPI_IF_DIN_CNT_REG,
 			     a3700_spi->buf_len);
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-01-18 11:24 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-17 16:15 [PATCH 0/4] spi: a3700: Add improvements and full-duplex transfers Maxime Chevallier
2018-01-17 16:15 ` [PATCH 1/4] spi: a3700: Clear DATA_OUT when performing a read Maxime Chevallier
2018-01-18 11:24   ` Applied "spi: a3700: Clear DATA_OUT when performing a read" to the spi tree Mark Brown
2018-01-17 16:15 ` [PATCH 2/4] spi: a3700: Set frequency limits at startup Maxime Chevallier
2018-01-18 11:23   ` Applied "spi: a3700: Set frequency limits at startup" to the spi tree Mark Brown
2018-01-17 16:15 ` [PATCH 3/4] spi: a3700: Allow to enable or disable FIFO mode Maxime Chevallier
2018-01-18 11:23   ` Applied "spi: a3700: Allow to enable or disable FIFO mode" to the spi tree Mark Brown
2018-01-17 16:15 ` [PATCH 4/4] spi: a3700: Add full-duplex support Maxime Chevallier
2018-01-18 11:23   ` Applied "spi: a3700: Add full-duplex support" to the spi tree Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).