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/+/9253

-- gerrit

commit 42858f6af9dc0bf48d1a7ab3646f8119829c7d1d
Author: Daniel Goehring <[email protected]>
Date:   Tue Aug 5 11:01:26 2025 -0600

    target/arm: add nested AP DAP 'apreg_gw' cmd support
    
    Create a new DAP 'apreg_gw' command for nested AP support.
    
    The abbreviation 'gw' refers to 'gateway', the top-level nested
    access port.
    
    Change-Id: Iaebf0a44cd3394767eefce5ec0e9d280dd3f3500
    Signed-off-by: Daniel Goehring <[email protected]>

diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index 77e3202927..9fdf32476f 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -3009,6 +3009,100 @@ COMMAND_HANDLER(dap_apreg_command)
        return retval;
 }
 
+COMMAND_HANDLER(dap_apreg_gw_command)
+{
+       struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
+       struct adiv5_ap *ap;
+       uint64_t apsel;
+       uint64_t apsel_gateway = DP_APSEL_INVALID;
+       uint32_t reg, value;
+       int retval;
+
+       if (CMD_ARGC < 2 || CMD_ARGC > 4)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], apsel);
+       if (!is_ap_num_valid(dap, apsel)) {
+               command_print(CMD, "Invalid AP number");
+               return ERROR_COMMAND_ARGUMENT_INVALID;
+       }
+
+       COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], apsel_gateway);
+       if (!is_ap_num_valid(dap, apsel_gateway)) {
+               command_print(CMD, "Invalid AP_GATEWAY number");
+               return ERROR_COMMAND_ARGUMENT_INVALID;
+       }
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], reg);
+       if (is_adiv6(dap)) {
+               if (reg >= 4096 || (reg & 3)) {
+                       command_print(CMD, "Invalid reg value (should be less 
than 4096 and 4 bytes aligned)");
+                       return ERROR_COMMAND_ARGUMENT_INVALID;
+               }
+       } else {        /* ADI version 5 */
+               if (reg >= 256 || (reg & 3)) {
+                       command_print(CMD, "Invalid reg value (should be less 
than 256 and 4 bytes aligned)");
+                       return ERROR_COMMAND_ARGUMENT_INVALID;
+               }
+       }
+
+       if (apsel_gateway == DP_APSEL_INVALID)
+               ap = dap_get_ap(dap, apsel);
+       else
+               ap = dap_get_ap_gateway(dap, apsel, apsel_gateway);
+
+       if (!ap) {
+               command_print(CMD, "Cannot get AP");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC == 4) {
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], value);
+               /* see if user supplied register address is a match for the CSW 
or TAR register */
+               if (reg == MEM_AP_REG_CSW(dap)) {
+                       ap->csw_value = 0;  /* invalid, in case write fails */
+                       retval = dap_queue_ap_write(ap, reg, value);
+                       if (retval == ERROR_OK)
+                               ap->csw_value = value;
+               } else if (reg == MEM_AP_REG_TAR(dap)) {
+                       retval = dap_queue_ap_write(ap, reg, value);
+                       if (retval == ERROR_OK) {
+                               ap->tar_value = (ap->tar_value & 
~0xFFFFFFFFull) | value;
+                       } else {
+                               /* To track independent writes to TAR and 
TAR64, two tar_valid flags */
+                               /* should be used. To keep it simple, tar_valid 
is only invalidated on a */
+                               /* write fail. This approach causes a later 
re-write of the TAR and TAR64 */
+                               /* if tar_valid is false. */
+                               ap->tar_valid = false;
+                       }
+               } else if (reg == MEM_AP_REG_TAR64(dap)) {
+                       retval = dap_queue_ap_write(ap, reg, value);
+                       if (retval == ERROR_OK) {
+                               ap->tar_value = (ap->tar_value & 0xFFFFFFFFull) 
| (((target_addr_t)value) << 32);
+                       } else {
+                               /* See above comment for the MEM_AP_REG_TAR 
failed write case */
+                               ap->tar_valid = false;
+                       }
+               } else {
+                       retval = dap_queue_ap_write(ap, reg, value);
+               }
+       } else {
+               retval = dap_queue_ap_read(ap, reg, &value);
+       }
+       if (retval == ERROR_OK)
+               retval = dap_run(dap);
+
+       dap_put_ap(ap);
+
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (CMD_ARGC == 3)
+               command_print(CMD, "0x%08" PRIx32, value);
+
+       return retval;
+}
+
 COMMAND_HANDLER(dap_dpreg_command)
 {
        struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
@@ -3093,10 +3187,18 @@ const struct command_registration 
dap_instance_commands[] = {
                .name = "apreg",
                .handler = dap_apreg_command,
                .mode = COMMAND_EXEC,
-               .help = "read/write a register from AP "
+               .help = "read/write a register from a non-nested AP "
                        "(reg is byte address of a word register, like 0 4 
8...)",
                .usage = "ap_num reg [value]",
        },
+       {
+               .name = "apreg_gw",
+               .handler = dap_apreg_gw_command,
+               .mode = COMMAND_EXEC,
+               .help = "read/write a register from a nested AP "
+                       "(reg is byte address of a word register, like 0 4 
8...)",
+               .usage = "ap_num ap_num_gateway reg [value]",
+       },
        {
                .name = "dpreg",
                .handler = dap_dpreg_command,

-- 

Reply via email to