1 /* 2 * linux/arch/arm/kernel/time.c 3 * 4 * Copyright (C) 1991, 1992, 1995 Linus Torvalds 5 * Modifications for ARM (C) 1994-2001 Russell King 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * This file contains the ARM-specific time handling details: 12 * reading the RTC at bootup, etc... 13 */ 14 #include <linux/module.h> 15 #include <linux/kernel.h> 16 #include <linux/interrupt.h> 17 #include <linux/time.h> 18 #include <linux/init.h> 19 #include <linux/sched.h> 20 #include <linux/smp.h> 21 #include <linux/timex.h> 22 #include <linux/errno.h> 23 #include <linux/profile.h> 24 #include <linux/sysdev.h> 25 #include <linux/timer.h> 26 #include <linux/irq.h> 27 28 #include <linux/mc146818rtc.h> 29 30 #include <asm/leds.h> 31 #include <asm/thread_info.h> 32 #include <asm/stacktrace.h> 33 #include <asm/mach/time.h> 34 35 /* 36 * Our system timer. 37 */ 38 struct sys_timer *system_timer; 39 40 #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) 41 /* this needs a better home */ 42 DEFINE_SPINLOCK(rtc_lock); 43 44 #ifdef CONFIG_RTC_DRV_CMOS_MODULE 45 EXPORT_SYMBOL(rtc_lock); 46 #endif 47 #endif /* pc-style 'CMOS' RTC support */ 48 49 /* change this if you have some constant time drift */ 50 #define USECS_PER_JIFFY (1000000/HZ) 51 52 #ifdef CONFIG_SMP 53 unsigned long profile_pc(struct pt_regs *regs) 54 { 55 struct stackframe frame; 56 57 if (!in_lock_functions(regs->ARM_pc)) 58 return regs->ARM_pc; 59 60 frame.fp = regs->ARM_fp; 61 frame.sp = regs->ARM_sp; 62 frame.lr = regs->ARM_lr; 63 frame.pc = regs->ARM_pc; 64 do { 65 int ret = unwind_frame(&frame); 66 if (ret < 0) 67 return 0; 68 } while (in_lock_functions(frame.pc)); 69 70 return frame.pc; 71 } 72 EXPORT_SYMBOL(profile_pc); 73 #endif 74 75 #ifndef CONFIG_GENERIC_TIME 76 static unsigned long dummy_gettimeoffset(void) 77 { 78 return 0; 79 } 80 #endif 81 82 #ifdef CONFIG_LEDS_TIMER 83 static inline void do_leds(void) 84 { 85 static unsigned int count = HZ/2; 86 87 if (--count == 0) { 88 count = HZ/2; 89 leds_event(led_timer); 90 } 91 } 92 #else 93 #define do_leds() 94 #endif 95 96 #ifndef CONFIG_GENERIC_TIME 97 void do_gettimeofday(struct timeval *tv) 98 { 99 unsigned long flags; 100 unsigned long seq; 101 unsigned long usec, sec; 102 103 do { 104 seq = read_seqbegin_irqsave(&xtime_lock, flags); 105 usec = system_timer->offset(); 106 sec = xtime.tv_sec; 107 usec += xtime.tv_nsec / 1000; 108 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); 109 110 /* usec may have gone up a lot: be safe */ 111 while (usec >= 1000000) { 112 usec -= 1000000; 113 sec++; 114 } 115 116 tv->tv_sec = sec; 117 tv->tv_usec = usec; 118 } 119 120 EXPORT_SYMBOL(do_gettimeofday); 121 122 int do_settimeofday(struct timespec *tv) 123 { 124 time_t wtm_sec, sec = tv->tv_sec; 125 long wtm_nsec, nsec = tv->tv_nsec; 126 127 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) 128 return -EINVAL; 129 130 write_seqlock_irq(&xtime_lock); 131 /* 132 * This is revolting. We need to set "xtime" correctly. However, the 133 * value in this location is the value at the most recent update of 134 * wall time. Discover what correction gettimeofday() would have 135 * done, and then undo it! 136 */ 137 nsec -= system_timer->offset() * NSEC_PER_USEC; 138 139 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); 140 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); 141 142 set_normalized_timespec(&xtime, sec, nsec); 143 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); 144 145 ntp_clear(); 146 write_sequnlock_irq(&xtime_lock); 147 clock_was_set(); 148 return 0; 149 } 150 151 EXPORT_SYMBOL(do_settimeofday); 152 #endif /* !CONFIG_GENERIC_TIME */ 153 154 #ifndef CONFIG_GENERIC_CLOCKEVENTS 155 /* 156 * Kernel system timer support. 157 */ 158 void timer_tick(void) 159 { 160 profile_tick(CPU_PROFILING); 161 do_leds(); 162 write_seqlock(&xtime_lock); 163 do_timer(1); 164 write_sequnlock(&xtime_lock); 165 #ifndef CONFIG_SMP 166 update_process_times(user_mode(get_irq_regs())); 167 #endif 168 } 169 #endif 170 171 #if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS) 172 static int timer_suspend(struct sys_device *dev, pm_message_t state) 173 { 174 struct sys_timer *timer = container_of(dev, struct sys_timer, dev); 175 176 if (timer->suspend != NULL) 177 timer->suspend(); 178 179 return 0; 180 } 181 182 static int timer_resume(struct sys_device *dev) 183 { 184 struct sys_timer *timer = container_of(dev, struct sys_timer, dev); 185 186 if (timer->resume != NULL) 187 timer->resume(); 188 189 return 0; 190 } 191 #else 192 #define timer_suspend NULL 193 #define timer_resume NULL 194 #endif 195 196 static struct sysdev_class timer_sysclass = { 197 .name = "timer", 198 .suspend = timer_suspend, 199 .resume = timer_resume, 200 }; 201 202 static int __init timer_init_sysfs(void) 203 { 204 int ret = sysdev_class_register(&timer_sysclass); 205 if (ret == 0) { 206 system_timer->dev.cls = &timer_sysclass; 207 ret = sysdev_register(&system_timer->dev); 208 } 209 210 return ret; 211 } 212 213 device_initcall(timer_init_sysfs); 214 215 void __init time_init(void) 216 { 217 #ifndef CONFIG_GENERIC_TIME 218 if (system_timer->offset == NULL) 219 system_timer->offset = dummy_gettimeoffset; 220 #endif 221 system_timer->init(); 222 } 223 224