[coreboot-gerrit] New patch to review for coreboot: spi/SST: fix write support for SST25VF064C

Alexander Couzens (lynxis@fe80.eu) gerrit at coreboot.org
Wed Mar 9 05:30:40 CET 2016


Alexander Couzens (lynxis at fe80.eu) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14000

-gerrit

commit 3bf7af4afb6423e933e8a8366d4566ceea40b372
Author: Alexander Couzens <lynxis at fe80.eu>
Date:   Wed Mar 9 05:11:44 2016 +0100

    spi/SST: fix write support for SST25VF064C
    
    The SST25VF064C doesn't support the auto incrementing write which
    all other supported SST chips support. Allow the chips to select
    their write method.
    
    Change-Id: Ic088d35461a625469ee6973d1267d7dd11963496
    Signed-off-by: Alexander Couzens <lynxis at fe80.eu>
---
 src/drivers/spi/sst.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 94 insertions(+), 2 deletions(-)

diff --git a/src/drivers/spi/sst.c b/src/drivers/spi/sst.c
index aab654c..87c1c5b 100644
--- a/src/drivers/spi/sst.c
+++ b/src/drivers/spi/sst.c
@@ -40,6 +40,8 @@ struct sst_spi_flash_params {
 	u8 idcode1;
 	u16 nr_sectors;
 	const char *name;
+	int (*write)(struct spi_flash *flash, u32 offset,
+				 size_t len, const void *buf);
 };
 
 struct sst_spi_flash {
@@ -47,44 +49,58 @@ struct sst_spi_flash {
 	const struct sst_spi_flash_params *params;
 };
 
+static int
+sst_write_ai(struct spi_flash *flash, u32 offset, size_t len, const void *buf);
+static int
+sst_write_256(struct spi_flash *flash, u32 offset, size_t len, const void *buf);
+
 #define SST_SECTOR_SIZE (4 * 1024)
 static const struct sst_spi_flash_params sst_spi_flash_table[] = {
 	{
 		.idcode1 = 0x8d,
 		.nr_sectors = 128,
 		.name = "SST25VF040B",
+		.write = sst_write_ai,
 	},{
 		.idcode1 = 0x8e,
 		.nr_sectors = 256,
 		.name = "SST25VF080B",
+		.write = sst_write_ai,
 	},{
 		.idcode1 = 0x41,
 		.nr_sectors = 512,
 		.name = "SST25VF016B",
+		.write = sst_write_ai,
 	},{
 		.idcode1 = 0x4a,
 		.nr_sectors = 1024,
 		.name = "SST25VF032B",
+		.write = sst_write_ai,
 	},{
 		.idcode1 = 0x4b,
 		.nr_sectors = 2048,
 		.name = "SST25VF064C",
+		.write = sst_write_256,
 	},{
 		.idcode1 = 0x01,
 		.nr_sectors = 16,
 		.name = "SST25WF512",
+		.write = sst_write_ai,
 	},{
 		.idcode1 = 0x02,
 		.nr_sectors = 32,
 		.name = "SST25WF010",
+		.write = sst_write_ai,
 	},{
 		.idcode1 = 0x03,
 		.nr_sectors = 64,
 		.name = "SST25WF020",
+		.write = sst_write_ai,
 	},{
 		.idcode1 = 0x04,
 		.nr_sectors = 128,
 		.name = "SST25WF040",
+		.write = sst_write_ai,
 	},
 };
 
@@ -143,7 +159,83 @@ sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
 }
 
 static int
-sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
+sst_write_256(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
+{
+	size_t actual, chunk_len, cmd_len;
+	unsigned long byte_addr;
+	unsigned long page_size;
+	int ret = 0;
+	u8 cmd[4];
+
+	page_size = 256;
+	byte_addr = offset % page_size;
+
+	flash->spi->rw = SPI_WRITE_FLAG;
+
+	/* If the data is not word aligned, write out leading single byte */
+	actual = offset % 2;
+	if (actual) {
+		ret = sst_byte_write(flash, offset, buf);
+		if (ret)
+			goto done;
+	}
+	offset += actual;
+
+	ret = sst_enable_writing(flash);
+	if (ret)
+		goto done;
+
+	cmd_len = 4;
+	cmd[0] = CMD_SST_AAI_WP;
+	cmd[1] = offset >> 16;
+	cmd[2] = offset >> 8;
+	cmd[3] = offset;
+
+	for (actual = 0; actual < len; actual += chunk_len) {
+		chunk_len = min(len - actual, page_size - byte_addr);
+		chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);
+
+		cmd[0] = CMD_SST_BP;
+		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",
+		     buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
+#endif
+
+		ret = spi_flash_cmd(flash->spi, CMD_SST_WREN, NULL, 0);
+		if (ret < 0) {
+			printk(BIOS_WARNING, "SF: Enabling Write failed\n");
+			break;
+		}
+
+		ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd),
+					  buf + actual, chunk_len);
+		if (ret < 0) {
+			printk(BIOS_WARNING, "SF: SST Page Program failed\n");
+			break;
+		}
+
+		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+		if (ret)
+			break;
+
+		offset += chunk_len;
+		byte_addr = 0;
+	}
+
+done:
+#if CONFIG_DEBUG_SPI_FLASH
+	printk(BIOS_SPEW, "SF: SST: program %s %zu bytes @ 0x%lx\n",
+	      ret ? "failure" : "success", len, (unsigned long)offset - actual);
+#endif
+	return ret;
+}
+
+static int
+sst_write_ai(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
 {
 	size_t actual, cmd_len;
 	int ret = 0;
@@ -257,7 +349,7 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
 	stm->flash.spi = spi;
 	stm->flash.name = params->name;
 
-	stm->flash.write = sst_write;
+	stm->flash.write = params->write;
 	stm->flash.erase = spi_flash_cmd_erase;
 	stm->flash.status = spi_flash_cmd_status;
 	stm->flash.read = spi_flash_cmd_read_fast;



More information about the coreboot-gerrit mailing list