This is an automated email from Gerrit.

"Tomas Vanek <van...@fbl.cz>" just uploaded a new patch set to Gerrit, which 
you can find at https://review.openocd.org/c/openocd/+/7576

-- gerrit

commit 5848e1c12852aec62b130125b8b0468f489e8e92
Author: Tomas Vanek <van...@fbl.cz>
Date:   Sun Apr 2 17:23:46 2023 +0200

    target/adiv5: probe MEM-AP supported transfer sizes including large data
    
    Based on Daniel Goehring's [1] and Peter Collingbourne's [2] work.
    
    Probe for support of 8, 16 bit and if the large data extension is available
    also probe for 64, 128 and 256 bit operations.
    Probe for the ability of packing 8 and 16 bit data
    (formerly probed in mem_ap_init()). The probe is integrated to
    mem_ap_read/write() routines and takes place just before the first memory
    access of the specific size.
    
    Add 64, 128 and 256 bit MEM-AP read/writes.
    
    Introduce specific error codes for unsupported transfer size
    and for unsupported packing.
    
    Change-Id: I180c4ef17d2fc3189e8e2f14bafd22d857f29608
    Link: 7191: target/adiv5: add MEM-AP 64-bit access support | 
https://review.openocd.org/c/openocd/+/7191
    Link: 7436: arm_adi_v5: Support reads wider than 32 bits | 
https://review.openocd.org/c/openocd/+/7436
    Signed-off-by: Tomas Vanek <van...@fbl.cz>

diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index 662d71bceb..34166770e8 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -50,7 +50,8 @@
 /*
  * Relevant specifications from ARM include:
  *
- * ARM(tm) Debug Interface v5 Architecture Specification    ARM IHI 0031E
+ * ARM(tm) Debug Interface v5 Architecture Specification    ARM IHI 0031F
+ * ARM(tm) Debug Interface v6 Architecture Specification    ARM IHI 0074C
  * CoreSight(tm) v1.0 Architecture Specification            ARM IHI 0029B
  *
  * CoreSight(tm) DAP-Lite TRM, ARM DDI 0316D
@@ -164,6 +165,8 @@ static uint32_t mem_ap_get_tar_increment(struct adiv5_ap 
*ap)
                        return 2;
                case CSW_32BIT:
                        return 4;
+               case CSW_64BIT:
+                       return 8;
                default:
                        return 0;
                }
@@ -319,12 +322,144 @@ int mem_ap_write_atomic_u32(struct adiv5_ap *ap, 
target_addr_t address,
        return dap_run(ap->dap);
 }
 
+/**
+ * Queue transactions setting up transfer parameters for the
+ * currently selected MEM-AP. If transfer size or packing
+ * has not been probed, run the queue, read back CSW and check if the requested
+ * transfer mode is supported.
+ *
+ * @param ap The MEM-AP.
+ * @param size Transfer width in bytes. Corresponding CSW.Size will be set.
+ * @param address Transfer address, MEM-AP TAR will be set to this value.
+ * @param addrinc TAR will be autoincremented.
+ * @param pack Try to setup packed transfer.
+ * @param this_size Points to a variable set to the size of single transfer
+ *             or to 4 when transferring packed bytes or halfwords
+ *
+ * @return ERROR_OK if the transaction was properly queued, else a fault code.
+ */
+static int mem_ap_setup_transfer_verify_size_packing(struct adiv5_ap *ap,
+       unsigned int size, target_addr_t address,
+       bool addrinc, bool pack, unsigned int *this_size)
+{
+       int retval;
+       uint32_t csw_size;
+
+       switch (size) {
+       case 1:
+               csw_size = CSW_8BIT;
+               break;
+       case 2:
+               csw_size = CSW_16BIT;
+               break;
+       case 4:
+               csw_size = CSW_32BIT;
+               break;
+       case 8:
+               csw_size = CSW_64BIT;
+               break;
+       case 16:
+               csw_size = CSW_128BIT;
+               break;
+       case 32:
+               csw_size = CSW_256BIT;
+               break;
+       default:
+               LOG_ERROR("Size %u not supported", size);
+               return ERROR_TARGET_SIZE_NOT_SUPPORTED;
+       }
+
+       if (!addrinc || size >= 4
+                       || (ap->packed_transfers_probed && 
!ap->packed_transfers_supported)
+                       || max_tar_block_size(ap->tar_autoincr_block, address) 
< 4)
+               pack = false;
+
+       uint32_t csw_addrinc = pack ? CSW_ADDRINC_PACKED :
+                addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;
+       retval = mem_ap_setup_csw(ap, csw_size | csw_addrinc);
+       if (retval != ERROR_OK)
+               return retval;
+
+       bool do_probe = !(ap->csw_size_probed & size)
+                || (pack && !ap->packed_transfers_probed);
+       if (do_probe) {
+               uint32_t csw_readback;
+               retval = dap_queue_ap_read(ap, MEM_AP_REG_CSW(ap->dap), 
&csw_readback);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = dap_run(ap->dap);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               bool size_supported = ((csw_readback & CSW_SIZE_MASK) == 
csw_size);
+               LOG_DEBUG("AP#0x%" PRIx64 " probed size %u: %s", ap->ap_num, 
size,
+                       size_supported ? "supported" : "not supported");
+               ap->csw_size_probed |= size;
+               if (size_supported) {
+                       ap->csw_size_supported |= size;
+                       if (pack) {
+                               ap->packed_transfers_probed = true;
+                               ap->packed_transfers_supported =
+                                       ((csw_readback & CSW_ADDRINC_MASK) == 
csw_addrinc);
+                               LOG_DEBUG("probed packing: %s",
+                                       ap->packed_transfers_supported ? 
"supported" : "not supported");
+                       }
+               }
+       }
+
+       if (!(ap->csw_size_supported & size)) {
+               LOG_ERROR("Size %u not supported", size);
+               return ERROR_TARGET_SIZE_NOT_SUPPORTED;
+       }
+
+       if (pack && !ap->packed_transfers_supported)
+               return ERROR_TARGET_PACKING_NOT_SUPPORTED;
+
+       *this_size = pack ? 4 : size;
+
+       return mem_ap_setup_tar(ap, address);
+}
+
+/**
+ * Queue transactions setting up transfer parameters for the
+ * currently selected MEM-AP. If transfer size or packing
+ * has not been probed, run the queue, read back CSW and check if the requested
+ * transfer mode is supported.
+ * If packing is not supported fallback and prepare CSW for unpacked transfer.
+ *
+ * @param ap The MEM-AP.
+ * @param size Transfer width in bytes. Corresponding CSW.Size will be set.
+ * @param address Transfer address, MEM-AP TAR will be set to this value.
+ * @param addrinc TAR will be autoincremented.
+ * @param pack Try to setup packed transfer.
+ * @param this_size Points to a variable set to the size of single transfer
+ *             or to 4 when transferring packed bytes or halfwords
+ *
+ * @return ERROR_OK if the transaction was properly queued, else a fault code.
+ */
+static int mem_ap_setup_transfer_verify_size_packing_fallback(struct adiv5_ap 
*ap,
+       unsigned int size, target_addr_t address,
+       bool addrinc, bool pack, unsigned int *this_size)
+{
+       int retval = mem_ap_setup_transfer_verify_size_packing(ap,
+                                       size, address,
+                                       addrinc, pack, this_size);
+       if (retval == ERROR_TARGET_PACKING_NOT_SUPPORTED) {
+               /* Retry without packing */
+               retval = mem_ap_setup_transfer_verify_size_packing(ap,
+                                       size, address,
+                                       addrinc, false, this_size);
+       }
+       return retval;
+}
+
 /**
  * Synchronous write of a block of memory, using a specific access size.
  *
  * @param ap The MEM-AP to access.
  * @param buffer The data buffer to write. No particular alignment is assumed.
- * @param size Which access size to use, in bytes. 1, 2 or 4.
+ * @param size Which access size to use, in bytes. 1, 2, 4 or 8.
  * @param count The number of writes to do (in size units, not bytes).
  * @param address Address to be written; it must be writable by the currently 
selected MEM-AP.
  * @param addrinc Whether the target address should be increased for each 
write or not. This
@@ -336,8 +471,6 @@ 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_size;
        int retval = ERROR_OK;
 
        /* TI BE-32 Quirks mode:
@@ -352,93 +485,85 @@ static int mem_ap_write(struct adiv5_ap *ap, const 
uint8_t *buffer, uint32_t siz
         * To make writes of size < 4 work as expected, we xor a value with the 
address before
         * setting the TAP, and we set the TAP after every transfer rather then 
relying on
         * address increment. */
-
-       target_addr_t ti_be_lane_xor = dap->ti_be_32_quirks ? 3 : 0;
-       target_addr_t ti_be_addr_xor;
-       if (size == 4) {
-               csw_size = CSW_32BIT;
-               ti_be_addr_xor = 0;
-       } else if (size == 2) {
-               csw_size = CSW_16BIT;
-               ti_be_addr_xor = dap->ti_be_32_quirks ? 2 : 0;
-       } else if (size == 1) {
-               csw_size = CSW_8BIT;
-               ti_be_addr_xor = dap->ti_be_32_quirks ? 3 : 0;
-       } else {
-               return ERROR_TARGET_UNALIGNED_ACCESS;
+       target_addr_t ti_be_addr_xor = 0;
+       target_addr_t ti_be_lane_xor = 0;
+       if (dap->ti_be_32_quirks) {
+               ti_be_lane_xor = 3;
+               switch (size) {
+               case 1:
+                       ti_be_addr_xor = 3;
+                       break;
+               case 2:
+                       ti_be_addr_xor = 2;
+                       break;
+               case 4:
+                       break;
+               default:
+                       LOG_ERROR("Write more than 32 bits not supported with 
ti_be_32_quirks");
+                       return ERROR_TARGET_SIZE_NOT_SUPPORTED;
+               }
        }
 
        if (ap->unaligned_access_bad && (address % size != 0))
                return ERROR_TARGET_UNALIGNED_ACCESS;
 
-       while (nbytes > 0) {
-               uint32_t this_size = size;
-
-               /* Select packed transfer if possible */
-               if (addrinc && ap->packed_transfers && nbytes >= 4
-                               && !dap->nu_npcx_quirks
-                               && max_tar_block_size(ap->tar_autoincr_block, 
address) >= 4) {
-                       this_size = 4;
-                       retval = mem_ap_setup_csw(ap, csw_size | 
CSW_ADDRINC_PACKED);
-               } else {
-                       retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr);
-               }
-
-               if (retval != ERROR_OK)
-                       break;
+       /* Nuvoton NPCX quirks prevent packed writes */
+       bool pack = !dap->nu_npcx_quirks;
 
-               retval = mem_ap_setup_tar(ap, address ^ ti_be_addr_xor);
+       while (nbytes > 0) {
+               unsigned int this_size;
+               retval = mem_ap_setup_transfer_verify_size_packing_fallback(ap,
+                                       size, address ^ ti_be_addr_xor,
+                                       addrinc, pack && nbytes >= 4, 
&this_size);
                if (retval != ERROR_OK)
                        return retval;
 
                /* 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 drw_byte_idx = address;
-               if (dap->nu_npcx_quirks && this_size <= 2) {
-                       switch (this_size) {
-                       case 2:
-                               {
-                                       /* Alternate low and high byte to all 
byte lanes */
-                                       uint32_t low = *buffer++;
-                                       uint32_t high = *buffer++;
-                                       outvalue |= low << 8 * (drw_byte_idx++ 
& 3);
-                                       outvalue |= high << 8 * (drw_byte_idx++ 
& 3);
-                                       outvalue |= low << 8 * (drw_byte_idx++ 
& 3);
-                                       outvalue |= high << 8 * (drw_byte_idx & 
3);
-                               }
-                               break;
-                       case 1:
-                               {
-                                       /* Mirror output byte to all byte lanes 
*/
-                                       uint32_t data = *buffer++;
-                                       outvalue |= data;
-                                       outvalue |= data << 8;
-                                       outvalue |= data << 16;
-                                       outvalue |= data << 24;
+               unsigned int drw_ops = DIV_ROUND_UP(this_size, 4);
+
+               while (drw_ops--) {
+                       uint32_t outvalue = 0;
+                       if (dap->nu_npcx_quirks && this_size <= 2) {
+                               switch (this_size) {
+                               case 2:
+                                       {
+                                               /* Alternate low and high byte 
to all byte lanes */
+                                               uint32_t low = *buffer++;
+                                               uint32_t high = *buffer++;
+                                               outvalue |= low << 8 * 
(drw_byte_idx++ & 3);
+                                               outvalue |= high << 8 * 
(drw_byte_idx++ & 3);
+                                               outvalue |= low << 8 * 
(drw_byte_idx++ & 3);
+                                               outvalue |= high << 8 * 
(drw_byte_idx & 3);
+                                       }
+                                       break;
+                               case 1:
+                                       {
+                                               /* Mirror output byte to all 
byte lanes */
+                                               uint32_t data = *buffer++;
+                                               outvalue |= data;
+                                               outvalue |= data << 8;
+                                               outvalue |= data << 16;
+                                               outvalue |= data << 24;
+                                       }
                                }
+                       } else {
+                               unsigned int drw_bytes = MIN(this_size, 4);
+                               while (drw_bytes--)
+                                       outvalue |= (uint32_t)*buffer++ <<
+                                                               8 * 
((drw_byte_idx++ & 3) ^ ti_be_lane_xor);
                        }
-               } else {
-                       switch (this_size) {
-                       case 4:
-                               outvalue |= (uint32_t)*buffer++ << 8 * 
((drw_byte_idx++ & 3) ^ ti_be_lane_xor);
-                               outvalue |= (uint32_t)*buffer++ << 8 * 
((drw_byte_idx++ & 3) ^ ti_be_lane_xor);
-                               /* fallthrough */
-                       case 2:
-                               outvalue |= (uint32_t)*buffer++ << 8 * 
((drw_byte_idx++ & 3) ^ ti_be_lane_xor);
-                               /* fallthrough */
-                       case 1:
-                               outvalue |= (uint32_t)*buffer++ << 8 * 
((drw_byte_idx & 3) ^ ti_be_lane_xor);
-                       }
-               }
-
-               nbytes -= this_size;
 
-               retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW(dap), outvalue);
+                       retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW(dap), 
outvalue);
+                       if (retval != ERROR_OK)
+                               break;
+               }
                if (retval != ERROR_OK)
                        break;
 
                mem_ap_update_tar_cache(ap);
+               nbytes -= this_size;
                if (addrinc)
                        address += this_size;
        }
@@ -463,7 +588,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t 
*buffer, uint32_t siz
  *
  * @param ap The MEM-AP to access.
  * @param buffer The data buffer to receive the data. No particular alignment 
is assumed.
- * @param size Which access size to use, in bytes. 1, 2 or 4.
+ * @param size Which access size to use, in bytes. 1, 2, 4 or 8.
  * @param count The number of reads to do (in size units, not bytes).
  * @param adr Address to be read; it must be readable by the currently 
selected MEM-AP.
  * @param addrinc Whether the target address should be increased after each 
read or not. This
@@ -475,8 +600,6 @@ 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_size;
        target_addr_t address = adr;
        int retval = ERROR_OK;
 
@@ -487,14 +610,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)
-               csw_size = CSW_32BIT;
-       else if (size == 2)
-               csw_size = CSW_16BIT;
-       else if (size == 1)
-               csw_size = CSW_8BIT;
-       else
-               return ERROR_TARGET_UNALIGNED_ACCESS;
+       if (dap->ti_be_32_quirks && size > 4) {
+               LOG_ERROR("Read more than 32 bits not supported with 
ti_be_32_quirks");
+               return ERROR_TARGET_SIZE_NOT_SUPPORTED;
+       }
 
        if (ap->unaligned_access_bad && (adr % size != 0))
                return ERROR_TARGET_UNALIGNED_ACCESS;
@@ -502,7 +621,8 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t 
*buffer, uint32_t size, uint
        /* Allocate buffer to hold the sequence of DRW reads that will be made. 
This is a significant
         * over-allocation if packed transfers are going to be used, but 
determining the real need at
         * this point would be messy. */
-       uint32_t *read_buf = calloc(count, sizeof(uint32_t));
+       uint32_t *read_buf = calloc(count, MAX(sizeof(uint32_t), size));
+
        /* Multiplication count * sizeof(uint32_t) may overflow, calloc() is 
safe */
        uint32_t *read_ptr = read_buf;
        if (!read_buf) {
@@ -514,26 +634,20 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t 
*buffer, uint32_t size, uint
         * useful bytes it contains, and their location in the word, depends on 
the type of transfer
         * and alignment. */
        while (nbytes > 0) {
-               uint32_t this_size = size;
-
-               /* Select packed transfer if possible */
-               if (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);
-               } else {
-                       retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr);
-               }
+               unsigned int this_size;
+               retval = mem_ap_setup_transfer_verify_size_packing_fallback(ap,
+                                       size, address,
+                                       addrinc, nbytes >= 4, &this_size);
                if (retval != ERROR_OK)
                        break;
 
-               retval = mem_ap_setup_tar(ap, address);
-               if (retval != ERROR_OK)
-                       break;
 
-               retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW(dap), read_ptr++);
-               if (retval != ERROR_OK)
-                       break;
+               unsigned int drw_ops = DIV_ROUND_UP(this_size, 4);
+               while (drw_ops--) {
+                       retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW(dap), 
read_ptr++);
+                       if (retval != ERROR_OK)
+                               break;
+               }
 
                nbytes -= this_size;
                if (addrinc)
@@ -552,7 +666,9 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t 
*buffer, uint32_t size, uint
 
        /* If something failed, read TAR to find out how much data was 
successfully read, so we can
         * at least give the caller what we have. */
-       if (retval != ERROR_OK) {
+       if (retval == ERROR_TARGET_SIZE_NOT_SUPPORTED) {
+               nbytes = 0;
+       } else if (retval != ERROR_OK) {
                target_addr_t tar;
                if (mem_ap_read_tar(ap, &tar) == ERROR_OK) {
                        /* TAR is incremented after failed transfer on some 
devices (eg Cortex-M4) */
@@ -567,37 +683,21 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t 
*buffer, uint32_t size, uint
 
        /* Replay loop to populate caller's buffer from the correct word and 
byte lane */
        while (nbytes > 0) {
-               uint32_t this_size = size;
+               /* Convert transfers longer than 32-bit on word-at-a-time basis 
*/
+               unsigned int this_size = MIN(size, 4);
 
-               if (addrinc && ap->packed_transfers && nbytes >= 4
+               if (size < 4 && addrinc && ap->packed_transfers_supported && 
nbytes >= 4
                                && max_tar_block_size(ap->tar_autoincr_block, 
address) >= 4) {
-                       this_size = 4;
+                       this_size = 4;  /* Packed read of 4 bytes or 2 
halfwords */
                }
 
+               unsigned int drw_bytes = this_size;
                if (dap->ti_be_32_quirks) {
-                       switch (this_size) {
-                       case 4:
-                               *buffer++ = *read_ptr >> 8 * (3 - (address++ & 
3));
-                               *buffer++ = *read_ptr >> 8 * (3 - (address++ & 
3));
-                               /* fallthrough */
-                       case 2:
+                       while (drw_bytes--)
                                *buffer++ = *read_ptr >> 8 * (3 - (address++ & 
3));
-                               /* fallthrough */
-                       case 1:
-                               *buffer++ = *read_ptr >> 8 * (3 - (address++ & 
3));
-                       }
                } else {
-                       switch (this_size) {
-                       case 4:
-                               *buffer++ = *read_ptr >> 8 * (address++ & 3);
-                               *buffer++ = *read_ptr >> 8 * (address++ & 3);
-                               /* fallthrough */
-                       case 2:
+                       while (drw_bytes--)
                                *buffer++ = *read_ptr >> 8 * (address++ & 3);
-                               /* fallthrough */
-                       case 1:
-                               *buffer++ = *read_ptr >> 8 * (address++ & 3);
-                       }
                }
 
                read_ptr++;
@@ -776,7 +876,7 @@ int dap_dp_init_or_reconnect(struct adiv5_dap *dap)
 int mem_ap_init(struct adiv5_ap *ap)
 {
        /* check that we support packed transfers */
-       uint32_t csw, cfg;
+       uint32_t cfg;
        int retval;
        struct adiv5_dap *dap = ap->dap;
 
@@ -793,30 +893,23 @@ int mem_ap_init(struct adiv5_ap *ap)
        ap->cfg_reg = cfg;
        ap->tar_valid = false;
        ap->csw_value = 0;      /* force csw and tar write */
-       retval = mem_ap_setup_transfer(ap, CSW_8BIT | CSW_ADDRINC_PACKED, 0);
-       if (retval != ERROR_OK)
-               return retval;
 
-       retval = dap_queue_ap_read(ap, MEM_AP_REG_CSW(dap), &csw);
-       if (retval != ERROR_OK)
-               return retval;
-
-       retval = dap_run(dap);
-       if (retval != ERROR_OK)
-               return retval;
+       /* CSW 32-bit size must be supported (IHI 0031F and 0074D). */
+       ap->csw_size_supported = BIT(CSW_32BIT);
+       ap->csw_size_probed = BIT(CSW_32BIT);
 
-       if (csw & CSW_ADDRINC_PACKED)
-               ap->packed_transfers = true;
-       else
-               ap->packed_transfers = false;
+       /* Suppress probing sizes longer than 32 bit if AP has no large data 
extension */
+       if (!(cfg & MEM_AP_REG_CFG_LD))
+               ap->csw_size_probed |= BIT(CSW_64BIT) | BIT(CSW_128BIT) | 
BIT(CSW_256BIT);
 
-       /* Packed transfers on TI BE-32 processors do not work correctly in
+       /* Both IHI 0031F and 0074D state: Implementations that support 
transfers
+        * smaller than a word must support packed transfers. Unfortunately at 
least
+        * Cortex-M0 and Cortex-M0+ do not comply with this rule.
+        * Probe for packed transfers except we know they are broken.
+        * Packed transfers on TI BE-32 processors do not work correctly in
         * many cases. */
-       if (dap->ti_be_32_quirks)
-               ap->packed_transfers = false;
-
-       LOG_DEBUG("MEM_AP Packed Transfers: %s",
-                       ap->packed_transfers ? "enabled" : "disabled");
+       ap->packed_transfers_supported = false;
+       ap->packed_transfers_probed = dap->ti_be_32_quirks ? true : false;
 
        /* The ARM ADI spec leaves implementation-defined whether unaligned
         * memory accesses work, only work partially, or cause a sticky error.
diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h
index cdcb0d48d2..29c718a355 100644
--- a/src/target/arm_adi_v5.h
+++ b/src/target/arm_adi_v5.h
@@ -165,6 +165,9 @@
 #define CSW_8BIT               0
 #define CSW_16BIT              1
 #define CSW_32BIT              2
+#define CSW_64BIT              3
+#define CSW_128BIT             4
+#define CSW_256BIT             5
 #define CSW_ADDRINC_MASK    (3UL << 4)
 #define CSW_ADDRINC_OFF     0UL
 #define CSW_ADDRINC_SINGLE  (1UL << 4)
@@ -269,6 +272,20 @@ struct adiv5_ap {
         */
        uint32_t csw_value;
 
+       /**
+        * Save the supported CSW.Size data types for the MEM-AP.
+        * Each bit corresponds to a data type.
+        * 0b1 = Supported data type. 0b0 = Not supported.
+        * Bit 0 = Byte (8-bits)
+        * Bit 1 = Halfword (16-bits)
+        * Bit 2 = Word (32-bits) - always supported by spec.
+        * Bit 3 = Doubleword (64-bits)
+        * Bit 4 = 128-bits
+        * Bit 5 = 256-bits
+        */
+       uint32_t csw_size_supported;
+       uint32_t csw_size_probed;
+
        /**
         * Cache for (MEM-AP) AP_REG_TAR register value This is written to
         * configure the address being read or written
@@ -286,7 +303,8 @@ struct adiv5_ap {
        uint32_t tar_autoincr_block;
 
        /* true if packed transfers are supported by the MEM-AP */
-       bool packed_transfers;
+       bool packed_transfers_supported;
+       bool packed_transfers_probed;
 
        /* true if unaligned memory access is not supported by the MEM-AP */
        bool unaligned_access_bad;
diff --git a/src/target/target.h b/src/target/target.h
index ef9ba1062b..7ce3608c99 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -803,6 +803,8 @@ int target_profiling_default(struct target *target, 
uint32_t *samples, uint32_t
 #define ERROR_TARGET_NOT_EXAMINED (-311)
 #define ERROR_TARGET_DUPLICATE_BREAKPOINT (-312)
 #define ERROR_TARGET_ALGO_EXIT  (-313)
+#define ERROR_TARGET_SIZE_NOT_SUPPORTED  (-314)
+#define ERROR_TARGET_PACKING_NOT_SUPPORTED  (-315)
 
 extern bool get_target_reset_nag(void);
 

-- 

Reply via email to