summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile13
-rw-r--r--flashchips.c31
-rw-r--r--flashrom.836
-rw-r--r--flashrom.c24
-rw-r--r--ogp_spi.c145
-rw-r--r--print.c5
-rw-r--r--print_wiki.c3
-rw-r--r--programmer.h18
-rw-r--r--spi.c9
9 files changed, 281 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 3215992..0f20b8a 100644
--- a/Makefile
+++ b/Makefile
@@ -146,6 +146,9 @@ CONFIG_NICNATSEMI ?= no
# Always enable SPI on Intel NICs for now.
CONFIG_NICINTEL_SPI ?= yes
+# Always enable SPI on OGP cards for now.
+CONFIG_OGP_SPI ?= yes
+
# Always enable Bus Pirate SPI for now.
CONFIG_BUSPIRATE_SPI ?= yes
@@ -165,10 +168,14 @@ else
ifeq ($(CONFIG_NICINTEL_SPI), yes)
override CONFIG_BITBANG_SPI = yes
else
+ifeq ($(CONFIG_OGP_SPI), yes)
+override CONFIG_BITBANG_SPI = yes
+else
CONFIG_BITBANG_SPI ?= no
endif
endif
endif
+endif
ifeq ($(CONFIG_INTERNAL), yes)
FEATURE_CFLAGS += -D'CONFIG_INTERNAL=1'
@@ -258,6 +265,12 @@ PROGRAMMER_OBJS += nicintel_spi.o
NEED_PCI := yes
endif
+ifeq ($(CONFIG_OGP_SPI), yes)
+FEATURE_CFLAGS += -D'CONFIG_OGP_SPI=1'
+PROGRAMMER_OBJS += ogp_spi.o
+NEED_PCI := yes
+endif
+
ifeq ($(CONFIG_BUSPIRATE_SPI), yes)
FEATURE_CFLAGS += -D'CONFIG_BUSPIRATE_SPI=1'
PROGRAMMER_OBJS += buspirate_spi.o
diff --git a/flashchips.c b/flashchips.c
index a9ce4a2..e13e829 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -4897,13 +4897,42 @@ struct flashchip flashchips[] = {
{
.vendor = "SST",
+ .name = "SST25VF010.REMS",
+ .bustype = CHIP_BUSTYPE_SPI,
+ .manufacture_id = SST_ID,
+ .model_id = SST_SST25VF010_REMS,
+ .total_size = 128,
+ .page_size = 256,
+ .tested = TEST_OK_PREW,
+ .probe = probe_spi_rems,
+ .probe_timing = TIMING_ZERO,
+ .block_erasers =
+ {
+ {
+ .eraseblocks = { {4 * 1024, 32} },
+ .block_erase = spi_block_erase_20,
+ }, {
+ .eraseblocks = { {32 * 1024, 4} },
+ .block_erase = spi_block_erase_52,
+ }, {
+ .eraseblocks = { {128 * 1024, 1} },
+ .block_erase = spi_block_erase_60,
+ },
+ },
+ .unlock = spi_disable_blockprotect,
+ .write = spi_chip_write_1,
+ .read = spi_chip_read,
+ },
+
+ {
+ .vendor = "SST",
.name = "SST25VF016B",
.bustype = CHIP_BUSTYPE_SPI,
.manufacture_id = SST_ID,
.model_id = SST_SST25VF016B,
.total_size = 2048,
.page_size = 256,
- .tested = TEST_OK_PRE,
+ .tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
diff --git a/flashrom.8 b/flashrom.8
index 0f2a6c4..6adb0ef 100644
--- a/flashrom.8
+++ b/flashrom.8
@@ -198,6 +198,9 @@ based programmer)"
.BR "* nicintel_spi" " (for SPI flash ROMs attached to an Intel Gigabit \
network cards)"
.sp
+.BR "* ogp_spi" " (for SPI flash ROMs attached to an Open Graphics Project \
+graphics card)"
+.sp
Some programmers have optional or mandatory parameters which are described
in detail in the
.B PROGRAMMER SPECIFIC INFO
@@ -432,6 +435,34 @@ four. Make sure to not forget the "0x" prefix for hexadecimal port addresses.
.sp
More information about the hardware is available at
http://rayer.ic.cz/elektro/spipgm.htm
+.TP
+.BR "ogp_spi " programmer
+The FLASH ROM chip to access must be specified with the
+.B rom
+parameter.
+.sp
+.B " flashrom \-p ogp_spi:rom=name"
+.sp
+Where
+.B name
+is either
+.B cprom
+or
+.B s3
+for the configuration ROM and
+.B bprom
+or
+.B bios
+for the BIOS ROM. If more than one card supported by the ogp_spi programmer
+is installed in your system, you have to specify the PCI address of the card
+you want to use with the
+.B pci=
+parameter as explained in the
+.B nic3com
+section above.
+.sp
+More information about the hardware is available at
+http://wiki.opengraphics.org
.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.
@@ -480,6 +511,9 @@ have to be run as superuser/root, and need additional raw access permission.
can be run as normal user on most operating systems if appropriate device
permissions are set.
.sp
+.B ogp
+needs PCI configuration space read access and raw memory access.
+.sp
On OpenBSD, you can obtain raw access permission by setting
securelevel=-1 in /etc/rc.securelevel and rebooting, or rebooting into single
user mode.
@@ -538,6 +572,8 @@ Luc Verhaegen
.br
Li-Ta Lo
.br
+Mark Marshall
+.br
Markus Boas
.br
Mattias Mattsson
diff --git a/flashrom.c b/flashrom.c
index 55d4d7b..9ac857e 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -52,7 +52,7 @@ enum programmer programmer = PROGRAMMER_DUMMY;
* 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 CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_NICNATSEMI+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_FT2232_SPI+CONFIG_SERPROG+CONFIG_BUSPIRATE_SPI+CONFIG_DEDIPROG+CONFIG_RAYER_SPI+CONFIG_NICINTEL_SPI > 1
+#if CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_NICNATSEMI+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_FT2232_SPI+CONFIG_SERPROG+CONFIG_BUSPIRATE_SPI+CONFIG_DEDIPROG+CONFIG_RAYER_SPI+CONFIG_NICINTEL_SPI+CONFIG_OGP_SPI > 1
#error Please enable either CONFIG_DUMMY or CONFIG_INTERNAL or disable support for all programmers except one.
#endif
enum programmer programmer =
@@ -96,6 +96,9 @@ enum programmer programmer =
#if CONFIG_NICINTEL_SPI == 1
PROGRAMMER_NICINTEL_SPI
#endif
+#if CONFIG_OGP_SPI == 1
+ PROGRAMMER_OGP_SPI
+#endif
;
#endif
@@ -439,6 +442,25 @@ const struct programmer_entry programmer_table[] = {
},
#endif
+#if CONFIG_OGP_SPI == 1
+ {
+ .name = "ogp_spi",
+ .init = ogp_spi_init,
+ .shutdown = ogp_spi_shutdown,
+ .map_flash_region = fallback_map,
+ .unmap_flash_region = fallback_unmap,
+ .chip_readb = noop_chip_readb,
+ .chip_readw = fallback_chip_readw,
+ .chip_readl = fallback_chip_readl,
+ .chip_readn = fallback_chip_readn,
+ .chip_writeb = noop_chip_writeb,
+ .chip_writew = fallback_chip_writew,
+ .chip_writel = fallback_chip_writel,
+ .chip_writen = fallback_chip_writen,
+ .delay = internal_delay,
+ },
+#endif
+
{}, /* This entry corresponds to PROGRAMMER_INVALID. */
};
diff --git a/ogp_spi.c b/ogp_spi.c
new file mode 100644
index 0000000..fb52a8c
--- /dev/null
+++ b/ogp_spi.c
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Mark Marshall
+ *
+ * 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
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "flash.h"
+#include "programmer.h"
+
+#define PCI_VENDOR_ID_OGP 0x1227
+
+/* These are the register addresses for the OGD1 / OGA1. If they are
+ * different for later versions of the hardware then we will need
+ * logic to select between the different hardware versions. */
+#define OGA1_XP10_BPROM_SI 0x0040 /* W */
+#define OGA1_XP10_BPROM_SO 0x0040 /* R */
+#define OGA1_XP10_BPROM_CE_BAR 0x0044 /* W */
+#define OGA1_XP10_BPROM_SCK 0x0048 /* W */
+#define OGA1_XP10_BPROM_REG_SEL 0x004C /* W */
+#define OGA1_XP10_CPROM_SI 0x0050 /* W */
+#define OGA1_XP10_CPROM_SO 0x0050 /* R */
+#define OGA1_XP10_CPROM_CE_BAR 0x0054 /* W */
+#define OGA1_XP10_CPROM_SCK 0x0058 /* W */
+#define OGA1_XP10_CPROM_REG_SEL 0x005C /* W */
+
+static uint8_t *ogp_spibar;
+
+static uint32_t ogp_reg_sel;
+static uint32_t ogp_reg_siso;
+static uint32_t ogp_reg__ce;
+static uint32_t ogp_reg_sck;
+
+const struct pcidev_status ogp_spi[] = {
+ {PCI_VENDOR_ID_OGP, 0x0000, OK, "Open Graphics Project", "Development Board OGD1"},
+ {},
+};
+
+static void ogp_request_spibus(void)
+{
+ pci_mmio_writel(1, ogp_spibar + ogp_reg_sel);
+}
+
+static void ogp_release_spibus(void)
+{
+ pci_mmio_writel(0, ogp_spibar + ogp_reg_sel);
+}
+
+static void ogp_bitbang_set_cs(int val)
+{
+ pci_mmio_writel(val, ogp_spibar + ogp_reg__ce);
+}
+
+static void ogp_bitbang_set_sck(int val)
+{
+ pci_mmio_writel(val, ogp_spibar + ogp_reg_sck);
+}
+
+static void ogp_bitbang_set_mosi(int val)
+{
+ pci_mmio_writel(val, ogp_spibar + ogp_reg_siso);
+}
+
+static int ogp_bitbang_get_miso(void)
+{
+ uint32_t tmp;
+
+ tmp = pci_mmio_readl(ogp_spibar + ogp_reg_siso);
+ return tmp & 0x1;
+}
+
+static const struct bitbang_spi_master bitbang_spi_master_ogp = {
+ .type = BITBANG_SPI_MASTER_OGP,
+ .set_cs = ogp_bitbang_set_cs,
+ .set_sck = ogp_bitbang_set_sck,
+ .set_mosi = ogp_bitbang_set_mosi,
+ .get_miso = ogp_bitbang_get_miso,
+ .request_bus = ogp_request_spibus,
+ .release_bus = ogp_release_spibus,
+};
+
+int ogp_spi_init(void)
+{
+ char *type;
+
+ type = extract_programmer_param("rom");
+
+ if (!type) {
+ msg_perr("Please use flashrom -p ogp_spi:rom=... to specify "
+ "which flashchip you want to access.\n");
+ return 1;
+ } else if (!strcasecmp(type, "bprom") || !strcasecmp(type, "bios")) {
+ ogp_reg_sel = OGA1_XP10_BPROM_REG_SEL;
+ ogp_reg_siso = OGA1_XP10_BPROM_SI;
+ ogp_reg__ce = OGA1_XP10_BPROM_CE_BAR;
+ ogp_reg_sck = OGA1_XP10_BPROM_SCK;
+ } else if (!strcasecmp(type, "cprom") || !strcasecmp(type, "s3")) {
+ ogp_reg_sel = OGA1_XP10_CPROM_REG_SEL;
+ ogp_reg_siso = OGA1_XP10_CPROM_SI;
+ ogp_reg__ce = OGA1_XP10_CPROM_CE_BAR;
+ ogp_reg_sck = OGA1_XP10_CPROM_SCK;
+ } else {
+ msg_perr("Invalid or missing rom= parameter.\n");
+ return 1;
+ }
+
+ get_io_perms();
+
+ io_base_addr = pcidev_init(PCI_VENDOR_ID_OGP, PCI_BASE_ADDRESS_0,
+ ogp_spi);
+
+ ogp_spibar = physmap("OGP registers", io_base_addr, 4096);
+
+ /* no delay for now. */
+ if (bitbang_spi_init(&bitbang_spi_master_ogp, 0))
+ return 1;
+
+ buses_supported = CHIP_BUSTYPE_SPI;
+ spi_controller = SPI_CONTROLLER_OGP;
+
+ return 0;
+}
+
+int ogp_spi_shutdown(void)
+{
+ physunmap(ogp_spibar, 4096);
+ pci_cleanup(pacc);
+ release_io_perms();
+
+ return 0;
+}
diff --git a/print.c b/print.c
index ae2bd39..86b4fb1 100644
--- a/print.c
+++ b/print.c
@@ -312,6 +312,11 @@ void print_supported(void)
programmer_table[PROGRAMMER_NICINTEL_SPI].name);
print_supported_pcidevs(nics_intel_spi);
#endif
+#if CONFIG_OGP_SPI == 1
+ printf("\nSupported devices for the %s programmer:\n",
+ programmer_table[PROGRAMMER_OGP_SPI].name);
+ print_supported_pcidevs(ogp_spi);
+#endif
}
#if CONFIG_INTERNAL == 1
diff --git a/print_wiki.c b/print_wiki.c
index 1b46dd0..48e0122 100644
--- a/print_wiki.c
+++ b/print_wiki.c
@@ -299,6 +299,9 @@ void print_supported_wiki(void)
#if CONFIG_NICINTEL_SPI == 1
print_supported_pcidevs_wiki(nics_intel_spi);
#endif
+#if CONFIG_OGP_SPI == 1
+ print_supported_pcidevs_wiki(ogp_spi);
+#endif
printf("\n|}\n");
}
diff --git a/programmer.h b/programmer.h
index a447092..345b4f3 100644
--- a/programmer.h
+++ b/programmer.h
@@ -76,6 +76,9 @@ enum programmer {
#if CONFIG_NICINTEL_SPI == 1
PROGRAMMER_NICINTEL_SPI,
#endif
+#if CONFIG_OGP_SPI == 1
+ PROGRAMMER_OGP_SPI,
+#endif
PROGRAMMER_INVALID /* This must always be the last entry. */
};
@@ -121,6 +124,9 @@ enum bitbang_spi_master_type {
BITBANG_SPI_MASTER_MCP,
#endif
#endif
+#if CONFIG_OGP_SPI == 1
+ BITBANG_SPI_MASTER_OGP,
+#endif
};
struct bitbang_spi_master {
@@ -221,7 +227,7 @@ int rpci_write_long(struct pci_dev *dev, int reg, u32 data);
#endif
/* print.c */
-#if CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_NICNATSEMI+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_NICINTEL_SPI >= 1
+#if CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_NICNATSEMI+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_NICINTEL_SPI+CONFIG_OGP_SPI >= 1
void print_supported_pcidevs(const struct pcidev_status *devs);
#endif
@@ -402,6 +408,13 @@ void nicintel_spi_chip_writeb(uint8_t val, chipaddr addr);
extern const struct pcidev_status nics_intel_spi[];
#endif
+/* ogp_spi.c */
+#if CONFIG_OGP_SPI == 1
+int ogp_spi_init(void);
+int ogp_spi_shutdown(void);
+extern const struct pcidev_status ogp_spi[];
+#endif
+
/* satasii.c */
#if CONFIG_SATASII == 1
int satasii_init(void);
@@ -523,6 +536,9 @@ enum spi_controller {
#if CONFIG_NICINTEL_SPI == 1
SPI_CONTROLLER_NICINTEL,
#endif
+#if CONFIG_OGP_SPI == 1
+ SPI_CONTROLLER_OGP,
+#endif
SPI_CONTROLLER_INVALID /* This must always be the last entry. */
};
extern const int spi_programmer_count;
diff --git a/spi.c b/spi.c
index 3df7458..7d76120 100644
--- a/spi.c
+++ b/spi.c
@@ -146,6 +146,15 @@ const struct spi_programmer spi_programmer[] = {
},
#endif
+#if CONFIG_OGP_SPI == 1
+ { /* SPI_CONTROLLER_OGP */
+ .command = bitbang_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = bitbang_spi_read,
+ .write_256 = bitbang_spi_write_256,
+ },
+#endif
+
{}, /* This entry corresponds to SPI_CONTROLLER_INVALID. */
};
OpenPOWER on IntegriCloud