From 05f717c81da603472988e31c63a2c082fef6c491 Mon Sep 17 00:00:00 2001
From: Maksim Kuleshov <[email protected]>
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 <[email protected]>
---
 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

_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to