-/**
- * 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;
-
- 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;
-
- retval = dap_setup_accessport(dap, CSW_32BIT | CSW_ADDRINC_SINGLE,
- 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;
- 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;
- 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);
-
- 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;
- 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, 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 apsel,
- uint32_t address, uint32_t *value)
-{
- dap_ap_select(swjdp, apsel);
- return mem_ap_read_u32(swjdp, address, value);
-}
-
-int mem_ap_sel_write_u32(struct adiv5_dap *swjdp, uint8_t apsel,
- uint32_t address, uint32_t value)
-{
- dap_ap_select(swjdp, apsel);
- return mem_ap_write_u32(swjdp, address, value);
-}
-
-int mem_ap_sel_read_atomic_u32(struct adiv5_dap *swjdp, uint8_t apsel,
- uint32_t address, uint32_t *value)
-{
- dap_ap_select(swjdp, apsel);
- return mem_ap_read_atomic_u32(swjdp, address, value);
-}
-
-int mem_ap_sel_write_atomic_u32(struct adiv5_dap *swjdp, uint8_t apsel,
- uint32_t address, uint32_t value)
-{
- dap_ap_select(swjdp, apsel);
- return mem_ap_write_atomic_u32(swjdp, address, value);
-}
-
-int mem_ap_sel_read_buf_u8(struct adiv5_dap *swjdp, uint8_t apsel,
- uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, apsel);
- return mem_ap_read_buf_u8(swjdp, buffer, count, address);
-}
-
-int mem_ap_sel_read_buf_u16(struct adiv5_dap *swjdp, uint8_t apsel,
- uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, apsel);
- return mem_ap_read_buf_u16(swjdp, buffer, count, address);
-}
-
-int mem_ap_sel_read_buf_u32(struct adiv5_dap *swjdp, uint8_t apsel,
- uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, apsel);
- return mem_ap_read_buf_u32(swjdp, buffer, count, address);
-}
-
-int mem_ap_sel_write_buf_u8(struct adiv5_dap *swjdp, uint8_t apsel,
- uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, apsel);
- return mem_ap_write_buf_u8(swjdp, buffer, count, address);
-}
-
-int mem_ap_sel_write_buf_u16(struct adiv5_dap *swjdp, uint8_t apsel,
- uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, apsel);
- return mem_ap_write_buf_u16(swjdp, buffer, count, address);
-}
-
-int mem_ap_sel_write_buf_u32(struct adiv5_dap *swjdp, uint8_t apsel,
- uint8_t *buffer, int count, uint32_t address)
-{
- dap_ap_select(swjdp, apsel);
- return mem_ap_write_buf_u32(swjdp, buffer, count, address);
-}
-
-
-/*--------------------------------------------------------------------------*/
-
-
-/* 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->apsel = !0;
- dap_ap_select(dap, 0);
-
- /* DP initialization */
-
- retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);