Skip to content

Commit

Permalink
Merge tag 'timers-core-2023-04-28' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/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
  • Loading branch information
torvalds committed Apr 29, 2023
2 parents 8c1318e + 158009f commit 7d8d201
Show file tree
Hide file tree
Showing 15 changed files with 223 additions and 207 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ properties:
- rockchip,rk3188-timer
- rockchip,rk3228-timer
- rockchip,rk3229-timer
- rockchip,rk3288-timer
- rockchip,rk3368-timer
- rockchip,rk3588-timer
- rockchip,px30-timer
- const: rockchip,rk3288-timer
reg:
Expand Down
9 changes: 9 additions & 0 deletions drivers/clocksource/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,15 @@ config MTK_TIMER
help
Support for Mediatek timer driver.

config MTK_CPUX_TIMER
bool "MediaTek CPUX timer driver" if COMPILE_TEST
depends on HAS_IOMEM
default ARCH_MEDIATEK
select TIMER_OF
select CLKSRC_MMIO
help
Support for MediaTek CPUXGPT timer driver.

config SPRD_TIMER
bool "Spreadtrum timer driver" if EXPERT
depends on HAS_IOMEM
Expand Down
1 change: 1 addition & 0 deletions drivers/clocksource/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ obj-$(CONFIG_FSL_FTM_TIMER) += timer-fsl-ftm.o
obj-$(CONFIG_VF_PIT_TIMER) += timer-vf-pit.o
obj-$(CONFIG_CLKSRC_QCOM) += timer-qcom.o
obj-$(CONFIG_MTK_TIMER) += timer-mediatek.o
obj-$(CONFIG_MTK_CPUX_TIMER) += timer-mediatek-cpux.o
obj-$(CONFIG_CLKSRC_PISTACHIO) += timer-pistachio.o
obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o
obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o
Expand Down
2 changes: 1 addition & 1 deletion drivers/clocksource/exynos_mct.c
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ static int __init mct_init_dt(struct device_node *np, unsigned int int_type)
* processor cannot use the global comparator.
*/
if (frc_shared)
return ret;
return 0;

return exynos4_clockevent_init();
}
Expand Down
7 changes: 1 addition & 6 deletions drivers/clocksource/sh_mtu2.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,11 +484,6 @@ static int sh_mtu2_probe(struct platform_device *pdev)
return 0;
}

static int sh_mtu2_remove(struct platform_device *pdev)
{
return -EBUSY; /* cannot unregister clockevent */
}

static const struct platform_device_id sh_mtu2_id_table[] = {
{ "sh-mtu2", 0 },
{ },
Expand All @@ -503,10 +498,10 @@ MODULE_DEVICE_TABLE(of, sh_mtu2_of_table);

static struct platform_driver sh_mtu2_device_driver = {
.probe = sh_mtu2_probe,
.remove = sh_mtu2_remove,
.driver = {
.name = "sh_mtu2",
.of_match_table = of_match_ptr(sh_mtu2_of_table),
.suppress_bind_attrs = true,
},
.id_table = sh_mtu2_id_table,
};
Expand Down
30 changes: 24 additions & 6 deletions drivers/clocksource/timer-davinci.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,21 +257,25 @@ int __init davinci_timer_register(struct clk *clk,
resource_size(&timer_cfg->reg),
"davinci-timer")) {
pr_err("Unable to request memory region\n");
return -EBUSY;
rv = -EBUSY;
goto exit_clk_disable;
}

base = ioremap(timer_cfg->reg.start, resource_size(&timer_cfg->reg));
if (!base) {
pr_err("Unable to map the register range\n");
return -ENOMEM;
rv = -ENOMEM;
goto exit_mem_region;
}

davinci_timer_init(base);
tick_rate = clk_get_rate(clk);

clockevent = kzalloc(sizeof(*clockevent), GFP_KERNEL);
if (!clockevent)
return -ENOMEM;
if (!clockevent) {
rv = -ENOMEM;
goto exit_iounmap_base;
}

clockevent->dev.name = "tim12";
clockevent->dev.features = CLOCK_EVT_FEAT_ONESHOT;
Expand All @@ -296,7 +300,7 @@ int __init davinci_timer_register(struct clk *clk,
"clockevent/tim12", clockevent);
if (rv) {
pr_err("Unable to request the clockevent interrupt\n");
return rv;
goto exit_free_clockevent;
}

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

sched_clock_register(davinci_timer_read_sched_clock,
DAVINCI_TIMER_CLKSRC_BITS, tick_rate);

return 0;

exit_free_irq:
free_irq(timer_cfg->irq[DAVINCI_TIMER_CLOCKEVENT_IRQ].start,
clockevent);
exit_free_clockevent:
kfree(clockevent);
exit_iounmap_base:
iounmap(base);
exit_mem_region:
release_mem_region(timer_cfg->reg.start,
resource_size(&timer_cfg->reg));
exit_clk_disable:
clk_disable_unprepare(clk);
return rv;
}

static int __init of_davinci_timer_register(struct device_node *np)
Expand Down
19 changes: 0 additions & 19 deletions drivers/clocksource/timer-imx-gpt.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,25 +420,6 @@ static int __init _mxc_timer_init(struct imx_timer *imxtm)
return mxc_clockevent_init(imxtm);
}

void __init mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type)
{
struct imx_timer *imxtm;

imxtm = kzalloc(sizeof(*imxtm), GFP_KERNEL);
BUG_ON(!imxtm);

imxtm->clk_per = clk_get_sys("imx-gpt.0", "per");
imxtm->clk_ipg = clk_get_sys("imx-gpt.0", "ipg");

imxtm->base = ioremap(pbase, SZ_4K);
BUG_ON(!imxtm->base);

imxtm->type = type;
imxtm->irq = irq;

_mxc_timer_init(imxtm);
}

static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type type)
{
struct imx_timer *imxtm;
Expand Down
140 changes: 140 additions & 0 deletions drivers/clocksource/timer-mediatek-cpux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* MediaTek SoCs CPUX General Purpose Timer handling
*
* Based on timer-mediatek.c:
* Copyright (C) 2014 Matthias Brugger <[email protected]>
*
* Copyright (C) 2022 Collabora Ltd.
* AngeloGioacchino Del Regno <[email protected]>
*/

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/sched_clock.h>
#include <linux/slab.h>
#include "timer-of.h"

#define TIMER_SYNC_TICKS 3

/* cpux mcusys wrapper */
#define CPUX_CON_REG 0x0
#define CPUX_IDX_REG 0x4

/* cpux */
#define CPUX_IDX_GLOBAL_CTRL 0x0
#define CPUX_ENABLE BIT(0)
#define CPUX_CLK_DIV_MASK GENMASK(10, 8)
#define CPUX_CLK_DIV1 BIT(8)
#define CPUX_CLK_DIV2 BIT(9)
#define CPUX_CLK_DIV4 BIT(10)
#define CPUX_IDX_GLOBAL_IRQ 0x30

static u32 mtk_cpux_readl(u32 reg_idx, struct timer_of *to)
{
writel(reg_idx, timer_of_base(to) + CPUX_IDX_REG);
return readl(timer_of_base(to) + CPUX_CON_REG);
}

static void mtk_cpux_writel(u32 val, u32 reg_idx, struct timer_of *to)
{
writel(reg_idx, timer_of_base(to) + CPUX_IDX_REG);
writel(val, timer_of_base(to) + CPUX_CON_REG);
}

static void mtk_cpux_set_irq(struct timer_of *to, bool enable)
{
const unsigned long *irq_mask = cpumask_bits(cpu_possible_mask);
u32 val;

val = mtk_cpux_readl(CPUX_IDX_GLOBAL_IRQ, to);

if (enable)
val |= *irq_mask;
else
val &= ~(*irq_mask);

mtk_cpux_writel(val, CPUX_IDX_GLOBAL_IRQ, to);
}

static int mtk_cpux_clkevt_shutdown(struct clock_event_device *clkevt)
{
/* Clear any irq */
mtk_cpux_set_irq(to_timer_of(clkevt), false);

/*
* Disabling CPUXGPT timer will crash the platform, especially
* if Trusted Firmware is using it (usually, for sleep states),
* so we only mask the IRQ and call it a day.
*/
return 0;
}

static int mtk_cpux_clkevt_resume(struct clock_event_device *clkevt)
{
mtk_cpux_set_irq(to_timer_of(clkevt), true);
return 0;
}

static struct timer_of to = {
/*
* There are per-cpu interrupts for the CPUX General Purpose Timer
* but since this timer feeds the AArch64 System Timer we can rely
* on the CPU timer PPIs as well, so we don't declare TIMER_OF_IRQ.
*/
.flags = TIMER_OF_BASE | TIMER_OF_CLOCK,

.clkevt = {
.name = "mtk-cpuxgpt",
.cpumask = cpu_possible_mask,
.rating = 10,
.set_state_shutdown = mtk_cpux_clkevt_shutdown,
.tick_resume = mtk_cpux_clkevt_resume,
},
};

static int __init mtk_cpux_init(struct device_node *node)
{
u32 freq, val;
int ret;

/* If this fails, bad things are about to happen... */
ret = timer_of_init(node, &to);
if (ret) {
WARN(1, "Cannot start CPUX timers.\n");
return ret;
}

/*
* Check if we're given a clock with the right frequency for this
* timer, otherwise warn but keep going with the setup anyway, as
* that makes it possible to still boot the kernel, even though
* it may not work correctly (random lockups, etc).
* The reason behind this is that having an early UART may not be
* possible for everyone and this gives a chance to retrieve kmsg
* for eventual debugging even on consumer devices.
*/
freq = timer_of_rate(&to);
if (freq > 13000000)
WARN(1, "Requested unsupported timer frequency %u\n", freq);

/* Clock input is 26MHz, set DIV2 to achieve 13MHz clock */
val = mtk_cpux_readl(CPUX_IDX_GLOBAL_CTRL, &to);
val &= ~CPUX_CLK_DIV_MASK;
val |= CPUX_CLK_DIV2;
mtk_cpux_writel(val, CPUX_IDX_GLOBAL_CTRL, &to);

/* Enable all CPUXGPT timers */
val = mtk_cpux_readl(CPUX_IDX_GLOBAL_CTRL, &to);
mtk_cpux_writel(val | CPUX_ENABLE, CPUX_IDX_GLOBAL_CTRL, &to);

clockevents_config_and_register(&to.clkevt, timer_of_rate(&to),
TIMER_SYNC_TICKS, 0xffffffff);

return 0;
}
TIMER_OF_DECLARE(mtk_mt6795, "mediatek,mt6795-systimer", mtk_cpux_init);
Loading

0 comments on commit 7d8d201

Please sign in to comment.