add new gpio cable driver by Stefano Babic

git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1814 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Mike Frysinger 15 years ago
parent 545dca732e
commit 7941d528ea

@ -1,3 +1,12 @@
2010-07-30 Mike Frysinger <vapier@gentoo.org>
* include/urjtag/cable.h (URJ_CABLE_PARAM_KEY): Add new cable params for tdi,
tdo, tms, and tck for new GPIO cable driver.
* src/tap/cable.c (cable_param): Likewise.
* src/tap/cable_list.h: Add new GPIO cable driver entry.
* configure.ac, src/tap/Makefile.am: Likewise.
* src/tap/cable/gpio.c: New GPIO cable driver by Stefano Babic.
2010-07-18 Mike Frysinger <vapier@gentoo.org>
* src/apps/jtag/jtag.c (main): Do not abort running just because a user's

@ -5,6 +5,7 @@ or someone is missing who should be listed there!
Shaju Abraham
Julien Aube
Stefano Babic
Beregnyei Balazs
Michael Banditt
Jeff Bartlett

@ -645,6 +645,7 @@ URJ_DRIVER_SET([cable], [
ea253
ei012
ft2232
gpio
ice100
igloo
jlink

@ -59,6 +59,10 @@ typedef enum URJ_CABLE_PARAM_KEY
URJ_CABLE_PARAM_KEY_DESC, /* string generic_usbconn */
URJ_CABLE_PARAM_KEY_DRIVER, /* string generic_usbconn */
URJ_CABLE_PARAM_KEY_BITMAP, /* string wiggler */
URJ_CABLE_PARAM_KEY_TDI, /* lu gpio used as TDI */
URJ_CABLE_PARAM_KEY_TDO, /* lu gpio used as TDO */
URJ_CABLE_PARAM_KEY_TMS, /* lu gpio used as TMS */
URJ_CABLE_PARAM_KEY_TCK, /* lu gpio used as TCK */
}
urj_cable_param_key_t;

@ -114,6 +114,7 @@ src/tap/cable/ft2232.c
src/tap/cable/generic.c
src/tap/cable/generic_parport.c
src/tap/cable/generic_usbconn.c
src/tap/cable/gpio.c
src/tap/cable/jim.c
src/tap/cable/jlink.c
src/tap/cable/keithkoep.c

@ -77,6 +77,11 @@ libtap_la_SOURCES += \
cable/ei012.c
endif
if ENABLE_CABLE_GPIO
libtap_la_SOURCES += \
cable/gpio.c
endif
if ENABLE_CABLE_KEITHKOEP
libtap_la_SOURCES += \
cable/keithkoep.c

@ -668,6 +668,10 @@ static const urj_param_descr_t cable_param[] =
{ URJ_CABLE_PARAM_KEY_DESC, URJ_PARAM_TYPE_STRING, "desc", },
{ URJ_CABLE_PARAM_KEY_DRIVER, URJ_PARAM_TYPE_STRING, "driver", },
{ URJ_CABLE_PARAM_KEY_BITMAP, URJ_PARAM_TYPE_STRING, "bitmap", },
{ URJ_CABLE_PARAM_KEY_TDI, URJ_PARAM_TYPE_LU, "tdi", },
{ URJ_CABLE_PARAM_KEY_TDO, URJ_PARAM_TYPE_LU, "tdo", },
{ URJ_CABLE_PARAM_KEY_TMS, URJ_PARAM_TYPE_LU, "tms", },
{ URJ_CABLE_PARAM_KEY_TCK, URJ_PARAM_TYPE_LU, "tck", },
};
const urj_param_list_t urj_cable_param_list =

@ -0,0 +1,421 @@
/*
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de.
* GPIO JTAG Cable Driver
*
* Based on TS7800 GPIO JTAG Cable Driver
* Copyright (C) 2008 Catalin Ionescu
*
* 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.
*
* 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., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
#include <sysdep.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <urjtag/cable.h>
#include <urjtag/parport.h>
#include <urjtag/chain.h>
#include <urjtag/cmd.h>
#include "generic.h"
#define GPIO_PATH "/sys/class/gpio/"
#define GPIO_EXPORT_PATH GPIO_PATH "export"
#define GPIO_UNEXPORT_PATH GPIO_PATH "unexport"
/* pin mapping */
enum {
GPIO_TDI = 0,
GPIO_TCK,
GPIO_TMS,
GPIO_TDO,
GPIO_REQUIRED
};
typedef struct {
unsigned int jtag_gpios[4];
int signals;
uint32_t lastout;
FILE *fp_gpios[4];
} gpio_params_t;
static int gpio_export (unsigned int gpio, int export)
{
int ret;
char *fname;
FILE *fp;
if (export)
fname = GPIO_EXPORT_PATH;
else
fname = GPIO_UNEXPORT_PATH;
fp = fopen (fname, "w");
if (!fp)
{
urj_warning (_("%s: cannot open to (un)export GPIO %u\n"), fname, gpio);
return URJ_STATUS_FAIL;
}
ret = fprintf (fp, "%u", gpio);
fclose (fp);
return URJ_STATUS_OK;
}
static int gpio_direction (unsigned int gpio, int out)
{
int ret;
char fname[50];
FILE *fp;
snprintf (fname, sizeof (fname) - 1,
"%sgpio%u/direction", GPIO_PATH, gpio);
fname[sizeof (fname) - 1] = '\0';
fp = fopen (fname, "w");
if (!fp)
{
urj_warning (_("%s: cannot open to set direction\n"), fname);
return URJ_STATUS_FAIL;
}
ret = fprintf (fp, "%s", out ? "out" : "in");
fclose (fp);
if (ret != strlen (out ? "out" : "in"))
{
urj_warning (_("Error setting direction gpio %u %s %d\n"),
gpio, out ? "out" : "in", ret);
return URJ_STATUS_FAIL;
}
return URJ_STATUS_OK;
}
static int gpio_set_value (FILE *fp, int value)
{
int ret;
ret = fprintf (fp, "%u", value ? 1 : 0);
if (ret != 1)
{
urj_warning (_("Error setting value gpio\n"));
return URJ_STATUS_FAIL;
}
return URJ_STATUS_OK;
}
static int gpio_get_value (unsigned int gpio)
{
int ret;
int value;
char fname[50];
FILE *fp;
snprintf (fname, sizeof (fname),
"%sgpio%u/value", GPIO_PATH, gpio);
fname[sizeof (fname) - 1] = '\0';
fp = fopen (fname, "r");
if (!fp)
{
urj_warning (_("%s: cannot open to read GPIO %u\n"), fname, gpio);
return URJ_STATUS_FAIL;
}
ret = fscanf (fp, "%i", &value);
fclose (fp);
if (ret != 1)
{
urj_warning (_("Error getting value of gpio %u\n"), gpio);
return URJ_STATUS_FAIL;
}
return value;
}
static int
gpio_open (urj_cable_t *cable)
{
gpio_params_t *p = cable->params;
char fname[50];
int i, ret;
/* Export all gpios */
for (i = 0; i < GPIO_REQUIRED; i++)
{
unsigned int gpio = p->jtag_gpios[i];
ret = gpio_export (gpio, 1);
if (ret)
{
urj_warning (_("gpio[%d] %u cannot be exported\n"), i, gpio);
return URJ_STATUS_FAIL;
}
gpio_direction (gpio, (i == GPIO_TDO) ? 0 : 1);
p->fp_gpios[i] = NULL;
snprintf (fname, sizeof (fname), "%sgpio%u/value", GPIO_PATH, gpio);
fname[sizeof (fname) - 1] = '\0';
if (i != GPIO_TDO)
p->fp_gpios[i] = fopen (fname, "w");
else
p->fp_gpios[i] = fopen (fname, "r");
if (!p->fp_gpios[i])
{
urj_warning (_("%s: cannot open gpio[%d] %u\n"), fname, i, gpio);
return URJ_STATUS_FAIL;
}
if (setvbuf(p->fp_gpios[i], (char *)NULL, _IONBF, 0))
{
urj_warning (_("gpio[%d] %u still in buffered mode\n"), i, gpio);
return URJ_STATUS_FAIL;
}
}
return URJ_STATUS_OK;
}
static int
gpio_close (urj_cable_t *cable)
{
int i;
gpio_params_t *p = cable->params;
for (i = 0; i < GPIO_REQUIRED; i++)
{
if (p->fp_gpios[i])
fclose (p->fp_gpios[i]);
gpio_export (p->jtag_gpios[i], 0);
}
return URJ_STATUS_OK;
}
static void
gpio_help (urj_log_level_t ll, const char *cablename)
{
urj_log (ll,
_("Usage: cable %s tdi=<gpio_tdi> tdo=<gpio_tdo> "
"tck=<gpio_tck> tms=<gpio_tms>\n"
"\n"), cablename);
}
static int
gpio_connect (urj_cable_t *cable, const urj_param_t *params[])
{
gpio_params_t *cable_params;
int i;
cable_params = calloc (1, sizeof (*cable_params));
if (!cable_params)
{
urj_error_set (URJ_ERROR_OUT_OF_MEMORY, _("calloc(%zd) fails"),
sizeof (*cable_params));
free (cable);
return URJ_STATUS_FAIL;
}
cable_params->jtag_gpios[GPIO_TDI] = GPIO_REQUIRED;
cable_params->jtag_gpios[GPIO_TDO] = GPIO_REQUIRED;
cable_params->jtag_gpios[GPIO_TMS] = GPIO_REQUIRED;
cable_params->jtag_gpios[GPIO_TCK] = GPIO_REQUIRED;
if (params != NULL)
/* parse arguments beyond the cable name */
for (i = 0; params[i] != NULL; i++)
{
switch (params[i]->key)
{
case URJ_CABLE_PARAM_KEY_TDI:
cable_params->jtag_gpios[GPIO_TDI] = params[i]->value.lu;
break;
case URJ_CABLE_PARAM_KEY_TDO:
cable_params->jtag_gpios[GPIO_TDO] = params[i]->value.lu;
break;
case URJ_CABLE_PARAM_KEY_TMS:
cable_params->jtag_gpios[GPIO_TMS] = params[i]->value.lu;
break;
case URJ_CABLE_PARAM_KEY_TCK:
cable_params->jtag_gpios[GPIO_TCK] = params[i]->value.lu;
break;
default:
break;
}
}
urj_log (URJ_LOG_LEVEL_NORMAL,
_("Initializing GPIO JTAG Chain\n"));
/*
* We need to configure the cable only once. Next time
* is called, the old parameters are taken if a newer
* is not passed
*/
for (i = GPIO_TDI; i <= GPIO_TDO; i++)
if (cable_params->jtag_gpios[i] == GPIO_REQUIRED)
{
urj_error_set (URJ_ERROR_SYNTAX, _("missing required gpios\n"));
gpio_help (URJ_ERROR_SYNTAX, "gpio");
return URJ_STATUS_FAIL;
}
cable->params = cable_params;
cable->chain = NULL;
cable->delay = 1000;
return URJ_STATUS_OK;
}
static void
gpio_disconnect (urj_cable_t *cable)
{
urj_tap_chain_disconnect (cable->chain);
gpio_close (cable);
}
static void
gpio_cable_free (urj_cable_t *cable)
{
free (cable->params);
free (cable);
}
static int
gpio_init (urj_cable_t *cable)
{
gpio_params_t *p = cable->params;
if (gpio_open (cable) != URJ_STATUS_OK)
return URJ_STATUS_FAIL;
p->signals = URJ_POD_CS_TRST;
return URJ_STATUS_OK;
}
static void
gpio_done (urj_cable_t *cable)
{
gpio_close (cable);
}
static void
gpio_clock (urj_cable_t *cable, int tms, int tdi, int n)
{
gpio_params_t *p = cable->params;
int i;
tms = tms ? 1 : 0;
tdi = tdi ? 1 : 0;
gpio_set_value (p->fp_gpios[GPIO_TMS], tms);
gpio_set_value (p->fp_gpios[GPIO_TDI], tdi);
for (i = 0; i < n; i++)
{
gpio_set_value (p->fp_gpios[GPIO_TCK], 0);
gpio_set_value (p->fp_gpios[GPIO_TCK], 1);
gpio_set_value (p->fp_gpios[GPIO_TCK], 0);
}
}
static int
gpio_get_tdo ( urj_cable_t *cable )
{
gpio_params_t *p = cable->params;
gpio_set_value(p->fp_gpios[GPIO_TCK], 0);
gpio_set_value(p->fp_gpios[GPIO_TDI], 0);
gpio_set_value(p->fp_gpios[GPIO_TMS], 0);
p->lastout &= ~(URJ_POD_CS_TMS | URJ_POD_CS_TDI | URJ_POD_CS_TCK);
urj_tap_cable_wait (cable);
return (gpio_get_value (p->jtag_gpios[GPIO_TDO]));
}
static int
gpio_current_signals (urj_cable_t *cable)
{
gpio_params_t *p = cable->params;
int sigs = p->signals & ~(URJ_POD_CS_TMS | URJ_POD_CS_TDI | URJ_POD_CS_TCK);
if (p->lastout & URJ_POD_CS_TCK) sigs |= URJ_POD_CS_TCK;
if (p->lastout & URJ_POD_CS_TDI) sigs |= URJ_POD_CS_TDI;
if (p->lastout & URJ_POD_CS_TMS) sigs |= URJ_POD_CS_TMS;
return sigs;
}
static int
gpio_set_signal (urj_cable_t *cable, int mask, int val)
{
int prev_sigs = gpio_current_signals (cable);
gpio_params_t *p = cable->params;
mask &= (URJ_POD_CS_TDI | URJ_POD_CS_TCK | URJ_POD_CS_TMS); // only these can be modified
if (mask != 0)
{
if (mask & URJ_POD_CS_TMS)
gpio_set_value (p->fp_gpios[GPIO_TMS], val & URJ_POD_CS_TMS);
if (mask & URJ_POD_CS_TDI)
gpio_set_value (p->fp_gpios[GPIO_TDI], val & URJ_POD_CS_TDI);
if (mask & URJ_POD_CS_TCK)
gpio_set_value (p->fp_gpios[GPIO_TCK], val & URJ_POD_CS_TCK);
}
p->lastout = val & mask;
return prev_sigs;
}
static int
gpio_get_signal (urj_cable_t *cable, urj_pod_sigsel_t sig)
{
return (gpio_current_signals (cable) & sig) ? 1 : 0;
}
const urj_cable_driver_t urj_tap_cable_gpio_driver = {
"gpio",
N_("GPIO JTAG Chain"),
URJ_CABLE_DEVICE_OTHER,
{ .other = gpio_connect, },
gpio_disconnect,
gpio_cable_free,
gpio_init,
gpio_done,
urj_tap_cable_generic_set_frequency,
gpio_clock,
gpio_get_tdo,
urj_tap_cable_generic_transfer,
gpio_set_signal,
gpio_get_signal,
urj_tap_cable_generic_flush_one_by_one,
gpio_help
};

@ -59,6 +59,9 @@ _URJ_CABLE(ft2232_turtelizer2)
_URJ_CABLE(ft2232_usbscarab2)
_URJ_CABLE(ft2232_usbtojtagif)
#endif
#ifdef ENABLE_CABLE_GPIO
_URJ_CABLE(gpio)
#endif
#ifdef ENABLE_CABLE_ICE100
_URJ_CABLE(ice100B)
_URJ_CABLE(ezkit_10)

Loading…
Cancel
Save