+static int stlink_dap_op_queue_dp_read(struct adiv5_dap *dap, unsigned int reg,
+ uint32_t *data)
+{
+ if (stlink_dap_get_error() != ERROR_OK)
+ return ERROR_OK;
+
+ unsigned int i = stlink_dap_handle->queue_index++;
+ struct dap_queue *q = &stlink_dap_handle->queue[i];
+ q->cmd = CMD_DP_READ;
+ q->dp_r.reg = reg;
+ q->dp_r.dap = dap;
+ q->dp_r.p_data = data;
+
+ if (i == MAX_QUEUE_DEPTH - 1)
+ stlink_dap_run_internal(dap);
+
+ return ERROR_OK;
+}
+
+static int stlink_dap_op_queue_dp_write(struct adiv5_dap *dap, unsigned int reg,
+ uint32_t data)
+{
+ if (stlink_dap_get_error() != ERROR_OK)
+ return ERROR_OK;
+
+ unsigned int i = stlink_dap_handle->queue_index++;
+ struct dap_queue *q = &stlink_dap_handle->queue[i];
+ q->cmd = CMD_DP_WRITE;
+ q->dp_w.reg = reg;
+ q->dp_w.dap = dap;
+ q->dp_w.data = data;
+
+ if (i == MAX_QUEUE_DEPTH - 1)
+ stlink_dap_run_internal(dap);
+
+ return ERROR_OK;
+}
+
+static int stlink_dap_op_queue_ap_read(struct adiv5_ap *ap, unsigned int reg,
+ uint32_t *data)
+{
+ if (stlink_dap_get_error() != ERROR_OK)
+ return ERROR_OK;
+
+ unsigned int i = stlink_dap_handle->queue_index++;
+ struct dap_queue *q = &stlink_dap_handle->queue[i];
+
+ if ((stlink_dap_handle->version.flags & STLINK_F_HAS_CSW) &&
+ (reg == MEM_AP_REG_DRW || reg == MEM_AP_REG_BD0 || reg == MEM_AP_REG_BD1 ||
+ reg == MEM_AP_REG_BD2 || reg == MEM_AP_REG_BD3)) {
+ /* de-queue previous write-TAR */
+ struct dap_queue *prev_q = q - 1;
+ if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_TAR) {
+ stlink_dap_handle->queue_index = i;
+ i--;
+ q = prev_q;
+ prev_q--;
+ }
+ /* de-queue previous write-CSW */
+ if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW) {
+ stlink_dap_handle->queue_index = i;
+ q = prev_q;
+ }
+
+ switch (ap->csw_value & CSW_SIZE_MASK) {
+ case CSW_8BIT:
+ q->cmd = CMD_MEM_AP_READ8;
+ break;
+ case CSW_16BIT:
+ q->cmd = CMD_MEM_AP_READ16;
+ break;
+ case CSW_32BIT:
+ q->cmd = CMD_MEM_AP_READ32;
+ break;
+ default:
+ LOG_ERROR("ST-Link: Unsupported CSW size %d", ap->csw_value & CSW_SIZE_MASK);
+ stlink_dap_record_error(ERROR_FAIL);
+ return ERROR_FAIL;
+ }
+
+ q->mem_ap.addr = (reg == MEM_AP_REG_DRW) ? ap->tar_value : ((ap->tar_value & ~0x0f) | (reg & 0x0c));
+ q->mem_ap.ap = ap;
+ q->mem_ap.p_data = data;
+ q->mem_ap.csw = ap->csw_default;
+
+ /* force TAR and CSW update */
+ ap->tar_valid = false;
+ ap->csw_value = 0;
+ } else {
+ q->cmd = CMD_AP_READ;
+ q->ap_r.reg = reg;
+ q->ap_r.ap = ap;
+ q->ap_r.p_data = data;
+ }
+
+ if (i == MAX_QUEUE_DEPTH - 1)
+ stlink_dap_run_internal(ap->dap);
+
+ return ERROR_OK;
+}
+
+static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned int reg,
+ uint32_t data)
+{
+ if (stlink_dap_get_error() != ERROR_OK)
+ return ERROR_OK;
+
+ unsigned int i = stlink_dap_handle->queue_index++;
+ struct dap_queue *q = &stlink_dap_handle->queue[i];
+
+ if ((stlink_dap_handle->version.flags & STLINK_F_HAS_CSW) &&
+ (reg == MEM_AP_REG_DRW || reg == MEM_AP_REG_BD0 || reg == MEM_AP_REG_BD1 ||
+ reg == MEM_AP_REG_BD2 || reg == MEM_AP_REG_BD3)) {
+ /* de-queue previous write-TAR */
+ struct dap_queue *prev_q = q - 1;
+ if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_TAR) {
+ stlink_dap_handle->queue_index = i;
+ i--;
+ q = prev_q;
+ prev_q--;
+ }
+ /* de-queue previous write-CSW */
+ if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW) {
+ stlink_dap_handle->queue_index = i;
+ q = prev_q;
+ }
+
+ switch (ap->csw_value & CSW_SIZE_MASK) {
+ case CSW_8BIT:
+ q->cmd = CMD_MEM_AP_WRITE8;
+ break;
+ case CSW_16BIT:
+ q->cmd = CMD_MEM_AP_WRITE16;
+ break;
+ case CSW_32BIT:
+ q->cmd = CMD_MEM_AP_WRITE32;
+ break;
+ default:
+ LOG_ERROR("ST-Link: Unsupported CSW size %d", ap->csw_value & CSW_SIZE_MASK);
+ stlink_dap_record_error(ERROR_FAIL);
+ return ERROR_FAIL;
+ }
+
+ q->mem_ap.addr = (reg == MEM_AP_REG_DRW) ? ap->tar_value : ((ap->tar_value & ~0x0f) | (reg & 0x0c));
+ q->mem_ap.ap = ap;
+ q->mem_ap.data = data;
+ q->mem_ap.csw = ap->csw_default;
+
+ /* force TAR and CSW update */
+ ap->tar_valid = false;
+ ap->csw_value = 0;
+ } else {
+ q->cmd = CMD_AP_WRITE;
+ q->ap_w.reg = reg;
+ q->ap_w.ap = ap;
+ q->ap_w.data = data;
+ }
+
+ if (i == MAX_QUEUE_DEPTH - 1)
+ stlink_dap_run_internal(ap->dap);
+
+ return ERROR_OK;
+}
+