History

Merge tag 'timers-clocksource-2025-11-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull clocksource updates from Thomas Gleixner: "Updates for clocksource and clockevent drivers: - A new driver for the Realtel system timer - Prevent the unbinding of timers when the drivers do not support that - Expand the timer counter readout for the SPRD driver to 64 bit to allow IOT devices suspend times of more than 36 hours, which is the current limit of the 32-bi readout - The usual small cleanups, fixes and enhancements all over the place" * tag 'timers-clocksource-2025-11-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: clocksource/drivers: Add Realtek system timer driver dt-bindings: timer: Add Realtek SYSTIMER clocksource/drivers/stm32-lp: Drop unused module alias clocksource/drivers/rda: Add sched_clock_register for RDA8810PL SoC clocksource/drivers/nxp-stm: Prevent driver unbind clocksource/drivers/nxp-pit: Prevent driver unbind clocksource/drivers/arm_arch_timer_mmio: Prevent driver unbind clocksource/drivers/nxp-stm: Fix section mismatches clocksource/drivers/sh_cmt: Always leave device running after probe clocksource/drivers/stm: Fix double deregistration on probe failure clocksource/drivers/ralink: Fix resource leaks in init error path clocksource/drivers/timer-sp804: Fix read_current_timer() issue when clock source is not registered clocksource/drivers/sprd: Enable register for timer counter from 32 bit to 64 bit

Linus Torvalds committed 11 months ago

Commit 5028f422 parents 9ce62eb 2437f7914 files · +291 −56Browse files

Unified · Split

14 files
  1. Documentation/devicetree/bindings/timer/realtek,rtd1625-systimer.yaml +47 −0
  2. MAINTAINERS +5 −0
  3. drivers/clocksource/Kconfig +11 −0
  4. drivers/clocksource/Makefile +1 −0
  5. drivers/clocksource/arm_arch_timer_mmio.c +2 −0
  6. drivers/clocksource/sh_cmt.c +3 −33
  7. drivers/clocksource/timer-nxp-pit.c +2 −1
  8. drivers/clocksource/timer-nxp-stm.c +11 −12
  9. drivers/clocksource/timer-ralink.c +9 −2
  10. drivers/clocksource/timer-rda.c +8 −1
  11. drivers/clocksource/timer-realtek.c +150 −0
  12. drivers/clocksource/timer-sp804.c +24 −0
  13. drivers/clocksource/timer-sprd.c +18 −6
  14. drivers/clocksource/timer-stm32-lp.c +0 −1
Documentation/devicetree/bindings/timer/realtek,rtd1625-systimer.yaml+47−0
@@ -0,0 +1,47 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/timer/realtek,rtd1625-systimer.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Realtek System Timer
8
9maintainers:
10 - Hao-Wen Ting <haowen.ting@realtek.com>
11
12description:
13 The Realtek SYSTIMER (System Timer) is a 64-bit global hardware counter operating
14 at a fixed 1MHz frequency. Thanks to its compare match interrupt capability,
15 the timer natively supports oneshot mode for tick broadcast functionality.
16
17properties:
18 compatible:
19 oneOf:
20 - const: realtek,rtd1625-systimer
21 - items:
22 - const: realtek,rtd1635-systimer
23 - const: realtek,rtd1625-systimer
24
25 reg:
26 maxItems: 1
27
28 interrupts:
29 maxItems: 1
30
31required:
32 - compatible
33 - reg
34 - interrupts
35
36additionalProperties: false
37
38examples:
39 - |
40 #include <dt-bindings/interrupt-controller/arm-gic.h>
41
42 timer@89420 {
43 compatible = "realtek,rtd1635-systimer",
44 "realtek,rtd1625-systimer";
45 reg = <0x89420 0x18>;
46 interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
47 };
MAINTAINERS+5−0
@@ -21681,6 +21681,11 @@ S: Maintained · 21680 unmodified lines
21681F: Documentation/devicetree/bindings/spi/realtek,rtl9301-snand.yaml21681F: Documentation/devicetree/bindings/spi/realtek,rtl9301-snand.yaml
21682F: drivers/spi/spi-realtek-rtl-snand.c21682F: drivers/spi/spi-realtek-rtl-snand.c
21683 21683
21684REALTEK SYSTIMER DRIVER
21685M: Hao-Wen Ting <haowen.ting@realtek.com>
21686S: Maintained
21687F: drivers/clocksource/timer-realtek.c
21688
21684REALTEK WIRELESS DRIVER (rtlwifi family)21689REALTEK WIRELESS DRIVER (rtlwifi family)
21685M: Ping-Ke Shih <pkshih@realtek.com>21690M: Ping-Ke Shih <pkshih@realtek.com>
21686L: linux-wireless@vger.kernel.org21691L: linux-wireless@vger.kernel.org
drivers/clocksource/Kconfig+11−0
@@ -782,4 +782,15 @@ config NXP_STM_TIMER · 781 unmodified lines
782 Enables the support for NXP System Timer Module found in the782 Enables the support for NXP System Timer Module found in the
783 s32g NXP platform series.783 s32g NXP platform series.
784 784
785config RTK_SYSTIMER
786 bool "Realtek SYSTIMER support"
787 depends on ARM || ARM64
788 depends on ARCH_REALTEK || COMPILE_TEST
789 select TIMER_OF
790 help
791 This option enables the driver that registers the global 1 MHz hardware
792 counter as a clock event device on Realtek SoCs. Make sure to enable
793 this option only when building for a Realtek platform or for compilation
794 testing.
795
785endmenu796endmenu
drivers/clocksource/Makefile+1−0
@@ -95,3 +95,4 @@ obj-$(CONFIG_CLKSRC_LOONGSON1_PWM) += timer-loongson1-pwm.o · 94 unmodified lines
95obj-$(CONFIG_EP93XX_TIMER) += timer-ep93xx.o95obj-$(CONFIG_EP93XX_TIMER) += timer-ep93xx.o
96obj-$(CONFIG_RALINK_TIMER) += timer-ralink.o96obj-$(CONFIG_RALINK_TIMER) += timer-ralink.o
97obj-$(CONFIG_NXP_STM_TIMER) += timer-nxp-stm.o97obj-$(CONFIG_NXP_STM_TIMER) += timer-nxp-stm.o
98obj-$(CONFIG_RTK_SYSTIMER) += timer-realtek.o
drivers/clocksource/arm_arch_timer_mmio.c+2−0
@@ -426,6 +426,7 @@ static struct platform_driver arch_timer_mmio_drv = { · 425 unmodified lines
426 .driver = {426 .driver = {
427 .name = "arch-timer-mmio",427 .name = "arch-timer-mmio",
428 .of_match_table = arch_timer_mmio_of_table,428 .of_match_table = arch_timer_mmio_of_table,
429 .suppress_bind_attrs = true,
429 },430 },
430 .probe = arch_timer_mmio_probe,431 .probe = arch_timer_mmio_probe,
431};432};
@@ -434,6 +435,7 @@ builtin_platform_driver(arch_timer_mmio_drv); · 2 unmodified lines
434static struct platform_driver arch_timer_mmio_acpi_drv = {435static struct platform_driver arch_timer_mmio_acpi_drv = {
435 .driver = {436 .driver = {
436 .name = "gtdt-arm-mmio-timer",437 .name = "gtdt-arm-mmio-timer",
438 .suppress_bind_attrs = true,
437 },439 },
438 .probe = arch_timer_mmio_probe,440 .probe = arch_timer_mmio_probe,
439};441};
drivers/clocksource/sh_cmt.c+3−33
@@ -355,14 +355,6 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch) · 354 unmodified lines
355 355
356 dev_pm_syscore_device(&ch->cmt->pdev->dev, true);356 dev_pm_syscore_device(&ch->cmt->pdev->dev, true);
357 357
358 /* enable clock */
359 ret = clk_enable(ch->cmt->clk);
360 if (ret) {
361 dev_err(&ch->cmt->pdev->dev, "ch%u: cannot enable clock\n",
362 ch->index);
363 goto err0;
364 }
365
366 /* make sure channel is disabled */358 /* make sure channel is disabled */
367 sh_cmt_start_stop_ch(ch, 0);359 sh_cmt_start_stop_ch(ch, 0);
368 360
@@ -384,19 +376,12 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch) · 15 unmodified lines
384 if (ret || sh_cmt_read_cmcnt(ch)) {376 if (ret || sh_cmt_read_cmcnt(ch)) {
385 dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n",377 dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n",
386 ch->index);378 ch->index);
387 ret = -ETIMEDOUT;379 return -ETIMEDOUT;
388 goto err1;
389 }380 }
390 381
391 /* enable channel */382 /* enable channel */
392 sh_cmt_start_stop_ch(ch, 1);383 sh_cmt_start_stop_ch(ch, 1);
393 return 0;384 return 0;
394 err1:
395 /* stop clock */
396 clk_disable(ch->cmt->clk);
397
398 err0:
399 return ret;
400}385}
401 386
402static void sh_cmt_disable(struct sh_cmt_channel *ch)387static void sh_cmt_disable(struct sh_cmt_channel *ch)
@@ -407,9 +392,6 @@ static void sh_cmt_disable(struct sh_cmt_channel *ch) · 4 unmodified lines
407 /* disable interrupts in CMT block */392 /* disable interrupts in CMT block */
408 sh_cmt_write_cmcsr(ch, 0);393 sh_cmt_write_cmcsr(ch, 0);
409 394
410 /* stop clock */
411 clk_disable(ch->cmt->clk);
412
413 dev_pm_syscore_device(&ch->cmt->pdev->dev, false);395 dev_pm_syscore_device(&ch->cmt->pdev->dev, false);
414}396}
415 397
@@ -583,8 +565,6 @@ static int sh_cmt_start_clocksource(struct sh_cmt_channel *ch) · 167 unmodified lines
583 int ret = 0;565 int ret = 0;
584 unsigned long flags;566 unsigned long flags;
585 567
586 pm_runtime_get_sync(&ch->cmt->pdev->dev);
587
588 raw_spin_lock_irqsave(&ch->lock, flags);568 raw_spin_lock_irqsave(&ch->lock, flags);
589 569
590 if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))570 if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
@@ -619,8 +599,6 @@ static void sh_cmt_stop_clocksource(struct sh_cmt_channel *ch) · 28 unmodified lines
619 sh_cmt_disable(ch);599 sh_cmt_disable(ch);
620 600
621 raw_spin_unlock_irqrestore(&ch->lock, flags);601 raw_spin_unlock_irqrestore(&ch->lock, flags);
622
623 pm_runtime_put(&ch->cmt->pdev->dev);
624}602}
625 603
626static int sh_cmt_start_clockevent(struct sh_cmt_channel *ch)604static int sh_cmt_start_clockevent(struct sh_cmt_channel *ch)
@@ -630,10 +608,8 @@ static int sh_cmt_start_clockevent(struct sh_cmt_channel *ch) · 3 unmodified lines
630 608
631 raw_spin_lock_irqsave(&ch->lock, flags);609 raw_spin_lock_irqsave(&ch->lock, flags);
632 610
633 if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) {611 if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
634 pm_runtime_get_sync(&ch->cmt->pdev->dev);
635 ret = sh_cmt_enable(ch);612 ret = sh_cmt_enable(ch);
636 }
637 613
638 if (ret)614 if (ret)
639 goto out;615 goto out;
@@ -656,10 +632,8 @@ static void sh_cmt_stop_clockevent(struct sh_cmt_channel *ch) · 16 unmodified lines
656 632
657 ch->flags &= ~FLAG_CLOCKEVENT;633 ch->flags &= ~FLAG_CLOCKEVENT;
658 634
659 if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) {635 if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
660 sh_cmt_disable(ch);636 sh_cmt_disable(ch);
661 pm_runtime_put(&ch->cmt->pdev->dev);
662 }
663 637
664 /* adjust the timeout to maximum if only clocksource left */638 /* adjust the timeout to maximum if only clocksource left */
665 if (ch->flags & FLAG_CLOCKSOURCE)639 if (ch->flags & FLAG_CLOCKSOURCE)
@@ -1134,8 +1108,6 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) · 468 unmodified lines
1134 mask &= ~(1 << hwidx);1108 mask &= ~(1 << hwidx);
1135 }1109 }
1136 1110
1137 clk_disable(cmt->clk);
1138
1139 platform_set_drvdata(pdev, cmt);1111 platform_set_drvdata(pdev, cmt);
1140 1112
1141 return 0;1113 return 0;
@@ -1183,8 +1155,6 @@ static int sh_cmt_probe(struct platform_device *pdev) · 41 unmodified lines
1183 out:1155 out:
1184 if (cmt->has_clockevent || cmt->has_clocksource)1156 if (cmt->has_clockevent || cmt->has_clocksource)
1185 pm_runtime_irq_safe(&pdev->dev);1157 pm_runtime_irq_safe(&pdev->dev);
1186 else
1187 pm_runtime_idle(&pdev->dev);
1188 1158
1189 return 0;1159 return 0;
1190}1160}
drivers/clocksource/timer-nxp-pit.c+2−1
@@ -374,9 +374,10 @@ static struct platform_driver nxp_pit_driver = { · 373 unmodified lines
374 .driver = {374 .driver = {
375 .name = "nxp-pit",375 .name = "nxp-pit",
376 .of_match_table = pit_timer_of_match,376 .of_match_table = pit_timer_of_match,
377 .suppress_bind_attrs = true,
377 },378 },
378 .probe = pit_timer_probe,379 .probe = pit_timer_probe,
379};380};
380module_platform_driver(nxp_pit_driver);381builtin_platform_driver(nxp_pit_driver);
381 382
382TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init);383TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init);
drivers/clocksource/timer-nxp-stm.c+11−12
@@ -177,15 +177,15 @@ static void nxp_stm_clocksource_resume(struct clocksource *cs) · 176 unmodified lines
177 nxp_stm_clocksource_enable(cs);177 nxp_stm_clocksource_enable(cs);
178}178}
179 179
180static void __init devm_clocksource_unregister(void *data)180static void devm_clocksource_unregister(void *data)
181{181{
182 struct stm_timer *stm_timer = data;182 struct stm_timer *stm_timer = data;
183 183
184 clocksource_unregister(&stm_timer->cs);184 clocksource_unregister(&stm_timer->cs);
185}185}
186 186
187static int __init nxp_stm_clocksource_init(struct device *dev, struct stm_timer *stm_timer,187static int nxp_stm_clocksource_init(struct device *dev, struct stm_timer *stm_timer,
188 const char *name, void __iomem *base, struct clk *clk)188 const char *name, void __iomem *base, struct clk *clk)
189{189{
190 int ret;190 int ret;
191 191
@@ -208,10 +208,8 @@ static int __init nxp_stm_clocksource_init(struct device *dev, struct stm_timer · 16 unmodified lines
208 return ret;208 return ret;
209 209
210 ret = devm_add_action_or_reset(dev, devm_clocksource_unregister, stm_timer);210 ret = devm_add_action_or_reset(dev, devm_clocksource_unregister, stm_timer);
211 if (ret) {211 if (ret)
212 clocksource_unregister(&stm_timer->cs);
213 return ret;212 return ret;
214 }
215 213
216 stm_sched_clock = stm_timer;214 stm_sched_clock = stm_timer;
217 215
@@ -298,9 +296,9 @@ static void nxp_stm_clockevent_resume(struct clock_event_device *ced) · 80 unmodified lines
298 nxp_stm_module_get(stm_timer);296 nxp_stm_module_get(stm_timer);
299}297}
300 298
301static int __init nxp_stm_clockevent_per_cpu_init(struct device *dev, struct stm_timer *stm_timer,299static int nxp_stm_clockevent_per_cpu_init(struct device *dev, struct stm_timer *stm_timer,
302 const char *name, void __iomem *base, int irq,300 const char *name, void __iomem *base, int irq,
303 struct clk *clk, int cpu)301 struct clk *clk, int cpu)
304{302{
305 stm_timer->base = base;303 stm_timer->base = base;
306 stm_timer->rate = clk_get_rate(clk);304 stm_timer->rate = clk_get_rate(clk);
@@ -388,7 +386,7 @@ static irqreturn_t nxp_stm_module_interrupt(int irq, void *dev_id) · 81 unmodified lines
388 return IRQ_HANDLED;386 return IRQ_HANDLED;
389}387}
390 388
391static int __init nxp_stm_timer_probe(struct platform_device *pdev)389static int nxp_stm_timer_probe(struct platform_device *pdev)
392{390{
393 struct stm_timer *stm_timer;391 struct stm_timer *stm_timer;
394 struct device *dev = &pdev->dev;392 struct device *dev = &pdev->dev;
@@ -484,14 +482,15 @@ static const struct of_device_id nxp_stm_of_match[] = { · 89 unmodified lines
484};482};
485MODULE_DEVICE_TABLE(of, nxp_stm_of_match);483MODULE_DEVICE_TABLE(of, nxp_stm_of_match);
486 484
487static struct platform_driver nxp_stm_probe = {485static struct platform_driver nxp_stm_driver = {
488 .probe = nxp_stm_timer_probe,486 .probe = nxp_stm_timer_probe,
489 .driver = {487 .driver = {
490 .name = "nxp-stm",488 .name = "nxp-stm",
491 .of_match_table = nxp_stm_of_match,489 .of_match_table = nxp_stm_of_match,
490 .suppress_bind_attrs = true,
492 },491 },
493};492};
494module_platform_driver(nxp_stm_probe);493builtin_platform_driver(nxp_stm_driver);
495 494
496MODULE_DESCRIPTION("NXP System Timer Module driver");495MODULE_DESCRIPTION("NXP System Timer Module driver");
497MODULE_LICENSE("GPL");496MODULE_LICENSE("GPL");
drivers/clocksource/timer-ralink.c+9−2
@@ -130,14 +130,15 @@ static int __init ralink_systick_init(struct device_node *np) · 129 unmodified lines
130 systick.dev.irq = irq_of_parse_and_map(np, 0);130 systick.dev.irq = irq_of_parse_and_map(np, 0);
131 if (!systick.dev.irq) {131 if (!systick.dev.irq) {
132 pr_err("%pOFn: request_irq failed", np);132 pr_err("%pOFn: request_irq failed", np);
133 return -EINVAL;133 ret = -EINVAL;
134 goto err_iounmap;
134 }135 }
135 136
136 ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,137 ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
137 SYSTICK_FREQ, 301, 16,138 SYSTICK_FREQ, 301, 16,
138 clocksource_mmio_readl_up);139 clocksource_mmio_readl_up);
139 if (ret)140 if (ret)
140 return ret;141 goto err_free_irq;
141 142
142 clockevents_register_device(&systick.dev);143 clockevents_register_device(&systick.dev);
143 144
@@ -145,6 +146,12 @@ static int __init ralink_systick_init(struct device_node *np) · 1 unmodified line
145 np, systick.dev.mult, systick.dev.shift);146 np, systick.dev.mult, systick.dev.shift);
146 147
147 return 0;148 return 0;
149
150err_free_irq:
151 irq_dispose_mapping(systick.dev.irq);
152err_iounmap:
153 iounmap(systick.membase);
154 return ret;
148}155}
149 156
150TIMER_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);157TIMER_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);
drivers/clocksource/timer-rda.c+8−1
@@ -13,6 +13,7 @@ · 12 unmodified lines
13 13
14#include <linux/init.h>14#include <linux/init.h>
15#include <linux/interrupt.h>15#include <linux/interrupt.h>
16#include <linux/sched_clock.h>
16 17
17#include "timer-of.h"18#include "timer-of.h"
18 19
@@ -153,7 +154,7 @@ static struct timer_of rda_ostimer_of = { · 134 unmodified lines
153 },154 },
154};155};
155 156
156static u64 rda_hwtimer_read(struct clocksource *cs)157static u64 rda_hwtimer_clocksource_read(void)
157{158{
158 void __iomem *base = timer_of_base(&rda_ostimer_of);159 void __iomem *base = timer_of_base(&rda_ostimer_of);
159 u32 lo, hi;160 u32 lo, hi;
@@ -167,6 +168,11 @@ static u64 rda_hwtimer_read(struct clocksource *cs) · 7 unmodified lines
167 return ((u64)hi << 32) | lo;168 return ((u64)hi << 32) | lo;
168}169}
169 170
171static u64 rda_hwtimer_read(struct clocksource *cs)
172{
173 return rda_hwtimer_clocksource_read();
174}
175
170static struct clocksource rda_hwtimer_clocksource = {176static struct clocksource rda_hwtimer_clocksource = {
171 .name = "rda-timer",177 .name = "rda-timer",
172 .rating = 400,178 .rating = 400,
@@ -185,6 +191,7 @@ static int __init rda_timer_init(struct device_node *np) · 12 unmodified lines
185 return ret;191 return ret;
186 192
187 clocksource_register_hz(&rda_hwtimer_clocksource, rate);193 clocksource_register_hz(&rda_hwtimer_clocksource, rate);
194 sched_clock_register(rda_hwtimer_clocksource_read, 64, rate);
188 195
189 clockevents_config_and_register(&rda_ostimer_of.clkevt, rate,196 clockevents_config_and_register(&rda_ostimer_of.clkevt, rate,
190 0x2, UINT_MAX);197 0x2, UINT_MAX);
drivers/clocksource/timer-realtek.c+150−0
@@ -0,0 +1,150 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2025 Realtek Semiconductor Corp.
4 */
5
6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7
8#include <linux/irqflags.h>
9#include <linux/interrupt.h>
10#include "timer-of.h"
11
12#define ENBL 1
13#define DSBL 0
14
15#define SYSTIMER_RATE 1000000
16#define SYSTIMER_MIN_DELTA 0x64
17#define SYSTIMER_MAX_DELTA ULONG_MAX
18
19/* SYSTIMER Register Offset (RTK Internal Use) */
20#define TS_LW_OFST 0x0
21#define TS_HW_OFST 0x4
22#define TS_CMP_VAL_LW_OFST 0x8
23#define TS_CMP_VAL_HW_OFST 0xC
24#define TS_CMP_CTRL_OFST 0x10
25#define TS_CMP_STAT_OFST 0x14
26
27/* SYSTIMER CMP CTRL REG Mask */
28#define TS_CMP_EN_MASK 0x1
29#define TS_WR_EN0_MASK 0x2
30
31static void __iomem *systimer_base;
32
33static u64 rtk_ts64_read(void)
34{
35 u32 low, high;
36 u64 ts;
37
38 /* Caution: Read LSB word (TS_LW_OFST) first then MSB (TS_HW_OFST) */
39 low = readl(systimer_base + TS_LW_OFST);
40 high = readl(systimer_base + TS_HW_OFST);
41 ts = ((u64)high << 32) | low;
42
43 return ts;
44}
45
46static void rtk_cmp_value_write(u64 value)
47{
48 u32 high, low;
49
50 low = value & 0xFFFFFFFF;
51 high = value >> 32;
52
53 writel(high, systimer_base + TS_CMP_VAL_HW_OFST);
54 writel(low, systimer_base + TS_CMP_VAL_LW_OFST);
55}
56
57static inline void rtk_cmp_en_write(bool cmp_en)
58{
59 u32 val;
60
61 val = TS_WR_EN0_MASK;
62 if (cmp_en == ENBL)
63 val |= TS_CMP_EN_MASK;
64
65 writel(val, systimer_base + TS_CMP_CTRL_OFST);
66}
67
68static int rtk_syst_clkevt_next_event(unsigned long cycles, struct clock_event_device *clkevt)
69{
70 u64 cmp_val;
71
72 rtk_cmp_en_write(DSBL);
73 cmp_val = rtk_ts64_read();
74
75 /* Set CMP value to current timestamp plus delta_us */
76 rtk_cmp_value_write(cmp_val + cycles);
77 rtk_cmp_en_write(ENBL);
78 return 0;
79}
80
81static irqreturn_t rtk_ts_match_intr_handler(int irq, void *dev_id)
82{
83 struct clock_event_device *clkevt = dev_id;
84 void __iomem *reg_base;
85 u32 val;
86
87 /* Disable TS CMP Match */
88 rtk_cmp_en_write(DSBL);
89
90 /* Clear TS CMP INTR */
91 reg_base = systimer_base + TS_CMP_STAT_OFST;
92 val = readl(reg_base) & TS_CMP_EN_MASK;
93 writel(val | TS_CMP_EN_MASK, reg_base);
94 clkevt->event_handler(clkevt);
95
96 return IRQ_HANDLED;
97}
98
99static int rtk_syst_shutdown(struct clock_event_device *clkevt)
100{
101 void __iomem *reg_base;
102 u64 cmp_val = 0;
103
104 /* Disable TS CMP Match */
105 rtk_cmp_en_write(DSBL);
106 /* Set compare value to 0 */
107 rtk_cmp_value_write(cmp_val);
108
109 /* Clear TS CMP INTR */
110 reg_base = systimer_base + TS_CMP_STAT_OFST;
111 writel(TS_CMP_EN_MASK, reg_base);
112 return 0;
113}
114
115static struct timer_of rtk_timer_to = {
116 .flags = TIMER_OF_IRQ | TIMER_OF_BASE,
117
118 .clkevt = {
119 .name = "rtk-clkevt",
120 .rating = 300,
121 .cpumask = cpu_possible_mask,
122 .features = CLOCK_EVT_FEAT_DYNIRQ |
123 CLOCK_EVT_FEAT_ONESHOT,
124 .set_next_event = rtk_syst_clkevt_next_event,
125 .set_state_oneshot = rtk_syst_shutdown,
126 .set_state_shutdown = rtk_syst_shutdown,
127 },
128
129 .of_irq = {
130 .flags = IRQF_TIMER | IRQF_IRQPOLL,
131 .handler = rtk_ts_match_intr_handler,
132 },
133};
134
135static int __init rtk_systimer_init(struct device_node *node)
136{
137 int ret;
138
139 ret = timer_of_init(node, &rtk_timer_to);
140 if (ret)
141 return ret;
142
143 systimer_base = timer_of_base(&rtk_timer_to);
144 clockevents_config_and_register(&rtk_timer_to.clkevt, SYSTIMER_RATE,
145 SYSTIMER_MIN_DELTA, SYSTIMER_MAX_DELTA);
146
147 return 0;
148}
149
150TIMER_OF_DECLARE(rtk_systimer, "realtek,rtd1625-systimer", rtk_systimer_init);
drivers/clocksource/timer-sp804.c+24−0
@@ -21,6 +21,10 @@ · 20 unmodified lines
21#include <linux/of_irq.h>21#include <linux/of_irq.h>
22#include <linux/sched_clock.h>22#include <linux/sched_clock.h>
23 23
24#ifdef CONFIG_ARM
25#include <linux/delay.h>
26#endif
27
24#include "timer-sp.h"28#include "timer-sp.h"
25 29
26/* Hisilicon 64-bit timer(a variant of ARM SP804) */30/* Hisilicon 64-bit timer(a variant of ARM SP804) */
@@ -102,6 +106,23 @@ static u64 notrace sp804_read(void) · 75 unmodified lines
102 return ~readl_relaxed(sched_clkevt->value);106 return ~readl_relaxed(sched_clkevt->value);
103}107}
104 108
109#ifdef CONFIG_ARM
110static struct delay_timer delay;
111static unsigned long sp804_read_delay_timer_read(void)
112{
113 return sp804_read();
114}
115
116static void sp804_register_delay_timer(int freq)
117{
118 delay.freq = freq;
119 delay.read_current_timer = sp804_read_delay_timer_read;
120 register_current_timer_delay(&delay);
121}
122#else
123static inline void sp804_register_delay_timer(int freq) {}
124#endif
125
105static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,126static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
106 const char *name,127 const char *name,
107 struct clk *clk,128 struct clk *clk,
@@ -114,6 +135,8 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base, · 6 unmodified lines
114 if (rate < 0)135 if (rate < 0)
115 return -EINVAL;136 return -EINVAL;
116 137
138 sp804_register_delay_timer(rate);
139
117 clkevt = sp804_clkevt_get(base);140 clkevt = sp804_clkevt_get(base);
118 141
119 writel(0, clkevt->ctrl);142 writel(0, clkevt->ctrl);
@@ -318,6 +341,7 @@ static int __init sp804_of_init(struct device_node *np, struct sp804_timer *time · 198 unmodified lines
318 if (ret)341 if (ret)
319 goto err;342 goto err;
320 }343 }
344
321 initialized = true;345 initialized = true;
322 346
323 return 0;347 return 0;
drivers/clocksource/timer-sprd.c+18−6
@@ -30,6 +30,7 @@ · 29 unmodified lines
30#define TIMER_VALUE_SHDW_HI 0x1c30#define TIMER_VALUE_SHDW_HI 0x1c
31 31
32#define TIMER_VALUE_LO_MASK GENMASK(31, 0)32#define TIMER_VALUE_LO_MASK GENMASK(31, 0)
33#define TIMER_VALUE_HI_MASK GENMASK(31, 0)
33 34
34static void sprd_timer_enable(void __iomem *base, u32 flag)35static void sprd_timer_enable(void __iomem *base, u32 flag)
35{36{
@@ -162,15 +163,26 @@ static struct timer_of suspend_to = { · 126 unmodified lines
162 163
163static u64 sprd_suspend_timer_read(struct clocksource *cs)164static u64 sprd_suspend_timer_read(struct clocksource *cs)
164{165{
165 return ~(u64)readl_relaxed(timer_of_base(&suspend_to) +166 u32 lo, hi;
166 TIMER_VALUE_SHDW_LO) & cs->mask;167
168 do {
169 hi = readl_relaxed(timer_of_base(&suspend_to) +
170 TIMER_VALUE_SHDW_HI);
171 lo = readl_relaxed(timer_of_base(&suspend_to) +
172 TIMER_VALUE_SHDW_LO);
173 } while (hi != readl_relaxed(timer_of_base(&suspend_to) + TIMER_VALUE_SHDW_HI));
174
175 return ~(((u64)hi << 32) | lo);
167}176}
168 177
169static int sprd_suspend_timer_enable(struct clocksource *cs)178static int sprd_suspend_timer_enable(struct clocksource *cs)
170{179{
171 sprd_timer_update_counter(timer_of_base(&suspend_to),180 writel_relaxed(TIMER_VALUE_LO_MASK,
172 TIMER_VALUE_LO_MASK);181 timer_of_base(&suspend_to) + TIMER_LOAD_LO);
173 sprd_timer_enable(timer_of_base(&suspend_to), TIMER_CTL_PERIOD_MODE);182 writel_relaxed(TIMER_VALUE_HI_MASK,
183 timer_of_base(&suspend_to) + TIMER_LOAD_HI);
184 sprd_timer_enable(timer_of_base(&suspend_to),
185 TIMER_CTL_PERIOD_MODE|TIMER_CTL_64BIT_WIDTH);
174 186
175 return 0;187 return 0;
176}188}
@@ -186,7 +198,7 @@ static struct clocksource suspend_clocksource = { · 9 unmodified lines
186 .read = sprd_suspend_timer_read,198 .read = sprd_suspend_timer_read,
187 .enable = sprd_suspend_timer_enable,199 .enable = sprd_suspend_timer_enable,
188 .disable = sprd_suspend_timer_disable,200 .disable = sprd_suspend_timer_disable,
189 .mask = CLOCKSOURCE_MASK(32),201 .mask = CLOCKSOURCE_MASK(64),
190 .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,202 .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,
191};203};
192 204
drivers/clocksource/timer-stm32-lp.c+0−1
@@ -289,5 +289,4 @@ static struct platform_driver stm32_clkevent_lp_driver = { · 288 unmodified lines
289};289};
290module_platform_driver(stm32_clkevent_lp_driver);290module_platform_driver(stm32_clkevent_lp_driver);
291 291
292MODULE_ALIAS("platform:stm32-lptimer-timer");
293MODULE_DESCRIPTION("STMicroelectronics STM32 clockevent low power driver");292MODULE_DESCRIPTION("STMicroelectronics STM32 clockevent low power driver");

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t