diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/m68knommu/platform/5307 |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/m68knommu/platform/5307')
-rw-r--r-- | arch/m68knommu/platform/5307/Makefile | 29 | ||||
-rw-r--r-- | arch/m68knommu/platform/5307/config.c | 148 | ||||
-rw-r--r-- | arch/m68knommu/platform/5307/entry.S | 268 | ||||
-rw-r--r-- | arch/m68knommu/platform/5307/head.S | 253 | ||||
-rw-r--r-- | arch/m68knommu/platform/5307/ints.c | 280 | ||||
-rw-r--r-- | arch/m68knommu/platform/5307/pit.c | 88 | ||||
-rw-r--r-- | arch/m68knommu/platform/5307/timers.c | 138 | ||||
-rw-r--r-- | arch/m68knommu/platform/5307/vectors.c | 95 |
8 files changed, 1299 insertions, 0 deletions
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile new file mode 100644 index 000000000000..84b6b70641e1 --- /dev/null +++ b/arch/m68knommu/platform/5307/Makefile | |||
@@ -0,0 +1,29 @@ | |||
1 | # | ||
2 | # Makefile for the m68knommu kernel. | ||
3 | # | ||
4 | |||
5 | # | ||
6 | # If you want to play with the HW breakpoints then you will | ||
7 | # need to add define this, which will give you a stack backtrace | ||
8 | # on the console port whenever a DBG interrupt occurs. You have to | ||
9 | # set up you HW breakpoints to trigger a DBG interrupt: | ||
10 | # | ||
11 | # EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT | ||
12 | # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT | ||
13 | # | ||
14 | |||
15 | ifdef CONFIG_FULLDEBUG | ||
16 | AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 | ||
17 | endif | ||
18 | |||
19 | obj-$(CONFIG_COLDFIRE) += entry.o vectors.o ints.o | ||
20 | obj-$(CONFIG_M5206) += timers.o | ||
21 | obj-$(CONFIG_M5206e) += timers.o | ||
22 | obj-$(CONFIG_M5249) += timers.o | ||
23 | obj-$(CONFIG_M527x) += pit.o | ||
24 | obj-$(CONFIG_M5272) += timers.o | ||
25 | obj-$(CONFIG_M5307) += config.o timers.o | ||
26 | obj-$(CONFIG_M528x) += pit.o | ||
27 | obj-$(CONFIG_M5407) += timers.o | ||
28 | |||
29 | extra-y := head.o | ||
diff --git a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c new file mode 100644 index 000000000000..7ed5782e9236 --- /dev/null +++ b/arch/m68knommu/platform/5307/config.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /***************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * linux/arch/m68knommu/platform/5307/config.c | ||
5 | * | ||
6 | * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) | ||
7 | * Copyright (C) 2000, Lineo (www.lineo.com) | ||
8 | */ | ||
9 | |||
10 | /***************************************************************************/ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/param.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <asm/irq.h> | ||
19 | #include <asm/dma.h> | ||
20 | #include <asm/traps.h> | ||
21 | #include <asm/machdep.h> | ||
22 | #include <asm/coldfire.h> | ||
23 | #include <asm/mcftimer.h> | ||
24 | #include <asm/mcfsim.h> | ||
25 | #include <asm/mcfdma.h> | ||
26 | #include <asm/mcfwdebug.h> | ||
27 | |||
28 | /***************************************************************************/ | ||
29 | |||
30 | void coldfire_tick(void); | ||
31 | void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); | ||
32 | unsigned long coldfire_timer_offset(void); | ||
33 | void coldfire_trap_init(void); | ||
34 | void coldfire_reset(void); | ||
35 | |||
36 | extern unsigned int mcf_timervector; | ||
37 | extern unsigned int mcf_profilevector; | ||
38 | extern unsigned int mcf_timerlevel; | ||
39 | |||
40 | /***************************************************************************/ | ||
41 | |||
42 | /* | ||
43 | * Some platforms need software versions of the GPIO data registers. | ||
44 | */ | ||
45 | unsigned short ppdata; | ||
46 | unsigned char ledbank = 0xff; | ||
47 | |||
48 | /***************************************************************************/ | ||
49 | |||
50 | /* | ||
51 | * DMA channel base address table. | ||
52 | */ | ||
53 | unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { | ||
54 | MCF_MBAR + MCFDMA_BASE0, | ||
55 | MCF_MBAR + MCFDMA_BASE1, | ||
56 | MCF_MBAR + MCFDMA_BASE2, | ||
57 | MCF_MBAR + MCFDMA_BASE3, | ||
58 | }; | ||
59 | |||
60 | unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; | ||
61 | |||
62 | /***************************************************************************/ | ||
63 | |||
64 | void mcf_autovector(unsigned int vec) | ||
65 | { | ||
66 | volatile unsigned char *mbar; | ||
67 | |||
68 | if ((vec >= 25) && (vec <= 31)) { | ||
69 | mbar = (volatile unsigned char *) MCF_MBAR; | ||
70 | vec = 0x1 << (vec - 24); | ||
71 | *(mbar + MCFSIM_AVR) |= vec; | ||
72 | mcf_setimr(mcf_getimr() & ~vec); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /***************************************************************************/ | ||
77 | |||
78 | void mcf_settimericr(unsigned int timer, unsigned int level) | ||
79 | { | ||
80 | volatile unsigned char *icrp; | ||
81 | unsigned int icr, imr; | ||
82 | |||
83 | if (timer <= 2) { | ||
84 | switch (timer) { | ||
85 | case 2: icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break; | ||
86 | default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break; | ||
87 | } | ||
88 | |||
89 | icrp = (volatile unsigned char *) (MCF_MBAR + icr); | ||
90 | *icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3; | ||
91 | mcf_setimr(mcf_getimr() & ~imr); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | /***************************************************************************/ | ||
96 | |||
97 | int mcf_timerirqpending(int timer) | ||
98 | { | ||
99 | unsigned int imr = 0; | ||
100 | |||
101 | switch (timer) { | ||
102 | case 1: imr = MCFSIM_IMR_TIMER1; break; | ||
103 | case 2: imr = MCFSIM_IMR_TIMER2; break; | ||
104 | default: break; | ||
105 | } | ||
106 | return (mcf_getipr() & imr); | ||
107 | } | ||
108 | |||
109 | /***************************************************************************/ | ||
110 | |||
111 | void config_BSP(char *commandp, int size) | ||
112 | { | ||
113 | mcf_setimr(MCFSIM_IMR_MASKALL); | ||
114 | |||
115 | #if defined(CONFIG_BOOTPARAM) | ||
116 | strncpy(commandp, CONFIG_BOOTPARAM_STRING, size); | ||
117 | commandp[size-1] = 0; | ||
118 | #elif defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ | ||
119 | defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \ | ||
120 | defined(CONFIG_CLEOPATRA) | ||
121 | /* Copy command line from FLASH to local buffer... */ | ||
122 | memcpy(commandp, (char *) 0xf0004000, size); | ||
123 | commandp[size-1] = 0; | ||
124 | /* Different timer setup - to prevent device clash */ | ||
125 | mcf_timervector = 30; | ||
126 | mcf_profilevector = 31; | ||
127 | mcf_timerlevel = 6; | ||
128 | #else | ||
129 | memset(commandp, 0, size); | ||
130 | #endif | ||
131 | |||
132 | mach_sched_init = coldfire_timer_init; | ||
133 | mach_tick = coldfire_tick; | ||
134 | mach_gettimeoffset = coldfire_timer_offset; | ||
135 | mach_trap_init = coldfire_trap_init; | ||
136 | mach_reset = coldfire_reset; | ||
137 | |||
138 | #ifdef MCF_BDM_DISABLE | ||
139 | /* | ||
140 | * Disable the BDM clocking. This also turns off most of the rest of | ||
141 | * the BDM device. This is good for EMC reasons. This option is not | ||
142 | * incompatible with the memory protection option. | ||
143 | */ | ||
144 | wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK); | ||
145 | #endif | ||
146 | } | ||
147 | |||
148 | /***************************************************************************/ | ||
diff --git a/arch/m68knommu/platform/5307/entry.S b/arch/m68knommu/platform/5307/entry.S new file mode 100644 index 000000000000..89b180d4ed6a --- /dev/null +++ b/arch/m68knommu/platform/5307/entry.S | |||
@@ -0,0 +1,268 @@ | |||
1 | /* | ||
2 | * linux/arch/m68knommu/platform/5307/entry.S | ||
3 | * | ||
4 | * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) | ||
5 | * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, | ||
6 | * Kenneth Albanowski <kjahds@kjahds.com>, | ||
7 | * Copyright (C) 2000 Lineo Inc. (www.lineo.com) | ||
8 | * Copyright (C) 2004 Macq Electronique SA. (www.macqel.com) | ||
9 | * | ||
10 | * Based on: | ||
11 | * | ||
12 | * linux/arch/m68k/kernel/entry.S | ||
13 | * | ||
14 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
15 | * | ||
16 | * This file is subject to the terms and conditions of the GNU General Public | ||
17 | * License. See the file README.legal in the main directory of this archive | ||
18 | * for more details. | ||
19 | * | ||
20 | * Linux/m68k support by Hamish Macdonald | ||
21 | * | ||
22 | * 68060 fixes by Jesper Skov | ||
23 | * ColdFire support by Greg Ungerer (gerg@snapgear.com) | ||
24 | * 5307 fixes by David W. Miller | ||
25 | * linux 2.4 support David McCullough <davidm@snapgear.com> | ||
26 | * Bug, speed and maintainability fixes by Philippe De Muyter <phdm@macqel.be> | ||
27 | */ | ||
28 | |||
29 | #include <linux/config.h> | ||
30 | #include <linux/sys.h> | ||
31 | #include <linux/linkage.h> | ||
32 | #include <asm/unistd.h> | ||
33 | #include <asm/thread_info.h> | ||
34 | #include <asm/errno.h> | ||
35 | #include <asm/setup.h> | ||
36 | #include <asm/segment.h> | ||
37 | #include <asm/asm-offsets.h> | ||
38 | #include <asm/entry.h> | ||
39 | |||
40 | .bss | ||
41 | |||
42 | sw_ksp: | ||
43 | .long 0 | ||
44 | |||
45 | sw_usp: | ||
46 | .long 0 | ||
47 | |||
48 | .text | ||
49 | |||
50 | .globl system_call | ||
51 | .globl resume | ||
52 | .globl ret_from_exception | ||
53 | .globl ret_from_signal | ||
54 | .globl sys_call_table | ||
55 | .globl ret_from_interrupt | ||
56 | .globl inthandler | ||
57 | .globl fasthandler | ||
58 | |||
59 | ENTRY(system_call) | ||
60 | SAVE_ALL | ||
61 | move #0x2000,%sr /* enable intrs again */ | ||
62 | |||
63 | movel #-LENOSYS,%d2 | ||
64 | movel %d2,PT_D0(%sp) /* default return value in d0 */ | ||
65 | /* original D0 is in orig_d0 */ | ||
66 | movel %d0,%d2 | ||
67 | |||
68 | /* save top of frame */ | ||
69 | pea %sp@ | ||
70 | jbsr set_esp0 | ||
71 | addql #4,%sp | ||
72 | |||
73 | cmpl #NR_syscalls,%d2 | ||
74 | jcc ret_from_exception | ||
75 | lea sys_call_table,%a0 | ||
76 | lsll #2,%d2 /* movel %a0@(%d2:l:4),%d3 */ | ||
77 | movel %a0@(%d2),%d3 | ||
78 | jeq ret_from_exception | ||
79 | lsrl #2,%d2 | ||
80 | |||
81 | movel %sp,%d2 /* get thread_info pointer */ | ||
82 | andl #-THREAD_SIZE,%d2 /* at start of kernel stack */ | ||
83 | movel %d2,%a0 | ||
84 | btst #TIF_SYSCALL_TRACE,%a0@(TI_FLAGS) | ||
85 | bnes 1f | ||
86 | |||
87 | movel %d3,%a0 | ||
88 | jbsr %a0@ | ||
89 | movel %d0,%sp@(PT_D0) /* save the return value */ | ||
90 | jra ret_from_exception | ||
91 | 1: | ||
92 | subql #4,%sp | ||
93 | SAVE_SWITCH_STACK | ||
94 | jbsr syscall_trace | ||
95 | RESTORE_SWITCH_STACK | ||
96 | addql #4,%sp | ||
97 | movel %d3,%a0 | ||
98 | jbsr %a0@ | ||
99 | movel %d0,%sp@(PT_D0) /* save the return value */ | ||
100 | subql #4,%sp /* dummy return address */ | ||
101 | SAVE_SWITCH_STACK | ||
102 | jbsr syscall_trace | ||
103 | |||
104 | ret_from_signal: | ||
105 | RESTORE_SWITCH_STACK | ||
106 | addql #4,%sp | ||
107 | |||
108 | ret_from_exception: | ||
109 | btst #5,%sp@(PT_SR) /* check if returning to kernel */ | ||
110 | jeq Luser_return /* if so, skip resched, signals */ | ||
111 | |||
112 | Lkernel_return: | ||
113 | moveml %sp@,%d1-%d5/%a0-%a2 | ||
114 | lea %sp@(32),%sp /* space for 8 regs */ | ||
115 | movel %sp@+,%d0 | ||
116 | addql #4,%sp /* orig d0 */ | ||
117 | addl %sp@+,%sp /* stk adj */ | ||
118 | rte | ||
119 | |||
120 | Luser_return: | ||
121 | movel %sp,%d1 /* get thread_info pointer */ | ||
122 | andl #-THREAD_SIZE,%d1 /* at base of kernel stack */ | ||
123 | movel %d1,%a0 | ||
124 | movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */ | ||
125 | andl #_TIF_WORK_MASK,%d1 | ||
126 | jne Lwork_to_do /* still work to do */ | ||
127 | |||
128 | Lreturn: | ||
129 | move #0x2700,%sr /* disable intrs */ | ||
130 | movel sw_usp,%a0 /* get usp */ | ||
131 | movel %sp@(PT_PC),%a0@- /* copy exception program counter */ | ||
132 | movel %sp@(PT_FORMATVEC),%a0@-/* copy exception format/vector/sr */ | ||
133 | moveml %sp@,%d1-%d5/%a0-%a2 | ||
134 | lea %sp@(32),%sp /* space for 8 regs */ | ||
135 | movel %sp@+,%d0 | ||
136 | addql #4,%sp /* orig d0 */ | ||
137 | addl %sp@+,%sp /* stk adj */ | ||
138 | addql #8,%sp /* remove exception */ | ||
139 | movel %sp,sw_ksp /* save ksp */ | ||
140 | subql #8,sw_usp /* set exception */ | ||
141 | movel sw_usp,%sp /* restore usp */ | ||
142 | rte | ||
143 | |||
144 | Lwork_to_do: | ||
145 | movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */ | ||
146 | btst #TIF_NEED_RESCHED,%d1 | ||
147 | jne reschedule | ||
148 | |||
149 | /* GERG: do we need something here for TRACEing?? */ | ||
150 | |||
151 | Lsignal_return: | ||
152 | subql #4,%sp /* dummy return address */ | ||
153 | SAVE_SWITCH_STACK | ||
154 | pea %sp@(SWITCH_STACK_SIZE) | ||
155 | clrl %sp@- | ||
156 | jsr do_signal | ||
157 | addql #8,%sp | ||
158 | RESTORE_SWITCH_STACK | ||
159 | addql #4,%sp | ||
160 | jmp Lreturn | ||
161 | |||
162 | /* | ||
163 | * This is the generic interrupt handler (for all hardware interrupt | ||
164 | * sources). It figures out the vector number and calls the appropriate | ||
165 | * interrupt service routine directly. | ||
166 | */ | ||
167 | ENTRY(inthandler) | ||
168 | SAVE_ALL | ||
169 | moveq #-1,%d0 | ||
170 | movel %d0,%sp@(PT_ORIG_D0) | ||
171 | addql #1,local_irq_count | ||
172 | |||
173 | movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */ | ||
174 | andl #0x03fc,%d0 /* mask out vector only */ | ||
175 | |||
176 | leal per_cpu__kstat+STAT_IRQ,%a0 | ||
177 | addql #1,%a0@(%d0) | ||
178 | |||
179 | lsrl #2,%d0 /* calculate real vector # */ | ||
180 | movel %d0,%d1 /* calculate array offset */ | ||
181 | lsll #4,%d1 | ||
182 | lea irq_list,%a0 | ||
183 | addl %d1,%a0 /* pointer to array struct */ | ||
184 | |||
185 | movel %sp,%sp@- /* push regs arg onto stack */ | ||
186 | movel %a0@(8),%sp@- /* push devid arg */ | ||
187 | movel %d0,%sp@- /* push vector # on stack */ | ||
188 | |||
189 | movel %a0@,%a0 /* get function to call */ | ||
190 | jbsr %a0@ /* call vector handler */ | ||
191 | lea %sp@(12),%sp /* pop parameters off stack */ | ||
192 | |||
193 | bra ret_from_interrupt /* this was fallthrough */ | ||
194 | |||
195 | /* | ||
196 | * This is the fast interrupt handler (for certain hardware interrupt | ||
197 | * sources). Unlike the normal interrupt handler it just uses the | ||
198 | * current stack (doesn't care if it is user or kernel). It also | ||
199 | * doesn't bother doing the bottom half handlers. | ||
200 | */ | ||
201 | ENTRY(fasthandler) | ||
202 | SAVE_LOCAL | ||
203 | |||
204 | movew %sp@(PT_FORMATVEC),%d0 | ||
205 | andl #0x03fc,%d0 /* mask out vector only */ | ||
206 | |||
207 | leal per_cpu__kstat+STAT_IRQ,%a0 | ||
208 | addql #1,%a0@(%d0) | ||
209 | |||
210 | movel %sp,%sp@- /* push regs arg onto stack */ | ||
211 | clrl %sp@- /* push devid arg */ | ||
212 | lsrl #2,%d0 /* calculate real vector # */ | ||
213 | movel %d0,%sp@- /* push vector # on stack */ | ||
214 | |||
215 | lsll #4,%d0 /* adjust for array offset */ | ||
216 | lea irq_list,%a0 | ||
217 | movel %a0@(%d0),%a0 /* get function to call */ | ||
218 | jbsr %a0@ /* call vector handler */ | ||
219 | lea %sp@(12),%sp /* pop parameters off stack */ | ||
220 | |||
221 | RESTORE_LOCAL | ||
222 | |||
223 | ENTRY(ret_from_interrupt) | ||
224 | subql #1,local_irq_count | ||
225 | jeq 2f | ||
226 | 1: | ||
227 | RESTORE_ALL | ||
228 | 2: | ||
229 | moveb %sp@(PT_SR),%d0 | ||
230 | andl #0x7,%d0 | ||
231 | jhi 1b | ||
232 | |||
233 | /* check if we need to do software interrupts */ | ||
234 | movel irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0 | ||
235 | jeq ret_from_exception | ||
236 | |||
237 | pea ret_from_exception | ||
238 | jmp do_softirq | ||
239 | |||
240 | /* | ||
241 | * Beware - when entering resume, prev (the current task) is | ||
242 | * in a0, next (the new task) is in a1,so don't change these | ||
243 | * registers until their contents are no longer needed. | ||
244 | */ | ||
245 | ENTRY(resume) | ||
246 | movel %a0, %d1 /* get prev thread in d1 */ | ||
247 | |||
248 | movew %sr,%d0 /* save thread status reg */ | ||
249 | movew %d0,%a0@(TASK_THREAD+THREAD_SR) | ||
250 | |||
251 | oril #0x700,%d0 /* disable interrupts */ | ||
252 | move %d0,%sr | ||
253 | |||
254 | movel sw_usp,%d0 /* save usp */ | ||
255 | movel %d0,%a0@(TASK_THREAD+THREAD_USP) | ||
256 | |||
257 | SAVE_SWITCH_STACK | ||
258 | movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */ | ||
259 | movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */ | ||
260 | RESTORE_SWITCH_STACK | ||
261 | |||
262 | movel %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */ | ||
263 | movel %a0, sw_usp | ||
264 | |||
265 | movew %a1@(TASK_THREAD+THREAD_SR),%d0 /* restore thread status reg */ | ||
266 | movew %d0, %sr | ||
267 | rts | ||
268 | |||
diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S new file mode 100644 index 000000000000..c7d7a395c4cc --- /dev/null +++ b/arch/m68knommu/platform/5307/head.S | |||
@@ -0,0 +1,253 @@ | |||
1 | /*****************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * head.S -- common startup code for ColdFire CPUs. | ||
5 | * | ||
6 | * (C) Copyright 1999-2004, Greg Ungerer (gerg@snapgear.com). | ||
7 | */ | ||
8 | |||
9 | /*****************************************************************************/ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/sys.h> | ||
13 | #include <linux/linkage.h> | ||
14 | #include <asm/asm-offsets.h> | ||
15 | #include <asm/coldfire.h> | ||
16 | #include <asm/mcfcache.h> | ||
17 | #include <asm/mcfsim.h> | ||
18 | |||
19 | /*****************************************************************************/ | ||
20 | |||
21 | /* | ||
22 | * Define fixed memory sizes. Configuration of a fixed memory size | ||
23 | * overrides everything else. If the user defined a size we just | ||
24 | * blindly use it (they know what they are doing right :-) | ||
25 | */ | ||
26 | #if defined(CONFIG_RAM32MB) | ||
27 | #define MEM_SIZE 0x02000000 /* memory size 32Mb */ | ||
28 | #elif defined(CONFIG_RAM16MB) | ||
29 | #define MEM_SIZE 0x01000000 /* memory size 16Mb */ | ||
30 | #elif defined(CONFIG_RAM8MB) | ||
31 | #define MEM_SIZE 0x00800000 /* memory size 8Mb */ | ||
32 | #elif defined(CONFIG_RAM4MB) | ||
33 | #define MEM_SIZE 0x00400000 /* memory size 4Mb */ | ||
34 | #elif defined(CONFIG_RAM1MB) | ||
35 | #define MEM_SIZE 0x00100000 /* memory size 1Mb */ | ||
36 | #endif | ||
37 | |||
38 | /* | ||
39 | * Memory size exceptions for special cases. Some boards may be set | ||
40 | * for auto memory sizing, but we can't do it that way for some reason. | ||
41 | * For example the 5206eLITE board has static RAM, and auto-detecting | ||
42 | * the SDRAM will do you no good at all. | ||
43 | */ | ||
44 | #ifdef CONFIG_RAMAUTO | ||
45 | #if defined(CONFIG_M5206eLITE) | ||
46 | #define MEM_SIZE 0x00100000 /* 1MiB default memory */ | ||
47 | #endif | ||
48 | #endif /* CONFIG_RAMAUTO */ | ||
49 | |||
50 | /* | ||
51 | * If we don't have a fixed memory size now, then lets build in code | ||
52 | * to auto detect the DRAM size. Obviously this is the prefered | ||
53 | * method, and should work for most boards (it won't work for those | ||
54 | * that do not have their RAM starting at address 0). | ||
55 | */ | ||
56 | #if defined(MEM_SIZE) | ||
57 | .macro GET_MEM_SIZE | ||
58 | movel #MEM_SIZE,%d0 /* hard coded memory size */ | ||
59 | .endm | ||
60 | |||
61 | #elif defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \ | ||
62 | defined(CONFIG_M5249) || defined(CONFIG_M527x) || \ | ||
63 | defined(CONFIG_M528x) || defined(CONFIG_M5307) || \ | ||
64 | defined(CONFIG_M5407) | ||
65 | /* | ||
66 | * Not all these devices have exactly the same DRAM controller, | ||
67 | * but the DCMR register is virtually identical - give or take | ||
68 | * a couple of bits. The only exception is the 5272 devices, their | ||
69 | * DRAM controller is quite different. | ||
70 | */ | ||
71 | .macro GET_MEM_SIZE | ||
72 | movel MCF_MBAR+MCFSIM_DMR0,%d0 /* get mask for 1st bank */ | ||
73 | btst #0,%d0 /* check if region enabled */ | ||
74 | beq 1f | ||
75 | andl #0xfffc0000,%d0 | ||
76 | beq 1f | ||
77 | addl #0x00040000,%d0 /* convert mask to size */ | ||
78 | 1: | ||
79 | movel MCF_MBAR+MCFSIM_DMR1,%d1 /* get mask for 2nd bank */ | ||
80 | btst #0,%d1 /* check if region enabled */ | ||
81 | beq 2f | ||
82 | andl #0xfffc0000, %d1 | ||
83 | beq 2f | ||
84 | addl #0x00040000,%d1 | ||
85 | addl %d1,%d0 /* total mem size in d0 */ | ||
86 | 2: | ||
87 | .endm | ||
88 | |||
89 | #elif defined(CONFIG_M5272) | ||
90 | .macro GET_MEM_SIZE | ||
91 | movel MCF_MBAR+MCFSIM_CSOR7,%d0 /* get SDRAM address mask */ | ||
92 | andil #0xfffff000,%d0 /* mask out chip select options */ | ||
93 | negl %d0 /* negate bits */ | ||
94 | .endm | ||
95 | |||
96 | #else | ||
97 | #error "ERROR: I don't know how to determine your boards memory size?" | ||
98 | #endif | ||
99 | |||
100 | |||
101 | /* | ||
102 | * Most ColdFire boards have their DRAM starting at address 0. | ||
103 | * Notable exception is the 5206eLITE board. | ||
104 | */ | ||
105 | #if defined(CONFIG_M5206eLITE) | ||
106 | #define MEM_BASE 0x30000000 | ||
107 | #endif | ||
108 | |||
109 | #ifndef MEM_BASE | ||
110 | #define MEM_BASE 0x00000000 /* memory base at address 0 */ | ||
111 | #endif | ||
112 | |||
113 | /* | ||
114 | * The default location for the vectors is at the base of RAM. | ||
115 | * Some boards might like to use internal SRAM or something like | ||
116 | * that. If no board specific header defines an alternative then | ||
117 | * use the base of RAM. | ||
118 | */ | ||
119 | #ifndef VBR_BASE | ||
120 | #define VBR_BASE MEM_BASE /* vector address */ | ||
121 | #endif | ||
122 | |||
123 | /*****************************************************************************/ | ||
124 | |||
125 | /* | ||
126 | * Boards and platforms can do specific early hardware setup if | ||
127 | * they need to. Most don't need this, define away if not required. | ||
128 | */ | ||
129 | #ifndef PLATFORM_SETUP | ||
130 | #define PLATFORM_SETUP | ||
131 | #endif | ||
132 | |||
133 | /*****************************************************************************/ | ||
134 | |||
135 | .global _start | ||
136 | .global _rambase | ||
137 | .global _ramvec | ||
138 | .global _ramstart | ||
139 | .global _ramend | ||
140 | |||
141 | /*****************************************************************************/ | ||
142 | |||
143 | .data | ||
144 | |||
145 | /* | ||
146 | * During startup we store away the RAM setup. These are not in the | ||
147 | * bss, since their values are determined and written before the bss | ||
148 | * has been cleared. | ||
149 | */ | ||
150 | _rambase: | ||
151 | .long 0 | ||
152 | _ramvec: | ||
153 | .long 0 | ||
154 | _ramstart: | ||
155 | .long 0 | ||
156 | _ramend: | ||
157 | .long 0 | ||
158 | |||
159 | /*****************************************************************************/ | ||
160 | |||
161 | .text | ||
162 | |||
163 | /* | ||
164 | * This is the codes first entry point. This is where it all | ||
165 | * begins... | ||
166 | */ | ||
167 | |||
168 | _start: | ||
169 | nop /* filler */ | ||
170 | movew #0x2700, %sr /* no interrupts */ | ||
171 | |||
172 | /* | ||
173 | * Do any platform or board specific setup now. Most boards | ||
174 | * don't need anything. Those exceptions are define this in | ||
175 | * their board specific includes. | ||
176 | */ | ||
177 | PLATFORM_SETUP | ||
178 | |||
179 | /* | ||
180 | * Create basic memory configuration. Set VBR accordingly, | ||
181 | * and size memory. | ||
182 | */ | ||
183 | movel #VBR_BASE,%a7 | ||
184 | movec %a7,%VBR /* set vectors addr */ | ||
185 | movel %a7,_ramvec | ||
186 | |||
187 | movel #MEM_BASE,%a7 /* mark the base of RAM */ | ||
188 | movel %a7,_rambase | ||
189 | |||
190 | GET_MEM_SIZE /* macro code determines size */ | ||
191 | movel %d0,_ramend /* set end ram addr */ | ||
192 | |||
193 | /* | ||
194 | * Now that we know what the memory is, lets enable cache | ||
195 | * and get things moving. This is Coldfire CPU specific. | ||
196 | */ | ||
197 | CACHE_ENABLE /* enable CPU cache */ | ||
198 | |||
199 | |||
200 | #ifdef CONFIG_ROMFS_FS | ||
201 | /* | ||
202 | * Move ROM filesystem above bss :-) | ||
203 | */ | ||
204 | lea _sbss,%a0 /* get start of bss */ | ||
205 | lea _ebss,%a1 /* set up destination */ | ||
206 | movel %a0,%a2 /* copy of bss start */ | ||
207 | |||
208 | movel 8(%a0),%d0 /* get size of ROMFS */ | ||
209 | addql #8,%d0 /* allow for rounding */ | ||
210 | andl #0xfffffffc, %d0 /* whole words */ | ||
211 | |||
212 | addl %d0,%a0 /* copy from end */ | ||
213 | addl %d0,%a1 /* copy from end */ | ||
214 | movel %a1,_ramstart /* set start of ram */ | ||
215 | |||
216 | _copy_romfs: | ||
217 | movel -(%a0),%d0 /* copy dword */ | ||
218 | movel %d0,-(%a1) | ||
219 | cmpl %a0,%a2 /* check if at end */ | ||
220 | bne _copy_romfs | ||
221 | |||
222 | #else /* CONFIG_ROMFS_FS */ | ||
223 | lea _ebss,%a1 | ||
224 | movel %a1,_ramstart | ||
225 | #endif /* CONFIG_ROMFS_FS */ | ||
226 | |||
227 | |||
228 | /* | ||
229 | * Zero out the bss region. | ||
230 | */ | ||
231 | lea _sbss,%a0 /* get start of bss */ | ||
232 | lea _ebss,%a1 /* get end of bss */ | ||
233 | clrl %d0 /* set value */ | ||
234 | _clear_bss: | ||
235 | movel %d0,(%a0)+ /* clear each word */ | ||
236 | cmpl %a0,%a1 /* check if at end */ | ||
237 | bne _clear_bss | ||
238 | |||
239 | /* | ||
240 | * Load the current task pointer and stack. | ||
241 | */ | ||
242 | lea init_thread_union,%a0 | ||
243 | lea THREAD_SIZE(%a0),%sp | ||
244 | |||
245 | /* | ||
246 | * Assember start up done, start code proper. | ||
247 | */ | ||
248 | jsr start_kernel /* start Linux kernel */ | ||
249 | |||
250 | _exit: | ||
251 | jmp _exit /* should never get here */ | ||
252 | |||
253 | /*****************************************************************************/ | ||
diff --git a/arch/m68knommu/platform/5307/ints.c b/arch/m68knommu/platform/5307/ints.c new file mode 100644 index 000000000000..0117754d44f3 --- /dev/null +++ b/arch/m68knommu/platform/5307/ints.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * linux/arch/m68knommu/kernel/ints.c -- General interrupt handling code | ||
3 | * | ||
4 | * Copyright (C) 1999-2002 Greg Ungerer (gerg@snapgear.com) | ||
5 | * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, | ||
6 | * Kenneth Albanowski <kjahds@kjahds.com>, | ||
7 | * Copyright (C) 2000 Lineo Inc. (www.lineo.com) | ||
8 | * | ||
9 | * Based on: | ||
10 | * | ||
11 | * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code | ||
12 | * | ||
13 | * This file is subject to the terms and conditions of the GNU General Public | ||
14 | * License. See the file COPYING in the main directory of this archive | ||
15 | * for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/kernel_stat.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/config.h> | ||
25 | #include <linux/seq_file.h> | ||
26 | |||
27 | #include <asm/system.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/traps.h> | ||
30 | #include <asm/page.h> | ||
31 | #include <asm/machdep.h> | ||
32 | |||
33 | /* | ||
34 | * This table stores the address info for each vector handler. | ||
35 | */ | ||
36 | irq_handler_t irq_list[SYS_IRQS]; | ||
37 | |||
38 | #define NUM_IRQ_NODES 16 | ||
39 | static irq_node_t nodes[NUM_IRQ_NODES]; | ||
40 | |||
41 | /* The number of spurious interrupts */ | ||
42 | volatile unsigned int num_spurious; | ||
43 | |||
44 | unsigned int local_bh_count[NR_CPUS]; | ||
45 | unsigned int local_irq_count[NR_CPUS]; | ||
46 | |||
47 | static irqreturn_t default_irq_handler(int irq, void *ptr, struct pt_regs *regs) | ||
48 | { | ||
49 | #if 1 | ||
50 | printk(KERN_INFO "%s(%d): default irq handler vec=%d [0x%x]\n", | ||
51 | __FILE__, __LINE__, irq, irq); | ||
52 | #endif | ||
53 | return(IRQ_HANDLED); | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * void init_IRQ(void) | ||
58 | * | ||
59 | * Parameters: None | ||
60 | * | ||
61 | * Returns: Nothing | ||
62 | * | ||
63 | * This function should be called during kernel startup to initialize | ||
64 | * the IRQ handling routines. | ||
65 | */ | ||
66 | |||
67 | void __init init_IRQ(void) | ||
68 | { | ||
69 | int i; | ||
70 | |||
71 | for (i = 0; i < SYS_IRQS; i++) { | ||
72 | if (mach_default_handler) | ||
73 | irq_list[i].handler = (*mach_default_handler)[i]; | ||
74 | else | ||
75 | irq_list[i].handler = default_irq_handler; | ||
76 | irq_list[i].flags = IRQ_FLG_STD; | ||
77 | irq_list[i].dev_id = NULL; | ||
78 | irq_list[i].devname = NULL; | ||
79 | } | ||
80 | |||
81 | for (i = 0; i < NUM_IRQ_NODES; i++) | ||
82 | nodes[i].handler = NULL; | ||
83 | |||
84 | if (mach_init_IRQ) | ||
85 | mach_init_IRQ(); | ||
86 | } | ||
87 | |||
88 | irq_node_t *new_irq_node(void) | ||
89 | { | ||
90 | irq_node_t *node; | ||
91 | short i; | ||
92 | |||
93 | for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) | ||
94 | if (!node->handler) | ||
95 | return node; | ||
96 | |||
97 | printk(KERN_INFO "new_irq_node: out of nodes\n"); | ||
98 | return NULL; | ||
99 | } | ||
100 | |||
101 | int request_irq( | ||
102 | unsigned int irq, | ||
103 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
104 | unsigned long flags, | ||
105 | const char *devname, | ||
106 | void *dev_id) | ||
107 | { | ||
108 | if (irq < 0 || irq >= NR_IRQS) { | ||
109 | printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n", __FUNCTION__, | ||
110 | irq, devname); | ||
111 | return -ENXIO; | ||
112 | } | ||
113 | |||
114 | if (!(irq_list[irq].flags & IRQ_FLG_STD)) { | ||
115 | if (irq_list[irq].flags & IRQ_FLG_LOCK) { | ||
116 | printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n", | ||
117 | __FUNCTION__, irq, irq_list[irq].devname); | ||
118 | return -EBUSY; | ||
119 | } | ||
120 | if (flags & IRQ_FLG_REPLACE) { | ||
121 | printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n", | ||
122 | __FUNCTION__, devname, irq, irq_list[irq].devname); | ||
123 | return -EBUSY; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | if (flags & IRQ_FLG_FAST) { | ||
128 | extern asmlinkage void fasthandler(void); | ||
129 | extern void set_evector(int vecnum, void (*handler)(void)); | ||
130 | set_evector(irq, fasthandler); | ||
131 | } | ||
132 | |||
133 | irq_list[irq].handler = handler; | ||
134 | irq_list[irq].flags = flags; | ||
135 | irq_list[irq].dev_id = dev_id; | ||
136 | irq_list[irq].devname = devname; | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | EXPORT_SYMBOL(request_irq); | ||
141 | |||
142 | void free_irq(unsigned int irq, void *dev_id) | ||
143 | { | ||
144 | if (irq >= NR_IRQS) { | ||
145 | printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | if (irq_list[irq].dev_id != dev_id) | ||
150 | printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n", | ||
151 | __FUNCTION__, irq, irq_list[irq].devname); | ||
152 | |||
153 | if (irq_list[irq].flags & IRQ_FLG_FAST) { | ||
154 | extern asmlinkage void inthandler(void); | ||
155 | extern void set_evector(int vecnum, void (*handler)(void)); | ||
156 | set_evector(irq, inthandler); | ||
157 | } | ||
158 | |||
159 | if (mach_default_handler) | ||
160 | irq_list[irq].handler = (*mach_default_handler)[irq]; | ||
161 | else | ||
162 | irq_list[irq].handler = default_irq_handler; | ||
163 | irq_list[irq].flags = IRQ_FLG_STD; | ||
164 | irq_list[irq].dev_id = NULL; | ||
165 | irq_list[irq].devname = NULL; | ||
166 | } | ||
167 | |||
168 | EXPORT_SYMBOL(free_irq); | ||
169 | |||
170 | |||
171 | int sys_request_irq(unsigned int irq, | ||
172 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
173 | unsigned long flags, const char *devname, void *dev_id) | ||
174 | { | ||
175 | if (irq > IRQ7) { | ||
176 | printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n", | ||
177 | __FUNCTION__, irq, devname); | ||
178 | return -ENXIO; | ||
179 | } | ||
180 | |||
181 | #if 0 | ||
182 | if (!(irq_list[irq].flags & IRQ_FLG_STD)) { | ||
183 | if (irq_list[irq].flags & IRQ_FLG_LOCK) { | ||
184 | printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n", | ||
185 | __FUNCTION__, irq, irq_list[irq].devname); | ||
186 | return -EBUSY; | ||
187 | } | ||
188 | if (!(flags & IRQ_FLG_REPLACE)) { | ||
189 | printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n", | ||
190 | __FUNCTION__, devname, irq, irq_list[irq].devname); | ||
191 | return -EBUSY; | ||
192 | } | ||
193 | } | ||
194 | #endif | ||
195 | |||
196 | irq_list[irq].handler = handler; | ||
197 | irq_list[irq].flags = flags; | ||
198 | irq_list[irq].dev_id = dev_id; | ||
199 | irq_list[irq].devname = devname; | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | void sys_free_irq(unsigned int irq, void *dev_id) | ||
204 | { | ||
205 | if (irq > IRQ7) { | ||
206 | printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); | ||
207 | return; | ||
208 | } | ||
209 | |||
210 | if (irq_list[irq].dev_id != dev_id) | ||
211 | printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n", | ||
212 | __FUNCTION__, irq, irq_list[irq].devname); | ||
213 | |||
214 | irq_list[irq].handler = (*mach_default_handler)[irq]; | ||
215 | irq_list[irq].flags = 0; | ||
216 | irq_list[irq].dev_id = NULL; | ||
217 | irq_list[irq].devname = NULL; | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * Do we need these probe functions on the m68k? | ||
222 | * | ||
223 | * ... may be useful with ISA devices | ||
224 | */ | ||
225 | unsigned long probe_irq_on (void) | ||
226 | { | ||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | EXPORT_SYMBOL(probe_irq_on); | ||
231 | |||
232 | int probe_irq_off (unsigned long irqs) | ||
233 | { | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | EXPORT_SYMBOL(probe_irq_off); | ||
238 | |||
239 | asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) | ||
240 | { | ||
241 | if (vec >= VEC_INT1 && vec <= VEC_INT7) { | ||
242 | vec -= VEC_SPUR; | ||
243 | kstat_cpu(0).irqs[vec]++; | ||
244 | irq_list[vec].handler(vec, irq_list[vec].dev_id, fp); | ||
245 | } else { | ||
246 | if (mach_process_int) | ||
247 | mach_process_int(vec, fp); | ||
248 | else | ||
249 | panic("Can't process interrupt vector %ld\n", vec); | ||
250 | return; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | |||
255 | int show_interrupts(struct seq_file *p, void *v) | ||
256 | { | ||
257 | int i = *(loff_t *) v; | ||
258 | |||
259 | if (i < NR_IRQS) { | ||
260 | if (! (irq_list[i].flags & IRQ_FLG_STD)) { | ||
261 | seq_printf(p, "%3d: %10u ", i, | ||
262 | (i ? kstat_cpu(0).irqs[i] : num_spurious)); | ||
263 | if (irq_list[i].flags & IRQ_FLG_LOCK) | ||
264 | seq_printf(p, "L "); | ||
265 | else | ||
266 | seq_printf(p, " "); | ||
267 | seq_printf(p, "%s\n", irq_list[i].devname); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | if (i == NR_IRQS && mach_get_irq_list) | ||
272 | mach_get_irq_list(p, v); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | void init_irq_proc(void) | ||
277 | { | ||
278 | /* Insert /proc/irq driver here */ | ||
279 | } | ||
280 | |||
diff --git a/arch/m68knommu/platform/5307/pit.c b/arch/m68knommu/platform/5307/pit.c new file mode 100644 index 000000000000..a9b2c2e7e280 --- /dev/null +++ b/arch/m68knommu/platform/5307/pit.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /***************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * pit.c -- Motorola ColdFire PIT timer. Currently this type of | ||
5 | * hardware timer only exists in the Motorola ColdFire | ||
6 | * 5270/5271 and 5282 CPUs. | ||
7 | * | ||
8 | * Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com) | ||
9 | * Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com) | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | /***************************************************************************/ | ||
14 | |||
15 | #include <linux/config.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/param.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <asm/irq.h> | ||
22 | #include <asm/coldfire.h> | ||
23 | #include <asm/mcfpit.h> | ||
24 | #include <asm/mcfsim.h> | ||
25 | |||
26 | /***************************************************************************/ | ||
27 | |||
28 | void coldfire_pit_tick(void) | ||
29 | { | ||
30 | volatile struct mcfpit *tp; | ||
31 | |||
32 | /* Reset the ColdFire timer */ | ||
33 | tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1); | ||
34 | tp->pcsr |= MCFPIT_PCSR_PIF; | ||
35 | } | ||
36 | |||
37 | /***************************************************************************/ | ||
38 | |||
39 | void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)) | ||
40 | { | ||
41 | volatile unsigned char *icrp; | ||
42 | volatile unsigned long *imrp; | ||
43 | volatile struct mcfpit *tp; | ||
44 | |||
45 | request_irq(MCFINT_VECBASE + MCFINT_PIT1, handler, SA_INTERRUPT, | ||
46 | "ColdFire Timer", NULL); | ||
47 | |||
48 | icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 + | ||
49 | MCFINTC_ICR0 + MCFINT_PIT1); | ||
50 | *icrp = 0x2b; /* PIT1 with level 5, priority 3 */ | ||
51 | |||
52 | imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH); | ||
53 | *imrp &= ~(1 << (MCFINT_PIT1 - 32)); | ||
54 | |||
55 | /* Set up PIT timer 1 as poll clock */ | ||
56 | tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1); | ||
57 | tp->pcsr = MCFPIT_PCSR_DISABLE; | ||
58 | |||
59 | tp->pmr = ((MCF_CLK / 2) / 64) / HZ; | ||
60 | tp->pcsr = MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW | | ||
61 | MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64; | ||
62 | } | ||
63 | |||
64 | /***************************************************************************/ | ||
65 | |||
66 | unsigned long coldfire_pit_offset(void) | ||
67 | { | ||
68 | volatile struct mcfpit *tp; | ||
69 | volatile unsigned long *ipr; | ||
70 | unsigned long pmr, pcntr, offset; | ||
71 | |||
72 | tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1); | ||
73 | ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IPRH); | ||
74 | |||
75 | pmr = *(&tp->pmr); | ||
76 | pcntr = *(&tp->pcntr); | ||
77 | |||
78 | /* | ||
79 | * If we are still in the first half of the upcount and a | ||
80 | * timer interupt is pending, then add on a ticks worth of time. | ||
81 | */ | ||
82 | offset = ((pmr - pcntr) * (1000000 / HZ)) / pmr; | ||
83 | if ((offset < (1000000 / HZ / 2)) && (*ipr & (1 << (MCFINT_PIT1 - 32)))) | ||
84 | offset += 1000000 / HZ; | ||
85 | return offset; | ||
86 | } | ||
87 | |||
88 | /***************************************************************************/ | ||
diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c new file mode 100644 index 000000000000..ef49596aa09c --- /dev/null +++ b/arch/m68knommu/platform/5307/timers.c | |||
@@ -0,0 +1,138 @@ | |||
1 | /***************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * timers.c -- generic ColdFire hardware timer support. | ||
5 | * | ||
6 | * Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com) | ||
7 | */ | ||
8 | |||
9 | /***************************************************************************/ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/param.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <asm/irq.h> | ||
18 | #include <asm/traps.h> | ||
19 | #include <asm/machdep.h> | ||
20 | #include <asm/coldfire.h> | ||
21 | #include <asm/mcftimer.h> | ||
22 | #include <asm/mcfsim.h> | ||
23 | |||
24 | /***************************************************************************/ | ||
25 | |||
26 | /* | ||
27 | * Default the timer and vector to use for ColdFire. Some ColdFire | ||
28 | * CPU's and some boards may want different. Their sub-architecture | ||
29 | * startup code (in config.c) can change these if they want. | ||
30 | */ | ||
31 | unsigned int mcf_timervector = 29; | ||
32 | unsigned int mcf_profilevector = 31; | ||
33 | unsigned int mcf_timerlevel = 5; | ||
34 | |||
35 | static volatile struct mcftimer *mcf_timerp; | ||
36 | |||
37 | /* | ||
38 | * These provide the underlying interrupt vector support. | ||
39 | * Unfortunately it is a little different on each ColdFire. | ||
40 | */ | ||
41 | extern void mcf_settimericr(int timer, int level); | ||
42 | extern int mcf_timerirqpending(int timer); | ||
43 | |||
44 | /***************************************************************************/ | ||
45 | |||
46 | void coldfire_tick(void) | ||
47 | { | ||
48 | /* Reset the ColdFire timer */ | ||
49 | mcf_timerp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; | ||
50 | } | ||
51 | |||
52 | /***************************************************************************/ | ||
53 | |||
54 | void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)) | ||
55 | { | ||
56 | /* Set up an internal TIMER as poll clock */ | ||
57 | mcf_timerp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE1); | ||
58 | mcf_timerp->tmr = MCFTIMER_TMR_DISABLE; | ||
59 | |||
60 | mcf_timerp->trr = (unsigned short) ((MCF_BUSCLK / 16) / HZ); | ||
61 | mcf_timerp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | | ||
62 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; | ||
63 | |||
64 | request_irq(mcf_timervector, handler, SA_INTERRUPT, "timer", NULL); | ||
65 | mcf_settimericr(1, mcf_timerlevel); | ||
66 | |||
67 | #ifdef CONFIG_HIGHPROFILE | ||
68 | coldfire_profile_init(); | ||
69 | #endif | ||
70 | } | ||
71 | |||
72 | /***************************************************************************/ | ||
73 | |||
74 | unsigned long coldfire_timer_offset(void) | ||
75 | { | ||
76 | unsigned long trr, tcn, offset; | ||
77 | |||
78 | /* | ||
79 | * The change to pointer and de-reference is to force the compiler | ||
80 | * to read the registers with a single 16bit access. Otherwise it | ||
81 | * does some crazy 8bit read combining. | ||
82 | */ | ||
83 | tcn = *(&mcf_timerp->tcn); | ||
84 | trr = *(&mcf_timerp->trr); | ||
85 | offset = (tcn * (1000000 / HZ)) / trr; | ||
86 | |||
87 | /* Check if we just wrapped the counters and maybe missed a tick */ | ||
88 | if ((offset < (1000000 / HZ / 2)) && mcf_timerirqpending(1)) | ||
89 | offset += 1000000 / HZ; | ||
90 | return offset; | ||
91 | } | ||
92 | |||
93 | /***************************************************************************/ | ||
94 | #ifdef CONFIG_HIGHPROFILE | ||
95 | /***************************************************************************/ | ||
96 | |||
97 | /* | ||
98 | * Choose a reasonably fast profile timer. Make it an odd value to | ||
99 | * try and get good coverage of kernal operations. | ||
100 | */ | ||
101 | #define PROFILEHZ 1013 | ||
102 | |||
103 | static volatile struct mcftimer *mcf_proftp; | ||
104 | |||
105 | /* | ||
106 | * Use the other timer to provide high accuracy profiling info. | ||
107 | */ | ||
108 | |||
109 | void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) | ||
110 | { | ||
111 | /* Reset ColdFire timer2 */ | ||
112 | mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; | ||
113 | if (current->pid) | ||
114 | profile_tick(CPU_PROFILING, regs); | ||
115 | } | ||
116 | |||
117 | /***************************************************************************/ | ||
118 | |||
119 | void coldfire_profile_init(void) | ||
120 | { | ||
121 | printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ); | ||
122 | |||
123 | /* Set up TIMER 2 as high speed profile clock */ | ||
124 | mcf_proftp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE2); | ||
125 | mcf_proftp->tmr = MCFTIMER_TMR_DISABLE; | ||
126 | |||
127 | mcf_proftp->trr = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ); | ||
128 | mcf_proftp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | | ||
129 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; | ||
130 | |||
131 | request_irq(mcf_profilevector, coldfire_profile_tick, | ||
132 | (SA_INTERRUPT | IRQ_FLG_FAST), "profile timer", NULL); | ||
133 | mcf_settimericr(2, 7); | ||
134 | } | ||
135 | |||
136 | /***************************************************************************/ | ||
137 | #endif /* CONFIG_HIGHPROFILE */ | ||
138 | /***************************************************************************/ | ||
diff --git a/arch/m68knommu/platform/5307/vectors.c b/arch/m68knommu/platform/5307/vectors.c new file mode 100644 index 000000000000..ac313a160d8d --- /dev/null +++ b/arch/m68knommu/platform/5307/vectors.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /***************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * linux/arch/m68knommu/platform/5307/vectors.c | ||
5 | * | ||
6 | * Copyright (C) 1999-2003, Greg Ungerer <gerg@snapgear.com> | ||
7 | */ | ||
8 | |||
9 | /***************************************************************************/ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/param.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/unistd.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <asm/irq.h> | ||
19 | #include <asm/dma.h> | ||
20 | #include <asm/traps.h> | ||
21 | #include <asm/machdep.h> | ||
22 | #include <asm/coldfire.h> | ||
23 | #include <asm/mcftimer.h> | ||
24 | #include <asm/mcfsim.h> | ||
25 | #include <asm/mcfdma.h> | ||
26 | #include <asm/mcfwdebug.h> | ||
27 | |||
28 | /***************************************************************************/ | ||
29 | |||
30 | #ifdef TRAP_DBG_INTERRUPT | ||
31 | |||
32 | asmlinkage void dbginterrupt_c(struct frame *fp) | ||
33 | { | ||
34 | extern void dump(struct pt_regs *fp); | ||
35 | printk(KERN_DEBUG "%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__); | ||
36 | dump((struct pt_regs *) fp); | ||
37 | asm("halt"); | ||
38 | } | ||
39 | |||
40 | #endif | ||
41 | |||
42 | /***************************************************************************/ | ||
43 | |||
44 | extern e_vector *_ramvec; | ||
45 | |||
46 | void set_evector(int vecnum, void (*handler)(void)) | ||
47 | { | ||
48 | if (vecnum >= 0 && vecnum <= 255) | ||
49 | _ramvec[vecnum] = handler; | ||
50 | } | ||
51 | |||
52 | /***************************************************************************/ | ||
53 | |||
54 | /* Assembler routines */ | ||
55 | asmlinkage void buserr(void); | ||
56 | asmlinkage void trap(void); | ||
57 | asmlinkage void system_call(void); | ||
58 | asmlinkage void inthandler(void); | ||
59 | |||
60 | void __init coldfire_trap_init(void) | ||
61 | { | ||
62 | int i; | ||
63 | |||
64 | /* | ||
65 | * There is a common trap handler and common interrupt | ||
66 | * handler that handle almost every vector. We treat | ||
67 | * the system call and bus error special, they get their | ||
68 | * own first level handlers. | ||
69 | */ | ||
70 | for (i = 3; (i <= 23); i++) | ||
71 | _ramvec[i] = trap; | ||
72 | for (i = 33; (i <= 63); i++) | ||
73 | _ramvec[i] = trap; | ||
74 | for (i = 24; (i <= 31); i++) | ||
75 | _ramvec[i] = inthandler; | ||
76 | for (i = 64; (i < 255); i++) | ||
77 | _ramvec[i] = inthandler; | ||
78 | _ramvec[255] = 0; | ||
79 | |||
80 | _ramvec[2] = buserr; | ||
81 | _ramvec[32] = system_call; | ||
82 | |||
83 | #ifdef TRAP_DBG_INTERRUPT | ||
84 | _ramvec[12] = dbginterrupt; | ||
85 | #endif | ||
86 | } | ||
87 | |||
88 | /***************************************************************************/ | ||
89 | |||
90 | void coldfire_reset(void) | ||
91 | { | ||
92 | HARD_RESET_NOW(); | ||
93 | } | ||
94 | |||
95 | /***************************************************************************/ | ||