diff --git a/jtag/ChangeLog b/jtag/ChangeLog index c44e7865..d859b189 100644 --- a/jtag/ChangeLog +++ b/jtag/ChangeLog @@ -1,3 +1,9 @@ +2007-12-26 Kolja Waschk + + * tap/cable/vision_ep9307.c, tap/cable.c, tap/Makefile.am, configure.ac: + Integrated first modern (single-file w/o parport) cable driver + (1858709: EP9307 target specific cable driver, from Hartley Sweeten) + 2007-12-23 Kolja Waschk Version 0.7 released. diff --git a/jtag/NEWS b/jtag/NEWS index 09a8b9d7..815b14e5 100644 --- a/jtag/NEWS +++ b/jtag/NEWS @@ -2,6 +2,11 @@ $Id$ Also see libbrux/NEWS for more news, especially regarding the flash support. +urjtag-n/a + + * New and updated cable drivers + - Vision EP9307 GPIO (Hartley Sweeten) + urjtag-0.7 (2007-12-23) * Integrated SVF player (Arnim Laeuger) diff --git a/jtag/configure.ac b/jtag/configure.ac index 65fc1d0c..9c887f7c 100644 --- a/jtag/configure.ac +++ b/jtag/configure.ac @@ -284,6 +284,23 @@ AS_IF([test "x$HAVELIBFTD2XX" == xyes], [ ]) AC_SUBST(FTD2XXLIB) + +dnl Enable cable driver for Vision EP9307? +AC_ARG_ENABLE(ep9307, +[ --enable-ep9307 Enable cable driver for EP9307], +[case "${enableval}" in + yes) ep9307=true ;; + no) ep9307=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-ep9307) ;; + esac], +[ep9307=false]) +AS_IF([test "x$ep9307" = xtrue], [ + AM_CONDITIONAL(ENABLE_EP9307, true) + AC_DEFINE(ENABLE_EP9307, 1, [define if cable driver for ep9307 is enabled]) +],[ + AM_CONDITIONAL(ENABLE_EP9307, false) +]) + CFLAGS="$CFLAGS -Wall" CPPFLAGS="$CPPFLAGS -I\$(top_srcdir) -I\$(top_srcdir)/include" diff --git a/jtag/src/tap/Makefile.am b/jtag/src/tap/Makefile.am index 3a60b01a..2610d9cb 100644 --- a/jtag/src/tap/Makefile.am +++ b/jtag/src/tap/Makefile.am @@ -78,3 +78,9 @@ libtap_a_SOURCES += $(FTDIDEPENDENT) endif endif +if ENABLE_EP9307 +libtap_a_SOURCES += \ + cable/vision_ep9307.c +endif + + diff --git a/jtag/src/tap/cable.c b/jtag/src/tap/cable.c index c3015748..09dac851 100644 --- a/jtag/src/tap/cable.c +++ b/jtag/src/tap/cable.c @@ -57,6 +57,9 @@ extern cable_driver_t wiggler_cable_driver; extern cable_driver_t xpc_int_cable_driver; extern cable_driver_t xpc_ext_cable_driver; #endif +#ifdef ENABLE_EP9307 +extern cable_driver_t ep9307_cable_driver; +#endif cable_driver_t *cable_drivers[] = { &arcom_cable_driver, @@ -79,6 +82,9 @@ cable_driver_t *cable_drivers[] = { #ifdef HAVE_LIBUSB &xpc_int_cable_driver, &xpc_ext_cable_driver, +#endif +#ifdef ENABLE_EP9307 + &ep9307_cable_driver, #endif NULL /* last must be NULL */ }; diff --git a/jtag/src/tap/cable/vision_ep9307.c b/jtag/src/tap/cable/vision_ep9307.c new file mode 100644 index 00000000..7aefea1a --- /dev/null +++ b/jtag/src/tap/cable/vision_ep9307.c @@ -0,0 +1,323 @@ +/* + * $Id: vision_ep9307.c $ + * + * Vision EP9307 SoM GPIO JTAG Cable Driver + * Copyright (C) 2007, 2008 H Hartley Sweeten + * + * 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. + * + * Written by H Hartley Sweeten , 2007, 2008. + * + */ + +#include "sysdep.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "cable.h" +#include "chain.h" + +#include "generic.h" + +#include + +#define SYSCON_BASE 0x80930000 +#define SYSCON_DEVICE_CONFIG 0x80 +#define SYSCON_SWLOCK 0xC0 + +#define SYSCON_DEVCFG_HonIDE (1 << 11) + +#define GPIO_BASE 0x80840000 +#define GPIO_PHDR 0x40 +#define GPIO_PHDDR 0x44 + +#define TDO 4 +#define TDI 6 +#define TMS 5 +#define TCK 7 +#define TRST 3 + +#define HGPIO(b) (1 << (b)) +#define EP9307_TDO HGPIO(TDO) +#define EP9307_TDI HGPIO(TDI) +#define EP9307_TMS HGPIO(TMS) +#define EP9307_TCK HGPIO(TCK) +#define EP9307_TRST HGPIO(TRST) + +#define GPIO_INPUT_MASK ((EP9307_TCK)|(EP9307_TMS)|(EP9307_TDI)|(EP9307_TRST)) +#define GPIO_OUTPUT_MASK (~(EP9307_TDO)) +#define GPIO_BITMASK (~((EP9307_TDO)|(EP9307_TDI)|(EP9307_TMS)|(EP9307_TCK)|(EP9307_TRST))) + +typedef struct { + int fd_dev_mem; + void *map_base; + size_t map_size; + uint32_t *gpio_PHDR; + int trst; +} ep9307_params_t; + +static int +ep9307_gpio_open( cable_t *cable ) +{ + ep9307_params_t *p = cable->params; + off_t map_mask; + uint32_t *syscon_devcfg; + uint32_t *syscon_sysswlock; + uint32_t *gpio_PHDDR; + uint32_t tmp; + + /* Open the memory device so we can access the hardware registers */ + p->fd_dev_mem = open("/dev/mem", O_RDWR | O_SYNC); + if (p->fd_dev_mem == -1) { + printf( _("Error: unable to open /dev/mem\n") ); + return -1; + } + + p->map_size = getpagesize(); + map_mask = p->map_size - 1; + + /* Map the System Controller registers */ + p->map_base = mmap(0, p->map_size, PROT_READ | PROT_WRITE, MAP_SHARED, p->fd_dev_mem, SYSCON_BASE & ~map_mask); + if (p->map_base == MAP_FAILED) { + printf( _("Error: unable to mmap the System Control registers\n") ); + close (p->fd_dev_mem); + return -1; + } + + /* Create the pointers to access the DeviceCfg and SysSWLock registers */ + syscon_devcfg = (uint32_t*)(p->map_base + SYSCON_DEVICE_CONFIG); + syscon_sysswlock = (uint32_t*)(p->map_base + SYSCON_SWLOCK); + + /* Set the HonIDE bit in the DeviceCfg register so we can use Port H as GPIO */ + tmp = *((uint32_t*)syscon_devcfg); + tmp |= SYSCON_DEVCFG_HonIDE; + + /* The DeviceCfg register has a SoftwareLock; unlock it first */ + *((uint32_t*)syscon_sysswlock) = 0xAA; + *((uint32_t*)syscon_devcfg) = tmp; + + /* Unmap the System Controller registers */ + if (munmap(p->map_base, p->map_size) == -1) { + printf( _("Error: unable to munmap the System Controller registers\n")); + close (p->fd_dev_mem); + return -1; + } + + /* Map the GPIO registers */ + p->map_base = mmap(0, p->map_size, PROT_READ | PROT_WRITE, MAP_SHARED, p->fd_dev_mem, GPIO_BASE & ~map_mask); + if (p->map_base == MAP_FAILED) { + printf( _("Error: unable to mmap the GPIO registers\n") ); + close (p->fd_dev_mem); + return -1; + } + + /* Create the pointers to access the PHDR and PHDDR registers */ + p->gpio_PHDR = (uint32_t*)(p->map_base + GPIO_PHDR); + gpio_PHDDR = (uint32_t*)(p->map_base + GPIO_PHDDR); + + /* Set the GPIO pins as inputs/outputs as needed for the JTAG interface */ + tmp = *((uint32_t*)gpio_PHDDR); + tmp |= GPIO_INPUT_MASK; + tmp &= GPIO_OUTPUT_MASK; + *((uint32_t*)gpio_PHDDR) = tmp; + + return 0; +} + +static int +ep9307_gpio_close( cable_t *cable ) +{ + ep9307_params_t *p = cable->params; + + /* Unmap the GPIO registers */ + if (munmap(p->map_base, p->map_size) == -1) { + printf( _("Error: unable to munmap the GPIO registers\n")); + } + close(p->fd_dev_mem); + return 0; +} + +static int +ep9307_gpio_write( cable_t *cable, uint8_t data ) +{ + ep9307_params_t *p = cable->params; + uint32_t tmp; + + tmp = *((uint32_t*)p->gpio_PHDR); + tmp &= GPIO_BITMASK; + tmp |= data; + *((uint32_t*)p->gpio_PHDR) = tmp; + + return 0; +} + +static int +ep9307_gpio_read( cable_t *cable ) +{ + ep9307_params_t *p = cable->params; + uint32_t tmp; + + tmp = *((uint32_t*)p->gpio_PHDR); + + return tmp; +} + +static int +ep9307_connect( char *params[], cable_t *cable ) +{ + ep9307_params_t *cable_params; + + if ( cmd_params( params ) != 1) { + printf( _("Error: This cable type does not accept parameters!\n") ); + return 1; + } + + if (cable->params != NULL) { + printf( _("Disconnecting %s\n"), _(cable->driver->description) ); + cable->driver->disconnect( cable ); + } + + printf( _("Initializing Vision EP9307 SoM GPIO JTAG Cable\n") ); + + cable_params = malloc( sizeof *cable_params ); + if (!cable_params) { + printf( _("%s(%d) Out of memory\n"), __FILE__, __LINE__ ); + free( cable ); + return 4; + } + + cable->port = NULL; + cable->params = cable_params; + cable->chain = NULL; + + return 0; +} + +static void +ep9307_disconnect( cable_t *cable ) +{ + ep9307_gpio_close( cable ); + chain_disconnect( cable->chain ); +} + +static void +ep9307_cable_free( cable_t *cable ) +{ + free( cable->params ); + free( cable ); +} + +static int +ep9307_init( cable_t *cable ) +{ + ep9307_params_t *p = cable->params; + + if (ep9307_gpio_open( cable )) + return -1; + + ep9307_gpio_write( cable, 1 << TRST ); + p->trst = 1; + + return 0; +} + +static void +ep9307_done( cable_t *cable ) +{ + ep9307_gpio_close( cable ); +} + +static void +ep9307_clock( cable_t *cable, int tms, int tdi, int n ) +{ + ep9307_params_t *p = cable->params; + int bit_mask; + int i; + + tms = tms ? 1 : 0; + tdi = tdi ? 1 : 0; + + bit_mask = (tms << TMS) | (tdi << TDI) | (p->trst << TRST); + + for (i = 0; i < n; i++) { + ep9307_gpio_write( cable, (0 << TCK) | bit_mask ); + ep9307_gpio_write( cable, (1 << TCK) | bit_mask ); + } +} + +/** + * NOTE: This also lowers the TDI and TMS lines; is this intended? + */ +static int +ep9307_get_tdo( cable_t *cable ) +{ + ep9307_params_t *p = cable->params; + + ep9307_gpio_write( cable, (0 << TCK) | (p->trst << TRST) ); + return (ep9307_gpio_read( cable ) >> TDO) & 1; +} + +/** + * NOTE: This also lowers the TCK, TDI, and TMS lines; is this intended? + */ +static int +ep9307_set_trst( cable_t *cable, int trst ) +{ + ep9307_params_t *p = cable->params; + + p->trst = trst ? 1 : 0; + + ep9307_gpio_write( cable, p->trst << TRST ); + return p->trst; +} + +static int +ep9307_get_trst( cable_t *cable ) +{ + return (ep9307_gpio_read( cable ) >> TRST) & 1; +} + +static void +ep9307_help( const char *cablename ) +{ + printf( _( + "Usage: cable %s\n" + "\n" + ), cablename ); +} + +cable_driver_t ep9307_cable_driver = { + "EP9307", + N_("Vision EP9307 SoM GPIO JTAG Cable"), + ep9307_connect, + ep9307_disconnect, + ep9307_cable_free, + ep9307_init, + ep9307_done, + ep9307_clock, + ep9307_get_tdo, + generic_transfer, + ep9307_set_trst, + ep9307_get_trst, + ep9307_help +};