- 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)
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQRuKdf4M92Gi9vqihve5qtOL396pgUCXnJaXQAKCRDe5qtOL396
 pmVbAQChth0V/THG4aN/JySIIAmeY+u7VhYeI60AcPPpQa7iwQEA9G9ZRErogMQ/
 TDqgFKiLVR6Q+pyjCM0O96Z6rqSQ4g8=
 =iNoR
 -----END PGP SIGNATURE-----

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)
This commit is contained in:
Thomas Gleixner 2020-03-19 09:39:48 +01:00
commit 048495eb28
39 changed files with 470 additions and 329 deletions

View File

@ -11,6 +11,7 @@ Required properties:
"moxa,moxart-timer", "faraday,fttmr010"
"aspeed,ast2400-timer"
"aspeed,ast2500-timer"
"aspeed,ast2600-timer"
- reg : Should contain registers location and length
- interrupts : Should contain the three timer interrupts usually with

View File

@ -10,6 +10,7 @@ Required properties:
* ingenic,jz4740-tcu
* ingenic,jz4725b-tcu
* ingenic,jz4770-tcu
* ingenic,x1000-tcu
followed by "simple-mfd".
- reg: Should be the offset/length value corresponding to the TCU registers
- clocks: List of phandle & clock specifiers for clocks external to the TCU.

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
unsigned int irq;
const char *name;
if (cpu == 0)
action = &sirfsoc_timer_irq;
else
action = &sirfsoc_timer1_irq;
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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -37,6 +37,11 @@
#define TIMER3_MATCH2 (0x2c)
#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.
*/
@ -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,
"FTTMR010-TIMER1", &fttmr010->clkevt);
if (ret) {
pr_err("FTTMR010-TIMER1 no IRQ\n");
@ -370,10 +396,10 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed)
fttmr010->clkevt.features = CLOCK_EVT_FEAT_PERIODIC |
CLOCK_EVT_FEAT_ONESHOT;
fttmr010->clkevt.set_next_event = fttmr010_timer_set_next_event;
fttmr010->clkevt.set_state_shutdown = fttmr010_timer_shutdown;
fttmr010->clkevt.set_state_shutdown = fttmr010->timer_shutdown;
fttmr010->clkevt.set_state_periodic = fttmr010_timer_set_periodic;
fttmr010->clkevt.set_state_oneshot = fttmr010_timer_set_oneshot;
fttmr010->clkevt.tick_resume = fttmr010_timer_shutdown;
fttmr010->clkevt.tick_resume = fttmr010->timer_shutdown;
fttmr010->clkevt.cpumask = cpumask_of(0);
fttmr010->clkevt.irq = irq;
clockevents_config_and_register(&fttmr010->clkevt,
@ -404,14 +430,25 @@ out_disable_clock:
return ret;
}
static __init int ast2600_timer_init(struct device_node *np)
{
return fttmr010_common_init(np, true,
ast2600_timer_shutdown,
ast2600_timer_interrupt);
}
static __init int aspeed_timer_init(struct device_node *np)
{
return fttmr010_common_init(np, true);
return fttmr010_common_init(np, true,
fttmr010_timer_shutdown,
fttmr010_timer_interrupt);
}
static __init int fttmr010_timer_init(struct device_node *np)
{
return fttmr010_common_init(np, false);
return fttmr010_common_init(np, false,
fttmr010_timer_shutdown,
fttmr010_timer_interrupt);
}
TIMER_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_init);
@ -419,3 +456,4 @@ TIMER_OF_DECLARE(gemini, "cortina,gemini-timer", fttmr010_timer_init);
TIMER_OF_DECLARE(moxart, "moxa,moxart-timer", fttmr010_timer_init);
TIMER_OF_DECLARE(ast2400, "aspeed,ast2400-timer", aspeed_timer_init);
TIMER_OF_DECLARE(ast2500, "aspeed,ast2500-timer", aspeed_timer_init);
TIMER_OF_DECLARE(ast2600, "aspeed,ast2600-timer", ast2600_timer_init);

View File

@ -67,7 +67,6 @@ struct imx_timer {
struct clk *clk_ipg;
const struct imx_gpt_data *gpt;
struct clock_event_device ced;
struct irqaction act;
};
struct imx_gpt_data {
@ -273,7 +272,6 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
static int __init mxc_clockevent_init(struct imx_timer *imxtm)
{
struct clock_event_device *ced = &imxtm->ced;
struct irqaction *act = &imxtm->act;
ced->name = "mxc_timer1";
ced->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ;
@ -287,12 +285,8 @@ static int __init mxc_clockevent_init(struct imx_timer *imxtm)
clockevents_config_and_register(ced, clk_get_rate(imxtm->clk_per),
0xff, 0xfffffffe);
act->name = "i.MX Timer Tick";
act->flags = IRQF_TIMER | IRQF_IRQPOLL;
act->handler = mxc_timer_interrupt;
act->dev_id = ced;
return setup_irq(imxtm->irq, act);
return request_irq(imxtm->irq, mxc_timer_interrupt,
IRQF_TIMER | IRQF_IRQPOLL, "i.MX Timer Tick", ced);
}
static void imx1_gpt_setup_tctl(struct imx_timer *imxtm)

View File

@ -4,8 +4,6 @@
#include <linux/interrupt.h>
#include <linux/clockchips.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include "timer-of.h"

View File

@ -8,8 +8,6 @@
#include <linux/clocksource.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/sched_clock.h>
#include "timer-of.h"

View File

@ -123,13 +123,6 @@ static struct clock_event_device integrator_clockevent = {
.rating = 300,
};
static struct irqaction integrator_timer_irq = {
.name = "timer",
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = integrator_timer_interrupt,
.dev_id = &integrator_clockevent,
};
static int integrator_clockevent_init(unsigned long inrate,
void __iomem *base, int irq)
{
@ -149,7 +142,9 @@ static int integrator_clockevent_init(unsigned long inrate,
timer_reload = rate / HZ;
writel(ctrl, clkevt_base + TIMER_CTRL);
ret = setup_irq(irq, &integrator_timer_irq);
ret = request_irq(irq, integrator_timer_interrupt,
IRQF_TIMER | IRQF_IRQPOLL, "timer",
&integrator_clockevent);
if (ret)
return ret;

View File

@ -150,13 +150,6 @@ static irqreturn_t meson6_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
static struct irqaction meson6_timer_irq = {
.name = "meson6_timer",
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = meson6_timer_interrupt,
.dev_id = &meson6_clockevent,
};
static int __init meson6_timer_init(struct device_node *node)
{
u32 val;
@ -194,7 +187,9 @@ static int __init meson6_timer_init(struct device_node *node)
/* Stop the timer A */
meson6_clkevt_time_stop();
ret = setup_irq(irq, &meson6_timer_irq);
ret = request_irq(irq, meson6_timer_interrupt,
IRQF_TIMER | IRQF_IRQPOLL, "meson6_timer",
&meson6_clockevent);
if (ret) {
pr_warn("failed to setup irq %d\n", irq);
return ret;

View File

@ -264,6 +264,7 @@ static int __init mchp_pit64b_init_mode(struct mchp_pit64b_timer *timer,
if (!best_diff) {
timer->mode |= MCHP_PIT64B_MR_SGCLK;
clk_set_rate(timer->gclk, gclk_round);
goto done;
}

View File

@ -114,12 +114,6 @@ static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
static struct irqaction orion_clkevt_irq = {
.name = "orion_event",
.flags = IRQF_TIMER,
.handler = orion_clkevt_irq_handler,
};
static int __init orion_timer_init(struct device_node *np)
{
unsigned long rate;
@ -172,7 +166,8 @@ static int __init orion_timer_init(struct device_node *np)
sched_clock_register(orion_read_sched_clock, 32, rate);
/* setup timer1 as clockevent timer */
ret = setup_irq(irq, &orion_clkevt_irq);
ret = request_irq(irq, orion_clkevt_irq_handler, IRQF_TIMER,
"orion_event", NULL);
if (ret) {
pr_err("%pOFn: unable to setup irq\n", np);
return ret;

View File

@ -135,8 +135,11 @@ static int __init owl_timer_init(struct device_node *node)
}
clk = of_clk_get(node, 0);
if (IS_ERR(clk))
return PTR_ERR(clk);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
pr_err("Failed to get clock for clocksource (%d)\n", ret);
return ret;
}
rate = clk_get_rate(clk);
@ -144,8 +147,12 @@ static int __init owl_timer_init(struct device_node *node)
owl_timer_set_enabled(owl_clksrc_base, true);
sched_clock_register(owl_timer_sched_read, 32, rate);
clocksource_mmio_init(owl_clksrc_base + OWL_Tx_VAL, node->name,
rate, 200, 32, clocksource_mmio_readl_up);
ret = clocksource_mmio_init(owl_clksrc_base + OWL_Tx_VAL, node->name,
rate, 200, 32, clocksource_mmio_readl_up);
if (ret) {
pr_err("Failed to register clocksource (%d)\n", ret);
return ret;
}
owl_timer_reset(owl_clkevt_base);

View File

@ -165,14 +165,6 @@ static struct clocksource sirfsoc_clocksource = {
.resume = sirfsoc_clocksource_resume,
};
static struct irqaction sirfsoc_timer_irq = {
.name = "sirfsoc_timer0",
.flags = IRQF_TIMER,
.irq = 0,
.handler = sirfsoc_timer_interrupt,
.dev_id = &sirfsoc_clockevent,
};
/* Overwrite weak default sched_clock with more precise one */
static u64 notrace sirfsoc_read_sched_clock(void)
{
@ -190,6 +182,7 @@ static void __init sirfsoc_clockevent_init(void)
static int __init sirfsoc_prima2_timer_init(struct device_node *np)
{
unsigned long rate;
unsigned int irq;
struct clk *clk;
int ret;
@ -218,7 +211,7 @@ static int __init sirfsoc_prima2_timer_init(struct device_node *np)
return -ENXIO;
}
sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
irq = irq_of_parse_and_map(np, 0);
writel_relaxed(rate / PRIMA2_CLOCK_FREQ / 2 - 1,
sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
@ -234,7 +227,8 @@ static int __init sirfsoc_prima2_timer_init(struct device_node *np)
sched_clock_register(sirfsoc_read_sched_clock, 64, PRIMA2_CLOCK_FREQ);
ret = setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq);
ret = request_irq(irq, sirfsoc_timer_interrupt, IRQF_TIMER,
"sirfsoc_timer0", &sirfsoc_clockevent);
if (ret) {
pr_err("Failed to setup irq\n");
return ret;

View File

@ -27,8 +27,10 @@ void __init timer_probe(void)
init_func_ret = match->data;
of_node_set_flag(np, OF_POPULATED);
ret = init_func_ret(np);
if (ret) {
of_node_clear_flag(np, OF_POPULATED);
if (ret != -EPROBE_DEFER)
pr_err("Failed to initialize '%pOF': %d\n", np,
ret);

View File

@ -143,13 +143,6 @@ static struct clock_event_device ckevt_pxa_osmr0 = {
.resume = pxa_timer_resume,
};
static struct irqaction pxa_ost0_irq = {
.name = "ost0",
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = pxa_ost0_interrupt,
.dev_id = &ckevt_pxa_osmr0,
};
static int __init pxa_timer_common_init(int irq, unsigned long clock_tick_rate)
{
int ret;
@ -161,7 +154,8 @@ static int __init pxa_timer_common_init(int irq, unsigned long clock_tick_rate)
ckevt_pxa_osmr0.cpumask = cpumask_of(0);
ret = setup_irq(irq, &pxa_ost0_irq);
ret = request_irq(irq, pxa_ost0_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
"ost0", &ckevt_pxa_osmr0);
if (ret) {
pr_err("Failed to setup irq\n");
return ret;

View File

@ -168,13 +168,6 @@ static struct clock_event_device sp804_clockevent = {
.rating = 300,
};
static struct irqaction sp804_timer_irq = {
.name = "timer",
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = sp804_timer_interrupt,
.dev_id = &sp804_clockevent,
};
int __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name)
{
struct clock_event_device *evt = &sp804_clockevent;
@ -200,7 +193,9 @@ int __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct
writel(0, base + TIMER_CTRL);
setup_irq(irq, &sp804_timer_irq);
if (request_irq(irq, sp804_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
"timer", &sp804_clockevent))
pr_err("%s: request_irq() failed\n", "timer");
clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
return 0;

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* linux/arch/arm/plat-omap/dmtimer.c
*
@ -15,28 +16,11 @@
*
* Copyright (C) 2009 Texas Instruments
* Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/cpu_pm.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/device.h>
@ -109,6 +93,47 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
timer->context.tclr);
}
static void omap_timer_save_context(struct omap_dm_timer *timer)
{
timer->context.tclr =
omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
timer->context.twer =
omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG);
timer->context.tldr =
omap_dm_timer_read_reg(timer, OMAP_TIMER_LOAD_REG);
timer->context.tmar =
omap_dm_timer_read_reg(timer, OMAP_TIMER_MATCH_REG);
timer->context.tier = readl_relaxed(timer->irq_ena);
timer->context.tsicr =
omap_dm_timer_read_reg(timer, OMAP_TIMER_IF_CTRL_REG);
}
static int omap_timer_context_notifier(struct notifier_block *nb,
unsigned long cmd, void *v)
{
struct omap_dm_timer *timer;
timer = container_of(nb, struct omap_dm_timer, nb);
switch (cmd) {
case CPU_CLUSTER_PM_ENTER:
if ((timer->capability & OMAP_TIMER_ALWON) ||
!atomic_read(&timer->enabled))
break;
omap_timer_save_context(timer);
break;
case CPU_CLUSTER_PM_ENTER_FAILED:
case CPU_CLUSTER_PM_EXIT:
if ((timer->capability & OMAP_TIMER_ALWON) ||
!atomic_read(&timer->enabled))
break;
omap_timer_restore_context(timer);
break;
}
return NOTIFY_OK;
}
static int omap_dm_timer_reset(struct omap_dm_timer *timer)
{
u32 l, timeout = 100000;
@ -138,35 +163,6 @@ static int omap_dm_timer_reset(struct omap_dm_timer *timer)
return 0;
}
static int omap_dm_timer_of_set_source(struct omap_dm_timer *timer)
{
int ret;
struct clk *parent;
/*
* FIXME: OMAP1 devices do not use the clock framework for dmtimers so
* do not call clk_get() for these devices.
*/
if (!timer->fclk)
return -ENODEV;
parent = clk_get(&timer->pdev->dev, NULL);
if (IS_ERR(parent))
return -ENODEV;
/* Bail out if both clocks point to fck */
if (clk_is_match(parent, timer->fclk))
return 0;
ret = clk_set_parent(timer->fclk, parent);
if (ret < 0)
pr_err("%s: failed to set parent\n", __func__);
clk_put(parent);
return ret;
}
static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
int ret;
@ -225,21 +221,7 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
static void omap_dm_timer_enable(struct omap_dm_timer *timer)
{
int c;
pm_runtime_get_sync(&timer->pdev->dev);
if (!(timer->capability & OMAP_TIMER_ALWON)) {
if (timer->get_context_loss_count) {
c = timer->get_context_loss_count(&timer->pdev->dev);
if (c != timer->ctx_loss_count) {
omap_timer_restore_context(timer);
timer->ctx_loss_count = c;
}
} else {
omap_timer_restore_context(timer);
}
}
}
static void omap_dm_timer_disable(struct omap_dm_timer *timer)
@ -276,9 +258,7 @@ static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
__omap_dm_timer_enable_posted(timer);
omap_dm_timer_disable(timer);
rc = omap_dm_timer_of_set_source(timer);
if (rc == -ENODEV)
return omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
rc = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
return rc;
}
@ -508,7 +488,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
int omap_dm_timer_trigger(struct omap_dm_timer *timer)
{
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
pr_err("%s: timer not available or enabled.\n", __func__);
return -EINVAL;
}
@ -532,8 +512,6 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer)
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
/* Save the context */
timer->context.tclr = l;
return 0;
}
@ -549,38 +527,19 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer)
__omap_dm_timer_stop(timer, timer->posted, rate);
/*
* Since the register values are computed and written within
* __omap_dm_timer_stop, we need to use read to retrieve the
* context.
*/
timer->context.tclr =
omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
omap_dm_timer_disable(timer);
return 0;
}
static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
static int omap_dm_timer_set_load(struct omap_dm_timer *timer,
unsigned int load)
{
u32 l;
if (unlikely(!timer))
return -EINVAL;
omap_dm_timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
if (autoreload)
l |= OMAP_TIMER_CTRL_AR;
else
l &= ~OMAP_TIMER_CTRL_AR;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
/* Save the context */
timer->context.tclr = l;
timer->context.tldr = load;
omap_dm_timer_disable(timer);
return 0;
}
@ -602,15 +561,12 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
/* Save the context */
timer->context.tclr = l;
timer->context.tmar = match;
omap_dm_timer_disable(timer);
return 0;
}
static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
int toggle, int trigger)
int toggle, int trigger, int autoreload)
{
u32 l;
@ -620,20 +576,34 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
omap_dm_timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
OMAP_TIMER_CTRL_PT | (0x03 << 10));
OMAP_TIMER_CTRL_PT | (0x03 << 10) | OMAP_TIMER_CTRL_AR);
if (def_on)
l |= OMAP_TIMER_CTRL_SCPWM;
if (toggle)
l |= OMAP_TIMER_CTRL_PT;
l |= trigger << 10;
if (autoreload)
l |= OMAP_TIMER_CTRL_AR;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
/* Save the context */
timer->context.tclr = l;
omap_dm_timer_disable(timer);
return 0;
}
static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *timer)
{
u32 l;
if (unlikely(!timer))
return -EINVAL;
omap_dm_timer_enable(timer);
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
omap_dm_timer_disable(timer);
return l;
}
static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
int prescaler)
{
@ -651,8 +621,6 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
}
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
/* Save the context */
timer->context.tclr = l;
omap_dm_timer_disable(timer);
return 0;
}
@ -666,9 +634,6 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
omap_dm_timer_enable(timer);
__omap_dm_timer_int_enable(timer, value);
/* Save the context */
timer->context.tier = value;
timer->context.twer = value;
omap_dm_timer_disable(timer);
return 0;
}
@ -696,9 +661,6 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
/* Save the context */
timer->context.tier &= ~mask;
timer->context.twer &= ~mask;
omap_dm_timer_disable(timer);
return 0;
}
@ -707,7 +669,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
{
unsigned int l;
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
pr_err("%s: timer not available or enabled.\n", __func__);
return 0;
}
@ -719,7 +681,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
{
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
if (unlikely(!timer || !atomic_read(&timer->enabled)))
return -EINVAL;
__omap_dm_timer_write_status(timer, value);
@ -729,7 +691,7 @@ static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int
static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
{
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
pr_err("%s: timer not iavailable or enabled.\n", __func__);
return 0;
}
@ -739,7 +701,7 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
{
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
pr_err("%s: timer not available or enabled.\n", __func__);
return -EINVAL;
}
@ -767,6 +729,37 @@ int omap_dm_timers_active(void)
return 0;
}
static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev)
{
struct omap_dm_timer *timer = dev_get_drvdata(dev);
atomic_set(&timer->enabled, 0);
if (timer->capability & OMAP_TIMER_ALWON || !timer->func_base)
return 0;
omap_timer_save_context(timer);
return 0;
}
static int __maybe_unused omap_dm_timer_runtime_resume(struct device *dev)
{
struct omap_dm_timer *timer = dev_get_drvdata(dev);
if (!(timer->capability & OMAP_TIMER_ALWON) && timer->func_base)
omap_timer_restore_context(timer);
atomic_set(&timer->enabled, 1);
return 0;
}
static const struct dev_pm_ops omap_dm_timer_pm_ops = {
SET_RUNTIME_PM_OPS(omap_dm_timer_runtime_suspend,
omap_dm_timer_runtime_resume, NULL)
};
static const struct of_device_id omap_timer_match[];
/**
@ -808,6 +801,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
if (IS_ERR(timer->io_base))
return PTR_ERR(timer->io_base);
platform_set_drvdata(pdev, timer);
if (dev->of_node) {
if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
timer->capability |= OMAP_TIMER_ALWON;
@ -821,7 +816,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
timer->id = pdev->id;
timer->capability = pdata->timer_capability;
timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
timer->get_context_loss_count = pdata->get_context_loss_count;
}
if (!(timer->capability & OMAP_TIMER_ALWON)) {
timer->nb.notifier_call = omap_timer_context_notifier;
cpu_pm_register_notifier(&timer->nb);
}
if (pdata)
@ -875,6 +874,8 @@ static int omap_dm_timer_remove(struct platform_device *pdev)
list_for_each_entry(timer, &omap_timer_list, node)
if (!strcmp(dev_name(&timer->pdev->dev),
dev_name(&pdev->dev))) {
if (!(timer->capability & OMAP_TIMER_ALWON))
cpu_pm_unregister_notifier(&timer->nb);
list_del(&timer->node);
ret = 0;
break;
@ -903,6 +904,7 @@ static const struct omap_dm_timer_ops dmtimer_ops = {
.set_load = omap_dm_timer_set_load,
.set_match = omap_dm_timer_set_match,
.set_pwm = omap_dm_timer_set_pwm,
.get_pwm_status = omap_dm_timer_get_pwm_status,
.set_prescaler = omap_dm_timer_set_prescaler,
.read_counter = omap_dm_timer_read_counter,
.write_counter = omap_dm_timer_write_counter,
@ -953,6 +955,7 @@ static struct platform_driver omap_dm_timer_driver = {
.driver = {
.name = "omap_timer",
.of_match_table = of_match_ptr(omap_timer_match),
.pm = &omap_dm_timer_pm_ops,
},
};

View File

@ -330,12 +330,6 @@ static irqreturn_t u300_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
static struct irqaction u300_timer_irq = {
.name = "U300 Timer Tick",
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = u300_timer_interrupt,
};
/*
* Override the global weak sched_clock symbol with this
* local implementation which uses the clocksource to get some
@ -420,7 +414,8 @@ static int __init u300_timer_init_of(struct device_node *np)
u300_timer_base + U300_TIMER_APP_RGPT1);
/* Set up the IRQ handler */
ret = setup_irq(irq, &u300_timer_irq);
ret = request_irq(irq, u300_timer_interrupt,
IRQF_TIMER | IRQF_IRQPOLL, "U300 Timer Tick", NULL);
if (ret)
return ret;

View File

@ -123,19 +123,13 @@ static struct clock_event_device clockevent_pit = {
.rating = 300,
};
static struct irqaction pit_timer_irq = {
.name = "VF pit timer",
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = pit_timer_interrupt,
.dev_id = &clockevent_pit,
};
static int __init pit_clockevent_init(unsigned long rate, int irq)
{
__raw_writel(0, clkevt_base + PITTCTRL);
__raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);
BUG_ON(setup_irq(irq, &pit_timer_irq));
BUG_ON(request_irq(irq, pit_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
"VF pit timer", &clockevent_pit);
clockevent_pit.cpumask = cpumask_of(0);
clockevent_pit.irq = irq;

View File

@ -101,13 +101,6 @@ static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
static struct irqaction irq = {
.name = "vt8500_timer",
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = vt8500_timer_interrupt,
.dev_id = &clockevent,
};
static int __init vt8500_timer_init(struct device_node *np)
{
int timer_irq, ret;
@ -139,7 +132,9 @@ static int __init vt8500_timer_init(struct device_node *np)
clockevent.cpumask = cpumask_of(0);
ret = setup_irq(timer_irq, &irq);
ret = request_irq(timer_irq, vt8500_timer_interrupt,
IRQF_TIMER | IRQF_IRQPOLL, "vt8500_timer",
&clockevent);
if (ret) {
pr_err("%s: setup_irq failed for %s\n", __func__,
clockevent.name);

View File

@ -53,7 +53,6 @@ struct zevio_timer {
struct clk *clk;
struct clock_event_device clkevt;
struct irqaction clkevt_irq;
char clocksource_name[64];
char clockevent_name[64];
@ -172,12 +171,12 @@ static int __init zevio_timer_add(struct device_node *node)
/* Interrupt to occur when timer value matches 0 */
writel(0, timer->base + IO_MATCH(TIMER_MATCH));
timer->clkevt_irq.name = timer->clockevent_name;
timer->clkevt_irq.handler = zevio_timer_interrupt;
timer->clkevt_irq.dev_id = timer;
timer->clkevt_irq.flags = IRQF_TIMER | IRQF_IRQPOLL;
setup_irq(irqnr, &timer->clkevt_irq);
if (request_irq(irqnr, zevio_timer_interrupt,
IRQF_TIMER | IRQF_IRQPOLL,
timer->clockevent_name, timer)) {
pr_err("%s: request_irq() failed\n",
timer->clockevent_name);
}
clockevents_config_and_register(&timer->clkevt,
clk_get_rate(timer->clk), 0x0001, 0xffff);

View File

@ -183,7 +183,7 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
if (timer_active)
omap->pdata->stop(omap->dm_timer);
omap->pdata->set_load(omap->dm_timer, true, load_value);
omap->pdata->set_load(omap->dm_timer, load_value);
omap->pdata->set_match(omap->dm_timer, true, match_value);
dev_dbg(chip->dev, "load value: %#08x (%d), match value: %#08x (%d)\n",
@ -192,7 +192,8 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
omap->pdata->set_pwm(omap->dm_timer,
pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED,
true,
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE,
true);
/* If config was called while timer was running it must be reenabled. */
if (timer_active)
@ -222,7 +223,8 @@ static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip,
omap->pdata->set_pwm(omap->dm_timer,
polarity == PWM_POLARITY_INVERSED,
true,
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE,
true);
mutex_unlock(&omap->mutex);
return 0;

View File

@ -105,17 +105,17 @@ struct omap_dm_timer {
void __iomem *pend; /* write pending */
void __iomem *func_base; /* function register base */
atomic_t enabled;
unsigned long rate;
unsigned reserved:1;
unsigned posted:1;
struct timer_regs context;
int (*get_context_loss_count)(struct device *);
int ctx_loss_count;
int revision;
u32 capability;
u32 errata;
struct platform_device *pdev;
struct list_head node;
struct notifier_block nb;
};
int omap_dm_timer_reserve_systimer(int id);

View File

@ -25,7 +25,6 @@ struct dw_apb_timer {
struct dw_apb_clock_event_device {
struct clock_event_device ced;
struct dw_apb_timer timer;
struct irqaction irqaction;
void (*eoi)(struct dw_apb_timer *);
};

View File

@ -30,12 +30,12 @@ struct omap_dm_timer_ops {
int (*stop)(struct omap_dm_timer *timer);
int (*set_source)(struct omap_dm_timer *timer, int source);
int (*set_load)(struct omap_dm_timer *timer, int autoreload,
unsigned int value);
int (*set_load)(struct omap_dm_timer *timer, unsigned int value);
int (*set_match)(struct omap_dm_timer *timer, int enable,
unsigned int match);
int (*set_pwm)(struct omap_dm_timer *timer, int def_on,
int toggle, int trigger);
int toggle, int trigger, int autoreload);
int (*get_pwm_status)(struct omap_dm_timer *timer);
int (*set_prescaler)(struct omap_dm_timer *timer, int prescaler);
unsigned int (*read_counter)(struct omap_dm_timer *timer);