Merge tag 'timers-core-2024-03-23' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 23 Mar 2024 21:42:45 +0000 (14:42 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 23 Mar 2024 21:42:45 +0000 (14:42 -0700)
Pull more clocksource updates from Thomas Gleixner:
 "A set of updates for clocksource and clockevent drivers:

   - A fix for the prescaler of the ARM global timer where the prescaler
     mask define only covered 4 bits while it is actully 8 bits wide.
     This obviously restricted the possible range of prescaler
     adjustments

   - A fix for the RISC-V timer which prevents a timer interrupt being
     raised while the timer is initialized

   - A set of device tree updates to support new system on chips in
     various drivers

   - Kernel-doc and other cleanups all over the place"

* tag 'timers-core-2024-03-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  clocksource/drivers/timer-riscv: Clear timer interrupt on timer initialization
  dt-bindings: timer: Add support for cadence TTC PWM
  clocksource/drivers/arm_global_timer: Simplify prescaler register access
  clocksource/drivers/arm_global_timer: Guard against division by zero
  clocksource/drivers/arm_global_timer: Make gt_target_rate unsigned long
  dt-bindings: timer: add Ralink SoCs system tick counter
  clocksource: arm_global_timer: fix non-kernel-doc comment
  clocksource/drivers/arm_global_timer: Remove stray tab
  clocksource/drivers/arm_global_timer: Fix maximum prescaler value
  clocksource/drivers/imx-sysctr: Add i.MX95 support
  clocksource/drivers/imx-sysctr: Drop use global variables
  dt-bindings: timer: nxp,sysctr-timer: support i.MX95
  dt-bindings: timer: renesas: ostm: Document RZ/Five SoC
  dt-bindings: timer: renesas,tmu: Document input capture interrupt
  clocksource/drivers/ti-32K: Fix misuse of "/**" comment
  clocksource/drivers/stm32: Fix all kernel-doc warnings
  dt-bindings: timer: exynos4210-mct: Add google,gs101-mct compatible
  clocksource/drivers/imx: Fix -Wunused-but-set-variable warning

12 files changed:
Documentation/devicetree/bindings/timer/cdns,ttc.yaml
Documentation/devicetree/bindings/timer/nxp,sysctr-timer.yaml
Documentation/devicetree/bindings/timer/ralink,cevt-systick.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/timer/renesas,ostm.yaml
Documentation/devicetree/bindings/timer/renesas,tmu.yaml
Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.yaml
drivers/clocksource/arm_global_timer.c
drivers/clocksource/timer-imx-gpt.c
drivers/clocksource/timer-imx-sysctr.c
drivers/clocksource/timer-riscv.c
drivers/clocksource/timer-stm32.c
drivers/clocksource/timer-ti-32k.c

index dbba780c9b0213ee08bb9ed7568431bce200aeef..da342464d32ed2ff5c2b9ee29a36931edb989996 100644 (file)
@@ -32,12 +32,23 @@ properties:
     description: |
       Bit width of the timer, necessary if not 16.
 
+  "#pwm-cells":
+    const: 3
+
 required:
   - compatible
   - reg
-  - interrupts
   - clocks
 
+allOf:
+  - if:
+      not:
+        required:
+          - "#pwm-cells"
+    then:
+      required:
+        - interrupts
+
 additionalProperties: false
 
 examples:
@@ -50,3 +61,12 @@ examples:
         clocks = <&cpu_clk 3>;
         timer-width = <32>;
     };
+
+  - |
+    pwm: pwm@f8002000 {
+        compatible = "cdns,ttc";
+        reg = <0xf8002000 0x1000>;
+        clocks = <&cpu_clk 3>;
+        timer-width = <32>;
+        #pwm-cells = <3>;
+    };
index 2b9653dafab8f3380d60f942ef04f29a14e34bb8..891cca00952815b000aeaf41660354960e4233e4 100644 (file)
@@ -18,7 +18,9 @@ description: |
 
 properties:
   compatible:
-    const: nxp,sysctr-timer
+    enum:
+      - nxp,imx95-sysctr-timer
+      - nxp,sysctr-timer
 
   reg:
     maxItems: 1
diff --git a/Documentation/devicetree/bindings/timer/ralink,cevt-systick.yaml b/Documentation/devicetree/bindings/timer/ralink,cevt-systick.yaml
new file mode 100644 (file)
index 0000000..59d97fe
--- /dev/null
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/timer/ralink,cevt-systick.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: System tick counter present in Ralink family SoCs
+
+maintainers:
+  - Sergio Paracuellos <sergio.paracuellos@gmail.com>
+
+properties:
+  compatible:
+    const: ralink,cevt-systick
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    systick@d00 {
+        compatible = "ralink,cevt-systick";
+        reg = <0xd00 0x10>;
+
+        interrupt-parent = <&cpuintc>;
+        interrupts = <7>;
+    };
+...
index 7207929e5cd6a7a2db7e0146acfd61979ce734f1..8b06a681764e3b5dfedf7b41d7e87b12f5d083a9 100644 (file)
@@ -23,7 +23,7 @@ properties:
       - enum:
           - renesas,r7s72100-ostm  # RZ/A1H
           - renesas,r7s9210-ostm   # RZ/A2M
-          - renesas,r9a07g043-ostm # RZ/G2UL
+          - renesas,r9a07g043-ostm # RZ/G2UL and RZ/Five
           - renesas,r9a07g044-ostm # RZ/G2{L,LC}
           - renesas,r9a07g054-ostm # RZ/V2L
       - const: renesas,ostm        # Generic
index a67e427a9e7e22aa81d2efe987fec304d6feb41e..84bbe15028a1de941e38f4510500a43d4be88d68 100644 (file)
@@ -46,7 +46,19 @@ properties:
 
   interrupts:
     minItems: 2
-    maxItems: 3
+    items:
+      - description: Underflow interrupt, channel 0
+      - description: Underflow interrupt, channel 1
+      - description: Underflow interrupt, channel 2
+      - description: Input capture interrupt, channel 2
+
+  interrupt-names:
+    minItems: 2
+    items:
+      - const: tuni0
+      - const: tuni1
+      - const: tuni2
+      - const: ticpi2
 
   clocks:
     maxItems: 1
@@ -100,7 +112,9 @@ examples:
             reg = <0xffd80000 0x30>;
             interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
                          <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
-                         <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+                         <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "tuni0", "tuni1", "tuni2", "ticpi2";
             clocks = <&mstp0_clks R8A7779_CLK_TMU0>;
             clock-names = "fck";
             power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
index 829bd2227f7c9c64a86417af3dc5c6057bba9234..774b7992a0cafca8222220d6982726fa6ca217d7 100644 (file)
@@ -26,6 +26,7 @@ properties:
       - items:
           - enum:
               - axis,artpec8-mct
+              - google,gs101-mct
               - samsung,exynos3250-mct
               - samsung,exynos5250-mct
               - samsung,exynos5260-mct
@@ -127,6 +128,7 @@ allOf:
           contains:
             enum:
               - axis,artpec8-mct
+              - google,gs101-mct
               - samsung,exynos5260-mct
               - samsung,exynos5420-mct
               - samsung,exynos5433-mct
index 44a61dc6f93208c897f1379cbb1371191d29d7b4..ab1c8c2b66b887a8149d1dbc1d6d41428e22c7e9 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/bitfield.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/cpu.h>
 #define GT_CONTROL_COMP_ENABLE         BIT(1)  /* banked */
 #define GT_CONTROL_IRQ_ENABLE          BIT(2)  /* banked */
 #define GT_CONTROL_AUTO_INC            BIT(3)  /* banked */
-#define GT_CONTROL_PRESCALER_SHIFT      8
-#define GT_CONTROL_PRESCALER_MAX        0xF
-#define GT_CONTROL_PRESCALER_MASK       (GT_CONTROL_PRESCALER_MAX << \
-                                        GT_CONTROL_PRESCALER_SHIFT)
+#define GT_CONTROL_PRESCALER_MASK      GENMASK(15, 8)
 
 #define GT_INT_STATUS  0x0c
 #define GT_INT_STATUS_EVENT_FLAG       BIT(0)
@@ -52,7 +50,8 @@
  */
 static void __iomem *gt_base;
 static struct notifier_block gt_clk_rate_change_nb;
-static u32 gt_psv_new, gt_psv_bck, gt_target_rate;
+static u32 gt_psv_new, gt_psv_bck;
+static unsigned long gt_target_rate;
 static int gt_ppi;
 static struct clock_event_device __percpu *gt_evt;
 
@@ -88,7 +87,7 @@ static u64 gt_counter_read(void)
        return _gt_counter_read();
 }
 
-/**
+/*
  * To ensure that updates to comparator value register do not set the
  * Interrupt Status Register proceed as follows:
  * 1. Clear the Comp Enable bit in the Timer Control Register.
@@ -247,7 +246,7 @@ static void gt_write_presc(u32 psv)
 
        reg = readl(gt_base + GT_CONTROL);
        reg &= ~GT_CONTROL_PRESCALER_MASK;
-       reg |= psv << GT_CONTROL_PRESCALER_SHIFT;
+       reg |= FIELD_PREP(GT_CONTROL_PRESCALER_MASK, psv);
        writel(reg, gt_base + GT_CONTROL);
 }
 
@@ -256,8 +255,7 @@ static u32 gt_read_presc(void)
        u32 reg;
 
        reg = readl(gt_base + GT_CONTROL);
-       reg &= GT_CONTROL_PRESCALER_MASK;
-       return reg >> GT_CONTROL_PRESCALER_SHIFT;
+       return FIELD_GET(GT_CONTROL_PRESCALER_MASK, reg);
 }
 
 static void __init gt_delay_timer_init(void)
@@ -272,9 +270,9 @@ static int __init gt_clocksource_init(void)
        writel(0, gt_base + GT_COUNTER0);
        writel(0, gt_base + GT_COUNTER1);
        /* set prescaler and enable timer on all the cores */
-       writel(((CONFIG_ARM_GT_INITIAL_PRESCALER_VAL - 1) <<
-               GT_CONTROL_PRESCALER_SHIFT)
-              GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
+       writel(FIELD_PREP(GT_CONTROL_PRESCALER_MASK,
+                         CONFIG_ARM_GT_INITIAL_PRESCALER_VAL - 1) |
+              GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
 
 #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
        sched_clock_register(gt_sched_clock_read, 64, gt_target_rate);
@@ -290,18 +288,17 @@ static int gt_clk_rate_change_cb(struct notifier_block *nb,
        switch (event) {
        case PRE_RATE_CHANGE:
        {
-               int psv;
-
-               psv = DIV_ROUND_CLOSEST(ndata->new_rate,
-                                       gt_target_rate);
+               unsigned long psv;
 
-               if (abs(gt_target_rate - (ndata->new_rate / psv)) > MAX_F_ERR)
+               psv = DIV_ROUND_CLOSEST(ndata->new_rate, gt_target_rate);
+               if (!psv ||
+                   abs(gt_target_rate - (ndata->new_rate / psv)) > MAX_F_ERR)
                        return NOTIFY_BAD;
 
                psv--;
 
                /* prescaler within legal range? */
-               if (psv < 0 || psv > GT_CONTROL_PRESCALER_MAX)
+               if (!FIELD_FIT(GT_CONTROL_PRESCALER_MASK, psv))
                        return NOTIFY_BAD;
 
                /*
@@ -411,7 +408,7 @@ static int __init global_timer_of_register(struct device_node *np)
        err = gt_clocksource_init();
        if (err)
                goto out_irq;
-       
+
        err = cpuhp_setup_state(CPUHP_AP_ARM_GLOBAL_TIMER_STARTING,
                                "clockevents/arm/global_timer:starting",
                                gt_starting_cpu, gt_dying_cpu);
index 6a878d227a13b59a7eca83468402cc0117a5eef6..489e69169ed4e3d31cae8e6931afa015b224b84d 100644 (file)
@@ -258,9 +258,8 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
 {
        struct clock_event_device *ced = dev_id;
        struct imx_timer *imxtm = to_imx_timer(ced);
-       uint32_t tstat;
 
-       tstat = readl_relaxed(imxtm->base + imxtm->gpt->reg_tstat);
+       readl_relaxed(imxtm->base + imxtm->gpt->reg_tstat);
 
        imxtm->gpt->gpt_irq_acknowledge(imxtm);
 
index 5a7a951c4efcdf187e73e2190b27dcea943f97bc..44525813be1e285713eb32166de21e78f2bf2e50 100644 (file)
@@ -4,48 +4,62 @@
 
 #include <linux/interrupt.h>
 #include <linux/clockchips.h>
+#include <linux/slab.h>
 
 #include "timer-of.h"
 
 #define CMP_OFFSET     0x10000
+#define RD_OFFSET      0x20000
 
 #define CNTCV_LO       0x8
 #define CNTCV_HI       0xc
 #define CMPCV_LO       (CMP_OFFSET + 0x20)
 #define CMPCV_HI       (CMP_OFFSET + 0x24)
 #define CMPCR          (CMP_OFFSET + 0x2c)
+#define CNTCV_LO_IMX95 (RD_OFFSET + 0x8)
+#define CNTCV_HI_IMX95 (RD_OFFSET + 0xc)
 
 #define SYS_CTR_EN             0x1
 #define SYS_CTR_IRQ_MASK       0x2
 
 #define SYS_CTR_CLK_DIV                0x3
 
-static void __iomem *sys_ctr_base __ro_after_init;
-static u32 cmpcr __ro_after_init;
+struct sysctr_private {
+       u32 cmpcr;
+       u32 lo_off;
+       u32 hi_off;
+};
 
-static void sysctr_timer_enable(bool enable)
+static void sysctr_timer_enable(struct clock_event_device *evt, bool enable)
 {
-       writel(enable ? cmpcr | SYS_CTR_EN : cmpcr, sys_ctr_base + CMPCR);
+       struct timer_of *to = to_timer_of(evt);
+       struct sysctr_private *priv = to->private_data;
+       void __iomem *base = timer_of_base(to);
+
+       writel(enable ? priv->cmpcr | SYS_CTR_EN : priv->cmpcr, base + CMPCR);
 }
 
-static void sysctr_irq_acknowledge(void)
+static void sysctr_irq_acknowledge(struct clock_event_device *evt)
 {
        /*
         * clear the enable bit(EN =0) will clear
         * the status bit(ISTAT = 0), then the interrupt
         * signal will be negated(acknowledged).
         */
-       sysctr_timer_enable(false);
+       sysctr_timer_enable(evt, false);
 }
 
-static inline u64 sysctr_read_counter(void)
+static inline u64 sysctr_read_counter(struct clock_event_device *evt)
 {
+       struct timer_of *to = to_timer_of(evt);
+       struct sysctr_private *priv = to->private_data;
+       void __iomem *base = timer_of_base(to);
        u32 cnt_hi, tmp_hi, cnt_lo;
 
        do {
-               cnt_hi = readl_relaxed(sys_ctr_base + CNTCV_HI);
-               cnt_lo = readl_relaxed(sys_ctr_base + CNTCV_LO);
-               tmp_hi = readl_relaxed(sys_ctr_base + CNTCV_HI);
+               cnt_hi = readl_relaxed(base + priv->hi_off);
+               cnt_lo = readl_relaxed(base + priv->lo_off);
+               tmp_hi = readl_relaxed(base + priv->hi_off);
        } while (tmp_hi != cnt_hi);
 
        return  ((u64) cnt_hi << 32) | cnt_lo;
@@ -54,22 +68,24 @@ static inline u64 sysctr_read_counter(void)
 static int sysctr_set_next_event(unsigned long delta,
                                 struct clock_event_device *evt)
 {
+       struct timer_of *to = to_timer_of(evt);
+       void __iomem *base = timer_of_base(to);
        u32 cmp_hi, cmp_lo;
        u64 next;
 
-       sysctr_timer_enable(false);
+       sysctr_timer_enable(evt, false);
 
-       next = sysctr_read_counter();
+       next = sysctr_read_counter(evt);
 
        next += delta;
 
        cmp_hi = (next >> 32) & 0x00fffff;
        cmp_lo = next & 0xffffffff;
 
-       writel_relaxed(cmp_hi, sys_ctr_base + CMPCV_HI);
-       writel_relaxed(cmp_lo, sys_ctr_base + CMPCV_LO);
+       writel_relaxed(cmp_hi, base + CMPCV_HI);
+       writel_relaxed(cmp_lo, base + CMPCV_LO);
 
-       sysctr_timer_enable(true);
+       sysctr_timer_enable(evt, true);
 
        return 0;
 }
@@ -81,7 +97,7 @@ static int sysctr_set_state_oneshot(struct clock_event_device *evt)
 
 static int sysctr_set_state_shutdown(struct clock_event_device *evt)
 {
-       sysctr_timer_enable(false);
+       sysctr_timer_enable(evt, false);
 
        return 0;
 }
@@ -90,7 +106,7 @@ static irqreturn_t sysctr_timer_interrupt(int irq, void *dev_id)
 {
        struct clock_event_device *evt = dev_id;
 
-       sysctr_irq_acknowledge();
+       sysctr_irq_acknowledge(evt);
 
        evt->event_handler(evt);
 
@@ -117,34 +133,75 @@ static struct timer_of to_sysctr = {
        },
 };
 
-static void __init sysctr_clockevent_init(void)
+static int __init __sysctr_timer_init(struct device_node *np)
 {
+       struct sysctr_private *priv;
+       void __iomem *base;
+       int ret;
+
+       priv = kzalloc(sizeof(struct sysctr_private), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       ret = timer_of_init(np, &to_sysctr);
+       if (ret) {
+               kfree(priv);
+               return ret;
+       }
+
+       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;
+       }
+
        to_sysctr.clkevt.cpumask = cpu_possible_mask;
+       to_sysctr.private_data = priv;
+
+       base = timer_of_base(&to_sysctr);
+       priv->cmpcr = readl(base + CMPCR) & ~SYS_CTR_EN;
+
+       return 0;
+}
+
+static int __init sysctr_timer_init(struct device_node *np)
+{
+       struct sysctr_private *priv;
+       int ret;
+
+       ret = __sysctr_timer_init(np);
+       if (ret)
+               return ret;
+
+       priv = to_sysctr.private_data;
+       priv->lo_off = CNTCV_LO;
+       priv->hi_off = CNTCV_HI;
 
        clockevents_config_and_register(&to_sysctr.clkevt,
                                        timer_of_rate(&to_sysctr),
                                        0xff, 0x7fffffff);
+
+       return 0;
 }
 
-static int __init sysctr_timer_init(struct device_node *np)
+static int __init sysctr_timer_imx95_init(struct device_node *np)
 {
-       int ret = 0;
+       struct sysctr_private *priv;
+       int ret;
 
-       ret = timer_of_init(np, &to_sysctr);
+       ret = __sysctr_timer_init(np);
        if (ret)
                return ret;
 
-       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);
-       cmpcr &= ~SYS_CTR_EN;
+       priv = to_sysctr.private_data;
+       priv->lo_off = CNTCV_LO_IMX95;
+       priv->hi_off = CNTCV_HI_IMX95;
 
-       sysctr_clockevent_init();
+       clockevents_config_and_register(&to_sysctr.clkevt,
+                                       timer_of_rate(&to_sysctr),
+                                       0xff, 0x7fffffff);
 
        return 0;
 }
+
 TIMER_OF_DECLARE(sysctr_timer, "nxp,sysctr-timer", sysctr_timer_init);
+TIMER_OF_DECLARE(sysctr_timer_imx95, "nxp,imx95-sysctr-timer", sysctr_timer_imx95_init);
index 87a7ac0ce6cec46e4b00fa06a90402f4e2ced9de..48ce50c5f5e68eeec9de696476d424dd5b2c00d0 100644 (file)
@@ -108,6 +108,9 @@ static int riscv_timer_starting_cpu(unsigned int cpu)
 {
        struct clock_event_device *ce = per_cpu_ptr(&riscv_clock_event, cpu);
 
+       /* Clear timer interrupt */
+       riscv_clock_event_stop();
+
        ce->cpumask = cpumask_of(cpu);
        ce->irq = riscv_clock_event_irq;
        if (riscv_timer_cannot_wake_cpu)
index c9a753f96ba12d50930ab242bec5eb5bce79fcfc..0a4ea3288bfbea7040c07dfe91e69f44da8cc8dd 100644 (file)
@@ -73,7 +73,7 @@ static void stm32_timer_of_bits_set(struct timer_of *to, int bits)
  * Accessor helper to get the number of bits in the timer-of private
  * structure.
  *
- * Returns an integer corresponding to the number of bits.
+ * Returns: an integer corresponding to the number of bits.
  */
 static int stm32_timer_of_bits_get(struct timer_of *to)
 {
@@ -177,7 +177,7 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
 }
 
 /**
- * stm32_timer_width - Sort out the timer width (32/16)
+ * stm32_timer_set_width - Sort out the timer width (32/16)
  * @to: a pointer to a timer-of structure
  *
  * Write the 32-bit max value and read/return the result. If the timer
index 59b0be482f32c668065ffd78c2e23ada53266748..a86529a707370d3ee5412191d432b71231677d60 100644 (file)
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/**
+/*
  * timer-ti-32k.c - OMAP2 32k Timer Support
  *
  * Copyright (C) 2009 Nokia Corporation