#define CSW_MASTER_DEBUG (1 << 29) /* ? */
#define CSW_DBGSWENABLE (1 << 31)
-/* transaction mode */
-#define TRANS_MODE_NONE 0
-/* Transaction waits for previous to complete */
-#define TRANS_MODE_ATOMIC 1
-/* Freerunning transactions with delays and overrun checking */
-#define TRANS_MODE_COMPOSITE 2
-
/**
* This represents an ARM Debug Interface (v5) Debug Access Port (DAP).
* A DAP has two types of component: one Debug Port (DP), which is a
* transport agent; and at least one Access Port (AP), controlling
* resource access. Most common is a MEM-AP, for memory access.
*
+ * There are two basic DP transports: JTAG, and ARM's low pin-count SWD.
+ * Accordingly, this interface is responsible for hiding the transport
+ * differences so upper layer code can largely ignore them.
+ *
+ * When the chip is implemented with JTAG-DP or SW-DP, the transport is
+ * fixed as JTAG or SWD, respectively. Chips incorporating SWJ-DP permit
+ * a choice made at board design time (by only using the SWD pins), or
+ * as part of setting up a debug session (if all the dual-role JTAG/SWD
+ * signals are available).
+ *
* @todo Rename "swjdp_common" as "dap". Use of SWJ-DP is optional!
*/
struct swjdp_common
{
+ const struct dap_ops *ops;
+
struct arm_jtag *jtag_info;
/* Control config */
uint32_t dp_ctrl_stat;
- /* Support for several AP's in one DAP */
+
+ /**
+ * Cache for DP_SELECT bits identifying the current AP. A DAP may
+ * connect to multiple APs, such as one MEM-AP for general access,
+ * another reserved for accessing debug modules, and a JTAG-DP.
+ * "-1" indicates no cached value.
+ */
uint32_t apsel;
- /* Register select cache */
- uint32_t dp_select_value;
+
+ /**
+ * Cache for DP_SELECT bits identifying the current four-word AP
+ * register bank. This caches AP register addresss bits 7:4; JTAG
+ * and SWD access primitves pass address bits 3:2; bits 1:0 are zero.
+ * "-1" indicates no cached value.
+ */
+ uint32_t ap_bank_value;
+
+ /**
+ * Cache for (MEM-AP) AP_REG_CSW register value. This is written to
+ * configure an access mode, such as autoincrementing AP_REG_TAR during
+ * word access. "-1" indicates no cached value.
+ */
uint32_t ap_csw_value;
+
+ /**
+ * Cache for (MEM-AP) AP_REG_TAR register value This is written to
+ * configure the address being read or written
+ * "-1" indicates no cached value.
+ */
uint32_t ap_tar_value;
+
/* information about current pending SWjDP-AHBAP transaction */
- uint8_t trans_mode;
- uint8_t trans_rw;
uint8_t ack;
- /* extra tck clocks for memory bus access */
+
+ /**
+ * Configures how many extra tck clocks are added after starting a
+ * MEM-AP access before we try to read its status (and/or result).
+ */
uint32_t memaccess_tck;
/* Size of TAR autoincrement block, ARM ADI Specification requires at least 10 bits */
uint32_t tar_autoincr_block;
};
-/* Accessor function for currently selected DAP-AP number */
+/**
+ * Transport-neutral representation of queued DAP transactions, supporting
+ * both JTAG and SWD transports. All submitted transactions are logically
+ * queued, until the queue is executed by run(). Some implementations might
+ * execute transactions as soon as they're submitted, but no status is made
+ * availablue until run().
+ */
+struct dap_ops {
+ /** If the DAP transport isn't SWD, it must be JTAG. Upper level
+ * code may need to care about the difference in some cases.
+ */
+ bool is_swd;
+
+ /** Reads the DAP's IDCODe register. */
+ int (*queue_idcode_read)(struct swjdp_common *dap,
+ uint8_t *ack, uint32_t *data);
+
+ /** DP register read. */
+ int (*queue_dp_read)(struct swjdp_common *dap, unsigned reg,
+ uint32_t *data);
+ /** DP register write. */
+ int (*queue_dp_write)(struct swjdp_common *dap, unsigned reg,
+ uint32_t data);
+
+ /** AP register read. */
+ int (*queue_ap_read)(struct swjdp_common *dap, unsigned reg,
+ uint32_t *data);
+ /** AP register write. */
+ int (*queue_ap_write)(struct swjdp_common *dap, unsigned reg,
+ uint32_t data);
+ /** AP operation abort. */
+ int (*queue_ap_abort)(struct swjdp_common *dap, uint8_t *ack);
+
+ /** Executes all queued DAP operations. */
+ int (*run)(struct swjdp_common *dap);
+};
+
+/**
+ * Queue an IDCODE register read. This is primarily useful for SWD
+ * transports, where it is required as part of link initialization.
+ * (For JTAG, this register is read as part of scan chain setup.)
+ *
+ * @param dap The DAP used for reading.
+ * @param ack Pointer to where transaction status will be stored.
+ * @param data Pointer saying where to store the IDCODE value.
+ *
+ * @return ERROR_OK for success, else a fault code.
+ */
+static inline int dap_queue_idcode_read(struct swjdp_common *dap,
+ uint8_t *ack, uint32_t *data)
+{
+ return dap->ops->queue_idcode_read(dap, ack, data);
+}
+
+/**
+ * Queue a DP register read.
+ * Note that not all DP registers are readable; also, that JTAG and SWD
+ * have slight differences in DP register support.
+ *
+ * @param dap The DAP used for reading.
+ * @param reg The two-bit number of the DP register being read.
+ * @param data Pointer saying where to store the register's value
+ * (in host endianness).
+ *
+ * @return ERROR_OK for success, else a fault code.
+ */
+static inline int dap_queue_dp_read(struct swjdp_common *dap,
+ unsigned reg, uint32_t *data)
+{
+ return dap->ops->queue_dp_read(dap, reg, data);
+}
+
+/**
+ * Queue a DP register write.
+ * Note that not all DP registers are writable; also, that JTAG and SWD
+ * have slight differences in DP register support.
+ *
+ * @param dap The DAP used for writing.
+ * @param reg The two-bit number of the DP register being written.
+ * @param data Value being written (host endianness)
+ *
+ * @return ERROR_OK for success, else a fault code.
+ */
+static inline int dap_queue_dp_write(struct swjdp_common *dap,
+ unsigned reg, uint32_t data)
+{
+ return dap->ops->queue_dp_write(dap, reg, data);
+}
+
+/**
+ * Queue an AP register read.
+ *
+ * @param dap The DAP used for reading.
+ * @param reg The number of the AP register being read.
+ * @param data Pointer saying where to store the register's value
+ * (in host endianness).
+ *
+ * @return ERROR_OK for success, else a fault code.
+ */
+static inline int dap_queue_ap_read(struct swjdp_common *dap,
+ unsigned reg, uint32_t *data)
+{
+ return dap->ops->queue_ap_read(dap, reg, data);
+}
+
+/**
+ * Queue an AP register write.
+ *
+ * @param dap The DAP used for writing.
+ * @param reg The number of the AP register being written.
+ * @param data Value being written (host endianness)
+ *
+ * @return ERROR_OK for success, else a fault code.
+ */
+static inline int dap_queue_ap_write(struct swjdp_common *dap,
+ unsigned reg, uint32_t data)
+{
+ return dap->ops->queue_ap_write(dap, reg, data);
+}
+
+/**
+ * Queue an AP abort operation. The current AP transaction is aborted,
+ * including any update of the transaction counter. The AP is left in
+ * an unknown state (so it must be re-initialized). For use only after
+ * the AP has reported WAIT status for an extended period.
+ *
+ * @param dap The DAP used for writing.
+ * @param ack Pointer to where transaction status will be stored.
+ *
+ * @return ERROR_OK for success, else a fault code.
+ */
+static inline int dap_queue_ap_abort(struct swjdp_common *dap, uint8_t *ack)
+{
+ return dap->ops->queue_ap_abort(dap, ack);
+}
+
+/**
+ * Perform all queued DAP operations, and clear any errors posted in the
+ * CTRL_STAT register when they are done. Note that if more than one AP
+ * operation will be queued, one of the first operations in the queue
+ * should probably enable CORUNDETECT in the CTRL/STAT register.
+ *
+ * @param dap The DAP used.
+ *
+ * @return ERROR_OK for success, else a fault code.
+ */
+static inline int dap_run(struct swjdp_common *dap)
+{
+ return dap->ops->run(dap);
+}
+
+/** Accessor for currently selected DAP-AP number (0..255) */
static inline uint8_t dap_ap_get_select(struct swjdp_common *swjdp)
{
return (uint8_t)(swjdp ->apsel >> 24);
}
-/* Queued transactions -- use with care */
+/* AP selection applies to future AP transactions */
+void dap_ap_select(struct swjdp_common *dap,uint8_t apsel);
+
+/* Queued AP transactions */
int dap_setup_accessport(struct swjdp_common *swjdp,
uint32_t csw, uint32_t tar);
-int dap_ap_select(struct swjdp_common *swjdp,uint8_t apsel);
-int dap_ap_write_reg_u32(struct swjdp_common *swjdp,
- uint32_t addr, uint32_t value);
-int dap_ap_read_reg_u32(struct swjdp_common *swjdp,
- uint32_t addr, uint32_t *value);
-/* Queued transactions must be completed with swjdp_transaction_endcheck() */
-int swjdp_transaction_endcheck(struct swjdp_common *swjdp);
-
-/* MEM-AP memory mapped bus single uint32_t register transfers, without endcheck */
+/* Queued MEM-AP memory mapped single word transfers */
int mem_ap_read_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t *value);
int mem_ap_write_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t value);
-/* MEM-AP memory mapped bus transfers, single registers, complete transactions */
+/* Synchronous MEM-AP memory mapped single word transfers */
int mem_ap_read_atomic_u32(struct swjdp_common *swjdp,
uint32_t address, uint32_t *value);
int mem_ap_write_atomic_u32(struct swjdp_common *swjdp,
DAP_COMMAND_HANDLER(dap_apsel_command);
DAP_COMMAND_HANDLER(dap_apid_command);
+struct target;
+
+/* Put debug link into SWD mode */
+int dap_to_swd(struct target *target);
+
+/* Put debug link into JTAG mode */
+int dap_to_jtag(struct target *target);
+
#endif