All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/2 V3] SPI: Enable SPI_PREAMBLE Mode
@ 2013-05-24 13:18 Rajeshwari Shinde
  2013-05-24 13:18 ` [U-Boot] [PATCH 1/2 V3] SPI: Add support for preamble bytes Rajeshwari Shinde
  2013-05-24 13:18 ` [U-Boot] [PATCH 2/2 V3] EXYNOS: SPI: Support SPI_PREAMBLE mode Rajeshwari Shinde
  0 siblings, 2 replies; 3+ messages in thread
From: Rajeshwari Shinde @ 2013-05-24 13:18 UTC (permalink / raw)
  To: u-boot

This patch set enables PREAMBLE Mode for EXYNOS SPI.

Changes in v2:
	- Remove preamable_count variable which is not really needed
	- Fix checkpatch warning (multiple assignments)
Changes in V3:
	- Modified the if logic in spi_rx_tx function
	- Added blank lines as suggested by Minkyu Kang.
	- Removed in_bytes check in while loop.
	- Added a error check.
Rajeshwari Shinde (2):
  SPI: Add support for preamble bytes
  EXYNOS: SPI: Support SPI_PREAMBLE mode

 drivers/spi/exynos_spi.c |   69 +++++++++++++++++++++++++++++++++++++++------
 include/spi.h            |    5 +++
 2 files changed, 64 insertions(+), 10 deletions(-)

-- 
1.7.4.4

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

* [U-Boot] [PATCH 1/2 V3] SPI: Add support for preamble bytes
  2013-05-24 13:18 [U-Boot] [PATCH 0/2 V3] SPI: Enable SPI_PREAMBLE Mode Rajeshwari Shinde
@ 2013-05-24 13:18 ` Rajeshwari Shinde
  2013-05-24 13:18 ` [U-Boot] [PATCH 2/2 V3] EXYNOS: SPI: Support SPI_PREAMBLE mode Rajeshwari Shinde
  1 sibling, 0 replies; 3+ messages in thread
From: Rajeshwari Shinde @ 2013-05-24 13:18 UTC (permalink / raw)
  To: u-boot

A SPI slave may take time to react to a request. For SPI flash devices
this time is defined as one bit time, or a whole byte for 'fast read'
mode.

If the SPI slave is another CPU, then the time it takes to react may
vary. It is convenient to allow the slave device to tag the start of
the actual reply so that the host can determine when this 'preamble'
finishes and the actual message starts.

Add a preamble flag to the available SPI flags. If supported by the
driver then it will ignore any received bytes before the preamble
on each transaction. This ensures that reliable communication with
the slave is possible.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
---
Changes in V2:
	- None
Changes in V3:
	- None.
 include/spi.h |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/include/spi.h b/include/spi.h
index 3fe2e1e..1638b50 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -37,11 +37,16 @@
 #define	SPI_LSB_FIRST	0x08			/* per-word bits-on-wire */
 #define	SPI_3WIRE	0x10			/* SI/SO signals shared */
 #define	SPI_LOOP	0x20			/* loopback mode */
+#define	SPI_SLAVE	0x40			/* slave mode */
+#define	SPI_PREAMBLE	0x80			/* Skip preamble bytes */
 
 /* SPI transfer flags */
 #define SPI_XFER_BEGIN	0x01			/* Assert CS before transfer */
 #define SPI_XFER_END	0x02			/* Deassert CS after transfer */
 
+/* Header byte that marks the start of the message */
+#define SPI_PREAMBLE_END_BYTE	0xec
+
 /*-----------------------------------------------------------------------
  * Representation of a SPI slave, i.e. what we're communicating with.
  *
-- 
1.7.4.4

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

* [U-Boot] [PATCH 2/2 V3] EXYNOS: SPI: Support SPI_PREAMBLE mode
  2013-05-24 13:18 [U-Boot] [PATCH 0/2 V3] SPI: Enable SPI_PREAMBLE Mode Rajeshwari Shinde
  2013-05-24 13:18 ` [U-Boot] [PATCH 1/2 V3] SPI: Add support for preamble bytes Rajeshwari Shinde
@ 2013-05-24 13:18 ` Rajeshwari Shinde
  1 sibling, 0 replies; 3+ messages in thread
From: Rajeshwari Shinde @ 2013-05-24 13:18 UTC (permalink / raw)
  To: u-boot

Support interfaces with a preamble before each received message.

We handle this when the client has requested a SPI_XFER_END, meaning
that we must close of the transaction. In this case we read until we
see the preamble (or a timeout occurs), skipping all data before and
including the preamble. The client will receive only data bytes after
the preamble.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
---
Changes in v2:
	- Remove preamable_count variable which is not really needed
	- Fix checkpatch warning (multiple assignments)
Changes in V3:
	- Modified the if logic in spi_rx_tx function
	- Added blank lines as suggested by Minkyu Kang.
	- Removed in_bytes check in while loop.
	- Added a error check.
 drivers/spi/exynos_spi.c |   69 +++++++++++++++++++++++++++++++++++++++------
 1 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index 607e1cd..99895af 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -51,6 +51,7 @@ struct exynos_spi_slave {
 	unsigned int mode;
 	enum periph_id periph_id;	/* Peripheral ID for this device */
 	unsigned int fifo_size;
+	int skip_preamble;
 };
 
 static struct spi_bus *spi_get_bus(unsigned dev_index)
@@ -105,6 +106,8 @@ struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
 	else
 		spi_slave->fifo_size = 256;
 
+	spi_slave->skip_preamble = 0;
+
 	spi_slave->freq = bus->frequency;
 	if (max_hz)
 		spi_slave->freq = min(max_hz, spi_slave->freq);
@@ -217,17 +220,23 @@ static void spi_request_bytes(struct exynos_spi *regs, int count)
 	writel(count | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
 }
 
-static void spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
-			void **dinp, void const **doutp)
+static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
+			void **dinp, void const **doutp, unsigned long flags)
 {
 	struct exynos_spi *regs = spi_slave->regs;
 	uchar *rxp = *dinp;
 	const uchar *txp = *doutp;
 	int rx_lvl, tx_lvl;
 	uint out_bytes, in_bytes;
+	int toread;
+	unsigned start = get_timer(0);
+	int stopping;
 
 	out_bytes = in_bytes = todo;
 
+	stopping = spi_slave->skip_preamble && (flags & SPI_XFER_END) &&
+					!(spi_slave->mode & SPI_SLAVE);
+
 	/*
 	 * If there's something to send, do a software reset and set a
 	 * transaction size.
@@ -238,6 +247,8 @@ static void spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
 	 * Bytes are transmitted/received in pairs. Wait to receive all the
 	 * data because then transmission will be done as well.
 	 */
+	toread = in_bytes;
+
 	while (in_bytes) {
 		int temp;
 
@@ -248,15 +259,43 @@ static void spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
 			writel(temp, &regs->tx_data);
 			out_bytes--;
 		}
-		if (rx_lvl > 0 && in_bytes) {
+		if (rx_lvl > 0) {
 			temp = readl(&regs->rx_data);
-			if (rxp)
-				*rxp++ = temp;
-			in_bytes--;
+			if (spi_slave->skip_preamble) {
+				if (temp == SPI_PREAMBLE_END_BYTE) {
+					spi_slave->skip_preamble = 0;
+					stopping = 0;
+				}
+			} else {
+				if (rxp || stopping)
+					*rxp++ = temp;
+				in_bytes--;
+			}
+			toread--;
+		} else if (in_bytes) {
+			/*
+			 * We have run out of input data, but haven't read
+			 * enough bytes after the preamble yet. Read some more,
+			 * and make sure that we transmit dummy bytes too, to
+			 * keep things going.
+			 */
+			assert(!out_bytes);
+			out_bytes = in_bytes;
+			toread = in_bytes;
+			txp = NULL;
+			spi_request_bytes(regs, toread);
+		}
+		if (spi_slave->skip_preamble && get_timer(start) > 100) {
+			printf("SPI timeout: in_bytes=%d, out_bytes=%d, ",
+			       in_bytes, out_bytes);
+			return -1;
 		}
 	}
+
 	*dinp = rxp;
 	*doutp = txp;
+
+	return 0;
 }
 
 /**
@@ -276,6 +315,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 	struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
 	int upto, todo;
 	int bytelen;
+	int ret = 0;
 
 	/* spi core configured to do 8 bit transfers */
 	if (bitlen % 8) {
@@ -289,16 +329,24 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 
 	/* Exynos SPI limits each transfer to 65535 bytes */
 	bytelen =  bitlen / 8;
-	for (upto = 0; upto < bytelen; upto += todo) {
+	for (upto = 0; !ret && upto < bytelen; upto += todo) {
 		todo = min(bytelen - upto, (1 << 16) - 1);
-		spi_rx_tx(spi_slave, todo, &din, &dout);
+		ret = spi_rx_tx(spi_slave, todo, &din, &dout, flags);
+		if (ret)
+			break;
 	}
 
 	/* Stop the transaction, if necessary. */
-	if ((flags & SPI_XFER_END))
+	if ((flags & SPI_XFER_END) && !(spi_slave->mode & SPI_SLAVE)) {
 		spi_cs_deactivate(slave);
+		if (spi_slave->skip_preamble) {
+			assert(!spi_slave->skip_preamble);
+			debug("Failed to complete premable transaction\n");
+			ret = -1;
+		}
+	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -325,6 +373,7 @@ void spi_cs_activate(struct spi_slave *slave)
 
 	clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
 	debug("Activate CS, bus %d\n", spi_slave->slave.bus);
+	spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
 }
 
 /**
-- 
1.7.4.4

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

end of thread, other threads:[~2013-05-24 13:18 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-24 13:18 [U-Boot] [PATCH 0/2 V3] SPI: Enable SPI_PREAMBLE Mode Rajeshwari Shinde
2013-05-24 13:18 ` [U-Boot] [PATCH 1/2 V3] SPI: Add support for preamble bytes Rajeshwari Shinde
2013-05-24 13:18 ` [U-Boot] [PATCH 2/2 V3] EXYNOS: SPI: Support SPI_PREAMBLE mode Rajeshwari Shinde

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.