Author: stefanct Date: Sun May 6 19:03:40 2012 New Revision: 1532 URL: http://flashrom.org/trac/flashrom/changeset/1532
Log: dummyflasher: Add a status register to SPI chips.
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at Acked-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Modified: trunk/dummyflasher.c trunk/flashrom.8 trunk/it87spi.c trunk/spi.h trunk/spi25.c
Modified: trunk/dummyflasher.c ============================================================================== --- trunk/dummyflasher.c Sun May 6 17:11:26 2012 (r1531) +++ trunk/dummyflasher.c Sun May 6 19:03:40 2012 (r1532) @@ -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_ignorelist[256]; int spi_blacklist_size = 0; int spi_ignorelist_size = 0; +static uint8_t emu_status = 0; #endif #endif
@@ -133,6 +135,9 @@ 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ "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 @@ } 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 @@ /* No special response. */ break; } + if (writearr[0] != JEDEC_WREN && writearr[0] != JEDEC_EWSR) + emu_status &= ~SPI_SR_WEL; return 0; } #endif
Modified: trunk/flashrom.8 ============================================================================== --- trunk/flashrom.8 Sun May 6 17:11:26 2012 (r1531) +++ trunk/flashrom.8 Sun May 6 19:03:40 2012 (r1532) @@ -495,6 +495,15 @@ 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\
Modified: trunk/it87spi.c ============================================================================== --- trunk/it87spi.c Sun May 6 17:11:26 2012 (r1531) +++ trunk/it87spi.c Sun May 6 19:03:40 2012 (r1532) @@ -335,7 +335,7 @@ /* 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; }
Modified: trunk/spi.h ============================================================================== --- trunk/spi.h Sun May 6 17:11:26 2012 (r1531) +++ trunk/spi.h Sun May 6 19:03:40 2012 (r1532) @@ -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
Modified: trunk/spi25.c ============================================================================== --- trunk/spi25.c Sun May 6 17:11:26 2012 (r1531) +++ trunk/spi25.c Sun May 6 19:03:40 2012 (r1532) @@ -479,7 +479,7 @@ * 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 @@ * 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 @@ /* 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 @@ /* 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 @@ /* 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 @@ /* 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 @@ * 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 @@ 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 @@ 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 @@ */ 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 @@ 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); }