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.y...@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 --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,
-- 
2.28.0.rc1

Reply via email to