~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm26/kernel/time.c

Version: ~ [ linux-5.2-rc1 ] ~ [ linux-5.1.2 ] ~ [ linux-5.0.16 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.43 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.119 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.176 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.179 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.139 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.67 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/arch/arm26/kernel/time.c
  3  *
  4  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
  5  *  Modifications for ARM (C) 1994-2001 Russell King
  6  *  Mods for ARM26 (C) 2003 Ian Molton
  7  *
  8  * This program is free software; you can redistribute it and/or modify
  9  * it under the terms of the GNU General Public License version 2 as
 10  * published by the Free Software Foundation.
 11  *
 12  *  This file contains the ARM-specific time handling details:
 13  *  reading the RTC at bootup, etc...
 14  *
 15  *  1994-07-02  Alan Modra
 16  *              fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
 17  *  1998-12-20  Updated NTP code according to technical memorandum Jan '96
 18  *              "A Kernel Model for Precision Timekeeping" by Dave Mills
 19  */
 20 
 21 #include <linux/config.h>
 22 #include <linux/module.h>
 23 #include <linux/kernel.h>
 24 #include <linux/interrupt.h>
 25 #include <linux/time.h>
 26 #include <linux/init.h>
 27 #include <linux/smp.h>
 28 #include <linux/timex.h>
 29 #include <linux/errno.h>
 30 #include <linux/profile.h>
 31 
 32 #include <asm/hardware.h>
 33 #include <asm/io.h>
 34 #include <asm/irq.h>
 35 #include <asm/leds.h>
 36 
 37 u64 jiffies_64 = INITIAL_JIFFIES;
 38 
 39 EXPORT_SYMBOL(jiffies_64);
 40 
 41 extern unsigned long wall_jiffies;
 42 
 43 /* this needs a better home */
 44 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
 45 
 46 /* change this if you have some constant time drift */
 47 #define USECS_PER_JIFFY (1000000/HZ)
 48 
 49 static int dummy_set_rtc(void)
 50 {
 51         return 0;
 52 }
 53 
 54 /*
 55  * hook for setting the RTC's idea of the current time.
 56  */
 57 int (*set_rtc)(void) = dummy_set_rtc;
 58 
 59 static unsigned long dummy_gettimeoffset(void)
 60 {
 61         return 0;
 62 }
 63 
 64 /*
 65  * hook for getting the time offset.  Note that it is
 66  * always called with interrupts disabled.
 67  */
 68 unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset;
 69 
 70 /*
 71  * Handle kernel profile stuff...
 72  */
 73 static inline void do_profile(struct pt_regs *regs)
 74 {
 75         if (!user_mode(regs) &&
 76             prof_buffer &&
 77             current->pid) {
 78                 unsigned long pc = instruction_pointer(regs);
 79                 extern int _stext;
 80 
 81                 pc -= (unsigned long)&_stext;
 82 
 83                 pc >>= prof_shift;
 84 
 85                 if (pc >= prof_len)
 86                         pc = prof_len - 1;
 87 
 88                 prof_buffer[pc] += 1;
 89         }
 90 }
 91 
 92 static unsigned long next_rtc_update;
 93 
 94 /*
 95  * If we have an externally synchronized linux clock, then update
 96  * CMOS clock accordingly every ~11 minutes.  set_rtc() has to be
 97  * called as close as possible to 500 ms before the new second
 98  * starts.
 99  */
100 static inline void do_set_rtc(void)
101 {
102         if (time_status & STA_UNSYNC || set_rtc == NULL)
103                 return;
104 
105 //FIXME - timespec.tv_sec is a time_t not unsigned long
106         if (next_rtc_update &&
107             time_before((unsigned long)xtime.tv_sec, next_rtc_update))
108                 return;
109 
110         if (xtime.tv_nsec < 500000000 - ((unsigned) tick_nsec >> 1) &&
111             xtime.tv_nsec >= 500000000 + ((unsigned) tick_nsec >> 1))
112                 return;
113 
114         if (set_rtc())
115                 /*
116                  * rtc update failed.  Try again in 60s
117                  */
118                 next_rtc_update = xtime.tv_sec + 60;
119         else
120                 next_rtc_update = xtime.tv_sec + 660;
121 }
122 
123 #define do_leds()
124 
125 void do_gettimeofday(struct timeval *tv)
126 {
127         unsigned long flags;
128         unsigned long seq;
129         unsigned long usec, sec, lost;
130 
131         do {
132                 seq = read_seqbegin_irqsave(&xtime_lock, flags);
133                 usec = gettimeoffset();
134 
135                 lost = jiffies - wall_jiffies;
136                 if (lost)
137                         usec += lost * USECS_PER_JIFFY;
138 
139                 sec = xtime.tv_sec;
140                 usec += xtime.tv_nsec / 1000;
141         } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
142 
143         /* usec may have gone up a lot: be safe */
144         while (usec >= 1000000) {
145                 usec -= 1000000;
146                 sec++;
147         }
148 
149         tv->tv_sec = sec;
150         tv->tv_usec = usec;
151 }
152 
153 EXPORT_SYMBOL(do_gettimeofday);
154 
155 int do_settimeofday(struct timespec *tv)
156 {
157         if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
158                 return -EINVAL;
159 
160         write_seqlock_irq(&xtime_lock);
161         /*
162          * This is revolting. We need to set "xtime" correctly. However, the
163          * value in this location is the value at the most recent update of
164          * wall time.  Discover what correction gettimeofday() would have
165          * done, and then undo it!
166          */
167         tv->tv_nsec -= 1000 * (gettimeoffset() +
168                         (jiffies - wall_jiffies) * USECS_PER_JIFFY);
169 
170         while (tv->tv_nsec < 0) {
171                 tv->tv_nsec += NSEC_PER_SEC;
172                 tv->tv_sec--;
173         }
174 
175         xtime.tv_sec = tv->tv_sec;
176         xtime.tv_nsec = tv->tv_nsec;
177         time_adjust = 0;                /* stop active adjtime() */
178         time_status |= STA_UNSYNC;
179         time_maxerror = NTP_PHASE_LIMIT;
180         time_esterror = NTP_PHASE_LIMIT;
181         write_sequnlock_irq(&xtime_lock);
182         return 0;
183 }
184 
185 EXPORT_SYMBOL(do_settimeofday);
186 
187 static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
188 {
189         do_timer(regs);
190         do_set_rtc(); //FIME - EVERY timer IRQ?
191         do_profile(regs);
192         return IRQ_HANDLED; //FIXME - is this right?
193 }
194 
195 static struct irqaction timer_irq = {
196         .name   = "timer",
197         .flags  = SA_INTERRUPT,
198         .handler = timer_interrupt,
199 };
200 
201 extern void ioctime_init(void);
202 
203 /*
204  * Set up timer interrupt.
205  */
206 void __init time_init(void)
207 {
208         ioctime_init();
209 
210         setup_irq(IRQ_TIMER, &timer_irq);
211 }
212 
213 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp