armv7a: fix typo in cache_config help text
[fw/openocd] / src / target / adi_v5_jtag.c
index 48b4a7b8a0c2debb597fcb457a0ac1504b8d765c..7f61563f4e45aa15e6a18879bd3ad38b90530512 100644 (file)
@@ -23,7 +23,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.
  ***************************************************************************/
 
 /**
@@ -40,7 +40,6 @@
 #include "arm_adi_v5.h"
 #include <helper/time_support.h>
 
-
 /* JTAG instructions/registers for JTAG-DP and SWJ-DP */
 #define JTAG_DP_ABORT          0x8
 #define JTAG_DP_DPACC          0xA
@@ -51,6 +50,8 @@
 #define JTAG_ACK_OK_FAULT      0x2
 #define JTAG_ACK_WAIT          0x1
 
+static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack);
+
 /***************************************************************************
  *
  * DPACC and APACC scanchain access through JTAG-DP (or SWJ-DP)
  * @param ack points to where the three bit JTAG_ACK_* code will be stored
  */
 
-/* FIXME don't export ... this is a temporary workaround for the
- * mem_ap_read_buf_u32() mess, until it's no longer JTAG-specific.
- */
-int adi_jtag_dp_scan(struct adiv5_dap *dap,
+static 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)
 {
@@ -223,33 +221,32 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
                        DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
        if (retval != ERROR_OK)
                return retval;
-       if ((retval = jtag_execute_queue()) != ERROR_OK)
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
                return retval;
 
        dap->ack = dap->ack & 0x7;
 
        /* common code path avoids calling timeval_ms() */
-       if (dap->ack != JTAG_ACK_OK_FAULT)
-       {
+       if (dap->ack != JTAG_ACK_OK_FAULT) {
                long long then = timeval_ms();
 
-               while (dap->ack != JTAG_ACK_OK_FAULT)
-               {
-                       if (dap->ack == JTAG_ACK_WAIT)
-                       {
-                               if ((timeval_ms()-then) > 1000)
-                               {
-                                       /* NOTE:  this would be a good spot
-                                        * to use JTAG_DP_ABORT.
-                                        */
+               while (dap->ack != JTAG_ACK_OK_FAULT) {
+                       if (dap->ack == JTAG_ACK_WAIT) {
+                               if ((timeval_ms()-then) > 1000) {
                                        LOG_WARNING("Timeout (1000ms) waiting "
                                                "for ACK=OK/FAULT "
-                                               "in JTAG-DP transaction");
+                                               "in JTAG-DP transaction - aborting");
+
+                                       uint8_t ack;
+                                       int abort_ret = jtag_ap_q_abort(dap, &ack);
+
+                                       if (abort_ret != 0)
+                                               LOG_WARNING("Abort failed : return=%d ack=%d", abort_ret, ack);
+
                                        return ERROR_JTAG_DEVICE_ERROR;
                                }
-                       }
-                       else
-                       {
+                       } else {
                                LOG_WARNING("Invalid ACK %#x "
                                                "in JTAG-DP transaction",
                                                dap->ack);
@@ -260,7 +257,8 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
                                        DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
                        if (retval != ERROR_OK)
                                return retval;
-                       if ((retval = dap_run(dap)) != ERROR_OK)
+                       retval = jtag_execute_queue();
+                       if (retval != ERROR_OK)
                                return retval;
                        dap->ack = dap->ack & 0x7;
                }
@@ -269,18 +267,14 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
        /* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */
 
        /* Check for STICKYERR and STICKYORUN */
-       if (ctrlstat & (SSTICKYORUN | SSTICKYERR))
-       {
+       if (ctrlstat & (SSTICKYORUN | SSTICKYERR)) {
                LOG_DEBUG("jtag-dp: CTRL/STAT error, 0x%" PRIx32, ctrlstat);
                /* Check power to debug regions */
-               if ((ctrlstat & 0xf0000000) != 0xf0000000)
-               {
+               if ((ctrlstat & 0xf0000000) != 0xf0000000) {
                        retval = ahbap_debugport_init(dap);
                        if (retval != ERROR_OK)
                                return retval;
-               }
-               else
-               {
+               } else {
                        uint32_t mem_ap_csw, mem_ap_tar;
 
                        /* Maybe print information about last intended
@@ -314,7 +308,8 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
                                        DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
                        if (retval != ERROR_OK)
                                return retval;
-                       if ((retval = dap_run(dap)) != ERROR_OK)
+                       retval = jtag_execute_queue();
+                       if (retval != ERROR_OK)
                                return retval;
 
                        LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat);
@@ -329,13 +324,15 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
                        if (retval != ERROR_OK)
                                return retval;
 
-                       if ((retval = dap_run(dap)) != ERROR_OK)
+                       retval = jtag_execute_queue();
+                       if (retval != ERROR_OK)
                                return retval;
                        LOG_ERROR("MEM_AP_CSW 0x%" PRIx32 ", MEM_AP_TAR 0x%"
                                        PRIx32, mem_ap_csw, mem_ap_tar);
 
                }
-               if ((retval = dap_run(dap)) != ERROR_OK)
+               retval = jtag_execute_queue();
+               if (retval != ERROR_OK)
                        return retval;
                return ERROR_JTAG_DEVICE_ERROR;
        }
@@ -359,7 +356,7 @@ static int jtag_idcode_q_read(struct adiv5_dap *dap,
 
        fields[0].num_bits = 32;
        fields[0].out_value = NULL;
-       fields[0].in_value = (void *) data;
+       fields[0].in_value = (uint8_t *) data;
 
        jtag_add_dr_scan(jtag_info->tap, 1, fields, TAP_IDLE);
 
@@ -392,7 +389,7 @@ static int jtag_ap_q_bankselect(struct adiv5_dap *dap, unsigned reg)
                return ERROR_OK;
        dap->ap_bank_value = select_ap_bank;
 
-       select_ap_bank |= dap->apsel;
+       select_ap_bank |= dap->ap_current;
 
        return jtag_dp_q_write(dap, DP_SELECT, select_ap_bank);
 }
@@ -423,6 +420,40 @@ static int jtag_ap_q_write(struct adiv5_dap *dap, unsigned reg,
        return adi_jtag_ap_write_check(dap, reg, out_value_buf);
 }
 
+static int jtag_ap_q_read_block(struct adiv5_dap *dap, unsigned reg,
+               uint32_t blocksize, uint8_t *buffer)
+{
+       uint32_t readcount;
+       int retval = ERROR_OK;
+
+       /* Scan out first read */
+       retval = adi_jtag_dp_scan(dap, JTAG_DP_APACC, reg,
+                       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, reg,
+                               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);
+
+       return retval;
+}
+
 static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack)
 {
        /* for JTAG, this is the only valid ABORT register operation */
@@ -439,13 +470,14 @@ static int jtag_dp_run(struct adiv5_dap *dap)
  * part of DAP setup
 */
 const struct dap_ops jtag_dp_ops = {
-       .queue_idcode_read =    jtag_idcode_q_read,
-       .queue_dp_read =        jtag_dp_q_read,
-       .queue_dp_write =       jtag_dp_q_write,
-       .queue_ap_read =        jtag_ap_q_read,
-       .queue_ap_write =       jtag_ap_q_write,
-       .queue_ap_abort =       jtag_ap_q_abort,
-       .run =                  jtag_dp_run,
+       .queue_idcode_read   = jtag_idcode_q_read,
+       .queue_dp_read       = jtag_dp_q_read,
+       .queue_dp_write      = jtag_dp_q_write,
+       .queue_ap_read       = jtag_ap_q_read,
+       .queue_ap_write      = jtag_ap_q_write,
+       .queue_ap_read_block = jtag_ap_q_read_block,
+       .queue_ap_abort      = jtag_ap_q_abort,
+       .run                 = jtag_dp_run,
 };