summaryrefslogtreecommitdiffstats
path: root/arch/m68k/cpu
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2008-04-04 18:16:06 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2008-04-04 18:16:06 +0200
commitae6cc2d36baec9dee3a82d5542354fcac6b7679c (patch)
tree7078ba7beefa5b61fd9c38f76c8449d4fee1bd67 /arch/m68k/cpu
parent35497c757ce705f4c2a19662e9b2f130583b673b (diff)
downloadbarebox-ae6cc2d36baec9dee3a82d5542354fcac6b7679c.tar.gz
barebox-ae6cc2d36baec9dee3a82d5542354fcac6b7679c.tar.xz
[m68k] Add Freescale Coldfire V4E Architecture support
- Added m68k vector, exception & interrupt handlers - Added m68k macros to access m68k movec registers - Added Coldfire support code (MultiChannelDMA) - Added board support for phytec phyCore-MCF baseboard - Added board support for konzeptpark MCB2 prototype Signed-off-by: Carsten Schlote <schlote@vahanus.net>
Diffstat (limited to 'arch/m68k/cpu')
-rw-r--r--arch/m68k/cpu/Makefile41
-rw-r--r--arch/m68k/cpu/cpu.c185
-rw-r--r--arch/m68k/cpu/cw_console_io.c116
-rw-r--r--arch/m68k/cpu/early_init_support.c41
-rw-r--r--arch/m68k/cpu/interrupts.c246
-rw-r--r--arch/m68k/cpu/start-mcfv4e.S677
6 files changed, 1306 insertions, 0 deletions
diff --git a/arch/m68k/cpu/Makefile b/arch/m68k/cpu/Makefile
new file mode 100644
index 0000000000..4653534e47
--- /dev/null
+++ b/arch/m68k/cpu/Makefile
@@ -0,0 +1,41 @@
+#
+# (C) Copyright 2007 Carsten Schlote <schlote@vahanus.net>
+# See file CREDITS for list of people who contributed to this project.
+#
+# This file is part of U-Boot V2.
+#
+# U-Boot V2 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 3 of the License, or
+# (at your option) any later version.
+#
+# U-Boot V2 is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with U-Boot V2. If not, see <http://www.gnu.org/licenses/>.
+#
+
+obj-y += cpu.o
+obj-y += interrupts.o
+
+#
+# Support code for early IO over BDM wigglers
+#
+
+# obj-y += early_init_support.o
+
+#
+# Support for relocated early initdata
+#
+obj-$(CONFIG_HAS_EARLY_INIT) += early_init_support.o
+
+#
+# Startup codes - try to merge them into single file!
+#
+obj-$(CONFIG_ARCH_MCF54xx) += start-mcfv4e.o
+obj-$(CONFIG_ARCH_MCF5445x) += start-mcfv4m.o
+
+start-mcfv4e.o : start-mcfv4e.s \ No newline at end of file
diff --git a/arch/m68k/cpu/cpu.c b/arch/m68k/cpu/cpu.c
new file mode 100644
index 0000000000..5c48add8d9
--- /dev/null
+++ b/arch/m68k/cpu/cpu.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2008 Carsten Schlote <c.schlote@konzeptpark.de>
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This file is part of U-Boot V2.
+ *
+ * U-Boot V2 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * U-Boot V2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with U-Boot V2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * A few helper functions for M6kK/Coldfire
+ */
+#include <common.h>
+#include <command.h>
+#include <init.h>
+#include <asm/proc/processor.h> // FIXME -stup place
+#include <asm/arch/mcf54xx-regs.h>
+
+static uint32_t CACR_shadow = MCF5XXX_CACR_BEC;
+
+/*
+ * Reset init value := 0x010C0100
+ * MCF5XXX_CACR_DCINVA
+ * MCF5XXX_CACR_BEC
+ * MCF5XXX_CACR_BCINVA
+ * MCF5XXX_CACR_ICINVA
+ */
+
+/**
+ * Enable processor's instruction cache
+ */
+void icache_enable (void)
+{
+ CACR_shadow |= MCF5XXX_CACR_IEC;
+ mcf5xxx_wr_cacr( CACR_shadow );
+}
+
+/**
+ * Disable processor's instruction cache
+ */
+void icache_disable (void)
+{
+ CACR_shadow &= ~MCF5XXX_CACR_IEC;
+ mcf5xxx_wr_cacr( CACR_shadow );
+}
+
+/**
+ * Detect processor's current instruction cache status
+ * @return 0=disabled, 1=enabled
+ */
+int icache_status (void)
+{
+ return (CACR_shadow & MCF5XXX_CACR_IEC)?1:0;
+}
+
+/**
+ * Enable processor's data cache
+ */
+void dcache_enable (void)
+{
+ CACR_shadow |= MCF5XXX_CACR_DEC;
+ mcf5xxx_wr_cacr( CACR_shadow );
+}
+
+/**
+ * Disable processor's data cache
+ */
+void dcache_disable (void)
+{
+ CACR_shadow &= ~MCF5XXX_CACR_DEC;
+ mcf5xxx_wr_cacr( CACR_shadow );
+}
+
+/**
+ * Detect processor's current instruction cache status
+ * @return 0=disabled, 1=enabled
+ */
+int dcache_status (void)
+{
+ return (CACR_shadow & MCF5XXX_CACR_DEC)?1:0;
+}
+
+/**
+ * Flush CPU caches to memory
+ */
+void cpu_cache_flush(void)
+{
+ uint32_t way, set;
+ void *addr;
+
+ for ( way=0; way < 4; way++ ) {
+ addr = (void*)way;
+ for ( set=0; set < 512; set++ ) {
+ mcf5xxx_cpushl_bc ( addr );
+ addr += 0x10;
+ }
+ }
+}
+
+/**
+ * Flush CPU caches to memory and disable them.
+ */
+void cpu_cache_disable(void)
+{
+ uint32_t lastipl;
+
+ lastipl = asm_set_ipl( 7 );
+
+ cpu_cache_flush();
+ mcf5xxx_wr_acr0( 0 );
+ mcf5xxx_wr_acr1( 0 );
+ mcf5xxx_wr_acr2( 0 );
+ mcf5xxx_wr_acr3( 0 );
+
+ CACR_shadow &= ~MCF5XXX_CACR_IEC;
+ CACR_shadow &= ~MCF5XXX_CACR_DEC;
+ mcf5xxx_wr_cacr( CACR_shadow | (MCF5XXX_CACR_DCINVA|MCF5XXX_CACR_ICINVA));
+
+ lastipl = asm_set_ipl( lastipl );
+}
+
+/**
+ * Prepare a "clean" CPU for Linux to run
+ * @return 0 (always)
+ *
+ * This function is called by the generic U-Boot part just before we call
+ * Linux. It prepares the processor for Linux.
+ */
+int cleanup_before_linux (void)
+{
+ /*
+ * we never enable dcache so we do not need to disable
+ * it. Linux can be called with icache enabled, so just
+ * do nothing here
+ */
+
+ /* flush I/D-cache */
+ cpu_cache_disable();
+
+ /* reenable icache */
+ icache_enable();
+ return (0);
+}
+/** @page m68k_boot_preparation Linux Preparation on M68k/Coldfire
+ *
+ * For M68K we never enable data cache so we do not need to disable it again.
+ *
+ * Linux can be called with instruction cache enabled. As this is the
+ * default setting we are running in U-Boot, there's no special preparation
+ * required.
+ */
+
+
+/** Early init of Coldfire V4E CPU
+ */
+static int cpu_init (void)
+{
+ /* Enable ICache - branch cache is already on */
+ icache_enable();
+
+ /*
+ * setup up stacks if necessary
+ * setup other CPU specifics here to prepare
+ * handling of exceptions and interrupts
+ */
+#ifdef CONFIG_USE_IRQ
+ printf("Prepare CPU interrupts for handlers\n");
+ mcf_interrupts_initialize();
+#endif
+
+ return 0;
+}
+
+core_initcall(cpu_init);
diff --git a/arch/m68k/cpu/cw_console_io.c b/arch/m68k/cpu/cw_console_io.c
new file mode 100644
index 0000000000..b0575e4c8a
--- /dev/null
+++ b/arch/m68k/cpu/cw_console_io.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2008 Carsten Schlote <c.schlote@konzeptpark.de>
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This file is part of U-Boot V2.
+ *
+ * U-Boot V2 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * U-Boot V2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with U-Boot V2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Debug output stubs over BDM for Codewarrior
+ */
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <reloc.h>
+#include <init.h>
+
+#ifdef CONFIG_HAS_EARLY_INIT
+
+
+#if 0 // FIXME - make a CW debug port serial driver for u-boot
+
+/*
+ * The result of an I/O command can be any one of the following.
+ */
+typedef enum DSIOResult
+{
+ kDSIONoError = 0x00,
+ kDSIOError = 0x01,
+ kDSIOEOF = 0x02
+} DSIOResult;
+
+/*
+ * MessageCommandID
+ */
+typedef enum MessageCommandID
+{
+ /*
+ * target->host support commands
+ */
+
+ kDSWriteFile = 0xD0, /* L2 L3 */
+ kDSReadFile = 0xD1 /* L2 L3 */
+
+} MessageCommandID;
+
+
+enum DSIOResult TransferData(
+ MessageCommandID msg,
+ unsigned char *buffer, int size,
+ int * txsize
+)
+{
+ enum DSIOResult iores = kDSIOError;
+ unsigned long sized2=0;
+
+ /* -- Call codewarrior stub -- */
+ __asm__ __volatile__ (
+" move.l %[cmd],%%d0 \n"
+" move.l #0,%%d1 \n"
+" move.l %[size],%%d2 \n"
+" move.l %[buffer],%%d3 \n"
+" trap #14 \n"
+" move.l %%d1,%[txsize] \n"
+" move.l %%d0,%[res] \n"
+ : [res] "=r" (iores), [txsize] "=g" (sized2)
+ : [cmd] "g" (msg), [size] "g" (size), [buffer] "g" (buffer)
+ : "d2","d3" );
+
+ if (txsize!=NULL) *txsize=sized2;
+ return iores;
+}
+
+void *get_early_console_base(const char *name)
+{
+ return (void*)0xdeadbeef;
+}
+
+static unsigned char early_iobuffer[80];
+static int early_iobuffer_cnt;
+
+void early_console_putc(void *base, char c)
+{
+ early_iobuffer[early_iobuffer_cnt++] = c;
+ if ( ( early_iobuffer_cnt >= sizeof(early_iobuffer)) ||
+ (c == '\n') )
+ {
+ TransferData(kDSWriteFile,early_iobuffer,early_iobuffer_cnt, NULL);
+ early_iobuffer_cnt = 0;
+ }
+}
+
+void early_console_init(void *base, int baudrate)
+{
+ early_iobuffer_cnt = 0;
+}
+
+//void early_console_start(const char *name, int baudrate)
+//{
+//}
+
+#endif
+
+#endif
diff --git a/arch/m68k/cpu/early_init_support.c b/arch/m68k/cpu/early_init_support.c
new file mode 100644
index 0000000000..2f6be43539
--- /dev/null
+++ b/arch/m68k/cpu/early_init_support.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2008 Carsten Schlote <c.schlote@konzeptpark.de>
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This file is part of U-Boot V2.
+ *
+ * U-Boot V2 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * U-Boot V2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with U-Boot V2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Early InitData support routines
+ */
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <reloc.h>
+#include <init.h>
+
+#ifdef CONFIG_HAS_EARLY_INIT
+
+/** Returns relocation offset to early init data
+ */
+unsigned long reloc_offset(void)
+{
+ //extern char __early_init_data_begin[];
+ //FIXME: return (unsigned long)init_data_ptr - (unsigned long)__early_init_data_begin;
+ return 0;
+}
+
+#endif
diff --git a/arch/m68k/cpu/interrupts.c b/arch/m68k/cpu/interrupts.c
new file mode 100644
index 0000000000..16aac38ad5
--- /dev/null
+++ b/arch/m68k/cpu/interrupts.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2008 Carsten Schlote <c.schlote@konzeptpark.de>
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This file is part of U-Boot V2.
+ *
+ * U-Boot V2 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * U-Boot V2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with U-Boot V2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Interrupt routines and supporting code for Coldfire V4E
+ */
+#include <common.h>
+#include <asm/ptrace.h>
+#include <asm/arch/mcf54xx-regs.h>
+
+#ifdef CONFIG_USE_IRQ
+void enable_interrupts(void)
+{
+ asm_set_ipl(0);
+}
+
+int disable_interrupts(void)
+{
+ return asm_set_ipl(7) ? 1 : 0;
+}
+#endif
+
+/**
+ */
+static void mcf_bad_mode (void)
+{
+ panic ("Resetting CPU ...\n");
+ mdelay(3000);
+ reset_cpu (0);
+}
+
+/**
+ */
+static void mcf_show_regs (struct pt_regs *regs)
+{
+ unsigned long flags;
+ flags = condition_codes (regs);
+
+ printf ("pc : [<%08lx>]\n"
+ "sp : %08lx fp : %08lx\n",
+ instruction_pointer (regs),
+ regs->M68K_sp, regs->M68K_a6);
+
+ printf ("d0-d3 : %08lx %08lx %08lx %08lx\n",
+ regs->M68K_d0, regs->M68K_d1, regs->M68K_d2, regs->M68K_d3);
+ printf ("d3-d7 : %08lx %08lx %08lx %08lx\n",
+ regs->M68K_d3, regs->M68K_d4, regs->M68K_d5, regs->M68K_d6);
+
+ printf ("a0-d3 : %08lx %08lx %08lx %08lx\n",
+ regs->M68K_a0, regs->M68K_a1, regs->M68K_a2, regs->M68K_a3);
+ printf ("a3-d7 : %08lx %08lx %08lx %08lx\n",
+ regs->M68K_a3, regs->M68K_a4, regs->M68K_a5, regs->M68K_a6);
+
+ printf ("fp0 : %08lx%08lx fp1 : %08lx%08lx\n",
+ regs->M68K_fp0+1, regs->M68K_fp0, regs->M68K_fp1+1, regs->M68K_fp1);
+ printf ("fp2 : %08lx%08lx fp3 : %08lx%08lx\n",
+ regs->M68K_fp2+1, regs->M68K_fp2, regs->M68K_fp3+1, regs->M68K_fp3);
+ printf ("fp4 : %08lx%08lx fp5 : %08lx%08lx\n",
+ regs->M68K_fp4+1, regs->M68K_fp4, regs->M68K_fp5+1, regs->M68K_fp5);
+ printf ("fp6 : %08lx%08lx fp7 : %08lx%08lx\n",
+ regs->M68K_fp6+1, regs->M68K_fp6, regs->M68K_fp7+1, regs->M68K_fp7);
+
+ printf ("Flags: %c%c%c%c",
+ flags & CC_X_BIT ? 'X' : 'x',
+ flags & CC_N_BIT ? 'N' : 'n',
+ flags & CC_Z_BIT ? 'Z' : 'z',
+ flags & CC_V_BIT ? 'V' : 'v',
+ flags & CC_C_BIT ? 'C' : 'c' );
+
+ printf (" IRQs %s (%0x) Mode %s\n",
+ interrupts_enabled (regs) ? "on" : "off", interrupts_enabled (regs),
+ user_mode (regs) ? "user" : "supervisor");
+}
+
+void mcf_execute_exception_handler (struct pt_regs *pt_regs)
+{
+ printf ("unhandled exception\n");
+ mcf_show_regs (pt_regs);
+ mcf_bad_mode ();
+}
+
+#ifndef CONFIG_USE_IRQ
+
+void mcf_execute_irq_handler (struct pt_regs *pt_regs, int vector)
+{
+ printf ("interrupt request\n");
+ mcf_show_regs (pt_regs);
+ mcf_bad_mode ();
+}
+
+#else
+
+#ifndef CONFIG_MAX_ISR_HANDLERS
+#define CONFIG_MAX_ISR_HANDLERS (20)
+#endif
+
+typedef struct
+{
+ int vector;
+ int (*handler)(void *, void *);
+ void *hdev;
+ void *harg;
+}
+mcfv4e_irq_handler_s;
+
+mcfv4e_irq_handler_s irq_handler_table[CONFIG_MAX_ISR_HANDLERS];
+
+/** Initialize an empty interrupt handler list
+ */
+void mcf_interrupts_initialize (void)
+{
+ int index;
+ for (index = 0; index < CONFIG_MAX_ISR_HANDLERS; index++)
+ {
+ irq_handler_table[index].vector = 0;
+ irq_handler_table[index].handler = 0;
+ irq_handler_table[index].hdev = 0;
+ irq_handler_table[index].harg = 0;
+ }
+}
+
+/** Add an interrupt handler to the handler list
+ *
+ * @param vector : M68k exception/interrupt vector number
+ * @param handler : Pointer to handler function
+ * @param hdev : Handler specific data
+ * @param harg : Handler specific arg
+ */
+int mcf_interrupts_register_handler(
+ int vector,
+ int (*handler)(void *, void *), void *hdev, void *harg)
+{
+ /*
+ * This function places an interrupt handler in the ISR table,
+ * thereby registering it so that the low-level handler may call it.
+ *
+ * The two parameters are intended for the first arg to be a
+ * pointer to the device itself, and the second a pointer to a data
+ * structure used by the device driver for that particular device.
+ */
+ int index;
+
+ if ((vector == 0) || (handler == NULL))
+ {
+ return 0;
+ }
+
+ for (index = 0; index < CONFIG_MAX_ISR_HANDLERS; index++)
+ {
+ if (irq_handler_table[index].vector == vector)
+ {
+ /* only one entry of each type per vector */
+ return 0;
+ }
+
+ if (irq_handler_table[index].vector == 0)
+ {
+ irq_handler_table[index].vector = vector;
+ irq_handler_table[index].handler = handler;
+ irq_handler_table[index].hdev = hdev;
+ irq_handler_table[index].harg = harg;
+ return 1;
+ }
+ }
+ return 0; /* no available slots */
+}
+
+/** Remove an interrupt handler from the handler list
+ *
+ * @param type : FIXME
+ * @param handler : Pointer of handler function to remove.
+ */
+void mcf_interrupts_remove_handler (int type ,int (*handler)(void *, void *))
+{
+ /*
+ * This routine removes from the ISR table all
+ * entries that matches 'handler'.
+ */
+ int index;
+
+ for (index = 0; index < CONFIG_MAX_ISR_HANDLERS; index++)
+ {
+ if (irq_handler_table[index].handler == handler)
+ {
+ irq_handler_table[index].vector = 0;
+ irq_handler_table[index].handler = 0;
+ irq_handler_table[index].hdev = 0;
+ irq_handler_table[index].harg = 0;
+ }
+ }
+}
+
+/** Traverse list of registered interrupts and call matching handlers.
+ *
+ * @param pt_regs : Pointer to saved register context
+ * @param vector : M68k exception/interrupt vector number
+ */
+int mcf_execute_irq_handler (struct pt_regs *pt_regs, int vector)
+{
+ /*
+ * This routine searches the ISR table for an entry that matches
+ * 'vector'. If one is found, then 'handler' is executed.
+ */
+ int index, retval = 0;
+
+ /*
+ * Try to locate a user-registered Interrupt Service Routine handler.
+ */
+ for (index = 0; index < CONFIG_MAX_ISR_HANDLERS; index++)
+ {
+ if (irq_handler_table[index].handler == NULL)
+ {
+ printf("\nFault: No handler for IRQ vector %ld found.\n", vector);
+ break;
+ }
+ if (irq_handler_table[index].vector == vector)
+ {
+ if (irq_handler_table[index].handler(irq_handler_table[index].hdev,irq_handler_table[index].harg))
+ {
+ retval = 1;
+ break;
+ }
+ }
+ }
+
+ return retval;
+}
+
+#endif
diff --git a/arch/m68k/cpu/start-mcfv4e.S b/arch/m68k/cpu/start-mcfv4e.S
new file mode 100644
index 0000000000..c77fe676bb
--- /dev/null
+++ b/arch/m68k/cpu/start-mcfv4e.S
@@ -0,0 +1,677 @@
+/*
+ * Copyright (c) 2008 Carsten Schlote <c.schlote@konzeptpark.de>
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This file is part of U-Boot V2.
+ *
+ * U-Boot V2 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * U-Boot V2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with U-Boot V2. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Resetcode and exception/interrupt shells for Coldfire V4E
+ *
+ * This file contains the common startup code for use on at least Coldfire
+ * V4E cores:
+ * - MCF547x
+ * - MCF548x
+ */
+#include <config.h>
+
+ .section ".vectors","a"
+
+/*
+ * Define some addresses from your board configuration file
+ */
+ .equ __MBAR,CFG_MBAR_ADDRESS
+ .globl __MBAR
+
+ .equ __CORE_SRAM0,CFG_CORE0_SRAM_ADDRESS
+ .equ __CORE_SRAM0_SIZE,CFG_CORE0_SRAM_SIZE
+
+ .equ __CORE_SRAM1,CFG_CORE1_SRAM_ADDRESS
+ .equ __CORE_SRAM1_SIZE,CFG_CORE1_SRAM_SIZE
+
+ /*
+ * Preload stack pointer with end of Core SRAM - useable _after_ you have
+ * setup the MBR register in reset code!
+ *
+ * The upper 4 LW of the Core SRAM are left spare - it can be used as
+ * fixed address temporay storage in the code below (ok, well also to
+ * fix up stack traces in the debugger)
+ *
+ * So we have a stack usable for C code, before we even started SDRAM!
+ */
+ .equ ___SP_INIT,__CORE_SRAM1+__CORE_SRAM1_SIZE-16
+
+/*
+ * Vector table for M68k and U-Boot Link Address
+ *
+ * On M68k/Coldfire cores all exceptions and interrupts are routed through
+ * a vector array. This vector is by default at address 0x0000_0000, but
+ * can be moved to any other 1MB aligned address.
+ *
+ * We take advantage of this to move U-Boot out of low memory. Some BDM
+ * debuggers won't like a moved vector base and might need tweaking to
+ * work.
+ *
+ * Note: Respect alignment restrictions for TEXT_BASE, which must be
+ * 1MB aligned.
+ */
+
+ .globl _u_boot_start
+_u_boot_start:
+
+VECTOR_TABLE:
+_VECTOR_TABLE:
+INITSP: .long ___SP_INIT /* Initial SP */
+INITPC: .long 0x410 /* Initial PC */
+vector02: .long _asm_exception_handler /* Access Error */
+vector03: .long _asm_exception_handler /* Address Error */
+vector04: .long _asm_exception_handler /* Illegal Instruction */
+vector05: .long _asm_exception_handler /* Divide by Zero */
+vector06: .long _asm_exception_handler /* Reserved */
+vector07: .long _asm_exception_handler /* Reserved */
+vector08: .long _asm_exception_handler /* Privilege Violation */
+vector09: .long _asm_exception_handler /* Trace */
+vector0A: .long _asm_exception_handler /* Unimplemented A-Line */
+vector0B: .long _asm_exception_handler /* Unimplemented F-Line */
+vector0C: .long _asm_exception_handler /* Non-PC Brkpt Debug Int */
+vector0D: .long _asm_exception_handler /* PC Brkpt Debug Int */
+vector0E: .long _asm_exception_handler /* Format Error */
+vector0F: .long _asm_exception_handler /* Unitialized Int */
+vector10: .long _asm_exception_handler /* Reserved */
+vector11: .long _asm_exception_handler /* Reserved */
+vector12: .long _asm_exception_handler /* Reserved */
+vector13: .long _asm_exception_handler /* Reserved */
+vector14: .long _asm_exception_handler /* Reserved */
+vector15: .long _asm_exception_handler /* Reserved */
+vector16: .long _asm_exception_handler /* Reserved */
+vector17: .long _asm_exception_handler /* Reserved */
+vector18: .long _asm_exception_handler /* Spurious Interrupt */
+vector19: .long _asm_isr_handler /* Autovector Level 1 */
+vector1A: .long _asm_isr_handler /* Autovector Level 2 */
+vector1B: .long _asm_isr_handler /* Autovector Level 3 */
+vector1C: .long _asm_isr_handler /* Autovector Level 4 */
+vector1D: .long _asm_isr_handler /* Autovector Level 5 */
+vector1E: .long _asm_isr_handler /* Autovector Level 6 */
+vector1F: .long _asm_isr_handler /* Autovector Level 7 */
+vector20: .long _asm_exception_handler /* TRAP #0 */
+vector21: .long _asm_exception_handler /* TRAP #1 */
+vector22: .long _asm_exception_handler /* TRAP #2 */
+vector23: .long _asm_exception_handler /* TRAP #3 */
+vector24: .long _asm_exception_handler /* TRAP #4 */
+vector25: .long _asm_exception_handler /* TRAP #5 */
+vector26: .long _asm_exception_handler /* TRAP #6 */
+vector27: .long _asm_exception_handler /* TRAP #7 */
+vector28: .long _asm_exception_handler /* TRAP #8 */
+vector29: .long _asm_exception_handler /* TRAP #9 */
+vector2A: .long _asm_exception_handler /* TRAP #10 */
+vector2B: .long _asm_exception_handler /* TRAP #11 */
+vector2C: .long _asm_exception_handler /* TRAP #12 */
+vector2D: .long _asm_exception_handler /* TRAP #13 */
+vector2E: .long _asm_exception_handler /* TRAP #14 */
+vector2F: .long _dbug_sc_handler /* TRAP #15 - System Call */
+vector30: .long _asm_exception_handler /* Reserved */
+vector31: .long _asm_exception_handler /* Reserved */
+vector32: .long _asm_exception_handler /* Reserved */
+vector33: .long _asm_exception_handler /* Reserved */
+vector34: .long _asm_exception_handler /* Reserved */
+vector35: .long _asm_exception_handler /* Reserved */
+vector36: .long _asm_exception_handler /* Reserved */
+vector37: .long _asm_exception_handler /* Reserved */
+vector38: .long _asm_exception_handler /* Reserved */
+vector39: .long _asm_exception_handler /* Reserved */
+vector3A: .long _asm_exception_handler /* Reserved */
+vector3B: .long _asm_exception_handler /* Reserved */
+vector3C: .long _asm_exception_handler /* Reserved */
+vector3D: .long _asm_exception_handler /* Unsupported Instruction */
+vector3E: .long _asm_exception_handler /* Reserved */
+vector3F: .long _asm_exception_handler /* Reserved */
+vector40: .long _asm_isr_handler /* User Defined Interrupts */
+vector41: .long _asm_isr_handler
+vector42: .long _asm_isr_handler
+vector43: .long _asm_isr_handler
+vector44: .long _asm_isr_handler
+vector45: .long _asm_isr_handler
+vector46: .long _asm_isr_handler
+vector47: .long _asm_isr_handler
+vector48: .long _asm_isr_handler
+vector49: .long _asm_isr_handler
+vector4A: .long _asm_isr_handler
+vector4B: .long _asm_isr_handler
+vector4C: .long _asm_isr_handler
+vector4D: .long _asm_isr_handler
+vector4E: .long _asm_isr_handler
+vector4F: .long _asm_isr_handler
+vector50: .long _asm_isr_handler
+vector51: .long _asm_isr_handler
+vector52: .long _asm_isr_handler
+vector53: .long _asm_isr_handler
+vector54: .long _asm_isr_handler
+vector55: .long _asm_isr_handler
+vector56: .long _asm_isr_handler
+vector57: .long _asm_isr_handler
+vector58: .long _asm_isr_handler
+vector59: .long _asm_isr_handler
+vector5A: .long _asm_isr_handler
+vector5B: .long _asm_isr_handler
+vector5C: .long _asm_isr_handler
+vector5D: .long _asm_isr_handler
+vector5E: .long _asm_isr_handler
+vector5F: .long _asm_isr_handler
+vector60: .long _asm_isr_handler
+vector61: .long _asm_isr_handler
+vector62: .long _asm_isr_handler
+vector63: .long _asm_isr_handler
+vector64: .long _asm_isr_handler
+vector65: .long _asm_isr_handler
+vector66: .long _asm_isr_handler
+vector67: .long _asm_isr_handler
+vector68: .long _asm_isr_handler
+vector69: .long _asm_isr_handler
+vector6A: .long _asm_isr_handler
+vector6B: .long _asm_isr_handler
+vector6C: .long _asm_isr_handler
+vector6D: .long _asm_isr_handler
+vector6E: .long _asm_isr_handler
+vector6F: .long _asm_isr_handler
+vector70: .long _asm_isr_handler
+vector71: .long _asm_isr_handler
+vector72: .long _asm_isr_handler
+vector73: .long _asm_isr_handler
+vector74: .long _asm_isr_handler
+vector75: .long _asm_isr_handler
+vector76: .long _asm_isr_handler
+vector77: .long _asm_isr_handler
+vector78: .long _asm_isr_handler
+vector79: .long _asm_isr_handler
+vector7A: .long _asm_isr_handler
+vector7B: .long _asm_isr_handler
+vector7C: .long _asm_isr_handler
+vector7D: .long _asm_isr_handler
+vector7E: .long _asm_isr_handler
+vector7F: .long _asm_isr_handler
+vector80: .long _asm_isr_handler
+vector81: .long _asm_isr_handler
+vector82: .long _asm_isr_handler
+vector83: .long _asm_isr_handler
+vector84: .long _asm_isr_handler
+vector85: .long _asm_isr_handler
+vector86: .long _asm_isr_handler
+vector87: .long _asm_isr_handler
+vector88: .long _asm_isr_handler
+vector89: .long _asm_isr_handler
+vector8A: .long _asm_isr_handler
+vector8B: .long _asm_isr_handler
+vector8C: .long _asm_isr_handler
+vector8D: .long _asm_isr_handler
+vector8E: .long _asm_isr_handler
+vector8F: .long _asm_isr_handler
+vector90: .long _asm_isr_handler
+vector91: .long _asm_isr_handler
+vector92: .long _asm_isr_handler
+vector93: .long _asm_isr_handler
+vector94: .long _asm_isr_handler
+vector95: .long _asm_isr_handler
+vector96: .long _asm_isr_handler
+vector97: .long _asm_isr_handler
+vector98: .long _asm_isr_handler
+vector99: .long _asm_isr_handler
+vector9A: .long _asm_isr_handler
+vector9B: .long _asm_isr_handler
+vector9C: .long _asm_isr_handler
+vector9D: .long _asm_isr_handler
+vector9E: .long _asm_isr_handler
+vector9F: .long _asm_isr_handler
+vectorA0: .long _asm_isr_handler
+vectorA1: .long _asm_isr_handler
+vectorA2: .long _asm_isr_handler
+vectorA3: .long _asm_isr_handler
+vectorA4: .long _asm_isr_handler
+vectorA5: .long _asm_isr_handler
+vectorA6: .long _asm_isr_handler
+vectorA7: .long _asm_isr_handler
+vectorA8: .long _asm_isr_handler
+vectorA9: .long _asm_isr_handler
+vectorAA: .long _asm_isr_handler
+vectorAB: .long _asm_isr_handler
+vectorAC: .long _asm_isr_handler
+vectorAD: .long _asm_isr_handler
+vectorAE: .long _asm_isr_handler
+vectorAF: .long _asm_isr_handler
+vectorB0: .long _asm_isr_handler
+vectorB1: .long _asm_isr_handler
+vectorB2: .long _asm_isr_handler
+vectorB3: .long _asm_isr_handler
+vectorB4: .long _asm_isr_handler
+vectorB5: .long _asm_isr_handler
+vectorB6: .long _asm_isr_handler
+vectorB7: .long _asm_isr_handler
+vectorB8: .long _asm_isr_handler
+vectorB9: .long _asm_isr_handler
+vectorBA: .long _asm_isr_handler
+vectorBB: .long _asm_isr_handler
+vectorBC: .long _asm_isr_handler
+vectorBD: .long _asm_isr_handler
+vectorBE: .long _asm_isr_handler
+vectorBF: .long _asm_isr_handler
+vectorC0: .long _asm_isr_handler
+vectorC1: .long _asm_isr_handler
+vectorC2: .long _asm_isr_handler
+vectorC3: .long _asm_isr_handler
+vectorC4: .long _asm_isr_handler
+vectorC5: .long _asm_isr_handler
+vectorC6: .long _asm_isr_handler
+vectorC7: .long _asm_isr_handler
+vectorC8: .long _asm_isr_handler
+vectorC9: .long _asm_isr_handler
+vectorCA: .long _asm_isr_handler
+vectorCB: .long _asm_isr_handler
+vectorCC: .long _asm_isr_handler
+vectorCD: .long _asm_isr_handler
+vectorCE: .long _asm_isr_handler
+vectorCF: .long _asm_isr_handler
+vectorD0: .long _asm_isr_handler
+vectorD1: .long _asm_isr_handler
+vectorD2: .long _asm_isr_handler
+vectorD3: .long _asm_isr_handler
+vectorD4: .long _asm_isr_handler
+vectorD5: .long _asm_isr_handler
+vectorD6: .long _asm_isr_handler
+vectorD7: .long _asm_isr_handler
+vectorD8: .long _asm_isr_handler
+vectorD9: .long _asm_isr_handler
+vectorDA: .long _asm_isr_handler
+vectorDB: .long _asm_isr_handler
+vectorDC: .long _asm_isr_handler
+vectorDD: .long _asm_isr_handler
+vectorDE: .long _asm_isr_handler
+vectorDF: .long _asm_isr_handler
+vectorE0: .long _asm_isr_handler
+vectorE1: .long _asm_isr_handler
+vectorE2: .long _asm_isr_handler
+vectorE3: .long _asm_isr_handler
+vectorE4: .long _asm_isr_handler
+vectorE5: .long _asm_isr_handler
+vectorE6: .long _asm_isr_handler
+vectorE7: .long _asm_isr_handler
+vectorE8: .long _asm_isr_handler
+vectorE9: .long _asm_isr_handler
+vectorEA: .long _asm_isr_handler
+vectorEB: .long _asm_isr_handler
+vectorEC: .long _asm_isr_handler
+vectorED: .long _asm_isr_handler
+vectorEE: .long _asm_isr_handler
+vectorEF: .long _asm_isr_handler
+vectorF0: .long _asm_isr_handler
+vectorF1: .long _asm_isr_handler
+vectorF2: .long _asm_isr_handler
+vectorF3: .long _asm_isr_handler
+vectorF4: .long _asm_isr_handler
+vectorF5: .long _asm_isr_handler
+vectorF6: .long _asm_isr_handler
+vectorF7: .long _asm_isr_handler
+vectorF8: .long _asm_isr_handler
+vectorF9: .long _asm_isr_handler
+vectorFA: .long _asm_isr_handler
+vectorFB: .long _asm_isr_handler
+vectorFC: .long _asm_isr_handler
+vectorFD: .long _asm_isr_handler
+vectorFE: .long _asm_isr_handler
+vectorFF: .long _asm_isr_handler
+
+/*
+ * Leave some bytes spare here for CW debugger (console IO stuff)
+ */
+ .rept 4
+ .long 0xdeadbeef
+ .endr
+
+/** @func reset Startup Code (reset vector)
+ *
+ * The vector array is mapped to address 0 at reset and SP and PC are
+ * fetched from adress 0 and 4.
+ *
+ * For debugger uploads this image will reside in the middle of RAM, leaving
+ * as much memory for other stuff in low memory available, e.g. Linux and
+ * an init ramdisk.
+ *
+ * For real system resets, the boot rom is mapped to all addresses in
+ * system, as long as somebody sets up the CS. Now the trick part until
+ * relocation to RAM is that we must code at the start of your bootrom
+ * - all link addresses are wrong, so we need the reloc.h stuff to find the
+ * right address.
+ *
+ * The following things happen here:
+ * * do important init, like SDRAM, only if we don't start from memory!
+ * * setup Memory and board specific bits prior to relocation.
+ * * Setup stack
+ * * relocate U-Boot to ram
+ *
+ */
+ .globl _start
+_start:
+ .global reset
+reset:
+ /* Mask all IRQs */
+ move.w #0x2700,%sr
+
+ /* Initialize MBAR - keep D0/D1 registers */
+ move.l #__MBAR,%d2
+ movec %d2,%MBAR
+ nop
+
+ /* Initialize RAMBAR0 - locate it on the data bus */
+ move.l #__CORE_SRAM0,%d2
+ add.l #0x21,%d2
+ movec %d2,%RAMBAR0
+ nop
+
+ /* Initialize RAMBAR1 - locate it on the data bus */
+ move.l #__CORE_SRAM1,%d2
+ add.l #0x21,%d2
+ movec %d2,%RAMBAR1
+ nop
+
+ /* Point Stack Pointer into Core SRAM temporarily */
+ move.l #___SP_INIT,%d2
+ move.l %d2,%sp
+ nop
+
+ /* Invalidate the data, instruction, and branch caches */
+ /* Turn on the branch cache */
+ move.l #0x010C0100,%d2
+ movec %d2,%cacr
+ nop
+
+ /* Prepare stack top */
+ clr.l %sp@(0)
+ move.l %d0,%sp@(4)
+ move.l %d1,%sp@(8)
+ clr.l %sp@(12)
+
+ /*
+ * This call is intended to give all developers a chance to use a
+ * standard reset vector file, but also do some special things
+ * required only on their specific CPU.
+ */
+#ifdef ARCH_HAS_INIT_LOWLEVEL
+ bsr.l arch_init_lowlevel
+ nop
+#endif
+ /*
+ * If the code vector table is not at TEXT_BASE and so this code
+ * as well, jump to the address mirror at FLASH ROM start address
+ *
+ * So load your image to TEXT_BASE for debugging or flash a binary
+ * image to your bootflash - code below will take proper action.
+ */
+ lea.l %pc@(VECTOR_TABLE),%a0
+ move.l #TEXT_BASE,%a1
+ cmp.l %a0,%a1
+ beq.s saveland
+
+ /*
+ * Execution is not at TEXT_BASE. We assume entry to this code by
+ * a hardware reset and change execution to address of _FLASH_ rom.
+ */
+ lea.l %pc@(saveland),%a0 // Effective ! Address of label below
+ move.l %a0,%d0
+ and.l #0x00ffffff,%d0 // Cut away address high byte
+ move.l #CFG_FLASH_ADDRESS,%d1 // Get flash address
+ and.l #0xff000000,%d1 // and just take base for CS0
+ or.l %d1,%d0 // Compose new address
+ move.l %d0,%a0
+ jmp %a0@ // Jump to flash rom address!
+ nop
+
+ /* We now either in SDRAM or FLASH START addresses, save to
+ change chip selects */
+saveland:
+ nop
+
+ /*
+ * Before relocating, we have to setup RAM timing
+ * because memory timing is board-dependend, you will
+ * find a lowlevel_init.[c|S] in your board directory.
+ *
+ * Do not jump/call other u-boot code here!
+ */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+ bsr.l board_init_lowlevel
+ nop
+#endif
+
+ /*
+ * relocate U-Boot Code to RAM (including copy of vectors)
+ */
+relocate:
+ lea.l %pc@(VECTOR_TABLE),%a0
+ move.l #TEXT_BASE,%a1
+ move.l #__bss_start,%a3
+ cmp.l %a0,%a1
+ beq.s skip_relocate
+
+ /*
+ * Calculate number of long words, and copy them to RAM
+ */
+ move.l %a3,%d2
+ sub.l %a1,%d2
+ asr.l #2,%d2
+copy_loop:
+ move.l %a0@+,%a1@+
+ subq.l #1,%d2
+ bne.s copy_loop
+
+skip_relocate:
+
+ /* Clear BSS segment in RAM */
+clear_bss:
+ move.l #__bss_end,%a4
+ moveq.l #0,%d2
+clear_loop:
+ move.l %d2,%a3@+
+ cmp.l %a4,%a3
+ ble.s clear_loop
+
+ /*
+ * Relocate Vectors to memory start (address 0)
+ *
+ * NOTE: It could be at other places, but debuggers expect
+ * this table to be at address 0.
+ */
+#ifdef CONFIG_COPY_LOWMEM_VECTORS
+reloc_vectors:
+ lea.l %pc@(VECTOR_TABLE),%a0
+ move.l #0,%a1
+ cmp.l %a0,%a1
+ beq.s skip_copy_vectors
+
+ move.l #0x100,%d2
+copy_loop_vectors:
+ move.l %a0@+,%a1@+
+ subq.l #1,%d2
+ bne.s copy_loop_vectors
+skip_copy_vectors:
+#endif
+
+#ifndef CONFIG_USE_LOWMEM_VECTORS
+ move.l #TEXT_BASE,%d0
+ movec %d0,%vbr
+ nop
+#endif
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+ /*
+ * Call other half of initcode in relocated code
+ *
+ * You allowed to call other U-Boot code from here
+ */
+ jsr.l board_init_highlevel
+ nop
+#endif
+ /*
+ * Now jump to real link address and U-Boot entry point
+ */
+ nop
+ jmp.l start_uboot
+ nop
+ nop
+
+/*
+ * Interrupt handling
+ */
+
+/*
+ * IRQ stack frame.
+ */
+#define S_FRAME_SIZE 148
+
+#define S_SP S_A7
+#define S_SR 144
+#define S_PC 140
+
+#define S_FPIAR 136
+#define S_FPSR 132
+#define S_FPCR 128
+
+#define S_FP7 120
+#define S_FP6 112
+#define S_FP5 104
+#define S_FP4 96
+#define S_FP3 88
+#define S_FP2 80
+#define S_FP1 72
+#define S_FP0 64
+
+#define S_A7 60
+#define S_A6 56
+#define S_A5 52
+#define S_A4 48
+#define S_A3 44
+#define S_A2 40
+#define S_A1 36
+#define S_A0 32
+
+#define S_D7 28
+#define S_D6 24
+#define S_D5 20
+#define S_D4 16
+#define S_D3 12
+#define S_D2 8
+#define S_D1 4
+#define S_D0 0
+
+
+/*
+ * exception handlers
+ */
+#ifdef CONFIG_USE_IRQ
+ .global _dbug_sc_handler
+_dbug_sc_handler:
+ .global _asm_exception_handler
+_asm_exception_handler:
+ move.w #0x2700,%sr /* Disable IRQs */
+
+ move.l %sp,___SP_INIT /* Remember on top of stack */
+ move.l #___SP_INIT,%sp /* Set stack to known area */
+
+ move.l %a0,%sp@-
+ lea _asm_context,%a0
+
+ movem.l %d0-%d7/%a0-%a7,%a0@
+
+ fmovem %fp0-%fp7,%a0@(S_FP0)
+ fmove.l %fpcr,%a0@(S_FPCR)
+ fmove.l %fpsr,%a0@(S_FPSR)
+ fmove.l %fpiar,%a0@(S_FPIAR)
+
+ move.l %sp@+,%a0@(S_A0)
+ move.l %sp@,%a1
+ move.l %a1,%a0@(S_SP)
+ move.l %a1@(4),%a0@(S_PC)
+ move.w %a1@(2),%a0@(S_SR)
+
+ jsr cpu_cache_flush
+ nop
+
+ move.l %a1,%sp@-
+ jsr mcf_execute_exception_handler
+
+
+ lea _asm_context,%a0
+ move.l %a0@(S_SP),%sp
+
+ move.l %a0@(S_D1),%d1
+ move.l %a0@(S_D0),%d0
+ move.l %a0@(S_A1),%a1
+ move.l %a0@(S_A0),%a0
+
+ rte
+ nop
+ nop
+
+ .global _asm_isr_handler
+_asm_isr_handler:
+ link %a6,#-16
+ movem.l %d0-%d1/%a0-%a1,%sp@
+
+ move.w %a6@(4),%d0
+ lsr.l #2,%d0
+ andi.l #0x0000FF,%d0
+ move.l %d0,%sp@-
+ move.l #0,%a0
+ move.l %a0,%sp@-
+ jsr mcf_execute_irq_handler
+ lea %sp@(8),%sp
+ cmpi.l #1,%d0
+ beq handled
+
+nothandled:
+ movem.l %sp@,%d0-%d1/%a0-%a1
+ unlk %a6
+ jmp _asm_exception_handler
+ nop
+
+handled:
+ movem.l %sp@,%d0-%d1/%a0-%a1
+ unlk %a6
+ rte
+ nop
+ nop
+
+#else
+
+ .global _dbug_sc_handler
+_dbug_sc_handler:
+ .global _asm_exception_handler
+_asm_exception_handler:
+ nop
+ // FIXME - do something useful here
+ rte
+
+ .global _asm_isr_handler
+_asm_isr_handler:
+ nop
+ // FIXME - do something useful here
+ rte
+
+#endif
+
+ .data
+_asm_context:
+ .space S_FRAME_SIZE,0x55
+
+
+ .end