Add support for Xilinx parallel III (DLC5) programing cable
The rayer_spi driver defaults to the RayeR cable, but selecting other
predefined pin layouts with the type= parameter is possible:
flashrom -p rayer_spi:type=xilinx
Corresponding to flashrom svn r1437.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
diff --git a/flashrom.8 b/flashrom.8
index 1b9bf60..76f25bd 100644
--- a/flashrom.8
+++ b/flashrom.8
@@ -210,8 +210,8 @@
.sp
.BR "* dediprog" " (for SPI flash ROMs attached to a Dediprog SF100)"
.sp
-.BR "* rayer_spi" " (for SPI flash ROMs attached to a RayeR parport \
-based programmer)"
+.BR "* rayer_spi" " (for SPI flash ROMs attached to a RayeR parport "
+or Xilinx DLC5 compatible cable)
.sp
.BR "* nicintel_spi" " (for SPI flash ROMs on Intel Gigabit network cards)"
.sp
@@ -512,8 +512,22 @@
is base I/O port address of the parallel port, which must be a multiple of
four. Make sure to not forget the "0x" prefix for hexadecimal port addresses.
.sp
-More information about the hardware is available at
-.BR http://rayer.ic.cz/elektro/spipgm.htm .
+The default cable type is the RayeR cable. You can use the optional
+.B type
+parameter to specify the cable type with the
+.sp
+.B " flashrom \-p rayer_spi:type=model"
+.sp
+syntax where
+.B model
+can be
+.BR rayer " for the RayeR cable or " xilinx " for the Xilinx Parallel Cable III
+(DLC 5).
+.sp
+More information about the RayeR hardware is available at
+.BR "http://rayer.ic.cz/elektro/spipgm.htm " .
+The schematic of the Xilinx DLC 5 was published at
+.BR "http://www.xilinx.com/itp/xilinx4/data/docs/pac/appendixb.html " .
.TP
.BR "ogp_spi " programmer
The flash ROM chip to access must be specified with the
diff --git a/rayer_spi.c b/rayer_spi.c
index 0807487..7f9270a 100644
--- a/rayer_spi.c
+++ b/rayer_spi.c
@@ -31,18 +31,25 @@
#if defined(__i386__) || defined(__x86_64__)
#include <stdlib.h>
+#include <string.h>
#include "flash.h"
#include "programmer.h"
+enum rayer_type {
+ TYPE_RAYER,
+ TYPE_XILINX_DLC5,
+};
+
/* We have two sets of pins, out and in. The numbers for both sets are
* independent and are bitshift values, not real pin numbers.
+ * Default settings are for the the RayeR hardware.
*/
/* Pins for master->slave direction */
-#define SPI_CS_PIN 5
-#define SPI_SCK_PIN 6
-#define SPI_MOSI_PIN 7
+static int rayer_cs_bit = 5;
+static int rayer_sck_bit = 6;
+static int rayer_mosi_bit = 7;
/* Pins for slave->master direction */
-#define SPI_MISO_PIN 6
+static int rayer_miso_bit = 6;
static uint16_t lpt_iobase;
@@ -51,22 +58,22 @@
static void rayer_bitbang_set_cs(int val)
{
- lpt_outbyte &= ~(1 << SPI_CS_PIN);
- lpt_outbyte |= (val << SPI_CS_PIN);
+ lpt_outbyte &= ~(1 << rayer_cs_bit);
+ lpt_outbyte |= (val << rayer_cs_bit);
OUTB(lpt_outbyte, lpt_iobase);
}
static void rayer_bitbang_set_sck(int val)
{
- lpt_outbyte &= ~(1 << SPI_SCK_PIN);
- lpt_outbyte |= (val << SPI_SCK_PIN);
+ lpt_outbyte &= ~(1 << rayer_sck_bit);
+ lpt_outbyte |= (val << rayer_sck_bit);
OUTB(lpt_outbyte, lpt_iobase);
}
static void rayer_bitbang_set_mosi(int val)
{
- lpt_outbyte &= ~(1 << SPI_MOSI_PIN);
- lpt_outbyte |= (val << SPI_MOSI_PIN);
+ lpt_outbyte &= ~(1 << rayer_mosi_bit);
+ lpt_outbyte |= (val << rayer_mosi_bit);
OUTB(lpt_outbyte, lpt_iobase);
}
@@ -75,7 +82,7 @@
uint8_t tmp;
tmp = INB(lpt_iobase + 1);
- tmp = (tmp >> SPI_MISO_PIN) & 0x1;
+ tmp = (tmp >> rayer_miso_bit) & 0x1;
return tmp;
}
@@ -89,14 +96,15 @@
int rayer_spi_init(void)
{
- char *portpos = NULL;
+ char *arg = NULL;
+ enum rayer_type rayer_type = TYPE_RAYER;
/* Non-default port requested? */
- portpos = extract_programmer_param("iobase");
- if (portpos) {
+ arg = extract_programmer_param("iobase");
+ if (arg) {
char *endptr = NULL;
unsigned long tmp;
- tmp = strtoul(portpos, &endptr, 0);
+ tmp = strtoul(arg, &endptr, 0);
/* Port 0, port >0x10000, unaligned ports and garbage strings
* are rejected.
*/
@@ -109,7 +117,7 @@
msg_perr("Error: iobase= specified, but the I/O base "
"given was invalid.\nIt must be a multiple of "
"0x4 and lie between 0x100 and 0xfffc.\n");
- free(portpos);
+ free(arg);
return 1;
} else {
lpt_iobase = (uint16_t)tmp;
@@ -120,11 +128,44 @@
/* Pick a default value for the I/O base. */
lpt_iobase = 0x378;
}
- free(portpos);
+ free(arg);
msg_pdbg("Using address 0x%x as I/O base for parallel port access.\n",
lpt_iobase);
+ arg = extract_programmer_param("type");
+ if (arg) {
+ if (!strcasecmp(arg, "rayer")) {
+ rayer_type = TYPE_RAYER;
+ } else if (!strcasecmp(arg, "xilinx")) {
+ rayer_type = TYPE_XILINX_DLC5;
+ } else {
+ msg_perr("Error: Invalid device type specified.\n");
+ free(arg);
+ return 1;
+ }
+ }
+ free(arg);
+ switch (rayer_type) {
+ case TYPE_RAYER:
+ msg_pdbg("Using RayeR SPIPGM pinout.\n");
+ /* Bits for master->slave direction */
+ rayer_cs_bit = 5;
+ rayer_sck_bit = 6;
+ rayer_mosi_bit = 7;
+ /* Bits for slave->master direction */
+ rayer_miso_bit = 6;
+ break;
+ case TYPE_XILINX_DLC5:
+ msg_pdbg("Using Xilinx Parallel Cable III (DLC 5) pinout.\n");
+ /* Bits for master->slave direction */
+ rayer_cs_bit = 2;
+ rayer_sck_bit = 1;
+ rayer_mosi_bit = 0;
+ /* Bits for slave->master direction */
+ rayer_miso_bit = 4;
+ }
+
get_io_perms();
/* Get the initial value before writing to any line. */