From fd3f088f35f610a7ee3045b7d172b362342e43c6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 3 Apr 2023 11:40:17 +0200 Subject: clocksource/drivers/exynos_mct: Explicitly return 0 for shared timer For a shared timers, the mct_init_dt() should not initialize the clock even with global comparator. This is not an error, thus the function should simply return 0, not 'ret'. This also fixes smatch warning: drivers/clocksource/exynos_mct.c:635 mct_init_dt() warn: missing error code? 'ret' Reported-by: kernel test robot Reported-by: Dan Carpenter Link: https://lore.kernel.org/r/202304021446.46XVKag0-lkp@intel.com/ Signed-off-by: Krzysztof Kozlowski Reviewed-by: Vincent Whitchurch Reviewed-by: Alim Akhtar Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230403094017.9556-1-krzysztof.kozlowski@linaro.org --- drivers/clocksource/exynos_mct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index bfd60093ee1c..ef8cb1b71be4 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -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(); } -- cgit v1.2.3 From 49d576ea72a4fa5be15717babfa308b70b2bc5a4 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 9 Mar 2023 11:39:13 +0100 Subject: clocksource/drivers/timer-mediatek: Split out CPUXGPT timers On MediaTek platforms, CPUXGPT is the source for the AArch64 System Timer, read through CNTVCT_EL0. The handling for starting this timer ASAP was introduced in commit 327e93cf9a59 ("clocksource/drivers/timer-mediatek: Implement CPUXGPT timers") which description also contains an important full explanation of the reasons why this driver is necessary and cannot be a module. In preparation for an eventual conversion of timer-mediatek to a platform_driver that would be possibly built as a module, split out the CPUXGPT timers driver to a new timer-mediatek-cpux.c driver. This commit brings no functional changes. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Walter Chang Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230309103913.116775-1-angelogioacchino.delregno@collabora.com --- drivers/clocksource/Kconfig | 9 ++ drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-mediatek-cpux.c | 140 ++++++++++++++++++++++++++++++ drivers/clocksource/timer-mediatek.c | 114 ------------------------ 4 files changed, 150 insertions(+), 114 deletions(-) create mode 100644 drivers/clocksource/timer-mediatek-cpux.c (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 5fc8f0e7fb38..526382dc7482 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -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 diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 64ab547de97b..f12d3987a960 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -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 diff --git a/drivers/clocksource/timer-mediatek-cpux.c b/drivers/clocksource/timer-mediatek-cpux.c new file mode 100644 index 000000000000..a8e3df4c09fd --- /dev/null +++ b/drivers/clocksource/timer-mediatek-cpux.c @@ -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 + * + * Copyright (C) 2022 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#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); diff --git a/drivers/clocksource/timer-mediatek.c b/drivers/clocksource/timer-mediatek.c index d5b29fd03ca2..7bcb4a3f26fb 100644 --- a/drivers/clocksource/timer-mediatek.c +++ b/drivers/clocksource/timer-mediatek.c @@ -22,19 +22,6 @@ #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 - /* gpt */ #define GPT_IRQ_EN_REG 0x00 #define GPT_IRQ_ENABLE(val) BIT((val) - 1) @@ -85,52 +72,6 @@ static void __iomem *gpt_sched_reg __read_mostly; -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 void mtk_syst_ack_irq(struct timer_of *to) { /* Clear and disable interrupt */ @@ -340,60 +281,6 @@ static struct timer_of to = { }, }; -static int __init mtk_cpux_init(struct device_node *node) -{ - static struct timer_of to_cpux; - u32 freq, val; - int ret; - - /* - * 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. - */ - to_cpux.flags = TIMER_OF_BASE | TIMER_OF_CLOCK; - to_cpux.clkevt.name = "mtk-cpuxgpt"; - to_cpux.clkevt.rating = 10; - to_cpux.clkevt.cpumask = cpu_possible_mask; - to_cpux.clkevt.set_state_shutdown = mtk_cpux_clkevt_shutdown; - to_cpux.clkevt.tick_resume = mtk_cpux_clkevt_resume; - - /* If this fails, bad things are about to happen... */ - ret = timer_of_init(node, &to_cpux); - 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_cpux); - 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_cpux); - val &= ~CPUX_CLK_DIV_MASK; - val |= CPUX_CLK_DIV2; - mtk_cpux_writel(val, CPUX_IDX_GLOBAL_CTRL, &to_cpux); - - /* Enable all CPUXGPT timers */ - val = mtk_cpux_readl(CPUX_IDX_GLOBAL_CTRL, &to_cpux); - mtk_cpux_writel(val | CPUX_ENABLE, CPUX_IDX_GLOBAL_CTRL, &to_cpux); - - clockevents_config_and_register(&to_cpux.clkevt, timer_of_rate(&to_cpux), - TIMER_SYNC_TICKS, 0xffffffff); - - return 0; -} - static int __init mtk_syst_init(struct device_node *node) { int ret; @@ -452,4 +339,3 @@ static int __init mtk_gpt_init(struct device_node *node) } TIMER_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_gpt_init); TIMER_OF_DECLARE(mtk_mt6765, "mediatek,mt6765-timer", mtk_syst_init); -TIMER_OF_DECLARE(mtk_mt6795, "mediatek,mt6795-systimer", mtk_cpux_init); -- cgit v1.2.3 From f68a40ee4732731f149961abab27a45b6c11f413 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 7 Mar 2023 09:43:13 -0300 Subject: clocksource/drivers/timer-imx-gpt: Remove non-DT function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mxc_timer_init() was originally only used by non-DT i.MX platforms. i.MX has already been converted to be a DT-only platform. Remove the unused mxc_timer_init() function. Signed-off-by: Fabio Estevam Acked-by: Uwe Kleine-König Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230307124313.708255-1-festevam@denx.de --- drivers/clocksource/timer-imx-gpt.c | 19 ------------------- include/soc/imx/timer.h | 7 ------- 2 files changed, 26 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c index 7b2c70f2f353..ca3e4cbc80c6 100644 --- a/drivers/clocksource/timer-imx-gpt.c +++ b/drivers/clocksource/timer-imx-gpt.c @@ -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; diff --git a/include/soc/imx/timer.h b/include/soc/imx/timer.h index b888d5076b4d..25f29c6bbd0b 100644 --- a/include/soc/imx/timer.h +++ b/include/soc/imx/timer.h @@ -13,11 +13,4 @@ enum imx_gpt_type { GPT_TYPE_IMX6DL, /* i.MX6DL/SX/SL */ }; -/* - * This is a stop-gap solution for clock drivers like imx1/imx21 which call - * mxc_timer_init() to initialize timer for non-DT boot. It can be removed - * when these legacy non-DT support is converted or dropped. - */ -void mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type); - #endif /* __SOC_IMX_TIMER_H__ */ -- cgit v1.2.3 From 0fabf9f3a0c1ca44e01c5c4dccacfe69143413c5 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sun, 19 Mar 2023 11:32:20 -0500 Subject: clocksource/drivers/timer-ti-dm: Use of_address_to_resource() Replace of_get_address() and of_translate_address() calls with single call to of_address_to_resource(). Signed-off-by: Rob Herring Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230319163220.226273-1-robh@kernel.org --- drivers/clocksource/timer-ti-dm-systimer.c | 57 ++++++++++++++---------------- 1 file changed, 27 insertions(+), 30 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c index 632523c1232f..3b98a3c04f87 100644 --- a/drivers/clocksource/timer-ti-dm-systimer.c +++ b/drivers/clocksource/timer-ti-dm-systimer.c @@ -251,24 +251,22 @@ static void __init dmtimer_systimer_assign_alwon(void) counter_32k = -ENODEV; for_each_matching_node(np, dmtimer_match_table) { + struct resource res; if (!dmtimer_is_preferred(np)) continue; - if (of_property_read_bool(np, "ti,timer-alwon")) { - const __be32 *addr; - - addr = of_get_address(np, 0, NULL, NULL); - pa = of_translate_address(np, addr); - if (pa) { - /* Quirky omap3 boards must use dmtimer12 */ - if (quirk_unreliable_oscillator && - pa == 0x48318000) - continue; - - of_node_put(np); - break; - } - } + if (!of_property_read_bool(np, "ti,timer-alwon")) + continue; + + if (of_address_to_resource(np, 0, &res)) + continue; + + /* Quirky omap3 boards must use dmtimer12 */ + if (quirk_unreliable_oscillator && res.start == 0x48318000) + continue; + + of_node_put(np); + break; } /* Usually no need for dmtimer clocksource if we have counter32 */ @@ -285,24 +283,22 @@ static void __init dmtimer_systimer_assign_alwon(void) static u32 __init dmtimer_systimer_find_first_available(void) { struct device_node *np; - const __be32 *addr; u32 pa = 0; for_each_matching_node(np, dmtimer_match_table) { + struct resource res; if (!dmtimer_is_preferred(np)) continue; - addr = of_get_address(np, 0, NULL, NULL); - pa = of_translate_address(np, addr); - if (pa) { - if (pa == clocksource || pa == clockevent) { - pa = 0; - continue; - } - - of_node_put(np); - break; - } + if (of_address_to_resource(np, 0, &res)) + continue; + + if (res.start == clocksource || res.start == clockevent) + continue; + + pa = res.start; + of_node_put(np); + break; } return pa; @@ -812,7 +808,7 @@ err_out_free: */ static int __init dmtimer_systimer_init(struct device_node *np) { - const __be32 *addr; + struct resource res; u32 pa; /* One time init for the preferred timer configuration */ @@ -826,8 +822,9 @@ static int __init dmtimer_systimer_init(struct device_node *np) return -EINVAL; } - addr = of_get_address(np, 0, NULL, NULL); - pa = of_translate_address(np, addr); + + of_address_to_resource(np, 0, &res); + pa = (u32)res.start; if (!pa) return -EINVAL; -- cgit v1.2.3 From 78012e3880a62e0eb130a0b5a10230162ad42a06 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 13 Mar 2023 08:54:26 +0100 Subject: clocksource/drivers/sh_mtu2: Mark driver as non-removable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The comment in the remove callback suggests that the driver is not supposed to be unbound. However returning an error code in the remove callback doesn't accomplish that. Instead set the suppress_bind_attrs property (which makes it impossible to unbind the driver via sysfs). The only remaining way to unbind a sh_tmu2 device would be module unloading, but that doesn't apply here, as the driver cannot be built as a module. Also drop the useless remove callback. Signed-off-by: Uwe Kleine-König Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230313075430.2730803-2-u.kleine-koenig@pengutronix.de --- drivers/clocksource/sh_mtu2.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 169a1fccc497..6bd2d0299397 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -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 }, { }, @@ -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, }; -- cgit v1.2.3 From ede38f924a9e3c60382a13576347dc41967e8762 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 13 Mar 2023 08:54:27 +0100 Subject: clocksource/drivers/timer-stm32-lp: Mark driver as non-removable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The comment in the remove callback suggests that the driver is not supposed to be unbound. However returning an error code in the remove callback doesn't accomplish that. Instead set the suppress_bind_attrs property (which makes it impossible to unbind the driver via sysfs). The only remaining way to unbind an stm32-lp device would be module unloading, but that doesn't apply here, as the driver cannot be built as a module. Also drop the useless remove callback. [dlezcano] : Fixed up the wrong function removed Signed-off-by: Uwe Kleine-König Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230313075430.2730803-3-u.kleine-koenig@pengutronix.de --- drivers/clocksource/timer-stm32-lp.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c index db2841d0beb8..0adf22d30ba1 100644 --- a/drivers/clocksource/timer-stm32-lp.c +++ b/drivers/clocksource/timer-stm32-lp.c @@ -195,11 +195,6 @@ out_clk_disable: return ret; } -static int stm32_clkevent_lp_remove(struct platform_device *pdev) -{ - return -EBUSY; /* cannot unregister clockevent */ -} - static const struct of_device_id stm32_clkevent_lp_of_match[] = { { .compatible = "st,stm32-lptimer-timer", }, {}, @@ -207,11 +202,11 @@ static const struct of_device_id stm32_clkevent_lp_of_match[] = { MODULE_DEVICE_TABLE(of, stm32_clkevent_lp_of_match); static struct platform_driver stm32_clkevent_lp_driver = { - .probe = stm32_clkevent_lp_probe, - .remove = stm32_clkevent_lp_remove, + .probe = stm32_clkevent_lp_probe, .driver = { .name = "stm32-lptimer-timer", .of_match_table = of_match_ptr(stm32_clkevent_lp_of_match), + .suppress_bind_attrs = true, }, }; module_platform_driver(stm32_clkevent_lp_driver); -- cgit v1.2.3 From 8efcbe927c5129d5b2528bbb40034c7dde87a6b6 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 13 Mar 2023 08:54:28 +0100 Subject: clocksource/drivers/timer-ti-dm: Improve error message in .remove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a platform driver's remove callback returns an error code, the driver core emits a generic (and thus little helpful) error message. Instead emit a more specifc error message about the actual error and return zero to suppress the core's message. Note that returning zero has no side effects apart from not emitting said error message. This prepares converting platform driver's remove message to return void. Signed-off-by: Uwe Kleine-König Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230313075430.2730803-4-u.kleine-koenig@pengutronix.de --- drivers/clocksource/timer-ti-dm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index b24b903a8822..098562bda487 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -1197,7 +1197,10 @@ static int omap_dm_timer_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); - return ret; + if (ret) + dev_err(&pdev->dev, "Unable to determine timer entry in list of drivers on remove\n"); + + return 0; } static const struct omap_dm_timer_ops dmtimer_ops = { -- cgit v1.2.3 From d7b76421c03fa58d16a52eb839302f582602997a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 13 Mar 2023 08:54:29 +0100 Subject: clocksource/drivers/timer-tegra186: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230313075430.2730803-5-u.kleine-koenig@pengutronix.de --- drivers/clocksource/timer-tegra186.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-tegra186.c b/drivers/clocksource/timer-tegra186.c index ea742889ee06..ccc762d32422 100644 --- a/drivers/clocksource/timer-tegra186.c +++ b/drivers/clocksource/timer-tegra186.c @@ -447,15 +447,13 @@ unregister_tsc: return err; } -static int tegra186_timer_remove(struct platform_device *pdev) +static void tegra186_timer_remove(struct platform_device *pdev) { struct tegra186_timer *tegra = platform_get_drvdata(pdev); clocksource_unregister(&tegra->usec); clocksource_unregister(&tegra->osc); clocksource_unregister(&tegra->tsc); - - return 0; } static int __maybe_unused tegra186_timer_suspend(struct device *dev) @@ -505,7 +503,7 @@ static struct platform_driver tegra186_wdt_driver = { .of_match_table = tegra186_timer_of_match, }, .probe = tegra186_timer_probe, - .remove = tegra186_timer_remove, + .remove_new = tegra186_timer_remove, }; module_platform_driver(tegra186_wdt_driver); -- cgit v1.2.3 From b1f0390048e2641d3451f8cdbbef24c79d1a8fdd Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 13 Mar 2023 08:54:30 +0100 Subject: clocksource/drivers/timer-ti-dm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230313075430.2730803-6-u.kleine-koenig@pengutronix.de --- drivers/clocksource/timer-ti-dm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index 098562bda487..ab7a6caa36c5 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -1177,7 +1177,7 @@ err_disable: * In addition to freeing platform resources it also deletes the timer * entry from the local list. */ -static int omap_dm_timer_remove(struct platform_device *pdev) +static void omap_dm_timer_remove(struct platform_device *pdev) { struct dmtimer *timer; unsigned long flags; @@ -1199,8 +1199,6 @@ static int omap_dm_timer_remove(struct platform_device *pdev) if (ret) dev_err(&pdev->dev, "Unable to determine timer entry in list of drivers on remove\n"); - - return 0; } static const struct omap_dm_timer_ops dmtimer_ops = { @@ -1275,7 +1273,7 @@ MODULE_DEVICE_TABLE(of, omap_timer_match); static struct platform_driver omap_dm_timer_driver = { .probe = omap_dm_timer_probe, - .remove = omap_dm_timer_remove, + .remove_new = omap_dm_timer_remove, .driver = { .name = "omap_timer", .of_match_table = omap_timer_match, -- cgit v1.2.3 From b6f228e800ccf285906bb1c4c366ce3848a5443e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 18:38:03 +0100 Subject: clocksource/drivers/stm32-lp: Drop of_match_ptr for ID table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it might not be relevant here). drivers/clocksource/timer-stm32-lp.c:203:34: error: ‘stm32_clkevent_lp_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230311173803.263446-1-krzysztof.kozlowski@linaro.org --- drivers/clocksource/timer-stm32-lp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c index 0adf22d30ba1..d14a17549fe8 100644 --- a/drivers/clocksource/timer-stm32-lp.c +++ b/drivers/clocksource/timer-stm32-lp.c @@ -205,7 +205,7 @@ static struct platform_driver stm32_clkevent_lp_driver = { .probe = stm32_clkevent_lp_probe, .driver = { .name = "stm32-lptimer-timer", - .of_match_table = of_match_ptr(stm32_clkevent_lp_of_match), + .of_match_table = stm32_clkevent_lp_of_match, .suppress_bind_attrs = true, }, }; -- cgit v1.2.3 From fb73556386e074e9bee9fa2d253aeaefe4e063e0 Mon Sep 17 00:00:00 2001 From: Qinrun Dai Date: Thu, 13 Apr 2023 13:50:37 +0000 Subject: clocksource/drivers/davinci: Fix memory leak in davinci_timer_register when init fails Smatch reports: drivers/clocksource/timer-davinci.c:332 davinci_timer_register() warn: 'base' from ioremap() not released on lines: 274. Fix this and other potential memory leak problems by adding a set of corresponding exit lables. Fixes: 721154f972aa ("clocksource/drivers/davinci: Add support for clockevents") Signed-off-by: Qinrun Dai Link: https://lore.kernel.org/r/20230413135037.1505799-1-flno@hust.edu.cn Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-davinci.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-davinci.c b/drivers/clocksource/timer-davinci.c index 9996c0542520..b1c248498be4 100644 --- a/drivers/clocksource/timer-davinci.c +++ b/drivers/clocksource/timer-davinci.c @@ -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; @@ -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; @@ -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) -- cgit v1.2.3 From 8d7aac5153f21108365137b76e395dcf9bb3a800 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 12 Apr 2023 09:41:41 +0300 Subject: clocksource/drivers/timer-ti-dm: Fix finding alwon timer Clean-up commit b6999fa1c847 ("clocksource/drivers/timer-ti-dm: Use of_address_to_resource()") caused a regression where pa is never set making all related SoCs fail to boot. Let's fix this by setting pa if found. Fixes: b6999fa1c847 ("clocksource/drivers/timer-ti-dm: Use of_address_to_resource()") Cc: Rob Herring Signed-off-by: Tony Lindgren Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230412064142.12726-1-tony@atomide.com --- drivers/clocksource/timer-ti-dm-systimer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c index 3b98a3c04f87..4fa68f657056 100644 --- a/drivers/clocksource/timer-ti-dm-systimer.c +++ b/drivers/clocksource/timer-ti-dm-systimer.c @@ -261,8 +261,10 @@ static void __init dmtimer_systimer_assign_alwon(void) if (of_address_to_resource(np, 0, &res)) continue; + pa = res.start; + /* Quirky omap3 boards must use dmtimer12 */ - if (quirk_unreliable_oscillator && res.start == 0x48318000) + if (quirk_unreliable_oscillator && pa == 0x48318000) continue; of_node_put(np); -- cgit v1.2.3 From 87dd04f9b1a37a92ebbea5eb46e4941551d3547e Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:01 -0600 Subject: clocksource/drivers/ti: Use of_property_read_bool() for boolean properties It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. Convert reading boolean properties to to of_property_read_bool(). Signed-off-by: Rob Herring Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230310144702.1541660-1-robh@kernel.org --- drivers/clocksource/timer-ti-dm-systimer.c | 4 ++-- drivers/clocksource/timer-ti-dm.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c index 4fa68f657056..c2dcd8d68e45 100644 --- a/drivers/clocksource/timer-ti-dm-systimer.c +++ b/drivers/clocksource/timer-ti-dm-systimer.c @@ -584,7 +584,7 @@ static int __init dmtimer_clkevt_init_common(struct dmtimer_clockevent *clkevt, writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup); pr_info("TI gptimer %s: %s%lu Hz at %pOF\n", - name, of_find_property(np, "ti,timer-alwon", NULL) ? + name, of_property_read_bool(np, "ti,timer-alwon") ? "always-on " : "", t->rate, np->parent); return 0; @@ -785,7 +785,7 @@ static int __init dmtimer_clocksource_init(struct device_node *np) t->base + t->ctrl); pr_info("TI gptimer clocksource: %s%pOF\n", - of_find_property(np, "ti,timer-alwon", NULL) ? + of_property_read_bool(np, "ti,timer-alwon") ? "always-on " : "", np->parent); if (!dmtimer_sched_clock_counter) { diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index ab7a6caa36c5..1d3ad51e4634 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -1104,13 +1104,13 @@ static int omap_dm_timer_probe(struct platform_device *pdev) platform_set_drvdata(pdev, timer); if (dev->of_node) { - if (of_find_property(dev->of_node, "ti,timer-alwon", NULL)) + if (of_property_read_bool(dev->of_node, "ti,timer-alwon")) timer->capability |= OMAP_TIMER_ALWON; - if (of_find_property(dev->of_node, "ti,timer-dsp", NULL)) + if (of_property_read_bool(dev->of_node, "ti,timer-dsp")) timer->capability |= OMAP_TIMER_HAS_DSP_IRQ; - if (of_find_property(dev->of_node, "ti,timer-pwm", NULL)) + if (of_property_read_bool(dev->of_node, "ti,timer-pwm")) timer->capability |= OMAP_TIMER_HAS_PWM; - if (of_find_property(dev->of_node, "ti,timer-secure", NULL)) + if (of_property_read_bool(dev->of_node, "ti,timer-secure")) timer->capability |= OMAP_TIMER_SECURE; } else { timer->id = pdev->id; -- cgit v1.2.3