Commit 8596e589 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'timers-core-2021-08-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer updates from Thomas Gleixner:
 "Updates for timekeeping, timers and related drivers:

  Core code:

   - Cure a couple of correctness issues in the posix CPU timer code to
     prevent that the tick dependency for NOHZ full is kept alive for no
     reason.

   - Avoid expensive double reprogramming of the clockevent device in
     hrtimer_start_range_ns().

   - Avoid pointless SMP function calls when the clock was set to avoid
     disturbing CPUs which do not have any affected timers queued.

   - Make the clocksource watchdog test work correctly when CONFIG_HZ is
     less than 100.

  Drivers:

   - Prefer the ARM architected timer over the Exynos timer which is way
     more expensive to access.

   - Add device tree bindings for new Ingenic SoCs

   - The usual improvements and cleanups all over the place"

* tag 'timers-core-2021-08-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (29 commits)
  clocksource: Make clocksource watchdog test safe for slow-HZ systems
  dt-bindings: timer: Add ABIs for new Ingenic SoCs
  clocksource/drivers/fttmr010: Pass around less pointers
  clocksource/drivers/mediatek: Optimize systimer irq clear flow on shutdown
  clocksource/drivers/ingenic: Use bitfield macro helpers
  clocksource/drivers/sh_cmt: Fix wrong setting if don't request IRQ for clock source channel
  dt-bindings: timer: convert rockchip,rk-timer.txt to YAML
  clocksource/drivers/exynos_mct: Mark MCT device as CLOCK_EVT_FEAT_PERCPU
  clocksource/drivers/exynos_mct: Prioritise Arm arch timer on arm64
  hrtimer: Unbreak hrtimer_force_reprogram()
  hrtimer: Use raw_cpu_ptr() in clock_was_set()
  hrtimer: Avoid more SMP function calls in clock_was_set()
  hrtimer: Avoid unnecessary SMP function calls in clock_was_set()
  hrtimer: Add bases argument to clock_was_set()
  time/timekeeping: Avoid invoking clock_was_set() twice
  timekeeping: Distangle resume and clock-was-set events
  timerfd: Provide timerfd_resume()
  hrtimer: Force clock_was_set() handling for the HIGHRES=n, NOHZ=y case
  hrtimer: Ensure timerfd notification for HIGHRES=n
  hrtimer: Consolidate reprogramming code
  ...
parents bed91667 d25a0252
Loading
Loading
Loading
Loading
+0 −27
Original line number Diff line number Diff line
Rockchip rk timer

Required properties:
- compatible: should be:
  "rockchip,rv1108-timer", "rockchip,rk3288-timer": for Rockchip RV1108
  "rockchip,rk3036-timer", "rockchip,rk3288-timer": for Rockchip RK3036
  "rockchip,rk3066-timer", "rockchip,rk3288-timer": for Rockchip RK3066
  "rockchip,rk3188-timer", "rockchip,rk3288-timer": for Rockchip RK3188
  "rockchip,rk3228-timer", "rockchip,rk3288-timer": for Rockchip RK3228
  "rockchip,rk3229-timer", "rockchip,rk3288-timer": for Rockchip RK3229
  "rockchip,rk3288-timer": for Rockchip RK3288
  "rockchip,rk3368-timer", "rockchip,rk3288-timer": for Rockchip RK3368
  "rockchip,rk3399-timer": for Rockchip RK3399
- reg: base address of the timer register starting with TIMERS CONTROL register
- interrupts: should contain the interrupts for Timer0
- clocks : must contain an entry for each entry in clock-names
- clock-names : must include the following entries:
  "timer", "pclk"

Example:
	timer: timer@ff810000 {
		compatible = "rockchip,rk3288-timer";
		reg = <0xff810000 0x20>;
		interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
		clocks = <&xin24m>, <&cru PCLK_TIMER>;
		clock-names = "timer", "pclk";
	};
+64 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/timer/rockchip,rk-timer.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Rockchip Timer Device Tree Bindings

maintainers:
  - Daniel Lezcano <daniel.lezcano@linaro.org>

properties:
  compatible:
    oneOf:
      - const: rockchip,rk3288-timer
      - const: rockchip,rk3399-timer
      - items:
          - enum:
              - rockchip,rv1108-timer
              - rockchip,rk3036-timer
              - rockchip,rk3066-timer
              - rockchip,rk3188-timer
              - rockchip,rk3228-timer
              - rockchip,rk3229-timer
              - rockchip,rk3288-timer
              - rockchip,rk3368-timer
              - rockchip,px30-timer
          - const: rockchip,rk3288-timer
  reg:
    maxItems: 1

  interrupts:
    maxItems: 1

  clocks:
    minItems: 2
    maxItems: 2

  clock-names:
    items:
      - const: pclk
      - const: timer

required:
  - compatible
  - reg
  - interrupts
  - clocks
  - clock-names

additionalProperties: false

examples:
  - |
    #include <dt-bindings/interrupt-controller/arm-gic.h>
    #include <dt-bindings/clock/rk3288-cru.h>

    timer: timer@ff810000 {
        compatible = "rockchip,rk3288-timer";
        reg = <0xff810000 0x20>;
        interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&cru PCLK_TIMER>, <&xin24m>;
        clock-names = "pclk", "timer";
    };
+13 −3
Original line number Diff line number Diff line
@@ -51,6 +51,15 @@

#define TICK_BASE_CNT	1

#ifdef CONFIG_ARM
/* Use values higher than ARM arch timer. See 6282edb72bed. */
#define MCT_CLKSOURCE_RATING		450
#define MCT_CLKEVENTS_RATING		500
#else
#define MCT_CLKSOURCE_RATING		350
#define MCT_CLKEVENTS_RATING		350
#endif

enum {
	MCT_INT_SPI,
	MCT_INT_PPI
@@ -206,7 +215,7 @@ static void exynos4_frc_resume(struct clocksource *cs)

static struct clocksource mct_frc = {
	.name		= "mct-frc",
	.rating		= 450,	/* use value higher than ARM arch timer */
	.rating		= MCT_CLKSOURCE_RATING,
	.read		= exynos4_frc_read,
	.mask		= CLOCKSOURCE_MASK(32),
	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
@@ -456,8 +465,9 @@ static int exynos4_mct_starting_cpu(unsigned int cpu)
	evt->set_state_oneshot = set_state_shutdown;
	evt->set_state_oneshot_stopped = set_state_shutdown;
	evt->tick_resume = set_state_shutdown;
	evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
	evt->rating = 500;	/* use value higher than ARM arch timer */
	evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
			CLOCK_EVT_FEAT_PERCPU;
	evt->rating = MCT_CLKEVENTS_RATING,

	exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET);

+7 −6
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
 * Copyright (c) 2020 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
 */

#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
@@ -34,8 +35,6 @@
/* bits within the OSTCCR register */
#define OSTCCR_PRESCALE1_MASK	0x3
#define OSTCCR_PRESCALE2_MASK	0xc
#define OSTCCR_PRESCALE1_LSB	0
#define OSTCCR_PRESCALE2_LSB	2

/* bits within the OSTCR register */
#define OSTCR_OST1CLR			BIT(0)
@@ -98,7 +97,7 @@ static unsigned long ingenic_ost_percpu_timer_recalc_rate(struct clk_hw *hw,

	prescale = readl(ost_clk->ost->base + info->ostccr_reg);

	prescale = (prescale & OSTCCR_PRESCALE1_MASK) >> OSTCCR_PRESCALE1_LSB;
	prescale = FIELD_GET(OSTCCR_PRESCALE1_MASK, prescale);

	return parent_rate >> (prescale * 2);
}
@@ -112,7 +111,7 @@ static unsigned long ingenic_ost_global_timer_recalc_rate(struct clk_hw *hw,

	prescale = readl(ost_clk->ost->base + info->ostccr_reg);

	prescale = (prescale & OSTCCR_PRESCALE2_MASK) >> OSTCCR_PRESCALE2_LSB;
	prescale = FIELD_GET(OSTCCR_PRESCALE2_MASK, prescale);

	return parent_rate >> (prescale * 2);
}
@@ -151,7 +150,8 @@ static int ingenic_ost_percpu_timer_set_rate(struct clk_hw *hw, unsigned long re
	int val;

	val = readl(ost_clk->ost->base + info->ostccr_reg);
	val = (val & ~OSTCCR_PRESCALE1_MASK) | (prescale << OSTCCR_PRESCALE1_LSB);
	val &= ~OSTCCR_PRESCALE1_MASK;
	val |= FIELD_PREP(OSTCCR_PRESCALE1_MASK, prescale);
	writel(val, ost_clk->ost->base + info->ostccr_reg);

	return 0;
@@ -166,7 +166,8 @@ static int ingenic_ost_global_timer_set_rate(struct clk_hw *hw, unsigned long re
	int val;

	val = readl(ost_clk->ost->base + info->ostccr_reg);
	val = (val & ~OSTCCR_PRESCALE2_MASK) | (prescale << OSTCCR_PRESCALE2_LSB);
	val &= ~OSTCCR_PRESCALE2_MASK;
	val |= FIELD_PREP(OSTCCR_PRESCALE2_MASK, prescale);
	writel(val, ost_clk->ost->base + info->ostccr_reg);

	return 0;
+18 −12
Original line number Diff line number Diff line
@@ -579,7 +579,8 @@ static int sh_cmt_start(struct sh_cmt_channel *ch, unsigned long flag)
	ch->flags |= flag;

	/* setup timeout if no clockevent */
	if ((flag == FLAG_CLOCKSOURCE) && (!(ch->flags & FLAG_CLOCKEVENT)))
	if (ch->cmt->num_channels == 1 &&
	    flag == FLAG_CLOCKSOURCE && (!(ch->flags & FLAG_CLOCKEVENT)))
		__sh_cmt_set_next(ch, ch->max_match_value);
 out:
	raw_spin_unlock_irqrestore(&ch->lock, flags);
@@ -621,8 +622,10 @@ static struct sh_cmt_channel *cs_to_sh_cmt(struct clocksource *cs)
static u64 sh_cmt_clocksource_read(struct clocksource *cs)
{
	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
	unsigned long flags;
	u32 has_wrapped;

	if (ch->cmt->num_channels == 1) {
		unsigned long flags;
		u64 value;
		u32 raw;

@@ -637,6 +640,9 @@ static u64 sh_cmt_clocksource_read(struct clocksource *cs)
		return value + raw;
	}

	return sh_cmt_get_counter(ch, &has_wrapped);
}

static int sh_cmt_clocksource_enable(struct clocksource *cs)
{
	int ret;
@@ -697,7 +703,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch,
	cs->disable = sh_cmt_clocksource_disable;
	cs->suspend = sh_cmt_clocksource_suspend;
	cs->resume = sh_cmt_clocksource_resume;
	cs->mask = CLOCKSOURCE_MASK(sizeof(u64) * 8);
	cs->mask = CLOCKSOURCE_MASK(ch->cmt->info->width);
	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;

	dev_info(&ch->cmt->pdev->dev, "ch%u: used as clock source\n",
Loading