jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / target / arm_adi_v5.h
index ce9155ae7fec663f180248a4f9b091b0960e1efa..92c3dbc3a666610322831bd9ffbaea134ad78d0f 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 /***************************************************************************
  *   Copyright (C) 2006 by Magnus Lundin                                   *
  *   lundin@mlu.mine.nu                                                    *
@@ -5,18 +7,7 @@
  *   Copyright (C) 2008 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
  *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ *   Copyright (C) 2019-2021, Ampere Computing LLC                         *
  ***************************************************************************/
 
 #ifndef OPENOCD_TARGET_ARM_ADI_V5_H
 
 #include <helper/list.h>
 #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 DP_DPIDR        BANK_REG(0x0, 0x0) /* DPv1+: ro */
 #define DP_ABORT        BANK_REG(0x0, 0x0) /* DPv1+: SWD: wo */
+#define DP_DPIDR1       BANK_REG(0x1, 0x0) /* DPv3: ro */
+#define DP_BASEPTR0     BANK_REG(0x2, 0x0) /* DPv3: ro */
+#define DP_BASEPTR1     BANK_REG(0x3, 0x0) /* DPv3: ro */
 #define DP_CTRL_STAT    BANK_REG(0x0, 0x4) /* DPv0+: rw */
 #define DP_DLCR         BANK_REG(0x1, 0x4) /* DPv1+: SWD: rw */
 #define DP_TARGETID     BANK_REG(0x2, 0x4) /* DPv2: ro */
 #define DP_DLPIDR       BANK_REG(0x3, 0x4) /* DPv2: ro */
 #define DP_EVENTSTAT    BANK_REG(0x4, 0x4) /* DPv2: ro */
+#define DP_SELECT1      BANK_REG(0x5, 0x4) /* DPv3: ro */
 #define DP_RESEND       BANK_REG(0x0, 0x8) /* DPv1+: SWD: ro */
 #define DP_SELECT       BANK_REG(0x0, 0x8) /* DPv0+: JTAG: rw; SWD: wo */
 #define DP_RDBUFF       BANK_REG(0x0, 0xC) /* DPv0+: ro */
 
 #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 */
 #define WDERRCLR        (1UL << 3) /* SWD-only */
 #define ORUNERRCLR      (1UL << 4) /* SWD-only */
 
+/* Fields of register DP_DPIDR1 */
+#define DP_DPIDR1_ASIZE_MASK    (0x7F)
+#define DP_DPIDR1_ERRMODE       BIT(7)
+
+/* Fields of register DP_BASEPTR0 */
+#define DP_BASEPTR0_VALID       BIT(0)
+
 /* Fields of the DP's CTRL/STAT register */
 #define CORUNDETECT     (1UL << 0)
 #define SSTICKYORUN     (1UL << 1)
 #define CSYSPWRUPREQ    (1UL << 30)
 #define CSYSPWRUPACK    (1UL << 31)
 
-#define DP_SELECT_APSEL 0xFF000000
-#define DP_SELECT_APBANK 0x000000F0
-#define DP_SELECT_DPBANK 0x0000000F
-#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */
+#define DP_DLPIDR_PROTVSN      1u
 
-#define DP_APSEL_MAX        (255)
-#define DP_APSEL_INVALID    (-1)
+#define ADIV5_DP_SELECT_APSEL  0xFF000000
+#define ADIV5_DP_SELECT_APBANK 0x000000F0
+#define DP_SELECT_DPBANK               0x0000000F
+/*
+ * Mask of AP ADDR in select cache, concatenating DP SELECT and DP_SELECT1.
+ * In case of ADIv5, the mask contains both APSEL and APBANKSEL fields.
+ */
+#define SELECT_AP_MASK                 (~(uint64_t)DP_SELECT_DPBANK)
+
+#define DP_APSEL_MAX                   (255) /* Strict limit for ADIv5, number of AP buffers for ADIv6 */
+#define DP_APSEL_INVALID               0xF00 /* more than DP_APSEL_MAX and not ADIv6 aligned 4k */
+
+#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_TAR         0x04
-#define MEM_AP_REG_TAR64       0x08            /* RW: Large Physical Address Extension */
-#define MEM_AP_REG_DRW         0x0C            /* RW: Data Read/Write register */
-#define MEM_AP_REG_BD0         0x10            /* RW: Banked Data register 0-3 */
-#define MEM_AP_REG_BD1         0x14
-#define MEM_AP_REG_BD2         0x18
-#define MEM_AP_REG_BD3         0x1C
-#define MEM_AP_REG_MBT         0x20            /* --: Memory Barrier Transfer register */
-#define MEM_AP_REG_BASE64      0xF0            /* RO: Debug Base Address (LA) register */
-#define MEM_AP_REG_CFG         0xF4            /* RO: Configuration register */
-#define MEM_AP_REG_BASE                0xF8            /* RO: Debug Base Address register */
+#define ADIV5_MEM_AP_REG_CSW    (0x00)
+#define ADIV5_MEM_AP_REG_TAR    (0x04)
+#define ADIV5_MEM_AP_REG_TAR64  (0x08)         /* RW: Large Physical Address Extension */
+#define ADIV5_MEM_AP_REG_DRW    (0x0C)         /* RW: Data Read/Write register */
+#define ADIV5_MEM_AP_REG_BD0    (0x10)         /* RW: Banked Data register 0-3 */
+#define ADIV5_MEM_AP_REG_BD1    (0x14)
+#define ADIV5_MEM_AP_REG_BD2    (0x18)
+#define ADIV5_MEM_AP_REG_BD3    (0x1C)
+#define ADIV5_MEM_AP_REG_MBT    (0x20)         /* --: Memory Barrier Transfer register */
+#define ADIV5_MEM_AP_REG_BASE64 (0xF0)         /* RO: Debug Base Address (LA) register */
+#define ADIV5_MEM_AP_REG_CFG    (0xF4)         /* RO: Configuration register */
+#define ADIV5_MEM_AP_REG_BASE   (0xF8)         /* RO: Debug Base Address register */
+
+#define ADIV6_MEM_AP_REG_CSW    (0xD00 + ADIV5_MEM_AP_REG_CSW)
+#define ADIV6_MEM_AP_REG_TAR    (0xD00 + ADIV5_MEM_AP_REG_TAR)
+#define ADIV6_MEM_AP_REG_TAR64  (0xD00 + ADIV5_MEM_AP_REG_TAR64)
+#define ADIV6_MEM_AP_REG_DRW    (0xD00 + ADIV5_MEM_AP_REG_DRW)
+#define ADIV6_MEM_AP_REG_BD0    (0xD00 + ADIV5_MEM_AP_REG_BD0)
+#define ADIV6_MEM_AP_REG_BD1    (0xD00 + ADIV5_MEM_AP_REG_BD1)
+#define ADIV6_MEM_AP_REG_BD2    (0xD00 + ADIV5_MEM_AP_REG_BD2)
+#define ADIV6_MEM_AP_REG_BD3    (0xD00 + ADIV5_MEM_AP_REG_BD3)
+#define ADIV6_MEM_AP_REG_MBT    (0xD00 + ADIV5_MEM_AP_REG_MBT)
+#define ADIV6_MEM_AP_REG_BASE64 (0xD00 + ADIV5_MEM_AP_REG_BASE64)
+#define ADIV6_MEM_AP_REG_CFG    (0xD00 + ADIV5_MEM_AP_REG_CFG)
+#define ADIV6_MEM_AP_REG_BASE   (0xD00 + ADIV5_MEM_AP_REG_BASE)
+
+#define MEM_AP_REG_CSW(dap)     (is_adiv6(dap) ? ADIV6_MEM_AP_REG_CSW    : ADIV5_MEM_AP_REG_CSW)
+#define MEM_AP_REG_TAR(dap)     (is_adiv6(dap) ? ADIV6_MEM_AP_REG_TAR    : ADIV5_MEM_AP_REG_TAR)
+#define MEM_AP_REG_TAR64(dap)   (is_adiv6(dap) ? ADIV6_MEM_AP_REG_TAR64  : ADIV5_MEM_AP_REG_TAR64)
+#define MEM_AP_REG_DRW(dap)     (is_adiv6(dap) ? ADIV6_MEM_AP_REG_DRW    : ADIV5_MEM_AP_REG_DRW)
+#define MEM_AP_REG_BD0(dap)     (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BD0    : ADIV5_MEM_AP_REG_BD0)
+#define MEM_AP_REG_BD1(dap)     (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BD1    : ADIV5_MEM_AP_REG_BD1)
+#define MEM_AP_REG_BD2(dap)     (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BD2    : ADIV5_MEM_AP_REG_BD2)
+#define MEM_AP_REG_BD3(dap)     (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BD3    : ADIV5_MEM_AP_REG_BD3)
+#define MEM_AP_REG_MBT(dap)     (is_adiv6(dap) ? ADIV6_MEM_AP_REG_MBT    : ADIV5_MEM_AP_REG_MBT)
+#define MEM_AP_REG_BASE64(dap)  (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BASE64 : ADIV5_MEM_AP_REG_BASE64)
+#define MEM_AP_REG_CFG(dap)     (is_adiv6(dap) ? ADIV6_MEM_AP_REG_CFG    : ADIV5_MEM_AP_REG_CFG)
+#define MEM_AP_REG_BASE(dap)    (is_adiv6(dap) ? ADIV6_MEM_AP_REG_BASE   : ADIV5_MEM_AP_REG_BASE)
+
 /* Generic AP register address */
-#define AP_REG_IDR                     0xFC            /* RO: Identification Register */
+#define ADIV5_AP_REG_IDR        (0xFC)         /* RO: Identification Register */
+#define ADIV6_AP_REG_IDR        (0xD00 + ADIV5_AP_REG_IDR)
+#define AP_REG_IDR(dap)         (is_adiv6(dap) ? ADIV6_AP_REG_IDR : ADIV5_AP_REG_IDR)
 
 /* Fields of the MEM-AP's CSW register */
 #define CSW_SIZE_MASK          7
 #define CSW_8BIT               0
 #define CSW_16BIT              1
 #define CSW_32BIT              2
+#define CSW_64BIT              3
+#define CSW_128BIT             4
+#define CSW_256BIT             5
 #define CSW_ADDRINC_MASK    (3UL << 4)
 #define CSW_ADDRINC_OFF     0UL
 #define CSW_ADDRINC_SINGLE  (1UL << 4)
 /* APB: initial value of csw_default */
 #define CSW_APB_DEFAULT         (CSW_DBGSWENABLE)
 
+/* Fields of the MEM-AP's CFG register */
+#define MEM_AP_REG_CFG_BE       BIT(0)
+#define MEM_AP_REG_CFG_LA       BIT(1)
+#define MEM_AP_REG_CFG_LD       BIT(2)
+#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 {
@@ -167,6 +240,7 @@ enum swd_special_seq {
        SWD_TO_JTAG,
        SWD_TO_DORMANT,
        DORMANT_TO_SWD,
+       DORMANT_TO_JTAG,
 };
 
 /**
@@ -180,9 +254,11 @@ struct adiv5_ap {
        struct adiv5_dap *dap;
 
        /**
-        * Number of this AP.
+        * ADIv5: Number of this AP (0~255)
+        * ADIv6: Base address of this AP (4k aligned)
+        * TODO: to be more coherent, it should be renamed apsel
         */
-       uint8_t ap_num;
+       uint64_t ap_num;
 
        /**
         * Default value for (MEM-AP) AP_REG_CSW register.
@@ -196,12 +272,32 @@ struct adiv5_ap {
         */
        uint32_t csw_value;
 
+       /**
+        * Save the supported CSW.Size data types for the MEM-AP.
+        * Each bit corresponds to a data type.
+        * 0b1 = Supported data size. 0b0 = Not supported.
+        * Bit 0 = Byte (8-bits)
+        * Bit 1 = Halfword (16-bits)
+        * Bit 2 = Word (32-bits) - always supported by spec.
+        * Bit 3 = Doubleword (64-bits)
+        * Bit 4 = 128-bits
+        * Bit 5 = 256-bits
+        */
+       uint32_t csw_size_supported_mask;
+       /**
+        * Probed CSW.Size data types for the MEM-AP.
+        * Each bit corresponds to a data type.
+        * 0b1 = Data size has been probed. 0b0 = Not yet probed.
+        * Bits assigned to sizes same way as above.
+        */
+       uint32_t csw_size_probed_mask;
+
        /**
         * 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 tar_value;
+       target_addr_t tar_value;
 
        /**
         * Configures how many extra tck clocks are added after starting a
@@ -213,13 +309,23 @@ struct adiv5_ap {
        uint32_t tar_autoincr_block;
 
        /* true if packed transfers are supported by the MEM-AP */
-       bool packed_transfers;
+       bool packed_transfers_supported;
+       bool packed_transfers_probed;
 
        /* true if unaligned memory access is not supported by the MEM-AP */
        bool unaligned_access_bad;
 
        /* true if tar_value is in sync with TAR register */
        bool tar_valid;
+
+       /* MEM AP configuration register indicating LPAE support */
+       uint32_t cfg_reg;
+
+       /* references counter */
+       unsigned int refcount;
+
+       /* AP referenced during config. Never put it, even when refcount reaches zero */
+       bool config_ap_never_release;
 };
 
 
@@ -258,13 +364,23 @@ struct adiv5_dap {
        struct adiv5_ap ap[DP_APSEL_MAX + 1];
 
        /* The current manually selected AP by the "dap apsel" command */
-       uint32_t apsel;
+       uint64_t apsel;
 
+       /** Cache for DP SELECT and SELECT1 (ADIv6) register. */
+       uint64_t select;
+       /** Validity of DP SELECT cache. false will force register rewrite */
+       bool select_valid;
+       bool select1_valid;     /* ADIv6 only */
        /**
-        * Cache for DP_SELECT register. A value of DP_SELECT_INVALID
-        * indicates no cached value and forces rewrite of the register.
+        * Partial DPBANKSEL validity for SWD only.
+        * ADIv6 line reset sets DP SELECT DPBANKSEL to zero,
+        * ADIv5 does not.
+        * We can rely on it for the banked DP register 0 also on ADIv5
+        * as ADIv5 has no mapping for DP reg 0 - it is always DPIDR.
+        * It is important to avoid setting DP SELECT in connection
+        * reset state before reading DPIDR.
         */
-       uint32_t select;
+       bool select_dpbanksel_valid;
 
        /* information about current pending SWjDP-AHBAP transaction */
        uint8_t  ack;
@@ -281,6 +397,10 @@ struct adiv5_dap {
         * swizzle appropriately. */
        bool ti_be_32_quirks;
 
+       /* The Nuvoton NPCX M4 has an issue with writing to non-4-byte-aligned mmios.
+        * The work around is to repeat the data in all 4 bytes of DRW */
+       bool nu_npcx_quirks;
+
        /**
         * STLINK adapter need to know if last AP operation was read or write, and
         * in case of write has to flush it with a dummy read from DP_RDBUFF
@@ -296,6 +416,24 @@ 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;
+
+       /**
+        * Record if enter in SWD required passing through DORMANT
+        */
+       bool switch_through_dormant;
+
+       /** Indicates ADI version (5, 6 or 0 for unknown) being used */
+       unsigned int adi_version;
+
+       /* ADIv6 only field indicating ROM Table address size */
+       unsigned int asize;
 };
 
 /**
@@ -306,6 +444,9 @@ struct adiv5_dap {
  * available until run().
  */
 struct dap_ops {
+       /** Optional; called once on the first enabled dap before connecting */
+       int (*pre_connect_init)(struct adiv5_dap *dap);
+
        /** connect operation for SWD */
        int (*connect)(struct adiv5_dap *dap);
 
@@ -340,25 +481,50 @@ 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 */
 };
 
+extern const struct dap_ops jtag_dp_ops;
+extern const struct dap_ops swd_dap_ops;
+
+/* Check the ap->cfg_reg Long Address field (bit 1)
+ *
+ * 0b0: The AP only supports physical addresses 32 bits or smaller
+ * 0b1: The AP supports physical addresses larger than 32 bits
+ *
+ * @param ap The AP used for reading.
+ *
+ * @return true for 64 bit, false for 32 bit
+ */
+static inline bool is_64bit_ap(struct adiv5_ap *ap)
+{
+       return (ap->cfg_reg & MEM_AP_REG_CFG_LA) != 0;
+}
+
+/**
+ * Check if DAP is ADIv6
+ *
+ * @param dap The DAP to test
+ *
+ * @return true for ADIv6, false for either ADIv5 or unknown version
+ */
+static inline bool is_adiv6(const struct adiv5_dap *dap)
+{
+       return dap->adi_version == 6;
+}
+
 /**
  * Send an adi-v5 sequence to the DAP.
  *
@@ -370,7 +536,7 @@ enum ap_type {
 static inline int dap_send_sequence(struct adiv5_dap *dap,
                enum swd_special_seq seq)
 {
-       assert(dap->ops != NULL);
+       assert(dap->ops);
        return dap->ops->send_sequence(dap, seq);
 }
 
@@ -389,7 +555,7 @@ static inline int dap_send_sequence(struct adiv5_dap *dap,
 static inline int dap_queue_dp_read(struct adiv5_dap *dap,
                unsigned reg, uint32_t *data)
 {
-       assert(dap->ops != NULL);
+       assert(dap->ops);
        return dap->ops->queue_dp_read(dap, reg, data);
 }
 
@@ -407,7 +573,7 @@ static inline int dap_queue_dp_read(struct adiv5_dap *dap,
 static inline int dap_queue_dp_write(struct adiv5_dap *dap,
                unsigned reg, uint32_t data)
 {
-       assert(dap->ops != NULL);
+       assert(dap->ops);
        return dap->ops->queue_dp_write(dap, reg, data);
 }
 
@@ -424,7 +590,11 @@ static inline int dap_queue_dp_write(struct adiv5_dap *dap,
 static inline int dap_queue_ap_read(struct adiv5_ap *ap,
                unsigned reg, uint32_t *data)
 {
-       assert(ap->dap->ops != NULL);
+       assert(ap->dap->ops);
+       if (ap->refcount == 0) {
+               ap->refcount = 1;
+               LOG_ERROR("BUG: refcount AP#0x%" PRIx64 " used without get", ap->ap_num);
+       }
        return ap->dap->ops->queue_ap_read(ap, reg, data);
 }
 
@@ -440,7 +610,11 @@ static inline int dap_queue_ap_read(struct adiv5_ap *ap,
 static inline int dap_queue_ap_write(struct adiv5_ap *ap,
                unsigned reg, uint32_t data)
 {
-       assert(ap->dap->ops != NULL);
+       assert(ap->dap->ops);
+       if (ap->refcount == 0) {
+               ap->refcount = 1;
+               LOG_ERROR("BUG: refcount AP#0x%" PRIx64 " used without get", ap->ap_num);
+       }
        return ap->dap->ops->queue_ap_write(ap, reg, data);
 }
 
@@ -457,7 +631,7 @@ static inline int dap_queue_ap_write(struct adiv5_ap *ap,
  */
 static inline int dap_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
 {
-       assert(dap->ops != NULL);
+       assert(dap->ops);
        return dap->ops->queue_ap_abort(dap, ack);
 }
 
@@ -473,13 +647,13 @@ static inline int dap_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
  */
 static inline int dap_run(struct adiv5_dap *dap)
 {
-       assert(dap->ops != NULL);
+       assert(dap->ops);
        return dap->ops->run(dap);
 }
 
 static inline int dap_sync(struct adiv5_dap *dap)
 {
-       assert(dap->ops != NULL);
+       assert(dap->ops);
        if (dap->ops->sync)
                return dap->ops->sync(dap);
        return ERROR_OK;
@@ -528,27 +702,27 @@ static inline int dap_dp_poll_register(struct adiv5_dap *dap, unsigned reg,
 
 /* Queued MEM-AP memory mapped single word transfers. */
 int mem_ap_read_u32(struct adiv5_ap *ap,
-               uint32_t address, uint32_t *value);
+               target_addr_t address, uint32_t *value);
 int mem_ap_write_u32(struct adiv5_ap *ap,
-               uint32_t address, uint32_t value);
+               target_addr_t address, uint32_t value);
 
 /* Synchronous MEM-AP memory mapped single word transfers. */
 int mem_ap_read_atomic_u32(struct adiv5_ap *ap,
-               uint32_t address, uint32_t *value);
+               target_addr_t address, uint32_t *value);
 int mem_ap_write_atomic_u32(struct adiv5_ap *ap,
-               uint32_t address, uint32_t value);
+               target_addr_t address, uint32_t value);
 
 /* Synchronous MEM-AP memory mapped bus block transfers. */
 int mem_ap_read_buf(struct adiv5_ap *ap,
-               uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address);
+               uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address);
 int mem_ap_write_buf(struct adiv5_ap *ap,
-               const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address);
+               const uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address);
 
 /* Synchronous, non-incrementing buffer functions for accessing fifos. */
 int mem_ap_read_buf_noincr(struct adiv5_ap *ap,
-               uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address);
+               uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address);
 int mem_ap_write_buf_noincr(struct adiv5_ap *ap,
-               const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address);
+               const uint8_t *buffer, uint32_t size, uint32_t count, target_addr_t address);
 
 /* Initialisation of the debug system, power domains and registers */
 int dap_dp_init(struct adiv5_dap *dap);
@@ -558,23 +732,35 @@ int mem_ap_init(struct adiv5_ap *ap);
 /* Invalidate cached DP select and cached TAR and CSW of all APs */
 void dap_invalidate_cache(struct adiv5_dap *dap);
 
-/* Probe the AP for ROM Table location */
-int dap_get_debugbase(struct adiv5_ap *ap,
-                       uint32_t *dbgbase, uint32_t *apid);
+/* read ADIv6 baseptr register */
+int adiv6_dap_read_baseptr(struct command_invocation *cmd, struct adiv5_dap *dap, target_addr_t *baseptr);
 
-/* Probe Access Ports to find a particular type */
-int dap_find_ap(struct adiv5_dap *dap,
+/* test if ap_num is valid, based on current knowledge of dap */
+bool is_ap_num_valid(struct adiv5_dap *dap, uint64_t ap_num);
+
+/* Probe Access Ports to find a particular type. Increment AP refcount */
+int dap_find_get_ap(struct adiv5_dap *dap,
                        enum ap_type type_to_find,
                        struct adiv5_ap **ap_out);
 
-static inline struct adiv5_ap *dap_ap(struct adiv5_dap *dap, uint8_t ap_num)
+/* Return AP with specified ap_num. Increment AP refcount */
+struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, uint64_t ap_num);
+
+/* Return AP with specified ap_num. Increment AP refcount and keep it non-zero */
+struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, uint64_t ap_num);
+
+/* Decrement AP refcount and release the AP when refcount reaches zero */
+int dap_put_ap(struct adiv5_ap *ap);
+
+/** Check if SWD multidrop configuration is valid */
+static inline bool dap_is_multidrop(struct adiv5_dap *dap)
 {
-       return &dap->ap[ap_num];
+       return dap->multidrop_dp_id_valid && dap->multidrop_instance_id_valid;
 }
 
 /* Lookup CoreSight component */
 int dap_lookup_cs_component(struct adiv5_ap *ap,
-                       uint32_t dbgbase, uint8_t type, uint32_t *addr, int32_t *idx);
+                       uint8_t type, target_addr_t *addr, int32_t idx);
 
 struct target;
 
@@ -597,16 +783,25 @@ extern const struct swd_driver *adiv5_dap_swd_driver(struct adiv5_dap *self);
 extern int dap_cleanup_all(void);
 
 struct adiv5_private_config {
-       int ap_num;
+       uint64_t ap_num;
        struct adiv5_dap *dap;
 };
 
 extern int adiv5_verify_config(struct adiv5_private_config *pc);
+
+enum adiv5_configure_dap_optional {
+       ADI_CONFIGURE_DAP_COMPULSORY = false,
+       ADI_CONFIGURE_DAP_OPTIONAL = true
+};
+
+extern int adiv5_jim_configure_ext(struct target *target, struct jim_getopt_info *goi,
+                                                                  struct adiv5_private_config *pc,
+                                                                  enum adiv5_configure_dap_optional optional);
 extern int adiv5_jim_configure(struct target *target, struct jim_getopt_info *goi);
 
 struct adiv5_mem_ap_spot {
        struct adiv5_dap *dap;
-       int ap_num;
+       uint64_t ap_num;
        uint32_t base;
 };
 

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)