Convert SPI chips to partial write
However, wrap the write functions in a compat layer to allow converting
the rest of flashrom later. Tested on Intel NM10 by David Hendricks.
Corresponding to flashrom svn r1080.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
diff --git a/spi25.c b/spi25.c
index 51be397..fa76531 100644
--- a/spi25.c
+++ b/spi25.c
@@ -874,6 +874,7 @@
/*
* Read a part of the flash chip.
+ * FIXME: Use the chunk code from Michael Karcher instead.
* Each page is read separately in chunks with a maximum size of chunksize.
*/
int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize)
@@ -913,6 +914,7 @@
/*
* Write a part of the flash chip.
+ * FIXME: Use the chunk code from Michael Karcher instead.
* Each page is written separately in chunks with a maximum size of chunksize.
*/
int spi_write_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize)
@@ -963,20 +965,13 @@
* and for chips where memory mapped programming is impossible
* (e.g. due to size constraints in IT87* for over 512 kB)
*/
-int spi_chip_write_1(struct flashchip *flash, uint8_t *buf)
+/* real chunksize is 1, logical chunksize is 1 */
+int spi_chip_write_1_new(struct flashchip *flash, uint8_t *buf, int start, int len)
{
- int total_size = 1024 * flash->total_size;
int i, result = 0;
spi_disable_blockprotect();
- /* Erase first */
- msg_cinfo("Erasing flash before programming... ");
- if (erase_flash(flash)) {
- msg_cerr("ERASE FAILED!\n");
- return -1;
- }
- msg_cinfo("done.\n");
- for (i = 0; i < total_size; i++) {
+ for (i = start; i < start + len; i++) {
result = spi_byte_program(i, buf[i]);
if (result)
return 1;
@@ -987,11 +982,23 @@
return 0;
}
-int spi_aai_write(struct flashchip *flash, uint8_t *buf)
+int spi_chip_write_1(struct flashchip *flash, uint8_t *buf)
{
- uint32_t addr = 0;
- uint32_t len = flash->total_size * 1024;
- uint32_t pos = addr;
+ spi_disable_blockprotect();
+ /* Erase first */
+ msg_cinfo("Erasing flash before programming... ");
+ if (erase_flash(flash)) {
+ msg_cerr("ERASE FAILED!\n");
+ return -1;
+ }
+ msg_cinfo("done.\n");
+
+ return spi_chip_write_1_new(flash, buf, 0, flash->total_size * 1024);
+}
+
+int spi_aai_write(struct flashchip *flash, uint8_t *buf, int start, int len)
+{
+ uint32_t pos = start;
int result;
unsigned char cmd[JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE] = {
JEDEC_AAI_WORD_PROGRAM,
@@ -1006,9 +1013,9 @@
.writecnt = JEDEC_AAI_WORD_PROGRAM_OUTSIZE,
.writearr = (const unsigned char[]){
JEDEC_AAI_WORD_PROGRAM,
- (pos >> 16) & 0xff,
- (pos >> 8) & 0xff,
- (pos & 0xff),
+ (start >> 16) & 0xff,
+ (start >> 8) & 0xff,
+ (start & 0xff),
buf[0],
buf[1]
},
@@ -1026,17 +1033,21 @@
#if defined(__i386__) || defined(__x86_64__)
case SPI_CONTROLLER_IT87XX:
case SPI_CONTROLLER_WBSIO:
- msg_cerr("%s: impossible with this SPI controller,"
+ msg_perr("%s: impossible with this SPI controller,"
" degrading to byte program\n", __func__);
- return spi_chip_write_1(flash, buf);
+ return spi_chip_write_1_new(flash, buf, start, len);
#endif
#endif
default:
break;
}
+ /* The even start address and even length requirements can be either
+ * honored outside this function, or we can call spi_byte_program
+ * for the first and/or last byte and use AAI for the rest.
+ */
/* The data sheet requires a start address with the low bit cleared. */
- if (addr % 2) {
+ if (start % 2) {
msg_cerr("%s: start address not even! Please report a bug at "
"flashrom@flashrom.org\n", __func__);
return SPI_GENERIC_ERROR;
@@ -1048,15 +1059,14 @@
return SPI_GENERIC_ERROR;
}
- if (erase_flash(flash)) {
- msg_cerr("ERASE FAILED!\n");
- return -1;
- }
result = spi_send_multicommand(cmds);
if (result) {
msg_cerr("%s failed during start command execution\n",
__func__);
+ /* FIXME: Should we send WRDI here as well to make sure the chip
+ * is not in AAI mode?
+ */
return result;
}
while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
@@ -1065,7 +1075,7 @@
/* We already wrote 2 bytes in the multicommand step. */
pos += 2;
- while (pos < addr + len) {
+ while (pos < start + len) {
cmd[1] = buf[pos++];
cmd[2] = buf[pos++];
spi_send_command(JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL);