[flashrom] [PATCH 4/7] add lpt_bitbang_spi based on rayer_spi

Maksim Kuleshov mmcx at mail.ru
Sun Mar 31 17:06:23 CEST 2013


From 05f717c81da603472988e31c63a2c082fef6c491 Mon Sep 17 00:00:00 2001
From: Maksim Kuleshov <mmcx at mail.ru>
Date: Sun, 31 Mar 2013 17:41:12 +0400
Subject: [PATCH 4/7] add lpt_bitbang_spi based on rayer_spi
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

add lpt_bitbang_spi based on rayer_spi
    Integrated patchs:
        [flashrom] [PATCH (1-5)/5] rayer_spi: Create list of programmer types
            Wed Mar 6 23:48:43 CET 2013 Kyösti Mälkki
        [flashrom] [PATCH (0-3)/3] rayer_spi: Add support for Willem EPROM programmer SPI
            Sat Mar 16 23:42:50 CET 2013 Ondrej Zary

Signed-off-by: Maksim Kuleshov <mmcx at mail.ru>
---
 lpt_bitbang_spi.c |  406 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 lpt_bitbang_spi.h |    6 +
 2 files changed, 412 insertions(+)
 create mode 100644 lpt_bitbang_spi.c
 create mode 100644 lpt_bitbang_spi.h

diff --git a/lpt_bitbang_spi.c b/lpt_bitbang_spi.c
new file mode 100644
index 0000000..2350e2b
--- /dev/null
+++ b/lpt_bitbang_spi.c
@@ -0,0 +1,406 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2009,2010 Carl-Daniel Hailfinger
+ * Copyright (C) 2013 Kyösti Mälkki
+ * Copyright (C) 2013 Ondrej Zary
+ * Copyright (C) 2013 Maksim Kuleshov
+ *
+ * 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 <strings.h>
+#include <string.h>
+#include "lpt_bitbang_spi.h"
+
+#include "flash.h"
+#include "programmer.h"
+
+#include "lpt_io.h"
+
+typedef uint_fast16_t pins_mask_t;
+
+struct lpt_bitbang_spi_pin {
+	pins_mask_t set_mask;
+	pins_mask_t clear_mask;
+};
+
+struct lpt_bitbang_spi_programmer {
+	const char *type;
+	const enum test_state status;
+	const char *description;
+	const char *url;
+	struct lpt_bitbang_spi_pin spi_cs;
+	struct lpt_bitbang_spi_pin spi_sck;
+	struct lpt_bitbang_spi_pin spi_miso;
+	struct lpt_bitbang_spi_pin spi_mosi;
+	struct lpt_bitbang_spi_pin on_enable;
+	struct lpt_bitbang_spi_pin on_disable;
+	int (*preinit) (void *data);
+	int (*shutdown) (void *data);
+};
+
+enum {
+	LPT_OUT_PIN_1 = (1UL << (0 + 8)),
+	LPT_OUT_PIN_2 = (1UL << 0),
+	LPT_OUT_PIN_3 = (1UL << 1),
+	LPT_OUT_PIN_4 = (1UL << 2),
+	LPT_OUT_PIN_5 = (1UL << 3),
+	LPT_OUT_PIN_6 = (1UL << 4),
+	LPT_OUT_PIN_7 = (1UL << 5),
+	LPT_OUT_PIN_8 = (1UL << 6),
+	LPT_OUT_PIN_9 = (1UL << 7),
+	LPT_OUT_PIN_14 = (1UL << (1 + 8)),
+	LPT_OUT_PIN_15 = (1UL << 3),
+	LPT_OUT_PIN_16 = (1UL << (2 + 8)),
+	LPT_OUT_PIN_17 = (1UL << (3 + 8)),
+
+	LPT_IN_PIN_10 = (1UL << 6),
+	LPT_IN_PIN_11 = (1UL << 7),
+	LPT_IN_PIN_12 = (1UL << 5),
+	LPT_IN_PIN_13 = (1UL << 4),
+};
+
+static struct lpt_bitbang_spi_programmer prog_rayer_spipgm = {
+	.type = "rayer",
+	.status = NT,
+	.description = "SPIPGM hardware by \"RayeR\" Martin Rehak",
+	.url = "http://rayer.ic.cz/elektro/spipgm.htm",
+	.spi_cs = {LPT_OUT_PIN_7, 0},
+	.spi_sck = {LPT_OUT_PIN_8, 0},
+	.spi_mosi = {LPT_OUT_PIN_9, 0},
+	.spi_miso = {LPT_IN_PIN_10, 0},
+};
+
+static struct lpt_bitbang_spi_programmer prog_xilinx_dlc5 = {
+	.type = "xilinx",
+	.status = NT,
+	.description = "Xilinx Parallel Cable III (DLC 5)",
+	.url =
+	    "http://www.xilinx.com/support/documentation/user_guides/xtp029.pdf",
+	.spi_cs = {LPT_OUT_PIN_4, 0},
+	.spi_sck = {LPT_OUT_PIN_3, 0},
+	.spi_mosi = {LPT_OUT_PIN_2, 0},
+	.spi_miso = {LPT_IN_PIN_13, 0},
+	.on_enable = {LPT_OUT_PIN_6, LPT_OUT_PIN_5},
+	.on_disable = {LPT_OUT_PIN_6 | LPT_OUT_PIN_5, 0},
+};
+
+static struct lpt_bitbang_spi_programmer prog_altera_byteblastermv = {
+	.type = "byteblaster",
+	.status = NT,
+	.description = "Altera ByteBlasterMV",
+	.url = "ftp://ftp.altera.com/pub/lit_req/document/ds/dsbytemv.pdf",
+	.spi_cs = {LPT_OUT_PIN_3, 0},
+	.spi_sck = {LPT_OUT_PIN_2, 0},
+	.spi_mosi = {LPT_OUT_PIN_8, 0},
+	.spi_miso = {LPT_IN_PIN_11, 0},
+	.on_enable = {0, LPT_OUT_PIN_14},
+	.on_disable = {LPT_OUT_PIN_14, 0},
+};
+
+static struct lpt_bitbang_spi_programmer prog_atmel_stk200 = {
+	.type = "stk200",
+	.status = NT,
+	.description = "Atmel STK200/300 adapter",
+	.url = "http://real.kiev.ua/old/avreal/en/adapters.html#STK",
+	.spi_cs = {LPT_OUT_PIN_9, 0},
+	.spi_sck = {LPT_OUT_PIN_6, 0},
+	.spi_mosi = {LPT_OUT_PIN_7, 0},
+	.spi_miso = {LPT_IN_PIN_10, 0},
+	.on_enable = {0, LPT_OUT_PIN_4 | LPT_OUT_PIN_5},
+	.on_disable = {LPT_OUT_PIN_4 | LPT_OUT_PIN_5, 0},
+};
+
+static struct lpt_bitbang_spi_programmer prog_wiggler_lpt = {
+	.type = "wiggler",
+	.status = NT,
+	.description = "Wiggler LPT",
+	.url = "http://wiki.openwrt.org/doc/hardware/port.jtag.cable.buffered",
+	.spi_cs = {LPT_OUT_PIN_3, 0},
+	.spi_sck = {LPT_OUT_PIN_4, 0},
+	.spi_mosi = {LPT_OUT_PIN_5, 0},
+	.spi_miso = {LPT_IN_PIN_11, 0},
+};
+
+static struct lpt_bitbang_spi_programmer prog_willem_spi = {
+	.type = "willem",
+	.status = NT,
+	.description = "Willem EPROM Programmer SPI",
+	.spi_cs = {LPT_OUT_PIN_17, 0},
+	.spi_sck = {LPT_OUT_PIN_3, 0},
+	.spi_mosi = {0, LPT_OUT_PIN_2},
+	.spi_miso = {LPT_IN_PIN_11, 0},
+	.on_enable = {LPT_OUT_PIN_16 | LPT_OUT_PIN_14 | LPT_OUT_PIN_1, 0},
+	.on_disable = {LPT_OUT_PIN_1, LPT_OUT_PIN_16 | LPT_OUT_PIN_14},
+};
+
+static struct lpt_bitbang_spi_programmer *lpt_bitbang_spi_types[] = {
+	&prog_rayer_spipgm,
+	&prog_xilinx_dlc5,
+	&prog_altera_byteblastermv,
+	&prog_atmel_stk200,
+	&prog_wiggler_lpt,
+	&prog_willem_spi,
+	NULL
+};
+
+static struct lpt_bitbang_spi_programmer *programmer = NULL;
+static lpt_io_context_t lpt_io_context = NULL;
+static pins_mask_t lpt_pins_state_cached = 0;
+
+#define LOBYTE(value) ((value) & 0xff)
+#define HIBYTE(value) (((value)>>8) & 0xff)
+
+static void lpt_bitbang_out_pins(pins_mask_t lpt_pins_state)
+{
+	lpt_io_out_data(lpt_io_context, LOBYTE(lpt_pins_state));
+	lpt_io_out_control(lpt_io_context, HIBYTE(lpt_pins_state));
+	lpt_pins_state_cached = lpt_pins_state;
+}
+
+static void lpt_bitbang_change_pins(pins_mask_t set_mask,
+				    pins_mask_t clear_mask)
+{
+	pins_mask_t lpt_pins_state = lpt_pins_state_cached;
+	lpt_pins_state |= set_mask;
+	lpt_pins_state &= ~clear_mask;
+
+	if (LOBYTE(lpt_pins_state) != LOBYTE(lpt_pins_state_cached)) {
+		lpt_io_out_data(lpt_io_context, LOBYTE(lpt_pins_state));
+	}
+
+	if (HIBYTE(lpt_pins_state) != HIBYTE(lpt_pins_state_cached)) {
+		lpt_io_out_control(lpt_io_context, HIBYTE(lpt_pins_state));
+	}
+
+	lpt_pins_state_cached = lpt_pins_state;
+}
+
+static void lpt_bitbang_spi_set_pin(struct lpt_bitbang_spi_pin *pin, int val)
+{
+	if (val) {
+		lpt_bitbang_change_pins(pin->set_mask, pin->clear_mask);
+
+	} else {
+		lpt_bitbang_change_pins(pin->clear_mask, pin->set_mask);
+	}
+}
+
+static inline int lpt_bitbang_spi_get_pin(struct lpt_bitbang_spi_pin *pin)
+{
+	uint8_t tmp = lpt_io_in_status(lpt_io_context);
+	return ((tmp & pin->set_mask) | (~tmp & pin->clear_mask)) != 0;
+}
+
+static void lpt_bitbang_spi_set_cs(int val)
+{
+	lpt_bitbang_spi_set_pin(&programmer->spi_cs, val);
+}
+
+static void lpt_bitbang_spi_set_sck(int val)
+{
+	lpt_bitbang_spi_set_pin(&programmer->spi_sck, val);
+}
+
+static void lpt_bitbang_spi_set_mosi(int val)
+{
+	lpt_bitbang_spi_set_pin(&programmer->spi_mosi, val);
+}
+
+static int lpt_bitbang_spi_get_miso(void)
+{
+	return lpt_bitbang_spi_get_pin(&programmer->spi_miso);
+}
+
+static int lpt_bitbang_spi_generic_preinit(void *data)
+{
+	struct lpt_bitbang_spi_programmer *prog =
+	    (struct lpt_bitbang_spi_programmer *)data;
+	msg_pdbg("%s preinit\n", prog->type);
+	lpt_bitbang_spi_set_pin(&prog->on_enable, 1);
+	return 0;
+}
+
+static int lpt_bitbang_spi_generic_shutdown(void *data)
+{
+	struct lpt_bitbang_spi_programmer *prog =
+	    (struct lpt_bitbang_spi_programmer *)data;
+	msg_pdbg("%s shutdown\n", prog->type);
+	lpt_bitbang_spi_set_pin(&prog->spi_cs, 1);
+	lpt_bitbang_spi_set_pin(&prog->on_disable, 1);
+	return 0;
+}
+
+static const struct bitbang_spi_master lpt_bitbang_spi_master = {
+	.type = BITBANG_SPI_MASTER_RAYER,
+	.set_cs = lpt_bitbang_spi_set_cs,
+	.set_sck = lpt_bitbang_spi_set_sck,
+	.set_mosi = lpt_bitbang_spi_set_mosi,
+	.get_miso = lpt_bitbang_spi_get_miso,
+	.half_period = 0,
+};
+
+static int lpt_bitbang_spi_io_init(void *data)
+{
+	(void)data;
+	int io_selected = 0;
+
+	if (!io_selected) {
+		char *arg = extract_programmer_param("ppdev");
+
+		if (arg) {
+			int err;
+			msg_pdbg("Using ppdev=%s for parallel port access.\n",
+				 arg);
+			err =
+			    lpt_io_init(&lpt_io_context, "ppdev", (void *)arg);
+			free(arg);
+			io_selected = 1;
+
+			if (err) {
+				return err;
+			}
+		}
+	}
+
+	if (!io_selected) {
+		char *arg = extract_programmer_param("iobase");
+
+		if (arg) {
+			int err;
+			char *endptr = NULL;
+			unsigned long iobase = strtoul(arg, &endptr, 0);
+			free(arg);
+			io_selected = 2;
+
+			/* Port 0, port >0x10000, unaligned ports and garbage strings
+			 * are rejected.
+			 */
+			if ((iobase <= 0x100) || (iobase >= 0x10000)
+			    || (iobase & 0x3) || (*endptr != '\0')) {
+				/* Using ports below 0x100 is a really bad idea, and
+				 * should only be done if no port between 0x100 and
+				 * 0xfffc works due to routing issues.
+				 */
+				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");
+				return 1;
+
+			} else {
+				msg_pinfo
+				    ("Using address 0x%lx as I/O base for parallel port access.\n",
+				     iobase);
+				err =
+				    lpt_io_init(&lpt_io_context, "direct",
+						(void *)&iobase);
+
+				if (err) {
+					return err;
+				}
+			}
+		}
+	}
+
+	if (!io_selected) {
+		int err;
+		/* Pick a default value for the I/O base. */
+		unsigned long iobase = 0x378;
+		io_selected = 3;
+		msg_pdbg
+		    ("Using address 0x%lx as I/O base for parallel port access.\n",
+		     iobase);
+		err = lpt_io_init(&lpt_io_context, "direct", (void *)&iobase);
+
+		if (err) {
+			return err;
+		}
+	}
+
+	if (!io_selected) {
+		msg_perr("not awailable lpt_io method\n");
+		return 1;
+	}
+
+	/* Get the initial value before writing to any line. */
+	lpt_bitbang_out_pins(lpt_io_in_data(lpt_io_context));
+	return 0;
+}
+
+int lpt_bitbang_spi_init(void)
+{
+	struct lpt_bitbang_spi_programmer **prog = lpt_bitbang_spi_types;
+	char *arg = NULL;
+	programmer = *prog;
+	arg = extract_programmer_param("type");
+
+	if (arg) {
+		for (; *prog; ++prog) {
+			if (0 == strcasecmp(arg, (*prog)->type)) {
+				break;
+			}
+		}
+
+		free(arg);
+
+		if (!*prog) {
+			msg_perr("Error: Invalid device type specified.\n");
+			return 1;
+		}
+	}
+
+	msg_pinfo("programmer: %s\n", (*prog)->type);
+
+	if ((*prog)->description) {
+		msg_pinfo("decription: \"%s\"\n", (*prog)->description);
+	}
+
+	if ((*prog)->url) {
+		msg_pinfo("url: \"%s\"\n", (*prog)->url);
+	}
+
+	programmer = *prog;
+
+	if (lpt_bitbang_spi_io_init(NULL)) {
+		return 1;
+	}
+
+	if (programmer->shutdown) {
+		register_shutdown(programmer->shutdown, (void *)programmer);
+
+	} else {
+		register_shutdown(lpt_bitbang_spi_generic_shutdown,
+				  (void *)programmer);
+	}
+
+	if (programmer->preinit) {
+		if (programmer->preinit(programmer)) {
+			return 1;
+		}
+
+	} else {
+		if (lpt_bitbang_spi_generic_preinit(programmer)) {
+			return 1;
+		}
+	}
+
+	if (bitbang_spi_init(&lpt_bitbang_spi_master)) {
+		return 1;
+	}
+
+	return 0;
+}
diff --git a/lpt_bitbang_spi.h b/lpt_bitbang_spi.h
new file mode 100644
index 0000000..901628a
--- /dev/null
+++ b/lpt_bitbang_spi.h
@@ -0,0 +1,6 @@
+#ifndef lpt_bitbang_spi_h_included_
+#define lpt_bitbang_spi_h_included_
+
+int lpt_bitbang_spi_init(void);
+
+#endif
-- 
1.7.10.4



More information about the flashrom mailing list