This is an automated email from Gerrit.

"Antonio Borneo <[email protected]>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/6697

-- gerrit

commit decab23275175804fe0f88d17799357931a0a3b2
Author: Antonio Borneo <[email protected]>
Date:   Thu Nov 11 23:49:23 2021 +0100

    adiv6: add low level swd transport
    
    During enter in SWD read DP_DPIDR without selecting the register
    bank through DP_SELECT_DPBANK.
    Handle the different format of DP_SELECT register.
    
    Change-Id: Iea1b8eb6ec94177e16a430d5885595a38e833eeb
    Signed-off-by: Antonio Borneo <[email protected]>

diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c
index 557fe65b4..17354d9d1 100644
--- a/src/target/adi_v5_swd.c
+++ b/src/target/adi_v5_swd.c
@@ -29,6 +29,7 @@
  * for details, see "ARM IHI 0031A"
  * ARM Debug Interface v5 Architecture Specification
  * especially section 5.3 for SWD protocol
+ * and "ARM IHI 0074C" ARM Debug Interface Architecture Specification ADIv6.0
  *
  * On many chips (most current Cortex-M3 parts) SWD is a run-time alternative
  * to JTAG.  Boards may support one or both.  There are also SWD-only chips,
@@ -135,6 +136,21 @@ static int swd_connect(struct adiv5_dap *dap)
                dap->do_reconnect = false;
                dap_invalidate_cache(dap);
 
+               /* The sequences to enter in SWD (JTAG_TO_SWD and 
DORMANT_TO_SWD) end
+                * with a SWD line reset sequence (50 clk with SWDIO high).
+                * From ARM IHI 0074C ADIv6.0, chapter B4.3.3 "Connection and 
line reset
+                * sequence":
+                * - line reset sets DP_SELECT_DPBANK to zero;
+                * - read of DP_DPIDR takes the connection out of reset;
+                * - write of DP_TARGETSEL keeps the connection in reset;
+                * - other accesses return protocol error (SWDIO not driven by 
target).
+                *
+                * Read DP_DPIDR to get out of reset. Initialize dap->select to 
zero to
+                * skip the write to DP_SELECT, avoiding the protocol error. 
Set again
+                * dap->select to DP_SELECT_INVALID because the rest of the 
register is
+                * unknown after line reset.
+                */
+               dap->select = 0;
                status = swd_queue_dp_read(dap, DP_DPIDR, &dpidr);
                if (status == ERROR_OK) {
                        status = swd_run_inner(dap);
@@ -146,6 +162,7 @@ static int swd_connect(struct adiv5_dap *dap)
 
                dap->jtag_to_swd_through_dormant = 
!dap->jtag_to_swd_through_dormant;
        } while (timeval_ms() < timeout);
+       dap->select = DP_SELECT_INVALID;
 
        if (status != ERROR_OK) {
                LOG_ERROR("Error connecting DP: cannot read IDR");
@@ -226,20 +243,20 @@ static int swd_queue_ap_abort(struct adiv5_dap *dap, 
uint8_t *ack)
 /** Select the DP register bank matching bits 7:4 of reg. */
 static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned reg)
 {
-       /* Only register address 4 is banked. */
-       if ((reg & 0xf) != 4)
+       /* Only register address 0 and 4 are banked. */
+       if ((reg & 0xf) > 4)
                return ERROR_OK;
 
-       uint32_t select_dp_bank = (reg & 0x000000F0) >> 4;
-       uint32_t sel = select_dp_bank
-                       | (dap->select & (DP_SELECT_APSEL | DP_SELECT_APBANK));
+       uint64_t sel = (reg & 0x000000F0) >> 4;
+       if (dap->select != DP_SELECT_INVALID)
+               sel |= dap->select & ~0xfULL;
 
        if (sel == dap->select)
                return ERROR_OK;
 
        dap->select = sel;
 
-       int retval = swd_queue_dp_write(dap, DP_SELECT, sel);
+       int retval = swd_queue_dp_write(dap, DP_SELECT, (uint32_t)sel);
        if (retval != ERROR_OK)
                dap->select = DP_SELECT_INVALID;
 
@@ -300,17 +317,42 @@ static int swd_queue_dp_write(struct adiv5_dap *dap, 
unsigned reg,
 /** Select the AP register bank matching bits 7:4 of reg. */
 static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg)
 {
+       int retval;
        struct adiv5_dap *dap = ap->dap;
-       uint32_t sel = ((uint32_t)ap->ap_num << 24)
-                       | (reg & 0x000000F0)
-                       | (dap->select & DP_SELECT_DPBANK);
+       uint64_t sel;
+
+       if (is_adiv6(dap)) {
+               sel = ap->ap_num | (reg & 0x00000FF0);
+               if (sel == (dap->select & ~0xfULL))
+                       return ERROR_OK;
+
+               if (dap->select != DP_SELECT_INVALID)
+                       sel |= dap->select & 0xf;
+               dap->select = sel;
+               LOG_DEBUG("AP BANKSEL: %" PRIx64, sel);
+
+               retval = swd_queue_dp_write(dap, DP_SELECT, (uint32_t)sel);
+
+               if (retval == ERROR_OK && dap->asize > 32)
+                       retval = swd_queue_dp_write(dap, DP_SELECT1, 
(uint32_t)(sel >> 32));
+
+               if (retval != ERROR_OK)
+                       dap->select = DP_SELECT_INVALID;
+
+               return retval;
+       }
+
+       /* ADIv5 */
+       sel = (ap->ap_num << 24) | (reg & 0x000000F0);
+       if (dap->select != DP_SELECT_INVALID)
+               sel |= dap->select & DP_SELECT_DPBANK;
 
        if (sel == dap->select)
                return ERROR_OK;
 
        dap->select = sel;
 
-       int retval = swd_queue_dp_write(dap, DP_SELECT, sel);
+       retval = swd_queue_dp_write(dap, DP_SELECT, sel);
        if (retval != ERROR_OK)
                dap->select = DP_SELECT_INVALID;
 
@@ -324,14 +366,6 @@ static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned 
reg,
        const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
        assert(swd);
 
-       if (is_adiv6(dap)) {
-               static bool error_flagged;
-               if (!error_flagged)
-                       LOG_ERROR("ADIv6 dap not supported in SWD mode");
-               error_flagged = true;
-               return ERROR_FAIL;
-       }
-
        int retval = swd_check_reconnect(dap);
        if (retval != ERROR_OK)
                return retval;
@@ -353,14 +387,6 @@ static int swd_queue_ap_write(struct adiv5_ap *ap, 
unsigned reg,
        const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
        assert(swd);
 
-       if (is_adiv6(dap)) {
-               static bool error_flagged;
-               if (!error_flagged)
-                       LOG_ERROR("ADIv6 dap not supported in SWD mode");
-               error_flagged = true;
-               return ERROR_FAIL;
-       }
-
        int retval = swd_check_reconnect(dap);
        if (retval != ERROR_OK)
                return retval;

-- 

Reply via email to