%D%/image.h \
%D%/mips32.h \
%D%/mips64.h \
+ %D%/mips_cpu.h \
%D%/mips_m4k.h \
%D%/mips_mips64.h \
%D%/mips_ejtag.h \
#endif
#include "mips32.h"
+#include "mips_cpu.h"
#include "breakpoints.h"
#include "algorithm.h"
#include "register.h"
return ERROR_OK;
}
+/* read processor identification cp0 register */
+static int mips32_read_c0_prid(struct target *target)
+{
+ struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
+ int retval;
+
+ retval = mips32_cp0_read(ejtag_info, &mips32->prid, 15, 0);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("processor id not available, failed to read cp0 PRId register");
+ mips32->prid = 0;
+ }
+
+ return retval;
+}
+
+/*
+ * Detect processor type and apply required quirks.
+ *
+ * NOTE: The proper detection of certain CPUs can become quite complicated.
+ * Please consult the following Linux kernel code when adding new CPUs:
+ * arch/mips/include/asm/cpu.h
+ * arch/mips/kernel/cpu-probe.c
+ */
+int mips32_cpu_probe(struct target *target)
+{
+ struct mips32_common *mips32 = target_to_mips32(target);
+ const char *cpu_name = "unknown";
+ int retval;
+
+ if (mips32->prid)
+ return ERROR_OK; /* Already probed once, return early. */
+
+ retval = mips32_read_c0_prid(target);
+ if (retval != ERROR_OK)
+ return retval;
+
+ switch (mips32->prid & PRID_COMP_MASK) {
+ case PRID_COMP_INGENIC_E1:
+ switch (mips32->prid & PRID_IMP_MASK) {
+ case PRID_IMP_XBURST_REV1:
+ cpu_name = "Ingenic XBurst rev1";
+ mips32->cpu_quirks |= EJTAG_QUIRK_PAD_DRET;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ LOG_DEBUG("CPU: %s (PRId %08x)", cpu_name, mips32->prid);
+
+ return ERROR_OK;
+}
+
/* read config to config3 cp0 registers and log isa implementation */
int mips32_read_config_regs(struct target *target)
{
#ifndef OPENOCD_TARGET_MIPS32_H
#define OPENOCD_TARGET_MIPS32_H
+#include <helper/bits.h>
+
#include "target.h"
#include "mips32_pracc.h"
#define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000
+/* Insert extra NOPs after the DRET instruction on exit from debug. */
+#define EJTAG_QUIRK_PAD_DRET BIT(0)
+
/* offsets into mips32 core register cache */
enum {
MIPS32_PC = 37,
enum mips32_isa_mode isa_mode;
enum mips32_isa_imp isa_imp;
+ /* processor identification register */
+ uint32_t prid;
+ /* CPU specific quirks */
+ uint32_t cpu_quirks;
+
/* working area for fastdata access */
struct working_area *fast_data_area;
int mips32_examine(struct target *target);
+int mips32_cpu_probe(struct target *target);
+
int mips32_read_config_regs(struct target *target);
int mips32_register_commands(struct command_context *cmd_ctx);
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef OPENOCD_TARGET_MIPS_CPU_H
+#define OPENOCD_TARGET_MIPS_CPU_H
+
+/*
+ * NOTE: The proper detection of certain CPUs can become quite complicated.
+ * Please consult the following Linux kernel code when adding new CPUs:
+ * 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
+
+/*
+ * 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 */
{
struct pa_list pracc_list = {.instr = MIPS32_DRET(ejtag_info->isa), .addr = 0};
struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = &pracc_list, .code_count = 1, .store_count = 0};
+ struct mips32_common *mips32 = container_of(ejtag_info,
+ struct mips32_common, ejtag_info);
/* 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,
+ mips32->cpu_quirks & EJTAG_QUIRK_PAD_DRET);
/* pic32mx workaround, false pending at low core clock */
jtag_add_sleep(1000);
/* attempt to find halt reason */
mips_m4k_examine_debug_reason(target);
+ mips32_cpu_probe(target);
+
mips32_read_config_regs(target);
/* default to mips32 isa, it will be changed below if required */