diff options
| -rw-r--r-- | arch/arm/include/asm/sched_clock.h | 108 | ||||
| -rw-r--r-- | arch/arm/kernel/sched_clock.c | 118 | ||||
| -rw-r--r-- | arch/arm/mach-ixp4xx/common.c | 16 | ||||
| -rw-r--r-- | arch/arm/mach-mmp/time.c | 16 | ||||
| -rw-r--r-- | arch/arm/mach-omap1/time.c | 58 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/timer.c | 20 | ||||
| -rw-r--r-- | arch/arm/mach-picoxcell/time.c | 17 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/time.c | 15 | ||||
| -rw-r--r-- | arch/arm/mach-sa1100/time.c | 28 | ||||
| -rw-r--r-- | arch/arm/mach-tegra/timer.c | 24 | ||||
| -rw-r--r-- | arch/arm/mach-u300/timer.c | 15 | ||||
| -rw-r--r-- | arch/arm/plat-iop/time.c | 16 | ||||
| -rw-r--r-- | arch/arm/plat-mxc/time.c | 15 | ||||
| -rw-r--r-- | arch/arm/plat-nomadik/timer.c | 20 | ||||
| -rw-r--r-- | arch/arm/plat-omap/counter_32k.c | 40 | ||||
| -rw-r--r-- | arch/arm/plat-omap/include/plat/common.h | 1 | ||||
| -rw-r--r-- | arch/arm/plat-orion/time.c | 21 | ||||
| -rw-r--r-- | arch/arm/plat-s5p/s5p-time.c | 19 | ||||
| -rw-r--r-- | arch/arm/plat-versatile/sched-clock.c | 29 |
19 files changed, 161 insertions, 435 deletions
diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h index c8e6ddf3e860..e3f757263438 100644 --- a/arch/arm/include/asm/sched_clock.h +++ b/arch/arm/include/asm/sched_clock.h | |||
| @@ -8,113 +8,7 @@ | |||
| 8 | #ifndef ASM_SCHED_CLOCK | 8 | #ifndef ASM_SCHED_CLOCK |
| 9 | #define ASM_SCHED_CLOCK | 9 | #define ASM_SCHED_CLOCK |
| 10 | 10 | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/types.h> | ||
| 13 | |||
| 14 | struct clock_data { | ||
| 15 | u64 epoch_ns; | ||
| 16 | u32 epoch_cyc; | ||
| 17 | u32 epoch_cyc_copy; | ||
| 18 | u32 mult; | ||
| 19 | u32 shift; | ||
| 20 | }; | ||
| 21 | |||
| 22 | #define DEFINE_CLOCK_DATA(name) struct clock_data name | ||
| 23 | |||
| 24 | static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift) | ||
| 25 | { | ||
| 26 | return (cyc * mult) >> shift; | ||
| 27 | } | ||
| 28 | |||
| 29 | /* | ||
| 30 | * Atomically update the sched_clock epoch. Your update callback will | ||
| 31 | * be called from a timer before the counter wraps - read the current | ||
| 32 | * counter value, and call this function to safely move the epochs | ||
| 33 | * forward. Only use this from the update callback. | ||
| 34 | */ | ||
| 35 | static inline void update_sched_clock(struct clock_data *cd, u32 cyc, u32 mask) | ||
| 36 | { | ||
| 37 | unsigned long flags; | ||
| 38 | u64 ns = cd->epoch_ns + | ||
| 39 | cyc_to_ns((cyc - cd->epoch_cyc) & mask, cd->mult, cd->shift); | ||
| 40 | |||
| 41 | /* | ||
| 42 | * Write epoch_cyc and epoch_ns in a way that the update is | ||
| 43 | * detectable in cyc_to_fixed_sched_clock(). | ||
| 44 | */ | ||
| 45 | raw_local_irq_save(flags); | ||
| 46 | cd->epoch_cyc = cyc; | ||
| 47 | smp_wmb(); | ||
| 48 | cd->epoch_ns = ns; | ||
| 49 | smp_wmb(); | ||
| 50 | cd->epoch_cyc_copy = cyc; | ||
| 51 | raw_local_irq_restore(flags); | ||
| 52 | } | ||
| 53 | |||
| 54 | /* | ||
| 55 | * If your clock rate is known at compile time, using this will allow | ||
| 56 | * you to optimize the mult/shift loads away. This is paired with | ||
| 57 | * init_fixed_sched_clock() to ensure that your mult/shift are correct. | ||
| 58 | */ | ||
| 59 | static inline unsigned long long cyc_to_fixed_sched_clock(struct clock_data *cd, | ||
| 60 | u32 cyc, u32 mask, u32 mult, u32 shift) | ||
| 61 | { | ||
| 62 | u64 epoch_ns; | ||
| 63 | u32 epoch_cyc; | ||
| 64 | |||
| 65 | /* | ||
| 66 | * Load the epoch_cyc and epoch_ns atomically. We do this by | ||
| 67 | * ensuring that we always write epoch_cyc, epoch_ns and | ||
| 68 | * epoch_cyc_copy in strict order, and read them in strict order. | ||
| 69 | * If epoch_cyc and epoch_cyc_copy are not equal, then we're in | ||
| 70 | * the middle of an update, and we should repeat the load. | ||
| 71 | */ | ||
| 72 | do { | ||
| 73 | epoch_cyc = cd->epoch_cyc; | ||
| 74 | smp_rmb(); | ||
| 75 | epoch_ns = cd->epoch_ns; | ||
| 76 | smp_rmb(); | ||
| 77 | } while (epoch_cyc != cd->epoch_cyc_copy); | ||
| 78 | |||
| 79 | return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, mult, shift); | ||
| 80 | } | ||
| 81 | |||
| 82 | /* | ||
| 83 | * Otherwise, you need to use this, which will obtain the mult/shift | ||
| 84 | * from the clock_data structure. Use init_sched_clock() with this. | ||
| 85 | */ | ||
| 86 | static inline unsigned long long cyc_to_sched_clock(struct clock_data *cd, | ||
| 87 | u32 cyc, u32 mask) | ||
| 88 | { | ||
| 89 | return cyc_to_fixed_sched_clock(cd, cyc, mask, cd->mult, cd->shift); | ||
| 90 | } | ||
| 91 | |||
| 92 | /* | ||
| 93 | * Initialize the clock data - calculate the appropriate multiplier | ||
| 94 | * and shift. Also setup a timer to ensure that the epoch is refreshed | ||
| 95 | * at the appropriate time interval, which will call your update | ||
| 96 | * handler. | ||
| 97 | */ | ||
| 98 | void init_sched_clock(struct clock_data *, void (*)(void), | ||
| 99 | unsigned int, unsigned long); | ||
| 100 | |||
| 101 | /* | ||
| 102 | * Use this initialization function rather than init_sched_clock() if | ||
| 103 | * you're using cyc_to_fixed_sched_clock, which will warn if your | ||
| 104 | * constants are incorrect. | ||
| 105 | */ | ||
| 106 | static inline void init_fixed_sched_clock(struct clock_data *cd, | ||
| 107 | void (*update)(void), unsigned int bits, unsigned long rate, | ||
| 108 | u32 mult, u32 shift) | ||
| 109 | { | ||
| 110 | init_sched_clock(cd, update, bits, rate); | ||
| 111 | if (cd->mult != mult || cd->shift != shift) { | ||
| 112 | pr_crit("sched_clock: wrong multiply/shift: %u>>%u vs calculated %u>>%u\n" | ||
| 113 | "sched_clock: fix multiply/shift to avoid scheduler hiccups\n", | ||
| 114 | mult, shift, cd->mult, cd->shift); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | extern void sched_clock_postinit(void); | 11 | extern void sched_clock_postinit(void); |
| 12 | extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); | ||
| 119 | 13 | ||
| 120 | #endif | 14 | #endif |
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c index 9a46370fe9da..5416c7c12528 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/arch/arm/kernel/sched_clock.c | |||
| @@ -14,61 +14,153 @@ | |||
| 14 | 14 | ||
| 15 | #include <asm/sched_clock.h> | 15 | #include <asm/sched_clock.h> |
| 16 | 16 | ||
| 17 | struct clock_data { | ||
| 18 | u64 epoch_ns; | ||
| 19 | u32 epoch_cyc; | ||
| 20 | u32 epoch_cyc_copy; | ||
| 21 | u32 mult; | ||
| 22 | u32 shift; | ||
| 23 | }; | ||
| 24 | |||
| 17 | static void sched_clock_poll(unsigned long wrap_ticks); | 25 | static void sched_clock_poll(unsigned long wrap_ticks); |
| 18 | static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0); | 26 | static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0); |
| 19 | static void (*sched_clock_update_fn)(void); | 27 | |
| 28 | static struct clock_data cd = { | ||
| 29 | .mult = NSEC_PER_SEC / HZ, | ||
| 30 | }; | ||
| 31 | |||
| 32 | static u32 __read_mostly sched_clock_mask = 0xffffffff; | ||
| 33 | |||
| 34 | static u32 notrace jiffy_sched_clock_read(void) | ||
| 35 | { | ||
| 36 | return (u32)(jiffies - INITIAL_JIFFIES); | ||
| 37 | } | ||
| 38 | |||
| 39 | static u32 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read; | ||
| 40 | |||
| 41 | static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift) | ||
| 42 | { | ||
| 43 | return (cyc * mult) >> shift; | ||
| 44 | } | ||
| 45 | |||
| 46 | static unsigned long long cyc_to_sched_clock(u32 cyc, u32 mask) | ||
| 47 | { | ||
| 48 | u64 epoch_ns; | ||
| 49 | u32 epoch_cyc; | ||
| 50 | |||
| 51 | /* | ||
| 52 | * Load the epoch_cyc and epoch_ns atomically. We do this by | ||
| 53 | * ensuring that we always write epoch_cyc, epoch_ns and | ||
| 54 | * epoch_cyc_copy in strict order, and read them in strict order. | ||
| 55 | * If epoch_cyc and epoch_cyc_copy are not equal, then we're in | ||
| 56 | * the middle of an update, and we should repeat the load. | ||
| 57 | */ | ||
| 58 | do { | ||
| 59 | epoch_cyc = cd.epoch_cyc; | ||
| 60 | smp_rmb(); | ||
| 61 | epoch_ns = cd.epoch_ns; | ||
| 62 | smp_rmb(); | ||
| 63 | } while (epoch_cyc != cd.epoch_cyc_copy); | ||
| 64 | |||
| 65 | return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, cd.mult, cd.shift); | ||
| 66 | } | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Atomically update the sched_clock epoch. | ||
| 70 | */ | ||
| 71 | static void notrace update_sched_clock(void) | ||
| 72 | { | ||
| 73 | unsigned long flags; | ||
| 74 | u32 cyc; | ||
| 75 | u64 ns; | ||
| 76 | |||
| 77 | cyc = read_sched_clock(); | ||
| 78 | ns = cd.epoch_ns + | ||
| 79 | cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask, | ||
| 80 | cd.mult, cd.shift); | ||
| 81 | /* | ||
| 82 | * Write epoch_cyc and epoch_ns in a way that the update is | ||
| 83 | * detectable in cyc_to_fixed_sched_clock(). | ||
| 84 | */ | ||
| 85 | raw_local_irq_save(flags); | ||
| 86 | cd.epoch_cyc = cyc; | ||
| 87 | smp_wmb(); | ||
| 88 | cd.epoch_ns = ns; | ||
| 89 | smp_wmb(); | ||
| 90 | cd.epoch_cyc_copy = cyc; | ||
| 91 | raw_local_irq_restore(flags); | ||
| 92 | } | ||
| 20 | 93 | ||
| 21 | static void sched_clock_poll(unsigned long wrap_ticks) | 94 | static void sched_clock_poll(unsigned long wrap_ticks) |
| 22 | { | 95 | { |
| 23 | mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks)); | 96 | mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks)); |
| 24 | sched_clock_update_fn(); | 97 | update_sched_clock(); |
| 25 | } | 98 | } |
| 26 | 99 | ||
| 27 | void __init init_sched_clock(struct clock_data *cd, void (*update)(void), | 100 | void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) |
| 28 | unsigned int clock_bits, unsigned long rate) | ||
| 29 | { | 101 | { |
| 30 | unsigned long r, w; | 102 | unsigned long r, w; |
| 31 | u64 res, wrap; | 103 | u64 res, wrap; |
| 32 | char r_unit; | 104 | char r_unit; |
| 33 | 105 | ||
| 34 | sched_clock_update_fn = update; | 106 | BUG_ON(bits > 32); |
| 107 | WARN_ON(!irqs_disabled()); | ||
| 108 | WARN_ON(read_sched_clock != jiffy_sched_clock_read); | ||
| 109 | read_sched_clock = read; | ||
| 110 | sched_clock_mask = (1 << bits) - 1; | ||
| 35 | 111 | ||
| 36 | /* calculate the mult/shift to convert counter ticks to ns. */ | 112 | /* calculate the mult/shift to convert counter ticks to ns. */ |
| 37 | clocks_calc_mult_shift(&cd->mult, &cd->shift, rate, NSEC_PER_SEC, 0); | 113 | clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0); |
| 38 | 114 | ||
| 39 | r = rate; | 115 | r = rate; |
| 40 | if (r >= 4000000) { | 116 | if (r >= 4000000) { |
| 41 | r /= 1000000; | 117 | r /= 1000000; |
| 42 | r_unit = 'M'; | 118 | r_unit = 'M'; |
| 43 | } else { | 119 | } else if (r >= 1000) { |
| 44 | r /= 1000; | 120 | r /= 1000; |
| 45 | r_unit = 'k'; | 121 | r_unit = 'k'; |
| 46 | } | 122 | } else |
| 123 | r_unit = ' '; | ||
| 47 | 124 | ||
| 48 | /* calculate how many ns until we wrap */ | 125 | /* calculate how many ns until we wrap */ |
| 49 | wrap = cyc_to_ns((1ULL << clock_bits) - 1, cd->mult, cd->shift); | 126 | wrap = cyc_to_ns((1ULL << bits) - 1, cd.mult, cd.shift); |
| 50 | do_div(wrap, NSEC_PER_MSEC); | 127 | do_div(wrap, NSEC_PER_MSEC); |
| 51 | w = wrap; | 128 | w = wrap; |
| 52 | 129 | ||
| 53 | /* calculate the ns resolution of this counter */ | 130 | /* calculate the ns resolution of this counter */ |
| 54 | res = cyc_to_ns(1ULL, cd->mult, cd->shift); | 131 | res = cyc_to_ns(1ULL, cd.mult, cd.shift); |
| 55 | pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n", | 132 | pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n", |
| 56 | clock_bits, r, r_unit, res, w); | 133 | bits, r, r_unit, res, w); |
| 57 | 134 | ||
| 58 | /* | 135 | /* |
| 59 | * Start the timer to keep sched_clock() properly updated and | 136 | * Start the timer to keep sched_clock() properly updated and |
| 60 | * sets the initial epoch. | 137 | * sets the initial epoch. |
| 61 | */ | 138 | */ |
| 62 | sched_clock_timer.data = msecs_to_jiffies(w - (w / 10)); | 139 | sched_clock_timer.data = msecs_to_jiffies(w - (w / 10)); |
| 63 | update(); | 140 | update_sched_clock(); |
| 64 | 141 | ||
| 65 | /* | 142 | /* |
| 66 | * Ensure that sched_clock() starts off at 0ns | 143 | * Ensure that sched_clock() starts off at 0ns |
| 67 | */ | 144 | */ |
| 68 | cd->epoch_ns = 0; | 145 | cd.epoch_ns = 0; |
| 146 | |||
| 147 | pr_debug("Registered %pF as sched_clock source\n", read); | ||
| 148 | } | ||
| 149 | |||
| 150 | unsigned long long notrace sched_clock(void) | ||
| 151 | { | ||
| 152 | u32 cyc = read_sched_clock(); | ||
| 153 | return cyc_to_sched_clock(cyc, sched_clock_mask); | ||
| 69 | } | 154 | } |
| 70 | 155 | ||
| 71 | void __init sched_clock_postinit(void) | 156 | void __init sched_clock_postinit(void) |
| 72 | { | 157 | { |
| 158 | /* | ||
| 159 | * If no sched_clock function has been provided at that point, | ||
| 160 | * make it the final one one. | ||
| 161 | */ | ||
| 162 | if (read_sched_clock == jiffy_sched_clock_read) | ||
| 163 | setup_sched_clock(jiffy_sched_clock_read, 32, HZ); | ||
| 164 | |||
| 73 | sched_clock_poll(sched_clock_timer.data); | 165 | sched_clock_poll(sched_clock_timer.data); |
| 74 | } | 166 | } |
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index b86a0055ab96..c1b12f945fc9 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
| 18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 19 | #include <linux/serial.h> | 19 | #include <linux/serial.h> |
| 20 | #include <linux/sched.h> | ||
| 21 | #include <linux/tty.h> | 20 | #include <linux/tty.h> |
| 22 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
| 23 | #include <linux/serial_core.h> | 22 | #include <linux/serial_core.h> |
| @@ -403,18 +402,9 @@ void __init ixp4xx_sys_init(void) | |||
| 403 | /* | 402 | /* |
| 404 | * sched_clock() | 403 | * sched_clock() |
| 405 | */ | 404 | */ |
| 406 | static DEFINE_CLOCK_DATA(cd); | 405 | static u32 notrace ixp4xx_read_sched_clock(void) |
| 407 | |||
| 408 | unsigned long long notrace sched_clock(void) | ||
| 409 | { | 406 | { |
| 410 | u32 cyc = *IXP4XX_OSTS; | 407 | return *IXP4XX_OSTS; |
| 411 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
| 412 | } | ||
| 413 | |||
| 414 | static void notrace ixp4xx_update_sched_clock(void) | ||
| 415 | { | ||
| 416 | u32 cyc = *IXP4XX_OSTS; | ||
| 417 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 418 | } | 408 | } |
| 419 | 409 | ||
| 420 | /* | 410 | /* |
| @@ -430,7 +420,7 @@ unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ; | |||
| 430 | EXPORT_SYMBOL(ixp4xx_timer_freq); | 420 | EXPORT_SYMBOL(ixp4xx_timer_freq); |
| 431 | static void __init ixp4xx_clocksource_init(void) | 421 | static void __init ixp4xx_clocksource_init(void) |
| 432 | { | 422 | { |
| 433 | init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq); | 423 | setup_sched_clock(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq); |
| 434 | 424 | ||
| 435 | clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32, | 425 | clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32, |
| 436 | ixp4xx_clocksource_read); | 426 | ixp4xx_clocksource_read); |
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 4e91ee6e27c8..71fc4ee4602c 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | 25 | ||
| 26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
| 27 | #include <linux/irq.h> | 27 | #include <linux/irq.h> |
| 28 | #include <linux/sched.h> | ||
| 29 | 28 | ||
| 30 | #include <asm/sched_clock.h> | 29 | #include <asm/sched_clock.h> |
| 31 | #include <mach/addr-map.h> | 30 | #include <mach/addr-map.h> |
| @@ -42,8 +41,6 @@ | |||
| 42 | #define MAX_DELTA (0xfffffffe) | 41 | #define MAX_DELTA (0xfffffffe) |
| 43 | #define MIN_DELTA (16) | 42 | #define MIN_DELTA (16) |
| 44 | 43 | ||
| 45 | static DEFINE_CLOCK_DATA(cd); | ||
| 46 | |||
| 47 | /* | 44 | /* |
| 48 | * FIXME: the timer needs some delay to stablize the counter capture | 45 | * FIXME: the timer needs some delay to stablize the counter capture |
| 49 | */ | 46 | */ |
| @@ -59,16 +56,9 @@ static inline uint32_t timer_read(void) | |||
| 59 | return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(1)); | 56 | return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(1)); |
| 60 | } | 57 | } |
| 61 | 58 | ||
| 62 | unsigned long long notrace sched_clock(void) | 59 | static u32 notrace mmp_read_sched_clock(void) |
| 63 | { | 60 | { |
| 64 | u32 cyc = timer_read(); | 61 | return timer_read(); |
| 65 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
| 66 | } | ||
| 67 | |||
| 68 | static void notrace mmp_update_sched_clock(void) | ||
| 69 | { | ||
| 70 | u32 cyc = timer_read(); | ||
| 71 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 72 | } | 62 | } |
| 73 | 63 | ||
| 74 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | 64 | static irqreturn_t timer_interrupt(int irq, void *dev_id) |
| @@ -201,7 +191,7 @@ void __init timer_init(int irq) | |||
| 201 | { | 191 | { |
| 202 | timer_config(); | 192 | timer_config(); |
| 203 | 193 | ||
| 204 | init_sched_clock(&cd, mmp_update_sched_clock, 32, CLOCK_TICK_RATE); | 194 | setup_sched_clock(mmp_read_sched_clock, 32, CLOCK_TICK_RATE); |
| 205 | 195 | ||
| 206 | ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift); | 196 | ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift); |
| 207 | ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt); | 197 | ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt); |
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index 485a21d31004..b8faffa44f9e 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
| 38 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
| 39 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
| 40 | #include <linux/sched.h> | ||
| 41 | #include <linux/spinlock.h> | 40 | #include <linux/spinlock.h> |
| 42 | #include <linux/clk.h> | 41 | #include <linux/clk.h> |
| 43 | #include <linux/err.h> | 42 | #include <linux/err.h> |
| @@ -190,30 +189,9 @@ static __init void omap_init_mpu_timer(unsigned long rate) | |||
| 190 | * --------------------------------------------------------------------------- | 189 | * --------------------------------------------------------------------------- |
| 191 | */ | 190 | */ |
| 192 | 191 | ||
| 193 | static DEFINE_CLOCK_DATA(cd); | 192 | static u32 notrace omap_mpu_read_sched_clock(void) |
| 194 | |||
| 195 | static inline unsigned long long notrace _omap_mpu_sched_clock(void) | ||
| 196 | { | ||
| 197 | u32 cyc = ~omap_mpu_timer_read(1); | ||
| 198 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
| 199 | } | ||
| 200 | |||
| 201 | #ifndef CONFIG_OMAP_32K_TIMER | ||
| 202 | unsigned long long notrace sched_clock(void) | ||
| 203 | { | ||
| 204 | return _omap_mpu_sched_clock(); | ||
| 205 | } | ||
| 206 | #else | ||
| 207 | static unsigned long long notrace omap_mpu_sched_clock(void) | ||
| 208 | { | ||
| 209 | return _omap_mpu_sched_clock(); | ||
| 210 | } | ||
| 211 | #endif | ||
| 212 | |||
| 213 | static void notrace mpu_update_sched_clock(void) | ||
| 214 | { | 193 | { |
| 215 | u32 cyc = ~omap_mpu_timer_read(1); | 194 | return ~omap_mpu_timer_read(1); |
| 216 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 217 | } | 195 | } |
| 218 | 196 | ||
| 219 | static void __init omap_init_clocksource(unsigned long rate) | 197 | static void __init omap_init_clocksource(unsigned long rate) |
| @@ -223,7 +201,7 @@ static void __init omap_init_clocksource(unsigned long rate) | |||
| 223 | "%s: can't register clocksource!\n"; | 201 | "%s: can't register clocksource!\n"; |
| 224 | 202 | ||
| 225 | omap_mpu_timer_start(1, ~0, 1); | 203 | omap_mpu_timer_start(1, ~0, 1); |
| 226 | init_sched_clock(&cd, mpu_update_sched_clock, 32, rate); | 204 | setup_sched_clock(omap_mpu_read_sched_clock, 32, rate); |
| 227 | 205 | ||
| 228 | if (clocksource_mmio_init(&timer->read_tim, "mpu_timer2", rate, | 206 | if (clocksource_mmio_init(&timer->read_tim, "mpu_timer2", rate, |
| 229 | 300, 32, clocksource_mmio_readl_down)) | 207 | 300, 32, clocksource_mmio_readl_down)) |
| @@ -254,30 +232,6 @@ static inline void omap_mpu_timer_init(void) | |||
| 254 | } | 232 | } |
| 255 | #endif /* CONFIG_OMAP_MPU_TIMER */ | 233 | #endif /* CONFIG_OMAP_MPU_TIMER */ |
| 256 | 234 | ||
| 257 | #if defined(CONFIG_OMAP_MPU_TIMER) && defined(CONFIG_OMAP_32K_TIMER) | ||
| 258 | static unsigned long long (*preferred_sched_clock)(void); | ||
| 259 | |||
| 260 | unsigned long long notrace sched_clock(void) | ||
| 261 | { | ||
| 262 | if (!preferred_sched_clock) | ||
| 263 | return 0; | ||
| 264 | |||
| 265 | return preferred_sched_clock(); | ||
| 266 | } | ||
| 267 | |||
| 268 | static inline void preferred_sched_clock_init(bool use_32k_sched_clock) | ||
| 269 | { | ||
| 270 | if (use_32k_sched_clock) | ||
| 271 | preferred_sched_clock = omap_32k_sched_clock; | ||
| 272 | else | ||
| 273 | preferred_sched_clock = omap_mpu_sched_clock; | ||
| 274 | } | ||
| 275 | #else | ||
| 276 | static inline void preferred_sched_clock_init(bool use_32k_sched_clcok) | ||
| 277 | { | ||
| 278 | } | ||
| 279 | #endif | ||
| 280 | |||
| 281 | static inline int omap_32k_timer_usable(void) | 235 | static inline int omap_32k_timer_usable(void) |
| 282 | { | 236 | { |
| 283 | int res = false; | 237 | int res = false; |
| @@ -299,12 +253,8 @@ static inline int omap_32k_timer_usable(void) | |||
| 299 | */ | 253 | */ |
| 300 | static void __init omap1_timer_init(void) | 254 | static void __init omap1_timer_init(void) |
| 301 | { | 255 | { |
| 302 | if (omap_32k_timer_usable()) { | 256 | if (!omap_32k_timer_usable()) |
| 303 | preferred_sched_clock_init(1); | ||
| 304 | } else { | ||
| 305 | omap_mpu_timer_init(); | 257 | omap_mpu_timer_init(); |
| 306 | preferred_sched_clock_init(0); | ||
| 307 | } | ||
| 308 | } | 258 | } |
| 309 | 259 | ||
| 310 | struct sys_timer omap1_timer = { | 260 | struct sys_timer omap1_timer = { |
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 9edcd520510f..6eeff0e0ae01 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c | |||
| @@ -254,7 +254,6 @@ static struct omap_dm_timer clksrc; | |||
| 254 | /* | 254 | /* |
| 255 | * clocksource | 255 | * clocksource |
| 256 | */ | 256 | */ |
| 257 | static DEFINE_CLOCK_DATA(cd); | ||
| 258 | static cycle_t clocksource_read_cycles(struct clocksource *cs) | 257 | static cycle_t clocksource_read_cycles(struct clocksource *cs) |
| 259 | { | 258 | { |
| 260 | return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1); | 259 | return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1); |
| @@ -268,23 +267,12 @@ static struct clocksource clocksource_gpt = { | |||
| 268 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 267 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
| 269 | }; | 268 | }; |
| 270 | 269 | ||
| 271 | static void notrace dmtimer_update_sched_clock(void) | 270 | static u32 notrace dmtimer_read_sched_clock(void) |
| 272 | { | 271 | { |
| 273 | u32 cyc; | ||
| 274 | |||
| 275 | cyc = __omap_dm_timer_read_counter(&clksrc, 1); | ||
| 276 | |||
| 277 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 278 | } | ||
| 279 | |||
| 280 | unsigned long long notrace sched_clock(void) | ||
| 281 | { | ||
| 282 | u32 cyc = 0; | ||
| 283 | |||
| 284 | if (clksrc.reserved) | 272 | if (clksrc.reserved) |
| 285 | cyc = __omap_dm_timer_read_counter(&clksrc, 1); | 273 | return __omap_dm_timer_read_counter(clksrc.io_base, 1); |
| 286 | 274 | ||
| 287 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | 275 | return 0; |
| 288 | } | 276 | } |
| 289 | 277 | ||
| 290 | /* Setup free-running counter for clocksource */ | 278 | /* Setup free-running counter for clocksource */ |
| @@ -301,7 +289,7 @@ static void __init omap2_gp_clocksource_init(int gptimer_id, | |||
| 301 | 289 | ||
| 302 | __omap_dm_timer_load_start(&clksrc, | 290 | __omap_dm_timer_load_start(&clksrc, |
| 303 | OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1); | 291 | OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1); |
| 304 | init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate); | 292 | setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate); |
| 305 | 293 | ||
| 306 | if (clocksource_register_hz(&clocksource_gpt, clksrc.rate)) | 294 | if (clocksource_register_hz(&clocksource_gpt, clksrc.rate)) |
| 307 | pr_err("Could not register clocksource %s\n", | 295 | pr_err("Could not register clocksource %s\n", |
diff --git a/arch/arm/mach-picoxcell/time.c b/arch/arm/mach-picoxcell/time.c index 90a554ff4499..6c89cf8ab22e 100644 --- a/arch/arm/mach-picoxcell/time.c +++ b/arch/arm/mach-picoxcell/time.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | #include <linux/of.h> | 11 | #include <linux/of.h> |
| 12 | #include <linux/of_address.h> | 12 | #include <linux/of_address.h> |
| 13 | #include <linux/of_irq.h> | 13 | #include <linux/of_irq.h> |
| 14 | #include <linux/sched.h> | ||
| 15 | 14 | ||
| 16 | #include <asm/mach/time.h> | 15 | #include <asm/mach/time.h> |
| 17 | #include <asm/sched_clock.h> | 16 | #include <asm/sched_clock.h> |
| @@ -66,21 +65,11 @@ static void picoxcell_add_clocksource(struct device_node *source_timer) | |||
| 66 | dw_apb_clocksource_register(cs); | 65 | dw_apb_clocksource_register(cs); |
| 67 | } | 66 | } |
| 68 | 67 | ||
| 69 | static DEFINE_CLOCK_DATA(cd); | ||
| 70 | static void __iomem *sched_io_base; | 68 | static void __iomem *sched_io_base; |
| 71 | 69 | ||
| 72 | unsigned long long notrace sched_clock(void) | 70 | unsigned u32 notrace picoxcell_read_sched_clock(void) |
| 73 | { | 71 | { |
| 74 | cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0; | 72 | return __raw_readl(sched_io_base); |
| 75 | |||
| 76 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
| 77 | } | ||
| 78 | |||
| 79 | static void notrace picoxcell_update_sched_clock(void) | ||
| 80 | { | ||
| 81 | cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0; | ||
| 82 | |||
| 83 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 84 | } | 73 | } |
| 85 | 74 | ||
| 86 | static const struct of_device_id picoxcell_rtc_ids[] __initconst = { | 75 | static const struct of_device_id picoxcell_rtc_ids[] __initconst = { |
| @@ -100,7 +89,7 @@ static void picoxcell_init_sched_clock(void) | |||
| 100 | timer_get_base_and_rate(sched_timer, &sched_io_base, &rate); | 89 | timer_get_base_and_rate(sched_timer, &sched_io_base, &rate); |
| 101 | of_node_put(sched_timer); | 90 | of_node_put(sched_timer); |
| 102 | 91 | ||
| 103 | init_sched_clock(&cd, picoxcell_update_sched_clock, 32, rate); | 92 | setup_sched_clock(picoxcell_read_sched_clock, 32, rate); |
| 104 | } | 93 | } |
| 105 | 94 | ||
| 106 | static const struct of_device_id picoxcell_timer_ids[] __initconst = { | 95 | static const struct of_device_id picoxcell_timer_ids[] __initconst = { |
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index de684701449c..b503049d6d26 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| 18 | #include <linux/clockchips.h> | 18 | #include <linux/clockchips.h> |
| 19 | #include <linux/sched.h> | ||
| 20 | 19 | ||
| 21 | #include <asm/div64.h> | 20 | #include <asm/div64.h> |
| 22 | #include <asm/mach/irq.h> | 21 | #include <asm/mach/irq.h> |
| @@ -32,18 +31,10 @@ | |||
| 32 | * long as there is always less than 582 seconds between successive | 31 | * long as there is always less than 582 seconds between successive |
| 33 | * calls to sched_clock() which should always be the case in practice. | 32 | * calls to sched_clock() which should always be the case in practice. |
| 34 | */ | 33 | */ |
| 35 | static DEFINE_CLOCK_DATA(cd); | ||
| 36 | 34 | ||
| 37 | unsigned long long notrace sched_clock(void) | 35 | static u32 notrace pxa_read_sched_clock(void) |
| 38 | { | 36 | { |
| 39 | u32 cyc = OSCR; | 37 | return OSCR; |
| 40 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
| 41 | } | ||
| 42 | |||
| 43 | static void notrace pxa_update_sched_clock(void) | ||
| 44 | { | ||
| 45 | u32 cyc = OSCR; | ||
| 46 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 47 | } | 38 | } |
| 48 | 39 | ||
| 49 | 40 | ||
| @@ -119,7 +110,7 @@ static void __init pxa_timer_init(void) | |||
| 119 | OIER = 0; | 110 | OIER = 0; |
| 120 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; | 111 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; |
| 121 | 112 | ||
| 122 | init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate); | 113 | setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate); |
| 123 | 114 | ||
| 124 | clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4); | 115 | clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4); |
| 125 | ckevt_pxa_osmr0.max_delta_ns = | 116 | ckevt_pxa_osmr0.max_delta_ns = |
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index fa6602491d54..1ee6d4ca8dd7 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| 13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
| 14 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
| 15 | #include <linux/sched.h> /* just for sched_clock() - funny that */ | ||
| 16 | #include <linux/timex.h> | 15 | #include <linux/timex.h> |
| 17 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
| 18 | 17 | ||
| @@ -20,29 +19,9 @@ | |||
| 20 | #include <asm/sched_clock.h> | 19 | #include <asm/sched_clock.h> |
| 21 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
| 22 | 21 | ||
| 23 | /* | 22 | static u32 notrace sa100_read_sched_clock(void) |
| 24 | * This is the SA11x0 sched_clock implementation. | ||
| 25 | */ | ||
| 26 | static DEFINE_CLOCK_DATA(cd); | ||
| 27 | |||
| 28 | /* | ||
| 29 | * Constants generated by clocks_calc_mult_shift(m, s, 3.6864MHz, | ||
| 30 | * NSEC_PER_SEC, 60). | ||
| 31 | * This gives a resolution of about 271ns and a wrap period of about 19min. | ||
| 32 | */ | ||
| 33 | #define SC_MULT 2275555556u | ||
| 34 | #define SC_SHIFT 23 | ||
| 35 | |||
| 36 | unsigned long long notrace sched_clock(void) | ||
| 37 | { | ||
| 38 | u32 cyc = OSCR; | ||
| 39 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); | ||
| 40 | } | ||
| 41 | |||
| 42 | static void notrace sa1100_update_sched_clock(void) | ||
| 43 | { | 23 | { |
| 44 | u32 cyc = OSCR; | 24 | return OSCR; |
| 45 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 46 | } | 25 | } |
| 47 | 26 | ||
| 48 | #define MIN_OSCR_DELTA 2 | 27 | #define MIN_OSCR_DELTA 2 |
| @@ -109,8 +88,7 @@ static void __init sa1100_timer_init(void) | |||
| 109 | OIER = 0; | 88 | OIER = 0; |
| 110 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; | 89 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; |
| 111 | 90 | ||
| 112 | init_fixed_sched_clock(&cd, sa1100_update_sched_clock, 32, | 91 | setup_sched_clock(sa1100_read_sched_clock, 32, 3686400); |
| 113 | 3686400, SC_MULT, SC_SHIFT); | ||
| 114 | 92 | ||
| 115 | clockevents_calc_mult_shift(&ckevt_sa1100_osmr0, 3686400, 4); | 93 | clockevents_calc_mult_shift(&ckevt_sa1100_osmr0, 3686400, 4); |
| 116 | ckevt_sa1100_osmr0.max_delta_ns = | 94 | ckevt_sa1100_osmr0.max_delta_ns = |
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index e2272d263a83..732c724008b1 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | 19 | ||
| 20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
| 22 | #include <linux/sched.h> | ||
| 23 | #include <linux/time.h> | 22 | #include <linux/time.h> |
| 24 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
| 25 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
| @@ -106,25 +105,9 @@ static struct clock_event_device tegra_clockevent = { | |||
| 106 | .set_mode = tegra_timer_set_mode, | 105 | .set_mode = tegra_timer_set_mode, |
| 107 | }; | 106 | }; |
| 108 | 107 | ||
| 109 | static DEFINE_CLOCK_DATA(cd); | 108 | static u32 notrace tegra_read_sched_clock(void) |
| 110 | |||
| 111 | /* | ||
| 112 | * Constants generated by clocks_calc_mult_shift(m, s, 1MHz, NSEC_PER_SEC, 60). | ||
| 113 | * This gives a resolution of about 1us and a wrap period of about 1h11min. | ||
| 114 | */ | ||
| 115 | #define SC_MULT 4194304000u | ||
| 116 | #define SC_SHIFT 22 | ||
| 117 | |||
| 118 | unsigned long long notrace sched_clock(void) | ||
| 119 | { | ||
| 120 | u32 cyc = timer_readl(TIMERUS_CNTR_1US); | ||
| 121 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); | ||
| 122 | } | ||
| 123 | |||
| 124 | static void notrace tegra_update_sched_clock(void) | ||
| 125 | { | 109 | { |
| 126 | u32 cyc = timer_readl(TIMERUS_CNTR_1US); | 110 | return timer_readl(TIMERUS_CNTR_1US); |
| 127 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 128 | } | 111 | } |
| 129 | 112 | ||
| 130 | /* | 113 | /* |
| @@ -218,8 +201,7 @@ static void __init tegra_init_timer(void) | |||
| 218 | WARN(1, "Unknown clock rate"); | 201 | WARN(1, "Unknown clock rate"); |
| 219 | } | 202 | } |
| 220 | 203 | ||
| 221 | init_fixed_sched_clock(&cd, tegra_update_sched_clock, 32, | 204 | setup_sched_clock(tegra_read_sched_clock, 32, 1000000); |
| 222 | 1000000, SC_MULT, SC_SHIFT); | ||
| 223 | 205 | ||
| 224 | if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, | 206 | if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, |
| 225 | "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) { | 207 | "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) { |
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index 5f51bdeef0ef..bc1c7897e82d 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | * Author: Linus Walleij <linus.walleij@stericsson.com> | 9 | * Author: Linus Walleij <linus.walleij@stericsson.com> |
| 10 | */ | 10 | */ |
| 11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
| 12 | #include <linux/sched.h> | ||
| 13 | #include <linux/time.h> | 12 | #include <linux/time.h> |
| 14 | #include <linux/timex.h> | 13 | #include <linux/timex.h> |
| 15 | #include <linux/clockchips.h> | 14 | #include <linux/clockchips.h> |
| @@ -337,18 +336,10 @@ static struct irqaction u300_timer_irq = { | |||
| 337 | * this wraps around for now, since it is just a relative time | 336 | * this wraps around for now, since it is just a relative time |
| 338 | * stamp. (Inspired by OMAP implementation.) | 337 | * stamp. (Inspired by OMAP implementation.) |
| 339 | */ | 338 | */ |
| 340 | static DEFINE_CLOCK_DATA(cd); | ||
| 341 | 339 | ||
| 342 | unsigned long long notrace sched_clock(void) | 340 | static u32 notrace u300_read_sched_clock(void) |
| 343 | { | 341 | { |
| 344 | u32 cyc = readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); | 342 | return readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); |
| 345 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
| 346 | } | ||
| 347 | |||
| 348 | static void notrace u300_update_sched_clock(void) | ||
| 349 | { | ||
| 350 | u32 cyc = readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); | ||
| 351 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 352 | } | 343 | } |
| 353 | 344 | ||
| 354 | 345 | ||
| @@ -366,7 +357,7 @@ static void __init u300_timer_init(void) | |||
| 366 | clk_enable(clk); | 357 | clk_enable(clk); |
| 367 | rate = clk_get_rate(clk); | 358 | rate = clk_get_rate(clk); |
| 368 | 359 | ||
| 369 | init_sched_clock(&cd, u300_update_sched_clock, 32, rate); | 360 | setup_sched_clock(u300_read_sched_clock, 32, rate); |
| 370 | 361 | ||
| 371 | /* | 362 | /* |
| 372 | * Disable the "OS" and "DD" timers - these are designed for Symbian! | 363 | * Disable the "OS" and "DD" timers - these are designed for Symbian! |
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index 568dd0223d17..cbfbbe461788 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #include <linux/time.h> | 18 | #include <linux/time.h> |
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/timex.h> | 20 | #include <linux/timex.h> |
| 21 | #include <linux/sched.h> | ||
| 22 | #include <linux/io.h> | 21 | #include <linux/io.h> |
| 23 | #include <linux/clocksource.h> | 22 | #include <linux/clocksource.h> |
| 24 | #include <linux/clockchips.h> | 23 | #include <linux/clockchips.h> |
| @@ -52,21 +51,12 @@ static struct clocksource iop_clocksource = { | |||
| 52 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 51 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
| 53 | }; | 52 | }; |
| 54 | 53 | ||
| 55 | static DEFINE_CLOCK_DATA(cd); | ||
| 56 | |||
| 57 | /* | 54 | /* |
| 58 | * IOP sched_clock() implementation via its clocksource. | 55 | * IOP sched_clock() implementation via its clocksource. |
| 59 | */ | 56 | */ |
| 60 | unsigned long long notrace sched_clock(void) | 57 | static u32 notrace iop_read_sched_clock(void) |
| 61 | { | 58 | { |
| 62 | u32 cyc = 0xffffffffu - read_tcr1(); | 59 | return 0xffffffffu - read_tcr1(); |
| 63 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
| 64 | } | ||
| 65 | |||
| 66 | static void notrace iop_update_sched_clock(void) | ||
| 67 | { | ||
| 68 | u32 cyc = 0xffffffffu - read_tcr1(); | ||
| 69 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 70 | } | 60 | } |
| 71 | 61 | ||
| 72 | /* | 62 | /* |
| @@ -152,7 +142,7 @@ void __init iop_init_time(unsigned long tick_rate) | |||
| 152 | { | 142 | { |
| 153 | u32 timer_ctl; | 143 | u32 timer_ctl; |
| 154 | 144 | ||
| 155 | init_sched_clock(&cd, iop_update_sched_clock, 32, tick_rate); | 145 | setup_sched_clock(iop_read_sched_clock, 32, tick_rate); |
| 156 | 146 | ||
| 157 | ticks_per_jiffy = DIV_ROUND_CLOSEST(tick_rate, HZ); | 147 | ticks_per_jiffy = DIV_ROUND_CLOSEST(tick_rate, HZ); |
| 158 | iop_tick_rate = tick_rate; | 148 | iop_tick_rate = tick_rate; |
diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index 4b0fe285e83c..1c96cdb4c35e 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c | |||
| @@ -108,18 +108,9 @@ static void gpt_irq_acknowledge(void) | |||
| 108 | 108 | ||
| 109 | static void __iomem *sched_clock_reg; | 109 | static void __iomem *sched_clock_reg; |
| 110 | 110 | ||
| 111 | static DEFINE_CLOCK_DATA(cd); | 111 | static u32 notrace mxc_read_sched_clock(void) |
| 112 | unsigned long long notrace sched_clock(void) | ||
| 113 | { | 112 | { |
| 114 | cycle_t cyc = sched_clock_reg ? __raw_readl(sched_clock_reg) : 0; | 113 | return sched_clock_reg ? __raw_readl(sched_clock_reg) : 0; |
| 115 | |||
| 116 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void notrace mxc_update_sched_clock(void) | ||
| 120 | { | ||
| 121 | cycle_t cyc = sched_clock_reg ? __raw_readl(sched_clock_reg) : 0; | ||
| 122 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 123 | } | 114 | } |
| 124 | 115 | ||
| 125 | static int __init mxc_clocksource_init(struct clk *timer_clk) | 116 | static int __init mxc_clocksource_init(struct clk *timer_clk) |
| @@ -129,7 +120,7 @@ static int __init mxc_clocksource_init(struct clk *timer_clk) | |||
| 129 | 120 | ||
| 130 | sched_clock_reg = reg; | 121 | sched_clock_reg = reg; |
| 131 | 122 | ||
| 132 | init_sched_clock(&cd, mxc_update_sched_clock, 32, c); | 123 | setup_sched_clock(mxc_read_sched_clock, 32, c); |
| 133 | return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32, | 124 | return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32, |
| 134 | clocksource_mmio_readl_up); | 125 | clocksource_mmio_readl_up); |
| 135 | } | 126 | } |
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index 30b6433d910d..ad1b45b605a4 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
| 18 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
| 19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
| 20 | #include <linux/sched.h> | ||
| 21 | #include <asm/mach/time.h> | 20 | #include <asm/mach/time.h> |
| 22 | #include <asm/sched_clock.h> | 21 | #include <asm/sched_clock.h> |
| 23 | 22 | ||
| @@ -79,23 +78,12 @@ void __iomem *mtu_base; /* Assigned by machine code */ | |||
| 79 | * local implementation which uses the clocksource to get some | 78 | * local implementation which uses the clocksource to get some |
| 80 | * better resolution when scheduling the kernel. | 79 | * better resolution when scheduling the kernel. |
| 81 | */ | 80 | */ |
| 82 | static DEFINE_CLOCK_DATA(cd); | 81 | static u32 notrace nomadik_read_sched_clock(void) |
| 83 | |||
| 84 | unsigned long long notrace sched_clock(void) | ||
| 85 | { | 82 | { |
| 86 | u32 cyc; | ||
| 87 | |||
| 88 | if (unlikely(!mtu_base)) | 83 | if (unlikely(!mtu_base)) |
| 89 | return 0; | 84 | return 0; |
| 90 | 85 | ||
| 91 | cyc = -readl(mtu_base + MTU_VAL(0)); | 86 | return -readl(mtu_base + MTU_VAL(0)); |
| 92 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
| 93 | } | ||
| 94 | |||
| 95 | static void notrace nomadik_update_sched_clock(void) | ||
| 96 | { | ||
| 97 | u32 cyc = -readl(mtu_base + MTU_VAL(0)); | ||
| 98 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 99 | } | 87 | } |
| 100 | #endif | 88 | #endif |
| 101 | 89 | ||
| @@ -231,9 +219,11 @@ void __init nmdk_timer_init(void) | |||
| 231 | rate, 200, 32, clocksource_mmio_readl_down)) | 219 | rate, 200, 32, clocksource_mmio_readl_down)) |
| 232 | pr_err("timer: failed to initialize clock source %s\n", | 220 | pr_err("timer: failed to initialize clock source %s\n", |
| 233 | "mtu_0"); | 221 | "mtu_0"); |
| 222 | |||
| 234 | #ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK | 223 | #ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK |
| 235 | init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate); | 224 | setup_sched_clock(nomadik_read_sched_clock, 32, rate); |
| 236 | #endif | 225 | #endif |
| 226 | |||
| 237 | /* Timer 1 is used for events */ | 227 | /* Timer 1 is used for events */ |
| 238 | 228 | ||
| 239 | clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); | 229 | clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); |
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index a6cbb712da51..5f0f2292b7fb 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
| 18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
| 19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
| 20 | #include <linux/sched.h> | ||
| 21 | #include <linux/clocksource.h> | 20 | #include <linux/clocksource.h> |
| 22 | 21 | ||
| 23 | #include <asm/sched_clock.h> | 22 | #include <asm/sched_clock.h> |
| @@ -37,41 +36,9 @@ static void __iomem *timer_32k_base; | |||
| 37 | 36 | ||
| 38 | #define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410 | 37 | #define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410 |
| 39 | 38 | ||
| 40 | /* | 39 | static u32 notrace omap_32k_read_sched_clock(void) |
| 41 | * Returns current time from boot in nsecs. It's OK for this to wrap | ||
| 42 | * around for now, as it's just a relative time stamp. | ||
| 43 | */ | ||
| 44 | static DEFINE_CLOCK_DATA(cd); | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Constants generated by clocks_calc_mult_shift(m, s, 32768, NSEC_PER_SEC, 60). | ||
| 48 | * This gives a resolution of about 30us and a wrap period of about 36hrs. | ||
| 49 | */ | ||
| 50 | #define SC_MULT 4000000000u | ||
| 51 | #define SC_SHIFT 17 | ||
| 52 | |||
| 53 | static inline unsigned long long notrace _omap_32k_sched_clock(void) | ||
| 54 | { | ||
| 55 | u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0; | ||
| 56 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); | ||
| 57 | } | ||
| 58 | |||
| 59 | #if defined(CONFIG_OMAP_32K_TIMER) && !defined(CONFIG_OMAP_MPU_TIMER) | ||
| 60 | unsigned long long notrace sched_clock(void) | ||
| 61 | { | ||
| 62 | return _omap_32k_sched_clock(); | ||
| 63 | } | ||
| 64 | #else | ||
| 65 | unsigned long long notrace omap_32k_sched_clock(void) | ||
| 66 | { | ||
| 67 | return _omap_32k_sched_clock(); | ||
| 68 | } | ||
| 69 | #endif | ||
| 70 | |||
| 71 | static void notrace omap_update_sched_clock(void) | ||
| 72 | { | 40 | { |
| 73 | u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0; | 41 | return timer_32k_base ? __raw_readl(timer_32k_base) : 0; |
| 74 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 75 | } | 42 | } |
| 76 | 43 | ||
| 77 | /** | 44 | /** |
| @@ -147,8 +114,7 @@ int __init omap_init_clocksource_32k(void) | |||
| 147 | clocksource_mmio_readl_up)) | 114 | clocksource_mmio_readl_up)) |
| 148 | printk(err, "32k_counter"); | 115 | printk(err, "32k_counter"); |
| 149 | 116 | ||
| 150 | init_fixed_sched_clock(&cd, omap_update_sched_clock, 32, | 117 | setup_sched_clock(omap_32k_read_sched_clock, 32, 32768); |
| 151 | 32768, SC_MULT, SC_SHIFT); | ||
| 152 | } | 118 | } |
| 153 | return 0; | 119 | return 0; |
| 154 | } | 120 | } |
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index 257f9770b2da..b4d7ec3fbfbe 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | #include <plat/omap_hwmod.h> | 31 | #include <plat/omap_hwmod.h> |
| 32 | 32 | ||
| 33 | extern int __init omap_init_clocksource_32k(void); | 33 | extern int __init omap_init_clocksource_32k(void); |
| 34 | extern unsigned long long notrace omap_32k_sched_clock(void); | ||
| 35 | 34 | ||
| 36 | extern void omap_reserve(void); | 35 | extern void omap_reserve(void); |
| 37 | extern int omap_dss_reset(struct omap_hwmod *); | 36 | extern int omap_dss_reset(struct omap_hwmod *); |
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 69a61367e4b8..1ed8d1397fcf 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/sched.h> | ||
| 16 | #include <linux/timer.h> | 15 | #include <linux/timer.h> |
| 17 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
| 18 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| @@ -60,24 +59,10 @@ static u32 ticks_per_jiffy; | |||
| 60 | * Orion's sched_clock implementation. It has a resolution of | 59 | * Orion's sched_clock implementation. It has a resolution of |
| 61 | * at least 7.5ns (133MHz TCLK). | 60 | * at least 7.5ns (133MHz TCLK). |
| 62 | */ | 61 | */ |
| 63 | static DEFINE_CLOCK_DATA(cd); | ||
| 64 | 62 | ||
| 65 | unsigned long long notrace sched_clock(void) | 63 | static u32 notrace orion_read_sched_clock(void) |
| 66 | { | 64 | { |
| 67 | u32 cyc = ~readl(timer_base + TIMER0_VAL_OFF); | 65 | return ~readl(timer_base + TIMER0_VAL_OFF); |
| 68 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
| 69 | } | ||
| 70 | |||
| 71 | |||
| 72 | static void notrace orion_update_sched_clock(void) | ||
| 73 | { | ||
| 74 | u32 cyc = ~readl(timer_base + TIMER0_VAL_OFF); | ||
| 75 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 76 | } | ||
| 77 | |||
| 78 | static void __init setup_sched_clock(unsigned long tclk) | ||
| 79 | { | ||
| 80 | init_sched_clock(&cd, orion_update_sched_clock, 32, tclk); | ||
| 81 | } | 66 | } |
| 82 | 67 | ||
| 83 | /* | 68 | /* |
| @@ -217,7 +202,7 @@ orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask, | |||
| 217 | /* | 202 | /* |
| 218 | * Set scale and timer for sched_clock. | 203 | * Set scale and timer for sched_clock. |
| 219 | */ | 204 | */ |
| 220 | setup_sched_clock(tclk); | 205 | setup_sched_clock(orion_read_sched_clock, 32, tclk); |
| 221 | 206 | ||
| 222 | /* | 207 | /* |
| 223 | * Setup free-running clocksource timer (interrupts | 208 | * Setup free-running clocksource timer (interrupts |
diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c index c833e7b57599..17c0a2c58dfd 100644 --- a/arch/arm/plat-s5p/s5p-time.c +++ b/arch/arm/plat-s5p/s5p-time.c | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/sched.h> | ||
| 14 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
| 15 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
| 16 | #include <linux/err.h> | 15 | #include <linux/err.h> |
| @@ -321,26 +320,14 @@ static void __iomem *s5p_timer_reg(void) | |||
| 321 | * this wraps around for now, since it is just a relative time | 320 | * this wraps around for now, since it is just a relative time |
| 322 | * stamp. (Inspired by U300 implementation.) | 321 | * stamp. (Inspired by U300 implementation.) |
| 323 | */ | 322 | */ |
| 324 | static DEFINE_CLOCK_DATA(cd); | 323 | static u32 notrace s5p_read_sched_clock(void) |
| 325 | |||
| 326 | unsigned long long notrace sched_clock(void) | ||
| 327 | { | 324 | { |
| 328 | void __iomem *reg = s5p_timer_reg(); | 325 | void __iomem *reg = s5p_timer_reg(); |
| 329 | 326 | ||
| 330 | if (!reg) | 327 | if (!reg) |
| 331 | return 0; | 328 | return 0; |
| 332 | 329 | ||
| 333 | return cyc_to_sched_clock(&cd, ~__raw_readl(reg), (u32)~0); | 330 | return ~__raw_readl(reg); |
| 334 | } | ||
| 335 | |||
| 336 | static void notrace s5p_update_sched_clock(void) | ||
| 337 | { | ||
| 338 | void __iomem *reg = s5p_timer_reg(); | ||
| 339 | |||
| 340 | if (!reg) | ||
| 341 | return; | ||
| 342 | |||
| 343 | update_sched_clock(&cd, ~__raw_readl(reg), (u32)~0); | ||
| 344 | } | 331 | } |
| 345 | 332 | ||
| 346 | static void __init s5p_clocksource_init(void) | 333 | static void __init s5p_clocksource_init(void) |
| @@ -358,7 +345,7 @@ static void __init s5p_clocksource_init(void) | |||
| 358 | s5p_time_setup(timer_source.source_id, TCNT_MAX); | 345 | s5p_time_setup(timer_source.source_id, TCNT_MAX); |
| 359 | s5p_time_start(timer_source.source_id, PERIODIC); | 346 | s5p_time_start(timer_source.source_id, PERIODIC); |
| 360 | 347 | ||
| 361 | init_sched_clock(&cd, s5p_update_sched_clock, 32, clock_rate); | 348 | setup_sched_clock(s5p_read_sched_clock, 32, clock_rate); |
| 362 | 349 | ||
| 363 | if (clocksource_mmio_init(s5p_timer_reg(), "s5p_clocksource_timer", | 350 | if (clocksource_mmio_init(s5p_timer_reg(), "s5p_clocksource_timer", |
| 364 | clock_rate, 250, 32, clocksource_mmio_readl_down)) | 351 | clock_rate, 250, 32, clocksource_mmio_readl_down)) |
diff --git a/arch/arm/plat-versatile/sched-clock.c b/arch/arm/plat-versatile/sched-clock.c index 3d6a4c292cab..b33b74c87232 100644 --- a/arch/arm/plat-versatile/sched-clock.c +++ b/arch/arm/plat-versatile/sched-clock.c | |||
| @@ -18,41 +18,24 @@ | |||
| 18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 20 | */ | 20 | */ |
| 21 | #include <linux/kernel.h> | ||
| 21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
| 22 | #include <linux/sched.h> | ||
| 23 | 23 | ||
| 24 | #include <asm/sched_clock.h> | 24 | #include <asm/sched_clock.h> |
| 25 | #include <plat/sched_clock.h> | 25 | #include <plat/sched_clock.h> |
| 26 | 26 | ||
| 27 | static DEFINE_CLOCK_DATA(cd); | ||
| 28 | static void __iomem *ctr; | 27 | static void __iomem *ctr; |
| 29 | 28 | ||
| 30 | /* | 29 | static u32 notrace versatile_read_sched_clock(void) |
| 31 | * Constants generated by clocks_calc_mult_shift(m, s, 24MHz, NSEC_PER_SEC, 60). | ||
| 32 | * This gives a resolution of about 41ns and a wrap period of about 178s. | ||
| 33 | */ | ||
| 34 | #define SC_MULT 2796202667u | ||
| 35 | #define SC_SHIFT 26 | ||
| 36 | |||
| 37 | unsigned long long notrace sched_clock(void) | ||
| 38 | { | 30 | { |
| 39 | if (ctr) { | 31 | if (ctr) |
| 40 | u32 cyc = readl(ctr); | 32 | return readl(ctr); |
| 41 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, | ||
| 42 | SC_MULT, SC_SHIFT); | ||
| 43 | } else | ||
| 44 | return 0; | ||
| 45 | } | ||
| 46 | 33 | ||
| 47 | static void notrace versatile_update_sched_clock(void) | 34 | return 0; |
| 48 | { | ||
| 49 | u32 cyc = readl(ctr); | ||
| 50 | update_sched_clock(&cd, cyc, (u32)~0); | ||
| 51 | } | 35 | } |
| 52 | 36 | ||
| 53 | void __init versatile_sched_clock_init(void __iomem *reg, unsigned long rate) | 37 | void __init versatile_sched_clock_init(void __iomem *reg, unsigned long rate) |
| 54 | { | 38 | { |
| 55 | ctr = reg; | 39 | ctr = reg; |
| 56 | init_fixed_sched_clock(&cd, versatile_update_sched_clock, | 40 | setup_sched_clock(versatile_read_sched_clock, 32, rate); |
| 57 | 32, rate, SC_MULT, SC_SHIFT); | ||
| 58 | } | 41 | } |
