[flashrom] [PATCH] Add support for RayeR SPIPGM hardware.

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Wed Jun 2 03:42:09 CEST 2010


Hi,

On 01.06.2010 11:54, rayer wrote:
> it still hangs while autodetecting flash chip at AE49F2008 (is
> displayed as last probed),
> only with -c option it works.

Does it really work with -c CHIPNAME or do you need -f as well?

I found a bug in the bitbanging SPI core (buffer confusion) and fixed it.
This version also reduces reach chunk size to 256 bytes instead of 65536
bytes. That makes buffer management more efficient (only one round of
memory allocations).

Idwer will build a new .exe, and it would be great if you could test it with
flashrom -p rayer_bitbang_spi -V
and make a photo or screenshot of the run. I will add more debugging if
it still hangs.

-snip-

Add support for RayeR SPIPGM hardware as described in
http://rayer.ic.cz/elektro/spipgm.htm

To use the RayeR driver, run
flashrom -p rayer_bitbang_spi -V

Known bugs/limitations:
- Won't compile/work on non-x86 architectures.
- Will always use direct port I/O access.


Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>

Index: flashrom-bitbang_spi_rayer/flash.h
===================================================================
--- flashrom-bitbang_spi_rayer/flash.h	(Revision 1025)
+++ flashrom-bitbang_spi_rayer/flash.h	(Arbeitskopie)
@@ -81,6 +81,9 @@
 #if CONFIG_DEDIPROG == 1
 	PROGRAMMER_DEDIPROG,
 #endif
+#if CONFIG_RAYER_BITBANG_SPI == 1
+	PROGRAMMER_RAYER_BITBANG_SPI,
+#endif
 	PROGRAMMER_INVALID /* This must always be the last entry. */
 };
 
@@ -128,13 +131,14 @@
 void programmer_delay(int usecs);
 
 enum bitbang_spi_master {
+#if CONFIG_RAYER_BITBANG_SPI == 1
+	BITBANG_SPI_MASTER_RAYER,
+#endif
 	BITBANG_SPI_INVALID /* This must always be the last entry. */
 };
 
 extern const int bitbang_spi_master_count;
 
-extern enum bitbang_spi_master bitbang_spi_master;
-
 struct bitbang_spi_master_entry {
 	void (*set_cs) (int val);
 	void (*set_sck) (int val);
@@ -524,10 +528,19 @@
 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);
 
+/* rayer_bitbang_spi.c */
+#if CONFIG_RAYER_BITBANG_SPI == 1
+int rayer_bitbang_spi_init(void);
+void rayer_bitbang_set_cs(int val);
+void rayer_bitbang_set_sck(int val);
+void rayer_bitbang_set_mosi(int val);
+int rayer_bitbang_get_miso(void);
+#endif
+
 /* bitbang_spi.c */
 extern int bitbang_spi_half_period;
 extern const struct bitbang_spi_master_entry bitbang_spi_master_table[];
-int bitbang_spi_init(void);
+int bitbang_spi_init(enum bitbang_spi_master master);
 int bitbang_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
 int bitbang_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
 int bitbang_spi_write_256(struct flashchip *flash, uint8_t *buf);
@@ -643,6 +656,9 @@
 #if CONFIG_DEDIPROG == 1
 	SPI_CONTROLLER_DEDIPROG,
 #endif
+#if CONFIG_RAYER_BITBANG_SPI == 1
+	SPI_CONTROLLER_RAYER_BITBANG,
+#endif
 	SPI_CONTROLLER_INVALID /* This must always be the last entry. */
 };
 extern const int spi_programmer_count;
Index: flashrom-bitbang_spi_rayer/spi25.c
===================================================================
--- flashrom-bitbang_spi_rayer/spi25.c	(Revision 1025)
+++ flashrom-bitbang_spi_rayer/spi25.c	(Arbeitskopie)
@@ -192,6 +192,9 @@
 #if CONFIG_DEDIPROG == 1
 	case SPI_CONTROLLER_DEDIPROG:
 #endif
+#if CONFIG_RAYER_BITBANG_SPI == 1
+	case SPI_CONTROLLER_RAYER_BITBANG:
+#endif
 		return probe_spi_rdid_generic(flash, 4);
 	default:
 		msg_cinfo("4b ID not supported on this SPI controller\n");
Index: flashrom-bitbang_spi_rayer/hwaccess.h
===================================================================
--- flashrom-bitbang_spi_rayer/hwaccess.h	(Revision 1025)
+++ flashrom-bitbang_spi_rayer/hwaccess.h	(Arbeitskopie)
@@ -169,6 +169,10 @@
 #define __DARWIN__
 #endif
 
+/* Clarification about OUTB/OUTW/OUTL argument order:
+ * OUT[BWL](val, port)
+ */
+
 #if defined(__FreeBSD__) || defined(__DragonFly__)
   #include <machine/cpufunc.h>
   #define off64_t off_t
Index: flashrom-bitbang_spi_rayer/bitbang_spi.c
===================================================================
--- flashrom-bitbang_spi_rayer/bitbang_spi.c	(Revision 1025)
+++ flashrom-bitbang_spi_rayer/bitbang_spi.c	(Arbeitskopie)
@@ -32,11 +32,20 @@
 enum bitbang_spi_master bitbang_spi_master = BITBANG_SPI_INVALID;
 
 const struct bitbang_spi_master_entry bitbang_spi_master_table[] = {
-	{}, /* This entry corresponds to BITBANG_SPI_INVALID. */
+#if CONFIG_RAYER_BITBANG_SPI == 1
+	{
+		.set_cs = rayer_bitbang_set_cs,
+		.set_sck = rayer_bitbang_set_sck,
+		.set_mosi = rayer_bitbang_set_mosi,
+		.get_miso = rayer_bitbang_get_miso,
+	},
+#endif
+	{}, /* This entry corresponds to SPI_BITBANG_INVALID. */
 };
 
 const int bitbang_spi_master_count = ARRAY_SIZE(bitbang_spi_master_table);
 
+/* Note that CS# is active low, so val=0 means the chip is active. */
 void bitbang_spi_set_cs(int val)
 {
 	bitbang_spi_master_table[bitbang_spi_master].set_cs(val);
@@ -57,10 +66,19 @@
 	return bitbang_spi_master_table[bitbang_spi_master].get_miso();
 }
 
-int bitbang_spi_init(void)
+int bitbang_spi_init(enum bitbang_spi_master master)
 {
+	bitbang_spi_master = master;
+
+	if (bitbang_spi_master == BITBANG_SPI_INVALID) {
+		msg_perr("Invalid bitbang SPI master. \n"
+			 "Please report a bug at flashrom at flashrom.org\n",
+			 __func__);
+		return 1;
+	}
 	bitbang_spi_set_cs(1);
 	bitbang_spi_set_sck(0);
+	bitbang_spi_set_mosi(0);
 	buses_supported = CHIP_BUSTYPE_SPI;
 	return 0;
 }
@@ -87,6 +105,7 @@
 {
 	static unsigned char *bufout = NULL;
 	static unsigned char *bufin = NULL;
+	unsigned char *tmp;
 	static int oldbufsize = 0;
 	int bufsize;
 	int i;
@@ -98,20 +117,34 @@
 	bufsize = max(writecnt + readcnt, 260);
 	/* Never shrink. realloc() calls are expensive. */
 	if (bufsize > oldbufsize) {
-		bufout = realloc(bufout, bufsize);
-		if (!bufout) {
+		tmp = realloc(bufout, bufsize);
+		if (!tmp) {
 			msg_perr("Out of memory!\n");
+			if (bufout)
+				free(bufout);
+			bufout = NULL;
 			if (bufin)
 				free(bufin);
+			bufin = NULL;
+			oldbufsize = 0;
 			exit(1);
-		}
-		bufin = realloc(bufout, bufsize);
-		if (!bufin) {
+		} else
+			bufout = tmp;
+
+		tmp = realloc(bufin, bufsize);
+		if (!tmp) {
 			msg_perr("Out of memory!\n");
+			if (bufin)
+				free(bufin);
+			bufin = NULL;
 			if (bufout)
 				free(bufout);
+			bufout = NULL;
+			oldbufsize = 0;
 			exit(1);
-		}
+		} else
+			bufin = tmp;
+
 		oldbufsize = bufsize;
 	}
 		
@@ -135,8 +168,13 @@
 
 int bitbang_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
 {
-	/* Maximum read length is unlimited, use 64k bytes. */
-	return spi_read_chunked(flash, buf, start, len, 64 * 1024);
+	/* Maximum read length is unlimited in theory.
+	 * The current implementation can handle reads of up to 65536 bytes.
+	 * Please note that you need two buffers of 2n+4 bytes each for a read
+	 * of n bytes, resulting in a total memory requirement of 4n+8 bytes.
+	 * To conserve memory, read in chunks of 256 bytes.
+	 */
+	return spi_read_chunked(flash, buf, start, len, 256);
 }
 
 int bitbang_spi_write_256(struct flashchip *flash, uint8_t *buf)
Index: flashrom-bitbang_spi_rayer/spi.c
===================================================================
--- flashrom-bitbang_spi_rayer/spi.c	(Revision 1025)
+++ flashrom-bitbang_spi_rayer/spi.c	(Arbeitskopie)
@@ -122,6 +122,15 @@
 	},
 #endif
 
+#if CONFIG_RAYER_BITBANG_SPI == 1
+	{ /* SPI_CONTROLLER_RAYER_BITBANG */
+		.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. */
 };
 
Index: flashrom-bitbang_spi_rayer/Makefile
===================================================================
--- flashrom-bitbang_spi_rayer/Makefile	(Revision 1025)
+++ flashrom-bitbang_spi_rayer/Makefile	(Arbeitskopie)
@@ -85,8 +85,15 @@
 # Always enable serprog for now. Needs to be disabled on Windows.
 CONFIG_SERPROG ?= yes
 
-# Bitbanging SPI infrastructure is not used yet.
+# RayeR SPIPGM hardware support
+CONFIG_RAYER_BITBANG_SPI ?= yes
+
+# Bitbanging SPI infrastructure, default off unless needed.
+ifeq ($(CONFIG_RAYER_BITBANG_SPI), yes)
+CONFIG_BITBANG_SPI = yes
+else
 CONFIG_BITBANG_SPI ?= no
+endif
 
 # Always enable 3Com NICs for now.
 CONFIG_NIC3COM ?= yes
@@ -138,6 +145,13 @@
 endif
 endif
 
+ifeq ($(CONFIG_RAYER_BITBANG_SPI), yes)
+FEATURE_CFLAGS += -D'CONFIG_RAYER_BITBANG_SPI=1'
+PROGRAMMER_OBJS += rayer_bitbang_spi.o
+# Actually, NEED_PCI is wrong. NEED_IOPORT_ACCESS would be more correct.
+NEED_PCI := yes
+endif
+
 ifeq ($(CONFIG_BITBANG_SPI), yes)
 FEATURE_CFLAGS += -D'CONFIG_BITBANG_SPI=1'
 PROGRAMMER_OBJS += bitbang_spi.o
Index: flashrom-bitbang_spi_rayer/flashrom.c
===================================================================
--- flashrom-bitbang_spi_rayer/flashrom.c	(Revision 1025)
+++ flashrom-bitbang_spi_rayer/flashrom.c	(Arbeitskopie)
@@ -48,7 +48,7 @@
  * 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_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_FT2232_SPI+CONFIG_SERPROG+CONFIG_BUSPIRATE_SPI+CONFIG_DEDIPROG > 1
+#if CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_FT2232_SPI+CONFIG_SERPROG+CONFIG_BUSPIRATE_SPI+CONFIG_DEDIPROG+CONFIG_RAYER_BITBANG_SPI > 1
 #error Please enable either CONFIG_DUMMY or CONFIG_INTERNAL or disable support for all programmers except one.
 #endif
 enum programmer programmer =
@@ -83,6 +83,9 @@
 #if CONFIG_DEDIPROG == 1
 	PROGRAMMER_DEDIPROG
 #endif
+#if CONFIG_RAYER_BITBANG_SPI == 1
+	PROGRAMMER_RAYER_BITBANG_SPI
+#endif
 ;
 #endif
 
@@ -373,6 +376,25 @@
 	},
 #endif
 
+#if CONFIG_RAYER_BITBANG_SPI == 1
+	{
+		.name			= "rayer_bitbang_spi",
+		.init			= rayer_bitbang_spi_init,
+		.shutdown		= noop_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. */
 };
 
Index: flashrom-bitbang_spi_rayer/rayer_bitbang_spi.c
===================================================================
--- flashrom-bitbang_spi_rayer/rayer_bitbang_spi.c	(Revision 0)
+++ flashrom-bitbang_spi_rayer/rayer_bitbang_spi.c	(Revision 0)
@@ -0,0 +1,112 @@
+/*
+ * 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; 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 SPIPGM hardware by "RayeR" Martin Rehak.
+ * See http://rayer.ic.cz/elektro/spipgm.htm for schematics and instructions.
+ */
+
+/* This driver uses non-portable direct I/O port accesses which won't work on
+ * any non-x86 platform, and even on x86 there is a high chance there will be
+ * collisions with any loaded parallel port drivers.
+ * The big advantage of direct port I/O is OS independence and speed because
+ * most OS parport drivers will perform many unnecessary accesses although
+ * this driver just treats the parallel port as a GPIO set.
+ */
+#if defined(__i386__) || defined(__x86_64__)
+
+#include "flash.h"
+
+/* We have two sets of pins, out and in. The numbers for both sets are
+ * independent and are bitshift values, not real pin numbers.
+ */
+/* Pins for master->slave direction */
+#define SPI_CS_PIN 5
+#define SPI_SCK_PIN 6
+#define SPI_MOSI_PIN 7
+/* Pins for slave->master direction */
+#define SPI_MISO_PIN 6
+
+static int lpt_iobase;
+
+/* FIXME: All rayer_bitbang_set_* functions could use caching of the value
+ * stored at port lpt_iobase to avoid unnecessary INB. In theory, only one
+ * INB(lpt_iobase) would be needed on programmer init to get the initial
+ * value.
+ */
+
+void rayer_bitbang_set_cs(int val)
+{
+	uint8_t tmp;
+
+	tmp = INB(lpt_iobase);
+	tmp &= ~(1 << SPI_CS_PIN);
+	tmp |= (val << SPI_CS_PIN);
+	OUTB(tmp, lpt_iobase);
+}
+
+void rayer_bitbang_set_sck(int val)
+{
+	uint8_t tmp;
+
+	tmp = INB(lpt_iobase);
+	tmp &= ~(1 << SPI_SCK_PIN);
+	tmp |= (val << SPI_SCK_PIN);
+	OUTB(tmp, lpt_iobase);
+}
+
+void rayer_bitbang_set_mosi(int val)
+{
+	uint8_t tmp;
+
+	tmp = INB(lpt_iobase);
+	tmp &= ~(1 << SPI_MOSI_PIN);
+	tmp |= (val << SPI_MOSI_PIN);
+	OUTB(tmp, lpt_iobase);
+}
+
+int rayer_bitbang_get_miso(void)
+{
+	uint8_t tmp;
+
+	tmp = INB(lpt_iobase + 1);
+	tmp = (tmp >> SPI_MISO_PIN) & 0x1;
+	return tmp;
+}
+
+int rayer_bitbang_spi_init(void)
+{
+	/* Pick a default value for now. */
+	lpt_iobase = 0x378;
+
+	msg_pdbg("Using port 0x%x as I/O base for parallel port access.\n",
+		 lpt_iobase);
+
+	get_io_perms();
+
+	if (bitbang_spi_init(BITBANG_SPI_MASTER_RAYER))
+		return 1;
+
+	spi_controller = SPI_CONTROLLER_RAYER_BITBANG;
+
+	return 0;
+}
+
+#else
+#error PCI port I/O access is not supported on this architecture yet.
+#endif


-- 
http://www.hailfinger.org/





More information about the flashrom mailing list