Jz47xx.c
From Qi-Hardware
/** $Id: jz47xx.c $* emQbit LTDA.* Carlos Iván Camargo Bareño* Based on 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 Carlos Camargo Bareño <carlos@emqbit.com>, 2010**/#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 <urjtag/cable.h>#include <urjtag/chain.h>#include "generic.h"#include "jz47xx_gpio.h"#include <cmd.h>#define JZ_GPIO_BASE 0x10010000typedef struct {
int fd_dev_mem;
size_t map_size;
JZ_PIO *pio_base;
int signals;
uint32_t lastout;
} jz47xx_params_t;
PJZ_PIO* pio;
static void
jz_gpio_as_output (int port, unsigned int o)
{pio[port]->PXFUNC = (1 << (o));
pio[port]->PXSELC = (1 << (o));
pio[port]->PXDIRS = (1 << (o));
}static void
jz_gpio_as_input (int port, unsigned int o)
{pio[port]->PXFUNC = (1 << (o));
pio[port]->PXSELC = (1 << (o));
pio[port]->PXDIRC = (1 << (o));
}static void
jz_gpio_set_pin (int port, unsigned int o)
{pio[port]->PXDATS = (1 << (o));
}static void
jz_gpio_clear_pin (int port, unsigned int o)
{pio[port]->PXDATC = (1 << (o));
}static void
jz_gpio_out (int port, unsigned int o, unsigned int val)
{if (val == 0)
pio[port]->PXDATC = (1 << (o));
elsepio[port]->PXDATS = (1 << (o));
}static unsigned int
jz_gpio_get_pin (int port, unsigned int o)
{return (pio[port]->PXPIN & (1 << o)) ? 1 : 0;
}static int
jz47xx_gpio_open( urj_cable_t *cable )
{unsigned char port;
pio = (PJZ_PIO*)malloc(sizeof(PJZ_PIO)*4);
jz47xx_params_t *p = cable->params;
/* Open the memory device so we can access the hardware registers */p->map_size = sizeof(PJZ_PIO)*4;
if ((p->fd_dev_mem = open ("/dev/mem", O_RDWR | O_SYNC)) == -1)
{cable_tfprintf (stderr, "Cannot open /dev/mem.\n");
return 0;
}/* Map the System Controller registers */p->pio_base = (JZ_PIO *) mmap (0, getpagesize (), PROT_READ | PROT_WRITE, MAP_SHARED, p->fd_dev_mem, JZ_GPIO_BASE);
if (p-> pio_base == (JZ_PIO *) - 1)
{fprintf (stderr, "Cannot mmap.\n");
return 0;
}for(port=0; port<4; port++)
pio[port] = (JZ_PIO *) ((unsigned int) p->pio_base + port * 0x100);
/* Set the GPIO pins as inputs/outputs as needed for the JTAG interface */jz_gpio_as_input (JZ_GPIO_PORT_D, TDO);
jz_gpio_as_output (JZ_GPIO_PORT_D, TCK);
jz_gpio_as_output (JZ_GPIO_PORT_C, TDI);
jz_gpio_as_output (JZ_GPIO_PORT_D, TMS);
jz_gpio_as_output (JZ_GPIO_PORT_C, 17);
jz_gpio_set_pin (JZ_GPIO_PORT_C, 17);
return 0;
}static int
jz47xx_gpio_close( urj_cable_t *cable )
{jz47xx_params_t *p = cable->params;
if (munmap(p->pio_base, p->map_size) == -1) {
printf( _("Error: unable to munmap the GPIO registers\n"));
}close(p->fd_dev_mem);
return 0;
}static int
jz47xx_connect( urj_cable_t *cable, const urj_param_t *params[] )
{jz47xx_params_t *cable_params;
if ( urj_param_num (params) > 0) {
printf( _("Error: This cable type does not acable_tccept parameters!\n") );
return 1;
}printf( _("Initializing SIE Built-in 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
jz47xx_disconnect( urj_cable_t *cable )
{jz47xx_gpio_close( cable );
urj_tap_chain_disconnect( cable->chain );
}static void
jz47xx_cable_free( urj_cable_t *cable )
{free( cable->params );
free( cable );
}static int
jz47xx_init( urj_cable_t *cable )
{if (jz47xx_gpio_open( cable ))
return -1;
return 0;
}static void
jz47xx_done( urj_cable_t *cable )
{jz47xx_gpio_close( cable );
}static void
jz47xx_clock( urj_cable_t *cable, int tms, int tdi, int n )
{int i;
tms = tms ? 1 : 0;
tdi = tdi ? 1 : 0;
jz_gpio_out (JZ_GPIO_PORT_C, TDI, tdi);
jz_gpio_out (JZ_GPIO_PORT_D, TMS, tms);
for (i = 0; i < n; i++) {
jz_gpio_out (JZ_GPIO_PORT_D, TCK, 0);
jz_gpio_out (JZ_GPIO_PORT_D, TCK, 1);
jz_gpio_out (JZ_GPIO_PORT_D, TCK, 0);
}}/*** NOTE: This also lowers the TDI and TMS lines; is this intended?*/static int
jz47xx_get_tdo( urj_cable_t *cable )
{jz_gpio_out (JZ_GPIO_PORT_D, TCK, 0);
return jz_gpio_get_pin (JZ_GPIO_PORT_D, TDO);
}static int
jz47xx_current_signals( urj_cable_t *cable )
{jz47xx_params_t *p = cable->params;
int sigs = p->signals & ~(URJ_POD_CS_TMS | URJ_POD_CS_TDI | URJ_POD_CS_TCK);
if (p->lastout & (1 << TCK)) sigs |= URJ_POD_CS_TCK;
if (p->lastout & (1 << TDI)) sigs |= URJ_POD_CS_TDI;
if (p->lastout & (1 << TMS)) sigs |= URJ_POD_CS_TMS;
return sigs;
}static int
jz47xx_set_signal( urj_cable_t *cable, int mask, int val )
{int prev_sigs = jz47xx_current_signals( cable );
mask &= (URJ_POD_CS_TDI | URJ_POD_CS_TCK | URJ_POD_CS_TMS); // only these can be modified
if (mask != 0)
{int sigs = (prev_sigs & ~mask) | (val & mask);
int tms = (sigs & URJ_POD_CS_TMS) ? (1 << TMS) : 0;
int tdi = (sigs & URJ_POD_CS_TDI) ? (1 << TDI) : 0;
int tck = (sigs & URJ_POD_CS_TCK) ? (1 << TCK) : 0;
jz_gpio_out (JZ_GPIO_PORT_C, TDI, tdi);
jz_gpio_out (JZ_GPIO_PORT_D, TMS, tms);
jz_gpio_out (JZ_GPIO_PORT_D, TCK, tck);
}return prev_sigs;
}static int
jz47xx_get_signal( urj_cable_t *cable,urj_pod_sigsel_t sig )
{return (jz47xx_current_signals( cable ) & sig) ? 1 : 0;
}static void
jz47xx_help( const char *cablename )
{printf( _(
"Usage: cable %s\n""\n"), cablename );
}const urj_cable_driver_t urj_tap_cable_jz47xx_driver = {
"jz47xx",
N_("SIE board GPIO JTAG controller"),
URJ_CABLE_DEVICE_OTHER,{ .other = jz47xx_connect, },
jz47xx_disconnect,jz47xx_cable_free,jz47xx_init,jz47xx_done,urj_tap_cable_generic_set_frequency,jz47xx_clock,jz47xx_get_tdo,urj_tap_cable_generic_transfer,jz47xx_set_signal,jz47xx_get_signal,urj_tap_cable_generic_flush_one_by_one,jz47xx_help
};