summaryrefslogtreecommitdiffstats
path: root/arch/m68knommu/platform/5307
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68knommu/platform/5307')
-rw-r--r--arch/m68knommu/platform/5307/Makefile29
-rw-r--r--arch/m68knommu/platform/5307/config.c148
-rw-r--r--arch/m68knommu/platform/5307/entry.S268
-rw-r--r--arch/m68knommu/platform/5307/head.S253
-rw-r--r--arch/m68knommu/platform/5307/ints.c280
-rw-r--r--arch/m68knommu/platform/5307/pit.c88
-rw-r--r--arch/m68knommu/platform/5307/timers.c138
-rw-r--r--arch/m68knommu/platform/5307/vectors.c95
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 @@
+#
+# Makefile for the m68knommu kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this, which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+ifdef CONFIG_FULLDEBUG
+AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+endif
+
+obj-$(CONFIG_COLDFIRE) += entry.o vectors.o ints.o
+obj-$(CONFIG_M5206) += timers.o
+obj-$(CONFIG_M5206e) += timers.o
+obj-$(CONFIG_M5249) += timers.o
+obj-$(CONFIG_M527x) += pit.o
+obj-$(CONFIG_M5272) += timers.o
+obj-$(CONFIG_M5307) += config.o timers.o
+obj-$(CONFIG_M528x) += pit.o
+obj-$(CONFIG_M5407) += timers.o
+
+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 @@
+/***************************************************************************/
+
+/*
+ * linux/arch/m68knommu/platform/5307/config.c
+ *
+ * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ * Copyright (C) 2000, Lineo (www.lineo.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcftimer.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfdma.h>
+#include <asm/mcfwdebug.h>
+
+/***************************************************************************/
+
+void coldfire_tick(void);
+void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_timer_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+extern unsigned int mcf_timervector;
+extern unsigned int mcf_profilevector;
+extern unsigned int mcf_timerlevel;
+
+/***************************************************************************/
+
+/*
+ * Some platforms need software versions of the GPIO data registers.
+ */
+unsigned short ppdata;
+unsigned char ledbank = 0xff;
+
+/***************************************************************************/
+
+/*
+ * DMA channel base address table.
+ */
+unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = {
+ MCF_MBAR + MCFDMA_BASE0,
+ MCF_MBAR + MCFDMA_BASE1,
+ MCF_MBAR + MCFDMA_BASE2,
+ MCF_MBAR + MCFDMA_BASE3,
+};
+
+unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
+
+/***************************************************************************/
+
+void mcf_autovector(unsigned int vec)
+{
+ volatile unsigned char *mbar;
+
+ if ((vec >= 25) && (vec <= 31)) {
+ mbar = (volatile unsigned char *) MCF_MBAR;
+ vec = 0x1 << (vec - 24);
+ *(mbar + MCFSIM_AVR) |= vec;
+ mcf_setimr(mcf_getimr() & ~vec);
+ }
+}
+
+/***************************************************************************/
+
+void mcf_settimericr(unsigned int timer, unsigned int level)
+{
+ volatile unsigned char *icrp;
+ unsigned int icr, imr;
+
+ if (timer <= 2) {
+ switch (timer) {
+ case 2: icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break;
+ default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break;
+ }
+
+ icrp = (volatile unsigned char *) (MCF_MBAR + icr);
+ *icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3;
+ mcf_setimr(mcf_getimr() & ~imr);
+ }
+}
+
+/***************************************************************************/
+
+int mcf_timerirqpending(int timer)
+{
+ unsigned int imr = 0;
+
+ switch (timer) {
+ case 1: imr = MCFSIM_IMR_TIMER1; break;
+ case 2: imr = MCFSIM_IMR_TIMER2; break;
+ default: break;
+ }
+ return (mcf_getipr() & imr);
+}
+
+/***************************************************************************/
+
+void config_BSP(char *commandp, int size)
+{
+ mcf_setimr(MCFSIM_IMR_MASKALL);
+
+#if defined(CONFIG_BOOTPARAM)
+ strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
+ commandp[size-1] = 0;
+#elif defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
+ defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \
+ defined(CONFIG_CLEOPATRA)
+ /* Copy command line from FLASH to local buffer... */
+ memcpy(commandp, (char *) 0xf0004000, size);
+ commandp[size-1] = 0;
+ /* Different timer setup - to prevent device clash */
+ mcf_timervector = 30;
+ mcf_profilevector = 31;
+ mcf_timerlevel = 6;
+#else
+ memset(commandp, 0, size);
+#endif
+
+ mach_sched_init = coldfire_timer_init;
+ mach_tick = coldfire_tick;
+ mach_gettimeoffset = coldfire_timer_offset;
+ mach_trap_init = coldfire_trap_init;
+ mach_reset = coldfire_reset;
+
+#ifdef MCF_BDM_DISABLE
+ /*
+ * Disable the BDM clocking. This also turns off most of the rest of
+ * the BDM device. This is good for EMC reasons. This option is not
+ * incompatible with the memory protection option.
+ */
+ wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
+#endif
+}
+
+/***************************************************************************/
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 @@
+/*
+ * linux/arch/m68knommu/platform/5307/entry.S
+ *
+ * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
+ * Kenneth Albanowski <kjahds@kjahds.com>,
+ * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
+ * Copyright (C) 2004 Macq Electronique SA. (www.macqel.com)
+ *
+ * Based on:
+ *
+ * linux/arch/m68k/kernel/entry.S
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ *
+ * Linux/m68k support by Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ * ColdFire support by Greg Ungerer (gerg@snapgear.com)
+ * 5307 fixes by David W. Miller
+ * linux 2.4 support David McCullough <davidm@snapgear.com>
+ * Bug, speed and maintainability fixes by Philippe De Muyter <phdm@macqel.be>
+ */
+
+#include <linux/config.h>
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/asm-offsets.h>
+#include <asm/entry.h>
+
+.bss
+
+sw_ksp:
+.long 0
+
+sw_usp:
+.long 0
+
+.text
+
+.globl system_call
+.globl resume
+.globl ret_from_exception
+.globl ret_from_signal
+.globl sys_call_table
+.globl ret_from_interrupt
+.globl inthandler
+.globl fasthandler
+
+ENTRY(system_call)
+ SAVE_ALL
+ move #0x2000,%sr /* enable intrs again */
+
+ movel #-LENOSYS,%d2
+ movel %d2,PT_D0(%sp) /* default return value in d0 */
+ /* original D0 is in orig_d0 */
+ movel %d0,%d2
+
+ /* save top of frame */
+ pea %sp@
+ jbsr set_esp0
+ addql #4,%sp
+
+ cmpl #NR_syscalls,%d2
+ jcc ret_from_exception
+ lea sys_call_table,%a0
+ lsll #2,%d2 /* movel %a0@(%d2:l:4),%d3 */
+ movel %a0@(%d2),%d3
+ jeq ret_from_exception
+ lsrl #2,%d2
+
+ movel %sp,%d2 /* get thread_info pointer */
+ andl #-THREAD_SIZE,%d2 /* at start of kernel stack */
+ movel %d2,%a0
+ btst #TIF_SYSCALL_TRACE,%a0@(TI_FLAGS)
+ bnes 1f
+
+ movel %d3,%a0
+ jbsr %a0@
+ movel %d0,%sp@(PT_D0) /* save the return value */
+ jra ret_from_exception
+1:
+ subql #4,%sp
+ SAVE_SWITCH_STACK
+ jbsr syscall_trace
+ RESTORE_SWITCH_STACK
+ addql #4,%sp
+ movel %d3,%a0
+ jbsr %a0@
+ movel %d0,%sp@(PT_D0) /* save the return value */
+ subql #4,%sp /* dummy return address */
+ SAVE_SWITCH_STACK
+ jbsr syscall_trace
+
+ret_from_signal:
+ RESTORE_SWITCH_STACK
+ addql #4,%sp
+
+ret_from_exception:
+ btst #5,%sp@(PT_SR) /* check if returning to kernel */
+ jeq Luser_return /* if so, skip resched, signals */
+
+Lkernel_return:
+ moveml %sp@,%d1-%d5/%a0-%a2
+ lea %sp@(32),%sp /* space for 8 regs */
+ movel %sp@+,%d0
+ addql #4,%sp /* orig d0 */
+ addl %sp@+,%sp /* stk adj */
+ rte
+
+Luser_return:
+ movel %sp,%d1 /* get thread_info pointer */
+ andl #-THREAD_SIZE,%d1 /* at base of kernel stack */
+ movel %d1,%a0
+ movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */
+ andl #_TIF_WORK_MASK,%d1
+ jne Lwork_to_do /* still work to do */
+
+Lreturn:
+ move #0x2700,%sr /* disable intrs */
+ movel sw_usp,%a0 /* get usp */
+ movel %sp@(PT_PC),%a0@- /* copy exception program counter */
+ movel %sp@(PT_FORMATVEC),%a0@-/* copy exception format/vector/sr */
+ moveml %sp@,%d1-%d5/%a0-%a2
+ lea %sp@(32),%sp /* space for 8 regs */
+ movel %sp@+,%d0
+ addql #4,%sp /* orig d0 */
+ addl %sp@+,%sp /* stk adj */
+ addql #8,%sp /* remove exception */
+ movel %sp,sw_ksp /* save ksp */
+ subql #8,sw_usp /* set exception */
+ movel sw_usp,%sp /* restore usp */
+ rte
+
+Lwork_to_do:
+ movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */
+ btst #TIF_NEED_RESCHED,%d1
+ jne reschedule
+
+ /* GERG: do we need something here for TRACEing?? */
+
+Lsignal_return:
+ subql #4,%sp /* dummy return address */
+ SAVE_SWITCH_STACK
+ pea %sp@(SWITCH_STACK_SIZE)
+ clrl %sp@-
+ jsr do_signal
+ addql #8,%sp
+ RESTORE_SWITCH_STACK
+ addql #4,%sp
+ jmp Lreturn
+
+/*
+ * This is the generic interrupt handler (for all hardware interrupt
+ * sources). It figures out the vector number and calls the appropriate
+ * interrupt service routine directly.
+ */
+ENTRY(inthandler)
+ SAVE_ALL
+ moveq #-1,%d0
+ movel %d0,%sp@(PT_ORIG_D0)
+ addql #1,local_irq_count
+
+ movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */
+ andl #0x03fc,%d0 /* mask out vector only */
+
+ leal per_cpu__kstat+STAT_IRQ,%a0
+ addql #1,%a0@(%d0)
+
+ lsrl #2,%d0 /* calculate real vector # */
+ movel %d0,%d1 /* calculate array offset */
+ lsll #4,%d1
+ lea irq_list,%a0
+ addl %d1,%a0 /* pointer to array struct */
+
+ movel %sp,%sp@- /* push regs arg onto stack */
+ movel %a0@(8),%sp@- /* push devid arg */
+ movel %d0,%sp@- /* push vector # on stack */
+
+ movel %a0@,%a0 /* get function to call */
+ jbsr %a0@ /* call vector handler */
+ lea %sp@(12),%sp /* pop parameters off stack */
+
+ bra ret_from_interrupt /* this was fallthrough */
+
+/*
+ * This is the fast interrupt handler (for certain hardware interrupt
+ * sources). Unlike the normal interrupt handler it just uses the
+ * current stack (doesn't care if it is user or kernel). It also
+ * doesn't bother doing the bottom half handlers.
+ */
+ENTRY(fasthandler)
+ SAVE_LOCAL
+
+ movew %sp@(PT_FORMATVEC),%d0
+ andl #0x03fc,%d0 /* mask out vector only */
+
+ leal per_cpu__kstat+STAT_IRQ,%a0
+ addql #1,%a0@(%d0)
+
+ movel %sp,%sp@- /* push regs arg onto stack */
+ clrl %sp@- /* push devid arg */
+ lsrl #2,%d0 /* calculate real vector # */
+ movel %d0,%sp@- /* push vector # on stack */
+
+ lsll #4,%d0 /* adjust for array offset */
+ lea irq_list,%a0
+ movel %a0@(%d0),%a0 /* get function to call */
+ jbsr %a0@ /* call vector handler */
+ lea %sp@(12),%sp /* pop parameters off stack */
+
+ RESTORE_LOCAL
+
+ENTRY(ret_from_interrupt)
+ subql #1,local_irq_count
+ jeq 2f
+1:
+ RESTORE_ALL
+2:
+ moveb %sp@(PT_SR),%d0
+ andl #0x7,%d0
+ jhi 1b
+
+ /* check if we need to do software interrupts */
+ movel irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0
+ jeq ret_from_exception
+
+ pea ret_from_exception
+ jmp do_softirq
+
+/*
+ * Beware - when entering resume, prev (the current task) is
+ * in a0, next (the new task) is in a1,so don't change these
+ * registers until their contents are no longer needed.
+ */
+ENTRY(resume)
+ movel %a0, %d1 /* get prev thread in d1 */
+
+ movew %sr,%d0 /* save thread status reg */
+ movew %d0,%a0@(TASK_THREAD+THREAD_SR)
+
+ oril #0x700,%d0 /* disable interrupts */
+ move %d0,%sr
+
+ movel sw_usp,%d0 /* save usp */
+ movel %d0,%a0@(TASK_THREAD+THREAD_USP)
+
+ SAVE_SWITCH_STACK
+ movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */
+ movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
+ RESTORE_SWITCH_STACK
+
+ movel %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */
+ movel %a0, sw_usp
+
+ movew %a1@(TASK_THREAD+THREAD_SR),%d0 /* restore thread status reg */
+ movew %d0, %sr
+ rts
+
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 @@
+/*****************************************************************************/
+
+/*
+ * head.S -- common startup code for ColdFire CPUs.
+ *
+ * (C) Copyright 1999-2004, Greg Ungerer (gerg@snapgear.com).
+ */
+
+/*****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/coldfire.h>
+#include <asm/mcfcache.h>
+#include <asm/mcfsim.h>
+
+/*****************************************************************************/
+
+/*
+ * Define fixed memory sizes. Configuration of a fixed memory size
+ * overrides everything else. If the user defined a size we just
+ * blindly use it (they know what they are doing right :-)
+ */
+#if defined(CONFIG_RAM32MB)
+#define MEM_SIZE 0x02000000 /* memory size 32Mb */
+#elif defined(CONFIG_RAM16MB)
+#define MEM_SIZE 0x01000000 /* memory size 16Mb */
+#elif defined(CONFIG_RAM8MB)
+#define MEM_SIZE 0x00800000 /* memory size 8Mb */
+#elif defined(CONFIG_RAM4MB)
+#define MEM_SIZE 0x00400000 /* memory size 4Mb */
+#elif defined(CONFIG_RAM1MB)
+#define MEM_SIZE 0x00100000 /* memory size 1Mb */
+#endif
+
+/*
+ * Memory size exceptions for special cases. Some boards may be set
+ * for auto memory sizing, but we can't do it that way for some reason.
+ * For example the 5206eLITE board has static RAM, and auto-detecting
+ * the SDRAM will do you no good at all.
+ */
+#ifdef CONFIG_RAMAUTO
+#if defined(CONFIG_M5206eLITE)
+#define MEM_SIZE 0x00100000 /* 1MiB default memory */
+#endif
+#endif /* CONFIG_RAMAUTO */
+
+/*
+ * If we don't have a fixed memory size now, then lets build in code
+ * to auto detect the DRAM size. Obviously this is the prefered
+ * method, and should work for most boards (it won't work for those
+ * that do not have their RAM starting at address 0).
+ */
+#if defined(MEM_SIZE)
+.macro GET_MEM_SIZE
+ movel #MEM_SIZE,%d0 /* hard coded memory size */
+.endm
+
+#elif defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
+ defined(CONFIG_M5249) || defined(CONFIG_M527x) || \
+ defined(CONFIG_M528x) || defined(CONFIG_M5307) || \
+ defined(CONFIG_M5407)
+/*
+ * Not all these devices have exactly the same DRAM controller,
+ * but the DCMR register is virtually identical - give or take
+ * a couple of bits. The only exception is the 5272 devices, their
+ * DRAM controller is quite different.
+ */
+.macro GET_MEM_SIZE
+ movel MCF_MBAR+MCFSIM_DMR0,%d0 /* get mask for 1st bank */
+ btst #0,%d0 /* check if region enabled */
+ beq 1f
+ andl #0xfffc0000,%d0
+ beq 1f
+ addl #0x00040000,%d0 /* convert mask to size */
+1:
+ movel MCF_MBAR+MCFSIM_DMR1,%d1 /* get mask for 2nd bank */
+ btst #0,%d1 /* check if region enabled */
+ beq 2f
+ andl #0xfffc0000, %d1
+ beq 2f
+ addl #0x00040000,%d1
+ addl %d1,%d0 /* total mem size in d0 */
+2:
+.endm
+
+#elif defined(CONFIG_M5272)
+.macro GET_MEM_SIZE
+ movel MCF_MBAR+MCFSIM_CSOR7,%d0 /* get SDRAM address mask */
+ andil #0xfffff000,%d0 /* mask out chip select options */
+ negl %d0 /* negate bits */
+.endm
+
+#else
+#error "ERROR: I don't know how to determine your boards memory size?"
+#endif
+
+
+/*
+ * Most ColdFire boards have their DRAM starting at address 0.
+ * Notable exception is the 5206eLITE board.
+ */
+#if defined(CONFIG_M5206eLITE)
+#define MEM_BASE 0x30000000
+#endif
+
+#ifndef MEM_BASE
+#define MEM_BASE 0x00000000 /* memory base at address 0 */
+#endif
+
+/*
+ * The default location for the vectors is at the base of RAM.
+ * Some boards might like to use internal SRAM or something like
+ * that. If no board specific header defines an alternative then
+ * use the base of RAM.
+ */
+#ifndef VBR_BASE
+#define VBR_BASE MEM_BASE /* vector address */
+#endif
+
+/*****************************************************************************/
+
+/*
+ * Boards and platforms can do specific early hardware setup if
+ * they need to. Most don't need this, define away if not required.
+ */
+#ifndef PLATFORM_SETUP
+#define PLATFORM_SETUP
+#endif
+
+/*****************************************************************************/
+
+.global _start
+.global _rambase
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+/*****************************************************************************/
+
+.data
+
+/*
+ * During startup we store away the RAM setup. These are not in the
+ * bss, since their values are determined and written before the bss
+ * has been cleared.
+ */
+_rambase:
+.long 0
+_ramvec:
+.long 0
+_ramstart:
+.long 0
+_ramend:
+.long 0
+
+/*****************************************************************************/
+
+.text
+
+/*
+ * This is the codes first entry point. This is where it all
+ * begins...
+ */
+
+_start:
+ nop /* filler */
+ movew #0x2700, %sr /* no interrupts */
+
+ /*
+ * Do any platform or board specific setup now. Most boards
+ * don't need anything. Those exceptions are define this in
+ * their board specific includes.
+ */
+ PLATFORM_SETUP
+
+ /*
+ * Create basic memory configuration. Set VBR accordingly,
+ * and size memory.
+ */
+ movel #VBR_BASE,%a7
+ movec %a7,%VBR /* set vectors addr */
+ movel %a7,_ramvec
+
+ movel #MEM_BASE,%a7 /* mark the base of RAM */
+ movel %a7,_rambase
+
+ GET_MEM_SIZE /* macro code determines size */
+ movel %d0,_ramend /* set end ram addr */
+
+ /*
+ * Now that we know what the memory is, lets enable cache
+ * and get things moving. This is Coldfire CPU specific.
+ */
+ CACHE_ENABLE /* enable CPU cache */
+
+
+#ifdef CONFIG_ROMFS_FS
+ /*
+ * Move ROM filesystem above bss :-)
+ */
+ lea _sbss,%a0 /* get start of bss */
+ lea _ebss,%a1 /* set up destination */
+ movel %a0,%a2 /* copy of bss start */
+
+ movel 8(%a0),%d0 /* get size of ROMFS */
+ addql #8,%d0 /* allow for rounding */
+ andl #0xfffffffc, %d0 /* whole words */
+
+ addl %d0,%a0 /* copy from end */
+ addl %d0,%a1 /* copy from end */
+ movel %a1,_ramstart /* set start of ram */
+
+_copy_romfs:
+ movel -(%a0),%d0 /* copy dword */
+ movel %d0,-(%a1)
+ cmpl %a0,%a2 /* check if at end */
+ bne _copy_romfs
+
+#else /* CONFIG_ROMFS_FS */
+ lea _ebss,%a1
+ movel %a1,_ramstart
+#endif /* CONFIG_ROMFS_FS */
+
+
+ /*
+ * Zero out the bss region.
+ */
+ lea _sbss,%a0 /* get start of bss */
+ lea _ebss,%a1 /* get end of bss */
+ clrl %d0 /* set value */
+_clear_bss:
+ movel %d0,(%a0)+ /* clear each word */
+ cmpl %a0,%a1 /* check if at end */
+ bne _clear_bss
+
+ /*
+ * Load the current task pointer and stack.
+ */
+ lea init_thread_union,%a0
+ lea THREAD_SIZE(%a0),%sp
+
+ /*
+ * Assember start up done, start code proper.
+ */
+ jsr start_kernel /* start Linux kernel */
+
+_exit:
+ jmp _exit /* should never get here */
+
+/*****************************************************************************/
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 @@
+/*
+ * linux/arch/m68knommu/kernel/ints.c -- General interrupt handling code
+ *
+ * Copyright (C) 1999-2002 Greg Ungerer (gerg@snapgear.com)
+ * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
+ * Kenneth Albanowski <kjahds@kjahds.com>,
+ * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
+ *
+ * Based on:
+ *
+ * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+#include <linux/seq_file.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/page.h>
+#include <asm/machdep.h>
+
+/*
+ * This table stores the address info for each vector handler.
+ */
+irq_handler_t irq_list[SYS_IRQS];
+
+#define NUM_IRQ_NODES 16
+static irq_node_t nodes[NUM_IRQ_NODES];
+
+/* The number of spurious interrupts */
+volatile unsigned int num_spurious;
+
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+
+static irqreturn_t default_irq_handler(int irq, void *ptr, struct pt_regs *regs)
+{
+#if 1
+ printk(KERN_INFO "%s(%d): default irq handler vec=%d [0x%x]\n",
+ __FILE__, __LINE__, irq, irq);
+#endif
+ return(IRQ_HANDLED);
+}
+
+/*
+ * void init_IRQ(void)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ * This function should be called during kernel startup to initialize
+ * the IRQ handling routines.
+ */
+
+void __init init_IRQ(void)
+{
+ int i;
+
+ for (i = 0; i < SYS_IRQS; i++) {
+ if (mach_default_handler)
+ irq_list[i].handler = (*mach_default_handler)[i];
+ else
+ irq_list[i].handler = default_irq_handler;
+ irq_list[i].flags = IRQ_FLG_STD;
+ irq_list[i].dev_id = NULL;
+ irq_list[i].devname = NULL;
+ }
+
+ for (i = 0; i < NUM_IRQ_NODES; i++)
+ nodes[i].handler = NULL;
+
+ if (mach_init_IRQ)
+ mach_init_IRQ();
+}
+
+irq_node_t *new_irq_node(void)
+{
+ irq_node_t *node;
+ short i;
+
+ for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
+ if (!node->handler)
+ return node;
+
+ printk(KERN_INFO "new_irq_node: out of nodes\n");
+ return NULL;
+}
+
+int request_irq(
+ unsigned int irq,
+ irqreturn_t (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags,
+ const char *devname,
+ void *dev_id)
+{
+ if (irq < 0 || irq >= NR_IRQS) {
+ printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n", __FUNCTION__,
+ irq, devname);
+ return -ENXIO;
+ }
+
+ if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
+ if (irq_list[irq].flags & IRQ_FLG_LOCK) {
+ printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n",
+ __FUNCTION__, irq, irq_list[irq].devname);
+ return -EBUSY;
+ }
+ if (flags & IRQ_FLG_REPLACE) {
+ printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n",
+ __FUNCTION__, devname, irq, irq_list[irq].devname);
+ return -EBUSY;
+ }
+ }
+
+ if (flags & IRQ_FLG_FAST) {
+ extern asmlinkage void fasthandler(void);
+ extern void set_evector(int vecnum, void (*handler)(void));
+ set_evector(irq, fasthandler);
+ }
+
+ irq_list[irq].handler = handler;
+ irq_list[irq].flags = flags;
+ irq_list[irq].dev_id = dev_id;
+ irq_list[irq].devname = devname;
+ return 0;
+}
+
+EXPORT_SYMBOL(request_irq);
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+ if (irq >= NR_IRQS) {
+ printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+
+ if (irq_list[irq].dev_id != dev_id)
+ printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n",
+ __FUNCTION__, irq, irq_list[irq].devname);
+
+ if (irq_list[irq].flags & IRQ_FLG_FAST) {
+ extern asmlinkage void inthandler(void);
+ extern void set_evector(int vecnum, void (*handler)(void));
+ set_evector(irq, inthandler);
+ }
+
+ if (mach_default_handler)
+ irq_list[irq].handler = (*mach_default_handler)[irq];
+ else
+ irq_list[irq].handler = default_irq_handler;
+ irq_list[irq].flags = IRQ_FLG_STD;
+ irq_list[irq].dev_id = NULL;
+ irq_list[irq].devname = NULL;
+}
+
+EXPORT_SYMBOL(free_irq);
+
+
+int sys_request_irq(unsigned int irq,
+ irqreturn_t (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
+{
+ if (irq > IRQ7) {
+ printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n",
+ __FUNCTION__, irq, devname);
+ return -ENXIO;
+ }
+
+#if 0
+ if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
+ if (irq_list[irq].flags & IRQ_FLG_LOCK) {
+ printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n",
+ __FUNCTION__, irq, irq_list[irq].devname);
+ return -EBUSY;
+ }
+ if (!(flags & IRQ_FLG_REPLACE)) {
+ printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n",
+ __FUNCTION__, devname, irq, irq_list[irq].devname);
+ return -EBUSY;
+ }
+ }
+#endif
+
+ irq_list[irq].handler = handler;
+ irq_list[irq].flags = flags;
+ irq_list[irq].dev_id = dev_id;
+ irq_list[irq].devname = devname;
+ return 0;
+}
+
+void sys_free_irq(unsigned int irq, void *dev_id)
+{
+ if (irq > IRQ7) {
+ printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+
+ if (irq_list[irq].dev_id != dev_id)
+ printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n",
+ __FUNCTION__, irq, irq_list[irq].devname);
+
+ irq_list[irq].handler = (*mach_default_handler)[irq];
+ irq_list[irq].flags = 0;
+ irq_list[irq].dev_id = NULL;
+ irq_list[irq].devname = NULL;
+}
+
+/*
+ * Do we need these probe functions on the m68k?
+ *
+ * ... may be useful with ISA devices
+ */
+unsigned long probe_irq_on (void)
+{
+ return 0;
+}
+
+EXPORT_SYMBOL(probe_irq_on);
+
+int probe_irq_off (unsigned long irqs)
+{
+ return 0;
+}
+
+EXPORT_SYMBOL(probe_irq_off);
+
+asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
+{
+ if (vec >= VEC_INT1 && vec <= VEC_INT7) {
+ vec -= VEC_SPUR;
+ kstat_cpu(0).irqs[vec]++;
+ irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
+ } else {
+ if (mach_process_int)
+ mach_process_int(vec, fp);
+ else
+ panic("Can't process interrupt vector %ld\n", vec);
+ return;
+ }
+}
+
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *) v;
+
+ if (i < NR_IRQS) {
+ if (! (irq_list[i].flags & IRQ_FLG_STD)) {
+ seq_printf(p, "%3d: %10u ", i,
+ (i ? kstat_cpu(0).irqs[i] : num_spurious));
+ if (irq_list[i].flags & IRQ_FLG_LOCK)
+ seq_printf(p, "L ");
+ else
+ seq_printf(p, " ");
+ seq_printf(p, "%s\n", irq_list[i].devname);
+ }
+ }
+
+ if (i == NR_IRQS && mach_get_irq_list)
+ mach_get_irq_list(p, v);
+ return 0;
+}
+
+void init_irq_proc(void)
+{
+ /* Insert /proc/irq driver here */
+}
+
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 @@
+/***************************************************************************/
+
+/*
+ * pit.c -- Motorola ColdFire PIT timer. Currently this type of
+ * hardware timer only exists in the Motorola ColdFire
+ * 5270/5271 and 5282 CPUs.
+ *
+ * Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com)
+ * Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
+ *
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/coldfire.h>
+#include <asm/mcfpit.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+void coldfire_pit_tick(void)
+{
+ volatile struct mcfpit *tp;
+
+ /* Reset the ColdFire timer */
+ tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
+ tp->pcsr |= MCFPIT_PCSR_PIF;
+}
+
+/***************************************************************************/
+
+void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
+{
+ volatile unsigned char *icrp;
+ volatile unsigned long *imrp;
+ volatile struct mcfpit *tp;
+
+ request_irq(MCFINT_VECBASE + MCFINT_PIT1, handler, SA_INTERRUPT,
+ "ColdFire Timer", NULL);
+
+ icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 +
+ MCFINTC_ICR0 + MCFINT_PIT1);
+ *icrp = 0x2b; /* PIT1 with level 5, priority 3 */
+
+ imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
+ *imrp &= ~(1 << (MCFINT_PIT1 - 32));
+
+ /* Set up PIT timer 1 as poll clock */
+ tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
+ tp->pcsr = MCFPIT_PCSR_DISABLE;
+
+ tp->pmr = ((MCF_CLK / 2) / 64) / HZ;
+ tp->pcsr = MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW |
+ MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64;
+}
+
+/***************************************************************************/
+
+unsigned long coldfire_pit_offset(void)
+{
+ volatile struct mcfpit *tp;
+ volatile unsigned long *ipr;
+ unsigned long pmr, pcntr, offset;
+
+ tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
+ ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IPRH);
+
+ pmr = *(&tp->pmr);
+ pcntr = *(&tp->pcntr);
+
+ /*
+ * If we are still in the first half of the upcount and a
+ * timer interupt is pending, then add on a ticks worth of time.
+ */
+ offset = ((pmr - pcntr) * (1000000 / HZ)) / pmr;
+ if ((offset < (1000000 / HZ / 2)) && (*ipr & (1 << (MCFINT_PIT1 - 32))))
+ offset += 1000000 / HZ;
+ return offset;
+}
+
+/***************************************************************************/
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 @@
+/***************************************************************************/
+
+/*
+ * timers.c -- generic ColdFire hardware timer support.
+ *
+ * Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcftimer.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+/*
+ * Default the timer and vector to use for ColdFire. Some ColdFire
+ * CPU's and some boards may want different. Their sub-architecture
+ * startup code (in config.c) can change these if they want.
+ */
+unsigned int mcf_timervector = 29;
+unsigned int mcf_profilevector = 31;
+unsigned int mcf_timerlevel = 5;
+
+static volatile struct mcftimer *mcf_timerp;
+
+/*
+ * These provide the underlying interrupt vector support.
+ * Unfortunately it is a little different on each ColdFire.
+ */
+extern void mcf_settimericr(int timer, int level);
+extern int mcf_timerirqpending(int timer);
+
+/***************************************************************************/
+
+void coldfire_tick(void)
+{
+ /* Reset the ColdFire timer */
+ mcf_timerp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
+}
+
+/***************************************************************************/
+
+void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
+{
+ /* Set up an internal TIMER as poll clock */
+ mcf_timerp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE1);
+ mcf_timerp->tmr = MCFTIMER_TMR_DISABLE;
+
+ mcf_timerp->trr = (unsigned short) ((MCF_BUSCLK / 16) / HZ);
+ mcf_timerp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
+ MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
+
+ request_irq(mcf_timervector, handler, SA_INTERRUPT, "timer", NULL);
+ mcf_settimericr(1, mcf_timerlevel);
+
+#ifdef CONFIG_HIGHPROFILE
+ coldfire_profile_init();
+#endif
+}
+
+/***************************************************************************/
+
+unsigned long coldfire_timer_offset(void)
+{
+ unsigned long trr, tcn, offset;
+
+ /*
+ * The change to pointer and de-reference is to force the compiler
+ * to read the registers with a single 16bit access. Otherwise it
+ * does some crazy 8bit read combining.
+ */
+ tcn = *(&mcf_timerp->tcn);
+ trr = *(&mcf_timerp->trr);
+ offset = (tcn * (1000000 / HZ)) / trr;
+
+ /* Check if we just wrapped the counters and maybe missed a tick */
+ if ((offset < (1000000 / HZ / 2)) && mcf_timerirqpending(1))
+ offset += 1000000 / HZ;
+ return offset;
+}
+
+/***************************************************************************/
+#ifdef CONFIG_HIGHPROFILE
+/***************************************************************************/
+
+/*
+ * Choose a reasonably fast profile timer. Make it an odd value to
+ * try and get good coverage of kernal operations.
+ */
+#define PROFILEHZ 1013
+
+static volatile struct mcftimer *mcf_proftp;
+
+/*
+ * Use the other timer to provide high accuracy profiling info.
+ */
+
+void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs)
+{
+ /* Reset ColdFire timer2 */
+ mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
+ if (current->pid)
+ profile_tick(CPU_PROFILING, regs);
+}
+
+/***************************************************************************/
+
+void coldfire_profile_init(void)
+{
+ printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ);
+
+ /* Set up TIMER 2 as high speed profile clock */
+ mcf_proftp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE2);
+ mcf_proftp->tmr = MCFTIMER_TMR_DISABLE;
+
+ mcf_proftp->trr = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ);
+ mcf_proftp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
+ MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
+
+ request_irq(mcf_profilevector, coldfire_profile_tick,
+ (SA_INTERRUPT | IRQ_FLG_FAST), "profile timer", NULL);
+ mcf_settimericr(2, 7);
+}
+
+/***************************************************************************/
+#endif /* CONFIG_HIGHPROFILE */
+/***************************************************************************/
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 @@
+/***************************************************************************/
+
+/*
+ * linux/arch/m68knommu/platform/5307/vectors.c
+ *
+ * Copyright (C) 1999-2003, Greg Ungerer <gerg@snapgear.com>
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/unistd.h>
+#include <linux/delay.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcftimer.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfdma.h>
+#include <asm/mcfwdebug.h>
+
+/***************************************************************************/
+
+#ifdef TRAP_DBG_INTERRUPT
+
+asmlinkage void dbginterrupt_c(struct frame *fp)
+{
+ extern void dump(struct pt_regs *fp);
+ printk(KERN_DEBUG "%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__);
+ dump((struct pt_regs *) fp);
+ asm("halt");
+}
+
+#endif
+
+/***************************************************************************/
+
+extern e_vector *_ramvec;
+
+void set_evector(int vecnum, void (*handler)(void))
+{
+ if (vecnum >= 0 && vecnum <= 255)
+ _ramvec[vecnum] = handler;
+}
+
+/***************************************************************************/
+
+/* Assembler routines */
+asmlinkage void buserr(void);
+asmlinkage void trap(void);
+asmlinkage void system_call(void);
+asmlinkage void inthandler(void);
+
+void __init coldfire_trap_init(void)
+{
+ int i;
+
+ /*
+ * There is a common trap handler and common interrupt
+ * handler that handle almost every vector. We treat
+ * the system call and bus error special, they get their
+ * own first level handlers.
+ */
+ for (i = 3; (i <= 23); i++)
+ _ramvec[i] = trap;
+ for (i = 33; (i <= 63); i++)
+ _ramvec[i] = trap;
+ for (i = 24; (i <= 31); i++)
+ _ramvec[i] = inthandler;
+ for (i = 64; (i < 255); i++)
+ _ramvec[i] = inthandler;
+ _ramvec[255] = 0;
+
+ _ramvec[2] = buserr;
+ _ramvec[32] = system_call;
+
+#ifdef TRAP_DBG_INTERRUPT
+ _ramvec[12] = dbginterrupt;
+#endif
+}
+
+/***************************************************************************/
+
+void coldfire_reset(void)
+{
+ HARD_RESET_NOW();
+}
+
+/***************************************************************************/
OpenPOWER on IntegriCloud