diff mbox series

[2/7] MIPS: time: Use CPUHUP to handle r4k timer

Message ID 20200817034701.3515721-3-jiaxun.yang@flygoat.com (mailing list archive)
State Deferred
Headers show
Series R4000 clock enhancements for Loongson | expand

Commit Message

Jiaxun Yang Aug. 17, 2020, 3:46 a.m. UTC
There is no need to hijack initialization procudre to take care of
r4k timer we have CPUHP framework to deal with the CPU plug sequence.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/time.h | 28 +++++++++++++++-------------
 arch/mips/kernel/cevt-r4k.c  | 30 ++++++++++++++++++++++--------
 arch/mips/kernel/smp.c       |  3 ---
 arch/mips/kernel/time.c      | 22 ++++++++++++++++++++--
 include/linux/cpuhotplug.h   |  1 +
 5 files changed, 58 insertions(+), 26 deletions(-)
diff mbox series

Patch

diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h
index e855a3611d92..d00a5b05a420 100644
--- a/arch/mips/include/asm/time.h
+++ b/arch/mips/include/asm/time.h
@@ -39,30 +39,32 @@  extern int __weak get_c0_perfcount_int(void);
  * Initialize the calling CPU's compare interrupt as clockevent device
  */
 extern unsigned int get_c0_compare_int(void);
-extern int r4k_clockevent_init(void);
 
-static inline int mips_clockevent_init(void)
-{
 #ifdef CONFIG_CEVT_R4K
-	return r4k_clockevent_init();
+extern int r4k_clockevent_init(void);
+extern int r4k_clockevent_percpu_init(int cpu);
 #else
-	return -ENXIO;
-#endif
+static inline int r4k_clockevent_init(void)
+{
+	return -ENODEV;
+}
+static inline int r4k_clockevent_percpu_init(int cpu)
+{
+	return -ENODEV;
 }
+#endif
 
 /*
  * Initialize the count register as a clocksource
  */
-extern int init_r4k_clocksource(void);
-
-static inline int init_mips_clocksource(void)
-{
 #ifdef CONFIG_CSRC_R4K
-	return init_r4k_clocksource();
+extern int init_r4k_clocksource(void);
 #else
-	return 0;
-#endif
+static inline int init_r4k_clocksource(void)
+{
+	return -ENODEV;
 }
+#endif
 
 static inline void clockevent_set_clock(struct clock_event_device *cd,
 					unsigned int clock)
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 995ad9e69ded..f0c52d751d0a 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -294,10 +294,8 @@  core_initcall(r4k_register_cpufreq_notifier);
 
 #endif /* !CONFIG_CPU_FREQ */
 
-int r4k_clockevent_init(void)
+int r4k_clockevent_percpu_init(int cpu)
 {
-	unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED;
-	unsigned int cpu = smp_processor_id();
 	struct clock_event_device *cd;
 	unsigned int irq, min_delta;
 
@@ -307,11 +305,6 @@  int r4k_clockevent_init(void)
 	if (!c0_compare_int_usable())
 		return -ENXIO;
 
-	/*
-	 * With vectored interrupts things are getting platform specific.
-	 * get_c0_compare_int is a hook to allow a platform to return the
-	 * interrupt number of its liking.
-	 */
 	irq = get_c0_compare_int();
 
 	cd = &per_cpu(mips_clockevent_device, cpu);
@@ -331,9 +324,30 @@  int r4k_clockevent_init(void)
 
 	clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff);
 
+	return 0;
+}
+
+int r4k_clockevent_init(void)
+{
+	int ret;
+	unsigned int irq;
+	unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED;
+
+	ret = r4k_clockevent_percpu_init(0);
+	if (ret)
+		return ret;
+
+
 	if (cp0_timer_irq_installed)
 		return 0;
 
+	/*
+	 * With vectored interrupts things are getting platform specific.
+	 * get_c0_compare_int is a hook to allow a platform to return the
+	 * interrupt number of its liking.
+	 */
+	irq = get_c0_compare_int();
+
 	cp0_timer_irq_installed = 1;
 
 	if (request_irq(irq, c0_compare_interrupt, flags, "timer",
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index ead9ac883241..0ca4f7cf6402 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -337,7 +337,6 @@  asmlinkage void start_secondary(void)
 
 	cpu_probe();
 	per_cpu_trap_init(false);
-	mips_clockevent_init();
 	mp_ops->init_secondary();
 	cpu_report();
 	maar_init();
@@ -358,8 +357,6 @@  asmlinkage void start_secondary(void)
 	/* Notify boot CPU that we're starting & ready to sync counters */
 	complete(&cpu_starting);
 
-	synchronise_count_slave(cpu);
-
 	/* The CPU is running and counters synchronised, now mark it online */
 	set_cpu_online(cpu, true);
 
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index caa01457dce6..9b16e60aaa30 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -8,6 +8,7 @@ 
  */
 #include <linux/bug.h>
 #include <linux/clockchips.h>
+#include <linux/cpuhotplug.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -24,6 +25,7 @@ 
 #include <asm/cpu-features.h>
 #include <asm/cpu-type.h>
 #include <asm/div64.h>
+#include <asm/r4k-timer.h>
 #include <asm/time.h>
 
 #ifdef CONFIG_CPU_FREQ
@@ -155,6 +157,16 @@  static __init int cpu_has_mfc0_count_bug(void)
 	return 0;
 }
 
+#if defined(CONFIG_CEVT_R4K) || defined(CONFIG_CSRC_R4K)
+static int mips_r4k_timer_starting_cpu(unsigned int cpu)
+{
+	synchronise_count_slave(cpu);
+	r4k_clockevent_percpu_init(cpu);
+
+	return 0;
+}
+#endif
+
 void __init time_init(void)
 {
 	plat_time_init();
@@ -167,6 +179,12 @@  void __init time_init(void)
 	 * timer interrupt isn't reliable; the interference doesn't
 	 * matter then, because we don't use the interrupt.
 	 */
-	if (mips_clockevent_init() != 0 || !cpu_has_mfc0_count_bug())
-		init_mips_clocksource();
+	if (r4k_clockevent_init() != 0 || !cpu_has_mfc0_count_bug())
+		init_r4k_clocksource();
+
+#if defined(CONFIG_CEVT_R4K) || defined(CONFIG_CSRC_R4K)
+	cpuhp_setup_state_nocalls(CPUHP_AP_MIPS_R4K_TIMER_STARTING,
+			  "clockevents/mips/r4k/timer:starting",
+			  mips_r4k_timer_starting_cpu, NULL);
+#endif
 }
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 191772d4a4d7..163288803cd4 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -129,6 +129,7 @@  enum cpuhp_state {
 	CPUHP_AP_TEGRA_TIMER_STARTING,
 	CPUHP_AP_ARMADA_TIMER_STARTING,
 	CPUHP_AP_MARCO_TIMER_STARTING,
+	CPUHP_AP_MIPS_R4K_TIMER_STARTING,
 	CPUHP_AP_MIPS_GIC_TIMER_STARTING,
 	CPUHP_AP_ARC_TIMER_STARTING,
 	CPUHP_AP_RISCV_TIMER_STARTING,