This is an automated email from Gerrit.

"Conor Paxton <conor.pax...@microchip.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8558

-- gerrit

commit 8d7bf3ce9e07a3f1c931a843380da93b1605e51f
Author: Conor Paxton <conor.pax...@microchip.com>
Date:   Mon Jun 10 19:59:43 2024 +0100

    target: riscv: enable jtag comms via tunnelling to a soft processor
    
    For Microchip FPGA devices implementing CoreJTAGDebug
    
    Change-Id: Ib317425e7de1d384ccc6f34c0ec7f45bd00f282c
    Signed-off-by: Tommy Murphy <tommy_mur...@hotmail.com>
    Signed-off-by: Anton Krug <anton.k...@gmail.com>
    Signed-off-by: Daire McNamara <daire.mcnam...@microchip.com>
    Signed-off-by: Matteo Bonicolini <matteo.bonicol...@microchip.com>
    Signed-off-by: Conor Paxton <conor.pax...@microchip.com>

diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 99f40a7393..e66e35b277 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -130,6 +130,15 @@ int bscan_tunnel_ir_width; /* if zero, then tunneling is 
not present/active */
 
 static const uint8_t bscan_zero[4] = {0};
 static const uint8_t bscan_one[4] = {1};
+static const uint8_t bscan_three[4] = {3};
+static const uint8_t bscan_four[4] = {4};
+static const uint8_t bscan_five[4] = {5};
+static const uint8_t bscan_six[4] = {6};
+static const uint8_t bscan_sixteen[4] = {0x10};
+static const uint8_t bscan_seventeen[4] = {0x11};
+static const uint8_t bscan_twenty_seven[4] = {0x1b};
+static const uint8_t bscan_thirty_two[4] = {0x20};
+static const uint8_t bscan_exit[4] = {0x00, 0x36};
 
 static uint8_t ir_user4[4];
 static struct scan_field select_user4 = {
@@ -184,12 +193,70 @@ static struct scan_field 
_bscan_tunnel_nested_tap_select_dmi[] = {
                        .in_value = NULL,
                }
 };
+
+static struct scan_field _bscan_tunnel_ujtag_select_dmi1[] = {
+               {
+                       .num_bits = 3,
+                       .out_value = bscan_four,
+                       .in_value = NULL,
+               },
+               {
+                       .num_bits = 4,
+                       .out_value = bscan_three,
+                       .in_value = NULL,
+               },
+               {
+                       .num_bits = 6,
+                       .out_value = bscan_five,
+                       .in_value = NULL,
+               },
+               {
+                       .num_bits = 5, /* initialized in riscv_init_target to 
ir width of DM */
+                       .out_value = bscan_seventeen,
+                       .in_value = NULL,
+               },
+               {
+                       .num_bits = 3,
+                       .out_value = bscan_one,
+                       .in_value = NULL,
+               },
+               {
+                       .num_bits = 1,
+                       .out_value = bscan_zero,
+                       .in_value = NULL,
+               },
+};
+
+static struct scan_field _bscan_tunnel_ujtag_select_dmi2[] = {
+               {
+                       .num_bits = 9,
+                       .out_value = bscan_zero,
+                       .in_value = NULL,
+               },
+               {
+                       .num_bits = 3,
+                       .out_value = bscan_three,
+                       .in_value = NULL,
+               },
+               {
+                       .num_bits = 3,
+                       .out_value = bscan_three,
+                       .in_value = NULL,
+               },
+};
+
 static struct scan_field *bscan_tunnel_nested_tap_select_dmi = 
_bscan_tunnel_nested_tap_select_dmi;
 static uint32_t bscan_tunnel_nested_tap_select_dmi_num_fields = 
ARRAY_SIZE(_bscan_tunnel_nested_tap_select_dmi);
 
 static struct scan_field *bscan_tunnel_data_register_select_dmi = 
_bscan_tunnel_data_register_select_dmi;
 static uint32_t bscan_tunnel_data_register_select_dmi_num_fields = 
ARRAY_SIZE(_bscan_tunnel_data_register_select_dmi);
 
+static struct scan_field *bscan_tunnel_ujtag_select_dmi1 = 
_bscan_tunnel_ujtag_select_dmi1;
+static uint32_t bscan_tunnel_ujtag_select_dmi1_num_fields = 
ARRAY_SIZE(_bscan_tunnel_ujtag_select_dmi1);
+
+static struct scan_field *bscan_tunnel_ujtag_select_dmi2 = 
_bscan_tunnel_ujtag_select_dmi2;
+static uint32_t bscan_tunnel_ujtag_select_dmi2_num_fields = 
ARRAY_SIZE(_bscan_tunnel_ujtag_select_dmi2);
+
 struct trigger {
        uint64_t address;
        uint32_t length;
@@ -285,9 +352,121 @@ void select_dmi_via_bscan(struct target *target)
        if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER)
                jtag_add_dr_scan(target->tap, 
bscan_tunnel_data_register_select_dmi_num_fields,
                                                                                
bscan_tunnel_data_register_select_dmi, TAP_IDLE);
-       else /* BSCAN_TUNNEL_NESTED_TAP */
+       else if (bscan_tunnel_type == BSCAN_TUNNEL_NESTED_TAP)
                jtag_add_dr_scan(target->tap, 
bscan_tunnel_nested_tap_select_dmi_num_fields,
                                                                                
bscan_tunnel_nested_tap_select_dmi, TAP_IDLE);
+       else if (bscan_tunnel_type == BSCAN_TUNNEL_UJTAG) {
+               jtag_add_dr_scan(target->tap, 
bscan_tunnel_ujtag_select_dmi1_num_fields,
+                                                                               
bscan_tunnel_ujtag_select_dmi1, TAP_IDLE);
+               jtag_add_dr_scan(target->tap, 
bscan_tunnel_ujtag_select_dmi2_num_fields,
+                                                                               
bscan_tunnel_ujtag_select_dmi2, TAP_IDLE);
+       }
+}
+
+#include <helper/jep106.h>
+uint32_t idcode_scan_via_bscan(struct target *target, uint32_t out)
+{
+       /* On BSCAN TAP: Select IR=USER4, issue tunneled IR scan via BSCAN 
TAP's DR */
+       uint8_t out_value[5] = {0};
+       uint8_t in_value[5] = {0};
+
+       buf_set_u32(out_value, 0, 32, out);
+       struct scan_field tunneled_ir[7] = {};
+       struct scan_field tunneled_dr[9] = {};
+
+       if (bscan_tunnel_type == BSCAN_TUNNEL_UJTAG) {
+               tunneled_ir[0].num_bits = 3;
+               tunneled_ir[0].out_value = bscan_five;
+               tunneled_ir[0].in_value = NULL;
+
+               tunneled_ir[1].num_bits = 5;
+               tunneled_ir[1].out_value = bscan_six;
+               tunneled_ir[1].in_value = NULL;
+
+               tunneled_ir[2].num_bits = 6;
+               tunneled_ir[2].out_value = bscan_five;
+               tunneled_ir[2].in_value = NULL;
+
+               tunneled_ir[3].num_bits = 5;
+               tunneled_ir[3].out_value = bscan_one;
+               tunneled_ir[3].in_value = NULL;
+
+               tunneled_ir[4].num_bits = 3;
+               tunneled_ir[4].out_value = bscan_one;
+               tunneled_ir[4].in_value = NULL;
+
+               tunneled_ir[5].num_bits = 1;
+               tunneled_ir[5].out_value = bscan_zero;
+               tunneled_ir[5].in_value = NULL;
+
+               tunneled_ir[6].num_bits = 15;
+               tunneled_ir[6].out_value = bscan_exit;
+               tunneled_ir[6].in_value = NULL;
+
+               tunneled_dr[0].num_bits = 3;
+               tunneled_dr[0].out_value = bscan_three;
+               tunneled_dr[0].in_value = NULL;
+
+               tunneled_dr[1].num_bits = 3;
+               tunneled_dr[1].out_value = bscan_one;
+               tunneled_dr[1].in_value = NULL;
+
+               tunneled_dr[2].num_bits = 6;
+               tunneled_dr[2].out_value = bscan_thirty_two;
+               tunneled_dr[2].in_value = NULL;
+
+               tunneled_dr[3].num_bits = 32 + 1;
+               tunneled_dr[3].out_value = out_value;
+               tunneled_dr[3].in_value = in_value;
+
+               tunneled_dr[4].num_bits = 3;
+               tunneled_dr[4].out_value = bscan_one;
+               tunneled_dr[4].in_value = NULL;
+
+               tunneled_dr[5].num_bits = 1;
+               tunneled_dr[5].out_value = bscan_zero;
+               tunneled_dr[5].in_value = NULL;
+
+               tunneled_dr[6].num_bits = 9;
+               tunneled_dr[6].out_value = bscan_zero;
+               tunneled_dr[6].in_value = NULL;
+
+               tunneled_dr[7].num_bits = 3;
+               tunneled_dr[7].out_value = bscan_three;
+               tunneled_dr[7].in_value = NULL;
+
+               tunneled_dr[8].num_bits = 3;
+               tunneled_dr[8].out_value = bscan_three;
+               tunneled_dr[8].in_value = NULL;
+       }
+       jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE);
+       if (bscan_tunnel_type == BSCAN_TUNNEL_UJTAG) {
+               jtag_add_dr_scan(target->tap, 6, &tunneled_ir[0], TAP_IDLE);
+               jtag_add_dr_scan(target->tap, 1, &tunneled_ir[6], TAP_IDLE);
+       }
+       if (bscan_tunnel_type == BSCAN_TUNNEL_UJTAG) {
+               jtag_add_dr_scan(target->tap, 6, &tunneled_dr[0], TAP_IDLE);
+               jtag_add_dr_scan(target->tap, 3, &tunneled_dr[6], TAP_IDLE);
+       }
+
+       int retval = jtag_execute_queue();
+       if (retval != ERROR_OK) {
+               LOG_ERROR("failed jtag scan: %d", retval);
+               return retval;
+       }
+
+#define _EXTRACT_MFG(X)  (((X) & 0xffe) >> 1)
+#define _EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
+#define _EXTRACT_VER(X)  (((X) & 0xf0000000) >> 28)
+
+       /* Note the starting offset is bit 1, not bit 0.  In BSCAN tunnel, 
there is a one-bit TCK skew between
+          output and input */
+       uint32_t in = buf_get_u32(in_value, 1, 32);
+       LOG_INFO("UJTAG TUNNELED IDCODE: 0x%08x "
+                       "(mfg: 0x%3.3x (%s), part: 0x%4.4x, ver: 0x%1.1x)", in, 
_EXTRACT_MFG(in),
+                       jep106_manufacturer(_EXTRACT_MFG(in)), 
_EXTRACT_PART(in), _EXTRACT_VER(in));
+
+       return in;
 }
 
 uint32_t dtmcontrol_scan_via_bscan(struct target *target, uint32_t out)
@@ -299,8 +478,8 @@ uint32_t dtmcontrol_scan_via_bscan(struct target *target, 
uint32_t out)
        uint8_t in_value[5] = {0};
 
        buf_set_u32(out_value, 0, 32, out);
-       struct scan_field tunneled_ir[4] = {};
-       struct scan_field tunneled_dr[4] = {};
+       struct scan_field tunneled_ir[7] = {};
+       struct scan_field tunneled_dr[9] = {};
 
        if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER) {
                tunneled_ir[0].num_bits = 3;
@@ -328,8 +507,7 @@ uint32_t dtmcontrol_scan_via_bscan(struct target *target, 
uint32_t out)
                tunneled_dr[3].num_bits = 1;
                tunneled_dr[3].out_value = bscan_one;
                tunneled_dr[3].in_value = NULL;
-       } else {
-               /* BSCAN_TUNNEL_NESTED_TAP */
+       } else if (bscan_tunnel_type == BSCAN_TUNNEL_NESTED_TAP) {
                tunneled_ir[3].num_bits = 3;
                tunneled_ir[3].out_value = bscan_zero;
                tunneled_ir[3].in_value = NULL;
@@ -355,10 +533,86 @@ uint32_t dtmcontrol_scan_via_bscan(struct target *target, 
uint32_t out)
                tunneled_dr[0].num_bits = 1;
                tunneled_dr[0].out_value = bscan_one;
                tunneled_dr[0].in_value = NULL;
+       } else if (bscan_tunnel_type == BSCAN_TUNNEL_UJTAG) {
+               tunneled_ir[0].num_bits = 3;
+               tunneled_ir[0].out_value = bscan_five;
+               tunneled_ir[0].in_value = NULL;
+
+               tunneled_ir[1].num_bits = 5;
+               tunneled_ir[1].out_value = bscan_six;
+               tunneled_ir[1].in_value = NULL;
+
+               tunneled_ir[2].num_bits = 6;
+               tunneled_ir[2].out_value = bscan_five;
+               tunneled_ir[2].in_value = NULL;
+
+               tunneled_ir[3].num_bits = 5;
+               tunneled_ir[3].out_value = bscan_sixteen;
+               tunneled_ir[3].in_value = NULL;
+
+               tunneled_ir[4].num_bits = 3;
+               tunneled_ir[4].out_value = bscan_one;
+               tunneled_ir[4].in_value = NULL;
+
+               tunneled_ir[5].num_bits = 1;
+               tunneled_ir[5].out_value = bscan_zero;
+               tunneled_ir[5].in_value = NULL;
+
+               tunneled_ir[6].num_bits = 15;
+               tunneled_ir[6].out_value = bscan_exit;
+               tunneled_ir[6].in_value = NULL;
+
+               tunneled_dr[0].num_bits = 3;
+               tunneled_dr[0].out_value = bscan_three;
+               tunneled_dr[0].in_value = NULL;
+
+               tunneled_dr[1].num_bits = 3;
+               tunneled_dr[1].out_value = bscan_one;
+               tunneled_dr[1].in_value = NULL;
+
+               tunneled_dr[2].num_bits = 6;
+               tunneled_dr[2].out_value = bscan_thirty_two;
+               tunneled_dr[2].in_value = NULL;
+
+               tunneled_dr[3].num_bits = 32 + 1;
+               tunneled_dr[3].out_value = out_value;
+               tunneled_dr[3].in_value = in_value;
+
+               tunneled_dr[4].num_bits = 3;
+               tunneled_dr[4].out_value = bscan_one;
+               tunneled_dr[4].in_value = NULL;
+
+               tunneled_dr[5].num_bits = 1;
+               tunneled_dr[5].out_value = bscan_zero;
+               tunneled_dr[5].in_value = NULL;
+
+               tunneled_dr[6].num_bits = 9;
+               tunneled_dr[6].out_value = bscan_zero;
+               tunneled_dr[6].in_value = NULL;
+
+               tunneled_dr[7].num_bits = 3;
+               tunneled_dr[7].out_value = bscan_three;
+               tunneled_dr[7].in_value = NULL;
+
+               tunneled_dr[8].num_bits = 3;
+               tunneled_dr[8].out_value = bscan_three;
+               tunneled_dr[8].in_value = NULL;
+
        }
        jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE);
-       jtag_add_dr_scan(target->tap, ARRAY_SIZE(tunneled_ir), tunneled_ir, 
TAP_IDLE);
-       jtag_add_dr_scan(target->tap, ARRAY_SIZE(tunneled_dr), tunneled_dr, 
TAP_IDLE);
+       if (bscan_tunnel_type == BSCAN_TUNNEL_UJTAG) {
+               jtag_add_dr_scan(target->tap, 6, &tunneled_ir[0], TAP_IDLE);
+               jtag_add_dr_scan(target->tap, 1, &tunneled_ir[6], TAP_IDLE);
+       } else {
+               jtag_add_dr_scan(target->tap, 4, tunneled_ir, TAP_IDLE);
+       }
+       if (bscan_tunnel_type == BSCAN_TUNNEL_UJTAG) {
+               jtag_add_dr_scan(target->tap, 6, &tunneled_dr[0], TAP_IDLE);
+               jtag_add_dr_scan(target->tap, 3, &tunneled_dr[6], TAP_IDLE);
+       } else {
+               jtag_add_dr_scan(target->tap, 4, tunneled_dr, TAP_IDLE);
+       }
+
        select_dmi_via_bscan(target);
 
        int retval = jtag_execute_queue();
@@ -380,6 +634,9 @@ static uint32_t dtmcontrol_scan(struct target *target, 
uint32_t out)
        uint8_t in_value[4];
        uint8_t out_value[4] = { 0 };
 
+       if (bscan_tunnel_type == BSCAN_TUNNEL_UJTAG)
+               idcode_scan_via_bscan(target, 0);
+
        if (bscan_tunnel_ir_width != 0)
                return dtmcontrol_scan_via_bscan(target, out);
 
@@ -458,7 +715,9 @@ static int riscv_init_target(struct command_context 
*cmd_ctx,
                bscan_tunneled_ir_width[0] = bscan_tunnel_ir_width;
                if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER)
                        bscan_tunnel_data_register_select_dmi[1].num_bits = 
bscan_tunnel_ir_width;
-               else /* BSCAN_TUNNEL_NESTED_TAP */
+               else if (bscan_tunnel_type == BSCAN_TUNNEL_NESTED_TAP)
+                       bscan_tunnel_nested_tap_select_dmi[2].num_bits = 
bscan_tunnel_ir_width;
+               else if (bscan_tunnel_type == BSCAN_TUNNEL_UJTAG)
                        bscan_tunnel_nested_tap_select_dmi[2].num_bits = 
bscan_tunnel_ir_width;
        }
 
@@ -2786,6 +3045,8 @@ COMMAND_HANDLER(riscv_use_bscan_tunnel)
                LOG_INFO("Nested Tap based Bscan Tunnel Selected");
        else if (tunnel_type == BSCAN_TUNNEL_DATA_REGISTER)
                LOG_INFO("Simple Register based Bscan Tunnel Selected");
+       else if (tunnel_type == BSCAN_TUNNEL_UJTAG)
+               LOG_INFO("UJTAG based Bscan Tunnel Selected");
        else
                LOG_INFO("Invalid Tunnel type selected ! : selecting default 
Nested Tap Type");
 
@@ -4436,8 +4697,7 @@ void riscv_add_bscan_tunneled_scan(struct target *target, 
struct scan_field *fie
 
                ctxt->tunneled_dr[0].num_bits = 3;
                ctxt->tunneled_dr[0].out_value = bscan_zero;
-       } else {
-               /* BSCAN_TUNNEL_NESTED_TAP */
+       } else if (bscan_tunnel_type == BSCAN_TUNNEL_NESTED_TAP) {
                ctxt->tunneled_dr[0].num_bits = 1;
                ctxt->tunneled_dr[0].out_value = bscan_one;
                ctxt->tunneled_dr[1].num_bits = 7;
@@ -4450,6 +4710,40 @@ void riscv_add_bscan_tunneled_scan(struct target 
*target, struct scan_field *fie
                ctxt->tunneled_dr[2].in_value = field->in_value;
                ctxt->tunneled_dr[3].num_bits = 3;
                ctxt->tunneled_dr[3].out_value = bscan_zero;
+       } else if (bscan_tunnel_type == BSCAN_TUNNEL_UJTAG) {
+               ctxt->tunneled_dr[0].num_bits = 3;
+               ctxt->tunneled_dr[0].out_value = bscan_three;
+
+               ctxt->tunneled_dr[1].num_bits = 3;
+               ctxt->tunneled_dr[1].out_value = bscan_one;
+
+               ctxt->tunneled_dr[2].num_bits = 6;
+               ctxt->tunneled_dr_width = field->num_bits;
+               ctxt->tunneled_dr[2].out_value = &ctxt->tunneled_dr_width;
+
+               /* for BSCAN tunnel, there is a one-TCK skew between shift in 
and shift out, so
+                  scanning num_bits + 1, and then will right shift the input 
field after executing the queues */
+               ctxt->tunneled_dr[3].num_bits = field->num_bits + 1;
+               ctxt->tunneled_dr[3].out_value = field->out_value;
+               ctxt->tunneled_dr[3].in_value = field->in_value;
+
+               ctxt->tunneled_dr[4].num_bits = 3;
+               ctxt->tunneled_dr[4].out_value = bscan_one;
+
+               ctxt->tunneled_dr[5].num_bits = 1;
+               ctxt->tunneled_dr[5].out_value = bscan_zero; // goto idle
+
+               ctxt->tunneled_dr[6].num_bits = 9;
+               ctxt->tunneled_dr[6].out_value = bscan_zero;
+
+               ctxt->tunneled_dr[7].num_bits = 6;
+               ctxt->tunneled_dr[7].out_value = bscan_twenty_seven; // 01'1011
+       }
+
+       if (bscan_tunnel_type == BSCAN_TUNNEL_UJTAG) {
+               jtag_add_dr_scan(target->tap, 6, ctxt->tunneled_dr, TAP_IDLE);
+               jtag_add_dr_scan(target->tap, 2, &ctxt->tunneled_dr[6], 
TAP_IDLE);
+       } else {
+               jtag_add_dr_scan(target->tap, 4, ctxt->tunneled_dr, TAP_IDLE);
        }
-       jtag_add_dr_scan(target->tap, ARRAY_SIZE(ctxt->tunneled_dr), 
ctxt->tunneled_dr, TAP_IDLE);
 }
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index 6cb2709de8..c4ca371571 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -233,7 +233,7 @@ COMMAND_HELPER(riscv_print_info_line, const char *section, 
const char *key,
 
 typedef struct {
        uint8_t tunneled_dr_width;
-       struct scan_field tunneled_dr[4];
+       struct scan_field tunneled_dr[8];
 } riscv_bscan_tunneled_scan_context_t;
 
 typedef struct {
@@ -281,7 +281,7 @@ extern struct scan_field select_idcode;
 
 extern struct scan_field *bscan_tunneled_select_dmi;
 extern uint32_t bscan_tunneled_select_dmi_num_fields;
-typedef enum { BSCAN_TUNNEL_NESTED_TAP, BSCAN_TUNNEL_DATA_REGISTER } 
bscan_tunnel_type_t;
+typedef enum { BSCAN_TUNNEL_NESTED_TAP, BSCAN_TUNNEL_DATA_REGISTER, 
BSCAN_TUNNEL_UJTAG } bscan_tunnel_type_t;
 extern int bscan_tunnel_ir_width;
 
 uint32_t dtmcontrol_scan_via_bscan(struct target *target, uint32_t out);

-- 

Reply via email to