[U-Boot] [PATCH 2/2][v3] 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.
changes for v3: rebased on first patch.
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 55b29cc..5ed6a59 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) { @@ -71,6 +73,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, slave->bus = bus; slave->cs = cs; slave->slave_data.mode = mode; + slave->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN;
/* Set eSPI BRG clock source */ get_sys_info(&sysinfo); @@ -174,6 +177,9 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, u8 *cmd_buf = slave->slave_data.cmd_buf; size_t cmd_len = slave->slave_data.cmd_len;
+ if (slave->max_transfer_length > ESPI_MAX_DATA_TRANSFER_LEN) + return -1; + switch (flags) { case SPI_XFER_BEGIN: cmd_len = slave->slave_data.cmd_len = bitlen / 8; diff --git a/include/spi.h b/include/spi.h index 213f6e6..c2c0d36 100644 --- a/include/spi.h +++ b/include/spi.h @@ -70,11 +70,13 @@ struct spi_slave_data { * bus: ID of the bus that the slave is attached to. * cs: ID of the chip select connected to the slave. * slave_data: slave data for hardware and transfer. + * max_transfer_length: maximum data transfer length supported by the slave. */ struct spi_slave { unsigned int bus; unsigned int cs; struct spi_slave_data slave_data; + unsigned int max_transfer_length; };
/*-----------------------------------------------------------------------

From: Xie Shaohui-B21989 Sent: Friday, April 22, 2011 4:31 PM To: u-boot@lists.denx.de Cc: Gala Kumar-B11780; Zang Roy-R61911; Xie Shaohui-B21989; Mike Frysinger Subject: [PATCH 2/2][v3] 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.
changes for v3: rebased on first patch.
[Xie Shaohui] This patch is not needed any more; I have merged it to previous patch and resend it as v4.
Best Regards, Shaohui Xie

On Tuesday, April 26, 2011 02:31:32 Xie Shaohui-B21989 wrote:
From: Xie Shaohui-B21989
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.
[Xie Shaohui] This patch is not needed any more; I have merged it to previous patch and resend it as v4.
so with the new logic in the espi controller, you dont need to change the common spi flash code to make things work ? so i should just forget about these "0xFFFA" threads ?
atm, i dont think there are any outstanding spi/spi-flash patches from you guys. so if there's something you want me to review/ack, please ping it specifically for me ... -mike
participants (3)
-
Mike Frysinger
-
Shaohui Xie
-
Xie Shaohui-B21989