Patchwork [U-Boot,2/2] powerpc: make espi can read more than 0xFFFA bytes

login
register
mail settings
Submitter shaohui xie
Date March 18, 2011, 6:18 a.m.
Message ID <1300429135-6884-1-git-send-email-b21989@freescale.com>
Download mbox | patch
Permalink /patch/87488/
State Superseded
Headers show

Comments

shaohui xie - March 18, 2011, 6:18 a.m.
espi flash read returns invalid data if the read length is more than 0xFFFA
bytes, it supports maximum transaction of 2^16 bytes at a time, resister
spcom[TRANLEN] is 16 bits. If the transaction length is greater than  0xFFFF,
it need to be split into multiple transactions.

Signed-off-by: Shaohui Xie <b21989@freescale.com>
Cc: Mike Frysinger <vapier@gentoo.org>
---
this patch is rebased on Mike's sf unify patches.

 drivers/mtd/spi/spi_flash.c |   30 ++++++++++++++++++++++++++++++
 drivers/spi/fsl_espi.c      |    6 ++++++
 include/spi.h               |    2 ++
 3 files changed, 38 insertions(+), 0 deletions(-)

Patch

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index f745def..f50ca63 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -127,11 +127,41 @@  int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
 {
 	u8 cmd[5];
 
+#ifndef CONFIG_FSL_ESPI
 	cmd[0] = CMD_READ_ARRAY_FAST;
 	spi_flash_addr(offset, cmd);
 	cmd[4] = 0x00;
 
 	return spi_flash_read_common(flash, cmd, sizeof(cmd), data, len);
+#else
+	int max_tran_len, num_chunks, tran_len, ret;
+
+	max_tran_len = flash->spi->max_transfer_length;
+	num_chunks = len / max_tran_len + (len % max_tran_len ? 1 : 0);
+
+	while (num_chunks--) {
+		tran_len = min(len , max_tran_len);
+
+		cmd[0] = CMD_READ_ARRAY_FAST;
+		spi_flash_addr(offset, cmd);
+		cmd[4] = 0x00;
+
+		debug("READ: 0x%x => cmd =
+		{ 0x%02x 0x%02x%02x%02x%02x } tran_len = 0x%x\n",
+		offset, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], tran_len);
+
+		ret = spi_flash_read_common(
+				flash, cmd, sizeof(cmd), data, tran_len);
+		if (ret < 0)
+			return ret;
+
+		offset += max_tran_len;
+		data += max_tran_len;
+		len -= max_tran_len;
+	}
+
+	return ret;
+#endif
 }
 
 int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
diff --git a/drivers/spi/fsl_espi.c b/drivers/spi/fsl_espi.c
index f4ff884..66ae1a8 100644
--- a/drivers/spi/fsl_espi.c
+++ b/drivers/spi/fsl_espi.c
@@ -53,6 +53,8 @@ 
 		ESPI_CSMODE_CSBEF(0) | ESPI_CSMODE_CSAFT(0) | \
 		ESPI_CSMODE_CSCG(1))
 
+#define ESPI_MAX_DATA_TRANSFER_LEN 0xFFF0
+
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 		unsigned int max_hz, unsigned int mode)
 {
@@ -72,6 +74,7 @@  struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 
 	slave->bus = bus;
 	slave->cs = cs;
+	slave->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN;
 
 	/* Enable eSPI interface */
 	espi->mode = ESPI_MODE_RXTHR(3) | ESPI_MODE_TXTHR(4) | ESPI_MODE_EN;
@@ -153,6 +156,9 @@  int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out,
 	unsigned char *ch;
 	int num_bytes = len % 4;
 
+	if (t->data_len > ESPI_MAX_DATA_TRANSFER_LEN)
+		return -1;
+
 	debug("spi_xfer: slave %u:%u dout %08X(%08x) din %08X(%08x) len %u\n",
 	      slave->bus, slave->cs, *(uint *) dout,
 	      dout, *(uint *) din, din, len);
diff --git a/include/spi.h b/include/spi.h
index 423899f..b0e13d5 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -77,12 +77,14 @@  struct espi_transfer {
  *
  *   bus:	ID of the bus that the slave is attached to.
  *   cs:	ID of the chip select connected to the slave.
+ *   max_txn_length: maximum data transfer length supported by the slave.
  *   transfer:	Represent an eSPI transaction.
  */
 struct spi_slave {
 	unsigned int	bus;
 	unsigned int	cs;
 
+	unsigned int    max_transfer_length;
 	struct espi_transfer *transfer;
 };