summaryrefslogtreecommitdiff
path: root/src/target/arm_adi_v5.c
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2010-03-02 22:41:59 -0800
committerDavid Brownell <dbrownell@users.sourceforge.net>2010-03-02 22:41:59 -0800
commitdb6c994642f29b7d47abb4233494a606fbb65369 (patch)
tree48ef0ba30b5018f6409eb498426d4977ab80e965 /src/target/arm_adi_v5.c
parentd72e90ae4b070cc08799e800c111dd422ac6b1a4 (diff)
downloadopenocd+libswd-db6c994642f29b7d47abb4233494a606fbb65369.tar.gz
openocd+libswd-db6c994642f29b7d47abb4233494a606fbb65369.tar.bz2
openocd+libswd-db6c994642f29b7d47abb4233494a606fbb65369.tar.xz
openocd+libswd-db6c994642f29b7d47abb4233494a606fbb65369.zip
ARM: start abstracting ADIv5 transports (JTAG/SWD)
To support both JTAG and SWD, ADIv5 needs DAP operations which are transport-neutral, instead being of JTAG-specific. This patch: - Defines such a transport-neutral interface, abstracting access to DP and AP registers through a conceptual queue of operations. - Builds the first implementation of such a transport with the existing JTAG-specific code. In contrast to the current JTAG-only interface, the interface adds support for two previously-missing (and unused) DAP operations: - aborting the current AP transaction (untested); - reading the IDCODE register (tested) ... required for SWD init. The choice of transports may be fixed at the chip, board, or JTAG/SWD adapter level. Or if all the relevant hardware supports both transport options, the choice may be made at runtime, This patch provides basic infrastructure to support whichever choice is made. The current "JTAG-only" transport choice policy will necessarily continue for now, until SWD support becomes available in OpenOCD. Later patches start phasing out JTAG-specific calls in favor of transport-neutral calls. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Diffstat (limited to 'src/target/arm_adi_v5.c')
-rw-r--r--src/target/arm_adi_v5.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index 115ccf12..735308a4 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -350,6 +350,11 @@ int jtagdp_transaction_endcheck(struct swjdp_common *swjdp)
* *
***************************************************************************/
+/* FIXME remove dap_dp_{read,write}_reg() ... these should become the
+ * bodies of the JTAG implementations of dap_queue_dp_{read,write}() and
+ * callers should switch over to the transport-neutral calls.
+ */
+
static int dap_dp_write_reg(struct swjdp_common *swjdp,
uint32_t value, uint8_t reg_addr)
{
@@ -403,6 +408,12 @@ static int dap_ap_bankselect(struct swjdp_common *swjdp, uint32_t ap_reg)
return ERROR_OK;
}
+/* FIXME remove dap_ap_{read,write}_reg() and dap_ap_write_reg_u32()
+ * ... these should become the bodies of the JTAG implementations of
+ * dap_queue_ap_{read,write}(), then all their current callers should
+ * switch over to the transport-neutral calls.
+ */
+
static int dap_ap_write_reg(struct swjdp_common *swjdp,
uint32_t reg_addr, uint8_t *out_value_buf)
{
@@ -1143,6 +1154,107 @@ int mem_ap_read_buf_u8(struct swjdp_common *swjdp, uint8_t *buffer,
return retval;
}
+/*--------------------------------------------------------------------------*/
+
+static int jtag_idcode_q_read(struct swjdp_common *dap,
+ uint8_t *ack, uint32_t *data)
+{
+ struct arm_jtag *jtag_info = dap->jtag_info;
+ int retval;
+ struct scan_field fields[1];
+
+ jtag_set_end_state(TAP_IDLE);
+
+ /* This is a standard JTAG operation -- no DAP tweakage */
+ retval = arm_jtag_set_instr(jtag_info, JTAG_DP_IDCODE, NULL);
+ if (retval != ERROR_OK)
+ return retval;
+
+ fields[0].tap = jtag_info->tap;
+ fields[0].num_bits = 32;
+ fields[0].out_value = NULL;
+ fields[0].in_value = (void *) data;
+
+ jtag_add_dr_scan(1, fields, jtag_get_end_state());
+ retval = jtag_get_error();
+ if (retval != ERROR_OK)
+ return retval;
+
+ jtag_add_callback(arm_le_to_h_u32,
+ (jtag_callback_data_t) data);
+
+ return retval;
+}
+
+static int jtag_dp_q_read(struct swjdp_common *dap, unsigned reg,
+ uint32_t *data)
+{
+ return dap_dp_read_reg(dap, data, reg);
+}
+
+static int jtag_dp_q_write(struct swjdp_common *dap, unsigned reg,
+ uint32_t data)
+{
+ return dap_dp_write_reg(dap, data, reg);
+}
+
+static int jtag_ap_q_bankselect(struct swjdp_common *dap, unsigned reg)
+{
+ uint32_t select = reg & 0x000000F0;
+
+ if (select == dap->ap_bank_value)
+ return ERROR_OK;
+ dap->ap_bank_value = select;
+
+ select |= dap->apsel;
+
+ return jtag_dp_q_write(dap, DP_SELECT, select);
+}
+
+static int jtag_ap_q_read(struct swjdp_common *dap, unsigned reg,
+ uint32_t *data)
+{
+ int retval = jtag_ap_q_bankselect(dap, reg);
+
+ if (retval != ERROR_OK)
+ return retval;
+ return dap_ap_read_reg_u32(dap, reg, data);
+}
+
+static int jtag_ap_q_write(struct swjdp_common *dap, unsigned reg,
+ uint32_t data)
+{
+ int retval = jtag_ap_q_bankselect(dap, reg);
+
+ if (retval != ERROR_OK)
+ return retval;
+ return dap_ap_write_reg_u32(dap, reg, data);
+}
+
+static int jtag_ap_q_abort(struct swjdp_common *dap, uint8_t *ack)
+{
+ /* for JTAG, this is the only valid ABORT register operation */
+ return adi_jtag_dp_scan_u32(dap, JTAG_DP_ABORT,
+ 0, DPAP_WRITE, 1, NULL, ack);
+}
+
+static int jtag_dp_run(struct swjdp_common *dap)
+{
+ return jtagdp_transaction_endcheck(dap);
+}
+
+static 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,
+};
+
+/*--------------------------------------------------------------------------*/
+
/**
* 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
@@ -1164,6 +1276,9 @@ int ahbap_debugport_init(struct swjdp_common *swjdp)
LOG_DEBUG(" ");
+ /* JTAG-DP or SWJ-DP, in JTAG mode */
+ swjdp->ops = &jtag_dp_ops;
+
/* Default MEM-AP setup.
*
* REVISIT AP #0 may be an inappropriate default for this.