X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fclocksource%2Farm_arch_timer.c;h=a328d2c30f33cba2e6001e105d2180b8d96aeefb;hb=8db0e8e150db6f3be4e4c9ac9c449b0c47ee9190;hp=fd4b7f684bd030151d388071e05a3c2cfcb5e2c4;hpb=9888e4d4831d72a64c4378878ada1a4d7539a790;p=platform%2Fkernel%2Flinux-exynos.git diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index fd4b7f6..a328d2c 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -78,6 +78,7 @@ static bool arch_counter_suspend_stop; static bool vdso_default = true; static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); +static bool mct_enable = IS_ENABLED(CONFIG_CLKSRC_EXYNOS_MCT); static int __init early_evtstrm_cfg(char *buf) { @@ -299,8 +300,7 @@ static u64 notrace arm64_858921_read_cntvct_el0(void) #endif #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND -DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, - timer_unstable_counter_workaround); +DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround); EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled); @@ -892,7 +892,7 @@ static void __init arch_counter_register(unsigned type) if (type & ARCH_TIMER_TYPE_CP15) { if (IS_ENABLED(CONFIG_ARM64) || arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) - arch_timer_read_counter = arch_counter_get_cntvct; + arch_timer_read_counter = arch_counter_get_cntpct; else arch_timer_read_counter = arch_counter_get_cntpct; @@ -1018,12 +1018,25 @@ static int __init arch_timer_register(void) goto out_unreg_notify; - /* Register and immediately configure the timer on the boot CPU */ - err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING, - "clockevents/arm/arch_timer:starting", - arch_timer_starting_cpu, arch_timer_dying_cpu); - if (err) - goto out_unreg_cpupm; + if (mct_enable) { + /* + * FIXME: The arm64 architecture enables the arm_arch_timer always + * even if arm_arch_timer is not stable. When Exynos5433 uses the + * arm_arch_timer, it fails to enable/disble the secondary cpu. + * To fix the hotplug issue of secondary cpu, if Exynos's MCT timer + * is enabled, arm_arch_timer doesn't register the clockevent + * for Per-CPU. + */ + return 0; + } else { + /* Register and immediately configure the timer on the boot CPU */ + err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING, + "clockevents/arm/arch_timer:starting", + arch_timer_starting_cpu, arch_timer_dying_cpu); + if (err) + goto out_unreg_cpupm; + } + return 0; out_unreg_cpupm: @@ -1268,10 +1281,6 @@ arch_timer_mem_find_best_frame(struct arch_timer_mem *timer_mem) iounmap(cntctlbase); - if (!best_frame) - pr_err("Unable to find a suitable frame in timer @ %pa\n", - &timer_mem->cntctlbase); - return best_frame; } @@ -1372,6 +1381,8 @@ static int __init arch_timer_mem_of_init(struct device_node *np) frame = arch_timer_mem_find_best_frame(timer_mem); if (!frame) { + pr_err("Unable to find a suitable frame in timer @ %pa\n", + &timer_mem->cntctlbase); ret = -EINVAL; goto out; } @@ -1420,7 +1431,7 @@ arch_timer_mem_verify_cntfrq(struct arch_timer_mem *timer_mem) static int __init arch_timer_mem_acpi_init(int platform_timer_count) { struct arch_timer_mem *timers, *timer; - struct arch_timer_mem_frame *frame; + struct arch_timer_mem_frame *frame, *best_frame = NULL; int timer_count, i, ret = 0; timers = kcalloc(platform_timer_count, sizeof(*timers), @@ -1432,14 +1443,6 @@ static int __init arch_timer_mem_acpi_init(int platform_timer_count) if (ret || !timer_count) goto out; - for (i = 0; i < timer_count; i++) { - ret = arch_timer_mem_verify_cntfrq(&timers[i]); - if (ret) { - pr_err("Disabling MMIO timers due to CNTFRQ mismatch\n"); - goto out; - } - } - /* * While unlikely, it's theoretically possible that none of the frames * in a timer expose the combination of feature we want. @@ -1448,12 +1451,26 @@ static int __init arch_timer_mem_acpi_init(int platform_timer_count) timer = &timers[i]; frame = arch_timer_mem_find_best_frame(timer); - if (frame) - break; + if (!best_frame) + best_frame = frame; + + ret = arch_timer_mem_verify_cntfrq(timer); + if (ret) { + pr_err("Disabling MMIO timers due to CNTFRQ mismatch\n"); + goto out; + } + + if (!best_frame) /* implies !frame */ + /* + * Only complain about missing suitable frames if we + * haven't already found one in a previous iteration. + */ + pr_err("Unable to find a suitable frame in timer @ %pa\n", + &timer->cntctlbase); } - if (frame) - ret = arch_timer_mem_frame_register(frame); + if (best_frame) + ret = arch_timer_mem_frame_register(best_frame); out: kfree(timers); return ret;