diff options
author | Greg Ungerer <gerg@uclinux.org> | 2014-08-18 21:39:09 -0400 |
---|---|---|
committer | Greg Ungerer <gerg@uclinux.org> | 2014-09-28 19:18:34 -0400 |
commit | f86b9e03837beafb4b48d53a76ee4b88559226de (patch) | |
tree | 53a673c3719aec83c6c55c265ed6e6433d6550ca /arch/m68k/coldfire/timers.c | |
parent | fe82dcec644244676d55a1384c958d5f67979adb (diff) |
m68k: move coldfire platform code
Move the m68k ColdFire platform support code directory to be with the
existing m68k platforms. Although the ColdFire is not a platform as such,
we have always kept all its support together. No reason to change that
as this time.
Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'arch/m68k/coldfire/timers.c')
-rw-r--r-- | arch/m68k/coldfire/timers.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/arch/m68k/coldfire/timers.c b/arch/m68k/coldfire/timers.c new file mode 100644 index 000000000000..cd496a20fcc7 --- /dev/null +++ b/arch/m68k/coldfire/timers.c | |||
@@ -0,0 +1,195 @@ | |||
1 | /***************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * timers.c -- generic ColdFire hardware timer support. | ||
5 | * | ||
6 | * Copyright (C) 1999-2008, Greg Ungerer <gerg@snapgear.com> | ||
7 | */ | ||
8 | |||
9 | /***************************************************************************/ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/profile.h> | ||
17 | #include <linux/clocksource.h> | ||
18 | #include <asm/io.h> | ||
19 | #include <asm/traps.h> | ||
20 | #include <asm/machdep.h> | ||
21 | #include <asm/coldfire.h> | ||
22 | #include <asm/mcftimer.h> | ||
23 | #include <asm/mcfsim.h> | ||
24 | |||
25 | /***************************************************************************/ | ||
26 | |||
27 | /* | ||
28 | * By default use timer1 as the system clock timer. | ||
29 | */ | ||
30 | #define FREQ (MCF_BUSCLK / 16) | ||
31 | #define TA(a) (MCFTIMER_BASE1 + (a)) | ||
32 | |||
33 | /* | ||
34 | * These provide the underlying interrupt vector support. | ||
35 | * Unfortunately it is a little different on each ColdFire. | ||
36 | */ | ||
37 | void coldfire_profile_init(void); | ||
38 | |||
39 | #if defined(CONFIG_M53xx) || defined(CONFIG_M5441x) | ||
40 | #define __raw_readtrr __raw_readl | ||
41 | #define __raw_writetrr __raw_writel | ||
42 | #else | ||
43 | #define __raw_readtrr __raw_readw | ||
44 | #define __raw_writetrr __raw_writew | ||
45 | #endif | ||
46 | |||
47 | static u32 mcftmr_cycles_per_jiffy; | ||
48 | static u32 mcftmr_cnt; | ||
49 | |||
50 | static irq_handler_t timer_interrupt; | ||
51 | |||
52 | /***************************************************************************/ | ||
53 | |||
54 | static void init_timer_irq(void) | ||
55 | { | ||
56 | #ifdef MCFSIM_ICR_AUTOVEC | ||
57 | /* Timer1 is always used as system timer */ | ||
58 | writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3, | ||
59 | MCFSIM_TIMER1ICR); | ||
60 | mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1); | ||
61 | |||
62 | #ifdef CONFIG_HIGHPROFILE | ||
63 | /* Timer2 is to be used as a high speed profile timer */ | ||
64 | writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3, | ||
65 | MCFSIM_TIMER2ICR); | ||
66 | mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2); | ||
67 | #endif | ||
68 | #endif /* MCFSIM_ICR_AUTOVEC */ | ||
69 | } | ||
70 | |||
71 | /***************************************************************************/ | ||
72 | |||
73 | static irqreturn_t mcftmr_tick(int irq, void *dummy) | ||
74 | { | ||
75 | /* Reset the ColdFire timer */ | ||
76 | __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, TA(MCFTIMER_TER)); | ||
77 | |||
78 | mcftmr_cnt += mcftmr_cycles_per_jiffy; | ||
79 | return timer_interrupt(irq, dummy); | ||
80 | } | ||
81 | |||
82 | /***************************************************************************/ | ||
83 | |||
84 | static struct irqaction mcftmr_timer_irq = { | ||
85 | .name = "timer", | ||
86 | .flags = IRQF_TIMER, | ||
87 | .handler = mcftmr_tick, | ||
88 | }; | ||
89 | |||
90 | /***************************************************************************/ | ||
91 | |||
92 | static cycle_t mcftmr_read_clk(struct clocksource *cs) | ||
93 | { | ||
94 | unsigned long flags; | ||
95 | u32 cycles; | ||
96 | u16 tcn; | ||
97 | |||
98 | local_irq_save(flags); | ||
99 | tcn = __raw_readw(TA(MCFTIMER_TCN)); | ||
100 | cycles = mcftmr_cnt; | ||
101 | local_irq_restore(flags); | ||
102 | |||
103 | return cycles + tcn; | ||
104 | } | ||
105 | |||
106 | /***************************************************************************/ | ||
107 | |||
108 | static struct clocksource mcftmr_clk = { | ||
109 | .name = "tmr", | ||
110 | .rating = 250, | ||
111 | .read = mcftmr_read_clk, | ||
112 | .mask = CLOCKSOURCE_MASK(32), | ||
113 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
114 | }; | ||
115 | |||
116 | /***************************************************************************/ | ||
117 | |||
118 | void hw_timer_init(irq_handler_t handler) | ||
119 | { | ||
120 | __raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR)); | ||
121 | mcftmr_cycles_per_jiffy = FREQ / HZ; | ||
122 | /* | ||
123 | * The coldfire timer runs from 0 to TRR included, then 0 | ||
124 | * again and so on. It counts thus actually TRR + 1 steps | ||
125 | * for 1 tick, not TRR. So if you want n cycles, | ||
126 | * initialize TRR with n - 1. | ||
127 | */ | ||
128 | __raw_writetrr(mcftmr_cycles_per_jiffy - 1, TA(MCFTIMER_TRR)); | ||
129 | __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | | ||
130 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR)); | ||
131 | |||
132 | clocksource_register_hz(&mcftmr_clk, FREQ); | ||
133 | |||
134 | timer_interrupt = handler; | ||
135 | init_timer_irq(); | ||
136 | setup_irq(MCF_IRQ_TIMER, &mcftmr_timer_irq); | ||
137 | |||
138 | #ifdef CONFIG_HIGHPROFILE | ||
139 | coldfire_profile_init(); | ||
140 | #endif | ||
141 | } | ||
142 | |||
143 | /***************************************************************************/ | ||
144 | #ifdef CONFIG_HIGHPROFILE | ||
145 | /***************************************************************************/ | ||
146 | |||
147 | /* | ||
148 | * By default use timer2 as the profiler clock timer. | ||
149 | */ | ||
150 | #define PA(a) (MCFTIMER_BASE2 + (a)) | ||
151 | |||
152 | /* | ||
153 | * Choose a reasonably fast profile timer. Make it an odd value to | ||
154 | * try and get good coverage of kernel operations. | ||
155 | */ | ||
156 | #define PROFILEHZ 1013 | ||
157 | |||
158 | /* | ||
159 | * Use the other timer to provide high accuracy profiling info. | ||
160 | */ | ||
161 | irqreturn_t coldfire_profile_tick(int irq, void *dummy) | ||
162 | { | ||
163 | /* Reset ColdFire timer2 */ | ||
164 | __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER)); | ||
165 | if (current->pid) | ||
166 | profile_tick(CPU_PROFILING); | ||
167 | return IRQ_HANDLED; | ||
168 | } | ||
169 | |||
170 | /***************************************************************************/ | ||
171 | |||
172 | static struct irqaction coldfire_profile_irq = { | ||
173 | .name = "profile timer", | ||
174 | .flags = IRQF_TIMER, | ||
175 | .handler = coldfire_profile_tick, | ||
176 | }; | ||
177 | |||
178 | void coldfire_profile_init(void) | ||
179 | { | ||
180 | printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", | ||
181 | PROFILEHZ); | ||
182 | |||
183 | /* Set up TIMER 2 as high speed profile clock */ | ||
184 | __raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR)); | ||
185 | |||
186 | __raw_writetrr(((MCF_BUSCLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR)); | ||
187 | __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | | ||
188 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR)); | ||
189 | |||
190 | setup_irq(MCF_IRQ_PROFILER, &coldfire_profile_irq); | ||
191 | } | ||
192 | |||
193 | /***************************************************************************/ | ||
194 | #endif /* CONFIG_HIGHPROFILE */ | ||
195 | /***************************************************************************/ | ||