From: Stephen Boyd <sboyd@codeaurora.org>
To: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org
Subject: [PATCHv7 10/11] clocksource: time-armada-370-xp: Divorce from local timer API
Date: Mon, 3 Jun 2013 13:34:01 -0700 [thread overview]
Message-ID: <1370291642-13259-11-git-send-email-sboyd@codeaurora.org> (raw)
In-Reply-To: <1370291642-13259-1-git-send-email-sboyd@codeaurora.org>
Separate the armada 370xp local timers from the local timer API.
This will allow us to remove ARM local timer support in the near
future and makes this driver multi-architecture friendly.
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
drivers/clocksource/time-armada-370-xp.c | 89 +++++++++++++++-----------------
1 file changed, 41 insertions(+), 48 deletions(-)
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index efe4aef..4a31e86 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/clk.h>
+#include <linux/cpu.h>
#include <linux/timer.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
@@ -31,7 +32,6 @@
#include <linux/time-armada-370-xp.h>
#include <asm/sched_clock.h>
-#include <asm/localtimer.h>
/*
* Timer block registers.
*/
@@ -70,7 +70,7 @@ static bool timer25Mhz = true;
*/
static u32 ticks_per_jiffy;
-static struct clock_event_device __percpu **percpu_armada_370_xp_evt;
+static struct clock_event_device __percpu *armada_370_xp_evt;
static u32 notrace armada_370_xp_read_sched_clock(void)
{
@@ -143,21 +143,14 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode,
}
}
-static struct clock_event_device armada_370_xp_clkevt = {
- .name = "armada_370_xp_per_cpu_tick",
- .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
- .shift = 32,
- .rating = 300,
- .set_next_event = armada_370_xp_clkevt_next_event,
- .set_mode = armada_370_xp_clkevt_mode,
-};
+static int armada_370_xp_clkevt_irq;
static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id)
{
/*
* ACK timer interrupt and call event handler.
*/
- struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+ struct clock_event_device *evt = dev_id;
writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS);
evt->event_handler(evt);
@@ -173,42 +166,55 @@ static int __cpuinit armada_370_xp_timer_setup(struct clock_event_device *evt)
u32 u;
int cpu = smp_processor_id();
- /* Use existing clock_event for cpu 0 */
- if (!smp_processor_id())
- return 0;
-
u = readl(local_base + TIMER_CTRL_OFF);
if (timer25Mhz)
writel(u | TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
else
writel(u & ~TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
- evt->name = armada_370_xp_clkevt.name;
- evt->irq = armada_370_xp_clkevt.irq;
- evt->features = armada_370_xp_clkevt.features;
- evt->shift = armada_370_xp_clkevt.shift;
- evt->rating = armada_370_xp_clkevt.rating,
+ evt->name = "armada_370_xp_per_cpu_tick",
+ evt->features = CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_PERIODIC;
+ evt->shift = 32,
+ evt->rating = 300,
evt->set_next_event = armada_370_xp_clkevt_next_event,
evt->set_mode = armada_370_xp_clkevt_mode,
+ evt->irq = armada_370_xp_clkevt_irq;
evt->cpumask = cpumask_of(cpu);
- *__this_cpu_ptr(percpu_armada_370_xp_evt) = evt;
-
clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe);
enable_percpu_irq(evt->irq, 0);
return 0;
}
-static void armada_370_xp_timer_stop(struct clock_event_device *evt)
+static void __cpuinit armada_370_xp_timer_stop(struct clock_event_device *evt)
{
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
disable_percpu_irq(evt->irq);
}
-static struct local_timer_ops armada_370_xp_local_timer_ops __cpuinitdata = {
- .setup = armada_370_xp_timer_setup,
- .stop = armada_370_xp_timer_stop,
+static int __cpuinit 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 __cpuinitdata = {
+ .notifier_call = armada_370_xp_timer_cpu_notify,
};
void __init armada_370_xp_timer_init(void)
@@ -224,9 +230,6 @@ void __init armada_370_xp_timer_init(void)
if (of_find_property(np, "marvell,timer-25Mhz", NULL)) {
/* The fixed 25MHz timer is available so let's use it */
- u = readl(local_base + TIMER_CTRL_OFF);
- writel(u | TIMER0_25MHZ,
- local_base + TIMER_CTRL_OFF);
u = readl(timer_base + TIMER_CTRL_OFF);
writel(u | TIMER0_25MHZ,
timer_base + TIMER_CTRL_OFF);
@@ -236,9 +239,6 @@ void __init armada_370_xp_timer_init(void)
struct clk *clk = of_clk_get(np, 0);
WARN_ON(IS_ERR(clk));
rate = clk_get_rate(clk);
- u = readl(local_base + TIMER_CTRL_OFF);
- writel(u & ~(TIMER0_25MHZ),
- local_base + TIMER_CTRL_OFF);
u = readl(timer_base + TIMER_CTRL_OFF);
writel(u & ~(TIMER0_25MHZ),
@@ -252,7 +252,7 @@ void __init armada_370_xp_timer_init(void)
* We use timer 0 as clocksource, and private(local) timer 0
* for clockevents
*/
- armada_370_xp_clkevt.irq = irq_of_parse_and_map(np, 4);
+ armada_370_xp_clkevt_irq = irq_of_parse_and_map(np, 4);
ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
@@ -277,26 +277,19 @@ void __init armada_370_xp_timer_init(void)
"armada_370_xp_clocksource",
timer_clk, 300, 32, clocksource_mmio_readl_down);
- /* Register the clockevent on the private timer of CPU 0 */
- armada_370_xp_clkevt.cpumask = cpumask_of(0);
- clockevents_config_and_register(&armada_370_xp_clkevt,
- timer_clk, 1, 0xfffffffe);
+ register_cpu_notifier(&armada_370_xp_timer_cpu_nb);
- percpu_armada_370_xp_evt = alloc_percpu(struct clock_event_device *);
+ armada_370_xp_evt = alloc_percpu(struct clock_event_device);
/*
* Setup clockevent timer (interrupt-driven).
*/
- *__this_cpu_ptr(percpu_armada_370_xp_evt) = &armada_370_xp_clkevt;
- res = request_percpu_irq(armada_370_xp_clkevt.irq,
+ res = request_percpu_irq(armada_370_xp_clkevt_irq,
armada_370_xp_timer_interrupt,
- armada_370_xp_clkevt.name,
- percpu_armada_370_xp_evt);
- if (!res) {
- enable_percpu_irq(armada_370_xp_clkevt.irq, 0);
-#ifdef CONFIG_LOCAL_TIMERS
- local_timer_register(&armada_370_xp_local_timer_ops);
-#endif
- }
+ "armada_370_xp_per_cpu_tick",
+ armada_370_xp_evt);
+ /* Immediately configure the timer on the boot CPU */
+ if (!res)
+ armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
}
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
WARNING: multiple messages have this Message-ID (diff)
From: sboyd@codeaurora.org (Stephen Boyd)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCHv7 10/11] clocksource: time-armada-370-xp: Divorce from local timer API
Date: Mon, 3 Jun 2013 13:34:01 -0700 [thread overview]
Message-ID: <1370291642-13259-11-git-send-email-sboyd@codeaurora.org> (raw)
In-Reply-To: <1370291642-13259-1-git-send-email-sboyd@codeaurora.org>
Separate the armada 370xp local timers from the local timer API.
This will allow us to remove ARM local timer support in the near
future and makes this driver multi-architecture friendly.
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>,
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
drivers/clocksource/time-armada-370-xp.c | 89 +++++++++++++++-----------------
1 file changed, 41 insertions(+), 48 deletions(-)
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index efe4aef..4a31e86 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/clk.h>
+#include <linux/cpu.h>
#include <linux/timer.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
@@ -31,7 +32,6 @@
#include <linux/time-armada-370-xp.h>
#include <asm/sched_clock.h>
-#include <asm/localtimer.h>
/*
* Timer block registers.
*/
@@ -70,7 +70,7 @@ static bool timer25Mhz = true;
*/
static u32 ticks_per_jiffy;
-static struct clock_event_device __percpu **percpu_armada_370_xp_evt;
+static struct clock_event_device __percpu *armada_370_xp_evt;
static u32 notrace armada_370_xp_read_sched_clock(void)
{
@@ -143,21 +143,14 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode,
}
}
-static struct clock_event_device armada_370_xp_clkevt = {
- .name = "armada_370_xp_per_cpu_tick",
- .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
- .shift = 32,
- .rating = 300,
- .set_next_event = armada_370_xp_clkevt_next_event,
- .set_mode = armada_370_xp_clkevt_mode,
-};
+static int armada_370_xp_clkevt_irq;
static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id)
{
/*
* ACK timer interrupt and call event handler.
*/
- struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+ struct clock_event_device *evt = dev_id;
writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS);
evt->event_handler(evt);
@@ -173,42 +166,55 @@ static int __cpuinit armada_370_xp_timer_setup(struct clock_event_device *evt)
u32 u;
int cpu = smp_processor_id();
- /* Use existing clock_event for cpu 0 */
- if (!smp_processor_id())
- return 0;
-
u = readl(local_base + TIMER_CTRL_OFF);
if (timer25Mhz)
writel(u | TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
else
writel(u & ~TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
- evt->name = armada_370_xp_clkevt.name;
- evt->irq = armada_370_xp_clkevt.irq;
- evt->features = armada_370_xp_clkevt.features;
- evt->shift = armada_370_xp_clkevt.shift;
- evt->rating = armada_370_xp_clkevt.rating,
+ evt->name = "armada_370_xp_per_cpu_tick",
+ evt->features = CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_PERIODIC;
+ evt->shift = 32,
+ evt->rating = 300,
evt->set_next_event = armada_370_xp_clkevt_next_event,
evt->set_mode = armada_370_xp_clkevt_mode,
+ evt->irq = armada_370_xp_clkevt_irq;
evt->cpumask = cpumask_of(cpu);
- *__this_cpu_ptr(percpu_armada_370_xp_evt) = evt;
-
clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe);
enable_percpu_irq(evt->irq, 0);
return 0;
}
-static void armada_370_xp_timer_stop(struct clock_event_device *evt)
+static void __cpuinit armada_370_xp_timer_stop(struct clock_event_device *evt)
{
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
disable_percpu_irq(evt->irq);
}
-static struct local_timer_ops armada_370_xp_local_timer_ops __cpuinitdata = {
- .setup = armada_370_xp_timer_setup,
- .stop = armada_370_xp_timer_stop,
+static int __cpuinit 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 __cpuinitdata = {
+ .notifier_call = armada_370_xp_timer_cpu_notify,
};
void __init armada_370_xp_timer_init(void)
@@ -224,9 +230,6 @@ void __init armada_370_xp_timer_init(void)
if (of_find_property(np, "marvell,timer-25Mhz", NULL)) {
/* The fixed 25MHz timer is available so let's use it */
- u = readl(local_base + TIMER_CTRL_OFF);
- writel(u | TIMER0_25MHZ,
- local_base + TIMER_CTRL_OFF);
u = readl(timer_base + TIMER_CTRL_OFF);
writel(u | TIMER0_25MHZ,
timer_base + TIMER_CTRL_OFF);
@@ -236,9 +239,6 @@ void __init armada_370_xp_timer_init(void)
struct clk *clk = of_clk_get(np, 0);
WARN_ON(IS_ERR(clk));
rate = clk_get_rate(clk);
- u = readl(local_base + TIMER_CTRL_OFF);
- writel(u & ~(TIMER0_25MHZ),
- local_base + TIMER_CTRL_OFF);
u = readl(timer_base + TIMER_CTRL_OFF);
writel(u & ~(TIMER0_25MHZ),
@@ -252,7 +252,7 @@ void __init armada_370_xp_timer_init(void)
* We use timer 0 as clocksource, and private(local) timer 0
* for clockevents
*/
- armada_370_xp_clkevt.irq = irq_of_parse_and_map(np, 4);
+ armada_370_xp_clkevt_irq = irq_of_parse_and_map(np, 4);
ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
@@ -277,26 +277,19 @@ void __init armada_370_xp_timer_init(void)
"armada_370_xp_clocksource",
timer_clk, 300, 32, clocksource_mmio_readl_down);
- /* Register the clockevent on the private timer of CPU 0 */
- armada_370_xp_clkevt.cpumask = cpumask_of(0);
- clockevents_config_and_register(&armada_370_xp_clkevt,
- timer_clk, 1, 0xfffffffe);
+ register_cpu_notifier(&armada_370_xp_timer_cpu_nb);
- percpu_armada_370_xp_evt = alloc_percpu(struct clock_event_device *);
+ armada_370_xp_evt = alloc_percpu(struct clock_event_device);
/*
* Setup clockevent timer (interrupt-driven).
*/
- *__this_cpu_ptr(percpu_armada_370_xp_evt) = &armada_370_xp_clkevt;
- res = request_percpu_irq(armada_370_xp_clkevt.irq,
+ res = request_percpu_irq(armada_370_xp_clkevt_irq,
armada_370_xp_timer_interrupt,
- armada_370_xp_clkevt.name,
- percpu_armada_370_xp_evt);
- if (!res) {
- enable_percpu_irq(armada_370_xp_clkevt.irq, 0);
-#ifdef CONFIG_LOCAL_TIMERS
- local_timer_register(&armada_370_xp_local_timer_ops);
-#endif
- }
+ "armada_370_xp_per_cpu_tick",
+ armada_370_xp_evt);
+ /* Immediately configure the timer on the boot CPU */
+ if (!res)
+ armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
}
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
next prev parent reply other threads:[~2013-06-03 20:34 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-03 20:33 [PATCHv7 00/11] Remove ARM local timer API Stephen Boyd
2013-06-03 20:33 ` Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 01/11] clockevents: Prefer CPU local devices over global devices Stephen Boyd
2013-06-03 20:33 ` Stephen Boyd
2013-06-06 15:12 ` Daniel Lezcano
2013-06-06 15:12 ` Daniel Lezcano
2013-06-06 18:04 ` Stephen Boyd
2013-06-06 18:04 ` Stephen Boyd
2013-06-06 22:30 ` Daniel Lezcano
2013-06-06 22:30 ` Daniel Lezcano
2013-06-06 22:38 ` Stephen Boyd
2013-06-06 22:38 ` Stephen Boyd
2013-06-12 21:44 ` Stephen Boyd
2013-06-12 21:44 ` Stephen Boyd
2013-06-13 9:33 ` Daniel Lezcano
2013-06-13 9:33 ` Daniel Lezcano
2013-06-13 13:15 ` Thomas Gleixner
2013-06-13 13:15 ` Thomas Gleixner
2013-06-13 18:39 ` Stephen Boyd
2013-06-13 18:39 ` Stephen Boyd
2013-06-13 20:16 ` Sören Brinkmann
2013-06-13 20:16 ` Sören Brinkmann
2013-06-13 20:16 ` Sören Brinkmann
2013-06-18 10:22 ` Mark Rutland
2013-06-18 10:22 ` Mark Rutland
2013-06-19 16:30 ` Stephen Boyd
2013-06-19 16:30 ` Stephen Boyd
2013-06-21 17:07 ` Stephen Boyd
2013-06-21 17:07 ` Stephen Boyd
2013-06-24 20:07 ` Stephen Boyd
2013-06-24 20:07 ` Stephen Boyd
2013-06-24 20:30 ` [tip:timers/core] " tip-bot for Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 02/11] clocksource: add generic dummy timer driver Stephen Boyd
2013-06-03 20:33 ` Stephen Boyd
2013-06-06 16:23 ` Daniel Lezcano
2013-06-06 16:23 ` Daniel Lezcano
2013-06-24 20:30 ` [tip:timers/core] clocksource: Add " tip-bot for Mark Rutland
2013-06-03 20:33 ` [PATCHv7 03/11] ARM: smp: Remove duplicate dummy timer implementation Stephen Boyd
2013-06-03 20:33 ` Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 04/11] ARM: smp_twd: Divorce smp_twd from local timer API Stephen Boyd
2013-06-03 20:33 ` Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 05/11] ARM: OMAP2+: Divorce " Stephen Boyd
2013-06-03 20:33 ` Stephen Boyd
2013-06-03 20:33 ` Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 06/11] ARM: EXYNOS4: Divorce mct " Stephen Boyd
2013-06-03 20:33 ` Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 07/11] ARM: PRIMA2: Divorce timer-marco " Stephen Boyd
2013-06-03 20:33 ` Stephen Boyd
2013-06-03 20:33 ` [PATCHv7 08/11] ARM: msm: Divorce msm_timer " Stephen Boyd
2013-06-03 20:33 ` Stephen Boyd
2013-06-03 20:34 ` [PATCHv7 09/11] clocksource: time-armada-370-xp: Fix sparse warning Stephen Boyd
2013-06-03 20:34 ` Stephen Boyd
2013-06-03 20:34 ` Stephen Boyd [this message]
2013-06-03 20:34 ` [PATCHv7 10/11] clocksource: time-armada-370-xp: Divorce from local timer API Stephen Boyd
2013-06-03 20:34 ` [PATCHv7 11/11] ARM: smp: Remove " Stephen Boyd
2013-06-03 20:34 ` Stephen Boyd
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1370291642-13259-11-git-send-email-sboyd@codeaurora.org \
--to=sboyd@codeaurora.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.