aboutsummaryrefslogtreecommitdiff
path: root/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/jtag/drivers/usb_blaster/ublast_access_ftdi.c')
-rw-r--r--src/jtag/drivers/usb_blaster/ublast_access_ftdi.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c b/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c
new file mode 100644
index 00000000..23893e14
--- /dev/null
+++ b/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c
@@ -0,0 +1,136 @@
+/*
+ * Driver for USB-JTAG, Altera USB-Blaster and compatibles
+ *
+ * Inspired from original code from Kolja Waschk's USB-JTAG project
+ * (http://www.ixo.de/info/usb_jtag/), and from openocd project.
+ *
+ * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr
+ * Copyright (C) 2011 Ali Lown ali@lown.me.uk
+ * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca
+ * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <jtag/interface.h>
+#include <jtag/commands.h>
+
+#include "ublast_access.h"
+#include <ftdi.h>
+
+static struct ftdi_context *ublast_getftdic(struct ublast_lowlevel *low)
+{
+ return low->priv;
+}
+
+static int ublast_ftdi_read(struct ublast_lowlevel *low, uint8_t *buf,
+ unsigned size, uint32_t *bytes_read)
+{
+ int retval;
+ int timeout = 100;
+ struct ftdi_context *ftdic = ublast_getftdic(low);
+
+ *bytes_read = 0;
+ while ((*bytes_read < size) && timeout--) {
+ retval = ftdi_read_data(ftdic, buf + *bytes_read,
+ size - *bytes_read);
+ if (retval < 0) {
+ *bytes_read = 0;
+ LOG_ERROR("ftdi_read_data: %s",
+ ftdi_get_error_string(ftdic));
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+ *bytes_read += retval;
+ }
+ return ERROR_OK;
+}
+
+static int ublast_ftdi_write(struct ublast_lowlevel *low, uint8_t *buf, int size,
+ uint32_t *bytes_written)
+{
+ int retval;
+ struct ftdi_context *ftdic = ublast_getftdic(low);
+
+ retval = ftdi_write_data(ftdic, buf, size);
+ if (retval < 0) {
+ *bytes_written = 0;
+ LOG_ERROR("ftdi_write_data: %s",
+ ftdi_get_error_string(ftdic));
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+ *bytes_written = retval;
+ return ERROR_OK;
+}
+
+static int ublast_ftdi_init(struct ublast_lowlevel *low)
+{
+ uint8_t latency_timer;
+ struct ftdi_context *ftdic = ublast_getftdic(low);
+
+ LOG_INFO("usb blaster interface using libftdi");
+ if (ftdi_init(ftdic) < 0)
+ return ERROR_JTAG_INIT_FAILED;
+
+ /* context, vendor id, product id */
+ if (ftdi_usb_open(ftdic, low->ublast_vid, low->ublast_pid) < 0) {
+ LOG_ERROR("unable to open ftdi device: %s", ftdic->error_str);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if (ftdi_usb_reset(ftdic) < 0) {
+ LOG_ERROR("unable to reset ftdi device");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if (ftdi_set_latency_timer(ftdic, 2) < 0) {
+ LOG_ERROR("unable to set latency timer");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if (ftdi_get_latency_timer(ftdic, &latency_timer) < 0) {
+ LOG_ERROR("unable to get latency timer");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+ LOG_DEBUG("current latency timer: %u", latency_timer);
+
+ ftdi_disable_bitbang(ftdic);
+ return ERROR_OK;
+}
+
+static int ublast_ftdi_quit(struct ublast_lowlevel *low)
+{
+ struct ftdi_context *ftdic = ublast_getftdic(low);
+
+ ftdi_usb_close(ftdic);
+ ftdi_deinit(ftdic);
+ return ERROR_OK;
+};
+
+static struct ublast_lowlevel_priv {
+ struct ftdi_context ftdic;
+} info;
+
+static struct ublast_lowlevel low = {
+ .open = ublast_ftdi_init,
+ .close = ublast_ftdi_quit,
+ .read = ublast_ftdi_read,
+ .write = ublast_ftdi_write,
+ .priv = &info,
+};
+
+struct ublast_lowlevel *ublast_register_ftdi(void)
+{
+ return &low;
+}