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

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 --- changes for v2: fix some compile warnings. remove ifdef and use if else instead.
drivers/mtd/spi/spi_flash.c | 39 +++++++++++++++++++++++++++++++++++---- drivers/spi/fsl_espi.c | 6 ++++++ include/spi.h | 2 ++ 3 files changed, 43 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index c75b716..f90ef25 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -1,6 +1,7 @@ /* * SPI flash interface * + * Copyright 2009-2011 Freescale Semiconductor, Inc. * Copyright (C) 2008 Atmel Corporation * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik * @@ -82,11 +83,41 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, { u8 cmd[5];
- cmd[0] = CMD_READ_ARRAY_FAST; - spi_flash_addr(offset, cmd); - cmd[4] = 0x00; + if (len <= flash->spi->max_transfer_length) { + 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 = 0; + + 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);
- return spi_flash_read_common(flash, cmd, sizeof(cmd), data, 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; + } }
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 9b8ae9a..7630fb3 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 */ out_be32(&espi->mode, ESPI_MODE_RXTHR(3) @@ -165,6 +168,9 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, unsigned char *buffer; size_t buf_len;
+ if (slave->max_transfer_length > ESPI_MAX_DATA_TRANSFER_LEN) + return -1; + switch (flags) { case SPI_XFER_BEGIN: cmd_len = bitlen / 8; diff --git a/include/spi.h b/include/spi.h index c5da3ca..866b920 100644 --- a/include/spi.h +++ b/include/spi.h @@ -58,10 +58,12 @@ * * bus: ID of the bus that the slave is attached to. * cs: ID of the chip select connected to the slave. + * max_transfer_length: maximum data transfer length supported by the slave. */ struct spi_slave { unsigned int bus; unsigned int cs; + unsigned int max_transfer_length; };
/*-----------------------------------------------------------------------

On Thu, Apr 21, 2011 at 2:05 AM, Shaohui Xie wrote:
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.
hrm, so how does this work under Linux ? or does it just not ? -mike

From: vapierfilter@gmail.com [mailto:vapierfilter@gmail.com] On Behalf Of Mike Frysinger Sent: Friday, April 22, 2011 1:17 AM To: Xie Shaohui-B21989 Cc: u-boot@lists.denx.de; Gala Kumar-B11780; Zang Roy-R61911 Subject: Re: [PATCH 2/2][v2] powerpc: make espi can read more than 0xFFFA bytes
On Thu, Apr 21, 2011 at 2:05 AM, Shaohui Xie wrote:
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.
hrm, so how does this work under Linux ? or does it just not ?
[Xie Shaohui] This does work under Linux, being solved in similar way.
Best Regards, Shaohui Xie

On Friday, April 22, 2011 05:23:59 Xie Shaohui-B21989 wrote:
From: Mike Frysinger
On Thu, Apr 21, 2011 at 2:05 AM, Shaohui Xie wrote:
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.
hrm, so how does this work under Linux ? or does it just not ?
[Xie Shaohui] This does work under Linux, being solved in similar way.
so it doesnt work under Linux atm, but you're trying to get similar changes made to the Linux code upstream ? -mike
participants (3)
-
Mike Frysinger
-
Shaohui Xie
-
Xie Shaohui-B21989