blob: bc4db9e5ab70c1caa2092d72889c49c62ae517c4 [file] [log] [blame]
Thomas Gleixner35728b82018-10-31 19:21:09 +01001// SPDX-License-Identifier: GPL-2.0+
Thomas Gleixner6c7811c2018-10-31 19:21:12 +01002/*
3 * This file contains the jiffies based clocksource.
4 *
5 * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com)
6 */
john stultz734efb42006-06-26 00:25:05 -07007#include <linux/clocksource.h>
8#include <linux/jiffies.h>
Torben Hohnfbad1ea2011-01-27 15:59:00 +01009#include <linux/module.h>
john stultz734efb42006-06-26 00:25:05 -070010#include <linux/init.h>
11
Thomas Gleixnerbfb83b22015-03-25 13:06:04 +010012#include "timekeeping.h"
Paul E. McKenneyd25a0252021-08-12 09:31:28 -070013#include "tick-internal.h"
Torben Hohne2830b52011-01-27 16:00:32 +010014
john stultz734efb42006-06-26 00:25:05 -070015
Thomas Gleixnera5a1d1c2016-12-21 20:32:01 +010016static u64 jiffies_read(struct clocksource *cs)
john stultz734efb42006-06-26 00:25:05 -070017{
Thomas Gleixnera5a1d1c2016-12-21 20:32:01 +010018 return (u64) jiffies;
john stultz734efb42006-06-26 00:25:05 -070019}
20
Frederic Weisbecker93825f22017-01-31 04:09:16 +010021/*
22 * The Jiffies based clocksource is the lowest common
23 * denominator clock source which should function on
24 * all systems. It has the same coarse resolution as
25 * the timer interrupt frequency HZ and it suffers
26 * inaccuracies caused by missed or lost timer
27 * interrupts and the inability for the timer
Ingo Molnar4bf07f62021-03-22 22:39:03 +010028 * interrupt hardware to accurately tick at the
Frederic Weisbecker93825f22017-01-31 04:09:16 +010029 * requested HZ value. It is also not recommended
30 * for "tick-less" systems.
31 */
Lars-Peter Clausenf95a9852012-10-18 11:34:41 +020032static struct clocksource clocksource_jiffies = {
Paul E. McKenney2e27e792021-05-27 12:01:22 -070033 .name = "jiffies",
34 .rating = 1, /* lowest valid rating*/
35 .uncertainty_margin = 32 * NSEC_PER_MSEC,
36 .read = jiffies_read,
37 .mask = CLOCKSOURCE_MASK(32),
38 .mult = TICK_NSEC << JIFFIES_SHIFT, /* details above */
39 .shift = JIFFIES_SHIFT,
40 .max_cycles = 10,
john stultz734efb42006-06-26 00:25:05 -070041};
42
Thomas Gleixnere5d4d172020-03-21 12:25:58 +010043__cacheline_aligned_in_smp DEFINE_RAW_SPINLOCK(jiffies_lock);
Davidlohr Bueso1a2b85f2020-10-21 12:07:49 -070044__cacheline_aligned_in_smp seqcount_raw_spinlock_t jiffies_seq =
45 SEQCNT_RAW_SPINLOCK_ZERO(jiffies_seq, &jiffies_lock);
John Stultzd6ad4182012-02-28 16:50:11 -080046
Torben Hohnfbad1ea2011-01-27 15:59:00 +010047#if (BITS_PER_LONG < 64)
48u64 get_jiffies_64(void)
49{
Rasmus Villemoese1e41b62019-03-18 20:55:56 +010050 unsigned int seq;
Torben Hohnfbad1ea2011-01-27 15:59:00 +010051 u64 ret;
52
53 do {
Thomas Gleixnere5d4d172020-03-21 12:25:58 +010054 seq = read_seqcount_begin(&jiffies_seq);
Torben Hohnfbad1ea2011-01-27 15:59:00 +010055 ret = jiffies_64;
Thomas Gleixnere5d4d172020-03-21 12:25:58 +010056 } while (read_seqcount_retry(&jiffies_seq, seq));
Torben Hohnfbad1ea2011-01-27 15:59:00 +010057 return ret;
58}
59EXPORT_SYMBOL(get_jiffies_64);
60#endif
61
62EXPORT_SYMBOL(jiffies);
63
john stultz734efb42006-06-26 00:25:05 -070064static int __init init_jiffies_clocksource(void)
65{
John Stultzf8935982015-03-11 21:16:37 -070066 return __clocksource_register(&clocksource_jiffies);
john stultz734efb42006-06-26 00:25:05 -070067}
68
john stultz98de9e32007-04-04 19:08:24 -070069core_initcall(init_jiffies_clocksource);
Martin Schwidefskyf1b82742009-08-14 15:47:21 +020070
71struct clocksource * __init __weak clocksource_default_clock(void)
72{
73 return &clocksource_jiffies;
74}
John Stultzb3c869d2012-09-04 12:42:27 -040075
Valdis Kletniekse8750052019-03-12 04:38:35 -040076static struct clocksource refined_jiffies;
John Stultzb3c869d2012-09-04 12:42:27 -040077
78int register_refined_jiffies(long cycles_per_second)
79{
80 u64 nsec_per_tick, shift_hz;
81 long cycles_per_tick;
82
83
84
85 refined_jiffies = clocksource_jiffies;
86 refined_jiffies.name = "refined-jiffies";
87 refined_jiffies.rating++;
88
89 /* Calc cycles per tick */
90 cycles_per_tick = (cycles_per_second + HZ/2)/HZ;
91 /* shift_hz stores hz<<8 for extra accuracy */
92 shift_hz = (u64)cycles_per_second << 8;
93 shift_hz += cycles_per_tick/2;
94 do_div(shift_hz, cycles_per_tick);
95 /* Calculate nsec_per_tick using shift_hz */
Frederic Weisbeckerfa3aa7a2017-03-07 10:55:34 +010096 nsec_per_tick = (u64)NSEC_PER_SEC << 8;
John Stultzb3c869d2012-09-04 12:42:27 -040097 nsec_per_tick += (u32)shift_hz/2;
98 do_div(nsec_per_tick, (u32)shift_hz);
99
100 refined_jiffies.mult = ((u32)nsec_per_tick) << JIFFIES_SHIFT;
101
John Stultzf8935982015-03-11 21:16:37 -0700102 __clocksource_register(&refined_jiffies);
John Stultzb3c869d2012-09-04 12:42:27 -0400103 return 0;
104}