static uint16_t direction;
static uint16_t jtag_output_init;
static uint16_t jtag_direction_init;
-static uint16_t swd_output_init;
-static uint16_t swd_direction_init;
-static int ftdi_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq);
+static int ftdi_swd_switch_seq(enum swd_special_seq seq);
static struct signal *find_signal_by_name(const char *name)
{
ftdi_set_signal(trst, '0');
else
LOG_ERROR("Can't assert TRST: nTRST signal is not defined");
- } else if (trst && cmd->cmd.reset->trst == 0) {
+ } else if (trst && jtag_get_reset_config() & RESET_HAS_TRST &&
+ cmd->cmd.reset->trst == 0) {
if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN)
ftdi_set_signal(trst, 'z');
else
ftdi_set_signal(srst, '0');
else
LOG_ERROR("Can't assert SRST: nSRST signal is not defined");
- } else if (srst && cmd->cmd.reset->srst == 0) {
+ } else if (srst && jtag_get_reset_config() & RESET_HAS_SRST &&
+ cmd->cmd.reset->srst == 0) {
if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL)
ftdi_set_signal(srst, '1');
else
if (!mpsse_ctx)
return ERROR_JTAG_INIT_FAILED;
- output = swd_mode ? swd_output_init : jtag_output_init;
- direction = swd_mode ? swd_direction_init : jtag_direction_init;
+ output = jtag_output_init;
+ direction = jtag_direction_init;
+
+ if (swd_mode) {
+ struct signal *sig = find_signal_by_name("SWD_EN");
+ if (!sig) {
+ LOG_ERROR("SWD mode is active but SWD_EN signal is not defined");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+ /* A dummy SWD_EN would have zero mask */
+ if (sig->data_mask)
+ ftdi_set_signal(sig, '1');
+ }
mpsse_set_data_bits_low_byte(mpsse_ctx, output & 0xff, direction & 0xff);
mpsse_set_data_bits_high_byte(mpsse_ctx, output >> 8, direction >> 8);
mpsse_loopback_config(mpsse_ctx, false);
- /* Set a low default */
- freq = mpsse_set_frequency(mpsse_ctx, 1000);
-
- if (swd_mode)
- ftdi_swd_switch_seq(NULL, JTAG_TO_SWD);
- else
- ftdi_swd_switch_seq(NULL, SWD_TO_JTAG);
+ freq = mpsse_set_frequency(mpsse_ctx, jtag_get_speed_khz() * 1000);
return mpsse_flush(mpsse_ctx);
}
{
mpsse_close(mpsse_ctx);
+ free(swd_cmd_queue);
+
return ERROR_OK;
}
return ERROR_OK;
}
-COMMAND_HANDLER(ftdi_handle_layout_init_swd_command)
-{
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], swd_output_init);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], swd_direction_init);
-
- return ERROR_OK;
-}
-
COMMAND_HANDLER(ftdi_handle_layout_signal_command)
{
if (CMD_ARGC < 1)
} else if (strcmp("-noe", CMD_ARGV[i]) == 0) {
invert_oe = true;
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], oe_mask);
+ } else if (!strcmp("-alias", CMD_ARGV[i]) ||
+ !strcmp("-nalias", CMD_ARGV[i])) {
+ if (!strcmp("-nalias", CMD_ARGV[i]))
+ invert_data = true;
+ struct signal *sig = find_signal_by_name(CMD_ARGV[i + 1]);
+ if (!sig) {
+ LOG_ERROR("signal %s is not defined", CMD_ARGV[i + 1]);
+ return ERROR_FAIL;
+ }
+ data_mask = sig->data_mask;
+ oe_mask = sig->oe_mask;
+ invert_oe = sig->invert_oe;
+ invert_data ^= sig->invert_data;
} else {
LOG_ERROR("unknown option '%s'", CMD_ARGV[i]);
return ERROR_COMMAND_SYNTAX_ERROR;
.handler = &ftdi_handle_layout_init_command,
.mode = COMMAND_CONFIG,
.help = "initialize the FTDI GPIO signals used "
- "to control output-enables and reset signals"
- "when JTAG mode is selected",
- .usage = "data direction",
- },
- {
- .name = "ftdi_layout_init_swd",
- .handler = &ftdi_handle_layout_init_swd_command,
- .mode = COMMAND_CONFIG,
- .help = "initialize the FTDI GPIO signals used "
- "to control output-enables and reset signals"
- "when SWD mode is selected",
+ "to control output-enables and reset signals",
.usage = "data direction",
},
{
.mode = COMMAND_ANY,
.help = "define a signal controlled by one or more FTDI GPIO as data "
"and/or output enable",
- .usage = "name [-data mask|-ndata mask] [-oe mask|-noe mask]",
+ .usage = "name [-data mask|-ndata mask] [-oe mask|-noe mask] [-alias|-nalias name]",
},
{
.name = "ftdi_set_signal",
COMMAND_REGISTRATION_DONE
};
+static int create_default_signal(const char *name, uint16_t data_mask)
+{
+ struct signal *sig = create_signal(name);
+ if (!sig) {
+ LOG_ERROR("failed to create signal %s", name);
+ return ERROR_FAIL;
+ }
+ sig->invert_data = false;
+ sig->data_mask = data_mask;
+ sig->invert_oe = false;
+ sig->oe_mask = 0;
+
+ return ERROR_OK;
+}
+
+static int create_signals(void)
+{
+ if (create_default_signal("TCK", 0x01) != ERROR_OK)
+ return ERROR_FAIL;
+ if (create_default_signal("TDI", 0x02) != ERROR_OK)
+ return ERROR_FAIL;
+ if (create_default_signal("TDO", 0x04) != ERROR_OK)
+ return ERROR_FAIL;
+ if (create_default_signal("TMS", 0x08) != ERROR_OK)
+ return ERROR_FAIL;
+ return ERROR_OK;
+}
+
static int ftdi_swd_init(void)
{
LOG_INFO("FTDI SWD mode enabled");
swd_mode = true;
+ if (create_signals() != ERROR_OK)
+ return ERROR_FAIL;
+
swd_cmd_queue_alloced = 10;
swd_cmd_queue = malloc(swd_cmd_queue_alloced * sizeof(*swd_cmd_queue));
* @param dap
* @return
*/
-static int ftdi_swd_run_queue(struct adiv5_dap *dap)
+static int ftdi_swd_run_queue(void)
{
LOG_DEBUG("Executing %zu queued transactions", swd_cmd_queue_length);
int retval;
}
for (size_t i = 0; i < swd_cmd_queue_length; i++) {
- int ack = buf_get_u32(&swd_cmd_queue[i].trn_ack_data_parity_trn, 1, 3);
+ int ack = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1, 3);
LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
1 + 3 + (swd_cmd_queue[i].cmd & SWD_CMD_RnW ? 0 : 1), 32));
if (ack != SWD_ACK_OK) {
- queued_retval = ack;
+ queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
goto skip;
} else if (swd_cmd_queue[i].cmd & SWD_CMD_RnW) {
return retval;
}
-static void ftdi_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd, uint32_t *dst, uint32_t data)
+static void ftdi_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk)
{
if (swd_cmd_queue_length >= swd_cmd_queue_alloced) {
/* Not enough room in the queue. Run the queue and increase its size for next time.
* Note that it's not possible to avoid running the queue here, because mpsse contains
* pointers into the queue which may be invalid after the realloc. */
- queued_retval = ftdi_swd_run_queue(dap);
+ queued_retval = ftdi_swd_run_queue();
struct swd_cmd_queue_entry *q = realloc(swd_cmd_queue, swd_cmd_queue_alloced * 2 * sizeof(*swd_cmd_queue));
if (q != NULL) {
swd_cmd_queue = q;
/* Insert idle cycles after AP accesses to avoid WAIT */
if (cmd & SWD_CMD_APnDP)
- mpsse_clock_data_out(mpsse_ctx, NULL, 0, dap->memaccess_tck, SWD_MODE);
+ mpsse_clock_data_out(mpsse_ctx, NULL, 0, ap_delay_clk, SWD_MODE);
}
-static void ftdi_swd_read_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t *value)
+static void ftdi_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
{
assert(cmd & SWD_CMD_RnW);
- ftdi_swd_queue_cmd(dap, cmd, value, 0);
+ ftdi_swd_queue_cmd(cmd, value, 0, ap_delay_clk);
}
-static void ftdi_swd_write_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t value)
+static void ftdi_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
{
assert(!(cmd & SWD_CMD_RnW));
- ftdi_swd_queue_cmd(dap, cmd, NULL, value);
+ ftdi_swd_queue_cmd(cmd, NULL, value, ap_delay_clk);
}
-static int_least32_t ftdi_swd_frequency(struct adiv5_dap *dap, int_least32_t hz)
+static int_least32_t ftdi_swd_frequency(int_least32_t hz)
{
if (hz > 0)
freq = mpsse_set_frequency(mpsse_ctx, hz);
return freq;
}
-static int ftdi_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq)
+static int ftdi_swd_switch_seq(enum swd_special_seq seq)
{
switch (seq) {
case LINE_RESET: