Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only 2 : : /* 3 : : * linux/arch/arm/kernel/time.c 4 : : * 5 : : * Copyright (C) 1991, 1992, 1995 Linus Torvalds 6 : : * Modifications for ARM (C) 1994-2001 Russell King 7 : : * 8 : : * This file contains the ARM-specific time handling details: 9 : : * reading the RTC at bootup, etc... 10 : : */ 11 : : #include <linux/clk-provider.h> 12 : : #include <linux/clocksource.h> 13 : : #include <linux/errno.h> 14 : : #include <linux/export.h> 15 : : #include <linux/init.h> 16 : : #include <linux/interrupt.h> 17 : : #include <linux/irq.h> 18 : : #include <linux/kernel.h> 19 : : #include <linux/profile.h> 20 : : #include <linux/sched.h> 21 : : #include <linux/sched_clock.h> 22 : : #include <linux/smp.h> 23 : : #include <linux/time.h> 24 : : #include <linux/timex.h> 25 : : #include <linux/timer.h> 26 : : 27 : : #include <asm/mach/arch.h> 28 : : #include <asm/mach/time.h> 29 : : #include <asm/stacktrace.h> 30 : : #include <asm/thread_info.h> 31 : : 32 : : #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \ 33 : : defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) 34 : : /* this needs a better home */ 35 : : DEFINE_SPINLOCK(rtc_lock); 36 : : EXPORT_SYMBOL(rtc_lock); 37 : : #endif /* pc-style 'CMOS' RTC support */ 38 : : 39 : : /* change this if you have some constant time drift */ 40 : : #define USECS_PER_JIFFY (1000000/HZ) 41 : : 42 : : #ifdef CONFIG_SMP 43 : 0 : unsigned long profile_pc(struct pt_regs *regs) 44 : : { 45 : : struct stackframe frame; 46 : : 47 : 0 : if (!in_lock_functions(regs->ARM_pc)) 48 : 0 : return regs->ARM_pc; 49 : : 50 : : arm_get_current_stackframe(regs, &frame); 51 : : do { 52 : 0 : int ret = unwind_frame(&frame); 53 : 0 : if (ret < 0) 54 : : return 0; 55 : 0 : } while (in_lock_functions(frame.pc)); 56 : : 57 : 0 : return frame.pc; 58 : : } 59 : : EXPORT_SYMBOL(profile_pc); 60 : : #endif 61 : : 62 : : #ifndef CONFIG_GENERIC_CLOCKEVENTS 63 : : /* 64 : : * Kernel system timer support. 65 : : */ 66 : : void timer_tick(void) 67 : : { 68 : : profile_tick(CPU_PROFILING); 69 : : xtime_update(1); 70 : : #ifndef CONFIG_SMP 71 : : update_process_times(user_mode(get_irq_regs())); 72 : : #endif 73 : : } 74 : : #endif 75 : : 76 : 3 : static void dummy_clock_access(struct timespec64 *ts) 77 : : { 78 : 3 : ts->tv_sec = 0; 79 : 3 : ts->tv_nsec = 0; 80 : 3 : } 81 : : 82 : : static clock_access_fn __read_persistent_clock = dummy_clock_access; 83 : : 84 : 3 : void read_persistent_clock64(struct timespec64 *ts) 85 : : { 86 : 3 : __read_persistent_clock(ts); 87 : 3 : } 88 : : 89 : 0 : int __init register_persistent_clock(clock_access_fn read_persistent) 90 : : { 91 : : /* Only allow the clockaccess functions to be registered once */ 92 : 0 : if (__read_persistent_clock == dummy_clock_access) { 93 : 0 : if (read_persistent) 94 : 0 : __read_persistent_clock = read_persistent; 95 : : return 0; 96 : : } 97 : : 98 : : return -EINVAL; 99 : : } 100 : : 101 : 3 : void __init time_init(void) 102 : : { 103 : 3 : if (machine_desc->init_time) { 104 : 0 : machine_desc->init_time(); 105 : : } else { 106 : : #ifdef CONFIG_COMMON_CLK 107 : 3 : of_clk_init(NULL); 108 : : #endif 109 : 3 : timer_probe(); 110 : : } 111 : 3 : }