From ccb80012481fd8d16c7557c00bb54c42103eef9d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 16 Oct 2019 16:47:44 +0200 Subject: [PATCH 1/5] clocksource/drivers/timer-of: Convert last full_name to %pOF Commit 469869d18a886e04 ("clocksource: Convert to using %pOF instead of full_name") converted all but the one just added before by commit 32f2fea6e77e64cd ("clocksource/drivers/timer-of: Handle of_irq_get_byname() result correctly"). Signed-off-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20191016144747.29538-2-geert+renesas@glider.be --- drivers/clocksource/timer-of.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/timer-of.c b/drivers/clocksource/timer-of.c index d8c2bd4391d0..384394205a12 100644 --- a/drivers/clocksource/timer-of.c +++ b/drivers/clocksource/timer-of.c @@ -55,8 +55,8 @@ static __init int timer_of_irq_init(struct device_node *np, if (of_irq->name) { of_irq->irq = ret = of_irq_get_byname(np, of_irq->name); if (ret < 0) { - pr_err("Failed to get interrupt %s for %s\n", - of_irq->name, np->full_name); + pr_err("Failed to get interrupt %s for %pOF\n", + of_irq->name, np); return ret; } } else { From 4411464d6f8b5e5759637235a6f2b2a85c2be0f1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 16 Oct 2019 16:47:45 +0200 Subject: [PATCH 2/5] clocksource/drivers/timer-of: Use unique device name instead of timer If a hardware-specific driver does not provide a name, the timer-of core falls back to device_node.name. Due to generic DT node naming policies, that name is almost always "timer", and thus doesn't identify the actual timer used. Fix this by using device_node.full_name instead, which includes the unit addrees. Example impact on /proc/timer_list: -Clock Event Device: timer +Clock Event Device: timer@fcfec400 Signed-off-by: Geert Uytterhoeven Reviewed-by: Rob Herring Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20191016144747.29538-3-geert+renesas@glider.be --- drivers/clocksource/timer-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/timer-of.c b/drivers/clocksource/timer-of.c index 384394205a12..8c11bd743dd0 100644 --- a/drivers/clocksource/timer-of.c +++ b/drivers/clocksource/timer-of.c @@ -190,7 +190,7 @@ int __init timer_of_init(struct device_node *np, struct timer_of *to) } if (!to->clkevt.name) - to->clkevt.name = np->name; + to->clkevt.name = np->full_name; to->np = np; From 227314239a5e87fb531cbf3bd8953b2d1d2694bd Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 16 Oct 2019 16:47:46 +0200 Subject: [PATCH 3/5] clocksource/drivers/renesas-ostm: Convert to timer_of Convert the Renesas OSTM driver to use the timer_of framework. This reduces the driver object size by 367 bytes (with gcc 7.4.0). Signed-off-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20191016144747.29538-4-geert+renesas@glider.be --- drivers/clocksource/Kconfig | 1 + drivers/clocksource/renesas-ostm.c | 187 +++++++++++------------------ 2 files changed, 72 insertions(+), 116 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index f35a53ce8988..5fdd76cb1768 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -528,6 +528,7 @@ config SH_TIMER_MTU2 config RENESAS_OSTM bool "Renesas OSTM timer driver" if COMPILE_TEST select CLKSRC_MMIO + select TIMER_OF help Enables the support for the Renesas OSTM. diff --git a/drivers/clocksource/renesas-ostm.c b/drivers/clocksource/renesas-ostm.c index 37c39b901bb1..46012d905604 100644 --- a/drivers/clocksource/renesas-ostm.c +++ b/drivers/clocksource/renesas-ostm.c @@ -6,14 +6,14 @@ * Copyright (C) 2017 Chris Brandt */ -#include -#include #include #include #include #include #include +#include "timer-of.h" + /* * The OSTM contains independent channels. * The first OSTM channel probed will be set up as a free running @@ -24,12 +24,6 @@ * driven clock event. */ -struct ostm_device { - void __iomem *base; - unsigned long ticks_per_jiffy; - struct clock_event_device ced; -}; - static void __iomem *system_clock; /* For sched_clock() */ /* OSTM REGISTERS */ @@ -47,41 +41,32 @@ static void __iomem *system_clock; /* For sched_clock() */ #define CTL_ONESHOT 0x02 #define CTL_FREERUN 0x02 -static struct ostm_device *ced_to_ostm(struct clock_event_device *ced) +static void ostm_timer_stop(struct timer_of *to) { - return container_of(ced, struct ostm_device, ced); -} - -static void ostm_timer_stop(struct ostm_device *ostm) -{ - if (readb(ostm->base + OSTM_TE) & TE) { - writeb(TT, ostm->base + OSTM_TT); + if (readb(timer_of_base(to) + OSTM_TE) & TE) { + writeb(TT, timer_of_base(to) + OSTM_TT); /* * Read back the register simply to confirm the write operation * has completed since I/O writes can sometimes get queued by * the bus architecture. */ - while (readb(ostm->base + OSTM_TE) & TE) + while (readb(timer_of_base(to) + OSTM_TE) & TE) ; } } -static int __init ostm_init_clksrc(struct ostm_device *ostm, unsigned long rate) +static int __init ostm_init_clksrc(struct timer_of *to) { - /* - * irq not used (clock sources don't use interrupts) - */ + ostm_timer_stop(to); - ostm_timer_stop(ostm); + writel(0, timer_of_base(to) + OSTM_CMP); + writeb(CTL_FREERUN, timer_of_base(to) + OSTM_CTL); + writeb(TS, timer_of_base(to) + OSTM_TS); - writel(0, ostm->base + OSTM_CMP); - writeb(CTL_FREERUN, ostm->base + OSTM_CTL); - writeb(TS, ostm->base + OSTM_TS); - - return clocksource_mmio_init(ostm->base + OSTM_CNT, - "ostm", rate, - 300, 32, clocksource_mmio_readl_up); + return clocksource_mmio_init(timer_of_base(to) + OSTM_CNT, "ostm", + timer_of_rate(to), 300, 32, + clocksource_mmio_readl_up); } static u64 notrace ostm_read_sched_clock(void) @@ -89,87 +74,75 @@ static u64 notrace ostm_read_sched_clock(void) return readl(system_clock); } -static void __init ostm_init_sched_clock(struct ostm_device *ostm, - unsigned long rate) +static void __init ostm_init_sched_clock(struct timer_of *to) { - system_clock = ostm->base + OSTM_CNT; - sched_clock_register(ostm_read_sched_clock, 32, rate); + system_clock = timer_of_base(to) + OSTM_CNT; + sched_clock_register(ostm_read_sched_clock, 32, timer_of_rate(to)); } static int ostm_clock_event_next(unsigned long delta, - struct clock_event_device *ced) + struct clock_event_device *ced) { - struct ostm_device *ostm = ced_to_ostm(ced); + struct timer_of *to = to_timer_of(ced); - ostm_timer_stop(ostm); + ostm_timer_stop(to); - writel(delta, ostm->base + OSTM_CMP); - writeb(CTL_ONESHOT, ostm->base + OSTM_CTL); - writeb(TS, ostm->base + OSTM_TS); + writel(delta, timer_of_base(to) + OSTM_CMP); + writeb(CTL_ONESHOT, timer_of_base(to) + OSTM_CTL); + writeb(TS, timer_of_base(to) + OSTM_TS); return 0; } static int ostm_shutdown(struct clock_event_device *ced) { - struct ostm_device *ostm = ced_to_ostm(ced); + struct timer_of *to = to_timer_of(ced); - ostm_timer_stop(ostm); + ostm_timer_stop(to); return 0; } static int ostm_set_periodic(struct clock_event_device *ced) { - struct ostm_device *ostm = ced_to_ostm(ced); + struct timer_of *to = to_timer_of(ced); if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced)) - ostm_timer_stop(ostm); + ostm_timer_stop(to); - writel(ostm->ticks_per_jiffy - 1, ostm->base + OSTM_CMP); - writeb(CTL_PERIODIC, ostm->base + OSTM_CTL); - writeb(TS, ostm->base + OSTM_TS); + writel(timer_of_period(to) - 1, timer_of_base(to) + OSTM_CMP); + writeb(CTL_PERIODIC, timer_of_base(to) + OSTM_CTL); + writeb(TS, timer_of_base(to) + OSTM_TS); return 0; } static int ostm_set_oneshot(struct clock_event_device *ced) { - struct ostm_device *ostm = ced_to_ostm(ced); + struct timer_of *to = to_timer_of(ced); - ostm_timer_stop(ostm); + ostm_timer_stop(to); return 0; } static irqreturn_t ostm_timer_interrupt(int irq, void *dev_id) { - struct ostm_device *ostm = dev_id; + struct clock_event_device *ced = dev_id; - if (clockevent_state_oneshot(&ostm->ced)) - ostm_timer_stop(ostm); + if (clockevent_state_oneshot(ced)) + ostm_timer_stop(to_timer_of(ced)); /* notify clockevent layer */ - if (ostm->ced.event_handler) - ostm->ced.event_handler(&ostm->ced); + if (ced->event_handler) + ced->event_handler(ced); return IRQ_HANDLED; } -static int __init ostm_init_clkevt(struct ostm_device *ostm, int irq, - unsigned long rate) +static int __init ostm_init_clkevt(struct timer_of *to) { - struct clock_event_device *ced = &ostm->ced; - int ret = -ENXIO; + struct clock_event_device *ced = &to->clkevt; - ret = request_irq(irq, ostm_timer_interrupt, - IRQF_TIMER | IRQF_IRQPOLL, - "ostm", ostm); - if (ret) { - pr_err("ostm: failed to request irq\n"); - return ret; - } - - ced->name = "ostm"; ced->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC; ced->set_state_shutdown = ostm_shutdown; ced->set_state_periodic = ostm_set_periodic; @@ -178,79 +151,61 @@ static int __init ostm_init_clkevt(struct ostm_device *ostm, int irq, ced->shift = 32; ced->rating = 300; ced->cpumask = cpumask_of(0); - clockevents_config_and_register(ced, rate, 0xf, 0xffffffff); + clockevents_config_and_register(ced, timer_of_rate(to), 0xf, + 0xffffffff); return 0; } static int __init ostm_init(struct device_node *np) { - struct ostm_device *ostm; - int ret = -EFAULT; - struct clk *ostm_clk = NULL; - int irq; - unsigned long rate; + struct timer_of *to; + int ret; - ostm = kzalloc(sizeof(*ostm), GFP_KERNEL); - if (!ostm) + to = kzalloc(sizeof(*to), GFP_KERNEL); + if (!to) return -ENOMEM; - ostm->base = of_iomap(np, 0); - if (!ostm->base) { - pr_err("ostm: failed to remap I/O memory\n"); - goto err; + to->flags = TIMER_OF_BASE | TIMER_OF_CLOCK; + if (system_clock) { + /* + * clock sources don't use interrupts, clock events do + */ + to->flags |= TIMER_OF_IRQ; + to->of_irq.flags = IRQF_TIMER | IRQF_IRQPOLL; + to->of_irq.handler = ostm_timer_interrupt; } - irq = irq_of_parse_and_map(np, 0); - if (irq < 0) { - pr_err("ostm: Failed to get irq\n"); - goto err; - } - - ostm_clk = of_clk_get(np, 0); - if (IS_ERR(ostm_clk)) { - pr_err("ostm: Failed to get clock\n"); - ostm_clk = NULL; - goto err; - } - - ret = clk_prepare_enable(ostm_clk); - if (ret) { - pr_err("ostm: Failed to enable clock\n"); - goto err; - } - - rate = clk_get_rate(ostm_clk); - ostm->ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ); + ret = timer_of_init(np, to); + if (ret) + goto err_free; /* * First probed device will be used as system clocksource. Any * additional devices will be used as clock events. */ if (!system_clock) { - ret = ostm_init_clksrc(ostm, rate); - - if (!ret) { - ostm_init_sched_clock(ostm, rate); - pr_info("ostm: used for clocksource\n"); - } + ret = ostm_init_clksrc(to); + if (ret) + goto err_cleanup; + ostm_init_sched_clock(to); + pr_info("ostm: used for clocksource\n"); } else { - ret = ostm_init_clkevt(ostm, irq, rate); + ret = ostm_init_clkevt(to); + if (ret) + goto err_cleanup; - if (!ret) - pr_info("ostm: used for clock events\n"); - } - -err: - if (ret) { - clk_disable_unprepare(ostm_clk); - iounmap(ostm->base); - kfree(ostm); - return ret; + pr_info("ostm: used for clock events\n"); } return 0; + +err_cleanup: + timer_of_cleanup(to); +err_free: + kfree(to); + return ret; } TIMER_OF_DECLARE(ostm, "renesas,ostm", ostm_init); From b35a5e5961f814799b75a97a16c9b51e0d477c06 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 16 Oct 2019 16:47:47 +0200 Subject: [PATCH 4/5] clocksource/drivers/renesas-ostm: Use unique device name instead of ostm Currently all OSTM devices are called "ostm", also in kernel messages. As there can be multiple instances in an SoC, this can confuse the user. Hence construct a unique name from the DT node name, like is done for platform devices. On RSK+RZA1, the boot log changes like: -clocksource: ostm: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 57352151442 ns +clocksource: timer@fcfec000: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 57352151442 ns sched_clock: 32 bits at 33MHz, resolution 30ns, wraps every 64440619504ns -ostm: used for clocksource -ostm: used for clock events +/soc/timer@fcfec000: used for clocksource +/soc/timer@fcfec400: used for clock events ... -clocksource: Switched to clocksource ostm +clocksource: Switched to clocksource timer@fcfec000 Signed-off-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20191016144747.29538-5-geert+renesas@glider.be --- drivers/clocksource/renesas-ostm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clocksource/renesas-ostm.c b/drivers/clocksource/renesas-ostm.c index 46012d905604..3d06ba66008c 100644 --- a/drivers/clocksource/renesas-ostm.c +++ b/drivers/clocksource/renesas-ostm.c @@ -64,9 +64,9 @@ static int __init ostm_init_clksrc(struct timer_of *to) writeb(CTL_FREERUN, timer_of_base(to) + OSTM_CTL); writeb(TS, timer_of_base(to) + OSTM_TS); - return clocksource_mmio_init(timer_of_base(to) + OSTM_CNT, "ostm", - timer_of_rate(to), 300, 32, - clocksource_mmio_readl_up); + return clocksource_mmio_init(timer_of_base(to) + OSTM_CNT, + to->np->full_name, timer_of_rate(to), 300, + 32, clocksource_mmio_readl_up); } static u64 notrace ostm_read_sched_clock(void) @@ -190,13 +190,13 @@ static int __init ostm_init(struct device_node *np) goto err_cleanup; ostm_init_sched_clock(to); - pr_info("ostm: used for clocksource\n"); + pr_info("%pOF: used for clocksource\n", np); } else { ret = ostm_init_clkevt(to); if (ret) goto err_cleanup; - pr_info("ostm: used for clock events\n"); + pr_info("%pOF: used for clock events\n", np); } return 0; From 6e001f6a4cc73cd06fc7b8c633bc4906c33dd8ad Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 16 Oct 2019 20:43:30 +0800 Subject: [PATCH 5/5] clocksource/drivers/asm9260: Add a check for of_clk_get asm9260_timer_init misses a check for of_clk_get. Add a check for it and print errors like other clocksource drivers. Signed-off-by: Chuhong Yuan Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20191016124330.22211-1-hslester96@gmail.com --- drivers/clocksource/asm9260_timer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c index 9f09a59161e7..5b39d3701fa3 100644 --- a/drivers/clocksource/asm9260_timer.c +++ b/drivers/clocksource/asm9260_timer.c @@ -194,6 +194,10 @@ static int __init asm9260_timer_init(struct device_node *np) } clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + pr_err("Failed to get clk!\n"); + return PTR_ERR(clk); + } ret = clk_prepare_enable(clk); if (ret) {