diff options
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 80 | ||||
-rw-r--r-- | drivers/clocksource/arm_global_timer.c | 39 | ||||
-rw-r--r-- | drivers/clocksource/bcm_kona_timer.c | 16 | ||||
-rw-r--r-- | drivers/clocksource/clps711x-timer.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/dummy_timer.c | 36 | ||||
-rw-r--r-- | drivers/clocksource/exynos_mct.c | 46 | ||||
-rw-r--r-- | drivers/clocksource/metag_generic.c | 33 | ||||
-rw-r--r-- | drivers/clocksource/mips-gic-timer.c | 40 | ||||
-rw-r--r-- | drivers/clocksource/pxa_timer.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/qcom-timer.c | 41 | ||||
-rw-r--r-- | drivers/clocksource/sun4i_timer.c | 9 | ||||
-rw-r--r-- | drivers/clocksource/time-armada-370-xp.c | 42 | ||||
-rw-r--r-- | drivers/clocksource/time-pistachio.c | 8 | ||||
-rw-r--r-- | drivers/clocksource/timer-atlas7.c | 41 | ||||
-rw-r--r-- | drivers/clocksource/timer-atmel-pit.c | 7 |
15 files changed, 160 insertions, 282 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 5effd3027319..57700541f951 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -8,6 +8,9 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ + +#define pr_fmt(fmt) "arm_arch_timer: " fmt + #include <linux/init.h> #include <linux/kernel.h> #include <linux/device.h> @@ -370,14 +373,33 @@ static bool arch_timer_has_nonsecure_ppi(void) arch_timer_ppi[PHYS_NONSECURE_PPI]); } -static int arch_timer_setup(struct clock_event_device *clk) +static u32 check_ppi_trigger(int irq) +{ + u32 flags = irq_get_trigger_type(irq); + + if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) { + pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq); + pr_warn("WARNING: Please fix your firmware\n"); + flags = IRQF_TRIGGER_LOW; + } + + return flags; +} + +static int arch_timer_starting_cpu(unsigned int cpu) { + struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); + u32 flags; + __arch_timer_setup(ARCH_CP15_TIMER, clk); - enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0); + flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]); + enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags); - if (arch_timer_has_nonsecure_ppi()) - enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0); + if (arch_timer_has_nonsecure_ppi()) { + flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]); + enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags); + } arch_counter_set_user_access(); if (evtstrm_enable) @@ -527,29 +549,14 @@ static void arch_timer_stop(struct clock_event_device *clk) clk->set_state_shutdown(clk); } -static int arch_timer_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int arch_timer_dying_cpu(unsigned int cpu) { - /* - * Grab cpu pointer in each case to avoid spurious - * preemptible warnings - */ - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_STARTING: - arch_timer_setup(this_cpu_ptr(arch_timer_evt)); - break; - case CPU_DYING: - arch_timer_stop(this_cpu_ptr(arch_timer_evt)); - break; - } + struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); - return NOTIFY_OK; + arch_timer_stop(clk); + return 0; } -static struct notifier_block arch_timer_cpu_nb = { - .notifier_call = arch_timer_cpu_notify, -}; - #ifdef CONFIG_CPU_PM static unsigned int saved_cntkctl; static int arch_timer_cpu_pm_notify(struct notifier_block *self, @@ -570,11 +577,21 @@ static int __init arch_timer_cpu_pm_init(void) { return cpu_pm_register_notifier(&arch_timer_cpu_pm_notifier); } + +static void __init arch_timer_cpu_pm_deinit(void) +{ + WARN_ON(cpu_pm_unregister_notifier(&arch_timer_cpu_pm_notifier)); +} + #else static int __init arch_timer_cpu_pm_init(void) { return 0; } + +static void __init arch_timer_cpu_pm_deinit(void) +{ +} #endif static int __init arch_timer_register(void) @@ -621,22 +638,23 @@ static int __init arch_timer_register(void) goto out_free; } - err = register_cpu_notifier(&arch_timer_cpu_nb); - if (err) - goto out_free_irq; - err = arch_timer_cpu_pm_init(); if (err) goto out_unreg_notify; - /* Immediately configure the timer on the boot CPU */ - arch_timer_setup(this_cpu_ptr(arch_timer_evt)); + /* Register and immediately configure the timer on the boot CPU */ + err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING, + "AP_ARM_ARCH_TIMER_STARTING", + arch_timer_starting_cpu, arch_timer_dying_cpu); + if (err) + goto out_unreg_cpupm; return 0; +out_unreg_cpupm: + arch_timer_cpu_pm_deinit(); + out_unreg_notify: - unregister_cpu_notifier(&arch_timer_cpu_nb); -out_free_irq: free_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], arch_timer_evt); if (arch_timer_has_nonsecure_ppi()) free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index 2a9ceb6e93f9..8da03298f844 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -165,9 +165,9 @@ static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int gt_clockevents_init(struct clock_event_device *clk) +static int gt_starting_cpu(unsigned int cpu) { - int cpu = smp_processor_id(); + struct clock_event_device *clk = this_cpu_ptr(gt_evt); clk->name = "arm_global_timer"; clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | @@ -186,10 +186,13 @@ static int gt_clockevents_init(struct clock_event_device *clk) return 0; } -static void gt_clockevents_stop(struct clock_event_device *clk) +static int gt_dying_cpu(unsigned int cpu) { + struct clock_event_device *clk = this_cpu_ptr(gt_evt); + gt_clockevent_shutdown(clk); disable_percpu_irq(clk->irq); + return 0; } static cycle_t gt_clocksource_read(struct clocksource *cs) @@ -252,24 +255,6 @@ static int __init gt_clocksource_init(void) return clocksource_register_hz(>_clocksource, gt_clk_rate); } -static int gt_cpu_notify(struct notifier_block *self, unsigned long action, - void *hcpu) -{ - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_STARTING: - gt_clockevents_init(this_cpu_ptr(gt_evt)); - break; - case CPU_DYING: - gt_clockevents_stop(this_cpu_ptr(gt_evt)); - break; - } - - return NOTIFY_OK; -} -static struct notifier_block gt_cpu_nb = { - .notifier_call = gt_cpu_notify, -}; - static int __init global_timer_of_register(struct device_node *np) { struct clk *gt_clk; @@ -325,18 +310,14 @@ static int __init global_timer_of_register(struct device_node *np) goto out_free; } - err = register_cpu_notifier(>_cpu_nb); - if (err) { - pr_warn("global-timer: unable to register cpu notifier.\n"); - goto out_irq; - } - - /* Immediately configure the timer on the boot CPU */ + /* Register and immediately configure the timer on the boot CPU */ err = gt_clocksource_init(); if (err) goto out_irq; - err = gt_clockevents_init(this_cpu_ptr(gt_evt)); + err = cpuhp_setup_state(CPUHP_AP_ARM_GLOBAL_TIMER_STARTING, + "AP_ARM_GLOBAL_TIMER_STARTING", + gt_starting_cpu, gt_dying_cpu); if (err) goto out_irq; diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c index 7e3fd375a627..92f6e4deee74 100644 --- a/drivers/clocksource/bcm_kona_timer.c +++ b/drivers/clocksource/bcm_kona_timer.c @@ -66,10 +66,10 @@ static void kona_timer_disable_and_clear(void __iomem *base) } -static void +static int kona_timer_get_counter(void __iomem *timer_base, uint32_t *msw, uint32_t *lsw) { - int loop_limit = 4; + int loop_limit = 3; /* * Read 64-bit free running counter @@ -83,18 +83,19 @@ kona_timer_get_counter(void __iomem *timer_base, uint32_t *msw, uint32_t *lsw) * if new hi-word is equal to previously read hi-word then stop. */ - while (--loop_limit) { + do { *msw = readl(timer_base + KONA_GPTIMER_STCHI_OFFSET); *lsw = readl(timer_base + KONA_GPTIMER_STCLO_OFFSET); if (*msw == readl(timer_base + KONA_GPTIMER_STCHI_OFFSET)) break; - } + } while (--loop_limit); if (!loop_limit) { pr_err("bcm_kona_timer: getting counter failed.\n"); pr_err(" Timer will be impacted\n"); + return -ETIMEDOUT; } - return; + return 0; } static int kona_timer_set_next_event(unsigned long clc, @@ -112,8 +113,11 @@ static int kona_timer_set_next_event(unsigned long clc, uint32_t lsw, msw; uint32_t reg; + int ret; - kona_timer_get_counter(timers.tmr_regs, &msw, &lsw); + ret = kona_timer_get_counter(timers.tmr_regs, &msw, &lsw); + if (ret) + return ret; /* Load the "next" event tick value */ writel(lsw + clc, timers.tmr_regs + KONA_GPTIMER_STCM0_OFFSET); diff --git a/drivers/clocksource/clps711x-timer.c b/drivers/clocksource/clps711x-timer.c index 84aed78261e4..24db6d605549 100644 --- a/drivers/clocksource/clps711x-timer.c +++ b/drivers/clocksource/clps711x-timer.c @@ -119,5 +119,5 @@ static int __init clps711x_timer_init(struct device_node *np) return -EINVAL; } } -CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,clps711x-timer", clps711x_timer_init); +CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,ep7209-timer", clps711x_timer_init); #endif diff --git a/drivers/clocksource/dummy_timer.c b/drivers/clocksource/dummy_timer.c index 776b6c86dcd5..89f1c2edbe02 100644 --- a/drivers/clocksource/dummy_timer.c +++ b/drivers/clocksource/dummy_timer.c @@ -16,10 +16,9 @@ static DEFINE_PER_CPU(struct clock_event_device, dummy_timer_evt); -static void dummy_timer_setup(void) +static int dummy_timer_starting_cpu(unsigned int cpu) { - int cpu = smp_processor_id(); - struct clock_event_device *evt = raw_cpu_ptr(&dummy_timer_evt); + struct clock_event_device *evt = per_cpu_ptr(&dummy_timer_evt, cpu); evt->name = "dummy_timer"; evt->features = CLOCK_EVT_FEAT_PERIODIC | @@ -29,36 +28,13 @@ static void dummy_timer_setup(void) evt->cpumask = cpumask_of(cpu); clockevents_register_device(evt); + return 0; } -static int dummy_timer_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) -{ - if ((action & ~CPU_TASKS_FROZEN) == CPU_STARTING) - dummy_timer_setup(); - - return NOTIFY_OK; -} - -static struct notifier_block dummy_timer_cpu_nb = { - .notifier_call = dummy_timer_cpu_notify, -}; - static int __init dummy_timer_register(void) { - int err = 0; - - cpu_notifier_register_begin(); - err = __register_cpu_notifier(&dummy_timer_cpu_nb); - if (err) - goto out; - - /* We won't get a call on the boot CPU, so register immediately */ - if (num_possible_cpus() > 1) - dummy_timer_setup(); - -out: - cpu_notifier_register_done(); - return err; + return cpuhp_setup_state(CPUHP_AP_DUMMY_TIMER_STARTING, + "AP_DUMMY_TIMER_STARTING", + dummy_timer_starting_cpu, NULL); } early_initcall(dummy_timer_register); diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 0d18dd4b3bd2..41840d02c331 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -443,10 +443,11 @@ static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int exynos4_local_timer_setup(struct mct_clock_event_device *mevt) +static int exynos4_mct_starting_cpu(unsigned int cpu) { + struct mct_clock_event_device *mevt = + per_cpu_ptr(&percpu_mct_tick, cpu); struct clock_event_device *evt = &mevt->evt; - unsigned int cpu = smp_processor_id(); mevt->base = EXYNOS4_MCT_L_BASE(cpu); snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d", cpu); @@ -480,8 +481,10 @@ static int exynos4_local_timer_setup(struct mct_clock_event_device *mevt) return 0; } -static void exynos4_local_timer_stop(struct mct_clock_event_device *mevt) +static int exynos4_mct_dying_cpu(unsigned int cpu) { + struct mct_clock_event_device *mevt = + per_cpu_ptr(&percpu_mct_tick, cpu); struct clock_event_device *evt = &mevt->evt; evt->set_state_shutdown(evt); @@ -491,39 +494,12 @@ static void exynos4_local_timer_stop(struct mct_clock_event_device *mevt) } else { disable_percpu_irq(mct_irqs[MCT_L0_IRQ]); } + return 0; } -static int exynos4_mct_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) -{ - struct mct_clock_event_device *mevt; - - /* - * Grab cpu pointer in each case to avoid spurious - * preemptible warnings - */ - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_STARTING: - mevt = this_cpu_ptr(&percpu_mct_tick); - exynos4_local_timer_setup(mevt); - break; - case CPU_DYING: - mevt = this_cpu_ptr(&percpu_mct_tick); - exynos4_local_timer_stop(mevt); - break; - } - - return NOTIFY_OK; -} - -static struct notifier_block exynos4_mct_cpu_nb = { - .notifier_call = exynos4_mct_cpu_notify, -}; - static int __init exynos4_timer_resources(struct device_node *np, void __iomem *base) { int err, cpu; - struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); struct clk *mct_clk, *tick_clk; tick_clk = np ? of_clk_get_by_name(np, "fin_pll") : @@ -570,12 +546,14 @@ static int __init exynos4_timer_resources(struct device_node *np, void __iomem * } } - err = register_cpu_notifier(&exynos4_mct_cpu_nb); + /* Install hotplug callbacks which configure the timer on this CPU */ + err = cpuhp_setup_state(CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING, + "AP_EXYNOS4_MCT_TIMER_STARTING", + exynos4_mct_starting_cpu, + exynos4_mct_dying_cpu); if (err) goto out_irq; - /* Immediately configure the timer on the boot CPU */ - exynos4_local_timer_setup(mevt); return 0; out_irq: diff --git a/drivers/clocksource/metag_generic.c b/drivers/clocksource/metag_generic.c index bcd5c0d602a0..a80ab3e446b7 100644 --- a/drivers/clocksource/metag_generic.c +++ b/drivers/clocksource/metag_generic.c @@ -90,7 +90,7 @@ unsigned long long sched_clock(void) return ticks << HARDWARE_TO_NS_SHIFT; } -static void arch_timer_setup(unsigned int cpu) +static int arch_timer_starting_cpu(unsigned int cpu) { unsigned int txdivtime; struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); @@ -132,27 +132,9 @@ static void arch_timer_setup(unsigned int cpu) val = core_reg_read(TXUCT_ID, TXTIMER_REGNUM, thread0); __core_reg_set(TXTIMER, val); } + return 0; } -static int arch_timer_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) -{ - int cpu = (long)hcpu; - - switch (action) { - case CPU_STARTING: - case CPU_STARTING_FROZEN: - arch_timer_setup(cpu); - break; - } - - return NOTIFY_OK; -} - -static struct notifier_block arch_timer_cpu_nb = { - .notifier_call = arch_timer_cpu_notify, -}; - int __init metag_generic_timer_init(void) { /* @@ -170,11 +152,8 @@ int __init metag_generic_timer_init(void) setup_irq(tbisig_map(TBID_SIGNUM_TRT), &metag_timer_irq); - /* Configure timer on boot CPU */ - arch_timer_setup(smp_processor_id()); - - /* Hook cpu boot to configure other CPU's timers */ - register_cpu_notifier(&arch_timer_cpu_nb); - - return 0; + /* Hook cpu boot to configure the CPU's timers */ + return cpuhp_setup_state(CPUHP_AP_METAG_TIMER_STARTING, + "AP_METAG_TIMER_STARTING", + arch_timer_starting_cpu, NULL); } diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index 1572c7a778ab..b4b3ab5a11ad 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c @@ -49,10 +49,9 @@ struct irqaction gic_compare_irqaction = { .name = "timer", }; -static void gic_clockevent_cpu_init(struct clock_event_device *cd) +static void gic_clockevent_cpu_init(unsigned int cpu, + struct clock_event_device *cd) { - unsigned int cpu = smp_processor_id(); - cd->name = "MIPS GIC"; cd->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; @@ -79,19 +78,10 @@ static void gic_update_frequency(void *data) clockevents_update_freq(this_cpu_ptr(&gic_clockevent_device), rate); } -static int gic_cpu_notifier(struct notifier_block *nb, unsigned long action, - void *data) +static int gic_starting_cpu(unsigned int cpu) { - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_STARTING: - gic_clockevent_cpu_init(this_cpu_ptr(&gic_clockevent_device)); - break; - case CPU_DYING: - gic_clockevent_cpu_exit(this_cpu_ptr(&gic_clockevent_device)); - break; - } - - return NOTIFY_OK; + gic_clockevent_cpu_init(cpu, this_cpu_ptr(&gic_clockevent_device)); + return 0; } static int gic_clk_notifier(struct notifier_block *nb, unsigned long action, @@ -105,10 +95,11 @@ static int gic_clk_notifier(struct notifier_block *nb, unsigned long action, return NOTIFY_OK; } - -static struct notifier_block gic_cpu_nb = { - .notifier_call = gic_cpu_notifier, -}; +static int gic_dying_cpu(unsigned int cpu) +{ + gic_clockevent_cpu_exit(this_cpu_ptr(&gic_clockevent_device)); + return 0; +} static struct notifier_block gic_clk_nb = { .notifier_call = gic_clk_notifier, @@ -125,12 +116,9 @@ static int gic_clockevent_init(void) if (ret < 0) return ret; - ret = register_cpu_notifier(&gic_cpu_nb); - if (ret < 0) - pr_warn("GIC: Unable to register CPU notifier\n"); - - gic_clockevent_cpu_init(this_cpu_ptr(&gic_clockevent_device)); - + cpuhp_setup_state(CPUHP_AP_MIPS_GIC_TIMER_STARTING, + "AP_MIPS_GIC_TIMER_STARTING", gic_starting_cpu, + gic_dying_cpu); return 0; } @@ -176,7 +164,7 @@ void __init gic_clocksource_init(unsigned int frequency) gic_start_count(); } -static void __init gic_clocksource_of_init(struct device_node *node) +static int __init gic_clocksource_of_init(struct device_node *node) { struct clk *clk; int ret; diff --git a/drivers/clocksource/pxa_timer.c b/drivers/clocksource/pxa_timer.c index 937e10b84d58..3e1cb512f3ce 100644 --- a/drivers/clocksource/pxa_timer.c +++ b/drivers/clocksource/pxa_timer.c @@ -21,6 +21,8 @@ #include <linux/of_irq.h> #include <linux/sched_clock.h> +#include <clocksource/pxa.h> + #include <asm/div64.h> #define OSMR0 0x00 /* OS Timer 0 Match Register */ diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c index 662576339049..3283cfa2aa52 100644 --- a/drivers/clocksource/qcom-timer.c +++ b/drivers/clocksource/qcom-timer.c @@ -105,9 +105,9 @@ static struct clocksource msm_clocksource = { static int msm_timer_irq; static int msm_timer_has_ppi; -static int msm_local_timer_setup(struct clock_event_device *evt) +static int msm_local_timer_starting_cpu(unsigned int cpu) { - int cpu = smp_processor_id(); + struct clock_event_device *evt = per_cpu_ptr(msm_evt, cpu); int err; evt->irq = msm_timer_irq; @@ -135,35 +135,15 @@ static int msm_local_timer_setup(struct clock_event_device *evt) return 0; } -static void msm_local_timer_stop(struct clock_event_device *evt) +static int msm_local_timer_dying_cpu(unsigned int cpu) { + struct clock_event_device *evt = per_cpu_ptr(msm_evt, cpu); + evt->set_state_shutdown(evt); disable_percpu_irq(evt->irq); + return 0; } -static int msm_timer_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) -{ - /* - * Grab cpu pointer in each case to avoid spurious - * preemptible warnings - */ - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_STARTING: - msm_local_timer_setup(this_cpu_ptr(msm_evt)); - break; - case CPU_DYING: - msm_local_timer_stop(this_cpu_ptr(msm_evt)); - break; - } - - return NOTIFY_OK; -} - -static struct notifier_block msm_timer_cpu_nb = { - .notifier_call = msm_timer_cpu_notify, -}; - static u64 notrace msm_sched_clock_read(void) { return msm_clocksource.read(&msm_clocksource); @@ -200,14 +180,15 @@ static int __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq, if (res) { pr_err("request_percpu_irq failed\n"); } else { - res = register_cpu_notifier(&msm_timer_cpu_nb); + /* Install and invoke hotplug callbacks */ + res = cpuhp_setup_state(CPUHP_AP_QCOM_TIMER_STARTING, + "AP_QCOM_TIMER_STARTING", + msm_local_timer_starting_cpu, + msm_local_timer_dying_cpu); if (res) { free_percpu_irq(irq, msm_evt); goto err; } - - /* Immediately configure the timer on the boot CPU */ - msm_local_timer_setup(raw_cpu_ptr(msm_evt)); } err: diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 97669ee4df2a..c83452cacb41 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -123,12 +123,16 @@ static struct clock_event_device sun4i_clockevent = { .set_next_event = sun4i_clkevt_next_event, }; +static void sun4i_timer_clear_interrupt(void) +{ + writel(TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_ST_REG); +} static irqreturn_t sun4i_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = (struct clock_event_device *)dev_id; - writel(0x1, timer_base + TIMER_IRQ_ST_REG); + sun4i_timer_clear_interrupt(); evt->event_handler(evt); return IRQ_HANDLED; @@ -208,6 +212,9 @@ static int __init sun4i_timer_init(struct device_node *node) /* Make sure timer is stopped before playing with interrupts */ sun4i_clkevt_time_stop(0); + /* clear timer0 interrupt */ + sun4i_timer_clear_interrupt(); + sun4i_clockevent.cpumask = cpu_possible_mask; sun4i_clockevent.irq = irq; diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index 20ec066481fe..3c39e6f45971 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@ -170,10 +170,10 @@ static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id) /* * Setup the local clock events for a CPU. */ -static int armada_370_xp_timer_setup(struct clock_event_device *evt) +static int armada_370_xp_timer_starting_cpu(unsigned int cpu) { + struct clock_event_device *evt = per_cpu_ptr(armada_370_xp_evt, cpu); u32 clr = 0, set = 0; - int cpu = smp_processor_id(); if (timer25Mhz) set = TIMER0_25MHZ; @@ -200,35 +200,15 @@ static int armada_370_xp_timer_setup(struct clock_event_device *evt) return 0; } -static void armada_370_xp_timer_stop(struct clock_event_device *evt) +static int armada_370_xp_timer_dying_cpu(unsigned int cpu) { + struct clock_event_device *evt = per_cpu_ptr(armada_370_xp_evt, cpu); + evt->set_state_shutdown(evt); disable_percpu_irq(evt->irq); + return 0; } -static int armada_370_xp_timer_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) -{ - /* - * Grab cpu pointer in each case to avoid spurious - * preemptible warnings - */ - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_STARTING: - armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt)); - break; - case CPU_DYING: - armada_370_xp_timer_stop(this_cpu_ptr(armada_370_xp_evt)); - break; - } - - return NOTIFY_OK; -} - -static struct notifier_block armada_370_xp_timer_cpu_nb = { - .notifier_call = armada_370_xp_timer_cpu_notify, -}; - static u32 timer0_ctrl_reg, timer0_local_ctrl_reg; static int armada_370_xp_timer_suspend(void) @@ -322,8 +302,6 @@ static int __init armada_370_xp_timer_common_init(struct device_node *np) return res; } - register_cpu_notifier(&armada_370_xp_timer_cpu_nb); - armada_370_xp_evt = alloc_percpu(struct clock_event_device); if (!armada_370_xp_evt) return -ENOMEM; @@ -341,9 +319,12 @@ static int __init armada_370_xp_timer_common_init(struct device_node *np) return res; } - res = armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt)); + res = cpuhp_setup_state(CPUHP_AP_ARMADA_TIMER_STARTING, + "AP_ARMADA_TIMER_STARTING", + armada_370_xp_timer_starting_cpu, + armada_370_xp_timer_dying_cpu); if (res) { - pr_err("Failed to setup timer"); + pr_err("Failed to setup hotplug state and timer"); return res; } @@ -357,7 +338,6 @@ static int __init armada_xp_timer_init(struct device_node *np) struct clk *clk = of_clk_get_by_name(np, "fixed"); int ret; - clk = of_clk_get(np, 0); if (IS_ERR(clk)) { pr_err("Failed to get clock"); return PTR_ERR(clk); diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c index a7d9a08e4b0e..a8e6c7df853d 100644 --- a/drivers/clocksource/time-pistachio.c +++ b/drivers/clocksource/time-pistachio.c @@ -202,10 +202,10 @@ static int __init pistachio_clksrc_of_init(struct device_node *node) rate = clk_get_rate(fast_clk); /* Disable irq's for clocksource usage */ - gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 0); - gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 1); - gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 2); - gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 3); + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 0); + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 1); + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 2); + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 3); /* Enable timer block */ writel(TIMER_ME_GLOBAL, pcs_gpt.base); diff --git a/drivers/clocksource/timer-atlas7.c b/drivers/clocksource/timer-atlas7.c index 90f8fbc154a4..4334e0330ada 100644 --- a/drivers/clocksource/timer-atlas7.c +++ b/drivers/clocksource/timer-atlas7.c @@ -172,9 +172,9 @@ static struct irqaction sirfsoc_timer1_irq = { .handler = sirfsoc_timer_interrupt, }; -static int sirfsoc_local_timer_setup(struct clock_event_device *ce) +static int sirfsoc_local_timer_starting_cpu(unsigned int cpu) { - int cpu = smp_processor_id(); + struct clock_event_device *ce = per_cpu_ptr(sirfsoc_clockevent, cpu); struct irqaction *action; if (cpu == 0) @@ -203,50 +203,27 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce) return 0; } -static void sirfsoc_local_timer_stop(struct clock_event_device *ce) +static int sirfsoc_local_timer_dying_cpu(unsigned int cpu) { - int cpu = smp_processor_id(); - sirfsoc_timer_count_disable(1); if (cpu == 0) remove_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq); else remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq); + return 0; } -static int sirfsoc_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) -{ - /* - * Grab cpu pointer in each case to avoid spurious - * preemptible warnings - */ - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_STARTING: - sirfsoc_local_timer_setup(this_cpu_ptr(sirfsoc_clockevent)); - break; - case CPU_DYING: - sirfsoc_local_timer_stop(this_cpu_ptr(sirfsoc_clockevent)); - break; - } - - return NOTIFY_OK; -} - -static struct notifier_block sirfsoc_cpu_nb = { - .notifier_call = sirfsoc_cpu_notify, -}; - static int __init sirfsoc_clockevent_init(void) { sirfsoc_clockevent = alloc_percpu(struct clock_event_device); BUG_ON(!sirfsoc_clockevent); - BUG_ON(register_cpu_notifier(&sirfsoc_cpu_nb)); - - /* Immediately configure the timer on the boot CPU */ - return sirfsoc_local_timer_setup(this_cpu_ptr(sirfsoc_clockevent)); + /* Install and invoke hotplug callbacks */ + return cpuhp_setup_state(CPUHP_AP_MARCO_TIMER_STARTING, + "AP_MARCO_TIMER_STARTING", + sirfsoc_local_timer_starting_cpu, + sirfsoc_local_timer_dying_cpu); } /* initialize the kernel jiffy timer source */ diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c index 1ffac0cb0cb7..7f0f5b26d8c5 100644 --- a/drivers/clocksource/timer-atmel-pit.c +++ b/drivers/clocksource/timer-atmel-pit.c @@ -240,6 +240,7 @@ static int __init at91sam926x_pit_common_init(struct pit_data *data) static int __init at91sam926x_pit_dt_init(struct device_node *node) { struct pit_data *data; + int ret; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) @@ -261,6 +262,12 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node) return PTR_ERR(data->mck); } + ret = clk_prepare_enable(data->mck); + if (ret) { + pr_err("Unable to enable mck\n"); + return ret; + } + /* Get the interrupts property */ data->irq = irq_of_parse_and_map(node, 0); if (!data->irq) { |