diff options
Diffstat (limited to 'arch/arm/kernel/time.c')
-rw-r--r-- | arch/arm/kernel/time.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c new file mode 100644 index 000000000..a66e37e21 --- /dev/null +++ b/arch/arm/kernel/time.c @@ -0,0 +1,125 @@ +/* + * linux/arch/arm/kernel/time.c + * + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * Modifications for ARM (C) 1994-2001 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This file contains the ARM-specific time handling details: + * reading the RTC at bootup, etc... + */ +#include <linux/clk-provider.h> +#include <linux/clocksource.h> +#include <linux/errno.h> +#include <linux/export.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/profile.h> +#include <linux/sched.h> +#include <linux/sched_clock.h> +#include <linux/smp.h> +#include <linux/time.h> +#include <linux/timex.h> +#include <linux/timer.h> + +#include <asm/mach/arch.h> +#include <asm/mach/time.h> +#include <asm/stacktrace.h> +#include <asm/thread_info.h> + +#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \ + defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) +/* this needs a better home */ +DEFINE_SPINLOCK(rtc_lock); +EXPORT_SYMBOL(rtc_lock); +#endif /* pc-style 'CMOS' RTC support */ + +/* change this if you have some constant time drift */ +#define USECS_PER_JIFFY (1000000/HZ) + +#ifdef CONFIG_SMP +unsigned long profile_pc(struct pt_regs *regs) +{ + struct stackframe frame; + + if (!in_lock_functions(regs->ARM_pc)) + return regs->ARM_pc; + + arm_get_current_stackframe(regs, &frame); + do { + int ret = unwind_frame(&frame); + if (ret < 0) + return 0; + } while (in_lock_functions(frame.pc)); + + return frame.pc; +} +EXPORT_SYMBOL(profile_pc); +#endif + +#ifndef CONFIG_GENERIC_CLOCKEVENTS +/* + * Kernel system timer support. + */ +void timer_tick(void) +{ + profile_tick(CPU_PROFILING); + xtime_update(1); +#ifndef CONFIG_SMP + update_process_times(user_mode(get_irq_regs())); +#endif +} +#endif + +static void dummy_clock_access(struct timespec64 *ts) +{ + ts->tv_sec = 0; + ts->tv_nsec = 0; +} + +static clock_access_fn __read_persistent_clock = dummy_clock_access; +static clock_access_fn __read_boot_clock = dummy_clock_access;; + +void read_persistent_clock64(struct timespec64 *ts) +{ + __read_persistent_clock(ts); +} + +void read_boot_clock64(struct timespec64 *ts) +{ + __read_boot_clock(ts); +} + +int __init register_persistent_clock(clock_access_fn read_boot, + clock_access_fn read_persistent) +{ + /* Only allow the clockaccess functions to be registered once */ + if (__read_persistent_clock == dummy_clock_access && + __read_boot_clock == dummy_clock_access) { + if (read_boot) + __read_boot_clock = read_boot; + if (read_persistent) + __read_persistent_clock = read_persistent; + + return 0; + } + + return -EINVAL; +} + +void __init time_init(void) +{ + if (machine_desc->init_time) { + machine_desc->init_time(); + } else { +#ifdef CONFIG_COMMON_CLK + of_clk_init(NULL); +#endif + clocksource_of_init(); + } +} |