diff options
author | Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at> | 2012-05-06 17:03:40 +0000 |
---|---|---|
committer | Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at> | 2012-05-06 17:03:40 +0000 |
commit | 5e695ab4d7555952f0b020f235d868955251e3ae (patch) | |
tree | 2fbeddbc906b96de794bd02794d73360124277d6 | |
parent | dc704edad44995845727a231e3f1d6dda74708fd (diff) | |
download | flashrom-5e695ab4d7555952f0b020f235d868955251e3ae.tar.gz flashrom-5e695ab4d7555952f0b020f235d868955251e3ae.tar.bz2 flashrom-5e695ab4d7555952f0b020f235d868955251e3ae.zip |
dummyflasher: Add a status register to SPI chips
Corresponding to flashrom svn r1532.
Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
-rw-r--r-- | dummyflasher.c | 66 | ||||
-rw-r--r-- | flashrom.8 | 9 | ||||
-rw-r--r-- | it87spi.c | 2 | ||||
-rw-r--r-- | spi.h | 6 | ||||
-rw-r--r-- | spi25.c | 22 |
5 files changed, 82 insertions, 23 deletions
diff --git a/dummyflasher.c b/dummyflasher.c index afe05182e..50e8bf326 100644 --- a/dummyflasher.c +++ b/dummyflasher.c @@ -21,6 +21,7 @@ #include <stdlib.h> #include <stdio.h> #include <ctype.h> +#include <errno.h> #include "flash.h" #include "chipdrivers.h" #include "programmer.h" @@ -61,6 +62,7 @@ unsigned char spi_blacklist[256]; unsigned char spi_ignorelist[256]; int spi_blacklist_size = 0; int spi_ignorelist_size = 0; +static uint8_t emu_status = 0; #endif #endif @@ -133,6 +135,9 @@ int dummy_init(void) char *bustext = NULL; char *tmp = NULL; int i; +#if EMULATE_SPI_CHIP + char *status = NULL; +#endif #if EMULATE_CHIP struct stat image_stat; #endif @@ -309,6 +314,23 @@ int dummy_init(void) return 1; } +#ifdef EMULATE_SPI_CHIP + status = extract_programmer_param("spi_status"); + if (status) { + char *endptr; + errno = 0; + emu_status = strtoul(status, &endptr, 0); + free(status); + if (errno != 0 || status == endptr) { + msg_perr("Error: initial status register specified, " + "but the value could not be converted.\n"); + return 1; + } + msg_pdbg("Initial status register is set to 0x%02x.\n", + emu_status); + } +#endif + msg_pdbg("Filling fake flash chip with 0xff, size %i\n", emu_chip_size); memset(flashchip_contents, 0xff, emu_chip_size); @@ -429,7 +451,6 @@ static int emulate_spi_chip_response(unsigned int writecnt, { unsigned int offs, i; static int unsigned aai_offs; - static int aai_active = 0; if (writecnt == 0) { msg_perr("No command sent to the chip!\n"); @@ -453,6 +474,17 @@ static int emulate_spi_chip_response(unsigned int writecnt, return 0; } } + + if (emu_max_aai_size && (emu_status & SPI_SR_AAI)) { + if (writearr[0] != JEDEC_AAI_WORD_PROGRAM && + writearr[0] != JEDEC_WRDI && + writearr[0] != JEDEC_RDSR) { + msg_perr("Forbidden opcode (0x%02x) attempted during " + "AAI sequence!\n", writearr[0]); + return 0; + } + } + switch (writearr[0]) { case JEDEC_RES: if (emu_chip != EMULATE_ST_M25P10_RES) @@ -481,10 +513,23 @@ static int emulate_spi_chip_response(unsigned int writecnt, if (readcnt > 2) readarr[2] = 0x4a; break; - case JEDEC_RDSR: - memset(readarr, 0, readcnt); - if (aai_active) - memset(readarr, 1 << 6, readcnt); + case JEDEC_RDSR: { + memset(readarr, emu_status, readcnt); + break; + } + /* FIXME: this should be chip-specific. */ + case JEDEC_EWSR: + case JEDEC_WREN: + emu_status |= SPI_SR_WEL; + break; + case JEDEC_WRSR: + if (!(emu_status & SPI_SR_WEL)) { + msg_perr("WRSR attempted, but WEL is 0!\n"); + break; + } + /* FIXME: add some reasonable simulation of the busy flag */ + emu_status = writearr[1] & ~SPI_SR_WIP; + msg_pdbg2("WRSR wrote 0x%02x.\n", emu_status); break; case JEDEC_READ: offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; @@ -510,7 +555,7 @@ static int emulate_spi_chip_response(unsigned int writecnt, case JEDEC_AAI_WORD_PROGRAM: if (!emu_max_aai_size) break; - if (!aai_active) { + if (!(emu_status & SPI_SR_AAI)) { if (writecnt < JEDEC_AAI_WORD_PROGRAM_OUTSIZE) { msg_perr("Initial AAI WORD PROGRAM size too " "short!\n"); @@ -521,7 +566,7 @@ static int emulate_spi_chip_response(unsigned int writecnt, "long!\n"); return 1; } - aai_active = 1; + emu_status |= SPI_SR_AAI; aai_offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; /* Truncate to emu_chip_size. */ @@ -544,9 +589,8 @@ static int emulate_spi_chip_response(unsigned int writecnt, } break; case JEDEC_WRDI: - if (!emu_max_aai_size) - break; - aai_active = 0; + if (emu_max_aai_size) + emu_status &= ~SPI_SR_AAI; break; case JEDEC_SE: if (!emu_jedec_se_size) @@ -633,6 +677,8 @@ static int emulate_spi_chip_response(unsigned int writecnt, /* No special response. */ break; } + if (writearr[0] != JEDEC_WREN && writearr[0] != JEDEC_EWSR) + emu_status &= ~SPI_SR_WEL; return 0; } #endif diff --git a/flashrom.8 b/flashrom.8 index 51081272a..2bb57f1f7 100644 --- a/flashrom.8 +++ b/flashrom.8 @@ -495,6 +495,15 @@ SPI commands. If commandlist is e.g. 0302, the emulated flash chip will ignore command 0x03 (READ) and command 0x02 (WRITE). commandlist may be up to 512 characters (256 commands) long. Implementation note: flashrom won't detect an error during command execution. +.sp +.TP +.B SPI status register +.sp +You can specify the initial content of the chip's status register with the +.sp +.B " flashrom -p dummy:spi_status=content" +.sp +syntax where content is an 8-bit hexadecimal value. .SS .BR "nic3com" , " nicrealtek" , " nicsmc1211" , " nicnatsemi" , " nicintel\ " , " nicintel_spi" , " gfxnvidia" , " ogp_spi" , " drkaiser" , " satasii\ @@ -335,7 +335,7 @@ static int it8716f_spi_page_program(struct flashctx *flash, uint8_t *buf, /* Wait until the Write-In-Progress bit is cleared. * This usually takes 1-10 ms, so wait in 1 ms steps. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(1000); return 0; } @@ -95,7 +95,11 @@ #define JEDEC_RDSR 0x05 #define JEDEC_RDSR_OUTSIZE 0x01 #define JEDEC_RDSR_INSIZE 0x01 -#define JEDEC_RDSR_BIT_WIP (0x01 << 0) + +/* Status Register Bits */ +#define SPI_SR_WIP (0x01 << 0) +#define SPI_SR_WEL (0x01 << 1) +#define SPI_SR_AAI (0x01 << 6) /* Write Status Enable */ #define JEDEC_EWSR 0x50 @@ -479,7 +479,7 @@ int spi_chip_erase_60(struct flashctx *flash) * This usually takes 1-85 s, so wait in 1 s steps. */ /* FIXME: We assume spi_read_status_register will never fail. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(1000 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -515,7 +515,7 @@ int spi_chip_erase_c7(struct flashctx *flash) * This usually takes 1-85 s, so wait in 1 s steps. */ /* FIXME: We assume spi_read_status_register will never fail. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(1000 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -557,7 +557,7 @@ int spi_block_erase_52(struct flashctx *flash, unsigned int addr, /* Wait until the Write-In-Progress bit is cleared. * This usually takes 100-4000 ms, so wait in 100 ms steps. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(100 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -604,7 +604,7 @@ int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, /* Wait until the Write-In-Progress bit is cleared. * This usually takes 100-4000 ms, so wait in 100 ms steps. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(100 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -649,7 +649,7 @@ int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, /* Wait until the Write-In-Progress bit is cleared. * This usually takes 100-4000 ms, so wait in 100 ms steps. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(100 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -692,7 +692,7 @@ int spi_block_erase_20(struct flashctx *flash, unsigned int addr, /* Wait until the Write-In-Progress bit is cleared. * This usually takes 15-800 ms, so wait in 10 ms steps. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(10 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -805,7 +805,7 @@ static int spi_write_status_register_flag(struct flashctx *flash, int status, co * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed. */ programmer_delay(100 * 1000); - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) { + while (spi_read_status_register(flash) & SPI_SR_WIP) { if (++i > 490) { msg_cerr("Error: WIP bit after WRSR never cleared\n"); return TIMEOUT_ERROR; @@ -1035,7 +1035,7 @@ int spi_write_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, rc = spi_nbyte_program(flash, starthere + j, buf + starthere - start + j, towrite); if (rc) break; - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(10); } if (rc) @@ -1062,7 +1062,7 @@ int spi_chip_write_1(struct flashctx *flash, uint8_t *buf, unsigned int start, result = spi_byte_program(flash, i, buf[i - start]); if (result) return 1; - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(10); } @@ -1157,7 +1157,7 @@ int spi_aai_write(struct flashctx *flash, uint8_t *buf, unsigned int start, */ return result; } - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(10); /* We already wrote 2 bytes in the multicommand step. */ @@ -1169,7 +1169,7 @@ int spi_aai_write(struct flashctx *flash, uint8_t *buf, unsigned int start, cmd[2] = buf[pos++ - start]; spi_send_command(flash, JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL); - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(10); } |