2008-02-25 17:48:04 +00:00
/***************************************************************************
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 *
* *
2009-05-18 17:41:27 +00:00
* Copyright ( C ) 2009 by SoftPLC Corporation . http : //softplc.com *
* Dick Hollenbeck < dick @ softplc . com > *
* *
2009-02-03 05:59:17 +00:00
* 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 */
# include "jtag.h"
# include "time_support.h"
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>
# if (BUILD_FT2232_FTD2XX==1 && BUILD_FT2232_LIBFTDI==1)
# error "BUILD_FT2232_FTD2XX && BUILD_FT2232_LIBFTDI are mutually exclusive"
# elif(BUILD_FT2232_FTD2XX!=1 && BUILD_FT2232_LIBFTDI!=1)
# 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-04-21 05:29:23 +00:00
static int ft2232_execute_queue ( void ) ;
2008-02-25 17:48:04 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_speed ( int speed ) ;
static int ft2232_speed_div ( int speed , int * khz ) ;
static int ft2232_khz ( int khz , int * jtag_speed ) ;
static int ft2232_register_commands ( struct command_context_s * cmd_ctx ) ;
static int ft2232_init ( void ) ;
static int ft2232_quit ( void ) ;
2008-02-25 17:48:04 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_handle_device_desc_command ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc ) ;
static int ft2232_handle_serial_command ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc ) ;
static int ft2232_handle_layout_command ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc ) ;
static int ft2232_handle_vid_pid_command ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc ) ;
static int ft2232_handle_latency_command ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc ) ;
2008-02-25 17:48:04 +00:00
2009-01-09 07:42:45 +00:00
/**
* Function ft2232_stableclocks
* will 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 is the count of clocks cycles to send .
* @ return int - ERROR_OK or ERROR_JTAG_QUEUE_FAILED
*/
2009-02-03 05:59:17 +00:00
static int ft2232_stableclocks ( int num_cycles , jtag_command_t * 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 ;
static u8 ft2232_latency = 2 ;
static unsigned ft2232_max_tck = 6000 ;
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-02-03 05:59:17 +00:00
static u16 ft2232_vid [ MAX_USB_IDS + 1 ] = { 0x0403 , 0 } ;
static u16 ft2232_pid [ MAX_USB_IDS + 1 ] = { 0x6010 , 0 } ;
2008-02-25 17:48:04 +00:00
typedef struct ft2232_layout_s
{
char * name ;
2009-02-03 05:59:17 +00:00
int ( * init ) ( void ) ;
void ( * reset ) ( int trst , int srst ) ;
void ( * blink ) ( void ) ;
2008-02-25 17:48:04 +00:00
} ft2232_layout_t ;
/* init procedures for supported layouts */
2009-04-21 05:29:23 +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 ) ;
2009-05-18 17:41:27 +00:00
static int axm0432_jtag_init ( void ) ;
static int sheevaplug_init ( void ) ;
static int icebear_jtag_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 ) ;
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 ) ;
2008-02-25 17:48:04 +00:00
2009-05-18 17:41:27 +00:00
ft2232_layout_t 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 } ,
{ " 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-03-01 21:01:11 +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-04-20 06:40:45 +00:00
{ NULL , NULL , NULL , NULL } ,
2008-02-25 17:48:04 +00:00
} ;
2009-02-03 05:59:17 +00:00
static u8 nTRST , nTRSTnOE , nSRST , nSRSTnOE ;
2008-02-25 17:48:04 +00:00
2009-02-03 05:59:17 +00:00
static ft2232_layout_t * layout ;
static u8 low_output = 0x0 ;
static u8 low_direction = 0x0 ;
static u8 high_output = 0x0 ;
static u8 high_direction = 0x0 ;
2008-02-25 17:48:04 +00:00
# if BUILD_FT2232_FTD2XX == 1
2009-05-18 17:41:27 +00:00
static FT_HANDLE ftdih = NULL ;
2008-02-25 17:48:04 +00:00
# elif BUILD_FT2232_LIBFTDI == 1
static struct ftdi_context ftdic ;
# endif
2009-01-09 07:42:45 +00:00
2009-02-03 05:59:17 +00:00
static jtag_command_t * first_unsent ; /* next command that has to be sent */
static int require_send ;
2009-01-09 07:42:45 +00:00
2009-05-18 17:41:27 +00:00
/* http://urjtag.wiki.sourceforge.net/Cable+FT2232 says:
" 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-02-03 05:59:17 +00:00
static u8 * ft2232_buffer = NULL ;
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 .
*/
static inline void buffer_write ( u8 val )
{
assert ( ft2232_buffer ) ;
assert ( ( unsigned ) ft2232_buffer_size < ( unsigned ) FT2232_BUFFER_SIZE ) ;
ft2232_buffer [ ft2232_buffer_size + + ] = val ;
}
/**
* Function buffer_read
* returns a byte from the byte buffer .
*/
static inline u8 buffer_read ( void )
{
assert ( ft2232_buffer ) ;
assert ( ft2232_read_pointer < ft2232_buffer_size ) ;
return ft2232_buffer [ ft2232_read_pointer + + ] ;
}
/**
* Function clock_tms
* clocks out \ a bit_count bits on the TMS line , starting with the least
* significant bit of tms_bits and progressing to more significant bits .
* Rigorous state transition logging is done here via tap_set_state ( ) .
*
* @ param pmsse_cmd is one of the MPSSE TMS oriented commands such as 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 .
*
* @ param tms_bits holds the sequence of bits to send .
* @ param tms_count tells how many bits in the sequence .
* @ param tdi_bit is a single bit which is passed on to TDI before the first TCK cycle
* and is held static for the duration of TMS clocking . See the MPSSE spec referenced above .
*/
static void clock_tms ( u8 mpsse_cmd , int tms_bits , int tms_count , bool tdi_bit )
{
u8 tms_byte ;
int i ;
int tms_ndx ; /* bit index into tms_byte */
assert ( tms_count > 0 ) ;
// LOG_DEBUG("mpsse cmd=%02x, tms_bits=0x%08x, bit_count=%d", mpsse_cmd, tms_bits, tms_count );
for ( tms_byte = tms_ndx = i = 0 ; i < tms_count ; + + i , tms_bits > > = 1 )
{
bool bit = tms_bits & 1 ;
if ( bit )
tms_byte | = ( 1 < < tms_ndx ) ;
/* always do state transitions in public view */
tap_set_state ( tap_state_transition ( tap_get_state ( ) , bit ) ) ;
/* we wrote a bit to tms_byte just above, increment bit index. if bit was zero
also increment .
*/
+ + tms_ndx ;
if ( tms_ndx = = 7 | | i = = tms_count - 1 )
{
buffer_write ( mpsse_cmd ) ;
buffer_write ( tms_ndx - 1 ) ;
/* Bit 7 of the byte is passed on to TDI/DO before the first TCK/SK of
TMS / CS and is held static for the duration of TMS / CS clocking .
*/
buffer_write ( tms_byte | ( tdi_bit < < 7 ) ) ;
}
}
}
/**
* Function get_tms_buffer_requirements
* returns what clock_tms ( ) will consume if called with
* same \ a bit_count .
*/
static inline int get_tms_buffer_requirements ( int bit_count )
{
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 .
*/
static void move_to_state ( tap_state_t goal_state )
{
tap_state_t start_state = tap_get_state ( ) ;
/* goal_state is 1/2 of a tuple/pair of states which allow convenient
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 ) ;
DEBUG_JTAG_IO ( " start=%s goal=%s " , tap_state_name ( start_state ) , tap_state_name ( goal_state ) ) ;
clock_tms ( 0x4b , tms_bits , tms_count , 0 ) ;
}
2008-02-25 17:48:04 +00:00
2008-12-13 06:25:50 +00:00
jtag_interface_t ft2232_interface =
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
. name = " ft2232 " ,
2008-02-25 17:48:04 +00:00
. execute_queue = ft2232_execute_queue ,
2009-02-03 05:59:17 +00:00
. speed = ft2232_speed ,
2008-05-12 09:01:38 +00:00
. speed_div = ft2232_speed_div ,
2009-02-03 05:59:17 +00:00
. khz = ft2232_khz ,
. register_commands = ft2232_register_commands ,
2008-02-25 17:48:04 +00:00
. init = ft2232_init ,
. quit = ft2232_quit ,
} ;
2009-04-21 05:29:23 +00:00
static int ft2232_write ( u8 * buf , int size , u32 * bytes_written )
2008-02-25 17:48:04 +00:00
{
# if BUILD_FT2232_FTD2XX == 1
FT_STATUS status ;
2009-05-18 17:41:27 +00:00
DWORD dw_bytes_written ;
2009-02-03 05:59:17 +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-02-03 05:59:17 +00:00
if ( ( retval = ftdi_write_data ( & ftdic , buf , size ) ) < 0 )
2008-02-25 17:48:04 +00:00
{
* bytes_written = 0 ;
2009-02-03 05:59:17 +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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_read ( u8 * buf , u32 size , u32 * bytes_read )
2008-02-25 17:48:04 +00:00
{
# if BUILD_FT2232_FTD2XX == 1
2009-02-03 05:59:17 +00:00
DWORD dw_bytes_read ;
2008-02-25 17:48:04 +00:00
FT_STATUS status ;
2009-02-03 05:59:17 +00:00
int timeout = 5 ;
2008-02-25 17:48:04 +00:00
* bytes_read = 0 ;
2009-02-03 05:59:17 +00:00
while ( ( * bytes_read < size ) & & timeout - - )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +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 ;
int timeout = 100 ;
* bytes_read = 0 ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
while ( ( * bytes_read < size ) & & timeout - - )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +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-02-03 05:59:17 +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 )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " couldn't read the requested number of bytes from FT2232 device (%i < %i) " , * bytes_read , 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-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-02-03 05:59:17 +00:00
u8 buf [ 3 ] ;
2008-02-25 17:48:04 +00:00
int retval ;
u32 bytes_written ;
2009-05-18 17:41:27 +00:00
buf [ 0 ] = 0x86 ; /* command "set divisor" */
2009-02-03 05:59:17 +00:00
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-02-03 05:59:17 +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-02-03 05:59:17 +00:00
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-05-18 17:41:27 +00:00
* khz = 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-02-03 05:59:17 +00:00
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
{
2008-08-25 16:16:00 +00:00
if ( khz = = 0 )
{
2009-05-24 21:13:29 +00:00
LOG_DEBUG ( " RTCK not supported " ) ;
2008-08-25 16:16:00 +00:00
return ERROR_FAIL ;
}
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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_register_commands ( struct command_context_s * cmd_ctx )
2008-02-25 17:48:04 +00:00
{
register_command ( cmd_ctx , NULL , " ft2232_device_desc " , ft2232_handle_device_desc_command ,
2009-02-03 05:59:17 +00:00
COMMAND_CONFIG , " the USB device description of the FTDI FT2232 device " ) ;
2008-02-25 17:48:04 +00:00
register_command ( cmd_ctx , NULL , " ft2232_serial " , ft2232_handle_serial_command ,
2009-02-03 05:59:17 +00:00
COMMAND_CONFIG , " the serial number of the FTDI FT2232 device " ) ;
2008-02-25 17:48:04 +00:00
register_command ( cmd_ctx , NULL , " ft2232_layout " , ft2232_handle_layout_command ,
2009-02-03 05:59:17 +00:00
COMMAND_CONFIG , " the layout of the FT2232 GPIO signals used to control output-enables and reset signals " ) ;
2008-02-25 17:48:04 +00:00
register_command ( cmd_ctx , NULL , " ft2232_vid_pid " , ft2232_handle_vid_pid_command ,
2009-02-03 05:59:17 +00:00
COMMAND_CONFIG , " the vendor ID and product ID of the FTDI FT2232 device " ) ;
2008-02-25 17:48:04 +00:00
register_command ( cmd_ctx , NULL , " ft2232_latency " , ft2232_handle_latency_command ,
2009-02-03 05:59:17 +00:00
COMMAND_CONFIG , " set the FT2232 latency timer to a new value " ) ;
2008-02-25 17:48:04 +00:00
return ERROR_OK ;
}
2009-02-03 05:59:17 +00:00
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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static void ft2232_read_scan ( enum scan_type type , u8 * 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-05-18 17:41: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 */
buffer [ cur_byte ] = ( buffer [ cur_byte ] | ( ( ( buffer_read ( ) ) < < 1 ) & 0x80 ) ) > > ( 8 - bits_left ) ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +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-02-03 05:59:17 +00:00
int i ;
char line [ 256 ] ;
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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_send_and_recv ( jtag_command_t * first , jtag_command_t * last )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
jtag_command_t * cmd ;
u8 * buffer ;
int scan_size ;
enum scan_type type ;
int retval ;
2009-04-25 00:54:21 +00:00
u32 bytes_written = 0 ;
u32 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-02-03 05:59:17 +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 )
{
int timeout = 100 ;
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-02-03 05:59:17 +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-02-03 05:59:17 +00:00
LOG_ERROR ( " ft2232_expect_read (%i) != ft2232_buffer_size (%i) (%i retries) " , ft2232_expect_read ,
ft2232_buffer_size ,
100 - 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_
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " read buffer (%i retries): %i bytes " , 100 - 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 ) ;
buffer = calloc ( CEIL ( scan_size , 8 ) , 1 ) ;
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-02-03 05:59:17 +00:00
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
*/
static void ft2232_add_pathmove ( tap_state_t * path , int num_states )
2008-02-25 17:48:04 +00:00
{
2009-05-18 17:41:27 +00:00
int tms_bits = 0 ;
int state_ndx ;
tap_state_t walker = tap_get_state ( ) ;
2008-12-13 06:25:50 +00:00
2009-05-18 17:41:27 +00:00
assert ( ( unsigned ) num_states < = 32u ) ; /* tms_bits only holds 32 bits */
2008-02-27 06:59:35 +00:00
2009-05-18 17:41:27 +00:00
/* this loop verifies that the path is legal and logs each state in the path */
for ( state_ndx = 0 ; state_ndx < num_states ; + + state_ndx )
{
tap_state_t desired_next_state = path [ state_ndx ] ;
2008-12-13 06:25:50 +00:00
2009-05-18 17:41:27 +00:00
if ( tap_state_transition ( walker , false ) = = desired_next_state )
; /* bit within tms_bits at index state_ndx is already zero */
else if ( tap_state_transition ( walker , true ) = = desired_next_state )
tms_bits | = ( 1 < < state_ndx ) ;
else
2008-02-25 17:48:04 +00:00
{
2009-05-18 17:41:27 +00:00
LOG_ERROR ( " BUG: %s -> %s isn't a valid TAP transition " ,
tap_state_name ( walker ) , tap_state_name ( desired_next_state ) ) ;
exit ( - 1 ) ;
2008-02-25 17:48:04 +00:00
}
2008-12-13 06:25:50 +00:00
2009-05-18 17:41:27 +00:00
walker = desired_next_state ;
2008-02-25 17:48:04 +00:00
}
2009-05-18 17:41:27 +00:00
clock_tms ( 0x4b , tms_bits , num_states , 0 ) ;
2009-02-03 05:59:17 +00:00
tap_set_end_state ( tap_get_state ( ) ) ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +00:00
2009-05-16 20:09:07 +00:00
void ft2232_add_scan ( bool ir_scan , enum scan_type type , u8 * 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-05-18 17:41: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-05-18 17:41: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-05-18 17:41: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-05-18 17:41: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-05-18 17:41: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-05-18 17:41: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
buffer_write ( ( u8 ) ( thisrun_bytes - 1 ) ) ;
buffer_write ( ( u8 ) ( ( 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-05-18 17:41: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-02-03 05:59:17 +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-05-18 17:41: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-05-18 17:41: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-05-18 17:41: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
buffer_write ( bits_left - 2 ) ;
2008-02-25 17:48:04 +00:00
if ( type ! = SCAN_IN )
2009-05-18 17:41:27 +00:00
buffer_write ( buffer [ cur_byte ] ) ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +00:00
if ( ( ir_scan & & ( tap_get_end_state ( ) = = TAP_IRSHIFT ) )
| | ( ! 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-05-18 17:41: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-05-18 17:41: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-05-18 17:41: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
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 ;
u8 mpsse_cmd ;
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-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TMS scan (read)"); */
2008-02-25 17:48:04 +00:00
}
else
{
2009-05-18 17:41: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-03-25 15:45:17 +00:00
/* LOG_DEBUG("added TMS scan (no read)"); */
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +00:00
2009-05-18 17:41:27 +00:00
clock_tms ( mpsse_cmd , tms_bits , tms_count , last_bit ) ;
}
if ( tap_get_state ( ) ! = tap_get_end_state ( ) )
{
move_to_state ( tap_get_end_state ( ) ) ;
2008-02-25 17:48:04 +00:00
}
}
2009-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_large_scan ( scan_command_t * cmd , enum scan_type type , u8 * 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-02-03 05:59:17 +00:00
u8 * receive_buffer = malloc ( CEIL ( scan_size , 8 ) ) ;
u8 * receive_pointer = receive_buffer ;
2008-02-25 17:48:04 +00:00
u32 bytes_written ;
u32 bytes_read ;
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-05-18 17:41: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-02-03 05:59:17 +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 ) ;
}
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " ft2232_buffer_size: %i, bytes_written: %i " , ft2232_buffer_size , 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-05-18 17:41: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-05-18 17:41: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-05-18 17:41: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-05-18 17:41:27 +00:00
buffer_write ( ( u8 ) ( thisrun_bytes - 1 ) ) ;
buffer_write ( ( u8 ) ( ( 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-05-18 17:41: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-02-03 05:59:17 +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 ) ;
}
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " ft2232_buffer_size: %i, bytes_written: %i " , ft2232_buffer_size , 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-02-03 05:59:17 +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 ) ;
}
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " thisrun_read: %i, bytes_read: %i " , thisrun_read , 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-02-03 05:59:17 +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-05-18 17:41: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-05-18 17:41: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-05-18 17:41: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
buffer_write ( bits_left - 2 ) ;
2008-02-25 17:48:04 +00:00
if ( type ! = SCAN_IN )
2009-05-18 17:41: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-05-18 17:41: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-05-18 17:41: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-05-18 17:41: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
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 = 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 ( ) ) ;
u8 mpsse_cmd ;
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
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-02-03 05:59:17 +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 ) ;
}
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " ft2232_buffer_size: %i, bytes_written: %i " , ft2232_buffer_size , 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-02-03 05:59:17 +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 ) ;
}
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " thisrun_read: %i, bytes_read: %i " , thisrun_read , 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-02-03 05:59:17 +00:00
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-05-18 17:41: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-02-03 05:59:17 +00:00
if ( type = = SCAN_IN ) /* only from device to host */
2008-02-25 17:48:04 +00:00
{
/* complete bytes */
2009-01-09 07:42:45 +00:00
predicted_size + = CEIL ( 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-02-03 05:59:17 +00:00
predicted_size + = ( ( scan_size - 1 ) % 8 ) ? 2 : 0 ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +00:00
else /* host to device, or bidirectional */
2008-02-25 17:48:04 +00:00
{
/* complete bytes */
2009-01-09 07:42:45 +00:00
predicted_size + = num_bytes + CEIL ( 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-02-03 05:59:17 +00:00
predicted_size + = ( ( scan_size - 1 ) % 8 ) ? 3 : 0 ;
2008-02-25 17:48:04 +00:00
}
return predicted_size ;
}
2009-02-03 05:59:17 +00:00
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 */
predicted_size + = ( CEIL ( scan_size , 8 ) > 1 ) ? ( CEIL ( 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-02-03 05:59:17 +00:00
predicted_size + = ( ( scan_size - 1 ) % 8 ) ? 1 : 0 ;
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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static void usbjtag_reset ( int trst , int srst )
2008-02-25 17:48:04 +00:00
{
if ( trst = = 1 )
{
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
2009-02-03 05:59:17 +00:00
low_direction | = nTRSTnOE ; /* switch to output pin (output is low) */
2008-02-25 17:48:04 +00:00
else
2009-02-03 05:59:17 +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 )
low_direction & = ~ nTRSTnOE ; /* switch to input pin (high-Z + internal and external pullup) */
else
2009-02-03 05:59:17 +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-02-03 05:59:17 +00:00
low_output & = ~ nSRST ; /* switch output low */
2008-02-25 17:48:04 +00:00
else
2009-02-03 05:59:17 +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-02-03 05:59:17 +00:00
low_output | = nSRST ; /* switch output high */
2008-02-25 17:48:04 +00:00
else
2009-02-03 05:59:17 +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-05-18 17:41:27 +00:00
buffer_write ( 0x80 ) ;
buffer_write ( low_output ) ;
buffer_write ( low_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +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
{
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-05-18 17:41: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-02-03 05:59:17 +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
{
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-05-18 17:41: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-02-03 05:59:17 +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-05-18 17:41: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-02-03 05:59: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-05-18 17:41: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-02-03 05:59:17 +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-05-18 17:41: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-02-03 05:59:17 +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-05-18 17:41: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-02-03 05:59:17 +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-05-18 17:41: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-05-18 17:41: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-02-03 05:59:17 +00:00
2009-03-01 21:01:11 +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-05-18 17:41: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-04-25 00:54:21 +00:00
static int ft2232_execute_end_state ( jtag_command_t * cmd )
2008-02-25 17:48:04 +00:00
{
2009-04-25 00:54:21 +00:00
int retval ;
retval = ERROR_OK ;
2009-02-03 05:59:17 +00:00
2009-05-18 17:41:27 +00:00
DEBUG_JTAG_IO ( " execute_end_state: %s " , tap_state_name ( cmd - > cmd . end_state - > end_state ) ) ;
2009-01-09 07:42:45 +00:00
2009-04-25 00:54:21 +00:00
if ( cmd - > cmd . end_state - > end_state ! = TAP_INVALID )
ft2232_end_state ( cmd - > cmd . end_state - > end_state ) ;
2008-02-25 17:48:04 +00:00
2009-04-25 00:54:21 +00:00
return retval ;
}
2008-12-13 06:25:50 +00:00
2008-02-25 17:48:04 +00:00
2009-04-25 00:54:21 +00:00
static int ft2232_execute_runtest ( jtag_command_t * cmd )
{
int retval ;
int i ;
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 ;
predicted_size + = 3 * CEIL ( cmd - > cmd . runtest - > num_cycles , 7 ) ;
if ( ( cmd - > cmd . runtest - > end_state ! = TAP_INVALID ) & & ( cmd - > cmd . runtest - > end_state ! = TAP_IDLE ) )
predicted_size + = 3 ;
if ( ( cmd - > cmd . runtest - > end_state = = TAP_INVALID ) & & ( tap_get_end_state ( ) ! = TAP_IDLE ) )
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-05-18 17:41: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-05-18 17:41: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-05-18 17:41: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-05-18 17:41:27 +00:00
buffer_write ( 0x0 ) ;
2009-04-25 00:54:21 +00:00
tap_set_state ( TAP_IDLE ) ;
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)"); */
}
if ( cmd - > cmd . runtest - > end_state ! = TAP_INVALID )
ft2232_end_state ( cmd - > cmd . runtest - > end_state ) ;
if ( tap_get_state ( ) ! = tap_get_end_state ( ) )
{
2009-05-18 17:41: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 ;
2008-12-13 06:25:50 +00:00
# ifdef _DEBUG_JTAG_IO_
2009-04-25 00:54:21 +00:00
LOG_DEBUG ( " runtest: %i, end in %s " , cmd - > cmd . runtest - > num_cycles , tap_state_name ( tap_get_end_state ( ) ) ) ;
2008-02-25 17:48:04 +00:00
# endif
2009-01-09 07:42:45 +00:00
2009-04-25 00:54:21 +00:00
return retval ;
}
2009-01-09 07:42:45 +00:00
2009-05-18 17:41:27 +00:00
2009-04-25 00:54:21 +00:00
static int ft2232_execute_statemove ( jtag_command_t * cmd )
{
2009-05-18 17:41:27 +00:00
int predicted_size = 0 ;
int retval = ERROR_OK ;
2009-02-03 05:59:17 +00:00
2009-04-25 00:54:21 +00:00
DEBUG_JTAG_IO ( " statemove end in %i " , cmd - > cmd . statemove - > end_state ) ;
/* 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 ;
}
if ( cmd - > cmd . statemove - > end_state ! = TAP_INVALID )
ft2232_end_state ( cmd - > cmd . statemove - > end_state ) ;
2009-02-03 05:59:17 +00:00
2009-05-18 17:41:27 +00:00
/* move to end state */
if ( tap_get_state ( ) ! = tap_get_end_state ( ) )
{
move_to_state ( tap_get_end_state ( ) ) ;
require_send = 1 ;
}
2009-04-25 00:54:21 +00:00
return retval ;
}
2009-02-03 05:59:17 +00:00
2009-04-25 00:54:21 +00:00
static int ft2232_execute_pathmove ( jtag_command_t * cmd )
{
2009-05-18 17:41:27 +00:00
int predicted_size = 0 ;
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 ,
tap_state_name ( tap_get_state ( ) ) ,
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-05-18 17:41:27 +00:00
predicted_size = 3 * CEIL ( 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
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-05-18 17:41:27 +00:00
2009-04-25 00:54:21 +00:00
static int ft2232_execute_scan ( jtag_command_t * cmd )
{
u8 * buffer ;
int scan_size ; /* size of IR or DR scan */
int predicted_size = 0 ;
2009-05-18 17:41:27 +00:00
int retval = ERROR_OK ;
enum scan_type type = jtag_scan_type ( cmd - > cmd . scan ) ;
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 ) ;
if ( ( predicted_size + 1 ) > FT2232_BUFFER_SIZE )
{
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 */
if ( cmd - > cmd . scan - > end_state ! = TAP_INVALID )
ft2232_end_state ( cmd - > cmd . scan - > end_state ) ;
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); */
if ( cmd - > cmd . scan - > end_state ! = TAP_INVALID )
ft2232_end_state ( cmd - > cmd . scan - > end_state ) ;
ft2232_add_scan ( cmd - > cmd . scan - > ir_scan , type , buffer , scan_size ) ;
require_send = 1 ;
if ( buffer )
free ( buffer ) ;
2009-02-03 05:59:17 +00:00
# ifdef _DEBUG_JTAG_IO_
2009-04-25 00:54:21 +00:00
LOG_DEBUG ( " %s scan, %i bits, end in %s " , ( cmd - > cmd . scan - > ir_scan ) ? " IR " : " DR " , scan_size ,
tap_state_name ( tap_get_end_state ( ) ) ) ;
2009-02-03 05:59:17 +00:00
# endif
2009-04-25 00:54:21 +00:00
return retval ;
}
static int ft2232_execute_reset ( jtag_command_t * cmd )
{
int retval ;
int predicted_size = 0 ;
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 ;
}
layout - > reset ( cmd - > cmd . reset - > trst , cmd - > cmd . reset - > srst ) ;
require_send = 1 ;
2009-02-03 05:59:17 +00:00
2008-12-13 06:25:50 +00:00
# ifdef _DEBUG_JTAG_IO_
2009-04-25 00:54:21 +00:00
LOG_DEBUG ( " trst: %i, srst: %i " , cmd - > cmd . reset - > trst , cmd - > cmd . reset - > srst ) ;
2009-01-09 07:42:45 +00:00
# endif
2009-04-25 00:54:21 +00:00
return retval ;
}
2009-01-09 07:42:45 +00:00
2009-04-25 00:54:21 +00:00
static int ft2232_execute_sleep ( jtag_command_t * cmd )
{
int retval ;
retval = ERROR_OK ;
DEBUG_JTAG_IO ( " sleep %i " , cmd - > cmd . sleep - > us ) ;
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-01-09 07:42:45 +00:00
# ifdef _DEBUG_JTAG_IO_
2009-02-03 05:59:17 +00:00
LOG_DEBUG ( " sleep %i usec while in %s " , cmd - > cmd . sleep - > us , tap_state_name ( tap_get_state ( ) ) ) ;
2008-02-25 17:48:04 +00:00
# endif
2009-01-09 07:42:45 +00:00
2009-04-25 00:54:21 +00:00
return retval ;
}
2009-02-03 05:59:17 +00:00
2009-04-25 00:54:21 +00:00
static int ft2232_execute_stableclocks ( jtag_command_t * cmd )
{
int retval ;
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-02-03 05:59:17 +00:00
# ifdef _DEBUG_JTAG_IO_
2009-04-25 00:54:21 +00:00
LOG_DEBUG ( " clocks %i while in %s " , cmd - > cmd . stableclocks - > num_cycles , tap_state_name ( tap_get_state ( ) ) ) ;
2009-02-03 05:59:17 +00:00
# endif
2009-04-25 00:54:21 +00:00
return retval ;
}
static int ft2232_execute_command ( jtag_command_t * cmd )
{
int retval ;
retval = ERROR_OK ;
switch ( cmd - > type )
{
2009-05-18 17:41:27 +00:00
case JTAG_END_STATE : retval = ft2232_execute_end_state ( cmd ) ; break ;
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 ;
default :
LOG_ERROR ( " BUG: unknown JTAG command type encountered " ) ;
exit ( - 1 ) ;
2009-04-25 00:54:21 +00:00
}
return retval ;
}
static int ft2232_execute_queue ( )
{
jtag_command_t * cmd = jtag_command_queue ; /* currently processed command */
int retval ;
first_unsent = cmd ; /* next command that has to be sent */
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 ;
}
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
# if BUILD_FT2232_FTD2XX == 1
2009-02-03 05:59:17 +00:00
static int ft2232_init_ftd2xx ( u16 vid , u16 pid , int more , int * try_more )
2008-02-25 17:48:04 +00:00
{
2009-05-18 17:41:27 +00:00
FT_STATUS status ;
DWORD openex_flags = 0 ;
char * openex_string = NULL ;
u8 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-02-03 05:59:17 +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 ) ;
if ( status ! = FT_OK ) {
// 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.
if ( openex_string = = ft2232_device_desc ) {
// Try the alternate method.
openex_string = ft2232_device_desc_A ;
status = FT_OpenEx ( openex_string , openex_flags , & ftdih ) ;
if ( status = = FT_OK ) {
// yea, the "alternate" method worked!
} else {
// drat, give the user a meaningfull message.
// telling the use we tried *BOTH* methods.
LOG_WARNING ( " Unable to open FTDI Device tried: '%s' and '%s' \n " ,
ft2232_device_desc ,
ft2232_device_desc_A ) ;
}
}
}
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-02-03 05:59:17 +00:00
char * * desc_array = malloc ( sizeof ( char * ) * ( num_devices + 1 ) ) ;
2009-04-20 06:40:45 +00:00
u32 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 + + )
2008-12-27 03:07:32 +00:00
LOG_ERROR ( " %i: \" %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-02-03 05:59:17 +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-02-03 05:59:17 +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-02-03 05:59:17 +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-02-03 05:59:17 +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 ;
}
return ERROR_OK ;
}
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
static int ft2232_purge_ftd2xx ( void )
{
FT_STATUS status ;
2009-02-03 05:59:17 +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-02-03 05:59:17 +00:00
static int ft2232_init_libftdi ( u16 vid , u16 pid , int more , int * try_more )
2008-02-25 17:48:04 +00:00
{
u8 latency_timer ;
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 */
return ERROR_OK ;
}
2009-02-03 05:59:17 +00:00
2008-02-25 17:48:04 +00:00
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-02-03 05:59:17 +00:00
u8 buf [ 1 ] ;
2008-02-25 17:48:04 +00:00
int retval ;
u32 bytes_written ;
2009-02-03 05:59:17 +00:00
ft2232_layout_t * cur_layout = ft2232_layouts ;
2008-02-25 17:48:04 +00:00
int i ;
2008-12-13 06:25:50 +00:00
2009-05-18 17:41:27 +00:00
if ( tap_get_tms_path_len ( TAP_IRPAUSE , TAP_IRPAUSE ) = = 7 )
{
LOG_DEBUG ( " ft2232 interface using 7 step jtag state transitions " ) ;
}
else
{
LOG_DEBUG ( " ft2232 interface using shortest path jtag state transitions " ) ;
}
2009-02-03 05:59:17 +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 ;
ft2232_speed ( jtag_speed ) ;
buf [ 0 ] = 0x85 ; /* Disconnect TDI/DO to TDO/DI for Loopback */
2009-02-03 05:59:17 +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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int usbjtag_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
u8 buf [ 3 ] ;
2008-02-25 17:48:04 +00:00
u32 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 )
{
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 ;
}
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
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" */
buf [ 1 ] = low_output ; /* value (TMS=1,TCK=0, TDI=0, xRST high) */
2008-02-25 17:48:04 +00:00
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-02-03 05:59:17 +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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int axm0432_jtag_init ( void )
2008-12-11 19:03:17 +00:00
{
2009-02-03 05:59:17 +00:00
u8 buf [ 3 ] ;
2008-12-11 19:03:17 +00:00
u32 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" */
buf [ 1 ] = low_output ; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
2008-12-11 19:03:17 +00:00
buf [ 2 ] = low_direction ; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */
LOG_DEBUG ( " %2.2x %2.2x %2.2x " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] ) ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +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 ;
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-02-03 05:59:17 +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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int jtagkey_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
u8 buf [ 3 ] ;
2008-02-25 17:48:04 +00:00
u32 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" */
buf [ 1 ] = low_output ; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
2008-02-25 17:48:04 +00:00
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-02-03 05:59:17 +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-02-03 05:59:17 +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 ;
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-02-03 05:59:17 +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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int olimex_jtag_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
u8 buf [ 3 ] ;
2008-02-25 17:48:04 +00:00
u32 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" */
buf [ 1 ] = low_output ; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
2008-02-25 17:48:04 +00:00
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-02-03 05:59:17 +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
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 ;
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-02-03 05:59:17 +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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int flyswatter_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
u8 buf [ 3 ] ;
2008-02-25 17:48:04 +00:00
u32 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" */
buf [ 1 ] = low_output ; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
2008-02-25 17:48:04 +00:00
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-02-03 05:59:17 +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-02-03 05:59:17 +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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int turtle_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
u8 buf [ 3 ] ;
2008-02-25 17:48:04 +00:00
u32 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" */
buf [ 1 ] = low_output ; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
2008-02-25 17:48:04 +00:00
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-02-03 05:59:17 +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-02-03 05:59:17 +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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int comstick_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
u8 buf [ 3 ] ;
2008-02-25 17:48:04 +00:00
u32 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" */
buf [ 1 ] = low_output ; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
2008-02-25 17:48:04 +00:00
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-02-03 05:59:17 +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-02-03 05:59:17 +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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int stm32stick_init ( void )
2008-02-25 17:48:04 +00:00
{
2009-02-03 05:59:17 +00:00
u8 buf [ 3 ] ;
2008-02-25 17:48:04 +00:00
u32 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" */
buf [ 1 ] = low_output ; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
2008-02-25 17:48:04 +00:00
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-02-03 05:59:17 +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-02-03 05:59:17 +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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int sheevaplug_init ( void )
2009-03-01 21:01:11 +00:00
{
u8 buf [ 3 ] ;
u32 bytes_written ;
low_output = 0x08 ;
low_direction = 0x1b ;
/* initialize low byte for jtag */
buf [ 0 ] = 0x80 ; /* command "set data bits low byte" */
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 */
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-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-05-18 17:41:27 +00:00
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +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-05-18 17:41: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-05-18 17:41:27 +00:00
buffer_write ( 0x82 ) ;
buffer_write ( high_output ) ;
buffer_write ( high_direction ) ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_handle_device_desc_command ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc )
2008-02-25 17:48:04 +00:00
{
2009-03-07 15:51:26 +00:00
char * cp ;
char buf [ 200 ] ;
2008-02-25 17:48:04 +00:00
if ( argc = = 1 )
{
ft2232_device_desc = strdup ( args [ 0 ] ) ;
2009-03-07 15:51:26 +00:00
cp = strchr ( ft2232_device_desc , 0 ) ;
// 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.
if ( ( cp [ - 1 ] = = ' A ' ) & & ( cp [ - 2 ] = = ' ' ) ) {
// it was, so make this the "A" version.
ft2232_device_desc_A = ft2232_device_desc ;
// and *CREATE* the non-A version.
strcpy ( buf , ft2232_device_desc ) ;
cp = strchr ( buf , 0 ) ;
cp [ - 2 ] = 0 ;
ft2232_device_desc = strdup ( buf ) ;
} else {
// <space>A not defined
// so create it
sprintf ( buf , " %s A " , ft2232_device_desc ) ;
ft2232_device_desc_A = strdup ( buf ) ;
}
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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_handle_serial_command ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc )
2008-02-25 17:48:04 +00:00
{
if ( argc = = 1 )
{
ft2232_serial = strdup ( args [ 0 ] ) ;
}
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-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_handle_layout_command ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc )
2008-02-25 17:48:04 +00:00
{
if ( argc = = 0 )
return ERROR_OK ;
ft2232_layout = malloc ( strlen ( args [ 0 ] ) + 1 ) ;
strcpy ( ft2232_layout , args [ 0 ] ) ;
return ERROR_OK ;
}
2009-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_handle_vid_pid_command ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc )
2008-02-25 17:48:04 +00:00
{
int i ;
2009-02-03 05:59:17 +00:00
if ( argc > MAX_USB_IDS * 2 )
{
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 ) ;
argc = MAX_USB_IDS * 2 ;
2008-02-25 17:48:04 +00:00
}
2009-02-03 05:59:17 +00:00
if ( argc < 2 | | ( 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 " ) ;
2008-02-25 17:48:04 +00:00
if ( argc < 2 )
return ERROR_OK ;
}
2009-02-03 05:59:17 +00:00
for ( i = 0 ; i + 1 < argc ; i + = 2 )
{
2008-02-25 17:48:04 +00:00
ft2232_vid [ i > > 1 ] = strtol ( args [ i ] , NULL , 0 ) ;
2009-02-03 05:59:17 +00:00
ft2232_pid [ i > > 1 ] = strtol ( args [ i + 1 ] , NULL , 0 ) ;
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 ;
return ERROR_OK ;
}
2009-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static int ft2232_handle_latency_command ( struct command_context_s * cmd_ctx , char * cmd , char * * args , int argc )
2008-02-25 17:48:04 +00:00
{
if ( argc = = 1 )
{
ft2232_latency = atoi ( args [ 0 ] ) ;
}
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-02-03 05:59:17 +00:00
static int ft2232_stableclocks ( int num_cycles , jtag_command_t * 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-02-03 05:59:17 +00:00
u8 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-05-18 17:41:27 +00:00
buffer_write ( 0x4b ) ;
2009-01-09 07:42:45 +00:00
/* scan 7 bit */
2009-05-18 17:41: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-05-18 17:41: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
2009-05-18 17:41:27 +00:00
2009-04-29 07:38:35 +00:00
/* ---------------------------------------------------------------------
* Support for IceBear JTAG adapter from Section5 :
* http : //section5.ch/icebear
*
* 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 ) {
u8 buf [ 3 ] ;
u32 bytes_written ;
low_direction = 0x0b ; /* output: TCK TDI TMS; input: TDO */
low_output = 0x08 ; /* high: TMS; low: TCK TDI */
nTRST = 0x10 ;
nSRST = 0x20 ;
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 ] ) ;
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) ) {
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 ] ) ;
if ( ( ( ft2232_write ( buf , 3 , & bytes_written ) ) ! = ERROR_OK ) | | ( bytes_written ! = 3 ) ) {
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 ) {
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-05-18 17:41:27 +00:00
buffer_write ( 0x80 ) ;
buffer_write ( low_output ) ;
buffer_write ( low_direction ) ;
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 ) ;
}