linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4] spi: fsl-espi: determine need for byte swap only once
       [not found] ` <2424ba57-be1a-d32d-0c14-1662c2d02409-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2016-11-25 22:58   ` Heiner Kallweit
       [not found]     ` <bfa9887d-ed21-6d89-7e7b-d65c67571d85-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2016-11-25 22:59   ` [PATCH 2/4] spi: fsl-espi: eliminate need for linearization when writing to hardware Heiner Kallweit
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Heiner Kallweit @ 2016-11-25 22:58 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA

Determine need for byte swap only once and store it in new member
swab in struct fsl_espi.

Signed-off-by: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
This extension is needed for subsequent patches of this series.
---
 drivers/spi/spi-fsl-espi.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index 4fbcc36..4222578 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -98,6 +98,7 @@ struct fsl_espi {
 	const void *tx;
 	void *rx;
 
+	bool swab;
 	unsigned int rx_len;
 	unsigned int tx_len;
 	unsigned int rxskip;
@@ -140,14 +141,14 @@ static void fsl_espi_memcpy_swab(void *to, const void *from,
 				 struct spi_message *m,
 				 struct spi_transfer *t)
 {
+	struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
 	unsigned int len = t->len;
 
-	if (!(m->spi->mode & SPI_LSB_FIRST) || t->bits_per_word <= 8) {
+	if (!espi->swab) {
 		memcpy(to, from, len);
 		return;
 	}
 
-	/* In case of LSB-first and bits_per_word > 8 byte-swap all words */
 	while (len)
 		if (len >= 4) {
 			*(u32 *)to = swahb32p(from);
@@ -384,6 +385,9 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 	struct spi_device *spi = m->spi;
 	int ret;
 
+	/* In case of LSB-first and bits_per_word > 8 byte-swap all words */
+	espi->swab = spi->mode & SPI_LSB_FIRST && trans->bits_per_word > 8;
+
 	espi->rxskip = fsl_espi_check_rxskip_mode(m);
 	if (trans->rx_nbits == SPI_NBITS_DUAL && !espi->rxskip) {
 		dev_err(espi->dev, "Dual output mode requires RXSKIP mode!\n");
-- 
2.10.2


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 2/4] spi: fsl-espi: eliminate need for linearization when writing to hardware
       [not found] ` <2424ba57-be1a-d32d-0c14-1662c2d02409-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2016-11-25 22:58   ` [PATCH 1/4] spi: fsl-espi: determine need for byte swap only once Heiner Kallweit
@ 2016-11-25 22:59   ` Heiner Kallweit
       [not found]     ` <fe019347-2d40-7e0a-4ee4-cadaa8930d5f-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2016-11-25 22:59   ` [PATCH 3/4] spi: fsl-espi: eliminate need for linearization when reading from hardware Heiner Kallweit
  2016-11-25 23:00   ` [PATCH 4/4] spi: fsl-espi: remove unused linearization code Heiner Kallweit
  3 siblings, 1 reply; 8+ messages in thread
From: Heiner Kallweit @ 2016-11-25 22:59 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA

Eliminate need for linearization when writing to the hardware and
read from the transfer buffers directly.

Signed-off-by: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/spi/spi-fsl-espi.c | 79 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 65 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index 4222578..189ab36 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -98,6 +98,11 @@ struct fsl_espi {
 	const void *tx;
 	void *rx;
 
+	struct list_head *m_transfers;
+	struct spi_transfer *tx_t;
+	unsigned int tx_pos;
+	bool tx_done;
+
 	bool swab;
 	unsigned int rx_len;
 	unsigned int tx_len;
@@ -131,6 +136,12 @@ static inline void fsl_espi_write_reg(struct fsl_espi *espi, int offset,
 	iowrite32be(val, espi->reg_base + offset);
 }
 
+static inline void fsl_espi_write_reg16(struct fsl_espi *espi, int offset,
+					u16 val)
+{
+	iowrite16(val, espi->reg_base + offset);
+}
+
 static inline void fsl_espi_write_reg8(struct fsl_espi *espi, int offset,
 				       u8 val)
 {
@@ -260,22 +271,58 @@ static unsigned int fsl_espi_check_rxskip_mode(struct spi_message *m)
 static void fsl_espi_fill_tx_fifo(struct fsl_espi *espi, u32 events)
 {
 	u32 tx_fifo_avail;
+	unsigned int tx_left;
+	const void *tx_buf;
 
 	/* if events is zero transfer has not started and tx fifo is empty */
 	tx_fifo_avail = events ? SPIE_TXCNT(events) :  FSL_ESPI_FIFO_SIZE;
-
-	while (tx_fifo_avail >= min(4U, espi->tx_len) && espi->tx_len)
-		if (espi->tx_len >= 4) {
-			fsl_espi_write_reg(espi, ESPI_SPITF, *(u32 *)espi->tx);
-			espi->tx += 4;
-			espi->tx_len -= 4;
+start:
+	tx_left = espi->tx_t->len - espi->tx_pos;
+	tx_buf = espi->tx_t->tx_buf;
+	while (tx_fifo_avail >= min(4U, tx_left) && tx_left) {
+		if (tx_left >= 4) {
+			if (!tx_buf)
+				fsl_espi_write_reg(espi, ESPI_SPITF, 0);
+			else if (espi->swab)
+				fsl_espi_write_reg(espi, ESPI_SPITF,
+					swahb32p(tx_buf + espi->tx_pos));
+			else
+				fsl_espi_write_reg(espi, ESPI_SPITF,
+					*(u32 *)(tx_buf + espi->tx_pos));
+			espi->tx_pos += 4;
+			tx_left -= 4;
 			tx_fifo_avail -= 4;
+		} else if (tx_left >= 2 && tx_buf && espi->swab) {
+			fsl_espi_write_reg16(espi, ESPI_SPITF,
+					swab16p(tx_buf + espi->tx_pos));
+			espi->tx_pos += 2;
+			tx_left -= 2;
+			tx_fifo_avail -= 2;
 		} else {
-			fsl_espi_write_reg8(espi, ESPI_SPITF, *(u8 *)espi->tx);
-			espi->tx += 1;
-			espi->tx_len -= 1;
+			if (!tx_buf)
+				fsl_espi_write_reg8(espi, ESPI_SPITF, 0);
+			else
+				fsl_espi_write_reg8(espi, ESPI_SPITF,
+					*(u8 *)(tx_buf + espi->tx_pos));
+			espi->tx_pos += 1;
+			tx_left -= 1;
 			tx_fifo_avail -= 1;
 		}
+	}
+
+	if (!tx_left) {
+		/* Last transfer finished, in rxskip mode only one is needed */
+		if (list_is_last(&espi->tx_t->transfer_list,
+		    espi->m_transfers) || espi->rxskip) {
+			espi->tx_done = true;
+			return;
+		}
+		espi->tx_t = list_next_entry(espi->tx_t, transfer_list);
+		espi->tx_pos = 0;
+		/* continue with next transfer if tx fifo is not full */
+		if (tx_fifo_avail)
+			goto start;
+	}
 }
 
 static void fsl_espi_read_rx_fifo(struct fsl_espi *espi, u32 events)
@@ -369,9 +416,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 	/* Won't hang up forever, SPI bus sometimes got lost interrupts... */
 	ret = wait_for_completion_timeout(&espi->done, 2 * HZ);
 	if (ret == 0)
-		dev_err(espi->dev,
-			"Transaction hanging up (left %u tx bytes, %u rx bytes)\n",
-			espi->tx_len, espi->rx_len);
+		dev_err(espi->dev, "Transfer timed out!\n");
 
 	/* disable rx ints */
 	fsl_espi_write_reg(espi, ESPI_SPIM, 0);
@@ -388,6 +433,12 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 	/* In case of LSB-first and bits_per_word > 8 byte-swap all words */
 	espi->swab = spi->mode & SPI_LSB_FIRST && trans->bits_per_word > 8;
 
+	espi->m_transfers = &m->transfers;
+	espi->tx_t = list_first_entry(&m->transfers, struct spi_transfer,
+				      transfer_list);
+	espi->tx_pos = 0;
+	espi->tx_done = false;
+
 	espi->rxskip = fsl_espi_check_rxskip_mode(m);
 	if (trans->rx_nbits == SPI_NBITS_DUAL && !espi->rxskip) {
 		dev_err(espi->dev, "Dual output mode requires RXSKIP mode!\n");
@@ -508,10 +559,10 @@ static void fsl_espi_cpu_irq(struct fsl_espi *espi, u32 events)
 	if (espi->rx_len)
 		fsl_espi_read_rx_fifo(espi, events);
 
-	if (espi->tx_len)
+	if (!espi->tx_done)
 		fsl_espi_fill_tx_fifo(espi, events);
 
-	if (espi->tx_len || espi->rx_len)
+	if (!espi->tx_done || espi->rx_len)
 		return;
 
 	/* we're done, but check for errors before returning */
-- 
2.10.2


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 3/4] spi: fsl-espi: eliminate need for linearization when reading from hardware
       [not found] ` <2424ba57-be1a-d32d-0c14-1662c2d02409-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2016-11-25 22:58   ` [PATCH 1/4] spi: fsl-espi: determine need for byte swap only once Heiner Kallweit
  2016-11-25 22:59   ` [PATCH 2/4] spi: fsl-espi: eliminate need for linearization when writing to hardware Heiner Kallweit
@ 2016-11-25 22:59   ` Heiner Kallweit
       [not found]     ` <80a5a858-dc54-ea9d-3c6e-34fdedc516d7-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2016-11-25 23:00   ` [PATCH 4/4] spi: fsl-espi: remove unused linearization code Heiner Kallweit
  3 siblings, 1 reply; 8+ messages in thread
From: Heiner Kallweit @ 2016-11-25 22:59 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA

Eliminate need for linearization when reading from the hardware and
write to the transfer buffers directly.

Signed-off-by: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/spi/spi-fsl-espi.c | 77 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 63 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index 189ab36..e93892d 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -102,6 +102,9 @@ struct fsl_espi {
 	struct spi_transfer *tx_t;
 	unsigned int tx_pos;
 	bool tx_done;
+	struct spi_transfer *rx_t;
+	unsigned int rx_pos;
+	bool rx_done;
 
 	bool swab;
 	unsigned int rx_len;
@@ -125,6 +128,11 @@ static inline u32 fsl_espi_read_reg(struct fsl_espi *espi, int offset)
 	return ioread32be(espi->reg_base + offset);
 }
 
+static inline u16 fsl_espi_read_reg16(struct fsl_espi *espi, int offset)
+{
+	return ioread16(espi->reg_base + offset);
+}
+
 static inline u8 fsl_espi_read_reg8(struct fsl_espi *espi, int offset)
 {
 	return ioread8(espi->reg_base + offset);
@@ -328,19 +336,53 @@ static void fsl_espi_fill_tx_fifo(struct fsl_espi *espi, u32 events)
 static void fsl_espi_read_rx_fifo(struct fsl_espi *espi, u32 events)
 {
 	u32 rx_fifo_avail = SPIE_RXCNT(events);
+	unsigned int rx_left;
+	void *rx_buf;
 
-	while (rx_fifo_avail >= min(4U, espi->rx_len) && espi->rx_len)
-		if (espi->rx_len >= 4) {
-			*(u32 *)espi->rx = fsl_espi_read_reg(espi, ESPI_SPIRF);
-			espi->rx += 4;
-			espi->rx_len -= 4;
+start:
+	rx_left = espi->rx_t->len - espi->rx_pos;
+	rx_buf = espi->rx_t->rx_buf;
+	while (rx_fifo_avail >= min(4U, rx_left) && rx_left) {
+		if (rx_left >= 4) {
+			u32 val = fsl_espi_read_reg(espi, ESPI_SPIRF);
+
+			if (rx_buf && espi->swab)
+				*(u32 *)(rx_buf + espi->rx_pos) = swahb32(val);
+			else if (rx_buf)
+				*(u32 *)(rx_buf + espi->rx_pos) = val;
+			espi->rx_pos += 4;
+			rx_left -= 4;
 			rx_fifo_avail -= 4;
+		} else if (rx_left >= 2 && rx_buf && espi->swab) {
+			u16 val = fsl_espi_read_reg16(espi, ESPI_SPIRF);
+
+			*(u16 *)(rx_buf + espi->rx_pos) = swab16(val);
+			espi->rx_pos += 2;
+			rx_left -= 2;
+			rx_fifo_avail -= 2;
 		} else {
-			*(u8 *)espi->rx = fsl_espi_read_reg8(espi, ESPI_SPIRF);
-			espi->rx += 1;
-			espi->rx_len -= 1;
+			u8 val = fsl_espi_read_reg8(espi, ESPI_SPIRF);
+
+			if (rx_buf)
+				*(u8 *)(rx_buf + espi->rx_pos) = val;
+			espi->rx_pos += 1;
+			rx_left -= 1;
 			rx_fifo_avail -= 1;
 		}
+	}
+
+	if (!rx_left) {
+		if (list_is_last(&espi->rx_t->transfer_list,
+		    espi->m_transfers)) {
+			espi->rx_done = true;
+			return;
+		}
+		espi->rx_t = list_next_entry(espi->rx_t, transfer_list);
+		espi->rx_pos = 0;
+		/* continue with next transfer if rx fifo is not empty */
+		if (rx_fifo_avail)
+			goto start;
+	}
 }
 
 static void fsl_espi_setup_transfer(struct spi_device *spi,
@@ -375,6 +417,7 @@ static void fsl_espi_setup_transfer(struct spi_device *spi,
 static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 {
 	struct fsl_espi *espi = spi_master_get_devdata(spi->master);
+	unsigned int rx_len = t->len;
 	u32 mask, spcom;
 	int ret;
 
@@ -395,6 +438,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 		spcom |= SPCOM_RXSKIP(espi->rxskip);
 		espi->tx_len = espi->rxskip;
 		espi->rx_len = t->len - espi->rxskip;
+		rx_len = t->len - espi->rxskip;
 		espi->rx = t->rx_buf + espi->rxskip;
 		if (t->rx_nbits == SPI_NBITS_DUAL)
 			spcom |= SPCOM_DO;
@@ -404,7 +448,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 
 	/* enable interrupts */
 	mask = SPIM_DON;
-	if (espi->rx_len > FSL_ESPI_FIFO_SIZE)
+	if (rx_len > FSL_ESPI_FIFO_SIZE)
 		mask |= SPIM_RXT;
 	fsl_espi_write_reg(espi, ESPI_SPIM, mask);
 
@@ -438,6 +482,10 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 				      transfer_list);
 	espi->tx_pos = 0;
 	espi->tx_done = false;
+	espi->rx_t = list_first_entry(&m->transfers, struct spi_transfer,
+				      transfer_list);
+	espi->rx_pos = 0;
+	espi->rx_done = false;
 
 	espi->rxskip = fsl_espi_check_rxskip_mode(m);
 	if (trans->rx_nbits == SPI_NBITS_DUAL && !espi->rxskip) {
@@ -445,6 +493,10 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 		return -EINVAL;
 	}
 
+	/* In RXSKIP mode skip first transfer for reads */
+	if (espi->rxskip)
+		espi->rx_t = list_next_entry(espi->rx_t, transfer_list);
+
 	fsl_espi_copy_to_buf(m, espi);
 	fsl_espi_setup_transfer(spi, trans);
 
@@ -453,9 +505,6 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 	if (trans->delay_usecs)
 		udelay(trans->delay_usecs);
 
-	if (!ret)
-		fsl_espi_copy_from_buf(m, espi);
-
 	return ret;
 }
 
@@ -556,13 +605,13 @@ static void fsl_espi_cleanup(struct spi_device *spi)
 
 static void fsl_espi_cpu_irq(struct fsl_espi *espi, u32 events)
 {
-	if (espi->rx_len)
+	if (!espi->rx_done)
 		fsl_espi_read_rx_fifo(espi, events);
 
 	if (!espi->tx_done)
 		fsl_espi_fill_tx_fifo(espi, events);
 
-	if (!espi->tx_done || espi->rx_len)
+	if (!espi->tx_done || !espi->rx_done)
 		return;
 
 	/* we're done, but check for errors before returning */
-- 
2.10.2


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 4/4] spi: fsl-espi: remove unused linearization code
       [not found] ` <2424ba57-be1a-d32d-0c14-1662c2d02409-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
                     ` (2 preceding siblings ...)
  2016-11-25 22:59   ` [PATCH 3/4] spi: fsl-espi: eliminate need for linearization when reading from hardware Heiner Kallweit
@ 2016-11-25 23:00   ` Heiner Kallweit
       [not found]     ` <4ce7fd3d-bdb2-3e28-a362-b4a61a207a89-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  3 siblings, 1 reply; 8+ messages in thread
From: Heiner Kallweit @ 2016-11-25 23:00 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA

After introducing direct transfers between hardware and transfer
buffers remove all code which is unused now.

This includes getting rid of the 64k linearization buffer.

Signed-off-by: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/spi/spi-fsl-espi.c | 80 ----------------------------------------------
 1 file changed, 80 deletions(-)

diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index e93892d..cd28329 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -95,9 +95,6 @@ struct fsl_espi {
 	struct device *dev;
 	void __iomem *reg_base;
 
-	const void *tx;
-	void *rx;
-
 	struct list_head *m_transfers;
 	struct spi_transfer *tx_t;
 	unsigned int tx_pos;
@@ -107,11 +104,8 @@ struct fsl_espi {
 	bool rx_done;
 
 	bool swab;
-	unsigned int rx_len;
-	unsigned int tx_len;
 	unsigned int rxskip;
 
-	u8 *local_buf;
 	spinlock_t lock;
 
 	u32 spibrg;             /* SPIBRG input clock */
@@ -156,61 +150,6 @@ static inline void fsl_espi_write_reg8(struct fsl_espi *espi, int offset,
 	iowrite8(val, espi->reg_base + offset);
 }
 
-static void fsl_espi_memcpy_swab(void *to, const void *from,
-				 struct spi_message *m,
-				 struct spi_transfer *t)
-{
-	struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
-	unsigned int len = t->len;
-
-	if (!espi->swab) {
-		memcpy(to, from, len);
-		return;
-	}
-
-	while (len)
-		if (len >= 4) {
-			*(u32 *)to = swahb32p(from);
-			to += 4;
-			from += 4;
-			len -= 4;
-		} else {
-			*(u16 *)to = swab16p(from);
-			to += 2;
-			from += 2;
-			len -= 2;
-		}
-}
-
-static void fsl_espi_copy_to_buf(struct spi_message *m,
-				 struct fsl_espi *espi)
-{
-	struct spi_transfer *t;
-	u8 *buf = espi->local_buf;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->tx_buf)
-			fsl_espi_memcpy_swab(buf, t->tx_buf, m, t);
-		/* In RXSKIP mode controller shifts out zeros internally */
-		else if (!espi->rxskip)
-			memset(buf, 0, t->len);
-		buf += t->len;
-	}
-}
-
-static void fsl_espi_copy_from_buf(struct spi_message *m,
-				   struct fsl_espi *espi)
-{
-	struct spi_transfer *t;
-	u8 *buf = espi->local_buf;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->rx_buf)
-			fsl_espi_memcpy_swab(t->rx_buf, buf, m, t);
-		buf += t->len;
-	}
-}
-
 static int fsl_espi_check_message(struct spi_message *m)
 {
 	struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
@@ -421,12 +360,6 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 	u32 mask, spcom;
 	int ret;
 
-	espi->rx_len = t->len;
-	espi->tx_len = t->len;
-
-	espi->tx = t->tx_buf;
-	espi->rx = t->rx_buf;
-
 	reinit_completion(&espi->done);
 
 	/* Set SPCOM[CS] and SPCOM[TRANLEN] field */
@@ -436,10 +369,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 	/* configure RXSKIP mode */
 	if (espi->rxskip) {
 		spcom |= SPCOM_RXSKIP(espi->rxskip);
-		espi->tx_len = espi->rxskip;
-		espi->rx_len = t->len - espi->rxskip;
 		rx_len = t->len - espi->rxskip;
-		espi->rx = t->rx_buf + espi->rxskip;
 		if (t->rx_nbits == SPI_NBITS_DUAL)
 			spcom |= SPCOM_DO;
 	}
@@ -497,7 +427,6 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 	if (espi->rxskip)
 		espi->rx_t = list_next_entry(espi->rx_t, transfer_list);
 
-	fsl_espi_copy_to_buf(m, espi);
 	fsl_espi_setup_transfer(spi, trans);
 
 	ret = fsl_espi_bufs(spi, trans);
@@ -511,7 +440,6 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 static int fsl_espi_do_one_msg(struct spi_master *master,
 			       struct spi_message *m)
 {
-	struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
 	unsigned int delay_usecs = 0, rx_nbits = 0;
 	struct spi_transfer *t, trans = {};
 	int ret;
@@ -534,8 +462,6 @@ static int fsl_espi_do_one_msg(struct spi_master *master,
 	trans.speed_hz = t->speed_hz;
 	trans.bits_per_word = t->bits_per_word;
 	trans.delay_usecs = delay_usecs;
-	trans.tx_buf = espi->local_buf;
-	trans.rx_buf = espi->local_buf;
 	trans.rx_nbits = rx_nbits;
 
 	if (trans.len)
@@ -773,12 +699,6 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem,
 
 	init_completion(&espi->done);
 
-	espi->local_buf = devm_kmalloc(dev, SPCOM_TRANLEN_MAX, GFP_KERNEL);
-	if (!espi->local_buf) {
-		ret = -ENOMEM;
-		goto err_probe;
-	}
-
 	espi->reg_base = devm_ioremap_resource(dev, mem);
 	if (IS_ERR(espi->reg_base)) {
 		ret = PTR_ERR(espi->reg_base);
-- 
2.10.2


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Applied "spi: fsl-espi: remove unused linearization code" to the spi tree
       [not found]     ` <4ce7fd3d-bdb2-3e28-a362-b4a61a207a89-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2016-11-30 18:07       ` Mark Brown
  0 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2016-11-30 18:07 UTC (permalink / raw)
  To: Heiner Kallweit; +Cc: Mark Brown, Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA

The patch

   spi: fsl-espi: remove unused linearization code

has been applied to the spi tree at

   git://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 d54ef0574ade2eab4d203687d53ed20351e323ab Mon Sep 17 00:00:00 2001
From: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Sat, 26 Nov 2016 00:00:28 +0100
Subject: [PATCH] spi: fsl-espi: remove unused linearization code

After introducing direct transfers between hardware and transfer
buffers remove all code which is unused now.

This includes getting rid of the 64k linearization buffer.

Signed-off-by: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi-fsl-espi.c | 80 ----------------------------------------------
 1 file changed, 80 deletions(-)

diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index e93892dca90a..cd2832940092 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -95,9 +95,6 @@ struct fsl_espi {
 	struct device *dev;
 	void __iomem *reg_base;
 
-	const void *tx;
-	void *rx;
-
 	struct list_head *m_transfers;
 	struct spi_transfer *tx_t;
 	unsigned int tx_pos;
@@ -107,11 +104,8 @@ struct fsl_espi {
 	bool rx_done;
 
 	bool swab;
-	unsigned int rx_len;
-	unsigned int tx_len;
 	unsigned int rxskip;
 
-	u8 *local_buf;
 	spinlock_t lock;
 
 	u32 spibrg;             /* SPIBRG input clock */
@@ -156,61 +150,6 @@ static inline void fsl_espi_write_reg8(struct fsl_espi *espi, int offset,
 	iowrite8(val, espi->reg_base + offset);
 }
 
-static void fsl_espi_memcpy_swab(void *to, const void *from,
-				 struct spi_message *m,
-				 struct spi_transfer *t)
-{
-	struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
-	unsigned int len = t->len;
-
-	if (!espi->swab) {
-		memcpy(to, from, len);
-		return;
-	}
-
-	while (len)
-		if (len >= 4) {
-			*(u32 *)to = swahb32p(from);
-			to += 4;
-			from += 4;
-			len -= 4;
-		} else {
-			*(u16 *)to = swab16p(from);
-			to += 2;
-			from += 2;
-			len -= 2;
-		}
-}
-
-static void fsl_espi_copy_to_buf(struct spi_message *m,
-				 struct fsl_espi *espi)
-{
-	struct spi_transfer *t;
-	u8 *buf = espi->local_buf;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->tx_buf)
-			fsl_espi_memcpy_swab(buf, t->tx_buf, m, t);
-		/* In RXSKIP mode controller shifts out zeros internally */
-		else if (!espi->rxskip)
-			memset(buf, 0, t->len);
-		buf += t->len;
-	}
-}
-
-static void fsl_espi_copy_from_buf(struct spi_message *m,
-				   struct fsl_espi *espi)
-{
-	struct spi_transfer *t;
-	u8 *buf = espi->local_buf;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->rx_buf)
-			fsl_espi_memcpy_swab(t->rx_buf, buf, m, t);
-		buf += t->len;
-	}
-}
-
 static int fsl_espi_check_message(struct spi_message *m)
 {
 	struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
@@ -421,12 +360,6 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 	u32 mask, spcom;
 	int ret;
 
-	espi->rx_len = t->len;
-	espi->tx_len = t->len;
-
-	espi->tx = t->tx_buf;
-	espi->rx = t->rx_buf;
-
 	reinit_completion(&espi->done);
 
 	/* Set SPCOM[CS] and SPCOM[TRANLEN] field */
@@ -436,10 +369,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 	/* configure RXSKIP mode */
 	if (espi->rxskip) {
 		spcom |= SPCOM_RXSKIP(espi->rxskip);
-		espi->tx_len = espi->rxskip;
-		espi->rx_len = t->len - espi->rxskip;
 		rx_len = t->len - espi->rxskip;
-		espi->rx = t->rx_buf + espi->rxskip;
 		if (t->rx_nbits == SPI_NBITS_DUAL)
 			spcom |= SPCOM_DO;
 	}
@@ -497,7 +427,6 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 	if (espi->rxskip)
 		espi->rx_t = list_next_entry(espi->rx_t, transfer_list);
 
-	fsl_espi_copy_to_buf(m, espi);
 	fsl_espi_setup_transfer(spi, trans);
 
 	ret = fsl_espi_bufs(spi, trans);
@@ -511,7 +440,6 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 static int fsl_espi_do_one_msg(struct spi_master *master,
 			       struct spi_message *m)
 {
-	struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
 	unsigned int delay_usecs = 0, rx_nbits = 0;
 	struct spi_transfer *t, trans = {};
 	int ret;
@@ -534,8 +462,6 @@ static int fsl_espi_do_one_msg(struct spi_master *master,
 	trans.speed_hz = t->speed_hz;
 	trans.bits_per_word = t->bits_per_word;
 	trans.delay_usecs = delay_usecs;
-	trans.tx_buf = espi->local_buf;
-	trans.rx_buf = espi->local_buf;
 	trans.rx_nbits = rx_nbits;
 
 	if (trans.len)
@@ -773,12 +699,6 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem,
 
 	init_completion(&espi->done);
 
-	espi->local_buf = devm_kmalloc(dev, SPCOM_TRANLEN_MAX, GFP_KERNEL);
-	if (!espi->local_buf) {
-		ret = -ENOMEM;
-		goto err_probe;
-	}
-
 	espi->reg_base = devm_ioremap_resource(dev, mem);
 	if (IS_ERR(espi->reg_base)) {
 		ret = PTR_ERR(espi->reg_base);
-- 
2.10.2

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Applied "spi: fsl-espi: eliminate need for linearization when reading from hardware" to the spi tree
       [not found]     ` <80a5a858-dc54-ea9d-3c6e-34fdedc516d7-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2016-11-30 18:07       ` Mark Brown
  0 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2016-11-30 18:07 UTC (permalink / raw)
  To: Heiner Kallweit; +Cc: Mark Brown, Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA

The patch

   spi: fsl-espi: eliminate need for linearization when reading from hardware

has been applied to the spi tree at

   git://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 dcb425f3ba6ebee4269f68461420246ba9d4ec02 Mon Sep 17 00:00:00 2001
From: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Fri, 25 Nov 2016 23:59:57 +0100
Subject: [PATCH] spi: fsl-espi: eliminate need for linearization when reading
 from hardware

Eliminate need for linearization when reading from the hardware and
write to the transfer buffers directly.

Signed-off-by: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi-fsl-espi.c | 77 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 63 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index 189ab36b787f..e93892dca90a 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -102,6 +102,9 @@ struct fsl_espi {
 	struct spi_transfer *tx_t;
 	unsigned int tx_pos;
 	bool tx_done;
+	struct spi_transfer *rx_t;
+	unsigned int rx_pos;
+	bool rx_done;
 
 	bool swab;
 	unsigned int rx_len;
@@ -125,6 +128,11 @@ static inline u32 fsl_espi_read_reg(struct fsl_espi *espi, int offset)
 	return ioread32be(espi->reg_base + offset);
 }
 
+static inline u16 fsl_espi_read_reg16(struct fsl_espi *espi, int offset)
+{
+	return ioread16(espi->reg_base + offset);
+}
+
 static inline u8 fsl_espi_read_reg8(struct fsl_espi *espi, int offset)
 {
 	return ioread8(espi->reg_base + offset);
@@ -328,19 +336,53 @@ static void fsl_espi_fill_tx_fifo(struct fsl_espi *espi, u32 events)
 static void fsl_espi_read_rx_fifo(struct fsl_espi *espi, u32 events)
 {
 	u32 rx_fifo_avail = SPIE_RXCNT(events);
+	unsigned int rx_left;
+	void *rx_buf;
 
-	while (rx_fifo_avail >= min(4U, espi->rx_len) && espi->rx_len)
-		if (espi->rx_len >= 4) {
-			*(u32 *)espi->rx = fsl_espi_read_reg(espi, ESPI_SPIRF);
-			espi->rx += 4;
-			espi->rx_len -= 4;
+start:
+	rx_left = espi->rx_t->len - espi->rx_pos;
+	rx_buf = espi->rx_t->rx_buf;
+	while (rx_fifo_avail >= min(4U, rx_left) && rx_left) {
+		if (rx_left >= 4) {
+			u32 val = fsl_espi_read_reg(espi, ESPI_SPIRF);
+
+			if (rx_buf && espi->swab)
+				*(u32 *)(rx_buf + espi->rx_pos) = swahb32(val);
+			else if (rx_buf)
+				*(u32 *)(rx_buf + espi->rx_pos) = val;
+			espi->rx_pos += 4;
+			rx_left -= 4;
 			rx_fifo_avail -= 4;
+		} else if (rx_left >= 2 && rx_buf && espi->swab) {
+			u16 val = fsl_espi_read_reg16(espi, ESPI_SPIRF);
+
+			*(u16 *)(rx_buf + espi->rx_pos) = swab16(val);
+			espi->rx_pos += 2;
+			rx_left -= 2;
+			rx_fifo_avail -= 2;
 		} else {
-			*(u8 *)espi->rx = fsl_espi_read_reg8(espi, ESPI_SPIRF);
-			espi->rx += 1;
-			espi->rx_len -= 1;
+			u8 val = fsl_espi_read_reg8(espi, ESPI_SPIRF);
+
+			if (rx_buf)
+				*(u8 *)(rx_buf + espi->rx_pos) = val;
+			espi->rx_pos += 1;
+			rx_left -= 1;
 			rx_fifo_avail -= 1;
 		}
+	}
+
+	if (!rx_left) {
+		if (list_is_last(&espi->rx_t->transfer_list,
+		    espi->m_transfers)) {
+			espi->rx_done = true;
+			return;
+		}
+		espi->rx_t = list_next_entry(espi->rx_t, transfer_list);
+		espi->rx_pos = 0;
+		/* continue with next transfer if rx fifo is not empty */
+		if (rx_fifo_avail)
+			goto start;
+	}
 }
 
 static void fsl_espi_setup_transfer(struct spi_device *spi,
@@ -375,6 +417,7 @@ static void fsl_espi_setup_transfer(struct spi_device *spi,
 static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 {
 	struct fsl_espi *espi = spi_master_get_devdata(spi->master);
+	unsigned int rx_len = t->len;
 	u32 mask, spcom;
 	int ret;
 
@@ -395,6 +438,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 		spcom |= SPCOM_RXSKIP(espi->rxskip);
 		espi->tx_len = espi->rxskip;
 		espi->rx_len = t->len - espi->rxskip;
+		rx_len = t->len - espi->rxskip;
 		espi->rx = t->rx_buf + espi->rxskip;
 		if (t->rx_nbits == SPI_NBITS_DUAL)
 			spcom |= SPCOM_DO;
@@ -404,7 +448,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 
 	/* enable interrupts */
 	mask = SPIM_DON;
-	if (espi->rx_len > FSL_ESPI_FIFO_SIZE)
+	if (rx_len > FSL_ESPI_FIFO_SIZE)
 		mask |= SPIM_RXT;
 	fsl_espi_write_reg(espi, ESPI_SPIM, mask);
 
@@ -438,6 +482,10 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 				      transfer_list);
 	espi->tx_pos = 0;
 	espi->tx_done = false;
+	espi->rx_t = list_first_entry(&m->transfers, struct spi_transfer,
+				      transfer_list);
+	espi->rx_pos = 0;
+	espi->rx_done = false;
 
 	espi->rxskip = fsl_espi_check_rxskip_mode(m);
 	if (trans->rx_nbits == SPI_NBITS_DUAL && !espi->rxskip) {
@@ -445,6 +493,10 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 		return -EINVAL;
 	}
 
+	/* In RXSKIP mode skip first transfer for reads */
+	if (espi->rxskip)
+		espi->rx_t = list_next_entry(espi->rx_t, transfer_list);
+
 	fsl_espi_copy_to_buf(m, espi);
 	fsl_espi_setup_transfer(spi, trans);
 
@@ -453,9 +505,6 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 	if (trans->delay_usecs)
 		udelay(trans->delay_usecs);
 
-	if (!ret)
-		fsl_espi_copy_from_buf(m, espi);
-
 	return ret;
 }
 
@@ -556,13 +605,13 @@ static void fsl_espi_cleanup(struct spi_device *spi)
 
 static void fsl_espi_cpu_irq(struct fsl_espi *espi, u32 events)
 {
-	if (espi->rx_len)
+	if (!espi->rx_done)
 		fsl_espi_read_rx_fifo(espi, events);
 
 	if (!espi->tx_done)
 		fsl_espi_fill_tx_fifo(espi, events);
 
-	if (!espi->tx_done || espi->rx_len)
+	if (!espi->tx_done || !espi->rx_done)
 		return;
 
 	/* we're done, but check for errors before returning */
-- 
2.10.2

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Applied "spi: fsl-espi: eliminate need for linearization when writing to hardware" to the spi tree
       [not found]     ` <fe019347-2d40-7e0a-4ee4-cadaa8930d5f-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2016-11-30 18:08       ` Mark Brown
  0 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2016-11-30 18:08 UTC (permalink / raw)
  To: Heiner Kallweit; +Cc: Mark Brown, Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA

The patch

   spi: fsl-espi: eliminate need for linearization when writing to hardware

has been applied to the spi tree at

   git://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 05823432844515e6e6e0e80dd44624a36ea405b7 Mon Sep 17 00:00:00 2001
From: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Fri, 25 Nov 2016 23:59:24 +0100
Subject: [PATCH] spi: fsl-espi: eliminate need for linearization when writing
 to hardware

Eliminate need for linearization when writing to the hardware and
read from the transfer buffers directly.

Signed-off-by: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi-fsl-espi.c | 79 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 65 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index 4222578a4dd4..189ab36b787f 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -98,6 +98,11 @@ struct fsl_espi {
 	const void *tx;
 	void *rx;
 
+	struct list_head *m_transfers;
+	struct spi_transfer *tx_t;
+	unsigned int tx_pos;
+	bool tx_done;
+
 	bool swab;
 	unsigned int rx_len;
 	unsigned int tx_len;
@@ -131,6 +136,12 @@ static inline void fsl_espi_write_reg(struct fsl_espi *espi, int offset,
 	iowrite32be(val, espi->reg_base + offset);
 }
 
+static inline void fsl_espi_write_reg16(struct fsl_espi *espi, int offset,
+					u16 val)
+{
+	iowrite16(val, espi->reg_base + offset);
+}
+
 static inline void fsl_espi_write_reg8(struct fsl_espi *espi, int offset,
 				       u8 val)
 {
@@ -260,22 +271,58 @@ static unsigned int fsl_espi_check_rxskip_mode(struct spi_message *m)
 static void fsl_espi_fill_tx_fifo(struct fsl_espi *espi, u32 events)
 {
 	u32 tx_fifo_avail;
+	unsigned int tx_left;
+	const void *tx_buf;
 
 	/* if events is zero transfer has not started and tx fifo is empty */
 	tx_fifo_avail = events ? SPIE_TXCNT(events) :  FSL_ESPI_FIFO_SIZE;
-
-	while (tx_fifo_avail >= min(4U, espi->tx_len) && espi->tx_len)
-		if (espi->tx_len >= 4) {
-			fsl_espi_write_reg(espi, ESPI_SPITF, *(u32 *)espi->tx);
-			espi->tx += 4;
-			espi->tx_len -= 4;
+start:
+	tx_left = espi->tx_t->len - espi->tx_pos;
+	tx_buf = espi->tx_t->tx_buf;
+	while (tx_fifo_avail >= min(4U, tx_left) && tx_left) {
+		if (tx_left >= 4) {
+			if (!tx_buf)
+				fsl_espi_write_reg(espi, ESPI_SPITF, 0);
+			else if (espi->swab)
+				fsl_espi_write_reg(espi, ESPI_SPITF,
+					swahb32p(tx_buf + espi->tx_pos));
+			else
+				fsl_espi_write_reg(espi, ESPI_SPITF,
+					*(u32 *)(tx_buf + espi->tx_pos));
+			espi->tx_pos += 4;
+			tx_left -= 4;
 			tx_fifo_avail -= 4;
+		} else if (tx_left >= 2 && tx_buf && espi->swab) {
+			fsl_espi_write_reg16(espi, ESPI_SPITF,
+					swab16p(tx_buf + espi->tx_pos));
+			espi->tx_pos += 2;
+			tx_left -= 2;
+			tx_fifo_avail -= 2;
 		} else {
-			fsl_espi_write_reg8(espi, ESPI_SPITF, *(u8 *)espi->tx);
-			espi->tx += 1;
-			espi->tx_len -= 1;
+			if (!tx_buf)
+				fsl_espi_write_reg8(espi, ESPI_SPITF, 0);
+			else
+				fsl_espi_write_reg8(espi, ESPI_SPITF,
+					*(u8 *)(tx_buf + espi->tx_pos));
+			espi->tx_pos += 1;
+			tx_left -= 1;
 			tx_fifo_avail -= 1;
 		}
+	}
+
+	if (!tx_left) {
+		/* Last transfer finished, in rxskip mode only one is needed */
+		if (list_is_last(&espi->tx_t->transfer_list,
+		    espi->m_transfers) || espi->rxskip) {
+			espi->tx_done = true;
+			return;
+		}
+		espi->tx_t = list_next_entry(espi->tx_t, transfer_list);
+		espi->tx_pos = 0;
+		/* continue with next transfer if tx fifo is not full */
+		if (tx_fifo_avail)
+			goto start;
+	}
 }
 
 static void fsl_espi_read_rx_fifo(struct fsl_espi *espi, u32 events)
@@ -369,9 +416,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
 	/* Won't hang up forever, SPI bus sometimes got lost interrupts... */
 	ret = wait_for_completion_timeout(&espi->done, 2 * HZ);
 	if (ret == 0)
-		dev_err(espi->dev,
-			"Transaction hanging up (left %u tx bytes, %u rx bytes)\n",
-			espi->tx_len, espi->rx_len);
+		dev_err(espi->dev, "Transfer timed out!\n");
 
 	/* disable rx ints */
 	fsl_espi_write_reg(espi, ESPI_SPIM, 0);
@@ -388,6 +433,12 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 	/* In case of LSB-first and bits_per_word > 8 byte-swap all words */
 	espi->swab = spi->mode & SPI_LSB_FIRST && trans->bits_per_word > 8;
 
+	espi->m_transfers = &m->transfers;
+	espi->tx_t = list_first_entry(&m->transfers, struct spi_transfer,
+				      transfer_list);
+	espi->tx_pos = 0;
+	espi->tx_done = false;
+
 	espi->rxskip = fsl_espi_check_rxskip_mode(m);
 	if (trans->rx_nbits == SPI_NBITS_DUAL && !espi->rxskip) {
 		dev_err(espi->dev, "Dual output mode requires RXSKIP mode!\n");
@@ -508,10 +559,10 @@ static void fsl_espi_cpu_irq(struct fsl_espi *espi, u32 events)
 	if (espi->rx_len)
 		fsl_espi_read_rx_fifo(espi, events);
 
-	if (espi->tx_len)
+	if (!espi->tx_done)
 		fsl_espi_fill_tx_fifo(espi, events);
 
-	if (espi->tx_len || espi->rx_len)
+	if (!espi->tx_done || espi->rx_len)
 		return;
 
 	/* we're done, but check for errors before returning */
-- 
2.10.2

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Applied "spi: fsl-espi: determine need for byte swap only once" to the spi tree
       [not found]     ` <bfa9887d-ed21-6d89-7e7b-d65c67571d85-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2016-11-30 18:08       ` Mark Brown
  0 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2016-11-30 18:08 UTC (permalink / raw)
  To: Heiner Kallweit; +Cc: Mark Brown, Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA

The patch

   spi: fsl-espi: determine need for byte swap only once

has been applied to the spi tree at

   git://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 e1cdee73dfcac393768117511e52a6142587dacf Mon Sep 17 00:00:00 2001
From: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Fri, 25 Nov 2016 23:58:49 +0100
Subject: [PATCH] spi: fsl-espi: determine need for byte swap only once

Determine need for byte swap only once and store it in new member
swab in struct fsl_espi.

Signed-off-by: Heiner Kallweit <hkallweit1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi-fsl-espi.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index 4fbcc36fa891..4222578a4dd4 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -98,6 +98,7 @@ struct fsl_espi {
 	const void *tx;
 	void *rx;
 
+	bool swab;
 	unsigned int rx_len;
 	unsigned int tx_len;
 	unsigned int rxskip;
@@ -140,14 +141,14 @@ static void fsl_espi_memcpy_swab(void *to, const void *from,
 				 struct spi_message *m,
 				 struct spi_transfer *t)
 {
+	struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
 	unsigned int len = t->len;
 
-	if (!(m->spi->mode & SPI_LSB_FIRST) || t->bits_per_word <= 8) {
+	if (!espi->swab) {
 		memcpy(to, from, len);
 		return;
 	}
 
-	/* In case of LSB-first and bits_per_word > 8 byte-swap all words */
 	while (len)
 		if (len >= 4) {
 			*(u32 *)to = swahb32p(from);
@@ -384,6 +385,9 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 	struct spi_device *spi = m->spi;
 	int ret;
 
+	/* In case of LSB-first and bits_per_word > 8 byte-swap all words */
+	espi->swab = spi->mode & SPI_LSB_FIRST && trans->bits_per_word > 8;
+
 	espi->rxskip = fsl_espi_check_rxskip_mode(m);
 	if (trans->rx_nbits == SPI_NBITS_DUAL && !espi->rxskip) {
 		dev_err(espi->dev, "Dual output mode requires RXSKIP mode!\n");
-- 
2.10.2

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2016-11-30 18:08 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <2424ba57-be1a-d32d-0c14-1662c2d02409@gmail.com>
     [not found] ` <2424ba57-be1a-d32d-0c14-1662c2d02409-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-11-25 22:58   ` [PATCH 1/4] spi: fsl-espi: determine need for byte swap only once Heiner Kallweit
     [not found]     ` <bfa9887d-ed21-6d89-7e7b-d65c67571d85-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-11-30 18:08       ` Applied "spi: fsl-espi: determine need for byte swap only once" to the spi tree Mark Brown
2016-11-25 22:59   ` [PATCH 2/4] spi: fsl-espi: eliminate need for linearization when writing to hardware Heiner Kallweit
     [not found]     ` <fe019347-2d40-7e0a-4ee4-cadaa8930d5f-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-11-30 18:08       ` Applied "spi: fsl-espi: eliminate need for linearization when writing to hardware" to the spi tree Mark Brown
2016-11-25 22:59   ` [PATCH 3/4] spi: fsl-espi: eliminate need for linearization when reading from hardware Heiner Kallweit
     [not found]     ` <80a5a858-dc54-ea9d-3c6e-34fdedc516d7-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-11-30 18:07       ` Applied "spi: fsl-espi: eliminate need for linearization when reading from hardware" to the spi tree Mark Brown
2016-11-25 23:00   ` [PATCH 4/4] spi: fsl-espi: remove unused linearization code Heiner Kallweit
     [not found]     ` <4ce7fd3d-bdb2-3e28-a362-b4a61a207a89-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-11-30 18:07       ` Applied "spi: fsl-espi: remove unused linearization code" 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).