1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-27 23:22:37 +02:00

Refine SPI AAI support

Modernize SPI AAI code, blacklist IT87 SPI for AAI, allow AAI to run
without warnings on ICH/VIA SPI. Add some code to make conversion to
partial write possible for AAI.

Corresponding to flashrom svn r1052.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Sean Nelson <audiohacked@gmail.com>
This commit is contained in:
Carl-Daniel Hailfinger 2010-06-20 10:41:35 +00:00
parent 8ae500e09d
commit 9c62d11d55
2 changed files with 72 additions and 15 deletions

6
spi.h
View File

@ -112,6 +112,12 @@
#define JEDEC_BYTE_PROGRAM_OUTSIZE 0x05 #define JEDEC_BYTE_PROGRAM_OUTSIZE 0x05
#define JEDEC_BYTE_PROGRAM_INSIZE 0x00 #define JEDEC_BYTE_PROGRAM_INSIZE 0x00
/* Write AAI word (SST25VF080B) */
#define JEDEC_AAI_WORD_PROGRAM 0xad
#define JEDEC_AAI_WORD_PROGRAM_OUTSIZE 0x06
#define JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE 0x06
#define JEDEC_AAI_WORD_PROGRAM_INSIZE 0x00
/* Error codes */ /* Error codes */
#define SPI_GENERIC_ERROR -1 #define SPI_GENERIC_ERROR -1
#define SPI_INVALID_OPCODE -2 #define SPI_INVALID_OPCODE -2

81
spi25.c
View File

@ -1012,15 +1012,44 @@ int spi_chip_write_1(struct flashchip *flash, uint8_t *buf)
int spi_aai_write(struct flashchip *flash, uint8_t *buf) int spi_aai_write(struct flashchip *flash, uint8_t *buf)
{ {
uint32_t pos = 2, size = flash->total_size * 1024; uint32_t addr = 0;
unsigned char w[6] = {0xad, 0, 0, 0, buf[0], buf[1]}; uint32_t len = flash->total_size * 1024;
uint32_t pos = addr;
int result; int result;
unsigned char cmd[JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE] = {
JEDEC_AAI_WORD_PROGRAM,
};
struct spi_command cmds[] = {
{
.writecnt = JEDEC_WREN_OUTSIZE,
.writearr = (const unsigned char[]){ JEDEC_WREN },
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = JEDEC_AAI_WORD_PROGRAM_OUTSIZE,
.writearr = (const unsigned char[]){
JEDEC_AAI_WORD_PROGRAM,
(pos >> 16) & 0xff,
(pos >> 8) & 0xff,
(pos & 0xff),
buf[0],
buf[1]
},
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = 0,
.writearr = NULL,
.readcnt = 0,
.readarr = NULL,
}};
switch (spi_controller) { switch (spi_controller) {
#if CONFIG_INTERNAL == 1 #if CONFIG_INTERNAL == 1
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
case SPI_CONTROLLER_IT87XX:
case SPI_CONTROLLER_WBSIO: case SPI_CONTROLLER_WBSIO:
msg_cerr("%s: impossible with Winbond SPI masters," msg_cerr("%s: impossible with this SPI controller,"
" degrading to byte program\n", __func__); " degrading to byte program\n", __func__);
return spi_chip_write_1(flash, buf); return spi_chip_write_1(flash, buf);
#endif #endif
@ -1028,24 +1057,46 @@ int spi_aai_write(struct flashchip *flash, uint8_t *buf)
default: default:
break; break;
} }
/* The data sheet requires a start address with the low bit cleared. */
if (addr % 2) {
msg_cerr("%s: start address not even! Please report a bug at "
"flashrom@flashrom.org\n", __func__);
return SPI_GENERIC_ERROR;
}
/* The data sheet requires total AAI write length to be even. */
if (len % 2) {
msg_cerr("%s: total write length not even! Please report a "
"bug at flashrom@flashrom.org\n", __func__);
return SPI_GENERIC_ERROR;
}
if (erase_flash(flash)) { if (erase_flash(flash)) {
msg_cerr("ERASE FAILED!\n"); msg_cerr("ERASE FAILED!\n");
return -1; return -1;
} }
/* FIXME: This will fail on ICH/VIA SPI. */
result = spi_write_enable(); result = spi_send_multicommand(cmds);
if (result) if (result) {
msg_cerr("%s failed during start command execution\n",
__func__);
return result; return result;
spi_send_command(6, 0, w, NULL);
while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
programmer_delay(5); /* SST25VF040B Tbp is max 10us */
while (pos < size) {
w[1] = buf[pos++];
w[2] = buf[pos++];
spi_send_command(3, 0, w, NULL);
while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
programmer_delay(5); /* SST25VF040B Tbp is max 10us */
} }
while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
programmer_delay(10);
/* We already wrote 2 bytes in the multicommand step. */
pos += 2;
while (pos < addr + len) {
cmd[1] = buf[pos++];
cmd[2] = buf[pos++];
spi_send_command(JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL);
while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
programmer_delay(10);
}
/* Use WRDI to exit AAI mode. */
spi_write_disable(); spi_write_disable();
return 0; return 0;
} }