target/arm_adi_v5, cortex_m: retry ahbap_debugport_init few times in case of an error
[openocd.git] / src / target / arm_adi_v5.c
index 2695c463b47c275af89f68ab878e2911a6c730a0..3df39f9edb2908ef27dd6e7415ffdd989b503822 100644 (file)
@@ -10,6 +10,9 @@
  *                                                                         *
  *   Copyright (C) 2009-2010 by David Brownell                             *
  *                                                                         *
+ *   Copyright (C) 2013 by Andreas Fritiofson                              *
+ *   andreas.fritiofson@gmail.com                                          *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
@@ -23,7 +26,7 @@
  *   You should have received a copy of the GNU General Public License     *
  *   along with this program; if not, write to the                         *
  *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
  ***************************************************************************/
 
 /**
 #include "config.h"
 #endif
 
+#include "jtag/interface.h"
 #include "arm.h"
 #include "arm_adi_v5.h"
 #include <helper/time_support.h>
 
-
 /* ARM ADI Specification requires at least 10 bits used for TAR autoincrement  */
 
 /*
@@ -82,7 +85,7 @@
 */
 static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address)
 {
-       return (tar_autoincr_block - ((tar_autoincr_block - 1) & address)) >> 2;
+       return tar_autoincr_block - ((tar_autoincr_block - 1) & address);
 }
 
 /***************************************************************************
@@ -100,13 +103,12 @@ static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address
  * @param apsel Number of the AP to (implicitly) use with further
  *     transactions.  This normally identifies a MEM-AP.
  */
-void dap_ap_select(struct adiv5_dap *dap,uint8_t apsel)
+void dap_ap_select(struct adiv5_dap *dap, uint8_t ap)
 {
-       uint32_t select_apsel = (apsel << 24) & 0xFF000000;
+       uint32_t new_ap = (ap << 24) & 0xFF000000;
 
-       if (select_apsel != dap->apsel)
-       {
-               dap->apsel = select_apsel;
+       if (new_ap != dap->ap_current) {
+               dap->ap_current = new_ap;
                /* Switching AP invalidates cached values.
                 * Values MUST BE UPDATED BEFORE AP ACCESS.
                 */
@@ -116,6 +118,33 @@ void dap_ap_select(struct adiv5_dap *dap,uint8_t apsel)
        }
 }
 
+static int dap_setup_accessport_csw(struct adiv5_dap *dap, uint32_t csw)
+{
+       csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT |
+               dap->apcsw[dap->ap_current >> 24];
+
+       if (csw != dap->ap_csw_value) {
+               /* LOG_DEBUG("DAP: Set CSW %x",csw); */
+               int retval = dap_queue_ap_write(dap, AP_REG_CSW, csw);
+               if (retval != ERROR_OK)
+                       return retval;
+               dap->ap_csw_value = csw;
+       }
+       return ERROR_OK;
+}
+
+static int dap_setup_accessport_tar(struct adiv5_dap *dap, uint32_t tar)
+{
+       if (tar != dap->ap_tar_value || dap->ap_csw_value & CSW_ADDRINC_MASK) {
+               /* LOG_DEBUG("DAP: Set TAR %x",tar); */
+               int retval = dap_queue_ap_write(dap, AP_REG_TAR, tar);
+               if (retval != ERROR_OK)
+                       return retval;
+               dap->ap_tar_value = tar;
+       }
+       return ERROR_OK;
+}
+
 /**
  * Queue transactions setting up transfer parameters for the
  * currently selected MEM-AP.
@@ -138,27 +167,12 @@ void dap_ap_select(struct adiv5_dap *dap,uint8_t apsel)
 int dap_setup_accessport(struct adiv5_dap *dap, uint32_t csw, uint32_t tar)
 {
        int retval;
-
-       csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT;
-       if (csw != dap->ap_csw_value)
-       {
-               /* LOG_DEBUG("DAP: Set CSW %x",csw); */
-               retval = dap_queue_ap_write(dap, AP_REG_CSW, csw);
-               if (retval != ERROR_OK)
-                       return retval;
-               dap->ap_csw_value = csw;
-       }
-       if (tar != dap->ap_tar_value)
-       {
-               /* LOG_DEBUG("DAP: Set TAR %x",tar); */
-               retval = dap_queue_ap_write(dap, AP_REG_TAR, tar);
-               if (retval != ERROR_OK)
-                       return retval;
-               dap->ap_tar_value = tar;
-       }
-       /* Disable TAR cache when autoincrementing */
-       if (csw & CSW_ADDRINC_MASK)
-               dap->ap_tar_value = -1;
+       retval = dap_setup_accessport_csw(dap, csw);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = dap_setup_accessport_tar(dap, tar);
+       if (retval != ERROR_OK)
+               return retval;
        return ERROR_OK;
 }
 
@@ -263,886 +277,1145 @@ int mem_ap_write_atomic_u32(struct adiv5_dap *dap, uint32_t address,
        return dap_run(dap);
 }
 
-/*****************************************************************************
-*                                                                            *
-* mem_ap_write_buf(struct adiv5_dap *dap, uint8_t *buffer, int count, uint32_t address) *
-*                                                                            *
-* Write a buffer in target order (little endian)                             *
-*                                                                            *
-*****************************************************************************/
-int mem_ap_write_buf_u32(struct adiv5_dap *dap, uint8_t *buffer, int count, uint32_t address)
+/**
+ * Synchronous write of a block of memory, using a specific access size.
+ *
+ * @param dap The DAP connected to the MEM-AP.
+ * @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 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
+ *  should normally be true, except when writing to e.g. a FIFO.
+ * @return ERROR_OK on success, otherwise an error code.
+ */
+int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, uint32_t count,
+               uint32_t address, bool addrinc)
 {
-       int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK;
-       uint32_t adr = address;
-       uint8_t* pBuffer = buffer;
+       size_t nbytes = size * count;
+       const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;
+       uint32_t csw_size;
+       uint32_t addr_xor;
+       int retval;
 
-       count >>= 2;
-       wcount = count;
+       /* TI BE-32 Quirks mode:
+        * Writes on big-endian TMS570 behave very strangely. Observed behavior:
+        *   size   write address   bytes written in order
+        *   4      TAR ^ 0         (val >> 24), (val >> 16), (val >> 8), (val)
+        *   2      TAR ^ 2         (val >> 8), (val)
+        *   1      TAR ^ 3         (val)
+        * For example, if you attempt to write a single byte to address 0, the processor
+        * will actually write a byte to address 3.
+        *
+        * 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. */
+
+       if (size == 4) {
+               csw_size = CSW_32BIT;
+               addr_xor = 0;
+       } else if (size == 2) {
+               csw_size = CSW_16BIT;
+               addr_xor = dap->ti_be_32_quirks ? 2 : 0;
+       } else if (size == 1) {
+               csw_size = CSW_8BIT;
+               addr_xor = dap->ti_be_32_quirks ? 3 : 0;
+       } else {
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+       }
 
-       /* if we have an unaligned access - reorder data */
-       if (adr & 0x3u)
-       {
-               for (writecount = 0; writecount < count; writecount++)
-               {
-                       int i;
-                       uint32_t outvalue;
-                       memcpy(&outvalue, pBuffer, sizeof(uint32_t));
-
-                       for (i = 0; i < 4; i++)
-                       {
-                               *((uint8_t*)pBuffer + (adr & 0x3)) = outvalue;
-                               outvalue >>= 8;
-                               adr++;
-                       }
-                       pBuffer += sizeof(uint32_t);
+       if (dap->unaligned_access_bad && (address % size != 0))
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+
+       retval = dap_setup_accessport_tar(dap, address ^ addr_xor);
+       if (retval != ERROR_OK)
+               return retval;
+
+       while (nbytes > 0) {
+               uint32_t this_size = size;
+
+               /* Select packed transfer if possible */
+               if (addrinc && dap->packed_transfers && nbytes >= 4
+                               && max_tar_block_size(dap->tar_autoincr_block, address) >= 4) {
+                       this_size = 4;
+                       retval = dap_setup_accessport_csw(dap, csw_size | CSW_ADDRINC_PACKED);
+               } else {
+                       retval = dap_setup_accessport_csw(dap, csw_size | csw_addrincr);
                }
-       }
 
-       while (wcount > 0)
-       {
-               /* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/
-               blocksize = max_tar_block_size(dap->tar_autoincr_block, address);
-               if (wcount < blocksize)
-                       blocksize = wcount;
+               if (retval != ERROR_OK)
+                       break;
+
+               /* 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;
+               if (dap->ti_be_32_quirks) {
+                       switch (this_size) {
+                       case 4:
+                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
+                               break;
+                       case 2:
+                               outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (address++ & 3) ^ addr_xor);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (address++ & 3) ^ addr_xor);
+                               break;
+                       case 1:
+                               outvalue |= (uint32_t)*buffer++ << 8 * (0 ^ (address++ & 3) ^ addr_xor);
+                               break;
+                       }
+               } else {
+                       switch (this_size) {
+                       case 4:
+                               outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
+                       case 2:
+                               outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
+                       case 1:
+                               outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
+                       }
+               }
 
-               /* handle unaligned data at 4k boundary */
-               if (blocksize == 0)
-                       blocksize = 1;
+               nbytes -= this_size;
 
-               retval = dap_setup_accessport(dap, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+               retval = dap_queue_ap_write(dap, AP_REG_DRW, outvalue);
                if (retval != ERROR_OK)
-                       return retval;
+                       break;
 
-               for (writecount = 0; writecount < blocksize; writecount++)
-               {
-                       retval = dap_queue_ap_write(dap, AP_REG_DRW,
-                               *(uint32_t *) ((void *) (buffer + 4 * writecount)));
+               /* Rewrite TAR if it wrapped or we're xoring addresses */
+               if (addrinc && (addr_xor || (address % dap->tar_autoincr_block < size && nbytes > 0))) {
+                       retval = dap_setup_accessport_tar(dap, address ^ addr_xor);
                        if (retval != ERROR_OK)
                                break;
                }
+       }
 
-               if ((retval = dap_run(dap)) == ERROR_OK)
-               {
-                       wcount = wcount - blocksize;
-                       address = address + 4 * blocksize;
-                       buffer = buffer + 4 * blocksize;
-               }
-               else
-               {
-                       errorcount++;
-               }
+       /* REVISIT: Might want to have a queued version of this function that does not run. */
+       if (retval == ERROR_OK)
+               retval = dap_run(dap);
 
-               if (errorcount > 1)
-               {
-                       LOG_WARNING("Block write error address 0x%" PRIx32 ", wcount 0x%x", address, wcount);
-                       return retval;
-               }
+       if (retval != ERROR_OK) {
+               uint32_t tar;
+               if (dap_queue_ap_read(dap, AP_REG_TAR, &tar) == ERROR_OK
+                               && dap_run(dap) == ERROR_OK)
+                       LOG_ERROR("Failed to write memory at 0x%08"PRIx32, tar);
+               else
+                       LOG_ERROR("Failed to write memory and, additionally, failed to find out where");
        }
 
        return retval;
 }
 
-static int mem_ap_write_buf_packed_u16(struct adiv5_dap *dap,
-               uint8_t *buffer, int count, uint32_t address)
+/**
+ * Synchronous read of a block of memory, using a specific access size.
+ *
+ * @param dap The DAP connected to the MEM-AP.
+ * @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 count The number of reads to do (in size units, not bytes).
+ * @param address 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
+ *  should normally be true, except when reading from e.g. a FIFO.
+ * @return ERROR_OK on success, otherwise an error code.
+ */
+int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t count,
+               uint32_t adr, bool addrinc)
 {
-       int retval = ERROR_OK;
-       int wcount, blocksize, writecount, i;
+       size_t nbytes = size * count;
+       const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;
+       uint32_t csw_size;
+       uint32_t address = adr;
+       int retval;
 
-       wcount = count >> 1;
+       /* TI BE-32 Quirks mode:
+        * Reads on big-endian TMS570 behave strangely differently than writes.
+        * They read from the physical address requested, but with DRW byte-reversed.
+        * For example, a byte read from address 0 will place the result in the high bytes of DRW.
+        * 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->unaligned_access_bad && (adr % size != 0))
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+
+       /* 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 = malloc(count * sizeof(uint32_t));
+       uint32_t *read_ptr = read_buf;
+       if (read_buf == NULL) {
+               LOG_ERROR("Failed to allocate read buffer");
+               return ERROR_FAIL;
+       }
 
-       while (wcount > 0)
-       {
-               int nbytes;
+       retval = dap_setup_accessport_tar(dap, address);
+       if (retval != ERROR_OK) {
+               free(read_buf);
+               return retval;
+       }
 
-               /* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/
-               blocksize = max_tar_block_size(dap->tar_autoincr_block, address);
+       /* Queue up all reads. Each read will store the entire DRW word in the read buffer. How many
+        * 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 && dap->packed_transfers && nbytes >= 4
+                               && max_tar_block_size(dap->tar_autoincr_block, address) >= 4) {
+                       this_size = 4;
+                       retval = dap_setup_accessport_csw(dap, csw_size | CSW_ADDRINC_PACKED);
+               } else {
+                       retval = dap_setup_accessport_csw(dap, csw_size | csw_addrincr);
+               }
+               if (retval != ERROR_OK)
+                       break;
 
-               if (wcount < blocksize)
-                       blocksize = wcount;
+               retval = dap_queue_ap_read(dap, AP_REG_DRW, read_ptr++);
+               if (retval != ERROR_OK)
+                       break;
 
-               /* handle unaligned data at 4k boundary */
-               if (blocksize == 0)
-                       blocksize = 1;
+               nbytes -= this_size;
+               address += this_size;
 
-               retval = dap_setup_accessport(dap, CSW_16BIT | CSW_ADDRINC_PACKED, address);
-               if (retval != ERROR_OK)
-                       return retval;
-               writecount = blocksize;
+               /* Rewrite TAR if it wrapped */
+               if (addrinc && address % dap->tar_autoincr_block < size && nbytes > 0) {
+                       retval = dap_setup_accessport_tar(dap, address);
+                       if (retval != ERROR_OK)
+                               break;
+               }
+       }
 
-               do
-               {
-                       nbytes = MIN((writecount << 1), 4);
+       if (retval == ERROR_OK)
+               retval = dap_run(dap);
 
-                       if (nbytes < 4)
-                       {
-                               retval = mem_ap_write_buf_u16(dap, buffer,
-                                               nbytes, address);
-                               if (retval != ERROR_OK)
-                               {
-                                       LOG_WARNING("Block write error address "
-                                               "0x%" PRIx32 ", count 0x%x",
-                                               address, count);
-                                       return retval;
-                               }
+       /* Restore state */
+       address = adr;
+       nbytes = size * count;
+       read_ptr = read_buf;
+
+       /* 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) {
+               uint32_t tar;
+               if (dap_queue_ap_read(dap, AP_REG_TAR, &tar) == ERROR_OK
+                               && dap_run(dap) == ERROR_OK) {
+                       LOG_ERROR("Failed to read memory at 0x%08"PRIx32, tar);
+                       if (nbytes > tar - address)
+                               nbytes = tar - address;
+               } else {
+                       LOG_ERROR("Failed to read memory and, additionally, failed to find out where");
+                       nbytes = 0;
+               }
+       }
 
-                               address += nbytes >> 1;
-                       }
-                       else
-                       {
-                               uint32_t outvalue;
-                               memcpy(&outvalue, buffer, sizeof(uint32_t));
-
-                               for (i = 0; i < nbytes; i++)
-                               {
-                                       *((uint8_t*)buffer + (address & 0x3)) = outvalue;
-                                       outvalue >>= 8;
-                                       address++;
-                               }
+       /* Replay loop to populate caller's buffer from the correct word and byte lane */
+       while (nbytes > 0) {
+               uint32_t this_size = size;
 
-                               memcpy(&outvalue, buffer, sizeof(uint32_t));
-                               retval = dap_queue_ap_write(dap,
-                                               AP_REG_DRW, outvalue);
-                               if (retval != ERROR_OK)
-                                       break;
+               if (addrinc && dap->packed_transfers && nbytes >= 4
+                               && max_tar_block_size(dap->tar_autoincr_block, address) >= 4) {
+                       this_size = 4;
+               }
 
-                               if ((retval = dap_run(dap)) != ERROR_OK)
-                               {
-                                       LOG_WARNING("Block write error address "
-                                               "0x%" PRIx32 ", count 0x%x",
-                                               address, count);
-                                       return retval;
-                               }
+               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));
+                       case 2:
+                               *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));
+                       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);
+                       case 2:
+                               *buffer++ = *read_ptr >> 8 * (address++ & 3);
+                       case 1:
+                               *buffer++ = *read_ptr >> 8 * (address++ & 3);
+                       }
+               }
 
-                       buffer += nbytes >> 1;
-                       writecount -= nbytes >> 1;
-
-               } while (writecount);
-               wcount -= blocksize;
+               read_ptr++;
+               nbytes -= this_size;
        }
 
+       free(read_buf);
        return retval;
 }
 
-int mem_ap_write_buf_u16(struct adiv5_dap *dap, uint8_t *buffer, int count, uint32_t address)
+/*--------------------------------------------------------------------*/
+/*          Wrapping function with selection of AP                    */
+/*--------------------------------------------------------------------*/
+int mem_ap_sel_read_u32(struct adiv5_dap *swjdp, uint8_t ap,
+               uint32_t address, uint32_t *value)
 {
-       int retval = ERROR_OK;
-
-       if (count >= 4)
-               return mem_ap_write_buf_packed_u16(dap, buffer, count, address);
-
-       while (count > 0)
-       {
-               retval = dap_setup_accessport(dap, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
-               if (retval != ERROR_OK)
-                       return retval;
-               uint16_t svalue;
-               memcpy(&svalue, buffer, sizeof(uint16_t));
-               uint32_t outvalue = (uint32_t)svalue << 8 * (address & 0x3);
-               retval = dap_queue_ap_write(dap, AP_REG_DRW, outvalue);
-               if (retval != ERROR_OK)
-                       break;
-
-               retval = dap_run(dap);
-               if (retval != ERROR_OK)
-                       break;
+       dap_ap_select(swjdp, ap);
+       return mem_ap_read_u32(swjdp, address, value);
+}
 
-               count -= 2;
-               address += 2;
-               buffer += 2;
-       }
+int mem_ap_sel_write_u32(struct adiv5_dap *swjdp, uint8_t ap,
+               uint32_t address, uint32_t value)
+{
+       dap_ap_select(swjdp, ap);
+       return mem_ap_write_u32(swjdp, address, value);
+}
 
-       return retval;
+int mem_ap_sel_read_atomic_u32(struct adiv5_dap *swjdp, uint8_t ap,
+               uint32_t address, uint32_t *value)
+{
+       dap_ap_select(swjdp, ap);
+       return mem_ap_read_atomic_u32(swjdp, address, value);
 }
 
-static int mem_ap_write_buf_packed_u8(struct adiv5_dap *dap,
-               uint8_t *buffer, int count, uint32_t address)
+int mem_ap_sel_write_atomic_u32(struct adiv5_dap *swjdp, uint8_t ap,
+               uint32_t address, uint32_t value)
 {
-       int retval = ERROR_OK;
-       int wcount, blocksize, writecount, i;
+       dap_ap_select(swjdp, ap);
+       return mem_ap_write_atomic_u32(swjdp, address, value);
+}
 
-       wcount = count;
+int mem_ap_sel_read_buf(struct adiv5_dap *swjdp, uint8_t ap,
+               uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address)
+{
+       dap_ap_select(swjdp, ap);
+       return mem_ap_read(swjdp, buffer, size, count, address, true);
+}
 
-       while (wcount > 0)
-       {
-               int nbytes;
+int mem_ap_sel_write_buf(struct adiv5_dap *swjdp, uint8_t ap,
+               const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address)
+{
+       dap_ap_select(swjdp, ap);
+       return mem_ap_write(swjdp, buffer, size, count, address, true);
+}
 
-               /* Adjust to write blocks within boundaries aligned to the TAR autoincremnent size*/
-               blocksize = max_tar_block_size(dap->tar_autoincr_block, address);
+int mem_ap_sel_read_buf_noincr(struct adiv5_dap *swjdp, uint8_t ap,
+               uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address)
+{
+       dap_ap_select(swjdp, ap);
+       return mem_ap_read(swjdp, buffer, size, count, address, false);
+}
 
-               if (wcount < blocksize)
-                       blocksize = wcount;
+int mem_ap_sel_write_buf_noincr(struct adiv5_dap *swjdp, uint8_t ap,
+               const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address)
+{
+       dap_ap_select(swjdp, ap);
+       return mem_ap_write(swjdp, buffer, size, count, address, false);
+}
 
-               retval = dap_setup_accessport(dap, CSW_8BIT | CSW_ADDRINC_PACKED, address);
-               if (retval != ERROR_OK)
-                       return retval;
-               writecount = blocksize;
+/*--------------------------------------------------------------------------*/
 
-               do
-               {
-                       nbytes = MIN(writecount, 4);
 
-                       if (nbytes < 4)
-                       {
-                               retval = mem_ap_write_buf_u8(dap, buffer, nbytes, address);
-                               if (retval != ERROR_OK)
-                               {
-                                       LOG_WARNING("Block write error address "
-                                               "0x%" PRIx32 ", count 0x%x",
-                                               address, count);
-                                       return retval;
-                               }
+#define DAP_POWER_DOMAIN_TIMEOUT (10)
 
-                               address += nbytes;
-                       }
-                       else
-                       {
-                               uint32_t outvalue;
-                               memcpy(&outvalue, buffer, sizeof(uint32_t));
-
-                               for (i = 0; i < nbytes; i++)
-                               {
-                                       *((uint8_t*)buffer + (address & 0x3)) = outvalue;
-                                       outvalue >>= 8;
-                                       address++;
-                               }
+/* FIXME don't import ... just initialize as
+ * part of DAP transport setup
+*/
+extern const struct dap_ops jtag_dp_ops;
 
-                               memcpy(&outvalue, buffer, sizeof(uint32_t));
-                               retval = dap_queue_ap_write(dap,
-                                               AP_REG_DRW, outvalue);
-                               if (retval != ERROR_OK)
-                                       break;
+/*--------------------------------------------------------------------------*/
 
-                               if ((retval = dap_run(dap)) != ERROR_OK)
-                               {
-                                       LOG_WARNING("Block write error address "
-                                               "0x%" PRIx32 ", count 0x%x",
-                                               address, count);
-                                       return retval;
-                               }
-                       }
+/**
+ * Initialize a DAP.  This sets up the power domains, prepares the DP
+ * for further use, and arranges to use AP #0 for all AP operations
+ * until dap_ap-select() changes that policy.
+ *
+ * @param dap The DAP being initialized.
+ *
+ * @todo Rename this.  We also need an initialization scheme which account
+ * for SWD transports not just JTAG; that will need to address differences
+ * in layering.  (JTAG is useful without any debug target; but not SWD.)
+ * And this may not even use an AHB-AP ... e.g. DAP-Lite uses an APB-AP.
+ */
+int ahbap_debugport_init(struct adiv5_dap *dap)
+{
+       /* check that we support packed transfers */
+       uint32_t csw, cfg;
+       int retval;
 
-                       buffer += nbytes;
-                       writecount -= nbytes;
+       LOG_DEBUG(" ");
 
-               } while (writecount);
-               wcount -= blocksize;
-       }
+       /* JTAG-DP or SWJ-DP, in JTAG mode
+        * ... for SWD mode this is patched as part
+        * of link switchover
+        */
+       if (!dap->ops)
+               dap->ops = &jtag_dp_ops;
 
-       return retval;
-}
+       /* Default MEM-AP setup.
+        *
+        * REVISIT AP #0 may be an inappropriate default for this.
+        * Should we probe, or take a hint from the caller?
+        * Presumably we can ignore the possibility of multiple APs.
+        */
+       dap->ap_current = !0;
+       dap_ap_select(dap, 0);
+       dap->last_read = NULL;
 
-int mem_ap_write_buf_u8(struct adiv5_dap *dap, uint8_t *buffer, int count, uint32_t address)
-{
-       int retval = ERROR_OK;
+       for (size_t i = 0; i < 10; i++) {
+               /* DP initialization */
 
-       if (count >= 4)
-               return mem_ap_write_buf_packed_u8(dap, buffer, count, address);
+               dap->dp_bank_value = 0;
 
-       while (count > 0)
-       {
-               retval = dap_setup_accessport(dap, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
-               if (retval != ERROR_OK)
-                       return retval;
-               uint32_t outvalue = (uint32_t)*buffer << 8 * (address & 0x3);
-               retval = dap_queue_ap_write(dap, AP_REG_DRW, outvalue);
+               retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
                if (retval != ERROR_OK)
-                       break;
+                       continue;
 
-               retval = dap_run(dap);
+               retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR);
                if (retval != ERROR_OK)
-                       break;
-
-               count--;
-               address++;
-               buffer++;
-       }
-
-       return retval;
-}
-
-/* FIXME don't import ... this is a temporary workaround for the
- * mem_ap_read_buf_u32() mess, until it's no longer JTAG-specific.
- */
-extern int adi_jtag_dp_scan(struct adiv5_dap *dap,
-               uint8_t instr, uint8_t reg_addr, uint8_t RnW,
-               uint8_t *outvalue, uint8_t *invalue, uint8_t *ack);
+                       continue;
 
-/**
- * Synchronously read a block of 32-bit words into a buffer
- * @param dap The DAP connected to the MEM-AP.
- * @param buffer where the words will be stored (in host byte order).
- * @param count How many words to read.
- * @param address Memory address from which to read words; all the
- *     words must be readable by the currently selected MEM-AP.
- */
-int mem_ap_read_buf_u32(struct adiv5_dap *dap, uint8_t *buffer,
-               int count, uint32_t address)
-{
-       int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;
-       uint32_t adr = address;
-       uint8_t* pBuffer = buffer;
+               retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
+               if (retval != ERROR_OK)
+                       continue;
 
-       count >>= 2;
-       wcount = count;
+               dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ;
+               retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat);
+               if (retval != ERROR_OK)
+                       continue;
 
-       while (wcount > 0)
-       {
-               /* Adjust to read blocks within boundaries aligned to the
-                * TAR autoincrement size (at least 2^10).  Autoincrement
-                * mode avoids an extra per-word roundtrip to update TAR.
-                */
-               blocksize = max_tar_block_size(dap->tar_autoincr_block,
-                               address);
-               if (wcount < blocksize)
-                       blocksize = wcount;
+               /* Check that we have debug power domains activated */
+               LOG_DEBUG("DAP: wait CDBGPWRUPACK");
+               retval = dap_dp_poll_register(dap, DP_CTRL_STAT,
+                                             CDBGPWRUPACK, CDBGPWRUPACK,
+                                             DAP_POWER_DOMAIN_TIMEOUT);
+               if (retval != ERROR_OK)
+                       continue;
 
-               /* handle unaligned data at 4k boundary */
-               if (blocksize == 0)
-                       blocksize = 1;
+               LOG_DEBUG("DAP: wait CSYSPWRUPACK");
+               retval = dap_dp_poll_register(dap, DP_CTRL_STAT,
+                                             CSYSPWRUPACK, CSYSPWRUPACK,
+                                             DAP_POWER_DOMAIN_TIMEOUT);
+               if (retval != ERROR_OK)
+                       continue;
 
-               retval = dap_setup_accessport(dap, CSW_32BIT | CSW_ADDRINC_SINGLE,
-                               address);
+               retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
                if (retval != ERROR_OK)
-                       return retval;
+                       continue;
+               /* With debug power on we can activate OVERRUN checking */
+               dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT;
+               retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat);
+               if (retval != ERROR_OK)
+                       continue;
+               retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
+               if (retval != ERROR_OK)
+                       continue;
 
-               /* FIXME remove these three calls to adi_jtag_dp_scan(),
-                * so this routine becomes transport-neutral.  Be careful
-                * not to cause performance problems with JTAG; would it
-                * suffice to loop over dap_queue_ap_read(), or would that
-                * be slower when JTAG is the chosen transport?
-                */
+               retval = dap_setup_accessport(dap, CSW_8BIT | CSW_ADDRINC_PACKED, 0);
+               if (retval != ERROR_OK)
+                       continue;
 
-               /* Scan out first read */
-               retval = adi_jtag_dp_scan(dap, JTAG_DP_APACC, AP_REG_DRW,
-                               DPAP_READ, 0, NULL, NULL);
+               retval = dap_queue_ap_read(dap, AP_REG_CSW, &csw);
                if (retval != ERROR_OK)
-                       return retval;
-               for (readcount = 0; readcount < blocksize - 1; readcount++)
-               {
-                       /* Scan out next read; scan in posted value for the
-                        * previous one.  Assumes read is acked "OK/FAULT",
-                        * and CTRL_STAT says that meant "OK".
-                        */
-                       retval = adi_jtag_dp_scan(dap, JTAG_DP_APACC, AP_REG_DRW,
-                                       DPAP_READ, 0, buffer + 4 * readcount,
-                                       &dap->ack);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
+                       continue;
 
-               /* Scan in last posted value; RDBUFF has no other effect,
-                * assuming ack is OK/FAULT and CTRL_STAT says "OK".
-                */
-               retval = adi_jtag_dp_scan(dap, JTAG_DP_DPACC, DP_RDBUFF,
-                               DPAP_READ, 0, buffer + 4 * readcount,
-                               &dap->ack);
+               retval = dap_queue_ap_read(dap, AP_REG_CFG, &cfg);
                if (retval != ERROR_OK)
-                       return retval;
+                       continue;
 
                retval = dap_run(dap);
                if (retval != ERROR_OK)
-               {
-                       errorcount++;
-                       if (errorcount <= 1)
-                       {
-                               /* try again */
-                               continue;
-                       }
-                       LOG_WARNING("Block read error address 0x%" PRIx32, address);
-                       return retval;
-               }
-               wcount = wcount - blocksize;
-               address += 4 * blocksize;
-               buffer += 4 * blocksize;
-       }
+                       continue;
 
-       /* if we have an unaligned access - reorder data */
-       if (adr & 0x3u)
-       {
-               for (readcount = 0; readcount < count; readcount++)
-               {
-                       int i;
-                       uint32_t data;
-                       memcpy(&data, pBuffer, sizeof(uint32_t));
-
-                       for (i = 0; i < 4; i++)
-                       {
-                               *((uint8_t*)pBuffer) =
-                                               (data >> 8 * (adr & 0x3));
-                               pBuffer++;
-                               adr++;
-                       }
-               }
+               break;
        }
 
-       return retval;
-}
+       if (retval != ERROR_OK)
+               return retval;
 
-static int mem_ap_read_buf_packed_u16(struct adiv5_dap *dap,
-               uint8_t *buffer, int count, uint32_t address)
-{
-       uint32_t invalue;
-       int retval = ERROR_OK;
-       int wcount, blocksize, readcount, i;
+       if (csw & CSW_ADDRINC_PACKED)
+               dap->packed_transfers = true;
+       else
+               dap->packed_transfers = false;
 
-       wcount = count >> 1;
+       /* Packed transfers on TI BE-32 processors do not work correctly in
+        * many cases. */
+       if (dap->ti_be_32_quirks)
+               dap->packed_transfers = false;
 
-       while (wcount > 0)
-       {
-               int nbytes;
+       LOG_DEBUG("MEM_AP Packed Transfers: %s",
+                       dap->packed_transfers ? "enabled" : "disabled");
 
-               /* Adjust to read blocks within boundaries aligned to the TAR autoincremnent size*/
-               blocksize = max_tar_block_size(dap->tar_autoincr_block, address);
-               if (wcount < blocksize)
-                       blocksize = wcount;
+       /* The ARM ADI spec leaves implementation-defined whether unaligned
+        * memory accesses work, only work partially, or cause a sticky error.
+        * On TI BE-32 processors, reads seem to return garbage in some bytes
+        * and unaligned writes seem to cause a sticky error.
+        * TODO: it would be nice to have a way to detect whether unaligned
+        * operations are supported on other processors. */
+       dap->unaligned_access_bad = dap->ti_be_32_quirks;
 
-               retval = dap_setup_accessport(dap, CSW_16BIT | CSW_ADDRINC_PACKED, address);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               /* handle unaligned data at 4k boundary */
-               if (blocksize == 0)
-                       blocksize = 1;
-               readcount = blocksize;
-
-               do
-               {
-                       retval = dap_queue_ap_read(dap, AP_REG_DRW, &invalue);
-                       if (retval != ERROR_OK)
-                               return retval;
-                       if ((retval = dap_run(dap)) != ERROR_OK)
-                       {
-                               LOG_WARNING("Block read error address 0x%" PRIx32 ", count 0x%x", address, count);
-                               return retval;
-                       }
-
-                       nbytes = MIN((readcount << 1), 4);
+       LOG_DEBUG("MEM_AP CFG: large data %d, long address %d, big-endian %d",
+                       !!(cfg & 0x04), !!(cfg & 0x02), !!(cfg & 0x01));
 
-                       for (i = 0; i < nbytes; i++)
-                       {
-                               *((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3));
-                               buffer++;
-                               address++;
-                       }
+       return ERROR_OK;
+}
 
-                       readcount -= (nbytes >> 1);
-               } while (readcount);
-               wcount -= blocksize;
-       }
+/* CID interpretation -- see ARM IHI 0029B section 3
+ * and ARM IHI 0031A table 13-3.
+ */
+static const char *class_description[16] = {
+       "Reserved", "ROM table", "Reserved", "Reserved",
+       "Reserved", "Reserved", "Reserved", "Reserved",
+       "Reserved", "CoreSight component", "Reserved", "Peripheral Test Block",
+       "Reserved", "OptimoDE DESS",
+       "Generic IP component", "PrimeCell or System component"
+};
 
-       return retval;
+static bool is_dap_cid_ok(uint32_t cid3, uint32_t cid2, uint32_t cid1, uint32_t cid0)
+{
+       return cid3 == 0xb1 && cid2 == 0x05
+                       && ((cid1 & 0x0f) == 0) && cid0 == 0x0d;
 }
 
-/**
- * Synchronously read a block of 16-bit halfwords into a buffer
- * @param dap The DAP connected to the MEM-AP.
- * @param buffer where the halfwords will be stored (in host byte order).
- * @param count How many halfwords to read.
- * @param address Memory address from which to read words; all the
- *     words must be readable by the currently selected MEM-AP.
+/*
+ * This function checks the ID for each access port to find the requested Access Port type
  */
-int mem_ap_read_buf_u16(struct adiv5_dap *dap, uint8_t *buffer,
-               int count, uint32_t address)
+int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, uint8_t *ap_num_out)
 {
-       uint32_t invalue, i;
-       int retval = ERROR_OK;
+       int ap;
 
-       if (count >= 4)
-               return mem_ap_read_buf_packed_u16(dap, buffer, count, address);
+       /* Maximum AP number is 255 since the SELECT register is 8 bits */
+       for (ap = 0; ap <= 255; ap++) {
 
-       while (count > 0)
-       {
-               retval = dap_setup_accessport(dap, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
+               /* read the IDR register of the Access Port */
+               uint32_t id_val = 0;
+               dap_ap_select(dap, ap);
+
+               int retval = dap_queue_ap_read(dap, AP_REG_IDR, &id_val);
                if (retval != ERROR_OK)
                        return retval;
-               retval = dap_queue_ap_read(dap, AP_REG_DRW, &invalue);
-               if (retval != ERROR_OK)
-                       break;
 
                retval = dap_run(dap);
-               if (retval != ERROR_OK)
-                       break;
 
-               if (address & 0x1)
-               {
-                       for (i = 0; i < 2; i++)
-                       {
-                               *((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3));
-                               buffer++;
-                               address++;
-                       }
-               }
-               else
-               {
-                       uint16_t svalue = (invalue >> 8 * (address & 0x3));
-                       memcpy(buffer, &svalue, sizeof(uint16_t));
-                       address += 2;
-                       buffer += 2;
+               /* IDR bits:
+                * 31-28 : Revision
+                * 27-24 : JEDEC bank (0x4 for ARM)
+                * 23-17 : JEDEC code (0x3B for ARM)
+                * 16    : Mem-AP
+                * 15-8  : Reserved
+                *  7-0  : AP Identity (1=AHB-AP 2=APB-AP 0x10=JTAG-AP)
+                */
+
+               /* Reading register for a non-existant AP should not cause an error,
+                * but just to be sure, try to continue searching if an error does happen.
+                */
+               if ((retval == ERROR_OK) &&                  /* Register read success */
+                       ((id_val & 0x0FFF0000) == 0x04770000) && /* Jedec codes match */
+                       ((id_val & 0xFF) == type_to_find)) {     /* type matches*/
+
+                       LOG_DEBUG("Found %s at AP index: %d (IDR=0x%08" PRIX32 ")",
+                                               (type_to_find == AP_TYPE_AHB_AP)  ? "AHB-AP"  :
+                                               (type_to_find == AP_TYPE_APB_AP)  ? "APB-AP"  :
+                                               (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown",
+                                               ap, id_val);
+
+                       *ap_num_out = ap;
+                       return ERROR_OK;
                }
-               count -= 2;
        }
 
-       return retval;
+       LOG_DEBUG("No %s found",
+                               (type_to_find == AP_TYPE_AHB_AP)  ? "AHB-AP"  :
+                               (type_to_find == AP_TYPE_APB_AP)  ? "APB-AP"  :
+                               (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown");
+       return ERROR_FAIL;
 }
 
-/* FIX!!! is this a potential performance bottleneck w.r.t. requiring too many
- * roundtrips when jtag_execute_queue() has a large overhead(e.g. for USB)s?
- *
- * The solution is to arrange for a large out/in scan in this loop and
- * and convert data afterwards.
- */
-static int mem_ap_read_buf_packed_u8(struct adiv5_dap *dap,
-               uint8_t *buffer, int count, uint32_t address)
+int dap_get_debugbase(struct adiv5_dap *dap, int ap,
+                       uint32_t *dbgbase, uint32_t *apid)
 {
-       uint32_t invalue;
-       int retval = ERROR_OK;
-       int wcount, blocksize, readcount, i;
-
-       wcount = count;
-
-       while (wcount > 0)
-       {
-               int nbytes;
-
-               /* Adjust to read blocks within boundaries aligned to the TAR autoincremnent size*/
-               blocksize = max_tar_block_size(dap->tar_autoincr_block, address);
-
-               if (wcount < blocksize)
-                       blocksize = wcount;
-
-               retval = dap_setup_accessport(dap, CSW_8BIT | CSW_ADDRINC_PACKED, address);
-               if (retval != ERROR_OK)
-                       return retval;
-               readcount = blocksize;
+       uint32_t ap_old;
+       int retval;
 
-               do
-               {
-                       retval = dap_queue_ap_read(dap, AP_REG_DRW, &invalue);
-                       if (retval != ERROR_OK)
-                               return retval;
-                       if ((retval = dap_run(dap)) != ERROR_OK)
-                       {
-                               LOG_WARNING("Block read error address 0x%" PRIx32 ", count 0x%x", address, count);
-                               return retval;
-                       }
+       /* AP address is in bits 31:24 of DP_SELECT */
+       if (ap >= 256)
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
-                       nbytes = MIN(readcount, 4);
+       ap_old = dap->ap_current;
+       dap_ap_select(dap, ap);
 
-                       for (i = 0; i < nbytes; i++)
-                       {
-                               *((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3));
-                               buffer++;
-                               address++;
-                       }
+       retval = dap_queue_ap_read(dap, AP_REG_BASE, dbgbase);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = dap_queue_ap_read(dap, AP_REG_IDR, apid);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = dap_run(dap);
+       if (retval != ERROR_OK)
+               return retval;
 
-                       readcount -= nbytes;
-               } while (readcount);
-               wcount -= blocksize;
-       }
+       dap_ap_select(dap, ap_old);
 
-       return retval;
+       return ERROR_OK;
 }
 
-/**
- * Synchronously read a block of bytes into a buffer
- * @param dap The DAP connected to the MEM-AP.
- * @param buffer where the bytes will be stored.
- * @param count How many bytes to read.
- * @param address Memory address from which to read data; all the
- *     data must be readable by the currently selected MEM-AP.
- */
-int mem_ap_read_buf_u8(struct adiv5_dap *dap, uint8_t *buffer,
-               int count, uint32_t address)
+int dap_lookup_cs_component(struct adiv5_dap *dap, int ap,
+                       uint32_t dbgbase, uint8_t type, uint32_t *addr, int32_t *idx)
 {
-       uint32_t invalue;
-       int retval = ERROR_OK;
+       uint32_t ap_old;
+       uint32_t romentry, entry_offset = 0, component_base, devtype;
+       int retval;
 
-       if (count >= 4)
-               return mem_ap_read_buf_packed_u8(dap, buffer, count, address);
+       if (ap >= 256)
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
-       while (count > 0)
-       {
-               retval = dap_setup_accessport(dap, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = dap_queue_ap_read(dap, AP_REG_DRW, &invalue);
+       *addr = 0;
+       ap_old = dap->ap_current;
+       dap_ap_select(dap, ap);
+
+       do {
+               retval = mem_ap_read_atomic_u32(dap, (dbgbase&0xFFFFF000) |
+                                               entry_offset, &romentry);
                if (retval != ERROR_OK)
                        return retval;
-               retval = dap_run(dap);
-               if (retval != ERROR_OK)
-                       break;
 
-               *((uint8_t*)buffer) = (invalue >> 8 * (address & 0x3));
-               count--;
-               address++;
-               buffer++;
-       }
+               component_base = (dbgbase & 0xFFFFF000)
+                       + (romentry & 0xFFFFF000);
 
-       return retval;
-}
+               if (romentry & 0x1) {
+                       uint32_t c_cid1;
+                       retval = mem_ap_read_atomic_u32(dap, component_base | 0xff4, &c_cid1);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("Can't read component with base address 0x%" PRIx32
+                                         ", the corresponding core might be turned off", component_base);
+                               return retval;
+                       }
+                       if (((c_cid1 >> 4) & 0x0f) == 1) {
+                               retval = dap_lookup_cs_component(dap, ap, component_base,
+                                                       type, addr, idx);
+                               if (retval == ERROR_OK)
+                                       break;
+                               if (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+                                       return retval;
+                       }
 
-/*--------------------------------------------------------------------------*/
+                       retval = mem_ap_read_atomic_u32(dap,
+                                       (component_base & 0xfffff000) | 0xfcc,
+                                       &devtype);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       if ((devtype & 0xff) == type) {
+                               if (!*idx) {
+                                       *addr = component_base;
+                                       break;
+                               } else
+                                       (*idx)--;
+                       }
+               }
+               entry_offset += 4;
+       } while (romentry > 0);
 
+       dap_ap_select(dap, ap_old);
 
-/* FIXME don't import ... just initialize as
- * part of DAP transport setup
-*/
-extern const struct dap_ops jtag_dp_ops;
+       if (!*addr)
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
 
-/*--------------------------------------------------------------------------*/
+       return ERROR_OK;
+}
 
-/**
- * Initialize a DAP.  This sets up the power domains, prepares the DP
- * for further use, and arranges to use AP #0 for all AP operations
- * until dap_ap-select() changes that policy.
- *
- * @param dap The DAP being initialized.
- *
- * @todo Rename this.  We also need an initialization scheme which account
- * for SWD transports not just JTAG; that will need to address differences
- * in layering.  (JTAG is useful without any debug target; but not SWD.)
- * And this may not even use an AHB-AP ... e.g. DAP-Lite uses an APB-AP.
- */
-int ahbap_debugport_init(struct adiv5_dap *dap)
+static int dap_rom_display(struct command_context *cmd_ctx,
+                               struct adiv5_dap *dap, int ap, uint32_t dbgbase, int depth)
 {
-       uint32_t ctrlstat;
-       int cnt = 0;
        int retval;
+       uint32_t cid0, cid1, cid2, cid3, memtype, romentry;
+       uint16_t entry_offset;
+       char tabs[7] = "";
 
-       LOG_DEBUG(" ");
-
-       /* JTAG-DP or SWJ-DP, in JTAG mode
-        * ... for SWD mode this is patched as part
-        * of link switchover
-        */
-       if (!dap->ops)
-               dap->ops = &jtag_dp_ops;
+       if (depth > 16) {
+               command_print(cmd_ctx, "\tTables too deep");
+               return ERROR_FAIL;
+       }
 
-       /* Default MEM-AP setup.
-        *
-        * REVISIT AP #0 may be an inappropriate default for this.
-        * Should we probe, or take a hint from the caller?
-        * Presumably we can ignore the possibility of multiple APs.
-        */
-       dap->apsel = !0;
-       dap_ap_select(dap, 0);
+       if (depth)
+               snprintf(tabs, sizeof(tabs), "[L%02d] ", depth);
 
-       /* DP initialization */
+       /* bit 16 of apid indicates a memory access port */
+       if (dbgbase & 0x02)
+               command_print(cmd_ctx, "\t%sValid ROM table present", tabs);
+       else
+               command_print(cmd_ctx, "\t%sROM table in legacy format", tabs);
 
-       retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
+       /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec  */
+       retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF0, &cid0);
        if (retval != ERROR_OK)
                return retval;
-
-       retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR);
+       retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF4, &cid1);
        if (retval != ERROR_OK)
                return retval;
-
-       retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
+       retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF8, &cid2);
        if (retval != ERROR_OK)
                return retval;
-
-       dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ;
-       retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat);
+       retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFFC, &cid3);
        if (retval != ERROR_OK)
                return retval;
-
-       retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat);
+       retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFCC, &memtype);
        if (retval != ERROR_OK)
                return retval;
-       if ((retval = dap_run(dap)) != ERROR_OK)
+       retval = dap_run(dap);
+       if (retval != ERROR_OK)
                return retval;
 
-       /* Check that we have debug power domains activated */
-       while (!(ctrlstat & CDBGPWRUPACK) && (cnt++ < 10))
-       {
-               LOG_DEBUG("DAP: wait CDBGPWRUPACK");
-               retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat);
-               if (retval != ERROR_OK)
-                       return retval;
-               if ((retval = dap_run(dap)) != ERROR_OK)
-                       return retval;
-               alive_sleep(10);
-       }
+       if (!is_dap_cid_ok(cid3, cid2, cid1, cid0))
+               command_print(cmd_ctx, "\t%sCID3 0x%02x"
+                               ", CID2 0x%02x"
+                               ", CID1 0x%02x"
+                               ", CID0 0x%02x",
+                               tabs,
+                               (unsigned)cid3, (unsigned)cid2,
+                               (unsigned)cid1, (unsigned)cid0);
+       if (memtype & 0x01)
+               command_print(cmd_ctx, "\t%sMEMTYPE system memory present on bus", tabs);
+       else
+               command_print(cmd_ctx, "\t%sMEMTYPE system memory not present: dedicated debug bus", tabs);
 
-       while (!(ctrlstat & CSYSPWRUPACK) && (cnt++ < 10))
-       {
-               LOG_DEBUG("DAP: wait CSYSPWRUPACK");
-               retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat);
+       /* Now we read ROM table entries from dbgbase&0xFFFFF000) | 0x000 until we get 0x00000000 */
+       for (entry_offset = 0; ; entry_offset += 4) {
+               retval = mem_ap_read_atomic_u32(dap, (dbgbase&0xFFFFF000) | entry_offset, &romentry);
                if (retval != ERROR_OK)
                        return retval;
-               if ((retval = dap_run(dap)) != ERROR_OK)
-                       return retval;
-               alive_sleep(10);
-       }
-
-       retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
-       if (retval != ERROR_OK)
-               return retval;
-       /* With debug power on we can activate OVERRUN checking */
-       dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT;
-       retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat);
-       if (retval != ERROR_OK)
-               return retval;
-       retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
-       if (retval != ERROR_OK)
-               return retval;
-
-       return ERROR_OK;
-}
-
-/* CID interpretation -- see ARM IHI 0029B section 3
- * and ARM IHI 0031A table 13-3.
- */
-static const char *class_description[16] ={
-       "Reserved", "ROM table", "Reserved", "Reserved",
-       "Reserved", "Reserved", "Reserved", "Reserved",
-       "Reserved", "CoreSight component", "Reserved", "Peripheral Test Block",
-       "Reserved", "OptimoDE DESS",
-               "Generic IP component", "PrimeCell or System component"
-};
-
-static bool
-is_dap_cid_ok(uint32_t cid3, uint32_t cid2, uint32_t cid1, uint32_t cid0)
-{
-       return cid3 == 0xb1 && cid2 == 0x05
-                       && ((cid1 & 0x0f) == 0) && cid0 == 0x0d;
-}
-
-struct broken_cpu {
-       uint32_t        dbgbase;
-       uint32_t        apid;
-       uint32_t        idcode;
-       uint32_t        correct_dbgbase;
-       char            *model;
-} broken_cpus[] = {
-       { 0x80000000, 0x04770002, 0x1ba00477, 0x60000000, "imx51" },
-};
-
-int dap_get_debugbase(struct adiv5_dap *dap, int apsel,
-                       uint32_t *out_dbgbase, uint32_t *out_apid)
-{
-       uint32_t apselold;
-       int retval;
-       unsigned int i;
-       uint32_t dbgbase, apid, idcode;
+               command_print(cmd_ctx, "\t%sROMTABLE[0x%x] = 0x%" PRIx32 "",
+                               tabs, entry_offset, romentry);
+               if (romentry & 0x01) {
+                       uint32_t c_cid0, c_cid1, c_cid2, c_cid3;
+                       uint32_t c_pid0, c_pid1, c_pid2, c_pid3, c_pid4;
+                       uint32_t component_base;
+                       unsigned part_num;
+                       const char *type, *full;
+
+                       component_base = (dbgbase & 0xFFFFF000) + (romentry & 0xFFFFF000);
+
+                       /* IDs are in last 4K section */
+                       retval = mem_ap_read_atomic_u32(dap, component_base + 0xFE0, &c_pid0);
+                       if (retval != ERROR_OK) {
+                               command_print(cmd_ctx, "\t%s\tCan't read component with base address 0x%" PRIx32
+                                             ", the corresponding core might be turned off", tabs, component_base);
+                               continue;
+                       }
+                       c_pid0 &= 0xff;
+                       retval = mem_ap_read_atomic_u32(dap, component_base + 0xFE4, &c_pid1);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       c_pid1 &= 0xff;
+                       retval = mem_ap_read_atomic_u32(dap, component_base + 0xFE8, &c_pid2);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       c_pid2 &= 0xff;
+                       retval = mem_ap_read_atomic_u32(dap, component_base + 0xFEC, &c_pid3);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       c_pid3 &= 0xff;
+                       retval = mem_ap_read_atomic_u32(dap, component_base + 0xFD0, &c_pid4);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       c_pid4 &= 0xff;
 
-       /* AP address is in bits 31:24 of DP_SELECT */
-       if (apsel >= 256)
-               return ERROR_INVALID_ARGUMENTS;
+                       retval = mem_ap_read_atomic_u32(dap, component_base + 0xFF0, &c_cid0);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       c_cid0 &= 0xff;
+                       retval = mem_ap_read_atomic_u32(dap, component_base + 0xFF4, &c_cid1);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       c_cid1 &= 0xff;
+                       retval = mem_ap_read_atomic_u32(dap, component_base + 0xFF8, &c_cid2);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       c_cid2 &= 0xff;
+                       retval = mem_ap_read_atomic_u32(dap, component_base + 0xFFC, &c_cid3);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       c_cid3 &= 0xff;
+
+                       command_print(cmd_ctx, "\t\tComponent base address 0x%" PRIx32 ", "
+                                     "start address 0x%" PRIx32, component_base,
+                                     /* component may take multiple 4K pages */
+                                     (uint32_t)(component_base - 0x1000*(c_pid4 >> 4)));
+                       command_print(cmd_ctx, "\t\tComponent class is 0x%" PRIx8 ", %s",
+                                       (uint8_t)((c_cid1 >> 4) & 0xf),
+                                       /* See ARM IHI 0029B Table 3-3 */
+                                       class_description[(c_cid1 >> 4) & 0xf]);
+
+                       /* CoreSight component? */
+                       if (((c_cid1 >> 4) & 0x0f) == 9) {
+                               uint32_t devtype;
+                               unsigned minor;
+                               const char *major = "Reserved", *subtype = "Reserved";
 
-       apselold = dap->apsel;
-       dap_ap_select(dap, apsel);
+                               retval = mem_ap_read_atomic_u32(dap,
+                                               (component_base & 0xfffff000) | 0xfcc,
+                                               &devtype);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                               minor = (devtype >> 4) & 0x0f;
+                               switch (devtype & 0x0f) {
+                               case 0:
+                                       major = "Miscellaneous";
+                                       switch (minor) {
+                                       case 0:
+                                               subtype = "other";
+                                               break;
+                                       case 4:
+                                               subtype = "Validation component";
+                                               break;
+                                       }
+                                       break;
+                               case 1:
+                                       major = "Trace Sink";
+                                       switch (minor) {
+                                       case 0:
+                                               subtype = "other";
+                                               break;
+                                       case 1:
+                                               subtype = "Port";
+                                               break;
+                                       case 2:
+                                               subtype = "Buffer";
+                                               break;
+                                       case 3:
+                                               subtype = "Router";
+                                               break;
+                                       }
+                                       break;
+                               case 2:
+                                       major = "Trace Link";
+                                       switch (minor) {
+                                       case 0:
+                                               subtype = "other";
+                                               break;
+                                       case 1:
+                                               subtype = "Funnel, router";
+                                               break;
+                                       case 2:
+                                               subtype = "Filter";
+                                               break;
+                                       case 3:
+                                               subtype = "FIFO, buffer";
+                                               break;
+                                       }
+                                       break;
+                               case 3:
+                                       major = "Trace Source";
+                                       switch (minor) {
+                                       case 0:
+                                               subtype = "other";
+                                               break;
+                                       case 1:
+                                               subtype = "Processor";
+                                               break;
+                                       case 2:
+                                               subtype = "DSP";
+                                               break;
+                                       case 3:
+                                               subtype = "Engine/Coprocessor";
+                                               break;
+                                       case 4:
+                                               subtype = "Bus";
+                                               break;
+                                       case 6:
+                                               subtype = "Software";
+                                               break;
+                                       }
+                                       break;
+                               case 4:
+                                       major = "Debug Control";
+                                       switch (minor) {
+                                       case 0:
+                                               subtype = "other";
+                                               break;
+                                       case 1:
+                                               subtype = "Trigger Matrix";
+                                               break;
+                                       case 2:
+                                               subtype = "Debug Auth";
+                                               break;
+                                       case 3:
+                                               subtype = "Power Requestor";
+                                               break;
+                                       }
+                                       break;
+                               case 5:
+                                       major = "Debug Logic";
+                                       switch (minor) {
+                                       case 0:
+                                               subtype = "other";
+                                               break;
+                                       case 1:
+                                               subtype = "Processor";
+                                               break;
+                                       case 2:
+                                               subtype = "DSP";
+                                               break;
+                                       case 3:
+                                               subtype = "Engine/Coprocessor";
+                                               break;
+                                       case 4:
+                                               subtype = "Bus";
+                                               break;
+                                       case 5:
+                                               subtype = "Memory";
+                                               break;
+                                       }
+                                       break;
+                               case 6:
+                                       major = "Perfomance Monitor";
+                                       switch (minor) {
+                                       case 0:
+                                               subtype = "other";
+                                               break;
+                                       case 1:
+                                               subtype = "Processor";
+                                               break;
+                                       case 2:
+                                               subtype = "DSP";
+                                               break;
+                                       case 3:
+                                               subtype = "Engine/Coprocessor";
+                                               break;
+                                       case 4:
+                                               subtype = "Bus";
+                                               break;
+                                       case 5:
+                                               subtype = "Memory";
+                                               break;
+                                       }
+                                       break;
+                               }
+                               command_print(cmd_ctx, "\t\tType is 0x%02" PRIx8 ", %s, %s",
+                                               (uint8_t)(devtype & 0xff),
+                                               major, subtype);
+                               /* REVISIT also show 0xfc8 DevId */
+                       }
 
-       retval = dap_queue_ap_read(dap, AP_REG_BASE, &dbgbase);
-       if (retval != ERROR_OK)
-               return retval;
-       retval = dap_queue_ap_read(dap, AP_REG_IDR, &apid);
-       if (retval != ERROR_OK)
-               return retval;
-       retval = dap_run(dap);
-       if (retval != ERROR_OK)
-               return retval;
+                       if (!is_dap_cid_ok(cid3, cid2, cid1, cid0))
+                               command_print(cmd_ctx,
+                                               "\t\tCID3 0%02x"
+                                               ", CID2 0%02x"
+                                               ", CID1 0%02x"
+                                               ", CID0 0%02x",
+                                               (int)c_cid3,
+                                               (int)c_cid2,
+                                               (int)c_cid1,
+                                               (int)c_cid0);
+                       command_print(cmd_ctx,
+                               "\t\tPeripheral ID[4..0] = hex "
+                               "%02x %02x %02x %02x %02x",
+                               (int)c_pid4, (int)c_pid3, (int)c_pid2,
+                               (int)c_pid1, (int)c_pid0);
+
+                       /* Part number interpretations are from Cortex
+                        * core specs, the CoreSight components TRM
+                        * (ARM DDI 0314H), CoreSight System Design
+                        * Guide (ARM DGI 0012D) and ETM specs; also
+                        * from chip observation (e.g. TI SDTI).
+                        */
+                       part_num = (c_pid0 & 0xff);
+                       part_num |= (c_pid1 & 0x0f) << 8;
+                       switch (part_num) {
+                       case 0x000:
+                               type = "Cortex-M3 NVIC";
+                               full = "(Interrupt Controller)";
+                               break;
+                       case 0x001:
+                               type = "Cortex-M3 ITM";
+                               full = "(Instrumentation Trace Module)";
+                               break;
+                       case 0x002:
+                               type = "Cortex-M3 DWT";
+                               full = "(Data Watchpoint and Trace)";
+                               break;
+                       case 0x003:
+                               type = "Cortex-M3 FBP";
+                               full = "(Flash Patch and Breakpoint)";
+                               break;
+                       case 0x008:
+                               type = "Cortex-M0 SCS";
+                               full = "(System Control Space)";
+                               break;
+                       case 0x00a:
+                               type = "Cortex-M0 DWT";
+                               full = "(Data Watchpoint and Trace)";
+                               break;
+                       case 0x00b:
+                               type = "Cortex-M0 BPU";
+                               full = "(Breakpoint Unit)";
+                               break;
+                       case 0x00c:
+                               type = "Cortex-M4 SCS";
+                               full = "(System Control Space)";
+                               break;
+                       case 0x00d:
+                               type = "CoreSight ETM11";
+                               full = "(Embedded Trace)";
+                               break;
+                       /* case 0x113: what? */
+                       case 0x120:             /* from OMAP3 memmap */
+                               type = "TI SDTI";
+                               full = "(System Debug Trace Interface)";
+                               break;
+                       case 0x343:             /* from OMAP3 memmap */
+                               type = "TI DAPCTL";
+                               full = "";
+                               break;
+                       case 0x906:
+                               type = "Coresight CTI";
+                               full = "(Cross Trigger)";
+                               break;
+                       case 0x907:
+                               type = "Coresight ETB";
+                               full = "(Trace Buffer)";
+                               break;
+                       case 0x908:
+                               type = "Coresight CSTF";
+                               full = "(Trace Funnel)";
+                               break;
+                       case 0x910:
+                               type = "CoreSight ETM9";
+                               full = "(Embedded Trace)";
+                               break;
+                       case 0x912:
+                               type = "Coresight TPIU";
+                               full = "(Trace Port Interface Unit)";
+                               break;
+                       case 0x913:
+                               type = "Coresight ITM";
+                               full = "(Instrumentation Trace Macrocell)";
+                               break;
+                       case 0x914:
+                               type = "Coresight SWO";
+                               full = "(Single Wire Output)";
+                               break;
+                       case 0x917:
+                               type = "Coresight HTM";
+                               full = "(AHB Trace Macrocell)";
+                               break;
+                       case 0x920:
+                               type = "CoreSight ETM11";
+                               full = "(Embedded Trace)";
+                               break;
+                       case 0x921:
+                               type = "Cortex-A8 ETM";
+                               full = "(Embedded Trace)";
+                               break;
+                       case 0x922:
+                               type = "Cortex-A8 CTI";
+                               full = "(Cross Trigger)";
+                               break;
+                       case 0x923:
+                               type = "Cortex-M3 TPIU";
+                               full = "(Trace Port Interface Unit)";
+                               break;
+                       case 0x924:
+                               type = "Cortex-M3 ETM";
+                               full = "(Embedded Trace)";
+                               break;
+                       case 0x925:
+                               type = "Cortex-M4 ETM";
+                               full = "(Embedded Trace)";
+                               break;
+                       case 0x930:
+                               type = "Cortex-R4 ETM";
+                               full = "(Embedded Trace)";
+                               break;
+                       case 0x950:
+                               type = "CoreSight Component";
+                               full = "(unidentified Cortex-A9 component)";
+                               break;
+                       case 0x961:
+                               type = "CoreSight TMC";
+                               full = "(Trace Memory Controller)";
+                               break;
+                       case 0x962:
+                               type = "CoreSight STM";
+                               full = "(System Trace Macrocell)";
+                               break;
+                       case 0x9a0:
+                               type = "CoreSight PMU";
+                               full = "(Performance Monitoring Unit)";
+                               break;
+                       case 0x9a1:
+                               type = "Cortex-M4 TPUI";
+                               full = "(Trace Port Interface Unit)";
+                               break;
+                       case 0x9a5:
+                               type = "Cortex-A5 ETM";
+                               full = "(Embedded Trace)";
+                               break;
+                       case 0xc05:
+                               type = "Cortex-A5 Debug";
+                               full = "(Debug Unit)";
+                               break;
+                       case 0xc08:
+                               type = "Cortex-A8 Debug";
+                               full = "(Debug Unit)";
+                               break;
+                       case 0xc09:
+                               type = "Cortex-A9 Debug";
+                               full = "(Debug Unit)";
+                               break;
+                       case 0x4af:
+                               type = "Cortex-A15 Debug";
+                               full = "(Debug Unit)";
+                               break;
+                       default:
+                               LOG_DEBUG("Unrecognized Part number 0x%" PRIx32, part_num);
+                               type = "-*- unrecognized -*-";
+                               full = "";
+                               break;
+                       }
+                       command_print(cmd_ctx, "\t\tPart is %s %s",
+                                       type, full);
 
-       /* Excavate the device ID code */
-       struct jtag_tap *tap = dap->jtag_info->tap;
-       while (tap != NULL) {
-               if (tap->hasidcode) {
-                       idcode = tap->idcode;
-                       break;
+                       /* ROM Table? */
+                       if (((c_cid1 >> 4) & 0x0f) == 1) {
+                               retval = dap_rom_display(cmd_ctx, dap, ap, component_base, depth + 1);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       }
+               } else {
+                       if (romentry)
+                               command_print(cmd_ctx, "\t\tComponent not present");
+                       else
+                               break;
                }
-               tap = tap->next_tap;
        }
-       if (tap == NULL || !tap->hasidcode)
-               return ERROR_OK;
-
-       /* Some CPUs are messed up, so fixup if needed. */
-       for (i = 0; i < sizeof(broken_cpus)/sizeof(struct broken_cpu); i++)
-               if (broken_cpus[i].dbgbase == dbgbase &&
-                       broken_cpus[i].apid == apid &&
-                       broken_cpus[i].idcode == idcode) {
-                       LOG_WARNING("Found broken CPU (%s), trying to fixup "
-                               "ROM Table location from 0x%08x to 0x%08x",
-                               broken_cpus[i].model, dbgbase,
-                               broken_cpus[i].correct_dbgbase);
-                       dbgbase = broken_cpus[i].correct_dbgbase;
-                       break;
-               }
-
-       dap_ap_select(dap, apselold);
-
-       /* The asignment happens only here to prevent modification of these
-        * values before they are certain. */
-       *out_dbgbase = dbgbase;
-       *out_apid = apid;
-
+       command_print(cmd_ctx, "\t%s\tEnd of ROM table", tabs);
        return ERROR_OK;
 }
 
-int dap_lookup_cs_component(struct adiv5_dap *dap, int apsel,
-                       uint32_t dbgbase, uint8_t type, uint32_t *addr)
-{
-       uint32_t apselold;
-       uint32_t romentry, entry_offset = 0, component_base, devtype;
-       int retval = ERROR_FAIL;
-
-       if (apsel >= 256)
-               return ERROR_INVALID_ARGUMENTS;
-
-       apselold = dap->apsel;
-       dap_ap_select(dap, apsel);
-
-       do
-       {
-               retval = mem_ap_read_atomic_u32(dap, (dbgbase&0xFFFFF000) |
-                                               entry_offset, &romentry);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               component_base = (dbgbase & 0xFFFFF000)
-                       + (romentry & 0xFFFFF000);
-
-               if (romentry & 0x1) {
-                       retval = mem_ap_read_atomic_u32(dap,
-                                       (component_base & 0xfffff000) | 0xfcc,
-                                       &devtype);
-                       if ((devtype & 0xff) == type) {
-                               *addr = component_base;
-                               retval = ERROR_OK;
-                               break;
-                       }
-               }
-               entry_offset += 4;
-       } while (romentry > 0);
-
-       dap_ap_select(dap, apselold);
-
-       return retval;
-}
-
 static int dap_info_command(struct command_context *cmd_ctx,
-               struct adiv5_dap *dap, int apsel)
+               struct adiv5_dap *dap, int ap)
 {
        int retval;
        uint32_t dbgbase, apid;
        int romtable_present = 0;
        uint8_t mem_ap;
-       uint32_t apselold;
+       uint32_t ap_old;
 
-       retval = dap_get_debugbase(dap, apsel, &dbgbase, &apid);
+       retval = dap_get_debugbase(dap, ap, &dbgbase, &apid);
        if (retval != ERROR_OK)
                return retval;
 
-       apselold = dap->apsel;
-       dap_ap_select(dap, apsel);
+       ap_old = dap->ap_current;
+       dap_ap_select(dap, ap);
 
        /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec  */
        mem_ap = ((apid&0x10000) && ((apid&0x0F) != 0));
        command_print(cmd_ctx, "AP ID register 0x%8.8" PRIx32, apid);
-       if (apid)
-       {
-               switch (apid&0x0F)
-               {
+       if (apid) {
+               switch (apid&0x0F) {
                        case 0:
                                command_print(cmd_ctx, "\tType is JTAG-AP");
                                break;
@@ -1161,374 +1434,16 @@ static int dap_info_command(struct command_context *cmd_ctx,
                 * not a ROM table ... or have no such components at all.
                 */
                if (mem_ap)
-                       command_print(cmd_ctx, "AP BASE 0x%8.8" PRIx32,
-                                       dbgbase);
-       }
-       else
-       {
-               command_print(cmd_ctx, "No AP found at this apsel 0x%x", apsel);
-       }
+                       command_print(cmd_ctx, "AP BASE 0x%8.8" PRIx32, dbgbase);
+       } else
+               command_print(cmd_ctx, "No AP found at this ap 0x%x", ap);
 
        romtable_present = ((mem_ap) && (dbgbase != 0xFFFFFFFF));
        if (romtable_present)
-       {
-               uint32_t cid0,cid1,cid2,cid3,memtype,romentry;
-               uint16_t entry_offset;
-
-               /* bit 16 of apid indicates a memory access port */
-               if (dbgbase & 0x02)
-                       command_print(cmd_ctx, "\tValid ROM table present");
-               else
-                       command_print(cmd_ctx, "\tROM table in legacy format");
-
-               /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec  */
-               retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF0, &cid0);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF4, &cid1);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF8, &cid2);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFFC, &cid3);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFCC, &memtype);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = dap_run(dap);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               if (!is_dap_cid_ok(cid3, cid2, cid1, cid0))
-                       command_print(cmd_ctx, "\tCID3 0x%2.2x"
-                                       ", CID2 0x%2.2x"
-                                       ", CID1 0x%2.2x"
-                                       ", CID0 0x%2.2x",
-                                       (unsigned) cid3, (unsigned)cid2,
-                                       (unsigned) cid1, (unsigned) cid0);
-               if (memtype & 0x01)
-                       command_print(cmd_ctx, "\tMEMTYPE system memory present on bus");
-               else
-                       command_print(cmd_ctx, "\tMEMTYPE System memory not present. "
-                                       "Dedicated debug bus.");
-
-               /* Now we read ROM table entries from dbgbase&0xFFFFF000) | 0x000 until we get 0x00000000 */
-               entry_offset = 0;
-               do
-               {
-                       retval = mem_ap_read_atomic_u32(dap, (dbgbase&0xFFFFF000) | entry_offset, &romentry);
-                       if (retval != ERROR_OK)
-                               return retval;
-                       command_print(cmd_ctx, "\tROMTABLE[0x%x] = 0x%" PRIx32 "",entry_offset,romentry);
-                       if (romentry&0x01)
-                       {
-                               uint32_t c_cid0, c_cid1, c_cid2, c_cid3;
-                               uint32_t c_pid0, c_pid1, c_pid2, c_pid3, c_pid4;
-                               uint32_t component_base;
-                               unsigned part_num;
-                               char *type, *full;
-
-                               component_base = (dbgbase & 0xFFFFF000)
-                                               + (romentry & 0xFFFFF000);
-
-                               /* IDs are in last 4K section */
-
-
-                               retval = mem_ap_read_atomic_u32(dap,
-                                       component_base + 0xFE0, &c_pid0);
-                               if (retval != ERROR_OK)
-                                       return retval;
-                               c_pid0 &= 0xff;
-                               retval = mem_ap_read_atomic_u32(dap,
-                                       component_base + 0xFE4, &c_pid1);
-                               if (retval != ERROR_OK)
-                                       return retval;
-                               c_pid1 &= 0xff;
-                               retval = mem_ap_read_atomic_u32(dap,
-                                       component_base + 0xFE8, &c_pid2);
-                               if (retval != ERROR_OK)
-                                       return retval;
-                               c_pid2 &= 0xff;
-                               retval = mem_ap_read_atomic_u32(dap,
-                                       component_base + 0xFEC, &c_pid3);
-                               if (retval != ERROR_OK)
-                                       return retval;
-                               c_pid3 &= 0xff;
-                               retval = mem_ap_read_atomic_u32(dap,
-                                       component_base + 0xFD0, &c_pid4);
-                               if (retval != ERROR_OK)
-                                       return retval;
-                               c_pid4 &= 0xff;
-
-                               retval = mem_ap_read_atomic_u32(dap,
-                                       component_base + 0xFF0, &c_cid0);
-                               if (retval != ERROR_OK)
-                                       return retval;
-                               c_cid0 &= 0xff;
-                               retval = mem_ap_read_atomic_u32(dap,
-                                       component_base + 0xFF4, &c_cid1);
-                               if (retval != ERROR_OK)
-                                       return retval;
-                               c_cid1 &= 0xff;
-                               retval = mem_ap_read_atomic_u32(dap,
-                                       component_base + 0xFF8, &c_cid2);
-                               if (retval != ERROR_OK)
-                                       return retval;
-                               c_cid2 &= 0xff;
-                               retval = mem_ap_read_atomic_u32(dap,
-                                       component_base + 0xFFC, &c_cid3);
-                               if (retval != ERROR_OK)
-                                       return retval;
-                               c_cid3 &= 0xff;
-
-
-                               command_print(cmd_ctx,
-                               "\t\tComponent base address 0x%" PRIx32
-                                       ", start address 0x%" PRIx32,
-                                               component_base,
-                               /* component may take multiple 4K pages */
-                               component_base - 0x1000*(c_pid4 >> 4));
-                               command_print(cmd_ctx, "\t\tComponent class is 0x%x, %s",
-                                               (int) (c_cid1 >> 4) & 0xf,
-                                               /* See ARM IHI 0029B Table 3-3 */
-                                               class_description[(c_cid1 >> 4) & 0xf]);
-
-                               /* CoreSight component? */
-                               if (((c_cid1 >> 4) & 0x0f) == 9) {
-                                       uint32_t devtype;
-                                       unsigned minor;
-                                       char *major = "Reserved", *subtype = "Reserved";
-
-                                       retval = mem_ap_read_atomic_u32(dap,
-                                                       (component_base & 0xfffff000) | 0xfcc,
-                                                       &devtype);
-                                       if (retval != ERROR_OK)
-                                               return retval;
-                                       minor = (devtype >> 4) & 0x0f;
-                                       switch (devtype & 0x0f) {
-                                       case 0:
-                                               major = "Miscellaneous";
-                                               switch (minor) {
-                                               case 0:
-                                                       subtype = "other";
-                                                       break;
-                                               case 4:
-                                                       subtype = "Validation component";
-                                                       break;
-                                               }
-                                               break;
-                                       case 1:
-                                               major = "Trace Sink";
-                                               switch (minor) {
-                                               case 0:
-                                                       subtype = "other";
-                                                       break;
-                                               case 1:
-                                                       subtype = "Port";
-                                                       break;
-                                               case 2:
-                                                       subtype = "Buffer";
-                                                       break;
-                                               }
-                                               break;
-                                       case 2:
-                                               major = "Trace Link";
-                                               switch (minor) {
-                                               case 0:
-                                                       subtype = "other";
-                                                       break;
-                                               case 1:
-                                                       subtype = "Funnel, router";
-                                                       break;
-                                               case 2:
-                                                       subtype = "Filter";
-                                                       break;
-                                               case 3:
-                                                       subtype = "FIFO, buffer";
-                                                       break;
-                                               }
-                                               break;
-                                       case 3:
-                                               major = "Trace Source";
-                                               switch (minor) {
-                                               case 0:
-                                                       subtype = "other";
-                                                       break;
-                                               case 1:
-                                                       subtype = "Processor";
-                                                       break;
-                                               case 2:
-                                                       subtype = "DSP";
-                                                       break;
-                                               case 3:
-                                                       subtype = "Engine/Coprocessor";
-                                                       break;
-                                               case 4:
-                                                       subtype = "Bus";
-                                                       break;
-                                               }
-                                               break;
-                                       case 4:
-                                               major = "Debug Control";
-                                               switch (minor) {
-                                               case 0:
-                                                       subtype = "other";
-                                                       break;
-                                               case 1:
-                                                       subtype = "Trigger Matrix";
-                                                       break;
-                                               case 2:
-                                                       subtype = "Debug Auth";
-                                                       break;
-                                               }
-                                               break;
-                                       case 5:
-                                               major = "Debug Logic";
-                                               switch (minor) {
-                                               case 0:
-                                                       subtype = "other";
-                                                       break;
-                                               case 1:
-                                                       subtype = "Processor";
-                                                       break;
-                                               case 2:
-                                                       subtype = "DSP";
-                                                       break;
-                                               case 3:
-                                                       subtype = "Engine/Coprocessor";
-                                                       break;
-                                               }
-                                               break;
-                                       }
-                                       command_print(cmd_ctx, "\t\tType is 0x%2.2x, %s, %s",
-                                                       (unsigned) (devtype & 0xff),
-                                                       major, subtype);
-                                       /* REVISIT also show 0xfc8 DevId */
-                               }
-
-                               if (!is_dap_cid_ok(cid3, cid2, cid1, cid0))
-                                       command_print(cmd_ctx,
-                                                     "\t\tCID3 0%2.2x"
-                                                       ", CID2 0%2.2x"
-                                                       ", CID1 0%2.2x"
-                                                       ", CID0 0%2.2x",
-                                                       (int) c_cid3,
-                                                       (int) c_cid2,
-                                                       (int)c_cid1,
-                                                       (int)c_cid0);
-                               command_print(cmd_ctx,
-                               "\t\tPeripheral ID[4..0] = hex "
-                               "%2.2x %2.2x %2.2x %2.2x %2.2x",
-                               (int) c_pid4, (int) c_pid3, (int) c_pid2,
-                               (int) c_pid1, (int) c_pid0);
-
-                               /* Part number interpretations are from Cortex
-                                * core specs, the CoreSight components TRM
-                                * (ARM DDI 0314H), CoreSight System Design
-                                * Guide (ARM DGI 0012D) and ETM specs; also
-                                * from chip observation (e.g. TI SDTI).
-                                */
-                               part_num = (c_pid0 & 0xff);
-                               part_num |= (c_pid1 & 0x0f) << 8;
-                               switch (part_num) {
-                               case 0x000:
-                                       type = "Cortex-M3 NVIC";
-                                       full = "(Interrupt Controller)";
-                                       break;
-                               case 0x001:
-                                       type = "Cortex-M3 ITM";
-                                       full = "(Instrumentation Trace Module)";
-                                       break;
-                               case 0x002:
-                                       type = "Cortex-M3 DWT";
-                                       full = "(Data Watchpoint and Trace)";
-                                       break;
-                               case 0x003:
-                                       type = "Cortex-M3 FBP";
-                                       full = "(Flash Patch and Breakpoint)";
-                                       break;
-                               case 0x00d:
-                                       type = "CoreSight ETM11";
-                                       full = "(Embedded Trace)";
-                                       break;
-                               // case 0x113: what?
-                               case 0x120:             /* from OMAP3 memmap */
-                                       type = "TI SDTI";
-                                       full = "(System Debug Trace Interface)";
-                                       break;
-                               case 0x343:             /* from OMAP3 memmap */
-                                       type = "TI DAPCTL";
-                                       full = "";
-                                       break;
-                               case 0x906:
-                                       type = "Coresight CTI";
-                                       full = "(Cross Trigger)";
-                                       break;
-                               case 0x907:
-                                       type = "Coresight ETB";
-                                       full = "(Trace Buffer)";
-                                       break;
-                               case 0x908:
-                                       type = "Coresight CSTF";
-                                       full = "(Trace Funnel)";
-                                       break;
-                               case 0x910:
-                                       type = "CoreSight ETM9";
-                                       full = "(Embedded Trace)";
-                                       break;
-                               case 0x912:
-                                       type = "Coresight TPIU";
-                                       full = "(Trace Port Interface Unit)";
-                                       break;
-                               case 0x921:
-                                       type = "Cortex-A8 ETM";
-                                       full = "(Embedded Trace)";
-                                       break;
-                               case 0x922:
-                                       type = "Cortex-A8 CTI";
-                                       full = "(Cross Trigger)";
-                                       break;
-                               case 0x923:
-                                       type = "Cortex-M3 TPIU";
-                                       full = "(Trace Port Interface Unit)";
-                                       break;
-                               case 0x924:
-                                       type = "Cortex-M3 ETM";
-                                       full = "(Embedded Trace)";
-                                       break;
-                               case 0x930:
-                                       type = "Cortex-R4 ETM";
-                                       full = "(Embedded Trace)";
-                                       break;
-                               case 0xc08:
-                                       type = "Cortex-A8 Debug";
-                                       full = "(Debug Unit)";
-                                       break;
-                               default:
-                                       type = "-*- unrecognized -*-";
-                                       full = "";
-                                       break;
-                               }
-                               command_print(cmd_ctx, "\t\tPart is %s %s",
-                                               type, full);
-                       }
-                       else
-                       {
-                               if (romentry)
-                                       command_print(cmd_ctx, "\t\tComponent not present");
-                               else
-                                       command_print(cmd_ctx, "\t\tEnd of ROM table");
-                       }
-                       entry_offset += 4;
-               } while (romentry > 0);
-       }
+               dap_rom_display(cmd_ctx, dap, ap, dbgbase, 0);
        else
-       {
                command_print(cmd_ctx, "\tNo ROM table present");
-       }
-       dap_ap_select(dap, apselold);
+       dap_ap_select(dap, ap_old);
 
        return ERROR_OK;
 }
@@ -1560,10 +1475,9 @@ COMMAND_HANDLER(dap_baseaddr_command)
        struct arm *arm = target_to_arm(target);
        struct adiv5_dap *dap = arm->dap;
 
-       uint32_t apsel, apselsave, baseaddr;
+       uint32_t apsel, baseaddr;
        int retval;
 
-       apselsave = dap->apsel;
        switch (CMD_ARGC) {
        case 0:
                apsel = dap->apsel;
@@ -1572,14 +1486,13 @@ COMMAND_HANDLER(dap_baseaddr_command)
                COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
                /* AP address is in bits 31:24 of DP_SELECT */
                if (apsel >= 256)
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                break;
        default:
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       if (apselsave != apsel)
-               dap_ap_select(dap, apsel);
+       dap_ap_select(dap, apsel);
 
        /* NOTE:  assumes we're talking to a MEM-AP, which
         * has a base address.  There are other kinds of AP,
@@ -1595,9 +1508,6 @@ COMMAND_HANDLER(dap_baseaddr_command)
 
        command_print(CMD_CTX, "0x%8.8" PRIx32, baseaddr);
 
-       if (apselsave != apsel)
-               dap_ap_select(dap, apselsave);
-
        return retval;
 }
 
@@ -1644,13 +1554,15 @@ COMMAND_HANDLER(dap_apsel_command)
                COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
                /* AP address is in bits 31:24 of DP_SELECT */
                if (apsel >= 256)
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                break;
        default:
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
+       dap->apsel = apsel;
        dap_ap_select(dap, apsel);
+
        retval = dap_queue_ap_read(dap, AP_REG_IDR, &apid);
        if (retval != ERROR_OK)
                return retval;
@@ -1664,16 +1576,48 @@ COMMAND_HANDLER(dap_apsel_command)
        return retval;
 }
 
+COMMAND_HANDLER(dap_apcsw_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct arm *arm = target_to_arm(target);
+       struct adiv5_dap *dap = arm->dap;
+
+       uint32_t apcsw = dap->apcsw[dap->apsel], sprot = 0;
+
+       switch (CMD_ARGC) {
+       case 0:
+               command_print(CMD_CTX, "apsel %" PRIi32 " selected, csw 0x%8.8" PRIx32,
+                       (dap->apsel), apcsw);
+               break;
+       case 1:
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], sprot);
+               /* AP address is in bits 31:24 of DP_SELECT */
+               if (sprot > 1)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               if (sprot)
+                       apcsw |= CSW_SPROT;
+               else
+                       apcsw &= ~CSW_SPROT;
+               break;
+       default:
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       dap->apcsw[dap->apsel] = apcsw;
+
+       return 0;
+}
+
+
+
 COMMAND_HANDLER(dap_apid_command)
 {
        struct target *target = get_current_target(CMD_CTX);
        struct arm *arm = target_to_arm(target);
        struct adiv5_dap *dap = arm->dap;
 
-       uint32_t apsel, apselsave, apid;
+       uint32_t apsel, apid;
        int retval;
 
-       apselsave = dap->apsel;
        switch (CMD_ARGC) {
        case 0:
                apsel = dap->apsel;
@@ -1682,14 +1626,13 @@ COMMAND_HANDLER(dap_apid_command)
                COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
                /* AP address is in bits 31:24 of DP_SELECT */
                if (apsel >= 256)
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                break;
        default:
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       if (apselsave != apsel)
-               dap_ap_select(dap, apsel);
+       dap_ap_select(dap, apsel);
 
        retval = dap_queue_ap_read(dap, AP_REG_IDR, &apid);
        if (retval != ERROR_OK)
@@ -1699,12 +1642,36 @@ COMMAND_HANDLER(dap_apid_command)
                return retval;
 
        command_print(CMD_CTX, "0x%8.8" PRIx32, apid);
-       if (apselsave != apsel)
-               dap_ap_select(dap, apselsave);
 
        return retval;
 }
 
+COMMAND_HANDLER(dap_ti_be_32_quirks_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct arm *arm = target_to_arm(target);
+       struct adiv5_dap *dap = arm->dap;
+
+       uint32_t enable = dap->ti_be_32_quirks;
+
+       switch (CMD_ARGC) {
+       case 0:
+               break;
+       case 1:
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], enable);
+               if (enable > 1)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               break;
+       default:
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       dap->ti_be_32_quirks = enable;
+       command_print(CMD_CTX, "TI BE-32 quirks mode %s",
+               enable ? "enabled" : "disabled");
+
+       return 0;
+}
+
 static const struct command_registration dap_commands[] = {
        {
                .name = "info",
@@ -1722,6 +1689,14 @@ static const struct command_registration dap_commands[] = {
                        "and display the result",
                .usage = "[ap_num]",
        },
+       {
+               .name = "apcsw",
+               .handler = dap_apcsw_command,
+               .mode = COMMAND_EXEC,
+               .help = "Set csw access bit ",
+               .usage = "[sprot]",
+       },
+
        {
                .name = "apid",
                .handler = dap_apid_command,
@@ -1746,6 +1721,13 @@ static const struct command_registration dap_commands[] = {
                        "bus access [0-255]",
                .usage = "[cycles]",
        },
+       {
+               .name = "ti_be_32_quirks",
+               .handler = dap_ti_be_32_quirks_command,
+               .mode = COMMAND_CONFIG,
+               .help = "set/get quirks mode for TI TMS450/TMS570 processors",
+               .usage = "[enable]",
+       },
        COMMAND_REGISTRATION_DONE
 };
 
@@ -1754,9 +1736,8 @@ const struct command_registration dap_command_handlers[] = {
                .name = "dap",
                .mode = COMMAND_EXEC,
                .help = "DAP command group",
+               .usage = "",
                .chain = dap_commands,
        },
        COMMAND_REGISTRATION_DONE
 };
-
-

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)