Skip to content

Commit 7d8d201

Browse files
committed
Merge tag 'timers-core-2023-04-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull more timer updates from Thomas Gleixner: "Timekeeping and clocksource/event driver updates the second batch: - A trivial documentation fix in the timekeeping core - A really boring set of small fixes, enhancements and cleanups in the drivers code. No new clocksource/clockevent drivers for a change" * tag 'timers-core-2023-04-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: timekeeping: Fix references to nonexistent ktime_get_fast_ns() dt-bindings: timer: rockchip: Add rk3588 compatible dt-bindings: timer: rockchip: Drop superfluous rk3288 compatible clocksource/drivers/ti: Use of_property_read_bool() for boolean properties clocksource/drivers/timer-ti-dm: Fix finding alwon timer clocksource/drivers/davinci: Fix memory leak in davinci_timer_register when init fails clocksource/drivers/stm32-lp: Drop of_match_ptr for ID table clocksource/drivers/timer-ti-dm: Convert to platform remove callback returning void clocksource/drivers/timer-tegra186: Convert to platform remove callback returning void clocksource/drivers/timer-ti-dm: Improve error message in .remove clocksource/drivers/timer-stm32-lp: Mark driver as non-removable clocksource/drivers/sh_mtu2: Mark driver as non-removable clocksource/drivers/timer-ti-dm: Use of_address_to_resource() clocksource/drivers/timer-imx-gpt: Remove non-DT function clocksource/drivers/timer-mediatek: Split out CPUXGPT timers clocksource/drivers/exynos_mct: Explicitly return 0 for shared timer
2 parents 8c1318e + 158009f commit 7d8d201

15 files changed

Lines changed: 223 additions & 207 deletions

File tree

Documentation/devicetree/bindings/timer/rockchip,rk-timer.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ properties:
2323
- rockchip,rk3188-timer
2424
- rockchip,rk3228-timer
2525
- rockchip,rk3229-timer
26-
- rockchip,rk3288-timer
2726
- rockchip,rk3368-timer
27+
- rockchip,rk3588-timer
2828
- rockchip,px30-timer
2929
- const: rockchip,rk3288-timer
3030
reg:

drivers/clocksource/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,15 @@ config MTK_TIMER
479479
help
480480
Support for Mediatek timer driver.
481481

482+
config MTK_CPUX_TIMER
483+
bool "MediaTek CPUX timer driver" if COMPILE_TEST
484+
depends on HAS_IOMEM
485+
default ARCH_MEDIATEK
486+
select TIMER_OF
487+
select CLKSRC_MMIO
488+
help
489+
Support for MediaTek CPUXGPT timer driver.
490+
482491
config SPRD_TIMER
483492
bool "Spreadtrum timer driver" if EXPERT
484493
depends on HAS_IOMEM

drivers/clocksource/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ obj-$(CONFIG_FSL_FTM_TIMER) += timer-fsl-ftm.o
5151
obj-$(CONFIG_VF_PIT_TIMER) += timer-vf-pit.o
5252
obj-$(CONFIG_CLKSRC_QCOM) += timer-qcom.o
5353
obj-$(CONFIG_MTK_TIMER) += timer-mediatek.o
54+
obj-$(CONFIG_MTK_CPUX_TIMER) += timer-mediatek-cpux.o
5455
obj-$(CONFIG_CLKSRC_PISTACHIO) += timer-pistachio.o
5556
obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o
5657
obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o

drivers/clocksource/exynos_mct.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ static int __init mct_init_dt(struct device_node *np, unsigned int int_type)
682682
* processor cannot use the global comparator.
683683
*/
684684
if (frc_shared)
685-
return ret;
685+
return 0;
686686

687687
return exynos4_clockevent_init();
688688
}

drivers/clocksource/sh_mtu2.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -484,11 +484,6 @@ static int sh_mtu2_probe(struct platform_device *pdev)
484484
return 0;
485485
}
486486

487-
static int sh_mtu2_remove(struct platform_device *pdev)
488-
{
489-
return -EBUSY; /* cannot unregister clockevent */
490-
}
491-
492487
static const struct platform_device_id sh_mtu2_id_table[] = {
493488
{ "sh-mtu2", 0 },
494489
{ },
@@ -503,10 +498,10 @@ MODULE_DEVICE_TABLE(of, sh_mtu2_of_table);
503498

504499
static struct platform_driver sh_mtu2_device_driver = {
505500
.probe = sh_mtu2_probe,
506-
.remove = sh_mtu2_remove,
507501
.driver = {
508502
.name = "sh_mtu2",
509503
.of_match_table = of_match_ptr(sh_mtu2_of_table),
504+
.suppress_bind_attrs = true,
510505
},
511506
.id_table = sh_mtu2_id_table,
512507
};

drivers/clocksource/timer-davinci.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,21 +257,25 @@ int __init davinci_timer_register(struct clk *clk,
257257
resource_size(&timer_cfg->reg),
258258
"davinci-timer")) {
259259
pr_err("Unable to request memory region\n");
260-
return -EBUSY;
260+
rv = -EBUSY;
261+
goto exit_clk_disable;
261262
}
262263

263264
base = ioremap(timer_cfg->reg.start, resource_size(&timer_cfg->reg));
264265
if (!base) {
265266
pr_err("Unable to map the register range\n");
266-
return -ENOMEM;
267+
rv = -ENOMEM;
268+
goto exit_mem_region;
267269
}
268270

269271
davinci_timer_init(base);
270272
tick_rate = clk_get_rate(clk);
271273

272274
clockevent = kzalloc(sizeof(*clockevent), GFP_KERNEL);
273-
if (!clockevent)
274-
return -ENOMEM;
275+
if (!clockevent) {
276+
rv = -ENOMEM;
277+
goto exit_iounmap_base;
278+
}
275279

276280
clockevent->dev.name = "tim12";
277281
clockevent->dev.features = CLOCK_EVT_FEAT_ONESHOT;
@@ -296,7 +300,7 @@ int __init davinci_timer_register(struct clk *clk,
296300
"clockevent/tim12", clockevent);
297301
if (rv) {
298302
pr_err("Unable to request the clockevent interrupt\n");
299-
return rv;
303+
goto exit_free_clockevent;
300304
}
301305

302306
davinci_clocksource.dev.rating = 300;
@@ -323,13 +327,27 @@ int __init davinci_timer_register(struct clk *clk,
323327
rv = clocksource_register_hz(&davinci_clocksource.dev, tick_rate);
324328
if (rv) {
325329
pr_err("Unable to register clocksource\n");
326-
return rv;
330+
goto exit_free_irq;
327331
}
328332

329333
sched_clock_register(davinci_timer_read_sched_clock,
330334
DAVINCI_TIMER_CLKSRC_BITS, tick_rate);
331335

332336
return 0;
337+
338+
exit_free_irq:
339+
free_irq(timer_cfg->irq[DAVINCI_TIMER_CLOCKEVENT_IRQ].start,
340+
clockevent);
341+
exit_free_clockevent:
342+
kfree(clockevent);
343+
exit_iounmap_base:
344+
iounmap(base);
345+
exit_mem_region:
346+
release_mem_region(timer_cfg->reg.start,
347+
resource_size(&timer_cfg->reg));
348+
exit_clk_disable:
349+
clk_disable_unprepare(clk);
350+
return rv;
333351
}
334352

335353
static int __init of_davinci_timer_register(struct device_node *np)

drivers/clocksource/timer-imx-gpt.c

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -420,25 +420,6 @@ static int __init _mxc_timer_init(struct imx_timer *imxtm)
420420
return mxc_clockevent_init(imxtm);
421421
}
422422

423-
void __init mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type)
424-
{
425-
struct imx_timer *imxtm;
426-
427-
imxtm = kzalloc(sizeof(*imxtm), GFP_KERNEL);
428-
BUG_ON(!imxtm);
429-
430-
imxtm->clk_per = clk_get_sys("imx-gpt.0", "per");
431-
imxtm->clk_ipg = clk_get_sys("imx-gpt.0", "ipg");
432-
433-
imxtm->base = ioremap(pbase, SZ_4K);
434-
BUG_ON(!imxtm->base);
435-
436-
imxtm->type = type;
437-
imxtm->irq = irq;
438-
439-
_mxc_timer_init(imxtm);
440-
}
441-
442423
static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type type)
443424
{
444425
struct imx_timer *imxtm;
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* MediaTek SoCs CPUX General Purpose Timer handling
4+
*
5+
* Based on timer-mediatek.c:
6+
* Copyright (C) 2014 Matthias Brugger <matthias.bgg@gmail.com>
7+
*
8+
* Copyright (C) 2022 Collabora Ltd.
9+
* AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
10+
*/
11+
12+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13+
14+
#include <linux/clockchips.h>
15+
#include <linux/clocksource.h>
16+
#include <linux/interrupt.h>
17+
#include <linux/irqreturn.h>
18+
#include <linux/sched_clock.h>
19+
#include <linux/slab.h>
20+
#include "timer-of.h"
21+
22+
#define TIMER_SYNC_TICKS 3
23+
24+
/* cpux mcusys wrapper */
25+
#define CPUX_CON_REG 0x0
26+
#define CPUX_IDX_REG 0x4
27+
28+
/* cpux */
29+
#define CPUX_IDX_GLOBAL_CTRL 0x0
30+
#define CPUX_ENABLE BIT(0)
31+
#define CPUX_CLK_DIV_MASK GENMASK(10, 8)
32+
#define CPUX_CLK_DIV1 BIT(8)
33+
#define CPUX_CLK_DIV2 BIT(9)
34+
#define CPUX_CLK_DIV4 BIT(10)
35+
#define CPUX_IDX_GLOBAL_IRQ 0x30
36+
37+
static u32 mtk_cpux_readl(u32 reg_idx, struct timer_of *to)
38+
{
39+
writel(reg_idx, timer_of_base(to) + CPUX_IDX_REG);
40+
return readl(timer_of_base(to) + CPUX_CON_REG);
41+
}
42+
43+
static void mtk_cpux_writel(u32 val, u32 reg_idx, struct timer_of *to)
44+
{
45+
writel(reg_idx, timer_of_base(to) + CPUX_IDX_REG);
46+
writel(val, timer_of_base(to) + CPUX_CON_REG);
47+
}
48+
49+
static void mtk_cpux_set_irq(struct timer_of *to, bool enable)
50+
{
51+
const unsigned long *irq_mask = cpumask_bits(cpu_possible_mask);
52+
u32 val;
53+
54+
val = mtk_cpux_readl(CPUX_IDX_GLOBAL_IRQ, to);
55+
56+
if (enable)
57+
val |= *irq_mask;
58+
else
59+
val &= ~(*irq_mask);
60+
61+
mtk_cpux_writel(val, CPUX_IDX_GLOBAL_IRQ, to);
62+
}
63+
64+
static int mtk_cpux_clkevt_shutdown(struct clock_event_device *clkevt)
65+
{
66+
/* Clear any irq */
67+
mtk_cpux_set_irq(to_timer_of(clkevt), false);
68+
69+
/*
70+
* Disabling CPUXGPT timer will crash the platform, especially
71+
* if Trusted Firmware is using it (usually, for sleep states),
72+
* so we only mask the IRQ and call it a day.
73+
*/
74+
return 0;
75+
}
76+
77+
static int mtk_cpux_clkevt_resume(struct clock_event_device *clkevt)
78+
{
79+
mtk_cpux_set_irq(to_timer_of(clkevt), true);
80+
return 0;
81+
}
82+
83+
static struct timer_of to = {
84+
/*
85+
* There are per-cpu interrupts for the CPUX General Purpose Timer
86+
* but since this timer feeds the AArch64 System Timer we can rely
87+
* on the CPU timer PPIs as well, so we don't declare TIMER_OF_IRQ.
88+
*/
89+
.flags = TIMER_OF_BASE | TIMER_OF_CLOCK,
90+
91+
.clkevt = {
92+
.name = "mtk-cpuxgpt",
93+
.cpumask = cpu_possible_mask,
94+
.rating = 10,
95+
.set_state_shutdown = mtk_cpux_clkevt_shutdown,
96+
.tick_resume = mtk_cpux_clkevt_resume,
97+
},
98+
};
99+
100+
static int __init mtk_cpux_init(struct device_node *node)
101+
{
102+
u32 freq, val;
103+
int ret;
104+
105+
/* If this fails, bad things are about to happen... */
106+
ret = timer_of_init(node, &to);
107+
if (ret) {
108+
WARN(1, "Cannot start CPUX timers.\n");
109+
return ret;
110+
}
111+
112+
/*
113+
* Check if we're given a clock with the right frequency for this
114+
* timer, otherwise warn but keep going with the setup anyway, as
115+
* that makes it possible to still boot the kernel, even though
116+
* it may not work correctly (random lockups, etc).
117+
* The reason behind this is that having an early UART may not be
118+
* possible for everyone and this gives a chance to retrieve kmsg
119+
* for eventual debugging even on consumer devices.
120+
*/
121+
freq = timer_of_rate(&to);
122+
if (freq > 13000000)
123+
WARN(1, "Requested unsupported timer frequency %u\n", freq);
124+
125+
/* Clock input is 26MHz, set DIV2 to achieve 13MHz clock */
126+
val = mtk_cpux_readl(CPUX_IDX_GLOBAL_CTRL, &to);
127+
val &= ~CPUX_CLK_DIV_MASK;
128+
val |= CPUX_CLK_DIV2;
129+
mtk_cpux_writel(val, CPUX_IDX_GLOBAL_CTRL, &to);
130+
131+
/* Enable all CPUXGPT timers */
132+
val = mtk_cpux_readl(CPUX_IDX_GLOBAL_CTRL, &to);
133+
mtk_cpux_writel(val | CPUX_ENABLE, CPUX_IDX_GLOBAL_CTRL, &to);
134+
135+
clockevents_config_and_register(&to.clkevt, timer_of_rate(&to),
136+
TIMER_SYNC_TICKS, 0xffffffff);
137+
138+
return 0;
139+
}
140+
TIMER_OF_DECLARE(mtk_mt6795, "mediatek,mt6795-systimer", mtk_cpux_init);

0 commit comments

Comments
 (0)