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+
7+title: Realtek System Timer
8+
9+maintainers:
10+ - Hao-Wen Ting <haowen.ting@realtek.com>
11+
12+description:
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+
17+properties:
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+
31+required:
32+ - compatible
33+ - reg
34+ - interrupts
35+
36+additionalProperties: false
37+
38+examples:
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
2168121681 F: Documentation/devicetree/bindings/spi/realtek,rtl9301-snand.yaml
2168221682 F: drivers/spi/spi-realtek-rtl-snand.c
2168321683
21684+REALTEK SYSTIMER DRIVER
21685+M: Hao-Wen Ting <haowen.ting@realtek.com>
21686+S: Maintained
21687+F: drivers/clocksource/timer-realtek.c
21688+
2168421689 REALTEK WIRELESS DRIVER (rtlwifi family)
2168521690 M: Ping-Ke Shih <pkshih@realtek.com>
2168621691 L: linux-wireless@vger.kernel.org
drivers/clocksource/Kconfig+11−0
@@ -782,4 +782,15 @@ config NXP_STM_TIMER · 781 unmodified lines
782782 Enables the support for NXP System Timer Module found in the
783783 s32g NXP platform series.
784784
785+config 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+
785796 endmenu
drivers/clocksource/Makefile+1−0
@@ -95,3 +95,4 @@ obj-$(CONFIG_CLKSRC_LOONGSON1_PWM) += timer-loongson1-pwm.o · 94 unmodified lines
9595 obj-$(CONFIG_EP93XX_TIMER) += timer-ep93xx.o
9696 obj-$(CONFIG_RALINK_TIMER) += timer-ralink.o
9797 obj-$(CONFIG_NXP_STM_TIMER) += timer-nxp-stm.o
98+obj-$(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
426426 .driver = {
427427 .name = "arch-timer-mmio",
428428 .of_match_table = arch_timer_mmio_of_table,
429+ .suppress_bind_attrs = true,
429430 },
430431 .probe = arch_timer_mmio_probe,
431432 };
@@ -434,6 +435,7 @@ builtin_platform_driver(arch_timer_mmio_drv); · 2 unmodified lines
434435 static struct platform_driver arch_timer_mmio_acpi_drv = {
435436 .driver = {
436437 .name = "gtdt-arm-mmio-timer",
438+ .suppress_bind_attrs = true,
437439 },
438440 .probe = arch_timer_mmio_probe,
439441 };
drivers/clocksource/sh_cmt.c+3−33
@@ -355,14 +355,6 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch) · 354 unmodified lines
355355
356356 dev_pm_syscore_device(&ch->cmt->pdev->dev, true);
357357
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−
366358 /* make sure channel is disabled */
367359 sh_cmt_start_stop_ch(ch, 0);
368360
@@ -384,19 +376,12 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch) · 15 unmodified lines
384376 if (ret || sh_cmt_read_cmcnt(ch)) {
385377 dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n",
386378 ch->index);
387− ret = -ETIMEDOUT;
388− goto err1;
379+ return -ETIMEDOUT;
389380 }
390381
391382 /* enable channel */
392383 sh_cmt_start_stop_ch(ch, 1);
393384 return 0;
394− err1:
395− /* stop clock */
396− clk_disable(ch->cmt->clk);
397−
398− err0:
399− return ret;
400385 }
401386
402387 static 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
407392 /* disable interrupts in CMT block */
408393 sh_cmt_write_cmcsr(ch, 0);
409394
410− /* stop clock */
411− clk_disable(ch->cmt->clk);
412−
413395 dev_pm_syscore_device(&ch->cmt->pdev->dev, false);
414396 }
415397
@@ -583,8 +565,6 @@ static int sh_cmt_start_clocksource(struct sh_cmt_channel *ch) · 167 unmodified lines
583565 int ret = 0;
584566 unsigned long flags;
585567
586− pm_runtime_get_sync(&ch->cmt->pdev->dev);
587−
588568 raw_spin_lock_irqsave(&ch->lock, flags);
589569
590570 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
619599 sh_cmt_disable(ch);
620600
621601 raw_spin_unlock_irqrestore(&ch->lock, flags);
622−
623− pm_runtime_put(&ch->cmt->pdev->dev);
624602 }
625603
626604 static 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
630608
631609 raw_spin_lock_irqsave(&ch->lock, flags);
632610
633− if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) {
634− pm_runtime_get_sync(&ch->cmt->pdev->dev);
611+ if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
635612 ret = sh_cmt_enable(ch);
636− }
637613
638614 if (ret)
639615 goto out;
@@ -656,10 +632,8 @@ static void sh_cmt_stop_clockevent(struct sh_cmt_channel *ch) · 16 unmodified lines
656632
657633 ch->flags &= ~FLAG_CLOCKEVENT;
658634
659− if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) {
635+ if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
660636 sh_cmt_disable(ch);
661− pm_runtime_put(&ch->cmt->pdev->dev);
662− }
663637
664638 /* adjust the timeout to maximum if only clocksource left */
665639 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
11341108 mask &= ~(1 << hwidx);
11351109 }
11361110
1137− clk_disable(cmt->clk);
1138−
11391111 platform_set_drvdata(pdev, cmt);
11401112
11411113 return 0;
@@ -1183,8 +1155,6 @@ static int sh_cmt_probe(struct platform_device *pdev) · 41 unmodified lines
11831155 out:
11841156 if (cmt->has_clockevent || cmt->has_clocksource)
11851157 pm_runtime_irq_safe(&pdev->dev);
1186− else
1187− pm_runtime_idle(&pdev->dev);
11881158
11891159 return 0;
11901160 }
drivers/clocksource/timer-nxp-pit.c+2−1
@@ -374,9 +374,10 @@ static struct platform_driver nxp_pit_driver = { · 373 unmodified lines
374374 .driver = {
375375 .name = "nxp-pit",
376376 .of_match_table = pit_timer_of_match,
377+ .suppress_bind_attrs = true,
377378 },
378379 .probe = pit_timer_probe,
379380 };
380−module_platform_driver(nxp_pit_driver);
381+builtin_platform_driver(nxp_pit_driver);
381382
382383 TIMER_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
177177 nxp_stm_clocksource_enable(cs);
178178 }
179179
180−static void __init devm_clocksource_unregister(void *data)
180+static void devm_clocksource_unregister(void *data)
181181 {
182182 struct stm_timer *stm_timer = data;
183183
184184 clocksource_unregister(&stm_timer->cs);
185185 }
186186
187−static int __init nxp_stm_clocksource_init(struct device *dev, struct stm_timer *stm_timer,
188− const char *name, void __iomem *base, struct clk *clk)
187+static int nxp_stm_clocksource_init(struct device *dev, struct stm_timer *stm_timer,
188+ const char *name, void __iomem *base, struct clk *clk)
189189 {
190190 int ret;
191191
@@ -208,10 +208,8 @@ static int __init nxp_stm_clocksource_init(struct device *dev, struct stm_timer · 16 unmodified lines
208208 return ret;
209209
210210 ret = devm_add_action_or_reset(dev, devm_clocksource_unregister, stm_timer);
211− if (ret) {
212− clocksource_unregister(&stm_timer->cs);
211+ if (ret)
213212 return ret;
214− }
215213
216214 stm_sched_clock = stm_timer;
217215
@@ -298,9 +296,9 @@ static void nxp_stm_clockevent_resume(struct clock_event_device *ced) · 80 unmodified lines
298296 nxp_stm_module_get(stm_timer);
299297 }
300298
301−static int __init nxp_stm_clockevent_per_cpu_init(struct device *dev, struct stm_timer *stm_timer,
302− const char *name, void __iomem *base, int irq,
303− struct clk *clk, int cpu)
299+static int nxp_stm_clockevent_per_cpu_init(struct device *dev, struct stm_timer *stm_timer,
300+ const char *name, void __iomem *base, int irq,
301+ struct clk *clk, int cpu)
304302 {
305303 stm_timer->base = base;
306304 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
388386 return IRQ_HANDLED;
389387 }
390388
391−static int __init nxp_stm_timer_probe(struct platform_device *pdev)
389+static int nxp_stm_timer_probe(struct platform_device *pdev)
392390 {
393391 struct stm_timer *stm_timer;
394392 struct device *dev = &pdev->dev;
@@ -484,14 +482,15 @@ static const struct of_device_id nxp_stm_of_match[] = { · 89 unmodified lines
484482 };
485483 MODULE_DEVICE_TABLE(of, nxp_stm_of_match);
486484
487−static struct platform_driver nxp_stm_probe = {
485+static struct platform_driver nxp_stm_driver = {
488486 .probe = nxp_stm_timer_probe,
489487 .driver = {
490488 .name = "nxp-stm",
491489 .of_match_table = nxp_stm_of_match,
490+ .suppress_bind_attrs = true,
492491 },
493492 };
494−module_platform_driver(nxp_stm_probe);
493+builtin_platform_driver(nxp_stm_driver);
495494
496495 MODULE_DESCRIPTION("NXP System Timer Module driver");
497496 MODULE_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
130130 systick.dev.irq = irq_of_parse_and_map(np, 0);
131131 if (!systick.dev.irq) {
132132 pr_err("%pOFn: request_irq failed", np);
133− return -EINVAL;
133+ ret = -EINVAL;
134+ goto err_iounmap;
134135 }
135136
136137 ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
137138 SYSTICK_FREQ, 301, 16,
138139 clocksource_mmio_readl_up);
139140 if (ret)
140− return ret;
141+ goto err_free_irq;
141142
142143 clockevents_register_device(&systick.dev);
143144
@@ -145,6 +146,12 @@ static int __init ralink_systick_init(struct device_node *np) · 1 unmodified line
145146 np, systick.dev.mult, systick.dev.shift);
146147
147148 return 0;
149+
150+err_free_irq:
151+ irq_dispose_mapping(systick.dev.irq);
152+err_iounmap:
153+ iounmap(systick.membase);
154+ return ret;
148155 }
149156
150157 TIMER_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);
drivers/clocksource/timer-rda.c+8−1
@@ -13,6 +13,7 @@ · 12 unmodified lines
1313
1414 #include <linux/init.h>
1515 #include <linux/interrupt.h>
16+#include <linux/sched_clock.h>
1617
1718 #include "timer-of.h"
1819
@@ -153,7 +154,7 @@ static struct timer_of rda_ostimer_of = { · 134 unmodified lines
153154 },
154155 };
155156
156−static u64 rda_hwtimer_read(struct clocksource *cs)
157+static u64 rda_hwtimer_clocksource_read(void)
157158 {
158159 void __iomem *base = timer_of_base(&rda_ostimer_of);
159160 u32 lo, hi;
@@ -167,6 +168,11 @@ static u64 rda_hwtimer_read(struct clocksource *cs) · 7 unmodified lines
167168 return ((u64)hi << 32) | lo;
168169 }
169170
171+static u64 rda_hwtimer_read(struct clocksource *cs)
172+{
173+ return rda_hwtimer_clocksource_read();
174+}
175+
170176 static struct clocksource rda_hwtimer_clocksource = {
171177 .name = "rda-timer",
172178 .rating = 400,
@@ -185,6 +191,7 @@ static int __init rda_timer_init(struct device_node *np) · 12 unmodified lines
185191 return ret;
186192
187193 clocksource_register_hz(&rda_hwtimer_clocksource, rate);
194+ sched_clock_register(rda_hwtimer_clocksource_read, 64, rate);
188195
189196 clockevents_config_and_register(&rda_ostimer_of.clkevt, rate,
190197 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+
31+static void __iomem *systimer_base;
32+
33+static 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+
46+static 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+
57+static 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+
68+static 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+
81+static 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+
99+static 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+
115+static 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+
135+static 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+
150+TIMER_OF_DECLARE(rtk_systimer, "realtek,rtd1625-systimer", rtk_systimer_init);
drivers/clocksource/timer-sp804.c+24−0
@@ -21,6 +21,10 @@ · 20 unmodified lines
2121 #include <linux/of_irq.h>
2222 #include <linux/sched_clock.h>
2323
24+#ifdef CONFIG_ARM
25+#include <linux/delay.h>
26+#endif
27+
2428 #include "timer-sp.h"
2529
2630 /* Hisilicon 64-bit timer(a variant of ARM SP804) */
@@ -102,6 +106,23 @@ static u64 notrace sp804_read(void) · 75 unmodified lines
102106 return ~readl_relaxed(sched_clkevt->value);
103107 }
104108
109+#ifdef CONFIG_ARM
110+static struct delay_timer delay;
111+static unsigned long sp804_read_delay_timer_read(void)
112+{
113+ return sp804_read();
114+}
115+
116+static 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
123+static inline void sp804_register_delay_timer(int freq) {}
124+#endif
125+
105126 static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
106127 const char *name,
107128 struct clk *clk,
@@ -114,6 +135,8 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base, · 6 unmodified lines
114135 if (rate < 0)
115136 return -EINVAL;
116137
138+ sp804_register_delay_timer(rate);
139+
117140 clkevt = sp804_clkevt_get(base);
118141
119142 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
318341 if (ret)
319342 goto err;
320343 }
344+
321345 initialized = true;
322346
323347 return 0;
drivers/clocksource/timer-sprd.c+18−6
@@ -30,6 +30,7 @@ · 29 unmodified lines
3030 #define TIMER_VALUE_SHDW_HI 0x1c
3131
3232 #define TIMER_VALUE_LO_MASK GENMASK(31, 0)
33+#define TIMER_VALUE_HI_MASK GENMASK(31, 0)
3334
3435 static void sprd_timer_enable(void __iomem *base, u32 flag)
3536 {
@@ -162,15 +163,26 @@ static struct timer_of suspend_to = { · 126 unmodified lines
162163
163164 static u64 sprd_suspend_timer_read(struct clocksource *cs)
164165 {
165− return ~(u64)readl_relaxed(timer_of_base(&suspend_to) +
166− TIMER_VALUE_SHDW_LO) & cs->mask;
166+ u32 lo, hi;
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);
167176 }
168177
169178 static int sprd_suspend_timer_enable(struct clocksource *cs)
170179 {
171− sprd_timer_update_counter(timer_of_base(&suspend_to),
172− TIMER_VALUE_LO_MASK);
173− sprd_timer_enable(timer_of_base(&suspend_to), TIMER_CTL_PERIOD_MODE);
180+ writel_relaxed(TIMER_VALUE_LO_MASK,
181+ timer_of_base(&suspend_to) + TIMER_LOAD_LO);
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);
174186
175187 return 0;
176188 }
@@ -186,7 +198,7 @@ static struct clocksource suspend_clocksource = { · 9 unmodified lines
186198 .read = sprd_suspend_timer_read,
187199 .enable = sprd_suspend_timer_enable,
188200 .disable = sprd_suspend_timer_disable,
189− .mask = CLOCKSOURCE_MASK(32),
201+ .mask = CLOCKSOURCE_MASK(64),
190202 .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,
191203 };
192204
drivers/clocksource/timer-stm32-lp.c+0−1
@@ -289,5 +289,4 @@ static struct platform_driver stm32_clkevent_lp_driver = { · 288 unmodified lines
289289 };
290290 module_platform_driver(stm32_clkevent_lp_driver);
291291
292−MODULE_ALIAS("platform:stm32-lptimer-timer");
293292 MODULE_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