diff options
| -rw-r--r-- | arch/xtensa/Kconfig | 3 | ||||
| -rw-r--r-- | arch/xtensa/kernel/time.c | 103 |
2 files changed, 33 insertions, 73 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 7bbc6c19289c..fa6dc4dd3b19 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig | |||
| @@ -48,6 +48,9 @@ config HZ | |||
| 48 | int | 48 | int |
| 49 | default 100 | 49 | default 100 |
| 50 | 50 | ||
| 51 | config GENERIC_TIME | ||
| 52 | def_bool y | ||
| 53 | |||
| 51 | source "init/Kconfig" | 54 | source "init/Kconfig" |
| 52 | source "kernel/Kconfig.freezer" | 55 | source "kernel/Kconfig.freezer" |
| 53 | 56 | ||
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index db14a3d88db7..8848120d291b 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
| 16 | #include <linux/time.h> | 16 | #include <linux/time.h> |
| 17 | #include <linux/clocksource.h> | ||
| 17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
| 18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| @@ -29,6 +30,26 @@ unsigned long ccount_per_jiffy; /* per 1/HZ */ | |||
| 29 | unsigned long nsec_per_ccount; /* nsec per ccount increment */ | 30 | unsigned long nsec_per_ccount; /* nsec per ccount increment */ |
| 30 | #endif | 31 | #endif |
| 31 | 32 | ||
| 33 | static cycle_t ccount_read(void) | ||
| 34 | { | ||
| 35 | return (cycle_t)get_ccount(); | ||
| 36 | } | ||
| 37 | |||
| 38 | static struct clocksource ccount_clocksource = { | ||
| 39 | .name = "ccount", | ||
| 40 | .rating = 200, | ||
| 41 | .read = ccount_read, | ||
| 42 | .mask = CLOCKSOURCE_MASK(32), | ||
| 43 | /* | ||
| 44 | * With a shift of 22 the lower limit of the cpu clock is | ||
| 45 | * 1MHz, where NSEC_PER_CCOUNT is 1000 or a bit less than | ||
| 46 | * 2^10: Since we have 32 bits and the multiplicator can | ||
| 47 | * already take up as much as 10 bits, this leaves us with | ||
| 48 | * remaining upper 22 bits. | ||
| 49 | */ | ||
| 50 | .shift = 22, | ||
| 51 | }; | ||
| 52 | |||
| 32 | static irqreturn_t timer_interrupt(int irq, void *dev_id); | 53 | static irqreturn_t timer_interrupt(int irq, void *dev_id); |
| 33 | static struct irqaction timer_irqaction = { | 54 | static struct irqaction timer_irqaction = { |
| 34 | .handler = timer_interrupt, | 55 | .handler = timer_interrupt, |
| @@ -38,9 +59,11 @@ static struct irqaction timer_irqaction = { | |||
| 38 | 59 | ||
| 39 | void __init time_init(void) | 60 | void __init time_init(void) |
| 40 | { | 61 | { |
| 41 | /* The platform must provide a function to calibrate the processor | 62 | xtime.tv_nsec = 0; |
| 42 | * speed for the CALIBRATE. | 63 | xtime.tv_sec = read_persistent_clock(); |
| 43 | */ | 64 | |
| 65 | set_normalized_timespec(&wall_to_monotonic, | ||
| 66 | -xtime.tv_sec, -xtime.tv_nsec); | ||
| 44 | 67 | ||
| 45 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT | 68 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT |
| 46 | printk("Calibrating CPU frequency "); | 69 | printk("Calibrating CPU frequency "); |
| @@ -48,12 +71,10 @@ void __init time_init(void) | |||
| 48 | printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ), | 71 | printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ), |
| 49 | (int)(ccount_per_jiffy/(10000/HZ))%100); | 72 | (int)(ccount_per_jiffy/(10000/HZ))%100); |
| 50 | #endif | 73 | #endif |
| 51 | 74 | ccount_clocksource.mult = | |
| 52 | xtime.tv_nsec = 0; | 75 | clocksource_hz2mult(CCOUNT_PER_JIFFY * HZ, |
| 53 | xtime.tv_sec = read_persistent_clock(); | 76 | ccount_clocksource.shift); |
| 54 | 77 | clocksource_register(&ccount_clocksource); | |
| 55 | set_normalized_timespec(&wall_to_monotonic, | ||
| 56 | -xtime.tv_sec, -xtime.tv_nsec); | ||
| 57 | 78 | ||
| 58 | /* Initialize the linux timer interrupt. */ | 79 | /* Initialize the linux timer interrupt. */ |
| 59 | 80 | ||
| @@ -61,69 +82,6 @@ void __init time_init(void) | |||
| 61 | set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY); | 82 | set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY); |
| 62 | } | 83 | } |
| 63 | 84 | ||
| 64 | |||
| 65 | int do_settimeofday(struct timespec *tv) | ||
| 66 | { | ||
| 67 | time_t wtm_sec, sec = tv->tv_sec; | ||
| 68 | long wtm_nsec, nsec = tv->tv_nsec; | ||
| 69 | unsigned long delta; | ||
| 70 | |||
| 71 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | ||
| 72 | return -EINVAL; | ||
| 73 | |||
| 74 | write_seqlock_irq(&xtime_lock); | ||
| 75 | |||
| 76 | /* This is revolting. We need to set "xtime" correctly. However, the | ||
| 77 | * value in this location is the value at the most recent update of | ||
| 78 | * wall time. Discover what correction gettimeofday() would have | ||
| 79 | * made, and then undo it! | ||
| 80 | */ | ||
| 81 | |||
| 82 | delta = CCOUNT_PER_JIFFY; | ||
| 83 | delta += get_ccount() - get_linux_timer(); | ||
| 84 | nsec -= delta * NSEC_PER_CCOUNT; | ||
| 85 | |||
| 86 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); | ||
| 87 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); | ||
| 88 | |||
| 89 | set_normalized_timespec(&xtime, sec, nsec); | ||
| 90 | set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); | ||
| 91 | |||
| 92 | ntp_clear(); | ||
| 93 | write_sequnlock_irq(&xtime_lock); | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | EXPORT_SYMBOL(do_settimeofday); | ||
| 98 | |||
| 99 | |||
| 100 | void do_gettimeofday(struct timeval *tv) | ||
| 101 | { | ||
| 102 | unsigned long flags; | ||
| 103 | unsigned long volatile sec, usec, delta, seq; | ||
| 104 | |||
| 105 | do { | ||
| 106 | seq = read_seqbegin_irqsave(&xtime_lock, flags); | ||
| 107 | |||
| 108 | sec = xtime.tv_sec; | ||
| 109 | usec = (xtime.tv_nsec / NSEC_PER_USEC); | ||
| 110 | |||
| 111 | delta = get_linux_timer() - get_ccount(); | ||
| 112 | |||
| 113 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
| 114 | |||
| 115 | usec += (((unsigned long) CCOUNT_PER_JIFFY - delta) | ||
| 116 | * (unsigned long) NSEC_PER_CCOUNT) / NSEC_PER_USEC; | ||
| 117 | |||
| 118 | for (; usec >= 1000000; sec++, usec -= 1000000) | ||
| 119 | ; | ||
| 120 | |||
| 121 | tv->tv_sec = sec; | ||
| 122 | tv->tv_usec = usec; | ||
| 123 | } | ||
| 124 | |||
| 125 | EXPORT_SYMBOL(do_gettimeofday); | ||
| 126 | |||
| 127 | /* | 85 | /* |
| 128 | * The timer interrupt is called HZ times per second. | 86 | * The timer interrupt is called HZ times per second. |
| 129 | */ | 87 | */ |
| @@ -177,4 +135,3 @@ void __cpuinit calibrate_delay(void) | |||
| 177 | (loops_per_jiffy/(10000/HZ)) % 100); | 135 | (loops_per_jiffy/(10000/HZ)) % 100); |
| 178 | } | 136 | } |
| 179 | #endif | 137 | #endif |
| 180 | |||
