Skip to content

Commit

Permalink
Merge tag 'timers-core-2021-08-30' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/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
  ...
  • Loading branch information
Linus Torvalds committed Aug 30, 2021
2 parents bed9166 + d25a025 commit 8596e58
Show file tree
Hide file tree
Showing 22 changed files with 574 additions and 230 deletions.
27 changes: 0 additions & 27 deletions Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt

This file was deleted.

64 changes: 64 additions & 0 deletions Documentation/devicetree/bindings/timer/rockchip,rk-timer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# 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";
};
16 changes: 13 additions & 3 deletions drivers/clocksource/exynos_mct.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);

Expand Down
13 changes: 7 additions & 6 deletions drivers/clocksource/ingenic-sysost.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
30 changes: 18 additions & 12 deletions drivers/clocksource/sh_cmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -621,20 +622,25 @@ 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;
u64 value;
u32 raw;

raw_spin_lock_irqsave(&ch->lock, flags);
value = ch->total_cycles;
raw = sh_cmt_get_counter(ch, &has_wrapped);
if (ch->cmt->num_channels == 1) {
unsigned long flags;
u64 value;
u32 raw;

if (unlikely(has_wrapped))
raw += ch->match_value + 1;
raw_spin_unlock_irqrestore(&ch->lock, flags);
raw_spin_lock_irqsave(&ch->lock, flags);
value = ch->total_cycles;
raw = sh_cmt_get_counter(ch, &has_wrapped);

if (unlikely(has_wrapped))
raw += ch->match_value + 1;
raw_spin_unlock_irqrestore(&ch->lock, flags);

return value + raw;
}

return value + raw;
return sh_cmt_get_counter(ch, &has_wrapped);
}

static int sh_cmt_clocksource_enable(struct clocksource *cs)
Expand Down Expand Up @@ -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",
Expand Down
32 changes: 16 additions & 16 deletions drivers/clocksource/timer-fttmr010.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,7 @@ static irqreturn_t ast2600_timer_interrupt(int irq, void *dev_id)
}

static int __init fttmr010_common_init(struct device_node *np,
bool is_aspeed,
int (*timer_shutdown)(struct clock_event_device *),
irq_handler_t irq_handler)
bool is_aspeed, bool is_ast2600)
{
struct fttmr010 *fttmr010;
int irq;
Expand Down Expand Up @@ -374,17 +372,25 @@ static int __init fttmr010_common_init(struct device_node *np,
fttmr010->tick_rate);
}

fttmr010->timer_shutdown = timer_shutdown;

/*
* Setup clockevent timer (interrupt-driven) on timer 1.
*/
writel(0, fttmr010->base + TIMER1_COUNT);
writel(0, fttmr010->base + TIMER1_LOAD);
writel(0, fttmr010->base + TIMER1_MATCH1);
writel(0, fttmr010->base + TIMER1_MATCH2);
ret = request_irq(irq, irq_handler, IRQF_TIMER,
"FTTMR010-TIMER1", &fttmr010->clkevt);

if (is_ast2600) {
fttmr010->timer_shutdown = ast2600_timer_shutdown;
ret = request_irq(irq, ast2600_timer_interrupt,
IRQF_TIMER, "FTTMR010-TIMER1",
&fttmr010->clkevt);
} else {
fttmr010->timer_shutdown = fttmr010_timer_shutdown;
ret = request_irq(irq, fttmr010_timer_interrupt,
IRQF_TIMER, "FTTMR010-TIMER1",
&fttmr010->clkevt);
}
if (ret) {
pr_err("FTTMR010-TIMER1 no IRQ\n");
goto out_unmap;
Expand Down Expand Up @@ -432,23 +438,17 @@ static int __init fttmr010_common_init(struct device_node *np,

static __init int ast2600_timer_init(struct device_node *np)
{
return fttmr010_common_init(np, true,
ast2600_timer_shutdown,
ast2600_timer_interrupt);
return fttmr010_common_init(np, true, true);
}

static __init int aspeed_timer_init(struct device_node *np)
{
return fttmr010_common_init(np, true,
fttmr010_timer_shutdown,
fttmr010_timer_interrupt);
return fttmr010_common_init(np, true, false);
}

static __init int fttmr010_timer_init(struct device_node *np)
{
return fttmr010_common_init(np, false,
fttmr010_timer_shutdown,
fttmr010_timer_interrupt);
return fttmr010_common_init(np, false, false);
}

TIMER_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_init);
Expand Down
8 changes: 6 additions & 2 deletions drivers/clocksource/timer-mediatek.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@
* SYST_CON_EN: Clock enable. Shall be set to
* - Start timer countdown.
* - Allow timeout ticks being updated.
* - Allow changing interrupt functions.
* - Allow changing interrupt status,like clear irq pending.
*
* SYST_CON_IRQ_EN: Set to allow interrupt.
* SYST_CON_IRQ_EN: Set to enable interrupt.
*
* SYST_CON_IRQ_CLR: Set to clear interrupt.
*/
Expand All @@ -75,6 +75,7 @@ static void __iomem *gpt_sched_reg __read_mostly;
static void mtk_syst_ack_irq(struct timer_of *to)
{
/* Clear and disable interrupt */
writel(SYST_CON_EN, SYST_CON_REG(to));
writel(SYST_CON_IRQ_CLR | SYST_CON_EN, SYST_CON_REG(to));
}

Expand Down Expand Up @@ -111,6 +112,9 @@ static int mtk_syst_clkevt_next_event(unsigned long ticks,

static int mtk_syst_clkevt_shutdown(struct clock_event_device *clkevt)
{
/* Clear any irq */
mtk_syst_ack_irq(to_timer_of(clkevt));

/* Disable timer */
writel(0, SYST_CON_REG(to_timer_of(clkevt)));

Expand Down
16 changes: 16 additions & 0 deletions fs/timerfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,22 @@ void timerfd_clock_was_set(void)
rcu_read_unlock();
}

static void timerfd_resume_work(struct work_struct *work)
{
timerfd_clock_was_set();
}

static DECLARE_WORK(timerfd_work, timerfd_resume_work);

/*
* Invoked from timekeeping_resume(). Defer the actual update to work so
* timerfd_clock_was_set() runs in task context.
*/
void timerfd_resume(void)
{
schedule_work(&timerfd_work);
}

static void __timerfd_remove_cancel(struct timerfd_ctx *ctx)
{
if (ctx->might_cancel) {
Expand Down
19 changes: 19 additions & 0 deletions include/dt-bindings/clock/ingenic,sysost.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,23 @@
#define OST_CLK_PERCPU_TIMER2 3
#define OST_CLK_PERCPU_TIMER3 4

#define OST_CLK_EVENT_TIMER 1

#define OST_CLK_EVENT_TIMER0 0
#define OST_CLK_EVENT_TIMER1 1
#define OST_CLK_EVENT_TIMER2 2
#define OST_CLK_EVENT_TIMER3 3
#define OST_CLK_EVENT_TIMER4 4
#define OST_CLK_EVENT_TIMER5 5
#define OST_CLK_EVENT_TIMER6 6
#define OST_CLK_EVENT_TIMER7 7
#define OST_CLK_EVENT_TIMER8 8
#define OST_CLK_EVENT_TIMER9 9
#define OST_CLK_EVENT_TIMER10 10
#define OST_CLK_EVENT_TIMER11 11
#define OST_CLK_EVENT_TIMER12 12
#define OST_CLK_EVENT_TIMER13 13
#define OST_CLK_EVENT_TIMER14 14
#define OST_CLK_EVENT_TIMER15 15

#endif /* __DT_BINDINGS_CLOCK_INGENIC_OST_H__ */
Loading

0 comments on commit 8596e58

Please sign in to comment.