From 823ad3e6e88353226ec28f48183a467181887a1b Mon Sep 17 00:00:00 2001 From: Kurt Mahan Date: Wed, 31 Oct 2007 16:56:09 -0600 Subject: [PATCH] Core Coldfire/MCF54455 kernel changes. LTIBName: mcfv4e-kernel-mods Signed-off-by: Kurt Mahan --- arch/m68k/Kconfig | 65 ++++++++++++++++++++++++++++++++++++++- arch/m68k/Kconfig.debug | 9 +++++ arch/m68k/Makefile | 14 ++++++++ arch/m68k/kernel/Makefile | 15 ++++++--- arch/m68k/kernel/asm-offsets.c | 7 ++++ arch/m68k/kernel/dma.c | 17 ++++++++++ arch/m68k/kernel/process.c | 57 +++++++++++++++++++++++++++++++++++ arch/m68k/kernel/setup.c | 49 ++++++++++++++++++++++++++---- arch/m68k/kernel/time.c | 5 +++ arch/m68k/kernel/vmlinux.lds.S | 2 + 10 files changed, 227 insertions(+), 13 deletions(-) --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -119,6 +119,20 @@ config SUN3 If you don't want to compile a kernel exclusively for a Sun 3, say N. +config COLDFIRE + bool "ColdFire V4e support" + default y + select CFV4E + help + Say Y if you want to build a kernel to run on one of the ColdFire + V4e boards. + +config CFV4E + bool + depends on COLDFIRE + select MMU_CFV4E if MMU + default y + config AMIGA bool "Amiga support" depends on !MMU_SUN3 @@ -294,14 +308,53 @@ config M68060 If you anticipate running this kernel on a computer with a MC68060 processor, say Y. Otherwise, say N. +config M54455 + bool "MCF54455 support" + depends on COLDFIRE + default y + help + This option will add support for the MCF54455 processor with mmu. + +config MCFCLK + int "M54455EVB System Clock" + depends on M54455 + default 266666666 + help + System clock for EVB. Usually 266MHz for u-boot and 200MHz for dBUG. + +config MCF_USER_HALT + bool "Coldfire User Halt Enable" + depends on M54455 + default n + help + Enables the HALT instruction in User Mode. + config MMU_MOTOROLA bool - depends on MMU && !MMU_SUN3 + depends on MMU && !MMU_SUN3 && !COLDFIRE default y config MMU_SUN3 bool +config MMU_CFV4E + bool + +config SDRAM_BASE + hex + depends on M54455 + default 0x40000000 + +config SDRAM_SIZE + hex + depends on M54455 + default 0x0FFFFFFF + +config NOR_FLASH_BASE + hex "NOR Flash Base Address" + depends on M54455 + default 0x00000000 + config M68KFPU_EMU bool "Math emulation support (EXPERIMENTAL)" depends on EXPERIMENTAL @@ -468,6 +521,14 @@ config ZONE_DMA source "drivers/pci/Kconfig" source "drivers/zorro/Kconfig" +endmenu + +menu "Power management options" + +config PM + bool "Power Management support" + help + Support processor power management modes endmenu @@ -647,7 +708,7 @@ config DN_SERIAL config SERIAL_CONSOLE bool "Support for serial port console" - depends on (AMIGA || ATARI || MAC || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_SCC=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL) + depends on (AMIGA || ATARI || MAC || SUN3 || SUN3X || VME || APOLLO || COLDFIRE) && (ATARI_MFPSER=y || ATARI_SCC=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL || SERIAL_COLDFIRE) ---help--- If you say Y here, it will be possible to use a serial port as the system console (the system console is the device which receives all --- a/arch/m68k/Kconfig.debug +++ b/arch/m68k/Kconfig.debug @@ -2,4 +2,13 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config BOOTPARAM + bool 'Compiled-in Kernel Boot Parameter' + depends on COLDFIRE + +config BOOTPARAM_STRING + string 'Kernel Boot Parameter' + default 'console=ttyS0,115200' + depends on BOOTPARAM + endmenu --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile @@ -16,7 +16,9 @@ KBUILD_DEFCONFIG := amiga_defconfig # override top level makefile +ifndef CONFIG_COLDFIRE AS += -m68020 +endif LDFLAGS := -m m68kelf LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds ifneq ($(SUBARCH),$(ARCH)) @@ -36,6 +38,7 @@ CHECKFLAGS += -D__mc68000__ KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2 # enable processor switch if compiled only for a single cpu +ifndef CONFIG_COLDFIRE ifndef CONFIG_M68020 ifndef CONFIG_M68030 @@ -49,6 +52,12 @@ endif endif endif +endif + +ifdef CONFIG_M54455 +CFLAGS := $(CFLAGS) -march=isac -mcpu=54455 -msoft-float -g +AFLAGS := $(AFLAGS) -march=isac -mcpu=54455 -msoft-float +endif ifdef CONFIG_KGDB # If configured for kgdb support, include debugging infos and keep the @@ -57,8 +66,12 @@ KBUILD_CFLAGS := $(subst -fomit-frame-po endif ifndef CONFIG_SUN3 +ifndef CONFIG_COLDFIRE head-y := arch/m68k/kernel/head.o else +head-y := arch/m68k/coldfire/head.o +endif +else head-y := arch/m68k/kernel/sun3-head.o endif @@ -79,6 +92,7 @@ core-$(CONFIG_SUN3) += arch/m68k/sun3/ core-$(CONFIG_M68040) += arch/m68k/fpsp040/ core-$(CONFIG_M68060) += arch/m68k/ifpsp060/ core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/ +core-$(CONFIG_COLDFIRE) += arch/m68k/coldfire/ all: zImage --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -2,14 +2,19 @@ # Makefile for the linux kernel. # -ifndef CONFIG_SUN3 - extra-y := head.o +ifdef CONFIG_SUN3 + extra-y := sun3-head.o vmlinux.lds + obj-y := entry.o signal.o ints.o else - extra-y := sun3-head.o +ifndef CONFIG_COLDFIRE + extra-y := head.o vmlinux.lds + obj-y := entry.o signal.o traps.o ints.o +else # CONFIG_COLDFIRE + extra-y := ../coldfire/head.o vmlinux.lds +endif endif -extra-y += vmlinux.lds -obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \ +obj-y += process.o ptrace.o module.o \ sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o devres.o devres-y = ../../../kernel/irq/devres.o --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c @@ -58,8 +58,15 @@ int main(void) DEFINE(PT_A2, offsetof(struct pt_regs, a2)); DEFINE(PT_PC, offsetof(struct pt_regs, pc)); DEFINE(PT_SR, offsetof(struct pt_regs, sr)); +#ifdef CONFIG_COLDFIRE + /* Need to get the context out of struct mm for ASID setting */ + DEFINE(MM_CONTEXT, offsetof(struct mm_struct, context)); + /* Coldfire exception frame has vector *before* pc */ + DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) - 4); +#else /* bitfields are a bit difficult */ DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4); +#endif /* offsets into the irq_handler struct */ DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler)); --- a/arch/m68k/kernel/dma.c +++ b/arch/m68k/kernel/dma.c @@ -17,6 +17,7 @@ void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t flag) { +#ifndef CONFIG_M54455 struct page *page, **map; pgprot_t pgprot; void *addr; @@ -55,6 +56,18 @@ void *dma_alloc_coherent(struct device * kfree(map); return addr; +#else + /* + * On the M5445x platform the memory allocated with GFP_DMA + * is guaranteed to be DMA'able. + */ + void *addr; + + size = PAGE_ALIGN(size); + addr = kmalloc(size, GFP_DMA); + *handle = virt_to_phys(addr); + return addr; +#endif } EXPORT_SYMBOL(dma_alloc_coherent); @@ -62,7 +75,11 @@ void dma_free_coherent(struct device *de void *addr, dma_addr_t handle) { pr_debug("dma_free_coherent: %p, %x\n", addr, handle); +#ifndef CONFIG_M54455 vfree(addr); +#else + kfree(addr); +#endif } EXPORT_SYMBOL(dma_free_coherent); --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -191,6 +191,7 @@ EXPORT_SYMBOL(kernel_thread); void flush_thread(void) { +#if !defined(CONFIG_COLDFIRE) unsigned long zero = 0; set_fs(USER_DS); current->thread.fs = __USER_DS; @@ -198,6 +199,14 @@ void flush_thread(void) asm volatile (".chip 68k/68881\n\t" "frestore %0@\n\t" ".chip 68k" : : "a" (&zero)); +#else + set_fs(USER_DS); + current->thread.fs = USER_DS; +#if defined(CONFIG_FPU) + if (!FPU_IS_EMU) + asm volatile ("frestore %0@\n\t" : : "a" (&zero)); +#endif +#endif } /* @@ -261,6 +270,7 @@ int copy_thread(int nr, unsigned long cl * Must save the current SFC/DFC value, NOT the value when * the parent was last descheduled - RGH 10-08-96 */ +#if !defined(CONFIG_COLDFIRE) p->thread.fs = get_fs().seg; if (!FPU_IS_EMU) { @@ -272,9 +282,34 @@ int copy_thread(int nr, unsigned long cl "fmoveml %/fpiar/%/fpcr/%/fpsr,%1" : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0]) : "memory"); +#else + p->thread.fs = get_fs(); + +#if defined(CONFIG_FPU) + if (!FPU_IS_EMU) { + /* Copy the current fpu state */ + asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) + : "memory"); + + if (p->thread.fpstate[0]) { + asm volatile ("fmovemd %/fp0-%/fp7,%0" + : : "m" (p->thread.fp[0]) + : "memory"); + asm volatile ("fmovel %/fpiar,%0" + : : "m" (p->thread.fpcntl[0]) + : "memory"); + asm volatile ("fmovel %/fpcr,%0" + : : "m" (p->thread.fpcntl[1]) + : "memory"); + asm volatile ("fmovel %/fpsr,%0" + : : "m" (p->thread.fpcntl[2]) + : "memory"); + } /* Restore the state in case the fpu was busy */ asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0])); } +#endif +#endif return 0; } @@ -283,7 +318,9 @@ int copy_thread(int nr, unsigned long cl int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) { +#if !defined(CONFIG_COLDFIRE) || defined(CONFIG_FPU) char fpustate[216]; +#endif if (FPU_IS_EMU) { int i; @@ -300,6 +337,7 @@ int dump_fpu (struct pt_regs *regs, stru } /* First dump the fpu context to avoid protocol violation. */ +#if !defined(CONFIG_COLDFIRE) asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory"); if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2]) return 0; @@ -310,6 +348,25 @@ int dump_fpu (struct pt_regs *regs, stru asm volatile ("fmovemx %/fp0-%/fp7,%0" :: "m" (fpu->fpregs[0]) : "memory"); +#elif defined(CONFIG_FPU) + asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory"); + if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2]) + return 0; + + asm volatile ("fmovel %/fpiar,%0" + : : "m" (fpu->fpcntl[0]) + : "memory"); + asm volatile ("fmovel %/fpcr,%0" + : : "m" (fpu->fpcntl[1]) + : "memory"); + asm volatile ("fmovel %/fpsr,%0" + : : "m" (fpu->fpcntl[2]) + : "memory"); + asm volatile ("fmovemd %/fp0-%/fp7,%0" + : : "m" (fpu->fpregs[0]) + : "memory"); +#endif + return 1; } EXPORT_SYMBOL(dump_fpu); --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -67,13 +67,22 @@ EXPORT_SYMBOL(m68k_memory); struct mem_info m68k_ramdisk; +#if !defined(CONFIG_COLDFIRE) static char m68k_command_line[CL_SIZE]; +#else +char m68k_command_line[CL_SIZE]; +unsigned long uboot_info_stk; +EXPORT_SYMBOL(uboot_info_stk); +#endif void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL; /* machine dependent irq functions */ void (*mach_init_IRQ) (void) __initdata = NULL; void (*mach_get_model) (char *model); int (*mach_get_hardware_list) (char *buffer); +#ifdef CONFIG_COLDFIRE +void (*mach_tick)(void); +#endif /* machine dependent timer functions */ unsigned long (*mach_gettimeoffset) (void); int (*mach_hwclk) (int, struct rtc_time*); @@ -128,13 +137,17 @@ extern void config_hp300(void); extern void config_q40(void); extern void config_sun3x(void); +#ifdef CONFIG_COLDFIRE +void coldfire_sort_memrec(void); +#endif + #define MASK_256K 0xfffc0000 extern void paging_init(void); static void __init m68k_parse_bootinfo(const struct bi_record *record) { - while (record->tag != BI_LAST) { + while ((record->tag != BI_LAST) && !(CONFIG_COLDFIRE)) { int unknown = 0; const unsigned long *data = record->data; @@ -192,7 +205,11 @@ static void __init m68k_parse_bootinfo(c record->size); } - m68k_realnum_memory = m68k_num_memory; +#ifdef CONFIG_COLDFIRE + coldfire_sort_memrec(); +#endif + + m68k_realnum_memory = m68k_num_memory; #ifdef CONFIG_SINGLE_MEMORY_CHUNK if (m68k_num_memory > 1) { printk("Ignoring last %i chunks of physical memory\n", @@ -205,7 +222,9 @@ static void __init m68k_parse_bootinfo(c void __init setup_arch(char **cmdline_p) { extern int _etext, _edata, _end; +#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE) int i; +#endif /* The bootinfo is located right after the kernel bss */ m68k_parse_bootinfo((const struct bi_record *)&_end); @@ -220,9 +239,10 @@ void __init setup_arch(char **cmdline_p) * We should really do our own FPU check at startup. * [what do we do with buggy 68LC040s? if we have problems * with them, we should add a test to check_bugs() below] */ -#ifndef CONFIG_M68KFPU_EMU_ONLY +#if !defined(CONFIG_M68KFPU_EMU_ONLY) && defined(CONFIG_FPU) /* clear the fpu if we have one */ - if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) { + if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060| + FPU_CFV4E)) { volatile int zero = 0; asm volatile ("frestore %0" : : "m" (zero)); } @@ -310,13 +330,18 @@ void __init setup_arch(char **cmdline_p) config_sun3x(); break; #endif +#ifdef CONFIG_COLDFIRE + case MACH_CFMMU: + config_coldfire(); + break; +#endif default: panic("No configuration setup"); } paging_init(); -#ifndef CONFIG_SUN3 +#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE) for (i = 1; i < m68k_num_memory; i++) free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr, m68k_memory[i].size); @@ -343,6 +368,10 @@ void __init setup_arch(char **cmdline_p) #endif /* !CONFIG_SUN3 */ +#ifdef CONFIG_COLDFIRE + mmu_context_init(); +#endif + /* set ISA defs early as possible */ #if defined(CONFIG_ISA) && defined(MULTI_ISA) #if defined(CONFIG_Q40) @@ -373,6 +402,7 @@ static int show_cpuinfo(struct seq_file #define LOOP_CYCLES_68030 (8) #define LOOP_CYCLES_68040 (3) #define LOOP_CYCLES_68060 (1) +#define LOOP_CYCLES_COLDFIRE (2) if (CPU_IS_020) { cpu = "68020"; @@ -386,6 +416,9 @@ static int show_cpuinfo(struct seq_file } else if (CPU_IS_060) { cpu = "68060"; clockfactor = LOOP_CYCLES_68060; + } else if (CPU_IS_CFV4E) { + cpu = "ColdFire V4e"; + clockfactor = LOOP_CYCLES_COLDFIRE; } else { cpu = "680x0"; clockfactor = 0; @@ -404,6 +437,8 @@ static int show_cpuinfo(struct seq_file fpu = "68060"; else if (m68k_fputype & FPU_SUNFPA) fpu = "Sun FPA"; + else if (m68k_fputype & FPU_CFV4E) + fpu = "ColdFire V4e"; else fpu = "none"; #endif @@ -420,6 +455,8 @@ static int show_cpuinfo(struct seq_file mmu = "Sun-3"; else if (m68k_mmutype & MMU_APOLLO) mmu = "Apollo"; + else if (m68k_mmutype & MMU_CFV4E) + mmu = "ColdFire"; else mmu = "unknown"; @@ -482,7 +519,7 @@ int get_hardware_list(char *buffer) void check_bugs(void) { -#ifndef CONFIG_M68KFPU_EMU +#if !defined(CONFIG_M68KFPU_EMU) && !defined(CONFIG_M54455) if (m68k_fputype == 0) { printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, " "WHICH IS REQUIRED BY LINUX/M68K ***\n"); --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -40,6 +40,11 @@ static inline int set_rtc_mmss(unsigned */ static irqreturn_t timer_interrupt(int irq, void *dummy) { +#ifdef CONFIG_COLDFIRE + /* kick hardware timer if necessary */ + if (mach_tick) + mach_tick(); +#endif do_timer(1); #ifndef CONFIG_SMP update_process_times(user_mode(get_irq_regs())); --- a/arch/m68k/kernel/vmlinux.lds.S +++ b/arch/m68k/kernel/vmlinux.lds.S @@ -5,6 +5,8 @@ PHDRS } #ifdef CONFIG_SUN3 #include "vmlinux-sun3.lds" +#elif CONFIG_COLDFIRE +#include "../coldfire/vmlinux-cf.lds" #else #include "vmlinux-std.lds" #endif