2008-02-28 07:35:51 +00:00
/***************************************************************************
* Copyright ( C ) 2005 by Dominic Rath *
* Dominic . Rath @ gmx . de *
* *
* 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 . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2009-12-03 12:14:31 +00:00
# include <jtag/interface.h>
2008-02-28 07:35:51 +00:00
# if PARPORT_USE_PPDEV == 1
# include <linux/parport.h>
# include <linux/ppdev.h>
# include <sys/ioctl.h>
# else /* not PARPORT_USE_PPDEV */
# ifndef _WIN32
# include <sys/io.h>
# endif
# endif
# if PARPORT_USE_GIVEIO == 1
# if IS_CYGWIN == 1
# include <windows.h>
# endif
# endif
2010-01-03 22:51:01 +00:00
/**
* @ file
* Support the Amontec Chameleon POD with JTAG Accelerator support .
* This is a parallel port JTAG adapter with a CPLD between the
* parallel port and the JTAG connection . VHDL code running in the
* CPLD significantly accelerates JTAG operations compared to the
* bitbanging " Wiggler " style of most parallel port adapters .
*/
2008-02-28 07:35:51 +00:00
/* configuration */
2009-06-18 07:07:59 +00:00
static uint16_t amt_jtagaccel_port ;
2008-02-28 07:35:51 +00:00
/* interface variables
*/
2009-06-18 07:07:12 +00:00
static uint8_t aw_control_rst = 0x00 ;
static uint8_t aw_control_fsm = 0x10 ;
static uint8_t aw_control_baudrate = 0x20 ;
2008-02-28 07:35:51 +00:00
static int rtck_enabled = 0 ;
# if PARPORT_USE_PPDEV == 1
static int device_handle ;
2009-04-21 05:29:23 +00:00
2010-01-03 20:59:51 +00:00
static const int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR ;
/* FIXME do something sane when these ioctl/read/write calls fail. */
# define AMT_AW(val) \
do { \
int __retval ; \
\
__retval = ioctl ( device_handle , PPSETMODE , & addr_mode ) ; \
__retval = write ( device_handle , & val , 1 ) ; \
} while ( 0 )
# define AMT_AR(val) \
do { \
int __retval ; \
\
__retval = ioctl ( device_handle , PPSETMODE , & addr_mode ) ; \
__retval = read ( device_handle , & val , 1 ) ; \
} while ( 0 )
static const int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA ;
# define AMT_DW(val) \
do { \
int __retval ; \
\
__retval = ioctl ( device_handle , PPSETMODE , & data_mode ) ; \
__retval = write ( device_handle , & val , 1 ) ; \
} while ( 0 )
# define AMT_DR(val) \
do { \
int __retval ; \
\
__retval = ioctl ( device_handle , PPSETMODE , & data_mode ) ; \
__retval = read ( device_handle , & val , 1 ) ; \
} while ( 0 )
2009-04-21 05:29:23 +00:00
2008-02-28 07:35:51 +00:00
# else
2009-04-21 05:29:23 +00:00
2008-02-28 07:35:51 +00:00
# define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
# define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
# define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
# define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
2009-04-21 05:29:23 +00:00
# endif // PARPORT_USE_PPDEV
2008-02-28 07:35:51 +00:00
/* tap_move[i][j]: tap movement command to go from state i to state j
* 0 : Test - Logic - Reset
* 1 : Run - Test / Idle
* 2 : Shift - DR
* 3 : Pause - DR
* 4 : Shift - IR
* 5 : Pause - IR
*/
2009-06-18 07:07:12 +00:00
static uint8_t amt_jtagaccel_tap_move [ 6 ] [ 6 ] [ 2 ] =
2008-02-28 07:35:51 +00:00
{
2008-12-13 06:59:24 +00:00
/* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
2009-07-06 10:34:49 +00:00
{ { 0x1f , 0x00 } , { 0x0f , 0x00 } , { 0x05 , 0x00 } , { 0x0a , 0x00 } , { 0x06 , 0x00 } , { 0x96 , 0x00 } } , /* RESET */
{ { 0x1f , 0x00 } , { 0x00 , 0x00 } , { 0x04 , 0x00 } , { 0x05 , 0x00 } , { 0x06 , 0x00 } , { 0x0b , 0x00 } } , /* IDLE */
2008-12-13 06:59:24 +00:00
{ { 0x1f , 0x00 } , { 0x0d , 0x00 } , { 0x00 , 0x00 } , { 0x01 , 0x00 } , { 0x8f , 0x09 } , { 0x8f , 0x01 } } , /* DRSHIFT */
{ { 0x1f , 0x00 } , { 0x0c , 0x00 } , { 0x08 , 0x00 } , { 0x00 , 0x00 } , { 0x8f , 0x09 } , { 0x8f , 0x01 } } , /* DRPAUSE */
{ { 0x1f , 0x00 } , { 0x0d , 0x00 } , { 0x07 , 0x00 } , { 0x97 , 0x00 } , { 0x00 , 0x00 } , { 0x01 , 0x00 } } , /* IRSHIFT */
{ { 0x1f , 0x00 } , { 0x0c , 0x00 } , { 0x07 , 0x00 } , { 0x97 , 0x00 } , { 0x08 , 0x00 } , { 0x00 , 0x00 } } , /* IRPAUSE */
2008-02-28 07:35:51 +00:00
} ;
2009-02-03 05:59:17 +00:00
2009-04-21 05:29:23 +00:00
static void amt_jtagaccel_reset ( int trst , int srst )
2008-02-28 07:35:51 +00:00
{
if ( trst = = 1 )
aw_control_rst | = 0x4 ;
else if ( trst = = 0 )
aw_control_rst & = ~ 0x4 ;
if ( srst = = 1 )
aw_control_rst | = 0x1 ;
else if ( srst = = 0 )
aw_control_rst & = ~ 0x1 ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
AMT_AW ( aw_control_rst ) ;
}
2009-04-21 05:29:23 +00:00
static int amt_jtagaccel_speed ( int speed )
2008-02-28 07:35:51 +00:00
{
aw_control_baudrate & = 0xf0 ;
aw_control_baudrate | = speed & 0x0f ;
AMT_AW ( aw_control_baudrate ) ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static void amt_jtagaccel_end_state ( tap_state_t state )
2008-02-28 07:35:51 +00:00
{
2009-02-03 05:59:17 +00:00
if ( tap_is_state_stable ( state ) )
tap_set_end_state ( state ) ;
2008-02-28 07:35:51 +00:00
else
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " BUG: %i is not a valid end state " , state ) ;
2008-02-28 07:35:51 +00:00
exit ( - 1 ) ;
}
}
2009-04-21 05:29:23 +00:00
static void amt_wait_scan_busy ( void )
2008-02-28 07:35:51 +00:00
{
int timeout = 4096 ;
2009-06-18 07:07:12 +00:00
uint8_t ar_status ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
AMT_AR ( ar_status ) ;
while ( ( ( ar_status ) & 0x80 ) & & ( timeout - - > 0 ) )
AMT_AR ( ar_status ) ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
if ( ar_status & 0x80 )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x " , ( rtck_enabled ) ? " enabled " : " disabled " , ar_status ) ;
2008-02-28 07:35:51 +00:00
exit ( - 1 ) ;
}
}
2009-04-21 05:29:23 +00:00
static void amt_jtagaccel_state_move ( void )
2008-02-28 07:35:51 +00:00
{
2009-06-18 07:07:12 +00:00
uint8_t aw_scan_tms_5 ;
uint8_t tms_scan [ 2 ] ;
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
tap_state_t cur_state = tap_get_state ( ) ;
tap_state_t end_state = tap_get_end_state ( ) ;
tms_scan [ 0 ] = amt_jtagaccel_tap_move [ tap_move_ndx ( cur_state ) ] [ tap_move_ndx ( end_state ) ] [ 0 ] ;
tms_scan [ 1 ] = amt_jtagaccel_tap_move [ tap_move_ndx ( cur_state ) ] [ tap_move_ndx ( end_state ) ] [ 1 ] ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
aw_scan_tms_5 = 0x40 | ( tms_scan [ 0 ] & 0x1f ) ;
AMT_AW ( aw_scan_tms_5 ) ;
2010-12-14 12:17:01 +00:00
int jtag_speed = 0 ;
2010-12-06 08:21:23 +00:00
int retval = jtag_get_speed ( & jtag_speed ) ;
assert ( retval = = ERROR_OK ) ;
2008-02-28 07:35:51 +00:00
if ( jtag_speed > 3 | | rtck_enabled )
amt_wait_scan_busy ( ) ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
if ( tms_scan [ 0 ] & 0x80 )
{
aw_scan_tms_5 = 0x40 | ( tms_scan [ 1 ] & 0x1f ) ;
AMT_AW ( aw_scan_tms_5 ) ;
if ( jtag_speed > 3 | | rtck_enabled )
amt_wait_scan_busy ( ) ;
}
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
tap_set_state ( end_state ) ;
2008-02-28 07:35:51 +00:00
}
2009-04-21 05:29:23 +00:00
static void amt_jtagaccel_runtest ( int num_cycles )
2008-02-28 07:35:51 +00:00
{
int i = 0 ;
2009-06-18 07:07:12 +00:00
uint8_t aw_scan_tms_5 ;
uint8_t aw_scan_tms_1to4 ;
2008-02-28 07:35:51 +00:00
2009-02-03 05:59:17 +00:00
tap_state_t saved_end_state = tap_get_end_state ( ) ;
2008-12-13 06:25:50 +00:00
2008-12-13 06:59:24 +00:00
/* only do a state_move when we're not already in IDLE */
2009-02-03 05:59:17 +00:00
if ( tap_get_state ( ) ! = TAP_IDLE )
2008-02-28 07:35:51 +00:00
{
2008-12-13 06:25:50 +00:00
amt_jtagaccel_end_state ( TAP_IDLE ) ;
2008-02-28 07:35:51 +00:00
amt_jtagaccel_state_move ( ) ;
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
while ( num_cycles - i > = 5 )
{
aw_scan_tms_5 = 0x40 ;
AMT_AW ( aw_scan_tms_5 ) ;
i + = 5 ;
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
if ( num_cycles - i > 0 )
{
aw_scan_tms_1to4 = 0x80 | ( ( num_cycles - i - 1 ) & 0x3 ) < < 4 ;
AMT_AW ( aw_scan_tms_1to4 ) ;
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
amt_jtagaccel_end_state ( saved_end_state ) ;
2009-02-03 05:59:17 +00:00
if ( tap_get_state ( ) ! = tap_get_end_state ( ) )
2008-02-28 07:35:51 +00:00
amt_jtagaccel_state_move ( ) ;
}
2009-06-18 07:07:12 +00:00
static void amt_jtagaccel_scan ( bool ir_scan , enum scan_type type , uint8_t * buffer , int scan_size )
2008-02-28 07:35:51 +00:00
{
int bits_left = scan_size ;
int bit_count = 0 ;
2009-02-03 05:59:17 +00:00
tap_state_t saved_end_state = tap_get_end_state ( ) ;
2009-06-18 07:07:12 +00:00
uint8_t aw_tdi_option ;
uint8_t dw_tdi_scan ;
uint8_t dr_tdo ;
uint8_t aw_tms_scan ;
uint8_t tms_scan [ 2 ] ;
2010-12-06 08:21:23 +00:00
int jtag_speed_var ;
int retval = jtag_get_speed ( & jtag_speed_var ) ;
assert ( retval = = ERROR_OK ) ;
2008-02-28 07:35:51 +00:00
if ( ir_scan )
2008-12-13 06:25:50 +00:00
amt_jtagaccel_end_state ( TAP_IRSHIFT ) ;
2008-02-28 07:35:51 +00:00
else
2008-12-13 06:25:50 +00:00
amt_jtagaccel_end_state ( TAP_DRSHIFT ) ;
2008-02-28 07:35:51 +00:00
amt_jtagaccel_state_move ( ) ;
amt_jtagaccel_end_state ( saved_end_state ) ;
/* handle unaligned bits at the beginning */
if ( ( scan_size - 1 ) % 8 )
{
aw_tdi_option = 0x30 | ( ( ( scan_size - 1 ) % 8 ) - 1 ) ;
AMT_AW ( aw_tdi_option ) ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
dw_tdi_scan = buf_get_u32 ( buffer , bit_count , ( scan_size - 1 ) % 8 ) & 0xff ;
AMT_DW ( dw_tdi_scan ) ;
2010-12-06 08:21:23 +00:00
if ( jtag_speed_var > 3 | | rtck_enabled )
2008-02-28 07:35:51 +00:00
amt_wait_scan_busy ( ) ;
if ( ( type = = SCAN_IN ) | | ( type = = SCAN_IO ) )
{
AMT_DR ( dr_tdo ) ;
dr_tdo = dr_tdo > > ( 8 - ( ( scan_size - 1 ) % 8 ) ) ;
buf_set_u32 ( buffer , bit_count , ( scan_size - 1 ) % 8 , dr_tdo ) ;
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
bit_count + = ( scan_size - 1 ) % 8 ;
bits_left - = ( scan_size - 1 ) % 8 ;
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
while ( bits_left - 1 > = 8 )
{
dw_tdi_scan = buf_get_u32 ( buffer , bit_count , 8 ) & 0xff ;
AMT_DW ( dw_tdi_scan ) ;
2010-12-06 08:21:23 +00:00
if ( jtag_speed_var > 3 | | rtck_enabled )
2008-02-28 07:35:51 +00:00
amt_wait_scan_busy ( ) ;
if ( ( type = = SCAN_IN ) | | ( type = = SCAN_IO ) )
{
AMT_DR ( dr_tdo ) ;
buf_set_u32 ( buffer , bit_count , 8 , dr_tdo ) ;
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
bit_count + = 8 ;
bits_left - = 8 ;
}
2008-12-13 06:25:50 +00:00
2009-02-03 05:59:17 +00:00
tms_scan [ 0 ] = amt_jtagaccel_tap_move [ tap_move_ndx ( tap_get_state ( ) ) ] [ tap_move_ndx ( tap_get_end_state ( ) ) ] [ 0 ] ;
tms_scan [ 1 ] = amt_jtagaccel_tap_move [ tap_move_ndx ( tap_get_state ( ) ) ] [ tap_move_ndx ( tap_get_end_state ( ) ) ] [ 1 ] ;
2008-02-28 07:35:51 +00:00
aw_tms_scan = 0x40 | ( tms_scan [ 0 ] & 0x1f ) | ( buf_get_u32 ( buffer , bit_count , 1 ) < < 5 ) ;
AMT_AW ( aw_tms_scan ) ;
2010-12-06 08:21:23 +00:00
if ( jtag_speed_var > 3 | | rtck_enabled )
2008-02-28 07:35:51 +00:00
amt_wait_scan_busy ( ) ;
if ( ( type = = SCAN_IN ) | | ( type = = SCAN_IO ) )
{
AMT_DR ( dr_tdo ) ;
dr_tdo = dr_tdo > > 7 ;
buf_set_u32 ( buffer , bit_count , 1 , dr_tdo ) ;
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
if ( tms_scan [ 0 ] & 0x80 )
{
aw_tms_scan = 0x40 | ( tms_scan [ 1 ] & 0x1f ) ;
AMT_AW ( aw_tms_scan ) ;
2010-12-06 08:21:23 +00:00
if ( jtag_speed_var > 3 | | rtck_enabled )
2008-02-28 07:35:51 +00:00
amt_wait_scan_busy ( ) ;
}
2009-02-03 05:59:17 +00:00
tap_set_state ( tap_get_end_state ( ) ) ;
2008-02-28 07:35:51 +00:00
}
2009-04-21 05:29:23 +00:00
static int amt_jtagaccel_execute_queue ( void )
2008-02-28 07:35:51 +00:00
{
2009-11-13 14:15:31 +00:00
struct jtag_command * cmd = jtag_command_queue ; /* currently processed command */
2008-02-28 07:35:51 +00:00
int scan_size ;
enum scan_type type ;
2009-06-18 07:07:12 +00:00
uint8_t * buffer ;
2008-02-28 07:35:51 +00:00
int retval ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +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-28 07:35:51 +00:00
retval = ERROR_OK ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
while ( cmd )
{
switch ( cmd - > type )
{
case JTAG_RESET :
# ifdef _DEBUG_JTAG_IO_
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " reset trst: %i srst %i " , cmd - > cmd . reset - > trst , cmd - > cmd . reset - > srst ) ;
2008-02-28 07:35:51 +00:00
# endif
if ( cmd - > cmd . reset - > trst = = 1 )
{
2009-02-03 05:59:17 +00:00
tap_set_state ( TAP_RESET ) ;
2008-02-28 07:35:51 +00:00
}
amt_jtagaccel_reset ( cmd - > cmd . reset - > trst , cmd - > cmd . reset - > srst ) ;
break ;
case JTAG_RUNTEST :
# ifdef _DEBUG_JTAG_IO_
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " runtest %i cycles, end in %i " , cmd - > cmd . runtest - > num_cycles , cmd - > cmd . runtest - > end_state ) ;
2008-02-28 07:35:51 +00:00
# endif
2009-06-02 07:21:44 +00:00
amt_jtagaccel_end_state ( cmd - > cmd . runtest - > end_state ) ;
2008-02-28 07:35:51 +00:00
amt_jtagaccel_runtest ( cmd - > cmd . runtest - > num_cycles ) ;
break ;
2010-06-05 09:30:49 +00:00
case JTAG_TLR_RESET :
2008-02-28 07:35:51 +00:00
# ifdef _DEBUG_JTAG_IO_
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " statemove end in %i " , cmd - > cmd . statemove - > end_state ) ;
2008-02-28 07:35:51 +00:00
# endif
2009-06-02 07:21:44 +00:00
amt_jtagaccel_end_state ( cmd - > cmd . statemove - > end_state ) ;
2008-02-28 07:35:51 +00:00
amt_jtagaccel_state_move ( ) ;
break ;
case JTAG_SCAN :
# ifdef _DEBUG_JTAG_IO_
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " scan end in %i " , cmd - > cmd . scan - > end_state ) ;
2008-02-28 07:35:51 +00:00
# endif
2009-06-02 07:21:44 +00:00
amt_jtagaccel_end_state ( cmd - > cmd . scan - > end_state ) ;
2008-02-28 07:35:51 +00:00
scan_size = jtag_build_buffer ( cmd - > cmd . scan , & buffer ) ;
type = jtag_scan_type ( cmd - > cmd . scan ) ;
amt_jtagaccel_scan ( cmd - > cmd . scan - > ir_scan , type , buffer , scan_size ) ;
if ( jtag_read_buffer ( buffer , cmd - > cmd . scan ) ! = ERROR_OK )
retval = ERROR_JTAG_QUEUE_FAILED ;
if ( buffer )
free ( buffer ) ;
break ;
case JTAG_SLEEP :
# ifdef _DEBUG_JTAG_IO_
2009-07-23 07:04:21 +00:00
LOG_DEBUG ( " sleep % " PRIi32 , cmd - > cmd . sleep - > us ) ;
2008-02-28 07:35:51 +00:00
# endif
jtag_sleep ( cmd - > cmd . sleep - > us ) ;
break ;
default :
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " BUG: unknown JTAG command type encountered " ) ;
2008-02-28 07:35:51 +00:00
exit ( - 1 ) ;
}
cmd = cmd - > next ;
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
return retval ;
}
# if PARPORT_USE_GIVEIO == 1
2008-08-06 14:36:37 +00:00
int amt_jtagaccel_get_giveio_access ( void )
2008-02-28 07:35:51 +00:00
{
2009-02-03 05:59:17 +00:00
HANDLE h ;
OSVERSIONINFO version ;
2008-02-28 07:35:51 +00:00
2009-02-03 05:59:17 +00:00
version . dwOSVersionInfoSize = sizeof version ;
2009-06-23 22:47:42 +00:00
if ( ! GetVersionEx ( & version ) ) {
2008-12-13 06:25:50 +00:00
errno = EINVAL ;
return - 1 ;
2009-02-03 05:59:17 +00:00
}
if ( version . dwPlatformId ! = VER_PLATFORM_WIN32_NT )
2008-12-13 06:25:50 +00:00
return 0 ;
2008-02-28 07:35:51 +00:00
2009-06-23 22:47:42 +00:00
h = CreateFile ( " \\ \\ . \\ giveio " , GENERIC_READ , 0 , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL ) ;
2009-02-03 05:59:17 +00:00
if ( h = = INVALID_HANDLE_VALUE ) {
2008-12-13 06:25:50 +00:00
errno = ENODEV ;
return - 1 ;
2009-02-03 05:59:17 +00:00
}
2008-02-28 07:35:51 +00:00
2009-06-23 22:47:42 +00:00
CloseHandle ( h ) ;
2008-02-28 07:35:51 +00:00
2009-02-03 05:59:17 +00:00
return 0 ;
2008-02-28 07:35:51 +00:00
}
# endif
2009-04-21 05:29:23 +00:00
static int amt_jtagaccel_init ( void )
2008-02-28 07:35:51 +00:00
{
# if PARPORT_USE_PPDEV == 1
char buffer [ 256 ] ;
int i = 0 ;
2009-06-18 07:07:12 +00:00
uint8_t control_port ;
2008-02-28 07:35:51 +00:00
# else
2009-06-18 07:07:12 +00:00
uint8_t status_port ;
2008-02-28 07:35:51 +00:00
# endif
2009-06-18 07:07:12 +00:00
uint8_t ar_status ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
# if PARPORT_USE_PPDEV == 1
if ( device_handle > 0 )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " device is already opened " ) ;
2008-02-28 07:35:51 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
snprintf ( buffer , 256 , " /dev/parport%d " , amt_jtagaccel_port ) ;
device_handle = open ( buffer , O_RDWR ) ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
if ( device_handle < 0 )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " cannot open device. check it exists and that user read and write rights are set " ) ;
2008-02-28 07:35:51 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
i = ioctl ( device_handle , PPCLAIM ) ;
if ( i < 0 )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " cannot claim device " ) ;
2008-02-28 07:35:51 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
i = IEEE1284_MODE_EPP ;
i = ioctl ( device_handle , PPSETMODE , & i ) ;
if ( i < 0 )
{
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " cannot set compatible mode to device " ) ;
2008-02-28 07:35:51 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
control_port = 0x00 ;
i = ioctl ( device_handle , PPWCONTROL , & control_port ) ;
control_port = 0x04 ;
i = ioctl ( device_handle , PPWCONTROL , & control_port ) ;
# else
if ( amt_jtagaccel_port = = 0 )
{
amt_jtagaccel_port = 0x378 ;
2008-03-25 15:45:17 +00:00
LOG_WARNING ( " No parport port specified, using default '0x378' (LPT1) " ) ;
2008-02-28 07:35:51 +00:00
}
# if PARPORT_USE_GIVEIO == 1
if ( amt_jtagaccel_get_giveio_access ( ) ! = 0 ) {
2008-12-13 06:25:50 +00:00
# else /* PARPORT_USE_GIVEIO */
2008-02-28 07:35:51 +00:00
if ( ioperm ( amt_jtagaccel_port , 5 , 1 ) ! = 0 ) {
# endif /* PARPORT_USE_GIVEIO */
2008-03-25 15:45:17 +00:00
LOG_ERROR ( " missing privileges for direct i/o " ) ;
2008-02-28 07:35:51 +00:00
return ERROR_JTAG_INIT_FAILED ;
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
/* prepare epp port */
/* clear timeout */
status_port = inb ( amt_jtagaccel_port + 1 ) ;
outb ( status_port | 0x1 , amt_jtagaccel_port + 1 ) ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
/* reset epp port */
outb ( 0x00 , amt_jtagaccel_port + 2 ) ;
outb ( 0x04 , amt_jtagaccel_port + 2 ) ;
# endif
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
if ( rtck_enabled )
2008-12-13 06:25:50 +00:00
{
2008-02-28 07:35:51 +00:00
/* set RTCK enable bit */
aw_control_fsm | = 0x02 ;
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
/* enable JTAG port */
aw_control_fsm | = 0x04 ;
AMT_AW ( aw_control_fsm ) ;
2008-12-13 06:25:50 +00:00
2009-06-09 08:40:31 +00:00
enum reset_types jtag_reset_config = jtag_get_reset_config ( ) ;
2008-02-28 07:35:51 +00:00
if ( jtag_reset_config & RESET_TRST_OPEN_DRAIN )
aw_control_rst & = ~ 0x8 ;
else
aw_control_rst | = 0x8 ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
if ( jtag_reset_config & RESET_SRST_PUSH_PULL )
aw_control_rst & = ~ 0x2 ;
else
aw_control_rst | = 0x2 ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
amt_jtagaccel_reset ( 0 , 0 ) ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
/* read status register */
AMT_AR ( ar_status ) ;
2008-03-25 15:45:17 +00:00
LOG_DEBUG ( " AR_STATUS: 0x%2.2x " , ar_status ) ;
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
return ERROR_OK ;
}
2009-04-21 05:29:23 +00:00
static int amt_jtagaccel_quit ( void )
2008-02-28 07:35:51 +00:00
{
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
return ERROR_OK ;
}
2009-11-10 07:56:52 +00:00
COMMAND_HANDLER ( amt_jtagaccel_handle_parport_port_command )
2008-02-28 07:35:51 +00:00
{
2009-11-15 12:57:12 +00:00
if ( CMD_ARGC = = 1 )
2009-06-12 01:40:17 +00:00
{
/* only if the port wasn't overwritten by cmdline */
if ( amt_jtagaccel_port = = 0 )
{
2009-10-23 04:05:50 +00:00
uint16_t port ;
2009-11-15 16:15:59 +00:00
COMMAND_PARSE_NUMBER ( u16 , CMD_ARGV [ 0 ] , port ) ;
2009-10-23 04:05:50 +00:00
amt_jtagaccel_port = port ;
2009-06-12 01:40:17 +00:00
}
else
{
LOG_ERROR ( " The parport port was already configured! " ) ;
return ERROR_FAIL ;
}
}
2008-02-28 07:35:51 +00:00
2009-11-15 13:57:37 +00:00
command_print ( CMD_CTX , " parport port = %u " , amt_jtagaccel_port ) ;
2008-02-28 07:35:51 +00:00
return ERROR_OK ;
}
2009-11-10 07:56:52 +00:00
COMMAND_HANDLER ( amt_jtagaccel_handle_rtck_command )
2008-02-28 07:35:51 +00:00
{
2009-11-15 12:57:12 +00:00
if ( CMD_ARGC = = 0 )
2008-02-28 07:35:51 +00:00
{
2009-11-15 13:57:37 +00:00
command_print ( CMD_CTX , " amt_jtagaccel RTCK feature %s " , ( rtck_enabled ) ? " enabled " : " disabled " ) ;
2008-02-28 07:35:51 +00:00
return ERROR_OK ;
}
else
{
2009-11-15 16:15:59 +00:00
if ( strcmp ( CMD_ARGV [ 0 ] , " enabled " ) = = 0 )
2008-02-28 07:35:51 +00:00
{
rtck_enabled = 1 ;
}
else
{
rtck_enabled = 0 ;
}
}
2008-12-13 06:25:50 +00:00
2008-02-28 07:35:51 +00:00
return ERROR_OK ;
}
2009-11-10 05:21:06 +00:00
2009-11-21 03:53:28 +00:00
static const struct command_registration amtjtagaccel_command_handlers [ ] = {
{
. name = " parport_port " ,
. handler = & amt_jtagaccel_handle_parport_port_command ,
. mode = COMMAND_CONFIG ,
2010-01-03 22:51:01 +00:00
. help = " configure or display the parallel port to use " ,
. usage = " [port_num] " ,
2009-11-21 03:53:28 +00:00
} ,
{
2010-01-03 22:51:01 +00:00
/**
* @ todo Remove this " rtck " command ; just use the standard
* mechanism to enable / disable adaptive clocking . First
* implement the standard mechanism and deprecate " rtck " ;
* after a year or so , it ' ll be safe to remove this .
*/
2010-01-03 21:30:06 +00:00
. name = " rtck " ,
2009-11-21 03:53:28 +00:00
. handler = & amt_jtagaccel_handle_rtck_command ,
. mode = COMMAND_CONFIG ,
2010-01-03 22:51:01 +00:00
. help = " configure or display RTCK support " ,
. usage = " [enable|disable] " ,
2009-11-21 03:53:28 +00:00
} ,
COMMAND_REGISTRATION_DONE
} ;
2009-11-13 12:14:50 +00:00
struct jtag_interface amt_jtagaccel_interface = {
2010-01-03 20:59:51 +00:00
. name = " amt_jtagaccel " ,
. commands = amtjtagaccel_command_handlers ,
. init = amt_jtagaccel_init ,
. quit = amt_jtagaccel_quit ,
. speed = amt_jtagaccel_speed ,
. execute_queue = amt_jtagaccel_execute_queue ,
} ;