ARM: gic: Consolidate PPI handling with request_percpu_irq() API
The commit 292b293 creates the MSM boot failures, so squash
the commit 28af690 with it to avoid such failures. The commit ddd847
and 0c1991 are required to keep the watchdog and Copper targets working.
commit 292b293ceef2eda1f96f0c90b96e954d7bdabd1c
Author: Marc Zyngier <marc.zyngier@arm.com>
Date: Wed Jul 20 16:24:14 2011 +0100
ARM: gic: consolidate PPI handling
PPI handling is a bit of an odd beast. It uses its own low level
handling code and is hardwired to the local timers (hence lacking
a registration interface).
Instead, switch the low handling to the normal SPI handling code.
PPIs are handled by the handle_percpu_devid_irq flow.
This also allows the removal of some duplicated code.
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: David Brown <davidb@codeaurora.org>
Cc: Bryan Huntsman <bryanh@codeaurora.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Acked-by: David Brown <davidb@codeaurora.org>
Tested-by: David Brown <davidb@codeaurora.org>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
commit 28af690a284dfcb627bd69d0963db1c0f412cb8c
Author: Marc Zyngier <marc.zyngier@arm.com>
Date: Fri Jul 22 12:52:37 2011 +0100
ARM: gic, local timers: use the request_percpu_irq() interface
This patch remove the hardcoded link between local timers and PPIs,
and convert the PPI users (TWD, MCT and MSM timers) to the new
*_percpu_irq interface. Also some collateral cleanup
(local_timer_ack() is gone, and the interrupt handler is strictly
private to each driver).
PPIs are now useable for more than just the local timers.
Additional testing by David Brown (msm8250 and msm8660) and
Shawn Guo (imx6q).
Cc: David Brown <davidb@codeaurora.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Acked-by: David Brown <davidb@codeaurora.org>
Tested-by: David Brown <davidb@codeaurora.org>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
commit ddd8478d68f8cf75ee9771667c0cbe2a9d1caeb9
Author: Trilok Soni <tsoni@codeaurora.org>
Date: Tue Dec 6 00:56:01 2011 +0530
msm: watchdog: Use request_percpu_irq() interface
Change-Id: I7c319344f6a7f7a7c70682ac87f5c385e56d130c
Signed-off-by: Trilok Soni <tsoni@codeaurora.org>
Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
commit 0c19915e092214a4c17a9920c4c1f3d78610217d
Author: Sathish Ambley <sambley@codeaurora.org>
Date: Fri Dec 9 17:07:37 2011 +0530
arm: arch_timer: Use request_percpu_irq() API
Change-Id: Iee9b218d538f315cd884a47d95bcc0dcc49b0fe1
Signed-off-by: Sathish Ambley <sambley@codeaurora.org>
Change-Id: I7bbba706b1f2e55814be5891ed76063725c2bfb1
Signed-off-by: Ravi Kumar <kumarrav@codeaurora.org>
[tsoni@codeaurora.org: MSM specific fixes]
Signed-off-by: Trilok Soni <tsoni@codeaurora.org>
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 7e61e8b..6f04470 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -102,7 +102,7 @@
struct msm_clock {
struct clock_event_device clockevent;
struct clocksource clocksource;
- struct irqaction irq;
+ unsigned int irq;
void __iomem *regbase;
uint32_t freq;
uint32_t shift;
@@ -110,6 +110,12 @@
uint32_t write_delay;
uint32_t rollover_offset;
uint32_t index;
+ void __iomem *global_counter;
+ void __iomem *local_counter;
+ union {
+ struct clock_event_device *evt;
+ struct clock_event_device __percpu **percpu_evt;
+ };
};
enum {
@@ -117,7 +123,6 @@
MSM_CLOCK_DGT,
};
-
struct msm_clock_percpu_data {
uint32_t last_set;
uint32_t sleep_offset;
@@ -155,14 +160,7 @@
.shift = 17,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
},
- .irq = {
- .name = "gp_timer",
- .flags = IRQF_DISABLED | IRQF_TIMER |
- IRQF_TRIGGER_RISING,
- .handler = msm_timer_interrupt,
- .dev_id = &msm_clocks[0].clockevent,
- .irq = INT_GP_TIMER_EXP
- },
+ .irq = INT_GP_TIMER_EXP,
.regbase = MSM_TMR_BASE + 0x4,
.freq = 32768,
.index = MSM_CLOCK_GPT,
@@ -185,22 +183,13 @@
.shift = 24,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
},
- .irq = {
- .name = "dg_timer",
- .flags = IRQF_DISABLED | IRQF_TIMER |
- IRQF_TRIGGER_RISING,
- .handler = msm_timer_interrupt,
- .dev_id = &msm_clocks[1].clockevent,
- .irq = INT_DEBUG_TIMER_EXP
- },
+ .irq = INT_DEBUG_TIMER_EXP,
.regbase = MSM_TMR_BASE + 0x24,
.index = MSM_CLOCK_DGT,
.write_delay = 9,
}
};
-static DEFINE_PER_CPU(struct clock_event_device*, local_clock_event);
-
static DEFINE_PER_CPU(struct msm_clock_percpu_data[NR_TIMERS],
msm_clocks_percpu);
@@ -208,9 +197,7 @@
static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
{
- struct clock_event_device *evt = dev_id;
- if (smp_processor_id() != 0)
- evt = __get_cpu_var(local_clock_event);
+ struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
if (evt->event_handler == NULL)
return IRQ_HANDLED;
evt->event_handler(evt);
@@ -356,9 +343,9 @@
get_cpu_var(msm_active_clock) = clock;
put_cpu_var(msm_active_clock);
__raw_writel(TIMER_ENABLE_EN, clock->regbase + TIMER_ENABLE);
- chip = irq_get_chip(clock->irq.irq);
+ chip = irq_get_chip(clock->irq);
if (chip && chip->irq_unmask)
- chip->irq_unmask(irq_get_irq_data(clock->irq.irq));
+ chip->irq_unmask(irq_get_irq_data(clock->irq));
if (clock != &msm_clocks[MSM_CLOCK_GPT])
__raw_writel(TIMER_ENABLE_EN,
msm_clocks[MSM_CLOCK_GPT].regbase +
@@ -374,9 +361,9 @@
msm_read_timer_count(clock, LOCAL_TIMER) +
clock_state->sleep_offset;
__raw_writel(0, clock->regbase + TIMER_MATCH_VAL);
- chip = irq_get_chip(clock->irq.irq);
+ chip = irq_get_chip(clock->irq);
if (chip && chip->irq_mask)
- chip->irq_mask(irq_get_irq_data(clock->irq.irq));
+ chip->irq_mask(irq_get_irq_data(clock->irq));
if (!is_smp() || clock != &msm_clocks[MSM_CLOCK_DGT]
|| smp_processor_id())
@@ -1073,14 +1060,35 @@
printk(KERN_ERR "msm_timer_init: clocksource_register "
"failed for %s\n", cs->name);
- res = setup_irq(clock->irq.irq, &clock->irq);
- if (res)
- printk(KERN_ERR "msm_timer_init: setup_irq "
- "failed for %s\n", cs->name);
+ ce->irq = clock->irq;
+ if (cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064() ||
+ cpu_is_msm8930() || cpu_is_msm9615()) {
+ clock->percpu_evt = alloc_percpu(struct clock_event_device *);
+ if (!clock->percpu_evt) {
+ pr_err("msm_timer_init: memory allocation "
+ "failed for %s\n", ce->name);
+ continue;
+ }
- chip = irq_get_chip(clock->irq.irq);
+ *__this_cpu_ptr(clock->percpu_evt) = ce;
+ res = request_percpu_irq(ce->irq, msm_timer_interrupt,
+ ce->name, clock->percpu_evt);
+ if (!res)
+ enable_percpu_irq(ce->irq, 0);
+ } else {
+ clock->evt = ce;
+ res = request_irq(ce->irq, msm_timer_interrupt,
+ IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
+ ce->name, &clock->evt);
+ }
+
+ if (res)
+ pr_err("msm_timer_init: request_irq failed for %s\n",
+ ce->name);
+
+ chip = irq_get_chip(clock->irq);
if (chip && chip->irq_mask)
- chip->irq_mask(irq_get_irq_data(clock->irq.irq));
+ chip->irq_mask(irq_get_irq_data(clock->irq));
clockevents_register_device(ce);
}
@@ -1097,7 +1105,6 @@
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
- unsigned long flags;
static DEFINE_PER_CPU(bool, first_boot) = true;
struct msm_clock *clock = &msm_clocks[msm_global_timer];
@@ -1115,7 +1122,7 @@
__raw_writel(~0, clock->regbase + TIMER_MATCH_VAL);
__get_cpu_var(first_boot) = false;
}
- evt->irq = clock->irq.irq;
+ evt->irq = clock->irq;
evt->name = "local_timer";
evt->features = CLOCK_EVT_FEAT_ONESHOT;
evt->rating = clock->clockevent.rating;
@@ -1127,21 +1134,18 @@
clockevent_delta2ns(0xf0000000 >> clock->shift, evt);
evt->min_delta_ns = clockevent_delta2ns(4, evt);
- __get_cpu_var(local_clock_event) = evt;
-
- local_irq_save(flags);
- gic_clear_spi_pending(clock->irq.irq);
- local_irq_restore(flags);
- gic_enable_ppi(clock->irq.irq);
+ *__this_cpu_ptr(clock->percpu_evt) = evt;
clockevents_register_device(evt);
+ enable_percpu_irq(evt->irq, 0);
return 0;
}
-int local_timer_ack(void)
+void local_timer_stop(struct clock_event_device *evt)
{
- return 1;
+ evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+ disable_percpu_irq(evt->irq);
}
#endif