target: restructure dap support
[fw/openocd] / src / target / arm_adi_v5.c
index a0d0f4ef042f7ed6d3297ee4405b6605762a76ef..2b7d7b22d7d96b22288f5a946a5cbe4b39cf6652 100644 (file)
@@ -76,6 +76,7 @@
 #include <helper/jep106.h>
 #include <helper/time_support.h>
 #include <helper/list.h>
+#include <helper/jim-nvp.h>
 
 /* ARM ADI Specification requires at least 10 bits used for TAR autoincrement  */
 
@@ -221,7 +222,8 @@ int mem_ap_read_u32(struct adiv5_ap *ap, uint32_t address,
        /* Use banked addressing (REG_BDx) to avoid some link traffic
         * (updating TAR) when reading several consecutive addresses.
         */
-       retval = mem_ap_setup_transfer(ap, CSW_32BIT | CSW_ADDRINC_OFF,
+       retval = mem_ap_setup_transfer(ap,
+                       CSW_32BIT | (ap->csw_value & CSW_ADDRINC_MASK),
                        address & 0xFFFFFFF0);
        if (retval != ERROR_OK)
                return retval;
@@ -272,7 +274,8 @@ int mem_ap_write_u32(struct adiv5_ap *ap, uint32_t address,
        /* Use banked addressing (REG_BDx) to avoid some link traffic
         * (updating TAR) when writing several consecutive addresses.
         */
-       retval = mem_ap_setup_transfer(ap, CSW_32BIT | CSW_ADDRINC_OFF,
+       retval = mem_ap_setup_transfer(ap,
+                       CSW_32BIT | (ap->csw_value & CSW_ADDRINC_MASK),
                        address & 0xFFFFFFF0);
        if (retval != ERROR_OK)
                return retval;
@@ -323,7 +326,7 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz
        const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;
        uint32_t csw_size;
        uint32_t addr_xor;
-       int retval;
+       int retval = ERROR_OK;
 
        /* TI BE-32 Quirks mode:
         * Writes on big-endian TMS570 behave very strangely. Observed behavior:
@@ -376,33 +379,34 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz
                /* How many source bytes each transfer will consume, and their location in the DRW,
                 * depends on the type of transfer and alignment. See ARM document IHI0031C. */
                uint32_t outvalue = 0;
+               uint32_t drw_byte_idx = address;
                if (dap->ti_be_32_quirks) {
                        switch (this_size) {
                        case 4:
-                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
-                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
-                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
-                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx & 3) ^ addr_xor);
                                break;
                        case 2:
-                               outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (address++ & 3) ^ addr_xor);
-                               outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (address++ & 3) ^ addr_xor);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (drw_byte_idx++ & 3) ^ addr_xor);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (drw_byte_idx & 3) ^ addr_xor);
                                break;
                        case 1:
-                               outvalue |= (uint32_t)*buffer++ << 8 * (0 ^ (address++ & 3) ^ addr_xor);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (0 ^ (drw_byte_idx & 3) ^ addr_xor);
                                break;
                        }
                } else {
                        switch (this_size) {
                        case 4:
-                               outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
-                               outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3);
                                /* fallthrough */
                        case 2:
-                               outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3);
                                /* fallthrough */
                        case 1:
-                               outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
+                               outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3);
                        }
                }
 
@@ -413,6 +417,8 @@ static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t siz
                        break;
 
                mem_ap_update_tar_cache(ap);
+               if (addrinc)
+                       address += this_size;
        }
 
        /* REVISIT: Might want to have a queued version of this function that does not run. */
@@ -450,7 +456,7 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint
        const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;
        uint32_t csw_size;
        uint32_t address = adr;
-       int retval;
+       int retval = ERROR_OK;
 
        /* TI BE-32 Quirks mode:
         * Reads on big-endian TMS570 behave strangely differently than writes.
@@ -474,7 +480,8 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint
        /* Allocate buffer to hold the sequence of DRW reads that will be made. This is a significant
         * over-allocation if packed transfers are going to be used, but determining the real need at
         * this point would be messy. */
-       uint32_t *read_buf = malloc(count * sizeof(uint32_t));
+       uint32_t *read_buf = calloc(count, sizeof(uint32_t));
+       /* Multiplication count * sizeof(uint32_t) may overflow, calloc() is safe */
        uint32_t *read_ptr = read_buf;
        if (read_buf == NULL) {
                LOG_ERROR("Failed to allocate read buffer");
@@ -507,7 +514,8 @@ static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint
                        break;
 
                nbytes -= this_size;
-               address += this_size;
+               if (addrinc)
+                       address += this_size;
 
                mem_ap_update_tar_cache(ap);
        }
@@ -607,33 +615,8 @@ int mem_ap_write_buf_noincr(struct adiv5_ap *ap,
 
 #define DAP_POWER_DOMAIN_TIMEOUT (10)
 
-/* FIXME don't import ... just initialize as
- * part of DAP transport setup
-*/
-extern const struct dap_ops jtag_dp_ops;
-
 /*--------------------------------------------------------------------------*/
 
-/**
- * Create a new DAP
- */
-struct adiv5_dap *dap_init(void)
-{
-       struct adiv5_dap *dap = calloc(1, sizeof(struct adiv5_dap));
-       int i;
-       /* Set up with safe defaults */
-       for (i = 0; i <= 255; i++) {
-               dap->ap[i].dap = dap;
-               dap->ap[i].ap_num = i;
-               /* memaccess_tck max is 255 */
-               dap->ap[i].memaccess_tck = 255;
-               /* Number of bits for tar autoincrement, impl. dep. at least 10 */
-               dap->ap[i].tar_autoincr_block = (1<<10);
-       }
-       INIT_LIST_HEAD(&dap->cmd_journal);
-       return dap;
-}
-
 /**
  * Invalidate cached DP select and cached TAR and CSW of all APs
  */
@@ -660,14 +643,7 @@ int dap_dp_init(struct adiv5_dap *dap)
 {
        int retval;
 
-       LOG_DEBUG(" ");
-       /* JTAG-DP or SWJ-DP, in JTAG mode
-        * ... for SWD mode this is patched as part
-        * of link switchover
-        * FIXME: This should already be setup by the respective transport specific DAP creation.
-        */
-       if (!dap->ops)
-               dap->ops = &jtag_dp_ops;
+       LOG_DEBUG("%s", adiv5_dap_name(dap));
 
        dap_invalidate_cache(dap);
 
@@ -1034,12 +1010,14 @@ static const struct {
        { ARM_ID, 0x4a2, "Cortex-A57 ROM",             "(ROM Table)", },
        { ARM_ID, 0x4a3, "Cortex-A53 ROM",             "(v7 Memory Map ROM Table)", },
        { ARM_ID, 0x4a4, "Cortex-A72 ROM",             "(ROM Table)", },
+       { ARM_ID, 0x4a9, "Cortex-A9 ROM",              "(ROM Table)", },
        { ARM_ID, 0x4af, "Cortex-A15 ROM",             "(ROM Table)", },
        { ARM_ID, 0x4c0, "Cortex-M0+ ROM",             "(ROM Table)", },
        { ARM_ID, 0x4c3, "Cortex-M3 ROM",              "(ROM Table)", },
        { ARM_ID, 0x4c4, "Cortex-M4 ROM",              "(ROM Table)", },
        { ARM_ID, 0x4c7, "Cortex-M7 PPB ROM",          "(Private Peripheral Bus ROM Table)", },
        { ARM_ID, 0x4c8, "Cortex-M7 ROM",              "(ROM Table)", },
+       { ARM_ID, 0x4b5, "Cortex-R5 ROM",              "(ROM Table)", },
        { ARM_ID, 0x470, "Cortex-M1 ROM",              "(ROM Table)", },
        { ARM_ID, 0x471, "Cortex-M0 ROM",              "(ROM Table)", },
        { ARM_ID, 0x906, "CoreSight CTI",              "(Cross Trigger)", },
@@ -1080,7 +1058,7 @@ static const struct {
        { ARM_ID, 0x9a9, "Cortex-M7 TPIU",             "(Trace Port Interface Unit)", },
        { ARM_ID, 0x9ae, "Cortex-A17 PMU",             "(Performance Monitor Unit)", },
        { ARM_ID, 0x9af, "Cortex-A15 PMU",             "(Performance Monitor Unit)", },
-       { ARM_ID, 0x9b7, "Cortex-R7 PMU",              "(Performance Monitoring Unit)", },
+       { ARM_ID, 0x9b7, "Cortex-R7 PMU",              "(Performance Monitor Unit)", },
        { ARM_ID, 0x9d3, "Cortex-A53 PMU",             "(Performance Monitor Unit)", },
        { ARM_ID, 0x9d7, "Cortex-A57 PMU",             "(Performance Monitor Unit)", },
        { ARM_ID, 0x9d8, "Cortex-A72 PMU",             "(Performance Monitor Unit)", },
@@ -1103,6 +1081,11 @@ static const struct {
        { 0x0c1,  0x1ed, "XMC1000 ROM",                "(ROM Table)" },
        { 0x0E5,  0x000, "SHARC+/Blackfin+",           "", },
        { 0x0F0,  0x440, "Qualcomm QDSS Component v1", "(Qualcomm Designed CoreSight Component v1)", },
+       { 0x3eb,  0x181, "Tegra 186 ROM",              "(ROM Table)", },
+       { 0x3eb,  0x211, "Tegra 210 ROM",              "(ROM Table)", },
+       { 0x3eb,  0x202, "Denver ETM",                 "(Denver Embedded Trace)", },
+       { 0x3eb,  0x302, "Denver Debug",               "(Debug Unit)", },
+       { 0x3eb,  0x402, "Denver PMU",                 "(Performance Monitor Unit)", },
        /* legacy comment: 0x113: what? */
        { ANY_ID, 0x120, "TI SDTI",                    "(System Debug Trace Interface)", }, /* from OMAP3 memmap */
        { ANY_ID, 0x343, "TI DAPCTL",                  "", }, /* from OMAP3 memmap */
@@ -1362,7 +1345,7 @@ static int dap_rom_display(struct command_context *cmd_ctx,
        return ERROR_OK;
 }
 
-static int dap_info_command(struct command_context *cmd_ctx,
+int dap_info_command(struct command_context *cmd_ctx,
                struct adiv5_ap *ap)
 {
        int retval;
@@ -1420,46 +1403,131 @@ static int dap_info_command(struct command_context *cmd_ctx,
        return ERROR_OK;
 }
 
+enum adiv5_cfg_param {
+       CFG_DAP,
+       CFG_AP_NUM
+};
+
+static const Jim_Nvp nvp_config_opts[] = {
+       { .name = "-dap",    .value = CFG_DAP },
+       { .name = "-ap-num", .value = CFG_AP_NUM },
+       { .name = NULL, .value = -1 }
+};
+
 int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi)
 {
        struct adiv5_private_config *pc;
-       const char *arg;
-       jim_wide ap_num;
        int e;
 
-       /* check if argv[0] is for us */
-       arg = Jim_GetString(goi->argv[0], NULL);
-       if (strcmp(arg, "-ap-num"))
-               return JIM_CONTINUE;
+       pc = (struct adiv5_private_config *)target->private_config;
+       if (pc == NULL) {
+               pc = calloc(1, sizeof(struct adiv5_private_config));
+               pc->ap_num = -1;
+               target->private_config = pc;
+       }
 
-       e = Jim_GetOpt_String(goi, &arg, NULL);
-       if (e != JIM_OK)
-               return e;
+       target->has_dap = true;
+
+       if (goi->argc > 0) {
+               Jim_Nvp *n;
+
+               Jim_SetEmptyResult(goi->interp);
+
+               /* check first if topmost item is for us */
+               e = Jim_Nvp_name2value_obj(goi->interp, nvp_config_opts,
+                                                                  goi->argv[0], &n);
+               if (e != JIM_OK)
+                       return JIM_CONTINUE;
+
+               e = Jim_GetOpt_Obj(goi, NULL);
+               if (e != JIM_OK)
+                       return e;
+
+               switch (n->value) {
+               case CFG_DAP:
+                       if (goi->isconfigure) {
+                               Jim_Obj *o_t;
+                               struct adiv5_dap *dap;
+                               e = Jim_GetOpt_Obj(goi, &o_t);
+                               if (e != JIM_OK)
+                                       return e;
+                               dap = dap_instance_by_jim_obj(goi->interp, o_t);
+                               if (dap == NULL) {
+                                       Jim_SetResultString(goi->interp, "DAP name invalid!", -1);
+                                       return JIM_ERR;
+                               }
+                               if (pc->dap != NULL && pc->dap != dap) {
+                                       Jim_SetResultString(goi->interp,
+                                               "DAP assignment cannot be changed after target was created!", -1);
+                                       return JIM_ERR;
+                               }
+                               if (target->tap_configured) {
+                                       Jim_SetResultString(goi->interp,
+                                               "-chain-position and -dap configparams are mutually exclusive!", -1);
+                                       return JIM_ERR;
+                               }
+                               pc->dap = dap;
+                               target->tap = dap->tap;
+                               target->dap_configured = true;
+                       } else {
+                               if (goi->argc != 0) {
+                                       Jim_WrongNumArgs(goi->interp,
+                                                                               goi->argc, goi->argv,
+                                       "NO PARAMS");
+                                       return JIM_ERR;
+                               }
+
+                               if (pc->dap == NULL) {
+                                       Jim_SetResultString(goi->interp, "DAP not configured", -1);
+                                       return JIM_ERR;
+                               }
+                               Jim_SetResultString(goi->interp, adiv5_dap_name(pc->dap), -1);
+                       }
+                       break;
 
-       if (goi->argc == 0) {
-               Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-ap-num ?ap-number? ...");
-               return JIM_ERR;
+               case CFG_AP_NUM:
+                       if (goi->isconfigure) {
+                               jim_wide ap_num;
+                               e = Jim_GetOpt_Wide(goi, &ap_num);
+                               if (e != JIM_OK)
+                                       return e;
+                               pc->ap_num = ap_num;
+                       } else {
+                               if (goi->argc != 0) {
+                                       Jim_WrongNumArgs(goi->interp,
+                                                                        goi->argc, goi->argv,
+                                         "NO PARAMS");
+                                       return JIM_ERR;
+                               }
+
+                               if (pc->ap_num < 0) {
+                                       Jim_SetResultString(goi->interp, "AP number not configured", -1);
+                                       return JIM_ERR;
+                               }
+                               Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, (int)pc->ap_num));
+                       }
+                       break;
+               }
        }
 
-       e = Jim_GetOpt_Wide(goi, &ap_num);
-       if (e != JIM_OK)
-               return e;
+       return JIM_OK;
+}
 
-       if (target->private_config == NULL) {
-               pc = calloc(1, sizeof(struct adiv5_private_config));
-               target->private_config = pc;
-               pc->ap_num = ap_num;
-       }
+int adiv5_verify_config(struct adiv5_private_config *pc)
+{
+       if (pc == NULL)
+               return ERROR_FAIL;
 
+       if (pc->dap == NULL)
+               return ERROR_FAIL;
 
-       return JIM_OK;
+       return ERROR_OK;
 }
 
+
 COMMAND_HANDLER(handle_dap_info_command)
 {
-       struct target *target = get_current_target(CMD_CTX);
-       struct arm *arm = target_to_arm(target);
-       struct adiv5_dap *dap = arm->dap;
+       struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
        uint32_t apsel;
 
        switch (CMD_ARGC) {
@@ -1480,10 +1548,7 @@ COMMAND_HANDLER(handle_dap_info_command)
 
 COMMAND_HANDLER(dap_baseaddr_command)
 {
-       struct target *target = get_current_target(CMD_CTX);
-       struct arm *arm = target_to_arm(target);
-       struct adiv5_dap *dap = arm->dap;
-
+       struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
        uint32_t apsel, baseaddr;
        int retval;
 
@@ -1520,10 +1585,7 @@ COMMAND_HANDLER(dap_baseaddr_command)
 
 COMMAND_HANDLER(dap_memaccess_command)
 {
-       struct target *target = get_current_target(CMD_CTX);
-       struct arm *arm = target_to_arm(target);
-       struct adiv5_dap *dap = arm->dap;
-
+       struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
        uint32_t memaccess_tck;
 
        switch (CMD_ARGC) {
@@ -1546,10 +1608,7 @@ COMMAND_HANDLER(dap_memaccess_command)
 
 COMMAND_HANDLER(dap_apsel_command)
 {
-       struct target *target = get_current_target(CMD_CTX);
-       struct arm *arm = target_to_arm(target);
-       struct adiv5_dap *dap = arm->dap;
-
+       struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
        uint32_t apsel, apid;
        int retval;
 
@@ -1584,11 +1643,9 @@ COMMAND_HANDLER(dap_apsel_command)
 
 COMMAND_HANDLER(dap_apcsw_command)
 {
-       struct target *target = get_current_target(CMD_CTX);
-       struct arm *arm = target_to_arm(target);
-       struct adiv5_dap *dap = arm->dap;
-
-       uint32_t apcsw = dap->ap[dap->apsel].csw_default, sprot = 0;
+       struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
+       uint32_t apcsw = dap->ap[dap->apsel].csw_default;
+       uint32_t sprot = 0;
 
        switch (CMD_ARGC) {
        case 0:
@@ -1617,10 +1674,7 @@ COMMAND_HANDLER(dap_apcsw_command)
 
 COMMAND_HANDLER(dap_apid_command)
 {
-       struct target *target = get_current_target(CMD_CTX);
-       struct arm *arm = target_to_arm(target);
-       struct adiv5_dap *dap = arm->dap;
-
+       struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
        uint32_t apsel, apid;
        int retval;
 
@@ -1652,10 +1706,7 @@ COMMAND_HANDLER(dap_apid_command)
 
 COMMAND_HANDLER(dap_apreg_command)
 {
-       struct target *target = get_current_target(CMD_CTX);
-       struct arm *arm = target_to_arm(target);
-       struct adiv5_dap *dap = arm->dap;
-
+       struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
        uint32_t apsel, reg, value;
        int retval;
 
@@ -1691,10 +1742,7 @@ COMMAND_HANDLER(dap_apreg_command)
 
 COMMAND_HANDLER(dap_ti_be_32_quirks_command)
 {
-       struct target *target = get_current_target(CMD_CTX);
-       struct arm *arm = target_to_arm(target);
-       struct adiv5_dap *dap = arm->dap;
-
+       struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
        uint32_t enable = dap->ti_be_32_quirks;
 
        switch (CMD_ARGC) {
@@ -1715,7 +1763,7 @@ COMMAND_HANDLER(dap_ti_be_32_quirks_command)
        return 0;
 }
 
-static const struct command_registration dap_commands[] = {
+const struct command_registration dap_instance_commands[] = {
        {
                .name = "info",
                .handler = handle_dap_info_command,
@@ -1781,14 +1829,3 @@ static const struct command_registration dap_commands[] = {
        },
        COMMAND_REGISTRATION_DONE
 };
-
-const struct command_registration dap_command_handlers[] = {
-       {
-               .name = "dap",
-               .mode = COMMAND_EXEC,
-               .help = "DAP command group",
-               .usage = "",
-               .chain = dap_commands,
-       },
-       COMMAND_REGISTRATION_DONE
-};