diff options
Diffstat (limited to 'target/linux/coldfire/patches/008-mcfv4e_coldfire_code.patch')
-rw-r--r-- | target/linux/coldfire/patches/008-mcfv4e_coldfire_code.patch | 4484 |
1 files changed, 0 insertions, 4484 deletions
diff --git a/target/linux/coldfire/patches/008-mcfv4e_coldfire_code.patch b/target/linux/coldfire/patches/008-mcfv4e_coldfire_code.patch deleted file mode 100644 index 9da89c8..0000000 --- a/target/linux/coldfire/patches/008-mcfv4e_coldfire_code.patch +++ /dev/null @@ -1,4484 +0,0 @@ -From 70b2bd01829b38a1a79caeda05d436b2e5fecf82 Mon Sep 17 00:00:00 2001 -From: Kurt Mahan <kmahan@freescale.com> -Date: Wed, 31 Oct 2007 17:00:18 -0600 -Subject: [PATCH] Core Coldfire/MCF5445x specific code. - -LTIBName: mcfv4e-coldfire-code -Signed-off-by: Kurt Mahan <kmahan@freescale.com> ---- - arch/m68k/coldfire/Makefile | 11 + - arch/m68k/coldfire/cache.c | 215 +++++++++ - arch/m68k/coldfire/config.c | 420 ++++++++++++++++++ - arch/m68k/coldfire/entry.S | 701 ++++++++++++++++++++++++++++++ - arch/m68k/coldfire/head.S | 474 ++++++++++++++++++++ - arch/m68k/coldfire/ints.c | 384 ++++++++++++++++ - arch/m68k/coldfire/iomap.c | 54 +++ - arch/m68k/coldfire/mcf5445x-pci.c | 427 ++++++++++++++++++ - arch/m68k/coldfire/muldi3.S | 64 +++ - arch/m68k/coldfire/pci.c | 245 +++++++++++ - arch/m68k/coldfire/signal.c | 868 +++++++++++++++++++++++++++++++++++++ - arch/m68k/coldfire/traps.c | 454 +++++++++++++++++++ - arch/m68k/coldfire/vmlinux-cf.lds | 92 ++++ - 13 files changed, 4409 insertions(+), 0 deletions(-) - create mode 100644 arch/m68k/coldfire/Makefile - create mode 100644 arch/m68k/coldfire/cache.c - create mode 100644 arch/m68k/coldfire/config.c - create mode 100644 arch/m68k/coldfire/entry.S - create mode 100644 arch/m68k/coldfire/head.S - create mode 100644 arch/m68k/coldfire/ints.c - create mode 100644 arch/m68k/coldfire/iomap.c - create mode 100644 arch/m68k/coldfire/mcf5445x-pci.c - create mode 100644 arch/m68k/coldfire/muldi3.S - create mode 100644 arch/m68k/coldfire/pci.c - create mode 100644 arch/m68k/coldfire/signal.c - create mode 100644 arch/m68k/coldfire/traps.c - create mode 100644 arch/m68k/coldfire/vmlinux-cf.lds - ---- /dev/null -+++ b/arch/m68k/coldfire/Makefile -@@ -0,0 +1,11 @@ -+# -+# Makefile for Linux arch/m68k/coldfire source directory -+# -+ -+obj-y:= entry.o config.o cache.o signal.o muldi3.o traps.o ints.o -+ -+ifneq ($(strip $(CONFIG_USB) $(CONFIG_USB_GADGET_MCF5445X)),) -+ obj-y += usb.o usb/ -+endif -+ -+obj-$(CONFIG_PCI) += pci.o mcf5445x-pci.o iomap.o ---- /dev/null -+++ b/arch/m68k/coldfire/cache.c -@@ -0,0 +1,215 @@ -+/* -+ * linux/arch/m68k/coldifre/cache.c -+ * -+ * Matt Waddel Matt.Waddel@freescale.com -+ * Copyright Freescale Semiconductor, Inc. 2007 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include <linux/interrupt.h> -+#include <asm/cfcache.h> -+#include <asm/coldfire.h> -+#include <asm/system.h> -+ -+#define _DCACHE_SIZE (2*16384) -+#define _ICACHE_SIZE (2*16384) -+ -+#define _SET_SHIFT 4 -+ -+/* -+ * Masks for cache sizes. Programming note: because the set size is a -+ * power of two, the mask is also the last address in the set. -+ */ -+ -+#define _DCACHE_SET_MASK ((_DCACHE_SIZE/64-1)<<_SET_SHIFT) -+#define _ICACHE_SET_MASK ((_ICACHE_SIZE/64-1)<<_SET_SHIFT) -+#define LAST_DCACHE_ADDR _DCACHE_SET_MASK -+#define LAST_ICACHE_ADDR _ICACHE_SET_MASK -+ -+/************************************************************ -+ * Routine to cleanly flush the cache, pushing all lines and -+ * invalidating them. -+ * -+ * The is the flash-resident version, used after copying the .text -+ * segment from flash to ram. -+ *************************************************************/ -+void FLASHDcacheFlushInvalidate(void) -+ __attribute__ ((section (".text_loader"))); -+ -+void FLASHDcacheFlushInvalidate() -+{ -+ unsigned long set; -+ unsigned long start_set; -+ unsigned long end_set; -+ -+ start_set = 0; -+ end_set = (unsigned long)LAST_DCACHE_ADDR; -+ -+ for (set = start_set; set < end_set; set += (0x10 - 3)) -+ asm volatile("cpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)" : : "a" (set)); -+} -+ -+/************************************************************ -+ * Routine to cleanly flush the cache, pushing all lines and -+ * invalidating them. -+ * -+ *************************************************************/ -+void DcacheFlushInvalidate() -+{ -+ unsigned long set; -+ unsigned long start_set; -+ unsigned long end_set; -+ -+ start_set = 0; -+ end_set = (unsigned long)LAST_DCACHE_ADDR; -+ -+ for (set = start_set; set < end_set; set += (0x10 - 3)) -+ asm volatile("cpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)" : : "a" (set)); -+} -+ -+ -+ -+/****************************************************************************** -+ * Routine to cleanly flush the a block of cache, pushing all relevant lines -+ * and invalidating them. -+ * -+ ******************************************************************************/ -+void DcacheFlushInvalidateCacheBlock(void *start, unsigned long size) -+{ -+ unsigned long set; -+ unsigned long start_set; -+ unsigned long end_set; -+ -+ /* if size is bigger than the cache can store -+ * set the size to the maximum amount -+ */ -+ -+ if (size > LAST_DCACHE_ADDR) -+ size = LAST_DCACHE_ADDR; -+ -+ start_set = ((unsigned long)start) & _DCACHE_SET_MASK; -+ end_set = ((unsigned long)(start+size-1)) & _DCACHE_SET_MASK; -+ -+ if (start_set > end_set) { -+ /* from the begining to the lowest address */ -+ for (set = 0; set <= end_set; set += (0x10 - 3)) -+ asm volatile("cpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)" : : "a" (set)); -+ -+ /* next loop will finish the cache ie pass the hole */ -+ end_set = LAST_DCACHE_ADDR; -+ } -+ for (set = start_set; set <= end_set; set += (0x10 - 3)) -+ asm volatile("cpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%dc,(%0)" : : "a" (set)); -+} -+ -+ -+void IcacheInvalidateCacheBlock(void *start, unsigned long size) -+{ -+ unsigned long set; -+ unsigned long start_set; -+ unsigned long end_set; -+ -+ /* if size is bigger than the cache can store -+ * set the size to the maximum ammount -+ */ -+ -+ if (size > LAST_ICACHE_ADDR) -+ size = LAST_ICACHE_ADDR; -+ -+ start_set = ((unsigned long)start) & _ICACHE_SET_MASK; -+ end_set = ((unsigned long)(start+size-1)) & _ICACHE_SET_MASK; -+ -+ if (start_set > end_set) { -+ /* from the begining to the lowest address */ -+ for (set = 0; set <= end_set; set += (0x10 - 3)) -+ asm volatile("cpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)" : : "a" (set)); -+ -+ /* next loop will finish the cache ie pass the hole */ -+ end_set = LAST_ICACHE_ADDR; -+ } -+ for (set = start_set; set <= end_set; set += (0x10 - 3)) -+ asm volatile("cpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)\n" -+ "\taddq%.l #1,%0\n" -+ "\tcpushl %%ic,(%0)" : : "a" (set)); -+} -+ -+ -+/******************************************************************** -+ * Disable the data cache completely -+ ********************************************************************/ -+void DcacheDisable(void) -+{ -+ int newValue; -+ unsigned long flags; -+ -+ local_save_flags(flags); -+ local_irq_disable(); -+ -+ DcacheFlushInvalidate(); /* begin by flushing the cache */ -+ newValue = CACHE_DISABLE_MODE; /* disable it */ -+ cacr_set(newValue); -+ local_irq_restore(flags); -+} -+ -+/******************************************************************** -+ * Unconditionally enable the data cache -+ ********************************************************************/ -+void DcacheEnable(void) -+{ -+ cacr_set(CACHE_INITIAL_MODE); -+} -+ -+ -+unsigned long shadow_cacr; -+ -+void cacr_set(unsigned long x) -+{ -+ shadow_cacr = x; -+ -+ __asm__ __volatile__ ("movec %0, %%cacr" -+ : /* no outputs */ -+ : "r" (shadow_cacr)); -+} -+ -+unsigned long cacr_get(void) -+{ -+ return shadow_cacr; -+} ---- /dev/null -+++ b/arch/m68k/coldfire/config.c -@@ -0,0 +1,420 @@ -+/* -+ * linux/arch/m68k/coldifre/config.c -+ * -+ * Matt Waddel Matt.Waddel@freescale.com -+ * Copyright Freescale Semiconductor, Inc. 2007 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/string.h> -+#include <linux/kernel.h> -+#include <linux/console.h> -+#include <linux/bootmem.h> -+#include <linux/mm.h> -+#include <asm/bootinfo.h> -+#include <asm/machdep.h> -+#include <asm/coldfire.h> -+#include <asm/cfcache.h> -+#include <asm/bootinfo.h> -+#include <asm/io.h> -+#include <asm/cfmmu.h> -+#include <asm/setup.h> -+#include <asm/irq.h> -+#include <asm/traps.h> -+#include <asm/movs.h> -+#include <asm/movs.h> -+#include <asm/page.h> -+#include <asm/pgalloc.h> -+#include <asm/mcf5445x_intc.h> -+#include <asm/mcf5445x_sdramc.h> -+#include <asm/mcf5445x_fbcs.h> -+#include <asm/mcf5445x_dtim.h> -+ -+/* JKM -- testing */ -+#include <linux/pfn.h> -+/* JKM */ -+ -+extern int get_irq_list(struct seq_file *p, void *v); -+extern char _text, _end; -+extern char _etext, _edata, __init_begin, __init_end; -+extern struct console mcfrs_console; -+extern char m68k_command_line[CL_SIZE]; -+extern unsigned long availmem; -+ -+static int irq_enable[NR_IRQS]; -+unsigned long num_pages; -+ -+void coldfire_sort_memrec(void) -+{ -+ int i, j; -+ -+ /* Sort the m68k_memory records by address */ -+ for (i = 0; i < m68k_num_memory; ++i) { -+ for (j = i + 1; j < m68k_num_memory; ++j) { -+ if (m68k_memory[i].addr > m68k_memory[j].addr) { -+ struct mem_info tmp; -+ tmp = m68k_memory[i]; -+ m68k_memory[i] = m68k_memory[j]; -+ m68k_memory[j] = tmp; -+ } -+ } -+ } -+ /* Trim off discontiguous bits */ -+ for (i = 1; i < m68k_num_memory; ++i) { -+ if ((m68k_memory[i-1].addr + m68k_memory[i-1].size) != -+ m68k_memory[i].addr) { -+ printk(KERN_DEBUG "m68k_parse_bootinfo: addr gap between \ -+ 0x%lx & 0x%lx\n", -+ m68k_memory[i-1].addr+m68k_memory[i-1].size, -+ m68k_memory[i].addr); -+ m68k_num_memory = i; -+ break; -+ } -+ } -+} -+ -+int __init uboot_commandline(char *bootargs) -+{ -+ int len = 0, cmd_line_len; -+ static struct uboot_record uboot_info; -+ -+ extern unsigned long uboot_info_stk; -+ -+ /* Add 0x80000000 to get post-remapped kernel memory location */ -+ uboot_info.bd_info = (*(u32 *)(uboot_info_stk)) + 0x80000000; -+ uboot_info.initrd_start = (*(u32 *)(uboot_info_stk+4)) + 0x80000000; -+ uboot_info.initrd_end = (*(u32 *)(uboot_info_stk+8)) + 0x80000000; -+ uboot_info.cmd_line_start = (*(u32 *)(uboot_info_stk+12)) + 0x80000000; -+ uboot_info.cmd_line_stop = (*(u32 *)(uboot_info_stk+16)) + 0x80000000; -+ -+ cmd_line_len = uboot_info.cmd_line_stop - uboot_info.cmd_line_start; -+ if ((cmd_line_len > 0) && (cmd_line_len < CL_SIZE-1)) -+ len = (int)strncpy(bootargs, (char *)uboot_info.cmd_line_start,\ -+ cmd_line_len); -+ -+ return len; -+} -+ -+/* -+ * This routine does things not done in the bootloader. -+ */ -+#define DEFAULT_COMMAND_LINE "root=/dev/mtdblock1 rw rootfstype=jffs2 ip=none mtdparts=physmap-flash.0:5M(kernel)ro,-(jffs2)" -+asmlinkage void __init cf_early_init(void) -+{ -+ struct bi_record *record = (struct bi_record *) &_end; -+ -+ extern char _end; -+ -+ SET_VBR((void *)MCF_RAMBAR1); -+ -+ /* Mask all interrupts */ -+ MCF_INTC0_IMRL = 0xFFFFFFFF; -+ MCF_INTC0_IMRH = 0xFFFFFFFF; -+ MCF_INTC1_IMRL = 0xFFFFFFFF; -+ MCF_INTC1_IMRH = 0xFFFFFFFF; -+ -+#if defined(CONFIG_NOR_FLASH_BASE) -+ MCF_FBCS_CSAR(1) = CONFIG_NOR_FLASH_BASE; -+#else -+ MCF_FBCS_CSAR(1) = 0x00000000; -+#endif -+ -+#if CONFIG_SDRAM_SIZE > (256*1024*1024) -+ /* Init optional SDRAM chip select */ -+ MCF_SDRAMC_SDCS(1) = (256*1024*1024) | 0x1B; -+#endif -+ -+ m68k_machtype = MACH_CFMMU; -+ m68k_fputype = FPU_CFV4E; -+ m68k_mmutype = MMU_CFV4E; -+ m68k_cputype = CPU_CFV4E; -+ -+ m68k_num_memory = 0; -+ m68k_memory[m68k_num_memory].addr = CONFIG_SDRAM_BASE; -+ m68k_memory[m68k_num_memory++].size = CONFIG_SDRAM_SIZE; -+ -+ if (!uboot_commandline(m68k_command_line)) { -+#if defined(CONFIG_BOOTPARAM) -+ strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE-1); -+#else -+ strcpy(m68k_command_line, DEFAULT_COMMAND_LINE); -+#endif -+ } -+ -+ -+#if defined(CONFIG_BLK_DEV_INITRD) -+ /* add initrd image */ -+ record = (struct bi_record *) ((void *)record + record->size); -+ record->tag = BI_RAMDISK; -+ record->size = sizeof(record->tag) + sizeof(record->size) -+ + sizeof(record->data[0]) + sizeof(record->data[1]); -+#endif -+ -+ /* Mark end of tags. */ -+ record = (struct bi_record *) ((void *) record + record->size); -+ record->tag = 0; -+ record->data[0] = 0; -+ record->data[1] = 0; -+ record->size = sizeof(record->tag) + sizeof(record->size) -+ + sizeof(record->data[0]) + sizeof(record->data[1]); -+ -+ /* Invalidate caches via CACR */ -+ cacr_set(CACHE_DISABLE_MODE); -+ -+ /* Turn on caches via CACR, enable EUSP */ -+ cacr_set(CACHE_INITIAL_MODE); -+} -+ -+void settimericr(unsigned int timer, unsigned int level) -+{ -+ volatile unsigned char *icrp; -+ unsigned int icr; -+ unsigned char irq; -+ -+ if (timer <= 2) { -+ switch (timer) { -+ case 2: irq = 33; icr = MCFSIM_ICR_TIMER2; break; -+ default: irq = 32; icr = MCFSIM_ICR_TIMER1; break; -+ } -+ -+ icrp = (volatile unsigned char *) (icr); -+ *icrp = level; -+ coldfire_enable_irq0(irq); -+ } -+} -+ -+/* 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 = 0; -+ e_vector *vectors; -+ -+ vectors = (e_vector *)MCF_RAMBAR1; -+ /* -+ * 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++) -+ vectors[i] = trap; -+ for (i = 33; (i <= 63); i++) -+ vectors[i] = trap; -+ for (i = 24; (i <= 31); i++) -+ vectors[i] = inthandler; -+ for (i = 64; (i < 255); i++) -+ vectors[i] = inthandler; -+ -+ vectors[255] = 0; -+ vectors[2] = buserr; -+ vectors[32] = system_call; -+} -+ -+void coldfire_tick(void) -+{ -+ /* Reset the ColdFire timer */ -+ __raw_writeb(MCF_DTIM_DTER_CAP | MCF_DTIM_DTER_REF, MCF_DTIM0_DTER); -+} -+ -+void __init coldfire_sched_init(irq_handler_t handler) -+{ -+ unsigned int mcf_timerlevel = 5; -+ unsigned int mcf_timervector = 64+32; -+ -+ __raw_writew(MCF_DTIM_DTMR_RST_RST, MCF_DTIM0_DTMR); -+ __raw_writel(((MCF_BUSCLK / 16) / HZ), MCF_DTIM0_DTRR); -+ __raw_writew(MCF_DTIM_DTMR_ORRI | MCF_DTIM_DTMR_CLK_DIV16 | -+ MCF_DTIM_DTMR_FRR | MCF_DTIM_DTMR_RST_EN, \ -+ MCF_DTIM0_DTMR); -+ -+ request_irq(mcf_timervector, handler, SA_INTERRUPT, \ -+ "timer", (void *)MCF_DTIM0_DTMR); -+ -+ settimericr(1, mcf_timerlevel); -+} -+ -+int timerirqpending(int timer) -+{ -+ unsigned int imr = 0; -+ -+ switch (timer) { -+ case 1: imr = 0x1; break; -+ case 2: imr = 0x2; break; -+ default: break; -+ } -+ -+ return (getiprh() & imr); -+} -+ -+unsigned long coldfire_gettimeoffset(void) -+{ -+ volatile unsigned long trr, tcn, offset; -+ -+ tcn = __raw_readw(MCF_DTIM0_DTCN); -+ trr = __raw_readl(MCF_DTIM0_DTRR); -+ offset = (tcn * (1000000 / HZ)) / trr; -+ -+ /* Check if we just wrapped the counters and maybe missed a tick */ -+ if ((offset < (1000000 / HZ / 2)) && timerirqpending(1)) -+ offset += 1000000 / HZ; -+ return offset; -+} -+ -+void coldfire_reboot(void) -+{ -+ /* disable interrupts and do a software reset */ -+ asm("movew #0x2700, %%sr\n\t" -+ "moveb #0x80, %%d0\n\t" -+ "moveb %%d0, 0xfc0a0000\n\t" -+ : : : "%d0"); -+} -+ -+/* int coldfire_hwclk(int i, struct rtc_time *t) -+{ -+ printk ("Real time clock needs porting.\n"); -+ return 0; -+}*/ -+ -+static void coldfire_get_model(char *model) -+{ -+ sprintf(model, "Version 4 ColdFire"); -+} -+ -+void coldfire_enable_irq(unsigned int vec) -+{ -+ unsigned long flags; -+ -+ vec -= 64; -+ -+ if (((int)vec < 0) || (vec > 63)) { -+ printk(KERN_WARNING "enable_irq %d failed\n", vec); -+ return; -+ } -+ -+ local_irq_save(flags); -+ irq_enable[vec]++; -+ if (vec < 32) -+ MCF_INTC0_IMRL &= ~(1 << vec); -+ else -+ MCF_INTC0_IMRH &= ~(1 << (vec - 32)); -+ local_irq_restore(flags); -+} -+ -+void coldfire_disable_irq(unsigned int vec) -+{ -+ unsigned long flags; -+ -+ vec -= 64; -+ -+ if (((int)vec < 0) || (vec > 63)) { -+ printk(KERN_WARNING "disable_irq %d failed\n", vec); -+ return; -+ } -+ -+ local_irq_save(flags); -+ if (--irq_enable[vec] == 0) { -+ if (vec < 32) -+ MCF_INTC0_IMRL |= (1 << vec); -+ else -+ MCF_INTC0_IMRH |= (1 << (vec - 32)); -+ -+ } -+ local_irq_restore(flags); -+} -+ -+static void __init -+coldfire_bootmem_alloc(unsigned long memory_start, unsigned long memory_end) -+{ -+ unsigned long base_pfn; -+ -+ /* compute total pages in system */ -+ num_pages = PAGE_ALIGN(memory_end - PAGE_OFFSET) >> PAGE_SHIFT; -+ -+ /* align start/end to page boundries */ -+ memory_start = PAGE_ALIGN(memory_start); -+ memory_end = memory_end & PAGE_MASK; -+ -+ /* page numbers */ -+ base_pfn = __pa(PAGE_OFFSET) >> PAGE_SHIFT; -+ min_low_pfn = __pa(memory_start) >> PAGE_SHIFT; -+ max_low_pfn = __pa(memory_end) >> PAGE_SHIFT; -+ -+ high_memory = (void *)memory_end; -+ availmem = memory_start; -+ -+ /* setup bootmem data */ -+ m68k_setup_node(0); -+ availmem += init_bootmem_node(NODE_DATA(0), min_low_pfn, -+ base_pfn, max_low_pfn); -+ availmem = PAGE_ALIGN(availmem); -+ free_bootmem(__pa(availmem), memory_end - (availmem)); -+} -+ -+void __init config_coldfire(void) -+{ -+ unsigned long endmem, startmem; -+ int i; -+ -+ /* -+ * Calculate endmem from m68k_memory, assume all are contiguous -+ */ -+ startmem = ((((int) &_end) + (PAGE_SIZE - 1)) & PAGE_MASK); -+ endmem = PAGE_OFFSET; -+ for (i = 0; i < m68k_num_memory; ++i) -+ endmem += m68k_memory[i].size; -+ -+ printk(KERN_INFO "starting up linux startmem 0x%lx, endmem 0x%lx, \ -+ size %luMB\n", startmem, endmem, (endmem - startmem) >> 20); -+ -+ memset(irq_enable, 0, sizeof(irq_enable)); -+ -+ /* -+ * Setup coldfire mach-specific handlers -+ */ -+ mach_max_dma_address = 0xffffffff; -+ mach_sched_init = coldfire_sched_init; -+ mach_tick = coldfire_tick; -+ mach_gettimeoffset = coldfire_gettimeoffset; -+ mach_reset = coldfire_reboot; -+/* mach_hwclk = coldfire_hwclk; to be done */ -+ mach_get_model = coldfire_get_model; -+ -+ coldfire_bootmem_alloc(startmem, endmem); -+ -+ /* -+ * initrd setup -+ */ -+/* #ifdef CONFIG_BLK_DEV_INITRD -+ if (m68k_ramdisk.size) { -+ reserve_bootmem (__pa(m68k_ramdisk.addr), m68k_ramdisk.size); -+ initrd_start = (unsigned long) m68k_ramdisk.addr; -+ initrd_end = initrd_start + m68k_ramdisk.size; -+ printk (KERN_DEBUG "initrd: %08lx - %08lx\n", initrd_start, -+ initrd_end); -+ } -+#endif */ -+ -+#if defined(CONFIG_DUMMY_CONSOLE) || defined(CONFIG_FRAMEBUFFER_CONSOLE) -+ conswitchp = &dummy_con; -+#endif -+ -+#if defined(CONFIG_SERIAL_COLDFIRE) -+ /* -+ * This causes trouble when it is re-registered later. -+ * Currently this is fixed by conditionally commenting -+ * out the register_console in mcf_serial.c -+ */ -+ register_console(&mcfrs_console); -+#endif -+} ---- /dev/null -+++ b/arch/m68k/coldfire/entry.S -@@ -0,0 +1,701 @@ -+/* -+ * arch/m68k/coldfire/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-2006 Macq Electronique SA. (www.macqel.com) -+ * Matt Waddel Matt.Waddel@freescale.com -+ * Kurt Mahan kmahan@freescale.com -+ * Copyright Freescale Semiconductor, Inc. 2007 -+ * -+ * Based on: -+ * -+ * arch/m68knommu/platform/5307/entry.S & -+ * 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 -+ * -+ * 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> -+ * Ported to mmu Coldfire by Matt Waddel -+ */ -+ -+#include <linux/sys.h> -+#include <linux/linkage.h> -+#include <asm/cf_entry.h> -+#include <asm/errno.h> -+#include <asm/setup.h> -+#include <asm/segment.h> -+#include <asm/traps.h> -+#include <asm/unistd.h> -+ -+/* -+ * TASK_INFO: -+ * -+ * - TINFO_PREEMPT (struct thread_info / preempt_count) -+ * Used to keep track of preemptability -+ * - TINFO_FLAGS (struct thread_info / flags - include/asm-m68k/thread_info.h) -+ * Various bit flags that are checked for scheduling/tracing -+ * Bits 0-7 are checked every exception exit -+ * 8-15 are checked every syscall exit -+ * -+ * TIF_SIGPENDING 6 -+ * TIF_NEED_RESCHED 7 -+ * TIF_DELAYED_TRACE 14 -+ * TIF_SYSCALL_TRACE 15 -+ * TIF_MEMDIE 16 (never checked here) -+ */ -+ -+.bss -+ -+sw_ksp: -+.long 0 -+ -+sw_usp: -+.long 0 -+ -+.text -+ -+.globl system_call -+.globl buserr -+.globl trap -+.globl resume -+.globl ret_from_exception -+.globl ret_from_signal -+.globl sys_call_table -+.globl ret_from_interrupt -+.globl inthandler -+ -+ENTRY(buserr) -+ SAVE_ALL_INT -+ GET_CURRENT(%d0) -+ movel %sp,%sp@- /* stack frame pointer argument */ -+ jsr buserr_c -+ addql #4,%sp -+ jra .Lret_from_exception -+ -+ENTRY(trap) -+ SAVE_ALL_INT -+ GET_CURRENT(%d0) -+ movel %sp,%sp@- /* stack frame pointer argument */ -+ jsr trap_c -+ addql #4,%sp -+ jra .Lret_from_exception -+ -+ /* After a fork we jump here directly from resume, -+ %d1 contains the previous task schedule_tail */ -+ENTRY(ret_from_fork) -+ movel %d1,%sp@- -+ jsr schedule_tail -+ addql #4,%sp -+ jra .Lret_from_exception -+ -+do_trace_entry: -+ movel #-ENOSYS,%d1 /* needed for strace */ -+ movel %d1,%sp@(PT_D0) -+ subql #4,%sp -+ SAVE_SWITCH_STACK -+ jbsr syscall_trace -+ RESTORE_SWITCH_STACK -+ addql #4,%sp -+ movel %sp@(PT_ORIG_D0),%d0 -+ cmpl #NR_syscalls,%d0 -+ jcs syscall -+badsys: -+ movel #-ENOSYS,%d1 -+ movel %d1,%sp@(PT_D0) -+ jra ret_from_exception -+ -+do_trace_exit: -+ subql #4,%sp -+ SAVE_SWITCH_STACK -+ jbsr syscall_trace -+ RESTORE_SWITCH_STACK -+ addql #4,%sp -+ jra .Lret_from_exception -+ -+ENTRY(ret_from_signal) -+ RESTORE_SWITCH_STACK -+ addql #4,%sp -+ jra .Lret_from_exception -+ -+ENTRY(system_call) -+ SAVE_ALL_SYS -+ -+ GET_CURRENT(%d1) -+ /* save top of frame */ -+ movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) -+ -+ /* syscall trace */ -+ tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) -+ jmi do_trace_entry /* SYSCALL_TRACE is set */ -+ cmpl #NR_syscalls,%d0 -+ jcc badsys -+syscall: -+ movel #sys_call_table,%a0 -+ asll #2,%d0 -+ addl %d0,%a0 -+ movel %a0@,%a0 -+ jsr %a0@ -+ movel %d0,%sp@(PT_D0) /* save the return value */ -+ret_from_syscall: -+ movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0 -+ jne syscall_exit_work /* flags set so process */ -+1: RESTORE_ALL -+ -+syscall_exit_work: -+ btst #5,%sp@(PT_SR) /* check if returning to kernel */ -+ bnes 1b /* if so, skip resched, signals */ -+ -+ btstl #15,%d0 /* check if SYSCALL_TRACE */ -+ jne do_trace_exit -+ btstl #14,%d0 /* check if DELAYED_TRACE */ -+ jne do_delayed_trace -+ btstl #6,%d0 /* check if SIGPENDING */ -+ jne do_signal_return -+ pea resume_userspace -+ jra schedule -+ -+ENTRY(ret_from_exception) -+.Lret_from_exception: -+ btst #5,%sp@(PT_SR) /* check if returning to kernel */ -+ bnes 1f /* if so, skip resched, signals */ -+ movel %d0,%sp@- /* Only allow interrupts when we are */ -+ move %sr,%d0 /* last one on the kernel stack, */ -+ andl #ALLOWINT,%d0 /* otherwise stack overflow can occur */ -+ move %d0,%sr /* during heavy interrupt load. */ -+ movel %sp@+,%d0 -+ -+resume_userspace: -+ moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0 -+ jne exit_work /* SIGPENDING and/or NEED_RESCHED set */ -+1: RESTORE_ALL -+ -+exit_work: -+ /* save top of frame */ -+ movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) -+ btstl #6,%d0 /* check for SIGPENDING in flags */ -+ jne do_signal_return -+ pea resume_userspace -+ jra schedule -+ -+do_signal_return: -+ subql #4,%sp /* dummy return address */ -+ SAVE_SWITCH_STACK -+ pea %sp@(SWITCH_STACK_SIZE) -+ clrl %sp@- -+ bsrl do_signal -+ addql #8,%sp -+ RESTORE_SWITCH_STACK -+ addql #4,%sp -+ jbra resume_userspace -+ -+do_delayed_trace: -+ bclr #7,%sp@(PT_SR) /* clear trace bit in SR */ -+ pea 1 /* send SIGTRAP */ -+ movel %curptr,%sp@- -+ pea LSIGTRAP -+ jbsr send_sig -+ addql #8,%sp -+ addql #4,%sp -+ jbra resume_userspace -+ -+/* -+ * This is the 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_INT -+ GET_CURRENT(%d0) -+ addql #1,%curptr@(TASK_INFO+TINFO_PREEMPT) -+ /* put exception # in d0 */ -+ movel %sp@(PT_VECTOR),%d0 -+ swap %d0 /* extract bits 25:18 */ -+ lsrl #2,%d0 -+ andl #0x0ff,%d0 -+ -+ movel %sp,%sp@- -+ movel %d0,%sp@- /* put vector # on stack */ -+auto_irqhandler_fixup = . + 2 -+ jbsr process_int /* process the IRQ */ -+ addql #8,%sp /* pop parameters off stack */ -+ -+ENTRY(ret_from_interrupt) -+ret_from_interrupt: -+ -+ subql #1,%curptr@(TASK_INFO+TINFO_PREEMPT) -+ jeq ret_from_last_interrupt -+2: RESTORE_ALL -+ -+ ALIGN -+ret_from_last_interrupt: -+ moveb %sp@(PT_SR),%d0 -+ andl #(~ALLOWINT>>8)&0xff,%d0 -+ jne 2b -+ -+ /* check if we need to do software interrupts */ -+ tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING -+ jeq .Lret_from_exception -+ pea ret_from_exception -+ jra do_softirq -+ -+ENTRY(user_inthandler) -+ SAVE_ALL_INT -+ GET_CURRENT(%d0) -+ addql #1,%curptr@(TASK_INFO+TINFO_PREEMPT) -+ /* put exception # in d0 */ -+ movel %sp@(PT_VECTOR),%d0 -+user_irqvec_fixup = . + 2 -+ swap %d0 /* extract bits 25:18 */ -+ lsrl #2,%d0 -+ andl #0x0ff,%d0 -+ -+ movel %sp,%sp@- -+ movel %d0,%sp@- /* put vector # on stack */ -+user_irqhandler_fixup = . + 2 -+ jbsr process_int /* process the IRQ */ -+ addql #8,%sp /* pop parameters off stack */ -+ -+ subql #1,%curptr@(TASK_INFO+TINFO_PREEMPT) -+ jeq ret_from_last_interrupt -+ RESTORE_ALL -+ -+/* Handler for uninitialized and spurious interrupts */ -+ -+ENTRY(bad_inthandler) -+ SAVE_ALL_INT -+ GET_CURRENT(%d0) -+ addql #1,%curptr@(TASK_INFO+TINFO_PREEMPT) -+ -+ movel %sp,%sp@- -+ jsr handle_badint -+ addql #4,%sp -+ -+ subql #1,%curptr@(TASK_INFO+TINFO_PREEMPT) -+ jeq ret_from_last_interrupt -+ RESTORE_ALL -+ -+ENTRY(sys_fork) -+ SAVE_SWITCH_STACK -+ pea %sp@(SWITCH_STACK_SIZE) -+ jbsr m68k_fork -+ addql #4,%sp -+ RESTORE_SWITCH_STACK -+ rts -+ -+ENTRY(sys_clone) -+ SAVE_SWITCH_STACK -+ pea %sp@(SWITCH_STACK_SIZE) -+ jbsr m68k_clone -+ addql #4,%sp -+ RESTORE_SWITCH_STACK -+ rts -+ -+ENTRY(sys_vfork) -+ SAVE_SWITCH_STACK -+ pea %sp@(SWITCH_STACK_SIZE) -+ jbsr m68k_vfork -+ addql #4,%sp -+ RESTORE_SWITCH_STACK -+ rts -+ -+ENTRY(sys_sigsuspend) -+ SAVE_SWITCH_STACK -+ pea %sp@(SWITCH_STACK_SIZE) -+ jbsr do_sigsuspend -+ addql #4,%sp -+ RESTORE_SWITCH_STACK -+ rts -+ -+ENTRY(sys_rt_sigsuspend) -+ SAVE_SWITCH_STACK -+ pea %sp@(SWITCH_STACK_SIZE) -+ jbsr do_rt_sigsuspend -+ addql #4,%sp -+ RESTORE_SWITCH_STACK -+ rts -+ -+ENTRY(sys_sigreturn) -+ SAVE_SWITCH_STACK -+ jbsr do_sigreturn -+ RESTORE_SWITCH_STACK -+ rts -+ -+ENTRY(sys_rt_sigreturn) -+ SAVE_SWITCH_STACK -+ jbsr do_rt_sigreturn -+ RESTORE_SWITCH_STACK -+ rts -+ -+resume: -+ /* -+ * 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. -+ */ -+ -+ /* save sr */ -+ movew %sr,%d0 -+ movew %d0,%a0@(TASK_THREAD+THREAD_SR) -+ -+ /* save usp */ -+ /* Save USP via %a1 (which is saved/restored from %d0) */ -+ movel %a1,%d0 -+ movel %usp,%a1 -+ movel %a1,%a0@(TASK_THREAD+THREAD_USP) -+ movel %d0,%a1 -+ -+ /* save non-scratch registers on stack */ -+ SAVE_SWITCH_STACK -+ -+ /* save current kernel stack pointer */ -+ movel %sp,%a0@(TASK_THREAD+THREAD_KSP) -+ -+ /* Return previous task in %d1 */ -+ movel %curptr,%d1 -+ -+ /* switch to new task (a1 contains new task) */ -+ movel %a1,%curptr -+ -+ /* restore the kernel stack pointer */ -+ movel %a1@(TASK_THREAD+THREAD_KSP),%sp -+ -+ /* restore non-scratch registers */ -+ RESTORE_SWITCH_STACK -+ -+ /* restore user stack pointer */ -+ movel %a1@(TASK_THREAD+THREAD_USP),%a0 -+ movel %a0,%usp -+ -+ /* restore status register */ -+ movew %a1@(TASK_THREAD+THREAD_SR),%d0 -+ movew %d0,%sr -+ -+ rts -+ -+.data -+ALIGN -+sys_call_table: -+ .long sys_ni_syscall /* 0 - old "setup()" system call*/ -+ .long sys_exit -+ .long sys_fork -+ .long sys_read -+ .long sys_write -+ .long sys_open /* 5 */ -+ .long sys_close -+ .long sys_waitpid -+ .long sys_creat -+ .long sys_link -+ .long sys_unlink /* 10 */ -+ .long sys_execve -+ .long sys_chdir -+ .long sys_time -+ .long sys_mknod -+ .long sys_chmod /* 15 */ -+ .long sys_chown16 -+ .long sys_ni_syscall /* old break syscall holder */ -+ .long sys_stat -+ .long sys_lseek -+ .long sys_getpid /* 20 */ -+ .long sys_mount -+ .long sys_oldumount -+ .long sys_setuid16 -+ .long sys_getuid16 -+ .long sys_stime /* 25 */ -+ .long sys_ptrace -+ .long sys_alarm -+ .long sys_fstat -+ .long sys_pause -+ .long sys_utime /* 30 */ -+ .long sys_ni_syscall /* old stty syscall holder */ -+ .long sys_ni_syscall /* old gtty syscall holder */ -+ .long sys_access -+ .long sys_nice -+ .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ -+ .long sys_sync -+ .long sys_kill -+ .long sys_rename -+ .long sys_mkdir -+ .long sys_rmdir /* 40 */ -+ .long sys_dup -+ .long sys_pipe -+ .long sys_times -+ .long sys_ni_syscall /* old prof syscall holder */ -+ .long sys_brk /* 45 */ -+ .long sys_setgid16 -+ .long sys_getgid16 -+ .long sys_signal -+ .long sys_geteuid16 -+ .long sys_getegid16 /* 50 */ -+ .long sys_acct -+ .long sys_umount /* recycled never used phys() */ -+ .long sys_ni_syscall /* old lock syscall holder */ -+ .long sys_ioctl -+ .long sys_fcntl /* 55 */ -+ .long sys_ni_syscall /* old mpx syscall holder */ -+ .long sys_setpgid -+ .long sys_ni_syscall /* old ulimit syscall holder */ -+ .long sys_ni_syscall -+ .long sys_umask /* 60 */ -+ .long sys_chroot -+ .long sys_ustat -+ .long sys_dup2 -+ .long sys_getppid -+ .long sys_getpgrp /* 65 */ -+ .long sys_setsid -+ .long sys_sigaction -+ .long sys_sgetmask -+ .long sys_ssetmask -+ .long sys_setreuid16 /* 70 */ -+ .long sys_setregid16 -+ .long sys_sigsuspend -+ .long sys_sigpending -+ .long sys_sethostname -+ .long sys_setrlimit /* 75 */ -+ .long sys_old_getrlimit -+ .long sys_getrusage -+ .long sys_gettimeofday -+ .long sys_settimeofday -+ .long sys_getgroups16 /* 80 */ -+ .long sys_setgroups16 -+ .long old_select -+ .long sys_symlink -+ .long sys_lstat -+ .long sys_readlink /* 85 */ -+ .long sys_uselib -+ .long sys_swapon -+ .long sys_reboot -+ .long old_readdir -+ .long old_mmap /* 90 */ -+ .long sys_munmap -+ .long sys_truncate -+ .long sys_ftruncate -+ .long sys_fchmod -+ .long sys_fchown16 /* 95 */ -+ .long sys_getpriority -+ .long sys_setpriority -+ .long sys_ni_syscall /* old profil syscall holder */ -+ .long sys_statfs -+ .long sys_fstatfs /* 100 */ -+ .long sys_ni_syscall /* ioperm for i386 */ -+ .long sys_socketcall -+ .long sys_syslog -+ .long sys_setitimer -+ .long sys_getitimer /* 105 */ -+ .long sys_newstat -+ .long sys_newlstat -+ .long sys_newfstat -+ .long sys_ni_syscall -+ .long sys_ni_syscall /* 110 */ /* iopl for i386 */ -+ .long sys_vhangup -+ .long sys_ni_syscall /* obsolete idle() syscall */ -+ .long sys_ni_syscall /* vm86old for i386 */ -+ .long sys_wait4 -+ .long sys_swapoff /* 115 */ -+ .long sys_sysinfo -+ .long sys_ipc -+ .long sys_fsync -+ .long sys_sigreturn -+ .long sys_clone /* 120 */ -+ .long sys_setdomainname -+ .long sys_newuname -+ .long sys_cacheflush /* modify_ldt for i386 */ -+ .long sys_adjtimex -+ .long sys_mprotect /* 125 */ -+ .long sys_sigprocmask -+ .long sys_ni_syscall /* old "create_module" */ -+ .long sys_init_module -+ .long sys_delete_module -+ .long sys_ni_syscall /* 130 - old "get_kernel_syms" */ -+ .long sys_quotactl -+ .long sys_getpgid -+ .long sys_fchdir -+ .long sys_bdflush -+ .long sys_sysfs /* 135 */ -+ .long sys_personality -+ .long sys_ni_syscall /* for afs_syscall */ -+ .long sys_setfsuid16 -+ .long sys_setfsgid16 -+ .long sys_llseek /* 140 */ -+ .long sys_getdents -+ .long sys_select -+ .long sys_flock -+ .long sys_msync -+ .long sys_readv /* 145 */ -+ .long sys_writev -+ .long sys_getsid -+ .long sys_fdatasync -+ .long sys_sysctl -+ .long sys_mlock /* 150 */ -+ .long sys_munlock -+ .long sys_mlockall -+ .long sys_munlockall -+ .long sys_sched_setparam -+ .long sys_sched_getparam /* 155 */ -+ .long sys_sched_setscheduler -+ .long sys_sched_getscheduler -+ .long sys_sched_yield -+ .long sys_sched_get_priority_max -+ .long sys_sched_get_priority_min /* 160 */ -+ .long sys_sched_rr_get_interval -+ .long sys_nanosleep -+ .long sys_mremap -+ .long sys_setresuid16 -+ .long sys_getresuid16 /* 165 */ -+ .long sys_getpagesize -+ .long sys_ni_syscall /* old sys_query_module */ -+ .long sys_poll -+ .long sys_nfsservctl -+ .long sys_setresgid16 /* 170 */ -+ .long sys_getresgid16 -+ .long sys_prctl -+ .long sys_rt_sigreturn -+ .long sys_rt_sigaction -+ .long sys_rt_sigprocmask /* 175 */ -+ .long sys_rt_sigpending -+ .long sys_rt_sigtimedwait -+ .long sys_rt_sigqueueinfo -+ .long sys_rt_sigsuspend -+ .long sys_pread64 /* 180 */ -+ .long sys_pwrite64 -+ .long sys_lchown16; -+ .long sys_getcwd -+ .long sys_capget -+ .long sys_capset /* 185 */ -+ .long sys_sigaltstack -+ .long sys_sendfile -+ .long sys_ni_syscall /* streams1 */ -+ .long sys_ni_syscall /* streams2 */ -+ .long sys_vfork /* 190 */ -+ .long sys_getrlimit -+ .long sys_mmap2 -+ .long sys_truncate64 -+ .long sys_ftruncate64 -+ .long sys_stat64 /* 195 */ -+ .long sys_lstat64 -+ .long sys_fstat64 -+ .long sys_chown -+ .long sys_getuid -+ .long sys_getgid /* 200 */ -+ .long sys_geteuid -+ .long sys_getegid -+ .long sys_setreuid -+ .long sys_setregid -+ .long sys_getgroups /* 205 */ -+ .long sys_setgroups -+ .long sys_fchown -+ .long sys_setresuid -+ .long sys_getresuid -+ .long sys_setresgid /* 210 */ -+ .long sys_getresgid -+ .long sys_lchown -+ .long sys_setuid -+ .long sys_setgid -+ .long sys_setfsuid /* 215 */ -+ .long sys_setfsgid -+ .long sys_pivot_root -+ .long sys_ni_syscall -+ .long sys_ni_syscall -+ .long sys_getdents64 /* 220 */ -+ .long sys_gettid -+ .long sys_tkill -+ .long sys_setxattr -+ .long sys_lsetxattr -+ .long sys_fsetxattr /* 225 */ -+ .long sys_getxattr -+ .long sys_lgetxattr -+ .long sys_fgetxattr -+ .long sys_listxattr -+ .long sys_llistxattr /* 230 */ -+ .long sys_flistxattr -+ .long sys_removexattr -+ .long sys_lremovexattr -+ .long sys_fremovexattr -+ .long sys_futex /* 235 */ -+ .long sys_sendfile64 -+ .long sys_mincore -+ .long sys_madvise -+ .long sys_fcntl64 -+ .long sys_readahead /* 240 */ -+ .long sys_io_setup -+ .long sys_io_destroy -+ .long sys_io_getevents -+ .long sys_io_submit -+ .long sys_io_cancel /* 245 */ -+ .long sys_fadvise64 -+ .long sys_exit_group -+ .long sys_lookup_dcookie -+ .long sys_epoll_create -+ .long sys_epoll_ctl /* 250 */ -+ .long sys_epoll_wait -+ .long sys_remap_file_pages -+ .long sys_set_tid_address -+ .long sys_timer_create -+ .long sys_timer_settime /* 255 */ -+ .long sys_timer_gettime -+ .long sys_timer_getoverrun -+ .long sys_timer_delete -+ .long sys_clock_settime -+ .long sys_clock_gettime /* 260 */ -+ .long sys_clock_getres -+ .long sys_clock_nanosleep -+ .long sys_statfs64 -+ .long sys_fstatfs64 -+ .long sys_tgkill /* 265 */ -+ .long sys_utimes -+ .long sys_fadvise64_64 -+ .long sys_mbind -+ .long sys_get_mempolicy -+ .long sys_set_mempolicy /* 270 */ -+ .long sys_mq_open -+ .long sys_mq_unlink -+ .long sys_mq_timedsend -+ .long sys_mq_timedreceive -+ .long sys_mq_notify /* 275 */ -+ .long sys_mq_getsetattr -+ .long sys_waitid -+ .long sys_ni_syscall /* for sys_vserver */ -+ .long sys_add_key -+ .long sys_request_key /* 280 */ -+ .long sys_keyctl -+ .long sys_ioprio_set -+ .long sys_ioprio_get -+ .long sys_inotify_init -+ .long sys_inotify_add_watch /* 285 */ -+ .long sys_inotify_rm_watch -+ .long sys_migrate_pages -+ .long sys_openat -+ .long sys_mkdirat -+ .long sys_mknodat /* 290 */ -+ .long sys_fchownat -+ .long sys_futimesat -+ .long sys_fstatat64 -+ .long sys_unlinkat -+ .long sys_renameat /* 295 */ -+ .long sys_linkat -+ .long sys_symlinkat -+ .long sys_readlinkat -+ .long sys_fchmodat -+ .long sys_faccessat /* 300 */ -+ .long sys_ni_syscall /* Reserved for pselect6 */ -+ .long sys_ni_syscall /* Reserved for ppoll */ -+ .long sys_unshare -+ .long sys_set_robust_list -+ .long sys_get_robust_list /* 305 */ -+ .long sys_splice -+ .long sys_sync_file_range -+ .long sys_tee -+ .long sys_vmsplice -+ .long sys_move_pages /* 310 */ -+ ---- /dev/null -+++ b/arch/m68k/coldfire/head.S -@@ -0,0 +1,474 @@ -+/* -+ * head.S is the MMU enabled ColdFire specific initial boot code -+ * -+ * Ported to ColdFire by -+ * Matt Waddel Matt.Waddel@freescale.com -+ * Kurt Mahan kmahan@freescale.com -+ * Copyright Freescale Semiconductor, Inc. 2007 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * Parts of this code came from arch/m68k/kernel/head.S -+ */ -+#include <linux/linkage.h> -+#include <linux/init.h> -+#include <asm/bootinfo.h> -+#include <asm/setup.h> -+#include <asm/entry.h> -+#include <asm/pgtable.h> -+#include <asm/page.h> -+#include <asm/coldfire.h> -+#include <asm/mcfuart.h> -+#include <asm/cfcache.h> -+ -+#define DEBUG -+ -+.globl kernel_pg_dir -+.globl availmem -+.globl set_context -+.globl set_fpga -+ -+#ifdef DEBUG -+/* When debugging use readable names for labels */ -+#ifdef __STDC__ -+#define L(name) .head.S.##name -+#else -+#define L(name) .head.S./**/name -+#endif -+#else -+#ifdef __STDC__ -+#define L(name) .L##name -+#else -+#define L(name) .L/**/name -+#endif -+#endif -+ -+/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */ -+#ifndef __INITDATA -+#define __INITDATA .data -+#define __FINIT .previous -+#endif -+ -+/* -+ * Setup ACR mappings to provide the following memory map: -+ * Data -+ * 0xA0000000 -> 0xAFFFFFFF [0] NO CACHE / PRECISE / SUPER ONLY -+ * 0xFC000000 -> 0xFCFFFFFF [1] NO CACHE / PRECISE / SUPER ONLY -+ * Code -+ * None currently (mapped via TLBs) -+ */ -+ -+#define ACR0_DEFAULT #0xA00FA048 /* ACR0 default value */ -+#define ACR1_DEFAULT #0xFC00A040 /* ACR1 default value */ -+#define ACR2_DEFAULT #0x00000000 /* ACR2 default value */ -+#define ACR3_DEFAULT #0x00000000 /* ACR3 default value */ -+ -+/* ACR mapping for FPGA (maps 0) */ -+#define ACR0_FPGA #0x000FA048 /* ACR0 enable FPGA */ -+ -+/* Several macros to make the writing of subroutines easier: -+ * - func_start marks the beginning of the routine which setups the frame -+ * register and saves the registers, it also defines another macro -+ * to automatically restore the registers again. -+ * - func_return marks the end of the routine and simply calls the prepared -+ * macro to restore registers and jump back to the caller. -+ * - func_define generates another macro to automatically put arguments -+ * onto the stack call the subroutine and cleanup the stack again. -+ */ -+ -+.macro load_symbol_address symbol,register -+ movel #\symbol,\register -+.endm -+ -+.macro func_start name,saveregs,savesize,stack=0 -+L(\name): -+ linkw %a6,#-\stack -+ subal #(\savesize),%sp -+ moveml \saveregs,%sp@ -+.set stackstart,-\stack -+ -+.macro func_return_\name -+ moveml %sp@,\saveregs -+ addal #(\savesize),%sp -+ unlk %a6 -+ rts -+.endm -+.endm -+ -+.macro func_return name -+ func_return_\name -+.endm -+ -+.macro func_call name -+ jbsr L(\name) -+.endm -+ -+.macro move_stack nr,arg1,arg2,arg3,arg4 -+.if \nr -+ move_stack "(\nr-1)",\arg2,\arg3,\arg4 -+ movel \arg1,%sp@- -+.endif -+.endm -+ -+.macro func_define name,nr=0 -+.macro \name arg1,arg2,arg3,arg4 -+ move_stack \nr,\arg1,\arg2,\arg3,\arg4 -+ func_call \name -+.if \nr -+ lea %sp@(\nr*4),%sp -+.endif -+.endm -+.endm -+ -+func_define serial_putc,1 -+ -+.macro putc ch -+ pea \ch -+ func_call serial_putc -+ addql #4,%sp -+.endm -+ -+.macro dputc ch -+#ifdef DEBUG -+ putc \ch -+#endif -+.endm -+ -+func_define putn,1 -+ -+.macro dputn nr -+#ifdef DEBUG -+ putn \nr -+#endif -+.endm -+ -+/* -+ mmu_map - creates a new TLB entry -+ -+ virt_addr Must be on proper boundary -+ phys_addr Must be on proper boundary -+ itlb MMUOR_ITLB if instruction TLB or 0 -+ asid address space ID -+ shared_global MMUTR_SG if shared between different ASIDs or 0 -+ size_code MMUDR_SZ1M 1 MB -+ MMUDR_SZ4K 4 KB -+ MMUDR_SZ8K 8 KB -+ MMUDR_SZ16M 16 MB -+ cache_mode MMUDR_INC instruction non-cacheable -+ MMUDR_IC instruction cacheable -+ MMUDR_DWT data writethrough -+ MMUDR_DCB data copyback -+ MMUDR_DNCP data non-cacheable, precise -+ MMUDR_DNCIP data non-cacheable, imprecise -+ super_prot MMUDR_SP if user mode generates exception or 0 -+ readable MMUDR_R if permits read access (data TLB) or 0 -+ writable MMUDR_W if permits write access (data TLB) or 0 -+ executable MMUDR_X if permits execute access (instruction TLB) or 0 -+ locked MMUDR_LK prevents TLB entry from being replaced or 0 -+ temp_data_reg a data register to use for temporary values -+*/ -+.macro mmu_map virt_addr,phys_addr,itlb,asid,shared_global,size_code,cache_mode,super_prot,readable,writable,executable,locked,temp_data_reg -+ /* Set up search of TLB. */ -+ movel #(\virt_addr+1), \temp_data_reg -+ movel \temp_data_reg, MMUAR -+ /* Search. */ -+ movel #(MMUOR_STLB + MMUOR_ADR +\itlb), \temp_data_reg -+ movew \temp_data_reg, (MMUOR) -+ /* Set up tag value. */ -+ movel #(\virt_addr + \asid + \shared_global + MMUTR_V), \temp_data_reg -+ movel \temp_data_reg, MMUTR -+ /* Set up data value. */ -+ movel #(\phys_addr + \size_code + \cache_mode + \super_prot + \readable + \writable + \executable + \locked), \temp_data_reg -+ movel \temp_data_reg, MMUDR -+ /* Save it. */ -+ movel #(MMUOR_ACC + MMUOR_UAA + \itlb), \temp_data_reg -+ movew \temp_data_reg, (MMUOR) -+.endm /* mmu_map */ -+ -+.macro mmu_unmap virt_addr,itlb,temp_data_reg -+ /* Set up search of TLB. */ -+ movel #(\virt_addr+1), \temp_data_reg -+ movel \temp_data_reg, MMUAR -+ /* Search. */ -+ movel #(MMUOR_STLB + MMUOR_ADR +\itlb), \temp_data_reg -+ movew \temp_data_reg, (MMUOR) -+ /* Test for hit. */ -+ movel MMUSR,\temp_data_reg -+ btst #MMUSR_HITN,\temp_data_reg -+ beq 1f -+ /* Read the TLB. */ -+ movel #(MMUOR_RW + MMUOR_ACC +\itlb), \temp_data_reg -+ movew \temp_data_reg, (MMUOR) -+ movel MMUSR,\temp_data_reg -+ /* Set up tag value. */ -+ movel #0, \temp_data_reg -+ movel \temp_data_reg, MMUTR -+ /* Set up data value. */ -+ movel #0, \temp_data_reg -+ movel \temp_data_reg, MMUDR -+ /* Save it. */ -+ movel #(MMUOR_ACC + MMUOR_UAA + \itlb), \temp_data_reg -+ movew \temp_data_reg, (MMUOR) -+1: -+.endm /* mmu_unmap */ -+ -+/* .text */ -+.section ".text.head","ax" -+ENTRY(_stext) -+/* Version numbers of the bootinfo interface -- if we later pass info -+ * from boot ROM we might want to put something real here. -+ * -+ * The area from _stext to _start will later be used as kernel pointer table -+ */ -+ bras 1f /* Jump over bootinfo version numbers */ -+ -+ .long BOOTINFOV_MAGIC -+ .long 0 -+1: jmp __start-0x80000000 -+ -+.equ kernel_pg_dir,_stext -+.equ .,_stext+0x1000 -+ -+ENTRY(_start) -+ jra __start -+__INIT -+ENTRY(__start) -+ -+/* Save the location of u-boot info - cmd line, bd_info, etc. */ -+ movel %a7,%a4 /* Don't use %a4 before cf_early_init */ -+ addl #0x80000004,%a4 /* 0x80000004= 1 stack push + high mem offset */ -+ -+/* Setup initial stack pointer */ -+ movel #0x40001000,%sp -+ -+/* Clear usp */ -+ subl %a0,%a0 -+ movel %a0,%usp -+ -+ movel #(MCF_RAMBAR1 + 0x221), %d0 -+ movec %d0, %rambar1 -+ movew #0x2700,%sr -+ -+ movel #(MMU_BASE+1),%d0 -+ movecl %d0,%mmubar -+ movel #MMUOR_CA,%a0 /* Clear tlb entries */ -+ movew %a0,(MMUOR) -+ movel #(MMUOR_CA + MMUOR_ITLB),%a0 /* Use ITLB for searches */ -+ movew %a0,(MMUOR) -+ movel #0,%a0 /* Clear Addr Space User ID */ -+ movecl %a0,%asid -+ -+/* setup ACRs */ -+ movel ACR0_DEFAULT, %d0 /* ACR0 (DATA) setup */ -+ movec %d0, %acr0 -+ movel ACR1_DEFAULT, %d0 /* ACR1 (DATA) setup */ -+ movec %d0, %acr1 -+ movel ACR2_DEFAULT, %d0 /* ACR2 (CODE) setup */ -+ movec %d0, %acr2 -+ movel ACR3_DEFAULT, %d0 /* ACR3 (CODE) setup */ -+ movec %d0, %acr3 -+ -+ /* If you change the memory size to another value make a matching -+ change in paging_init(cf-mmu.c) to zones_size[]. */ -+ -+ /* Map 256MB as code */ -+ mmu_map (PAGE_OFFSET+0*0x1000000), (PHYS_OFFSET+0*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+1*0x1000000), (PHYS_OFFSET+1*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+2*0x1000000), (PHYS_OFFSET+2*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+3*0x1000000), (PHYS_OFFSET+3*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+4*0x1000000), (PHYS_OFFSET+4*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+5*0x1000000), (PHYS_OFFSET+5*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+6*0x1000000), (PHYS_OFFSET+6*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+7*0x1000000), (PHYS_OFFSET+7*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+8*0x1000000), (PHYS_OFFSET+8*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+9*0x1000000), (PHYS_OFFSET+9*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+10*0x1000000), (PHYS_OFFSET+10*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+11*0x1000000), (PHYS_OFFSET+11*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+12*0x1000000), (PHYS_OFFSET+12*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+13*0x1000000), (PHYS_OFFSET+13*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+14*0x1000000), (PHYS_OFFSET+14*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+15*0x1000000), (PHYS_OFFSET+15*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_IC, MMUDR_SP, \ -+ 0, 0, MMUDR_X, MMUDR_LK, %d0 -+ -+ /* Map 256MB as data also */ -+ mmu_map (PAGE_OFFSET+0*0x1000000), (PHYS_OFFSET+0*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+1*0x1000000), (PHYS_OFFSET+1*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+2*0x1000000), (PHYS_OFFSET+2*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+3*0x1000000), (PHYS_OFFSET+3*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+4*0x1000000), (PHYS_OFFSET+4*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+5*0x1000000), (PHYS_OFFSET+5*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+6*0x1000000), (PHYS_OFFSET+6*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+7*0x1000000), (PHYS_OFFSET+7*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+8*0x1000000), (PHYS_OFFSET+8*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+9*0x1000000), (PHYS_OFFSET+9*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+10*0x1000000), (PHYS_OFFSET+10*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+11*0x1000000), (PHYS_OFFSET+11*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+12*0x1000000), (PHYS_OFFSET+12*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+13*0x1000000), (PHYS_OFFSET+13*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+14*0x1000000), (PHYS_OFFSET+14*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ mmu_map (PAGE_OFFSET+15*0x1000000), (PHYS_OFFSET+15*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, MMUDR_LK, %d0 -+ -+ /* Do unity mapping to enable the MMU. Map first 16 MB in place as -+ code (delete TLBs after MMU is enabled and we are executing in high -+ memory). */ -+ mmu_map (PHYS_OFFSET+0*0x1000000), (PHYS_OFFSET+0*0x1000000), \ -+ MMUOR_ITLB, 0, MMUTR_SG, MMUDR_SZ16M, MMUDR_INC, MMUDR_SP, 0, \ -+ 0, MMUDR_X, 0, %d0 -+ /* Map first 16 MB as data too. */ -+ mmu_map (PHYS_OFFSET+0*0x1000000), (PHYS_OFFSET+0*0x1000000), 0, 0, \ -+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \ -+ 0, 0, %d0 -+ -+ /* Turn on MMU */ -+ movel #(MMUCR_EN),%a0 -+ movel %a0,MMUCR -+ nop /* This synchs the pipeline after a write to MMUCR */ -+ -+ movel #__running_high,%a0 /* Get around PC-relative addressing. */ -+ jmp %a0@ -+ -+ENTRY(__running_high) -+ load_symbol_address _stext,%sp -+ movel L(memory_start),%a0 -+ movel %a0,availmem -+ load_symbol_address L(phys_kernel_start),%a0 -+ load_symbol_address _stext,%a1 -+ subl #_stext,%a1 -+ addl #PAGE_OFFSET,%a1 -+ movel %a1,%a0@ -+ -+ /* Unmap first 16 MB, code and data. */ -+ mmu_unmap (PHYS_OFFSET+0*0x1000000), MMUOR_ITLB, %d0 -+ mmu_unmap (PHYS_OFFSET+0*0x1000000), 0, %d0 -+ -+/* Setup initial stack pointer */ -+ lea init_task,%a2 -+ lea init_thread_union+THREAD_SIZE,%sp -+ subl %a6,%a6 /* clear a6 for gdb */ -+ -+#ifdef CONFIG_MCF_USER_HALT -+/* Setup debug control reg to allow halts from user space */ -+ lea wdbg_uhe,%a0 -+ wdebug (%a0) -+#endif -+ -+ movel %a4,uboot_info_stk /* save uboot info to variable */ -+ jsr cf_early_init -+ jmp start_kernel -+ -+.section ".text.head","ax" -+set_context: -+func_start set_context,%d0,(1*4) -+ movel 12(%sp),%d0 -+ movec %d0,%asid -+func_return set_context -+ -+/* -+ * set_fpga(addr,val) -+ * -+ * Map in 0x00000000 -> 0x0fffffff and then do the write. -+ */ -+set_fpga: -+ movew %sr,%d1 -+ movew #0x2700,%sr -+ movel ACR0_FPGA, %d0 -+ movec %d0, %acr0 -+ nop -+ moveal 4(%sp),%a0 -+ movel 8(%sp),%a0@ -+ movel ACR0_DEFAULT, %d0 -+ movec %d0, %acr0 -+ nop -+ movew %d1,%sr -+ rts -+ -+ .data -+ .align 4 -+ -+availmem: -+ .long 0 -+L(phys_kernel_start): -+ .long PAGE_OFFSET -+L(kernel_end): -+ .long 0 -+L(memory_start): -+ .long PAGE_OFFSET_RAW -+ -+#ifdef CONFIG_MCF_USER_HALT -+/* -+ * Enable User Halt Enable in the debug control register. -+ */ -+wdbg_uhe: -+ .word 0x2c80 /* DR0 */ -+ .word 0x00b0 /* 31:16 */ -+ .word 0x0400 /* 15:0 -- enable UHE */ -+ .word 0x0000 /* unused */ -+#endif -+ -+ ---- /dev/null -+++ b/arch/m68k/coldfire/ints.c -@@ -0,0 +1,384 @@ -+/* -+ * linux/arch/m68k/coldfire/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) -+ * Matt Waddel Matt.Waddel@freescale.com -+ * Copyright Freescale Semiconductor, Inc. 2007 -+ * Kurt Mahan kmahan@freescale.com -+ * -+ * Based on: -+ * linux/arch/m68k/kernel/ints.c & -+ * linux/arch/m68knommu/5307/ints.c -+ * -+ * 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/seq_file.h> -+#include <linux/interrupt.h> -+ -+#include <asm/system.h> -+#include <asm/irq.h> -+#include <asm/traps.h> -+#include <asm/page.h> -+#include <asm/machdep.h> -+#include <asm/irq_regs.h> -+ -+#include <asm/mcfsim.h> -+ -+/* -+ * IRQ Handler lists. -+ */ -+static struct irq_node *irq_list[SYS_IRQS]; -+static struct irq_controller *irq_controller[SYS_IRQS]; -+static int irq_depth[SYS_IRQS]; -+ -+/* -+ * IRQ Controller -+ */ -+#ifdef CONFIG_M54455 -+void m5445x_irq_enable(unsigned int irq); -+void m5445x_irq_disable(unsigned int irq); -+static struct irq_controller m5445x_irq_controller = { -+ .name = "M5445X", -+ .lock = SPIN_LOCK_UNLOCKED, -+ .enable = m5445x_irq_enable, -+ .disable = m5445x_irq_disable, -+}; -+#endif -+ -+#define POOL_SIZE SYS_IRQS -+static struct irq_node pool[POOL_SIZE]; -+static struct irq_node *get_irq_node(void); -+ -+/* The number of spurious interrupts */ -+unsigned int num_spurious; -+asmlinkage void handle_badint(struct pt_regs *regs); -+ -+/* -+ * void init_IRQ(void) -+ * -+ * This function should be called during kernel startup to initialize -+ * the IRQ handling routines. -+ */ -+void __init init_IRQ(void) -+{ -+ int i; -+ -+#ifdef CONFIG_M54455 -+ for (i = 0; i < SYS_IRQS; i++) -+ irq_controller[i] = &m5445x_irq_controller; -+#endif -+} -+ -+/* -+ * process_int(unsigned long vec, struct pt_regs *fp) -+ * -+ * Process an interrupt. Called from entry.S. -+ */ -+asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) -+{ -+ struct pt_regs *old_regs; -+ struct irq_node *node; -+ old_regs = set_irq_regs(fp); -+ kstat_cpu(0).irqs[vec]++; -+ -+ node = irq_list[vec]; -+ if (!node) -+ handle_badint(fp); -+ else { -+ do { -+ node->handler(vec, node->dev_id); -+ node = node->next; -+ } while (node); -+ } -+ -+ set_irq_regs(old_regs); -+} -+ -+/* -+ * show_interrupts( struct seq_file *p, void *v) -+ * -+ * Called to show all the current interrupt information. -+ */ -+int show_interrupts(struct seq_file *p, void *v) -+{ -+ struct irq_controller *contr; -+ struct irq_node *node; -+ int i = *(loff_t *) v; -+ -+ if ((i < NR_IRQS) && (irq_list[i])) { -+ contr = irq_controller[i]; -+ node = irq_list[i]; -+ seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, -+ kstat_cpu(0).irqs[i], node->devname); -+ while ((node = node->next)) -+ seq_printf(p, ", %s", node->devname); -+ -+ seq_printf(p, "\n"); -+ } -+ -+ return 0; -+} -+ -+/* -+ * get_irq_node(void) -+ * -+ * Get an irq node from the pool. -+ */ -+struct irq_node *get_irq_node(void) -+{ -+ struct irq_node *p = pool; -+ int i; -+ -+ for (i = 0; i < POOL_SIZE; i++, p++) { -+ if (!p->handler) { -+ memset(p, 0, sizeof(struct irq_node)); -+ return p; -+ } -+ } -+ printk(KERN_INFO "%s(%s:%d): No more irq nodes, I suggest you \ -+ increase POOL_SIZE", __FUNCTION__, __FILE__, __LINE__); -+ return NULL; -+} -+ -+void init_irq_proc(void) -+{ -+ /* Insert /proc/irq driver here */ -+} -+ -+int setup_irq(unsigned int irq, struct irq_node *node) -+{ -+ struct irq_controller *contr; -+ struct irq_node **prev; -+ unsigned long flags; -+ -+ if (irq >= NR_IRQS || !irq_controller[irq]) { -+ printk("%s: Incorrect IRQ %d from %s\n", -+ __FUNCTION__, irq, node->devname); -+ return -ENXIO; -+ } -+ -+ contr = irq_controller[irq]; -+ spin_lock_irqsave(&contr->lock, flags); -+ -+ prev = irq_list + irq; -+ if (*prev) { -+ /* Can't share interrupts unless both agree to */ -+ if (!((*prev)->flags & node->flags & IRQF_SHARED)) { -+ spin_unlock_irqrestore(&contr->lock, flags); -+ return -EBUSY; -+ } -+ while (*prev) -+ prev = &(*prev)->next; -+ } -+ -+ if (!irq_list[irq]) { -+ if (contr->startup) -+ contr->startup(irq); -+ else -+ contr->enable(irq); -+ } -+ node->next = NULL; -+ *prev = node; -+ -+ spin_unlock_irqrestore(&contr->lock, flags); -+ -+ return 0; -+} -+ -+int request_irq(unsigned int irq, -+ irq_handler_t handler, -+ unsigned long flags, const char *devname, void *dev_id) -+{ -+ struct irq_node *node = get_irq_node(); -+ int res; -+ -+ if (!node) -+ return -ENOMEM; -+ -+ node->handler = handler; -+ node->flags = flags; -+ node->dev_id = dev_id; -+ node->devname = devname; -+ -+ res = setup_irq(irq, node); -+ if (res) -+ node->handler = NULL; -+ -+ return res; -+} -+EXPORT_SYMBOL(request_irq); -+ -+void free_irq(unsigned int irq, void *dev_id) -+{ -+ struct irq_controller *contr; -+ struct irq_node **p, *node; -+ unsigned long flags; -+ -+ if (irq >= NR_IRQS || !irq_controller[irq]) { -+ printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); -+ return; -+ } -+ -+ contr = irq_controller[irq]; -+ spin_lock_irqsave(&contr->lock, flags); -+ -+ p = irq_list + irq; -+ while ((node = *p)) { -+ if (node->dev_id == dev_id) -+ break; -+ p = &node->next; -+ } -+ -+ if (node) { -+ *p = node->next; -+ node->handler = NULL; -+ } else -+ printk(KERN_DEBUG "%s: Removing probably wrong IRQ %d\n", -+ __FUNCTION__, irq); -+ -+ if (!irq_list[irq]) { -+ if (contr->shutdown) -+ contr->shutdown(irq); -+ else -+ contr->disable(irq); -+ } -+ -+ spin_unlock_irqrestore(&contr->lock, flags); -+} -+EXPORT_SYMBOL(free_irq); -+ -+void enable_irq(unsigned int irq) -+{ -+ struct irq_controller *contr; -+ unsigned long flags; -+ -+ if (irq >= NR_IRQS || !irq_controller[irq]) { -+ printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); -+ return; -+ } -+ -+ contr = irq_controller[irq]; -+ spin_lock_irqsave(&contr->lock, flags); -+ if (irq_depth[irq]) { -+ if (!--irq_depth[irq]) { -+ if (contr->enable) -+ contr->enable(irq); -+ } -+ } else -+ WARN_ON(1); -+ spin_unlock_irqrestore(&contr->lock, flags); -+} -+EXPORT_SYMBOL(enable_irq); -+ -+void disable_irq(unsigned int irq) -+{ -+ struct irq_controller *contr; -+ unsigned long flags; -+ -+ if (irq >= NR_IRQS || !irq_controller[irq]) { -+ printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); -+ return; -+ } -+ -+ contr = irq_controller[irq]; -+ spin_lock_irqsave(&contr->lock, flags); -+ if (!irq_depth[irq]++) { -+ if (contr->disable) -+ contr->disable(irq); -+ } -+ spin_unlock_irqrestore(&contr->lock, flags); -+} -+EXPORT_SYMBOL(disable_irq); -+ -+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 handle_badint(struct pt_regs *regs) -+{ -+ kstat_cpu(0).irqs[0]++; -+ num_spurious++; -+ printk(KERN_DEBUG "unexpected interrupt from %u\n", regs->vector); -+} -+EXPORT_SYMBOL(handle_badint); -+ -+#ifdef CONFIG_M54455 -+/* -+ * M5445X Implementation -+ */ -+void m5445x_irq_enable(unsigned int irq) -+{ -+ /* enable the interrupt hardware */ -+ if (irq < 64) -+ return; -+ -+ /* adjust past non-hardware ints */ -+ irq -= 64; -+ -+ /* check for eport */ -+ if ((irq > 0) && (irq < 8)) { -+ /* enable eport */ -+ MCF_EPORT_EPPAR &= ~(3 << (irq*2)); /* level */ -+ MCF_EPORT_EPDDR &= ~(1 << irq); /* input */ -+ MCF_EPORT_EPIER |= 1 << irq; /* irq enabled */ -+ } -+ -+ if (irq < 64) { -+ /* controller 0 */ -+ MCF_INTC0_ICR(irq) = 0x02; -+ MCF_INTC0_CIMR = irq; -+ } else { -+ /* controller 1 */ -+ irq -= 64; -+ MCF_INTC1_ICR(irq) = 0x02; -+ MCF_INTC1_CIMR = irq; -+ } -+} -+ -+void m5445x_irq_disable(unsigned int irq) -+{ -+ /* disable the interrupt hardware */ -+ if (irq < 64) -+ return; -+ -+ /* adjust past non-hardware ints */ -+ irq -= 64; -+ -+ /* check for eport */ -+ if ((irq > 0) && (irq < 8)) { -+ /* disable eport */ -+ MCF_EPORT_EPIER &= ~(1 << irq); -+ } -+ -+ if (irq < 64) { -+ /* controller 0 */ -+ MCF_INTC0_ICR(irq) = 0x00; -+ MCF_INTC0_SIMR = irq; -+ } else { -+ /* controller 1 */ -+ irq -= 64; -+ MCF_INTC1_ICR(irq) = 0x00; -+ MCF_INTC1_SIMR = irq; -+ } -+} -+#endif ---- /dev/null -+++ b/arch/m68k/coldfire/iomap.c -@@ -0,0 +1,54 @@ -+/* -+ * arch/m68k/coldfire/iomap.c -+ * -+ * Generic coldfire iomap interface -+ * -+ * Based on the sh64 iomap.c by Paul Mundt. -+ * -+ * 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/pci.h> -+#include <asm/io.h> -+ -+void __iomem *__attribute__ ((weak)) -+ioport_map(unsigned long port, unsigned int len) -+{ -+ return (void __iomem *)port; -+} -+EXPORT_SYMBOL(pci_iomap); -+ -+void ioport_unmap(void __iomem *addr) -+{ -+ /* Nothing .. */ -+} -+EXPORT_SYMBOL(pci_iounmap); -+ -+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) -+{ -+ unsigned long start = pci_resource_start(dev, bar); -+ unsigned long len = pci_resource_len(dev, bar); -+ unsigned long flags = pci_resource_flags(dev, bar); -+printk(KERN_INFO "PCI_IOMAP: BAR=%d START=0x%lx LEN=0x%lx FLAGS=0x%lx\n", -+ bar, start, len, flags); -+ -+ if (!len) -+ return NULL; -+ if (max && len > max) -+ len = max; -+ if (flags & IORESOURCE_IO) -+ return ioport_map(start, len); -+ if (flags & IORESOURCE_MEM) -+ return (void __iomem *)start; -+ -+ /* What? */ -+ return NULL; -+} -+EXPORT_SYMBOL(ioport_map); -+ -+void pci_iounmap(struct pci_dev *dev, void __iomem *addr) -+{ -+ /* Nothing .. */ -+} -+EXPORT_SYMBOL(ioport_unmap); ---- /dev/null -+++ b/arch/m68k/coldfire/mcf5445x-pci.c -@@ -0,0 +1,427 @@ -+/* -+ * arch/m68k/coldfire/mcf5445x-pci.c -+ * -+ * Coldfire M5445x specific PCI implementation. -+ * -+ * Copyright (c) 2007 Freescale Semiconductor, Inc. -+ * Kurt Mahan <kmahan@freescale.com> -+ */ -+ -+#include <linux/delay.h> -+#include <linux/pci.h> -+ -+#include <asm/mcfsim.h> -+#include <asm/pci.h> -+#include <asm/irq.h> -+ -+/* -+ * Layout MCF5445x to PCI memory mappings: -+ * -+ * WIN MCF5445x PCI TYPE -+ * --- -------- --- ---- -+ * [0] 0xA0000000 -> 0xA7FFFFFF 0xA0000000 -> 0xA7FFFFFF MEM -+ * [1] 0xA8000000 -> 0xABFFFFFF 0xA8000000 -> 0xABFFFFFF MEM -+ * [2] 0xAC000000 -> 0xAFFFFFFF 0xAC000000 -> 0xAFFFFFFF IO -+ */ -+ -+#define MCF5445X_PCI_MEM_BASE 0xA0000000 -+#define MCF5445X_PCI_MEM_SIZE 0x0C000000 -+ -+#define MCF5445X_PCI_CONFIG_BASE 0xAC000000 -+#define MCF5445X_PCI_CONFIG_SIZE 0x04000000 -+ -+#define MCF5445X_PCI_IO_BASE 0xAC000000 -+#define MCF5445X_PCI_IO_SIZE 0x04000000 -+ -+/* PCI Bus memory resource block */ -+struct resource pci_iomem_resource = { -+ .name = "PCI memory space", -+ .start = MCF5445X_PCI_MEM_BASE, -+ .flags = IORESOURCE_MEM, -+ .end = MCF5445X_PCI_MEM_BASE + MCF5445X_PCI_MEM_SIZE - 1 -+}; -+ -+/* PCI Bus ioport resource block */ -+struct resource pci_ioport_resource = { -+ .name = "PCI I/O space", -+ .start = MCF5445X_PCI_IO_BASE, -+ .flags = IORESOURCE_IO, -+ .end = MCF5445X_PCI_IO_BASE + MCF5445X_PCI_IO_SIZE - 1 -+}; -+ -+/* -+ * The M54455EVB multiplexes all the PCI interrupts via -+ * the FPGA and routes them to a single interrupt. The -+ * PCI spec requires all PCI interrupt routines be smart -+ * enough to sort out their own interrupts. -+ * The interrupt source from the FPGA is configured -+ * to EPORT 3. -+ */ -+#define MCF5445X_PCI_IRQ 0x43 -+ -+#define PCI_SLOTS 4 -+ -+/* -+ * FPGA Info -+ */ -+#define FPGA_PCI_IRQ_ENABLE (u32 *)0x09000000 -+#define FPGA_PCI_IRQ_STATUS (u32 *)0x09000004 -+#define FPGA_PCI_IRQ_ROUTE (u32 *)0x0900000c -+#define FPGA_SEVEN_LED (u32 *)0x09000014 -+ -+extern void set_fpga(u32 *addr, u32 val); -+ -+#ifdef DEBUG -+void mcf5445x_pci_dumpregs(void); -+#endif -+ -+/* -+ * static void mcf5445x_conf_device(struct pci_dev *dev) -+ * -+ * Machine dependent Configure the given device. -+ * -+ * Parameters: -+ * -+ * dev - the pci device. -+ */ -+void __init -+mcf5445x_conf_device(struct pci_dev *dev) -+{ -+ set_fpga(FPGA_PCI_IRQ_ENABLE, 0x0f); -+} -+ -+/* -+ * int mcf5445x_pci_config_read(unsigned int seg, unsigned int bus, -+ * unsigned int devfn, int reg, -+ * u32 *value) -+ * -+ * Read from PCI configuration space. -+ * -+ */ -+int mcf5445x_pci_config_read(unsigned int seg, unsigned int bus, -+ unsigned int devfn, int reg, int len, u32 *value) -+{ -+ u32 addr = MCF_PCI_PCICAR_BUSNUM(bus) | -+ MCF_PCI_PCICAR_DEVNUM(PCI_SLOT(devfn)) | -+ MCF_PCI_PCICAR_FUNCNUM(PCI_FUNC(devfn)) | -+ MCF_PCI_PCICAR_DWORD(reg) | -+ MCF_PCI_PCICAR_E; -+ -+ if ((bus > 255) || (devfn > 255) || (reg > 255)) { -+ *value = -1; -+ return -EINVAL; -+ } -+ -+ /* setup for config mode */ -+ MCF_PCI_PCICAR = addr; -+ __asm__ __volatile__("nop"); -+ -+ switch (len) { -+ case 1: -+ *value = *(volatile u8 *)(MCF5445X_PCI_CONFIG_BASE+(reg&3)); -+ break; -+ case 2: -+ *value = le16_to_cpu(*(volatile u16 *) -+ (MCF5445X_PCI_CONFIG_BASE + (reg&2))); -+ break; -+ case 4: -+ *value = le32_to_cpu(*(volatile u32 *) -+ (MCF5445X_PCI_CONFIG_BASE)); -+ break; -+ } -+ -+ /* clear config mode */ -+ MCF_PCI_PCICAR = ~MCF_PCI_PCICAR_E; -+ __asm__ __volatile__("nop"); -+ -+ return 0; -+} -+ -+/* -+ * int mcf5445x_pci_config_write(unsigned int seg, unsigned int bus, -+ * unsigned int devfn, int reg, -+ * u32 *value) -+ * -+ * Write to PCI configuration space -+ */ -+int mcf5445x_pci_config_write(unsigned int seg, unsigned int bus, -+ unsigned int devfn, int reg, int len, u32 value) -+{ -+ u32 addr = MCF_PCI_PCICAR_BUSNUM(bus) | -+ MCF_PCI_PCICAR_DEVNUM(PCI_SLOT(devfn)) | -+ MCF_PCI_PCICAR_FUNCNUM(PCI_FUNC(devfn)) | -+ MCF_PCI_PCICAR_DWORD(reg) | -+ MCF_PCI_PCICAR_E; -+ -+ if ((bus > 255) || (devfn > 255) || (reg > 255)) -+ return -EINVAL; -+ -+ /* setup for config mode */ -+ MCF_PCI_PCICAR = addr; -+ __asm__ __volatile__("nop"); -+ -+ switch (len) { -+ case 1: -+ *(volatile u8 *)(MCF5445X_PCI_CONFIG_BASE+(reg&3)) = (u8)value; -+ break; -+ case 2: -+ *(volatile u16 *)(MCF5445X_PCI_CONFIG_BASE+(reg&2)) = -+ cpu_to_le16((u16)value); -+ break; -+ case 4: -+ *(volatile u32 *)(MCF5445X_PCI_CONFIG_BASE) = -+ cpu_to_le32(value); -+ break; -+ } -+ -+ /* clear config mode */ -+ MCF_PCI_PCICAR = ~MCF_PCI_PCICAR_E; -+ __asm__ __volatile__("nop"); -+ -+ return 0; -+} -+ -+/* hardware operations */ -+static struct pci_raw_ops mcf5445x_pci_ops = { -+ .read = mcf5445x_pci_config_read, -+ .write = mcf5445x_pci_config_write, -+}; -+ -+/* -+ * irqreturn_t mcf5445x_pci_interrupt( int irq, void *dev) -+ * -+ * PCI controller interrupt handler. -+ */ -+static irqreturn_t -+mcf5445x_pci_interrupt(int irq, void *dev) -+{ -+ u32 status = MCF_PCI_PCIGSCR; -+#ifdef DEBUG -+ printk(KERN_INFO "PCI: Controller irq status=0x%08x\n", status); -+#endif -+ /* clear */ -+ MCF_PCI_PCIGSCR = status; -+ -+ return IRQ_HANDLED; -+} -+ -+/* -+ * irqreturn_t mcf5445x_pci_arb_interrupt( int irq, void *dev) -+ * -+ * PCI Arbiter interrupt handler. -+ */ -+static irqreturn_t -+mcf5445x_pci_arb_interrupt(int irq, void *dev) -+{ -+ u32 status = MCF_PCIARB_PASR; -+#ifdef DEBUG -+ printk(KERN_INFO "PCI: Arbiter irq status=0x%08x\n", status); -+#endif -+ /* clear */ -+ MCF_PCIARB_PASR = status; -+ return IRQ_HANDLED; -+} -+ -+/* -+ * struct pci_bus_info *init_mcf5445x_pci(void) -+ * -+ * Machine specific initialisation: -+ * -+ * - Allocate and initialise a 'pci_bus_info' structure -+ * - Initialize hardware -+ * -+ * Result: pointer to 'pci_bus_info' structure. -+ */ -+int __init -+init_mcf5445x_pci(void) -+{ -+ /* -+ * Initialize the PCI core -+ */ -+ -+ /* arbitration controller */ -+ MCF_PCIARB_PACR = MCF_PCIARB_PACR_INTMPRI | -+ MCF_PCIARB_PACR_EXTMPRI(0x0f) | -+ MCF_PCIARB_PACR_INTMINTEN | -+ MCF_PCIARB_PACR_EXTMINTEN(0x0f); -+ -+ /* pci pin assignment regs */ -+ MCF_GPIO_PAR_PCI = MCF_GPIO_PAR_PCI_GNT0 | -+ MCF_GPIO_PAR_PCI_GNT1 | -+ MCF_GPIO_PAR_PCI_GNT2 | -+ MCF_GPIO_PAR_PCI_GNT3_GNT3 | -+ MCF_GPIO_PAR_PCI_REQ0 | -+ MCF_GPIO_PAR_PCI_REQ1 | -+ MCF_GPIO_PAR_PCI_REQ2 | -+ MCF_GPIO_PAR_PCI_REQ3_REQ3; -+ -+ /* target control reg */ -+ MCF_PCI_PCITCR = MCF_PCI_PCITCR_P | -+ MCF_PCI_PCITCR_WCT(8); -+ -+ /* PCI MEM address */ -+ MCF_PCI_PCIIW0BTAR = 0xA007A000; -+ -+ /* PCI MEM address */ -+ MCF_PCI_PCIIW1BTAR = 0xA803A800; -+ -+ /* PCI IO address */ -+ MCF_PCI_PCIIW2BTAR = 0xAC03AC00; -+ -+ /* window control */ -+ MCF_PCI_PCIIWCR = MCF_PCI_PCIIWCR_WINCTRL0_ENABLE | -+ MCF_PCI_PCIIWCR_WINCTRL0_MEMREAD | -+ MCF_PCI_PCIIWCR_WINCTRL1_ENABLE | -+ MCF_PCI_PCIIWCR_WINCTRL1_MEMREAD | -+ MCF_PCI_PCIIWCR_WINCTRL2_ENABLE | -+ MCF_PCI_PCIIWCR_WINCTRL2_IO; -+ -+ /* initiator control reg */ -+ MCF_PCI_PCIICR = 0x00ff; -+ -+ /* type 0 - command */ -+ MCF_PCI_PCISCR = MCF_PCI_PCISCR_MW | /* mem write/inval */ -+ MCF_PCI_PCISCR_B | /* bus master enable */ -+ MCF_PCI_PCISCR_M; /* mem access enable */ -+ -+ /* type 0 - config reg */ -+ MCF_PCI_PCICR1 = MCF_PCI_PCICR1_CACHELINESIZE(8) | -+ MCF_PCI_PCICR1_LATTIMER(0xff); -+ -+ /* type 0 - config 2 reg */ -+ MCF_PCI_PCICR2 = 0; -+ -+ /* target control reg */ -+ MCF_PCI_PCITCR2 = MCF_PCI_PCITCR2_B0E | -+ MCF_PCI_PCITCR2_B4E; -+ -+ /* translate addresses from PCI[0] to CF[SDRAM] */ -+ MCF_PCI_PCITBATR0 = MCF_RAMBAR1 | MCF_PCI_PCITBATR0_EN; -+ MCF_PCI_PCITBATR4 = MCF_RAMBAR1 | MCF_PCI_PCITBATR4_EN; -+ -+ /* setup controller interrupt handlers */ -+ if (request_irq(55+128, mcf5445x_pci_interrupt, IRQF_SHARED, -+ "PCI Controller", NULL)) -+ printk(KERN_ERR "PCI: Unable to register controller irq\n"); -+ -+ if (request_irq (56+128, mcf5445x_pci_arb_interrupt, IRQF_SHARED, "PCI Arbiter", NULL)) -+ printk(KERN_ERR "PCI: Unable to register arbiter irq\n"); -+ -+ /* global control - clear reset bit */ -+ MCF_PCI_PCIGSCR = MCF_PCI_PCIGSCR_SEE | -+ MCF_PCI_PCIGSCR_PEE; -+ -+ /* let everything settle */ -+ udelay(1000); -+ -+ /* allocate bus ioport resource */ -+ if (request_resource(&ioport_resource, &pci_ioport_resource) < 0) -+ printk(KERN_ERR "PCI: Unable to alloc ioport resource\n"); -+ -+ /* allocate bus iomem resource */ -+ if (request_resource(&iomem_resource, &pci_iomem_resource) < 0) -+ printk(KERN_ERR "PCI: Unable to alloc iomem resource\n"); -+ -+ /* setup FPGA to route PCI to IRQ3(67), SW7 to IRQ7, SW6 to IRQ4 */ -+ set_fpga(FPGA_PCI_IRQ_ENABLE, 0x00000000); -+ set_fpga(FPGA_PCI_IRQ_ROUTE, 0x00000039); -+ set_fpga(FPGA_SEVEN_LED, 0x000000FF); -+ -+ raw_pci_ops = &mcf5445x_pci_ops; -+ -+ return 0; -+} -+ -+/* -+ * DEBUGGING -+ */ -+ -+#ifdef DEBUG -+struct regdump { -+ u32 addr; -+ char regname[16]; -+}; -+ -+struct regdump type0regs[] = { -+ { 0xfc0a8000, "PCIIDR" }, -+ { 0xfc0a8004, "PCISCR" }, -+ { 0xfc0a8008, "PCICCRIR" }, -+ { 0xfc0a800c, "PCICR1" }, -+ { 0xfc0a8010, "PCIBAR0" }, -+ { 0xfc0a8014, "PCIBAR1" }, -+ { 0xfc0a8018, "PCIBAR2" }, -+ { 0xfc0a801c, "PCIBAR3" }, -+ { 0xfc0a8020, "PCIBAR4" }, -+ { 0xfc0a8024, "PCIBAR5" }, -+ { 0xfc0a8028, "PCICCPR" }, -+ { 0xfc0a802c, "PCISID" }, -+ { 0xfc0a8030, "PCIERBAR" }, -+ { 0xfc0a8034, "PCICPR" }, -+ { 0xfc0a803c, "PCICR2" }, -+ { 0, "" } -+}; -+ -+struct regdump genregs[] = { -+ { 0xfc0a8060, "PCIGSCR" }, -+ { 0xfc0a8064, "PCITBATR0" }, -+ { 0xfc0a8068, "PCITBATR1" }, -+ { 0xfc0a806c, "PCITCR1" }, -+ { 0xfc0a8070, "PCIIW0BTAR" }, -+ { 0xfc0a8074, "PCIIW1BTAR" }, -+ { 0xfc0a8078, "PCIIW2BTAR" }, -+ { 0xfc0a8080, "PCIIWCR" }, -+ { 0xfc0a8084, "PCIICR" }, -+ { 0xfc0a8088, "PCIISR" }, -+ { 0xfc0a808c, "PCITCR2" }, -+ { 0xfc0a8090, "PCITBATR0" }, -+ { 0xfc0a8094, "PCITBATR1" }, -+ { 0xfc0a8098, "PCITBATR2" }, -+ { 0xfc0a809c, "PCITBATR3" }, -+ { 0xfc0a80a0, "PCITBATR4" }, -+ { 0xfc0a80a4, "PCITBATR5" }, -+ { 0xfc0a80a8, "PCIINTR" }, -+ { 0xfc0a80f8, "PCICAR" }, -+ { 0, "" } -+}; -+ -+struct regdump arbregs[] = { -+ { 0xfc0ac000, "PACR" }, -+ { 0xfc0ac004, "PASR" }, /* documentation error */ -+ { 0, "" } -+}; -+ -+/* -+ * void mcf5445x_pci_dumpregs() -+ * -+ * Dump out all the PCI registers -+ */ -+void -+mcf5445x_pci_dumpregs(void) -+{ -+ struct regdump *reg; -+ -+ printk(KERN_INFO "*** MCF5445x PCI TARGET 0 REGISTERS ***\n"); -+ -+ reg = type0regs; -+ while (reg->addr) { -+ printk(KERN_INFO "0x%08x 0x%08x %s\n", reg->addr, -+ *((u32 *)reg->addr), reg->regname); -+ reg++; -+ } -+ -+ printk(KERN_INFO "\n*** MCF5445x PCI GENERAL REGISTERS ***\n"); -+ reg = genregs; -+ while (reg->addr) { -+ printk(KERN_INFO "0x%08x 0x%08x %s\n", reg->addr, -+ *((u32 *)reg->addr), reg->regname); -+ reg++; -+ } -+ printk(KERN_INFO "\n*** MCF5445x PCI ARBITER REGISTERS ***\n"); -+ reg = arbregs; -+ while (reg->addr) { -+ printk(KERN_INFO "0x%08x 0x%08x %s\n", reg->addr, -+ *((u32 *)reg->addr), reg->regname); -+ reg++; -+ } -+} -+#endif /* DEBUG */ ---- /dev/null -+++ b/arch/m68k/coldfire/muldi3.S -@@ -0,0 +1,64 @@ -+/* -+ * Coldfire muldi3 assembly verion -+ */ -+ -+#include <linux/linkage.h> -+.globl __muldi3 -+ -+ENTRY(__muldi3) -+ linkw %fp,#0 -+ lea %sp@(-32),%sp -+ moveml %d2-%d7/%a2-%a3,%sp@ -+ moveal %fp@(8), %a2 -+ moveal %fp@(12), %a3 -+ moveal %fp@(16), %a0 -+ moveal %fp@(20),%a1 -+ movel %a3,%d2 -+ andil #65535,%d2 -+ movel %a3,%d3 -+ clrw %d3 -+ swap %d3 -+ movel %a1,%d0 -+ andil #65535,%d0 -+ movel %a1,%d1 -+ clrw %d1 -+ swap %d1 -+ movel %d2,%d7 -+ mulsl %d0,%d7 -+ movel %d2,%d4 -+ mulsl %d1,%d4 -+ movel %d3,%d2 -+ mulsl %d0,%d2 -+ mulsl %d1,%d3 -+ movel %d7,%d0 -+ clrw %d0 -+ swap %d0 -+ addl %d0,%d4 -+ addl %d2,%d4 -+ cmpl %d4,%d2 -+ blss 1f -+ addil #65536,%d3 -+1: -+ movel %d4,%d0 -+ clrw %d0 -+ swap %d0 -+ movel %d3,%d5 -+ addl %d0,%d5 -+ movew %d4,%d6 -+ swap %d6 -+ movew %d7,%d6 -+ movel %d5,%d0 -+ movel %d6,%d1 -+ movel %a3,%d2 -+ movel %a0,%d3 -+ mulsl %d3,%d2 -+ movel %a2,%d3 -+ movel %a1,%d4 -+ mulsl %d4,%d3 -+ addl %d3,%d2 -+ movel %d2,%d0 -+ addl %d5,%d0 -+ moveml %sp@, %d2-%d7/%a2-%a3 -+ lea %sp@(32),%sp -+ unlk %fp -+ rts ---- /dev/null -+++ b/arch/m68k/coldfire/pci.c -@@ -0,0 +1,245 @@ -+/* -+ * linux/arch/m68k/coldfire/pci.c -+ * -+ * PCI initialization for Coldfire architectures. -+ * -+ * Currently Supported: -+ * M5445x -+ * -+ * Copyright (c) 2007 Freescale Semiconductor, Inc. -+ * Kurt Mahan <kmahan@freescale.com> -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/pci.h> -+ -+#include <asm/mcfsim.h> -+#include <asm/pci.h> -+ -+/* pci ops for reading/writing config */ -+struct pci_raw_ops *raw_pci_ops; -+ -+/* pci debug flag */ -+static int debug_pci; -+ -+#ifdef CONFIG_M54455 -+extern int init_mcf5445x_pci(void); -+extern void mcf5445x_conf_device(struct pci_dev *dev); -+extern void mcf5445x_pci_dumpregs(void); -+ -+extern struct resource pci_ioport_resource; -+extern struct resource pci_iomem_resource; -+#endif -+ -+static int -+pci_read(struct pci_bus *bus, unsigned int devfn, int where, -+ int size, u32 *value) -+{ -+ return raw_pci_ops->read(0, bus->number, devfn, where, size, value); -+} -+ -+static int -+pci_write(struct pci_bus *bus, unsigned int devfn, int where, -+ int size, u32 value) -+{ -+ return raw_pci_ops->write(0, bus->number, devfn, where, size, value); -+} -+ -+struct pci_ops pci_root_ops = { -+ .read = pci_read, -+ .write = pci_write, -+}; -+ -+/* -+ * pcibios_setup(char *) -+ * -+ * Initialize the pcibios based on cmd line params. -+ */ -+char * __init -+pcibios_setup(char *str) -+{ -+ if (!strcmp(str, "debug")) { -+ debug_pci = 1; -+ return NULL; -+ } -+ return str; -+} -+ -+/* -+ * We need to avoid collisions with `mirrored' VGA ports -+ * and other strange ISA hardware, so we always want the -+ * addresses to be allocated in the 0x000-0x0ff region -+ * modulo 0x400. -+ * -+ * Why? Because some silly external IO cards only decode -+ * the low 10 bits of the IO address. The 0x00-0xff region -+ * is reserved for motherboard devices that decode all 16 -+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff, -+ * but we want to try to avoid allocating at 0x2900-0x2bff -+ * which might have be mirrored at 0x0100-0x03ff.. -+ */ -+void -+pcibios_align_resource(void *data, struct resource *res, resource_size_t size, -+ resource_size_t align) -+{ -+ struct pci_dev *dev = data; -+ -+ if (res->flags & IORESOURCE_IO) { -+ resource_size_t start = res->start; -+ -+ if (size > 0x100) -+ printk(KERN_ERR "PCI: I/O Region %s/%d too large" -+ " (%ld bytes)\n", pci_name(dev), -+ dev->resource - res, (long int)size); -+ -+ if (start & 0x300) { -+ start = (start + 0x3ff) & ~0x3ff; -+ res->start = start; -+ } -+ } -+} -+ -+/* -+ * Swizzle the device pin each time we cross a bridge -+ * and return the slot number. -+ */ -+static u8 __devinit -+pcibios_swizzle(struct pci_dev *dev, u8 *pin) -+{ -+ return 0; -+} -+ -+/* -+ * Map a slot/pin to an IRQ. -+ */ -+static int -+pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ return 0x43; -+} -+ -+/* -+ * pcibios_update_irq(struct pci_dev *dev, int irq) -+ * -+ * Update a PCI interrupt. -+ */ -+void __init -+pcibios_update_irq(struct pci_dev *dev, int irq) -+{ -+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -+} -+ -+/* -+ * pcibios_enable_device(struct pci_dev *dev, int mask) -+ * -+ * Enable a device on the PCI bus. -+ */ -+int -+pcibios_enable_device(struct pci_dev *dev, int mask) -+{ -+ u16 cmd, old_cmd; -+ int idx; -+ struct resource *r; -+ -+ pci_read_config_word(dev, PCI_COMMAND, &cmd); -+ old_cmd = cmd; -+ for (idx = 0; idx < 6; idx++) { -+ r = &dev->resource[idx]; -+ if (!r->start && r->end) { -+ printk(KERN_ERR "PCI: Device %s not available because " -+ "of resource collisions\n", pci_name(dev)); -+ return -EINVAL; -+ } -+ if (r->flags & IORESOURCE_IO) -+ cmd |= PCI_COMMAND_IO; -+ if (r->flags & IORESOURCE_MEM) -+ cmd |= PCI_COMMAND_MEMORY; -+ } -+ if (cmd != old_cmd) { -+ printk("PCI: Enabling device %s (%04x -> %04x)\n", -+ pci_name(dev), old_cmd, cmd); -+ pci_write_config_word(dev, PCI_COMMAND, cmd); -+#ifdef CONFIG_M54455 -+ mcf5445x_conf_device(dev); -+#endif -+ } -+ -+ return 0; -+} -+ -+/* -+ * pcibios_fixup_bus(struct pci_bus *bus) -+ */ -+void __init -+pcibios_fixup_bus(struct pci_bus *bus) -+{ -+ struct pci_dev *dev = bus->self; -+ -+ if (!dev) { -+ /* Root bus. */ -+#ifdef CONFIG_M54455 -+ bus->resource[0] = &pci_ioport_resource; -+ bus->resource[1] = &pci_iomem_resource; -+#endif -+ } -+} -+ -+/* -+ * pcibios_init(void) -+ * -+ * Allocate/initialize low level pci bus/devices. -+ */ -+static int __init -+pcibios_init(void) -+{ -+ struct pci_bus *bus; -+ -+ if (!raw_pci_ops) { -+ printk(KERN_WARNING "PCIBIOS: FATAL: NO PCI Hardware found\n"); -+ return 0; -+ } -+ -+ /* allocate and scan the (only) bus */ -+ bus = pci_scan_bus_parented(NULL, 0, &pci_root_ops, NULL); -+ -+ /* setup everything */ -+ if (bus) { -+ /* compute the bridge window sizes */ -+ pci_bus_size_bridges(bus); -+ -+ /* (re)assign device resources */ -+ pci_bus_assign_resources(bus); -+ -+ /* add the bus to the system */ -+ pci_bus_add_devices(bus); -+ -+ /* fixup irqs */ -+ pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq); -+ } -+ -+ return 0; -+} -+ -+/* -+ * pci_init(void) -+ * -+ * Initialize the PCI Hardware. -+ */ -+static int __init -+pci_init(void) -+{ -+#if defined(CONFIG_M54455) -+ init_mcf5445x_pci(); -+#endif -+ if (!raw_pci_ops) -+ printk(KERN_ERR "PCI: FATAL: NO PCI Detected\n"); -+ -+ return 0; -+} -+ -+/* low level hardware (first) */ -+arch_initcall(pci_init); -+ -+/* basic bios init (second) */ -+subsys_initcall(pcibios_init); ---- /dev/null -+++ b/arch/m68k/coldfire/signal.c -@@ -0,0 +1,868 @@ -+/* -+ * linux/arch/m68k/kernel/signal.c -+ * -+ * Copyright (C) 1991, 1992 Linus Torvalds -+ * -+ * 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. -+ */ -+ -+/* -+ * Derived from m68k/kernel/signal.c and the original authors are credited -+ * there. -+ * -+ * Coldfire support by: -+ * Matt Waddel Matt.Waddel@freescale.com -+ * Copyright Freescale Semiconductor, Inc 2007 -+ */ -+ -+#include <linux/sched.h> -+#include <linux/mm.h> -+#include <linux/kernel.h> -+#include <linux/signal.h> -+#include <linux/syscalls.h> -+#include <linux/errno.h> -+#include <linux/wait.h> -+#include <linux/ptrace.h> -+#include <linux/unistd.h> -+#include <linux/stddef.h> -+#include <linux/highuid.h> -+#include <linux/personality.h> -+#include <linux/tty.h> -+#include <linux/binfmts.h> -+ -+#include <asm/setup.h> -+#include <asm/cf_uaccess.h> -+#include <asm/cf_pgtable.h> -+#include <asm/traps.h> -+#include <asm/ucontext.h> -+ -+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -+ -+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); -+ -+const int frame_extra_sizes[16] = { -+ [1] = -1, -+ [2] = sizeof(((struct frame *)0)->un.fmt2), -+ [3] = sizeof(((struct frame *)0)->un.fmt3), -+ [4] = 0, -+ [5] = -1, -+ [6] = -1, -+ [7] = sizeof(((struct frame *)0)->un.fmt7), -+ [8] = -1, -+ [9] = sizeof(((struct frame *)0)->un.fmt9), -+ [10] = sizeof(((struct frame *)0)->un.fmta), -+ [11] = sizeof(((struct frame *)0)->un.fmtb), -+ [12] = -1, -+ [13] = -1, -+ [14] = -1, -+ [15] = -1, -+}; -+ -+/* -+ * Atomically swap in the new signal mask, and wait for a signal. -+ */ -+asmlinkage int do_sigsuspend(struct pt_regs *regs) -+{ -+ old_sigset_t mask = regs->d3; -+ sigset_t saveset; -+ -+ mask &= _BLOCKABLE; -+ spin_lock_irq(¤t->sighand->siglock); -+ saveset = current->blocked; -+ siginitset(¤t->blocked, mask); -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sighand->siglock); -+ -+ regs->d0 = -EINTR; -+ while (1) { -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ if (do_signal(&saveset, regs)) -+ return -EINTR; -+ } -+} -+ -+asmlinkage int -+do_rt_sigsuspend(struct pt_regs *regs) -+{ -+ sigset_t __user *unewset = (sigset_t __user *)regs->d1; -+ size_t sigsetsize = (size_t)regs->d2; -+ sigset_t saveset, newset; -+ -+ /* XXX: Don't preclude handling different sized sigset_t's. */ -+ if (sigsetsize != sizeof(sigset_t)) -+ return -EINVAL; -+ -+ if (copy_from_user(&newset, unewset, sizeof(newset))) -+ return -EFAULT; -+ sigdelsetmask(&newset, ~_BLOCKABLE); -+ -+ spin_lock_irq(¤t->sighand->siglock); -+ saveset = current->blocked; -+ current->blocked = newset; -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sighand->siglock); -+ -+ regs->d0 = -EINTR; -+ while (1) { -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ if (do_signal(&saveset, regs)) -+ return -EINTR; -+ } -+} -+ -+asmlinkage int -+sys_sigaction(int sig, const struct old_sigaction __user *act, -+ struct old_sigaction __user *oact) -+{ -+ struct k_sigaction new_ka, old_ka; -+ int ret; -+ -+ if (act) { -+ old_sigset_t mask; -+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) || -+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) || -+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) -+ return -EFAULT; -+ __get_user(new_ka.sa.sa_flags, &act->sa_flags); -+ __get_user(mask, &act->sa_mask); -+ siginitset(&new_ka.sa.sa_mask, mask); -+ } -+ -+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); -+ -+ if (!ret && oact) { -+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || -+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || -+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) -+ return -EFAULT; -+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags); -+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); -+ } -+ -+ return ret; -+} -+ -+asmlinkage int -+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) -+{ -+ return do_sigaltstack(uss, uoss, rdusp()); -+} -+ -+ -+/* -+ * Do a signal return; undo the signal stack. -+ * -+ * Keep the return code on the stack quadword aligned! -+ * That makes the cache flush below easier. -+ */ -+ -+struct sigframe -+{ -+ char __user *pretcode; -+ int sig; -+ int code; -+ struct sigcontext __user *psc; -+ char retcode[16]; -+ unsigned long extramask[_NSIG_WORDS-1]; -+ struct sigcontext sc; -+}; -+ -+struct rt_sigframe -+{ -+ char __user *pretcode; -+ int sig; -+ struct siginfo __user *pinfo; -+ void __user *puc; -+ char retcode[16]; -+ struct siginfo info; -+ struct ucontext uc; -+}; -+ -+#define FPCONTEXT_SIZE 216 -+#define uc_fpstate uc_filler[0] -+#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4] -+#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1] -+ -+#ifdef CONFIG_FPU -+static unsigned char fpu_version; /* version num of fpu, set by setup_frame */ -+ -+static inline int restore_fpu_state(struct sigcontext *sc) -+{ -+ int err = 1; -+ -+ if (FPU_IS_EMU) { -+ /* restore registers */ -+ memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12); -+ memcpy(current->thread.fp, sc->sc_fpregs, 24); -+ return 0; -+ } -+ -+ if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { -+ /* Verify the frame format. */ -+ if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version)) -+ goto out; -+ if (CPU_IS_020_OR_030) { -+ if (m68k_fputype & FPU_68881 && -+ !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4)) -+ goto out; -+ if (m68k_fputype & FPU_68882 && -+ !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4)) -+ goto out; -+ } else if (CPU_IS_040) { -+ if (!(sc->sc_fpstate[1] == 0x00 || -+ sc->sc_fpstate[1] == 0x28 || -+ sc->sc_fpstate[1] == 0x60)) -+ goto out; -+ } else if (CPU_IS_060) { -+ if (!(sc->sc_fpstate[3] == 0x00 || -+ sc->sc_fpstate[3] == 0x60 || -+ sc->sc_fpstate[3] == 0xe0)) -+ goto out; -+ } else -+ goto out; -+ -+ } -+ err = 0; -+ -+out: -+ return err; -+} -+ -+static inline int rt_restore_fpu_state(struct ucontext __user *uc) -+{ -+ unsigned char fpstate[FPCONTEXT_SIZE]; -+ int context_size = CPU_IS_060 ? 8 : 0; -+ fpregset_t fpregs; -+ int err = 1; -+ -+ if (FPU_IS_EMU) { -+ /* restore fpu control register */ -+ if (__copy_from_user(current->thread.fpcntl, -+ uc->uc_mcontext.fpregs.f_fpcntl, 12)) -+ goto out; -+ /* restore all other fpu register */ -+ if (__copy_from_user(current->thread.fp, -+ uc->uc_mcontext.fpregs.f_fpregs, 96)) -+ goto out; -+ return 0; -+ } -+ -+ if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate)) -+ goto out; -+ if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { -+ if (!CPU_IS_060) -+ context_size = fpstate[1]; -+ /* Verify the frame format. */ -+ if (!CPU_IS_060 && (fpstate[0] != fpu_version)) -+ goto out; -+ if (CPU_IS_020_OR_030) { -+ if (m68k_fputype & FPU_68881 && -+ !(context_size == 0x18 || context_size == 0xb4)) -+ goto out; -+ if (m68k_fputype & FPU_68882 && -+ !(context_size == 0x38 || context_size == 0xd4)) -+ goto out; -+ } else if (CPU_IS_040) { -+ if (!(context_size == 0x00 || -+ context_size == 0x28 || -+ context_size == 0x60)) -+ goto out; -+ } else if (CPU_IS_060) { -+ if (!(fpstate[3] == 0x00 || -+ fpstate[3] == 0x60 || -+ fpstate[3] == 0xe0)) -+ goto out; -+ } else -+ goto out; -+ if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs, -+ sizeof(fpregs))) -+ goto out; -+ } -+ if (context_size && -+ __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1, -+ context_size)) -+ goto out; -+ err = 0; -+ -+out: -+ return err; -+} -+#endif -+ -+static inline int -+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, -+ void __user *fp, int *pd0) -+{ -+ int fsize, formatvec; -+ struct sigcontext context; -+ int err = 0; -+ -+ /* get previous context */ -+ if (copy_from_user(&context, usc, sizeof(context))) -+ goto badframe; -+ -+ /* restore passed registers */ -+ regs->d1 = context.sc_d1; -+ regs->a0 = context.sc_a0; -+ regs->a1 = context.sc_a1; -+ regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); -+ regs->pc = context.sc_pc; -+ regs->orig_d0 = -1; /* disable syscall checks */ -+ wrusp(context.sc_usp); -+ formatvec = context.sc_formatvec; -+ regs->format = formatvec >> 12; -+ regs->vector = formatvec & 0xfff; -+ -+#ifdef CONFIG_FPU -+ err = restore_fpu_state(&context); -+#endif -+ -+ fsize = frame_extra_sizes[regs->format]; -+ if (fsize < 0) { -+ /* -+ * user process trying to return with weird frame format -+ */ -+#ifdef DEBUG -+ printk(KERN_DEBUG "user process returning with weird \ -+ frame format\n"); -+#endif -+ goto badframe; -+ } -+ -+ /* OK. Make room on the supervisor stack for the extra junk, -+ * if necessary. -+ */ -+ -+ { -+ struct switch_stack *sw = (struct switch_stack *)regs - 1; -+ regs->d0 = context.sc_d0; -+#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) -+ __asm__ __volatile__ -+ (" movel %0,%/sp\n\t" -+ " bra ret_from_signal\n" -+ "4:\n" -+ ".section __ex_table,\"a\"\n" -+ " .align 4\n" -+ " .long 2b,4b\n" -+ ".previous" -+ : /* no outputs, it doesn't ever return */ -+ : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), -+ "n" (frame_offset), "a" (fp) -+ : "a0"); -+#undef frame_offset -+ /* -+ * If we ever get here an exception occurred while -+ * building the above stack-frame. -+ */ -+ goto badframe; -+ } -+ -+ *pd0 = context.sc_d0; -+ return err; -+ -+badframe: -+ return 1; -+} -+ -+static inline int -+rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, -+ struct ucontext __user *uc, int *pd0) -+{ -+ int fsize, temp; -+ greg_t __user *gregs = uc->uc_mcontext.gregs; -+ unsigned long usp; -+ int err; -+ -+ err = __get_user(temp, &uc->uc_mcontext.version); -+ if (temp != MCONTEXT_VERSION) -+ goto badframe; -+ /* restore passed registers */ -+ err |= __get_user(regs->d0, &gregs[0]); -+ err |= __get_user(regs->d1, &gregs[1]); -+ err |= __get_user(regs->d2, &gregs[2]); -+ err |= __get_user(regs->d3, &gregs[3]); -+ err |= __get_user(regs->d4, &gregs[4]); -+ err |= __get_user(regs->d5, &gregs[5]); -+ err |= __get_user(sw->d6, &gregs[6]); -+ err |= __get_user(sw->d7, &gregs[7]); -+ err |= __get_user(regs->a0, &gregs[8]); -+ err |= __get_user(regs->a1, &gregs[9]); -+ err |= __get_user(regs->a2, &gregs[10]); -+ err |= __get_user(sw->a3, &gregs[11]); -+ err |= __get_user(sw->a4, &gregs[12]); -+ err |= __get_user(sw->a5, &gregs[13]); -+ err |= __get_user(sw->a6, &gregs[14]); -+ err |= __get_user(usp, &gregs[15]); -+ wrusp(usp); -+ err |= __get_user(regs->pc, &gregs[16]); -+ err |= __get_user(temp, &gregs[17]); -+ regs->sr = (regs->sr & 0xff00) | (temp & 0xff); -+ regs->orig_d0 = -1; /* disable syscall checks */ -+ err |= __get_user(temp, &uc->uc_formatvec); -+ regs->format = temp >> 12; -+ regs->vector = temp & 0xfff; -+ -+#ifdef CONFIG_FPU -+ err |= rt_restore_fpu_state(uc); -+#endif -+ -+ if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) -+ goto badframe; -+ -+ fsize = frame_extra_sizes[regs->format]; -+ if (fsize < 0) { -+ /* -+ * user process trying to return with weird frame format -+ */ -+#ifdef DEBUG -+ printk(KERN_DEBUG "user process returning with weird \ -+ frame format\n"); -+#endif -+ goto badframe; -+ } -+ -+ /* OK. Make room on the supervisor stack for the extra junk, -+ * if necessary. -+ */ -+ -+ { -+#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) -+ __asm__ __volatile__ -+ (" movel %0,%/sp\n\t" -+ " bra ret_from_signal\n" -+ "4:\n" -+ ".section __ex_table,\"a\"\n" -+ " .align 4\n" -+ " .long 2b,4b\n" -+ ".previous" -+ : /* no outputs, it doesn't ever return */ -+ : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), -+ "n" (frame_offset), "a" (&uc->uc_extra) -+ : "a0"); -+#undef frame_offset -+ /* -+ * If we ever get here an exception occurred while -+ * building the above stack-frame. -+ */ -+ goto badframe; -+ } -+ -+ *pd0 = regs->d0; -+ return err; -+ -+badframe: -+ return 1; -+} -+ -+asmlinkage int do_sigreturn(unsigned long __unused) -+{ -+ struct switch_stack *sw = (struct switch_stack *) &__unused; -+ struct pt_regs *regs = (struct pt_regs *) (sw + 1); -+ unsigned long usp = rdusp(); -+ struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); -+ sigset_t set; -+ int d0; -+ -+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) -+ goto badframe; -+ if (__get_user(set.sig[0], &frame->sc.sc_mask) || -+ (_NSIG_WORDS > 1 && -+ __copy_from_user(&set.sig[1], &frame->extramask, -+ sizeof(frame->extramask)))) -+ goto badframe; -+ -+ sigdelsetmask(&set, ~_BLOCKABLE); -+ spin_lock_irq(¤t->sighand->siglock); -+ current->blocked = set; -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sighand->siglock); -+ -+ if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0)) -+ goto badframe; -+ return d0; -+ -+badframe: -+ force_sig(SIGSEGV, current); -+ return 0; -+} -+ -+asmlinkage int do_rt_sigreturn(unsigned long __unused) -+{ -+ struct switch_stack *sw = (struct switch_stack *) &__unused; -+ struct pt_regs *regs = (struct pt_regs *) (sw + 1); -+ unsigned long usp = rdusp(); -+ struct rt_sigframe __user *frame = -+ (struct rt_sigframe __user *)(usp - 4); -+ sigset_t set; -+ int d0; -+ -+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) -+ goto badframe; -+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) -+ goto badframe; -+ -+ sigdelsetmask(&set, ~_BLOCKABLE); -+ spin_lock_irq(¤t->sighand->siglock); -+ current->blocked = set; -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sighand->siglock); -+ -+ if (rt_restore_ucontext(regs, sw, &frame->uc, &d0)) -+ goto badframe; -+ return d0; -+ -+badframe: -+ force_sig(SIGSEGV, current); -+ return 0; -+} -+ -+#ifdef CONFIG_FPU -+/* -+ * Set up a signal frame. -+ */ -+ -+static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) -+{ -+ if (FPU_IS_EMU) { -+ /* save registers */ -+ memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12); -+ memcpy(sc->sc_fpregs, current->thread.fp, 24); -+ return; -+ } -+} -+ -+static inline int rt_save_fpu_state(struct ucontext __user *uc, -+ struct pt_regs *regs) -+{ -+ int err = 0; -+ -+ if (FPU_IS_EMU) { -+ /* save fpu control register */ -+ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl, -+ current->thread.fpcntl, 12); -+ /* save all other fpu register */ -+ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, -+ current->thread.fp, 96); -+ return err; -+ } -+ -+ return err; -+} -+#endif -+ -+static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, -+ unsigned long mask) -+{ -+ sc->sc_mask = mask; -+ sc->sc_usp = rdusp(); -+ sc->sc_d0 = regs->d0; -+ sc->sc_d1 = regs->d1; -+ sc->sc_a0 = regs->a0; -+ sc->sc_a1 = regs->a1; -+ sc->sc_sr = regs->sr; -+ sc->sc_pc = regs->pc; -+ sc->sc_formatvec = regs->format << 12 | regs->vector; -+#ifdef CONFIG_FPU -+ save_fpu_state(sc, regs); -+#endif -+} -+ -+static inline int rt_setup_ucontext(struct ucontext __user *uc, -+ struct pt_regs *regs) -+{ -+ struct switch_stack *sw = (struct switch_stack *)regs - 1; -+ greg_t __user *gregs = uc->uc_mcontext.gregs; -+ int err = 0; -+ -+ err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); -+ err |= __put_user(regs->d0, &gregs[0]); -+ err |= __put_user(regs->d1, &gregs[1]); -+ err |= __put_user(regs->d2, &gregs[2]); -+ err |= __put_user(regs->d3, &gregs[3]); -+ err |= __put_user(regs->d4, &gregs[4]); -+ err |= __put_user(regs->d5, &gregs[5]); -+ err |= __put_user(sw->d6, &gregs[6]); -+ err |= __put_user(sw->d7, &gregs[7]); -+ err |= __put_user(regs->a0, &gregs[8]); -+ err |= __put_user(regs->a1, &gregs[9]); -+ err |= __put_user(regs->a2, &gregs[10]); -+ err |= __put_user(sw->a3, &gregs[11]); -+ err |= __put_user(sw->a4, &gregs[12]); -+ err |= __put_user(sw->a5, &gregs[13]); -+ err |= __put_user(sw->a6, &gregs[14]); -+ err |= __put_user(rdusp(), &gregs[15]); -+ err |= __put_user(regs->pc, &gregs[16]); -+ err |= __put_user(regs->sr, &gregs[17]); -+ err |= __put_user((regs->format << 12) | regs->vector, -+ &uc->uc_formatvec); -+#ifdef CONFIG_FPU -+ err |= rt_save_fpu_state(uc, regs); -+#endif -+ return err; -+} -+ -+extern void IcacheInvalidateCacheBlock(void *, unsigned long); -+static inline void push_cache(unsigned long vaddr) -+{ -+ IcacheInvalidateCacheBlock((void *)vaddr, 8); -+} -+ -+static inline void __user * -+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) -+{ -+ unsigned long usp; -+ -+ /* Default to using normal stack. */ -+ usp = rdusp(); -+ -+ /* This is the X/Open sanctioned signal stack switching. */ -+ if (ka->sa.sa_flags & SA_ONSTACK) { -+ if (!sas_ss_flags(usp)) -+ usp = current->sas_ss_sp + current->sas_ss_size; -+ } -+ return (void __user *)((usp - frame_size) & -8UL); -+} -+ -+static void setup_frame(int sig, struct k_sigaction *ka, -+ sigset_t *set, struct pt_regs *regs) -+{ -+ struct sigframe __user *frame; -+ int fsize = frame_extra_sizes[regs->format]; -+ struct sigcontext context; -+ int err = 0; -+ -+ if (fsize < 0) { -+#ifdef DEBUG -+ printk(KERN_DEBUG "setup_frame: Unknown frame format %#x\n", -+ regs->format); -+#endif -+ goto give_sigsegv; -+ } -+ -+ frame = get_sigframe(ka, regs, sizeof(*frame)); -+ -+ err |= __put_user((current_thread_info()->exec_domain -+ && current_thread_info()->exec_domain->signal_invmap -+ && sig < 32 -+ ? current_thread_info()->exec_domain->signal_invmap[sig] -+ : sig), -+ &frame->sig); -+ -+ err |= __put_user(regs->vector, &frame->code); -+ err |= __put_user(&frame->sc, &frame->psc); -+ -+ if (_NSIG_WORDS > 1) -+ err |= copy_to_user(frame->extramask, &set->sig[1], -+ sizeof(frame->extramask)); -+ -+ setup_sigcontext(&context, regs, set->sig[0]); -+ err |= copy_to_user(&frame->sc, &context, sizeof(context)); -+ -+ /* Set up to return from userspace. */ -+ err |= __put_user(frame->retcode, &frame->pretcode); -+ /* moveq #,d0; trap #0 */ -+ err |= __put_user(0x70004e40 + (__NR_sigreturn << 16), -+ (long __user *)(frame->retcode)); -+ -+ if (err) -+ goto give_sigsegv; -+ -+ push_cache((unsigned long) &frame->retcode); -+ -+ /* Set up registers for signal handler */ -+ wrusp((unsigned long) frame); -+ regs->pc = (unsigned long) ka->sa.sa_handler; -+ -+adjust_stack: -+ /* Prepare to skip over the extra stuff in the exception frame. */ -+ if (regs->stkadj) { -+ struct pt_regs *tregs = -+ (struct pt_regs *)((ulong)regs + regs->stkadj); -+#ifdef DEBUG -+ printk(KERN_DEBUG "Performing stackadjust=%04x\n", -+ regs->stkadj); -+#endif -+ /* This must be copied with decreasing addresses to -+ handle overlaps. */ -+ tregs->vector = 0; -+ tregs->format = 0; -+ tregs->pc = regs->pc; -+ tregs->sr = regs->sr; -+ } -+ return; -+ -+give_sigsegv: -+ force_sigsegv(sig, current); -+ goto adjust_stack; -+} -+ -+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, -+ sigset_t *set, struct pt_regs *regs) -+{ -+ struct rt_sigframe __user *frame; -+ int fsize = frame_extra_sizes[regs->format]; -+ int err = 0; -+ -+ if (fsize < 0) { -+#ifdef DEBUG -+ printk(KERN_DEBUG "setup_frame: Unknown frame format %#x\n", -+ regs->format); -+#endif -+ goto give_sigsegv; -+ } -+ -+ frame = get_sigframe(ka, regs, sizeof(*frame)); -+ -+ if (fsize) { -+ err |= copy_to_user(&frame->uc.uc_extra, regs + 1, fsize); -+ regs->stkadj = fsize; -+ } -+ -+ err |= __put_user((current_thread_info()->exec_domain -+ && current_thread_info()->exec_domain->signal_invmap -+ && sig < 32 -+ ? current_thread_info()->exec_domain->signal_invmap[sig] -+ : sig), -+ &frame->sig); -+ err |= __put_user(&frame->info, &frame->pinfo); -+ err |= __put_user(&frame->uc, &frame->puc); -+ err |= copy_siginfo_to_user(&frame->info, info); -+ -+ /* Create the ucontext. */ -+ err |= __put_user(0, &frame->uc.uc_flags); -+ err |= __put_user(NULL, &frame->uc.uc_link); -+ err |= __put_user((void __user *)current->sas_ss_sp, -+ &frame->uc.uc_stack.ss_sp); -+ err |= __put_user(sas_ss_flags(rdusp()), -+ &frame->uc.uc_stack.ss_flags); -+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); -+ err |= rt_setup_ucontext(&frame->uc, regs); -+ err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); -+ -+ /* Set up to return from userspace. */ -+ err |= __put_user(frame->retcode, &frame->pretcode); -+ -+ /* moveq #,d0; andi.l #,D0; trap #0 */ -+ err |= __put_user(0x70AD0280, (long *)(frame->retcode + 0)); -+ err |= __put_user(0x000000ff, (long *)(frame->retcode + 4)); -+ err |= __put_user(0x4e400000, (long *)(frame->retcode + 8)); -+ -+ if (err) -+ goto give_sigsegv; -+ -+ push_cache((unsigned long) &frame->retcode); -+ -+ /* Set up registers for signal handler */ -+ wrusp((unsigned long) frame); -+ regs->pc = (unsigned long) ka->sa.sa_handler; -+ -+adjust_stack: -+ /* Prepare to skip over the extra stuff in the exception frame. */ -+ if (regs->stkadj) { -+ struct pt_regs *tregs = -+ (struct pt_regs *)((ulong)regs + regs->stkadj); -+#ifdef DEBUG -+ printk(KERN_DEBUG "Performing stackadjust=%04x\n", -+ regs->stkadj); -+#endif -+ /* This must be copied with decreasing addresses to -+ handle overlaps. */ -+ tregs->vector = 0; -+ tregs->format = 0; -+ tregs->pc = regs->pc; -+ tregs->sr = regs->sr; -+ } -+ return; -+ -+give_sigsegv: -+ force_sigsegv(sig, current); -+ goto adjust_stack; -+} -+ -+static inline void -+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) -+{ -+ switch (regs->d0) { -+ case -ERESTARTNOHAND: -+ if (!has_handler) -+ goto do_restart; -+ regs->d0 = -EINTR; -+ break; -+ -+ case -ERESTARTSYS: -+ if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { -+ regs->d0 = -EINTR; -+ break; -+ } -+ /* fallthrough */ -+ case -ERESTARTNOINTR: -+do_restart: -+ regs->d0 = regs->orig_d0; -+ regs->pc -= 2; -+ break; -+ } -+} -+ -+/* -+ * OK, we're invoking a handler -+ */ -+static void -+handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, -+ sigset_t *oldset, struct pt_regs *regs) -+{ -+ /* are we from a system call? */ -+ if (regs->orig_d0 >= 0) -+ /* If so, check system call restarting.. */ -+ handle_restart(regs, ka, 1); -+ -+ /* set up the stack frame */ -+ if (ka->sa.sa_flags & SA_SIGINFO) -+ setup_rt_frame(sig, ka, info, oldset, regs); -+ else -+ setup_frame(sig, ka, oldset, regs); -+ -+ if (ka->sa.sa_flags & SA_ONESHOT) -+ ka->sa.sa_handler = SIG_DFL; -+ -+ spin_lock_irq(¤t->sighand->siglock); -+ sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); -+ if (!(ka->sa.sa_flags & SA_NODEFER)) -+ sigaddset(¤t->blocked, sig); -+ recalc_sigpending(); -+ spin_unlock_irq(¤t->sighand->siglock); -+} -+ -+/* -+ * Note that 'init' is a special process: it doesn't get signals it doesn't -+ * want to handle. Thus you cannot kill init even with a SIGKILL even by -+ * mistake. -+ */ -+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) -+{ -+ siginfo_t info; -+ struct k_sigaction ka; -+ int signr; -+ -+ current->thread.esp0 = (unsigned long) regs; -+ -+ if (!oldset) -+ oldset = ¤t->blocked; -+ -+ signr = get_signal_to_deliver(&info, &ka, regs, NULL); -+ if (signr > 0) { -+ /* Whee! Actually deliver the signal. */ -+ handle_signal(signr, &ka, &info, oldset, regs); -+ return 1; -+ } -+ -+ /* Did we come from a system call? */ -+ if (regs->orig_d0 >= 0) -+ /* Restart the system call - no handlers present */ -+ handle_restart(regs, NULL, 0); -+ -+ return 0; -+} ---- /dev/null -+++ b/arch/m68k/coldfire/traps.c -@@ -0,0 +1,454 @@ -+/* -+ * linux/arch/m68knommu/kernel/traps.c -+ * -+ * Copyright (C) 1993, 1994 by Hamish Macdonald -+ * -+ * 68040 fixes by Michael Rausch -+ * 68040 fixes by Martin Apel -+ * 68060 fixes by Roman Hodek -+ * 68060 fixes by Jesper Skov -+ * -+ * 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. -+ */ -+ -+/* -+ * Sets up all exception vectors -+ */ -+#include <linux/sched.h> -+#include <linux/signal.h> -+#include <linux/kernel.h> -+#include <linux/mm.h> -+#include <linux/module.h> -+#include <linux/types.h> -+#include <linux/a.out.h> -+#include <linux/user.h> -+#include <linux/string.h> -+#include <linux/linkage.h> -+#include <linux/init.h> -+#include <linux/ptrace.h> -+#include <linux/kallsyms.h> -+ -+#include <asm/setup.h> -+#include <asm/fpu.h> -+#include <asm/system.h> -+#include <asm/uaccess.h> -+#include <asm/traps.h> -+#include <asm/pgtable.h> -+#include <asm/machdep.h> -+#include <asm/siginfo.h> -+ -+static char const * const vec_names[] = { -+ "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR", -+ "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc", -+ "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111", -+ "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION", -+ "FORMAT ERROR", "UNINITIALIZED INTERRUPT", -+ "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17", -+ "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19", -+ "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21", -+ "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23", -+ "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT", -+ "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT", -+ "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3", -+ "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7", -+ "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11", -+ "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15", -+ "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW", -+ "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN", -+ "FPCP UNSUPPORTED OPERATION", -+ "MMU CONFIGURATION ERROR" -+}; -+ -+asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, -+ unsigned long error_code); -+asmlinkage void trap_c(struct frame *fp); -+extern void __init coldfire_trap_init(void); -+ -+void __init trap_init(void) -+{ -+ coldfire_trap_init(); -+} -+ -+/* The following table converts the FS encoding of a ColdFire -+ exception stack frame into the error_code value needed by -+ do_fault. */ -+ -+static const unsigned char fs_err_code[] = { -+ 0, /* 0000 */ -+ 0, /* 0001 */ -+ 0, /* 0010 */ -+ 0, /* 0011 */ -+ 1, /* 0100 */ -+ 0, /* 0101 */ -+ 0, /* 0110 */ -+ 0, /* 0111 */ -+ 2, /* 1000 */ -+ 3, /* 1001 */ -+ 2, /* 1010 */ -+ 0, /* 1011 */ -+ 1, /* 1100 */ -+ 1, /* 1101 */ -+ 0, /* 1110 */ -+ 0 /* 1111 */ -+}; -+ -+#ifdef DEBUG -+static const char *fs_err_msg[16] = { -+ "Normal", -+ "Reserved", -+ "Interrupt during debug service routine", -+ "Reserved", -+ "X Protection", -+ "TLB X miss (opword)", -+ "TLB X miss (ext. word)", -+ "IFP in emulator mode", -+ "W Protection", -+ "Write error", -+ "TLB W miss", -+ "Reserved", -+ "R Protection", -+ "R/RMW Protection", -+ "TLB R miss", -+ "OEP in emulator mode", -+}; -+#endif -+ -+static inline void access_errorCF(struct frame *fp) -+{ -+ unsigned long int mmusr, complainingAddress; -+ unsigned int err_code, fs; -+ int need_page_fault; -+ -+ mmusr = fp->ptregs.mmusr; -+ complainingAddress = fp->ptregs.mmuar; -+#ifdef DEBUG -+ printk(KERN_DEBUG "pc %#lx, mmusr %#lx, complainingAddress %#lx\n", \ -+ fp->ptregs.pc, mmusr, complainingAddress); -+#endif -+ -+ /* -+ * error_code: -+ * bit 0 == 0 means no page found, 1 means protection fault -+ * bit 1 == 0 means read, 1 means write -+ */ -+ -+ fs = (fp->ptregs.fs2 << 2) | fp->ptregs.fs1; -+ switch (fs) { -+ case 5: /* 0101 TLB opword X miss */ -+ need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 0); -+ complainingAddress = fp->ptregs.pc; -+ break; -+ case 6: /* 0110 TLB extension word X miss */ -+ need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 1); -+ complainingAddress = fp->ptregs.pc + sizeof(long); -+ break; -+ case 10: /* 1010 TLB W miss */ -+ need_page_fault = cf_tlb_miss(&fp->ptregs, 1, 1, 0); -+ break; -+ case 14: /* 1110 TLB R miss */ -+ need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 1, 0); -+ break; -+ default: -+ /* 0000 Normal */ -+ /* 0001 Reserved */ -+ /* 0010 Interrupt during debug service routine */ -+ /* 0011 Reserved */ -+ /* 0100 X Protection */ -+ /* 0111 IFP in emulator mode */ -+ /* 1000 W Protection*/ -+ /* 1001 Write error*/ -+ /* 1011 Reserved*/ -+ /* 1100 R Protection*/ -+ /* 1101 R Protection*/ -+ /* 1111 OEP in emulator mode*/ -+ need_page_fault = 1; -+ break; -+ } -+ -+ if (need_page_fault) { -+ err_code = fs_err_code[fs]; -+ if ((fs == 13) && (mmusr & MMUSR_WF)) /* rd-mod-wr access */ -+ err_code |= 2; /* bit1 - write, bit0 - protection */ -+ do_page_fault(&fp->ptregs, complainingAddress, err_code); -+ } -+} -+ -+void die_if_kernel(char *str, struct pt_regs *fp, int nr) -+{ -+ if (!(fp->sr & PS_S)) -+ return; -+ -+ console_verbose(); -+ printk(KERN_EMERG "%s: %08x\n", str, nr); -+ printk(KERN_EMERG "PC: [<%08lx>]", fp->pc); -+ print_symbol(" %s", fp->pc); -+ printk(KERN_EMERG "\nSR: %04x SP: %p a2: %08lx\n", -+ fp->sr, fp, fp->a2); -+ printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", -+ fp->d0, fp->d1, fp->d2, fp->d3); -+ printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", -+ fp->d4, fp->d5, fp->a0, fp->a1); -+ -+ printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n", -+ current->comm, current->pid, PAGE_SIZE+(unsigned long)current); -+ show_stack(NULL, (unsigned long *)fp); -+ do_exit(SIGSEGV); -+} -+ -+asmlinkage void buserr_c(struct frame *fp) -+{ -+ unsigned int fs; -+ -+ /* Only set esp0 if coming from user mode */ -+ if (user_mode(&fp->ptregs)) -+ current->thread.esp0 = (unsigned long) fp; -+ -+ fs = (fp->ptregs.fs2 << 2) | fp->ptregs.fs1; -+#if defined(DEBUG) -+ printk(KERN_DEBUG "*** Bus Error *** (%x)%s\n", fs, -+ fs_err_msg[fs & 0xf]); -+#endif -+ switch (fs) { -+ case 0x5: -+ case 0x6: -+ case 0x7: -+ case 0x9: -+ case 0xa: -+ case 0xd: -+ case 0xe: -+ case 0xf: -+ access_errorCF(fp); -+ break; -+ default: -+ die_if_kernel("bad frame format", &fp->ptregs, 0); -+#if defined(DEBUG) -+ printk(KERN_DEBUG "Unknown SIGSEGV - 4\n"); -+#endif -+ force_sig(SIGSEGV, current); -+ } -+} -+ -+ -+int kstack_depth_to_print = 48; -+ -+void show_stack(struct task_struct *task, unsigned long *stack) -+{ -+ unsigned long *endstack, addr, symaddr; -+ extern char _start, _etext; -+ int i; -+ -+ if (!stack) { -+ if (task) -+ stack = (unsigned long *)task->thread.ksp; -+ else -+ stack = (unsigned long *)&stack; -+ } -+ -+ addr = (unsigned long) stack; -+ endstack = (unsigned long *) PAGE_ALIGN(addr); -+ -+ printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack); -+ for (i = 0; i < kstack_depth_to_print; i++) { -+ if (stack + 1 > endstack) -+ break; -+ if (i % 8 == 0) -+ printk("\n" KERN_EMERG " "); -+ symaddr = *stack; -+ printk(KERN_EMERG " %08lx", *stack++); -+ if ((symaddr >= 0xc0000000) && (symaddr < 0xc1000000)) -+ print_symbol("(%s)", symaddr); -+ } -+ printk("\n"); -+ -+ printk(KERN_EMERG "Call Trace:"); -+ i = 0; -+ while (stack + 1 <= endstack) { -+ addr = *stack++; -+ /* -+ * If the address is either in the text segment of the -+ * kernel, or in the region which contains vmalloc'ed -+ * memory, it *may* be the address of a calling -+ * routine; if so, print it so that someone tracing -+ * down the cause of the crash will be able to figure -+ * out the call path that was taken. -+ */ -+ if (((addr >= (unsigned long) &_start) && -+ (addr <= (unsigned long) &_etext))) { -+ if (i % 4 == 0) -+ printk("\n" KERN_EMERG " "); -+ printk(KERN_EMERG " [<%08lx>]", addr); -+ i++; -+ } -+ } -+ printk("\n"); -+} -+ -+void bad_super_trap(struct frame *fp) -+{ -+ console_verbose(); -+ if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0])) -+ printk(KERN_WARNING "*** %s *** FORMAT=%X\n", -+ vec_names[(fp->ptregs.vector) >> 2], -+ fp->ptregs.format); -+ else -+ printk(KERN_WARNING "*** Exception %d *** FORMAT=%X\n", -+ (fp->ptregs.vector) >> 2, -+ fp->ptregs.format); -+ printk(KERN_WARNING "Current process id is %d\n", current->pid); -+ die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0); -+} -+ -+asmlinkage void trap_c(struct frame *fp) -+{ -+ int sig; -+ siginfo_t info; -+ -+ if (fp->ptregs.sr & PS_S) { -+ if ((fp->ptregs.vector >> 2) == VEC_TRACE) { -+ /* traced a trapping instruction */ -+ current->ptrace |= PT_DTRACE; -+ } else -+ bad_super_trap(fp); -+ return; -+ } -+ -+ /* send the appropriate signal to the user program */ -+ switch ((fp->ptregs.vector) >> 2) { -+ case VEC_ADDRERR: -+ info.si_code = BUS_ADRALN; -+ sig = SIGBUS; -+ break; -+ case VEC_ILLEGAL: -+ case VEC_LINE10: -+ case VEC_LINE11: -+ info.si_code = ILL_ILLOPC; -+ sig = SIGILL; -+ break; -+ case VEC_PRIV: -+ info.si_code = ILL_PRVOPC; -+ sig = SIGILL; -+ break; -+ case VEC_COPROC: -+ info.si_code = ILL_COPROC; -+ sig = SIGILL; -+ break; -+ case VEC_TRAP1: /* gdbserver breakpoint */ -+ fp->ptregs.pc -= 2; -+ info.si_code = TRAP_TRACE; -+ sig = SIGTRAP; -+ break; -+ case VEC_TRAP2: -+ case VEC_TRAP3: -+ case VEC_TRAP4: -+ case VEC_TRAP5: -+ case VEC_TRAP6: -+ case VEC_TRAP7: -+ case VEC_TRAP8: -+ case VEC_TRAP9: -+ case VEC_TRAP10: -+ case VEC_TRAP11: -+ case VEC_TRAP12: -+ case VEC_TRAP13: -+ case VEC_TRAP14: -+ info.si_code = ILL_ILLTRP; -+ sig = SIGILL; -+ break; -+ case VEC_FPBRUC: -+ case VEC_FPOE: -+ case VEC_FPNAN: -+ info.si_code = FPE_FLTINV; -+ sig = SIGFPE; -+ break; -+ case VEC_FPIR: -+ info.si_code = FPE_FLTRES; -+ sig = SIGFPE; -+ break; -+ case VEC_FPDIVZ: -+ info.si_code = FPE_FLTDIV; -+ sig = SIGFPE; -+ break; -+ case VEC_FPUNDER: -+ info.si_code = FPE_FLTUND; -+ sig = SIGFPE; -+ break; -+ case VEC_FPOVER: -+ info.si_code = FPE_FLTOVF; -+ sig = SIGFPE; -+ break; -+ case VEC_ZERODIV: -+ info.si_code = FPE_INTDIV; -+ sig = SIGFPE; -+ break; -+ case VEC_CHK: -+ case VEC_TRAP: -+ info.si_code = FPE_INTOVF; -+ sig = SIGFPE; -+ break; -+ case VEC_TRACE: /* ptrace single step */ -+ info.si_code = TRAP_TRACE; -+ sig = SIGTRAP; -+ break; -+ case VEC_TRAP15: /* breakpoint */ -+ info.si_code = TRAP_BRKPT; -+ sig = SIGTRAP; -+ break; -+ default: -+ info.si_code = ILL_ILLOPC; -+ sig = SIGILL; -+ break; -+ } -+ info.si_signo = sig; -+ info.si_errno = 0; -+ switch (fp->ptregs.format) { -+ default: -+ info.si_addr = (void *) fp->ptregs.pc; -+ break; -+ case 2: -+ info.si_addr = (void *) fp->un.fmt2.iaddr; -+ break; -+ case 7: -+ info.si_addr = (void *) fp->un.fmt7.effaddr; -+ break; -+ case 9: -+ info.si_addr = (void *) fp->un.fmt9.iaddr; -+ break; -+ case 10: -+ info.si_addr = (void *) fp->un.fmta.daddr; -+ break; -+ case 11: -+ info.si_addr = (void *) fp->un.fmtb.daddr; -+ break; -+ } -+ force_sig_info(sig, &info, current); -+} -+ -+asmlinkage void set_esp0(unsigned long ssp) -+{ -+ current->thread.esp0 = ssp; -+} -+ -+/* -+ * The architecture-independent backtrace generator -+ */ -+void dump_stack(void) -+{ -+ unsigned long stack; -+ -+ show_stack(current, &stack); -+} -+EXPORT_SYMBOL(dump_stack); -+ -+#ifdef CONFIG_M68KFPU_EMU -+asmlinkage void fpemu_signal(int signal, int code, void *addr) -+{ -+ siginfo_t info; -+ -+ info.si_signo = signal; -+ info.si_errno = 0; -+ info.si_code = code; -+ info.si_addr = addr; -+ force_sig_info(signal, &info, current); -+} -+#endif ---- /dev/null -+++ b/arch/m68k/coldfire/vmlinux-cf.lds -@@ -0,0 +1,92 @@ -+/* ld script to make m68k Coldfire Linux kernel */ -+ -+#include <asm-generic/vmlinux.lds.h> -+ -+OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k") -+OUTPUT_ARCH(m68k) -+ENTRY(_start) -+jiffies = jiffies_64 + 4; -+SECTIONS -+{ -+ . = 0xC0020000; -+ _text = .; /* Text and read-only data */ -+ .text : { -+ *(.text.head) -+ TEXT_TEXT -+ SCHED_TEXT -+ LOCK_TEXT -+ *(.fixup) -+ *(.gnu.warning) -+ } :text = 0x4e75 -+ -+ _etext = .; /* End of text section */ -+ -+ . = ALIGN(16); -+ __start___ex_table = .; -+ __ex_table : { *(__ex_table) } -+ __stop___ex_table = .; -+ -+ RODATA -+ -+ .data : { /* Data */ -+ DATA_DATA -+ CONSTRUCTORS -+ } -+ -+ .bss : { *(.bss) } /* BSS */ -+ -+ . = ALIGN(16); -+ .data.cacheline_aligned : { *(.data.cacheline_aligned) } :data -+ -+ _edata = .; /* End of data section */ -+ -+ . = ALIGN(8192); /* Initrd */ -+ __init_begin = .; -+ .init.text : { -+ _sinittext = .; -+ *(.init.text) -+ _einittext = .; -+ } -+ .init.data : { *(.init.data) } -+ . = ALIGN(16); -+ __setup_start = .; -+ .init.setup : { *(.init.setup) } -+ __setup_end = .; -+ __initcall_start = .; -+ .initcall.init : { -+ INITCALLS -+ } -+ __initcall_end = .; -+ __con_initcall_start = .; -+ .con_initcall.init : { *(.con_initcall.init) } -+ __con_initcall_end = .; -+ SECURITY_INIT -+#ifdef CONFIG_BLK_DEV_INITRD -+ . = ALIGN(8192); -+ __initramfs_start = .; -+ .init.ramfs : { *(.init.ramfs) } -+ __initramfs_end = .; -+#endif -+ . = ALIGN(8192); -+ __init_end = .; -+ -+ .data.init_task : { *(.data.init_task) } /* The initial task and kernel stack */ -+ -+ _end = . ; -+ -+ /* Sections to be discarded */ -+ /DISCARD/ : { -+ *(.exit.text) -+ *(.exit.data) -+ *(.exitcall.exit) -+ } -+ -+ /* Stabs debugging sections. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ .stab.excl 0 : { *(.stab.excl) } -+ .stab.exclstr 0 : { *(.stab.exclstr) } -+ .stab.index 0 : { *(.stab.index) } -+ .stab.indexstr 0 : { *(.stab.indexstr) } -+ .comment 0 : { *(.comment) } -+} |