diff --git a/.gitignore b/.gitignore
index 5de33077e..f0746c195 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,9 +11,9 @@
 *.la
 *.in
 
-# generated source files
-src/jtag/minidriver_imp.h
-src/jtag/jtag_minidriver.h
+# coverage files (gcov)
+*.gcda
+*.gcno
 
 # OpenULINK driver files generated by SDCC
 src/jtag/drivers/OpenULINK/*.rel
diff --git a/.gitmodules b/.gitmodules
index f2da17ed7..abb773538 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
-[submodule "tools/git2cl"]
-	path = tools/git2cl
-	url = https://git.savannah.nongnu.org/git/git2cl.git
 [submodule "jimtcl"]
 	path = jimtcl
 	url = https://github.com/msteveb/jimtcl.git
diff --git a/HACKING b/HACKING
index c023a50a3..b1d224dbf 100644
--- a/HACKING
+++ b/HACKING
@@ -118,6 +118,22 @@ patch:
   make
   @endcode
 
+- Code coverage analysis
+
+  By inspecting the code coverage, you can identify potential gaps in your testing
+  and use that information to improve your test scenarios.
+
+  Example usage:
+  @code
+  mkdir build-gcov; cd build-gcov
+  ../configure --enable-gcov [...]
+  make
+  # ... Now execute your test scenarios to collect OpenOCD code coverage ...
+  lcov --capture --directory ./src --output-file openocd-coverage.info
+  genhtml openocd-coverage.info --output-directory coverage_report
+  # ... Open coverage_report/index.html in a web browser ...
+  @endcode
+
 Please consider performing these additional checks where appropriate
 (especially Clang Static Analyzer for big portions of new code) and
 mention the results (e.g. "Valgrind-clean, no new Clang analyzer
diff --git a/Makefile.am b/Makefile.am
index 2230e628f..155a2b3bb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,6 +38,7 @@ endif
 
 # common flags used in openocd build
 AM_CFLAGS = $(GCC_WARNINGS)
+AM_LDFLAGS =
 
 AM_CPPFLAGS = $(HOST_CPPFLAGS)\
 			  -I$(top_srcdir)/src \
@@ -51,6 +52,12 @@ AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \
 else
 AM_CPPFLAGS += $(JIMTCL_CFLAGS)
 endif
+
+if USE_GCOV
+AM_CFLAGS += --coverage
+AM_LDFLAGS += --coverage
+endif
+
 EXTRA_DIST += \
 	BUGS \
 	HACKING \
@@ -116,14 +123,13 @@ TCL_PATH = tcl
 TCL_FILES = find $(srcdir)/$(TCL_PATH) -name '*.cfg' -o -name '*.tcl' -o -name '*.txt' | \
 		sed -e 's,^$(srcdir)/$(TCL_PATH),,'
 
-# Without the PERL_UNICODE="IO" workaround below when running git2cl, you get several
-# "Wide character" warnings and you also risk an invalid character encoding in
-# the generated ChangeLog file. For more information, see this bug report:
-#   Warning "Wide character in print"
-#   https://savannah.nongnu.org/bugs/?65689
+# The git log command below generates many empty text lines with only some space characters
+# for indentation purposes, so use sed to trim all trailing whitespace.
 dist-hook:
 	if test -d $(srcdir)/.git -a \( ! -e $(distdir)/ChangeLog -o -w $(distdir)/ChangeLog \) ; then \
-		git --git-dir $(srcdir)/.git log | PERL_UNICODE="IO" $(srcdir)/tools/git2cl/git2cl > $(distdir)/ChangeLog ; \
+		git --git-dir $(srcdir)/.git log --date=short --pretty="format:%ad  %aN <%aE>%n%n%w(0,4,6)* %B" \
+		| sed 's/[[:space:]]*$$//' > $(distdir)/ChangeLog.tmp && \
+		mv $(distdir)/ChangeLog.tmp $(distdir)/ChangeLog; \
 	fi
 	for i in $$($(TCL_FILES)); do \
 		j="$(distdir)/$(TCL_PATH)/$$i" && \
diff --git a/bootstrap b/bootstrap
index 7d4ca37bd..9dfdc41ac 100755
--- a/bootstrap
+++ b/bootstrap
@@ -3,8 +3,8 @@
 
 # Run the autotools bootstrap sequence to create the configure script
 
-# Abort execution on error
-set -e
+set -e  # Abort execution on error.
+set -u  # Abort if you reference an undefined variable.
 
 if which libtoolize > /dev/null; then
     libtoolize="libtoolize"
@@ -15,13 +15,21 @@ else
     exit 1
 fi
 
-if [ "$1" = "nosubmodule" ]; then
-    SKIP_SUBMODULE=1
-elif [ -n "$1" ]; then
-    echo "$0: Illegal argument $1"
-    echo "USAGE: $0 [nosubmodule]"
-    exit 1
-fi
+SKIP_SUBMODULE=0
+
+case "$#" in
+    0) ;;
+    1) if [ "$1" = "nosubmodule" ]; then
+           SKIP_SUBMODULE=1
+       else
+           echo "$0: Illegal argument $1" >&2
+           echo "USAGE: $0 [nosubmodule]" >&2
+           exit 1
+       fi;;
+   *)  echo "$0: Wrong number of command-line arguments." >&2
+       echo "USAGE: $0 [nosubmodule]" >&2
+       exit 1;;
+esac
 
 # bootstrap the autotools
 (
@@ -34,7 +42,7 @@ autoheader --warnings=all
 automake --warnings=all --gnu --add-missing --copy
 )
 
-if [ -n "$SKIP_SUBMODULE" ]; then
+if [ "$SKIP_SUBMODULE" -ne 0 ]; then
     echo "Skipping submodule setup"
 else
     echo "Setting up submodules"
diff --git a/configure.ac b/configure.ac
index c28a5b79f..34c8cbdd7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -172,6 +172,9 @@ m4_define([DUMMY_ADAPTER],
 m4_define([OPTIONAL_LIBRARIES],
 	[[[capstone], [Use Capstone disassembly framework], []]])
 
+m4_define([COVERAGE],
+	[[[gcov], [Collect coverage using gcov], []]])
+
 AC_ARG_ENABLE([doxygen-html],
   AS_HELP_STRING([--disable-doxygen-html],
     [Disable building Doxygen manual as HTML.]),
@@ -200,6 +203,19 @@ AC_ARG_ENABLE([werror],
   AS_HELP_STRING([--disable-werror], [Do not treat warnings as errors]),
   [gcc_werror=$enableval], [gcc_werror=$gcc_warnings])
 
+AC_ARG_ENABLE([gcov],
+  AS_HELP_STRING([--enable-gcov], [Enable runtime coverage collection via gcov]),
+  [enable_gcov=$enableval], [enable_gcov=no])
+
+AS_IF([test "x$enable_gcov" = "xyes"], [
+  AC_DEFINE([USE_GCOV], [1], [1 to enable coverage collection using gcov.])
+  dnl When collecting coverage, disable optimizations.
+  dnl This overrides the "-O2" that autoconf uses by default:
+  CFLAGS+=" -O0"
+], [
+  AC_DEFINE([USE_GCOV], [0], [0 to leave coverage collection disabled.])
+])
+
 # set default verbose options, overridden by following options
 debug_usb_io=no
 debug_usb_comms=no
@@ -257,9 +273,13 @@ AC_ARG_ENABLE([dmem],
 m4_define([AC_ARG_ADAPTERS], [
   m4_foreach([adapter], [$1],
 	[AC_ARG_ENABLE(ADAPTER_OPT([adapter]),
-		AS_HELP_STRING([--enable-ADAPTER_OPT([adapter])],
+		AS_HELP_STRING([--enable-ADAPTER_OPT([adapter])[[[=yes/no/auto]]]],
 			[Enable building support for the ]ADAPTER_DESC([adapter])[ (default is $2)]),
-		[], [ADAPTER_VAR([adapter])=$2])
+		[case "${enableval}" in
+			yes|no|auto) ;;
+			*) AC_MSG_ERROR([Option --enable-ADAPTER_OPT([adapter]) has invalid value "${enableval}".]) ;;
+			esac],
+		[ADAPTER_VAR([adapter])=$2])
   ])
 ])
 
@@ -268,7 +288,7 @@ AC_ARG_ADAPTERS([
   HIDAPI_ADAPTERS,
   HIDAPI_USB1_ADAPTERS,
   LIBFTDI_ADAPTERS,
-  LIBFTDI_USB1_ADAPTERS
+  LIBFTDI_USB1_ADAPTERS,
   LIBGPIOD_ADAPTERS,
   SERIAL_PORT_ADAPTERS,
   PCIE_ADAPTERS,
@@ -357,10 +377,6 @@ AS_CASE([$host_os],
       AC_MSG_ERROR([sysfsgpio is only available on linux])
     ])
 
-    AS_IF([test "x$enable_linuxgpiod" = "xyes"], [
-      AC_MSG_ERROR([linuxgpiod is only available on linux])
-    ])
-
     AS_CASE([$host_os], [freebsd*], [],
     [
       AS_IF([test "x$build_rshim" = "xyes"], [
@@ -399,6 +415,8 @@ AS_CASE(["${host_cpu}"],
     parport_use_ppdev=yes
 ])
 
+can_build_buspirate=yes
+
 AS_CASE([$host],
   [*-cygwin*], [
     is_win32=yes
@@ -430,12 +448,12 @@ AS_CASE([$host],
     ])
     parport_use_giveio=yes
 
-    AS_IF([test "x$enable_buspirate" = "xyes"], [
-      AC_MSG_ERROR([buspirate currently not supported by MinGW32 hosts])
+    AS_IF([test "x$ADAPTER_VAR([buspirate])" = "xyes"], [
+      AC_MSG_ERROR([The Bus Pirate adapter is currently not supported by MinGW32 hosts.])
     ])
 
     # In case enable_buspirate=auto, make sure it will not be built.
-    enable_buspirate=no
+    can_build_buspirate=no
 
     AC_SUBST([HOST_CPPFLAGS], ["-D__USE_MINGW_ANSI_STDIO -DFD_SETSIZE=128"])
   ],
@@ -579,12 +597,6 @@ AS_IF([test "x$build_gw16012" = "xyes"], [
   AC_DEFINE([BUILD_GW16012], [0], [0 if you don't want the Gateworks GW16012 driver.])
 ])
 
-AS_IF([test "x$enable_buspirate" != "xno"], [
-  AC_DEFINE([BUILD_BUSPIRATE], [1], [1 if you want the Buspirate JTAG driver.])
-], [
-  AC_DEFINE([BUILD_BUSPIRATE], [0], [0 if you don't want the Buspirate JTAG driver.])
-])
-
 AS_IF([test "x$use_internal_jimtcl" = "xyes"], [
   AS_IF([test -f "$srcdir/jimtcl/configure"], [
     AS_IF([test "x$use_internal_jimtcl_maintainer" = "xyes"], [
@@ -697,7 +709,7 @@ m4_define([PROCESS_ADAPTERS], [
 		])
 	], [
 		AS_IF([test "x$ADAPTER_VAR([adapter])" = "xyes"], [
-			AC_MSG_ERROR([$3 is required for [adapter] ADAPTER_DESC([adapter]).])
+			AC_MSG_ERROR([$3 is required for [adapter] "ADAPTER_DESC([adapter])".])
 		])
 		ADAPTER_VAR([adapter])=no
 		AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [0], [0 if you do not want the ]ADAPTER_DESC([adapter]).)
@@ -711,9 +723,11 @@ PROCESS_ADAPTERS([HIDAPI_ADAPTERS], ["x$use_hidapi" = "xyes"], [hidapi])
 PROCESS_ADAPTERS([HIDAPI_USB1_ADAPTERS], ["x$use_hidapi" = "xyes" -a "x$use_libusb1" = "xyes"], [hidapi and libusb-1.x])
 PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi])
 PROCESS_ADAPTERS([LIBFTDI_USB1_ADAPTERS], ["x$use_libftdi" = "xyes" -a "x$use_libusb1" = "xyes"], [libftdi and libusb-1.x])
-PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [libgpiod])
+PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [Linux libgpiod])
 PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2])
 PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build])
+PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"],
+                                         [internal error: validation should happen beforehand])
 PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused])
 
 AS_IF([test "x$enable_linuxgpiod" != "xno"], [
@@ -768,7 +782,6 @@ AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x
 AM_CONDITIONAL([AMTJTAGACCEL], [test "x$build_amtjtagaccel" = "xyes"])
 AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"])
 AM_CONDITIONAL([REMOTE_BITBANG], [test "x$build_remote_bitbang" = "xyes"])
-AM_CONDITIONAL([BUSPIRATE], [test "x$enable_buspirate" != "xno"])
 AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"])
 AM_CONDITIONAL([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"])
 AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"])
@@ -788,6 +801,8 @@ AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"])
 AM_CONDITIONAL([HAVE_JIMTCL_PKG_CONFIG], [test "x$have_jimtcl_pkg_config" = "xyes"])
 AM_CONDITIONAL([INTERNAL_LIBJAYLINK], [test "x$use_internal_libjaylink" = "xyes"])
 
+AM_CONDITIONAL([USE_GCOV], [test "x$enable_gcov" = "xyes"])
+
 # Look for environ alternatives.  Possibility #1: is environ in unistd.h or stdlib.h?
 AC_MSG_CHECKING([for environ in unistd.h and stdlib.h])
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@@ -863,7 +878,8 @@ m4_foreach([adapter], [USB1_ADAPTERS,
 	LIBGPIOD_ADAPTERS,
 	LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS,
 	DUMMY_ADAPTER,
-	OPTIONAL_LIBRARIES],
+	OPTIONAL_LIBRARIES,
+	COVERAGE],
 	[s=m4_format(["%-40s"], ADAPTER_DESC([adapter]))
 	AS_CASE([$ADAPTER_VAR([adapter])],
 		[auto], [
@@ -874,6 +890,11 @@ m4_foreach([adapter], [USB1_ADAPTERS,
 		],
 		[no], [
 			echo "$s"no
+		],
+		[
+			AC_MSG_ERROR(m4_normalize([
+				Error in [adapter] "ADAPTER_ARG([adapter])": Variable "ADAPTER_VAR([adapter])"
+				has invalid value "$ADAPTER_VAR([adapter])".]))
 	])
 ])
 echo
diff --git a/src/helper/jim-nvp.h b/src/helper/jim-nvp.h
index 11824cabf..45af6c867 100644
--- a/src/helper/jim-nvp.h
+++ b/src/helper/jim-nvp.h
@@ -19,6 +19,7 @@
 #ifndef OPENOCD_HELPER_JIM_NVP_H
 #define OPENOCD_HELPER_JIM_NVP_H
 
+#include <stdbool.h>
 #include <jim.h>
 
 /** Name Value Pairs, aka: NVP
@@ -136,7 +137,7 @@ struct jim_getopt_info {
 	Jim_Interp *interp;
 	int argc;
 	Jim_Obj *const *argv;
-	int isconfigure;		/* non-zero if configure */
+	bool is_configure;
 };
 
 /** GetOpt - how to.
diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c
index 996a23f1f..04942f753 100644
--- a/src/jtag/adapter.c
+++ b/src/jtag/adapter.c
@@ -66,6 +66,8 @@ static const struct gpio_map {
 	[ADAPTER_GPIO_IDX_LED] = { "led", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
 };
 
+static int adapter_config_khz(unsigned int khz);
+
 bool is_adapter_initialized(void)
 {
 	return adapter_config.adapter_initialized;
@@ -245,7 +247,8 @@ static int adapter_set_speed(int speed)
 	return is_adapter_initialized() ? adapter_driver->speed(speed) : ERROR_OK;
 }
 
-int adapter_config_khz(unsigned int khz)
+/** Attempt to configure the adapter for the specified kHz. */
+static int adapter_config_khz(unsigned int khz)
 {
 	LOG_DEBUG("handle adapter khz");
 	adapter_config.clock_mode = CLOCK_MODE_KHZ;
diff --git a/src/jtag/adapter.h b/src/jtag/adapter.h
index 23ffe2cc5..556952f8d 100644
--- a/src/jtag/adapter.h
+++ b/src/jtag/adapter.h
@@ -97,9 +97,6 @@ int adapter_get_speed(int *speed);
  */
 int adapter_get_speed_readable(int *speed);
 
-/** Attempt to configure the adapter for the specified kHz. */
-int adapter_config_khz(unsigned int khz);
-
 /**
  * Attempt to enable RTCK/RCLK. If that fails, fallback to the
  * specified frequency.
diff --git a/src/jtag/core.c b/src/jtag/core.c
index 907883f09..769e07571 100644
--- a/src/jtag/core.c
+++ b/src/jtag/core.c
@@ -51,6 +51,8 @@ static void jtag_add_scan_check(struct jtag_tap *active,
 		tap_state_t state),
 		int in_num_fields, struct scan_field *in_fields, tap_state_t state);
 
+static int jtag_error_clear(void);
+
 /**
  * The jtag_error variable is set when an error occurs while executing
  * the queue.  Application code may set this using jtag_set_error(),
@@ -127,7 +129,11 @@ void jtag_set_error(int error)
 	jtag_error = error;
 }
 
-int jtag_error_clear(void)
+/**
+ * Resets jtag_error to ERROR_OK, returning its previous value.
+ * @returns The previous value of @c jtag_error.
+ */
+static int jtag_error_clear(void)
 {
 	int temp = jtag_error;
 	jtag_error = ERROR_OK;
@@ -186,7 +192,7 @@ struct jtag_tap *jtag_all_taps(void)
 	return __jtag_all_taps;
 };
 
-unsigned int jtag_tap_count(void)
+static unsigned int jtag_tap_count(void)
 {
 	struct jtag_tap *t = jtag_all_taps();
 	unsigned int n = 0;
diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
index e404afe9f..8be834859 100644
--- a/src/jtag/drivers/Makefile.am
+++ b/src/jtag/drivers/Makefile.am
@@ -143,7 +143,7 @@ endif
 if ARMJTAGEW
 DRIVERFILES += %D%/arm-jtag-ew.c
 endif
-if BUSPIRATE
+if BUS_PIRATE
 DRIVERFILES += %D%/buspirate.c
 endif
 if REMOTE_BITBANG
diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c
index d52a345a0..58e59a559 100644
--- a/src/jtag/drivers/driver.c
+++ b/src/jtag/drivers/driver.c
@@ -341,7 +341,7 @@ int interface_jtag_add_sleep(uint32_t us)
 }
 
 /* add callback to end of queue */
-void interface_jtag_add_callback4(jtag_callback_t callback,
+static void interface_jtag_add_callback4(jtag_callback_t callback,
 		jtag_callback_data_t data0, jtag_callback_data_t data1,
 		jtag_callback_data_t data2, jtag_callback_data_t data3)
 {
@@ -395,7 +395,7 @@ static int jtag_convert_to_callback4(jtag_callback_data_t data0,
 	return ERROR_OK;
 }
 
-void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0)
+static void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0)
 {
 	jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0);
 }
diff --git a/src/jtag/drivers/minidriver_imp.h b/src/jtag/drivers/minidriver_imp.h
index b29b3c9cc..f3582f6e3 100644
--- a/src/jtag/drivers/minidriver_imp.h
+++ b/src/jtag/drivers/minidriver_imp.h
@@ -17,12 +17,6 @@ static inline void interface_jtag_add_scan_check_alloc(struct scan_field *field)
 	field->in_value = cmd_queue_alloc(num_bytes);
 }
 
-void interface_jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0);
-
-void interface_jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
-				  jtag_callback_data_t data1, jtag_callback_data_t data2,
-				  jtag_callback_data_t data3);
-
 void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
 			jtag_callback_data_t data1, jtag_callback_data_t data2,
 			jtag_callback_data_t data3);
diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c
index 1ef9550a0..38393ad0a 100644
--- a/src/jtag/drivers/mpsse.c
+++ b/src/jtag/drivers/mpsse.c
@@ -75,6 +75,8 @@ struct mpsse_ctx {
 	int retval;
 };
 
+static void mpsse_purge(struct mpsse_ctx *ctx);
+
 /* Returns true if the string descriptor indexed by str_index in device matches string */
 static bool string_descriptor_equal(struct libusb_device_handle *device, uint8_t str_index,
 	const char *string)
@@ -421,7 +423,7 @@ bool mpsse_is_high_speed(struct mpsse_ctx *ctx)
 	return ctx->type != TYPE_FT2232C;
 }
 
-void mpsse_purge(struct mpsse_ctx *ctx)
+static void mpsse_purge(struct mpsse_ctx *ctx)
 {
 	int err;
 	LOG_DEBUG("-");
@@ -709,7 +711,7 @@ void mpsse_loopback_config(struct mpsse_ctx *ctx, bool enable)
 	single_byte_boolean_helper(ctx, enable, 0x84, 0x85);
 }
 
-void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor)
+static void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor)
 {
 	LOG_DEBUG("%d", divisor);
 
@@ -726,7 +728,7 @@ void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor)
 	buffer_write_byte(ctx, divisor >> 8);
 }
 
-int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable)
+static int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable)
 {
 	if (!mpsse_is_high_speed(ctx))
 		return ERROR_FAIL;
@@ -737,7 +739,7 @@ int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable)
 	return ERROR_OK;
 }
 
-int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable)
+static int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable)
 {
 	if (!mpsse_is_high_speed(ctx))
 		return ERROR_FAIL;
diff --git a/src/jtag/drivers/mpsse.h b/src/jtag/drivers/mpsse.h
index 4a625d890..e95f842c9 100644
--- a/src/jtag/drivers/mpsse.h
+++ b/src/jtag/drivers/mpsse.h
@@ -59,9 +59,6 @@ void mpsse_set_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t
 void mpsse_read_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t *data);
 void mpsse_read_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t *data);
 void mpsse_loopback_config(struct mpsse_ctx *ctx, bool enable);
-void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor);
-int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable);
-int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable);
 
 /* Helper to set frequency in Hertz. Returns actual realizable frequency or negative error.
  * Frequency 0 means RTCK. */
@@ -69,6 +66,5 @@ int mpsse_set_frequency(struct mpsse_ctx *ctx, int frequency);
 
 /* Queue handling */
 int mpsse_flush(struct mpsse_ctx *ctx);
-void mpsse_purge(struct mpsse_ctx *ctx);
 
 #endif /* OPENOCD_JTAG_DRIVERS_MPSSE_H */
diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c
index 0385e4d85..d77f28b0f 100644
--- a/src/jtag/drivers/stlink_usb.c
+++ b/src/jtag/drivers/stlink_usb.c
@@ -3781,7 +3781,7 @@ static int stlink_open(struct hl_interface_param *param, enum stlink_mode mode,
 	}
 
 	/* initialize the debug hardware */
-	err = stlink_usb_init_mode(h, param->connect_under_reset, param->initial_interface_speed);
+	err = stlink_usb_init_mode(h, param->connect_under_reset, adapter_get_speed_khz());
 
 	if (err != ERROR_OK) {
 		LOG_ERROR("init mode failed (unable to connect to the target)");
@@ -5174,7 +5174,6 @@ static int stlink_dap_speed(int speed)
 		return ERROR_JTAG_NOT_IMPLEMENTED;
 	}
 
-	stlink_dap_param.initial_interface_speed = speed;
 	stlink_speed(stlink_dap_handle, speed, false);
 	return ERROR_OK;
 }
diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c
index e826f7910..96862b0d0 100644
--- a/src/jtag/hla/hla_interface.c
+++ b/src/jtag/hla/hla_interface.c
@@ -30,7 +30,6 @@ static struct hl_interface hl_if = {
 		.pid = { 0 },
 		.transport = HL_TRANSPORT_UNKNOWN,
 		.connect_under_reset = false,
-		.initial_interface_speed = -1,
 		.use_stlink_tcp = false,
 		.stlink_tcp_port = 7184,
 	},
@@ -165,11 +164,8 @@ static int hl_interface_speed(int speed)
 	if (!hl_if.layout->api->speed)
 		return ERROR_OK;
 
-	if (!hl_if.handle) {
-		/* pass speed as initial param as interface not open yet */
-		hl_if.param.initial_interface_speed = speed;
+	if (!hl_if.handle)
 		return ERROR_OK;
-	}
 
 	hl_if.layout->api->speed(hl_if.handle, speed, false);
 
diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h
index c95638b92..f1550d991 100644
--- a/src/jtag/hla/hla_interface.h
+++ b/src/jtag/hla/hla_interface.h
@@ -31,8 +31,6 @@ struct hl_interface_param {
 	enum hl_transports transport;
 	/** */
 	bool connect_under_reset;
-	/** Initial interface clock clock speed */
-	int initial_interface_speed;
 	/** */
 	bool use_stlink_tcp;
 	/** */
diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c
index c24ead8cd..67f0838e3 100644
--- a/src/jtag/interfaces.c
+++ b/src/jtag/interfaces.c
@@ -102,7 +102,7 @@ struct adapter_driver *adapter_drivers[] = {
 #if BUILD_ARMJTAGEW == 1
 		&armjtagew_adapter_driver,
 #endif
-#if BUILD_BUSPIRATE == 1
+#if BUILD_BUS_PIRATE == 1
 		&buspirate_adapter_driver,
 #endif
 #if BUILD_REMOTE_BITBANG == 1
diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h
index 6ba118f7a..6224eb07d 100644
--- a/src/jtag/jtag.h
+++ b/src/jtag/jtag.h
@@ -154,7 +154,6 @@ struct jtag_tap *jtag_tap_by_position(unsigned int abs_position);
 /* FIXME: "jtag_tap_next_enabled()" should accept a const pointer. */
 struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p);
 unsigned int jtag_tap_count_enabled(void);
-unsigned int jtag_tap_count(void);
 
 /*
  * - TRST_ASSERTED triggers two sets of callbacks, after operations to
@@ -569,11 +568,6 @@ void jtag_sleep(uint32_t us);
  * called with a non-zero error code.
  */
 void jtag_set_error(int error);
-/**
- * Resets jtag_error to ERROR_OK, returning its previous value.
- * @returns The previous value of @c jtag_error.
- */
-int jtag_error_clear(void);
 
 /**
  * Return true if it's safe for a background polling task to access the
diff --git a/src/openocd.c b/src/openocd.c
index 7a5147050..9fd709e32 100644
--- a/src/openocd.c
+++ b/src/openocd.c
@@ -375,6 +375,13 @@ int openocd_main(int argc, char *argv[])
 
 	log_exit();
 
+#if USE_GCOV
+	/* Always explicitly dump coverage data before terminating.
+	 * Otherwise coverage would not be dumped when exit_on_signal occurs. */
+	void __gcov_dump(void);
+	__gcov_dump();
+#endif
+
 	if (ret == ERROR_FAIL)
 		return EXIT_FAILURE;
 	else if (ret != ERROR_OK)
diff --git a/src/pld/pld.c b/src/pld/pld.c
index 81fb0c463..edd779613 100644
--- a/src/pld/pld.c
+++ b/src/pld/pld.c
@@ -28,7 +28,7 @@ static struct pld_driver *pld_drivers[] = {
 
 static struct pld_device *pld_devices;
 
-struct pld_device *get_pld_device_by_num(int num)
+static struct pld_device *get_pld_device_by_num(int num)
 {
 	struct pld_device *p;
 	int i = 0;
diff --git a/src/pld/pld.h b/src/pld/pld.h
index 5e2fcd20c..a6e2e0fc8 100644
--- a/src/pld/pld.h
+++ b/src/pld/pld.h
@@ -54,7 +54,6 @@ struct pld_device {
 
 int pld_register_commands(struct command_context *cmd_ctx);
 
-struct pld_device *get_pld_device_by_num(int num);
 struct pld_device *get_pld_device_by_name(const char *name);
 struct pld_device *get_pld_device_by_name_or_numstr(const char *str);
 
diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
index 269758e94..fbc51eeb5 100644
--- a/src/rtos/rtos.c
+++ b/src/rtos/rtos.c
@@ -109,7 +109,7 @@ int rtos_create(struct jim_getopt_info *goi, struct target *target)
 	Jim_Obj *res;
 	int e;
 
-	if (!goi->isconfigure && goi->argc != 0) {
+	if (!goi->is_configure && goi->argc != 0) {
 		Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS");
 		return JIM_ERR;
 	}
@@ -317,7 +317,7 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s
 	reply_len += 2 * strlen(next_suffix);            /* hexify(..., next_suffix, ...) */
 	reply_len += 1;                                  /* Terminating NUL */
 	if (reply_len > sizeof(reply)) {
-		LOG_ERROR("ERROR: RTOS symbol '%s%s' name is too long for GDB!", next_sym->symbol_name, next_suffix);
+		LOG_ERROR("RTOS symbol '%s%s' name is too long for GDB", next_sym->symbol_name, next_suffix);
 		goto done;
 	}
 
diff --git a/src/rtt/rtt.c b/src/rtt/rtt.c
index e31e75410..42c3ee3ad 100644
--- a/src/rtt/rtt.c
+++ b/src/rtt/rtt.c
@@ -297,11 +297,6 @@ int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer,
 		length, NULL);
 }
 
-bool rtt_started(void)
-{
-	return rtt.started;
-}
-
 bool rtt_configured(void)
 {
 	return rtt.configured;
diff --git a/src/rtt/rtt.h b/src/rtt/rtt.h
index a5630a951..49409074c 100644
--- a/src/rtt/rtt.h
+++ b/src/rtt/rtt.h
@@ -194,13 +194,6 @@ int rtt_get_polling_interval(unsigned int *interval);
  */
 int rtt_set_polling_interval(unsigned int interval);
 
-/**
- * Get whether RTT is started.
- *
- * @returns Whether RTT is started.
- */
-bool rtt_started(void);
-
 /**
  * Get whether RTT is configured.
  *
diff --git a/src/target/aarch64.c b/src/target/aarch64.c
index f0d486f58..9f122070a 100644
--- a/src/target/aarch64.c
+++ b/src/target/aarch64.c
@@ -2940,7 +2940,7 @@ static int aarch64_jim_configure(struct target *target, struct jim_getopt_info *
 
 		switch (n->value) {
 		case CFG_CTI: {
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				Jim_Obj *o_cti;
 				struct arm_cti *cti;
 				e = jim_getopt_obj(goi, &o_cti);
diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index eaaa209b9..0c7633bea 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -2359,7 +2359,7 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi,
 
 	switch (n->value) {
 	case CFG_DAP:
-		if (goi->isconfigure) {
+		if (goi->is_configure) {
 			Jim_Obj *o_t;
 			struct adiv5_dap *dap;
 			e = jim_getopt_obj(goi, &o_t);
@@ -2388,7 +2388,7 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi,
 		break;
 
 	case CFG_AP_NUM:
-		if (goi->isconfigure) {
+		if (goi->is_configure) {
 			/* jim_wide is a signed 64 bits int, ap_num is unsigned with max 52 bits */
 			jim_wide ap_num;
 			e = jim_getopt_wide(goi, &ap_num);
@@ -2415,7 +2415,7 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi,
 		LOG_WARNING("DEPRECATED! use \'-baseaddr' not \'-ctibase\'");
 		/* fall through */
 	case CFG_BASEADDR:
-		if (goi->isconfigure) {
+		if (goi->is_configure) {
 			jim_wide base;
 			e = jim_getopt_wide(goi, &base);
 			if (e != JIM_OK)
diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c
index 97d1fb34b..88eec832e 100644
--- a/src/target/arm_cti.c
+++ b/src/target/arm_cti.c
@@ -468,7 +468,7 @@ static int cti_create(struct jim_getopt_info *goi)
 	adiv5_mem_ap_spot_init(&cti->spot);
 
 	/* Do the rest as "configure" options */
-	goi->isconfigure = 1;
+	goi->is_configure = true;
 	e = cti_configure(goi, cti);
 	if (e != JIM_OK) {
 		free(cti);
diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c
index 55a977844..c14fd5fc8 100644
--- a/src/target/arm_tpiu_swo.c
+++ b/src/target/arm_tpiu_swo.c
@@ -358,7 +358,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s
 {
 	assert(obj);
 
-	if (goi->isconfigure && obj->enabled) {
+	if (goi->is_configure && obj->enabled) {
 		Jim_SetResultFormatted(goi->interp, "Cannot configure TPIU/SWO; %s is enabled!", obj->name);
 		return JIM_ERR;
 	}
@@ -382,7 +382,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s
 
 		switch (n->value) {
 		case CFG_PORT_WIDTH:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				jim_wide port_width;
 				e = jim_getopt_wide(goi, &port_width);
 				if (e != JIM_OK)
@@ -399,7 +399,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s
 			}
 			break;
 		case CFG_PROTOCOL:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				struct jim_nvp *p;
 				e = jim_getopt_nvp(goi, nvp_arm_tpiu_swo_protocol_opts, &p);
 				if (e != JIM_OK)
@@ -418,7 +418,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s
 			}
 			break;
 		case CFG_FORMATTER:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				struct jim_nvp *p;
 				e = jim_getopt_nvp(goi, nvp_arm_tpiu_swo_bool_opts, &p);
 				if (e != JIM_OK)
@@ -437,7 +437,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s
 			}
 			break;
 		case CFG_TRACECLKIN:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				jim_wide clk;
 				e = jim_getopt_wide(goi, &clk);
 				if (e != JIM_OK)
@@ -450,7 +450,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s
 			}
 			break;
 		case CFG_BITRATE:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				jim_wide clk;
 				e = jim_getopt_wide(goi, &clk);
 				if (e != JIM_OK)
@@ -463,7 +463,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s
 			}
 			break;
 		case CFG_OUTFILE:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				const char *s;
 				e = jim_getopt_string(goi, &s, NULL);
 				if (e != JIM_OK)
@@ -491,7 +491,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s
 			}
 			break;
 		case CFG_EVENT:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				if (goi->argc < 2) {
 					Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
 					return JIM_ERR;
@@ -521,7 +521,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s
 					ea = ea->next;
 				}
 
-				if (goi->isconfigure) {
+				if (goi->is_configure) {
 					if (!ea) {
 						ea = calloc(1, sizeof(*ea));
 						if (!ea) {
@@ -560,7 +560,7 @@ static int jim_arm_tpiu_swo_configure(Jim_Interp *interp, int argc, Jim_Obj * co
 	struct jim_getopt_info goi;
 
 	jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
-	goi.isconfigure = !strcmp(c->name, "configure");
+	goi.is_configure = !strcmp(c->name, "configure");
 	if (goi.argc < 1) {
 		Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
 			"missing: -option ...");
@@ -977,7 +977,7 @@ static int jim_arm_tpiu_swo_create(Jim_Interp *interp, int argc, Jim_Obj *const
 	}
 
 	/* Do the rest as "configure" options */
-	goi.isconfigure = 1;
+	goi.is_configure = true;
 	int e = arm_tpiu_swo_configure(&goi, obj);
 	if (e != JIM_OK)
 		goto err_exit;
diff --git a/src/target/armv8.c b/src/target/armv8.c
index 61d72741a..88534d962 100644
--- a/src/target/armv8.c
+++ b/src/target/armv8.c
@@ -1021,12 +1021,6 @@ static __attribute__((unused)) void armv8_show_fault_registers(struct target *ta
 		armv8_show_fault_registers32(armv8);
 }
 
-/*  method adapted to cortex A : reused arm v4 v5 method*/
-int armv8_mmu_translate_va(struct target *target,  target_addr_t va, target_addr_t *val)
-{
-	return ERROR_OK;
-}
-
 static void armv8_decode_cacheability(int attr)
 {
 	if (attr == 0) {
diff --git a/src/target/armv8.h b/src/target/armv8.h
index 349c8f002..49ab3e5cb 100644
--- a/src/target/armv8.h
+++ b/src/target/armv8.h
@@ -298,7 +298,6 @@ int armv8_identify_cache(struct armv8_common *armv8);
 int armv8_init_arch_info(struct target *target, struct armv8_common *armv8);
 int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va,
 		target_addr_t *val, int meminfo);
-int armv8_mmu_translate_va(struct target *target,  target_addr_t va, target_addr_t *val);
 
 int armv8_handle_cache_info_command(struct command_invocation *cmd,
 		struct armv8_cache_common *armv8_cache);
diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c
index 0427ba364..0e9ae6e3a 100644
--- a/src/target/breakpoints.c
+++ b/src/target/breakpoints.c
@@ -115,7 +115,7 @@ static int context_breakpoint_add_internal(struct target *target,
 			 * breakpoint" ... check all the parameters before
 			 * succeeding.
 			 */
-			LOG_ERROR("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")",
+			LOG_TARGET_ERROR(target, "Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")",
 				asid, breakpoint->unique_id);
 			return ERROR_TARGET_DUPLICATE_BREAKPOINT;
 		}
@@ -687,8 +687,7 @@ int watchpoint_remove(struct target *target, target_addr_t address)
 
 int watchpoint_clear_target(struct target *target)
 {
-	LOG_DEBUG("Delete all watchpoints for target: %s",
-		target_name(target));
+	LOG_TARGET_DEBUG(target, "Delete all watchpoints");
 
 	struct watchpoint *watchpoint = target->watchpoints;
 	int retval = ERROR_OK;
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index e78d2e29b..fa95fcbc7 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -1469,7 +1469,7 @@ static int cortex_m_resume(struct target *target, int current,
 	if (target->smp && !debug_execution) {
 		retval = cortex_m_restore_smp(target, !!handle_breakpoints);
 		if (retval != ERROR_OK)
-			LOG_WARNING("resume of a SMP target failed, trying to resume current one");
+			LOG_TARGET_WARNING(target, "resume of a SMP target failed, trying to resume current one");
 	}
 
 	cortex_m_restart_one(target, !!debug_execution);
@@ -2553,7 +2553,7 @@ static bool cortex_m_has_tz(struct target *target)
 
 	int retval = target_read_u32(target, DAUTHSTATUS, &dauthstatus);
 	if (retval != ERROR_OK) {
-		LOG_WARNING("Error reading DAUTHSTATUS register");
+		LOG_TARGET_WARNING(target, "Error reading DAUTHSTATUS register");
 		return false;
 	}
 	return (dauthstatus & DAUTHSTATUS_SID_MASK) != 0;
@@ -2602,7 +2602,7 @@ int cortex_m_examine(struct target *target)
 			} else {
 				armv7m->debug_ap = dap_get_ap(swjdp, cortex_m->apsel);
 				if (!armv7m->debug_ap) {
-					LOG_ERROR("Cannot get AP");
+					LOG_TARGET_ERROR(target, "Cannot get AP");
 					return ERROR_FAIL;
 				}
 			}
@@ -2659,9 +2659,9 @@ int cortex_m_examine(struct target *target)
 			LOG_TARGET_WARNING(target, "Erratum 3092511: Cortex-M7 can halt in an incorrect address when breakpoint and exception occurs simultaneously");
 			cortex_m->incorrect_halt_erratum = true;
 			if (armv7m->is_hla_target)
-				LOG_WARNING("No erratum 3092511 workaround on hla adapter");
+				LOG_TARGET_WARNING(target, "No erratum 3092511 workaround on hla adapter");
 			else
-				LOG_INFO("The erratum 3092511 workaround will resume after an incorrect halt");
+				LOG_TARGET_INFO(target, "The erratum 3092511 workaround will resume after an incorrect halt");
 		}
 		LOG_TARGET_DEBUG(target, "cpuid: 0x%8.8" PRIx32 "", cpuid);
 
diff --git a/src/target/dsp563xx_once.c b/src/target/dsp563xx_once.c
index 866f33152..bb41ae8c7 100644
--- a/src/target/dsp563xx_once.c
+++ b/src/target/dsp563xx_once.c
@@ -34,6 +34,8 @@
 #define JTAG_INSTR_DEBUG_REQUEST	0x07
 #define JTAG_INSTR_BYPASS		0x0F
 
+static int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data);
+
 /** */
 static inline int dsp563xx_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len, int rti)
 {
@@ -185,7 +187,7 @@ int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg
 }
 
 /** once read register with register len */
-int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data)
+static int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data)
 {
 	int err;
 
diff --git a/src/target/dsp563xx_once.h b/src/target/dsp563xx_once.h
index 871548837..4f27e1db7 100644
--- a/src/target/dsp563xx_once.h
+++ b/src/target/dsp563xx_once.h
@@ -65,8 +65,6 @@ int dsp563xx_once_target_status(struct jtag_tap *tap);
 /** once read registers */
 int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg *regs, int len);
 /** once read register */
-int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data);
-/** once read register */
 int dsp563xx_once_reg_read(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t *data);
 /** once write register */
 int dsp563xx_once_reg_write(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t data);
diff --git a/src/target/esirisc_jtag.c b/src/target/esirisc_jtag.c
index 5960e26cb..ad2bef543 100644
--- a/src/target/esirisc_jtag.c
+++ b/src/target/esirisc_jtag.c
@@ -19,6 +19,8 @@
 
 #include "esirisc_jtag.h"
 
+static uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info);
+
 static void esirisc_jtag_set_instr(struct esirisc_jtag *jtag_info, uint32_t new_instr)
 {
 	struct jtag_tap *tap = jtag_info->tap;
@@ -221,7 +223,7 @@ bool esirisc_jtag_is_stopped(struct esirisc_jtag *jtag_info)
 	return !!(jtag_info->status & 1<<6);	/* S */
 }
 
-uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info)
+static uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info)
 {
 	return jtag_info->status & 0x3f;		/* EID */
 }
@@ -490,7 +492,7 @@ int esirisc_jtag_enable_debug(struct esirisc_jtag *jtag_info)
 	return esirisc_jtag_send_ctrl(jtag_info, DEBUG_ENABLE_DEBUG);
 }
 
-int esirisc_jtag_disable_debug(struct esirisc_jtag *jtag_info)
+static __attribute__((unused)) int esirisc_jtag_disable_debug(struct esirisc_jtag *jtag_info)
 {
 	return esirisc_jtag_send_ctrl(jtag_info, DEBUG_DISABLE_DEBUG);
 }
diff --git a/src/target/esirisc_jtag.h b/src/target/esirisc_jtag.h
index 98ec8af8d..d59b75fbe 100644
--- a/src/target/esirisc_jtag.h
+++ b/src/target/esirisc_jtag.h
@@ -54,7 +54,6 @@ struct esirisc_jtag {
 
 bool esirisc_jtag_is_debug_active(struct esirisc_jtag *jtag_info);
 bool esirisc_jtag_is_stopped(struct esirisc_jtag *jtag_info);
-uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info);
 
 int esirisc_jtag_read_byte(struct esirisc_jtag *jtag_info,
 		uint32_t address, uint8_t *data);
@@ -81,7 +80,6 @@ int esirisc_jtag_write_csr(struct esirisc_jtag *jtag_info,
 		uint8_t bank, uint8_t csr, uint32_t data);
 
 int esirisc_jtag_enable_debug(struct esirisc_jtag *jtag_info);
-int esirisc_jtag_disable_debug(struct esirisc_jtag *jtag_info);
 
 int esirisc_jtag_assert_reset(struct esirisc_jtag *jtag_info);
 int esirisc_jtag_deassert_reset(struct esirisc_jtag *jtag_info);
diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c
index 1eb195712..ffcd3aafd 100644
--- a/src/target/semihosting_common.c
+++ b/src/target/semihosting_common.c
@@ -92,6 +92,8 @@ static int semihosting_common_fileio_info(struct target *target,
 	struct gdb_fileio_info *fileio_info);
 static int semihosting_common_fileio_end(struct target *target, int result,
 	int fileio_errno, bool ctrl_c);
+static void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields);
+static int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields);
 
 /**
  * Initialize common semihosting support.
@@ -298,7 +300,12 @@ static inline int semihosting_getchar(struct semihosting *semihosting, int fd)
  */
 static char *semihosting_user_op_params;
 
-const char *semihosting_opcode_to_str(const uint64_t opcode)
+/**
+ * @brief Convert the syscall opcode to a human-readable string
+ * @param[in] opcode Syscall opcode
+ * @return String representation of syscall opcode
+ */
+static const char *semihosting_opcode_to_str(const uint64_t opcode)
 {
 	switch (opcode) {
 		case SEMIHOSTING_SYS_CLOSE:
@@ -1729,8 +1736,7 @@ int semihosting_read_fields(struct target *target, size_t number,
 /**
  * Write all fields of a command from buffer to target.
  */
-int semihosting_write_fields(struct target *target, size_t number,
-	uint8_t *fields)
+static int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields)
 {
 	struct semihosting *semihosting = target->semihosting;
 	/* Use 4-byte multiples to trigger fast memory access. */
@@ -1754,9 +1760,7 @@ uint64_t semihosting_get_field(struct target *target, size_t index,
 /**
  * Store a field in the buffer, considering register size and endianness.
  */
-void semihosting_set_field(struct target *target, uint64_t value,
-	size_t index,
-	uint8_t *fields)
+static void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields)
 {
 	struct semihosting *semihosting = target->semihosting;
 	if (semihosting->word_size_bytes == 8)
diff --git a/src/target/semihosting_common.h b/src/target/semihosting_common.h
index a1848b488..1821ca4e2 100644
--- a/src/target/semihosting_common.h
+++ b/src/target/semihosting_common.h
@@ -188,13 +188,6 @@ struct semihosting {
 	int (*post_result)(struct target *target);
 };
 
-/**
- * @brief Convert the syscall opcode to a human-readable string
- * @param[in] opcode Syscall opcode
- * @return String representation of syscall opcode
- */
-const char *semihosting_opcode_to_str(uint64_t opcode);
-
 int semihosting_common_init(struct target *target, void *setup,
 	void *post_result);
 int semihosting_common(struct target *target);
@@ -202,13 +195,8 @@ int semihosting_common(struct target *target);
 /* utility functions which may also be used by semihosting extensions (custom vendor-defined syscalls) */
 int semihosting_read_fields(struct target *target, size_t number,
 	uint8_t *fields);
-int semihosting_write_fields(struct target *target, size_t number,
-	uint8_t *fields);
 uint64_t semihosting_get_field(struct target *target, size_t index,
 	uint8_t *fields);
-void semihosting_set_field(struct target *target, uint64_t value,
-	size_t index,
-	uint8_t *fields);
 
 extern const struct command_registration semihosting_common_handlers[];
 
diff --git a/src/target/target.c b/src/target/target.c
index 4716499c5..fb038311b 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -4921,7 +4921,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 		switch (n->value) {
 		case TCFG_TYPE:
 			/* not settable */
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				Jim_SetResultFormatted(goi->interp,
 						"not settable: %s", n->name);
 				return JIM_ERR;
@@ -4950,7 +4950,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 				return e;
 			}
 
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				if (goi->argc != 1) {
 					Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
 					return JIM_ERR;
@@ -4973,7 +4973,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 					teap = teap->next;
 				}
 
-				if (goi->isconfigure) {
+				if (goi->is_configure) {
 					/* START_DEPRECATED_TPIU */
 					if (n->value == TARGET_EVENT_TRACE_CONFIG)
 						LOG_INFO("DEPRECATED target event %s; use TPIU events {pre,post}-{enable,disable}", n->name);
@@ -5021,7 +5021,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 			break;
 
 		case TCFG_WORK_AREA_VIRT:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				target_free_all_working_areas(target);
 				e = jim_getopt_wide(goi, &w);
 				if (e != JIM_OK)
@@ -5037,7 +5037,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 			break;
 
 		case TCFG_WORK_AREA_PHYS:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				target_free_all_working_areas(target);
 				e = jim_getopt_wide(goi, &w);
 				if (e != JIM_OK)
@@ -5053,7 +5053,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 			break;
 
 		case TCFG_WORK_AREA_SIZE:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				target_free_all_working_areas(target);
 				e = jim_getopt_wide(goi, &w);
 				if (e != JIM_OK)
@@ -5068,7 +5068,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 			break;
 
 		case TCFG_WORK_AREA_BACKUP:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				target_free_all_working_areas(target);
 				e = jim_getopt_wide(goi, &w);
 				if (e != JIM_OK)
@@ -5085,7 +5085,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 
 
 		case TCFG_ENDIAN:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				e = jim_getopt_nvp(goi, nvp_target_endian, &n);
 				if (e != JIM_OK) {
 					jim_getopt_nvp_unknown(goi, nvp_target_endian, 1);
@@ -5106,7 +5106,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 			break;
 
 		case TCFG_COREID:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				e = jim_getopt_wide(goi, &w);
 				if (e != JIM_OK)
 					return e;
@@ -5120,7 +5120,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 			break;
 
 		case TCFG_CHAIN_POSITION:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				Jim_Obj *o_t;
 				struct jtag_tap *tap;
 
@@ -5147,7 +5147,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 			/* loop for more e*/
 			break;
 		case TCFG_DBGBASE:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				e = jim_getopt_wide(goi, &w);
 				if (e != JIM_OK)
 					return e;
@@ -5177,7 +5177,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 			break;
 
 		case TCFG_GDB_PORT:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				struct command_context *cmd_ctx = current_command_context(goi->interp);
 				if (cmd_ctx->mode != COMMAND_CONFIG) {
 					Jim_SetResultString(goi->interp, "-gdb-port must be configured before 'init'", -1);
@@ -5199,7 +5199,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target)
 			break;
 
 		case TCFG_GDB_MAX_CONNECTIONS:
-			if (goi->isconfigure) {
+			if (goi->is_configure) {
 				struct command_context *cmd_ctx = current_command_context(goi->interp);
 				if (cmd_ctx->mode != COMMAND_CONFIG) {
 					Jim_SetResultString(goi->interp, "-gdb-max-connections must be configured before 'init'", -1);
@@ -5230,7 +5230,7 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a
 	struct jim_getopt_info goi;
 
 	jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
-	goi.isconfigure = !strcmp(c->name, "configure");
+	goi.is_configure = !strcmp(c->name, "configure");
 	if (goi.argc < 1) {
 		Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
 				 "missing: -option ...");
@@ -5807,7 +5807,7 @@ static int target_create(struct jim_getopt_info *goi)
 	target->gdb_max_connections = 1;
 
 	/* Do the rest as "configure" options */
-	goi->isconfigure = 1;
+	goi->is_configure = true;
 	e = target_configure(goi, target);
 
 	if (e == JIM_OK) {
diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c
index 2c60b9f7e..8cca9a5e9 100644
--- a/src/target/x86_32_common.c
+++ b/src/target/x86_32_common.c
@@ -677,7 +677,7 @@ int x86_32_common_write_memory(struct target *t, target_addr_t addr,
 	return retval;
 }
 
-int x86_32_common_read_io(struct target *t, uint32_t addr,
+static int x86_32_common_read_io(struct target *t, uint32_t addr,
 			uint32_t size, uint8_t *buf)
 {
 	struct x86_32_common *x86_32 = target_to_x86_32(t);
diff --git a/src/target/x86_32_common.h b/src/target/x86_32_common.h
index 7392447a6..e23274769 100644
--- a/src/target/x86_32_common.h
+++ b/src/target/x86_32_common.h
@@ -309,8 +309,6 @@ int x86_32_common_read_memory(struct target *t, target_addr_t addr,
 			uint32_t size, uint32_t count, uint8_t *buf);
 int x86_32_common_write_memory(struct target *t, target_addr_t addr,
 			uint32_t size, uint32_t count, const uint8_t *buf);
-int x86_32_common_read_io(struct target *t, uint32_t addr,
-			uint32_t size, uint8_t *buf);
 int x86_32_common_write_io(struct target *t, uint32_t addr,
 			uint32_t size, const uint8_t *buf);
 int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp);
diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c
index 8369cc4e5..fe1b83bc3 100644
--- a/src/target/xtensa/xtensa.c
+++ b/src/target/xtensa/xtensa.c
@@ -1727,7 +1727,7 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in
 	xtensa_reg_val_t dbreakc[XT_WATCHPOINTS_NUM_MAX];
 	xtensa_reg_val_t icountlvl, cause;
 	xtensa_reg_val_t oldps, oldpc, cur_pc;
-	bool ps_lowered = false;
+	bool ps_modified = false;
 
 	LOG_TARGET_DEBUG(target, "current=%d, address=" TARGET_ADDR_FMT ", handle_breakpoints=%i",
 		current, address, handle_breakpoints);
@@ -1783,14 +1783,23 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in
 	 * RFI >= DBGLEVEL.
 	 */
 	if (xtensa->stepping_isr_mode == XT_STEPPING_ISR_OFF) {
-		if (!xtensa->core_config->high_irq.enabled) {
-			LOG_TARGET_WARNING(
-				target,
-				"disabling IRQs while stepping is not implemented w/o high prio IRQs option!");
-			return ERROR_FAIL;
+		if (xtensa->core_config->core_type == XT_LX) {
+			if (!xtensa->core_config->high_irq.enabled) {
+				LOG_TARGET_WARNING(target,
+						"disabling IRQs while stepping is not implemented w/o high prio IRQs option!");
+				return ERROR_FAIL;
+			}
+			/* Update ICOUNTLEVEL accordingly */
+			icountlvl = MIN((oldps & 0xF) + 1, xtensa->core_config->debug.irq_level);
+		} else {
+			/* Xtensa NX does not have the ICOUNTLEVEL feature present in Xtensa LX
+			 * and instead disable interrupts while stepping. This could change
+			 * the timing of the system while under debug */
+			xtensa_reg_val_t newps = oldps | XT_PS_DI_MSK;
+			xtensa_reg_set(target, XT_REG_IDX_PS, newps);
+			icountlvl = xtensa->core_config->debug.irq_level;
+			ps_modified = true;
 		}
-		/* Update ICOUNTLEVEL accordingly */
-		icountlvl = MIN((oldps & 0xF) + 1, xtensa->core_config->debug.irq_level);
 	} else {
 		icountlvl = xtensa->core_config->debug.irq_level;
 	}
@@ -1815,7 +1824,7 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in
 		xtensa_cause_clear(target);	/* so we don't recurse into the same routine */
 	if (xtensa->core_config->core_type == XT_LX && ((oldps & 0xf) >= icountlvl)) {
 		/* Lower interrupt level to allow stepping, but flag eps[dbglvl] to be restored */
-		ps_lowered = true;
+		ps_modified = true;
 		uint32_t newps = (oldps & ~0xf) | (icountlvl - 1);
 		xtensa_reg_set(target, xtensa->eps_dbglevel_idx, newps);
 		LOG_TARGET_DEBUG(target,
@@ -1916,11 +1925,12 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in
 	}
 
 	/* Restore int level */
-	if (ps_lowered) {
+	if (ps_modified) {
 		LOG_DEBUG("Restoring %s after stepping: 0x%08" PRIx32,
-			xtensa->core_cache->reg_list[xtensa->eps_dbglevel_idx].name,
-			oldps);
-		xtensa_reg_set(target, xtensa->eps_dbglevel_idx, oldps);
+			xtensa->core_cache->reg_list[(xtensa->core_config->core_type == XT_LX) ?
+				xtensa->eps_dbglevel_idx : XT_REG_IDX_PS].name, oldps);
+		xtensa_reg_set(target, (xtensa->core_config->core_type == XT_LX) ?
+			xtensa->eps_dbglevel_idx : XT_REG_IDX_PS, oldps);
 	}
 
 	/* write ICOUNTLEVEL back to zero */
@@ -3000,13 +3010,13 @@ static int xtensa_build_reg_cache(struct target *target)
 	/* Construct empty-register list for handling unknown register requests */
 	xtensa->empty_regs = calloc(xtensa->dbregs_num, sizeof(struct reg));
 	if (!xtensa->empty_regs) {
-		LOG_TARGET_ERROR(target, "ERROR: Out of memory");
+		LOG_TARGET_ERROR(target, "Out of memory");
 		goto fail;
 	}
 	for (unsigned int i = 0; i < xtensa->dbregs_num; i++) {
 		xtensa->empty_regs[i].name = calloc(8, sizeof(char));
 		if (!xtensa->empty_regs[i].name) {
-			LOG_TARGET_ERROR(target, "ERROR: Out of memory");
+			LOG_TARGET_ERROR(target, "Out of memory");
 			goto fail;
 		}
 		sprintf((char *)xtensa->empty_regs[i].name, "?0x%04x", i & 0x0000FFFF);
@@ -3024,7 +3034,7 @@ static int xtensa_build_reg_cache(struct target *target)
 	if (xtensa->regmap_contiguous && xtensa->contiguous_regs_desc) {
 		xtensa->contiguous_regs_list = calloc(xtensa->total_regs_num, sizeof(struct reg *));
 		if (!xtensa->contiguous_regs_list) {
-			LOG_TARGET_ERROR(target, "ERROR: Out of memory");
+			LOG_TARGET_ERROR(target, "Out of memory");
 			goto fail;
 		}
 		for (unsigned int i = 0; i < xtensa->total_regs_num; i++) {
@@ -4191,11 +4201,6 @@ COMMAND_HELPER(xtensa_cmd_mask_interrupts_do, struct xtensa *xtensa)
 		return ERROR_OK;
 	}
 
-	if (xtensa->core_config->core_type == XT_NX) {
-		command_print(CMD, "ERROR: ISR step mode only supported on Xtensa LX");
-		return ERROR_FAIL;
-	}
-
 	/* Masking is ON -> interrupts during stepping are OFF, and vice versa */
 	if (!strcasecmp(CMD_ARGV[0], "off"))
 		state = XT_STEPPING_ISR_ON;
diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h
index 1d56f8368..419277675 100644
--- a/src/target/xtensa/xtensa.h
+++ b/src/target/xtensa/xtensa.h
@@ -45,6 +45,7 @@
 
 /* PS register bits (NX) */
 #define XT_PS_DIEXC_MSK                         BIT(2)
+#define XT_PS_DI_MSK                            BIT(3)
 
 /* MS register bits (NX) */
 #define XT_MS_DE_MSK                            BIT(5)
diff --git a/tools/git2cl b/tools/git2cl
deleted file mode 160000
index 8373c9f74..000000000
--- a/tools/git2cl
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 8373c9f74993e218a08819cbcdbab3f3564bbeba
diff --git a/tools/scripts/checkpatch.pl b/tools/scripts/checkpatch.pl
index 01bd547ff..1011b3305 100755
--- a/tools/scripts/checkpatch.pl
+++ b/tools/scripts/checkpatch.pl
@@ -3251,6 +3251,9 @@ sub process {
 
 # Check for Gerrit Change-Ids not in any patch context
 		if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) {
+			# OpenOCD specific: Begin: exclude gerrit's Change-Id line from commit description
+			$in_commit_log = 0;
+			# OpenOCD specific: End
 			if (ERROR("GERRIT_CHANGE_ID",
 			          "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr) &&
 			    $fix) {