diff options
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/Kconfig | 9 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 1 | ||||
-rw-r--r-- | drivers/clocksource/em_sti.c | 1 | ||||
-rw-r--r-- | drivers/clocksource/exynos_mct.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/hyperv_timer.c | 21 | ||||
-rw-r--r-- | drivers/clocksource/ingenic-timer.c | 3 | ||||
-rw-r--r-- | drivers/clocksource/sh_cmt.c | 1 | ||||
-rw-r--r-- | drivers/clocksource/sh_mtu2.c | 8 | ||||
-rw-r--r-- | drivers/clocksource/sh_tmu.c | 1 | ||||
-rw-r--r-- | drivers/clocksource/timer-clint.c | 65 | ||||
-rw-r--r-- | drivers/clocksource/timer-davinci.c | 30 | ||||
-rw-r--r-- | drivers/clocksource/timer-imx-gpt.c | 19 | ||||
-rw-r--r-- | drivers/clocksource/timer-mediatek-cpux.c | 140 | ||||
-rw-r--r-- | drivers/clocksource/timer-mediatek.c | 114 | ||||
-rw-r--r-- | drivers/clocksource/timer-stm32-lp.c | 12 | ||||
-rw-r--r-- | drivers/clocksource/timer-tegra186.c | 7 | ||||
-rw-r--r-- | drivers/clocksource/timer-ti-dm-systimer.c | 63 | ||||
-rw-r--r-- | drivers/clocksource/timer-ti-dm.c | 16 |
18 files changed, 286 insertions, 227 deletions
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/em_sti.c b/drivers/clocksource/em_sti.c index c04b47bd4868..ca8d29ab70da 100644 --- a/drivers/clocksource/em_sti.c +++ b/drivers/clocksource/em_sti.c @@ -363,4 +363,3 @@ module_exit(em_sti_exit); MODULE_AUTHOR("Magnus Damm"); MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver"); -MODULE_LICENSE("GPL v2"); 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(); } diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index c0cef92b12b8..bcd9042a0c9f 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -49,7 +49,7 @@ static bool direct_mode_enabled; static int stimer0_irq = -1; static int stimer0_message_sint; -static DEFINE_PER_CPU(long, stimer0_evt); +static __maybe_unused DEFINE_PER_CPU(long, stimer0_evt); /* * Common code for stimer0 interrupts coming via Direct Mode or @@ -68,7 +68,7 @@ EXPORT_SYMBOL_GPL(hv_stimer0_isr); * stimer0 interrupt handler for architectures that support * per-cpu interrupts, which also implies Direct Mode. */ -static irqreturn_t hv_stimer0_percpu_isr(int irq, void *dev_id) +static irqreturn_t __maybe_unused hv_stimer0_percpu_isr(int irq, void *dev_id) { hv_stimer0_isr(); return IRQ_HANDLED; @@ -196,6 +196,7 @@ void __weak hv_remove_stimer0_handler(void) { }; +#ifdef CONFIG_ACPI /* Called only on architectures with per-cpu IRQs (i.e., not x86/x64) */ static int hv_setup_stimer0_irq(void) { @@ -230,6 +231,16 @@ static void hv_remove_stimer0_irq(void) stimer0_irq = -1; } } +#else +static int hv_setup_stimer0_irq(void) +{ + return 0; +} + +static void hv_remove_stimer0_irq(void) +{ +} +#endif /* hv_stimer_alloc - Global initialization of the clockevent and stimer0 */ int hv_stimer_alloc(bool have_percpu_irqs) @@ -506,9 +517,6 @@ static bool __init hv_init_tsc_clocksource(void) { union hv_reference_tsc_msr tsc_msr; - if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) - return false; - /* * If Hyper-V offers TSC_INVARIANT, then the virtualized TSC correctly * handles frequency and offset changes due to live migration, @@ -525,6 +533,9 @@ static bool __init hv_init_tsc_clocksource(void) hyperv_cs_msr.rating = 250; } + if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) + return false; + hv_read_reference_counter = read_hv_clock_tsc; /* diff --git a/drivers/clocksource/ingenic-timer.c b/drivers/clocksource/ingenic-timer.c index 24ed0f1f089b..089ce64b1c3f 100644 --- a/drivers/clocksource/ingenic-timer.c +++ b/drivers/clocksource/ingenic-timer.c @@ -9,13 +9,12 @@ #include <linux/clk.h> #include <linux/clockchips.h> #include <linux/clocksource.h> +#include <linux/cpuhotplug.h> #include <linux/interrupt.h> #include <linux/mfd/ingenic-tcu.h> #include <linux/mfd/syscon.h> #include <linux/of.h> -#include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> #include <linux/overflow.h> #include <linux/platform_device.h> #include <linux/regmap.h> diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 8b2e079d9df2..e81c588d9afe 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -1174,4 +1174,3 @@ module_exit(sh_cmt_exit); MODULE_AUTHOR("Magnus Damm"); MODULE_DESCRIPTION("SuperH CMT Timer Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 169a1fccc497..34872df5458a 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, }; @@ -530,4 +525,3 @@ module_exit(sh_mtu2_exit); MODULE_AUTHOR("Magnus Damm"); MODULE_DESCRIPTION("SuperH MTU2 Timer Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 932f31a7c5be..beffff81c00f 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -674,4 +674,3 @@ module_exit(sh_tmu_exit); MODULE_AUTHOR("Magnus Damm"); MODULE_DESCRIPTION("SuperH TMU Timer Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/clocksource/timer-clint.c b/drivers/clocksource/timer-clint.c index 6cfe2ab73eb0..9a55e733ae99 100644 --- a/drivers/clocksource/timer-clint.c +++ b/drivers/clocksource/timer-clint.c @@ -17,6 +17,9 @@ #include <linux/sched_clock.h> #include <linux/io-64-nonatomic-lo-hi.h> #include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/irqdomain.h> #include <linux/of_irq.h> #include <linux/smp.h> #include <linux/timex.h> @@ -31,6 +34,7 @@ /* CLINT manages IPI and Timer for RISC-V M-mode */ static u32 __iomem *clint_ipi_base; +static unsigned int clint_ipi_irq; static u64 __iomem *clint_timer_cmp; static u64 __iomem *clint_timer_val; static unsigned long clint_timer_freq; @@ -41,12 +45,10 @@ u64 __iomem *clint_time_val; EXPORT_SYMBOL(clint_time_val); #endif -static void clint_send_ipi(const struct cpumask *target) +#ifdef CONFIG_SMP +static void clint_send_ipi(unsigned int cpu) { - unsigned int cpu; - - for_each_cpu(cpu, target) - writel(1, clint_ipi_base + cpuid_to_hartid_map(cpu)); + writel(1, clint_ipi_base + cpuid_to_hartid_map(cpu)); } static void clint_clear_ipi(void) @@ -54,10 +56,18 @@ static void clint_clear_ipi(void) writel(0, clint_ipi_base + cpuid_to_hartid_map(smp_processor_id())); } -static struct riscv_ipi_ops clint_ipi_ops = { - .ipi_inject = clint_send_ipi, - .ipi_clear = clint_clear_ipi, -}; +static void clint_ipi_interrupt(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + + chained_irq_enter(chip, desc); + + clint_clear_ipi(); + ipi_mux_process(); + + chained_irq_exit(chip, desc); +} +#endif #ifdef CONFIG_64BIT #define clint_get_cycles() readq_relaxed(clint_timer_val) @@ -125,12 +135,19 @@ static int clint_timer_starting_cpu(unsigned int cpu) enable_percpu_irq(clint_timer_irq, irq_get_trigger_type(clint_timer_irq)); + enable_percpu_irq(clint_ipi_irq, + irq_get_trigger_type(clint_ipi_irq)); return 0; } static int clint_timer_dying_cpu(unsigned int cpu) { disable_percpu_irq(clint_timer_irq); + /* + * Don't disable IPI when CPU goes offline because + * the masking/unmasking of virtual IPIs is done + * via generic IPI-Mux + */ return 0; } @@ -170,6 +187,12 @@ static int __init clint_timer_init_dt(struct device_node *np) return -ENODEV; } + /* Find parent irq domain and map ipi irq */ + if (!clint_ipi_irq && + oirq.args[0] == RV_IRQ_SOFT && + irq_find_host(oirq.np)) + clint_ipi_irq = irq_of_parse_and_map(np, i); + /* Find parent irq domain and map timer irq */ if (!clint_timer_irq && oirq.args[0] == RV_IRQ_TIMER && @@ -177,9 +200,9 @@ static int __init clint_timer_init_dt(struct device_node *np) clint_timer_irq = irq_of_parse_and_map(np, i); } - /* If CLINT timer irq not found then fail */ - if (!clint_timer_irq) { - pr_err("%pOFP: timer irq not found\n", np); + /* If CLINT ipi or timer irq not found then fail */ + if (!clint_ipi_irq || !clint_timer_irq) { + pr_err("%pOFP: ipi/timer irq not found\n", np); return -ENODEV; } @@ -219,6 +242,19 @@ static int __init clint_timer_init_dt(struct device_node *np) goto fail_iounmap; } +#ifdef CONFIG_SMP + rc = ipi_mux_create(BITS_PER_BYTE, clint_send_ipi); + if (rc <= 0) { + pr_err("unable to create muxed IPIs\n"); + rc = (rc < 0) ? rc : -ENODEV; + goto fail_free_irq; + } + + irq_set_chained_handler(clint_ipi_irq, clint_ipi_interrupt); + riscv_ipi_set_virq_range(rc, BITS_PER_BYTE, true); + clint_clear_ipi(); +#endif + rc = cpuhp_setup_state(CPUHP_AP_CLINT_TIMER_STARTING, "clockevents/clint/timer:starting", clint_timer_starting_cpu, @@ -228,13 +264,10 @@ static int __init clint_timer_init_dt(struct device_node *np) goto fail_free_irq; } - riscv_set_ipi_ops(&clint_ipi_ops); - clint_clear_ipi(); - return 0; fail_free_irq: - free_irq(clint_timer_irq, &clint_clock_event); + free_percpu_irq(clint_timer_irq, &clint_clock_event); fail_iounmap: iounmap(base); return rc; 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) 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/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 <matthias.bgg@gmail.com> + * + * Copyright (C) 2022 Collabora Ltd. + * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> + */ + +#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); 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); diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c index db2841d0beb8..a4c95161cb22 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,15 +202,14 @@ 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), + .of_match_table = stm32_clkevent_lp_of_match, + .suppress_bind_attrs = true, }, }; module_platform_driver(stm32_clkevent_lp_driver); MODULE_ALIAS("platform:stm32-lptimer-timer"); MODULE_DESCRIPTION("STMicroelectronics STM32 clockevent low power driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/clocksource/timer-tegra186.c b/drivers/clocksource/timer-tegra186.c index ea742889ee06..83d08591ea0a 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,10 +503,9 @@ 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); MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); MODULE_DESCRIPTION("NVIDIA Tegra186 timers driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c index 632523c1232f..c2dcd8d68e45 100644 --- a/drivers/clocksource/timer-ti-dm-systimer.c +++ b/drivers/clocksource/timer-ti-dm-systimer.c @@ -251,24 +251,24 @@ 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; + + pa = res.start; + + /* Quirky omap3 boards must use dmtimer12 */ + if (quirk_unreliable_oscillator && pa == 0x48318000) + continue; + + of_node_put(np); + break; } /* Usually no need for dmtimer clocksource if we have counter32 */ @@ -285,24 +285,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; @@ -586,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; @@ -787,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) { @@ -812,7 +810,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 +824,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; diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index b24b903a8822..349236a7ba5f 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; @@ -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; @@ -1197,7 +1197,8 @@ 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"); } static const struct omap_dm_timer_ops dmtimer_ops = { @@ -1272,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, @@ -1283,5 +1284,4 @@ static struct platform_driver omap_dm_timer_driver = { module_platform_driver(omap_dm_timer_driver); MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver"); -MODULE_LICENSE("GPL"); MODULE_AUTHOR("Texas Instruments Inc"); |