From: Benedikt Spranger Date: Sat, 6 Mar 2010 17:47:10 +0100 Subject: ARM: AT91: PIT: Remove irq handler when clock event is unused Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.14/older/patches-4.14.8-rt9.tar.xz 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 Signed-off-by: Thomas Gleixner [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 suggested]. Signed-off-by: Sebastian Andrzej Siewior --- drivers/clocksource/timer-atmel-pit.c | 18 +++++++++--------- drivers/clocksource/timer-atmel-st.c | 34 ++++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 21 deletions(-) --- a/drivers/clocksource/timer-atmel-pit.c +++ b/drivers/clocksource/timer-atmel-pit.c @@ -96,15 +96,24 @@ static int pit_clkevt_shutdown(struct cl /* 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_ini 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; --- a/drivers/clocksource/timer-atmel-st.c +++ b/drivers/clocksource/timer-atmel-st.c @@ -115,18 +115,29 @@ static void clkdev32k_disable_and_flush_ 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 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(st { 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(st 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");