This is an automated email from Gerrit. "Daniel Goehring <dgoeh...@os.amperecomputing.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7191
-- gerrit commit d8de3ae0a830e88e22adae8adacd59f068d42f6b Author: Daniel Goehring <dgoeh...@os.amperecomputing.com> Date: Fri Sep 10 22:18:16 2021 -0400 target/adiv5: add MEM-AP mdd and mwd support Change-Id: Icb61639711d55b5642f20e2ef14e39e6a9c98937 Signed-off-by: Daniel Goehring <dgoeh...@os.amperecomputing.com> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index cc5f077750..44b30d3aa0 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -336,7 +336,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz { struct adiv5_dap *dap = ap->dap; size_t nbytes = size * count; - const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; + uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; uint32_t csw_size; target_addr_t addr_xor; int retval = ERROR_OK; @@ -354,7 +354,11 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz * setting the TAP, and we set the TAP after every transfer rather then relying on * address increment. */ - if (size == 4) { + if (size == 8) { + csw_size = CSW_64BIT; + addr_xor = 0; + csw_addrincr = CSW_ADDRINC_OFF; + } else if (size == 4) { csw_size = CSW_32BIT; addr_xor = 0; } else if (size == 2) { @@ -374,7 +378,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz uint32_t this_size = size; /* Select packed transfer if possible */ - if (addrinc && ap->packed_transfers && nbytes >= 4 + if ((size <= 4) && addrinc && ap->packed_transfers && nbytes >= 4 && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { this_size = 4; retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED); @@ -392,6 +396,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz /* How many source bytes each transfer will consume, and their location in the DRW, * depends on the type of transfer and alignment. See ARM document IHI0031C. */ uint32_t outvalue = 0; + uint32_t outlow = 0; uint32_t drw_byte_idx = address; if (dap->ti_be_32_quirks) { switch (this_size) { @@ -431,6 +436,12 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz } } else { switch (this_size) { + case 8: + outlow |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); + outlow |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); + outlow |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); + outlow |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); + /* fallthrough */ case 4: outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3); @@ -445,6 +456,11 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz nbytes -= this_size; + if (this_size > 4) { + retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW(dap), outlow); + if (retval != ERROR_OK) + break; + } retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW(dap), outvalue); if (retval != ERROR_OK) break; @@ -486,7 +502,7 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint { struct adiv5_dap *dap = ap->dap; size_t nbytes = size * count; - const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; + uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; uint32_t csw_size; target_addr_t address = adr; int retval = ERROR_OK; @@ -498,7 +514,10 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint * Also, packed 8-bit and 16-bit transfers seem to sometimes return garbage in some bytes, * so avoid them. */ - if (size == 4) + if (size == 8) { + csw_size = CSW_64BIT; + csw_addrincr = CSW_ADDRINC_OFF; + } else if (size == 4) csw_size = CSW_32BIT; else if (size == 2) csw_size = CSW_16BIT; @@ -528,7 +547,7 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint uint32_t this_size = size; /* Select packed transfer if possible */ - if (addrinc && ap->packed_transfers && nbytes >= 4 + if ((size <= 4) && addrinc && ap->packed_transfers && nbytes >= 4 && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { this_size = 4; retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED); @@ -545,6 +564,11 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW(dap), read_ptr++); if (retval != ERROR_OK) break; + if (size > 4) { + retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW(dap), read_ptr++); + if (retval != ERROR_OK) + break; + } nbytes -= this_size; if (addrinc) @@ -599,6 +623,13 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint } } else { switch (this_size) { + case 8: + *buffer++ = *read_ptr >> 8 * (address++ & 3); + *buffer++ = *read_ptr >> 8 * (address++ & 3); + *buffer++ = *read_ptr >> 8 * (address++ & 3); + *buffer++ = *read_ptr >> 8 * (address++ & 3); + read_ptr++; + /* fallthrough */ case 4: *buffer++ = *read_ptr >> 8 * (address++ & 3); *buffer++ = *read_ptr >> 8 * (address++ & 3); diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 3eddbc0e2d..e46a7006a5 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -161,6 +161,7 @@ #define CSW_8BIT 0 #define CSW_16BIT 1 #define CSW_32BIT 2 +#define CSW_64BIT 3 #define CSW_ADDRINC_MASK (3UL << 4) #define CSW_ADDRINC_OFF 0UL #define CSW_ADDRINC_SINGLE (1UL << 4) --