diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2020-03-19 09:39:48 +0100 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2020-03-19 09:39:48 +0100 |
commit | 048495eb28939996261754215b1d450756978499 (patch) | |
tree | 80ab17fd471962ec07e3546f75cbf126a1883ae4 /drivers/clocksource | |
parent | d441dceb5dce71150f28add80d36d91bbfccba99 (diff) | |
parent | 4f41fe386a94639cd9a1831298d4f85db5662f1e (diff) |
Merge tag 'timers-v5.7' of https://git.linaro.org/people/daniel.lezcano/linux into timers/core
Pull clockevent/clocksource updates from Daniel Lezcano:
- Avoid creating dead devices by flagging the driver with OF_POPULATED
in order to prevent the platform to create another device (Saravana Kannan)
- Remove unused includes from imx family drivers (Anson Huang)
- timer-dm-ti rework to prepare for pwm and suspend support (Lokesh Vutla)
- Fix the rate for the global clock on the pit64b (Claudiu Beznea)
- Fix timer-cs5535 by requesting an irq with non-NULL dev_id (Afzal Mohammed)
- Replace setup_irq() by request_irq() (Afzal Mohammed)
- Add support for the TCU of X1000 (Zhou Yanjie)
- Drop the bogus omap_dm_timer_of_set_source() function (Suman Anna)
- Do not update the counter when updating the period in order to
prevent a disruption when the pwm is used (Lokesh Vutla)
- Improve owl_timer_init() failure messages (Matheus Castello)
- Add driver for the Ingenic JZ47xx OST (Maarten ter Huurne)
- Pass the interrupt and the shutdown callbacks in the init function
for ast2600 support (Joel Stanley)
- Add the ast2600 compatible string for the fttmr010 (Joel Stanley)
Diffstat (limited to 'drivers/clocksource')
33 files changed, 459 insertions, 321 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index cc909e465823..f2142e6bbea3 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -697,6 +697,14 @@ config INGENIC_TIMER help Support for the timer/counter unit of the Ingenic JZ SoCs. +config INGENIC_OST + bool "Clocksource for Ingenic OS Timer" + depends on MIPS || COMPILE_TEST + depends on COMMON_CLK + select MFD_SYSCON + help + Support for the Operating System Timer of the Ingenic JZ SoCs. + config MICROCHIP_PIT64B bool "Microchip PIT64B support" depends on OF || COMPILE_TEST diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 713686faa549..641ba5383ab5 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -80,6 +80,7 @@ obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o obj-$(CONFIG_H8300_TPU) += h8300_tpu.o +obj-$(CONFIG_INGENIC_OST) += ingenic-ost.o obj-$(CONFIG_INGENIC_TIMER) += ingenic-timer.o obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o obj-$(CONFIG_X86_NUMACHIP) += numachip.o diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c index b235f446ee50..1592650b2c92 100644 --- a/drivers/clocksource/bcm2835_timer.c +++ b/drivers/clocksource/bcm2835_timer.c @@ -31,7 +31,6 @@ struct bcm2835_timer { void __iomem *compare; int match_mask; struct clock_event_device evt; - struct irqaction act; }; static void __iomem *system_clock __read_mostly; @@ -113,12 +112,9 @@ static int __init bcm2835_timer_init(struct device_node *node) timer->evt.features = CLOCK_EVT_FEAT_ONESHOT; timer->evt.set_next_event = bcm2835_time_set_next_event; timer->evt.cpumask = cpumask_of(0); - timer->act.name = node->name; - timer->act.flags = IRQF_TIMER | IRQF_SHARED; - timer->act.dev_id = timer; - timer->act.handler = bcm2835_time_interrupt; - ret = setup_irq(irq, &timer->act); + ret = request_irq(irq, bcm2835_time_interrupt, IRQF_TIMER | IRQF_SHARED, + node->name, timer); if (ret) { pr_err("Can't set up timer IRQ\n"); goto err_timer_free; diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c index 5c40be9880f5..a50ab5c2154f 100644 --- a/drivers/clocksource/bcm_kona_timer.c +++ b/drivers/clocksource/bcm_kona_timer.c @@ -160,12 +160,6 @@ static irqreturn_t kona_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction kona_timer_irq = { - .name = "Kona Timer Tick", - .flags = IRQF_TIMER, - .handler = kona_timer_interrupt, -}; - static int __init kona_timer_init(struct device_node *node) { u32 freq; @@ -192,7 +186,9 @@ static int __init kona_timer_init(struct device_node *node) kona_timer_disable_and_clear(timers.tmr_regs); kona_timer_clockevents_init(); - setup_irq(timers.tmr_irq, &kona_timer_irq); + if (request_irq(timers.tmr_irq, kona_timer_interrupt, IRQF_TIMER, + "Kona Timer Tick", NULL)) + pr_err("%s: request_irq() failed\n", "Kona Timer Tick"); kona_timer_set_next_event((arch_timer_rate / HZ), NULL); return 0; diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index 654766538f93..b207a77b0831 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c @@ -270,15 +270,10 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating, dw_ced->ced.rating = rating; dw_ced->ced.name = name; - dw_ced->irqaction.name = dw_ced->ced.name; - dw_ced->irqaction.handler = dw_apb_clockevent_irq; - dw_ced->irqaction.dev_id = &dw_ced->ced; - dw_ced->irqaction.irq = irq; - dw_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | - IRQF_NOBALANCING; - dw_ced->eoi = apbt_eoi; - err = setup_irq(irq, &dw_ced->irqaction); + err = request_irq(irq, dw_apb_clockevent_irq, + IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, + dw_ced->ced.name, &dw_ced->ced); if (err) { pr_err("failed to request timer irq\n"); kfree(dw_ced); diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index a267fe31ef13..fabad79baafc 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -329,19 +329,15 @@ static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction mct_comp_event_irq = { - .name = "mct_comp_irq", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = exynos4_mct_comp_isr, - .dev_id = &mct_comp_device, -}; - static int exynos4_clockevent_init(void) { mct_comp_device.cpumask = cpumask_of(0); clockevents_config_and_register(&mct_comp_device, clk_rate, 0xf, 0xffffffff); - setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq); + if (request_irq(mct_irqs[MCT_G0_IRQ], exynos4_mct_comp_isr, + IRQF_TIMER | IRQF_IRQPOLL, "mct_comp_irq", + &mct_comp_device)) + pr_err("%s: request_irq() failed\n", "mct_comp_irq"); return 0; } diff --git a/drivers/clocksource/ingenic-ost.c b/drivers/clocksource/ingenic-ost.c new file mode 100644 index 000000000000..029efc2731b4 --- /dev/null +++ b/drivers/clocksource/ingenic-ost.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * JZ47xx SoCs TCU Operating System Timer driver + * + * Copyright (C) 2016 Maarten ter Huurne <maarten@treewalker.org> + * Copyright (C) 2020 Paul Cercueil <paul@crapouillou.net> + */ + +#include <linux/clk.h> +#include <linux/clocksource.h> +#include <linux/mfd/ingenic-tcu.h> +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/regmap.h> +#include <linux/sched_clock.h> + +#define TCU_OST_TCSR_MASK 0xffc0 +#define TCU_OST_TCSR_CNT_MD BIT(15) + +#define TCU_OST_CHANNEL 15 + +/* + * The TCU_REG_OST_CNT{L,R} from <linux/mfd/ingenic-tcu.h> are only for the + * regmap; these are for use with the __iomem pointer. + */ +#define OST_REG_CNTL 0x4 +#define OST_REG_CNTH 0x8 + +struct ingenic_ost_soc_info { + bool is64bit; +}; + +struct ingenic_ost { + void __iomem *regs; + struct clk *clk; + + struct clocksource cs; +}; + +static struct ingenic_ost *ingenic_ost; + +static u64 notrace ingenic_ost_read_cntl(void) +{ + /* Read using __iomem pointer instead of regmap to avoid locking */ + return readl(ingenic_ost->regs + OST_REG_CNTL); +} + +static u64 notrace ingenic_ost_read_cnth(void) +{ + /* Read using __iomem pointer instead of regmap to avoid locking */ + return readl(ingenic_ost->regs + OST_REG_CNTH); +} + +static u64 notrace ingenic_ost_clocksource_readl(struct clocksource *cs) +{ + return ingenic_ost_read_cntl(); +} + +static u64 notrace ingenic_ost_clocksource_readh(struct clocksource *cs) +{ + return ingenic_ost_read_cnth(); +} + +static int __init ingenic_ost_probe(struct platform_device *pdev) +{ + const struct ingenic_ost_soc_info *soc_info; + struct device *dev = &pdev->dev; + struct ingenic_ost *ost; + struct clocksource *cs; + struct regmap *map; + unsigned long rate; + int err; + + soc_info = device_get_match_data(dev); + if (!soc_info) + return -EINVAL; + + ost = devm_kzalloc(dev, sizeof(*ost), GFP_KERNEL); + if (!ost) + return -ENOMEM; + + ingenic_ost = ost; + + ost->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ost->regs)) + return PTR_ERR(ost->regs); + + map = device_node_to_regmap(dev->parent->of_node); + if (!map) { + dev_err(dev, "regmap not found"); + return -EINVAL; + } + + ost->clk = devm_clk_get(dev, "ost"); + if (IS_ERR(ost->clk)) + return PTR_ERR(ost->clk); + + err = clk_prepare_enable(ost->clk); + if (err) + return err; + + /* Clear counter high/low registers */ + if (soc_info->is64bit) + regmap_write(map, TCU_REG_OST_CNTL, 0); + regmap_write(map, TCU_REG_OST_CNTH, 0); + + /* Don't reset counter at compare value. */ + regmap_update_bits(map, TCU_REG_OST_TCSR, + TCU_OST_TCSR_MASK, TCU_OST_TCSR_CNT_MD); + + rate = clk_get_rate(ost->clk); + + /* Enable OST TCU channel */ + regmap_write(map, TCU_REG_TESR, BIT(TCU_OST_CHANNEL)); + + cs = &ost->cs; + cs->name = "ingenic-ost"; + cs->rating = 320; + cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; + cs->mask = CLOCKSOURCE_MASK(32); + + if (soc_info->is64bit) + cs->read = ingenic_ost_clocksource_readl; + else + cs->read = ingenic_ost_clocksource_readh; + + err = clocksource_register_hz(cs, rate); + if (err) { + dev_err(dev, "clocksource registration failed"); + clk_disable_unprepare(ost->clk); + return err; + } + + if (soc_info->is64bit) + sched_clock_register(ingenic_ost_read_cntl, 32, rate); + else + sched_clock_register(ingenic_ost_read_cnth, 32, rate); + + return 0; +} + +static int __maybe_unused ingenic_ost_suspend(struct device *dev) +{ + struct ingenic_ost *ost = dev_get_drvdata(dev); + + clk_disable(ost->clk); + + return 0; +} + +static int __maybe_unused ingenic_ost_resume(struct device *dev) +{ + struct ingenic_ost *ost = dev_get_drvdata(dev); + + return clk_enable(ost->clk); +} + +static const struct dev_pm_ops __maybe_unused ingenic_ost_pm_ops = { + /* _noirq: We want the OST clock to be gated last / ungated first */ + .suspend_noirq = ingenic_ost_suspend, + .resume_noirq = ingenic_ost_resume, +}; + +static const struct ingenic_ost_soc_info jz4725b_ost_soc_info = { + .is64bit = false, +}; + +static const struct ingenic_ost_soc_info jz4770_ost_soc_info = { + .is64bit = true, +}; + +static const struct of_device_id ingenic_ost_of_match[] = { + { .compatible = "ingenic,jz4725b-ost", .data = &jz4725b_ost_soc_info, }, + { .compatible = "ingenic,jz4770-ost", .data = &jz4770_ost_soc_info, }, + { } +}; + +static struct platform_driver ingenic_ost_driver = { + .driver = { + .name = "ingenic-ost", +#ifdef CONFIG_PM_SUSPEND + .pm = &ingenic_ost_pm_ops, +#endif + .of_match_table = ingenic_ost_of_match, + }, +}; +builtin_platform_driver_probe(ingenic_ost_driver, ingenic_ost_probe); diff --git a/drivers/clocksource/ingenic-timer.c b/drivers/clocksource/ingenic-timer.c index 4bbdb3d3d0c6..496333650de2 100644 --- a/drivers/clocksource/ingenic-timer.c +++ b/drivers/clocksource/ingenic-timer.c @@ -230,6 +230,7 @@ static const struct of_device_id ingenic_tcu_of_match[] = { { .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, }, { .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, }, { .compatible = "ingenic,jz4770-tcu", .data = &jz4740_soc_info, }, + { .compatible = "ingenic,x1000-tcu", .data = &jz4740_soc_info, }, { /* sentinel */ } }; @@ -302,7 +303,7 @@ err_free_ingenic_tcu: TIMER_OF_DECLARE(jz4740_tcu_intc, "ingenic,jz4740-tcu", ingenic_tcu_init); TIMER_OF_DECLARE(jz4725b_tcu_intc, "ingenic,jz4725b-tcu", ingenic_tcu_init); TIMER_OF_DECLARE(jz4770_tcu_intc, "ingenic,jz4770-tcu", ingenic_tcu_init); - +TIMER_OF_DECLARE(x1000_tcu_intc, "ingenic,x1000-tcu", ingenic_tcu_init); static int __init ingenic_tcu_probe(struct platform_device *pdev) { diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c index f6ddae30933f..bc96a4cbf26c 100644 --- a/drivers/clocksource/mxs_timer.c +++ b/drivers/clocksource/mxs_timer.c @@ -117,13 +117,6 @@ static irqreturn_t mxs_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction mxs_timer_irq = { - .name = "MXS Timer Tick", - .dev_id = &mxs_clockevent_device, - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = mxs_timer_interrupt, -}; - static void mxs_irq_clear(char *state) { /* Disable interrupt in timer module */ @@ -277,6 +270,7 @@ static int __init mxs_timer_init(struct device_node *np) if (irq <= 0) return -EINVAL; - return setup_irq(irq, &mxs_timer_irq); + return request_irq(irq, mxs_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, + "MXS Timer Tick", &mxs_clockevent_device); } TIMER_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init); diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c index 3f7fa8c01367..f49a631d8f58 100644 --- a/drivers/clocksource/nomadik-mtu.c +++ b/drivers/clocksource/nomadik-mtu.c @@ -181,13 +181,6 @@ static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction nmdk_timer_irq = { - .name = "Nomadik Timer Tick", - .flags = IRQF_TIMER, - .handler = nmdk_timer_interrupt, - .dev_id = &nmdk_clkevt, -}; - static int __init nmdk_timer_init(void __iomem *base, int irq, struct clk *pclk, struct clk *clk) { @@ -232,7 +225,9 @@ static int __init nmdk_timer_init(void __iomem *base, int irq, sched_clock_register(nomadik_read_sched_clock, 32, rate); /* Timer 1 is used for events, register irq and clockevents */ - setup_irq(irq, &nmdk_timer_irq); + if (request_irq(irq, nmdk_timer_interrupt, IRQF_TIMER, + "Nomadik Timer Tick", &nmdk_clkevt)) + pr_err("%s: request_irq() failed\n", "Nomadik Timer Tick"); nmdk_clkevt.cpumask = cpumask_of(0); nmdk_clkevt.irq = irq; clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU); diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c index dae1b2b5a0c5..f760229d0c7f 100644 --- a/drivers/clocksource/samsung_pwm_timer.c +++ b/drivers/clocksource/samsung_pwm_timer.c @@ -256,13 +256,6 @@ static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction samsung_clock_event_irq = { - .name = "samsung_time_irq", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = samsung_clock_event_isr, - .dev_id = &time_event_device, -}; - static void __init samsung_clockevent_init(void) { unsigned long pclk; @@ -282,7 +275,10 @@ static void __init samsung_clockevent_init(void) clock_rate, 1, pwm.tcnt_max); irq_number = pwm.irq[pwm.event_id]; - setup_irq(irq_number, &samsung_clock_event_irq); + if (request_irq(irq_number, samsung_clock_event_isr, + IRQF_TIMER | IRQF_IRQPOLL, "samsung_time_irq", + &time_event_device)) + pr_err("%s: request_irq() failed\n", "samsung_time_irq"); if (pwm.variant.has_tint_cstat) { u32 mask = (1 << pwm.event_id); diff --git a/drivers/clocksource/timer-atlas7.c b/drivers/clocksource/timer-atlas7.c index 93c3ac6d72bd..c21c91c2bc56 100644 --- a/drivers/clocksource/timer-atlas7.c +++ b/drivers/clocksource/timer-atlas7.c @@ -159,29 +159,23 @@ static struct clocksource sirfsoc_clocksource = { .resume = sirfsoc_clocksource_resume, }; -static struct irqaction sirfsoc_timer_irq = { - .name = "sirfsoc_timer0", - .flags = IRQF_TIMER | IRQF_NOBALANCING, - .handler = sirfsoc_timer_interrupt, -}; - -static struct irqaction sirfsoc_timer1_irq = { - .name = "sirfsoc_timer1", - .flags = IRQF_TIMER | IRQF_NOBALANCING, - .handler = sirfsoc_timer_interrupt, -}; +static unsigned int sirfsoc_timer_irq, sirfsoc_timer1_irq; static int sirfsoc_local_timer_starting_cpu(unsigned int cpu) { struct clock_event_device *ce = per_cpu_ptr(sirfsoc_clockevent, cpu); - struct irqaction *action; - - if (cpu == 0) - action = &sirfsoc_timer_irq; - else - action = &sirfsoc_timer1_irq; + unsigned int irq; + const char *name; + + if (cpu == 0) { + irq = sirfsoc_timer_irq; + name = "sirfsoc_timer0"; + } else { + irq = sirfsoc_timer1_irq; + name = "sirfsoc_timer1"; + } - ce->irq = action->irq; + ce->irq = irq; ce->name = "local_timer"; ce->features = CLOCK_EVT_FEAT_ONESHOT; ce->rating = 200; @@ -196,9 +190,9 @@ static int sirfsoc_local_timer_starting_cpu(unsigned int cpu) ce->min_delta_ticks = 2; ce->cpumask = cpumask_of(cpu); - action->dev_id = ce; - BUG_ON(setup_irq(ce->irq, action)); - irq_force_affinity(action->irq, cpumask_of(cpu)); + BUG_ON(request_irq(ce->irq, sirfsoc_timer_interrupt, + IRQF_TIMER | IRQF_NOBALANCING, name, ce)); + irq_force_affinity(ce->irq, cpumask_of(cpu)); clockevents_register_device(ce); return 0; @@ -206,12 +200,14 @@ static int sirfsoc_local_timer_starting_cpu(unsigned int cpu) static int sirfsoc_local_timer_dying_cpu(unsigned int cpu) { + struct clock_event_device *ce = per_cpu_ptr(sirfsoc_clockevent, cpu); + sirfsoc_timer_count_disable(1); if (cpu == 0) - remove_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq); + free_irq(sirfsoc_timer_irq, ce); else - remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq); + free_irq(sirfsoc_timer1_irq, ce); return 0; } @@ -268,14 +264,14 @@ static int __init sirfsoc_of_timer_init(struct device_node *np) return -ENXIO; } - sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0); - if (!sirfsoc_timer_irq.irq) { + sirfsoc_timer_irq = irq_of_parse_and_map(np, 0); + if (!sirfsoc_timer_irq) { pr_err("No irq passed for timer0 via DT\n"); return -EINVAL; } - sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1); - if (!sirfsoc_timer1_irq.irq) { + sirfsoc_timer1_irq = irq_of_parse_and_map(np, 1); + if (!sirfsoc_timer1_irq) { pr_err("No irq passed for timer1 via DT\n"); return -EINVAL; } diff --git a/drivers/clocksource/timer-cs5535.c b/drivers/clocksource/timer-cs5535.c index 8f6bc536bef2..d47acfe848ae 100644 --- a/drivers/clocksource/timer-cs5535.c +++ b/drivers/clocksource/timer-cs5535.c @@ -131,14 +131,9 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction mfgptirq = { - .handler = mfgpt_tick, - .flags = IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED, - .name = DRV_NAME, -}; - static int __init cs5535_mfgpt_init(void) { + unsigned long flags = IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED; struct cs5535_mfgpt_timer *timer; int ret; uint16_t val; @@ -158,7 +153,7 @@ static int __init cs5535_mfgpt_init(void) } /* And register it with the kernel */ - ret = setup_irq(timer_irq, &mfgptirq); + ret = request_irq(timer_irq, mfgpt_tick, flags, DRV_NAME, timer); if (ret) { printk(KERN_ERR DRV_NAME ": Unable to set up the interrupt.\n"); goto err_irq; diff --git a/drivers/clocksource/timer-efm32.c b/drivers/clocksource/timer-efm32.c index 5a22cb079ad3..441a4b916841 100644 --- a/drivers/clocksource/timer-efm32.c +++ b/drivers/clocksource/timer-efm32.c @@ -119,13 +119,6 @@ static struct efm32_clock_event_ddata clock_event_ddata = { }, }; -static struct irqaction efm32_clock_event_irq = { - .name = "efm32 clockevent", - .flags = IRQF_TIMER, - .handler = efm32_clock_event_handler, - .dev_id = &clock_event_ddata, -}; - static int __init efm32_clocksource_init(struct device_node *np) { struct clk *clk; @@ -230,7 +223,8 @@ static int __init efm32_clockevent_init(struct device_node *np) DIV_ROUND_CLOSEST(rate, 1024), 0xf, 0xffff); - ret = setup_irq(irq, &efm32_clock_event_irq); + ret = request_irq(irq, efm32_clock_event_handler, IRQF_TIMER, + "efm32 clockevent", &clock_event_ddata); if (ret) { pr_err("Failed setup irq\n"); goto err_setup_irq; diff --git a/drivers/clocksource/timer-fsl-ftm.c b/drivers/clocksource/timer-fsl-ftm.c index a9d9a3ca5996..12a2ed7cfaff 100644 --- a/drivers/clocksource/timer-fsl-ftm.c +++ b/drivers/clocksource/timer-fsl-ftm.c @@ -176,13 +176,6 @@ static struct clock_event_device ftm_clockevent = { .rating = 300, }; -static struct irqaction ftm_timer_irq = { - .name = "Freescale ftm timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = ftm_evt_interrupt, - .dev_id = &ftm_clockevent, -}; - static int __init ftm_clockevent_init(unsigned long freq, int irq) { int err; @@ -192,7 +185,8 @@ static int __init ftm_clockevent_init(unsigned long freq, int irq) ftm_reset_counter(priv->clkevt_base); - err = setup_irq(irq, &ftm_timer_irq); + err = request_irq(irq, ftm_evt_interrupt, IRQF_TIMER | IRQF_IRQPOLL, + "Freescale ftm timer", &ftm_clockevent); if (err) { pr_err("ftm: setup irq failed: %d\n", err); return err; diff --git a/drivers/clocksource/timer-fttmr010.c b/drivers/clocksource/timer-fttmr010.c index fadff7915dd9..edb1d5f193f5 100644 --- a/drivers/clocksource/timer-fttmr010.c +++ b/drivers/clocksource/timer-fttmr010.c @@ -38,6 +38,11 @@ #define TIMER_CR (0x30) /* + * Control register set to clear for ast2600 only. + */ +#define AST2600_TIMER_CR_CLR (0x3c) + +/* * Control register (TMC30) bit fields for fttmr010/gemini/moxart timers. */ #define TIMER_1_CR_ENABLE BIT(0) @@ -97,6 +102,7 @@ struct fttmr010 { bool is_aspeed; u32 t1_enable_val; struct clock_event_device clkevt; + int (*timer_shutdown)(struct clock_event_device *evt); #ifdef CONFIG_ARM struct delay_timer delay_timer; #endif @@ -140,9 +146,7 @@ static int fttmr010_timer_set_next_event(unsigned long cycles, u32 cr; /* Stop */ - cr = readl(fttmr010->base + TIMER_CR); - cr &= ~fttmr010->t1_enable_val; - writel(cr, fttmr010->base + TIMER_CR); + fttmr010->timer_shutdown(evt); if (fttmr010->is_aspeed) { /* @@ -164,6 +168,16 @@ static int fttmr010_timer_set_next_event(unsigned long cycles, return 0; } +static int ast2600_timer_shutdown(struct clock_event_device *evt) +{ + struct fttmr010 *fttmr010 = to_fttmr010(evt); + + /* Stop */ + writel(fttmr010->t1_enable_val, fttmr010->base + AST2600_TIMER_CR_CLR); + + return 0; +} + static int fttmr010_timer_shutdown(struct clock_event_device *evt) { struct fttmr010 *fttmr010 = to_fttmr010(evt); @@ -183,9 +197,7 @@ static int fttmr010_timer_set_oneshot(struct clock_event_device *evt) u32 cr; /* Stop */ - cr = readl(fttmr010->base + TIMER_CR); - cr &= ~fttmr010->t1_enable_val; - writel(cr, fttmr010->base + TIMER_CR); + fttmr010->timer_shutdown(evt); /* Setup counter start from 0 or ~0 */ writel(0, fttmr010->base + TIMER1_COUNT); @@ -211,9 +223,7 @@ static int fttmr010_timer_set_periodic(struct clock_event_device *evt) u32 cr; /* Stop */ - cr = readl(fttmr010->base + TIMER_CR); - cr &= ~fttmr010->t1_enable_val; - writel(cr, fttmr010->base + TIMER_CR); + fttmr010->timer_shutdown(evt); /* Setup timer to fire at 1/HZ intervals. */ if (fttmr010->is_aspeed) { @@ -249,7 +259,21 @@ static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed) +static irqreturn_t ast2600_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + struct fttmr010 *fttmr010 = to_fttmr010(evt); + + writel(0x1, fttmr010->base + TIMER_INTR_STATE); + + evt->event_handler(evt); + return IRQ_HANDLED; +} + +static int __init fttmr010_common_init(struct device_node *np, + bool is_aspeed, + int (*timer_shutdown)(struct clock_event_device *), + irq_handler_t irq_handler) { struct fttmr010 *fttmr010; int irq; @@ -350,6 +374,8 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed) fttmr010->tick_rate); } + fttmr010->timer_shutdown = timer_shutdown; + /* * Setup clockevent timer (interrupt-driven) on timer 1. */ @@ -357,7 +383,7 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed) writel(0, fttmr010->base + TIMER1_LOAD); writel(0, fttmr010->base + TIMER1_MATCH1); writel(0, fttmr010->base + TIMER1_MATCH2); - ret = request_irq(irq, fttmr010_timer_interrupt, IRQF_TIMER, + ret = request_irq(irq, irq_handler, IRQF_TIMER, "FTT |