-
-
Save cleverca22/426715da598b338e97de5d896db92e30 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Makefile b/Makefile | |
index 7242b09..cb711ba 100644 | |
--- a/Makefile | |
+++ b/Makefile | |
@@ -696,6 +696,11 @@ CONFIG_DIGILENT_SPI ?= yes | |
# Disable J-Link for now. | |
CONFIG_JLINK_SPI ?= no | |
+# Enable VIA VL805 programmer for now. | |
+CONFIG_VL805 ?= yes | |
+ | |
+#PLACEHOLDER_NEWPROG_DEFAULTCONFIG | |
+ | |
# Disable wiki printing by default. It is only useful if you have wiki access. | |
CONFIG_PRINT_WIKI ?= no | |
@@ -759,7 +764,9 @@ else | |
ifeq ($(CONFIG_OGP_SPI), yes) | |
override CONFIG_BITBANG_SPI = yes | |
else | |
+#PLACEHOLDER_NEWPROG_BITBANGSPICONFIG1 | |
CONFIG_BITBANG_SPI ?= no | |
+#PLACEHOLDER_NEWPROG_BITBANGSPICONFIG2 | |
endif | |
endif | |
endif | |
@@ -996,6 +1003,14 @@ NEED_LINUX_I2C += CONFIG_MSTARDDC_SPI | |
PROGRAMMER_OBJS += mstarddc_spi.o | |
endif | |
+ifeq ($(CONFIG_VL805), yes) | |
+FEATURE_CFLAGS += -D'CONFIG_VL805=1' | |
+PROGRAMMER_OBJS += vl805.o | |
+NEED_PCI := yes | |
+endif | |
+ | |
+#PLACEHOLDER_NEWPROG_COMPILERULE | |
+ | |
ifeq ($(CONFIG_CH341A_SPI), yes) | |
FEATURE_CFLAGS += -D'CONFIG_CH341A_SPI=1' | |
PROGRAMMER_OBJS += ch341a_spi.o | |
diff --git a/flashrom.8.tmpl b/flashrom.8.tmpl | |
index aa5bcd4..6997dd9 100644 | |
--- a/flashrom.8.tmpl | |
+++ b/flashrom.8.tmpl | |
@@ -345,6 +345,9 @@ bitbanging adapter) | |
.sp | |
.BR "* stlinkv3_spi" " (for SPI flash ROMs attached to STMicroelectronics STLINK V3 devices)" | |
.sp | |
+.BR "* vl805" " (VIA VL805 programmer)" | |
+.sp | |
+.\"PLACEHOLDER_NEWPROG_MAN_SHORTDESCRIPTION | |
Some programmers have optional or mandatory parameters which are described | |
in detail in the | |
.B PROGRAMMER-SPECIFIC INFORMATION | |
@@ -1287,7 +1290,10 @@ syntax where \fBfrequency\fP is the SPI clock frequency in kHz. | |
If the passed frequency is not supported by the adapter the nearest lower | |
supported frequency will be used. | |
.SS | |
- | |
+.BR "vl805 " programmer | |
+Please describe the programmer parameters here. | |
+.SS | |
+.\"PLACEHOLDER_NEWPROG_MAN_LONGDESCRIPTION | |
.SH EXAMPLES | |
To back up and update your BIOS, run | |
.sp | |
@@ -1365,6 +1371,10 @@ permissions are set. | |
.B ogp | |
needs PCI configuration space read access and raw memory access. | |
.sp | |
+.B vl805 | |
+Please describe the programmer requirements here. | |
+.sp | |
+.\"PLACEHOLDER_NEWPROG_MAN_REQUIREMENTS | |
On OpenBSD, you can obtain raw access permission by setting | |
.B "securelevel=-1" | |
in | |
diff --git a/flashrom.c b/flashrom.c | |
index e540027..dc2224a 100644 | |
--- a/flashrom.c | |
+++ b/flashrom.c | |
@@ -473,6 +473,19 @@ const struct programmer_entry programmer_table[] = { | |
}, | |
#endif | |
+#if CONFIG_VL805 == 1 | |
+ { | |
+ .name = "vl805", | |
+ .type = PCI, | |
+ .devs.dev = devs_vl805, | |
+ .init = vl805_init, | |
+ .map_flash_region = fallback_map, | |
+ .unmap_flash_region = fallback_unmap, | |
+ .delay = internal_delay, | |
+ }, | |
+#endif | |
+ | |
+//PLACEHOLDER_NEWPROG_PROGRAMMER_ARRAY | |
{0}, /* This entry corresponds to PROGRAMMER_INVALID. */ | |
}; | |
diff --git a/pcidev.c b/pcidev.c | |
index 4012840..2afa749 100644 | |
--- a/pcidev.c | |
+++ b/pcidev.c | |
@@ -237,6 +237,7 @@ struct pci_dev *pcidev_init(const struct dev_entry *devs, int bar) | |
*/ | |
if ((addr = pcidev_validate(dev, bar, devs)) != 0) { | |
found++; | |
+ break; | |
} | |
} | |
} | |
diff --git a/programmer.h b/programmer.h | |
index 3cf53b9..3a0baa7 100644 | |
--- a/programmer.h | |
+++ b/programmer.h | |
@@ -127,6 +127,10 @@ enum programmer { | |
#if CONFIG_STLINKV3_SPI == 1 | |
PROGRAMMER_STLINKV3_SPI, | |
#endif | |
+#if CONFIG_VL805 == 1 | |
+ PROGRAMMER_VL805, | |
+#endif | |
+//PLACEHOLDER_NEWPROG_PROGRAMMER_ENUM | |
PROGRAMMER_INVALID /* This must always be the last entry. */ | |
}; | |
@@ -573,6 +577,15 @@ int jlink_spi_init(void); | |
int ni845x_spi_init(void); | |
#endif | |
+/* vl805.c */ | |
+#if CONFIG_VL805 == 1 | |
+int vl805_init(void); | |
+extern const struct dev_entry devs_vl805[]; | |
+ | |
+#endif | |
+ | |
+//PLACEHOLDER_NEWPROG_PUBLICFUNCTIONS | |
+ | |
/* flashrom.c */ | |
struct decode_sizes { | |
uint32_t parallel; | |
diff --git a/vl805.c b/vl805.c | |
new file mode 100644 | |
index 0000000..e407a6b | |
--- /dev/null | |
+++ b/vl805.c | |
@@ -0,0 +1,181 @@ | |
+/* | |
+ * This file is part of the flashrom project. | |
+ * | |
+ * Copyright (C) 2019 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; 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 | |
+ */ | |
+ | |
+/* Driver for the VIA VL805 programmer hardware by VIA. | |
+ * See http://www.via.com/ for more info. | |
+ */ | |
+ | |
+#include "flash.h" | |
+#include "programmer.h" | |
+#include "hwaccess.h" | |
+#include "spi.h" | |
+ | |
+const struct dev_entry devs_vl805[] = { | |
+ {0x1106, 0x3483, NT, "VIA", "VL805"}, | |
+ | |
+ {0}, | |
+}; | |
+ | |
+static struct pci_dev *dev = NULL; | |
+ | |
+static void vl805_setregval(int reg, uint32_t val) | |
+{ | |
+ pci_write_long(dev, 0x78, reg); | |
+ pci_write_long(dev, 0x7c, val); | |
+} | |
+ | |
+static uint32_t vl805_getregval(int reg) | |
+{ | |
+ pci_write_long(dev, 0x78, reg); | |
+ return pci_read_long(dev, 0x7c); | |
+} | |
+ | |
+/* Some of the registers have unknown purpose and are just used inside the init sequence replay. */ | |
+#define VL805_REG_0x30004 0x00030004 | |
+#define VL805_REG_0x4000c 0x0004000c // STOP_POLLING | |
+#define VL805_REG_0x40020 0x00040020 // PCI_WB_EN | |
+#define VL805_REG_SPI_OUTDATA 0x000400d0 | |
+#define VL805_REG_SPI_INDATA 0x000400e0 | |
+#define VL805_REG_SPI_TRANSACTION 0x000400f0 | |
+#define VL805_REG_0x400f8 0x000400f8 | |
+#define VL805_REG_SPI_CHIP_ENABLE_LEVEL 0x000400fc | |
+ | |
+static int vl805_spi_send_command(struct flashctx *flash, | |
+ unsigned int writecnt, unsigned int readcnt, | |
+ const unsigned char *writearr, | |
+ unsigned char *readarr) | |
+{ | |
+ unsigned int i, j; | |
+ uint32_t outdata; | |
+ uint32_t indata = 0; | |
+ unsigned int curwritecnt = 0; | |
+ unsigned int curreadcnt = 0; | |
+ | |
+ if (writecnt > 4) { | |
+ return 1; | |
+ } | |
+ if (readcnt > 4) { | |
+ return 1; | |
+ } | |
+ /* Send a SPI command to the flash chip. */ | |
+ | |
+ vl805_setregval(VL805_REG_SPI_CHIP_ENABLE_LEVEL, 0x00000000); | |
+ | |
+ /* FIXME: Test this for writecnt > 4. */ | |
+ for (j = 0; j < writecnt; j += 4) { | |
+ curwritecnt = min(4, writecnt - j); | |
+ outdata = 0; | |
+ for (i = 0; i < curwritecnt; i++) { | |
+ outdata <<= 8; | |
+ outdata |= writearr[j + i]; | |
+ } | |
+ vl805_setregval(VL805_REG_SPI_OUTDATA, outdata); | |
+ vl805_setregval(VL805_REG_SPI_TRANSACTION, 0x00000580 | (curwritecnt << 3)); | |
+ } | |
+ | |
+ /* Superfluous, the original driver doesn't do that, but we want to have a quiet bus. */ | |
+ vl805_setregval(VL805_REG_SPI_OUTDATA, 0); | |
+ | |
+ /* FIXME: Test this for readcnt > 4. */ | |
+ for (j = 0; j < readcnt; j += 4) { | |
+ curreadcnt = min(4, readcnt - j); | |
+ vl805_setregval(VL805_REG_SPI_TRANSACTION, 0x00000580 | (curreadcnt << 3)); | |
+ indata = vl805_getregval(VL805_REG_SPI_INDATA); | |
+ indata <<= (4 - curreadcnt) * 8; | |
+ for (i = 0; i < curreadcnt; i++) { | |
+ readarr[j + i] = (indata & 0xff000000) >> 24; | |
+ indata <<= 8; | |
+ } | |
+ } | |
+ | |
+ vl805_setregval(VL805_REG_SPI_CHIP_ENABLE_LEVEL, 0x00000001); | |
+ return 0; | |
+} | |
+ | |
+static const struct spi_master spi_master_vl805 = { | |
+ .max_data_read = 64 * 1024, /* Maximum data read size in one go (excluding opcode+address). */ | |
+ .max_data_write = 256, /* Maximum data write size in one go (excluding opcode+address). */ | |
+ .command = vl805_spi_send_command, | |
+ .multicommand = default_spi_send_multicommand, | |
+ .read = default_spi_read, | |
+ .write_256 = default_spi_write_256, | |
+ .write_aai = default_spi_write_aai, | |
+}; | |
+ | |
+static void vl805_programmer_active(uint8_t val) | |
+{ | |
+ pci_write_byte(dev, 0x43, val); | |
+} | |
+ | |
+static int vl805_shutdown(void *data) | |
+{ | |
+ /* Shutdown stuff. */ | |
+ vl805_programmer_active(0x0); | |
+ return 0; | |
+} | |
+ | |
+int vl805_init(void) | |
+{ | |
+ if (rget_io_perms()) | |
+ return 1; | |
+ | |
+ dev = pcidev_init(devs_vl805, PCI_BASE_ADDRESS_0); /* Actually no BAR setup needed at all. */ | |
+ msg_pdbg("pcidev_init returned %p\n", dev); | |
+ if (!dev) | |
+ return 1; | |
+ | |
+ vl805_programmer_active(0x1); | |
+ uint32_t val = pci_read_long(dev, 0x50); | |
+ msg_pdbg("VL805 firmware version 0x%08x\n", val); | |
+ vl805_programmer_active(0x0); | |
+ | |
+ /* Some sort of init sequence, just copied from the logs. */ | |
+ vl805_programmer_active(0x1); | |
+ vl805_setregval(VL805_REG_SPI_CHIP_ENABLE_LEVEL, 0x00000001); | |
+ | |
+ val = vl805_getregval(VL805_REG_0x30004); | |
+ val &= ~0xff00; | |
+ val |= 0x200; | |
+ vl805_setregval(VL805_REG_0x30004, val); | |
+ | |
+ val = vl805_getregval(VL805_REG_0x40020); | |
+ val &= ~0x00ff; | |
+ val |= 0x001; | |
+ vl805_setregval(VL805_REG_0x40020, 0xffffff01); | |
+ | |
+ val = vl805_getregval(VL805_REG_0x4000c); | |
+ val &= ~0xff; | |
+ val |= 0x1; | |
+ vl805_setregval(VL805_REG_0x4000c, 0x00000001); | |
+ | |
+ /* We send 4 uninitialized(?) bytes to the flash chip here. */ | |
+ vl805_setregval(VL805_REG_SPI_TRANSACTION, 0x000005a0); | |
+ vl805_setregval(VL805_REG_0x400f8, 0x0000000a); | |
+ | |
+ /* Some sort of cleanup sequence, just copied from the logs. */ | |
+ vl805_setregval(VL805_REG_SPI_TRANSACTION, 0x00000000); | |
+ vl805_programmer_active(0x0); | |
+ | |
+ register_shutdown(vl805_shutdown, NULL); | |
+ vl805_programmer_active(0x1); | |
+ | |
+ register_spi_master(&spi_master_vl805); | |
+ | |
+ return 0; | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment