#ifndef TARGET_ADIV5_H
#define TARGET_ADIV5_H
#include "general.h"
#include "jtag_scan.h"
#include "swd.h"
#if PC_HOSTED == 1
#include "platform.h"
#endif
#define ADIV5_APnDP 0x100U
#define ADIV5_DP_REG(x) (x)
#define ADIV5_AP_REG(x) (ADIV5_APnDP | (x))
#define ADIV5_DP_DPIDR ADIV5_DP_REG(0x0U)
#define ADIV5_DP_ABORT ADIV5_DP_REG(0x0U)
#define ADIV5_DP_CTRLSTAT ADIV5_DP_REG(0x4U)
#define ADIV5_DP_TARGETID ADIV5_DP_REG(0x4U)
#define ADIV5_DP_SELECT ADIV5_DP_REG(0x8U)
#define ADIV5_DP_RDBUFF ADIV5_DP_REG(0xcU)
#define ADIV5_DP_TARGETSEL ADIV5_DP_REG(0xcU)
#define ADIV5_SWD_TO_JTAG_SELECT_SEQUENCE 0xe73cU
#define ADIV5_JTAG_TO_SWD_SELECT_SEQUENCE 0xe79eU
#define ADIV5_SELECTION_ALERT_SEQUENCE_0 0x6209f392U
#define ADIV5_SELECTION_ALERT_SEQUENCE_1 0x86852d95U
#define ADIV5_SELECTION_ALERT_SEQUENCE_2 0xe3ddafe9U
#define ADIV5_SELECTION_ALERT_SEQUENCE_3 0x19bc0ea2U
#define ADIV5_ACTIVATION_CODE_ARM_SWD_DP 0x1aU
#define ADIV5_ACTIVATION_CODE_ARM_JTAG_DP 0x0aU
#define ADIV5_DP_DPIDR_REVISION_OFFSET 28U
#define ADIV5_DP_DPIDR_REVISION_MASK (0xfU << ADIV5_DP_DPIDR_VERSION_OFFSET)
#define ADIV5_DP_DPIDR_PARTNO_OFFSET 20U
#define ADIV5_DP_DPIDR_PARTNO_MASK (0xffU << ADIV5_DP_DPIDR_PARTNO_OFFSET)
#define ADIV5_DP_DPIDR_MINDP_OFFSET 16U
#define ADIV5_DP_DPIDR_MINDP (1U << ADIV5_DP_DPIDR_MINDP_OFFSET)
#define ADIV5_DP_DPIDR_VERSION_OFFSET 12U
#define ADIV5_DP_DPIDR_VERSION_MASK (0xfU << ADIV5_DP_DPIDR_VERSION_OFFSET)
#define ADIV5_DP_DPIDR_VERSION_DPv1 (1U << ADIV5_DP_DPIDR_VERSION_OFFSET)
#define ADIV5_DP_DPIDR_VERSION_DPv2 (2U << ADIV5_DP_DPIDR_VERSION_OFFSET)
#define ADIV5_DP_DPIDR_DESIGNER_OFFSET 1U
#define ADIV5_DP_DPIDR_DESIGNER_MASK (0x7ffU << ADIV5_DP_DPIDR_DESIGNER_OFFSET)
#define ADIV5_DP_BANK0 0U
#define ADIV5_DP_BANK1 1U
#define ADIV5_DP_BANK2 2U
#define ADIV5_DP_BANK3 3U
#define ADIV5_DP_BANK4 4U
#define ADIV5_DP_TARGETID_TREVISION_OFFSET 28U
#define ADIV5_DP_TARGETID_TREVISION_MASK (0xfU << ADIV5_DP_TARGETID_TREVISION_OFFSET)
#define ADIV5_DP_TARGETID_TPARTNO_OFFSET 12U
#define ADIV5_DP_TARGETID_TPARTNO_MASK (0xffffU << ADIV5_DP_TARGETID_TPARTNO_OFFSET)
#define ADIV5_DP_TARGETID_TDESIGNER_OFFSET 1U
#define ADIV5_DP_TARGETID_TDESIGNER_MASK (0x7ffU << ADIV5_DP_TARGETID_TDESIGNER_OFFSET)
#define ADIV5_DP_TARGETSEL_TINSTANCE_OFFSET 28U
#define ADIV5_DP_TARGETSEL_TINSTANCE_MASK (0xfU << ADIV5_DP_TARGETSEL_TINSTANCE_OFFSET)
#define ADIV5_DP_TARGETSEL_TPARTNO_OFFSET 12U
#define ADIV5_DP_TARGETSEL_TPARTNO_MASK (0xffffU << ADIV5_DP_TARGETSEL_TPARTNO_OFFSET)
#define ADIV5_DP_TARGETSEL_TDESIGNER_OFFSET 1U
#define ADIV5_DP_TARGETSEL_TDESIGNER_MASK (0x7ffU << ADIV5_DP_TARGETSEL_TDESIGNER_OFFSET)
#define ADIV5_DP_DESIGNER_JEP106_CONT_OFFSET 7U
#define ADIV5_DP_DESIGNER_JEP106_CONT_MASK (0xfU << ADIV5_DP_DESIGNER_JEP106_CONT_OFFSET)
#define ADIV5_DP_DESIGNER_JEP106_CODE_MASK (0x7fU)
#define ADIV5_DP_ABORT_ORUNERRCLR (1U << 4U)
#define ADIV5_DP_ABORT_WDERRCLR (1U << 3U)
#define ADIV5_DP_ABORT_STKERRCLR (1U << 2U)
#define ADIV5_DP_ABORT_STKCMPCLR (1U << 1U)
#define ADIV5_DP_ABORT_DAPABORT (1U << 0U)
#define ADIV5_DP_CTRLSTAT_CSYSPWRUPACK (1U << 31U)
#define ADIV5_DP_CTRLSTAT_CSYSPWRUPREQ (1U << 30U)
#define ADIV5_DP_CTRLSTAT_CDBGPWRUPACK (1U << 29U)
#define ADIV5_DP_CTRLSTAT_CDBGPWRUPREQ (1U << 28U)
#define ADIV5_DP_CTRLSTAT_CDBGRSTACK (1U << 27U)
#define ADIV5_DP_CTRLSTAT_CDBGRSTREQ (1U << 26U)
#define ADIV5_DP_CTRLSTAT_TRNCNT(x) ((x & 0xfffU) << 12U)
#define ADIV5_DP_CTRLSTAT_MASKLANE
#define ADIV5_DP_CTRLSTAT_WDATAERR (1U << 7U)
#define ADIV5_DP_CTRLSTAT_READOK (1U << 6U)
#define ADIV5_DP_CTRLSTAT_STICKYERR (1U << 5U)
#define ADIV5_DP_CTRLSTAT_STICKYCMP (1U << 4U)
#define ADIV5_DP_CTRLSTAT_TRNMODE_MASK (3U << 2U)
#define ADIV5_DP_CTRLSTAT_STICKYORUN (1U << 1U)
#define ADIV5_DP_CTRLSTAT_ORUNDETECT (1U << 0U)
#define ADIV5_DP_CTRLSTAT_ERRMASK 0xf0000032U
#define ADIV5_AP_CSW ADIV5_AP_REG(0x00U)
#define ADIV5_AP_TAR ADIV5_AP_REG(0x04U)
#define ADIV5_AP_DRW ADIV5_AP_REG(0x0cU)
#define ADIV5_AP_DB(x) ADIV5_AP_REG(0x10U + (4U * (x)))
#define ADIV5_AP_CFG ADIV5_AP_REG(0xf4U)
#define ADIV5_AP_BASE ADIV5_AP_REG(0xf8U)
#define ADIV5_AP_IDR ADIV5_AP_REG(0xfcU)
#define ADIV5_AP_CSW_DBGSWENABLE (1U << 31U)
#define ADIV5_AP_CSW_HNOSEC (1U << 30U)
#define ADIV5_AP_CSW_MASTERTYPE_DEBUG (1U << 29U)
#define ADIV5_AP_CSW_HPROT1 (1U << 25U)
#define ADIV5_AP_CSW_SPIDEN (1U << 23U)
#define ADIV5_AP_CSW_MTE (1U << 15U)
#define ADIV5_AP_CSW_TRINPROG (1U << 7U)
#define ADIV5_AP_CSW_DEVICEEN (1U << 6U)
#define ADIV5_AP_CSW_ADDRINC_NONE (0U << 4U)
#define ADIV5_AP_CSW_ADDRINC_SINGLE (1U << 4U)
#define ADIV5_AP_CSW_ADDRINC_PACKED (2U << 4U)
#define ADIV5_AP_CSW_ADDRINC_MASK (3U << 4U)
#define ADIV5_AP_CSW_SIZE_BYTE (0U << 0U)
#define ADIV5_AP_CSW_SIZE_HALFWORD (1U << 0U)
#define ADIV5_AP_CSW_SIZE_WORD (2U << 0U)
#define ADIV5_AP_CSW_SIZE_MASK (7U << 0U)
#define ADIV5_AP_BASE_BASEADDR UINT32_C(0xfffff000)
#define ADIV5_AP_BASE_PRESENT (1U << 0U)
#define ADIV5_AP_IDR_REVISION_OFFSET 28U
#define ADIV5_AP_IDR_REVISION_MASK 0xf0000000U
#define ADIV5_AP_IDR_REVISION(idr) (((idr)&ADIV5_AP_IDR_REVISION_MASK) >> ADIV5_AP_IDR_REVISION_OFFSET)
#define ADIV5_AP_IDR_DESIGNER_OFFSET 17U
#define ADIV5_AP_IDR_DESIGNER_MASK 0x0ffe0000U
#define ADIV5_AP_IDR_DESIGNER(idr) (((idr)&ADIV5_AP_IDR_DESIGNER_MASK) >> ADIV5_AP_IDR_DESIGNER_OFFSET)
#define ADIV5_AP_IDR_CLASS_OFFSET 13U
#define ADIV5_AP_IDR_CLASS_MASK 0x0001e000U
#define ADIV5_AP_IDR_CLASS(idr) (((idr)&ADIV5_AP_IDR_CLASS_MASK) >> ADIV5_AP_IDR_CLASS_OFFSET)
#define ADIV5_AP_IDR_VARIANT_OFFSET 4U
#define ADIV5_AP_IDR_VARIANT_MASK 0x000000f0U
#define ADIV5_AP_IDR_VARIANT(idr) (((idr)&ADIV5_AP_IDR_VARIANT_MASK) >> ADIV5_AP_IDR_VARIANT_OFFSET)
#define ADIV5_AP_IDR_TYPE_OFFSET 0U
#define ADIV5_AP_IDR_TYPE_MASK 0x0000000fU
#define ADIV5_AP_IDR_TYPE(idr) ((idr)&ADIV5_AP_IDR_TYPE_MASK)
#define ADIV5_ROM_MEMTYPE 0xfccU
#define ADIV5_ROM_MEMTYPE_SYSMEM (1U << 0U)
#define ADIV5_ROM_ROMENTRY_PRESENT (1U << 0U)
#define ADIV5_ROM_ROMENTRY_OFFSET UINT32_C(0xfffff000)
#define JTAG_IDCODE_VERSION_OFFSET 28U
#define JTAG_IDCODE_VERSION_MASK (0xfU << JTAG_IDCODE_VERSION_OFFSET)
#define JTAG_IDCODE_PARTNO_OFFSET 12U
#define JTAG_IDCODE_PARTNO_MASK (0xffffU << JTAG_IDCODE_PARTNO_OFFSET)
#define JTAG_IDCODE_DESIGNER_OFFSET 1U
#define JTAG_IDCODE_DESIGNER_MASK (0x7ffU << JTAG_IDCODE_DESIGNER_OFFSET)
#define JTAG_IDCODE_PARTNO_DPv0 0xba00U
#define ADIV5_LOW_WRITE 0
#define ADIV5_LOW_READ 1
#define SWDP_ACK_OK 0x01U
#define SWDP_ACK_WAIT 0x02U
#define SWDP_ACK_FAULT 0x04U
#define SWDP_ACK_NO_RESPONSE 0x07U
typedef struct adiv5_access_port adiv5_access_port_s;
typedef struct adiv5_debug_port adiv5_debug_port_s;
struct adiv5_debug_port {
int refcnt;
bool (*dp_low_write)(uint16_t addr, const uint32_t data);
uint32_t (*dp_read)(adiv5_debug_port_s *dp, uint16_t addr);
uint32_t (*error)(adiv5_debug_port_s *dp, bool protocol_recovery);
uint32_t (*low_access)(adiv5_debug_port_s *dp, uint8_t RnW, uint16_t addr, uint32_t value);
void (*abort)(adiv5_debug_port_s *dp, uint32_t abort);
#if PC_HOSTED == 1
void (*ap_regs_read)(adiv5_access_port_s *ap, void *data);
uint32_t (*ap_reg_read)(adiv5_access_port_s *ap, uint8_t reg_num);
void (*ap_reg_write)(adiv5_access_port_s *ap, uint8_t num, uint32_t value);
void (*read_block)(uint32_t addr, uint8_t *data, int size);
void (*dap_write_block_sized)(uint32_t addr, uint8_t *data, int size, align_e align);
#endif
uint32_t (*ap_read)(adiv5_access_port_s *ap, uint16_t addr);
void (*ap_write)(adiv5_access_port_s *ap, uint16_t addr, uint32_t value);
void (*mem_read)(adiv5_access_port_s *ap, void *dest, uint32_t src, size_t len);
void (*mem_write)(adiv5_access_port_s *ap, uint32_t dest, const void *src, size_t len, align_e align);
uint8_t dev_index;
uint8_t fault;
uint8_t instance;
uint32_t targetsel;
uint8_t version;
bool mindp;
uint16_t designer_code;
uint16_t partno;
uint16_t target_designer_code;
uint16_t target_partno;
};
struct adiv5_access_port {
int refcnt;
adiv5_debug_port_s *dp;
uint8_t apsel;
uint32_t idr;
uint32_t base;
uint32_t csw;
uint32_t ap_cortexm_demcr;
uint32_t ap_storage;
uint16_t designer_code;
uint16_t partno;
};
uint8_t make_packet_request(uint8_t RnW, uint16_t addr);
#if PC_HOSTED == 0
static inline uint32_t adiv5_dp_read(adiv5_debug_port_s *dp, uint16_t addr)
{
return dp->dp_read(dp, addr);
}
static inline uint32_t adiv5_dp_error(adiv5_debug_port_s *dp)
{
return dp->error(dp, false);
}
static inline uint32_t adiv5_dp_low_access(adiv5_debug_port_s *dp, uint8_t RnW, uint16_t addr, uint32_t value)
{
return dp->low_access(dp, RnW, addr, value);
}
static inline void adiv5_dp_abort(adiv5_debug_port_s *dp, uint32_t abort)
{
dp->abort(dp, abort);
}
static inline uint32_t adiv5_ap_read(adiv5_access_port_s *ap, uint16_t addr)
{
return ap->dp->ap_read(ap, addr);
}
static inline void adiv5_ap_write(adiv5_access_port_s *ap, uint16_t addr, uint32_t value)
{
ap->dp->ap_write(ap, addr, value);
}
static inline void adiv5_mem_read(adiv5_access_port_s *ap, void *dest, uint32_t src, size_t len)
{
ap->dp->mem_read(ap, dest, src, len);
}
static inline void adiv5_mem_write_sized(
adiv5_access_port_s *ap, uint32_t dest, const void *src, size_t len, align_e align)
{
ap->dp->mem_write(ap, dest, src, len, align);
}
static inline void adiv5_dp_write(adiv5_debug_port_s *dp, uint16_t addr, uint32_t value)
{
dp->low_access(dp, ADIV5_LOW_WRITE, addr, value);
}
#else
uint32_t adiv5_dp_read(adiv5_debug_port_s *dp, uint16_t addr);
uint32_t adiv5_dp_error(adiv5_debug_port_s *dp);
uint32_t adiv5_dp_low_access(adiv5_debug_port_s *dp, uint8_t RnW, uint16_t addr, uint32_t value);
void adiv5_dp_abort(adiv5_debug_port_s *dp, uint32_t abort);
uint32_t adiv5_ap_read(adiv5_access_port_s *ap, uint16_t addr);
void adiv5_ap_write(adiv5_access_port_s *ap, uint16_t addr, uint32_t value);
void adiv5_mem_read(adiv5_access_port_s *ap, void *dest, uint32_t src, size_t len);
void adiv5_mem_write_sized(adiv5_access_port_s *ap, uint32_t dest, const void *src, size_t len, align_e align);
void adiv5_dp_write(adiv5_debug_port_s *dp, uint16_t addr, uint32_t value);
#endif
static inline uint32_t adiv5_dp_recoverable_access(adiv5_debug_port_s *dp, uint8_t rnw, uint16_t addr, uint32_t value)
{
const uint32_t result = dp->low_access(dp, rnw, addr, value);
if (dp->fault == SWDP_ACK_NO_RESPONSE) {
uint32_t response;
swd_proc.seq_in_parity(&response, 32);
DEBUG_WARN("Recovering and re-trying access\n");
dp->error(dp, true);
return dp->low_access(dp, rnw, addr, value);
}
return result;
}
void adiv5_dp_init(adiv5_debug_port_s *dp);
void bmda_adiv5_dp_init(adiv5_debug_port_s *dp);
adiv5_access_port_s *adiv5_new_ap(adiv5_debug_port_s *dp, uint8_t apsel);
void remote_jtag_dev(const jtag_dev_s *jtag_dev);
void adiv5_ap_ref(adiv5_access_port_s *ap);
void adiv5_ap_unref(adiv5_access_port_s *ap);
void bmda_add_jtag_dev(uint32_t dev_index, const jtag_dev_s *jtag_dev);
void adiv5_jtag_dp_handler(uint8_t jd_index);
#if PC_HOSTED == 1
void bmda_jtag_dp_init(adiv5_debug_port_s *dp);
bool bmda_swd_dp_init(adiv5_debug_port_s *dp);
#endif
void adiv5_mem_write(adiv5_access_port_s *ap, uint32_t dest, const void *src, size_t len);
uint64_t adiv5_ap_read_pidr(adiv5_access_port_s *ap, uint32_t addr);
void *adiv5_unpack_data(void *dest, uint32_t src, uint32_t val, align_e align);
const void *adiv5_pack_data(uint32_t dest, const void *src, uint32_t *data, align_e align);
void ap_mem_access_setup(adiv5_access_port_s *ap, uint32_t addr, align_e align);
void adiv5_mem_write_bytes(adiv5_access_port_s *ap, uint32_t dest, const void *src, size_t len, align_e align);
void advi5_mem_read_bytes(adiv5_access_port_s *ap, void *dest, uint32_t src, size_t len);
void firmware_ap_write(adiv5_access_port_s *ap, uint16_t addr, uint32_t value);
uint32_t firmware_ap_read(adiv5_access_port_s *ap, uint16_t addr);
uint32_t firmware_swdp_low_access(adiv5_debug_port_s *dp, uint8_t RnW, uint16_t addr, uint32_t value);
uint32_t fw_adiv5_jtagdp_low_access(adiv5_debug_port_s *dp, uint8_t RnW, uint16_t addr, uint32_t value);
uint32_t firmware_swdp_read(adiv5_debug_port_s *dp, uint16_t addr);
uint32_t fw_adiv5_jtagdp_read(adiv5_debug_port_s *dp, uint16_t addr);
uint32_t firmware_swdp_error(adiv5_debug_port_s *dp, bool protocol_recovery);
void firmware_swdp_abort(adiv5_debug_port_s *dp, uint32_t abort);
void adiv5_jtagdp_abort(adiv5_debug_port_s *dp, uint32_t abort);
void adiv5_swd_multidrop_scan(adiv5_debug_port_s *dp, uint32_t targetid);
uint32_t adiv5_dp_read_dpidr(adiv5_debug_port_s *dp);
#endif