Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0+ 2 : /* 3 : * This file contains the jiffies based clocksource. 4 : * 5 : * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) 6 : */ 7 : #include <linux/clocksource.h> 8 : #include <linux/jiffies.h> 9 : #include <linux/module.h> 10 : #include <linux/init.h> 11 : 12 : #include "timekeeping.h" 13 : 14 : 15 : /* Since jiffies uses a simple TICK_NSEC multiplier 16 : * conversion, the .shift value could be zero. However 17 : * this would make NTP adjustments impossible as they are 18 : * in units of 1/2^.shift. Thus we use JIFFIES_SHIFT to 19 : * shift both the nominator and denominator the same 20 : * amount, and give ntp adjustments in units of 1/2^8 21 : * 22 : * The value 8 is somewhat carefully chosen, as anything 23 : * larger can result in overflows. TICK_NSEC grows as HZ 24 : * shrinks, so values greater than 8 overflow 32bits when 25 : * HZ=100. 26 : */ 27 : #if HZ < 34 28 : #define JIFFIES_SHIFT 6 29 : #elif HZ < 67 30 : #define JIFFIES_SHIFT 7 31 : #else 32 : #define JIFFIES_SHIFT 8 33 : #endif 34 : 35 583 : static u64 jiffies_read(struct clocksource *cs) 36 : { 37 583 : return (u64) jiffies; 38 : } 39 : 40 : /* 41 : * The Jiffies based clocksource is the lowest common 42 : * denominator clock source which should function on 43 : * all systems. It has the same coarse resolution as 44 : * the timer interrupt frequency HZ and it suffers 45 : * inaccuracies caused by missed or lost timer 46 : * interrupts and the inability for the timer 47 : * interrupt hardware to accuratly tick at the 48 : * requested HZ value. It is also not recommended 49 : * for "tick-less" systems. 50 : */ 51 : static struct clocksource clocksource_jiffies = { 52 : .name = "jiffies", 53 : .rating = 1, /* lowest valid rating*/ 54 : .read = jiffies_read, 55 : .mask = CLOCKSOURCE_MASK(32), 56 : .mult = TICK_NSEC << JIFFIES_SHIFT, /* details above */ 57 : .shift = JIFFIES_SHIFT, 58 : .max_cycles = 10, 59 : }; 60 : 61 : __cacheline_aligned_in_smp DEFINE_RAW_SPINLOCK(jiffies_lock); 62 : __cacheline_aligned_in_smp seqcount_raw_spinlock_t jiffies_seq = 63 : SEQCNT_RAW_SPINLOCK_ZERO(jiffies_seq, &jiffies_lock); 64 : 65 : #if (BITS_PER_LONG < 64) 66 : u64 get_jiffies_64(void) 67 : { 68 : unsigned int seq; 69 : u64 ret; 70 : 71 : do { 72 : seq = read_seqcount_begin(&jiffies_seq); 73 : ret = jiffies_64; 74 : } while (read_seqcount_retry(&jiffies_seq, seq)); 75 : return ret; 76 : } 77 : EXPORT_SYMBOL(get_jiffies_64); 78 : #endif 79 : 80 : EXPORT_SYMBOL(jiffies); 81 : 82 1 : static int __init init_jiffies_clocksource(void) 83 : { 84 1 : return __clocksource_register(&clocksource_jiffies); 85 : } 86 : 87 : core_initcall(init_jiffies_clocksource); 88 : 89 2 : struct clocksource * __init __weak clocksource_default_clock(void) 90 : { 91 2 : return &clocksource_jiffies; 92 : } 93 : 94 : static struct clocksource refined_jiffies; 95 : 96 1 : int register_refined_jiffies(long cycles_per_second) 97 : { 98 1 : u64 nsec_per_tick, shift_hz; 99 1 : long cycles_per_tick; 100 : 101 : 102 : 103 1 : refined_jiffies = clocksource_jiffies; 104 1 : refined_jiffies.name = "refined-jiffies"; 105 1 : refined_jiffies.rating++; 106 : 107 : /* Calc cycles per tick */ 108 1 : cycles_per_tick = (cycles_per_second + HZ/2)/HZ; 109 : /* shift_hz stores hz<<8 for extra accuracy */ 110 1 : shift_hz = (u64)cycles_per_second << 8; 111 1 : shift_hz += cycles_per_tick/2; 112 1 : do_div(shift_hz, cycles_per_tick); 113 : /* Calculate nsec_per_tick using shift_hz */ 114 1 : nsec_per_tick = (u64)NSEC_PER_SEC << 8; 115 1 : nsec_per_tick += (u32)shift_hz/2; 116 1 : do_div(nsec_per_tick, (u32)shift_hz); 117 : 118 1 : refined_jiffies.mult = ((u32)nsec_per_tick) << JIFFIES_SHIFT; 119 : 120 1 : __clocksource_register(&refined_jiffies); 121 1 : return 0; 122 : }