mirror of
https://review.coreboot.org/flashrom.git
synced 2025-07-01 14:11:15 +02:00
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>
This commit is contained in:
60
spi25.c
60
spi25.c
@ -874,6 +874,7 @@ int spi_nbyte_read(int address, uint8_t *bytes, int len)
|
||||
|
||||
/*
|
||||
* 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 @@ int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len,
|
||||
|
||||
/*
|
||||
* 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 @@ int spi_write_chunked(struct flashchip *flash, uint8_t *buf, int start, int len,
|
||||
* 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 @@ int spi_chip_write_1(struct flashchip *flash, uint8_t *buf)
|
||||
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 @@ int spi_aai_write(struct flashchip *flash, uint8_t *buf)
|
||||
.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 @@ int spi_aai_write(struct flashchip *flash, uint8_t *buf)
|
||||
#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 @@ int spi_aai_write(struct flashchip *flash, uint8_t *buf)
|
||||
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 @@ int spi_aai_write(struct flashchip *flash, uint8_t *buf)
|
||||
/* 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);
|
||||
|
Reference in New Issue
Block a user