Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  linux/arch/arm/kernel/time.c
0004  *
0005  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
0006  *  Modifications for ARM (C) 1994-2001 Russell King
0007  *
0008  *  This file contains the ARM-specific time handling details:
0009  *  reading the RTC at bootup, etc...
0010  */
0011 #include <linux/clockchips.h>
0012 #include <linux/clocksource.h>
0013 #include <linux/errno.h>
0014 #include <linux/export.h>
0015 #include <linux/init.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/irq.h>
0018 #include <linux/kernel.h>
0019 #include <linux/of_clk.h>
0020 #include <linux/profile.h>
0021 #include <linux/sched.h>
0022 #include <linux/sched_clock.h>
0023 #include <linux/smp.h>
0024 #include <linux/time.h>
0025 #include <linux/timex.h>
0026 #include <linux/timer.h>
0027 
0028 #include <asm/mach/arch.h>
0029 #include <asm/mach/time.h>
0030 #include <asm/stacktrace.h>
0031 #include <asm/thread_info.h>
0032 
0033 #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \
0034     defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE)
0035 /* this needs a better home */
0036 DEFINE_SPINLOCK(rtc_lock);
0037 EXPORT_SYMBOL(rtc_lock);
0038 #endif  /* pc-style 'CMOS' RTC support */
0039 
0040 /* change this if you have some constant time drift */
0041 #define USECS_PER_JIFFY (1000000/HZ)
0042 
0043 #ifdef CONFIG_SMP
0044 unsigned long profile_pc(struct pt_regs *regs)
0045 {
0046     struct stackframe frame;
0047 
0048     if (!in_lock_functions(regs->ARM_pc))
0049         return regs->ARM_pc;
0050 
0051     arm_get_current_stackframe(regs, &frame);
0052     do {
0053         int ret = unwind_frame(&frame);
0054         if (ret < 0)
0055             return 0;
0056     } while (in_lock_functions(frame.pc));
0057 
0058     return frame.pc;
0059 }
0060 EXPORT_SYMBOL(profile_pc);
0061 #endif
0062 
0063 static void dummy_clock_access(struct timespec64 *ts)
0064 {
0065     ts->tv_sec = 0;
0066     ts->tv_nsec = 0;
0067 }
0068 
0069 static clock_access_fn __read_persistent_clock = dummy_clock_access;
0070 
0071 void read_persistent_clock64(struct timespec64 *ts)
0072 {
0073     __read_persistent_clock(ts);
0074 }
0075 
0076 int __init register_persistent_clock(clock_access_fn read_persistent)
0077 {
0078     /* Only allow the clockaccess functions to be registered once */
0079     if (__read_persistent_clock == dummy_clock_access) {
0080         if (read_persistent)
0081             __read_persistent_clock = read_persistent;
0082         return 0;
0083     }
0084 
0085     return -EINVAL;
0086 }
0087 
0088 void __init time_init(void)
0089 {
0090     if (machine_desc->init_time) {
0091         machine_desc->init_time();
0092     } else {
0093 #ifdef CONFIG_COMMON_CLK
0094         of_clk_init(NULL);
0095 #endif
0096         timer_probe();
0097         tick_setup_hrtimer_broadcast();
0098     }
0099 }