xref: /openbmc/linux/arch/arm/kernel/time.c (revision f414f13f2fd0d8bb12a87268a55827cda771d42b)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  linux/arch/arm/kernel/time.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
51da177e4SLinus Torvalds  *  Modifications for ARM (C) 1994-2001 Russell King
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
81da177e4SLinus Torvalds  * it under the terms of the GNU General Public License version 2 as
91da177e4SLinus Torvalds  * published by the Free Software Foundation.
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  *  This file contains the ARM-specific time handling details:
121da177e4SLinus Torvalds  *  reading the RTC at bootup, etc...
131da177e4SLinus Torvalds  */
14ecea4ab6SPaul Gortmaker #include <linux/export.h>
151da177e4SLinus Torvalds #include <linux/kernel.h>
161da177e4SLinus Torvalds #include <linux/interrupt.h>
171da177e4SLinus Torvalds #include <linux/time.h>
181da177e4SLinus Torvalds #include <linux/init.h>
19d43c36dcSAlexey Dobriyan #include <linux/sched.h>
201da177e4SLinus Torvalds #include <linux/smp.h>
211da177e4SLinus Torvalds #include <linux/timex.h>
221da177e4SLinus Torvalds #include <linux/errno.h>
231da177e4SLinus Torvalds #include <linux/profile.h>
241da177e4SLinus Torvalds #include <linux/timer.h>
25*f414f13fSArnd Bergmann #include <linux/clocksource.h>
26e317c8ccSFrederik Deweerdt #include <linux/irq.h>
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds #include <asm/thread_info.h>
29211baa70SRussell King #include <asm/sched_clock.h>
302d7c11bfSCatalin Marinas #include <asm/stacktrace.h>
318ff1443cSRussell King #include <asm/mach/arch.h>
321da177e4SLinus Torvalds #include <asm/mach/time.h>
331da177e4SLinus Torvalds 
3463216d3cSArnd Bergmann #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \
3563216d3cSArnd Bergmann     defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE)
361da177e4SLinus Torvalds /* this needs a better home */
371da177e4SLinus Torvalds DEFINE_SPINLOCK(rtc_lock);
381da177e4SLinus Torvalds EXPORT_SYMBOL(rtc_lock);
399dd34948SDavid Brownell #endif	/* pc-style 'CMOS' RTC support */
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds /* change this if you have some constant time drift */
421da177e4SLinus Torvalds #define USECS_PER_JIFFY	(1000000/HZ)
431da177e4SLinus Torvalds 
441da177e4SLinus Torvalds #ifdef CONFIG_SMP
451da177e4SLinus Torvalds unsigned long profile_pc(struct pt_regs *regs)
461da177e4SLinus Torvalds {
472d7c11bfSCatalin Marinas 	struct stackframe frame;
481da177e4SLinus Torvalds 
492d7c11bfSCatalin Marinas 	if (!in_lock_functions(regs->ARM_pc))
502d7c11bfSCatalin Marinas 		return regs->ARM_pc;
511da177e4SLinus Torvalds 
522d7c11bfSCatalin Marinas 	frame.fp = regs->ARM_fp;
532d7c11bfSCatalin Marinas 	frame.sp = regs->ARM_sp;
542d7c11bfSCatalin Marinas 	frame.lr = regs->ARM_lr;
552d7c11bfSCatalin Marinas 	frame.pc = regs->ARM_pc;
562d7c11bfSCatalin Marinas 	do {
572d7c11bfSCatalin Marinas 		int ret = unwind_frame(&frame);
582d7c11bfSCatalin Marinas 		if (ret < 0)
592d7c11bfSCatalin Marinas 			return 0;
602d7c11bfSCatalin Marinas 	} while (in_lock_functions(frame.pc));
612d7c11bfSCatalin Marinas 
622d7c11bfSCatalin Marinas 	return frame.pc;
631da177e4SLinus Torvalds }
641da177e4SLinus Torvalds EXPORT_SYMBOL(profile_pc);
651da177e4SLinus Torvalds #endif
661da177e4SLinus Torvalds 
679e4559ddSKevin Hilman #ifndef CONFIG_GENERIC_CLOCKEVENTS
681da177e4SLinus Torvalds /*
691da177e4SLinus Torvalds  * Kernel system timer support.
701da177e4SLinus Torvalds  */
710cd61b68SLinus Torvalds void timer_tick(void)
721da177e4SLinus Torvalds {
73e317c8ccSFrederik Deweerdt 	profile_tick(CPU_PROFILING);
746906e33cSTorben Hohn 	xtime_update(1);
751da177e4SLinus Torvalds #ifndef CONFIG_SMP
76c97d4869SRussell King 	update_process_times(user_mode(get_irq_regs()));
771da177e4SLinus Torvalds #endif
781da177e4SLinus Torvalds }
799e4559ddSKevin Hilman #endif
801da177e4SLinus Torvalds 
81bd0493eaSMarc Zyngier static void dummy_clock_access(struct timespec *ts)
82bd0493eaSMarc Zyngier {
83bd0493eaSMarc Zyngier 	ts->tv_sec = 0;
84bd0493eaSMarc Zyngier 	ts->tv_nsec = 0;
85bd0493eaSMarc Zyngier }
86bd0493eaSMarc Zyngier 
87bd0493eaSMarc Zyngier static clock_access_fn __read_persistent_clock = dummy_clock_access;
88bd0493eaSMarc Zyngier static clock_access_fn __read_boot_clock = dummy_clock_access;;
89bd0493eaSMarc Zyngier 
90bd0493eaSMarc Zyngier void read_persistent_clock(struct timespec *ts)
91bd0493eaSMarc Zyngier {
92bd0493eaSMarc Zyngier 	__read_persistent_clock(ts);
93bd0493eaSMarc Zyngier }
94bd0493eaSMarc Zyngier 
95bd0493eaSMarc Zyngier void read_boot_clock(struct timespec *ts)
96bd0493eaSMarc Zyngier {
97bd0493eaSMarc Zyngier 	__read_boot_clock(ts);
98bd0493eaSMarc Zyngier }
99bd0493eaSMarc Zyngier 
100bd0493eaSMarc Zyngier int __init register_persistent_clock(clock_access_fn read_boot,
101bd0493eaSMarc Zyngier 				     clock_access_fn read_persistent)
102bd0493eaSMarc Zyngier {
103bd0493eaSMarc Zyngier 	/* Only allow the clockaccess functions to be registered once */
104bd0493eaSMarc Zyngier 	if (__read_persistent_clock == dummy_clock_access &&
105bd0493eaSMarc Zyngier 	    __read_boot_clock == dummy_clock_access) {
106bd0493eaSMarc Zyngier 		if (read_boot)
107bd0493eaSMarc Zyngier 			__read_boot_clock = read_boot;
108bd0493eaSMarc Zyngier 		if (read_persistent)
109bd0493eaSMarc Zyngier 			__read_persistent_clock = read_persistent;
110bd0493eaSMarc Zyngier 
111bd0493eaSMarc Zyngier 		return 0;
112bd0493eaSMarc Zyngier 	}
113bd0493eaSMarc Zyngier 
114bd0493eaSMarc Zyngier 	return -EINVAL;
115bd0493eaSMarc Zyngier }
116bd0493eaSMarc Zyngier 
1171da177e4SLinus Torvalds void __init time_init(void)
1181da177e4SLinus Torvalds {
119*f414f13fSArnd Bergmann 	if (machine_desc->init_time)
1206bb27d73SStephen Warren 		machine_desc->init_time();
121*f414f13fSArnd Bergmann 	else
122*f414f13fSArnd Bergmann 		clocksource_of_init();
123*f414f13fSArnd Bergmann 
124211baa70SRussell King 	sched_clock_postinit();
1251da177e4SLinus Torvalds }
126