From 7cfab50f93cef921fbbb169100bb3ee18212facd Mon Sep 17 00:00:00 2001
From: Anatolij Gustschin <agust@denx.de>
Date: Fri, 17 Jul 2009 00:27:14 +0200
Subject: [PATCH] add aria driver

Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
 configure.ac              |    3 +-
 po/POTFILES.in            |    1 +
 src/tap/Makefile.am       |    5 +
 src/tap/cable.c           |    4 +
 src/tap/cable/aria_gpio.c |  362 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 374 insertions(+), 1 deletions(-)
 create mode 100644 src/tap/cable/aria_gpio.c

diff --git a/configure.ac b/configure.ac
index 8737097..3928cb2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -468,7 +468,7 @@ CHECK_DRIVER([$busdrivers], [enabled_bus_drivers], [zefant_xs3],    [ENABLE_BUS_
 
 # Enable cable drivers
 AC_DEFUN([DEF_ENABLE_CABLEDRIVERS], [\
-arcom byteblaster dlc5 ea253 ei012 ft2232 igloo jlink keithkoep lattice mpcbdm triton usbblaster wiggler xpc])
+arcom aria_gpio byteblaster dlc5 ea253 ei012 ft2232 igloo jlink keithkoep lattice mpcbdm triton usbblaster wiggler xpc])
 AC_DEFUN([DEF_DISABLE_CABLEDRIVERS], [ep9307 jim ts7800])
 AC_ARG_ENABLE(cable,
 [AS_HELP_STRING([--enable-cable], [Enable default set or specific cable drivers.])]
@@ -495,6 +495,7 @@ AS_IF([test "x$HAVELIBUSB" != "xyes"], [
 #
 enabled_cable_drivers=''
 CHECK_DRIVER([$cabledrivers], [enabled_cable_drivers], [arcom],       [ENABLE_CABLE_ARCOM])
+CHECK_DRIVER([$cabledrivers], [enabled_cable_drivers], [aria_gpio],   [ENABLE_CABLE_ARIA])
 CHECK_DRIVER([$cabledrivers], [enabled_cable_drivers], [byteblaster], [ENABLE_CABLE_BYTEBLASTER])
 CHECK_DRIVER([$cabledrivers], [enabled_cable_drivers], [dlc5],        [ENABLE_CABLE_DLC5])
 CHECK_DRIVER([$cabledrivers], [enabled_cable_drivers], [ea253],       [ENABLE_CABLE_EA253])
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 37a4453..7daf71b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -102,6 +102,7 @@ src/svf/svf_bison.c
 src/svf/svf.c
 src/svf/svf_flex.c
 src/tap/cable/arcom.c
+src/tap/cable/aria_gpio.c
 src/tap/cable/byteblaster.c
 src/tap/cable.c
 src/tap/cable/dlc5.c
diff --git a/src/tap/Makefile.am b/src/tap/Makefile.am
index e0defd5..edb0d64 100644
--- a/src/tap/Makefile.am
+++ b/src/tap/Makefile.am
@@ -50,6 +50,11 @@ libtap_a_SOURCES += \
 	cable/arcom.c
 endif
 
+if ENABLE_CABLE_ARIA
+libtap_a_SOURCES += \
+	cable/aria_gpio.c
+endif
+
 if ENABLE_CABLE_BYTEBLASTER
 libtap_a_SOURCES += \
 	cable/byteblaster.c
diff --git a/src/tap/cable.c b/src/tap/cable.c
index c8945fd..b35567a 100644
--- a/src/tap/cable.c
+++ b/src/tap/cable.c
@@ -40,6 +40,7 @@
 #undef VERBOSE
 
 extern cable_driver_t arcom_cable_driver;
+extern cable_driver_t aria_cable_driver;
 extern cable_driver_t byteblaster_cable_driver;
 extern cable_driver_t usbblaster_cable_driver;
 extern cable_driver_t ft2232_cable_driver;
@@ -74,6 +75,9 @@ cable_driver_t *cable_drivers[] = {
 #ifdef ENABLE_CABLE_ARCOM
 	&arcom_cable_driver,
 #endif
+#ifdef ENABLE_CABLE_ARIA
+	&aria_cable_driver,
+#endif
 #ifdef ENABLE_CABLE_BYTEBLASTER
 	&byteblaster_cable_driver,
 #endif
diff --git a/src/tap/cable/aria_gpio.c b/src/tap/cable/aria_gpio.c
new file mode 100644
index 0000000..e35ee60
--- /dev/null
+++ b/src/tap/cable/aria_gpio.c
@@ -0,0 +1,362 @@
+/*
+ * Aria GPIO JTAG Cable Driver
+ * Copyright (C) 2009 DENX
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "cable.h"
+#include "chain.h"
+
+#include "generic.h"
+
+#include <cmd.h>
+
+
+#define CPU_IS_REV_2
+
+/* base is page aligned here, so not realy GPIO/IOCTL base */
+#define GPIO_BASE		0x80001000
+#define GPIO_DIR		(0x0100/4)
+#define GPIO_ODR		(0x0104/4)
+#define GPIO_OUT		(0x0108/4)
+#define GPIO_IN			(0x0108/4)
+
+#define IOCTL_BASE		0x8000a000
+#define IOCTL_J1850_TX		(0x0200/4)
+#define IOCTL_PSC6_2		(0x028c/4)
+#define IOCTL_PSC6_3		(0x0290/4)
+
+/* GPIO4 pin multiplexing */
+#ifdef CPU_IS_REV_2
+#define PAD_IOCTL_J1850_TX_FUNCMUX	0x2
+#else
+#define PAD_IOCTL_J1850_TX_FUNCMUX	0x3
+#endif
+
+/* pin mapping on aria */
+#define TDO			(31 - 28)
+#define TDI			(31 - 14)
+#define TCK			(31 - 15)
+#define TMS			(31 - 4)
+
+#define HGPIO(b)		(1 << (b))
+#define aria_TDO		HGPIO(TDO)
+#define aria_TDI		HGPIO(TDI)
+#define aria_TMS		HGPIO(TMS)
+#define aria_TCK		HGPIO(TCK)
+
+#define GPIO_INPUT_MASK		((aria_TCK)|(aria_TMS)|(aria_TDI))
+#define GPIO_OUTPUT_MASK	aria_TDO
+#define GPIO_BITMASK		(~((aria_TDO)|(aria_TDI)|(aria_TMS)|(aria_TCK)))
+
+typedef struct {
+	int		fd_dev_mem;
+	void		*map_base;
+	size_t		map_size;
+	uint32_t	*gpio_base;
+	int		signals;
+	uint32_t	lastout;
+	void		*ioctl_map_base;
+	uint32_t	*ioctl_base;
+} aria_params_t;
+
+static int
+aria_gpio_open( cable_t *cable )
+{
+	aria_params_t *p = cable->params;
+	off_t map_mask;
+
+	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 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 GPIO registers */
+	p->gpio_base = (uint32_t*)p->map_base;
+
+	/* Map the IOCTL registers */
+	p->ioctl_map_base = mmap(0, p->map_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+				 p->fd_dev_mem, IOCTL_BASE & ~map_mask);
+	if (p->ioctl_map_base == MAP_FAILED) {
+		printf( _("Error: unable to mmap the IOCTL registers\n") );
+		close (p->fd_dev_mem);
+		return -1;
+	}
+
+	p->ioctl_base = (uint32_t*)p->ioctl_map_base;
+
+	/* Set the GPIO pins as inputs/outputs as needed for the JTAG interface */
+
+	p->gpio_base[GPIO_DIR] = p->lastout = (( p->gpio_base[GPIO_DIR] & GPIO_BITMASK ) &
+						~GPIO_OUTPUT_MASK) | GPIO_INPUT_MASK;
+
+	p->gpio_base[GPIO_ODR] &= ~GPIO_INPUT_MASK;
+
+	printf("%s: DIR 0x%x\n", __func__, (unsigned int)p->gpio_base[GPIO_DIR]);
+	printf("%s: ODR 0x%x\n", __func__, (unsigned int)p->gpio_base[GPIO_ODR]);
+
+#if 1
+	printf("%s: GPIO_BITMASK 0x%x, GPIO_OUTPUT_MASK 0x%x\n",
+		 __func__, GPIO_BITMASK, GPIO_OUTPUT_MASK);
+#endif
+
+	p->ioctl_base[IOCTL_J1850_TX] = (PAD_IOCTL_J1850_TX_FUNCMUX << 7) | 3;
+	p->ioctl_base[IOCTL_PSC6_2] = 0x183;
+	p->ioctl_base[IOCTL_PSC6_3] = 0x183;
+
+	printf("%s: J1850_TX 0x%x\n", __func__, (unsigned int)p->ioctl_base[IOCTL_J1850_TX]);
+	printf("%s: PSC6_2 0x%x\n", __func__, (unsigned int)p->ioctl_base[IOCTL_PSC6_2]);
+	printf("%s: PSC6_3 0x%x\n", __func__, (unsigned int)p->ioctl_base[IOCTL_PSC6_3]);
+
+	return 0;
+}
+
+static int
+aria_gpio_close( cable_t *cable )
+{
+	aria_params_t *p = cable->params;
+
+	/* Unmap the GPIO/ IOCTL registers */
+
+	if (munmap(p->map_base, p->map_size) == -1) {
+		printf( _("Error: unable to munmap the GPIO registers\n"));
+	}
+
+	if (munmap(p->ioctl_map_base, p->map_size) == -1) {
+		printf( _("Error: unable to munmap the IOCTL registers\n"));
+	}
+
+	close(p->fd_dev_mem);
+	return 0;
+}
+
+static int
+aria_gpio_write( cable_t *cable, uint32_t data )
+{
+	aria_params_t *p = cable->params;
+
+/*
+	printf("%s: 0x%x\n", __func__,
+		(unsigned int)((p->lastout & GPIO_BITMASK) | data));
+*/
+	p->gpio_base[GPIO_OUT] = p->lastout = (p->lastout & GPIO_BITMASK) | data;
+
+	cable_wait(cable);
+
+	return 0;
+}
+
+static int
+aria_gpio_read( cable_t *cable )
+{
+	aria_params_t *p = cable->params;
+	int d;
+
+	d = p->gpio_base[GPIO_IN];
+
+/*
+	printf("%s: 0x%x\n", __func__, d);
+*/
+	return d;
+}
+
+static int
+aria_connect( char *params[], cable_t *cable )
+{
+	aria_params_t *cable_params;
+
+	if ( cmd_params( params ) != 1) {
+	  printf( _("Error: This cable type does not accept parameters!\n") );
+	  return 1;
+	}
+
+	printf( _("Initializing Aria GPIO JTAG Chain\n") );
+
+	cable_params = malloc( sizeof *cable_params );
+	if (!cable_params) {
+		printf( _("%s(%d) Out of memory\n"), __FILE__, __LINE__ );
+		free( cable );
+		return 4;
+	}
+
+	cable->params = cable_params;
+	cable->chain = NULL;
+	cable->delay = 1000;
+
+	return 0;
+}
+
+static void
+aria_disconnect( cable_t *cable )
+{
+	aria_gpio_close( cable );
+	chain_disconnect( cable->chain );
+}
+
+static void
+aria_cable_free( cable_t *cable )
+{
+	free( cable->params );
+	free( cable );
+}
+
+static int
+aria_init( cable_t *cable )
+{
+	aria_params_t *p = cable->params;
+
+	printf("%s:\n", __func__);
+
+	if (aria_gpio_open( cable ))
+		return -1;
+
+	p->signals = CS_TRST;
+
+	return 0;
+}
+
+static void
+aria_done( cable_t *cable )
+{
+	aria_gpio_close( cable );
+}
+
+static void
+aria_clock( cable_t *cable, int tms, int tdi, int n )
+{
+	int bit_mask;
+	int i;
+
+	tms = tms ? 1 : 0;
+	tdi = tdi ? 1 : 0;
+
+	bit_mask = (tms << TMS) | (tdi << TDI);
+
+	for (i = 0; i < n; i++) {
+		aria_gpio_write( cable, (0 << TCK) | bit_mask );
+		aria_gpio_write( cable, (1 << TCK) | bit_mask );
+		aria_gpio_write( cable, (0 << TCK) | bit_mask );
+	}
+}
+
+/*
+ * NOTE: This also lowers the TDI and TMS lines; is this intended?
+ */
+static int
+aria_get_tdo( cable_t *cable )
+{
+	aria_params_t *p = cable->params;
+
+	aria_gpio_write( cable, p->lastout & ~(0 << TCK) );
+
+	cable_wait( cable );
+
+	return (aria_gpio_read( cable ) >> TDO) & 1;
+}
+
+static int
+aria_current_signals( cable_t *cable )
+{
+	aria_params_t *p = cable->params;
+
+	int sigs = p->signals & ~(CS_TMS | CS_TDI | CS_TCK);
+
+	if (p->lastout & (1 << TCK)) sigs |= CS_TCK;
+	if (p->lastout & (1 << TDI)) sigs |= CS_TDI;
+	if (p->lastout & (1 << TMS)) sigs |= CS_TMS;
+
+	return sigs;
+}
+
+static int
+aria_set_signal( cable_t *cable, int mask, int val )
+{
+	int prev_sigs = aria_current_signals( cable );
+
+	mask &= (CS_TDI | CS_TCK | CS_TMS); // only these can be modified
+
+	if (mask != 0) {
+		int sigs = (prev_sigs & ~mask) | (val & mask);
+		int tms = (sigs & CS_TMS) ? (1 << TMS) : 0;
+		int tdi = (sigs & CS_TDI) ? (1 << TDI) : 0;
+		int tck = (sigs & CS_TCK) ? (1 << TCK) : 0;
+
+		aria_gpio_write( cable, tms | tdi | tck );
+	}
+
+	return prev_sigs;
+}
+
+static int
+aria_get_signal( cable_t *cable, pod_sigsel_t sig )
+{
+	return (aria_current_signals( cable ) & sig) ? 1 : 0;
+}
+
+static void
+aria_help( const char *cablename )
+{
+	printf( _(
+		"Usage: cable %s\n"
+		"\n"
+	), cablename );
+}
+
+cable_driver_t aria_cable_driver = {
+	"aria_gpio",
+	N_("Aria GPIO JTAG Chain"),
+	aria_connect,
+	aria_disconnect,
+	aria_cable_free,
+	aria_init,
+	aria_done,
+	generic_set_frequency,
+	aria_clock,
+	aria_get_tdo,
+	generic_transfer,
+	aria_set_signal,
+	aria_get_signal,
+	generic_flush_one_by_one,
+	aria_help
+};
-- 
1.6.0.6

