summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tango
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 10:05:51 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 10:05:51 +0000
commit5d1646d90e1f2cceb9f0828f4b28318cd0ec7744 (patch)
treea94efe259b9009378be6d90eb30d2b019d95c194 /arch/arm/mach-tango
parentInitial commit. (diff)
downloadlinux-5d1646d90e1f2cceb9f0828f4b28318cd0ec7744.tar.xz
linux-5d1646d90e1f2cceb9f0828f4b28318cd0ec7744.zip
Adding upstream version 5.10.209.upstream/5.10.209upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'arch/arm/mach-tango')
-rw-r--r--arch/arm/mach-tango/Kconfig13
-rw-r--r--arch/arm/mach-tango/Makefile4
-rw-r--r--arch/arm/mach-tango/platsmp.c52
-rw-r--r--arch/arm/mach-tango/pm.c31
-rw-r--r--arch/arm/mach-tango/pm.h7
-rw-r--r--arch/arm/mach-tango/setup.c20
-rw-r--r--arch/arm/mach-tango/smc.S12
-rw-r--r--arch/arm/mach-tango/smc.h9
8 files changed, 148 insertions, 0 deletions
diff --git a/arch/arm/mach-tango/Kconfig b/arch/arm/mach-tango/Kconfig
new file mode 100644
index 000000000..a9eeda36a
--- /dev/null
+++ b/arch/arm/mach-tango/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+config ARCH_TANGO
+ bool "Sigma Designs Tango4 (SMP87xx)"
+ depends on ARCH_MULTI_V7
+ # Cortex-A9 MPCore r3p0, PL310 r3p2
+ select ARM_ERRATA_754322
+ select ARM_ERRATA_764369 if SMP
+ select ARM_ERRATA_775420
+ select ARM_GIC
+ select CLKSRC_TANGO_XTAL
+ select HAVE_ARM_SCU
+ select HAVE_ARM_TWD
+ select TANGO_IRQ
diff --git a/arch/arm/mach-tango/Makefile b/arch/arm/mach-tango/Makefile
new file mode 100644
index 000000000..97cd04508
--- /dev/null
+++ b/arch/arm/mach-tango/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-y += setup.o smc.o
+obj-$(CONFIG_SMP) += platsmp.o
+obj-$(CONFIG_SUSPEND) += pm.o
diff --git a/arch/arm/mach-tango/platsmp.c b/arch/arm/mach-tango/platsmp.c
new file mode 100644
index 000000000..65012afbc
--- /dev/null
+++ b/arch/arm/mach-tango/platsmp.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include "smc.h"
+
+static int tango_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ tango_set_aux_boot_addr(__pa_symbol(secondary_startup));
+ tango_start_aux_core(cpu);
+ return 0;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * cpu_kill() and cpu_die() run concurrently on different cores.
+ * Firmware will only "kill" a core once it has properly "died".
+ * Try a few times to kill a core before giving up, and sleep
+ * between tries to give that core enough time to die.
+ */
+static int tango_cpu_kill(unsigned int cpu)
+{
+ int i, err;
+
+ for (i = 0; i < 10; ++i) {
+ msleep(10);
+ err = tango_aux_core_kill(cpu);
+ if (!err)
+ return true;
+ }
+
+ return false;
+}
+
+static void tango_cpu_die(unsigned int cpu)
+{
+ while (tango_aux_core_die(cpu) < 0)
+ cpu_relax();
+
+ panic("cpu %d failed to die\n", cpu);
+}
+#endif
+
+static const struct smp_operations tango_smp_ops __initconst = {
+ .smp_boot_secondary = tango_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_kill = tango_cpu_kill,
+ .cpu_die = tango_cpu_die,
+#endif
+};
+
+CPU_METHOD_OF_DECLARE(tango4_smp, "sigma,tango4-smp", &tango_smp_ops);
diff --git a/arch/arm/mach-tango/pm.c b/arch/arm/mach-tango/pm.c
new file mode 100644
index 000000000..a32c3b631
--- /dev/null
+++ b/arch/arm/mach-tango/pm.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <asm/suspend.h>
+#include "smc.h"
+#include "pm.h"
+
+static int tango_pm_powerdown(unsigned long arg)
+{
+ tango_suspend(__pa_symbol(cpu_resume));
+
+ return -EIO; /* tango_suspend has failed */
+}
+
+static int tango_pm_enter(suspend_state_t state)
+{
+ if (state == PM_SUSPEND_MEM)
+ return cpu_suspend(0, tango_pm_powerdown);
+
+ return -EINVAL;
+}
+
+static const struct platform_suspend_ops tango_pm_ops = {
+ .enter = tango_pm_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+void __init tango_pm_init(void)
+{
+ suspend_set_ops(&tango_pm_ops);
+}
diff --git a/arch/arm/mach-tango/pm.h b/arch/arm/mach-tango/pm.h
new file mode 100644
index 000000000..35ea705a0
--- /dev/null
+++ b/arch/arm/mach-tango/pm.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifdef CONFIG_SUSPEND
+void __init tango_pm_init(void);
+#else
+#define tango_pm_init NULL
+#endif
diff --git a/arch/arm/mach-tango/setup.c b/arch/arm/mach-tango/setup.c
new file mode 100644
index 000000000..824f90737
--- /dev/null
+++ b/arch/arm/mach-tango/setup.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <asm/mach/arch.h>
+#include <asm/hardware/cache-l2x0.h>
+#include "smc.h"
+#include "pm.h"
+
+static void tango_l2c_write(unsigned long val, unsigned int reg)
+{
+ if (reg == L2X0_CTRL)
+ tango_set_l2_control(val);
+}
+
+static const char *const tango_dt_compat[] = { "sigma,tango4", NULL };
+
+DT_MACHINE_START(TANGO_DT, "Sigma Tango DT")
+ .dt_compat = tango_dt_compat,
+ .l2c_aux_mask = ~0,
+ .l2c_write_sec = tango_l2c_write,
+ .init_late = tango_pm_init,
+MACHINE_END
diff --git a/arch/arm/mach-tango/smc.S b/arch/arm/mach-tango/smc.S
new file mode 100644
index 000000000..b1752aaa7
--- /dev/null
+++ b/arch/arm/mach-tango/smc.S
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/linkage.h>
+
+ .arch armv7-a
+ .arch_extension sec
+ENTRY(tango_smc)
+ push {lr}
+ mov ip, r1
+ dsb /* This barrier is probably unnecessary */
+ smc #0
+ pop {pc}
+ENDPROC(tango_smc)
diff --git a/arch/arm/mach-tango/smc.h b/arch/arm/mach-tango/smc.h
new file mode 100644
index 000000000..455ce3e06
--- /dev/null
+++ b/arch/arm/mach-tango/smc.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+extern int tango_smc(unsigned int val, unsigned int service);
+
+#define tango_set_l2_control(val) tango_smc(val, 0x102)
+#define tango_start_aux_core(val) tango_smc(val, 0x104)
+#define tango_set_aux_boot_addr(val) tango_smc(val, 0x105)
+#define tango_suspend(val) tango_smc(val, 0x120)
+#define tango_aux_core_die(val) tango_smc(val, 0x121)
+#define tango_aux_core_kill(val) tango_smc(val, 0x122)