Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…no/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)
  • Loading branch information
Thomas Gleixner committed Mar 19, 2020
2 parents d441dce + 4f41fe3 commit 048495e
Show file tree
Hide file tree
Showing 39 changed files with 471 additions and 330 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/timer/ingenic,tcu.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 8 additions & 0 deletions drivers/clocksource/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/clocksource/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 2 additions & 6 deletions drivers/clocksource/bcm2835_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
10 changes: 3 additions & 7 deletions drivers/clocksource/bcm_kona_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
11 changes: 3 additions & 8 deletions drivers/clocksource/dw_apb_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
12 changes: 4 additions & 8 deletions drivers/clocksource/exynos_mct.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
189 changes: 189 additions & 0 deletions drivers/clocksource/ingenic-ost.c
Original file line number Diff line number Diff line change
@@ -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);
3 changes: 2 additions & 1 deletion drivers/clocksource/ingenic-timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */ }
};

Expand Down Expand Up @@ -302,7 +303,7 @@ static int __init ingenic_tcu_init(struct device_node *np)
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)
{
Expand Down
10 changes: 2 additions & 8 deletions drivers/clocksource/mxs_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
11 changes: 3 additions & 8 deletions drivers/clocksource/nomadik-mtu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 048495e

Please sign in to comment.