This is an automated email from Gerrit.

"Tomas Vanek <van...@fbl.cz>" just uploaded a new patch set to Gerrit, which 
you can find at https://review.openocd.org/c/openocd/+/7213

-- gerrit

commit bd8ca58f1922f823c2337b5324b84f9cf2b26bdd
Author: Tomas Vanek <van...@fbl.cz>
Date:   Tue Sep 20 18:55:51 2022 +0200

    target/adi_v5_swd: fix SWD multidrop
    
    Implementation of ADI v6 introduced banking of DP reg 0.
    The accompanying change preventing DP SELECT write before
    DP IDR read during connect was added to swd_connect_single() only.
    Unchanged swd_connect_multidrop() / swd_multidrop_select_inner()
    was broken as it emited DP SELECT and put DP to protocol error state.
    
    Copy dap->select handling to swd_multidrop_select_inner().
    
    Fixes: 72fb88613f02 (adiv6: add low level swd transport)
    
    Change-Id: I514cd6d9ae2ba97ce3657b459df22638c278a0b1
    Signed-off-by: Tomas Vanek <van...@fbl.cz>

diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c
index 979c643e90..512d0934b9 100644
--- a/src/target/adi_v5_swd.c
+++ b/src/target/adi_v5_swd.c
@@ -177,6 +177,19 @@ static int swd_multidrop_select_inner(struct adiv5_dap 
*dap, uint32_t *dpidr_ptr
        assert(dap_is_multidrop(dap));
 
        swd_send_sequence(dap, LINE_RESET);
+       /* 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;
 
        retval = swd_queue_dp_write_inner(dap, DP_TARGETSEL, 
dap->multidrop_targetsel);
        if (retval != ERROR_OK)
@@ -186,6 +199,8 @@ static int swd_multidrop_select_inner(struct adiv5_dap 
*dap, uint32_t *dpidr_ptr
        if (retval != ERROR_OK)
                return retval;
 
+       dap->select = DP_SELECT_INVALID;
+
        if (clear_sticky) {
                /* Clear all sticky errors (including ORUN) */
                swd_clear_sticky_errors(dap);
@@ -342,6 +357,7 @@ static int swd_connect_single(struct adiv5_dap *dap)
 
                dap->switch_through_dormant = !dap->switch_through_dormant;
        } while (timeval_ms() < timeout);
+
        dap->select = DP_SELECT_INVALID;
 
        if (retval != ERROR_OK) {

-- 

Reply via email to