From 50aed5c157f4d15622a73fdcfeca75cd70c3dde2 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Fri, 12 Mar 2010 12:01:05 +0000 Subject: [PATCH] svn ver. 931 --- ...-r710-r893.diff => flashrom-r710-r931.diff | 6346 +++++++++++++---- flashrom.spec | 18 +- import.log | 1 + 3 files changed, 4835 insertions(+), 1530 deletions(-) rename flashrom-r710-r893.diff => flashrom-r710-r931.diff (78%) diff --git a/flashrom-r710-r893.diff b/flashrom-r710-r931.diff similarity index 78% rename from flashrom-r710-r893.diff rename to flashrom-r710-r931.diff index 0e86b59..044c6e4 100644 --- a/flashrom-r710-r893.diff +++ b/flashrom-r710-r931.diff @@ -1,8 +1,13 @@ diff --git a/82802ab.c b/82802ab.c -index 28fa177..dfe81e8 100644 +index 28fa177..e63dc10 100644 --- a/82802ab.c +++ b/82802ab.c -@@ -33,13 +33,13 @@ +@@ -29,17 +29,18 @@ + #include + #include + #include "flash.h" ++#include "chipdrivers.h" + // I need that Berkeley bit-map printer void print_82802ab_status(uint8_t status) { @@ -23,7 +28,7 @@ index 28fa177..dfe81e8 100644 } int probe_82802ab(struct flashchip *flash) -@@ -47,14 +47,11 @@ int probe_82802ab(struct flashchip *flash) +@@ -47,14 +48,11 @@ int probe_82802ab(struct flashchip *flash) chipaddr bios = flash->virtual_memory; uint8_t id1, id2; @@ -42,7 +47,7 @@ index 28fa177..dfe81e8 100644 chip_writeb(0x90, bios); programmer_delay(10); -@@ -62,13 +59,11 @@ int probe_82802ab(struct flashchip *flash) +@@ -62,13 +60,11 @@ int probe_82802ab(struct flashchip *flash) id2 = chip_readb(bios + 0x01); /* Leave ID mode */ @@ -58,7 +63,7 @@ index 28fa177..dfe81e8 100644 if (id1 != flash->manufacture_id || id2 != flash->model_id) return 0; -@@ -81,7 +76,6 @@ int probe_82802ab(struct flashchip *flash) +@@ -81,7 +77,6 @@ int probe_82802ab(struct flashchip *flash) uint8_t wait_82802ab(chipaddr bios) { uint8_t status; @@ -66,7 +71,7 @@ index 28fa177..dfe81e8 100644 chip_writeb(0x70, bios); if ((chip_readb(bios) & 0x80) == 0) { // it's busy -@@ -90,49 +84,38 @@ uint8_t wait_82802ab(chipaddr bios) +@@ -90,49 +85,38 @@ uint8_t wait_82802ab(chipaddr bios) status = chip_readb(bios); @@ -131,7 +136,7 @@ index 28fa177..dfe81e8 100644 return 0; } -@@ -145,7 +128,7 @@ int erase_82802ab(struct flashchip *flash) +@@ -145,7 +129,7 @@ int erase_82802ab(struct flashchip *flash) printf("total_size is %d; flash->page_size is %d\n", total_size, flash->page_size); for (i = 0; i < total_size; i += flash->page_size) @@ -140,7 +145,7 @@ index 28fa177..dfe81e8 100644 fprintf(stderr, "ERASE FAILED!\n"); return -1; } -@@ -199,7 +182,7 @@ int write_82802ab(struct flashchip *flash, uint8_t *buf) +@@ -199,7 +183,7 @@ int write_82802ab(struct flashchip *flash, uint8_t *buf) } /* erase block by block and write block by block; this is the most secure way */ @@ -149,7 +154,7 @@ index 28fa177..dfe81e8 100644 fprintf(stderr, "ERASE FAILED!\n"); return -1; } -@@ -207,7 +190,6 @@ int write_82802ab(struct flashchip *flash, uint8_t *buf) +@@ -207,7 +191,6 @@ int write_82802ab(struct flashchip *flash, uint8_t *buf) bios + i * page_size, page_size); } printf("\n"); @@ -158,7 +163,7 @@ index 28fa177..dfe81e8 100644 return 0; diff --git a/Makefile b/Makefile -index 881c8f2..62c6a74 100644 +index 881c8f2..9245624 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ INSTALL = install @@ -186,9 +191,9 @@ index 881c8f2..62c6a74 100644 endif -LIBS += -lpci -lz -+CHIP_OBJS = jedec.o stm50flw0x0x.o w39v080fa.o sharplhf00l04.o w29ee011.o \ ++CHIP_OBJS = jedec.o stm50flw0x0x.o w39v040c.o w39v080fa.o sharplhf00l04.o w29ee011.o \ + sst28sf040.o m29f400bt.o 82802ab.o pm49fl00x.o \ -+ sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o ++ sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o -OBJS = chipset_enable.o board_enable.o udelay.o jedec.o stm50flw0x0x.o \ - sst28sf040.o am29f040b.o mx29f002.o m29f400bt.o pm29f002.o \ @@ -211,11 +216,11 @@ index 881c8f2..62c6a74 100644 # Note to packagers: Any tree exported with "make export" or "make tarball" # will not require subversion. The downloadable snapshots are already exported. -SVNVERSION := 710 -+SVNVERSION := 893 ++SVNVERSION := 931 RELEASE := 0.9.1 VERSION := $(RELEASE)-r$(SVNVERSION) -@@ -66,23 +65,145 @@ RELEASENAME ?= $(VERSION) +@@ -66,23 +65,150 @@ RELEASENAME ?= $(VERSION) SVNDEF := -D'FLASHROM_VERSION="$(VERSION)"' @@ -238,6 +243,10 @@ index 881c8f2..62c6a74 100644 +# Always enable SiI SATA controllers for now. +CONFIG_SATASII ?= yes + ++# Highpoint (HPT) ATA/RAID controller support. ++# IMPORTANT: This code is not yet working! ++CONFIG_ATAHPT ?= no ++ +# Always enable FT2232 SPI dongles for now. +CONFIG_FT2232SPI ?= yes + @@ -258,7 +267,7 @@ index 881c8f2..62c6a74 100644 + +ifeq ($(CONFIG_INTERNAL), yes) +FEATURE_CFLAGS += -D'INTERNAL_SUPPORT=1' -+PROGRAMMER_OBJS += chipset_enable.o board_enable.o cbtable.o dmi.o it87spi.o ichspi.o sb600spi.o wbsio_spi.o ++PROGRAMMER_OBJS += chipset_enable.o board_enable.o cbtable.o dmi.o it87spi.o ichspi.o sb600spi.o wbsio_spi.o internal.o +NEED_PCI := yes +endif @@ -294,6 +303,12 @@ index 881c8f2..62c6a74 100644 +NEED_PCI := yes +endif + ++ifeq ($(CONFIG_ATAHPT), yes) ++FEATURE_CFLAGS += -D'ATAHPT_SUPPORT=1' ++PROGRAMMER_OBJS += atahpt.o ++NEED_PCI := yes ++endif ++ +ifeq ($(CONFIG_FT2232SPI), yes) +FTDILIBS := $(shell pkg-config --libs libftdi 2>/dev/null || printf "%s" "-lftdi -lusb") +# This is a totally ugly hack. @@ -301,13 +316,13 @@ index 881c8f2..62c6a74 100644 +FEATURE_LIBS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "$(FTDILIBS)") +PROGRAMMER_OBJS += ft2232_spi.o +endif -+ + +-FEATURE_LIBS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "-lftdi") +ifeq ($(CONFIG_DUMMY), yes) +FEATURE_CFLAGS += -D'DUMMY_SUPPORT=1' +PROGRAMMER_OBJS += dummyflasher.o +endif - --FEATURE_LIBS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "-lftdi") ++ +ifeq ($(CONFIG_DRKAISER), yes) +FEATURE_CFLAGS += -D'DRKAISER_SUPPORT=1' +PROGRAMMER_OBJS += drkaiser.o @@ -337,15 +352,10 @@ index 881c8f2..62c6a74 100644 +ifeq ($(NEED_PCI), yes) +LIBS += -lpci +FEATURE_CFLAGS += -D'NEED_PCI=1' -+PROGRAMMER_OBJS += pcidev.o physmap.o internal.o #FIXME: We need to move stuff -+ # from internal.c and pcidev.c to pci.c -+ # internal.c needs to be split -+ # into internal-programmer-only stuff -+ # and a support lib for all internal+pci -+ # based stuff. ++PROGRAMMER_OBJS += pcidev.o physmap.o hwaccess.o +ifeq ($(OS_ARCH), NetBSD) +LIBS += -lpciutils # The libpci we want. -+LIBS += -l$(shell uname -m) # For (i386|x86_64)_iopl(2). ++LIBS += -l$(shell uname -p) # For (i386|x86_64)_iopl(2). +endif +endif + @@ -365,7 +375,7 @@ index 881c8f2..62c6a74 100644 # TAROPTIONS reduces information leakage from the packager's system. # If other tar programs support command line arguments for setting uid/gid of -@@ -96,7 +217,7 @@ clean: +@@ -96,7 +222,7 @@ clean: rm -f $(PROGRAM) *.o distclean: clean @@ -374,7 +384,7 @@ index 881c8f2..62c6a74 100644 dep: @$(CC) $(CPPFLAGS) $(SVNDEF) -MM *.c > .dependencies -@@ -108,26 +229,51 @@ compiler: +@@ -108,26 +234,51 @@ compiler: @printf "Checking for a C compiler... " @$(shell ( echo "int main(int argc, char **argv)"; \ echo "{ return 0; }"; ) > .test.c ) @@ -434,7 +444,7 @@ index 881c8f2..62c6a74 100644 features: compiler @echo "FEATURES := yes" > .features.tmp @printf "Checking for FTDI support... " -@@ -135,11 +281,16 @@ features: compiler +@@ -135,11 +286,16 @@ features: compiler echo "struct ftdi_context *ftdic = NULL;"; \ echo "int main(int argc, char **argv)"; \ echo "{ return ftdi_init(ftdic); }"; ) > .featuretest.c ) @@ -453,7 +463,7 @@ index 881c8f2..62c6a74 100644 install: $(PROGRAM) mkdir -p $(DESTDIR)$(PREFIX)/sbin diff --git a/README b/README -index b6a0792..3082f71 100644 +index b6a0792..0150e90 100644 --- a/README +++ b/README @@ -11,6 +11,8 @@ program flash chips. @@ -483,7 +493,7 @@ index b6a0792..3082f71 100644 ln -s /usr/pkg/include/pciutils pci - gmake CFLAGS=-I. LDFLAGS="-L/usr/pkg/lib" -+ gmake CFLAGS=-I. LDFLAGS="-L/usr/pkg/lib -Wl,-rpath-link,/usr/pkg/lib" ++ gmake CPPFLAGS=-I. LDFLAGS="-L/usr/pkg/lib -Wl,-rpath-link,/usr/pkg/lib" To compile and run on Darwin/Mac OS X: @@ -535,85 +545,248 @@ index b6a0792..3082f71 100644 Contact diff --git a/am29f040b.c b/am29f040b.c -index 7f1269c..62774ba 100644 +deleted file mode 100644 +index 7f1269c..0000000 --- a/am29f040b.c -+++ b/am29f040b.c -@@ -20,9 +20,9 @@ - - #include "flash.h" - ++++ /dev/null +@@ -1,140 +0,0 @@ +-/* +- * This file is part of the flashrom project. +- * +- * Copyright (C) 2000 Silicon Integrated System Corporation +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ +- +-#include "flash.h" +- -static int erase_sector_29f040b(struct flashchip *flash, unsigned long address) -+/* FIMXE: Use erase_sector_jedec if not? */ -+int erase_sector_29f040b(struct flashchip *flash, unsigned int address, unsigned int blocklen) - { +-{ - int page_size = flash->page_size; - chipaddr bios = flash->virtual_memory; - - chip_writeb(0xAA, bios + 0x555); -@@ -32,18 +32,30 @@ static int erase_sector_29f040b(struct flashchip *flash, unsigned long address) - chip_writeb(0x55, bios + 0x2AA); - chip_writeb(0x30, bios + address); - +- chipaddr bios = flash->virtual_memory; +- +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0x2AA); +- chip_writeb(0x80, bios + 0x555); +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0x2AA); +- chip_writeb(0x30, bios + address); +- - programmer_delay(2 * 1000 * 1000); -+ programmer_delay(10); - - /* wait for Toggle bit ready */ - toggle_ready_jedec(bios + address); - +- +- /* wait for Toggle bit ready */ +- toggle_ready_jedec(bios + address); +- - if (check_erased_range(flash, address, page_size)) { -+ if (check_erased_range(flash, address, blocklen)) { - fprintf(stderr, "ERASE FAILED!\n"); - return -1; - } - return 0; - } - -+/* erase chip with block_erase() prototype */ -+int erase_chip_29f040b(struct flashchip *flash, unsigned int addr, unsigned int blocklen) +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- return 0; +-} +- +-static int write_sector_29f040b(chipaddr bios, uint8_t *src, chipaddr dst, +- unsigned int page_size) +-{ +- int i; +- +- for (i = 0; i < page_size; i++) { +- if ((i & 0xfff) == 0xfff) +- printf("0x%08lx", dst - bios); +- +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0x2AA); +- chip_writeb(0xA0, bios + 0x555); +- chip_writeb(*src++, dst++); +- +- /* wait for Toggle bit ready */ +- toggle_ready_jedec(bios); +- +- if ((i & 0xfff) == 0xfff) +- printf("\b\b\b\b\b\b\b\b\b\b"); +- } +- +- return 0; +-} +- +-int probe_29f040b(struct flashchip *flash) +-{ +- chipaddr bios = flash->virtual_memory; +- uint8_t id1, id2; +- +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0x2AA); +- chip_writeb(0x90, bios + 0x555); +- +- id1 = chip_readb(bios); +- id2 = chip_readb(bios + 0x01); +- +- chip_writeb(0xF0, bios); +- +- programmer_delay(10); +- +- printf_debug("%s: id1 0x%02x, id2 0x%02x\n", __FUNCTION__, id1, id2); +- if (id1 == flash->manufacture_id && id2 == flash->model_id) +- return 1; +- +- return 0; +-} +- +-int erase_29f040b(struct flashchip *flash) +-{ +- int total_size = flash->total_size * 1024; +- chipaddr bios = flash->virtual_memory; +- +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0x2AA); +- chip_writeb(0x80, bios + 0x555); +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0x2AA); +- chip_writeb(0x10, bios + 0x555); +- +- programmer_delay(10); +- toggle_ready_jedec(bios); +- +- if (check_erased_range(flash, 0, total_size)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- return 0; +-} +- +-int write_29f040b(struct flashchip *flash, uint8_t *buf) +-{ +- int i; +- int total_size = flash->total_size * 1024; +- int page_size = flash->page_size; +- chipaddr bios = flash->virtual_memory; +- +- printf("Programming page "); +- for (i = 0; i < total_size / page_size; i++) { +- /* erase the page before programming */ +- if (erase_sector_29f040b(flash, i * page_size)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- +- /* write to the sector */ +- printf("%04d at address: ", i); +- write_sector_29f040b(bios, buf + i * page_size, +- bios + i * page_size, page_size); +- printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); +- } +- printf("\n"); +- +- return 0; +-} +diff --git a/atahpt.c b/atahpt.c +new file mode 100644 +index 0000000..c87bc36 +--- /dev/null ++++ b/atahpt.c +@@ -0,0 +1,85 @@ ++/* ++ * This file is part of the flashrom project. ++ * ++ * Copyright (C) 2010 Uwe Hermann ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include "flash.h" ++ ++#define BIOS_ROM_ADDR 0x90 ++#define BIOS_ROM_DATA 0x94 ++ ++#define REG_FLASH_ACCESS 0x58 ++ ++#define PCI_VENDOR_ID_HPT 0x1103 ++ ++struct pcidev_status ata_hpt[] = { ++ {0x1103, 0x0004, NT, "Highpoint", "HPT366/368/370/370A/372/372N"}, ++ {0x1103, 0x0005, NT, "Highpoint", "HPT372A/372N"}, ++ {0x1103, 0x0006, NT, "Highpoint", "HPT302/302N"}, ++ ++ {}, ++}; ++ ++int atahpt_init(void) +{ -+ if ((addr != 0) || (blocklen != flash->total_size * 1024)) { -+ fprintf(stderr, "%s called with incorrect arguments\n", -+ __func__); -+ return -1; -+ } -+ return erase_29f040b(flash); ++ uint32_t reg32; ++ ++ get_io_perms(); ++ ++ io_base_addr = pcidev_init(PCI_VENDOR_ID_HPT, PCI_BASE_ADDRESS_4, ++ ata_hpt, programmer_param); ++ ++ /* Enable flash access. */ ++ reg32 = pci_read_long(pcidev_dev, REG_FLASH_ACCESS); ++ reg32 |= (1 << 24); ++ pci_write_long(pcidev_dev, REG_FLASH_ACCESS, reg32); ++ ++ buses_supported = CHIP_BUSTYPE_PARALLEL; ++ ++ return 0; +} + -+/* FIXME: use write_sector_jedec? */ - static int write_sector_29f040b(chipaddr bios, uint8_t *src, chipaddr dst, - unsigned int page_size) - { -@@ -84,13 +96,14 @@ int probe_29f040b(struct flashchip *flash) - - programmer_delay(10); - -- printf_debug("%s: id1 0x%02x, id2 0x%02x\n", __FUNCTION__, id1, id2); -+ printf_debug("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); - if (id1 == flash->manufacture_id && id2 == flash->model_id) - return 1; - - return 0; - } - -+/* FIXME: use erase_chip_jedec? */ - int erase_29f040b(struct flashchip *flash) - { - int total_size = flash->total_size * 1024; -@@ -123,7 +136,7 @@ int write_29f040b(struct flashchip *flash, uint8_t *buf) - printf("Programming page "); - for (i = 0; i < total_size / page_size; i++) { - /* erase the page before programming */ -- if (erase_sector_29f040b(flash, i * page_size)) { -+ if (erase_sector_29f040b(flash, i * page_size, page_size)) { - fprintf(stderr, "ERASE FAILED!\n"); - return -1; - } ++int atahpt_shutdown(void) ++{ ++ uint32_t reg32; ++ ++ /* Disable flash access again. */ ++ reg32 = pci_read_long(pcidev_dev, REG_FLASH_ACCESS); ++ reg32 &= ~(1 << 24); ++ pci_write_long(pcidev_dev, REG_FLASH_ACCESS, reg32); ++ ++ free(programmer_param); ++ pci_cleanup(pacc); ++ release_io_perms(); ++ return 0; ++} ++ ++void atahpt_chip_writeb(uint8_t val, chipaddr addr) ++{ ++ OUTL((uint32_t)addr, io_base_addr + BIOS_ROM_ADDR); ++ OUTB(val, io_base_addr + BIOS_ROM_DATA); ++} ++ ++uint8_t atahpt_chip_readb(const chipaddr addr) ++{ ++ OUTL((uint32_t)addr, io_base_addr + BIOS_ROM_ADDR); ++ return INB(io_base_addr + BIOS_ROM_DATA); ++} diff --git a/bitbang_spi.c b/bitbang_spi.c new file mode 100644 -index 0000000..8925884 +index 0000000..8d6a9a1 --- /dev/null +++ b/bitbang_spi.c -@@ -0,0 +1,164 @@ +@@ -0,0 +1,165 @@ +/* + * This file is part of the flashrom project. + * @@ -639,6 +812,7 @@ index 0000000..8925884 +#include +#include +#include "flash.h" ++#include "chipdrivers.h" +#include "spi.h" + +/* Length of half a clock period in usecs */ @@ -779,7 +953,7 @@ index 0000000..8925884 + return 0; +} diff --git a/board_enable.c b/board_enable.c -index c87e782..2de5fd7 100644 +index c87e782..0e89137 100644 --- a/board_enable.c +++ b/board_enable.c @@ -66,6 +66,35 @@ void sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask) @@ -818,7 +992,7 @@ index c87e782..2de5fd7 100644 /** * Winbond W83627HF: Raise GPIO24. * -@@ -162,25 +191,67 @@ static void w836xx_memw_enable(uint16_t port) +@@ -162,25 +191,111 @@ static void w836xx_memw_enable(uint16_t port) } /** @@ -847,11 +1021,7 @@ index c87e782..2de5fd7 100644 + enter_conf_mode_ite(port); + sio_mask(port, 0x24, 0x04, 0x04); /* Flash ROM I/F Writes Enable */ + exit_conf_mode_ite(port); - -- /* All memory cycles, not just ROM ones, go to LPC. */ -- val = pci_read_byte(dev, 0x59); -- val &= ~0x80; -- pci_write_byte(dev, 0x59, val); ++ + return 0; +} + @@ -869,6 +1039,54 @@ index c87e782..2de5fd7 100644 +static int it8705f_write_enable_2e(const char *name) +{ + return it8705f_write_enable(0x2e, name); ++} + +- /* All memory cycles, not just ROM ones, go to LPC. */ +- val = pci_read_byte(dev, 0x59); +- val &= ~0x80; +- pci_write_byte(dev, 0x59, val); ++static int pc87360_gpio_set(uint8_t gpio, int raise) ++{ ++ static const int bankbase[] = {0, 4, 8, 10, 12}; ++ int gpio_bank = gpio / 8; ++ int gpio_pin = gpio % 8; ++ uint16_t baseport; ++ uint8_t id; ++ uint8_t val; ++ ++ if (gpio_bank > 4) ++ { ++ fprintf(stderr, "PC87360: Invalid GPIO %d\n", gpio); ++ return -1; ++ } ++ ++ id = sio_read(0x2E, 0x20); ++ if (id != 0xE1) ++ { ++ fprintf(stderr, "PC87360: unexpected ID %02x\n", id); ++ return -1; ++ } ++ ++ sio_write(0x2E, 0x07, 0x07); /* select GPIO device */ ++ baseport = (sio_read(0x2E, 0x60) << 8) | sio_read(0x2E, 0x61); ++ if((baseport & 0xFFF0) == 0xFFF0 || baseport == 0) ++ { ++ fprintf (stderr, "PC87360: invalid GPIO base address %04x\n", ++ baseport); ++ return -1; ++ } ++ sio_mask (0x2E, 0x30, 0x01, 0x01); /* Enable logical device */ ++ sio_write(0x2E, 0xF0, gpio_bank*16 + gpio_pin); ++ sio_mask (0x2E, 0xF1, 0x01, 0x01); /* Make pin output */ ++ ++ val = INB(baseport + bankbase[gpio_bank]); ++ if(raise) ++ val |= 1 << gpio_pin; ++ else ++ val &= ~(1 << gpio_pin); ++ OUTB(val, baseport + bankbase[gpio_bank]); ++ ++ return 0; } /** @@ -895,7 +1113,7 @@ index c87e782..2de5fd7 100644 if ((gpio >= 12) && (gpio <= 15)) { /* GPIO12-15 -> output */ -@@ -192,126 +263,75 @@ static void vt823x_gpio_set(struct pci_dev *dev, uint8_t gpio, int raise) +@@ -192,126 +307,75 @@ static void vt823x_gpio_set(struct pci_dev *dev, uint8_t gpio, int raise) val = pci_read_byte(dev, 0xE4); val |= 0x20; pci_write_byte(dev, 0xE4, val); @@ -1054,7 +1272,7 @@ index c87e782..2de5fd7 100644 } /** -@@ -390,94 +410,126 @@ static int board_asus_p5a(const char *name) +@@ -390,94 +454,135 @@ static int board_asus_p5a(const char *name) return 0; } @@ -1165,12 +1383,12 @@ index c87e782..2de5fd7 100644 + } + break; + } ++ ++ base = pci_read_long(dev, 0x64) & 0x0000FF00; /* System control area */ ++ base += 0xC0; - OUTB(tmp, 0x4036); - OUTB(tmp, 0xEB); -+ base = pci_read_long(dev, 0x64) & 0x0000FF00; /* System control area */ -+ base += 0xC0; -+ + tmp = INB(base + gpio); + tmp &= ~0x0F; /* null lower nibble */ + tmp |= 0x04; /* gpio -> output. */ @@ -1183,20 +1401,28 @@ index c87e782..2de5fd7 100644 /** - * Suited for Acorp 6A815EPD. -+ * Suited for MSI K8N Neo4: nVidia CK804. ++ * Suited for ASUS M2NBP-VM CSM: nVidia MCP51. */ -static int board_acorp_6a815epd(const char *name) -+static int nvidia_mcp_gpio2_raise(const char *name) ++static int nvidia_mcp_gpio0_raise(const char *name) { - struct pci_dev *dev; - uint16_t port; - uint8_t val; -- ++ return nvidia_mcp_gpio_set(0x00, 1); ++} + - dev = pci_dev_find(0x8086, 0x2440); /* Intel ICH2 LPC */ - if (!dev) { - fprintf(stderr, "\nERROR: ICH2 LPC bridge not found.\n"); - return -1; - } ++/** ++ * Suited for MSI K8N Neo4: nVidia CK804. ++ * Suited for MSI K8N GM2-L: nVidia MCP51. ++ */ ++static int nvidia_mcp_gpio2_raise(const char *name) ++{ + return nvidia_mcp_gpio_set(0x02, 1); +} @@ -1232,7 +1458,7 @@ index c87e782..2de5fd7 100644 } /** -@@ -522,165 +574,345 @@ static int board_artecgroup_dbe6x(const char *name) +@@ -522,165 +627,366 @@ static int board_artecgroup_dbe6x(const char *name) } /** @@ -1254,32 +1480,24 @@ index c87e782..2de5fd7 100644 - unsigned int gpio_bit) +static int intel_piix4_gpo_set(unsigned int gpo, int raise) { ++ unsigned int gpo_byte, gpo_bit; struct pci_dev *dev; - uint16_t gpiobar; - uint32_t reg32; + uint32_t tmp, base; - -- dev = pci_dev_find(ich_vendor, ich_device); /* Intel ICHx LPC */ ++ + dev = pci_dev_find(0x8086, 0x7110); /* Intel PIIX4 ISA bridge */ - if (!dev) { -- fprintf(stderr, "\nERROR: ICHx LPC dev %4x:%4x not found.\n", -- ich_vendor, ich_device); ++ if (!dev) { + fprintf(stderr, "\nERROR: Intel PIIX4 ISA bridge not found.\n"); - return -1; - } - -- /* Use GPIOBASE register to find the I/O space for GPIO. */ -- gpiobar = pci_read_word(dev, gpiobase_reg) & gp_lvl_bitmask; ++ return -1; ++ } ++ + /* sanity check */ + if (gpo > 30) { + fprintf(stderr, "\nERROR: Intel PIIX4 has no GPO%d.\n", gpo); + return -1; + } - -- /* Set specified GPIO to high. */ -- reg32 = INL(gpiobar + gp_lvl); -- reg32 |= (1 << gpio_bit); -- OUTL(reg32, gpiobar + gp_lvl); ++ + /* these are dual function pins which are most likely in use already */ + if (((gpo >= 1) && (gpo <= 7)) || + ((gpo >= 9) && (gpo <= 21)) || (gpo == 29)) { @@ -1307,24 +1525,35 @@ index c87e782..2de5fd7 100644 + } + pci_write_long(dev, 0xB0, tmp); + } -+ + +- dev = pci_dev_find(ich_vendor, ich_device); /* Intel ICHx LPC */ + /* GPO {0,8,27,28,30} are always available. */ + + dev = pci_dev_find(0x8086, 0x7113); /* Intel PIIX4 PM */ -+ if (!dev) { + if (!dev) { +- fprintf(stderr, "\nERROR: ICHx LPC dev %4x:%4x not found.\n", +- ich_vendor, ich_device); + fprintf(stderr, "\nERROR: Intel PIIX4 PM not found.\n"); -+ return -1; -+ } -+ + return -1; + } + +- /* Use GPIOBASE register to find the I/O space for GPIO. */ +- gpiobar = pci_read_word(dev, gpiobase_reg) & gp_lvl_bitmask; + /* PM IO base */ + base = pci_read_long(dev, 0x40) & 0x0000FFC0; -+ -+ tmp = INL(base + 0x34); /* GPO register */ + +- /* Set specified GPIO to high. */ +- reg32 = INL(gpiobar + gp_lvl); +- reg32 |= (1 << gpio_bit); +- OUTL(reg32, gpiobar + gp_lvl); ++ gpo_byte = gpo >> 3; ++ gpo_bit = gpo & 7; ++ tmp = INB(base + 0x34 + gpo_byte); /* GPO register */ + if (raise) -+ tmp |= 0x01 << gpo; ++ tmp |= 0x01 << gpo_bit; + else -+ tmp |= ~(0x01 << gpo); -+ OUTL(tmp, base + 0x34); ++ tmp &= ~(0x01 << gpo_bit); ++ OUTB(tmp, base + 0x34 + gpo_byte); return 0; } @@ -1430,9 +1659,7 @@ index c87e782..2de5fd7 100644 + strapped to zero. From some mobile ich9 version on, this becomes + 6:1. The mask below catches all. */ + base = pci_read_word(dev, intel_ich_gpio_table[i].base_reg) & 0xFFC0; - -- val = INL(gpiobar + ICH7_GPIO_LVL2); /* GP_LVL2 */ -- printf_debug("\nGPIOBAR=0x%04x GP_LVL: 0x%08x\n", gpiobar, val); ++ + /* check whether the line is allowed */ + if (gpio < 32) + allowed = (intel_ich_gpio_table[i].bank0 >> gpio) & 0x01; @@ -1440,28 +1667,16 @@ index c87e782..2de5fd7 100644 + allowed = (intel_ich_gpio_table[i].bank1 >> (gpio - 32)) & 0x01; + else + allowed = (intel_ich_gpio_table[i].bank2 >> (gpio - 64)) & 0x01; - -- /* bit 2 (0x04) = 0 #TBL --> bootblock locking = 1 -- * bit 2 (0x04) = 1 #TBL --> bootblock locking = 0 -- * bit 3 (0x08) = 0 #WP --> block locking = 1 -- * bit 3 (0x08) = 1 #WP --> block locking = 0 -- * -- * To enable full block locking, you would do: -- * val &= ~ ((1 << 2) | (1 << 3)); -- */ -- val |= (1 << 2) | (1 << 3); ++ + if (!allowed) { + fprintf(stderr, "\nERROR: This Intel LPC Bridge does not allow" + " setting GPIO%02d\n", gpio); + return -1; + } - -- OUTL(val, gpiobar + ICH7_GPIO_LVL2); ++ + printf("\nIntel ICH LPC Bridge: %sing GPIO%02d.\n", + raise ? "Rais" : "Dropp", gpio); - -- return 0; --} ++ + if (gpio < 32) { + /* Set line to GPIO */ + tmp = INL(base); @@ -1484,21 +1699,14 @@ index c87e782..2de5fd7 100644 + return -1; + } + } - --/** -- * Suited for: -- * - Biostar P4M80-M4: VIA P4M800 + VT8237 + IT8705AF -- * - GIGABYTE GA-7VT600: VIA KT600 + VT8237 + IT8705 -- */ --static int it8705_rom_write_enable(const char *name) --{ -- /* enter IT87xx conf mode */ -- enter_conf_mode_ite(0x2e); ++ + /* Set GPIO to OUTPUT */ + tmp = INL(base + 0x04); + tmp &= ~(1 << gpio); + OUTL(tmp, base + 0x04); -+ + +- val = INL(gpiobar + ICH7_GPIO_LVL2); /* GP_LVL2 */ +- printf_debug("\nGPIOBAR=0x%04x GP_LVL: 0x%08x\n", gpiobar, val); + /* Raise GPIO line */ + tmp = INL(base + 0x0C); + if (raise) @@ -1526,13 +1734,21 @@ index c87e782..2de5fd7 100644 + } + } -- /* select right flash chip */ -- sio_mask(0x2e, 0x22, 0x80, 0x80); +- /* bit 2 (0x04) = 0 #TBL --> bootblock locking = 1 +- * bit 2 (0x04) = 1 #TBL --> bootblock locking = 0 +- * bit 3 (0x08) = 0 #WP --> block locking = 1 +- * bit 3 (0x08) = 1 #WP --> block locking = 0 +- * +- * To enable full block locking, you would do: +- * val &= ~ ((1 << 2) | (1 << 3)); +- */ +- val |= (1 << 2) | (1 << 3); + /* Set GPIO to OUTPUT */ + tmp = INL(base + 0x34); + tmp &= ~(1 << gpio); + OUTL(tmp, base + 0x34); -+ + +- OUTL(val, gpiobar + ICH7_GPIO_LVL2); + /* Raise GPIO line */ + tmp = INL(base + 0x38); + if (raise) @@ -1554,18 +1770,12 @@ index c87e782..2de5fd7 100644 + "not allow setting GPIO%02d\n", gpio + 64); + return -1; + } - -- /* bit 3: flash chip write enable -- * bit 7: map flash chip at 1MB-128K (why though? ignoring this.) -- */ -- sio_mask(0x2e, 0x24, 0x04, 0x04); ++ + /* Set GPIO to OUTPUT */ + tmp = INL(base + 0x44); + tmp &= ~(1 << gpio); + OUTL(tmp, base + 0x44); - -- /* exit IT87xx conf mode */ -- exit_conf_mode_ite(0x2e); ++ + /* Raise GPIO line */ + tmp = INL(base + 0x48); + if (raise) @@ -1579,47 +1789,83 @@ index c87e782..2de5fd7 100644 } /** -- * Suited for AOpen vKM400Am-S: VIA KM400 + VT8237 + IT8705F. +- * Suited for: +- * - Biostar P4M80-M4: VIA P4M800 + VT8237 + IT8705AF +- * - GIGABYTE GA-7VT600: VIA KT600 + VT8237 + IT8705 + * Suited for Abit IP35: Intel P35 + ICH9R. ++ * Suited for Abit IP35 Pro: Intel P35 + ICH9R. */ --static int board_aopen_vkm400(const char *name) +-static int it8705_rom_write_enable(const char *name) +static int intel_ich_gpio16_raise(const char *name) { -- struct pci_dev *dev; +- /* enter IT87xx conf mode */ +- enter_conf_mode_ite(0x2e); +- +- /* select right flash chip */ +- sio_mask(0x2e, 0x22, 0x80, 0x80); +- +- /* bit 3: flash chip write enable +- * bit 7: map flash chip at 1MB-128K (why though? ignoring this.) +- */ +- sio_mask(0x2e, 0x24, 0x04, 0x04); +- +- /* exit IT87xx conf mode */ +- exit_conf_mode_ite(0x2e); + return intel_ich_gpio_set(16, 1); +} +- return 0; ++/** ++ * Suited for MSI MS-7046: LGA775 + 915P + ICH6. ++ */ ++static int intel_ich_gpio19_raise(const char *name) ++{ ++ return intel_ich_gpio_set(19, 1); + } + + /** +- * Suited for AOpen vKM400Am-S: VIA KM400 + VT8237 + IT8705F. ++ * Suited for: ++ * - Asus P4B266LM (Sony Vaio PCV-RX650): socket478 + 845D + ICH2. ++ * - Asus P4P800-E Deluxe: Intel socket478 + 865PE + ICH5R. + */ +-static int board_aopen_vkm400(const char *name) ++static int intel_ich_gpio21_raise(const char *name) + { +- struct pci_dev *dev; ++ return intel_ich_gpio_set(21, 1); ++} + - dev = pci_dev_find(0x1106, 0x3227); /* VT8237 ISA bridge */ - if (!dev) { - fprintf(stderr, "\nERROR: VT8237 ISA bridge not found.\n"); - return -1; - } +/** -+ * Suited for MSI MS-7046: LGA775 + 915P + ICH6. -+ */ -+static int intel_ich_gpio19_raise(const char *name) -+{ -+ return intel_ich_gpio_set(19, 1); -+} - -- vt823x_set_all_writes_to_lpc(dev); -+/** + * Suited for: -+ * - Asus P4B266LM (Sony Vaio PCV-RX650): socket478 + 845D + ICH2. -+ * - Asus P4P800-E Deluxe: Intel socket478 + 865PE + ICH5R. -+ */ -+static int intel_ich_gpio21_raise(const char *name) -+{ -+ return intel_ich_gpio_set(21, 1); -+} - -- return it8705_rom_write_enable(name); -+/** -+ * Suited for ASUS P4B266: socket478 + intel 845D + ICH2. ++ * - Asus P4B266: socket478 + intel 845D + ICH2. ++ * - Asus P4B-MX variant in HP Vectra VL420 SFF: socket478 + 845D + ICH2 + */ +static int intel_ich_gpio22_raise(const char *name) +{ + return intel_ich_gpio_set(22, 1); ++} + +- vt823x_set_all_writes_to_lpc(dev); ++/** ++ * Suited for HP Vectra VL400: 815 + ICH + PC87360. ++ */ + +- return it8705_rom_write_enable(name); ++static int board_hp_vl400(const char *name) ++{ ++ int ret; ++ ret = intel_ich_gpio_set(25, 1); /* Master write enable ? */ ++ if (!ret) ++ ret = pc87360_gpio_set(0x09, 1); /* #WP ? */ ++ if (!ret) ++ ret = pc87360_gpio_set(0x27, 1); /* #TBL */ ++ return ret; } /** @@ -1681,7 +1927,7 @@ index c87e782..2de5fd7 100644 } /** -@@ -715,23 +947,35 @@ static int board_soyo_sy_7vca(const char *name) +@@ -715,23 +1021,35 @@ static int board_soyo_sy_7vca(const char *name) return 0; } @@ -1731,7 +1977,7 @@ index c87e782..2de5fd7 100644 } /** -@@ -802,32 +1046,6 @@ static int board_mitac_6513wu(const char *name) +@@ -802,32 +1120,6 @@ static int board_mitac_6513wu(const char *name) } /** @@ -1764,7 +2010,19 @@ index c87e782..2de5fd7 100644 * Suited for Asus A7V8X: VIA KT400 + VT8235 + IT8703F-A */ static int board_asus_a7v8x(const char *name) -@@ -930,41 +1148,34 @@ static int board_asus_a7v600x(const char *name) +@@ -922,49 +1214,44 @@ it8712f_gpio_set(unsigned int line, int raise) + } + + /** +- * Suited for Asus A7V600-X: VIA KT600 + VT8237 + IT8712F ++ * Suited for: ++ * - Asus A7V600-X: VIA KT600 + VT8237 + IT8712F ++ * - Asus A7V8X-X: VIA KT400 + VT8235 + IT8712F + */ +-static int board_asus_a7v600x(const char *name) ++static int it8712f_gpio3_1_raise(const char *name) + { + return it8712f_gpio_set(32, 1); } /** @@ -1828,7 +2086,7 @@ index c87e782..2de5fd7 100644 * * The coreboot ids are used two fold. When running with a coreboot firmware, * the ids uniquely matches the coreboot board identification string. When a -@@ -977,195 +1188,65 @@ static int board_asus_p4p800(const char *name) +@@ -977,195 +1264,71 @@ static int board_asus_p4p800(const char *name) /* Please keep this list alphabetically ordered by vendor/board name. */ struct board_pciid_enable board_pciid_enables[] = { @@ -1883,7 +2141,7 @@ index c87e782..2de5fd7 100644 - - { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL}, /* end marker */ -}; -- + -/* Please keep this list alphabetically ordered by vendor/board. */ -const struct board_info boards_ok[] = { - /* Verified working boards that don't need write-enables. */ @@ -2006,7 +2264,7 @@ index c87e782..2de5fd7 100644 -const struct board_info laptops_ok[] = { - /* Verified working laptops. */ - { "Lenovo", "3000 V100 TF05Cxx", }, - +- - {}, -}; - @@ -2021,68 +2279,74 @@ index c87e782..2de5fd7 100644 - { "IBM/Lenovo", "240", }, - - {}, -+ /* first pci-id set [4], second pci-id set [4], dmi identifier coreboot id [2], vendor name board name max_rom_... flash enable */ -+ {0x8086, 0x2926, 0x147b, 0x1084, 0x11ab, 0x4364, 0x147b, 0x1084, NULL, NULL, NULL, "Abit", "IP35", 0, intel_ich_gpio16_raise}, -+ {0x105a, 0x0d30, 0x105a, 0x4d33, 0x8086, 0x1130, 0x8086, 0, NULL, NULL, NULL, "Acorp", "6A815EPD", 0, board_acorp_6a815epd}, -+ {0x8086, 0x24D4, 0x1849, 0x24D0, 0x8086, 0x24D5, 0x1849, 0x9739, NULL, NULL, NULL, "ASRock", "P4i65GV", 0, intel_ich_gpio23_raise}, -+ {0x1022, 0x746B, 0, 0, 0, 0, 0, 0, NULL, "AGAMI", "ARUMA", "agami", "Aruma", 0, w83627hf_gpio24_raise_2e}, -+ {0x1106, 0x3177, 0x17F2, 0x3177, 0x1106, 0x3148, 0x17F2, 0x3148, NULL, NULL, NULL, "Albatron", "PM266A", 0, w836xx_memw_enable_2e}, -+ {0x1106, 0x3205, 0x1106, 0x3205, 0x10EC, 0x8139, 0xA0A0, 0x0477, NULL, NULL, NULL, "AOpen", "vKM400Am-S", 0, it8705f_write_enable_2e}, -+ {0x1022, 0x2090, 0, 0, 0x1022, 0x2080, 0, 0, NULL, "artecgroup", "dbe61", "Artec Group", "DBE61", 0, board_artecgroup_dbe6x}, -+ {0x1022, 0x2090, 0, 0, 0x1022, 0x2080, 0, 0, NULL, "artecgroup", "dbe62", "Artec Group", "DBE62", 0, board_artecgroup_dbe6x}, -+ {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3065, 0x1043, 0x80ED, NULL, NULL, NULL, "ASUS", "A7V600-X", 0, board_asus_a7v600x}, -+ {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3177, 0x1043, 0x808C, NULL, NULL, NULL, "ASUS", "A7V8X", 0, board_asus_a7v8x}, -+ {0x1106, 0x3177, 0x1043, 0x80A1, 0x1106, 0x3205, 0x1043, 0x8118, NULL, NULL, NULL, "ASUS", "A7V8X-MX SE", 0, w836xx_memw_enable_2e}, -+ {0x1106, 0x1336, 0x1043, 0x80ed, 0x1106, 0x3288, 0x1043, 0x8249, NULL, NULL, NULL, "ASUS", "M2V-MX", 0, via_vt823x_gpio5_raise}, -+ {0x8086, 0x1a30, 0x1043, 0x8070, 0x8086, 0x244b, 0x1043, 0x8028, NULL, NULL, NULL, "ASUS", "P4B266", 0, intel_ich_gpio22_raise}, -+ {0x8086, 0x1A30, 0x1043, 0x8025, 0x8086, 0x244B, 0x104D, 0x80F0, NULL, NULL, NULL, "ASUS", "P4B266-LM", 0, intel_ich_gpio21_raise}, -+ {0x8086, 0x2570, 0x1043, 0x80F2, 0x105A, 0x3373, 0x1043, 0x80F5, NULL, NULL, NULL, "ASUS", "P4P800-E Deluxe", 0, intel_ich_gpio21_raise}, -+ {0x10B9, 0x1541, 0, 0, 0x10B9, 0x1533, 0, 0, "^P5A$", "asus", "p5a", "ASUS", "P5A", 0, board_asus_p5a}, -+ {0x10DE, 0x0030, 0x1043, 0x818a, 0x8086, 0x100E, 0x1043, 0x80EE, NULL, NULL, NULL, "ASUS", "P5ND2-SLI Deluxe", 0, nvidia_mcp_gpio10_raise}, -+ {0x1106, 0x3149, 0x1565, 0x3206, 0x1106, 0x3344, 0x1565, 0x1202, NULL, NULL, NULL, "Biostar", "P4M80-M4", 0, it8705f_write_enable_2e}, -+ {0x8086, 0x3590, 0x1028, 0x016c, 0x1000, 0x0030, 0x1028, 0x016c, NULL, NULL, NULL, "Dell", "PowerEdge 1850", 0, intel_ich_gpio23_raise}, -+ {0x1039, 0x5513, 0x1019, 0x0A41, 0x1039, 0x0018, 0, 0, NULL, NULL, NULL, "Elitegroup", "K7S6A", 0, it8705f_write_enable_2e}, -+ {0x1106, 0x3038, 0x1019, 0x0996, 0x1106, 0x3177, 0x1019, 0x0996, NULL, NULL, NULL, "Elitegroup", "K7VTA3", 256, it8705f_write_enable_2e}, -+ {0x1106, 0x3177, 0x1106, 0x3177, 0x1106, 0x3059, 0x1695, 0x3005, NULL, NULL, NULL, "EPoX", "EP-8K5A2", 0, w836xx_memw_enable_2e}, -+ {0x10EC, 0x8139, 0x1695, 0x9001, 0x11C1, 0x5811, 0x1695, 0x9015, NULL, NULL, NULL, "EPoX", "EP-8RDA3+", 0, nvidia_mcp_gpio31_raise}, -+ {0x8086, 0x7110, 0, 0, 0x8086, 0x7190, 0, 0, NULL, "epox", "ep-bx3", "EPoX", "EP-BX3", 0, board_epox_ep_bx3}, -+ {0x1106, 0x0686, 0x1106, 0x0686, 0x1106, 0x3058, 0x1458, 0xa000, NULL, NULL, NULL, "GIGABYTE", "GA-7ZM", 512, NULL}, -+ {0x1039, 0x0761, 0, 0, 0x10EC, 0x8168, 0, 0, NULL, "gigabyte", "2761gxdk", "GIGABYTE", "GA-2761GXDK", 0, it87xx_probe_spi_flash}, -+ {0x1106, 0x3227, 0x1458, 0x5001, 0x10ec, 0x8139, 0x1458, 0xe000, NULL, NULL, NULL, "GIGABYTE", "GA-7VT600", 0, it8705f_write_enable_2e}, -+ {0x10DE, 0x0050, 0x1458, 0x0C11, 0x10DE, 0x005e, 0x1458, 0x5000, NULL, NULL, NULL, "GIGABYTE", "GA-K8N-SLI", 0, nvidia_mcp_gpio21_raise}, -+ {0x10DE, 0x0360, 0x1458, 0x0C11, 0x10DE, 0x0369, 0x1458, 0x5001, NULL, "gigabyte", "m57sli", "GIGABYTE", "GA-M57SLI-S4", 0, it87xx_probe_spi_flash}, -+ {0x10de, 0x03e0, 0, 0, 0x10DE, 0x03D0, 0, 0, NULL, NULL, NULL, "GIGABYTE", "GA-M61P-S3", 0, it87xx_probe_spi_flash}, -+ {0x1002, 0x4398, 0x1458, 0x5004, 0x1002, 0x4391, 0x1458, 0xb000, NULL, NULL, NULL, "GIGABYTE", "GA-MA78G-DS3H", 0, it87xx_probe_spi_flash}, -+ {0x1002, 0x4398, 0x1458, 0x5004, 0x1002, 0x4391, 0x1458, 0xb002, NULL, NULL, NULL, "GIGABYTE", "GA-MA78GM-S2H", 0, it87xx_probe_spi_flash}, -+ {0x1002, 0x438d, 0x1458, 0x5001, 0x1002, 0x5956, 0x1002, 0x5956, NULL, NULL, NULL, "GIGABYTE", "GA-MA790FX-DQ6", 0, it87xx_probe_spi_flash}, -+ {0x1166, 0x0223, 0x103c, 0x320d, 0x102b, 0x0522, 0x103c, 0x31fa, NULL, "hp", "dl145_g3", "HP", "DL145 G3", 0, board_hp_dl145_g3_enable}, -+ {0x1166, 0x0205, 0x1014, 0x0347, 0x1002, 0x515E, 0x1014, 0x0325, NULL, NULL, NULL, "IBM", "x3455", 0, board_ibm_x3455}, -+ {0x1039, 0x5513, 0x8086, 0xd61f, 0x1039, 0x6330, 0x8086, 0xd61f, NULL, NULL, NULL, "Intel", "D201GLY", 0, wbsio_check_for_spi}, -+ {0x1022, 0x7468, 0, 0, 0, 0, 0, 0, NULL, "iwill", "dk8_htx", "IWILL", "DK8-HTX", 0, w83627hf_gpio24_raise_2e}, -+ {0x8086, 0x27A0, 0, 0, 0x8086, 0x27b8, 0, 0, NULL, "kontron", "986lcd-m", "Kontron", "986LCD-M", 0, board_kontron_986lcd_m}, -+ {0x8086, 0x2411, 0x8086, 0x2411, 0x8086, 0x7125, 0x0e11, 0xb165, NULL, NULL, NULL, "Mitac", "6513WU", 0, board_mitac_6513wu}, -+ {0x13f6, 0x0111, 0x1462, 0x5900, 0x1106, 0x3177, 0x1106, 0, NULL, NULL, NULL, "MSI", "MS-6590 (KT4 Ultra)", 0, board_msi_kt4v}, -+ {0x1106, 0x3149, 0x1462, 0x7094, 0x10ec, 0x8167, 0x1462, 0x094c, NULL, NULL, NULL, "MSI", "MS-6702E (K8T Neo2-F)", 0, w83627thf_gpio4_4_raise_2e}, -+ {0x1106, 0x0571, 0x1462, 0x7120, 0x1106, 0x3065, 0x1462, 0x7120, NULL, NULL, NULL, "MSI", "MS-6712 (KT4V)", 0, board_msi_kt4v}, -+ {0x1039, 0x7012, 0x1462, 0x0050, 0x1039, 0x6325, 0x1462, 0x0058, NULL, NULL, NULL, "MSI", "MS-7005 (651M-L)", 0, board_msi_651ml}, -+ {0x8086, 0x2658, 0x1462, 0x7046, 0x1106, 0x3044, 0x1462, 0x046d, NULL, NULL, NULL, "MSI", "MS-7046", 0, intel_ich_gpio19_raise}, -+ {0x10DE, 0x005E, 0x1462, 0x7135, 0x10DE, 0x0050, 0x1462, 0x7135, NULL, "msi", "k8n-neo3", "MSI", "MS-7135 (K8N Neo3)", 0, w83627thf_gpio4_4_raise_4e}, -+ {0x10DE, 0x005E, 0x1462, 0x7125, 0x10DE, 0x0052, 0x1462, 0x7125, NULL, NULL, NULL, "MSI", "K8N Neo4-F", 0, nvidia_mcp_gpio2_raise}, -+ {0x1106, 0x3099, 0, 0, 0x1106, 0x3074, 0, 0, NULL, "shuttle", "ak31", "Shuttle", "AK31", 0, w836xx_memw_enable_2e}, -+ {0x1106, 0x3104, 0x1297, 0xa238, 0x1106, 0x3059, 0x1297, 0xc063, NULL, NULL, NULL, "Shuttle", "AK38N", 256, it8705f_write_enable_2e}, -+ {0x10DE, 0x0050, 0x1297, 0x5036, 0x1412, 0x1724, 0x1297, 0x5036, NULL, NULL, NULL, "Shuttle", "FN25", 0, board_shuttle_fn25}, -+ {0x1106, 0x3038, 0x0925, 0x1234, 0x1106, 0x3058, 0x15DD, 0x7609, NULL, NULL, NULL, "Soyo", "SY-7VCA", 0, board_soyo_sy_7vca}, -+ {0x8086, 0x1076, 0x8086, 0x1176, 0x1106, 0x3059, 0x10f1, 0x2498, NULL, NULL, NULL, "Tyan", "S2498 (Tomcat K7M)", 0, w836xx_memw_enable_2e}, -+ {0x1106, 0x3038, 0x0925, 0x1234, 0x1106, 0x0596, 0x1106, 0, NULL, NULL, NULL, "Tekram", "P6Pro-A5", 256, NULL}, -+ {0x1106, 0x3177, 0x1106, 0xAA01, 0x1106, 0x3123, 0x1106, 0xAA01, NULL, NULL, NULL, "VIA", "EPIA M/MII/...", 0, via_vt823x_gpio15_raise}, -+ {0x1106, 0x0259, 0x1106, 0x3227, 0x1106, 0x3065, 0x1106, 0x3149, NULL, NULL, NULL, "VIA", "EPIA-N/NL", 0, via_vt823x_gpio9_raise}, -+ {0x1106, 0x5337, 0x1458, 0xb003, 0x1106, 0x287e, 0x1106, 0x337e, NULL, NULL, NULL, "VIA", "PC3500G", 0, it87xx_probe_spi_flash}, ++ /* first pci-id set [4], second pci-id set [4], dmi identifier coreboot id [2], vendor name board name max_rom_... OK? flash enable */ ++ {0x8086, 0x2926, 0x147b, 0x1084, 0x11ab, 0x4364, 0x147b, 0x1084, NULL, NULL, NULL, "Abit", "IP35", 0, OK, intel_ich_gpio16_raise}, ++ {0x8086, 0x2930, 0x147b, 0x1083, 0x10ec, 0x8167, 0x147b, 0x1083, NULL, NULL, NULL, "Abit", "IP35 Pro", 0, OK, intel_ich_gpio16_raise}, ++ {0x105a, 0x0d30, 0x105a, 0x4d33, 0x8086, 0x1130, 0x8086, 0, NULL, NULL, NULL, "Acorp", "6A815EPD", 0, OK, board_acorp_6a815epd}, ++ {0x8086, 0x24D4, 0x1849, 0x24D0, 0x8086, 0x24D5, 0x1849, 0x9739, NULL, NULL, NULL, "ASRock", "P4i65GV", 0, OK, intel_ich_gpio23_raise}, ++ {0x1022, 0x746B, 0, 0, 0, 0, 0, 0, NULL, "AGAMI", "ARUMA", "agami", "Aruma", 0, OK, w83627hf_gpio24_raise_2e}, ++ {0x1106, 0x3177, 0x17F2, 0x3177, 0x1106, 0x3148, 0x17F2, 0x3148, NULL, NULL, NULL, "Albatron", "PM266A", 0, OK, w836xx_memw_enable_2e}, ++ {0x1106, 0x3205, 0x1106, 0x3205, 0x10EC, 0x8139, 0xA0A0, 0x0477, NULL, NULL, NULL, "AOpen", "vKM400Am-S", 0, OK, it8705f_write_enable_2e}, ++ {0x1022, 0x2090, 0, 0, 0x1022, 0x2080, 0, 0, NULL, "artecgroup", "dbe61", "Artec Group", "DBE61", 0, OK, board_artecgroup_dbe6x}, ++ {0x1022, 0x2090, 0, 0, 0x1022, 0x2080, 0, 0, NULL, "artecgroup", "dbe62", "Artec Group", "DBE62", 0, OK, board_artecgroup_dbe6x}, ++ {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3065, 0x1043, 0x80ED, NULL, NULL, NULL, "ASUS", "A7V600-X", 0, OK, it8712f_gpio3_1_raise}, ++ {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3177, 0x1043, 0x808C, NULL, NULL, NULL, "ASUS", "A7V8X", 0, OK, board_asus_a7v8x}, ++ {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3177, 0x1043, 0x80A1, NULL, NULL, NULL, "ASUS", "A7V8X-X", 0, OK, it8712f_gpio3_1_raise}, ++ {0x1106, 0x3177, 0x1043, 0x80A1, 0x1106, 0x3205, 0x1043, 0x8118, NULL, NULL, NULL, "ASUS", "A7V8X-MX SE", 0, OK, w836xx_memw_enable_2e}, ++ {0x10DE, 0x0264, 0x1043, 0x81C0, 0x10DE, 0x0260, 0x1043, 0x81C0, NULL, NULL, NULL, "ASUS", "M2NBP-VM CSM", 0, OK, nvidia_mcp_gpio0_raise}, ++ {0x1106, 0x1336, 0x1043, 0x80ed, 0x1106, 0x3288, 0x1043, 0x8249, NULL, NULL, NULL, "ASUS", "M2V-MX", 0, OK, via_vt823x_gpio5_raise}, ++ {0x8086, 0x1a30, 0x1043, 0x8070, 0x8086, 0x244b, 0x1043, 0x8028, NULL, NULL, NULL, "ASUS", "P4B266", 0, OK, intel_ich_gpio22_raise}, ++ {0x8086, 0x1A30, 0x1043, 0x8025, 0x8086, 0x244B, 0x104D, 0x80F0, NULL, NULL, NULL, "ASUS", "P4B266-LM", 0, OK, intel_ich_gpio21_raise}, ++ {0x8086, 0x2570, 0x1043, 0x80F2, 0x105A, 0x3373, 0x1043, 0x80F5, NULL, NULL, NULL, "ASUS", "P4P800-E Deluxe", 0, OK, intel_ich_gpio21_raise}, ++ {0x10B9, 0x1541, 0, 0, 0x10B9, 0x1533, 0, 0, "^P5A$", "asus", "p5a", "ASUS", "P5A", 0, OK, board_asus_p5a}, ++ {0x10DE, 0x0030, 0x1043, 0x818a, 0x8086, 0x100E, 0x1043, 0x80EE, NULL, NULL, NULL, "ASUS", "P5ND2-SLI Deluxe", 0, OK, nvidia_mcp_gpio10_raise}, ++ {0x1106, 0x3149, 0x1565, 0x3206, 0x1106, 0x3344, 0x1565, 0x1202, NULL, NULL, NULL, "Biostar", "P4M80-M4", 0, OK, it8705f_write_enable_2e}, ++ {0x8086, 0x3590, 0x1028, 0x016c, 0x1000, 0x0030, 0x1028, 0x016c, NULL, NULL, NULL, "Dell", "PowerEdge 1850", 0, OK, intel_ich_gpio23_raise}, ++ {0x1039, 0x5513, 0x1019, 0x0A41, 0x1039, 0x0018, 0, 0, NULL, NULL, NULL, "Elitegroup", "K7S6A", 0, OK, it8705f_write_enable_2e}, ++ {0x1106, 0x3038, 0x1019, 0x0996, 0x1106, 0x3177, 0x1019, 0x0996, NULL, NULL, NULL, "Elitegroup", "K7VTA3", 256, OK, it8705f_write_enable_2e}, ++ {0x1106, 0x3177, 0x1106, 0x3177, 0x1106, 0x3059, 0x1695, 0x3005, NULL, NULL, NULL, "EPoX", "EP-8K5A2", 0, OK, w836xx_memw_enable_2e}, ++ {0x10EC, 0x8139, 0x1695, 0x9001, 0x11C1, 0x5811, 0x1695, 0x9015, NULL, NULL, NULL, "EPoX", "EP-8RDA3+", 0, OK, nvidia_mcp_gpio31_raise}, ++ {0x8086, 0x7110, 0, 0, 0x8086, 0x7190, 0, 0, NULL, "epox", "ep-bx3", "EPoX", "EP-BX3", 0, OK, board_epox_ep_bx3}, ++ {0x1106, 0x0686, 0x1106, 0x0686, 0x1106, 0x3058, 0x1458, 0xa000, NULL, NULL, NULL, "GIGABYTE", "GA-7ZM", 512, OK, NULL}, ++ {0x1039, 0x0761, 0, 0, 0x10EC, 0x8168, 0, 0, NULL, "gigabyte", "2761gxdk", "GIGABYTE", "GA-2761GXDK", 0, OK, it87xx_probe_spi_flash}, ++ {0x1106, 0x3227, 0x1458, 0x5001, 0x10ec, 0x8139, 0x1458, 0xe000, NULL, NULL, NULL, "GIGABYTE", "GA-7VT600", 0, OK, it8705f_write_enable_2e}, ++ {0x10DE, 0x0050, 0x1458, 0x0C11, 0x10DE, 0x005e, 0x1458, 0x5000, NULL, NULL, NULL, "GIGABYTE", "GA-K8N-SLI", 0, OK, nvidia_mcp_gpio21_raise}, ++ {0x10DE, 0x0360, 0x1458, 0x0C11, 0x10DE, 0x0369, 0x1458, 0x5001, NULL, "gigabyte", "m57sli", "GIGABYTE", "GA-M57SLI-S4", 0, OK, it87xx_probe_spi_flash}, ++ {0x10de, 0x03e0, 0, 0, 0x10DE, 0x03D0, 0, 0, NULL, NULL, NULL, "GIGABYTE", "GA-M61P-S3", 0, OK, it87xx_probe_spi_flash}, ++ {0x1002, 0x4398, 0x1458, 0x5004, 0x1002, 0x4391, 0x1458, 0xb000, NULL, NULL, NULL, "GIGABYTE", "GA-MA78G-DS3H", 0, OK, it87xx_probe_spi_flash}, ++ {0x1002, 0x4398, 0x1458, 0x5004, 0x1002, 0x4391, 0x1458, 0xb002, NULL, NULL, NULL, "GIGABYTE", "GA-MA78GM-S2H", 0, OK, it87xx_probe_spi_flash}, ++ {0x1002, 0x438d, 0x1458, 0x5001, 0x1002, 0x5956, 0x1002, 0x5956, NULL, NULL, NULL, "GIGABYTE", "GA-MA790FX-DQ6", 0, OK, it87xx_probe_spi_flash}, ++ {0x1166, 0x0223, 0x103c, 0x320d, 0x102b, 0x0522, 0x103c, 0x31fa, NULL, "hp", "dl145_g3", "HP", "DL145 G3", 0, OK, board_hp_dl145_g3_enable}, ++ {0x8086, 0x2415, 0x103c, 0x1249, 0x10b7, 0x9200, 0x103c, 0x1246, NULL, NULL, NULL, "HP", "Vectra VL400", 0, OK, board_hp_vl400}, ++ {0x8086, 0x1a30, 0x103c, 0x1a30, 0x8086, 0x2443, 0x103c, 0x2440, "^VL420$", NULL, NULL, "HP", "VL420 SFF", 0, OK, intel_ich_gpio22_raise}, ++ {0x1166, 0x0205, 0x1014, 0x0347, 0x1002, 0x515E, 0x1014, 0x0325, NULL, NULL, NULL, "IBM", "x3455", 0, OK, board_ibm_x3455}, ++ {0x1039, 0x5513, 0x8086, 0xd61f, 0x1039, 0x6330, 0x8086, 0xd61f, NULL, NULL, NULL, "Intel", "D201GLY", 0, OK, wbsio_check_for_spi}, ++ {0x1022, 0x7468, 0, 0, 0, 0, 0, 0, NULL, "iwill", "dk8_htx", "IWILL", "DK8-HTX", 0, OK, w83627hf_gpio24_raise_2e}, ++ {0x8086, 0x27A0, 0, 0, 0x8086, 0x27b8, 0, 0, NULL, "kontron", "986lcd-m", "Kontron", "986LCD-M", 0, OK, board_kontron_986lcd_m}, ++ {0x8086, 0x2411, 0x8086, 0x2411, 0x8086, 0x7125, 0x0e11, 0xb165, NULL, NULL, NULL, "Mitac", "6513WU", 0, OK, board_mitac_6513wu}, ++ {0x13f6, 0x0111, 0x1462, 0x5900, 0x1106, 0x3177, 0x1106, 0, NULL, NULL, NULL, "MSI", "MS-6590 (KT4 Ultra)", 0, OK, board_msi_kt4v}, ++ {0x1106, 0x3149, 0x1462, 0x7094, 0x10ec, 0x8167, 0x1462, 0x094c, NULL, NULL, NULL, "MSI", "MS-6702E (K8T Neo2-F)", 0, OK, w83627thf_gpio4_4_raise_2e}, ++ {0x1106, 0x0571, 0x1462, 0x7120, 0x1106, 0x3065, 0x1462, 0x7120, NULL, NULL, NULL, "MSI", "MS-6712 (KT4V)", 0, OK, board_msi_kt4v}, ++ {0x1039, 0x7012, 0x1462, 0x0050, 0x1039, 0x6325, 0x1462, 0x0058, NULL, NULL, NULL, "MSI", "MS-7005 (651M-L)", 0, OK, board_msi_651ml}, ++ {0x8086, 0x2658, 0x1462, 0x7046, 0x1106, 0x3044, 0x1462, 0x046d, NULL, NULL, NULL, "MSI", "MS-7046", 0, OK, intel_ich_gpio19_raise}, ++ {0x10DE, 0x005E, 0x1462, 0x7135, 0x10DE, 0x0050, 0x1462, 0x7135, NULL, "msi", "k8n-neo3", "MSI", "MS-7135 (K8N Neo3)", 0, OK, w83627thf_gpio4_4_raise_4e}, ++ {0x10DE, 0x0270, 0x1462, 0x7207, 0x10DE, 0x0264, 0x1462, 0x7207, NULL, NULL, NULL, "MSI", "MS-7207 (K8N GM2-L)", 0, NT, nvidia_mcp_gpio2_raise}, ++ {0x10DE, 0x005E, 0x1462, 0x7125, 0x10DE, 0x0052, 0x1462, 0x7125, NULL, NULL, NULL, "MSI", "K8N Neo4-F", 0, OK, nvidia_mcp_gpio2_raise}, ++ {0x1106, 0x3099, 0, 0, 0x1106, 0x3074, 0, 0, NULL, "shuttle", "ak31", "Shuttle", "AK31", 0, OK, w836xx_memw_enable_2e}, ++ {0x1106, 0x3104, 0x1297, 0xa238, 0x1106, 0x3059, 0x1297, 0xc063, NULL, NULL, NULL, "Shuttle", "AK38N", 256, OK, it8705f_write_enable_2e}, ++ {0x10DE, 0x0050, 0x1297, 0x5036, 0x1412, 0x1724, 0x1297, 0x5036, NULL, NULL, NULL, "Shuttle", "FN25", 0, OK, board_shuttle_fn25}, ++ {0x1106, 0x3038, 0x0925, 0x1234, 0x1106, 0x3058, 0x15DD, 0x7609, NULL, NULL, NULL, "Soyo", "SY-7VCA", 0, OK, board_soyo_sy_7vca}, ++ {0x8086, 0x1076, 0x8086, 0x1176, 0x1106, 0x3059, 0x10f1, 0x2498, NULL, NULL, NULL, "Tyan", "S2498 (Tomcat K7M)", 0, OK, w836xx_memw_enable_2e}, ++ {0x1106, 0x3038, 0x0925, 0x1234, 0x1106, 0x0596, 0x1106, 0, NULL, NULL, NULL, "Tekram", "P6Pro-A5", 256, OK, NULL}, ++ {0x1106, 0x3177, 0x1106, 0xAA01, 0x1106, 0x3123, 0x1106, 0xAA01, NULL, NULL, NULL, "VIA", "EPIA M/MII/...", 0, OK, via_vt823x_gpio15_raise}, ++ {0x1106, 0x0259, 0x1106, 0x3227, 0x1106, 0x3065, 0x1106, 0x3149, NULL, NULL, NULL, "VIA", "EPIA-N/NL", 0, OK, via_vt823x_gpio9_raise}, ++ {0x1106, 0x5337, 0x1458, 0xb003, 0x1106, 0x287e, 0x1106, 0x337e, NULL, NULL, NULL, "VIA", "PC3500G", 0, OK, it87xx_probe_spi_flash}, + -+ { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL}, /* end marker */ ++ { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 0, NT, NULL}, /* end marker */ }; /** -@@ -1230,7 +1311,8 @@ static struct board_pciid_enable *board_match_pci_card_ids(void) +@@ -1230,7 +1393,8 @@ static struct board_pciid_enable *board_match_pci_card_ids(void) struct board_pciid_enable *board = board_pciid_enables; for (; board->vendor_name; board++) { @@ -2092,7 +2356,7 @@ index c87e782..2de5fd7 100644 continue; if (!pci_card_find(board->first_vendor, board->first_device, -@@ -1252,6 +1334,18 @@ static struct board_pciid_enable *board_match_pci_card_ids(void) +@@ -1252,6 +1416,18 @@ static struct board_pciid_enable *board_match_pci_card_ids(void) } } @@ -2111,18 +2375,36 @@ index c87e782..2de5fd7 100644 return board; } -@@ -1270,14 +1364,21 @@ int board_flash_enable(const char *vendor, const char *part) +@@ -1269,15 +1445,39 @@ int board_flash_enable(const char *vendor, const char *part) + if (!board) board = board_match_pci_card_ids(); - if (board) { +- if (board) { - printf("Disabling flash write protection for board \"%s %s\"... ", - board->vendor_name, board->board_name); -- ++ if (board && board->status == NT) { ++ if (!force_boardenable) ++ { ++ printf("WARNING: Your mainboard is %s %s, but the mainboard-specific\n" ++ "code has not been tested, and thus will not not be executed by default.\n" ++ "Depending on your hardware environment, erasing, writing or even probing\n" ++ "can fail without running the board specific code.\n\n" ++ "Please see the man page (section PROGRAMMER SPECIFIC INFO, subsection\n" ++ "\"internal programmer\") for details\n", ++ board->vendor_name, board->board_name); ++ board = NULL; ++ } ++ else ++ printf("NOTE: Running an untested board enable procedure.\n" ++ "Please report success/failure to flashrom@flashrom.org\n"); ++ } + - ret = board->enable(board->vendor_name); - if (ret) - printf("FAILED!\n"); - else - printf("OK.\n"); ++ if (board) { + if (board->max_rom_decode_parallel) + max_rom_decode.parallel = + board->max_rom_decode_parallel * 1024; @@ -2143,10 +2425,10 @@ index c87e782..2de5fd7 100644 return ret; diff --git a/buspirate_spi.c b/buspirate_spi.c new file mode 100644 -index 0000000..ecdd689 +index 0000000..f1a0be1 --- /dev/null +++ b/buspirate_spi.c -@@ -0,0 +1,318 @@ +@@ -0,0 +1,319 @@ +/* + * This file is part of the flashrom project. + * @@ -2172,6 +2454,7 @@ index 0000000..ecdd689 +#include +#include +#include "flash.h" ++#include "chipdrivers.h" +#include "spi.h" + +/* Change this to #define if you want to test without a serial implementation */ @@ -2554,10 +2837,10 @@ index 9d7e758..c12354c 100644 } diff --git a/chipdrivers.h b/chipdrivers.h new file mode 100644 -index 0000000..c5062ca +index 0000000..a378803 --- /dev/null +++ b/chipdrivers.h -@@ -0,0 +1,180 @@ +@@ -0,0 +1,144 @@ +/* + * This file is part of the flashrom project. + * @@ -2620,21 +2903,6 @@ index 0000000..c5062ca +int erase_82802ab_block(struct flashchip *flash, unsigned int page, unsigned int pagesize); +int write_82802ab(struct flashchip *flash, uint8_t *buf); + -+/* am29f040b.c */ -+int probe_29f040b(struct flashchip *flash); -+int erase_29f040b(struct flashchip *flash); -+int erase_sector_29f040b(struct flashchip *flash, unsigned int blockaddr, unsigned int blocksize); -+int erase_chip_29f040b(struct flashchip *flash, unsigned int blockaddr, unsigned int blocksize); -+int write_29f040b(struct flashchip *flash, uint8_t *buf); -+ -+/* pm29f002.c */ -+int write_pm29f002(struct flashchip *flash, uint8_t *buf); -+ -+/* en29f002a.c */ -+int probe_en29f002a(struct flashchip *flash); -+int erase_en29f002a(struct flashchip *flash); -+int write_en29f002a(struct flashchip *flash, uint8_t *buf); -+ +/* jedec.c */ +uint8_t oddparity(uint8_t val); +void toggle_ready_jedec(chipaddr dst); @@ -2650,11 +2918,6 @@ index 0000000..c5062ca +int erase_chip_block_jedec(struct flashchip *flash, unsigned int page, unsigned int blocksize); +int write_sector_jedec_common(struct flashchip *flash, uint8_t *src, chipaddr dst, unsigned int page_size, unsigned int mask); + -+/* m29f002.c */ -+int erase_m29f002(struct flashchip *flash); -+int write_m29f002t(struct flashchip *flash, uint8_t *buf); -+int write_m29f002b(struct flashchip *flash, uint8_t *buf); -+ +/* m29f400bt.c */ +int probe_m29f400bt(struct flashchip *flash); +int erase_m29f400bt(struct flashchip *flash); @@ -2666,17 +2929,9 @@ index 0000000..c5062ca +void write_page_m29f400bt(chipaddr bios, uint8_t *src, + chipaddr dst, int page_size); + -+/* mx29f002.c */ -+int probe_29f002(struct flashchip *flash); -+int erase_29f002(struct flashchip *flash); -+int erase_chip_29f002(struct flashchip *flash, unsigned int addr, unsigned int blocklen); -+int erase_sector_29f002(struct flashchip *flash, unsigned int address, unsigned int blocklen); -+int write_29f002(struct flashchip *flash, uint8_t *buf); -+ +/* pm49fl00x.c */ -+int probe_49fl00x(struct flashchip *flash); -+int erase_49fl00x(struct flashchip *flash); -+int write_49fl00x(struct flashchip *flash, uint8_t *buf); ++int unlock_49fl00x(struct flashchip *flash); ++int lock_49fl00x(struct flashchip *flash); + +/* sharplhf00l04.c */ +int probe_lhf00l04(struct flashchip *flash); @@ -2690,14 +2945,6 @@ index 0000000..c5062ca +int erase_sector_28sf040(struct flashchip *flash, unsigned int address, unsigned int sector_size); +int write_28sf040(struct flashchip *flash, uint8_t *buf); + -+/* sst39sf020.c */ -+int probe_39sf020(struct flashchip *flash); -+int write_39sf020(struct flashchip *flash, uint8_t *buf); -+ -+/* sst49lf040.c */ -+int erase_49lf040(struct flashchip *flash); -+int write_49lf040(struct flashchip *flash, uint8_t *buf); -+ +/* sst49lfxxxc.c */ +int probe_49lfxxxc(struct flashchip *flash); +int erase_49lfxxxc(struct flashchip *flash); @@ -2705,6 +2952,7 @@ index 0000000..c5062ca +int erase_block_49lfxxxc(struct flashchip *flash, unsigned int address, unsigned int sector_size); +int erase_chip_49lfxxxc(struct flashchip *flash, unsigned int addr, unsigned int blocksize); +int write_49lfxxxc(struct flashchip *flash, uint8_t *buf); ++int unlock_49lfxxxc(struct flashchip *flash); + +/* sst_fwhub.c */ +int probe_sst_fwhub(struct flashchip *flash); @@ -2717,18 +2965,17 @@ index 0000000..c5062ca +int probe_w39v040c(struct flashchip *flash); +int erase_w39v040c(struct flashchip *flash); +int write_w39v040c(struct flashchip *flash, uint8_t *buf); ++int printlock_w39v040c(struct flashchip *flash); + +/* w39V080fa.c */ +int probe_winbond_fwhub(struct flashchip *flash); +int erase_winbond_fwhub(struct flashchip *flash); +int write_winbond_fwhub(struct flashchip *flash, uint8_t *buf); ++int unlock_winbond_fwhub(struct flashchip *flash); + +/* w29ee011.c */ +int probe_w29ee011(struct flashchip *flash); + -+/* w49f002u.c */ -+int write_49f002(struct flashchip *flash, uint8_t *buf); -+ +/* stm50flw0x0x.c */ +int probe_stm50flw0x0x(struct flashchip *flash); +int erase_stm50flw0x0x(struct flashchip *flash); @@ -2739,7 +2986,7 @@ index 0000000..c5062ca + +#endif /* !__CHIPDRIVERS_H__ */ diff --git a/chipset_enable.c b/chipset_enable.c -index 8dcaf0b..50e62b1 100644 +index 8dcaf0b..fc60484 100644 --- a/chipset_enable.c +++ b/chipset_enable.c @@ -4,6 +4,8 @@ @@ -2811,25 +3058,25 @@ index 8dcaf0b..50e62b1 100644 - OUTB(0x02, 0x4f); - } + uint8_t tmp; ++ ++ tmp = pci_read_byte(dev, 0xd0); ++ tmp |= 0xf8; ++ pci_write_byte(dev, 0xd0, tmp); - OUTB(0x24, 0x2e); - printf_debug("2f is %#x\n", INB(0x2f)); - b = INB(0x2f) | 0xfc; - OUTB(0x24, 0x2e); - OUTB(b, 0x2f); -+ tmp = pci_read_byte(dev, 0xd0); -+ tmp |= 0xf8; -+ pci_write_byte(dev, 0xd0, tmp); - -- OUTB(0x02, 0x2e); -- OUTB(0x02, 0x2f); + return 0; +} +- OUTB(0x02, 0x2e); +- OUTB(0x02, 0x2f); +static int enable_flash_sis_mapping(struct pci_dev *dev, const char *name) +{ + uint8_t new, newer; -+ + + /* Extended BIOS enable = 1, Lower BIOS Enable = 1 */ + /* This is 0xFFF8000~0xFFFF0000 decoding on SiS 540/630. */ + new = pci_read_byte(dev, 0x40); @@ -3277,7 +3524,201 @@ index 8dcaf0b..50e62b1 100644 old = pci_read_byte(dev, 0x6d); new = old | 0x01; -@@ -972,12 +1124,16 @@ const struct penable chipset_enables[] = { +@@ -902,18 +1054,186 @@ static int enable_flash_mcp55(struct pci_dev *dev, const char *name) + return 0; + } + ++/* This is a shot in the dark. Even if the code is totally bogus for some ++ * chipsets, users will at least start to send in reports. ++ */ ++static int enable_flash_mcp6x_7x_common(struct pci_dev *dev, const char *name) ++{ ++ int ret = 0; ++ uint8_t val; ++ uint16_t status; ++ char *busname; ++ uint32_t mcp_spibaraddr; ++ void *mcp_spibar; ++ struct pci_dev *smbusdev; ++ ++ msg_pinfo("This chipset is not really supported yet. Guesswork...\n"); ++ ++ /* dev is the ISA bridge. No idea what the stuff below does. */ ++ val = pci_read_byte(dev, 0x8a); ++ msg_pdbg("ISA/LPC bridge reg 0x8a contents: 0x%02x, bit 6 is %i, bit 5 " ++ "is %i\n", val, (val >> 6) & 0x1, (val >> 5) & 0x1); ++ switch ((val >> 5) & 0x3) { ++ case 0x0: ++ buses_supported = CHIP_BUSTYPE_LPC; ++ break; ++ case 0x2: ++ buses_supported = CHIP_BUSTYPE_SPI; ++ break; ++ default: ++ buses_supported = CHIP_BUSTYPE_UNKNOWN; ++ break; ++ } ++ busname = flashbuses_to_text(buses_supported); ++ msg_pdbg("Guessed flash bus type is %s\n", busname); ++ free(busname); ++ ++ /* Force enable SPI and disable LPC? Not a good idea. */ ++#if 0 ++ val |= (1 << 6); ++ val &= ~(1 << 5); ++ pci_write_byte(dev, 0x8a, val); ++#endif ++ ++ /* Look for the SMBus device (SMBus PCI class) */ ++ smbusdev = pci_dev_find_vendorclass(0x10de, 0x0c05); ++ if (!smbusdev) { ++ if (buses_supported & CHIP_BUSTYPE_SPI) { ++ msg_perr("ERROR: SMBus device not found. Not enabling " ++ "SPI.\n"); ++ buses_supported &= ~CHIP_BUSTYPE_SPI; ++ ret = 1; ++ } else { ++ msg_pinfo("Odd. SMBus device not found.\n"); ++ } ++ goto out_msg; ++ } ++ msg_pdbg("Found SMBus device %04x:%04x at %02x:%02x:%01x\n", ++ smbusdev->vendor_id, smbusdev->device_id, ++ smbusdev->bus, smbusdev->dev, smbusdev->func); ++ ++ /* Locate the BAR where the SPI interface lives. */ ++ mcp_spibaraddr = pci_read_long(smbusdev, 0x74); ++ msg_pdbg("SPI BAR is at 0x%08x, ", mcp_spibaraddr); ++ /* We hope this has native alignment. We know the SPI interface (well, ++ * a set of GPIOs that is connected to SPI flash) is at offset 0x530, ++ * so we expect a size of at least 0x800. Clear the lower bits. ++ * It is entirely possible that the BAR is 64k big and the low bits are ++ * reserved for an entirely different purpose. ++ */ ++ mcp_spibaraddr &= ~0x7ff; ++ msg_pdbg("after clearing low bits BAR is at 0x%08x\n", mcp_spibaraddr); ++ ++ /* Accessing a NULL pointer BAR is evil. Don't do it. */ ++ if (mcp_spibaraddr && (buses_supported == CHIP_BUSTYPE_SPI)) { ++ /* Map the BAR. Bytewise/wordwise access at 0x530 and 0x540. */ ++ mcp_spibar = physmap("MCP67 SPI", mcp_spibaraddr, 0x544); ++ ++/* Guessed. If this is correct, migrate to a separate MCP67 SPI driver. */ ++#define MCP67_SPI_CS (1 << 1) ++#define MCP67_SPI_SCK (1 << 2) ++#define MCP67_SPI_MOSI (1 << 3) ++#define MCP67_SPI_MISO (1 << 4) ++#define MCP67_SPI_ENABLE (1 << 0) ++#define MCP67_SPI_IDLE (1 << 8) ++ ++ status = mmio_readw(mcp_spibar + 0x530); ++ msg_pdbg("SPI control is 0x%04x, enable=%i, idle=%i\n", ++ status, status & 0x1, (status >> 8) & 0x1); ++ /* FIXME: Remove the physunmap once the SPI driver exists. */ ++ physunmap(mcp_spibar, 0x544); ++ } else if (!mcp_spibaraddr && (buses_supported & CHIP_BUSTYPE_SPI)) { ++ msg_pdbg("Strange. MCP SPI BAR is invalid.\n"); ++ buses_supported &= ~CHIP_BUSTYPE_SPI; ++ ret = 1; ++ } else if (mcp_spibaraddr && !(buses_supported & CHIP_BUSTYPE_SPI)) { ++ msg_pdbg("Strange. MCP SPI BAR is valid, but chipset apparently" ++ " doesn't have SPI enabled.\n"); ++ } else { ++ msg_pdbg("MCP SPI is not used.\n"); ++ } ++out_msg: ++ msg_pinfo("Please send the output of \"flashrom -V\" to " ++ "flashrom@flashrom.org to help us finish support for your " ++ "chipset. Thanks.\n"); ++ ++ return ret; ++} ++ ++/** ++ * The MCP61/MCP67 code is guesswork based on cleanroom reverse engineering. ++ * Due to that, it only reads info and doesn't change any settings. ++ * It is assumed that LPC chips need the MCP55 code and SPI chips need the ++ * code provided in enable_flash_mcp6x_7x_common. Until we know for sure, call ++ * enable_flash_mcp55 from this function only if enable_flash_mcp6x_7x_common ++ * indicates the flash chip is LPC. Warning: enable_flash_mcp55 ++ * might make SPI flash inaccessible. The same caveat applies to SPI init ++ * for LPC flash. ++ */ ++static int enable_flash_mcp67(struct pci_dev *dev, const char *name) ++{ ++ int result = 0; ++ ++ result = enable_flash_mcp6x_7x_common(dev, name); ++ if (result) ++ return result; ++ ++ /* Not sure if this is correct. No docs as usual. */ ++ switch (buses_supported) { ++ case CHIP_BUSTYPE_LPC: ++ result = enable_flash_mcp55(dev, name); ++ break; ++ case CHIP_BUSTYPE_SPI: ++ msg_pinfo("SPI on this chipset is not supported yet.\n"); ++ buses_supported = CHIP_BUSTYPE_NONE; ++ break; ++ default: ++ msg_pinfo("Something went wrong with bus type detection.\n"); ++ buses_supported = CHIP_BUSTYPE_NONE; ++ break; ++ } ++ ++ return result; ++} ++ ++static int enable_flash_mcp7x(struct pci_dev *dev, const char *name) ++{ ++ int result = 0; ++ ++ result = enable_flash_mcp6x_7x_common(dev, name); ++ if (result) ++ return result; ++ ++ /* Not sure if this is correct. No docs as usual. */ ++ switch (buses_supported) { ++ case CHIP_BUSTYPE_LPC: ++ msg_pinfo("LPC on this chipset is not supported yet.\n"); ++ break; ++ case CHIP_BUSTYPE_SPI: ++ msg_pinfo("SPI on this chipset is not supported yet.\n"); ++ buses_supported = CHIP_BUSTYPE_NONE; ++ break; ++ default: ++ msg_pinfo("Something went wrong with bus type detection.\n"); ++ buses_supported = CHIP_BUSTYPE_NONE; ++ break; ++ } ++ ++ return result; ++} ++ + static int enable_flash_ht1000(struct pci_dev *dev, const char *name) + { +- uint8_t byte; ++ uint8_t val; + + /* Set the 4MB enable bit. */ +- byte = pci_read_byte(dev, 0x41); +- byte |= 0x0e; +- pci_write_byte(dev, 0x41, byte); ++ val = pci_read_byte(dev, 0x41); ++ val |= 0x0e; ++ pci_write_byte(dev, 0x41, val); + +- byte = pci_read_byte(dev, 0x43); +- byte |= (1 << 4); +- pci_write_byte(dev, 0x43, byte); ++ val = pci_read_byte(dev, 0x43); ++ val |= (1 << 4); ++ pci_write_byte(dev, 0x43, val); + + return 0; + } +@@ -972,12 +1292,16 @@ const struct penable chipset_enables[] = { {0x1022, 0x7468, OK, "AMD", "AMD8111", enable_flash_amd8111}, {0x1078, 0x0100, OK, "AMD", "CS5530(A)", enable_flash_cs5530}, {0x1022, 0x2080, OK, "AMD", "CS5536", enable_flash_cs5536}, @@ -3294,7 +3735,7 @@ index 8dcaf0b..50e62b1 100644 {0x8086, 0x7198, OK, "Intel", "440MX", enable_flash_piix4}, {0x8086, 0x25a1, OK, "Intel", "6300ESB", enable_flash_ich_4e}, {0x8086, 0x2670, OK, "Intel", "631xESB/632xESB/3100", enable_flash_ich_dc}, -@@ -1000,6 +1156,7 @@ const struct penable chipset_enables[] = { +@@ -1000,6 +1324,7 @@ const struct penable chipset_enables[] = { {0x8086, 0x27b8, OK, "Intel", "ICH7/ICH7R", enable_flash_ich7}, {0x8086, 0x27b9, OK, "Intel", "ICH7M", enable_flash_ich7}, {0x8086, 0x27bd, OK, "Intel", "ICH7MDH", enable_flash_ich7}, @@ -3302,7 +3743,7 @@ index 8dcaf0b..50e62b1 100644 {0x8086, 0x2410, OK, "Intel", "ICH", enable_flash_ich_4e}, {0x8086, 0x2812, OK, "Intel", "ICH8DH", enable_flash_ich8}, {0x8086, 0x2814, OK, "Intel", "ICH8DO", enable_flash_ich8}, -@@ -1017,6 +1174,8 @@ const struct penable chipset_enables[] = { +@@ -1017,6 +1342,8 @@ const struct penable chipset_enables[] = { {0x8086, 0x7000, OK, "Intel", "PIIX3", enable_flash_piix4}, {0x8086, 0x7110, OK, "Intel", "PIIX4/4E/4M", enable_flash_piix4}, {0x8086, 0x122e, OK, "Intel", "PIIX", enable_flash_piix4}, @@ -3311,12 +3752,29 @@ index 8dcaf0b..50e62b1 100644 {0x10de, 0x0050, OK, "NVIDIA", "CK804", enable_flash_ck804}, /* LPC */ {0x10de, 0x0051, OK, "NVIDIA", "CK804", enable_flash_ck804}, /* Pro */ {0x10de, 0x0060, OK, "NVIDIA", "NForce2", enable_flash_nvidia_nforce2}, -@@ -1035,16 +1194,44 @@ const struct penable chipset_enables[] = { +@@ -1034,17 +1361,60 @@ const struct penable chipset_enables[] = { + {0x10de, 0x0365, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* LPC */ {0x10de, 0x0366, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* LPC */ {0x10de, 0x0367, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* Pro */ - {0x10de, 0x0548, OK, "NVIDIA", "MCP67", enable_flash_mcp55}, +- {0x10de, 0x0548, OK, "NVIDIA", "MCP67", enable_flash_mcp55}, - {0x1039, 0x0008, OK, "SiS", "SiS5595", enable_flash_sis5595}, - {0x1039, 0x0630, NT, "SiS", "SiS630", enable_flash_sis630}, ++ {0x10de, 0x03e0, NT, "NVIDIA", "MCP61", enable_flash_mcp67}, ++ {0x10de, 0x03e1, NT, "NVIDIA", "MCP61", enable_flash_mcp67}, ++ {0x10de, 0x03e2, NT, "NVIDIA", "MCP61", enable_flash_mcp67}, ++ {0x10de, 0x03e3, NT, "NVIDIA", "MCP61", enable_flash_mcp67}, ++ {0x10de, 0x0440, NT, "NVIDIA", "MCP65", enable_flash_mcp7x}, ++ {0x10de, 0x0441, NT, "NVIDIA", "MCP65", enable_flash_mcp7x}, ++ {0x10de, 0x0442, NT, "NVIDIA", "MCP65", enable_flash_mcp7x}, ++ {0x10de, 0x0443, NT, "NVIDIA", "MCP65", enable_flash_mcp7x}, ++ {0x10de, 0x0548, OK, "NVIDIA", "MCP67", enable_flash_mcp67}, ++ {0x10de, 0x075c, NT, "NVIDIA", "MCP78S", enable_flash_mcp7x}, ++ {0x10de, 0x075d, NT, "NVIDIA", "MCP78S", enable_flash_mcp7x}, ++ {0x10de, 0x07d7, NT, "NVIDIA", "MCP73", enable_flash_mcp7x}, ++ {0x10de, 0x0aac, NT, "NVIDIA", "MCP79", enable_flash_mcp7x}, ++ {0x10de, 0x0aad, NT, "NVIDIA", "MCP79", enable_flash_mcp7x}, ++ {0x10de, 0x0aae, NT, "NVIDIA", "MCP79", enable_flash_mcp7x}, ++ {0x10de, 0x0aaf, NT, "NVIDIA", "MCP79", enable_flash_mcp7x}, + {0x1039, 0x0496, NT, "SiS", "85C496+497", enable_flash_sis85c496}, + {0x1039, 0x0406, NT, "SiS", "501/5101/5501", enable_flash_sis501}, + {0x1039, 0x5511, NT, "SiS", "5511", enable_flash_sis5511}, @@ -3809,10 +4267,10 @@ index 0000000..2ced043 + diff --git a/dediprog.c b/dediprog.c new file mode 100644 -index 0000000..c6d2a30 +index 0000000..2d0d060 --- /dev/null +++ b/dediprog.c -@@ -0,0 +1,394 @@ +@@ -0,0 +1,395 @@ +/* + * This file is part of the flashrom project. + * @@ -3838,6 +4296,7 @@ index 0000000..c6d2a30 +#include +#include +#include "flash.h" ++#include "chipdrivers.h" +#include "spi.h" + +#define DEFAULT_TIMEOUT 3000 @@ -4209,10 +4668,10 @@ index 0000000..c6d2a30 +} diff --git a/dmi.c b/dmi.c new file mode 100644 -index 0000000..d165e9f +index 0000000..30a4670 --- /dev/null +++ b/dmi.c -@@ -0,0 +1,168 @@ +@@ -0,0 +1,177 @@ +/* + * This file is part of the flashrom project. + * @@ -4251,16 +4710,13 @@ index 0000000..d165e9f + +/* The short_id for baseboard starts with "m" as in mainboard to leave + "b" available for BIOS */ -+struct { -+ const char *dmidecode_name; -+ char short_id[3]; -+} dmi_properties[DMI_ID_INVALID] = { -+ {"system-manufacturer", "sm"}, -+ {"system-product-name", "sp"}, -+ {"system-version", "sv"}, -+ {"baseboard-manufacturer", "mm"}, -+ {"baseboard-product-name", "mp"}, -+ {"baseboard-version", "mv"} ++const char *dmidecode_names[DMI_ID_INVALID] = { ++ "system-manufacturer", ++ "system-product-name", ++ "system-version", ++ "baseboard-manufacturer", ++ "baseboard-product-name", ++ "baseboard-version" +}; + +#define DMI_COMMAND_LEN_MAX 260 @@ -4272,55 +4728,66 @@ index 0000000..d165e9f +/* strings longer than 4096 in DMI are just insane */ +#define DMI_MAX_ANSWER_LEN 4096 + -+void dmi_init(void) ++static char *get_dmi_string(const char *string_name) +{ + FILE *dmidecode_pipe; -+ int i; -+ char *answerbuf = malloc(DMI_MAX_ANSWER_LEN); -+ if(!answerbuf) -+ { -+ fprintf(stderr, "DMI: couldn't alloc answer buffer\n"); -+ return; ++ char *result; ++ char answerbuf[DMI_MAX_ANSWER_LEN]; ++ char commandline[DMI_COMMAND_LEN_MAX+40]; ++ snprintf(commandline, sizeof(commandline), ++ "%s -s %s", dmidecode_command, string_name); ++ dmidecode_pipe = popen(commandline, "r"); ++ if (!dmidecode_pipe) { ++ printf_debug("DMI pipe open error\n"); ++ return NULL; ++ } ++ if (!fgets(answerbuf, DMI_MAX_ANSWER_LEN, dmidecode_pipe) && ++ ferror(dmidecode_pipe)) { ++ printf_debug("DMI pipe read error\n"); ++ pclose(dmidecode_pipe); ++ return NULL; ++ } ++ /* Toss all output above DMI_MAX_ANSWER_LEN away to prevent ++ deadlock on pclose. */ ++ while (!feof(dmidecode_pipe)) ++ getc(dmidecode_pipe); ++ if (pclose(dmidecode_pipe) != 0) { ++ printf_debug("DMI pipe close error\n"); ++ return NULL; + } -+ for (i = 0; i < DMI_ID_INVALID; i++) -+ { -+ char commandline[DMI_COMMAND_LEN_MAX+40]; -+ snprintf(commandline, sizeof(commandline), -+ "%s -s %s", dmidecode_command, -+ dmi_properties[i].dmidecode_name); -+ dmidecode_pipe = popen(commandline, "r"); -+ if (!dmidecode_pipe) -+ { -+ printf_debug("DMI pipe open error\n"); -+ goto out_free; -+ } -+ if (!fgets(answerbuf, DMI_MAX_ANSWER_LEN, dmidecode_pipe) && -+ ferror(dmidecode_pipe)) -+ { -+ printf_debug("DMI pipe read error\n"); -+ pclose(dmidecode_pipe); -+ goto out_free; -+ } -+ /* Toss all output above DMI_MAX_ANSWER_LEN away to prevent -+ deadlock on pclose. */ -+ while (!feof(dmidecode_pipe)) -+ getc(dmidecode_pipe); -+ if (pclose(dmidecode_pipe) != 0) -+ { -+ printf_debug("DMI pipe close error\n"); -+ goto out_free; -+ } + -+ /* chomp trailing newline */ -+ if (answerbuf[0] != 0 && -+ answerbuf[strlen(answerbuf) - 1] == '\n') -+ answerbuf[strlen(answerbuf) - 1] = 0; -+ printf_debug("DMI string %d: \"%s\"\n", i, answerbuf); -+ dmistrings[i] = strdup(answerbuf); -+ } ++ /* chomp trailing newline */ ++ if (answerbuf[0] != 0 && ++ answerbuf[strlen(answerbuf) - 1] == '\n') ++ answerbuf[strlen(answerbuf) - 1] = 0; ++ printf_debug("DMI string %s: \"%s\"\n", string_name, answerbuf); ++ ++ result = strdup(answerbuf); ++ if (!result) ++ puts("WARNING: Out of memory - DMI support fails"); ++ ++ return result; ++} ++ ++void dmi_init(void) ++{ ++ int i; ++ char *chassis_type; + has_dmi_support = 1; -+out_free: -+ free(answerbuf); ++ for (i = 0; i < DMI_ID_INVALID; i++) { ++ dmistrings[i] = get_dmi_string(dmidecode_names[i]); ++ if (!dmistrings[i]) { ++ has_dmi_support = 0; ++ break; ++ } ++ } ++ ++ chassis_type = get_dmi_string("chassis-type"); ++ if (chassis_type && !strcmp(chassis_type, "Notebook")) { ++ printf_debug("Laptop detected via DMI"); ++ is_laptop = 1; ++ } ++ free(chassis_type); +} + +/** @@ -4377,13 +4844,14 @@ index 0000000..d165e9f + return 0; + + for (i = 0;i < DMI_ID_INVALID; i++) -+ return dmi_compare(dmistrings[i], pattern); ++ if(dmi_compare(dmistrings[i], pattern)) ++ return 1; + + return 0; +} diff --git a/drkaiser.c b/drkaiser.c new file mode 100644 -index 0000000..f13c13e +index 0000000..572fee3 --- /dev/null +++ b/drkaiser.c @@ -0,0 +1,79 @@ @@ -4418,7 +4886,7 @@ index 0000000..f13c13e +#define PCI_MAGIC_DRKAISER_VALUE 0xa971 + +struct pcidev_status drkaiser_pcidev[] = { -+ {0x1803, 0x5057, PCI_OK, "Dr. Kaiser", "PC-Waechter (Actel FPGA)"}, ++ {0x1803, 0x5057, OK, "Dr. Kaiser", "PC-Waechter (Actel FPGA)"}, + {}, +}; + @@ -4467,7 +4935,7 @@ index 0000000..f13c13e + return mmio_readb(drkaiser_bar + addr); +} diff --git a/dummyflasher.c b/dummyflasher.c -index 903f88b..0f62d16 100644 +index 903f88b..8ebd695 100644 --- a/dummyflasher.c +++ b/dummyflasher.c @@ -27,7 +27,7 @@ @@ -4479,7 +4947,14 @@ index 903f88b..0f62d16 100644 /* "all" is equivalent to specifying no type. */ if (programmer_param && (!strcmp(programmer_param, "all"))) { -@@ -43,95 +43,95 @@ int dummy_init(void) +@@ -38,100 +38,101 @@ int dummy_init(void) + programmer_param = strdup("parallel,lpc,fwh,spi"); + /* Convert the parameters to lowercase. */ + for (i = 0; programmer_param[i] != '\0'; i++) +- programmer_param[i] = (char)tolower(programmer_param[i]); ++ programmer_param[i] = ++ (char)tolower((unsigned char)programmer_param[i]); + buses_supported = CHIP_BUSTYPE_NONE; if (strstr(programmer_param, "parallel")) { buses_supported |= CHIP_BUSTYPE_PARALLEL; @@ -4597,7 +5072,7 @@ index 903f88b..0f62d16 100644 memset(buf, 0xff, len); return; } -@@ -141,18 +141,18 @@ int dummy_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -141,18 +142,18 @@ int dummy_spi_send_command(unsigned int writecnt, unsigned int readcnt, { int i; @@ -4623,30 +5098,100 @@ index 903f88b..0f62d16 100644 return 0; } diff --git a/en29f002a.c b/en29f002a.c -index b89eb31..020df32 100644 +deleted file mode 100644 +index b89eb31..0000000 --- a/en29f002a.c -+++ b/en29f002a.c -@@ -47,7 +47,7 @@ int probe_en29f512(struct flashchip *flash) - chip_writeb(0x55, bios + 0x2AA); - chip_writeb(0xF0, bios + 0x555); - ++++ /dev/null +@@ -1,125 +0,0 @@ +-/* +- * This file is part of the flashrom project. +- * +- * Copyright (C) 2007 Carl-Daniel Hailfinger +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ +- +-/* +- * EN29F512 has 1C,21 +- * EN29F010 has 1C,20 +- * EN29F040A has 1C,04 +- * EN29LV010 has 1C,6E and uses short F0 reset sequence +- * EN29LV040(A) has 1C,4F and uses short F0 reset sequence +- */ +- +-#include "flash.h" +- +-int probe_en29f512(struct flashchip *flash) +-{ +- chipaddr bios = flash->virtual_memory; +- uint8_t id1, id2; +- +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0x2AA); +- chip_writeb(0x90, bios + 0x555); +- +- programmer_delay(10); +- +- id1 = chip_readb(bios + 0x100); +- id2 = chip_readb(bios + 0x101); +- +- /* exit by writing F0 anywhere? or the code below */ +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0x2AA); +- chip_writeb(0xF0, bios + 0x555); +- - printf_debug("%s: id1 0x%02x, id2 0x%02x\n", __FUNCTION__, id1, id2); -+ printf_debug("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); - - if (id1 == flash->manufacture_id && id2 == flash->model_id) - return 1; -@@ -80,46 +80,10 @@ int probe_en29f002a(struct flashchip *flash) - chip_writeb(0x55, bios + 0xAAA); - chip_writeb(0xF0, bios + 0x555); - +- +- if (id1 == flash->manufacture_id && id2 == flash->model_id) +- return 1; +- +- return 0; +-} +- +-/* +- * EN29F002AT has 1C,92 +- * EN29F002AB has 1C,97 +- */ +- +-/* This does not seem to function properly for EN29F002NT. */ +-int probe_en29f002a(struct flashchip *flash) +-{ +- chipaddr bios = flash->virtual_memory; +- uint8_t id1, id2; +- +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0xAAA); +- chip_writeb(0x90, bios + 0x555); +- +- programmer_delay(10); +- +- id1 = chip_readb(bios + 0x100); +- id2 = chip_readb(bios + 0x101); +- +- /* exit by writing F0 anywhere? or the code below */ +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0xAAA); +- chip_writeb(0xF0, bios + 0x555); +- - printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2); -+ printf_debug("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2); - - if (id1 == flash->manufacture_id && id2 == flash->model_id) - return 1; - - return 0; - } +- +- if (id1 == flash->manufacture_id && id2 == flash->model_id) +- return 1; +- +- return 0; +-} - -/* The EN29F002 chip needs repeated single byte writing, no block writing. */ -int write_en29f002a(struct flashchip *flash, uint8_t *buf) @@ -4684,10 +5229,10 @@ index b89eb31..020df32 100644 - return 0; -} diff --git a/flash.h b/flash.h -index d3e2e30..d8f02bb 100644 +index d3e2e30..34b04e6 100644 --- a/flash.h +++ b/flash.h -@@ -24,74 +24,52 @@ +@@ -24,74 +24,55 @@ #ifndef __FLASH_H__ #define __FLASH_H__ 1 @@ -4771,6 +5316,9 @@ index d3e2e30..d8f02bb 100644 +#if SATASII_SUPPORT == 1 PROGRAMMER_SATASII, +#endif ++#if ATAHPT_SUPPORT == 1 ++ PROGRAMMER_ATAHPT, ++#endif +#if INTERNAL_SUPPORT == 1 PROGRAMMER_IT87SPI, +#endif @@ -4789,7 +5337,16 @@ index d3e2e30..d8f02bb 100644 PROGRAMMER_INVALID /* This must always be the last entry. */ }; -@@ -136,6 +114,21 @@ uint32_t chip_readl(const chipaddr addr); +@@ -121,6 +102,8 @@ struct programmer_entry { + + extern const struct programmer_entry programmer_table[]; + ++int register_shutdown(void (*function) (void *data), void *data); ++ + int programmer_init(void); + int programmer_shutdown(void); + void *programmer_map_flash_region(const char *descr, unsigned long phys_addr, +@@ -136,6 +119,21 @@ uint32_t chip_readl(const chipaddr addr); void chip_readn(uint8_t *buf, const chipaddr addr, size_t len); void programmer_delay(int usecs); @@ -4811,7 +5368,7 @@ index d3e2e30..d8f02bb 100644 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) enum chipbustype { -@@ -148,6 +141,28 @@ enum chipbustype { +@@ -148,6 +146,28 @@ enum chipbustype { CHIP_BUSTYPE_UNKNOWN = CHIP_BUSTYPE_PARALLEL | CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI, }; @@ -4840,7 +5397,7 @@ index d3e2e30..d8f02bb 100644 struct flashchip { const char *vendor; const char *name; -@@ -164,6 +179,7 @@ struct flashchip { +@@ -164,6 +184,7 @@ struct flashchip { int total_size; int page_size; @@ -4848,10 +5405,11 @@ index d3e2e30..d8f02bb 100644 /* * Indicate if flashrom has been tested with this flash chip and if -@@ -176,6 +192,19 @@ struct flashchip { +@@ -175,7 +196,21 @@ struct flashchip { + /* Delay after "enter/exit ID mode" commands in microseconds. */ int probe_timing; - int (*erase) (struct flashchip *flash); +- int (*erase) (struct flashchip *flash); + + /* + * Erase blocks and associated erase function. Any chip erase function @@ -4865,10 +5423,12 @@ index d3e2e30..d8f02bb 100644 + int (*block_erase) (struct flashchip *flash, unsigned int blockaddr, unsigned int blocklen); + } block_erasers[NUM_ERASEFUNCTIONS]; + ++ int (*printlock) (struct flashchip *flash); ++ int (*unlock) (struct flashchip *flash); int (*write) (struct flashchip *flash, uint8_t *buf); int (*read) (struct flashchip *flash, uint8_t *buf, int start, int len); -@@ -192,6 +221,7 @@ struct flashchip { +@@ -192,6 +227,7 @@ struct flashchip { #define TEST_OK_WRITE (1 << 3) #define TEST_OK_PR (TEST_OK_PROBE | TEST_OK_READ) #define TEST_OK_PRE (TEST_OK_PROBE | TEST_OK_READ | TEST_OK_ERASE) @@ -4876,7 +5436,7 @@ index d3e2e30..d8f02bb 100644 #define TEST_OK_PREW (TEST_OK_PROBE | TEST_OK_READ | TEST_OK_ERASE | TEST_OK_WRITE) #define TEST_OK_MASK 0x0f -@@ -214,6 +244,7 @@ struct flashchip { +@@ -214,6 +250,7 @@ struct flashchip { extern struct flashchip flashchips[]; @@ -4884,7 +5444,7 @@ index d3e2e30..d8f02bb 100644 struct penable { uint16_t vendor_id; uint16_t device_id; -@@ -240,6 +271,9 @@ struct board_pciid_enable { +@@ -240,6 +277,9 @@ struct board_pciid_enable { uint16_t second_card_vendor; uint16_t second_card_device; @@ -4894,15 +5454,16 @@ index d3e2e30..d8f02bb 100644 /* The vendor / part name from the coreboot table. */ const char *lb_vendor; const char *lb_part; -@@ -247,6 +281,7 @@ struct board_pciid_enable { +@@ -247,6 +287,8 @@ struct board_pciid_enable { const char *vendor_name; const char *board_name; + int max_rom_decode_parallel; ++ int status; int (*enable) (const char *name); }; -@@ -261,18 +296,20 @@ extern const struct board_info boards_ok[]; +@@ -261,18 +303,18 @@ extern const struct board_info boards_ok[]; extern const struct board_info boards_bad[]; extern const struct board_info laptops_ok[]; extern const struct board_info laptops_bad[]; @@ -4915,8 +5476,8 @@ index d3e2e30..d8f02bb 100644 +#if NEED_PCI == 1 /* pcidev.c */ - #define PCI_OK 0 - #define PCI_NT 1 /* Not tested */ +-#define PCI_OK 0 +-#define PCI_NT 1 /* Not tested */ extern uint32_t io_base_addr; extern struct pci_access *pacc; @@ -4924,7 +5485,7 @@ index d3e2e30..d8f02bb 100644 extern struct pci_dev *pcidev_dev; struct pcidev_status { uint16_t vendor_id; -@@ -281,16 +318,17 @@ struct pcidev_status { +@@ -281,16 +323,17 @@ struct pcidev_status { const char *vendor_name; const char *device_name; }; @@ -4940,7 +5501,7 @@ index d3e2e30..d8f02bb 100644 -void print_supported_chipsets(void); -void print_supported_boards(void); +void print_supported(void); -+#if (NIC3COM_SUPPORT == 1) || (GFXNVIDIA_SUPPORT == 1) || (DRKAISER_SUPPORT == 1) || (SATASII_SUPPORT == 1) ++#if (NIC3COM_SUPPORT == 1) || (GFXNVIDIA_SUPPORT == 1) || (DRKAISER_SUPPORT == 1) || (SATASII_SUPPORT == 1) || (ATAHPT_SUPPORT == 1) void print_supported_pcidevs(struct pcidev_status *devs); -void print_wiki_tables(void); +#endif @@ -4948,7 +5509,7 @@ index d3e2e30..d8f02bb 100644 /* board_enable.c */ void w836xx_ext_enter(uint16_t port); -@@ -301,39 +339,46 @@ void sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask); +@@ -301,39 +344,48 @@ void sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask); int board_flash_enable(const char *vendor, const char *part); /* chipset_enable.c */ @@ -5009,11 +5570,13 @@ index d3e2e30..d8f02bb 100644 void get_io_perms(void); void release_io_perms(void); +#if INTERNAL_SUPPORT == 1 ++extern int is_laptop; ++extern int force_boardenable; +void probe_superio(void); int internal_init(void); int internal_shutdown(void); void internal_chip_writeb(uint8_t val, chipaddr addr); -@@ -343,28 +388,29 @@ uint8_t internal_chip_readb(const chipaddr addr); +@@ -343,28 +395,29 @@ uint8_t internal_chip_readb(const chipaddr addr); uint16_t internal_chip_readw(const chipaddr addr); uint32_t internal_chip_readl(const chipaddr addr); void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len); @@ -5049,7 +5612,7 @@ index d3e2e30..d8f02bb 100644 int dummy_init(void); int dummy_shutdown(void); void *dummy_map(const char *descr, unsigned long phys_addr, size_t len); -@@ -379,20 +425,43 @@ uint32_t dummy_chip_readl(const chipaddr addr); +@@ -379,20 +432,52 @@ uint32_t dummy_chip_readl(const chipaddr addr); void dummy_chip_readn(uint8_t *buf, const chipaddr addr, size_t len); int dummy_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr); @@ -5089,11 +5652,20 @@ index d3e2e30..d8f02bb 100644 void satasii_chip_writeb(uint8_t val, chipaddr addr); uint8_t satasii_chip_readb(const chipaddr addr); extern struct pcidev_status satas_sii[]; ++#endif ++ ++/* atahpt.c */ ++#if ATAHPT_SUPPORT == 1 ++int atahpt_init(void); ++int atahpt_shutdown(void); ++void atahpt_chip_writeb(uint8_t val, chipaddr addr); ++uint8_t atahpt_chip_readb(const chipaddr addr); ++extern struct pcidev_status ata_hpt[]; +#endif /* ft2232_spi.c */ #define FTDI_FT2232H 0x6010 -@@ -402,46 +471,116 @@ int ft2232_spi_send_command(unsigned int writecnt, unsigned int readcnt, const u +@@ -402,46 +487,122 @@ int ft2232_spi_send_command(unsigned int writecnt, unsigned int readcnt, const u int ft2232_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf); @@ -5122,6 +5694,11 @@ index d3e2e30..d8f02bb 100644 +int dediprog_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); + /* flashrom.c */ ++enum write_granularity { ++ write_gran_1bit, ++ write_gran_1byte, ++ write_gran_256bytes, ++}; +extern enum chipbustype buses_supported; +struct decode_sizes { + uint32_t parallel; @@ -5148,6 +5725,7 @@ index d3e2e30..d8f02bb 100644 +char *extract_param(char **haystack, char *needle, char *delim); int check_erased_range(struct flashchip *flash, int start, int len); int verify_range(struct flashchip *flash, uint8_t *cmpbuf, int start, int len, char *message); ++int need_erase(uint8_t *have, uint8_t *want, int len, enum write_granularity gran); char *strcat_realloc(char *dest, const char *src); +void print_version(void); +int selfcheck(void); @@ -5215,7 +5793,7 @@ index d3e2e30..d8f02bb 100644 SPI_CONTROLLER_INVALID /* This must always be the last entry. */ }; extern const int spi_programmer_count; -@@ -454,7 +593,7 @@ struct spi_command { +@@ -454,7 +615,7 @@ struct spi_command { struct spi_programmer { int (*command)(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr); @@ -5224,7 +5802,7 @@ index d3e2e30..d8f02bb 100644 /* Optimized functions for this programmer */ int (*read)(struct flashchip *flash, uint8_t *buf, int start, int len); -@@ -464,56 +603,13 @@ struct spi_programmer { +@@ -464,56 +625,13 @@ struct spi_programmer { extern enum spi_controller spi_controller; extern const struct spi_programmer spi_programmer[]; extern void *spibar; @@ -5284,7 +5862,7 @@ index d3e2e30..d8f02bb 100644 /* ichspi.c */ int ich_init_opcodes(void); -@@ -521,12 +617,13 @@ int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -521,12 +639,13 @@ int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr); int ich_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); int ich_spi_write_256(struct flashchip *flash, uint8_t * buf); @@ -5299,7 +5877,7 @@ index d3e2e30..d8f02bb 100644 int it87spi_init(void); int it87xx_probe_spi_flash(const char *name); int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt, -@@ -541,96 +638,6 @@ int sb600_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); +@@ -541,96 +660,6 @@ int sb600_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); int sb600_spi_write_1(struct flashchip *flash, uint8_t *buf); extern uint8_t *sb600_spibar; @@ -5396,7 +5974,7 @@ index d3e2e30..d8f02bb 100644 /* wbsio_spi.c */ int wbsio_check_for_spi(const char *name); int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt, -@@ -638,11 +645,6 @@ int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -638,11 +667,6 @@ int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt, int wbsio_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); int wbsio_spi_write_1(struct flashchip *flash, uint8_t *buf); @@ -5408,7 +5986,7 @@ index d3e2e30..d8f02bb 100644 /* serprog.c */ int serprog_init(void); int serprog_shutdown(void); -@@ -651,4 +653,21 @@ uint8_t serprog_chip_readb(const chipaddr addr); +@@ -651,4 +675,19 @@ uint8_t serprog_chip_readb(const chipaddr addr); void serprog_chip_readn(uint8_t *buf, const chipaddr addr, size_t len); void serprog_delay(int delay); @@ -5426,12 +6004,10 @@ index d3e2e30..d8f02bb 100644 +int serialport_shutdown(void); +int serialport_write(unsigned char *buf, unsigned int writecnt); +int serialport_read(unsigned char *buf, unsigned int readcnt); -+ -+#include "chipdrivers.h" + #endif /* !__FLASH_H__ */ diff --git a/flashchips.c b/flashchips.c -index 5fd78f2..f66b95a 100644 +index 5fd78f2..24736d4 100644 --- a/flashchips.c +++ b/flashchips.c @@ -5,6 +5,7 @@ @@ -5442,19 +6018,30 @@ index 5fd78f2..f66b95a 100644 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -@@ -44,6 +45,11 @@ struct flashchip flashchips[] = { +@@ -23,6 +24,7 @@ + + #include "flash.h" + #include "flashchips.h" ++#include "chipdrivers.h" + + /** + * List of supported flash chips. +@@ -43,7 +45,13 @@ struct flashchip flashchips[] = { + * .tested = Test status * .probe = Probe function * .probe_timing = Probe function delay - * .erase = Chip erase function +- * .erase = Chip erase function + * .block_erasers[] = Array of erase layouts and erase functions + * { + * .eraseblocks[] = Array of { blocksize, blockcount } + * .block_erase = Block erase function + * } ++ * .printlock = Chip lock status function ++ * .unlock = Chip unlock function * .write = Chip write function * .read = Chip read function */ -@@ -56,11 +62,22 @@ struct flashchip flashchips[] = { +@@ -56,11 +64,21 @@ struct flashchip flashchips[] = { .model_id = AM_29F010B, /* Same as Am29F010A */ .total_size = 128, .page_size = 16 * 1024, @@ -5467,7 +6054,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_jedec, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -5482,7 +6068,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -72,11 +89,27 @@ struct flashchip flashchips[] = { +@@ -72,11 +90,26 @@ struct flashchip flashchips[] = { .model_id = AM_29F002BB, .total_size = 256, .page_size = 256, @@ -5493,7 +6079,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_en29f002a, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -5513,7 +6098,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -88,11 +121,27 @@ struct flashchip flashchips[] = { +@@ -88,11 +121,26 @@ struct flashchip flashchips[] = { .model_id = AM_29F002BT, .total_size = 256, .page_size = 256, @@ -5525,7 +6110,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_en29f002a, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -5545,7 +6129,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -102,13 +151,24 @@ struct flashchip flashchips[] = { +@@ -102,13 +150,23 @@ struct flashchip flashchips[] = { .bustype = CHIP_BUSTYPE_PARALLEL, .manufacture_id = AMD_ID, .model_id = AM_29F016D, @@ -5559,7 +6143,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (am29f040b.c) */ - .erase = erase_29f040b, - .write = write_29f040b, -+ .erase = NULL, + .block_erasers = + { + { @@ -5574,7 +6157,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -120,11 +180,22 @@ struct flashchip flashchips[] = { +@@ -120,11 +178,21 @@ struct flashchip flashchips[] = { .model_id = AM_29F040B, .total_size = 512, .page_size = 64 * 1024, @@ -5586,7 +6169,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (am29f040b.c) */ - .erase = erase_29f040b, - .write = write_29f040b, -+ .erase = NULL, + .block_erasers = + { + { @@ -5601,7 +6183,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -136,11 +207,22 @@ struct flashchip flashchips[] = { +@@ -136,11 +204,21 @@ struct flashchip flashchips[] = { .model_id = AM_29F080B, .total_size = 1024, .page_size = 64 * 1024, @@ -5612,7 +6194,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_29f040b, - .write = write_29f040b, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -5627,7 +6208,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -152,11 +234,22 @@ struct flashchip flashchips[] = { +@@ -152,11 +230,21 @@ struct flashchip flashchips[] = { .model_id = AM_29LV040B, .total_size = 512, .page_size = 64 * 1024, @@ -5638,7 +6219,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (am29f040b.c) */ - .erase = erase_29f040b, - .write = write_29f040b, -+ .erase = NULL, + .block_erasers = + { + { @@ -5653,7 +6233,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -168,11 +261,22 @@ struct flashchip flashchips[] = { +@@ -168,11 +256,21 @@ struct flashchip flashchips[] = { .model_id = AM_29LV080B, .total_size = 1024, .page_size = 64 * 1024, @@ -5664,7 +6244,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (am29f040b.c) */ - .erase = erase_29f040b, - .write = write_29f040b, -+ .erase = NULL, + .block_erasers = + { + { @@ -5679,7 +6258,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -184,10 +288,26 @@ struct flashchip flashchips[] = { +@@ -184,10 +282,25 @@ struct flashchip flashchips[] = { .model_id = ASD_AE49F2008, .total_size = 256, .page_size = 128, @@ -5688,7 +6267,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_jedec, .probe_timing = TIMING_FIXME, - .erase = erase_chip_jedec, -+ .erase = NULL, + .block_erasers = + { + { @@ -5707,12 +6285,11 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, .read = read_memmapped, }, -@@ -203,7 +323,26 @@ struct flashchip flashchips[] = { +@@ -203,7 +316,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -5735,12 +6312,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -219,7 +358,26 @@ struct flashchip flashchips[] = { +@@ -219,7 +350,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -5763,12 +6339,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -235,7 +393,26 @@ struct flashchip flashchips[] = { +@@ -235,7 +384,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -5791,12 +6366,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -251,7 +428,26 @@ struct flashchip flashchips[] = { +@@ -251,7 +418,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -5819,7 +6393,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -264,10 +460,29 @@ struct flashchip flashchips[] = { +@@ -264,10 +449,28 @@ struct flashchip flashchips[] = { .model_id = AT_25DF321, .total_size = 4096, .page_size = 256, @@ -5828,7 +6402,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -5851,12 +6424,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -283,7 +498,26 @@ struct flashchip flashchips[] = { +@@ -283,7 +486,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -5879,12 +6451,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -299,7 +533,26 @@ struct flashchip flashchips[] = { +@@ -299,7 +520,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -5907,12 +6478,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -315,7 +568,26 @@ struct flashchip flashchips[] = { +@@ -315,7 +554,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -5935,12 +6505,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -331,7 +603,26 @@ struct flashchip flashchips[] = { +@@ -331,7 +588,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -5963,12 +6532,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -347,7 +638,26 @@ struct flashchip flashchips[] = { +@@ -347,7 +622,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -5991,10 +6559,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -364,6 +674,13 @@ struct flashchip flashchips[] = { +@@ -363,7 +656,13 @@ struct flashchip flashchips[] = { + .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = NULL, +- .erase = NULL, + .block_erasers = + { + { @@ -6005,12 +6574,11 @@ index 5fd78f2..f66b95a 100644 .write = NULL /* Incompatible Page write */, .read = spi_chip_read, }, -@@ -379,7 +696,26 @@ struct flashchip flashchips[] = { +@@ -379,7 +678,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6033,12 +6601,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -395,7 +731,26 @@ struct flashchip flashchips[] = { +@@ -395,7 +712,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6061,12 +6628,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -411,7 +766,26 @@ struct flashchip flashchips[] = { +@@ -411,7 +746,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6089,12 +6655,19 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -444,7 +818,26 @@ struct flashchip flashchips[] = { +@@ -428,7 +781,6 @@ struct flashchip flashchips[] = { + .tested = TEST_UNTESTED, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = spi_chip_erase_60_c7, + .write = spi_chip_write_256, + .read = spi_chip_read, + },*/ +@@ -444,7 +796,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6117,7 +6690,7 @@ index 5fd78f2..f66b95a 100644 .write = NULL /* Incompatible Page write */, .read = spi_chip_read, }, -@@ -457,10 +850,18 @@ struct flashchip flashchips[] = { +@@ -457,10 +827,17 @@ struct flashchip flashchips[] = { .model_id = AT_29C512, .total_size = 64, .page_size = 128, @@ -6128,7 +6701,6 @@ index 5fd78f2..f66b95a 100644 + .probe = probe_jedec, .probe_timing = 10000, /* 10mS, Enter=Exec */ - .erase = erase_chip_jedec, -+ .erase = NULL, + .block_erasers = + { + { @@ -6139,7 +6711,7 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, .read = read_memmapped, -@@ -474,10 +875,18 @@ struct flashchip flashchips[] = { +@@ -474,10 +851,17 @@ struct flashchip flashchips[] = { .model_id = AT_29C010A, .total_size = 128, .page_size = 128, @@ -6149,7 +6721,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_jedec, .probe_timing = 10000, /* 10mS, Enter=Exec */ - .erase = erase_chip_jedec, -+ .erase = NULL, + .block_erasers = + { + { @@ -6160,7 +6731,7 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, /* FIXME */ .read = read_memmapped, }, -@@ -490,10 +899,18 @@ struct flashchip flashchips[] = { +@@ -490,10 +874,17 @@ struct flashchip flashchips[] = { .model_id = AT_29C020, .total_size = 256, .page_size = 256, @@ -6170,7 +6741,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_jedec, .probe_timing = 10000, /* 10ms */ - .erase = erase_chip_jedec, -+ .erase = NULL, + .block_erasers = + { + { @@ -6181,7 +6751,7 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, .read = read_memmapped, }, -@@ -506,10 +923,18 @@ struct flashchip flashchips[] = { +@@ -506,10 +897,17 @@ struct flashchip flashchips[] = { .model_id = AT_29C040A, .total_size = 512, .page_size = 256, @@ -6190,7 +6760,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_jedec, .probe_timing = 10000, /* 10 ms */ - .erase = erase_chip_jedec, -+ .erase = NULL, + .block_erasers = + { + { @@ -6201,7 +6770,79 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, .read = read_memmapped, }, -@@ -666,11 +1091,19 @@ struct flashchip flashchips[] = { +@@ -525,7 +923,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_READ, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL /* Incompatible Page write */, + .read = NULL /* Incompatible read */, + }, +@@ -541,7 +938,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_READ, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -557,7 +953,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_READ, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -573,7 +968,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_READ, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -589,7 +983,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_READ, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -605,7 +998,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_READ, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -621,7 +1013,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_READ, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL /* Incompatible read */, + }, +@@ -637,7 +1028,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_READ, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -653,7 +1043,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_READ, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -666,11 +1055,18 @@ struct flashchip flashchips[] = { .model_id = AT_49BV512, .total_size = 64, .page_size = 64, @@ -6213,7 +6854,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_49f002, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -6225,7 +6865,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -682,11 +1115,27 @@ struct flashchip flashchips[] = { +@@ -682,11 +1078,26 @@ struct flashchip flashchips[] = { .model_id = AT_49F002N, .total_size = 256, .page_size = 256, @@ -6236,7 +6876,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_49f002, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -6256,7 +6895,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -698,26 +1147,92 @@ struct flashchip flashchips[] = { +@@ -698,26 +1109,89 @@ struct flashchip flashchips[] = { .model_id = AT_49F002NT, .total_size = 256, .page_size = 256, @@ -6268,7 +6907,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_49f002, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -6301,10 +6939,8 @@ index 5fd78f2..f66b95a 100644 .page_size = 256, - .tested = TEST_OK_PREW, + .tested = TEST_OK_PRW, - .probe = probe_spi_rdid4, - .probe_timing = TIMING_ZERO, -- .erase = spi_chip_erase_c7, -+ .erase = NULL, ++ .probe = probe_spi_rdid4, ++ .probe_timing = TIMING_ZERO, + .block_erasers = + { + { @@ -6334,9 +6970,9 @@ index 5fd78f2..f66b95a 100644 + .total_size = 512, + .page_size = 256, + .tested = TEST_OK_PRW, -+ .probe = probe_spi_rdid4, -+ .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .probe = probe_spi_rdid4, + .probe_timing = TIMING_ZERO, +- .erase = spi_chip_erase_c7, + .block_erasers = + { + { @@ -6356,7 +6992,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -730,11 +1245,27 @@ struct flashchip flashchips[] = { +@@ -730,11 +1204,26 @@ struct flashchip flashchips[] = { .model_id = AMIC_A29002B, .total_size = 256, .page_size = 64 * 1024, @@ -6367,7 +7003,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (mx29f002.c) */ - .erase = erase_29f002, - .write = write_29f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -6387,7 +7022,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -746,11 +1277,27 @@ struct flashchip flashchips[] = { +@@ -746,11 +1235,26 @@ struct flashchip flashchips[] = { .model_id = AMIC_A29002T, .total_size = 256, .page_size = 64 * 1024, @@ -6399,7 +7034,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (mx29f002.c) */ - .erase = erase_29f002, - .write = write_29f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -6419,7 +7053,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -762,11 +1309,22 @@ struct flashchip flashchips[] = { +@@ -762,11 +1266,21 @@ struct flashchip flashchips[] = { .model_id = AMIC_A29040B, .total_size = 512, .page_size = 64 * 1024, @@ -6431,7 +7065,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (am29f040b.c) */ - .erase = erase_29f040b, - .write = write_29f040b, -+ .erase = NULL, + .block_erasers = + { + { @@ -6446,7 +7079,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -778,10 +1336,21 @@ struct flashchip flashchips[] = { +@@ -778,11 +1292,22 @@ struct flashchip flashchips[] = { .model_id = AMIC_A49LF040A, .total_size = 512, .page_size = 64 * 1024, @@ -6454,11 +7087,11 @@ index 5fd78f2..f66b95a 100644 - .probe = probe_49fl00x, - .probe_timing = TIMING_FIXME, /* routine is wrapper to probe_jedec (pm49fl00x.c) */ - .erase = erase_49fl00x, +- .write = write_49fl00x, + .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, + .tested = TEST_UNTESTED, + .probe = probe_jedec, + .probe_timing = TIMING_ZERO, /* routine is wrapper to probe_jedec (pm49fl00x.c) */ -+ .erase = NULL, + .block_erasers = + { + { @@ -6469,10 +7102,12 @@ index 5fd78f2..f66b95a 100644 + .block_erase = erase_chip_block_jedec, + } + }, - .write = write_49fl00x, ++ .unlock = unlock_49fl00x, ++ .write = write_jedec_1, .read = read_memmapped, }, -@@ -794,11 +1363,27 @@ struct flashchip flashchips[] = { + +@@ -794,11 +1319,26 @@ struct flashchip flashchips[] = { .model_id = EMST_F49B002UA, .total_size = 256, .page_size = 4096, @@ -6483,7 +7118,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_49f002, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -6503,12 +7137,11 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -813,7 +1398,53 @@ struct flashchip flashchips[] = { +@@ -813,7 +1353,51 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6539,7 +7172,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -6558,12 +7190,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -829,7 +1460,53 @@ struct flashchip flashchips[] = { +@@ -829,7 +1413,51 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6594,7 +7225,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -6613,12 +7243,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -845,7 +1522,55 @@ struct flashchip flashchips[] = { +@@ -845,7 +1473,53 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6650,7 +7279,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -6670,12 +7298,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -861,7 +1586,55 @@ struct flashchip flashchips[] = { +@@ -861,7 +1535,53 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6707,7 +7334,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -6727,12 +7353,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -877,7 +1650,55 @@ struct flashchip flashchips[] = { +@@ -877,7 +1597,53 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6764,7 +7389,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -6784,12 +7408,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -893,7 +1714,55 @@ struct flashchip flashchips[] = { +@@ -893,7 +1659,53 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6821,7 +7444,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -6841,12 +7463,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -909,7 +1778,55 @@ struct flashchip flashchips[] = { +@@ -909,7 +1721,53 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6878,7 +7499,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -6898,12 +7518,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -925,7 +1842,55 @@ struct flashchip flashchips[] = { +@@ -925,7 +1783,53 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6935,7 +7554,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -6955,12 +7573,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -941,7 +1906,26 @@ struct flashchip flashchips[] = { +@@ -941,7 +1845,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -6983,12 +7600,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -957,7 +1941,26 @@ struct flashchip flashchips[] = { +@@ -957,7 +1879,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7011,12 +7627,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -973,7 +1976,26 @@ struct flashchip flashchips[] = { +@@ -973,7 +1913,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7039,12 +7654,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -989,7 +2011,26 @@ struct flashchip flashchips[] = { +@@ -989,7 +1947,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7067,12 +7681,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1005,7 +2046,23 @@ struct flashchip flashchips[] = { +@@ -1005,7 +1981,22 @@ struct flashchip flashchips[] = { .tested = TEST_OK_PROBE, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7092,12 +7705,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1021,7 +2078,23 @@ struct flashchip flashchips[] = { +@@ -1021,7 +2012,22 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7117,12 +7729,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1037,7 +2110,23 @@ struct flashchip flashchips[] = { +@@ -1037,7 +2043,22 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7142,12 +7753,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1053,7 +2142,23 @@ struct flashchip flashchips[] = { +@@ -1053,12 +2074,54 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7167,7 +7777,39 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1066,11 +2171,27 @@ struct flashchip flashchips[] = { + + { ++ .vendor = "Eon", ++ .name = "EN29F010", ++ .bustype = CHIP_BUSTYPE_PARALLEL, ++ .manufacture_id = EON_ID, ++ .model_id = EN_29F010, ++ .total_size = 128, ++ .page_size = 128, ++ .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, ++ .tested = TEST_OK_PREW, ++ .probe = probe_jedec, ++ .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ ++ .block_erasers = ++ { ++ { ++ .eraseblocks = { {16 * 1024, 8} }, ++ .block_erase = erase_sector_jedec, ++ }, ++ { ++ .eraseblocks = { {128 * 1024, 1} }, ++ .block_erase = erase_chip_block_jedec, ++ }, ++ }, ++ .write = write_jedec_1, ++ .read = read_memmapped, ++ }, ++ ++ { + .vendor = "EON", + .name = "EN29F002(A)(N)B", + .bustype = CHIP_BUSTYPE_PARALLEL, +@@ -1066,11 +2129,26 @@ struct flashchip flashchips[] = { .model_id = EN_29F002B, .total_size = 256, .page_size = 256, @@ -7178,7 +7820,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_en29f002a, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -7198,7 +7839,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -1082,11 +2203,27 @@ struct flashchip flashchips[] = { +@@ -1082,11 +2160,26 @@ struct flashchip flashchips[] = { .model_id = EN_29F002T, .total_size = 256, .page_size = 256, @@ -7210,7 +7851,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_en29f002a, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -7230,7 +7870,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -1098,10 +2235,26 @@ struct flashchip flashchips[] = { +@@ -1098,10 +2191,25 @@ struct flashchip flashchips[] = { .model_id = MBM29F004BC, .total_size = 512, .page_size = 64 * 1024, @@ -7238,8 +7878,8 @@ index 5fd78f2..f66b95a 100644 .tested = TEST_UNTESTED, .probe = probe_jedec, - .probe_timing = TIMING_FIXME, +- .erase = NULL, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ - .erase = NULL, + .block_erasers = + { + { @@ -7258,7 +7898,7 @@ index 5fd78f2..f66b95a 100644 .write = NULL, .read = read_memmapped, }, -@@ -1114,15 +2267,32 @@ struct flashchip flashchips[] = { +@@ -1114,15 +2222,31 @@ struct flashchip flashchips[] = { .model_id = MBM29F004TC, .total_size = 512, .page_size = 64 * 1024, @@ -7266,8 +7906,8 @@ index 5fd78f2..f66b95a 100644 .tested = TEST_UNTESTED, .probe = probe_jedec, - .probe_timing = TIMING_FIXME, +- .erase = NULL, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ - .erase = NULL, + .block_erasers = + { + { @@ -7292,7 +7932,7 @@ index 5fd78f2..f66b95a 100644 .vendor = "Fujitsu", .name = "MBM29F400BC", .bustype = CHIP_BUSTYPE_PARALLEL, -@@ -1130,10 +2300,26 @@ struct flashchip flashchips[] = { +@@ -1130,10 +2254,25 @@ struct flashchip flashchips[] = { .model_id = MBM29F400BC, .total_size = 512, .page_size = 64 * 1024, @@ -7301,7 +7941,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_m29f400bt, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (m29f400bt.c) */ - .erase = erase_m29f400bt, -+ .erase = NULL, + .block_erasers = + { + { @@ -7320,7 +7959,7 @@ index 5fd78f2..f66b95a 100644 .write = write_coreboot_m29f400bt, .read = read_memmapped, }, -@@ -1146,10 +2332,26 @@ struct flashchip flashchips[] = { +@@ -1146,10 +2285,25 @@ struct flashchip flashchips[] = { .model_id = MBM29F400TC, .total_size = 512, .page_size = 64 * 1024, @@ -7329,7 +7968,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_m29f400bt, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (m29f400bt.c) */ - .erase = erase_m29f400bt, -+ .erase = NULL, + .block_erasers = + { + { @@ -7348,7 +7986,7 @@ index 5fd78f2..f66b95a 100644 .write = write_coreboot_m29f400bt, .read = read_memmapped, }, -@@ -1162,10 +2364,22 @@ struct flashchip flashchips[] = { +@@ -1162,10 +2316,21 @@ struct flashchip flashchips[] = { .model_id = P28F001BXB, .total_size = 128, .page_size = 128 * 1024, /* 8k + 2x4k + 112k */ @@ -7357,8 +7995,8 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_BAD_WRITE, .probe = probe_jedec, - .probe_timing = TIMING_FIXME, +- .erase = NULL, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ - .erase = NULL, + .block_erasers = + { + { @@ -7373,7 +8011,7 @@ index 5fd78f2..f66b95a 100644 .write = NULL, .read = read_memmapped, }, -@@ -1178,10 +2392,22 @@ struct flashchip flashchips[] = { +@@ -1178,26 +2343,66 @@ struct flashchip flashchips[] = { .model_id = P28F001BXT, .total_size = 128, .page_size = 128 * 1024, /* 112k + 2x4k + 8k */ @@ -7382,8 +8020,8 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_BAD_WRITE, .probe = probe_jedec, - .probe_timing = TIMING_FIXME, +- .erase = NULL, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ - .erase = NULL, + .block_erasers = + { + { @@ -7398,7 +8036,34 @@ index 5fd78f2..f66b95a 100644 .write = NULL, .read = read_memmapped, }, -@@ -1194,10 +2420,18 @@ struct flashchip flashchips[] = { + + { + .vendor = "Intel", ++ .name = "28F004S5", ++ .bustype = CHIP_BUSTYPE_PARALLEL, ++ .manufacture_id = INTEL_ID, ++ .model_id = E_28F004S5, ++ .total_size = 512, ++ .page_size = 256, ++ .tested = TEST_UNTESTED, ++ .probe = probe_82802ab, ++ .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ ++ .block_erasers = ++ { ++ { ++ .eraseblocks = { {64 * 1024, 8} }, ++ .block_erase = erase_82802ab_block, ++ }, ++ }, ++ .write = write_82802ab, ++ .read = read_memmapped, ++ }, ++ ++ { ++ .vendor = "Intel", + .name = "82802AB", + .bustype = CHIP_BUSTYPE_FWH, + .manufacture_id = INTEL_ID, .model_id = I_82802AB, .total_size = 512, .page_size = 64 * 1024, @@ -7408,7 +8073,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_82802ab, .probe_timing = TIMING_IGNORED, /* routine does not use probe_timing (82802ab.c) */ - .erase = erase_82802ab, -+ .erase = NULL, + .block_erasers = + { + { @@ -7419,7 +8083,7 @@ index 5fd78f2..f66b95a 100644 .write = write_82802ab, .read = read_memmapped, }, -@@ -1210,10 +2444,18 @@ struct flashchip flashchips[] = { +@@ -1210,10 +2415,17 @@ struct flashchip flashchips[] = { .model_id = I_82802AC, .total_size = 1024, .page_size = 64 * 1024, @@ -7429,7 +8093,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_82802ab, .probe_timing = TIMING_IGNORED, /* routine does not use probe_timing (82802ab.c) */ - .erase = erase_82802ab, -+ .erase = NULL, + .block_erasers = + { + { @@ -7440,12 +8103,11 @@ index 5fd78f2..f66b95a 100644 .write = write_82802ab, .read = read_memmapped, }, -@@ -1229,7 +2471,26 @@ struct flashchip flashchips[] = { +@@ -1229,7 +2441,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7468,12 +8130,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1245,7 +2506,23 @@ struct flashchip flashchips[] = { +@@ -1245,7 +2475,22 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7493,12 +8154,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1261,7 +2538,26 @@ struct flashchip flashchips[] = { +@@ -1261,7 +2506,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7521,7 +8181,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1274,10 +2570,29 @@ struct flashchip flashchips[] = { +@@ -1274,10 +2537,28 @@ struct flashchip flashchips[] = { .model_id = MX_25L4005, .total_size = 512, .page_size = 256, @@ -7530,7 +8190,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7553,7 +8212,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1290,10 +2605,29 @@ struct flashchip flashchips[] = { +@@ -1290,10 +2571,28 @@ struct flashchip flashchips[] = { .model_id = MX_25L8005, .total_size = 1024, .page_size = 256, @@ -7562,7 +8221,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7585,7 +8243,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1306,10 +2640,29 @@ struct flashchip flashchips[] = { +@@ -1306,10 +2605,28 @@ struct flashchip flashchips[] = { .model_id = MX_25L1605, .total_size = 2048, .page_size = 256, @@ -7594,7 +8252,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7617,12 +8274,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1325,7 +2678,23 @@ struct flashchip flashchips[] = { +@@ -1325,7 +2642,22 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7642,7 +8298,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1338,10 +2707,26 @@ struct flashchip flashchips[] = { +@@ -1338,10 +2670,25 @@ struct flashchip flashchips[] = { .model_id = MX_25L3205, .total_size = 4096, .page_size = 256, @@ -7651,7 +8307,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7671,12 +8326,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1357,7 +2742,23 @@ struct flashchip flashchips[] = { +@@ -1357,7 +2704,22 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7696,12 +8350,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1373,7 +2774,23 @@ struct flashchip flashchips[] = { +@@ -1373,7 +2735,22 @@ struct flashchip flashchips[] = { .tested = TEST_OK_PROBE, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7721,12 +8374,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1389,7 +2806,23 @@ struct flashchip flashchips[] = { +@@ -1389,7 +2766,22 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -7746,7 +8398,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1402,11 +2835,28 @@ struct flashchip flashchips[] = { +@@ -1402,11 +2794,27 @@ struct flashchip flashchips[] = { .model_id = MX_29F001B, .total_size = 128, .page_size = 32 * 1024, @@ -7757,7 +8409,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (mx29f002.c) */ - .erase = erase_29f002, - .write = write_29f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -7778,7 +8429,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -1418,11 +2868,28 @@ struct flashchip flashchips[] = { +@@ -1418,11 +2826,27 @@ struct flashchip flashchips[] = { .model_id = MX_29F001T, .total_size = 128, .page_size = 32 * 1024, @@ -7790,7 +8441,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (mx29f002.c) */ - .erase = erase_29f002, - .write = write_29f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -7811,7 +8461,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -1434,11 +2901,27 @@ struct flashchip flashchips[] = { +@@ -1434,11 +2858,26 @@ struct flashchip flashchips[] = { .model_id = MX_29F002B, .total_size = 256, .page_size = 64 * 1024, @@ -7822,7 +8472,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (mx29f002.c) */ - .erase = erase_29f002, - .write = write_29f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -7842,7 +8491,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -1450,11 +2933,27 @@ struct flashchip flashchips[] = { +@@ -1450,11 +2889,26 @@ struct flashchip flashchips[] = { .model_id = MX_29F002T, .total_size = 256, .page_size = 64 * 1024, @@ -7854,7 +8503,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (mx29f002.c) */ - .erase = erase_29f002, - .write = write_29f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -7874,7 +8522,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -1466,11 +2965,22 @@ struct flashchip flashchips[] = { +@@ -1466,11 +2920,21 @@ struct flashchip flashchips[] = { .model_id = MX_29LV040, .total_size = 512, .page_size = 64 * 1024, @@ -7886,7 +8534,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (mx29f002.c) */ - .erase = erase_29f002, - .write = write_29f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -7901,12 +8548,11 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -1485,7 +2995,20 @@ struct flashchip flashchips[] = { +@@ -1485,7 +2949,19 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_d8, -+ .erase = NULL, + .block_erasers = + { + { @@ -7923,12 +8569,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1501,7 +3024,20 @@ struct flashchip flashchips[] = { +@@ -1501,7 +2977,19 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_d8, -+ .erase = NULL, + .block_erasers = + { + { @@ -7945,7 +8590,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1512,12 +3048,25 @@ struct flashchip flashchips[] = { +@@ -1512,12 +3000,24 @@ struct flashchip flashchips[] = { .bustype = CHIP_BUSTYPE_SPI, .manufacture_id = ST_ID, .model_id = ST_M25PE40, @@ -7956,7 +8601,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_d8, -+ .erase = NULL, + .block_erasers = + { + { @@ -7973,12 +8617,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1533,7 +3082,20 @@ struct flashchip flashchips[] = { +@@ -1533,7 +3033,19 @@ struct flashchip flashchips[] = { .tested = TEST_OK_PREW, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_d8, -+ .erase = NULL, + .block_erasers = + { + { @@ -7995,12 +8638,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1549,7 +3111,20 @@ struct flashchip flashchips[] = { +@@ -1549,7 +3061,19 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_d8, -+ .erase = NULL, + .block_erasers = + { + { @@ -8017,12 +8659,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1565,7 +3140,20 @@ struct flashchip flashchips[] = { +@@ -1565,7 +3089,19 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8039,12 +8680,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1581,7 +3169,26 @@ struct flashchip flashchips[] = { +@@ -1581,7 +3117,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8067,12 +8707,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1597,7 +3204,20 @@ struct flashchip flashchips[] = { +@@ -1597,7 +3151,19 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8089,12 +8728,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1613,7 +3233,20 @@ struct flashchip flashchips[] = { +@@ -1613,7 +3179,19 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8111,12 +8749,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1629,7 +3262,26 @@ struct flashchip flashchips[] = { +@@ -1629,7 +3207,25 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8139,12 +8776,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1645,40 +3297,85 @@ struct flashchip flashchips[] = { +@@ -1645,40 +3241,82 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8180,7 +8816,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_FIXME, - .erase = erase_29f040b, - .write = write_pm29f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -8217,7 +8852,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_FIXME, - .erase = erase_29f040b, - .write = write_pm29f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -8237,7 +8871,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -1690,26 +3387,54 @@ struct flashchip flashchips[] = { +@@ -1690,47 +3328,113 @@ struct flashchip flashchips[] = { .model_id = PMC_39F010, .total_size = 128, .page_size = 4096, @@ -8249,7 +8883,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_49f002, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -8276,15 +8909,14 @@ index 5fd78f2..f66b95a 100644 .model_id = PMC_49FL002, .total_size = 256, .page_size = 16 * 1024, -- .tested = TEST_OK_PREW, ++ .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, + .tested = TEST_OK_PREW, - .probe = probe_49fl00x, - .probe_timing = TIMING_FIXME, /* routine is wrapper to probe_jedec (pm49fl00x.c) */ - .erase = erase_49fl00x, -+ .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, -+ .tested = TEST_UNTESTED, +- .write = write_49fl00x, + .probe = probe_jedec, + .probe_timing = TIMING_ZERO, /* routine is wrapper to probe_jedec (pm49fl00x.c) */ -+ .erase = NULL, /* Was: erase_49fl00x */ + .block_erasers = + { + { @@ -8298,10 +8930,11 @@ index 5fd78f2..f66b95a 100644 + .block_erase = erase_chip_block_jedec, + } + }, - .write = write_49fl00x, ++ .unlock = unlock_49fl00x, ++ .write = write_jedec_1, .read = read_memmapped, }, -@@ -1717,20 +3442,60 @@ struct flashchip flashchips[] = { + { .vendor = "PMC", .name = "Pm49FL004", @@ -8315,11 +8948,11 @@ index 5fd78f2..f66b95a 100644 - .probe = probe_49fl00x, - .probe_timing = TIMING_FIXME, /* routine is wrapper to probe_jedec (pm49fl00x.c) */ - .erase = erase_49fl00x, +- .write = write_49fl00x, + .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, + .tested = TEST_UNTESTED, + .probe = probe_jedec, + .probe_timing = TIMING_ZERO, /* routine is wrapper to probe_jedec (pm49fl00x.c) */ -+ .erase = NULL, /* Was: erase_49fl00x */ + .block_erasers = + { + { @@ -8333,7 +8966,8 @@ index 5fd78f2..f66b95a 100644 + .block_erase = erase_chip_block_jedec, + } + }, - .write = write_49fl00x, ++ .unlock = unlock_49fl00x, ++ .write = write_jedec_1, .read = read_memmapped, }, @@ -8348,7 +8982,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -8367,7 +9000,7 @@ index 5fd78f2..f66b95a 100644 .vendor = "Sharp", .name = "LHF00L04", .bustype = CHIP_BUSTYPE_FWH, /* A/A Mux */ -@@ -1738,26 +3503,78 @@ struct flashchip flashchips[] = { +@@ -1738,26 +3442,75 @@ struct flashchip flashchips[] = { .model_id = SHARP_LHF00L04, .total_size = 1024, .page_size = 64 * 1024, @@ -8378,7 +9011,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_lhf00l04, + .probe = probe_49lfxxxc, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -8409,7 +9041,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_OK_PREW, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -8437,7 +9068,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8451,7 +9081,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -1770,10 +3587,29 @@ struct flashchip flashchips[] = { +@@ -1770,10 +3523,28 @@ struct flashchip flashchips[] = { .model_id = SST_25VF016B, .total_size = 2048, .page_size = 256, @@ -8460,7 +9090,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8483,7 +9112,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_1, .read = spi_chip_read, }, -@@ -1786,42 +3622,93 @@ struct flashchip flashchips[] = { +@@ -1786,42 +3557,90 @@ struct flashchip flashchips[] = { .model_id = SST_25VF032B, .total_size = 4096, .page_size = 256, @@ -8492,7 +9121,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8532,7 +9160,6 @@ index 5fd78f2..f66b95a 100644 + .probe = probe_spi_rems, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8567,7 +9194,6 @@ index 5fd78f2..f66b95a 100644 + .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60, -+ .erase = NULL, + .block_erasers = + { + { @@ -8590,7 +9216,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_1, .read = spi_chip_read, }, -@@ -1833,11 +3720,30 @@ struct flashchip flashchips[] = { +@@ -1833,11 +3652,29 @@ struct flashchip flashchips[] = { .manufacture_id = SST_ID, .model_id = SST_25VF040B_REMS, .total_size = 512, @@ -8600,7 +9226,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rems, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8623,7 +9248,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_1, .read = spi_chip_read, }, -@@ -1850,10 +3756,29 @@ struct flashchip flashchips[] = { +@@ -1850,10 +3687,28 @@ struct flashchip flashchips[] = { .model_id = SST_25VF080B, .total_size = 1024, .page_size = 256, @@ -8632,7 +9257,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_60_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -8655,7 +9279,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_1, .read = spi_chip_read, }, -@@ -1866,10 +3791,21 @@ struct flashchip flashchips[] = { +@@ -1866,10 +3721,20 @@ struct flashchip flashchips[] = { .model_id = SST_28SF040, .total_size = 512, .page_size = 256, @@ -8664,7 +9288,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_28sf040, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (sst28sf040.c) */ - .erase = erase_28sf040, -+ .erase = NULL, + .block_erasers = + { + { @@ -8678,7 +9301,7 @@ index 5fd78f2..f66b95a 100644 .write = write_28sf040, .read = read_memmapped, }, -@@ -1882,10 +3818,18 @@ struct flashchip flashchips[] = { +@@ -1882,10 +3747,17 @@ struct flashchip flashchips[] = { .model_id = SST_29EE010, .total_size = 128, .page_size = 128, @@ -8688,7 +9311,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_jedec, .probe_timing = 10, - .erase = erase_chip_jedec, -+ .erase = NULL, + .block_erasers = + { + { @@ -8699,7 +9321,7 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, .read = read_memmapped, }, -@@ -1898,10 +3842,18 @@ struct flashchip flashchips[] = { +@@ -1898,10 +3770,17 @@ struct flashchip flashchips[] = { .model_id = SST_29LE010, .total_size = 128, .page_size = 128, @@ -8708,7 +9330,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_jedec, .probe_timing = 10, - .erase = erase_chip_jedec, -+ .erase = NULL, + .block_erasers = + { + { @@ -8719,7 +9340,7 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, .read = read_memmapped, }, -@@ -1914,10 +3866,18 @@ struct flashchip flashchips[] = { +@@ -1914,10 +3793,17 @@ struct flashchip flashchips[] = { .model_id = SST_29EE020A, .total_size = 256, .page_size = 128, @@ -8730,7 +9351,6 @@ index 5fd78f2..f66b95a 100644 - .probe_timing = TIMING_FIXME, - .erase = erase_chip_jedec, + .probe_timing = 10, -+ .erase = NULL, + .block_erasers = + { + { @@ -8741,7 +9361,7 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, .read = read_memmapped, }, -@@ -1930,27 +3890,73 @@ struct flashchip flashchips[] = { +@@ -1930,27 +3816,70 @@ struct flashchip flashchips[] = { .model_id = SST_29LE020, .total_size = 256, .page_size = 128, @@ -8750,7 +9370,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_jedec, .probe_timing = 10, - .erase = erase_chip_jedec, -+ .erase = NULL, + .block_erasers = + { + { @@ -8774,7 +9393,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_jedec, + .probe_timing = 1, /* 150 ns */ -+ .erase = NULL, + .block_erasers = + { + { @@ -8804,7 +9422,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 1, /* 150 ns */ - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -8819,7 +9436,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -1962,11 +3968,22 @@ struct flashchip flashchips[] = { +@@ -1962,11 +3891,21 @@ struct flashchip flashchips[] = { .model_id = SST_39SF020, .total_size = 256, .page_size = 4096, @@ -8830,7 +9447,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 1, /* 150 ns */ - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -8845,7 +9461,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -1978,11 +3995,22 @@ struct flashchip flashchips[] = { +@@ -1978,11 +3917,21 @@ struct flashchip flashchips[] = { .model_id = SST_39SF040, .total_size = 512, .page_size = 4096, @@ -8856,7 +9472,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 1, /* 150 ns */ - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -8871,7 +9486,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -1994,11 +4022,22 @@ struct flashchip flashchips[] = { +@@ -1994,11 +3943,21 @@ struct flashchip flashchips[] = { .model_id = SST_39VF512, .total_size = 64, .page_size = 4096, @@ -8882,7 +9497,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 1, /* 150 ns*/ - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -8897,7 +9511,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2010,11 +4049,22 @@ struct flashchip flashchips[] = { +@@ -2010,11 +3969,21 @@ struct flashchip flashchips[] = { .model_id = SST_39VF010, .total_size = 128, .page_size = 4096, @@ -8908,7 +9522,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 1, /* 150 ns */ - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -8923,7 +9536,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2026,11 +4076,22 @@ struct flashchip flashchips[] = { +@@ -2026,11 +3995,21 @@ struct flashchip flashchips[] = { .model_id = SST_39VF020, .total_size = 256, .page_size = 4096, @@ -8934,7 +9547,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 1, /* 150 ns */ - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -8949,7 +9561,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2042,11 +4103,22 @@ struct flashchip flashchips[] = { +@@ -2042,11 +4021,21 @@ struct flashchip flashchips[] = { .model_id = SST_39VF040, .total_size = 512, .page_size = 4096, @@ -8960,7 +9572,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 1, /* 150 ns */ - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -8975,7 +9586,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2058,11 +4130,25 @@ struct flashchip flashchips[] = { +@@ -2058,11 +4047,24 @@ struct flashchip flashchips[] = { .model_id = SST_39VF080, .total_size = 1024, .page_size = 4096, @@ -8985,7 +9596,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 1, /* 150 ns */ - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -9003,7 +9613,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2074,10 +4160,24 @@ struct flashchip flashchips[] = { +@@ -2074,10 +4076,23 @@ struct flashchip flashchips[] = { .model_id = SST_49LF002A, .total_size = 256, .page_size = 16 * 1024, @@ -9014,7 +9624,6 @@ index 5fd78f2..f66b95a 100644 - .probe_timing = TIMING_FIXME, /* routine is wrapper to probe_jedec (sst_fwhub.c) */ - .erase = erase_sst_fwhub, + .probe_timing = 1, /* 150 ns | routine is wrapper to probe_jedec (sst_fwhub.c) */ -+ .erase = NULL, + .block_erasers = + { + { @@ -9031,7 +9640,7 @@ index 5fd78f2..f66b95a 100644 .write = write_sst_fwhub, .read = read_memmapped, }, -@@ -2090,15 +4190,32 @@ struct flashchip flashchips[] = { +@@ -2090,15 +4105,31 @@ struct flashchip flashchips[] = { .model_id = SST_49LF003A, .total_size = 384, .page_size = 64 * 1024, @@ -9042,7 +9651,6 @@ index 5fd78f2..f66b95a 100644 - .probe_timing = TIMING_FIXME, /* routine is wrapper to probe_jedec (sst_fwhub.c) */ - .erase = erase_sst_fwhub, + .probe_timing = 1, /* 150 ns | routine is wrapper to probe_jedec (sst_fwhub.c) */ -+ .erase = NULL, + .block_erasers = + { + { @@ -9067,7 +9675,7 @@ index 5fd78f2..f66b95a 100644 .vendor = "SST", .name = "SST49LF004A/B", .bustype = CHIP_BUSTYPE_FWH, /* A/A Mux */ -@@ -2106,10 +4223,24 @@ struct flashchip flashchips[] = { +@@ -2106,10 +4137,23 @@ struct flashchip flashchips[] = { .model_id = SST_49LF004A, .total_size = 512, .page_size = 64 * 1024, @@ -9077,7 +9685,6 @@ index 5fd78f2..f66b95a 100644 - .probe_timing = TIMING_FIXME, /* routine is wrapper to probe_jedec (sst_fwhub.c) */ - .erase = erase_sst_fwhub, + .probe_timing = 1, /* 150 ns | routine is wrapper to probe_jedec (sst_fwhub.c) */ -+ .erase = NULL, + .block_erasers = + { + { @@ -9094,7 +9701,7 @@ index 5fd78f2..f66b95a 100644 .write = write_sst_fwhub, .read = read_memmapped, }, -@@ -2122,10 +4253,26 @@ struct flashchip flashchips[] = { +@@ -2122,10 +4166,25 @@ struct flashchip flashchips[] = { .model_id = SST_49LF004C, .total_size = 512, .page_size = 4 * 1024, @@ -9103,7 +9710,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_49lfxxxc, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (sst49lfxxxc.c) */ - .erase = erase_49lfxxxc, -+ .erase = NULL, + .block_erasers = + { + { @@ -9122,7 +9728,7 @@ index 5fd78f2..f66b95a 100644 .write = write_49lfxxxc, .read = read_memmapped, }, -@@ -2138,10 +4285,24 @@ struct flashchip flashchips[] = { +@@ -2138,10 +4197,23 @@ struct flashchip flashchips[] = { .model_id = SST_49LF008A, .total_size = 1024, .page_size = 64 * 1024, @@ -9133,7 +9739,6 @@ index 5fd78f2..f66b95a 100644 - .probe_timing = TIMING_FIXME, /* routine is wrapper to probe_jedec (sst_fwhub.c) */ - .erase = erase_sst_fwhub, + .probe_timing = 1, /* 150 ns | routine is wrapper to probe_jedec (sst_fwhub.c) */ -+ .erase = NULL, + .block_erasers = + { + { @@ -9150,7 +9755,7 @@ index 5fd78f2..f66b95a 100644 .write = write_sst_fwhub, .read = read_memmapped, }, -@@ -2154,10 +4315,26 @@ struct flashchip flashchips[] = { +@@ -2154,10 +4226,25 @@ struct flashchip flashchips[] = { .model_id = SST_49LF008C, .total_size = 1024, .page_size = 4 * 1024, @@ -9159,7 +9764,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_49lfxxxc, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (sst49lfxxxc.c) */ - .erase = erase_49lfxxxc, -+ .erase = NULL, + .block_erasers = + { + { @@ -9178,7 +9782,7 @@ index 5fd78f2..f66b95a 100644 .write = write_49lfxxxc, .read = read_memmapped, }, -@@ -2170,10 +4347,26 @@ struct flashchip flashchips[] = { +@@ -2170,10 +4257,25 @@ struct flashchip flashchips[] = { .model_id = SST_49LF016C, .total_size = 2048, .page_size = 4 * 1024, @@ -9188,7 +9792,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_49lfxxxc, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (sst49lfxxxc.c) */ - .erase = erase_49lfxxxc, -+ .erase = NULL, + .block_erasers = + { + { @@ -9207,7 +9810,7 @@ index 5fd78f2..f66b95a 100644 .write = write_49lfxxxc, .read = read_memmapped, }, -@@ -2186,11 +4379,25 @@ struct flashchip flashchips[] = { +@@ -2186,11 +4288,24 @@ struct flashchip flashchips[] = { .model_id = SST_49LF020, .total_size = 256, .page_size = 16 * 1024, @@ -9218,7 +9821,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 1, /* 150 ns */ - .erase = erase_49lf040, - .write = write_49lf040, -+ .erase = NULL, + .block_erasers = + { + { @@ -9236,7 +9838,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2202,11 +4409,25 @@ struct flashchip flashchips[] = { +@@ -2202,11 +4317,24 @@ struct flashchip flashchips[] = { .model_id = SST_49LF020A, .total_size = 256, .page_size = 4 * 1024, @@ -9246,7 +9848,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 1, /* 150 ns */ - .erase = erase_49lf040, - .write = write_49lf040, -+ .erase = NULL, + .block_erasers = + { + { @@ -9264,7 +9865,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2218,11 +4439,25 @@ struct flashchip flashchips[] = { +@@ -2218,11 +4346,24 @@ struct flashchip flashchips[] = { .model_id = SST_49LF040, .total_size = 512, .page_size = 4096, @@ -9275,7 +9876,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 1, /* 150 ns */ - .erase = erase_49lf040, - .write = write_49lf040, -+ .erase = NULL, + .block_erasers = + { + { @@ -9293,7 +9893,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2234,11 +4469,25 @@ struct flashchip flashchips[] = { +@@ -2234,11 +4375,24 @@ struct flashchip flashchips[] = { .model_id = SST_49LF040B, .total_size = 512, .page_size = 64 * 1024, @@ -9306,7 +9906,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_jedec, + .probe_timing = 1, /* 150ns | routine is wrapper to probe_jedec (sst_fwhub.c) */ -+ .erase = NULL, + .block_erasers = + { + { @@ -9324,7 +9923,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2250,11 +4499,25 @@ struct flashchip flashchips[] = { +@@ -2250,11 +4404,24 @@ struct flashchip flashchips[] = { .model_id = SST_49LF080A, .total_size = 1024, .page_size = 4096, @@ -9335,7 +9934,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_FIXME, - .erase = erase_49lf040, - .write = write_49lf040, -+ .erase = NULL, + .block_erasers = + { + { @@ -9353,7 +9951,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2266,10 +4529,27 @@ struct flashchip flashchips[] = { +@@ -2266,10 +4433,26 @@ struct flashchip flashchips[] = { .model_id = SST_49LF160C, .total_size = 2048, .page_size = 4 * 1024, @@ -9362,8 +9960,7 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_OK_PRW, .probe = probe_49lfxxxc, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (sst49lfxxxc.c) */ - .erase = erase_49lfxxxc, -+ .erase = NULL, +- .erase = erase_49lfxxxc, + .block_erasers = + { + { @@ -9379,15 +9976,15 @@ index 5fd78f2..f66b95a 100644 + .block_erase = erase_block_49lfxxxc, + } + }, ++ .unlock = unlock_49lfxxxc, .write = write_49lfxxxc, .read = read_memmapped, }, -@@ -2285,7 +4565,17 @@ struct flashchip flashchips[] = { +@@ -2285,7 +4468,16 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9401,12 +9998,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2306,7 +4596,17 @@ struct flashchip flashchips[] = { +@@ -2306,7 +4498,16 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_res, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9420,12 +10016,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_1, /* 128 */ .read = spi_chip_read, }, -@@ -2322,7 +4622,17 @@ struct flashchip flashchips[] = { +@@ -2322,7 +4523,16 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9439,12 +10034,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2339,7 +4649,17 @@ struct flashchip flashchips[] = { +@@ -2339,7 +4549,16 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_res, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9458,12 +10052,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_1, /* 128 */ .read = spi_chip_read, }, -@@ -2355,7 +4675,17 @@ struct flashchip flashchips[] = { +@@ -2355,7 +4574,16 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9477,7 +10070,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2368,10 +4698,20 @@ struct flashchip flashchips[] = { +@@ -2368,10 +4596,19 @@ struct flashchip flashchips[] = { .model_id = ST_M25P40, .total_size = 512, .page_size = 256, @@ -9486,7 +10079,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9500,12 +10092,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2387,7 +4727,17 @@ struct flashchip flashchips[] = { +@@ -2387,7 +4624,16 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_res, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9519,7 +10110,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2400,10 +4750,20 @@ struct flashchip flashchips[] = { +@@ -2400,10 +4646,19 @@ struct flashchip flashchips[] = { .model_id = ST_M25P80, .total_size = 1024, .page_size = 256, @@ -9528,7 +10119,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9542,7 +10132,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2416,10 +4776,20 @@ struct flashchip flashchips[] = { +@@ -2416,10 +4671,19 @@ struct flashchip flashchips[] = { .model_id = ST_M25P16, .total_size = 2048, .page_size = 256, @@ -9551,7 +10141,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9565,7 +10154,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2432,10 +4802,20 @@ struct flashchip flashchips[] = { +@@ -2432,10 +4696,19 @@ struct flashchip flashchips[] = { .model_id = ST_M25P32, .total_size = 4096, .page_size = 256, @@ -9574,7 +10163,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9588,12 +10176,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2451,7 +4831,17 @@ struct flashchip flashchips[] = { +@@ -2451,7 +4724,16 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9607,12 +10194,11 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2467,7 +4857,17 @@ struct flashchip flashchips[] = { +@@ -2467,7 +4749,16 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -9626,7 +10212,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2480,11 +4880,27 @@ struct flashchip flashchips[] = { +@@ -2480,11 +4771,26 @@ struct flashchip flashchips[] = { .model_id = ST_M29F002B, .total_size = 256, .page_size = 64 * 1024, @@ -9637,7 +10223,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_m29f002, - .write = write_m29f002b, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -9657,7 +10242,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2496,11 +4912,27 @@ struct flashchip flashchips[] = { +@@ -2496,11 +4802,26 @@ struct flashchip flashchips[] = { .model_id = ST_M29F002T, .total_size = 256, .page_size = 64 * 1024, @@ -9669,7 +10254,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_m29f002, - .write = write_m29f002t, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -9689,7 +10273,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2512,15 +4944,27 @@ struct flashchip flashchips[] = { +@@ -2512,15 +4833,26 @@ struct flashchip flashchips[] = { .model_id = ST_M29F040B, .total_size = 512, .page_size = 64 * 1024, @@ -9701,7 +10285,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (am29f040b.c) */ - .erase = erase_29f040b, - .write = write_29f040b, -+ .erase = NULL, + .block_erasers = + { + { @@ -9721,7 +10304,7 @@ index 5fd78f2..f66b95a 100644 .vendor = "ST", .name = "M29F400BT", .bustype = CHIP_BUSTYPE_PARALLEL, -@@ -2528,10 +4972,26 @@ struct flashchip flashchips[] = { +@@ -2528,10 +4860,25 @@ struct flashchip flashchips[] = { .model_id = ST_M29F400BT, .total_size = 512, .page_size = 64 * 1024, @@ -9730,7 +10313,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_m29f400bt, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (m29f400bt.c) */ - .erase = erase_m29f400bt, -+ .erase = NULL, + .block_erasers = + { + { @@ -9749,7 +10331,7 @@ index 5fd78f2..f66b95a 100644 .write = write_coreboot_m29f400bt, .read = read_memmapped, }, -@@ -2544,11 +5004,22 @@ struct flashchip flashchips[] = { +@@ -2544,11 +4891,21 @@ struct flashchip flashchips[] = { .model_id = ST_M29W010B, .total_size = 128, .page_size = 16 * 1024, @@ -9760,7 +10342,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_jedec, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -9775,7 +10356,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2560,26 +5031,80 @@ struct flashchip flashchips[] = { +@@ -2560,26 +4917,77 @@ struct flashchip flashchips[] = { .model_id = ST_M29W040B, .total_size = 512, .page_size = 64 * 1024, @@ -9786,7 +10367,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_jedec, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -9813,7 +10393,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_OK_PREW, + .probe = probe_jedec, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -9841,7 +10420,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_stm50flw0x0x, + .probe = probe_82802ab, + .probe_timing = TIMING_FIXME, -+ .erase = NULL, + .block_erasers = + { + { @@ -9863,7 +10441,7 @@ index 5fd78f2..f66b95a 100644 .write = write_stm50flw0x0x, .read = read_memmapped, }, -@@ -2587,15 +5112,34 @@ struct flashchip flashchips[] = { +@@ -2587,15 +4995,33 @@ struct flashchip flashchips[] = { { .vendor = "ST", .name = "M50FLW040B", @@ -9880,7 +10458,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_stm50flw0x0x, + .probe = probe_82802ab, + .probe_timing = TIMING_FIXME, -+ .erase = NULL, + .block_erasers = + { + { @@ -9902,7 +10479,7 @@ index 5fd78f2..f66b95a 100644 .write = write_stm50flw0x0x, .read = read_memmapped, }, -@@ -2603,15 +5147,34 @@ struct flashchip flashchips[] = { +@@ -2603,15 +5029,33 @@ struct flashchip flashchips[] = { { .vendor = "ST", .name = "M50FLW080A", @@ -9920,7 +10497,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_82802ab, + .probe_timing = TIMING_FIXME, -+ .erase = NULL, + .block_erasers = + { + { @@ -9942,7 +10518,7 @@ index 5fd78f2..f66b95a 100644 .write = write_stm50flw0x0x, .read = read_memmapped, }, -@@ -2619,15 +5182,34 @@ struct flashchip flashchips[] = { +@@ -2619,15 +5063,33 @@ struct flashchip flashchips[] = { { .vendor = "ST", .name = "M50FLW080B", @@ -9959,7 +10535,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_stm50flw0x0x, + .probe = probe_82802ab, + .probe_timing = TIMING_FIXME, -+ .erase = NULL, + .block_erasers = + { + { @@ -9981,7 +10556,7 @@ index 5fd78f2..f66b95a 100644 .write = write_stm50flw0x0x, .read = read_memmapped, }, -@@ -2640,11 +5222,27 @@ struct flashchip flashchips[] = { +@@ -2640,11 +5102,26 @@ struct flashchip flashchips[] = { .model_id = ST_M50FW002, .total_size = 256, .page_size = 64 * 1024, @@ -9990,7 +10565,7 @@ index 5fd78f2..f66b95a 100644 - .probe = probe_49lfxxxc, + .probe = probe_82802ab, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (sst49lfxxxc.c) */ - .erase = NULL, +- .erase = NULL, - .write = NULL, + .block_erasers = + { @@ -10011,7 +10586,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2656,11 +5254,22 @@ struct flashchip flashchips[] = { +@@ -2656,11 +5133,21 @@ struct flashchip flashchips[] = { .model_id = ST_M50FW016, .total_size = 2048, .page_size = 64 * 1024, @@ -10021,7 +10596,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (82802ab.c) */ - .erase = erase_82802ab, - .write = write_82802ab, -+ .erase = NULL, + .block_erasers = + { + { @@ -10036,7 +10610,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2672,11 +5281,22 @@ struct flashchip flashchips[] = { +@@ -2672,11 +5159,21 @@ struct flashchip flashchips[] = { .model_id = ST_M50FW040, .total_size = 512, .page_size = 64 * 1024, @@ -10047,7 +10621,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (82802ab.c) */ - .erase = erase_82802ab, - .write = write_82802ab, -+ .erase = NULL, + .block_erasers = + { + { @@ -10062,7 +10635,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2688,11 +5308,22 @@ struct flashchip flashchips[] = { +@@ -2688,11 +5185,21 @@ struct flashchip flashchips[] = { .model_id = ST_M50FW080, .total_size = 1024, .page_size = 64 * 1024, @@ -10073,7 +10646,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (82802ab.c) */ - .erase = erase_82802ab, - .write = write_82802ab, -+ .erase = NULL, + .block_erasers = + { + { @@ -10088,7 +10660,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2704,11 +5335,28 @@ struct flashchip flashchips[] = { +@@ -2704,11 +5211,27 @@ struct flashchip flashchips[] = { .model_id = ST_M50LPW116, .total_size = 2048, .page_size = 64 * 1024, @@ -10100,7 +10672,6 @@ index 5fd78f2..f66b95a 100644 - .write = write_jedec, + .probe = probe_82802ab, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -10121,7 +10692,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2720,11 +5368,22 @@ struct flashchip flashchips[] = { +@@ -2720,11 +5243,21 @@ struct flashchip flashchips[] = { .model_id = S29C31004T, .total_size = 512, .page_size = 128, @@ -10132,7 +10703,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_49f002, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -10147,7 +10717,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2736,11 +5395,22 @@ struct flashchip flashchips[] = { +@@ -2736,11 +5269,21 @@ struct flashchip flashchips[] = { .model_id = S29C51001T, .total_size = 128, .page_size = 128, @@ -10158,7 +10728,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_49f002, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -10173,7 +10742,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2752,11 +5422,22 @@ struct flashchip flashchips[] = { +@@ -2752,11 +5295,21 @@ struct flashchip flashchips[] = { .model_id = S29C51002T, .total_size = 256, .page_size = 128, @@ -10185,7 +10754,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_49f002, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ -+ .erase = NULL, + .block_erasers = + { + { @@ -10200,7 +10768,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2768,11 +5449,22 @@ struct flashchip flashchips[] = { +@@ -2768,11 +5321,21 @@ struct flashchip flashchips[] = { .model_id = S29C51004T, .total_size = 512, .page_size = 128, @@ -10211,7 +10779,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_49f002, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -10226,7 +10793,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2784,11 +5476,27 @@ struct flashchip flashchips[] = { +@@ -2784,11 +5347,26 @@ struct flashchip flashchips[] = { .model_id = TI_TMS29F002RB, .total_size = 256, .page_size = 16384, /* Non-uniform sectors */ @@ -10234,9 +10801,9 @@ index 5fd78f2..f66b95a 100644 .tested = TEST_UNTESTED, .probe = probe_jedec, - .probe_timing = TIMING_FIXME, -+ .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ - .erase = NULL, +- .erase = NULL, - .write = NULL, ++ .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { @@ -10256,7 +10823,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2800,11 +5508,27 @@ struct flashchip flashchips[] = { +@@ -2800,11 +5378,26 @@ struct flashchip flashchips[] = { .model_id = TI_TMS29F002RT, .total_size = 256, .page_size = 16384, /* Non-uniform sectors */ @@ -10264,9 +10831,9 @@ index 5fd78f2..f66b95a 100644 .tested = TEST_UNTESTED, .probe = probe_jedec, - .probe_timing = TIMING_FIXME, -+ .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ - .erase = NULL, +- .erase = NULL, - .write = NULL, ++ .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { @@ -10286,63 +10853,49 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2819,7 +5543,26 @@ struct flashchip flashchips[] = { +@@ -2819,7 +5412,19 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 32} }, + .block_erase = spi_block_erase_20, + }, { -+ .eraseblocks = { {32 * 1024, 4} }, -+ .block_erase = spi_block_erase_52, -+ }, { + .eraseblocks = { {64 * 1024, 2} }, + .block_erase = spi_block_erase_d8, + }, { + .eraseblocks = { {128 * 1024, 1} }, -+ .block_erase = spi_block_erase_60, -+ }, { -+ .eraseblocks = { {128 * 1024, 1} }, + .block_erase = spi_block_erase_c7, + } + }, .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2835,7 +5578,26 @@ struct flashchip flashchips[] = { +@@ -2835,7 +5440,19 @@ struct flashchip flashchips[] = { .tested = TEST_UNTESTED, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 64} }, + .block_erase = spi_block_erase_20, + }, { -+ .eraseblocks = { {32 * 1024, 8} }, -+ .block_erase = spi_block_erase_52, -+ }, { + .eraseblocks = { {64 * 1024, 4} }, + .block_erase = spi_block_erase_d8, + }, { + .eraseblocks = { {256 * 1024, 1} }, -+ .block_erase = spi_block_erase_60, -+ }, { -+ .eraseblocks = { {256 * 1024, 1} }, + .block_erase = spi_block_erase_c7, + } + }, .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2848,10 +5610,29 @@ struct flashchip flashchips[] = { +@@ -2848,10 +5465,22 @@ struct flashchip flashchips[] = { .model_id = W_25X40, .total_size = 512, .page_size = 256, @@ -10351,30 +10904,23 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 128} }, + .block_erase = spi_block_erase_20, + }, { -+ .eraseblocks = { {32 * 1024, 16} }, -+ .block_erase = spi_block_erase_52, -+ }, { + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = spi_block_erase_d8, + }, { + .eraseblocks = { {512 * 1024, 1} }, -+ .block_erase = spi_block_erase_60, -+ }, { -+ .eraseblocks = { {512 * 1024, 1} }, + .block_erase = spi_block_erase_c7, + } + }, .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2864,10 +5645,29 @@ struct flashchip flashchips[] = { +@@ -2864,10 +5493,22 @@ struct flashchip flashchips[] = { .model_id = W_25X80, .total_size = 1024, .page_size = 256, @@ -10383,35 +10929,27 @@ index 5fd78f2..f66b95a 100644 .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 256} }, + .block_erase = spi_block_erase_20, + }, { -+ .eraseblocks = { {32 * 1024, 32} }, -+ .block_erase = spi_block_erase_52, -+ }, { + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = spi_block_erase_d8, + }, { + .eraseblocks = { {1024 * 1024, 1} }, -+ .block_erase = spi_block_erase_60, -+ }, { -+ .eraseblocks = { {1024 * 1024, 1} }, + .block_erase = spi_block_erase_c7, + } + }, .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2883,7 +5683,96 @@ struct flashchip flashchips[] = { +@@ -2883,7 +5524,93 @@ struct flashchip flashchips[] = { .tested = TEST_OK_PR, .probe = probe_spi_rdid, .probe_timing = TIMING_ZERO, - .erase = spi_chip_erase_c7, -+ .erase = NULL, + .block_erasers = + { + { @@ -10446,7 +10984,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_OK_PROBE, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -10481,7 +11018,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .block_erasers = + { + { @@ -10504,7 +11040,7 @@ index 5fd78f2..f66b95a 100644 .write = spi_chip_write_256, .read = spi_chip_read, }, -@@ -2896,10 +5785,18 @@ struct flashchip flashchips[] = { +@@ -2896,10 +5623,17 @@ struct flashchip flashchips[] = { .model_id = W_29C011, .total_size = 128, .page_size = 128, @@ -10515,7 +11051,6 @@ index 5fd78f2..f66b95a 100644 - .probe_timing = TIMING_FIXME, - .erase = erase_chip_jedec, + .probe_timing = 10, /* used datasheet for the W29C011A */ -+ .erase = NULL, + .block_erasers = + { + { @@ -10526,7 +11061,7 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, .read = read_memmapped, }, -@@ -2912,10 +5809,18 @@ struct flashchip flashchips[] = { +@@ -2912,10 +5646,17 @@ struct flashchip flashchips[] = { .model_id = W_29C020C, .total_size = 256, .page_size = 128, @@ -10536,7 +11071,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_jedec, .probe_timing = 10, - .erase = erase_chip_jedec, -+ .erase = NULL, + .block_erasers = + { + { @@ -10547,7 +11081,7 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, .read = read_memmapped, }, -@@ -2928,10 +5833,18 @@ struct flashchip flashchips[] = { +@@ -2928,10 +5669,17 @@ struct flashchip flashchips[] = { .model_id = W_29C040P, .total_size = 512, .page_size = 256, @@ -10556,7 +11090,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_jedec, .probe_timing = 10, - .erase = erase_chip_jedec, -+ .erase = NULL, + .block_erasers = + { + { @@ -10567,7 +11100,7 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, .read = read_memmapped, }, -@@ -2944,10 +5857,18 @@ struct flashchip flashchips[] = { +@@ -2944,10 +5692,17 @@ struct flashchip flashchips[] = { .model_id = W_29C011, .total_size = 128, .page_size = 128, @@ -10577,7 +11110,6 @@ index 5fd78f2..f66b95a 100644 .probe = probe_w29ee011, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (w29ee011.c) */ - .erase = erase_chip_jedec, -+ .erase = NULL, + .block_erasers = + { + { @@ -10588,7 +11120,7 @@ index 5fd78f2..f66b95a 100644 .write = write_jedec, .read = read_memmapped, }, -@@ -2959,12 +5880,23 @@ struct flashchip flashchips[] = { +@@ -2959,12 +5714,22 @@ struct flashchip flashchips[] = { .manufacture_id = WINBOND_ID, .model_id = W_39V040A, .total_size = 512, @@ -10601,7 +11133,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 10, - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -10616,7 +11147,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2975,12 +5907,23 @@ struct flashchip flashchips[] = { +@@ -2975,12 +5740,22 @@ struct flashchip flashchips[] = { .manufacture_id = WINBOND_ID, .model_id = W_39V040B, .total_size = 512, @@ -10629,7 +11160,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 10, - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -10644,7 +11174,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -2991,12 +5934,23 @@ struct flashchip flashchips[] = { +@@ -2991,12 +5766,23 @@ struct flashchip flashchips[] = { .manufacture_id = WINBOND_ID, .model_id = W_39V040C, .total_size = 512, @@ -10659,7 +11189,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_jedec, + .probe_timing = TIMING_FIXME, -+ .erase = NULL, /* Was erase_w39v040c */ + .block_erasers = + { + { @@ -10670,11 +11199,12 @@ index 5fd78f2..f66b95a 100644 + .block_erase = erase_chip_block_jedec, + } + }, ++ .printlock = printlock_w39v040c, + .write = write_jedec_1, .read = read_memmapped, }, -@@ -3007,12 +5961,26 @@ struct flashchip flashchips[] = { +@@ -3007,12 +5793,25 @@ struct flashchip flashchips[] = { .manufacture_id = WINBOND_ID, .model_id = W_39V040FA, .total_size = 512, @@ -10687,7 +11217,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 10, - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -10705,7 +11234,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -3023,12 +5991,23 @@ struct flashchip flashchips[] = { +@@ -3023,12 +5822,22 @@ struct flashchip flashchips[] = { .manufacture_id = WINBOND_ID, .model_id = W_39V080A, .total_size = 1024, @@ -10718,7 +11247,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 10, - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -10733,7 +11261,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -3040,11 +6019,27 @@ struct flashchip flashchips[] = { +@@ -3040,11 +5849,26 @@ struct flashchip flashchips[] = { .model_id = W_49F002U, .total_size = 256, .page_size = 128, @@ -10745,7 +11273,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_49f002, + .probe_timing = 10, -+ .erase = NULL, + .block_erasers = + { + { @@ -10765,7 +11292,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -3056,11 +6051,27 @@ struct flashchip flashchips[] = { +@@ -3056,11 +5880,26 @@ struct flashchip flashchips[] = { .model_id = W_49V002A, .total_size = 256, .page_size = 128, @@ -10776,7 +11303,6 @@ index 5fd78f2..f66b95a 100644 .probe_timing = 10, - .erase = erase_chip_jedec, - .write = write_49f002, -+ .erase = NULL, + .block_erasers = + { + { @@ -10796,7 +11322,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -3072,11 +6083,27 @@ struct flashchip flashchips[] = { +@@ -3072,11 +5911,26 @@ struct flashchip flashchips[] = { .model_id = W_49V002FA, .total_size = 256, .page_size = 128, @@ -10807,7 +11333,6 @@ index 5fd78f2..f66b95a 100644 - .erase = erase_chip_jedec, - .write = write_49f002, + .probe_timing = 10, -+ .erase = NULL, + .block_erasers = + { + { @@ -10827,7 +11352,7 @@ index 5fd78f2..f66b95a 100644 .read = read_memmapped, }, -@@ -3087,12 +6114,23 @@ struct flashchip flashchips[] = { +@@ -3087,12 +5941,23 @@ struct flashchip flashchips[] = { .manufacture_id = WINBOND_ID, .model_id = W_39V080FA, .total_size = 1024, @@ -10842,7 +11367,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_UNTESTED, + .probe = probe_jedec, + .probe_timing = TIMING_FIXME, -+ .erase = NULL, /* Was erase_winbond_fwhub */ + .block_erasers = + { + { @@ -10853,11 +11377,12 @@ index 5fd78f2..f66b95a 100644 + .block_erase = erase_chip_block_jedec, + } + }, ++ .unlock = unlock_winbond_fwhub, + .write = write_jedec_1, .read = read_memmapped, }, -@@ -3103,12 +6141,23 @@ struct flashchip flashchips[] = { +@@ -3103,12 +5968,23 @@ struct flashchip flashchips[] = { .manufacture_id = WINBOND_ID, .model_id = W_39V080FA_DM, .total_size = 512, @@ -10871,7 +11396,6 @@ index 5fd78f2..f66b95a 100644 - .write = write_winbond_fwhub, + .probe = probe_jedec, + .probe_timing = TIMING_FIXME, -+ .erase = NULL, /* Was erase_winbond_fwhub */ + .block_erasers = + { + { @@ -10882,11 +11406,57 @@ index 5fd78f2..f66b95a 100644 + .block_erase = erase_chip_block_jedec, + } + }, ++ .unlock = unlock_winbond_fwhub, + .write = write_jedec_1, .read = read_memmapped, }, -@@ -3208,5 +6257,48 @@ struct flashchip flashchips[] = { +@@ -3123,7 +5999,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_PREW, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -3139,7 +6014,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_PREW, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -3155,7 +6029,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_PREW, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -3171,7 +6044,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_PREW, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -3187,7 +6059,6 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_PREW, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, + .read = NULL, + }, +@@ -3203,10 +6074,49 @@ struct flashchip flashchips[] = { + .tested = TEST_BAD_PREW, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, +- .erase = NULL, + .write = NULL, .read = NULL, }, @@ -10901,7 +11471,6 @@ index 5fd78f2..f66b95a 100644 + .tested = TEST_BAD_PREW, + .probe = probe_spi_rdid, + .probe_timing = TIMING_ZERO, -+ .erase = NULL, + .write = NULL, + .read = NULL, + }, @@ -10916,7 +11485,6 @@ index 5fd78f2..f66b95a 100644 + .page_size = 256, + .tested = TEST_BAD_PREW, + .probe = probe_spi_rdid, -+ .erase = NULL, + .write = NULL, + }, + { @@ -10929,14 +11497,13 @@ index 5fd78f2..f66b95a 100644 + .page_size = 256, + .tested = TEST_BAD_PREW, + .probe = probe_spi_rems, -+ .erase = NULL, + .write = NULL, + }, + { NULL } }; diff --git a/flashchips.h b/flashchips.h -index 40edbbb..e299852 100644 +index 40edbbb..4337e52 100644 --- a/flashchips.h +++ b/flashchips.h @@ -34,6 +34,7 @@ @@ -10977,7 +11544,26 @@ index 40edbbb..e299852 100644 #define EN_25D16 0x3015 #define EN_25F05 0x3110 #define EN_25F10 0x3111 -@@ -251,11 +268,11 @@ +@@ -179,7 +196,7 @@ + #define EN_25F16 0x3115 + #define EN_25F32 0x3116 + #define EN_29F512 0x7F21 +-#define EN_29F010 0x7F20 ++#define EN_29F010 0x20 + #define EN_29F040A 0x7F04 + #define EN_29LV010 0x7F6E + #define EN_29LV040A 0x7F4F /* EN_29LV040(A) */ +@@ -237,6 +254,9 @@ + #define INTEL_ID 0x89 /* Intel */ + #define I_82802AB 0xAD + #define I_82802AC 0xAC ++#define E_28F004S5 0xA7 ++#define E_28F008S5 0xA6 ++#define E_28F016S5 0xAA + #define P28F001BXT 0x94 /* 28F001BX-T */ + #define P28F001BXB 0x95 /* 28F001BX-B */ + #define SHARP_LH28F008SA 0xA2 /* Sharp chip, Intel Vendor ID */ +@@ -251,11 +271,11 @@ * and use the same set of IDs. */ #define MX_ID 0xC2 /* Macronix (MX) */ @@ -10991,7 +11577,7 @@ index 40edbbb..e299852 100644 #define MX_25L1605 0x2015 /* MX25L1605{,A,D} */ #define MX_25L3205 0x2016 /* MX25L3205{,A} */ #define MX_25L6405 0x2017 /* MX25L3205{,D} */ -@@ -325,6 +342,14 @@ +@@ -325,6 +345,14 @@ #define PMC_49FL002 0x6D #define PMC_49FL004 0x6E @@ -11006,7 +11592,7 @@ index 40edbbb..e299852 100644 #define SHARP_ID 0xB0 /* Sharp */ #define SHARP_LH28F008BJxxPT 0xEC #define SHARP_LH28F008BJxxPB 0xED -@@ -340,6 +365,7 @@ +@@ -340,6 +368,7 @@ * the second device ID byte is memory capacity. */ #define SPANSION_ID 0x01 /* Spansion, same ID as AMD */ @@ -11014,7 +11600,7 @@ index 40edbbb..e299852 100644 #define SPANSION_S25FL016A 0x0214 /* -@@ -380,6 +406,7 @@ +@@ -380,6 +409,7 @@ #define SST_29VF020 0x25 #define SST_29SF040 0x13 #define SST_29VF040 0x14 @@ -11022,7 +11608,7 @@ index 40edbbb..e299852 100644 #define SST_39SF010 0xB5 #define SST_39SF020 0xB6 /* Same as 39SF020A */ #define SST_39SF040 0xB7 -@@ -446,6 +473,7 @@ +@@ -446,6 +476,7 @@ #define ST_M29F800DT 0xEC #define ST_M29W010B 0x23 #define ST_M29W040B 0xE3 @@ -11031,10 +11617,32 @@ index 40edbbb..e299852 100644 #define SYNCMOS_ID 0x40 /* SyncMOS and Mosel Vitelic */ #define S29C51001T 0x01 diff --git a/flashrom.8 b/flashrom.8 -index 1324854..1baea3f 100644 +index 1324854..25f4a1e 100644 --- a/flashrom.8 +++ b/flashrom.8 -@@ -140,6 +140,10 @@ Specify the programmer device. Currently supported are: +@@ -22,7 +22,11 @@ checking that your flashrom version won't interpret options in a different way. + .PP + You can specify one of \-E, \-r, \-w, \-v or no operation. + If no operation is specified, then all that happens +-is that flash info is dumped and the flash chip is set to writable. ++is that flash info is dumped and the flash chip is set to writable. It is ++recommended that if you try flashrom the first time on a system, you run it ++in probe only mode and check the output. Also you are advised to make a ++backup of your current ROM contents with \-r before you try to write a new ++image. + .TP + .B "\-r, \-\-read " + Read flash ROM contents and save them into the given +@@ -131,7 +135,7 @@ Same as + but outputs the supported hardware in MediaWiki syntax, so that it can be + easily pasted into the wiki page at http://www.flashrom.org/. + .TP +-.B "\-p, \-\-programmer " ++.B "\-p, \-\-programmer [:parameters]" + Specify the programmer device. Currently supported are: + .sp + .BR "* internal" " (default, for in-system flashing in the mainboard)" +@@ -140,15 +144,84 @@ Specify the programmer device. Currently supported are: .sp .BR "* nic3com" " (for flash ROMs on 3COM network cards)" .sp @@ -11044,42 +11652,180 @@ index 1324854..1baea3f 100644 +.sp .BR "* satasii" " (for flash ROMs on Silicon Image SATA/IDE controllers)" .sp ++.BR "* atahpt" " (for flash ROMs on Highpoint ATA/RAID controllers)" ++.sp .BR "* it87spi" " (for flash ROMs behind an ITE IT87xx Super I/O LPC/SPI translation unit)" -@@ -148,6 +152,8 @@ Specify the programmer device. Currently supported are: + .sp + .BR "* ft2232spi" " (for flash ROMs attached to a FT2232H/FT4232H based USB SPI programmer)" .sp .BR "* serprog" " (for flash ROMs attached to Urja's AVR programmer)" .sp +-The dummy programmer has an optional parameter specifying the bus types it +.BR "* buspiratespi" " (for flash ROMs attached to a Bus Pirate)" +.sp - The dummy programmer has an optional parameter specifying the bus types it ++Some programmers have optional or mandatory parameters which are described ++in detail in the ++.B PROGRAMMER SPECIFIC INFO ++section. Support for some programmers can be disabled at compile time. ++.B "flashrom -h" ++lists all supported programmers. ++.TP ++.B "\-h, \-\-help" ++Show a help text and exit. ++.TP ++.B "\-R, \-\-version" ++Show version information and exit. ++.SH PROGRAMMER SPECIFIC INFO ++Some programmer drivers accept further parameters to set programmer-specific ++parameters. These parameters are seperated from the programmer name by a ++colon. While some programmers take arguments at fixed positions, other ++programmers use a key/value interface in which the key and value is separated ++by an equal sign and different pairs are separated by a comma or a colon. ++.TP ++.BR "internal " programmer ++Some mainboards require to run mainboard specific code to enable flash erase ++and write support (and probe support on old systems with parallel flash). ++The mainboard brand and model (if it requires specific code) is usually ++autodetected using one of the following mechanisms: If your system is ++running coreboot, the mainboard type is determined from the coreboot table, ++otherwise, the mainboard is detected by examining the onboard PCI devices ++and possibly DMI info. If PCI and DMI do not contain information to uniquely ++identify the mainboard (which is the exception), it might be necessary to ++specify the mainboard using the \-m switch (see above). ++.sp ++Some of these board-specific flash enabling functions (called board enables) ++in flashrom have not yet been tested. If your mainboard is detected needing ++an untested board enable function, a warning message is printed and the ++board enable is not executed, because a wrong board enable function might ++cause the system to behave erratically, as board enable functions touch the ++low-level internals of a mainboard. Not executing a board enable function ++(if one is needed) might cause detection or erasing failure. If your board ++protects only part of the flash (commonly the top end, called boot block), ++flashrom might encounter an error only after erasing the unprotected part, ++so running without the board-enable function might be dangerous for erase ++and write (which includes erase). ++.sp ++The suggested procedure for a mainboard with untested board specific code is ++to first try to probe the ROM (just invoke flashrom and check that it ++detects your flash chip type) without running the board enable code (i.e. ++without any parameters). If it finds your chip, fine, otherwise, retry ++probing your chip with the board-enable code running, using ++.sp ++.B "flashrom -p internal:boardenable=force" ++.sp ++If your chip is still not detected, the board enable code seems to be broken ++or the flash chip unsupported. Otherwise, make a backup of your current ROM ++contents (using \-r) and store it to a medium outside of your computer, like ++an USB drive or a network share. If you needed to run the board enable code ++already for probing, use it for reading too. Now you can try to write the ++new image. You should enable the board enable code in any case now, as it ++has been written because it is known that writing/erasing without the board ++enable is going to fail. In any case (success or failure), please report to ++the flashrom mailing list, see below. ++.sp ++.BR "dummy " programmer ++An optional parameter specifies the bus types it should support. For that you have to use the .B "flashrom -p dummy:type" -@@ -178,6 +184,7 @@ Example: + syntax where +@@ -159,11 +232,13 @@ in any order. .sp - Currently the following programmers support this mechanism: - .BR nic3com , -+.BR gfxnvidia , - .BR satasii . + Example: + .B "flashrom -p dummy:lpc,fwh" +-.sp +-If you have multiple supported PCI cards which can program flash chips +-(NICs, SATA/IDE controllers, etc.) in your system, you must use the ++.TP ++.BR "nic3com" , " gfxnvidia" , " satasii" and " atahpt " programmers ++These programmers have an option to specify the PCI address of the card ++your want to use, which must be specified if more than one card supported ++by the selected programmer is installed in your system. The syntax is + .B "flashrom -p xxxx:bb:dd.f" +-syntax to explicitly select one of them, where ++, where + .B xxxx + is the name of the programmer + .B bb +@@ -175,20 +250,18 @@ is the PCI function number of the desired NIC. .sp - The it87spi programmer has an optional parameter which will set the I/O base -@@ -214,6 +221,16 @@ syntax and for IP, you have to use + Example: + .B "flashrom -p nic3com:05:04.0" +-.sp +-Currently the following programmers support this mechanism: +-.BR nic3com , +-.BR satasii . +-.sp +-The it87spi programmer has an optional parameter which will set the I/O base +-port of the IT87* SPI controller interface to the port specified in the +-parameter. For that you have to use the ++.TP ++.BR "it87spi " programmer ++An optional parameter sets the I/O base port of the IT87* SPI controller ++interface to the port specified in the parameter instead of using the port ++address set by the BIOS. For that you have to use the + .B "flashrom -p it87spi:port=portnum" + syntax where + .B portnum + is an I/O port number which must be a multiple of 8. +-.sp +-The ft2232spi programmer has an optional parameter specifying the controller ++.TP ++.BR "ft2232spi " programmer ++An optional parameter species the controller + type and interface/port it should support. For that you have to use the + .B "flashrom -p ft2232spi:model,port=interface" + syntax where +@@ -198,31 +271,35 @@ can be any of + and + .B interface + can be any of +-.B A +-.BR B . ++.BR "A B" . + The default model is + .B 4232H + and the default interface is + .BR B . +-.sp +-The serprog programmer has an optional parameter specifying either a serial ++.TP ++.BR "serprog " programmer ++A mandatory parameter specifies either a serial + device/baud combination or an IP/port combination for communication with the +-programmer. For serial, you have to use the ++programmer. In the device/baud combination, the device has to start with a ++slash. For serial, you have to use the + .B "flashrom -p serprog:/dev/device:baud" + syntax and for IP, you have to use + .B "flashrom -p serprog:ip:port" instead. More information about serprog is available in serprog-protocol.txt in the source distribution. - .sp -+The buspiratespi programmer has a required dev parameter specifying the Bus -+Pirate device node and an optional spispeed parameter specifying the frequency -+of the SPI bus. The parameter delimiter is a comma. Syntax is +-.sp +-Support for some programmers can be disabled at compile time. +-.B "flashrom -h" +-lists all supported programmers. + .TP +-.B "\-h, \-\-help" +-Show a help text and exit. +-.TP +-.B "\-R, \-\-version" +-Show version information and exit. ++.BR "buspiratespi " programmer ++A required dev parameter specifyies the Bus Pirate device node and an optional ++spispeed parameter specifyies the frequency of the SPI bus. The parameter ++delimiter is a comma. Syntax is ++.sp +.B "flashrom -p buspiratespi:dev=/dev/device,spispeed=frequency" ++.sp +where +.B frequency +can be any of +.B 30k 125k 250k 1M 2M 2.6M 4M 8M -+(in Hz). -+.sp - Support for some programmers can be disabled at compile time. - .B "flashrom -h" - lists all supported programmers. -@@ -245,7 +262,7 @@ Claus Gindhart ++(in Hz). The default is the maximum frequency of 8 MHz. + .SH EXIT STATUS + flashrom exits with 0 on success, 1 on most failures but with 2 if /dev/mem + (/dev/xsvc on Solaris) can not be opened and with 3 if a call to mmap() fails. +@@ -245,7 +322,7 @@ Claus Gindhart .br Dominik Geyer .br @@ -11088,7 +11834,7 @@ index 1324854..1baea3f 100644 .br Giampiero Giancipoli .br -@@ -275,9 +292,9 @@ Steven James +@@ -275,9 +352,9 @@ Steven James .br Uwe Hermann .br @@ -11101,10 +11847,10 @@ index 1324854..1baea3f 100644 some others .PP diff --git a/flashrom.c b/flashrom.c -index fc80301..326f725 100644 +index fc80301..6a91089 100644 --- a/flashrom.c +++ b/flashrom.c -@@ -33,10 +33,70 @@ +@@ -33,10 +33,73 @@ const char *flashrom_version = FLASHROM_VERSION; char *chip_to_probe = NULL; int verbose = 0; @@ -11119,7 +11865,7 @@ index fc80301..326f725 100644 + * if more than one of them is selected. If only one is selected, it is clear + * that the user wants that one to become the default. + */ -+#if NIC3COM_SUPPORT+GFXNVIDIA_SUPPORT+DRKAISER_SUPPORT+SATASII_SUPPORT+FT2232_SPI_SUPPORT+SERPROG_SUPPORT+BUSPIRATE_SPI_SUPPORT+DEDIPROG_SUPPORT > 1 ++#if NIC3COM_SUPPORT+GFXNVIDIA_SUPPORT+DRKAISER_SUPPORT+SATASII_SUPPORT+ATAHPT_SUPPORT+FT2232_SPI_SUPPORT+SERPROG_SUPPORT+BUSPIRATE_SPI_SUPPORT+DEDIPROG_SUPPORT > 1 +#error Please enable either CONFIG_DUMMY or CONFIG_INTERNAL or disable support for all external programmers except one. +#endif +enum programmer programmer = @@ -11135,6 +11881,9 @@ index fc80301..326f725 100644 +#if SATASII_SUPPORT == 1 + PROGRAMMER_SATASII +#endif ++#if ATAHPT_SUPPORT == 1 ++ PROGRAMMER_ATAHPT ++#endif +#if FT2232_SPI_SUPPORT == 1 + PROGRAMMER_FT2232SPI +#endif @@ -11175,7 +11924,7 @@ index fc80301..326f725 100644 { .name = "internal", .init = internal_init, -@@ -53,7 +113,9 @@ const struct programmer_entry programmer_table[] = { +@@ -53,7 +116,9 @@ const struct programmer_entry programmer_table[] = { .chip_writen = fallback_chip_writen, .delay = internal_delay, }, @@ -11185,7 +11934,7 @@ index fc80301..326f725 100644 { .name = "dummy", .init = dummy_init, -@@ -70,7 +132,9 @@ const struct programmer_entry programmer_table[] = { +@@ -70,7 +135,9 @@ const struct programmer_entry programmer_table[] = { .chip_writen = dummy_chip_writen, .delay = internal_delay, }, @@ -11195,12 +11944,12 @@ index fc80301..326f725 100644 { .name = "nic3com", .init = nic3com_init, -@@ -87,7 +151,47 @@ const struct programmer_entry programmer_table[] = { +@@ -87,7 +154,47 @@ const struct programmer_entry programmer_table[] = { .chip_writen = fallback_chip_writen, .delay = internal_delay, }, +#endif - ++ +#if GFXNVIDIA_SUPPORT == 1 + { + .name = "gfxnvidia", @@ -11219,7 +11968,7 @@ index fc80301..326f725 100644 + .delay = internal_delay, + }, +#endif -+ + +#if DRKAISER_SUPPORT == 1 + { + .name = "drkaiser", @@ -11243,11 +11992,30 @@ index fc80301..326f725 100644 { .name = "satasii", .init = satasii_init, -@@ -104,36 +208,39 @@ const struct programmer_entry programmer_table[] = { +@@ -104,36 +211,58 @@ const struct programmer_entry programmer_table[] = { .chip_writen = fallback_chip_writen, .delay = internal_delay, }, +#endif ++ ++#if ATAHPT_SUPPORT == 1 ++ { ++ .name = "atahpt", ++ .init = atahpt_init, ++ .shutdown = atahpt_shutdown, ++ .map_flash_region = fallback_map, ++ .unmap_flash_region = fallback_unmap, ++ .chip_readb = atahpt_chip_readb, ++ .chip_readw = fallback_chip_readw, ++ .chip_readl = fallback_chip_readl, ++ .chip_readn = fallback_chip_readn, ++ .chip_writeb = atahpt_chip_writeb, ++ .chip_writew = fallback_chip_writew, ++ .chip_writel = fallback_chip_writel, ++ .chip_writen = fallback_chip_writen, ++ .delay = internal_delay, ++ }, ++#endif +#if INTERNAL_SUPPORT == 1 { @@ -11289,7 +12057,7 @@ index fc80301..326f725 100644 .chip_writew = fallback_chip_writew, .chip_writel = fallback_chip_writel, .chip_writen = fallback_chip_writen, -@@ -160,6 +267,44 @@ const struct programmer_entry programmer_table[] = { +@@ -160,9 +289,76 @@ const struct programmer_entry programmer_table[] = { }, #endif @@ -11334,7 +12102,50 @@ index fc80301..326f725 100644 {}, /* This entry corresponds to PROGRAMMER_INVALID. */ }; -@@ -245,6 +390,8 @@ int read_memmapped(struct flashchip *flash, uint8_t *buf, int start, int len) ++#define SHUTDOWN_MAXFN 4 ++static int shutdown_fn_count = 0; ++struct shutdown_func_data { ++ void (*func) (void *data); ++ void *data; ++} shutdown_fn[SHUTDOWN_MAXFN]; ++ ++/* Register a function to be executed on programmer shutdown. ++ * The advantage over atexit() is that you can supply a void pointer which will ++ * be used as parameter to the registered function upon programmer shutdown. ++ * This pointer can point to arbitrary data used by said function, e.g. undo ++ * information for GPIO settings etc. If unneeded, set data=NULL. ++ * Please note that the first (void *data) belongs to the function signature of ++ * the function passed as first parameter. ++ */ ++int register_shutdown(void (*function) (void *data), void *data) ++{ ++ if (shutdown_fn_count >= SHUTDOWN_MAXFN) { ++ msg_perr("Tried to register more than %n shutdown functions.\n", ++ SHUTDOWN_MAXFN); ++ return 1; ++ } ++ shutdown_fn[shutdown_fn_count].func = function; ++ shutdown_fn[shutdown_fn_count].data = data; ++ shutdown_fn_count++; ++ ++ return 0; ++} ++ + int programmer_init(void) + { + return programmer_table[programmer].init(); +@@ -170,6 +366,10 @@ int programmer_init(void) + + int programmer_shutdown(void) + { ++ int i; ++ ++ for (i = shutdown_fn_count - 1; i >= 0; i--) ++ shutdown_fn[i].func(shutdown_fn[i].data); + return programmer_table[programmer].shutdown(); + } + +@@ -245,6 +445,8 @@ int read_memmapped(struct flashchip *flash, uint8_t *buf, int start, int len) return 0; } @@ -11343,7 +12154,7 @@ index fc80301..326f725 100644 int min(int a, int b) { return (a < b) ? a : b; -@@ -255,6 +402,15 @@ int max(int a, int b) +@@ -255,6 +457,15 @@ int max(int a, int b) return (a > b) ? a : b; } @@ -11359,7 +12170,7 @@ index fc80301..326f725 100644 char *strcat_realloc(char *dest, const char *src) { dest = realloc(dest, strlen(dest) + strlen(src) + 1); -@@ -264,6 +420,60 @@ char *strcat_realloc(char *dest, const char *src) +@@ -264,6 +475,60 @@ char *strcat_realloc(char *dest, const char *src) return dest; } @@ -11420,7 +12231,7 @@ index fc80301..326f725 100644 /* start is an offset to the base address of the flash chip */ int check_erased_range(struct flashchip *flash, int start, int len) { -@@ -281,7 +491,8 @@ int check_erased_range(struct flashchip *flash, int start, int len) +@@ -281,7 +546,8 @@ int check_erased_range(struct flashchip *flash, int start, int len) } /** @@ -11430,10 +12241,71 @@ index fc80301..326f725 100644 * @start offset to the base address of the flash chip * @len length of the verified area * @message string to print in the "FAILED" message -@@ -354,10 +565,197 @@ out_free: +@@ -354,10 +620,258 @@ out_free: return ret; } ++/** ++ * Check if the buffer @have can be programmed to the content of @want without ++ * erasing. This is only possible if all chunks of size @gran are either kept ++ * as-is or changed from an all-ones state to any other state. ++ * The following write granularities (enum @gran) are known: ++ * - 1 bit. Each bit can be cleared individually. ++ * - 1 byte. A byte can be written once. Further writes to an already written ++ * byte cause the contents to be either undefined or to stay unchanged. ++ * - 128 bytes. If less than 128 bytes are written, the rest will be ++ * erased. Each write to a 128-byte region will trigger an automatic erase ++ * before anything is written. Very uncommon behaviour and unsupported by ++ * this function. ++ * - 256 bytes. If less than 256 bytes are written, the contents of the ++ * unwritten bytes are undefined. ++ * ++ * @have buffer with current content ++ * @want buffer with desired content ++ * @len length of the verified area ++ * @gran write granularity (enum, not count) ++ * @return 0 if no erase is needed, 1 otherwise ++ */ ++int need_erase(uint8_t *have, uint8_t *want, int len, enum write_granularity gran) ++{ ++ int result = 0; ++ int i, j, limit; ++ ++ switch (gran) { ++ case write_gran_1bit: ++ for (i = 0; i < len; i++) ++ if ((have[i] & want[i]) != want[i]) { ++ result = 1; ++ break; ++ } ++ break; ++ case write_gran_1byte: ++ for (i = 0; i < len; i++) ++ if ((have[i] != want[i]) && (have[i] != 0xff)) { ++ result = 1; ++ break; ++ } ++ break; ++ case write_gran_256bytes: ++ for (j = 0; j < len / 256; j++) { ++ limit = min (256, len - j * 256); ++ /* Are have and want identical? */ ++ if (!memcmp(have + j * 256, want + j * 256, limit)) ++ continue; ++ /* have needs to be in erased state. */ ++ for (i = 0; i < limit; i++) ++ if (have[i] != 0xff) { ++ result = 1; ++ break; ++ } ++ if (result) ++ break; ++ } ++ break; ++ } ++ return result; ++} ++ +/* This function generates various test patterns useful for testing controller + * and chip communication as well as chip behaviour. + * @@ -11629,7 +12501,7 @@ index fc80301..326f725 100644 char *tmp; for (flash = first_flash; flash && flash->name; flash++) { -@@ -369,7 +767,8 @@ struct flashchip *probe_flash(struct flashchip *first_flash, int force) +@@ -369,7 +883,8 @@ struct flashchip *probe_flash(struct flashchip *first_flash, int force) printf_debug("failed! flashrom has no probe function for this flash chip.\n"); continue; } @@ -11639,7 +12511,7 @@ index fc80301..326f725 100644 tmp = flashbuses_to_text(buses_supported); printf_debug("skipped. Host bus type %s ", tmp); free(tmp); -@@ -380,6 +779,7 @@ struct flashchip *probe_flash(struct flashchip *first_flash, int force) +@@ -380,6 +895,7 @@ struct flashchip *probe_flash(struct flashchip *first_flash, int force) } size = flash->total_size * 1024; @@ -11647,7 +12519,17 @@ index fc80301..326f725 100644 base = flashbase ? flashbase : (0xffffffff - size + 1); flash->virtual_memory = (chipaddr)programmer_map_flash_region("flash chip", base, size); -@@ -434,7 +834,7 @@ int read_flash(struct flashchip *flash, char *filename) +@@ -405,6 +921,9 @@ notfound: + flash->vendor, flash->name, flash->total_size, + flashbuses_to_text(flash->bustype), base); + ++ if (flash->printlock) ++ flash->printlock(flash); ++ + return flash; + } + +@@ -434,7 +953,7 @@ int read_flash(struct flashchip *flash, char *filename) printf("Error: No filename specified.\n"); return 1; } @@ -11656,7 +12538,7 @@ index fc80301..326f725 100644 perror(filename); exit(1); } -@@ -455,110 +855,164 @@ int read_flash(struct flashchip *flash, char *filename) +@@ -455,110 +974,158 @@ int read_flash(struct flashchip *flash, char *filename) return 0; } @@ -11785,18 +12667,12 @@ index fc80301..326f725 100644 + if (!ret) + break; + } -+ /* If no block erase function was found or block erase failed, retry. */ -+ if ((!found || ret) && (flash->erase)) { -+ found = 1; -+ printf_debug("Trying whole-chip erase function... "); -+ ret = flash->erase(flash); -+ } + if (!found) { fprintf(stderr, "ERROR: flashrom has no erase function for this flash chip.\n"); return 1; } - flash->erase(flash); -- + - /* FIXME: The lines below are superfluous. We should check the result - * of flash->erase(flash) instead. - */ @@ -11806,7 +12682,7 @@ index fc80301..326f725 100644 - return 1; - } else - flash->read(flash, buf, 0, size); - +- - for (erasedbytes = 0; erasedbytes < size; erasedbytes++) - if (0xff != buf[erasedbytes]) { - printf("FAILED!\n"); @@ -11907,7 +12783,7 @@ index fc80301..326f725 100644 } void print_version(void) -@@ -566,251 +1020,36 @@ void print_version(void) +@@ -566,251 +1133,36 @@ void print_version(void) printf("flashrom v%s\n", flashrom_version); } @@ -11977,8 +12853,7 @@ index fc80301..326f725 100644 if (spi_programmer_count - 1 != SPI_CONTROLLER_INVALID) { fprintf(stderr, "SPI programmer table miscompilation!\n"); - exit(1); -+ ret = 1; - } +- } - - setbuf(stdout, NULL); - while ((opt = getopt_long(argc, argv, "rRwvnVEfc:m:l:i:p:Lzh", @@ -12120,7 +12995,8 @@ index fc80301..326f725 100644 - if (programmer_init()) { - fprintf(stderr, "Error: Programmer initialization failed.\n"); - exit(1); -- } ++ ret = 1; + } - - myusec_calibrate_delay(); - @@ -12179,7 +13055,7 @@ index fc80301..326f725 100644 if (TEST_OK_MASK != (flash->tested & TEST_OK_MASK)) { printf("===\n"); if (flash->tested & TEST_BAD_MASK) { -@@ -840,29 +1079,32 @@ int main(int argc, char *argv[]) +@@ -840,29 +1192,32 @@ int main(int argc, char *argv[]) printf(" WRITE"); printf("\n"); } @@ -12227,7 +13103,7 @@ index fc80301..326f725 100644 size = flash->total_size * 1024; buf = (uint8_t *) calloc(size, sizeof(char)); -@@ -872,6 +1114,7 @@ int main(int argc, char *argv[]) +@@ -872,26 +1227,40 @@ int main(int argc, char *argv[]) fprintf(stderr, "Erase is not working on this chip. "); if (!force) { fprintf(stderr, "Aborting.\n"); @@ -12235,8 +13111,11 @@ index fc80301..326f725 100644 return 1; } else { fprintf(stderr, "Continuing anyway.\n"); -@@ -879,11 +1122,14 @@ int main(int argc, char *argv[]) + } } ++ if (flash->unlock) ++ flash->unlock(flash); ++ if (erase_flash(flash)) { emergency_help_message(); + programmer_shutdown(); @@ -12244,6 +13123,9 @@ index fc80301..326f725 100644 } } else if (read_it) { - if (read_flash(flash, filename)) ++ if (flash->unlock) ++ flash->unlock(flash); ++ + if (read_flash(flash, filename)) { + programmer_shutdown(); return 1; @@ -12251,7 +13133,11 @@ index fc80301..326f725 100644 } else { struct stat image_stat; -@@ -892,6 +1138,7 @@ int main(int argc, char *argv[]) ++ if (flash->unlock) ++ flash->unlock(flash); ++ + if (flash->tested & TEST_BAD_ERASE) { + fprintf(stderr, "Erase is not working on this chip " "and erase is needed for write. "); if (!force) { fprintf(stderr, "Aborting.\n"); @@ -12259,7 +13145,7 @@ index fc80301..326f725 100644 return 1; } else { fprintf(stderr, "Continuing anyway.\n"); -@@ -901,29 +1148,36 @@ int main(int argc, char *argv[]) +@@ -901,29 +1270,36 @@ int main(int argc, char *argv[]) fprintf(stderr, "Write is not working on this chip. "); if (!force) { fprintf(stderr, "Aborting.\n"); @@ -12297,7 +13183,7 @@ index fc80301..326f725 100644 return 1; } } -@@ -938,12 +1192,14 @@ int main(int argc, char *argv[]) +@@ -938,12 +1314,14 @@ int main(int argc, char *argv[]) printf("Writing flash chip... "); if (!flash->write) { fprintf(stderr, "Error: flashrom has no write function for this flash chip.\n"); @@ -12312,7 +13198,7 @@ index fc80301..326f725 100644 return 1; } else { printf("COMPLETE.\n"); -@@ -955,7 +1211,7 @@ int main(int argc, char *argv[]) +@@ -955,7 +1333,7 @@ int main(int argc, char *argv[]) if (write_it) programmer_delay(1000*1000); ret = verify_flash(flash, buf); @@ -12322,10 +13208,14 @@ index fc80301..326f725 100644 */ if (ret && write_it) diff --git a/ft2232_spi.c b/ft2232_spi.c -index 00490fe..6e029c2 100644 +index 00490fe..97b4867 100644 --- a/ft2232_spi.c +++ b/ft2232_spi.c -@@ -29,15 +29,20 @@ +@@ -26,18 +26,24 @@ + #include + #include + #include "flash.h" ++#include "chipdrivers.h" #include "spi.h" #include @@ -12352,7 +13242,7 @@ index 00490fe..6e029c2 100644 static struct ftdi_context ftdic_context; -@@ -46,7 +51,7 @@ int send_buf(struct ftdi_context *ftdic, const unsigned char *buf, int size) +@@ -46,7 +52,7 @@ int send_buf(struct ftdi_context *ftdic, const unsigned char *buf, int size) int r; r = ftdi_write_data(ftdic, (unsigned char *) buf, size); if (r < 0) { @@ -12361,7 +13251,7 @@ index 00490fe..6e029c2 100644 ftdi_get_error_string(ftdic)); return 1; } -@@ -58,7 +63,7 @@ int get_buf(struct ftdi_context *ftdic, const unsigned char *buf, int size) +@@ -58,7 +64,7 @@ int get_buf(struct ftdi_context *ftdic, const unsigned char *buf, int size) int r; r = ftdi_read_data(ftdic, (unsigned char *) buf, size); if (r < 0) { @@ -12370,7 +13260,7 @@ index 00490fe..6e029c2 100644 ftdi_get_error_string(ftdic)); return 1; } -@@ -70,14 +75,13 @@ int ft2232_spi_init(void) +@@ -70,14 +76,13 @@ int ft2232_spi_init(void) int f; struct ftdi_context *ftdic = &ftdic_context; unsigned char buf[512]; @@ -12387,7 +13277,7 @@ index 00490fe..6e029c2 100644 } if (programmer_param && !strlen(programmer_param)) { -@@ -100,49 +104,49 @@ int ft2232_spi_init(void) +@@ -100,49 +105,49 @@ int ft2232_spi_init(void) ft2232_interface = INTERFACE_B; break; default: @@ -12450,7 +13340,7 @@ index 00490fe..6e029c2 100644 if (send_buf(ftdic, buf, 1)) return -1; #define MPSSE_CLK 60.0 -@@ -152,37 +156,36 @@ int ft2232_spi_init(void) +@@ -152,37 +157,36 @@ int ft2232_spi_init(void) #define MPSSE_CLK 12.0 #endif @@ -12498,7 +13388,7 @@ index 00490fe..6e029c2 100644 buses_supported = CHIP_BUSTYPE_SPI; spi_controller = SPI_CONTROLLER_FT2232; -@@ -195,39 +198,47 @@ int ft2232_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -195,39 +199,47 @@ int ft2232_spi_send_command(unsigned int writecnt, unsigned int readcnt, { struct ftdi_context *ftdic = &ftdic_context; static unsigned char *buf = NULL; @@ -12563,7 +13453,7 @@ index 00490fe..6e029c2 100644 * read command, then do the fetch of the results. */ if (readcnt) { -@@ -235,26 +246,36 @@ int ft2232_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -235,26 +247,36 @@ int ft2232_spi_send_command(unsigned int writecnt, unsigned int readcnt, buf[i++] = (readcnt - 1) & 0xff; buf[i++] = ((readcnt - 1) >> 8) & 0xff; ret = send_buf(ftdic, buf, i); @@ -12614,7 +13504,7 @@ index 00490fe..6e029c2 100644 } int ft2232_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) -@@ -269,14 +290,14 @@ int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf) +@@ -269,14 +291,14 @@ int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf) int i; spi_disable_blockprotect(); @@ -12635,7 +13525,7 @@ index 00490fe..6e029c2 100644 for (i = 0; i < total_size; i += 256) { int l, r; if (i + 256 <= total_size) -@@ -285,10 +306,10 @@ int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf) +@@ -285,10 +307,10 @@ int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf) l = total_size - i; if ((r = spi_nbyte_program(i, &buf[i], l))) { @@ -12650,7 +13540,7 @@ index 00490fe..6e029c2 100644 } diff --git a/gfxnvidia.c b/gfxnvidia.c new file mode 100644 -index 0000000..cc66ace +index 0000000..ec41279 --- /dev/null +++ b/gfxnvidia.c @@ -0,0 +1,104 @@ @@ -12684,29 +13574,29 @@ index 0000000..cc66ace +uint8_t *nvidia_bar; + +struct pcidev_status gfx_nvidia[] = { -+ {0x10de, 0x0010, PCI_NT, "NVIDIA", "Mutara V08 [NV2]" }, -+ {0x10de, 0x0018, PCI_NT, "NVIDIA", "RIVA 128" }, -+ {0x10de, 0x0020, PCI_NT, "NVIDIA", "RIVA TNT" }, -+ {0x10de, 0x0028, PCI_NT, "NVIDIA", "RIVA TNT2/TNT2 Pro" }, -+ {0x10de, 0x0029, PCI_NT, "NVIDIA", "RIVA TNT2 Ultra" }, -+ {0x10de, 0x002c, PCI_NT, "NVIDIA", "Vanta/Vanta LT" }, -+ {0x10de, 0x002d, PCI_OK, "NVIDIA", "RIVA TNT2 Model 64/Model 64 Pro" }, -+ {0x10de, 0x00a0, PCI_NT, "NVIDIA", "Aladdin TNT2" }, -+ {0x10de, 0x0100, PCI_NT, "NVIDIA", "GeForce 256" }, -+ {0x10de, 0x0101, PCI_NT, "NVIDIA", "GeForce DDR" }, -+ {0x10de, 0x0103, PCI_NT, "NVIDIA", "Quadro" }, -+ {0x10de, 0x0110, PCI_NT, "NVIDIA", "GeForce2 MX" }, -+ {0x10de, 0x0111, PCI_NT, "NVIDIA", "GeForce2 MX" }, -+ {0x10de, 0x0112, PCI_NT, "NVIDIA", "GeForce2 GO" }, -+ {0x10de, 0x0113, PCI_NT, "NVIDIA", "Quadro2 MXR" }, -+ {0x10de, 0x0150, PCI_NT, "NVIDIA", "GeForce2 GTS/Pro" }, -+ {0x10de, 0x0151, PCI_NT, "NVIDIA", "GeForce2 GTS" }, -+ {0x10de, 0x0152, PCI_NT, "NVIDIA", "GeForce2 Ultra" }, -+ {0x10de, 0x0153, PCI_NT, "NVIDIA", "Quadro2 Pro" }, -+ {0x10de, 0x0200, PCI_NT, "NVIDIA", "GeForce 3 nFX" }, -+ {0x10de, 0x0201, PCI_NT, "NVIDIA", "GeForce 3 nFX" }, -+ {0x10de, 0x0202, PCI_NT, "NVIDIA", "GeForce 3 nFX Ultra" }, -+ {0x10de, 0x0203, PCI_NT, "NVIDIA", "Quadro 3 DDC" }, ++ {0x10de, 0x0010, NT, "NVIDIA", "Mutara V08 [NV2]" }, ++ {0x10de, 0x0018, NT, "NVIDIA", "RIVA 128" }, ++ {0x10de, 0x0020, NT, "NVIDIA", "RIVA TNT" }, ++ {0x10de, 0x0028, NT, "NVIDIA", "RIVA TNT2/TNT2 Pro" }, ++ {0x10de, 0x0029, NT, "NVIDIA", "RIVA TNT2 Ultra" }, ++ {0x10de, 0x002c, NT, "NVIDIA", "Vanta/Vanta LT" }, ++ {0x10de, 0x002d, OK, "NVIDIA", "RIVA TNT2 Model 64/Model 64 Pro" }, ++ {0x10de, 0x00a0, NT, "NVIDIA", "Aladdin TNT2" }, ++ {0x10de, 0x0100, NT, "NVIDIA", "GeForce 256" }, ++ {0x10de, 0x0101, NT, "NVIDIA", "GeForce DDR" }, ++ {0x10de, 0x0103, NT, "NVIDIA", "Quadro" }, ++ {0x10de, 0x0110, NT, "NVIDIA", "GeForce2 MX" }, ++ {0x10de, 0x0111, NT, "NVIDIA", "GeForce2 MX" }, ++ {0x10de, 0x0112, NT, "NVIDIA", "GeForce2 GO" }, ++ {0x10de, 0x0113, NT, "NVIDIA", "Quadro2 MXR" }, ++ {0x10de, 0x0150, NT, "NVIDIA", "GeForce2 GTS/Pro" }, ++ {0x10de, 0x0151, NT, "NVIDIA", "GeForce2 GTS" }, ++ {0x10de, 0x0152, NT, "NVIDIA", "GeForce2 Ultra" }, ++ {0x10de, 0x0153, NT, "NVIDIA", "Quadro2 Pro" }, ++ {0x10de, 0x0200, NT, "NVIDIA", "GeForce 3 nFX" }, ++ {0x10de, 0x0201, NT, "NVIDIA", "GeForce 3 nFX" }, ++ {0x10de, 0x0202, NT, "NVIDIA", "GeForce 3 nFX Ultra" }, ++ {0x10de, 0x0203, NT, "NVIDIA", "Quadro 3 DDC" }, + + {}, +}; @@ -12758,12 +13648,101 @@ index 0000000..cc66ace +{ + return mmio_readb(nvidia_bar + addr); +} +diff --git a/hwaccess.c b/hwaccess.c +new file mode 100644 +index 0000000..7f7b805 +--- /dev/null ++++ b/hwaccess.c +@@ -0,0 +1,83 @@ ++/* ++ * This file is part of the flashrom project. ++ * ++ * Copyright (C) 2009,2010 Carl-Daniel Hailfinger ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "flash.h" ++ ++#if defined(__FreeBSD__) || defined(__DragonFly__) ++int io_fd; ++#endif ++ ++void get_io_perms(void) ++{ ++#if defined (__sun) && (defined(__i386) || defined(__amd64)) ++ if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) { ++#elif defined(__FreeBSD__) || defined (__DragonFly__) ++ if ((io_fd = open("/dev/io", O_RDWR)) < 0) { ++#else ++ if (iopl(3) != 0) { ++#endif ++ fprintf(stderr, "ERROR: Could not get I/O privileges (%s).\n" ++ "You need to be root.\n", strerror(errno)); ++ exit(1); ++ } ++} ++ ++void release_io_perms(void) ++{ ++#if defined(__FreeBSD__) || defined(__DragonFly__) ++ close(io_fd); ++#endif ++} ++ ++void mmio_writeb(uint8_t val, void *addr) ++{ ++ *(volatile uint8_t *) addr = val; ++} ++ ++void mmio_writew(uint16_t val, void *addr) ++{ ++ *(volatile uint16_t *) addr = val; ++} ++ ++void mmio_writel(uint32_t val, void *addr) ++{ ++ *(volatile uint32_t *) addr = val; ++} ++ ++uint8_t mmio_readb(void *addr) ++{ ++ return *(volatile uint8_t *) addr; ++} ++ ++uint16_t mmio_readw(void *addr) ++{ ++ return *(volatile uint16_t *) addr; ++} ++ ++uint32_t mmio_readl(void *addr) ++{ ++ return *(volatile uint32_t *) addr; ++} diff --git a/hwaccess.h b/hwaccess.h new file mode 100644 -index 0000000..0729226 +index 0000000..89469b0 --- /dev/null +++ b/hwaccess.h -@@ -0,0 +1,156 @@ +@@ -0,0 +1,152 @@ +/* + * This file is part of the flashrom project. + * @@ -12899,10 +13878,6 @@ index 0000000..0729226 + #endif +#endif + -+#if defined(__FreeBSD__) || defined(__DragonFly__) -+extern int io_fd; -+#endif -+ +#if !defined(__DARWIN__) && !defined(__FreeBSD__) && !defined(__DragonFly__) +typedef struct { uint32_t hi, lo; } msr_t; +msr_t rdmsr(int addr); @@ -12921,11 +13896,22 @@ index 0000000..0729226 + +#endif /* !__HWACCESS_H__ */ diff --git a/ichspi.c b/ichspi.c -index 831dd9d..a6bf154 100644 +index 831dd9d..9ab61ff 100644 --- a/ichspi.c +++ b/ichspi.c -@@ -36,6 +36,17 @@ +@@ -5,6 +5,7 @@ + * Copyright (C) 2008 Claus Gindhart + * Copyright (C) 2008 Dominik Geyer + * Copyright (C) 2008 coresystems GmbH ++ * Copyright (C) 2009 Carl-Daniel Hailfinger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -34,8 +35,20 @@ + + #include #include "flash.h" ++#include "chipdrivers.h" #include "spi.h" +/* Change this to #define if you want lowlevel debugging of commands @@ -12942,7 +13928,79 @@ index 831dd9d..a6bf154 100644 /* ICH9 controller register definition */ #define ICH9_REG_FADDR 0x08 /* 32 Bits */ #define ICH9_REG_FDATA0 0x10 /* 64 Bytes */ -@@ -216,7 +227,7 @@ static int generate_opcodes(OPCODES * op) +@@ -105,7 +118,7 @@ typedef struct _OPCODE { + uint8_t atomic; //Use preop: (0: none, 1: preop0, 2: preop1 + } OPCODE; + +-/* Opcode definition: ++/* Suggested opcode definition: + * Preop 1: Write Enable + * Preop 2: Write Status register enable + * +@@ -115,7 +128,7 @@ typedef struct _OPCODE { + * OP 3: Read Status register + * OP 4: Read ID + * OP 5: Write Status register +- * OP 6: chip private (read JDEC id) ++ * OP 6: chip private (read JEDEC id) + * OP 7: Chip erase + */ + typedef struct _OPCODES { +@@ -156,6 +169,7 @@ struct preop_opcode_pair { + uint8_t opcode; + }; + ++/* List of opcodes which need preopcodes and matching preopcodes. Unused. */ + struct preop_opcode_pair pops[] = { + {JEDEC_WREN, JEDEC_BYTE_PROGRAM}, + {JEDEC_WREN, JEDEC_SE}, /* sector erase */ +@@ -163,24 +177,30 @@ struct preop_opcode_pair pops[] = { + {JEDEC_WREN, JEDEC_BE_D8}, /* block erase */ + {JEDEC_WREN, JEDEC_CE_60}, /* chip erase */ + {JEDEC_WREN, JEDEC_CE_C7}, /* chip erase */ ++ /* FIXME: WRSR requires either EWSR or WREN depending on chip type. */ ++ {JEDEC_WREN, JEDEC_WRSR}, + {JEDEC_EWSR, JEDEC_WRSR}, + {0,} + }; + ++/* Reasonable default configuration. Needs ad-hoc modifications if we ++ * encounter unlisted opcodes. Fun. ++ */ + OPCODES O_ST_M25P = { + { + JEDEC_WREN, +- 0}, ++ JEDEC_EWSR, ++ }, + { +- {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 1}, // Write Byte ++ {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Write Byte + {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Data +- {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 1}, // Erase Sector ++ {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Erase Sector + {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read Device Status Reg + {JEDEC_REMS, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Electronic Manufacturer Signature +- {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 1}, // Write Status Register ++ {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Write Status Register + {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read JDEC ID +- {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 1}, // Bulk erase +- } ++ {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Bulk erase ++ } + }; + + OPCODES O_EXISTING = {}; +@@ -209,14 +229,15 @@ static int find_preop(OPCODES *op, uint8_t preop) + return -1; + } + ++/* Create a struct OPCODES based on what we find in the locked down chipset. */ + static int generate_opcodes(OPCODES * op) + { +- int a, b, i; ++ int a; + uint16_t preop, optype; uint32_t opmenu[2]; if (op == NULL) { @@ -12951,7 +14009,7 @@ index 831dd9d..a6bf154 100644 return -1; } -@@ -235,7 +246,7 @@ static int generate_opcodes(OPCODES * op) +@@ -235,7 +256,7 @@ static int generate_opcodes(OPCODES * op) opmenu[1] = REGREAD32(ICH9_REG_OPMENU + 4); break; default: @@ -12960,7 +14018,27 @@ index 831dd9d..a6bf154 100644 return -1; } -@@ -317,7 +328,7 @@ int program_opcodes(OPCODES * op) +@@ -257,17 +278,10 @@ static int generate_opcodes(OPCODES * op) + opmenu[1] >>= 8; + } + +- /* atomic (link opcode with required pre-op) */ +- for (a = 4; a < 8; a++) ++ /* No preopcodes used by default. */ ++ for (a = 0; a < 8; a++) + op->opcode[a].atomic = 0; + +- for (i = 0; pops[i].opcode; i++) { +- a = find_opcode(op, pops[i].opcode); +- b = find_preop(op, pops[i].preop); +- if ((a != -1) && (b != -1)) +- op->opcode[a].atomic = (uint8_t) ++b; +- } +- + return 0; + } + +@@ -317,7 +331,7 @@ int program_opcodes(OPCODES * op) REGWRITE32(ICH9_REG_OPMENU + 4, opmenu[1]); break; default: @@ -12969,8 +14047,81 @@ index 831dd9d..a6bf154 100644 return -1; } -@@ -610,7 +621,7 @@ static int run_opcode(OPCODE op, uint32_t offset, +@@ -431,14 +445,15 @@ static int ich7_run_opcode(OPCODE op, uint32_t offset, + temp16 |= ((uint16_t) (opcode_index & 0x07)) << 4; + + /* Handle Atomic */ +- if (op.atomic != 0) { +- /* Select atomic command */ ++ switch (op.atomic) { ++ case 2: ++ /* Select second preop. */ ++ temp16 |= SPIC_SPOP; ++ /* And fall through. */ ++ case 1: ++ /* Atomic command (preop+op) */ + temp16 |= SPIC_ACS; +- /* Select prefix opcode */ +- if ((op.atomic - 1) == 1) { +- /*Select prefix opcode 2 */ +- temp16 |= SPIC_SPOP; +- } ++ break; + } + + /* Start */ +@@ -548,14 +563,15 @@ static int ich9_run_opcode(OPCODE op, uint32_t offset, + temp32 |= ((uint32_t) (opcode_index & 0x07)) << (8 + 4); + + /* Handle Atomic */ +- if (op.atomic != 0) { +- /* Select atomic command */ ++ switch (op.atomic) { ++ case 2: ++ /* Select second preop. */ ++ temp32 |= SSFC_SPOP; ++ /* And fall through. */ ++ case 1: ++ /* Atomic command (preop+op) */ + temp32 |= SSFC_ACS; +- /* Selct prefix opcode */ +- if ((op.atomic - 1) == 1) { +- /*Select prefix opcode 2 */ +- temp32 |= SSFC_SPOP; +- } ++ break; + } + + /* Start */ +@@ -598,19 +614,31 @@ static int run_opcode(OPCODE op, uint32_t offset, + { + switch (spi_controller) { + case SPI_CONTROLLER_VIA: +- if (datalength > 16) ++ if (datalength > 16) { ++ fprintf(stderr, "%s: Internal command size error for " ++ "opcode 0x%02x, got datalength=%i, want <=16\n", ++ __func__, op.opcode, datalength); return SPI_INVALID_LENGTH; ++ } + return ich7_run_opcode(op, offset, datalength, data, 16); + case SPI_CONTROLLER_ICH7: +- if (datalength > 64) ++ if (datalength > 64) { ++ fprintf(stderr, "%s: Internal command size error for " ++ "opcode 0x%02x, got datalength=%i, want <=16\n", ++ __func__, op.opcode, datalength); + return SPI_INVALID_LENGTH; ++ } + return ich7_run_opcode(op, offset, datalength, data, 64); + case SPI_CONTROLLER_ICH9: +- if (datalength > 64) ++ if (datalength > 64) { ++ fprintf(stderr, "%s: Internal command size error for " ++ "opcode 0x%02x, got datalength=%i, want <=16\n", ++ __func__, op.opcode, datalength); + return SPI_INVALID_LENGTH; ++ } return ich9_run_opcode(op, offset, datalength, data); default: - printf_debug("%s: unsupported chipset\n", __FUNCTION__); @@ -12978,7 +14129,7 @@ index 831dd9d..a6bf154 100644 } /* If we ever get here, something really weird happened */ -@@ -624,7 +635,7 @@ static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes, +@@ -624,7 +652,7 @@ static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes, uint32_t remaining = page_size; int towrite; @@ -12987,7 +14138,7 @@ index 831dd9d..a6bf154 100644 offset, page_size, bytes); for (; remaining > 0; remaining -= towrite) { -@@ -658,20 +669,16 @@ int ich_spi_write_256(struct flashchip *flash, uint8_t * buf) +@@ -658,20 +686,16 @@ int ich_spi_write_256(struct flashchip *flash, uint8_t * buf) int maxdata = 64; spi_disable_blockprotect(); @@ -13015,7 +14166,78 @@ index 831dd9d..a6bf154 100644 if (spi_controller == SPI_CONTROLLER_VIA) maxdata = 16; -@@ -742,22 +749,26 @@ int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -690,7 +714,6 @@ int ich_spi_write_256(struct flashchip *flash, uint8_t * buf) + int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr) + { +- int a; + int result; + int opcode_index = -1; + const unsigned char cmd = *writearr; +@@ -700,21 +723,54 @@ int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt, + int count; + + /* find cmd in opcodes-table */ +- for (a = 0; a < 8; a++) { +- if ((curopcodes->opcode[a]).opcode == cmd) { +- opcode_index = a; +- break; +- } +- } +- +- /* unknown / not programmed command */ ++ opcode_index = find_opcode(curopcodes, cmd); + if (opcode_index == -1) { ++ /* FIXME: Reprogram opcodes if possible. Autodetect type of ++ * opcode by checking readcnt/writecnt. ++ */ + printf_debug("Invalid OPCODE 0x%02x\n", cmd); + return SPI_INVALID_OPCODE; + } + + opcode = &(curopcodes->opcode[opcode_index]); + ++ /* The following valid writecnt/readcnt combinations exist: ++ * writecnt = 4, readcnt >= 0 ++ * writecnt = 1, readcnt >= 0 ++ * writecnt >= 4, readcnt = 0 ++ * writecnt >= 1, readcnt = 0 ++ * writecnt >= 1 is guaranteed for all commands. ++ */ ++ if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS) && ++ (writecnt != 4)) { ++ fprintf(stderr, "%s: Internal command size error for opcode " ++ "0x%02x, got writecnt=%i, want =4\n", __func__, cmd, ++ writecnt); ++ return SPI_INVALID_LENGTH; ++ } ++ if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_NO_ADDRESS) && ++ (writecnt != 1)) { ++ fprintf(stderr, "%s: Internal command size error for opcode " ++ "0x%02x, got writecnt=%i, want =1\n", __func__, cmd, ++ writecnt); ++ return SPI_INVALID_LENGTH; ++ } ++ if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) && ++ (writecnt < 4)) { ++ fprintf(stderr, "%s: Internal command size error for opcode " ++ "0x%02x, got writecnt=%i, want >=4\n", __func__, cmd, ++ writecnt); ++ return SPI_INVALID_LENGTH; ++ } ++ if (((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) || ++ (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)) && ++ (readcnt)) { ++ fprintf(stderr, "%s: Internal command size error for opcode " ++ "0x%02x, got readcnt=%i, want =0\n", __func__, cmd, ++ readcnt); ++ return SPI_INVALID_LENGTH; ++ } ++ + /* if opcode-type requires an address */ + if (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS || + opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) { +@@ -742,22 +798,72 @@ int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt, return result; } @@ -13034,41 +14256,90 @@ index 831dd9d..a6bf154 100644 - printf_debug(" due to SPI master limitation, ignoring" - " and hoping it will be run as PREOP\n"); - ret = 0; -- } -- spicommands++; ++ int i; + int oppos, preoppos; + for (; (cmds->writecnt || cmds->readcnt) && !ret; cmds++) { -+ /* Is the next command valid or a terminator? */ + if ((cmds + 1)->writecnt || (cmds + 1)->readcnt) { ++ /* Next command is valid. */ + preoppos = find_preop(curopcodes, cmds->writearr[0]); + oppos = find_opcode(curopcodes, (cmds + 1)->writearr[0]); -+ /* Is the opcode of the current command listed in the -+ * ICH struct OPCODES as associated preopcode for the -+ * opcode of the next command? -+ */ -+ if ((oppos != -1) && (preoppos != -1) && -+ ((curopcodes->opcode[oppos].atomic - 1) == preoppos)) ++ if ((oppos == -1) && (preoppos != -1)) { ++ /* Current command is listed as preopcode in ++ * ICH struct OPCODES, but next command is not ++ * listed as opcode in that struct. ++ * Check for command sanity, then ++ * try to reprogram the ICH opcode list. ++ */ ++ if (find_preop(curopcodes, ++ (cmds + 1)->writearr[0]) != -1) { ++ fprintf(stderr, "%s: Two subsequent " ++ "preopcodes 0x%02x and 0x%02x, " ++ "ignoring the first.\n", ++ __func__, cmds->writearr[0], ++ (cmds + 1)->writearr[0]); ++ continue; ++ } ++ /* If the chipset is locked down, we'll fail ++ * during execution of the next command anyway. ++ * No need to bother with fixups. ++ */ ++ if (!ichspi_lock) { ++ printf_debug("%s: FIXME: Add on-the-fly" ++ " reprogramming of the " ++ "chipset opcode list.\n", ++ __func__); ++ /* FIXME: Reprogram opcode menu. ++ * Find a less-useful opcode, replace it ++ * with the wanted opcode, detect optype ++ * and reprogram the opcode menu. ++ * Update oppos so the next if-statement ++ * can do something useful. ++ */ ++ //curopcodes.opcode[lessusefulindex] = (cmds + 1)->writearr[0]); ++ //update_optypes(curopcodes); ++ //program_opcodes(curopcodes); ++ //oppos = find_opcode(curopcodes, (cmds + 1)->writearr[0]); ++ continue; ++ } ++ } ++ if ((oppos != -1) && (preoppos != -1)) { ++ /* Current command is listed as preopcode in ++ * ICH struct OPCODES and next command is listed ++ * as opcode in that struct. Match them up. ++ */ ++ curopcodes->opcode[oppos].atomic = preoppos + 1; + continue; -+ } -+ ++ } ++ /* If none of the above if-statements about oppos or ++ * preoppos matched, this is a normal opcode. ++ */ + } +- spicommands++; + ret = ich_spi_send_command(cmds->writecnt, cmds->readcnt, + cmds->writearr, cmds->readarr); ++ /* Reset the type of all opcodes to non-atomic. */ ++ for (i = 0; i < 8; i++) ++ curopcodes->opcode[i].atomic = 0; } return ret; } diff --git a/internal.c b/internal.c -index a3b2ae5..935240d 100644 +index a3b2ae5..0afed72 100644 --- a/internal.c +++ b/internal.c -@@ -31,6 +31,7 @@ - int io_fd; - #endif +@@ -27,10 +27,7 @@ + #include + #include "flash.h" +-#if defined(__FreeBSD__) || defined(__DragonFly__) +-int io_fd; +-#endif +- +#if NEED_PCI == 1 struct pci_dev *pci_dev_find_filter(struct pci_filter filter) { struct pci_dev *temp; -@@ -42,6 +43,26 @@ struct pci_dev *pci_dev_find_filter(struct pci_filter filter) +@@ -42,6 +39,26 @@ struct pci_dev *pci_dev_find_filter(struct pci_filter filter) return NULL; } @@ -13095,34 +14366,71 @@ index a3b2ae5..935240d 100644 struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device) { struct pci_dev *temp; -@@ -79,6 +100,7 @@ struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device, +@@ -79,33 +96,46 @@ struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device, return NULL; } -+#endif - - void get_io_perms(void) - { -@@ -102,6 +124,18 @@ void release_io_perms(void) +- +-void get_io_perms(void) +-{ +-#if defined (__sun) && (defined(__i386) || defined(__amd64)) +- if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) { +-#elif defined(__FreeBSD__) || defined (__DragonFly__) +- if ((io_fd = open("/dev/io", O_RDWR)) < 0) { +-#else +- if (iopl(3) != 0) { #endif - } +- fprintf(stderr, "ERROR: Could not get I/O privileges (%s).\n" +- "You need to be root.\n", strerror(errno)); +- exit(1); +- } +-} +-void release_io_perms(void) +#if INTERNAL_SUPPORT == 1 +struct superio superio = {}; ++int force_boardenable = 0; + +void probe_superio(void) -+{ + { +-#if defined(__FreeBSD__) || defined(__DragonFly__) +- close(io_fd); + superio = probe_superio_ite(); +#if 0 /* Winbond SuperI/O code is not yet available. */ + if (superio.vendor == SUPERIO_VENDOR_NONE) + superio = probe_superio_winbond(); -+#endif -+} + #endif + } + ++int is_laptop; + int internal_init(void) { int ret = 0; -@@ -118,6 +152,10 @@ int internal_init(void) + ++ if (programmer_param && !strlen(programmer_param)) { ++ free(programmer_param); ++ programmer_param = NULL; ++ } ++ if (programmer_param) { ++ char *arg; ++ arg = extract_param(&programmer_param, "boardenable=", ",:"); ++ if (arg && !strcmp(arg,"force")) ++ force_boardenable = 1; ++ else if (arg) ++ msg_perr("Unknown argument for boardenable: %s\n", arg); ++ free(arg); ++ ++ if (strlen(programmer_param)) ++ msg_perr("Unhandled programmer parameters: %s\n", ++ programmer_param); ++ free(programmer_param); ++ programmer_param = NULL; ++ } + get_io_perms(); + + /* Initialize PCI access for flash enables */ +@@ -118,6 +148,20 @@ int internal_init(void) * mainboard specific flash enable sequence. */ coreboot_init(); @@ -13130,10 +14438,20 @@ index a3b2ae5..935240d 100644 + + /* Probe for the SuperI/O chip and fill global struct superio. */ + probe_superio(); ++ ++ /* Warn if a laptop is detected */ ++ if (is_laptop) ++ printf("========================================================================\n" ++ "WARNING! You seem to be running flashrom on a laptop.\n" ++ "Laptops, notebooks and netbooks are difficult to support and we recommend\n" ++ "to use the vendor flashing utility. The embedded controller (EC) in these\n" ++ "machines often interacts badly with flashing\n" ++ "See http://www.flashrom.org/Laptops\n" ++ "========================================================================\n"); /* try to enable it. Failure IS an option, since not all motherboards * really need this to be done, etc., etc. -@@ -143,6 +181,7 @@ int internal_shutdown(void) +@@ -143,6 +187,7 @@ int internal_shutdown(void) return 0; } @@ -13141,11 +14459,41 @@ index a3b2ae5..935240d 100644 void internal_chip_writeb(uint8_t val, chipaddr addr) { -@@ -209,85 +248,3 @@ uint32_t mmio_readl(void *addr) - { - return *(volatile uint32_t *) addr; +@@ -179,115 +224,3 @@ void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len) + memcpy(buf, (void *)addr, len); + return; } - +-void mmio_writeb(uint8_t val, void *addr) +-{ +- *(volatile uint8_t *) addr = val; +-} +- +-void mmio_writew(uint16_t val, void *addr) +-{ +- *(volatile uint16_t *) addr = val; +-} +- +-void mmio_writel(uint32_t val, void *addr) +-{ +- *(volatile uint32_t *) addr = val; +-} +- +-uint8_t mmio_readb(void *addr) +-{ +- return *(volatile uint8_t *) addr; +-} +- +-uint16_t mmio_readw(void *addr) +-{ +- return *(volatile uint16_t *) addr; +-} +- +-uint32_t mmio_readl(void *addr) +-{ +- return *(volatile uint32_t *) addr; +-} +- -void internal_delay(int usecs) -{ - /* If the delay is >1 s, use usleep because timing does not need to @@ -13228,10 +14576,18 @@ index a3b2ae5..935240d 100644 - return; -} diff --git a/it87spi.c b/it87spi.c -index 299725c..fcbf086 100644 +index 299725c..ed72c90 100644 --- a/it87spi.c +++ b/it87spi.c -@@ -54,46 +54,82 @@ void exit_conf_mode_ite(uint16_t port) +@@ -26,6 +26,7 @@ + #include + #include + #include "flash.h" ++#include "chipdrivers.h" + #include "spi.h" + + #define ITE_SUPERIO_PORT1 0x2e +@@ -54,46 +55,82 @@ void exit_conf_mode_ite(uint16_t port) sio_write(port, 0x02, 0x02); } @@ -13329,7 +14685,7 @@ index 299725c..fcbf086 100644 if (programmer_param && !strlen(programmer_param)) { free(programmer_param); programmer_param = NULL; -@@ -101,21 +137,25 @@ static uint16_t find_ite_spi_flash_port(uint16_t port) +@@ -101,21 +138,25 @@ static uint16_t find_ite_spi_flash_port(uint16_t port) if (programmer_param && (portpos = strstr(programmer_param, "port="))) { portpos += 5; flashport = strtol(portpos, (char **)NULL, 0); @@ -13360,7 +14716,7 @@ index 299725c..fcbf086 100644 if (it8716f_flashport) spi_controller = SPI_CONTROLLER_IT87XX; -@@ -129,6 +169,8 @@ int it87spi_init(void) +@@ -129,6 +170,8 @@ int it87spi_init(void) int ret; get_io_perms(); @@ -13369,7 +14725,7 @@ index 299725c..fcbf086 100644 ret = it87spi_common_init(); if (!ret) { buses_supported = CHIP_BUSTYPE_SPI; -@@ -167,8 +209,8 @@ int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -167,8 +210,8 @@ int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt, busy = INB(it8716f_flashport) & 0x80; } while (busy); if (readcnt > 3) { @@ -13380,7 +14736,7 @@ index 299725c..fcbf086 100644 return SPI_INVALID_LENGTH; } switch (writecnt) { -@@ -197,8 +239,8 @@ int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -197,8 +240,8 @@ int it8716f_spi_send_command(unsigned int writecnt, unsigned int readcnt, writeenc = 0x3; break; default: @@ -13391,7 +14747,7 @@ index 299725c..fcbf086 100644 return SPI_INVALID_LENGTH; } /* -@@ -278,12 +320,12 @@ int it8716f_spi_chip_write_256(struct flashchip *flash, uint8_t *buf) +@@ -278,12 +321,12 @@ int it8716f_spi_chip_write_256(struct flashchip *flash, uint8_t *buf) } else { spi_disable_blockprotect(); /* Erase first */ @@ -13409,7 +14765,7 @@ index 299725c..fcbf086 100644 it8716f_spi_page_program(flash, i, buf); } diff --git a/jedec.c b/jedec.c -index 0e426d6..055e910 100644 +index 0e426d6..fee7302 100644 --- a/jedec.c +++ b/jedec.c @@ -5,6 +5,7 @@ @@ -13420,8 +14776,11 @@ index 0e426d6..055e910 100644 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -@@ -24,6 +25,9 @@ +@@ -22,8 +23,12 @@ + */ + #include "flash.h" ++#include "chipdrivers.h" #define MAX_REFLASH_TRIES 0x10 +#define MASK_FULL 0xffff @@ -13430,7 +14789,7 @@ index 0e426d6..055e910 100644 /* Check one byte for odd parity */ uint8_t oddparity(uint8_t val) -@@ -33,7 +37,7 @@ uint8_t oddparity(uint8_t val) +@@ -33,7 +38,7 @@ uint8_t oddparity(uint8_t val) return (val ^ (val >> 1)) & 0x1; } @@ -13439,7 +14798,7 @@ index 0e426d6..055e910 100644 { unsigned int i = 0; uint8_t tmp1, tmp2; -@@ -41,12 +45,33 @@ void toggle_ready_jedec(chipaddr dst) +@@ -41,12 +46,33 @@ void toggle_ready_jedec(chipaddr dst) tmp1 = chip_readb(dst) & 0x40; while (i++ < 0xFFFFFFF) { @@ -13473,7 +14832,7 @@ index 0e426d6..055e910 100644 } void data_polling_jedec(chipaddr dst, uint8_t data) -@@ -62,30 +87,19 @@ void data_polling_jedec(chipaddr dst, uint8_t data) +@@ -62,30 +88,19 @@ void data_polling_jedec(chipaddr dst, uint8_t data) break; } } @@ -13512,7 +14871,7 @@ index 0e426d6..055e910 100644 { chipaddr bios = flash->virtual_memory; uint8_t id1, id2; -@@ -109,15 +123,15 @@ int probe_jedec(struct flashchip *flash) +@@ -109,15 +124,15 @@ int probe_jedec(struct flashchip *flash) } /* Issue JEDEC Product ID Entry command */ @@ -13537,7 +14896,7 @@ index 0e426d6..055e910 100644 /* Read product ID */ id1 = chip_readb(bios); -@@ -138,14 +152,20 @@ int probe_jedec(struct flashchip *flash) +@@ -138,14 +153,20 @@ int probe_jedec(struct flashchip *flash) } /* Issue JEDEC Product ID Exit command */ @@ -13565,7 +14924,7 @@ index 0e426d6..055e910 100644 if (!oddparity(id1)) printf_debug(", id1 parity violation"); -@@ -169,33 +189,37 @@ int probe_jedec(struct flashchip *flash) +@@ -169,33 +190,37 @@ int probe_jedec(struct flashchip *flash) printf_debug(", id2 is normal flash content"); printf_debug("\n"); @@ -13613,7 +14972,7 @@ index 0e426d6..055e910 100644 if (check_erased_range(flash, page, pagesize)) { fprintf(stderr,"ERASE FAILED!\n"); -@@ -204,27 +228,28 @@ int erase_sector_jedec(struct flashchip *flash, unsigned int page, int pagesize) +@@ -204,27 +229,28 @@ int erase_sector_jedec(struct flashchip *flash, unsigned int page, int pagesize) return 0; } @@ -13649,7 +15008,7 @@ index 0e426d6..055e910 100644 if (check_erased_range(flash, block, blocksize)) { fprintf(stderr,"ERASE FAILED!\n"); -@@ -233,27 +258,27 @@ int erase_block_jedec(struct flashchip *flash, unsigned int block, int blocksize +@@ -233,27 +259,27 @@ int erase_block_jedec(struct flashchip *flash, unsigned int block, int blocksize return 0; } @@ -13685,7 +15044,7 @@ index 0e426d6..055e910 100644 if (check_erased_range(flash, 0, total_size)) { fprintf(stderr,"ERASE FAILED!\n"); -@@ -262,23 +287,68 @@ int erase_chip_jedec(struct flashchip *flash) +@@ -262,23 +288,68 @@ int erase_chip_jedec(struct flashchip *flash) return 0; } @@ -13762,7 +15121,7 @@ index 0e426d6..055e910 100644 /* If the data is 0xFF, don't program it */ if (*src != 0xFF) chip_writeb(*src, dst); -@@ -290,68 +360,46 @@ retry: +@@ -290,68 +361,46 @@ retry: dst = d; src = s; @@ -13855,7 +15214,7 @@ index 0e426d6..055e910 100644 if (erase_chip_jedec(flash)) { fprintf(stderr,"ERASE FAILED!\n"); -@@ -361,12 +409,89 @@ int write_jedec(struct flashchip *flash, uint8_t *buf) +@@ -361,12 +410,89 @@ int write_jedec(struct flashchip *flash, uint8_t *buf) printf("Programming page: "); for (i = 0; i < total_size / page_size; i++) { printf("%04d at address: 0x%08x", i, i * page_size); @@ -13980,32 +15339,146 @@ index c432ebe..26b7c6a 100644 int read_romlayout(char *name) { diff --git a/m29f002.c b/m29f002.c -index 00cbbc1..01a7a50 100644 +deleted file mode 100644 +index 00cbbc1..0000000 --- a/m29f002.c -+++ b/m29f002.c -@@ -45,6 +45,7 @@ static int rewrite_block(struct flashchip *flash, uint8_t *src, - chipaddr dst = bios + start; - - /* erase */ -+ /* FIXME: use erase_sector_jedec? */ - chip_writeb(0xaa, bios + 0x555); - chip_writeb(0x55, bios + 0xaaa); - chip_writeb(0x80, bios + 0x555); -@@ -59,6 +60,7 @@ static int rewrite_block(struct flashchip *flash, uint8_t *src, - } - - /* program */ -+ /* FIXME: use write_sector_jedec? */ - while (size--) { - chip_writeb(0xaa, bios + 0x555); - chip_writeb(0x55, bios + 0xaaa); ++++ /dev/null +@@ -1,126 +0,0 @@ +-/* +- * This file is part of the flashrom project. +- * +- * Copyright (C) 2009 Peter Stuge +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ +- +-#include "flash.h" +- +-int erase_m29f002(struct flashchip *flash) +-{ +- chipaddr bios = flash->virtual_memory; +- chip_writeb(0xaa, bios + 0x555); +- chip_writeb(0x55, bios + 0xaaa); +- chip_writeb(0x80, bios + 0x555); +- chip_writeb(0xaa, bios + 0x555); +- chip_writeb(0x55, bios + 0xaaa); +- chip_writeb(0x10, bios + 0x555); +- programmer_delay(10); +- toggle_ready_jedec(bios); +- if (check_erased_range(flash, 0, flash->total_size * 1024)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- return 0; +-} +- +-static int rewrite_block(struct flashchip *flash, uint8_t *src, +- unsigned long start, int size) +-{ +- chipaddr bios = flash->virtual_memory; +- chipaddr dst = bios + start; +- +- /* erase */ +- chip_writeb(0xaa, bios + 0x555); +- chip_writeb(0x55, bios + 0xaaa); +- chip_writeb(0x80, bios + 0x555); +- chip_writeb(0xaa, bios + 0x555); +- chip_writeb(0x55, bios + 0xaaa); +- chip_writeb(0x30, dst); +- programmer_delay(10); +- toggle_ready_jedec(bios); +- if (check_erased_range(flash, start, size)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- +- /* program */ +- while (size--) { +- chip_writeb(0xaa, bios + 0x555); +- chip_writeb(0x55, bios + 0xaaa); +- chip_writeb(0xa0, bios + 0x555); +- chip_writeb(*src, dst); +- toggle_ready_jedec(dst); +- dst++; +- src++; +- } +- return 0; +-} +- +-static int do_block(struct flashchip *flash, uint8_t *src, int i, +- unsigned long start, int size) +-{ +- int ret; +- printf("%d at address: 0x%08lx", i, start); +- ret = rewrite_block(flash, src + start, start, size); +- if (ret) +- return ret; +- printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); +- return 0; +-} +- +-int write_m29f002t(struct flashchip *flash, uint8_t *buf) +-{ +- int i, page_size = flash->page_size; +- +- /* M29F002(N)T has 7 blocks. From bottom to top their sizes are: +- * 64k 64k 64k 32k 8k 8k 16k +- * flash->page_size is set to 64k in flashchips.c +- */ +- +- printf("Programming block: "); +- for (i = 0; i < 3; i++) +- do_block(flash, buf, i, i * page_size, page_size); +- do_block(flash, buf, i++, 0x30000, 32 * 1024); +- do_block(flash, buf, i++, 0x38000, 8 * 1024); +- do_block(flash, buf, i++, 0x3a000, 8 * 1024); +- do_block(flash, buf, i, 0x3c000, 16 * 1024); +- +- printf("\n"); +- return 0; +-} +- +-int write_m29f002b(struct flashchip *flash, uint8_t *buf) +-{ +- int i = 0, page_size = flash->page_size; +- +- /* M29F002B has 7 blocks. From bottom to top their sizes are: +- * 16k 8k 8k 32k 64k 64k 64k +- * flash->page_size is set to 64k in flashchips.c +- */ +- +- printf("Programming block: "); +- do_block(flash, buf, i++, 0x00000, 16 * 1024); +- do_block(flash, buf, i++, 0x04000, 8 * 1024); +- do_block(flash, buf, i++, 0x06000, 8 * 1024); +- do_block(flash, buf, i++, 0x08000, 32 * 1024); +- for (; i < 7; i++) +- do_block(flash, buf, i, (i - 3) * page_size, page_size); +- +- printf("\n"); +- return 0; +-} diff --git a/m29f400bt.c b/m29f400bt.c -index ace6dae..e77572a 100644 +index ace6dae..c394074 100644 --- a/m29f400bt.c +++ b/m29f400bt.c -@@ -20,14 +20,11 @@ +@@ -19,15 +19,13 @@ + */ #include "flash.h" ++#include "chipdrivers.h" -void protect_m29f400bt(chipaddr bios) -{ @@ -14023,7 +15496,7 @@ index ace6dae..e77572a 100644 void write_page_m29f400bt(chipaddr bios, uint8_t *src, chipaddr dst, int page_size) -@@ -75,7 +72,7 @@ int probe_m29f400bt(struct flashchip *flash) +@@ -75,7 +73,7 @@ int probe_m29f400bt(struct flashchip *flash) programmer_delay(10); @@ -14032,7 +15505,7 @@ index ace6dae..e77572a 100644 if (id1 == flash->manufacture_id && id2 == flash->model_id) return 1; -@@ -105,7 +102,7 @@ int erase_m29f400bt(struct flashchip *flash) +@@ -105,7 +103,7 @@ int erase_m29f400bt(struct flashchip *flash) return 0; } @@ -14041,7 +15514,7 @@ index ace6dae..e77572a 100644 { chipaddr bios = flash->virtual_memory; chipaddr dst = bios + start; -@@ -129,6 +126,16 @@ int block_erase_m29f400bt(struct flashchip *flash, int start, int len) +@@ -129,6 +127,16 @@ int block_erase_m29f400bt(struct flashchip *flash, int start, int len) return 0; } @@ -14058,7 +15531,7 @@ index ace6dae..e77572a 100644 int write_m29f400bt(struct flashchip *flash, uint8_t *buf) { int i; -@@ -194,7 +201,6 @@ int write_m29f400bt(struct flashchip *flash, uint8_t *buf) +@@ -194,7 +202,6 @@ int write_m29f400bt(struct flashchip *flash, uint8_t *buf) write_page_m29f400bt(bios, buf + 0x7c000, bios + 0x7c000, 16 * 1024); printf("\n"); @@ -14066,7 +15539,7 @@ index ace6dae..e77572a 100644 return 0; } -@@ -248,7 +254,6 @@ int write_coreboot_m29f400bt(struct flashchip *flash, uint8_t *buf) +@@ -248,7 +255,6 @@ int write_coreboot_m29f400bt(struct flashchip *flash, uint8_t *buf) write_page_m29f400bt(bios, buf + 0x30000, bios + 0x30000, 64 * 1024); printf("\n"); @@ -14075,89 +15548,91 @@ index ace6dae..e77572a 100644 return 0; } diff --git a/mx29f002.c b/mx29f002.c -index d5c6041..411e539 100644 +deleted file mode 100644 +index d5c6041..0000000 --- a/mx29f002.c -+++ b/mx29f002.c -@@ -36,65 +36,67 @@ int probe_29f002(struct flashchip *flash) - - programmer_delay(10); - ++++ /dev/null +@@ -1,100 +0,0 @@ +-/* +- * This file is part of the flashrom project. +- * +- * Copyright (C) 2000 Silicon Integrated System Corporation +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ +- +-#include "flash.h" +- +-int probe_29f002(struct flashchip *flash) +-{ +- chipaddr bios = flash->virtual_memory; +- uint8_t id1, id2; +- +- chip_writeb(0xAA, bios + 0x5555); +- chip_writeb(0x55, bios + 0x2AAA); +- chip_writeb(0x90, bios + 0x5555); +- +- id1 = chip_readb(bios); +- id2 = chip_readb(bios + 0x01); +- +- chip_writeb(0xF0, bios); +- +- programmer_delay(10); +- - printf_debug("%s: id1 0x%02x, id2 0x%02x\n", __FUNCTION__, id1, id2); -+ printf_debug("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); - if (id1 == flash->manufacture_id && id2 == flash->model_id) - return 1; - - return 0; - } - +- if (id1 == flash->manufacture_id && id2 == flash->model_id) +- return 1; +- +- return 0; +-} +- -int erase_29f002(struct flashchip *flash) -+int erase_sector_29f002(struct flashchip *flash, unsigned int address, unsigned int blocklen) - { - chipaddr bios = flash->virtual_memory; - +-{ +- chipaddr bios = flash->virtual_memory; +- - chip_writeb(0xF0, bios + 0x555); - chip_writeb(0xAA, bios + 0x555); - chip_writeb(0x55, bios + 0x2AA); - chip_writeb(0x80, bios + 0x555); - chip_writeb(0xAA, bios + 0x555); - chip_writeb(0x55, bios + 0x2AA); +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0x2AA); +- chip_writeb(0x80, bios + 0x555); +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0x2AA); - chip_writeb(0x10, bios + 0x555); -+ chip_writeb(0x30, bios + address); - +- - programmer_delay(100); - toggle_ready_jedec(bios); -+ programmer_delay(10); - +- - if (check_erased_range(flash, 0, flash->total_size * 1024)) { -+ /* wait for Toggle bit ready */ -+ toggle_ready_jedec(bios + address); -+ -+ if (check_erased_range(flash, address, blocklen)) { - fprintf(stderr, "ERASE FAILED!\n"); - return -1; - } - return 0; - } - +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- return 0; +-} +- -int write_29f002(struct flashchip *flash, uint8_t *buf) -+int erase_chip_29f002(struct flashchip *flash, unsigned int addr, unsigned int blocklen) -+{ -+ if ((addr != 0) || (blocklen != flash->total_size * 1024)) { -+ fprintf(stderr, "%s called with incorrect arguments\n", -+ __func__); -+ return -1; -+ } -+ return erase_29f002(flash); -+} -+ -+/* FIXME: Use erase_chip_jedec? -+ * erase_29f002 uses shorter addresses, sends F0 (exit ID mode) and -+ * and has a bigger delay before polling the toggle bit */ -+int erase_29f002(struct flashchip *flash) - { +-{ - int i; - int total_size = flash->total_size * 1024; - chipaddr bios = flash->virtual_memory; +- chipaddr bios = flash->virtual_memory; - chipaddr dst = bios; - +- - chip_writeb(0xF0, bios); - programmer_delay(10); - if (erase_29f002(flash)) { -+ chip_writeb(0xF0, bios + 0x555); -+ chip_writeb(0xAA, bios + 0x555); -+ chip_writeb(0x55, bios + 0x2AA); -+ chip_writeb(0x80, bios + 0x555); -+ chip_writeb(0xAA, bios + 0x555); -+ chip_writeb(0x55, bios + 0x2AA); -+ chip_writeb(0x10, bios + 0x555); -+ -+ programmer_delay(100); -+ toggle_ready_jedec(bios); -+ -+ if (check_erased_range(flash, 0, flash->total_size * 1024)) { - fprintf(stderr, "ERASE FAILED!\n"); - return -1; - } +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } - printf("Programming page: "); - for (i = 0; i < total_size; i++) { - /* write to the sector */ @@ -14176,12 +15651,43 @@ index d5c6041..411e539 100644 - } - printf("\n"); - - return 0; - } +- return 0; +-} diff --git a/nic3com.c b/nic3com.c -index 075e760..a4878d2 100644 +index 075e760..d3dcce5 100644 --- a/nic3com.c +++ b/nic3com.c +@@ -36,20 +36,20 @@ uint16_t id; + + struct pcidev_status nics_3com[] = { + /* 3C90xB */ +- {0x10b7, 0x9055, PCI_OK, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-TX"}, +- {0x10b7, 0x9001, PCI_NT, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-T4" }, +- {0x10b7, 0x9004, PCI_OK, "3COM", "3C90xB: PCI 10BASE-T (TPO)" }, +- {0x10b7, 0x9005, PCI_NT, "3COM", "3C90xB: PCI 10BASE-T/10BASE2/AUI (COMBO)" }, +- {0x10b7, 0x9006, PCI_NT, "3COM", "3C90xB: PCI 10BASE-T/10BASE2 (TPC)" }, +- {0x10b7, 0x900a, PCI_NT, "3COM", "3C90xB: PCI 10BASE-FL" }, +- {0x10b7, 0x905a, PCI_NT, "3COM", "3C90xB: PCI 10BASE-FX" }, +- {0x10b7, 0x9058, PCI_OK, "3COM", "3C905B: Cyclone 10/100/BNC" }, ++ {0x10b7, 0x9055, OK, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-TX"}, ++ {0x10b7, 0x9001, NT, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-T4" }, ++ {0x10b7, 0x9004, OK, "3COM", "3C90xB: PCI 10BASE-T (TPO)" }, ++ {0x10b7, 0x9005, NT, "3COM", "3C90xB: PCI 10BASE-T/10BASE2/AUI (COMBO)" }, ++ {0x10b7, 0x9006, NT, "3COM", "3C90xB: PCI 10BASE-T/10BASE2 (TPC)" }, ++ {0x10b7, 0x900a, NT, "3COM", "3C90xB: PCI 10BASE-FL" }, ++ {0x10b7, 0x905a, NT, "3COM", "3C90xB: PCI 10BASE-FX" }, ++ {0x10b7, 0x9058, OK, "3COM", "3C905B: Cyclone 10/100/BNC" }, + + /* 3C905C */ +- {0x10b7, 0x9200, PCI_OK, "3COM", "3C905C: EtherLink 10/100 PCI (TX)" }, ++ {0x10b7, 0x9200, OK, "3COM", "3C905C: EtherLink 10/100 PCI (TX)" }, + + /* 3C980C */ +- {0x10b7, 0x9805, PCI_NT, "3COM", "3C980C: EtherLink Server 10/100 PCI (TX)" }, ++ {0x10b7, 0x9805, NT, "3COM", "3C980C: EtherLink Server 10/100 PCI (TX)" }, + + {}, + }; @@ -58,7 +58,8 @@ int nic3com_init(void) { get_io_perms(); @@ -14193,7 +15699,7 @@ index 075e760..a4878d2 100644 /* 3COM 3C90xB cards need a special fixup. */ diff --git a/pcidev.c b/pcidev.c -index 580ebae..6c92c0a 100644 +index 580ebae..fcb04e6 100644 --- a/pcidev.c +++ b/pcidev.c @@ -28,7 +28,8 @@ struct pci_access *pacc; @@ -14206,7 +15712,7 @@ index 580ebae..6c92c0a 100644 { int i; uint32_t addr; -@@ -37,12 +38,16 @@ uint32_t pcidev_validate(struct pci_dev *dev, struct pcidev_status *devs) +@@ -37,14 +38,18 @@ uint32_t pcidev_validate(struct pci_dev *dev, struct pcidev_status *devs) if (dev->device_id != devs[i].device_id) continue; @@ -14226,8 +15732,11 @@ index 580ebae..6c92c0a 100644 + dev->vendor_id, dev->device_id, dev->bus, dev->dev, + dev->func); - if (devs[i].status == PCI_NT) { +- if (devs[i].status == PCI_NT) { ++ if (devs[i].status == NT) { printf("===\nThis PCI device is UNTESTED. Please " + "report the 'flashrom -p xxxx' output \n" + "to flashrom@flashrom.org if it works " @@ -57,7 +62,8 @@ uint32_t pcidev_validate(struct pci_dev *dev, struct pcidev_status *devs) return 0; } @@ -14256,6 +15765,14 @@ index 580ebae..6c92c0a 100644 "to explicitly select the card with the given BDF " "(PCI bus, device, function).\n"); exit(1); +@@ -111,6 +117,6 @@ void print_supported_pcidevs(struct pcidev_status *devs) + printf("%s %s [%02x:%02x]%s\n", devs[i].vendor_name, + devs[i].device_name, devs[i].vendor_id, + devs[i].device_id, +- (devs[i].status == PCI_NT) ? " (untested)" : ""); ++ (devs[i].status == NT) ? " (untested)" : ""); + } + } diff --git a/physmap.c b/physmap.c index 778a783..fba7a53 100644 --- a/physmap.c @@ -14391,54 +15908,103 @@ index 778a783..fba7a53 100644 return msr; } diff --git a/pm29f002.c b/pm29f002.c -index a01df88..bf78d13 100644 +deleted file mode 100644 +index a01df88..0000000 --- a/pm29f002.c -+++ b/pm29f002.c -@@ -20,18 +20,20 @@ - - #include "flash.h" - -+/* if write_sector_jedec is used, -+ this is write_jedec_1 */ - int write_pm29f002(struct flashchip *flash, uint8_t *buf) - { - int i, total_size = flash->total_size * 1024; - chipaddr bios = flash->virtual_memory; - chipaddr dst = bios; - ++++ /dev/null +@@ -1,56 +0,0 @@ +-/* +- * This file is part of the flashrom project. +- * +- * Copyright (C) 2009 Uwe Hermann +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ +- +-#include "flash.h" +- +-int write_pm29f002(struct flashchip *flash, uint8_t *buf) +-{ +- int i, total_size = flash->total_size * 1024; +- chipaddr bios = flash->virtual_memory; +- chipaddr dst = bios; +- - /* Pm29F002T/B use the same erase method... */ - if (erase_29f040b(flash)) { -+ if (erase_flash(flash)) { - fprintf(stderr, "ERASE FAILED!\n"); - return -1; - } - -+ /* FIXME: use write_sector_jedec? */ - printf("Programming page: "); - for (i = 0; i < total_size; i++) { - if ((i & 0xfff) == 0) +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- +- printf("Programming page: "); +- for (i = 0; i < total_size; i++) { +- if ((i & 0xfff) == 0) +- printf("address: 0x%08lx", (unsigned long)i); +- +- /* Pm29F002T/B only support byte-wise programming. */ +- chip_writeb(0xAA, bios + 0x555); +- chip_writeb(0x55, bios + 0x2AA); +- chip_writeb(0xA0, bios + 0x555); +- chip_writeb(*buf++, dst++); +- +- /* Wait for Toggle bit ready. */ +- toggle_ready_jedec(dst); +- +- if ((i & 0xfff) == 0) +- printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); +- } +- +- printf("\n"); +- +- return 0; +-} diff --git a/pm49fl00x.c b/pm49fl00x.c -index 27a1163..9d104e2 100644 +index 27a1163..5e5eec8 100644 --- a/pm49fl00x.c +++ b/pm49fl00x.c -@@ -36,16 +36,6 @@ void write_lockbits_49fl00x(chipaddr bios, int size, +@@ -21,6 +21,7 @@ + */ + + #include "flash.h" ++#include "chipdrivers.h" + + void write_lockbits_49fl00x(chipaddr bios, int size, + unsigned char bits, int block_size) +@@ -36,14 +37,16 @@ void write_lockbits_49fl00x(chipaddr bios, int size, } } -int probe_49fl00x(struct flashchip *flash) --{ ++int unlock_49fl00x(struct flashchip *flash) + { - int ret = probe_jedec(flash); - - if (ret == 1) - map_flash_registers(flash); -- ++ write_lockbits_49fl00x(flash->virtual_registers, flash->total_size * 1024, 0, flash->page_size); ++ return 0; ++} + - return ret; --} -- ++int lock_49fl00x(struct flashchip *flash) ++{ ++ write_lockbits_49fl00x(flash->virtual_registers, flash->total_size * 1024, 1, flash->page_size); ++ return 0; + } + int erase_49fl00x(struct flashchip *flash) - { - int i; -@@ -101,8 +91,8 @@ int write_49fl00x(struct flashchip *flash, uint8_t *buf) +@@ -101,8 +104,8 @@ int write_49fl00x(struct flashchip *flash, uint8_t *buf) /* write to the sector */ printf("%04d at address: 0x%08x", i, i * page_size); @@ -14450,7 +16016,7 @@ index 27a1163..9d104e2 100644 fflush(stdout); } diff --git a/print.c b/print.c -index ce46e1b..fce72fd 100644 +index ce46e1b..2208dca 100644 --- a/print.c +++ b/print.c @@ -21,22 +21,9 @@ @@ -14511,7 +16077,7 @@ index ce46e1b..fce72fd 100644 printf(" "); if (b[i].lb_vendor != NULL) printf("-m %s:%s\n", b[i].lb_vendor, b[i].lb_part); -@@ -234,505 +222,187 @@ void print_supported_boards(void) +@@ -234,505 +222,188 @@ void print_supported_boards(void) print_supported_boards_helper(laptops_bad, "Laptops which have been verified to NOT work yet"); } @@ -14793,6 +16359,7 @@ index ce46e1b..fce72fd 100644 + { "ASUS", "A7N8X-E Deluxe", }, + { "ASUS", "A7V400-MX", }, + { "ASUS", "A7V8X-MX", }, ++ { "ASUS", "A7V8X-X", }, + { "ASUS", "A8N-E", }, + { "ASUS", "A8NE-FM/S", }, + { "ASUS", "A8N-SLI", }, @@ -15191,10 +16758,10 @@ index ce46e1b..fce72fd 100644 diff --git a/print_wiki.c b/print_wiki.c new file mode 100644 -index 0000000..aa5475c +index 0000000..4156c3e --- /dev/null +++ b/print_wiki.c -@@ -0,0 +1,571 @@ +@@ -0,0 +1,575 @@ +/* + * This file is part of the flashrom project. + * @@ -15407,6 +16974,7 @@ index 0000000..aa5475c + { "ASUS", "A7V600-X", "http://www.asus.com/product.aspx?P_ID=L2XYS0rmtCjeOr4k" }, + { "ASUS", "A7V8X", "http://www.asus.com/product.aspx?P_ID=qfpaGrAy2kLVo0f2" }, + { "ASUS", "A7V8X-MX SE", "http://www.asus.com/product.aspx?P_ID=1guVBT1qV5oqhHyZ" }, ++ { "ASUS", "A7V8X-X", "http://www.asus.com/product.aspx?P_ID=YcXfRrWHZ9RKoVmw" }, + { "ASUS", "P4B266", "http://www.ciao.co.uk/ASUS_Intel_845D_Chipset_P4B266__5409807#productdetail" }, + { "ASUS", "P4P800-E Deluxe", "http://www.asus.com/product.aspx?P_ID=INIJUvLlif7LHp3g" }, + { "ASUS", "P5ND2-SLI Deluxe", "http://www.asus.com/product.aspx?P_ID=WY7XroDuUImVbgp5" }, @@ -15738,7 +17306,7 @@ index 0000000..aa5475c + "%04x:%04x || {{%s}}\n", (c) ? "eeeeee" : "dddddd", + devs[i].vendor_name, devs[i].device_name, + devs[i].vendor_id, devs[i].device_id, -+ (devs[i].status == PCI_NT) ? (c) ? "?2" : "?" : "OK"); ++ (devs[i].status == NT) ? (c) ? "?2" : "?" : "OK"); + } +} + @@ -15763,6 +17331,9 @@ index 0000000..aa5475c +#if SATASII_SUPPORT == 1 + print_supported_pcidevs_wiki(satas_sii); +#endif ++#if ATAHPT_SUPPORT == 1 ++ print_supported_pcidevs_wiki(ata_hpt); ++#endif + printf("\n|}\n"); +} + @@ -15872,9 +17443,28 @@ index 0000000..ca641e1 + return; +} diff --git a/satasii.c b/satasii.c -index 2564436..90995c9 100644 +index 2564436..90d38bd 100644 --- a/satasii.c +++ b/satasii.c +@@ -30,12 +30,12 @@ uint8_t *sii_bar; + uint16_t id; + + struct pcidev_status satas_sii[] = { +- {0x1095, 0x0680, PCI_OK, "Silicon Image", "PCI0680 Ultra ATA-133 Host Ctrl"}, +- {0x1095, 0x3112, PCI_OK, "Silicon Image", "SiI 3112 [SATALink/SATARaid] SATA Ctrl"}, +- {0x1095, 0x3114, PCI_OK, "Silicon Image", "SiI 3114 [SATALink/SATARaid] SATA Ctrl"}, +- {0x1095, 0x3124, PCI_NT, "Silicon Image", "SiI 3124 PCI-X SATA Ctrl"}, +- {0x1095, 0x3132, PCI_OK, "Silicon Image", "SiI 3132 SATA Raid II Ctrl"}, +- {0x1095, 0x3512, PCI_NT, "Silicon Image", "SiI 3512 [SATALink/SATARaid] SATA Ctrl"}, ++ {0x1095, 0x0680, OK, "Silicon Image", "PCI0680 Ultra ATA-133 Host Ctrl"}, ++ {0x1095, 0x3112, OK, "Silicon Image", "SiI 3112 [SATALink/SATARaid] SATA Ctrl"}, ++ {0x1095, 0x3114, OK, "Silicon Image", "SiI 3114 [SATALink/SATARaid] SATA Ctrl"}, ++ {0x1095, 0x3124, NT, "Silicon Image", "SiI 3124 PCI-X SATA Ctrl"}, ++ {0x1095, 0x3132, OK, "Silicon Image", "SiI 3132 SATA Raid II Ctrl"}, ++ {0x1095, 0x3512, NT, "Silicon Image", "SiI 3512 [SATALink/SATARaid] SATA Ctrl"}, + + {}, + }; @@ -47,7 +47,8 @@ int satasii_init(void) get_io_perms(); @@ -15895,10 +17485,18 @@ index 2564436..90995c9 100644 buses_supported = CHIP_BUSTYPE_PARALLEL; diff --git a/sb600spi.c b/sb600spi.c -index c853f42..9172eac 100644 +index c853f42..0cf797c 100644 --- a/sb600spi.c +++ b/sb600spi.c -@@ -48,30 +48,35 @@ int sb600_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) +@@ -22,6 +22,7 @@ + + #include + #include "flash.h" ++#include "chipdrivers.h" + #include "spi.h" + + /* This struct is unused, but helps visualize the SB600 SPI BAR layout. +@@ -48,30 +49,35 @@ int sb600_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) /* FIXME: SB600 can write 5 bytes per transaction. */ int sb600_spi_write_1(struct flashchip *flash, uint8_t *buf) { @@ -15945,7 +17543,7 @@ index c853f42..9172eac 100644 } static void reset_internal_fifo_pointer(void) -@@ -79,7 +84,7 @@ static void reset_internal_fifo_pointer(void) +@@ -79,7 +85,7 @@ static void reset_internal_fifo_pointer(void) mmio_writeb(mmio_readb(sb600_spibar + 2) | 0x10, sb600_spibar + 2); while (mmio_readb(sb600_spibar + 0xD) & 0x7) @@ -15954,7 +17552,7 @@ index c853f42..9172eac 100644 } static void execute_command(void) -@@ -100,17 +105,17 @@ int sb600_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -100,17 +106,17 @@ int sb600_spi_send_command(unsigned int writecnt, unsigned int readcnt, writecnt--; @@ -15976,7 +17574,7 @@ index c853f42..9172eac 100644 "it is limited to 8 bytes\n", __func__, writecnt); return SPI_INVALID_LENGTH; } -@@ -130,10 +135,10 @@ int sb600_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -130,10 +136,10 @@ int sb600_spi_send_command(unsigned int writecnt, unsigned int readcnt, /* Send the write byte to FIFO. */ for (count = 0; count < writecnt; count++, writearr++) { @@ -15989,7 +17587,7 @@ index c853f42..9172eac 100644 /* * We should send the data by sequence, which means we need to reset -@@ -159,16 +164,16 @@ int sb600_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -159,16 +165,16 @@ int sb600_spi_send_command(unsigned int writecnt, unsigned int readcnt, /* Skip the bytes we sent. */ for (count = 0; count < writecnt; count++) { cmd = mmio_readb(sb600_spibar + 0xC); @@ -16721,10 +18319,18 @@ index 23e1a0c..0035e9a 100644 sp_pass_writen(); sp_check_opbuf_usage(5); diff --git a/sharplhf00l04.c b/sharplhf00l04.c -index 53b9931..9669e20 100644 +index 53b9931..d5ab38c 100644 --- a/sharplhf00l04.c +++ b/sharplhf00l04.c -@@ -33,81 +33,20 @@ void print_lhf00l04_status(uint8_t status) +@@ -20,6 +20,7 @@ + + #include + #include "flash.h" ++#include "chipdrivers.h" + + // I need that Berkeley bit-map printer + void print_lhf00l04_status(uint8_t status) +@@ -33,81 +34,20 @@ void print_lhf00l04_status(uint8_t status) printf("%s", status & 0x2 ? "WP|TBL#|WP#,ABORT:" : "UNLOCK:"); } @@ -16813,7 +18419,7 @@ index 53b9931..9669e20 100644 print_lhf00l04_status(status); // clear write protect printf("write protect is at 0x%lx\n", (wrprotect)); -@@ -120,34 +59,17 @@ int erase_lhf00l04_block(struct flashchip *flash, int offset) +@@ -120,34 +60,17 @@ int erase_lhf00l04_block(struct flashchip *flash, int offset) chip_writeb(0xd0, bios); programmer_delay(10); // now let's see what the register is @@ -16851,7 +18457,7 @@ index 53b9931..9669e20 100644 void write_page_lhf00l04(chipaddr bios, uint8_t *src, chipaddr dst, int page_size) { -@@ -157,7 +79,7 @@ void write_page_lhf00l04(chipaddr bios, uint8_t *src, +@@ -157,7 +80,7 @@ void write_page_lhf00l04(chipaddr bios, uint8_t *src, /* transfer data from source to destination */ chip_writeb(0x40, dst); chip_writeb(*src++, dst++); @@ -16860,7 +18466,7 @@ index 53b9931..9669e20 100644 } } -@@ -168,7 +90,7 @@ int write_lhf00l04(struct flashchip *flash, uint8_t *buf) +@@ -168,7 +91,7 @@ int write_lhf00l04(struct flashchip *flash, uint8_t *buf) int page_size = flash->page_size; chipaddr bios = flash->virtual_memory; @@ -16869,7 +18475,7 @@ index 53b9931..9669e20 100644 fprintf(stderr, "ERASE FAILED!\n"); return -1; } -@@ -180,7 +102,6 @@ int write_lhf00l04(struct flashchip *flash, uint8_t *buf) +@@ -180,7 +103,6 @@ int write_lhf00l04(struct flashchip *flash, uint8_t *buf) printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); } printf("\n"); @@ -16878,10 +18484,18 @@ index 53b9931..9669e20 100644 return 0; } diff --git a/spi.c b/spi.c -index 7f678a1..e1ab2ea 100644 +index 7f678a1..41bb8f3 100644 --- a/spi.c +++ b/spi.c -@@ -40,6 +40,7 @@ const struct spi_programmer spi_programmer[] = { +@@ -25,6 +25,7 @@ + #include + #include "flash.h" + #include "flashchips.h" ++#include "chipdrivers.h" + #include "spi.h" + + enum spi_controller spi_controller = SPI_CONTROLLER_NONE; +@@ -40,6 +41,7 @@ const struct spi_programmer spi_programmer[] = { .write_256 = NULL, }, @@ -16889,7 +18503,7 @@ index 7f678a1..e1ab2ea 100644 { /* SPI_CONTROLLER_ICH7 */ .command = ich_spi_send_command, .multicommand = ich_spi_send_multicommand, -@@ -81,6 +82,7 @@ const struct spi_programmer spi_programmer[] = { +@@ -81,6 +83,7 @@ const struct spi_programmer spi_programmer[] = { .read = wbsio_spi_read, .write_256 = wbsio_spi_write_1, }, @@ -16897,7 +18511,7 @@ index 7f678a1..e1ab2ea 100644 #if FT2232_SPI_SUPPORT == 1 { /* SPI_CONTROLLER_FT2232 */ -@@ -91,12 +93,32 @@ const struct spi_programmer spi_programmer[] = { +@@ -91,12 +94,32 @@ const struct spi_programmer spi_programmer[] = { }, #endif @@ -16930,7 +18544,7 @@ index 7f678a1..e1ab2ea 100644 {}, /* This entry corresponds to SPI_CONTROLLER_INVALID. */ }; -@@ -116,7 +138,7 @@ int spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -116,7 +139,7 @@ int spi_send_command(unsigned int writecnt, unsigned int readcnt, writearr, readarr); } @@ -16939,7 +18553,7 @@ index 7f678a1..e1ab2ea 100644 { if (!spi_programmer[spi_controller].multicommand) { fprintf(stderr, "%s called, but SPI is unsupported on this " -@@ -124,7 +146,7 @@ int spi_send_multicommand(struct spi_command *spicommands) +@@ -124,7 +147,7 @@ int spi_send_multicommand(struct spi_command *spicommands) return 1; } @@ -16948,7 +18562,7 @@ index 7f678a1..e1ab2ea 100644 } int default_spi_send_command(unsigned int writecnt, unsigned int readcnt, -@@ -146,13 +168,12 @@ int default_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -146,807 +169,16 @@ int default_spi_send_command(unsigned int writecnt, unsigned int readcnt, return spi_send_multicommand(cmd); } @@ -16960,49 +18574,1095 @@ index 7f678a1..e1ab2ea 100644 - result = spi_send_command(spicommands->writecnt, spicommands->readcnt, - spicommands->writearr, spicommands->readarr); - spicommands++; +- } +- return result; +-} +- +-static int spi_rdid(unsigned char *readarr, int bytes) +-{ +- const unsigned char cmd[JEDEC_RDID_OUTSIZE] = { JEDEC_RDID }; +- int ret; +- int i; +- +- ret = spi_send_command(sizeof(cmd), bytes, cmd, readarr); +- if (ret) +- return ret; +- printf_debug("RDID returned"); +- for (i = 0; i < bytes; i++) +- printf_debug(" 0x%02x", readarr[i]); +- printf_debug(". "); +- return 0; +-} +- +-static int spi_rems(unsigned char *readarr) +-{ +- unsigned char cmd[JEDEC_REMS_OUTSIZE] = { JEDEC_REMS, 0, 0, 0 }; +- uint32_t readaddr; +- int ret; +- +- ret = spi_send_command(sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr); +- if (ret == SPI_INVALID_ADDRESS) { +- /* Find the lowest even address allowed for reads. */ +- readaddr = (spi_get_valid_read_addr() + 1) & ~1; +- cmd[1] = (readaddr >> 16) & 0xff, +- cmd[2] = (readaddr >> 8) & 0xff, +- cmd[3] = (readaddr >> 0) & 0xff, +- ret = spi_send_command(sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr); +- } +- if (ret) +- return ret; +- printf_debug("REMS returned %02x %02x. ", readarr[0], readarr[1]); +- return 0; +-} +- +-static int spi_res(unsigned char *readarr) +-{ +- unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 }; +- uint32_t readaddr; +- int ret; +- +- ret = spi_send_command(sizeof(cmd), JEDEC_RES_INSIZE, cmd, readarr); +- if (ret == SPI_INVALID_ADDRESS) { +- /* Find the lowest even address allowed for reads. */ +- readaddr = (spi_get_valid_read_addr() + 1) & ~1; +- cmd[1] = (readaddr >> 16) & 0xff, +- cmd[2] = (readaddr >> 8) & 0xff, +- cmd[3] = (readaddr >> 0) & 0xff, +- ret = spi_send_command(sizeof(cmd), JEDEC_RES_INSIZE, cmd, readarr); +- } +- if (ret) +- return ret; +- printf_debug("RES returned %02x. ", readarr[0]); +- return 0; +-} +- +-int spi_write_enable(void) +-{ +- const unsigned char cmd[JEDEC_WREN_OUTSIZE] = { JEDEC_WREN }; +- int result; +- +- /* Send WREN (Write Enable) */ +- result = spi_send_command(sizeof(cmd), 0, cmd, NULL); +- +- if (result) +- fprintf(stderr, "%s failed\n", __func__); +- +- return result; +-} +- +-int spi_write_disable(void) +-{ +- const unsigned char cmd[JEDEC_WRDI_OUTSIZE] = { JEDEC_WRDI }; +- +- /* Send WRDI (Write Disable) */ +- return spi_send_command(sizeof(cmd), 0, cmd, NULL); +-} +- +-static int probe_spi_rdid_generic(struct flashchip *flash, int bytes) +-{ +- unsigned char readarr[4]; +- uint32_t id1; +- uint32_t id2; +- +- if (spi_rdid(readarr, bytes)) +- return 0; +- +- if (!oddparity(readarr[0])) +- printf_debug("RDID byte 0 parity violation. "); +- +- /* Check if this is a continuation vendor ID */ +- if (readarr[0] == 0x7f) { +- if (!oddparity(readarr[1])) +- printf_debug("RDID byte 1 parity violation. "); +- id1 = (readarr[0] << 8) | readarr[1]; +- id2 = readarr[2]; +- if (bytes > 3) { +- id2 <<= 8; +- id2 |= readarr[3]; +- } +- } else { +- id1 = readarr[0]; +- id2 = (readarr[1] << 8) | readarr[2]; +- } +- +- printf_debug("%s: id1 0x%02x, id2 0x%02x\n", __FUNCTION__, id1, id2); +- +- if (id1 == flash->manufacture_id && id2 == flash->model_id) { +- /* Print the status register to tell the +- * user about possible write protection. +- */ +- spi_prettyprint_status_register(flash); +- +- return 1; +- } +- +- /* Test if this is a pure vendor match. */ +- if (id1 == flash->manufacture_id && +- GENERIC_DEVICE_ID == flash->model_id) +- return 1; +- +- return 0; +-} +- +-int probe_spi_rdid(struct flashchip *flash) +-{ +- return probe_spi_rdid_generic(flash, 3); +-} +- +-/* support 4 bytes flash ID */ +-int probe_spi_rdid4(struct flashchip *flash) +-{ +- /* only some SPI chipsets support 4 bytes commands */ +- switch (spi_controller) { +- case SPI_CONTROLLER_ICH7: +- case SPI_CONTROLLER_ICH9: +- case SPI_CONTROLLER_VIA: +- case SPI_CONTROLLER_SB600: +- case SPI_CONTROLLER_WBSIO: +-#if FT2232_SPI_SUPPORT == 1 +- case SPI_CONTROLLER_FT2232: +-#endif +- case SPI_CONTROLLER_DUMMY: +- return probe_spi_rdid_generic(flash, 4); +- default: +- printf_debug("4b ID not supported on this SPI controller\n"); +- } +- +- return 0; +-} +- +-int probe_spi_rems(struct flashchip *flash) +-{ +- unsigned char readarr[JEDEC_REMS_INSIZE]; +- uint32_t id1, id2; +- +- if (spi_rems(readarr)) +- return 0; +- +- id1 = readarr[0]; +- id2 = readarr[1]; +- +- printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2); +- +- if (id1 == flash->manufacture_id && id2 == flash->model_id) { +- /* Print the status register to tell the +- * user about possible write protection. +- */ +- spi_prettyprint_status_register(flash); +- +- return 1; +- } +- +- /* Test if this is a pure vendor match. */ +- if (id1 == flash->manufacture_id && +- GENERIC_DEVICE_ID == flash->model_id) +- return 1; +- +- return 0; +-} +- +-int probe_spi_res(struct flashchip *flash) +-{ +- unsigned char readarr[3]; +- uint32_t id2; +- +- /* Check if RDID was successful and did not return 0xff 0xff 0xff. +- * In that case, RES is pointless. +- */ +- if (!spi_rdid(readarr, 3) && ((readarr[0] != 0xff) || +- (readarr[1] != 0xff) || (readarr[2] != 0xff))) +- return 0; +- +- if (spi_res(readarr)) +- return 0; +- +- id2 = readarr[0]; +- printf_debug("%s: id 0x%x\n", __FUNCTION__, id2); +- if (id2 != flash->model_id) +- return 0; +- +- /* Print the status register to tell the +- * user about possible write protection. +- */ +- spi_prettyprint_status_register(flash); +- return 1; +-} +- +-uint8_t spi_read_status_register(void) +-{ +- const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR }; +- /* FIXME: No workarounds for driver/hardware bugs in generic code. */ +- unsigned char readarr[2]; /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */ +- int ret; +- +- /* Read Status Register */ +- ret = spi_send_command(sizeof(cmd), sizeof(readarr), cmd, readarr); +- if (ret) +- fprintf(stderr, "RDSR failed!\n"); +- +- return readarr[0]; +-} +- +-/* Prettyprint the status register. Common definitions. */ +-void spi_prettyprint_status_register_common(uint8_t status) +-{ +- printf_debug("Chip status register: Bit 5 / Block Protect 3 (BP3) is " +- "%sset\n", (status & (1 << 5)) ? "" : "not "); +- printf_debug("Chip status register: Bit 4 / Block Protect 2 (BP2) is " +- "%sset\n", (status & (1 << 4)) ? "" : "not "); +- printf_debug("Chip status register: Bit 3 / Block Protect 1 (BP1) is " +- "%sset\n", (status & (1 << 3)) ? "" : "not "); +- printf_debug("Chip status register: Bit 2 / Block Protect 0 (BP0) is " +- "%sset\n", (status & (1 << 2)) ? "" : "not "); +- printf_debug("Chip status register: Write Enable Latch (WEL) is " +- "%sset\n", (status & (1 << 1)) ? "" : "not "); +- printf_debug("Chip status register: Write In Progress (WIP/BUSY) is " +- "%sset\n", (status & (1 << 0)) ? "" : "not "); +-} +- +-/* Prettyprint the status register. Works for +- * ST M25P series +- * MX MX25L series +- */ +-void spi_prettyprint_status_register_st_m25p(uint8_t status) +-{ +- printf_debug("Chip status register: Status Register Write Disable " +- "(SRWD) is %sset\n", (status & (1 << 7)) ? "" : "not "); +- printf_debug("Chip status register: Bit 6 is " +- "%sset\n", (status & (1 << 6)) ? "" : "not "); +- spi_prettyprint_status_register_common(status); +-} +- +-void spi_prettyprint_status_register_sst25(uint8_t status) +-{ +- printf_debug("Chip status register: Block Protect Write Disable " +- "(BPL) is %sset\n", (status & (1 << 7)) ? "" : "not "); +- printf_debug("Chip status register: Auto Address Increment Programming " +- "(AAI) is %sset\n", (status & (1 << 6)) ? "" : "not "); +- spi_prettyprint_status_register_common(status); +-} +- +-/* Prettyprint the status register. Works for +- * SST 25VF016 +- */ +-void spi_prettyprint_status_register_sst25vf016(uint8_t status) +-{ +- const char *bpt[] = { +- "none", +- "1F0000H-1FFFFFH", +- "1E0000H-1FFFFFH", +- "1C0000H-1FFFFFH", +- "180000H-1FFFFFH", +- "100000H-1FFFFFH", +- "all", "all" +- }; +- spi_prettyprint_status_register_sst25(status); +- printf_debug("Resulting block protection : %s\n", +- bpt[(status & 0x1c) >> 2]); +-} +- +-void spi_prettyprint_status_register_sst25vf040b(uint8_t status) +-{ +- const char *bpt[] = { +- "none", +- "0x70000-0x7ffff", +- "0x60000-0x7ffff", +- "0x40000-0x7ffff", +- "all blocks", "all blocks", "all blocks", "all blocks" +- }; +- spi_prettyprint_status_register_sst25(status); +- printf_debug("Resulting block protection : %s\n", +- bpt[(status & 0x1c) >> 2]); +-} +- +-void spi_prettyprint_status_register(struct flashchip *flash) +-{ +- uint8_t status; +- +- status = spi_read_status_register(); +- printf_debug("Chip status register is %02x\n", status); +- switch (flash->manufacture_id) { +- case ST_ID: +- if (((flash->model_id & 0xff00) == 0x2000) || +- ((flash->model_id & 0xff00) == 0x2500)) +- spi_prettyprint_status_register_st_m25p(status); +- break; +- case MX_ID: +- if ((flash->model_id & 0xff00) == 0x2000) +- spi_prettyprint_status_register_st_m25p(status); +- break; +- case SST_ID: +- switch (flash->model_id) { +- case 0x2541: +- spi_prettyprint_status_register_sst25vf016(status); +- break; +- case 0x8d: +- case 0x258d: +- spi_prettyprint_status_register_sst25vf040b(status); +- break; +- default: +- spi_prettyprint_status_register_sst25(status); +- break; +- } +- break; +- } +-} +- +-int spi_chip_erase_60(struct flashchip *flash) +-{ +- int result; +- struct spi_command spicommands[] = { +- { +- .writecnt = JEDEC_WREN_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_WREN }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = JEDEC_CE_60_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_CE_60 }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = 0, +- .writearr = NULL, +- .readcnt = 0, +- .readarr = NULL, +- }}; +- +- result = spi_disable_blockprotect(); +- if (result) { +- fprintf(stderr, "spi_disable_blockprotect failed\n"); +- return result; +- } +- +- result = spi_send_multicommand(spicommands); +- if (result) { +- fprintf(stderr, "%s failed during command execution\n", +- __func__); +- return result; +- } +- /* Wait until the Write-In-Progress bit is cleared. +- * 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() & JEDEC_RDSR_BIT_WIP) +- programmer_delay(1000 * 1000); +- if (check_erased_range(flash, 0, flash->total_size * 1024)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- return 0; +-} +- +-int spi_chip_erase_c7(struct flashchip *flash) +-{ +- int result; +- struct spi_command spicommands[] = { +- { +- .writecnt = JEDEC_WREN_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_WREN }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = JEDEC_CE_C7_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_CE_C7 }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = 0, +- .writearr = NULL, +- .readcnt = 0, +- .readarr = NULL, +- }}; +- +- result = spi_disable_blockprotect(); +- if (result) { +- fprintf(stderr, "spi_disable_blockprotect failed\n"); +- return result; +- } +- +- result = spi_send_multicommand(spicommands); +- if (result) { +- fprintf(stderr, "%s failed during command execution\n", __func__); +- return result; +- } +- /* Wait until the Write-In-Progress bit is cleared. +- * 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() & JEDEC_RDSR_BIT_WIP) +- programmer_delay(1000 * 1000); +- if (check_erased_range(flash, 0, flash->total_size * 1024)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- return 0; +-} +- +-int spi_chip_erase_60_c7(struct flashchip *flash) +-{ +- int result; +- result = spi_chip_erase_60(flash); +- if (result) { +- printf_debug("spi_chip_erase_60 failed, trying c7\n"); +- result = spi_chip_erase_c7(flash); + for (; (cmds->writecnt || cmds->readcnt) && !result; cmds++) { + result = spi_send_command(cmds->writecnt, cmds->readcnt, + cmds->writearr, cmds->readarr); } return result; } -@@ -264,7 +285,7 @@ static int probe_spi_rdid_generic(struct flashchip *flash, int bytes) - id2 = (readarr[1] << 8) | readarr[2]; - } -- printf_debug("%s: id1 0x%02x, id2 0x%02x\n", __FUNCTION__, id1, id2); +-int spi_block_erase_52(struct flashchip *flash, unsigned int addr, unsigned int blocklen) +-{ +- int result; +- struct spi_command spicommands[] = { +- { +- .writecnt = JEDEC_WREN_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_WREN }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = JEDEC_BE_52_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_BE_52, (addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr & 0xff) }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = 0, +- .writearr = NULL, +- .readcnt = 0, +- .readarr = NULL, +- }}; +- +- result = spi_send_multicommand(spicommands); +- if (result) { +- fprintf(stderr, "%s failed during command execution\n", +- __func__); +- return result; +- } +- /* 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() & JEDEC_RDSR_BIT_WIP) +- programmer_delay(100 * 1000); +- if (check_erased_range(flash, addr, blocklen)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- return 0; +-} +- +-/* Block size is usually +- * 64k for Macronix +- * 32k for SST +- * 4-32k non-uniform for EON +- */ +-int spi_block_erase_d8(struct flashchip *flash, unsigned int addr, unsigned int blocklen) +-{ +- int result; +- struct spi_command spicommands[] = { +- { +- .writecnt = JEDEC_WREN_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_WREN }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = JEDEC_BE_D8_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_BE_D8, (addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr & 0xff) }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = 0, +- .writearr = NULL, +- .readcnt = 0, +- .readarr = NULL, +- }}; +- +- result = spi_send_multicommand(spicommands); +- if (result) { +- fprintf(stderr, "%s failed during command execution\n", __func__); +- return result; +- } +- /* 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() & JEDEC_RDSR_BIT_WIP) +- programmer_delay(100 * 1000); +- if (check_erased_range(flash, addr, blocklen)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- return 0; +-} +- +-int spi_chip_erase_d8(struct flashchip *flash) +-{ +- int i, rc = 0; +- int total_size = flash->total_size * 1024; +- int erase_size = 64 * 1024; +- +- spi_disable_blockprotect(); +- +- printf("Erasing chip: \n"); +- +- for (i = 0; i < total_size / erase_size; i++) { +- rc = spi_block_erase_d8(flash, i * erase_size, erase_size); +- if (rc) { +- fprintf(stderr, "Error erasing block at 0x%x\n", i); +- break; +- } +- } +- +- printf("\n"); +- +- return rc; +-} +- +-/* Sector size is usually 4k, though Macronix eliteflash has 64k */ +-int spi_block_erase_20(struct flashchip *flash, unsigned int addr, unsigned int blocklen) +-{ +- int result; +- struct spi_command spicommands[] = { +- { +- .writecnt = JEDEC_WREN_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_WREN }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = JEDEC_SE_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_SE, (addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr & 0xff) }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = 0, +- .writearr = NULL, +- .readcnt = 0, +- .readarr = NULL, +- }}; +- +- result = spi_send_multicommand(spicommands); +- if (result) { +- fprintf(stderr, "%s failed during command execution\n", +- __func__); +- return result; +- } +- /* 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() & JEDEC_RDSR_BIT_WIP) +- programmer_delay(10 * 1000); +- if (check_erased_range(flash, addr, blocklen)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- return 0; +-} +- +-int spi_block_erase_60(struct flashchip *flash, unsigned int addr, unsigned int blocklen) +-{ +- if ((addr != 0) || (blocklen != flash->total_size * 1024)) { +- fprintf(stderr, "%s called with incorrect arguments\n", +- __func__); +- return -1; +- } +- return spi_chip_erase_60(flash); +-} +- +-int spi_block_erase_c7(struct flashchip *flash, unsigned int addr, unsigned int blocklen) +-{ +- if ((addr != 0) || (blocklen != flash->total_size * 1024)) { +- fprintf(stderr, "%s called with incorrect arguments\n", +- __func__); +- return -1; +- } +- return spi_chip_erase_c7(flash); +-} +- +-int spi_write_status_enable(void) +-{ +- const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR }; +- int result; +- +- /* Send EWSR (Enable Write Status Register). */ +- result = spi_send_command(sizeof(cmd), JEDEC_EWSR_INSIZE, cmd, NULL); +- +- if (result) +- fprintf(stderr, "%s failed\n", __func__); +- +- return result; +-} +- +-/* +- * This is according the SST25VF016 datasheet, who knows it is more +- * generic that this... +- */ +-int spi_write_status_register(int status) +-{ +- int result; +- struct spi_command spicommands[] = { +- { +- .writecnt = JEDEC_EWSR_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_EWSR }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = JEDEC_WRSR_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = 0, +- .writearr = NULL, +- .readcnt = 0, +- .readarr = NULL, +- }}; +- +- result = spi_send_multicommand(spicommands); +- if (result) { +- fprintf(stderr, "%s failed during command execution\n", +- __func__); +- } +- return result; +-} +- +-int spi_byte_program(int addr, uint8_t byte) +-{ +- int result; +- struct spi_command spicommands[] = { +- { +- .writecnt = JEDEC_WREN_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_WREN }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_BYTE_PROGRAM, (addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr & 0xff), byte }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = 0, +- .writearr = NULL, +- .readcnt = 0, +- .readarr = NULL, +- }}; +- +- result = spi_send_multicommand(spicommands); +- if (result) { +- fprintf(stderr, "%s failed during command execution\n", +- __func__); +- } +- return result; +-} +- +-int spi_nbyte_program(int address, uint8_t *bytes, int len) +-{ +- int result; +- /* FIXME: Switch to malloc based on len unless that kills speed. */ +- unsigned char cmd[JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + 256] = { +- JEDEC_BYTE_PROGRAM, +- (address >> 16) & 0xff, +- (address >> 8) & 0xff, +- (address >> 0) & 0xff, +- }; +- struct spi_command spicommands[] = { +- { +- .writecnt = JEDEC_WREN_OUTSIZE, +- .writearr = (const unsigned char[]){ JEDEC_WREN }, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + len, +- .writearr = cmd, +- .readcnt = 0, +- .readarr = NULL, +- }, { +- .writecnt = 0, +- .writearr = NULL, +- .readcnt = 0, +- .readarr = NULL, +- }}; +- +- if (!len) { +- fprintf(stderr, "%s called for zero-length write\n", __func__); +- return 1; +- } +- if (len > 256) { +- fprintf(stderr, "%s called for too long a write\n", __func__); +- return 1; +- } +- +- memcpy(&cmd[4], bytes, len); +- +- result = spi_send_multicommand(spicommands); +- if (result) { +- fprintf(stderr, "%s failed during command execution\n", +- __func__); +- } +- return result; +-} +- +-int spi_disable_blockprotect(void) +-{ +- uint8_t status; +- int result; +- +- status = spi_read_status_register(); +- /* If there is block protection in effect, unprotect it first. */ +- if ((status & 0x3c) != 0) { +- printf_debug("Some block protection in effect, disabling\n"); +- result = spi_write_status_register(status & ~0x3c); +- if (result) { +- fprintf(stderr, "spi_write_status_register failed\n"); +- return result; +- } +- } +- return 0; +-} +- +-int spi_nbyte_read(int address, uint8_t *bytes, int len) +-{ +- const unsigned char cmd[JEDEC_READ_OUTSIZE] = { +- JEDEC_READ, +- (address >> 16) & 0xff, +- (address >> 8) & 0xff, +- (address >> 0) & 0xff, +- }; +- +- /* Send Read */ +- return spi_send_command(sizeof(cmd), len, cmd, bytes); +-} +- +-/* +- * Read a complete flash chip. +- * 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) +-{ +- int rc = 0; +- int i, j, starthere, lenhere; +- int page_size = flash->page_size; +- int toread; +- +- /* Warning: This loop has a very unusual condition and body. +- * The loop needs to go through each page with at least one affected +- * byte. The lowest page number is (start / page_size) since that +- * division rounds down. The highest page number we want is the page +- * where the last byte of the range lives. That last byte has the +- * address (start + len - 1), thus the highest page number is +- * (start + len - 1) / page_size. Since we want to include that last +- * page as well, the loop condition uses <=. +- */ +- for (i = start / page_size; i <= (start + len - 1) / page_size; i++) { +- /* Byte position of the first byte in the range in this page. */ +- /* starthere is an offset to the base address of the chip. */ +- starthere = max(start, i * page_size); +- /* Length of bytes in the range in this page. */ +- lenhere = min(start + len, (i + 1) * page_size) - starthere; +- for (j = 0; j < lenhere; j += chunksize) { +- toread = min(chunksize, lenhere - j); +- rc = spi_nbyte_read(starthere + j, buf + starthere - start + j, toread); +- if (rc) +- break; +- } +- if (rc) +- break; +- } +- +- return rc; +-} +- + int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len) + { + if (!spi_programmer[spi_controller].read) { +@@ -959,34 +191,6 @@ int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len) + } + + /* +- * Program chip using byte programming. (SLOW!) +- * This is for chips which can only handle one byte writes +- * 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) +-{ +- int total_size = 1024 * flash->total_size; +- int i; +- +- spi_disable_blockprotect(); +- /* Erase first */ +- printf("Erasing flash before programming... "); +- if (flash->erase(flash)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- printf("done.\n"); +- for (i = 0; i < total_size; i++) { +- spi_byte_program(i, buf[i]); +- while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) +- programmer_delay(10); +- } +- +- return 0; +-} +- +-/* + * Program chip using page (256 bytes) programming. + * Some SPI masters can't do this, they use single byte programming instead. + */ +@@ -1006,38 +210,3 @@ uint32_t spi_get_valid_read_addr(void) + /* Need to return BBAR for ICH chipsets. */ + return 0; + } +- +-int spi_aai_write(struct flashchip *flash, uint8_t *buf) +-{ +- uint32_t pos = 2, size = flash->total_size * 1024; +- unsigned char w[6] = {0xad, 0, 0, 0, buf[0], buf[1]}; +- int result; +- +- switch (spi_controller) { +- case SPI_CONTROLLER_WBSIO: +- fprintf(stderr, "%s: impossible with Winbond SPI masters," +- " degrading to byte program\n", __func__); +- return spi_chip_write_1(flash, buf); +- default: +- break; +- } +- if (flash->erase(flash)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- result = spi_write_enable(); +- if (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 */ +- } +- spi_write_disable(); +- return 0; +-} +diff --git a/spi.h b/spi.h +index 3050ccf..1b49d59 100644 +--- a/spi.h ++++ b/spi.h +@@ -74,6 +74,11 @@ + #define JEDEC_BE_D8_OUTSIZE 0x04 + #define JEDEC_BE_D8_INSIZE 0x00 + ++/* Block Erase 0xd7 is supported by PMC chips. */ ++#define JEDEC_BE_D7 0xd7 ++#define JEDEC_BE_D7_OUTSIZE 0x04 ++#define JEDEC_BE_D7_INSIZE 0x00 ++ + /* Sector Erase 0x20 is supported by Macronix/SST chips. */ + #define JEDEC_SE 0x20 + #define JEDEC_SE_OUTSIZE 0x04 +@@ -106,6 +111,7 @@ + #define JEDEC_BYTE_PROGRAM_INSIZE 0x00 + + /* Error codes */ ++#define SPI_GENERIC_ERROR -1 + #define SPI_INVALID_OPCODE -2 + #define SPI_INVALID_ADDRESS -3 + #define SPI_INVALID_LENGTH -4 +diff --git a/spi25.c b/spi25.c +new file mode 100644 +index 0000000..54121b0 +--- /dev/null ++++ b/spi25.c +@@ -0,0 +1,992 @@ ++/* ++ * This file is part of the flashrom project. ++ * ++ * Copyright (C) 2007, 2008, 2009 Carl-Daniel Hailfinger ++ * Copyright (C) 2008 coresystems GmbH ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/* ++ * Contains the common SPI chip driver functions ++ */ ++ ++#include ++#include "flash.h" ++#include "flashchips.h" ++#include "chipdrivers.h" ++#include "spi.h" ++ ++void spi_prettyprint_status_register(struct flashchip *flash); ++ ++static int spi_rdid(unsigned char *readarr, int bytes) ++{ ++ const unsigned char cmd[JEDEC_RDID_OUTSIZE] = { JEDEC_RDID }; ++ int ret; ++ int i; ++ ++ ret = spi_send_command(sizeof(cmd), bytes, cmd, readarr); ++ if (ret) ++ return ret; ++ printf_debug("RDID returned"); ++ for (i = 0; i < bytes; i++) ++ printf_debug(" 0x%02x", readarr[i]); ++ printf_debug(". "); ++ return 0; ++} ++ ++static int spi_rems(unsigned char *readarr) ++{ ++ unsigned char cmd[JEDEC_REMS_OUTSIZE] = { JEDEC_REMS, 0, 0, 0 }; ++ uint32_t readaddr; ++ int ret; ++ ++ ret = spi_send_command(sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr); ++ if (ret == SPI_INVALID_ADDRESS) { ++ /* Find the lowest even address allowed for reads. */ ++ readaddr = (spi_get_valid_read_addr() + 1) & ~1; ++ cmd[1] = (readaddr >> 16) & 0xff, ++ cmd[2] = (readaddr >> 8) & 0xff, ++ cmd[3] = (readaddr >> 0) & 0xff, ++ ret = spi_send_command(sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr); ++ } ++ if (ret) ++ return ret; ++ printf_debug("REMS returned %02x %02x. ", readarr[0], readarr[1]); ++ return 0; ++} ++ ++static int spi_res(unsigned char *readarr) ++{ ++ unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 }; ++ uint32_t readaddr; ++ int ret; ++ ++ ret = spi_send_command(sizeof(cmd), JEDEC_RES_INSIZE, cmd, readarr); ++ if (ret == SPI_INVALID_ADDRESS) { ++ /* Find the lowest even address allowed for reads. */ ++ readaddr = (spi_get_valid_read_addr() + 1) & ~1; ++ cmd[1] = (readaddr >> 16) & 0xff, ++ cmd[2] = (readaddr >> 8) & 0xff, ++ cmd[3] = (readaddr >> 0) & 0xff, ++ ret = spi_send_command(sizeof(cmd), JEDEC_RES_INSIZE, cmd, readarr); ++ } ++ if (ret) ++ return ret; ++ printf_debug("RES returned %02x. ", readarr[0]); ++ return 0; ++} ++ ++int spi_write_enable(void) ++{ ++ const unsigned char cmd[JEDEC_WREN_OUTSIZE] = { JEDEC_WREN }; ++ int result; ++ ++ /* Send WREN (Write Enable) */ ++ result = spi_send_command(sizeof(cmd), 0, cmd, NULL); ++ ++ if (result) ++ fprintf(stderr, "%s failed\n", __func__); ++ ++ return result; ++} ++ ++int spi_write_disable(void) ++{ ++ const unsigned char cmd[JEDEC_WRDI_OUTSIZE] = { JEDEC_WRDI }; ++ ++ /* Send WRDI (Write Disable) */ ++ return spi_send_command(sizeof(cmd), 0, cmd, NULL); ++} ++ ++static int probe_spi_rdid_generic(struct flashchip *flash, int bytes) ++{ ++ unsigned char readarr[4]; ++ uint32_t id1; ++ uint32_t id2; ++ ++ if (spi_rdid(readarr, bytes)) ++ return 0; ++ ++ if (!oddparity(readarr[0])) ++ printf_debug("RDID byte 0 parity violation. "); ++ ++ /* Check if this is a continuation vendor ID */ ++ if (readarr[0] == 0x7f) { ++ if (!oddparity(readarr[1])) ++ printf_debug("RDID byte 1 parity violation. "); ++ id1 = (readarr[0] << 8) | readarr[1]; ++ id2 = readarr[2]; ++ if (bytes > 3) { ++ id2 <<= 8; ++ id2 |= readarr[3]; ++ } ++ } else { ++ id1 = readarr[0]; ++ id2 = (readarr[1] << 8) | readarr[2]; ++ } ++ + printf_debug("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); - - if (id1 == flash->manufacture_id && id2 == flash->model_id) { - /* Print the status register to tell the -@@ -280,6 +301,11 @@ static int probe_spi_rdid_generic(struct flashchip *flash, int bytes) - GENERIC_DEVICE_ID == flash->model_id) - return 1; - ++ ++ if (id1 == flash->manufacture_id && id2 == flash->model_id) { ++ /* Print the status register to tell the ++ * user about possible write protection. ++ */ ++ spi_prettyprint_status_register(flash); ++ ++ return 1; ++ } ++ ++ /* Test if this is a pure vendor match. */ ++ if (id1 == flash->manufacture_id && ++ GENERIC_DEVICE_ID == flash->model_id) ++ return 1; ++ + /* Test if there is any vendor ID. */ + if (GENERIC_MANUF_ID == flash->manufacture_id && + id1 != 0xff) + return 1; + - return 0; - } - -@@ -293,15 +319,25 @@ int probe_spi_rdid4(struct flashchip *flash) - { - /* only some SPI chipsets support 4 bytes commands */ - switch (spi_controller) { ++ return 0; ++} ++ ++int probe_spi_rdid(struct flashchip *flash) ++{ ++ return probe_spi_rdid_generic(flash, 3); ++} ++ ++/* support 4 bytes flash ID */ ++int probe_spi_rdid4(struct flashchip *flash) ++{ ++ /* only some SPI chipsets support 4 bytes commands */ ++ switch (spi_controller) { +#if INTERNAL_SUPPORT == 1 - case SPI_CONTROLLER_ICH7: - case SPI_CONTROLLER_ICH9: - case SPI_CONTROLLER_VIA: - case SPI_CONTROLLER_SB600: - case SPI_CONTROLLER_WBSIO: ++ case SPI_CONTROLLER_ICH7: ++ case SPI_CONTROLLER_ICH9: ++ case SPI_CONTROLLER_VIA: ++ case SPI_CONTROLLER_SB600: ++ case SPI_CONTROLLER_WBSIO: ++#endif ++#if FT2232_SPI_SUPPORT == 1 ++ case SPI_CONTROLLER_FT2232: +#endif - #if FT2232_SPI_SUPPORT == 1 - case SPI_CONTROLLER_FT2232: - #endif +#if DUMMY_SUPPORT == 1 - case SPI_CONTROLLER_DUMMY: ++ case SPI_CONTROLLER_DUMMY: +#endif +#if BUSPIRATE_SPI_SUPPORT == 1 + case SPI_CONTROLLER_BUSPIRATE: @@ -17010,115 +19670,388 @@ index 7f678a1..e1ab2ea 100644 +#if DEDIPROG_SUPPORT == 1 + case SPI_CONTROLLER_DEDIPROG: +#endif - return probe_spi_rdid_generic(flash, 4); - default: - printf_debug("4b ID not supported on this SPI controller\n"); -@@ -321,7 +357,7 @@ int probe_spi_rems(struct flashchip *flash) - id1 = readarr[0]; - id2 = readarr[1]; - -- printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2); ++ return probe_spi_rdid_generic(flash, 4); ++ default: ++ printf_debug("4b ID not supported on this SPI controller\n"); ++ } ++ ++ return 0; ++} ++ ++int probe_spi_rems(struct flashchip *flash) ++{ ++ unsigned char readarr[JEDEC_REMS_INSIZE]; ++ uint32_t id1, id2; ++ ++ if (spi_rems(readarr)) ++ return 0; ++ ++ id1 = readarr[0]; ++ id2 = readarr[1]; ++ + printf_debug("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2); - - if (id1 == flash->manufacture_id && id2 == flash->model_id) { - /* Print the status register to tell the -@@ -337,6 +373,11 @@ int probe_spi_rems(struct flashchip *flash) - GENERIC_DEVICE_ID == flash->model_id) - return 1; - ++ ++ if (id1 == flash->manufacture_id && id2 == flash->model_id) { ++ /* Print the status register to tell the ++ * user about possible write protection. ++ */ ++ spi_prettyprint_status_register(flash); ++ ++ return 1; ++ } ++ ++ /* Test if this is a pure vendor match. */ ++ if (id1 == flash->manufacture_id && ++ GENERIC_DEVICE_ID == flash->model_id) ++ return 1; ++ + /* Test if there is any vendor ID. */ + if (GENERIC_MANUF_ID == flash->manufacture_id && + id1 != 0xff) + return 1; + - return 0; - } - -@@ -356,7 +397,7 @@ int probe_spi_res(struct flashchip *flash) - return 0; - - id2 = readarr[0]; -- printf_debug("%s: id 0x%x\n", __FUNCTION__, id2); ++ return 0; ++} ++ ++int probe_spi_res(struct flashchip *flash) ++{ ++ unsigned char readarr[3]; ++ uint32_t id2; ++ const unsigned char allff[] = {0xff, 0xff, 0xff}; ++ const unsigned char all00[] = {0x00, 0x00, 0x00}; ++ ++ /* Check if RDID is usable and does not return 0xff 0xff 0xff or ++ * 0x00 0x00 0x00. In that case, RES is pointless. ++ */ ++ if (!spi_rdid(readarr, 3) && memcmp(readarr, allff, 3) && ++ memcmp(readarr, all00, 3)) { ++ msg_cdbg("Ignoring RES in favour of RDID.\n"); ++ return 0; ++ } ++ /* Check if REMS is usable and does not return 0xff 0xff or ++ * 0x00 0x00. In that case, RES is pointless. ++ */ ++ if (!spi_rems(readarr) && memcmp(readarr, allff, JEDEC_REMS_INSIZE) && ++ memcmp(readarr, all00, JEDEC_REMS_INSIZE)) { ++ msg_cdbg("Ignoring RES in favour of REMS.\n"); ++ return 0; ++ } ++ ++ if (spi_res(readarr)) ++ return 0; ++ ++ /* FIXME: Handle the case where RES gives a 2-byte response. */ ++ id2 = readarr[0]; + printf_debug("%s: id 0x%x\n", __func__, id2); - if (id2 != flash->model_id) - return 0; - -@@ -490,7 +531,7 @@ void spi_prettyprint_status_register(struct flashchip *flash) - int spi_chip_erase_60(struct flashchip *flash) - { - int result; -- struct spi_command spicommands[] = { ++ if (id2 != flash->model_id) ++ return 0; ++ ++ /* Print the status register to tell the ++ * user about possible write protection. ++ */ ++ spi_prettyprint_status_register(flash); ++ return 1; ++} ++ ++uint8_t spi_read_status_register(void) ++{ ++ const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR }; ++ /* FIXME: No workarounds for driver/hardware bugs in generic code. */ ++ unsigned char readarr[2]; /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */ ++ int ret; ++ ++ /* Read Status Register */ ++ ret = spi_send_command(sizeof(cmd), sizeof(readarr), cmd, readarr); ++ if (ret) ++ fprintf(stderr, "RDSR failed!\n"); ++ ++ return readarr[0]; ++} ++ ++/* Prettyprint the status register. Common definitions. */ ++void spi_prettyprint_status_register_common(uint8_t status) ++{ ++ printf_debug("Chip status register: Bit 5 / Block Protect 3 (BP3) is " ++ "%sset\n", (status & (1 << 5)) ? "" : "not "); ++ printf_debug("Chip status register: Bit 4 / Block Protect 2 (BP2) is " ++ "%sset\n", (status & (1 << 4)) ? "" : "not "); ++ printf_debug("Chip status register: Bit 3 / Block Protect 1 (BP1) is " ++ "%sset\n", (status & (1 << 3)) ? "" : "not "); ++ printf_debug("Chip status register: Bit 2 / Block Protect 0 (BP0) is " ++ "%sset\n", (status & (1 << 2)) ? "" : "not "); ++ printf_debug("Chip status register: Write Enable Latch (WEL) is " ++ "%sset\n", (status & (1 << 1)) ? "" : "not "); ++ printf_debug("Chip status register: Write In Progress (WIP/BUSY) is " ++ "%sset\n", (status & (1 << 0)) ? "" : "not "); ++} ++ ++/* Prettyprint the status register. Works for ++ * ST M25P series ++ * MX MX25L series ++ */ ++void spi_prettyprint_status_register_st_m25p(uint8_t status) ++{ ++ printf_debug("Chip status register: Status Register Write Disable " ++ "(SRWD) is %sset\n", (status & (1 << 7)) ? "" : "not "); ++ printf_debug("Chip status register: Bit 6 is " ++ "%sset\n", (status & (1 << 6)) ? "" : "not "); ++ spi_prettyprint_status_register_common(status); ++} ++ ++void spi_prettyprint_status_register_sst25(uint8_t status) ++{ ++ printf_debug("Chip status register: Block Protect Write Disable " ++ "(BPL) is %sset\n", (status & (1 << 7)) ? "" : "not "); ++ printf_debug("Chip status register: Auto Address Increment Programming " ++ "(AAI) is %sset\n", (status & (1 << 6)) ? "" : "not "); ++ spi_prettyprint_status_register_common(status); ++} ++ ++/* Prettyprint the status register. Works for ++ * SST 25VF016 ++ */ ++void spi_prettyprint_status_register_sst25vf016(uint8_t status) ++{ ++ const char *bpt[] = { ++ "none", ++ "1F0000H-1FFFFFH", ++ "1E0000H-1FFFFFH", ++ "1C0000H-1FFFFFH", ++ "180000H-1FFFFFH", ++ "100000H-1FFFFFH", ++ "all", "all" ++ }; ++ spi_prettyprint_status_register_sst25(status); ++ printf_debug("Resulting block protection : %s\n", ++ bpt[(status & 0x1c) >> 2]); ++} ++ ++void spi_prettyprint_status_register_sst25vf040b(uint8_t status) ++{ ++ const char *bpt[] = { ++ "none", ++ "0x70000-0x7ffff", ++ "0x60000-0x7ffff", ++ "0x40000-0x7ffff", ++ "all blocks", "all blocks", "all blocks", "all blocks" ++ }; ++ spi_prettyprint_status_register_sst25(status); ++ printf_debug("Resulting block protection : %s\n", ++ bpt[(status & 0x1c) >> 2]); ++} ++ ++void spi_prettyprint_status_register(struct flashchip *flash) ++{ ++ uint8_t status; ++ ++ status = spi_read_status_register(); ++ printf_debug("Chip status register is %02x\n", status); ++ switch (flash->manufacture_id) { ++ case ST_ID: ++ if (((flash->model_id & 0xff00) == 0x2000) || ++ ((flash->model_id & 0xff00) == 0x2500)) ++ spi_prettyprint_status_register_st_m25p(status); ++ break; ++ case MX_ID: ++ if ((flash->model_id & 0xff00) == 0x2000) ++ spi_prettyprint_status_register_st_m25p(status); ++ break; ++ case SST_ID: ++ switch (flash->model_id) { ++ case 0x2541: ++ spi_prettyprint_status_register_sst25vf016(status); ++ break; ++ case 0x8d: ++ case 0x258d: ++ spi_prettyprint_status_register_sst25vf040b(status); ++ break; ++ default: ++ spi_prettyprint_status_register_sst25(status); ++ break; ++ } ++ break; ++ } ++} ++ ++int spi_chip_erase_60(struct flashchip *flash) ++{ ++ int result; + struct spi_command cmds[] = { - { - .writecnt = JEDEC_WREN_OUTSIZE, - .writearr = (const unsigned char[]){ JEDEC_WREN }, -@@ -514,7 +555,7 @@ int spi_chip_erase_60(struct flashchip *flash) - return result; - } - -- result = spi_send_multicommand(spicommands); ++ { ++ .writecnt = JEDEC_WREN_OUTSIZE, ++ .writearr = (const unsigned char[]){ JEDEC_WREN }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = JEDEC_CE_60_OUTSIZE, ++ .writearr = (const unsigned char[]){ JEDEC_CE_60 }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = 0, ++ .writearr = NULL, ++ .readcnt = 0, ++ .readarr = NULL, ++ }}; ++ ++ result = spi_disable_blockprotect(); ++ if (result) { ++ fprintf(stderr, "spi_disable_blockprotect failed\n"); ++ return result; ++ } ++ + result = spi_send_multicommand(cmds); - if (result) { - fprintf(stderr, "%s failed during command execution\n", - __func__); -@@ -536,7 +577,7 @@ int spi_chip_erase_60(struct flashchip *flash) - int spi_chip_erase_c7(struct flashchip *flash) - { - int result; -- struct spi_command spicommands[] = { ++ if (result) { ++ fprintf(stderr, "%s failed during command execution\n", ++ __func__); ++ return result; ++ } ++ /* Wait until the Write-In-Progress bit is cleared. ++ * 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() & JEDEC_RDSR_BIT_WIP) ++ programmer_delay(1000 * 1000); ++ if (check_erased_range(flash, 0, flash->total_size * 1024)) { ++ fprintf(stderr, "ERASE FAILED!\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++int spi_chip_erase_c7(struct flashchip *flash) ++{ ++ int result; + struct spi_command cmds[] = { - { - .writecnt = JEDEC_WREN_OUTSIZE, - .writearr = (const unsigned char[]){ JEDEC_WREN }, -@@ -560,7 +601,7 @@ int spi_chip_erase_c7(struct flashchip *flash) - return result; - } - -- result = spi_send_multicommand(spicommands); ++ { ++ .writecnt = JEDEC_WREN_OUTSIZE, ++ .writearr = (const unsigned char[]){ JEDEC_WREN }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = JEDEC_CE_C7_OUTSIZE, ++ .writearr = (const unsigned char[]){ JEDEC_CE_C7 }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = 0, ++ .writearr = NULL, ++ .readcnt = 0, ++ .readarr = NULL, ++ }}; ++ ++ result = spi_disable_blockprotect(); ++ if (result) { ++ fprintf(stderr, "spi_disable_blockprotect failed\n"); ++ return result; ++ } ++ + result = spi_send_multicommand(cmds); - if (result) { - fprintf(stderr, "%s failed during command execution\n", __func__); - return result; -@@ -592,7 +633,7 @@ int spi_chip_erase_60_c7(struct flashchip *flash) - int spi_block_erase_52(struct flashchip *flash, unsigned int addr, unsigned int blocklen) - { - int result; -- struct spi_command spicommands[] = { ++ if (result) { ++ fprintf(stderr, "%s failed during command execution\n", __func__); ++ return result; ++ } ++ /* Wait until the Write-In-Progress bit is cleared. ++ * 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() & JEDEC_RDSR_BIT_WIP) ++ programmer_delay(1000 * 1000); ++ if (check_erased_range(flash, 0, flash->total_size * 1024)) { ++ fprintf(stderr, "ERASE FAILED!\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++int spi_chip_erase_60_c7(struct flashchip *flash) ++{ ++ int result; ++ result = spi_chip_erase_60(flash); ++ if (result) { ++ printf_debug("spi_chip_erase_60 failed, trying c7\n"); ++ result = spi_chip_erase_c7(flash); ++ } ++ return result; ++} ++ ++int spi_block_erase_52(struct flashchip *flash, unsigned int addr, unsigned int blocklen) ++{ ++ int result; + struct spi_command cmds[] = { - { - .writecnt = JEDEC_WREN_OUTSIZE, - .writearr = (const unsigned char[]){ JEDEC_WREN }, -@@ -610,10 +651,10 @@ int spi_block_erase_52(struct flashchip *flash, unsigned int addr, unsigned int - .readarr = NULL, - }}; - -- result = spi_send_multicommand(spicommands); ++ { ++ .writecnt = JEDEC_WREN_OUTSIZE, ++ .writearr = (const unsigned char[]){ JEDEC_WREN }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = JEDEC_BE_52_OUTSIZE, ++ .writearr = (const unsigned char[]){ ++ JEDEC_BE_52, ++ (addr >> 16) & 0xff, ++ (addr >> 8) & 0xff, ++ (addr & 0xff) ++ }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = 0, ++ .writearr = NULL, ++ .readcnt = 0, ++ .readarr = NULL, ++ }}; ++ + result = spi_send_multicommand(cmds); - if (result) { -- fprintf(stderr, "%s failed during command execution\n", -- __func__); ++ if (result) { + fprintf(stderr, "%s failed during command execution at address 0x%x\n", + __func__, addr); - return result; - } - /* Wait until the Write-In-Progress bit is cleared. -@@ -636,7 +677,7 @@ int spi_block_erase_52(struct flashchip *flash, unsigned int addr, unsigned int - int spi_block_erase_d8(struct flashchip *flash, unsigned int addr, unsigned int blocklen) - { - int result; -- struct spi_command spicommands[] = { ++ return result; ++ } ++ /* 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() & JEDEC_RDSR_BIT_WIP) ++ programmer_delay(100 * 1000); ++ if (check_erased_range(flash, addr, blocklen)) { ++ fprintf(stderr, "ERASE FAILED!\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++/* Block size is usually ++ * 64k for Macronix ++ * 32k for SST ++ * 4-32k non-uniform for EON ++ */ ++int spi_block_erase_d8(struct flashchip *flash, unsigned int addr, unsigned int blocklen) ++{ ++ int result; + struct spi_command cmds[] = { - { - .writecnt = JEDEC_WREN_OUTSIZE, - .writearr = (const unsigned char[]){ JEDEC_WREN }, -@@ -654,9 +695,52 @@ int spi_block_erase_d8(struct flashchip *flash, unsigned int addr, unsigned int - .readarr = NULL, - }}; - -- result = spi_send_multicommand(spicommands); ++ { ++ .writecnt = JEDEC_WREN_OUTSIZE, ++ .writearr = (const unsigned char[]){ JEDEC_WREN }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = JEDEC_BE_D8_OUTSIZE, ++ .writearr = (const unsigned char[]){ ++ JEDEC_BE_D8, ++ (addr >> 16) & 0xff, ++ (addr >> 8) & 0xff, ++ (addr & 0xff) ++ }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = 0, ++ .writearr = NULL, ++ .readcnt = 0, ++ .readarr = NULL, ++ }}; ++ + result = spi_send_multicommand(cmds); - if (result) { -- fprintf(stderr, "%s failed during command execution\n", __func__); ++ if (result) { + fprintf(stderr, "%s failed during command execution at address 0x%x\n", + __func__, addr); + return result; @@ -17149,7 +20082,12 @@ index 7f678a1..e1ab2ea 100644 + .readarr = NULL, + }, { + .writecnt = JEDEC_BE_D7_OUTSIZE, -+ .writearr = (const unsigned char[]){ JEDEC_BE_D7, (addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr & 0xff) }, ++ .writearr = (const unsigned char[]){ ++ JEDEC_BE_D7, ++ (addr >> 16) & 0xff, ++ (addr >> 8) & 0xff, ++ (addr & 0xff) ++ }, + .readcnt = 0, + .readarr = NULL, + }, { @@ -17163,194 +20101,377 @@ index 7f678a1..e1ab2ea 100644 + if (result) { + fprintf(stderr, "%s failed during command execution at address 0x%x\n", + __func__, addr); - return result; - } - /* Wait until the Write-In-Progress bit is cleared. -@@ -698,7 +782,7 @@ int spi_chip_erase_d8(struct flashchip *flash) - int spi_block_erase_20(struct flashchip *flash, unsigned int addr, unsigned int blocklen) - { - int result; -- struct spi_command spicommands[] = { ++ return result; ++ } ++ /* 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() & JEDEC_RDSR_BIT_WIP) ++ programmer_delay(100 * 1000); ++ if (check_erased_range(flash, addr, blocklen)) { ++ fprintf(stderr, "ERASE FAILED!\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++int spi_chip_erase_d8(struct flashchip *flash) ++{ ++ int i, rc = 0; ++ int total_size = flash->total_size * 1024; ++ int erase_size = 64 * 1024; ++ ++ spi_disable_blockprotect(); ++ ++ printf("Erasing chip: \n"); ++ ++ for (i = 0; i < total_size / erase_size; i++) { ++ rc = spi_block_erase_d8(flash, i * erase_size, erase_size); ++ if (rc) { ++ fprintf(stderr, "Error erasing block at 0x%x\n", i); ++ break; ++ } ++ } ++ ++ printf("\n"); ++ ++ return rc; ++} ++ ++/* Sector size is usually 4k, though Macronix eliteflash has 64k */ ++int spi_block_erase_20(struct flashchip *flash, unsigned int addr, unsigned int blocklen) ++{ ++ int result; + struct spi_command cmds[] = { - { - .writecnt = JEDEC_WREN_OUTSIZE, - .writearr = (const unsigned char[]){ JEDEC_WREN }, -@@ -716,10 +800,10 @@ int spi_block_erase_20(struct flashchip *flash, unsigned int addr, unsigned int - .readarr = NULL, - }}; - -- result = spi_send_multicommand(spicommands); ++ { ++ .writecnt = JEDEC_WREN_OUTSIZE, ++ .writearr = (const unsigned char[]){ JEDEC_WREN }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = JEDEC_SE_OUTSIZE, ++ .writearr = (const unsigned char[]){ ++ JEDEC_SE, ++ (addr >> 16) & 0xff, ++ (addr >> 8) & 0xff, ++ (addr & 0xff) ++ }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = 0, ++ .writearr = NULL, ++ .readcnt = 0, ++ .readarr = NULL, ++ }}; ++ + result = spi_send_multicommand(cmds); - if (result) { -- fprintf(stderr, "%s failed during command execution\n", -- __func__); ++ if (result) { + fprintf(stderr, "%s failed during command execution at address 0x%x\n", + __func__, addr); - return result; - } - /* Wait until the Write-In-Progress bit is cleared. -@@ -775,8 +859,9 @@ int spi_write_status_enable(void) - int spi_write_status_register(int status) - { - int result; -- struct spi_command spicommands[] = { ++ return result; ++ } ++ /* 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() & JEDEC_RDSR_BIT_WIP) ++ programmer_delay(10 * 1000); ++ if (check_erased_range(flash, addr, blocklen)) { ++ fprintf(stderr, "ERASE FAILED!\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++int spi_block_erase_60(struct flashchip *flash, unsigned int addr, unsigned int blocklen) ++{ ++ if ((addr != 0) || (blocklen != flash->total_size * 1024)) { ++ fprintf(stderr, "%s called with incorrect arguments\n", ++ __func__); ++ return -1; ++ } ++ return spi_chip_erase_60(flash); ++} ++ ++int spi_block_erase_c7(struct flashchip *flash, unsigned int addr, unsigned int blocklen) ++{ ++ if ((addr != 0) || (blocklen != flash->total_size * 1024)) { ++ fprintf(stderr, "%s called with incorrect arguments\n", ++ __func__); ++ return -1; ++ } ++ return spi_chip_erase_c7(flash); ++} ++ ++int spi_write_status_enable(void) ++{ ++ const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR }; ++ int result; ++ ++ /* Send EWSR (Enable Write Status Register). */ ++ result = spi_send_command(sizeof(cmd), JEDEC_EWSR_INSIZE, cmd, NULL); ++ ++ if (result) ++ fprintf(stderr, "%s failed\n", __func__); ++ ++ return result; ++} ++ ++/* ++ * This is according the SST25VF016 datasheet, who knows it is more ++ * generic that this... ++ */ ++int spi_write_status_register(int status) ++{ ++ int result; + struct spi_command cmds[] = { - { ++ { + /* FIXME: WRSR requires either EWSR or WREN depending on chip type. */ - .writecnt = JEDEC_EWSR_OUTSIZE, - .writearr = (const unsigned char[]){ JEDEC_EWSR }, - .readcnt = 0, -@@ -793,7 +878,7 @@ int spi_write_status_register(int status) - .readarr = NULL, - }}; - -- result = spi_send_multicommand(spicommands); ++ .writecnt = JEDEC_EWSR_OUTSIZE, ++ .writearr = (const unsigned char[]){ JEDEC_EWSR }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = JEDEC_WRSR_OUTSIZE, ++ .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = 0, ++ .writearr = NULL, ++ .readcnt = 0, ++ .readarr = NULL, ++ }}; ++ + result = spi_send_multicommand(cmds); - if (result) { - fprintf(stderr, "%s failed during command execution\n", - __func__); -@@ -801,10 +886,10 @@ int spi_write_status_register(int status) - return result; - } - --int spi_byte_program(int addr, uint8_t byte) ++ if (result) { ++ fprintf(stderr, "%s failed during command execution\n", ++ __func__); ++ } ++ return result; ++} ++ +int spi_byte_program(int addr, uint8_t databyte) - { - int result; -- struct spi_command spicommands[] = { ++{ ++ int result; + struct spi_command cmds[] = { - { - .writecnt = JEDEC_WREN_OUTSIZE, - .writearr = (const unsigned char[]){ JEDEC_WREN }, -@@ -812,7 +897,7 @@ int spi_byte_program(int addr, uint8_t byte) - .readarr = NULL, - }, { - .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE, -- .writearr = (const unsigned char[]){ JEDEC_BYTE_PROGRAM, (addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr & 0xff), byte }, -+ .writearr = (const unsigned char[]){ JEDEC_BYTE_PROGRAM, (addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr & 0xff), databyte }, - .readcnt = 0, - .readarr = NULL, - }, { -@@ -822,25 +907,25 @@ int spi_byte_program(int addr, uint8_t byte) - .readarr = NULL, - }}; - -- result = spi_send_multicommand(spicommands); ++ { ++ .writecnt = JEDEC_WREN_OUTSIZE, ++ .writearr = (const unsigned char[]){ JEDEC_WREN }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE, ++ .writearr = (const unsigned char[]){ ++ JEDEC_BYTE_PROGRAM, ++ (addr >> 16) & 0xff, ++ (addr >> 8) & 0xff, ++ (addr & 0xff), ++ databyte ++ }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = 0, ++ .writearr = NULL, ++ .readcnt = 0, ++ .readarr = NULL, ++ }}; ++ + result = spi_send_multicommand(cmds); - if (result) { -- fprintf(stderr, "%s failed during command execution\n", -- __func__); ++ if (result) { + fprintf(stderr, "%s failed during command execution at address 0x%x\n", + __func__, addr); - } - return result; - } - --int spi_nbyte_program(int address, uint8_t *bytes, int len) ++ } ++ return result; ++} ++ +int spi_nbyte_program(int addr, uint8_t *bytes, int len) - { - int result; - /* FIXME: Switch to malloc based on len unless that kills speed. */ - unsigned char cmd[JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + 256] = { - JEDEC_BYTE_PROGRAM, -- (address >> 16) & 0xff, -- (address >> 8) & 0xff, -- (address >> 0) & 0xff, ++{ ++ int result; ++ /* FIXME: Switch to malloc based on len unless that kills speed. */ ++ unsigned char cmd[JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + 256] = { ++ JEDEC_BYTE_PROGRAM, + (addr >> 16) & 0xff, + (addr >> 8) & 0xff, + (addr >> 0) & 0xff, - }; -- struct spi_command spicommands[] = { ++ }; + struct spi_command cmds[] = { - { - .writecnt = JEDEC_WREN_OUTSIZE, - .writearr = (const unsigned char[]){ JEDEC_WREN }, -@@ -869,10 +954,10 @@ int spi_nbyte_program(int address, uint8_t *bytes, int len) - - memcpy(&cmd[4], bytes, len); - -- result = spi_send_multicommand(spicommands); ++ { ++ .writecnt = JEDEC_WREN_OUTSIZE, ++ .writearr = (const unsigned char[]){ JEDEC_WREN }, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + len, ++ .writearr = cmd, ++ .readcnt = 0, ++ .readarr = NULL, ++ }, { ++ .writecnt = 0, ++ .writearr = NULL, ++ .readcnt = 0, ++ .readarr = NULL, ++ }}; ++ ++ if (!len) { ++ fprintf(stderr, "%s called for zero-length write\n", __func__); ++ return 1; ++ } ++ if (len > 256) { ++ fprintf(stderr, "%s called for too long a write\n", __func__); ++ return 1; ++ } ++ ++ memcpy(&cmd[4], bytes, len); ++ + result = spi_send_multicommand(cmds); - if (result) { -- fprintf(stderr, "%s failed during command execution\n", -- __func__); ++ if (result) { + fprintf(stderr, "%s failed during command execution at address 0x%x\n", + __func__, addr); - } - return result; - } -@@ -967,18 +1052,20 @@ int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len) - int spi_chip_write_1(struct flashchip *flash, uint8_t *buf) - { - int total_size = 1024 * flash->total_size; -- int i; ++ } ++ return result; ++} ++ ++int spi_disable_blockprotect(void) ++{ ++ uint8_t status; ++ int result; ++ ++ status = spi_read_status_register(); ++ /* If there is block protection in effect, unprotect it first. */ ++ if ((status & 0x3c) != 0) { ++ printf_debug("Some block protection in effect, disabling\n"); ++ result = spi_write_status_register(status & ~0x3c); ++ if (result) { ++ fprintf(stderr, "spi_write_status_register failed\n"); ++ return result; ++ } ++ } ++ return 0; ++} ++ ++int spi_nbyte_read(int address, uint8_t *bytes, int len) ++{ ++ const unsigned char cmd[JEDEC_READ_OUTSIZE] = { ++ JEDEC_READ, ++ (address >> 16) & 0xff, ++ (address >> 8) & 0xff, ++ (address >> 0) & 0xff, ++ }; ++ ++ /* Send Read */ ++ return spi_send_command(sizeof(cmd), len, cmd, bytes); ++} ++ ++/* ++ * Read a complete flash chip. ++ * 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) ++{ ++ int rc = 0; ++ int i, j, starthere, lenhere; ++ int page_size = flash->page_size; ++ int toread; ++ ++ /* Warning: This loop has a very unusual condition and body. ++ * The loop needs to go through each page with at least one affected ++ * byte. The lowest page number is (start / page_size) since that ++ * division rounds down. The highest page number we want is the page ++ * where the last byte of the range lives. That last byte has the ++ * address (start + len - 1), thus the highest page number is ++ * (start + len - 1) / page_size. Since we want to include that last ++ * page as well, the loop condition uses <=. ++ */ ++ for (i = start / page_size; i <= (start + len - 1) / page_size; i++) { ++ /* Byte position of the first byte in the range in this page. */ ++ /* starthere is an offset to the base address of the chip. */ ++ starthere = max(start, i * page_size); ++ /* Length of bytes in the range in this page. */ ++ lenhere = min(start + len, (i + 1) * page_size) - starthere; ++ for (j = 0; j < lenhere; j += chunksize) { ++ toread = min(chunksize, lenhere - j); ++ rc = spi_nbyte_read(starthere + j, buf + starthere - start + j, toread); ++ if (rc) ++ break; ++ } ++ if (rc) ++ break; ++ } ++ ++ return rc; ++} ++ ++/* ++ * Program chip using byte programming. (SLOW!) ++ * This is for chips which can only handle one byte writes ++ * 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) ++{ ++ int total_size = 1024 * flash->total_size; + int i, result = 0; - - spi_disable_blockprotect(); - /* Erase first */ - printf("Erasing flash before programming... "); -- if (flash->erase(flash)) { ++ ++ spi_disable_blockprotect(); ++ /* Erase first */ ++ printf("Erasing flash before programming... "); + if (erase_flash(flash)) { - fprintf(stderr, "ERASE FAILED!\n"); - return -1; - } - printf("done.\n"); - for (i = 0; i < total_size; i++) { -- spi_byte_program(i, buf[i]); ++ fprintf(stderr, "ERASE FAILED!\n"); ++ return -1; ++ } ++ printf("done.\n"); ++ for (i = 0; i < total_size; i++) { + result = spi_byte_program(i, buf[i]); + if (result) + return 1; - while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) - programmer_delay(10); - } -@@ -1014,17 +1101,20 @@ int spi_aai_write(struct flashchip *flash, uint8_t *buf) - int result; - - switch (spi_controller) { -+#if INTERNAL_SUPPORT == 1 - case SPI_CONTROLLER_WBSIO: - fprintf(stderr, "%s: impossible with Winbond SPI masters," - " degrading to byte program\n", __func__); - return spi_chip_write_1(flash, buf); -+#endif - default: - break; - } -- if (flash->erase(flash)) { -+ if (erase_flash(flash)) { - fprintf(stderr, "ERASE FAILED!\n"); - return -1; - } -+ /* FIXME: This will fail on ICH/VIA SPI. */ - result = spi_write_enable(); - if (result) - return result; -diff --git a/spi.h b/spi.h -index 3050ccf..1b49d59 100644 ---- a/spi.h -+++ b/spi.h -@@ -74,6 +74,11 @@ - #define JEDEC_BE_D8_OUTSIZE 0x04 - #define JEDEC_BE_D8_INSIZE 0x00 - -+/* Block Erase 0xd7 is supported by PMC chips. */ -+#define JEDEC_BE_D7 0xd7 -+#define JEDEC_BE_D7_OUTSIZE 0x04 -+#define JEDEC_BE_D7_INSIZE 0x00 ++ while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) ++ programmer_delay(10); ++ } + - /* Sector Erase 0x20 is supported by Macronix/SST chips. */ - #define JEDEC_SE 0x20 - #define JEDEC_SE_OUTSIZE 0x04 -@@ -106,6 +111,7 @@ - #define JEDEC_BYTE_PROGRAM_INSIZE 0x00 - - /* Error codes */ -+#define SPI_GENERIC_ERROR -1 - #define SPI_INVALID_OPCODE -2 - #define SPI_INVALID_ADDRESS -3 - #define SPI_INVALID_LENGTH -4 ++ return 0; ++} ++ ++int spi_aai_write(struct flashchip *flash, uint8_t *buf) ++{ ++ uint32_t pos = 2, size = flash->total_size * 1024; ++ unsigned char w[6] = {0xad, 0, 0, 0, buf[0], buf[1]}; ++ int result; ++ ++ switch (spi_controller) { ++#if INTERNAL_SUPPORT == 1 ++ case SPI_CONTROLLER_WBSIO: ++ fprintf(stderr, "%s: impossible with Winbond SPI masters," ++ " degrading to byte program\n", __func__); ++ return spi_chip_write_1(flash, buf); ++#endif ++ default: ++ break; ++ } ++ if (erase_flash(flash)) { ++ fprintf(stderr, "ERASE FAILED!\n"); ++ return -1; ++ } ++ /* FIXME: This will fail on ICH/VIA SPI. */ ++ result = spi_write_enable(); ++ if (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 */ ++ } ++ spi_write_disable(); ++ return 0; ++} diff --git a/sst28sf040.c b/sst28sf040.c -index 35f8c27..f253e39 100644 +index 35f8c27..bbb9d56 100644 --- a/sst28sf040.c +++ b/sst28sf040.c @@ -3,6 +3,7 @@ @@ -17361,7 +20482,15 @@ index 35f8c27..f253e39 100644 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -@@ -30,31 +31,27 @@ +@@ -20,6 +21,7 @@ + */ + + #include "flash.h" ++#include "chipdrivers.h" + + #define AUTO_PG_ERASE1 0x20 + #define AUTO_PG_ERASE2 0xD0 +@@ -30,31 +32,27 @@ static void protect_28sf040(chipaddr bios) { @@ -17408,7 +20537,7 @@ index 35f8c27..f253e39 100644 { chipaddr bios = flash->virtual_memory; -@@ -71,7 +68,7 @@ static int erase_sector_28sf040(struct flashchip *flash, unsigned long address, +@@ -71,7 +69,7 @@ static int erase_sector_28sf040(struct flashchip *flash, unsigned long address, return 0; } @@ -17417,7 +20546,7 @@ index 35f8c27..f253e39 100644 unsigned int page_size) { int i; -@@ -111,7 +108,7 @@ int probe_28sf040(struct flashchip *flash) +@@ -111,7 +109,7 @@ int probe_28sf040(struct flashchip *flash) chip_writeb(RESET, bios); programmer_delay(10); @@ -17426,7 +20555,7 @@ index 35f8c27..f253e39 100644 if (id1 == flash->manufacture_id && id2 == flash->model_id) return 1; -@@ -166,3 +163,13 @@ int write_28sf040(struct flashchip *flash, uint8_t *buf) +@@ -166,3 +164,13 @@ int write_28sf040(struct flashchip *flash, uint8_t *buf) return 0; } @@ -17441,22 +20570,85 @@ index 35f8c27..f253e39 100644 + return erase_28sf040(flash); +} diff --git a/sst49lf040.c b/sst49lf040.c -index ab1c918..c91a139 100644 +deleted file mode 100644 +index ab1c918..0000000 --- a/sst49lf040.c -+++ b/sst49lf040.c -@@ -59,8 +59,8 @@ int write_49lf040(struct flashchip *flash, uint8_t *buf) - if (i % 10 == 0) - printf("%04d at address: 0x%08x ", i, i * page_size); - ++++ /dev/null +@@ -1,72 +0,0 @@ +-/* +- * This file is part of the flashrom project. +- * +- * Copyright (C) 2000 Silicon Integrated System Corporation +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ +- +-#include "flash.h" +- +-int erase_49lf040(struct flashchip *flash) +-{ +- int i; +- int total_size = flash->total_size * 1024; +- int page_size = flash->page_size; +- +- for (i = 0; i < total_size / page_size; i++) { +- /* Chip erase only works in parallel programming mode +- * for the 49lf040. Use sector-erase instead */ +- if (erase_sector_jedec(flash, i * page_size, page_size)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- } +- +- return 0; +-} +- +-int write_49lf040(struct flashchip *flash, uint8_t *buf) +-{ +- int i; +- int total_size = flash->total_size * 1024; +- int page_size = flash->page_size; +- chipaddr bios = flash->virtual_memory; +- +- printf("Programming page: "); +- for (i = 0; i < total_size / page_size; i++) { +- /* erase the page before programming +- * Chip erase only works in parallel programming mode +- * for the 49lf040. Use sector-erase instead */ +- if (erase_sector_jedec(flash, i * page_size, page_size)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- +- /* write to the sector */ +- if (i % 10 == 0) +- printf("%04d at address: 0x%08x ", i, i * page_size); +- - write_sector_jedec(bios, buf + i * page_size, - bios + i * page_size, page_size); -+ write_sector_jedec_common(flash, buf + i * page_size, -+ bios + i * page_size, page_size, 0xffff); - - if (i % 10 == 0) - printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); +- +- if (i % 10 == 0) +- printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); +- fflush(stdout); +- } +- printf("\n"); +- +- return 0; +-} diff --git a/sst49lfxxxc.c b/sst49lfxxxc.c -index 848ccde..80e5520 100644 +index 848ccde..9f9ee30 100644 --- a/sst49lfxxxc.c +++ b/sst49lfxxxc.c @@ -3,6 +3,7 @@ @@ -17467,7 +20659,15 @@ index 848ccde..80e5520 100644 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -@@ -35,6 +36,15 @@ +@@ -21,6 +22,7 @@ + + #include + #include "flash.h" ++#include "chipdrivers.h" + + #define SECTOR_ERASE 0x30 + #define BLOCK_ERASE 0x20 +@@ -35,6 +37,15 @@ #define STATUS_ESS (1 << 6) #define STATUS_WSMS (1 << 7) @@ -17483,16 +20683,21 @@ index 848ccde..80e5520 100644 static int write_lockbits_49lfxxxc(struct flashchip *flash, unsigned char bits) { chipaddr registers = flash->virtual_registers; -@@ -72,7 +82,7 @@ static int write_lockbits_49lfxxxc(struct flashchip *flash, unsigned char bits) +@@ -72,7 +83,12 @@ static int write_lockbits_49lfxxxc(struct flashchip *flash, unsigned char bits) return 0; } -static int erase_sector_49lfxxxc(struct flashchip *flash, unsigned long address, int sector_size) ++int unlock_49lfxxxc(struct flashchip *flash) ++{ ++ return write_lockbits_49lfxxxc(flash, 0); ++} ++ +int erase_sector_49lfxxxc(struct flashchip *flash, unsigned int address, unsigned int sector_size) { unsigned char status; chipaddr bios = flash->virtual_memory; -@@ -97,6 +107,31 @@ static int erase_sector_49lfxxxc(struct flashchip *flash, unsigned long address, +@@ -97,6 +113,31 @@ static int erase_sector_49lfxxxc(struct flashchip *flash, unsigned long address, return 0; } @@ -17524,7 +20729,7 @@ index 848ccde..80e5520 100644 static int write_sector_49lfxxxc(chipaddr bios, uint8_t *src, chipaddr dst, unsigned int page_size) { -@@ -141,7 +176,7 @@ int probe_49lfxxxc(struct flashchip *flash) +@@ -141,7 +182,7 @@ int probe_49lfxxxc(struct flashchip *flash) chip_writeb(RESET, bios); @@ -17534,7 +20739,7 @@ index 848ccde..80e5520 100644 if (!(id1 == flash->manufacture_id && id2 == flash->model_id)) return 0; diff --git a/sst_fwhub.c b/sst_fwhub.c -index e7ae9e9..75d9e05 100644 +index e7ae9e9..9819cee 100644 --- a/sst_fwhub.c +++ b/sst_fwhub.c @@ -2,6 +2,8 @@ @@ -17546,16 +20751,18 @@ index e7ae9e9..75d9e05 100644 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -@@ -20,6 +22,8 @@ +@@ -20,7 +22,10 @@ /* Adapted from the Intel FW hub stuff for 82802ax parts. */ +#include +#include #include "flash.h" ++#include "chipdrivers.h" // I need that Berkeley bit-map printer -@@ -86,15 +90,13 @@ int probe_sst_fwhub(struct flashchip *flash) + void print_sst_fwhub_status(uint8_t status) +@@ -86,15 +91,13 @@ int probe_sst_fwhub(struct flashchip *flash) if (probe_jedec(flash) == 0) return 0; @@ -17572,7 +20779,7 @@ index e7ae9e9..75d9e05 100644 { uint8_t blockstatus = clear_sst_fwhub_block_lock(flash, offset); -@@ -113,6 +115,25 @@ int erase_sst_fwhub_block(struct flashchip *flash, int offset, int page_size) +@@ -113,6 +116,25 @@ int erase_sst_fwhub_block(struct flashchip *flash, int offset, int page_size) return 0; } @@ -17598,7 +20805,7 @@ index e7ae9e9..75d9e05 100644 int erase_sst_fwhub(struct flashchip *flash) { int i; -@@ -130,28 +151,33 @@ int erase_sst_fwhub(struct flashchip *flash) +@@ -130,28 +152,33 @@ int erase_sst_fwhub(struct flashchip *flash) int write_sst_fwhub(struct flashchip *flash, uint8_t *buf) { @@ -17648,7 +20855,7 @@ index e7ae9e9..75d9e05 100644 } printf("\n"); diff --git a/stm50flw0x0x.c b/stm50flw0x0x.c -index 30b7d50..3b56436 100644 +index 30b7d50..7095aec 100644 --- a/stm50flw0x0x.c +++ b/stm50flw0x0x.c @@ -2,6 +2,7 @@ @@ -17659,10 +20866,11 @@ index 30b7d50..3b56436 100644 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -@@ -31,81 +32,19 @@ +@@ -30,82 +31,21 @@ + #include #include "flash.h" #include "flashchips.h" - +- -void protect_stm50flw0x0x(chipaddr bios) -{ - chip_writeb(0xAA, bios + 0x5555); @@ -17722,7 +20930,8 @@ index 30b7d50..3b56436 100644 - - return 1; -} -- ++#include "chipdrivers.h" + static void wait_stm50flw0x0x(chipaddr bios) { - uint8_t id1; @@ -17743,7 +20952,7 @@ index 30b7d50..3b56436 100644 // this is needed to jam it out of "read id" mode chip_writeb(0xAA, bios + 0x5555); -@@ -161,9 +100,9 @@ int unlock_block_stm50flw0x0x(struct flashchip *flash, int offset) +@@ -161,9 +101,9 @@ int unlock_block_stm50flw0x0x(struct flashchip *flash, int offset) return 0; } @@ -17755,7 +20964,7 @@ index 30b7d50..3b56436 100644 // clear status register chip_writeb(0x50, bios); -@@ -175,11 +114,34 @@ int erase_block_stm50flw0x0x(struct flashchip *flash, int offset) +@@ -175,11 +115,34 @@ int erase_block_stm50flw0x0x(struct flashchip *flash, int offset) wait_stm50flw0x0x(flash->virtual_memory); @@ -17792,7 +21001,7 @@ index 30b7d50..3b56436 100644 return 0; } -@@ -230,7 +192,6 @@ int erase_stm50flw0x0x(struct flashchip *flash) +@@ -230,7 +193,6 @@ int erase_stm50flw0x0x(struct flashchip *flash) int i; int total_size = flash->total_size * 1024; int page_size = flash->page_size; @@ -17800,7 +21009,7 @@ index 30b7d50..3b56436 100644 printf("Erasing page:\n"); for (i = 0; i < total_size / page_size; i++) { -@@ -241,17 +202,26 @@ int erase_stm50flw0x0x(struct flashchip *flash) +@@ -241,17 +203,26 @@ int erase_stm50flw0x0x(struct flashchip *flash) fprintf(stderr, "UNLOCK FAILED!\n"); return -1; } @@ -17829,7 +21038,7 @@ index 30b7d50..3b56436 100644 int write_stm50flw0x0x(struct flashchip *flash, uint8_t * buf) { int i, rc = 0; -@@ -285,13 +255,12 @@ int write_stm50flw0x0x(struct flashchip *flash, uint8_t * buf) +@@ -285,13 +256,12 @@ int write_stm50flw0x0x(struct flashchip *flash, uint8_t * buf) rc = unlock_block_stm50flw0x0x(flash, i * page_size); if (!rc) @@ -17866,10 +21075,18 @@ index 9a0ab36..f61d793 100644 +} + diff --git a/w29ee011.c b/w29ee011.c -index a26cd80..de9a547 100644 +index a26cd80..63cf4fc 100644 --- a/w29ee011.c +++ b/w29ee011.c -@@ -61,7 +61,7 @@ int probe_w29ee011(struct flashchip *flash) +@@ -20,6 +20,7 @@ + + #include + #include "flash.h" ++#include "chipdrivers.h" + + int probe_w29ee011(struct flashchip *flash) + { +@@ -61,7 +62,7 @@ int probe_w29ee011(struct flashchip *flash) chip_writeb(0xF0, bios + 0x5555); programmer_delay(10); @@ -17879,10 +21096,15 @@ index a26cd80..de9a547 100644 if (id1 == flash->manufacture_id && id2 == flash->model_id) return 1; diff --git a/w39v040c.c b/w39v040c.c -index 7fccd53..66ab115 100644 +index 7fccd53..20e53fa 100644 --- a/w39v040c.c +++ b/w39v040c.c -@@ -23,7 +23,11 @@ +@@ -19,11 +19,16 @@ + */ + + #include "flash.h" ++#include "chipdrivers.h" + int probe_w39v040c(struct flashchip *flash) { chipaddr bios = flash->virtual_memory; @@ -17895,7 +21117,7 @@ index 7fccd53..66ab115 100644 chip_writeb(0xAA, bios + 0x5555); programmer_delay(10); -@@ -32,8 +36,6 @@ int probe_w39v040c(struct flashchip *flash) +@@ -32,8 +37,6 @@ int probe_w39v040c(struct flashchip *flash) chip_writeb(0x90, bios + 0x5555); programmer_delay(10); @@ -17904,7 +21126,7 @@ index 7fccd53..66ab115 100644 lock = chip_readb(bios + 0xfff2); chip_writeb(0xAA, bios + 0x5555); -@@ -43,17 +45,9 @@ int probe_w39v040c(struct flashchip *flash) +@@ -43,16 +46,34 @@ int probe_w39v040c(struct flashchip *flash) chip_writeb(0xF0, bios + 0x5555); programmer_delay(40); @@ -17917,15 +21139,38 @@ index 7fccd53..66ab115 100644 - __func__, lock & 0x4 ? "" : "un", lock & 0x8 ? "" : "un"); - return 1; - } -- -- return 0; + printf("%s: Boot block #TBL is %slocked, rest of chip #WP is %slocked.\n", + __func__, lock & 0x4 ? "" : "un", lock & 0x8 ? "" : "un"); + return 1; ++} ++ ++int printlock_w39v040c(struct flashchip *flash) ++{ ++ chipaddr bios = flash->virtual_memory; ++ uint8_t lock; ++ ++ chip_writeb(0xAA, bios + 0x5555); ++ programmer_delay(10); ++ chip_writeb(0x55, bios + 0x2AAA); ++ programmer_delay(10); ++ chip_writeb(0x90, bios + 0x5555); ++ programmer_delay(10); ++ ++ lock = chip_readb(bios + 0xfff2); ++ ++ chip_writeb(0xAA, bios + 0x5555); ++ programmer_delay(10); ++ chip_writeb(0x55, bios + 0x2AAA); ++ programmer_delay(10); ++ chip_writeb(0xF0, bios + 0x5555); ++ programmer_delay(40); + ++ printf("%s: Boot block #TBL is %slocked, rest of chip #WP is %slocked.\n", ++ __func__, lock & 0x4 ? "" : "un", lock & 0x8 ? "" : "un"); + return 0; } - int erase_w39v040c(struct flashchip *flash) -@@ -78,7 +72,7 @@ int write_w39v040c(struct flashchip *flash, uint8_t *buf) +@@ -78,7 +99,7 @@ int write_w39v040c(struct flashchip *flash, uint8_t *buf) int page_size = flash->page_size; chipaddr bios = flash->virtual_memory; @@ -17934,7 +21179,7 @@ index 7fccd53..66ab115 100644 fprintf(stderr, "ERASE FAILED!\n"); return -1; } -@@ -86,8 +80,8 @@ int write_w39v040c(struct flashchip *flash, uint8_t *buf) +@@ -86,8 +107,8 @@ int write_w39v040c(struct flashchip *flash, uint8_t *buf) printf("Programming page: "); for (i = 0; i < total_size / page_size; i++) { printf("%04d at address: 0x%08x", i, i * page_size); @@ -17946,13 +21191,14 @@ index 7fccd53..66ab115 100644 } printf("\n"); diff --git a/w39v080fa.c b/w39v080fa.c -index 31ef15f..8e846dc 100644 +index 31ef15f..0163766 100644 --- a/w39v080fa.c +++ b/w39v080fa.c -@@ -20,37 +20,6 @@ +@@ -19,37 +19,7 @@ + */ #include "flash.h" - +- -int probe_winbond_fwhub(struct flashchip *flash) -{ - chipaddr bios = flash->virtual_memory; @@ -17983,11 +21229,11 @@ index 31ef15f..8e846dc 100644 - - return 1; -} -- ++#include "chipdrivers.h" + static int unlock_block_winbond_fwhub(struct flashchip *flash, int offset) { - chipaddr wrprotect = flash->virtual_registers + offset + 2; -@@ -201,7 +170,7 @@ int write_winbond_fwhub(struct flashchip *flash, uint8_t *buf) +@@ -201,7 +171,7 @@ int write_winbond_fwhub(struct flashchip *flash, uint8_t *buf) printf("Programming: "); for (i = 0; i < total_size; i += flash->page_size) { printf("0x%08x\b\b\b\b\b\b\b\b\b\b", i); @@ -17997,22 +21243,60 @@ index 31ef15f..8e846dc 100644 printf("\n"); diff --git a/w49f002u.c b/w49f002u.c -index d12bc72..87ce000 100644 +deleted file mode 100644 +index d12bc72..0000000 --- a/w49f002u.c -+++ b/w49f002u.c -@@ -36,8 +36,8 @@ int write_49f002(struct flashchip *flash, uint8_t *buf) - for (i = 0; i < total_size / page_size; i++) { - printf("%04d at address: 0x%08x ", i, i * page_size); - /* Byte-wise writing of 'page_size' bytes. */ ++++ /dev/null +@@ -1,47 +0,0 @@ +-/* +- * This file is part of the flashrom project. +- * +- * Copyright (C) 2000 Silicon Integrated System Corporation +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- */ +- +-#include "flash.h" +- +-int write_49f002(struct flashchip *flash, uint8_t *buf) +-{ +- int i; +- int total_size = flash->total_size * 1024; +- int page_size = flash->page_size; +- chipaddr bios = flash->virtual_memory; +- +- if (erase_chip_jedec(flash)) { +- fprintf(stderr, "ERASE FAILED!\n"); +- return -1; +- } +- +- printf("Programming page: "); +- for (i = 0; i < total_size / page_size; i++) { +- printf("%04d at address: 0x%08x ", i, i * page_size); +- /* Byte-wise writing of 'page_size' bytes. */ - write_sector_jedec(bios, buf + i * page_size, - bios + i * page_size, page_size); -+ write_sector_jedec_common(flash, buf + i * page_size, -+ bios + i * page_size, page_size, 0xffff); - printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); - fflush(stdout); - } +- printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); +- fflush(stdout); +- } +- printf("\n"); +- +- return 0; +-} diff --git a/wbsio_spi.c b/wbsio_spi.c -index 6b9425f..922aff1 100644 +index 6b9425f..ca39322 100644 --- a/wbsio_spi.c +++ b/wbsio_spi.c @@ -2,6 +2,7 @@ @@ -18023,7 +21307,15 @@ index 6b9425f..922aff1 100644 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -@@ -34,18 +35,18 @@ static uint16_t wbsio_get_spibase(uint16_t port) +@@ -19,6 +20,7 @@ + + #include + #include "flash.h" ++#include "chipdrivers.h" + #include "spi.h" + + #define WBSIO_PORT1 0x2e +@@ -34,18 +36,18 @@ static uint16_t wbsio_get_spibase(uint16_t port) w836xx_ext_enter(port); id = sio_read(port, 0x20); if (id != 0xa0) { @@ -18045,7 +21337,7 @@ index 6b9425f..922aff1 100644 goto done; } -@@ -62,7 +63,7 @@ int wbsio_check_for_spi(const char *name) +@@ -62,7 +64,7 @@ int wbsio_check_for_spi(const char *name) if (0 == (wbsio_spibase = wbsio_get_spibase(WBSIO_PORT2))) return 1; @@ -18054,7 +21346,7 @@ index 6b9425f..922aff1 100644 buses_supported |= CHIP_BUSTYPE_SPI; spi_controller = SPI_CONTROLLER_WBSIO; -@@ -96,42 +97,42 @@ int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -96,42 +98,42 @@ int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt, int i; uint8_t mode = 0; @@ -18108,7 +21400,7 @@ index 6b9425f..922aff1 100644 } mode = 0x60 | (writearr[1] & 0x0f); } else if (5 == writecnt && 4 == readcnt) { -@@ -142,17 +143,17 @@ int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -142,17 +144,17 @@ int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt, */ ; } else if (4 == writecnt && readcnt >= 1 && readcnt <= 4) { @@ -18130,7 +21422,7 @@ index 6b9425f..922aff1 100644 __func__, writecnt, readcnt); /* Command type refers to the number of bytes read/written. */ return SPI_INVALID_LENGTH; -@@ -165,12 +166,12 @@ int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt, +@@ -165,12 +167,12 @@ int wbsio_spi_send_command(unsigned int writecnt, unsigned int readcnt, if (!readcnt) return 0; @@ -18146,7 +21438,7 @@ index 6b9425f..922aff1 100644 return 0; } -@@ -179,7 +180,7 @@ int wbsio_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) +@@ -179,7 +181,7 @@ int wbsio_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) int size = flash->total_size * 1024; if (size > 1024 * 1024) { @@ -18155,7 +21447,7 @@ index 6b9425f..922aff1 100644 return 1; } -@@ -191,7 +192,7 @@ int wbsio_spi_write_1(struct flashchip *flash, uint8_t *buf) +@@ -191,7 +193,7 @@ int wbsio_spi_write_1(struct flashchip *flash, uint8_t *buf) int size = flash->total_size * 1024; if (size > 1024 * 1024) { diff --git a/flashrom.spec b/flashrom.spec index aae2edd..4cfb70a 100644 --- a/flashrom.spec +++ b/flashrom.spec @@ -1,15 +1,15 @@ -%global svnrev 893 +%global svnrev 931 Summary: Simple program for reading/writing BIOS chips content Name: flashrom Version: 0.9.1 -Release: 2.svn%{svnrev}%{?dist} +Release: 3.svn%{svnrev}%{?dist} License: GPLv2 Group: Applications/System URL: http://flashrom.org Source0: http://qa.coreboot.org/releases/%{name}-%{version}.tar.bz2 Source1: http://qa.coreboot.org/releases/%{name}-%{version}.tar.bz2.asc -Patch0: flashrom-r710-r893.diff +Patch0: flashrom-r710-r931.diff BuildRequires: pciutils-devel BuildRequires: zlib-devel BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -42,6 +42,18 @@ CFLAGS="%{optflags}" %{__make} %{?_smp_mflags} %{_mandir}/man8/%{name}.* %changelog +* Fri Mar 12 2010 Peter Lemenkov 0.9.1-3.svn931 +- Updated to latest svn ver. 931 +- ASUS A7V8X-X board +- MS-7202 board +- Asus M2NBP-VM CSM board +- HP Vectra VL420SFF board +- Eon EN29F010 chip +- Abit IP35 Pro board +- HP Vectra VL400 board +- Intel E28F004S5 flash chip +- Lots of bugfixes + * Mon Feb 8 2010 Peter Lemenkov 0.9.1-2.svn893 - Updated to latest svn ver. 893 - ST M29W512B chip diff --git a/import.log b/import.log index 812debe..9ff21f0 100644 --- a/import.log +++ b/import.log @@ -7,3 +7,4 @@ flashrom-0-0_18_20090414svn4107_fc10:HEAD:flashrom-0-0.18.20090414svn4107.fc10.s flashrom-0_9_0-1_fc10:HEAD:flashrom-0.9.0-1.fc10.src.rpm:1241503535 flashrom-0_9_1-1_fc11:HEAD:flashrom-0.9.1-1.fc11.src.rpm:1252055642 flashrom-0_9_1-2_svn893_fc12:HEAD:flashrom-0.9.1-2.svn893.fc12.src.rpm:1265623249 +flashrom-0_9_1-3_svn931_fc12:HEAD:flashrom-0.9.1-3.svn931.fc12.src.rpm:1268395198