This is an automated email from Gerrit. "Paul Fertser <fercer...@gmail.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7859
-- gerrit commit c70392aa849b570375c34de109d641497febe8be Author: Artur Rojek <cont...@artur-rojek.eu> Date: Sun Aug 13 16:49:25 2023 +0200 mips32: add per-cpu quirks feature Introduce the ability to detect CPUs based on CP0 PRId register and apply cpu specific quirks, which alter the default ejtag behavior. First of those is EJTAG_QUIRK_PAD_DRET, which makes sure extra NOPs are placed after the DRET instruction on exit from debug mode. This fixes resume behavior on Ingenic JZ4780 SoC. The proper detection of some (currently unsupported) CPUs becomes quite complicated, so please consult the following Linux kernel code when adding new CPUs: * arch/mips/include/asm/cpu.h * arch/mips/kernel/cpu-probe.c Change-Id: I0f413d5096cd43ef346b02cea85024985b7face6 Signed-off-by: Artur Rojek <cont...@artur-rojek.eu> Signed-off-by: Paul Fertser <fercer...@gmail.com> diff --git a/src/target/mips32.c b/src/target/mips32.c index 0c58b565ef..468027e51b 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -18,6 +18,7 @@ #endif #include "mips32.h" +#include "mips_cpu.h" #include "breakpoints.h" #include "algorithm.h" #include "register.h" @@ -693,6 +694,31 @@ int mips32_enable_interrupts(struct target *target, int enable) return ERROR_OK; } +/* detect processor type and apply required quirks */ +static void mips32_cpu_probe(struct target *target) +{ + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + const char *cpu_name = "unknown"; + + switch (ejtag_info->prid & PRID_COMP_MASK) { + case PRID_COMP_INGENIC_E1: + switch (ejtag_info->prid & PRID_IMP_MASK) { + case PRID_IMP_XBURST_REV1: + cpu_name = "Ingenic XBurst rev1"; + ejtag_info->quirks |= EJTAG_QUIRK_PAD_DRET; + break; + default: + break; + } + break; + default: + break; + } + + LOG_DEBUG("CPU: %s (PRId %08x)", cpu_name, ejtag_info->prid); +} + /* read processor identification cp0 register */ int mips32_read_c0_prid(struct target *target) { @@ -707,9 +733,13 @@ int mips32_read_c0_prid(struct target *target) if (retval != ERROR_OK) { LOG_ERROR("processor id not available, failed to read cp0 PRId register"); ejtag_info->prid = 0; + + return retval; } - return retval; + mips32_cpu_probe(target); + + return ERROR_OK; } /* read config to config3 cp0 registers and log isa implementation */ diff --git a/src/target/mips_cpu.h b/src/target/mips_cpu.h new file mode 100644 index 0000000000..45e1667d77 --- /dev/null +++ b/src/target/mips_cpu.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef OPENOCD_TARGET_MIPS_CPU_H +#define OPENOCD_TARGET_MIPS_CPU_H + +/* + * Consult the following Linux kernel code when adding detection of new SoCs: + * arch/mips/include/asm/cpu.h + * arch/mips/kernel/cpu-probe.c + */ + +/* Assigned Company values for bits 23:16 of the PRId register. */ +#define PRID_COMP_MASK 0xff0000 + +#define PRID_COMP_LEGACY 0x000000 +#define PRID_COMP_INGENIC_E1 0xe10000 /* JZ4780 */ + +/* + * Assigned Processor ID (implementation) values for bits 15:8 of the PRId + * register. In order to detect a certain CPU type exactly eventually additional + * registers may need to be examined. + */ +#define PRID_IMP_MASK 0xff00 + +#define PRID_IMP_XBURST_REV1 0x0200 /* XBurst®1 with MXU1.0/MXU1.1 SIMD ISA */ + +#endif /* OPENOCD_TARGET_MIPS_CPU_H */ diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index a1a179216d..45d37ec031 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -261,7 +261,7 @@ int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info) struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = &pracc_list, .code_count = 1, .store_count = 0}; /* execute our dret instruction */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 0); /* shift out instr, omit last check */ + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, ejtag_info->quirks & EJTAG_QUIRK_PAD_DRET); /* pic32mx workaround, false pending at low core clock */ jtag_add_sleep(1000); diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index b95838cb4b..45a027d7ef 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -10,6 +10,7 @@ #ifndef OPENOCD_TARGET_MIPS_EJTAG_H #define OPENOCD_TARGET_MIPS_EJTAG_H +#include <helper/bits.h> #include <jtag/jtag.h> /* tap instructions */ @@ -171,6 +172,9 @@ #define EJTAG_VERSION_41 4 #define EJTAG_VERSION_51 5 +/* Insert extra NOPs after the DRET instruction on exit from debug. */ +#define EJTAG_QUIRK_PAD_DRET BIT(0) + /* * Additional defines for MIPS64 EJTAG */ @@ -205,6 +209,8 @@ struct mips_ejtag { uint32_t isa; uint32_t endianness; + uint32_t quirks; /* ejtag operation quirks */ + /* Memory-Mapped Registers. This addresses are not same on different * EJTAG versions. */ uint32_t debug_caps; --