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 */ 14*4178bac4SSebastian Hesselbarth #include <linux/clk-provider.h> 15f414f13fSArnd Bergmann #include <linux/clocksource.h> 16*4178bac4SSebastian Hesselbarth #include <linux/errno.h> 17*4178bac4SSebastian Hesselbarth #include <linux/export.h> 18*4178bac4SSebastian Hesselbarth #include <linux/init.h> 19*4178bac4SSebastian Hesselbarth #include <linux/interrupt.h> 20e317c8ccSFrederik Deweerdt #include <linux/irq.h> 21*4178bac4SSebastian Hesselbarth #include <linux/kernel.h> 22*4178bac4SSebastian Hesselbarth #include <linux/profile.h> 23*4178bac4SSebastian Hesselbarth #include <linux/sched.h> 2438ff87f7SStephen Boyd #include <linux/sched_clock.h> 25*4178bac4SSebastian Hesselbarth #include <linux/smp.h> 26*4178bac4SSebastian Hesselbarth #include <linux/time.h> 27*4178bac4SSebastian Hesselbarth #include <linux/timex.h> 28*4178bac4SSebastian Hesselbarth #include <linux/timer.h> 291da177e4SLinus Torvalds 308ff1443cSRussell King #include <asm/mach/arch.h> 311da177e4SLinus Torvalds #include <asm/mach/time.h> 32*4178bac4SSebastian Hesselbarth #include <asm/stacktrace.h> 33*4178bac4SSebastian Hesselbarth #include <asm/thread_info.h> 341da177e4SLinus Torvalds 3563216d3cSArnd Bergmann #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \ 3663216d3cSArnd Bergmann defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) 371da177e4SLinus Torvalds /* this needs a better home */ 381da177e4SLinus Torvalds DEFINE_SPINLOCK(rtc_lock); 391da177e4SLinus Torvalds EXPORT_SYMBOL(rtc_lock); 409dd34948SDavid Brownell #endif /* pc-style 'CMOS' RTC support */ 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds /* change this if you have some constant time drift */ 431da177e4SLinus Torvalds #define USECS_PER_JIFFY (1000000/HZ) 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds #ifdef CONFIG_SMP 461da177e4SLinus Torvalds unsigned long profile_pc(struct pt_regs *regs) 471da177e4SLinus Torvalds { 482d7c11bfSCatalin Marinas struct stackframe frame; 491da177e4SLinus Torvalds 502d7c11bfSCatalin Marinas if (!in_lock_functions(regs->ARM_pc)) 512d7c11bfSCatalin Marinas return regs->ARM_pc; 521da177e4SLinus Torvalds 532d7c11bfSCatalin Marinas frame.fp = regs->ARM_fp; 542d7c11bfSCatalin Marinas frame.sp = regs->ARM_sp; 552d7c11bfSCatalin Marinas frame.lr = regs->ARM_lr; 562d7c11bfSCatalin Marinas frame.pc = regs->ARM_pc; 572d7c11bfSCatalin Marinas do { 582d7c11bfSCatalin Marinas int ret = unwind_frame(&frame); 592d7c11bfSCatalin Marinas if (ret < 0) 602d7c11bfSCatalin Marinas return 0; 612d7c11bfSCatalin Marinas } while (in_lock_functions(frame.pc)); 622d7c11bfSCatalin Marinas 632d7c11bfSCatalin Marinas return frame.pc; 641da177e4SLinus Torvalds } 651da177e4SLinus Torvalds EXPORT_SYMBOL(profile_pc); 661da177e4SLinus Torvalds #endif 671da177e4SLinus Torvalds 689e4559ddSKevin Hilman #ifndef CONFIG_GENERIC_CLOCKEVENTS 691da177e4SLinus Torvalds /* 701da177e4SLinus Torvalds * Kernel system timer support. 711da177e4SLinus Torvalds */ 720cd61b68SLinus Torvalds void timer_tick(void) 731da177e4SLinus Torvalds { 74e317c8ccSFrederik Deweerdt profile_tick(CPU_PROFILING); 756906e33cSTorben Hohn xtime_update(1); 761da177e4SLinus Torvalds #ifndef CONFIG_SMP 77c97d4869SRussell King update_process_times(user_mode(get_irq_regs())); 781da177e4SLinus Torvalds #endif 791da177e4SLinus Torvalds } 809e4559ddSKevin Hilman #endif 811da177e4SLinus Torvalds 82bd0493eaSMarc Zyngier static void dummy_clock_access(struct timespec *ts) 83bd0493eaSMarc Zyngier { 84bd0493eaSMarc Zyngier ts->tv_sec = 0; 85bd0493eaSMarc Zyngier ts->tv_nsec = 0; 86bd0493eaSMarc Zyngier } 87bd0493eaSMarc Zyngier 88bd0493eaSMarc Zyngier static clock_access_fn __read_persistent_clock = dummy_clock_access; 89bd0493eaSMarc Zyngier static clock_access_fn __read_boot_clock = dummy_clock_access;; 90bd0493eaSMarc Zyngier 91bd0493eaSMarc Zyngier void read_persistent_clock(struct timespec *ts) 92bd0493eaSMarc Zyngier { 93bd0493eaSMarc Zyngier __read_persistent_clock(ts); 94bd0493eaSMarc Zyngier } 95bd0493eaSMarc Zyngier 96bd0493eaSMarc Zyngier void read_boot_clock(struct timespec *ts) 97bd0493eaSMarc Zyngier { 98bd0493eaSMarc Zyngier __read_boot_clock(ts); 99bd0493eaSMarc Zyngier } 100bd0493eaSMarc Zyngier 101bd0493eaSMarc Zyngier int __init register_persistent_clock(clock_access_fn read_boot, 102bd0493eaSMarc Zyngier clock_access_fn read_persistent) 103bd0493eaSMarc Zyngier { 104bd0493eaSMarc Zyngier /* Only allow the clockaccess functions to be registered once */ 105bd0493eaSMarc Zyngier if (__read_persistent_clock == dummy_clock_access && 106bd0493eaSMarc Zyngier __read_boot_clock == dummy_clock_access) { 107bd0493eaSMarc Zyngier if (read_boot) 108bd0493eaSMarc Zyngier __read_boot_clock = read_boot; 109bd0493eaSMarc Zyngier if (read_persistent) 110bd0493eaSMarc Zyngier __read_persistent_clock = read_persistent; 111bd0493eaSMarc Zyngier 112bd0493eaSMarc Zyngier return 0; 113bd0493eaSMarc Zyngier } 114bd0493eaSMarc Zyngier 115bd0493eaSMarc Zyngier return -EINVAL; 116bd0493eaSMarc Zyngier } 117bd0493eaSMarc Zyngier 1181da177e4SLinus Torvalds void __init time_init(void) 1191da177e4SLinus Torvalds { 120*4178bac4SSebastian Hesselbarth if (machine_desc->init_time) { 1216bb27d73SStephen Warren machine_desc->init_time(); 122*4178bac4SSebastian Hesselbarth } else { 123*4178bac4SSebastian Hesselbarth #ifdef CONFIG_COMMON_CLK 124*4178bac4SSebastian Hesselbarth of_clk_init(NULL); 125*4178bac4SSebastian Hesselbarth #endif 126f414f13fSArnd Bergmann clocksource_of_init(); 1271da177e4SLinus Torvalds } 128*4178bac4SSebastian Hesselbarth } 129