mw_debug: Add Lattice ECP5 support
authorMatt Johnston <matt@codeconstruct.com.au>
Fri, 4 Feb 2022 07:29:40 +0000 (15:29 +0800)
committerMatt Johnston <matt@codeconstruct.com.au>
Mon, 7 Feb 2022 05:37:51 +0000 (13:37 +0800)
"-b ecp5" will select ECP5 interface that talks to a JTAGG
primitive.

For example with a FT232H JTAG board:

./mw_debug  -t 'ft2232 vid=0x0403 pid=0x6014'  -s 30000000 -b ecp5 mr ff003888 6
Connected to libftdi driver.
Found device ID: 0x41113043
00000000ff0038886d6f636c65570a0a  ..Welcom
00000000ff00389063694d206f742065  e to Mic
00000000ff0038982120747461776f72  rowatt !
00000000ff0038a00000000000000a0a  ........
00000000ff0038a867697320636f5320   Soc sig
00000000ff0038b0203a65727574616e  nature:
Core: running
 NIA: c0000000000187f8
 MSR: 9000000000001033

Signed-off-by: Matt Johnston <matt@codeconstruct.com.au>
scripts/mw_debug/mw_debug.c

index 1f7688b8fd24e3850be394ead2098f10d7901ca3..62717601a2d481eda60bb255f10f5acf49255c2a 100644 (file)
@@ -212,16 +212,13 @@ static struct backend sim_backend = {
 
 static urj_chain_t *jc;
 
-static int jtag_init(const char *target, int freq)
+static int common_jtag_init(const char *target, int freq)
 {
        const char *sep;
        const char *cable;
        const int max_params = 20;
        char *params[max_params+1];
-       urj_part_t *p;
-       uint32_t id;
-       int rc, part;
-
+       int rc;
 
        if (!target)
                target = "probe";
@@ -272,19 +269,33 @@ static int jtag_init(const char *target, int freq)
                urj_tap_cable_set_frequency(jc->cable, freq);
        }
 
+       return 0;
+}
+
+static int bscane2_init(const char *target, int freq)
+{
+       urj_part_t *p;
+       uint32_t id;
+       int rc;
+
+       rc = common_jtag_init(target, freq);
+       if (rc < 0) {
+           return rc;
+       }
+
        /* XXX Hard wire part 0, that might need to change (use params and detect !) */
        rc = urj_tap_manual_add(jc, 6);
        if (rc < 0) {
-               fprintf(stderr, "JTAG failed to add part! : %s\n", urj_error_describe());
+               fprintf(stderr, "JTAG failed to add part !\n");
                return -1;
        }
        if (jc->parts == NULL || jc->parts->len == 0) {
-               fprintf(stderr, "JTAG Something's wrong after adding part! : %s\n", urj_error_describe());
+               fprintf(stderr, "JTAG Something's wrong after adding part !\n");
                return -1;
        }
        urj_part_parts_set_instruction(jc->parts, "BYPASS");
 
-       jc->active_part = part = 0;
+       jc->active_part = 0;
 
        p = urj_tap_chain_active_part(jc);
        if (!p) {
@@ -320,6 +331,69 @@ static int jtag_init(const char *target, int freq)
        return 0;
 }
 
+static int ecp5_init(const char *target, int freq)
+{
+       urj_part_t *p;
+       uint32_t id;
+       int rc;
+
+       rc = common_jtag_init(target, freq);
+       if (rc < 0) {
+           return rc;
+       }
+
+       /* XXX Hard wire part 0, that might need to change (use params and detect !) */
+       rc = urj_tap_manual_add(jc, 8);
+       if (rc < 0) {
+               fprintf(stderr, "JTAG failed to add part! : %s\n", urj_error_describe());
+               return -1;
+       }
+       if (jc->parts == NULL || jc->parts->len == 0) {
+               fprintf(stderr, "JTAG Something's wrong after adding part! : %s\n", urj_error_describe());
+               return -1;
+       }
+       urj_part_parts_set_instruction(jc->parts, "BYPASS");
+
+       jc->active_part = 0;
+
+       p = urj_tap_chain_active_part(jc);
+       if (!p) {
+               fprintf(stderr, "Failed to get active JTAG part\n");
+               return -1;
+       }
+       rc = urj_part_data_register_define(p, "IDCODE_REG", 32);
+       if (rc != URJ_STATUS_OK) {
+               fprintf(stderr, "JTAG failed to add IDCODE_REG register! : %s\n",
+                       urj_error_describe());
+               return -1;
+       }
+       // READ_ID = 0xE0 = 11100000, from Lattice TN1260 sysconfig guide
+       if (urj_part_instruction_define(p, "IDCODE", "11100000", "IDCODE_REG") == NULL) {
+               fprintf(stderr, "JTAG failed to add IDCODE instruction! : %s\n",
+                       urj_error_describe());
+               return -1;
+       }
+       rc = urj_part_data_register_define(p, "USER2_REG", 74);
+       if (rc != URJ_STATUS_OK) {
+               fprintf(stderr, "JTAG failed to add USER2_REG register !\n");
+               return -1;
+       }
+       // ER1 = 0x32 = 00110010b
+       if (urj_part_instruction_define(p, "USER2", "00110010", "USER2_REG") == NULL) {
+               fprintf(stderr, "JTAG failed to add USER2 instruction !\n");
+               return -1;
+       }
+       urj_part_set_instruction(p, "IDCODE");
+       urj_tap_chain_shift_instructions(jc);
+       urj_tap_chain_shift_data_registers(jc, 1);
+       id = urj_tap_register_get_value(p->active_instruction->data_register->out);
+       printf("Found device ID: 0x%08x\n", id);
+       urj_part_set_instruction(p, "USER2");
+       urj_tap_chain_shift_instructions(jc);
+
+       return 0;
+}
+
 static int jtag_reset(void)
 {
        return 0;
@@ -359,8 +433,14 @@ static int jtag_command(uint8_t op, uint8_t addr, uint64_t *data)
        return rc;
 }
 
-static struct backend jtag_backend = {
-       .init   = jtag_init,
+static struct backend bscane2_backend = {
+       .init   = bscane2_init,
+       .reset = jtag_reset,
+       .command = jtag_command,
+};
+
+static struct backend ecp5_backend = {
+       .init   = ecp5_init,
        .reset = jtag_reset,
        .command = jtag_command,
 };
@@ -682,7 +762,7 @@ static void ltrig_set(uint64_t addr)
 
 static void usage(const char *cmd)
 {
-       fprintf(stderr, "Usage: %s -b <jtag|sim> <command> <args>\n", cmd);
+       fprintf(stderr, "Usage: %s -b <jtag|ecp5|sim> <command> <args>\n", cmd);
 
        fprintf(stderr, "\n");
        fprintf(stderr, " CPU core:\n");
@@ -750,8 +830,10 @@ int main(int argc, char *argv[])
                case 'b':
                        if (strcmp(optarg, "sim") == 0)
                                b = &sim_backend;
-                       else if (strcmp(optarg, "jtag") == 0)
-                               b = &jtag_backend;
+                       else if (strcmp(optarg, "jtag") == 0 || strcmp(optarg, "bscane2") == 0)
+                               b = &bscane2_backend;
+                       else if (strcmp(optarg, "ecp5") == 0)
+                               b = &ecp5_backend;
                        else {
                                fprintf(stderr, "Unknown backend %s\n", optarg);
                                exit(1);
@@ -773,7 +855,7 @@ int main(int argc, char *argv[])
        }
 
        if (b == NULL)
-               b = &jtag_backend;
+               b = &bscane2_backend;
 
        rc = b->init(target, freq);
        if (rc < 0)