From 1110495de926db4b21b9969da522e5270c67f115 Mon Sep 17 00:00:00 2001 From: Kyösti Mälkki Date: Sun, 29 Jun 2014 16:17:33 +0300 Subject: SPI: Split writes using spi_crop_chunk() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SPI controllers in Intel and AMD bridges have a slightly different restriction on how long transactions they can handle. Change-Id: I3d149d4b7e7e9633482a153d5e380a86c553d871 Signed-off-by: Kyösti Mälkki Reviewed-on: http://review.coreboot.org/6163 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan --- src/drivers/spi/adesto.c | 4 ++-- src/drivers/spi/amic.c | 4 ++-- src/drivers/spi/gigadevice.c | 4 ++-- src/drivers/spi/macronix.c | 5 ++--- src/drivers/spi/stmicro.c | 4 ++-- src/drivers/spi/winbond.c | 4 ++-- src/include/spi-generic.h | 2 ++ src/include/spi_flash.h | 8 -------- src/soc/intel/baytrail/spi.c | 7 ++++++- src/soc/intel/fsp_baytrail/spi.c | 7 ++++++- src/southbridge/amd/agesa/hudson/spi.c | 6 ++++++ src/southbridge/amd/cimx/sb800/spi.c | 7 +++++++ src/southbridge/intel/common/spi.c | 7 ++++++- 13 files changed, 45 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/drivers/spi/adesto.c b/src/drivers/spi/adesto.c index 9dc8e14546..50e58839a1 100644 --- a/src/drivers/spi/adesto.c +++ b/src/drivers/spi/adesto.c @@ -100,7 +100,7 @@ static int adesto_write(struct spi_flash *flash, for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); - chunk_len = min(chunk_len, CONTROLLER_PAGE_LIMIT); + chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len); cmd[0] = CMD_AT25DF_PP; cmd[1] = (offset >> 16) & 0xff; @@ -118,7 +118,7 @@ static int adesto_write(struct spi_flash *flash, goto out; } - ret = spi_flash_cmd_write(flash->spi, cmd, 4, + ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf + actual, chunk_len); if (ret < 0) { printk(BIOS_WARNING, "SF: adesto Page Program failed\n"); diff --git a/src/drivers/spi/amic.c b/src/drivers/spi/amic.c index 4cccc71197..63a68a5309 100644 --- a/src/drivers/spi/amic.c +++ b/src/drivers/spi/amic.c @@ -82,7 +82,7 @@ static int amic_write(struct spi_flash *flash, for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); - chunk_len = min(chunk_len, CONTROLLER_PAGE_LIMIT); + chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len); cmd[0] = CMD_A25_PP; cmd[1] = (offset >> 16) & 0xff; @@ -100,7 +100,7 @@ static int amic_write(struct spi_flash *flash, goto out; } - ret = spi_flash_cmd_write(flash->spi, cmd, 4, + ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf + actual, chunk_len); if (ret < 0) { printk(BIOS_WARNING, "SF: AMIC Page Program failed\n"); diff --git a/src/drivers/spi/gigadevice.c b/src/drivers/spi/gigadevice.c index 3fb89c7fc5..783d321566 100644 --- a/src/drivers/spi/gigadevice.c +++ b/src/drivers/spi/gigadevice.c @@ -141,7 +141,7 @@ static int gigadevice_write(struct spi_flash *flash, u32 offset, for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); - chunk_len = min(chunk_len, CONTROLLER_PAGE_LIMIT); + chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len); ret = spi_flash_cmd(flash->spi, CMD_GD25_WREN, NULL, 0); if (ret < 0) { @@ -161,7 +161,7 @@ static int gigadevice_write(struct spi_flash *flash, u32 offset, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); #endif - ret = spi_flash_cmd_write(flash->spi, cmd, 4, + ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf + actual, chunk_len); if (ret < 0) { printk(BIOS_WARNING, diff --git a/src/drivers/spi/macronix.c b/src/drivers/spi/macronix.c index 3611599065..6e910f6b91 100644 --- a/src/drivers/spi/macronix.c +++ b/src/drivers/spi/macronix.c @@ -144,13 +144,12 @@ static int macronix_write(struct spi_flash *flash, ret = 0; for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); - chunk_len = min(chunk_len, CONTROLLER_PAGE_LIMIT); + chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len); cmd[0] = CMD_MX25XX_PP; cmd[1] = (offset >> 16) & 0xff; cmd[2] = (offset >> 8) & 0xff; cmd[3] = offset & 0xff; - #if CONFIG_DEBUG_SPI_FLASH printk(BIOS_SPEW, "PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x }" " chunk_len = %zu\n", @@ -163,7 +162,7 @@ static int macronix_write(struct spi_flash *flash, break; } - ret = spi_flash_cmd_write(flash->spi, cmd, 4, + ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf + actual, chunk_len); if (ret < 0) { printk(BIOS_WARNING, "SF: Macronix Page Program failed\n"); diff --git a/src/drivers/spi/stmicro.c b/src/drivers/spi/stmicro.c index c825bd083b..bc7969d138 100644 --- a/src/drivers/spi/stmicro.c +++ b/src/drivers/spi/stmicro.c @@ -155,7 +155,7 @@ static int stmicro_write(struct spi_flash *flash, for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); - chunk_len = min(chunk_len, CONTROLLER_PAGE_LIMIT); + chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len); cmd[0] = CMD_M25PXX_PP; cmd[1] = (offset >> 16) & 0xff; @@ -173,7 +173,7 @@ static int stmicro_write(struct spi_flash *flash, goto out; } - ret = spi_flash_cmd_write(flash->spi, cmd, 4, + ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf + actual, chunk_len); if (ret < 0) { printk(BIOS_WARNING, "SF: STMicro Page Program failed\n"); diff --git a/src/drivers/spi/winbond.c b/src/drivers/spi/winbond.c index eb0868ec7a..7ddd312616 100644 --- a/src/drivers/spi/winbond.c +++ b/src/drivers/spi/winbond.c @@ -134,7 +134,7 @@ static int winbond_write(struct spi_flash *flash, for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); - chunk_len = min(chunk_len, CONTROLLER_PAGE_LIMIT); + chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len); cmd[0] = CMD_W25_PP; cmd[1] = (offset >> 16) & 0xff; @@ -152,7 +152,7 @@ static int winbond_write(struct spi_flash *flash, goto out; } - ret = spi_flash_cmd_write(flash->spi, cmd, 4, + ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf + actual, chunk_len); if (ret < 0) { printk(BIOS_WARNING, "SF: Winbond Page Program failed\n"); diff --git a/src/include/spi-generic.h b/src/include/spi-generic.h index 6c62de6d1d..3b10ae9f49 100644 --- a/src/include/spi-generic.h +++ b/src/include/spi-generic.h @@ -168,6 +168,8 @@ void spi_cs_deactivate(struct spi_slave *slave); */ void spi_set_speed(struct spi_slave *slave, uint32_t hz); +unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len); + /*----------------------------------------------------------------------- * Write 8 bits, then read 8 bits. * slave: The SPI slave we're communicating with diff --git a/src/include/spi_flash.h b/src/include/spi_flash.h index 61c931e32c..70ca784c90 100644 --- a/src/include/spi_flash.h +++ b/src/include/spi_flash.h @@ -39,14 +39,6 @@ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) -#define CONFIG_ICH_SPI -#ifdef CONFIG_ICH_SPI -#define CONTROLLER_PAGE_LIMIT 64 -#else -/* any number larger than 4K would do, actually */ -#define CONTROLLER_PAGE_LIMIT ((int)(~0U>>1)) -#endif - struct spi_flash { struct spi_slave *spi; diff --git a/src/soc/intel/baytrail/spi.c b/src/soc/intel/baytrail/spi.c index b649f53411..0dc980f8af 100644 --- a/src/soc/intel/baytrail/spi.c +++ b/src/soc/intel/baytrail/spi.c @@ -499,6 +499,11 @@ static int ich_status_poll(u16 bitmask, int wait_til_set) return -1; } +unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len) +{ + return min(cntlr.databytes, buf_len); +} + int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bytesout, void *din, unsigned int bytesin) { @@ -588,7 +593,7 @@ int spi_xfer(struct spi_slave *slave, const void *dout, */ if (trans.bytesout > cntlr.databytes) { printk(BIOS_DEBUG, "ICH SPI: Too much to write. Does your SPI chip driver use" - " CONTROLLER_PAGE_LIMIT?\n"); + " spi_crop_chunk()?\n"); return -1; } diff --git a/src/soc/intel/fsp_baytrail/spi.c b/src/soc/intel/fsp_baytrail/spi.c index 50f11231da..4feb502819 100644 --- a/src/soc/intel/fsp_baytrail/spi.c +++ b/src/soc/intel/fsp_baytrail/spi.c @@ -497,6 +497,11 @@ static int ich_status_poll(u16 bitmask, int wait_til_set) return -1; } +unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len) +{ + return min(cntlr.databytes, buf_len); +} + int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bytesout, void *din, unsigned int bytesin) { @@ -585,7 +590,7 @@ int spi_xfer(struct spi_slave *slave, const void *dout, */ if (trans.bytesout > cntlr.databytes) { printk(BIOS_DEBUG, "ICH SPI: Too much to write. Does your SPI chip driver use" - " CONTROLLER_PAGE_LIMIT?\n"); + " spi_crop_chunk()?\n"); return -1; } diff --git a/src/southbridge/amd/agesa/hudson/spi.c b/src/southbridge/amd/agesa/hudson/spi.c index 720b26f83e..f050a63f91 100644 --- a/src/southbridge/amd/agesa/hudson/spi.c +++ b/src/southbridge/amd/agesa/hudson/spi.c @@ -42,6 +42,7 @@ static int bus_claimed = 0; #define SPI_REG_CNTRL11 0xd #define CNTRL11_FIFOPTR_MASK 0x07 +#define AMD_SB_SPI_TX_LEN 64 static u32 spibar; @@ -86,6 +87,11 @@ void spi_init(void) spibar = pci_read_config32(dev, 0xA0) & ~0x1F; } +unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len) +{ + return min(AMD_SB_SPI_TX_LEN - cmd_len, buf_len); +} + int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bytesout, void *din, unsigned int bytesin) { diff --git a/src/southbridge/amd/cimx/sb800/spi.c b/src/southbridge/amd/cimx/sb800/spi.c index a46349e933..e5b2407082 100644 --- a/src/southbridge/amd/cimx/sb800/spi.c +++ b/src/southbridge/amd/cimx/sb800/spi.c @@ -32,6 +32,8 @@ static int bus_claimed = 0; #endif +#define AMD_SB_SPI_TX_LEN 8 + static u32 spibar; static void reset_internal_fifo_pointer(void) @@ -56,6 +58,11 @@ void spi_init() spibar = pci_read_config32(dev, 0xA0) & ~0x1F; } +unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len) +{ + return min(AMD_SB_SPI_TX_LEN - cmd_len, buf_len); +} + int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bytesout, void *din, unsigned int bytesin) { diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c index 76fd22691f..8e7192b49f 100644 --- a/src/southbridge/intel/common/spi.c +++ b/src/southbridge/intel/common/spi.c @@ -550,6 +550,11 @@ static int spi_is_multichip (void) return !!((cntlr.flmap0 >> 8) & 3); } +unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len) +{ + return min(cntlr.databytes, buf_len); +} + int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bytesout, void *din, unsigned int bytesin) { @@ -639,7 +644,7 @@ int spi_xfer(struct spi_slave *slave, const void *dout, */ if (trans.bytesout > cntlr.databytes) { printk(BIOS_DEBUG, "ICH SPI: Too much to write. Does your SPI chip driver use" - " CONTROLLER_PAGE_LIMIT?\n"); + " spi_crop_chunk()?\n"); return -1; } -- cgit v1.2.3