2008-02-25 17:48:04 +00:00
/***************************************************************************
2009-09-28 12:22:20 +00:00
* Copyright ( C ) 2009 by Ø yvind Harboe *
* Ø yvind Harboe < oyvind . harboe @ zylin . com > *
* *
* Copyright ( C ) 2009 by SoftPLC Corporation . http : //softplc.com *
* Dick Hollenbeck < dick @ softplc . com > *
* *
2009-02-03 05:59:17 +00:00
* Copyright ( C ) 2004 , 2006 by Dominic Rath *
* Dominic . Rath @ gmx . de *
* *
* Copyright ( C ) 2008 by Spencer Oliver *
* spen @ spen - soft . co . uk *
* *
* 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 . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This code uses information contained in the MPSSE specification which was
* found here :
* http : //www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf
* Hereafter this is called the " MPSSE Spec " .
2009-05-18 17:41:27 +00:00
*
* The datasheet for the ftdichip . com ' s FT2232D part is here :
* http : //www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf
2009-02-03 05:59:17 +00:00
*/
2008-02-25 17:48:04 +00:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
/* project specific includes */
2009-12-03 12:14:31 +00:00
# include <jtag/interface.h>
2009-12-03 12:14:30 +00:00
# include <jtag/commands.h>
2009-12-03 12:14:29 +00:00
# include <helper/time_support.h>
2008-02-25 17:48:04 +00:00
2009-05-11 08:26:42 +00:00
# if IS_CYGWIN == 1
# include <windows.h>
# endif
2009-05-18 17:41:27 +00:00
# include <assert.h>
2009-06-23 22:42:03 +00:00
# if (BUILD_FT2232_FTD2XX == 1 && BUILD_FT2232_LIBFTDI == 1)
2009-05-18 17:41:27 +00:00
# error "BUILD_FT2232_FTD2XX && BUILD_FT2232_LIBFTDI are mutually exclusive"
2009-06-23 22:38:12 +00:00
# elif (BUILD_FT2232_FTD2XX != 1 && BUILD_FT2232_LIBFTDI != 1)
2009-05-18 17:41:27 +00:00
# error "BUILD_FT2232_FTD2XX || BUILD_FT2232_LIBFTDI must be chosen"
# endif
2008-02-25 17:48:04 +00:00
/* FT2232 access library includes */
# if BUILD_FT2232_FTD2XX == 1
# include <ftd2xx.h>
# elif BUILD_FT2232_LIBFTDI == 1
# include <ftdi.h>
# endif
2009-05-18 17:41:27 +00:00
/* max TCK for the high speed devices 30000 kHz */
# define FTDI_2232H_4232H_MAX_TCK 30000
2009-08-18 14:41:58 +00:00
/* max TCK for the full speed devices 6000 kHz */
# define FTDI_2232C_MAX_TCK 6000
/* this speed value tells that RTCK is requested */
# define RTCK_SPEED -1
2009-05-18 17:41:27 +00:00
2009-10-30 18:54:07 +00:00
/*
* On my Athlon XP 1900 + EHCI host with FT2232H JTAG dongle I get read timeout
* errors with a retry count of 100. Increasing it solves the problem for me .
* - Dimitar
*
* FIXME There ' s likely an issue with the usb_read_timeout from libftdi .
* Fix that ( libusb ? kernel ? libftdi ? here ? ) and restore the retry count
* to something sane .
*/
# define LIBFTDI_READ_RETRY_COUNT 2000
2009-08-20 07:54:49 +00:00
# ifndef BUILD_FT2232_HIGHSPEED
# if BUILD_FT2232_FTD2XX == 1
enum { FT_DEVICE_2232H = 6 , FT_DEVICE_4232H } ;
# elif BUILD_FT2232_LIBFTDI == 1
enum { TYPE_2232H = 4 , TYPE_4232H = 5 } ;
# endif
# endif
2008-02-25 17:48:04 +00:00
2009-01-09 07:42:45 +00:00
/**
2009-06-03 04:37:51 +00:00
* Send out \ a num_cycles on the TCK line while the TAP ( s ) are in a
* stable state . Calling code must ensure that current state is stable ,
* that verification is not done in here .
*
* @ param num_cycles The number of clocks cycles to send .
* @ param cmd The command to send .
*
* @ returns ERROR_OK on success , or ERROR_JTAG_QUEUE_FAILED on failure .
2009-01-09 07:42:45 +00:00
*/
2009-11-13 14:15:31 +00:00
static int ft2232_stableclocks ( int num_cycles , struct jtag_command * cmd ) ;
2009-01-09 07:42:45 +00:00
2009-05-18 17:41:27 +00:00
static char * ft2232_device_desc_A = NULL ;
static char * ft2232_device_desc = NULL ;
static char * ft2232_serial = NULL ;
static char * ft2232_layout = NULL ;
2009-06-18 07:07:12 +00:00
static uint8_t ft2232_latency = 2 ;
2009-08-18 14:41:58 +00:00
static unsigned ft2232_max_tck = FTDI_2232C_MAX_TCK ;
2008-02-25 17:48:04 +00:00
2009-02-03 05:59:17 +00:00
# define MAX_USB_IDS 8
2008-02-25 17:48:04 +00:00
/* vid = pid = 0 marks the end of the list */
2009-06-18 07:07:59 +00:00
static uint16_t ft2232_vid [ MAX_USB_IDS + 1 ] = { 0x0403 , 0 } ;
static uint16_t ft2232_pid [ MAX_USB_IDS + 1 ] = { 0x6010 , 0 } ;
2008-02-25 17:48:04 +00:00
2009-11-13 13:17:18 +00:00
struct ft2232_layout {
2008-02-25 17:48:04 +00:00
char * name ;
2009-02-03 05:59:17 +00:00
int ( * init ) ( void ) ;
void ( * reset ) ( int trst , int srst ) ;
void ( * blink ) ( void ) ;
2009-11-13 13:17:18 +00:00
} ;
2008-02-25 17:48:04 +00:00
/* init procedures for supported layouts */
2009-06-04 01:17:27 +00:00
static int usbjtag_init ( void ) ;
static int jtagkey_init ( void ) ;
static int olimex_jtag_init ( void ) ;
static int flyswatter_init ( void ) ;
static int turtle_init ( void ) ;
static int comstick_init ( void ) ;
static int stm32stick_init ( void ) ;
static int axm0432_jtag_init ( void ) ;
static int sheevaplug_init ( void ) ;
static int icebear_jtag_init ( void ) ;
static int cortino_jtag_init ( void ) ;
2009-10-27 19:40:24 +00:00
static int signalyzer_h_init ( void ) ;
2009-11-05 05:20:44 +00:00
static int ktlink_init ( void ) ;
2008-02-25 17:48:04 +00:00
/* reset procedures for supported layouts */
2009-04-21 05:29:23 +00:00
static void usbjtag_reset ( int trst , int srst ) ;
static void jtagkey_reset ( int trst , int srst ) ;
static void olimex_jtag_reset ( int trst , int srst ) ;
static void flyswatter_reset ( int trst , int srst ) ;
static void turtle_reset ( int trst , int srst ) ;
static void comstick_reset ( int trst , int srst ) ;
static void stm32stick_reset ( int trst , int srst ) ;
static void axm0432_jtag_reset ( int trst , int srst ) ;
static void sheevaplug_reset ( int trst , int srst ) ;
2009-04-29 07:38:35 +00:00
static void icebear_jtag_reset ( int trst , int srst ) ;
2009-10-27 19:40:24 +00:00
static void signalyzer_h_reset ( int trst , int srst ) ;
2009-11-05 05:20:44 +00:00
static void ktlink_reset ( int trst , int srst ) ;
2008-12-11 19:03:17 +00:00
2008-02-25 17:48:04 +00:00
/* blink procedures for layouts that support a blinking led */
2009-04-21 05:29:23 +00:00
static void olimex_jtag_blink ( void ) ;
static void flyswatter_jtag_blink ( void ) ;
static void turtle_jtag_blink ( void ) ;
2009-10-27 19:40:24 +00:00
static void signalyzer_h_blink ( void ) ;
2009-11-05 05:20:44 +00:00
static void ktlink_blink ( void ) ;
2008-02-25 17:48:04 +00:00
2009-11-13 13:17:18 +00:00
static const struct ft2232_layout ft2232_layouts [ ] =
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
{ " usbjtag " , usbjtag_init , usbjtag_reset , NULL } ,
{ " jtagkey " , jtagkey_init , jtagkey_reset , NULL } ,
{ " jtagkey_prototype_v1 " , jtagkey_init , jtagkey_reset , NULL } ,
{ " oocdlink " , jtagkey_init , jtagkey_reset , NULL } ,
{ " signalyzer " , usbjtag_init , usbjtag_reset , NULL } ,
{ " evb_lm3s811 " , usbjtag_init , usbjtag_reset , NULL } ,
2009-06-30 09:09:30 +00:00
{ " luminary_icdi " , usbjtag_init , usbjtag_reset , NULL } ,
2009-02-03 05:59:17 +00:00
{ " olimex-jtag " , olimex_jtag_init , olimex_jtag_reset , olimex_jtag_blink } ,
2009-03-01 21:07:44 +00:00
{ " flyswatter " , flyswatter_init , flyswatter_reset , flyswatter_jtag_blink } ,
2009-02-03 05:59:17 +00:00
{ " turtelizer2 " , turtle_init , turtle_reset , turtle_jtag_blink } ,
{ " comstick " , comstick_init , comstick_reset , NULL } ,
{ " stm32stick " , stm32stick_init , stm32stick_reset , NULL } ,
{ " axm0432_jtag " , axm0432_jtag_init , axm0432_jtag_reset , NULL } ,
2009-05-27 11:58:19 +00:00
{ " sheevaplug " , sheevaplug_init , sheevaplug_reset , NULL } ,
2009-04-29 07:38:35 +00:00
{ " icebear " , icebear_jtag_init , icebear_jtag_reset , NULL } ,
2009-05-27 11:58:19 +00:00
{ " cortino " , cortino_jtag_init , comstick_reset , NULL } ,
2009-10-27 19:40:24 +00:00
{ " signalyzer-h " , signalyzer_h_init , signalyzer_h_reset , signalyzer_h_blink } ,
2009-11-05 05:20:44 +00:00
{ " ktlink " , ktlink_init , ktlink_reset , ktlink_blink } ,
2009-04-20 06:40:45 +00:00
{ NULL , NULL , NULL , NULL } ,
2008-02-25 17:48:04 +00:00
} ;
2009-06-18 07:07:12 +00:00
static uint8_t nTRST , nTRSTnOE , nSRST , nSRSTnOE ;
2008-02-25 17:48:04 +00:00
2009-11-13 13:17:18 +00:00
static const struct ft2232_layout * layout ;
2009-06-18 07:07:12 +00:00
static uint8_t low_output = 0x0 ;
static uint8_t low_direction = 0x0 ;
static uint8_t high_output = 0x0 ;
static uint8_t high_direction = 0x0 ;
2008-02-25 17:48:04 +00:00
# if BUILD_FT2232_FTD2XX == 1
2009-06-04 01:17:27 +00:00
static FT_HANDLE ftdih = NULL ;
static FT_DEVICE ftdi_device = 0 ;
2008-02-25 17:48:04 +00:00
# elif BUILD_FT2232_LIBFTDI == 1
static struct ftdi_context ftdic ;
2009-08-18 14:41:58 +00:00
static enum ftdi_chip_type ftdi_device ;
2008-02-25 17:48:04 +00:00
# endif
2009-11-13 14:15:31 +00:00
static struct jtag_command * first_unsent ; /* next command that has to be sent */
2009-02-03 05:59:17 +00:00
static int require_send ;
2009-01-09 07:42:45 +00:00
2009-06-23 22:44:17 +00:00
/* http://urjtag.wiki.sourceforge.net/Cable + FT2232 says:
2009-05-18 17:41:27 +00:00
" There is a significant difference between libftdi and libftd2xx. The latter
one allows to schedule up to 64 * 64 bytes of result data while libftdi fails
with more than 4 * 64. As a consequence , the FT2232 driver is forced to
perform around 16 x more USB transactions for long command streams with TDO
capture when running with libftdi . "
No idea how we get
# define FT2232_BUFFER_SIZE 131072
a comment would have been nice .
*/
# define FT2232_BUFFER_SIZE 131072
2009-06-18 07:07:12 +00:00
static uint8_t * ft2232_buffer = NULL ;
2009-02-03 05:59:17 +00:00
static int ft2232_buffer_size = 0 ;
static int ft2232_read_pointer = 0 ;
static int ft2232_expect_read = 0 ;
2009-01-09 07:42:45 +00:00
2009-05-18 17:41:27 +00:00
/**
* Function buffer_write
* writes a byte into the byte buffer , " ft2232_buffer " , which must be sent later .
* @ param val is the byte to send .
*/
2009-06-18 07:07:12 +00:00
static inline void buffer_write ( uint8_t val )
2009-05-18 17:41:27 +00:00
{
2009-06-04 01:17:27 +00:00
assert ( ft2232_buffer ) ;
assert ( ( unsigned ) ft2232_buffer_size < ( unsigned ) FT2232_BUFFER_SIZE ) ;
2009-05-18 17:41:27 +00:00
ft2232_buffer [ ft2232_buffer_size + + ] = val ;
}
/**
* Function buffer_read
* returns a byte from the byte buffer .
*/
2009-06-18 07:07:12 +00:00
static inline uint8_t buffer_read ( void )
2009-05-18 17:41:27 +00:00
{
2009-06-04 01:17:27 +00:00
assert ( ft2232_buffer ) ;
assert ( ft2232_read_pointer < ft2232_buffer_size ) ;
2009-05-18 17:41:27 +00:00
return ft2232_buffer [ ft2232_read_pointer + + ] ;
}
/**
2009-06-03 04:37:51 +00:00
* Clocks out \ a bit_count bits on the TMS line , starting with the least
2009-05-18 17:41:27 +00:00
* significant bit of tms_bits and progressing to more significant bits .
* Rigorous state transition logging is done here via tap_set_state ( ) .
*
2009-06-03 04:37:51 +00:00
* @ param mpsse_cmd One of the MPSSE TMS oriented commands such as
2009-06-04 01:17:27 +00:00
* 0x4b or 0x6b . See the MPSSE spec referenced above for their
* functionality . The MPSSE command " Clock Data to TMS/CS Pin (no Read) "
* is often used for this , 0x4b .
2009-06-03 04:37:51 +00:00
*
* @ param tms_bits Holds the sequence of bits to send .
* @ param tms_count Tells how many bits in the sequence .
* @ param tdi_bit A single bit to pass on to TDI before the first TCK
2009-06-04 01:17:27 +00:00
* cycle and held static for the duration of TMS clocking .
2009-05-18 17:41:27 +00:00
*
2009-06-03 04:37:51 +00:00
* See the MPSSE spec referenced above .
2009-05-18 17:41:27 +00:00
*/
2009-06-18 07:07:12 +00:00
static void clock_tms ( uint8_t mpsse_cmd , int tms_bits , int tms_count , bool tdi_bit )
2009-05-18 17:41:27 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t tms_byte ;
2009-05-18 17:41:27 +00:00
int i ;
int tms_ndx ; /* bit index into tms_byte */
2009-06-04 01:17:27 +00:00
assert ( tms_count > 0 ) ;
2009-05-18 17:41:27 +00:00
2009-10-07 17:30:51 +00:00
DEBUG_JTAG_IO ( " mpsse cmd=%02x, tms_bits = 0x%08x, bit_count=%d " ,
mpsse_cmd , tms_bits , tms_count ) ;
2009-05-18 17:41:27 +00:00
for ( tms_byte = tms_ndx = i = 0 ; i < tms_count ; + + i , tms_bits > > = 1 )
{
bool bit = tms_bits & 1 ;
2009-06-04 01:17:27 +00:00
if ( bit )
2009-06-23 22:41:13 +00:00
tms_byte | = ( 1 < < tms_ndx ) ;
2009-05-18 17:41:27 +00:00
/* always do state transitions in public view */
2009-06-04 01:17:27 +00:00
tap_set_state ( tap_state_transition ( tap_get_state ( ) , bit ) ) ;
2009-05-18 17:41:27 +00:00
2009-06-04 01:17:27 +00:00
/* we wrote a bit to tms_byte just above, increment bit index. if bit was zero
2009-05-18 17:41:27 +00:00
also increment .
*/
+ + tms_ndx ;
2009-06-23 22:42:03 +00:00
if ( tms_ndx = = 7 | | i = = tms_count - 1 )
2009-05-18 17:41:27 +00:00
{
2009-06-04 01:17:27 +00:00
buffer_write ( mpsse_cmd ) ;
buffer_write ( tms_ndx - 1 ) ;
2009-05-18 17:41:27 +00:00
2009-06-04 01:17:27 +00:00
/* Bit 7 of the byte is passed on to TDI/DO before the first TCK/SK of
2009-05-18 17:41:27 +00:00
TMS / CS and is held static for the duration of TMS / CS clocking .
*/
2009-06-04 01:17:27 +00:00
buffer_write ( tms_byte | ( tdi_bit < < 7 ) ) ;
2009-05-18 17:41:27 +00:00
}
}
}
/**
* Function get_tms_buffer_requirements
* returns what clock_tms ( ) will consume if called with
* same \ a bit_count .
*/
2009-06-04 01:17:27 +00:00
static inline int get_tms_buffer_requirements ( int bit_count )
2009-05-18 17:41:27 +00:00
{
return ( ( bit_count + 6 ) / 7 ) * 3 ;
}
/**
* Function move_to_state
* moves the TAP controller from the current state to a
* \ a goal_state through a path given by tap_get_tms_path ( ) . State transition
* logging is performed by delegation to clock_tms ( ) .
*
* @ param goal_state is the destination state for the move .
*/
2009-06-04 01:17:27 +00:00
static void move_to_state ( tap_state_t goal_state )
2009-05-18 17:41:27 +00:00
{
2009-06-04 01:17:27 +00:00
tap_state_t start_state = tap_get_state ( ) ;
2009-05-18 17:41:27 +00:00
2009-06-04 01:17:27 +00:00
/* goal_state is 1/2 of a tuple/pair of states which allow convenient
2009-05-18 17:41:27 +00:00
lookup of the required TMS pattern to move to this state from the
start state .
*/
/* do the 2 lookups */
int tms_bits = tap_get_tms_path ( start_state , goal_state ) ;
int tms_count = tap_get_tms_path_len ( start_state , goal_state ) ;
2009-06-04 01:17:27 +00:00
DEBUG_JTAG_IO ( " start=%s goal=%s " , tap_state_name ( start_state ) , tap_state_name ( goal_state ) ) ;
2009-05-18 17:41:27 +00:00
2009-06-04 01:17:27 +00:00
clock_tms ( 0x4b , tms_bits , tms_count , 0 ) ;
2009-05-18 17:41:27 +00:00
}
2009-06-18 07:11:11 +00:00
static int ft2232_write ( uint8_t * buf , int size , uint32_t * bytes_written )
2008-02-25 17:48:04 +00:00
{
# if BUILD_FT2232_FTD2XX == 1
FT_STATUS status ;
2009-08-18 14:41:58 +00:00
DWORD dw_bytes_written ;
2009-06-04 01:17:27 +00:00
if ( ( status = FT_Write ( ftdih , buf , size , & dw_bytes_written ) ) ! = FT_OK )
2008-02-25 17:48:04 +00:00
{
* bytes_written = dw_bytes_written ;
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " FT_Write returned: %lu " , status ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_DEVICE_ERROR ;
}
else
{
* bytes_written = dw_bytes_written ;
2008-12-13 06:25:50 +00:00
return ERROR_OK ;
2008-02-25 17:48:04 +00:00
}
# elif BUILD_FT2232_LIBFTDI == 1
int retval ;
2009-06-04 01:17:27 +00:00
if ( ( retval = ftdi_write_data ( & ftdic , buf , size ) ) < 0 )
2008-02-25 17:48:04 +00:00
{
* bytes_written = 0 ;
2009-06-04 01:17:27 +00:00
LOG_ERROR ( " ftdi_write_data: %s " , ftdi_get_error_string ( & ftdic ) ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_DEVICE_ERROR ;
}
else
{
* bytes_written = retval ;
2008-12-13 06:25:50 +00:00
return ERROR_OK ;
2008-02-25 17:48:04 +00:00
}
# endif
}
2009-06-18 07:11:11 +00:00
static int ft2232_read ( uint8_t * buf , uint32_t size , uint32_t * bytes_read )
2008-02-25 17:48:04 +00:00
{
# if BUILD_FT2232_FTD2XX == 1
2009-08-18 14:41:58 +00:00
DWORD dw_bytes_read ;
2008-02-25 17:48:04 +00:00
FT_STATUS status ;
2009-08-18 14:41:58 +00:00
int timeout = 5 ;
2008-02-25 17:48:04 +00:00
* bytes_read = 0 ;
2009-06-04 01:17:27 +00:00
while ( ( * bytes_read < size ) & & timeout - - )
2008-02-25 17:48:04 +00:00
{
2009-06-04 01:17:27 +00:00
if ( ( status = FT_Read ( ftdih , buf + * bytes_read , size -
* bytes_read , & dw_bytes_read ) ) ! = FT_OK )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
* bytes_read = 0 ;
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " FT_Read returned: %lu " , status ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_DEVICE_ERROR ;
}
2008-12-13 06:25:50 +00:00
* bytes_read + = dw_bytes_read ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
# elif BUILD_FT2232_LIBFTDI == 1
int retval ;
2009-10-30 18:54:07 +00:00
int timeout = LIBFTDI_READ_RETRY_COUNT ;
2008-02-25 17:48:04 +00:00
* bytes_read = 0 ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
while ( ( * bytes_read < size ) & & timeout - - )
2008-02-25 17:48:04 +00:00
{
2009-06-04 01:17:27 +00:00
if ( ( retval = ftdi_read_data ( & ftdic , buf + * bytes_read , size - * bytes_read ) ) < 0 )
2008-02-25 17:48:04 +00:00
{
* bytes_read = 0 ;
2009-06-04 01:17:27 +00:00
LOG_ERROR ( " ftdi_read_data: %s " , ftdi_get_error_string ( & ftdic ) ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_DEVICE_ERROR ;
}
* bytes_read + = retval ;
}
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
# endif
if ( * bytes_read < size )
{
2009-10-30 18:54:07 +00:00
LOG_ERROR ( " couldn't read enough bytes from "
" FT2232 device (%i < %i) " ,
( unsigned ) * bytes_read ,
( unsigned ) size ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_DEVICE_ERROR ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-06-02 07:51:16 +00:00
static bool ft2232_device_is_highspeed ( void )
{
2009-08-20 07:54:49 +00:00
# if BUILD_FT2232_FTD2XX == 1
2009-06-02 07:51:16 +00:00
return ( ftdi_device = = FT_DEVICE_2232H ) | | ( ftdi_device = = FT_DEVICE_4232H ) ;
2009-08-20 07:54:49 +00:00
# elif BUILD_FT2232_LIBFTDI == 1
2009-08-18 14:41:58 +00:00
return ( ftdi_device = = TYPE_2232H | | ftdi_device = = TYPE_4232H ) ;
# endif
2009-06-02 07:51:16 +00:00
}
2009-08-18 14:41:58 +00:00
/*
* Commands that only apply to the FT2232H and FT4232H devices .
* See chapter 6 in http : //www.ftdichip.com/Documents/AppNotes/
* AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes . pdf
*/
2009-06-02 07:51:16 +00:00
2009-08-18 14:41:58 +00:00
static int ft2232h_ft4232h_adaptive_clocking ( bool enable )
{
uint8_t buf = enable ? 0x96 : 0x97 ;
2009-06-02 07:51:16 +00:00
LOG_DEBUG ( " %2.2x " , buf ) ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2009-06-02 07:51:16 +00:00
int retval = ft2232_write ( & buf , 1 , & bytes_written ) ;
2009-08-18 14:41:58 +00:00
if ( ( ERROR_OK ! = retval ) | | ( bytes_written ! = 1 ) )
2009-06-02 07:51:16 +00:00
{
2009-08-18 14:41:58 +00:00
LOG_ERROR ( " couldn't write command to %s adaptive clocking "
, enable ? " enable " : " disable " ) ;
2009-06-02 07:51:16 +00:00
return retval ;
}
return ERROR_OK ;
}
2009-08-18 14:41:58 +00:00
/**
* Enable / disable the clk divide by 5 of the 60 MHz master clock .
* This result in a JTAG clock speed range of 91.553 Hz - 6 MHz
* respective 457.763 Hz - 30 MHz .
*/
static int ft2232h_ft4232h_clk_divide_by_5 ( bool enable )
2009-06-02 07:51:16 +00:00
{
2009-08-18 14:41:58 +00:00
uint32_t bytes_written ;
uint8_t buf = enable ? 0x8b : 0x8a ;
int retval = ft2232_write ( & buf , 1 , & bytes_written ) ;
if ( ( ERROR_OK ! = retval ) | | ( bytes_written ! = 1 ) )
{
LOG_ERROR ( " couldn't write command to %s clk divide by 5 "
, enable ? " enable " : " disable " ) ;
return ERROR_JTAG_INIT_FAILED ;
}
ft2232_max_tck = enable ? FTDI_2232C_MAX_TCK : FTDI_2232H_4232H_MAX_TCK ;
LOG_INFO ( " max TCK change to: %u kHz " , ft2232_max_tck ) ;
return ERROR_OK ;
2009-06-02 07:51:16 +00:00
}
2009-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_speed ( int speed )
2008-02-25 17:48:04 +00:00
{
2009-08-18 14:41:58 +00:00
uint8_t buf [ 3 ] ;
2008-02-25 17:48:04 +00:00
int retval ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2008-02-25 17:48:04 +00:00
2009-08-18 14:41:58 +00:00
retval = ERROR_OK ;
bool enable_adaptive_clocking = ( RTCK_SPEED = = speed ) ;
if ( ft2232_device_is_highspeed ( ) )
retval = ft2232h_ft4232h_adaptive_clocking ( enable_adaptive_clocking ) ;
else if ( enable_adaptive_clocking )
{
LOG_ERROR ( " ft2232 device %lu does not support RTCK "
, ( long unsigned int ) ftdi_device ) ;
return ERROR_FAIL ;
}
if ( ( enable_adaptive_clocking ) | | ( ERROR_OK ! = retval ) )
return retval ;
2009-06-02 07:51:16 +00:00
2009-08-18 14:41:58 +00:00
buf [ 0 ] = 0x86 ; /* command "set divisor" */
buf [ 1 ] = speed & 0xff ; /* valueL (0 = 6MHz, 1 = 3MHz, 2 = 2.0MHz, ...*/
buf [ 2 ] = ( speed > > 8 ) & 0xff ; /* valueH */
2008-12-13 06:25:50 +00:00
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2009-06-04 01:17:27 +00:00
if ( ( ( retval = ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " couldn't set FT2232 TCK speed " ) ;
2008-02-25 17:48:04 +00:00
return retval ;
}
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int ft2232_speed_div ( int speed , int * khz )
2008-05-10 12:11:02 +00:00
{
2008-12-13 06:25:50 +00:00
/* Take a look in the FT2232 manual,
2008-05-12 09:01:38 +00:00
* AN2232C - 01 Command Processor for
* MPSSE and MCU Host Bus . Chapter 3.8 */
2008-12-13 06:25:50 +00:00
2009-08-18 14:41:58 +00:00
* khz = ( RTCK_SPEED = = speed ) ? 0 : ft2232_max_tck / ( 1 + speed ) ;
2008-12-13 06:25:50 +00:00
2008-05-10 12:11:02 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int ft2232_khz ( int khz , int * jtag_speed )
2008-05-10 12:11:02 +00:00
{
2009-06-23 22:42:03 +00:00
if ( khz = = 0 )
2008-08-25 16:16:00 +00:00
{
2009-08-18 14:41:58 +00:00
if ( ft2232_device_is_highspeed ( ) )
{
* jtag_speed = RTCK_SPEED ;
return ERROR_OK ;
}
else
{
LOG_DEBUG ( " RCLK not supported " ) ;
return ERROR_FAIL ;
}
2008-08-25 16:16:00 +00:00
}
2009-02-03 05:59:17 +00:00
2008-12-13 06:25:50 +00:00
/* Take a look in the FT2232 manual,
2008-05-12 09:01:38 +00:00
* AN2232C - 01 Command Processor for
* MPSSE and MCU Host Bus . Chapter 3.8
2008-12-13 06:25:50 +00:00
*
2008-05-12 09:01:38 +00:00
* We will calc here with a multiplier
* of 10 for better rounding later . */
2008-12-13 06:25:50 +00:00
2009-05-18 17:41:27 +00:00
/* Calc speed, (ft2232_max_tck / khz) - 1 */
2008-05-12 09:01:38 +00:00
/* Use 65000 for better rounding */
2009-05-18 17:41:27 +00:00
* jtag_speed = ( ( ft2232_max_tck * 10 ) / khz ) - 10 ;
2008-12-13 06:25:50 +00:00
2008-05-12 09:01:38 +00:00
/* Add 0.9 for rounding */
* jtag_speed + = 9 ;
2008-12-13 06:25:50 +00:00
2008-05-12 09:01:38 +00:00
/* Calc real speed */
* jtag_speed = * jtag_speed / 10 ;
2008-12-13 06:25:50 +00:00
2008-05-12 09:01:38 +00:00
/* Check if speed is greater than 0 */
if ( * jtag_speed < 0 )
{
* jtag_speed = 0 ;
}
2008-12-13 06:25:50 +00:00
2008-05-26 17:59:26 +00:00
/* Check max value */
if ( * jtag_speed > 0xFFFF )
{
* jtag_speed = 0xFFFF ;
}
2008-12-13 06:25:50 +00:00
2008-05-10 12:11:02 +00:00
return ERROR_OK ;
}
2009-06-04 01:16:43 +00:00
static void ft2232_end_state ( tap_state_t state )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
if ( tap_is_state_stable ( state ) )
tap_set_end_state ( state ) ;
2008-02-25 17:48:04 +00:00
else
{
2009-05-18 17:41:27 +00:00
LOG_ERROR ( " BUG: %s is not a stable end state " , tap_state_name ( state ) ) ;
2008-02-25 17:48:04 +00:00
exit ( - 1 ) ;
}
}
2009-06-18 07:07:12 +00:00
static void ft2232_read_scan ( enum scan_type type , uint8_t * buffer , int scan_size )
2008-02-25 17:48:04 +00:00
{
2009-01-09 07:42:45 +00:00
int num_bytes = ( scan_size + 7 ) / 8 ;
2008-02-25 17:48:04 +00:00
int bits_left = scan_size ;
2009-02-03 05:59:17 +00:00
int cur_byte = 0 ;
2008-02-25 17:48:04 +00:00
2009-02-03 05:59:17 +00:00
while ( num_bytes - - > 1 )
2008-02-25 17:48:04 +00:00
{
2009-05-18 17:41:27 +00:00
buffer [ cur_byte + + ] = buffer_read ( ) ;
2008-02-25 17:48:04 +00:00
bits_left - = 8 ;
}
buffer [ cur_byte ] = 0x0 ;
2009-06-04 01:17:27 +00:00
/* There is one more partial byte left from the clock data in/out instructions */
2008-02-25 17:48:04 +00:00
if ( bits_left > 1 )
{
2009-05-18 17:41:27 +00:00
buffer [ cur_byte ] = buffer_read ( ) > > 1 ;
2008-02-25 17:48:04 +00:00
}
2009-05-18 17:41:27 +00:00
/* This shift depends on the length of the clock data to tms instruction, insterted at end of the scan, now fixed to a two step transition in ft2232_add_scan */
2009-06-04 01:17:27 +00:00
buffer [ cur_byte ] = ( buffer [ cur_byte ] | ( ( ( buffer_read ( ) ) < < 1 ) & 0x80 ) ) > > ( 8 - bits_left ) ;
2008-02-25 17:48:04 +00:00
}
2009-04-21 05:29:23 +00:00
static void ft2232_debug_dump_buffer ( void )
2008-02-25 17:48:04 +00:00
{
2009-08-18 14:41:58 +00:00
int i ;
char line [ 256 ] ;
2009-02-03 05:59:17 +00:00
char * line_p = line ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
for ( i = 0 ; i < ft2232_buffer_size ; i + + )
{
line_p + = snprintf ( line_p , 256 - ( line_p - line ) , " %2.2x " , ft2232_buffer [ i ] ) ;
if ( i % 16 = = 15 )
{
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %s " , line ) ;
2008-02-25 17:48:04 +00:00
line_p = line ;
}
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( line_p ! = line )
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %s " , line ) ;
2008-02-25 17:48:04 +00:00
}
2009-11-13 14:15:31 +00:00
static int ft2232_send_and_recv ( struct jtag_command * first , struct jtag_command * last )
2008-02-25 17:48:04 +00:00
{
2009-11-13 14:15:31 +00:00
struct jtag_command * cmd ;
2009-08-18 14:41:58 +00:00
uint8_t * buffer ;
int scan_size ;
2009-02-03 05:59:17 +00:00
enum scan_type type ;
2009-08-18 14:41:58 +00:00
int retval ;
uint32_t bytes_written = 0 ;
uint32_t bytes_read = 0 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
# ifdef _DEBUG_USB_IO_
2009-02-03 05:59:17 +00:00
struct timeval start , inter , inter2 , end ;
struct timeval d_inter , d_inter2 , d_end ;
2008-02-25 17:48:04 +00:00
# endif
# ifdef _DEBUG_USB_COMMS_
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " write buffer (size %i): " , ft2232_buffer_size ) ;
2008-02-25 17:48:04 +00:00
ft2232_debug_dump_buffer ( ) ;
# endif
# ifdef _DEBUG_USB_IO_
2008-12-13 06:25:50 +00:00
gettimeofday ( & start , NULL ) ;
2008-02-25 17:48:04 +00:00
# endif
2009-06-04 01:17:27 +00:00
if ( ( retval = ft2232_write ( ft2232_buffer , ft2232_buffer_size , & bytes_written ) ) ! = ERROR_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " couldn't write MPSSE commands to FT2232 " ) ;
2008-10-15 11:44:36 +00:00
return retval ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
# ifdef _DEBUG_USB_IO_
2008-12-13 06:25:50 +00:00
gettimeofday ( & inter , NULL ) ;
2008-02-25 17:48:04 +00:00
# endif
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( ft2232_expect_read )
{
2009-10-30 18:54:07 +00:00
/* FIXME this "timeout" is never changed ... */
int timeout = LIBFTDI_READ_RETRY_COUNT ;
2008-02-25 17:48:04 +00:00
ft2232_buffer_size = 0 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
# ifdef _DEBUG_USB_IO_
2008-12-13 06:25:50 +00:00
gettimeofday ( & inter2 , NULL ) ;
2008-02-25 17:48:04 +00:00
# endif
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( retval = ft2232_read ( ft2232_buffer , ft2232_expect_read , & bytes_read ) ) ! = ERROR_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " couldn't read from FT2232 " ) ;
2008-10-15 11:44:36 +00:00
return retval ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
# ifdef _DEBUG_USB_IO_
2008-12-13 06:25:50 +00:00
gettimeofday ( & end , NULL ) ;
2008-02-25 17:48:04 +00:00
timeval_subtract ( & d_inter , & inter , & start ) ;
timeval_subtract ( & d_inter2 , & inter2 , & start ) ;
timeval_subtract ( & d_end , & end , & start ) ;
2009-04-21 12:10:29 +00:00
LOG_INFO ( " inter: %u.%06u, inter2: %u.%06u end: %u.%06u " ,
( unsigned ) d_inter . tv_sec , ( unsigned ) d_inter . tv_usec ,
( unsigned ) d_inter2 . tv_sec , ( unsigned ) d_inter2 . tv_usec ,
( unsigned ) d_end . tv_sec , ( unsigned ) d_end . tv_usec ) ;
2008-02-25 17:48:04 +00:00
# endif
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
ft2232_buffer_size = bytes_read ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( ft2232_expect_read ! = ft2232_buffer_size )
{
2009-10-30 18:54:07 +00:00
LOG_ERROR ( " ft2232_expect_read (%i) != "
" ft2232_buffer_size (%i) "
" (%i retries) " ,
ft2232_expect_read ,
2009-02-03 05:59:17 +00:00
ft2232_buffer_size ,
2009-10-30 18:54:07 +00:00
LIBFTDI_READ_RETRY_COUNT - timeout ) ;
2008-12-13 06:25:50 +00:00
ft2232_debug_dump_buffer ( ) ;
2008-02-25 17:48:04 +00:00
exit ( - 1 ) ;
}
# ifdef _DEBUG_USB_COMMS_
2009-10-30 18:54:07 +00:00
LOG_DEBUG ( " read buffer (%i retries): %i bytes " ,
LIBFTDI_READ_RETRY_COUNT - timeout ,
ft2232_buffer_size ) ;
2008-02-25 17:48:04 +00:00
ft2232_debug_dump_buffer ( ) ;
# endif
}
2009-02-03 05:59:17 +00:00
ft2232_expect_read = 0 ;
2008-02-25 17:48:04 +00:00
ft2232_read_pointer = 0 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* return ERROR_OK, unless a jtag_read_buffer returns a failed check
* that wasn ' t handled by a caller - provided error handler
2008-12-13 06:25:50 +00:00
*/
2008-02-25 17:48:04 +00:00
retval = ERROR_OK ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
cmd = first ;
while ( cmd ! = last )
{
switch ( cmd - > type )
{
2009-02-03 05:59:17 +00:00
case JTAG_SCAN :
type = jtag_scan_type ( cmd - > cmd . scan ) ;
if ( type ! = SCAN_OUT )
{
scan_size = jtag_scan_size ( cmd - > cmd . scan ) ;
2009-11-16 10:53:57 +00:00
buffer = calloc ( DIV_ROUND_UP ( scan_size , 8 ) , 1 ) ;
2009-02-03 05:59:17 +00:00
ft2232_read_scan ( type , buffer , scan_size ) ;
if ( jtag_read_buffer ( buffer , cmd - > cmd . scan ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
free ( buffer ) ;
}
break ;
default :
break ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
cmd = cmd - > next ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
ft2232_buffer_size = 0 ;
return retval ;
}
2009-05-18 17:41:27 +00:00
/**
* Function ft2232_add_pathmove
* moves the TAP controller from the current state to a new state through the
* given path , where path is an array of tap_state_t ' s .
*
* @ param path is an array of tap_stat_t which gives the states to traverse through
* ending with the last state at path [ num_states - 1 ]
* @ param num_states is the count of state steps to move through
*/
2009-06-04 01:17:27 +00:00
static void ft2232_add_pathmove ( tap_state_t * path , int num_states )
2008-02-25 17:48:04 +00:00
{
2009-09-17 12:25:53 +00:00
int state_count = 0 ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
assert ( ( unsigned ) num_states < = 32u ) ; /* tms_bits only holds 32 bits */
2008-02-27 06:59:35 +00:00
2009-10-07 17:30:51 +00:00
DEBUG_JTAG_IO ( " - " ) ;
2009-05-18 17:41:27 +00:00
/* this loop verifies that the path is legal and logs each state in the path */
2009-09-17 12:25:53 +00:00
while ( num_states )
2009-05-18 17:41:27 +00:00
{
2009-09-19 06:54:01 +00:00
unsigned char tms_byte = 0 ; /* zero this on each MPSSE batch */
int bit_count = 0 ;
int num_states_batch = num_states > 7 ? 7 : num_states ;
2009-09-17 12:25:53 +00:00
/* command "Clock Data to TMS/CS Pin (no Read)" */
buffer_write ( 0x4b ) ;
2009-05-18 17:41:27 +00:00
2009-09-17 12:25:53 +00:00
/* number of states remaining */
buffer_write ( num_states_batch - 1 ) ;
2009-09-19 06:54:01 +00:00
while ( num_states_batch - - ) {
/* either TMS=0 or TMS=1 must work ... */
if ( tap_state_transition ( tap_get_state ( ) , false )
= = path [ state_count ] )
2009-09-17 12:25:53 +00:00
buf_set_u32 ( & tms_byte , bit_count + + , 1 , 0x0 ) ;
2009-09-19 06:54:01 +00:00
else if ( tap_state_transition ( tap_get_state ( ) , true )
= = path [ state_count ] )
2009-09-17 12:25:53 +00:00
buf_set_u32 ( & tms_byte , bit_count + + , 1 , 0x1 ) ;
2009-09-19 06:54:01 +00:00
/* ... or else the caller goofed BADLY */
else {
LOG_ERROR ( " BUG: %s -> %s isn't a valid "
" TAP state transition " ,
tap_state_name ( tap_get_state ( ) ) ,
tap_state_name ( path [ state_count ] ) ) ;
2009-09-17 12:25:53 +00:00
exit ( - 1 ) ;
}
2009-09-19 06:54:01 +00:00
tap_set_state ( path [ state_count ] ) ;
2009-09-17 12:25:53 +00:00
state_count + + ;
num_states - - ;
}
2009-05-18 17:41:27 +00:00
2009-09-17 12:25:53 +00:00
buffer_write ( tms_byte ) ;
2009-09-19 06:54:01 +00:00
}
2009-02-03 05:59:17 +00:00
tap_set_end_state ( tap_get_state ( ) ) ;
2008-02-25 17:48:04 +00:00
}
2009-06-18 07:07:12 +00:00
static void ft2232_add_scan ( bool ir_scan , enum scan_type type , uint8_t * buffer , int scan_size )
2008-02-25 17:48:04 +00:00
{
int num_bytes = ( scan_size + 7 ) / 8 ;
int bits_left = scan_size ;
2009-02-03 05:59:17 +00:00
int cur_byte = 0 ;
2008-02-25 17:48:04 +00:00
int last_bit ;
2009-06-04 01:17:27 +00:00
if ( ! ir_scan )
2008-02-25 17:48:04 +00:00
{
2009-05-18 17:41:27 +00:00
if ( tap_get_state ( ) ! = TAP_DRSHIFT )
2008-02-25 17:48:04 +00:00
{
2009-06-04 01:17:27 +00:00
move_to_state ( TAP_DRSHIFT ) ;
2008-02-25 17:48:04 +00:00
}
2009-05-18 17:41:27 +00:00
}
else
{
if ( tap_get_state ( ) ! = TAP_IRSHIFT )
2008-02-25 17:48:04 +00:00
{
2009-06-04 01:17:27 +00:00
move_to_state ( TAP_IRSHIFT ) ;
2008-02-25 17:48:04 +00:00
}
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* add command for complete bytes */
while ( num_bytes > 1 )
{
int thisrun_bytes ;
if ( type = = SCAN_IO )
{
/* Clock Data Bytes In and Out LSB First */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x39 ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bytes (io %i)", num_bytes); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_OUT )
{
/* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x19 ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bytes (o)"); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_IN )
{
/* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x28 ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bytes (i %i)", num_bytes); */
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
thisrun_bytes = ( num_bytes > 65537 ) ? 65536 : ( num_bytes - 1 ) ;
2009-02-03 05:59:17 +00:00
num_bytes - = thisrun_bytes ;
2009-05-18 17:41:27 +00:00
2009-06-18 07:07:12 +00:00
buffer_write ( ( uint8_t ) ( thisrun_bytes - 1 ) ) ;
buffer_write ( ( uint8_t ) ( ( thisrun_bytes - 1 ) > > 8 ) ) ;
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
if ( type ! = SCAN_IN )
{
/* add complete bytes */
2009-02-03 05:59:17 +00:00
while ( thisrun_bytes - - > 0 )
2008-02-25 17:48:04 +00:00
{
2009-06-04 01:17:27 +00:00
buffer_write ( buffer [ cur_byte + + ] ) ;
2008-02-25 17:48:04 +00:00
bits_left - = 8 ;
}
}
else /* (type == SCAN_IN) */
{
bits_left - = 8 * ( thisrun_bytes ) ;
}
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* the most signifcant bit is scanned during TAP movement */
if ( type ! = SCAN_IN )
2009-06-04 01:17:27 +00:00
last_bit = ( buffer [ cur_byte ] > > ( bits_left - 1 ) ) & 0x1 ;
2008-02-25 17:48:04 +00:00
else
last_bit = 0 ;
/* process remaining bits but the last one */
if ( bits_left > 1 )
{
if ( type = = SCAN_IO )
{
/* Clock Data Bits In and Out LSB First */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x3b ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_OUT )
{
/* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x1b ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (o)"); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_IN )
{
/* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x2a ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */
2008-02-25 17:48:04 +00:00
}
2009-05-18 17:41:27 +00:00
2009-06-04 01:17:27 +00:00
buffer_write ( bits_left - 2 ) ;
2008-02-25 17:48:04 +00:00
if ( type ! = SCAN_IN )
2009-06-04 01:17:27 +00:00
buffer_write ( buffer [ cur_byte ] ) ;
2008-02-25 17:48:04 +00:00
}
2009-06-23 22:46:23 +00:00
if ( ( ir_scan & & ( tap_get_end_state ( ) = = TAP_IRSHIFT ) )
2009-06-04 01:17:27 +00:00
| | ( ! ir_scan & & ( tap_get_end_state ( ) = = TAP_DRSHIFT ) ) )
2008-02-25 17:48:04 +00:00
{
if ( type = = SCAN_IO )
{
/* Clock Data Bits In and Out LSB First */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x3b ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_OUT )
{
/* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x1b ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (o)"); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_IN )
{
/* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x2a ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */
2008-02-25 17:48:04 +00:00
}
2009-06-04 01:17:27 +00:00
buffer_write ( 0x0 ) ;
buffer_write ( last_bit ) ;
2008-02-25 17:48:04 +00:00
}
else
{
2009-05-18 17:41:27 +00:00
int tms_bits ;
int tms_count ;
2009-06-18 07:07:12 +00:00
uint8_t mpsse_cmd ;
2009-05-18 17:41:27 +00:00
2008-02-25 17:48:04 +00:00
/* move from Shift-IR/DR to end state */
if ( type ! = SCAN_OUT )
{
2009-05-18 17:41:27 +00:00
/* We always go to the PAUSE state in two step at the end of an IN or IO scan */
/* This must be coordinated with the bit shifts in ft2232_read_scan */
tms_bits = 0x01 ;
tms_count = 2 ;
2008-02-25 17:48:04 +00:00
/* Clock Data to TMS/CS Pin with Read */
2009-05-18 17:41:27 +00:00
mpsse_cmd = 0x6b ;
2008-02-25 17:48:04 +00:00
}
else
{
2009-06-04 01:17:27 +00:00
tms_bits = tap_get_tms_path ( tap_get_state ( ) , tap_get_end_state ( ) ) ;
tms_count = tap_get_tms_path_len ( tap_get_state ( ) , tap_get_end_state ( ) ) ;
2008-02-25 17:48:04 +00:00
/* Clock Data to TMS/CS Pin (no Read) */
2009-05-18 17:41:27 +00:00
mpsse_cmd = 0x4b ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +00:00
2009-10-07 17:30:51 +00:00
DEBUG_JTAG_IO ( " finish %s " , ( type = = SCAN_OUT ) ? " without read " : " via PAUSE " ) ;
2009-06-04 01:17:27 +00:00
clock_tms ( mpsse_cmd , tms_bits , tms_count , last_bit ) ;
2009-05-18 17:41:27 +00:00
}
2009-06-04 01:17:27 +00:00
2009-05-18 17:41:27 +00:00
if ( tap_get_state ( ) ! = tap_get_end_state ( ) )
{
2009-06-04 01:17:27 +00:00
move_to_state ( tap_get_end_state ( ) ) ;
2008-02-25 17:48:04 +00:00
}
}
2009-11-13 13:30:28 +00:00
static int ft2232_large_scan ( struct scan_command * cmd , enum scan_type type , uint8_t * buffer , int scan_size )
2008-02-25 17:48:04 +00:00
{
int num_bytes = ( scan_size + 7 ) / 8 ;
int bits_left = scan_size ;
2009-02-03 05:59:17 +00:00
int cur_byte = 0 ;
2008-02-25 17:48:04 +00:00
int last_bit ;
2009-11-16 10:53:57 +00:00
uint8_t * receive_buffer = malloc ( DIV_ROUND_UP ( scan_size , 8 ) ) ;
2009-06-18 07:07:12 +00:00
uint8_t * receive_pointer = receive_buffer ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
uint32_t bytes_read ;
2008-02-25 17:48:04 +00:00
int retval ;
int thisrun_read = 0 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( cmd - > ir_scan )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " BUG: large IR scans are not supported " ) ;
2008-02-25 17:48:04 +00:00
exit ( - 1 ) ;
}
2009-02-03 05:59:17 +00:00
if ( tap_get_state ( ) ! = TAP_DRSHIFT )
2008-02-25 17:48:04 +00:00
{
2009-06-04 01:17:27 +00:00
move_to_state ( TAP_DRSHIFT ) ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( retval = ft2232_write ( ft2232_buffer , ft2232_buffer_size , & bytes_written ) ) ! = ERROR_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " couldn't write MPSSE commands to FT2232 " ) ;
2008-02-25 17:48:04 +00:00
exit ( - 1 ) ;
}
2009-06-23 22:50:08 +00:00
LOG_DEBUG ( " ft2232_buffer_size: %i, bytes_written: %i " ,
2009-06-19 23:15:58 +00:00
ft2232_buffer_size , ( int ) bytes_written ) ;
2008-02-25 17:48:04 +00:00
ft2232_buffer_size = 0 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* add command for complete bytes */
while ( num_bytes > 1 )
{
int thisrun_bytes ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( type = = SCAN_IO )
{
/* Clock Data Bytes In and Out LSB First */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x39 ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bytes (io %i)", num_bytes); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_OUT )
{
/* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x19 ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bytes (o)"); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_IN )
{
/* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x28 ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bytes (i %i)", num_bytes); */
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
thisrun_bytes = ( num_bytes > 65537 ) ? 65536 : ( num_bytes - 1 ) ;
2009-02-03 05:59:17 +00:00
thisrun_read = thisrun_bytes ;
num_bytes - = thisrun_bytes ;
2009-06-18 07:07:12 +00:00
buffer_write ( ( uint8_t ) ( thisrun_bytes - 1 ) ) ;
buffer_write ( ( uint8_t ) ( ( thisrun_bytes - 1 ) > > 8 ) ) ;
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
if ( type ! = SCAN_IN )
{
/* add complete bytes */
2009-02-03 05:59:17 +00:00
while ( thisrun_bytes - - > 0 )
2008-02-25 17:48:04 +00:00
{
2009-06-04 01:17:27 +00:00
buffer_write ( buffer [ cur_byte ] ) ;
2008-02-25 17:48:04 +00:00
cur_byte + + ;
bits_left - = 8 ;
}
}
else /* (type == SCAN_IN) */
{
bits_left - = 8 * ( thisrun_bytes ) ;
}
2009-06-04 01:17:27 +00:00
if ( ( retval = ft2232_write ( ft2232_buffer , ft2232_buffer_size , & bytes_written ) ) ! = ERROR_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " couldn't write MPSSE commands to FT2232 " ) ;
2008-02-25 17:48:04 +00:00
exit ( - 1 ) ;
}
2009-06-23 22:50:08 +00:00
LOG_DEBUG ( " ft2232_buffer_size: %i, bytes_written: %i " ,
ft2232_buffer_size ,
2009-06-19 23:15:58 +00:00
( int ) bytes_written ) ;
2008-02-25 17:48:04 +00:00
ft2232_buffer_size = 0 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( type ! = SCAN_OUT )
{
2009-06-04 01:17:27 +00:00
if ( ( retval = ft2232_read ( receive_pointer , thisrun_read , & bytes_read ) ) ! = ERROR_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " couldn't read from FT2232 " ) ;
2008-02-25 17:48:04 +00:00
exit ( - 1 ) ;
}
2009-06-23 22:50:08 +00:00
LOG_DEBUG ( " thisrun_read: %i, bytes_read: %i " ,
thisrun_read ,
2009-06-19 23:15:58 +00:00
( int ) bytes_read ) ;
2008-02-25 17:48:04 +00:00
receive_pointer + = bytes_read ;
}
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
thisrun_read = 0 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* the most signifcant bit is scanned during TAP movement */
if ( type ! = SCAN_IN )
2009-06-04 01:17:27 +00:00
last_bit = ( buffer [ cur_byte ] > > ( bits_left - 1 ) ) & 0x1 ;
2008-02-25 17:48:04 +00:00
else
last_bit = 0 ;
/* process remaining bits but the last one */
if ( bits_left > 1 )
{
if ( type = = SCAN_IO )
{
/* Clock Data Bits In and Out LSB First */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x3b ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_OUT )
{
/* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x1b ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (o)"); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_IN )
{
/* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x2a ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */
2008-02-25 17:48:04 +00:00
}
2009-06-04 01:17:27 +00:00
buffer_write ( bits_left - 2 ) ;
2008-02-25 17:48:04 +00:00
if ( type ! = SCAN_IN )
2009-06-04 01:17:27 +00:00
buffer_write ( buffer [ cur_byte ] ) ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( type ! = SCAN_OUT )
thisrun_read + = 2 ;
}
2009-02-03 05:59:17 +00:00
if ( tap_get_end_state ( ) = = TAP_DRSHIFT )
2008-02-25 17:48:04 +00:00
{
if ( type = = SCAN_IO )
{
/* Clock Data Bits In and Out LSB First */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x3b ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_OUT )
{
/* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x1b ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (o)"); */
2008-02-25 17:48:04 +00:00
}
else if ( type = = SCAN_IN )
{
/* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x2a ) ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */
2008-02-25 17:48:04 +00:00
}
2009-06-04 01:17:27 +00:00
buffer_write ( 0x0 ) ;
buffer_write ( last_bit ) ;
2008-02-25 17:48:04 +00:00
}
else
{
2009-06-04 01:17:27 +00:00
int tms_bits = tap_get_tms_path ( tap_get_state ( ) , tap_get_end_state ( ) ) ;
int tms_count = tap_get_tms_path_len ( tap_get_state ( ) , tap_get_end_state ( ) ) ;
2009-06-18 07:07:12 +00:00
uint8_t mpsse_cmd ;
2009-05-18 17:41:27 +00:00
2008-02-25 17:48:04 +00:00
/* move from Shift-IR/DR to end state */
if ( type ! = SCAN_OUT )
{
/* Clock Data to TMS/CS Pin with Read */
2009-05-18 17:41:27 +00:00
mpsse_cmd = 0x6b ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TMS scan (read)"); */
2008-02-25 17:48:04 +00:00
}
else
{
/* Clock Data to TMS/CS Pin (no Read) */
2009-05-18 17:41:27 +00:00
mpsse_cmd = 0x4b ;
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TMS scan (no read)"); */
2008-02-25 17:48:04 +00:00
}
2009-05-18 17:41:27 +00:00
2009-10-07 17:30:51 +00:00
DEBUG_JTAG_IO ( " finish, %s " , ( type = = SCAN_OUT ) ? " no read " : " read " ) ;
2009-06-04 01:17:27 +00:00
clock_tms ( mpsse_cmd , tms_bits , tms_count , last_bit ) ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( type ! = SCAN_OUT )
thisrun_read + = 1 ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( retval = ft2232_write ( ft2232_buffer , ft2232_buffer_size , & bytes_written ) ) ! = ERROR_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " couldn't write MPSSE commands to FT2232 " ) ;
2008-02-25 17:48:04 +00:00
exit ( - 1 ) ;
}
2009-06-23 22:50:08 +00:00
LOG_DEBUG ( " ft2232_buffer_size: %i, bytes_written: %i " ,
ft2232_buffer_size ,
2009-06-19 23:15:58 +00:00
( int ) bytes_written ) ;
2008-02-25 17:48:04 +00:00
ft2232_buffer_size = 0 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( type ! = SCAN_OUT )
{
2009-06-04 01:17:27 +00:00
if ( ( retval = ft2232_read ( receive_pointer , thisrun_read , & bytes_read ) ) ! = ERROR_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " couldn't read from FT2232 " ) ;
2008-02-25 17:48:04 +00:00
exit ( - 1 ) ;
}
2009-06-23 22:50:08 +00:00
LOG_DEBUG ( " thisrun_read: %i, bytes_read: %i " ,
thisrun_read ,
2009-06-19 23:15:58 +00:00
( int ) bytes_read ) ;
2008-02-25 17:48:04 +00:00
receive_pointer + = bytes_read ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int ft2232_predict_scan_out ( int scan_size , enum scan_type type )
2008-02-25 17:48:04 +00:00
{
int predicted_size = 3 ;
int num_bytes = ( scan_size - 1 ) / 8 ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
if ( tap_get_state ( ) ! = TAP_DRSHIFT )
2009-06-04 01:17:27 +00:00
predicted_size + = get_tms_buffer_requirements ( tap_get_tms_path_len ( tap_get_state ( ) , TAP_DRSHIFT ) ) ;
2008-12-13 06:25:50 +00:00
2009-08-18 14:41:58 +00:00
if ( type = = SCAN_IN ) /* only from device to host */
2008-02-25 17:48:04 +00:00
{
/* complete bytes */
2009-11-16 10:53:57 +00:00
predicted_size + = DIV_ROUND_UP ( num_bytes , 65536 ) * 3 ;
2009-05-18 17:41:27 +00:00
2008-02-25 17:48:04 +00:00
/* remaining bits - 1 (up to 7) */
2009-06-04 01:17:27 +00:00
predicted_size + = ( ( scan_size - 1 ) % 8 ) ? 2 : 0 ;
2008-02-25 17:48:04 +00:00
}
2009-08-18 14:41:58 +00:00
else /* host to device, or bidirectional */
2008-02-25 17:48:04 +00:00
{
/* complete bytes */
2009-11-16 10:53:57 +00:00
predicted_size + = num_bytes + DIV_ROUND_UP ( num_bytes , 65536 ) * 3 ;
2009-05-18 17:41:27 +00:00
2008-02-25 17:48:04 +00:00
/* remaining bits -1 (up to 7) */
2009-06-04 01:17:27 +00:00
predicted_size + = ( ( scan_size - 1 ) % 8 ) ? 3 : 0 ;
2008-02-25 17:48:04 +00:00
}
return predicted_size ;
}
2009-04-21 05:29:23 +00:00
static int ft2232_predict_scan_in ( int scan_size , enum scan_type type )
2008-02-25 17:48:04 +00:00
{
int predicted_size = 0 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( type ! = SCAN_OUT )
{
/* complete bytes */
2009-11-16 10:53:57 +00:00
predicted_size + = ( DIV_ROUND_UP ( scan_size , 8 ) > 1 ) ? ( DIV_ROUND_UP ( scan_size , 8 ) - 1 ) : 0 ;
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
/* remaining bits - 1 */
2009-06-04 01:17:27 +00:00
predicted_size + = ( ( scan_size - 1 ) % 8 ) ? 1 : 0 ;
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
/* last bit (from TMS scan) */
predicted_size + = 1 ;
}
2008-12-13 06:25:50 +00:00
2008-03-25 15:45:17 +00:00
/* LOG_DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size); */
2008-02-25 17:48:04 +00:00
return predicted_size ;
}
2009-04-21 05:29:23 +00:00
static void usbjtag_reset ( int trst , int srst )
2008-02-25 17:48:04 +00:00
{
2009-06-09 08:40:31 +00:00
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
2008-02-25 17:48:04 +00:00
if ( trst = = 1 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
2009-08-18 14:41:58 +00:00
low_direction | = nTRSTnOE ; /* switch to output pin (output is low) */
2008-02-25 17:48:04 +00:00
else
2009-08-18 14:41:58 +00:00
low_output & = ~ nTRST ; /* switch output low */
2008-02-25 17:48:04 +00:00
}
else if ( trst = = 0 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
2009-08-18 14:41:58 +00:00
low_direction & = ~ nTRSTnOE ; /* switch to input pin (high-Z + internal and external pullup) */
2008-02-25 17:48:04 +00:00
else
2009-08-18 14:41:58 +00:00
low_output | = nTRST ; /* switch output high */
2008-02-25 17:48:04 +00:00
}
if ( srst = = 1 )
{
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
2009-08-18 14:41:58 +00:00
low_output & = ~ nSRST ; /* switch output low */
2008-02-25 17:48:04 +00:00
else
2009-08-18 14:41:58 +00:00
low_direction | = nSRSTnOE ; /* switch to output pin (output is low) */
2008-02-25 17:48:04 +00:00
}
else if ( srst = = 0 )
{
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
2009-08-18 14:41:58 +00:00
low_output | = nSRST ; /* switch output high */
2008-02-25 17:48:04 +00:00
else
2009-08-18 14:41:58 +00:00
low_direction & = ~ nSRSTnOE ; /* switch to input pin (high-Z) */
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* command "set data bits low byte" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x80 ) ;
buffer_write ( low_output ) ;
buffer_write ( low_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-04-21 05:29:23 +00:00
static void jtagkey_reset ( int trst , int srst )
2008-02-25 17:48:04 +00:00
{
2009-06-09 08:40:31 +00:00
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
2008-02-25 17:48:04 +00:00
if ( trst = = 1 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
high_output & = ~ nTRSTnOE ;
else
high_output & = ~ nTRST ;
}
else if ( trst = = 0 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
high_output | = nTRSTnOE ;
else
high_output | = nTRST ;
}
if ( srst = = 1 )
{
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
high_output & = ~ nSRST ;
else
high_output & = ~ nSRSTnOE ;
}
else if ( srst = = 0 )
{
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
high_output | = nSRST ;
else
high_output | = nSRSTnOE ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* command "set data bits high byte" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2009-02-03 05:59:17 +00:00
LOG_DEBUG ( " trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x " , trst , srst , high_output ,
high_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-04-21 05:29:23 +00:00
static void olimex_jtag_reset ( int trst , int srst )
2008-02-25 17:48:04 +00:00
{
2009-06-09 08:40:31 +00:00
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
2008-02-25 17:48:04 +00:00
if ( trst = = 1 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
high_output & = ~ nTRSTnOE ;
else
high_output & = ~ nTRST ;
}
else if ( trst = = 0 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
high_output | = nTRSTnOE ;
else
high_output | = nTRST ;
}
2008-05-12 09:01:38 +00:00
if ( srst = = 1 )
{
high_output | = nSRST ;
}
else if ( srst = = 0 )
{
high_output & = ~ nSRST ;
}
/* command "set data bits high byte" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2009-02-03 05:59:17 +00:00
LOG_DEBUG ( " trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x " , trst , srst , high_output ,
high_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-04-21 05:29:23 +00:00
static void axm0432_jtag_reset ( int trst , int srst )
2008-12-11 19:03:17 +00:00
{
if ( trst = = 1 )
{
2009-02-03 05:59:17 +00:00
tap_set_state ( TAP_RESET ) ;
2008-12-11 19:03:17 +00:00
high_output & = ~ nTRST ;
}
else if ( trst = = 0 )
{
high_output | = nTRST ;
}
2008-12-11 23:22:16 +00:00
if ( srst = = 1 )
{
high_output & = ~ nSRST ;
}
else if ( srst = = 0 )
{
high_output | = nSRST ;
}
2008-12-11 19:03:17 +00:00
2008-12-11 23:22:16 +00:00
/* command "set data bits low byte" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2009-02-03 05:59:17 +00:00
LOG_DEBUG ( " trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x " , trst , srst , high_output ,
high_direction ) ;
2008-12-11 23:22:16 +00:00
}
2008-12-11 19:03:17 +00:00
2009-04-21 05:29:23 +00:00
static void flyswatter_reset ( int trst , int srst )
2008-02-25 17:48:04 +00:00
{
if ( trst = = 1 )
{
low_output & = ~ nTRST ;
}
else if ( trst = = 0 )
{
low_output | = nTRST ;
}
2008-05-12 09:01:38 +00:00
if ( srst = = 1 )
{
low_output | = nSRST ;
}
else if ( srst = = 0 )
{
low_output & = ~ nSRST ;
}
/* command "set data bits low byte" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x80 ) ;
buffer_write ( low_output ) ;
buffer_write ( low_direction ) ;
2008-05-12 09:01:38 +00:00
LOG_DEBUG ( " trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x " , trst , srst , low_output , low_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-04-21 05:29:23 +00:00
static void turtle_reset ( int trst , int srst )
2008-02-25 17:48:04 +00:00
{
trst = trst ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( srst = = 1 )
{
low_output | = nSRST ;
}
else if ( srst = = 0 )
{
low_output & = ~ nSRST ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* command "set data bits low byte" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x80 ) ;
buffer_write ( low_output ) ;
buffer_write ( low_direction ) ;
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x " , srst , low_output , low_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-04-21 05:29:23 +00:00
static void comstick_reset ( int trst , int srst )
2008-02-25 17:48:04 +00:00
{
if ( trst = = 1 )
{
high_output & = ~ nTRST ;
}
else if ( trst = = 0 )
{
high_output | = nTRST ;
}
2008-05-12 09:01:38 +00:00
if ( srst = = 1 )
{
high_output & = ~ nSRST ;
}
else if ( srst = = 0 )
{
high_output | = nSRST ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* command "set data bits high byte" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2009-02-03 05:59:17 +00:00
LOG_DEBUG ( " trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x " , trst , srst , high_output ,
high_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-04-21 05:29:23 +00:00
static void stm32stick_reset ( int trst , int srst )
2008-02-25 17:48:04 +00:00
{
if ( trst = = 1 )
{
high_output & = ~ nTRST ;
}
else if ( trst = = 0 )
{
high_output | = nTRST ;
}
2008-05-12 09:01:38 +00:00
if ( srst = = 1 )
{
low_output & = ~ nSRST ;
}
else if ( srst = = 0 )
{
low_output | = nSRST ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* command "set data bits low byte" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x80 ) ;
buffer_write ( low_output ) ;
buffer_write ( low_direction ) ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* command "set data bits high byte" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2009-02-03 05:59:17 +00:00
LOG_DEBUG ( " trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x " , trst , srst , high_output ,
high_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-04-21 05:29:23 +00:00
static void sheevaplug_reset ( int trst , int srst )
2009-03-01 21:01:11 +00:00
{
if ( trst = = 1 )
high_output & = ~ nTRST ;
else if ( trst = = 0 )
high_output | = nTRST ;
if ( srst = = 1 )
high_output & = ~ nSRSTnOE ;
else if ( srst = = 0 )
high_output | = nSRSTnOE ;
/* command "set data bits high byte" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2009-03-01 21:01:11 +00:00
LOG_DEBUG ( " trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x " , trst , srst , high_output , high_direction ) ;
}
2009-11-13 14:15:31 +00:00
static int ft2232_execute_runtest ( struct jtag_command * cmd )
2009-04-25 00:54:21 +00:00
{
2009-08-18 14:41:58 +00:00
int retval ;
int i ;
2009-04-25 00:54:21 +00:00
int predicted_size = 0 ;
retval = ERROR_OK ;
2009-05-18 17:41:27 +00:00
DEBUG_JTAG_IO ( " runtest %i cycles, end in %s " ,
2009-04-25 00:54:21 +00:00
cmd - > cmd . runtest - > num_cycles ,
2009-05-18 17:41:27 +00:00
tap_state_name ( cmd - > cmd . runtest - > end_state ) ) ;
2009-04-25 00:54:21 +00:00
/* only send the maximum buffer size that FT2232C can handle */
predicted_size = 0 ;
if ( tap_get_state ( ) ! = TAP_IDLE )
predicted_size + = 3 ;
2009-11-16 10:53:57 +00:00
predicted_size + = 3 * DIV_ROUND_UP ( cmd - > cmd . runtest - > num_cycles , 7 ) ;
2009-06-04 01:17:27 +00:00
if ( cmd - > cmd . runtest - > end_state ! = TAP_IDLE )
2009-04-25 00:54:21 +00:00
predicted_size + = 3 ;
2009-06-04 01:17:27 +00:00
if ( tap_get_end_state ( ) ! = TAP_IDLE )
2009-04-25 00:54:21 +00:00
predicted_size + = 3 ;
if ( ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE )
2008-02-25 17:48:04 +00:00
{
2009-04-25 00:54:21 +00:00
if ( ft2232_send_and_recv ( first_unsent , cmd ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
require_send = 0 ;
first_unsent = cmd ;
}
if ( tap_get_state ( ) ! = TAP_IDLE )
{
2009-06-04 01:17:27 +00:00
move_to_state ( TAP_IDLE ) ;
2009-04-25 00:54:21 +00:00
require_send = 1 ;
}
i = cmd - > cmd . runtest - > num_cycles ;
while ( i > 0 )
{
2009-05-18 17:41:27 +00:00
/* there are no state transitions in this code, so omit state tracking */
2009-04-25 00:54:21 +00:00
/* command "Clock Data to TMS/CS Pin (no Read)" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x4b ) ;
2009-02-03 05:59:17 +00:00
2009-04-25 00:54:21 +00:00
/* scan 7 bits */
2009-06-04 01:17:27 +00:00
buffer_write ( ( i > 7 ) ? 6 : ( i - 1 ) ) ;
2008-12-13 06:25:50 +00:00
2009-04-25 00:54:21 +00:00
/* TMS data bits */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x0 ) ;
2009-05-18 17:41:27 +00:00
2009-04-25 00:54:21 +00:00
i - = ( i > 7 ) ? 7 : i ;
/* LOG_DEBUG("added TMS scan (no read)"); */
}
2009-06-02 07:21:44 +00:00
ft2232_end_state ( cmd - > cmd . runtest - > end_state ) ;
2009-04-25 00:54:21 +00:00
2009-06-04 01:17:27 +00:00
if ( tap_get_state ( ) ! = tap_get_end_state ( ) )
2009-04-25 00:54:21 +00:00
{
2009-06-04 01:17:27 +00:00
move_to_state ( tap_get_end_state ( ) ) ;
2009-04-25 00:54:21 +00:00
}
2009-05-18 17:41:27 +00:00
2009-04-25 00:54:21 +00:00
require_send = 1 ;
2009-10-07 17:30:51 +00:00
DEBUG_JTAG_IO ( " runtest: %i, end in %s " ,
cmd - > cmd . runtest - > num_cycles ,
tap_state_name ( tap_get_end_state ( ) ) ) ;
2009-04-25 00:54:21 +00:00
return retval ;
}
2009-01-09 07:42:45 +00:00
2009-11-13 14:15:31 +00:00
static int ft2232_execute_statemove ( struct jtag_command * cmd )
2009-04-25 00:54:21 +00:00
{
2009-06-04 01:17:27 +00:00
int predicted_size = 0 ;
int retval = ERROR_OK ;
2009-02-03 05:59:17 +00:00
2009-10-07 17:30:51 +00:00
DEBUG_JTAG_IO ( " statemove end in %s " ,
tap_state_name ( cmd - > cmd . statemove - > end_state ) ) ;
2009-04-25 00:54:21 +00:00
/* only send the maximum buffer size that FT2232C can handle */
predicted_size = 3 ;
if ( ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE )
{
if ( ft2232_send_and_recv ( first_unsent , cmd ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
require_send = 0 ;
first_unsent = cmd ;
}
2009-06-02 07:21:44 +00:00
ft2232_end_state ( cmd - > cmd . statemove - > end_state ) ;
2009-02-03 05:59:17 +00:00
2009-09-27 16:55:52 +00:00
/* For TAP_RESET, ignore the current recorded state. It's often
* wrong at server startup , and this transation is critical whenever
* it ' s requested .
*/
if ( tap_get_end_state ( ) = = TAP_RESET ) {
clock_tms ( 0x4b , 0xff , 5 , 0 ) ;
require_send = 1 ;
/* shortest-path move to desired end state */
} else if ( tap_get_state ( ) ! = tap_get_end_state ( ) )
2009-05-18 17:41:27 +00:00
{
2009-06-04 01:17:27 +00:00
move_to_state ( tap_get_end_state ( ) ) ;
2009-05-18 17:41:27 +00:00
require_send = 1 ;
}
2009-04-25 00:54:21 +00:00
return retval ;
}
2009-02-03 05:59:17 +00:00
2009-11-13 14:15:31 +00:00
static int ft2232_execute_pathmove ( struct jtag_command * cmd )
2009-04-25 00:54:21 +00:00
{
2009-06-04 01:17:27 +00:00
int predicted_size = 0 ;
2009-05-18 17:41:27 +00:00
int retval = ERROR_OK ;
tap_state_t * path = cmd - > cmd . pathmove - > path ;
int num_states = cmd - > cmd . pathmove - > num_states ;
DEBUG_JTAG_IO ( " pathmove: %i states, current: %s end: %s " , num_states ,
2009-06-04 01:17:27 +00:00
tap_state_name ( tap_get_state ( ) ) ,
2009-08-18 14:41:58 +00:00
tap_state_name ( path [ num_states - 1 ] ) ) ;
2009-02-03 05:59:17 +00:00
2009-04-25 00:54:21 +00:00
/* only send the maximum buffer size that FT2232C can handle */
2009-11-16 10:53:57 +00:00
predicted_size = 3 * DIV_ROUND_UP ( num_states , 7 ) ;
2009-04-25 00:54:21 +00:00
if ( ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE )
{
if ( ft2232_send_and_recv ( first_unsent , cmd ) ! = ERROR_OK )
2009-05-18 17:41:27 +00:00
retval = ERROR_JTAG_QUEUE_FAILED ;
2009-04-25 00:54:21 +00:00
require_send = 0 ;
first_unsent = cmd ;
}
2009-05-18 17:41:27 +00:00
2009-06-04 01:17:27 +00:00
ft2232_add_pathmove ( path , num_states ) ;
2009-04-25 00:54:21 +00:00
require_send = 1 ;
2009-05-18 17:41:27 +00:00
2009-04-25 00:54:21 +00:00
return retval ;
}
2009-01-09 07:42:45 +00:00
2009-11-13 14:15:31 +00:00
static int ft2232_execute_scan ( struct jtag_command * cmd )
2009-04-25 00:54:21 +00:00
{
2009-08-18 14:41:58 +00:00
uint8_t * buffer ;
int scan_size ; /* size of IR or DR scan */
int predicted_size = 0 ;
int retval = ERROR_OK ;
2009-05-18 17:41:27 +00:00
enum scan_type type = jtag_scan_type ( cmd - > cmd . scan ) ;
2009-06-04 01:17:27 +00:00
DEBUG_JTAG_IO ( " %s type:%d " , cmd - > cmd . scan - > ir_scan ? " IRSCAN " : " DRSCAN " , type ) ;
2009-04-25 00:54:21 +00:00
scan_size = jtag_build_buffer ( cmd - > cmd . scan , & buffer ) ;
2009-05-18 17:41:27 +00:00
2009-04-25 00:54:21 +00:00
predicted_size = ft2232_predict_scan_out ( scan_size , type ) ;
2009-06-04 01:17:27 +00:00
if ( ( predicted_size + 1 ) > FT2232_BUFFER_SIZE )
2009-04-25 00:54:21 +00:00
{
LOG_DEBUG ( " oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE) " ) ;
/* unsent commands before this */
if ( first_unsent ! = cmd )
if ( ft2232_send_and_recv ( first_unsent , cmd ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
/* current command */
2009-06-02 07:21:44 +00:00
ft2232_end_state ( cmd - > cmd . scan - > end_state ) ;
2009-04-25 00:54:21 +00:00
ft2232_large_scan ( cmd - > cmd . scan , type , buffer , scan_size ) ;
require_send = 0 ;
first_unsent = cmd - > next ;
if ( buffer )
free ( buffer ) ;
return retval ;
}
else if ( ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE )
{
LOG_DEBUG ( " ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p) " ,
first_unsent ,
cmd ) ;
if ( ft2232_send_and_recv ( first_unsent , cmd ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
require_send = 0 ;
first_unsent = cmd ;
}
ft2232_expect_read + = ft2232_predict_scan_in ( scan_size , type ) ;
/* LOG_DEBUG("new read size: %i", ft2232_expect_read); */
2009-06-02 07:21:44 +00:00
ft2232_end_state ( cmd - > cmd . scan - > end_state ) ;
2009-04-25 00:54:21 +00:00
ft2232_add_scan ( cmd - > cmd . scan - > ir_scan , type , buffer , scan_size ) ;
require_send = 1 ;
if ( buffer )
free ( buffer ) ;
2009-10-07 17:30:51 +00:00
DEBUG_JTAG_IO ( " %s scan, %i bits, end in %s " ,
( cmd - > cmd . scan - > ir_scan ) ? " IR " : " DR " , scan_size ,
2009-06-04 01:17:27 +00:00
tap_state_name ( tap_get_end_state ( ) ) ) ;
2009-04-25 00:54:21 +00:00
return retval ;
}
2009-11-13 14:15:31 +00:00
static int ft2232_execute_reset ( struct jtag_command * cmd )
2009-04-25 00:54:21 +00:00
{
2009-08-18 14:41:58 +00:00
int retval ;
int predicted_size = 0 ;
2009-04-25 00:54:21 +00:00
retval = ERROR_OK ;
DEBUG_JTAG_IO ( " reset trst: %i srst %i " ,
cmd - > cmd . reset - > trst , cmd - > cmd . reset - > srst ) ;
/* only send the maximum buffer size that FT2232C can handle */
predicted_size = 3 ;
if ( ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE )
{
if ( ft2232_send_and_recv ( first_unsent , cmd ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
require_send = 0 ;
first_unsent = cmd ;
}
2009-09-28 12:22:20 +00:00
if ( ( cmd - > cmd . reset - > trst = = 1 ) | | ( cmd - > cmd . reset - > srst & & ( jtag_get_reset_config ( ) & RESET_SRST_PULLS_TRST ) ) )
{
tap_set_state ( TAP_RESET ) ;
}
2009-04-25 00:54:21 +00:00
layout - > reset ( cmd - > cmd . reset - > trst , cmd - > cmd . reset - > srst ) ;
require_send = 1 ;
2009-02-03 05:59:17 +00:00
2009-10-07 17:30:51 +00:00
DEBUG_JTAG_IO ( " trst: %i, srst: %i " ,
cmd - > cmd . reset - > trst , cmd - > cmd . reset - > srst ) ;
2009-04-25 00:54:21 +00:00
return retval ;
}
2009-01-09 07:42:45 +00:00
2009-11-13 14:15:31 +00:00
static int ft2232_execute_sleep ( struct jtag_command * cmd )
2009-04-25 00:54:21 +00:00
{
2009-08-18 14:41:58 +00:00
int retval ;
2009-04-25 00:54:21 +00:00
retval = ERROR_OK ;
2009-11-12 22:21:33 +00:00
DEBUG_JTAG_IO ( " sleep % " PRIi32 , cmd - > cmd . sleep - > us ) ;
2009-04-25 00:54:21 +00:00
if ( ft2232_send_and_recv ( first_unsent , cmd ) ! = ERROR_OK )
2009-02-03 05:59:17 +00:00
retval = ERROR_JTAG_QUEUE_FAILED ;
2009-04-25 00:54:21 +00:00
first_unsent = cmd - > next ;
jtag_sleep ( cmd - > cmd . sleep - > us ) ;
2009-11-12 22:21:33 +00:00
DEBUG_JTAG_IO ( " sleep % " PRIi32 " usec while in %s " ,
2009-10-07 17:30:51 +00:00
cmd - > cmd . sleep - > us ,
tap_state_name ( tap_get_state ( ) ) ) ;
2009-04-25 00:54:21 +00:00
return retval ;
}
2009-02-03 05:59:17 +00:00
2009-11-13 14:15:31 +00:00
static int ft2232_execute_stableclocks ( struct jtag_command * cmd )
2009-04-25 00:54:21 +00:00
{
2009-08-18 14:41:58 +00:00
int retval ;
2009-04-25 00:54:21 +00:00
retval = ERROR_OK ;
/* this is only allowed while in a stable state. A check for a stable
* state was done in jtag_add_clocks ( )
*/
if ( ft2232_stableclocks ( cmd - > cmd . stableclocks - > num_cycles , cmd ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
2009-10-07 17:30:51 +00:00
DEBUG_JTAG_IO ( " clocks %i while in %s " ,
cmd - > cmd . stableclocks - > num_cycles ,
tap_state_name ( tap_get_state ( ) ) ) ;
2009-04-25 00:54:21 +00:00
return retval ;
}
2009-11-13 14:15:31 +00:00
static int ft2232_execute_command ( struct jtag_command * cmd )
2009-04-25 00:54:21 +00:00
{
2009-08-18 14:41:58 +00:00
int retval ;
2009-04-25 00:54:21 +00:00
retval = ERROR_OK ;
switch ( cmd - > type )
{
2009-06-04 01:17:27 +00:00
case JTAG_RESET : retval = ft2232_execute_reset ( cmd ) ; break ;
case JTAG_RUNTEST : retval = ft2232_execute_runtest ( cmd ) ; break ;
case JTAG_STATEMOVE : retval = ft2232_execute_statemove ( cmd ) ; break ;
case JTAG_PATHMOVE : retval = ft2232_execute_pathmove ( cmd ) ; break ;
case JTAG_SCAN : retval = ft2232_execute_scan ( cmd ) ; break ;
case JTAG_SLEEP : retval = ft2232_execute_sleep ( cmd ) ; break ;
case JTAG_STABLECLOCKS : retval = ft2232_execute_stableclocks ( cmd ) ; break ;
2009-05-18 17:41:27 +00:00
default :
LOG_ERROR ( " BUG: unknown JTAG command type encountered " ) ;
exit ( - 1 ) ;
2009-04-25 00:54:21 +00:00
}
return retval ;
}
2009-11-10 05:21:06 +00:00
static int ft2232_execute_queue ( void )
2009-04-25 00:54:21 +00:00
{
2009-11-13 14:15:31 +00:00
struct jtag_command * cmd = jtag_command_queue ; /* currently processed command */
2009-08-18 14:41:58 +00:00
int retval ;
2009-04-25 00:54:21 +00:00
2009-08-18 14:41:58 +00:00
first_unsent = cmd ; /* next command that has to be sent */
2009-04-25 00:54:21 +00:00
require_send = 0 ;
/* return ERROR_OK, unless ft2232_send_and_recv reports a failed check
* that wasn ' t handled by a caller - provided error handler
*/
retval = ERROR_OK ;
2009-02-03 05:59:17 +00:00
2009-04-25 00:54:21 +00:00
ft2232_buffer_size = 0 ;
ft2232_expect_read = 0 ;
/* blink, if the current layout has that feature */
if ( layout - > blink )
layout - > blink ( ) ;
while ( cmd )
{
if ( ft2232_execute_command ( cmd ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
2009-04-25 00:58:49 +00:00
/* Start reading input before FT2232 TX buffer fills up */
2009-04-25 02:53:07 +00:00
cmd = cmd - > next ;
if ( ft2232_expect_read > 256 )
2009-04-25 00:58:49 +00:00
{
if ( ft2232_send_and_recv ( first_unsent , cmd ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
first_unsent = cmd ;
}
2008-02-25 17:48:04 +00:00
}
if ( require_send > 0 )
if ( ft2232_send_and_recv ( first_unsent , cmd ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
return retval ;
}
# if BUILD_FT2232_FTD2XX == 1
2009-06-18 07:07:59 +00:00
static int ft2232_init_ftd2xx ( uint16_t vid , uint16_t pid , int more , int * try_more )
2008-02-25 17:48:04 +00:00
{
2009-06-04 01:17:27 +00:00
FT_STATUS status ;
2009-06-02 07:51:16 +00:00
DWORD deviceID ;
char SerialNumber [ 16 ] ;
2009-06-04 01:17:27 +00:00
char Description [ 64 ] ;
DWORD openex_flags = 0 ;
char * openex_string = NULL ;
2009-06-18 07:07:12 +00:00
uint8_t latency_timer ;
2008-02-25 17:48:04 +00:00
2009-02-03 05:59:17 +00:00
LOG_DEBUG ( " 'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x) " , ft2232_layout , vid , pid ) ;
2008-02-25 17:48:04 +00:00
# if IS_WIN32 == 0
/* Add non-standard Vid/Pid to the linux driver */
2009-06-04 01:17:27 +00:00
if ( ( status = FT_SetVIDPID ( vid , pid ) ) ! = FT_OK )
2008-02-25 17:48:04 +00:00
{
2008-12-11 23:22:16 +00:00
LOG_WARNING ( " couldn't add %4.4x:%4.4x " , vid , pid ) ;
2008-02-25 17:48:04 +00:00
}
# endif
if ( ft2232_device_desc & & ft2232_serial )
{
2008-03-25 15:45:17 +00:00
LOG_WARNING ( " can't open by device description and serial number, giving precedence to serial " ) ;
2008-02-25 17:48:04 +00:00
ft2232_device_desc = NULL ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( ft2232_device_desc )
{
openex_string = ft2232_device_desc ;
2009-02-03 05:59:17 +00:00
openex_flags = FT_OPEN_BY_DESCRIPTION ;
2008-02-25 17:48:04 +00:00
}
else if ( ft2232_serial )
{
openex_string = ft2232_serial ;
2009-02-03 05:59:17 +00:00
openex_flags = FT_OPEN_BY_SERIAL_NUMBER ;
2008-02-25 17:48:04 +00:00
}
else
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " neither device description nor serial number specified " ) ;
LOG_ERROR ( " please add \" ft2232_device_desc <string> \" or \" ft2232_serial <string> \" to your .cfg file " ) ;
2008-12-13 06:25:50 +00:00
return ERROR_JTAG_INIT_FAILED ;
2008-02-25 17:48:04 +00:00
}
2009-03-07 15:51:26 +00:00
status = FT_OpenEx ( openex_string , openex_flags , & ftdih ) ;
2009-06-04 01:17:27 +00:00
if ( status ! = FT_OK ) {
2009-08-18 14:41:58 +00:00
/* under Win32, the FTD2XX driver appends an "A" to the end
* of the description , if we tried by the desc , then
* try by the alternate " A " description . */
2009-06-04 01:17:27 +00:00
if ( openex_string = = ft2232_device_desc ) {
2009-08-18 14:41:58 +00:00
/* Try the alternate method. */
2009-03-07 15:51:26 +00:00
openex_string = ft2232_device_desc_A ;
status = FT_OpenEx ( openex_string , openex_flags , & ftdih ) ;
2009-06-04 01:17:27 +00:00
if ( status = = FT_OK ) {
2009-08-18 14:41:58 +00:00
/* yea, the "alternate" method worked! */
2009-03-07 15:51:26 +00:00
} else {
2009-08-18 14:41:58 +00:00
/* drat, give the user a meaningfull message.
* telling the use we tried * BOTH * methods . */
2009-03-07 15:51:26 +00:00
LOG_WARNING ( " Unable to open FTDI Device tried: '%s' and '%s' \n " ,
ft2232_device_desc ,
2009-06-04 01:17:27 +00:00
ft2232_device_desc_A ) ;
2009-03-07 15:51:26 +00:00
}
}
}
2009-06-04 01:17:27 +00:00
if ( status ! = FT_OK )
2008-02-25 17:48:04 +00:00
{
DWORD num_devices ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
if ( more )
{
2008-12-11 23:22:16 +00:00
LOG_WARNING ( " unable to open ftdi device (trying more): %lu " , status ) ;
2008-02-25 17:48:04 +00:00
* try_more = 1 ;
return ERROR_JTAG_INIT_FAILED ;
}
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " unable to open ftdi device: %lu " , status ) ;
2008-02-25 17:48:04 +00:00
status = FT_ListDevices ( & num_devices , NULL , FT_LIST_NUMBER_ONLY ) ;
if ( status = = FT_OK )
{
2009-06-04 01:17:27 +00:00
char * * desc_array = malloc ( sizeof ( char * ) * ( num_devices + 1 ) ) ;
2009-06-18 07:11:11 +00:00
uint32_t i ;
2008-02-25 17:48:04 +00:00
for ( i = 0 ; i < num_devices ; i + + )
desc_array [ i ] = malloc ( 64 ) ;
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
desc_array [ num_devices ] = NULL ;
status = FT_ListDevices ( desc_array , & num_devices , FT_LIST_ALL | openex_flags ) ;
if ( status = = FT_OK )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " ListDevices: %lu \n " , num_devices ) ;
2008-02-25 17:48:04 +00:00
for ( i = 0 ; i < num_devices ; i + + )
2009-07-02 11:16:57 +00:00
LOG_ERROR ( " % " PRIu32 " : \" %s \" " , i , desc_array [ i ] ) ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
for ( i = 0 ; i < num_devices ; i + + )
free ( desc_array [ i ] ) ;
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
free ( desc_array ) ;
}
else
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " ListDevices: NONE \n " ) ;
2008-02-25 17:48:04 +00:00
}
return ERROR_JTAG_INIT_FAILED ;
}
2009-06-04 01:17:27 +00:00
if ( ( status = FT_SetLatencyTimer ( ftdih , ft2232_latency ) ) ! = FT_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " unable to set latency timer: %lu " , status ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( status = FT_GetLatencyTimer ( ftdih , & latency_timer ) ) ! = FT_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " unable to get latency timer: %lu " , status ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
else
{
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " current latency timer: %i " , latency_timer ) ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( status = FT_SetTimeouts ( ftdih , 5000 , 5000 ) ) ! = FT_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " unable to set timeouts: %lu " , status ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2009-06-04 01:17:27 +00:00
if ( ( status = FT_SetBitMode ( ftdih , 0x0b , 2 ) ) ! = FT_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " unable to enable bit i/o mode: %lu " , status ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2009-06-04 01:17:27 +00:00
if ( ( status = FT_GetDeviceInfo ( ftdih , & ftdi_device , & deviceID , SerialNumber , Description , NULL ) ) ! = FT_OK )
2009-06-02 07:51:16 +00:00
{
LOG_ERROR ( " unable to get FT_GetDeviceInfo: %lu " , status ) ;
return ERROR_JTAG_INIT_FAILED ;
}
else
{
2009-08-18 14:41:58 +00:00
static const char * type_str [ ] =
{ " BM " , " AM " , " 100AX " , " UNKNOWN " , " 2232C " , " 232R " , " 2232H " , " 4232H " } ;
2009-11-25 04:32:10 +00:00
unsigned no_of_known_types = ARRAY_SIZE ( type_str ) - 1 ;
2009-08-19 08:39:06 +00:00
unsigned type_index = ( ( unsigned ) ftdi_device < = no_of_known_types )
2009-08-20 07:54:49 +00:00
? ftdi_device : FT_DEVICE_UNKNOWN ;
2009-08-18 14:41:58 +00:00
LOG_INFO ( " device: %lu \" %s \" " , ftdi_device , type_str [ type_index ] ) ;
2009-06-02 07:51:16 +00:00
LOG_INFO ( " deviceID: %lu " , deviceID ) ;
LOG_INFO ( " SerialNumber: %s " , SerialNumber ) ;
LOG_INFO ( " Description: %s " , Description ) ;
}
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
static int ft2232_purge_ftd2xx ( void )
{
FT_STATUS status ;
2009-06-04 01:17:27 +00:00
if ( ( status = FT_Purge ( ftdih , FT_PURGE_RX | FT_PURGE_TX ) ) ! = FT_OK )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " error purging ftd2xx device: %lu " , status ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
return ERROR_OK ;
}
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
# endif /* BUILD_FT2232_FTD2XX == 1 */
# if BUILD_FT2232_LIBFTDI == 1
2009-06-18 07:07:59 +00:00
static int ft2232_init_libftdi ( uint16_t vid , uint16_t pid , int more , int * try_more )
2008-02-25 17:48:04 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t latency_timer ;
2008-02-25 17:48:04 +00:00
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " 'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x) " ,
2009-02-03 05:59:17 +00:00
ft2232_layout , vid , pid ) ;
2008-02-25 17:48:04 +00:00
if ( ftdi_init ( & ftdic ) < 0 )
return ERROR_JTAG_INIT_FAILED ;
2009-05-18 17:23:52 +00:00
if ( ftdi_set_interface ( & ftdic , INTERFACE_A ) < 0 )
{
LOG_ERROR ( " unable to select FT2232 channel A: %s " , ftdic . error_str ) ;
return ERROR_JTAG_INIT_FAILED ;
}
2008-02-25 17:48:04 +00:00
/* context, vendor id, product id */
if ( ftdi_usb_open_desc ( & ftdic , vid , pid , ft2232_device_desc ,
2009-02-03 05:59:17 +00:00
ft2232_serial ) < 0 )
{
2008-02-25 17:48:04 +00:00
if ( more )
2008-03-25 15:45:17 +00:00
LOG_WARNING ( " unable to open ftdi device (trying more): %s " ,
2009-02-03 05:59:17 +00:00
ftdic . error_str ) ;
2008-02-25 17:48:04 +00:00
else
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " unable to open ftdi device: %s " , ftdic . error_str ) ;
2008-02-25 17:48:04 +00:00
* try_more = 1 ;
return ERROR_JTAG_INIT_FAILED ;
}
2009-05-18 17:41:27 +00:00
/* There is already a reset in ftdi_usb_open_desc, this should be redundant */
2008-02-25 17:48:04 +00:00
if ( ftdi_usb_reset ( & ftdic ) < 0 )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " unable to reset ftdi device " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
if ( ftdi_set_latency_timer ( & ftdic , ft2232_latency ) < 0 )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " unable to set latency timer " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( ftdi_get_latency_timer ( & ftdic , & latency_timer ) < 0 )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " unable to get latency timer " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
else
{
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " current latency timer: %i " , latency_timer ) ;
2008-02-25 17:48:04 +00:00
}
ftdi_set_bitmode ( & ftdic , 0x0b , 2 ) ; /* ctx, JTAG I/O mask */
2009-08-18 14:41:58 +00:00
ftdi_device = ftdic . type ;
static const char * type_str [ ] =
{ " AM " , " BM " , " 2232C " , " R " , " 2232H " , " 4232H " , " Unknown " } ;
2009-11-25 04:32:10 +00:00
unsigned no_of_known_types = ARRAY_SIZE ( type_str ) - 1 ;
2009-08-18 14:41:58 +00:00
unsigned type_index = ( ( unsigned ) ftdi_device < no_of_known_types )
? ftdi_device : no_of_known_types ;
LOG_DEBUG ( " FTDI chip type: %i \" %s \" " , ( int ) ftdi_device , type_str [ type_index ] ) ;
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
static int ft2232_purge_libftdi ( void )
{
if ( ftdi_usb_purge_buffers ( & ftdic ) < 0 )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " ftdi_purge_buffers: %s " , ftdic . error_str ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
return ERROR_OK ;
}
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
# endif /* BUILD_FT2232_LIBFTDI == 1 */
2009-04-21 05:29:23 +00:00
static int ft2232_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t buf [ 1 ] ;
2008-02-25 17:48:04 +00:00
int retval ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2009-11-13 13:17:18 +00:00
const struct ft2232_layout * cur_layout = ft2232_layouts ;
2008-02-25 17:48:04 +00:00
int i ;
2008-12-13 06:25:50 +00:00
2009-06-23 22:42:03 +00:00
if ( tap_get_tms_path_len ( TAP_IRPAUSE , TAP_IRPAUSE ) = = 7 )
2009-06-04 01:17:27 +00:00
{
2009-05-18 17:41:27 +00:00
LOG_DEBUG ( " ft2232 interface using 7 step jtag state transitions " ) ;
}
else
{
LOG_DEBUG ( " ft2232 interface using shortest path jtag state transitions " ) ;
2009-06-04 01:17:27 +00:00
2009-05-18 17:41:27 +00:00
}
2009-06-04 01:17:27 +00:00
if ( ( ft2232_layout = = NULL ) | | ( ft2232_layout [ 0 ] = = 0 ) )
2008-02-25 17:48:04 +00:00
{
ft2232_layout = " usbjtag " ;
2008-03-25 15:45:17 +00:00
LOG_WARNING ( " No ft2232 layout specified, using default 'usbjtag' " ) ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
while ( cur_layout - > name )
{
if ( strcmp ( cur_layout - > name , ft2232_layout ) = = 0 )
{
layout = cur_layout ;
break ;
}
cur_layout + + ;
}
if ( ! layout )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " No matching layout found for %s " , ft2232_layout ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
for ( i = 0 ; 1 ; i + + )
{
2008-02-25 17:48:04 +00:00
/*
* " more indicates that there are more IDs to try, so we should
* not print an error for an ID mismatch ( but for anything
* else , we should ) .
*
* try_more indicates that the error code returned indicates an
* ID mismatch ( and nothing else ) and that we should proceeed
* with the next ID pair .
*/
2009-02-03 05:59:17 +00:00
int more = ft2232_vid [ i + 1 ] | | ft2232_pid [ i + 1 ] ;
2008-02-25 17:48:04 +00:00
int try_more = 0 ;
# if BUILD_FT2232_FTD2XX == 1
retval = ft2232_init_ftd2xx ( ft2232_vid [ i ] , ft2232_pid [ i ] ,
2009-02-03 05:59:17 +00:00
more , & try_more ) ;
2008-02-25 17:48:04 +00:00
# elif BUILD_FT2232_LIBFTDI == 1
retval = ft2232_init_libftdi ( ft2232_vid [ i ] , ft2232_pid [ i ] ,
2009-02-03 05:59:17 +00:00
more , & try_more ) ;
2008-12-13 06:25:50 +00:00
# endif
2008-02-25 17:48:04 +00:00
if ( retval > = 0 )
break ;
if ( ! more | | ! try_more )
return retval ;
}
ft2232_buffer_size = 0 ;
ft2232_buffer = malloc ( FT2232_BUFFER_SIZE ) ;
if ( layout - > init ( ) ! = ERROR_OK )
return ERROR_JTAG_INIT_FAILED ;
2009-08-18 14:41:58 +00:00
if ( ft2232_device_is_highspeed ( ) )
{
2009-08-20 07:54:49 +00:00
# ifndef BUILD_FT2232_HIGHSPEED
# if BUILD_FT2232_FTD2XX == 1
LOG_WARNING ( " High Speed device found - You need a newer FTD2XX driver (version 2.04.16 or later) " ) ;
# elif BUILD_FT2232_LIBFTDI == 1
LOG_WARNING ( " High Speed device found - You need a newer libftdi version (0.16 or later) " ) ;
# endif
# endif
/* make sure the legacy mode is disabled */
2009-08-18 14:41:58 +00:00
if ( ft2232h_ft4232h_clk_divide_by_5 ( false ) ! = ERROR_OK )
return ERROR_JTAG_INIT_FAILED ;
}
2009-06-09 08:40:10 +00:00
ft2232_speed ( jtag_get_speed ( ) ) ;
2008-02-25 17:48:04 +00:00
buf [ 0 ] = 0x85 ; /* Disconnect TDI/DO to TDO/DI for Loopback */
2009-06-04 01:17:27 +00:00
if ( ( ( retval = ft2232_write ( buf , 1 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 1 ) )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " couldn't write to FT2232 to disable loopback " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
# if BUILD_FT2232_FTD2XX == 1
return ft2232_purge_ftd2xx ( ) ;
# elif BUILD_FT2232_LIBFTDI == 1
return ft2232_purge_libftdi ( ) ;
2008-12-13 06:25:50 +00:00
# endif
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int usbjtag_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t buf [ 3 ] ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
low_output = 0x08 ;
2008-02-25 17:48:04 +00:00
low_direction = 0x0b ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( strcmp ( ft2232_layout , " usbjtag " ) = = 0 )
{
2009-02-03 05:59:17 +00:00
nTRST = 0x10 ;
2008-02-25 17:48:04 +00:00
nTRSTnOE = 0x10 ;
2009-02-03 05:59:17 +00:00
nSRST = 0x40 ;
2008-02-25 17:48:04 +00:00
nSRSTnOE = 0x40 ;
}
else if ( strcmp ( ft2232_layout , " signalyzer " ) = = 0 )
{
2009-02-03 05:59:17 +00:00
nTRST = 0x10 ;
2008-02-25 17:48:04 +00:00
nTRSTnOE = 0x10 ;
2009-02-03 05:59:17 +00:00
nSRST = 0x20 ;
2008-02-25 17:48:04 +00:00
nSRSTnOE = 0x20 ;
}
else if ( strcmp ( ft2232_layout , " evb_lm3s811 " ) = = 0 )
{
2009-12-28 20:59:47 +00:00
/* There are multiple revisions of LM3S811 eval boards:
* - Rev B ( and older ? ) boards have no SWO trace support .
* - Rev C boards add ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN ;
* they should use the " luminary_icdi " layout instead .
*/
2008-02-25 17:48:04 +00:00
nTRST = 0x0 ;
nTRSTnOE = 0x00 ;
nSRST = 0x20 ;
nSRSTnOE = 0x20 ;
2009-02-03 05:59:17 +00:00
low_output = 0x88 ;
2008-02-25 17:48:04 +00:00
low_direction = 0x8b ;
}
2009-06-30 09:09:30 +00:00
else if ( strcmp ( ft2232_layout , " luminary_icdi " ) = = 0 )
{
2009-12-28 20:59:47 +00:00
/* Most Luminary eval boards support SWO trace output,
* and should use this " luminary_icdi " layout .
*/
2009-06-30 09:09:30 +00:00
nTRST = 0x0 ;
nTRSTnOE = 0x00 ;
nSRST = 0x20 ;
nSRSTnOE = 0x20 ;
low_output = 0x88 ;
low_direction = 0xcb ;
}
2008-02-25 17:48:04 +00:00
else
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " BUG: usbjtag_init called for unknown layout '%s' " , ft2232_layout ) ;
2008-12-13 06:25:50 +00:00
return ERROR_JTAG_INIT_FAILED ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2009-06-09 08:40:31 +00:00
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
2008-02-25 17:48:04 +00:00
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
{
low_direction & = ~ nTRSTnOE ; /* nTRST input */
2009-02-03 05:59:17 +00:00
low_output & = ~ nTRST ; /* nTRST = 0 */
2008-02-25 17:48:04 +00:00
}
else
{
2009-02-03 05:59:17 +00:00
low_direction | = nTRSTnOE ; /* nTRST output */
low_output | = nTRST ; /* nTRST = 1 */
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
{
2009-02-03 05:59:17 +00:00
low_direction | = nSRSTnOE ; /* nSRST output */
low_output | = nSRST ; /* nSRST = 1 */
2008-02-25 17:48:04 +00:00
}
else
{
low_direction & = ~ nSRSTnOE ; /* nSRST input */
2009-02-03 05:59:17 +00:00
low_output & = ~ nSRST ; /* nSRST = 0 */
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize low byte for jtag */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
2009-06-23 22:42:54 +00:00
buf [ 1 ] = low_output ; /* value (TMS = 1,TCK = 0, TDI = 0, xRST high) */
buf [ 2 ] = low_direction ; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in */
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'USBJTAG' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int axm0432_jtag_init ( void )
2008-12-11 19:03:17 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t buf [ 3 ] ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
low_output = 0x08 ;
2008-12-11 19:03:17 +00:00
low_direction = 0x2b ;
2008-12-13 06:25:50 +00:00
2008-12-11 19:03:17 +00:00
/* initialize low byte for jtag */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
2009-06-23 22:42:54 +00:00
buf [ 1 ] = low_output ; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
buf [ 2 ] = low_direction ; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
2008-12-11 19:03:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-12-11 19:03:17 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'JTAGkey' layout " ) ;
2008-12-11 19:03:17 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
if ( strcmp ( layout - > name , " axm0432_jtag " ) = = 0 )
{
2009-02-03 05:59:17 +00:00
nTRST = 0x08 ;
nTRSTnOE = 0x0 ; /* No output enable for TRST*/
nSRST = 0x04 ;
nSRSTnOE = 0x0 ; /* No output enable for SRST*/
2008-12-11 19:03:17 +00:00
}
else
{
LOG_ERROR ( " BUG: axm0432_jtag_init called for non axm0432 layout " ) ;
exit ( - 1 ) ;
}
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
high_output = 0x0 ;
2008-12-11 19:03:17 +00:00
high_direction = 0x0c ;
2009-06-09 08:40:31 +00:00
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
2008-12-11 23:22:16 +00:00
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
2008-12-11 19:03:17 +00:00
{
2008-12-11 23:22:16 +00:00
LOG_ERROR ( " can't set nTRSTOE to push-pull on the Dicarlo jtag " ) ;
}
2008-12-11 19:03:17 +00:00
else
{
high_output | = nTRST ;
}
2008-12-11 23:22:16 +00:00
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
2008-12-11 19:03:17 +00:00
{
LOG_ERROR ( " can't set nSRST to push-pull on the Dicarlo jtag " ) ;
}
else
{
high_output | = nSRST ;
}
2008-12-13 06:25:50 +00:00
2008-12-11 19:03:17 +00:00
/* initialize high port */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x82 ; /* command "set data bits high byte" */
buf [ 1 ] = high_output ; /* value */
buf [ 2 ] = high_direction ; /* all outputs (xRST and xRSTnOE) */
2008-12-11 19:03:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-12-11 19:03:17 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'Dicarlo' layout " ) ;
2008-12-11 19:03:17 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-12-11 19:03:17 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int jtagkey_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t buf [ 3 ] ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
low_output = 0x08 ;
2008-02-25 17:48:04 +00:00
low_direction = 0x1b ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize low byte for jtag */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
2009-06-23 22:42:54 +00:00
buf [ 1 ] = low_output ; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
buf [ 2 ] = low_direction ; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'JTAGkey' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( strcmp ( layout - > name , " jtagkey " ) = = 0 )
{
2009-02-03 05:59:17 +00:00
nTRST = 0x01 ;
2008-02-25 17:48:04 +00:00
nTRSTnOE = 0x4 ;
2009-02-03 05:59:17 +00:00
nSRST = 0x02 ;
2008-02-25 17:48:04 +00:00
nSRSTnOE = 0x08 ;
}
2009-06-04 01:17:27 +00:00
else if ( ( strcmp ( layout - > name , " jtagkey_prototype_v1 " ) = = 0 )
| | ( strcmp ( layout - > name , " oocdlink " ) = = 0 ) )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
nTRST = 0x02 ;
2008-02-25 17:48:04 +00:00
nTRSTnOE = 0x1 ;
2009-02-03 05:59:17 +00:00
nSRST = 0x08 ;
2008-02-25 17:48:04 +00:00
nSRSTnOE = 0x04 ;
}
else
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " BUG: jtagkey_init called for non jtagkey layout " ) ;
2008-02-25 17:48:04 +00:00
exit ( - 1 ) ;
}
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
high_output = 0x0 ;
2008-02-25 17:48:04 +00:00
high_direction = 0x0f ;
2009-06-09 08:40:31 +00:00
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
2008-02-25 17:48:04 +00:00
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
{
high_output | = nTRSTnOE ;
high_output & = ~ nTRST ;
}
else
{
high_output & = ~ nTRSTnOE ;
high_output | = nTRST ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
{
high_output & = ~ nSRSTnOE ;
high_output | = nSRST ;
}
else
{
high_output | = nSRSTnOE ;
high_output & = ~ nSRST ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize high port */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x82 ; /* command "set data bits high byte" */
buf [ 1 ] = high_output ; /* value */
buf [ 2 ] = high_direction ; /* all outputs (xRST and xRSTnOE) */
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'JTAGkey' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int olimex_jtag_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t buf [ 3 ] ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
low_output = 0x08 ;
2008-02-25 17:48:04 +00:00
low_direction = 0x1b ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize low byte for jtag */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
2009-06-23 22:42:54 +00:00
buf [ 1 ] = low_output ; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
buf [ 2 ] = low_direction ; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2009-06-04 01:16:43 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'Olimex' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
nTRST = 0x01 ;
2008-02-25 17:48:04 +00:00
nTRSTnOE = 0x4 ;
2009-02-03 05:59:17 +00:00
nSRST = 0x02 ;
2008-02-25 17:48:04 +00:00
nSRSTnOE = 0x00 ; /* no output enable for nSRST */
2009-02-03 05:59:17 +00:00
high_output = 0x0 ;
2008-02-25 17:48:04 +00:00
high_direction = 0x0f ;
2009-06-09 08:40:31 +00:00
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
2008-02-25 17:48:04 +00:00
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
{
high_output | = nTRSTnOE ;
high_output & = ~ nTRST ;
}
else
{
high_output & = ~ nTRSTnOE ;
high_output | = nTRST ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " can't set nSRST to push-pull on the Olimex ARM-USB-OCD " ) ;
2008-02-25 17:48:04 +00:00
}
else
{
high_output & = ~ nSRST ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* turn red LED on */
high_output | = 0x08 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize high port */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x82 ; /* command "set data bits high byte" */
buf [ 1 ] = high_output ; /* value */
buf [ 2 ] = high_direction ; /* all outputs (xRST and xRSTnOE) */
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:16:43 +00:00
if ( ( ft2232_write ( buf , 3 , & bytes_written ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2009-06-04 01:16:43 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'Olimex' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int flyswatter_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t buf [ 3 ] ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
low_output = 0x18 ;
2008-02-25 17:48:04 +00:00
low_direction = 0xfb ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize low byte for jtag */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
2009-06-23 22:42:54 +00:00
buf [ 1 ] = low_output ; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
buf [ 2 ] = low_direction ; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE[12]=out, n[ST]srst = out */
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'flyswatter' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
nTRST = 0x10 ;
nTRSTnOE = 0x0 ; /* not output enable for nTRST */
nSRST = 0x20 ;
nSRSTnOE = 0x00 ; /* no output enable for nSRST */
2008-02-25 17:48:04 +00:00
2009-02-03 05:59:17 +00:00
high_output = 0x00 ;
2008-02-25 17:48:04 +00:00
high_direction = 0x0c ;
2009-03-01 21:07:44 +00:00
/* turn red LED3 on, LED2 off */
2008-02-25 17:48:04 +00:00
high_output | = 0x08 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize high port */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x82 ; /* command "set data bits high byte" */
buf [ 1 ] = high_output ; /* value */
buf [ 2 ] = high_direction ; /* all outputs (xRST and xRSTnOE) */
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'flyswatter' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int turtle_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t buf [ 3 ] ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
low_output = 0x08 ;
2008-02-25 17:48:04 +00:00
low_direction = 0x5b ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize low byte for jtag */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
2009-06-23 22:42:54 +00:00
buf [ 1 ] = low_output ; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
buf [ 2 ] = low_direction ; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'turtelizer2' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
nSRST = 0x40 ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
high_output = 0x00 ;
2008-02-25 17:48:04 +00:00
high_direction = 0x0C ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize high port */
buf [ 0 ] = 0x82 ; /* command "set data bits high byte" */
buf [ 1 ] = high_output ;
buf [ 2 ] = high_direction ;
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'turtelizer2' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int comstick_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t buf [ 3 ] ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
low_output = 0x08 ;
2008-02-25 17:48:04 +00:00
low_direction = 0x0b ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize low byte for jtag */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
2009-06-23 22:42:54 +00:00
buf [ 1 ] = low_output ; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
buf [ 2 ] = low_direction ; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'comstick' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
nTRST = 0x01 ;
nTRSTnOE = 0x00 ; /* no output enable for nTRST */
nSRST = 0x02 ;
nSRSTnOE = 0x00 ; /* no output enable for nSRST */
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
high_output = 0x03 ;
2008-02-25 17:48:04 +00:00
high_direction = 0x03 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize high port */
buf [ 0 ] = 0x82 ; /* command "set data bits high byte" */
buf [ 1 ] = high_output ;
buf [ 2 ] = high_direction ;
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'comstick' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int stm32stick_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t buf [ 3 ] ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
low_output = 0x88 ;
2008-02-25 17:48:04 +00:00
low_direction = 0x8b ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize low byte for jtag */
2009-02-03 05:59:17 +00:00
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
2009-06-23 22:42:54 +00:00
buf [ 1 ] = low_output ; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
buf [ 2 ] = low_direction ; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'stm32stick' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
nTRST = 0x01 ;
nTRSTnOE = 0x00 ; /* no output enable for nTRST */
nSRST = 0x80 ;
nSRSTnOE = 0x00 ; /* no output enable for nSRST */
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
high_output = 0x01 ;
2008-02-25 17:48:04 +00:00
high_direction = 0x03 ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
/* initialize high port */
buf [ 0 ] = 0x82 ; /* command "set data bits high byte" */
buf [ 1 ] = high_output ;
buf [ 2 ] = high_direction ;
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'stm32stick' layout " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int sheevaplug_init ( void )
2009-03-01 21:01:11 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t buf [ 3 ] ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2009-03-01 21:01:11 +00:00
low_output = 0x08 ;
low_direction = 0x1b ;
/* initialize low byte for jtag */
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
2009-06-23 22:42:54 +00:00
buf [ 1 ] = low_output ; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
buf [ 2 ] = low_direction ; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in */
2009-03-01 21:01:11 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
{
2009-05-18 17:41:27 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'sheevaplug' layout " ) ;
2009-03-01 21:01:11 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
nTRSTnOE = 0x1 ;
nTRST = 0x02 ;
nSRSTnOE = 0x4 ;
nSRST = 0x08 ;
high_output = 0x0 ;
high_direction = 0x0f ;
/* nTRST is always push-pull */
high_output & = ~ nTRSTnOE ;
high_output | = nTRST ;
/* nSRST is always open-drain */
high_output | = nSRSTnOE ;
high_output & = ~ nSRST ;
/* initialize high port */
buf [ 0 ] = 0x82 ; /* command "set data bits high byte" */
buf [ 1 ] = high_output ; /* value */
buf [ 2 ] = high_direction ; /* all outputs - xRST */
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
{
2009-05-18 17:41:27 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'sheevaplug' layout " ) ;
2009-03-01 21:01:11 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
return ERROR_OK ;
}
2009-06-04 01:17:27 +00:00
static int cortino_jtag_init ( void )
2009-05-27 11:58:19 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t buf [ 3 ] ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2009-05-27 11:58:19 +00:00
low_output = 0x08 ;
low_direction = 0x1b ;
/* initialize low byte for jtag */
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
2009-06-23 22:42:54 +00:00
buf [ 1 ] = low_output ; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
buf [ 2 ] = low_direction ; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
2009-05-27 11:58:19 +00:00
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2009-05-27 11:58:19 +00:00
{
LOG_ERROR ( " couldn't initialize FT2232 with 'cortino' layout " ) ;
return ERROR_JTAG_INIT_FAILED ;
}
nTRST = 0x01 ;
nTRSTnOE = 0x00 ; /* no output enable for nTRST */
nSRST = 0x02 ;
nSRSTnOE = 0x00 ; /* no output enable for nSRST */
high_output = 0x03 ;
high_direction = 0x03 ;
/* initialize high port */
buf [ 0 ] = 0x82 ; /* command "set data bits high byte" */
buf [ 1 ] = high_output ;
buf [ 2 ] = high_direction ;
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
2009-05-27 11:58:19 +00:00
{
LOG_ERROR ( " couldn't initialize FT2232 with 'stm32stick' layout " ) ;
return ERROR_JTAG_INIT_FAILED ;
}
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static void olimex_jtag_blink ( void )
2008-02-25 17:48:04 +00:00
{
/* Olimex ARM-USB-OCD has a LED connected to ACBUS3
* ACBUS3 is bit 3 of the GPIOH port
*/
if ( high_output & 0x08 )
{
/* set port pin high */
high_output & = 0x07 ;
}
else
{
/* set port pin low */
high_output | = 0x08 ;
}
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-04-21 05:29:23 +00:00
static void flyswatter_jtag_blink ( void )
2009-03-01 21:07:44 +00:00
{
/*
* Flyswatter has two LEDs connected to ACBUS2 and ACBUS3
*/
high_output ^ = 0x0c ;
2009-06-04 01:17:27 +00:00
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2009-03-01 21:07:44 +00:00
}
2009-04-21 05:29:23 +00:00
static void turtle_jtag_blink ( void )
2008-02-25 17:48:04 +00:00
{
2008-12-13 06:25:50 +00:00
/*
2009-02-03 05:59:17 +00:00
* Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3
2008-02-25 17:48:04 +00:00
*/
if ( high_output & 0x08 )
{
high_output = 0x04 ;
}
else
{
high_output = 0x08 ;
}
2008-12-13 06:25:50 +00:00
2009-06-04 01:17:27 +00:00
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-04-21 05:29:23 +00:00
static int ft2232_quit ( void )
2008-02-25 17:48:04 +00:00
{
# if BUILD_FT2232_FTD2XX == 1
FT_STATUS status ;
status = FT_Close ( ftdih ) ;
# elif BUILD_FT2232_LIBFTDI == 1
ftdi_usb_close ( & ftdic ) ;
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
ftdi_deinit ( & ftdic ) ;
# endif
free ( ft2232_buffer ) ;
ft2232_buffer = NULL ;
return ERROR_OK ;
}
2009-11-10 07:56:52 +00:00
COMMAND_HANDLER ( ft2232_handle_device_desc_command )
2008-02-25 17:48:04 +00:00
{
2009-03-07 15:51:26 +00:00
char * cp ;
char buf [ 200 ] ;
2009-11-15 12:57:12 +00:00
if ( CMD_ARGC = = 1 )
2008-02-25 17:48:04 +00:00
{
2009-11-15 16:15:59 +00:00
ft2232_device_desc = strdup ( CMD_ARGV [ 0 ] ) ;
2009-06-04 01:17:27 +00:00
cp = strchr ( ft2232_device_desc , 0 ) ;
2009-08-18 14:41:58 +00:00
/* under Win32, the FTD2XX driver appends an "A" to the end
* of the description , this examines the given desc
* and creates the ' missing ' _A or non_A variable . */
2009-06-04 01:17:27 +00:00
if ( ( cp [ - 1 ] = = ' A ' ) & & ( cp [ - 2 ] = = ' ' ) ) {
2009-08-18 14:41:58 +00:00
/* it was, so make this the "A" version. */
2009-03-07 15:51:26 +00:00
ft2232_device_desc_A = ft2232_device_desc ;
2009-08-18 14:41:58 +00:00
/* and *CREATE* the non-A version. */
2009-06-04 01:17:27 +00:00
strcpy ( buf , ft2232_device_desc ) ;
cp = strchr ( buf , 0 ) ;
2009-03-07 15:51:26 +00:00
cp [ - 2 ] = 0 ;
2009-06-04 01:17:27 +00:00
ft2232_device_desc = strdup ( buf ) ;
2009-03-07 15:51:26 +00:00
} else {
2009-08-18 14:41:58 +00:00
/* <space > A not defined
* so create it */
2009-06-04 01:17:27 +00:00
sprintf ( buf , " %s A " , ft2232_device_desc ) ;
ft2232_device_desc_A = strdup ( buf ) ;
2009-03-07 15:51:26 +00:00
}
2008-02-25 17:48:04 +00:00
}
else
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " expected exactly one argument to ft2232_device_desc <description> " ) ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-11-10 07:56:52 +00:00
COMMAND_HANDLER ( ft2232_handle_serial_command )
2008-02-25 17:48:04 +00:00
{
2009-11-15 12:57:12 +00:00
if ( CMD_ARGC = = 1 )
2008-02-25 17:48:04 +00:00
{
2009-11-15 16:15:59 +00:00
ft2232_serial = strdup ( CMD_ARGV [ 0 ] ) ;
2008-02-25 17:48:04 +00:00
}
else
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " expected exactly one argument to ft2232_serial <serial-number> " ) ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-11-10 07:56:52 +00:00
COMMAND_HANDLER ( ft2232_handle_layout_command )
2008-02-25 17:48:04 +00:00
{
2009-11-15 12:57:12 +00:00
if ( CMD_ARGC = = 0 )
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
2009-11-15 16:15:59 +00:00
ft2232_layout = malloc ( strlen ( CMD_ARGV [ 0 ] ) + 1 ) ;
strcpy ( ft2232_layout , CMD_ARGV [ 0 ] ) ;
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-11-10 07:56:52 +00:00
COMMAND_HANDLER ( ft2232_handle_vid_pid_command )
2008-02-25 17:48:04 +00:00
{
2009-11-15 12:57:12 +00:00
if ( CMD_ARGC > MAX_USB_IDS * 2 )
2009-02-03 05:59:17 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_WARNING ( " ignoring extra IDs in ft2232_vid_pid "
2009-02-03 05:59:17 +00:00
" (maximum is %d pairs) " , MAX_USB_IDS ) ;
2009-11-15 12:57:12 +00:00
CMD_ARGC = MAX_USB_IDS * 2 ;
2008-02-25 17:48:04 +00:00
}
2009-11-15 12:57:12 +00:00
if ( CMD_ARGC < 2 | | ( CMD_ARGC & 1 ) )
2008-02-25 17:48:04 +00:00
{
2008-03-25 15:45:17 +00:00
LOG_WARNING ( " incomplete ft2232_vid_pid configuration directive " ) ;
2009-11-15 12:57:12 +00:00
if ( CMD_ARGC < 2 )
2009-06-12 01:40:48 +00:00
return ERROR_COMMAND_SYNTAX_ERROR ;
2009-08-18 14:41:58 +00:00
/* remove the incomplete trailing id */
2009-11-15 12:57:12 +00:00
CMD_ARGC - = 1 ;
2008-02-25 17:48:04 +00:00
}
2009-11-10 08:02:18 +00:00
unsigned i ;
2009-11-15 12:57:12 +00:00
for ( i = 0 ; i < CMD_ARGC ; i + = 2 )
2009-02-03 05:59:17 +00:00
{
2009-11-15 16:15:59 +00:00
COMMAND_PARSE_NUMBER ( u16 , CMD_ARGV [ i ] , ft2232_vid [ i > > 1 ] ) ;
COMMAND_PARSE_NUMBER ( u16 , CMD_ARGV [ i + 1 ] , ft2232_pid [ i > > 1 ] ) ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
/*
* Explicitly terminate , in case there are multiples instances of
* ft2232_vid_pid .
*/
ft2232_vid [ i > > 1 ] = ft2232_pid [ i > > 1 ] = 0 ;
2009-11-10 08:02:18 +00:00
return ERROR_OK ;
2008-02-25 17:48:04 +00:00
}
2009-11-10 07:56:52 +00:00
COMMAND_HANDLER ( ft2232_handle_latency_command )
2008-02-25 17:48:04 +00:00
{
2009-11-15 12:57:12 +00:00
if ( CMD_ARGC = = 1 )
2008-02-25 17:48:04 +00:00
{
2009-11-15 16:15:59 +00:00
ft2232_latency = atoi ( CMD_ARGV [ 0 ] ) ;
2008-02-25 17:48:04 +00:00
}
else
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " expected exactly one argument to ft2232_latency <ms> " ) ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-01-09 07:42:45 +00:00
2009-11-13 14:15:31 +00:00
static int ft2232_stableclocks ( int num_cycles , struct jtag_command * cmd )
2009-01-09 07:42:45 +00:00
{
int retval = 0 ;
2009-01-23 07:10:11 +00:00
/* 7 bits of either ones or zeros. */
2009-06-18 07:07:12 +00:00
uint8_t tms = ( tap_get_state ( ) = = TAP_RESET ? 0x7F : 0x00 ) ;
2009-01-23 07:10:11 +00:00
2009-01-09 07:42:45 +00:00
while ( num_cycles > 0 )
{
/* the command 0x4b, "Clock Data to TMS/CS Pin (no Read)" handles
* at most 7 bits per invocation . Here we invoke it potentially
* several times .
*/
int bitcount_per_command = ( num_cycles > 7 ) ? 7 : num_cycles ;
if ( ft2232_buffer_size + 3 > = FT2232_BUFFER_SIZE )
{
if ( ft2232_send_and_recv ( first_unsent , cmd ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
first_unsent = cmd ;
}
2009-05-18 17:41:27 +00:00
/* there are no state transitions in this code, so omit state tracking */
2009-01-09 07:42:45 +00:00
/* command "Clock Data to TMS/CS Pin (no Read)" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x4b ) ;
2009-01-09 07:42:45 +00:00
/* scan 7 bit */
2009-06-04 01:17:27 +00:00
buffer_write ( bitcount_per_command - 1 ) ;
2009-01-09 07:42:45 +00:00
2009-01-23 07:10:11 +00:00
/* TMS data bits are either all zeros or ones to stay in the current stable state */
2009-06-04 01:17:27 +00:00
buffer_write ( tms ) ;
2009-01-09 07:42:45 +00:00
require_send = 1 ;
num_cycles - = bitcount_per_command ;
}
return retval ;
}
2009-04-29 07:38:35 +00:00
/* ---------------------------------------------------------------------
* Support for IceBear JTAG adapter from Section5 :
2009-06-04 01:17:27 +00:00
* http : //section5.ch/icebear
2009-04-29 07:38:35 +00:00
*
* Author : Sten , debian @ sansys - electronic . com
*/
/* Icebear pin layout
*
* ADBUS5 ( nEMU ) nSRST | 2 1 | GND ( 10 k - > VCC )
* GND GND | 4 3 | n . c .
* ADBUS3 TMS | 6 5 | ADBUS6 VCC
* ADBUS0 TCK | 8 7 | ADBUS7 ( GND )
* ADBUS4 nTRST | 10 9 | ACBUS0 ( GND )
* ADBUS1 TDI | 12 11 | ACBUS1 ( GND )
* ADBUS2 TDO | 14 13 | GND GND
*
* ADBUS0 O L TCK ACBUS0 GND
* ADBUS1 O L TDI ACBUS1 GND
* ADBUS2 I TDO ACBUS2 n . c .
* ADBUS3 O H TMS ACBUS3 n . c .
* ADBUS4 O H nTRST
* ADBUS5 O H nSRST
* ADBUS6 - VCC
* ADBUS7 - GND
*/
static int icebear_jtag_init ( void ) {
2009-06-18 07:07:12 +00:00
uint8_t buf [ 3 ] ;
2009-06-18 07:11:11 +00:00
uint32_t bytes_written ;
2009-04-29 07:38:35 +00:00
low_direction = 0x0b ; /* output: TCK TDI TMS; input: TDO */
low_output = 0x08 ; /* high: TMS; low: TCK TDI */
nTRST = 0x10 ;
nSRST = 0x20 ;
2009-06-09 08:40:31 +00:00
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
2009-04-29 07:38:35 +00:00
if ( ( jtag_reset_config & RESET_TRST_OPEN_DRAIN ) ! = 0 ) {
low_direction & = ~ nTRST ; /* nTRST high impedance */
}
else {
low_direction | = nTRST ;
low_output | = nTRST ;
}
low_direction | = nSRST ;
low_output | = nSRST ;
/* initialize low byte for jtag */
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
buf [ 1 ] = low_output ;
buf [ 2 ] = low_direction ;
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) ) {
2009-04-29 07:38:35 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'IceBear' layout (low) " ) ;
return ERROR_JTAG_INIT_FAILED ;
}
high_output = 0x0 ;
high_direction = 0x00 ;
/* initialize high port */
buf [ 0 ] = 0x82 ; /* command "set data bits high byte" */
buf [ 1 ] = high_output ; /* value */
buf [ 2 ] = high_direction ; /* all outputs (xRST and xRSTnOE) */
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2009-06-04 01:17:27 +00:00
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) ) {
2009-04-29 07:38:35 +00:00
LOG_ERROR ( " couldn't initialize FT2232 with 'IceBear' layout (high) " ) ;
return ERROR_JTAG_INIT_FAILED ;
}
return ERROR_OK ;
}
static void icebear_jtag_reset ( int trst , int srst ) {
if ( trst = = 1 ) {
low_direction | = nTRST ;
low_output & = ~ nTRST ;
}
else if ( trst = = 0 ) {
2009-06-09 08:40:31 +00:00
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
2009-04-29 07:38:35 +00:00
if ( ( jtag_reset_config & RESET_TRST_OPEN_DRAIN ) ! = 0 )
low_direction & = ~ nTRST ;
else
low_output | = nTRST ;
}
if ( srst = = 1 ) {
low_output & = ~ nSRST ;
}
else if ( srst = = 0 ) {
low_output | = nSRST ;
}
/* command "set data bits low byte" */
2009-06-04 01:17:27 +00:00
buffer_write ( 0x80 ) ;
buffer_write ( low_output ) ;
buffer_write ( low_direction ) ;
2009-05-18 17:41:27 +00:00
2009-04-29 07:38:35 +00:00
LOG_DEBUG ( " trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x " , trst , srst , low_output , low_direction ) ;
}
2009-10-27 19:40:24 +00:00
/* ---------------------------------------------------------------------
* Support for Signalyzer H2 and Signalyzer H4
* JTAG adapter from Xverve Technologies Inc .
* http : //www.signalyzer.com or http://www.xverve.com
*
* Author : Oleg Seiljus , oleg @ signalyzer . com
*/
static unsigned char signalyzer_h_side ;
static unsigned int signalyzer_h_adapter_type ;
static int signalyzer_h_ctrl_write ( int address , unsigned short value ) ;
# if BUILD_FT2232_FTD2XX == 1
static int signalyzer_h_ctrl_read ( int address , unsigned short * value ) ;
# endif
# define SIGNALYZER_COMMAND_ADDR 128
# define SIGNALYZER_DATA_BUFFER_ADDR 129
# define SIGNALYZER_COMMAND_VERSION 0x41
# define SIGNALYZER_COMMAND_RESET 0x42
# define SIGNALYZER_COMMAND_POWERCONTROL_GET 0x50
# define SIGNALYZER_COMMAND_POWERCONTROL_SET 0x51
# define SIGNALYZER_COMMAND_PWM_SET 0x52
# define SIGNALYZER_COMMAND_LED_SET 0x53
# define SIGNALYZER_COMMAND_ADC 0x54
# define SIGNALYZER_COMMAND_GPIO_STATE 0x55
# define SIGNALYZER_COMMAND_GPIO_MODE 0x56
# define SIGNALYZER_COMMAND_GPIO_PORT 0x57
# define SIGNALYZER_COMMAND_I2C 0x58
# define SIGNALYZER_CHAN_A 1
# define SIGNALYZER_CHAN_B 2
/* LEDS use channel C */
# define SIGNALYZER_CHAN_C 4
# define SIGNALYZER_LED_GREEN 1
# define SIGNALYZER_LED_RED 2
# define SIGNALYZER_MODULE_TYPE_EM_LT16_A 0x0301
# define SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG 0x0302
# define SIGNALYZER_MODULE_TYPE_EM_JTAG 0x0303
# define SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P 0x0304
# define SIGNALYZER_MODULE_TYPE_EM_JTAG_P 0x0305
static int signalyzer_h_ctrl_write ( int address , unsigned short value )
{
# if BUILD_FT2232_FTD2XX == 1
return FT_WriteEE ( ftdih , address , value ) ;
# elif BUILD_FT2232_LIBFTDI == 1
return 0 ;
# endif
}
# if BUILD_FT2232_FTD2XX == 1
static int signalyzer_h_ctrl_read ( int address , unsigned short * value )
{
return FT_ReadEE ( ftdih , address , value ) ;
}
# endif
static int signalyzer_h_led_set ( unsigned char channel , unsigned char led ,
int on_time_ms , int off_time_ms , unsigned char cycles )
{
unsigned char on_time ;
unsigned char off_time ;
if ( on_time_ms < 0xFFFF )
on_time = ( unsigned char ) ( on_time_ms / 62 ) ;
else
on_time = 0xFF ;
off_time = ( unsigned char ) ( off_time_ms / 62 ) ;
# if BUILD_FT2232_FTD2XX == 1
FT_STATUS status ;
if ( ( status = signalyzer_h_ctrl_write ( SIGNALYZER_DATA_BUFFER_ADDR ,
( ( uint32_t ) ( channel < < 8 ) | led ) ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
( SIGNALYZER_DATA_BUFFER_ADDR + 1 ) ,
( ( uint32_t ) ( on_time < < 8 ) | off_time ) ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
( SIGNALYZER_DATA_BUFFER_ADDR + 2 ) ,
( ( uint32_t ) cycles ) ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write ( SIGNALYZER_COMMAND_ADDR ,
SIGNALYZER_COMMAND_LED_SET ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
return ERROR_OK ;
# elif BUILD_FT2232_LIBFTDI == 1
int retval ;
if ( ( retval = signalyzer_h_ctrl_write ( SIGNALYZER_DATA_BUFFER_ADDR ,
( ( uint32_t ) ( channel < < 8 ) | led ) ) ) < 0 )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %s " ,
ftdi_get_error_string ( & ftdic ) ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( retval = signalyzer_h_ctrl_write (
( SIGNALYZER_DATA_BUFFER_ADDR + 1 ) ,
( ( uint32_t ) ( on_time < < 8 ) | off_time ) ) ) < 0 )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %s " ,
ftdi_get_error_string ( & ftdic ) ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( retval = signalyzer_h_ctrl_write (
( SIGNALYZER_DATA_BUFFER_ADDR + 2 ) ,
( uint32_t ) cycles ) ) < 0 )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %s " ,
ftdi_get_error_string ( & ftdic ) ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( retval = signalyzer_h_ctrl_write ( SIGNALYZER_COMMAND_ADDR ,
SIGNALYZER_COMMAND_LED_SET ) ) < 0 )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %s " ,
ftdi_get_error_string ( & ftdic ) ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
return ERROR_OK ;
# endif
}
static int signalyzer_h_init ( void )
{
# if BUILD_FT2232_FTD2XX == 1
FT_STATUS status ;
int i ;
# endif
char * end_of_desc ;
2009-11-05 05:41:08 +00:00
uint16_t read_buf [ 12 ] = { 0 } ;
2009-10-27 19:40:24 +00:00
uint8_t buf [ 3 ] ;
uint32_t bytes_written ;
/* turn on center green led */
signalyzer_h_led_set ( SIGNALYZER_CHAN_C , SIGNALYZER_LED_GREEN ,
0xFFFF , 0x00 , 0x00 ) ;
/* determine what channel config wants to open
* TODO : change me . . . current implementation is made to work
* with openocd description parsing .
*/
end_of_desc = strrchr ( ft2232_device_desc , 0x00 ) ;
if ( end_of_desc )
{
signalyzer_h_side = * ( end_of_desc - 1 ) ;
if ( signalyzer_h_side = = ' B ' )
signalyzer_h_side = SIGNALYZER_CHAN_B ;
else
signalyzer_h_side = SIGNALYZER_CHAN_A ;
}
else
{
LOG_ERROR ( " No Channel was specified " ) ;
return ERROR_FAIL ;
}
signalyzer_h_led_set ( signalyzer_h_side , SIGNALYZER_LED_GREEN ,
1000 , 1000 , 0xFF ) ;
# if BUILD_FT2232_FTD2XX == 1
/* read signalyzer versionining information */
if ( ( status = signalyzer_h_ctrl_write ( SIGNALYZER_COMMAND_ADDR ,
SIGNALYZER_COMMAND_VERSION ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
for ( i = 0 ; i < 10 ; i + + )
{
if ( ( status = signalyzer_h_ctrl_read (
( SIGNALYZER_DATA_BUFFER_ADDR + i ) ,
& read_buf [ i ] ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_read returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
}
LOG_INFO ( " Signalyzer: ID info: { %.4x %.4x %.4x %.4x %.4x %.4x %.4x } " ,
read_buf [ 0 ] , read_buf [ 1 ] , read_buf [ 2 ] , read_buf [ 3 ] ,
read_buf [ 4 ] , read_buf [ 5 ] , read_buf [ 6 ] ) ;
/* set gpio register */
if ( ( status = signalyzer_h_ctrl_write ( SIGNALYZER_DATA_BUFFER_ADDR ,
( uint32_t ) ( signalyzer_h_side < < 8 ) ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write ( SIGNALYZER_DATA_BUFFER_ADDR + 1 ,
0x0404 ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write ( SIGNALYZER_COMMAND_ADDR ,
SIGNALYZER_COMMAND_GPIO_STATE ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
/* read adapter type information */
if ( ( status = signalyzer_h_ctrl_write ( SIGNALYZER_DATA_BUFFER_ADDR ,
( ( uint32_t ) ( signalyzer_h_side < < 8 ) | 0x01 ) ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
( SIGNALYZER_DATA_BUFFER_ADDR + 1 ) , 0xA000 ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
( SIGNALYZER_DATA_BUFFER_ADDR + 2 ) , 0x0008 ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write ( SIGNALYZER_COMMAND_ADDR ,
SIGNALYZER_COMMAND_I2C ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
usleep ( 100000 ) ;
if ( ( status = signalyzer_h_ctrl_read ( SIGNALYZER_COMMAND_ADDR ,
& read_buf [ 0 ] ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_read returned: %lu " , status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( read_buf [ 0 ] ! = 0x0498 )
signalyzer_h_adapter_type = 0x0000 ;
else
{
for ( i = 0 ; i < 4 ; i + + )
{
if ( ( status = signalyzer_h_ctrl_read (
( SIGNALYZER_DATA_BUFFER_ADDR + i ) ,
& read_buf [ i ] ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_read returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
}
signalyzer_h_adapter_type = read_buf [ 0 ] ;
}
# elif BUILD_FT2232_LIBFTDI == 1
/* currently libftdi does not allow reading individual eeprom
* locations , therefore adapter type cannot be detected .
* override with most common type
*/
signalyzer_h_adapter_type = SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG ;
# endif
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
/* ADAPTOR: EM_LT16_A */
if ( signalyzer_h_adapter_type = = SIGNALYZER_MODULE_TYPE_EM_LT16_A )
{
LOG_INFO ( " Signalyzer: EM-LT (16-channel level translator) "
" detected. (HW: %2x). " , ( read_buf [ 1 ] > > 8 ) ) ;
nTRST = 0x10 ;
nTRSTnOE = 0x10 ;
nSRST = 0x20 ;
nSRSTnOE = 0x20 ;
low_output = 0x08 ;
low_direction = 0x1b ;
high_output = 0x0 ;
high_direction = 0x0 ;
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
{
low_direction & = ~ nTRSTnOE ; /* nTRST input */
low_output & = ~ nTRST ; /* nTRST = 0 */
}
else
{
low_direction | = nTRSTnOE ; /* nTRST output */
low_output | = nTRST ; /* nTRST = 1 */
}
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
{
low_direction | = nSRSTnOE ; /* nSRST output */
low_output | = nSRST ; /* nSRST = 1 */
}
else
{
low_direction & = ~ nSRSTnOE ; /* nSRST input */
low_output & = ~ nSRST ; /* nSRST = 0 */
}
# if BUILD_FT2232_FTD2XX == 1
/* enable power to the module */
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_DATA_BUFFER_ADDR ,
( ( uint32_t ) ( signalyzer_h_side < < 8 ) | 0x01 ) ) )
! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write ( SIGNALYZER_COMMAND_ADDR ,
SIGNALYZER_COMMAND_POWERCONTROL_SET ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
/* set gpio mode register */
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_DATA_BUFFER_ADDR ,
( uint32_t ) ( signalyzer_h_side < < 8 ) ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_DATA_BUFFER_ADDR + 1 , 0x0000 ) )
! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write ( SIGNALYZER_COMMAND_ADDR ,
SIGNALYZER_COMMAND_GPIO_MODE ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
/* set gpio register */
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_DATA_BUFFER_ADDR ,
( uint32_t ) ( signalyzer_h_side < < 8 ) ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_DATA_BUFFER_ADDR + 1 , 0x4040 ) )
! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_COMMAND_ADDR ,
SIGNALYZER_COMMAND_GPIO_STATE ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
# endif
}
/* ADAPTOR: EM_ARM_JTAG, EM_ARM_JTAG_P, EM_JTAG, EM_JTAG_P */
else if ( ( signalyzer_h_adapter_type = = SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG ) | |
( signalyzer_h_adapter_type = = SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P ) | |
( signalyzer_h_adapter_type = = SIGNALYZER_MODULE_TYPE_EM_JTAG ) | |
( signalyzer_h_adapter_type = = SIGNALYZER_MODULE_TYPE_EM_JTAG_P ) )
{
if ( signalyzer_h_adapter_type
= = SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG )
LOG_INFO ( " Signalyzer: EM-ARM-JTAG (ARM JTAG) "
" detected. (HW: %2x). " , ( read_buf [ 1 ] > > 8 ) ) ;
else if ( signalyzer_h_adapter_type
= = SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P )
LOG_INFO ( " Signalyzer: EM-ARM-JTAG_P "
" (ARM JTAG with PSU) detected. (HW: %2x). " ,
( read_buf [ 1 ] > > 8 ) ) ;
else if ( signalyzer_h_adapter_type
= = SIGNALYZER_MODULE_TYPE_EM_JTAG )
LOG_INFO ( " Signalyzer: EM-JTAG (Generic JTAG) "
" detected. (HW: %2x). " , ( read_buf [ 1 ] > > 8 ) ) ;
else if ( signalyzer_h_adapter_type
= = SIGNALYZER_MODULE_TYPE_EM_JTAG_P )
LOG_INFO ( " Signalyzer: EM-JTAG-P "
" (Generic JTAG with PSU) detected. (HW: %2x). " ,
( read_buf [ 1 ] > > 8 ) ) ;
nTRST = 0x02 ;
nTRSTnOE = 0x04 ;
nSRST = 0x08 ;
nSRSTnOE = 0x10 ;
low_output = 0x08 ;
low_direction = 0x1b ;
high_output = 0x0 ;
high_direction = 0x1f ;
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
{
high_output | = nTRSTnOE ;
high_output & = ~ nTRST ;
}
else
{
high_output & = ~ nTRSTnOE ;
high_output | = nTRST ;
}
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
{
high_output & = ~ nSRSTnOE ;
high_output | = nSRST ;
}
else
{
high_output | = nSRSTnOE ;
high_output & = ~ nSRST ;
}
# if BUILD_FT2232_FTD2XX == 1
/* enable power to the module */
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_DATA_BUFFER_ADDR ,
( ( uint32_t ) ( signalyzer_h_side < < 8 ) | 0x01 ) ) )
! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_COMMAND_ADDR ,
SIGNALYZER_COMMAND_POWERCONTROL_SET ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
/* set gpio mode register (IO_16 and IO_17 set as analog
* inputs , other is gpio )
*/
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_DATA_BUFFER_ADDR ,
( uint32_t ) ( signalyzer_h_side < < 8 ) ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_DATA_BUFFER_ADDR + 1 , 0x0060 ) )
! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_COMMAND_ADDR ,
SIGNALYZER_COMMAND_GPIO_MODE ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
/* set gpio register (all inputs, for -P modules,
* PSU will be turned off )
*/
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_DATA_BUFFER_ADDR ,
( uint32_t ) ( signalyzer_h_side < < 8 ) ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_DATA_BUFFER_ADDR + 1 , 0x0000 ) )
! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
if ( ( status = signalyzer_h_ctrl_write (
SIGNALYZER_COMMAND_ADDR ,
SIGNALYZER_COMMAND_GPIO_STATE ) ) ! = FT_OK )
{
LOG_ERROR ( " signalyzer_h_ctrl_write returned: %lu " ,
status ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
# endif
}
else if ( signalyzer_h_adapter_type = = 0x0000 )
{
LOG_INFO ( " Signalyzer: No external modules were detected. " ) ;
nTRST = 0x10 ;
nTRSTnOE = 0x10 ;
nSRST = 0x20 ;
nSRSTnOE = 0x20 ;
low_output = 0x08 ;
low_direction = 0x1b ;
high_output = 0x0 ;
high_direction = 0x0 ;
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
{
low_direction & = ~ nTRSTnOE ; /* nTRST input */
low_output & = ~ nTRST ; /* nTRST = 0 */
}
else
{
low_direction | = nTRSTnOE ; /* nTRST output */
low_output | = nTRST ; /* nTRST = 1 */
}
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
{
low_direction | = nSRSTnOE ; /* nSRST output */
low_output | = nSRST ; /* nSRST = 1 */
}
else
{
low_direction & = ~ nSRSTnOE ; /* nSRST input */
low_output & = ~ nSRST ; /* nSRST = 0 */
}
}
else
{
LOG_ERROR ( " Unknown module type is detected: %.4x " ,
signalyzer_h_adapter_type ) ;
return ERROR_JTAG_DEVICE_ERROR ;
}
/* initialize low byte of controller for jtag operation */
buf [ 0 ] = 0x80 ;
buf [ 1 ] = low_output ;
buf [ 2 ] = low_direction ;
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK )
| | ( bytes_written ! = 3 ) )
{
LOG_ERROR ( " couldn't initialize Signalyzer-H layout " ) ;
return ERROR_JTAG_INIT_FAILED ;
}
# if BUILD_FT2232_FTD2XX == 1
if ( ftdi_device = = FT_DEVICE_2232H )
{
/* initialize high byte of controller for jtag operation */
buf [ 0 ] = 0x82 ;
buf [ 1 ] = high_output ;
buf [ 2 ] = high_direction ;
if ( ( ft2232_write ( buf , 3 , & bytes_written ) ! = ERROR_OK )
| | ( bytes_written ! = 3 ) )
{
LOG_ERROR ( " couldn't initialize Signalyzer-H layout " ) ;
return ERROR_JTAG_INIT_FAILED ;
}
}
# elif BUILD_FT2232_LIBFTDI == 1
if ( ftdi_device = = TYPE_2232H )
{
/* initialize high byte of controller for jtag operation */
buf [ 0 ] = 0x82 ;
buf [ 1 ] = high_output ;
buf [ 2 ] = high_direction ;
if ( ( ft2232_write ( buf , 3 , & bytes_written ) ! = ERROR_OK )
| | ( bytes_written ! = 3 ) )
{
LOG_ERROR ( " couldn't initialize Signalyzer-H layout " ) ;
return ERROR_JTAG_INIT_FAILED ;
}
}
# endif
return ERROR_OK ;
}
static void signalyzer_h_reset ( int trst , int srst )
{
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
/* ADAPTOR: EM_LT16_A */
if ( signalyzer_h_adapter_type = = SIGNALYZER_MODULE_TYPE_EM_LT16_A )
{
if ( trst = = 1 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
/* switch to output pin (output is low) */
low_direction | = nTRSTnOE ;
else
/* switch output low */
low_output & = ~ nTRST ;
}
else if ( trst = = 0 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
/* switch to input pin (high-Z + internal
* and external pullup ) */
low_direction & = ~ nTRSTnOE ;
else
/* switch output high */
low_output | = nTRST ;
}
if ( srst = = 1 )
{
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
/* switch output low */
low_output & = ~ nSRST ;
else
/* switch to output pin (output is low) */
low_direction | = nSRSTnOE ;
}
else if ( srst = = 0 )
{
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
/* switch output high */
low_output | = nSRST ;
else
/* switch to input pin (high-Z) */
low_direction & = ~ nSRSTnOE ;
}
/* command "set data bits low byte" */
buffer_write ( 0x80 ) ;
buffer_write ( low_output ) ;
buffer_write ( low_direction ) ;
LOG_DEBUG ( " trst: %i, srst: %i, low_output: 0x%2.2x, "
" low_direction: 0x%2.2x " ,
trst , srst , low_output , low_direction ) ;
}
/* ADAPTOR: EM_ARM_JTAG, EM_ARM_JTAG_P, EM_JTAG, EM_JTAG_P */
else if ( ( signalyzer_h_adapter_type = = SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG ) | |
( signalyzer_h_adapter_type = = SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P ) | |
( signalyzer_h_adapter_type = = SIGNALYZER_MODULE_TYPE_EM_JTAG ) | |
( signalyzer_h_adapter_type = = SIGNALYZER_MODULE_TYPE_EM_JTAG_P ) )
{
if ( trst = = 1 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
high_output & = ~ nTRSTnOE ;
else
high_output & = ~ nTRST ;
}
else if ( trst = = 0 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
high_output | = nTRSTnOE ;
else
high_output | = nTRST ;
}
if ( srst = = 1 )
{
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
high_output & = ~ nSRST ;
else
high_output & = ~ nSRSTnOE ;
}
else if ( srst = = 0 )
{
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
high_output | = nSRST ;
else
high_output | = nSRSTnOE ;
}
/* command "set data bits high byte" */
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
LOG_INFO ( " trst: %i, srst: %i, high_output: 0x%2.2x, "
" high_direction: 0x%2.2x " ,
trst , srst , high_output , high_direction ) ;
}
else if ( signalyzer_h_adapter_type = = 0x0000 )
{
if ( trst = = 1 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
/* switch to output pin (output is low) */
low_direction | = nTRSTnOE ;
else
/* switch output low */
low_output & = ~ nTRST ;
}
else if ( trst = = 0 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
/* switch to input pin (high-Z + internal
* and external pullup ) */
low_direction & = ~ nTRSTnOE ;
else
/* switch output high */
low_output | = nTRST ;
}
if ( srst = = 1 )
{
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
/* switch output low */
low_output & = ~ nSRST ;
else
/* switch to output pin (output is low) */
low_direction | = nSRSTnOE ;
}
else if ( srst = = 0 )
{
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
/* switch output high */
low_output | = nSRST ;
else
/* switch to input pin (high-Z) */
low_direction & = ~ nSRSTnOE ;
}
/* command "set data bits low byte" */
buffer_write ( 0x80 ) ;
buffer_write ( low_output ) ;
buffer_write ( low_direction ) ;
LOG_DEBUG ( " trst: %i, srst: %i, low_output: 0x%2.2x, "
" low_direction: 0x%2.2x " ,
trst , srst , low_output , low_direction ) ;
}
}
static void signalyzer_h_blink ( void )
{
signalyzer_h_led_set ( signalyzer_h_side , SIGNALYZER_LED_RED , 100 , 0 , 1 ) ;
}
2009-11-05 05:20:44 +00:00
/********************************************************************
* Support for KT - LINK
* JTAG adapter from KRISTECH
* http : //www.kristech.eu
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int ktlink_init ( void )
{
2009-11-05 05:41:08 +00:00
uint8_t buf [ 3 ] ;
uint32_t bytes_written ;
uint8_t swd_en = 0x20 ; //0x20 SWD disable, 0x00 SWD enable (ADBUS5)
low_output = 0x08 | swd_en ; // value; TMS=1,TCK=0,TDI=0,SWD=swd_en
low_direction = 0x3B ; // out=1; TCK/TDI/TMS=out,TDO=in,SWD=out,RTCK=in,SRSTIN=in
// initialize low port
buf [ 0 ] = 0x80 ; // command "set data bits low byte"
buf [ 1 ] = low_output ;
buf [ 2 ] = low_direction ;
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
{
LOG_ERROR ( " couldn't initialize FT2232 with 'ktlink' layout " ) ;
return ERROR_JTAG_INIT_FAILED ;
}
nTRST = 0x01 ;
nSRST = 0x02 ;
nTRSTnOE = 0x04 ;
nSRSTnOE = 0x08 ;
high_output = 0x80 ; // turn LED on
high_direction = 0xFF ; // all outputs
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN ) {
high_output | = nTRSTnOE ;
high_output & = ~ nTRST ;
} else {
high_output & = ~ nTRSTnOE ;
high_output | = nTRST ;
}
if ( jtag_reset_config & RESET_SRST_PUSH_PULL ) {
high_output & = ~ nSRSTnOE ;
high_output | = nSRST ;
} else {
high_output | = nSRSTnOE ;
high_output & = ~ nSRST ;
}
// initialize high port
buf [ 0 ] = 0x82 ; // command "set data bits high byte"
buf [ 1 ] = high_output ; // value
buf [ 2 ] = high_direction ;
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) )
{
LOG_ERROR ( " couldn't initialize FT2232 with 'ktlink' layout " ) ;
return ERROR_JTAG_INIT_FAILED ;
}
return ERROR_OK ;
2009-11-05 05:20:44 +00:00
}
static void ktlink_reset ( int trst , int srst )
{
2009-11-05 05:41:08 +00:00
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
if ( trst = = 1 ) {
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
high_output & = ~ nTRSTnOE ;
else
high_output & = ~ nTRST ;
} else if ( trst = = 0 ) {
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
high_output | = nTRSTnOE ;
else
high_output | = nTRST ;
}
if ( srst = = 1 ) {
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
high_output & = ~ nSRST ;
else
high_output & = ~ nSRSTnOE ;
} else if ( srst = = 0 ) {
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
high_output | = nSRST ;
else
high_output | = nSRSTnOE ;
}
buffer_write ( 0x82 ) ; // command "set data bits high byte"
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
LOG_DEBUG ( " trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x " , trst , srst , high_output , high_direction ) ;
2009-11-05 05:20:44 +00:00
}
static void ktlink_blink ( void )
{
2009-11-05 05:41:08 +00:00
/* LED connected to ACBUS7 */
if ( high_output & 0x80 )
high_output & = 0x7F ;
else
high_output | = 0x80 ;
2009-11-05 05:20:44 +00:00
2009-11-05 05:41:08 +00:00
buffer_write ( 0x82 ) ; // command "set data bits high byte"
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2009-11-05 05:20:44 +00:00
}
2009-11-10 05:21:06 +00:00
2009-11-21 04:06:50 +00:00
static const struct command_registration ft2232_command_handlers [ ] = {
{
. name = " ft2232_device_desc " ,
. handler = & ft2232_handle_device_desc_command ,
. mode = COMMAND_CONFIG ,
. help = " set the USB device description of the FTDI FT2232 device " ,
. usage = " <description> " ,
} ,
{
. name = " ft2232_serial " ,
. handler = & ft2232_handle_serial_command ,
. mode = COMMAND_CONFIG ,
. help = " set the serial number of the FTDI FT2232 device " ,
. usage = " <serial#> " ,
} ,
{
. name = " ft2232_layout " ,
. handler = & ft2232_handle_layout_command ,
. mode = COMMAND_CONFIG ,
. help = " set the layout of the FT2232 GPIO signals used "
" to control output-enables and reset signals " ,
. usage = " <layout> " ,
} ,
{
. name = " ft2232_vid_pid " ,
. handler = & ft2232_handle_vid_pid_command ,
. mode = COMMAND_CONFIG ,
. help = " the vendor ID and product ID of the FTDI FT2232 device " ,
. usage = " <vid> <pid> [...] " ,
} ,
{
. name = " ft2232_latency " ,
. handler = & ft2232_handle_latency_command ,
. mode = COMMAND_CONFIG ,
. help = " set the FT2232 latency timer to a new value " ,
. usage = " <vid> <pid> [...] " ,
} ,
COMMAND_REGISTRATION_DONE
} ;
2009-11-13 12:14:50 +00:00
struct jtag_interface ft2232_interface = {
2009-11-10 05:21:06 +00:00
. name = " ft2232 " ,
2009-11-21 06:01:59 +00:00
. commands = ft2232_command_handlers ,
2009-11-10 05:21:06 +00:00
. init = & ft2232_init ,
. quit = & ft2232_quit ,
. speed = & ft2232_speed ,
. speed_div = & ft2232_speed_div ,
. khz = & ft2232_khz ,
. execute_queue = & ft2232_execute_queue ,
} ;