This is an automated email from Gerrit.

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

-- gerrit

commit fdaede4c76ef9c6465825b9d7551b45428d46d1a
Author: Daniel Goehring <[email protected]>
Date:   Fri Jul 18 21:08:45 2025 -0600

    target/arm: add nested AP low level JTAG support
    
    Add nested Access-Port support to the low level JTAG procedures
    
    jtag_ap_q_read()
    jtag_ap_q_write()
    
    When calling these two procedures, if the access port is nested,
    generate transactions on the first MEM-AP port to access the TAR,
    CSW, and DRW registers of the downstream AHB-AP port.
    
    The updated JTAG read/write queue routines provide the framework
    for future nested AP support modifications.
    
    Change-Id: Id972131378d03db691c3b074cc014413068435a4
    Signed-off-by: Daniel Goehring <[email protected]>

diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c
index c9ed5b948b..3d52cd55cf 100644
--- a/src/target/adi_v5_jtag.c
+++ b/src/target/adi_v5_jtag.c
@@ -818,9 +818,14 @@ static int jtag_ap_q_bankselect(struct adiv5_ap *ap, 
unsigned int reg)
        return ERROR_OK;
 }
 
+static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned int reg,
+               uint32_t data);
+
 static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned int reg,
                uint32_t *data)
 {
+       struct adiv5_ap *ap_gateway = ap->ap_gateway;
+
        int retval = jtag_limit_queue_size(ap->dap);
        if (retval != ERROR_OK)
                return retval;
@@ -829,13 +834,41 @@ static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned 
int reg,
        if (retval != ERROR_OK)
                return retval;
 
-       retval = jtag_ap_q_bankselect(ap, reg);
-       if (retval != ERROR_OK)
-               return retval;
+       if (ap_gateway) {
+               uint32_t csw = CSW_32BIT | CSW_ADDRINC_OFF | 
ap_gateway->csw_default;
+               uint32_t tar = ap->ap_num | reg;
+
+               if (csw != ap_gateway->csw_value) {
+                       retval = jtag_ap_q_write(ap_gateway, 
MEM_AP_REG_CSW(ap_gateway->dap), csw);
+                       if (retval != ERROR_OK) {
+                               ap_gateway->csw_value = 0;
+                               return retval;
+                       }
+                       ap_gateway->csw_value = csw;
+               }
+
+               if (!ap_gateway->tar_valid || tar != ap_gateway->tar_value) {
+                       retval = jtag_ap_q_write(ap_gateway, 
MEM_AP_REG_TAR(ap_gateway->dap), tar);
+                       if (retval != ERROR_OK) {
+                               ap_gateway->tar_valid = false;
+                               return retval;
+                       }
+                       ap_gateway->tar_value = tar;
+                       ap_gateway->tar_valid = true;
+               }
 
-       retval =  adi_jtag_dp_scan_u32(ap->dap, JTAG_DP_APACC, reg,
-                       DPAP_READ, 0, ap->dap->last_read, ap->memaccess_tck, 
NULL);
-       ap->dap->last_read = data;
+               retval = jtag_ap_q_read(ap_gateway, 
MEM_AP_REG_DRW(ap_gateway->dap), data);
+               if (retval != ERROR_OK)
+                       return retval;
+       } else {
+               retval = jtag_ap_q_bankselect(ap, reg);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval =  adi_jtag_dp_scan_u32(ap->dap, JTAG_DP_APACC, reg,
+                               DPAP_READ, 0, ap->dap->last_read, 
ap->memaccess_tck, NULL);
+               ap->dap->last_read = data;
+       }
 
        return retval;
 }
@@ -843,6 +876,8 @@ static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned int 
reg,
 static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned int reg,
                uint32_t data)
 {
+       struct adiv5_ap *ap_gateway = ap->ap_gateway;
+
        int retval = jtag_limit_queue_size(ap->dap);
        if (retval != ERROR_OK)
                return retval;
@@ -851,13 +886,42 @@ static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned 
int reg,
        if (retval != ERROR_OK)
                return retval;
 
-       retval = jtag_ap_q_bankselect(ap, reg);
-       if (retval != ERROR_OK)
-               return retval;
+       if (ap_gateway) {
+               uint32_t csw = CSW_32BIT | CSW_ADDRINC_OFF | 
ap_gateway->csw_default;
+               uint32_t tar = ap->ap_num | reg;
+
+               if (csw != ap_gateway->csw_value) {
+                       retval = jtag_ap_q_write(ap_gateway, 
MEM_AP_REG_CSW(ap_gateway->dap), csw);
+                       if (retval != ERROR_OK) {
+                               ap_gateway->csw_value = 0;
+                               return retval;
+                       }
+                       ap_gateway->csw_value = csw;
+               }
+
+               if (!ap_gateway->tar_valid || tar != ap_gateway->tar_value) {
+                       retval = jtag_ap_q_write(ap_gateway, 
MEM_AP_REG_TAR(ap_gateway->dap), tar);
+                       if (retval != ERROR_OK) {
+                               ap_gateway->tar_valid = false;
+                               return retval;
+                       }
+                       ap_gateway->tar_value = tar;
+                       ap_gateway->tar_valid = true;
+               }
+
+               retval = jtag_ap_q_write(ap_gateway, 
MEM_AP_REG_DRW(ap_gateway->dap), data);
+               if (retval != ERROR_OK)
+                       return retval;
+       } else {
+               retval = jtag_ap_q_bankselect(ap, reg);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval =  adi_jtag_dp_scan_u32(ap->dap, JTAG_DP_APACC, reg,
+                               DPAP_WRITE, data, ap->dap->last_read, 
ap->memaccess_tck, NULL);
+               ap->dap->last_read = NULL;
+       }
 
-       retval =  adi_jtag_dp_scan_u32(ap->dap, JTAG_DP_APACC, reg,
-                       DPAP_WRITE, data, ap->dap->last_read, 
ap->memaccess_tck, NULL);
-       ap->dap->last_read = NULL;
        return retval;
 }
 
diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index 67a3fcc577..a87933fe0f 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -1177,6 +1177,7 @@ static struct adiv5_ap *_dap_get_ap(struct adiv5_dap 
*dap, uint64_t ap_num)
                for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) {
                        struct adiv5_ap *ap = &dap->ap[i];
                        if (!is_ap_in_use(ap)) {
+                               ap->ap_gateway = NULL;
                                ap->ap_num = ap_num;
                                ++ap->refcount;
                                return ap;
@@ -1188,6 +1189,7 @@ static struct adiv5_ap *_dap_get_ap(struct adiv5_dap 
*dap, uint64_t ap_num)
 
        /* ADIv5 */
        struct adiv5_ap *ap = &dap->ap[ap_num];
+       ap->ap_gateway = NULL;
        ap->ap_num = ap_num;
        ++ap->refcount;
        return ap;
diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h
index ebd2752bd8..49bc3ff0b0 100644
--- a/src/target/arm_adi_v5.h
+++ b/src/target/arm_adi_v5.h
@@ -260,6 +260,11 @@ struct adiv5_ap {
         */
        uint64_t ap_num;
 
+       /**
+        * Gateway AP
+        */
+       struct adiv5_ap *ap_gateway;
+
        /**
         * Default value for (MEM-AP) AP_REG_CSW register.
         */
diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c
index 5ba5e1c387..55f2c99150 100644
--- a/src/target/arm_dap.c
+++ b/src/target/arm_dap.c
@@ -37,6 +37,7 @@ static void dap_instance_init(struct adiv5_dap *dap)
        for (i = 0; i <= DP_APSEL_MAX; i++) {
                dap->ap[i].dap = dap;
                dap->ap[i].ap_num = DP_APSEL_INVALID;
+               dap->ap[i].ap_gateway = NULL;
                /* memaccess_tck max is 255 */
                dap->ap[i].memaccess_tck = 255;
                /* Number of bits for tar autoincrement, impl. dep. at least 10 
*/

-- 

Reply via email to