/***************************************************************************
* Copyright (C) 2008 digenius technology GmbH. *
* Michael Bruck *
* *
* Copyright (C) 2008,2009 Oyvind Harboe oyvind.harboe@zylin.com *
* *
* 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
#include "arm_jtag.h"
#include "arm11_dbgtap.h"
#include <helper/time_support.h>
#if 0
#define JTAG_DEBUG(expr ...) do { if (1) \
LOG_DEBUG(expr); } while (0)
#else
#define JTAG_DEBUG(expr ...) do { if (0) \
LOG_DEBUG(expr); } while (0)
#endif
/*
This pathmove goes from Pause-IR to Shift-IR while avoiding RTI. The
behavior of the FTDI driver IIRC was to go via RTI.
Conversely there may be other places in this code where the ARM11 code relies
on the driver to hit through RTI when coming from Update-?R.
*/
static const tap_state_t arm11_move_pi_to_si_via_ci[] = {
TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IRSHIFT
};
/* REVISIT no error handling here! */
static void arm11_add_ir_scan_vc(struct jtag_tap *tap, struct scan_field *fields,
tap_state_t state)
{
if (cmd_queue_cur_state == TAP_IRPAUSE)
jtag_add_pathmove(ARRAY_SIZE(arm11_move_pi_to_si_via_ci),
arm11_move_pi_to_si_via_ci);
jtag_add_ir_scan(tap, fields, state);
}
static const tap_state_t arm11_move_pd_to_sd_via_cd[] = {
TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT
};
/* REVISIT no error handling here! */
void arm11_add_dr_scan_vc(struct jtag_tap *tap, int num_fields, struct scan_field *fields,
tap_state_t state)
{
if (cmd_queue_cur_state == TAP_DRPAUSE)
jtag_add_pathmove(ARRAY_SIZE(arm11_move_pd_to_sd_via_cd),
arm11_move_pd_to_sd_via_cd);
jtag_add_dr_scan(tap, num_fields, fields, state);
}
/** Code de-clutter: Construct struct scan_field to write out a value
*
* \param arm11 Target state variable.
* \param num_bits Length of the data field
* \param out_data pointer to the data that will be sent out
* <em > (data is read when it is added to the JTAG queue)</em>
* \param in_data pointer to the memory that will receive data that was clocked in
* <em > (data is written when the JTAG queue is executed)</em>
* \param field target data structure that will be initialized
*/
void arm11_setup_field(struct arm11_common *arm11, int num_bits,
void *out_data, void *in_data, struct scan_field *field)
{
field->num_bits = num_bits;
field->out_value = out_data;
field->in_value = in_data;
}
static const char *arm11_ir_to_string(uint8_t ir)
{
const char *s = "unknown";
switch (ir) {
case ARM11_EXTEST:
s = "EXTEST";
break;
case ARM11_SCAN_N:
s = "SCAN_N";
break;
case ARM11_RESTART:
s = "RESTART";
break;
case ARM11_HALT:
s = "HALT";
break;
case ARM11_INTEST:
s = "INTEST";
break;
case ARM11_ITRSEL:
s = "ITRSEL";
break;
case ARM11_IDCODE:
s = "IDCODE";
break;
case ARM11_BYPASS:
s = "BYPASS";
break;
}
return s;
}
/** Write JTAG instruction register
*
* \param arm11 Target state variable.
* \param instr An ARM11 DBGTAP instruction. Use enum #arm11_instructions.
* \param state Pass the final TAP state or ARM11_TAP_DEFAULT for the default value (Pause-IR).
*
* \remarks This adds to the JTAG command queue but does \em not execute it.
*/
void arm11_add_IR(struct arm11_common *arm11, uint8_t instr, tap_state_t<