+// SPDX-License-Identifier: GPL-2.0-or-later
+
/***************************************************************************
* Copyright (C) 2009 Zachary T Welch *
* zw@superlucidity.net *
* *
* 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, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include "adapter.h"
#include "jtag.h"
#include "swd.h"
#include "interface.h"
/* callbacks to inform high-level handlers about JTAG state changes */
static struct jtag_event_callback *jtag_event_callbacks;
-/* speed in kHz*/
-static int speed_khz;
-/* speed to fallback to when RCLK is requested but not supported */
-static int rclk_fallback_speed_khz;
-static enum {CLOCK_MODE_UNSELECTED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode;
-static int jtag_speed;
-
-/* FIXME: change name to this variable, it is not anymore JTAG only */
-static struct adapter_driver *jtag;
-
extern struct adapter_driver *adapter_driver;
void jtag_set_flush_queue_sleep(int ms)
/************/
-static bool jtag_poll = 1;
+static bool jtag_poll = true;
+static bool jtag_poll_en = true;
bool is_jtag_poll_safe(void)
{
/* Polling can be disabled explicitly with set_enabled(false).
+ * It can also be masked with mask().
* It is also implicitly disabled while TRST is active and
* while SRST is gating the JTAG clock.
*/
+ if (!jtag_poll_en)
+ return false;
+
if (!transport_is_jtag())
return jtag_poll;
jtag_poll = value;
}
+bool jtag_poll_mask(void)
+{
+ bool retval = jtag_poll_en;
+ jtag_poll_en = false;
+ return retval;
+}
+
+void jtag_poll_unmask(bool saved)
+{
+ jtag_poll_en = saved;
+}
+
/************/
struct jtag_tap *jtag_all_taps(void)
unsigned jtag_num_taps = 0;
struct jtag_tap **tap = &__jtag_all_taps;
- while (*tap != NULL) {
+ while (*tap) {
jtag_num_taps++;
tap = &(*tap)->next_tap;
}
struct jtag_tap *t = jtag_all_taps();
while (t) {
- if (0 == strcmp(t->dotted_name, s))
+ if (strcmp(t->dotted_name, s) == 0)
return t;
t = t->next_tap;
}
jtag_add_scan(active, in_num_fields, in_fields, state);
for (int i = 0; i < in_num_fields; i++) {
- if ((in_fields[i].check_value != NULL) && (in_fields[i].in_value != NULL)) {
+ if ((in_fields[i].check_value) && (in_fields[i].in_value)) {
jtag_add_callback4(jtag_check_value_mask_callback,
(jtag_callback_data_t)in_fields[i].in_value,
(jtag_callback_data_t)in_fields[i].check_value,
{
int retval;
- if (!(jtag->jtag_ops->supported & DEBUG_CAP_TMS_SEQ))
+ if (!(adapter_driver->jtag_ops->supported & DEBUG_CAP_TMS_SEQ))
return ERROR_JTAG_NOT_IMPLEMENTED;
jtag_checks();
/* Maybe change SRST signal state */
if (jtag_srst != req_srst) {
- retval = jtag->reset(0, req_srst);
+ retval = adapter_driver->reset(0, req_srst);
if (retval != ERROR_OK) {
LOG_ERROR("SRST error");
return ERROR_FAIL;
int new_srst = 0;
int new_trst = 0;
- if (!jtag->reset) {
+ if (!adapter_driver->reset) {
legacy_jtag_add_reset(req_tlr_or_trst, req_srst);
return;
}
/* guarantee jtag queue empty before changing reset status */
jtag_execute_queue();
- retval = jtag->reset(new_trst, new_srst);
+ retval = adapter_driver->reset(new_trst, new_srst);
if (retval != ERROR_OK) {
jtag_set_error(retval);
LOG_ERROR("TRST/SRST error");
int default_interface_jtag_execute_queue(void)
{
- if (!jtag) {
+ if (!is_adapter_initialized()) {
LOG_ERROR("No JTAG interface configured yet. "
"Issue 'init' command in startup scripts "
"before communicating with targets.");
* The fix can be applied immediately after next release (v0.11.0 ?)
*/
LOG_ERROR("JTAG API jtag_execute_queue() called on non JTAG interface");
- if (!jtag->jtag_ops || !jtag->jtag_ops->execute_queue)
+ if (!adapter_driver->jtag_ops || !adapter_driver->jtag_ops->execute_queue)
return ERROR_OK;
}
- int result = jtag->jtag_ops->execute_queue();
+ struct jtag_command *cmd = jtag_command_queue_get();
+ int result = adapter_driver->jtag_ops->execute_queue(cmd);
- struct jtag_command *cmd = jtag_command_queue;
while (debug_level >= LOG_LVL_DEBUG_IO && cmd) {
switch (cmd->type) {
case JTAG_SCAN:
/* current instruction is either BYPASS or IDCODE */
buf_set_ones(tap->cur_instr, tap->ir_length);
- tap->bypass = 1;
+ tap->bypass = true;
}
return ERROR_OK;
#define JTAG_MAX_AUTO_TAPS 20
-#define EXTRACT_JEP106_BANK(X) (((X) & 0xf00) >> 8)
-#define EXTRACT_JEP106_ID(X) (((X) & 0xfe) >> 1)
#define EXTRACT_MFG(X) (((X) & 0xffe) >> 1)
#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
#define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28)
name, msg,
(unsigned int)idcode,
(unsigned int)EXTRACT_MFG(idcode),
- jep106_manufacturer(EXTRACT_JEP106_BANK(idcode), EXTRACT_JEP106_ID(idcode)),
+ jep106_manufacturer(EXTRACT_MFG(idcode)),
(unsigned int)EXTRACT_PART(idcode),
(unsigned int)EXTRACT_VER(idcode));
}
static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
{
- if (tap->expected_ids_cnt == 0 || !tap->hasidcode)
+ if (tap->expected_ids_cnt == 0 || !tap->has_idcode)
return true;
/* optionally ignore the JTAG version field - bits 28-31 of IDCODE */
return true;
/* treat "-expected-id 0" as a "don't-warn" wildcard */
- if (0 == tap->expected_ids[ii])
+ if (tap->expected_ids[ii] == 0)
return true;
}
jtag_tap_init(tap);
}
- if ((idcode & 1) == 0) {
+ if ((idcode & 1) == 0 && !tap->ignore_bypass) {
/* Zero for LSB indicates a device in bypass */
LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%" PRIx32 ")",
tap->dotted_name, idcode);
- tap->hasidcode = false;
+ tap->has_idcode = false;
tap->idcode = 0;
bit_count += 1;
} else {
/* Friendly devices support IDCODE */
- tap->hasidcode = true;
+ tap->has_idcode = true;
tap->idcode = idcode;
jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found", tap->dotted_name, idcode);
static int jtag_validate_ircapture(void)
{
struct jtag_tap *tap;
- int total_ir_length = 0;
uint8_t *ir_test = NULL;
struct scan_field field;
- uint64_t val;
int chain_pos = 0;
int retval;
/* when autoprobing, accommodate huge IR lengths */
- for (tap = NULL, total_ir_length = 0;
- (tap = jtag_tap_next_enabled(tap)) != NULL;
- total_ir_length += tap->ir_length) {
+ int total_ir_length = 0;
+ for (tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
if (tap->ir_length == 0)
total_ir_length += JTAG_IRLEN_MAX;
+ else
+ total_ir_length += tap->ir_length;
}
/* increase length to add 2 bit sentinel after scan */
*/
if (tap->ir_length == 0) {
tap->ir_length = 2;
- while ((val = buf_get_u64(ir_test, chain_pos, tap->ir_length + 1)) == 1
+ while (buf_get_u64(ir_test, chain_pos, tap->ir_length + 1) == 1
&& tap->ir_length < JTAG_IRLEN_MAX) {
tap->ir_length++;
}
* this part of the JTAG spec, so their capture mask/value
* attributes might disable this test.
*/
- val = buf_get_u64(ir_test, chain_pos, tap->ir_length);
+ uint64_t val = buf_get_u64(ir_test, chain_pos, tap->ir_length);
if ((val & tap->ir_capture_mask) != tap->ir_capture_value) {
LOG_ERROR("%s: IR capture error; saw 0x%0*" PRIx64 " not 0x%0*" PRIx32,
jtag_tap_name(tap),
}
/* verify the '11' sentinel we wrote is returned at the end */
- val = buf_get_u64(ir_test, chain_pos, 2);
+ uint64_t val = buf_get_u64(ir_test, chain_pos, 2);
if (val != 0x3) {
char *cbuf = buf_to_hex_str(ir_test, total_ir_length);
buf_set_u32(tap->expected_mask, 0, ir_len_bits, tap->ir_capture_mask);
/* TAP will be in bypass mode after jtag_validate_ircapture() */
- tap->bypass = 1;
+ tap->bypass = true;
buf_set_ones(tap->cur_instr, tap->ir_length);
/* register the reset callback for the TAP */
free(tap);
}
-/**
- * Do low-level setup like initializing registers, output signals,
- * and clocking.
- */
-int adapter_init(struct command_context *cmd_ctx)
-{
- if (jtag)
- return ERROR_OK;
-
- if (!adapter_driver) {
- /* nothing was previously specified by "adapter driver" command */
- LOG_ERROR("Debug Adapter has to be specified, "
- "see \"adapter driver\" command");
- return ERROR_JTAG_INVALID_INTERFACE;
- }
-
- int retval;
- retval = adapter_driver->init();
- if (retval != ERROR_OK)
- return retval;
- jtag = adapter_driver;
-
- if (!jtag->speed) {
- LOG_INFO("This adapter doesn't support configurable speed");
- return ERROR_OK;
- }
-
- if (clock_mode == CLOCK_MODE_UNSELECTED) {
- LOG_ERROR("An adapter speed is not selected in the init script."
- " Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed.");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- int requested_khz = jtag_get_speed_khz();
- int actual_khz = requested_khz;
- int jtag_speed_var = 0;
- retval = jtag_get_speed(&jtag_speed_var);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag->speed(jtag_speed_var);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_get_speed_readable(&actual_khz);
- if (retval != ERROR_OK)
- LOG_INFO("adapter-specific clock speed value %d", jtag_speed_var);
- else if (actual_khz) {
- /* Adaptive clocking -- JTAG-specific */
- if ((clock_mode == CLOCK_MODE_RCLK)
- || ((clock_mode == CLOCK_MODE_KHZ) && !requested_khz)) {
- LOG_INFO("RCLK (adaptive clock speed) not supported - fallback to %d kHz"
- , actual_khz);
- } else
- LOG_INFO("clock speed %d kHz", actual_khz);
- } else
- LOG_INFO("RCLK (adaptive clock speed)");
-
- return ERROR_OK;
-}
-
int jtag_init_inner(struct command_context *cmd_ctx)
{
struct jtag_tap *tap;
return ERROR_OK;
}
-int adapter_quit(void)
-{
- if (jtag && jtag->quit) {
- /* close the JTAG interface */
- int result = jtag->quit();
- if (result != ERROR_OK)
- LOG_ERROR("failed: %d", result);
- }
-
- struct jtag_tap *t = jtag_all_taps();
- while (t) {
- struct jtag_tap *n = t->next_tap;
- jtag_tap_free(t);
- t = n;
- }
-
- return ERROR_OK;
-}
-
int swd_init_reset(struct command_context *cmd_ctx)
{
int retval, retval1;
return ERROR_OK;
}
-unsigned jtag_get_speed_khz(void)
-{
- return speed_khz;
-}
-
-static int adapter_khz_to_speed(unsigned khz, int *speed)
-{
- LOG_DEBUG("convert khz to interface specific speed value");
- speed_khz = khz;
- if (!jtag)
- return ERROR_OK;
- LOG_DEBUG("have interface set up");
- if (!jtag->khz) {
- LOG_ERROR("Translation from khz to jtag_speed not implemented");
- return ERROR_FAIL;
- }
- int speed_div1;
- int retval = jtag->khz(jtag_get_speed_khz(), &speed_div1);
- if (retval != ERROR_OK)
- return retval;
- *speed = speed_div1;
- return ERROR_OK;
-}
-
-static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int *speed)
-{
- int retval = adapter_khz_to_speed(0, speed);
- if ((retval != ERROR_OK) && fallback_speed_khz) {
- LOG_DEBUG("trying fallback speed...");
- retval = adapter_khz_to_speed(fallback_speed_khz, speed);
- }
- return retval;
-}
-
-static int jtag_set_speed(int speed)
-{
- jtag_speed = speed;
- /* this command can be called during CONFIG,
- * in which case jtag isn't initialized */
- return jtag ? jtag->speed(speed) : ERROR_OK;
-}
-
-int jtag_config_khz(unsigned khz)
-{
- LOG_DEBUG("handle jtag khz");
- clock_mode = CLOCK_MODE_KHZ;
- int speed = 0;
- int retval = adapter_khz_to_speed(khz, &speed);
- return (retval != ERROR_OK) ? retval : jtag_set_speed(speed);
-}
-
-int jtag_config_rclk(unsigned fallback_speed_khz)
-{
- LOG_DEBUG("handle jtag rclk");
- clock_mode = CLOCK_MODE_RCLK;
- rclk_fallback_speed_khz = fallback_speed_khz;
- int speed = 0;
- int retval = jtag_rclk_to_speed(fallback_speed_khz, &speed);
- return (retval != ERROR_OK) ? retval : jtag_set_speed(speed);
-}
-
-int jtag_get_speed(int *speed)
-{
- switch (clock_mode) {
- case CLOCK_MODE_KHZ:
- adapter_khz_to_speed(jtag_get_speed_khz(), speed);
- break;
- case CLOCK_MODE_RCLK:
- jtag_rclk_to_speed(rclk_fallback_speed_khz, speed);
- break;
- default:
- LOG_ERROR("BUG: unknown jtag clock mode");
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-int jtag_get_speed_readable(int *khz)
-{
- int jtag_speed_var = 0;
- int retval = jtag_get_speed(&jtag_speed_var);
- if (retval != ERROR_OK)
- return retval;
- if (!jtag)
- return ERROR_OK;
- if (!jtag->speed_div) {
- LOG_ERROR("Translation from jtag_speed to khz not implemented");
- return ERROR_FAIL;
- }
- return jtag->speed_div(jtag_speed_var, khz);
-}
-
void jtag_set_verify(bool enable)
{
jtag_verify = enable;
int jtag_power_dropout(int *dropout)
{
- if (!jtag) {
+ if (!is_adapter_initialized()) {
/* TODO: as the jtag interface is not valid all
* we can do at the moment is exit OpenOCD */
LOG_ERROR("No Valid JTAG Interface Configured.");
exit(-1);
}
- if (jtag->power_dropout)
- return jtag->power_dropout(dropout);
+ if (adapter_driver->power_dropout)
+ return adapter_driver->power_dropout(dropout);
*dropout = 0; /* by default we can't detect power dropout */
return ERROR_OK;
int jtag_srst_asserted(int *srst_asserted)
{
- if (jtag->srst_asserted)
- return jtag->srst_asserted(srst_asserted);
+ if (adapter_driver->srst_asserted)
+ return adapter_driver->srst_asserted(srst_asserted);
*srst_asserted = 0; /* by default we can't detect srst asserted */
return ERROR_OK;
int adapter_resets(int trst, int srst)
{
- if (get_current_transport() == NULL) {
+ if (!get_current_transport()) {
LOG_ERROR("transport is not selected");
return ERROR_FAIL;
}
transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() ||
transport_is_swim())
return adapter_system_reset(1);
- else if (get_current_transport() != NULL)
+ else if (get_current_transport())
LOG_ERROR("reset is not supported on %s",
get_current_transport()->name);
else
transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() ||
transport_is_swim())
return adapter_system_reset(0);
- else if (get_current_transport() != NULL)
+ else if (get_current_transport())
LOG_ERROR("reset is not supported on %s",
get_current_transport()->name);
else
uint32_t port_size, unsigned int *trace_freq,
unsigned int traceclkin_freq, uint16_t *prescaler)
{
- if (jtag->config_trace) {
- return jtag->config_trace(enabled, pin_protocol, port_size, trace_freq,
+ if (adapter_driver->config_trace) {
+ return adapter_driver->config_trace(enabled, pin_protocol, port_size, trace_freq,
traceclkin_freq, prescaler);
} else if (enabled) {
LOG_ERROR("The selected interface does not support tracing");
int adapter_poll_trace(uint8_t *buf, size_t *size)
{
- if (jtag->poll_trace)
- return jtag->poll_trace(buf, size);
+ if (adapter_driver->poll_trace)
+ return adapter_driver->poll_trace(buf, size);
return ERROR_FAIL;
}