X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Farm_adi_v5.c;h=2ddb6b5f8e35384e94406563717e0fab95b28b04;hb=4a7bb931e37e54e8b0cd9d3a6b41c693d1042106;hp=a15590070922fa5cf7fb511c16ed585efa7779b1;hpb=b1a1a48b30243d3582a8443f4baf3dd500683eda;p=openocd.git diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index a155900709..2ddb6b5f8e 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -113,34 +113,33 @@ void dap_ap_select(struct adiv5_dap *dap, uint8_t ap) * Values MUST BE UPDATED BEFORE AP ACCESS. */ dap->ap_bank_value = -1; - dap->ap_csw_value = -1; - dap->ap_tar_value = -1; } } -static int dap_setup_accessport_csw(struct adiv5_dap *dap, uint32_t csw) +static int mem_ap_setup_csw(struct adiv5_ap *ap, uint32_t csw) { csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT | - dap->apcsw[dap->ap_current >> 24]; + ap->csw_default; - if (csw != dap->ap_csw_value) { + if (csw != ap->csw_value) { /* LOG_DEBUG("DAP: Set CSW %x",csw); */ - int retval = dap_queue_ap_write(dap, AP_REG_CSW, csw); + int retval = dap_queue_ap_write(ap->dap, MEM_AP_REG_CSW, csw); if (retval != ERROR_OK) return retval; - dap->ap_csw_value = csw; + ap->csw_value = csw; } return ERROR_OK; } -static int dap_setup_accessport_tar(struct adiv5_dap *dap, uint32_t tar) +static int mem_ap_setup_tar(struct adiv5_ap *ap, uint32_t tar) { - if (tar != dap->ap_tar_value || dap->ap_csw_value & CSW_ADDRINC_MASK) { + if (tar != ap->tar_value || + (ap->csw_value & CSW_ADDRINC_MASK)) { /* LOG_DEBUG("DAP: Set TAR %x",tar); */ - int retval = dap_queue_ap_write(dap, AP_REG_TAR, tar); + int retval = dap_queue_ap_write(ap->dap, MEM_AP_REG_TAR, tar); if (retval != ERROR_OK) return retval; - dap->ap_tar_value = tar; + ap->tar_value = tar; } return ERROR_OK; } @@ -149,14 +148,12 @@ static int dap_setup_accessport_tar(struct adiv5_dap *dap, uint32_t tar) * Queue transactions setting up transfer parameters for the * currently selected MEM-AP. * - * Subsequent transfers using registers like AP_REG_DRW or AP_REG_BD2 + * Subsequent transfers using registers like MEM_AP_REG_DRW or MEM_AP_REG_BD2 * initiate data reads or writes using memory or peripheral addresses. * If the CSW is configured for it, the TAR may be automatically * incremented after each transfer. * - * @todo Rename to reflect it being specifically a MEM-AP function. - * - * @param dap The DAP connected to the MEM-AP. + * @param ap The MEM-AP. * @param csw MEM-AP Control/Status Word (CSW) register to assign. If this * matches the cached value, the register is not changed. * @param tar MEM-AP Transfer Address Register (TAR) to assign. If this @@ -164,13 +161,13 @@ static int dap_setup_accessport_tar(struct adiv5_dap *dap, uint32_t tar) * * @return ERROR_OK if the transaction was properly queued, else a fault code. */ -int dap_setup_accessport(struct adiv5_dap *dap, uint32_t csw, uint32_t tar) +static int mem_ap_setup_transfer(struct adiv5_ap *ap, uint32_t csw, uint32_t tar) { int retval; - retval = dap_setup_accessport_csw(dap, csw); + retval = mem_ap_setup_csw(ap, csw); if (retval != ERROR_OK) return retval; - retval = dap_setup_accessport_tar(dap, tar); + retval = mem_ap_setup_tar(ap, tar); if (retval != ERROR_OK) return retval; return ERROR_OK; @@ -179,7 +176,7 @@ int dap_setup_accessport(struct adiv5_dap *dap, uint32_t csw, uint32_t tar) /** * Asynchronous (queued) read of a word from memory or a system register. * - * @param dap The DAP connected to the MEM-AP performing the read. + * @param ap The MEM-AP to access. * @param address Address of the 32-bit word to read; it must be * readable by the currently selected MEM-AP. * @param value points to where the word will be stored when the @@ -187,27 +184,29 @@ int dap_setup_accessport(struct adiv5_dap *dap, uint32_t csw, uint32_t tar) * * @return ERROR_OK for success. Otherwise a fault code. */ -int mem_ap_read_u32(struct adiv5_dap *dap, uint32_t address, +int mem_ap_read_u32(struct adiv5_ap *ap, uint32_t address, uint32_t *value) { int retval; + dap_ap_select(ap->dap, ap->ap_num); + /* Use banked addressing (REG_BDx) to avoid some link traffic * (updating TAR) when reading several consecutive addresses. */ - retval = dap_setup_accessport(dap, CSW_32BIT | CSW_ADDRINC_OFF, + retval = mem_ap_setup_transfer(ap, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0); if (retval != ERROR_OK) return retval; - return dap_queue_ap_read(dap, AP_REG_BD0 | (address & 0xC), value); + return dap_queue_ap_read(ap->dap, MEM_AP_REG_BD0 | (address & 0xC), value); } /** * Synchronous read of a word from memory or a system register. * As a side effect, this flushes any queued transactions. * - * @param dap The DAP connected to the MEM-AP performing the read. + * @param ap The MEM-AP to access. * @param address Address of the 32-bit word to read; it must be * readable by the currently selected MEM-AP. * @param value points to where the result will be stored. @@ -215,22 +214,22 @@ int mem_ap_read_u32(struct adiv5_dap *dap, uint32_t address, * @return ERROR_OK for success; *value holds the result. * Otherwise a fault code. */ -int mem_ap_read_atomic_u32(struct adiv5_dap *dap, uint32_t address, +int mem_ap_read_atomic_u32(struct adiv5_ap *ap, uint32_t address, uint32_t *value) { int retval; - retval = mem_ap_read_u32(dap, address, value); + retval = mem_ap_read_u32(ap, address, value); if (retval != ERROR_OK) return retval; - return dap_run(dap); + return dap_run(ap->dap); } /** * Asynchronous (queued) write of a word to memory or a system register. * - * @param dap The DAP connected to the MEM-AP. + * @param ap The MEM-AP to access. * @param address Address to be written; it must be writable by * the currently selected MEM-AP. * @param value Word that will be written to the address when transaction @@ -238,20 +237,22 @@ int mem_ap_read_atomic_u32(struct adiv5_dap *dap, uint32_t address, * * @return ERROR_OK for success. Otherwise a fault code. */ -int mem_ap_write_u32(struct adiv5_dap *dap, uint32_t address, +int mem_ap_write_u32(struct adiv5_ap *ap, uint32_t address, uint32_t value) { int retval; + dap_ap_select(ap->dap, ap->ap_num); + /* Use banked addressing (REG_BDx) to avoid some link traffic * (updating TAR) when writing several consecutive addresses. */ - retval = dap_setup_accessport(dap, CSW_32BIT | CSW_ADDRINC_OFF, + retval = mem_ap_setup_transfer(ap, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0); if (retval != ERROR_OK) return retval; - return dap_queue_ap_write(dap, AP_REG_BD0 | (address & 0xC), + return dap_queue_ap_write(ap->dap, MEM_AP_REG_BD0 | (address & 0xC), value); } @@ -259,28 +260,28 @@ int mem_ap_write_u32(struct adiv5_dap *dap, uint32_t address, * Synchronous write of a word to memory or a system register. * As a side effect, this flushes any queued transactions. * - * @param dap The DAP connected to the MEM-AP. + * @param ap The MEM-AP to access. * @param address Address to be written; it must be writable by * the currently selected MEM-AP. * @param value Word that will be written. * * @return ERROR_OK for success; the data was written. Otherwise a fault code. */ -int mem_ap_write_atomic_u32(struct adiv5_dap *dap, uint32_t address, +int mem_ap_write_atomic_u32(struct adiv5_ap *ap, uint32_t address, uint32_t value) { - int retval = mem_ap_write_u32(dap, address, value); + int retval = mem_ap_write_u32(ap, address, value); if (retval != ERROR_OK) return retval; - return dap_run(dap); + return dap_run(ap->dap); } /** * Synchronous write of a block of memory, using a specific access size. * - * @param dap The DAP connected to the MEM-AP. + * @param ap The MEM-AP to access. * @param buffer The data buffer to write. No particular alignment is assumed. * @param size Which access size to use, in bytes. 1, 2 or 4. * @param count The number of writes to do (in size units, not bytes). @@ -289,9 +290,10 @@ int mem_ap_write_atomic_u32(struct adiv5_dap *dap, uint32_t address, * 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, +static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address, bool addrinc) { + struct adiv5_dap *dap = ap->dap; size_t nbytes = size * count; const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; uint32_t csw_size; @@ -324,10 +326,12 @@ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, ui return ERROR_TARGET_UNALIGNED_ACCESS; } - if (dap->unaligned_access_bad && (address % size != 0)) + if (ap->unaligned_access_bad && (address % size != 0)) return ERROR_TARGET_UNALIGNED_ACCESS; - retval = dap_setup_accessport_tar(dap, address ^ addr_xor); + dap_ap_select(ap->dap, ap->ap_num); + + retval = mem_ap_setup_tar(ap, address ^ addr_xor); if (retval != ERROR_OK) return retval; @@ -335,12 +339,12 @@ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, ui 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) { + if (addrinc && ap->packed_transfers && nbytes >= 4 + && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { this_size = 4; - retval = dap_setup_accessport_csw(dap, csw_size | CSW_ADDRINC_PACKED); + retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED); } else { - retval = dap_setup_accessport_csw(dap, csw_size | csw_addrincr); + retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr); } if (retval != ERROR_OK) @@ -379,13 +383,13 @@ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, ui nbytes -= this_size; - retval = dap_queue_ap_write(dap, AP_REG_DRW, outvalue); + retval = dap_queue_ap_write(dap, MEM_AP_REG_DRW, outvalue); if (retval != ERROR_OK) break; /* 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 (addrinc && (addr_xor || (address % ap->tar_autoincr_block < size && nbytes > 0))) { + retval = mem_ap_setup_tar(ap, address ^ addr_xor); if (retval != ERROR_OK) break; } @@ -397,7 +401,7 @@ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, ui if (retval != ERROR_OK) { uint32_t tar; - if (dap_queue_ap_read(dap, AP_REG_TAR, &tar) == ERROR_OK + if (dap_queue_ap_read(dap, MEM_AP_REG_TAR, &tar) == ERROR_OK && dap_run(dap) == ERROR_OK) LOG_ERROR("Failed to write memory at 0x%08"PRIx32, tar); else @@ -410,7 +414,7 @@ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, ui /** * Synchronous read of a block of memory, using a specific access size. * - * @param dap The DAP connected to the MEM-AP. + * @param ap The MEM-AP to access. * @param buffer The data buffer to receive the data. No particular alignment is assumed. * @param size Which access size to use, in bytes. 1, 2 or 4. * @param count The number of reads to do (in size units, not bytes). @@ -419,9 +423,10 @@ int mem_ap_write(struct adiv5_dap *dap, const uint8_t *buffer, uint32_t size, ui * 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, +static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint32_t count, uint32_t adr, bool addrinc) { + struct adiv5_dap *dap = ap->dap; size_t nbytes = size * count; const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF; uint32_t csw_size; @@ -444,7 +449,7 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t else return ERROR_TARGET_UNALIGNED_ACCESS; - if (dap->unaligned_access_bad && (adr % size != 0)) + if (ap->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 @@ -457,7 +462,9 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t return ERROR_FAIL; } - retval = dap_setup_accessport_tar(dap, address); + dap_ap_select(ap->dap, ap->ap_num); + + retval = mem_ap_setup_tar(ap, address); if (retval != ERROR_OK) { free(read_buf); return retval; @@ -470,17 +477,17 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t 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) { + if (addrinc && ap->packed_transfers && nbytes >= 4 + && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { this_size = 4; - retval = dap_setup_accessport_csw(dap, csw_size | CSW_ADDRINC_PACKED); + retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED); } else { - retval = dap_setup_accessport_csw(dap, csw_size | csw_addrincr); + retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr); } if (retval != ERROR_OK) break; - retval = dap_queue_ap_read(dap, AP_REG_DRW, read_ptr++); + retval = dap_queue_ap_read(dap, MEM_AP_REG_DRW, read_ptr++); if (retval != ERROR_OK) break; @@ -488,8 +495,8 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t address += this_size; /* Rewrite TAR if it wrapped */ - if (addrinc && address % dap->tar_autoincr_block < size && nbytes > 0) { - retval = dap_setup_accessport_tar(dap, address); + if (addrinc && address % ap->tar_autoincr_block < size && nbytes > 0) { + retval = mem_ap_setup_tar(ap, address); if (retval != ERROR_OK) break; } @@ -507,7 +514,7 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t * 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 + if (dap_queue_ap_read(dap, MEM_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) @@ -522,8 +529,8 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t while (nbytes > 0) { uint32_t this_size = size; - if (addrinc && dap->packed_transfers && nbytes >= 4 - && max_tar_block_size(dap->tar_autoincr_block, address) >= 4) { + if (addrinc && ap->packed_transfers && nbytes >= 4 + && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) { this_size = 4; } @@ -557,366 +564,172 @@ int mem_ap_read(struct adiv5_dap *dap, uint8_t *buffer, uint32_t size, uint32_t return retval; } -/*--------------------------------------------------------------------*/ -/* 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) -{ - dap_ap_select(swjdp, ap); - return mem_ap_read_u32(swjdp, address, value); -} - -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); -} - -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); -} - -int mem_ap_sel_write_atomic_u32(struct adiv5_dap *swjdp, uint8_t ap, - uint32_t address, uint32_t value) -{ - dap_ap_select(swjdp, ap); - return mem_ap_write_atomic_u32(swjdp, address, value); -} - -int mem_ap_sel_read_buf(struct adiv5_dap *swjdp, uint8_t ap, +int mem_ap_read_buf(struct adiv5_ap *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); + return mem_ap_read(ap, buffer, size, count, address, true); } -int mem_ap_sel_write_buf(struct adiv5_dap *swjdp, uint8_t ap, +int mem_ap_write_buf(struct adiv5_ap *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); + return mem_ap_write(ap, buffer, size, count, address, true); } -int mem_ap_sel_read_buf_noincr(struct adiv5_dap *swjdp, uint8_t ap, +int mem_ap_read_buf_noincr(struct adiv5_ap *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); + return mem_ap_read(ap, buffer, size, count, address, false); } -int mem_ap_sel_write_buf_noincr(struct adiv5_dap *swjdp, uint8_t ap, +int mem_ap_write_buf_noincr(struct adiv5_ap *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); + return mem_ap_write(ap, buffer, size, count, address, false); } -#define MDM_REG_STAT 0x00 -#define MDM_REG_CTRL 0x04 -#define MDM_REG_ID 0xfc - -#define MDM_STAT_FMEACK (1<<0) -#define MDM_STAT_FREADY (1<<1) -#define MDM_STAT_SYSSEC (1<<2) -#define MDM_STAT_SYSRES (1<<3) -#define MDM_STAT_FMEEN (1<<5) -#define MDM_STAT_BACKDOOREN (1<<6) -#define MDM_STAT_LPEN (1<<7) -#define MDM_STAT_VLPEN (1<<8) -#define MDM_STAT_LLSMODEXIT (1<<9) -#define MDM_STAT_VLLSXMODEXIT (1<<10) -#define MDM_STAT_CORE_HALTED (1<<16) -#define MDM_STAT_CORE_SLEEPDEEP (1<<17) -#define MDM_STAT_CORESLEEPING (1<<18) - -#define MEM_CTRL_FMEIP (1<<0) -#define MEM_CTRL_DBG_DIS (1<<1) -#define MEM_CTRL_DBG_REQ (1<<2) -#define MEM_CTRL_SYS_RES_REQ (1<<3) -#define MEM_CTRL_CORE_HOLD_RES (1<<4) -#define MEM_CTRL_VLLSX_DBG_REQ (1<<5) -#define MEM_CTRL_VLLSX_DBG_ACK (1<<6) -#define MEM_CTRL_VLLSX_STAT_ACK (1<<7) - -#define MDM_ACCESS_TIMEOUT 3000 /* ms */ - -/** - * - */ -int dap_syssec_kinetis_mdmap(struct adiv5_dap *dap) -{ - uint32_t val; - int retval; - int timeout = 0; - enum reset_types jtag_reset_config = jtag_get_reset_config(); - - dap_ap_select(dap, 1); - - /* first check mdm-ap id register */ - retval = dap_queue_ap_read(dap, MDM_REG_ID, &val); - if (retval != ERROR_OK) - return retval; - dap_run(dap); - - if (val != 0x001C0000) { - LOG_DEBUG("id doesn't match %08" PRIX32 " != 0x001C0000", val); - dap_ap_select(dap, 0); - return ERROR_FAIL; - } - - /* read and parse status register - * it's important that the device is out of - * reset here - */ - while (1) { - if (timeout++ > MDM_ACCESS_TIMEOUT) { - LOG_DEBUG("MDMAP : flash ready timeout"); - return ERROR_FAIL; - } - retval = dap_queue_ap_read(dap, MDM_REG_STAT, &val); - if (retval != ERROR_OK) - return retval; - dap_run(dap); - - LOG_DEBUG("MDM_REG_STAT %08" PRIX32, val); - if (val & MDM_STAT_FREADY) - break; - alive_sleep(1); - } - - if ((val & MDM_STAT_SYSSEC)) { - LOG_DEBUG("MDMAP: system is secured, masserase needed"); - - if (!(val & MDM_STAT_FMEEN)) - LOG_DEBUG("MDMAP: masserase is disabled"); - else { - /* we need to assert reset */ - if (jtag_reset_config & RESET_HAS_SRST) { - /* default to asserting srst */ - adapter_assert_reset(); - } else { - LOG_DEBUG("SRST not configured"); - dap_ap_select(dap, 0); - return ERROR_FAIL; - } - timeout = 0; - while (1) { - if (timeout++ > MDM_ACCESS_TIMEOUT) { - LOG_DEBUG("MDMAP : flash ready timeout"); - return ERROR_FAIL; - } - retval = dap_queue_ap_write(dap, MDM_REG_CTRL, MEM_CTRL_FMEIP); - if (retval != ERROR_OK) - return retval; - dap_run(dap); - /* read status register and wait for ready */ - retval = dap_queue_ap_read(dap, MDM_REG_STAT, &val); - if (retval != ERROR_OK) - return retval; - dap_run(dap); - LOG_DEBUG("MDM_REG_STAT %08" PRIX32, val); - - if ((val & 1)) - break; - alive_sleep(1); - } - timeout = 0; - while (1) { - if (timeout++ > MDM_ACCESS_TIMEOUT) { - LOG_DEBUG("MDMAP : flash ready timeout"); - return ERROR_FAIL; - } - retval = dap_queue_ap_write(dap, MDM_REG_CTRL, 0); - if (retval != ERROR_OK) - return retval; - dap_run(dap); - /* read status register */ - retval = dap_queue_ap_read(dap, MDM_REG_STAT, &val); - if (retval != ERROR_OK) - return retval; - dap_run(dap); - LOG_DEBUG("MDM_REG_STAT %08" PRIX32, val); - /* read control register and wait for ready */ - retval = dap_queue_ap_read(dap, MDM_REG_CTRL, &val); - if (retval != ERROR_OK) - return retval; - dap_run(dap); - LOG_DEBUG("MDM_REG_CTRL %08" PRIX32, val); - - if (val == 0x00) - break; - alive_sleep(1); - } - } - } +/*--------------------------------------------------------------------------*/ - dap_ap_select(dap, 0); - return ERROR_OK; -} +#define DAP_POWER_DOMAIN_TIMEOUT (10) -/** */ -struct dap_syssec_filter { - /** */ - uint32_t idcode; - /** */ - int (*dap_init)(struct adiv5_dap *dap); -}; +/* FIXME don't import ... just initialize as + * part of DAP transport setup +*/ +extern const struct dap_ops jtag_dp_ops; -/** */ -static struct dap_syssec_filter dap_syssec_filter_data[] = { - { 0x4BA00477, dap_syssec_kinetis_mdmap } -}; +/*--------------------------------------------------------------------------*/ /** - * + * Create a new DAP */ -int dap_syssec(struct adiv5_dap *dap) +struct adiv5_dap *dap_init(void) { - unsigned int i; - struct jtag_tap *tap; - - for (i = 0; i < sizeof(dap_syssec_filter_data); i++) { - tap = dap->jtag_info->tap; - - while (tap != NULL) { - if (tap->hasidcode && (dap_syssec_filter_data[i].idcode == tap->idcode)) { - LOG_DEBUG("DAP: mdmap_init for idcode: %08" PRIx32, tap->idcode); - dap_syssec_filter_data[i].dap_init(dap); - } - tap = tap->next_tap; - } + struct adiv5_dap *dap = calloc(1, sizeof(struct adiv5_dap)); + int i; + /* Set up with safe defaults */ + for (i = 0; i <= 255; i++) { + dap->ap[i].dap = dap; + dap->ap[i].ap_num = i; + /* memaccess_tck max is 255 */ + dap->ap[i].memaccess_tck = 255; + /* Number of bits for tar autoincrement, impl. dep. at least 10 */ + dap->ap[i].tar_autoincr_block = (1<<10); } - - return ERROR_OK; + dap->ap_current = -1; + dap->ap_bank_value = -1; + dap->dp_bank_value = -1; + return dap; } -/*--------------------------------------------------------------------------*/ - - -/* FIXME don't import ... just initialize as - * part of DAP transport setup -*/ -extern const struct dap_ops jtag_dp_ops; - -/*--------------------------------------------------------------------------*/ - /** * 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. + * for further use and activates overrun checking. * * @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) +int dap_dp_init(struct adiv5_dap *dap) { - uint32_t ctrlstat; - int cnt = 0; int retval; LOG_DEBUG(" "); - /* JTAG-DP or SWJ-DP, in JTAG mode * ... for SWD mode this is patched as part * of link switchover + * FIXME: This should already be setup by the respective transport specific DAP creation. */ if (!dap->ops) dap->ops = &jtag_dp_ops; - /* 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->ap_current = -1; + dap->ap_bank_value = -1; + dap->last_read = NULL; - /* DP initialization */ + for (size_t i = 0; i < 10; i++) { + /* DP initialization */ - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); - if (retval != ERROR_OK) - return retval; + dap->dp_bank_value = 0; - retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR); - if (retval != ERROR_OK) - return retval; + retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); + if (retval != ERROR_OK) + continue; - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); - if (retval != ERROR_OK) - return retval; + retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR); + if (retval != ERROR_OK) + continue; - dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; - 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) + continue; - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat); - if (retval != ERROR_OK) - return retval; - retval = dap_run(dap); - 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); + if (retval != ERROR_OK) + continue; - /* Check that we have debug power domains activated */ - while (!(ctrlstat & CDBGPWRUPACK) && (cnt++ < 10)) { + /* Check that we have debug power domains activated */ LOG_DEBUG("DAP: wait CDBGPWRUPACK"); - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat); - if (retval != ERROR_OK) - return retval; - retval = dap_run(dap); + retval = dap_dp_poll_register(dap, DP_CTRL_STAT, + CDBGPWRUPACK, CDBGPWRUPACK, + DAP_POWER_DOMAIN_TIMEOUT); if (retval != ERROR_OK) - return retval; - alive_sleep(10); - } + continue; - while (!(ctrlstat & CSYSPWRUPACK) && (cnt++ < 10)) { LOG_DEBUG("DAP: wait CSYSPWRUPACK"); - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, &ctrlstat); + retval = dap_dp_poll_register(dap, DP_CTRL_STAT, + CSYSPWRUPACK, CSYSPWRUPACK, + DAP_POWER_DOMAIN_TIMEOUT); if (retval != ERROR_OK) - return retval; + continue; + + retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); + if (retval != ERROR_OK) + 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; + retval = dap_run(dap); if (retval != ERROR_OK) - return retval; - alive_sleep(10); - } + continue; - 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; + break; + } - dap_syssec(dap); + 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 ap The MEM-AP being initialized. + */ +int mem_ap_init(struct adiv5_ap *ap) +{ /* check that we support packed transfers */ uint32_t csw, cfg; + int retval; + struct adiv5_dap *dap = ap->dap; - retval = dap_setup_accessport(dap, CSW_8BIT | CSW_ADDRINC_PACKED, 0); + dap_ap_select(dap, ap->ap_num); + + retval = mem_ap_setup_transfer(ap, CSW_8BIT | CSW_ADDRINC_PACKED, 0); if (retval != ERROR_OK) return retval; - retval = dap_queue_ap_read(dap, AP_REG_CSW, &csw); + retval = dap_queue_ap_read(dap, MEM_AP_REG_CSW, &csw); if (retval != ERROR_OK) return retval; - retval = dap_queue_ap_read(dap, AP_REG_CFG, &cfg); + retval = dap_queue_ap_read(dap, MEM_AP_REG_CFG, &cfg); if (retval != ERROR_OK) return retval; @@ -925,17 +738,17 @@ int ahbap_debugport_init(struct adiv5_dap *dap) return retval; if (csw & CSW_ADDRINC_PACKED) - dap->packed_transfers = true; + ap->packed_transfers = true; else - dap->packed_transfers = false; + ap->packed_transfers = false; /* Packed transfers on TI BE-32 processors do not work correctly in * many cases. */ if (dap->ti_be_32_quirks) - dap->packed_transfers = false; + ap->packed_transfers = false; LOG_DEBUG("MEM_AP Packed Transfers: %s", - dap->packed_transfers ? "enabled" : "disabled"); + ap->packed_transfers ? "enabled" : "disabled"); /* The ARM ADI spec leaves implementation-defined whether unaligned * memory accesses work, only work partially, or cause a sticky error. @@ -943,7 +756,7 @@ int ahbap_debugport_init(struct adiv5_dap *dap) * 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; + ap->unaligned_access_bad = dap->ti_be_32_quirks; LOG_DEBUG("MEM_AP CFG: large data %d, long address %d, big-endian %d", !!(cfg & 0x04), !!(cfg & 0x02), !!(cfg & 0x01)); @@ -971,16 +784,16 @@ static bool is_dap_cid_ok(uint32_t cid3, uint32_t cid2, uint32_t cid1, uint32_t /* * This function checks the ID for each access port to find the requested Access Port type */ -int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, uint8_t *ap_num_out) +int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_ap **ap_out) { - int ap; + int ap_num; /* Maximum AP number is 255 since the SELECT register is 8 bits */ - for (ap = 0; ap <= 255; ap++) { + for (ap_num = 0; ap_num <= 255; ap_num++) { /* read the IDR register of the Access Port */ uint32_t id_val = 0; - dap_ap_select(dap, ap); + dap_ap_select(dap, ap_num); int retval = dap_queue_ap_read(dap, AP_REG_IDR, &id_val); if (retval != ERROR_OK) @@ -992,25 +805,27 @@ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, uint8_t *ap_nu * 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) + * 16-13 : Class (0b1000=Mem-AP) + * 12-8 : Reserved + * 7-4 : AP Variant (non-zero for JTAG-AP) + * 3-0 : AP Type (0=JTAG-AP 1=AHB-AP 2=APB-AP 4=AXI-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*/ + ((id_val & IDR_JEP106) == IDR_JEP106_ARM) && /* Jedec codes match */ + ((id_val & IDR_TYPE) == 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_AXI_AP) ? "AXI-AP" : (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown", - ap, id_val); + ap_num, id_val); - *ap_num_out = ap; + *ap_out = &dap->ap[ap_num]; return ERROR_OK; } } @@ -1018,69 +833,49 @@ int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, uint8_t *ap_nu 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_AXI_AP) ? "AXI-AP" : (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown"); return ERROR_FAIL; } -int dap_get_debugbase(struct adiv5_dap *dap, int ap, - uint32_t *out_dbgbase, uint32_t *out_apid) +int dap_get_debugbase(struct adiv5_ap *ap, + uint32_t *dbgbase, uint32_t *apid) { + struct adiv5_dap *dap = ap->dap; uint32_t ap_old; int retval; - uint32_t dbgbase, apid; - - /* AP address is in bits 31:24 of DP_SELECT */ - if (ap >= 256) - return ERROR_COMMAND_SYNTAX_ERROR; - ap_old = dap->ap_current; - dap_ap_select(dap, ap); + ap_old = dap_ap_get_select(dap); + dap_ap_select(dap, ap->ap_num); - retval = dap_queue_ap_read(dap, AP_REG_BASE, &dbgbase); + retval = dap_queue_ap_read(dap, MEM_AP_REG_BASE, dbgbase); if (retval != ERROR_OK) return retval; - retval = dap_queue_ap_read(dap, AP_REG_IDR, &apid); + 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; - /* Excavate the device ID code */ - struct jtag_tap *tap = dap->jtag_info->tap; - while (tap != NULL) { - if (tap->hasidcode) - break; - tap = tap->next_tap; - } - if (tap == NULL || !tap->hasidcode) - return ERROR_OK; - dap_ap_select(dap, ap_old); - /* The asignment happens only here to prevent modification of these - * values before they are certain. */ - *out_dbgbase = dbgbase; - *out_apid = apid; - return ERROR_OK; } -int dap_lookup_cs_component(struct adiv5_dap *dap, int ap, - uint32_t dbgbase, uint8_t type, uint32_t *addr) +int dap_lookup_cs_component(struct adiv5_ap *ap, + uint32_t dbgbase, uint8_t type, uint32_t *addr, int32_t *idx) { + struct adiv5_dap *dap = ap->dap; uint32_t ap_old; uint32_t romentry, entry_offset = 0, component_base, devtype; - int retval = ERROR_FAIL; - - if (ap >= 256) - return ERROR_COMMAND_SYNTAX_ERROR; + int retval; - ap_old = dap->ap_current; - dap_ap_select(dap, ap); + *addr = 0; + ap_old = dap_ap_get_select(dap); do { - retval = mem_ap_read_atomic_u32(dap, (dbgbase&0xFFFFF000) | + retval = mem_ap_read_atomic_u32(ap, (dbgbase&0xFFFFF000) | entry_offset, &romentry); if (retval != ERROR_OK) return retval; @@ -1089,15 +884,33 @@ int dap_lookup_cs_component(struct adiv5_dap *dap, int ap, + (romentry & 0xFFFFF000); if (romentry & 0x1) { - retval = mem_ap_read_atomic_u32(dap, + uint32_t c_cid1; + retval = mem_ap_read_atomic_u32(ap, 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(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(ap, (component_base & 0xfffff000) | 0xfcc, &devtype); if (retval != ERROR_OK) return retval; if ((devtype & 0xff) == type) { - *addr = component_base; - retval = ERROR_OK; - break; + if (!*idx) { + *addr = component_base; + break; + } else + (*idx)--; } } entry_offset += 4; @@ -1105,12 +918,16 @@ int dap_lookup_cs_component(struct adiv5_dap *dap, int ap, dap_ap_select(dap, ap_old); - return retval; + if (!*addr) + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + + return ERROR_OK; } static int dap_rom_display(struct command_context *cmd_ctx, - struct adiv5_dap *dap, int ap, uint32_t dbgbase, int depth) + struct adiv5_ap *ap, uint32_t dbgbase, int depth) { + struct adiv5_dap *dap = ap->dap; int retval; uint32_t cid0, cid1, cid2, cid3, memtype, romentry; uint16_t entry_offset; @@ -1131,19 +948,19 @@ static int dap_rom_display(struct command_context *cmd_ctx, command_print(cmd_ctx, "\t%sROM table in legacy format", tabs); /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ - retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF0, &cid0); + retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFF0, &cid0); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF4, &cid1); + retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFF4, &cid1); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFF8, &cid2); + retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFF8, &cid2); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFFC, &cid3); + retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFFC, &cid3); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_u32(dap, (dbgbase&0xFFFFF000) | 0xFCC, &memtype); + retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFCC, &memtype); if (retval != ERROR_OK) return retval; retval = dap_run(dap); @@ -1165,7 +982,7 @@ static int dap_rom_display(struct command_context *cmd_ctx, /* 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); + retval = mem_ap_read_atomic_u32(ap, (dbgbase&0xFFFFF000) | entry_offset, &romentry); if (retval != ERROR_OK) return retval; command_print(cmd_ctx, "\t%sROMTABLE[0x%x] = 0x%" PRIx32 "", @@ -1174,49 +991,49 @@ static int dap_rom_display(struct command_context *cmd_ctx, 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; + uint32_t 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); + retval = mem_ap_read_atomic_u32(ap, 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); + retval = mem_ap_read_atomic_u32(ap, 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); + retval = mem_ap_read_atomic_u32(ap, 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); + retval = mem_ap_read_atomic_u32(ap, 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); + retval = mem_ap_read_atomic_u32(ap, 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); + retval = mem_ap_read_atomic_u32(ap, 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); + retval = mem_ap_read_atomic_u32(ap, 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); + retval = mem_ap_read_atomic_u32(ap, 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); + retval = mem_ap_read_atomic_u32(ap, component_base + 0xFFC, &c_cid3); if (retval != ERROR_OK) return retval; c_cid3 &= 0xff; @@ -1234,9 +1051,9 @@ static int dap_rom_display(struct command_context *cmd_ctx, if (((c_cid1 >> 4) & 0x0f) == 9) { uint32_t devtype; unsigned minor; - char *major = "Reserved", *subtype = "Reserved"; + const char *major = "Reserved", *subtype = "Reserved"; - retval = mem_ap_read_atomic_u32(dap, + retval = mem_ap_read_atomic_u32(ap, (component_base & 0xfffff000) | 0xfcc, &devtype); if (retval != ERROR_OK) @@ -1266,6 +1083,9 @@ static int dap_rom_display(struct command_context *cmd_ctx, case 2: subtype = "Buffer"; break; + case 3: + subtype = "Router"; + break; } break; case 2: @@ -1303,6 +1123,9 @@ static int dap_rom_display(struct command_context *cmd_ctx, case 4: subtype = "Bus"; break; + case 6: + subtype = "Software"; + break; } break; case 4: @@ -1317,6 +1140,9 @@ static int dap_rom_display(struct command_context *cmd_ctx, case 2: subtype = "Debug Auth"; break; + case 3: + subtype = "Power Requestor"; + break; } break; case 5: @@ -1334,6 +1160,35 @@ static int dap_rom_display(struct command_context *cmd_ctx, 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; } @@ -1384,6 +1239,18 @@ static int dap_rom_display(struct command_context *cmd_ctx, 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)"; @@ -1425,6 +1292,18 @@ static int dap_rom_display(struct command_context *cmd_ctx, 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)"; @@ -1453,6 +1332,14 @@ static int dap_rom_display(struct command_context *cmd_ctx, 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)"; @@ -1461,6 +1348,14 @@ static int dap_rom_display(struct command_context *cmd_ctx, 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)"; @@ -1469,7 +1364,12 @@ static int dap_rom_display(struct command_context *cmd_ctx, 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; @@ -1479,7 +1379,7 @@ static int dap_rom_display(struct command_context *cmd_ctx, /* ROM Table? */ if (((c_cid1 >> 4) & 0x0f) == 1) { - retval = dap_rom_display(cmd_ctx, dap, ap, component_base, depth + 1); + retval = dap_rom_display(cmd_ctx, ap, component_base, depth + 1); if (retval != ERROR_OK) return retval; } @@ -1495,54 +1395,55 @@ static int dap_rom_display(struct command_context *cmd_ctx, } static int dap_info_command(struct command_context *cmd_ctx, - struct adiv5_dap *dap, int ap) + struct adiv5_ap *ap) { int retval; - uint32_t dbgbase = 0, apid = 0; /* Silence gcc by initializing */ + uint32_t dbgbase, apid; int romtable_present = 0; uint8_t mem_ap; - uint32_t ap_old; - retval = dap_get_debugbase(dap, ap, &dbgbase, &apid); + /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ + retval = dap_get_debugbase(ap, &dbgbase, &apid); if (retval != ERROR_OK) return retval; - 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) { - case 0: - command_print(cmd_ctx, "\tType is JTAG-AP"); - break; - case 1: - command_print(cmd_ctx, "\tType is MEM-AP AHB"); - break; - case 2: - command_print(cmd_ctx, "\tType is MEM-AP APB"); - break; - default: - command_print(cmd_ctx, "\tUnknown AP type"); - break; - } + if (apid == 0) { + command_print(cmd_ctx, "No AP found at this ap 0x%x", ap->ap_num); + return ERROR_FAIL; + } - /* NOTE: a MEM-AP may have a single CoreSight component that's - * 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 ap 0x%x", ap); - - romtable_present = ((mem_ap) && (dbgbase != 0xFFFFFFFF)); - if (romtable_present) { - dap_rom_display(cmd_ctx, dap, ap, dbgbase, 0); - } else - command_print(cmd_ctx, "\tNo ROM table present"); - dap_ap_select(dap, ap_old); + switch (apid & (IDR_JEP106 | IDR_TYPE)) { + case IDR_JEP106_ARM | AP_TYPE_JTAG_AP: + command_print(cmd_ctx, "\tType is JTAG-AP"); + break; + case IDR_JEP106_ARM | AP_TYPE_AHB_AP: + command_print(cmd_ctx, "\tType is MEM-AP AHB"); + break; + case IDR_JEP106_ARM | AP_TYPE_APB_AP: + command_print(cmd_ctx, "\tType is MEM-AP APB"); + break; + case IDR_JEP106_ARM | AP_TYPE_AXI_AP: + command_print(cmd_ctx, "\tType is MEM-AP AXI"); + break; + default: + command_print(cmd_ctx, "\tUnknown AP type"); + break; + } + + /* NOTE: a MEM-AP may have a single CoreSight component that's + * not a ROM table ... or have no such components at all. + */ + mem_ap = (apid & IDR_CLASS) == AP_CLASS_MEM_AP; + if (mem_ap) { + command_print(cmd_ctx, "MEM-AP BASE 0x%8.8" PRIx32, dbgbase); + + romtable_present = dbgbase != 0xFFFFFFFF; + if (romtable_present) + dap_rom_display(cmd_ctx, ap, dbgbase, 0); + else + command_print(cmd_ctx, "\tNo ROM table present"); + } return ERROR_OK; } @@ -1560,12 +1461,14 @@ COMMAND_HANDLER(handle_dap_info_command) break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); + if (apsel >= 256) + return ERROR_COMMAND_SYNTAX_ERROR; break; default: return ERROR_COMMAND_SYNTAX_ERROR; } - return dap_info_command(CMD_CTX, dap, apsel); + return dap_info_command(CMD_CTX, &dap->ap[apsel]); } COMMAND_HANDLER(dap_baseaddr_command) @@ -1598,7 +1501,7 @@ COMMAND_HANDLER(dap_baseaddr_command) * though they're not common for now. This should * use the ID register to verify it's a MEM-AP. */ - retval = dap_queue_ap_read(dap, AP_REG_BASE, &baseaddr); + retval = dap_queue_ap_read(dap, MEM_AP_REG_BASE, &baseaddr); if (retval != ERROR_OK) return retval; retval = dap_run(dap); @@ -1620,7 +1523,7 @@ COMMAND_HANDLER(dap_memaccess_command) switch (CMD_ARGC) { case 0: - memaccess_tck = dap->memaccess_tck; + memaccess_tck = dap->ap[dap->apsel].memaccess_tck; break; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], memaccess_tck); @@ -1628,10 +1531,10 @@ COMMAND_HANDLER(dap_memaccess_command) default: return ERROR_COMMAND_SYNTAX_ERROR; } - dap->memaccess_tck = memaccess_tck; + dap->ap[dap->apsel].memaccess_tck = memaccess_tck; command_print(CMD_CTX, "memory bus access delay set to %" PRIi32 " tck", - dap->memaccess_tck); + dap->ap[dap->apsel].memaccess_tck); return ERROR_OK; } @@ -1681,7 +1584,7 @@ COMMAND_HANDLER(dap_apcsw_command) struct arm *arm = target_to_arm(target); struct adiv5_dap *dap = arm->dap; - uint32_t apcsw = dap->apcsw[dap->apsel], sprot = 0; + uint32_t apcsw = dap->ap[dap->apsel].csw_default, sprot = 0; switch (CMD_ARGC) { case 0: @@ -1701,7 +1604,7 @@ COMMAND_HANDLER(dap_apcsw_command) default: return ERROR_COMMAND_SYNTAX_ERROR; } - dap->apcsw[dap->apsel] = apcsw; + dap->ap[dap->apsel].csw_default = apcsw; return 0; }