From eaa1a955094b20ca4b1c5064200d140b27f8d96f Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 7 Sep 2022 09:00:56 +0100 Subject: clocksource/drivers/renesas-ostm: Add support for RZ/V2L SoC The OSTM block is identical on Renesas RZ/G2L and RZ/V2L SoC's, so instead of adding dependency for each SoC's add dependency on ARCH_RZG2L. The ARCH_RZG2L config option is already selected by ARCH_R9A07G044 and ARCH_R9A07G054. With the above change OSTM will be enabled on RZ/V2L SoC. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20220907080056.3460-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/renesas-ostm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/renesas-ostm.c b/drivers/clocksource/renesas-ostm.c index 21d1392637b8..8da972dc1713 100644 --- a/drivers/clocksource/renesas-ostm.c +++ b/drivers/clocksource/renesas-ostm.c @@ -224,7 +224,7 @@ err_free: TIMER_OF_DECLARE(ostm, "renesas,ostm", ostm_init); -#ifdef CONFIG_ARCH_R9A07G044 +#ifdef CONFIG_ARCH_RZG2L static int __init ostm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; -- cgit v1.2.3 From 4364044c326cbf2ad09e9fa99a9a28a342fecce6 Mon Sep 17 00:00:00 2001 From: Victor Hassan Date: Tue, 6 Sep 2022 13:20:56 +0800 Subject: clocksource/drivers/sun4i: Add definition of clear interrupt To prevent misunderstanding, use TIMER_IRQ_CLEAR instead of TIMER_IRQ_EN in function sun4i_timer_clear_interrupt. Signed-off-by: Victor Hassan Acked-by: Jernej Skrabec Link: https://lore.kernel.org/r/20220906052056.43404-1-victor@allwinnertech.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-sun4i.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-sun4i.c b/drivers/clocksource/timer-sun4i.c index 94dc6e42e983..e5a70aa1deb4 100644 --- a/drivers/clocksource/timer-sun4i.c +++ b/drivers/clocksource/timer-sun4i.c @@ -26,6 +26,7 @@ #define TIMER_IRQ_EN_REG 0x00 #define TIMER_IRQ_EN(val) BIT(val) #define TIMER_IRQ_ST_REG 0x04 +#define TIMER_IRQ_CLEAR(val) BIT(val) #define TIMER_CTL_REG(val) (0x10 * val + 0x10) #define TIMER_CTL_ENABLE BIT(0) #define TIMER_CTL_RELOAD BIT(1) @@ -123,7 +124,7 @@ static int sun4i_clkevt_next_event(unsigned long evt, static void sun4i_timer_clear_interrupt(void __iomem *base) { - writel(TIMER_IRQ_EN(0), base + TIMER_IRQ_ST_REG); + writel(TIMER_IRQ_CLEAR(0), base + TIMER_IRQ_ST_REG); } static irqreturn_t sun4i_timer_interrupt(int irq, void *dev_id) -- cgit v1.2.3 From e8550f0e7bde9bd31697e3c534d386f7f3b5787b Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Thu, 9 Jun 2022 13:27:36 +0200 Subject: clocksource/drivers/exynos_mct: Support frc-shared property When the FRC is shared with another main processor, the other processor is assumed to have started it and this processor should not write to the global registers. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Vincent Whitchurch Link: https://lore.kernel.org/r/20220609112738.359385-3-vincent.whitchurch@axis.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/exynos_mct.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index f29c812b70c9..12023831dedf 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -233,9 +233,16 @@ static cycles_t exynos4_read_current_timer(void) } #endif -static int __init exynos4_clocksource_init(void) +static int __init exynos4_clocksource_init(bool frc_shared) { - exynos4_mct_frc_start(); + /* + * When the frc is shared, the main processer should have already + * turned it on and we shouldn't be writing to TCON. + */ + if (frc_shared) + mct_frc.resume = NULL; + else + exynos4_mct_frc_start(); #if defined(CONFIG_ARM) exynos4_delay_timer.read_current_timer = &exynos4_read_current_timer; @@ -605,6 +612,7 @@ out_irq: static int __init mct_init_dt(struct device_node *np, unsigned int int_type) { + bool frc_shared = of_property_read_bool(np, "samsung,frc-shared"); int ret; ret = exynos4_timer_resources(np); @@ -615,10 +623,17 @@ static int __init mct_init_dt(struct device_node *np, unsigned int int_type) if (ret) return ret; - ret = exynos4_clocksource_init(); + ret = exynos4_clocksource_init(frc_shared); if (ret) return ret; + /* + * When the FRC is shared with a main processor, this secondary + * processor cannot use the global comparator. + */ + if (frc_shared) + return ret; + return exynos4_clockevent_init(); } -- cgit v1.2.3 From 47dbe4eb9822208be2b7ec901c7e0c15536f9c92 Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Thu, 9 Jun 2022 13:27:37 +0200 Subject: clocksource/drivers/exynos_mct: Support local-timers property If the device tree indicates that the hardware requires that the processor only use certain local timers, respect that. Signed-off-by: Vincent Whitchurch Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220609112738.359385-4-vincent.whitchurch@axis.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/exynos_mct.c | 62 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 6 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 12023831dedf..bfd60093ee1c 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -33,7 +33,7 @@ #define EXYNOS4_MCT_G_INT_ENB EXYNOS4_MCTREG(0x248) #define EXYNOS4_MCT_G_WSTAT EXYNOS4_MCTREG(0x24C) #define _EXYNOS4_MCT_L_BASE EXYNOS4_MCTREG(0x300) -#define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * x)) +#define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * (x))) #define EXYNOS4_MCT_L_MASK (0xffffff00) #define MCT_L_TCNTB_OFFSET (0x00) @@ -66,6 +66,8 @@ #define MCT_L0_IRQ 4 /* Max number of IRQ as per DT binding document */ #define MCT_NR_IRQS 20 +/* Max number of local timers */ +#define MCT_NR_LOCAL (MCT_NR_IRQS - MCT_L0_IRQ) enum { MCT_INT_SPI, @@ -456,7 +458,6 @@ static int exynos4_mct_starting_cpu(unsigned int cpu) per_cpu_ptr(&percpu_mct_tick, cpu); struct clock_event_device *evt = &mevt->evt; - mevt->base = EXYNOS4_MCT_L_BASE(cpu); snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d", cpu); evt->name = mevt->name; @@ -527,8 +528,17 @@ static int __init exynos4_timer_resources(struct device_node *np) return 0; } +/** + * exynos4_timer_interrupts - initialize MCT interrupts + * @np: device node for MCT + * @int_type: interrupt type, MCT_INT_PPI or MCT_INT_SPI + * @local_idx: array mapping CPU numbers to local timer indices + * @nr_local: size of @local_idx array + */ static int __init exynos4_timer_interrupts(struct device_node *np, - unsigned int int_type) + unsigned int int_type, + const u32 *local_idx, + size_t nr_local) { int nr_irqs, i, err, cpu; @@ -561,13 +571,21 @@ static int __init exynos4_timer_interrupts(struct device_node *np, } else { for_each_possible_cpu(cpu) { int mct_irq; + unsigned int irq_idx; struct mct_clock_event_device *pcpu_mevt = per_cpu_ptr(&percpu_mct_tick, cpu); + if (cpu >= nr_local) { + err = -EINVAL; + goto out_irq; + } + + irq_idx = MCT_L0_IRQ + local_idx[cpu]; + pcpu_mevt->evt.irq = -1; - if (MCT_L0_IRQ + cpu >= ARRAY_SIZE(mct_irqs)) + if (irq_idx >= ARRAY_SIZE(mct_irqs)) break; - mct_irq = mct_irqs[MCT_L0_IRQ + cpu]; + mct_irq = mct_irqs[irq_idx]; irq_set_status_flags(mct_irq, IRQ_NOAUTOEN); if (request_irq(mct_irq, @@ -583,6 +601,17 @@ static int __init exynos4_timer_interrupts(struct device_node *np, } } + for_each_possible_cpu(cpu) { + struct mct_clock_event_device *mevt = per_cpu_ptr(&percpu_mct_tick, cpu); + + if (cpu >= nr_local) { + err = -EINVAL; + goto out_irq; + } + + mevt->base = EXYNOS4_MCT_L_BASE(local_idx[cpu]); + } + /* Install hotplug callbacks which configure the timer on this CPU */ err = cpuhp_setup_state(CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING, "clockevents/exynos4/mct_timer:starting", @@ -613,13 +642,34 @@ out_irq: static int __init mct_init_dt(struct device_node *np, unsigned int int_type) { bool frc_shared = of_property_read_bool(np, "samsung,frc-shared"); + u32 local_idx[MCT_NR_LOCAL] = {0}; + int nr_local; int ret; + nr_local = of_property_count_u32_elems(np, "samsung,local-timers"); + if (nr_local == 0) + return -EINVAL; + if (nr_local > 0) { + if (nr_local > ARRAY_SIZE(local_idx)) + return -EINVAL; + + ret = of_property_read_u32_array(np, "samsung,local-timers", + local_idx, nr_local); + if (ret) + return ret; + } else { + int i; + + nr_local = ARRAY_SIZE(local_idx); + for (i = 0; i < nr_local; i++) + local_idx[i] = i; + } + ret = exynos4_timer_resources(np); if (ret) return ret; - ret = exynos4_timer_interrupts(np, int_type); + ret = exynos4_timer_interrupts(np, int_type, local_idx, nr_local); if (ret) return ret; -- cgit v1.2.3 From 55ccdab79524ce9a46965af6e1908b90fa92b303 Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Thu, 9 Jun 2022 13:27:38 +0200 Subject: clocksource/drivers/exynos_mct: Enable building on ARTPEC This timer block is used on ARTPEC-8. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Vincent Whitchurch Link: https://lore.kernel.org/r/20220609112738.359385-5-vincent.whitchurch@axis.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 4f2bb7315b67..4469e7f555e9 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -434,7 +434,7 @@ config ATMEL_TCB_CLKSRC config CLKSRC_EXYNOS_MCT bool "Exynos multi core timer driver" if COMPILE_TEST depends on ARM || ARM64 - depends on ARCH_EXYNOS || COMPILE_TEST + depends on ARCH_ARTPEC || ARCH_EXYNOS || COMPILE_TEST help Support for Multi Core Timer controller on Exynos SoCs. -- cgit v1.2.3 From 6c3b62d93e195f78c1437c8fa7581e9b2f00886e Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Wed, 14 Sep 2022 14:14:24 +0800 Subject: clocksource/drivers/arm_arch_timer: Fix handling of ARM erratum 858921 The commit a38b71b0833e ("clocksource/drivers/arm_arch_timer: Move system register timer programming over to CVAL") moves the programming of the timers from the countdown timer (TVAL) over to the comparator (CVAL). This makes it necessary to read the counter when programming next event. However, the workaround of Cortex-A73 erratum 858921 does not set the corresponding set_next_event_phys and set_next_event_virt. Add the appropriate hooks to apply the erratum mitigation when programming the next timer event. Fixes: a38b71b0833e ("clocksource/drivers/arm_arch_timer: Move system register timer programming over to CVAL") Signed-off-by: Kunkun Jiang Acked-by: Marc Zyngier Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20220914061424.1260-1-jiangkunkun@huawei.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/arm_arch_timer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 9ab8221ee3c6..ff935efb6a88 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -473,6 +473,8 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { .desc = "ARM erratum 858921", .read_cntpct_el0 = arm64_858921_read_cntpct_el0, .read_cntvct_el0 = arm64_858921_read_cntvct_el0, + .set_next_event_phys = erratum_set_next_event_phys, + .set_next_event_virt = erratum_set_next_event_virt, }, #endif #ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1 -- cgit v1.2.3 From 0e2c8e6d769bcdc4f6634a02c545356282275e68 Mon Sep 17 00:00:00 2001 From: Lin Yujun Date: Wed, 14 Sep 2022 11:30:18 +0800 Subject: clocksource/drivers/timer-gxp: Add missing error handling in gxp_timer_probe Add platform_device_put() to make sure to free the platform device in the event platform_device_add() fails. Fixes: 5184f4bf151b ("clocksource/drivers/timer-gxp: Add HPE GXP Timer") Signed-off-by: Lin Yujun Link: https://lore.kernel.org/r/20220914033018.97484-1-linyujun809@huawei.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-gxp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-gxp.c b/drivers/clocksource/timer-gxp.c index 8b38b3212388..fe4fa8d7b3f1 100644 --- a/drivers/clocksource/timer-gxp.c +++ b/drivers/clocksource/timer-gxp.c @@ -171,6 +171,7 @@ static int gxp_timer_probe(struct platform_device *pdev) { struct platform_device *gxp_watchdog_device; struct device *dev = &pdev->dev; + int ret; if (!gxp_timer) { pr_err("Gxp Timer not initialized, cannot create watchdog"); @@ -187,7 +188,11 @@ static int gxp_timer_probe(struct platform_device *pdev) gxp_watchdog_device->dev.platform_data = gxp_timer->counter; gxp_watchdog_device->dev.parent = dev; - return platform_device_add(gxp_watchdog_device); + ret = platform_device_add(gxp_watchdog_device); + if (ret) + platform_device_put(gxp_watchdog_device); + + return ret; } static const struct of_device_id gxp_timer_of_match[] = { -- cgit v1.2.3 From caa590067efd659d8811ad8904489536912ebc53 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 15 Aug 2022 16:12:42 +0300 Subject: clocksource/drivers/timer-ti-dm: Drop unused functions We still have some unused functions left, let's drop them. Signed-off-by: Tony Lindgren Reviewed-by: Janusz Krzysztofik Link: https://lore.kernel.org/r/20220815131250.34603-2-tony@atomide.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-ti-dm.c | 51 --------------------------------------- include/clocksource/timer-ti-dm.h | 7 ------ 2 files changed, 58 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index 469f7c91564b..b8f8c1138e31 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -388,16 +388,6 @@ static inline u32 omap_dm_timer_reserved_systimer(int id) return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0; } -int omap_dm_timer_reserve_systimer(int id) -{ - if (omap_dm_timer_reserved_systimer(id)) - return -ENODEV; - - omap_reserved_systimers |= (1 << (id - 1)); - - return 0; -} - static struct omap_dm_timer *_omap_dm_timer_request(int req_type, void *data) { struct omap_dm_timer *timer = NULL, *t; @@ -499,20 +489,6 @@ static struct omap_dm_timer *omap_dm_timer_request_specific(int id) return _omap_dm_timer_request(REQUEST_BY_ID, &id); } -/** - * omap_dm_timer_request_by_cap - Request a timer by capability - * @cap: Bit mask of capabilities to match - * - * Find a timer based upon capabilities bit mask. Callers of this function - * should use the definitions found in the plat/dmtimer.h file under the - * comment "timer capabilities used in hwmod database". Returns pointer to - * timer handle on success and a NULL pointer on failure. - */ -struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap) -{ - return _omap_dm_timer_request(REQUEST_BY_CAP, &cap); -} - /** * omap_dm_timer_request_by_node - Request a timer by device-tree node * @np: Pointer to device-tree timer node @@ -606,17 +582,6 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) #endif -int omap_dm_timer_trigger(struct omap_dm_timer *timer) -{ - if (unlikely(!timer || !atomic_read(&timer->enabled))) { - pr_err("%s: timer not available or enabled.\n", __func__); - return -EINVAL; - } - - omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); - return 0; -} - static int omap_dm_timer_start(struct omap_dm_timer *timer) { u32 l; @@ -833,22 +798,6 @@ static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int return 0; } -int omap_dm_timers_active(void) -{ - struct omap_dm_timer *timer; - - list_for_each_entry(timer, &omap_timer_list, node) { - if (!timer->reserved) - continue; - - if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & - OMAP_TIMER_CTRL_ST) { - return 1; - } - } - return 0; -} - static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev) { struct omap_dm_timer *timer = dev_get_drvdata(dev); diff --git a/include/clocksource/timer-ti-dm.h b/include/clocksource/timer-ti-dm.h index b0f80cfd2a26..4142bf77be1a 100644 --- a/include/clocksource/timer-ti-dm.h +++ b/include/clocksource/timer-ti-dm.h @@ -119,17 +119,10 @@ struct omap_dm_timer { struct notifier_block nb; }; -int omap_dm_timer_reserve_systimer(int id); -struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap); - int omap_dm_timer_get_irq(struct omap_dm_timer *timer); u32 omap_dm_timer_modify_idlect_mask(u32 inputmask); -int omap_dm_timer_trigger(struct omap_dm_timer *timer); - -int omap_dm_timers_active(void); - /* * Do not use the defines below, they are not needed. They should be only * used by dmtimer.c and sys_timer related code. -- cgit v1.2.3 From 90c9aada19606ae78259cef78a46646a97ec8f67 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 15 Aug 2022 16:12:43 +0300 Subject: clocksource/drivers/timer-ti-dm: Simplify register reads with dmtimer_read() We can simplify register read access by checking for the register write posted mode in the read function. This way we can combine the functions for __omap_dm_timer_read() and omap_dm_timer_read_reg() into a single function dmtimer_read(). We update the shared register access first, the timer revision specific register access will be updated in a later patch. Signed-off-by: Tony Lindgren Reviewed-by: Janusz Krzysztofik Link: https://lore.kernel.org/r/20220815131250.34603-3-tony@atomide.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-ti-dm.c | 88 ++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 48 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index b8f8c1138e31..070d47d6a88c 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -44,14 +44,28 @@ enum { REQUEST_BY_NODE, }; -static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg, - int posted) +/** + * dmtimer_read - read timer registers in posted and non-posted mode + * @timer: timer pointer over which read operation to perform + * @reg: lowest byte holds the register offset + * + * The posted mode bit is encoded in reg. Note that in posted mode, write + * pending bit must be checked. Otherwise a read of a non completed write + * will produce an error. + */ +static inline u32 dmtimer_read(struct omap_dm_timer *timer, u32 reg) { - if (posted) - while (readl_relaxed(timer->pend) & (reg >> WPSHIFT)) + u16 wp, offset; + + wp = reg >> WPSHIFT; + offset = reg & 0xff; + + /* Wait for a possible write pending bit in posted mode */ + if (wp && timer->posted) + while (readl_relaxed(timer->pend) & wp) cpu_relax(); - return readl_relaxed(timer->func_base + (reg & 0xff)); + return readl_relaxed(timer->func_base + offset); } static inline void __omap_dm_timer_write(struct omap_dm_timer *timer, @@ -121,13 +135,13 @@ static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer, { u32 l; - l = __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted); + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); if (l & OMAP_TIMER_CTRL_ST) { l &= ~0x1; __omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, l, posted); #ifdef CONFIG_ARCH_OMAP2PLUS /* Readback to make sure write has completed */ - __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted); + dmtimer_read(timer, OMAP_TIMER_CTRL_REG); /* * Wait for functional clock period x 3.5 to make sure that * timer is stopped @@ -148,9 +162,9 @@ static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer, } static inline unsigned int -__omap_dm_timer_read_counter(struct omap_dm_timer *timer, int posted) +__omap_dm_timer_read_counter(struct omap_dm_timer *timer) { - return __omap_dm_timer_read(timer, OMAP_TIMER_COUNTER_REG, posted); + return dmtimer_read(timer, OMAP_TIMER_COUNTER_REG); } static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer, @@ -159,21 +173,6 @@ static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer, writel_relaxed(value, timer->irq_stat); } -/** - * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode - * @timer: timer pointer over which read operation to perform - * @reg: lowest byte holds the register offset - * - * The posted mode bit is encoded in reg. Note that in posted mode write - * pending bit must be checked. Otherwise a read of a non completed write - * will produce an error. - */ -static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg) -{ - WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET); - return __omap_dm_timer_read(timer, reg, timer->posted); -} - /** * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode * @timer: timer pointer over which write operation is to perform @@ -213,20 +212,14 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer) static void omap_timer_save_context(struct omap_dm_timer *timer) { - timer->context.ocp_cfg = - __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0); - - timer->context.tclr = - omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); - timer->context.twer = - omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG); - timer->context.tldr = - omap_dm_timer_read_reg(timer, OMAP_TIMER_LOAD_REG); - timer->context.tmar = - omap_dm_timer_read_reg(timer, OMAP_TIMER_MATCH_REG); + timer->context.ocp_cfg = dmtimer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET); + + timer->context.tclr = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); + timer->context.twer = dmtimer_read(timer, OMAP_TIMER_WAKEUP_EN_REG); + timer->context.tldr = dmtimer_read(timer, OMAP_TIMER_LOAD_REG); + timer->context.tmar = dmtimer_read(timer, OMAP_TIMER_MATCH_REG); timer->context.tier = readl_relaxed(timer->irq_ena); - timer->context.tsicr = - omap_dm_timer_read_reg(timer, OMAP_TIMER_IF_CTRL_REG); + timer->context.tsicr = dmtimer_read(timer, OMAP_TIMER_IF_CTRL_REG); } static int omap_timer_context_notifier(struct notifier_block *nb, @@ -266,8 +259,7 @@ static int omap_dm_timer_reset(struct omap_dm_timer *timer) omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); do { - l = __omap_dm_timer_read(timer, - OMAP_TIMER_V1_SYS_STAT_OFFSET, 0); + l = dmtimer_read(timer, OMAP_TIMER_V1_SYS_STAT_OFFSET); } while (!l && timeout--); if (!timeout) { @@ -276,7 +268,7 @@ static int omap_dm_timer_reset(struct omap_dm_timer *timer) } /* Configure timer for smart-idle mode */ - l = __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0); + l = dmtimer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET); l |= 0x2 << 0x3; __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l, 0); @@ -550,7 +542,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) list_for_each_entry(timer, &omap_timer_list, node) { u32 l; - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); if (l & OMAP_TIMER_CTRL_ST) { if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0) inputmask &= ~(1 << 1); @@ -591,7 +583,7 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer) omap_dm_timer_enable(timer); - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); if (!(l & OMAP_TIMER_CTRL_ST)) { l |= OMAP_TIMER_CTRL_ST; omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); @@ -638,7 +630,7 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, return -EINVAL; omap_dm_timer_enable(timer); - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); if (enable) l |= OMAP_TIMER_CTRL_CE; else @@ -659,7 +651,7 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, return -EINVAL; omap_dm_timer_enable(timer); - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM | OMAP_TIMER_CTRL_PT | (0x03 << 10) | OMAP_TIMER_CTRL_AR); if (def_on) @@ -683,7 +675,7 @@ static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *timer) return -EINVAL; omap_dm_timer_enable(timer); - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); omap_dm_timer_disable(timer); return l; @@ -698,7 +690,7 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, return -EINVAL; omap_dm_timer_enable(timer); - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2)); if (prescaler >= 0) { l |= OMAP_TIMER_CTRL_PRE; @@ -743,7 +735,7 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask) l = readl_relaxed(timer->irq_ena) & ~mask; writel_relaxed(l, timer->irq_dis); - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask; + l = dmtimer_read(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask; omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l); omap_dm_timer_disable(timer); @@ -781,7 +773,7 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) return 0; } - return __omap_dm_timer_read_counter(timer, timer->posted); + return __omap_dm_timer_read_counter(timer); } static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) -- cgit v1.2.3 From 49cd16bb573e43dc2ee64d734b9b545475dbb35f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 15 Aug 2022 16:12:44 +0300 Subject: clocksource/drivers/timer-ti-dm: Simplify register writes with dmtimer_write() We can simplify register write access by checking for the register write posted mode in the write function. This way we can combine the functions for __omap_dm_timer_write() and omap_dm_timer_write_reg() into a single function dmtimer_write(). We update the shared register access first, the timer revision specific register access will be updated in a later patch. Signed-off-by: Tony Lindgren Reviewed-by: Janusz Krzysztofik Link: https://lore.kernel.org/r/20220815131250.34603-4-tony@atomide.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-ti-dm.c | 98 ++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 54 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index 070d47d6a88c..61c3c7684314 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -68,14 +68,29 @@ static inline u32 dmtimer_read(struct omap_dm_timer *timer, u32 reg) return readl_relaxed(timer->func_base + offset); } -static inline void __omap_dm_timer_write(struct omap_dm_timer *timer, - u32 reg, u32 val, int posted) +/** + * dmtimer_write - write timer registers in posted and non-posted mode + * @timer: timer pointer over which write operation is to perform + * @reg: lowest byte holds the register offset + * @value: data to write into the register + * + * The posted mode bit is encoded in reg. Note that in posted mode, the write + * pending bit must be checked. Otherwise a write on a register which has a + * pending write will be lost. + */ +static inline void dmtimer_write(struct omap_dm_timer *timer, u32 reg, u32 val) { - if (posted) - while (readl_relaxed(timer->pend) & (reg >> WPSHIFT)) + u16 wp, offset; + + wp = reg >> WPSHIFT; + offset = reg & 0xff; + + /* Wait for a possible write pending bit in posted mode */ + if (wp && timer->posted) + while (readl_relaxed(timer->pend) & wp) cpu_relax(); - writel_relaxed(val, timer->func_base + (reg & 0xff)); + writel_relaxed(val, timer->func_base + offset); } static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer) @@ -120,25 +135,24 @@ static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer) if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) { timer->posted = OMAP_TIMER_NONPOSTED; - __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0, 0); + dmtimer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0); return; } - __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, - OMAP_TIMER_CTRL_POSTED, 0); + dmtimer_write(timer, OMAP_TIMER_IF_CTRL_REG, OMAP_TIMER_CTRL_POSTED); timer->context.tsicr = OMAP_TIMER_CTRL_POSTED; timer->posted = OMAP_TIMER_POSTED; } static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer, - int posted, unsigned long rate) + unsigned long rate) { u32 l; l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); if (l & OMAP_TIMER_CTRL_ST) { l &= ~0x1; - __omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, l, posted); + dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l); #ifdef CONFIG_ARCH_OMAP2PLUS /* Readback to make sure write has completed */ dmtimer_read(timer, OMAP_TIMER_CTRL_REG); @@ -158,7 +172,7 @@ static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer, unsigned int value) { writel_relaxed(value, timer->irq_ena); - __omap_dm_timer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value, 0); + dmtimer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value); } static inline unsigned int @@ -173,41 +187,17 @@ static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer, writel_relaxed(value, timer->irq_stat); } -/** - * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode - * @timer: timer pointer over which write operation is to perform - * @reg: lowest byte holds the register offset - * @value: data to write into the register - * - * The posted mode bit is encoded in reg. Note that in posted mode the write - * pending bit must be checked. Otherwise a write on a register which has a - * pending write will be lost. - */ -static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg, - u32 value) -{ - WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET); - __omap_dm_timer_write(timer, reg, value, timer->posted); -} - static void omap_timer_restore_context(struct omap_dm_timer *timer) { - __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, - timer->context.ocp_cfg, 0); - - omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, - timer->context.twer); - omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, - timer->context.tcrr); - omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, - timer->context.tldr); - omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, - timer->context.tmar); - omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, - timer->context.tsicr); + dmtimer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, timer->context.ocp_cfg); + + dmtimer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, timer->context.twer); + dmtimer_write(timer, OMAP_TIMER_COUNTER_REG, timer->context.tcrr); + dmtimer_write(timer, OMAP_TIMER_LOAD_REG, timer->context.tldr); + dmtimer_write(timer, OMAP_TIMER_MATCH_REG, timer->context.tmar); + dmtimer_write(timer, OMAP_TIMER_IF_CTRL_REG, timer->context.tsicr); writel_relaxed(timer->context.tier, timer->irq_ena); - omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, - timer->context.tclr); + dmtimer_write(timer, OMAP_TIMER_CTRL_REG, timer->context.tclr); } static void omap_timer_save_context(struct omap_dm_timer *timer) @@ -256,7 +246,7 @@ static int omap_dm_timer_reset(struct omap_dm_timer *timer) if (timer->revision != 1) return -EINVAL; - omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); + dmtimer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); do { l = dmtimer_read(timer, OMAP_TIMER_V1_SYS_STAT_OFFSET); @@ -270,7 +260,7 @@ static int omap_dm_timer_reset(struct omap_dm_timer *timer) /* Configure timer for smart-idle mode */ l = dmtimer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET); l |= 0x2 << 0x3; - __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l, 0); + dmtimer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l); timer->posted = 0; @@ -586,7 +576,7 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer) l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); if (!(l & OMAP_TIMER_CTRL_ST)) { l |= OMAP_TIMER_CTRL_ST; - omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); + dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l); } return 0; @@ -602,7 +592,7 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer) if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) rate = clk_get_rate(timer->fclk); - __omap_dm_timer_stop(timer, timer->posted, rate); + __omap_dm_timer_stop(timer, rate); omap_dm_timer_disable(timer); return 0; @@ -615,7 +605,7 @@ static int omap_dm_timer_set_load(struct omap_dm_timer *timer, return -EINVAL; omap_dm_timer_enable(timer); - omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); + dmtimer_write(timer, OMAP_TIMER_LOAD_REG, load); omap_dm_timer_disable(timer); return 0; @@ -635,8 +625,8 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, l |= OMAP_TIMER_CTRL_CE; else l &= ~OMAP_TIMER_CTRL_CE; - omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); - omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); + dmtimer_write(timer, OMAP_TIMER_MATCH_REG, match); + dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l); omap_dm_timer_disable(timer); return 0; @@ -661,7 +651,7 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, l |= trigger << 10; if (autoreload) l |= OMAP_TIMER_CTRL_AR; - omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); + dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l); omap_dm_timer_disable(timer); return 0; @@ -696,7 +686,7 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, l |= OMAP_TIMER_CTRL_PRE; l |= prescaler << 2; } - omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); + dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l); omap_dm_timer_disable(timer); return 0; @@ -736,7 +726,7 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask) writel_relaxed(l, timer->irq_dis); l = dmtimer_read(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask; - omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l); + dmtimer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, l); omap_dm_timer_disable(timer); return 0; @@ -783,7 +773,7 @@ static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int return -EINVAL; } - omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); + dmtimer_write(timer, OMAP_TIMER_COUNTER_REG, value); /* Save the context */ timer->context.tcrr = value; -- cgit v1.2.3 From f32bdac10cb5f461f8c71c3b9703617c42322d2f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 15 Aug 2022 16:12:45 +0300 Subject: clocksource/drivers/timer-ti-dm: Simplify register access further Let's unify register access and use dmtimer_read() and dmtimer_write() also for the timer revision specific registers like we now do for the shread registers. Signed-off-by: Tony Lindgren Reviewed-by: Janusz Krzysztofik Link: https://lore.kernel.org/r/20220815131250.34603-5-tony@atomide.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-ti-dm.c | 28 ++++++++++++++-------------- include/clocksource/timer-ti-dm.h | 6 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index 61c3c7684314..fe8ba0fad869 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -101,16 +101,16 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer) tidr = readl_relaxed(timer->io_base); if (!(tidr >> 16)) { timer->revision = 1; - timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET; - timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET; - timer->irq_dis = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET; + timer->irq_stat = OMAP_TIMER_V1_STAT_OFFSET; + timer->irq_ena = OMAP_TIMER_V1_INT_EN_OFFSET; + timer->irq_dis = OMAP_TIMER_V1_INT_EN_OFFSET; timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET; timer->func_base = timer->io_base; } else { timer->revision = 2; - timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS; - timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET; - timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR; + timer->irq_stat = OMAP_TIMER_V2_IRQSTATUS - OMAP_TIMER_V2_FUNC_OFFSET; + timer->irq_ena = OMAP_TIMER_V2_IRQENABLE_SET - OMAP_TIMER_V2_FUNC_OFFSET; + timer->irq_dis = OMAP_TIMER_V2_IRQENABLE_CLR - OMAP_TIMER_V2_FUNC_OFFSET; timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET + OMAP_TIMER_V2_FUNC_OFFSET; @@ -165,13 +165,13 @@ static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer, } /* Ack possibly pending interrupt */ - writel_relaxed(OMAP_TIMER_INT_OVERFLOW, timer->irq_stat); + dmtimer_write(timer, timer->irq_stat, OMAP_TIMER_INT_OVERFLOW); } static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer, unsigned int value) { - writel_relaxed(value, timer->irq_ena); + dmtimer_write(timer, timer->irq_ena, value); dmtimer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value); } @@ -184,7 +184,7 @@ __omap_dm_timer_read_counter(struct omap_dm_timer *timer) static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) { - writel_relaxed(value, timer->irq_stat); + dmtimer_write(timer, timer->irq_stat, value); } static void omap_timer_restore_context(struct omap_dm_timer *timer) @@ -196,7 +196,7 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer) dmtimer_write(timer, OMAP_TIMER_LOAD_REG, timer->context.tldr); dmtimer_write(timer, OMAP_TIMER_MATCH_REG, timer->context.tmar); dmtimer_write(timer, OMAP_TIMER_IF_CTRL_REG, timer->context.tsicr); - writel_relaxed(timer->context.tier, timer->irq_ena); + dmtimer_write(timer, timer->irq_ena, timer->context.tier); dmtimer_write(timer, OMAP_TIMER_CTRL_REG, timer->context.tclr); } @@ -208,7 +208,7 @@ static void omap_timer_save_context(struct omap_dm_timer *timer) timer->context.twer = dmtimer_read(timer, OMAP_TIMER_WAKEUP_EN_REG); timer->context.tldr = dmtimer_read(timer, OMAP_TIMER_LOAD_REG); timer->context.tmar = dmtimer_read(timer, OMAP_TIMER_MATCH_REG); - timer->context.tier = readl_relaxed(timer->irq_ena); + timer->context.tier = dmtimer_read(timer, timer->irq_ena); timer->context.tsicr = dmtimer_read(timer, OMAP_TIMER_IF_CTRL_REG); } @@ -722,9 +722,9 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask) omap_dm_timer_enable(timer); if (timer->revision == 1) - l = readl_relaxed(timer->irq_ena) & ~mask; + l = dmtimer_read(timer, timer->irq_ena) & ~mask; - writel_relaxed(l, timer->irq_dis); + dmtimer_write(timer, timer->irq_dis, l); l = dmtimer_read(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask; dmtimer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, l); @@ -741,7 +741,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) return 0; } - l = readl_relaxed(timer->irq_stat); + l = dmtimer_read(timer, timer->irq_stat); return l; } diff --git a/include/clocksource/timer-ti-dm.h b/include/clocksource/timer-ti-dm.h index 4142bf77be1a..e874eed2fa46 100644 --- a/include/clocksource/timer-ti-dm.h +++ b/include/clocksource/timer-ti-dm.h @@ -100,9 +100,9 @@ struct omap_dm_timer { struct clk *fclk; void __iomem *io_base; - void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */ - void __iomem *irq_ena; /* irq enable */ - void __iomem *irq_dis; /* irq disable, only on v2 ip */ + int irq_stat; /* TISR/IRQSTATUS interrupt status */ + int irq_ena; /* irq enable */ + int irq_dis; /* irq disable, only on v2 ip */ void __iomem *pend; /* write pending */ void __iomem *func_base; /* function register base */ -- cgit v1.2.3 From 1d513f439d7930363adce4588030af7c8fa71cc9 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 15 Aug 2022 16:12:46 +0300 Subject: clocksource/drivers/timer-ti-dm: Move private defines to the driver These defines are only used by timer-ti-dm driver. Signed-off-by: Tony Lindgren Reviewed-by: Janusz Krzysztofik Link: https://lore.kernel.org/r/20220815131250.34603-6-tony@atomide.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-ti-dm.c | 62 +++++++++++++++++++++++++++++++++++++++ include/clocksource/timer-ti-dm.h | 62 --------------------------------------- 2 files changed, 62 insertions(+), 62 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index fe8ba0fad869..e82ec5626849 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -33,6 +33,68 @@ #include +/* + * timer errata flags + * + * Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This + * errata prevents us from using posted mode on these devices, unless the + * timer counter register is never read. For more details please refer to + * the OMAP3/4/5 errata documents. + */ +#define OMAP_TIMER_ERRATA_I103_I767 0x80000000 + +/* posted mode types */ +#define OMAP_TIMER_NONPOSTED 0x00 +#define OMAP_TIMER_POSTED 0x01 + +/* register offsets with the write pending bit encoded */ +#define WPSHIFT 16 + +#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_CTRL_REG (_OMAP_TIMER_CTRL_OFFSET \ + | (WP_TCLR << WPSHIFT)) + +#define OMAP_TIMER_COUNTER_REG (_OMAP_TIMER_COUNTER_OFFSET \ + | (WP_TCRR << WPSHIFT)) + +#define OMAP_TIMER_LOAD_REG (_OMAP_TIMER_LOAD_OFFSET \ + | (WP_TLDR << WPSHIFT)) + +#define OMAP_TIMER_TRIGGER_REG (_OMAP_TIMER_TRIGGER_OFFSET \ + | (WP_TTGR << WPSHIFT)) + +#define OMAP_TIMER_WRITE_PEND_REG (_OMAP_TIMER_WRITE_PEND_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_MATCH_REG (_OMAP_TIMER_MATCH_OFFSET \ + | (WP_TMAR << WPSHIFT)) + +#define OMAP_TIMER_CAPTURE_REG (_OMAP_TIMER_CAPTURE_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_IF_CTRL_REG (_OMAP_TIMER_IF_CTRL_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_CAPTURE2_REG (_OMAP_TIMER_CAPTURE2_OFFSET \ + | (WP_NONE << WPSHIFT)) + +#define OMAP_TIMER_TICK_POS_REG (_OMAP_TIMER_TICK_POS_OFFSET \ + | (WP_TPIR << WPSHIFT)) + +#define OMAP_TIMER_TICK_NEG_REG (_OMAP_TIMER_TICK_NEG_OFFSET \ + | (WP_TNIR << WPSHIFT)) + +#define OMAP_TIMER_TICK_COUNT_REG (_OMAP_TIMER_TICK_COUNT_OFFSET \ + | (WP_TCVR << WPSHIFT)) + +#define OMAP_TIMER_TICK_INT_MASK_SET_REG \ + (_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT)) + +#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \ + (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT)) + static u32 omap_reserved_systimers; static LIST_HEAD(omap_timer_list); static DEFINE_SPINLOCK(dm_timer_lock); diff --git a/include/clocksource/timer-ti-dm.h b/include/clocksource/timer-ti-dm.h index e874eed2fa46..df3c6c88264f 100644 --- a/include/clocksource/timer-ti-dm.h +++ b/include/clocksource/timer-ti-dm.h @@ -52,10 +52,6 @@ #define OMAP_TIMER_TRIGGER_OVERFLOW 0x01 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE 0x02 -/* posted mode types */ -#define OMAP_TIMER_NONPOSTED 0x00 -#define OMAP_TIMER_POSTED 0x01 - /* timer capabilities used in hwmod database */ #define OMAP_TIMER_SECURE 0x80000000 #define OMAP_TIMER_ALWON 0x40000000 @@ -63,16 +59,6 @@ #define OMAP_TIMER_NEEDS_RESET 0x10000000 #define OMAP_TIMER_HAS_DSP_IRQ 0x08000000 -/* - * timer errata flags - * - * Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This - * errata prevents us from using posted mode on these devices, unless the - * timer counter register is never read. For more details please refer to - * the OMAP3/4/5 errata documents. - */ -#define OMAP_TIMER_ERRATA_I103_I767 0x80000000 - struct timer_regs { u32 ocp_cfg; u32 tidr; @@ -192,52 +178,4 @@ u32 omap_dm_timer_modify_idlect_mask(u32 inputmask); #define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET 0x54 /* TOCR, 34xx only */ #define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET 0x58 /* TOWR, 34xx only */ -/* register offsets with the write pending bit encoded */ -#define WPSHIFT 16 - -#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \ - | (WP_NONE << WPSHIFT)) - -#define OMAP_TIMER_CTRL_REG (_OMAP_TIMER_CTRL_OFFSET \ - | (WP_TCLR << WPSHIFT)) - -#define OMAP_TIMER_COUNTER_REG (_OMAP_TIMER_COUNTER_OFFSET \ - | (WP_TCRR << WPSHIFT)) - -#define OMAP_TIMER_LOAD_REG (_OMAP_TIMER_LOAD_OFFSET \ - | (WP_TLDR << WPSHIFT)) - -#define OMAP_TIMER_TRIGGER_REG (_OMAP_TIMER_TRIGGER_OFFSET \ - | (WP_TTGR << WPSHIFT)) - -#define OMAP_TIMER_WRITE_PEND_REG (_OMAP_TIMER_WRITE_PEND_OFFSET \ - | (WP_NONE << WPSHIFT)) - -#define OMAP_TIMER_MATCH_REG (_OMAP_TIMER_MATCH_OFFSET \ - | (WP_TMAR << WPSHIFT)) - -#define OMAP_TIMER_CAPTURE_REG (_OMAP_TIMER_CAPTURE_OFFSET \ - | (WP_NONE << WPSHIFT)) - -#define OMAP_TIMER_IF_CTRL_REG (_OMAP_TIMER_IF_CTRL_OFFSET \ - | (WP_NONE << WPSHIFT)) - -#define OMAP_TIMER_CAPTURE2_REG (_OMAP_TIMER_CAPTURE2_OFFSET \ - | (WP_NONE << WPSHIFT)) - -#define OMAP_TIMER_TICK_POS_REG (_OMAP_TIMER_TICK_POS_OFFSET \ - | (WP_TPIR << WPSHIFT)) - -#define OMAP_TIMER_TICK_NEG_REG (_OMAP_TIMER_TICK_NEG_OFFSET \ - | (WP_TNIR << WPSHIFT)) - -#define OMAP_TIMER_TICK_COUNT_REG (_OMAP_TIMER_TICK_COUNT_OFFSET \ - | (WP_TCVR << WPSHIFT)) - -#define OMAP_TIMER_TICK_INT_MASK_SET_REG \ - (_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT)) - -#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \ - (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT)) - #endif /* __CLOCKSOURCE_DMTIMER_H */ -- cgit v1.2.3 From bd351f1aee21ca667b39658550b5f3c61e8bb77f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 15 Aug 2022 16:12:47 +0300 Subject: clocksource/drivers/timer-ti-dm: Use runtime PM directly and check errors Use pm_runtime_resume_and_get() and check for a possible error returned. We want to do this as omap_dm_timer_enable() and omap_dm_timer_disable() are exposed to the pwm and remoteproc drivers, and in the following patch we turn struct omap_dm_timer into a cookie used by the exposed functions only. Signed-off-by: Tony Lindgren Reviewed-by: Janusz Krzysztofik Link: https://lore.kernel.org/r/20220815131250.34603-7-tony@atomide.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-ti-dm.c | 117 +++++++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 26 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index e82ec5626849..4967a91a114a 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -387,16 +387,24 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) static void omap_dm_timer_enable(struct omap_dm_timer *timer) { - pm_runtime_get_sync(&timer->pdev->dev); + struct device *dev = &timer->pdev->dev; + int rc; + + rc = pm_runtime_resume_and_get(dev); + if (rc) + dev_err(dev, "could not enable timer\n"); } static void omap_dm_timer_disable(struct omap_dm_timer *timer) { - pm_runtime_put_sync(&timer->pdev->dev); + struct device *dev = &timer->pdev->dev; + + pm_runtime_put_sync(dev); } static int omap_dm_timer_prepare(struct omap_dm_timer *timer) { + struct device *dev = &timer->pdev->dev; int rc; /* @@ -411,18 +419,20 @@ static int omap_dm_timer_prepare(struct omap_dm_timer *timer) } } - omap_dm_timer_enable(timer); + rc = pm_runtime_resume_and_get(dev); + if (rc) + return rc; if (timer->capability & OMAP_TIMER_NEEDS_RESET) { rc = omap_dm_timer_reset(timer); if (rc) { - omap_dm_timer_disable(timer); + pm_runtime_put_sync(dev); return rc; } } __omap_dm_timer_enable_posted(timer); - omap_dm_timer_disable(timer); + pm_runtime_put_sync(dev); return 0; } @@ -628,12 +638,16 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) static int omap_dm_timer_start(struct omap_dm_timer *timer) { + struct device *dev = &timer->pdev->dev; + int rc; u32 l; if (unlikely(!timer)) return -EINVAL; - omap_dm_timer_enable(timer); + rc = pm_runtime_resume_and_get(dev); + if (rc) + return rc; l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); if (!(l & OMAP_TIMER_CTRL_ST)) { @@ -646,6 +660,7 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer) static int omap_dm_timer_stop(struct omap_dm_timer *timer) { + struct device *dev = &timer->pdev->dev; unsigned long rate = 0; if (unlikely(!timer)) @@ -656,32 +671,47 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer) __omap_dm_timer_stop(timer, rate); - omap_dm_timer_disable(timer); + pm_runtime_put_sync(dev); + return 0; } static int omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load) { + struct device *dev; + int rc; + if (unlikely(!timer)) return -EINVAL; - omap_dm_timer_enable(timer); + dev = &timer->pdev->dev; + rc = pm_runtime_resume_and_get(dev); + if (rc) + return rc; + dmtimer_write(timer, OMAP_TIMER_LOAD_REG, load); - omap_dm_timer_disable(timer); + pm_runtime_put_sync(dev); + return 0; } static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match) { + struct device *dev; + int rc; u32 l; if (unlikely(!timer)) return -EINVAL; - omap_dm_timer_enable(timer); + dev = &timer->pdev->dev; + rc = pm_runtime_resume_and_get(dev); + if (rc) + return rc; + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); if (enable) l |= OMAP_TIMER_CTRL_CE; @@ -690,19 +720,26 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, dmtimer_write(timer, OMAP_TIMER_MATCH_REG, match); dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l); - omap_dm_timer_disable(timer); + pm_runtime_put_sync(dev); + return 0; } static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger, int autoreload) { + struct device *dev; + int rc; u32 l; if (unlikely(!timer)) return -EINVAL; - omap_dm_timer_enable(timer); + dev = &timer->pdev->dev; + rc = pm_runtime_resume_and_get(dev); + if (rc) + return rc; + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM | OMAP_TIMER_CTRL_PT | (0x03 << 10) | OMAP_TIMER_CTRL_AR); @@ -715,20 +752,28 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, l |= OMAP_TIMER_CTRL_AR; dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l); - omap_dm_timer_disable(timer); + pm_runtime_put_sync(dev); + return 0; } static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *timer) { + struct device *dev; + int rc; u32 l; if (unlikely(!timer)) return -EINVAL; - omap_dm_timer_enable(timer); + dev = &timer->pdev->dev; + rc = pm_runtime_resume_and_get(dev); + if (rc) + return rc; + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); - omap_dm_timer_disable(timer); + + pm_runtime_put_sync(dev); return l; } @@ -736,12 +781,18 @@ static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *timer) static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) { + struct device *dev; + int rc; u32 l; if (unlikely(!timer) || prescaler < -1 || prescaler > 7) return -EINVAL; - omap_dm_timer_enable(timer); + dev = &timer->pdev->dev; + rc = pm_runtime_resume_and_get(dev); + if (rc) + return rc; + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2)); if (prescaler >= 0) { @@ -750,20 +801,29 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, } dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l); - omap_dm_timer_disable(timer); + pm_runtime_put_sync(dev); + return 0; } static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value) { + struct device *dev; + int rc; + if (unlikely(!timer)) return -EINVAL; - omap_dm_timer_enable(timer); + dev = &timer->pdev->dev; + rc = pm_runtime_resume_and_get(dev); + if (rc) + return rc; + __omap_dm_timer_int_enable(timer, value); - omap_dm_timer_disable(timer); + pm_runtime_put_sync(dev); + return 0; } @@ -776,12 +836,17 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, */ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask) { + struct device *dev; u32 l = mask; + int rc; if (unlikely(!timer)) return -EINVAL; - omap_dm_timer_enable(timer); + dev = &timer->pdev->dev; + rc = pm_runtime_resume_and_get(dev); + if (rc) + return rc; if (timer->revision == 1) l = dmtimer_read(timer, timer->irq_ena) & ~mask; @@ -790,7 +855,8 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask) l = dmtimer_read(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask; dmtimer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, l); - omap_dm_timer_disable(timer); + pm_runtime_put_sync(dev); + return 0; } @@ -943,11 +1009,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev) pm_runtime_enable(dev); if (!timer->reserved) { - ret = pm_runtime_get_sync(dev); - if (ret < 0) { + ret = pm_runtime_resume_and_get(dev); + if (ret) { dev_err(dev, "%s: pm_runtime_get_sync failed!\n", __func__); - goto err_get_sync; + goto err_disable; } __omap_dm_timer_init_regs(timer); pm_runtime_put(dev); @@ -962,8 +1028,7 @@ static int omap_dm_timer_probe(struct platform_device *pdev) return 0; -err_get_sync: - pm_runtime_put_noidle(dev); +err_disable: pm_runtime_disable(dev); return ret; } -- cgit v1.2.3 From a6e543f61531b63bfc8d43053c6ec6f65117f627 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 15 Aug 2022 16:12:48 +0300 Subject: clocksource/drivers/timer-ti-dm: Move struct omap_dm_timer fields to driver There is no longer any need to expose the elements of struct omap_dm_timer outside the driver. The pwm and remoteproc drivers just use struct omap_dm_timer as a cookie. Let's move the elements of struct omap_dm_timer into struct dmtimer that is private to the driver. To do this, we mostly rename omap_dm_timer to dmtimer in the driver. We keep omap_dm_timer only for the exposed functions in the platform_data for the pwm and remoteproc drivers. Let's also add a note about not using the exposed functions internally as those will get deprecated eventually in favor of Linux generic frameworks. Signed-off-by: Tony Lindgren Reviewed-by: Janusz Krzysztofik Link: https://lore.kernel.org/r/20220815131250.34603-8-tony@atomide.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-ti-dm.c | 218 +++++++++++++++++++++++++++++--------- include/clocksource/timer-ti-dm.h | 43 -------- 2 files changed, 170 insertions(+), 91 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index 4967a91a114a..0d0130ec4d1c 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -95,6 +95,53 @@ #define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \ (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT)) +struct timer_regs { + u32 ocp_cfg; + u32 tidr; + u32 tier; + u32 twer; + u32 tclr; + u32 tcrr; + u32 tldr; + u32 ttrg; + u32 twps; + u32 tmar; + u32 tcar1; + u32 tsicr; + u32 tcar2; + u32 tpir; + u32 tnir; + u32 tcvr; + u32 tocr; + u32 towr; +}; + +struct dmtimer { + struct omap_dm_timer cookie; + int id; + int irq; + struct clk *fclk; + + void __iomem *io_base; + int irq_stat; /* TISR/IRQSTATUS interrupt status */ + int irq_ena; /* irq enable */ + int irq_dis; /* irq disable, only on v2 ip */ + void __iomem *pend; /* write pending */ + void __iomem *func_base; /* function register base */ + + atomic_t enabled; + unsigned long rate; + unsigned reserved:1; + unsigned posted:1; + struct timer_regs context; + int revision; + u32 capability; + u32 errata; + struct platform_device *pdev; + struct list_head node; + struct notifier_block nb; +}; + static u32 omap_reserved_systimers; static LIST_HEAD(omap_timer_list); static DEFINE_SPINLOCK(dm_timer_lock); @@ -115,7 +162,7 @@ enum { * pending bit must be checked. Otherwise a read of a non completed write * will produce an error. */ -static inline u32 dmtimer_read(struct omap_dm_timer *timer, u32 reg) +static inline u32 dmtimer_read(struct dmtimer *timer, u32 reg) { u16 wp, offset; @@ -140,7 +187,7 @@ static inline u32 dmtimer_read(struct omap_dm_timer *timer, u32 reg) * pending bit must be checked. Otherwise a write on a register which has a * pending write will be lost. */ -static inline void dmtimer_write(struct omap_dm_timer *timer, u32 reg, u32 val) +static inline void dmtimer_write(struct dmtimer *timer, u32 reg, u32 val) { u16 wp, offset; @@ -155,7 +202,7 @@ static inline void dmtimer_write(struct omap_dm_timer *timer, u32 reg, u32 val) writel_relaxed(val, timer->func_base + offset); } -static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer) +static inline void __omap_dm_timer_init_regs(struct dmtimer *timer) { u32 tidr; @@ -190,7 +237,7 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer) * complete. Enabling this feature can improve performance for writing to the * timer registers. */ -static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer) +static inline void __omap_dm_timer_enable_posted(struct dmtimer *timer) { if (timer->posted) return; @@ -206,7 +253,7 @@ static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer) timer->posted = OMAP_TIMER_POSTED; } -static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer, +static inline void __omap_dm_timer_stop(struct dmtimer *timer, unsigned long rate) { u32 l; @@ -230,26 +277,26 @@ static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer, dmtimer_write(timer, timer->irq_stat, OMAP_TIMER_INT_OVERFLOW); } -static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer, - unsigned int value) +static inline void __omap_dm_timer_int_enable(struct dmtimer *timer, + unsigned int value) { dmtimer_write(timer, timer->irq_ena, value); dmtimer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value); } static inline unsigned int -__omap_dm_timer_read_counter(struct omap_dm_timer *timer) +__omap_dm_timer_read_counter(struct dmtimer *timer) { return dmtimer_read(timer, OMAP_TIMER_COUNTER_REG); } -static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer, +static inline void __omap_dm_timer_write_status(struct dmtimer *timer, unsigned int value) { dmtimer_write(timer, timer->irq_stat, value); } -static void omap_timer_restore_context(struct omap_dm_timer *timer) +static void omap_timer_restore_context(struct dmtimer *timer) { dmtimer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, timer->context.ocp_cfg); @@ -262,7 +309,7 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer) dmtimer_write(timer, OMAP_TIMER_CTRL_REG, timer->context.tclr); } -static void omap_timer_save_context(struct omap_dm_timer *timer) +static void omap_timer_save_context(struct dmtimer *timer) { timer->context.ocp_cfg = dmtimer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET); @@ -277,9 +324,9 @@ static void omap_timer_save_context(struct omap_dm_timer *timer) static int omap_timer_context_notifier(struct notifier_block *nb, unsigned long cmd, void *v) { - struct omap_dm_timer *timer; + struct dmtimer *timer; - timer = container_of(nb, struct omap_dm_timer, nb); + timer = container_of(nb, struct dmtimer, nb); switch (cmd) { case CPU_CLUSTER_PM_ENTER: @@ -301,7 +348,7 @@ static int omap_timer_context_notifier(struct notifier_block *nb, return NOTIFY_OK; } -static int omap_dm_timer_reset(struct omap_dm_timer *timer) +static int omap_dm_timer_reset(struct dmtimer *timer) { u32 l, timeout = 100000; @@ -329,13 +376,29 @@ static int omap_dm_timer_reset(struct omap_dm_timer *timer) return 0; } -static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) +/* + * Functions exposed to PWM and remoteproc drivers via platform_data. + * Do not use these in the driver, these will get deprecated and will + * will be replaced by Linux generic framework functions such as + * chained interrupts and clock framework. + */ +static struct dmtimer *to_dmtimer(struct omap_dm_timer *cookie) +{ + if (!cookie) + return NULL; + + return container_of(cookie, struct dmtimer, cookie); +} + +static int omap_dm_timer_set_source(struct omap_dm_timer *cookie, int source) { int ret; const char *parent_name; struct clk *parent; struct dmtimer_platform_data *pdata; + struct dmtimer *timer; + timer = to_dmtimer(cookie); if (unlikely(!timer) || IS_ERR(timer->fclk)) return -EINVAL; @@ -385,8 +448,9 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) return ret; } -static void omap_dm_timer_enable(struct omap_dm_timer *timer) +static void omap_dm_timer_enable(struct omap_dm_timer *cookie) { + struct dmtimer *timer = to_dmtimer(cookie); struct device *dev = &timer->pdev->dev; int rc; @@ -395,14 +459,15 @@ static void omap_dm_timer_enable(struct omap_dm_timer *timer) dev_err(dev, "could not enable timer\n"); } -static void omap_dm_timer_disable(struct omap_dm_timer *timer) +static void omap_dm_timer_disable(struct omap_dm_timer *cookie) { + struct dmtimer *timer = to_dmtimer(cookie); struct device *dev = &timer->pdev->dev; pm_runtime_put_sync(dev); } -static int omap_dm_timer_prepare(struct omap_dm_timer *timer) +static int omap_dm_timer_prepare(struct dmtimer *timer) { struct device *dev = &timer->pdev->dev; int rc; @@ -442,9 +507,9 @@ static inline u32 omap_dm_timer_reserved_systimer(int id) return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0; } -static struct omap_dm_timer *_omap_dm_timer_request(int req_type, void *data) +static struct dmtimer *_omap_dm_timer_request(int req_type, void *data) { - struct omap_dm_timer *timer = NULL, *t; + struct dmtimer *timer = NULL, *t; struct device_node *np = NULL; unsigned long flags; u32 cap = 0; @@ -528,11 +593,19 @@ found: static struct omap_dm_timer *omap_dm_timer_request(void) { - return _omap_dm_timer_request(REQUEST_ANY, NULL); + struct dmtimer *timer; + + timer = _omap_dm_timer_request(REQUEST_ANY, NULL); + if (!timer) + return NULL; + + return &timer->cookie; } static struct omap_dm_timer *omap_dm_timer_request_specific(int id) { + struct dmtimer *timer; + /* Requesting timer by ID is not supported when device tree is used */ if (of_have_populated_dt()) { pr_warn("%s: Please use omap_dm_timer_request_by_node()\n", @@ -540,7 +613,11 @@ static struct omap_dm_timer *omap_dm_timer_request_specific(int id) return NULL; } - return _omap_dm_timer_request(REQUEST_BY_ID, &id); + timer = _omap_dm_timer_request(REQUEST_BY_ID, &id); + if (!timer) + return NULL; + + return &timer->cookie; } /** @@ -552,14 +629,23 @@ static struct omap_dm_timer *omap_dm_timer_request_specific(int id) */ static struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np) { + struct dmtimer *timer; + if (!np) return NULL; - return _omap_dm_timer_request(REQUEST_BY_NODE, np); + timer = _omap_dm_timer_request(REQUEST_BY_NODE, np); + if (!timer) + return NULL; + + return &timer->cookie; } -static int omap_dm_timer_free(struct omap_dm_timer *timer) +static int omap_dm_timer_free(struct omap_dm_timer *cookie) { + struct dmtimer *timer; + + timer = to_dmtimer(cookie); if (unlikely(!timer)) return -EINVAL; @@ -570,8 +656,9 @@ static int omap_dm_timer_free(struct omap_dm_timer *timer) return 0; } -int omap_dm_timer_get_irq(struct omap_dm_timer *timer) +int omap_dm_timer_get_irq(struct omap_dm_timer *cookie) { + struct dmtimer *timer = to_dmtimer(cookie); if (timer) return timer->irq; return -EINVAL; @@ -580,7 +667,7 @@ int omap_dm_timer_get_irq(struct omap_dm_timer *timer) #if defined(CONFIG_ARCH_OMAP1) #include -static struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) +static struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *cookie) { return NULL; } @@ -592,7 +679,7 @@ static struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) { int i = 0; - struct omap_dm_timer *timer = NULL; + struct dmtimer *timer = NULL; unsigned long flags; /* If ARMXOR cannot be idled this function call is unnecessary */ @@ -620,8 +707,10 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) #else -static struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) +static struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *cookie) { + struct dmtimer *timer = to_dmtimer(cookie); + if (timer && !IS_ERR(timer->fclk)) return timer->fclk; return NULL; @@ -636,15 +725,19 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) #endif -static int omap_dm_timer_start(struct omap_dm_timer *timer) +static int omap_dm_timer_start(struct omap_dm_timer *cookie) { - struct device *dev = &timer->pdev->dev; + struct dmtimer *timer; + struct device *dev; int rc; u32 l; + timer = to_dmtimer(cookie); if (unlikely(!timer)) return -EINVAL; + dev = &timer->pdev->dev; + rc = pm_runtime_resume_and_get(dev); if (rc) return rc; @@ -658,14 +751,18 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer) return 0; } -static int omap_dm_timer_stop(struct omap_dm_timer *timer) +static int omap_dm_timer_stop(struct omap_dm_timer *cookie) { - struct device *dev = &timer->pdev->dev; + struct dmtimer *timer; + struct device *dev; unsigned long rate = 0; + timer = to_dmtimer(cookie); if (unlikely(!timer)) return -EINVAL; + dev = &timer->pdev->dev; + if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) rate = clk_get_rate(timer->fclk); @@ -676,12 +773,14 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer) return 0; } -static int omap_dm_timer_set_load(struct omap_dm_timer *timer, +static int omap_dm_timer_set_load(struct omap_dm_timer *cookie, unsigned int load) { + struct dmtimer *timer; struct device *dev; int rc; + timer = to_dmtimer(cookie); if (unlikely(!timer)) return -EINVAL; @@ -697,13 +796,15 @@ static int omap_dm_timer_set_load(struct omap_dm_timer *timer, return 0; } -static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, +static int omap_dm_timer_set_match(struct omap_dm_timer *cookie, int enable, unsigned int match) { + struct dmtimer *timer; struct device *dev; int rc; u32 l; + timer = to_dmtimer(cookie); if (unlikely(!timer)) return -EINVAL; @@ -725,13 +826,15 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, return 0; } -static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, +static int omap_dm_timer_set_pwm(struct omap_dm_timer *cookie, int def_on, int toggle, int trigger, int autoreload) { + struct dmtimer *timer; struct device *dev; int rc; u32 l; + timer = to_dmtimer(cookie); if (unlikely(!timer)) return -EINVAL; @@ -757,12 +860,14 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, return 0; } -static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *timer) +static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *cookie) { + struct dmtimer *timer; struct device *dev; int rc; u32 l; + timer = to_dmtimer(cookie); if (unlikely(!timer)) return -EINVAL; @@ -778,13 +883,15 @@ static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *timer) return l; } -static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, - int prescaler) +static int omap_dm_timer_set_prescaler(struct omap_dm_timer *cookie, + int prescaler) { + struct dmtimer *timer; struct device *dev; int rc; u32 l; + timer = to_dmtimer(cookie); if (unlikely(!timer) || prescaler < -1 || prescaler > 7) return -EINVAL; @@ -806,12 +913,14 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, return 0; } -static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, +static int omap_dm_timer_set_int_enable(struct omap_dm_timer *cookie, unsigned int value) { + struct dmtimer *timer; struct device *dev; int rc; + timer = to_dmtimer(cookie); if (unlikely(!timer)) return -EINVAL; @@ -834,12 +943,14 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, * * Disables the specified timer interrupts for a timer. */ -static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask) +static int omap_dm_timer_set_int_disable(struct omap_dm_timer *cookie, u32 mask) { + struct dmtimer *timer; struct device *dev; u32 l = mask; int rc; + timer = to_dmtimer(cookie); if (unlikely(!timer)) return -EINVAL; @@ -860,10 +971,12 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask) return 0; } -static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) +static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *cookie) { + struct dmtimer *timer; unsigned int l; + timer = to_dmtimer(cookie); if (unlikely(!timer || !atomic_read(&timer->enabled))) { pr_err("%s: timer not available or enabled.\n", __func__); return 0; @@ -874,8 +987,11 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) return l; } -static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) +static int omap_dm_timer_write_status(struct omap_dm_timer *cookie, unsigned int value) { + struct dmtimer *timer; + + timer = to_dmtimer(cookie); if (unlikely(!timer || !atomic_read(&timer->enabled))) return -EINVAL; @@ -884,8 +1000,11 @@ static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int return 0; } -static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) +static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *cookie) { + struct dmtimer *timer; + + timer = to_dmtimer(cookie); if (unlikely(!timer || !atomic_read(&timer->enabled))) { pr_err("%s: timer not iavailable or enabled.\n", __func__); return 0; @@ -894,8 +1013,11 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) return __omap_dm_timer_read_counter(timer); } -static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) +static int omap_dm_timer_write_counter(struct omap_dm_timer *cookie, unsigned int value) { + struct dmtimer *timer; + + timer = to_dmtimer(cookie); if (unlikely(!timer || !atomic_read(&timer->enabled))) { pr_err("%s: timer not available or enabled.\n", __func__); return -EINVAL; @@ -910,7 +1032,7 @@ static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev) { - struct omap_dm_timer *timer = dev_get_drvdata(dev); + struct dmtimer *timer = dev_get_drvdata(dev); atomic_set(&timer->enabled, 0); @@ -924,7 +1046,7 @@ static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev) static int __maybe_unused omap_dm_timer_runtime_resume(struct device *dev) { - struct omap_dm_timer *timer = dev_get_drvdata(dev); + struct dmtimer *timer = dev_get_drvdata(dev); if (!(timer->capability & OMAP_TIMER_ALWON) && timer->func_base) omap_timer_restore_context(timer); @@ -951,7 +1073,7 @@ static const struct of_device_id omap_timer_match[]; static int omap_dm_timer_probe(struct platform_device *pdev) { unsigned long flags; - struct omap_dm_timer *timer; + struct dmtimer *timer; struct device *dev = &pdev->dev; const struct dmtimer_platform_data *pdata; int ret; @@ -1043,7 +1165,7 @@ err_disable: */ static int omap_dm_timer_remove(struct platform_device *pdev) { - struct omap_dm_timer *timer; + struct dmtimer *timer; unsigned long flags; int ret = -EINVAL; diff --git a/include/clocksource/timer-ti-dm.h b/include/clocksource/timer-ti-dm.h index df3c6c88264f..77eceeae708c 100644 --- a/include/clocksource/timer-ti-dm.h +++ b/include/clocksource/timer-ti-dm.h @@ -59,50 +59,7 @@ #define OMAP_TIMER_NEEDS_RESET 0x10000000 #define OMAP_TIMER_HAS_DSP_IRQ 0x08000000 -struct timer_regs { - u32 ocp_cfg; - u32 tidr; - u32 tier; - u32 twer; - u32 tclr; - u32 tcrr; - u32 tldr; - u32 ttrg; - u32 twps; - u32 tmar; - u32 tcar1; - u32 tsicr; - u32 tcar2; - u32 tpir; - u32 tnir; - u32 tcvr; - u32 tocr; - u32 towr; -}; - struct omap_dm_timer { - int id; - int irq; - struct clk *fclk; - - void __iomem *io_base; - int irq_stat; /* TISR/IRQSTATUS interrupt status */ - int irq_ena; /* irq enable */ - int irq_dis; /* irq disable, only on v2 ip */ - void __iomem *pend; /* write pending */ - void __iomem *func_base; /* function register base */ - - atomic_t enabled; - unsigned long rate; - unsigned reserved:1; - unsigned posted:1; - struct timer_regs context; - int revision; - u32 capability; - u32 errata; - struct platform_device *pdev; - struct list_head node; - struct notifier_block nb; }; int omap_dm_timer_get_irq(struct omap_dm_timer *timer); -- cgit v1.2.3 From 664ad59da11687ef9b518fc2519af6a71a1db9f1 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 15 Aug 2022 16:12:49 +0300 Subject: clocksource/drivers/timer-ti-dm: Add flag to detect omap1 Let's make it clear that some features need to be tested currently on omap1. Only omap1 still uses platform_data. Signed-off-by: Tony Lindgren Reviewed-by: Janusz Krzysztofik Link: https://lore.kernel.org/r/20220815131250.34603-9-tony@atomide.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-ti-dm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index 0d0130ec4d1c..2310f973fec6 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -133,6 +133,7 @@ struct dmtimer { unsigned long rate; unsigned reserved:1; unsigned posted:1; + unsigned omap1:1; struct timer_regs context; int revision; u32 capability; @@ -423,7 +424,7 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *cookie, int source) * use the clock framework to set the parent clock. To be removed * once OMAP1 migrated to using clock framework for dmtimers */ - if (pdata && pdata->set_timer_src) + if (timer->omap1 && pdata && pdata->set_timer_src) return pdata->set_timer_src(timer->pdev, source); #if defined(CONFIG_COMMON_CLK) @@ -476,7 +477,7 @@ static int omap_dm_timer_prepare(struct dmtimer *timer) * FIXME: OMAP1 devices do not use the clock framework for dmtimers so * do not call clk_get() for these devices. */ - if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) { + if (!timer->omap1) { timer->fclk = clk_get(&timer->pdev->dev, "fck"); if (WARN_ON_ONCE(IS_ERR(timer->fclk))) { dev_err(&timer->pdev->dev, ": No fclk handle.\n"); @@ -763,7 +764,7 @@ static int omap_dm_timer_stop(struct omap_dm_timer *cookie) dev = &timer->pdev->dev; - if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) + if (!timer->omap1) rate = clk_get_rate(timer->fclk); __omap_dm_timer_stop(timer, rate); @@ -1119,6 +1120,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev) timer->reserved = omap_dm_timer_reserved_systimer(timer->id); } + timer->omap1 = timer->capability & OMAP_TIMER_NEEDS_RESET; + if (!(timer->capability & OMAP_TIMER_ALWON)) { timer->nb.notifier_call = omap_timer_context_notifier; cpu_pm_register_notifier(&timer->nb); -- cgit v1.2.3 From 789d4b1070261fa98b06384d2067f23c080dc9f1 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 15 Aug 2022 16:12:50 +0300 Subject: clocksource/drivers/timer-ti-dm: Get clock in probe with devm_clk_get() We can simplify the code a bit by getting the clock in probe, and using devm_clk_get(). This will also make further changes easier as the clock is available in probe instead of prepare. Signed-off-by: Tony Lindgren Reviewed-by: Janusz Krzysztofik Link: https://lore.kernel.org/r/20220815131250.34603-10-tony@atomide.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-ti-dm.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index 2310f973fec6..cad29ded3a48 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -473,18 +473,6 @@ static int omap_dm_timer_prepare(struct dmtimer *timer) struct device *dev = &timer->pdev->dev; int rc; - /* - * FIXME: OMAP1 devices do not use the clock framework for dmtimers so - * do not call clk_get() for these devices. - */ - if (!timer->omap1) { - timer->fclk = clk_get(&timer->pdev->dev, "fck"); - if (WARN_ON_ONCE(IS_ERR(timer->fclk))) { - dev_err(&timer->pdev->dev, ": No fclk handle.\n"); - return -EINVAL; - } - } - rc = pm_runtime_resume_and_get(dev); if (rc) return rc; @@ -650,8 +638,6 @@ static int omap_dm_timer_free(struct omap_dm_timer *cookie) if (unlikely(!timer)) return -EINVAL; - clk_put(timer->fclk); - WARN_ON(!timer->reserved); timer->reserved = 0; return 0; @@ -1098,7 +1084,6 @@ static int omap_dm_timer_probe(struct platform_device *pdev) if (timer->irq < 0) return timer->irq; - timer->fclk = ERR_PTR(-ENODEV); timer->io_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(timer->io_base)) return PTR_ERR(timer->io_base); @@ -1122,6 +1107,15 @@ static int omap_dm_timer_probe(struct platform_device *pdev) timer->omap1 = timer->capability & OMAP_TIMER_NEEDS_RESET; + /* OMAP1 devices do not yet use the clock framework for dmtimers */ + if (!timer->omap1) { + timer->fclk = devm_clk_get(dev, "fck"); + if (IS_ERR(timer->fclk)) + return PTR_ERR(timer->fclk); + } else { + timer->fclk = ERR_PTR(-ENODEV); + } + if (!(timer->capability & OMAP_TIMER_ALWON)) { timer->nb.notifier_call = omap_timer_context_notifier; cpu_pm_register_notifier(&timer->nb); -- cgit v1.2.3 From 27b30995b75d1e79360c164ba179bca86ab76ba6 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 2 Sep 2022 19:12:07 +0800 Subject: clocksource/drivers/imx-sysctr: handle nxp,no-divider property The previous hardware design embedds a internal divider for base clock. New design not has that divider, so check the nxp,no-divider property, if true, directly use base clock input, otherwise divide by 3 as before. Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20220902111207.2902493-3-peng.fan@oss.nxp.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/timer-imx-sysctr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/timer-imx-sysctr.c b/drivers/clocksource/timer-imx-sysctr.c index 523e37662a6e..5a7a951c4efc 100644 --- a/drivers/clocksource/timer-imx-sysctr.c +++ b/drivers/clocksource/timer-imx-sysctr.c @@ -134,8 +134,10 @@ static int __init sysctr_timer_init(struct device_node *np) if (ret) return ret; - /* system counter clock is divided by 3 internally */ - to_sysctr.of_clk.rate /= SYS_CTR_CLK_DIV; + if (!of_property_read_bool(np, "nxp,no-divider")) { + /* system counter clock is divided by 3 internally */ + to_sysctr.of_clk.rate /= SYS_CTR_CLK_DIV; + } sys_ctr_base = timer_of_base(&to_sysctr); cmpcr = readl(sys_ctr_base + CMPCR); -- cgit v1.2.3 From af246cc6d0ed11318223606128bb0b09866c4c08 Mon Sep 17 00:00:00 2001 From: Yang Guo Date: Tue, 27 Sep 2022 11:32:21 +0800 Subject: clocksource/drivers/arm_arch_timer: Fix CNTPCT_LO and CNTVCT_LO value CNTPCT_LO and CNTVCT_LO are defined by mistake in commit '8b82c4f883a7', so fix them according to the Arm ARM DDI 0487I.a, Table I2-4 "CNTBaseN memory map" as follows: Offset Register Type Description 0x000 CNTPCT[31:0] RO Physical Count register. 0x004 CNTPCT[63:32] RO 0x008 CNTVCT[31:0] RO Virtual Count register. 0x00C CNTVCT[63:32] RO Fixes: 8b82c4f883a7 ("clocksource/drivers/arm_arch_timer: Move MMIO timer programming over to CVAL") Cc: stable@vger.kernel.org Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: Marc Zyngier Cc: Mark Rutland Acked-by: Marc Zyngier Signed-off-by: Yang Guo Signed-off-by: Shaokun Zhang Link: https://lore.kernel.org/r/20220927033221.49589-1-zhangshaokun@hisilicon.com Signed-off-by: Daniel Lezcano --- drivers/clocksource/arm_arch_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index ff935efb6a88..a7ff77550e17 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -44,8 +44,8 @@ #define CNTACR_RWVT BIT(4) #define CNTACR_RWPT BIT(5) -#define CNTVCT_LO 0x00 -#define CNTPCT_LO 0x08 +#define CNTPCT_LO 0x00 +#define CNTVCT_LO 0x08 #define CNTFRQ 0x10 #define CNTP_CVAL_LO 0x20 #define CNTP_CTL 0x2c -- cgit v1.2.3