target/adi_v5_swd: add support for SWD multidrop
[fw/openocd] / src / target / arm_adi_v5.h
index 73ceea03f0718914f0f84e302b355f1080863205..758cfa096d1984e896adac25011286eaca3b6442 100644 (file)
@@ -33,6 +33,9 @@
 #include "arm_jtag.h"
 #include "helper/bits.h"
 
+/* JEP106 ID for ARM */
+#define ARM_ID 0x23B
+
 /* three-bit ACK values for SWD access (sent LSB first) */
 #define SWD_ACK_OK    0x1
 #define SWD_ACK_WAIT  0x2
 
 #define DLCR_TO_TRN(dlcr) ((uint32_t)(1 + ((3 & (dlcr)) >> 8))) /* 1..4 clocks */
 
+/* Fields of DP_DPIDR register */
+#define DP_DPIDR_VERSION_SHIFT 12
+#define DP_DPIDR_VERSION_MASK  (0xFUL << DP_DPIDR_VERSION_SHIFT)
+
 /* Fields of the DP's AP ABORT register */
 #define DAPABORT        (1UL << 0)
 #define STKCMPCLR       (1UL << 1) /* SWD-only */
@@ -86,6 +93,8 @@
 #define CSYSPWRUPREQ    (1UL << 30)
 #define CSYSPWRUPACK    (1UL << 31)
 
+#define DP_DLPIDR_PROTVSN      1u
+
 #define DP_SELECT_APSEL 0xFF000000
 #define DP_SELECT_APBANK 0x000000F0
 #define DP_SELECT_DPBANK 0x0000000F
 #define DP_APSEL_MAX        (255)
 #define DP_APSEL_INVALID    (-1)
 
+#define DP_TARGETSEL_INVALID 0xFFFFFFFFU
+#define DP_TARGETSEL_DPID_MASK 0x0FFFFFFFU
+#define DP_TARGETSEL_INSTANCEID_MASK 0xF0000000U
+#define DP_TARGETSEL_INSTANCEID_SHIFT 28
+
 
 /* MEM-AP register addresses */
 #define MEM_AP_REG_CSW         0x00
 #define MEM_AP_REG_CFG_INVALID  0xFFFFFFF8
 
 /* Fields of the MEM-AP's IDR register */
-#define IDR_REV     (0xFUL << 28)
-#define IDR_JEP106  (0x7FFUL << 17)
-#define IDR_CLASS   (0xFUL << 13)
-#define IDR_VARIANT (0xFUL << 4)
-#define IDR_TYPE    (0xFUL << 0)
-
-#define IDR_JEP106_ARM 0x04760000
+#define AP_REG_IDR_REVISION_MASK        (0xF0000000)
+#define AP_REG_IDR_REVISION_SHIFT       (28)
+#define AP_REG_IDR_DESIGNER_MASK        (0x0FFE0000)
+#define AP_REG_IDR_DESIGNER_SHIFT       (17)
+#define AP_REG_IDR_CLASS_MASK           (0x0001E000)
+#define AP_REG_IDR_CLASS_SHIFT          (13)
+#define AP_REG_IDR_VARIANT_MASK         (0x000000F0)
+#define AP_REG_IDR_VARIANT_SHIFT        (4)
+#define AP_REG_IDR_TYPE_MASK            (0x0000000F)
+#define AP_REG_IDR_TYPE_SHIFT           (0)
+
+#define AP_REG_IDR_CLASS_NONE           (0x0)
+#define AP_REG_IDR_CLASS_COM            (0x1)
+#define AP_REG_IDR_CLASS_MEM_AP         (0x8)
+
+#define AP_REG_IDR_VALUE(d, c, t) (\
+       (((d) << AP_REG_IDR_DESIGNER_SHIFT) & AP_REG_IDR_DESIGNER_MASK) | \
+       (((c) << AP_REG_IDR_CLASS_SHIFT) & AP_REG_IDR_CLASS_MASK) | \
+       (((t) << AP_REG_IDR_TYPE_SHIFT) & AP_REG_IDR_TYPE_MASK) \
+)
+
+#define AP_TYPE_MASK (AP_REG_IDR_DESIGNER_MASK | AP_REG_IDR_CLASS_MASK | AP_REG_IDR_TYPE_MASK)
 
 /* FIXME: not SWD specific; should be renamed, e.g. adiv5_special_seq */
 enum swd_special_seq {
@@ -173,6 +202,7 @@ enum swd_special_seq {
        SWD_TO_JTAG,
        SWD_TO_DORMANT,
        DORMANT_TO_SWD,
+       DORMANT_TO_JTAG,
 };
 
 /**
@@ -305,6 +335,13 @@ struct adiv5_dap {
        /** Flag saying whether to ignore the syspwrupack flag in DAP. Some devices
         *  do not set this bit until later in the bringup sequence */
        bool ignore_syspwrupack;
+
+       /** Value to select DP in SWD multidrop mode or DP_TARGETSEL_INVALID */
+       uint32_t multidrop_targetsel;
+       /** TPARTNO and TDESIGNER fields of multidrop_targetsel have been configured */
+       bool multidrop_dp_id_valid;
+       /** TINSTANCE field of multidrop_targetsel has been configured */
+       bool multidrop_instance_id_valid;
 };
 
 /**
@@ -349,23 +386,19 @@ struct dap_ops {
        void (*quit)(struct adiv5_dap *dap);
 };
 
-/*
- * Access Port classes
- */
-enum ap_class {
-       AP_CLASS_NONE   = 0x00000,  /* No class defined */
-       AP_CLASS_MEM_AP = 0x10000,  /* MEM-AP */
-};
-
 /*
  * Access Port types
  */
 enum ap_type {
-       AP_TYPE_JTAG_AP = 0x0,  /* JTAG-AP - JTAG master for controlling other JTAG devices */
-       AP_TYPE_AHB3_AP = 0x1,  /* AHB3 Memory-AP */
-       AP_TYPE_APB_AP  = 0x2,  /* APB Memory-AP */
-       AP_TYPE_AXI_AP  = 0x4,  /* AXI Memory-AP */
-       AP_TYPE_AHB5_AP = 0x5,  /* AHB5 Memory-AP. */
+       AP_TYPE_JTAG_AP  = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_NONE,   0),  /* JTAG-AP */
+       AP_TYPE_COM_AP   = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_COM,    0),  /* COM-AP */
+       AP_TYPE_AHB3_AP  = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 1),  /* AHB3 Memory-AP */
+       AP_TYPE_APB_AP   = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 2),  /* APB2 or APB3 Memory-AP */
+       AP_TYPE_AXI_AP   = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 4),  /* AXI3 or AXI4 Memory-AP */
+       AP_TYPE_AHB5_AP  = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 5),  /* AHB5 Memory-AP */
+       AP_TYPE_APB4_AP  = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 6),  /* APB4 Memory-AP */
+       AP_TYPE_AXI5_AP  = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 7),  /* AXI5 Memory-AP */
+       AP_TYPE_AHB5H_AP = AP_REG_IDR_VALUE(ARM_ID, AP_REG_IDR_CLASS_MEM_AP, 8),  /* AHB5 with enhanced HPROT Memory-AP */
 };
 
 /* Check the ap->cfg_reg Long Address field (bit 1)
@@ -595,6 +628,12 @@ static inline struct adiv5_ap *dap_ap(struct adiv5_dap *dap, uint8_t ap_num)
        return &dap->ap[ap_num];
 }
 
+/** Check if SWD multidrop configuration is valid */
+static inline bool dap_is_multidrop(struct adiv5_dap *dap)
+{
+       return dap->multidrop_dp_id_valid && dap->multidrop_instance_id_valid;
+}
+
 /* Lookup CoreSight component */
 int dap_lookup_cs_component(struct adiv5_ap *ap,
                        target_addr_t dbgbase, uint8_t type, target_addr_t *addr, int32_t *idx);