diff options
Diffstat (limited to 'arch/xtensa/kernel/time.c')
| -rw-r--r-- | arch/xtensa/kernel/time.c | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 22949be4a5d8..60d29fe0b1bd 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c | |||
| @@ -32,12 +32,20 @@ EXPORT_SYMBOL(rtc_lock); | |||
| 32 | 32 | ||
| 33 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT | 33 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT |
| 34 | unsigned long ccount_per_jiffy; /* per 1/HZ */ | 34 | unsigned long ccount_per_jiffy; /* per 1/HZ */ |
| 35 | unsigned long ccount_nsec; /* nsec per ccount increment */ | 35 | unsigned long nsec_per_ccount; /* nsec per ccount increment */ |
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | unsigned int last_ccount_stamp; | ||
| 39 | static long last_rtc_update = 0; | 38 | static long last_rtc_update = 0; |
| 40 | 39 | ||
| 40 | /* | ||
| 41 | * Scheduler clock - returns current tim in nanosec units. | ||
| 42 | */ | ||
| 43 | |||
| 44 | unsigned long long sched_clock(void) | ||
| 45 | { | ||
| 46 | return (unsigned long long)jiffies * (1000000000 / HZ); | ||
| 47 | } | ||
| 48 | |||
| 41 | static irqreturn_t timer_interrupt(int irq, void *dev_id); | 49 | static irqreturn_t timer_interrupt(int irq, void *dev_id); |
| 42 | static struct irqaction timer_irqaction = { | 50 | static struct irqaction timer_irqaction = { |
| 43 | .handler = timer_interrupt, | 51 | .handler = timer_interrupt, |
| @@ -69,7 +77,6 @@ void __init time_init(void) | |||
| 69 | 77 | ||
| 70 | xtime.tv_nsec = 0; | 78 | xtime.tv_nsec = 0; |
| 71 | last_rtc_update = xtime.tv_sec = sec_n; | 79 | last_rtc_update = xtime.tv_sec = sec_n; |
| 72 | last_ccount_stamp = get_ccount(); | ||
| 73 | 80 | ||
| 74 | set_normalized_timespec(&wall_to_monotonic, | 81 | set_normalized_timespec(&wall_to_monotonic, |
| 75 | -xtime.tv_sec, -xtime.tv_nsec); | 82 | -xtime.tv_sec, -xtime.tv_nsec); |
| @@ -85,7 +92,7 @@ int do_settimeofday(struct timespec *tv) | |||
| 85 | { | 92 | { |
| 86 | time_t wtm_sec, sec = tv->tv_sec; | 93 | time_t wtm_sec, sec = tv->tv_sec; |
| 87 | long wtm_nsec, nsec = tv->tv_nsec; | 94 | long wtm_nsec, nsec = tv->tv_nsec; |
| 88 | unsigned long ccount; | 95 | unsigned long delta; |
| 89 | 96 | ||
| 90 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | 97 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) |
| 91 | return -EINVAL; | 98 | return -EINVAL; |
| @@ -97,8 +104,10 @@ int do_settimeofday(struct timespec *tv) | |||
| 97 | * wall time. Discover what correction gettimeofday() would have | 104 | * wall time. Discover what correction gettimeofday() would have |
| 98 | * made, and then undo it! | 105 | * made, and then undo it! |
| 99 | */ | 106 | */ |
| 100 | ccount = get_ccount(); | 107 | |
| 101 | nsec -= (ccount - last_ccount_stamp) * CCOUNT_NSEC; | 108 | delta = CCOUNT_PER_JIFFY; |
| 109 | delta += get_ccount() - get_linux_timer(); | ||
| 110 | nsec -= delta * NSEC_PER_CCOUNT; | ||
| 102 | 111 | ||
| 103 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); | 112 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); |
| 104 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); | 113 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); |
| @@ -117,17 +126,21 @@ EXPORT_SYMBOL(do_settimeofday); | |||
| 117 | void do_gettimeofday(struct timeval *tv) | 126 | void do_gettimeofday(struct timeval *tv) |
| 118 | { | 127 | { |
| 119 | unsigned long flags; | 128 | unsigned long flags; |
| 120 | unsigned long sec, usec, delta, seq; | 129 | unsigned long volatile sec, usec, delta, seq; |
| 121 | 130 | ||
| 122 | do { | 131 | do { |
| 123 | seq = read_seqbegin_irqsave(&xtime_lock, flags); | 132 | seq = read_seqbegin_irqsave(&xtime_lock, flags); |
| 124 | 133 | ||
| 125 | delta = get_ccount() - last_ccount_stamp; | ||
| 126 | sec = xtime.tv_sec; | 134 | sec = xtime.tv_sec; |
| 127 | usec = (xtime.tv_nsec / NSEC_PER_USEC); | 135 | usec = (xtime.tv_nsec / NSEC_PER_USEC); |
| 136 | |||
| 137 | delta = get_linux_timer() - get_ccount(); | ||
| 138 | |||
| 128 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | 139 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); |
| 129 | 140 | ||
| 130 | usec += (delta * CCOUNT_NSEC) / NSEC_PER_USEC; | 141 | usec += (((unsigned long) CCOUNT_PER_JIFFY - delta) |
| 142 | * (unsigned long) NSEC_PER_CCOUNT) / NSEC_PER_USEC; | ||
| 143 | |||
| 131 | for (; usec >= 1000000; sec++, usec -= 1000000) | 144 | for (; usec >= 1000000; sec++, usec -= 1000000) |
| 132 | ; | 145 | ; |
| 133 | 146 | ||
| @@ -158,9 +171,12 @@ again: | |||
| 158 | 171 | ||
| 159 | write_seqlock(&xtime_lock); | 172 | write_seqlock(&xtime_lock); |
| 160 | 173 | ||
| 161 | last_ccount_stamp = next; | 174 | do_timer(1); /* Linux handler in kernel/timer.c */ |
| 175 | |||
| 176 | /* Note that writing CCOMPARE clears the interrupt. */ | ||
| 177 | |||
| 162 | next += CCOUNT_PER_JIFFY; | 178 | next += CCOUNT_PER_JIFFY; |
| 163 | do_timer (1); /* Linux handler in kernel/timer.c */ | 179 | set_linux_timer(next); |
| 164 | 180 | ||
| 165 | if (ntp_synced() && | 181 | if (ntp_synced() && |
| 166 | xtime.tv_sec - last_rtc_update >= 659 && | 182 | xtime.tv_sec - last_rtc_update >= 659 && |
| @@ -175,19 +191,15 @@ again: | |||
| 175 | write_sequnlock(&xtime_lock); | 191 | write_sequnlock(&xtime_lock); |
| 176 | } | 192 | } |
| 177 | 193 | ||
| 178 | /* NOTE: writing CCOMPAREn clears the interrupt. */ | 194 | /* Allow platform to do something useful (Wdog). */ |
| 179 | 195 | ||
| 180 | set_linux_timer (next); | 196 | platform_heartbeat(); |
| 181 | 197 | ||
| 182 | /* Make sure we didn't miss any tick... */ | 198 | /* Make sure we didn't miss any tick... */ |
| 183 | 199 | ||
| 184 | if ((signed long)(get_ccount() - next) > 0) | 200 | if ((signed long)(get_ccount() - next) > 0) |
| 185 | goto again; | 201 | goto again; |
| 186 | 202 | ||
| 187 | /* Allow platform to do something useful (Wdog). */ | ||
| 188 | |||
| 189 | platform_heartbeat(); | ||
| 190 | |||
| 191 | return IRQ_HANDLED; | 203 | return IRQ_HANDLED; |
| 192 | } | 204 | } |
| 193 | 205 | ||
