summaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/arm_arch_timer.c80
-rw-r--r--drivers/clocksource/arm_global_timer.c39
-rw-r--r--drivers/clocksource/bcm_kona_timer.c16
-rw-r--r--drivers/clocksource/clps711x-timer.c2
-rw-r--r--drivers/clocksource/dummy_timer.c36
-rw-r--r--drivers/clocksource/exynos_mct.c46
-rw-r--r--drivers/clocksource/metag_generic.c33
-rw-r--r--drivers/clocksource/mips-gic-timer.c40
-rw-r--r--drivers/clocksource/pxa_timer.c2
-rw-r--r--drivers/clocksource/qcom-timer.c41
-rw-r--r--drivers/clocksource/sun4i_timer.c9
-rw-r--r--drivers/clocksource/time-armada-370-xp.c42
-rw-r--r--drivers/clocksource/time-pistachio.c8
-rw-r--r--drivers/clocksource/timer-atlas7.c41
-rw-r--r--drivers/clocksource/timer-atmel-pit.c7
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(&gt_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(&gt_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) {
OpenPOWER on IntegriCloud