aboutsummaryrefslogtreecommitdiff
path: root/src/target/arm_adi_v5.h
diff options
context:
space:
mode:
authorTomas Vanek <vanekt@fbl.cz>2023-03-14 18:40:25 +0100
committerTomas Vanek <vanekt@fbl.cz>2023-12-29 14:33:55 +0000
commitee3fb5a0eacb42e8e881239194485d79d128d246 (patch)
treefa01d78ddfa46588c866b716bf7ee059abb512a4 /src/target/arm_adi_v5.h
parent492dc7c537d5685e5e6d41757b73eea2365b96ee (diff)
downloadriscv-openocd-ee3fb5a0eacb42e8e881239194485d79d128d246.zip
riscv-openocd-ee3fb5a0eacb42e8e881239194485d79d128d246.tar.gz
riscv-openocd-ee3fb5a0eacb42e8e881239194485d79d128d246.tar.bz2
target/arm_adi_v5: fix DP SELECT logic
The original code supported ADIv5 only, just one SELECT register with some reserved bits - the pseudo value DP_SELECT_INVALID was just fine to indicate the DP SELECT register is in an unknown state. Added ADIv6 support required DP SELECT and SELECT1 registers without reserved bits. Therefore DP_SELECT_INVALID value became reachable as a (fortunately not really used) ADIv6 AP ADDR. JTAG DPBANKSEL setting support introduced with ADIv6 does not honor DP_SELECT_INVALID correctly: required select value gets compared to DP_SELECT_INVALID value and the most common zero bank does not trigger DP SELECT write. DP banked registers need just to set DP SELECT. ADIv6 AP register addressing scheme may use both DP SELECT and SELECT1. This further complicates using a single invalid value. Moreover the difference how the SWD line reset influences DPBANKSEL field between ADIv5 and ADIv6 deserves better handling than setting select cache to zero and then to DP_SELECT_INVALID in a very specific code positions. Introduce bool flags indicating the validity of each SELECT register and one SWD specific for DPBANKSEL field. Use the latter to prevent selecting DP BANK before taking the connection out of reset by reading DPIDR. Treat DP SELECT and SELECT1 individually in ADIv6 64-bit mode. Update comments to reflect the difference between ADIv5 and ADIv6 in SWD line reset. Change-Id: Ibbb0b06cb592be072571218b666566a13d8dff0e Signed-off-by: Tomas Vanek <vanekt@fbl.cz> Reviewed-on: https://review.openocd.org/c/openocd/+/7541 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Diffstat (limited to 'src/target/arm_adi_v5.h')
-rw-r--r--src/target/arm_adi_v5.h22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h
index e215893..e07b577 100644
--- a/src/target/arm_adi_v5.h
+++ b/src/target/arm_adi_v5.h
@@ -100,7 +100,11 @@
#define ADIV5_DP_SELECT_APSEL 0xFF000000
#define ADIV5_DP_SELECT_APBANK 0x000000F0
#define DP_SELECT_DPBANK 0x0000000F
-#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */
+/*
+ * Mask of AP ADDR in select cache, concatenating DP SELECT and DP_SELECT1.
+ * In case of ADIv5, the mask contains both APSEL and APBANKSEL fields.
+ */
+#define SELECT_AP_MASK (~(uint64_t)DP_SELECT_DPBANK)
#define DP_APSEL_MAX (255) /* Strict limit for ADIv5, number of AP buffers for ADIv6 */
#define DP_APSEL_INVALID 0xF00 /* more than DP_APSEL_MAX and not ADIv6 aligned 4k */
@@ -338,11 +342,21 @@ struct adiv5_dap {
/* The current manually selected AP by the "dap apsel" command */
uint64_t apsel;
+ /** Cache for DP SELECT and SELECT1 (ADIv6) register. */
+ uint64_t select;
+ /** Validity of DP SELECT cache. false will force register rewrite */
+ bool select_valid;
+ bool select1_valid; /* ADIv6 only */
/**
- * Cache for DP_SELECT register. A value of DP_SELECT_INVALID
- * indicates no cached value and forces rewrite of the register.
+ * Partial DPBANKSEL validity for SWD only.
+ * ADIv6 line reset sets DP SELECT DPBANKSEL to zero,
+ * ADIv5 does not.
+ * We can rely on it for the banked DP register 0 also on ADIv5
+ * as ADIv5 has no mapping for DP reg 0 - it is always DPIDR.
+ * It is important to avoid setting DP SELECT in connection
+ * reset state before reading DPIDR.
*/
- uint64_t select;
+ bool select_dpbanksel_valid;
/* information about current pending SWjDP-AHBAP transaction */
uint8_t ack;