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 profile_pc(struct pt_regs * regs)441da177e4SLinus Torvaldsunsigned 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 dummy_clock_access(struct timespec64 * ts)63cb850717SXunlei Pangstatic void dummy_clock_access(struct timespec64 *ts) 64bd0493eaSMarc Zyngier { 65bd0493eaSMarc Zyngier ts->tv_sec = 0; 66bd0493eaSMarc Zyngier ts->tv_nsec = 0; 67bd0493eaSMarc Zyngier } 68bd0493eaSMarc Zyngier 69bd0493eaSMarc Zyngier static clock_access_fn __read_persistent_clock = dummy_clock_access; 70bd0493eaSMarc Zyngier read_persistent_clock64(struct timespec64 * ts)71cb850717SXunlei Pangvoid read_persistent_clock64(struct timespec64 *ts) 72bd0493eaSMarc Zyngier { 73bd0493eaSMarc Zyngier __read_persistent_clock(ts); 74bd0493eaSMarc Zyngier } 75bd0493eaSMarc Zyngier register_persistent_clock(clock_access_fn read_persistent)76227e3958SPavel Tatashinint __init register_persistent_clock(clock_access_fn read_persistent) 77bd0493eaSMarc Zyngier { 78bd0493eaSMarc Zyngier /* Only allow the clockaccess functions to be registered once */ 79227e3958SPavel Tatashin if (__read_persistent_clock == dummy_clock_access) { 80bd0493eaSMarc Zyngier if (read_persistent) 81bd0493eaSMarc Zyngier __read_persistent_clock = read_persistent; 82bd0493eaSMarc Zyngier return 0; 83bd0493eaSMarc Zyngier } 84bd0493eaSMarc Zyngier 85bd0493eaSMarc Zyngier return -EINVAL; 86bd0493eaSMarc Zyngier } 87bd0493eaSMarc Zyngier time_init(void)881da177e4SLinus Torvaldsvoid __init time_init(void) 891da177e4SLinus Torvalds { 904178bac4SSebastian Hesselbarth if (machine_desc->init_time) { 916bb27d73SStephen Warren machine_desc->init_time(); 924178bac4SSebastian Hesselbarth } else { 934178bac4SSebastian Hesselbarth #ifdef CONFIG_COMMON_CLK 944178bac4SSebastian Hesselbarth of_clk_init(NULL); 954178bac4SSebastian Hesselbarth #endif 96ba5d08c0SDaniel Lezcano timer_probe(); 97022eb8aeSBenjamin Gaignard tick_setup_hrtimer_broadcast(); 981da177e4SLinus Torvalds } 994178bac4SSebastian Hesselbarth } 100