[PATCH 1/2] mips: econet: add multi-vpe capability to EN751221

Caleb James DeLisle <[email protected]> Tue, 28 Jul 2026 18:49:58 +0000
Newsgroups org.kernel.vger.linux-mips,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
EN751221 is a 34Kc so it has two VPEs (threads) but MIPS_SMP_MT
requires VEIC to be enabled in the interrupt controller, which only
became supported in
commit 2ee2a685ee83 ("irqchip/econet-en751221: Support MIPS 34Kc VEIC mode")

Register SMP_MT on startup and override init_secondary with CPU
interrupt unmasking as required by the EN751221 VEIC intc hardware.

Signed-off-by: Caleb James DeLisle <[email protected]>
---
 arch/mips/econet/Kconfig |  4 +---
 arch/mips/econet/init.c  | 42 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/arch/mips/econet/Kconfig b/arch/mips/econet/Kconfig
index b37b9d25d5a4..579fb5b01532 100644
--- a/arch/mips/econet/Kconfig
+++ b/arch/mips/econet/Kconfig
@@ -16,9 +16,7 @@ choice
 		select HAVE_PCI
 		select IRQ_MIPS_CPU
 		select PCI_DRIVERS_GENERIC
-		select SMP
-		select SMP_UP
-		select SYS_SUPPORTS_SMP
+		select SYS_SUPPORTS_MULTITHREADING
 		help
 		  The EN751221 family includes EN7512, RN7513, EN7521, EN7526.
 		  They are based on single core MIPS 34Kc processors. To boot
diff --git a/arch/mips/econet/init.c b/arch/mips/econet/init.c
index 6f43ffb209cb..ae45b8788504 100644
--- a/arch/mips/econet/init.c
+++ b/arch/mips/econet/init.c
@@ -28,6 +28,41 @@ static void hw_reset(char *command)
 	iowrite32(RESET, CR_AHB_RSTCR);
 }
 
+/*
+ * vsmp_init_secondary expects either GIC or cascading interrupt configuration.
+ * The EN751221 is a 34Kc with VEIC, but not GIC compatible. The cascading
+ * configuration enables lines 6 and 7 for performance counters, but when this
+ * is done on the EN751221 intc with VEIC enabled, it causes the whole intc to
+ * stop sending interrupts.
+ * Only unmask lines 0 and 1 (software interrupts) in init_secondary.
+ */
+#ifdef CONFIG_MIPS_MT_SMP
+extern const struct plat_smp_ops vsmp_smp_ops;
+static struct plat_smp_ops en75_smp_ops __ro_after_init;
+
+static void en751221_init_secondary(void)
+{
+	write_c0_status((read_c0_status() & ~ST0_IM) |
+		(STATUSF_IP0 | STATUSF_IP1));
+}
+
+static int __init en751221_register_vsmp_smp_ops(void)
+{
+	if (!cpu_has_mipsmt)
+		return -ENODEV;
+
+	en75_smp_ops = vsmp_smp_ops;
+	en75_smp_ops.init_secondary = en751221_init_secondary;
+	register_smp_ops(&en75_smp_ops);
+	return 0;
+}
+#else
+static int __init en751221_register_vsmp_smp_ops(void)
+{
+	return -ENODEV;
+}
+#endif /* CONFIG_MIPS_MT_SMP */
+
 /* 1. Bring up early printk. */
 void __init prom_init(void)
 {
@@ -51,11 +86,16 @@ void __init plat_mem_setup(void)
 	early_init_dt_scan_memory();
 }
 
-/* 3. Overload __weak device_tree_init(), add SMP_UP ops */
+/* 3. Overload __weak device_tree_init(), add SMP ops */
 void __init device_tree_init(void)
 {
 	unflatten_and_copy_device_tree();
 
+	/* EN751221 dual-vpe */
+	if (!en751221_register_vsmp_smp_ops())
+		return;
+
+	/* EN751221 with MT_SMP disabled */
 	register_up_smp_ops();
 }
 
-- 
2.39.5