mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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
     restricted obviously the possible range of the 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.
 -----BEGIN PGP SIGNATURE-----
 
 iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmX/MDcTHHRnbHhAbGlu
 dXRyb25peC5kZQAKCRCmGPVMDXSYofUcD/9hZjJp11tNJNibLGjJrZUIg1Zpiu7c
 avlrG/KT9BgElyp8D4WG3GTY7ng9vzJ7XNXG5eXyrkMClzlDYmXt5oeoUM3KRFDg
 G/kX0ee/+vcP5IKVsYR3w1MQ7QGe7VfE5FU4CxtR3OjG3T5Gueim1AKBtM26QazK
 wHe1/yp0vIPjZO1awlWQm9CJ+DSD2Mb1oPo8c9Bitd5KXXjPg8uR3bk2kOVYMdzC
 B6xYvQWF3Pl7NXcQKOnIazqsNlphsYiBGc5ZbKp5zjDggmp/ChBedt6ePCccU3DO
 VXE6D4eyZ5hmQbFzSEZUYsWcNzkeH8ZWnxkjeAoG60Y2vErLVsceytaIja061VOl
 BP2j8QbQ7ztwLOTtZc8KwJsVfxBh1xhwAUwe5Mpl171m7K2n+zquR8Clq4SqL2DK
 mjUcHKIZzyhZ4HX3rRwVOpJmfbJlRxSRjiLp+oPulJBB9pLMjarxwQ6Ij68yrPst
 kVow4Ur45abmXsDRj3lc3+bDcfMr8AM3l/HjD7AZamC2TAvkp1hkYPghhazdolx5
 qQA3swdQl0tq49SNvvLbVRjRiCiQmUdpOGpnevvqxEO/BESGquVfPrihOYqIQuwh
 +yurmba5L8uxpsBCPtGfiMse9fbE7GVQJkMqhr9KNNOfER30rEe8bmqr6r71+uZJ
 19Jp2U76zNfVXA==
 =M9Gu
 -----END PGP SIGNATURE-----
Merge tag 'timers-core-2024-03-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
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
			
			
This commit is contained in:
		
						commit
						00164f477f
					
				
					 12 changed files with 193 additions and 61 deletions
				
			
		| 
						 | 
					@ -32,12 +32,23 @@ properties:
 | 
				
			||||||
    description: |
 | 
					    description: |
 | 
				
			||||||
      Bit width of the timer, necessary if not 16.
 | 
					      Bit width of the timer, necessary if not 16.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "#pwm-cells":
 | 
				
			||||||
 | 
					    const: 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
required:
 | 
					required:
 | 
				
			||||||
  - compatible
 | 
					  - compatible
 | 
				
			||||||
  - reg
 | 
					  - reg
 | 
				
			||||||
  - interrupts
 | 
					 | 
				
			||||||
  - clocks
 | 
					  - clocks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					allOf:
 | 
				
			||||||
 | 
					  - if:
 | 
				
			||||||
 | 
					      not:
 | 
				
			||||||
 | 
					        required:
 | 
				
			||||||
 | 
					          - "#pwm-cells"
 | 
				
			||||||
 | 
					    then:
 | 
				
			||||||
 | 
					      required:
 | 
				
			||||||
 | 
					        - interrupts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
additionalProperties: false
 | 
					additionalProperties: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
examples:
 | 
					examples:
 | 
				
			||||||
| 
						 | 
					@ -50,3 +61,12 @@ examples:
 | 
				
			||||||
        clocks = <&cpu_clk 3>;
 | 
					        clocks = <&cpu_clk 3>;
 | 
				
			||||||
        timer-width = <32>;
 | 
					        timer-width = <32>;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - |
 | 
				
			||||||
 | 
					    pwm: pwm@f8002000 {
 | 
				
			||||||
 | 
					        compatible = "cdns,ttc";
 | 
				
			||||||
 | 
					        reg = <0xf8002000 0x1000>;
 | 
				
			||||||
 | 
					        clocks = <&cpu_clk 3>;
 | 
				
			||||||
 | 
					        timer-width = <32>;
 | 
				
			||||||
 | 
					        #pwm-cells = <3>;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,9 @@ description: |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
properties:
 | 
					properties:
 | 
				
			||||||
  compatible:
 | 
					  compatible:
 | 
				
			||||||
    const: nxp,sysctr-timer
 | 
					    enum:
 | 
				
			||||||
 | 
					      - nxp,imx95-sysctr-timer
 | 
				
			||||||
 | 
					      - nxp,sysctr-timer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  reg:
 | 
					  reg:
 | 
				
			||||||
    maxItems: 1
 | 
					    maxItems: 1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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>;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					...
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ properties:
 | 
				
			||||||
      - enum:
 | 
					      - enum:
 | 
				
			||||||
          - renesas,r7s72100-ostm  # RZ/A1H
 | 
					          - renesas,r7s72100-ostm  # RZ/A1H
 | 
				
			||||||
          - renesas,r7s9210-ostm   # RZ/A2M
 | 
					          - 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,r9a07g044-ostm # RZ/G2{L,LC}
 | 
				
			||||||
          - renesas,r9a07g054-ostm # RZ/V2L
 | 
					          - renesas,r9a07g054-ostm # RZ/V2L
 | 
				
			||||||
      - const: renesas,ostm        # Generic
 | 
					      - const: renesas,ostm        # Generic
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,19 @@ properties:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  interrupts:
 | 
					  interrupts:
 | 
				
			||||||
    minItems: 2
 | 
					    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:
 | 
					  clocks:
 | 
				
			||||||
    maxItems: 1
 | 
					    maxItems: 1
 | 
				
			||||||
| 
						 | 
					@ -100,7 +112,9 @@ examples:
 | 
				
			||||||
            reg = <0xffd80000 0x30>;
 | 
					            reg = <0xffd80000 0x30>;
 | 
				
			||||||
            interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
 | 
					            interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
 | 
				
			||||||
                         <GIC_SPI 33 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>;
 | 
					            clocks = <&mstp0_clks R8A7779_CLK_TMU0>;
 | 
				
			||||||
            clock-names = "fck";
 | 
					            clock-names = "fck";
 | 
				
			||||||
            power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 | 
					            power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@ properties:
 | 
				
			||||||
      - items:
 | 
					      - items:
 | 
				
			||||||
          - enum:
 | 
					          - enum:
 | 
				
			||||||
              - axis,artpec8-mct
 | 
					              - axis,artpec8-mct
 | 
				
			||||||
 | 
					              - google,gs101-mct
 | 
				
			||||||
              - samsung,exynos3250-mct
 | 
					              - samsung,exynos3250-mct
 | 
				
			||||||
              - samsung,exynos5250-mct
 | 
					              - samsung,exynos5250-mct
 | 
				
			||||||
              - samsung,exynos5260-mct
 | 
					              - samsung,exynos5260-mct
 | 
				
			||||||
| 
						 | 
					@ -127,6 +128,7 @@ allOf:
 | 
				
			||||||
          contains:
 | 
					          contains:
 | 
				
			||||||
            enum:
 | 
					            enum:
 | 
				
			||||||
              - axis,artpec8-mct
 | 
					              - axis,artpec8-mct
 | 
				
			||||||
 | 
					              - google,gs101-mct
 | 
				
			||||||
              - samsung,exynos5260-mct
 | 
					              - samsung,exynos5260-mct
 | 
				
			||||||
              - samsung,exynos5420-mct
 | 
					              - samsung,exynos5420-mct
 | 
				
			||||||
              - samsung,exynos5433-mct
 | 
					              - samsung,exynos5433-mct
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/init.h>
 | 
					#include <linux/init.h>
 | 
				
			||||||
#include <linux/interrupt.h>
 | 
					#include <linux/interrupt.h>
 | 
				
			||||||
 | 
					#include <linux/bitfield.h>
 | 
				
			||||||
#include <linux/clocksource.h>
 | 
					#include <linux/clocksource.h>
 | 
				
			||||||
#include <linux/clockchips.h>
 | 
					#include <linux/clockchips.h>
 | 
				
			||||||
#include <linux/cpu.h>
 | 
					#include <linux/cpu.h>
 | 
				
			||||||
| 
						 | 
					@ -31,10 +32,7 @@
 | 
				
			||||||
#define GT_CONTROL_COMP_ENABLE		BIT(1)	/* banked */
 | 
					#define GT_CONTROL_COMP_ENABLE		BIT(1)	/* banked */
 | 
				
			||||||
#define GT_CONTROL_IRQ_ENABLE		BIT(2)	/* banked */
 | 
					#define GT_CONTROL_IRQ_ENABLE		BIT(2)	/* banked */
 | 
				
			||||||
#define GT_CONTROL_AUTO_INC		BIT(3)	/* banked */
 | 
					#define GT_CONTROL_AUTO_INC		BIT(3)	/* banked */
 | 
				
			||||||
#define GT_CONTROL_PRESCALER_SHIFT      8
 | 
					#define GT_CONTROL_PRESCALER_MASK	GENMASK(15, 8)
 | 
				
			||||||
#define GT_CONTROL_PRESCALER_MAX        0xF
 | 
					 | 
				
			||||||
#define GT_CONTROL_PRESCALER_MASK       (GT_CONTROL_PRESCALER_MAX << \
 | 
					 | 
				
			||||||
					 GT_CONTROL_PRESCALER_SHIFT)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define GT_INT_STATUS	0x0c
 | 
					#define GT_INT_STATUS	0x0c
 | 
				
			||||||
#define GT_INT_STATUS_EVENT_FLAG	BIT(0)
 | 
					#define GT_INT_STATUS_EVENT_FLAG	BIT(0)
 | 
				
			||||||
| 
						 | 
					@ -52,7 +50,8 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void __iomem *gt_base;
 | 
					static void __iomem *gt_base;
 | 
				
			||||||
static struct notifier_block gt_clk_rate_change_nb;
 | 
					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 int gt_ppi;
 | 
				
			||||||
static struct clock_event_device __percpu *gt_evt;
 | 
					static struct clock_event_device __percpu *gt_evt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +87,7 @@ static u64 gt_counter_read(void)
 | 
				
			||||||
	return _gt_counter_read();
 | 
						return _gt_counter_read();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/*
 | 
				
			||||||
 * To ensure that updates to comparator value register do not set the
 | 
					 * To ensure that updates to comparator value register do not set the
 | 
				
			||||||
 * Interrupt Status Register proceed as follows:
 | 
					 * Interrupt Status Register proceed as follows:
 | 
				
			||||||
 * 1. Clear the Comp Enable bit in the Timer Control Register.
 | 
					 * 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 = readl(gt_base + GT_CONTROL);
 | 
				
			||||||
	reg &= ~GT_CONTROL_PRESCALER_MASK;
 | 
						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);
 | 
						writel(reg, gt_base + GT_CONTROL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -256,8 +255,7 @@ static u32 gt_read_presc(void)
 | 
				
			||||||
	u32 reg;
 | 
						u32 reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reg = readl(gt_base + GT_CONTROL);
 | 
						reg = readl(gt_base + GT_CONTROL);
 | 
				
			||||||
	reg &= GT_CONTROL_PRESCALER_MASK;
 | 
						return FIELD_GET(GT_CONTROL_PRESCALER_MASK, reg);
 | 
				
			||||||
	return reg >> GT_CONTROL_PRESCALER_SHIFT;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void __init gt_delay_timer_init(void)
 | 
					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_COUNTER0);
 | 
				
			||||||
	writel(0, gt_base + GT_COUNTER1);
 | 
						writel(0, gt_base + GT_COUNTER1);
 | 
				
			||||||
	/* set prescaler and enable timer on all the cores */
 | 
						/* set prescaler and enable timer on all the cores */
 | 
				
			||||||
	writel(((CONFIG_ARM_GT_INITIAL_PRESCALER_VAL - 1) <<
 | 
						writel(FIELD_PREP(GT_CONTROL_PRESCALER_MASK,
 | 
				
			||||||
		GT_CONTROL_PRESCALER_SHIFT)
 | 
								  CONFIG_ARM_GT_INITIAL_PRESCALER_VAL - 1) |
 | 
				
			||||||
	       | GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
 | 
						       GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
 | 
					#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
 | 
				
			||||||
	sched_clock_register(gt_sched_clock_read, 64, gt_target_rate);
 | 
						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) {
 | 
						switch (event) {
 | 
				
			||||||
	case PRE_RATE_CHANGE:
 | 
						case PRE_RATE_CHANGE:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int psv;
 | 
							unsigned long psv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		psv = DIV_ROUND_CLOSEST(ndata->new_rate,
 | 
							psv = DIV_ROUND_CLOSEST(ndata->new_rate, gt_target_rate);
 | 
				
			||||||
					gt_target_rate);
 | 
							if (!psv ||
 | 
				
			||||||
 | 
							    abs(gt_target_rate - (ndata->new_rate / psv)) > MAX_F_ERR)
 | 
				
			||||||
		if (abs(gt_target_rate - (ndata->new_rate / psv)) > MAX_F_ERR)
 | 
					 | 
				
			||||||
			return NOTIFY_BAD;
 | 
								return NOTIFY_BAD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		psv--;
 | 
							psv--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* prescaler within legal range? */
 | 
							/* prescaler within legal range? */
 | 
				
			||||||
		if (psv < 0 || psv > GT_CONTROL_PRESCALER_MAX)
 | 
							if (!FIELD_FIT(GT_CONTROL_PRESCALER_MASK, psv))
 | 
				
			||||||
			return NOTIFY_BAD;
 | 
								return NOTIFY_BAD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -258,9 +258,8 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct clock_event_device *ced = dev_id;
 | 
						struct clock_event_device *ced = dev_id;
 | 
				
			||||||
	struct imx_timer *imxtm = to_imx_timer(ced);
 | 
						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);
 | 
						imxtm->gpt->gpt_irq_acknowledge(imxtm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,48 +4,62 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/interrupt.h>
 | 
					#include <linux/interrupt.h>
 | 
				
			||||||
#include <linux/clockchips.h>
 | 
					#include <linux/clockchips.h>
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "timer-of.h"
 | 
					#include "timer-of.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CMP_OFFSET	0x10000
 | 
					#define CMP_OFFSET	0x10000
 | 
				
			||||||
 | 
					#define RD_OFFSET	0x20000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CNTCV_LO	0x8
 | 
					#define CNTCV_LO	0x8
 | 
				
			||||||
#define CNTCV_HI	0xc
 | 
					#define CNTCV_HI	0xc
 | 
				
			||||||
#define CMPCV_LO	(CMP_OFFSET + 0x20)
 | 
					#define CMPCV_LO	(CMP_OFFSET + 0x20)
 | 
				
			||||||
#define CMPCV_HI	(CMP_OFFSET + 0x24)
 | 
					#define CMPCV_HI	(CMP_OFFSET + 0x24)
 | 
				
			||||||
#define CMPCR		(CMP_OFFSET + 0x2c)
 | 
					#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_EN		0x1
 | 
				
			||||||
#define SYS_CTR_IRQ_MASK	0x2
 | 
					#define SYS_CTR_IRQ_MASK	0x2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SYS_CTR_CLK_DIV		0x3
 | 
					#define SYS_CTR_CLK_DIV		0x3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void __iomem *sys_ctr_base __ro_after_init;
 | 
					struct sysctr_private {
 | 
				
			||||||
static u32 cmpcr __ro_after_init;
 | 
						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
 | 
						 * clear the enable bit(EN =0) will clear
 | 
				
			||||||
	 * the status bit(ISTAT = 0), then the interrupt
 | 
						 * the status bit(ISTAT = 0), then the interrupt
 | 
				
			||||||
	 * signal will be negated(acknowledged).
 | 
						 * 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;
 | 
						u32 cnt_hi, tmp_hi, cnt_lo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
		cnt_hi = readl_relaxed(sys_ctr_base + CNTCV_HI);
 | 
							cnt_hi = readl_relaxed(base + priv->hi_off);
 | 
				
			||||||
		cnt_lo = readl_relaxed(sys_ctr_base + CNTCV_LO);
 | 
							cnt_lo = readl_relaxed(base + priv->lo_off);
 | 
				
			||||||
		tmp_hi = readl_relaxed(sys_ctr_base + CNTCV_HI);
 | 
							tmp_hi = readl_relaxed(base + priv->hi_off);
 | 
				
			||||||
	} while (tmp_hi != cnt_hi);
 | 
						} while (tmp_hi != cnt_hi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return  ((u64) cnt_hi << 32) | cnt_lo;
 | 
						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,
 | 
					static int sysctr_set_next_event(unsigned long delta,
 | 
				
			||||||
				 struct clock_event_device *evt)
 | 
									 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;
 | 
						u32 cmp_hi, cmp_lo;
 | 
				
			||||||
	u64 next;
 | 
						u64 next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sysctr_timer_enable(false);
 | 
						sysctr_timer_enable(evt, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	next = sysctr_read_counter();
 | 
						next = sysctr_read_counter(evt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	next += delta;
 | 
						next += delta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmp_hi = (next >> 32) & 0x00fffff;
 | 
						cmp_hi = (next >> 32) & 0x00fffff;
 | 
				
			||||||
	cmp_lo = next & 0xffffffff;
 | 
						cmp_lo = next & 0xffffffff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	writel_relaxed(cmp_hi, sys_ctr_base + CMPCV_HI);
 | 
						writel_relaxed(cmp_hi, base + CMPCV_HI);
 | 
				
			||||||
	writel_relaxed(cmp_lo, sys_ctr_base + CMPCV_LO);
 | 
						writel_relaxed(cmp_lo, base + CMPCV_LO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sysctr_timer_enable(true);
 | 
						sysctr_timer_enable(evt, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						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)
 | 
					static int sysctr_set_state_shutdown(struct clock_event_device *evt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	sysctr_timer_enable(false);
 | 
						sysctr_timer_enable(evt, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -90,7 +106,7 @@ static irqreturn_t sysctr_timer_interrupt(int irq, void *dev_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct clock_event_device *evt = dev_id;
 | 
						struct clock_event_device *evt = dev_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sysctr_irq_acknowledge();
 | 
						sysctr_irq_acknowledge(evt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evt->event_handler(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)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	to_sysctr.clkevt.cpumask = cpu_possible_mask;
 | 
						struct sysctr_private *priv;
 | 
				
			||||||
 | 
						void __iomem *base;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clockevents_config_and_register(&to_sysctr.clkevt,
 | 
						priv = kzalloc(sizeof(struct sysctr_private), GFP_KERNEL);
 | 
				
			||||||
					timer_of_rate(&to_sysctr),
 | 
						if (!priv)
 | 
				
			||||||
					0xff, 0x7fffffff);
 | 
							return -ENOMEM;
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init sysctr_timer_init(struct device_node *np)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = timer_of_init(np, &to_sysctr);
 | 
						ret = timer_of_init(np, &to_sysctr);
 | 
				
			||||||
	if (ret)
 | 
						if (ret) {
 | 
				
			||||||
 | 
							kfree(priv);
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!of_property_read_bool(np, "nxp,no-divider")) {
 | 
						if (!of_property_read_bool(np, "nxp,no-divider")) {
 | 
				
			||||||
		/* system counter clock is divided by 3 internally */
 | 
							/* system counter clock is divided by 3 internally */
 | 
				
			||||||
		to_sysctr.of_clk.rate /= SYS_CTR_CLK_DIV;
 | 
							to_sysctr.of_clk.rate /= SYS_CTR_CLK_DIV;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sys_ctr_base = timer_of_base(&to_sysctr);
 | 
						to_sysctr.clkevt.cpumask = cpu_possible_mask;
 | 
				
			||||||
	cmpcr = readl(sys_ctr_base + CMPCR);
 | 
						to_sysctr.private_data = priv;
 | 
				
			||||||
	cmpcr &= ~SYS_CTR_EN;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sysctr_clockevent_init();
 | 
						base = timer_of_base(&to_sysctr);
 | 
				
			||||||
 | 
						priv->cmpcr = readl(base + CMPCR) & ~SYS_CTR_EN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						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_imx95_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_IMX95;
 | 
				
			||||||
 | 
						priv->hi_off = CNTCV_HI_IMX95;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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, "nxp,sysctr-timer", sysctr_timer_init);
 | 
				
			||||||
 | 
					TIMER_OF_DECLARE(sysctr_timer_imx95, "nxp,imx95-sysctr-timer", sysctr_timer_imx95_init);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
						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->cpumask = cpumask_of(cpu);
 | 
				
			||||||
	ce->irq = riscv_clock_event_irq;
 | 
						ce->irq = riscv_clock_event_irq;
 | 
				
			||||||
	if (riscv_timer_cannot_wake_cpu)
 | 
						if (riscv_timer_cannot_wake_cpu)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					 * Accessor helper to get the number of bits in the timer-of private
 | 
				
			||||||
 * structure.
 | 
					 * 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)
 | 
					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
 | 
					 * @to: a pointer to a timer-of structure
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Write the 32-bit max value and read/return the result. If the timer
 | 
					 * Write the 32-bit max value and read/return the result. If the timer
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0-only
 | 
					// SPDX-License-Identifier: GPL-2.0-only
 | 
				
			||||||
/**
 | 
					/*
 | 
				
			||||||
 * timer-ti-32k.c - OMAP2 32k Timer Support
 | 
					 * timer-ti-32k.c - OMAP2 32k Timer Support
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright (C) 2009 Nokia Corporation
 | 
					 * Copyright (C) 2009 Nokia Corporation
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue