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)
{
#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);
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;
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:
iounmap(cntctlbase);
- if (!best_frame)
- pr_err("Unable to find a suitable frame in timer @ %pa\n",
- &timer_mem->cntctlbase);
-
return best_frame;
}
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;
}
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),
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.
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;