Commit 57be2b484a417bffae66359b9b89e7239480b729

Authored by Paul Mundt
1 parent 1ce7ddd5f4

sh: clockevent/clocksource/hrtimers/nohz TMU support.

This adds basic support for clockevents and clocksources,
presently only implemented for TMU-based systems (which
are the majority of SH-3 and SH-4 systems).

The old NO_IDLE_HZ implementation is also dropped completely,
the only users of this were on TMU-based systems anyways.

More work needs to be done to generalize the TMU handling,
in that the current implementation is rather tied to the
notion of TMU0 and TMU1 utilization.

Additionally, as more SH timers switch over to this scheme,
we'll be able to gut most of the remaining system timer
infrastructure that existed before.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>

Showing 5 changed files with 178 additions and 233 deletions Side-by-side Diff

... ... @@ -52,6 +52,9 @@
52 52 config GENERIC_TIME
53 53 def_bool n
54 54  
  55 +config GENERIC_CLOCKEVENTS
  56 + def_bool n
  57 +
55 58 config SYS_SUPPORTS_APM_EMULATION
56 59 bool
57 60  
58 61  
... ... @@ -436,11 +439,11 @@
436 439  
437 440 menu "Timer and clock configuration"
438 441  
439   -if !GENERIC_TIME
440   -
441 442 config SH_TMU
442 443 bool "TMU timer support"
443 444 depends on CPU_SH3 || CPU_SH4
  445 + select GENERIC_TIME
  446 + select GENERIC_CLOCKEVENTS
444 447 default y
445 448 help
446 449 This enables the use of the TMU as the system timer.
... ... @@ -459,8 +462,6 @@
459 462 help
460 463 This enables the use of the MTU2 as the system timer.
461 464  
462   -endif
463   -
464 465 config SH_TIMER_IRQ
465 466 int
466 467 default "28" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
... ... @@ -468,24 +469,6 @@
468 469 default "140" if CPU_SUBTYPE_SH7206
469 470 default "16"
470 471  
471   -config NO_IDLE_HZ
472   - bool "Dynamic tick timer"
473   - help
474   - Select this option if you want to disable continuous timer ticks
475   - and have them programmed to occur as required. This option saves
476   - power as the system can remain in idle state for longer.
477   -
478   - By default dynamic tick is disabled during the boot, and can be
479   - manually enabled with:
480   -
481   - echo 1 > /sys/devices/system/timer/timer0/dyn_tick
482   -
483   - Alternatively, if you want dynamic tick automatically enabled
484   - during boot, pass "dyntick=enable" via the kernel command string.
485   -
486   - Please note that dynamic tick may affect the accuracy of
487   - timekeeping on some platforms depending on the implementation.
488   -
489 472 config SH_PCLK_FREQ
490 473 int "Peripheral clock frequency (in Hz)"
491 474 default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
... ... @@ -508,6 +491,8 @@
508 491 depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206
509 492 help
510 493 MD2 - MD0 pin setting.
  494 +
  495 +source "kernel/time/Kconfig"
511 496  
512 497 endmenu
513 498  
arch/sh/kernel/process.c
... ... @@ -16,6 +16,7 @@
16 16 #include <linux/kallsyms.h>
17 17 #include <linux/kexec.h>
18 18 #include <linux/kdebug.h>
  19 +#include <linux/tick.h>
19 20 #include <asm/uaccess.h>
20 21 #include <asm/mmu_context.h>
21 22 #include <asm/pgalloc.h>
22 23  
... ... @@ -60,8 +61,10 @@
60 61 if (!idle)
61 62 idle = default_idle;
62 63  
  64 + tick_nohz_stop_sched_tick();
63 65 while (!need_resched())
64 66 idle();
  67 + tick_nohz_restart_sched_tick();
65 68  
66 69 preempt_enable_no_resched();
67 70 schedule();
arch/sh/kernel/time.c
... ... @@ -3,7 +3,7 @@
3 3 *
4 4 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
5 5 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
6   - * Copyright (C) 2002 - 2006 Paul Mundt
  6 + * Copyright (C) 2002 - 2007 Paul Mundt
7 7 * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
8 8 *
9 9 * Some code taken from i386 version.
... ... @@ -15,6 +15,7 @@
15 15 #include <linux/profile.h>
16 16 #include <linux/timex.h>
17 17 #include <linux/sched.h>
  18 +#include <linux/clockchips.h>
18 19 #include <asm/clock.h>
19 20 #include <asm/rtc.h>
20 21 #include <asm/timer.h>
... ... @@ -38,6 +39,14 @@
38 39 return 0;
39 40 }
40 41  
  42 +/*
  43 + * Null high precision timer functions for systems lacking one.
  44 + */
  45 +static cycle_t null_hpt_read(void)
  46 +{
  47 + return 0;
  48 +}
  49 +
41 50 void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
42 51 int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
43 52  
... ... @@ -101,6 +110,7 @@
101 110 EXPORT_SYMBOL(do_settimeofday);
102 111 #endif /* !CONFIG_GENERIC_TIME */
103 112  
  113 +#ifndef CONFIG_GENERIC_CLOCKEVENTS
104 114 /* last time the RTC clock got updated */
105 115 static long last_rtc_update;
106 116  
... ... @@ -138,6 +148,7 @@
138 148 last_rtc_update = xtime.tv_sec - 600;
139 149 }
140 150 }
  151 +#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
141 152  
142 153 #ifdef CONFIG_PM
143 154 int timer_suspend(struct sys_device *dev, pm_message_t state)
144 155  
145 156  
146 157  
147 158  
148 159  
149 160  
150 161  
151 162  
152 163  
153 164  
154 165  
155 166  
156 167  
157 168  
158 169  
159 170  
160 171  
161 172  
162 173  
... ... @@ -168,136 +179,58 @@
168 179 .resume = timer_resume,
169 180 };
170 181  
171   -#ifdef CONFIG_NO_IDLE_HZ
172   -static int timer_dyn_tick_enable(void)
  182 +static int __init timer_init_sysfs(void)
173 183 {
174   - struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
175   - unsigned long flags;
176   - int ret = -ENODEV;
  184 + int ret = sysdev_class_register(&timer_sysclass);
  185 + if (ret != 0)
  186 + return ret;
177 187  
178   - if (dyn_tick) {
179   - spin_lock_irqsave(&dyn_tick->lock, flags);
180   - ret = 0;
181   - if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
182   - ret = dyn_tick->enable();
183   -
184   - if (ret == 0)
185   - dyn_tick->state |= DYN_TICK_ENABLED;
186   - }
187   - spin_unlock_irqrestore(&dyn_tick->lock, flags);
188   - }
189   -
190   - return ret;
  188 + sys_timer->dev.cls = &timer_sysclass;
  189 + return sysdev_register(&sys_timer->dev);
191 190 }
  191 +device_initcall(timer_init_sysfs);
192 192  
193   -static int timer_dyn_tick_disable(void)
194   -{
195   - struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
196   - unsigned long flags;
197   - int ret = -ENODEV;
  193 +void (*board_time_init)(void);
198 194  
199   - if (dyn_tick) {
200   - spin_lock_irqsave(&dyn_tick->lock, flags);
201   - ret = 0;
202   - if (dyn_tick->state & DYN_TICK_ENABLED) {
203   - ret = dyn_tick->disable();
204   -
205   - if (ret == 0)
206   - dyn_tick->state &= ~DYN_TICK_ENABLED;
207   - }
208   - spin_unlock_irqrestore(&dyn_tick->lock, flags);
209   - }
210   -
211   - return ret;
212   -}
213   -
214 195 /*
215   - * Reprogram the system timer for at least the calculated time interval.
216   - * This function should be called from the idle thread with IRQs disabled,
217   - * immediately before sleeping.
  196 + * Shamelessly based on the MIPS and Sparc64 work.
218 197 */
219   -void timer_dyn_reprogram(void)
220   -{
221   - struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
222   - unsigned long next, seq, flags;
  198 +static unsigned long timer_ticks_per_nsec_quotient __read_mostly;
  199 +unsigned long sh_hpt_frequency = 0;
223 200  
224   - if (!dyn_tick)
225   - return;
  201 +#define NSEC_PER_CYC_SHIFT 10
226 202  
227   - spin_lock_irqsave(&dyn_tick->lock, flags);
228   - if (dyn_tick->state & DYN_TICK_ENABLED) {
229   - next = next_timer_interrupt();
230   - do {
231   - seq = read_seqbegin(&xtime_lock);
232   - dyn_tick->reprogram(next - jiffies);
233   - } while (read_seqretry(&xtime_lock, seq));
234   - }
235   - spin_unlock_irqrestore(&dyn_tick->lock, flags);
236   -}
  203 +struct clocksource clocksource_sh = {
  204 + .name = "SuperH",
  205 + .rating = 200,
  206 + .mask = CLOCKSOURCE_MASK(32),
  207 + .read = null_hpt_read,
  208 + .shift = 16,
  209 + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  210 +};
237 211  
238   -static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
  212 +static void __init init_sh_clocksource(void)
239 213 {
240   - return sprintf(buf, "%i\n",
241   - (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
242   -}
  214 + if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read)
  215 + return;
243 216  
244   -static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
245   - size_t count)
246   -{
247   - unsigned int enable = simple_strtoul(buf, NULL, 2);
  217 + clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency,
  218 + clocksource_sh.shift);
248 219  
249   - if (enable)
250   - timer_dyn_tick_enable();
251   - else
252   - timer_dyn_tick_disable();
  220 + timer_ticks_per_nsec_quotient =
  221 + clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT);
253 222  
254   - return count;
  223 + clocksource_register(&clocksource_sh);
255 224 }
256   -static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
257 225  
258   -/*
259   - * dyntick=enable|disable
260   - */
261   -static char dyntick_str[4] __initdata = "";
262   -
263   -static int __init dyntick_setup(char *str)
  226 +#ifdef CONFIG_GENERIC_TIME
  227 +unsigned long long sched_clock(void)
264 228 {
265   - if (str)
266   - strlcpy(dyntick_str, str, sizeof(dyntick_str));
267   - return 1;
  229 + unsigned long long ticks = clocksource_sh.read();
  230 + return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT;
268 231 }
269   -
270   -__setup("dyntick=", dyntick_setup);
271 232 #endif
272 233  
273   -static int __init timer_init_sysfs(void)
274   -{
275   - int ret = sysdev_class_register(&timer_sysclass);
276   - if (ret != 0)
277   - return ret;
278   -
279   - sys_timer->dev.cls = &timer_sysclass;
280   - ret = sysdev_register(&sys_timer->dev);
281   -
282   -#ifdef CONFIG_NO_IDLE_HZ
283   - if (ret == 0 && sys_timer->dyn_tick) {
284   - ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick);
285   -
286   - /*
287   - * Turn on dynamic tick after calibrate delay
288   - * for correct bogomips
289   - */
290   - if (ret == 0 && dyntick_str[0] == 'e')
291   - ret = timer_dyn_tick_enable();
292   - }
293   -#endif
294   -
295   - return ret;
296   -}
297   -device_initcall(timer_init_sysfs);
298   -
299   -void (*board_time_init)(void);
300   -
301 234 void __init time_init(void)
302 235 {
303 236 if (board_time_init)
... ... @@ -316,10 +249,15 @@
316 249 sys_timer = get_sys_timer();
317 250 printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
318 251  
319   -#ifdef CONFIG_NO_IDLE_HZ
320   - if (sys_timer->dyn_tick)
321   - spin_lock_init(&sys_timer->dyn_tick->lock);
322   -#endif
  252 + if (sys_timer->ops->read)
  253 + clocksource_sh.read = sys_timer->ops->read;
  254 +
  255 + init_sh_clocksource();
  256 +
  257 + if (sh_hpt_frequency)
  258 + printk("Using %lu.%03lu MHz high precision timer.\n",
  259 + ((sh_hpt_frequency + 500) / 1000) / 1000,
  260 + ((sh_hpt_frequency + 500) / 1000) % 1000);
323 261  
324 262 #if defined(CONFIG_SH_KGDB)
325 263 /*
arch/sh/kernel/timers/timer-tmu.c
1 1 /*
2 2 * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support
3 3 *
4   - * Copyright (C) 2005 Paul Mundt
  4 + * Copyright (C) 2005 - 2007 Paul Mundt
5 5 *
6 6 * TMU handling code hacked out of arch/sh/kernel/time.c
7 7 *
... ... @@ -18,6 +18,7 @@
18 18 #include <linux/kernel.h>
19 19 #include <linux/interrupt.h>
20 20 #include <linux/seqlock.h>
  21 +#include <linux/clockchips.h>
21 22 #include <asm/timer.h>
22 23 #include <asm/rtc.h>
23 24 #include <asm/io.h>
24 25  
25 26  
26 27  
27 28  
28 29  
29 30  
30 31  
31 32  
32 33  
33 34  
34 35  
35 36  
... ... @@ -25,56 +26,75 @@
25 26 #include <asm/clock.h>
26 27  
27 28 #define TMU_TOCR_INIT 0x00
28   -#define TMU0_TCR_INIT 0x0020
29   -#define TMU_TSTR_INIT 1
  29 +#define TMU_TCR_INIT 0x0020
30 30  
31   -#define TMU0_TCR_CALIB 0x0000
  31 +static int tmu_timer_start(void)
  32 +{
  33 + ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR);
  34 + return 0;
  35 +}
32 36  
33   -static unsigned long tmu_timer_get_offset(void)
  37 +static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload)
34 38 {
35   - int count;
36   - static int count_p = 0x7fffffff; /* for the first call after boot */
37   - static unsigned long jiffies_p = 0;
  39 + ctrl_outl(interval, TMU0_TCNT);
38 40  
39 41 /*
40   - * cache volatile jiffies temporarily; we have IRQs turned off.
  42 + * TCNT reloads from TCOR on underflow, clear it if we don't
  43 + * intend to auto-reload
41 44 */
42   - unsigned long jiffies_t;
  45 + if (reload)
  46 + ctrl_outl(interval, TMU0_TCOR);
  47 + else
  48 + ctrl_outl(0, TMU0_TCOR);
43 49  
44   - /* timer count may underflow right here */
45   - count = ctrl_inl(TMU0_TCNT); /* read the latched count */
  50 + tmu_timer_start();
  51 +}
46 52  
47   - jiffies_t = jiffies;
  53 +static int tmu_timer_stop(void)
  54 +{
  55 + ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR);
  56 + return 0;
  57 +}
48 58  
49   - /*
50   - * avoiding timer inconsistencies (they are rare, but they happen)...
51   - * there is one kind of problem that must be avoided here:
52   - * 1. the timer counter underflows
53   - */
  59 +static cycle_t tmu_timer_read(void)
  60 +{
  61 + return ~ctrl_inl(TMU1_TCNT);
  62 +}
54 63  
55   - if (jiffies_t == jiffies_p) {
56   - if (count > count_p) {
57   - /* the nutcase */
58   - if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
59   - count -= LATCH;
60   - } else {
61   - printk("%s (): hardware timer problem?\n",
62   - __FUNCTION__);
63   - }
64   - }
65   - } else
66   - jiffies_p = jiffies_t;
  64 +static int tmu_set_next_event(unsigned long cycles,
  65 + struct clock_event_device *evt)
  66 +{
  67 + tmu0_timer_set_interval(cycles, 1);
  68 + return 0;
  69 +}
67 70  
68   - count_p = count;
69   -
70   - count = ((LATCH-1) - count) * TICK_SIZE;
71   - count = (count + LATCH/2) / LATCH;
72   -
73   - return count;
  71 +static void tmu_set_mode(enum clock_event_mode mode,
  72 + struct clock_event_device *evt)
  73 +{
  74 + switch (mode) {
  75 + case CLOCK_EVT_MODE_PERIODIC:
  76 + ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR);
  77 + break;
  78 + case CLOCK_EVT_MODE_ONESHOT:
  79 + ctrl_outl(0, TMU0_TCOR);
  80 + break;
  81 + case CLOCK_EVT_MODE_UNUSED:
  82 + case CLOCK_EVT_MODE_SHUTDOWN:
  83 + break;
  84 + }
74 85 }
75 86  
  87 +static struct clock_event_device tmu0_clockevent = {
  88 + .name = "tmu0",
  89 + .shift = 32,
  90 + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
  91 + .set_mode = tmu_set_mode,
  92 + .set_next_event = tmu_set_next_event,
  93 +};
  94 +
76 95 static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
77 96 {
  97 + struct clock_event_device *evt = &tmu0_clockevent;
78 98 unsigned long timer_status;
79 99  
80 100 /* Clear UNF bit */
81 101  
82 102  
83 103  
84 104  
85 105  
86 106  
87 107  
88 108  
89 109  
90 110  
91 111  
92 112  
93 113  
94 114  
95 115  
96 116  
... ... @@ -82,72 +102,76 @@
82 102 timer_status &= ~0x100;
83 103 ctrl_outw(timer_status, TMU0_TCR);
84 104  
85   - /*
86   - * Here we are in the timer irq handler. We just have irqs locally
87   - * disabled but we don't know if the timer_bh is running on the other
88   - * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
89   - * the irq version of write_lock because as just said we have irq
90   - * locally disabled. -arca
91   - */
92   - write_seqlock(&xtime_lock);
93   - handle_timer_tick();
94   - write_sequnlock(&xtime_lock);
  105 + evt->event_handler(evt);
95 106  
96 107 return IRQ_HANDLED;
97 108 }
98 109  
99   -static struct irqaction tmu_irq = {
100   - .name = "timer",
  110 +static struct irqaction tmu0_irq = {
  111 + .name = "periodic timer",
101 112 .handler = tmu_timer_interrupt,
102 113 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
103 114 .mask = CPU_MASK_NONE,
104 115 };
105 116  
106   -static void tmu_clk_init(struct clk *clk)
  117 +static void tmu0_clk_init(struct clk *clk)
107 118 {
108   - u8 divisor = TMU0_TCR_INIT & 0x7;
109   - ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
  119 + u8 divisor = TMU_TCR_INIT & 0x7;
  120 + ctrl_outw(TMU_TCR_INIT, TMU0_TCR);
110 121 clk->rate = clk->parent->rate / (4 << (divisor << 1));
111 122 }
112 123  
113   -static void tmu_clk_recalc(struct clk *clk)
  124 +static void tmu0_clk_recalc(struct clk *clk)
114 125 {
115 126 u8 divisor = ctrl_inw(TMU0_TCR) & 0x7;
116 127 clk->rate = clk->parent->rate / (4 << (divisor << 1));
117 128 }
118 129  
119   -static struct clk_ops tmu_clk_ops = {
120   - .init = tmu_clk_init,
121   - .recalc = tmu_clk_recalc,
  130 +static struct clk_ops tmu0_clk_ops = {
  131 + .init = tmu0_clk_init,
  132 + .recalc = tmu0_clk_recalc,
122 133 };
123 134  
124 135 static struct clk tmu0_clk = {
125 136 .name = "tmu0_clk",
126   - .ops = &tmu_clk_ops,
  137 + .ops = &tmu0_clk_ops,
127 138 };
128 139  
129   -static int tmu_timer_start(void)
  140 +static void tmu1_clk_init(struct clk *clk)
130 141 {
131   - ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
132   - return 0;
  142 + u8 divisor = TMU_TCR_INIT & 0x7;
  143 + ctrl_outw(divisor, TMU1_TCR);
  144 + clk->rate = clk->parent->rate / (4 << (divisor << 1));
133 145 }
134 146  
135   -static int tmu_timer_stop(void)
  147 +static void tmu1_clk_recalc(struct clk *clk)
136 148 {
137   - ctrl_outb(0, TMU_TSTR);
138   - return 0;
  149 + u8 divisor = ctrl_inw(TMU1_TCR) & 0x7;
  150 + clk->rate = clk->parent->rate / (4 << (divisor << 1));
139 151 }
140 152  
  153 +static struct clk_ops tmu1_clk_ops = {
  154 + .init = tmu1_clk_init,
  155 + .recalc = tmu1_clk_recalc,
  156 +};
  157 +
  158 +static struct clk tmu1_clk = {
  159 + .name = "tmu1_clk",
  160 + .ops = &tmu1_clk_ops,
  161 +};
  162 +
141 163 static int tmu_timer_init(void)
142 164 {
143 165 unsigned long interval;
  166 + unsigned long frequency;
144 167  
145   - setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq);
  168 + setup_irq(CONFIG_SH_TIMER_IRQ, &tmu0_irq);
146 169  
147 170 tmu0_clk.parent = clk_get(NULL, "module_clk");
  171 + tmu1_clk.parent = clk_get(NULL, "module_clk");
148 172  
149   - /* Start TMU0 */
150 173 tmu_timer_stop();
  174 +
151 175 #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
152 176 !defined(CONFIG_CPU_SUBTYPE_SH7760) && \
153 177 !defined(CONFIG_CPU_SUBTYPE_SH7785)
154 178  
155 179  
156 180  
157 181  
158 182  
... ... @@ -155,16 +179,30 @@
155 179 #endif
156 180  
157 181 clk_register(&tmu0_clk);
  182 + clk_register(&tmu1_clk);
158 183 clk_enable(&tmu0_clk);
  184 + clk_enable(&tmu1_clk);
159 185  
160   - interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ;
161   - printk(KERN_INFO "Interval = %ld\n", interval);
  186 + frequency = clk_get_rate(&tmu0_clk);
  187 + interval = (frequency + HZ / 2) / HZ;
162 188  
163   - ctrl_outl(interval, TMU0_TCOR);
164   - ctrl_outl(interval, TMU0_TCNT);
  189 + sh_hpt_frequency = clk_get_rate(&tmu1_clk);
  190 + ctrl_outl(~0, TMU1_TCNT);
  191 + ctrl_outl(~0, TMU1_TCOR);
165 192  
166   - tmu_timer_start();
  193 + tmu0_timer_set_interval(interval, 1);
167 194  
  195 + tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC,
  196 + tmu0_clockevent.shift);
  197 + tmu0_clockevent.max_delta_ns =
  198 + clockevent_delta2ns(-1, &tmu0_clockevent);
  199 + tmu0_clockevent.min_delta_ns =
  200 + clockevent_delta2ns(1, &tmu0_clockevent);
  201 +
  202 + tmu0_clockevent.cpumask = cpumask_of_cpu(0);
  203 +
  204 + clockevents_register_device(&tmu0_clockevent);
  205 +
168 206 return 0;
169 207 }
170 208  
... ... @@ -172,9 +210,7 @@
172 210 .init = tmu_timer_init,
173 211 .start = tmu_timer_start,
174 212 .stop = tmu_timer_stop,
175   -#ifndef CONFIG_GENERIC_TIME
176   - .get_offset = tmu_timer_get_offset,
177   -#endif
  213 + .read = tmu_timer_read,
178 214 };
179 215  
180 216 struct sys_timer tmu_timer = {
include/asm-sh/timer.h
... ... @@ -2,12 +2,14 @@
2 2 #define __ASM_SH_TIMER_H
3 3  
4 4 #include <linux/sysdev.h>
  5 +#include <linux/clocksource.h>
5 6 #include <asm/cpu/timer.h>
6 7  
7 8 struct sys_timer_ops {
8 9 int (*init)(void);
9 10 int (*start)(void);
10 11 int (*stop)(void);
  12 + cycle_t (*read)(void);
11 13 #ifndef CONFIG_GENERIC_TIME
12 14 unsigned long (*get_offset)(void);
13 15 #endif
14 16  
... ... @@ -18,29 +20,8 @@
18 20  
19 21 struct sys_device dev;
20 22 struct sys_timer_ops *ops;
21   -
22   -#ifdef CONFIG_NO_IDLE_HZ
23   - struct dyn_tick_timer *dyn_tick;
24   -#endif
25 23 };
26 24  
27   -#ifdef CONFIG_NO_IDLE_HZ
28   -#define DYN_TICK_ENABLED (1 << 1)
29   -
30   -struct dyn_tick_timer {
31   - spinlock_t lock;
32   - unsigned int state; /* Current state */
33   - int (*enable)(void); /* Enables dynamic tick */
34   - int (*disable)(void); /* Disables dynamic tick */
35   - void (*reprogram)(unsigned long); /* Reprograms the timer */
36   - int (*handler)(int, void *);
37   -};
38   -
39   -void timer_dyn_reprogram(void);
40   -#else
41   -#define timer_dyn_reprogram() do { } while (0)
42   -#endif
43   -
44 25 #define TICK_SIZE (tick_nsec / 1000)
45 26  
46 27 extern struct sys_timer tmu_timer, cmt_timer, mtu2_timer;
... ... @@ -58,6 +39,8 @@
58 39  
59 40 /* arch/sh/kernel/time.c */
60 41 void handle_timer_tick(void);
  42 +extern unsigned long sh_hpt_frequency;
  43 +extern struct clocksource clocksource_sh;
61 44  
62 45 #endif /* __ASM_SH_TIMER_H */