This is an automated email from Gerrit.

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

-- gerrit

commit 0a1949e1b12d2f5dfc328d15e54b69927f06f2b9
Author: Tomas Vanek <[email protected]>
Date:   Sun Feb 11 18:01:24 2024 +0100

    target/riscv: DM access on a DAP
    
    Modify riscv target to optionally accept -dap and -ap-num options
    instead of -chain-position
    The selected AP is used as an alternative DMI.
    DTM version is fixed to 1 because DTM control scan is not available.
    
    Basic DM access works.
    
    riscv_batch works without a configurable delay. Also an optional
    read back request in riscv_batch_add_dm_write() is silently ignored.
    
    Signed-off-by: Tomas Vanek <[email protected]>
    Change-Id: I5399207d897d93419198c40b521e4464e04ff1a6

diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c
index 5acbddaf37..bd59deb193 100644
--- a/src/target/riscv/batch.c
+++ b/src/target/riscv/batch.c
@@ -10,6 +10,8 @@
 #include "riscv.h"
 #include "field_helpers.h"
 
+#include <target/arm_adi_v5.h>
+
 // TODO: DTM_DMI_MAX_ADDRESS_LENGTH should be reduced to 32 (per the debug 
spec)
 #define DTM_DMI_MAX_ADDRESS_LENGTH     ((1<<DTM_DTMCS_ABITS_LENGTH)-1)
 #define DMI_SCAN_MAX_BIT_LENGTH (DTM_DMI_MAX_ADDRESS_LENGTH + 
DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH)
@@ -50,35 +52,45 @@ struct riscv_batch *riscv_batch_alloc(struct target 
*target, size_t scans)
        out->bscan_ctxt = NULL;
        out->read_keys = NULL;
 
-       /* FIXME: There is potential for memory usage reduction. We could 
allocate
-        * smaller buffers than DMI_SCAN_BUF_SIZE (that is, buffers that 
correspond to
-        * the real DR scan length on the given target) */
-       out->data_out = malloc(sizeof(*out->data_out) * scans * 
DMI_SCAN_BUF_SIZE);
-       if (!out->data_out) {
-               LOG_ERROR("Failed to allocate data_out in RISC-V batch.");
-               goto alloc_error;
-       };
+       struct riscv_info *r = riscv_info(target);
+       out->emulated = r->alternative_dmi;
+
+       if (out->emulated && r->get_dmi_ap)
+               out->ap = r->get_dmi_ap(target);
+
+       if (!out->emulated) {
+               /* FIXME: There is potential for memory usage reduction. We 
could allocate
+                * smaller buffers than DMI_SCAN_BUF_SIZE (that is, buffers 
that correspond to
+                * the real DR scan length on the given target) */
+               out->data_out = malloc(sizeof(*out->data_out) * scans * 
DMI_SCAN_BUF_SIZE);
+               if (!out->data_out) {
+                       LOG_ERROR("Failed to allocate data_out in RISC-V 
batch.");
+                       goto alloc_error;
+               };
+       }
        out->data_in = malloc(sizeof(*out->data_in) * scans * 
DMI_SCAN_BUF_SIZE);
        if (!out->data_in) {
                LOG_ERROR("Failed to allocate data_in in RISC-V batch.");
                goto alloc_error;
        }
-       out->fields = malloc(sizeof(*out->fields) * scans);
-       if (!out->fields) {
-               LOG_ERROR("Failed to allocate fields in RISC-V batch.");
-               goto alloc_error;
-       }
-       out->delay_classes = malloc(sizeof(*out->delay_classes) * scans);
-       if (!out->delay_classes) {
-               LOG_ERROR("Failed to allocate delay_classes in RISC-V batch.");
-               goto alloc_error;
-       }
-       if (bscan_tunnel_ir_width != 0) {
-               out->bscan_ctxt = malloc(sizeof(*out->bscan_ctxt) * scans);
-               if (!out->bscan_ctxt) {
-                       LOG_ERROR("Failed to allocate bscan_ctxt in RISC-V 
batch.");
+       if (!out->emulated) {
+               out->fields = malloc(sizeof(*out->fields) * scans);
+               if (!out->fields) {
+                       LOG_ERROR("Failed to allocate fields in RISC-V batch.");
+                       goto alloc_error;
+               }
+               out->delay_classes = malloc(sizeof(*out->delay_classes) * 
scans);
+               if (!out->delay_classes) {
+                       LOG_ERROR("Failed to allocate delay_classes in RISC-V 
batch.");
                        goto alloc_error;
                }
+               if (bscan_tunnel_ir_width != 0) {
+                       out->bscan_ctxt = malloc(sizeof(*out->bscan_ctxt) * 
scans);
+                       if (!out->bscan_ctxt) {
+                               LOG_ERROR("Failed to allocate bscan_ctxt in 
RISC-V batch.");
+                               goto alloc_error;
+                       }
+               }
        }
        out->read_keys = malloc(sizeof(*out->read_keys) * scans);
        if (!out->read_keys) {
@@ -335,6 +347,36 @@ void riscv_batch_add_dmi_write(struct riscv_batch *batch, 
uint32_t address, uint
        // otherwise return an error (during batch creation or when the batch 
is executed).
 
        assert(batch->used_scans < batch->allocated_scans);
+       if (batch->emulated) {
+               if (batch->queued_retval == ERROR_OK) {
+                       if (batch->ap) {
+                               uint32_t dmi_addr = 4 * 
riscv_get_dmi_address(batch->target, address);
+                               batch->queued_retval = 
mem_ap_write_u32(batch->ap, dmi_addr, data);
+#ifdef DMI_WRITE_READBACK
+                               if (read_back && batch->queued_retval == 
ERROR_OK) {
+                                       uint32_t *data_in = (uint32_t 
*)batch->data_in;
+                                       data_in = &data_in[batch->used_scans];
+                                       batch->queued_retval = 
mem_ap_read_u32(batch->ap, dmi_addr, data_in);
+                                       batch->used_scans++;
+                               }
+#endif
+                       } else {
+                               uint32_t dmi_addr = 
riscv_get_dmi_address(batch->target, address);
+                               batch->queued_retval = 
riscv_dmi_write(batch->target, dmi_addr, data);
+#ifdef DMI_WRITE_READBACK
+                               if (read_back && batch->queued_retval == 
ERROR_OK) {
+                                       uint32_t *data_in = (uint32_t 
*)batch->data_in;
+                                       data_in = &data_in[batch->used_scans];
+                                       batch->queued_retval = 
riscv_dmi_read(batch->target,
+                                                                               
   data_in, dmi_addr);
+                                       batch->used_scans++;
+                               }
+#endif
+                       }
+               }
+               batch->last_scan = RISCV_SCAN_TYPE_WRITE;
+               return;
+       }
        struct scan_field *field = batch->fields + batch->used_scans;
 
        field->num_bits = get_dmi_scan_length(batch->target);
@@ -365,30 +407,53 @@ size_t riscv_batch_add_dmi_read(struct riscv_batch 
*batch, uint32_t address,
        // otherwise return an error (during batch creation or when the batch 
is executed).
 
        assert(batch->used_scans < batch->allocated_scans);
-       struct scan_field *field = batch->fields + batch->used_scans;
+       if (batch->emulated) {
+               if (batch->queued_retval == ERROR_OK) {
+                       uint32_t *data_in = (uint32_t *)batch->data_in;
+                       data_in = &data_in[batch->used_scans];
+                       if (batch->ap) {
+                               uint32_t dmi_addr = 4 * 
riscv_get_dmi_address(batch->target, address);
+                               batch->queued_retval = 
mem_ap_read_u32(batch->ap, dmi_addr, data_in);
+                       } else {
+                               uint32_t dmi_addr = 
riscv_get_dmi_address(batch->target, address);
+                               batch->queued_retval = 
riscv_dmi_read(batch->target,
+                                                                               
   data_in, dmi_addr);
+                       }
+               }
+               batch->read_keys[batch->read_keys_used] = batch->used_scans;
+       } else {
+               struct scan_field *field = batch->fields + batch->used_scans;
 
-       field->num_bits = get_dmi_scan_length(batch->target);
-       assert(field->num_bits <= DMI_SCAN_MAX_BIT_LENGTH);
+               field->num_bits = get_dmi_scan_length(batch->target);
+               assert(field->num_bits <= DMI_SCAN_MAX_BIT_LENGTH);
 
-       uint8_t *out_value = batch->data_out + batch->used_scans * 
DMI_SCAN_BUF_SIZE;
-       uint8_t *in_value = batch->data_in + batch->used_scans * 
DMI_SCAN_BUF_SIZE;
+               uint8_t *out_value = batch->data_out + batch->used_scans * 
DMI_SCAN_BUF_SIZE;
+               uint8_t *in_value = batch->data_in + batch->used_scans * 
DMI_SCAN_BUF_SIZE;
 
-       field->out_value = out_value;
-       field->in_value = in_value;
-       riscv_fill_dmi_read(batch->target, out_value, address);
-       riscv_fill_dm_nop(batch->target, in_value);
+               field->out_value = out_value;
+               field->in_value = in_value;
+               riscv_fill_dmi_read(batch->target, out_value, address);
+               riscv_fill_dm_nop(batch->target, in_value);
+
+               batch->delay_classes[batch->used_scans] = delay_class;
+               batch->read_keys[batch->read_keys_used] = batch->used_scans + 1;
+       }
 
-       batch->delay_classes[batch->used_scans] = delay_class;
        batch->last_scan = RISCV_SCAN_TYPE_READ;
        batch->used_scans++;
 
-       batch->read_keys[batch->read_keys_used] = batch->used_scans;
        return batch->read_keys_used++;
 }
 
 uint32_t riscv_batch_get_dmi_read_op(const struct riscv_batch *batch, size_t 
key)
 {
        assert(key < batch->read_keys_used);
+       if (batch->emulated) {
+               if (batch->queued_retval == ERROR_OK)
+                       return DTM_DMI_OP_SUCCESS;
+               else
+                       return DTM_DMI_OP_FAILED;
+       }
        size_t index = batch->read_keys[key];
        assert(index < batch->used_scans);
        uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index;
@@ -401,6 +466,10 @@ uint32_t riscv_batch_get_dmi_read_data(const struct 
riscv_batch *batch, size_t k
        assert(key < batch->read_keys_used);
        size_t index = batch->read_keys[key];
        assert(index < batch->used_scans);
+       if (batch->emulated) {
+               uint32_t *data_in = (uint32_t *)batch->data_in;
+               return data_in[index];
+       }
        uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index;
        /* extract "data" field from the DMI read result */
        return buf_get_u32(base, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH);
@@ -409,6 +478,9 @@ uint32_t riscv_batch_get_dmi_read_data(const struct 
riscv_batch *batch, size_t k
 void riscv_batch_add_nop(struct riscv_batch *batch)
 {
        assert(batch->used_scans < batch->allocated_scans);
+       if (batch->emulated)
+               return;
+
        struct scan_field *field = batch->fields + batch->used_scans;
 
        field->num_bits = get_dmi_scan_length(batch->target);
@@ -438,6 +510,10 @@ size_t riscv_batch_available_scans(struct riscv_batch 
*batch)
 bool riscv_batch_was_batch_busy(const struct riscv_batch *batch)
 {
        assert(batch->was_run);
+
+       if (batch->emulated)
+               return false;
+
        assert(batch->used_scans);
        assert(batch->last_scan == RISCV_SCAN_TYPE_NOP);
        return riscv_batch_was_scan_busy(batch, batch->used_scans - 1);
diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h
index 5d8b57234e..687a2babd5 100644
--- a/src/target/riscv/batch.h
+++ b/src/target/riscv/batch.h
@@ -7,6 +7,8 @@
 #include "jtag/jtag.h"
 #include "riscv.h"
 
+#include "target/arm_adi_v5.h"
+
 enum riscv_scan_type {
        RISCV_SCAN_TYPE_INVALID,
        RISCV_SCAN_TYPE_NOP,
@@ -159,6 +161,10 @@ struct riscv_batch {
         * Only valid when `was_run` is set.
         */
        unsigned int last_scan_delay;
+
+       bool emulated;
+       int queued_retval;
+       struct adiv5_ap *ap;
 };
 
 /* Allocates (or frees) a new scan set.  "scans" is the maximum number of JTAG
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 22128d7ab7..236646c1ed 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -18,6 +18,7 @@
 #include "target/algorithm.h"
 #include "target/target_type.h"
 #include <helper/align.h>
+#include <target/arm_adi_v5.h>
 #include <helper/log.h>
 #include "jtag/jtag.h"
 #include "target/register.h"
@@ -138,6 +139,8 @@ typedef struct {
         * abstractcs.busy may have remained set. In that case we may need to
         * re-check the busy state before executing these operations. */
        bool abstract_cmd_maybe_busy;
+
+       struct adiv5_ap *dmi_ap;
 } dm013_info_t;
 
 typedef struct {
@@ -257,6 +260,9 @@ typedef struct {
 
        /* This hart was placed into a halt group in examine(). */
        bool haltgroup_supported;
+
+       /* DM is accessed other way than by JTAG */
+       bool alternative_dmi;
 } riscv013_info_t;
 
 static OOCD_LIST_HEAD(dm_list);
@@ -280,6 +286,7 @@ static dm013_info_t *get_dm(struct target *target)
        if (info->dm)
                return info->dm;
 
+       struct riscv_info *r = riscv_info(target);
        unsigned int abs_chain_position = target->tap->abs_chain_position;
 
        dm013_info_t *entry;
@@ -305,11 +312,28 @@ static dm013_info_t *get_dm(struct target *target)
                dm->base = target->dbgbase;
                dm->current_hartid = 0;
                dm->hart_count = -1;
+
+               if (r->alternative_dmi) {
+                       struct riscv_private_config *config = 
riscv_private_config(target);
+                       struct adiv5_private_config *pc = &config->adi_pc;
+                       dm->dmi_ap = dap_get_ap(pc->dap, pc->ap_num);
+                       if (!dm->dmi_ap) {
+                               LOG_TARGET_ERROR(target, "Cannot use %s AP 
0x%08" PRIx64 " for DM access",
+                                                                
adiv5_dap_name(pc->dap), pc->ap_num);
+                               free(dm);
+                               return NULL;
+                       }
+               }
+
                INIT_LIST_HEAD(&dm->target_list);
                list_add(&dm->list, &dm_list);
        }
 
        info->dm = dm;
+
+       if (dm->dmi_ap)
+               info->alternative_dmi = true;
+
        target_list_t *target_entry;
        list_for_each_entry(target_entry, &dm->target_list, list) {
                if (target_entry->target == target)
@@ -343,12 +367,22 @@ static void riscv013_dm_free(struct target *target)
        }
 
        if (list_empty(&dm->target_list)) {
+               if (dm->dmi_ap)
+                       dap_put_ap(dm->dmi_ap);
+
                list_del(&dm->list);
                free(dm);
        }
        info->dm = NULL;
 }
 
+static struct adiv5_ap *riscv013_get_dmi_ap(struct target *target)
+{
+       dm013_info_t *dm = get_dm(target);
+
+       return dm->dmi_ap;
+}
+
 static struct riscv_debug_reg_ctx get_riscv_debug_reg_ctx(const struct target 
*target)
 {
        if (!target_was_examined(target)) {
@@ -406,8 +440,13 @@ static uint32_t set_dmcontrol_hartsel(uint32_t initial, 
int hart_index)
 
 /*** Utility functions. ***/
 
-static void select_dmi(struct jtag_tap *tap)
+static void select_dmi(struct target *target)
 {
+       riscv013_info_t *info = get_info(target);
+       if (info->alternative_dmi)
+               return;
+
+       struct jtag_tap *tap = target->tap;
        if (bscan_tunnel_ir_width != 0) {
                select_dmi_via_bscan(tap);
                return;
@@ -2001,53 +2040,60 @@ static int examine(struct target *target)
        /* Don't need to select dbus, since the first thing we do is read 
dtmcontrol. */
        LOG_TARGET_DEBUG(target, "dbgbase=0x%x", target->dbgbase);
 
-       uint32_t dtmcontrol;
-       if (dtmcs_scan(target->tap, 0, &dtmcontrol) != ERROR_OK || dtmcontrol 
== 0) {
-               LOG_TARGET_ERROR(target, "Could not scan dtmcontrol. Check JTAG 
connectivity/board power.");
-               return ERROR_FAIL;
-       }
+       riscv013_info_t *info = get_info(target);
 
-       LOG_TARGET_DEBUG(target, "dtmcontrol=0x%x", dtmcontrol);
-       LOG_DEBUG_REG(target, DTM_DTMCS, dtmcontrol);
+       info->index = target->coreid;
 
-       if (get_field(dtmcontrol, DTM_DTMCS_VERSION) != 1) {
-               LOG_TARGET_ERROR(target, "Unsupported DTM version %" PRIu32 ". 
(dtmcontrol=0x%" PRIx32 ")",
-                               get_field32(dtmcontrol, DTM_DTMCS_VERSION), 
dtmcontrol);
+       dm013_info_t *dm = get_dm(target);
+       if (!dm)
                return ERROR_FAIL;
-       }
 
-       riscv013_info_t *info = get_info(target);
+       if (!info->alternative_dmi) {
+               uint32_t dtmcontrol;
+               if (dtmcs_scan(target->tap, 0, &dtmcontrol) != ERROR_OK || 
dtmcontrol == 0) {
+                       LOG_TARGET_ERROR(target, "Could not scan dtmcontrol. 
Check JTAG connectivity/board power.");
+                       return ERROR_FAIL;
+               }
 
-       info->index = target->coreid;
-       info->abits = get_field(dtmcontrol, DTM_DTMCS_ABITS);
-       info->dtmcs_idle = get_field(dtmcontrol, DTM_DTMCS_IDLE);
+               LOG_TARGET_DEBUG(target, "dtmcontrol=0x%x", dtmcontrol);
+               LOG_DEBUG_REG(target, DTM_DTMCS, dtmcontrol);
 
-       if (info->abits > RISCV013_DTMCS_ABITS_MAX) {
-               /* Max. address width given by the debug specification is 
exceeded */
-               LOG_TARGET_ERROR(target, "The target's debug bus (DMI) address 
width exceeds "
-                       "the maximum:");
-               LOG_TARGET_ERROR(target, " found dtmcs.abits = %d; maximum is 
abits = %d.",
-                       info->abits, RISCV013_DTMCS_ABITS_MAX);
-               return ERROR_FAIL;
-       }
+               if (get_field(dtmcontrol, DTM_DTMCS_VERSION) != 1) {
+                       LOG_TARGET_ERROR(target, "Unsupported DTM version %" 
PRIu32 ". (dtmcontrol=0x%" PRIx32 ")",
+                                       get_field32(dtmcontrol, 
DTM_DTMCS_VERSION), dtmcontrol);
+                       return ERROR_FAIL;
+               }
 
-       if (info->abits == 0) {
-               LOG_TARGET_ERROR(target,
-                               "dtmcs.abits is zero. Check JTAG 
connectivity/board power");
-               return ERROR_FAIL;
-       }
-       if (info->abits < RISCV013_DTMCS_ABITS_MIN) {
-               /* The requirement for minimum DMI address width of 7 bits is 
part of
-                * the RISC-V Debug spec since Jan-20-2017 (commit 03df6ee7). 
However,
-                * implementations exist that implement narrower DMI address. 
For example
-                * Spike as of Q1/2025 uses dmi.abits = 6.
-                *
-                * For that reason, warn the user but continue.
-                */
-               LOG_TARGET_WARNING(target, "The target's debug bus (DMI) 
address width is "
-                       "lower than the minimum:");
-               LOG_TARGET_WARNING(target, " found dtmcs.abits = %d; minimum is 
abits = %d.",
-                       info->abits, RISCV013_DTMCS_ABITS_MIN);
+               info->abits = get_field(dtmcontrol, DTM_DTMCS_ABITS);
+               info->dtmcs_idle = get_field(dtmcontrol, DTM_DTMCS_IDLE);
+
+               if (info->abits > RISCV013_DTMCS_ABITS_MAX) {
+                       /* Max. address width given by the debug specification 
is exceeded */
+                       LOG_TARGET_ERROR(target, "The target's debug bus (DMI) 
address width exceeds "
+                               "the maximum:");
+                       LOG_TARGET_ERROR(target, " found dtmcs.abits = %d; 
maximum is abits = %d.",
+                               info->abits, RISCV013_DTMCS_ABITS_MAX);
+                       return ERROR_FAIL;
+               }
+
+               if (info->abits == 0) {
+                       LOG_TARGET_ERROR(target,
+                                       "dtmcs.abits is zero. Check JTAG 
connectivity/board power");
+                       return ERROR_FAIL;
+               }
+               if (info->abits < RISCV013_DTMCS_ABITS_MIN) {
+                       /* The requirement for minimum DMI address width of 7 
bits is part of
+                        * the RISC-V Debug spec since Jan-20-2017 (commit 
03df6ee7). However,
+                        * implementations exist that implement narrower DMI 
address. For example
+                        * Spike as of Q1/2025 uses dmi.abits = 6.
+                        *
+                        * For that reason, warn the user but continue.
+                        */
+                       LOG_TARGET_WARNING(target, "The target's debug bus 
(DMI) address width is "
+                               "lower than the minimum:");
+                       LOG_TARGET_WARNING(target, " found dtmcs.abits = %d; 
minimum is abits = %d.",
+                               info->abits, RISCV013_DTMCS_ABITS_MIN);
+               }
        }
 
        if (!check_dbgbase_exists(target)) {
@@ -2515,7 +2561,20 @@ static int batch_run(struct target *target, struct 
riscv_batch *batch)
 {
        RISCV_INFO(r);
        RISCV013_INFO(info);
-       select_dmi(target->tap);
+       select_dmi(target);
+
+       if (batch->emulated) {
+               if (batch->ap) {
+                       int retval = dap_run(batch->ap->dap);
+                       if (retval == ERROR_OK)
+                               batch->was_run = true;
+
+                       return retval;
+               }
+
+               return ERROR_OK;
+       }
+
        riscv_batch_add_nop(batch);
        const int result = riscv_batch_run_from(batch, 0, &info->learned_delays,
                        /*resets_delays*/  r->reset_delays_wait >= 0,
@@ -2538,7 +2597,20 @@ static int batch_run(struct target *target, struct 
riscv_batch *batch)
 static int batch_run_timeout(struct target *target, struct riscv_batch *batch)
 {
        RISCV013_INFO(info);
-       select_dmi(target->tap);
+       select_dmi(target);
+
+       if (batch->emulated) {
+               if (batch->ap) {
+                       int retval = dap_run(batch->ap->dap);
+                       if (retval == ERROR_OK)
+                               batch->was_run = true;
+
+                       return retval;
+               }
+
+               return ERROR_OK;
+       }
+
        riscv_batch_add_nop(batch);
 
        size_t finished_scans = 0;
@@ -2894,6 +2966,8 @@ static int init_target(struct command_context *cmd_ctx,
                        return ERROR_FAIL;
        }
        generic_info->sample_memory = sample_memory;
+       generic_info->get_dmi_ap = riscv013_get_dmi_ap;
+
        riscv013_info_t *info = get_info(target);
 
        info->progbufsize = -1;
@@ -2909,7 +2983,7 @@ static int assert_reset(struct target *target)
        RISCV013_INFO(info);
        int result;
 
-       select_dmi(target->tap);
+       select_dmi(target);
 
        if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) {
                /* Run the user-supplied script if there is one. */
@@ -2963,7 +3037,7 @@ static int deassert_reset(struct target *target)
                return ERROR_FAIL;
        int result;
 
-       select_dmi(target->tap);
+       select_dmi(target);
        /* Clear the reset, but make sure haltreq is still set */
        uint32_t control = 0;
        control = set_field(control, DM_DMCONTROL_DMACTIVE, 1);
@@ -4455,7 +4529,7 @@ read_memory_progbuf(struct target *target, const struct 
riscv_mem_access_args ar
 {
        assert(riscv_mem_access_is_read(args));
 
-       select_dmi(target->tap);
+       select_dmi(target);
        memset(args.read_buffer, 0, args.count * args.size);
 
        if (execute_autofence(target) != ERROR_OK)
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 0688ad327b..cfe1c2ee17 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -13,6 +13,7 @@
 #include "target/target.h"
 #include "target/algorithm.h"
 #include "target/target_type.h"
+#include <target/arm_adi_v5.h>
 #include <target/smp.h>
 #include "jtag/jtag.h"
 #include "target/register.h"
@@ -477,7 +478,7 @@ static struct target_type *get_target_type(struct target 
*target)
 
 static struct riscv_private_config *alloc_default_riscv_private_config(void)
 {
-       struct riscv_private_config * const config = malloc(sizeof(*config));
+       struct riscv_private_config * const config = calloc(1, sizeof(*config));
        if (!config) {
                LOG_ERROR("Out of memory!");
                return NULL;
@@ -638,7 +639,7 @@ static int riscv_jim_configure(struct target *target,
        int e = jim_nvp_name2value_obj(goi->interp, nvp_config_opts,
                                goi->argv[0], &n);
        if (e != JIM_OK)
-               return JIM_CONTINUE;
+               return adiv5_jim_configure_ext(target, goi, &config->adi_pc, 
ADI_CONFIGURE_DAP_OPTIONAL);
 
        e = jim_getopt_obj(goi, NULL);
        if (e != JIM_OK)
@@ -755,7 +756,6 @@ static void riscv_deinit_target(struct target *target)
        }
 
        free(target->arch_info);
-
        target->arch_info = NULL;
 }
 
@@ -2480,14 +2480,23 @@ static int riscv_examine(struct target *target)
        /* Don't need to select dbus, since the first thing we do is read 
dtmcontrol. */
 
        RISCV_INFO(info);
-       uint32_t dtmcontrol;
-       if (dtmcs_scan(target->tap, 0, &dtmcontrol) != ERROR_OK || dtmcontrol 
== 0) {
-               LOG_TARGET_ERROR(target, "Could not read dtmcontrol. Check JTAG 
connectivity/board power.");
-               return ERROR_FAIL;
+       uint32_t dtm_version;
+
+       struct adiv5_private_config *pc = target->private_config;
+       if (adiv5_verify_config(pc) == ERROR_OK) {
+               dtm_version = 1;
+               info->alternative_dmi = true;
+       } else {
+               uint32_t dtmcontrol;
+               if (dtmcs_scan(target->tap, 0, &dtmcontrol) != ERROR_OK || 
dtmcontrol == 0) {
+                       LOG_TARGET_ERROR(target, "Could not read dtmcontrol. 
Check JTAG connectivity/board power.");
+                       return ERROR_FAIL;
+               }
+
+               LOG_TARGET_DEBUG(target, "dtmcontrol=0x%" PRIx32, dtmcontrol);
+               dtm_version = get_field(dtmcontrol, DTMCONTROL_VERSION);
+               LOG_TARGET_DEBUG(target, "version=0x%" PRIx32, dtm_version);
        }
-       LOG_TARGET_DEBUG(target, "dtmcontrol=0x%" PRIx32, dtmcontrol);
-       uint32_t dtm_version = get_field(dtmcontrol, DTMCONTROL_VERSION);
-       LOG_TARGET_DEBUG(target, "version=0x%" PRIx32, dtm_version);
 
        struct target_type *tt;
        if (info->dtm_version == DTM_DTMCS_VERSION_UNKNOWN) {
@@ -4663,7 +4672,7 @@ uint32_t riscv_get_dmi_address(const struct target 
*target, uint32_t dm_address)
        return r->get_dmi_address(target, dm_address);
 }
 
-static int riscv_dmi_read(struct target *target, uint32_t *value, uint32_t 
address)
+int riscv_dmi_read(struct target *target, uint32_t *value, uint32_t address)
 {
        if (!target) {
                LOG_ERROR("target is NULL!");
@@ -4681,7 +4690,7 @@ static int riscv_dmi_read(struct target *target, uint32_t 
*value, uint32_t addre
        return r->dmi_read(target, value, address);
 }
 
-static int riscv_dmi_write(struct target *target, uint32_t dmi_address, 
uint32_t value)
+int riscv_dmi_write(struct target *target, uint32_t dmi_address, uint32_t 
value)
 {
        if (!target) {
                LOG_ERROR("target is NULL!");
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index 2a0a9b95f0..f6958af8ad 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -12,6 +12,7 @@ struct riscv_program;
 #include "target/semihosting_common.h"
 #include "target/target.h"
 #include "target/register.h"
+#include <target/arm_adi_v5.h>
 #include <helper/command.h>
 #include <helper/bits.h>
 
@@ -307,6 +308,8 @@ struct riscv_info {
 
        unsigned int (*data_bits)(struct target *target);
 
+       struct adiv5_ap *(*get_dmi_ap)(struct target *target);
+
        COMMAND_HELPER((*print_info), struct target *target);
 
        /* Storage for arch_info of non-custom registers. */
@@ -365,6 +368,8 @@ struct riscv_info {
        bool wp_allow_ge_lt_trigger;
 
        bool autofence;
+
+       bool alternative_dmi;
 };
 
 enum riscv_priv_mode {
@@ -378,6 +383,7 @@ enum riscv_priv_mode {
 
 struct riscv_private_config {
        bool dcsr_ebreak_fields[N_RISCV_MODE];
+       struct adiv5_private_config adi_pc;
 };
 
 static inline struct riscv_private_config
@@ -487,6 +493,9 @@ unsigned int riscv_get_dmi_address_bits(const struct target 
*target);
 
 uint32_t riscv_get_dmi_address(const struct target *target, uint32_t 
dm_address);
 
+int riscv_dmi_read(struct target *target, uint32_t *value, uint32_t 
dmi_address);
+int riscv_dmi_write(struct target *target, uint32_t dmi_address, uint32_t 
value);
+
 int riscv_enumerate_triggers(struct target *target);
 
 int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint);

-- 

Reply via email to