From 9c64f8a98ba63a3ab249f272716ada201fd52aa6 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 4 Feb 2022 15:29:40 +0800 Subject: [PATCH] mw_debug: Add Lattice ECP5 support "-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 00000000ff003888: 6d6f636c65570a0a ..Welcom 00000000ff003890: 63694d206f742065 e to Mic 00000000ff003898: 2120747461776f72 rowatt ! 00000000ff0038a0: 0000000000000a0a ........ 00000000ff0038a8: 67697320636f5320 Soc sig 00000000ff0038b0: 203a65727574616e nature: Core: running NIA: c0000000000187f8 MSR: 9000000000001033 Signed-off-by: Matt Johnston --- scripts/mw_debug/mw_debug.c | 110 +++++++++++++++++++++++++++++++----- 1 file changed, 96 insertions(+), 14 deletions(-) diff --git a/scripts/mw_debug/mw_debug.c b/scripts/mw_debug/mw_debug.c index 1f7688b..6271760 100644 --- a/scripts/mw_debug/mw_debug.c +++ b/scripts/mw_debug/mw_debug.c @@ -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 \n", cmd); + fprintf(stderr, "Usage: %s -b \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)