diff options
| author | Mark Salter <msalter@redhat.com> | 2010-10-27 12:28:57 -0400 |
|---|---|---|
| committer | David Howells <dhowells@redhat.com> | 2010-10-27 12:28:57 -0400 |
| commit | 730c1fad0ee22a170d2ee76a904709ee304931c0 (patch) | |
| tree | 365289c84b02c5c54d43238f2bc9b14b143cafbc | |
| parent | 2502c64eeb125c5d57e3e7dc38320b500d69e088 (diff) | |
MN10300: Generic time support
Implement generic time support for MN10300.
Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
| -rw-r--r-- | arch/mn10300/Kconfig | 22 | ||||
| -rw-r--r-- | arch/mn10300/include/asm/timex.h | 17 | ||||
| -rw-r--r-- | arch/mn10300/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/mn10300/kernel/cevt-mn10300.c | 131 | ||||
| -rw-r--r-- | arch/mn10300/kernel/csrc-mn10300.c | 35 | ||||
| -rw-r--r-- | arch/mn10300/kernel/internal.h | 13 | ||||
| -rw-r--r-- | arch/mn10300/kernel/irq.c | 32 | ||||
| -rw-r--r-- | arch/mn10300/kernel/smp.c | 15 | ||||
| -rw-r--r-- | arch/mn10300/kernel/time.c | 79 | ||||
| -rw-r--r-- | arch/mn10300/unit-asb2303/include/unit/timex.h | 48 | ||||
| -rw-r--r-- | arch/mn10300/unit-asb2305/include/unit/timex.h | 48 | ||||
| -rw-r--r-- | arch/mn10300/unit-asb2364/include/unit/timex.h | 74 |
12 files changed, 401 insertions, 115 deletions
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 81e27816aaf8..42ca55a47377 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig | |||
| @@ -56,6 +56,27 @@ config GENERIC_FIND_NEXT_BIT | |||
| 56 | config GENERIC_HWEIGHT | 56 | config GENERIC_HWEIGHT |
| 57 | def_bool y | 57 | def_bool y |
| 58 | 58 | ||
| 59 | config GENERIC_TIME | ||
| 60 | def_bool y | ||
| 61 | |||
| 62 | config GENERIC_CLOCKEVENTS | ||
| 63 | def_bool y | ||
| 64 | |||
| 65 | config GENERIC_CLOCKEVENTS_BUILD | ||
| 66 | def_bool y | ||
| 67 | depends on GENERIC_CLOCKEVENTS | ||
| 68 | |||
| 69 | config GENERIC_CLOCKEVENTS_BROADCAST | ||
| 70 | bool | ||
| 71 | |||
| 72 | config CEVT_MN10300 | ||
| 73 | def_bool y | ||
| 74 | depends on GENERIC_CLOCKEVENTS | ||
| 75 | |||
| 76 | config CSRC_MN10300 | ||
| 77 | def_bool y | ||
| 78 | depends on GENERIC_TIME | ||
| 79 | |||
| 59 | config GENERIC_BUG | 80 | config GENERIC_BUG |
| 60 | def_bool y | 81 | def_bool y |
| 61 | 82 | ||
| @@ -245,6 +266,7 @@ config MN10300_USING_JTAG | |||
| 245 | single-stepping, which are taken over completely by the JTAG unit. | 266 | single-stepping, which are taken over completely by the JTAG unit. |
| 246 | 267 | ||
| 247 | source "kernel/Kconfig.hz" | 268 | source "kernel/Kconfig.hz" |
| 269 | source "kernel/time/Kconfig" | ||
| 248 | 270 | ||
| 249 | config MN10300_RTC | 271 | config MN10300_RTC |
| 250 | bool "Using MN10300 RTC" | 272 | bool "Using MN10300 RTC" |
diff --git a/arch/mn10300/include/asm/timex.h b/arch/mn10300/include/asm/timex.h index ce5719a2ce7c..bd4e90dfe6c2 100644 --- a/arch/mn10300/include/asm/timex.h +++ b/arch/mn10300/include/asm/timex.h | |||
| @@ -18,15 +18,28 @@ | |||
| 18 | 18 | ||
| 19 | #define CLOCK_TICK_RATE MN10300_JCCLK /* Underlying HZ */ | 19 | #define CLOCK_TICK_RATE MN10300_JCCLK /* Underlying HZ */ |
| 20 | 20 | ||
| 21 | extern cycles_t cacheflush_time; | ||
| 22 | |||
| 23 | #ifdef __KERNEL__ | 21 | #ifdef __KERNEL__ |
| 24 | 22 | ||
| 23 | extern cycles_t cacheflush_time; | ||
| 24 | |||
| 25 | static inline cycles_t get_cycles(void) | 25 | static inline cycles_t get_cycles(void) |
| 26 | { | 26 | { |
| 27 | return read_timestamp_counter(); | 27 | return read_timestamp_counter(); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | extern int init_clockevents(void); | ||
| 31 | extern int init_clocksource(void); | ||
| 32 | |||
| 33 | static inline void setup_jiffies_interrupt(int irq, | ||
| 34 | struct irqaction *action) | ||
| 35 | { | ||
| 36 | u16 tmp; | ||
| 37 | setup_irq(irq, action); | ||
| 38 | set_intr_level(irq, NUM2GxICR_LEVEL(CONFIG_TIMER_IRQ_LEVEL)); | ||
| 39 | GxICR(irq) |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST; | ||
| 40 | tmp = GxICR(irq); | ||
| 41 | } | ||
| 42 | |||
| 30 | #endif /* __KERNEL__ */ | 43 | #endif /* __KERNEL__ */ |
| 31 | 44 | ||
| 32 | #endif /* _ASM_TIMEX_H */ | 45 | #endif /* _ASM_TIMEX_H */ |
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile index 5b41192f496b..8f5f1e81baf5 100644 --- a/arch/mn10300/kernel/Makefile +++ b/arch/mn10300/kernel/Makefile | |||
| @@ -28,3 +28,5 @@ obj-$(CONFIG_MN10300_RTC) += rtc.o | |||
| 28 | obj-$(CONFIG_PROFILE) += profile.o profile-low.o | 28 | obj-$(CONFIG_PROFILE) += profile.o profile-low.o |
| 29 | obj-$(CONFIG_MODULES) += module.o | 29 | obj-$(CONFIG_MODULES) += module.o |
| 30 | obj-$(CONFIG_KPROBES) += kprobes.o | 30 | obj-$(CONFIG_KPROBES) += kprobes.o |
| 31 | obj-$(CONFIG_CSRC_MN10300) += csrc-mn10300.o | ||
| 32 | obj-$(CONFIG_CEVT_MN10300) += cevt-mn10300.o | ||
diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c new file mode 100644 index 000000000000..d4cb535bf786 --- /dev/null +++ b/arch/mn10300/kernel/cevt-mn10300.c | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | /* MN10300 clockevents | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by Mark Salter (msalter@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/clockchips.h> | ||
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/percpu.h> | ||
| 14 | #include <linux/smp.h> | ||
| 15 | #include <asm/timex.h> | ||
| 16 | #include "internal.h" | ||
| 17 | |||
| 18 | #ifdef CONFIG_SMP | ||
| 19 | #if (CONFIG_NR_CPUS > 2) && !defined(CONFIG_GEENERIC_CLOCKEVENTS_BROADCAST) | ||
| 20 | #error "This doesn't scale well! Need per-core local timers." | ||
| 21 | #endif | ||
| 22 | #else /* CONFIG_SMP */ | ||
| 23 | #define stop_jiffies_counter1() | ||
| 24 | #define reload_jiffies_counter1(x) | ||
| 25 | #define TMJC1IRQ TMJCIRQ | ||
| 26 | #endif | ||
| 27 | |||
| 28 | |||
| 29 | static int next_event(unsigned long delta, | ||
| 30 | struct clock_event_device *evt) | ||
| 31 | { | ||
| 32 | unsigned int cpu = smp_processor_id(); | ||
| 33 | |||
| 34 | if (cpu == 0) { | ||
| 35 | stop_jiffies_counter(); | ||
| 36 | reload_jiffies_counter(delta - 1); | ||
| 37 | } else { | ||
| 38 | stop_jiffies_counter1(); | ||
| 39 | reload_jiffies_counter1(delta - 1); | ||
| 40 | } | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | static void set_clock_mode(enum clock_event_mode mode, | ||
| 45 | struct clock_event_device *evt) | ||
| 46 | { | ||
| 47 | /* Nothing to do ... */ | ||
| 48 | } | ||
| 49 | |||
| 50 | static DEFINE_PER_CPU(struct clock_event_device, mn10300_clockevent_device); | ||
| 51 | static DEFINE_PER_CPU(struct irqaction, timer_irq); | ||
| 52 | |||
| 53 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
| 54 | { | ||
| 55 | struct clock_event_device *cd; | ||
| 56 | unsigned int cpu = smp_processor_id(); | ||
| 57 | |||
| 58 | if (cpu == 0) | ||
| 59 | stop_jiffies_counter(); | ||
| 60 | else | ||
| 61 | stop_jiffies_counter1(); | ||
| 62 | |||
| 63 | cd = &per_cpu(mn10300_clockevent_device, cpu); | ||
| 64 | cd->event_handler(cd); | ||
| 65 | |||
| 66 | return IRQ_HANDLED; | ||
| 67 | } | ||
| 68 | |||
| 69 | static void event_handler(struct clock_event_device *dev) | ||
| 70 | { | ||
| 71 | } | ||
| 72 | |||
| 73 | int __init init_clockevents(void) | ||
| 74 | { | ||
| 75 | struct clock_event_device *cd; | ||
| 76 | struct irqaction *iact; | ||
| 77 | unsigned int cpu = smp_processor_id(); | ||
| 78 | |||
| 79 | cd = &per_cpu(mn10300_clockevent_device, cpu); | ||
| 80 | |||
| 81 | if (cpu == 0) { | ||
| 82 | stop_jiffies_counter(); | ||
| 83 | cd->irq = TMJCIRQ; | ||
| 84 | } else { | ||
| 85 | stop_jiffies_counter1(); | ||
| 86 | cd->irq = TMJC1IRQ; | ||
| 87 | } | ||
| 88 | |||
| 89 | cd->name = "Timestamp"; | ||
| 90 | cd->features = CLOCK_EVT_FEAT_ONESHOT; | ||
| 91 | |||
| 92 | /* Calculate the min / max delta */ | ||
| 93 | clockevent_set_clock(cd, MN10300_JCCLK); | ||
| 94 | |||
| 95 | cd->max_delta_ns = clockevent_delta2ns(TMJCBR_MAX, cd); | ||
| 96 | cd->min_delta_ns = clockevent_delta2ns(100, cd); | ||
| 97 | |||
| 98 | cd->rating = 200; | ||
| 99 | cd->cpumask = cpumask_of(smp_processor_id()); | ||
| 100 | cd->set_mode = set_clock_mode; | ||
| 101 | cd->event_handler = event_handler; | ||
| 102 | cd->set_next_event = next_event; | ||
| 103 | |||
| 104 | iact = &per_cpu(timer_irq, cpu); | ||
| 105 | iact->flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER; | ||
| 106 | iact->handler = timer_interrupt; | ||
| 107 | |||
| 108 | clockevents_register_device(cd); | ||
| 109 | |||
| 110 | #if defined(CONFIG_SMP) && !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) | ||
| 111 | /* setup timer irq affinity so it only runs on this cpu */ | ||
| 112 | { | ||
| 113 | struct irq_desc *desc; | ||
| 114 | desc = irq_to_desc(cd->irq); | ||
| 115 | cpumask_copy(desc->affinity, cpumask_of(cpu)); | ||
| 116 | iact->flags |= IRQF_NOBALANCING; | ||
| 117 | } | ||
| 118 | #endif | ||
| 119 | |||
| 120 | if (cpu == 0) { | ||
| 121 | reload_jiffies_counter(MN10300_JC_PER_HZ - 1); | ||
| 122 | iact->name = "CPU0 Timer"; | ||
| 123 | } else { | ||
| 124 | reload_jiffies_counter1(MN10300_JC_PER_HZ - 1); | ||
| 125 | iact->name = "CPU1 Timer"; | ||
| 126 | } | ||
| 127 | |||
| 128 | setup_jiffies_interrupt(cd->irq, iact); | ||
| 129 | |||
| 130 | return 0; | ||
| 131 | } | ||
diff --git a/arch/mn10300/kernel/csrc-mn10300.c b/arch/mn10300/kernel/csrc-mn10300.c new file mode 100644 index 000000000000..ba2f0c4d6e01 --- /dev/null +++ b/arch/mn10300/kernel/csrc-mn10300.c | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | /* MN10300 clocksource | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by Mark Salter (msalter@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/clocksource.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <asm/timex.h> | ||
| 14 | #include "internal.h" | ||
| 15 | |||
| 16 | static cycle_t mn10300_read(struct clocksource *cs) | ||
| 17 | { | ||
| 18 | return read_timestamp_counter(); | ||
| 19 | } | ||
| 20 | |||
| 21 | static struct clocksource clocksource_mn10300 = { | ||
| 22 | .name = "TSC", | ||
| 23 | .rating = 200, | ||
| 24 | .read = mn10300_read, | ||
| 25 | .mask = CLOCKSOURCE_MASK(32), | ||
| 26 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
| 27 | }; | ||
| 28 | |||
| 29 | int __init init_clocksource(void) | ||
| 30 | { | ||
| 31 | startup_timestamp_counter(); | ||
| 32 | clocksource_set_clock(&clocksource_mn10300, MN10300_TSCCLK); | ||
| 33 | clocksource_register(&clocksource_mn10300); | ||
| 34 | return 0; | ||
| 35 | } | ||
diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h index 3b1f48b7e7f4..6a064ab5af07 100644 --- a/arch/mn10300/kernel/internal.h +++ b/arch/mn10300/kernel/internal.h | |||
| @@ -9,6 +9,9 @@ | |||
| 9 | * 2 of the Licence, or (at your option) any later version. | 9 | * 2 of the Licence, or (at your option) any later version. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | struct clocksource; | ||
| 13 | struct clock_event_device; | ||
| 14 | |||
| 12 | /* | 15 | /* |
| 13 | * kthread.S | 16 | * kthread.S |
| 14 | */ | 17 | */ |
| @@ -30,3 +33,13 @@ extern void mn10300_low_ipi_handler(void); | |||
| 30 | * time.c | 33 | * time.c |
| 31 | */ | 34 | */ |
| 32 | extern irqreturn_t local_timer_interrupt(void); | 35 | extern irqreturn_t local_timer_interrupt(void); |
| 36 | |||
| 37 | /* | ||
| 38 | * time.c | ||
| 39 | */ | ||
| 40 | #ifdef CONFIG_CEVT_MN10300 | ||
| 41 | extern void clockevent_set_clock(struct clock_event_device *, unsigned int); | ||
| 42 | #endif | ||
| 43 | #ifdef CONFIG_CSRC_MN10300 | ||
| 44 | extern void clocksource_set_clock(struct clocksource *, unsigned int); | ||
| 45 | #endif | ||
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index 80f15725ecad..2f66a45dcd18 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c | |||
| @@ -16,14 +16,6 @@ | |||
| 16 | #include <asm/setup.h> | 16 | #include <asm/setup.h> |
| 17 | #include <asm/serial-regs.h> | 17 | #include <asm/serial-regs.h> |
| 18 | 18 | ||
| 19 | #ifdef CONFIG_SMP | ||
| 20 | #undef GxICR | ||
| 21 | #define GxICR(X) CROSS_GxICR(X, irq_affinity_online[X]) | ||
| 22 | |||
| 23 | #undef GxICR_u8 | ||
| 24 | #define GxICR_u8(X) CROSS_GxICR_u8(X, irq_affinity_online[X]) | ||
| 25 | #endif /* CONFIG_SMP */ | ||
| 26 | |||
| 27 | unsigned long __mn10300_irq_enabled_epsw[NR_CPUS] __cacheline_aligned_in_smp = { | 19 | unsigned long __mn10300_irq_enabled_epsw[NR_CPUS] __cacheline_aligned_in_smp = { |
| 28 | [0 ... NR_CPUS - 1] = EPSW_IE | EPSW_IM_7 | 20 | [0 ... NR_CPUS - 1] = EPSW_IE | EPSW_IM_7 |
| 29 | }; | 21 | }; |
| @@ -92,9 +84,11 @@ static void mn10300_cpupic_mask_ack(unsigned int irq) | |||
| 92 | GxICR(irq) = (tmp & GxICR_LEVEL); | 84 | GxICR(irq) = (tmp & GxICR_LEVEL); |
| 93 | tmp2 = GxICR(irq); | 85 | tmp2 = GxICR(irq); |
| 94 | 86 | ||
| 95 | irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity); | 87 | irq_affinity_online[irq] = |
| 96 | GxICR(irq) = (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT; | 88 | any_online_cpu(*irq_desc[irq].affinity); |
| 97 | tmp = GxICR(irq); | 89 | CROSS_GxICR(irq, irq_affinity_online[irq]) = |
| 90 | (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT; | ||
| 91 | tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); | ||
| 98 | } | 92 | } |
| 99 | 93 | ||
| 100 | arch_local_irq_restore(flags); | 94 | arch_local_irq_restore(flags); |
| @@ -128,8 +122,8 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq) | |||
| 128 | tmp = GxICR(irq); | 122 | tmp = GxICR(irq); |
| 129 | 123 | ||
| 130 | irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity); | 124 | irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity); |
| 131 | GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; | 125 | CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; |
| 132 | tmp = GxICR(irq); | 126 | tmp = CROSS_GxICR(irq, irq_affinity_online[irq]); |
| 133 | } | 127 | } |
| 134 | 128 | ||
| 135 | arch_local_irq_restore(flags); | 129 | arch_local_irq_restore(flags); |
| @@ -217,7 +211,7 @@ static struct irq_chip mn10300_cpu_pic_level = { | |||
| 217 | .unmask = mn10300_cpupic_unmask_clear, | 211 | .unmask = mn10300_cpupic_unmask_clear, |
| 218 | #ifdef CONFIG_SMP | 212 | #ifdef CONFIG_SMP |
| 219 | .set_affinity = mn10300_cpupic_setaffinity, | 213 | .set_affinity = mn10300_cpupic_setaffinity, |
| 220 | #endif /* CONFIG_SMP */ | 214 | #endif |
| 221 | }; | 215 | }; |
| 222 | 216 | ||
| 223 | /* | 217 | /* |
| @@ -235,7 +229,7 @@ static struct irq_chip mn10300_cpu_pic_edge = { | |||
| 235 | .unmask = mn10300_cpupic_unmask, | 229 | .unmask = mn10300_cpupic_unmask, |
| 236 | #ifdef CONFIG_SMP | 230 | #ifdef CONFIG_SMP |
| 237 | .set_affinity = mn10300_cpupic_setaffinity, | 231 | .set_affinity = mn10300_cpupic_setaffinity, |
| 238 | #endif /* CONFIG_SMP */ | 232 | #endif |
| 239 | }; | 233 | }; |
| 240 | 234 | ||
| 241 | /* | 235 | /* |
| @@ -446,9 +440,9 @@ void migrate_irqs(void) | |||
| 446 | if (irq_affinity_online[irq] == self) { | 440 | if (irq_affinity_online[irq] == self) { |
| 447 | u16 x, tmp; | 441 | u16 x, tmp; |
| 448 | 442 | ||
| 449 | x = CROSS_GxICR(irq, self); | 443 | x = GxICR(irq); |
| 450 | CROSS_GxICR(irq, self) = x & GxICR_LEVEL; | 444 | GxICR(irq) = x & GxICR_LEVEL; |
| 451 | tmp = CROSS_GxICR(irq, self); | 445 | tmp = GxICR(irq); |
| 452 | 446 | ||
| 453 | new = any_online_cpu(irq_desc[irq].affinity); | 447 | new = any_online_cpu(irq_desc[irq].affinity); |
| 454 | irq_affinity_online[irq] = new; | 448 | irq_affinity_online[irq] = new; |
| @@ -458,7 +452,7 @@ void migrate_irqs(void) | |||
| 458 | tmp = CROSS_GxICR(irq, new); | 452 | tmp = CROSS_GxICR(irq, new); |
| 459 | 453 | ||
| 460 | x &= GxICR_LEVEL | GxICR_ENABLE; | 454 | x &= GxICR_LEVEL | GxICR_ENABLE; |
| 461 | if (CROSS_GxICR(irq, self) & GxICR_REQUEST) | 455 | if (GxICR(irq) & GxICR_REQUEST) { |
| 462 | x |= GxICR_REQUEST | GxICR_DETECT; | 456 | x |= GxICR_REQUEST | GxICR_DETECT; |
| 463 | CROSS_GxICR(irq, new) = x; | 457 | CROSS_GxICR(irq, new) = x; |
| 464 | tmp = CROSS_GxICR(irq, new); | 458 | tmp = CROSS_GxICR(irq, new); |
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c index b80234c28e0d..0dcd1c686ba8 100644 --- a/arch/mn10300/kernel/smp.c +++ b/arch/mn10300/kernel/smp.c | |||
| @@ -126,7 +126,6 @@ static struct irq_chip mn10300_ipi_type = { | |||
| 126 | 126 | ||
| 127 | static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id); | 127 | static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id); |
| 128 | static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id); | 128 | static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id); |
| 129 | static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id); | ||
| 130 | 129 | ||
| 131 | static struct irqaction reschedule_ipi = { | 130 | static struct irqaction reschedule_ipi = { |
| 132 | .handler = smp_reschedule_interrupt, | 131 | .handler = smp_reschedule_interrupt, |
| @@ -136,11 +135,15 @@ static struct irqaction call_function_ipi = { | |||
| 136 | .handler = smp_call_function_interrupt, | 135 | .handler = smp_call_function_interrupt, |
| 137 | .name = "smp call function IPI" | 136 | .name = "smp call function IPI" |
| 138 | }; | 137 | }; |
| 138 | |||
| 139 | #if !defined(CONFIG_GENERIC_CLOCKEVENTS) || defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) | ||
| 140 | static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id); | ||
| 139 | static struct irqaction local_timer_ipi = { | 141 | static struct irqaction local_timer_ipi = { |
| 140 | .handler = smp_ipi_timer_interrupt, | 142 | .handler = smp_ipi_timer_interrupt, |
| 141 | .flags = IRQF_DISABLED, | 143 | .flags = IRQF_DISABLED, |
| 142 | .name = "smp local timer IPI" | 144 | .name = "smp local timer IPI" |
| 143 | }; | 145 | }; |
| 146 | #endif | ||
| 144 | 147 | ||
| 145 | /** | 148 | /** |
| 146 | * init_ipi - Initialise the IPI mechanism | 149 | * init_ipi - Initialise the IPI mechanism |
| @@ -165,11 +168,14 @@ static void init_ipi(void) | |||
| 165 | mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI); | 168 | mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI); |
| 166 | 169 | ||
| 167 | /* set up the local timer IPI */ | 170 | /* set up the local timer IPI */ |
| 171 | #if !defined(CONFIG_GENERIC_CLOCKEVENTS) || \ | ||
| 172 | defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) | ||
| 168 | set_irq_chip_and_handler(LOCAL_TIMER_IPI, | 173 | set_irq_chip_and_handler(LOCAL_TIMER_IPI, |
| 169 | &mn10300_ipi_type, handle_percpu_irq); | 174 | &mn10300_ipi_type, handle_percpu_irq); |
| 170 | setup_irq(LOCAL_TIMER_IPI, &local_timer_ipi); | 175 | setup_irq(LOCAL_TIMER_IPI, &local_timer_ipi); |
| 171 | set_intr_level(LOCAL_TIMER_IPI, LOCAL_TIMER_GxICR_LV); | 176 | set_intr_level(LOCAL_TIMER_IPI, LOCAL_TIMER_GxICR_LV); |
| 172 | mn10300_ipi_enable(LOCAL_TIMER_IPI); | 177 | mn10300_ipi_enable(LOCAL_TIMER_IPI); |
| 178 | #endif | ||
| 173 | 179 | ||
| 174 | #ifdef CONFIG_MN10300_CACHE_ENABLED | 180 | #ifdef CONFIG_MN10300_CACHE_ENABLED |
| 175 | /* set up the cache flush IPI */ | 181 | /* set up the cache flush IPI */ |
| @@ -505,6 +511,8 @@ void smp_nmi_call_function_interrupt(void) | |||
| 505 | } | 511 | } |
| 506 | } | 512 | } |
| 507 | 513 | ||
| 514 | #if !defined(CONFIG_GENERIC_CLOCKEVENTS) || \ | ||
| 515 | defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) | ||
| 508 | /** | 516 | /** |
| 509 | * smp_ipi_timer_interrupt - Local timer IPI handler | 517 | * smp_ipi_timer_interrupt - Local timer IPI handler |
| 510 | * @irq: The interrupt number. | 518 | * @irq: The interrupt number. |
| @@ -516,6 +524,7 @@ static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id) | |||
| 516 | { | 524 | { |
| 517 | return local_timer_interrupt(); | 525 | return local_timer_interrupt(); |
| 518 | } | 526 | } |
| 527 | #endif | ||
| 519 | 528 | ||
| 520 | void __init smp_init_cpus(void) | 529 | void __init smp_init_cpus(void) |
| 521 | { | 530 | { |
| @@ -620,7 +629,6 @@ void smp_prepare_cpu_init(void) | |||
| 620 | int __init start_secondary(void *unused) | 629 | int __init start_secondary(void *unused) |
| 621 | { | 630 | { |
| 622 | smp_cpu_init(); | 631 | smp_cpu_init(); |
| 623 | |||
| 624 | smp_callin(); | 632 | smp_callin(); |
| 625 | while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) | 633 | while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) |
| 626 | cpu_relax(); | 634 | cpu_relax(); |
| @@ -629,6 +637,9 @@ int __init start_secondary(void *unused) | |||
| 629 | preempt_disable(); | 637 | preempt_disable(); |
| 630 | smp_online(); | 638 | smp_online(); |
| 631 | 639 | ||
| 640 | #ifdef CONFIG_GENERIC_CLOCKEVENTS | ||
| 641 | init_clockevents(); | ||
| 642 | #endif | ||
| 632 | cpu_idle(); | 643 | cpu_idle(); |
| 633 | return 0; | 644 | return 0; |
| 634 | } | 645 | } |
diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index 0cb9bdb3b6bd..f860a340acc9 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #include <linux/smp.h> | 17 | #include <linux/smp.h> |
| 18 | #include <linux/profile.h> | 18 | #include <linux/profile.h> |
| 19 | #include <linux/cnt32_to_63.h> | 19 | #include <linux/cnt32_to_63.h> |
| 20 | #include <linux/clocksource.h> | ||
| 21 | #include <linux/clockchips.h> | ||
| 20 | #include <asm/irq.h> | 22 | #include <asm/irq.h> |
| 21 | #include <asm/div64.h> | 23 | #include <asm/div64.h> |
| 22 | #include <asm/processor.h> | 24 | #include <asm/processor.h> |
| @@ -27,14 +29,6 @@ | |||
| 27 | static unsigned long mn10300_last_tsc; /* time-stamp counter at last time | 29 | static unsigned long mn10300_last_tsc; /* time-stamp counter at last time |
| 28 | * interrupt occurred */ | 30 | * interrupt occurred */ |
| 29 | 31 | ||
| 30 | static irqreturn_t timer_interrupt(int irq, void *dev_id); | ||
| 31 | |||
| 32 | static struct irqaction timer_irq = { | ||
| 33 | .handler = timer_interrupt, | ||
| 34 | .flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER, | ||
| 35 | .name = "timer", | ||
| 36 | }; | ||
| 37 | |||
| 38 | static unsigned long sched_clock_multiplier; | 32 | static unsigned long sched_clock_multiplier; |
| 39 | 33 | ||
| 40 | /* | 34 | /* |
| @@ -54,7 +48,7 @@ unsigned long long sched_clock(void) | |||
| 54 | 48 | ||
| 55 | /* read the TSC value | 49 | /* read the TSC value |
| 56 | */ | 50 | */ |
| 57 | tsc = 0 - get_cycles(); /* get_cycles() counts down */ | 51 | tsc = get_cycles(); |
| 58 | 52 | ||
| 59 | /* expand to 64-bits. | 53 | /* expand to 64-bits. |
| 60 | * - sched_clock() must be called once a minute or better or the | 54 | * - sched_clock() must be called once a minute or better or the |
| @@ -103,6 +97,7 @@ irqreturn_t local_timer_interrupt(void) | |||
| 103 | return IRQ_HANDLED; | 97 | return IRQ_HANDLED; |
| 104 | } | 98 | } |
| 105 | 99 | ||
| 100 | #ifndef CONFIG_GENERIC_TIME | ||
| 106 | /* | 101 | /* |
| 107 | * advance the kernel's time keeping clocks (xtime and jiffies) | 102 | * advance the kernel's time keeping clocks (xtime and jiffies) |
| 108 | * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time | 103 | * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time |
| @@ -116,11 +111,11 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
| 116 | write_seqlock(&xtime_lock); | 111 | write_seqlock(&xtime_lock); |
| 117 | 112 | ||
| 118 | while (tsc = get_cycles(), | 113 | while (tsc = get_cycles(), |
| 119 | elapse = mn10300_last_tsc - tsc, /* time elapsed since last | 114 | elapse = tsc - mn10300_last_tsc, /* time elapsed since last |
| 120 | * tick */ | 115 | * tick */ |
| 121 | elapse > MN10300_TSC_PER_HZ | 116 | elapse > MN10300_TSC_PER_HZ |
| 122 | ) { | 117 | ) { |
| 123 | mn10300_last_tsc -= MN10300_TSC_PER_HZ; | 118 | mn10300_last_tsc += MN10300_TSC_PER_HZ; |
| 124 | 119 | ||
| 125 | /* advance the kernel's time tracking system */ | 120 | /* advance the kernel's time tracking system */ |
| 126 | do_timer(1); | 121 | do_timer(1); |
| @@ -135,6 +130,50 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
| 135 | return ret; | 130 | return ret; |
| 136 | } | 131 | } |
| 137 | 132 | ||
| 133 | static struct irqaction timer_irq = { | ||
| 134 | .handler = timer_interrupt, | ||
| 135 | .flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER, | ||
| 136 | .name = "timer", | ||
| 137 | }; | ||
| 138 | #endif /* CONFIG_GENERIC_TIME */ | ||
| 139 | |||
| 140 | #ifdef CONFIG_CSRC_MN10300 | ||
| 141 | void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) | ||
| 142 | { | ||
| 143 | u64 temp; | ||
| 144 | u32 shift; | ||
| 145 | |||
| 146 | /* Find a shift value */ | ||
| 147 | for (shift = 32; shift > 0; shift--) { | ||
| 148 | temp = (u64) NSEC_PER_SEC << shift; | ||
| 149 | do_div(temp, clock); | ||
| 150 | if ((temp >> 32) == 0) | ||
| 151 | break; | ||
| 152 | } | ||
| 153 | cs->shift = shift; | ||
| 154 | cs->mult = (u32) temp; | ||
| 155 | } | ||
| 156 | #endif | ||
| 157 | |||
| 158 | #if CONFIG_CEVT_MN10300 | ||
| 159 | void __cpuinit clockevent_set_clock(struct clock_event_device *cd, | ||
| 160 | unsigned int clock) | ||
| 161 | { | ||
| 162 | u64 temp; | ||
| 163 | u32 shift; | ||
| 164 | |||
| 165 | /* Find a shift value */ | ||
| 166 | for (shift = 32; shift > 0; shift--) { | ||
| 167 | temp = (u64) clock << shift; | ||
| 168 | do_div(temp, NSEC_PER_SEC); | ||
| 169 | if ((temp >> 32) == 0) | ||
| 170 | break; | ||
| 171 | } | ||
| 172 | cd->shift = shift; | ||
| 173 | cd->mult = (u32) temp; | ||
| 174 | } | ||
| 175 | #endif | ||
| 176 | |||
| 138 | /* | 177 | /* |
| 139 | * initialise the various timers used by the main part of the kernel | 178 | * initialise the various timers used by the main part of the kernel |
| 140 | */ | 179 | */ |
| @@ -146,21 +185,25 @@ void __init time_init(void) | |||
| 146 | */ | 185 | */ |
| 147 | TMPSCNT |= TMPSCNT_ENABLE; | 186 | TMPSCNT |= TMPSCNT_ENABLE; |
| 148 | 187 | ||
| 188 | #ifdef CONFIG_GENERIC_TIME | ||
| 189 | init_clocksource(); | ||
| 190 | #else | ||
| 149 | startup_timestamp_counter(); | 191 | startup_timestamp_counter(); |
| 192 | #endif | ||
| 150 | 193 | ||
| 151 | printk(KERN_INFO | 194 | printk(KERN_INFO |
| 152 | "timestamp counter I/O clock running at %lu.%02lu" | 195 | "timestamp counter I/O clock running at %lu.%02lu" |
| 153 | " (calibrated against RTC)\n", | 196 | " (calibrated against RTC)\n", |
| 154 | MN10300_TSCCLK / 1000000, (MN10300_TSCCLK / 10000) % 100); | 197 | MN10300_TSCCLK / 1000000, (MN10300_TSCCLK / 10000) % 100); |
| 155 | 198 | ||
| 156 | mn10300_last_tsc = TMTSCBC; | 199 | mn10300_last_tsc = read_timestamp_counter(); |
| 157 | 200 | ||
| 158 | /* use timer 0 & 1 cascaded to tick at as close to HZ as possible */ | 201 | #ifdef CONFIG_GENERIC_CLOCKEVENTS |
| 159 | setup_irq(TMJCIRQ, &timer_irq); | 202 | init_clockevents(); |
| 160 | 203 | #else | |
| 161 | set_intr_level(TMJCIRQ, NUM2GxICR_LEVEL(CONFIG_TIMER_IRQ_LEVEL)); | 204 | reload_jiffies_counter(MN10300_JC_PER_HZ - 1); |
| 162 | 205 | setup_jiffies_interrupt(TMJCIRQ, &timer_irq, CONFIG_TIMER_IRQ_LEVEL); | |
| 163 | startup_jiffies_counter(); | 206 | #endif |
| 164 | 207 | ||
| 165 | #ifdef CONFIG_MN10300_WD_TIMER | 208 | #ifdef CONFIG_MN10300_WD_TIMER |
| 166 | /* start the watchdog timer */ | 209 | /* start the watchdog timer */ |
diff --git a/arch/mn10300/unit-asb2303/include/unit/timex.h b/arch/mn10300/unit-asb2303/include/unit/timex.h index d1b8dafe7d7d..cc18fe7d8b90 100644 --- a/arch/mn10300/unit-asb2303/include/unit/timex.h +++ b/arch/mn10300/unit-asb2303/include/unit/timex.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* ASB2303-specific timer specifications | 1 | /* ASB2303-specific timer specifications |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2007, 2010 Red Hat, Inc. All Rights Reserved. |
| 4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
| @@ -24,10 +24,6 @@ | |||
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | #define TMJCBR_MAX 0xffff | 26 | #define TMJCBR_MAX 0xffff |
| 27 | #define TMJCBC TM01BC | ||
| 28 | |||
| 29 | #define TMJCMD TM01MD | ||
| 30 | #define TMJCBR TM01BR | ||
| 31 | #define TMJCIRQ TM1IRQ | 27 | #define TMJCIRQ TM1IRQ |
| 32 | #define TMJCICR TM1ICR | 28 | #define TMJCICR TM1ICR |
| 33 | 29 | ||
| @@ -61,34 +57,32 @@ | |||
| 61 | #define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ) | 57 | #define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ) |
| 62 | #define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ) | 58 | #define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ) |
| 63 | 59 | ||
| 64 | static inline void startup_jiffies_counter(void) | 60 | static inline void stop_jiffies_counter(void) |
| 65 | { | 61 | { |
| 66 | u16 md, t16; | 62 | u16 tmp; |
| 63 | TM01MD = JC_TIMER_CLKSRC | TM1MD_SRC_TM0CASCADE << 8; | ||
| 64 | tmp = TM01MD; | ||
| 65 | } | ||
| 67 | 66 | ||
| 68 | md = JC_TIMER_CLKSRC; | 67 | static inline void reload_jiffies_counter(u32 cnt) |
| 69 | TMJCBR = MN10300_JC_PER_HZ - 1; | 68 | { |
| 70 | t16 = TMJCBR; | 69 | u32 tmp; |
| 71 | 70 | ||
| 72 | TMJCMD = | 71 | TM01BR = cnt; |
| 73 | md | | 72 | tmp = TM01BR; |
| 74 | TM1MD_SRC_TM0CASCADE << 8 | | ||
| 75 | TM0MD_INIT_COUNTER | | ||
| 76 | TM1MD_INIT_COUNTER << 8; | ||
| 77 | 73 | ||
| 78 | TMJCMD = | 74 | TM01MD = JC_TIMER_CLKSRC | \ |
| 79 | md | | 75 | TM1MD_SRC_TM0CASCADE << 8 | \ |
| 80 | TM1MD_SRC_TM0CASCADE << 8 | | 76 | TM0MD_INIT_COUNTER | \ |
| 81 | TM0MD_COUNT_ENABLE | | 77 | TM1MD_INIT_COUNTER << 8; |
| 82 | TM1MD_COUNT_ENABLE << 8; | ||
| 83 | 78 | ||
| 84 | t16 = TMJCMD; | ||
| 85 | 79 | ||
| 86 | TMJCICR |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST; | 80 | TM01MD = JC_TIMER_CLKSRC | \ |
| 87 | t16 = TMJCICR; | 81 | TM1MD_SRC_TM0CASCADE << 8 | \ |
| 88 | } | 82 | TM0MD_COUNT_ENABLE | \ |
| 83 | TM1MD_COUNT_ENABLE << 8; | ||
| 89 | 84 | ||
| 90 | static inline void shutdown_jiffies_counter(void) | 85 | tmp = TM01MD; |
| 91 | { | ||
| 92 | } | 86 | } |
| 93 | 87 | ||
| 94 | #endif /* !__ASSEMBLY__ */ | 88 | #endif /* !__ASSEMBLY__ */ |
| @@ -148,7 +142,7 @@ typedef unsigned long cycles_t; | |||
| 148 | 142 | ||
| 149 | static inline cycles_t read_timestamp_counter(void) | 143 | static inline cycles_t read_timestamp_counter(void) |
| 150 | { | 144 | { |
| 151 | return (cycles_t)TMTSCBC; | 145 | return (cycles_t)~TMTSCBC; |
| 152 | } | 146 | } |
| 153 | 147 | ||
| 154 | #endif /* !__ASSEMBLY__ */ | 148 | #endif /* !__ASSEMBLY__ */ |
diff --git a/arch/mn10300/unit-asb2305/include/unit/timex.h b/arch/mn10300/unit-asb2305/include/unit/timex.h index cd8bc14e3ca3..758af30d1a16 100644 --- a/arch/mn10300/unit-asb2305/include/unit/timex.h +++ b/arch/mn10300/unit-asb2305/include/unit/timex.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* ASB2305-specific timer specifications | 1 | /* ASB2305-specific timer specifications |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2007, 2010 Red Hat, Inc. All Rights Reserved. |
| 4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
| @@ -24,10 +24,6 @@ | |||
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | #define TMJCBR_MAX 0xffff | 26 | #define TMJCBR_MAX 0xffff |
| 27 | #define TMJCBC TM01BC | ||
| 28 | |||
| 29 | #define TMJCMD TM01MD | ||
| 30 | #define TMJCBR TM01BR | ||
| 31 | #define TMJCIRQ TM1IRQ | 27 | #define TMJCIRQ TM1IRQ |
| 32 | #define TMJCICR TM1ICR | 28 | #define TMJCICR TM1ICR |
| 33 | 29 | ||
| @@ -61,34 +57,32 @@ | |||
| 61 | #define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ) | 57 | #define MN10300_JC_PER_HZ ((MN10300_JCCLK + HZ / 2) / HZ) |
| 62 | #define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ) | 58 | #define MN10300_TSC_PER_HZ ((MN10300_TSCCLK + HZ / 2) / HZ) |
| 63 | 59 | ||
| 64 | static inline void startup_jiffies_counter(void) | 60 | static inline void stop_jiffies_counter(void) |
| 65 | { | 61 | { |
| 66 | u16 md, t16; | 62 | u16 tmp; |
| 63 | TM01MD = JC_TIMER_CLKSRC | TM1MD_SRC_TM0CASCADE << 8; | ||
| 64 | tmp = TM01MD; | ||
| 65 | } | ||
| 67 | 66 | ||
| 68 | md = JC_TIMER_CLKSRC; | 67 | static inline void reload_jiffies_counter(u32 cnt) |
| 69 | TMJCBR = MN10300_JC_PER_HZ - 1; | 68 | { |
| 70 | t16 = TMJCBR; | 69 | u32 tmp; |
| 71 | 70 | ||
| 72 | TMJCMD = | 71 | TM01BR = cnt; |
| 73 | md | | 72 | tmp = TM01BR; |
| 74 | TM1MD_SRC_TM0CASCADE << 8 | | ||
| 75 | TM0MD_INIT_COUNTER | | ||
| 76 | TM1MD_INIT_COUNTER << 8; | ||
| 77 | 73 | ||
| 78 | TMJCMD = | 74 | TM01MD = JC_TIMER_CLKSRC | \ |
| 79 | md | | 75 | TM1MD_SRC_TM0CASCADE << 8 | \ |
| 80 | TM1MD_SRC_TM0CASCADE << 8 | | 76 | TM0MD_INIT_COUNTER | \ |
| 81 | TM0MD_COUNT_ENABLE | | 77 | TM1MD_INIT_COUNTER << 8; |
| 82 | TM1MD_COUNT_ENABLE << 8; | ||
| 83 | 78 | ||
| 84 | t16 = TMJCMD; | ||
| 85 | 79 | ||
| 86 | TMJCICR |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST; | 80 | TM01MD = JC_TIMER_CLKSRC | \ |
| 87 | t16 = TMJCICR; | 81 | TM1MD_SRC_TM0CASCADE << 8 | \ |
| 88 | } | 82 | TM0MD_COUNT_ENABLE | \ |
| 83 | TM1MD_COUNT_ENABLE << 8; | ||
| 89 | 84 | ||
| 90 | static inline void shutdown_jiffies_counter(void) | 85 | tmp = TM01MD; |
| 91 | { | ||
| 92 | } | 86 | } |
| 93 | 87 | ||
| 94 | #endif /* !__ASSEMBLY__ */ | 88 | #endif /* !__ASSEMBLY__ */ |
| @@ -148,7 +142,7 @@ typedef unsigned long cycles_t; | |||
| 148 | 142 | ||
| 149 | static inline cycles_t read_timestamp_counter(void) | 143 | static inline cycles_t read_timestamp_counter(void) |
| 150 | { | 144 | { |
| 151 | return (cycles_t)TMTSCBC; | 145 | return (cycles_t)~TMTSCBC; |
| 152 | } | 146 | } |
| 153 | 147 | ||
| 154 | #endif /* !__ASSEMBLY__ */ | 148 | #endif /* !__ASSEMBLY__ */ |
diff --git a/arch/mn10300/unit-asb2364/include/unit/timex.h b/arch/mn10300/unit-asb2364/include/unit/timex.h index b5223f705ef8..ddb7ed010706 100644 --- a/arch/mn10300/unit-asb2364/include/unit/timex.h +++ b/arch/mn10300/unit-asb2364/include/unit/timex.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* timex.h: MN2WS0038 architecture timer specifications | 1 | /* timex.h: MN2WS0038 architecture timer specifications |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2002, 2010 Red Hat, Inc. All Rights Reserved. |
| 4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
| @@ -24,12 +24,7 @@ | |||
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | #define TMJCBR_MAX 0xffffff /* 24bit */ | 26 | #define TMJCBR_MAX 0xffffff /* 24bit */ |
| 27 | #define TMJCBC TMTBC | ||
| 28 | |||
| 29 | #define TMJCMD TMTMD | ||
| 30 | #define TMJCBR TMTBR | ||
| 31 | #define TMJCIRQ TMTIRQ | 27 | #define TMJCIRQ TMTIRQ |
| 32 | #define TMJCICR TMTICR | ||
| 33 | 28 | ||
| 34 | #ifndef __ASSEMBLY__ | 29 | #ifndef __ASSEMBLY__ |
| 35 | 30 | ||
| @@ -50,25 +45,63 @@ | |||
| 50 | # error MTM tick timer interval value is overflow. | 45 | # error MTM tick timer interval value is overflow. |
| 51 | #endif | 46 | #endif |
| 52 | 47 | ||
| 48 | static inline void stop_jiffies_counter(void) | ||
| 49 | { | ||
| 50 | u16 tmp; | ||
| 51 | TMTMD = 0; | ||
| 52 | tmp = TMTMD; | ||
| 53 | } | ||
| 53 | 54 | ||
| 54 | static inline void startup_jiffies_counter(void) | 55 | static inline void reload_jiffies_counter(u32 cnt) |
| 55 | { | 56 | { |
| 56 | u32 sync; | 57 | u32 tmp; |
| 58 | |||
| 59 | TMTBR = cnt; | ||
| 60 | tmp = TMTBR; | ||
| 57 | 61 | ||
| 58 | TMJCBR = MN10300_JC_PER_HZ - 1; | 62 | TMTMD = TMTMD_TMTLDE; |
| 59 | sync = TMJCBR; | 63 | TMTMD = TMTMD_TMTCNE; |
| 64 | tmp = TMTMD; | ||
| 65 | } | ||
| 60 | 66 | ||
| 61 | TMJCMD = TMTMD_TMTLDE; | 67 | #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_CLOCKEVENTS) && \ |
| 62 | TMJCMD = TMTMD_TMTCNE; | 68 | !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) |
| 63 | sync = TMJCMD; | 69 | /* |
| 70 | * If we aren't using broadcasting, each core needs its own event timer. | ||
| 71 | * Since CPU0 uses the tick timer which is 24-bits, we use timer 4 & 5 | ||
| 72 | * cascaded to 32-bits for CPU1 (but only really use 24-bits to match | ||
| 73 | * CPU0). | ||
| 74 | */ | ||
| 64 | 75 | ||
| 65 | TMJCICR |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST; | 76 | #define TMJC1IRQ TM5IRQ |
| 66 | sync = TMJCICR; | 77 | |
| 78 | static inline void stop_jiffies_counter1(void) | ||
| 79 | { | ||
| 80 | u8 tmp; | ||
| 81 | TM4MD = 0; | ||
| 82 | TM5MD = 0; | ||
| 83 | tmp = TM4MD; | ||
| 84 | tmp = TM5MD; | ||
| 67 | } | 85 | } |
| 68 | 86 | ||
| 69 | static inline void shutdown_jiffies_counter(void) | 87 | static inline void reload_jiffies_counter1(u32 cnt) |
| 70 | { | 88 | { |
| 89 | u32 tmp; | ||
| 90 | |||
| 91 | TM45BR = cnt; | ||
| 92 | tmp = TM45BR; | ||
| 93 | |||
| 94 | TM4MD = TM4MD_INIT_COUNTER; | ||
| 95 | tmp = TM4MD; | ||
| 96 | |||
| 97 | TM5MD = TM5MD_SRC_TM4CASCADE | TM5MD_INIT_COUNTER; | ||
| 98 | TM5MD = TM5MD_SRC_TM4CASCADE | TM5MD_COUNT_ENABLE; | ||
| 99 | tmp = TM5MD; | ||
| 100 | |||
| 101 | TM4MD = TM4MD_COUNT_ENABLE; | ||
| 102 | tmp = TM4MD; | ||
| 71 | } | 103 | } |
| 104 | #endif /* CONFIG_SMP&GENERIC_CLOCKEVENTS&!GENERIC_CLOCKEVENTS_BROADCAST */ | ||
| 72 | 105 | ||
| 73 | #endif /* !__ASSEMBLY__ */ | 106 | #endif /* !__ASSEMBLY__ */ |
| 74 | 107 | ||
| @@ -76,15 +109,16 @@ static inline void shutdown_jiffies_counter(void) | |||
| 76 | /* | 109 | /* |
| 77 | * timestamp counter specifications | 110 | * timestamp counter specifications |
| 78 | */ | 111 | */ |
| 79 | |||
| 80 | #define TMTSCBR_MAX 0xffffffff | 112 | #define TMTSCBR_MAX 0xffffffff |
| 113 | |||
| 114 | #ifndef __ASSEMBLY__ | ||
| 115 | |||
| 116 | /* Use 32-bit timestamp counter */ | ||
| 81 | #define TMTSCMD TMSMD | 117 | #define TMTSCMD TMSMD |
| 82 | #define TMTSCBR TMSBR | 118 | #define TMTSCBR TMSBR |
| 83 | #define TMTSCBC TMSBC | 119 | #define TMTSCBC TMSBC |
| 84 | #define TMTSCICR TMSICR | 120 | #define TMTSCICR TMSICR |
| 85 | 121 | ||
| 86 | #ifndef __ASSEMBLY__ | ||
| 87 | |||
| 88 | static inline void startup_timestamp_counter(void) | 122 | static inline void startup_timestamp_counter(void) |
| 89 | { | 123 | { |
| 90 | u32 sync; | 124 | u32 sync; |
| @@ -117,7 +151,7 @@ typedef unsigned long cycles_t; | |||
| 117 | 151 | ||
| 118 | static inline cycles_t read_timestamp_counter(void) | 152 | static inline cycles_t read_timestamp_counter(void) |
| 119 | { | 153 | { |
| 120 | return (cycles_t)TMTSCBC; | 154 | return (cycles_t)~TMTSCBC; |
| 121 | } | 155 | } |
| 122 | 156 | ||
| 123 | #endif /* !__ASSEMBLY__ */ | 157 | #endif /* !__ASSEMBLY__ */ |
