-/* 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);
-
-/**
- * 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
- * @param addr_incr if true, increment the source address for each u32
- * 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, bool addr_incr)
-{
- int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;
- uint32_t adr = address;
- uint8_t *pBuffer = buffer;
- uint32_t incr_flag = CSW_ADDRINC_OFF;
-
- count >>= 2;
- wcount = count;
-
- 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;
-
- /* handle unaligned data at 4k boundary */
- if (blocksize == 0)
- blocksize = 1;
-
- if (addr_incr)
- incr_flag = CSW_ADDRINC_SINGLE;
-
- retval = dap_setup_accessport(dap, CSW_32BIT | incr_flag,
- address);
- if (retval != ERROR_OK)
- return retval;
-
- /* 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?
- */
-
- /* Scan out first read */
- retval = adi_jtag_dp_scan(dap, JTAG_DP_APACC, AP_REG_DRW,
- DPAP_READ, 0, NULL, NULL);
- 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;
- }
-
- /* 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);
- if (retval != ERROR_OK)
- return retval;
-
- 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;
- if (addr_incr)
- address += 4 * blocksize;
- buffer += 4 * blocksize;
- }
-
- /* 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++;
- }
- }
- }
-
- 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;
-
- wcount = count >> 1;
-
- 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_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;
- retval = dap_run(dap);
- if (retval != ERROR_OK) {
- LOG_WARNING("Block read error address 0x%" PRIx32 ", count 0x%x", address, count);
- return retval;
- }
-
- nbytes = MIN((readcount << 1), 4);
-
- for (i = 0; i < nbytes; i++) {
- *((uint8_t *)buffer) = (invalue >> 8 * (address & 0x3));
- buffer++;
- address++;
- }
-
- readcount -= (nbytes >> 1);
- } while (readcount);
- wcount -= blocksize;
- }
-
- return retval;
-}
-
-/**
- * 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.
- */
-int mem_ap_read_buf_u16(struct adiv5_dap *dap, uint8_t *buffer,
- int count, uint32_t address)
-{
- uint32_t invalue, i;
- int retval = ERROR_OK;
-
- if (count >= 4)
- return mem_ap_read_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;
- 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;
- }
- count -= 2;
- }
-
- return retval;
-}
-
-/* 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)
-{
- 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;
-
- do {
- retval = dap_queue_ap_read(dap, AP_REG_DRW, &invalue);
- if (retval != ERROR_OK)
- return retval;
- retval = dap_run(dap);
- if (retval != ERROR_OK) {
- LOG_WARNING("Block read error address 0x%" PRIx32 ", count 0x%x", address, count);
- return retval;
- }
-
- nbytes = MIN(readcount, 4);
-
- for (i = 0; i < nbytes; i++) {
- *((uint8_t *)buffer) = (invalue >> 8 * (address & 0x3));
- buffer++;
- address++;
- }
-
- readcount -= nbytes;
- } while (readcount);
- wcount -= blocksize;
- }
-
- return retval;
-}
-
-/**
- * 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)
-{
- uint32_t invalue;
- int retval = ERROR_OK;
-
- if (count >= 4)
- return mem_ap_read_buf_packed_u8(dap, buffer, count, address);
-
- 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);
- 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++;
- }
-
- 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_u8(struct adiv5_dap *swjdp, uint8_t ap,
- uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, ap);
- return mem_ap_read_buf_u8(swjdp, buffer, count, address);
-}
-
-int mem_ap_sel_read_buf_u16(struct adiv5_dap *swjdp, uint8_t ap,
- uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, ap);
- return mem_ap_read_buf_u16(swjdp, buffer, count, address);
-}
-
-int mem_ap_sel_read_buf_u32_noincr(struct adiv5_dap *swjdp, uint8_t ap,
- uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, ap);
- return mem_ap_read_buf_u32(swjdp, buffer, count, address, false);
-}
-
-int mem_ap_sel_read_buf_u32(struct adiv5_dap *swjdp, uint8_t ap,
- uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, ap);
- return mem_ap_read_buf_u32(swjdp, buffer, count, address, true);
-}
-
-int mem_ap_sel_write_buf_u8(struct adiv5_dap *swjdp, uint8_t ap,
- const uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, ap);
- return mem_ap_write_buf_u8(swjdp, buffer, count, address);
-}
-
-int mem_ap_sel_write_buf_u16(struct adiv5_dap *swjdp, uint8_t ap,
- const uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, ap);
- return mem_ap_write_buf_u16(swjdp, buffer, count, address);
-}
-
-int mem_ap_sel_write_buf_u32(struct adiv5_dap *swjdp, uint8_t ap,
- const uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, ap);
- return mem_ap_write_buf_u32(swjdp, buffer, count, address, true);
-}
-
-int mem_ap_sel_write_buf_u32_noincr(struct adiv5_dap *swjdp, uint8_t ap,
- const uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, ap);
- return mem_ap_write_buf_u32(swjdp, buffer, 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)
-
-/**
- *
- */
-int dap_syssec_kinetis_mdmap(struct adiv5_dap *dap)
-{
- uint32_t val;
- int retval;
- 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 %08X != 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
- */
- retval = dap_queue_ap_read(dap, MDM_REG_STAT, &val);
- if (retval != ERROR_OK)
- return retval;
- dap_run(dap);
-
- LOG_DEBUG("MDM_REG_STAT %08X", val);
-
- if ((val & (MDM_STAT_SYSSEC|MDM_STAT_FREADY)) != (MDM_STAT_FREADY)) {
- 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;
- }
-
- while (1) {
- 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 %08X", val);
-
- if ((val & 1))
- break;
- }
-
- while (1) {
- 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 %08X", 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 %08X", val);
-
- if (val == 0x00)
- break;
- }
- }
- }
-
- dap_ap_select(dap, 0);
-
- return ERROR_OK;
-}
-
-/** */
-struct dap_syssec_filter {
- /** */
- uint32_t idcode;
- /** */
- int (*dap_init)(struct adiv5_dap *dap);
-};
-
-/** */
-static struct dap_syssec_filter dap_syssec_filter_data[] = {
- { 0x4BA00477, dap_syssec_kinetis_mdmap }
-};
-
-/**
- *
- */
-int dap_syssec(struct adiv5_dap *dap)
-{
- 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: %08x", tap->idcode);
- dap_syssec_filter_data[i].dap_init(dap);
- }
- tap = tap->next_tap;
- }
- }
-
- return ERROR_OK;
-}
-
-/*--------------------------------------------------------------------------*/
-
-
-/* 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.
- *
- * @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)
-{
- 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
- */
- 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);
-
- /* DP initialization */
-
- 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);