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/+/9250
-- gerrit commit 82eb9a8b9d58531689a85dfca87f2b2e2729d77b Author: Daniel Goehring <[email protected]> Date: Fri Jul 18 21:36:57 2025 -0600 target/arm: add nested AP lookup support Add equivalent AP lookup commands which support gateways for nested APs. Since a nested AP's address can be identical to a non-nested AP's address, these added routines use the gateway AP's address for the AP lookup. Change-Id: I5a8d25f258233f709cb5dc831f029fb6f9fb2a01 Signed-off-by: Daniel Goehring <[email protected]> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 2a599904c4..def4faa75a 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1167,20 +1167,24 @@ static inline bool is_ap_in_use(struct adiv5_ap *ap) static struct adiv5_ap *_dap_get_ap(struct adiv5_dap *dap, uint64_t ap_num) { + struct adiv5_ap *ap; + struct adiv5_ap *ap_gateway; + if (!is_ap_num_valid(dap, ap_num)) { LOG_ERROR("Invalid AP#0x%" PRIx64, ap_num); return NULL; } if (is_adiv6(dap)) { 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_num == ap_num) { + ap = &dap->ap[i]; + ap_gateway = ap->ap_gateway; + if (is_ap_in_use(ap) && !ap_gateway && ap->ap_num == ap_num) { ++ap->refcount; return ap; } } for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) { - struct adiv5_ap *ap = &dap->ap[i]; + ap = &dap->ap[i]; if (!is_ap_in_use(ap)) { ap->ap_gateway = NULL; ap->ap_num = ap_num; @@ -1193,13 +1197,68 @@ 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 = &dap->ap[ap_num]; ap->ap_gateway = NULL; ap->ap_num = ap_num; ++ap->refcount; return ap; } +static struct adiv5_ap *_dap_get_ap_gateway(struct adiv5_dap *dap, uint64_t ap_num, uint64_t ap_num_gateway) +{ + struct adiv5_ap *ap; + struct adiv5_ap *ap_gateway; + + if (!is_ap_num_valid(dap, ap_num)) { + LOG_ERROR("Invalid AP#0x%" PRIx64, ap_num); + return NULL; + } + if (!is_ap_num_valid(dap, ap_num_gateway)) { + LOG_ERROR("Invalid AP_GATEWAY#0x%" PRIx64, ap_num_gateway); + return NULL; + } + + if (is_adiv6(dap)) { + for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) { + ap = &dap->ap[i]; + ap_gateway = ap->ap_gateway; + if (is_ap_in_use(ap) && ap_gateway && is_ap_in_use(ap_gateway) && + ap->ap_num == ap_num && ap_gateway->ap_num == ap_num_gateway) { + ++ap->refcount; + ++ap_gateway->refcount; + return ap; + } + } + ap_gateway = dap_get_ap(dap, ap_num_gateway); + if (!ap_gateway) { + LOG_ERROR("No more AP available!"); + return NULL; + } + for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) { + ap = &dap->ap[i]; + if (!is_ap_in_use(ap)) { + ap->ap_gateway = ap_gateway; + ap->ap_num = ap_num; + ++ap->refcount; + return ap; + } + } + dap_put_ap(ap_gateway); + LOG_ERROR("No more AP available!"); + return NULL; + } + + /* ADIv5 */ + ap = &dap->ap[ap_num]; + ap_gateway = &dap->ap[ap_num_gateway]; + ap->ap_gateway = ap_gateway; + ap->ap_num = ap_num; + ap_gateway->ap_num = ap_num_gateway; + ++ap->refcount; + ++ap_gateway->refcount; + return ap; +} + /* Return AP with specified ap_num. Increment AP refcount */ struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, uint64_t ap_num) { @@ -1209,6 +1268,18 @@ struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, uint64_t ap_num) return ap; } +struct adiv5_ap *dap_get_ap_gateway(struct adiv5_dap *dap, uint64_t ap_num, uint64_t ap_num_gateway) +{ + struct adiv5_ap *ap = _dap_get_ap_gateway(dap, ap_num, ap_num_gateway); + if (ap) { + LOG_DEBUG("refcount AP#0x%" PRIx64 " get %u", ap_num, ap->refcount); + if (ap->ap_gateway) + LOG_DEBUG("refcount AP_GATEWAY#0x%" PRIx64 " get %u", + ap_num_gateway, ap->ap_gateway->refcount); + } + return ap; +} + /* Return AP with specified ap_num. Increment AP refcount and keep it non-zero */ struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, uint64_t ap_num) { @@ -1220,9 +1291,27 @@ struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, uint64_t ap_num) return ap; } +/* Return AP with specified ap_num. Increment AP refcount and keep it non-zero */ +struct adiv5_ap *dap_get_config_ap_gateway(struct adiv5_dap *dap, uint64_t ap_num, uint64_t ap_num_gateway) +{ + struct adiv5_ap *ap = _dap_get_ap_gateway(dap, ap_num, ap_num_gateway); + if (ap) { + ap->config_ap_never_release = true; + LOG_DEBUG("refcount AP#0x%" PRIx64 " get_config %u", ap_num, ap->refcount); + if (ap->ap_gateway) { + ap->ap_gateway->config_ap_never_release = true; + LOG_DEBUG("refcount AP_GATEWAY#0x%" PRIx64 " get_config %u", + ap_num_gateway, ap->ap_gateway->refcount); + } + } + return ap; +} + /* Decrement AP refcount and release the AP when refcount reaches zero */ int dap_put_ap(struct adiv5_ap *ap) { + struct adiv5_ap *ap_gateway = ap->ap_gateway; + if (ap->refcount == 0) { LOG_ERROR("BUG: refcount AP#0x%" PRIx64 " put underflow", ap->ap_num); return ERROR_FAIL; @@ -1234,11 +1323,33 @@ int dap_put_ap(struct adiv5_ap *ap) if (!is_ap_in_use(ap)) { /* defaults from dap_instance_init() */ ap->ap_num = DP_APSEL_INVALID; + ap->ap_gateway = NULL; ap->memaccess_tck = 255; ap->tar_autoincr_block = (1 << 10); ap->csw_default = CSW_AHB_DEFAULT; ap->cfg_reg = MEM_AP_REG_CFG_INVALID; } + + if (ap_gateway) { + if (ap_gateway->refcount == 0) { + LOG_ERROR("BUG: refcount AP_GATEWAY#0x%" PRIx64 " put underflow", ap_gateway->ap_num); + return ERROR_FAIL; + } + + --ap_gateway->refcount; + + LOG_DEBUG("refcount AP_GATEWAY#0x%" PRIx64 " put %u", ap_gateway->ap_num, ap_gateway->refcount); + if (!is_ap_in_use(ap_gateway)) { + /* defaults from dap_instance_init() */ + ap_gateway->ap_num = DP_APSEL_INVALID; + ap_gateway->ap_gateway = NULL; + ap_gateway->memaccess_tck = 255; + ap_gateway->tar_autoincr_block = (1 << 10); + ap_gateway->csw_default = CSW_AHB_DEFAULT; + ap_gateway->cfg_reg = MEM_AP_REG_CFG_INVALID; + } + } + return ERROR_OK; } diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 49bc3ff0b0..72a29faff2 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -750,9 +750,11 @@ int dap_find_get_ap(struct adiv5_dap *dap, /* Return AP with specified ap_num. Increment AP refcount */ struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, uint64_t ap_num); +struct adiv5_ap *dap_get_ap_gateway(struct adiv5_dap *dap, uint64_t ap_num, uint64_t ap_num_gateway); /* Return AP with specified ap_num. Increment AP refcount and keep it non-zero */ struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, uint64_t ap_num); +struct adiv5_ap *dap_get_config_ap_gateway(struct adiv5_dap *dap, uint64_t ap_num, uint64_t ap_num_gateway); /* Decrement AP refcount and release the AP when refcount reaches zero */ int dap_put_ap(struct adiv5_ap *ap); --
