1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * linux/arch/arm/kernel/time.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 1991, 1992, 1995 Linus Torvalds 61da177e4SLinus Torvalds * Modifications for ARM (C) 1994-2001 Russell King 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * This file contains the ARM-specific time handling details: 91da177e4SLinus Torvalds * reading the RTC at bootup, etc... 101da177e4SLinus Torvalds */ 11022eb8aeSBenjamin Gaignard #include <linux/clockchips.h> 12f414f13fSArnd Bergmann #include <linux/clocksource.h> 134178bac4SSebastian Hesselbarth #include <linux/errno.h> 144178bac4SSebastian Hesselbarth #include <linux/export.h> 154178bac4SSebastian Hesselbarth #include <linux/init.h> 164178bac4SSebastian Hesselbarth #include <linux/interrupt.h> 17e317c8ccSFrederik Deweerdt #include <linux/irq.h> 184178bac4SSebastian Hesselbarth #include <linux/kernel.h> 19*9bffcf42SGeert Uytterhoeven #include <linux/of_clk.h> 204178bac4SSebastian Hesselbarth #include <linux/profile.h> 214178bac4SSebastian Hesselbarth #include <linux/sched.h> 2238ff87f7SStephen Boyd #include <linux/sched_clock.h> 234178bac4SSebastian Hesselbarth #include <linux/smp.h> 244178bac4SSebastian Hesselbarth #include <linux/time.h> 254178bac4SSebastian Hesselbarth #include <linux/timex.h> 264178bac4SSebastian Hesselbarth #include <linux/timer.h> 271da177e4SLinus Torvalds 288ff1443cSRussell King #include <asm/mach/arch.h> 291da177e4SLinus Torvalds #include <asm/mach/time.h> 304178bac4SSebastian Hesselbarth #include <asm/stacktrace.h> 314178bac4SSebastian Hesselbarth #include <asm/thread_info.h> 321da177e4SLinus Torvalds 3363216d3cSArnd Bergmann #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \ 3463216d3cSArnd Bergmann defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) 351da177e4SLinus Torvalds /* this needs a better home */ 361da177e4SLinus Torvalds DEFINE_SPINLOCK(rtc_lock); 371da177e4SLinus Torvalds EXPORT_SYMBOL(rtc_lock); 389dd34948SDavid Brownell #endif /* pc-style 'CMOS' RTC support */ 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds /* change this if you have some constant time drift */ 411da177e4SLinus Torvalds #define USECS_PER_JIFFY (1000000/HZ) 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds #ifdef CONFIG_SMP 441da177e4SLinus Torvalds unsigned long profile_pc(struct pt_regs *regs) 451da177e4SLinus Torvalds { 462d7c11bfSCatalin Marinas struct stackframe frame; 471da177e4SLinus Torvalds 482d7c11bfSCatalin Marinas if (!in_lock_functions(regs->ARM_pc)) 492d7c11bfSCatalin Marinas return regs->ARM_pc; 501da177e4SLinus Torvalds 51a3250c92SNikolay Borisov arm_get_current_stackframe(regs, &frame); 522d7c11bfSCatalin Marinas do { 532d7c11bfSCatalin Marinas int ret = unwind_frame(&frame); 542d7c11bfSCatalin Marinas if (ret < 0) 552d7c11bfSCatalin Marinas return 0; 562d7c11bfSCatalin Marinas } while (in_lock_functions(frame.pc)); 572d7c11bfSCatalin Marinas 582d7c11bfSCatalin Marinas return frame.pc; 591da177e4SLinus Torvalds } 601da177e4SLinus Torvalds EXPORT_SYMBOL(profile_pc); 611da177e4SLinus Torvalds #endif 621da177e4SLinus Torvalds 639e4559ddSKevin Hilman #ifndef CONFIG_GENERIC_CLOCKEVENTS 641da177e4SLinus Torvalds /* 651da177e4SLinus Torvalds * Kernel system timer support. 661da177e4SLinus Torvalds */ 670cd61b68SLinus Torvalds void timer_tick(void) 681da177e4SLinus Torvalds { 69e317c8ccSFrederik Deweerdt profile_tick(CPU_PROFILING); 706906e33cSTorben Hohn xtime_update(1); 711da177e4SLinus Torvalds #ifndef CONFIG_SMP 72c97d4869SRussell King update_process_times(user_mode(get_irq_regs())); 731da177e4SLinus Torvalds #endif 741da177e4SLinus Torvalds } 759e4559ddSKevin Hilman #endif 761da177e4SLinus Torvalds 77cb850717SXunlei Pang static void dummy_clock_access(struct timespec64 *ts) 78bd0493eaSMarc Zyngier { 79bd0493eaSMarc Zyngier ts->tv_sec = 0; 80bd0493eaSMarc Zyngier ts->tv_nsec = 0; 81bd0493eaSMarc Zyngier } 82bd0493eaSMarc Zyngier 83bd0493eaSMarc Zyngier static clock_access_fn __read_persistent_clock = dummy_clock_access; 84bd0493eaSMarc Zyngier 85cb850717SXunlei Pang void read_persistent_clock64(struct timespec64 *ts) 86bd0493eaSMarc Zyngier { 87bd0493eaSMarc Zyngier __read_persistent_clock(ts); 88bd0493eaSMarc Zyngier } 89bd0493eaSMarc Zyngier 90227e3958SPavel Tatashin int __init register_persistent_clock(clock_access_fn read_persistent) 91bd0493eaSMarc Zyngier { 92bd0493eaSMarc Zyngier /* Only allow the clockaccess functions to be registered once */ 93227e3958SPavel Tatashin if (__read_persistent_clock == dummy_clock_access) { 94bd0493eaSMarc Zyngier if (read_persistent) 95bd0493eaSMarc Zyngier __read_persistent_clock = read_persistent; 96bd0493eaSMarc Zyngier return 0; 97bd0493eaSMarc Zyngier } 98bd0493eaSMarc Zyngier 99bd0493eaSMarc Zyngier return -EINVAL; 100bd0493eaSMarc Zyngier } 101bd0493eaSMarc Zyngier 1021da177e4SLinus Torvalds void __init time_init(void) 1031da177e4SLinus Torvalds { 1044178bac4SSebastian Hesselbarth if (machine_desc->init_time) { 1056bb27d73SStephen Warren machine_desc->init_time(); 1064178bac4SSebastian Hesselbarth } else { 1074178bac4SSebastian Hesselbarth #ifdef CONFIG_COMMON_CLK 1084178bac4SSebastian Hesselbarth of_clk_init(NULL); 1094178bac4SSebastian Hesselbarth #endif 110ba5d08c0SDaniel Lezcano timer_probe(); 111022eb8aeSBenjamin Gaignard tick_setup_hrtimer_broadcast(); 1121da177e4SLinus Torvalds } 1134178bac4SSebastian Hesselbarth } 114