mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-28 07:23:43 +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:
parent
8ae500e09d
commit
9c62d11d55
6
spi.h
6
spi.h
@ -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
81
spi25.c
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user