157 lines
5.0 KiB
Diff
157 lines
5.0 KiB
Diff
|
From 8cd864ed82e31456f316eb79641466106683f1a8 Mon Sep 17 00:00:00 2001
|
||
|
From: Benedikt Spranger <b.spranger@linutronix.de>
|
||
|
Date: Sat, 6 Mar 2010 17:47:10 +0100
|
||
|
Subject: [PATCH 056/365] ARM: AT91: PIT: Remove irq handler when clock event
|
||
|
is unused
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
Setup and remove the interrupt handler in clock event mode selection.
|
||
|
This avoids calling the (shared) interrupt handler when the device is
|
||
|
not used.
|
||
|
|
||
|
Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
|
||
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||
|
[bigeasy: redo the patch with NR_IRQS_LEGACY which is probably required since
|
||
|
commit 8fe82a55 ("ARM: at91: sparse irq support") which is included since v3.6.
|
||
|
Patch based on what Sami Pietikäinen <Sami.Pietikainen@wapice.com> suggested].
|
||
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||
|
---
|
||
|
drivers/clocksource/timer-atmel-pit.c | 18 +++++++-------
|
||
|
drivers/clocksource/timer-atmel-st.c | 34 +++++++++++++++++----------
|
||
|
2 files changed, 31 insertions(+), 21 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c
|
||
|
index 6555821bbdae..2c66bb3e595b 100644
|
||
|
--- a/drivers/clocksource/timer-atmel-pit.c
|
||
|
+++ b/drivers/clocksource/timer-atmel-pit.c
|
||
|
@@ -96,15 +96,24 @@ static int pit_clkevt_shutdown(struct clock_event_device *dev)
|
||
|
|
||
|
/* disable irq, leaving the clocksource active */
|
||
|
pit_write(data->base, AT91_PIT_MR, (data->cycle - 1) | AT91_PIT_PITEN);
|
||
|
+ free_irq(data->irq, data);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id);
|
||
|
/*
|
||
|
* Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16)
|
||
|
*/
|
||
|
static int pit_clkevt_set_periodic(struct clock_event_device *dev)
|
||
|
{
|
||
|
struct pit_data *data = clkevt_to_pit_data(dev);
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ ret = request_irq(data->irq, at91sam926x_pit_interrupt,
|
||
|
+ IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
|
||
|
+ "at91_tick", data);
|
||
|
+ if (ret)
|
||
|
+ panic(pr_fmt("Unable to setup IRQ\n"));
|
||
|
|
||
|
/* update clocksource counter */
|
||
|
data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
|
||
|
@@ -230,15 +239,6 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
- /* Set up irq handler */
|
||
|
- ret = request_irq(data->irq, at91sam926x_pit_interrupt,
|
||
|
- IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
|
||
|
- "at91_tick", data);
|
||
|
- if (ret) {
|
||
|
- pr_err("Unable to setup IRQ\n");
|
||
|
- return ret;
|
||
|
- }
|
||
|
-
|
||
|
/* Set up and register clockevents */
|
||
|
data->clkevt.name = "pit";
|
||
|
data->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
|
||
|
diff --git a/drivers/clocksource/timer-atmel-st.c b/drivers/clocksource/timer-atmel-st.c
|
||
|
index e90ab5b63a90..9e124087c55f 100644
|
||
|
--- a/drivers/clocksource/timer-atmel-st.c
|
||
|
+++ b/drivers/clocksource/timer-atmel-st.c
|
||
|
@@ -115,18 +115,29 @@ static void clkdev32k_disable_and_flush_irq(void)
|
||
|
last_crtr = read_CRTR();
|
||
|
}
|
||
|
|
||
|
+static int atmel_st_irq;
|
||
|
+
|
||
|
static int clkevt32k_shutdown(struct clock_event_device *evt)
|
||
|
{
|
||
|
clkdev32k_disable_and_flush_irq();
|
||
|
irqmask = 0;
|
||
|
regmap_write(regmap_st, AT91_ST_IER, irqmask);
|
||
|
+ free_irq(atmel_st_irq, regmap_st);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int clkevt32k_set_oneshot(struct clock_event_device *dev)
|
||
|
{
|
||
|
+ int ret;
|
||
|
+
|
||
|
clkdev32k_disable_and_flush_irq();
|
||
|
|
||
|
+ ret = request_irq(atmel_st_irq, at91rm9200_timer_interrupt,
|
||
|
+ IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
|
||
|
+ "at91_tick", regmap_st);
|
||
|
+ if (ret)
|
||
|
+ panic(pr_fmt("Unable to setup IRQ\n"));
|
||
|
+
|
||
|
/*
|
||
|
* ALM for oneshot irqs, set by next_event()
|
||
|
* before 32 seconds have passed.
|
||
|
@@ -139,8 +150,16 @@ static int clkevt32k_set_oneshot(struct clock_event_device *dev)
|
||
|
|
||
|
static int clkevt32k_set_periodic(struct clock_event_device *dev)
|
||
|
{
|
||
|
+ int ret;
|
||
|
+
|
||
|
clkdev32k_disable_and_flush_irq();
|
||
|
|
||
|
+ ret = request_irq(atmel_st_irq, at91rm9200_timer_interrupt,
|
||
|
+ IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
|
||
|
+ "at91_tick", regmap_st);
|
||
|
+ if (ret)
|
||
|
+ panic(pr_fmt("Unable to setup IRQ\n"));
|
||
|
+
|
||
|
/* PIT for periodic irqs; fixed rate of 1/HZ */
|
||
|
irqmask = AT91_ST_PITS;
|
||
|
regmap_write(regmap_st, AT91_ST_PIMR, timer_latch);
|
||
|
@@ -198,7 +217,7 @@ static int __init atmel_st_timer_init(struct device_node *node)
|
||
|
{
|
||
|
struct clk *sclk;
|
||
|
unsigned int sclk_rate, val;
|
||
|
- int irq, ret;
|
||
|
+ int ret;
|
||
|
|
||
|
regmap_st = syscon_node_to_regmap(node);
|
||
|
if (IS_ERR(regmap_st)) {
|
||
|
@@ -212,21 +231,12 @@ static int __init atmel_st_timer_init(struct device_node *node)
|
||
|
regmap_read(regmap_st, AT91_ST_SR, &val);
|
||
|
|
||
|
/* Get the interrupts property */
|
||
|
- irq = irq_of_parse_and_map(node, 0);
|
||
|
- if (!irq) {
|
||
|
+ atmel_st_irq = irq_of_parse_and_map(node, 0);
|
||
|
+ if (!atmel_st_irq) {
|
||
|
pr_err("Unable to get IRQ from DT\n");
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
- /* Make IRQs happen for the system timer */
|
||
|
- ret = request_irq(irq, at91rm9200_timer_interrupt,
|
||
|
- IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
|
||
|
- "at91_tick", regmap_st);
|
||
|
- if (ret) {
|
||
|
- pr_err("Unable to setup IRQ\n");
|
||
|
- return ret;
|
||
|
- }
|
||
|
-
|
||
|
sclk = of_clk_get(node, 0);
|
||
|
if (IS_ERR(sclk)) {
|
||
|
pr_err("Unable to get slow clock\n");
|
||
|
--
|
||
|
2.28.0
|
||
|
|