File-copy from v4.4.100

This is the result of 'cp' from a linux-stable tree with the 'v4.4.100'
tag checked out (commit 26d6298789e695c9f627ce49a7bbd2286405798a) on
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

Please refer to that tree for all history prior to this point.

Change-Id: I8a9ee2aea93cd29c52c847d0ce33091a73ae6afe
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
new file mode 100644
index 0000000..78ae555
--- /dev/null
+++ b/arch/mn10300/Kconfig
@@ -0,0 +1,493 @@
+config MN10300
+	def_bool y
+	select HAVE_OPROFILE
+	select HAVE_UID16
+	select GENERIC_IRQ_SHOW
+	select ARCH_WANT_IPC_PARSE_VERSION
+	select HAVE_ARCH_TRACEHOOK
+	select HAVE_ARCH_KGDB
+	select GENERIC_ATOMIC64
+	select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER
+	select VIRT_TO_BUS
+	select GENERIC_CLOCKEVENTS
+	select MODULES_USE_ELF_RELA
+	select OLD_SIGSUSPEND3
+	select OLD_SIGACTION
+	select HAVE_DEBUG_STACKOVERFLOW
+
+config AM33_2
+	def_bool n
+
+config AM33_3
+	def_bool n
+
+config AM34_2
+	def_bool n
+	select MN10300_HAS_ATOMIC_OPS_UNIT
+	select MN10300_HAS_CACHE_SNOOP
+
+config ERRATUM_NEED_TO_RELOAD_MMUCTR
+	def_bool y if AM33_3 || AM34_2
+
+config MMU
+	def_bool y
+
+config HIGHMEM
+	def_bool n
+
+config NUMA
+	def_bool n
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool y
+
+config RWSEM_XCHGADD_ALGORITHM
+	bool
+
+config GENERIC_CALIBRATE_DELAY
+	def_bool y
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+config GENERIC_BUG
+	def_bool y
+
+config QUICKLIST
+	def_bool y
+
+config ARCH_HAS_ILOG2_U32
+	def_bool y
+
+config HOTPLUG_CPU
+	def_bool n
+
+source "init/Kconfig"
+
+source "kernel/Kconfig.freezer"
+
+
+menu "Panasonic MN10300 system setup"
+
+choice
+	prompt "Unit type"
+	default MN10300_UNIT_ASB2303
+	help
+	  This option specifies board for which the kernel will be
+	  compiled. It affects the external peripherals catered for.
+
+config MN10300_UNIT_ASB2303
+	bool "ASB2303"
+
+config MN10300_UNIT_ASB2305
+	bool "ASB2305"
+
+config MN10300_UNIT_ASB2364
+	bool "ASB2364"
+	select SMSC911X_ARCH_HOOKS if SMSC911X
+
+endchoice
+
+choice
+	prompt "Processor support"
+	default MN10300_PROC_MN103E010
+	help
+	  This option specifies the processor for which the kernel will be
+	  compiled. It affects the on-chip peripherals catered for.
+
+config MN10300_PROC_MN103E010
+	bool "MN103E010"
+	depends on MN10300_UNIT_ASB2303 || MN10300_UNIT_ASB2305
+	select AM33_2
+	select MN10300_PROC_HAS_TTYSM0
+	select MN10300_PROC_HAS_TTYSM1
+	select MN10300_PROC_HAS_TTYSM2
+
+config MN10300_PROC_MN2WS0050
+	bool "MN2WS0050"
+	depends on MN10300_UNIT_ASB2364
+	select AM34_2
+	select MN10300_PROC_HAS_TTYSM0
+	select MN10300_PROC_HAS_TTYSM1
+	select MN10300_PROC_HAS_TTYSM2
+
+endchoice
+
+config MN10300_HAS_ATOMIC_OPS_UNIT
+	def_bool n
+	help
+	  This should be enabled if the processor has an atomic ops unit
+	  capable of doing LL/SC equivalent operations.
+
+config FPU
+	bool "FPU present"
+	default y
+	depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050
+
+config LAZY_SAVE_FPU
+	bool "Save FPU state lazily"
+	default y
+	depends on FPU && !SMP
+	help
+	  Enable this to be lazy in the saving of the FPU state to the owning
+	  task's thread struct.  This is useful if most tasks on the system
+	  don't use the FPU as only those tasks that use it will pass it
+	  between them, and the state needn't be saved for a task that isn't
+	  using it.
+
+	  This can't be so easily used on SMP as the process that owns the FPU
+	  state on a CPU may be currently running on another CPU, so for the
+	  moment, it is disabled.
+
+source "arch/mn10300/mm/Kconfig.cache"
+
+config MN10300_TLB_USE_PIDR
+	def_bool y
+
+menu "Memory layout options"
+
+config KERNEL_RAM_BASE_ADDRESS
+	hex "Base address of kernel RAM"
+	default "0x90000000"
+
+config INTERRUPT_VECTOR_BASE
+	hex "Base address of vector table"
+	default "0x90000000"
+	help
+	  The base address of the vector table will be programmed into
+          the TBR register. It must be on 16MiB address boundary.
+
+config KERNEL_TEXT_ADDRESS
+	hex "Base address of kernel"
+	default "0x90001000"
+
+config KERNEL_ZIMAGE_BASE_ADDRESS
+	hex "Base address of compressed vmlinux image"
+	default "0x50700000"
+
+config BOOT_STACK_OFFSET
+	hex
+	default	"0xF00"	if SMP
+	default	"0xFF0" if !SMP
+
+config BOOT_STACK_SIZE
+	hex
+	depends on SMP
+	default	"0x100"
+endmenu
+
+config SMP
+	bool "Symmetric multi-processing support"
+	default y
+	depends on MN10300_PROC_MN2WS0050
+	---help---
+	  This enables support for systems with more than one CPU. If you have
+	  a system with only one CPU, say N. If you have a system with more
+	  than one CPU, say Y.
+
+	  If you say N here, the kernel will run on uni- and multiprocessor
+	  machines, but will use only one CPU of a multiprocessor machine. If
+	  you say Y here, the kernel will run on many, but not all,
+	  uniprocessor machines. On a uniprocessor machine, the kernel
+	  will run faster if you say N here.
+
+	  See also <file:Documentation/x86/i386/IO-APIC.txt>,
+	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  If you don't know what to do here, say N.
+
+config NR_CPUS
+	int
+	depends on SMP
+	default "2"
+
+source "kernel/Kconfig.preempt"
+
+config MN10300_CURRENT_IN_E2
+	bool "Hold current task address in E2 register"
+	depends on !SMP
+	default y
+	help
+	  This option removes the E2/R2 register from the set available to gcc
+	  for normal use and instead uses it to store the address of the
+	  current process's task_struct whilst in the kernel.
+
+	  This means the kernel doesn't need to calculate the address each time
+	  "current" is used (take SP, AND with mask and dereference pointer
+	  just to get the address), and instead can just use E2+offset
+	  addressing each time.
+
+	  This has no effect on userspace.
+
+config MN10300_USING_JTAG
+	bool "Using JTAG to debug kernel"
+	default y
+	help
+	  This options indicates that JTAG will be used to debug the kernel. It
+	  suppresses the use of certain hardware debugging features, such as
+	  single-stepping, which are taken over completely by the JTAG unit.
+
+source "kernel/Kconfig.hz"
+
+config MN10300_RTC
+	bool "Using MN10300 RTC"
+	depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050
+	select GENERIC_CMOS_UPDATE
+	default n
+	help
+	  This option enables support for the RTC, thus enabling time to be
+	  tracked, even when system is powered down. This is available on-chip
+	  on the MN103E010.
+
+config MN10300_WD_TIMER
+	bool "Using MN10300 watchdog timer"
+	default y
+	help
+	  This options indicates that the watchdog timer will be used.
+
+config PCI
+	bool "Use PCI"
+	depends on MN10300_UNIT_ASB2305
+	default y
+	select GENERIC_PCI_IOMAP
+	help
+	  Some systems (such as the ASB2305) have PCI onboard. If you have one
+	  of these boards and you wish to use the PCI facilities, say Y here.
+
+	  The PCI-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>, contains valuable
+	  information about which PCI hardware does work under Linux and which
+	  doesn't.
+
+source "drivers/pci/Kconfig"
+
+source "drivers/pcmcia/Kconfig"
+
+menu "MN10300 internal serial options"
+
+config MN10300_PROC_HAS_TTYSM0
+	bool
+	default n
+
+config MN10300_PROC_HAS_TTYSM1
+	bool
+	default n
+
+config MN10300_PROC_HAS_TTYSM2
+	bool
+	default n
+
+config MN10300_TTYSM
+	bool "Support for ttySM serial ports"
+	depends on MN10300
+	default y
+	select SERIAL_CORE
+	help
+	  This option enables support for the on-chip serial ports that the
+	  MN10300 has available.
+
+config MN10300_TTYSM_CONSOLE
+	bool "Support for console on ttySM serial ports"
+	depends on MN10300_TTYSM
+	select SERIAL_CORE_CONSOLE
+	help
+	  This option enables support for a console on the on-chip serial ports
+	  that the MN10300 has available.
+
+#
+# /dev/ttySM0
+#
+config MN10300_TTYSM0
+	bool "Enable SIF0 (/dev/ttySM0)"
+	depends on MN10300_TTYSM && MN10300_PROC_HAS_TTYSM0
+	help
+	  Enable access to SIF0 through /dev/ttySM0 or gdb-stub
+
+choice
+	prompt "Select the timer to supply the clock for SIF0"
+	default MN10300_TTYSM0_TIMER8
+	depends on MN10300_TTYSM0
+
+config MN10300_TTYSM0_TIMER8
+	bool "Use timer 8 (16-bit)"
+
+config MN10300_TTYSM0_TIMER2
+	bool "Use timer 2 (8-bit)"
+
+endchoice
+
+#
+# /dev/ttySM1
+#
+config MN10300_TTYSM1
+	bool "Enable SIF1 (/dev/ttySM1)"
+	depends on MN10300_TTYSM && MN10300_PROC_HAS_TTYSM1
+	help
+	  Enable access to SIF1 through /dev/ttySM1 or gdb-stub
+
+choice
+	prompt "Select the timer to supply the clock for SIF1"
+	default MN10300_TTYSM1_TIMER12 \
+		if !(AM33_2 || AM33_3)
+	default MN10300_TTYSM1_TIMER9 \
+		if AM33_2 || AM33_3
+	depends on MN10300_TTYSM1
+
+config MN10300_TTYSM1_TIMER12
+	bool "Use timer 12 (16-bit)"
+	depends on !(AM33_2 || AM33_3)
+
+config MN10300_TTYSM1_TIMER9
+	bool "Use timer 9 (16-bit)"
+	depends on AM33_2 || AM33_3
+
+config MN10300_TTYSM1_TIMER3
+	bool "Use timer 3 (8-bit)"
+	depends on AM33_2 || AM33_3
+
+endchoice
+
+#
+# /dev/ttySM2
+#
+config MN10300_TTYSM2
+	bool "Enable SIF2 (/dev/ttySM2)"
+	depends on MN10300_TTYSM && MN10300_PROC_HAS_TTYSM2
+	help
+	  Enable access to SIF2 through /dev/ttySM2 or gdb-stub
+
+choice
+	prompt "Select the timer to supply the clock for SIF2"
+	default MN10300_TTYSM2_TIMER3 \
+		if !(AM33_2 || AM33_3)
+	default MN10300_TTYSM2_TIMER10 \
+		if AM33_2 || AM33_3
+	depends on MN10300_TTYSM2
+
+config MN10300_TTYSM2_TIMER9
+	bool "Use timer 9 (16-bit)"
+	depends on !(AM33_2 || AM33_3)
+
+config MN10300_TTYSM2_TIMER1
+	bool "Use timer 1 (8-bit)"
+	depends on !(AM33_2 || AM33_3)
+
+config MN10300_TTYSM2_TIMER3
+	bool "Use timer 3 (8-bit)"
+	depends on !(AM33_2 || AM33_3)
+
+config MN10300_TTYSM2_TIMER10
+	bool "Use timer 10 (16-bit)"
+	depends on AM33_2 || AM33_3
+
+endchoice
+
+config MN10300_TTYSM2_CTS
+	bool "Enable the use of the CTS line /dev/ttySM2"
+	depends on MN10300_TTYSM2 && AM33_2
+
+endmenu
+
+menu "Interrupt request priority options"
+
+comment "[!] NOTE: A lower number/level indicates a higher priority (0 is highest, 6 is lowest)"
+
+comment "____Non-maskable interrupt levels____"
+comment "The following must be set to a higher priority than local_irq_disable() and on-chip serial"
+
+config DEBUGGER_IRQ_LEVEL
+	int "DEBUGGER interrupt priority"
+	depends on KERNEL_DEBUGGER
+	range 0 1 if LINUX_CLI_LEVEL = 2
+	range 0 2 if LINUX_CLI_LEVEL = 3
+	range 0 3 if LINUX_CLI_LEVEL = 4
+	range 0 4 if LINUX_CLI_LEVEL = 5
+	range 0 5 if LINUX_CLI_LEVEL = 6
+	default 0
+
+comment "The following must be set to a higher priority than local_irq_disable()"
+
+config MN10300_SERIAL_IRQ_LEVEL
+	int "MN10300 on-chip serial interrupt priority"
+	depends on MN10300_TTYSM
+	range 1 1 if LINUX_CLI_LEVEL = 2
+	range 1 2 if LINUX_CLI_LEVEL = 3
+	range 1 3 if LINUX_CLI_LEVEL = 4
+	range 1 4 if LINUX_CLI_LEVEL = 5
+	range 1 5 if LINUX_CLI_LEVEL = 6
+	default 1
+
+comment "-"
+comment "____Maskable interrupt levels____"
+
+config LINUX_CLI_LEVEL
+	int "The highest interrupt priority excluded by local_irq_disable() (2-6)"
+	range 2 6
+	default 2
+	help
+	  local_irq_disable() doesn't actually disable maskable interrupts -
+	  what it does is restrict the levels of interrupt which are permitted
+	  (a lower level indicates a higher priority) by lowering the value in
+	  EPSW.IM from 7.  Any interrupt is permitted for which the level is
+	  lower than EPSW.IM.
+
+	  Certain interrupts, such as DEBUGGER and virtual MN10300 on-chip
+	  serial DMA interrupts are allowed to interrupt normal disabled
+	  sections.
+
+comment "The following must be set to a equal to or lower priority than LINUX_CLI_LEVEL"
+
+config TIMER_IRQ_LEVEL
+	int "Kernel timer interrupt priority"
+	range LINUX_CLI_LEVEL 6
+	default 4
+
+config PCI_IRQ_LEVEL
+	int "PCI interrupt priority"
+	depends on PCI
+	range LINUX_CLI_LEVEL 6
+	default 5
+
+config ETHERNET_IRQ_LEVEL
+	int "Ethernet interrupt priority"
+	depends on SMC91X || SMC911X || SMSC911X
+	range LINUX_CLI_LEVEL 6
+	default 6
+
+config EXT_SERIAL_IRQ_LEVEL
+	int "External serial port interrupt priority"
+	depends on SERIAL_8250
+	range LINUX_CLI_LEVEL 6
+	default 6
+
+endmenu
+
+source "mm/Kconfig"
+
+menu "Power management options"
+source kernel/power/Kconfig
+endmenu
+
+endmenu
+
+
+menu "Executable formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/mn10300/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug
new file mode 100644
index 0000000..94efb3e
--- /dev/null
+++ b/arch/mn10300/Kconfig.debug
@@ -0,0 +1,155 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_DECOMPRESS_KERNEL
+	bool "Using serial port during decompressing kernel"
+	depends on DEBUG_KERNEL
+	default n
+	help
+	  If you say Y here you will confirm the start and the end of
+	  decompressing Linux seeing "Uncompressing Linux... " and
+	  "Ok, booting the kernel.\n" on console.
+
+config TEST_MISALIGNMENT_HANDLER
+	bool "Run tests on the misalignment handler"
+	depends on DEBUG_KERNEL
+	default n
+	help
+	  If you say Y here the kernel will execute a list of misaligned memory
+	  accesses to make sure the misalignment handler deals them with
+	  correctly.  If it does not, the kernel will throw a BUG.
+
+config KPROBES
+	bool "Kprobes"
+	depends on DEBUG_KERNEL
+	help
+	  Kprobes allows you to trap at almost any kernel address and
+	  execute a callback function.  register_kprobe() establishes
+	  a probepoint and specifies the callback.  Kprobes is useful
+	  for kernel debugging, non-intrusive instrumentation and testing.
+	  If in doubt, say "N".
+
+config GDBSTUB
+	bool "Remote GDB kernel debugging"
+	depends on DEBUG_KERNEL && DEPRECATED
+	select DEBUG_INFO
+	select FRAME_POINTER
+	help
+	  If you say Y here, it will be possible to remotely debug the kernel
+	  using gdb. This enlarges your kernel ELF image disk size by several
+	  megabytes and requires a machine with more than 16 MB, better 32 MB
+	  RAM to avoid excessive linking time. This is only useful for kernel
+	  hackers. If unsure, say N.
+
+	  This is deprecated in favour of KGDB and will be removed in a later
+	  version.
+
+config GDBSTUB_IMMEDIATE
+	bool "Break into GDB stub immediately"
+	depends on GDBSTUB
+	help
+	  If you say Y here, GDB stub will break into the program as soon as
+	  possible, leaving the program counter at the beginning of
+	  start_kernel() in init/main.c.
+
+config GDBSTUB_ALLOW_SINGLE_STEP
+	bool "Allow software single-stepping in GDB stub"
+	depends on GDBSTUB && !SMP && !PREEMPT
+	help
+	  Allow GDB stub to perform software single-stepping through the
+	  kernel.  This doesn't work very well on SMP or preemptible kernels as
+	  it uses temporary breakpoints to emulate single-stepping.
+
+config GDB_CONSOLE
+	bool "Console output to GDB"
+	depends on GDBSTUB
+	help
+	  If you are using GDB for remote debugging over a serial port and
+	  would like kernel messages to be formatted into GDB $O packets so
+	  that GDB prints them as program output, say 'Y'.
+
+config GDBSTUB_DEBUGGING
+	bool "Debug GDB stub by messages to serial port"
+	depends on GDBSTUB
+	help
+	  This causes debugging messages to be displayed at various points
+	  during execution of the GDB stub routines. Such messages will be
+	  displayed on ttyS0 if that isn't the GDB stub's port, or ttySM0
+	  otherwise.
+
+config GDBSTUB_DEBUG_ENTRY
+	bool "Debug GDB stub entry"
+	depends on GDBSTUB_DEBUGGING
+	help
+	  This option causes information to be displayed about entry to or exit
+	  from the main GDB stub routine.
+
+config GDBSTUB_DEBUG_PROTOCOL
+	bool "Debug GDB stub protocol"
+	depends on GDBSTUB_DEBUGGING
+	help
+	  This option causes information to be displayed about the GDB remote
+	  protocol messages generated exchanged with GDB.
+
+config GDBSTUB_DEBUG_IO
+	bool "Debug GDB stub I/O"
+	depends on GDBSTUB_DEBUGGING
+	help
+	  This option causes information to be displayed about GDB stub's
+	  low-level I/O.
+
+config GDBSTUB_DEBUG_BREAKPOINT
+	bool "Debug GDB stub breakpoint management"
+	depends on GDBSTUB_DEBUGGING
+	help
+	  This option causes information to be displayed about GDB stub's
+	  breakpoint management.
+
+choice
+	prompt "GDB stub port"
+	default GDBSTUB_ON_TTYSM0
+	depends on GDBSTUB
+	help
+	  Select the serial port used for GDB-stub.
+
+config GDBSTUB_ON_TTYSM0
+	bool "/dev/ttySM0 [SIF0]"
+	depends on MN10300_TTYSM0
+	select GDBSTUB_ON_TTYSMx
+
+config GDBSTUB_ON_TTYSM1
+	bool "/dev/ttySM1 [SIF1]"
+	depends on MN10300_TTYSM1
+	select GDBSTUB_ON_TTYSMx
+
+config GDBSTUB_ON_TTYSM2
+	bool "/dev/ttySM2 [SIF2]"
+	depends on MN10300_TTYSM2
+	select GDBSTUB_ON_TTYSMx
+
+config GDBSTUB_ON_TTYS0
+	bool "/dev/ttyS0"
+	select GDBSTUB_ON_TTYSx
+
+config GDBSTUB_ON_TTYS1
+	bool "/dev/ttyS1"
+	select GDBSTUB_ON_TTYSx
+
+endchoice
+
+config GDBSTUB_ON_TTYSMx
+	bool
+	depends on GDBSTUB_ON_TTYSM0 || GDBSTUB_ON_TTYSM1 || GDBSTUB_ON_TTYSM2
+	default y
+
+config GDBSTUB_ON_TTYSx
+	bool
+	depends on GDBSTUB_ON_TTYS0 || GDBSTUB_ON_TTYS1
+	default y
+
+endmenu
+
+config KERNEL_DEBUGGER
+	def_bool y
+	depends on GDBSTUB || KGDB
diff --git a/arch/mn10300/Makefile b/arch/mn10300/Makefile
new file mode 100644
index 0000000..3f1ea5d
--- /dev/null
+++ b/arch/mn10300/Makefile
@@ -0,0 +1,99 @@
+###############################################################################
+#
+# MN10300 Kernel makefile system specifications
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Modified by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+
+KBUILD_DEFCONFIG := asb2303_defconfig
+
+CCSPECS	:= $(shell $(CC) -v 2>&1 | grep "^Reading specs from " | head -1 | cut -c20-)
+CCDIR	:= $(strip $(patsubst %/specs,%,$(CCSPECS)))
+KBUILD_CPPFLAGS += -nostdinc -I$(CCDIR)/include
+
+LDFLAGS		:=
+OBJCOPYFLAGS	:= -O binary -R .note -R .comment -R .GCC-command-line -R .note.gnu.build-id -S
+#LDFLAGS_vmlinux := -Map linkmap.txt
+CHECKFLAGS	+=
+
+PROCESSOR	:= unset
+UNIT		:= unset
+
+KBUILD_CFLAGS	+= -mam33 -DCPU=AM33 $(call cc-option,-mmem-funcs,)
+KBUILD_AFLAGS	+= -mam33 -DCPU=AM33
+
+ifeq ($(CONFIG_MN10300_CURRENT_IN_E2),y)
+KBUILD_CFLAGS	+= -ffixed-e2 -fcall-saved-e5
+endif
+
+ifeq ($(CONFIG_MN10300_PROC_MN103E010),y)
+PROCESSOR	:= mn103e010
+endif
+ifeq ($(CONFIG_MN10300_PROC_MN2WS0050),y)
+PROCESSOR	:= mn2ws0050
+endif
+
+ifeq ($(CONFIG_MN10300_UNIT_ASB2303),y)
+UNIT		:= asb2303
+endif
+ifeq ($(CONFIG_MN10300_UNIT_ASB2305),y)
+UNIT		:= asb2305
+endif
+ifeq ($(CONFIG_MN10300_UNIT_ASB2364),y)
+UNIT		:= asb2364
+endif
+
+
+head-y		:= arch/mn10300/kernel/head.o
+
+core-y		+= arch/mn10300/kernel/ arch/mn10300/mm/
+
+ifneq ($(PROCESSOR),unset)
+core-y		+= arch/mn10300/proc-$(PROCESSOR)/
+endif
+ifneq ($(UNIT),unset)
+core-y		+= arch/mn10300/unit-$(UNIT)/
+endif
+libs-y		+= arch/mn10300/lib/
+
+drivers-$(CONFIG_OPROFILE)	+= arch/mn10300/oprofile/
+
+boot := arch/mn10300/boot
+
+.PHONY: zImage
+
+KBUILD_IMAGE := $(boot)/zImage
+CLEAN_FILES += $(boot)/zImage
+CLEAN_FILES += $(boot)/compressed/vmlinux
+CLEAN_FILES += $(boot)/compressed/vmlinux.bin
+CLEAN_FILES += $(boot)/compressed/vmlinux.bin.gz
+
+zImage: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+all: zImage
+
+bootstrap:
+	$(Q)$(MAKEBOOT) bootstrap
+
+archclean:
+	$(Q)$(MAKE) $(clean)=arch/mn10300/proc-mn103e010
+	$(Q)$(MAKE) $(clean)=arch/mn10300/unit-asb2303
+	$(Q)$(MAKE) $(clean)=arch/mn10300/unit-asb2305
+
+define archhelp
+  echo  '* zImage        - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
+endef
+
+#
+# include the appropriate processor- and unit-specific headers
+#
+KBUILD_CPPFLAGS += -I$(srctree)/arch/mn10300/proc-$(PROCESSOR)/include
+KBUILD_CPPFLAGS += -I$(srctree)/arch/mn10300/unit-$(UNIT)/include
diff --git a/arch/mn10300/boot/.gitignore b/arch/mn10300/boot/.gitignore
new file mode 100644
index 0000000..b6718de
--- /dev/null
+++ b/arch/mn10300/boot/.gitignore
@@ -0,0 +1 @@
+zImage
diff --git a/arch/mn10300/boot/Makefile b/arch/mn10300/boot/Makefile
new file mode 100644
index 0000000..36c9caf
--- /dev/null
+++ b/arch/mn10300/boot/Makefile
@@ -0,0 +1,28 @@
+# MN10300 kernel compressor and wrapper
+#
+# Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+
+targets		:= vmlinux.bin zImage
+
+subdir- 	:= compressed
+
+# ---------------------------------------------------------------------------
+
+
+$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+	$(call if_changed,objcopy)
+	@echo 'Kernel: $@ is ready'
+
+$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
+	$(call if_changed,objcopy)
+
+$(obj)/compressed/vmlinux: FORCE
+	$(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
diff --git a/arch/mn10300/boot/compressed/Makefile b/arch/mn10300/boot/compressed/Makefile
new file mode 100644
index 0000000..08a95e1
--- /dev/null
+++ b/arch/mn10300/boot/compressed/Makefile
@@ -0,0 +1,22 @@
+#
+# Create a compressed vmlinux image from the original vmlinux
+#
+
+targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
+
+LDFLAGS_vmlinux := -Ttext $(CONFIG_KERNEL_ZIMAGE_BASE_ADDRESS) -e startup_32
+
+$(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
+	$(call if_changed,ld)
+	@:
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+	$(call if_changed,objcopy)
+
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,gzip)
+
+LDFLAGS_piggy.o := -r --format binary --oformat elf32-am33lin -T
+
+$(obj)/piggy.o: $(obj)/vmlinux.lds $(obj)/vmlinux.bin.gz FORCE
+	$(call if_changed,ld)
diff --git a/arch/mn10300/boot/compressed/head.S b/arch/mn10300/boot/compressed/head.S
new file mode 100644
index 0000000..7b50345
--- /dev/null
+++ b/arch/mn10300/boot/compressed/head.S
@@ -0,0 +1,151 @@
+/* Boot entry point for a compressed MN10300 kernel
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+	.section	.text
+
+#define DEBUG
+
+#include <linux/linkage.h>
+#include <asm/cpu-regs.h>
+#include <asm/cache.h>
+#ifdef CONFIG_SMP
+#include <proc/smp-regs.h>
+#endif
+
+	.globl startup_32
+startup_32:
+#ifdef CONFIG_SMP
+	#
+	# Secondary CPUs jump directly to the kernel entry point
+	#
+	# Must save primary CPU's D0-D2 registers as they hold boot parameters
+	#
+	mov	(CPUID), d3
+	and	CPUID_MASK,d3
+	beq	startup_primary
+	mov	CONFIG_KERNEL_TEXT_ADDRESS,a0
+	jmp	(a0)
+
+startup_primary:
+#endif /* CONFIG_SMP */
+
+	# first save parameters from bootloader
+	mov	param_save_area,a0
+	mov	d0,(a0)
+	mov	d1,(4,a0)
+	mov	d2,(8,a0)
+
+	mov	sp,a3
+	mov	decomp_stack+0x2000-4,a0
+	mov	a0,sp
+
+	# invalidate and enable both of the caches
+	mov	CHCTR,a0
+	clr	d0
+	movhu	d0,(a0)					# turn off first
+	mov	CHCTR_ICINV|CHCTR_DCINV,d0
+	movhu	d0,(a0)
+	setlb
+	mov	(a0),d0
+	btst	CHCTR_ICBUSY|CHCTR_DCBUSY,d0		# wait till not busy
+	lne
+
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+#ifdef CONFIG_MN10300_CACHE_WBACK
+	mov	CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
+#else
+	mov	CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
+#endif /* WBACK */
+	movhu	d0,(a0)					# enable
+#endif /* !ENABLED */
+
+	# clear the BSS area
+	mov	__bss_start,a0
+	mov	_end,a1
+	clr	d0
+bssclear:
+	cmp	a1,a0
+	bge	bssclear_end
+	movbu	d0,(a0)
+	inc	a0
+	bra	bssclear
+bssclear_end:
+
+	# decompress the kernel
+	call	decompress_kernel[],0
+#ifdef CONFIG_MN10300_CACHE_WBACK
+	call	mn10300_dcache_flush_inv[],0
+#endif
+
+	# disable caches again
+	mov	CHCTR,a0
+	clr	d0
+	movhu	d0,(a0)
+	setlb
+	mov	(a0),d0
+	btst	CHCTR_ICBUSY|CHCTR_DCBUSY,d0		# wait till not busy
+	lne
+
+	mov	param_save_area,a0
+	mov	(a0),d0
+	mov	(4,a0),d1
+	mov	(8,a0),d2
+
+	# jump to the kernel proper entry point
+	mov	a3,sp
+	mov	CONFIG_KERNEL_TEXT_ADDRESS,a0
+	jmp	(a0)
+
+
+###############################################################################
+#
+# Cache flush routines
+#
+###############################################################################
+#ifdef CONFIG_MN10300_CACHE_WBACK
+mn10300_dcache_flush_inv:
+	movhu	(CHCTR),d0
+	btst	CHCTR_DCEN,d0
+	beq	mn10300_dcache_flush_inv_end
+
+	mov	L1_CACHE_NENTRIES,d1
+	clr	a1
+
+mn10300_dcache_flush_inv_loop:
+	mov	(DCACHE_PURGE_WAY0(0),a1),d0	# unconditional purge
+	mov	(DCACHE_PURGE_WAY1(0),a1),d0	# unconditional purge
+	mov	(DCACHE_PURGE_WAY2(0),a1),d0	# unconditional purge
+	mov	(DCACHE_PURGE_WAY3(0),a1),d0	# unconditional purge
+
+	add	L1_CACHE_BYTES,a1
+	add	-1,d1
+	bne	mn10300_dcache_flush_inv_loop
+
+mn10300_dcache_flush_inv_end:
+	ret	[],0
+#endif /* CONFIG_MN10300_CACHE_WBACK */
+
+
+###############################################################################
+#
+# Data areas
+#
+###############################################################################
+	.data
+	.align		4
+param_save_area:
+	.rept 3
+	.word		0
+	.endr
+
+	.section	.bss
+	.align		4
+decomp_stack:
+	.space		0x2000
diff --git a/arch/mn10300/boot/compressed/misc.c b/arch/mn10300/boot/compressed/misc.c
new file mode 100644
index 0000000..42cbd77
--- /dev/null
+++ b/arch/mn10300/boot/compressed/misc.c
@@ -0,0 +1,393 @@
+/* MN10300 Miscellaneous helper routines for kernel decompressor
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ * - Derived from arch/x86/boot/compressed/misc_32.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/compiler.h>
+#include <asm/serial-regs.h>
+#include "misc.h"
+
+#ifndef CONFIG_GDBSTUB_ON_TTYSx
+/* display 'Uncompressing Linux... ' messages on ttyS0 or ttyS1 */
+#if 1	/* ttyS0 */
+#define CYG_DEV_BASE	0xA6FB0000
+#else   /* ttyS1 */
+#define CYG_DEV_BASE	0xA6FC0000
+#endif
+
+#define CYG_DEV_THR	(*((volatile __u8*)(CYG_DEV_BASE + 0x00)))
+#define CYG_DEV_MCR	(*((volatile __u8*)(CYG_DEV_BASE + 0x10)))
+#define SIO_MCR_DTR	0x01
+#define SIO_MCR_RTS	0x02
+#define CYG_DEV_LSR	(*((volatile __u8*)(CYG_DEV_BASE + 0x14)))
+#define SIO_LSR_THRE	0x20		/* transmitter holding register empty */
+#define SIO_LSR_TEMT	0x40		/* transmitter register empty */
+#define CYG_DEV_MSR	(*((volatile __u8*)(CYG_DEV_BASE + 0x18)))
+#define SIO_MSR_CTS	0x10		/* clear to send */
+#define SIO_MSR_DSR	0x20		/* data set ready */
+
+#define LSR_WAIT_FOR(STATE) \
+	do { while (!(CYG_DEV_LSR & SIO_LSR_##STATE)) {} } while (0)
+#define FLOWCTL_QUERY(LINE) \
+	({ CYG_DEV_MSR & SIO_MSR_##LINE; })
+#define FLOWCTL_WAIT_FOR(LINE) \
+	do { while (!(CYG_DEV_MSR & SIO_MSR_##LINE)) {} } while (0)
+#define FLOWCTL_CLEAR(LINE) \
+	do { CYG_DEV_MCR &= ~SIO_MCR_##LINE; } while (0)
+#define FLOWCTL_SET(LINE) \
+	do { CYG_DEV_MCR |= SIO_MCR_##LINE; } while (0)
+#endif
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+#define STATIC static
+
+#undef memset
+#undef memcpy
+
+static inline void *memset(const void *s, int c, size_t n)
+{
+	int i;
+	char *ss = (char *) s;
+
+	for (i = 0; i < n; i++)
+		ss[i] = c;
+	return (void *)s;
+}
+
+#define memzero(s, n) memset((s), 0, (n))
+
+static inline void *memcpy(void *__dest, const void *__src, size_t __n)
+{
+	int i;
+	const char *s = __src;
+	char *d = __dest;
+
+	for (i = 0; i < __n; i++)
+		d[i] = s[i];
+	return __dest;
+}
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define WSIZE 0x8000	/* Window size must be at least 32k, and a power of
+			 * two */
+
+static uch *inbuf;	/* input buffer */
+static uch window[WSIZE]; /* sliding window buffer */
+
+static unsigned insize;	/* valid bytes in inbuf */
+static unsigned inptr;	/* index of next byte to be processed in inbuf */
+static unsigned outcnt;	/* bytes in output buffer */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0 /* bit 6,7:   reserved */
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond, msg) { if (!(cond)) error(msg); }
+#  define Trace(x)	fprintf x
+#  define Tracev(x)	{ if (verbose) fprintf x ; }
+#  define Tracevv(x)	{ if (verbose > 1) fprintf x ; }
+#  define Tracec(c, x)	{ if (verbose && (c)) fprintf x ; }
+#  define Tracecv(c, x)	{ if (verbose > 1 && (c)) fprintf x ; }
+#else
+#  define Assert(cond, msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c, x)
+#  define Tracecv(c, x)
+#endif
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void error(const char *) __attribute__((noreturn));
+static void kputs(const char *);
+
+static inline unsigned char get_byte(void)
+{
+	unsigned char ch = inptr < insize ? inbuf[inptr++] : fill_inbuf();
+
+#if 0
+	char hex[3];
+	hex[0] = ((ch & 0x0f) > 9) ?
+		((ch & 0x0f) + 'A' - 0xa) : ((ch & 0x0f) + '0');
+	hex[1] = ((ch >> 4) > 9) ?
+		((ch >> 4) + 'A' - 0xa) : ((ch >> 4) + '0');
+	hex[2] = 0;
+	kputs(hex);
+#endif
+	return ch;
+}
+
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+#define EXT_MEM_K (*(unsigned short *)0x90002)
+#ifndef STANDARD_MEMORY_BIOS_CALL
+#define ALT_MEM_K (*(unsigned long *) 0x901e0)
+#endif
+#define SCREEN_INFO (*(struct screen_info *)0x90000)
+
+static long bytes_out;
+static uch *output_data;
+static unsigned long output_ptr;
+
+
+static unsigned long free_mem_ptr = (unsigned long) &end;
+static unsigned long free_mem_end_ptr = (unsigned long) &end + 0x90000;
+
+#define INPLACE_MOVE_ROUTINE	0x1000
+#define LOW_BUFFER_START	0x2000
+#define LOW_BUFFER_END		0x90000
+#define LOW_BUFFER_SIZE		(LOW_BUFFER_END - LOW_BUFFER_START)
+#define HEAP_SIZE		0x3000
+static int high_loaded;
+static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
+
+static char *vidmem = (char *)0xb8000;
+static int lines, cols;
+
+#define BOOTLOADER_INFLATE
+#include "../../../../lib/inflate.c"
+
+static inline void scroll(void)
+{
+	int i;
+
+	memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
+	for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
+		vidmem[i] = ' ';
+}
+
+static inline void kputchar(unsigned char ch)
+{
+#ifdef CONFIG_MN10300_UNIT_ASB2305
+	while (SC0STR & SC01STR_TBF)
+		continue;
+
+	if (ch == 0x0a) {
+		SC0TXB = 0x0d;
+		while (SC0STR & SC01STR_TBF)
+			continue;
+	}
+
+	SC0TXB = ch;
+
+#else
+	while (SC1STR & SC01STR_TBF)
+		continue;
+
+	if (ch == 0x0a) {
+		SC1TXB = 0x0d;
+		while (SC1STR & SC01STR_TBF)
+			continue;
+	}
+
+	SC1TXB = ch;
+
+#endif
+}
+
+static void kputs(const char *s)
+{
+#ifdef CONFIG_DEBUG_DECOMPRESS_KERNEL
+#ifndef CONFIG_GDBSTUB_ON_TTYSx
+	char ch;
+
+	FLOWCTL_SET(DTR);
+
+	while (*s) {
+		LSR_WAIT_FOR(THRE);
+
+		ch = *s++;
+		if (ch == 0x0a) {
+			CYG_DEV_THR = 0x0d;
+			LSR_WAIT_FOR(THRE);
+		}
+		CYG_DEV_THR = ch;
+	}
+
+	FLOWCTL_CLEAR(DTR);
+#else
+
+	for (; *s; s++)
+		kputchar(*s);
+
+#endif
+#endif /* CONFIG_DEBUG_DECOMPRESS_KERNEL */
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf()
+{
+	if (insize != 0)
+		error("ran out of input data\n");
+
+	inbuf = input_data;
+	insize = input_len;
+	inptr = 1;
+	return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window_low(void)
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in, *out, ch;
+
+    in = window;
+    out = &output_data[output_ptr];
+    for (n = 0; n < outcnt; n++) {
+	    ch = *out++ = *in++;
+	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    output_ptr += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void flush_window_high(void)
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in,  ch;
+    in = window;
+    for (n = 0; n < outcnt; n++) {
+	ch = *output_data++ = *in++;
+	if ((ulg) output_data == LOW_BUFFER_END)
+		output_data = high_buffer_start;
+	c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void flush_window(void)
+{
+	if (high_loaded)
+		flush_window_high();
+	else
+		flush_window_low();
+}
+
+static void error(const char *x)
+{
+	kputs("\n\n");
+	kputs(x);
+	kputs("\n\n -- System halted");
+
+	while (1)
+		/* Halt */;
+}
+
+#define STACK_SIZE (4096)
+
+long user_stack[STACK_SIZE];
+
+struct {
+	long *a;
+	short b;
+} stack_start = { &user_stack[STACK_SIZE], 0 };
+
+void setup_normal_output_buffer(void)
+{
+#ifdef STANDARD_MEMORY_BIOS_CALL
+	if (EXT_MEM_K < 1024)
+		error("Less than 2MB of memory.\n");
+#else
+	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024)
+		error("Less than 2MB of memory.\n");
+#endif
+	output_data = (char *) 0x100000; /* Points to 1M */
+}
+
+struct moveparams {
+	uch *low_buffer_start;
+	int lcount;
+	uch *high_buffer_start;
+	int hcount;
+};
+
+void setup_output_buffer_if_we_run_high(struct moveparams *mv)
+{
+	high_buffer_start = (uch *)(((ulg) &end) + HEAP_SIZE);
+#ifdef STANDARD_MEMORY_BIOS_CALL
+	if (EXT_MEM_K < (3 * 1024))
+		error("Less than 4MB of memory.\n");
+#else
+	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3 * 1024))
+		error("Less than 4MB of memory.\n");
+#endif
+	mv->low_buffer_start = output_data = (char *) LOW_BUFFER_START;
+	high_loaded = 1;
+	free_mem_end_ptr = (long) high_buffer_start;
+	if (0x100000 + LOW_BUFFER_SIZE > (ulg) high_buffer_start) {
+		high_buffer_start = (uch *)(0x100000 + LOW_BUFFER_SIZE);
+		mv->hcount = 0; /* say: we need not to move high_buffer */
+	} else {
+		mv->hcount = -1;
+	}
+	mv->high_buffer_start = high_buffer_start;
+}
+
+void close_output_buffer_if_we_run_high(struct moveparams *mv)
+{
+	mv->lcount = bytes_out;
+	if (bytes_out > LOW_BUFFER_SIZE) {
+		mv->lcount = LOW_BUFFER_SIZE;
+		if (mv->hcount)
+			mv->hcount = bytes_out - LOW_BUFFER_SIZE;
+	} else {
+		mv->hcount = 0;
+	}
+}
+
+#undef DEBUGFLAG
+#ifdef DEBUGFLAG
+int debugflag;
+#endif
+
+int decompress_kernel(struct moveparams *mv)
+{
+#ifdef DEBUGFLAG
+	while (!debugflag)
+		barrier();
+#endif
+
+	output_data = (char *) CONFIG_KERNEL_TEXT_ADDRESS;
+
+	makecrc();
+	kputs("Uncompressing Linux... ");
+	gunzip();
+	kputs("Ok, booting the kernel.\n");
+	return 0;
+}
diff --git a/arch/mn10300/boot/compressed/misc.h b/arch/mn10300/boot/compressed/misc.h
new file mode 100644
index 0000000..da921cd
--- /dev/null
+++ b/arch/mn10300/boot/compressed/misc.h
@@ -0,0 +1,18 @@
+/* Internal definitions for the MN10300 kernel decompressor
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+extern int end;
+
+/*
+ * vmlinux.lds
+ */
+extern char input_data[];
+extern int input_len;
diff --git a/arch/mn10300/boot/compressed/vmlinux.lds b/arch/mn10300/boot/compressed/vmlinux.lds
new file mode 100644
index 0000000..a084903
--- /dev/null
+++ b/arch/mn10300/boot/compressed/vmlinux.lds
@@ -0,0 +1,9 @@
+SECTIONS
+{
+  .data : {
+	input_len = .;
+	LONG(input_data_end - input_data) input_data = .;
+	*(.data)
+	input_data_end = .;
+	}
+}
diff --git a/arch/mn10300/boot/install.sh b/arch/mn10300/boot/install.sh
new file mode 100644
index 0000000..abba309
--- /dev/null
+++ b/arch/mn10300/boot/install.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+#
+# arch/mn10300/boot/install -c.sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# Licence.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+#
+# "make install -c" script for i386 architecture
+#
+# Arguments:
+#   $1 - kernel version
+#   $2 - kernel image file
+#   $3 - kernel map file
+#   $4 - default install -c path (blank if root directory)
+#   $5 - boot rom file
+#
+
+# User may have a custom install -c script
+
+rm -fr $4/../usr/include/linux $4/../usr/include/asm
+install -c -m 0755 $2 $4/vmlinuz
+install -c -m 0755 $5 $4/boot.rom
+install -c -m 0755 -d $4/../usr/include/linux
+cd ${srctree}/include/linux
+for i in `find . -maxdepth 1 -name '*.h' -print`; do
+  install -c -m 0644 $i $4/../usr/include/linux
+done
+install -c -m 0755 -d $4/../usr/include/linux/byteorder
+cd ${srctree}/include/linux/byteorder
+for i in `find . -name '*.h' -print`; do
+  install -c -m 0644 $i $4/../usr/include/linux/byteorder
+done
+install -c -m 0755 -d $4/../usr/include/linux/lockd
+cd ${srctree}/include/linux/lockd
+for i in `find . -name '*.h' -print`; do
+  install -c -m 0644 $i $4/../usr/include/linux/lockd
+done
+install -c -m 0755 -d $4/../usr/include/linux/netfilter_ipv4
+cd ${srctree}/include/linux/netfilter_ipv4
+for i in `find . -name '*.h' -print`; do
+  install -c -m 0644 $i $4/../usr/include/linux/netfilter_ipv4
+done
+install -c -m 0755 -d $4/../usr/include/linux/nfsd
+cd ${srctree}/include/linux/nfsd
+for i in `find . -name '*.h' -print`; do
+  install -c -m 0644 $i $4/../usr/include/linux/nfsd/$i
+done
+install -c -m 0755 -d $4/../usr/include/linux/raid
+cd ${srctree}/include/linux/raid
+for i in `find . -name '*.h' -print`; do
+  install -c -m 0644 $i $4/../usr/include/linux/raid
+done
+install -c -m 0755 -d $4/../usr/include/linux/sunrpc
+cd ${srctree}/include/linux/sunrpc
+for i in `find . -name '*.h' -print`; do
+  install -c -m 0644 $i $4/../usr/include/linux/sunrpc
+done
+install -c -m 0755 -d $4/../usr/include/asm
+cd ${srctree}/include/asm
+for i in `find . -name '*.h' -print`; do
+  install -c -m 0644 $i $4/../usr/include/asm
+done
diff --git a/arch/mn10300/boot/tools/build.c b/arch/mn10300/boot/tools/build.c
new file mode 100644
index 0000000..4f552ea
--- /dev/null
+++ b/arch/mn10300/boot/tools/build.c
@@ -0,0 +1,190 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 1997 Martin Mares
+ */
+
+/*
+ * This file builds a disk-image from three different files:
+ *
+ * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
+ * - setup: 8086 machine code, sets up system parm
+ * - system: 80386 code for actual system
+ *
+ * It does some checking that all files are of the correct type, and
+ * just writes the result to stdout, removing headers and padding to
+ * the right amount. It also writes some system data to stderr.
+ */
+
+/*
+ * Changes by tytso to allow root device specification
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ * Cross compiling fixes by Gertjan van Wingerde, July 1996
+ * Rewritten by Martin Mares, April 1997
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <asm/boot.h>
+
+#define DEFAULT_MAJOR_ROOT 0
+#define DEFAULT_MINOR_ROOT 0
+
+/* Minimal number of setup sectors (see also bootsect.S) */
+#define SETUP_SECTS 4
+
+uint8_t buf[1024];
+int fd;
+int is_big_kernel;
+
+__attribute__((noreturn))
+void die(const char *str, ...)
+{
+	va_list args;
+	va_start(args, str);
+	vfprintf(stderr, str, args);
+	fputc('\n', stderr);
+	exit(1);
+}
+
+void file_open(const char *name)
+{
+	fd = open(name, O_RDONLY, 0);
+	if (fd < 0)
+		die("Unable to open `%s': %m", name);
+}
+
+__attribute__((noreturn))
+void usage(void)
+{
+	die("Usage: build [-b] bootsect setup system [rootdev] [> image]");
+}
+
+int main(int argc, char **argv)
+{
+	unsigned int i, c, sz, setup_sectors;
+	uint32_t sys_size;
+	uint8_t major_root, minor_root;
+	struct stat sb;
+
+	if (argc > 2 && !strcmp(argv[1], "-b")) {
+		is_big_kernel = 1;
+		argc--, argv++;
+	}
+	if ((argc < 4) || (argc > 5))
+		usage();
+	if (argc > 4) {
+		if (!strcmp(argv[4], "CURRENT")) {
+			if (stat("/", &sb)) {
+				perror("/");
+				die("Couldn't stat /");
+			}
+			major_root = major(sb.st_dev);
+			minor_root = minor(sb.st_dev);
+		} else if (strcmp(argv[4], "FLOPPY")) {
+			if (stat(argv[4], &sb)) {
+				perror(argv[4]);
+				die("Couldn't stat root device.");
+			}
+			major_root = major(sb.st_rdev);
+			minor_root = minor(sb.st_rdev);
+		} else {
+			major_root = 0;
+			minor_root = 0;
+		}
+	} else {
+		major_root = DEFAULT_MAJOR_ROOT;
+		minor_root = DEFAULT_MINOR_ROOT;
+	}
+	fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
+
+	file_open(argv[1]);
+	i = read(fd, buf, sizeof(buf));
+	fprintf(stderr, "Boot sector %d bytes.\n", i);
+	if (i != 512)
+		die("Boot block must be exactly 512 bytes");
+	if (buf[510] != 0x55 || buf[511] != 0xaa)
+		die("Boot block hasn't got boot flag (0xAA55)");
+	buf[508] = minor_root;
+	buf[509] = major_root;
+	if (write(1, buf, 512) != 512)
+		die("Write call failed");
+	close(fd);
+
+	/* Copy the setup code */
+	file_open(argv[2]);
+	for (i = 0; (c = read(fd, buf, sizeof(buf))) > 0; i += c)
+		if (write(1, buf, c) != c)
+			die("Write call failed");
+	if (c != 0)
+		die("read-error on `setup'");
+	close(fd);
+
+	/* Pad unused space with zeros */
+	setup_sectors = (i + 511) / 512;
+	/* for compatibility with ancient versions of LILO. */
+	if (setup_sectors < SETUP_SECTS)
+		setup_sectors = SETUP_SECTS;
+	fprintf(stderr, "Setup is %d bytes.\n", i);
+	memset(buf, 0, sizeof(buf));
+	while (i < setup_sectors * 512) {
+		c = setup_sectors * 512 - i;
+		if (c > sizeof(buf))
+			c = sizeof(buf);
+		if (write(1, buf, c) != c)
+			die("Write call failed");
+		i += c;
+	}
+
+	file_open(argv[3]);
+	if (fstat(fd, &sb))
+		die("Unable to stat `%s': %m", argv[3]);
+	sz = sb.st_size;
+	fprintf(stderr, "System is %d kB\n", sz / 1024);
+	sys_size = (sz + 15) / 16;
+	/* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */
+	if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE))
+		die("System is too big. Try using %smodules.",
+			is_big_kernel ? "" : "bzImage or ");
+	if (sys_size > 0xffff)
+		fprintf(stderr,
+			"warning: kernel is too big for standalone boot "
+			"from floppy\n");
+	while (sz > 0) {
+		int l, n;
+
+		l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
+		n = read(fd, buf, l);
+		if (n != l) {
+			if (n < 0)
+				die("Error reading %s: %m", argv[3]);
+			else
+				die("%s: Unexpected EOF", argv[3]);
+		}
+		if (write(1, buf, l) != l)
+			die("Write failed");
+		sz -= l;
+	}
+	close(fd);
+
+	/* Write sizes to the bootsector */
+	if (lseek(1, 497, SEEK_SET) != 497)
+		die("Output: seek failed");
+	buf[0] = setup_sectors;
+	if (write(1, buf, 1) != 1)
+		die("Write of setup sector count failed");
+	if (lseek(1, 500, SEEK_SET) != 500)
+		die("Output: seek failed");
+	buf[0] = (sys_size & 0xff);
+	buf[1] = ((sys_size >> 8) & 0xff);
+	if (write(1, buf, 2) != 2)
+		die("Write of image length failed");
+
+	return 0;
+}
diff --git a/arch/mn10300/configs/asb2303_defconfig b/arch/mn10300/configs/asb2303_defconfig
new file mode 100644
index 0000000..1fd41ec
--- /dev/null
+++ b/arch/mn10300/configs/asb2303_defconfig
@@ -0,0 +1,73 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_TINY_RCU=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EXPERT=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+# CONFIG_BLOCK is not set
+CONFIG_PREEMPT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_MN10300_RTC=y
+CONFIG_MN10300_TTYSM_CONSOLE=y
+CONFIG_MN10300_TTYSM0=y
+CONFIG_MN10300_TTYSM1=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_I4=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_RTC=y
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_PROC_KCORE=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_STRIP_ASM_SYMS=y
diff --git a/arch/mn10300/configs/asb2364_defconfig b/arch/mn10300/configs/asb2364_defconfig
new file mode 100644
index 0000000..fbb96ae
--- /dev/null
+++ b/arch/mn10300/configs/asb2364_defconfig
@@ -0,0 +1,97 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_RELAY=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EXPERT=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLOCK is not set
+CONFIG_MN10300_UNIT_ASB2364=y
+CONFIG_PREEMPT=y
+# CONFIG_MN10300_USING_JTAG is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_MN10300_TTYSM_CONSOLE=y
+CONFIG_MN10300_TTYSM0=y
+CONFIG_MN10300_TTYSM0_TIMER2=y
+CONFIG_MN10300_TTYSM1=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_I4=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_PROC_KCORE=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
new file mode 100644
index 0000000..1c8dd0f
--- /dev/null
+++ b/arch/mn10300/include/asm/Kbuild
@@ -0,0 +1,12 @@
+
+generic-y += barrier.h
+generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += exec.h
+generic-y += irq_work.h
+generic-y += mcs_spinlock.h
+generic-y += mm-arch-hooks.h
+generic-y += preempt.h
+generic-y += sections.h
+generic-y += trace_clock.h
+generic-y += word-at-a-time.h
diff --git a/arch/mn10300/include/asm/asm-offsets.h b/arch/mn10300/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/mn10300/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/mn10300/include/asm/atomic.h b/arch/mn10300/include/asm/atomic.h
new file mode 100644
index 0000000..ce318d5
--- /dev/null
+++ b/arch/mn10300/include/asm/atomic.h
@@ -0,0 +1,136 @@
+/* MN10300 Atomic counter operations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_ATOMIC_H
+#define _ASM_ATOMIC_H
+
+#include <asm/irqflags.h>
+#include <asm/cmpxchg.h>
+#include <asm/barrier.h>
+
+#ifndef CONFIG_SMP
+#include <asm-generic/atomic.h>
+#else
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+#define ATOMIC_INIT(i)	{ (i) }
+
+#ifdef __KERNEL__
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v.  Note that the guaranteed
+ */
+#define atomic_read(v)	READ_ONCE((v)->counter)
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.  Note that the guaranteed
+ */
+#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
+
+#define ATOMIC_OP(op)							\
+static inline void atomic_##op(int i, atomic_t *v)			\
+{									\
+	int retval, status;						\
+									\
+	asm volatile(							\
+		"1:	mov	%4,(_AAR,%3)	\n"			\
+		"	mov	(_ADR,%3),%1	\n"			\
+		"	" #op "	%5,%1		\n"			\
+		"	mov	%1,(_ADR,%3)	\n"			\
+		"	mov	(_ADR,%3),%0	\n"	/* flush */	\
+		"	mov	(_ASR,%3),%0	\n"			\
+		"	or	%0,%0		\n"			\
+		"	bne	1b		\n"			\
+		: "=&r"(status), "=&r"(retval), "=m"(v->counter)	\
+		: "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i)	\
+		: "memory", "cc");					\
+}
+
+#define ATOMIC_OP_RETURN(op)						\
+static inline int atomic_##op##_return(int i, atomic_t *v)		\
+{									\
+	int retval, status;						\
+									\
+	asm volatile(							\
+		"1:	mov	%4,(_AAR,%3)	\n"			\
+		"	mov	(_ADR,%3),%1	\n"			\
+		"	" #op "	%5,%1		\n"			\
+		"	mov	%1,(_ADR,%3)	\n"			\
+		"	mov	(_ADR,%3),%0	\n"	/* flush */	\
+		"	mov	(_ASR,%3),%0	\n"			\
+		"	or	%0,%0		\n"			\
+		"	bne	1b		\n"			\
+		: "=&r"(status), "=&r"(retval), "=m"(v->counter)	\
+		: "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i)	\
+		: "memory", "cc");					\
+	return retval;							\
+}
+
+#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op)
+
+ATOMIC_OPS(add)
+ATOMIC_OPS(sub)
+
+ATOMIC_OP(and)
+ATOMIC_OP(or)
+ATOMIC_OP(xor)
+
+#undef ATOMIC_OPS
+#undef ATOMIC_OP_RETURN
+#undef ATOMIC_OP
+
+static inline int atomic_add_negative(int i, atomic_t *v)
+{
+	return atomic_add_return(i, v) < 0;
+}
+
+static inline void atomic_inc(atomic_t *v)
+{
+	atomic_add_return(1, v);
+}
+
+static inline void atomic_dec(atomic_t *v)
+{
+	atomic_sub_return(1, v);
+}
+
+#define atomic_dec_return(v)		atomic_sub_return(1, (v))
+#define atomic_inc_return(v)		atomic_add_return(1, (v))
+
+#define atomic_sub_and_test(i, v)	(atomic_sub_return((i), (v)) == 0)
+#define atomic_dec_and_test(v)		(atomic_sub_return(1, (v)) == 0)
+#define atomic_inc_and_test(v)		(atomic_add_return(1, (v)) == 0)
+
+#define __atomic_add_unless(v, a, u)				\
+({								\
+	int c, old;						\
+	c = atomic_read(v);					\
+	while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
+		c = old;					\
+	c;							\
+})
+
+#define atomic_xchg(ptr, v)		(xchg(&(ptr)->counter, (v)))
+#define atomic_cmpxchg(v, old, new)	(cmpxchg(&((v)->counter), (old), (new)))
+
+#endif /* __KERNEL__ */
+#endif /* CONFIG_SMP */
+#endif /* _ASM_ATOMIC_H */
diff --git a/arch/mn10300/include/asm/bitops.h b/arch/mn10300/include/asm/bitops.h
new file mode 100644
index 0000000..fe6f8e2
--- /dev/null
+++ b/arch/mn10300/include/asm/bitops.h
@@ -0,0 +1,232 @@
+/* MN10300 bit operations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ *
+ * These have to be done with inline assembly: that way the bit-setting
+ * is guaranteed to be atomic. All bit operations return 0 if the bit
+ * was cleared before the operation and != 0 if it was not.
+ *
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+#ifndef __ASM_BITOPS_H
+#define __ASM_BITOPS_H
+
+#include <asm/cpu-regs.h>
+#include <asm/barrier.h>
+
+/*
+ * set bit
+ */
+#define __set_bit(nr, addr)					\
+({								\
+	volatile unsigned char *_a = (unsigned char *)(addr);	\
+	const unsigned shift = (nr) & 7;			\
+	_a += (nr) >> 3;					\
+								\
+	asm volatile("bset %2,(%1) # set_bit reg"		\
+		     : "=m"(*_a)				\
+		     : "a"(_a), "d"(1 << shift),  "m"(*_a)	\
+		     : "memory", "cc");				\
+})
+
+#define set_bit(nr, addr) __set_bit((nr), (addr))
+
+/*
+ * clear bit
+ */
+#define ___clear_bit(nr, addr)					\
+({								\
+	volatile unsigned char *_a = (unsigned char *)(addr);	\
+	const unsigned shift = (nr) & 7;			\
+	_a += (nr) >> 3;					\
+								\
+	asm volatile("bclr %2,(%1) # clear_bit reg"		\
+		     : "=m"(*_a)				\
+		     : "a"(_a), "d"(1 << shift), "m"(*_a)	\
+		     : "memory", "cc");				\
+})
+
+#define clear_bit(nr, addr) ___clear_bit((nr), (addr))
+
+
+static inline void __clear_bit(unsigned long nr, volatile void *addr)
+{
+	unsigned int *a = (unsigned int *) addr;
+	int mask;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	*a &= ~mask;
+}
+
+/*
+ * test bit
+ */
+static inline int test_bit(unsigned long nr, const volatile void *addr)
+{
+	return 1UL & (((const volatile unsigned int *) addr)[nr >> 5] >> (nr & 31));
+}
+
+/*
+ * change bit
+ */
+static inline void __change_bit(unsigned long nr, volatile void *addr)
+{
+	int	mask;
+	unsigned int *a = (unsigned int *) addr;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	*a ^= mask;
+}
+
+extern void change_bit(unsigned long nr, volatile void *addr);
+
+/*
+ * test and set bit
+ */
+#define __test_and_set_bit(nr,addr)				\
+({								\
+	volatile unsigned char *_a = (unsigned char *)(addr);	\
+	const unsigned shift = (nr) & 7;			\
+	unsigned epsw;						\
+	_a += (nr) >> 3;					\
+								\
+	asm volatile("bset %3,(%2) # test_set_bit reg\n"	\
+		     "mov epsw,%1"				\
+		     : "=m"(*_a), "=d"(epsw)			\
+		     : "a"(_a), "d"(1 << shift), "m"(*_a)	\
+		     : "memory", "cc");				\
+								\
+	!(epsw & EPSW_FLAG_Z);					\
+})
+
+#define test_and_set_bit(nr, addr) __test_and_set_bit((nr), (addr))
+
+/*
+ * test and clear bit
+ */
+#define __test_and_clear_bit(nr, addr)				\
+({								\
+        volatile unsigned char *_a = (unsigned char *)(addr);	\
+	const unsigned shift = (nr) & 7;			\
+	unsigned epsw;						\
+	_a += (nr) >> 3;					\
+								\
+	asm volatile("bclr %3,(%2) # test_clear_bit reg\n"	\
+		     "mov epsw,%1"				\
+		     : "=m"(*_a), "=d"(epsw)			\
+		     : "a"(_a), "d"(1 << shift), "m"(*_a)	\
+		     : "memory", "cc");				\
+								\
+	!(epsw & EPSW_FLAG_Z);					\
+})
+
+#define test_and_clear_bit(nr, addr) __test_and_clear_bit((nr), (addr))
+
+/*
+ * test and change bit
+ */
+static inline int __test_and_change_bit(unsigned long nr, volatile void *addr)
+{
+	int	mask, retval;
+	unsigned int *a = (unsigned int *)addr;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	retval = (mask & *a) != 0;
+	*a ^= mask;
+
+	return retval;
+}
+
+extern int test_and_change_bit(unsigned long nr, volatile void *addr);
+
+#include <asm-generic/bitops/lock.h>
+
+#ifdef __KERNEL__
+
+/**
+ * __ffs - find first bit set
+ * @x: the word to search
+ *
+ * - return 31..0 to indicate bit 31..0 most least significant bit set
+ * - if no bits are set in x, the result is undefined
+ */
+static inline __attribute__((const))
+unsigned long __ffs(unsigned long x)
+{
+	int bit;
+	asm("bsch %2,%0" : "=r"(bit) : "0"(0), "r"(x & -x) : "cc");
+	return bit;
+}
+
+/*
+ * special slimline version of fls() for calculating ilog2_u32()
+ * - note: no protection against n == 0
+ */
+static inline __attribute__((const))
+int __ilog2_u32(u32 n)
+{
+	int bit;
+	asm("bsch %2,%0" : "=r"(bit) : "0"(0), "r"(n) : "cc");
+	return bit;
+}
+
+/**
+ * fls - find last bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs:
+ * - return 32..1 to indicate bit 31..0 most significant bit set
+ * - return 0 to indicate no bits set
+ */
+static inline __attribute__((const))
+int fls(int x)
+{
+	return (x != 0) ? __ilog2_u32(x) + 1 : 0;
+}
+
+/**
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+	return __ilog2_u32(word);
+}
+
+/**
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * - return 32..1 to indicate bit 31..0 most least significant bit set
+ * - return 0 to indicate no bits set
+ */
+static inline __attribute__((const))
+int ffs(int x)
+{
+	/* Note: (x & -x) gives us a mask that is the least significant
+	 * (rightmost) 1-bit of the value in x.
+	 */
+	return fls(x & -x);
+}
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
+#include <asm-generic/bitops/le.h>
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_BITOPS_H */
diff --git a/arch/mn10300/include/asm/bug.h b/arch/mn10300/include/asm/bug.h
new file mode 100644
index 0000000..aa6a388
--- /dev/null
+++ b/arch/mn10300/include/asm/bug.h
@@ -0,0 +1,37 @@
+/* MN10300 Kernel bug reporting
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_BUG_H
+#define _ASM_BUG_H
+
+#ifdef CONFIG_BUG
+
+/*
+ * Tell the user there is some problem.
+ */
+#define BUG()							\
+do {								\
+	asm volatile(						\
+		"	syscall 15			\n"	\
+		"0:					\n"	\
+		"	.section __bug_table,\"a\"	\n"	\
+		"	.long 0b,%0,%1			\n"	\
+		"	.previous			\n"	\
+		:						\
+		: "i"(__FILE__), "i"(__LINE__)			\
+		);						\
+} while (1)
+
+#define HAVE_ARCH_BUG
+#endif /* CONFIG_BUG */
+
+#include <asm-generic/bug.h>
+
+#endif /* _ASM_BUG_H */
diff --git a/arch/mn10300/include/asm/bugs.h b/arch/mn10300/include/asm/bugs.h
new file mode 100644
index 0000000..31c8bc5
--- /dev/null
+++ b/arch/mn10300/include/asm/bugs.h
@@ -0,0 +1,20 @@
+/* MN10300 Checks for architecture-dependent bugs
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_BUGS_H
+#define _ASM_BUGS_H
+
+#include <asm/processor.h>
+
+static inline void __init check_bugs(void)
+{
+}
+
+#endif /* _ASM_BUGS_H */
diff --git a/arch/mn10300/include/asm/busctl-regs.h b/arch/mn10300/include/asm/busctl-regs.h
new file mode 100644
index 0000000..1632aef
--- /dev/null
+++ b/arch/mn10300/include/asm/busctl-regs.h
@@ -0,0 +1,151 @@
+/* AM33v2 on-board bus controller registers
+ *
+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_BUSCTL_REGS_H
+#define _ASM_BUSCTL_REGS_H
+
+#include <asm/cpu-regs.h>
+
+#ifdef __KERNEL__
+
+/* bus controller registers */
+#define BCCR			__SYSREG(0xc0002000, u32)	/* bus controller control reg */
+#define BCCR_B0AD		0x00000003	/* block 0 (80000000-83ffffff) bus allocation */
+#define BCCR_B1AD		0x0000000c	/* block 1 (84000000-87ffffff) bus allocation */
+#define BCCR_B2AD		0x00000030	/* block 2 (88000000-8bffffff) bus allocation */
+#define BCCR_B3AD		0x000000c0	/* block 3 (8c000000-8fffffff) bus allocation */
+#define BCCR_B4AD		0x00000300	/* block 4 (90000000-93ffffff) bus allocation */
+#define BCCR_B5AD		0x00000c00	/* block 5 (94000000-97ffffff) bus allocation */
+#define BCCR_B6AD		0x00003000	/* block 6 (98000000-9bffffff) bus allocation */
+#define BCCR_B7AD		0x0000c000	/* block 7 (9c000000-9fffffff) bus allocation */
+#define BCCR_BxAD_EXBUS		0x0		/* - direct to system bus controller */
+#define BCCR_BxAD_OPEXBUS	0x1		/* - direct to memory bus controller */
+#define BCCR_BxAD_OCMBUS	0x2		/* - direct to on chip memory */
+#define BCCR_API		0x00070000	/* bus arbitration priority */
+#define BCCR_API_DMACICD	0x00000000	/* - DMA > CI > CD */
+#define BCCR_API_DMACDCI	0x00010000	/* - DMA > CD > CI */
+#define BCCR_API_CICDDMA	0x00020000	/* - CI > CD > DMA */
+#define BCCR_API_CDCIDMA	0x00030000	/* - CD > CI > DMA */
+#define BCCR_API_ROUNDROBIN	0x00040000	/* - round robin */
+#define BCCR_BEPRI_DMACICD	0x00c00000	/* bus error address priority */
+#define BCCR_BEPRI_DMACDCI	0x00000000	/* - DMA > CI > CD */
+#define BCCR_BEPRI_CICDDMA	0x00400000	/* - DMA > CD > CI */
+#define BCCR_BEPRI_CDCIDMA	0x00800000	/* - CI > CD > DMA */
+#define BCCR_BEPRI		0x00c00000	/* - CD > CI > DMA */
+#define BCCR_TMON		0x03000000	/* timeout value settings */
+#define BCCR_TMON_16IOCLK	0x00000000	/* - 16 IOCLK cycles */
+#define BCCR_TMON_256IOCLK	0x01000000	/* - 256 IOCLK cycles */
+#define BCCR_TMON_4096IOCLK	0x02000000	/* - 4096 IOCLK cycles */
+#define BCCR_TMON_65536IOCLK	0x03000000	/* - 65536 IOCLK cycles */
+#define BCCR_TMOE		0x10000000	/* timeout detection enable */
+
+#define BCBERR			__SYSREG(0xc0002010, u32)	/* bus error source reg */
+#define BCBERR_BESB		0x0000001f	/* erroneous access destination space */
+#define BCBERR_BESB_MON		0x00000001	/* - monitor space */
+#define BCBERR_BESB_IO		0x00000002	/* - IO bus */
+#define BCBERR_BESB_EX		0x00000004	/* - EX bus */
+#define BCBERR_BESB_OPEX	0x00000008	/* - OpEX bus */
+#define BCBERR_BESB_OCM		0x00000010	/* - on chip memory */
+#define BCBERR_BERW		0x00000100	/* type of access */
+#define BCBERR_BERW_WRITE	0x00000000	/* - write */
+#define BCBERR_BERW_READ	0x00000100	/* - read */
+#define BCBERR_BESD		0x00000200	/* error detector */
+#define BCBERR_BESD_BCU		0x00000000	/* - BCU detected error */
+#define BCBERR_BESD_SLAVE_BUS	0x00000200	/* - slave bus detected error */
+#define BCBERR_BEBST		0x00000400	/* type of access */
+#define BCBERR_BEBST_SINGLE	0x00000000	/* - single */
+#define BCBERR_BEBST_BURST	0x00000400	/* - burst */
+#define BCBERR_BEME		0x00000800	/* multiple bus error flag */
+#define BCBERR_BEMR		0x00007000	/* master bus that caused the error */
+#define BCBERR_BEMR_NOERROR	0x00000000	/* - no error */
+#define BCBERR_BEMR_CI		0x00001000	/* - CPU instruction fetch bus caused error */
+#define BCBERR_BEMR_CD		0x00002000	/* - CPU data bus caused error */
+#define BCBERR_BEMR_DMA		0x00004000	/* - DMA bus caused error */
+
+#define BCBEAR			__SYSREGC(0xc0002020, u32)	/* bus error address reg */
+
+/* system bus controller registers */
+#define SBBASE(X)		__SYSREG(0xd8c00100 + (X) * 0x10, u32)	/* SBC base addr regs */
+#define SBBASE_BE		0x00000001	/* bank enable */
+#define SBBASE_BAM		0x0000fffe	/* bank address mask [31:17] */
+#define SBBASE_BBA		0xfffe0000	/* bank base address [31:17] */
+
+#define SBCNTRL0(X)		__SYSREG(0xd8c00200 + (X) * 0x10, u32)	/* SBC bank ctrl0 regs */
+#define SBCNTRL0_WEH		0x00000f00	/* write enable hold */
+#define SBCNTRL0_REH		0x0000f000	/* read enable hold */
+#define SBCNTRL0_RWH		0x000f0000	/* SRW signal hold */
+#define SBCNTRL0_CSH		0x00f00000	/* chip select hold */
+#define SBCNTRL0_DAH		0x0f000000	/* data hold */
+#define SBCNTRL0_ADH		0xf0000000	/* address hold */
+
+#define SBCNTRL1(X)		__SYSREG(0xd8c00204 + (X) * 0x10, u32)	/* SBC bank ctrl1 regs */
+#define SBCNTRL1_WED		0x00000f00	/* write enable delay */
+#define SBCNTRL1_RED		0x0000f000	/* read enable delay */
+#define SBCNTRL1_RWD		0x000f0000	/* SRW signal delay */
+#define SBCNTRL1_ASW		0x00f00000	/* address strobe width */
+#define SBCNTRL1_CSD		0x0f000000	/* chip select delay */
+#define SBCNTRL1_ASD		0xf0000000	/* address strobe delay */
+
+#define SBCNTRL2(X)		__SYSREG(0xd8c00208 + (X) * 0x10, u32)	/* SBC bank ctrl2 regs */
+#define SBCNTRL2_WC		0x000000ff	/* wait count */
+#define SBCNTRL2_BWC		0x00000f00	/* burst wait count */
+#define SBCNTRL2_WM		0x01000000	/* wait mode setting */
+#define SBCNTRL2_WM_FIXEDWAIT	0x00000000	/* - fixed wait access */
+#define SBCNTRL2_WM_HANDSHAKE	0x01000000	/* - handshake access */
+#define SBCNTRL2_BM		0x02000000	/* bus synchronisation mode */
+#define SBCNTRL2_BM_SYNC	0x00000000	/* - synchronous mode */
+#define SBCNTRL2_BM_ASYNC	0x02000000	/* - asynchronous mode */
+#define SBCNTRL2_BW		0x04000000	/* bus width */
+#define SBCNTRL2_BW_32		0x00000000	/* - 32 bits */
+#define SBCNTRL2_BW_16		0x04000000	/* - 16 bits */
+#define SBCNTRL2_RWINV		0x08000000	/* R/W signal invert polarity */
+#define SBCNTRL2_RWINV_NORM	0x00000000	/* - normal (read high) */
+#define SBCNTRL2_RWINV_INV	0x08000000	/* - inverted (read low) */
+#define SBCNTRL2_BT		0x70000000	/* bus type setting */
+#define SBCNTRL2_BT_SRAM	0x00000000	/* - SRAM interface */
+#define SBCNTRL2_BT_ADMUX	0x00000000	/* - addr/data multiplexed interface */
+#define SBCNTRL2_BT_BROM	0x00000000	/* - burst ROM interface */
+#define SBCNTRL2_BTSE		0x80000000	/* burst enable */
+
+/* memory bus controller */
+#define SDBASE(X)		__SYSREG(0xda000008 + (X) * 0x4, u32)	/* MBC base addr regs */
+#define SDBASE_CE		0x00000001	/* chip enable */
+#define SDBASE_CBAM		0x0000fff0	/* chip base address mask [31:20] */
+#define SDBASE_CBAM_SHIFT	16
+#define SDBASE_CBA		0xfff00000	/* chip base address [31:20] */
+
+#define SDRAMBUS		__SYSREG(0xda000000, u32)	/* bus mode control reg */
+#define SDRAMBUS_REFEN		0x00000004	/* refresh enable */
+#define SDRAMBUS_TRC		0x00000018	/* refresh command delay time */
+#define SDRAMBUS_BSTPT		0x00000020	/* burst stop command enable */
+#define SDRAMBUS_PONSEQ		0x00000040	/* power on sequence */
+#define SDRAMBUS_SELFREQ	0x00000080	/* self-refresh mode request */
+#define SDRAMBUS_SELFON		0x00000100	/* self-refresh mode on */
+#define SDRAMBUS_SIZE		0x00030000	/* SDRAM size */
+#define SDRAMBUS_SIZE_64Mbit	0x00010000	/* 64Mbit SDRAM (x16) */
+#define SDRAMBUS_SIZE_128Mbit	0x00020000	/* 128Mbit SDRAM (x16) */
+#define SDRAMBUS_SIZE_256Mbit	0x00030000	/* 256Mbit SDRAM (x16) */
+#define SDRAMBUS_TRASWAIT	0x000c0000	/* row address precharge command cycle number */
+#define SDRAMBUS_REFNUM		0x00300000	/* refresh command number */
+#define SDRAMBUS_BSTWAIT	0x00c00000	/* burst stop command cycle */
+#define SDRAMBUS_SETWAIT	0x03000000	/* mode register setting command cycle */
+#define SDRAMBUS_PREWAIT	0x0c000000	/* precharge command cycle */
+#define SDRAMBUS_RASLATE	0x30000000	/* RAS latency */
+#define SDRAMBUS_CASLATE	0xc0000000	/* CAS latency */
+
+#define SDREFCNT		__SYSREG(0xda000004, u32)	/* refresh period reg */
+#define SDREFCNT_PERI		0x00000fff	/* refresh period */
+
+#define SDSHDW			__SYSREG(0xda000010, u32)	/* test reg */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_BUSCTL_REGS_H */
diff --git a/arch/mn10300/include/asm/cache.h b/arch/mn10300/include/asm/cache.h
new file mode 100644
index 0000000..f29cde2
--- /dev/null
+++ b/arch/mn10300/include/asm/cache.h
@@ -0,0 +1,60 @@
+/* MN10300 cache management registers
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_CACHE_H
+#define _ASM_CACHE_H
+
+#include <asm/cpu-regs.h>
+#include <proc/cache.h>
+
+#ifndef __ASSEMBLY__
+#define L1_CACHE_DISPARITY	(L1_CACHE_NENTRIES * L1_CACHE_BYTES)
+#else
+#define L1_CACHE_DISPARITY	L1_CACHE_NENTRIES * L1_CACHE_BYTES
+#endif
+
+#define ARCH_DMA_MINALIGN	L1_CACHE_BYTES
+
+/* data cache purge registers
+ * - read from the register to unconditionally purge that cache line
+ * - write address & 0xffffff00 to conditionally purge that cache line
+ *   - clear LSB to request invalidation as well
+ */
+#define DCACHE_PURGE(WAY, ENTRY) \
+	__SYSREG(0xc8400000 + (WAY) * L1_CACHE_WAYDISP + \
+		 (ENTRY) * L1_CACHE_BYTES, u32)
+
+#define DCACHE_PURGE_WAY0(ENTRY) \
+	__SYSREG(0xc8400000 + 0 * L1_CACHE_WAYDISP + (ENTRY) * L1_CACHE_BYTES, u32)
+#define DCACHE_PURGE_WAY1(ENTRY) \
+	__SYSREG(0xc8400000 + 1 * L1_CACHE_WAYDISP + (ENTRY) * L1_CACHE_BYTES, u32)
+#define DCACHE_PURGE_WAY2(ENTRY) \
+	__SYSREG(0xc8400000 + 2 * L1_CACHE_WAYDISP + (ENTRY) * L1_CACHE_BYTES, u32)
+#define DCACHE_PURGE_WAY3(ENTRY) \
+	__SYSREG(0xc8400000 + 3 * L1_CACHE_WAYDISP + (ENTRY) * L1_CACHE_BYTES, u32)
+
+/* instruction cache access registers */
+#define ICACHE_DATA(WAY, ENTRY, OFF) \
+	__SYSREG(0xc8000000 + (WAY) * L1_CACHE_WAYDISP + \
+		(ENTRY) * L1_CACHE_BYTES + (OFF) * 4, u32)
+#define ICACHE_TAG(WAY, ENTRY)	 \
+	__SYSREG(0xc8100000 + (WAY) * L1_CACHE_WAYDISP + \
+		(ENTRY) * L1_CACHE_BYTES, u32)
+
+/* data cache access registers */
+#define DCACHE_DATA(WAY, ENTRY, OFF) \
+	__SYSREG(0xc8200000 + (WAY) * L1_CACHE_WAYDISP + \
+		(ENTRY) * L1_CACHE_BYTES + (OFF) * 4, u32)
+#define DCACHE_TAG(WAY, ENTRY)	 \
+	__SYSREG(0xc8300000 + (WAY) * L1_CACHE_WAYDISP + \
+		(ENTRY) * L1_CACHE_BYTES, u32)
+
+#endif /* _ASM_CACHE_H */
diff --git a/arch/mn10300/include/asm/cacheflush.h b/arch/mn10300/include/asm/cacheflush.h
new file mode 100644
index 0000000..6d6df83
--- /dev/null
+++ b/arch/mn10300/include/asm/cacheflush.h
@@ -0,0 +1,164 @@
+/* MN10300 Cache flushing
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_CACHEFLUSH_H
+#define _ASM_CACHEFLUSH_H
+
+#ifndef __ASSEMBLY__
+
+/* Keep includes the same across arches.  */
+#include <linux/mm.h>
+
+/*
+ * Primitive routines
+ */
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+extern void mn10300_local_icache_inv(void);
+extern void mn10300_local_icache_inv_page(unsigned long start);
+extern void mn10300_local_icache_inv_range(unsigned long start, unsigned long end);
+extern void mn10300_local_icache_inv_range2(unsigned long start, unsigned long size);
+extern void mn10300_local_dcache_inv(void);
+extern void mn10300_local_dcache_inv_page(unsigned long start);
+extern void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end);
+extern void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size);
+extern void mn10300_icache_inv(void);
+extern void mn10300_icache_inv_page(unsigned long start);
+extern void mn10300_icache_inv_range(unsigned long start, unsigned long end);
+extern void mn10300_icache_inv_range2(unsigned long start, unsigned long size);
+extern void mn10300_dcache_inv(void);
+extern void mn10300_dcache_inv_page(unsigned long start);
+extern void mn10300_dcache_inv_range(unsigned long start, unsigned long end);
+extern void mn10300_dcache_inv_range2(unsigned long start, unsigned long size);
+#ifdef CONFIG_MN10300_CACHE_WBACK
+extern void mn10300_local_dcache_flush(void);
+extern void mn10300_local_dcache_flush_page(unsigned long start);
+extern void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end);
+extern void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size);
+extern void mn10300_local_dcache_flush_inv(void);
+extern void mn10300_local_dcache_flush_inv_page(unsigned long start);
+extern void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end);
+extern void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size);
+extern void mn10300_dcache_flush(void);
+extern void mn10300_dcache_flush_page(unsigned long start);
+extern void mn10300_dcache_flush_range(unsigned long start, unsigned long end);
+extern void mn10300_dcache_flush_range2(unsigned long start, unsigned long size);
+extern void mn10300_dcache_flush_inv(void);
+extern void mn10300_dcache_flush_inv_page(unsigned long start);
+extern void mn10300_dcache_flush_inv_range(unsigned long start, unsigned long end);
+extern void mn10300_dcache_flush_inv_range2(unsigned long start, unsigned long size);
+#else
+#define mn10300_local_dcache_flush()			do {} while (0)
+#define mn10300_local_dcache_flush_page(start)		do {} while (0)
+#define mn10300_local_dcache_flush_range(start, end)	do {} while (0)
+#define mn10300_local_dcache_flush_range2(start, size)	do {} while (0)
+#define mn10300_local_dcache_flush_inv() \
+		mn10300_local_dcache_inv()
+#define mn10300_local_dcache_flush_inv_page(start) \
+		mn10300_local_dcache_inv_page(start)
+#define mn10300_local_dcache_flush_inv_range(start, end) \
+		mn10300_local_dcache_inv_range(start, end)
+#define mn10300_local_dcache_flush_inv_range2(start, size) \
+		mn10300_local_dcache_inv_range2(start, size)
+#define mn10300_dcache_flush()				do {} while (0)
+#define mn10300_dcache_flush_page(start)		do {} while (0)
+#define mn10300_dcache_flush_range(start, end)		do {} while (0)
+#define mn10300_dcache_flush_range2(start, size)	do {} while (0)
+#define mn10300_dcache_flush_inv()			mn10300_dcache_inv()
+#define mn10300_dcache_flush_inv_page(start) \
+	mn10300_dcache_inv_page((start))
+#define mn10300_dcache_flush_inv_range(start, end) \
+	mn10300_dcache_inv_range((start), (end))
+#define mn10300_dcache_flush_inv_range2(start, size) \
+	mn10300_dcache_inv_range2((start), (size))
+#endif /* CONFIG_MN10300_CACHE_WBACK */
+#else
+#define mn10300_local_icache_inv()			do {} while (0)
+#define mn10300_local_icache_inv_page(start)		do {} while (0)
+#define mn10300_local_icache_inv_range(start, end)	do {} while (0)
+#define mn10300_local_icache_inv_range2(start, size)	do {} while (0)
+#define mn10300_local_dcache_inv()			do {} while (0)
+#define mn10300_local_dcache_inv_page(start)		do {} while (0)
+#define mn10300_local_dcache_inv_range(start, end)	do {} while (0)
+#define mn10300_local_dcache_inv_range2(start, size)	do {} while (0)
+#define mn10300_local_dcache_flush()			do {} while (0)
+#define mn10300_local_dcache_flush_inv_page(start)	do {} while (0)
+#define mn10300_local_dcache_flush_inv()		do {} while (0)
+#define mn10300_local_dcache_flush_inv_range(start, end)do {} while (0)
+#define mn10300_local_dcache_flush_inv_range2(start, size) do {} while (0)
+#define mn10300_local_dcache_flush_page(start)		do {} while (0)
+#define mn10300_local_dcache_flush_range(start, end)	do {} while (0)
+#define mn10300_local_dcache_flush_range2(start, size)	do {} while (0)
+#define mn10300_icache_inv()				do {} while (0)
+#define mn10300_icache_inv_page(start)			do {} while (0)
+#define mn10300_icache_inv_range(start, end)		do {} while (0)
+#define mn10300_icache_inv_range2(start, size)		do {} while (0)
+#define mn10300_dcache_inv()				do {} while (0)
+#define mn10300_dcache_inv_page(start)			do {} while (0)
+#define mn10300_dcache_inv_range(start, end)		do {} while (0)
+#define mn10300_dcache_inv_range2(start, size)		do {} while (0)
+#define mn10300_dcache_flush()				do {} while (0)
+#define mn10300_dcache_flush_inv_page(start)		do {} while (0)
+#define mn10300_dcache_flush_inv()			do {} while (0)
+#define mn10300_dcache_flush_inv_range(start, end)	do {} while (0)
+#define mn10300_dcache_flush_inv_range2(start, size)	do {} while (0)
+#define mn10300_dcache_flush_page(start)		do {} while (0)
+#define mn10300_dcache_flush_range(start, end)		do {} while (0)
+#define mn10300_dcache_flush_range2(start, size)	do {} while (0)
+#endif /* CONFIG_MN10300_CACHE_ENABLED */
+
+/*
+ * Virtually-indexed cache management (our cache is physically indexed)
+ */
+#define flush_cache_all()			do {} while (0)
+#define flush_cache_mm(mm)			do {} while (0)
+#define flush_cache_dup_mm(mm)			do {} while (0)
+#define flush_cache_range(mm, start, end)	do {} while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do {} while (0)
+#define flush_cache_vmap(start, end)		do {} while (0)
+#define flush_cache_vunmap(start, end)		do {} while (0)
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
+#define flush_dcache_page(page)			do {} while (0)
+#define flush_dcache_mmap_lock(mapping)		do {} while (0)
+#define flush_dcache_mmap_unlock(mapping)	do {} while (0)
+
+/*
+ * Physically-indexed cache management
+ */
+#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE)
+extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
+extern void flush_icache_range(unsigned long start, unsigned long end);
+#elif defined(CONFIG_MN10300_CACHE_INV_ICACHE)
+static inline void flush_icache_page(struct vm_area_struct *vma,
+				     struct page *page)
+{
+	mn10300_icache_inv_page(page_to_phys(page));
+}
+extern void flush_icache_range(unsigned long start, unsigned long end);
+#else
+#define flush_icache_range(start, end)		do {} while (0)
+#define flush_icache_page(vma, pg)		do {} while (0)
+#endif
+
+
+#define flush_icache_user_range(vma, pg, adr, len) \
+	flush_icache_range(adr, adr + len)
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+	do {					\
+		memcpy(dst, src, len);		\
+		flush_icache_page(vma, page);	\
+	} while (0)
+
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+	memcpy(dst, src, len)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_CACHEFLUSH_H */
diff --git a/arch/mn10300/include/asm/checksum.h b/arch/mn10300/include/asm/checksum.h
new file mode 100644
index 0000000..9fb2a8d
--- /dev/null
+++ b/arch/mn10300/include/asm/checksum.h
@@ -0,0 +1,86 @@
+/* MN10300 Optimised checksumming code
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_CHECKSUM_H
+#define _ASM_CHECKSUM_H
+
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+extern __wsum csum_partial_copy_nocheck(const void *src, void *dst,
+					int len, __wsum sum);
+extern __wsum csum_partial_copy_from_user(const void *src, void *dst,
+					  int len, __wsum sum,
+					  int *err_ptr);
+extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+extern __sum16 ip_compute_csum(const void *buff, int len);
+
+#define csum_partial_copy_fromuser csum_partial_copy
+extern __wsum csum_partial_copy(const void *src, void *dst, int len,
+				__wsum sum);
+
+static inline __sum16 csum_fold(__wsum sum)
+{
+	asm(
+		"	add	%1,%0		\n"
+		"	addc	0xffff,%0	\n"
+		: "=r" (sum)
+		: "r" (sum << 16), "0" (sum & 0xffff0000)
+		: "cc"
+	    );
+	return (~sum) >> 16;
+}
+
+static inline __wsum csum_tcpudp_nofold(unsigned long saddr,
+					unsigned long daddr,
+					unsigned short len,
+					unsigned short proto,
+					__wsum sum)
+{
+	__wsum tmp;
+
+	tmp = (__wsum) ntohs(len) << 16;
+	tmp += (__wsum) proto << 8;
+
+	asm(
+		"	add	%1,%0		\n"
+		"	addc	%2,%0		\n"
+		"	addc	%3,%0		\n"
+		"	addc	0,%0		\n"
+		: "=r" (sum)
+		: "r" (daddr), "r"(saddr), "r"(tmp), "0"(sum)
+		: "cc"
+	    );
+	return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(unsigned long saddr,
+					unsigned long daddr,
+					unsigned short len,
+					unsigned short proto,
+					__wsum sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+}
+
+#undef _HAVE_ARCH_IPV6_CSUM
+
+/*
+ *	Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+extern __wsum csum_and_copy_to_user(const void *src, void *dst, int len,
+				    __wsum sum, int *err_ptr);
+
+
+#endif /* _ASM_CHECKSUM_H */
diff --git a/arch/mn10300/include/asm/cmpxchg.h b/arch/mn10300/include/asm/cmpxchg.h
new file mode 100644
index 0000000..97a4aaf
--- /dev/null
+++ b/arch/mn10300/include/asm/cmpxchg.h
@@ -0,0 +1,115 @@
+/* MN10300 Atomic xchg/cmpxchg operations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_CMPXCHG_H
+#define _ASM_CMPXCHG_H
+
+#include <asm/irqflags.h>
+
+#ifdef CONFIG_SMP
+#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
+static inline
+unsigned long __xchg(volatile unsigned long *m, unsigned long val)
+{
+	unsigned long status;
+	unsigned long oldval;
+
+	asm volatile(
+		"1:	mov	%4,(_AAR,%3)	\n"
+		"	mov	(_ADR,%3),%1	\n"
+		"	mov	%5,(_ADR,%3)	\n"
+		"	mov	(_ADR,%3),%0	\n"	/* flush */
+		"	mov	(_ASR,%3),%0	\n"
+		"	or	%0,%0		\n"
+		"	bne	1b		\n"
+		: "=&r"(status), "=&r"(oldval), "=m"(*m)
+		: "a"(ATOMIC_OPS_BASE_ADDR), "r"(m), "r"(val)
+		: "memory", "cc");
+
+	return oldval;
+}
+
+static inline unsigned long __cmpxchg(volatile unsigned long *m,
+				      unsigned long old, unsigned long new)
+{
+	unsigned long status;
+	unsigned long oldval;
+
+	asm volatile(
+		"1:	mov	%4,(_AAR,%3)	\n"
+		"	mov	(_ADR,%3),%1	\n"
+		"	cmp	%5,%1		\n"
+		"	bne	2f		\n"
+		"	mov	%6,(_ADR,%3)	\n"
+		"2:	mov	(_ADR,%3),%0	\n"	/* flush */
+		"	mov	(_ASR,%3),%0	\n"
+		"	or	%0,%0		\n"
+		"	bne	1b		\n"
+		: "=&r"(status), "=&r"(oldval), "=m"(*m)
+		: "a"(ATOMIC_OPS_BASE_ADDR), "r"(m),
+		  "r"(old), "r"(new)
+		: "memory", "cc");
+
+	return oldval;
+}
+#else  /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
+#error "No SMP atomic operation support!"
+#endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
+
+#else  /* CONFIG_SMP */
+
+/*
+ * Emulate xchg for non-SMP MN10300
+ */
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+static inline
+unsigned long __xchg(volatile unsigned long *m, unsigned long val)
+{
+	unsigned long oldval;
+	unsigned long flags;
+
+	flags = arch_local_cli_save();
+	oldval = *m;
+	*m = val;
+	arch_local_irq_restore(flags);
+	return oldval;
+}
+
+/*
+ * Emulate cmpxchg for non-SMP MN10300
+ */
+static inline unsigned long __cmpxchg(volatile unsigned long *m,
+				      unsigned long old, unsigned long new)
+{
+	unsigned long oldval;
+	unsigned long flags;
+
+	flags = arch_local_cli_save();
+	oldval = *m;
+	if (oldval == old)
+		*m = new;
+	arch_local_irq_restore(flags);
+	return oldval;
+}
+
+#endif /* CONFIG_SMP */
+
+#define xchg(ptr, v)						\
+	((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),	\
+				     (unsigned long)(v)))
+
+#define cmpxchg(ptr, o, n)					\
+	((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
+					(unsigned long)(o),	\
+					(unsigned long)(n)))
+
+#endif /* _ASM_CMPXCHG_H */
diff --git a/arch/mn10300/include/asm/cpu-regs.h b/arch/mn10300/include/asm/cpu-regs.h
new file mode 100644
index 0000000..c54effa
--- /dev/null
+++ b/arch/mn10300/include/asm/cpu-regs.h
@@ -0,0 +1,353 @@
+/* MN10300 Core system registers
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_CPU_REGS_H
+#define _ASM_CPU_REGS_H
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#endif
+
+/* we tell the compiler to pretend to be AM33 so that it doesn't try and use
+ * the FP regs, but tell the assembler that we're actually allowed AM33v2
+ * instructions */
+#ifndef __ASSEMBLY__
+asm(" .am33_2\n");
+#else
+.am33_2
+#endif
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#define __SYSREG(ADDR, TYPE) (*(volatile TYPE *)(ADDR))
+#define __SYSREGC(ADDR, TYPE) (*(const volatile TYPE *)(ADDR))
+#else
+#define __SYSREG(ADDR, TYPE) ADDR
+#define __SYSREGC(ADDR, TYPE) ADDR
+#endif
+
+/* CPU registers */
+#define EPSW_FLAG_Z		0x00000001	/* zero flag */
+#define EPSW_FLAG_N		0x00000002	/* negative flag */
+#define EPSW_FLAG_C		0x00000004	/* carry flag */
+#define EPSW_FLAG_V		0x00000008	/* overflow flag */
+#define EPSW_IM			0x00000700	/* interrupt mode */
+#define EPSW_IM_0		0x00000000	/* interrupt mode 0 */
+#define EPSW_IM_1		0x00000100	/* interrupt mode 1 */
+#define EPSW_IM_2		0x00000200	/* interrupt mode 2 */
+#define EPSW_IM_3		0x00000300	/* interrupt mode 3 */
+#define EPSW_IM_4		0x00000400	/* interrupt mode 4 */
+#define EPSW_IM_5		0x00000500	/* interrupt mode 5 */
+#define EPSW_IM_6		0x00000600	/* interrupt mode 6 */
+#define EPSW_IM_7		0x00000700	/* interrupt mode 7 */
+#define EPSW_IE			0x00000800	/* interrupt enable */
+#define EPSW_S			0x00003000	/* software auxiliary bits */
+#define EPSW_T			0x00008000	/* trace enable */
+#define EPSW_nSL		0x00010000	/* not supervisor level */
+#define EPSW_NMID		0x00020000	/* nonmaskable interrupt disable */
+#define EPSW_nAR		0x00040000	/* register bank control */
+#define EPSW_ML			0x00080000	/* monitor level */
+#define EPSW_FE			0x00100000	/* FPU enable */
+#define EPSW_IM_SHIFT		8		/* EPSW_IM_SHIFT determines the interrupt mode */
+
+#define NUM2EPSW_IM(num)	((num) << EPSW_IM_SHIFT)
+
+/* FPU registers */
+#define FPCR_EF_I		0x00000001	/* inexact result FPU exception flag */
+#define FPCR_EF_U		0x00000002	/* underflow FPU exception flag */
+#define FPCR_EF_O		0x00000004	/* overflow FPU exception flag */
+#define FPCR_EF_Z		0x00000008	/* zero divide FPU exception flag */
+#define FPCR_EF_V		0x00000010	/* invalid operand FPU exception flag */
+#define FPCR_EE_I		0x00000020	/* inexact result FPU exception enable */
+#define FPCR_EE_U		0x00000040	/* underflow FPU exception enable */
+#define FPCR_EE_O		0x00000080	/* overflow FPU exception enable */
+#define FPCR_EE_Z		0x00000100	/* zero divide FPU exception enable */
+#define FPCR_EE_V		0x00000200	/* invalid operand FPU exception enable */
+#define FPCR_EC_I		0x00000400	/* inexact result FPU exception cause */
+#define FPCR_EC_U		0x00000800	/* underflow FPU exception cause */
+#define FPCR_EC_O		0x00001000	/* overflow FPU exception cause */
+#define FPCR_EC_Z		0x00002000	/* zero divide FPU exception cause */
+#define FPCR_EC_V		0x00004000	/* invalid operand FPU exception cause */
+#define FPCR_RM			0x00030000	/* rounding mode */
+#define FPCR_RM_NEAREST		0x00000000	/* - round to nearest value */
+#define FPCR_FCC_U		0x00040000	/* FPU unordered condition code */
+#define FPCR_FCC_E		0x00080000	/* FPU equal condition code */
+#define FPCR_FCC_G		0x00100000	/* FPU greater than condition code */
+#define FPCR_FCC_L		0x00200000	/* FPU less than condition code */
+#define FPCR_INIT		0x00000000	/* no exceptions, rounding to nearest */
+
+/* CPU control registers */
+#define CPUP			__SYSREG(0xc0000020, u16)	/* CPU pipeline register */
+#define CPUP_DWBD		0x0020		/* write buffer disable flag */
+#define CPUP_IPFD		0x0040		/* instruction prefetch disable flag */
+#define CPUP_EXM		0x0080		/* exception operation mode */
+#define CPUP_EXM_AM33V1		0x0000		/* - AM33 v1 exception mode */
+#define CPUP_EXM_AM33V2		0x0080		/* - AM33 v2 exception mode */
+
+#define CPUM			__SYSREG(0xc0000040, u16)	/* CPU mode register */
+#define CPUM_SLEEP		0x0004		/* set to enter sleep state */
+#define CPUM_HALT		0x0008		/* set to enter halt state */
+#define CPUM_STOP		0x0010		/* set to enter stop state */
+
+#define CPUREV			__SYSREGC(0xc0000050, u32)	/* CPU revision register */
+#define CPUREV_TYPE		0x0000000f	/* CPU type */
+#define CPUREV_TYPE_S		0
+#define CPUREV_TYPE_AM33_1	0x00000000	/* - AM33-1 core, AM33/1.00 arch */
+#define CPUREV_TYPE_AM33_2	0x00000001	/* - AM33-2 core, AM33/2.00 arch */
+#define CPUREV_TYPE_AM34_1	0x00000002	/* - AM34-1 core, AM33/2.00 arch */
+#define CPUREV_TYPE_AM33_3	0x00000003	/* - AM33-3 core, AM33/2.00 arch */
+#define CPUREV_TYPE_AM34_2	0x00000004	/* - AM34-2 core, AM33/3.00 arch */
+#define CPUREV_REVISION		0x000000f0	/* CPU revision */
+#define CPUREV_REVISION_S	4
+#define CPUREV_ICWAY		0x00000f00	/* number of instruction cache ways */
+#define CPUREV_ICWAY_S		8
+#define CPUREV_ICSIZE		0x0000f000	/* instruction cache way size */
+#define CPUREV_ICSIZE_S		12
+#define CPUREV_DCWAY		0x000f0000	/* number of data cache ways */
+#define CPUREV_DCWAY_S		16
+#define CPUREV_DCSIZE		0x00f00000	/* data cache way size */
+#define CPUREV_DCSIZE_S		20
+#define CPUREV_FPUTYPE		0x0f000000	/* FPU core type */
+#define CPUREV_FPUTYPE_NONE	0x00000000	/* - no FPU core implemented */
+#define CPUREV_OCDCTG		0xf0000000	/* on-chip debug function category */
+
+#define DCR			__SYSREG(0xc0000030, u16)	/* Debug control register */
+
+/* interrupt/exception control registers */
+#define IVAR0			__SYSREG(0xc0000000, u16)	/* interrupt vector 0 */
+#define IVAR1			__SYSREG(0xc0000004, u16)	/* interrupt vector 1 */
+#define IVAR2			__SYSREG(0xc0000008, u16)	/* interrupt vector 2 */
+#define IVAR3			__SYSREG(0xc000000c, u16)	/* interrupt vector 3 */
+#define IVAR4			__SYSREG(0xc0000010, u16)	/* interrupt vector 4 */
+#define IVAR5			__SYSREG(0xc0000014, u16)	/* interrupt vector 5 */
+#define IVAR6			__SYSREG(0xc0000018, u16)	/* interrupt vector 6 */
+
+#define TBR			__SYSREG(0xc0000024, u32)	/* Trap table base */
+#define TBR_TB			0xff000000	/* table base address bits 31-24 */
+#define TBR_INT_CODE		0x00ffffff	/* interrupt code */
+
+#define DEAR			__SYSREG(0xc0000038, u32)	/* Data access exception address */
+
+#define sISR			__SYSREG(0xc0000044, u32)	/* Supervisor interrupt status */
+#define	sISR_IRQICE		0x00000001	/* ICE interrupt */
+#define	sISR_ISTEP		0x00000002	/* single step interrupt */
+#define	sISR_MISSA		0x00000004	/* memory access address misalignment fault */
+#define	sISR_UNIMP		0x00000008	/* unimplemented instruction execution fault */
+#define	sISR_PIEXE		0x00000010	/* program interrupt */
+#define	sISR_MEMERR		0x00000020	/* illegal memory access fault */
+#define	sISR_IBREAK		0x00000040	/* instraction break interrupt */
+#define	sISR_DBSRL		0x00000080	/* debug serial interrupt */
+#define	sISR_PERIDB		0x00000100	/* peripheral debug interrupt */
+#define	sISR_EXUNIMP		0x00000200	/* unimplemented ex-instruction execution fault */
+#define	sISR_OBREAK		0x00000400	/* operand break interrupt */
+#define	sISR_PRIV		0x00000800	/* privileged instruction execution fault */
+#define	sISR_BUSERR		0x00001000	/* bus error fault */
+#define	sISR_DBLFT		0x00002000	/* double fault */
+#define	sISR_DBG		0x00008000	/* debug reserved interrupt */
+#define sISR_ITMISS		0x00010000	/* instruction TLB miss */
+#define sISR_DTMISS		0x00020000	/* data TLB miss */
+#define sISR_ITEX		0x00040000	/* instruction TLB access exception */
+#define sISR_DTEX		0x00080000	/* data TLB access exception */
+#define sISR_ILGIA		0x00100000	/* illegal instruction access exception */
+#define sISR_ILGDA		0x00200000	/* illegal data access exception */
+#define sISR_IOIA		0x00400000	/* internal I/O space instruction access excep */
+#define sISR_PRIVA		0x00800000	/* privileged space instruction access excep */
+#define sISR_PRIDA		0x01000000	/* privileged space data access excep */
+#define sISR_DISA		0x02000000	/* data space instruction access excep */
+#define sISR_SYSC		0x04000000	/* system call instruction excep */
+#define sISR_FPUD		0x08000000	/* FPU disabled excep */
+#define sISR_FPUUI		0x10000000	/* FPU unimplemented instruction excep */
+#define sISR_FPUOP		0x20000000	/* FPU operation excep */
+#define sISR_NE			0x80000000	/* multiple synchronous exceptions excep */
+
+/* cache control registers */
+#define CHCTR			__SYSREG(0xc0000070, u16)	/* cache control */
+#define CHCTR_ICEN		0x0001		/* instruction cache enable */
+#define CHCTR_DCEN		0x0002		/* data cache enable */
+#define CHCTR_ICBUSY		0x0004		/* instruction cache busy */
+#define CHCTR_DCBUSY		0x0008		/* data cache busy */
+#define CHCTR_ICINV		0x0010		/* instruction cache invalidate */
+#define CHCTR_DCINV		0x0020		/* data cache invalidate */
+#define CHCTR_DCWTMD		0x0040		/* data cache writing mode */
+#define CHCTR_DCWTMD_WRBACK	0x0000		/* - write back mode */
+#define CHCTR_DCWTMD_WRTHROUGH	0x0040		/* - write through mode */
+#define CHCTR_DCALMD		0x0080		/* data cache allocation mode */
+#define CHCTR_ICWMD		0x0f00		/* instruction cache way mode */
+#define CHCTR_DCWMD		0xf000		/* data cache way mode */
+
+#ifdef CONFIG_AM34_2
+#define ICIVCR			__SYSREG(0xc0000c00, u32)	/* icache area invalidate control */
+#define ICIVCR_ICIVBSY		0x00000008			/* icache area invalidate busy */
+#define ICIVCR_ICI		0x00000001			/* icache area invalidate */
+
+#define ICIVMR			__SYSREG(0xc0000c04, u32)	/* icache area invalidate mask */
+
+#define	DCPGCR			__SYSREG(0xc0000c10, u32)	/* data cache area purge control */
+#define	DCPGCR_DCPGBSY		0x00000008			/* data cache area purge busy */
+#define	DCPGCR_DCP		0x00000002			/* data cache area purge */
+#define	DCPGCR_DCI		0x00000001			/* data cache area invalidate */
+
+#define	DCPGMR			__SYSREG(0xc0000c14, u32)	/* data cache area purge mask */
+#endif /* CONFIG_AM34_2 */
+
+/* MMU control registers */
+#define MMUCTR			__SYSREG(0xc0000090, u32)	/* MMU control register */
+#define MMUCTR_IRP		0x0000003f	/* instruction TLB replace pointer */
+#define MMUCTR_ITE		0x00000040	/* instruction TLB enable */
+#define MMUCTR_IIV		0x00000080	/* instruction TLB invalidate */
+#define MMUCTR_ITL		0x00000700	/* instruction TLB lock pointer */
+#define MMUCTR_ITL_NOLOCK	0x00000000	/* - no lock */
+#define MMUCTR_ITL_LOCK0	0x00000100	/* - entry 0 locked */
+#define MMUCTR_ITL_LOCK0_1	0x00000200	/* - entry 0-1 locked */
+#define MMUCTR_ITL_LOCK0_3	0x00000300	/* - entry 0-3 locked */
+#define MMUCTR_ITL_LOCK0_7	0x00000400	/* - entry 0-7 locked */
+#define MMUCTR_ITL_LOCK0_15	0x00000500	/* - entry 0-15 locked */
+#define MMUCTR_CE		0x00008000	/* cacheable bit enable */
+#define MMUCTR_DRP		0x003f0000	/* data TLB replace pointer */
+#define MMUCTR_DTE		0x00400000	/* data TLB enable */
+#define MMUCTR_DIV		0x00800000	/* data TLB invalidate */
+#define MMUCTR_DTL		0x07000000	/* data TLB lock pointer */
+#define MMUCTR_DTL_NOLOCK	0x00000000	/* - no lock */
+#define MMUCTR_DTL_LOCK0	0x01000000	/* - entry 0 locked */
+#define MMUCTR_DTL_LOCK0_1	0x02000000	/* - entry 0-1 locked */
+#define MMUCTR_DTL_LOCK0_3	0x03000000	/* - entry 0-3 locked */
+#define MMUCTR_DTL_LOCK0_7	0x04000000	/* - entry 0-7 locked */
+#define MMUCTR_DTL_LOCK0_15	0x05000000	/* - entry 0-15 locked */
+#ifdef CONFIG_AM34_2
+#define MMUCTR_WTE		0x80000000	/* write-through cache TLB entry bit enable */
+#endif
+
+#define PIDR			__SYSREG(0xc0000094, u16)	/* PID register */
+#define PIDR_PID		0x00ff		/* process identifier */
+
+#define PTBR			__SYSREG(0xc0000098, unsigned long) /* Page table base register */
+
+#define IPTEL			__SYSREG(0xc00000a0, u32)	/* instruction TLB entry */
+#define DPTEL			__SYSREG(0xc00000b0, u32)	/* data TLB entry */
+#define xPTEL_V			0x00000001	/* TLB entry valid */
+#define xPTEL_UNUSED1		0x00000002	/* unused bit */
+#define xPTEL_UNUSED2		0x00000004	/* unused bit */
+#define xPTEL_C			0x00000008	/* cached if set */
+#define xPTEL_PV		0x00000010	/* page valid */
+#define xPTEL_D			0x00000020	/* dirty */
+#define xPTEL_PR		0x000001c0	/* page protection */
+#define xPTEL_PR_ROK		0x00000000	/* - R/O kernel */
+#define xPTEL_PR_RWK		0x00000100	/* - R/W kernel */
+#define xPTEL_PR_ROK_ROU	0x00000080	/* - R/O kernel and R/O user */
+#define xPTEL_PR_RWK_ROU	0x00000180	/* - R/W kernel and R/O user */
+#define xPTEL_PR_RWK_RWU	0x000001c0	/* - R/W kernel and R/W user */
+#define xPTEL_G			0x00000200	/* global (use PID if 0) */
+#define xPTEL_PS		0x00000c00	/* page size */
+#define xPTEL_PS_4Kb		0x00000000	/* - 4Kb page */
+#define xPTEL_PS_128Kb		0x00000400	/* - 128Kb page */
+#define xPTEL_PS_1Kb		0x00000800	/* - 1Kb page */
+#define xPTEL_PS_4Mb		0x00000c00	/* - 4Mb page */
+#define xPTEL_PPN		0xfffff006	/* physical page number */
+
+#define IPTEU			__SYSREG(0xc00000a4, u32)	/* instruction TLB virtual addr */
+#define DPTEU			__SYSREG(0xc00000b4, u32)	/* data TLB virtual addr */
+#define xPTEU_VPN		0xfffffc00	/* virtual page number */
+#define xPTEU_PID		0x000000ff	/* process identifier to which applicable */
+
+#define IPTEL2			__SYSREG(0xc00000a8, u32)	/* instruction TLB entry */
+#define DPTEL2			__SYSREG(0xc00000b8, u32)	/* data TLB entry */
+#define xPTEL2_V		0x00000001	/* TLB entry valid */
+#define xPTEL2_C		0x00000002	/* cacheable */
+#define xPTEL2_PV		0x00000004	/* page valid */
+#define xPTEL2_D		0x00000008	/* dirty */
+#define xPTEL2_PR		0x00000070	/* page protection */
+#define xPTEL2_PR_ROK		0x00000000	/* - R/O kernel */
+#define xPTEL2_PR_RWK		0x00000040	/* - R/W kernel */
+#define xPTEL2_PR_ROK_ROU	0x00000020	/* - R/O kernel and R/O user */
+#define xPTEL2_PR_RWK_ROU	0x00000060	/* - R/W kernel and R/O user */
+#define xPTEL2_PR_RWK_RWU	0x00000070	/* - R/W kernel and R/W user */
+#define xPTEL2_G		0x00000080	/* global (use PID if 0) */
+#define xPTEL2_PS		0x00000300	/* page size */
+#define xPTEL2_PS_4Kb		0x00000000	/* - 4Kb page */
+#define xPTEL2_PS_128Kb		0x00000100	/* - 128Kb page */
+#define xPTEL2_PS_1Kb		0x00000200	/* - 1Kb page */
+#define xPTEL2_PS_4Mb		0x00000300	/* - 4Mb page */
+#define xPTEL2_CWT		0x00000400	/* cacheable write-through */
+#define xPTEL2_UNUSED1		0x00000800	/* unused bit (broadcast mask) */
+#define xPTEL2_PPN		0xfffff000	/* physical page number */
+
+#define xPTEL2_V_BIT		0	/* bit numbers corresponding to above masks */
+#define xPTEL2_C_BIT		1
+#define xPTEL2_PV_BIT		2
+#define xPTEL2_D_BIT		3
+#define xPTEL2_G_BIT		7
+#define xPTEL2_UNUSED1_BIT	11
+
+#define MMUFCR			__SYSREGC(0xc000009c, u32)	/* MMU exception cause */
+#define MMUFCR_IFC		__SYSREGC(0xc000009c, u16)	/* MMU instruction excep cause */
+#define MMUFCR_DFC		__SYSREGC(0xc000009e, u16)	/* MMU data exception cause */
+#define MMUFCR_xFC_TLBMISS	0x0001		/* TLB miss flag */
+#define MMUFCR_xFC_INITWR	0x0002		/* initial write excep flag */
+#define MMUFCR_xFC_PGINVAL	0x0004		/* page invalid excep flag */
+#define MMUFCR_xFC_PROTVIOL	0x0008		/* protection violation excep flag */
+#define MMUFCR_xFC_ACCESS	0x0010		/* access level flag */
+#define MMUFCR_xFC_ACCESS_USR	0x0000		/* - user mode */
+#define MMUFCR_xFC_ACCESS_SR	0x0010		/* - supervisor mode */
+#define MMUFCR_xFC_TYPE		0x0020		/* access type flag */
+#define MMUFCR_xFC_TYPE_READ	0x0000		/* - read */
+#define MMUFCR_xFC_TYPE_WRITE	0x0020		/* - write */
+#define MMUFCR_xFC_PR		0x01c0		/* page protection flag */
+#define MMUFCR_xFC_PR_ROK	0x0000		/* - R/O kernel */
+#define MMUFCR_xFC_PR_RWK	0x0100		/* - R/W kernel */
+#define MMUFCR_xFC_PR_ROK_ROU	0x0080		/* - R/O kernel and R/O user */
+#define MMUFCR_xFC_PR_RWK_ROU	0x0180		/* - R/W kernel and R/O user */
+#define MMUFCR_xFC_PR_RWK_RWU	0x01c0		/* - R/W kernel and R/W user */
+#define MMUFCR_xFC_ILLADDR	0x0200		/* illegal address excep flag */
+
+#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
+/* atomic operation registers */
+#define AAR		__SYSREG(0xc0000a00, u32)	/* cacheable address */
+#define AAR2		__SYSREG(0xc0000a04, u32)	/* uncacheable address */
+#define ADR		__SYSREG(0xc0000a08, u32)	/* data */
+#define ASR		__SYSREG(0xc0000a0c, u32)	/* status */
+#define AARU		__SYSREG(0xd400aa00, u32)	/* user address */
+#define ADRU		__SYSREG(0xd400aa08, u32)	/* user data */
+#define ASRU		__SYSREG(0xd400aa0c, u32)	/* user status */
+
+#define ASR_RW		0x00000008	/* read */
+#define ASR_BW		0x00000004	/* bus error */
+#define ASR_IW		0x00000002	/* interrupt */
+#define ASR_LW		0x00000001	/* bus lock */
+
+#define ASRU_RW		ASR_RW		/* read */
+#define ASRU_BW		ASR_BW		/* bus error */
+#define ASRU_IW		ASR_IW		/* interrupt */
+#define ASRU_LW		ASR_LW		/* bus lock */
+
+/* in inline ASM, we stick the base pointer in to a reg and use offsets from
+ * it */
+#define ATOMIC_OPS_BASE_ADDR 0xc0000a00
+#ifndef __ASSEMBLY__
+asm(
+	"_AAR	= 0\n"
+	"_AAR2	= 4\n"
+	"_ADR	= 8\n"
+	"_ASR	= 12\n");
+#else
+#define _AAR		0
+#define _AAR2		4
+#define _ADR		8
+#define _ASR		12
+#endif
+
+/* physical page address for userspace atomic operations registers */
+#define USER_ATOMIC_OPS_PAGE_ADDR  0xd400a000
+
+#endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_CPU_REGS_H */
diff --git a/arch/mn10300/include/asm/current.h b/arch/mn10300/include/asm/current.h
new file mode 100644
index 0000000..ca6027d
--- /dev/null
+++ b/arch/mn10300/include/asm/current.h
@@ -0,0 +1,37 @@
+/* MN10300 Current task structure accessor
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_CURRENT_H
+#define _ASM_CURRENT_H
+
+#include <linux/thread_info.h>
+
+/*
+ * dedicate E2 to keeping the current task pointer
+ */
+#ifdef CONFIG_MN10300_CURRENT_IN_E2
+
+register struct task_struct *const current asm("e2") __attribute__((used));
+
+#define get_current() current
+
+extern struct task_struct *__current;
+
+#else
+static inline __attribute__((const))
+struct task_struct *get_current(void)
+{
+	return current_thread_info()->task;
+}
+
+#define current get_current()
+#endif
+
+#endif /* _ASM_CURRENT_H */
diff --git a/arch/mn10300/include/asm/debugger.h b/arch/mn10300/include/asm/debugger.h
new file mode 100644
index 0000000..e1d3b08
--- /dev/null
+++ b/arch/mn10300/include/asm/debugger.h
@@ -0,0 +1,43 @@
+/* Kernel debugger for MN10300
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_DEBUGGER_H
+#define _ASM_DEBUGGER_H
+
+#if defined(CONFIG_KERNEL_DEBUGGER)
+
+extern int debugger_intercept(enum exception_code, int, int, struct pt_regs *);
+extern int at_debugger_breakpoint(struct pt_regs *);
+
+#ifndef CONFIG_MN10300_DEBUGGER_CACHE_NO_FLUSH
+extern void debugger_local_cache_flushinv(void);
+extern void debugger_local_cache_flushinv_one(u8 *);
+#else
+static inline void debugger_local_cache_flushinv(void) {}
+static inline void debugger_local_cache_flushinv_one(u8 *addr) {}
+#endif
+
+#else /* CONFIG_KERNEL_DEBUGGER */
+
+static inline int debugger_intercept(enum exception_code excep,
+				     int signo, int si_code,
+				     struct pt_regs *regs)
+{
+	return 0;
+}
+
+static inline int at_debugger_breakpoint(struct pt_regs *regs)
+{
+	return 0;
+}
+
+#endif /* CONFIG_KERNEL_DEBUGGER */
+#endif /* _ASM_DEBUGGER_H */
diff --git a/arch/mn10300/include/asm/delay.h b/arch/mn10300/include/asm/delay.h
new file mode 100644
index 0000000..34517b3
--- /dev/null
+++ b/arch/mn10300/include/asm/delay.h
@@ -0,0 +1,19 @@
+/* MN10300 Uninterruptible delay routines
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_DELAY_H
+#define _ASM_DELAY_H
+
+extern void __udelay(unsigned long usecs);
+extern void __delay(unsigned long loops);
+
+#define udelay(n) __udelay(n)
+
+#endif /* _ASM_DELAY_H */
diff --git a/arch/mn10300/include/asm/device.h b/arch/mn10300/include/asm/device.h
new file mode 100644
index 0000000..f0a4c25
--- /dev/null
+++ b/arch/mn10300/include/asm/device.h
@@ -0,0 +1 @@
+#include <asm-generic/device.h>
diff --git a/arch/mn10300/include/asm/div64.h b/arch/mn10300/include/asm/div64.h
new file mode 100644
index 0000000..503efab
--- /dev/null
+++ b/arch/mn10300/include/asm/div64.h
@@ -0,0 +1,115 @@
+/* MN10300 64-bit division
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_DIV64
+#define _ASM_DIV64
+
+#include <linux/types.h>
+
+extern void ____unhandled_size_in_do_div___(void);
+
+/*
+ * Beginning with gcc 4.6, the MDR register is represented explicitly.  We
+ * must, therefore, at least explicitly clobber the register when we make
+ * changes to it.  The following assembly fragments *could* be rearranged in
+ * order to leave the moves to/from the MDR register to the compiler, but the
+ * gains would be minimal at best.
+ */
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+# define CLOBBER_MDR_CC		"mdr", "cc"
+#else
+# define CLOBBER_MDR_CC		"cc"
+#endif
+
+/*
+ * divide n by base, leaving the result in n and returning the remainder
+ * - we can do this quite efficiently on the MN10300 by cascading the divides
+ *   through the MDR register
+ */
+#define do_div(n, base)							\
+({									\
+	unsigned __rem = 0;						\
+	if (sizeof(n) <= 4) {						\
+		asm("mov	%1,mdr	\n"				\
+		    "divu	%2,%0	\n"				\
+		    "mov	mdr,%1	\n"				\
+		    : "+r"(n), "=d"(__rem)				\
+		    : "r"(base), "1"(__rem)				\
+		    : CLOBBER_MDR_CC					\
+		    );							\
+	} else if (sizeof(n) <= 8) {					\
+		union {							\
+			unsigned long long l;				\
+			u32 w[2];					\
+		} __quot;						\
+		__quot.l = n;						\
+		asm("mov	%0,mdr	\n"	/* MDR = 0 */		\
+		    "divu	%3,%1	\n"				\
+		    /* __quot.MSL = __div.MSL / base, */		\
+		    /* MDR = MDR:__div.MSL % base */			\
+		    "divu	%3,%2	\n"				\
+		    /* __quot.LSL = MDR:__div.LSL / base, */		\
+		    /* MDR = MDR:__div.LSL % base */			\
+		    "mov	mdr,%0	\n"				\
+		    : "=d"(__rem), "=r"(__quot.w[1]), "=r"(__quot.w[0])	\
+		    : "r"(base), "0"(__rem), "1"(__quot.w[1]),		\
+		      "2"(__quot.w[0])					\
+		    : CLOBBER_MDR_CC					\
+		    );							\
+		n = __quot.l;						\
+	} else {							\
+		____unhandled_size_in_do_div___();			\
+	}								\
+	__rem;								\
+})
+
+/*
+ * do an unsigned 32-bit multiply and divide with intermediate 64-bit product
+ * so as not to lose accuracy
+ * - we use the MDR register to hold the MSW of the product
+ */
+static inline __attribute__((const))
+unsigned __muldiv64u(unsigned val, unsigned mult, unsigned div)
+{
+	unsigned result;
+
+	asm("mulu	%2,%0	\n"	/* MDR:val = val*mult */
+	    "divu	%3,%0	\n"	/* val = MDR:val/div;
+					 * MDR = MDR:val%div */
+	    : "=r"(result)
+	    : "0"(val), "ir"(mult), "r"(div)
+	    : CLOBBER_MDR_CC
+	    );
+
+	return result;
+}
+
+/*
+ * do a signed 32-bit multiply and divide with intermediate 64-bit product so
+ * as not to lose accuracy
+ * - we use the MDR register to hold the MSW of the product
+ */
+static inline __attribute__((const))
+signed __muldiv64s(signed val, signed mult, signed div)
+{
+	signed result;
+
+	asm("mul	%2,%0	\n"	/* MDR:val = val*mult */
+	    "div	%3,%0	\n"	/* val = MDR:val/div;
+					 * MDR = MDR:val%div */
+	    : "=r"(result)
+	    : "0"(val), "ir"(mult), "r"(div)
+	    : CLOBBER_MDR_CC
+	    );
+
+	return result;
+}
+
+#endif /* _ASM_DIV64 */
diff --git a/arch/mn10300/include/asm/dma-mapping.h b/arch/mn10300/include/asm/dma-mapping.h
new file mode 100644
index 0000000..a18abfc
--- /dev/null
+++ b/arch/mn10300/include/asm/dma-mapping.h
@@ -0,0 +1,186 @@
+/* DMA mapping routines for the MN10300 arch
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+
+#include <asm/cache.h>
+#include <asm/io.h>
+
+/*
+ * See Documentation/DMA-API.txt for the description of how the
+ * following DMA API should work.
+ */
+
+extern void *dma_alloc_coherent(struct device *dev, size_t size,
+				dma_addr_t *dma_handle, int flag);
+
+extern void dma_free_coherent(struct device *dev, size_t size,
+			      void *vaddr, dma_addr_t dma_handle);
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent((d), (s), (h), (f))
+#define dma_free_noncoherent(d, s, v, h)  dma_free_coherent((d), (s), (v), (h))
+
+static inline
+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+			  enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+	mn10300_dcache_flush_inv();
+	return virt_to_bus(ptr);
+}
+
+static inline
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		      enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+static inline
+int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
+	       enum dma_data_direction direction)
+{
+	struct scatterlist *sg;
+	int i;
+
+	BUG_ON(!valid_dma_direction(direction));
+	WARN_ON(nents == 0 || sglist[0].length == 0);
+
+	for_each_sg(sglist, sg, nents, i) {
+		BUG_ON(!sg_page(sg));
+
+		sg->dma_address = sg_phys(sg);
+	}
+
+	mn10300_dcache_flush_inv();
+	return nents;
+}
+
+static inline
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+		  enum dma_data_direction direction)
+{
+	BUG_ON(!valid_dma_direction(direction));
+}
+
+static inline
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+			unsigned long offset, size_t size,
+			enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+	return page_to_bus(page) + offset;
+}
+
+static inline
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+		    enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+static inline
+void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+			     size_t size, enum dma_data_direction direction)
+{
+}
+
+static inline
+void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
+				size_t size, enum dma_data_direction direction)
+{
+	mn10300_dcache_flush_inv();
+}
+
+static inline
+void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+				   unsigned long offset, size_t size,
+				   enum dma_data_direction direction)
+{
+}
+
+static inline void
+dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+				 unsigned long offset, size_t size,
+				 enum dma_data_direction direction)
+{
+	mn10300_dcache_flush_inv();
+}
+
+
+static inline
+void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
+			 int nelems, enum dma_data_direction direction)
+{
+}
+
+static inline
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+			    int nelems, enum dma_data_direction direction)
+{
+	mn10300_dcache_flush_inv();
+}
+
+static inline
+int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	return 0;
+}
+
+static inline
+int dma_supported(struct device *dev, u64 mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s, so we can't
+	 * guarantee allocations that must be within a tighter range than
+	 * GFP_DMA
+	 */
+	if (mask < 0x00ffffff)
+		return 0;
+	return 1;
+}
+
+static inline
+int dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+
+	*dev->dma_mask = mask;
+	return 0;
+}
+
+static inline
+void dma_cache_sync(void *vaddr, size_t size,
+		    enum dma_data_direction direction)
+{
+	mn10300_dcache_flush_inv();
+}
+
+/* Not supported for now */
+static inline int dma_mmap_coherent(struct device *dev,
+				    struct vm_area_struct *vma, void *cpu_addr,
+				    dma_addr_t dma_addr, size_t size)
+{
+	return -EINVAL;
+}
+
+static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
+				  void *cpu_addr, dma_addr_t dma_addr,
+				  size_t size)
+{
+	return -EINVAL;
+}
+
+#endif
diff --git a/arch/mn10300/include/asm/dma.h b/arch/mn10300/include/asm/dma.h
new file mode 100644
index 0000000..10b77d4
--- /dev/null
+++ b/arch/mn10300/include/asm/dma.h
@@ -0,0 +1,117 @@
+/* MN10300 ISA DMA handlers and definitions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_DMA_H
+#define _ASM_DMA_H
+
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+
+#undef MAX_DMA_CHANNELS		/* switch off linux/kernel/dma.c */
+#define MAX_DMA_ADDRESS		0xbfffffff
+
+extern spinlock_t dma_spin_lock;
+
+static inline unsigned long claim_dma_lock(void)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dma_spin_lock, flags);
+	return flags;
+}
+
+static inline void release_dma_lock(unsigned long flags)
+{
+	spin_unlock_irqrestore(&dma_spin_lock, flags);
+}
+
+/* enable/disable a specific DMA channel */
+static inline void enable_dma(unsigned int dmanr)
+{
+}
+
+static inline void disable_dma(unsigned int dmanr)
+{
+}
+
+/* Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a known state.
+ * After that, keep track of it. :-)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while holding the DMA lock ! ---
+ */
+static inline void clear_dma_ff(unsigned int dmanr)
+{
+}
+
+/* set mode (above) for a specific DMA channel */
+static inline void set_dma_mode(unsigned int dmanr, char mode)
+{
+}
+
+/* Set only the page register bits of the transfer address.
+ * This is used for successive transfers when we know the contents of
+ * the lower 16 bits of the DMA current address register, but a 64k boundary
+ * may have been crossed.
+ */
+static inline void set_dma_page(unsigned int dmanr, char pagenr)
+{
+}
+
+
+/* Set transfer address & page bits for specific DMA channel.
+ * Assumes dma flipflop is clear.
+ */
+static inline void set_dma_addr(unsigned int dmanr, unsigned int a)
+{
+}
+
+
+/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for
+ * a specific DMA channel.
+ * You must ensure the parameters are valid.
+ * NOTE: from a manual: "the number of transfers is one more
+ * than the initial word count"! This is taken into account.
+ * Assumes dma flip-flop is clear.
+ * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
+ */
+static inline void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+}
+
+
+/* Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * If called before the channel has been used, it may return 1.
+ * Otherwise, it returns the number of _bytes_ left to transfer.
+ *
+ * Assumes DMA flip-flop is clear.
+ */
+static inline int get_dma_residue(unsigned int dmanr)
+{
+	return 0;
+}
+
+
+/* These are in kernel/dma.c: */
+extern int request_dma(unsigned int dmanr, const char *device_id);
+extern void free_dma(unsigned int dmanr);
+
+/* From PCI */
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy 	(0)
+#endif
+
+#endif /* _ASM_DMA_H */
diff --git a/arch/mn10300/include/asm/dmactl-regs.h b/arch/mn10300/include/asm/dmactl-regs.h
new file mode 100644
index 0000000..80337b3
--- /dev/null
+++ b/arch/mn10300/include/asm/dmactl-regs.h
@@ -0,0 +1,16 @@
+/* MN10300 on-board DMA controller registers
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_DMACTL_REGS_H
+#define _ASM_DMACTL_REGS_H
+
+#include <proc/dmactl-regs.h>
+
+#endif /* _ASM_DMACTL_REGS_H */
diff --git a/arch/mn10300/include/asm/elf.h b/arch/mn10300/include/asm/elf.h
new file mode 100644
index 0000000..f592d7a
--- /dev/null
+++ b/arch/mn10300/include/asm/elf.h
@@ -0,0 +1,153 @@
+/* MN10300 ELF constant and register definitions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_ELF_H
+#define _ASM_ELF_H
+
+#include <linux/utsname.h>
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
+/*
+ * AM33 relocations
+ */
+#define R_MN10300_NONE		0	/* No reloc.  */
+#define R_MN10300_32		1	/* Direct 32 bit.  */
+#define R_MN10300_16		2	/* Direct 16 bit.  */
+#define R_MN10300_8		3	/* Direct 8 bit.  */
+#define R_MN10300_PCREL32	4	/* PC-relative 32-bit.  */
+#define R_MN10300_PCREL16	5	/* PC-relative 16-bit signed.  */
+#define R_MN10300_PCREL8	6	/* PC-relative 8-bit signed.  */
+#define R_MN10300_24		9	/* Direct 24 bit.  */
+#define R_MN10300_RELATIVE	23	/* Adjust by program base.  */
+#define R_MN10300_SYM_DIFF	33	/* Adjustment when relaxing. */
+#define R_MN10300_ALIGN 	34	/* Alignment requirement. */
+
+/*
+ * AM33/AM34 HW Capabilities
+ */
+#define HWCAP_MN10300_ATOMIC_OP_UNIT	1	/* Has AM34 Atomic Operations */
+
+
+/*
+ * ELF register definitions..
+ */
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG ((sizeof(struct pt_regs) / sizeof(elf_greg_t)) - 1)
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+#define ELF_NFPREG 32
+typedef float elf_fpreg_t;
+
+typedef struct {
+	elf_fpreg_t	fpregs[ELF_NFPREG];
+	u_int32_t	fpcr;
+} elf_fpregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture
+ */
+#define elf_check_arch(x) \
+	(((x)->e_machine == EM_CYGNUS_MN10300) ||	\
+	 ((x)->e_machine == EM_MN10300))
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_MN10300
+
+/*
+ * ELF process initialiser
+ */
+#define ELF_PLAT_INIT(_r, load_addr)					\
+do {									\
+	struct pt_regs *_ur = current->thread.uregs;			\
+	_ur->a3   = 0;	_ur->a2   = 0;	_ur->d3   = 0;	_ur->d2   = 0;	\
+	_ur->mcvf = 0;	_ur->mcrl = 0;	_ur->mcrh = 0;	_ur->mdrq = 0;	\
+	_ur->e1   = 0;	_ur->e0   = 0;	_ur->e7   = 0;	_ur->e6   = 0;	\
+	_ur->e5   = 0;	_ur->e4   = 0;	_ur->e3   = 0;	_ur->e2   = 0;	\
+	_ur->lar  = 0;	_ur->lir  = 0;	_ur->mdr  = 0;			\
+	_ur->a1   = 0;	_ur->a0   = 0;	_ur->d1   = 0;	_ur->d0   = 0;	\
+} while (0)
+
+#define CORE_DUMP_USE_REGSET
+#define ELF_EXEC_PAGESIZE	4096
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * the loader.  We need to make sure that it is out of the way of the program
+ * that it will "exec", and that there is sufficient room for the brk.
+ * - must clear the VMALLOC area
+ */
+#define ELF_ET_DYN_BASE         0x04000000
+
+/*
+ * regs is struct pt_regs, pr_reg is elf_gregset_t (which is
+ * now struct user_regs, they are different)
+ * - ELF_CORE_COPY_REGS has been guessed, and may be wrong
+ */
+#define ELF_CORE_COPY_REGS(pr_reg, regs)	\
+do {						\
+	pr_reg[0]	= regs->a3;		\
+	pr_reg[1]	= regs->a2;		\
+	pr_reg[2]	= regs->d3;		\
+	pr_reg[3]	= regs->d2;		\
+	pr_reg[4]	= regs->mcvf;		\
+	pr_reg[5]	= regs->mcrl;		\
+	pr_reg[6]	= regs->mcrh;		\
+	pr_reg[7]	= regs->mdrq;		\
+	pr_reg[8]	= regs->e1;		\
+	pr_reg[9]	= regs->e0;		\
+	pr_reg[10]	= regs->e7;		\
+	pr_reg[11]	= regs->e6;		\
+	pr_reg[12]	= regs->e5;		\
+	pr_reg[13]	= regs->e4;		\
+	pr_reg[14]	= regs->e3;		\
+	pr_reg[15]	= regs->e2;		\
+	pr_reg[16]	= regs->sp;		\
+	pr_reg[17]	= regs->lar;		\
+	pr_reg[18]	= regs->lir;		\
+	pr_reg[19]	= regs->mdr;		\
+	pr_reg[20]	= regs->a1;		\
+	pr_reg[21]	= regs->a0;		\
+	pr_reg[22]	= regs->d1;		\
+	pr_reg[23]	= regs->d0;		\
+	pr_reg[24]	= regs->orig_d0;	\
+	pr_reg[25]	= regs->epsw;		\
+	pr_reg[26]	= regs->pc;		\
+} while (0);
+
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this CPU supports.  This could be done in user space,
+ * but it's not easy, and we've already done it here.
+ */
+#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
+#define ELF_HWCAP	(HWCAP_MN10300_ATOMIC_OP_UNIT)
+#else
+#define ELF_HWCAP	(0)
+#endif
+
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization.  This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ *
+ * For the moment, we have only optimizations for the Intel generations,
+ * but that could change...
+ */
+#define ELF_PLATFORM  (NULL)
+
+#endif /* _ASM_ELF_H */
diff --git a/arch/mn10300/include/asm/emergency-restart.h b/arch/mn10300/include/asm/emergency-restart.h
new file mode 100644
index 0000000..3711bd9
--- /dev/null
+++ b/arch/mn10300/include/asm/emergency-restart.h
@@ -0,0 +1 @@
+#include <asm-generic/emergency-restart.h>
diff --git a/arch/mn10300/include/asm/exceptions.h b/arch/mn10300/include/asm/exceptions.h
new file mode 100644
index 0000000..95a4d42
--- /dev/null
+++ b/arch/mn10300/include/asm/exceptions.h
@@ -0,0 +1,121 @@
+/* MN10300 Microcontroller core exceptions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_EXCEPTIONS_H
+#define _ASM_EXCEPTIONS_H
+
+#include <linux/linkage.h>
+
+/*
+ * define the breakpoint instruction opcode to use
+ * - note that the JTAG unit steals 0xFF, so you can't use JTAG and GDBSTUB at
+ *   the same time.
+ */
+#define GDBSTUB_BKPT		0xFF
+
+#ifndef __ASSEMBLY__
+
+/*
+ * enumeration of exception codes (as extracted from TBR MSW)
+ */
+enum exception_code {
+	EXCEP_RESET		= 0x000000,	/* reset */
+
+	/* MMU exceptions */
+	EXCEP_ITLBMISS		= 0x000100,	/* instruction TLB miss */
+	EXCEP_DTLBMISS		= 0x000108,	/* data TLB miss */
+	EXCEP_IAERROR		= 0x000110,	/* instruction address */
+	EXCEP_DAERROR		= 0x000118,	/* data address */
+
+	/* system exceptions */
+	EXCEP_TRAP		= 0x000128,	/* program interrupt (PI instruction) */
+	EXCEP_ISTEP		= 0x000130,	/* single step */
+	EXCEP_IBREAK		= 0x000150,	/* instruction breakpoint */
+	EXCEP_OBREAK		= 0x000158,	/* operand breakpoint */
+	EXCEP_PRIVINS		= 0x000160,	/* privileged instruction execution */
+	EXCEP_UNIMPINS		= 0x000168,	/* unimplemented instruction execution */
+	EXCEP_UNIMPEXINS	= 0x000170,	/* unimplemented extended instruction execution */
+	EXCEP_MEMERR		= 0x000178,	/* illegal memory access */
+	EXCEP_MISALIGN		= 0x000180,	/* misalignment */
+	EXCEP_BUSERROR		= 0x000188,	/* bus error */
+	EXCEP_ILLINSACC		= 0x000190,	/* illegal instruction access */
+	EXCEP_ILLDATACC		= 0x000198,	/* illegal data access */
+	EXCEP_IOINSACC		= 0x0001a0,	/* I/O space instruction access */
+	EXCEP_PRIVINSACC	= 0x0001a8,	/* privileged space instruction access */
+	EXCEP_PRIVDATACC	= 0x0001b0,	/* privileged space data access */
+	EXCEP_DATINSACC		= 0x0001b8,	/* data space instruction access */
+	EXCEP_DOUBLE_FAULT	= 0x000200,	/* double fault */
+
+	/* FPU exceptions */
+	EXCEP_FPU_DISABLED	= 0x0001c0,	/* FPU disabled */
+	EXCEP_FPU_UNIMPINS	= 0x0001c8,	/* FPU unimplemented operation */
+	EXCEP_FPU_OPERATION	= 0x0001d0,	/* FPU operation */
+
+	/* interrupts */
+	EXCEP_WDT		= 0x000240,	/* watchdog timer overflow */
+	EXCEP_NMI		= 0x000248,	/* non-maskable interrupt */
+	EXCEP_IRQ_LEVEL0	= 0x000280,	/* level 0 maskable interrupt */
+	EXCEP_IRQ_LEVEL1	= 0x000288,	/* level 1 maskable interrupt */
+	EXCEP_IRQ_LEVEL2	= 0x000290,	/* level 2 maskable interrupt */
+	EXCEP_IRQ_LEVEL3	= 0x000298,	/* level 3 maskable interrupt */
+	EXCEP_IRQ_LEVEL4	= 0x0002a0,	/* level 4 maskable interrupt */
+	EXCEP_IRQ_LEVEL5	= 0x0002a8,	/* level 5 maskable interrupt */
+	EXCEP_IRQ_LEVEL6	= 0x0002b0,	/* level 6 maskable interrupt */
+
+	/* system calls */
+	EXCEP_SYSCALL0		= 0x000300,	/* system call 0 */
+	EXCEP_SYSCALL1		= 0x000308,	/* system call 1 */
+	EXCEP_SYSCALL2		= 0x000310,	/* system call 2 */
+	EXCEP_SYSCALL3		= 0x000318,	/* system call 3 */
+	EXCEP_SYSCALL4		= 0x000320,	/* system call 4 */
+	EXCEP_SYSCALL5		= 0x000328,	/* system call 5 */
+	EXCEP_SYSCALL6		= 0x000330,	/* system call 6 */
+	EXCEP_SYSCALL7		= 0x000338,	/* system call 7 */
+	EXCEP_SYSCALL8		= 0x000340,	/* system call 8 */
+	EXCEP_SYSCALL9		= 0x000348,	/* system call 9 */
+	EXCEP_SYSCALL10		= 0x000350,	/* system call 10 */
+	EXCEP_SYSCALL11		= 0x000358,	/* system call 11 */
+	EXCEP_SYSCALL12		= 0x000360,	/* system call 12 */
+	EXCEP_SYSCALL13		= 0x000368,	/* system call 13 */
+	EXCEP_SYSCALL14		= 0x000370,	/* system call 14 */
+	EXCEP_SYSCALL15		= 0x000378,	/* system call 15 */
+};
+
+extern void __set_intr_stub(enum exception_code code, void *handler);
+extern void set_intr_stub(enum exception_code code, void *handler);
+
+struct pt_regs;
+
+extern asmlinkage void __common_exception(void);
+extern asmlinkage void itlb_miss(void);
+extern asmlinkage void dtlb_miss(void);
+extern asmlinkage void itlb_aerror(void);
+extern asmlinkage void dtlb_aerror(void);
+extern asmlinkage void raw_bus_error(void);
+extern asmlinkage void double_fault(void);
+extern asmlinkage int  system_call(struct pt_regs *);
+extern asmlinkage void nmi(struct pt_regs *, enum exception_code);
+extern asmlinkage void uninitialised_exception(struct pt_regs *,
+					       enum exception_code);
+extern asmlinkage void irq_handler(void);
+extern asmlinkage void profile_handler(void);
+extern asmlinkage void nmi_handler(void);
+extern asmlinkage void misalignment(struct pt_regs *, enum exception_code);
+
+extern void die(const char *, struct pt_regs *, enum exception_code)
+	__noreturn;
+
+extern int die_if_no_fixup(const char *, struct pt_regs *, enum exception_code);
+
+#define NUM2EXCEP_IRQ_LEVEL(num)	(EXCEP_IRQ_LEVEL0 + (num) * 8)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_EXCEPTIONS_H */
diff --git a/arch/mn10300/include/asm/fb.h b/arch/mn10300/include/asm/fb.h
new file mode 100644
index 0000000..697b24a
--- /dev/null
+++ b/arch/mn10300/include/asm/fb.h
@@ -0,0 +1,23 @@
+/* MN10300 Frame buffer stuff
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_FB_H
+#define _ASM_FB_H
+
+#include <linux/fb.h>
+
+#define fb_pgprotect(...) do {} while (0)
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* _ASM_FB_H */
diff --git a/arch/mn10300/include/asm/fpu.h b/arch/mn10300/include/asm/fpu.h
new file mode 100644
index 0000000..738ff72
--- /dev/null
+++ b/arch/mn10300/include/asm/fpu.h
@@ -0,0 +1,134 @@
+/* MN10300 FPU definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * Derived from include/asm-i386/i387.h: Copyright (C) 1994 Linus Torvalds
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_FPU_H
+#define _ASM_FPU_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/sched.h>
+#include <asm/exceptions.h>
+#include <asm/sigcontext.h>
+
+#ifdef __KERNEL__
+
+extern asmlinkage void fpu_disabled(void);
+
+#ifdef CONFIG_FPU
+
+#ifdef CONFIG_LAZY_SAVE_FPU
+/* the task that currently owns the FPU state */
+extern struct task_struct *fpu_state_owner;
+#endif
+
+#if (THREAD_USING_FPU & ~0xff)
+#error THREAD_USING_FPU must be smaller than 0x100.
+#endif
+
+static inline void set_using_fpu(struct task_struct *tsk)
+{
+	asm volatile(
+		"bset %0,(0,%1)"
+		:
+		: "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags)
+		: "memory", "cc");
+}
+
+static inline void clear_using_fpu(struct task_struct *tsk)
+{
+	asm volatile(
+		"bclr %0,(0,%1)"
+		:
+		: "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags)
+		: "memory", "cc");
+}
+
+#define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU)
+
+extern asmlinkage void fpu_kill_state(struct task_struct *);
+extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
+extern asmlinkage void fpu_init_state(void);
+extern asmlinkage void fpu_save(struct fpu_state_struct *);
+extern int fpu_setup_sigcontext(struct fpucontext *buf);
+extern int fpu_restore_sigcontext(struct fpucontext *buf);
+
+static inline void unlazy_fpu(struct task_struct *tsk)
+{
+	preempt_disable();
+#ifndef CONFIG_LAZY_SAVE_FPU
+	if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
+		fpu_save(&tsk->thread.fpu_state);
+		tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
+		tsk->thread.uregs->epsw &= ~EPSW_FE;
+	}
+#else
+	if (fpu_state_owner == tsk)
+		fpu_save(&tsk->thread.fpu_state);
+#endif
+	preempt_enable();
+}
+
+static inline void exit_fpu(void)
+{
+#ifdef CONFIG_LAZY_SAVE_FPU
+	struct task_struct *tsk = current;
+
+	preempt_disable();
+	if (fpu_state_owner == tsk)
+		fpu_state_owner = NULL;
+	preempt_enable();
+#endif
+}
+
+static inline void flush_fpu(void)
+{
+	struct task_struct *tsk = current;
+
+	preempt_disable();
+#ifndef CONFIG_LAZY_SAVE_FPU
+	if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
+		tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
+		tsk->thread.uregs->epsw &= ~EPSW_FE;
+	}
+#else
+	if (fpu_state_owner == tsk) {
+		fpu_state_owner = NULL;
+		tsk->thread.uregs->epsw &= ~EPSW_FE;
+	}
+#endif
+	preempt_enable();
+	clear_using_fpu(tsk);
+}
+
+#else /* CONFIG_FPU */
+
+extern asmlinkage
+void unexpected_fpu_exception(struct pt_regs *, enum exception_code);
+#define fpu_exception unexpected_fpu_exception
+
+struct task_struct;
+struct fpu_state_struct;
+static inline bool is_using_fpu(struct task_struct *tsk) { return false; }
+static inline void set_using_fpu(struct task_struct *tsk) {}
+static inline void clear_using_fpu(struct task_struct *tsk) {}
+static inline void fpu_init_state(void) {}
+static inline void fpu_save(struct fpu_state_struct *s) {}
+static inline void fpu_kill_state(struct task_struct *tsk) {}
+static inline void unlazy_fpu(struct task_struct *tsk) {}
+static inline void exit_fpu(void) {}
+static inline void flush_fpu(void) {}
+static inline int fpu_setup_sigcontext(struct fpucontext *buf) { return 0; }
+static inline int fpu_restore_sigcontext(struct fpucontext *buf) { return 0; }
+#endif /* CONFIG_FPU  */
+
+#endif /* __KERNEL__ */
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_FPU_H */
diff --git a/arch/mn10300/include/asm/frame.inc b/arch/mn10300/include/asm/frame.inc
new file mode 100644
index 0000000..1c3eb4f
--- /dev/null
+++ b/arch/mn10300/include/asm/frame.inc
@@ -0,0 +1,97 @@
+/* MN10300 Microcontroller core system register definitions -*- asm -*-
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_FRAME_INC
+#define _ASM_FRAME_INC
+
+#ifndef __ASSEMBLY__
+#error not for use in C files
+#endif
+
+#ifndef __ASM_OFFSETS_H__
+#include <asm/asm-offsets.h>
+#endif
+#include <asm/thread_info.h>
+
+#define pi break
+
+#define fp a3
+
+###############################################################################
+#
+# build a stack frame from the registers
+# - the caller has subtracted 4 from SP before coming here
+#
+###############################################################################
+.macro SAVE_ALL
+	add	-4,sp				# next exception frame ptr save area
+	movm	[other],(sp)
+	mov	usp,a1
+	mov	a1,(sp)				# USP in MOVM[other] dummy slot
+	movm	[d2,d3,a2,a3,exreg0,exreg1,exother],(sp)
+	mov	sp,fp				# FRAME pointer in A3
+	add	-12,sp				# allow for calls to be made
+
+	# push the exception frame onto the front of the list
+	GET_THREAD_INFO a1
+	mov	(TI_frame,a1),a0
+	mov	a0,(REG_NEXT,fp)
+	mov	fp,(TI_frame,a1)
+
+	# disable the FPU inside the kernel
+	and	~EPSW_FE,epsw
+
+	# we may be holding current in E2
+#ifdef CONFIG_MN10300_CURRENT_IN_E2
+	mov	(__current),e2
+#endif
+.endm
+
+###############################################################################
+#
+# restore the registers from a stack frame
+#
+###############################################################################
+.macro RESTORE_ALL
+	# peel back the stack to the calling frame
+	# - we need that when returning from interrupts to kernel mode
+	GET_THREAD_INFO a0
+	mov	(TI_frame,a0),fp
+	mov	fp,sp
+	mov	(REG_NEXT,fp),d0
+	mov	d0,(TI_frame,a0)                # userspace has regs->next == 0
+
+#ifndef CONFIG_MN10300_USING_JTAG
+	mov	(REG_EPSW,fp),d0
+	btst	EPSW_T,d0
+	beq	99f
+
+	or	EPSW_NMID,epsw
+	movhu	(DCR),d1
+	or	0x0001, d1
+	movhu	d1,(DCR)
+
+99:
+#endif
+	movm	(sp),[d2,d3,a2,a3,exreg0,exreg1,exother]
+
+	# must restore usp even if returning to kernel space,
+	# when CONFIG_PREEMPT is enabled.
+	mov	(sp),a1				# USP in MOVM[other] dummy slot
+	mov	a1,usp
+
+	movm	(sp),[other]
+	add	8,sp
+	rti
+
+.endm
+
+
+#endif /* _ASM_FRAME_INC */
diff --git a/arch/mn10300/include/asm/ftrace.h b/arch/mn10300/include/asm/ftrace.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/mn10300/include/asm/ftrace.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/mn10300/include/asm/futex.h b/arch/mn10300/include/asm/futex.h
new file mode 100644
index 0000000..0b74582
--- /dev/null
+++ b/arch/mn10300/include/asm/futex.h
@@ -0,0 +1 @@
+#include <asm-generic/futex.h>
diff --git a/arch/mn10300/include/asm/gdb-stub.h b/arch/mn10300/include/asm/gdb-stub.h
new file mode 100644
index 0000000..f5495ad
--- /dev/null
+++ b/arch/mn10300/include/asm/gdb-stub.h
@@ -0,0 +1,182 @@
+/* MN10300 Kernel GDB stub definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from asm-mips/gdb-stub.h (c) 1995 Andreas Busse
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_GDB_STUB_H
+#define _ASM_GDB_STUB_H
+
+#include <asm/exceptions.h>
+
+/*
+ * register ID numbers in GDB remote protocol
+ */
+
+#define GDB_REGID_PC		9
+#define GDB_REGID_FP		7
+#define GDB_REGID_SP		8
+
+/*
+ * virtual stack layout for the GDB exception handler
+ */
+#define NUMREGS			64
+
+#define GDB_FR_D0		(0 * 4)
+#define GDB_FR_D1		(1 * 4)
+#define GDB_FR_D2		(2 * 4)
+#define GDB_FR_D3		(3 * 4)
+#define GDB_FR_A0		(4 * 4)
+#define GDB_FR_A1		(5 * 4)
+#define GDB_FR_A2		(6 * 4)
+#define GDB_FR_A3		(7 * 4)
+
+#define GDB_FR_SP		(8 * 4)
+#define GDB_FR_PC		(9 * 4)
+#define GDB_FR_MDR		(10 * 4)
+#define GDB_FR_EPSW		(11 * 4)
+#define GDB_FR_LIR		(12 * 4)
+#define GDB_FR_LAR		(13 * 4)
+#define GDB_FR_MDRQ		(14 * 4)
+
+#define GDB_FR_E0		(15 * 4)
+#define GDB_FR_E1		(16 * 4)
+#define GDB_FR_E2		(17 * 4)
+#define GDB_FR_E3		(18 * 4)
+#define GDB_FR_E4		(19 * 4)
+#define GDB_FR_E5		(20 * 4)
+#define GDB_FR_E6		(21 * 4)
+#define GDB_FR_E7		(22 * 4)
+
+#define GDB_FR_SSP		(23 * 4)
+#define GDB_FR_MSP		(24 * 4)
+#define GDB_FR_USP		(25 * 4)
+#define GDB_FR_MCRH		(26 * 4)
+#define GDB_FR_MCRL		(27 * 4)
+#define GDB_FR_MCVF		(28 * 4)
+
+#define GDB_FR_FPCR		(29 * 4)
+#define GDB_FR_DUMMY0		(30 * 4)
+#define GDB_FR_DUMMY1		(31 * 4)
+
+#define GDB_FR_FS0		(32 * 4)
+
+#define GDB_FR_SIZE		(NUMREGS * 4)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This is the same as above, but for the high-level
+ * part of the GDB stub.
+ */
+
+struct gdb_regs {
+	/* saved main processor registers */
+	u32	d0, d1, d2, d3, a0, a1, a2, a3;
+	u32	sp, pc, mdr, epsw, lir, lar, mdrq;
+	u32	e0, e1, e2, e3, e4, e5, e6, e7;
+	u32	ssp, msp, usp, mcrh, mcrl, mcvf;
+
+	/* saved floating point registers */
+	u32	fpcr, _dummy0, _dummy1;
+	u32	fs0,  fs1,  fs2,  fs3,  fs4,  fs5,  fs6,  fs7;
+	u32	fs8,  fs9,  fs10, fs11, fs12, fs13, fs14, fs15;
+	u32	fs16, fs17, fs18, fs19, fs20, fs21, fs22, fs23;
+	u32	fs24, fs25, fs26, fs27, fs28, fs29, fs30, fs31;
+};
+
+/*
+ * Prototypes
+ */
+extern void show_registers_only(struct pt_regs *regs);
+
+extern asmlinkage void gdbstub_init(void);
+extern asmlinkage void gdbstub_exit(int status);
+extern asmlinkage void gdbstub_io_init(void);
+extern asmlinkage void gdbstub_io_set_baud(unsigned baud);
+extern asmlinkage int  gdbstub_io_rx_char(unsigned char *_ch, int nonblock);
+extern asmlinkage void gdbstub_io_tx_char(unsigned char ch);
+extern asmlinkage void gdbstub_io_tx_flush(void);
+
+extern asmlinkage void gdbstub_io_rx_handler(void);
+extern asmlinkage void gdbstub_rx_irq(struct pt_regs *, enum exception_code);
+extern asmlinkage int  gdbstub_intercept(struct pt_regs *, enum exception_code);
+extern asmlinkage void gdbstub_exception(struct pt_regs *, enum exception_code);
+extern asmlinkage void __gdbstub_bug_trap(void);
+extern asmlinkage void __gdbstub_pause(void);
+
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+extern asmlinkage void gdbstub_purge_cache(void);
+#else
+#define gdbstub_purge_cache()	do {} while (0)
+#endif
+
+/* Used to prevent crashes in memory access */
+extern asmlinkage int  gdbstub_read_byte(const u8 *, u8 *);
+extern asmlinkage int  gdbstub_read_word(const u8 *, u8 *);
+extern asmlinkage int  gdbstub_read_dword(const u8 *, u8 *);
+extern asmlinkage int  gdbstub_write_byte(u32, u8 *);
+extern asmlinkage int  gdbstub_write_word(u32, u8 *);
+extern asmlinkage int  gdbstub_write_dword(u32, u8 *);
+
+extern asmlinkage void gdbstub_read_byte_guard(void);
+extern asmlinkage void gdbstub_read_byte_cont(void);
+extern asmlinkage void gdbstub_read_word_guard(void);
+extern asmlinkage void gdbstub_read_word_cont(void);
+extern asmlinkage void gdbstub_read_dword_guard(void);
+extern asmlinkage void gdbstub_read_dword_cont(void);
+extern asmlinkage void gdbstub_write_byte_guard(void);
+extern asmlinkage void gdbstub_write_byte_cont(void);
+extern asmlinkage void gdbstub_write_word_guard(void);
+extern asmlinkage void gdbstub_write_word_cont(void);
+extern asmlinkage void gdbstub_write_dword_guard(void);
+extern asmlinkage void gdbstub_write_dword_cont(void);
+
+extern u8	gdbstub_rx_buffer[PAGE_SIZE];
+extern u32	gdbstub_rx_inp;
+extern u32	gdbstub_rx_outp;
+extern u8	gdbstub_rx_overflow;
+extern u8	gdbstub_busy;
+extern u8	gdbstub_rx_unget;
+
+#ifdef CONFIG_GDBSTUB_DEBUGGING
+extern void gdbstub_printk(const char *fmt, ...)
+	__attribute__((format(printf, 1, 2)));
+#else
+static inline __attribute__((format(printf, 1, 2)))
+void gdbstub_printk(const char *fmt, ...)
+{
+}
+#endif
+
+#ifdef CONFIG_GDBSTUB_DEBUG_ENTRY
+#define gdbstub_entry(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__)
+#else
+#define gdbstub_entry(FMT, ...) no_printk(FMT, ##__VA_ARGS__)
+#endif
+
+#ifdef CONFIG_GDBSTUB_DEBUG_PROTOCOL
+#define gdbstub_proto(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__)
+#else
+#define gdbstub_proto(FMT, ...) no_printk(FMT, ##__VA_ARGS__)
+#endif
+
+#ifdef CONFIG_GDBSTUB_DEBUG_IO
+#define gdbstub_io(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__)
+#else
+#define gdbstub_io(FMT, ...) no_printk(FMT, ##__VA_ARGS__)
+#endif
+
+#ifdef CONFIG_GDBSTUB_DEBUG_BREAKPOINT
+#define gdbstub_bkpt(FMT, ...) gdbstub_printk(FMT, ##__VA_ARGS__)
+#else
+#define gdbstub_bkpt(FMT, ...) no_printk(FMT, ##__VA_ARGS__)
+#endif
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_GDB_STUB_H */
diff --git a/arch/mn10300/include/asm/hardirq.h b/arch/mn10300/include/asm/hardirq.h
new file mode 100644
index 0000000..0000d65
--- /dev/null
+++ b/arch/mn10300/include/asm/hardirq.h
@@ -0,0 +1,49 @@
+/* MN10300 Hardware IRQ statistics and management
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_HARDIRQ_H
+#define _ASM_HARDIRQ_H
+
+#include <linux/threads.h>
+#include <linux/irq.h>
+#include <asm/exceptions.h>
+
+/* assembly code in softirq.h is sensitive to the offsets of these fields */
+typedef struct {
+	unsigned int	__softirq_pending;
+#ifdef CONFIG_MN10300_WD_TIMER
+	unsigned int	__nmi_count;	/* arch dependent */
+	unsigned int	__irq_count;	/* arch dependent */
+#endif
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+
+extern void ack_bad_irq(int irq);
+
+/*
+ * manipulate stubs in the MN10300 CPU Trap/Interrupt Vector table
+ * - these should jump to __common_exception in entry.S unless there's a good
+ *   reason to do otherwise (see trap_preinit() in traps.c)
+ */
+typedef void (*intr_stub_fnx)(struct pt_regs *regs,
+			      enum exception_code intcode);
+
+/*
+ * manipulate pointers in the Exception table (see entry.S)
+ * - these are indexed by decoding the lower 24 bits of the TBR register
+ * - note that the MN103E010 doesn't always trap through the correct vector,
+ *   but does always set the TBR correctly
+ */
+extern asmlinkage void set_excp_vector(enum exception_code code,
+				       intr_stub_fnx handler);
+
+#endif /* _ASM_HARDIRQ_H */
diff --git a/arch/mn10300/include/asm/highmem.h b/arch/mn10300/include/asm/highmem.h
new file mode 100644
index 0000000..1ddea5a
--- /dev/null
+++ b/arch/mn10300/include/asm/highmem.h
@@ -0,0 +1,131 @@
+/* MN10300 Virtual kernel memory mappings for high memory
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from include/asm-i386/highmem.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_HIGHMEM_H
+#define _ASM_HIGHMEM_H
+
+#ifdef __KERNEL__
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/highmem.h>
+#include <asm/kmap_types.h>
+#include <asm/pgtable.h>
+
+/* undef for production */
+#undef HIGHMEM_DEBUG
+
+/* declarations for highmem.c */
+extern unsigned long highstart_pfn, highend_pfn;
+
+extern pte_t *kmap_pte;
+extern pgprot_t kmap_prot;
+extern pte_t *pkmap_page_table;
+
+extern void __init kmap_init(void);
+
+/*
+ * Right now we initialize only a single pte table. It can be extended
+ * easily, subsequent pte tables have to be allocated in one physical
+ * chunk of RAM.
+ */
+#define PKMAP_BASE	0xfe000000UL
+#define LAST_PKMAP	1024
+#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
+#define PKMAP_NR(virt)  ((virt - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+extern unsigned long kmap_high(struct page *page);
+extern void kunmap_high(struct page *page);
+
+static inline unsigned long kmap(struct page *page)
+{
+	if (in_interrupt())
+		BUG();
+	if (page < highmem_start_page)
+		return page_address(page);
+	return kmap_high(page);
+}
+
+static inline void kunmap(struct page *page)
+{
+	if (in_interrupt())
+		BUG();
+	if (page < highmem_start_page)
+		return;
+	kunmap_high(page);
+}
+
+/*
+ * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
+ * gives a more generic (and caching) interface. But kmap_atomic can
+ * be used in IRQ contexts, so in some (very limited) cases we need
+ * it.
+ */
+static inline void *kmap_atomic(struct page *page)
+{
+	unsigned long vaddr;
+	int idx, type;
+
+	preempt_disable();
+	pagefault_disable();
+	if (page < highmem_start_page)
+		return page_address(page);
+
+	type = kmap_atomic_idx_push();
+	idx = type + KM_TYPE_NR * smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#if HIGHMEM_DEBUG
+	if (!pte_none(*(kmap_pte - idx)))
+		BUG();
+#endif
+	set_pte(kmap_pte - idx, mk_pte(page, kmap_prot));
+	local_flush_tlb_one(vaddr);
+
+	return (void *)vaddr;
+}
+
+static inline void __kunmap_atomic(unsigned long vaddr)
+{
+	int type;
+
+	if (vaddr < FIXADDR_START) { /* FIXME */
+		pagefault_enable();
+		preempt_enable();
+		return;
+	}
+
+	type = kmap_atomic_idx();
+
+#if HIGHMEM_DEBUG
+	{
+		unsigned int idx;
+		idx = type + KM_TYPE_NR * smp_processor_id();
+
+		if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx))
+			BUG();
+
+		/*
+		 * force other mappings to Oops if they'll try to access
+		 * this pte without first remap it
+		 */
+		pte_clear(kmap_pte - idx);
+		local_flush_tlb_one(vaddr);
+	}
+#endif
+
+	kmap_atomic_idx_pop();
+	pagefault_enable();
+	preempt_enable();
+}
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_HIGHMEM_H */
diff --git a/arch/mn10300/include/asm/hw_irq.h b/arch/mn10300/include/asm/hw_irq.h
new file mode 100644
index 0000000..7061990
--- /dev/null
+++ b/arch/mn10300/include/asm/hw_irq.h
@@ -0,0 +1,14 @@
+/* MN10300 Hardware interrupt definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_HW_IRQ_H
+#define _ASM_HW_IRQ_H
+
+#endif /* _ASM_HW_IRQ_H */
diff --git a/arch/mn10300/include/asm/intctl-regs.h b/arch/mn10300/include/asm/intctl-regs.h
new file mode 100644
index 0000000..d65bbee
--- /dev/null
+++ b/arch/mn10300/include/asm/intctl-regs.h
@@ -0,0 +1,71 @@
+/* MN10300 On-board interrupt controller registers
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_INTCTL_REGS_H
+#define _ASM_INTCTL_REGS_H
+
+#include <asm/cpu-regs.h>
+
+#ifdef __KERNEL__
+
+/*
+ * Interrupt controller registers
+ * - Registers 64-191 are at addresses offset from the main array
+ */
+#define GxICR(X)						\
+	__SYSREG(0xd4000000 + (X) * 4 +				\
+		 (((X) >= 64) && ((X) < 192)) * 0xf00, u16)
+
+#define GxICR_u8(X)							\
+	__SYSREG(0xd4000000 + (X) * 4 +					\
+		 (((X) >= 64) && ((X) < 192)) * 0xf00, u8)
+
+#include <proc/intctl-regs.h>
+
+#define XIRQ_TRIGGER_LOWLEVEL	0
+#define XIRQ_TRIGGER_HILEVEL	1
+#define XIRQ_TRIGGER_NEGEDGE	2
+#define XIRQ_TRIGGER_POSEDGE	3
+
+/* non-maskable interrupt control */
+#define NMIIRQ			0
+#define NMICR			GxICR(NMIIRQ)	/* NMI control register */
+#define NMICR_NMIF		0x0001		/* NMI pin interrupt flag */
+#define NMICR_WDIF		0x0002		/* watchdog timer overflow flag */
+#define NMICR_ABUSERR		0x0008		/* async bus error flag */
+
+/* maskable interrupt control */
+#define GxICR_DETECT		0x0001		/* interrupt detect flag */
+#define GxICR_REQUEST		0x0010		/* interrupt request flag */
+#define GxICR_ENABLE		0x0100		/* interrupt enable flag */
+#define GxICR_LEVEL		0x7000		/* interrupt priority level */
+#define GxICR_LEVEL_0		0x0000		/* - level 0 */
+#define GxICR_LEVEL_1		0x1000		/* - level 1 */
+#define GxICR_LEVEL_2		0x2000		/* - level 2 */
+#define GxICR_LEVEL_3		0x3000		/* - level 3 */
+#define GxICR_LEVEL_4		0x4000		/* - level 4 */
+#define GxICR_LEVEL_5		0x5000		/* - level 5 */
+#define GxICR_LEVEL_6		0x6000		/* - level 6 */
+#define GxICR_LEVEL_SHIFT	12
+#define GxICR_NMI		0x8000		/* nmi request flag */
+
+#define NUM2GxICR_LEVEL(num)	((num) << GxICR_LEVEL_SHIFT)
+
+#ifndef __ASSEMBLY__
+extern void set_intr_level(int irq, u16 level);
+extern void mn10300_set_lateack_irq_type(int irq);
+#endif
+
+/* external interrupts */
+#define XIRQxICR(X)		GxICR((X))	/* external interrupt control regs */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_INTCTL_REGS_H */
diff --git a/arch/mn10300/include/asm/io.h b/arch/mn10300/include/asm/io.h
new file mode 100644
index 0000000..6218935
--- /dev/null
+++ b/arch/mn10300/include/asm/io.h
@@ -0,0 +1,325 @@
+/* MN10300 I/O port emulation and memory-mapped I/O
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#include <asm/page.h> /* I/O is all done through memory accesses */
+#include <asm/cpu-regs.h>
+#include <asm/cacheflush.h>
+#include <asm-generic/pci_iomap.h>
+
+#define mmiowb() do {} while (0)
+
+/*****************************************************************************/
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the x86 architecture, we just read/write the
+ * memory location directly.
+ */
+static inline u8 readb(const volatile void __iomem *addr)
+{
+	return *(const volatile u8 *) addr;
+}
+
+static inline u16 readw(const volatile void __iomem *addr)
+{
+	return *(const volatile u16 *) addr;
+}
+
+static inline u32 readl(const volatile void __iomem *addr)
+{
+	return *(const volatile u32 *) addr;
+}
+
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+
+#define readb_relaxed readb
+#define readw_relaxed readw
+#define readl_relaxed readl
+
+static inline void writeb(u8 b, volatile void __iomem *addr)
+{
+	*(volatile u8 *) addr = b;
+}
+
+static inline void writew(u16 b, volatile void __iomem *addr)
+{
+	*(volatile u16 *) addr = b;
+}
+
+static inline void writel(u32 b, volatile void __iomem *addr)
+{
+	*(volatile u32 *) addr = b;
+}
+
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+#define writeb_relaxed writeb
+#define writew_relaxed writew
+#define writel_relaxed writel
+
+/*****************************************************************************/
+/*
+ * traditional input/output functions
+ */
+static inline u8 inb_local(unsigned long addr)
+{
+	return readb((volatile void __iomem *) addr);
+}
+
+static inline void outb_local(u8 b, unsigned long addr)
+{
+	return writeb(b, (volatile void __iomem *) addr);
+}
+
+static inline u8 inb(unsigned long addr)
+{
+	return readb((volatile void __iomem *) addr);
+}
+
+static inline u16 inw(unsigned long addr)
+{
+	return readw((volatile void __iomem *) addr);
+}
+
+static inline u32 inl(unsigned long addr)
+{
+	return readl((volatile void __iomem *) addr);
+}
+
+static inline void outb(u8 b, unsigned long addr)
+{
+	return writeb(b, (volatile void __iomem *) addr);
+}
+
+static inline void outw(u16 b, unsigned long addr)
+{
+	return writew(b, (volatile void __iomem *) addr);
+}
+
+static inline void outl(u32 b, unsigned long addr)
+{
+	return writel(b, (volatile void __iomem *) addr);
+}
+
+#define inb_p(addr)	inb(addr)
+#define inw_p(addr)	inw(addr)
+#define inl_p(addr)	inl(addr)
+#define outb_p(x, addr)	outb((x), (addr))
+#define outw_p(x, addr)	outw((x), (addr))
+#define outl_p(x, addr)	outl((x), (addr))
+
+static inline void insb(unsigned long addr, void *buffer, int count)
+{
+	if (count) {
+		u8 *buf = buffer;
+		do {
+			u8 x = inb(addr);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void insw(unsigned long addr, void *buffer, int count)
+{
+	if (count) {
+		u16 *buf = buffer;
+		do {
+			u16 x = inw(addr);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void insl(unsigned long addr, void *buffer, int count)
+{
+	if (count) {
+		u32 *buf = buffer;
+		do {
+			u32 x = inl(addr);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void outsb(unsigned long addr, const void *buffer, int count)
+{
+	if (count) {
+		const u8 *buf = buffer;
+		do {
+			outb(*buf++, addr);
+		} while (--count);
+	}
+}
+
+static inline void outsw(unsigned long addr, const void *buffer, int count)
+{
+	if (count) {
+		const u16 *buf = buffer;
+		do {
+			outw(*buf++, addr);
+		} while (--count);
+	}
+}
+
+extern void __outsl(unsigned long addr, const void *buffer, int count);
+static inline void outsl(unsigned long addr, const void *buffer, int count)
+{
+	if ((unsigned long) buffer & 0x3)
+		return __outsl(addr, buffer, count);
+
+	if (count) {
+		const u32 *buf = buffer;
+		do {
+			outl(*buf++, addr);
+		} while (--count);
+	}
+}
+
+#define ioread8(addr)		readb(addr)
+#define ioread16(addr)		readw(addr)
+#define ioread32(addr)		readl(addr)
+
+#define iowrite8(v, addr)	writeb((v), (addr))
+#define iowrite16(v, addr)	writew((v), (addr))
+#define iowrite32(v, addr)	writel((v), (addr))
+
+#define ioread16be(addr)	be16_to_cpu(readw(addr))
+#define ioread32be(addr)	be32_to_cpu(readl(addr))
+#define iowrite16be(v, addr)	writew(cpu_to_be16(v), (addr))
+#define iowrite32be(v, addr)	writel(cpu_to_be32(v), (addr))
+
+#define ioread8_rep(p, dst, count) \
+	insb((unsigned long) (p), (dst), (count))
+#define ioread16_rep(p, dst, count) \
+	insw((unsigned long) (p), (dst), (count))
+#define ioread32_rep(p, dst, count) \
+	insl((unsigned long) (p), (dst), (count))
+
+#define iowrite8_rep(p, src, count) \
+	outsb((unsigned long) (p), (src), (count))
+#define iowrite16_rep(p, src, count) \
+	outsw((unsigned long) (p), (src), (count))
+#define iowrite32_rep(p, src, count) \
+	outsl((unsigned long) (p), (src), (count))
+
+#define readsb(p, dst, count) \
+	insb((unsigned long) (p), (dst), (count))
+#define readsw(p, dst, count) \
+	insw((unsigned long) (p), (dst), (count))
+#define readsl(p, dst, count) \
+	insl((unsigned long) (p), (dst), (count))
+
+#define writesb(p, src, count) \
+	outsb((unsigned long) (p), (src), (count))
+#define writesw(p, src, count) \
+	outsw((unsigned long) (p), (src), (count))
+#define writesl(p, src, count) \
+	outsl((unsigned long) (p), (src), (count))
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#ifdef __KERNEL__
+
+#include <linux/vmalloc.h>
+#define __io_virt(x) ((void *) (x))
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p)
+{
+}
+
+/*
+ * Change virtual addresses to physical addresses and vv.
+ * These are pretty trivial
+ */
+static inline unsigned long virt_to_phys(volatile void *address)
+{
+	return __pa(address);
+}
+
+static inline void *phys_to_virt(unsigned long address)
+{
+	return __va(address);
+}
+
+/*
+ * Change "struct page" to physical address.
+ */
+static inline void __iomem *__ioremap(unsigned long offset, unsigned long size,
+				      unsigned long flags)
+{
+	return (void __iomem *) offset;
+}
+
+static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
+{
+	return (void __iomem *)(offset & ~0x20000000);
+}
+
+/*
+ * This one maps high address device memory and turns off caching for that
+ * area.  it's useful if some control registers are in such an area and write
+ * combining or read caching is not desirable:
+ */
+static inline void __iomem *ioremap_nocache(unsigned long offset, unsigned long size)
+{
+	return (void __iomem *) (offset | 0x20000000);
+}
+
+#define ioremap_wc ioremap_nocache
+#define ioremap_wt ioremap_nocache
+#define ioremap_uc ioremap_nocache
+
+static inline void iounmap(void __iomem *addr)
+{
+}
+
+static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	return (void __iomem *) port;
+}
+
+static inline void ioport_unmap(void __iomem *p)
+{
+}
+
+#define xlate_dev_kmem_ptr(p)	((void *) (p))
+#define xlate_dev_mem_ptr(p)	((void *) (p))
+
+/*
+ * PCI bus iomem addresses must be in the region 0x80000000-0x9fffffff
+ */
+static inline unsigned long virt_to_bus(volatile void *address)
+{
+	return ((unsigned long) address) & ~0x20000000;
+}
+
+static inline void *bus_to_virt(unsigned long address)
+{
+	return (void *) address;
+}
+
+#define page_to_bus page_to_phys
+
+#define memset_io(a, b, c)	memset(__io_virt(a), (b), (c))
+#define memcpy_fromio(a, b, c)	memcpy((a), __io_virt(b), (c))
+#define memcpy_toio(a, b, c)	memcpy(__io_virt(a), (b), (c))
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_IO_H */
diff --git a/arch/mn10300/include/asm/irq.h b/arch/mn10300/include/asm/irq.h
new file mode 100644
index 0000000..1a73fb3
--- /dev/null
+++ b/arch/mn10300/include/asm/irq.h
@@ -0,0 +1,40 @@
+/* MN10300 Hardware interrupt definitions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ * - Derived from include/asm-i386/irq.h:
+ *   - (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_IRQ_H
+#define _ASM_IRQ_H
+
+#include <asm/intctl-regs.h>
+#include <asm/reset-regs.h>
+#include <proc/irq.h>
+
+/* this number is used when no interrupt has been assigned */
+#define NO_IRQ		INT_MAX
+
+/*
+ * hardware irq numbers
+ * - the ASB2364 has an FPGA with an IRQ multiplexer on it
+ */
+#ifdef CONFIG_MN10300_UNIT_ASB2364
+#include <unit/irq.h>
+#else
+#define NR_CPU_IRQS	GxICR_NUM_IRQS
+#define NR_IRQS		NR_CPU_IRQS
+#endif
+
+/* external hardware irq numbers */
+#define NR_XIRQS	GxICR_NUM_XIRQS
+
+#define irq_canonicalize(IRQ) (IRQ)
+
+#endif /* _ASM_IRQ_H */
diff --git a/arch/mn10300/include/asm/irq_regs.h b/arch/mn10300/include/asm/irq_regs.h
new file mode 100644
index 0000000..97d0cb5
--- /dev/null
+++ b/arch/mn10300/include/asm/irq_regs.h
@@ -0,0 +1,28 @@
+/* MN10300 IRQ registers pointer definition
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_IRQ_REGS_H
+#define _ASM_IRQ_REGS_H
+
+/*
+ * Per-cpu current frame pointer - the location of the last exception frame on
+ * the stack
+ */
+#define ARCH_HAS_OWN_IRQ_REGS
+
+#ifndef __ASSEMBLY__
+static inline __attribute__((const))
+struct pt_regs *get_irq_regs(void)
+{
+	return current_frame();
+}
+#endif
+
+#endif /* _ASM_IRQ_REGS_H */
diff --git a/arch/mn10300/include/asm/irqflags.h b/arch/mn10300/include/asm/irqflags.h
new file mode 100644
index 0000000..8730c0a
--- /dev/null
+++ b/arch/mn10300/include/asm/irqflags.h
@@ -0,0 +1,215 @@
+/* MN10300 IRQ flag handling
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#include <asm/cpu-regs.h>
+/* linux/smp.h <- linux/irqflags.h needs asm/smp.h first */
+#include <asm/smp.h>
+
+/*
+ * interrupt control
+ * - "disabled": run in IM1/2
+ *   - level 0 - kernel debugger
+ *   - level 1 - virtual serial DMA (if present)
+ *   - level 5 - normal interrupt priority
+ *   - level 6 - timer interrupt
+ * - "enabled":  run in IM7
+ */
+#define MN10300_CLI_LEVEL	(CONFIG_LINUX_CLI_LEVEL << EPSW_IM_SHIFT)
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+
+	asm volatile("mov epsw,%0" : "=d"(flags));
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	asm volatile(
+		"	and %0,epsw	\n"
+		"	or %1,epsw	\n"
+		"	nop		\n"
+		"	nop		\n"
+		"	nop		\n"
+		:
+		: "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)
+		: "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+
+	flags = arch_local_save_flags();
+	arch_local_irq_disable();
+	return flags;
+}
+
+/*
+ * we make sure arch_irq_enable() doesn't cause priority inversion
+ */
+extern unsigned long __mn10300_irq_enabled_epsw[];
+
+static inline void arch_local_irq_enable(void)
+{
+	unsigned long tmp;
+	int cpu = raw_smp_processor_id();
+
+	asm volatile(
+		"	mov	epsw,%0		\n"
+		"	and	%1,%0		\n"
+		"	or	%2,%0		\n"
+		"	mov	%0,epsw		\n"
+		: "=&d"(tmp)
+		: "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw[cpu])
+		: "memory", "cc");
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile(
+		"	mov %0,epsw	\n"
+		"	nop		\n"
+		"	nop		\n"
+		"	nop		\n"
+		:
+		: "d"(flags)
+		: "memory", "cc");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags & (EPSW_IE | EPSW_IM)) != (EPSW_IE | EPSW_IM_7);
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+/*
+ * Hook to save power by halting the CPU
+ * - called from the idle loop
+ * - must reenable interrupts (which takes three instruction cycles to complete)
+ */
+static inline void arch_safe_halt(void)
+{
+#ifdef CONFIG_SMP
+	arch_local_irq_enable();
+#else
+	asm volatile(
+		"	or	%0,epsw	\n"
+		"	nop		\n"
+		"	nop		\n"
+		"	bset	%2,(%1)	\n"
+		:
+		: "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)
+		: "cc");
+#endif
+}
+
+#define __sleep_cpu()				\
+do {						\
+	asm volatile(				\
+		"	bset	%1,(%0)\n"	\
+		"1:	btst	%1,(%0)\n"	\
+		"	bne	1b\n"		\
+		:				\
+		: "i"(&CPUM), "i"(CPUM_SLEEP)	\
+		: "cc"				\
+		);				\
+} while (0)
+
+static inline void arch_local_cli(void)
+{
+	asm volatile(
+		"	and	%0,epsw		\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		:
+		: "i"(~EPSW_IE)
+		: "memory"
+		);
+}
+
+static inline unsigned long arch_local_cli_save(void)
+{
+	unsigned long flags = arch_local_save_flags();
+	arch_local_cli();
+	return flags;
+}
+
+static inline void arch_local_sti(void)
+{
+	asm volatile(
+		"	or	%0,epsw		\n"
+		:
+		: "i"(EPSW_IE)
+		: "memory");
+}
+
+static inline void arch_local_change_intr_mask_level(unsigned long level)
+{
+	asm volatile(
+		"	and	%0,epsw		\n"
+		"	or	%1,epsw		\n"
+		:
+		: "i"(~EPSW_IM), "i"(EPSW_IE | level)
+		: "cc", "memory");
+}
+
+#else /* !__ASSEMBLY__ */
+
+#define LOCAL_SAVE_FLAGS(reg)			\
+	mov	epsw,reg
+
+#define LOCAL_IRQ_DISABLE				\
+	and	~EPSW_IM,epsw;				\
+	or	EPSW_IE|MN10300_CLI_LEVEL,epsw;		\
+	nop;						\
+	nop;						\
+	nop
+
+#define LOCAL_IRQ_ENABLE		\
+	or	EPSW_IE|EPSW_IM_7,epsw
+
+#define LOCAL_IRQ_RESTORE(reg)	\
+	mov	reg,epsw
+
+#define LOCAL_CLI_SAVE(reg)	\
+	mov	epsw,reg;	\
+	and	~EPSW_IE,epsw;	\
+	nop;			\
+	nop;			\
+	nop
+
+#define LOCAL_CLI		\
+	and	~EPSW_IE,epsw;	\
+	nop;			\
+	nop;			\
+	nop
+
+#define LOCAL_STI		\
+	or	EPSW_IE,epsw
+
+#define LOCAL_CHANGE_INTR_MASK_LEVEL(level)	\
+	and	~EPSW_IM,epsw;			\
+	or	EPSW_IE|(level),epsw
+
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_IRQFLAGS_H */
diff --git a/arch/mn10300/include/asm/kdebug.h b/arch/mn10300/include/asm/kdebug.h
new file mode 100644
index 0000000..0f47e11
--- /dev/null
+++ b/arch/mn10300/include/asm/kdebug.h
@@ -0,0 +1,22 @@
+/* MN10300 In-kernel death knells
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_KDEBUG_H
+#define _ASM_KDEBUG_H
+
+/* Grossly misnamed. */
+enum die_val {
+	DIE_OOPS = 1,
+	DIE_BREAKPOINT,
+	DIE_GPF,
+};
+
+#endif /* _ASM_KDEBUG_H */
diff --git a/arch/mn10300/include/asm/kgdb.h b/arch/mn10300/include/asm/kgdb.h
new file mode 100644
index 0000000..eb245f1
--- /dev/null
+++ b/arch/mn10300/include/asm/kgdb.h
@@ -0,0 +1,81 @@
+/* Kernel debugger for MN10300
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_KGDB_H
+#define _ASM_KGDB_H
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound
+ * buffers at least NUMREGBYTES*2 are needed for register packets
+ * Longer buffer is needed to list all threads
+ */
+#define BUFMAX			1024
+
+/*
+ * Note that this register image is in a different order than the register
+ * image that Linux produces at interrupt time.
+ */
+enum regnames {
+	GDB_FR_D0		= 0,
+	GDB_FR_D1		= 1,
+	GDB_FR_D2		= 2,
+	GDB_FR_D3		= 3,
+	GDB_FR_A0		= 4,
+	GDB_FR_A1		= 5,
+	GDB_FR_A2		= 6,
+	GDB_FR_A3		= 7,
+
+	GDB_FR_SP		= 8,
+	GDB_FR_PC		= 9,
+	GDB_FR_MDR		= 10,
+	GDB_FR_EPSW		= 11,
+	GDB_FR_LIR		= 12,
+	GDB_FR_LAR		= 13,
+	GDB_FR_MDRQ		= 14,
+
+	GDB_FR_E0		= 15,
+	GDB_FR_E1		= 16,
+	GDB_FR_E2		= 17,
+	GDB_FR_E3		= 18,
+	GDB_FR_E4		= 19,
+	GDB_FR_E5		= 20,
+	GDB_FR_E6		= 21,
+	GDB_FR_E7		= 22,
+
+	GDB_FR_SSP		= 23,
+	GDB_FR_MSP		= 24,
+	GDB_FR_USP		= 25,
+	GDB_FR_MCRH		= 26,
+	GDB_FR_MCRL		= 27,
+	GDB_FR_MCVF		= 28,
+
+	GDB_FR_FPCR		= 29,
+	GDB_FR_DUMMY0		= 30,
+	GDB_FR_DUMMY1		= 31,
+
+	GDB_FR_FS0		= 32,
+
+	GDB_FR_SIZE		= 64,
+};
+
+#define GDB_ORIG_D0		41
+#define NUMREGBYTES		(GDB_FR_SIZE*4)
+
+static inline void arch_kgdb_breakpoint(void)
+{
+	asm(".globl __arch_kgdb_breakpoint; __arch_kgdb_breakpoint: break");
+}
+extern u8 __arch_kgdb_breakpoint;
+
+#define BREAK_INSTR_SIZE	1
+#define CACHE_FLUSH_IS_SAFE	1
+
+#endif /* _ASM_KGDB_H */
diff --git a/arch/mn10300/include/asm/kmap_types.h b/arch/mn10300/include/asm/kmap_types.h
new file mode 100644
index 0000000..76d093b
--- /dev/null
+++ b/arch/mn10300/include/asm/kmap_types.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_KMAP_TYPES_H
+#define _ASM_KMAP_TYPES_H
+
+#include <asm-generic/kmap_types.h>
+
+#endif /* _ASM_KMAP_TYPES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
new file mode 100644
index 0000000..c800b59
--- /dev/null
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -0,0 +1,50 @@
+/* MN10300 Kernel Probes support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by Mark Salter (msalter@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public Licence as published by
+ * the Free Software Foundation; either version 2 of the Licence, or
+ * (at your option) any later version.
+ *
+ * This program 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 Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public Licence
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+#ifndef _ASM_KPROBES_H
+#define _ASM_KPROBES_H
+
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+struct kprobe;
+
+typedef unsigned char kprobe_opcode_t;
+#define BREAKPOINT_INSTRUCTION	0xff
+#define MAX_INSN_SIZE 8
+#define MAX_STACK_SIZE 128
+
+/* Architecture specific copy of original instruction */
+struct arch_specific_insn {
+	/*  copy of original instruction
+	 */
+	kprobe_opcode_t insn[MAX_INSN_SIZE];
+};
+
+extern const int kretprobe_blacklist_size;
+
+extern int kprobe_exceptions_notify(struct notifier_block *self,
+				    unsigned long val, void *data);
+
+#define flush_insn_slot(p)  do {} while (0)
+
+extern void arch_remove_kprobe(struct kprobe *p);
+
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/linkage.h b/arch/mn10300/include/asm/linkage.h
new file mode 100644
index 0000000..dda3002
--- /dev/null
+++ b/arch/mn10300/include/asm/linkage.h
@@ -0,0 +1,20 @@
+/* MN10300 Linkage and calling-convention overrides
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_LINKAGE_H
+#define _ASM_LINKAGE_H
+
+/* don't override anything */
+#define asmlinkage
+
+#define __ALIGN		.align 4,0xcb
+#define __ALIGN_STR	".align 4,0xcb"
+
+#endif
diff --git a/arch/mn10300/include/asm/local.h b/arch/mn10300/include/asm/local.h
new file mode 100644
index 0000000..c11c530
--- /dev/null
+++ b/arch/mn10300/include/asm/local.h
@@ -0,0 +1 @@
+#include <asm-generic/local.h>
diff --git a/arch/mn10300/include/asm/local64.h b/arch/mn10300/include/asm/local64.h
new file mode 100644
index 0000000..36c93b5
--- /dev/null
+++ b/arch/mn10300/include/asm/local64.h
@@ -0,0 +1 @@
+#include <asm-generic/local64.h>
diff --git a/arch/mn10300/include/asm/mc146818rtc.h b/arch/mn10300/include/asm/mc146818rtc.h
new file mode 100644
index 0000000..df6bc6e
--- /dev/null
+++ b/arch/mn10300/include/asm/mc146818rtc.h
@@ -0,0 +1 @@
+#include <asm/rtc-regs.h>
diff --git a/arch/mn10300/include/asm/mmu.h b/arch/mn10300/include/asm/mmu.h
new file mode 100644
index 0000000..2d2d097
--- /dev/null
+++ b/arch/mn10300/include/asm/mmu.h
@@ -0,0 +1,19 @@
+/* MN10300 Memory management context
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from include/asm-frv/mmu.h
+ */
+
+#ifndef _ASM_MMU_H
+#define _ASM_MMU_H
+
+/*
+ * MMU context
+ */
+typedef struct {
+	unsigned long	tlbpid[NR_CPUS];	/* TLB PID for this process on
+						 * each CPU */
+} mm_context_t;
+
+#endif /* _ASM_MMU_H */
diff --git a/arch/mn10300/include/asm/mmu_context.h b/arch/mn10300/include/asm/mmu_context.h
new file mode 100644
index 0000000..75dbe69
--- /dev/null
+++ b/arch/mn10300/include/asm/mmu_context.h
@@ -0,0 +1,161 @@
+/* MN10300 MMU context management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ * - Derived from include/asm-m32r/mmu_context.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ *
+ *
+ * This implements an algorithm to provide TLB PID mappings to provide
+ * selective access to the TLB for processes, thus reducing the number of TLB
+ * flushes required.
+ *
+ * Note, however, that the M32R algorithm is technically broken as it does not
+ * handle version wrap-around, and could, theoretically, have a problem with a
+ * very long lived program that sleeps long enough for the version number to
+ * wrap all the way around so that its TLB mappings appear valid once again.
+ */
+#ifndef _ASM_MMU_CONTEXT_H
+#define _ASM_MMU_CONTEXT_H
+
+#include <linux/atomic.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm-generic/mm_hooks.h>
+
+#define MMU_CONTEXT_TLBPID_NR		256
+#define MMU_CONTEXT_TLBPID_MASK		0x000000ffUL
+#define MMU_CONTEXT_VERSION_MASK	0xffffff00UL
+#define MMU_CONTEXT_FIRST_VERSION	0x00000100UL
+#define MMU_NO_CONTEXT			0x00000000UL
+#define MMU_CONTEXT_TLBPID_LOCK_NR	0
+
+#define enter_lazy_tlb(mm, tsk)	do {} while (0)
+
+static inline void cpu_ran_vm(int cpu, struct mm_struct *mm)
+{
+#ifdef CONFIG_SMP
+	cpumask_set_cpu(cpu, mm_cpumask(mm));
+#endif
+}
+
+static inline bool cpu_maybe_ran_vm(int cpu, struct mm_struct *mm)
+{
+#ifdef CONFIG_SMP
+	return cpumask_test_and_set_cpu(cpu, mm_cpumask(mm));
+#else
+	return true;
+#endif
+}
+
+#ifdef CONFIG_MN10300_TLB_USE_PIDR
+extern unsigned long mmu_context_cache[NR_CPUS];
+#define mm_context(mm)	(mm->context.tlbpid[smp_processor_id()])
+
+/**
+ * allocate_mmu_context - Allocate storage for the arch-specific MMU data
+ * @mm: The userspace VM context being set up
+ */
+static inline unsigned long allocate_mmu_context(struct mm_struct *mm)
+{
+	unsigned long *pmc = &mmu_context_cache[smp_processor_id()];
+	unsigned long mc = ++(*pmc);
+
+	if (!(mc & MMU_CONTEXT_TLBPID_MASK)) {
+		/* we exhausted the TLB PIDs of this version on this CPU, so we
+		 * flush this CPU's TLB in its entirety and start new cycle */
+		local_flush_tlb_all();
+
+		/* fix the TLB version if needed (we avoid version #0 so as to
+		 * distinguish MMU_NO_CONTEXT) */
+		if (!mc)
+			*pmc = mc = MMU_CONTEXT_FIRST_VERSION;
+	}
+	mm_context(mm) = mc;
+	return mc;
+}
+
+/*
+ * get an MMU context if one is needed
+ */
+static inline unsigned long get_mmu_context(struct mm_struct *mm)
+{
+	unsigned long mc = MMU_NO_CONTEXT, cache;
+
+	if (mm) {
+		cache = mmu_context_cache[smp_processor_id()];
+		mc = mm_context(mm);
+
+		/* if we have an old version of the context, replace it */
+		if ((mc ^ cache) & MMU_CONTEXT_VERSION_MASK)
+			mc = allocate_mmu_context(mm);
+	}
+	return mc;
+}
+
+/*
+ * initialise the context related info for a new mm_struct instance
+ */
+static inline int init_new_context(struct task_struct *tsk,
+				   struct mm_struct *mm)
+{
+	int num_cpus = NR_CPUS, i;
+
+	for (i = 0; i < num_cpus; i++)
+		mm->context.tlbpid[i] = MMU_NO_CONTEXT;
+	return 0;
+}
+
+/*
+ * after we have set current->mm to a new value, this activates the context for
+ * the new mm so we see the new mappings.
+ */
+static inline void activate_context(struct mm_struct *mm)
+{
+	PIDR = get_mmu_context(mm) & MMU_CONTEXT_TLBPID_MASK;
+}
+#else  /* CONFIG_MN10300_TLB_USE_PIDR */
+
+#define init_new_context(tsk, mm)	(0)
+#define activate_context(mm)		local_flush_tlb()
+
+#endif /* CONFIG_MN10300_TLB_USE_PIDR */
+
+/**
+ * destroy_context - Destroy mm context information
+ * @mm: The MM being destroyed.
+ *
+ * Destroy context related info for an mm_struct that is about to be put to
+ * rest
+ */
+#define destroy_context(mm)	do {} while (0)
+
+/**
+ * switch_mm - Change between userspace virtual memory contexts
+ * @prev: The outgoing MM context.
+ * @next: The incoming MM context.
+ * @tsk: The incoming task.
+ */
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+			     struct task_struct *tsk)
+{
+	int cpu = smp_processor_id();
+
+	if (prev != next) {
+#ifdef CONFIG_SMP
+		per_cpu(cpu_tlbstate, cpu).active_mm = next;
+#endif
+		cpu_ran_vm(cpu, next);
+		PTBR = (unsigned long) next->pgd;
+		activate_context(next);
+	}
+}
+
+#define deactivate_mm(tsk, mm)	do {} while (0)
+#define activate_mm(prev, next)	switch_mm((prev), (next), NULL)
+
+#endif /* _ASM_MMU_CONTEXT_H */
diff --git a/arch/mn10300/include/asm/module.h b/arch/mn10300/include/asm/module.h
new file mode 100644
index 0000000..6571103
--- /dev/null
+++ b/arch/mn10300/include/asm/module.h
@@ -0,0 +1,22 @@
+/* MN10300 Arch-specific module definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by Mark Salter (msalter@redhat.com)
+ * Derived from include/asm-i386/module.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_MODULE_H
+#define _ASM_MODULE_H
+
+#include <asm-generic/module.h>
+
+/*
+ * Include the MN10300 architecture version.
+ */
+#define MODULE_ARCH_VERMAGIC __stringify(PROCESSOR_MODEL_NAME) " "
+
+#endif /* _ASM_MODULE_H */
diff --git a/arch/mn10300/include/asm/mutex.h b/arch/mn10300/include/asm/mutex.h
new file mode 100644
index 0000000..84f5490
--- /dev/null
+++ b/arch/mn10300/include/asm/mutex.h
@@ -0,0 +1,16 @@
+/* MN10300 Mutex fastpath
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ *
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+#include <asm-generic/mutex-null.h>
diff --git a/arch/mn10300/include/asm/nmi.h b/arch/mn10300/include/asm/nmi.h
new file mode 100644
index 0000000..f3671cb
--- /dev/null
+++ b/arch/mn10300/include/asm/nmi.h
@@ -0,0 +1,14 @@
+/* MN10300 NMI handling
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_NMI_H
+#define _ASM_NMI_H
+
+#endif /* _ASM_NMI_H */
diff --git a/arch/mn10300/include/asm/page.h b/arch/mn10300/include/asm/page.h
new file mode 100644
index 0000000..8288e12
--- /dev/null
+++ b/arch/mn10300/include/asm/page.h
@@ -0,0 +1,128 @@
+/* MN10300 Page table definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_PAGE_H
+#define _ASM_PAGE_H
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT	12
+
+#ifndef __ASSEMBLY__
+#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_MASK	(~(PAGE_SIZE - 1))
+#else
+#define PAGE_SIZE	+(1 << PAGE_SHIFT)	/* unary plus marks an
+						 * immediate val not an addr */
+#define PAGE_MASK	+(~(PAGE_SIZE - 1))
+#endif
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to, from)	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+
+#define clear_user_page(addr, vaddr, page)	clear_page(addr)
+#define copy_user_page(vto, vfrom, vaddr, to)	copy_page(vto, vfrom)
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
+
+#define PTE_MASK	PAGE_MASK
+#define HPAGE_SHIFT	22
+
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SIZE		((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK		(~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+#endif
+
+#define pte_val(x)	((x).pte)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x)	((pte_t) { (x) })
+#define __pgd(x)	((pgd_t) { (x) })
+#define __pgprot(x)	((pgprot_t) { (x) })
+
+#include <asm-generic/pgtable-nopmd.h>
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * This handles the memory map.. We could make this a config
+ * option, but too many people screw it up, and too few need
+ * it.
+ *
+ * A __PAGE_OFFSET of 0xC0000000 means that the kernel has
+ * a virtual address space of one gigabyte, which limits the
+ * amount of physical memory you can use to about 950MB.
+ */
+
+#ifndef __ASSEMBLY__
+
+/* Pure 2^n version of get_order */
+static inline int get_order(unsigned long size) __attribute__((const));
+static inline int get_order(unsigned long size)
+{
+	int order;
+
+	size = (size - 1) >> (PAGE_SHIFT - 1);
+	order = -1;
+	do {
+		size >>= 1;
+		order++;
+	} while (size);
+	return order;
+}
+
+#endif /* __ASSEMBLY__ */
+
+#include <asm/page_offset.h>
+
+#define __PAGE_OFFSET		(PAGE_OFFSET_RAW)
+#define PAGE_OFFSET		((unsigned long) __PAGE_OFFSET)
+
+/*
+ * main RAM and kernel working space are coincident at 0x90000000, but to make
+ * life more interesting, there's also an uncached virtual shadow at 0xb0000000
+ * - these mappings are fixed in the MMU
+ */
+#define __pfn_disp		(CONFIG_KERNEL_RAM_BASE_ADDRESS >> PAGE_SHIFT)
+
+#define __pa(x)			((unsigned long)(x))
+#define __va(x)			((void *)(unsigned long)(x))
+#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
+#define pfn_to_page(pfn)	(mem_map + ((pfn) - __pfn_disp))
+#define page_to_pfn(page)	((unsigned long)((page) - mem_map) + __pfn_disp)
+
+#define pfn_valid(pfn)					\
+({							\
+	unsigned long __pfn = (pfn) - __pfn_disp;	\
+	__pfn < max_mapnr;				\
+})
+
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
+
+#define VM_DATA_DEFAULT_FLAGS \
+	(VM_READ | VM_WRITE | \
+	((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
+		 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_PAGE_H */
diff --git a/arch/mn10300/include/asm/page_offset.h b/arch/mn10300/include/asm/page_offset.h
new file mode 100644
index 0000000..8eb5b16
--- /dev/null
+++ b/arch/mn10300/include/asm/page_offset.h
@@ -0,0 +1,11 @@
+/* MN10300 Kernel base address
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+#ifndef _ASM_PAGE_OFFSET_H
+#define _ASM_PAGE_OFFSET_H
+
+#define PAGE_OFFSET_RAW CONFIG_KERNEL_RAM_BASE_ADDRESS
+
+#endif
diff --git a/arch/mn10300/include/asm/pci.h b/arch/mn10300/include/asm/pci.h
new file mode 100644
index 0000000..be3debb
--- /dev/null
+++ b/arch/mn10300/include/asm/pci.h
@@ -0,0 +1,93 @@
+/* MN10300 PCI definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_PCI_H
+#define _ASM_PCI_H
+
+#ifdef __KERNEL__
+#include <linux/mm.h>		/* for struct page */
+
+#if 0
+#define __pcbdebug(FMT, ADDR, ...) \
+	printk(KERN_DEBUG "PCIBRIDGE[%08x]: "FMT"\n", \
+	       (u32)(ADDR), ##__VA_ARGS__)
+
+#define __pcidebug(FMT, BUS, DEVFN, WHERE,...)		\
+do {							\
+	printk(KERN_DEBUG "PCI[%02x:%02x.%x + %02x]: "FMT"\n",	\
+	       (BUS)->number,					\
+	       PCI_SLOT(DEVFN),					\
+	       PCI_FUNC(DEVFN),					\
+	       (u32)(WHERE), ##__VA_ARGS__);			\
+} while (0)
+
+#else
+#define __pcbdebug(FMT, ADDR, ...)		do {} while (0)
+#define __pcidebug(FMT, BUS, DEVFN, WHERE, ...)	do {} while (0)
+#endif
+
+/* Can be used to override the logic in pci_scan_bus for skipping
+ * already-configured bus numbers - to be used for buggy BIOSes or
+ * architectures with incomplete PCI setup by the loader */
+
+#ifdef CONFIG_PCI
+#define pcibios_assign_all_busses()	1
+extern void unit_pci_init(void);
+#else
+#define pcibios_assign_all_busses()	0
+#endif
+
+#define PCIBIOS_MIN_IO		0xBE000004
+#define PCIBIOS_MIN_MEM		0xB8000000
+
+void pcibios_set_master(struct pci_dev *dev);
+
+/* Dynamic DMA mapping stuff.
+ * i386 has everything mapped statically.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include <linux/string.h>
+#include <asm/io.h>
+
+struct pci_dev;
+
+/* The PCI address space does equal the physical memory
+ * address space.  The networking and block device layers use
+ * this boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS	(1)
+
+/* Return the index of the PCI controller for device. */
+static inline int pci_controller_num(struct pci_dev *dev)
+{
+	return 0;
+}
+
+#define HAVE_PCI_MMAP
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			       enum pci_mmap_state mmap_state,
+			       int write_combine);
+
+#endif /* __KERNEL__ */
+
+/* implement the pci_ DMA API in terms of the generic device dma_ one */
+#include <asm-generic/pci-dma-compat.h>
+
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+	return channel ? 15 : 14;
+}
+
+#include <asm-generic/pci_iomap.h>
+
+#endif /* _ASM_PCI_H */
diff --git a/arch/mn10300/include/asm/percpu.h b/arch/mn10300/include/asm/percpu.h
new file mode 100644
index 0000000..06a959d
--- /dev/null
+++ b/arch/mn10300/include/asm/percpu.h
@@ -0,0 +1 @@
+#include <asm-generic/percpu.h>
diff --git a/arch/mn10300/include/asm/pgalloc.h b/arch/mn10300/include/asm/pgalloc.h
new file mode 100644
index 0000000..0f25d5f
--- /dev/null
+++ b/arch/mn10300/include/asm/pgalloc.h
@@ -0,0 +1,56 @@
+/* MN10300 Page and page table/directory allocation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_PGALLOC_H
+#define _ASM_PGALLOC_H
+
+#include <asm/page.h>
+#include <linux/threads.h>
+#include <linux/mm.h>		/* for struct page */
+
+struct mm_struct;
+struct page;
+
+/* attach a page table to a PMD entry */
+#define pmd_populate_kernel(mm, pmd, pte) \
+	set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE))
+
+static inline
+void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
+{
+	set_pmd(pmd, __pmd((page_to_pfn(pte) << PAGE_SHIFT) | _PAGE_TABLE));
+}
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+/*
+ * Allocate and free page tables.
+ */
+
+extern pgd_t *pgd_alloc(struct mm_struct *);
+extern void pgd_free(struct mm_struct *, pgd_t *);
+
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	free_page((unsigned long) pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, struct page *pte)
+{
+	pgtable_page_dtor(pte);
+	__free_page(pte);
+}
+
+
+#define __pte_free_tlb(tlb, pte, addr) tlb_remove_page((tlb), (pte))
+
+#endif /* _ASM_PGALLOC_H */
diff --git a/arch/mn10300/include/asm/pgtable.h b/arch/mn10300/include/asm/pgtable.h
new file mode 100644
index 0000000..96d3f9d
--- /dev/null
+++ b/arch/mn10300/include/asm/pgtable.h
@@ -0,0 +1,494 @@
+/* MN10300 Page table manipulators and constants
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ *
+ *
+ * The Linux memory management assumes a three-level page table setup. On
+ * the i386, we use that, but "fold" the mid level into the top-level page
+ * table, so that we physically have the same two-level page table as the
+ * i386 mmu expects.
+ *
+ * This file contains the functions and defines necessary to modify and use
+ * the i386 page table tree for the purposes of the MN10300 TLB handler
+ * functions.
+ */
+#ifndef _ASM_PGTABLE_H
+#define _ASM_PGTABLE_H
+
+#include <asm/cpu-regs.h>
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <linux/threads.h>
+
+#include <asm/bitops.h>
+
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+extern unsigned long empty_zero_page[1024];
+extern spinlock_t pgd_lock;
+extern struct page *pgd_list;
+
+extern void pmd_ctor(void *, struct kmem_cache *, unsigned long);
+extern void pgtable_cache_init(void);
+extern void paging_init(void);
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * The Linux mn10300 paging architecture only implements both the traditional
+ * 2-level page tables
+ */
+#define PGDIR_SHIFT	22
+#define PTRS_PER_PGD	1024
+#define PTRS_PER_PUD	1	/* we don't really have any PUD physically */
+#define __PAGETABLE_PUD_FOLDED
+#define PTRS_PER_PMD	1	/* we don't really have any PMD physically */
+#define __PAGETABLE_PMD_FOLDED
+#define PTRS_PER_PTE	1024
+
+#define PGD_SIZE	PAGE_SIZE
+#define PMD_SIZE	(1UL << PMD_SHIFT)
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+
+#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
+#define FIRST_USER_ADDRESS	0UL
+
+#define USER_PGD_PTRS		(PAGE_OFFSET >> PGDIR_SHIFT)
+#define KERNEL_PGD_PTRS		(PTRS_PER_PGD - USER_PGD_PTRS)
+
+#define TWOLEVEL_PGDIR_SHIFT	22
+#define BOOT_USER_PGD_PTRS	(__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
+#define BOOT_KERNEL_PGD_PTRS	(1024 - BOOT_USER_PGD_PTRS)
+
+#ifndef __ASSEMBLY__
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+#endif
+
+/*
+ * Unfortunately, due to the way the MMU works on the MN10300, the vmalloc VM
+ * area has to be in the lower half of the virtual address range (the upper
+ * half is not translated through the TLB).
+ *
+ * So in this case, the vmalloc area goes at the bottom of the address map
+ * (leaving a hole at the very bottom to catch addressing errors), and
+ * userspace starts immediately above.
+ *
+ * The vmalloc() routines also leaves a hole of 4kB between each vmalloced
+ * area to catch addressing errors.
+ */
+#ifndef __ASSEMBLY__
+#define VMALLOC_OFFSET	(8UL * 1024 * 1024)
+#define VMALLOC_START	(0x70000000UL)
+#define VMALLOC_END	(0x7C000000UL)
+#else
+#define VMALLOC_OFFSET	(8 * 1024 * 1024)
+#define VMALLOC_START	(0x70000000)
+#define VMALLOC_END	(0x7C000000)
+#endif
+
+#ifndef __ASSEMBLY__
+extern pte_t kernel_vmalloc_ptes[(VMALLOC_END - VMALLOC_START) / PAGE_SIZE];
+#endif
+
+/* IPTEL2/DPTEL2 bit assignments */
+#define _PAGE_BIT_VALID		xPTEL2_V_BIT
+#define _PAGE_BIT_CACHE		xPTEL2_C_BIT
+#define _PAGE_BIT_PRESENT	xPTEL2_PV_BIT
+#define _PAGE_BIT_DIRTY		xPTEL2_D_BIT
+#define _PAGE_BIT_GLOBAL	xPTEL2_G_BIT
+#define _PAGE_BIT_ACCESSED	xPTEL2_UNUSED1_BIT	/* mustn't be loaded into IPTEL2/DPTEL2 */
+
+#define _PAGE_VALID		xPTEL2_V
+#define _PAGE_CACHE		xPTEL2_C
+#define _PAGE_PRESENT		xPTEL2_PV
+#define _PAGE_DIRTY		xPTEL2_D
+#define _PAGE_PROT		xPTEL2_PR
+#define _PAGE_PROT_RKNU		xPTEL2_PR_ROK
+#define _PAGE_PROT_WKNU		xPTEL2_PR_RWK
+#define _PAGE_PROT_RKRU		xPTEL2_PR_ROK_ROU
+#define _PAGE_PROT_WKRU		xPTEL2_PR_RWK_ROU
+#define _PAGE_PROT_WKWU		xPTEL2_PR_RWK_RWU
+#define _PAGE_GLOBAL		xPTEL2_G
+#define _PAGE_PS_MASK		xPTEL2_PS
+#define _PAGE_PS_4Kb		xPTEL2_PS_4Kb
+#define _PAGE_PS_128Kb		xPTEL2_PS_128Kb
+#define _PAGE_PS_1Kb		xPTEL2_PS_1Kb
+#define _PAGE_PS_4Mb		xPTEL2_PS_4Mb
+#define _PAGE_PSE		xPTEL2_PS_4Mb		/* 4MB page */
+#define _PAGE_CACHE_WT		xPTEL2_CWT
+#define _PAGE_ACCESSED		xPTEL2_UNUSED1
+#define _PAGE_NX		0			/* no-execute bit */
+
+/* If _PAGE_VALID is clear, we use these: */
+#define _PAGE_PROTNONE		0x000		/* If not present */
+
+#define __PAGE_PROT_UWAUX	0x010
+#define __PAGE_PROT_USER	0x020
+#define __PAGE_PROT_WRITE	0x040
+
+#define _PAGE_PRESENTV		(_PAGE_PRESENT|_PAGE_VALID)
+
+#ifndef __ASSEMBLY__
+
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+#define _PAGE_TABLE	(_PAGE_PRESENTV | _PAGE_PROT_WKNU | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_CHG_MASK	(PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+#define __PAGE_NONE	(_PAGE_PRESENTV | _PAGE_PROT_RKNU | _PAGE_ACCESSED | _PAGE_CACHE)
+#define __PAGE_SHARED	(_PAGE_PRESENTV | _PAGE_PROT_WKWU | _PAGE_ACCESSED | _PAGE_CACHE)
+#define __PAGE_COPY	(_PAGE_PRESENTV | _PAGE_PROT_RKRU | _PAGE_ACCESSED | _PAGE_CACHE)
+#define __PAGE_READONLY	(_PAGE_PRESENTV | _PAGE_PROT_RKRU | _PAGE_ACCESSED | _PAGE_CACHE)
+
+#define PAGE_NONE		__pgprot(__PAGE_NONE     | _PAGE_NX)
+#define PAGE_SHARED_NOEXEC	__pgprot(__PAGE_SHARED   | _PAGE_NX)
+#define PAGE_COPY_NOEXEC	__pgprot(__PAGE_COPY     | _PAGE_NX)
+#define PAGE_READONLY_NOEXEC	__pgprot(__PAGE_READONLY | _PAGE_NX)
+#define PAGE_SHARED_EXEC	__pgprot(__PAGE_SHARED)
+#define PAGE_COPY_EXEC		__pgprot(__PAGE_COPY)
+#define PAGE_READONLY_EXEC	__pgprot(__PAGE_READONLY)
+#define PAGE_COPY		PAGE_COPY_NOEXEC
+#define PAGE_READONLY		PAGE_READONLY_NOEXEC
+#define PAGE_SHARED		PAGE_SHARED_EXEC
+
+#define __PAGE_KERNEL_BASE (_PAGE_PRESENTV | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_GLOBAL)
+
+#define __PAGE_KERNEL		(__PAGE_KERNEL_BASE | _PAGE_PROT_WKNU | _PAGE_CACHE | _PAGE_NX)
+#define __PAGE_KERNEL_NOCACHE	(__PAGE_KERNEL_BASE | _PAGE_PROT_WKNU | _PAGE_NX)
+#define __PAGE_KERNEL_EXEC	(__PAGE_KERNEL & ~_PAGE_NX)
+#define __PAGE_KERNEL_RO	(__PAGE_KERNEL_BASE | _PAGE_PROT_RKNU | _PAGE_CACHE | _PAGE_NX)
+#define __PAGE_KERNEL_LARGE	(__PAGE_KERNEL | _PAGE_PSE)
+#define __PAGE_KERNEL_LARGE_EXEC (__PAGE_KERNEL_EXEC | _PAGE_PSE)
+
+#define PAGE_KERNEL		__pgprot(__PAGE_KERNEL)
+#define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO)
+#define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC)
+#define PAGE_KERNEL_NOCACHE	__pgprot(__PAGE_KERNEL_NOCACHE)
+#define PAGE_KERNEL_LARGE	__pgprot(__PAGE_KERNEL_LARGE)
+#define PAGE_KERNEL_LARGE_EXEC	__pgprot(__PAGE_KERNEL_LARGE_EXEC)
+
+#define __PAGE_USERIO		(__PAGE_KERNEL_BASE | _PAGE_PROT_WKWU | _PAGE_NX)
+#define PAGE_USERIO		__pgprot(__PAGE_USERIO)
+
+/*
+ * Whilst the MN10300 can do page protection for execute (given separate data
+ * and insn TLBs), we are not supporting it at the moment. Write permission,
+ * however, always implies read permission (but not execute permission).
+ */
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY_NOEXEC
+#define __P010	PAGE_COPY_NOEXEC
+#define __P011	PAGE_COPY_NOEXEC
+#define __P100	PAGE_READONLY_EXEC
+#define __P101	PAGE_READONLY_EXEC
+#define __P110	PAGE_COPY_EXEC
+#define __P111	PAGE_COPY_EXEC
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY_NOEXEC
+#define __S010	PAGE_SHARED_NOEXEC
+#define __S011	PAGE_SHARED_NOEXEC
+#define __S100	PAGE_READONLY_EXEC
+#define __S101	PAGE_READONLY_EXEC
+#define __S110	PAGE_SHARED_EXEC
+#define __S111	PAGE_SHARED_EXEC
+
+/*
+ * Define this to warn about kernel memory accesses that are
+ * done without a 'verify_area(VERIFY_WRITE,..)'
+ */
+#undef TEST_VERIFY_AREA
+
+#define pte_present(x)	(pte_val(x) & _PAGE_VALID)
+#define pte_clear(mm, addr, xp)				\
+do {							\
+	set_pte_at((mm), (addr), (xp), __pte(0));	\
+} while (0)
+
+#define pmd_none(x)	(!pmd_val(x))
+#define pmd_present(x)	(!pmd_none(x))
+#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
+#define	pmd_bad(x)	0
+
+
+#define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT))
+
+#ifndef __ASSEMBLY__
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+static inline int pte_user(pte_t pte)	{ return pte_val(pte) & __PAGE_PROT_USER; }
+static inline int pte_read(pte_t pte)	{ return pte_val(pte) & __PAGE_PROT_USER; }
+static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte)	{ return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_write(pte_t pte)	{ return pte_val(pte) & __PAGE_PROT_WRITE; }
+static inline int pte_special(pte_t pte){ return 0; }
+
+static inline pte_t pte_rdprotect(pte_t pte)
+{
+	pte_val(pte) &= ~(__PAGE_PROT_USER|__PAGE_PROT_UWAUX); return pte;
+}
+static inline pte_t pte_exprotect(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_NX; return pte;
+}
+
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	pte_val(pte) &= ~(__PAGE_PROT_WRITE|__PAGE_PROT_UWAUX); return pte;
+}
+
+static inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkexec(pte_t pte)	{ pte_val(pte) &= ~_PAGE_NX; return pte; }
+
+static inline pte_t pte_mkread(pte_t pte)
+{
+	pte_val(pte) |= __PAGE_PROT_USER;
+	if (pte_write(pte))
+		pte_val(pte) |= __PAGE_PROT_UWAUX;
+	return pte;
+}
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	pte_val(pte) |= __PAGE_PROT_WRITE;
+	if (pte_val(pte) & __PAGE_PROT_USER)
+		pte_val(pte) |= __PAGE_PROT_UWAUX;
+	return pte;
+}
+
+static inline pte_t pte_mkspecial(pte_t pte)	{ return pte; }
+
+#define pte_ERROR(e) \
+	printk(KERN_ERR "%s:%d: bad pte %08lx.\n", \
+	       __FILE__, __LINE__, pte_val(e))
+#define pgd_ERROR(e) \
+	printk(KERN_ERR "%s:%d: bad pgd %08lx.\n", \
+	       __FILE__, __LINE__, pgd_val(e))
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+#define pgd_clear(xp)				do { } while (0)
+
+/*
+ * Certain architectures need to do special things when PTEs
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval)			(*(pteptr) = pteval)
+#define set_pte_at(mm, addr, ptep, pteval)	set_pte((ptep), (pteval))
+#define set_pte_atomic(pteptr, pteval)		set_pte((pteptr), (pteval))
+
+/*
+ * (pmds are folded into pgds so this doesn't get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
+
+#define ptep_get_and_clear(mm, addr, ptep) \
+	__pte(xchg(&(ptep)->pte, 0))
+#define pte_same(a, b)		(pte_val(a) == pte_val(b))
+#define pte_page(x)		pfn_to_page(pte_pfn(x))
+#define pte_none(x)		(!pte_val(x))
+#define pte_pfn(x)		((unsigned long) (pte_val(x) >> PAGE_SHIFT))
+#define __pfn_addr(pfn)		((pfn) << PAGE_SHIFT)
+#define pfn_pte(pfn, prot)	__pte(__pfn_addr(pfn) | pgprot_val(prot))
+#define pfn_pmd(pfn, prot)	__pmd(__pfn_addr(pfn) | pgprot_val(prot))
+
+/*
+ * All present user pages are user-executable:
+ */
+static inline int pte_exec(pte_t pte)
+{
+	return pte_user(pte);
+}
+
+/*
+ * All present pages are kernel-executable:
+ */
+static inline int pte_exec_kernel(pte_t pte)
+{
+	return 1;
+}
+
+/* Encode and de-code a swap entry */
+#define __swp_type(x)			(((x).val >> 1) & 0x3f)
+#define __swp_offset(x)			((x).val >> 7)
+#define __swp_entry(type, offset) \
+	((swp_entry_t) { ((type) << 1) | ((offset) << 7) })
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)		__pte((x).val)
+
+static inline
+int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr,
+			      pte_t *ptep)
+{
+	if (!pte_dirty(*ptep))
+		return 0;
+	return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte);
+}
+
+static inline
+int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr,
+			      pte_t *ptep)
+{
+	if (!pte_young(*ptep))
+		return 0;
+	return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte);
+}
+
+static inline
+void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+	pte_val(*ptep) &= ~(__PAGE_PROT_WRITE|__PAGE_PROT_UWAUX);
+}
+
+static inline void ptep_mkdirty(pte_t *ptep)
+{
+	set_bit(_PAGE_BIT_DIRTY, &ptep->pte);
+}
+
+/*
+ * Macro to mark a page protection value as "uncacheable".  On processors which
+ * do not support it, this is a no-op.
+ */
+#define pgprot_noncached(prot)	__pgprot(pgprot_val(prot) & ~_PAGE_CACHE)
+
+/*
+ * Macro to mark a page protection value as "Write-Through".
+ * On processors which do not support it, this is a no-op.
+ */
+#define pgprot_through(prot)	__pgprot(pgprot_val(prot) | _PAGE_CACHE_WT)
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+
+#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+#define mk_pte_huge(entry) \
+	((entry).pte |= _PAGE_PRESENT | _PAGE_PSE | _PAGE_VALID)
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte_val(pte) &= _PAGE_CHG_MASK;
+	pte_val(pte) |= pgprot_val(newprot);
+	return pte;
+}
+
+#define page_pte(page)	page_pte_prot((page), __pgprot(0))
+
+#define pmd_page_kernel(pmd) \
+	((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+#define pmd_page(pmd)	pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)
+
+#define pmd_large(pmd) \
+	((pmd_val(pmd) & (_PAGE_PSE | _PAGE_PRESENT)) == \
+	 (_PAGE_PSE | _PAGE_PRESENT))
+
+/*
+ * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
+ *
+ * this macro returns the index of the entry in the pgd page which would
+ * control the given virtual address
+ */
+#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
+
+/*
+ * pgd_offset() returns a (pgd_t *)
+ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+ */
+#define pgd_offset(mm, address)	((mm)->pgd + pgd_index(address))
+
+/*
+ * a shortcut which implies the use of the kernel's pgd, instead
+ * of a process's
+ */
+#define pgd_offset_k(address)	pgd_offset(&init_mm, address)
+
+/*
+ * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
+ *
+ * this macro returns the index of the entry in the pmd page which would
+ * control the given virtual address
+ */
+#define pmd_index(address) \
+	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+
+/*
+ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+ *
+ * this macro returns the index of the entry in the pte page which would
+ * control the given virtual address
+ */
+#define pte_index(address) \
+	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+#define pte_offset_kernel(dir, address) \
+	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
+
+/*
+ * Make a given kernel text page executable/non-executable.
+ * Returns the previous executability setting of that page (which
+ * is used to restore the previous state). Used by the SMP bootup code.
+ * NOTE: this is an __init function for security reasons.
+ */
+static inline int set_kernel_exec(unsigned long vaddr, int enable)
+{
+	return 0;
+}
+
+#define pte_offset_map(dir, address) \
+	((pte_t *) page_address(pmd_page(*(dir))) + pte_index(address))
+#define pte_unmap(pte)		do {} while (0)
+
+/*
+ * The MN10300 has external MMU info in the form of a TLB: this is adapted from
+ * the kernel page tables containing the necessary information by tlb-mn10300.S
+ */
+extern void update_mmu_cache(struct vm_area_struct *vma,
+			     unsigned long address, pte_t *ptep);
+
+#endif /* !__ASSEMBLY__ */
+
+#define kern_addr_valid(addr)	(1)
+
+#define MK_IOSPACE_PFN(space, pfn)	(pfn)
+#define GET_IOSPACE(pfn)		0
+#define GET_PFN(pfn)			(pfn)
+
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+#define __HAVE_ARCH_PTEP_MKDIRTY
+#define __HAVE_ARCH_PTE_SAME
+#include <asm-generic/pgtable.h>
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_PGTABLE_H */
diff --git a/arch/mn10300/include/asm/pio-regs.h b/arch/mn10300/include/asm/pio-regs.h
new file mode 100644
index 0000000..96bc818
--- /dev/null
+++ b/arch/mn10300/include/asm/pio-regs.h
@@ -0,0 +1,233 @@
+/* MN10300 On-board I/O port module registers
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_PIO_REGS_H
+#define _ASM_PIO_REGS_H
+
+#include <asm/cpu-regs.h>
+#include <asm/intctl-regs.h>
+
+#ifdef __KERNEL__
+
+/* I/O port 0 */
+#define	P0MD			__SYSREG(0xdb000000, u16)	/* mode reg */
+#define P0MD_0			0x0003	/* mask */
+#define P0MD_0_IN		0x0000	/* input mode */
+#define P0MD_0_OUT		0x0001	/* output mode */
+#define P0MD_0_TM0IO		0x0002	/* timer 0 I/O mode */
+#define P0MD_0_EYECLK		0x0003	/* test signal output (clock) */
+#define P0MD_1			0x000c
+#define P0MD_1_IN		0x0000
+#define P0MD_1_OUT		0x0004
+#define P0MD_1_TM1IO		0x0008	/* timer 1 I/O mode */
+#define P0MD_1_EYED		0x000c	/* test signal output (data) */
+#define P0MD_2			0x0030
+#define P0MD_2_IN		0x0000
+#define P0MD_2_OUT		0x0010
+#define P0MD_2_TM2IO		0x0020	/* timer 2 I/O mode */
+#define P0MD_3			0x00c0
+#define P0MD_3_IN		0x0000
+#define P0MD_3_OUT		0x0040
+#define P0MD_3_TM3IO		0x0080	/* timer 3 I/O mode */
+#define P0MD_4			0x0300
+#define P0MD_4_IN		0x0000
+#define P0MD_4_OUT		0x0100
+#define P0MD_4_TM4IO		0x0200	/* timer 4 I/O mode */
+#define P0MD_4_XCTS		0x0300	/* XCTS input for serial port 2 */
+#define P0MD_5			0x0c00
+#define P0MD_5_IN		0x0000
+#define P0MD_5_OUT		0x0400
+#define P0MD_5_TM5IO		0x0800	/* timer 5 I/O mode */
+#define P0MD_6			0x3000
+#define P0MD_6_IN		0x0000
+#define P0MD_6_OUT		0x1000
+#define P0MD_6_TM6IOA		0x2000	/* timer 6 I/O mode A */
+#define P0MD_7			0xc000
+#define P0MD_7_IN		0x0000
+#define P0MD_7_OUT		0x4000
+#define P0MD_7_TM6IOB		0x8000	/* timer 6 I/O mode B */
+
+#define	P0IN			__SYSREG(0xdb000004, u8)	/* in reg */
+#define	P0OUT			__SYSREG(0xdb000008, u8)	/* out reg */
+
+#define	P0TMIO			__SYSREG(0xdb00000c, u8)	/* TM pin I/O control reg */
+#define P0TMIO_TM0_IN		0x00
+#define P0TMIO_TM0_OUT		0x01
+#define P0TMIO_TM1_IN		0x00
+#define P0TMIO_TM1_OUT		0x02
+#define P0TMIO_TM2_IN		0x00
+#define P0TMIO_TM2_OUT		0x04
+#define P0TMIO_TM3_IN		0x00
+#define P0TMIO_TM3_OUT		0x08
+#define P0TMIO_TM4_IN		0x00
+#define P0TMIO_TM4_OUT		0x10
+#define P0TMIO_TM5_IN		0x00
+#define P0TMIO_TM5_OUT		0x20
+#define P0TMIO_TM6A_IN		0x00
+#define P0TMIO_TM6A_OUT		0x40
+#define P0TMIO_TM6B_IN		0x00
+#define P0TMIO_TM6B_OUT		0x80
+
+/* I/O port 1 */
+#define	P1MD			__SYSREG(0xdb000100, u16)	/* mode reg */
+#define P1MD_0			0x0003	/* mask */
+#define P1MD_0_IN		0x0000	/* input mode */
+#define P1MD_0_OUT		0x0001	/* output mode */
+#define P1MD_0_TM7IO		0x0002	/* timer 7 I/O mode */
+#define P1MD_0_ADTRG		0x0003	/* A/D converter trigger mode */
+#define P1MD_1			0x000c
+#define P1MD_1_IN		0x0000
+#define P1MD_1_OUT		0x0004
+#define P1MD_1_TM8IO		0x0008	/* timer 8 I/O mode */
+#define P1MD_1_XDMR0		0x000c	/* DMA request input 0 mode */
+#define P1MD_2			0x0030
+#define P1MD_2_IN		0x0000
+#define P1MD_2_OUT		0x0010
+#define P1MD_2_TM9IO		0x0020	/* timer 9 I/O mode */
+#define P1MD_2_XDMR1		0x0030	/* DMA request input 1 mode */
+#define P1MD_3			0x00c0
+#define P1MD_3_IN		0x0000
+#define P1MD_3_OUT		0x0040
+#define P1MD_3_TM10IO		0x0080	/* timer 10 I/O mode */
+#define P1MD_3_FRQS0		0x00c0	/* CPU clock multiplier setting input 0 mode */
+#define P1MD_4			0x0300
+#define P1MD_4_IN		0x0000
+#define P1MD_4_OUT		0x0100
+#define P1MD_4_TM11IO		0x0200	/* timer 11 I/O mode */
+#define P1MD_4_FRQS1		0x0300	/* CPU clock multiplier setting input 1 mode */
+
+#define	P1IN			__SYSREG(0xdb000104, u8)	/* in reg */
+#define	P1OUT			__SYSREG(0xdb000108, u8)	/* out reg */
+#define	P1TMIO			__SYSREG(0xdb00010c, u8)	/* TM pin I/O control reg */
+#define P1TMIO_TM11_IN		0x00
+#define P1TMIO_TM11_OUT		0x01
+#define P1TMIO_TM10_IN		0x00
+#define P1TMIO_TM10_OUT		0x02
+#define P1TMIO_TM9_IN		0x00
+#define P1TMIO_TM9_OUT		0x04
+#define P1TMIO_TM8_IN		0x00
+#define P1TMIO_TM8_OUT		0x08
+#define P1TMIO_TM7_IN		0x00
+#define P1TMIO_TM7_OUT		0x10
+
+/* I/O port 2 */
+#define	P2MD			__SYSREG(0xdb000200, u16)	/* mode reg */
+#define P2MD_0			0x0003	/* mask */
+#define P2MD_0_IN		0x0000	/* input mode */
+#define P2MD_0_OUT		0x0001	/* output mode */
+#define P2MD_0_BOOTBW		0x0003	/* boot bus width selector mode */
+#define P2MD_1			0x000c
+#define P2MD_1_IN		0x0000
+#define P2MD_1_OUT		0x0004
+#define P2MD_1_BOOTSEL		0x000c	/* boot device selector mode */
+#define P2MD_2			0x0030
+#define P2MD_2_IN		0x0000
+#define P2MD_2_OUT		0x0010
+#define P2MD_3			0x00c0
+#define P2MD_3_IN		0x0000
+#define P2MD_3_OUT		0x0040
+#define P2MD_3_CKIO		0x00c0	/* mode */
+#define P2MD_4			0x0300
+#define P2MD_4_IN		0x0000
+#define P2MD_4_OUT		0x0100
+#define P2MD_4_CMOD		0x0300	/* mode */
+
+#define	P2IN			__SYSREG(0xdb000204, u8)	/* in reg */
+#define	P2OUT			__SYSREG(0xdb000208, u8)	/* out reg */
+#define	P2TMIO			__SYSREG(0xdb00020c, u8)	/* TM pin I/O control reg */
+
+/* I/O port 3 */
+#define	P3MD			__SYSREG(0xdb000300, u16)	/* mode reg */
+#define P3MD_0			0x0003	/* mask */
+#define P3MD_0_IN		0x0000	/* input mode */
+#define P3MD_0_OUT		0x0001	/* output mode */
+#define P3MD_0_AFRXD		0x0002	/* AFR interface mode */
+#define P3MD_1			0x000c
+#define P3MD_1_IN		0x0000
+#define P3MD_1_OUT		0x0004
+#define P3MD_1_AFTXD		0x0008	/* AFR interface mode */
+#define P3MD_2			0x0030
+#define P3MD_2_IN		0x0000
+#define P3MD_2_OUT		0x0010
+#define P3MD_2_AFSCLK		0x0020	/* AFR interface mode */
+#define P3MD_3			0x00c0
+#define P3MD_3_IN		0x0000
+#define P3MD_3_OUT		0x0040
+#define P3MD_3_AFFS		0x0080	/* AFR interface mode */
+#define P3MD_4			0x0300
+#define P3MD_4_IN		0x0000
+#define P3MD_4_OUT		0x0100
+#define P3MD_4_AFEHC		0x0200	/* AFR interface mode */
+
+#define	P3IN			__SYSREG(0xdb000304, u8)	/* in reg */
+#define	P3OUT			__SYSREG(0xdb000308, u8)	/* out reg */
+
+/* I/O port 4 */
+#define	P4MD			__SYSREG(0xdb000400, u16)	/* mode reg */
+#define P4MD_0			0x0003	/* mask */
+#define P4MD_0_IN		0x0000	/* input mode */
+#define P4MD_0_OUT		0x0001	/* output mode */
+#define P4MD_0_SCL0		0x0002	/* I2C/serial mode */
+#define P4MD_1			0x000c
+#define P4MD_1_IN		0x0000
+#define P4MD_1_OUT		0x0004
+#define P4MD_1_SDA0		0x0008
+#define P4MD_2			0x0030
+#define P4MD_2_IN		0x0000
+#define P4MD_2_OUT		0x0010
+#define P4MD_2_SCL1		0x0020
+#define P4MD_3			0x00c0
+#define P4MD_3_IN		0x0000
+#define P4MD_3_OUT		0x0040
+#define P4MD_3_SDA1		0x0080
+#define P4MD_4			0x0300
+#define P4MD_4_IN		0x0000
+#define P4MD_4_OUT		0x0100
+#define P4MD_4_SBO0		0x0200
+#define P4MD_5			0x0c00
+#define P4MD_5_IN		0x0000
+#define P4MD_5_OUT		0x0400
+#define P4MD_5_SBO1		0x0800
+#define P4MD_6			0x3000
+#define P4MD_6_IN		0x0000
+#define P4MD_6_OUT		0x1000
+#define P4MD_6_SBT0		0x2000
+#define P4MD_7			0xc000
+#define P4MD_7_IN		0x0000
+#define P4MD_7_OUT		0x4000
+#define P4MD_7_SBT1		0x8000
+
+#define	P4IN			__SYSREG(0xdb000404, u8)	/* in reg */
+#define	P4OUT			__SYSREG(0xdb000408, u8)	/* out reg */
+
+/* I/O port 5 */
+#define	P5MD			__SYSREG(0xdb000500, u16)	/* mode reg */
+#define P5MD_0			0x0003	/* mask */
+#define P5MD_0_IN		0x0000	/* input mode */
+#define P5MD_0_OUT		0x0001	/* output mode */
+#define P5MD_0_IRTXD		0x0002	/* IrDA mode */
+#define P5MD_0_SOUT		0x0004	/* serial mode */
+#define P5MD_1			0x000c
+#define P5MD_1_IN		0x0000
+#define P5MD_1_OUT		0x0004
+#define P5MD_1_IRRXDS		0x0008	/* IrDA mode */
+#define P5MD_1_SIN		0x000c	/* serial mode */
+#define P5MD_2			0x0030
+#define P5MD_2_IN		0x0000
+#define P5MD_2_OUT		0x0010
+#define P5MD_2_IRRXDF		0x0020	/* IrDA mode */
+
+#define	P5IN			__SYSREG(0xdb000504, u8)	/* in reg */
+#define	P5OUT			__SYSREG(0xdb000508, u8)	/* out reg */
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_PIO_REGS_H */
diff --git a/arch/mn10300/include/asm/processor.h b/arch/mn10300/include/asm/processor.h
new file mode 100644
index 0000000..769d5ed
--- /dev/null
+++ b/arch/mn10300/include/asm/processor.h
@@ -0,0 +1,178 @@
+/* MN10300 Processor specifics
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_PROCESSOR_H
+#define _ASM_PROCESSOR_H
+
+#include <linux/threads.h>
+#include <linux/thread_info.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/cpu-regs.h>
+#include <asm/uaccess.h>
+#include <asm/current.h>
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+struct mm_struct;
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr()			\
+({						\
+	void *__pc;				\
+	asm("mov pc,%0" : "=a"(__pc));		\
+	__pc;					\
+})
+
+extern void get_mem_info(unsigned long *mem_base, unsigned long *mem_size);
+
+extern void show_registers(struct pt_regs *regs);
+
+/*
+ *  CPU type and hardware bug flags. Kept separately for each CPU.
+ *  Members of this structure are referenced in head.S, so think twice
+ *  before touching them. [mj]
+ */
+
+struct mn10300_cpuinfo {
+	int		type;
+	unsigned long	loops_per_jiffy;
+	char		hard_math;
+};
+
+extern struct mn10300_cpuinfo boot_cpu_data;
+
+#ifdef CONFIG_SMP
+#if CONFIG_NR_CPUS < 2 || CONFIG_NR_CPUS > 8
+# error Sorry, NR_CPUS should be 2 to 8
+#endif
+extern struct mn10300_cpuinfo cpu_data[];
+#define current_cpu_data cpu_data[smp_processor_id()]
+#else  /* CONFIG_SMP */
+#define cpu_data &boot_cpu_data
+#define current_cpu_data boot_cpu_data
+#endif /* CONFIG_SMP */
+
+extern void identify_cpu(struct mn10300_cpuinfo *);
+extern void print_cpu_info(struct mn10300_cpuinfo *);
+extern void dodgy_tsc(void);
+
+#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
+
+/*
+ * User space process size: 1.75GB (default).
+ */
+#define TASK_SIZE		0x70000000
+
+/*
+ * Where to put the userspace stack by default
+ */
+#define STACK_TOP		0x70000000
+#define STACK_TOP_MAX		STACK_TOP
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE	0x30000000
+
+struct fpu_state_struct {
+	unsigned long	fs[32];		/* fpu registers */
+	unsigned long	fpcr;		/* fpu control register */
+};
+
+struct thread_struct {
+	struct pt_regs		*uregs;		/* userspace register frame */
+	unsigned long		pc;		/* kernel PC */
+	unsigned long		sp;		/* kernel SP */
+	unsigned long		a3;		/* kernel FP */
+	unsigned long		wchan;
+	unsigned long		usp;
+	unsigned long		fpu_flags;
+#define THREAD_USING_FPU	0x00000001	/* T if this task is using the FPU */
+#define THREAD_HAS_FPU		0x00000002	/* T if this task owns the FPU right now */
+	struct fpu_state_struct	fpu_state;
+};
+
+#define INIT_THREAD		\
+{				\
+	.uregs	= init_uregs,	\
+	.pc	= 0,		\
+	.sp	= 0,		\
+	.a3	= 0,		\
+	.wchan	= 0,		\
+}
+
+#define INIT_MMAP \
+{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, \
+  NULL, NULL }
+
+/*
+ * do necessary setup to start up a newly executed thread
+ */
+static inline void start_thread(struct pt_regs *regs,
+				unsigned long new_pc, unsigned long new_sp)
+{
+	regs->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;
+	regs->pc = new_pc;
+	regs->sp = new_sp;
+}
+
+
+/* Free all resources held by a thread. */
+extern void release_thread(struct task_struct *);
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define task_pt_regs(task) ((task)->thread.uregs)
+#define KSTK_EIP(task) (task_pt_regs(task)->pc)
+#define KSTK_ESP(task) (task_pt_regs(task)->sp)
+
+#define KSTK_TOP(info)				\
+({						\
+	(unsigned long)(info) + THREAD_SIZE;	\
+})
+
+#define ARCH_HAS_PREFETCH
+#define ARCH_HAS_PREFETCHW
+
+static inline void prefetch(const void *x)
+{
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+#ifdef CONFIG_MN10300_PROC_MN103E010
+	asm volatile ("nop; nop; dcpf (%0)" : : "r"(x));
+#else
+	asm volatile ("dcpf (%0)" : : "r"(x));
+#endif
+#endif
+}
+
+static inline void prefetchw(const void *x)
+{
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+#ifdef CONFIG_MN10300_PROC_MN103E010
+	asm volatile ("nop; nop; dcpf (%0)" : : "r"(x));
+#else
+	asm volatile ("dcpf (%0)" : : "r"(x));
+#endif
+#endif
+}
+
+#endif /* _ASM_PROCESSOR_H */
diff --git a/arch/mn10300/include/asm/ptrace.h b/arch/mn10300/include/asm/ptrace.h
new file mode 100644
index 0000000..838a383
--- /dev/null
+++ b/arch/mn10300/include/asm/ptrace.h
@@ -0,0 +1,26 @@
+/* MN10300 Exception frame layout and ptrace constants
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_PTRACE_H
+#define _ASM_PTRACE_H
+
+#include <uapi/asm/ptrace.h>
+
+
+#define user_mode(regs)			(((regs)->epsw & EPSW_nSL) == EPSW_nSL)
+#define instruction_pointer(regs)	((regs)->pc)
+#define user_stack_pointer(regs)	((regs)->sp)
+#define current_pt_regs()		current_frame()
+
+#define arch_has_single_step()	(1)
+
+#define profile_pc(regs) ((regs)->pc)
+
+#endif /* _ASM_PTRACE_H */
diff --git a/arch/mn10300/include/asm/reset-regs.h b/arch/mn10300/include/asm/reset-regs.h
new file mode 100644
index 0000000..8ca2a42
--- /dev/null
+++ b/arch/mn10300/include/asm/reset-regs.h
@@ -0,0 +1,60 @@
+/* MN10300 Reset controller and watchdog timer definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_RESET_REGS_H
+#define _ASM_RESET_REGS_H
+
+#include <asm/cpu-regs.h>
+#include <asm/exceptions.h>
+
+#ifdef __KERNEL__
+
+/*
+ * watchdog timer registers
+ */
+#define WDBC			__SYSREGC(0xc0001000, u8) /* watchdog binary counter reg */
+
+#define WDCTR			__SYSREG(0xc0001002, u8)  /* watchdog timer control reg */
+#define WDCTR_WDCK		0x07	/* clock source selection */
+#define WDCTR_WDCK_256th	0x00	/* - OSCI/256 */
+#define WDCTR_WDCK_1024th	0x01	/* - OSCI/1024 */
+#define WDCTR_WDCK_2048th	0x02	/* - OSCI/2048 */
+#define WDCTR_WDCK_16384th	0x03	/* - OSCI/16384 */
+#define WDCTR_WDCK_65536th	0x04	/* - OSCI/65536 */
+#define WDCTR_WDRST		0x40	/* binary counter reset */
+#define WDCTR_WDCNE		0x80	/* watchdog timer enable */
+
+#define RSTCTR			__SYSREG(0xc0001004, u8) /* reset control reg */
+#define RSTCTR_CHIPRST		0x01	/* chip reset */
+#define RSTCTR_DBFRST		0x02	/* double fault reset flag */
+#define RSTCTR_WDTRST		0x04	/* watchdog timer reset flag */
+#define RSTCTR_WDREN		0x08	/* watchdog timer reset enable */
+
+#ifndef __ASSEMBLY__
+
+static inline void mn10300_proc_hard_reset(void)
+{
+	RSTCTR &= ~RSTCTR_CHIPRST;
+	RSTCTR |= RSTCTR_CHIPRST;
+}
+
+extern unsigned int watchdog_alert_counter[];
+
+extern void watchdog_go(void);
+extern asmlinkage void watchdog_handler(void);
+extern asmlinkage
+void watchdog_interrupt(struct pt_regs *, enum exception_code);
+
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_RESET_REGS_H */
diff --git a/arch/mn10300/include/asm/rtc-regs.h b/arch/mn10300/include/asm/rtc-regs.h
new file mode 100644
index 0000000..c42deef
--- /dev/null
+++ b/arch/mn10300/include/asm/rtc-regs.h
@@ -0,0 +1,86 @@
+/* MN10300 on-chip Real-Time Clock registers
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_RTC_REGS_H
+#define _ASM_RTC_REGS_H
+
+#include <asm/intctl-regs.h>
+
+#ifdef __KERNEL__
+
+#define RTSCR			__SYSREG(0xd8600000, u8) /* RTC seconds count reg */
+#define RTSAR			__SYSREG(0xd8600001, u8) /* RTC seconds alarm reg */
+#define RTMCR			__SYSREG(0xd8600002, u8) /* RTC minutes count reg */
+#define RTMAR			__SYSREG(0xd8600003, u8) /* RTC minutes alarm reg */
+#define RTHCR			__SYSREG(0xd8600004, u8) /* RTC hours count reg */
+#define RTHAR			__SYSREG(0xd8600005, u8) /* RTC hours alarm reg */
+#define RTDWCR			__SYSREG(0xd8600006, u8) /* RTC day of the week count reg */
+#define RTDMCR			__SYSREG(0xd8600007, u8) /* RTC days count reg */
+#define RTMTCR			__SYSREG(0xd8600008, u8) /* RTC months count reg */
+#define RTYCR			__SYSREG(0xd8600009, u8) /* RTC years count reg */
+
+#define RTCRA			__SYSREG(0xd860000a, u8)/* RTC control reg A */
+#define RTCRA_RS		0x0f	/* periodic timer interrupt cycle setting */
+#define RTCRA_RS_NONE		0x00	/* - off */
+#define RTCRA_RS_3_90625ms	0x01	/* - 3.90625ms	(1/256s) */
+#define RTCRA_RS_7_8125ms	0x02	/* - 7.8125ms	(1/128s) */
+#define RTCRA_RS_122_070us	0x03	/* - 122.070us	(1/8192s) */
+#define RTCRA_RS_244_141us	0x04	/* - 244.141us	(1/4096s) */
+#define RTCRA_RS_488_281us	0x05	/* - 488.281us	(1/2048s) */
+#define RTCRA_RS_976_5625us	0x06	/* - 976.5625us	(1/1024s) */
+#define RTCRA_RS_1_953125ms	0x07	/* - 1.953125ms	(1/512s) */
+#define RTCRA_RS_3_90624ms	0x08	/* - 3.90624ms	(1/256s) */
+#define RTCRA_RS_7_8125ms_b	0x09	/* - 7.8125ms	(1/128s) */
+#define RTCRA_RS_15_625ms	0x0a	/* - 15.625ms	(1/64s) */
+#define RTCRA_RS_31_25ms	0x0b	/* - 31.25ms	(1/32s) */
+#define RTCRA_RS_62_5ms		0x0c	/* - 62.5ms	(1/16s) */
+#define RTCRA_RS_125ms		0x0d	/* - 125ms	(1/8s) */
+#define RTCRA_RS_250ms		0x0e	/* - 250ms	(1/4s) */
+#define RTCRA_RS_500ms		0x0f	/* - 500ms	(1/2s) */
+#define RTCRA_DVR		0x40	/* divider reset */
+#define RTCRA_UIP		0x80	/* clock update flag */
+
+#define RTCRB			__SYSREG(0xd860000b, u8) /* RTC control reg B */
+#define RTCRB_DSE		0x01	/* daylight savings time enable */
+#define RTCRB_TM		0x02	/* time format */
+#define RTCRB_TM_12HR		0x00	/* - 12 hour format */
+#define RTCRB_TM_24HR		0x02	/* - 24 hour format */
+#define RTCRB_DM		0x04	/* numeric value format */
+#define RTCRB_DM_BCD		0x00	/* - BCD */
+#define RTCRB_DM_BINARY		0x04	/* - binary */
+#define RTCRB_UIE		0x10	/* update interrupt disable */
+#define RTCRB_AIE		0x20	/* alarm interrupt disable */
+#define RTCRB_PIE		0x40	/* periodic interrupt disable */
+#define RTCRB_SET		0x80	/* clock update enable */
+
+#define RTSRC			__SYSREG(0xd860000c, u8) /* RTC status reg C */
+#define RTSRC_UF		0x10	/* update end interrupt flag */
+#define RTSRC_AF		0x20	/* alarm interrupt flag */
+#define RTSRC_PF		0x40	/* periodic interrupt flag */
+#define RTSRC_IRQF		0x80	/* interrupt flag */
+
+#define RTIRQ			32
+#define RTICR			GxICR(RTIRQ)
+
+/*
+ * MC146818 RTC compatibility defs for the MN10300 on-chip RTC
+ */
+#define RTC_PORT(x)		0xd8600000
+#define RTC_ALWAYS_BCD		1	/* RTC operates in binary mode */
+
+#define CMOS_READ(addr)		__SYSREG(0xd8600000 + (addr), u8)
+#define CMOS_WRITE(val, addr)	\
+	do { __SYSREG(0xd8600000 + (addr), u8) = val; } while (0)
+
+#define RTC_IRQ			RTIRQ
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_RTC_REGS_H */
diff --git a/arch/mn10300/include/asm/rtc.h b/arch/mn10300/include/asm/rtc.h
new file mode 100644
index 0000000..6c14bb1
--- /dev/null
+++ b/arch/mn10300/include/asm/rtc.h
@@ -0,0 +1,30 @@
+/* MN10300 Real time clock definitions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_RTC_H
+#define _ASM_RTC_H
+
+#ifdef CONFIG_MN10300_RTC
+
+#include <linux/init.h>
+
+extern void __init calibrate_clock(void);
+
+#else /* !CONFIG_MN10300_RTC */
+
+static inline void calibrate_clock(void)
+{
+}
+
+#endif /* !CONFIG_MN10300_RTC */
+
+#include <asm-generic/rtc.h>
+
+#endif /* _ASM_RTC_H */
diff --git a/arch/mn10300/include/asm/rwlock.h b/arch/mn10300/include/asm/rwlock.h
new file mode 100644
index 0000000..6d594d4
--- /dev/null
+++ b/arch/mn10300/include/asm/rwlock.h
@@ -0,0 +1,125 @@
+/*
+ * Helpers used by both rw spinlocks and rw semaphores.
+ *
+ * Based in part on code from semaphore.h and
+ * spinlock.h Copyright 1996 Linus Torvalds.
+ *
+ * Copyright 1999 Red Hat, Inc.
+ *
+ * Written by Benjamin LaHaise.
+ *
+ * Modified by Matsushita Electric Industrial Co., Ltd.
+ * Modifications:
+ * 13-Nov-2006 MEI Temporarily delete lock functions for SMP support.
+ *
+ * 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.
+ */
+#ifndef _ASM_RWLOCK_H
+#define _ASM_RWLOCK_H
+
+#define RW_LOCK_BIAS		 0x01000000
+
+#ifndef CONFIG_SMP
+
+typedef struct { unsigned long a[100]; } __dummy_lock_t;
+#define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
+
+#define RW_LOCK_BIAS_STR	"0x01000000"
+
+#define __build_read_lock_ptr(rw, helper)				\
+	do {								\
+		asm volatile(						\
+			"	mov	(%0),d3			\n"	\
+			"	sub	1,d3			\n"	\
+			"	mov	d3,(%0)			\n"	\
+			"	blt	1f			\n"	\
+			"	bra	2f			\n"	\
+			"1:	jmp	3f			\n"	\
+			"2:					\n"	\
+			"	.section .text.lock,\"ax\"	\n"	\
+			"3:	call	"helper"[],0		\n"	\
+			"	jmp	2b			\n"	\
+			"	.previous"				\
+			:						\
+			: "d" (rw)					\
+			: "memory", "d3", "cc");			\
+	} while (0)
+
+#define __build_read_lock_const(rw, helper)				\
+	do {								\
+		asm volatile(						\
+			"	mov	(%0),d3			\n"	\
+			"	sub	1,d3			\n"	\
+			"	mov	d3,(%0)			\n"	\
+			"	blt	1f			\n"	\
+			"	bra	2f			\n"	\
+			"1:	jmp	3f			\n"	\
+			"2:					\n"	\
+			"	.section .text.lock,\"ax\"	\n"	\
+			"3:	call	"helper"[],0		\n"	\
+			"	jmp	2b			\n"	\
+			"	.previous"				\
+			:						\
+			: "d" (rw)					\
+			: "memory", "d3", "cc");			\
+	} while (0)
+
+#define __build_read_lock(rw, helper) \
+	do {								\
+		if (__builtin_constant_p(rw))				\
+			__build_read_lock_const(rw, helper);		\
+		else							\
+			__build_read_lock_ptr(rw, helper);		\
+	} while (0)
+
+#define __build_write_lock_ptr(rw, helper)				\
+	do {								\
+		asm volatile(						\
+			"	mov	(%0),d3			\n"	\
+			"	sub	1,d3			\n"	\
+			"	mov	d3,(%0)			\n"	\
+			"	blt	1f			\n"	\
+			"	bra	2f			\n"	\
+			"1:	jmp	3f			\n"	\
+			"2:					\n"	\
+			"	.section .text.lock,\"ax\"	\n"	\
+			"3:	call	"helper"[],0		\n"	\
+			"	jmp	2b			\n"	\
+			"	.previous"				\
+			:						\
+			: "d" (rw)					\
+			: "memory", "d3", "cc");			\
+	} while (0)
+
+#define __build_write_lock_const(rw, helper)				\
+	do {								\
+		asm volatile(						\
+			"	mov	(%0),d3			\n"	\
+			"	sub	1,d3			\n"	\
+			"	mov	d3,(%0)			\n"	\
+			"	blt	1f			\n"	\
+			"	bra	2f			\n"	\
+			"1:	jmp	3f			\n"	\
+			"2:					\n"	\
+			"	.section .text.lock,\"ax\"	\n"	\
+			"3:	call	"helper"[],0		\n"	\
+			"	jmp	2b			\n"	\
+			"	.previous"				\
+			:						\
+			: "d" (rw)					\
+			: "memory", "d3", "cc");			\
+	} while (0)
+
+#define __build_write_lock(rw, helper)					\
+	do {								\
+		if (__builtin_constant_p(rw))				\
+			__build_write_lock_const(rw, helper);		\
+		else							\
+			__build_write_lock_ptr(rw, helper);		\
+	} while (0)
+
+#endif /* CONFIG_SMP */
+#endif /* _ASM_RWLOCK_H */
diff --git a/arch/mn10300/include/asm/serial-regs.h b/arch/mn10300/include/asm/serial-regs.h
new file mode 100644
index 0000000..8320cda
--- /dev/null
+++ b/arch/mn10300/include/asm/serial-regs.h
@@ -0,0 +1,191 @@
+/* MN10300 on-board serial port module registers
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_SERIAL_REGS_H
+#define _ASM_SERIAL_REGS_H
+
+#include <asm/cpu-regs.h>
+#include <asm/intctl-regs.h>
+
+#ifdef __KERNEL__
+
+/* serial port 0 */
+#define	SC0CTR			__SYSREG(0xd4002000, u16)	/* control reg */
+#define	SC01CTR_CK		0x0007	/* clock source select */
+#define	SC01CTR_CK_IOCLK_8	0x0001	/* - 1/8 IOCLK */
+#define	SC01CTR_CK_IOCLK_32	0x0002	/* - 1/32 IOCLK */
+#define	SC01CTR_CK_EXTERN_8	0x0006	/* - 1/8 external closk */
+#define	SC01CTR_CK_EXTERN	0x0007	/* - external closk */
+#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
+#define	SC0CTR_CK_TM8UFLOW_8	0x0000	/* - 1/8 timer 8 underflow (serial port 0 only) */
+#define	SC0CTR_CK_TM2UFLOW_2	0x0003	/* - 1/2 timer 2 underflow (serial port 0 only) */
+#define	SC0CTR_CK_TM0UFLOW_8	0x0004	/* - 1/8 timer 0 underflow (serial port 0 only) */
+#define	SC0CTR_CK_TM2UFLOW_8	0x0005	/* - 1/8 timer 2 underflow (serial port 0 only) */
+#define	SC1CTR_CK_TM9UFLOW_8	0x0000	/* - 1/8 timer 9 underflow (serial port 1 only) */
+#define	SC1CTR_CK_TM3UFLOW_2	0x0003	/* - 1/2 timer 3 underflow (serial port 1 only) */
+#define	SC1CTR_CK_TM1UFLOW_8	0x0004	/* - 1/8 timer 1 underflow (serial port 1 only) */
+#define	SC1CTR_CK_TM3UFLOW_8	0x0005	/* - 1/8 timer 3 underflow (serial port 1 only) */
+#else  /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+#define	SC0CTR_CK_TM8UFLOW_8	0x0000	/* - 1/8 timer 8 underflow (serial port 0 only) */
+#define	SC0CTR_CK_TM0UFLOW_8	0x0004	/* - 1/8 timer 0 underflow (serial port 0 only) */
+#define	SC0CTR_CK_TM2UFLOW_8	0x0005	/* - 1/8 timer 2 underflow (serial port 0 only) */
+#define	SC1CTR_CK_TM12UFLOW_8	0x0000	/* - 1/8 timer 12 underflow (serial port 1 only) */
+#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+#define	SC01CTR_STB		0x0008	/* stop bit select */
+#define	SC01CTR_STB_1BIT	0x0000	/* - 1 stop bit */
+#define	SC01CTR_STB_2BIT	0x0008	/* - 2 stop bits */
+#define	SC01CTR_PB		0x0070	/* parity bit select */
+#define	SC01CTR_PB_NONE		0x0000	/* - no parity */
+#define	SC01CTR_PB_FIXED0	0x0040	/* - fixed at 0 */
+#define	SC01CTR_PB_FIXED1	0x0050	/* - fixed at 1 */
+#define	SC01CTR_PB_EVEN		0x0060	/* - even parity */
+#define	SC01CTR_PB_ODD		0x0070	/* - odd parity */
+#define	SC01CTR_CLN		0x0080	/* character length */
+#define	SC01CTR_CLN_7BIT	0x0000	/* - 7 bit chars */
+#define	SC01CTR_CLN_8BIT	0x0080	/* - 8 bit chars */
+#define	SC01CTR_TOE		0x0100	/* T input output enable */
+#define	SC01CTR_OD		0x0200	/* bit order select */
+#define	SC01CTR_OD_LSBFIRST	0x0000	/* - LSB first */
+#define	SC01CTR_OD_MSBFIRST	0x0200	/* - MSB first */
+#define	SC01CTR_MD		0x0c00	/* mode select */
+#define SC01CTR_MD_STST_SYNC	0x0000	/* - start-stop synchronous */
+#define SC01CTR_MD_CLOCK_SYNC1	0x0400	/* - clock synchronous 1 */
+#define SC01CTR_MD_I2C		0x0800	/* - I2C mode */
+#define SC01CTR_MD_CLOCK_SYNC2	0x0c00	/* - clock synchronous 2 */
+#define	SC01CTR_IIC		0x1000	/* I2C mode select */
+#define	SC01CTR_BKE		0x2000	/* break transmit enable */
+#define	SC01CTR_RXE		0x4000	/* receive enable */
+#define	SC01CTR_TXE		0x8000	/* transmit enable */
+
+#define	SC0ICR			__SYSREG(0xd4002004, u8)	/* interrupt control reg */
+#define SC01ICR_DMD		0x80	/* output data mode */
+#define SC01ICR_TD		0x20	/* transmit DMA trigger cause */
+#define SC01ICR_TI		0x10	/* transmit interrupt cause */
+#define SC01ICR_RES		0x04	/* receive error select */
+#define SC01ICR_RI		0x01	/* receive interrupt cause */
+
+#define	SC0TXB			__SYSREG(0xd4002008, u8)	/* transmit buffer reg */
+#define	SC0RXB			__SYSREG(0xd4002009, u8)	/* receive buffer reg */
+
+#define	SC0STR			__SYSREG(0xd400200c, u16)	/* status reg */
+#define SC01STR_OEF		0x0001	/* overrun error found */
+#define SC01STR_PEF		0x0002	/* parity error found */
+#define SC01STR_FEF		0x0004	/* framing error found */
+#define SC01STR_RBF		0x0010	/* receive buffer status */
+#define SC01STR_TBF		0x0020	/* transmit buffer status */
+#define SC01STR_RXF		0x0040	/* receive status */
+#define SC01STR_TXF		0x0080	/* transmit status */
+#define SC01STR_STF		0x0100	/* I2C start sequence found */
+#define SC01STR_SPF		0x0200	/* I2C stop sequence found */
+
+#define SC0RXIRQ		20	/* timer 0 Receive IRQ */
+#define SC0TXIRQ		21	/* timer 0 Transmit IRQ */
+
+#define	SC0RXICR		GxICR(SC0RXIRQ)	/* serial 0 receive intr ctrl reg */
+#define	SC0TXICR		GxICR(SC0TXIRQ)	/* serial 0 transmit intr ctrl reg */
+
+/* serial port 1 */
+#define	SC1CTR			__SYSREG(0xd4002010, u16)	/* serial port 1 control */
+#define	SC1ICR			__SYSREG(0xd4002014, u8)	/* interrupt control reg */
+#define	SC1TXB			__SYSREG(0xd4002018, u8)	/* transmit buffer reg */
+#define	SC1RXB			__SYSREG(0xd4002019, u8)	/* receive buffer reg */
+#define	SC1STR			__SYSREG(0xd400201c, u16)	/* status reg */
+
+#define SC1RXIRQ		22	/* timer 1 Receive IRQ */
+#define SC1TXIRQ		23	/* timer 1 Transmit IRQ */
+
+#define	SC1RXICR		GxICR(SC1RXIRQ)	/* serial 1 receive intr ctrl reg */
+#define	SC1TXICR		GxICR(SC1TXIRQ)	/* serial 1 transmit intr ctrl reg */
+
+/* serial port 2 */
+#define	SC2CTR			__SYSREG(0xd4002020, u16)	/* control reg */
+#ifdef CONFIG_AM33_2
+#define	SC2CTR_CK		0x0003	/* clock source select */
+#define	SC2CTR_CK_TM10UFLOW	0x0000	/* - timer 10 underflow */
+#define	SC2CTR_CK_TM2UFLOW	0x0001	/* - timer 2 underflow */
+#define	SC2CTR_CK_EXTERN	0x0002	/* - external closk */
+#define	SC2CTR_CK_TM3UFLOW	0x0003	/* - timer 3 underflow */
+#else  /* CONFIG_AM33_2 */
+#define	SC2CTR_CK		0x0007	/* clock source select */
+#define	SC2CTR_CK_TM9UFLOW_8	0x0000	/* - 1/8 timer 9 underflow */
+#define	SC2CTR_CK_IOCLK_8	0x0001	/* - 1/8 IOCLK */
+#define	SC2CTR_CK_IOCLK_32	0x0002	/* - 1/32 IOCLK */
+#define	SC2CTR_CK_TM3UFLOW_2	0x0003	/* - 1/2 timer 3 underflow */
+#define	SC2CTR_CK_TM1UFLOW_8	0x0004	/* - 1/8 timer 1 underflow */
+#define	SC2CTR_CK_TM3UFLOW_8	0x0005	/* - 1/8 timer 3 underflow */
+#define	SC2CTR_CK_EXTERN_8	0x0006	/* - 1/8 external closk */
+#define	SC2CTR_CK_EXTERN	0x0007	/* - external closk */
+#endif /* CONFIG_AM33_2 */
+#define	SC2CTR_STB		0x0008	/* stop bit select */
+#define	SC2CTR_STB_1BIT		0x0000	/* - 1 stop bit */
+#define	SC2CTR_STB_2BIT		0x0008	/* - 2 stop bits */
+#define	SC2CTR_PB		0x0070	/* parity bit select */
+#define	SC2CTR_PB_NONE		0x0000	/* - no parity */
+#define	SC2CTR_PB_FIXED0	0x0040	/* - fixed at 0 */
+#define	SC2CTR_PB_FIXED1	0x0050	/* - fixed at 1 */
+#define	SC2CTR_PB_EVEN		0x0060	/* - even parity */
+#define	SC2CTR_PB_ODD		0x0070	/* - odd parity */
+#define	SC2CTR_CLN		0x0080	/* character length */
+#define	SC2CTR_CLN_7BIT		0x0000	/* - 7 bit chars */
+#define	SC2CTR_CLN_8BIT		0x0080	/* - 8 bit chars */
+#define	SC2CTR_TWE		0x0100	/* transmit wait enable (enable XCTS control) */
+#define	SC2CTR_OD		0x0200	/* bit order select */
+#define	SC2CTR_OD_LSBFIRST	0x0000	/* - LSB first */
+#define	SC2CTR_OD_MSBFIRST	0x0200	/* - MSB first */
+#define	SC2CTR_TWS		0x1000	/* transmit wait select */
+#define	SC2CTR_TWS_XCTS_HIGH	0x0000	/* - interrupt TX when XCTS high */
+#define	SC2CTR_TWS_XCTS_LOW	0x1000	/* - interrupt TX when XCTS low */
+#define	SC2CTR_BKE		0x2000	/* break transmit enable */
+#define	SC2CTR_RXE		0x4000	/* receive enable */
+#define	SC2CTR_TXE		0x8000	/* transmit enable */
+
+#define	SC2ICR			__SYSREG(0xd4002024, u8)	/* interrupt control reg */
+#define SC2ICR_TD		0x20	/* transmit DMA trigger cause */
+#define SC2ICR_TI		0x10	/* transmit interrupt cause */
+#define SC2ICR_RES		0x04	/* receive error select */
+#define SC2ICR_RI		0x01	/* receive interrupt cause */
+
+#define	SC2TXB			__SYSREG(0xd4002028, u8)	/* transmit buffer reg */
+#define	SC2RXB			__SYSREG(0xd4002029, u8)	/* receive buffer reg */
+
+#ifdef CONFIG_AM33_2
+#define	SC2STR			__SYSREG(0xd400202c, u8)	/* status reg */
+#else  /* CONFIG_AM33_2 */
+#define	SC2STR			__SYSREG(0xd400202c, u16)	/* status reg */
+#endif /* CONFIG_AM33_2 */
+#define SC2STR_OEF		0x0001	/* overrun error found */
+#define SC2STR_PEF		0x0002	/* parity error found */
+#define SC2STR_FEF		0x0004	/* framing error found */
+#define SC2STR_CTS		0x0008	/* XCTS input pin status (0 means high) */
+#define SC2STR_RBF		0x0010	/* receive buffer status */
+#define SC2STR_TBF		0x0020	/* transmit buffer status */
+#define SC2STR_RXF		0x0040	/* receive status */
+#define SC2STR_TXF		0x0080	/* transmit status */
+
+#ifdef CONFIG_AM33_2
+#define	SC2TIM			__SYSREG(0xd400202d, u8)	/* status reg */
+#endif
+
+#ifdef CONFIG_AM33_2
+#define SC2RXIRQ		24	/* serial 2 Receive IRQ */
+#define SC2TXIRQ		25	/* serial 2 Transmit IRQ */
+#else  /* CONFIG_AM33_2 */
+#define SC2RXIRQ		68	/* serial 2 Receive IRQ */
+#define SC2TXIRQ		69	/* serial 2 Transmit IRQ */
+#endif /* CONFIG_AM33_2 */
+
+#define	SC2RXICR		GxICR(SC2RXIRQ)	/* serial 2 receive intr ctrl reg */
+#define	SC2TXICR		GxICR(SC2TXIRQ)	/* serial 2 transmit intr ctrl reg */
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_SERIAL_REGS_H */
diff --git a/arch/mn10300/include/asm/serial.h b/arch/mn10300/include/asm/serial.h
new file mode 100644
index 0000000..c199021
--- /dev/null
+++ b/arch/mn10300/include/asm/serial.h
@@ -0,0 +1,36 @@
+/* Standard UART definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_SERIAL_H
+#define _ASM_SERIAL_H
+
+/* Standard COM flags (except for COM4, because of the 8514 problem) */
+#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
+#define STD_COM_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS	ASYNC_BOOT_AUTOCONF
+#endif
+
+#ifdef CONFIG_SERIAL_8250_MANY_PORTS
+#define FOURPORT_FLAGS	ASYNC_FOURPORT
+#define ACCENT_FLAGS	0
+#define BOCA_FLAGS	0
+#define HUB6_FLAGS	0
+#define RS_TABLE_SIZE	64
+#else
+#define RS_TABLE_SIZE
+#endif
+
+#include <unit/serial.h>
+
+#endif /* _ASM_SERIAL_H */
diff --git a/arch/mn10300/include/asm/setup.h b/arch/mn10300/include/asm/setup.h
new file mode 100644
index 0000000..fb02455
--- /dev/null
+++ b/arch/mn10300/include/asm/setup.h
@@ -0,0 +1,18 @@
+/* MN10300 Setup declarations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_SETUP_H
+#define _ASM_SETUP_H
+
+#include <uapi/asm/setup.h>
+
+extern void __init unit_setup(void);
+extern void __init unit_init_IRQ(void);
+#endif /* _ASM_SETUP_H */
diff --git a/arch/mn10300/include/asm/shmparam.h b/arch/mn10300/include/asm/shmparam.h
new file mode 100644
index 0000000..ab666ed
--- /dev/null
+++ b/arch/mn10300/include/asm/shmparam.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_SHMPARAM_H
+#define _ASM_SHMPARAM_H
+
+#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
+
+#endif /* _ASM_SHMPARAM_H */
diff --git a/arch/mn10300/include/asm/signal.h b/arch/mn10300/include/asm/signal.h
new file mode 100644
index 0000000..214ff5e
--- /dev/null
+++ b/arch/mn10300/include/asm/signal.h
@@ -0,0 +1,33 @@
+/* MN10300 Signal definitions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_SIGNAL_H
+#define _ASM_SIGNAL_H
+
+#include <uapi/asm/signal.h>
+
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+#define _NSIG		64
+#define _NSIG_BPW	32
+#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t;		/* at least 32 bits */
+
+typedef struct {
+	unsigned long	sig[_NSIG_WORDS];
+} sigset_t;
+
+#define __ARCH_HAS_SA_RESTORER
+
+#include <asm/sigcontext.h>
+
+#endif /* _ASM_SIGNAL_H */
diff --git a/arch/mn10300/include/asm/smp.h b/arch/mn10300/include/asm/smp.h
new file mode 100644
index 0000000..56c4241
--- /dev/null
+++ b/arch/mn10300/include/asm/smp.h
@@ -0,0 +1,109 @@
+/* MN10300 SMP support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * Modified by Matsushita Electric Industrial Co., Ltd.
+ * Modifications:
+ *  13-Nov-2006 MEI Define IPI-IRQ number and add inline/macro function
+ *                  for SMP support.
+ *  22-Jan-2007 MEI Add the define related to SMP_BOOT_IRQ.
+ *  23-Feb-2007 MEI Add the define related to SMP icahce invalidate.
+ *  23-Jun-2008 MEI Delete INTC_IPI.
+ *  22-Jul-2008 MEI Add smp_nmi_call_function and related defines.
+ *  04-Aug-2008 MEI Delete USE_DOIRQ_CACHE_IPI.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_SMP_H
+#define _ASM_SMP_H
+
+#ifndef __ASSEMBLY__
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/thread_info.h>
+#endif
+
+#ifdef CONFIG_SMP
+#include <proc/smp-regs.h>
+
+#define RESCHEDULE_IPI		63
+#define CALL_FUNC_SINGLE_IPI	192
+#define LOCAL_TIMER_IPI		193
+#define FLUSH_CACHE_IPI		194
+#define CALL_FUNCTION_NMI_IPI	195
+#define DEBUGGER_NMI_IPI	196
+
+#define SMP_BOOT_IRQ		195
+
+#define RESCHEDULE_GxICR_LV	GxICR_LEVEL_6
+#define CALL_FUNCTION_GxICR_LV	GxICR_LEVEL_4
+#define LOCAL_TIMER_GxICR_LV	GxICR_LEVEL_4
+#define FLUSH_CACHE_GxICR_LV	GxICR_LEVEL_0
+#define SMP_BOOT_GxICR_LV	GxICR_LEVEL_0
+#define DEBUGGER_GxICR_LV	CONFIG_DEBUGGER_IRQ_LEVEL
+
+#define TIME_OUT_COUNT_BOOT_IPI	100
+#define DELAY_TIME_BOOT_IPI	75000
+
+
+#ifndef __ASSEMBLY__
+
+/**
+ * raw_smp_processor_id - Determine the raw CPU ID of the CPU running it
+ *
+ * What we really want to do is to use the CPUID hardware CPU register to get
+ * this information, but accesses to that aren't cached, and run at system bus
+ * speed, not CPU speed.  A copy of this value is, however, stored in the
+ * thread_info struct, and that can be cached.
+ *
+ * An alternate way of dealing with this could be to use the EPSW.S bits to
+ * cache this information for systems with up to four CPUs.
+ */
+#define arch_smp_processor_id()	(CPUID)
+#if 0
+#define raw_smp_processor_id()	(arch_smp_processor_id())
+#else
+#define raw_smp_processor_id()	(current_thread_info()->cpu)
+#endif
+
+static inline int cpu_logical_map(int cpu)
+{
+	return cpu;
+}
+
+static inline int cpu_number_map(int cpu)
+{
+	return cpu;
+}
+
+
+extern cpumask_t cpu_boot_map;
+
+extern void smp_init_cpus(void);
+extern void smp_cache_interrupt(void);
+extern void send_IPI_allbutself(int irq);
+extern int smp_nmi_call_function(void (*func)(void *), void *info, int wait);
+
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+#ifdef CONFIG_HOTPLUG_CPU
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
+#endif /* CONFIG_HOTPLUG_CPU */
+
+#endif /* __ASSEMBLY__ */
+#else /* CONFIG_SMP */
+#ifndef __ASSEMBLY__
+
+static inline void smp_init_cpus(void) {}
+#define raw_smp_processor_id() 0
+
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_SMP */
+
+#endif /* _ASM_SMP_H */
diff --git a/arch/mn10300/include/asm/smsc911x.h b/arch/mn10300/include/asm/smsc911x.h
new file mode 100644
index 0000000..2fcd108
--- /dev/null
+++ b/arch/mn10300/include/asm/smsc911x.h
@@ -0,0 +1 @@
+#include <unit/smsc911x.h>
diff --git a/arch/mn10300/include/asm/spinlock.h b/arch/mn10300/include/asm/spinlock.h
new file mode 100644
index 0000000..1ae580f
--- /dev/null
+++ b/arch/mn10300/include/asm/spinlock.h
@@ -0,0 +1,193 @@
+/* MN10300 spinlock support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_SPINLOCK_H
+#define _ASM_SPINLOCK_H
+
+#include <linux/atomic.h>
+#include <asm/rwlock.h>
+#include <asm/page.h>
+
+/*
+ * Simple spin lock operations.  There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
+#define arch_spin_is_locked(x)	(*(volatile signed char *)(&(x)->slock) != 0)
+#define arch_spin_unlock_wait(x) do { barrier(); } while (arch_spin_is_locked(x))
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+	asm volatile(
+		"	bclr	1,(0,%0)	\n"
+		:
+		: "a"(&lock->slock)
+		: "memory", "cc");
+}
+
+static inline int arch_spin_trylock(arch_spinlock_t *lock)
+{
+	int ret;
+
+	asm volatile(
+		"	mov	1,%0		\n"
+		"	bset	%0,(%1)		\n"
+		"	bne	1f		\n"
+		"	clr	%0		\n"
+		"1:	xor	1,%0		\n"
+		: "=d"(ret)
+		: "a"(&lock->slock)
+		: "memory", "cc");
+
+	return ret;
+}
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+	asm volatile(
+		"1:	bset	1,(0,%0)	\n"
+		"	bne	1b		\n"
+		:
+		: "a"(&lock->slock)
+		: "memory", "cc");
+}
+
+static inline void arch_spin_lock_flags(arch_spinlock_t *lock,
+					 unsigned long flags)
+{
+	int temp;
+
+	asm volatile(
+		"1:	bset	1,(0,%2)	\n"
+		"	beq	3f		\n"
+		"	mov	%1,epsw		\n"
+		"2:	mov	(0,%2),%0	\n"
+		"	or	%0,%0		\n"
+		"	bne	2b		\n"
+		"	mov	%3,%0		\n"
+		"	mov	%0,epsw		\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	bra	1b\n"
+		"3:				\n"
+		: "=&d" (temp)
+		: "d" (flags), "a"(&lock->slock), "i"(EPSW_IE | MN10300_CLI_LEVEL)
+		: "memory", "cc");
+}
+
+#ifdef __KERNEL__
+
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+
+/**
+ * read_can_lock - would read_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+#define arch_read_can_lock(x) ((int)(x)->lock > 0)
+
+/**
+ * write_can_lock - would write_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+#define arch_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
+
+/*
+ * On mn10300, we implement read-write locks as a 32-bit counter
+ * with the high bit (sign) being the "contended" bit.
+ */
+static inline void arch_read_lock(arch_rwlock_t *rw)
+{
+#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
+	__build_read_lock(rw, "__read_lock_failed");
+#else
+	{
+		atomic_t *count = (atomic_t *)rw;
+		while (atomic_dec_return(count) < 0)
+			atomic_inc(count);
+	}
+#endif
+}
+
+static inline void arch_write_lock(arch_rwlock_t *rw)
+{
+#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
+	__build_write_lock(rw, "__write_lock_failed");
+#else
+	{
+		atomic_t *count = (atomic_t *)rw;
+		while (!atomic_sub_and_test(RW_LOCK_BIAS, count))
+			atomic_add(RW_LOCK_BIAS, count);
+	}
+#endif
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *rw)
+{
+#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
+	__build_read_unlock(rw);
+#else
+	{
+		atomic_t *count = (atomic_t *)rw;
+		atomic_inc(count);
+	}
+#endif
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *rw)
+{
+#if 0 //def CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
+	__build_write_unlock(rw);
+#else
+	{
+		atomic_t *count = (atomic_t *)rw;
+		atomic_add(RW_LOCK_BIAS, count);
+	}
+#endif
+}
+
+static inline int arch_read_trylock(arch_rwlock_t *lock)
+{
+	atomic_t *count = (atomic_t *)lock;
+	atomic_dec(count);
+	if (atomic_read(count) >= 0)
+		return 1;
+	atomic_inc(count);
+	return 0;
+}
+
+static inline int arch_write_trylock(arch_rwlock_t *lock)
+{
+	atomic_t *count = (atomic_t *)lock;
+	if (atomic_sub_and_test(RW_LOCK_BIAS, count))
+		return 1;
+	atomic_add(RW_LOCK_BIAS, count);
+	return 0;
+}
+
+#define arch_read_lock_flags(lock, flags)  arch_read_lock(lock)
+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+
+#define _raw_spin_relax(lock)	cpu_relax()
+#define _raw_read_relax(lock)	cpu_relax()
+#define _raw_write_relax(lock)	cpu_relax()
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_SPINLOCK_H */
diff --git a/arch/mn10300/include/asm/spinlock_types.h b/arch/mn10300/include/asm/spinlock_types.h
new file mode 100644
index 0000000..653dc51
--- /dev/null
+++ b/arch/mn10300/include/asm/spinlock_types.h
@@ -0,0 +1,20 @@
+#ifndef _ASM_SPINLOCK_TYPES_H
+#define _ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct arch_spinlock {
+	unsigned int slock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
+
+typedef struct {
+	unsigned int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED		{ RW_LOCK_BIAS }
+
+#endif /* _ASM_SPINLOCK_TYPES_H */
diff --git a/arch/mn10300/include/asm/string.h b/arch/mn10300/include/asm/string.h
new file mode 100644
index 0000000..47dbd43
--- /dev/null
+++ b/arch/mn10300/include/asm/string.h
@@ -0,0 +1,32 @@
+/* MN10300 Optimised string functions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_STRING_H
+#define _ASM_STRING_H
+
+#define __HAVE_ARCH_MEMSET
+#define __HAVE_ARCH_MEMCPY
+#define __HAVE_ARCH_MEMMOVE
+
+extern void *memset(void *dest, int ch, size_t count);
+extern void *memcpy(void *dest, const void *src, size_t count);
+extern void *memmove(void *dest, const void *src, size_t count);
+
+
+extern void __struct_cpy_bug(void);
+#define struct_cpy(x, y)			\
+({                                              \
+	if (sizeof(*(x)) != sizeof(*(y)))       \
+		__struct_cpy_bug;               \
+	memcpy(x, y, sizeof(*(x)));             \
+})
+
+#endif /* _ASM_STRING_H */
diff --git a/arch/mn10300/include/asm/switch_to.h b/arch/mn10300/include/asm/switch_to.h
new file mode 100644
index 0000000..393d311
--- /dev/null
+++ b/arch/mn10300/include/asm/switch_to.h
@@ -0,0 +1,49 @@
+/* MN10300 task switching definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_SWITCH_TO_H
+#define _ASM_SWITCH_TO_H
+
+#include <asm/barrier.h>
+
+struct task_struct;
+struct thread_struct;
+
+#if !defined(CONFIG_LAZY_SAVE_FPU)
+struct fpu_state_struct;
+extern asmlinkage void fpu_save(struct fpu_state_struct *);
+#define switch_fpu(prev, next)						\
+	do {								\
+		if ((prev)->thread.fpu_flags & THREAD_HAS_FPU) {	\
+			(prev)->thread.fpu_flags &= ~THREAD_HAS_FPU;	\
+			(prev)->thread.uregs->epsw &= ~EPSW_FE;		\
+			fpu_save(&(prev)->thread.fpu_state);		\
+		}							\
+	} while (0)
+#else
+#define switch_fpu(prev, next) do {} while (0)
+#endif
+
+/* context switching is now performed out-of-line in switch_to.S */
+extern asmlinkage
+struct task_struct *__switch_to(struct thread_struct *prev,
+				struct thread_struct *next,
+				struct task_struct *prev_task);
+
+#define switch_to(prev, next, last)					\
+do {									\
+	switch_fpu(prev, next);						\
+	current->thread.wchan = (u_long) __builtin_return_address(0);	\
+	(last) = __switch_to(&(prev)->thread, &(next)->thread, (prev));	\
+	mb();								\
+	current->thread.wchan = 0;					\
+} while (0)
+
+#endif /* _ASM_SWITCH_TO_H */
diff --git a/arch/mn10300/include/asm/syscall.h b/arch/mn10300/include/asm/syscall.h
new file mode 100644
index 0000000..b44b0bb
--- /dev/null
+++ b/arch/mn10300/include/asm/syscall.h
@@ -0,0 +1,117 @@
+/* Access to user system call parameters and results
+ *
+ * See asm-generic/syscall.h for function descriptions.
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_SYSCALL_H
+#define _ASM_SYSCALL_H
+
+#include <linux/sched.h>
+#include <linux/err.h>
+
+extern const unsigned long sys_call_table[];
+
+static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
+{
+	return regs->orig_d0;
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+				    struct pt_regs *regs)
+{
+	regs->d0 = regs->orig_d0;
+}
+
+static inline long syscall_get_error(struct task_struct *task,
+				     struct pt_regs *regs)
+{
+	unsigned long error = regs->d0;
+	return IS_ERR_VALUE(error) ? error : 0;
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+					    struct pt_regs *regs)
+{
+	return regs->d0;
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+					    struct pt_regs *regs,
+					    int error, long val)
+{
+	regs->d0 = (long) error ?: val;
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 unsigned long *args)
+{
+	switch (i) {
+	case 0:
+		if (!n--) break;
+		*args++ = regs->a0;
+	case 1:
+		if (!n--) break;
+		*args++ = regs->d1;
+	case 2:
+		if (!n--) break;
+		*args++ = regs->a3;
+	case 3:
+		if (!n--) break;
+		*args++ = regs->a2;
+	case 4:
+		if (!n--) break;
+		*args++ = regs->d3;
+	case 5:
+		if (!n--) break;
+		*args++ = regs->d2;
+	case 6:
+		if (!n--) break;
+	default:
+		BUG();
+		break;
+	}
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 const unsigned long *args)
+{
+	switch (i) {
+	case 0:
+		if (!n--) break;
+		regs->a0 = *args++;
+	case 1:
+		if (!n--) break;
+		regs->d1 = *args++;
+	case 2:
+		if (!n--) break;
+		regs->a3 = *args++;
+	case 3:
+		if (!n--) break;
+		regs->a2 = *args++;
+	case 4:
+		if (!n--) break;
+		regs->d3 = *args++;
+	case 5:
+		if (!n--) break;
+		regs->d2 = *args++;
+	case 6:
+		if (!n--) break;
+	default:
+		BUG();
+		break;
+	}
+}
+
+#endif /* _ASM_SYSCALL_H */
diff --git a/arch/mn10300/include/asm/termios.h b/arch/mn10300/include/asm/termios.h
new file mode 100644
index 0000000..c2e29c7
--- /dev/null
+++ b/arch/mn10300/include/asm/termios.h
@@ -0,0 +1,13 @@
+#ifndef _ASM_TERMIOS_H
+#define _ASM_TERMIOS_H
+
+#include <uapi/asm/termios.h>
+
+/*	intr=^C		quit=^|		erase=del	kill=^U
+	eof=^D		vtime=\0	vmin=\1		sxtc=\0
+	start=^Q	stop=^S		susp=^Z		eol=\0
+	reprint=^R	discard=^U	werase=^W	lnext=^V
+	eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+#endif	/* _ASM_TERMIOS_H */
diff --git a/arch/mn10300/include/asm/thread_info.h b/arch/mn10300/include/asm/thread_info.h
new file mode 100644
index 0000000..4861a78
--- /dev/null
+++ b/arch/mn10300/include/asm/thread_info.h
@@ -0,0 +1,162 @@
+/* MN10300 Low-level thread information
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#include <asm/page.h>
+
+#ifdef CONFIG_4KSTACKS
+#define THREAD_SIZE		(4096)
+#define THREAD_SIZE_ORDER	(0)
+#else
+#define THREAD_SIZE		(8192)
+#define THREAD_SIZE_ORDER	(1)
+#endif
+
+#define STACK_WARN		(THREAD_SIZE / 8)
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants
+ *   must also be changed
+ */
+#ifndef __ASSEMBLY__
+typedef struct {
+	unsigned long	seg;
+} mm_segment_t;
+
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	struct pt_regs		*frame;		/* current exception frame */
+	unsigned long		flags;		/* low level flags */
+	__u32			cpu;		/* current CPU */
+	__s32			preempt_count;	/* 0 => preemptable, <0 => BUG */
+
+	mm_segment_t		addr_limit;	/* thread address space:
+						   0-0xBFFFFFFF for user-thead
+						   0-0xFFFFFFFF for kernel-thread
+						*/
+
+	__u8			supervisor_stack[0];
+};
+
+#define thread_info_to_uregs(ti)					\
+	((struct pt_regs *)						\
+	 ((unsigned long)ti + THREAD_SIZE - sizeof(struct pt_regs)))
+
+#else /* !__ASSEMBLY__ */
+
+#ifndef __ASM_OFFSETS_H__
+#include <asm/asm-offsets.h>
+#endif
+
+#endif
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ */
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	.task		= &tsk,			\
+	.flags		= 0,			\
+	.cpu		= 0,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
+	.addr_limit	= KERNEL_DS,		\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+#define init_uregs							\
+	((struct pt_regs *)						\
+	 ((unsigned long) init_stack + THREAD_SIZE - sizeof(struct pt_regs)))
+
+extern struct thread_info *__current_ti;
+
+/* how to get the thread information struct from C */
+static inline __attribute__((const))
+struct thread_info *current_thread_info(void)
+{
+	struct thread_info *ti;
+	asm("mov sp,%0\n"
+	    "and %1,%0\n"
+	    : "=d" (ti)
+	    : "i" (~(THREAD_SIZE - 1))
+	    : "cc");
+	return ti;
+}
+
+static inline __attribute__((const))
+struct pt_regs *current_frame(void)
+{
+	return current_thread_info()->frame;
+}
+
+/* how to get the current stack pointer from C */
+static inline unsigned long current_stack_pointer(void)
+{
+	unsigned long sp;
+	asm("mov sp,%0; ":"=r" (sp));
+	return sp;
+}
+
+#ifndef CONFIG_KGDB
+void arch_release_thread_info(struct thread_info *ti);
+#endif
+#define get_thread_info(ti)	get_task_struct((ti)->task)
+#define put_thread_info(ti)	put_task_struct((ti)->task)
+
+#else /* !__ASSEMBLY__ */
+
+#ifndef __VMLINUX_LDS__
+/* how to get the thread information struct from ASM */
+.macro GET_THREAD_INFO reg
+	mov	sp,\reg
+	and	-THREAD_SIZE,\reg
+.endm
+#endif
+#endif
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to
+ *   access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
+#define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
+#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_MEMDIE		17	/* is terminating due to OOM killer */
+
+#define _TIF_SYSCALL_TRACE	+(1 << TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME	+(1 << TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING		+(1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	+(1 << TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP		+(1 << TIF_SINGLESTEP)
+#define _TIF_POLLING_NRFLAG	+(1 << TIF_POLLING_NRFLAG)
+
+#define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
+#define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/mn10300/include/asm/timer-regs.h b/arch/mn10300/include/asm/timer-regs.h
new file mode 100644
index 0000000..c634977
--- /dev/null
+++ b/arch/mn10300/include/asm/timer-regs.h
@@ -0,0 +1,452 @@
+/* AM33v2 on-board timer module registers
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_TIMER_REGS_H
+#define _ASM_TIMER_REGS_H
+
+#include <asm/cpu-regs.h>
+#include <asm/intctl-regs.h>
+
+#ifdef __KERNEL__
+
+/*
+ * Timer prescalar control
+ */
+#define	TMPSCNT			__SYSREG(0xd4003071, u8) /* timer prescaler control */
+#define	TMPSCNT_ENABLE		0x80	/* timer prescaler enable */
+#define	TMPSCNT_DISABLE		0x00	/* timer prescaler disable */
+
+/*
+ * 8-bit timers
+ */
+#define	TM0MD			__SYSREG(0xd4003000, u8) /* timer 0 mode register */
+#define	TM0MD_SRC		0x07	/* timer source */
+#define	TM0MD_SRC_IOCLK		0x00	/* - IOCLK */
+#define	TM0MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM0MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM0MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM0MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#if	defined(CONFIG_AM33_2)
+#define	TM0MD_SRC_TM2IO		0x03	/* - TM2IO pin input */
+#define	TM0MD_SRC_TM0IO		0x07	/* - TM0IO pin input */
+#endif /* CONFIG_AM33_2 */
+#define	TM0MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM0MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM1MD			__SYSREG(0xd4003001, u8) /* timer 1 mode register */
+#define	TM1MD_SRC		0x07	/* timer source */
+#define	TM1MD_SRC_IOCLK		0x00	/* - IOCLK */
+#define	TM1MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM1MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM1MD_SRC_TM0CASCADE	0x03	/* - cascade with timer 0 */
+#define	TM1MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM1MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#if defined(CONFIG_AM33_2)
+#define	TM1MD_SRC_TM1IO		0x07	/* - TM1IO pin input */
+#endif	/* CONFIG_AM33_2 */
+#define	TM1MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM1MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM2MD			__SYSREG(0xd4003002, u8) /* timer 2 mode register */
+#define	TM2MD_SRC		0x07	/* timer source */
+#define	TM2MD_SRC_IOCLK		0x00	/* - IOCLK */
+#define	TM2MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM2MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM2MD_SRC_TM1CASCADE	0x03	/* - cascade with timer 1 */
+#define	TM2MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM2MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#if defined(CONFIG_AM33_2)
+#define	TM2MD_SRC_TM2IO		0x07	/* - TM2IO pin input */
+#endif	/* CONFIG_AM33_2 */
+#define	TM2MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM2MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM3MD			__SYSREG(0xd4003003, u8) /* timer 3 mode register */
+#define	TM3MD_SRC		0x07	/* timer source */
+#define	TM3MD_SRC_IOCLK		0x00	/* - IOCLK */
+#define	TM3MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM3MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM3MD_SRC_TM2CASCADE	0x03	/* - cascade with timer 2 */
+#define	TM3MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM3MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM3MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#if defined(CONFIG_AM33_2)
+#define	TM3MD_SRC_TM3IO		0x07	/* - TM3IO pin input */
+#endif	/* CONFIG_AM33_2 */
+#define	TM3MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM3MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM01MD			__SYSREG(0xd4003000, u16)  /* timer 0:1 mode register */
+
+#define	TM0BR			__SYSREG(0xd4003010, u8)   /* timer 0 base register */
+#define	TM1BR			__SYSREG(0xd4003011, u8)   /* timer 1 base register */
+#define	TM2BR			__SYSREG(0xd4003012, u8)   /* timer 2 base register */
+#define	TM3BR			__SYSREG(0xd4003013, u8)   /* timer 3 base register */
+#define	TM01BR			__SYSREG(0xd4003010, u16)  /* timer 0:1 base register */
+
+#define	TM0BC			__SYSREGC(0xd4003020, u8)  /* timer 0 binary counter */
+#define	TM1BC			__SYSREGC(0xd4003021, u8)  /* timer 1 binary counter */
+#define	TM2BC			__SYSREGC(0xd4003022, u8)  /* timer 2 binary counter */
+#define	TM3BC			__SYSREGC(0xd4003023, u8)  /* timer 3 binary counter */
+#define	TM01BC			__SYSREGC(0xd4003020, u16) /* timer 0:1 binary counter */
+
+#define TM0IRQ			2	/* timer 0 IRQ */
+#define TM1IRQ			3	/* timer 1 IRQ */
+#define TM2IRQ			4	/* timer 2 IRQ */
+#define TM3IRQ			5	/* timer 3 IRQ */
+
+#define	TM0ICR			GxICR(TM0IRQ)	/* timer 0 uflow intr ctrl reg */
+#define	TM1ICR			GxICR(TM1IRQ)	/* timer 1 uflow intr ctrl reg */
+#define	TM2ICR			GxICR(TM2IRQ)	/* timer 2 uflow intr ctrl reg */
+#define	TM3ICR			GxICR(TM3IRQ)	/* timer 3 uflow intr ctrl reg */
+
+/*
+ * 16-bit timers 4,5 & 7-15
+ */
+#define	TM4MD			__SYSREG(0xd4003080, u8)   /* timer 4 mode register */
+#define	TM4MD_SRC		0x07	/* timer source */
+#define	TM4MD_SRC_IOCLK		0x00	/* - IOCLK */
+#define	TM4MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM4MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM4MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM4MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM4MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#if defined(CONFIG_AM33_2)
+#define	TM4MD_SRC_TM4IO		0x07	/* - TM4IO pin input */
+#endif	/* CONFIG_AM33_2 */
+#define	TM4MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM4MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM5MD			__SYSREG(0xd4003082, u8)   /* timer 5 mode register */
+#define	TM5MD_SRC		0x07	/* timer source */
+#define	TM5MD_SRC_IOCLK		0x00	/* - IOCLK */
+#define	TM5MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM5MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM5MD_SRC_TM4CASCADE	0x03	/* - cascade with timer 4 */
+#define	TM5MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM5MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM5MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#if defined(CONFIG_AM33_2)
+#define	TM5MD_SRC_TM5IO		0x07	/* - TM5IO pin input */
+#else	/* !CONFIG_AM33_2 */
+#define	TM5MD_SRC_TM7UFLOW	0x07	/* - timer 7 underflow */
+#endif	/* CONFIG_AM33_2 */
+#define	TM5MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM5MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM7MD			__SYSREG(0xd4003086, u8)   /* timer 7 mode register */
+#define	TM7MD_SRC		0x07	/* timer source */
+#define	TM7MD_SRC_IOCLK		0x00	/* - IOCLK */
+#define	TM7MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM7MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM7MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM7MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM7MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#if defined(CONFIG_AM33_2)
+#define	TM7MD_SRC_TM7IO		0x07	/* - TM7IO pin input */
+#endif	/* CONFIG_AM33_2 */
+#define	TM7MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM7MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM8MD			__SYSREG(0xd4003088, u8)   /* timer 8 mode register */
+#define	TM8MD_SRC		0x07	/* timer source */
+#define	TM8MD_SRC_IOCLK		0x00	/* - IOCLK */
+#define	TM8MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM8MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM8MD_SRC_TM7CASCADE	0x03	/* - cascade with timer 7 */
+#define	TM8MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM8MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM8MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#if defined(CONFIG_AM33_2)
+#define	TM8MD_SRC_TM8IO		0x07	/* - TM8IO pin input */
+#else	/* !CONFIG_AM33_2 */
+#define	TM8MD_SRC_TM7UFLOW	0x07	/* - timer 7 underflow */
+#endif	/* CONFIG_AM33_2 */
+#define	TM8MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM8MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM9MD			__SYSREG(0xd400308a, u8)   /* timer 9 mode register */
+#define	TM9MD_SRC		0x07	/* timer source */
+#define	TM9MD_SRC_IOCLK		0x00	/* - IOCLK */
+#define	TM9MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM9MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM9MD_SRC_TM8CASCADE	0x03	/* - cascade with timer 8 */
+#define	TM9MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM9MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM9MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#if defined(CONFIG_AM33_2)
+#define	TM9MD_SRC_TM9IO		0x07	/* - TM9IO pin input */
+#else	/* !CONFIG_AM33_2 */
+#define	TM9MD_SRC_TM7UFLOW	0x07	/* - timer 7 underflow */
+#endif	/* CONFIG_AM33_2 */
+#define	TM9MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM9MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM10MD			__SYSREG(0xd400308c, u8)   /* timer 10 mode register */
+#define	TM10MD_SRC		0x07	/* timer source */
+#define	TM10MD_SRC_IOCLK	0x00	/* - IOCLK */
+#define	TM10MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM10MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM10MD_SRC_TM9CASCADE	0x03	/* - cascade with timer 9 */
+#define	TM10MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM10MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM10MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#if defined(CONFIG_AM33_2)
+#define	TM10MD_SRC_TM10IO	0x07	/* - TM10IO pin input */
+#else	/* !CONFIG_AM33_2 */
+#define	TM10MD_SRC_TM7UFLOW	0x07	/* - timer 7 underflow */
+#endif	/* CONFIG_AM33_2 */
+#define	TM10MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM10MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM11MD			__SYSREG(0xd400308e, u8)   /* timer 11 mode register */
+#define	TM11MD_SRC		0x07	/* timer source */
+#define	TM11MD_SRC_IOCLK	0x00	/* - IOCLK */
+#define	TM11MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM11MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM11MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM11MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM11MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#if defined(CONFIG_AM33_2)
+#define	TM11MD_SRC_TM11IO	0x07	/* - TM11IO pin input */
+#else	/* !CONFIG_AM33_2 */
+#define	TM11MD_SRC_TM7UFLOW	0x07	/* - timer 7 underflow */
+#endif	/* CONFIG_AM33_2 */
+#define	TM11MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM11MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#if defined(CONFIG_AM34_2)
+#define	TM12MD			__SYSREG(0xd4003180, u8)   /* timer 11 mode register */
+#define	TM12MD_SRC		0x07	/* timer source */
+#define	TM12MD_SRC_IOCLK	0x00	/* - IOCLK */
+#define	TM12MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM12MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM12MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM12MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM12MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#define	TM12MD_SRC_TM7UFLOW	0x07	/* - timer 7 underflow */
+#define	TM12MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM12MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM13MD			__SYSREG(0xd4003182, u8)   /* timer 11 mode register */
+#define	TM13MD_SRC		0x07	/* timer source */
+#define	TM13MD_SRC_IOCLK	0x00	/* - IOCLK */
+#define	TM13MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM13MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM13MD_SRC_TM12CASCADE	0x03	/* - cascade with timer 12 */
+#define	TM13MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM13MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM13MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#define	TM13MD_SRC_TM7UFLOW	0x07	/* - timer 7 underflow */
+#define	TM13MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM13MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM14MD			__SYSREG(0xd4003184, u8)   /* timer 11 mode register */
+#define	TM14MD_SRC		0x07	/* timer source */
+#define	TM14MD_SRC_IOCLK	0x00	/* - IOCLK */
+#define	TM14MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM14MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM14MD_SRC_TM13CASCADE	0x03	/* - cascade with timer 13 */
+#define	TM14MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM14MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM14MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#define	TM14MD_SRC_TM7UFLOW	0x07	/* - timer 7 underflow */
+#define	TM14MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM14MD_COUNT_ENABLE	0x80	/* timer count enable */
+
+#define	TM15MD			__SYSREG(0xd4003186, u8)   /* timer 11 mode register */
+#define	TM15MD_SRC		0x07	/* timer source */
+#define	TM15MD_SRC_IOCLK	0x00	/* - IOCLK */
+#define	TM15MD_SRC_IOCLK_8	0x01	/* - 1/8 IOCLK */
+#define	TM15MD_SRC_IOCLK_32	0x02	/* - 1/32 IOCLK */
+#define	TM15MD_SRC_TM0UFLOW	0x04	/* - timer 0 underflow */
+#define	TM15MD_SRC_TM1UFLOW	0x05	/* - timer 1 underflow */
+#define	TM15MD_SRC_TM2UFLOW	0x06	/* - timer 2 underflow */
+#define	TM15MD_SRC_TM7UFLOW	0x07	/* - timer 7 underflow */
+#define	TM15MD_INIT_COUNTER	0x40	/* initialize TMnBC = TMnBR */
+#define	TM15MD_COUNT_ENABLE	0x80	/* timer count enable */
+#endif	/* CONFIG_AM34_2 */
+
+
+#define	TM4BR			__SYSREG(0xd4003090, u16)  /* timer 4 base register */
+#define	TM5BR			__SYSREG(0xd4003092, u16)  /* timer 5 base register */
+#define	TM45BR			__SYSREG(0xd4003090, u32)  /* timer 4:5 base register */
+#define	TM7BR			__SYSREG(0xd4003096, u16)  /* timer 7 base register */
+#define	TM8BR			__SYSREG(0xd4003098, u16)  /* timer 8 base register */
+#define	TM9BR			__SYSREG(0xd400309a, u16)  /* timer 9 base register */
+#define	TM89BR			__SYSREG(0xd4003098, u32)  /* timer 8:9 base register */
+#define	TM10BR			__SYSREG(0xd400309c, u16)  /* timer 10 base register */
+#define	TM11BR			__SYSREG(0xd400309e, u16)  /* timer 11 base register */
+#if defined(CONFIG_AM34_2)
+#define	TM12BR			__SYSREG(0xd4003190, u16)  /* timer 12 base register */
+#define	TM13BR			__SYSREG(0xd4003192, u16)  /* timer 13 base register */
+#define	TM14BR			__SYSREG(0xd4003194, u16)  /* timer 14 base register */
+#define	TM15BR			__SYSREG(0xd4003196, u16)  /* timer 15 base register */
+#endif	/* CONFIG_AM34_2 */
+
+#define	TM4BC			__SYSREG(0xd40030a0, u16)  /* timer 4 binary counter */
+#define	TM5BC			__SYSREG(0xd40030a2, u16)  /* timer 5 binary counter */
+#define	TM45BC			__SYSREG(0xd40030a0, u32)  /* timer 4:5 binary counter */
+#define	TM7BC			__SYSREG(0xd40030a6, u16)  /* timer 7 binary counter */
+#define	TM8BC			__SYSREG(0xd40030a8, u16)  /* timer 8 binary counter */
+#define	TM9BC			__SYSREG(0xd40030aa, u16)  /* timer 9 binary counter */
+#define	TM89BC			__SYSREG(0xd40030a8, u32)  /* timer 8:9 binary counter */
+#define	TM10BC			__SYSREG(0xd40030ac, u16)  /* timer 10 binary counter */
+#define	TM11BC			__SYSREG(0xd40030ae, u16)  /* timer 11 binary counter */
+#if defined(CONFIG_AM34_2)
+#define	TM12BC			__SYSREG(0xd40031a0, u16)  /* timer 12 binary counter */
+#define	TM13BC			__SYSREG(0xd40031a2, u16)  /* timer 13 binary counter */
+#define	TM14BC			__SYSREG(0xd40031a4, u16)  /* timer 14 binary counter */
+#define	TM15BC			__SYSREG(0xd40031a6, u16)  /* timer 15 binary counter */
+#endif	/* CONFIG_AM34_2 */
+
+#define TM4IRQ			6	/* timer 4 IRQ */
+#define TM5IRQ			7	/* timer 5 IRQ */
+#define TM7IRQ			11	/* timer 7 IRQ */
+#define TM8IRQ			12	/* timer 8 IRQ */
+#define TM9IRQ			13	/* timer 9 IRQ */
+#define TM10IRQ			14	/* timer 10 IRQ */
+#define TM11IRQ			15	/* timer 11 IRQ */
+#if defined(CONFIG_AM34_2)
+#define TM12IRQ			64	/* timer 12 IRQ */
+#define TM13IRQ			65	/* timer 13 IRQ */
+#define TM14IRQ			66	/* timer 14 IRQ */
+#define TM15IRQ			67	/* timer 15 IRQ */
+#endif	/* CONFIG_AM34_2 */
+
+#define	TM4ICR			GxICR(TM4IRQ)	/* timer 4 uflow intr ctrl reg */
+#define	TM5ICR			GxICR(TM5IRQ)	/* timer 5 uflow intr ctrl reg */
+#define	TM7ICR			GxICR(TM7IRQ)	/* timer 7 uflow intr ctrl reg */
+#define	TM8ICR			GxICR(TM8IRQ)	/* timer 8 uflow intr ctrl reg */
+#define	TM9ICR			GxICR(TM9IRQ)	/* timer 9 uflow intr ctrl reg */
+#define	TM10ICR			GxICR(TM10IRQ)	/* timer 10 uflow intr ctrl reg */
+#define	TM11ICR			GxICR(TM11IRQ)	/* timer 11 uflow intr ctrl reg */
+#if defined(CONFIG_AM34_2)
+#define	TM12ICR			GxICR(TM12IRQ)	/* timer 12 uflow intr ctrl reg */
+#define	TM13ICR			GxICR(TM13IRQ)	/* timer 13 uflow intr ctrl reg */
+#define	TM14ICR			GxICR(TM14IRQ)	/* timer 14 uflow intr ctrl reg */
+#define	TM15ICR			GxICR(TM15IRQ)	/* timer 15 uflow intr ctrl reg */
+#endif	/* CONFIG_AM34_2 */
+
+/*
+ * 16-bit timer 6
+ */
+#define	TM6MD			__SYSREG(0xd4003084, u16)  /* timer6 mode register */
+#define	TM6MD_SRC		0x0007	/* timer source */
+#define	TM6MD_SRC_IOCLK		0x0000	/* - IOCLK */
+#define	TM6MD_SRC_IOCLK_8	0x0001	/* - 1/8 IOCLK */
+#define	TM6MD_SRC_IOCLK_32	0x0002	/* - 1/32 IOCLK */
+#define	TM6MD_SRC_TM0UFLOW	0x0004	/* - timer 0 underflow */
+#define	TM6MD_SRC_TM1UFLOW	0x0005	/* - timer 1 underflow */
+#define	TM6MD_SRC_TM2UFLOW	0x0006	/* - timer 2 underflow */
+#if defined(CONFIG_AM33_2)
+/* #define	TM6MD_SRC_TM6IOB_BOTH	0x0006 */	/* - TM6IOB pin input (both edges) */
+#define	TM6MD_SRC_TM6IOB_SINGLE	0x0007	/* - TM6IOB pin input (single edge) */
+#endif	/* CONFIG_AM33_2 */
+#define	TM6MD_ONESHOT_ENABLE	0x0040	/* oneshot count */
+#define	TM6MD_CLR_ENABLE	0x0010	/* clear count enable */
+#if	defined(CONFIG_AM33_2)
+#define	TM6MD_TRIG_ENABLE	0x0080	/* TM6IOB pin trigger enable */
+#define TM6MD_PWM		0x3800	/* PWM output mode */
+#define TM6MD_PWM_DIS		0x0000	/* - disabled */
+#define	TM6MD_PWM_10BIT		0x1000	/* - 10 bits mode */
+#define	TM6MD_PWM_11BIT		0x1800	/* - 11 bits mode */
+#define	TM6MD_PWM_12BIT		0x3000	/* - 12 bits mode */
+#define	TM6MD_PWM_14BIT		0x3800	/* - 14 bits mode */
+#endif	/* CONFIG_AM33_2 */
+
+#define	TM6MD_INIT_COUNTER	0x4000	/* initialize TMnBC to zero */
+#define	TM6MD_COUNT_ENABLE	0x8000	/* timer count enable */
+
+#define	TM6MDA			__SYSREG(0xd40030b4, u8)   /* timer6 cmp/cap A mode reg */
+#define	TM6MDA_MODE_CMP_SINGLE	0x00	/* - compare, single buffer mode */
+#define	TM6MDA_MODE_CMP_DOUBLE	0x40	/* - compare, double buffer mode */
+#if	defined(CONFIG_AM33_2)
+#define TM6MDA_OUT		0x07	/* output select */
+#define	TM6MDA_OUT_SETA_RESETB	0x00	/* - set at match A, reset at match B */
+#define	TM6MDA_OUT_SETA_RESETOV	0x01	/* - set at match A, reset at overflow */
+#define	TM6MDA_OUT_SETA		0x02	/* - set at match A */
+#define	TM6MDA_OUT_RESETA	0x03	/* - reset at match A */
+#define	TM6MDA_OUT_TOGGLE	0x04	/* - toggle on match A */
+#define TM6MDA_MODE		0xc0	/* compare A register mode */
+#define	TM6MDA_MODE_CAP_S_EDGE	0x80	/* - capture, single edge mode */
+#define	TM6MDA_MODE_CAP_D_EDGE	0xc0	/* - capture, double edge mode */
+#define TM6MDA_EDGE		0x20	/* compare A edge select */
+#define	TM6MDA_EDGE_FALLING	0x00	/* capture on falling edge */
+#define	TM6MDA_EDGE_RISING	0x20	/* capture on rising edge */
+#define	TM6MDA_CAPTURE_ENABLE	0x10	/* capture enable */
+#else	/* !CONFIG_AM33_2 */
+#define	TM6MDA_MODE		0x40	/* compare A register mode */
+#endif	/* CONFIG_AM33_2 */
+
+#define	TM6MDB			__SYSREG(0xd40030b5, u8)   /* timer6 cmp/cap B mode reg */
+#define	TM6MDB_MODE_CMP_SINGLE	0x00	/* - compare, single buffer mode */
+#define	TM6MDB_MODE_CMP_DOUBLE	0x40	/* - compare, double buffer mode */
+#if defined(CONFIG_AM33_2)
+#define TM6MDB_OUT		0x07	/* output select */
+#define	TM6MDB_OUT_SETB_RESETA	0x00	/* - set at match B, reset at match A */
+#define	TM6MDB_OUT_SETB_RESETOV	0x01	/* - set at match B */
+#define	TM6MDB_OUT_RESETB	0x03	/* - reset at match B */
+#define	TM6MDB_OUT_TOGGLE	0x04	/* - toggle on match B */
+#define TM6MDB_MODE		0xc0	/* compare B register mode */
+#define	TM6MDB_MODE_CAP_S_EDGE	0x80	/* - capture, single edge mode */
+#define	TM6MDB_MODE_CAP_D_EDGE	0xc0	/* - capture, double edge mode */
+#define TM6MDB_EDGE		0x20	/* compare B edge select */
+#define	TM6MDB_EDGE_FALLING	0x00	/* capture on falling edge */
+#define	TM6MDB_EDGE_RISING	0x20	/* capture on rising edge */
+#define	TM6MDB_CAPTURE_ENABLE	0x10	/* capture enable */
+#else	/* !CONFIG_AM33_2 */
+#define	TM6MDB_MODE		0x40	/* compare B register mode */
+#endif	/* CONFIG_AM33_2 */
+
+#define	TM6CA			__SYSREG(0xd40030c4, u16)   /* timer6 cmp/capture reg A */
+#define	TM6CB			__SYSREG(0xd40030d4, u16)   /* timer6 cmp/capture reg B */
+#define	TM6BC			__SYSREG(0xd40030a4, u16)   /* timer6 binary counter */
+
+#define TM6IRQ			6	/* timer 6 IRQ */
+#define TM6AIRQ			9	/* timer 6A IRQ */
+#define TM6BIRQ			10	/* timer 6B IRQ */
+
+#define	TM6ICR			GxICR(TM6IRQ)	/* timer 6 uflow intr ctrl reg */
+#define	TM6AICR			GxICR(TM6AIRQ)	/* timer 6A intr control reg */
+#define	TM6BICR			GxICR(TM6BIRQ)	/* timer 6B intr control reg */
+
+#if defined(CONFIG_AM34_2)
+/*
+ * MTM: OS Tick-Timer
+ */
+#define	TMTMD			__SYSREG(0xd4004100, u8)	/* Tick Timer mode register */
+#define	TMTMD_TMTLDE		0x40	/* initialize TMTBC = TMTBR */
+#define	TMTMD_TMTCNE		0x80	/* timer count enable       */
+
+#define	TMTBR			__SYSREG(0xd4004110, u32)	/* Tick Timer mode reg */
+#define	TMTBC			__SYSREG(0xd4004120, u32)	/* Tick Timer mode reg */
+
+/*
+ * MTM: OS Timestamp-Timer
+ */
+#define	TMSMD			__SYSREG(0xd4004140, u8)	/* Tick Timer mode register */
+#define	TMSMD_TMSLDE		0x40		/* initialize TMSBC = TMSBR */
+#define	TMSMD_TMSCNE		0x80		/* timer count enable       */
+
+#define	TMSBR			__SYSREG(0xd4004150, u32)	/* Tick Timer mode register */
+#define	TMSBC			__SYSREG(0xd4004160, u32)	/* Tick Timer mode register */
+
+#define TMTIRQ			119		/* OS Tick timer   IRQ */
+#define TMSIRQ			120		/* Timestamp timer IRQ */
+
+#define	TMTICR			GxICR(TMTIRQ)	/* OS Tick timer   uflow intr ctrl reg */
+#define	TMSICR			GxICR(TMSIRQ)	/* Timestamp timer uflow intr ctrl reg */
+#endif	/* CONFIG_AM34_2 */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_TIMER_REGS_H */
diff --git a/arch/mn10300/include/asm/timex.h b/arch/mn10300/include/asm/timex.h
new file mode 100644
index 0000000..f8e6642
--- /dev/null
+++ b/arch/mn10300/include/asm/timex.h
@@ -0,0 +1,34 @@
+/* MN10300 Architecture time management specifications
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_TIMEX_H
+#define _ASM_TIMEX_H
+
+#include <unit/timex.h>
+
+#define TICK_SIZE (tick_nsec / 1000)
+
+#define CLOCK_TICK_RATE MN10300_JCCLK /* Underlying HZ */
+
+#ifdef __KERNEL__
+
+extern cycles_t cacheflush_time;
+
+static inline cycles_t get_cycles(void)
+{
+	return read_timestamp_counter();
+}
+
+extern int init_clockevents(void);
+extern int init_clocksource(void);
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_TIMEX_H */
diff --git a/arch/mn10300/include/asm/tlb.h b/arch/mn10300/include/asm/tlb.h
new file mode 100644
index 0000000..65d232b
--- /dev/null
+++ b/arch/mn10300/include/asm/tlb.h
@@ -0,0 +1,34 @@
+/* MN10300 TLB definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_TLB_H
+#define _ASM_TLB_H
+
+#include <asm/tlbflush.h>
+
+extern void check_pgt_cache(void);
+
+/*
+ * we don't need any special per-pte or per-vma handling...
+ */
+#define tlb_start_vma(tlb, vma)				do { } while (0)
+#define tlb_end_vma(tlb, vma)				do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address)	do { } while (0)
+
+/*
+ * .. because we flush the whole mm when it fills up
+ */
+#define tlb_flush(tlb)	flush_tlb_mm((tlb)->mm)
+
+/* for now, just use the generic stuff */
+#include <asm-generic/tlb.h>
+
+#endif /* _ASM_TLB_H */
diff --git a/arch/mn10300/include/asm/tlbflush.h b/arch/mn10300/include/asm/tlbflush.h
new file mode 100644
index 0000000..efddd6e
--- /dev/null
+++ b/arch/mn10300/include/asm/tlbflush.h
@@ -0,0 +1,154 @@
+/* MN10300 TLB flushing functions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_TLBFLUSH_H
+#define _ASM_TLBFLUSH_H
+
+#include <linux/mm.h>
+#include <asm/processor.h>
+
+struct tlb_state {
+	struct mm_struct	*active_mm;
+	int			state;
+};
+DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
+
+/**
+ * local_flush_tlb - Flush the current MM's entries from the local CPU's TLBs
+ */
+static inline void local_flush_tlb(void)
+{
+	int w;
+	asm volatile(
+		"	mov	%1,%0		\n"
+		"	or	%2,%0		\n"
+		"	mov	%0,%1		\n"
+		: "=d"(w)
+		: "m"(MMUCTR), "i"(MMUCTR_IIV|MMUCTR_DIV)
+		: "cc", "memory");
+}
+
+/**
+ * local_flush_tlb_all - Flush all entries from the local CPU's TLBs
+ */
+static inline void local_flush_tlb_all(void)
+{
+	local_flush_tlb();
+}
+
+/**
+ * local_flush_tlb_one - Flush one entry from the local CPU's TLBs
+ */
+static inline void local_flush_tlb_one(unsigned long addr)
+{
+	local_flush_tlb();
+}
+
+/**
+ * local_flush_tlb_page - Flush a page's entry from the local CPU's TLBs
+ * @mm: The MM to flush for
+ * @addr: The address of the target page in RAM (not its page struct)
+ */
+static inline
+void local_flush_tlb_page(struct mm_struct *mm, unsigned long addr)
+{
+	unsigned long pteu, flags, cnx;
+
+	addr &= PAGE_MASK;
+
+	local_irq_save(flags);
+
+	cnx = 1;
+#ifdef CONFIG_MN10300_TLB_USE_PIDR
+	cnx = mm->context.tlbpid[smp_processor_id()];
+#endif
+	if (cnx) {
+		pteu = addr;
+#ifdef CONFIG_MN10300_TLB_USE_PIDR
+		pteu |= cnx & xPTEU_PID;
+#endif
+		IPTEU = pteu;
+		DPTEU = pteu;
+		if (IPTEL & xPTEL_V)
+			IPTEL = 0;
+		if (DPTEL & xPTEL_V)
+			DPTEL = 0;
+	}
+	local_irq_restore(flags);
+}
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb() flushes the current mm struct TLBs
+ *  - flush_tlb_all() flushes all processes TLBs
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(mm, start, end) flushes a range of pages
+ *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
+ */
+#ifdef CONFIG_SMP
+
+#include <asm/smp.h>
+
+extern void flush_tlb_all(void);
+extern void flush_tlb_current_task(void);
+extern void flush_tlb_mm(struct mm_struct *);
+extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
+
+#define flush_tlb()		flush_tlb_current_task()
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end)
+{
+	flush_tlb_mm(vma->vm_mm);
+}
+
+#else   /* CONFIG_SMP */
+
+static inline void flush_tlb_all(void)
+{
+	preempt_disable();
+	local_flush_tlb_all();
+	preempt_enable();
+}
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+	preempt_disable();
+	local_flush_tlb_all();
+	preempt_enable();
+}
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end)
+{
+	preempt_disable();
+	local_flush_tlb_all();
+	preempt_enable();
+}
+
+#define flush_tlb_page(vma, addr)	local_flush_tlb_page((vma)->vm_mm, addr)
+#define flush_tlb()			flush_tlb_all()
+
+#endif /* CONFIG_SMP */
+
+static inline void flush_tlb_kernel_range(unsigned long start,
+					  unsigned long end)
+{
+	flush_tlb_all();
+}
+
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
+				      unsigned long start, unsigned long end)
+{
+}
+
+#endif /* _ASM_TLBFLUSH_H */
diff --git a/arch/mn10300/include/asm/topology.h b/arch/mn10300/include/asm/topology.h
new file mode 100644
index 0000000..5428f33
--- /dev/null
+++ b/arch/mn10300/include/asm/topology.h
@@ -0,0 +1 @@
+#include <asm-generic/topology.h>
diff --git a/arch/mn10300/include/asm/types.h b/arch/mn10300/include/asm/types.h
new file mode 100644
index 0000000..3d6e483
--- /dev/null
+++ b/arch/mn10300/include/asm/types.h
@@ -0,0 +1,22 @@
+/* MN10300 Basic type definitions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_TYPES_H
+#define _ASM_TYPES_H
+
+#include <uapi/asm/types.h>
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+
+#define BITS_PER_LONG 32
+
+#endif /* _ASM_TYPES_H */
diff --git a/arch/mn10300/include/asm/uaccess.h b/arch/mn10300/include/asm/uaccess.h
new file mode 100644
index 0000000..4af43d9
--- /dev/null
+++ b/arch/mn10300/include/asm/uaccess.h
@@ -0,0 +1,496 @@
+/* MN10300 userspace access functions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_UACCESS_H
+#define _ASM_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/thread_info.h>
+#include <linux/kernel.h>
+#include <asm/page.h>
+#include <asm/errno.h>
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+#define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
+
+#define KERNEL_XDS	MAKE_MM_SEG(0xBFFFFFFF)
+#define KERNEL_DS	MAKE_MM_SEG(0x9FFFFFFF)
+#define USER_DS		MAKE_MM_SEG(TASK_SIZE)
+
+#define get_ds()	(KERNEL_DS)
+#define get_fs()	(current_thread_info()->addr_limit)
+#define set_fs(x)	(current_thread_info()->addr_limit = (x))
+#define __kernel_ds_p() (current_thread_info()->addr_limit.seg == 0x9FFFFFFF)
+
+#define segment_eq(a, b) ((a).seg == (b).seg)
+
+#define __addr_ok(addr) \
+	((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
+
+/*
+ * check that a range of addresses falls within the current address limit
+ */
+static inline int ___range_ok(unsigned long addr, unsigned int size)
+{
+	int flag = 1, tmp;
+
+	asm("	add	%3,%1	\n"	/* set C-flag if addr + size > 4Gb */
+	    "	bcs	0f	\n"
+	    "	cmp	%4,%1	\n"	/* jump if addr+size>limit (error) */
+	    "	bhi	0f	\n"
+	    "	clr	%0	\n"	/* mark okay */
+	    "0:			\n"
+	    : "=r"(flag), "=&r"(tmp)
+	    : "1"(addr), "ir"(size),
+	      "r"(current_thread_info()->addr_limit.seg), "0"(flag)
+	    : "cc"
+	    );
+
+	return flag;
+}
+
+#define __range_ok(addr, size) ___range_ok((unsigned long)(addr), (u32)(size))
+
+#define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0)
+#define __access_ok(addr, size)     (__range_ok((addr), (size)) == 0)
+
+static inline int verify_area(int type, const void *addr, unsigned long size)
+{
+	return access_ok(type, addr, size) ? 0 : -EFAULT;
+}
+
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry
+{
+	unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern int fixup_exception(struct pt_regs *regs);
+
+#define put_user(x, ptr) __put_user_check((x), (ptr), sizeof(*(ptr)))
+#define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr)))
+
+/*
+ * The "__xxx" versions do not do address space checking, useful when
+ * doing multiple accesses to the same area (the user has to do the
+ * checks by hand with "access_ok()")
+ */
+#define __put_user(x, ptr) __put_user_nocheck((x), (ptr), sizeof(*(ptr)))
+#define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
+
+/*
+ * The "xxx_ret" versions return constant specified in third argument, if
+ * something bad happens. These macros can be optimized for the
+ * case of just returning from the function xxx_ret is used.
+ */
+
+#define put_user_ret(x, ptr, ret) \
+	({ if (put_user((x), (ptr)))	return (ret); })
+#define get_user_ret(x, ptr, ret) \
+	({ if (get_user((x), (ptr)))	return (ret); })
+#define __put_user_ret(x, ptr, ret) \
+	({ if (__put_user((x), (ptr)))	return (ret); })
+#define __get_user_ret(x, ptr, ret) \
+	({ if (__get_user((x), (ptr)))	return (ret); })
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+#define __get_user_nocheck(x, ptr, size)				\
+({									\
+	unsigned long __gu_addr;					\
+	int __gu_err;							\
+	__gu_addr = (unsigned long) (ptr);				\
+	switch (size) {							\
+	case 1: {							\
+		unsigned char __gu_val;					\
+		__get_user_asm("bu");					\
+		(x) = *(__force __typeof__(*(ptr))*) &__gu_val;		\
+		break;							\
+	}								\
+	case 2: {							\
+		unsigned short __gu_val;				\
+		__get_user_asm("hu");					\
+		(x) = *(__force __typeof__(*(ptr))*) &__gu_val;		\
+		break;							\
+	}								\
+	case 4: {							\
+		unsigned int __gu_val;					\
+		__get_user_asm("");					\
+		(x) = *(__force __typeof__(*(ptr))*) &__gu_val;		\
+		break;							\
+	}								\
+	default:							\
+		__get_user_unknown();					\
+		break;							\
+	}								\
+	__gu_err;							\
+})
+
+#define __get_user_check(x, ptr, size)					\
+({									\
+	const __typeof__(*(ptr))* __guc_ptr = (ptr);			\
+	int _e;								\
+	if (likely(__access_ok((unsigned long) __guc_ptr, (size))))	\
+		_e = __get_user_nocheck((x), __guc_ptr, (size));	\
+	else {								\
+		_e = -EFAULT;						\
+		(x) = (__typeof__(x))0;					\
+	}								\
+	_e;								\
+})
+
+#define __get_user_asm(INSN)					\
+({								\
+	asm volatile(					\
+		"1:\n"						\
+		"	mov"INSN"	%2,%1\n"		\
+		"	mov		0,%0\n"			\
+		"2:\n"						\
+		"	.section	.fixup,\"ax\"\n"	\
+		"3:\n\t"					\
+		"	mov		0,%1\n"			\
+		"	mov		%3,%0\n"		\
+		"	jmp		2b\n"			\
+		"	.previous\n"				\
+		"	.section	__ex_table,\"a\"\n"	\
+		"	.balign		4\n"			\
+		"	.long		1b, 3b\n"		\
+		"	.previous"				\
+		: "=&r" (__gu_err), "=&r" (__gu_val)		\
+		: "m" (__m(__gu_addr)), "i" (-EFAULT));		\
+})
+
+extern int __get_user_unknown(void);
+
+#define __put_user_nocheck(x, ptr, size)			\
+({								\
+	union {							\
+		__typeof__(*(ptr)) val;				\
+		u32 bits[2];					\
+	} __pu_val;						\
+	unsigned long __pu_addr;				\
+	int __pu_err;						\
+	__pu_val.val = (x);					\
+	__pu_addr = (unsigned long) (ptr);			\
+	switch (size) {						\
+	case 1:  __put_user_asm("bu"); break;			\
+	case 2:  __put_user_asm("hu"); break;			\
+	case 4:  __put_user_asm(""  ); break;			\
+	case 8:  __put_user_asm8();    break;			\
+	default: __pu_err = __put_user_unknown(); break;	\
+	}							\
+	__pu_err;						\
+})
+
+#define __put_user_check(x, ptr, size)					\
+({									\
+	union {								\
+		__typeof__(*(ptr)) val;					\
+		u32 bits[2];						\
+	} __pu_val;							\
+	unsigned long __pu_addr;					\
+	int __pu_err;							\
+	__pu_val.val = (x);						\
+	__pu_addr = (unsigned long) (ptr);				\
+	if (likely(__access_ok(__pu_addr, size))) {			\
+		switch (size) {						\
+		case 1:  __put_user_asm("bu"); break;			\
+		case 2:  __put_user_asm("hu"); break;			\
+		case 4:  __put_user_asm(""  ); break;			\
+		case 8:  __put_user_asm8();    break;			\
+		default: __pu_err = __put_user_unknown(); break;	\
+		}							\
+	}								\
+	else {								\
+		__pu_err = -EFAULT;					\
+	}								\
+	__pu_err;							\
+})
+
+#define __put_user_asm(INSN)					\
+({								\
+	asm volatile(						\
+		"1:\n"						\
+		"	mov"INSN"	%1,%2\n"		\
+		"	mov		0,%0\n"			\
+		"2:\n"						\
+		"	.section	.fixup,\"ax\"\n"	\
+		"3:\n"						\
+		"	mov		%3,%0\n"		\
+		"	jmp		2b\n"			\
+		"	.previous\n"				\
+		"	.section	__ex_table,\"a\"\n"	\
+		"	.balign		4\n"			\
+		"	.long		1b, 3b\n"		\
+		"	.previous"				\
+		: "=&r" (__pu_err)				\
+		: "r" (__pu_val.val), "m" (__m(__pu_addr)),	\
+		  "i" (-EFAULT)					\
+		);						\
+})
+
+#define __put_user_asm8()						\
+({									\
+	asm volatile(							\
+		"1:	mov		%1,%3		\n"		\
+		"2:	mov		%2,%4		\n"		\
+		"	mov		0,%0		\n"		\
+		"3:					\n"		\
+		"	.section	.fixup,\"ax\"	\n"		\
+		"4:					\n"		\
+		"	mov		%5,%0		\n"		\
+		"	jmp		3b		\n"		\
+		"	.previous			\n"		\
+		"	.section	__ex_table,\"a\"\n"		\
+		"	.balign		4		\n"		\
+		"	.long		1b, 4b		\n"		\
+		"	.long		2b, 4b		\n"		\
+		"	.previous			\n"		\
+		: "=&r" (__pu_err)					\
+		: "r" (__pu_val.bits[0]), "r" (__pu_val.bits[1]),	\
+		  "m" (__m(__pu_addr)), "m" (__m(__pu_addr+4)),		\
+		  "i" (-EFAULT)						\
+		);							\
+})
+
+extern int __put_user_unknown(void);
+
+
+/*
+ * Copy To/From Userspace
+ */
+/* Generic arbitrary sized copy.  */
+#define __copy_user(to, from, size)					\
+do {									\
+	if (size) {							\
+		void *__to = to;					\
+		const void *__from = from;				\
+		int w;							\
+		asm volatile(						\
+			"0:     movbu	(%0),%3;\n"			\
+			"1:     movbu	%3,(%1);\n"			\
+			"	inc	%0;\n"				\
+			"	inc	%1;\n"				\
+			"       add	-1,%2;\n"			\
+			"       bne	0b;\n"				\
+			"2:\n"						\
+			"	.section .fixup,\"ax\"\n"		\
+			"3:	jmp	2b\n"				\
+			"	.previous\n"				\
+			"	.section __ex_table,\"a\"\n"		\
+			"       .balign	4\n"				\
+			"       .long	0b,3b\n"			\
+			"       .long	1b,3b\n"			\
+			"	.previous\n"				\
+			: "=a"(__from), "=a"(__to), "=r"(size), "=&r"(w)\
+			: "0"(__from), "1"(__to), "2"(size)		\
+			: "cc", "memory");				\
+	}								\
+} while (0)
+
+#define __copy_user_zeroing(to, from, size)				\
+do {									\
+	if (size) {							\
+		void *__to = to;					\
+		const void *__from = from;				\
+		int w;							\
+		asm volatile(						\
+			"0:     movbu	(%0),%3;\n"			\
+			"1:     movbu	%3,(%1);\n"			\
+			"	inc	%0;\n"				\
+			"	inc	%1;\n"				\
+			"       add	-1,%2;\n"			\
+			"       bne	0b;\n"				\
+			"2:\n"						\
+			"	.section .fixup,\"ax\"\n"		\
+			"3:\n"						\
+			"	mov	%2,%0\n"			\
+			"	clr	%3\n"				\
+			"4:     movbu	%3,(%1);\n"			\
+			"	inc	%1;\n"				\
+			"       add	-1,%2;\n"			\
+			"       bne	4b;\n"				\
+			"	mov	%0,%2\n"			\
+			"	jmp	2b\n"				\
+			"	.previous\n"				\
+			"	.section __ex_table,\"a\"\n"		\
+			"       .balign	4\n"				\
+			"       .long	0b,3b\n"			\
+			"       .long	1b,3b\n"			\
+			"	.previous\n"				\
+			: "=a"(__from), "=a"(__to), "=r"(size), "=&r"(w)\
+			: "0"(__from), "1"(__to), "2"(size)		\
+			: "cc", "memory");				\
+	}								\
+} while (0)
+
+/* We let the __ versions of copy_from/to_user inline, because they're often
+ * used in fast paths and have only a small space overhead.
+ */
+static inline
+unsigned long __generic_copy_from_user_nocheck(void *to, const void *from,
+					       unsigned long n)
+{
+	__copy_user_zeroing(to, from, n);
+	return n;
+}
+
+static inline
+unsigned long __generic_copy_to_user_nocheck(void *to, const void *from,
+					     unsigned long n)
+{
+	__copy_user(to, from, n);
+	return n;
+}
+
+
+#if 0
+#error "don't use - these macros don't increment to & from pointers"
+/* Optimize just a little bit when we know the size of the move. */
+#define __constant_copy_user(to, from, size)	\
+do {						\
+	asm volatile(				\
+		"       mov %0,a0;\n"		\
+		"0:     movbu (%1),d3;\n"	\
+		"1:     movbu d3,(%2);\n"	\
+		"       add -1,a0;\n"		\
+		"       bne 0b;\n"		\
+		"2:;"				\
+		".section .fixup,\"ax\"\n"	\
+		"3:	jmp 2b\n"		\
+		".previous\n"			\
+		".section __ex_table,\"a\"\n"	\
+		"       .balign 4\n"		\
+		"       .long 0b,3b\n"		\
+		"       .long 1b,3b\n"		\
+		".previous"			\
+		:				\
+		: "d"(size), "d"(to), "d"(from)	\
+		: "d3", "a0");			\
+} while (0)
+
+/* Optimize just a little bit when we know the size of the move. */
+#define __constant_copy_user_zeroing(to, from, size)	\
+do {							\
+	asm volatile(					\
+		"       mov %0,a0;\n"			\
+		"0:     movbu (%1),d3;\n"		\
+		"1:     movbu d3,(%2);\n"		\
+		"       add -1,a0;\n"			\
+		"       bne 0b;\n"			\
+		"2:;"					\
+		".section .fixup,\"ax\"\n"		\
+		"3:	jmp 2b\n"			\
+		".previous\n"				\
+		".section __ex_table,\"a\"\n"		\
+		"       .balign 4\n"			\
+		"       .long 0b,3b\n"			\
+		"       .long 1b,3b\n"			\
+		".previous"				\
+		:					\
+		: "d"(size), "d"(to), "d"(from)		\
+		: "d3", "a0");				\
+} while (0)
+
+static inline
+unsigned long __constant_copy_to_user(void *to, const void *from,
+				      unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		__constant_copy_user(to, from, n);
+	return n;
+}
+
+static inline
+unsigned long __constant_copy_from_user(void *to, const void *from,
+					unsigned long n)
+{
+	if (access_ok(VERIFY_READ, from, n))
+		__constant_copy_user_zeroing(to, from, n);
+	return n;
+}
+
+static inline
+unsigned long __constant_copy_to_user_nocheck(void *to, const void *from,
+					      unsigned long n)
+{
+	__constant_copy_user(to, from, n);
+	return n;
+}
+
+static inline
+unsigned long __constant_copy_from_user_nocheck(void *to, const void *from,
+						unsigned long n)
+{
+	__constant_copy_user_zeroing(to, from, n);
+	return n;
+}
+#endif
+
+extern unsigned long __generic_copy_to_user(void __user *, const void *,
+					    unsigned long);
+extern unsigned long __generic_copy_from_user(void *, const void __user *,
+					      unsigned long);
+
+#define __copy_to_user_inatomic(to, from, n) \
+	__generic_copy_to_user_nocheck((to), (from), (n))
+#define __copy_from_user_inatomic(to, from, n) \
+	__generic_copy_from_user_nocheck((to), (from), (n))
+
+#define __copy_to_user(to, from, n)			\
+({							\
+	might_fault();					\
+	__copy_to_user_inatomic((to), (from), (n));	\
+})
+
+#define __copy_from_user(to, from, n)			\
+({							\
+	might_fault();					\
+	__copy_from_user_inatomic((to), (from), (n));	\
+})
+
+
+#define copy_to_user(to, from, n)   __generic_copy_to_user((to), (from), (n))
+#define copy_from_user(to, from, n) __generic_copy_from_user((to), (from), (n))
+
+extern long strncpy_from_user(char *dst, const char __user *src, long count);
+extern long __strncpy_from_user(char *dst, const char __user *src, long count);
+extern long strnlen_user(const char __user *str, long n);
+#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
+extern unsigned long clear_user(void __user *mem, unsigned long len);
+extern unsigned long __clear_user(void __user *mem, unsigned long len);
+
+#endif /* _ASM_UACCESS_H */
diff --git a/arch/mn10300/include/asm/ucontext.h b/arch/mn10300/include/asm/ucontext.h
new file mode 100644
index 0000000..fcab5c1
--- /dev/null
+++ b/arch/mn10300/include/asm/ucontext.h
@@ -0,0 +1,22 @@
+/* MN10300 User context
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_UCONTEXT_H
+#define _ASM_UCONTEXT_H
+
+struct ucontext {
+	unsigned long	  uc_flags;
+	struct ucontext  *uc_link;
+	stack_t		  uc_stack;
+	struct sigcontext uc_mcontext;
+	sigset_t	  uc_sigmask;	/* mask last for extensibility */
+};
+
+#endif /* _ASM_UCONTEXT_H */
diff --git a/arch/mn10300/include/asm/unaligned.h b/arch/mn10300/include/asm/unaligned.h
new file mode 100644
index 0000000..0df6713
--- /dev/null
+++ b/arch/mn10300/include/asm/unaligned.h
@@ -0,0 +1,20 @@
+/* MN10300 Unaligned memory access handling
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_MN10300_UNALIGNED_H
+#define _ASM_MN10300_UNALIGNED_H
+
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
+
+#define get_unaligned	__get_unaligned_le
+#define put_unaligned	__put_unaligned_le
+
+#endif /* _ASM_MN10300_UNALIGNED_H */
diff --git a/arch/mn10300/include/asm/unistd.h b/arch/mn10300/include/asm/unistd.h
new file mode 100644
index 0000000..0522468
--- /dev/null
+++ b/arch/mn10300/include/asm/unistd.h
@@ -0,0 +1,47 @@
+/* MN10300 System call number list
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_UNISTD_H
+#define _ASM_UNISTD_H
+
+#include <uapi/asm/unistd.h>
+
+
+#define NR_syscalls 340
+
+/*
+ * specify the deprecated syscalls we want to support on this arch
+ */
+#define __ARCH_WANT_OLD_READDIR
+#define __ARCH_WANT_OLD_STAT
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_IPC
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_SIGNAL
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_WAITPID
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_SELECT
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_CLONE
+
+#endif /* _ASM_UNISTD_H */
diff --git a/arch/mn10300/include/asm/user.h b/arch/mn10300/include/asm/user.h
new file mode 100644
index 0000000..e119390
--- /dev/null
+++ b/arch/mn10300/include/asm/user.h
@@ -0,0 +1,53 @@
+/* MN10300 User process data
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_USER_H
+#define _ASM_USER_H
+
+#include <asm/page.h>
+#include <linux/ptrace.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * When the kernel dumps core, it starts by dumping the user struct - this will
+ * be used by gdb to figure out where the data and stack segments are within
+ * the file, and what virtual addresses to use.
+ */
+struct user {
+	/* We start with the registers, to mimic the way that "memory" is
+	 * returned from the ptrace(3,...) function.
+	 */
+	struct pt_regs regs;		/* Where the registers are actually stored */
+
+	/* The rest of this junk is to help gdb figure out what goes where */
+	unsigned long int u_tsize;	/* Text segment size (pages). */
+	unsigned long int u_dsize;	/* Data segment size (pages). */
+	unsigned long int u_ssize;	/* Stack segment size (pages). */
+	unsigned long start_code;	/* Starting virtual address of text. */
+	unsigned long start_stack;	/* Starting virtual address of stack area.
+					   This is actually the bottom of the stack,
+					   the top of the stack is always found in the
+					   esp register.  */
+	long int signal;		/* Signal that caused the core dump. */
+	int reserved;			/* No longer used */
+	struct user_pt_regs *u_ar0;	/* Used by gdb to help find the values for */
+
+	/* the registers */
+	unsigned long magic;		/* To uniquely identify a core file */
+	char u_comm[32];		/* User command that was responsible */
+};
+#endif
+
+#define NBPG PAGE_SIZE
+#define UPAGES 1
+#define HOST_TEXT_START_ADDR	+(u.start_code)
+#define HOST_STACK_END_ADDR	+(u.start_stack + u.u_ssize * NBPG)
+
+#endif /* _ASM_USER_H */
diff --git a/arch/mn10300/include/asm/vga.h b/arch/mn10300/include/asm/vga.h
new file mode 100644
index 0000000..0163e50
--- /dev/null
+++ b/arch/mn10300/include/asm/vga.h
@@ -0,0 +1,17 @@
+/* MN10300 VGA register definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_VGA_H
+#define _ASM_VGA_H
+
+
+
+#endif /* _ASM_VGA_H */
diff --git a/arch/mn10300/include/asm/xor.h b/arch/mn10300/include/asm/xor.h
new file mode 100644
index 0000000..c82eb12
--- /dev/null
+++ b/arch/mn10300/include/asm/xor.h
@@ -0,0 +1 @@
+#include <asm-generic/xor.h>
diff --git a/arch/mn10300/include/uapi/asm/Kbuild b/arch/mn10300/include/uapi/asm/Kbuild
new file mode 100644
index 0000000..040178c
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/Kbuild
@@ -0,0 +1,34 @@
+# UAPI Header export list
+include include/uapi/asm-generic/Kbuild.asm
+
+header-y += auxvec.h
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += errno.h
+header-y += fcntl.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += kvm_para.h
+header-y += mman.h
+header-y += msgbuf.h
+header-y += param.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += resource.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += statfs.h
+header-y += swab.h
+header-y += termbits.h
+header-y += termios.h
+header-y += types.h
+header-y += unistd.h
diff --git a/arch/mn10300/include/uapi/asm/auxvec.h b/arch/mn10300/include/uapi/asm/auxvec.h
new file mode 100644
index 0000000..4fdb60b
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_AUXVEC_H
+#define _ASM_AUXVEC_H
+
+#endif
diff --git a/arch/mn10300/include/uapi/asm/bitsperlong.h b/arch/mn10300/include/uapi/asm/bitsperlong.h
new file mode 100644
index 0000000..6dc0bb0
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/bitsperlong.h
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff --git a/arch/mn10300/include/uapi/asm/byteorder.h b/arch/mn10300/include/uapi/asm/byteorder.h
new file mode 100644
index 0000000..5dd0bdd
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/byteorder.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_BYTEORDER_H
+#define _ASM_BYTEORDER_H
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_BYTEORDER_H */
diff --git a/arch/mn10300/include/uapi/asm/errno.h b/arch/mn10300/include/uapi/asm/errno.h
new file mode 100644
index 0000000..4c82b50
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/errno.h
@@ -0,0 +1 @@
+#include <asm-generic/errno.h>
diff --git a/arch/mn10300/include/uapi/asm/fcntl.h b/arch/mn10300/include/uapi/asm/fcntl.h
new file mode 100644
index 0000000..46ab12d
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/fcntl.h
@@ -0,0 +1 @@
+#include <asm-generic/fcntl.h>
diff --git a/arch/mn10300/include/uapi/asm/ioctl.h b/arch/mn10300/include/uapi/asm/ioctl.h
new file mode 100644
index 0000000..b279fe0
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/ioctl.h
@@ -0,0 +1 @@
+#include <asm-generic/ioctl.h>
diff --git a/arch/mn10300/include/uapi/asm/ioctls.h b/arch/mn10300/include/uapi/asm/ioctls.h
new file mode 100644
index 0000000..0212f4b
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/ioctls.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_IOCTLS_H
+#define _ASM_IOCTLS_H
+
+#include <asm-generic/ioctls.h>
+
+#endif /* _ASM_IOCTLS_H */
diff --git a/arch/mn10300/include/uapi/asm/ipcbuf.h b/arch/mn10300/include/uapi/asm/ipcbuf.h
new file mode 100644
index 0000000..84c7e51
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/ipcbuf.h
@@ -0,0 +1 @@
+#include <asm-generic/ipcbuf.h>
diff --git a/arch/mn10300/include/uapi/asm/kvm_para.h b/arch/mn10300/include/uapi/asm/kvm_para.h
new file mode 100644
index 0000000..14fab8f
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/kvm_para.h
@@ -0,0 +1 @@
+#include <asm-generic/kvm_para.h>
diff --git a/arch/mn10300/include/uapi/asm/mman.h b/arch/mn10300/include/uapi/asm/mman.h
new file mode 100644
index 0000000..db5c53d
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
+#include <asm-generic/mman.h>
+
+#define MIN_MAP_ADDR	PAGE_SIZE	/* minimum fixed mmap address */
+
+#define arch_mmap_check(addr, len, flags) \
+	(((flags) & MAP_FIXED && (addr) < MIN_MAP_ADDR) ? -EINVAL : 0)
diff --git a/arch/mn10300/include/uapi/asm/msgbuf.h b/arch/mn10300/include/uapi/asm/msgbuf.h
new file mode 100644
index 0000000..8b60245
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/msgbuf.h
@@ -0,0 +1,31 @@
+#ifndef _ASM_MSGBUF_H
+#define _ASM_MSGBUF_H
+
+/*
+ * The msqid64_ds structure for MN10300 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+	struct ipc64_perm	msg_perm;
+	__kernel_time_t		msg_stime;	/* last msgsnd time */
+	unsigned long		__unused1;
+	__kernel_time_t		msg_rtime;	/* last msgrcv time */
+	unsigned long		__unused2;
+	__kernel_time_t		msg_ctime;	/* last change time */
+	unsigned long		__unused3;
+	unsigned long		msg_cbytes;	/* current number of bytes on queue */
+	unsigned long		msg_qnum;	/* number of messages in queue */
+	unsigned long		msg_qbytes;	/* max number of bytes on queue */
+	__kernel_pid_t		msg_lspid;	/* pid of last msgsnd */
+	__kernel_pid_t		msg_lrpid;	/* last receive pid */
+	unsigned long		__unused4;
+	unsigned long		__unused5;
+};
+
+#endif /* _ASM_MSGBUF_H */
diff --git a/arch/mn10300/include/uapi/asm/param.h b/arch/mn10300/include/uapi/asm/param.h
new file mode 100644
index 0000000..02a0ca6
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/param.h
@@ -0,0 +1,18 @@
+/* MN10300 Kernel parameters
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_PARAM_H
+#define _ASM_PARAM_H
+
+#include <asm-generic/param.h>
+
+#define COMMAND_LINE_SIZE 256
+
+#endif /* _ASM_PARAM_H */
diff --git a/arch/mn10300/include/uapi/asm/poll.h b/arch/mn10300/include/uapi/asm/poll.h
new file mode 100644
index 0000000..c98509d
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/poll.h
@@ -0,0 +1 @@
+#include <asm-generic/poll.h>
diff --git a/arch/mn10300/include/uapi/asm/posix_types.h b/arch/mn10300/include/uapi/asm/posix_types.h
new file mode 100644
index 0000000..d31eeea
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/posix_types.h
@@ -0,0 +1,45 @@
+/* MN10300 POSIX types
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_POSIX_TYPES_H
+#define _ASM_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short	__kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
+typedef unsigned short	__kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
+typedef unsigned short	__kernel_uid_t;
+typedef unsigned short	__kernel_gid_t;
+#define __kernel_uid_t __kernel_uid_t
+
+#if __GNUC__ == 4
+typedef unsigned int	__kernel_size_t;
+typedef signed int	__kernel_ssize_t;
+#else
+typedef unsigned long	__kernel_size_t;
+typedef signed long	__kernel_ssize_t;
+#endif
+typedef int		__kernel_ptrdiff_t;
+#define __kernel_size_t __kernel_size_t
+
+typedef unsigned short	__kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
+
+#endif /* _ASM_POSIX_TYPES_H */
diff --git a/arch/mn10300/include/uapi/asm/ptrace.h b/arch/mn10300/include/uapi/asm/ptrace.h
new file mode 100644
index 0000000..71b2251
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/ptrace.h
@@ -0,0 +1,84 @@
+/* MN10300 Exception frame layout and ptrace constants
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _UAPI_ASM_PTRACE_H
+#define _UAPI_ASM_PTRACE_H
+
+#define PT_A3		0
+#define PT_A2		1
+#define PT_D3		2
+#define	PT_D2		3
+#define PT_MCVF		4
+#define	PT_MCRL		5
+#define PT_MCRH		6
+#define	PT_MDRQ		7
+#define	PT_E1		8
+#define	PT_E0		9
+#define	PT_E7		10
+#define	PT_E6		11
+#define	PT_E5		12
+#define	PT_E4		13
+#define	PT_E3		14
+#define	PT_E2		15
+#define	PT_SP		16
+#define	PT_LAR		17
+#define	PT_LIR		18
+#define	PT_MDR		19
+#define	PT_A1		20
+#define	PT_A0		21
+#define	PT_D1		22
+#define	PT_D0		23
+#define PT_ORIG_D0	24
+#define	PT_EPSW		25
+#define	PT_PC		26
+#define NR_PTREGS	27
+
+/*
+ * This defines the way registers are stored in the event of an exception
+ * - the strange order is due to the MOVM instruction
+ */
+struct pt_regs {
+	unsigned long		a3;		/* syscall arg 3 */
+	unsigned long		a2;		/* syscall arg 4 */
+	unsigned long		d3;		/* syscall arg 5 */
+	unsigned long		d2;		/* syscall arg 6 */
+	unsigned long		mcvf;
+	unsigned long		mcrl;
+	unsigned long		mcrh;
+	unsigned long		mdrq;
+	unsigned long		e1;
+	unsigned long		e0;
+	unsigned long		e7;
+	unsigned long		e6;
+	unsigned long		e5;
+	unsigned long		e4;
+	unsigned long		e3;
+	unsigned long		e2;
+	unsigned long		sp;
+	unsigned long		lar;
+	unsigned long		lir;
+	unsigned long		mdr;
+	unsigned long		a1;
+	unsigned long		a0;		/* syscall arg 1 */
+	unsigned long		d1;		/* syscall arg 2 */
+	unsigned long		d0;		/* syscall ret */
+	struct pt_regs		*next;		/* next frame pointer */
+	unsigned long		orig_d0;	/* syscall number */
+	unsigned long		epsw;
+	unsigned long		pc;
+};
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+
+#endif /* _UAPI_ASM_PTRACE_H */
diff --git a/arch/mn10300/include/uapi/asm/resource.h b/arch/mn10300/include/uapi/asm/resource.h
new file mode 100644
index 0000000..04bc4db
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/resource.h
@@ -0,0 +1 @@
+#include <asm-generic/resource.h>
diff --git a/arch/mn10300/include/uapi/asm/sembuf.h b/arch/mn10300/include/uapi/asm/sembuf.h
new file mode 100644
index 0000000..301f3f9
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/sembuf.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_SEMBUF_H
+#define _ASM_SEMBUF_H
+
+/*
+ * The semid64_ds structure for MN10300 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
+	__kernel_time_t	sem_otime;		/* last semop time */
+	unsigned long	__unused1;
+	__kernel_time_t	sem_ctime;		/* last change time */
+	unsigned long	__unused2;
+	unsigned long	sem_nsems;		/* no. of semaphores in array */
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _ASM_SEMBUF_H */
diff --git a/arch/mn10300/include/uapi/asm/setup.h b/arch/mn10300/include/uapi/asm/setup.h
new file mode 100644
index 0000000..ae5704f
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/setup.h
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here anymore, but the file must not be empty or patch
+ * will delete it.
+ */
diff --git a/arch/mn10300/include/uapi/asm/shmbuf.h b/arch/mn10300/include/uapi/asm/shmbuf.h
new file mode 100644
index 0000000..8f300cc
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/shmbuf.h
@@ -0,0 +1,42 @@
+#ifndef _ASM_SHMBUF_H
+#define _ASM_SHMBUF_H
+
+/*
+ * The shmid64_ds structure for MN10300 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+	struct ipc64_perm	shm_perm;	/* operation perms */
+	size_t			shm_segsz;	/* size of segment (bytes) */
+	__kernel_time_t		shm_atime;	/* last attach time */
+	unsigned long		__unused1;
+	__kernel_time_t		shm_dtime;	/* last detach time */
+	unsigned long		__unused2;
+	__kernel_time_t		shm_ctime;	/* last change time */
+	unsigned long		__unused3;
+	__kernel_pid_t		shm_cpid;	/* pid of creator */
+	__kernel_pid_t		shm_lpid;	/* pid of last operator */
+	unsigned long		shm_nattch;	/* no. of current attaches */
+	unsigned long		__unused4;
+	unsigned long		__unused5;
+};
+
+struct shminfo64 {
+	unsigned long	shmmax;
+	unsigned long	shmmin;
+	unsigned long	shmmni;
+	unsigned long	shmseg;
+	unsigned long	shmall;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _ASM_SHMBUF_H */
diff --git a/arch/mn10300/include/uapi/asm/sigcontext.h b/arch/mn10300/include/uapi/asm/sigcontext.h
new file mode 100644
index 0000000..4de3aff
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/sigcontext.h
@@ -0,0 +1,52 @@
+/* MN10300 Userspace signal context
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_SIGCONTEXT_H
+#define _ASM_SIGCONTEXT_H
+
+struct fpucontext {
+	/* Regular FPU environment */
+	unsigned long	fs[32];		/* fpu registers */
+	unsigned long	fpcr;		/* fpu control register */
+};
+
+struct sigcontext {
+	unsigned long	d0;
+	unsigned long	d1;
+	unsigned long	d2;
+	unsigned long	d3;
+	unsigned long	a0;
+	unsigned long	a1;
+	unsigned long	a2;
+	unsigned long	a3;
+	unsigned long	e0;
+	unsigned long	e1;
+	unsigned long	e2;
+	unsigned long	e3;
+	unsigned long	e4;
+	unsigned long	e5;
+	unsigned long	e6;
+	unsigned long	e7;
+	unsigned long	lar;
+	unsigned long	lir;
+	unsigned long	mdr;
+	unsigned long	mcvf;
+	unsigned long	mcrl;
+	unsigned long	mcrh;
+	unsigned long	mdrq;
+	unsigned long	sp;
+	unsigned long	epsw;
+	unsigned long	pc;
+	struct fpucontext *fpucontext;
+	unsigned long	oldmask;
+};
+
+
+#endif /* _ASM_SIGCONTEXT_H */
diff --git a/arch/mn10300/include/uapi/asm/siginfo.h b/arch/mn10300/include/uapi/asm/siginfo.h
new file mode 100644
index 0000000..0815d29
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/siginfo.h
@@ -0,0 +1 @@
+#include <asm-generic/siginfo.h>
diff --git a/arch/mn10300/include/uapi/asm/signal.h b/arch/mn10300/include/uapi/asm/signal.h
new file mode 100644
index 0000000..f423a08
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/signal.h
@@ -0,0 +1,125 @@
+/* MN10300 Signal definitions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _UAPI_ASM_SIGNAL_H
+#define _UAPI_ASM_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG		32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+#define SIGBUS		 7
+#define SIGFPE		 8
+#define SIGKILL		 9
+#define SIGUSR1		10
+#define SIGSEGV		11
+#define SIGUSR2		12
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGSTKFLT	16
+#define SIGCHLD		17
+#define SIGCONT		18
+#define SIGSTOP		19
+#define SIGTSTP		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGURG		23
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGIO		29
+#define SIGPOLL		SIGIO
+/*
+#define SIGLOST		29
+*/
+#define SIGPWR		30
+#define SIGSYS		31
+#define	SIGUNUSED	31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN	32
+#define SIGRTMAX	_NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP	0x00000001U
+#define SA_NOCLDWAIT	0x00000002U
+#define SA_SIGINFO	0x00000004U
+#define SA_ONSTACK	0x08000000U
+#define SA_RESTART	0x10000000U
+#define SA_NODEFER	0x40000000U
+#define SA_RESETHAND	0x80000000U
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+
+#define SA_RESTORER	0x04000000
+
+#define MINSIGSTKSZ	2048
+#define SIGSTKSZ	8192
+
+#include <asm-generic/signal-defs.h>
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+	union {
+	  __sighandler_t _sa_handler;
+	  void (*_sa_sigaction)(int, struct siginfo *, void *);
+	} _u;
+	sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+#define sa_handler	_u._sa_handler
+#define sa_sigaction	_u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+	void __user	*ss_sp;
+	int		ss_flags;
+	size_t		ss_size;
+} stack_t;
+
+
+#endif /* _UAPI_ASM_SIGNAL_H */
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
new file mode 100644
index 0000000..cab7d6d
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -0,0 +1,88 @@
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockopt(2) */
+#define SOL_SOCKET	1
+
+#define SO_DEBUG	1
+#define SO_REUSEADDR	2
+#define SO_TYPE		3
+#define SO_ERROR	4
+#define SO_DONTROUTE	5
+#define SO_BROADCAST	6
+#define SO_SNDBUF	7
+#define SO_RCVBUF	8
+#define SO_SNDBUFFORCE	32
+#define SO_RCVBUFFORCE	33
+#define SO_KEEPALIVE	9
+#define SO_OOBINLINE	10
+#define SO_NO_CHECK	11
+#define SO_PRIORITY	12
+#define SO_LINGER	13
+#define SO_BSDCOMPAT	14
+#define SO_REUSEPORT	15
+#define SO_PASSCRED	16
+#define SO_PEERCRED	17
+#define SO_RCVLOWAT	18
+#define SO_SNDLOWAT	19
+#define SO_RCVTIMEO	20
+#define SO_SNDTIMEO	21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION		22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
+#define SO_SECURITY_ENCRYPTION_NETWORK		24
+
+#define SO_BINDTODEVICE	25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+#define SO_GET_FILTER		SO_ATTACH_FILTER
+
+#define SO_PEERNAME		28
+#define SO_TIMESTAMP		29
+#define SCM_TIMESTAMP		SO_TIMESTAMP
+
+#define SO_ACCEPTCONN		30
+
+#define SO_PEERSEC		31
+#define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
+
+#define SO_MARK			36
+
+#define SO_TIMESTAMPING		37
+#define SCM_TIMESTAMPING	SO_TIMESTAMPING
+
+#define SO_PROTOCOL		38
+#define SO_DOMAIN		39
+
+#define SO_RXQ_OVFL             40
+
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+#define SO_PEEK_OFF		42
+
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS		43
+
+#define SO_LOCK_FILTER		44
+
+#define SO_SELECT_ERR_QUEUE	45
+
+#define SO_BUSY_POLL		46
+
+#define SO_MAX_PACING_RATE	47
+
+#define SO_BPF_EXTENSIONS	48
+
+#define SO_INCOMING_CPU		49
+
+#define SO_ATTACH_BPF		50
+#define SO_DETACH_BPF		SO_DETACH_FILTER
+
+#endif /* _ASM_SOCKET_H */
diff --git a/arch/mn10300/include/uapi/asm/sockios.h b/arch/mn10300/include/uapi/asm/sockios.h
new file mode 100644
index 0000000..b03043a
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/sockios.h
@@ -0,0 +1,13 @@
+#ifndef _ASM_SOCKIOS_H
+#define _ASM_SOCKIOS_H
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN 	0x8901
+#define SIOCSPGRP	0x8902
+#define FIOGETOWN	0x8903
+#define SIOCGPGRP	0x8904
+#define SIOCATMARK	0x8905
+#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
+
+#endif /* _ASM_SOCKIOS_H */
diff --git a/arch/mn10300/include/uapi/asm/stat.h b/arch/mn10300/include/uapi/asm/stat.h
new file mode 100644
index 0000000..63ff837
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/stat.h
@@ -0,0 +1,78 @@
+#ifndef _ASM_STAT_H
+#define _ASM_STAT_H
+
+struct __old_kernel_stat {
+	unsigned short st_dev;
+	unsigned short st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned long  st_size;
+	unsigned long  st_atime;
+	unsigned long  st_mtime;
+	unsigned long  st_ctime;
+};
+
+struct stat {
+	unsigned long  st_dev;
+	unsigned long  st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned long  st_rdev;
+	unsigned long  st_size;
+	unsigned long  st_blksize;
+	unsigned long  st_blocks;
+	unsigned long  st_atime;
+	unsigned long  st_atime_nsec;
+	unsigned long  st_mtime;
+	unsigned long  st_mtime_nsec;
+	unsigned long  st_ctime;
+	unsigned long  st_ctime_nsec;
+	unsigned long  __unused4;
+	unsigned long  __unused5;
+};
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+	unsigned long long	st_dev;
+	unsigned char	__pad0[4];
+
+#define STAT64_HAS_BROKEN_ST_INO	1
+	unsigned long	__st_ino;
+
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+
+	unsigned long	st_uid;
+	unsigned long	st_gid;
+
+	unsigned long long	st_rdev;
+	unsigned char	__pad3[4];
+
+	long long	st_size;
+	unsigned long	st_blksize;
+
+	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
+	unsigned long	__pad4;		/* future possible st_blocks high bits */
+
+	unsigned long	st_atime;
+	unsigned long	st_atime_nsec;
+
+	unsigned long	st_mtime;
+	unsigned int	st_mtime_nsec;
+
+	unsigned long	st_ctime;
+	unsigned long	st_ctime_nsec;
+
+	unsigned long long	st_ino;
+};
+
+#define STAT_HAVE_NSEC 1
+
+#endif /* _ASM_STAT_H */
diff --git a/arch/mn10300/include/uapi/asm/statfs.h b/arch/mn10300/include/uapi/asm/statfs.h
new file mode 100644
index 0000000..0b91fe1
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/statfs.h
@@ -0,0 +1 @@
+#include <asm-generic/statfs.h>
diff --git a/arch/mn10300/include/uapi/asm/swab.h b/arch/mn10300/include/uapi/asm/swab.h
new file mode 100644
index 0000000..bd818a8
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/swab.h
@@ -0,0 +1,42 @@
+/* MN10300 Byte-order primitive construction
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_SWAB_H
+#define _ASM_SWAB_H
+
+#include <linux/types.h>
+
+#ifdef __GNUC__
+
+static inline __attribute__((const))
+__u32 __arch_swab32(__u32 x)
+{
+	__u32 ret;
+	asm("swap %1,%0" : "=r" (ret) : "r" (x));
+	return ret;
+}
+#define __arch_swab32 __arch_swab32
+
+static inline __attribute__((const))
+__u16 __arch_swab16(__u16 x)
+{
+	__u16 ret;
+	asm("swaph %1,%0" : "=r" (ret) : "r" (x));
+	return ret;
+}
+#define __arch_swab32 __arch_swab32
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __SWAB_64_THRU_32__
+#endif
+
+#endif /* __GNUC__ */
+
+#endif /* _ASM_SWAB_H */
diff --git a/arch/mn10300/include/uapi/asm/termbits.h b/arch/mn10300/include/uapi/asm/termbits.h
new file mode 100644
index 0000000..130d424
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/termbits.h
@@ -0,0 +1,201 @@
+#ifndef _ASM_TERMBITS_H
+#define _ASM_TERMBITS_H
+
+#include <linux/posix_types.h>
+
+typedef unsigned char	cc_t;
+typedef unsigned int	speed_t;
+typedef unsigned int	tcflag_t;
+
+#define NCCS 19
+struct termios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+};
+
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
+struct ktermios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+
+/* c_iflag bits */
+#define IGNBRK	0000001
+#define BRKINT	0000002
+#define IGNPAR	0000004
+#define PARMRK	0000010
+#define INPCK	0000020
+#define ISTRIP	0000040
+#define INLCR	0000100
+#define IGNCR	0000200
+#define ICRNL	0000400
+#define IUCLC	0001000
+#define IXON	0002000
+#define IXANY	0004000
+#define IXOFF	0010000
+#define IMAXBEL	0020000
+#define IUTF8	0040000
+
+/* c_oflag bits */
+#define OPOST	0000001
+#define OLCUC	0000002
+#define ONLCR	0000004
+#define OCRNL	0000010
+#define ONOCR	0000020
+#define ONLRET	0000040
+#define OFILL	0000100
+#define OFDEL	0000200
+#define NLDLY	0000400
+#define   NL0	0000000
+#define   NL1	0000400
+#define CRDLY	0003000
+#define   CR0	0000000
+#define   CR1	0001000
+#define   CR2	0002000
+#define   CR3	0003000
+#define TABDLY	0014000
+#define   TAB0	0000000
+#define   TAB1	0004000
+#define   TAB2	0010000
+#define   TAB3	0014000
+#define   XTABS	0014000
+#define BSDLY	0020000
+#define   BS0	0000000
+#define   BS1	0020000
+#define VTDLY	0040000
+#define   VT0	0000000
+#define   VT1	0040000
+#define FFDLY	0100000
+#define   FF0	0000000
+#define   FF1	0100000
+
+/* c_cflag bit meaning */
+#define CBAUD	0010017
+#define  B0	0000000		/* hang up */
+#define  B50	0000001
+#define  B75	0000002
+#define  B110	0000003
+#define  B134	0000004
+#define  B150	0000005
+#define  B200	0000006
+#define  B300	0000007
+#define  B600	0000010
+#define  B1200	0000011
+#define  B1800	0000012
+#define  B2400	0000013
+#define  B4800	0000014
+#define  B9600	0000015
+#define  B19200	0000016
+#define  B38400	0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE	0000060
+#define   CS5	0000000
+#define   CS6	0000020
+#define   CS7	0000040
+#define   CS8	0000060
+#define CSTOPB	0000100
+#define CREAD	0000200
+#define PARENB	0000400
+#define PARODD	0001000
+#define HUPCL	0002000
+#define CLOCAL	0004000
+#define CBAUDEX 0010000
+#define   BOTHER  0010000
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CTVB	  004000000000		/* VisioBraille Terminal flow control */
+#define CMSPAR	  010000000000		/* mark or space (stick) parity */
+#define CRTSCTS	  020000000000		/* flow control */
+
+#define IBSHIFT	  16		/* Shift from CBAUD to CIBAUD */
+
+/* c_lflag bits */
+#define ISIG	0000001
+#define ICANON	0000002
+#define XCASE	0000004
+#define ECHO	0000010
+#define ECHOE	0000020
+#define ECHOK	0000040
+#define ECHONL	0000100
+#define NOFLSH	0000200
+#define TOSTOP	0000400
+#define ECHOCTL	0001000
+#define ECHOPRT	0002000
+#define ECHOKE	0004000
+#define FLUSHO	0010000
+#define PENDIN	0040000
+#define IEXTEN	0100000
+#define EXTPROC	0200000
+
+/* tcflow() and TCXONC use these */
+#define	TCOOFF		0
+#define	TCOON		1
+#define	TCIOFF		2
+#define	TCION		3
+
+/* tcflush() and TCFLSH use these */
+#define	TCIFLUSH	0
+#define	TCOFLUSH	1
+#define	TCIOFLUSH	2
+
+/* tcsetattr uses these */
+#define	TCSANOW		0
+#define	TCSADRAIN	1
+#define	TCSAFLUSH	2
+
+#endif /* _ASM_TERMBITS_H */
diff --git a/arch/mn10300/include/uapi/asm/termios.h b/arch/mn10300/include/uapi/asm/termios.h
new file mode 100644
index 0000000..11d3cc9
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/termios.h
@@ -0,0 +1,83 @@
+#ifndef _UAPI_ASM_TERMIOS_H
+#define _UAPI_ASM_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+	unsigned short ws_row;
+	unsigned short ws_col;
+	unsigned short ws_xpixel;
+	unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	unsigned char c_line;		/* line discipline */
+	unsigned char c_cc[NCC];	/* control characters */
+};
+
+
+/* modem lines */
+#define TIOCM_LE	0x001
+#define TIOCM_DTR	0x002
+#define TIOCM_RTS	0x004
+#define TIOCM_ST	0x008
+#define TIOCM_SR	0x010
+#define TIOCM_CTS	0x020
+#define TIOCM_CAR	0x040
+#define TIOCM_RNG	0x080
+#define TIOCM_DSR	0x100
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RI	TIOCM_RNG
+#define TIOCM_OUT1	0x2000
+#define TIOCM_OUT2	0x4000
+#define TIOCM_LOOP	0x8000
+
+#define TIOCM_MODEM_BITS       TIOCM_OUT2      /* IRDA support */
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
+	unsigned short __tmp; \
+	get_user(__tmp, &(termio)->x); \
+	*(unsigned short *) &(termios)->x = __tmp; \
+}
+
+#define user_termio_to_kernel_termios(termios, termio) \
+({ \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
+	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+#define kernel_termios_to_user_termio(termio, termios) \
+({ \
+	put_user((termios)->c_iflag, &(termio)->c_iflag); \
+	put_user((termios)->c_oflag, &(termio)->c_oflag); \
+	put_user((termios)->c_cflag, &(termio)->c_cflag); \
+	put_user((termios)->c_lflag, &(termio)->c_lflag); \
+	put_user((termios)->c_line,  &(termio)->c_line); \
+	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+})
+
+#define user_termios_to_kernel_termios(k, u) \
+	copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) \
+	copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) \
+	copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) \
+	copy_to_user(u, k, sizeof(struct termios))
+
+#endif /* _UAPI_ASM_TERMIOS_H */
diff --git a/arch/mn10300/include/uapi/asm/types.h b/arch/mn10300/include/uapi/asm/types.h
new file mode 100644
index 0000000..8b3f050
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/types.h
@@ -0,0 +1,11 @@
+/* MN10300 Basic type definitions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm-generic/int-ll64.h>
diff --git a/arch/mn10300/include/uapi/asm/unistd.h b/arch/mn10300/include/uapi/asm/unistd.h
new file mode 100644
index 0000000..e28ac3f
--- /dev/null
+++ b/arch/mn10300/include/uapi/asm/unistd.h
@@ -0,0 +1,354 @@
+/* MN10300 System call number list
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _UAPI_ASM_UNISTD_H
+#define _UAPI_ASM_UNISTD_H
+
+#define __NR_restart_syscall      0
+#define __NR_exit		  1
+#define __NR_fork		  2
+#define __NR_read		  3
+#define __NR_write		  4
+#define __NR_open		  5
+#define __NR_close		  6
+#define __NR_waitpid		  7
+#define __NR_creat		  8
+#define __NR_link		  9
+#define __NR_unlink		 10
+#define __NR_execve		 11
+#define __NR_chdir		 12
+#define __NR_time		 13
+#define __NR_mknod		 14
+#define __NR_chmod		 15
+#define __NR_lchown		 16
+#define __NR_break		 17
+#define __NR_oldstat		 18
+#define __NR_lseek		 19
+#define __NR_getpid		 20
+#define __NR_mount		 21
+#define __NR_umount		 22
+#define __NR_setuid		 23
+#define __NR_getuid		 24
+#define __NR_stime		 25
+#define __NR_ptrace		 26
+#define __NR_alarm		 27
+#define __NR_oldfstat		 28
+#define __NR_pause		 29
+#define __NR_utime		 30
+#define __NR_stty		 31
+#define __NR_gtty		 32
+#define __NR_access		 33
+#define __NR_nice		 34
+#define __NR_ftime		 35
+#define __NR_sync		 36
+#define __NR_kill		 37
+#define __NR_rename		 38
+#define __NR_mkdir		 39
+#define __NR_rmdir		 40
+#define __NR_dup		 41
+#define __NR_pipe		 42
+#define __NR_times		 43
+#define __NR_prof		 44
+#define __NR_brk		 45
+#define __NR_setgid		 46
+#define __NR_getgid		 47
+#define __NR_signal		 48
+#define __NR_geteuid		 49
+#define __NR_getegid		 50
+#define __NR_acct		 51
+#define __NR_umount2		 52
+#define __NR_lock		 53
+#define __NR_ioctl		 54
+#define __NR_fcntl		 55
+#define __NR_mpx		 56
+#define __NR_setpgid		 57
+#define __NR_ulimit		 58
+#define __NR_oldolduname	 59
+#define __NR_umask		 60
+#define __NR_chroot		 61
+#define __NR_ustat		 62
+#define __NR_dup2		 63
+#define __NR_getppid		 64
+#define __NR_getpgrp		 65
+#define __NR_setsid		 66
+#define __NR_sigaction		 67
+#define __NR_sgetmask		 68
+#define __NR_ssetmask		 69
+#define __NR_setreuid		 70
+#define __NR_setregid		 71
+#define __NR_sigsuspend		 72
+#define __NR_sigpending		 73
+#define __NR_sethostname	 74
+#define __NR_setrlimit		 75
+#define __NR_getrlimit		 76	/* Back compatible 2Gig limited rlimit */
+#define __NR_getrusage		 77
+#define __NR_gettimeofday	 78
+#define __NR_settimeofday	 79
+#define __NR_getgroups		 80
+#define __NR_setgroups		 81
+#define __NR_select		 82
+#define __NR_symlink		 83
+#define __NR_oldlstat		 84
+#define __NR_readlink		 85
+#define __NR_uselib		 86
+#define __NR_swapon		 87
+#define __NR_reboot		 88
+#define __NR_readdir		 89
+#define __NR_mmap		 90
+#define __NR_munmap		 91
+#define __NR_truncate		 92
+#define __NR_ftruncate		 93
+#define __NR_fchmod		 94
+#define __NR_fchown		 95
+#define __NR_getpriority	 96
+#define __NR_setpriority	 97
+#define __NR_profil		 98
+#define __NR_statfs		 99
+#define __NR_fstatfs		100
+#define __NR_ioperm		101
+#define __NR_socketcall		102
+#define __NR_syslog		103
+#define __NR_setitimer		104
+#define __NR_getitimer		105
+#define __NR_stat		106
+#define __NR_lstat		107
+#define __NR_fstat		108
+#define __NR_olduname		109
+#define __NR_iopl		110
+#define __NR_vhangup		111
+#define __NR_idle		112
+#define __NR_vm86old		113
+#define __NR_wait4		114
+#define __NR_swapoff		115
+#define __NR_sysinfo		116
+#define __NR_ipc		117
+#define __NR_fsync		118
+#define __NR_sigreturn		119
+#define __NR_clone		120
+#define __NR_setdomainname	121
+#define __NR_uname		122
+#define __NR_modify_ldt		123
+#define __NR_adjtimex		124
+#define __NR_mprotect		125
+#define __NR_sigprocmask	126
+#define __NR_create_module	127
+#define __NR_init_module	128
+#define __NR_delete_module	129
+#define __NR_get_kernel_syms	130
+#define __NR_quotactl		131
+#define __NR_getpgid		132
+#define __NR_fchdir		133
+#define __NR_bdflush		134
+#define __NR_sysfs		135
+#define __NR_personality	136
+#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
+#define __NR_setfsuid		138
+#define __NR_setfsgid		139
+#define __NR__llseek		140
+#define __NR_getdents		141
+#define __NR__newselect		142
+#define __NR_flock		143
+#define __NR_msync		144
+#define __NR_readv		145
+#define __NR_writev		146
+#define __NR_getsid		147
+#define __NR_fdatasync		148
+#define __NR__sysctl		149
+#define __NR_mlock		150
+#define __NR_munlock		151
+#define __NR_mlockall		152
+#define __NR_munlockall		153
+#define __NR_sched_setparam		154
+#define __NR_sched_getparam		155
+#define __NR_sched_setscheduler		156
+#define __NR_sched_getscheduler		157
+#define __NR_sched_yield		158
+#define __NR_sched_get_priority_max	159
+#define __NR_sched_get_priority_min	160
+#define __NR_sched_rr_get_interval	161
+#define __NR_nanosleep		162
+#define __NR_mremap		163
+#define __NR_setresuid		164
+#define __NR_getresuid		165
+#define __NR_vm86		166
+#define __NR_query_module	167
+#define __NR_poll		168
+#define __NR_nfsservctl		169
+#define __NR_setresgid		170
+#define __NR_getresgid		171
+#define __NR_prctl              172
+#define __NR_rt_sigreturn	173
+#define __NR_rt_sigaction	174
+#define __NR_rt_sigprocmask	175
+#define __NR_rt_sigpending	176
+#define __NR_rt_sigtimedwait	177
+#define __NR_rt_sigqueueinfo	178
+#define __NR_rt_sigsuspend	179
+#define __NR_pread64		180
+#define __NR_pwrite64		181
+#define __NR_chown		182
+#define __NR_getcwd		183
+#define __NR_capget		184
+#define __NR_capset		185
+#define __NR_sigaltstack	186
+#define __NR_sendfile		187
+#define __NR_getpmsg		188	/* some people actually want streams */
+#define __NR_putpmsg		189	/* some people actually want streams */
+#define __NR_vfork		190
+#define __NR_ugetrlimit		191	/* SuS compliant getrlimit */
+#define __NR_mmap2		192
+#define __NR_truncate64		193
+#define __NR_ftruncate64	194
+#define __NR_stat64		195
+#define __NR_lstat64		196
+#define __NR_fstat64		197
+#define __NR_lchown32		198
+#define __NR_getuid32		199
+#define __NR_getgid32		200
+#define __NR_geteuid32		201
+#define __NR_getegid32		202
+#define __NR_setreuid32		203
+#define __NR_setregid32		204
+#define __NR_getgroups32	205
+#define __NR_setgroups32	206
+#define __NR_fchown32		207
+#define __NR_setresuid32	208
+#define __NR_getresuid32	209
+#define __NR_setresgid32	210
+#define __NR_getresgid32	211
+#define __NR_chown32		212
+#define __NR_setuid32		213
+#define __NR_setgid32		214
+#define __NR_setfsuid32		215
+#define __NR_setfsgid32		216
+#define __NR_pivot_root		217
+#define __NR_mincore		218
+#define __NR_madvise		219
+#define __NR_madvise1		219	/* delete when C lib stub is removed */
+#define __NR_getdents64		220
+#define __NR_fcntl64		221
+/* 223 is unused */
+#define __NR_gettid		224
+#define __NR_readahead		225
+#define __NR_setxattr		226
+#define __NR_lsetxattr		227
+#define __NR_fsetxattr		228
+#define __NR_getxattr		229
+#define __NR_lgetxattr		230
+#define __NR_fgetxattr		231
+#define __NR_listxattr		232
+#define __NR_llistxattr		233
+#define __NR_flistxattr		234
+#define __NR_removexattr	235
+#define __NR_lremovexattr	236
+#define __NR_fremovexattr	237
+#define __NR_tkill		238
+#define __NR_sendfile64		239
+#define __NR_futex		240
+#define __NR_sched_setaffinity	241
+#define __NR_sched_getaffinity	242
+#define __NR_set_thread_area	243
+#define __NR_get_thread_area	244
+#define __NR_io_setup		245
+#define __NR_io_destroy		246
+#define __NR_io_getevents	247
+#define __NR_io_submit		248
+#define __NR_io_cancel		249
+#define __NR_fadvise64		250
+
+#define __NR_exit_group		252
+#define __NR_lookup_dcookie	253
+#define __NR_epoll_create	254
+#define __NR_epoll_ctl		255
+#define __NR_epoll_wait		256
+#define __NR_remap_file_pages	257
+#define __NR_set_tid_address	258
+#define __NR_timer_create	259
+#define __NR_timer_settime	(__NR_timer_create+1)
+#define __NR_timer_gettime	(__NR_timer_create+2)
+#define __NR_timer_getoverrun	(__NR_timer_create+3)
+#define __NR_timer_delete	(__NR_timer_create+4)
+#define __NR_clock_settime	(__NR_timer_create+5)
+#define __NR_clock_gettime	(__NR_timer_create+6)
+#define __NR_clock_getres	(__NR_timer_create+7)
+#define __NR_clock_nanosleep	(__NR_timer_create+8)
+#define __NR_statfs64		268
+#define __NR_fstatfs64		269
+#define __NR_tgkill		270
+#define __NR_utimes		271
+#define __NR_fadvise64_64	272
+#define __NR_vserver		273
+#define __NR_mbind		274
+#define __NR_get_mempolicy	275
+#define __NR_set_mempolicy	276
+#define __NR_mq_open 		277
+#define __NR_mq_unlink		(__NR_mq_open+1)
+#define __NR_mq_timedsend	(__NR_mq_open+2)
+#define __NR_mq_timedreceive	(__NR_mq_open+3)
+#define __NR_mq_notify		(__NR_mq_open+4)
+#define __NR_mq_getsetattr	(__NR_mq_open+5)
+#define __NR_kexec_load		283
+#define __NR_waitid		284
+#define __NR_add_key		286
+#define __NR_request_key	287
+#define __NR_keyctl		288
+#define __NR_cacheflush		289
+#define __NR_ioprio_set		290
+#define __NR_ioprio_get		291
+#define __NR_inotify_init	292
+#define __NR_inotify_add_watch	293
+#define __NR_inotify_rm_watch	294
+#define __NR_migrate_pages	295
+#define __NR_openat		296
+#define __NR_mkdirat		297
+#define __NR_mknodat		298
+#define __NR_fchownat		299
+#define __NR_futimesat		300
+#define __NR_fstatat64		301
+#define __NR_unlinkat		302
+#define __NR_renameat		303
+#define __NR_linkat		304
+#define __NR_symlinkat		305
+#define __NR_readlinkat		306
+#define __NR_fchmodat		307
+#define __NR_faccessat		308
+#define __NR_pselect6		309
+#define __NR_ppoll		310
+#define __NR_unshare		311
+#define __NR_set_robust_list	312
+#define __NR_get_robust_list	313
+#define __NR_splice		314
+#define __NR_sync_file_range	315
+#define __NR_tee		316
+#define __NR_vmsplice		317
+#define __NR_move_pages		318
+#define __NR_getcpu		319
+#define __NR_epoll_pwait	320
+#define __NR_utimensat		321
+#define __NR_signalfd		322
+#define __NR_timerfd_create	323
+#define __NR_eventfd		324
+#define __NR_fallocate		325
+#define __NR_timerfd_settime	326
+#define __NR_timerfd_gettime	327
+#define __NR_signalfd4		328
+#define __NR_eventfd2		329
+#define __NR_epoll_create1	330
+#define __NR_dup3		331
+#define __NR_pipe2		332
+#define __NR_inotify_init1	333
+#define __NR_preadv		334
+#define __NR_pwritev		335
+#define __NR_rt_tgsigqueueinfo	336
+#define __NR_perf_event_open	337
+#define __NR_recvmmsg		338
+#define __NR_setns		339
+
+#endif /* _UAPI_ASM_UNISTD_H */
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
new file mode 100644
index 0000000..561029f
--- /dev/null
+++ b/arch/mn10300/kernel/Makefile
@@ -0,0 +1,28 @@
+#
+# Makefile for the MN10300-specific core kernel code
+#
+extra-y := head.o vmlinux.lds
+
+fpu-obj-y := fpu-nofpu.o fpu-nofpu-low.o
+fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o
+
+obj-y   := process.o signal.o entry.o traps.o irq.o \
+	   ptrace.o setup.o time.o sys_mn10300.o io.o \
+	   switch_to.o mn10300_ksyms.o $(fpu-obj-y) \
+	   csrc-mn10300.o cevt-mn10300.o
+
+obj-$(CONFIG_SMP) += smp.o smp-low.o
+
+obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o
+
+obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \
+			       mn10300-debug.o
+obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o
+obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o
+obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o
+
+obj-$(CONFIG_MN10300_RTC) += rtc.o
+obj-$(CONFIG_PROFILE) += profile.o profile-low.o
+obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_KGDB) += kgdb.o
diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c
new file mode 100644
index 0000000..e5a61c6
--- /dev/null
+++ b/arch/mn10300/kernel/asm-offsets.c
@@ -0,0 +1,107 @@
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed
+ * to extract and format the required data.
+ */
+
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/personality.h>
+#include <linux/kbuild.h>
+#include <asm/ucontext.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
+#include <asm/ptrace.h>
+#include "sigframe.h"
+#include "mn10300-serial.h"
+
+void foo(void)
+{
+	OFFSET(SIGCONTEXT_d0, sigcontext, d0);
+	OFFSET(SIGCONTEXT_d1, sigcontext, d1);
+	BLANK();
+
+	OFFSET(TI_task,			thread_info, task);
+	OFFSET(TI_frame,		thread_info, frame);
+	OFFSET(TI_flags,		thread_info, flags);
+	OFFSET(TI_cpu,			thread_info, cpu);
+	OFFSET(TI_preempt_count,	thread_info, preempt_count);
+	OFFSET(TI_addr_limit,		thread_info, addr_limit);
+	BLANK();
+
+	OFFSET(REG_D0,			pt_regs, d0);
+	OFFSET(REG_D1,			pt_regs, d1);
+	OFFSET(REG_D2,			pt_regs, d2);
+	OFFSET(REG_D3,			pt_regs, d3);
+	OFFSET(REG_A0,			pt_regs, a0);
+	OFFSET(REG_A1,			pt_regs, a1);
+	OFFSET(REG_A2,			pt_regs, a2);
+	OFFSET(REG_A3,			pt_regs, a3);
+	OFFSET(REG_E0,			pt_regs, e0);
+	OFFSET(REG_E1,			pt_regs, e1);
+	OFFSET(REG_E2,			pt_regs, e2);
+	OFFSET(REG_E3,			pt_regs, e3);
+	OFFSET(REG_E4,			pt_regs, e4);
+	OFFSET(REG_E5,			pt_regs, e5);
+	OFFSET(REG_E6,			pt_regs, e6);
+	OFFSET(REG_E7,			pt_regs, e7);
+	OFFSET(REG_SP,			pt_regs, sp);
+	OFFSET(REG_EPSW,		pt_regs, epsw);
+	OFFSET(REG_PC,			pt_regs, pc);
+	OFFSET(REG_LAR,			pt_regs, lar);
+	OFFSET(REG_LIR,			pt_regs, lir);
+	OFFSET(REG_MDR,			pt_regs, mdr);
+	OFFSET(REG_MCVF,		pt_regs, mcvf);
+	OFFSET(REG_MCRL,		pt_regs, mcrl);
+	OFFSET(REG_MCRH,		pt_regs, mcrh);
+	OFFSET(REG_MDRQ,		pt_regs, mdrq);
+	OFFSET(REG_ORIG_D0,		pt_regs, orig_d0);
+	OFFSET(REG_NEXT,		pt_regs, next);
+	DEFINE(REG__END,		sizeof(struct pt_regs));
+	BLANK();
+
+	OFFSET(THREAD_UREGS,		thread_struct, uregs);
+	OFFSET(THREAD_PC,		thread_struct, pc);
+	OFFSET(THREAD_SP,		thread_struct, sp);
+	OFFSET(THREAD_A3,		thread_struct, a3);
+	OFFSET(THREAD_USP,		thread_struct, usp);
+#ifdef CONFIG_FPU
+	OFFSET(THREAD_FPU_FLAGS,	thread_struct, fpu_flags);
+	OFFSET(THREAD_FPU_STATE,	thread_struct, fpu_state);
+	DEFINE(__THREAD_USING_FPU,	THREAD_USING_FPU);
+	DEFINE(__THREAD_HAS_FPU,	THREAD_HAS_FPU);
+#endif /* CONFIG_FPU */
+	BLANK();
+
+	OFFSET(TASK_THREAD,		task_struct, thread);
+	BLANK();
+
+	DEFINE(CLONE_VM_asm,		CLONE_VM);
+	DEFINE(CLONE_FS_asm,		CLONE_FS);
+	DEFINE(CLONE_FILES_asm,		CLONE_FILES);
+	DEFINE(CLONE_SIGHAND_asm,	CLONE_SIGHAND);
+	DEFINE(CLONE_UNTRACED_asm,	CLONE_UNTRACED);
+	DEFINE(SIGCHLD_asm,		SIGCHLD);
+	BLANK();
+
+	OFFSET(RT_SIGFRAME_sigcontext,	rt_sigframe, uc.uc_mcontext);
+
+	DEFINE(PAGE_SIZE_asm,		PAGE_SIZE);
+
+	OFFSET(__rx_buffer,		mn10300_serial_port, rx_buffer);
+	OFFSET(__rx_inp,		mn10300_serial_port, rx_inp);
+	OFFSET(__rx_outp,		mn10300_serial_port, rx_outp);
+	OFFSET(__uart_state,		mn10300_serial_port, uart.state);
+	OFFSET(__tx_xchar,		mn10300_serial_port, tx_xchar);
+	OFFSET(__tx_flags,		mn10300_serial_port, tx_flags);
+	OFFSET(__intr_flags,		mn10300_serial_port, intr_flags);
+	OFFSET(__rx_icr,		mn10300_serial_port, rx_icr);
+	OFFSET(__tx_icr,		mn10300_serial_port, tx_icr);
+	OFFSET(__tm_icr,		mn10300_serial_port, _tmicr);
+	OFFSET(__iobase,		mn10300_serial_port, _iobase);
+
+	DEFINE(__UART_XMIT_SIZE,	UART_XMIT_SIZE);
+	OFFSET(__xmit_buffer,		uart_state, xmit.buf);
+	OFFSET(__xmit_head,		uart_state, xmit.head);
+	OFFSET(__xmit_tail,		uart_state, xmit.tail);
+}
diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c
new file mode 100644
index 0000000..d9b34dd
--- /dev/null
+++ b/arch/mn10300/kernel/cevt-mn10300.c
@@ -0,0 +1,135 @@
+/* MN10300 clockevents
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by Mark Salter (msalter@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <linux/smp.h>
+#include <asm/timex.h>
+#include "internal.h"
+
+#ifdef CONFIG_SMP
+#if (CONFIG_NR_CPUS > 2) && !defined(CONFIG_GEENERIC_CLOCKEVENTS_BROADCAST)
+#error "This doesn't scale well! Need per-core local timers."
+#endif
+#else /* CONFIG_SMP */
+#define stop_jiffies_counter1()
+#define reload_jiffies_counter1(x)
+#define TMJC1IRQ TMJCIRQ
+#endif
+
+
+static int next_event(unsigned long delta,
+		      struct clock_event_device *evt)
+{
+	unsigned int cpu = smp_processor_id();
+
+	if (cpu == 0) {
+		stop_jiffies_counter();
+		reload_jiffies_counter(delta - 1);
+	} else {
+		stop_jiffies_counter1();
+		reload_jiffies_counter1(delta - 1);
+	}
+	return 0;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, mn10300_clockevent_device);
+static DEFINE_PER_CPU(struct irqaction, timer_irq);
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *cd;
+	unsigned int cpu = smp_processor_id();
+
+	if (cpu == 0)
+		stop_jiffies_counter();
+	else
+		stop_jiffies_counter1();
+
+	cd = &per_cpu(mn10300_clockevent_device, cpu);
+	cd->event_handler(cd);
+
+	return IRQ_HANDLED;
+}
+
+static void event_handler(struct clock_event_device *dev)
+{
+}
+
+static inline void setup_jiffies_interrupt(int irq,
+					   struct irqaction *action)
+{
+	u16 tmp;
+	setup_irq(irq, action);
+	set_intr_level(irq, NUM2GxICR_LEVEL(CONFIG_TIMER_IRQ_LEVEL));
+	GxICR(irq) |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST;
+	tmp = GxICR(irq);
+}
+
+int __init init_clockevents(void)
+{
+	struct clock_event_device *cd;
+	struct irqaction *iact;
+	unsigned int cpu = smp_processor_id();
+
+	cd = &per_cpu(mn10300_clockevent_device, cpu);
+
+	if (cpu == 0) {
+		stop_jiffies_counter();
+		cd->irq	= TMJCIRQ;
+	} else {
+		stop_jiffies_counter1();
+		cd->irq	= TMJC1IRQ;
+	}
+
+	cd->name		= "Timestamp";
+	cd->features		= CLOCK_EVT_FEAT_ONESHOT;
+
+	/* Calculate shift/mult. We want to spawn at least 1 second */
+	clockevents_calc_mult_shift(cd, MN10300_JCCLK, 1);
+
+	/* Calculate the min / max delta */
+	cd->max_delta_ns	= clockevent_delta2ns(TMJCBR_MAX, cd);
+	cd->min_delta_ns	= clockevent_delta2ns(100, cd);
+
+	cd->rating		= 200;
+	cd->cpumask		= cpumask_of(smp_processor_id());
+	cd->event_handler	= event_handler;
+	cd->set_next_event	= next_event;
+
+	iact = &per_cpu(timer_irq, cpu);
+	iact->flags = IRQF_SHARED | IRQF_TIMER;
+	iact->handler = timer_interrupt;
+
+	clockevents_register_device(cd);
+
+#if defined(CONFIG_SMP) && !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
+	/* setup timer irq affinity so it only runs on this cpu */
+	{
+		struct irq_data *data;
+		data = irq_get_irq_data(cd->irq);
+		cpumask_copy(irq_data_get_affinity_mask(data), cpumask_of(cpu));
+		iact->flags |= IRQF_NOBALANCING;
+	}
+#endif
+
+	if (cpu == 0) {
+		reload_jiffies_counter(MN10300_JC_PER_HZ - 1);
+		iact->name = "CPU0 Timer";
+	} else {
+		reload_jiffies_counter1(MN10300_JC_PER_HZ - 1);
+		iact->name = "CPU1 Timer";
+	}
+
+	setup_jiffies_interrupt(cd->irq, iact);
+
+	return 0;
+}
diff --git a/arch/mn10300/kernel/csrc-mn10300.c b/arch/mn10300/kernel/csrc-mn10300.c
new file mode 100644
index 0000000..45644cf
--- /dev/null
+++ b/arch/mn10300/kernel/csrc-mn10300.c
@@ -0,0 +1,34 @@
+/* MN10300 clocksource
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by Mark Salter (msalter@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/clocksource.h>
+#include <linux/init.h>
+#include <asm/timex.h>
+#include "internal.h"
+
+static cycle_t mn10300_read(struct clocksource *cs)
+{
+	return read_timestamp_counter();
+}
+
+static struct clocksource clocksource_mn10300 = {
+	.name	= "TSC",
+	.rating	= 200,
+	.read	= mn10300_read,
+	.mask	= CLOCKSOURCE_MASK(32),
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+int __init init_clocksource(void)
+{
+	startup_timestamp_counter();
+	clocksource_register_hz(&clocksource_mn10300, MN10300_TSCCLK);
+	return 0;
+}
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
new file mode 100644
index 0000000..177d61d
--- /dev/null
+++ b/arch/mn10300/kernel/entry.S
@@ -0,0 +1,772 @@
+###############################################################################
+#
+# MN10300 Exception and interrupt entry points
+#
+# Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Modified by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/irqflags.h>
+#include <asm/thread_info.h>
+#include <asm/intctl-regs.h>
+#include <asm/busctl-regs.h>
+#include <asm/timer-regs.h>
+#include <unit/leds.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/errno.h>
+#include <asm/asm-offsets.h>
+#include <asm/frame.inc>
+
+#if defined(CONFIG_SMP) && defined(CONFIG_GDBSTUB)
+#include <asm/gdb-stub.h>
+#endif /* CONFIG_SMP && CONFIG_GDBSTUB */
+
+#ifdef CONFIG_PREEMPT
+#define preempt_stop		LOCAL_IRQ_DISABLE
+#else
+#define preempt_stop
+#define resume_kernel		restore_all
+#endif
+
+	.am33_2
+
+###############################################################################
+#
+# the return path for a forked child
+# - on entry, D0 holds the address of the previous task to run
+#
+###############################################################################
+ENTRY(ret_from_fork)
+	call	schedule_tail[],0
+	GET_THREAD_INFO a2
+
+	# return 0 to indicate child process
+	clr	d0
+	mov	d0,(REG_D0,fp)
+	jmp	syscall_exit
+
+ENTRY(ret_from_kernel_thread)
+	call	schedule_tail[],0
+	mov	(REG_D0,fp),d0
+	mov	(REG_A0,fp),a0
+	calls	(a0)
+	GET_THREAD_INFO a2		# A2 must be set on return from sys_exit()
+	clr	d0
+	mov	d0,(REG_D0,fp)
+	jmp	syscall_exit
+
+###############################################################################
+#
+# system call handler
+#
+###############################################################################
+ENTRY(system_call)
+	add	-4,sp
+	SAVE_ALL
+	mov	d0,(REG_ORIG_D0,fp)
+	GET_THREAD_INFO a2
+	cmp	nr_syscalls,d0
+	bcc	syscall_badsys
+	btst	_TIF_SYSCALL_TRACE,(TI_flags,a2)
+	bne	syscall_entry_trace
+syscall_call:
+	add	d0,d0,a1
+	add	a1,a1
+	mov	(REG_A0,fp),d0
+	mov	(sys_call_table,a1),a0
+	calls	(a0)
+	mov	d0,(REG_D0,fp)
+syscall_exit:
+	# make sure we don't miss an interrupt setting need_resched or
+	# sigpending between sampling and the rti
+	LOCAL_IRQ_DISABLE
+	mov	(TI_flags,a2),d2
+	btst	_TIF_ALLWORK_MASK,d2
+	bne	syscall_exit_work
+restore_all:
+	RESTORE_ALL
+
+###############################################################################
+#
+# perform work that needs to be done immediately before resumption and syscall
+# tracing
+#
+###############################################################################
+	ALIGN
+syscall_exit_work:
+	mov	(REG_EPSW,fp),d0
+	and	EPSW_nSL,d0
+	beq	resume_kernel		# returning to supervisor mode
+
+	LOCAL_IRQ_ENABLE		# could let syscall_trace_exit() call
+					# schedule() instead
+	btst	_TIF_SYSCALL_TRACE,d2
+	beq	work_pending
+	mov	fp,d0
+	call	syscall_trace_exit[],0	# do_syscall_trace(regs)
+	jmp	resume_userspace
+
+	ALIGN
+work_pending:
+	btst	_TIF_NEED_RESCHED,d2
+	beq	work_notifysig
+
+work_resched:
+	call	schedule[],0
+
+resume_userspace:
+	# make sure we don't miss an interrupt setting need_resched or
+	# sigpending between sampling and the rti
+	LOCAL_IRQ_DISABLE
+
+	# is there any work to be done other than syscall tracing?
+	mov	(TI_flags,a2),d2
+	btst	_TIF_WORK_MASK,d2
+	beq	restore_all
+
+	LOCAL_IRQ_ENABLE
+	btst	_TIF_NEED_RESCHED,d2
+	bne	work_resched
+
+	# deal with pending signals and notify-resume requests
+work_notifysig:
+	mov	fp,d0
+	mov	d2,d1
+	call	do_notify_resume[],0
+	jmp	resume_userspace
+
+	# perform syscall entry tracing
+syscall_entry_trace:
+	mov	-ENOSYS,d0
+	mov	d0,(REG_D0,fp)
+	mov	fp,d0
+	call	syscall_trace_entry[],0	# returns the syscall number to actually use
+	mov	(REG_D1,fp),d1
+	cmp	nr_syscalls,d0
+	bcs	syscall_call
+	jmp	syscall_exit
+
+syscall_badsys:
+	mov	-ENOSYS,d0
+	mov	d0,(REG_D0,fp)
+	jmp	resume_userspace
+
+	# userspace resumption stub bypassing syscall exit tracing
+	.globl	ret_from_exception, ret_from_intr
+	ALIGN
+ret_from_exception:
+	preempt_stop
+ret_from_intr:
+	GET_THREAD_INFO a2
+	mov	(REG_EPSW,fp),d0	# need to deliver signals before
+					# returning to userspace
+	and	EPSW_nSL,d0
+	bne	resume_userspace	# returning to userspace
+
+#ifdef CONFIG_PREEMPT
+resume_kernel:
+	LOCAL_IRQ_DISABLE
+	mov	(TI_preempt_count,a2),d0	# non-zero preempt_count ?
+	cmp	0,d0
+	bne	restore_all
+
+need_resched:
+	btst	_TIF_NEED_RESCHED,(TI_flags,a2)
+	beq	restore_all
+	mov	(REG_EPSW,fp),d0
+	and	EPSW_IM,d0
+	cmp	EPSW_IM_7,d0		# interrupts off (exception path) ?
+	bne	restore_all
+	call	preempt_schedule_irq[],0
+	jmp	need_resched
+#else
+	jmp	resume_kernel
+#endif
+
+
+###############################################################################
+#
+# IRQ handler entry point
+# - intended to be entered at multiple priorities
+#
+###############################################################################
+ENTRY(irq_handler)
+	add	-4,sp
+	SAVE_ALL
+
+	# it's not a syscall
+	mov	0xffffffff,d0
+	mov	d0,(REG_ORIG_D0,fp)
+
+	mov	fp,d0
+	call	do_IRQ[],0			# do_IRQ(regs)
+
+	jmp	ret_from_intr
+
+###############################################################################
+#
+# Double Fault handler entry point
+# - note that there will not be a stack, D0/A0 will hold EPSW/PC as were
+#
+###############################################################################
+	.section .bss
+	.balign	THREAD_SIZE
+	.space	THREAD_SIZE
+__df_stack:
+	.previous
+
+ENTRY(double_fault)
+	mov	a0,(__df_stack-4)	# PC as was
+	mov	d0,(__df_stack-8)	# EPSW as was
+	mn10300_set_dbfleds		# display 'db-f' on the LEDs
+	mov	0xaa55aa55,d0
+	mov	d0,(__df_stack-12)	# no ORIG_D0
+	mov	sp,a0			# save corrupted SP
+	mov	__df_stack-12,sp	# emergency supervisor stack
+	SAVE_ALL
+	mov	a0,(REG_A0,fp)		# save corrupted SP as A0 (which got
+					# clobbered by the CPU)
+	mov	fp,d0
+	calls	do_double_fault
+double_fault_loop:
+	bra	double_fault_loop
+
+###############################################################################
+#
+# Bus Error handler entry point
+# - handle external (async) bus errors separately
+#
+###############################################################################
+ENTRY(raw_bus_error)
+	add	-4,sp
+	mov	d0,(sp)
+#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
+	mov	(MMUCTR),d0
+	mov	d0,(MMUCTR)
+#endif
+	mov	(BCBERR),d0		# what
+	btst	BCBERR_BEMR_DMA,d0	# see if it was an external bus error
+	beq	__common_exception_aux	# it wasn't
+
+	SAVE_ALL
+	mov	(BCBEAR),d1		# destination of erroneous access
+
+	mov	(REG_ORIG_D0,fp),d2
+	mov	d2,(REG_D0,fp)
+	mov	-1,d2
+	mov	d2,(REG_ORIG_D0,fp)
+
+	add	-4,sp
+	mov	fp,(12,sp)		# frame pointer
+	call	io_bus_error[],0
+	jmp	restore_all
+
+###############################################################################
+#
+# NMI exception entry points
+#
+# This is used by ordinary interrupt channels that have the GxICR_NMI bit set
+# in addition to the main NMI and Watchdog channels.  SMP NMI IPIs use this
+# facility.
+#
+###############################################################################
+ENTRY(nmi_handler)
+	add	-4,sp
+	mov	d0,(sp)
+	mov	(TBR),d0
+
+#ifdef CONFIG_SMP
+	add	-4,sp
+	mov	d0,(sp)			# save d0(TBR)
+	movhu	(NMIAGR),d0
+	and	NMIAGR_GN,d0
+	lsr	0x2,d0
+	cmp	CALL_FUNCTION_NMI_IPI,d0
+	bne	nmi_not_smp_callfunc	# if not call function, jump
+
+	# function call nmi ipi
+	add	4,sp			# no need to store TBR
+	mov	GxICR_DETECT,d0		# clear NMI request
+	movbu	d0,(GxICR(CALL_FUNCTION_NMI_IPI))
+	movhu	(GxICR(CALL_FUNCTION_NMI_IPI)),d0
+	and	~EPSW_NMID,epsw		# enable NMI
+
+	mov	(sp),d0			# restore d0
+	SAVE_ALL
+	call	smp_nmi_call_function_interrupt[],0
+	RESTORE_ALL
+
+nmi_not_smp_callfunc:
+#ifdef CONFIG_KERNEL_DEBUGGER
+	cmp	DEBUGGER_NMI_IPI,d0
+	bne	nmi_not_debugger	# if not kernel debugger NMI IPI, jump
+
+	# kernel debugger NMI IPI
+	add	4,sp			# no need to store TBR
+	mov	GxICR_DETECT,d0		# clear NMI
+	movbu	d0,(GxICR(DEBUGGER_NMI_IPI))
+	movhu	(GxICR(DEBUGGER_NMI_IPI)),d0
+	and	~EPSW_NMID,epsw		# enable NMI
+
+	mov     (sp),d0
+	SAVE_ALL
+	mov	fp,d0			# arg 0: stacked register file
+	mov	a2,d1			# arg 1: exception number
+	call    debugger_nmi_interrupt[],0
+	RESTORE_ALL
+
+nmi_not_debugger:
+#endif /* CONFIG_KERNEL_DEBUGGER */
+	mov     (sp),d0                 # restore TBR to d0
+	add     4,sp
+#endif /* CONFIG_SMP */
+
+	bra	__common_exception_nonmi
+
+###############################################################################
+#
+# General exception entry point
+#
+###############################################################################
+ENTRY(__common_exception)
+	add	-4,sp
+	mov	d0,(sp)
+#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
+	mov	(MMUCTR),d0
+	mov	d0,(MMUCTR)
+#endif
+
+__common_exception_aux:
+	mov	(TBR),d0
+	and	~EPSW_NMID,epsw		# turn NMIs back on if not NMI
+	or	EPSW_IE,epsw
+
+__common_exception_nonmi:
+	and	0x0000FFFF,d0		# turn the exception code into a vector
+					# table index
+
+	btst	0x00000007,d0
+	bne	1f
+	cmp	0x00000400,d0
+	bge	1f
+
+	SAVE_ALL			# build the stack frame
+
+	mov	(REG_D0,fp),a2		# get the exception number
+	mov	(REG_ORIG_D0,fp),d0
+	mov	d0,(REG_D0,fp)
+	mov	-1,d0
+	mov	d0,(REG_ORIG_D0,fp)
+
+#ifdef CONFIG_GDBSTUB
+#ifdef CONFIG_SMP
+	call	gdbstub_busy_check[],0
+	and	d0,d0			# check return value
+	beq	2f
+#else  /* CONFIG_SMP */
+	btst	0x01,(gdbstub_busy)
+	beq	2f
+#endif /* CONFIG_SMP */
+	and	~EPSW_IE,epsw
+	mov	fp,d0
+	mov	a2,d1
+	call	gdbstub_exception[],0	# gdbstub itself caused an exception
+	bra	restore_all
+2:
+#endif /* CONFIG_GDBSTUB */
+
+	mov	fp,d0			# arg 0: stacked register file
+	mov	a2,d1			# arg 1: exception number
+	lsr	1,a2
+
+	mov	(exception_table,a2),a2
+	calls	(a2)
+	jmp	ret_from_exception
+
+1:	pi				# BUG() equivalent
+
+###############################################################################
+#
+# Exception handler functions table
+#
+###############################################################################
+	.data
+ENTRY(exception_table)
+	.rept	0x400>>1
+	 .long	uninitialised_exception
+	.endr
+	.previous
+
+###############################################################################
+#
+# Change an entry in the exception table
+# - D0 exception code, D1 handler
+#
+###############################################################################
+ENTRY(set_excp_vector)
+	lsr	1,d0
+	add	exception_table,d0
+	mov	d1,(d0)
+	mov	4,d1
+	ret	[],0
+
+###############################################################################
+#
+# System call table
+#
+###############################################################################
+	.data
+ENTRY(sys_call_table)
+	.long sys_restart_syscall	/* 0 */
+	.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_lchown16
+	.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	/* old sys_olduname */
+	.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 sys_old_select
+	.long sys_symlink
+	.long sys_lstat
+	.long sys_readlink	/* 85 */
+	.long sys_uselib
+	.long sys_swapon
+	.long sys_reboot
+	.long sys_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 */
+	.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	/* old sys_uname */
+	.long sys_ni_syscall	/* 110 - iopl */
+	.long sys_vhangup
+	.long sys_ni_syscall	/* old "idle" system call */
+	.long sys_ni_syscall	/* vm86old */
+	.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_ni_syscall	/* modify_ldt */
+	.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	/* reserved 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_ni_syscall	/* vm86 */
+	.long sys_ni_syscall	/* Old sys_query_module */
+	.long sys_poll
+	.long sys_ni_syscall	/* was 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_chown16
+	.long sys_getcwd
+	.long sys_capget
+	.long sys_capset	/* 185 */
+	.long sys_sigaltstack
+	.long sys_sendfile
+	.long sys_ni_syscall	/* reserved for streams1 */
+	.long sys_ni_syscall	/* reserved for streams2 */
+	.long sys_vfork		/* 190 */
+	.long sys_getrlimit
+	.long sys_mmap_pgoff
+	.long sys_truncate64
+	.long sys_ftruncate64
+	.long sys_stat64	/* 195 */
+	.long sys_lstat64
+	.long sys_fstat64
+	.long sys_lchown
+	.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_chown
+	.long sys_setuid
+	.long sys_setgid
+	.long sys_setfsuid	/* 215 */
+	.long sys_setfsgid
+	.long sys_pivot_root
+	.long sys_mincore
+	.long sys_madvise
+	.long sys_getdents64	/* 220 */
+	.long sys_fcntl64
+	.long sys_ni_syscall	/* reserved for TUX */
+	.long sys_ni_syscall
+	.long sys_gettid
+	.long sys_readahead	/* 225 */
+	.long sys_setxattr
+	.long sys_lsetxattr
+	.long sys_fsetxattr
+	.long sys_getxattr
+	.long sys_lgetxattr	/* 230 */
+	.long sys_fgetxattr
+	.long sys_listxattr
+	.long sys_llistxattr
+	.long sys_flistxattr
+	.long sys_removexattr	/* 235 */
+	.long sys_lremovexattr
+	.long sys_fremovexattr
+	.long sys_tkill
+	.long sys_sendfile64
+	.long sys_futex		/* 240 */
+	.long sys_sched_setaffinity
+	.long sys_sched_getaffinity
+	.long sys_ni_syscall	/* sys_set_thread_area */
+	.long sys_ni_syscall	/* sys_get_thread_area */
+	.long sys_io_setup	/* 245 */
+	.long sys_io_destroy
+	.long sys_io_getevents
+	.long sys_io_submit
+	.long sys_io_cancel
+	.long sys_fadvise64	/* 250 */
+	.long sys_ni_syscall
+	.long sys_exit_group
+	.long sys_lookup_dcookie
+	.long sys_epoll_create
+	.long sys_epoll_ctl	/* 255 */
+	.long sys_epoll_wait
+ 	.long sys_remap_file_pages
+ 	.long sys_set_tid_address
+ 	.long sys_timer_create
+ 	.long sys_timer_settime		/* 260 */
+ 	.long sys_timer_gettime
+ 	.long sys_timer_getoverrun
+ 	.long sys_timer_delete
+ 	.long sys_clock_settime
+ 	.long sys_clock_gettime		/* 265 */
+ 	.long sys_clock_getres
+ 	.long sys_clock_nanosleep
+	.long sys_statfs64
+	.long sys_fstatfs64
+	.long sys_tgkill		/* 270 */
+	.long sys_utimes
+ 	.long sys_fadvise64_64
+	.long sys_ni_syscall	/* sys_vserver */
+	.long sys_mbind
+	.long sys_get_mempolicy		/* 275 */
+	.long sys_set_mempolicy
+	.long sys_mq_open
+	.long sys_mq_unlink
+	.long sys_mq_timedsend
+	.long sys_mq_timedreceive	/* 280 */
+	.long sys_mq_notify
+	.long sys_mq_getsetattr
+	.long sys_kexec_load
+	.long sys_waitid
+	.long sys_ni_syscall		/* 285 */ /* available */
+	.long sys_add_key
+	.long sys_request_key
+	.long sys_keyctl
+	.long sys_cacheflush
+	.long sys_ioprio_set		/* 290 */
+	.long sys_ioprio_get
+	.long sys_inotify_init
+	.long sys_inotify_add_watch
+	.long sys_inotify_rm_watch
+	.long sys_migrate_pages		/* 295 */
+	.long sys_openat
+	.long sys_mkdirat
+	.long sys_mknodat
+	.long sys_fchownat
+	.long sys_futimesat		/* 300 */
+	.long sys_fstatat64
+	.long sys_unlinkat
+	.long sys_renameat
+	.long sys_linkat
+	.long sys_symlinkat		/* 305 */
+	.long sys_readlinkat
+	.long sys_fchmodat
+	.long sys_faccessat
+	.long sys_pselect6
+	.long sys_ppoll			/* 310 */
+	.long sys_unshare
+	.long sys_set_robust_list
+	.long sys_get_robust_list
+	.long sys_splice
+	.long sys_sync_file_range	/* 315 */
+	.long sys_tee
+	.long sys_vmsplice
+	.long sys_move_pages
+	.long sys_getcpu
+	.long sys_epoll_pwait		/* 320 */
+	.long sys_utimensat
+	.long sys_signalfd
+	.long sys_timerfd_create
+	.long sys_eventfd
+	.long sys_fallocate		/* 325 */
+	.long sys_timerfd_settime
+	.long sys_timerfd_gettime
+	.long sys_signalfd4
+	.long sys_eventfd2
+	.long sys_epoll_create1		/* 330 */
+	.long sys_dup3
+	.long sys_pipe2
+	.long sys_inotify_init1
+	.long sys_preadv
+	.long sys_pwritev		/* 335 */
+	.long sys_rt_tgsigqueueinfo
+	.long sys_perf_event_open
+	.long sys_recvmmsg
+	.long sys_setns
+
+
+nr_syscalls=(.-sys_call_table)/4
diff --git a/arch/mn10300/kernel/fpu-low.S b/arch/mn10300/kernel/fpu-low.S
new file mode 100644
index 0000000..78df25c
--- /dev/null
+++ b/arch/mn10300/kernel/fpu-low.S
@@ -0,0 +1,258 @@
+/* MN10300 Low level FPU management operations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/linkage.h>
+#include <asm/cpu-regs.h>
+#include <asm/smp.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
+#include <asm/frame.inc>
+
+.macro FPU_INIT_STATE_ALL
+	fmov	0,fs0
+	fmov	fs0,fs1
+	fmov	fs0,fs2
+	fmov	fs0,fs3
+	fmov	fs0,fs4
+	fmov	fs0,fs5
+	fmov	fs0,fs6
+	fmov	fs0,fs7
+	fmov	fs0,fs8
+	fmov	fs0,fs9
+	fmov	fs0,fs10
+	fmov	fs0,fs11
+	fmov	fs0,fs12
+	fmov	fs0,fs13
+	fmov	fs0,fs14
+	fmov	fs0,fs15
+	fmov	fs0,fs16
+	fmov	fs0,fs17
+	fmov	fs0,fs18
+	fmov	fs0,fs19
+	fmov	fs0,fs20
+	fmov	fs0,fs21
+	fmov	fs0,fs22
+	fmov	fs0,fs23
+	fmov	fs0,fs24
+	fmov	fs0,fs25
+	fmov	fs0,fs26
+	fmov	fs0,fs27
+	fmov	fs0,fs28
+	fmov	fs0,fs29
+	fmov	fs0,fs30
+	fmov	fs0,fs31
+	fmov	FPCR_INIT,fpcr
+.endm
+
+.macro FPU_SAVE_ALL areg,dreg
+	fmov	fs0,(\areg+)
+	fmov	fs1,(\areg+)
+	fmov	fs2,(\areg+)
+	fmov	fs3,(\areg+)
+	fmov	fs4,(\areg+)
+	fmov	fs5,(\areg+)
+	fmov	fs6,(\areg+)
+	fmov	fs7,(\areg+)
+	fmov	fs8,(\areg+)
+	fmov	fs9,(\areg+)
+	fmov	fs10,(\areg+)
+	fmov	fs11,(\areg+)
+	fmov	fs12,(\areg+)
+	fmov	fs13,(\areg+)
+	fmov	fs14,(\areg+)
+	fmov	fs15,(\areg+)
+	fmov	fs16,(\areg+)
+	fmov	fs17,(\areg+)
+	fmov	fs18,(\areg+)
+	fmov	fs19,(\areg+)
+	fmov	fs20,(\areg+)
+	fmov	fs21,(\areg+)
+	fmov	fs22,(\areg+)
+	fmov	fs23,(\areg+)
+	fmov	fs24,(\areg+)
+	fmov	fs25,(\areg+)
+	fmov	fs26,(\areg+)
+	fmov	fs27,(\areg+)
+	fmov	fs28,(\areg+)
+	fmov	fs29,(\areg+)
+	fmov	fs30,(\areg+)
+	fmov	fs31,(\areg+)
+	fmov	fpcr,\dreg
+	mov	\dreg,(\areg)
+.endm
+
+.macro FPU_RESTORE_ALL areg,dreg
+	fmov	(\areg+),fs0
+	fmov	(\areg+),fs1
+	fmov	(\areg+),fs2
+	fmov	(\areg+),fs3
+	fmov	(\areg+),fs4
+	fmov	(\areg+),fs5
+	fmov	(\areg+),fs6
+	fmov	(\areg+),fs7
+	fmov	(\areg+),fs8
+	fmov	(\areg+),fs9
+	fmov	(\areg+),fs10
+	fmov	(\areg+),fs11
+	fmov	(\areg+),fs12
+	fmov	(\areg+),fs13
+	fmov	(\areg+),fs14
+	fmov	(\areg+),fs15
+	fmov	(\areg+),fs16
+	fmov	(\areg+),fs17
+	fmov	(\areg+),fs18
+	fmov	(\areg+),fs19
+	fmov	(\areg+),fs20
+	fmov	(\areg+),fs21
+	fmov	(\areg+),fs22
+	fmov	(\areg+),fs23
+	fmov	(\areg+),fs24
+	fmov	(\areg+),fs25
+	fmov	(\areg+),fs26
+	fmov	(\areg+),fs27
+	fmov	(\areg+),fs28
+	fmov	(\areg+),fs29
+	fmov	(\areg+),fs30
+	fmov	(\areg+),fs31
+	mov	(\areg),\dreg
+	fmov	\dreg,fpcr
+.endm
+
+###############################################################################
+#
+# void fpu_init_state(void)
+# - initialise the FPU
+#
+###############################################################################
+	.globl	fpu_init_state
+	.type	fpu_init_state,@function
+fpu_init_state:
+	mov	epsw,d0
+	or	EPSW_FE,epsw
+
+#ifdef CONFIG_MN10300_PROC_MN103E010
+	nop
+	nop
+	nop
+#endif
+	FPU_INIT_STATE_ALL
+#ifdef CONFIG_MN10300_PROC_MN103E010
+	nop
+	nop
+	nop
+#endif
+	mov	d0,epsw
+	ret	[],0
+
+	.size	fpu_init_state,.-fpu_init_state
+
+###############################################################################
+#
+# void fpu_save(struct fpu_state_struct *)
+# - save the fpu state
+# - note that an FPU Operational exception might occur during this process
+#
+###############################################################################
+	.globl	fpu_save
+	.type	fpu_save,@function
+fpu_save:
+	mov	epsw,d1
+	or	EPSW_FE,epsw		/* enable the FPU so we can access it */
+
+#ifdef CONFIG_MN10300_PROC_MN103E010
+	nop
+	nop
+#endif
+	mov	d0,a0
+	FPU_SAVE_ALL	a0,d0
+#ifdef CONFIG_MN10300_PROC_MN103E010
+	nop
+	nop
+#endif
+
+	mov	d1,epsw
+	ret	[],0
+
+	.size	fpu_save,.-fpu_save
+
+###############################################################################
+#
+# void fpu_disabled(void)
+# - handle an exception due to the FPU being disabled
+#   when CONFIG_FPU is enabled
+#
+###############################################################################
+	.type	fpu_disabled,@function
+	.globl	fpu_disabled
+fpu_disabled:
+	or	EPSW_nAR|EPSW_FE,epsw
+	nop
+	nop
+	nop
+
+	mov	sp,a1
+	mov	(a1),d1			/* get epsw of user context */
+	and	~(THREAD_SIZE-1),a1	/* a1: (thread_info *ti) */
+	mov	(TI_task,a1),a2		/* a2: (task_struct *tsk) */
+	btst	EPSW_nSL,d1
+	beq	fpu_used_in_kernel
+
+	or	EPSW_FE,d1
+	mov	d1,(sp)
+	mov	(TASK_THREAD+THREAD_FPU_FLAGS,a2),d1
+#ifndef CONFIG_LAZY_SAVE_FPU
+	or	__THREAD_HAS_FPU,d1
+	mov	d1,(TASK_THREAD+THREAD_FPU_FLAGS,a2)
+#else  /* !CONFIG_LAZY_SAVE_FPU */
+	mov	(fpu_state_owner),a0
+	cmp	0,a0
+	beq	fpu_regs_save_end
+
+	mov	(TASK_THREAD+THREAD_UREGS,a0),a1
+	add	TASK_THREAD+THREAD_FPU_STATE,a0
+	FPU_SAVE_ALL a0,d0
+
+	mov	(REG_EPSW,a1),d0
+	and	~EPSW_FE,d0
+	mov	d0,(REG_EPSW,a1)
+
+fpu_regs_save_end:
+	mov	a2,(fpu_state_owner)
+#endif /* !CONFIG_LAZY_SAVE_FPU */
+
+	btst	__THREAD_USING_FPU,d1
+	beq	fpu_regs_init
+	add	TASK_THREAD+THREAD_FPU_STATE,a2
+	FPU_RESTORE_ALL a2,d0
+	rti
+
+fpu_regs_init:
+	FPU_INIT_STATE_ALL
+	add	TASK_THREAD+THREAD_FPU_FLAGS,a2
+	bset	__THREAD_USING_FPU,(0,a2)
+	rti
+
+fpu_used_in_kernel:
+	and	~(EPSW_nAR|EPSW_FE),epsw
+	nop
+	nop
+
+	add	-4,sp
+	SAVE_ALL
+	mov	-1,d0
+	mov	d0,(REG_ORIG_D0,fp)
+
+	and	~EPSW_NMID,epsw
+
+	mov	fp,d0
+	call	fpu_disabled_in_kernel[],0
+	jmp	ret_from_exception
+
+	.size	fpu_disabled,.-fpu_disabled
diff --git a/arch/mn10300/kernel/fpu-nofpu-low.S b/arch/mn10300/kernel/fpu-nofpu-low.S
new file mode 100644
index 0000000..7ea087a
--- /dev/null
+++ b/arch/mn10300/kernel/fpu-nofpu-low.S
@@ -0,0 +1,39 @@
+/* MN10300 Low level FPU management operations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/linkage.h>
+#include <asm/cpu-regs.h>
+#include <asm/smp.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
+#include <asm/frame.inc>
+
+###############################################################################
+#
+# void fpu_disabled(void)
+# - handle an exception due to the FPU being disabled
+#   when CONFIG_FPU is disabled
+#
+###############################################################################
+	.type	fpu_disabled,@function
+	.globl	fpu_disabled
+fpu_disabled:
+	add	-4,sp
+	SAVE_ALL
+	mov	-1,d0
+	mov	d0,(REG_ORIG_D0,fp)
+
+	and	~EPSW_NMID,epsw
+
+	mov	fp,d0
+	call	unexpected_fpu_exception[],0
+	jmp	ret_from_exception
+
+	.size	fpu_disabled,.-fpu_disabled
diff --git a/arch/mn10300/kernel/fpu-nofpu.c b/arch/mn10300/kernel/fpu-nofpu.c
new file mode 100644
index 0000000..31c765b
--- /dev/null
+++ b/arch/mn10300/kernel/fpu-nofpu.c
@@ -0,0 +1,30 @@
+/* MN10300 FPU management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/fpu.h>
+
+/*
+ * handle an FPU operational exception
+ * - there's a possibility that if the FPU is asynchronous, the signal might
+ *   be meant for a process other than the current one
+ */
+asmlinkage
+void unexpected_fpu_exception(struct pt_regs *regs, enum exception_code code)
+{
+	panic("An FPU exception was received, but there's no FPU enabled.");
+}
+
+/*
+ * fill in the FPU structure for a core dump
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpreg)
+{
+	return 0; /* not valid */
+}
diff --git a/arch/mn10300/kernel/fpu.c b/arch/mn10300/kernel/fpu.c
new file mode 100644
index 0000000..064fa19
--- /dev/null
+++ b/arch/mn10300/kernel/fpu.c
@@ -0,0 +1,175 @@
+/* MN10300 FPU management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/uaccess.h>
+#include <asm/fpu.h>
+#include <asm/elf.h>
+#include <asm/exceptions.h>
+
+#ifdef CONFIG_LAZY_SAVE_FPU
+struct task_struct *fpu_state_owner;
+#endif
+
+/*
+ * error functions in FPU disabled exception
+ */
+asmlinkage void fpu_disabled_in_kernel(struct pt_regs *regs)
+{
+	die_if_no_fixup("An FPU Disabled exception happened in kernel space\n",
+			regs, EXCEP_FPU_DISABLED);
+}
+
+/*
+ * handle an FPU operational exception
+ * - there's a possibility that if the FPU is asynchronous, the signal might
+ *   be meant for a process other than the current one
+ */
+asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
+{
+	struct task_struct *tsk = current;
+	siginfo_t info;
+	u32 fpcr;
+
+	if (!user_mode(regs))
+		die_if_no_fixup("An FPU Operation exception happened in"
+				" kernel space\n",
+				regs, code);
+
+	if (!is_using_fpu(tsk))
+		die_if_no_fixup("An FPU Operation exception happened,"
+				" but the FPU is not in use",
+				regs, code);
+
+	info.si_signo = SIGFPE;
+	info.si_errno = 0;
+	info.si_addr = (void *) tsk->thread.uregs->pc;
+	info.si_code = FPE_FLTINV;
+
+	unlazy_fpu(tsk);
+
+	fpcr = tsk->thread.fpu_state.fpcr;
+
+	if (fpcr & FPCR_EC_Z)
+		info.si_code = FPE_FLTDIV;
+	else if	(fpcr & FPCR_EC_O)
+		info.si_code = FPE_FLTOVF;
+	else if	(fpcr & FPCR_EC_U)
+		info.si_code = FPE_FLTUND;
+	else if	(fpcr & FPCR_EC_I)
+		info.si_code = FPE_FLTRES;
+
+	force_sig_info(SIGFPE, &info, tsk);
+}
+
+/*
+ * save the FPU state to a signal context
+ */
+int fpu_setup_sigcontext(struct fpucontext *fpucontext)
+{
+	struct task_struct *tsk = current;
+
+	if (!is_using_fpu(tsk))
+		return 0;
+
+	/* transfer the current FPU state to memory and cause fpu_init() to be
+	 * triggered by the next attempted FPU operation by the current
+	 * process.
+	 */
+	preempt_disable();
+
+#ifndef CONFIG_LAZY_SAVE_FPU
+	if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
+		fpu_save(&tsk->thread.fpu_state);
+		tsk->thread.uregs->epsw &= ~EPSW_FE;
+		tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
+	}
+#else /* !CONFIG_LAZY_SAVE_FPU */
+	if (fpu_state_owner == tsk) {
+		fpu_save(&tsk->thread.fpu_state);
+		fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
+		fpu_state_owner = NULL;
+	}
+#endif /* !CONFIG_LAZY_SAVE_FPU */
+
+	preempt_enable();
+
+	/* we no longer have a valid current FPU state */
+	clear_using_fpu(tsk);
+
+	/* transfer the saved FPU state onto the userspace stack */
+	if (copy_to_user(fpucontext,
+			 &tsk->thread.fpu_state,
+			 min(sizeof(struct fpu_state_struct),
+			     sizeof(struct fpucontext))))
+		return -1;
+
+	return 1;
+}
+
+/*
+ * kill a process's FPU state during restoration after signal handling
+ */
+void fpu_kill_state(struct task_struct *tsk)
+{
+	/* disown anything left in the FPU */
+	preempt_disable();
+
+#ifndef CONFIG_LAZY_SAVE_FPU
+	if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
+		tsk->thread.uregs->epsw &= ~EPSW_FE;
+		tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
+	}
+#else /* !CONFIG_LAZY_SAVE_FPU */
+	if (fpu_state_owner == tsk) {
+		fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
+		fpu_state_owner = NULL;
+	}
+#endif /* !CONFIG_LAZY_SAVE_FPU */
+
+	preempt_enable();
+
+	/* we no longer have a valid current FPU state */
+	clear_using_fpu(tsk);
+}
+
+/*
+ * restore the FPU state from a signal context
+ */
+int fpu_restore_sigcontext(struct fpucontext *fpucontext)
+{
+	struct task_struct *tsk = current;
+	int ret;
+
+	/* load up the old FPU state */
+	ret = copy_from_user(&tsk->thread.fpu_state, fpucontext,
+			     min(sizeof(struct fpu_state_struct),
+				 sizeof(struct fpucontext)));
+	if (!ret)
+		set_using_fpu(tsk);
+
+	return ret;
+}
+
+/*
+ * fill in the FPU structure for a core dump
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpreg)
+{
+	struct task_struct *tsk = current;
+	int fpvalid;
+
+	fpvalid = is_using_fpu(tsk);
+	if (fpvalid) {
+		unlazy_fpu(tsk);
+		memcpy(fpreg, &tsk->thread.fpu_state, sizeof(*fpreg));
+	}
+
+	return fpvalid;
+}
diff --git a/arch/mn10300/kernel/gdb-io-serial-low.S b/arch/mn10300/kernel/gdb-io-serial-low.S
new file mode 100644
index 0000000..b1d0152
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-serial-low.S
@@ -0,0 +1,91 @@
+###############################################################################
+#
+# 16550 serial Rx interrupt handler for gdbstub I/O
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/cpu-regs.h>
+#include <asm/thread_info.h>
+#include <asm/frame.inc>
+#include <asm/intctl-regs.h>
+#include <asm/irqflags.h>
+#include <unit/serial.h>
+
+	.text
+
+###############################################################################
+#
+# GDB stub serial receive interrupt entry point
+# - intended to run at interrupt priority 0
+#
+###############################################################################
+	.globl	gdbstub_io_rx_handler
+	.type	gdbstub_io_rx_handler,@function
+gdbstub_io_rx_handler:
+	movm	[d2,d3,a2,a3],(sp)
+
+#if 1
+	movbu	(GDBPORT_SERIAL_IIR),d2
+#endif
+
+	mov	(gdbstub_rx_inp),a3
+gdbstub_io_rx_more:
+	mov	a3,a2
+	add	2,a3
+	and	0x00000fff,a3
+	mov	(gdbstub_rx_outp),d3
+	cmp	a3,d3
+	beq	gdbstub_io_rx_overflow
+
+	movbu	(GDBPORT_SERIAL_LSR),d3
+	btst	UART_LSR_DR,d3
+	beq	gdbstub_io_rx_done
+	movbu	(GDBPORT_SERIAL_RX),d2
+	movbu	d3,(gdbstub_rx_buffer+1,a2)
+	movbu	d2,(gdbstub_rx_buffer,a2)
+	mov	a3,(gdbstub_rx_inp)
+	bra	gdbstub_io_rx_more
+
+gdbstub_io_rx_done:
+	mov	GxICR_DETECT,d2
+	movbu	d2,(XIRQxICR(GDBPORT_SERIAL_IRQ))	# ACK the interrupt
+	movhu	(XIRQxICR(GDBPORT_SERIAL_IRQ)),d2	# flush
+	movm	(sp),[d2,d3,a2,a3]
+	bset	0x01,(gdbstub_busy)
+	beq	gdbstub_io_rx_enter
+	rti
+
+gdbstub_io_rx_overflow:
+	bset	0x01,(gdbstub_rx_overflow)
+	bra	gdbstub_io_rx_done
+
+gdbstub_io_rx_enter:
+	LOCAL_CHANGE_INTR_MASK_LEVEL(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL+1))
+	add	-4,sp
+	SAVE_ALL
+
+	mov	0xffffffff,d0
+	mov	d0,(REG_ORIG_D0,fp)
+	mov	0x280,d1
+
+	mov	fp,d0
+	call	gdbstub_rx_irq[],0	# gdbstub_rx_irq(regs,excep)
+
+	LOCAL_CLI
+	bclr	0x01,(gdbstub_busy)
+
+	.globl gdbstub_return
+gdbstub_return:
+	RESTORE_ALL
+
+	.size	gdbstub_io_rx_handler,.-gdbstub_io_rx_handler
diff --git a/arch/mn10300/kernel/gdb-io-serial.c b/arch/mn10300/kernel/gdb-io-serial.c
new file mode 100644
index 0000000..df51242
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-serial.c
@@ -0,0 +1,174 @@
+/* 16550 serial driver for gdbstub I/O
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/nmi.h>
+
+#include <asm/pgtable.h>
+#include <asm/gdb-stub.h>
+#include <asm/exceptions.h>
+#include <asm/serial-regs.h>
+#include <unit/serial.h>
+#include <asm/smp.h>
+
+/*
+ * initialise the GDB stub
+ */
+void gdbstub_io_init(void)
+{
+	u16 tmp;
+
+	/* set up the serial port */
+	GDBPORT_SERIAL_LCR = UART_LCR_WLEN8; /* 1N8 */
+	GDBPORT_SERIAL_FCR = (UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
+			      UART_FCR_CLEAR_XMIT);
+
+	FLOWCTL_CLEAR(DTR);
+	FLOWCTL_SET(RTS);
+
+	gdbstub_io_set_baud(115200);
+
+	/* we want to get serial receive interrupts */
+	XIRQxICR(GDBPORT_SERIAL_IRQ) = 0;
+	tmp = XIRQxICR(GDBPORT_SERIAL_IRQ);
+
+#if   CONFIG_GDBSTUB_IRQ_LEVEL == 0
+	IVAR0 = EXCEP_IRQ_LEVEL0;
+#elif CONFIG_GDBSTUB_IRQ_LEVEL == 1
+	IVAR1 = EXCEP_IRQ_LEVEL1;
+#elif CONFIG_GDBSTUB_IRQ_LEVEL == 2
+	IVAR2 = EXCEP_IRQ_LEVEL2;
+#elif CONFIG_GDBSTUB_IRQ_LEVEL == 3
+	IVAR3 = EXCEP_IRQ_LEVEL3;
+#elif CONFIG_GDBSTUB_IRQ_LEVEL == 4
+	IVAR4 = EXCEP_IRQ_LEVEL4;
+#elif CONFIG_GDBSTUB_IRQ_LEVEL == 5
+	IVAR5 = EXCEP_IRQ_LEVEL5;
+#else
+#error "Unknown irq level for gdbstub."
+#endif
+
+	set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL),
+		gdbstub_io_rx_handler);
+
+	XIRQxICR(GDBPORT_SERIAL_IRQ) &= ~GxICR_REQUEST;
+	XIRQxICR(GDBPORT_SERIAL_IRQ) =
+		GxICR_ENABLE | NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL);
+	tmp = XIRQxICR(GDBPORT_SERIAL_IRQ);
+
+	GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI;
+
+	/* permit level 0 IRQs to take place */
+	arch_local_change_intr_mask_level(
+		NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
+}
+
+/*
+ * set up the GDB stub serial port baud rate timers
+ */
+void gdbstub_io_set_baud(unsigned baud)
+{
+	unsigned value;
+	u8 lcr;
+
+	value = 18432000 / 16 / baud;
+
+	lcr = GDBPORT_SERIAL_LCR;
+	GDBPORT_SERIAL_LCR |= UART_LCR_DLAB;
+	GDBPORT_SERIAL_DLL = value & 0xff;
+	GDBPORT_SERIAL_DLM = (value >> 8) & 0xff;
+	GDBPORT_SERIAL_LCR = lcr;
+}
+
+/*
+ * wait for a character to come from the debugger
+ */
+int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
+{
+	unsigned ix;
+	u8 ch, st;
+#if defined(CONFIG_MN10300_WD_TIMER)
+	int cpu;
+#endif
+
+	*_ch = 0xff;
+
+	if (gdbstub_rx_unget) {
+		*_ch = gdbstub_rx_unget;
+		gdbstub_rx_unget = 0;
+		return 0;
+	}
+
+ try_again:
+	/* pull chars out of the buffer */
+	ix = gdbstub_rx_outp;
+	barrier();
+	if (ix == gdbstub_rx_inp) {
+		if (nonblock)
+			return -EAGAIN;
+#ifdef CONFIG_MN10300_WD_TIMER
+	for (cpu = 0; cpu < NR_CPUS; cpu++)
+		watchdog_alert_counter[cpu] = 0;
+#endif
+		goto try_again;
+	}
+
+	ch = gdbstub_rx_buffer[ix++];
+	st = gdbstub_rx_buffer[ix++];
+	barrier();
+	gdbstub_rx_outp = ix & 0x00000fff;
+
+	if (st & UART_LSR_BI) {
+		gdbstub_proto("### GDB Rx Break Detected ###\n");
+		return -EINTR;
+	} else if (st & (UART_LSR_FE | UART_LSR_OE | UART_LSR_PE)) {
+		gdbstub_proto("### GDB Rx Error (st=%02x) ###\n", st);
+		return -EIO;
+	} else {
+		gdbstub_proto("### GDB Rx %02x (st=%02x) ###\n", ch, st);
+		*_ch = ch & 0x7f;
+		return 0;
+	}
+}
+
+/*
+ * send a character to the debugger
+ */
+void gdbstub_io_tx_char(unsigned char ch)
+{
+	FLOWCTL_SET(DTR);
+	LSR_WAIT_FOR(THRE);
+	/* FLOWCTL_WAIT_FOR(CTS); */
+
+	if (ch == 0x0a) {
+		GDBPORT_SERIAL_TX = 0x0d;
+		LSR_WAIT_FOR(THRE);
+		/* FLOWCTL_WAIT_FOR(CTS); */
+	}
+	GDBPORT_SERIAL_TX = ch;
+
+	FLOWCTL_CLEAR(DTR);
+}
+
+/*
+ * send a character to the debugger
+ */
+void gdbstub_io_tx_flush(void)
+{
+	LSR_WAIT_FOR(TEMT);
+	LSR_WAIT_FOR(THRE);
+	FLOWCTL_CLEAR(DTR);
+}
diff --git a/arch/mn10300/kernel/gdb-io-ttysm-low.S b/arch/mn10300/kernel/gdb-io-ttysm-low.S
new file mode 100644
index 0000000..060b7cc
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-ttysm-low.S
@@ -0,0 +1,93 @@
+###############################################################################
+#
+# MN10300 On-chip serial Rx interrupt handler for GDB stub I/O
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/thread_info.h>
+#include <asm/cpu-regs.h>
+#include <asm/frame.inc>
+#include <asm/intctl-regs.h>
+#include <unit/serial.h>
+#include "mn10300-serial.h"
+
+	.text
+
+###############################################################################
+#
+# GDB stub serial receive interrupt entry point
+# - intended to run at interrupt priority 0
+#
+###############################################################################
+	.globl	gdbstub_io_rx_handler
+	.type	gdbstub_io_rx_handler,@function
+gdbstub_io_rx_handler:
+	movm	[d2,d3,a2,a3],(sp)
+
+	mov	(gdbstub_rx_inp),a3
+gdbstub_io_rx_more:
+	mov	a3,a2
+	add	2,a3
+	and	PAGE_SIZE_asm-1,a3
+	mov	(gdbstub_rx_outp),d3
+	cmp	a3,d3
+	beq	gdbstub_io_rx_overflow
+
+	movbu	(SCgSTR),d3
+	btst	SC01STR_RBF,d3
+	beq	gdbstub_io_rx_done
+	movbu	(SCgRXB),d2
+	movbu	d3,(gdbstub_rx_buffer+1,a2)
+	movbu	d2,(gdbstub_rx_buffer,a2)
+	mov	a3,(gdbstub_rx_inp)
+	bra	gdbstub_io_rx_more
+
+gdbstub_io_rx_done:
+	mov	GxICR_DETECT,d2
+	movbu	d2,(GxICR(SCgRXIRQ))	# ACK the interrupt
+	movhu	(GxICR(SCgRXIRQ)),d2	# flush
+
+	movm	(sp),[d2,d3,a2,a3]
+	bset	0x01,(gdbstub_busy)
+	beq	gdbstub_io_rx_enter
+	rti
+
+gdbstub_io_rx_overflow:
+	bset	0x01,(gdbstub_rx_overflow)
+	bra	gdbstub_io_rx_done
+
+###############################################################################
+#
+# debugging interrupt - enter the GDB stub proper
+#
+###############################################################################
+gdbstub_io_rx_enter:
+	or	EPSW_IE|EPSW_IM_1,epsw
+	add	-4,sp
+	SAVE_ALL
+
+	mov	0xffffffff,d0
+	mov	d0,(REG_ORIG_D0,fp)
+	mov	0x280,d1
+
+	mov	fp,d0
+	call	gdbstub_rx_irq[],0	# gdbstub_io_rx_irq(regs,excep)
+
+	and	~EPSW_IE,epsw
+	bclr	0x01,(gdbstub_busy)
+
+	.globl gdbstub_return
+gdbstub_return:
+	RESTORE_ALL
+
+	.size	gdbstub_io_rx_handler,.-gdbstub_io_rx_handler
diff --git a/arch/mn10300/kernel/gdb-io-ttysm.c b/arch/mn10300/kernel/gdb-io-ttysm.c
new file mode 100644
index 0000000..caae8ca
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-ttysm.c
@@ -0,0 +1,303 @@
+/* MN10300 On-chip serial driver for gdbstub I/O
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <asm/pgtable.h>
+#include <asm/gdb-stub.h>
+#include <asm/exceptions.h>
+#include <unit/clock.h>
+#include "mn10300-serial.h"
+
+#if defined(CONFIG_GDBSTUB_ON_TTYSM0)
+struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif0;
+#elif defined(CONFIG_GDBSTUB_ON_TTYSM1)
+struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif1;
+#else
+struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif2;
+#endif
+
+
+/*
+ * initialise the GDB stub I/O routines
+ */
+void __init gdbstub_io_init(void)
+{
+	uint16_t scxctr;
+	int tmp;
+
+	switch (gdbstub_port->clock_src) {
+	case MNSCx_CLOCK_SRC_IOCLK:
+		gdbstub_port->ioclk = MN10300_IOCLK;
+		break;
+
+#ifdef MN10300_IOBCLK
+	case MNSCx_CLOCK_SRC_IOBCLK:
+		gdbstub_port->ioclk = MN10300_IOBCLK;
+		break;
+#endif
+	default:
+		BUG();
+	}
+
+	/* set up the serial port */
+	gdbstub_io_set_baud(115200);
+
+	/* we want to get serial receive interrupts */
+	set_intr_level(gdbstub_port->rx_irq,
+		NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL));
+	set_intr_level(gdbstub_port->tx_irq,
+		NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL));
+	set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL),
+		gdbstub_io_rx_handler);
+
+	*gdbstub_port->rx_icr |= GxICR_ENABLE;
+	tmp = *gdbstub_port->rx_icr;
+
+	/* enable the device */
+	scxctr = SC01CTR_CLN_8BIT;	/* 1N8 */
+	switch (gdbstub_port->div_timer) {
+	case MNSCx_DIV_TIMER_16BIT:
+		scxctr |= SC0CTR_CK_TM8UFLOW_8; /* == SC1CTR_CK_TM9UFLOW_8
+						   == SC2CTR_CK_TM10UFLOW_8 */
+		break;
+
+	case MNSCx_DIV_TIMER_8BIT:
+		scxctr |= SC0CTR_CK_TM2UFLOW_8;
+		break;
+	}
+
+	scxctr |= SC01CTR_TXE | SC01CTR_RXE;
+
+	*gdbstub_port->_control = scxctr;
+	tmp = *gdbstub_port->_control;
+
+	/* permit level 0 IRQs only */
+	arch_local_change_intr_mask_level(
+		NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1));
+}
+
+/*
+ * set up the GDB stub serial port baud rate timers
+ */
+void gdbstub_io_set_baud(unsigned baud)
+{
+	const unsigned bits = 10; /* 1 [start] + 8 [data] + 0 [parity] +
+				   * 1 [stop] */
+	unsigned long ioclk = gdbstub_port->ioclk;
+	unsigned xdiv, tmp;
+	uint16_t tmxbr;
+	uint8_t tmxmd;
+
+	if (!baud) {
+		baud = 9600;
+	} else if (baud == 134) {
+		baud = 269;	/* 134 is really 134.5 */
+		xdiv = 2;
+	}
+
+try_alternative:
+	xdiv = 1;
+
+	switch (gdbstub_port->div_timer) {
+	case MNSCx_DIV_TIMER_16BIT:
+		tmxmd = TM8MD_SRC_IOCLK;
+		tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 65535)
+			goto timer_okay;
+
+		tmxmd = TM8MD_SRC_IOCLK_8;
+		tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 65535)
+			goto timer_okay;
+
+		tmxmd = TM8MD_SRC_IOCLK_32;
+		tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 65535)
+			goto timer_okay;
+
+		break;
+
+	case MNSCx_DIV_TIMER_8BIT:
+		tmxmd = TM2MD_SRC_IOCLK;
+		tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 255)
+			goto timer_okay;
+
+		tmxmd = TM2MD_SRC_IOCLK_8;
+		tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 255)
+			goto timer_okay;
+
+		tmxmd = TM2MD_SRC_IOCLK_32;
+		tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 255)
+			goto timer_okay;
+		break;
+	}
+
+	/* as a last resort, if the quotient is zero, default to 9600 bps */
+	baud = 9600;
+	goto try_alternative;
+
+timer_okay:
+	gdbstub_port->uart.timeout = (2 * bits * HZ) / baud;
+	gdbstub_port->uart.timeout += HZ / 50;
+
+	/* set the timer to produce the required baud rate */
+	switch (gdbstub_port->div_timer) {
+	case MNSCx_DIV_TIMER_16BIT:
+		*gdbstub_port->_tmxmd = 0;
+		*gdbstub_port->_tmxbr = tmxbr;
+		*gdbstub_port->_tmxmd = TM8MD_INIT_COUNTER;
+		*gdbstub_port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE;
+		break;
+
+	case MNSCx_DIV_TIMER_8BIT:
+		*gdbstub_port->_tmxmd = 0;
+		*(volatile u8 *) gdbstub_port->_tmxbr = (u8)tmxbr;
+		*gdbstub_port->_tmxmd = TM2MD_INIT_COUNTER;
+		*gdbstub_port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE;
+		break;
+	}
+}
+
+/*
+ * wait for a character to come from the debugger
+ */
+int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
+{
+	unsigned ix;
+	u8 ch, st;
+#if defined(CONFIG_MN10300_WD_TIMER)
+	int cpu;
+#endif
+
+	*_ch = 0xff;
+
+	if (gdbstub_rx_unget) {
+		*_ch = gdbstub_rx_unget;
+		gdbstub_rx_unget = 0;
+		return 0;
+	}
+
+try_again:
+	/* pull chars out of the buffer */
+	ix = gdbstub_rx_outp;
+	barrier();
+	if (ix == gdbstub_rx_inp) {
+		if (nonblock)
+			return -EAGAIN;
+#ifdef CONFIG_MN10300_WD_TIMER
+	for (cpu = 0; cpu < NR_CPUS; cpu++)
+		watchdog_alert_counter[cpu] = 0;
+#endif
+		goto try_again;
+	}
+
+	ch = gdbstub_rx_buffer[ix++];
+	st = gdbstub_rx_buffer[ix++];
+	barrier();
+	gdbstub_rx_outp = ix & (PAGE_SIZE - 1);
+
+	st &= SC01STR_RXF | SC01STR_RBF | SC01STR_FEF | SC01STR_PEF |
+		SC01STR_OEF;
+
+	/* deal with what we've got
+	 * - note that the UART doesn't do BREAK-detection for us
+	 */
+	if (st & SC01STR_FEF && ch == 0) {
+		switch (gdbstub_port->rx_brk) {
+		case 0:	gdbstub_port->rx_brk = 1;	goto try_again;
+		case 1:	gdbstub_port->rx_brk = 2;	goto try_again;
+		case 2:
+			gdbstub_port->rx_brk = 3;
+			gdbstub_proto("### GDB MNSERIAL Rx Break Detected"
+				      " ###\n");
+			return -EINTR;
+		default:
+			goto try_again;
+		}
+	} else if (st & SC01STR_FEF) {
+		if (gdbstub_port->rx_brk)
+			goto try_again;
+
+		gdbstub_proto("### GDB MNSERIAL Framing Error ###\n");
+		return -EIO;
+	} else if (st & SC01STR_OEF) {
+		if (gdbstub_port->rx_brk)
+			goto try_again;
+
+		gdbstub_proto("### GDB MNSERIAL Overrun Error ###\n");
+		return -EIO;
+	} else if (st & SC01STR_PEF) {
+		if (gdbstub_port->rx_brk)
+			goto try_again;
+
+		gdbstub_proto("### GDB MNSERIAL Parity Error ###\n");
+		return -EIO;
+	} else {
+		/* look for the tail-end char on a break run */
+		if (gdbstub_port->rx_brk == 3) {
+			switch (ch) {
+			case 0xFF:
+			case 0xFE:
+			case 0xFC:
+			case 0xF8:
+			case 0xF0:
+			case 0xE0:
+			case 0xC0:
+			case 0x80:
+			case 0x00:
+				gdbstub_port->rx_brk = 0;
+				goto try_again;
+			default:
+				break;
+			}
+		}
+
+		gdbstub_port->rx_brk = 0;
+		gdbstub_io("### GDB Rx %02x (st=%02x) ###\n", ch, st);
+		*_ch = ch & 0x7f;
+		return 0;
+	}
+}
+
+/*
+ * send a character to the debugger
+ */
+void gdbstub_io_tx_char(unsigned char ch)
+{
+	while (*gdbstub_port->_status & SC01STR_TBF)
+		continue;
+
+	if (ch == 0x0a) {
+		*(u8 *) gdbstub_port->_txb = 0x0d;
+		while (*gdbstub_port->_status & SC01STR_TBF)
+			continue;
+	}
+
+	*(u8 *) gdbstub_port->_txb = ch;
+}
+
+/*
+ * flush the transmission buffers
+ */
+void gdbstub_io_tx_flush(void)
+{
+	while (*gdbstub_port->_status & (SC01STR_TBF | SC01STR_TXF))
+		continue;
+}
diff --git a/arch/mn10300/kernel/gdb-low.S b/arch/mn10300/kernel/gdb-low.S
new file mode 100644
index 0000000..e272555
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-low.S
@@ -0,0 +1,115 @@
+###############################################################################
+#
+# MN10300 Low-level gdbstub routines
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/cache.h>
+#include <asm/cpu-regs.h>
+#include <asm/exceptions.h>
+#include <asm/frame.inc>
+#include <asm/serial-regs.h>
+
+	.text
+
+###############################################################################
+#
+# GDB stub read memory with guard
+# - D0 holds the memory address to read
+# - D1 holds the address to store the byte into
+#
+###############################################################################
+	.globl gdbstub_read_byte_guard
+	.globl gdbstub_read_byte_cont
+ENTRY(gdbstub_read_byte)
+	mov	d0,a0
+	mov	d1,a1
+	clr	d0
+gdbstub_read_byte_guard:
+	movbu	(a0),d1
+gdbstub_read_byte_cont:
+	movbu	d1,(a1)
+	ret	[],0
+
+	.globl gdbstub_read_word_guard
+	.globl gdbstub_read_word_cont
+ENTRY(gdbstub_read_word)
+	mov	d0,a0
+	mov	d1,a1
+	clr	d0
+gdbstub_read_word_guard:
+	movhu	(a0),d1
+gdbstub_read_word_cont:
+	movhu	d1,(a1)
+	ret	[],0
+
+	.globl gdbstub_read_dword_guard
+	.globl gdbstub_read_dword_cont
+ENTRY(gdbstub_read_dword)
+	mov	d0,a0
+	mov	d1,a1
+	clr	d0
+gdbstub_read_dword_guard:
+	mov	(a0),d1
+gdbstub_read_dword_cont:
+	mov	d1,(a1)
+	ret	[],0
+
+###############################################################################
+#
+# GDB stub write memory with guard
+# - D0 holds the byte to store
+# - D1 holds the memory address to write
+#
+###############################################################################
+	.globl gdbstub_write_byte_guard
+	.globl gdbstub_write_byte_cont
+ENTRY(gdbstub_write_byte)
+	mov	d0,a0
+	mov	d1,a1
+	clr	d0
+gdbstub_write_byte_guard:
+	movbu	a0,(a1)
+gdbstub_write_byte_cont:
+	ret	[],0
+
+	.globl gdbstub_write_word_guard
+	.globl gdbstub_write_word_cont
+ENTRY(gdbstub_write_word)
+	mov	d0,a0
+	mov	d1,a1
+	clr	d0
+gdbstub_write_word_guard:
+	movhu	a0,(a1)
+gdbstub_write_word_cont:
+	ret	[],0
+
+	.globl gdbstub_write_dword_guard
+	.globl gdbstub_write_dword_cont
+ENTRY(gdbstub_write_dword)
+	mov	d0,a0
+	mov	d1,a1
+	clr	d0
+gdbstub_write_dword_guard:
+	mov	a0,(a1)
+gdbstub_write_dword_cont:
+	ret	[],0
+
+###############################################################################
+#
+# GDB stub BUG() trap
+#
+###############################################################################
+ENTRY(__gdbstub_bug_trap)
+	.byte	0xF7,0xF7	# don't use 0xFF as the JTAG unit preempts that
+	ret	[],0
diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c
new file mode 100644
index 0000000..a128c57
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-stub.c
@@ -0,0 +1,1923 @@
+/* MN10300 GDB stub
+ *
+ * Originally written by Glenn Engel, Lake Stevens Instrument Division
+ *
+ * Contributed by HP Systems
+ *
+ * Modified for SPARC by Stu Grossman, Cygnus Support.
+ *
+ * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
+ * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
+ *
+ * Copyright (C) 1995 Andreas Busse
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified for Linux/mn10300 by David Howells <dhowells@redhat.com>
+ */
+
+/*
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to set_debug_traps() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
+ *  simulates a breakpoint by executing a BREAK instruction.
+ *
+ *
+ *    The following gdb commands are supported:
+ *
+ * command          function                               Return value
+ *
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ *
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ *
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ *
+ *    k             kill
+ *
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ *
+ *    bBB..BB	    Set baud rate to BB..BB		   OK or BNN, then sets
+ *							   baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum.  A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host:                  Reply:
+ * $m0,10#2a               +$00010203040506070809101112131415#42
+ *
+ *
+ *  ==============
+ *  MORE EXAMPLES:
+ *  ==============
+ *
+ *  For reference -- the following are the steps that one
+ *  company took (RidgeRun Inc) to get remote gdb debugging
+ *  going. In this scenario the host machine was a PC and the
+ *  target platform was a Galileo EVB64120A MIPS evaluation
+ *  board.
+ *
+ *  Step 1:
+ *  First download gdb-5.0.tar.gz from the internet.
+ *  and then build/install the package.
+ *
+ *  Example:
+ *    $ tar zxf gdb-5.0.tar.gz
+ *    $ cd gdb-5.0
+ *    $ ./configure --target=am33_2.0-linux-gnu
+ *    $ make
+ *    $ install
+ *    am33_2.0-linux-gnu-gdb
+ *
+ *  Step 2:
+ *  Configure linux for remote debugging and build it.
+ *
+ *  Example:
+ *    $ cd ~/linux
+ *    $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
+ *    $ make dep; make vmlinux
+ *
+ *  Step 3:
+ *  Download the kernel to the remote target and start
+ *  the kernel running. It will promptly halt and wait
+ *  for the host gdb session to connect. It does this
+ *  since the "Kernel Hacking" option has defined
+ *  CONFIG_REMOTE_DEBUG which in turn enables your calls
+ *  to:
+ *     set_debug_traps();
+ *     breakpoint();
+ *
+ *  Step 4:
+ *  Start the gdb session on the host.
+ *
+ *  Example:
+ *    $ am33_2.0-linux-gnu-gdb vmlinux
+ *    (gdb) set remotebaud 115200
+ *    (gdb) target remote /dev/ttyS1
+ *    ...at this point you are connected to
+ *       the remote target and can use gdb
+ *       in the normal fasion. Setting
+ *       breakpoints, single stepping,
+ *       printing variables, etc.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/bug.h>
+
+#include <asm/pgtable.h>
+#include <asm/gdb-stub.h>
+#include <asm/exceptions.h>
+#include <asm/debugger.h>
+#include <asm/serial-regs.h>
+#include <asm/busctl-regs.h>
+#include <unit/leds.h>
+#include <unit/serial.h>
+
+/* define to use F7F7 rather than FF which is subverted by JTAG debugger */
+#undef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+ * at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 2048
+
+static const char gdbstub_banner[] =
+	"Linux/MN10300 GDB Stub (c) RedHat 2007\n";
+
+u8	gdbstub_rx_buffer[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
+u32	gdbstub_rx_inp;
+u32	gdbstub_rx_outp;
+u8	gdbstub_busy;
+u8	gdbstub_rx_overflow;
+u8	gdbstub_rx_unget;
+
+static u8	gdbstub_flush_caches;
+static char	input_buffer[BUFMAX];
+static char	output_buffer[BUFMAX];
+static char	trans_buffer[BUFMAX];
+
+struct gdbstub_bkpt {
+	u8	*addr;		/* address of breakpoint */
+	u8	len;		/* size of breakpoint */
+	u8	origbytes[7];	/* original bytes */
+};
+
+static struct gdbstub_bkpt gdbstub_bkpts[256];
+
+/*
+ * local prototypes
+ */
+static void getpacket(char *buffer);
+static int putpacket(char *buffer);
+static int computeSignal(enum exception_code excep);
+static int hex(unsigned char ch);
+static int hexToInt(char **ptr, int *intValue);
+static unsigned char *mem2hex(const void *mem, char *buf, int count,
+			      int may_fault);
+static const char *hex2mem(const char *buf, void *_mem, int count,
+			   int may_fault);
+
+/*
+ * Convert ch from a hex digit to an int
+ */
+static int hex(unsigned char ch)
+{
+	if (ch >= 'a' && ch <= 'f')
+		return ch - 'a' + 10;
+	if (ch >= '0' && ch <= '9')
+		return ch - '0';
+	if (ch >= 'A' && ch <= 'F')
+		return ch - 'A' + 10;
+	return -1;
+}
+
+#ifdef CONFIG_GDBSTUB_DEBUGGING
+
+void debug_to_serial(const char *p, int n)
+{
+	__debug_to_serial(p, n);
+	/* gdbstub_console_write(NULL, p, n); */
+}
+
+void gdbstub_printk(const char *fmt, ...)
+{
+	va_list args;
+	int len;
+
+	/* Emit the output into the temporary buffer */
+	va_start(args, fmt);
+	len = vsnprintf(trans_buffer, sizeof(trans_buffer), fmt, args);
+	va_end(args);
+	debug_to_serial(trans_buffer, len);
+}
+
+#endif
+
+static inline char *gdbstub_strcpy(char *dst, const char *src)
+{
+	int loop = 0;
+	while ((dst[loop] = src[loop]))
+	       loop++;
+	return dst;
+}
+
+/*
+ * scan for the sequence $<data>#<checksum>
+ */
+static void getpacket(char *buffer)
+{
+	unsigned char checksum;
+	unsigned char xmitcsum;
+	unsigned char ch;
+	int count, i, ret, error;
+
+	for (;;) {
+		/*
+		 * wait around for the start character,
+		 * ignore all other characters
+		 */
+		do {
+			gdbstub_io_rx_char(&ch, 0);
+		} while (ch != '$');
+
+		checksum = 0;
+		xmitcsum = -1;
+		count = 0;
+		error = 0;
+
+		/*
+		 * now, read until a # or end of buffer is found
+		 */
+		while (count < BUFMAX) {
+			ret = gdbstub_io_rx_char(&ch, 0);
+			if (ret < 0)
+				error = ret;
+
+			if (ch == '#')
+				break;
+			checksum += ch;
+			buffer[count] = ch;
+			count++;
+		}
+
+		if (error == -EIO) {
+			gdbstub_proto("### GDB Rx Error - Skipping packet"
+				      " ###\n");
+			gdbstub_proto("### GDB Tx NAK\n");
+			gdbstub_io_tx_char('-');
+			continue;
+		}
+
+		if (count >= BUFMAX || error)
+			continue;
+
+		buffer[count] = 0;
+
+		/* read the checksum */
+		ret = gdbstub_io_rx_char(&ch, 0);
+		if (ret < 0)
+			error = ret;
+		xmitcsum = hex(ch) << 4;
+
+		ret = gdbstub_io_rx_char(&ch, 0);
+		if (ret < 0)
+			error = ret;
+		xmitcsum |= hex(ch);
+
+		if (error) {
+			if (error == -EIO)
+				gdbstub_io("### GDB Rx Error -"
+					   " Skipping packet\n");
+			gdbstub_io("### GDB Tx NAK\n");
+			gdbstub_io_tx_char('-');
+			continue;
+		}
+
+		/* check the checksum */
+		if (checksum != xmitcsum) {
+			gdbstub_io("### GDB Tx NAK\n");
+			gdbstub_io_tx_char('-');	/* failed checksum */
+			continue;
+		}
+
+		gdbstub_proto("### GDB Rx '$%s#%02x' ###\n", buffer, checksum);
+		gdbstub_io("### GDB Tx ACK\n");
+		gdbstub_io_tx_char('+'); /* successful transfer */
+
+		/*
+		 * if a sequence char is present,
+		 * reply the sequence ID
+		 */
+		if (buffer[2] == ':') {
+			gdbstub_io_tx_char(buffer[0]);
+			gdbstub_io_tx_char(buffer[1]);
+
+			/*
+			 * remove sequence chars from buffer
+			 */
+			count = 0;
+			while (buffer[count])
+				count++;
+			for (i = 3; i <= count; i++)
+				buffer[i - 3] = buffer[i];
+		}
+
+		break;
+	}
+}
+
+/*
+ * send the packet in buffer.
+ * - return 0 if successfully ACK'd
+ * - return 1 if abandoned due to new incoming packet
+ */
+static int putpacket(char *buffer)
+{
+	unsigned char checksum;
+	unsigned char ch;
+	int count;
+
+	/*
+	 * $<packet info>#<checksum>.
+	 */
+	gdbstub_proto("### GDB Tx $'%s'#?? ###\n", buffer);
+
+	do {
+		gdbstub_io_tx_char('$');
+		checksum = 0;
+		count = 0;
+
+		while ((ch = buffer[count]) != 0) {
+			gdbstub_io_tx_char(ch);
+			checksum += ch;
+			count += 1;
+		}
+
+		gdbstub_io_tx_char('#');
+		gdbstub_io_tx_char(hex_asc_hi(checksum));
+		gdbstub_io_tx_char(hex_asc_lo(checksum));
+
+	} while (gdbstub_io_rx_char(&ch, 0),
+		 ch == '-' && (gdbstub_io("### GDB Rx NAK\n"), 0),
+		 ch != '-' && ch != '+' &&
+		 (gdbstub_io("### GDB Rx ??? %02x\n", ch), 0),
+		 ch != '+' && ch != '$');
+
+	if (ch == '+') {
+		gdbstub_io("### GDB Rx ACK\n");
+		return 0;
+	}
+
+	gdbstub_io("### GDB Tx Abandoned\n");
+	gdbstub_rx_unget = ch;
+	return 1;
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+static int hexToInt(char **ptr, int *intValue)
+{
+	int numChars = 0;
+	int hexValue;
+
+	*intValue = 0;
+
+	while (**ptr) {
+		hexValue = hex(**ptr);
+		if (hexValue < 0)
+			break;
+
+		*intValue = (*intValue << 4) | hexValue;
+		numChars++;
+
+		(*ptr)++;
+	}
+
+	return (numChars);
+}
+
+#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
+/*
+ * We single-step by setting breakpoints. When an exception
+ * is handled, we need to restore the instructions hoisted
+ * when the breakpoints were set.
+ *
+ * This is where we save the original instructions.
+ */
+static struct gdb_bp_save {
+	u8	*addr;
+	u8	opcode[2];
+} step_bp[2];
+
+static const unsigned char gdbstub_insn_sizes[256] =
+{
+	/* 1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
+	1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3,	/* 0 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */
+	2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, /* 2 */
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, /* 3 */
+	1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, /* 4 */
+	1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, /* 5 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 8 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 9 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* a */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* b */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, /* c */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
+	0, 2, 2, 2, 2, 2, 2, 4, 0, 3, 0, 4, 0, 6, 7, 1  /* f */
+};
+
+static int __gdbstub_mark_bp(u8 *addr, int ix)
+{
+	/* vmalloc area */
+	if (((u8 *) VMALLOC_START <= addr) && (addr < (u8 *) VMALLOC_END))
+		goto okay;
+	/* SRAM, SDRAM */
+	if (((u8 *) 0x80000000UL <= addr) && (addr < (u8 *) 0xa0000000UL))
+		goto okay;
+	return 0;
+
+okay:
+	if (gdbstub_read_byte(addr + 0, &step_bp[ix].opcode[0]) < 0 ||
+	    gdbstub_read_byte(addr + 1, &step_bp[ix].opcode[1]) < 0)
+		return 0;
+
+	step_bp[ix].addr = addr;
+	return 1;
+}
+
+static inline void __gdbstub_restore_bp(void)
+{
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+	if (step_bp[0].addr) {
+		gdbstub_write_byte(step_bp[0].opcode[0], step_bp[0].addr + 0);
+		gdbstub_write_byte(step_bp[0].opcode[1], step_bp[0].addr + 1);
+	}
+	if (step_bp[1].addr) {
+		gdbstub_write_byte(step_bp[1].opcode[0], step_bp[1].addr + 0);
+		gdbstub_write_byte(step_bp[1].opcode[1], step_bp[1].addr + 1);
+	}
+#else
+	if (step_bp[0].addr)
+		gdbstub_write_byte(step_bp[0].opcode[0], step_bp[0].addr + 0);
+	if (step_bp[1].addr)
+		gdbstub_write_byte(step_bp[1].opcode[0], step_bp[1].addr + 0);
+#endif
+
+	gdbstub_flush_caches = 1;
+
+	step_bp[0].addr		= NULL;
+	step_bp[0].opcode[0]	= 0;
+	step_bp[0].opcode[1]	= 0;
+	step_bp[1].addr		= NULL;
+	step_bp[1].opcode[0]	= 0;
+	step_bp[1].opcode[1]	= 0;
+}
+
+/*
+ * emulate single stepping by means of breakpoint instructions
+ */
+static int gdbstub_single_step(struct pt_regs *regs)
+{
+	unsigned size;
+	uint32_t x;
+	uint8_t cur, *pc, *sp;
+
+	step_bp[0].addr		= NULL;
+	step_bp[0].opcode[0]	= 0;
+	step_bp[0].opcode[1]	= 0;
+	step_bp[1].addr		= NULL;
+	step_bp[1].opcode[0]	= 0;
+	step_bp[1].opcode[1]	= 0;
+	x = 0;
+
+	pc = (u8 *) regs->pc;
+	sp = (u8 *) (regs + 1);
+	if (gdbstub_read_byte(pc, &cur) < 0)
+		return -EFAULT;
+
+	gdbstub_bkpt("Single Step from %p { %02x }\n", pc, cur);
+
+	gdbstub_flush_caches = 1;
+
+	size = gdbstub_insn_sizes[cur];
+	if (size > 0) {
+		if (!__gdbstub_mark_bp(pc + size, 0))
+			goto fault;
+	} else {
+		switch (cur) {
+			/* Bxx (d8,PC) */
+		case 0xc0 ... 0xca:
+			if (gdbstub_read_byte(pc + 1, (u8 *) &x) < 0)
+				goto fault;
+			if (!__gdbstub_mark_bp(pc + 2, 0))
+				goto fault;
+			if ((x < 0 || x > 2) &&
+			    !__gdbstub_mark_bp(pc + (s8) x, 1))
+				goto fault;
+			break;
+
+			/* LXX (d8,PC) */
+		case 0xd0 ... 0xda:
+			if (!__gdbstub_mark_bp(pc + 1, 0))
+				goto fault;
+			if (regs->pc != regs->lar &&
+			    !__gdbstub_mark_bp((u8 *) regs->lar, 1))
+				goto fault;
+			break;
+
+			/* SETLB - loads the next for bytes into the LIR
+			 * register */
+		case 0xdb:
+			if (!__gdbstub_mark_bp(pc + 1, 0))
+				goto fault;
+			break;
+
+			/* JMP (d16,PC) or CALL (d16,PC) */
+		case 0xcc:
+		case 0xcd:
+			if (gdbstub_read_byte(pc + 1, ((u8 *) &x) + 0) < 0 ||
+			    gdbstub_read_byte(pc + 2, ((u8 *) &x) + 1) < 0)
+				goto fault;
+			if (!__gdbstub_mark_bp(pc + (s16) x, 0))
+				goto fault;
+			break;
+
+			/* JMP (d32,PC) or CALL (d32,PC) */
+		case 0xdc:
+		case 0xdd:
+			if (gdbstub_read_byte(pc + 1, ((u8 *) &x) + 0) < 0 ||
+			    gdbstub_read_byte(pc + 2, ((u8 *) &x) + 1) < 0 ||
+			    gdbstub_read_byte(pc + 3, ((u8 *) &x) + 2) < 0 ||
+			    gdbstub_read_byte(pc + 4, ((u8 *) &x) + 3) < 0)
+				goto fault;
+			if (!__gdbstub_mark_bp(pc + (s32) x, 0))
+				goto fault;
+			break;
+
+			/* RETF */
+		case 0xde:
+			if (!__gdbstub_mark_bp((u8 *) regs->mdr, 0))
+				goto fault;
+			break;
+
+			/* RET */
+		case 0xdf:
+			if (gdbstub_read_byte(pc + 2, (u8 *) &x) < 0)
+				goto fault;
+			sp += (s8)x;
+			if (gdbstub_read_byte(sp + 0, ((u8 *) &x) + 0) < 0 ||
+			    gdbstub_read_byte(sp + 1, ((u8 *) &x) + 1) < 0 ||
+			    gdbstub_read_byte(sp + 2, ((u8 *) &x) + 2) < 0 ||
+			    gdbstub_read_byte(sp + 3, ((u8 *) &x) + 3) < 0)
+				goto fault;
+			if (!__gdbstub_mark_bp((u8 *) x, 0))
+				goto fault;
+			break;
+
+		case 0xf0:
+			if (gdbstub_read_byte(pc + 1, &cur) < 0)
+				goto fault;
+
+			if (cur >= 0xf0 && cur <= 0xf7) {
+				/* JMP (An) / CALLS (An) */
+				switch (cur & 3) {
+				case 0: x = regs->a0; break;
+				case 1: x = regs->a1; break;
+				case 2: x = regs->a2; break;
+				case 3: x = regs->a3; break;
+				}
+				if (!__gdbstub_mark_bp((u8 *) x, 0))
+					goto fault;
+			} else if (cur == 0xfc) {
+				/* RETS */
+				if (gdbstub_read_byte(
+					    sp + 0, ((u8 *) &x) + 0) < 0 ||
+				    gdbstub_read_byte(
+					    sp + 1, ((u8 *) &x) + 1) < 0 ||
+				    gdbstub_read_byte(
+					    sp + 2, ((u8 *) &x) + 2) < 0 ||
+				    gdbstub_read_byte(
+					    sp + 3, ((u8 *) &x) + 3) < 0)
+					goto fault;
+				if (!__gdbstub_mark_bp((u8 *) x, 0))
+					goto fault;
+			} else if (cur == 0xfd) {
+				/* RTI */
+				if (gdbstub_read_byte(
+					    sp + 4, ((u8 *) &x) + 0) < 0 ||
+				    gdbstub_read_byte(
+					    sp + 5, ((u8 *) &x) + 1) < 0 ||
+				    gdbstub_read_byte(
+					    sp + 6, ((u8 *) &x) + 2) < 0 ||
+				    gdbstub_read_byte(
+					    sp + 7, ((u8 *) &x) + 3) < 0)
+					goto fault;
+				if (!__gdbstub_mark_bp((u8 *) x, 0))
+					goto fault;
+			} else {
+				if (!__gdbstub_mark_bp(pc + 2, 0))
+					goto fault;
+			}
+
+			break;
+
+			/* potential 3-byte conditional branches */
+		case 0xf8:
+			if (gdbstub_read_byte(pc + 1, &cur) < 0)
+				goto fault;
+			if (!__gdbstub_mark_bp(pc + 3, 0))
+				goto fault;
+
+			if (cur >= 0xe8 && cur <= 0xeb) {
+				if (gdbstub_read_byte(
+					    pc + 2, ((u8 *) &x) + 0) < 0)
+					goto fault;
+				if ((x < 0 || x > 3) &&
+				    !__gdbstub_mark_bp(pc + (s8) x, 1))
+					goto fault;
+			}
+			break;
+
+		case 0xfa:
+			if (gdbstub_read_byte(pc + 1, &cur) < 0)
+				goto fault;
+
+			if (cur == 0xff) {
+				/* CALLS (d16,PC) */
+				if (gdbstub_read_byte(
+					    pc + 2, ((u8 *) &x) + 0) < 0 ||
+				    gdbstub_read_byte(
+					    pc + 3, ((u8 *) &x) + 1) < 0)
+					goto fault;
+				if (!__gdbstub_mark_bp(pc + (s16) x, 0))
+					goto fault;
+			} else {
+				if (!__gdbstub_mark_bp(pc + 4, 0))
+					goto fault;
+			}
+			break;
+
+		case 0xfc:
+			if (gdbstub_read_byte(pc + 1, &cur) < 0)
+				goto fault;
+			if (cur == 0xff) {
+				/* CALLS (d32,PC) */
+				if (gdbstub_read_byte(
+					    pc + 2, ((u8 *) &x) + 0) < 0 ||
+				    gdbstub_read_byte(
+					    pc + 3, ((u8 *) &x) + 1) < 0 ||
+				    gdbstub_read_byte(
+					    pc + 4, ((u8 *) &x) + 2) < 0 ||
+				    gdbstub_read_byte(
+					    pc + 5, ((u8 *) &x) + 3) < 0)
+					goto fault;
+				if (!__gdbstub_mark_bp(
+					    pc + (s32) x, 0))
+					goto fault;
+			} else {
+				if (!__gdbstub_mark_bp(
+					    pc + 6, 0))
+					goto fault;
+			}
+			break;
+
+		}
+	}
+
+	gdbstub_bkpt("Step: %02x at %p; %02x at %p\n",
+		     step_bp[0].opcode[0], step_bp[0].addr,
+		     step_bp[1].opcode[0], step_bp[1].addr);
+
+	if (step_bp[0].addr) {
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+		if (gdbstub_write_byte(0xF7, step_bp[0].addr + 0) < 0 ||
+		    gdbstub_write_byte(0xF7, step_bp[0].addr + 1) < 0)
+			goto fault;
+#else
+		if (gdbstub_write_byte(0xFF, step_bp[0].addr + 0) < 0)
+			goto fault;
+#endif
+	}
+
+	if (step_bp[1].addr) {
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+		if (gdbstub_write_byte(0xF7, step_bp[1].addr + 0) < 0 ||
+		    gdbstub_write_byte(0xF7, step_bp[1].addr + 1) < 0)
+			goto fault;
+#else
+		if (gdbstub_write_byte(0xFF, step_bp[1].addr + 0) < 0)
+			goto fault;
+#endif
+	}
+
+	return 0;
+
+ fault:
+	/* uh-oh - silly address alert, try and restore things */
+	__gdbstub_restore_bp();
+	return -EFAULT;
+}
+#endif /* CONFIG_GDBSTUB_ALLOW_SINGLE_STEP */
+
+#ifdef CONFIG_GDBSTUB_CONSOLE
+
+void gdbstub_console_write(struct console *con, const char *p, unsigned n)
+{
+	static const char gdbstub_cr[] = { 0x0d };
+	char outbuf[26];
+	int qty;
+	u8 busy;
+
+	busy = gdbstub_busy;
+	gdbstub_busy = 1;
+
+	outbuf[0] = 'O';
+
+	while (n > 0) {
+		qty = 1;
+
+		while (n > 0 && qty < 20) {
+			mem2hex(p, outbuf + qty, 2, 0);
+			qty += 2;
+			if (*p == 0x0a) {
+				mem2hex(gdbstub_cr, outbuf + qty, 2, 0);
+				qty += 2;
+			}
+			p++;
+			n--;
+		}
+
+		outbuf[qty] = 0;
+		putpacket(outbuf);
+	}
+
+	gdbstub_busy = busy;
+}
+
+static kdev_t gdbstub_console_dev(struct console *con)
+{
+	return MKDEV(1, 3); /* /dev/null */
+}
+
+static struct console gdbstub_console = {
+	.name	= "gdb",
+	.write	= gdbstub_console_write,
+	.device	= gdbstub_console_dev,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+};
+
+#endif
+
+/*
+ * Convert the memory pointed to by mem into hex, placing result in buf.
+ * - if successful, return a pointer to the last char put in buf (NUL)
+ * - in case of mem fault, return NULL
+ * may_fault is non-zero if we are reading from arbitrary memory, but is
+ * currently not used.
+ */
+static
+unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
+{
+	const u8 *mem = _mem;
+	u8 ch[4];
+
+	if ((u32) mem & 1 && count >= 1) {
+		if (gdbstub_read_byte(mem, ch) != 0)
+			return 0;
+		buf = hex_byte_pack(buf, ch[0]);
+		mem++;
+		count--;
+	}
+
+	if ((u32) mem & 3 && count >= 2) {
+		if (gdbstub_read_word(mem, ch) != 0)
+			return 0;
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
+		mem += 2;
+		count -= 2;
+	}
+
+	while (count >= 4) {
+		if (gdbstub_read_dword(mem, ch) != 0)
+			return 0;
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
+		buf = hex_byte_pack(buf, ch[2]);
+		buf = hex_byte_pack(buf, ch[3]);
+		mem += 4;
+		count -= 4;
+	}
+
+	if (count >= 2) {
+		if (gdbstub_read_word(mem, ch) != 0)
+			return 0;
+		buf = hex_byte_pack(buf, ch[0]);
+		buf = hex_byte_pack(buf, ch[1]);
+		mem += 2;
+		count -= 2;
+	}
+
+	if (count >= 1) {
+		if (gdbstub_read_byte(mem, ch) != 0)
+			return 0;
+		buf = hex_byte_pack(buf, ch[0]);
+	}
+
+	*buf = 0;
+	return buf;
+}
+
+/*
+ * convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written
+ * may_fault is non-zero if we are reading from arbitrary memory, but is
+ * currently not used.
+ */
+static
+const char *hex2mem(const char *buf, void *_mem, int count, int may_fault)
+{
+	u8 *mem = _mem;
+	union {
+		u32 val;
+		u8 b[4];
+	} ch;
+
+	if ((u32) mem & 1 && count >= 1) {
+		ch.b[0]  = hex(*buf++) << 4;
+		ch.b[0] |= hex(*buf++);
+		if (gdbstub_write_byte(ch.val, mem) != 0)
+			return 0;
+		mem++;
+		count--;
+	}
+
+	if ((u32) mem & 3 && count >= 2) {
+		ch.b[0]  = hex(*buf++) << 4;
+		ch.b[0] |= hex(*buf++);
+		ch.b[1]  = hex(*buf++) << 4;
+		ch.b[1] |= hex(*buf++);
+		if (gdbstub_write_word(ch.val, mem) != 0)
+			return 0;
+		mem += 2;
+		count -= 2;
+	}
+
+	while (count >= 4) {
+		ch.b[0]  = hex(*buf++) << 4;
+		ch.b[0] |= hex(*buf++);
+		ch.b[1]  = hex(*buf++) << 4;
+		ch.b[1] |= hex(*buf++);
+		ch.b[2]  = hex(*buf++) << 4;
+		ch.b[2] |= hex(*buf++);
+		ch.b[3]  = hex(*buf++) << 4;
+		ch.b[3] |= hex(*buf++);
+		if (gdbstub_write_dword(ch.val, mem) != 0)
+			return 0;
+		mem += 4;
+		count -= 4;
+	}
+
+	if (count >= 2) {
+		ch.b[0]  = hex(*buf++) << 4;
+		ch.b[0] |= hex(*buf++);
+		ch.b[1]  = hex(*buf++) << 4;
+		ch.b[1] |= hex(*buf++);
+		if (gdbstub_write_word(ch.val, mem) != 0)
+			return 0;
+		mem += 2;
+		count -= 2;
+	}
+
+	if (count >= 1) {
+		ch.b[0]  = hex(*buf++) << 4;
+		ch.b[0] |= hex(*buf++);
+		if (gdbstub_write_byte(ch.val, mem) != 0)
+			return 0;
+	}
+
+	return buf;
+}
+
+/*
+ * This table contains the mapping between MN10300 exception codes, and
+ * signals, which are primarily what GDB understands.  It also indicates
+ * which hardware traps we need to commandeer when initializing the stub.
+ */
+static const struct excep_to_sig_map {
+	enum exception_code	excep;	/* MN10300 exception code */
+	unsigned char		signo;	/* Signal that we map this into */
+} excep_to_sig_map[] = {
+	{ EXCEP_ITLBMISS,	SIGSEGV		},
+	{ EXCEP_DTLBMISS,	SIGSEGV		},
+	{ EXCEP_TRAP,		SIGTRAP		},
+	{ EXCEP_ISTEP,		SIGTRAP		},
+	{ EXCEP_IBREAK,		SIGTRAP		},
+	{ EXCEP_OBREAK,		SIGTRAP		},
+	{ EXCEP_UNIMPINS,	SIGILL		},
+	{ EXCEP_UNIMPEXINS,	SIGILL		},
+	{ EXCEP_MEMERR,		SIGSEGV		},
+	{ EXCEP_MISALIGN,	SIGSEGV		},
+	{ EXCEP_BUSERROR,	SIGBUS		},
+	{ EXCEP_ILLINSACC,	SIGSEGV		},
+	{ EXCEP_ILLDATACC,	SIGSEGV		},
+	{ EXCEP_IOINSACC,	SIGSEGV		},
+	{ EXCEP_PRIVINSACC,	SIGSEGV		},
+	{ EXCEP_PRIVDATACC,	SIGSEGV		},
+	{ EXCEP_FPU_DISABLED,	SIGFPE		},
+	{ EXCEP_FPU_UNIMPINS,	SIGFPE		},
+	{ EXCEP_FPU_OPERATION,	SIGFPE		},
+	{ EXCEP_WDT,		SIGALRM		},
+	{ EXCEP_NMI,		SIGQUIT		},
+	{ EXCEP_IRQ_LEVEL0,	SIGINT		},
+	{ EXCEP_IRQ_LEVEL1,	SIGINT		},
+	{ EXCEP_IRQ_LEVEL2,	SIGINT		},
+	{ EXCEP_IRQ_LEVEL3,	SIGINT		},
+	{ EXCEP_IRQ_LEVEL4,	SIGINT		},
+	{ EXCEP_IRQ_LEVEL5,	SIGINT		},
+	{ EXCEP_IRQ_LEVEL6,	SIGINT		},
+	{ 0, 0}
+};
+
+/*
+ * convert the MN10300 exception code into a UNIX signal number
+ */
+static int computeSignal(enum exception_code excep)
+{
+	const struct excep_to_sig_map *map;
+
+	for (map = excep_to_sig_map; map->signo; map++)
+		if (map->excep == excep)
+			return map->signo;
+
+	return SIGHUP; /* default for things we don't know about */
+}
+
+static u32 gdbstub_fpcr, gdbstub_fpufs_array[32];
+
+/*
+ *
+ */
+static void gdbstub_store_fpu(void)
+{
+#ifdef CONFIG_FPU
+
+	asm volatile(
+		"or %2,epsw\n"
+#ifdef CONFIG_MN10300_PROC_MN103E010
+		"nop\n"
+		"nop\n"
+#endif
+		"mov %1, a1\n"
+		"fmov fs0,  (a1+)\n"
+		"fmov fs1,  (a1+)\n"
+		"fmov fs2,  (a1+)\n"
+		"fmov fs3,  (a1+)\n"
+		"fmov fs4,  (a1+)\n"
+		"fmov fs5,  (a1+)\n"
+		"fmov fs6,  (a1+)\n"
+		"fmov fs7,  (a1+)\n"
+		"fmov fs8,  (a1+)\n"
+		"fmov fs9,  (a1+)\n"
+		"fmov fs10, (a1+)\n"
+		"fmov fs11, (a1+)\n"
+		"fmov fs12, (a1+)\n"
+		"fmov fs13, (a1+)\n"
+		"fmov fs14, (a1+)\n"
+		"fmov fs15, (a1+)\n"
+		"fmov fs16, (a1+)\n"
+		"fmov fs17, (a1+)\n"
+		"fmov fs18, (a1+)\n"
+		"fmov fs19, (a1+)\n"
+		"fmov fs20, (a1+)\n"
+		"fmov fs21, (a1+)\n"
+		"fmov fs22, (a1+)\n"
+		"fmov fs23, (a1+)\n"
+		"fmov fs24, (a1+)\n"
+		"fmov fs25, (a1+)\n"
+		"fmov fs26, (a1+)\n"
+		"fmov fs27, (a1+)\n"
+		"fmov fs28, (a1+)\n"
+		"fmov fs29, (a1+)\n"
+		"fmov fs30, (a1+)\n"
+		"fmov fs31, (a1+)\n"
+		"fmov fpcr, %0\n"
+		: "=d"(gdbstub_fpcr)
+		: "g" (&gdbstub_fpufs_array), "i"(EPSW_FE)
+		: "a1"
+		);
+#endif
+}
+
+/*
+ *
+ */
+static void gdbstub_load_fpu(void)
+{
+#ifdef CONFIG_FPU
+
+	asm volatile(
+		"or %1,epsw\n"
+#ifdef CONFIG_MN10300_PROC_MN103E010
+		"nop\n"
+		"nop\n"
+#endif
+		"mov %0, a1\n"
+		"fmov (a1+), fs0\n"
+		"fmov (a1+), fs1\n"
+		"fmov (a1+), fs2\n"
+		"fmov (a1+), fs3\n"
+		"fmov (a1+), fs4\n"
+		"fmov (a1+), fs5\n"
+		"fmov (a1+), fs6\n"
+		"fmov (a1+), fs7\n"
+		"fmov (a1+), fs8\n"
+		"fmov (a1+), fs9\n"
+		"fmov (a1+), fs10\n"
+		"fmov (a1+), fs11\n"
+		"fmov (a1+), fs12\n"
+		"fmov (a1+), fs13\n"
+		"fmov (a1+), fs14\n"
+		"fmov (a1+), fs15\n"
+		"fmov (a1+), fs16\n"
+		"fmov (a1+), fs17\n"
+		"fmov (a1+), fs18\n"
+		"fmov (a1+), fs19\n"
+		"fmov (a1+), fs20\n"
+		"fmov (a1+), fs21\n"
+		"fmov (a1+), fs22\n"
+		"fmov (a1+), fs23\n"
+		"fmov (a1+), fs24\n"
+		"fmov (a1+), fs25\n"
+		"fmov (a1+), fs26\n"
+		"fmov (a1+), fs27\n"
+		"fmov (a1+), fs28\n"
+		"fmov (a1+), fs29\n"
+		"fmov (a1+), fs30\n"
+		"fmov (a1+), fs31\n"
+		"fmov %2, fpcr\n"
+		:
+		: "g" (&gdbstub_fpufs_array), "i"(EPSW_FE), "d"(gdbstub_fpcr)
+		: "a1"
+	);
+#endif
+}
+
+/*
+ * set a software breakpoint
+ */
+int gdbstub_set_breakpoint(u8 *addr, int len)
+{
+	int bkpt, loop, xloop;
+
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+	len = (len + 1) & ~1;
+#endif
+
+	gdbstub_bkpt("setbkpt(%p,%d)\n", addr, len);
+
+	for (bkpt = 255; bkpt >= 0; bkpt--)
+		if (!gdbstub_bkpts[bkpt].addr)
+			break;
+	if (bkpt < 0)
+		return -ENOSPC;
+
+	for (loop = 0; loop < len; loop++)
+		if (gdbstub_read_byte(&addr[loop],
+				      &gdbstub_bkpts[bkpt].origbytes[loop]
+				      ) < 0)
+			return -EFAULT;
+
+	gdbstub_flush_caches = 1;
+
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+	for (loop = 0; loop < len; loop++)
+		if (gdbstub_write_byte(0xF7, &addr[loop]) < 0)
+			goto restore;
+#else
+	for (loop = 0; loop < len; loop++)
+		if (gdbstub_write_byte(0xFF, &addr[loop]) < 0)
+			goto restore;
+#endif
+
+	gdbstub_bkpts[bkpt].addr = addr;
+	gdbstub_bkpts[bkpt].len = len;
+
+	gdbstub_bkpt("Set BKPT[%02x]: %p-%p {%02x%02x%02x%02x%02x%02x%02x}\n",
+		     bkpt,
+		     gdbstub_bkpts[bkpt].addr,
+		     gdbstub_bkpts[bkpt].addr + gdbstub_bkpts[bkpt].len - 1,
+		     gdbstub_bkpts[bkpt].origbytes[0],
+		     gdbstub_bkpts[bkpt].origbytes[1],
+		     gdbstub_bkpts[bkpt].origbytes[2],
+		     gdbstub_bkpts[bkpt].origbytes[3],
+		     gdbstub_bkpts[bkpt].origbytes[4],
+		     gdbstub_bkpts[bkpt].origbytes[5],
+		     gdbstub_bkpts[bkpt].origbytes[6]
+		     );
+
+	return 0;
+
+restore:
+	for (xloop = 0; xloop < loop; xloop++)
+		gdbstub_write_byte(gdbstub_bkpts[bkpt].origbytes[xloop],
+				   addr + xloop);
+	return -EFAULT;
+}
+
+/*
+ * clear a software breakpoint
+ */
+int gdbstub_clear_breakpoint(u8 *addr, int len)
+{
+	int bkpt, loop;
+
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+	len = (len + 1) & ~1;
+#endif
+
+	gdbstub_bkpt("clearbkpt(%p,%d)\n", addr, len);
+
+	for (bkpt = 255; bkpt >= 0; bkpt--)
+		if (gdbstub_bkpts[bkpt].addr == addr &&
+		    gdbstub_bkpts[bkpt].len == len)
+			break;
+	if (bkpt < 0)
+		return -ENOENT;
+
+	gdbstub_bkpts[bkpt].addr = NULL;
+
+	gdbstub_flush_caches = 1;
+
+	for (loop = 0; loop < len; loop++)
+		if (gdbstub_write_byte(gdbstub_bkpts[bkpt].origbytes[loop],
+				       addr + loop) < 0)
+			return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * This function does all command processing for interfacing to gdb
+ * - returns 0 if the exception should be skipped, -ERROR otherwise.
+ */
+static int gdbstub(struct pt_regs *regs, enum exception_code excep)
+{
+	unsigned long *stack;
+	unsigned long epsw, mdr;
+	uint32_t zero, ssp;
+	uint8_t broke;
+	char *ptr;
+	int sigval;
+	int addr;
+	int length;
+	int loop;
+
+	if (excep == EXCEP_FPU_DISABLED)
+		return -ENOTSUPP;
+
+	gdbstub_flush_caches = 0;
+
+	mn10300_set_gdbleds(1);
+
+	asm volatile("mov mdr,%0" : "=d"(mdr));
+	local_save_flags(epsw);
+	arch_local_change_intr_mask_level(
+		NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1));
+
+	gdbstub_store_fpu();
+
+#ifdef CONFIG_GDBSTUB_IMMEDIATE
+	/* skip the initial pause loop */
+	if (regs->pc == (unsigned long) __gdbstub_pause)
+		regs->pc = (unsigned long) start_kernel;
+#endif
+
+	/* if we were single stepping, restore the opcodes hoisted for the
+	 * breakpoint[s] */
+	broke = 0;
+#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
+	if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) ||
+	    (step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc))
+		broke = 1;
+
+	__gdbstub_restore_bp();
+#endif
+
+	if (gdbstub_rx_unget) {
+		sigval = SIGINT;
+		if (gdbstub_rx_unget != 3)
+			goto packet_waiting;
+		gdbstub_rx_unget = 0;
+	}
+
+	stack = (unsigned long *) regs->sp;
+	sigval = broke ? SIGTRAP : computeSignal(excep);
+
+	/* send information about a BUG() */
+	if (!user_mode(regs) && excep == EXCEP_SYSCALL15) {
+		const struct bug_entry *bug;
+
+		bug = find_bug(regs->pc);
+		if (bug)
+			goto found_bug;
+		length = snprintf(trans_buffer, sizeof(trans_buffer),
+				  "BUG() at address %lx\n", regs->pc);
+		goto send_bug_pkt;
+
+	found_bug:
+		length = snprintf(trans_buffer, sizeof(trans_buffer),
+				  "BUG() at address %lx (%s:%d)\n",
+				  regs->pc, bug->file, bug->line);
+
+	send_bug_pkt:
+		ptr = output_buffer;
+		*ptr++ = 'O';
+		ptr = mem2hex(trans_buffer, ptr, length, 0);
+		*ptr = 0;
+		putpacket(output_buffer);
+
+		regs->pc -= 2;
+		sigval = SIGABRT;
+	} else if (regs->pc == (unsigned long) __gdbstub_bug_trap) {
+		regs->pc = regs->mdr;
+		sigval = SIGABRT;
+	}
+
+	/*
+	 * send a message to the debugger's user saying what happened if it may
+	 * not be clear cut (we can't map exceptions onto signals properly)
+	 */
+	if (sigval != SIGINT && sigval != SIGTRAP && sigval != SIGILL) {
+		static const char title[] = "Excep ", tbcberr[] = "BCBERR ";
+		static const char crlf[] = "\r\n";
+		char hx;
+		u32 bcberr = BCBERR;
+
+		ptr = output_buffer;
+		*ptr++ = 'O';
+		ptr = mem2hex(title, ptr, sizeof(title) - 1, 0);
+
+		hx = hex_asc_hi(excep >> 8);
+		ptr = hex_byte_pack(ptr, hx);
+		hx = hex_asc_lo(excep >> 8);
+		ptr = hex_byte_pack(ptr, hx);
+		hx = hex_asc_hi(excep);
+		ptr = hex_byte_pack(ptr, hx);
+		hx = hex_asc_lo(excep);
+		ptr = hex_byte_pack(ptr, hx);
+
+		ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
+		*ptr = 0;
+		putpacket(output_buffer);	/* send it off... */
+
+		/* BCBERR */
+		ptr = output_buffer;
+		*ptr++ = 'O';
+		ptr = mem2hex(tbcberr, ptr, sizeof(tbcberr) - 1, 0);
+
+		hx = hex_asc_hi(bcberr >> 24);
+		ptr = hex_byte_pack(ptr, hx);
+		hx = hex_asc_lo(bcberr >> 24);
+		ptr = hex_byte_pack(ptr, hx);
+		hx = hex_asc_hi(bcberr >> 16);
+		ptr = hex_byte_pack(ptr, hx);
+		hx = hex_asc_lo(bcberr >> 16);
+		ptr = hex_byte_pack(ptr, hx);
+		hx = hex_asc_hi(bcberr >> 8);
+		ptr = hex_byte_pack(ptr, hx);
+		hx = hex_asc_lo(bcberr >> 8);
+		ptr = hex_byte_pack(ptr, hx);
+		hx = hex_asc_hi(bcberr);
+		ptr = hex_byte_pack(ptr, hx);
+		hx = hex_asc_lo(bcberr);
+		ptr = hex_byte_pack(ptr, hx);
+
+		ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
+		*ptr = 0;
+		putpacket(output_buffer);	/* send it off... */
+	}
+
+	/*
+	 * tell the debugger that an exception has occurred
+	 */
+	ptr = output_buffer;
+
+	/*
+	 * Send trap type (converted to signal)
+	 */
+	*ptr++ = 'T';
+	ptr = hex_byte_pack(ptr, sigval);
+
+	/*
+	 * Send Error PC
+	 */
+	ptr = hex_byte_pack(ptr, GDB_REGID_PC);
+	*ptr++ = ':';
+	ptr = mem2hex(&regs->pc, ptr, 4, 0);
+	*ptr++ = ';';
+
+	/*
+	 * Send frame pointer
+	 */
+	ptr = hex_byte_pack(ptr, GDB_REGID_FP);
+	*ptr++ = ':';
+	ptr = mem2hex(&regs->a3, ptr, 4, 0);
+	*ptr++ = ';';
+
+	/*
+	 * Send stack pointer
+	 */
+	ssp = (unsigned long) (regs + 1);
+	ptr = hex_byte_pack(ptr, GDB_REGID_SP);
+	*ptr++ = ':';
+	ptr = mem2hex(&ssp, ptr, 4, 0);
+	*ptr++ = ';';
+
+	*ptr++ = 0;
+	putpacket(output_buffer);	/* send it off... */
+
+packet_waiting:
+	/*
+	 * Wait for input from remote GDB
+	 */
+	while (1) {
+		output_buffer[0] = 0;
+		getpacket(input_buffer);
+
+		switch (input_buffer[0]) {
+			/* request repeat of last signal number */
+		case '?':
+			output_buffer[0] = 'S';
+			output_buffer[1] = hex_asc_hi(sigval);
+			output_buffer[2] = hex_asc_lo(sigval);
+			output_buffer[3] = 0;
+			break;
+
+		case 'd':
+			/* toggle debug flag */
+			break;
+
+			/*
+			 * Return the value of the CPU registers
+			 */
+		case 'g':
+			zero = 0;
+			ssp = (u32) (regs + 1);
+			ptr = output_buffer;
+			ptr = mem2hex(&regs->d0, ptr, 4, 0);
+			ptr = mem2hex(&regs->d1, ptr, 4, 0);
+			ptr = mem2hex(&regs->d2, ptr, 4, 0);
+			ptr = mem2hex(&regs->d3, ptr, 4, 0);
+			ptr = mem2hex(&regs->a0, ptr, 4, 0);
+			ptr = mem2hex(&regs->a1, ptr, 4, 0);
+			ptr = mem2hex(&regs->a2, ptr, 4, 0);
+			ptr = mem2hex(&regs->a3, ptr, 4, 0);
+
+			ptr = mem2hex(&ssp, ptr, 4, 0);		/* 8 */
+			ptr = mem2hex(&regs->pc, ptr, 4, 0);
+			ptr = mem2hex(&regs->mdr, ptr, 4, 0);
+			ptr = mem2hex(&regs->epsw, ptr, 4, 0);
+			ptr = mem2hex(&regs->lir, ptr, 4, 0);
+			ptr = mem2hex(&regs->lar, ptr, 4, 0);
+			ptr = mem2hex(&regs->mdrq, ptr, 4, 0);
+
+			ptr = mem2hex(&regs->e0, ptr, 4, 0);	/* 15 */
+			ptr = mem2hex(&regs->e1, ptr, 4, 0);
+			ptr = mem2hex(&regs->e2, ptr, 4, 0);
+			ptr = mem2hex(&regs->e3, ptr, 4, 0);
+			ptr = mem2hex(&regs->e4, ptr, 4, 0);
+			ptr = mem2hex(&regs->e5, ptr, 4, 0);
+			ptr = mem2hex(&regs->e6, ptr, 4, 0);
+			ptr = mem2hex(&regs->e7, ptr, 4, 0);
+
+			ptr = mem2hex(&ssp, ptr, 4, 0);
+			ptr = mem2hex(&regs, ptr, 4, 0);
+			ptr = mem2hex(&regs->sp, ptr, 4, 0);
+			ptr = mem2hex(&regs->mcrh, ptr, 4, 0);	/* 26 */
+			ptr = mem2hex(&regs->mcrl, ptr, 4, 0);
+			ptr = mem2hex(&regs->mcvf, ptr, 4, 0);
+
+			ptr = mem2hex(&gdbstub_fpcr, ptr, 4, 0); /* 29 - FPCR */
+			ptr = mem2hex(&zero, ptr, 4, 0);
+			ptr = mem2hex(&zero, ptr, 4, 0);
+			for (loop = 0; loop < 32; loop++)
+				ptr = mem2hex(&gdbstub_fpufs_array[loop],
+					      ptr, 4, 0); /* 32 - FS0-31 */
+
+			break;
+
+			/*
+			 * set the value of the CPU registers - return OK
+			 */
+		case 'G':
+		{
+			const char *ptr;
+
+			ptr = &input_buffer[1];
+			ptr = hex2mem(ptr, &regs->d0, 4, 0);
+			ptr = hex2mem(ptr, &regs->d1, 4, 0);
+			ptr = hex2mem(ptr, &regs->d2, 4, 0);
+			ptr = hex2mem(ptr, &regs->d3, 4, 0);
+			ptr = hex2mem(ptr, &regs->a0, 4, 0);
+			ptr = hex2mem(ptr, &regs->a1, 4, 0);
+			ptr = hex2mem(ptr, &regs->a2, 4, 0);
+			ptr = hex2mem(ptr, &regs->a3, 4, 0);
+
+			ptr = hex2mem(ptr, &ssp, 4, 0);		/* 8 */
+			ptr = hex2mem(ptr, &regs->pc, 4, 0);
+			ptr = hex2mem(ptr, &regs->mdr, 4, 0);
+			ptr = hex2mem(ptr, &regs->epsw, 4, 0);
+			ptr = hex2mem(ptr, &regs->lir, 4, 0);
+			ptr = hex2mem(ptr, &regs->lar, 4, 0);
+			ptr = hex2mem(ptr, &regs->mdrq, 4, 0);
+
+			ptr = hex2mem(ptr, &regs->e0, 4, 0);	/* 15 */
+			ptr = hex2mem(ptr, &regs->e1, 4, 0);
+			ptr = hex2mem(ptr, &regs->e2, 4, 0);
+			ptr = hex2mem(ptr, &regs->e3, 4, 0);
+			ptr = hex2mem(ptr, &regs->e4, 4, 0);
+			ptr = hex2mem(ptr, &regs->e5, 4, 0);
+			ptr = hex2mem(ptr, &regs->e6, 4, 0);
+			ptr = hex2mem(ptr, &regs->e7, 4, 0);
+
+			ptr = hex2mem(ptr, &ssp, 4, 0);
+			ptr = hex2mem(ptr, &zero, 4, 0);
+			ptr = hex2mem(ptr, &regs->sp, 4, 0);
+			ptr = hex2mem(ptr, &regs->mcrh, 4, 0);	/* 26 */
+			ptr = hex2mem(ptr, &regs->mcrl, 4, 0);
+			ptr = hex2mem(ptr, &regs->mcvf, 4, 0);
+
+			ptr = hex2mem(ptr, &zero, 4, 0);	/* 29 - FPCR */
+			ptr = hex2mem(ptr, &zero, 4, 0);
+			ptr = hex2mem(ptr, &zero, 4, 0);
+			for (loop = 0; loop < 32; loop++)     /* 32 - FS0-31 */
+				ptr = hex2mem(ptr, &zero, 4, 0);
+
+#if 0
+			/*
+			 * See if the stack pointer has moved. If so, then copy
+			 * the saved locals and ins to the new location.
+			 */
+			unsigned long *newsp = (unsigned long *) registers[SP];
+			if (sp != newsp)
+				sp = memcpy(newsp, sp, 16 * 4);
+#endif
+
+			gdbstub_strcpy(output_buffer, "OK");
+		}
+		break;
+
+		/*
+		 * mAA..AA,LLLL  Read LLLL bytes at address AA..AA
+		 */
+		case 'm':
+			ptr = &input_buffer[1];
+
+			if (hexToInt(&ptr, &addr) &&
+			    *ptr++ == ',' &&
+			    hexToInt(&ptr, &length)
+			    ) {
+				if (mem2hex((char *) addr, output_buffer,
+					    length, 1))
+					break;
+				gdbstub_strcpy(output_buffer, "E03");
+			} else {
+				gdbstub_strcpy(output_buffer, "E01");
+			}
+			break;
+
+			/*
+			 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA
+			 * return OK
+			 */
+		case 'M':
+			ptr = &input_buffer[1];
+
+			if (hexToInt(&ptr, &addr) &&
+			    *ptr++ == ',' &&
+			    hexToInt(&ptr, &length) &&
+			    *ptr++ == ':'
+			    ) {
+				if (hex2mem(ptr, (char *) addr, length, 1))
+					gdbstub_strcpy(output_buffer, "OK");
+				else
+					gdbstub_strcpy(output_buffer, "E03");
+
+				gdbstub_flush_caches = 1;
+			} else {
+				gdbstub_strcpy(output_buffer, "E02");
+			}
+			break;
+
+			/*
+			 * cAA..AA    Continue at address AA..AA(optional)
+			 */
+		case 'c':
+			/* try to read optional parameter, pc unchanged if no
+			 * parm */
+
+			ptr = &input_buffer[1];
+			if (hexToInt(&ptr, &addr))
+				regs->pc = addr;
+			goto done;
+
+			/*
+			 * kill the program
+			 */
+		case 'k' :
+			goto done;	/* just continue */
+
+			/*
+			 * Reset the whole machine (FIXME: system dependent)
+			 */
+		case 'r':
+			break;
+
+			/*
+			 * Step to next instruction
+			 */
+		case 's':
+			/* Using the T flag doesn't seem to perform single
+			 * stepping (it seems to wind up being caught by the
+			 * JTAG unit), so we have to use breakpoints and
+			 * continue instead.
+			 */
+#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
+			if (gdbstub_single_step(regs) < 0)
+				/* ignore any fault error for now */
+				gdbstub_printk("unable to set single-step"
+					       " bp\n");
+			goto done;
+#else
+			gdbstub_strcpy(output_buffer, "E01");
+			break;
+#endif
+
+			/*
+			 * Set baud rate (bBB)
+			 */
+		case 'b':
+			do {
+				int baudrate;
+
+				ptr = &input_buffer[1];
+				if (!hexToInt(&ptr, &baudrate)) {
+					gdbstub_strcpy(output_buffer, "B01");
+					break;
+				}
+
+				if (baudrate) {
+					/* ACK before changing speed */
+					putpacket("OK");
+					gdbstub_io_set_baud(baudrate);
+				}
+			} while (0);
+			break;
+
+			/*
+			 * Set breakpoint
+			 */
+		case 'Z':
+			ptr = &input_buffer[1];
+
+			if (!hexToInt(&ptr, &loop) || *ptr++ != ',' ||
+			    !hexToInt(&ptr, &addr) || *ptr++ != ',' ||
+			    !hexToInt(&ptr, &length)
+			    ) {
+				gdbstub_strcpy(output_buffer, "E01");
+				break;
+			}
+
+			/* only support software breakpoints */
+			gdbstub_strcpy(output_buffer, "E03");
+			if (loop != 0 ||
+			    length < 1 ||
+			    length > 7 ||
+			    (unsigned long) addr < 4096)
+				break;
+
+			if (gdbstub_set_breakpoint((u8 *) addr, length) < 0)
+				break;
+
+			gdbstub_strcpy(output_buffer, "OK");
+			break;
+
+			/*
+			 * Clear breakpoint
+			 */
+		case 'z':
+			ptr = &input_buffer[1];
+
+			if (!hexToInt(&ptr, &loop) || *ptr++ != ',' ||
+			    !hexToInt(&ptr, &addr) || *ptr++ != ',' ||
+			    !hexToInt(&ptr, &length)
+			    ) {
+				gdbstub_strcpy(output_buffer, "E01");
+				break;
+			}
+
+			/* only support software breakpoints */
+			gdbstub_strcpy(output_buffer, "E03");
+			if (loop != 0 ||
+			    length < 1 ||
+			    length > 7 ||
+			    (unsigned long) addr < 4096)
+				break;
+
+			if (gdbstub_clear_breakpoint((u8 *) addr, length) < 0)
+				break;
+
+			gdbstub_strcpy(output_buffer, "OK");
+			break;
+
+		default:
+			gdbstub_proto("### GDB Unsupported Cmd '%s'\n",
+				      input_buffer);
+			break;
+		}
+
+		/* reply to the request */
+		putpacket(output_buffer);
+	}
+
+done:
+	/*
+	 * Need to flush the instruction cache here, as we may
+	 * have deposited a breakpoint, and the icache probably
+	 * has no way of knowing that a data ref to some location
+	 * may have changed something that is in the instruction
+	 * cache.
+	 * NB: We flush both caches, just to be sure...
+	 */
+	if (gdbstub_flush_caches)
+		debugger_local_cache_flushinv();
+
+	gdbstub_load_fpu();
+	mn10300_set_gdbleds(0);
+	if (excep == EXCEP_NMI)
+		NMICR = NMICR_NMIF;
+
+	touch_softlockup_watchdog();
+
+	local_irq_restore(epsw);
+	return 0;
+}
+
+/*
+ * Determine if we hit a debugger special breakpoint that needs skipping over
+ * automatically.
+ */
+int at_debugger_breakpoint(struct pt_regs *regs)
+{
+	return 0;
+}
+
+/*
+ * handle event interception
+ */
+asmlinkage int debugger_intercept(enum exception_code excep,
+				  int signo, int si_code, struct pt_regs *regs)
+{
+	static u8 notfirst = 1;
+	int ret;
+
+	if (gdbstub_busy)
+		gdbstub_printk("--> gdbstub reentered itself\n");
+	gdbstub_busy = 1;
+
+	if (notfirst) {
+		unsigned long mdr;
+		asm("mov mdr,%0" : "=d"(mdr));
+
+		gdbstub_entry(
+			"--> debugger_intercept(%p,%04x) [MDR=%lx PC=%lx]\n",
+			regs, excep, mdr, regs->pc);
+
+		gdbstub_entry(
+			"PC:  %08lx EPSW:  %08lx  SSP: %08lx mode: %s\n",
+			regs->pc, regs->epsw, (unsigned long) &ret,
+			user_mode(regs) ? "User" : "Super");
+		gdbstub_entry(
+			"d0:  %08lx   d1:  %08lx   d2: %08lx   d3: %08lx\n",
+			regs->d0, regs->d1, regs->d2, regs->d3);
+		gdbstub_entry(
+			"a0:  %08lx   a1:  %08lx   a2: %08lx   a3: %08lx\n",
+			regs->a0, regs->a1, regs->a2, regs->a3);
+		gdbstub_entry(
+			"e0:  %08lx   e1:  %08lx   e2: %08lx   e3: %08lx\n",
+			regs->e0, regs->e1, regs->e2, regs->e3);
+		gdbstub_entry(
+			"e4:  %08lx   e5:  %08lx   e6: %08lx   e7: %08lx\n",
+			regs->e4, regs->e5, regs->e6, regs->e7);
+		gdbstub_entry(
+			"lar: %08lx   lir: %08lx  mdr: %08lx  usp: %08lx\n",
+			regs->lar, regs->lir, regs->mdr, regs->sp);
+		gdbstub_entry(
+			"cvf: %08lx   crl: %08lx  crh: %08lx  drq: %08lx\n",
+			regs->mcvf, regs->mcrl, regs->mcrh, regs->mdrq);
+		gdbstub_entry(
+			"threadinfo=%p task=%p)\n",
+			current_thread_info(), current);
+	} else {
+		notfirst = 1;
+	}
+
+	ret = gdbstub(regs, excep);
+
+	gdbstub_entry("<-- debugger_intercept()\n");
+	gdbstub_busy = 0;
+	return ret;
+}
+
+/*
+ * handle the GDB stub itself causing an exception
+ */
+asmlinkage void gdbstub_exception(struct pt_regs *regs,
+				  enum exception_code excep)
+{
+	unsigned long mdr;
+
+	asm("mov mdr,%0" : "=d"(mdr));
+	gdbstub_entry("--> gdbstub exception({%p},%04x) [MDR=%lx]\n",
+		      regs, excep, mdr);
+
+	while ((unsigned long) regs == 0xffffffff) {}
+
+	/* handle guarded memory accesses where we know it might fault */
+	if (regs->pc == (unsigned) gdbstub_read_byte_guard) {
+		regs->pc = (unsigned) gdbstub_read_byte_cont;
+		goto fault;
+	}
+
+	if (regs->pc == (unsigned) gdbstub_read_word_guard) {
+		regs->pc = (unsigned) gdbstub_read_word_cont;
+		goto fault;
+	}
+
+	if (regs->pc == (unsigned) gdbstub_read_dword_guard) {
+		regs->pc = (unsigned) gdbstub_read_dword_cont;
+		goto fault;
+	}
+
+	if (regs->pc == (unsigned) gdbstub_write_byte_guard) {
+		regs->pc = (unsigned) gdbstub_write_byte_cont;
+		goto fault;
+	}
+
+	if (regs->pc == (unsigned) gdbstub_write_word_guard) {
+		regs->pc = (unsigned) gdbstub_write_word_cont;
+		goto fault;
+	}
+
+	if (regs->pc == (unsigned) gdbstub_write_dword_guard) {
+		regs->pc = (unsigned) gdbstub_write_dword_cont;
+		goto fault;
+	}
+
+	gdbstub_printk("\n### GDB stub caused an exception ###\n");
+
+	/* something went horribly wrong */
+	console_verbose();
+	show_registers(regs);
+
+	panic("GDB Stub caused an unexpected exception - can't continue\n");
+
+	/* we caught an attempt by the stub to access silly memory */
+fault:
+	gdbstub_entry("<-- gdbstub exception() = EFAULT\n");
+	regs->d0 = -EFAULT;
+	return;
+}
+
+/*
+ * send an exit message to GDB
+ */
+void gdbstub_exit(int status)
+{
+	unsigned char checksum;
+	unsigned char ch;
+	int count;
+
+	gdbstub_busy = 1;
+	output_buffer[0] = 'W';
+	output_buffer[1] = hex_asc_hi(status);
+	output_buffer[2] = hex_asc_lo(status);
+	output_buffer[3] = 0;
+
+	gdbstub_io_tx_char('$');
+	checksum = 0;
+	count = 0;
+
+	while ((ch = output_buffer[count]) != 0) {
+		gdbstub_io_tx_char(ch);
+		checksum += ch;
+		count += 1;
+	}
+
+	gdbstub_io_tx_char('#');
+	gdbstub_io_tx_char(hex_asc_hi(checksum));
+	gdbstub_io_tx_char(hex_asc_lo(checksum));
+
+	/* make sure the output is flushed, or else RedBoot might clobber it */
+	gdbstub_io_tx_flush();
+
+	gdbstub_busy = 0;
+}
+
+/*
+ * initialise the GDB stub
+ */
+asmlinkage void __init gdbstub_init(void)
+{
+#ifdef CONFIG_GDBSTUB_IMMEDIATE
+	unsigned char ch;
+	int ret;
+#endif
+
+	gdbstub_busy = 1;
+
+	printk(KERN_INFO "%s", gdbstub_banner);
+
+	gdbstub_io_init();
+
+	gdbstub_entry("--> gdbstub_init\n");
+
+	/* try to talk to GDB (or anyone insane enough to want to type GDB
+	 * protocol by hand) */
+	gdbstub_io("### GDB Tx ACK\n");
+	gdbstub_io_tx_char('+'); /* 'hello world' */
+
+#ifdef CONFIG_GDBSTUB_IMMEDIATE
+	gdbstub_printk("GDB Stub waiting for packet\n");
+
+	/* in case GDB is started before us, ACK any packets that are already
+	 * sitting there (presumably "$?#xx")
+	 */
+	do { gdbstub_io_rx_char(&ch, 0); } while (ch != '$');
+	do { gdbstub_io_rx_char(&ch, 0); } while (ch != '#');
+	/* eat first csum byte */
+	do { ret = gdbstub_io_rx_char(&ch, 0); } while (ret != 0);
+	/* eat second csum byte */
+	do { ret = gdbstub_io_rx_char(&ch, 0); } while (ret != 0);
+
+	gdbstub_io("### GDB Tx NAK\n");
+	gdbstub_io_tx_char('-'); /* NAK it */
+
+#else
+	printk("GDB Stub ready\n");
+#endif
+
+	gdbstub_busy = 0;
+	gdbstub_entry("<-- gdbstub_init\n");
+}
+
+/*
+ * register the console at a more appropriate time
+ */
+#ifdef CONFIG_GDBSTUB_CONSOLE
+static int __init gdbstub_postinit(void)
+{
+	printk(KERN_NOTICE "registering console\n");
+	register_console(&gdbstub_console);
+	return 0;
+}
+
+__initcall(gdbstub_postinit);
+#endif
+
+/*
+ * handle character reception on GDB serial port
+ * - jump into the GDB stub if BREAK is detected on the serial line
+ */
+asmlinkage void gdbstub_rx_irq(struct pt_regs *regs, enum exception_code excep)
+{
+	char ch;
+	int ret;
+
+	gdbstub_entry("--> gdbstub_rx_irq\n");
+
+	do {
+		ret = gdbstub_io_rx_char(&ch, 1);
+		if (ret != -EIO && ret != -EAGAIN) {
+			if (ret != -EINTR)
+				gdbstub_rx_unget = ch;
+			gdbstub(regs, excep);
+		}
+	} while (ret != -EAGAIN);
+
+	gdbstub_entry("<-- gdbstub_rx_irq\n");
+}
diff --git a/arch/mn10300/kernel/head.S b/arch/mn10300/kernel/head.S
new file mode 100644
index 0000000..73e00fc
--- /dev/null
+++ b/arch/mn10300/kernel/head.S
@@ -0,0 +1,450 @@
+/* Boot entry point for MN10300 kernel
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/threads.h>
+#include <linux/linkage.h>
+#include <linux/serial_reg.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/frame.inc>
+#include <asm/param.h>
+#include <unit/serial.h>
+#ifdef CONFIG_SMP
+#include <asm/smp.h>
+#include <asm/intctl-regs.h>
+#include <asm/cpu-regs.h>
+#include <proc/smp-regs.h>
+#endif /* CONFIG_SMP */
+
+	__HEAD
+
+###############################################################################
+#
+# bootloader entry point
+#
+###############################################################################
+	.globl	_start
+	.type	_start,@function
+_start:
+#ifdef CONFIG_SMP
+	#
+	# If this is a secondary CPU (AP), then deal with that elsewhere
+	#
+	mov	(CPUID),d3
+	and	CPUID_MASK,d3
+	bne	startup_secondary
+
+	#
+	# We're dealing with the primary CPU (BP) here, then.
+	# Keep BP's D0,D1,D2 register for boot check.
+	#
+
+	# Set up the Boot IPI for each secondary CPU
+	mov	0x1,a0
+loop_set_secondary_icr:
+	mov	a0,a1
+	asl	CROSS_ICR_CPU_SHIFT,a1
+	add	CROSS_GxICR(SMP_BOOT_IRQ,0),a1
+	movhu	(a1),d3
+	or	GxICR_ENABLE|GxICR_LEVEL_0,d3
+	movhu	d3,(a1)
+	movhu	(a1),d3				# flush
+	inc	a0
+	cmp	NR_CPUS,a0
+	bne	loop_set_secondary_icr
+#endif /* CONFIG_SMP */
+
+	# save commandline pointer
+	mov	d0,a3
+
+	# preload the PGD pointer register
+	mov	swapper_pg_dir,d0
+	mov	d0,(PTBR)
+	clr	d0
+	movbu	d0,(PIDR)
+
+	# turn on the TLBs
+	mov	MMUCTR_IIV|MMUCTR_DIV,d0
+	mov	d0,(MMUCTR)
+#ifdef CONFIG_AM34_2
+	mov	MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0
+#else
+	mov	MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0
+#endif
+	mov	d0,(MMUCTR)
+
+	# turn on AM33v2 exception handling mode and set the trap table base
+	movhu	(CPUP),d0
+	or	CPUP_EXM_AM33V2,d0
+	movhu	d0,(CPUP)
+	mov	CONFIG_INTERRUPT_VECTOR_BASE,d0
+	mov	d0,(TBR)
+
+	# invalidate and enable both of the caches
+#ifdef CONFIG_SMP
+	mov	ECHCTR,a0
+	clr	d0
+	mov	d0,(a0)
+#endif
+	mov	CHCTR,a0
+	clr	d0
+	movhu	d0,(a0)					# turn off first
+	mov	CHCTR_ICINV|CHCTR_DCINV,d0
+	movhu	d0,(a0)
+	setlb
+	mov	(a0),d0
+	btst	CHCTR_ICBUSY|CHCTR_DCBUSY,d0		# wait till not busy
+	lne
+
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+#ifdef CONFIG_MN10300_CACHE_WBACK
+#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC
+	mov	CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
+#else
+	mov	CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0
+#endif /* NOWRALLOC */
+#else
+	mov	CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
+#endif /* WBACK */
+	movhu	d0,(a0)					# enable
+#endif /* ENABLED */
+
+	# turn on RTS on the debug serial port if applicable
+#ifdef CONFIG_MN10300_UNIT_ASB2305
+	bset	UART_MCR_RTS,(ASB2305_DEBUG_MCR)
+#endif
+
+	# clear the BSS area
+	mov	__bss_start,a0
+	mov	__bss_stop,a1
+	clr	d0
+bssclear:
+	cmp	a1,a0
+	bge	bssclear_end
+	mov	d0,(a0)
+	inc4	a0
+	bra	bssclear
+bssclear_end:
+
+	# retrieve the parameters (including command line) before we overwrite
+	# them
+	cmp	0xabadcafe,d1
+	bne	__no_parameters
+
+__copy_parameters:
+	mov	redboot_command_line,a0
+	mov	a0,a1
+	add	COMMAND_LINE_SIZE,a1
+1:
+	movbu	(a3),d0
+	inc	a3
+	movbu	d0,(a0)
+	inc	a0
+	cmp	a1,a0
+	blt	1b
+
+	mov	redboot_platform_name,a0
+	mov	a0,a1
+	add	COMMAND_LINE_SIZE,a1
+	mov	d2,a3
+1:
+	movbu	(a3),d0
+	inc	a3
+	movbu	d0,(a0)
+	inc	a0
+	cmp	a1,a0
+	blt	1b
+
+__no_parameters:
+
+	# set up the registers with recognisable rubbish in them
+	mov	init_thread_union+THREAD_SIZE-12,sp
+
+	mov	0xea01eaea,d0
+	mov	d0,(4,sp)		# EPSW save area
+	mov	0xea02eaea,d0
+	mov	d0,(8,sp)		# PC save area
+
+	mov	0xeb0060ed,d0
+	mov	d0,mdr
+	mov	0xeb0061ed,d0
+	mov	d0,mdrq
+	mov	0xeb0062ed,d0
+	mov	d0,mcrh
+	mov	0xeb0063ed,d0
+	mov	d0,mcrl
+	mov	0xeb0064ed,d0
+	mov	d0,mcvf
+	mov	0xed0065ed,a3
+	mov	a3,usp
+
+	mov	0xed00e0ed,e0
+	mov	0xed00e1ed,e1
+	mov	0xed00e2ed,e2
+	mov	0xed00e3ed,e3
+	mov	0xed00e4ed,e4
+	mov	0xed00e5ed,e5
+	mov	0xed00e6ed,e6
+	mov	0xed00e7ed,e7
+
+	mov	0xed00d0ed,d0
+	mov	0xed00d1ed,d1
+	mov	0xed00d2ed,d2
+	mov	0xed00d3ed,d3
+	mov	0xed00a0ed,a0
+	mov	0xed00a1ed,a1
+	mov	0xed00a2ed,a2
+	mov	0,a3
+
+	# set up the initial kernel stack
+	SAVE_ALL
+	mov	0xffffffff,d0
+	mov	d0,(REG_ORIG_D0,fp)
+
+	# put different recognisable rubbish in the regs
+	mov	0xfb0060ed,d0
+	mov	d0,mdr
+	mov	0xfb0061ed,d0
+	mov	d0,mdrq
+	mov	0xfb0062ed,d0
+	mov	d0,mcrh
+	mov	0xfb0063ed,d0
+	mov	d0,mcrl
+	mov	0xfb0064ed,d0
+	mov	d0,mcvf
+	mov	0xfd0065ed,a0
+	mov	a0,usp
+
+	mov	0xfd00e0ed,e0
+	mov	0xfd00e1ed,e1
+	mov	0xfd00e2ed,e2
+	mov	0xfd00e3ed,e3
+	mov	0xfd00e4ed,e4
+	mov	0xfd00e5ed,e5
+	mov	0xfd00e6ed,e6
+	mov	0xfd00e7ed,e7
+
+	mov	0xfd00d0ed,d0
+	mov	0xfd00d1ed,d1
+	mov	0xfd00d2ed,d2
+	mov	0xfd00d3ed,d3
+	mov	0xfd00a0ed,a0
+	mov	0xfd00a1ed,a1
+	mov	0xfd00a2ed,a2
+
+	# we may be holding current in E2
+#ifdef CONFIG_MN10300_CURRENT_IN_E2
+	mov	init_task,e2
+#endif
+
+	# initialise the processor and the unit
+	call	processor_init[],0
+	call	unit_init[],0
+
+#ifdef CONFIG_SMP
+	# mark the primary CPU in cpu_boot_map
+	mov	cpu_boot_map,a0
+	mov	0x1,d0
+	mov	d0,(a0)
+
+	# signal each secondary CPU to begin booting
+	mov	0x1,d2				# CPU ID
+
+loop_request_boot_secondary:
+	mov	d2,a0
+	# send SMP_BOOT_IPI to secondary CPU
+	asl	CROSS_ICR_CPU_SHIFT,a0
+	add	CROSS_GxICR(SMP_BOOT_IRQ,0),a0
+	movhu	(a0),d0
+	or	GxICR_REQUEST|GxICR_DETECT,d0
+	movhu	d0,(a0)
+	movhu	(a0),d0				# flush
+
+	# wait up to 100ms for AP's IPI to be received
+	clr	d3
+wait_on_secondary_boot:
+	mov	DELAY_TIME_BOOT_IPI,d0
+	call	__delay[],0
+	inc	d3
+	mov	cpu_boot_map,a0
+	mov	(a0),d0
+	lsr	d2,d0
+	btst	0x1,d0
+	bne	1f
+	cmp	TIME_OUT_COUNT_BOOT_IPI,d3
+	bne	wait_on_secondary_boot
+1:
+	inc	d2
+	cmp	NR_CPUS,d2
+	bne	loop_request_boot_secondary
+#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_GDBSTUB
+	call	gdbstub_init[],0
+
+#ifdef CONFIG_GDBSTUB_IMMEDIATE
+	.globl	__gdbstub_pause
+__gdbstub_pause:
+	bra	__gdbstub_pause
+#endif
+#endif
+
+	jmp	start_kernel
+	.size	_start,.-_start
+
+###############################################################################
+#
+# Secondary CPU boot point
+#
+###############################################################################
+#ifdef CONFIG_SMP
+startup_secondary:
+	# preload the PGD pointer register
+	mov	swapper_pg_dir,d0
+	mov	d0,(PTBR)
+	clr	d0
+	movbu	d0,(PIDR)
+
+	# turn on the TLBs
+	mov	MMUCTR_IIV|MMUCTR_DIV,d0
+	mov	d0,(MMUCTR)
+#ifdef CONFIG_AM34_2
+	mov	MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0
+#else
+	mov	MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0
+#endif
+	mov	d0,(MMUCTR)
+
+	# turn on AM33v2 exception handling mode and set the trap table base
+	movhu	(CPUP),d0
+	or	CPUP_EXM_AM33V2,d0
+	movhu	d0,(CPUP)
+
+	# set the interrupt vector table
+	mov	CONFIG_INTERRUPT_VECTOR_BASE,d0
+	mov	d0,(TBR)
+
+	# invalidate and enable both of the caches
+	mov	ECHCTR,a0
+	clr	d0
+	mov	d0,(a0)
+	mov	CHCTR,a0
+	clr	d0
+	movhu	d0,(a0)					# turn off first
+	mov	CHCTR_ICINV|CHCTR_DCINV,d0
+	movhu	d0,(a0)
+	setlb
+	mov	(a0),d0
+	btst	CHCTR_ICBUSY|CHCTR_DCBUSY,d0		# wait till not busy (use CPU loop buffer)
+	lne
+
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+#ifdef  CONFIG_MN10300_CACHE_WBACK
+#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC
+	mov	CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
+#else
+	mov	CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0
+#endif  /* !NOWRALLOC */
+#else
+	mov	CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
+#endif  /* WBACK */
+	movhu	d0,(a0)					# enable
+#endif  /* ENABLED */
+
+	# Clear the boot IPI interrupt for this CPU
+	movhu	(GxICR(SMP_BOOT_IRQ)),d0
+	and	~GxICR_REQUEST,d0
+	movhu	d0,(GxICR(SMP_BOOT_IRQ))
+	movhu	(GxICR(SMP_BOOT_IRQ)),d0		# flush
+
+	/* get stack */
+	mov	CONFIG_INTERRUPT_VECTOR_BASE + CONFIG_BOOT_STACK_OFFSET,a0
+	mov	(CPUID),d0
+	and	CPUID_MASK,d0
+	mulu	CONFIG_BOOT_STACK_SIZE,d0
+	sub	d0,a0
+	mov	a0,sp
+
+	# init interrupt for AP
+	call	smp_prepare_cpu_init[],0
+
+	# mark this secondary CPU in cpu_boot_map
+	mov	(CPUID),d0
+	mov	0x1,d1
+	asl	d0,d1
+	mov	cpu_boot_map,a0
+	bset	d1,(a0)
+
+	or	EPSW_IE|EPSW_IM_1,epsw  # permit level 0 interrupts
+	nop
+	nop
+#ifdef  CONFIG_MN10300_CACHE_WBACK
+	# flush the local cache if it's in writeback mode
+	call	mn10300_local_dcache_flush_inv[],0
+	setlb
+	mov	(CHCTR),d0
+	btst	CHCTR_DCBUSY,d0		# wait till not busy (use CPU loop buffer)
+	lne
+#endif
+
+	# now sleep waiting for further instructions
+secondary_sleep:
+	mov	CPUM_SLEEP,d0
+	movhu	d0,(CPUM)
+	nop
+	nop
+	bra	secondary_sleep
+	.size	startup_secondary,.-startup_secondary
+#endif /* CONFIG_SMP */
+
+###############################################################################
+#
+#
+#
+###############################################################################
+ENTRY(__head_end)
+
+/*
+ * This is initialized to disallow all access to the low 2G region
+ * - the high 2G region is managed directly by the MMU
+ * - range 0x70000000-0x7C000000 are initialised for use by VMALLOC
+ */
+	.section .bss
+	.balign PAGE_SIZE
+ENTRY(swapper_pg_dir)
+        .space PTRS_PER_PGD*4
+
+/*
+ * The page tables are initialized to only 8MB here - the final page
+ * tables are set up later depending on memory size.
+ */
+
+	.balign PAGE_SIZE
+ENTRY(empty_zero_page)
+	.space PAGE_SIZE
+
+	.balign PAGE_SIZE
+ENTRY(empty_bad_page)
+	.space PAGE_SIZE
+
+	.balign PAGE_SIZE
+ENTRY(empty_bad_pte_table)
+	.space PAGE_SIZE
+
+	.balign PAGE_SIZE
+ENTRY(large_page_table)
+	.space PAGE_SIZE
+
+	.balign PAGE_SIZE
+ENTRY(kernel_vmalloc_ptes)
+	.space ((VMALLOC_END-VMALLOC_START)/PAGE_SIZE)*4
diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h
new file mode 100644
index 0000000..5617855
--- /dev/null
+++ b/arch/mn10300/kernel/internal.h
@@ -0,0 +1,40 @@
+/* Internal definitions for the arch part of the core kernel
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/irqreturn.h>
+
+struct clocksource;
+struct clock_event_device;
+
+/*
+ * entry.S
+ */
+extern void ret_from_fork(struct task_struct *) __attribute__((noreturn));
+extern void ret_from_kernel_thread(struct task_struct *) __attribute__((noreturn));
+
+/*
+ * smp-low.S
+ */
+#ifdef CONFIG_SMP
+extern void mn10300_low_ipi_handler(void);
+#endif
+
+/*
+ * smp.c
+ */
+#ifdef CONFIG_SMP
+extern void smp_jump_to_debugger(void);
+#endif
+
+/*
+ * time.c
+ */
+extern irqreturn_t local_timer_interrupt(void);
diff --git a/arch/mn10300/kernel/io.c b/arch/mn10300/kernel/io.c
new file mode 100644
index 0000000..e96fdf6
--- /dev/null
+++ b/arch/mn10300/kernel/io.c
@@ -0,0 +1,30 @@
+/* MN10300 Misaligned multibyte-word I/O
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+
+/*
+ * output data from a potentially misaligned buffer
+ */
+void __outsl(unsigned long addr, const void *buffer, int count)
+{
+	const unsigned char *buf = buffer;
+	unsigned long val;
+
+	while (count--) {
+		memcpy(&val, buf, 4);
+		outl(val, addr);
+		buf += 4;
+	}
+}
+EXPORT_SYMBOL(__outsl);
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
new file mode 100644
index 0000000..c716437
--- /dev/null
+++ b/arch/mn10300/kernel/irq.c
@@ -0,0 +1,356 @@
+/* MN10300 Arch-specific interrupt handling
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
+#include <linux/cpumask.h>
+#include <asm/setup.h>
+#include <asm/serial-regs.h>
+
+unsigned long __mn10300_irq_enabled_epsw[NR_CPUS] __cacheline_aligned_in_smp = {
+	[0 ... NR_CPUS - 1] = EPSW_IE | EPSW_IM_7
+};
+EXPORT_SYMBOL(__mn10300_irq_enabled_epsw);
+
+#ifdef CONFIG_SMP
+static char irq_affinity_online[NR_IRQS] = {
+	[0 ... NR_IRQS - 1] = 0
+};
+
+#define NR_IRQ_WORDS	((NR_IRQS + 31) / 32)
+static unsigned long irq_affinity_request[NR_IRQ_WORDS] = {
+	[0 ... NR_IRQ_WORDS - 1] = 0
+};
+#endif  /* CONFIG_SMP */
+
+atomic_t irq_err_count;
+
+/*
+ * MN10300 interrupt controller operations
+ */
+static void mn10300_cpupic_ack(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+	unsigned long flags;
+	u16 tmp;
+
+	flags = arch_local_cli_save();
+	GxICR_u8(irq) = GxICR_DETECT;
+	tmp = GxICR(irq);
+	arch_local_irq_restore(flags);
+}
+
+static void __mask_and_set_icr(unsigned int irq,
+			       unsigned int mask, unsigned int set)
+{
+	unsigned long flags;
+	u16 tmp;
+
+	flags = arch_local_cli_save();
+	tmp = GxICR(irq);
+	GxICR(irq) = (tmp & mask) | set;
+	tmp = GxICR(irq);
+	arch_local_irq_restore(flags);
+}
+
+static void mn10300_cpupic_mask(struct irq_data *d)
+{
+	__mask_and_set_icr(d->irq, GxICR_LEVEL, 0);
+}
+
+static void mn10300_cpupic_mask_ack(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+#ifdef CONFIG_SMP
+	unsigned long flags;
+	u16 tmp;
+
+	flags = arch_local_cli_save();
+
+	if (!test_and_clear_bit(irq, irq_affinity_request)) {
+		tmp = GxICR(irq);
+		GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
+		tmp = GxICR(irq);
+	} else {
+		u16 tmp2;
+		tmp = GxICR(irq);
+		GxICR(irq) = (tmp & GxICR_LEVEL);
+		tmp2 = GxICR(irq);
+
+		irq_affinity_online[irq] =
+			cpumask_any_and(irq_data_get_affinity_mask(d),
+					cpu_online_mask);
+		CROSS_GxICR(irq, irq_affinity_online[irq]) =
+			(tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT;
+		tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
+	}
+
+	arch_local_irq_restore(flags);
+#else  /* CONFIG_SMP */
+	__mask_and_set_icr(irq, GxICR_LEVEL, GxICR_DETECT);
+#endif /* CONFIG_SMP */
+}
+
+static void mn10300_cpupic_unmask(struct irq_data *d)
+{
+	__mask_and_set_icr(d->irq, GxICR_LEVEL, GxICR_ENABLE);
+}
+
+static void mn10300_cpupic_unmask_clear(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+	/* the MN10300 PIC latches its interrupt request bit, even after the
+	 * device has ceased to assert its interrupt line and the interrupt
+	 * channel has been disabled in the PIC, so for level-triggered
+	 * interrupts we need to clear the request bit when we re-enable */
+#ifdef CONFIG_SMP
+	unsigned long flags;
+	u16 tmp;
+
+	flags = arch_local_cli_save();
+
+	if (!test_and_clear_bit(irq, irq_affinity_request)) {
+		tmp = GxICR(irq);
+		GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
+		tmp = GxICR(irq);
+	} else {
+		tmp = GxICR(irq);
+
+		irq_affinity_online[irq] = cpumask_any_and(irq_data_get_affinity_mask(d),
+							   cpu_online_mask);
+		CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
+		tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
+	}
+
+	arch_local_irq_restore(flags);
+#else  /* CONFIG_SMP */
+	__mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE | GxICR_DETECT);
+#endif /* CONFIG_SMP */
+}
+
+#ifdef CONFIG_SMP
+static int
+mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask,
+			   bool force)
+{
+	unsigned long flags;
+
+	flags = arch_local_cli_save();
+	set_bit(d->irq, irq_affinity_request);
+	arch_local_irq_restore(flags);
+	return 0;
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * MN10300 PIC level-triggered IRQ handling.
+ *
+ * The PIC has no 'ACK' function per se.  It is possible to clear individual
+ * channel latches, but each latch relatches whether or not the channel is
+ * masked, so we need to clear the latch when we unmask the channel.
+ *
+ * Also for this reason, we don't supply an ack() op (it's unused anyway if
+ * mask_ack() is provided), and mask_ack() just masks.
+ */
+static struct irq_chip mn10300_cpu_pic_level = {
+	.name			= "cpu_l",
+	.irq_disable		= mn10300_cpupic_mask,
+	.irq_enable		= mn10300_cpupic_unmask_clear,
+	.irq_ack		= NULL,
+	.irq_mask		= mn10300_cpupic_mask,
+	.irq_mask_ack		= mn10300_cpupic_mask,
+	.irq_unmask		= mn10300_cpupic_unmask_clear,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	= mn10300_cpupic_setaffinity,
+#endif
+};
+
+/*
+ * MN10300 PIC edge-triggered IRQ handling.
+ *
+ * We use the latch clearing function of the PIC as the 'ACK' function.
+ */
+static struct irq_chip mn10300_cpu_pic_edge = {
+	.name			= "cpu_e",
+	.irq_disable		= mn10300_cpupic_mask,
+	.irq_enable		= mn10300_cpupic_unmask,
+	.irq_ack		= mn10300_cpupic_ack,
+	.irq_mask		= mn10300_cpupic_mask,
+	.irq_mask_ack		= mn10300_cpupic_mask_ack,
+	.irq_unmask		= mn10300_cpupic_unmask,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	= mn10300_cpupic_setaffinity,
+#endif
+};
+
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(int irq)
+{
+	printk(KERN_WARNING "unexpected IRQ trap at vector %02x\n", irq);
+}
+
+/*
+ * change the level at which an IRQ executes
+ * - must not be called whilst interrupts are being processed!
+ */
+void set_intr_level(int irq, u16 level)
+{
+	BUG_ON(in_interrupt());
+
+	__mask_and_set_icr(irq, GxICR_ENABLE, level);
+}
+
+/*
+ * mark an interrupt to be ACK'd after interrupt handlers have been run rather
+ * than before
+ */
+void mn10300_set_lateack_irq_type(int irq)
+{
+	irq_set_chip_and_handler(irq, &mn10300_cpu_pic_level,
+				 handle_level_irq);
+}
+
+/*
+ * initialise the interrupt system
+ */
+void __init init_IRQ(void)
+{
+	int irq;
+
+	for (irq = 0; irq < NR_IRQS; irq++)
+		if (irq_get_chip(irq) == &no_irq_chip)
+			/* due to the PIC latching interrupt requests, even
+			 * when the IRQ is disabled, IRQ_PENDING is superfluous
+			 * and we can use handle_level_irq() for edge-triggered
+			 * interrupts */
+			irq_set_chip_and_handler(irq, &mn10300_cpu_pic_edge,
+						 handle_level_irq);
+
+	unit_init_IRQ();
+}
+
+/*
+ * handle normal device IRQs
+ */
+asmlinkage void do_IRQ(void)
+{
+	unsigned long sp, epsw, irq_disabled_epsw, old_irq_enabled_epsw;
+	unsigned int cpu_id = smp_processor_id();
+	int irq;
+
+	sp = current_stack_pointer();
+	BUG_ON(sp - (sp & ~(THREAD_SIZE - 1)) < STACK_WARN);
+
+	/* make sure local_irq_enable() doesn't muck up the interrupt priority
+	 * setting in EPSW */
+	old_irq_enabled_epsw = __mn10300_irq_enabled_epsw[cpu_id];
+	local_save_flags(epsw);
+	__mn10300_irq_enabled_epsw[cpu_id] = EPSW_IE | (EPSW_IM & epsw);
+	irq_disabled_epsw = EPSW_IE | MN10300_CLI_LEVEL;
+
+#ifdef CONFIG_MN10300_WD_TIMER
+	__IRQ_STAT(cpu_id, __irq_count)++;
+#endif
+
+	irq_enter();
+
+	for (;;) {
+		/* ask the interrupt controller for the next IRQ to process
+		 * - the result we get depends on EPSW.IM
+		 */
+		irq = IAGR & IAGR_GN;
+		if (!irq)
+			break;
+
+		local_irq_restore(irq_disabled_epsw);
+
+		generic_handle_irq(irq >> 2);
+
+		/* restore IRQ controls for IAGR access */
+		local_irq_restore(epsw);
+	}
+
+	__mn10300_irq_enabled_epsw[cpu_id] = old_irq_enabled_epsw;
+
+	irq_exit();
+}
+
+/*
+ * Display interrupt management information through /proc/interrupts
+ */
+int arch_show_interrupts(struct seq_file *p, int prec)
+{
+#ifdef CONFIG_MN10300_WD_TIMER
+	int j;
+
+	seq_printf(p, "%*s: ", prec, "NMI");
+	for (j = 0; j < NR_CPUS; j++)
+		if (cpu_online(j))
+			seq_printf(p, "%10u ", nmi_count(j));
+	seq_putc(p, '\n');
+#endif
+
+	seq_printf(p, "%*s: ", prec, "ERR");
+	seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
+	return 0;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+void migrate_irqs(void)
+{
+	int irq;
+	unsigned int self, new;
+	unsigned long flags;
+
+	self = smp_processor_id();
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		struct irq_data *data = irq_get_irq_data(irq);
+		struct cpumask *mask = irq_data_get_affinity_mask(data);
+
+		if (irqd_is_per_cpu(data))
+			continue;
+
+		if (cpumask_test_cpu(self, mask) &&
+		    !cpumask_intersects(&irq_affinity[irq], cpu_online_mask)) {
+			int cpu_id;
+			cpu_id = cpumask_first(cpu_online_mask);
+			cpumask_set_cpu(cpu_id, mask);
+		}
+		/* We need to operate irq_affinity_online atomically. */
+		arch_local_cli_save(flags);
+		if (irq_affinity_online[irq] == self) {
+			u16 x, tmp;
+
+			x = GxICR(irq);
+			GxICR(irq) = x & GxICR_LEVEL;
+			tmp = GxICR(irq);
+
+			new = cpumask_any_and(mask, cpu_online_mask);
+			irq_affinity_online[irq] = new;
+
+			CROSS_GxICR(irq, new) =
+				(x & GxICR_LEVEL) | GxICR_DETECT;
+			tmp = CROSS_GxICR(irq, new);
+
+			x &= GxICR_LEVEL | GxICR_ENABLE;
+			if (GxICR(irq) & GxICR_REQUEST)
+				x |= GxICR_REQUEST | GxICR_DETECT;
+			CROSS_GxICR(irq, new) = x;
+			tmp = CROSS_GxICR(irq, new);
+		}
+		arch_local_irq_restore(flags);
+	}
+}
+#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/mn10300/kernel/kgdb.c b/arch/mn10300/kernel/kgdb.c
new file mode 100644
index 0000000..9977082
--- /dev/null
+++ b/arch/mn10300/kernel/kgdb.c
@@ -0,0 +1,501 @@
+/* kgdb support for MN10300
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/slab.h>
+#include <linux/ptrace.h>
+#include <linux/kgdb.h>
+#include <linux/uaccess.h>
+#include <unit/leds.h>
+#include <unit/serial.h>
+#include <asm/debugger.h>
+#include <asm/serial-regs.h>
+#include "internal.h"
+
+/*
+ * Software single-stepping breakpoint save (used by __switch_to())
+ */
+static struct thread_info *kgdb_sstep_thread;
+u8 *kgdb_sstep_bp_addr[2];
+u8 kgdb_sstep_bp[2];
+
+/*
+ * Copy kernel exception frame registers to the GDB register file
+ */
+void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	unsigned long ssp = (unsigned long) (regs + 1);
+
+	gdb_regs[GDB_FR_D0]	= regs->d0;
+	gdb_regs[GDB_FR_D1]	= regs->d1;
+	gdb_regs[GDB_FR_D2]	= regs->d2;
+	gdb_regs[GDB_FR_D3]	= regs->d3;
+	gdb_regs[GDB_FR_A0]	= regs->a0;
+	gdb_regs[GDB_FR_A1]	= regs->a1;
+	gdb_regs[GDB_FR_A2]	= regs->a2;
+	gdb_regs[GDB_FR_A3]	= regs->a3;
+	gdb_regs[GDB_FR_SP]	= (regs->epsw & EPSW_nSL) ? regs->sp : ssp;
+	gdb_regs[GDB_FR_PC]	= regs->pc;
+	gdb_regs[GDB_FR_MDR]	= regs->mdr;
+	gdb_regs[GDB_FR_EPSW]	= regs->epsw;
+	gdb_regs[GDB_FR_LIR]	= regs->lir;
+	gdb_regs[GDB_FR_LAR]	= regs->lar;
+	gdb_regs[GDB_FR_MDRQ]	= regs->mdrq;
+	gdb_regs[GDB_FR_E0]	= regs->e0;
+	gdb_regs[GDB_FR_E1]	= regs->e1;
+	gdb_regs[GDB_FR_E2]	= regs->e2;
+	gdb_regs[GDB_FR_E3]	= regs->e3;
+	gdb_regs[GDB_FR_E4]	= regs->e4;
+	gdb_regs[GDB_FR_E5]	= regs->e5;
+	gdb_regs[GDB_FR_E6]	= regs->e6;
+	gdb_regs[GDB_FR_E7]	= regs->e7;
+	gdb_regs[GDB_FR_SSP]	= ssp;
+	gdb_regs[GDB_FR_MSP]	= 0;
+	gdb_regs[GDB_FR_USP]	= regs->sp;
+	gdb_regs[GDB_FR_MCRH]	= regs->mcrh;
+	gdb_regs[GDB_FR_MCRL]	= regs->mcrl;
+	gdb_regs[GDB_FR_MCVF]	= regs->mcvf;
+	gdb_regs[GDB_FR_DUMMY0]	= 0;
+	gdb_regs[GDB_FR_DUMMY1]	= 0;
+	gdb_regs[GDB_FR_FS0]	= 0;
+}
+
+/*
+ * Extracts kernel SP/PC values understandable by gdb from the values
+ * saved by switch_to().
+ */
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+{
+	gdb_regs[GDB_FR_SSP]	= p->thread.sp;
+	gdb_regs[GDB_FR_PC]	= p->thread.pc;
+	gdb_regs[GDB_FR_A3]	= p->thread.a3;
+	gdb_regs[GDB_FR_USP]	= p->thread.usp;
+	gdb_regs[GDB_FR_FPCR]	= p->thread.fpu_state.fpcr;
+}
+
+/*
+ * Fill kernel exception frame registers from the GDB register file
+ */
+void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	regs->d0	= gdb_regs[GDB_FR_D0];
+	regs->d1	= gdb_regs[GDB_FR_D1];
+	regs->d2	= gdb_regs[GDB_FR_D2];
+	regs->d3	= gdb_regs[GDB_FR_D3];
+	regs->a0	= gdb_regs[GDB_FR_A0];
+	regs->a1	= gdb_regs[GDB_FR_A1];
+	regs->a2	= gdb_regs[GDB_FR_A2];
+	regs->a3	= gdb_regs[GDB_FR_A3];
+	regs->sp	= gdb_regs[GDB_FR_SP];
+	regs->pc	= gdb_regs[GDB_FR_PC];
+	regs->mdr	= gdb_regs[GDB_FR_MDR];
+	regs->epsw	= gdb_regs[GDB_FR_EPSW];
+	regs->lir	= gdb_regs[GDB_FR_LIR];
+	regs->lar	= gdb_regs[GDB_FR_LAR];
+	regs->mdrq	= gdb_regs[GDB_FR_MDRQ];
+	regs->e0	= gdb_regs[GDB_FR_E0];
+	regs->e1	= gdb_regs[GDB_FR_E1];
+	regs->e2	= gdb_regs[GDB_FR_E2];
+	regs->e3	= gdb_regs[GDB_FR_E3];
+	regs->e4	= gdb_regs[GDB_FR_E4];
+	regs->e5	= gdb_regs[GDB_FR_E5];
+	regs->e6	= gdb_regs[GDB_FR_E6];
+	regs->e7	= gdb_regs[GDB_FR_E7];
+	regs->sp	= gdb_regs[GDB_FR_SSP];
+	/* gdb_regs[GDB_FR_MSP]; */
+	// regs->usp	= gdb_regs[GDB_FR_USP];
+	regs->mcrh	= gdb_regs[GDB_FR_MCRH];
+	regs->mcrl	= gdb_regs[GDB_FR_MCRL];
+	regs->mcvf	= gdb_regs[GDB_FR_MCVF];
+	/* gdb_regs[GDB_FR_DUMMY0]; */
+	/* gdb_regs[GDB_FR_DUMMY1]; */
+
+	// regs->fpcr	= gdb_regs[GDB_FR_FPCR];
+	// regs->fs0	= gdb_regs[GDB_FR_FS0];
+}
+
+struct kgdb_arch arch_kgdb_ops = {
+	.gdb_bpt_instr	= { 0xff },
+	.flags		= KGDB_HW_BREAKPOINT,
+};
+
+static const unsigned char mn10300_kgdb_insn_sizes[256] =
+{
+	/* 1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
+	1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3,	/* 0 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */
+	2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, /* 2 */
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, /* 3 */
+	1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, /* 4 */
+	1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, /* 5 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 8 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 9 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* a */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* b */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, /* c */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
+	0, 2, 2, 2, 2, 2, 2, 4, 0, 3, 0, 4, 0, 6, 7, 1  /* f */
+};
+
+/*
+ * Attempt to emulate single stepping by means of breakpoint instructions.
+ * Although there is a single-step trace flag in EPSW, its use is not
+ * sufficiently documented and is only intended for use with the JTAG debugger.
+ */
+static int kgdb_arch_do_singlestep(struct pt_regs *regs)
+{
+	unsigned long arg;
+	unsigned size;
+	u8 *pc = (u8 *)regs->pc, *sp = (u8 *)(regs + 1), cur;
+	u8 *x = NULL, *y = NULL;
+	int ret;
+
+	ret = probe_kernel_read(&cur, pc, 1);
+	if (ret < 0)
+		return ret;
+
+	size = mn10300_kgdb_insn_sizes[cur];
+	if (size > 0) {
+		x = pc + size;
+		goto set_x;
+	}
+
+	switch (cur) {
+		/* Bxx (d8,PC) */
+	case 0xc0 ... 0xca:
+		ret = probe_kernel_read(&arg, pc + 1, 1);
+		if (ret < 0)
+			return ret;
+		x = pc + 2;
+		if (arg >= 0 && arg <= 2)
+			goto set_x;
+		y = pc + (s8)arg;
+		goto set_x_and_y;
+
+		/* LXX (d8,PC) */
+	case 0xd0 ... 0xda:
+		x = pc + 1;
+		if (regs->pc == regs->lar)
+			goto set_x;
+		y = (u8 *)regs->lar;
+		goto set_x_and_y;
+
+		/* SETLB - loads the next four bytes into the LIR register
+		 * (which mustn't include a breakpoint instruction) */
+	case 0xdb:
+		x = pc + 5;
+		goto set_x;
+
+		/* JMP (d16,PC) or CALL (d16,PC) */
+	case 0xcc:
+	case 0xcd:
+		ret = probe_kernel_read(&arg, pc + 1, 2);
+		if (ret < 0)
+			return ret;
+		x = pc + (s16)arg;
+		goto set_x;
+
+		/* JMP (d32,PC) or CALL (d32,PC) */
+	case 0xdc:
+	case 0xdd:
+		ret = probe_kernel_read(&arg, pc + 1, 4);
+		if (ret < 0)
+			return ret;
+		x = pc + (s32)arg;
+		goto set_x;
+
+		/* RETF */
+	case 0xde:
+		x = (u8 *)regs->mdr;
+		goto set_x;
+
+		/* RET */
+	case 0xdf:
+		ret = probe_kernel_read(&arg, pc + 2, 1);
+		if (ret < 0)
+			return ret;
+		ret = probe_kernel_read(&x, sp + (s8)arg, 4);
+		if (ret < 0)
+			return ret;
+		goto set_x;
+
+	case 0xf0:
+		ret = probe_kernel_read(&cur, pc + 1, 1);
+		if (ret < 0)
+			return ret;
+
+		if (cur >= 0xf0 && cur <= 0xf7) {
+			/* JMP (An) / CALLS (An) */
+			switch (cur & 3) {
+			case 0: x = (u8 *)regs->a0; break;
+			case 1: x = (u8 *)regs->a1; break;
+			case 2: x = (u8 *)regs->a2; break;
+			case 3: x = (u8 *)regs->a3; break;
+			}
+			goto set_x;
+		} else if (cur == 0xfc) {
+			/* RETS */
+			ret = probe_kernel_read(&x, sp, 4);
+			if (ret < 0)
+				return ret;
+			goto set_x;
+		} else if (cur == 0xfd) {
+			/* RTI */
+			ret = probe_kernel_read(&x, sp + 4, 4);
+			if (ret < 0)
+				return ret;
+			goto set_x;
+		} else {
+			x = pc + 2;
+			goto set_x;
+		}
+		break;
+
+		/* potential 3-byte conditional branches */
+	case 0xf8:
+		ret = probe_kernel_read(&cur, pc + 1, 1);
+		if (ret < 0)
+			return ret;
+		x = pc + 3;
+
+		if (cur >= 0xe8 && cur <= 0xeb) {
+			ret = probe_kernel_read(&arg, pc + 2, 1);
+			if (ret < 0)
+				return ret;
+			if (arg >= 0 && arg <= 3)
+				goto set_x;
+			y = pc + (s8)arg;
+			goto set_x_and_y;
+		}
+		goto set_x;
+
+	case 0xfa:
+		ret = probe_kernel_read(&cur, pc + 1, 1);
+		if (ret < 0)
+			return ret;
+
+		if (cur == 0xff) {
+			/* CALLS (d16,PC) */
+			ret = probe_kernel_read(&arg, pc + 2, 2);
+			if (ret < 0)
+				return ret;
+			x = pc + (s16)arg;
+			goto set_x;
+		}
+
+		x = pc + 4;
+		goto set_x;
+
+	case 0xfc:
+		ret = probe_kernel_read(&cur, pc + 1, 1);
+		if (ret < 0)
+			return ret;
+
+		if (cur == 0xff) {
+			/* CALLS (d32,PC) */
+			ret = probe_kernel_read(&arg, pc + 2, 4);
+			if (ret < 0)
+				return ret;
+			x = pc + (s32)arg;
+			goto set_x;
+		}
+
+		x = pc + 6;
+		goto set_x;
+	}
+
+	return 0;
+
+set_x:
+	kgdb_sstep_bp_addr[0] = x;
+	kgdb_sstep_bp_addr[1] = NULL;
+	ret = probe_kernel_read(&kgdb_sstep_bp[0], x, 1);
+	if (ret < 0)
+		return ret;
+	ret = probe_kernel_write(x, &arch_kgdb_ops.gdb_bpt_instr, 1);
+	if (ret < 0)
+		return ret;
+	kgdb_sstep_thread = current_thread_info();
+	debugger_local_cache_flushinv_one(x);
+	return ret;
+
+set_x_and_y:
+	kgdb_sstep_bp_addr[0] = x;
+	kgdb_sstep_bp_addr[1] = y;
+	ret = probe_kernel_read(&kgdb_sstep_bp[0], x, 1);
+	if (ret < 0)
+		return ret;
+	ret = probe_kernel_read(&kgdb_sstep_bp[1], y, 1);
+	if (ret < 0)
+		return ret;
+	ret = probe_kernel_write(x, &arch_kgdb_ops.gdb_bpt_instr, 1);
+	if (ret < 0)
+		return ret;
+	ret = probe_kernel_write(y, &arch_kgdb_ops.gdb_bpt_instr, 1);
+	if (ret < 0) {
+		probe_kernel_write(kgdb_sstep_bp_addr[0],
+				   &kgdb_sstep_bp[0], 1);
+	} else {
+		kgdb_sstep_thread = current_thread_info();
+	}
+	debugger_local_cache_flushinv_one(x);
+	debugger_local_cache_flushinv_one(y);
+	return ret;
+}
+
+/*
+ * Remove emplaced single-step breakpoints, returning true if we hit one of
+ * them.
+ */
+static bool kgdb_arch_undo_singlestep(struct pt_regs *regs)
+{
+	bool hit = false;
+	u8 *x = kgdb_sstep_bp_addr[0], *y = kgdb_sstep_bp_addr[1];
+	u8 opcode;
+
+	if (kgdb_sstep_thread == current_thread_info()) {
+		if (x) {
+			if (x == (u8 *)regs->pc)
+				hit = true;
+			if (probe_kernel_read(&opcode, x,
+					      1) < 0 ||
+			    opcode != 0xff)
+				BUG();
+			probe_kernel_write(x, &kgdb_sstep_bp[0], 1);
+			debugger_local_cache_flushinv_one(x);
+		}
+		if (y) {
+			if (y == (u8 *)regs->pc)
+				hit = true;
+			if (probe_kernel_read(&opcode, y,
+					      1) < 0 ||
+			    opcode != 0xff)
+				BUG();
+			probe_kernel_write(y, &kgdb_sstep_bp[1], 1);
+			debugger_local_cache_flushinv_one(y);
+		}
+	}
+
+	kgdb_sstep_bp_addr[0] = NULL;
+	kgdb_sstep_bp_addr[1] = NULL;
+	kgdb_sstep_thread = NULL;
+	return hit;
+}
+
+/*
+ * Catch a single-step-pending thread being deleted and make sure the global
+ * single-step state is cleared.  At this point the breakpoints should have
+ * been removed by __switch_to().
+ */
+void arch_release_thread_info(struct thread_info *ti)
+{
+	if (kgdb_sstep_thread == ti) {
+		kgdb_sstep_thread = NULL;
+
+		/* However, we may now be running in degraded mode, with most
+		 * of the CPUs disabled until such a time as KGDB is reentered,
+		 * so force immediate reentry */
+		kgdb_breakpoint();
+	}
+}
+
+/*
+ * Handle unknown packets and [CcsDk] packets
+ * - at this point breakpoints have been installed
+ */
+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+			       char *remcom_in_buffer, char *remcom_out_buffer,
+			       struct pt_regs *regs)
+{
+	long addr;
+	char *ptr;
+
+	switch (remcom_in_buffer[0]) {
+	case 'c':
+	case 's':
+		/* try to read optional parameter, pc unchanged if no parm */
+		ptr = &remcom_in_buffer[1];
+		if (kgdb_hex2long(&ptr, &addr))
+			regs->pc = addr;
+	case 'D':
+	case 'k':
+		atomic_set(&kgdb_cpu_doing_single_step, -1);
+
+		if (remcom_in_buffer[0] == 's') {
+			kgdb_arch_do_singlestep(regs);
+			kgdb_single_step = 1;
+			atomic_set(&kgdb_cpu_doing_single_step,
+				   raw_smp_processor_id());
+		}
+		return 0;
+	}
+	return -1; /* this means that we do not want to exit from the handler */
+}
+
+/*
+ * Handle event interception
+ * - returns 0 if the exception should be skipped, -ERROR otherwise.
+ */
+int debugger_intercept(enum exception_code excep, int signo, int si_code,
+		       struct pt_regs *regs)
+{
+	int ret;
+
+	if (kgdb_arch_undo_singlestep(regs)) {
+		excep = EXCEP_TRAP;
+		signo = SIGTRAP;
+		si_code = TRAP_TRACE;
+	}
+
+	ret = kgdb_handle_exception(excep, signo, si_code, regs);
+
+	debugger_local_cache_flushinv();
+
+	return ret;
+}
+
+/*
+ * Determine if we've hit a debugger special breakpoint
+ */
+int at_debugger_breakpoint(struct pt_regs *regs)
+{
+	return regs->pc == (unsigned long)&__arch_kgdb_breakpoint;
+}
+
+/*
+ * Initialise kgdb
+ */
+int kgdb_arch_init(void)
+{
+	return 0;
+}
+
+/*
+ * Do something, perhaps, but don't know what.
+ */
+void kgdb_arch_exit(void)
+{
+}
+
+#ifdef CONFIG_SMP
+void debugger_nmi_interrupt(struct pt_regs *regs, enum exception_code code)
+{
+	kgdb_nmicallback(arch_smp_processor_id(), regs);
+	debugger_local_cache_flushinv();
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+	smp_jump_to_debugger();
+}
+#endif
diff --git a/arch/mn10300/kernel/kprobes.c b/arch/mn10300/kernel/kprobes.c
new file mode 100644
index 0000000..0311a7f
--- /dev/null
+++ b/arch/mn10300/kernel/kprobes.c
@@ -0,0 +1,656 @@
+/* MN10300 Kernel probes implementation
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by Mark Salter (msalter@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public Licence as published by
+ * the Free Software Foundation; either version 2 of the Licence, or
+ * (at your option) any later version.
+ *
+ * This program 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 Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public Licence
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/spinlock.h>
+#include <linux/preempt.h>
+#include <linux/kdebug.h>
+#include <asm/cacheflush.h>
+
+struct kretprobe_blackpoint kretprobe_blacklist[] = { { NULL, NULL } };
+const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist);
+
+/* kprobe_status settings */
+#define KPROBE_HIT_ACTIVE	0x00000001
+#define KPROBE_HIT_SS		0x00000002
+
+static struct kprobe *cur_kprobe;
+static unsigned long cur_kprobe_orig_pc;
+static unsigned long cur_kprobe_next_pc;
+static int cur_kprobe_ss_flags;
+static unsigned long kprobe_status;
+static kprobe_opcode_t cur_kprobe_ss_buf[MAX_INSN_SIZE + 2];
+static unsigned long cur_kprobe_bp_addr;
+
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+
+
+/* singlestep flag bits */
+#define SINGLESTEP_BRANCH 1
+#define SINGLESTEP_PCREL  2
+
+#define READ_BYTE(p, valp) \
+	do { *(u8 *)(valp) = *(u8 *)(p); } while (0)
+
+#define READ_WORD16(p, valp)					\
+	do {							\
+		READ_BYTE((p), (valp));				\
+		READ_BYTE((u8 *)(p) + 1, (u8 *)(valp) + 1);	\
+	} while (0)
+
+#define READ_WORD32(p, valp)					\
+	do {							\
+		READ_BYTE((p), (valp));				\
+		READ_BYTE((u8 *)(p) + 1, (u8 *)(valp) + 1);	\
+		READ_BYTE((u8 *)(p) + 2, (u8 *)(valp) + 2);	\
+		READ_BYTE((u8 *)(p) + 3, (u8 *)(valp) + 3);	\
+	} while (0)
+
+
+static const u8 mn10300_insn_sizes[256] =
+{
+	/* 1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
+	1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3,	/* 0 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */
+	2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, /* 2 */
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, /* 3 */
+	1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, /* 4 */
+	1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, /* 5 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 8 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 9 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* a */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* b */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, /* c */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
+	0, 2, 2, 2, 2, 2, 2, 4, 0, 3, 0, 4, 0, 6, 7, 1  /* f */
+};
+
+#define LT (1 << 0)
+#define GT (1 << 1)
+#define GE (1 << 2)
+#define LE (1 << 3)
+#define CS (1 << 4)
+#define HI (1 << 5)
+#define CC (1 << 6)
+#define LS (1 << 7)
+#define EQ (1 << 8)
+#define NE (1 << 9)
+#define RA (1 << 10)
+#define VC (1 << 11)
+#define VS (1 << 12)
+#define NC (1 << 13)
+#define NS (1 << 14)
+
+static const u16 cond_table[] = {
+	/*  V  C  N  Z  */
+	/*  0  0  0  0  */ (NE | NC | CC | VC | GE | GT | HI),
+	/*  0  0  0  1  */ (EQ | NC | CC | VC | GE | LE | LS),
+	/*  0  0  1  0  */ (NE | NS | CC | VC | LT | LE | HI),
+	/*  0  0  1  1  */ (EQ | NS | CC | VC | LT | LE | LS),
+	/*  0  1  0  0  */ (NE | NC | CS | VC | GE | GT | LS),
+	/*  0  1  0  1  */ (EQ | NC | CS | VC | GE | LE | LS),
+	/*  0  1  1  0  */ (NE | NS | CS | VC | LT | LE | LS),
+	/*  0  1  1  1  */ (EQ | NS | CS | VC | LT | LE | LS),
+	/*  1  0  0  0  */ (NE | NC | CC | VS | LT | LE | HI),
+	/*  1  0  0  1  */ (EQ | NC | CC | VS | LT | LE | LS),
+	/*  1  0  1  0  */ (NE | NS | CC | VS | GE | GT | HI),
+	/*  1  0  1  1  */ (EQ | NS | CC | VS | GE | LE | LS),
+	/*  1  1  0  0  */ (NE | NC | CS | VS | LT | LE | LS),
+	/*  1  1  0  1  */ (EQ | NC | CS | VS | LT | LE | LS),
+	/*  1  1  1  0  */ (NE | NS | CS | VS | GE | GT | LS),
+	/*  1  1  1  1  */ (EQ | NS | CS | VS | GE | LE | LS),
+};
+
+/*
+ * Calculate what the PC will be after executing next instruction
+ */
+static unsigned find_nextpc(struct pt_regs *regs, int *flags)
+{
+	unsigned size;
+	s8  x8;
+	s16 x16;
+	s32 x32;
+	u8 opc, *pc, *sp, *next;
+
+	next = 0;
+	*flags = SINGLESTEP_PCREL;
+
+	pc = (u8 *) regs->pc;
+	sp = (u8 *) (regs + 1);
+	opc = *pc;
+
+	size = mn10300_insn_sizes[opc];
+	if (size > 0) {
+		next = pc + size;
+	} else {
+		switch (opc) {
+			/* Bxx (d8,PC) */
+		case 0xc0 ... 0xca:
+			x8 = 2;
+			if (cond_table[regs->epsw & 0xf] & (1 << (opc & 0xf)))
+				x8 = (s8)pc[1];
+			next = pc + x8;
+			*flags |= SINGLESTEP_BRANCH;
+			break;
+
+			/* JMP (d16,PC) or CALL (d16,PC) */
+		case 0xcc:
+		case 0xcd:
+			READ_WORD16(pc + 1, &x16);
+			next = pc + x16;
+			*flags |= SINGLESTEP_BRANCH;
+			break;
+
+			/* JMP (d32,PC) or CALL (d32,PC) */
+		case 0xdc:
+		case 0xdd:
+			READ_WORD32(pc + 1, &x32);
+			next = pc + x32;
+			*flags |= SINGLESTEP_BRANCH;
+			break;
+
+			/* RETF */
+		case 0xde:
+			next = (u8 *)regs->mdr;
+			*flags &= ~SINGLESTEP_PCREL;
+			*flags |= SINGLESTEP_BRANCH;
+			break;
+
+			/* RET */
+		case 0xdf:
+			sp += pc[2];
+			READ_WORD32(sp, &x32);
+			next = (u8 *)x32;
+			*flags &= ~SINGLESTEP_PCREL;
+			*flags |= SINGLESTEP_BRANCH;
+			break;
+
+		case 0xf0:
+			next = pc + 2;
+			opc = pc[1];
+			if (opc >= 0xf0 && opc <= 0xf7) {
+				/* JMP (An) / CALLS (An) */
+				switch (opc & 3) {
+				case 0:
+					next = (u8 *)regs->a0;
+					break;
+				case 1:
+					next = (u8 *)regs->a1;
+					break;
+				case 2:
+					next = (u8 *)regs->a2;
+					break;
+				case 3:
+					next = (u8 *)regs->a3;
+					break;
+				}
+				*flags &= ~SINGLESTEP_PCREL;
+				*flags |= SINGLESTEP_BRANCH;
+			} else if (opc == 0xfc) {
+				/* RETS */
+				READ_WORD32(sp, &x32);
+				next = (u8 *)x32;
+				*flags &= ~SINGLESTEP_PCREL;
+				*flags |= SINGLESTEP_BRANCH;
+			} else if (opc == 0xfd) {
+				/* RTI */
+				READ_WORD32(sp + 4, &x32);
+				next = (u8 *)x32;
+				*flags &= ~SINGLESTEP_PCREL;
+				*flags |= SINGLESTEP_BRANCH;
+			}
+			break;
+
+			/* potential 3-byte conditional branches */
+		case 0xf8:
+			next = pc + 3;
+			opc = pc[1];
+			if (opc >= 0xe8 && opc <= 0xeb &&
+			    (cond_table[regs->epsw & 0xf] &
+			     (1 << ((opc & 0xf) + 3)))
+			    ) {
+				READ_BYTE(pc+2, &x8);
+				next = pc + x8;
+				*flags |= SINGLESTEP_BRANCH;
+			}
+			break;
+
+		case 0xfa:
+			if (pc[1] == 0xff) {
+				/* CALLS (d16,PC) */
+				READ_WORD16(pc + 2, &x16);
+				next = pc + x16;
+			} else
+				next = pc + 4;
+			*flags |= SINGLESTEP_BRANCH;
+			break;
+
+		case 0xfc:
+			x32 = 6;
+			if (pc[1] == 0xff) {
+				/* CALLS (d32,PC) */
+				READ_WORD32(pc + 2, &x32);
+			}
+			next = pc + x32;
+			*flags |= SINGLESTEP_BRANCH;
+			break;
+			/* LXX (d8,PC) */
+			/* SETLB - loads the next four bytes into the LIR reg */
+		case 0xd0 ... 0xda:
+		case 0xdb:
+			panic("Can't singlestep Lxx/SETLB\n");
+			break;
+		}
+	}
+	return (unsigned)next;
+
+}
+
+/*
+ * set up out of place singlestep of some branching instructions
+ */
+static unsigned __kprobes singlestep_branch_setup(struct pt_regs *regs)
+{
+	u8 opc, *pc, *sp, *next;
+
+	next = NULL;
+	pc = (u8 *) regs->pc;
+	sp = (u8 *) (regs + 1);
+
+	switch (pc[0]) {
+	case 0xc0 ... 0xca:	/* Bxx (d8,PC) */
+	case 0xcc:		/* JMP (d16,PC) */
+	case 0xdc:		/* JMP (d32,PC) */
+	case 0xf8:              /* Bxx (d8,PC)  3-byte version */
+		/* don't really need to do anything except cause trap  */
+		next = pc;
+		break;
+
+	case 0xcd:		/* CALL (d16,PC) */
+		pc[1] = 5;
+		pc[2] = 0;
+		next = pc + 5;
+		break;
+
+	case 0xdd:		/* CALL (d32,PC) */
+		pc[1] = 7;
+		pc[2] = 0;
+		pc[3] = 0;
+		pc[4] = 0;
+		next = pc + 7;
+		break;
+
+	case 0xde:		/* RETF */
+		next = pc + 3;
+		regs->mdr = (unsigned) next;
+		break;
+
+	case 0xdf:		/* RET */
+		sp += pc[2];
+		next = pc + 3;
+		*(unsigned *)sp = (unsigned) next;
+		break;
+
+	case 0xf0:
+		next = pc + 2;
+		opc = pc[1];
+		if (opc >= 0xf0 && opc <= 0xf3) {
+			/* CALLS (An) */
+			/* use CALLS (d16,PC) to avoid mucking with An */
+			pc[0] = 0xfa;
+			pc[1] = 0xff;
+			pc[2] = 4;
+			pc[3] = 0;
+			next = pc + 4;
+		} else if (opc >= 0xf4 && opc <= 0xf7) {
+			/* JMP (An) */
+			next = pc;
+		} else if (opc == 0xfc) {
+			/* RETS */
+			next = pc + 2;
+			*(unsigned *) sp = (unsigned) next;
+		} else if (opc == 0xfd) {
+			/* RTI */
+			next = pc + 2;
+			*(unsigned *)(sp + 4) = (unsigned) next;
+		}
+		break;
+
+	case 0xfa:	/* CALLS (d16,PC) */
+		pc[2] = 4;
+		pc[3] = 0;
+		next = pc + 4;
+		break;
+
+	case 0xfc:	/* CALLS (d32,PC) */
+		pc[2] = 6;
+		pc[3] = 0;
+		pc[4] = 0;
+		pc[5] = 0;
+		next = pc + 6;
+		break;
+
+	case 0xd0 ... 0xda:	/* LXX (d8,PC) */
+	case 0xdb:		/* SETLB */
+		panic("Can't singlestep Lxx/SETLB\n");
+	}
+
+	return (unsigned) next;
+}
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+	return 0;
+}
+
+void __kprobes arch_copy_kprobe(struct kprobe *p)
+{
+	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE);
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+	*p->addr = BREAKPOINT_INSTRUCTION;
+	flush_icache_range((unsigned long) p->addr,
+			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+#ifndef CONFIG_MN10300_CACHE_SNOOP
+	mn10300_dcache_flush();
+	mn10300_icache_inv();
+#endif
+}
+
+void arch_remove_kprobe(struct kprobe *p)
+{
+}
+
+static inline
+void __kprobes disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
+{
+	*p->addr = p->opcode;
+	regs->pc = (unsigned long) p->addr;
+#ifndef CONFIG_MN10300_CACHE_SNOOP
+	mn10300_dcache_flush();
+	mn10300_icache_inv();
+#endif
+}
+
+static inline
+void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	unsigned long nextpc;
+
+	cur_kprobe_orig_pc = regs->pc;
+	memcpy(cur_kprobe_ss_buf, &p->ainsn.insn[0], MAX_INSN_SIZE);
+	regs->pc = (unsigned long) cur_kprobe_ss_buf;
+
+	nextpc = find_nextpc(regs, &cur_kprobe_ss_flags);
+	if (cur_kprobe_ss_flags & SINGLESTEP_PCREL)
+		cur_kprobe_next_pc = cur_kprobe_orig_pc + (nextpc - regs->pc);
+	else
+		cur_kprobe_next_pc = nextpc;
+
+	/* branching instructions need special handling */
+	if (cur_kprobe_ss_flags & SINGLESTEP_BRANCH)
+		nextpc = singlestep_branch_setup(regs);
+
+	cur_kprobe_bp_addr = nextpc;
+
+	*(u8 *) nextpc = BREAKPOINT_INSTRUCTION;
+	mn10300_dcache_flush_range2((unsigned) cur_kprobe_ss_buf,
+				    sizeof(cur_kprobe_ss_buf));
+	mn10300_icache_inv();
+}
+
+static inline int __kprobes kprobe_handler(struct pt_regs *regs)
+{
+	struct kprobe *p;
+	int ret = 0;
+	unsigned int *addr = (unsigned int *) regs->pc;
+
+	/* We're in an interrupt, but this is clear and BUG()-safe. */
+	preempt_disable();
+
+	/* Check we're not actually recursing */
+	if (kprobe_running()) {
+		/* We *are* holding lock here, so this is safe.
+		   Disarm the probe we just hit, and ignore it. */
+		p = get_kprobe(addr);
+		if (p) {
+			disarm_kprobe(p, regs);
+			ret = 1;
+		} else {
+			p = cur_kprobe;
+			if (p->break_handler && p->break_handler(p, regs))
+				goto ss_probe;
+		}
+		/* If it's not ours, can't be delete race, (we hold lock). */
+		goto no_kprobe;
+	}
+
+	p = get_kprobe(addr);
+	if (!p) {
+		if (*addr != BREAKPOINT_INSTRUCTION) {
+			/* The breakpoint instruction was removed right after
+			 * we hit it.  Another cpu has removed either a
+			 * probepoint or a debugger breakpoint at this address.
+			 * In either case, no further handling of this
+			 * interrupt is appropriate.
+			 */
+			ret = 1;
+		}
+		/* Not one of ours: let kernel handle it */
+		goto no_kprobe;
+	}
+
+	kprobe_status = KPROBE_HIT_ACTIVE;
+	cur_kprobe = p;
+	if (p->pre_handler(p, regs)) {
+		/* handler has already set things up, so skip ss setup */
+		return 1;
+	}
+
+ss_probe:
+	prepare_singlestep(p, regs);
+	kprobe_status = KPROBE_HIT_SS;
+	return 1;
+
+no_kprobe:
+	preempt_enable_no_resched();
+	return ret;
+}
+
+/*
+ * Called after single-stepping.  p->addr is the address of the
+ * instruction whose first byte has been replaced by the "breakpoint"
+ * instruction.  To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction.  The address of this
+ * copy is p->ainsn.insn.
+ */
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+	/* we may need to fixup regs/stack after singlestepping a call insn */
+	if (cur_kprobe_ss_flags & SINGLESTEP_BRANCH) {
+		regs->pc = cur_kprobe_orig_pc;
+		switch (p->ainsn.insn[0]) {
+		case 0xcd:	/* CALL (d16,PC) */
+			*(unsigned *) regs->sp = regs->mdr = regs->pc + 5;
+			break;
+		case 0xdd:	/* CALL (d32,PC) */
+			/* fixup mdr and return address on stack */
+			*(unsigned *) regs->sp = regs->mdr = regs->pc + 7;
+			break;
+		case 0xf0:
+			if (p->ainsn.insn[1] >= 0xf0 &&
+			    p->ainsn.insn[1] <= 0xf3) {
+				/* CALLS (An) */
+				/* fixup MDR and return address on stack */
+				regs->mdr = regs->pc + 2;
+				*(unsigned *) regs->sp = regs->mdr;
+			}
+			break;
+
+		case 0xfa:	/* CALLS (d16,PC) */
+			/* fixup MDR and return address on stack */
+			*(unsigned *) regs->sp = regs->mdr = regs->pc + 4;
+			break;
+
+		case 0xfc:	/* CALLS (d32,PC) */
+			/* fixup MDR and return address on stack */
+			*(unsigned *) regs->sp = regs->mdr = regs->pc + 6;
+			break;
+		}
+	}
+
+	regs->pc = cur_kprobe_next_pc;
+	cur_kprobe_bp_addr = 0;
+}
+
+static inline int __kprobes post_kprobe_handler(struct pt_regs *regs)
+{
+	if (!kprobe_running())
+		return 0;
+
+	if (cur_kprobe->post_handler)
+		cur_kprobe->post_handler(cur_kprobe, regs, 0);
+
+	resume_execution(cur_kprobe, regs);
+	reset_current_kprobe();
+	preempt_enable_no_resched();
+	return 1;
+}
+
+/* Interrupts disabled, kprobe_lock held. */
+static inline
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+	if (cur_kprobe->fault_handler &&
+	    cur_kprobe->fault_handler(cur_kprobe, regs, trapnr))
+		return 1;
+
+	if (kprobe_status & KPROBE_HIT_SS) {
+		resume_execution(cur_kprobe, regs);
+		reset_current_kprobe();
+		preempt_enable_no_resched();
+	}
+	return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+				       unsigned long val, void *data)
+{
+	struct die_args *args = data;
+
+	switch (val) {
+	case DIE_BREAKPOINT:
+		if (cur_kprobe_bp_addr != args->regs->pc) {
+			if (kprobe_handler(args->regs))
+				return NOTIFY_STOP;
+		} else {
+			if (post_kprobe_handler(args->regs))
+				return NOTIFY_STOP;
+		}
+		break;
+	case DIE_GPF:
+		if (kprobe_running() &&
+		    kprobe_fault_handler(args->regs, args->trapnr))
+			return NOTIFY_STOP;
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+/* Jprobes support.  */
+static struct pt_regs jprobe_saved_regs;
+static struct pt_regs *jprobe_saved_regs_location;
+static kprobe_opcode_t jprobe_saved_stack[MAX_STACK_SIZE];
+
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct jprobe *jp = container_of(p, struct jprobe, kp);
+
+	jprobe_saved_regs_location = regs;
+	memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs));
+
+	/* Save a whole stack frame, this gets arguments
+	 * pushed onto the stack after using up all the
+	 * arg registers.
+	 */
+	memcpy(&jprobe_saved_stack, regs + 1, sizeof(jprobe_saved_stack));
+
+	/* setup return addr to the jprobe handler routine */
+	regs->pc = (unsigned long) jp->entry;
+	return 1;
+}
+
+void __kprobes jprobe_return(void)
+{
+	void *orig_sp = jprobe_saved_regs_location + 1;
+
+	preempt_enable_no_resched();
+	asm volatile("		mov	%0,sp\n"
+		     ".globl	jprobe_return_bp_addr\n"
+		     "jprobe_return_bp_addr:\n\t"
+		     "		.byte	0xff\n"
+		     : : "d" (orig_sp));
+}
+
+extern void jprobe_return_bp_addr(void);
+
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	u8 *addr = (u8 *) regs->pc;
+
+	if (addr == (u8 *) jprobe_return_bp_addr) {
+		if (jprobe_saved_regs_location != regs) {
+			printk(KERN_ERR"JPROBE:"
+			       " Current regs (%p) does not match saved regs"
+			       " (%p).\n",
+			       regs, jprobe_saved_regs_location);
+			BUG();
+		}
+
+		/* Restore old register state.
+		 */
+		memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
+
+		memcpy(regs + 1, &jprobe_saved_stack,
+		       sizeof(jprobe_saved_stack));
+		return 1;
+	}
+	return 0;
+}
+
+int __init arch_init_kprobes(void)
+{
+	return 0;
+}
diff --git a/arch/mn10300/kernel/mn10300-debug.c b/arch/mn10300/kernel/mn10300-debug.c
new file mode 100644
index 0000000..bd81964
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-debug.c
@@ -0,0 +1,58 @@
+/* Debugging stuff for the MN10300-based processors
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <asm/serial-regs.h>
+
+#undef MN10300_CONSOLE_ON_SERIO
+
+/*
+ * write a string directly through one of the serial ports on-board the MN10300
+ */
+#ifdef MN10300_CONSOLE_ON_SERIO
+void debug_to_serial_mnser(const char *p, int n)
+{
+	char ch;
+
+	for (; n > 0; n--) {
+		ch = *p++;
+
+#if MN10300_CONSOLE_ON_SERIO == 0
+		while (SC0STR & (SC01STR_TBF)) continue;
+		SC0TXB = ch;
+		while (SC0STR & (SC01STR_TBF)) continue;
+		if (ch == 0x0a) {
+			SC0TXB = 0x0d;
+			while (SC0STR & (SC01STR_TBF)) continue;
+		}
+
+#elif MN10300_CONSOLE_ON_SERIO == 1
+		while (SC1STR & (SC01STR_TBF)) continue;
+		SC1TXB = ch;
+		while (SC1STR & (SC01STR_TBF)) continue;
+		if (ch == 0x0a) {
+			SC1TXB = 0x0d;
+			while (SC1STR & (SC01STR_TBF)) continue;
+		}
+
+#elif MN10300_CONSOLE_ON_SERIO == 2
+		while (SC2STR & (SC2STR_TBF)) continue;
+		SC2TXB = ch;
+		while (SC2STR & (SC2STR_TBF)) continue;
+		if (ch == 0x0a) {
+			SC2TXB = 0x0d;
+			while (SC2STR & (SC2STR_TBF)) continue;
+		}
+
+#endif
+	}
+}
+#endif
+
diff --git a/arch/mn10300/kernel/mn10300-serial-low.S b/arch/mn10300/kernel/mn10300-serial-low.S
new file mode 100644
index 0000000..b95e76c
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-serial-low.S
@@ -0,0 +1,194 @@
+###############################################################################
+#
+# Virtual DMA driver for MN10300 serial ports
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/smp.h>
+#include <asm/cpu-regs.h>
+#include <asm/frame.inc>
+#include <asm/timer-regs.h>
+#include <proc/cache.h>
+#include <unit/timex.h>
+#include "mn10300-serial.h"
+
+#define	SCxCTR	0x00
+#define	SCxICR	0x04
+#define	SCxTXB	0x08
+#define	SCxRXB	0x09
+#define	SCxSTR	0x0c
+#define	SCxTIM	0x0d
+
+	.text
+
+###############################################################################
+#
+# serial port interrupt virtual DMA entry point
+# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
+#
+###############################################################################
+	.balign	L1_CACHE_BYTES
+ENTRY(mn10300_serial_vdma_interrupt)
+#	or	EPSW_IE,psw			# permit overriding by
+						# debugging interrupts
+	movm	[d2,d3,a2,a3,exreg0],(sp)
+
+	movhu	(IAGR),a2			# see if which interrupt is
+						# pending
+	and	IAGR_GN,a2
+	add	a2,a2
+	add	mn10300_serial_int_tbl,a2
+
+	mov	(a2+),a3
+	mov	(__iobase,a3),e2
+	mov	(a2),a2
+	jmp	(a2)
+
+###############################################################################
+#
+# serial port receive interrupt virtual DMA entry point
+# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
+# - stores data/status byte pairs in the ring buffer
+# - induces a scheduler tick timer interrupt when done, which we then subvert
+# on entry:
+#	A3	struct mn10300_serial_port *
+#	E2	I/O port base
+#
+###############################################################################
+ENTRY(mn10300_serial_vdma_rx_handler)
+	mov	(__rx_icr,a3),e3
+	mov	GxICR_DETECT,d2
+	movbu	d2,(e3)				# ACK the interrupt
+	movhu	(e3),d2				# flush
+
+	mov	(__rx_inp,a3),d3
+	mov	d3,a2
+	add	2,d3
+	and	MNSC_BUFFER_SIZE-1,d3
+	mov	(__rx_outp,a3),d2
+	cmp	d3,d2
+	beq	mnsc_vdma_rx_overflow
+
+	mov	(__rx_buffer,a3),d2
+	add	d2,a2
+	movhu	(SCxSTR,e2),d2
+	movbu	d2,(1,a2)
+	movbu	(SCxRXB,e2),d2
+	movbu	d2,(a2)
+	mov	d3,(__rx_inp,a3)
+	bset	MNSCx_RX_AVAIL,(__intr_flags,a3)
+
+mnsc_vdma_rx_done:
+	mov	(__tm_icr,a3),a2
+	mov	GxICR_LEVEL_6|GxICR_ENABLE|GxICR_REQUEST|GxICR_DETECT,d2
+	movhu	d2,(a2)				# request a slow interrupt
+	movhu	(a2),d2				# flush
+
+	movm	(sp),[d2,d3,a2,a3,exreg0]
+	rti
+
+mnsc_vdma_rx_overflow:
+	bset	MNSCx_RX_OVERF,(__intr_flags,a3)
+	bra	mnsc_vdma_rx_done
+
+###############################################################################
+#
+# serial port transmit interrupt virtual DMA entry point
+# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
+# - retrieves data bytes from the ring buffer and passes them to the serial port
+# - induces a scheduler tick timer interrupt when done, which we then subvert
+#	A3	struct mn10300_serial_port *
+#	E2	I/O port base
+#
+###############################################################################
+	.balign	L1_CACHE_BYTES
+ENTRY(mn10300_serial_vdma_tx_handler)
+	mov	(__tx_icr,a3),e3
+	mov	GxICR_DETECT,d2
+	movbu	d2,(e3)			# ACK the interrupt
+	movhu	(e3),d2			# flush
+
+	btst	0xFF,(__tx_flags,a3)	# handle transmit flags
+	bne	mnsc_vdma_tx_flags
+
+	movbu	(SCxSTR,e2),d2		# don't try and transmit a char if the
+					# buffer is not empty
+	btst	SC01STR_TBF,d2		# (may have tried to jumpstart)
+	bne	mnsc_vdma_tx_noint
+
+	movbu	(__tx_xchar,a3),d2	# handle hi-pri XON/XOFF
+	or	d2,d2
+	bne	mnsc_vdma_tx_xchar
+
+	mov	(__uart_state,a3),a2	# see if the TTY Tx queue has anything in it
+	mov	(__xmit_tail,a2),d3
+	mov	(__xmit_head,a2),d2
+	cmp	d3,d2
+	beq	mnsc_vdma_tx_empty
+
+	mov	(__xmit_buffer,a2),d2	# get a char from the buffer and
+					# transmit it
+	movbu	(d3,d2),d2
+	movbu	d2,(SCxTXB,e2)		# Tx
+
+	inc	d3			# advance the buffer pointer
+	and	__UART_XMIT_SIZE-1,d3
+	mov	(__xmit_head,a2),d2
+	mov	d3,(__xmit_tail,a2)
+
+	sub	d3,d2			# see if we've written everything
+	beq	mnsc_vdma_tx_empty
+
+	and	__UART_XMIT_SIZE-1,d2	# see if we just made a hole
+	cmp	__UART_XMIT_SIZE-2,d2
+	beq	mnsc_vdma_tx_made_hole
+
+mnsc_vdma_tx_done:
+	mov	(__tm_icr,a3),a2
+	mov	GxICR_LEVEL_6|GxICR_ENABLE|GxICR_REQUEST|GxICR_DETECT,d2
+	movhu	d2,(a2)			# request a slow interrupt
+	movhu	(a2),d2			# flush
+
+mnsc_vdma_tx_noint:
+	movm	(sp),[d2,d3,a2,a3,exreg0]
+	rti
+
+mnsc_vdma_tx_empty:
+	mov	+(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2
+	movhu	d2,(e3)			# disable the interrupt
+	movhu	(e3),d2			# flush
+
+	bset	MNSCx_TX_EMPTY,(__intr_flags,a3)
+	bra	mnsc_vdma_tx_done
+
+mnsc_vdma_tx_flags:
+	btst	MNSCx_TX_STOP,(__tx_flags,a3)
+	bne	mnsc_vdma_tx_stop
+	movhu	(SCxCTR,e2),d2		# turn on break mode
+	or	SC01CTR_BKE,d2
+	movhu	d2,(SCxCTR,e2)
+mnsc_vdma_tx_stop:
+	mov	+(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2
+	movhu	d2,(e3)			# disable transmit interrupts on this
+					# channel
+	movhu	(e3),d2			# flush
+	bra	mnsc_vdma_tx_noint
+
+mnsc_vdma_tx_xchar:
+	bclr	0xff,(__tx_xchar,a3)
+	movbu	d2,(SCxTXB,e2)
+	bra	mnsc_vdma_tx_done
+
+mnsc_vdma_tx_made_hole:
+	bset	MNSCx_TX_SPACE,(__intr_flags,a3)
+	bra	mnsc_vdma_tx_done
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c
new file mode 100644
index 0000000..7ecf698
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-serial.c
@@ -0,0 +1,1787 @@
+/* MN10300 On-chip serial port UART driver
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+static const char serial_name[] = "MN10300 Serial driver";
+static const char serial_version[] = "mn10300_serial-1.0";
+static const char serial_revdate[] = "2007-11-06";
+
+#if defined(CONFIG_MN10300_TTYSM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/circ_buf.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/serial-regs.h>
+#include <unit/timex.h>
+#include "mn10300-serial.h"
+
+#ifdef CONFIG_SMP
+#undef  GxICR
+#define GxICR(X) CROSS_GxICR(X, 0)
+#endif /* CONFIG_SMP */
+
+#define kenter(FMT, ...) \
+	printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__)
+#define _enter(FMT, ...) \
+	no_printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__)
+#define kdebug(FMT, ...) \
+	printk(KERN_DEBUG "--- " FMT "\n", ##__VA_ARGS__)
+#define _debug(FMT, ...) \
+	no_printk(KERN_DEBUG "--- " FMT "\n", ##__VA_ARGS__)
+#define kproto(FMT, ...) \
+	printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__)
+#define _proto(FMT, ...) \
+	no_printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__)
+
+#ifndef CODMSB
+/* c_cflag bit meaning */
+#define CODMSB	004000000000	/* change Transfer bit-order */
+#endif
+
+#define NR_UARTS 3
+
+#ifdef CONFIG_MN10300_TTYSM_CONSOLE
+static void mn10300_serial_console_write(struct console *co,
+					   const char *s, unsigned count);
+static int __init mn10300_serial_console_setup(struct console *co,
+						 char *options);
+
+static struct uart_driver mn10300_serial_driver;
+static struct console mn10300_serial_console = {
+	.name		= "ttySM",
+	.write		= mn10300_serial_console_write,
+	.device		= uart_console_device,
+	.setup		= mn10300_serial_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &mn10300_serial_driver,
+};
+#endif
+
+static struct uart_driver mn10300_serial_driver = {
+	.owner		= NULL,
+	.driver_name	= "mn10300-serial",
+	.dev_name	= "ttySM",
+	.major		= TTY_MAJOR,
+	.minor		= 128,
+	.nr		= NR_UARTS,
+#ifdef CONFIG_MN10300_TTYSM_CONSOLE
+	.cons		= &mn10300_serial_console,
+#endif
+};
+
+static unsigned int mn10300_serial_tx_empty(struct uart_port *);
+static void mn10300_serial_set_mctrl(struct uart_port *, unsigned int mctrl);
+static unsigned int mn10300_serial_get_mctrl(struct uart_port *);
+static void mn10300_serial_stop_tx(struct uart_port *);
+static void mn10300_serial_start_tx(struct uart_port *);
+static void mn10300_serial_send_xchar(struct uart_port *, char ch);
+static void mn10300_serial_stop_rx(struct uart_port *);
+static void mn10300_serial_enable_ms(struct uart_port *);
+static void mn10300_serial_break_ctl(struct uart_port *, int ctl);
+static int mn10300_serial_startup(struct uart_port *);
+static void mn10300_serial_shutdown(struct uart_port *);
+static void mn10300_serial_set_termios(struct uart_port *,
+					 struct ktermios *new,
+					 struct ktermios *old);
+static const char *mn10300_serial_type(struct uart_port *);
+static void mn10300_serial_release_port(struct uart_port *);
+static int mn10300_serial_request_port(struct uart_port *);
+static void mn10300_serial_config_port(struct uart_port *, int);
+static int mn10300_serial_verify_port(struct uart_port *,
+					struct serial_struct *);
+#ifdef CONFIG_CONSOLE_POLL
+static void mn10300_serial_poll_put_char(struct uart_port *, unsigned char);
+static int mn10300_serial_poll_get_char(struct uart_port *);
+#endif
+
+static const struct uart_ops mn10300_serial_ops = {
+	.tx_empty	= mn10300_serial_tx_empty,
+	.set_mctrl	= mn10300_serial_set_mctrl,
+	.get_mctrl	= mn10300_serial_get_mctrl,
+	.stop_tx	= mn10300_serial_stop_tx,
+	.start_tx	= mn10300_serial_start_tx,
+	.send_xchar	= mn10300_serial_send_xchar,
+	.stop_rx	= mn10300_serial_stop_rx,
+	.enable_ms	= mn10300_serial_enable_ms,
+	.break_ctl	= mn10300_serial_break_ctl,
+	.startup	= mn10300_serial_startup,
+	.shutdown	= mn10300_serial_shutdown,
+	.set_termios	= mn10300_serial_set_termios,
+	.type		= mn10300_serial_type,
+	.release_port	= mn10300_serial_release_port,
+	.request_port	= mn10300_serial_request_port,
+	.config_port	= mn10300_serial_config_port,
+	.verify_port	= mn10300_serial_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_put_char	= mn10300_serial_poll_put_char,
+	.poll_get_char	= mn10300_serial_poll_get_char,
+#endif
+};
+
+static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id);
+
+/*
+ * the first on-chip serial port: ttySM0 (aka SIF0)
+ */
+#ifdef CONFIG_MN10300_TTYSM0
+struct mn10300_serial_port mn10300_serial_port_sif0 = {
+	.uart.ops	= &mn10300_serial_ops,
+	.uart.membase	= (void __iomem *) &SC0CTR,
+	.uart.mapbase	= (unsigned long) &SC0CTR,
+	.uart.iotype	= UPIO_MEM,
+	.uart.irq	= 0,
+	.uart.uartclk	= 0, /* MN10300_IOCLK, */
+	.uart.fifosize	= 1,
+	.uart.flags	= UPF_BOOT_AUTOCONF,
+	.uart.line	= 0,
+	.uart.type	= PORT_MN10300,
+	.uart.lock	=
+	__SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif0.uart.lock),
+	.name		= "ttySM0",
+	._iobase	= &SC0CTR,
+	._control	= &SC0CTR,
+	._status	= (volatile u8 *)&SC0STR,
+	._intr		= &SC0ICR,
+	._rxb		= &SC0RXB,
+	._txb		= &SC0TXB,
+	.rx_name	= "ttySM0:Rx",
+	.tx_name	= "ttySM0:Tx",
+#if defined(CONFIG_MN10300_TTYSM0_TIMER8)
+	.tm_name	= "ttySM0:Timer8",
+	._tmxmd		= &TM8MD,
+	._tmxbr		= &TM8BR,
+	._tmicr		= &TM8ICR,
+	.tm_irq		= TM8IRQ,
+	.div_timer	= MNSCx_DIV_TIMER_16BIT,
+#elif defined(CONFIG_MN10300_TTYSM0_TIMER0)
+	.tm_name	= "ttySM0:Timer0",
+	._tmxmd		= &TM0MD,
+	._tmxbr		= (volatile u16 *)&TM0BR,
+	._tmicr		= &TM0ICR,
+	.tm_irq		= TM0IRQ,
+	.div_timer	= MNSCx_DIV_TIMER_8BIT,
+#elif defined(CONFIG_MN10300_TTYSM0_TIMER2)
+	.tm_name	= "ttySM0:Timer2",
+	._tmxmd		= &TM2MD,
+	._tmxbr		= (volatile u16 *)&TM2BR,
+	._tmicr		= &TM2ICR,
+	.tm_irq		= TM2IRQ,
+	.div_timer	= MNSCx_DIV_TIMER_8BIT,
+#else
+#error "Unknown config for ttySM0"
+#endif
+	.rx_irq		= SC0RXIRQ,
+	.tx_irq		= SC0TXIRQ,
+	.rx_icr		= &GxICR(SC0RXIRQ),
+	.tx_icr		= &GxICR(SC0TXIRQ),
+	.clock_src	= MNSCx_CLOCK_SRC_IOCLK,
+	.options	= 0,
+#ifdef CONFIG_GDBSTUB_ON_TTYSM0
+	.gdbstub	= 1,
+#endif
+};
+#endif /* CONFIG_MN10300_TTYSM0 */
+
+/*
+ * the second on-chip serial port: ttySM1 (aka SIF1)
+ */
+#ifdef CONFIG_MN10300_TTYSM1
+struct mn10300_serial_port mn10300_serial_port_sif1 = {
+	.uart.ops	= &mn10300_serial_ops,
+	.uart.membase	= (void __iomem *) &SC1CTR,
+	.uart.mapbase	= (unsigned long) &SC1CTR,
+	.uart.iotype	= UPIO_MEM,
+	.uart.irq	= 0,
+	.uart.uartclk	= 0, /* MN10300_IOCLK, */
+	.uart.fifosize	= 1,
+	.uart.flags	= UPF_BOOT_AUTOCONF,
+	.uart.line	= 1,
+	.uart.type	= PORT_MN10300,
+	.uart.lock	=
+	__SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif1.uart.lock),
+	.name		= "ttySM1",
+	._iobase	= &SC1CTR,
+	._control	= &SC1CTR,
+	._status	= (volatile u8 *)&SC1STR,
+	._intr		= &SC1ICR,
+	._rxb		= &SC1RXB,
+	._txb		= &SC1TXB,
+	.rx_name	= "ttySM1:Rx",
+	.tx_name	= "ttySM1:Tx",
+#if defined(CONFIG_MN10300_TTYSM1_TIMER9)
+	.tm_name	= "ttySM1:Timer9",
+	._tmxmd		= &TM9MD,
+	._tmxbr		= &TM9BR,
+	._tmicr		= &TM9ICR,
+	.tm_irq		= TM9IRQ,
+	.div_timer	= MNSCx_DIV_TIMER_16BIT,
+#elif defined(CONFIG_MN10300_TTYSM1_TIMER3)
+	.tm_name	= "ttySM1:Timer3",
+	._tmxmd		= &TM3MD,
+	._tmxbr		= (volatile u16 *)&TM3BR,
+	._tmicr		= &TM3ICR,
+	.tm_irq		= TM3IRQ,
+	.div_timer	= MNSCx_DIV_TIMER_8BIT,
+#elif defined(CONFIG_MN10300_TTYSM1_TIMER12)
+	.tm_name	= "ttySM1/Timer12",
+	._tmxmd		= &TM12MD,
+	._tmxbr		= &TM12BR,
+	._tmicr		= &TM12ICR,
+	.tm_irq		= TM12IRQ,
+	.div_timer	= MNSCx_DIV_TIMER_16BIT,
+#else
+#error "Unknown config for ttySM1"
+#endif
+	.rx_irq		= SC1RXIRQ,
+	.tx_irq		= SC1TXIRQ,
+	.rx_icr		= &GxICR(SC1RXIRQ),
+	.tx_icr		= &GxICR(SC1TXIRQ),
+	.clock_src	= MNSCx_CLOCK_SRC_IOCLK,
+	.options	= 0,
+#ifdef CONFIG_GDBSTUB_ON_TTYSM1
+	.gdbstub	= 1,
+#endif
+};
+#endif /* CONFIG_MN10300_TTYSM1 */
+
+/*
+ * the third on-chip serial port: ttySM2 (aka SIF2)
+ */
+#ifdef CONFIG_MN10300_TTYSM2
+struct mn10300_serial_port mn10300_serial_port_sif2 = {
+	.uart.ops	= &mn10300_serial_ops,
+	.uart.membase	= (void __iomem *) &SC2CTR,
+	.uart.mapbase	= (unsigned long) &SC2CTR,
+	.uart.iotype	= UPIO_MEM,
+	.uart.irq	= 0,
+	.uart.uartclk	= 0, /* MN10300_IOCLK, */
+	.uart.fifosize	= 1,
+	.uart.flags	= UPF_BOOT_AUTOCONF,
+	.uart.line	= 2,
+#ifdef CONFIG_MN10300_TTYSM2_CTS
+	.uart.type	= PORT_MN10300_CTS,
+#else
+	.uart.type	= PORT_MN10300,
+#endif
+	.uart.lock	=
+	__SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock),
+	.name		= "ttySM2",
+	._iobase	= &SC2CTR,
+	._control	= &SC2CTR,
+	._status	= (volatile u8 *)&SC2STR,
+	._intr		= &SC2ICR,
+	._rxb		= &SC2RXB,
+	._txb		= &SC2TXB,
+	.rx_name	= "ttySM2:Rx",
+	.tx_name	= "ttySM2:Tx",
+#if defined(CONFIG_MN10300_TTYSM2_TIMER10)
+	.tm_name	= "ttySM2/Timer10",
+	._tmxmd		= &TM10MD,
+	._tmxbr		= &TM10BR,
+	._tmicr		= &TM10ICR,
+	.tm_irq		= TM10IRQ,
+	.div_timer	= MNSCx_DIV_TIMER_16BIT,
+#elif defined(CONFIG_MN10300_TTYSM2_TIMER9)
+	.tm_name	= "ttySM2/Timer9",
+	._tmxmd		= &TM9MD,
+	._tmxbr		= &TM9BR,
+	._tmicr		= &TM9ICR,
+	.tm_irq		= TM9IRQ,
+	.div_timer	= MNSCx_DIV_TIMER_16BIT,
+#elif defined(CONFIG_MN10300_TTYSM2_TIMER1)
+	.tm_name	= "ttySM2/Timer1",
+	._tmxmd		= &TM1MD,
+	._tmxbr		= (volatile u16 *)&TM1BR,
+	._tmicr		= &TM1ICR,
+	.tm_irq		= TM1IRQ,
+	.div_timer	= MNSCx_DIV_TIMER_8BIT,
+#elif defined(CONFIG_MN10300_TTYSM2_TIMER3)
+	.tm_name	= "ttySM2/Timer3",
+	._tmxmd		= &TM3MD,
+	._tmxbr		= (volatile u16 *)&TM3BR,
+	._tmicr		= &TM3ICR,
+	.tm_irq		= TM3IRQ,
+	.div_timer	= MNSCx_DIV_TIMER_8BIT,
+#else
+#error "Unknown config for ttySM2"
+#endif
+	.rx_irq		= SC2RXIRQ,
+	.tx_irq		= SC2TXIRQ,
+	.rx_icr		= &GxICR(SC2RXIRQ),
+	.tx_icr		= &GxICR(SC2TXIRQ),
+	.clock_src	= MNSCx_CLOCK_SRC_IOCLK,
+#ifdef CONFIG_MN10300_TTYSM2_CTS
+	.options	= MNSCx_OPT_CTS,
+#else
+	.options	= 0,
+#endif
+#ifdef CONFIG_GDBSTUB_ON_TTYSM2
+	.gdbstub	= 1,
+#endif
+};
+#endif /* CONFIG_MN10300_TTYSM2 */
+
+
+/*
+ * list of available serial ports
+ */
+struct mn10300_serial_port *mn10300_serial_ports[NR_UARTS + 1] = {
+#ifdef CONFIG_MN10300_TTYSM0
+	[0]	= &mn10300_serial_port_sif0,
+#endif
+#ifdef CONFIG_MN10300_TTYSM1
+	[1]	= &mn10300_serial_port_sif1,
+#endif
+#ifdef CONFIG_MN10300_TTYSM2
+	[2]	= &mn10300_serial_port_sif2,
+#endif
+	[NR_UARTS] = NULL,
+};
+
+
+/*
+ * we abuse the serial ports' baud timers' interrupt lines to get the ability
+ * to deliver interrupts to userspace as we use the ports' interrupt lines to
+ * do virtual DMA on account of the ports having no hardware FIFOs
+ *
+ * we can generate an interrupt manually in the assembly stubs by writing to
+ * the enable and detect bits in the interrupt control register, so all we need
+ * to do here is disable the interrupt line
+ *
+ * note that we can't just leave the line enabled as the baud rate timer *also*
+ * generates interrupts
+ */
+static void mn10300_serial_mask_ack(unsigned int irq)
+{
+	unsigned long flags;
+	u16 tmp;
+
+	flags = arch_local_cli_save();
+	GxICR(irq) = GxICR_LEVEL_6;
+	tmp = GxICR(irq); /* flush write buffer */
+	arch_local_irq_restore(flags);
+}
+
+static void mn10300_serial_chip_mask_ack(struct irq_data *d)
+{
+	mn10300_serial_mask_ack(d->irq);
+}
+
+static void mn10300_serial_nop(struct irq_data *d)
+{
+}
+
+static struct irq_chip mn10300_serial_pic = {
+	.name		= "mnserial",
+	.irq_ack	= mn10300_serial_chip_mask_ack,
+	.irq_mask	= mn10300_serial_chip_mask_ack,
+	.irq_mask_ack	= mn10300_serial_chip_mask_ack,
+	.irq_unmask	= mn10300_serial_nop,
+};
+
+static void mn10300_serial_low_mask(struct irq_data *d)
+{
+	unsigned long flags;
+	u16 tmp;
+
+	flags = arch_local_cli_save();
+	GxICR(d->irq) = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
+	tmp = GxICR(d->irq); /* flush write buffer */
+	arch_local_irq_restore(flags);
+}
+
+static void mn10300_serial_low_unmask(struct irq_data *d)
+{
+	unsigned long flags;
+	u16 tmp;
+
+	flags = arch_local_cli_save();
+	GxICR(d->irq) =
+		NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE;
+	tmp = GxICR(d->irq); /* flush write buffer */
+	arch_local_irq_restore(flags);
+}
+
+static struct irq_chip mn10300_serial_low_pic = {
+	.name		= "mnserial-low",
+	.irq_mask	= mn10300_serial_low_mask,
+	.irq_unmask	= mn10300_serial_low_unmask,
+};
+
+/*
+ * serial virtual DMA interrupt jump table
+ */
+struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS];
+
+static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port)
+{
+	int retries = 100;
+	u16 x;
+
+	/* nothing to do if irq isn't set up */
+	if (!mn10300_serial_int_tbl[port->tx_irq].port)
+		return;
+
+	port->tx_flags |= MNSCx_TX_STOP;
+	mb();
+
+	/*
+	 * Here we wait for the irq to be disabled. Either it already is
+	 * disabled or we wait some number of retries for the VDMA handler
+	 * to disable it. The retries give the VDMA handler enough time to
+	 * run to completion if it was already in progress. If the VDMA IRQ
+	 * is enabled but the handler is not yet running when arrive here,
+	 * the STOP flag will prevent the handler from conflicting with the
+	 * driver code following this loop.
+	 */
+	while ((*port->tx_icr & GxICR_ENABLE) && retries-- > 0)
+		;
+	if (retries <= 0) {
+		*port->tx_icr =
+			NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
+		x = *port->tx_icr;
+	}
+}
+
+static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port)
+{
+	u16 x;
+
+	/* nothing to do if irq isn't set up */
+	if (!mn10300_serial_int_tbl[port->tx_irq].port)
+		return;
+
+	/* stop vdma irq if not already stopped */
+	if (!(port->tx_flags & MNSCx_TX_STOP))
+		mn10300_serial_dis_tx_intr(port);
+
+	port->tx_flags &= ~MNSCx_TX_STOP;
+	mb();
+
+	*port->tx_icr =
+		NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) |
+		GxICR_ENABLE | GxICR_REQUEST | GxICR_DETECT;
+	x = *port->tx_icr;
+}
+
+static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port)
+{
+	unsigned long flags;
+	u16 x;
+
+	flags = arch_local_cli_save();
+	*port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
+	x = *port->rx_icr;
+	arch_local_irq_restore(flags);
+}
+
+/*
+ * multi-bit equivalent of test_and_clear_bit()
+ */
+static int mask_test_and_clear(volatile u8 *ptr, u8 mask)
+{
+	u32 epsw;
+	asm volatile("	bclr	%1,(%2)		\n"
+		     "	mov	epsw,%0		\n"
+		     : "=d"(epsw) : "d"(mask), "a"(ptr)
+		     : "cc", "memory");
+	return !(epsw & EPSW_FLAG_Z);
+}
+
+/*
+ * receive chars from the ring buffer for this serial port
+ * - must do break detection here (not done in the UART)
+ */
+static void mn10300_serial_receive_interrupt(struct mn10300_serial_port *port)
+{
+	struct uart_icount *icount = &port->uart.icount;
+	struct tty_port *tport = &port->uart.state->port;
+	unsigned ix;
+	int count;
+	u8 st, ch, push, status, overrun;
+
+	_enter("%s", port->name);
+
+	push = 0;
+
+	count = CIRC_CNT(port->rx_inp, port->rx_outp, MNSC_BUFFER_SIZE);
+	count = tty_buffer_request_room(tport, count);
+	if (count == 0) {
+		if (!tport->low_latency)
+			tty_flip_buffer_push(tport);
+		return;
+	}
+
+try_again:
+	/* pull chars out of the hat */
+	ix = ACCESS_ONCE(port->rx_outp);
+	if (CIRC_CNT(port->rx_inp, ix, MNSC_BUFFER_SIZE) == 0) {
+		if (push && !tport->low_latency)
+			tty_flip_buffer_push(tport);
+		return;
+	}
+
+	smp_read_barrier_depends();
+	ch = port->rx_buffer[ix++];
+	st = port->rx_buffer[ix++];
+	smp_mb();
+	port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
+	port->uart.icount.rx++;
+
+	st &= SC01STR_FEF | SC01STR_PEF | SC01STR_OEF;
+	status = 0;
+	overrun = 0;
+
+	/* the UART doesn't detect BREAK, so we have to do that ourselves
+	 * - it starts as a framing error on a NUL character
+	 * - then we count another two NUL characters before issuing TTY_BREAK
+	 * - then we end on a normal char or one that has all the bottom bits
+	 *   zero and the top bits set
+	 */
+	switch (port->rx_brk) {
+	case 0:
+		/* not breaking at the moment */
+		break;
+
+	case 1:
+		if (st & SC01STR_FEF && ch == 0) {
+			port->rx_brk = 2;
+			goto try_again;
+		}
+		goto not_break;
+
+	case 2:
+		if (st & SC01STR_FEF && ch == 0) {
+			port->rx_brk = 3;
+			_proto("Rx Break Detected");
+			icount->brk++;
+			if (uart_handle_break(&port->uart))
+				goto ignore_char;
+			status |= 1 << TTY_BREAK;
+			goto insert;
+		}
+		goto not_break;
+
+	default:
+		if (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF))
+			goto try_again; /* still breaking */
+
+		port->rx_brk = 0; /* end of the break */
+
+		switch (ch) {
+		case 0xFF:
+		case 0xFE:
+		case 0xFC:
+		case 0xF8:
+		case 0xF0:
+		case 0xE0:
+		case 0xC0:
+		case 0x80:
+		case 0x00:
+			/* discard char at probable break end */
+			goto try_again;
+		}
+		break;
+	}
+
+process_errors:
+	/* handle framing error */
+	if (st & SC01STR_FEF) {
+		if (ch == 0) {
+			/* framing error with NUL char is probably a BREAK */
+			port->rx_brk = 1;
+			goto try_again;
+		}
+
+		_proto("Rx Framing Error");
+		icount->frame++;
+		status |= 1 << TTY_FRAME;
+	}
+
+	/* handle parity error */
+	if (st & SC01STR_PEF) {
+		_proto("Rx Parity Error");
+		icount->parity++;
+		status = TTY_PARITY;
+	}
+
+	/* handle normal char */
+	if (status == 0) {
+		if (uart_handle_sysrq_char(&port->uart, ch))
+			goto ignore_char;
+		status = (1 << TTY_NORMAL);
+	}
+
+	/* handle overrun error */
+	if (st & SC01STR_OEF) {
+		if (port->rx_brk)
+			goto try_again;
+
+		_proto("Rx Overrun Error");
+		icount->overrun++;
+		overrun = 1;
+	}
+
+insert:
+	status &= port->uart.read_status_mask;
+
+	if (!overrun && !(status & port->uart.ignore_status_mask)) {
+		int flag;
+
+		if (status & (1 << TTY_BREAK))
+			flag = TTY_BREAK;
+		else if (status & (1 << TTY_PARITY))
+			flag = TTY_PARITY;
+		else if (status & (1 << TTY_FRAME))
+			flag = TTY_FRAME;
+		else
+			flag = TTY_NORMAL;
+
+		tty_insert_flip_char(tport, ch, flag);
+	}
+
+	/* overrun is special, since it's reported immediately, and doesn't
+	 * affect the current character
+	 */
+	if (overrun)
+		tty_insert_flip_char(tport, 0, TTY_OVERRUN);
+
+	count--;
+	if (count <= 0) {
+		if (!tport->low_latency)
+			tty_flip_buffer_push(tport);
+		return;
+	}
+
+ignore_char:
+	push = 1;
+	goto try_again;
+
+not_break:
+	port->rx_brk = 0;
+	goto process_errors;
+}
+
+/*
+ * handle an interrupt from the serial transmission "virtual DMA" driver
+ * - note: the interrupt routine will disable its own interrupts when the Tx
+ *   buffer is empty
+ */
+static void mn10300_serial_transmit_interrupt(struct mn10300_serial_port *port)
+{
+	_enter("%s", port->name);
+
+	if (!port->uart.state || !port->uart.state->port.tty) {
+		mn10300_serial_dis_tx_intr(port);
+		return;
+	}
+
+	if (uart_tx_stopped(&port->uart) ||
+	    uart_circ_empty(&port->uart.state->xmit))
+		mn10300_serial_dis_tx_intr(port);
+
+	if (uart_circ_chars_pending(&port->uart.state->xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&port->uart);
+}
+
+/*
+ * deal with a change in the status of the CTS line
+ */
+static void mn10300_serial_cts_changed(struct mn10300_serial_port *port, u8 st)
+{
+	u16 ctr;
+
+	port->tx_cts = st;
+	port->uart.icount.cts++;
+
+	/* flip the CTS state selector flag to interrupt when it changes
+	 * back */
+	ctr = *port->_control;
+	ctr ^= SC2CTR_TWS;
+	*port->_control = ctr;
+
+	uart_handle_cts_change(&port->uart, st & SC2STR_CTS);
+	wake_up_interruptible(&port->uart.state->port.delta_msr_wait);
+}
+
+/*
+ * handle a virtual interrupt generated by the lower level "virtual DMA"
+ * routines (irq is the baud timer interrupt)
+ */
+static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id)
+{
+	struct mn10300_serial_port *port = dev_id;
+	u8 st;
+
+	spin_lock(&port->uart.lock);
+
+	if (port->intr_flags) {
+		_debug("INT %s: %x", port->name, port->intr_flags);
+
+		if (mask_test_and_clear(&port->intr_flags, MNSCx_RX_AVAIL))
+			mn10300_serial_receive_interrupt(port);
+
+		if (mask_test_and_clear(&port->intr_flags,
+					MNSCx_TX_SPACE | MNSCx_TX_EMPTY))
+			mn10300_serial_transmit_interrupt(port);
+	}
+
+	/* the only modem control line amongst the whole lot is CTS on
+	 * serial port 2 */
+	if (port->type == PORT_MN10300_CTS) {
+		st = *port->_status;
+		if ((port->tx_cts ^ st) & SC2STR_CTS)
+			mn10300_serial_cts_changed(port, st);
+	}
+
+	spin_unlock(&port->uart.lock);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * return indication of whether the hardware transmit buffer is empty
+ */
+static unsigned int mn10300_serial_tx_empty(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	_enter("%s", port->name);
+
+	return (*port->_status & (SC01STR_TXF | SC01STR_TBF)) ?
+		0 : TIOCSER_TEMT;
+}
+
+/*
+ * set the modem control lines (we don't have any)
+ */
+static void mn10300_serial_set_mctrl(struct uart_port *_port,
+				     unsigned int mctrl)
+{
+	struct mn10300_serial_port *port __attribute__ ((unused)) =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	_enter("%s,%x", port->name, mctrl);
+}
+
+/*
+ * get the modem control line statuses
+ */
+static unsigned int mn10300_serial_get_mctrl(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	_enter("%s", port->name);
+
+	if (port->type == PORT_MN10300_CTS && !(*port->_status & SC2STR_CTS))
+		return TIOCM_CAR | TIOCM_DSR;
+
+	return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR;
+}
+
+/*
+ * stop transmitting characters
+ */
+static void mn10300_serial_stop_tx(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	_enter("%s", port->name);
+
+	/* disable the virtual DMA */
+	mn10300_serial_dis_tx_intr(port);
+}
+
+/*
+ * start transmitting characters
+ * - jump-start transmission if it has stalled
+ *   - enable the serial Tx interrupt (used by the virtual DMA controller)
+ *   - force an interrupt to happen if necessary
+ */
+static void mn10300_serial_start_tx(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	_enter("%s{%lu}",
+	       port->name,
+	       CIRC_CNT(&port->uart.state->xmit.head,
+			&port->uart.state->xmit.tail,
+			UART_XMIT_SIZE));
+
+	/* kick the virtual DMA controller */
+	mn10300_serial_en_tx_intr(port);
+
+	_debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx",
+	       *port->_control, *port->_intr, *port->_status,
+	       *port->_tmxmd,
+	       (port->div_timer == MNSCx_DIV_TIMER_8BIT) ?
+	           *(volatile u8 *)port->_tmxbr : *port->_tmxbr,
+	       *port->tx_icr);
+}
+
+/*
+ * transmit a high-priority XON/XOFF character
+ */
+static void mn10300_serial_send_xchar(struct uart_port *_port, char ch)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+	unsigned long flags;
+
+	_enter("%s,%02x", port->name, ch);
+
+	if (likely(port->gdbstub)) {
+		port->tx_xchar = ch;
+		if (ch) {
+			spin_lock_irqsave(&port->uart.lock, flags);
+			mn10300_serial_en_tx_intr(port);
+			spin_unlock_irqrestore(&port->uart.lock, flags);
+		}
+	}
+}
+
+/*
+ * stop receiving characters
+ * - called whilst the port is being closed
+ */
+static void mn10300_serial_stop_rx(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	u16 ctr;
+
+	_enter("%s", port->name);
+
+	ctr = *port->_control;
+	ctr &= ~SC01CTR_RXE;
+	*port->_control = ctr;
+
+	mn10300_serial_dis_rx_intr(port);
+}
+
+/*
+ * enable modem status interrupts
+ */
+static void mn10300_serial_enable_ms(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	u16 ctr, cts;
+
+	_enter("%s", port->name);
+
+	if (port->type == PORT_MN10300_CTS) {
+		/* want to interrupt when CTS goes low if CTS is now high and
+		 * vice versa
+		 */
+		port->tx_cts = *port->_status;
+
+		cts = (port->tx_cts & SC2STR_CTS) ?
+			SC2CTR_TWE : SC2CTR_TWE | SC2CTR_TWS;
+
+		ctr = *port->_control;
+		ctr &= ~SC2CTR_TWS;
+		ctr |= cts;
+		*port->_control = ctr;
+
+		mn10300_serial_en_tx_intr(port);
+	}
+}
+
+/*
+ * transmit or cease transmitting a break signal
+ */
+static void mn10300_serial_break_ctl(struct uart_port *_port, int ctl)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+	unsigned long flags;
+
+	_enter("%s,%d", port->name, ctl);
+
+	spin_lock_irqsave(&port->uart.lock, flags);
+	if (ctl) {
+		/* tell the virtual DMA handler to assert BREAK */
+		port->tx_flags |= MNSCx_TX_BREAK;
+		mn10300_serial_en_tx_intr(port);
+	} else {
+		port->tx_flags &= ~MNSCx_TX_BREAK;
+		*port->_control &= ~SC01CTR_BKE;
+		mn10300_serial_en_tx_intr(port);
+	}
+	spin_unlock_irqrestore(&port->uart.lock, flags);
+}
+
+/*
+ * grab the interrupts and enable the port for reception
+ */
+static int mn10300_serial_startup(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+	struct mn10300_serial_int *pint;
+
+	_enter("%s{%d}", port->name, port->gdbstub);
+
+	if (unlikely(port->gdbstub))
+		return -EBUSY;
+
+	/* allocate an Rx buffer for the virtual DMA handler */
+	port->rx_buffer = kmalloc(MNSC_BUFFER_SIZE, GFP_KERNEL);
+	if (!port->rx_buffer)
+		return -ENOMEM;
+
+	port->rx_inp = port->rx_outp = 0;
+	port->tx_flags = 0;
+
+	/* finally, enable the device */
+	*port->_intr = SC01ICR_TI;
+	*port->_control |= SC01CTR_TXE | SC01CTR_RXE;
+
+	pint = &mn10300_serial_int_tbl[port->rx_irq];
+	pint->port = port;
+	pint->vdma = mn10300_serial_vdma_rx_handler;
+	pint = &mn10300_serial_int_tbl[port->tx_irq];
+	pint->port = port;
+	pint->vdma = mn10300_serial_vdma_tx_handler;
+
+	irq_set_chip(port->rx_irq, &mn10300_serial_low_pic);
+	irq_set_chip(port->tx_irq, &mn10300_serial_low_pic);
+	irq_set_chip(port->tm_irq, &mn10300_serial_pic);
+
+	if (request_irq(port->rx_irq, mn10300_serial_interrupt,
+			IRQF_NOBALANCING,
+			port->rx_name, port) < 0)
+		goto error;
+
+	if (request_irq(port->tx_irq, mn10300_serial_interrupt,
+			IRQF_NOBALANCING,
+			port->tx_name, port) < 0)
+		goto error2;
+
+	if (request_irq(port->tm_irq, mn10300_serial_interrupt,
+			IRQF_NOBALANCING,
+			port->tm_name, port) < 0)
+		goto error3;
+	mn10300_serial_mask_ack(port->tm_irq);
+
+	return 0;
+
+error3:
+	free_irq(port->tx_irq, port);
+error2:
+	free_irq(port->rx_irq, port);
+error:
+	kfree(port->rx_buffer);
+	port->rx_buffer = NULL;
+	return -EBUSY;
+}
+
+/*
+ * shutdown the port and release interrupts
+ */
+static void mn10300_serial_shutdown(struct uart_port *_port)
+{
+	unsigned long flags;
+	u16 x;
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	_enter("%s", port->name);
+
+	spin_lock_irqsave(&_port->lock, flags);
+	mn10300_serial_dis_tx_intr(port);
+
+	*port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
+	x = *port->rx_icr;
+	port->tx_flags = 0;
+	spin_unlock_irqrestore(&_port->lock, flags);
+
+	/* disable the serial port and its baud rate timer */
+	*port->_control &= ~(SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE);
+	*port->_tmxmd = 0;
+
+	if (port->rx_buffer) {
+		void *buf = port->rx_buffer;
+		port->rx_buffer = NULL;
+		kfree(buf);
+	}
+
+	/* disable all intrs */
+	free_irq(port->tm_irq, port);
+	free_irq(port->rx_irq, port);
+	free_irq(port->tx_irq, port);
+
+	mn10300_serial_int_tbl[port->tx_irq].port = NULL;
+	mn10300_serial_int_tbl[port->rx_irq].port = NULL;
+}
+
+/*
+ * this routine is called to set the UART divisor registers to match the
+ * specified baud rate for a serial port.
+ */
+static void mn10300_serial_change_speed(struct mn10300_serial_port *port,
+					  struct ktermios *new,
+					  struct ktermios *old)
+{
+	unsigned long flags;
+	unsigned long ioclk = port->ioclk;
+	unsigned cflag;
+	int baud, bits, xdiv, tmp;
+	u16 tmxbr, scxctr;
+	u8 tmxmd, battempt;
+	u8 div_timer = port->div_timer;
+
+	_enter("%s{%lu}", port->name, ioclk);
+
+	/* byte size and parity */
+	cflag = new->c_cflag;
+	switch (cflag & CSIZE) {
+	case CS7: scxctr = SC01CTR_CLN_7BIT; bits = 9;  break;
+	case CS8: scxctr = SC01CTR_CLN_8BIT; bits = 10; break;
+	default:  scxctr = SC01CTR_CLN_8BIT; bits = 10; break;
+	}
+
+	if (cflag & CSTOPB) {
+		scxctr |= SC01CTR_STB_2BIT;
+		bits++;
+	}
+
+	if (cflag & PARENB) {
+		bits++;
+		if (cflag & PARODD)
+			scxctr |= SC01CTR_PB_ODD;
+#ifdef CMSPAR
+		else if (cflag & CMSPAR)
+			scxctr |= SC01CTR_PB_FIXED0;
+#endif
+		else
+			scxctr |= SC01CTR_PB_EVEN;
+	}
+
+	/* Determine divisor based on baud rate */
+	battempt = 0;
+
+	switch (port->uart.line) {
+#ifdef CONFIG_MN10300_TTYSM0
+	case 0: /* ttySM0 */
+#if   defined(CONFIG_MN10300_TTYSM0_TIMER8)
+		scxctr |= SC0CTR_CK_TM8UFLOW_8;
+#elif defined(CONFIG_MN10300_TTYSM0_TIMER0)
+		scxctr |= SC0CTR_CK_TM0UFLOW_8;
+#elif defined(CONFIG_MN10300_TTYSM0_TIMER2)
+		scxctr |= SC0CTR_CK_TM2UFLOW_8;
+#else
+#error "Unknown config for ttySM0"
+#endif
+		break;
+#endif /* CONFIG_MN10300_TTYSM0 */
+
+#ifdef CONFIG_MN10300_TTYSM1
+	case 1: /* ttySM1 */
+#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
+#if   defined(CONFIG_MN10300_TTYSM1_TIMER9)
+		scxctr |= SC1CTR_CK_TM9UFLOW_8;
+#elif defined(CONFIG_MN10300_TTYSM1_TIMER3)
+		scxctr |= SC1CTR_CK_TM3UFLOW_8;
+#else
+#error "Unknown config for ttySM1"
+#endif
+#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+#if defined(CONFIG_MN10300_TTYSM1_TIMER12)
+		scxctr |= SC1CTR_CK_TM12UFLOW_8;
+#else
+#error "Unknown config for ttySM1"
+#endif
+#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+		break;
+#endif /* CONFIG_MN10300_TTYSM1 */
+
+#ifdef CONFIG_MN10300_TTYSM2
+	case 2: /* ttySM2 */
+#if defined(CONFIG_AM33_2)
+#if   defined(CONFIG_MN10300_TTYSM2_TIMER10)
+		scxctr |= SC2CTR_CK_TM10UFLOW;
+#else
+#error "Unknown config for ttySM2"
+#endif
+#else /* CONFIG_AM33_2 */
+#if   defined(CONFIG_MN10300_TTYSM2_TIMER9)
+		scxctr |= SC2CTR_CK_TM9UFLOW_8;
+#elif defined(CONFIG_MN10300_TTYSM2_TIMER1)
+		scxctr |= SC2CTR_CK_TM1UFLOW_8;
+#elif defined(CONFIG_MN10300_TTYSM2_TIMER3)
+		scxctr |= SC2CTR_CK_TM3UFLOW_8;
+#else
+#error "Unknown config for ttySM2"
+#endif
+#endif /* CONFIG_AM33_2 */
+		break;
+#endif /* CONFIG_MN10300_TTYSM2 */
+
+	default:
+		break;
+	}
+
+try_alternative:
+	baud = uart_get_baud_rate(&port->uart, new, old, 0,
+				  port->ioclk / 8);
+
+	_debug("ALT %d [baud %d]", battempt, baud);
+
+	if (!baud)
+		baud = 9600;	/* B0 transition handled in rs_set_termios */
+	xdiv = 1;
+	if (baud == 134) {
+		baud = 269;	/* 134 is really 134.5 */
+		xdiv = 2;
+	}
+
+	if (baud == 38400 &&
+	    (port->uart.flags & UPF_SPD_MASK) == UPF_SPD_CUST
+	    ) {
+		_debug("CUSTOM %u", port->uart.custom_divisor);
+
+		if (div_timer == MNSCx_DIV_TIMER_16BIT) {
+			if (port->uart.custom_divisor <= 65535) {
+				tmxmd = TM8MD_SRC_IOCLK;
+				tmxbr = port->uart.custom_divisor;
+				port->uart.uartclk = ioclk;
+				goto timer_okay;
+			}
+			if (port->uart.custom_divisor / 8 <= 65535) {
+				tmxmd = TM8MD_SRC_IOCLK_8;
+				tmxbr = port->uart.custom_divisor / 8;
+				port->uart.custom_divisor = tmxbr * 8;
+				port->uart.uartclk = ioclk / 8;
+				goto timer_okay;
+			}
+			if (port->uart.custom_divisor / 32 <= 65535) {
+				tmxmd = TM8MD_SRC_IOCLK_32;
+				tmxbr = port->uart.custom_divisor / 32;
+				port->uart.custom_divisor = tmxbr * 32;
+				port->uart.uartclk = ioclk / 32;
+				goto timer_okay;
+			}
+
+		} else if (div_timer == MNSCx_DIV_TIMER_8BIT) {
+			if (port->uart.custom_divisor <= 255) {
+				tmxmd = TM2MD_SRC_IOCLK;
+				tmxbr = port->uart.custom_divisor;
+				port->uart.uartclk = ioclk;
+				goto timer_okay;
+			}
+			if (port->uart.custom_divisor / 8 <= 255) {
+				tmxmd = TM2MD_SRC_IOCLK_8;
+				tmxbr = port->uart.custom_divisor / 8;
+				port->uart.custom_divisor = tmxbr * 8;
+				port->uart.uartclk = ioclk / 8;
+				goto timer_okay;
+			}
+			if (port->uart.custom_divisor / 32 <= 255) {
+				tmxmd = TM2MD_SRC_IOCLK_32;
+				tmxbr = port->uart.custom_divisor / 32;
+				port->uart.custom_divisor = tmxbr * 32;
+				port->uart.uartclk = ioclk / 32;
+				goto timer_okay;
+			}
+		}
+	}
+
+	switch (div_timer) {
+	case MNSCx_DIV_TIMER_16BIT:
+		port->uart.uartclk = ioclk;
+		tmxmd = TM8MD_SRC_IOCLK;
+		tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 65535)
+			goto timer_okay;
+
+		port->uart.uartclk = ioclk / 8;
+		tmxmd = TM8MD_SRC_IOCLK_8;
+		tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 65535)
+			goto timer_okay;
+
+		port->uart.uartclk = ioclk / 32;
+		tmxmd = TM8MD_SRC_IOCLK_32;
+		tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 65535)
+			goto timer_okay;
+		break;
+
+	case MNSCx_DIV_TIMER_8BIT:
+		port->uart.uartclk = ioclk;
+		tmxmd = TM2MD_SRC_IOCLK;
+		tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 255)
+			goto timer_okay;
+
+		port->uart.uartclk = ioclk / 8;
+		tmxmd = TM2MD_SRC_IOCLK_8;
+		tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 255)
+			goto timer_okay;
+
+		port->uart.uartclk = ioclk / 32;
+		tmxmd = TM2MD_SRC_IOCLK_32;
+		tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
+		if (tmp > 0 && tmp <= 255)
+			goto timer_okay;
+		break;
+
+	default:
+		BUG();
+		return;
+	}
+
+	/* refuse to change to a baud rate we can't support */
+	_debug("CAN'T SUPPORT");
+
+	switch (battempt) {
+	case 0:
+		if (old) {
+			new->c_cflag &= ~CBAUD;
+			new->c_cflag |= (old->c_cflag & CBAUD);
+			battempt = 1;
+			goto try_alternative;
+		}
+
+	case 1:
+		/* as a last resort, if the quotient is zero, default to 9600
+		 * bps */
+		new->c_cflag &= ~CBAUD;
+		new->c_cflag |= B9600;
+		battempt = 2;
+		goto try_alternative;
+
+	default:
+		/* hmmm... can't seem to support 9600 either
+		 * - we could try iterating through the speeds we know about to
+		 *   find the lowest
+		 */
+		new->c_cflag &= ~CBAUD;
+		new->c_cflag |= B0;
+
+		if (div_timer == MNSCx_DIV_TIMER_16BIT)
+			tmxmd = TM8MD_SRC_IOCLK_32;
+		else if (div_timer == MNSCx_DIV_TIMER_8BIT)
+			tmxmd = TM2MD_SRC_IOCLK_32;
+		tmxbr = 1;
+
+		port->uart.uartclk = ioclk / 32;
+		break;
+	}
+timer_okay:
+
+	_debug("UARTCLK: %u / %hu", port->uart.uartclk, tmxbr);
+
+	/* make the changes */
+	spin_lock_irqsave(&port->uart.lock, flags);
+
+	uart_update_timeout(&port->uart, new->c_cflag, baud);
+
+	/* set the timer to produce the required baud rate */
+	switch (div_timer) {
+	case MNSCx_DIV_TIMER_16BIT:
+		*port->_tmxmd = 0;
+		*port->_tmxbr = tmxbr;
+		*port->_tmxmd = TM8MD_INIT_COUNTER;
+		*port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE;
+		break;
+
+	case MNSCx_DIV_TIMER_8BIT:
+		*port->_tmxmd = 0;
+		*(volatile u8 *) port->_tmxbr = (u8) tmxbr;
+		*port->_tmxmd = TM2MD_INIT_COUNTER;
+		*port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE;
+		break;
+	}
+
+	/* CTS flow control flag and modem status interrupts */
+	scxctr &= ~(SC2CTR_TWE | SC2CTR_TWS);
+
+	if (port->type == PORT_MN10300_CTS && cflag & CRTSCTS) {
+		/* want to interrupt when CTS goes low if CTS is now
+		 * high and vice versa
+		 */
+		port->tx_cts = *port->_status;
+
+		if (port->tx_cts & SC2STR_CTS)
+			scxctr |= SC2CTR_TWE;
+		else
+			scxctr |= SC2CTR_TWE | SC2CTR_TWS;
+	}
+
+	/* set up parity check flag */
+	port->uart.read_status_mask = (1 << TTY_NORMAL) | (1 << TTY_OVERRUN);
+	if (new->c_iflag & INPCK)
+		port->uart.read_status_mask |=
+			(1 << TTY_PARITY) | (1 << TTY_FRAME);
+	if (new->c_iflag & (BRKINT | PARMRK))
+		port->uart.read_status_mask |= (1 << TTY_BREAK);
+
+	/* characters to ignore */
+	port->uart.ignore_status_mask = 0;
+	if (new->c_iflag & IGNPAR)
+		port->uart.ignore_status_mask |=
+			(1 << TTY_PARITY) | (1 << TTY_FRAME);
+	if (new->c_iflag & IGNBRK) {
+		port->uart.ignore_status_mask |= (1 << TTY_BREAK);
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns to (for real raw support).
+		 */
+		if (new->c_iflag & IGNPAR)
+			port->uart.ignore_status_mask |= (1 << TTY_OVERRUN);
+	}
+
+	/* Ignore all characters if CREAD is not set */
+	if ((new->c_cflag & CREAD) == 0)
+		port->uart.ignore_status_mask |= (1 << TTY_NORMAL);
+
+	scxctr |= SC01CTR_TXE | SC01CTR_RXE;
+	scxctr |= *port->_control & SC01CTR_BKE;
+	*port->_control = scxctr;
+
+	spin_unlock_irqrestore(&port->uart.lock, flags);
+}
+
+/*
+ * set the terminal I/O parameters
+ */
+static void mn10300_serial_set_termios(struct uart_port *_port,
+					 struct ktermios *new,
+					 struct ktermios *old)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	_enter("%s,%p,%p", port->name, new, old);
+
+	mn10300_serial_change_speed(port, new, old);
+
+	/* handle turning off CRTSCTS */
+	if (!(new->c_cflag & CRTSCTS)) {
+		u16 ctr = *port->_control;
+		ctr &= ~SC2CTR_TWE;
+		*port->_control = ctr;
+	}
+
+	/* change Transfer bit-order (LSB/MSB) */
+	if (new->c_cflag & CODMSB)
+		*port->_control |= SC01CTR_OD_MSBFIRST; /* MSB MODE */
+	else
+		*port->_control &= ~SC01CTR_OD_MSBFIRST; /* LSB MODE */
+}
+
+/*
+ * return description of port type
+ */
+static const char *mn10300_serial_type(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	if (port->uart.type == PORT_MN10300_CTS)
+		return "MN10300 SIF_CTS";
+
+	return "MN10300 SIF";
+}
+
+/*
+ * release I/O and memory regions in use by port
+ */
+static void mn10300_serial_release_port(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	_enter("%s", port->name);
+
+	release_mem_region((unsigned long) port->_iobase, 16);
+}
+
+/*
+ * request I/O and memory regions for port
+ */
+static int mn10300_serial_request_port(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	_enter("%s", port->name);
+
+	request_mem_region((unsigned long) port->_iobase, 16, port->name);
+	return 0;
+}
+
+/*
+ * configure the type and reserve the ports
+ */
+static void mn10300_serial_config_port(struct uart_port *_port, int type)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+
+	_enter("%s", port->name);
+
+	port->uart.type = PORT_MN10300;
+
+	if (port->options & MNSCx_OPT_CTS)
+		port->uart.type = PORT_MN10300_CTS;
+
+	mn10300_serial_request_port(_port);
+}
+
+/*
+ * verify serial parameters are suitable for this port type
+ */
+static int mn10300_serial_verify_port(struct uart_port *_port,
+					struct serial_struct *ss)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+	void *mapbase = (void *) (unsigned long) port->uart.mapbase;
+
+	_enter("%s", port->name);
+
+	/* these things may not be changed */
+	if (ss->irq		!= port->uart.irq	||
+	    ss->port		!= port->uart.iobase	||
+	    ss->io_type		!= port->uart.iotype	||
+	    ss->iomem_base	!= mapbase ||
+	    ss->iomem_reg_shift	!= port->uart.regshift	||
+	    ss->hub6		!= port->uart.hub6	||
+	    ss->xmit_fifo_size	!= port->uart.fifosize)
+		return -EINVAL;
+
+	/* type may be changed on a port that supports CTS */
+	if (ss->type != port->uart.type) {
+		if (!(port->options & MNSCx_OPT_CTS))
+			return -EINVAL;
+
+		if (ss->type != PORT_MN10300 &&
+		    ss->type != PORT_MN10300_CTS)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * initialise the MN10300 on-chip UARTs
+ */
+static int __init mn10300_serial_init(void)
+{
+	struct mn10300_serial_port *port;
+	int ret, i;
+
+	printk(KERN_INFO "%s version %s (%s)\n",
+	       serial_name, serial_version, serial_revdate);
+
+#if defined(CONFIG_MN10300_TTYSM2) && defined(CONFIG_AM33_2)
+	{
+		int tmp;
+		SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */
+		tmp = SC2TIM;
+	}
+#endif
+
+	set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL),
+		mn10300_serial_vdma_interrupt);
+
+	ret = uart_register_driver(&mn10300_serial_driver);
+	if (!ret) {
+		for (i = 0 ; i < NR_PORTS ; i++) {
+			port = mn10300_serial_ports[i];
+			if (!port || port->gdbstub)
+				continue;
+
+			switch (port->clock_src) {
+			case MNSCx_CLOCK_SRC_IOCLK:
+				port->ioclk = MN10300_IOCLK;
+				break;
+
+#ifdef MN10300_IOBCLK
+			case MNSCx_CLOCK_SRC_IOBCLK:
+				port->ioclk = MN10300_IOBCLK;
+				break;
+#endif
+			default:
+				BUG();
+			}
+
+			ret = uart_add_one_port(&mn10300_serial_driver,
+						&port->uart);
+
+			if (ret < 0) {
+				_debug("ERROR %d", -ret);
+				break;
+			}
+		}
+
+		if (ret)
+			uart_unregister_driver(&mn10300_serial_driver);
+	}
+
+	return ret;
+}
+
+__initcall(mn10300_serial_init);
+
+
+#ifdef CONFIG_MN10300_TTYSM_CONSOLE
+
+/*
+ * print a string to the serial port without disturbing the real user of the
+ * port too much
+ * - the console must be locked by the caller
+ */
+static void mn10300_serial_console_write(struct console *co,
+					   const char *s, unsigned count)
+{
+	struct mn10300_serial_port *port;
+	unsigned i;
+	u16 scxctr;
+	u8 tmxmd;
+	unsigned long flags;
+	int locked = 1;
+
+	port = mn10300_serial_ports[co->index];
+
+	local_irq_save(flags);
+	if (port->uart.sysrq) {
+		/* mn10300_serial_interrupt() already took the lock */
+		locked = 0;
+	} else if (oops_in_progress) {
+		locked = spin_trylock(&port->uart.lock);
+	} else
+		spin_lock(&port->uart.lock);
+
+	/* firstly hijack the serial port from the "virtual DMA" controller */
+	mn10300_serial_dis_tx_intr(port);
+
+	/* the transmitter may be disabled */
+	scxctr = *port->_control;
+	if (!(scxctr & SC01CTR_TXE)) {
+		/* restart the UART clock */
+		tmxmd = *port->_tmxmd;
+
+		switch (port->div_timer) {
+		case MNSCx_DIV_TIMER_16BIT:
+			*port->_tmxmd = 0;
+			*port->_tmxmd = TM8MD_INIT_COUNTER;
+			*port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE;
+			break;
+
+		case MNSCx_DIV_TIMER_8BIT:
+			*port->_tmxmd = 0;
+			*port->_tmxmd = TM2MD_INIT_COUNTER;
+			*port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE;
+			break;
+		}
+
+		/* enable the transmitter */
+		*port->_control = (scxctr & ~SC01CTR_BKE) | SC01CTR_TXE;
+
+	} else if (scxctr & SC01CTR_BKE) {
+		/* stop transmitting BREAK */
+		*port->_control = (scxctr & ~SC01CTR_BKE);
+	}
+
+	/* send the chars into the serial port (with LF -> LFCR conversion) */
+	for (i = 0; i < count; i++) {
+		char ch = *s++;
+
+		while (*port->_status & SC01STR_TBF)
+			continue;
+		*port->_txb = ch;
+
+		if (ch == 0x0a) {
+			while (*port->_status & SC01STR_TBF)
+				continue;
+			*port->_txb = 0xd;
+		}
+	}
+
+	/* can't let the transmitter be turned off if it's actually
+	 * transmitting */
+	while (*port->_status & (SC01STR_TXF | SC01STR_TBF))
+		continue;
+
+	/* disable the transmitter if we re-enabled it */
+	if (!(scxctr & SC01CTR_TXE))
+		*port->_control = scxctr;
+
+	mn10300_serial_en_tx_intr(port);
+
+	if (locked)
+		spin_unlock(&port->uart.lock);
+	local_irq_restore(flags);
+}
+
+/*
+ * set up a serial port as a console
+ * - construct a cflag setting for the first rs_open()
+ * - initialize the serial port
+ * - return non-zero if we didn't find a serial port.
+ */
+static int __init mn10300_serial_console_setup(struct console *co,
+						 char *options)
+{
+	struct mn10300_serial_port *port;
+	int i, parity = 'n', baud = 9600, bits = 8, flow = 0;
+
+	for (i = 0 ; i < NR_PORTS ; i++) {
+		port = mn10300_serial_ports[i];
+		if (port && !port->gdbstub && port->uart.line == co->index)
+			goto found_device;
+	}
+
+	return -ENODEV;
+
+found_device:
+	switch (port->clock_src) {
+	case MNSCx_CLOCK_SRC_IOCLK:
+		port->ioclk = MN10300_IOCLK;
+		break;
+
+#ifdef MN10300_IOBCLK
+	case MNSCx_CLOCK_SRC_IOBCLK:
+		port->ioclk = MN10300_IOBCLK;
+		break;
+#endif
+	default:
+		BUG();
+	}
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(&port->uart, co, baud, parity, bits, flow);
+}
+
+/*
+ * register console
+ */
+static int __init mn10300_serial_console_init(void)
+{
+	register_console(&mn10300_serial_console);
+	return 0;
+}
+
+console_initcall(mn10300_serial_console_init);
+#endif
+
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Polled character reception for the kernel debugger
+ */
+static int mn10300_serial_poll_get_char(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+	unsigned ix;
+	u8 st, ch;
+
+	_enter("%s", port->name);
+
+	if (mn10300_serial_int_tbl[port->rx_irq].port != NULL) {
+		do {
+			/* pull chars out of the hat */
+			ix = ACCESS_ONCE(port->rx_outp);
+			if (CIRC_CNT(port->rx_inp, ix, MNSC_BUFFER_SIZE) == 0)
+				return NO_POLL_CHAR;
+
+			smp_read_barrier_depends();
+			ch = port->rx_buffer[ix++];
+			st = port->rx_buffer[ix++];
+			smp_mb();
+			port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
+
+		} while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF));
+	} else {
+		do {
+			st = *port->_status;
+			if (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF))
+				continue;
+		} while (!(st & SC01STR_RBF));
+
+		ch = *port->_rxb;
+	}
+
+	return ch;
+}
+
+
+/*
+ * Polled character transmission for the kernel debugger
+ */
+static void mn10300_serial_poll_put_char(struct uart_port *_port,
+					 unsigned char ch)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+	u8 intr, tmp;
+
+	/* wait for the transmitter to finish anything it might be doing (and
+	 * this includes the virtual DMA handler, so it might take a while) */
+	while (*port->_status & (SC01STR_TBF | SC01STR_TXF))
+		continue;
+
+	/* disable the Tx ready interrupt */
+	intr = *port->_intr;
+	*port->_intr = intr & ~SC01ICR_TI;
+	tmp = *port->_intr;
+
+	if (ch == 0x0a) {
+		*port->_txb = 0x0d;
+		while (*port->_status & SC01STR_TBF)
+			continue;
+	}
+
+	*port->_txb = ch;
+	while (*port->_status & SC01STR_TBF)
+		continue;
+
+	/* restore the Tx interrupt flag */
+	*port->_intr = intr;
+	tmp = *port->_intr;
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
diff --git a/arch/mn10300/kernel/mn10300-serial.h b/arch/mn10300/kernel/mn10300-serial.h
new file mode 100644
index 0000000..01791c6
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-serial.h
@@ -0,0 +1,130 @@
+/* MN10300 On-chip serial port driver definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _MN10300_SERIAL_H
+#define _MN10300_SERIAL_H
+
+#ifndef __ASSEMBLY__
+#include <linux/serial_core.h>
+#include <linux/termios.h>
+#endif
+
+#include <asm/page.h>
+#include <asm/serial-regs.h>
+
+#define NR_PORTS		3		/* should be set 3 or 9 or 16 */
+
+#define MNSC_BUFFER_SIZE	+(PAGE_SIZE / 2)
+
+/* intr_flags bits */
+#define MNSCx_RX_AVAIL		0x01
+#define MNSCx_RX_OVERF		0x02
+#define MNSCx_TX_SPACE		0x04
+#define MNSCx_TX_EMPTY		0x08
+
+/* tx_flags bits */
+#define MNSCx_TX_BREAK		0x01
+#define MNSCx_TX_STOP		0x02
+
+#ifndef __ASSEMBLY__
+
+struct mn10300_serial_port {
+	char			*rx_buffer;	/* reception buffer base */
+	unsigned		rx_inp;		/* pointer to rx input offset */
+	unsigned		rx_outp;	/* pointer to rx output offset */
+	u8			tx_xchar;	/* high-priority XON/XOFF buffer */
+	u8			tx_flags;	/* transmit break/stop request */
+	u8			intr_flags;	/* interrupt flags */
+	volatile u16		*rx_icr;	/* Rx interrupt control register */
+	volatile u16		*tx_icr;	/* Tx interrupt control register */
+	int			rx_irq;		/* reception IRQ */
+	int			tx_irq;		/* transmission IRQ */
+	int			tm_irq;		/* timer IRQ */
+
+	const char		*name;		/* name of serial port */
+	const char		*rx_name;	/* Rx interrupt handler name of serial port */
+	const char		*tx_name;	/* Tx interrupt handler name of serial port */
+	const char		*tm_name;	/* Timer interrupt handler name */
+	unsigned short		type;		/* type of serial port */
+	unsigned char		isconsole;	/* T if it's a console */
+	volatile void		*_iobase;	/* pointer to base of I/O control regs */
+	volatile u16		*_control;	/* control register pointer */
+	volatile u8		*_status;	/* status register pointer */
+	volatile u8		*_intr;		/* interrupt register pointer */
+	volatile u8		*_rxb;		/* receive buffer register pointer */
+	volatile u8		*_txb;		/* transmit buffer register pointer */
+	volatile u16		*_tmicr;	/* timer interrupt control register */
+	volatile u8		*_tmxmd;	/* baud rate timer mode register */
+	volatile u16		*_tmxbr;	/* baud rate timer base register */
+
+	/* this must come down here so that assembly can use BSET to access the
+	 * above fields */
+	struct uart_port	uart;
+
+	unsigned short		rx_brk;		/* current break reception status */
+	u16			tx_cts;		/* current CTS status */
+	int			gdbstub;	/* preemptively stolen by GDB stub */
+
+	u8			clock_src;	/* clock source */
+#define MNSCx_CLOCK_SRC_IOCLK	0
+#define MNSCx_CLOCK_SRC_IOBCLK	1
+
+	u8			div_timer;	/* timer used as divisor */
+#define MNSCx_DIV_TIMER_16BIT	0
+#define MNSCx_DIV_TIMER_8BIT	1
+
+	u16			options;	/* options */
+#define MNSCx_OPT_CTS		0x0001
+
+	unsigned long		ioclk;		/* base clock rate */
+};
+
+#ifdef CONFIG_MN10300_TTYSM0
+extern struct mn10300_serial_port mn10300_serial_port_sif0;
+#endif
+
+#ifdef CONFIG_MN10300_TTYSM1
+extern struct mn10300_serial_port mn10300_serial_port_sif1;
+#endif
+
+#ifdef CONFIG_MN10300_TTYSM2
+extern struct mn10300_serial_port mn10300_serial_port_sif2;
+#endif
+
+extern struct mn10300_serial_port *mn10300_serial_ports[];
+
+struct mn10300_serial_int {
+	struct mn10300_serial_port *port;
+	asmlinkage void (*vdma)(void);
+};
+
+extern struct mn10300_serial_int mn10300_serial_int_tbl[];
+
+extern asmlinkage void mn10300_serial_vdma_interrupt(void);
+extern asmlinkage void mn10300_serial_vdma_rx_handler(void);
+extern asmlinkage void mn10300_serial_vdma_tx_handler(void);
+
+#endif /* __ASSEMBLY__ */
+
+#if defined(CONFIG_GDBSTUB_ON_TTYSM0)
+#define SCgSTR SC0STR
+#define SCgRXB SC0RXB
+#define SCgRXIRQ SC0RXIRQ
+#elif defined(CONFIG_GDBSTUB_ON_TTYSM1)
+#define SCgSTR SC1STR
+#define SCgRXB SC1RXB
+#define SCgRXIRQ SC1RXIRQ
+#elif defined(CONFIG_GDBSTUB_ON_TTYSM2)
+#define SCgSTR SC2STR
+#define SCgRXB SC2RXB
+#define SCgRXIRQ SC2RXIRQ
+#endif
+
+#endif /* _MN10300_SERIAL_H */
diff --git a/arch/mn10300/kernel/mn10300-watchdog-low.S b/arch/mn10300/kernel/mn10300-watchdog-low.S
new file mode 100644
index 0000000..f2f5c9c
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-watchdog-low.S
@@ -0,0 +1,66 @@
+###############################################################################
+#
+# MN10300 Watchdog interrupt handler
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/intctl-regs.h>
+#include <asm/timer-regs.h>
+#include <asm/frame.inc>
+#include <linux/threads.h>
+
+	.text
+
+###############################################################################
+#
+# Watchdog handler entry point
+# - special non-maskable interrupt
+#
+###############################################################################
+	.globl	watchdog_handler
+	.type	watchdog_handler,@function
+watchdog_handler:
+	add	-4,sp
+	SAVE_ALL
+
+	mov	0xffffffff,d0
+	mov	d0,(REG_ORIG_D0,fp)
+
+	mov	fp,d0
+	lsr	2,d1
+	call	watchdog_interrupt[],0		# watchdog_interrupt(regs,irq)
+
+	jmp	ret_from_intr
+
+	.size	watchdog_handler,.-watchdog_handler
+
+###############################################################################
+#
+# Watchdog touch entry point
+# - kept to absolute minimum (unfortunately, it's prototyped in linux/nmi.h so
+#   we can't inline it)
+#
+###############################################################################
+	.globl	touch_nmi_watchdog
+	.type	touch_nmi_watchdog,@function
+touch_nmi_watchdog:
+	clr	d0
+	clr	d1
+	mov	watchdog_alert_counter, a0
+	setlb
+	mov	d0, (a0+)
+	inc	d1
+	cmp	NR_CPUS, d1
+	lne
+	ret	[],0
+
+	.size	touch_nmi_watchdog,.-touch_nmi_watchdog
diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c
new file mode 100644
index 0000000..a2d8e69
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-watchdog.c
@@ -0,0 +1,205 @@
+/* MN10300 Watchdog timer
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from arch/i386/kernel/nmi.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/nmi.h>
+#include <asm/processor.h>
+#include <linux/atomic.h>
+#include <asm/intctl-regs.h>
+#include <asm/rtc-regs.h>
+#include <asm/div64.h>
+#include <asm/smp.h>
+#include <asm/gdb-stub.h>
+#include <proc/clock.h>
+
+static DEFINE_SPINLOCK(watchdog_print_lock);
+static unsigned int watchdog;
+static unsigned int watchdog_hz = 1;
+unsigned int watchdog_alert_counter[NR_CPUS];
+
+EXPORT_SYMBOL(touch_nmi_watchdog);
+
+/*
+ * the best way to detect whether a CPU has a 'hard lockup' problem
+ * is to check its timer makes IRQ counts. If they are not
+ * changing then that CPU has some problem.
+ *
+ * since NMIs dont listen to _any_ locks, we have to be extremely
+ * careful not to rely on unsafe variables. The printk might lock
+ * up though, so we have to break up any console locks first ...
+ * [when there will be more tty-related locks, break them up
+ *  here too!]
+ */
+static unsigned int last_irq_sums[NR_CPUS];
+
+int __init check_watchdog(void)
+{
+	irq_cpustat_t tmp[1];
+
+	printk(KERN_INFO "Testing Watchdog... ");
+
+	memcpy(tmp, irq_stat, sizeof(tmp));
+	local_irq_enable();
+	mdelay((10 * 1000) / watchdog_hz); /* wait 10 ticks */
+	local_irq_disable();
+
+	if (nmi_count(0) - tmp[0].__nmi_count <= 5) {
+		printk(KERN_WARNING "CPU#%d: Watchdog appears to be stuck!\n",
+		       0);
+		return -1;
+	}
+
+	printk(KERN_INFO "OK.\n");
+
+	/* now that we know it works we can reduce NMI frequency to something
+	 * more reasonable; makes a difference in some configs
+	 */
+	watchdog_hz = 1;
+
+	return 0;
+}
+
+static int __init setup_watchdog(char *str)
+{
+	unsigned tmp;
+	int opt;
+	u8 ctr;
+
+	get_option(&str, &opt);
+	if (opt != 1)
+		return 0;
+
+	watchdog = opt;
+	if (watchdog) {
+		set_intr_stub(EXCEP_WDT, watchdog_handler);
+		ctr = WDCTR_WDCK_65536th;
+		WDCTR = WDCTR_WDRST | ctr;
+		WDCTR = ctr;
+		tmp = WDCTR;
+
+		tmp = __muldiv64u(1 << (16 + ctr * 2), 1000000, MN10300_WDCLK);
+		tmp = 1000000000 / tmp;
+		watchdog_hz = (tmp + 500) / 1000;
+	}
+
+	return 1;
+}
+
+__setup("watchdog=", setup_watchdog);
+
+void __init watchdog_go(void)
+{
+	u8 wdt;
+
+	if (watchdog) {
+		printk(KERN_INFO "Watchdog: running at %uHz\n", watchdog_hz);
+		wdt = WDCTR & ~WDCTR_WDCNE;
+		WDCTR = wdt | WDCTR_WDRST;
+		wdt = WDCTR;
+		WDCTR = wdt | WDCTR_WDCNE;
+		wdt = WDCTR;
+
+		check_watchdog();
+	}
+}
+
+#ifdef CONFIG_SMP
+static void watchdog_dump_register(void *dummy)
+{
+	printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID);
+	show_registers(current_frame());
+}
+#endif
+
+asmlinkage
+void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep)
+{
+	/*
+	 * Since current-> is always on the stack, and we always switch
+	 * the stack NMI-atomically, it's safe to use smp_processor_id().
+	 */
+	int sum, cpu;
+	int irq = NMIIRQ;
+	u8 wdt, tmp;
+
+	wdt = WDCTR & ~WDCTR_WDCNE;
+	WDCTR = wdt;
+	tmp = WDCTR;
+	NMICR = NMICR_WDIF;
+
+	nmi_count(smp_processor_id())++;
+	kstat_incr_irq_this_cpu(irq);
+
+	for_each_online_cpu(cpu) {
+
+		sum = irq_stat[cpu].__irq_count;
+
+		if ((last_irq_sums[cpu] == sum)
+#if defined(CONFIG_GDBSTUB) && defined(CONFIG_SMP)
+			&& !(CHK_GDBSTUB_BUSY()
+			     || atomic_read(&cpu_doing_single_step))
+#endif
+			) {
+			/*
+			 * Ayiee, looks like this CPU is stuck ...
+			 * wait a few IRQs (5 seconds) before doing the oops ...
+			 */
+			watchdog_alert_counter[cpu]++;
+			if (watchdog_alert_counter[cpu] == 5 * watchdog_hz) {
+				spin_lock(&watchdog_print_lock);
+				/*
+				 * We are in trouble anyway, lets at least try
+				 * to get a message out.
+				 */
+				bust_spinlocks(1);
+				printk(KERN_ERR
+				       "NMI Watchdog detected LOCKUP on CPU%d,"
+				       " pc %08lx, registers:\n",
+				       cpu, regs->pc);
+#ifdef CONFIG_SMP
+				printk(KERN_ERR
+				       "--- Register Dump (CPU%d) ---\n",
+				       CPUID);
+#endif
+				show_registers(regs);
+#ifdef CONFIG_SMP
+				smp_nmi_call_function(watchdog_dump_register,
+					NULL, 1);
+#endif
+				printk(KERN_NOTICE "console shuts up ...\n");
+				console_silent();
+				spin_unlock(&watchdog_print_lock);
+				bust_spinlocks(0);
+#ifdef CONFIG_GDBSTUB
+				if (CHK_GDBSTUB_BUSY_AND_ACTIVE())
+					gdbstub_exception(regs, excep);
+				else
+					gdbstub_intercept(regs, excep);
+#endif
+				do_exit(SIGSEGV);
+			}
+		} else {
+			last_irq_sums[cpu] = sum;
+			watchdog_alert_counter[cpu] = 0;
+		}
+	}
+
+	WDCTR = wdt | WDCTR_WDRST;
+	tmp = WDCTR;
+	WDCTR = wdt | WDCTR_WDCNE;
+	tmp = WDCTR;
+}
diff --git a/arch/mn10300/kernel/mn10300_ksyms.c b/arch/mn10300/kernel/mn10300_ksyms.c
new file mode 100644
index 0000000..f9eb975
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300_ksyms.c
@@ -0,0 +1,42 @@
+/* MN10300 Miscellaneous and library kernel exports
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+
+EXPORT_SYMBOL(empty_zero_page);
+
+EXPORT_SYMBOL(change_bit);
+EXPORT_SYMBOL(test_and_change_bit);
+
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memset);
+
+EXPORT_SYMBOL(strncpy_from_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(clear_user);
+EXPORT_SYMBOL(__clear_user);
+EXPORT_SYMBOL(__generic_copy_from_user);
+EXPORT_SYMBOL(__generic_copy_to_user);
+EXPORT_SYMBOL(strnlen_user);
+
+extern u64 __ashrdi3(u64, unsigned);
+extern u64 __ashldi3(u64, unsigned);
+extern u64 __lshrdi3(u64, unsigned);
+extern s64 __negdi2(s64);
+extern int __ucmpdi2(u64, u64);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__negdi2);
+EXPORT_SYMBOL(__ucmpdi2);
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c
new file mode 100644
index 0000000..216ad23
--- /dev/null
+++ b/arch/mn10300/kernel/module.c
@@ -0,0 +1,156 @@
+/* MN10300 Kernel module helper routines
+ *
+ * Copyright (C) 2007, 2008, 2009 Red Hat, Inc. All Rights Reserved.
+ * Written by Mark Salter (msalter@redhat.com)
+ * - Derived from arch/i386/kernel/module.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public Licence as published by
+ * the Free Software Foundation; either version 2 of the Licence, or
+ * (at your option) any later version.
+ *
+ * This program 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 Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public Licence
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt, ...)
+#endif
+
+static void reloc_put16(uint8_t *p, uint32_t val)
+{
+	p[0] = val & 0xff;
+	p[1] = (val >> 8) & 0xff;
+}
+
+static void reloc_put24(uint8_t *p, uint32_t val)
+{
+	reloc_put16(p, val);
+	p[2] = (val >> 16) & 0xff;
+}
+
+static void reloc_put32(uint8_t *p, uint32_t val)
+{
+	reloc_put16(p, val);
+	reloc_put16(p+2, val >> 16);
+}
+
+/*
+ * apply a RELA relocation
+ */
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+	unsigned int i, sym_diff_seen = 0;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	Elf32_Addr relocation, sym_diff_val = 0;
+	uint8_t *location;
+	uint32_t value;
+
+	DEBUGP("Applying relocate section %u to %u\n",
+	       relsec, sechdrs[relsec].sh_info);
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* this is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+
+		/* this is the symbol the relocation is referring to (note that
+		 * all undefined symbols have been resolved by the caller) */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+
+		/* this is the adjustment to be made */
+		relocation = sym->st_value + rel[i].r_addend;
+
+		if (sym_diff_seen) {
+			switch (ELF32_R_TYPE(rel[i].r_info)) {
+			case R_MN10300_32:
+			case R_MN10300_24:
+			case R_MN10300_16:
+			case R_MN10300_8:
+				relocation -= sym_diff_val;
+				sym_diff_seen = 0;
+				break;
+			default:
+				printk(KERN_ERR "module %s: Unexpected SYM_DIFF relocation: %u\n",
+				       me->name, ELF32_R_TYPE(rel[i].r_info));
+				return -ENOEXEC;
+			}
+		}
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+			/* for the first four relocation types, we simply
+			 * store the adjustment at the location given */
+		case R_MN10300_32:
+			reloc_put32(location, relocation);
+			break;
+		case R_MN10300_24:
+			reloc_put24(location, relocation);
+			break;
+		case R_MN10300_16:
+			reloc_put16(location, relocation);
+			break;
+		case R_MN10300_8:
+			*location = relocation;
+			break;
+
+			/* for the next three relocation types, we write the
+			 * adjustment with the address subtracted over the
+			 * value at the location given */
+		case R_MN10300_PCREL32:
+			value = relocation - (uint32_t) location;
+			reloc_put32(location, value);
+			break;
+		case R_MN10300_PCREL16:
+			value = relocation - (uint32_t) location;
+			reloc_put16(location, value);
+			break;
+		case R_MN10300_PCREL8:
+			*location = relocation - (uint32_t) location;
+			break;
+
+		case R_MN10300_SYM_DIFF:
+			/* This is used to adjust the next reloc as required
+			 * by relaxation. */
+			sym_diff_seen = 1;
+			sym_diff_val = sym->st_value;
+			break;
+
+		case R_MN10300_ALIGN:
+			/* Just ignore the ALIGN relocs.
+			 * Only interesting if kernel performed relaxation. */
+			continue;
+
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	if (sym_diff_seen) {
+		printk(KERN_ERR "module %s: Nothing follows SYM_DIFF relocation: %u\n",
+				       me->name, ELF32_R_TYPE(rel[i].r_info));
+		return -ENOEXEC;
+	}
+	return 0;
+}
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
new file mode 100644
index 0000000..3707da5
--- /dev/null
+++ b/arch/mn10300/kernel/process.c
@@ -0,0 +1,192 @@
+/* MN10300  Process handling code
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/percpu.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/rcupdate.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/mmu_context.h>
+#include <asm/fpu.h>
+#include <asm/reset-regs.h>
+#include <asm/gdb-stub.h>
+#include "internal.h"
+
+/*
+ * return saved PC of a blocked thread.
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+	return ((unsigned long *) tsk->thread.sp)[3];
+}
+
+/*
+ * power off function, if any
+ */
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
+/*
+ * On SMP it's slightly faster (but much more power-consuming!)
+ * to poll the ->work.need_resched flag instead of waiting for the
+ * cross-CPU IPI to arrive. Use this option with caution.
+ *
+ * tglx: No idea why this depends on HOTPLUG_CPU !?!
+ */
+#if !defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU)
+void arch_cpu_idle(void)
+{
+	safe_halt();
+}
+#endif
+
+void release_segments(struct mm_struct *mm)
+{
+}
+
+void machine_restart(char *cmd)
+{
+#ifdef CONFIG_KERNEL_DEBUGGER
+	gdbstub_exit(0);
+#endif
+
+#ifdef mn10300_unit_hard_reset
+	mn10300_unit_hard_reset();
+#else
+	mn10300_proc_hard_reset();
+#endif
+}
+
+void machine_halt(void)
+{
+#ifdef CONFIG_KERNEL_DEBUGGER
+	gdbstub_exit(0);
+#endif
+}
+
+void machine_power_off(void)
+{
+#ifdef CONFIG_KERNEL_DEBUGGER
+	gdbstub_exit(0);
+#endif
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	show_regs_print_info(KERN_DEFAULT);
+}
+
+/*
+ * free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+	exit_fpu();
+}
+
+void flush_thread(void)
+{
+	flush_fpu();
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * we do not have to muck with descriptors here, that is
+ * done in switch_mm() as needed.
+ */
+void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
+{
+}
+
+/*
+ * this gets called so that we can store lazy state into memory and copy the
+ * current task into the new thread.
+ */
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
+{
+	unlazy_fpu(src);
+	*dst = *src;
+	return 0;
+}
+
+/*
+ * set up the kernel stack for a new thread and copy arch-specific thread
+ * control information
+ */
+int copy_thread(unsigned long clone_flags,
+		unsigned long c_usp, unsigned long ustk_size,
+		struct task_struct *p)
+{
+	struct thread_info *ti = task_thread_info(p);
+	struct pt_regs *c_regs;
+	unsigned long c_ksp;
+
+	c_ksp = (unsigned long) task_stack_page(p) + THREAD_SIZE;
+
+	/* allocate the userspace exception frame and set it up */
+	c_ksp -= sizeof(struct pt_regs);
+	c_regs = (struct pt_regs *) c_ksp;
+	c_ksp -= 12; /* allocate function call ABI slack */
+
+	/* set up things up so the scheduler can start the new task */
+	p->thread.uregs = c_regs;
+	ti->frame	= c_regs;
+	p->thread.a3	= (unsigned long) c_regs;
+	p->thread.sp	= c_ksp;
+	p->thread.wchan	= p->thread.pc;
+	p->thread.usp	= c_usp;
+
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(c_regs, 0, sizeof(struct pt_regs));
+		c_regs->a0 = c_usp; /* function */
+		c_regs->d0 = ustk_size; /* argument */
+		local_save_flags(c_regs->epsw);
+		c_regs->epsw |= EPSW_IE | EPSW_IM_7;
+		p->thread.pc	= (unsigned long) ret_from_kernel_thread;
+		return 0;
+	}
+	*c_regs = *current_pt_regs();
+	if (c_usp)
+		c_regs->sp = c_usp;
+	c_regs->epsw &= ~EPSW_FE; /* my FPU */
+
+	/* the new TLS pointer is passed in as arg #5 to sys_clone() */
+	if (clone_flags & CLONE_SETTLS)
+		c_regs->e2 = current_frame()->d3;
+
+	p->thread.pc	= (unsigned long) ret_from_fork;
+
+	return 0;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	return p->thread.wchan;
+}
diff --git a/arch/mn10300/kernel/profile-low.S b/arch/mn10300/kernel/profile-low.S
new file mode 100644
index 0000000..94ffac1
--- /dev/null
+++ b/arch/mn10300/kernel/profile-low.S
@@ -0,0 +1,72 @@
+###############################################################################
+#
+# Fast profiling interrupt handler
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/smp.h>
+#include <asm/intctl-regs.h>
+#include <asm/timer-regs.h>
+
+#define pi break
+
+	.balign	4
+counter:
+	.long	-1
+
+###############################################################################
+#
+# Profiling interrupt entry point
+# - intended to run at interrupt priority 1
+#
+###############################################################################
+ENTRY(profile_handler)
+	movm	[d2,d3,a2],(sp)
+
+	# ignore userspace
+	mov	(12,sp),d2
+	and	EPSW_nSL,d2
+	bne	out
+
+	# do nothing if there's no buffer
+	mov	(prof_buffer),a2
+	and	a2,a2
+	beq	out
+	or	0x20000000,a2
+
+	# calculate relative position in text segment
+	mov	(16,sp),d2
+	sub	_stext,d2
+	mov	(prof_shift),d3
+	lsr	d3,d2
+	mov	(prof_len),d3
+	cmp	d3,d2
+	bcc	outside_text
+
+	# increment the appropriate profile bucket
+do_inc:
+	asl2	d2
+	mov	(a2,d2),d3
+	inc	d3
+	mov	d3,(a2,d2)
+out:
+	mov	GxICR_DETECT,d2
+	movbu	d2,(TM11ICR)		# ACK the interrupt
+	movbu	(TM11ICR),d2
+	movm	(sp),[d2,d3,a2]
+	rti
+
+outside_text:
+	sub	1,d3
+	mov	d3,d2
+	bra	do_inc
diff --git a/arch/mn10300/kernel/profile.c b/arch/mn10300/kernel/profile.c
new file mode 100644
index 0000000..4f342f7
--- /dev/null
+++ b/arch/mn10300/kernel/profile.c
@@ -0,0 +1,51 @@
+/* MN10300 Profiling setup
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+/*
+ * initialise the profiling if enabled
+ * - using with gdbstub will give anomalous results
+ * - can't be used with gdbstub if running at IRQ priority 0
+ */
+static __init int profile_init(void)
+{
+	u16 tmp;
+
+	if (!prof_buffer)
+		return 0;
+
+	/* use timer 11 to drive the profiling interrupts */
+	set_intr_stub(EXCEP_IRQ_LEVEL0, profile_handler);
+
+	/* set IRQ priority at which to run */
+	set_intr_level(TM11IRQ, GxICR_LEVEL_0);
+
+	/* set up timer 11
+	 * - source: (IOCLK 33MHz)*2 = 66MHz
+	 * - frequency: (33330000*2) / 8 / 20625 = 202Hz
+	 */
+	TM11BR = 20625 - 1;
+	TM11MD = TM8MD_SRC_IOCLK_8;
+	TM11MD |= TM8MD_INIT_COUNTER;
+	TM11MD &= ~TM8MD_INIT_COUNTER;
+	TM11MD |= TM8MD_COUNT_ENABLE;
+
+	TM11ICR |= GxICR_ENABLE;
+	tmp = TM11ICR;
+
+	printk(KERN_INFO "Profiling initiated on timer 11, priority 0, %uHz\n",
+	       MN10300_IOCLK / 8 / (TM11BR + 1));
+	printk(KERN_INFO "Profile histogram stored %p-%p\n",
+	       prof_buffer, (u8 *)(prof_buffer + prof_len) - 1);
+
+	return 0;
+}
+
+__initcall(profile_init);
diff --git a/arch/mn10300/kernel/ptrace.c b/arch/mn10300/kernel/ptrace.c
new file mode 100644
index 0000000..5bd5851
--- /dev/null
+++ b/arch/mn10300/kernel/ptrace.c
@@ -0,0 +1,385 @@
+/* MN10300 Process tracing
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/regset.h>
+#include <linux/elf.h>
+#include <linux/tracehook.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/fpu.h>
+#include <asm/asm-offsets.h>
+
+/*
+ * translate ptrace register IDs into struct pt_regs offsets
+ */
+static const u8 ptrace_regid_to_frame[] = {
+	[PT_A3 << 2]		= REG_A3,
+	[PT_A2 << 2]		= REG_A2,
+	[PT_D3 << 2]		= REG_D3,
+	[PT_D2 << 2]		= REG_D2,
+	[PT_MCVF << 2]		= REG_MCVF,
+	[PT_MCRL << 2]		= REG_MCRL,
+	[PT_MCRH << 2]		= REG_MCRH,
+	[PT_MDRQ << 2]		= REG_MDRQ,
+	[PT_E1 << 2]		= REG_E1,
+	[PT_E0 << 2]		= REG_E0,
+	[PT_E7 << 2]		= REG_E7,
+	[PT_E6 << 2]		= REG_E6,
+	[PT_E5 << 2]		= REG_E5,
+	[PT_E4 << 2]		= REG_E4,
+	[PT_E3 << 2]		= REG_E3,
+	[PT_E2 << 2]		= REG_E2,
+	[PT_SP << 2]		= REG_SP,
+	[PT_LAR << 2]		= REG_LAR,
+	[PT_LIR << 2]		= REG_LIR,
+	[PT_MDR << 2]		= REG_MDR,
+	[PT_A1 << 2]		= REG_A1,
+	[PT_A0 << 2]		= REG_A0,
+	[PT_D1 << 2]		= REG_D1,
+	[PT_D0 << 2]		= REG_D0,
+	[PT_ORIG_D0 << 2]	= REG_ORIG_D0,
+	[PT_EPSW << 2]		= REG_EPSW,
+	[PT_PC << 2]		= REG_PC,
+};
+
+static inline int get_stack_long(struct task_struct *task, int offset)
+{
+	return *(unsigned long *)
+		((unsigned long) task->thread.uregs + offset);
+}
+
+static inline
+int put_stack_long(struct task_struct *task, int offset, unsigned long data)
+{
+	unsigned long stack;
+
+	stack = (unsigned long) task->thread.uregs + offset;
+	*(unsigned long *) stack = data;
+	return 0;
+}
+
+/*
+ * retrieve the contents of MN10300 userspace general registers
+ */
+static int genregs_get(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       void *kbuf, void __user *ubuf)
+{
+	const struct pt_regs *regs = task_pt_regs(target);
+	int ret;
+
+	/* we need to skip regs->next */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  regs, 0, PT_ORIG_D0 * sizeof(long));
+	if (ret < 0)
+		return ret;
+
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  &regs->orig_d0, PT_ORIG_D0 * sizeof(long),
+				  NR_PTREGS * sizeof(long));
+	if (ret < 0)
+		return ret;
+
+	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					NR_PTREGS * sizeof(long), -1);
+}
+
+/*
+ * update the contents of the MN10300 userspace general registers
+ */
+static int genregs_set(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       const void *kbuf, const void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+	unsigned long tmp;
+	int ret;
+
+	/* we need to skip regs->next */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 regs, 0, PT_ORIG_D0 * sizeof(long));
+	if (ret < 0)
+		return ret;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &regs->orig_d0, PT_ORIG_D0 * sizeof(long),
+				 PT_EPSW * sizeof(long));
+	if (ret < 0)
+		return ret;
+
+	/* we need to mask off changes to EPSW */
+	tmp = regs->epsw;
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &tmp, PT_EPSW * sizeof(long),
+				 PT_PC * sizeof(long));
+	tmp &= EPSW_FLAG_V | EPSW_FLAG_C | EPSW_FLAG_N | EPSW_FLAG_Z;
+	tmp |= regs->epsw & ~(EPSW_FLAG_V | EPSW_FLAG_C | EPSW_FLAG_N |
+			      EPSW_FLAG_Z);
+	regs->epsw = tmp;
+
+	if (ret < 0)
+		return ret;
+
+	/* and finally load the PC */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &regs->pc, PT_PC * sizeof(long),
+				 NR_PTREGS * sizeof(long));
+
+	if (ret < 0)
+		return ret;
+
+	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					 NR_PTREGS * sizeof(long), -1);
+}
+
+/*
+ * retrieve the contents of MN10300 userspace FPU registers
+ */
+static int fpuregs_get(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       void *kbuf, void __user *ubuf)
+{
+	const struct fpu_state_struct *fpregs = &target->thread.fpu_state;
+	int ret;
+
+	unlazy_fpu(target);
+
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  fpregs, 0, sizeof(*fpregs));
+	if (ret < 0)
+		return ret;
+
+	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					sizeof(*fpregs), -1);
+}
+
+/*
+ * update the contents of the MN10300 userspace FPU registers
+ */
+static int fpuregs_set(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       const void *kbuf, const void __user *ubuf)
+{
+	struct fpu_state_struct fpu_state = target->thread.fpu_state;
+	int ret;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &fpu_state, 0, sizeof(fpu_state));
+	if (ret < 0)
+		return ret;
+
+	fpu_kill_state(target);
+	target->thread.fpu_state = fpu_state;
+	set_using_fpu(target);
+
+	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					 sizeof(fpu_state), -1);
+}
+
+/*
+ * determine if the FPU registers have actually been used
+ */
+static int fpuregs_active(struct task_struct *target,
+			  const struct user_regset *regset)
+{
+	return is_using_fpu(target) ? regset->n : 0;
+}
+
+/*
+ * Define the register sets available on the MN10300 under Linux
+ */
+enum mn10300_regset {
+	REGSET_GENERAL,
+	REGSET_FPU,
+};
+
+static const struct user_regset mn10300_regsets[] = {
+	/*
+	 * General register format is:
+	 *	A3, A2, D3, D2, MCVF, MCRL, MCRH, MDRQ
+	 *	E1, E0, E7...E2, SP, LAR, LIR, MDR
+	 *	A1, A0, D1, D0, ORIG_D0, EPSW, PC
+	 */
+	[REGSET_GENERAL] = {
+		.core_note_type	= NT_PRSTATUS,
+		.n		= ELF_NGREG,
+		.size		= sizeof(long),
+		.align		= sizeof(long),
+		.get		= genregs_get,
+		.set		= genregs_set,
+	},
+	/*
+	 * FPU register format is:
+	 *	FS0-31, FPCR
+	 */
+	[REGSET_FPU] = {
+		.core_note_type	= NT_PRFPREG,
+		.n		= sizeof(struct fpu_state_struct) / sizeof(long),
+		.size		= sizeof(long),
+		.align		= sizeof(long),
+		.get		= fpuregs_get,
+		.set		= fpuregs_set,
+		.active		= fpuregs_active,
+	},
+};
+
+static const struct user_regset_view user_mn10300_native_view = {
+	.name		= "mn10300",
+	.e_machine	= EM_MN10300,
+	.regsets	= mn10300_regsets,
+	.n		= ARRAY_SIZE(mn10300_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+	return &user_mn10300_native_view;
+}
+
+/*
+ * set the single-step bit
+ */
+void user_enable_single_step(struct task_struct *child)
+{
+#ifndef CONFIG_MN10300_USING_JTAG
+	struct user *dummy = NULL;
+	long tmp;
+
+	tmp = get_stack_long(child, (unsigned long) &dummy->regs.epsw);
+	tmp |= EPSW_T;
+	put_stack_long(child, (unsigned long) &dummy->regs.epsw, tmp);
+#endif
+}
+
+/*
+ * make sure the single-step bit is not set
+ */
+void user_disable_single_step(struct task_struct *child)
+{
+#ifndef CONFIG_MN10300_USING_JTAG
+	struct user *dummy = NULL;
+	long tmp;
+
+	tmp = get_stack_long(child, (unsigned long) &dummy->regs.epsw);
+	tmp &= ~EPSW_T;
+	put_stack_long(child, (unsigned long) &dummy->regs.epsw, tmp);
+#endif
+}
+
+void ptrace_disable(struct task_struct *child)
+{
+	user_disable_single_step(child);
+}
+
+/*
+ * handle the arch-specific side of process tracing
+ */
+long arch_ptrace(struct task_struct *child, long request,
+		 unsigned long addr, unsigned long data)
+{
+	unsigned long tmp;
+	int ret;
+	unsigned long __user *datap = (unsigned long __user *) data;
+
+	switch (request) {
+	/* read the word at location addr in the USER area. */
+	case PTRACE_PEEKUSR:
+		ret = -EIO;
+		if ((addr & 3) || addr > sizeof(struct user) - 3)
+			break;
+
+		tmp = 0;  /* Default return condition */
+		if (addr < NR_PTREGS << 2)
+			tmp = get_stack_long(child,
+					     ptrace_regid_to_frame[addr]);
+		ret = put_user(tmp, datap);
+		break;
+
+		/* write the word at location addr in the USER area */
+	case PTRACE_POKEUSR:
+		ret = -EIO;
+		if ((addr & 3) || addr > sizeof(struct user) - 3)
+			break;
+
+		ret = 0;
+		if (addr < NR_PTREGS << 2)
+			ret = put_stack_long(child, ptrace_regid_to_frame[addr],
+					     data);
+		break;
+
+	case PTRACE_GETREGS:	/* Get all integer regs from the child. */
+		return copy_regset_to_user(child, &user_mn10300_native_view,
+					   REGSET_GENERAL,
+					   0, NR_PTREGS * sizeof(long),
+					   datap);
+
+	case PTRACE_SETREGS:	/* Set all integer regs in the child. */
+		return copy_regset_from_user(child, &user_mn10300_native_view,
+					     REGSET_GENERAL,
+					     0, NR_PTREGS * sizeof(long),
+					     datap);
+
+	case PTRACE_GETFPREGS:	/* Get the child FPU state. */
+		return copy_regset_to_user(child, &user_mn10300_native_view,
+					   REGSET_FPU,
+					   0, sizeof(struct fpu_state_struct),
+					   datap);
+
+	case PTRACE_SETFPREGS:	/* Set the child FPU state. */
+		return copy_regset_from_user(child, &user_mn10300_native_view,
+					     REGSET_FPU,
+					     0, sizeof(struct fpu_state_struct),
+					     datap);
+
+	default:
+		ret = ptrace_request(child, request, addr, data);
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * handle tracing of system call entry
+ * - return the revised system call number or ULONG_MAX to cause ENOSYS
+ */
+asmlinkage unsigned long syscall_trace_entry(struct pt_regs *regs)
+{
+	if (tracehook_report_syscall_entry(regs))
+		/* tracing decided this syscall should not happen, so
+		 * We'll return a bogus call number to get an ENOSYS
+		 * error, but leave the original number in
+		 * regs->orig_d0
+		 */
+		return ULONG_MAX;
+
+	return regs->orig_d0;
+}
+
+/*
+ * handle tracing of system call exit
+ */
+asmlinkage void syscall_trace_exit(struct pt_regs *regs)
+{
+	tracehook_report_syscall_exit(regs, 0);
+}
diff --git a/arch/mn10300/kernel/rtc.c b/arch/mn10300/kernel/rtc.c
new file mode 100644
index 0000000..48d7058
--- /dev/null
+++ b/arch/mn10300/kernel/rtc.c
@@ -0,0 +1,132 @@
+/* MN10300 RTC management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+#include <linux/bcd.h>
+#include <linux/timex.h>
+#include <asm/rtc-regs.h>
+#include <asm/rtc.h>
+
+DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL(rtc_lock);
+
+/*
+ * Read the current RTC time
+ */
+void read_persistent_clock(struct timespec *ts)
+{
+	struct rtc_time tm;
+
+	get_rtc_time(&tm);
+
+	ts->tv_nsec = 0;
+	ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday,
+			    tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+	/* if rtc is way off in the past, set something reasonable */
+	if (ts->tv_sec < 0)
+		ts->tv_sec = mktime(2009, 1, 1, 12, 0, 0);
+}
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
+ * ms after the second nowtime has started, because when nowtime is written
+ * into the registers of the CMOS clock, it will jump to the next second
+ * precisely 500 ms later.  Check the Motorola MC146818A or Dallas DS12887 data
+ * sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you'll only notice that after reboot!
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+	unsigned char save_control, save_freq_select;
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+
+	/* gets recalled with irq locally disabled */
+	spin_lock(&rtc_lock);
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being
+						* set */
+	CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset
+							* prescaler */
+	CMOS_WRITE(save_freq_select | RTC_DIV_RESET2, RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		cmos_minutes = bcd2bin(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
+		/* correct for half hour time zone */
+		real_minutes += 30;
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+			real_seconds = bin2bcd(real_seconds);
+			real_minutes = bin2bcd(real_minutes);
+		}
+		CMOS_WRITE(real_seconds, RTC_SECONDS);
+		CMOS_WRITE(real_minutes, RTC_MINUTES);
+	} else {
+		printk_once(KERN_NOTICE
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+		retval = -1;
+	}
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+	spin_unlock(&rtc_lock);
+
+	return retval;
+}
+
+int update_persistent_clock(struct timespec now)
+{
+	return set_rtc_mmss(now.tv_sec);
+}
+
+/*
+ * calibrate the TSC clock against the RTC
+ */
+void __init calibrate_clock(void)
+{
+	unsigned char status;
+
+	/* make sure the RTC is running and is set to operate in 24hr mode */
+	status = RTSRC;
+	RTCRB |= RTCRB_SET;
+	RTCRB |= RTCRB_TM_24HR;
+	RTCRB &= ~RTCRB_DM_BINARY;
+	RTCRA |= RTCRA_DVR;
+	RTCRA &= ~RTCRA_DVR;
+	RTCRB &= ~RTCRB_SET;
+}
diff --git a/arch/mn10300/kernel/setup.c b/arch/mn10300/kernel/setup.c
new file mode 100644
index 0000000..2ad7f32
--- /dev/null
+++ b/arch/mn10300/kernel/setup.c
@@ -0,0 +1,283 @@
+/* MN10300 Arch-specific initialisation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/cpu.h>
+#include <asm/processor.h>
+#include <linux/console.h>
+#include <asm/uaccess.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <proc/proc.h>
+#include <asm/fpu.h>
+#include <asm/sections.h>
+
+struct mn10300_cpuinfo boot_cpu_data;
+
+static char __initdata cmd_line[COMMAND_LINE_SIZE];
+char redboot_command_line[COMMAND_LINE_SIZE] =
+	"console=ttyS0,115200 root=/dev/mtdblock3 rw";
+
+char __initdata redboot_platform_name[COMMAND_LINE_SIZE];
+
+static struct resource code_resource = {
+	.start	= 0x100000,
+	.end	= 0,
+	.name	= "Kernel code",
+};
+
+static struct resource data_resource = {
+	.start	= 0,
+	.end	= 0,
+	.name	= "Kernel data",
+};
+
+static unsigned long __initdata phys_memory_base;
+static unsigned long __initdata phys_memory_end;
+static unsigned long __initdata memory_end;
+unsigned long memory_size;
+
+struct thread_info *__current_ti = &init_thread_union.thread_info;
+struct task_struct *__current = &init_task;
+
+#define mn10300_known_cpus 5
+static const char *const mn10300_cputypes[] = {
+	"am33-1",
+	"am33-2",
+	"am34-1",
+	"am33-3",
+	"am34-2",
+	"unknown"
+};
+
+/*
+ * Pick out the memory size.  We look for mem=size,
+ * where size is "size[KkMm]"
+ */
+static int __init early_mem(char *p)
+{
+	memory_size = memparse(p, &p);
+
+	if (memory_size == 0)
+		panic("Memory size not known\n");
+
+	return 0;
+}
+early_param("mem", early_mem);
+
+/*
+ * architecture specific setup
+ */
+void __init setup_arch(char **cmdline_p)
+{
+	unsigned long bootmap_size;
+	unsigned long kstart_pfn, start_pfn, free_pfn, end_pfn;
+
+	cpu_init();
+	unit_setup();
+	smp_init_cpus();
+
+	/* save unparsed command line copy for /proc/cmdline */
+	strlcpy(boot_command_line, redboot_command_line, COMMAND_LINE_SIZE);
+
+	/* populate cmd_line too for later use, preserving boot_command_line */
+	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+	*cmdline_p = cmd_line;
+
+	parse_early_param();
+
+	memory_end = (unsigned long) CONFIG_KERNEL_RAM_BASE_ADDRESS +
+		memory_size;
+	if (memory_end > phys_memory_end)
+		memory_end = phys_memory_end;
+
+	init_mm.start_code = (unsigned long)&_text;
+	init_mm.end_code = (unsigned long) &_etext;
+	init_mm.end_data = (unsigned long) &_edata;
+	init_mm.brk = (unsigned long) &_end;
+
+	code_resource.start = virt_to_bus(&_text);
+	code_resource.end = virt_to_bus(&_etext)-1;
+	data_resource.start = virt_to_bus(&_etext);
+	data_resource.end = virt_to_bus(&_edata)-1;
+
+	start_pfn = (CONFIG_KERNEL_RAM_BASE_ADDRESS >> PAGE_SHIFT);
+	kstart_pfn = PFN_UP(__pa(&_text));
+	free_pfn = PFN_UP(__pa(&_end));
+	end_pfn = PFN_DOWN(__pa(memory_end));
+
+	bootmap_size = init_bootmem_node(&contig_page_data,
+					 free_pfn,
+					 start_pfn,
+					 end_pfn);
+
+	if (kstart_pfn > start_pfn)
+		free_bootmem(PFN_PHYS(start_pfn),
+			     PFN_PHYS(kstart_pfn - start_pfn));
+
+	free_bootmem(PFN_PHYS(free_pfn),
+		     PFN_PHYS(end_pfn - free_pfn));
+
+	/* If interrupt vector table is in main ram, then we need to
+	   reserve the page it is occupying. */
+	if (CONFIG_INTERRUPT_VECTOR_BASE >= CONFIG_KERNEL_RAM_BASE_ADDRESS &&
+	    CONFIG_INTERRUPT_VECTOR_BASE < memory_end)
+		reserve_bootmem(CONFIG_INTERRUPT_VECTOR_BASE, PAGE_SIZE,
+				BOOTMEM_DEFAULT);
+
+	reserve_bootmem(PAGE_ALIGN(PFN_PHYS(free_pfn)), bootmap_size,
+			BOOTMEM_DEFAULT);
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+	conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+#endif
+
+	paging_init();
+}
+
+/*
+ * perform CPU initialisation
+ */
+void __init cpu_init(void)
+{
+	unsigned long cpurev = CPUREV, type;
+
+	type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S;
+	if (type > mn10300_known_cpus)
+		type = mn10300_known_cpus;
+
+	printk(KERN_INFO "Panasonic %s, rev %ld\n",
+	       mn10300_cputypes[type],
+	       (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S);
+
+	get_mem_info(&phys_memory_base, &memory_size);
+	phys_memory_end = phys_memory_base + memory_size;
+
+	fpu_init_state();
+}
+
+static struct cpu cpu_devices[NR_CPUS];
+
+static int __init topology_init(void)
+{
+	int i;
+
+	for_each_present_cpu(i)
+		register_cpu(&cpu_devices[i], i);
+
+	return 0;
+}
+
+subsys_initcall(topology_init);
+
+/*
+ * Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+#ifdef CONFIG_SMP
+	struct mn10300_cpuinfo *c = v;
+	unsigned long cpu_id = c - cpu_data;
+	unsigned long cpurev = c->type, type, icachesz, dcachesz;
+#else  /* CONFIG_SMP */
+	unsigned long cpu_id = 0;
+	unsigned long cpurev = CPUREV, type, icachesz, dcachesz;
+#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_SMP
+	if (!cpu_online(cpu_id))
+		return 0;
+#endif
+
+	type = (cpurev & CPUREV_TYPE) >> CPUREV_TYPE_S;
+	if (type > mn10300_known_cpus)
+		type = mn10300_known_cpus;
+
+	icachesz =
+		((cpurev & CPUREV_ICWAY ) >> CPUREV_ICWAY_S)  *
+		((cpurev & CPUREV_ICSIZE) >> CPUREV_ICSIZE_S) *
+		1024;
+
+	dcachesz =
+		((cpurev & CPUREV_DCWAY ) >> CPUREV_DCWAY_S)  *
+		((cpurev & CPUREV_DCSIZE) >> CPUREV_DCSIZE_S) *
+		1024;
+
+	seq_printf(m,
+		   "processor  : %ld\n"
+		   "vendor_id  : " PROCESSOR_VENDOR_NAME "\n"
+		   "cpu core   : %s\n"
+		   "cpu rev    : %lu\n"
+		   "model name : " PROCESSOR_MODEL_NAME		"\n"
+		   "icache size: %lu\n"
+		   "dcache size: %lu\n",
+		   cpu_id,
+		   mn10300_cputypes[type],
+		   (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S,
+		   icachesz,
+		   dcachesz
+		   );
+
+	seq_printf(m,
+		   "ioclk speed: %lu.%02luMHz\n"
+		   "bogomips   : %lu.%02lu\n\n",
+		   MN10300_IOCLK / 1000000,
+		   (MN10300_IOCLK / 10000) % 100,
+#ifdef CONFIG_SMP
+		   c->loops_per_jiffy / (500000 / HZ),
+		   (c->loops_per_jiffy / (5000 / HZ)) % 100
+#else  /* CONFIG_SMP */
+		   loops_per_jiffy / (500000 / HZ),
+		   (loops_per_jiffy / (5000 / HZ)) % 100
+#endif /* CONFIG_SMP */
+		   );
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+const struct seq_operations cpuinfo_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_cpuinfo,
+};
diff --git a/arch/mn10300/kernel/sigframe.h b/arch/mn10300/kernel/sigframe.h
new file mode 100644
index 0000000..0decba2
--- /dev/null
+++ b/arch/mn10300/kernel/sigframe.h
@@ -0,0 +1,33 @@
+/* MN10300 Signal frame definitions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+struct sigframe
+{
+	void (*pretcode)(void);
+	int sig;
+	struct sigcontext *psc;
+	struct sigcontext sc;
+	struct fpucontext fpuctx;
+	unsigned long extramask[_NSIG_WORDS-1];
+	char retcode[8];
+};
+
+struct rt_sigframe
+{
+	void (*pretcode)(void);
+	int sig;
+	struct siginfo *pinfo;
+	void *puc;
+	struct siginfo info;
+	struct ucontext uc;
+	struct fpucontext fpuctx;
+	char retcode[8];
+};
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c
new file mode 100644
index 0000000..dfd0301
--- /dev/null
+++ b/arch/mn10300/kernel/signal.c
@@ -0,0 +1,431 @@
+/* MN10300 Signal handling
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/tty.h>
+#include <linux/personality.h>
+#include <linux/suspend.h>
+#include <linux/tracehook.h>
+#include <asm/cacheflush.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+#include <asm/fpu.h>
+#include "sigframe.h"
+
+#define DEBUG_SIG 0
+
+/*
+ * do a signal return; undo the signal stack.
+ */
+static int restore_sigcontext(struct pt_regs *regs,
+			      struct sigcontext __user *sc, long *_d0)
+{
+	unsigned int err = 0;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current->restart_block.fn = do_no_restart_syscall;
+
+	if (is_using_fpu(current))
+		fpu_kill_state(current);
+
+#define COPY(x) err |= __get_user(regs->x, &sc->x)
+	COPY(d1); COPY(d2); COPY(d3);
+	COPY(a0); COPY(a1); COPY(a2); COPY(a3);
+	COPY(e0); COPY(e1); COPY(e2); COPY(e3);
+	COPY(e4); COPY(e5); COPY(e6); COPY(e7);
+	COPY(lar); COPY(lir);
+	COPY(mdr); COPY(mdrq);
+	COPY(mcvf); COPY(mcrl); COPY(mcrh);
+	COPY(sp); COPY(pc);
+#undef COPY
+
+	{
+		unsigned int tmpflags;
+#ifndef CONFIG_MN10300_USING_JTAG
+#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \
+		   EPSW_T | EPSW_nAR)
+#else
+#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \
+		   EPSW_nAR)
+#endif
+		err |= __get_user(tmpflags, &sc->epsw);
+		regs->epsw = (regs->epsw & ~USER_EPSW) |
+		  (tmpflags & USER_EPSW);
+		regs->orig_d0 = -1;		/* disable syscall checks */
+	}
+
+	{
+		struct fpucontext *buf;
+		err |= __get_user(buf, &sc->fpucontext);
+		if (buf) {
+			if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+				goto badframe;
+			err |= fpu_restore_sigcontext(buf);
+		}
+	}
+
+	err |= __get_user(*_d0, &sc->d0);
+	return err;
+
+badframe:
+	return 1;
+}
+
+/*
+ * standard signal return syscall
+ */
+asmlinkage long sys_sigreturn(void)
+{
+	struct sigframe __user *frame;
+	sigset_t set;
+	long d0;
+
+	frame = (struct sigframe __user *) current_frame()->sp;
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__get_user(set.sig[0], &frame->sc.oldmask))
+		goto badframe;
+
+	if (_NSIG_WORDS > 1 &&
+	    __copy_from_user(&set.sig[1], &frame->extramask,
+			     sizeof(frame->extramask)))
+		goto badframe;
+
+	set_current_blocked(&set);
+
+	if (restore_sigcontext(current_frame(), &frame->sc, &d0))
+		goto badframe;
+
+	return d0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+/*
+ * realtime signal return syscall
+ */
+asmlinkage long sys_rt_sigreturn(void)
+{
+	struct rt_sigframe __user *frame;
+	sigset_t set;
+	long d0;
+
+	frame = (struct rt_sigframe __user *) current_frame()->sp;
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		goto badframe;
+
+	set_current_blocked(&set);
+
+	if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
+		goto badframe;
+
+	if (restore_altstack(&frame->uc.uc_stack))
+		goto badframe;
+
+	return d0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+/*
+ * store the userspace context into a signal frame
+ */
+static int setup_sigcontext(struct sigcontext __user *sc,
+			    struct fpucontext *fpuctx,
+			    struct pt_regs *regs,
+			    unsigned long mask)
+{
+	int tmp, err = 0;
+
+#define COPY(x) err |= __put_user(regs->x, &sc->x)
+	COPY(d0); COPY(d1); COPY(d2); COPY(d3);
+	COPY(a0); COPY(a1); COPY(a2); COPY(a3);
+	COPY(e0); COPY(e1); COPY(e2); COPY(e3);
+	COPY(e4); COPY(e5); COPY(e6); COPY(e7);
+	COPY(lar); COPY(lir);
+	COPY(mdr); COPY(mdrq);
+	COPY(mcvf); COPY(mcrl); COPY(mcrh);
+	COPY(sp); COPY(epsw); COPY(pc);
+#undef COPY
+
+	tmp = fpu_setup_sigcontext(fpuctx);
+	if (tmp < 0)
+		err = 1;
+	else
+		err |= __put_user(tmp ? fpuctx : NULL, &sc->fpucontext);
+
+	/* non-iBCS2 extensions.. */
+	err |= __put_user(mask, &sc->oldmask);
+
+	return err;
+}
+
+/*
+ * determine which stack to use..
+ */
+static inline void __user *get_sigframe(struct ksignal *ksig,
+					struct pt_regs *regs,
+					size_t frame_size)
+{
+	unsigned long sp = sigsp(regs->sp, ksig);
+
+	return (void __user *) ((sp - frame_size) & ~7UL);
+}
+
+/*
+ * set up a normal signal frame
+ */
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
+		       struct pt_regs *regs)
+{
+	struct sigframe __user *frame;
+	int sig = ksig->sig;
+
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		return -EFAULT;
+
+	if (__put_user(sig, &frame->sig) < 0 ||
+	    __put_user(&frame->sc, &frame->psc) < 0)
+		return -EFAULT;
+
+	if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0]))
+		return -EFAULT;
+
+	if (_NSIG_WORDS > 1) {
+		if (__copy_to_user(frame->extramask, &set->sig[1],
+				   sizeof(frame->extramask)))
+			return -EFAULT;
+	}
+
+	/* set up to return from userspace.  If provided, use a stub already in
+	 * userspace */
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
+			return -EFAULT;
+	} else {
+		if (__put_user((void (*)(void))frame->retcode,
+			       &frame->pretcode))
+			return -EFAULT;
+		/* this is mov $,d0; syscall 0 */
+		if (__put_user(0x2c, (char *)(frame->retcode + 0)) ||
+		    __put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) ||
+		    __put_user(0x00, (char *)(frame->retcode + 2)) ||
+		    __put_user(0xf0, (char *)(frame->retcode + 3)) ||
+		    __put_user(0xe0, (char *)(frame->retcode + 4)))
+			return -EFAULT;
+		flush_icache_range((unsigned long) frame->retcode,
+				   (unsigned long) frame->retcode + 5);
+	}
+
+	/* set up registers for signal handler */
+	regs->sp = (unsigned long) frame;
+	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+	regs->d0 = sig;
+	regs->d1 = (unsigned long) &frame->sc;
+
+#if DEBUG_SIG
+	printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
+	       sig, current->comm, current->pid, frame, regs->pc,
+	       frame->pretcode);
+#endif
+
+	return 0;
+}
+
+/*
+ * set up a realtime signal frame
+ */
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+	int sig = ksig->sig;
+
+	frame = get_sigframe(ksig, regs, sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		return -EFAULT;
+
+	if (__put_user(sig, &frame->sig) ||
+	    __put_user(&frame->info, &frame->pinfo) ||
+	    __put_user(&frame->uc, &frame->puc) ||
+	    copy_siginfo_to_user(&frame->info, &ksig->info))
+		return -EFAULT;
+
+	/* create the ucontext.  */
+	if (__put_user(0, &frame->uc.uc_flags) ||
+	    __put_user(0, &frame->uc.uc_link) ||
+	    __save_altstack(&frame->uc.uc_stack, regs->sp) ||
+	    setup_sigcontext(&frame->uc.uc_mcontext,
+			     &frame->fpuctx, regs, set->sig[0]) ||
+	    __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
+		return -EFAULT;
+
+	/* set up to return from userspace.  If provided, use a stub already in
+	 * userspace */
+	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+		if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
+			return -EFAULT;
+
+	} else {
+		if (__put_user((void(*)(void))frame->retcode,
+			       &frame->pretcode) ||
+		    /* This is mov $,d0; syscall 0 */
+		    __put_user(0x2c, (char *)(frame->retcode + 0)) ||
+		    __put_user(__NR_rt_sigreturn,
+			       (char *)(frame->retcode + 1)) ||
+		    __put_user(0x00, (char *)(frame->retcode + 2)) ||
+		    __put_user(0xf0, (char *)(frame->retcode + 3)) ||
+		    __put_user(0xe0, (char *)(frame->retcode + 4)))
+			return -EFAULT;
+
+		flush_icache_range((u_long) frame->retcode,
+				   (u_long) frame->retcode + 5);
+	}
+
+	/* Set up registers for signal handler */
+	regs->sp = (unsigned long) frame;
+	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+	regs->d0 = sig;
+	regs->d1 = (long) &frame->info;
+
+#if DEBUG_SIG
+	printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
+	       sig, current->comm, current->pid, frame, regs->pc,
+	       frame->pretcode);
+#endif
+
+	return 0;
+}
+
+static inline void stepback(struct pt_regs *regs)
+{
+	regs->pc -= 2;
+	regs->orig_d0 = -1;
+}
+
+/*
+ * handle the actual delivery of a signal to userspace
+ */
+static int handle_signal(struct ksignal *ksig, struct pt_regs *regs)
+{
+	sigset_t *oldset = sigmask_to_save();
+	int ret;
+
+	/* Are we from a system call? */
+	if (regs->orig_d0 >= 0) {
+		/* If so, check system call restarting.. */
+		switch (regs->d0) {
+		case -ERESTART_RESTARTBLOCK:
+		case -ERESTARTNOHAND:
+			regs->d0 = -EINTR;
+			break;
+
+		case -ERESTARTSYS:
+			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
+				regs->d0 = -EINTR;
+				break;
+			}
+
+			/* fallthrough */
+		case -ERESTARTNOINTR:
+			regs->d0 = regs->orig_d0;
+			stepback(regs);
+		}
+	}
+
+	/* Set up the stack frame */
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(ksig, oldset, regs);
+	else
+		ret = setup_frame(ksig, oldset, regs);
+
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
+	return 0;
+}
+
+/*
+ * handle a potential signal
+ */
+static void do_signal(struct pt_regs *regs)
+{
+	struct ksignal ksig;
+
+	if (get_signal(&ksig)) {
+		handle_signal(&ksig, regs);
+		return;
+	}
+
+	/* did we come from a system call? */
+	if (regs->orig_d0 >= 0) {
+		/* restart the system call - no handlers present */
+		switch (regs->d0) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			regs->d0 = regs->orig_d0;
+			stepback(regs);
+			break;
+
+		case -ERESTART_RESTARTBLOCK:
+			regs->d0 = __NR_restart_syscall;
+			stepback(regs);
+			break;
+		}
+	}
+
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back */
+	restore_saved_sigmask();
+}
+
+/*
+ * notification of userspace execution resumption
+ * - triggered by current->work.notify_resume
+ */
+asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
+{
+	/* Pending single-step? */
+	if (thread_info_flags & _TIF_SINGLESTEP) {
+#ifndef CONFIG_MN10300_USING_JTAG
+		regs->epsw |= EPSW_T;
+		clear_thread_flag(TIF_SINGLESTEP);
+#else
+		BUG(); /* no h/w single-step if using JTAG unit */
+#endif
+	}
+
+	/* deal with pending signal delivery */
+	if (thread_info_flags & _TIF_SIGPENDING)
+		do_signal(regs);
+
+	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(current_frame());
+	}
+}
diff --git a/arch/mn10300/kernel/smp-low.S b/arch/mn10300/kernel/smp-low.S
new file mode 100644
index 0000000..71f1b2f
--- /dev/null
+++ b/arch/mn10300/kernel/smp-low.S
@@ -0,0 +1,97 @@
+/* SMP IPI low-level handler
+ *
+ * Copyright (C) 2006-2007 Matsushita Electric Industrial Co., Ltd.
+ * All Rights Reserved.
+ *
+ * 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/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/thread_info.h>
+#include <asm/cpu-regs.h>
+#include <asm/intctl-regs.h>
+#include <proc/smp-regs.h>
+#include <asm/asm-offsets.h>
+#include <asm/frame.inc>
+
+	.am33_2
+
+###############################################################################
+#
+# IPI interrupt handler
+#
+###############################################################################
+	.globl mn10300_low_ipi_handler
+mn10300_low_ipi_handler:
+	add	-4,sp
+	mov	d0,(sp)
+	movhu	(IAGR),d0
+	and	IAGR_GN,d0
+	lsr	0x2,d0
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+	cmp	FLUSH_CACHE_IPI,d0
+	beq	mn10300_flush_cache_ipi
+#endif
+	cmp	SMP_BOOT_IRQ,d0
+	beq	mn10300_smp_boot_ipi
+	/* OTHERS */
+	mov	(sp),d0
+	add	4,sp
+#ifdef CONFIG_GDBSTUB
+	jmp	gdbstub_io_rx_handler
+#else
+	jmp	end
+#endif
+
+###############################################################################
+#
+# Cache flush IPI interrupt handler
+#
+###############################################################################
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+mn10300_flush_cache_ipi:
+	mov	(sp),d0
+	add	4,sp
+
+	/* FLUSH_CACHE_IPI */
+	add	-4,sp
+	SAVE_ALL
+	mov	GxICR_DETECT,d2
+	movbu	d2,(GxICR(FLUSH_CACHE_IPI))	# ACK the interrupt
+	movhu	(GxICR(FLUSH_CACHE_IPI)),d2
+	call	smp_cache_interrupt[],0
+	RESTORE_ALL
+	jmp	end
+#endif
+
+###############################################################################
+#
+# SMP boot CPU IPI interrupt handler
+#
+###############################################################################
+mn10300_smp_boot_ipi:
+	/* clear interrupt */
+	movhu	(GxICR(SMP_BOOT_IRQ)),d0
+	and	~GxICR_REQUEST,d0
+	movhu	d0,(GxICR(SMP_BOOT_IRQ))
+	mov	(sp),d0
+	add	4,sp
+
+	# get stack
+	mov	(CPUID),a0
+	add	-1,a0
+	add	a0,a0
+	add	a0,a0
+	mov	(start_stack,a0),a0
+	mov	a0,sp
+	jmp	initialize_secondary
+
+
+# Jump here after RTI to suppress the icache lookahead
+end:
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c
new file mode 100644
index 0000000..f984193
--- /dev/null
+++ b/arch/mn10300/kernel/smp.c
@@ -0,0 +1,1185 @@
+/* SMP support routines.
+ *
+ * Copyright (C) 2006-2008 Panasonic Corporation
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/cpumask.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/profile.h>
+#include <linux/smp.h>
+#include <linux/cpu.h>
+#include <asm/tlbflush.h>
+#include <asm/bitops.h>
+#include <asm/processor.h>
+#include <asm/bug.h>
+#include <asm/exceptions.h>
+#include <asm/hardirq.h>
+#include <asm/fpu.h>
+#include <asm/mmu_context.h>
+#include <asm/thread_info.h>
+#include <asm/cpu-regs.h>
+#include <asm/intctl-regs.h>
+#include "internal.h"
+
+#ifdef CONFIG_HOTPLUG_CPU
+#include <asm/cacheflush.h>
+
+static unsigned long sleep_mode[NR_CPUS];
+
+static void run_sleep_cpu(unsigned int cpu);
+static void run_wakeup_cpu(unsigned int cpu);
+#endif /* CONFIG_HOTPLUG_CPU */
+
+/*
+ * Debug Message function
+ */
+
+#undef DEBUG_SMP
+#ifdef DEBUG_SMP
+#define Dprintk(fmt, ...) printk(KERN_DEBUG fmt, ##__VA_ARGS__)
+#else
+#define Dprintk(fmt, ...) no_printk(KERN_DEBUG fmt, ##__VA_ARGS__)
+#endif
+
+/* timeout value in msec for smp_nmi_call_function. zero is no timeout. */
+#define	CALL_FUNCTION_NMI_IPI_TIMEOUT	0
+
+/*
+ * Structure and data for smp_nmi_call_function().
+ */
+struct nmi_call_data_struct {
+	smp_call_func_t	func;
+	void		*info;
+	cpumask_t	started;
+	cpumask_t	finished;
+	int		wait;
+	char		size_alignment[0]
+	__attribute__ ((__aligned__(SMP_CACHE_BYTES)));
+} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
+
+static DEFINE_SPINLOCK(smp_nmi_call_lock);
+static struct nmi_call_data_struct *nmi_call_data;
+
+/*
+ * Data structures and variables
+ */
+static cpumask_t cpu_callin_map;	/* Bitmask of callin CPUs */
+static cpumask_t cpu_callout_map;	/* Bitmask of callout CPUs */
+cpumask_t cpu_boot_map;			/* Bitmask of boot APs */
+unsigned long start_stack[NR_CPUS - 1];
+
+/*
+ * Per CPU parameters
+ */
+struct mn10300_cpuinfo cpu_data[NR_CPUS] __cacheline_aligned;
+
+static int cpucount;			/* The count of boot CPUs */
+static cpumask_t smp_commenced_mask;
+cpumask_t cpu_initialized __initdata = CPU_MASK_NONE;
+
+/*
+ * Function Prototypes
+ */
+static int do_boot_cpu(int);
+static void smp_show_cpu_info(int cpu_id);
+static void smp_callin(void);
+static void smp_online(void);
+static void smp_store_cpu_info(int);
+static void smp_cpu_init(void);
+static void smp_tune_scheduling(void);
+static void send_IPI_mask(const cpumask_t *cpumask, int irq);
+static void init_ipi(void);
+
+/*
+ * IPI Initialization interrupt definitions
+ */
+static void mn10300_ipi_disable(unsigned int irq);
+static void mn10300_ipi_enable(unsigned int irq);
+static void mn10300_ipi_chip_disable(struct irq_data *d);
+static void mn10300_ipi_chip_enable(struct irq_data *d);
+static void mn10300_ipi_ack(struct irq_data *d);
+static void mn10300_ipi_nop(struct irq_data *d);
+
+static struct irq_chip mn10300_ipi_type = {
+	.name		= "cpu_ipi",
+	.irq_disable	= mn10300_ipi_chip_disable,
+	.irq_enable	= mn10300_ipi_chip_enable,
+	.irq_ack	= mn10300_ipi_ack,
+	.irq_eoi	= mn10300_ipi_nop
+};
+
+static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id);
+static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id);
+
+static struct irqaction reschedule_ipi = {
+	.handler	= smp_reschedule_interrupt,
+	.flags		= IRQF_NOBALANCING,
+	.name		= "smp reschedule IPI"
+};
+static struct irqaction call_function_ipi = {
+	.handler	= smp_call_function_interrupt,
+	.flags		= IRQF_NOBALANCING,
+	.name		= "smp call function IPI"
+};
+
+#if !defined(CONFIG_GENERIC_CLOCKEVENTS) || defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
+static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id);
+static struct irqaction local_timer_ipi = {
+	.handler	= smp_ipi_timer_interrupt,
+	.flags		= IRQF_NOBALANCING,
+	.name		= "smp local timer IPI"
+};
+#endif
+
+/**
+ * init_ipi - Initialise the IPI mechanism
+ */
+static void init_ipi(void)
+{
+	unsigned long flags;
+	u16 tmp16;
+
+	/* set up the reschedule IPI */
+	irq_set_chip_and_handler(RESCHEDULE_IPI, &mn10300_ipi_type,
+				 handle_percpu_irq);
+	setup_irq(RESCHEDULE_IPI, &reschedule_ipi);
+	set_intr_level(RESCHEDULE_IPI, RESCHEDULE_GxICR_LV);
+	mn10300_ipi_enable(RESCHEDULE_IPI);
+
+	/* set up the call function IPI */
+	irq_set_chip_and_handler(CALL_FUNC_SINGLE_IPI, &mn10300_ipi_type,
+				 handle_percpu_irq);
+	setup_irq(CALL_FUNC_SINGLE_IPI, &call_function_ipi);
+	set_intr_level(CALL_FUNC_SINGLE_IPI, CALL_FUNCTION_GxICR_LV);
+	mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI);
+
+	/* set up the local timer IPI */
+#if !defined(CONFIG_GENERIC_CLOCKEVENTS) || \
+    defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
+	irq_set_chip_and_handler(LOCAL_TIMER_IPI, &mn10300_ipi_type,
+				 handle_percpu_irq);
+	setup_irq(LOCAL_TIMER_IPI, &local_timer_ipi);
+	set_intr_level(LOCAL_TIMER_IPI, LOCAL_TIMER_GxICR_LV);
+	mn10300_ipi_enable(LOCAL_TIMER_IPI);
+#endif
+
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+	/* set up the cache flush IPI */
+	irq_set_chip(FLUSH_CACHE_IPI, &mn10300_ipi_type);
+	flags = arch_local_cli_save();
+	__set_intr_stub(NUM2EXCEP_IRQ_LEVEL(FLUSH_CACHE_GxICR_LV),
+			mn10300_low_ipi_handler);
+	GxICR(FLUSH_CACHE_IPI) = FLUSH_CACHE_GxICR_LV | GxICR_DETECT;
+	mn10300_ipi_enable(FLUSH_CACHE_IPI);
+	arch_local_irq_restore(flags);
+#endif
+
+	/* set up the NMI call function IPI */
+	irq_set_chip(CALL_FUNCTION_NMI_IPI, &mn10300_ipi_type);
+	flags = arch_local_cli_save();
+	GxICR(CALL_FUNCTION_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT;
+	tmp16 = GxICR(CALL_FUNCTION_NMI_IPI);
+	arch_local_irq_restore(flags);
+
+	/* set up the SMP boot IPI */
+	flags = arch_local_cli_save();
+	__set_intr_stub(NUM2EXCEP_IRQ_LEVEL(SMP_BOOT_GxICR_LV),
+			mn10300_low_ipi_handler);
+	arch_local_irq_restore(flags);
+
+#ifdef CONFIG_KERNEL_DEBUGGER
+	irq_set_chip(DEBUGGER_NMI_IPI, &mn10300_ipi_type);
+#endif
+}
+
+/**
+ * mn10300_ipi_shutdown - Shut down handling of an IPI
+ * @irq: The IPI to be shut down.
+ */
+static void mn10300_ipi_shutdown(unsigned int irq)
+{
+	unsigned long flags;
+	u16 tmp;
+
+	flags = arch_local_cli_save();
+
+	tmp = GxICR(irq);
+	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
+	tmp = GxICR(irq);
+
+	arch_local_irq_restore(flags);
+}
+
+/**
+ * mn10300_ipi_enable - Enable an IPI
+ * @irq: The IPI to be enabled.
+ */
+static void mn10300_ipi_enable(unsigned int irq)
+{
+	unsigned long flags;
+	u16 tmp;
+
+	flags = arch_local_cli_save();
+
+	tmp = GxICR(irq);
+	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
+	tmp = GxICR(irq);
+
+	arch_local_irq_restore(flags);
+}
+
+static void mn10300_ipi_chip_enable(struct irq_data *d)
+{
+	mn10300_ipi_enable(d->irq);
+}
+
+/**
+ * mn10300_ipi_disable - Disable an IPI
+ * @irq: The IPI to be disabled.
+ */
+static void mn10300_ipi_disable(unsigned int irq)
+{
+	unsigned long flags;
+	u16 tmp;
+
+	flags = arch_local_cli_save();
+
+	tmp = GxICR(irq);
+	GxICR(irq) = tmp & GxICR_LEVEL;
+	tmp = GxICR(irq);
+
+	arch_local_irq_restore(flags);
+}
+
+static void mn10300_ipi_chip_disable(struct irq_data *d)
+{
+	mn10300_ipi_disable(d->irq);
+}
+
+
+/**
+ * mn10300_ipi_ack - Acknowledge an IPI interrupt in the PIC
+ * @irq: The IPI to be acknowledged.
+ *
+ * Clear the interrupt detection flag for the IPI on the appropriate interrupt
+ * channel in the PIC.
+ */
+static void mn10300_ipi_ack(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+	unsigned long flags;
+	u16 tmp;
+
+	flags = arch_local_cli_save();
+	GxICR_u8(irq) = GxICR_DETECT;
+	tmp = GxICR(irq);
+	arch_local_irq_restore(flags);
+}
+
+/**
+ * mn10300_ipi_nop - Dummy IPI action
+ * @irq: The IPI to be acted upon.
+ */
+static void mn10300_ipi_nop(struct irq_data *d)
+{
+}
+
+/**
+ * send_IPI_mask - Send IPIs to all CPUs in list
+ * @cpumask: The list of CPUs to target.
+ * @irq: The IPI request to be sent.
+ *
+ * Send the specified IPI to all the CPUs in the list, not waiting for them to
+ * finish before returning.  The caller is responsible for synchronisation if
+ * that is needed.
+ */
+static void send_IPI_mask(const cpumask_t *cpumask, int irq)
+{
+	int i;
+	u16 tmp;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		if (cpumask_test_cpu(i, cpumask)) {
+			/* send IPI */
+			tmp = CROSS_GxICR(irq, i);
+			CROSS_GxICR(irq, i) =
+				tmp | GxICR_REQUEST | GxICR_DETECT;
+			tmp = CROSS_GxICR(irq, i); /* flush write buffer */
+		}
+	}
+}
+
+/**
+ * send_IPI_self - Send an IPI to this CPU.
+ * @irq: The IPI request to be sent.
+ *
+ * Send the specified IPI to the current CPU.
+ */
+void send_IPI_self(int irq)
+{
+	send_IPI_mask(cpumask_of(smp_processor_id()), irq);
+}
+
+/**
+ * send_IPI_allbutself - Send IPIs to all the other CPUs.
+ * @irq: The IPI request to be sent.
+ *
+ * Send the specified IPI to all CPUs in the system barring the current one,
+ * not waiting for them to finish before returning.  The caller is responsible
+ * for synchronisation if that is needed.
+ */
+void send_IPI_allbutself(int irq)
+{
+	cpumask_t cpumask;
+
+	cpumask_copy(&cpumask, cpu_online_mask);
+	cpumask_clear_cpu(smp_processor_id(), &cpumask);
+	send_IPI_mask(&cpumask, irq);
+}
+
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+	BUG();
+	/*send_IPI_mask(mask, CALL_FUNCTION_IPI);*/
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+	send_IPI_mask(cpumask_of(cpu), CALL_FUNC_SINGLE_IPI);
+}
+
+/**
+ * smp_send_reschedule - Send reschedule IPI to a CPU
+ * @cpu: The CPU to target.
+ */
+void smp_send_reschedule(int cpu)
+{
+	send_IPI_mask(cpumask_of(cpu), RESCHEDULE_IPI);
+}
+
+/**
+ * smp_nmi_call_function - Send a call function NMI IPI to all CPUs
+ * @func: The function to ask to be run.
+ * @info: The context data to pass to that function.
+ * @wait: If true, wait (atomically) until function is run on all CPUs.
+ *
+ * Send a non-maskable request to all CPUs in the system, requesting them to
+ * run the specified function with the given context data, and, potentially, to
+ * wait for completion of that function on all CPUs.
+ *
+ * Returns 0 if successful, -ETIMEDOUT if we were asked to wait, but hit the
+ * timeout.
+ */
+int smp_nmi_call_function(smp_call_func_t func, void *info, int wait)
+{
+	struct nmi_call_data_struct data;
+	unsigned long flags;
+	unsigned int cnt;
+	int cpus, ret = 0;
+
+	cpus = num_online_cpus() - 1;
+	if (cpus < 1)
+		return 0;
+
+	data.func = func;
+	data.info = info;
+	cpumask_copy(&data.started, cpu_online_mask);
+	cpumask_clear_cpu(smp_processor_id(), &data.started);
+	data.wait = wait;
+	if (wait)
+		data.finished = data.started;
+
+	spin_lock_irqsave(&smp_nmi_call_lock, flags);
+	nmi_call_data = &data;
+	smp_mb();
+
+	/* Send a message to all other CPUs and wait for them to respond */
+	send_IPI_allbutself(CALL_FUNCTION_NMI_IPI);
+
+	/* Wait for response */
+	if (CALL_FUNCTION_NMI_IPI_TIMEOUT > 0) {
+		for (cnt = 0;
+		     cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT &&
+			     !cpumask_empty(&data.started);
+		     cnt++)
+			mdelay(1);
+
+		if (wait && cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT) {
+			for (cnt = 0;
+			     cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT &&
+				     !cpumask_empty(&data.finished);
+			     cnt++)
+				mdelay(1);
+		}
+
+		if (cnt >= CALL_FUNCTION_NMI_IPI_TIMEOUT)
+			ret = -ETIMEDOUT;
+
+	} else {
+		/* If timeout value is zero, wait until cpumask has been
+		 * cleared */
+		while (!cpumask_empty(&data.started))
+			barrier();
+		if (wait)
+			while (!cpumask_empty(&data.finished))
+				barrier();
+	}
+
+	spin_unlock_irqrestore(&smp_nmi_call_lock, flags);
+	return ret;
+}
+
+/**
+ * smp_jump_to_debugger - Make other CPUs enter the debugger by sending an IPI
+ *
+ * Send a non-maskable request to all other CPUs in the system, instructing
+ * them to jump into the debugger.  The caller is responsible for checking that
+ * the other CPUs responded to the instruction.
+ *
+ * The caller should make sure that this CPU's debugger IPI is disabled.
+ */
+void smp_jump_to_debugger(void)
+{
+	if (num_online_cpus() > 1)
+		/* Send a message to all other CPUs */
+		send_IPI_allbutself(DEBUGGER_NMI_IPI);
+}
+
+/**
+ * stop_this_cpu - Callback to stop a CPU.
+ * @unused: Callback context (ignored).
+ */
+void stop_this_cpu(void *unused)
+{
+	static volatile int stopflag;
+	unsigned long flags;
+
+#ifdef CONFIG_GDBSTUB
+	/* In case of single stepping smp_send_stop by other CPU,
+	 * clear procindebug to avoid deadlock.
+	 */
+	atomic_set(&procindebug[smp_processor_id()], 0);
+#endif	/* CONFIG_GDBSTUB */
+
+	flags = arch_local_cli_save();
+	set_cpu_online(smp_processor_id(), false);
+
+	while (!stopflag)
+		cpu_relax();
+
+	set_cpu_online(smp_processor_id(), true);
+	arch_local_irq_restore(flags);
+}
+
+/**
+ * smp_send_stop - Send a stop request to all CPUs.
+ */
+void smp_send_stop(void)
+{
+	smp_nmi_call_function(stop_this_cpu, NULL, 0);
+}
+
+/**
+ * smp_reschedule_interrupt - Reschedule IPI handler
+ * @irq: The interrupt number.
+ * @dev_id: The device ID.
+ *
+ * Returns IRQ_HANDLED to indicate we handled the interrupt successfully.
+ */
+static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id)
+{
+	scheduler_ipi();
+	return IRQ_HANDLED;
+}
+
+/**
+ * smp_call_function_interrupt - Call function IPI handler
+ * @irq: The interrupt number.
+ * @dev_id: The device ID.
+ *
+ * Returns IRQ_HANDLED to indicate we handled the interrupt successfully.
+ */
+static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id)
+{
+	/* generic_smp_call_function_interrupt(); */
+	generic_smp_call_function_single_interrupt();
+	return IRQ_HANDLED;
+}
+
+/**
+ * smp_nmi_call_function_interrupt - Non-maskable call function IPI handler
+ */
+void smp_nmi_call_function_interrupt(void)
+{
+	smp_call_func_t func = nmi_call_data->func;
+	void *info = nmi_call_data->info;
+	int wait = nmi_call_data->wait;
+
+	/* Notify the initiating CPU that I've grabbed the data and am about to
+	 * execute the function
+	 */
+	smp_mb();
+	cpumask_clear_cpu(smp_processor_id(), &nmi_call_data->started);
+	(*func)(info);
+
+	if (wait) {
+		smp_mb();
+		cpumask_clear_cpu(smp_processor_id(),
+				  &nmi_call_data->finished);
+	}
+}
+
+#if !defined(CONFIG_GENERIC_CLOCKEVENTS) || \
+    defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
+/**
+ * smp_ipi_timer_interrupt - Local timer IPI handler
+ * @irq: The interrupt number.
+ * @dev_id: The device ID.
+ *
+ * Returns IRQ_HANDLED to indicate we handled the interrupt successfully.
+ */
+static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id)
+{
+	return local_timer_interrupt();
+}
+#endif
+
+void __init smp_init_cpus(void)
+{
+	int i;
+	for (i = 0; i < NR_CPUS; i++) {
+		set_cpu_possible(i, true);
+		set_cpu_present(i, true);
+	}
+}
+
+/**
+ * smp_cpu_init - Initialise AP in start_secondary.
+ *
+ * For this Application Processor, set up init_mm, initialise FPU and set
+ * interrupt level 0-6 setting.
+ */
+static void __init smp_cpu_init(void)
+{
+	unsigned long flags;
+	int cpu_id = smp_processor_id();
+	u16 tmp16;
+
+	if (test_and_set_bit(cpu_id, &cpu_initialized)) {
+		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu_id);
+		for (;;)
+			local_irq_enable();
+	}
+	printk(KERN_INFO "Initializing CPU#%d\n", cpu_id);
+
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+	BUG_ON(current->mm);
+
+	enter_lazy_tlb(&init_mm, current);
+
+	/* Force FPU initialization */
+	clear_using_fpu(current);
+
+	GxICR(CALL_FUNC_SINGLE_IPI) = CALL_FUNCTION_GxICR_LV | GxICR_DETECT;
+	mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI);
+
+	GxICR(LOCAL_TIMER_IPI) = LOCAL_TIMER_GxICR_LV | GxICR_DETECT;
+	mn10300_ipi_enable(LOCAL_TIMER_IPI);
+
+	GxICR(RESCHEDULE_IPI) = RESCHEDULE_GxICR_LV | GxICR_DETECT;
+	mn10300_ipi_enable(RESCHEDULE_IPI);
+
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+	GxICR(FLUSH_CACHE_IPI) = FLUSH_CACHE_GxICR_LV | GxICR_DETECT;
+	mn10300_ipi_enable(FLUSH_CACHE_IPI);
+#endif
+
+	mn10300_ipi_shutdown(SMP_BOOT_IRQ);
+
+	/* Set up the non-maskable call function IPI */
+	flags = arch_local_cli_save();
+	GxICR(CALL_FUNCTION_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT;
+	tmp16 = GxICR(CALL_FUNCTION_NMI_IPI);
+	arch_local_irq_restore(flags);
+}
+
+/**
+ * smp_prepare_cpu_init - Initialise CPU in startup_secondary
+ *
+ * Set interrupt level 0-6 setting and init ICR of the kernel debugger.
+ */
+void smp_prepare_cpu_init(void)
+{
+	int loop;
+
+	/* Set the interrupt vector registers */
+	IVAR0 = EXCEP_IRQ_LEVEL0;
+	IVAR1 = EXCEP_IRQ_LEVEL1;
+	IVAR2 = EXCEP_IRQ_LEVEL2;
+	IVAR3 = EXCEP_IRQ_LEVEL3;
+	IVAR4 = EXCEP_IRQ_LEVEL4;
+	IVAR5 = EXCEP_IRQ_LEVEL5;
+	IVAR6 = EXCEP_IRQ_LEVEL6;
+
+	/* Disable all interrupts and set to priority 6 (lowest) */
+	for (loop = 0; loop < GxICR_NUM_IRQS; loop++)
+		GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
+
+#ifdef CONFIG_KERNEL_DEBUGGER
+	/* initialise the kernel debugger interrupt */
+	do {
+		unsigned long flags;
+		u16 tmp16;
+
+		flags = arch_local_cli_save();
+		GxICR(DEBUGGER_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT;
+		tmp16 = GxICR(DEBUGGER_NMI_IPI);
+		arch_local_irq_restore(flags);
+	} while (0);
+#endif
+}
+
+/**
+ * start_secondary - Activate a secondary CPU (AP)
+ * @unused: Thread parameter (ignored).
+ */
+int __init start_secondary(void *unused)
+{
+	smp_cpu_init();
+	smp_callin();
+	while (!cpumask_test_cpu(smp_processor_id(), &smp_commenced_mask))
+		cpu_relax();
+
+	local_flush_tlb();
+	preempt_disable();
+	smp_online();
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+	init_clockevents();
+#endif
+	cpu_startup_entry(CPUHP_ONLINE);
+	return 0;
+}
+
+/**
+ * smp_prepare_cpus - Boot up secondary CPUs (APs)
+ * @max_cpus: Maximum number of CPUs to boot.
+ *
+ * Call do_boot_cpu, and boot up APs.
+ */
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	int phy_id;
+
+	/* Setup boot CPU information */
+	smp_store_cpu_info(0);
+	smp_tune_scheduling();
+
+	init_ipi();
+
+	/* If SMP should be disabled, then finish */
+	if (max_cpus == 0) {
+		printk(KERN_INFO "SMP mode deactivated.\n");
+		goto smp_done;
+	}
+
+	/* Boot secondary CPUs (for which phy_id > 0) */
+	for (phy_id = 0; phy_id < NR_CPUS; phy_id++) {
+		/* Don't boot primary CPU */
+		if (max_cpus <= cpucount + 1)
+			continue;
+		if (phy_id != 0)
+			do_boot_cpu(phy_id);
+		set_cpu_possible(phy_id, true);
+		smp_show_cpu_info(phy_id);
+	}
+
+smp_done:
+	Dprintk("Boot done.\n");
+}
+
+/**
+ * smp_store_cpu_info - Save a CPU's information
+ * @cpu: The CPU to save for.
+ *
+ * Save boot_cpu_data and jiffy for the specified CPU.
+ */
+static void __init smp_store_cpu_info(int cpu)
+{
+	struct mn10300_cpuinfo *ci = &cpu_data[cpu];
+
+	*ci = boot_cpu_data;
+	ci->loops_per_jiffy = loops_per_jiffy;
+	ci->type = CPUREV;
+}
+
+/**
+ * smp_tune_scheduling - Set time slice value
+ *
+ * Nothing to do here.
+ */
+static void __init smp_tune_scheduling(void)
+{
+}
+
+/**
+ * do_boot_cpu: Boot up one CPU
+ * @phy_id: Physical ID of CPU to boot.
+ *
+ * Send an IPI to a secondary CPU to boot it.  Returns 0 on success, 1
+ * otherwise.
+ */
+static int __init do_boot_cpu(int phy_id)
+{
+	struct task_struct *idle;
+	unsigned long send_status, callin_status;
+	int timeout, cpu_id;
+
+	send_status = GxICR_REQUEST;
+	callin_status = 0;
+	timeout = 0;
+	cpu_id = phy_id;
+
+	cpucount++;
+
+	/* Create idle thread for this CPU */
+	idle = fork_idle(cpu_id);
+	if (IS_ERR(idle))
+		panic("Failed fork for CPU#%d.", cpu_id);
+
+	idle->thread.pc = (unsigned long)start_secondary;
+
+	printk(KERN_NOTICE "Booting CPU#%d\n", cpu_id);
+	start_stack[cpu_id - 1] = idle->thread.sp;
+
+	task_thread_info(idle)->cpu = cpu_id;
+
+	/* Send boot IPI to AP */
+	send_IPI_mask(cpumask_of(phy_id), SMP_BOOT_IRQ);
+
+	Dprintk("Waiting for send to finish...\n");
+
+	/* Wait for AP's IPI receive in 100[ms] */
+	do {
+		udelay(1000);
+		send_status =
+			CROSS_GxICR(SMP_BOOT_IRQ, phy_id) & GxICR_REQUEST;
+	} while (send_status == GxICR_REQUEST && timeout++ < 100);
+
+	Dprintk("Waiting for cpu_callin_map.\n");
+
+	if (send_status == 0) {
+		/* Allow AP to start initializing */
+		cpumask_set_cpu(cpu_id, &cpu_callout_map);
+
+		/* Wait for setting cpu_callin_map */
+		timeout = 0;
+		do {
+			udelay(1000);
+			callin_status = cpumask_test_cpu(cpu_id,
+							 &cpu_callin_map);
+		} while (callin_status == 0 && timeout++ < 5000);
+
+		if (callin_status == 0)
+			Dprintk("Not responding.\n");
+	} else {
+		printk(KERN_WARNING "IPI not delivered.\n");
+	}
+
+	if (send_status == GxICR_REQUEST || callin_status == 0) {
+		cpumask_clear_cpu(cpu_id, &cpu_callout_map);
+		cpumask_clear_cpu(cpu_id, &cpu_callin_map);
+		cpumask_clear_cpu(cpu_id, &cpu_initialized);
+		cpucount--;
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * smp_show_cpu_info - Show SMP CPU information
+ * @cpu: The CPU of interest.
+ */
+static void __init smp_show_cpu_info(int cpu)
+{
+	struct mn10300_cpuinfo *ci = &cpu_data[cpu];
+
+	printk(KERN_INFO
+	       "CPU#%d : ioclk speed: %lu.%02luMHz : bogomips : %lu.%02lu\n",
+	       cpu,
+	       MN10300_IOCLK / 1000000,
+	       (MN10300_IOCLK / 10000) % 100,
+	       ci->loops_per_jiffy / (500000 / HZ),
+	       (ci->loops_per_jiffy / (5000 / HZ)) % 100);
+}
+
+/**
+ * smp_callin - Set cpu_callin_map of the current CPU ID
+ */
+static void __init smp_callin(void)
+{
+	unsigned long timeout;
+	int cpu;
+
+	cpu = smp_processor_id();
+	timeout = jiffies + (2 * HZ);
+
+	if (cpumask_test_cpu(cpu, &cpu_callin_map)) {
+		printk(KERN_ERR "CPU#%d already present.\n", cpu);
+		BUG();
+	}
+	Dprintk("CPU#%d waiting for CALLOUT\n", cpu);
+
+	/* Wait for AP startup 2s total */
+	while (time_before(jiffies, timeout)) {
+		if (cpumask_test_cpu(cpu, &cpu_callout_map))
+			break;
+		cpu_relax();
+	}
+
+	if (!time_before(jiffies, timeout)) {
+		printk(KERN_ERR
+		       "BUG: CPU#%d started up but did not get a callout!\n",
+		       cpu);
+		BUG();
+	}
+
+#ifdef CONFIG_CALIBRATE_DELAY
+	calibrate_delay();		/* Get our bogomips */
+#endif
+
+	/* Save our processor parameters */
+	smp_store_cpu_info(cpu);
+
+	/* Allow the boot processor to continue */
+	cpumask_set_cpu(cpu, &cpu_callin_map);
+}
+
+/**
+ * smp_online - Set cpu_online_mask
+ */
+static void __init smp_online(void)
+{
+	int cpu;
+
+	cpu = smp_processor_id();
+
+	notify_cpu_starting(cpu);
+
+	set_cpu_online(cpu, true);
+
+	local_irq_enable();
+}
+
+/**
+ * smp_cpus_done -
+ * @max_cpus: Maximum CPU count.
+ *
+ * Do nothing.
+ */
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+}
+
+/*
+ * smp_prepare_boot_cpu - Set up stuff for the boot processor.
+ *
+ * Set up the cpu_online_mask, cpu_callout_map and cpu_callin_map of the boot
+ * processor (CPU 0).
+ */
+void smp_prepare_boot_cpu(void)
+{
+	cpumask_set_cpu(0, &cpu_callout_map);
+	cpumask_set_cpu(0, &cpu_callin_map);
+	current_thread_info()->cpu = 0;
+}
+
+/*
+ * initialize_secondary - Initialise a secondary CPU (Application Processor).
+ *
+ * Set SP register and jump to thread's PC address.
+ */
+void initialize_secondary(void)
+{
+	asm volatile (
+		"mov	%0,sp	\n"
+		"jmp	(%1)	\n"
+		:
+		: "a"(current->thread.sp), "a"(current->thread.pc));
+}
+
+/**
+ * __cpu_up - Set smp_commenced_mask for the nominated CPU
+ * @cpu: The target CPU.
+ */
+int __cpu_up(unsigned int cpu, struct task_struct *tidle)
+{
+	int timeout;
+
+#ifdef CONFIG_HOTPLUG_CPU
+	if (sleep_mode[cpu])
+		run_wakeup_cpu(cpu);
+#endif /* CONFIG_HOTPLUG_CPU */
+
+	cpumask_set_cpu(cpu, &smp_commenced_mask);
+
+	/* Wait 5s total for a response */
+	for (timeout = 0 ; timeout < 5000 ; timeout++) {
+		if (cpu_online(cpu))
+			break;
+		udelay(1000);
+	}
+
+	BUG_ON(!cpu_online(cpu));
+	return 0;
+}
+
+/**
+ * setup_profiling_timer - Set up the profiling timer
+ * @multiplier - The frequency multiplier to use
+ *
+ * The frequency of the profiling timer can be changed by writing a multiplier
+ * value into /proc/profile.
+ */
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return -EINVAL;
+}
+
+/*
+ * CPU hotplug routines
+ */
+#ifdef CONFIG_HOTPLUG_CPU
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+	int cpu, ret;
+
+	for_each_cpu(cpu) {
+		ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL);
+		if (ret)
+			printk(KERN_WARNING
+			       "topology_init: register_cpu %d failed (%d)\n",
+			       cpu, ret);
+	}
+	return 0;
+}
+
+subsys_initcall(topology_init);
+
+int __cpu_disable(void)
+{
+	int cpu = smp_processor_id();
+	if (cpu == 0)
+		return -EBUSY;
+
+	migrate_irqs();
+	cpumask_clear_cpu(cpu, &mm_cpumask(current->active_mm));
+	return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+	run_sleep_cpu(cpu);
+}
+
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+static inline void hotplug_cpu_disable_cache(void)
+{
+	int tmp;
+	asm volatile(
+		"	movhu	(%1),%0	\n"
+		"	and	%2,%0	\n"
+		"	movhu	%0,(%1)	\n"
+		"1:	movhu	(%1),%0	\n"
+		"	btst	%3,%0	\n"
+		"	bne	1b	\n"
+		: "=&r"(tmp)
+		: "a"(&CHCTR),
+		  "i"(~(CHCTR_ICEN | CHCTR_DCEN)),
+		  "i"(CHCTR_ICBUSY | CHCTR_DCBUSY)
+		: "memory", "cc");
+}
+
+static inline void hotplug_cpu_enable_cache(void)
+{
+	int tmp;
+	asm volatile(
+		"movhu	(%1),%0	\n"
+		"or	%2,%0	\n"
+		"movhu	%0,(%1)	\n"
+		: "=&r"(tmp)
+		: "a"(&CHCTR),
+		  "i"(CHCTR_ICEN | CHCTR_DCEN)
+		: "memory", "cc");
+}
+
+static inline void hotplug_cpu_invalidate_cache(void)
+{
+	int tmp;
+	asm volatile (
+		"movhu	(%1),%0	\n"
+		"or	%2,%0	\n"
+		"movhu	%0,(%1)	\n"
+		: "=&r"(tmp)
+		: "a"(&CHCTR),
+		  "i"(CHCTR_ICINV | CHCTR_DCINV)
+		: "cc");
+}
+
+#else /* CONFIG_MN10300_CACHE_ENABLED */
+#define hotplug_cpu_disable_cache()	do {} while (0)
+#define hotplug_cpu_enable_cache()	do {} while (0)
+#define hotplug_cpu_invalidate_cache()	do {} while (0)
+#endif /* CONFIG_MN10300_CACHE_ENABLED */
+
+/**
+ * hotplug_cpu_nmi_call_function - Call a function on other CPUs for hotplug
+ * @cpumask: List of target CPUs.
+ * @func: The function to call on those CPUs.
+ * @info: The context data for the function to be called.
+ * @wait: Whether to wait for the calls to complete.
+ *
+ * Non-maskably call a function on another CPU for hotplug purposes.
+ *
+ * This function must be called with maskable interrupts disabled.
+ */
+static int hotplug_cpu_nmi_call_function(cpumask_t cpumask,
+					 smp_call_func_t func, void *info,
+					 int wait)
+{
+	/*
+	 * The address and the size of nmi_call_func_mask_data
+	 * need to be aligned on L1_CACHE_BYTES.
+	 */
+	static struct nmi_call_data_struct nmi_call_func_mask_data
+		__cacheline_aligned;
+	unsigned long start, end;
+
+	start = (unsigned long)&nmi_call_func_mask_data;
+	end = start + sizeof(struct nmi_call_data_struct);
+
+	nmi_call_func_mask_data.func = func;
+	nmi_call_func_mask_data.info = info;
+	nmi_call_func_mask_data.started = cpumask;
+	nmi_call_func_mask_data.wait = wait;
+	if (wait)
+		nmi_call_func_mask_data.finished = cpumask;
+
+	spin_lock(&smp_nmi_call_lock);
+	nmi_call_data = &nmi_call_func_mask_data;
+	mn10300_local_dcache_flush_range(start, end);
+	smp_wmb();
+
+	send_IPI_mask(cpumask, CALL_FUNCTION_NMI_IPI);
+
+	do {
+		mn10300_local_dcache_inv_range(start, end);
+		barrier();
+	} while (!cpumask_empty(&nmi_call_func_mask_data.started));
+
+	if (wait) {
+		do {
+			mn10300_local_dcache_inv_range(start, end);
+			barrier();
+		} while (!cpumask_empty(&nmi_call_func_mask_data.finished));
+	}
+
+	spin_unlock(&smp_nmi_call_lock);
+	return 0;
+}
+
+static void restart_wakeup_cpu(void)
+{
+	unsigned int cpu = smp_processor_id();
+
+	cpumask_set_cpu(cpu, &cpu_callin_map);
+	local_flush_tlb();
+	set_cpu_online(cpu, true);
+	smp_wmb();
+}
+
+static void prepare_sleep_cpu(void *unused)
+{
+	sleep_mode[smp_processor_id()] = 1;
+	smp_mb();
+	mn10300_local_dcache_flush_inv();
+	hotplug_cpu_disable_cache();
+	hotplug_cpu_invalidate_cache();
+}
+
+/* when this function called, IE=0, NMID=0. */
+static void sleep_cpu(void *unused)
+{
+	unsigned int cpu_id = smp_processor_id();
+	/*
+	 * CALL_FUNCTION_NMI_IPI for wakeup_cpu() shall not be requested,
+	 * before this cpu goes in SLEEP mode.
+	 */
+	do {
+		smp_mb();
+		__sleep_cpu();
+	} while (sleep_mode[cpu_id]);
+	restart_wakeup_cpu();
+}
+
+static void run_sleep_cpu(unsigned int cpu)
+{
+	unsigned long flags;
+	cpumask_t cpumask;
+
+	cpumask_copy(&cpumask, &cpumask_of(cpu));
+	flags = arch_local_cli_save();
+	hotplug_cpu_nmi_call_function(cpumask, prepare_sleep_cpu, NULL, 1);
+	hotplug_cpu_nmi_call_function(cpumask, sleep_cpu, NULL, 0);
+	udelay(1);		/* delay for the cpu to sleep. */
+	arch_local_irq_restore(flags);
+}
+
+static void wakeup_cpu(void)
+{
+	hotplug_cpu_invalidate_cache();
+	hotplug_cpu_enable_cache();
+	smp_mb();
+	sleep_mode[smp_processor_id()] = 0;
+}
+
+static void run_wakeup_cpu(unsigned int cpu)
+{
+	unsigned long flags;
+
+	flags = arch_local_cli_save();
+#if NR_CPUS == 2
+	mn10300_local_dcache_flush_inv();
+#else
+	/*
+	 * Before waking up the cpu,
+	 * all online cpus should stop and flush D-Cache for global data.
+	 */
+#error not support NR_CPUS > 2, when CONFIG_HOTPLUG_CPU=y.
+#endif
+	hotplug_cpu_nmi_call_function(cpumask_of(cpu), wakeup_cpu, NULL, 1);
+	arch_local_irq_restore(flags);
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/mn10300/kernel/switch_to.S b/arch/mn10300/kernel/switch_to.S
new file mode 100644
index 0000000..de3e74f
--- /dev/null
+++ b/arch/mn10300/kernel/switch_to.S
@@ -0,0 +1,179 @@
+###############################################################################
+#
+# MN10300 Context switch operation
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/cpu-regs.h>
+#ifdef CONFIG_SMP
+#include <proc/smp-regs.h>
+#endif /* CONFIG_SMP */
+
+	.text
+
+###############################################################################
+#
+# struct task_struct *__switch_to(struct thread_struct *prev,
+#				  struct thread_struct *next,
+#				  struct task_struct *prev_task)
+#
+###############################################################################
+ENTRY(__switch_to)
+	movm	[d2,d3,a2,a3,exreg1],(sp)
+	or	EPSW_NMID,epsw
+
+	mov	(44,sp),d2
+
+	mov	d0,a0
+	mov	d1,a1
+
+	# save prev context
+	mov	__switch_back,d0
+	mov	sp,a2
+	mov	a2,(THREAD_SP,a0)
+	mov	a3,(THREAD_A3,a0)
+
+#ifdef CONFIG_KGDB
+	btst	0xff,(kgdb_single_step)
+	bne	__switch_to__lift_sstep_bp
+__switch_to__continue:
+#endif
+	mov	d0,(THREAD_PC,a0)
+
+	mov	(THREAD_A3,a1),a3
+	mov	(THREAD_SP,a1),a2
+
+	# switch
+	mov	a2,sp
+
+	# load next context
+	GET_THREAD_INFO a2
+	mov	a2,(__current_ti)
+	mov	(TI_task,a2),a2
+	mov	a2,(__current)
+#ifdef CONFIG_MN10300_CURRENT_IN_E2
+	mov	a2,e2
+#endif
+
+	mov	(THREAD_PC,a1),a2
+	mov	d2,d0			# for ret_from_fork
+	mov	d0,a0			# for __switch_to
+
+	jmp	(a2)
+
+__switch_back:
+	and	~EPSW_NMID,epsw
+	ret	[d2,d3,a2,a3,exreg1],32
+
+#ifdef CONFIG_KGDB
+###############################################################################
+#
+# Lift the single-step breakpoints when the task being traced is switched out
+# A0 = prev
+# A1 = next
+#
+###############################################################################
+__switch_to__lift_sstep_bp:
+	add	-12,sp
+	mov	a0,e4
+	mov	a1,e5
+
+	# Clear the single-step flag to prevent us coming this way until we get
+	# switched back in
+	bclr	0xff,(kgdb_single_step)
+
+	# Remove first breakpoint
+	mov	(kgdb_sstep_bp_addr),a2
+	cmp	0,a2
+	beq	1f
+	movbu	(kgdb_sstep_bp),d0
+	movbu	d0,(a2)
+#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
+	mov	a2,d0
+	mov	a2,d1
+	add	1,d1
+	calls	flush_icache_range
+#endif
+1:
+
+	# Remove second breakpoint
+	mov	(kgdb_sstep_bp_addr+4),a2
+	cmp	0,a2
+	beq	2f
+	movbu	(kgdb_sstep_bp+1),d0
+	movbu	d0,(a2)
+#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
+	mov	a2,d0
+	mov	a2,d1
+	add	1,d1
+	calls	flush_icache_range
+#endif
+2:
+
+	# Change the resumption address and return
+	mov	__switch_back__reinstall_sstep_bp,d0
+	mov	e4,a0
+	mov	e5,a1
+	add	12,sp
+	bra	__switch_to__continue
+
+###############################################################################
+#
+# Reinstall the single-step breakpoints when the task being traced is switched
+# back in (A1 points to the new thread_struct).
+#
+###############################################################################
+__switch_back__reinstall_sstep_bp:
+	add	-12,sp
+	mov	a0,e4			# save the return value
+	mov	0xff,d3
+
+	# Reinstall first breakpoint
+	mov	(kgdb_sstep_bp_addr),a2
+	cmp	0,a2
+	beq	1f
+	movbu	(a2),d0
+	movbu	d0,(kgdb_sstep_bp)
+	movbu	d3,(a2)
+#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
+	mov	a2,d0
+	mov	a2,d1
+	add	1,d1
+	calls	flush_icache_range
+#endif
+1:
+
+	# Reinstall second breakpoint
+	mov	(kgdb_sstep_bp_addr+4),a2
+	cmp	0,a2
+	beq	2f
+	movbu	(a2),d0
+	movbu	d0,(kgdb_sstep_bp+1)
+	movbu	d3,(a2)
+#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
+	mov	a2,d0
+	mov	a2,d1
+	add	1,d1
+	calls	flush_icache_range
+#endif
+2:
+
+	mov	d3,(kgdb_single_step)
+
+	# Restore the return value (the previous thread_struct pointer)
+	mov	e4,a0
+	mov	a0,d0
+	add	12,sp
+	bra	__switch_back
+
+#endif /* CONFIG_KGDB */
diff --git a/arch/mn10300/kernel/sys_mn10300.c b/arch/mn10300/kernel/sys_mn10300.c
new file mode 100644
index 0000000..815f135
--- /dev/null
+++ b/arch/mn10300/kernel/sys_mn10300.c
@@ -0,0 +1,33 @@
+/* MN10300 Weird system calls
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/tty.h>
+
+#include <asm/uaccess.h>
+
+asmlinkage long old_mmap(unsigned long addr, unsigned long len,
+			 unsigned long prot, unsigned long flags,
+			 unsigned long fd, unsigned long offset)
+{
+	if (offset & ~PAGE_MASK)
+		return -EINVAL;
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+}
diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c
new file mode 100644
index 0000000..67c6416
--- /dev/null
+++ b/arch/mn10300/kernel/time.c
@@ -0,0 +1,124 @@
+/* MN10300 Low level time management
+ *
+ * Copyright (C) 2007-2008 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from arch/i386/kernel/time.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/profile.h>
+#include <linux/cnt32_to_63.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+#include <asm/processor.h>
+#include <asm/intctl-regs.h>
+#include <asm/rtc.h>
+#include "internal.h"
+
+static unsigned long mn10300_last_tsc;	/* time-stamp counter at last time
+					 * interrupt occurred */
+
+static unsigned long sched_clock_multiplier;
+
+/*
+ * scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+	union {
+		unsigned long long ll;
+		unsigned l[2];
+	} tsc64, result;
+	unsigned long tmp;
+	unsigned product[3]; /* 96-bit intermediate value */
+
+	/* cnt32_to_63() is not safe with preemption */
+	preempt_disable();
+
+	/* expand the tsc to 64-bits.
+	 * - sched_clock() must be called once a minute or better or the
+	 *   following will go horribly wrong - see cnt32_to_63()
+	 */
+	tsc64.ll = cnt32_to_63(get_cycles()) & 0x7fffffffffffffffULL;
+
+	preempt_enable();
+
+	/* scale the 64-bit TSC value to a nanosecond value via a 96-bit
+	 * intermediate
+	 */
+	asm("mulu	%2,%0,%3,%0	\n"	/* LSW * mult ->  0:%3:%0 */
+	    "mulu	%2,%1,%2,%1	\n"	/* MSW * mult -> %2:%1:0 */
+	    "add	%3,%1		\n"
+	    "addc	0,%2		\n"	/* result in %2:%1:%0 */
+	    : "=r"(product[0]), "=r"(product[1]), "=r"(product[2]), "=r"(tmp)
+	    :  "0"(tsc64.l[0]),  "1"(tsc64.l[1]),  "2"(sched_clock_multiplier)
+	    : "cc");
+
+	result.l[0] = product[1] << 16 | product[0] >> 16;
+	result.l[1] = product[2] << 16 | product[1] >> 16;
+
+	return result.ll;
+}
+
+/*
+ * initialise the scheduler clock
+ */
+static void __init mn10300_sched_clock_init(void)
+{
+	sched_clock_multiplier =
+		__muldiv64u(NSEC_PER_SEC, 1 << 16, MN10300_TSCCLK);
+}
+
+/**
+ * local_timer_interrupt - Local timer interrupt handler
+ *
+ * Handle local timer interrupts for this CPU.  They may have been propagated
+ * to this CPU from the CPU that actually gets them by way of an IPI.
+ */
+irqreturn_t local_timer_interrupt(void)
+{
+	profile_tick(CPU_PROFILING);
+	update_process_times(user_mode(get_irq_regs()));
+	return IRQ_HANDLED;
+}
+
+/*
+ * initialise the various timers used by the main part of the kernel
+ */
+void __init time_init(void)
+{
+	/* we need the prescalar running to be able to use IOCLK/8
+	 * - IOCLK runs at 1/4 (ST5 open) or 1/8 (ST5 closed) internal CPU clock
+	 * - IOCLK runs at Fosc rate (crystal speed)
+	 */
+	TMPSCNT |= TMPSCNT_ENABLE;
+
+	init_clocksource();
+
+	printk(KERN_INFO
+	       "timestamp counter I/O clock running at %lu.%02lu"
+	       " (calibrated against RTC)\n",
+	       MN10300_TSCCLK / 1000000, (MN10300_TSCCLK / 10000) % 100);
+
+	mn10300_last_tsc = read_timestamp_counter();
+
+	init_clockevents();
+
+#ifdef CONFIG_MN10300_WD_TIMER
+	/* start the watchdog timer */
+	watchdog_go();
+#endif
+
+	mn10300_sched_clock_init();
+}
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c
new file mode 100644
index 0000000..a7a987c
--- /dev/null
+++ b/arch/mn10300/kernel/traps.c
@@ -0,0 +1,616 @@
+/* MN10300 Exception handling
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/kallsyms.h>
+#include <linux/pci.h>
+#include <linux/kdebug.h>
+#include <linux/bug.h>
+#include <linux/irq.h>
+#include <linux/export.h>
+#include <asm/processor.h>
+#include <linux/uaccess.h>
+#include <asm/io.h>
+#include <linux/atomic.h>
+#include <asm/smp.h>
+#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/cpu-regs.h>
+#include <asm/busctl-regs.h>
+#include <unit/leds.h>
+#include <asm/fpu.h>
+#include <asm/sections.h>
+#include <asm/debugger.h>
+#include "internal.h"
+
+#if (CONFIG_INTERRUPT_VECTOR_BASE & 0xffffff)
+#error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!"
+#endif
+
+int kstack_depth_to_print = 24;
+
+spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock);
+
+struct exception_to_signal_map {
+	u8	signo;
+	u32	si_code;
+};
+
+static const struct exception_to_signal_map exception_to_signal_map[256] = {
+	/* MMU exceptions */
+	[EXCEP_ITLBMISS >> 3]	= { 0, 0 },
+	[EXCEP_DTLBMISS >> 3]	= { 0, 0 },
+	[EXCEP_IAERROR >> 3]	= { 0, 0 },
+	[EXCEP_DAERROR >> 3]	= { 0, 0 },
+
+	/* system exceptions */
+	[EXCEP_TRAP >> 3]	= { SIGTRAP,	TRAP_BRKPT },
+	[EXCEP_ISTEP >> 3]	= { SIGTRAP,	TRAP_TRACE },	/* Monitor */
+	[EXCEP_IBREAK >> 3]	= { SIGTRAP,	TRAP_HWBKPT },	/* Monitor */
+	[EXCEP_OBREAK >> 3]	= { SIGTRAP,	TRAP_HWBKPT },	/* Monitor */
+	[EXCEP_PRIVINS >> 3]	= { SIGILL,	ILL_PRVOPC },
+	[EXCEP_UNIMPINS >> 3]	= { SIGILL,	ILL_ILLOPC },
+	[EXCEP_UNIMPEXINS >> 3]	= { SIGILL,	ILL_ILLOPC },
+	[EXCEP_MEMERR >> 3]	= { SIGSEGV,	SEGV_ACCERR },
+	[EXCEP_MISALIGN >> 3]	= { SIGBUS,	BUS_ADRALN },
+	[EXCEP_BUSERROR >> 3]	= { SIGBUS,	BUS_ADRERR },
+	[EXCEP_ILLINSACC >> 3]	= { SIGSEGV,	SEGV_ACCERR },
+	[EXCEP_ILLDATACC >> 3]	= { SIGSEGV,	SEGV_ACCERR },
+	[EXCEP_IOINSACC >> 3]	= { SIGSEGV,	SEGV_ACCERR },
+	[EXCEP_PRIVINSACC >> 3]	= { SIGSEGV,	SEGV_ACCERR }, /* userspace */
+	[EXCEP_PRIVDATACC >> 3]	= { SIGSEGV,	SEGV_ACCERR }, /* userspace */
+	[EXCEP_DATINSACC >> 3]	= { SIGSEGV,	SEGV_ACCERR },
+	[EXCEP_DOUBLE_FAULT >> 3] = { SIGILL,	ILL_BADSTK },
+
+	/* FPU exceptions */
+	[EXCEP_FPU_DISABLED >> 3] = { SIGILL,	ILL_COPROC },
+	[EXCEP_FPU_UNIMPINS >> 3] = { SIGILL,	ILL_COPROC },
+	[EXCEP_FPU_OPERATION >> 3] = { SIGFPE,	FPE_INTDIV },
+
+	/* interrupts */
+	[EXCEP_WDT >> 3]	= { SIGALRM,	0 },
+	[EXCEP_NMI >> 3]	= { SIGQUIT,	0 },
+	[EXCEP_IRQ_LEVEL0 >> 3]	= { SIGINT,	0 },
+	[EXCEP_IRQ_LEVEL1 >> 3]	= { 0, 0 },
+	[EXCEP_IRQ_LEVEL2 >> 3]	= { 0, 0 },
+	[EXCEP_IRQ_LEVEL3 >> 3]	= { 0, 0 },
+	[EXCEP_IRQ_LEVEL4 >> 3]	= { 0, 0 },
+	[EXCEP_IRQ_LEVEL5 >> 3]	= { 0, 0 },
+	[EXCEP_IRQ_LEVEL6 >> 3]	= { 0, 0 },
+
+	/* system calls */
+	[EXCEP_SYSCALL0 >> 3]	= { 0, 0 },
+	[EXCEP_SYSCALL1 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL2 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL3 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL4 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL5 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL6 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL7 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL8 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL9 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL10 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL11 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL12 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL13 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL14 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL15 >> 3]	= { SIGABRT,	0 },
+};
+
+/*
+ * Handle kernel exceptions.
+ *
+ * See if there's a fixup handler we can force a jump to when an exception
+ * happens due to something kernel code did
+ */
+int die_if_no_fixup(const char *str, struct pt_regs *regs,
+		    enum exception_code code)
+{
+	u8 opcode;
+	int signo, si_code;
+
+	if (user_mode(regs))
+		return 0;
+
+	peripheral_leds_display_exception(code);
+
+	signo = exception_to_signal_map[code >> 3].signo;
+	si_code = exception_to_signal_map[code >> 3].si_code;
+
+	switch (code) {
+		/* see if we can fixup the kernel accessing memory */
+	case EXCEP_ITLBMISS:
+	case EXCEP_DTLBMISS:
+	case EXCEP_IAERROR:
+	case EXCEP_DAERROR:
+	case EXCEP_MEMERR:
+	case EXCEP_MISALIGN:
+	case EXCEP_BUSERROR:
+	case EXCEP_ILLDATACC:
+	case EXCEP_IOINSACC:
+	case EXCEP_PRIVINSACC:
+	case EXCEP_PRIVDATACC:
+	case EXCEP_DATINSACC:
+		if (fixup_exception(regs))
+			return 1;
+		break;
+
+	case EXCEP_TRAP:
+	case EXCEP_UNIMPINS:
+		if (probe_kernel_read(&opcode, (u8 *)regs->pc, 1) < 0)
+			break;
+		if (opcode == 0xff) {
+			if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0))
+				return 1;
+			if (at_debugger_breakpoint(regs))
+				regs->pc++;
+			signo = SIGTRAP;
+			si_code = TRAP_BRKPT;
+		}
+		break;
+
+	case EXCEP_SYSCALL1 ... EXCEP_SYSCALL14:
+		/* syscall return addr is _after_ the instruction */
+		regs->pc -= 2;
+		break;
+
+	case EXCEP_SYSCALL15:
+		if (report_bug(regs->pc, regs) == BUG_TRAP_TYPE_WARN)
+			return 1;
+
+		/* syscall return addr is _after_ the instruction */
+		regs->pc -= 2;
+		break;
+
+	default:
+		break;
+	}
+
+	if (debugger_intercept(code, signo, si_code, regs) == 0)
+		return 1;
+
+	if (notify_die(DIE_GPF, str, regs, code, 0, 0))
+		return 1;
+
+	/* make the process die as the last resort */
+	die(str, regs, code);
+}
+
+/*
+ * General exception handler
+ */
+asmlinkage void handle_exception(struct pt_regs *regs, u32 intcode)
+{
+	siginfo_t info;
+
+	/* deal with kernel exceptions here */
+	if (die_if_no_fixup(NULL, regs, intcode))
+		return;
+
+	/* otherwise it's a userspace exception */
+	info.si_signo = exception_to_signal_map[intcode >> 3].signo;
+	info.si_code = exception_to_signal_map[intcode >> 3].si_code;
+	info.si_errno = 0;
+	info.si_addr = (void *) regs->pc;
+	force_sig_info(info.si_signo, &info, current);
+}
+
+/*
+ * handle NMI
+ */
+asmlinkage void nmi(struct pt_regs *regs, enum exception_code code)
+{
+	/* see if gdbstub wants to deal with it */
+	if (debugger_intercept(code, SIGQUIT, 0, regs))
+		return;
+
+	printk(KERN_WARNING "--- Register Dump ---\n");
+	show_registers(regs);
+	printk(KERN_WARNING "---------------------\n");
+}
+
+/*
+ * show a stack trace from the specified stack pointer
+ */
+void show_trace(unsigned long *sp)
+{
+	unsigned long bottom, stack, addr, fp, raslot;
+
+	printk(KERN_EMERG "\nCall Trace:\n");
+
+	//stack = (unsigned long)sp;
+	asm("mov sp,%0" : "=a"(stack));
+	asm("mov a3,%0" : "=r"(fp));
+
+	raslot = ULONG_MAX;
+	bottom = (stack + THREAD_SIZE) & ~(THREAD_SIZE - 1);
+	for (; stack < bottom; stack += sizeof(addr)) {
+		addr = *(unsigned long *)stack;
+		if (stack == fp) {
+			if (addr > stack && addr < bottom) {
+				fp = addr;
+				raslot = stack + sizeof(addr);
+				continue;
+			}
+			fp = 0;
+			raslot = ULONG_MAX;
+		}
+
+		if (__kernel_text_address(addr)) {
+			printk(" [<%08lx>]", addr);
+			if (stack >= raslot)
+				raslot = ULONG_MAX;
+			else
+				printk(" ?");
+			print_symbol(" %s", addr);
+			printk("\n");
+		}
+	}
+
+	printk("\n");
+}
+
+/*
+ * show the raw stack from the specified stack pointer
+ */
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+	unsigned long *stack;
+	int i;
+
+	if (!sp)
+		sp = (unsigned long *) &sp;
+
+	stack = sp;
+	printk(KERN_EMERG "Stack:");
+	for (i = 0; i < kstack_depth_to_print; i++) {
+		if (((long) stack & (THREAD_SIZE - 1)) == 0)
+			break;
+		if ((i % 8) == 0)
+			printk(KERN_EMERG "  ");
+		printk("%08lx ", *stack++);
+	}
+
+	show_trace(sp);
+}
+
+/*
+ * dump the register file in the specified exception frame
+ */
+void show_registers_only(struct pt_regs *regs)
+{
+	unsigned long ssp;
+
+	ssp = (unsigned long) regs + sizeof(*regs);
+
+	printk(KERN_EMERG "PC:  %08lx EPSW:  %08lx  SSP: %08lx mode: %s\n",
+	       regs->pc, regs->epsw, ssp, user_mode(regs) ? "User" : "Super");
+	printk(KERN_EMERG "d0:  %08lx   d1:  %08lx   d2: %08lx   d3: %08lx\n",
+	       regs->d0, regs->d1, regs->d2, regs->d3);
+	printk(KERN_EMERG "a0:  %08lx   a1:  %08lx   a2: %08lx   a3: %08lx\n",
+	       regs->a0, regs->a1, regs->a2, regs->a3);
+	printk(KERN_EMERG "e0:  %08lx   e1:  %08lx   e2: %08lx   e3: %08lx\n",
+	       regs->e0, regs->e1, regs->e2, regs->e3);
+	printk(KERN_EMERG "e4:  %08lx   e5:  %08lx   e6: %08lx   e7: %08lx\n",
+	       regs->e4, regs->e5, regs->e6, regs->e7);
+	printk(KERN_EMERG "lar: %08lx   lir: %08lx  mdr: %08lx  usp: %08lx\n",
+	       regs->lar, regs->lir, regs->mdr, regs->sp);
+	printk(KERN_EMERG "cvf: %08lx   crl: %08lx  crh: %08lx  drq: %08lx\n",
+	       regs->mcvf, regs->mcrl, regs->mcrh, regs->mdrq);
+	printk(KERN_EMERG "threadinfo=%p task=%p)\n",
+	       current_thread_info(), current);
+
+	if ((unsigned long) current >= PAGE_OFFSET &&
+	    (unsigned long) current < (unsigned long)high_memory)
+		printk(KERN_EMERG "Process %s (pid: %d)\n",
+		       current->comm, current->pid);
+
+#ifdef CONFIG_SMP
+	printk(KERN_EMERG "CPUID:  %08x\n", CPUID);
+#endif
+	printk(KERN_EMERG "CPUP:   %04hx\n", CPUP);
+	printk(KERN_EMERG "TBR:    %08x\n", TBR);
+	printk(KERN_EMERG "DEAR:   %08x\n", DEAR);
+	printk(KERN_EMERG "sISR:   %08x\n", sISR);
+	printk(KERN_EMERG "NMICR:  %04hx\n", NMICR);
+	printk(KERN_EMERG "BCBERR: %08x\n", BCBERR);
+	printk(KERN_EMERG "BCBEAR: %08x\n", BCBEAR);
+	printk(KERN_EMERG "MMUFCR: %08x\n", MMUFCR);
+	printk(KERN_EMERG "IPTEU : %08x  IPTEL2: %08x\n", IPTEU, IPTEL2);
+	printk(KERN_EMERG "DPTEU:  %08x  DPTEL2: %08x\n", DPTEU, DPTEL2);
+}
+
+/*
+ * dump the registers and the stack
+ */
+void show_registers(struct pt_regs *regs)
+{
+	unsigned long sp;
+	int i;
+
+	show_registers_only(regs);
+
+	if (!user_mode(regs))
+		sp = (unsigned long) regs + sizeof(*regs);
+	else
+		sp = regs->sp;
+
+	/* when in-kernel, we also print out the stack and code at the
+	 * time of the fault..
+	 */
+	if (!user_mode(regs)) {
+		printk(KERN_EMERG "\n");
+		show_stack(current, (unsigned long *) sp);
+
+#if 0
+		printk(KERN_EMERG "\nCode: ");
+		if (regs->pc < PAGE_OFFSET)
+			goto bad;
+
+		for (i = 0; i < 20; i++) {
+			unsigned char c;
+			if (__get_user(c, &((unsigned char *) regs->pc)[i]))
+				goto bad;
+			printk("%02x ", c);
+		}
+#else
+		i = 0;
+#endif
+	}
+
+	printk("\n");
+	return;
+
+#if 0
+bad:
+	printk(KERN_EMERG " Bad PC value.");
+	break;
+#endif
+}
+
+/*
+ *
+ */
+void show_trace_task(struct task_struct *tsk)
+{
+	unsigned long sp = tsk->thread.sp;
+
+	/* User space on another CPU? */
+	if ((sp ^ (unsigned long) tsk) & (PAGE_MASK << 1))
+		return;
+
+	show_trace((unsigned long *) sp);
+}
+
+/*
+ * note the untimely death of part of the kernel
+ */
+void die(const char *str, struct pt_regs *regs, enum exception_code code)
+{
+	console_verbose();
+	spin_lock_irq(&die_lock);
+	printk(KERN_EMERG "\n%s: %04x\n",
+	       str, code & 0xffff);
+	show_registers(regs);
+
+	if (regs->pc >= 0x02000000 && regs->pc < 0x04000000 &&
+	    (regs->epsw & (EPSW_IM | EPSW_IE)) != (EPSW_IM | EPSW_IE)) {
+		printk(KERN_EMERG "Exception in usermode interrupt handler\n");
+		printk(KERN_EMERG "\nPlease connect to kernel debugger !!\n");
+		asm volatile ("0: bra 0b");
+	}
+
+	spin_unlock_irq(&die_lock);
+	do_exit(SIGSEGV);
+}
+
+/*
+ * display the register file when the stack pointer gets clobbered
+ */
+asmlinkage void do_double_fault(struct pt_regs *regs)
+{
+	struct task_struct *tsk = current;
+
+	strcpy(tsk->comm, "emergency tsk");
+	tsk->pid = 0;
+	console_verbose();
+	printk(KERN_EMERG "--- double fault ---\n");
+	show_registers(regs);
+}
+
+/*
+ * asynchronous bus error (external, usually I/O DMA)
+ */
+asmlinkage void io_bus_error(u32 bcberr, u32 bcbear, struct pt_regs *regs)
+{
+	console_verbose();
+
+	printk(KERN_EMERG "Asynchronous I/O Bus Error\n");
+	printk(KERN_EMERG "==========================\n");
+
+	if (bcberr & BCBERR_BEME)
+		printk(KERN_EMERG "- Multiple recorded errors\n");
+
+	printk(KERN_EMERG "- Faulting Buses:%s%s%s\n",
+	       bcberr & BCBERR_BEMR_CI  ? " CPU-Ins-Fetch" : "",
+	       bcberr & BCBERR_BEMR_CD  ? " CPU-Data" : "",
+	       bcberr & BCBERR_BEMR_DMA ? " DMA" : "");
+
+	printk(KERN_EMERG "- %s %s access made to %s at address %08x\n",
+	       bcberr &	BCBERR_BEBST ? "Burst" : "Single",
+	       bcberr &	BCBERR_BERW ? "Read" : "Write",
+	       bcberr &	BCBERR_BESB_MON  ? "Monitor Space" :
+	       bcberr &	BCBERR_BESB_IO   ? "Internal CPU I/O Space" :
+	       bcberr &	BCBERR_BESB_EX   ? "External I/O Bus" :
+	       bcberr &	BCBERR_BESB_OPEX ? "External Memory Bus" :
+	       "On Chip Memory",
+	       bcbear
+	       );
+
+	printk(KERN_EMERG "- Detected by the %s\n",
+	       bcberr&BCBERR_BESD ? "Bus Control Unit" : "Slave Bus");
+
+#ifdef CONFIG_PCI
+#define BRIDGEREGB(X) (*(volatile __u8  *)(0xBE040000 + (X)))
+#define BRIDGEREGW(X) (*(volatile __u16 *)(0xBE040000 + (X)))
+#define BRIDGEREGL(X) (*(volatile __u32 *)(0xBE040000 + (X)))
+
+	printk(KERN_EMERG "- PCI Memory Paging Reg:         %08x\n",
+	       *(volatile __u32 *) (0xBFFFFFF4));
+	printk(KERN_EMERG "- PCI Bridge Base Address 0:     %08x\n",
+	       BRIDGEREGL(PCI_BASE_ADDRESS_0));
+	printk(KERN_EMERG "- PCI Bridge AMPCI Base Address: %08x\n",
+	       BRIDGEREGL(0x48));
+	printk(KERN_EMERG "- PCI Bridge Command:                %04hx\n",
+	       BRIDGEREGW(PCI_COMMAND));
+	printk(KERN_EMERG "- PCI Bridge Status:                 %04hx\n",
+	       BRIDGEREGW(PCI_STATUS));
+	printk(KERN_EMERG "- PCI Bridge Int Status:         %08hx\n",
+	       BRIDGEREGL(0x4c));
+#endif
+
+	printk(KERN_EMERG "\n");
+	show_registers(regs);
+
+	panic("Halted due to asynchronous I/O Bus Error\n");
+}
+
+/*
+ * handle an exception for which a handler has not yet been installed
+ */
+asmlinkage void uninitialised_exception(struct pt_regs *regs,
+					enum exception_code code)
+{
+
+	/* see if gdbstub wants to deal with it */
+	if (debugger_intercept(code, SIGSYS, 0, regs) == 0)
+		return;
+
+	peripheral_leds_display_exception(code);
+	printk(KERN_EMERG "Uninitialised Exception 0x%04x\n", code & 0xFFFF);
+	show_registers(regs);
+
+	for (;;)
+		continue;
+}
+
+/*
+ * set an interrupt stub to jump to a handler
+ * ! NOTE: this does *not* flush the caches
+ */
+void __init __set_intr_stub(enum exception_code code, void *handler)
+{
+	unsigned long addr;
+	u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
+
+	addr = (unsigned long) handler - (unsigned long) vector;
+	vector[0] = 0xdc;		/* JMP handler */
+	vector[1] = addr;
+	vector[2] = addr >> 8;
+	vector[3] = addr >> 16;
+	vector[4] = addr >> 24;
+	vector[5] = 0xcb;
+	vector[6] = 0xcb;
+	vector[7] = 0xcb;
+}
+
+/*
+ * set an interrupt stub to jump to a handler
+ */
+void __init set_intr_stub(enum exception_code code, void *handler)
+{
+	unsigned long addr;
+	u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
+	unsigned long flags;
+
+	addr = (unsigned long) handler - (unsigned long) vector;
+
+	flags = arch_local_cli_save();
+
+	vector[0] = 0xdc;		/* JMP handler */
+	vector[1] = addr;
+	vector[2] = addr >> 8;
+	vector[3] = addr >> 16;
+	vector[4] = addr >> 24;
+	vector[5] = 0xcb;
+	vector[6] = 0xcb;
+	vector[7] = 0xcb;
+
+	arch_local_irq_restore(flags);
+
+#ifndef CONFIG_MN10300_CACHE_SNOOP
+	mn10300_dcache_flush_inv();
+	mn10300_icache_inv();
+#endif
+}
+
+/*
+ * initialise the exception table
+ */
+void __init trap_init(void)
+{
+	set_excp_vector(EXCEP_TRAP,		handle_exception);
+	set_excp_vector(EXCEP_ISTEP,		handle_exception);
+	set_excp_vector(EXCEP_IBREAK,		handle_exception);
+	set_excp_vector(EXCEP_OBREAK,		handle_exception);
+
+	set_excp_vector(EXCEP_PRIVINS,		handle_exception);
+	set_excp_vector(EXCEP_UNIMPINS,		handle_exception);
+	set_excp_vector(EXCEP_UNIMPEXINS,	handle_exception);
+	set_excp_vector(EXCEP_MEMERR,		handle_exception);
+	set_excp_vector(EXCEP_MISALIGN,		misalignment);
+	set_excp_vector(EXCEP_BUSERROR,		handle_exception);
+	set_excp_vector(EXCEP_ILLINSACC,	handle_exception);
+	set_excp_vector(EXCEP_ILLDATACC,	handle_exception);
+	set_excp_vector(EXCEP_IOINSACC,		handle_exception);
+	set_excp_vector(EXCEP_PRIVINSACC,	handle_exception);
+	set_excp_vector(EXCEP_PRIVDATACC,	handle_exception);
+	set_excp_vector(EXCEP_DATINSACC,	handle_exception);
+	set_excp_vector(EXCEP_FPU_UNIMPINS,	handle_exception);
+	set_excp_vector(EXCEP_FPU_OPERATION,	fpu_exception);
+
+	set_excp_vector(EXCEP_NMI,		nmi);
+
+	set_excp_vector(EXCEP_SYSCALL1,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL2,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL3,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL4,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL5,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL6,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL7,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL8,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL9,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL10,	handle_exception);
+	set_excp_vector(EXCEP_SYSCALL11,	handle_exception);
+	set_excp_vector(EXCEP_SYSCALL12,	handle_exception);
+	set_excp_vector(EXCEP_SYSCALL13,	handle_exception);
+	set_excp_vector(EXCEP_SYSCALL14,	handle_exception);
+	set_excp_vector(EXCEP_SYSCALL15,	handle_exception);
+}
+
+/*
+ * determine if a program counter value is a valid bug address
+ */
+int is_valid_bugaddr(unsigned long pc)
+{
+	return pc >= PAGE_OFFSET;
+}
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..13c4814
--- /dev/null
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -0,0 +1,93 @@
+/* MN10300 Main kernel linker script
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#define __VMLINUX_LDS__
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
+
+OUTPUT_FORMAT("elf32-am33lin", "elf32-am33lin", "elf32-am33lin")
+OUTPUT_ARCH(mn10300)
+ENTRY(_start)
+jiffies = jiffies_64;
+#ifndef CONFIG_MN10300_CURRENT_IN_E2
+current = __current;
+#endif
+SECTIONS
+{
+  . = CONFIG_KERNEL_TEXT_ADDRESS;
+  /* read-only */
+  _stext = .;
+  _text = .;			/* Text and read-only data */
+  .text : {
+	HEAD_TEXT
+	TEXT_TEXT
+	SCHED_TEXT
+	LOCK_TEXT
+	KPROBES_TEXT
+	*(.fixup)
+	*(.gnu.warning)
+	} = 0xcb
+
+  _etext = .;			/* End of text section */
+
+  EXCEPTION_TABLE(16)
+  BUG_TABLE
+
+  RO_DATA(PAGE_SIZE)
+
+  /* writeable */
+  _sdata = .;     /* Start of rw data section */
+  RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE)
+  _edata = .;
+
+  /* might get freed after init */
+  . = ALIGN(PAGE_SIZE);
+  .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
+  	__smp_locks = .;
+	*(.smp_locks)
+	__smp_locks_end = .;
+  }
+
+  /* will be freed after init */
+  . = ALIGN(PAGE_SIZE);		/* Init code and data */
+  __init_begin = .;
+  INIT_TEXT_SECTION(PAGE_SIZE)
+  INIT_DATA_SECTION(16)
+  . = ALIGN(4);
+  __alt_instructions = .;
+  .altinstructions : { *(.altinstructions) }
+  __alt_instructions_end = .;
+ .altinstr_replacement : { *(.altinstr_replacement) }
+  /* .exit.text is discard at runtime, not link time, to deal with references
+     from .altinstructions and .eh_frame */
+	.exit.text : { EXIT_TEXT; }
+	.exit.data : { EXIT_DATA; }
+
+  PERCPU_SECTION(32)
+  . = ALIGN(PAGE_SIZE);
+  __init_end = .;
+  /* freed after init ends here */
+
+  BSS_SECTION(0, PAGE_SIZE, 4)
+
+  _end = . ;
+
+  /* This is where the kernel creates the early boot page tables */
+  . = ALIGN(PAGE_SIZE);
+  pg0 = .;
+
+  STABS_DEBUG
+
+  DWARF_DEBUG
+
+  /* Sections to be discarded */
+  DISCARDS
+}
diff --git a/arch/mn10300/lib/Makefile b/arch/mn10300/lib/Makefile
new file mode 100644
index 0000000..0cd2346
--- /dev/null
+++ b/arch/mn10300/lib/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the MN10300-specific library files..
+#
+
+lib-y = delay.o usercopy.o checksum.o bitops.o memcpy.o memmove.o memset.o
+lib-y += do_csum.o
+lib-y += __ashldi3.o __ashrdi3.o __lshrdi3.o negdi2.o __ucmpdi2.o
diff --git a/arch/mn10300/lib/__ashldi3.S b/arch/mn10300/lib/__ashldi3.S
new file mode 100644
index 0000000..a51a950
--- /dev/null
+++ b/arch/mn10300/lib/__ashldi3.S
@@ -0,0 +1,51 @@
+/* MN10300 64-bit arithmetic left shift
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+        .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned long long __ashldi3(unsigned long long value [D1:D0],
+#			       unsigned by [(12,SP)])
+#
+###############################################################################
+        .globl	__ashldi3
+        .type	__ashldi3,@function
+__ashldi3:
+	mov	(12,sp),a0
+	and	+63,a0
+	beq	__ashldi3_zero
+
+	cmp	+31,a0
+	bhi	__ashldi3_32plus
+
+	# the count is in the range 1-31
+	asl	a0,d1
+
+	mov	+32,a1
+	sub	a0,a1,a1			# a1 = 32 - count
+	lsr	a1,d0,a1			# get overflow from LSW -> MSW
+
+	or_asl	a1,d1,a0,d0			# insert overflow into MSW and
+						# shift the LSW
+	rets
+
+	.balign	L1_CACHE_BYTES
+	# the count is in the range 32-63
+__ashldi3_32plus:
+	asl	a0,d0,d1
+	clr	d0
+__ashldi3_zero:
+	rets
+
+	.size	__ashldi3, .-__ashldi3
diff --git a/arch/mn10300/lib/__ashrdi3.S b/arch/mn10300/lib/__ashrdi3.S
new file mode 100644
index 0000000..6f42382
--- /dev/null
+++ b/arch/mn10300/lib/__ashrdi3.S
@@ -0,0 +1,52 @@
+/* MN10300 64-bit arithmetic right shift
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+        .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned long long __ashrdi3(unsigned long long value [D1:D0],
+#			       unsigned by [(12,SP)])
+#
+###############################################################################
+        .globl	__ashrdi3
+        .type	__ashrdi3,@function
+__ashrdi3:
+	mov	(12,sp),a0
+	and	+63,a0
+	beq	__ashrdi3_zero
+
+	cmp	+31,a0
+	bhi	__ashrdi3_32plus
+
+	# the count is in the range 1-31
+	lsr	a0,d0
+
+	mov	+32,a1
+	sub	a0,a1,a1			# a1 = 32 - count
+	asl	a1,d1,a1			# get underflow from MSW -> LSW
+
+	or_asr	a1,d0,a0,d1			# insert underflow into LSW and
+						# shift the MSW
+	rets
+
+	.balign	L1_CACHE_BYTES
+	# the count is in the range 32-63
+__ashrdi3_32plus:
+	asr	a0,d1,d0
+	ext	d0				# sign-extend result through MDR
+	mov	mdr,d1
+__ashrdi3_zero:
+	rets
+
+	.size	__ashrdi3, .-__ashrdi3
diff --git a/arch/mn10300/lib/__lshrdi3.S b/arch/mn10300/lib/__lshrdi3.S
new file mode 100644
index 0000000..a686aef
--- /dev/null
+++ b/arch/mn10300/lib/__lshrdi3.S
@@ -0,0 +1,52 @@
+/* MN10300 64-bit logical right shift
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <asm/cache.h>
+
+        .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned long long __lshrdi3(unsigned long long value [D1:D0],
+#			       unsigned by [(12,SP)])
+#
+###############################################################################
+        .globl	__lshrdi3
+        .type	__lshrdi3,@function
+__lshrdi3:
+	mov	(12,sp),a0
+	and	+63,a0
+	beq	__lshrdi3_zero
+
+	cmp	+31,a0
+	bhi	__lshrdi3_32plus
+
+	# the count is in the range 1-31
+	lsr	a0,d0
+
+	mov	+32,a1
+	sub	a0,a1,a1			# a1 = 32 - count
+	asl	a1,d1,a1			# get underflow from MSW -> LSW
+
+	or_lsr	a1,d0,a0,d1			# insert underflow into LSW and
+						# shift the MSW
+	rets
+
+	.balign	L1_CACHE_BYTES
+	# the count is in the range 32-63
+__lshrdi3_32plus:
+	lsr	a0,d1,d0
+	clr	d1
+__lshrdi3_zero:
+	rets
+
+	.size	__lshrdi3, .-__lshrdi3
diff --git a/arch/mn10300/lib/__ucmpdi2.S b/arch/mn10300/lib/__ucmpdi2.S
new file mode 100644
index 0000000..60dcbdf
--- /dev/null
+++ b/arch/mn10300/lib/__ucmpdi2.S
@@ -0,0 +1,43 @@
+/* __ucmpdi2.S: 64-bit unsigned compare
+ *
+ * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# int __ucmpdi2(unsigned long long a [D0:D1],
+#		unsigned long long b [(SP,12),(SP,16)])
+#
+# - returns 0, 1, or 2 as a <, =, > b respectively.
+#
+###############################################################################
+        .globl		__ucmpdi2
+        .type		__ucmpdi2,@function
+__ucmpdi2:
+	mov		(12,sp),a0		# b.lsw
+	mov		(16,sp),a1		# b.msw
+
+	sub		a0,d0
+	subc		a1,d1			# may clear Z, never sets it
+	bne		__ucmpdi2_differ	# a.msw != b.msw
+	mov		+1,d0
+	rets
+
+__ucmpdi2_differ:
+	# C flag is set if LE, clear if GE
+	subc		d0,d0			# -1 if LE, 0 if GE
+	add		+1,d0			#  0 if LE, 1 if GE
+	add		d0,d0			#  0 if LE, 2 if GE
+	rets
+
+	.size		__ucmpdi2, .-__ucmpdi2
diff --git a/arch/mn10300/lib/ashrdi3.c b/arch/mn10300/lib/ashrdi3.c
new file mode 100644
index 0000000..c54f61d
--- /dev/null
+++ b/arch/mn10300/lib/ashrdi3.c
@@ -0,0 +1,61 @@
+/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC 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 Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#define BITS_PER_UNIT 8
+
+typedef 	 int SItype	__attribute__((mode(SI)));
+typedef unsigned int USItype	__attribute__((mode(SI)));
+typedef		 int DItype	__attribute__((mode(DI)));
+typedef		 int word_type	__attribute__((mode(__word__)));
+
+struct DIstruct {
+	SItype low;
+	SItype high;
+};
+
+union DIunion {
+	struct DIstruct	s;
+	DItype		ll;
+};
+
+DItype __ashrdi3(DItype u, word_type b)
+{
+	union DIunion w;
+	union DIunion uu;
+	word_type bm;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+
+	bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
+	if (bm <= 0) {
+		/* w.s.high = 1..1 or 0..0 */
+		w.s.high = uu.s.high >> (sizeof(SItype) * BITS_PER_UNIT - 1);
+		w.s.low = uu.s.high >> -bm;
+	} else {
+		USItype carries = (USItype)uu.s.high << bm;
+		w.s.high = uu.s.high >> b;
+		w.s.low = ((USItype)uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
diff --git a/arch/mn10300/lib/bitops.c b/arch/mn10300/lib/bitops.c
new file mode 100644
index 0000000..37309cd
--- /dev/null
+++ b/arch/mn10300/lib/bitops.c
@@ -0,0 +1,50 @@
+/* MN10300 Non-trivial bit operations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <asm/bitops.h>
+
+/*
+ * try flipping a bit using BSET and BCLR
+ */
+void change_bit(unsigned long nr, volatile void *addr)
+{
+	if (test_bit(nr, addr))
+		goto try_clear_bit;
+
+try_set_bit:
+	if (!test_and_set_bit(nr, addr))
+		return;
+
+try_clear_bit:
+	if (test_and_clear_bit(nr, addr))
+		return;
+
+	goto try_set_bit;
+}
+
+/*
+ * try flipping a bit using BSET and BCLR and returning the old value
+ */
+int test_and_change_bit(unsigned long nr, volatile void *addr)
+{
+	if (test_bit(nr, addr))
+		goto try_clear_bit;
+
+try_set_bit:
+	if (!test_and_set_bit(nr, addr))
+		return 0;
+
+try_clear_bit:
+	if (test_and_clear_bit(nr, addr))
+		return 1;
+
+	goto try_set_bit;
+}
diff --git a/arch/mn10300/lib/checksum.c b/arch/mn10300/lib/checksum.c
new file mode 100644
index 0000000..b6580f5
--- /dev/null
+++ b/arch/mn10300/lib/checksum.c
@@ -0,0 +1,100 @@
+/* MN10300 Optimised checksumming wrappers
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#include "internal.h"
+
+static inline unsigned short from32to16(__wsum sum)
+{
+	asm("	add	%1,%0		\n"
+	    "	addc	0xffff,%0	\n"
+	    : "=r" (sum)
+	    : "r" (sum << 16), "0" (sum & 0xffff0000)
+	    : "cc"
+	    );
+	return sum >> 16;
+}
+
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	return ~do_csum(iph, ihl * 4);
+}
+EXPORT_SYMBOL(ip_fast_csum);
+
+__wsum csum_partial(const void *buff, int len, __wsum sum)
+{
+	__wsum result;
+
+	result = do_csum(buff, len);
+	result += sum;
+	if (sum > result)
+		result++;
+	return result;
+}
+EXPORT_SYMBOL(csum_partial);
+
+__sum16 ip_compute_csum(const void *buff, int len)
+{
+	return ~from32to16(do_csum(buff, len));
+}
+EXPORT_SYMBOL(ip_compute_csum);
+
+__wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
+{
+	copy_from_user(dst, src, len);
+	return csum_partial(dst, len, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy);
+
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+				 int len, __wsum sum)
+{
+	sum = csum_partial(src, len, sum);
+	memcpy(dst, src, len);
+	return sum;
+}
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+
+__wsum csum_partial_copy_from_user(const void *src, void *dst,
+				   int len, __wsum sum,
+				   int *err_ptr)
+{
+	int missing;
+
+	missing = copy_from_user(dst, src, len);
+	if (missing) {
+		memset(dst + len - missing, 0, missing);
+		*err_ptr = -EFAULT;
+	}
+
+	return csum_partial(dst, len, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy_from_user);
+
+__wsum csum_and_copy_to_user(const void *src, void *dst,
+			     int len, __wsum sum,
+			     int *err_ptr)
+{
+	int missing;
+
+	missing = copy_to_user(dst, src, len);
+	if (missing) {
+		memset(dst + len - missing, 0, missing);
+		*err_ptr = -EFAULT;
+	}
+
+	return csum_partial(src, len, sum);
+}
+EXPORT_SYMBOL(csum_and_copy_to_user);
diff --git a/arch/mn10300/lib/delay.c b/arch/mn10300/lib/delay.c
new file mode 100644
index 0000000..8e7ceb8
--- /dev/null
+++ b/arch/mn10300/lib/delay.c
@@ -0,0 +1,51 @@
+/* MN10300 Short delay interpolation routines
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <asm/div64.h>
+
+/*
+ * basic delay loop
+ */
+void __delay(unsigned long loops)
+{
+	int d0;
+
+	asm volatile(
+		"	bra	1f	\n"
+		"	.align	4	\n"
+		"1:	bra	2f	\n"
+		"	.align	4	\n"
+		"2:	add	-1,%0	\n"
+		"	bne	2b	\n"
+		: "=&d" (d0)
+		: "0" (loops)
+		: "cc");
+}
+EXPORT_SYMBOL(__delay);
+
+/*
+ * handle a delay specified in terms of microseconds
+ */
+void __udelay(unsigned long usecs)
+{
+	unsigned long start, stop, cnt;
+
+	/* usecs * CLK / 1E6 */
+	stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000);
+	start = TMTSCBC;
+
+	do {
+		cnt = start - TMTSCBC;
+	} while (cnt < stop);
+}
+EXPORT_SYMBOL(__udelay);
diff --git a/arch/mn10300/lib/do_csum.S b/arch/mn10300/lib/do_csum.S
new file mode 100644
index 0000000..1d27bba
--- /dev/null
+++ b/arch/mn10300/lib/do_csum.S
@@ -0,0 +1,157 @@
+/* Optimised simple memory checksum
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+	.section .text
+	.balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned int do_csum(const unsigned char *buff, int len)
+#
+###############################################################################
+	.globl	do_csum
+	.type	do_csum,@function
+do_csum:
+	movm	[d2,d3],(sp)
+	mov	d1,d2				# count
+	mov	d0,a0				# buff
+	mov	a0,a1
+	clr	d1				# accumulator
+
+	cmp	+0,d2
+	ble	do_csum_done			# check for zero length or negative
+
+	# 4-byte align the buffer pointer
+	btst	+3,a0
+	beq	do_csum_now_4b_aligned
+
+	btst	+1,a0
+	beq	do_csum_addr_not_odd
+	movbu	(a0),d0
+	inc	a0
+	asl	+8,d0
+	add	d0,d1
+	add	-1,d2
+
+do_csum_addr_not_odd:
+	cmp	+2,d2
+	bcs	do_csum_fewer_than_4
+	btst	+2,a0
+	beq	do_csum_now_4b_aligned
+	movhu	(a0+),d0
+	add	d0,d1
+	add	-2,d2
+	cmp	+4,d2
+	bcs	do_csum_fewer_than_4
+
+do_csum_now_4b_aligned:
+	# we want to checksum as much as we can in chunks of 32 bytes
+	cmp	+31,d2
+	bls	do_csum_remainder		# 4-byte aligned remainder
+
+	add	-32,d2
+	mov	+32,d3
+
+do_csum_loop:
+	mov	(a0+),d0
+	mov	(a0+),e0
+	mov	(a0+),e1
+	mov	(a0+),e3
+	add	d0,d1
+	addc	e0,d1
+	addc	e1,d1
+	addc	e3,d1
+	mov	(a0+),d0
+	mov	(a0+),e0
+	mov	(a0+),e1
+	mov	(a0+),e3
+	addc	d0,d1
+	addc	e0,d1
+	addc	e1,d1
+	addc	e3,d1
+	addc	+0,d1
+
+	sub	d3,d2
+	bcc	do_csum_loop
+
+	add	d3,d2
+	beq	do_csum_done
+
+do_csum_remainder:
+	# cut 16-31 bytes down to 0-15
+	cmp	+16,d2
+	bcs	do_csum_fewer_than_16
+	mov	(a0+),d0
+	mov	(a0+),e0
+	mov	(a0+),e1
+	mov	(a0+),e3
+	add	d0,d1
+	addc	e0,d1
+	addc	e1,d1
+	addc	e3,d1
+	addc	+0,d1
+	add	-16,d2
+	beq	do_csum_done
+
+do_csum_fewer_than_16:
+	# copy the remaining whole words
+	cmp	+4,d2
+	bcs	do_csum_fewer_than_4
+	cmp	+8,d2
+	bcs	do_csum_one_word
+	cmp	+12,d2
+	bcs	do_csum_two_words
+	mov	(a0+),d0
+	add	d0,d1
+	addc	+0,d1
+do_csum_two_words:
+	mov	(a0+),d0
+	add	d0,d1
+	addc	+0,d1
+do_csum_one_word:
+	mov	(a0+),d0
+	add	d0,d1
+	addc	+0,d1
+
+do_csum_fewer_than_4:
+	and	+3,d2
+	beq	do_csum_done
+	xor_cmp	d0,d0,+2,d2
+	bcs	do_csum_fewer_than_2
+	movhu	(a0+),d0
+	and	+1,d2
+	beq	do_csum_add_last_bit
+do_csum_fewer_than_2:
+	movbu	(a0),d3
+	add	d3,d0
+do_csum_add_last_bit:
+	add	d0,d1
+	addc	+0,d1
+
+do_csum_done:
+	# compress the checksum down to 16 bits
+	mov	+0xffff0000,d0
+	and	d1,d0
+	asl	+16,d1
+	add	d1,d0
+	addc	+0xffff,d0
+	lsr	+16,d0
+
+	# flip the halves of the word result if the buffer was oddly aligned
+	and	+1,a1
+	beq	do_csum_not_oddly_aligned
+	swaph	d0,d0				# exchange bits 15:8 with 7:0
+
+do_csum_not_oddly_aligned:
+	ret	[d2,d3],8
+
+	.size	do_csum, .-do_csum
diff --git a/arch/mn10300/lib/internal.h b/arch/mn10300/lib/internal.h
new file mode 100644
index 0000000..0014eee
--- /dev/null
+++ b/arch/mn10300/lib/internal.h
@@ -0,0 +1,15 @@
+/* Internal definitions for the arch part of the kernel library
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+/*
+ * do_csum.S
+ */
+extern unsigned int do_csum(const unsigned char *, size_t);
diff --git a/arch/mn10300/lib/lshrdi3.c b/arch/mn10300/lib/lshrdi3.c
new file mode 100644
index 0000000..e05e64e
--- /dev/null
+++ b/arch/mn10300/lib/lshrdi3.c
@@ -0,0 +1,60 @@
+/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC 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 Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#define BITS_PER_UNIT 8
+
+typedef 	 int SItype	__attribute__((mode(SI)));
+typedef unsigned int USItype	__attribute__((mode(SI)));
+typedef		 int DItype	__attribute__((mode(DI)));
+typedef		 int word_type	__attribute__((mode(__word__)));
+
+struct DIstruct {
+	SItype	low;
+	SItype	high;
+};
+
+union DIunion {
+	struct DIstruct	s;
+	DItype		ll;
+};
+
+DItype __lshrdi3(DItype u, word_type b)
+{
+	union DIunion w;
+	word_type bm;
+	union DIunion uu;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+
+	bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
+	if (bm <= 0) {
+		w.s.high = 0;
+		w.s.low = (USItype) uu.s.high >> -bm;
+	} else {
+		USItype carries = (USItype) uu.s.high << bm;
+		w.s.high = (USItype) uu.s.high >> b;
+		w.s.low = ((USItype) uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
diff --git a/arch/mn10300/lib/memcpy.S b/arch/mn10300/lib/memcpy.S
new file mode 100644
index 0000000..25fb9bb
--- /dev/null
+++ b/arch/mn10300/lib/memcpy.S
@@ -0,0 +1,135 @@
+/* MN10300 Optimised simple memory to memory copy
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+        .section .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# void *memcpy(void *dst, const void *src, size_t n)
+#
+###############################################################################
+	.globl	memcpy
+        .type	memcpy,@function
+memcpy:
+	movm	[d2,d3],(sp)
+	mov	d0,(12,sp)
+	mov	d1,(16,sp)
+	mov	(20,sp),d2			# count
+	mov	d0,a0				# dst
+	mov	d1,a1				# src
+	mov	d0,e3				# the return value
+
+	cmp	+0,d2
+	beq	memcpy_done			# return if zero-length copy
+
+	# see if the three parameters are all four-byte aligned
+	or	d0,d1,d3
+	or	d2,d3
+	and	+3,d3
+	bne	memcpy_1			# jump if not
+
+	# we want to transfer as much as we can in chunks of 32 bytes
+	cmp	+31,d2
+	bls	memcpy_4_remainder		# 4-byte aligned remainder
+
+	movm	[exreg1],(sp)
+	add	-32,d2
+	mov	+32,d3
+
+memcpy_4_loop:
+	mov	(a1+),d0
+	mov	(a1+),d1
+	mov	(a1+),e0
+	mov	(a1+),e1
+	mov	(a1+),e4
+	mov	(a1+),e5
+	mov	(a1+),e6
+	mov	(a1+),e7
+	mov	d0,(a0+)
+	mov	d1,(a0+)
+	mov	e0,(a0+)
+	mov	e1,(a0+)
+	mov	e4,(a0+)
+	mov	e5,(a0+)
+	mov	e6,(a0+)
+	mov	e7,(a0+)
+
+	sub	d3,d2
+	bcc	memcpy_4_loop
+
+	movm	(sp),[exreg1]
+	add	d3,d2
+	beq	memcpy_4_no_remainder
+
+memcpy_4_remainder:
+	# cut 4-7 words down to 0-3
+	cmp	+16,d2
+	bcs	memcpy_4_three_or_fewer_words
+	mov	(a1+),d0
+	mov	(a1+),d1
+	mov	(a1+),e0
+	mov	(a1+),e1
+	mov	d0,(a0+)
+	mov	d1,(a0+)
+	mov	e0,(a0+)
+	mov	e1,(a0+)
+	add	-16,d2
+	beq	memcpy_4_no_remainder
+
+	# copy the remaining 1, 2 or 3 words
+memcpy_4_three_or_fewer_words:
+	cmp	+8,d2
+	bcs	memcpy_4_one_word
+	beq	memcpy_4_two_words
+	mov	(a1+),d0
+	mov	d0,(a0+)
+memcpy_4_two_words:
+	mov	(a1+),d0
+	mov	d0,(a0+)
+memcpy_4_one_word:
+	mov	(a1+),d0
+	mov	d0,(a0+)
+
+memcpy_4_no_remainder:
+	# check we copied the correct amount
+	# TODO: REMOVE CHECK
+	sub	e3,a0,d2
+	mov	(20,sp),d1
+	cmp	d2,d1
+	beq	memcpy_done
+	break
+	break
+	break
+
+memcpy_done:
+	mov	e3,a0
+	ret	[d2,d3],8
+
+	# handle misaligned copying
+memcpy_1:
+	add	-1,d2
+	mov	+1,d3
+	setlb					# setlb requires the next insns
+						# to occupy exactly 4 bytes
+
+	sub	d3,d2
+	movbu	(a1),d0
+	movbu	d0,(a0)
+	add_add	d3,a1,d3,a0
+	lcc
+
+	mov	e3,a0
+	ret	[d2,d3],8
+
+memcpy_end:
+	.size	memcpy, memcpy_end-memcpy
diff --git a/arch/mn10300/lib/memmove.S b/arch/mn10300/lib/memmove.S
new file mode 100644
index 0000000..20b07b6
--- /dev/null
+++ b/arch/mn10300/lib/memmove.S
@@ -0,0 +1,160 @@
+/* MN10300 Optimised simple memory to memory copy, with support for overlapping
+ * regions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+        .section .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# void *memmove(void *dst, const void *src, size_t n)
+#
+###############################################################################
+	.globl	memmove
+        .type	memmove,@function
+memmove:
+	# fall back to memcpy if dst < src to work bottom up
+	cmp	d1,d0
+	bcs	memmove_memcpy
+
+	# work top down
+	movm	[d2,d3],(sp)
+	mov	d0,(12,sp)
+	mov	d1,(16,sp)
+	mov	(20,sp),d2			# count
+	add	d0,d2,a0			# dst end
+	add	d1,d2,a1			# src end
+	mov	d0,e3				# the return value
+
+	cmp	+0,d2
+	beq	memmove_done			# return if zero-length copy
+
+	# see if the three parameters are all four-byte aligned
+	or	d0,d1,d3
+	or	d2,d3
+	and	+3,d3
+	bne	memmove_1			# jump if not
+
+	# we want to transfer as much as we can in chunks of 32 bytes
+	add	-4,a1
+	cmp	+31,d2
+	bls	memmove_4_remainder		# 4-byte aligned remainder
+
+	add	-32,d2
+	mov	+32,d3
+
+memmove_4_loop:
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+	mov	(a1),d1
+	sub_sub	+4,a1,+4,a0
+	mov	d1,(a0)
+
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+	mov	(a1),d1
+	sub_sub	+4,a1,+4,a0
+	mov	d1,(a0)
+
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+	mov	(a1),d1
+	sub_sub	+4,a1,+4,a0
+	mov	d1,(a0)
+
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+	mov	(a1),d1
+	sub_sub	+4,a1,+4,a0
+	mov	d1,(a0)
+
+	sub	d3,d2
+	bcc	memmove_4_loop
+
+	add	d3,d2
+	beq	memmove_4_no_remainder
+
+memmove_4_remainder:
+	# cut 4-7 words down to 0-3
+	cmp	+16,d2
+	bcs	memmove_4_three_or_fewer_words
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+	mov	(a1),d1
+	sub_sub	+4,a1,+4,a0
+	mov	d1,(a0)
+	mov	(a1),e0
+	sub_sub	+4,a1,+4,a0
+	mov	e0,(a0)
+	mov	(a1),e1
+	sub_sub	+4,a1,+4,a0
+	mov	e1,(a0)
+	add	-16,d2
+	beq	memmove_4_no_remainder
+
+	# copy the remaining 1, 2 or 3 words
+memmove_4_three_or_fewer_words:
+	cmp	+8,d2
+	bcs	memmove_4_one_word
+	beq	memmove_4_two_words
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+memmove_4_two_words:
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+memmove_4_one_word:
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+
+memmove_4_no_remainder:
+	# check we copied the correct amount
+	# TODO: REMOVE CHECK
+	sub	e3,a0,d2
+	beq	memmove_done
+	break
+	break
+	break
+
+memmove_done:
+	mov	e3,a0
+	ret	[d2,d3],8
+
+	# handle misaligned copying
+memmove_1:
+	add	-1,a1
+	add	-1,d2
+	mov	+1,d3
+	setlb					# setlb requires the next insns
+						# to occupy exactly 4 bytes
+
+	sub	d3,d2
+	movbu	(a1),d0
+	sub_sub	d3,a1,d3,a0
+	movbu	d0,(a0)
+	lcc
+
+	mov	e3,a0
+	ret	[d2,d3],8
+
+memmove_memcpy:
+	jmp	memcpy
+
+memmove_end:
+	.size	memmove, memmove_end-memmove
diff --git a/arch/mn10300/lib/memset.S b/arch/mn10300/lib/memset.S
new file mode 100644
index 0000000..bc02e39
--- /dev/null
+++ b/arch/mn10300/lib/memset.S
@@ -0,0 +1,121 @@
+/* Optimised simple memory fill
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+        .section .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# void *memset(void *dst, int c, size_t n)
+#
+###############################################################################
+	.globl	memset
+        .type	memset,@function
+memset:
+	movm	[d2,d3],(sp)
+	mov	d0,(12,sp)
+	mov	d1,(16,sp)
+	mov	(20,sp),d2			# count
+	mov	d0,a0				# dst
+	mov	d0,e3				# the return value
+
+	cmp	+0,d2
+	beq	memset_done			# return if zero-length fill
+
+	# see if the region parameters are four-byte aligned
+	or	d0,d2,d3
+	and	+3,d3
+	bne	memset_1			# jump if not
+
+	extbu	d1
+	mov_asl	d1,d3,8,d1
+	or_asl	d1,d3,8,d1
+	or_asl	d1,d3,8,d1
+	or	d3,d1
+
+	# we want to transfer as much as we can in chunks of 32 bytes
+	cmp	+31,d2
+	bls	memset_4_remainder		# 4-byte aligned remainder
+
+	add	-32,d2
+	mov	+32,d3
+
+memset_4_loop:
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+
+	sub	d3,d2
+	bcc	memset_4_loop
+
+	add	d3,d2
+	beq	memset_4_no_remainder
+
+memset_4_remainder:
+	# cut 4-7 words down to 0-3
+	cmp	+16,d2
+	bcs	memset_4_three_or_fewer_words
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	add	-16,d2
+	beq	memset_4_no_remainder
+
+	# copy the remaining 1, 2 or 3 words
+memset_4_three_or_fewer_words:
+	cmp	+8,d2
+	bcs	memset_4_one_word
+	beq	memset_4_two_words
+	mov	d1,(a0+)
+memset_4_two_words:
+	mov	d1,(a0+)
+memset_4_one_word:
+	mov	d1,(a0+)
+
+memset_4_no_remainder:
+	# check we set the correct amount
+	# TODO: REMOVE CHECK
+	sub	e3,a0,d2
+	mov	(20,sp),d1
+	cmp	d2,d1
+	beq	memset_done
+	break
+	break
+	break
+
+memset_done:
+	mov	e3,a0
+	ret	[d2,d3],8
+
+	# handle misaligned copying
+memset_1:
+	add	-1,d2
+	mov	+1,d3
+	setlb					# setlb requires the next insns
+						# to occupy exactly 4 bytes
+
+	sub	d3,d2
+	movbu	d1,(a0)
+	inc	a0
+	lcc
+
+	mov	e3,a0
+	ret	[d2,d3],8
+
+memset_end:
+	.size	memset, memset_end-memset
diff --git a/arch/mn10300/lib/negdi2.c b/arch/mn10300/lib/negdi2.c
new file mode 100644
index 0000000..eae4ecd
--- /dev/null
+++ b/arch/mn10300/lib/negdi2.c
@@ -0,0 +1,57 @@
+/* More subroutines needed by GCC output code on some machines.  */
+/* Compile this one with gcc.  */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001  Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+In addition to the permissions in the GNU General Public Licence, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public Licence restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GNU CC 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 Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* It is incorrect to include config.h here, because this file is being
+   compiled for the target, and hence definitions concerning only the host
+   do not apply.  */
+
+#include <linux/types.h>
+
+union DWunion {
+	s64 ll;
+	struct {
+		s32 low;
+		s32 high;
+	} s;
+};
+
+s64 __negdi2(s64 u)
+{
+	union DWunion w;
+	union DWunion uu;
+
+	uu.ll = u;
+
+	w.s.low = -uu.s.low;
+	w.s.high = -uu.s.high - ((u32) w.s.low > 0);
+
+	return w.ll;
+}
diff --git a/arch/mn10300/lib/usercopy.c b/arch/mn10300/lib/usercopy.c
new file mode 100644
index 0000000..ce8899e
--- /dev/null
+++ b/arch/mn10300/lib/usercopy.c
@@ -0,0 +1,168 @@
+/* MN10300 Userspace accessor functions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/uaccess.h>
+
+unsigned long
+__generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		__copy_user(to, from, n);
+	return n;
+}
+
+unsigned long
+__generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_READ, from, n))
+		__copy_user_zeroing(to, from, n);
+	else
+		memset(to, 0, n);
+	return n;
+}
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+#define __do_strncpy_from_user(dst, src, count, res)		\
+do {								\
+	int w;							\
+	asm volatile(						\
+		"	mov	%1,%0\n"			\
+		"	cmp	0,%1\n"				\
+		"	beq	2f\n"				\
+		"0:\n"						\
+		"	movbu	(%5),%2\n"			\
+		"1:\n"						\
+		"	movbu	%2,(%6)\n"			\
+		"	inc	%5\n"				\
+		"	inc	%6\n"				\
+		"	cmp	0,%2\n"				\
+		"	beq	2f\n"				\
+		"	add	-1,%1\n"			\
+		"	bne	0b\n"				\
+		"2:\n"						\
+		"	sub	%1,%0\n"			\
+		"3:\n"						\
+		"	.section .fixup,\"ax\"\n"		\
+		"4:\n"						\
+		"	mov	%3,%0\n"			\
+		"	jmp	3b\n"				\
+		"	.previous\n"				\
+		"	.section __ex_table,\"a\"\n"		\
+		"	.balign 4\n"				\
+		"	.long 0b,4b\n"				\
+		"	.long 1b,4b\n"				\
+		"	.previous"				\
+		:"=&r"(res), "=r"(count), "=&r"(w)		\
+		:"i"(-EFAULT), "1"(count), "a"(src), "a"(dst)	\
+		: "memory", "cc");					\
+} while (0)
+
+long
+__strncpy_from_user(char *dst, const char *src, long count)
+{
+	long res;
+	__do_strncpy_from_user(dst, src, count, res);
+	return res;
+}
+
+long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+	long res = -EFAULT;
+	if (access_ok(VERIFY_READ, src, 1))
+		__do_strncpy_from_user(dst, src, count, res);
+	return res;
+}
+
+
+/*
+ * Clear a userspace memory
+ */
+#define __do_clear_user(addr, size)		\
+do {						\
+	int w;					\
+	asm volatile(				\
+		"	cmp 0,%0\n"		\
+		"	beq 1f\n"		\
+		"	clr %1\n"		\
+		"0:	movbu %1,(%3,%2)\n"	\
+		"	inc %3\n"		\
+		"	cmp %0,%3\n"		\
+		"	bne 0b\n"		\
+		"1:\n"				\
+		"	sub %3,%0\n"		\
+		"2:\n"				\
+		".section .fixup,\"ax\"\n"	\
+		"3:	jmp 2b\n"		\
+		".previous\n"			\
+		".section __ex_table,\"a\"\n"	\
+		"       .balign 4\n"		\
+		"       .long 0b,3b\n"		\
+		".previous\n"			\
+		: "+r"(size), "=&r"(w)		\
+		: "a"(addr), "d"(0)		\
+		: "memory", "cc");		\
+} while (0)
+
+unsigned long
+__clear_user(void *to, unsigned long n)
+{
+	__do_clear_user(to, n);
+	return n;
+}
+
+unsigned long
+clear_user(void *to, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		__do_clear_user(to, n);
+	return n;
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+long strnlen_user(const char *s, long n)
+{
+	unsigned long res, w;
+
+	if (!__addr_ok(s))
+		return 0;
+
+	if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
+		n = current_thread_info()->addr_limit.seg - (u_long)s;
+
+	asm volatile(
+		"0:	cmp %4,%0\n"
+		"	beq 2f\n"
+		"1:	movbu (%0,%3),%1\n"
+		"	inc %0\n"
+		"	cmp 0,%1\n"
+		"	beq 3f\n"
+		"	bra 0b\n"
+		"2:	clr %0\n"
+		"3:\n"
+		".section .fixup,\"ax\"\n"
+		"4:	jmp 2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.balign 4\n"
+		"	.long 1b,4b\n"
+		".previous\n"
+		:"=d"(res), "=&r"(w)
+		:"0"(0), "a"(s), "r"(n)
+		: "memory", "cc");
+	return res;
+}
diff --git a/arch/mn10300/mm/Kconfig.cache b/arch/mn10300/mm/Kconfig.cache
new file mode 100644
index 0000000..bfbe526
--- /dev/null
+++ b/arch/mn10300/mm/Kconfig.cache
@@ -0,0 +1,147 @@
+#
+# MN10300 CPU cache options
+#
+
+choice
+	prompt "CPU Caching mode"
+	default MN10300_CACHE_WBACK
+	help
+	  This option determines the caching mode for the kernel.
+
+	  Write-Back caching mode involves the all reads and writes causing
+	  the affected cacheline to be read into the cache first before being
+	  operated upon. Memory is not then updated by a write until the cache
+	  is filled and a cacheline needs to be displaced from the cache to
+	  make room. Only at that point is it written back.
+
+	  Write-Through caching only fetches cachelines from memory on a
+	  read. Writes always get written directly to memory. If the affected
+	  cacheline is also in cache, it will be updated too.
+
+	  The final option is to turn of caching entirely.
+
+config MN10300_CACHE_WBACK
+	bool "Write-Back"
+	help
+	  The dcache operates in delayed write-back mode.  It must be manually
+	  flushed if writes are made that subsequently need to be executed or
+	  to be DMA'd by a device.
+
+config MN10300_CACHE_WTHRU
+	bool "Write-Through"
+	help
+	  The dcache operates in immediate write-through mode.  Writes are
+	  committed to RAM immediately in addition to being stored in the
+	  cache.  This means that the written data is immediately available for
+	  execution or DMA.
+
+	  This is not available for use with an SMP kernel if cache flushing
+	  and invalidation by automatic purge register is not selected.
+
+config MN10300_CACHE_DISABLED
+	bool "Disabled"
+	help
+	  The icache and dcache are disabled.
+
+endchoice
+
+config MN10300_CACHE_ENABLED
+	def_bool y if !MN10300_CACHE_DISABLED
+
+
+choice
+	prompt "CPU cache flush/invalidate method"
+	default MN10300_CACHE_MANAGE_BY_TAG if !AM34_2
+	default MN10300_CACHE_MANAGE_BY_REG if AM34_2
+	depends on MN10300_CACHE_ENABLED
+	help
+	  This determines the method by which CPU cache flushing and
+	  invalidation is performed.
+
+config MN10300_CACHE_MANAGE_BY_TAG
+	bool "Use the cache tag registers directly"
+	depends on !(SMP && MN10300_CACHE_WTHRU)
+
+config MN10300_CACHE_MANAGE_BY_REG
+	bool "Flush areas by way of automatic purge registers (AM34 only)"
+	depends on AM34_2
+
+endchoice
+
+config MN10300_CACHE_INV_BY_TAG
+	def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_ENABLED
+
+config MN10300_CACHE_INV_BY_REG
+	def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_ENABLED
+
+config MN10300_CACHE_FLUSH_BY_TAG
+	def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_WBACK
+
+config MN10300_CACHE_FLUSH_BY_REG
+	def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_WBACK
+
+
+config MN10300_HAS_CACHE_SNOOP
+	def_bool n
+
+config MN10300_CACHE_SNOOP
+	bool "Use CPU Cache Snooping"
+	depends on MN10300_CACHE_ENABLED && MN10300_HAS_CACHE_SNOOP
+	default y
+
+config MN10300_CACHE_FLUSH_ICACHE
+	def_bool y if MN10300_CACHE_WBACK && !MN10300_CACHE_SNOOP
+	help
+	  Set if we need the dcache flushing before the icache is invalidated.
+
+config MN10300_CACHE_INV_ICACHE
+	def_bool y if MN10300_CACHE_WTHRU && !MN10300_CACHE_SNOOP
+	help
+	  Set if we need the icache to be invalidated, even if the dcache is in
+	  write-through mode and doesn't need flushing.
+
+#
+# The kernel debugger gets its own separate cache flushing functions
+#
+config MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG
+	def_bool y if KERNEL_DEBUGGER && \
+			MN10300_CACHE_WBACK && \
+			!MN10300_CACHE_SNOOP && \
+			MN10300_CACHE_MANAGE_BY_TAG
+	help
+	  Set if the debugger needs to flush the dcache and invalidate the
+	  icache using the cache tag registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_FLUSH_BY_REG
+	def_bool y if KERNEL_DEBUGGER && \
+			MN10300_CACHE_WBACK && \
+			!MN10300_CACHE_SNOOP && \
+			MN10300_CACHE_MANAGE_BY_REG
+	help
+	  Set if the debugger needs to flush the dcache and invalidate the
+	  icache using automatic purge registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_INV_BY_TAG
+	def_bool y if KERNEL_DEBUGGER && \
+			MN10300_CACHE_WTHRU && \
+			!MN10300_CACHE_SNOOP && \
+			MN10300_CACHE_MANAGE_BY_TAG
+	help
+	  Set if the debugger needs to invalidate the icache using the cache
+	  tag registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_INV_BY_REG
+	def_bool y if KERNEL_DEBUGGER && \
+			MN10300_CACHE_WTHRU && \
+			!MN10300_CACHE_SNOOP && \
+			MN10300_CACHE_MANAGE_BY_REG
+	help
+	  Set if the debugger needs to invalidate the icache using automatic
+	  purge registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_NO_FLUSH
+	def_bool y if KERNEL_DEBUGGER && \
+			(MN10300_CACHE_DISABLED || MN10300_CACHE_SNOOP)
+	help
+	  Set if the debugger does not need to flush the dcache and/or
+	  invalidate the icache to make breakpoints work.
diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile
new file mode 100644
index 0000000..11f3846
--- /dev/null
+++ b/arch/mn10300/mm/Makefile
@@ -0,0 +1,31 @@
+#
+# Makefile for the MN10300-specific memory management code
+#
+
+cache-smp-wback-$(CONFIG_MN10300_CACHE_WBACK) := cache-smp-flush.o
+
+cacheflush-y	:= cache.o
+cacheflush-$(CONFIG_SMP) += cache-smp.o cache-smp-inv.o $(cache-smp-wback-y)
+cacheflush-$(CONFIG_MN10300_CACHE_INV_ICACHE) += cache-inv-icache.o
+cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_ICACHE) += cache-flush-icache.o
+cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_TAG) += cache-inv-by-tag.o
+cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_REG) += cache-inv-by-reg.o
+cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o
+cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.o
+
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG) += \
+	cache-dbg-flush-by-tag.o cache-dbg-inv-by-tag.o
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_REG) += \
+	cache-dbg-flush-by-reg.o
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG) += \
+	cache-dbg-inv-by-tag.o cache-dbg-inv.o
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_REG) += \
+	cache-dbg-inv-by-reg.o cache-dbg-inv.o
+
+cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o
+
+obj-y := \
+	init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \
+	misalignment.o dma-alloc.o $(cacheflush-y)
+
+obj-$(CONFIG_SMP) += tlb-smp.o
diff --git a/arch/mn10300/mm/cache-dbg-flush-by-reg.S b/arch/mn10300/mm/cache-dbg-flush-by-reg.S
new file mode 100644
index 0000000..a775ea5
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-flush-by-reg.S
@@ -0,0 +1,160 @@
+/* MN10300 CPU cache invalidation routines, using automatic purge registers
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+	.am33_2
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv(void)
+# Flush the entire data cache back to RAM and invalidate the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv
+        .type	debugger_local_cache_flushinv,@function
+debugger_local_cache_flushinv:
+	#
+	# firstly flush the dcache
+	#
+	movhu	(CHCTR),d0
+	btst	CHCTR_DCEN|CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_end
+
+	mov	DCPGCR,a0
+
+	mov	epsw,d1
+	and	~EPSW_IE,epsw
+	or	EPSW_NMID,epsw
+	nop
+
+	btst	CHCTR_DCEN,d0
+	beq	debugger_local_cache_flushinv_no_dcache
+
+	# wait for busy bit of area purge
+	setlb
+	mov	(a0),d0
+	btst	DCPGCR_DCPGBSY,d0
+	lne
+
+	# set mask
+	clr	d0
+	mov	d0,(DCPGMR)
+
+	# area purge
+	#
+	# DCPGCR = DCPGCR_DCP
+	#
+	mov	DCPGCR_DCP,d0
+	mov	d0,(a0)
+
+	# wait for busy bit of area purge
+	setlb
+	mov	(a0),d0
+	btst	DCPGCR_DCPGBSY,d0
+	lne
+
+debugger_local_cache_flushinv_no_dcache:
+	#
+	# secondly, invalidate the icache if it is enabled
+	#
+	mov	CHCTR,a0
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_done
+
+	invalidate_icache 0
+
+debugger_local_cache_flushinv_done:
+	mov	d1,epsw
+
+debugger_local_cache_flushinv_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv_one
+	.type	debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one:
+	movhu	(CHCTR),d1
+	btst	CHCTR_DCEN|CHCTR_ICEN,d1
+	beq	debugger_local_cache_flushinv_one_end
+	btst	CHCTR_DCEN,d1
+	beq	debugger_local_cache_flushinv_one_no_dcache
+
+	# round cacheline addr down
+	and	L1_CACHE_TAG_MASK,d0
+	mov	d0,a1
+	mov	d0,d1
+
+	# determine the dcache purge control reg address
+	mov	DCACHE_PURGE(0,0),a0
+	and	L1_CACHE_TAG_ENTRY,d0
+	add	d0,a0
+
+	# retain valid entries in the cache
+	or	L1_CACHE_TAG_VALID,d1
+
+	# conditionally purge this line in all ways
+	mov	d1,(L1_CACHE_WAYDISP*0,a0)
+
+debugger_local_cache_flushinv_one_no_dcache:
+	#
+	# now try to flush the icache
+	#
+	mov	CHCTR,a0
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_one_end
+
+	LOCAL_CLI_SAVE(d1)
+
+	mov	ICIVCR,a0
+
+	# wait for the invalidator to quiesce
+	setlb
+	mov	(a0),d0
+	btst	ICIVCR_ICIVBSY,d0
+	lne
+
+	# set the mask
+	mov	L1_CACHE_TAG_MASK,d0
+	mov	d0,(ICIVMR)
+
+	# invalidate the cache line at the given address
+	or	ICIVCR_ICI,a1
+	mov	a1,(a0)
+
+	# wait for the invalidator to quiesce again
+	setlb
+	mov	(a0),d0
+	btst	ICIVCR_ICIVBSY,d0
+	lne
+
+	LOCAL_IRQ_RESTORE(d1)
+
+debugger_local_cache_flushinv_one_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff --git a/arch/mn10300/mm/cache-dbg-flush-by-tag.S b/arch/mn10300/mm/cache-dbg-flush-by-tag.S
new file mode 100644
index 0000000..bf56930
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-flush-by-tag.S
@@ -0,0 +1,114 @@
+/* MN10300 CPU cache invalidation routines, using direct tag flushing
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+	.am33_2
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv(void)
+#
+# Flush the entire data cache back to RAM and invalidate the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv
+        .type	debugger_local_cache_flushinv,@function
+debugger_local_cache_flushinv:
+	#
+	# firstly flush the dcache
+	#
+	movhu	(CHCTR),d0
+	btst	CHCTR_DCEN|CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_end
+
+	btst	CHCTR_DCEN,d0
+	beq	debugger_local_cache_flushinv_no_dcache
+
+	# read the addresses tagged in the cache's tag RAM and attempt to flush
+	# those addresses specifically
+	# - we rely on the hardware to filter out invalid tag entry addresses
+	mov	DCACHE_TAG(0,0),a0		# dcache tag RAM access address
+	mov	DCACHE_PURGE(0,0),a1		# dcache purge request address
+	mov	L1_CACHE_NWAYS*L1_CACHE_NENTRIES,e0  # total number of entries
+
+mn10300_local_dcache_flush_loop:
+	mov	(a0),d0
+	and	L1_CACHE_TAG_MASK,d0
+	or	L1_CACHE_TAG_VALID,d0		# retain valid entries in the
+						# cache
+	mov	d0,(a1)				# conditional purge
+
+	add	L1_CACHE_BYTES,a0
+	add	L1_CACHE_BYTES,a1
+	add	-1,e0
+	bne	mn10300_local_dcache_flush_loop
+
+debugger_local_cache_flushinv_no_dcache:
+	#
+	# secondly, invalidate the icache if it is enabled
+	#
+	mov	CHCTR,a0
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_end
+
+	invalidate_icache 1
+
+debugger_local_cache_flushinv_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv_one
+	.type	debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one:
+	movhu	(CHCTR),d1
+	btst	CHCTR_DCEN|CHCTR_ICEN,d1
+	beq	debugger_local_cache_flushinv_one_end
+	btst	CHCTR_DCEN,d1
+	beq	debugger_local_cache_flushinv_one_icache
+
+	# round cacheline addr down
+	and	L1_CACHE_TAG_MASK,d0
+	mov	d0,a1
+
+	# determine the dcache purge control reg address
+	mov	DCACHE_PURGE(0,0),a0
+	and	L1_CACHE_TAG_ENTRY,d0
+	add	d0,a0
+
+	# retain valid entries in the cache
+	or	L1_CACHE_TAG_VALID,a1
+
+	# conditionally purge this line in all ways
+	mov	a1,(L1_CACHE_WAYDISP*0,a0)
+
+	# now go and do the icache
+	bra	debugger_local_cache_flushinv_one_icache
+
+debugger_local_cache_flushinv_one_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff --git a/arch/mn10300/mm/cache-dbg-inv-by-reg.S b/arch/mn10300/mm/cache-dbg-inv-by-reg.S
new file mode 100644
index 0000000..c4e6252
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-inv-by-reg.S
@@ -0,0 +1,69 @@
+/* MN10300 CPU cache invalidation routines, using automatic purge registers
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+	.am33_2
+
+	.globl	debugger_local_cache_flushinv_one
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv_one
+	.type	debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one:
+	mov	d0,a1
+
+	mov	CHCTR,a0
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	mn10300_local_icache_inv_range_reg_end
+
+	LOCAL_CLI_SAVE(d1)
+
+	mov	ICIVCR,a0
+
+	# wait for the invalidator to quiesce
+	setlb
+	mov	(a0),d0
+	btst	ICIVCR_ICIVBSY,d0
+	lne
+
+	# set the mask
+	mov	~L1_CACHE_TAG_MASK,d0
+	mov	d0,(ICIVMR)
+
+	# invalidate the cache line at the given address
+	and	~L1_CACHE_TAG_MASK,a1
+	or	ICIVCR_ICI,a1
+	mov	a1,(a0)
+
+	# wait for the invalidator to quiesce again
+	setlb
+	mov	(a0),d0
+	btst	ICIVCR_ICIVBSY,d0
+	lne
+
+	LOCAL_IRQ_RESTORE(d1)
+
+mn10300_local_icache_inv_range_reg_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff --git a/arch/mn10300/mm/cache-dbg-inv-by-tag.S b/arch/mn10300/mm/cache-dbg-inv-by-tag.S
new file mode 100644
index 0000000..d8ec821
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-inv-by-tag.S
@@ -0,0 +1,120 @@
+/* MN10300 CPU cache invalidation routines, using direct tag flushing
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+	.am33_2
+
+	.globl	debugger_local_cache_flushinv_one_icache
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv_one_icache
+	.type	debugger_local_cache_flushinv_one_icache,@function
+debugger_local_cache_flushinv_one_icache:
+	movm	[d3,a2],(sp)
+
+	mov	CHCTR,a2
+	movhu	(a2),d0
+	btst	CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_one_icache_end
+
+	mov	d0,a1
+	and	L1_CACHE_TAG_MASK,a1
+
+	# read the tags from the tag RAM, and if they indicate a matching valid
+	# cache line then we invalidate that line
+	mov	ICACHE_TAG(0,0),a0
+	mov	a1,d0
+	and	L1_CACHE_TAG_ENTRY,d0
+	add	d0,a0				# starting icache tag RAM
+						# access address
+
+	and	~(L1_CACHE_DISPARITY-1),a1	# determine comparator base
+	or	L1_CACHE_TAG_VALID,a1
+	mov	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_VALID,d1
+
+	LOCAL_CLI_SAVE(d3)
+
+	# disable the icache
+	movhu	(a2),d0
+	and	~CHCTR_ICEN,d0
+	movhu	d0,(a2)
+
+	# and wait for it to calm down
+	setlb
+	movhu	(a2),d0
+	btst	CHCTR_ICBUSY,d0
+	lne
+
+	# check all the way tags for this cache entry
+	mov	(a0),d0				# read the tag in the way 0 slot
+	xor	a1,d0
+	and	d1,d0
+	beq	debugger_local_icache_kill	# jump if matched
+
+	add	L1_CACHE_WAYDISP,a0
+	mov	(a0),d0				# read the tag in the way 1 slot
+	xor	a1,d0
+	and	d1,d0
+	beq	debugger_local_icache_kill	# jump if matched
+
+	add	L1_CACHE_WAYDISP,a0
+	mov	(a0),d0				# read the tag in the way 2 slot
+	xor	a1,d0
+	and	d1,d0
+	beq	debugger_local_icache_kill	# jump if matched
+
+	add	L1_CACHE_WAYDISP,a0
+	mov	(a0),d0				# read the tag in the way 3 slot
+	xor	a1,d0
+	and	d1,d0
+	bne	debugger_local_icache_finish	# jump if not matched
+
+debugger_local_icache_kill:
+	mov	d0,(a0)				# kill the tag (D0 is 0 at this point)
+
+debugger_local_icache_finish:
+	# wait for the cache to finish what it's doing
+	setlb
+	movhu	(a2),d0
+	btst	CHCTR_ICBUSY,d0
+	lne
+
+	# and reenable it
+	or	CHCTR_ICEN,d0
+	movhu	d0,(a2)
+	movhu	(a2),d0
+
+	# re-enable interrupts
+	LOCAL_IRQ_RESTORE(d3)
+
+debugger_local_cache_flushinv_one_icache_end:
+	ret	[d3,a2],8
+	.size	debugger_local_cache_flushinv_one_icache,.-debugger_local_cache_flushinv_one_icache
+
+#ifdef CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG
+	.globl	debugger_local_cache_flushinv_one
+	.type	debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one = debugger_local_cache_flushinv_one_icache
+#endif
diff --git a/arch/mn10300/mm/cache-dbg-inv.S b/arch/mn10300/mm/cache-dbg-inv.S
new file mode 100644
index 0000000..eba2d6d
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-inv.S
@@ -0,0 +1,47 @@
+/* MN10300 CPU cache invalidation routines
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+	.am33_2
+
+	.globl	debugger_local_cache_flushinv
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv(void)
+#
+# Invalidate the entire icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv
+        .type	debugger_local_cache_flushinv,@function
+debugger_local_cache_flushinv:
+	#
+	# we only need to invalidate the icache in this cache mode
+	#
+	mov	CHCTR,a0
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_end
+
+	invalidate_icache 1
+
+debugger_local_cache_flushinv_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
diff --git a/arch/mn10300/mm/cache-disabled.c b/arch/mn10300/mm/cache-disabled.c
new file mode 100644
index 0000000..f669ea4
--- /dev/null
+++ b/arch/mn10300/mm/cache-disabled.c
@@ -0,0 +1,21 @@
+/* Handle the cache being disabled
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/mm.h>
+
+/*
+ * allow userspace to flush the instruction cache
+ */
+asmlinkage long sys_cacheflush(unsigned long start, unsigned long end)
+{
+	if (end < start)
+		return -EINVAL;
+	return 0;
+}
diff --git a/arch/mn10300/mm/cache-flush-by-reg.S b/arch/mn10300/mm/cache-flush-by-reg.S
new file mode 100644
index 0000000..1dcae02
--- /dev/null
+++ b/arch/mn10300/mm/cache-flush-by-reg.S
@@ -0,0 +1,308 @@
+/* MN10300 CPU core caching routines, using indirect regs on cache controller
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+
+	.am33_2
+
+#ifndef CONFIG_SMP
+	.globl mn10300_dcache_flush
+	.globl mn10300_dcache_flush_page
+	.globl mn10300_dcache_flush_range
+	.globl mn10300_dcache_flush_range2
+	.globl mn10300_dcache_flush_inv
+	.globl mn10300_dcache_flush_inv_page
+	.globl mn10300_dcache_flush_inv_range
+	.globl mn10300_dcache_flush_inv_range2
+
+mn10300_dcache_flush		= mn10300_local_dcache_flush
+mn10300_dcache_flush_page	= mn10300_local_dcache_flush_page
+mn10300_dcache_flush_range	= mn10300_local_dcache_flush_range
+mn10300_dcache_flush_range2	= mn10300_local_dcache_flush_range2
+mn10300_dcache_flush_inv	= mn10300_local_dcache_flush_inv
+mn10300_dcache_flush_inv_page	= mn10300_local_dcache_flush_inv_page
+mn10300_dcache_flush_inv_range	= mn10300_local_dcache_flush_inv_range
+mn10300_dcache_flush_inv_range2	= mn10300_local_dcache_flush_inv_range2
+
+#endif /* !CONFIG_SMP */
+
+###############################################################################
+#
+# void mn10300_local_dcache_flush(void)
+# Flush the entire data cache back to RAM
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_flush
+        .type	mn10300_local_dcache_flush,@function
+mn10300_local_dcache_flush:
+	movhu	(CHCTR),d0
+	btst	CHCTR_DCEN,d0
+	beq	mn10300_local_dcache_flush_end
+
+	mov	DCPGCR,a0
+
+	LOCAL_CLI_SAVE(d1)
+
+	# wait for busy bit of area purge
+	setlb
+	mov	(a0),d0
+	btst	DCPGCR_DCPGBSY,d0
+	lne
+
+	# set mask
+	clr	d0
+	mov	d0,(DCPGMR)
+
+	# area purge
+	#
+	# DCPGCR = DCPGCR_DCP
+	#
+	mov	DCPGCR_DCP,d0
+	mov	d0,(a0)
+
+	# wait for busy bit of area purge
+	setlb
+	mov	(a0),d0
+	btst	DCPGCR_DCPGBSY,d0
+	lne
+
+	LOCAL_IRQ_RESTORE(d1)
+
+mn10300_local_dcache_flush_end:
+	ret	[],0
+	.size	mn10300_local_dcache_flush,.-mn10300_local_dcache_flush
+
+###############################################################################
+#
+# void mn10300_local_dcache_flush_page(unsigned long start)
+# void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end)
+# void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size)
+# Flush a range of addresses on a page in the dcache
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_flush_page
+	.globl	mn10300_local_dcache_flush_range
+	.globl	mn10300_local_dcache_flush_range2
+	.type	mn10300_local_dcache_flush_page,@function
+	.type	mn10300_local_dcache_flush_range,@function
+	.type	mn10300_local_dcache_flush_range2,@function
+mn10300_local_dcache_flush_page:
+	and	~(PAGE_SIZE-1),d0
+	mov	PAGE_SIZE,d1
+mn10300_local_dcache_flush_range2:
+	add	d0,d1
+mn10300_local_dcache_flush_range:
+	movm	[d2,d3,a2],(sp)
+
+	movhu	(CHCTR),d2
+	btst	CHCTR_DCEN,d2
+	beq	mn10300_local_dcache_flush_range_end
+
+	# calculate alignsize
+	#
+	# alignsize = L1_CACHE_BYTES;
+	# for (i = (end - start - 1) / L1_CACHE_BYTES ;  i > 0; i >>= 1)
+	#     alignsize <<= 1;
+	# d2 = alignsize;
+	#
+	mov	L1_CACHE_BYTES,d2
+	sub	d0,d1,d3
+	add	-1,d3
+	lsr	L1_CACHE_SHIFT,d3
+	beq	2f
+1:
+	add     d2,d2
+	lsr     1,d3
+	bne     1b
+2:
+	mov	d1,a1		# a1 = end
+
+	LOCAL_CLI_SAVE(d3)
+	mov	DCPGCR,a0
+
+	# wait for busy bit of area purge
+	setlb
+	mov	(a0),d1
+	btst	DCPGCR_DCPGBSY,d1
+	lne
+
+	# determine the mask
+	mov	d2,d1
+	add	-1,d1
+	not	d1		# d1 = mask = ~(alignsize-1)
+	mov	d1,(DCPGMR)
+
+	and	d1,d0,a2	# a2 = mask & start
+
+dcpgloop:
+	# area purge
+	mov	a2,d0
+	or	DCPGCR_DCP,d0
+	mov	d0,(a0)		# DCPGCR = (mask & start) | DCPGCR_DCP
+
+	# wait for busy bit of area purge
+	setlb
+	mov	(a0),d1
+	btst	DCPGCR_DCPGBSY,d1
+	lne
+
+	# check purge of end address
+	add	d2,a2		# a2 += alignsize
+	cmp	a1,a2		# if (a2 < end) goto dcpgloop
+	bns	dcpgloop
+
+	LOCAL_IRQ_RESTORE(d3)
+
+mn10300_local_dcache_flush_range_end:
+	ret	[d2,d3,a2],12
+
+	.size	mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page
+	.size	mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range
+	.size	mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2
+
+###############################################################################
+#
+# void mn10300_local_dcache_flush_inv(void)
+# Flush the entire data cache and invalidate all entries
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_flush_inv
+	.type	mn10300_local_dcache_flush_inv,@function
+mn10300_local_dcache_flush_inv:
+	movhu	(CHCTR),d0
+	btst	CHCTR_DCEN,d0
+	beq	mn10300_local_dcache_flush_inv_end
+
+	mov	DCPGCR,a0
+
+	LOCAL_CLI_SAVE(d1)
+
+	# wait for busy bit of area purge & invalidate
+	setlb
+	mov	(a0),d0
+	btst	DCPGCR_DCPGBSY,d0
+	lne
+
+	# set the mask to cover everything
+	clr	d0
+	mov	d0,(DCPGMR)
+
+	# area purge & invalidate
+	mov	DCPGCR_DCP|DCPGCR_DCI,d0
+	mov	d0,(a0)
+
+	# wait for busy bit of area purge & invalidate
+	setlb
+	mov	(a0),d0
+	btst	DCPGCR_DCPGBSY,d0
+	lne
+
+	LOCAL_IRQ_RESTORE(d1)
+
+mn10300_local_dcache_flush_inv_end:
+	ret	[],0
+	.size	mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv
+
+###############################################################################
+#
+# void mn10300_local_dcache_flush_inv_page(unsigned long start)
+# void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end)
+# void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size)
+# Flush and invalidate a range of addresses on a page in the dcache
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_flush_inv_page
+	.globl	mn10300_local_dcache_flush_inv_range
+	.globl	mn10300_local_dcache_flush_inv_range2
+	.type	mn10300_local_dcache_flush_inv_page,@function
+	.type	mn10300_local_dcache_flush_inv_range,@function
+	.type	mn10300_local_dcache_flush_inv_range2,@function
+mn10300_local_dcache_flush_inv_page:
+	and	~(PAGE_SIZE-1),d0
+	mov	PAGE_SIZE,d1
+mn10300_local_dcache_flush_inv_range2:
+	add	d0,d1
+mn10300_local_dcache_flush_inv_range:
+	movm	[d2,d3,a2],(sp)
+
+	movhu	(CHCTR),d2
+	btst	CHCTR_DCEN,d2
+	beq	mn10300_local_dcache_flush_inv_range_end
+
+	# calculate alignsize
+	#
+	# alignsize = L1_CACHE_BYTES;
+	# for (i = (end - start - 1) / L1_CACHE_BYTES; i > 0; i >>= 1)
+	#     alignsize <<= 1;
+	# d2 = alignsize
+	#
+	mov	L1_CACHE_BYTES,d2
+	sub	d0,d1,d3
+	add	-1,d3
+	lsr	L1_CACHE_SHIFT,d3
+	beq	2f
+1:
+	add     d2,d2
+	lsr     1,d3
+	bne     1b
+2:
+	mov	d1,a1		# a1 = end
+
+	LOCAL_CLI_SAVE(d3)
+	mov	DCPGCR,a0
+
+	# wait for busy bit of area purge & invalidate
+	setlb
+	mov	(a0),d1
+	btst	DCPGCR_DCPGBSY,d1
+	lne
+
+	# set the mask
+	mov	d2,d1
+	add	-1,d1
+	not	d1		# d1 = mask = ~(alignsize-1)
+	mov	d1,(DCPGMR)
+
+	and	d1,d0,a2	# a2 = mask & start
+
+dcpgivloop:
+	# area purge & invalidate
+	mov	a2,d0
+	or	DCPGCR_DCP|DCPGCR_DCI,d0
+	mov	d0,(a0)		# DCPGCR = (mask & start)|DCPGCR_DCP|DCPGCR_DCI
+
+	# wait for busy bit of area purge & invalidate
+	setlb
+	mov	(a0),d1
+	btst	DCPGCR_DCPGBSY,d1
+	lne
+
+	# check purge & invalidate of end address
+	add	d2,a2		# a2 += alignsize
+	cmp	a1,a2		# if (a2 < end) goto dcpgivloop
+	bns	dcpgivloop
+
+	LOCAL_IRQ_RESTORE(d3)
+
+mn10300_local_dcache_flush_inv_range_end:
+	ret	[d2,d3,a2],12
+	.size	mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page
+	.size	mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range
+	.size	mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2
diff --git a/arch/mn10300/mm/cache-flush-by-tag.S b/arch/mn10300/mm/cache-flush-by-tag.S
new file mode 100644
index 0000000..1ddc068
--- /dev/null
+++ b/arch/mn10300/mm/cache-flush-by-tag.S
@@ -0,0 +1,250 @@
+/* MN10300 CPU core caching routines, using direct tag flushing
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+
+	.am33_2
+
+#ifndef CONFIG_SMP
+	.globl mn10300_dcache_flush
+	.globl mn10300_dcache_flush_page
+	.globl mn10300_dcache_flush_range
+	.globl mn10300_dcache_flush_range2
+	.globl mn10300_dcache_flush_inv
+	.globl mn10300_dcache_flush_inv_page
+	.globl mn10300_dcache_flush_inv_range
+	.globl mn10300_dcache_flush_inv_range2
+
+mn10300_dcache_flush		= mn10300_local_dcache_flush
+mn10300_dcache_flush_page	= mn10300_local_dcache_flush_page
+mn10300_dcache_flush_range	= mn10300_local_dcache_flush_range
+mn10300_dcache_flush_range2	= mn10300_local_dcache_flush_range2
+mn10300_dcache_flush_inv	= mn10300_local_dcache_flush_inv
+mn10300_dcache_flush_inv_page	= mn10300_local_dcache_flush_inv_page
+mn10300_dcache_flush_inv_range	= mn10300_local_dcache_flush_inv_range
+mn10300_dcache_flush_inv_range2	= mn10300_local_dcache_flush_inv_range2
+
+#endif /* !CONFIG_SMP */
+
+###############################################################################
+#
+# void mn10300_local_dcache_flush(void)
+# Flush the entire data cache back to RAM
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_flush
+        .type	mn10300_local_dcache_flush,@function
+mn10300_local_dcache_flush:
+	movhu	(CHCTR),d0
+	btst	CHCTR_DCEN,d0
+	beq	mn10300_local_dcache_flush_end
+
+	# read the addresses tagged in the cache's tag RAM and attempt to flush
+	# those addresses specifically
+	# - we rely on the hardware to filter out invalid tag entry addresses
+	mov	DCACHE_TAG(0,0),a0		# dcache tag RAM access address
+	mov	DCACHE_PURGE(0,0),a1		# dcache purge request address
+	mov	L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1  # total number of entries
+
+mn10300_local_dcache_flush_loop:
+	mov	(a0),d0
+	and	L1_CACHE_TAG_MASK,d0
+	or	L1_CACHE_TAG_VALID,d0		# retain valid entries in the
+						# cache
+	mov	d0,(a1)				# conditional purge
+
+	add	L1_CACHE_BYTES,a0
+	add	L1_CACHE_BYTES,a1
+	add	-1,d1
+	bne	mn10300_local_dcache_flush_loop
+
+mn10300_local_dcache_flush_end:
+	ret	[],0
+	.size	mn10300_local_dcache_flush,.-mn10300_local_dcache_flush
+
+###############################################################################
+#
+# void mn10300_local_dcache_flush_page(unsigned long start)
+# void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end)
+# void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size)
+# Flush a range of addresses on a page in the dcache
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_flush_page
+	.globl	mn10300_local_dcache_flush_range
+	.globl	mn10300_local_dcache_flush_range2
+	.type	mn10300_local_dcache_flush_page,@function
+	.type	mn10300_local_dcache_flush_range,@function
+	.type	mn10300_local_dcache_flush_range2,@function
+mn10300_local_dcache_flush_page:
+	and	~(PAGE_SIZE-1),d0
+	mov	PAGE_SIZE,d1
+mn10300_local_dcache_flush_range2:
+	add	d0,d1
+mn10300_local_dcache_flush_range:
+	movm	[d2],(sp)
+
+	movhu	(CHCTR),d2
+	btst	CHCTR_DCEN,d2
+	beq	mn10300_local_dcache_flush_range_end
+
+	sub	d0,d1,a0
+	cmp	MN10300_DCACHE_FLUSH_BORDER,a0
+	ble	1f
+
+	movm	(sp),[d2]
+	bra	mn10300_local_dcache_flush
+1:
+
+	# round start addr down
+	and	L1_CACHE_TAG_MASK,d0
+	mov	d0,a1
+
+	add	L1_CACHE_BYTES,d1			# round end addr up
+	and	L1_CACHE_TAG_MASK,d1
+
+	# write a request to flush all instances of an address from the cache
+	mov	DCACHE_PURGE(0,0),a0
+	mov	a1,d0
+	and	L1_CACHE_TAG_ENTRY,d0
+	add	d0,a0				# starting dcache purge control
+						# reg address
+
+	sub	a1,d1
+	lsr	L1_CACHE_SHIFT,d1		# total number of entries to
+						# examine
+
+	or	L1_CACHE_TAG_VALID,a1		# retain valid entries in the
+						# cache
+
+mn10300_local_dcache_flush_range_loop:
+	mov	a1,(L1_CACHE_WAYDISP*0,a0)	# conditionally purge this line
+						# all ways
+
+	add	L1_CACHE_BYTES,a0
+	add	L1_CACHE_BYTES,a1
+	and	~L1_CACHE_WAYDISP,a0		# make sure way stay on way 0
+	add	-1,d1
+	bne	mn10300_local_dcache_flush_range_loop
+
+mn10300_local_dcache_flush_range_end:
+	ret	[d2],4
+
+	.size	mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page
+	.size	mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range
+	.size	mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2
+
+###############################################################################
+#
+# void mn10300_local_dcache_flush_inv(void)
+# Flush the entire data cache and invalidate all entries
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_flush_inv
+	.type	mn10300_local_dcache_flush_inv,@function
+mn10300_local_dcache_flush_inv:
+	movhu	(CHCTR),d0
+	btst	CHCTR_DCEN,d0
+	beq	mn10300_local_dcache_flush_inv_end
+
+	mov	L1_CACHE_NENTRIES,d1
+	clr	a1
+
+mn10300_local_dcache_flush_inv_loop:
+	mov	(DCACHE_PURGE_WAY0(0),a1),d0	# unconditional purge
+	mov	(DCACHE_PURGE_WAY1(0),a1),d0	# unconditional purge
+	mov	(DCACHE_PURGE_WAY2(0),a1),d0	# unconditional purge
+	mov	(DCACHE_PURGE_WAY3(0),a1),d0	# unconditional purge
+
+	add	L1_CACHE_BYTES,a1
+	add	-1,d1
+	bne	mn10300_local_dcache_flush_inv_loop
+
+mn10300_local_dcache_flush_inv_end:
+	ret	[],0
+	.size	mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv
+
+###############################################################################
+#
+# void mn10300_local_dcache_flush_inv_page(unsigned long start)
+# void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end)
+# void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size)
+# Flush and invalidate a range of addresses on a page in the dcache
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_flush_inv_page
+	.globl	mn10300_local_dcache_flush_inv_range
+	.globl	mn10300_local_dcache_flush_inv_range2
+	.type	mn10300_local_dcache_flush_inv_page,@function
+	.type	mn10300_local_dcache_flush_inv_range,@function
+	.type	mn10300_local_dcache_flush_inv_range2,@function
+mn10300_local_dcache_flush_inv_page:
+	and	~(PAGE_SIZE-1),d0
+	mov	PAGE_SIZE,d1
+mn10300_local_dcache_flush_inv_range2:
+	add	d0,d1
+mn10300_local_dcache_flush_inv_range:
+	movm	[d2],(sp)
+
+	movhu	(CHCTR),d2
+	btst	CHCTR_DCEN,d2
+	beq	mn10300_local_dcache_flush_inv_range_end
+
+	sub	d0,d1,a0
+	cmp	MN10300_DCACHE_FLUSH_INV_BORDER,a0
+	ble	1f
+
+	movm	(sp),[d2]
+	bra	mn10300_local_dcache_flush_inv
+1:
+
+	and	L1_CACHE_TAG_MASK,d0		# round start addr down
+	mov	d0,a1
+
+	add	L1_CACHE_BYTES,d1		# round end addr up
+	and	L1_CACHE_TAG_MASK,d1
+
+	# write a request to flush and invalidate all instances of an address
+	# from the cache
+	mov	DCACHE_PURGE(0,0),a0
+	mov	a1,d0
+	and	L1_CACHE_TAG_ENTRY,d0
+	add	d0,a0				# starting dcache purge control
+						# reg address
+
+	sub	a1,d1
+	lsr	L1_CACHE_SHIFT,d1		# total number of entries to
+						# examine
+
+mn10300_local_dcache_flush_inv_range_loop:
+	mov	a1,(L1_CACHE_WAYDISP*0,a0)	# conditionally purge this line
+						# in all ways
+
+	add	L1_CACHE_BYTES,a0
+	add	L1_CACHE_BYTES,a1
+	and	~L1_CACHE_WAYDISP,a0		# make sure way stay on way 0
+	add	-1,d1
+	bne	mn10300_local_dcache_flush_inv_range_loop
+
+mn10300_local_dcache_flush_inv_range_end:
+	ret	[d2],4
+	.size	mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page
+	.size	mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range
+	.size	mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2
diff --git a/arch/mn10300/mm/cache-flush-icache.c b/arch/mn10300/mm/cache-flush-icache.c
new file mode 100644
index 0000000..fdb1a9d
--- /dev/null
+++ b/arch/mn10300/mm/cache-flush-icache.c
@@ -0,0 +1,155 @@
+/* Flush dcache and invalidate icache when the dcache is in writeback mode
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/smp.h>
+#include "cache-smp.h"
+
+/**
+ * flush_icache_page - Flush a page from the dcache and invalidate the icache
+ * @vma: The VMA the page is part of.
+ * @page: The page to be flushed.
+ *
+ * Write a page back from the dcache and invalidate the icache so that we can
+ * run code from it that we've just written into it
+ */
+void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+	unsigned long start = page_to_phys(page);
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+
+	mn10300_local_dcache_flush_page(start);
+	mn10300_local_icache_inv_page(start);
+
+	smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, start + PAGE_SIZE);
+	smp_unlock_cache(flags);
+}
+EXPORT_SYMBOL(flush_icache_page);
+
+/**
+ * flush_icache_page_range - Flush dcache and invalidate icache for part of a
+ *				single page
+ * @start: The starting virtual address of the page part.
+ * @end: The ending virtual address of the page part.
+ *
+ * Flush the dcache and invalidate the icache for part of a single page, as
+ * determined by the virtual addresses given.  The page must be in the paged
+ * area.
+ */
+static void flush_icache_page_range(unsigned long start, unsigned long end)
+{
+	unsigned long addr, size, off;
+	struct page *page;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *ppte, pte;
+
+	/* work out how much of the page to flush */
+	off = start & ~PAGE_MASK;
+	size = end - start;
+
+	/* get the physical address the page is mapped to from the page
+	 * tables */
+	pgd = pgd_offset(current->mm, start);
+	if (!pgd || !pgd_val(*pgd))
+		return;
+
+	pud = pud_offset(pgd, start);
+	if (!pud || !pud_val(*pud))
+		return;
+
+	pmd = pmd_offset(pud, start);
+	if (!pmd || !pmd_val(*pmd))
+		return;
+
+	ppte = pte_offset_map(pmd, start);
+	if (!ppte)
+		return;
+	pte = *ppte;
+	pte_unmap(ppte);
+
+	if (pte_none(pte))
+		return;
+
+	page = pte_page(pte);
+	if (!page)
+		return;
+
+	addr = page_to_phys(page);
+
+	/* flush the dcache and invalidate the icache coverage on that
+	 * region */
+	mn10300_local_dcache_flush_range2(addr + off, size);
+	mn10300_local_icache_inv_range2(addr + off, size);
+	smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, end);
+}
+
+/**
+ * flush_icache_range - Globally flush dcache and invalidate icache for region
+ * @start: The starting virtual address of the region.
+ * @end: The ending virtual address of the region.
+ *
+ * This is used by the kernel to globally flush some code it has just written
+ * from the dcache back to RAM and then to globally invalidate the icache over
+ * that region so that that code can be run on all CPUs in the system.
+ */
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+	unsigned long start_page, end_page;
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+
+	if (end > 0x80000000UL) {
+		/* addresses above 0xa0000000 do not go through the cache */
+		if (end > 0xa0000000UL) {
+			end = 0xa0000000UL;
+			if (start >= end)
+				goto done;
+		}
+
+		/* kernel addresses between 0x80000000 and 0x9fffffff do not
+		 * require page tables, so we just map such addresses
+		 * directly */
+		start_page = (start >= 0x80000000UL) ? start : 0x80000000UL;
+		mn10300_local_dcache_flush_range(start_page, end);
+		mn10300_local_icache_inv_range(start_page, end);
+		smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start_page, end);
+		if (start_page == start)
+			goto done;
+		end = start_page;
+	}
+
+	start_page = start & PAGE_MASK;
+	end_page = (end - 1) & PAGE_MASK;
+
+	if (start_page == end_page) {
+		/* the first and last bytes are on the same page */
+		flush_icache_page_range(start, end);
+	} else if (start_page + 1 == end_page) {
+		/* split over two virtually contiguous pages */
+		flush_icache_page_range(start, end_page);
+		flush_icache_page_range(end_page, end);
+	} else {
+		/* more than 2 pages; just flush the entire cache */
+		mn10300_dcache_flush();
+		mn10300_icache_inv();
+		smp_cache_call(SMP_IDCACHE_INV_FLUSH, 0, 0);
+	}
+
+done:
+	smp_unlock_cache(flags);
+}
+EXPORT_SYMBOL(flush_icache_range);
diff --git a/arch/mn10300/mm/cache-inv-by-reg.S b/arch/mn10300/mm/cache-inv-by-reg.S
new file mode 100644
index 0000000..a60825b
--- /dev/null
+++ b/arch/mn10300/mm/cache-inv-by-reg.S
@@ -0,0 +1,350 @@
+/* MN10300 CPU cache invalidation routines, using automatic purge registers
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+#define mn10300_local_dcache_inv_range_intr_interval \
+	+((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
+
+#if mn10300_local_dcache_inv_range_intr_interval > 0xff
+#error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
+#endif
+
+	.am33_2
+
+#ifndef CONFIG_SMP
+	.globl	mn10300_icache_inv
+	.globl	mn10300_icache_inv_page
+	.globl	mn10300_icache_inv_range
+	.globl	mn10300_icache_inv_range2
+	.globl	mn10300_dcache_inv
+	.globl	mn10300_dcache_inv_page
+	.globl	mn10300_dcache_inv_range
+	.globl	mn10300_dcache_inv_range2
+
+mn10300_icache_inv		= mn10300_local_icache_inv
+mn10300_icache_inv_page		= mn10300_local_icache_inv_page
+mn10300_icache_inv_range	= mn10300_local_icache_inv_range
+mn10300_icache_inv_range2	= mn10300_local_icache_inv_range2
+mn10300_dcache_inv		= mn10300_local_dcache_inv
+mn10300_dcache_inv_page		= mn10300_local_dcache_inv_page
+mn10300_dcache_inv_range	= mn10300_local_dcache_inv_range
+mn10300_dcache_inv_range2	= mn10300_local_dcache_inv_range2
+
+#endif /* !CONFIG_SMP */
+
+###############################################################################
+#
+# void mn10300_local_icache_inv(void)
+# Invalidate the entire icache
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_icache_inv
+        .type	mn10300_local_icache_inv,@function
+mn10300_local_icache_inv:
+	mov	CHCTR,a0
+
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	mn10300_local_icache_inv_end
+
+	invalidate_icache 1
+
+mn10300_local_icache_inv_end:
+	ret	[],0
+	.size	mn10300_local_icache_inv,.-mn10300_local_icache_inv
+
+###############################################################################
+#
+# void mn10300_local_dcache_inv(void)
+# Invalidate the entire dcache
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_inv
+	.type	mn10300_local_dcache_inv,@function
+mn10300_local_dcache_inv:
+	mov	CHCTR,a0
+
+	movhu	(a0),d0
+	btst	CHCTR_DCEN,d0
+	beq	mn10300_local_dcache_inv_end
+
+	invalidate_dcache 1
+	
+mn10300_local_dcache_inv_end:
+	ret	[],0
+	.size	mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
+
+###############################################################################
+#
+# void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
+# void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
+# void mn10300_local_dcache_inv_page(unsigned long start)
+# Invalidate a range of addresses on a page in the dcache
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_inv_page
+	.globl	mn10300_local_dcache_inv_range
+	.globl	mn10300_local_dcache_inv_range2
+	.type	mn10300_local_dcache_inv_page,@function
+	.type	mn10300_local_dcache_inv_range,@function
+	.type	mn10300_local_dcache_inv_range2,@function
+mn10300_local_dcache_inv_page:
+	and	~(PAGE_SIZE-1),d0
+	mov	PAGE_SIZE,d1
+mn10300_local_dcache_inv_range2:
+	add	d0,d1
+mn10300_local_dcache_inv_range:
+	# If we are in writeback mode we check the start and end alignments,
+	# and if they're not cacheline-aligned, we must flush any bits outside
+	# the range that share cachelines with stuff inside the range
+#ifdef CONFIG_MN10300_CACHE_WBACK
+	btst	~L1_CACHE_TAG_MASK,d0
+	bne	1f
+	btst	~L1_CACHE_TAG_MASK,d1
+	beq	2f
+1:
+	bra	mn10300_local_dcache_flush_inv_range
+2:
+#endif /* CONFIG_MN10300_CACHE_WBACK */
+
+	movm	[d2,d3,a2],(sp)
+
+	mov	CHCTR,a0
+	movhu	(a0),d2
+	btst	CHCTR_DCEN,d2
+	beq	mn10300_local_dcache_inv_range_end
+
+	# round the addresses out to be full cachelines, unless we're in
+	# writeback mode, in which case we would be in flush and invalidate by
+	# now
+#ifndef CONFIG_MN10300_CACHE_WBACK
+	and	L1_CACHE_TAG_MASK,d0	# round start addr down
+
+	mov	L1_CACHE_BYTES-1,d2
+	add	d2,d1
+	and	L1_CACHE_TAG_MASK,d1	# round end addr up
+#endif /* !CONFIG_MN10300_CACHE_WBACK */
+
+	sub	d0,d1,d2		# calculate the total size
+	mov	d0,a2			# A2 = start address
+	mov	d1,a1			# A1 = end address
+
+	LOCAL_CLI_SAVE(d3)
+
+	mov	DCPGCR,a0		# make sure the purger isn't busy
+	setlb
+	mov	(a0),d0
+	btst	DCPGCR_DCPGBSY,d0
+	lne
+
+	# skip initial address alignment calculation if address is zero
+	mov	d2,d1
+	cmp	0,a2
+	beq	1f
+
+dcivloop:
+	/* calculate alignsize
+	 *
+	 * alignsize = L1_CACHE_BYTES;
+	 * while (! start & alignsize) {
+	 *	alignsize <<=1;
+	 * }
+	 * d1 = alignsize;
+	 */
+	mov	L1_CACHE_BYTES,d1
+	lsr	1,d1
+	setlb
+	add	d1,d1
+	mov	d1,d0
+	and	a2,d0
+	leq
+
+1:
+	/* calculate invsize
+	 *
+	 * if (totalsize > alignsize) {
+	 *	invsize = alignsize;
+	 * } else {
+	 *	invsize = totalsize;
+	 *	tmp = 0x80000000;
+	 *	while (! invsize & tmp) {
+	 *		tmp >>= 1;
+	 *	}
+	 *	invsize = tmp;
+	 * }
+	 * d1 = invsize
+	 */
+	cmp	d2,d1
+	bns	2f
+	mov	d2,d1
+
+	mov	0x80000000,d0		# start from 31bit=1
+	setlb
+	lsr	1,d0
+	mov	d0,e0
+	and	d1,e0
+	leq
+	mov	d0,d1
+
+2:
+	/* set mask
+	 *
+	 * mask = ~(invsize-1);
+	 * DCPGMR = mask;
+	 */
+	mov	d1,d0
+	add	-1,d0
+	not	d0
+	mov	d0,(DCPGMR)
+
+	# invalidate area
+	mov	a2,d0
+	or	DCPGCR_DCI,d0
+	mov	d0,(a0)			# DCPGCR = (mask & start) | DCPGCR_DCI
+
+	setlb				# wait for the purge to complete
+	mov	(a0),d0
+	btst	DCPGCR_DCPGBSY,d0
+	lne
+
+	sub	d1,d2			# decrease size remaining
+	add	d1,a2			# increase next start address
+
+	/* check invalidating of end address
+	 *
+	 * a2 = a2 + invsize
+	 * if (a2 < end) {
+	 *     goto dcivloop;
+	 * } */
+	cmp	a1,a2
+	bns	dcivloop
+
+	LOCAL_IRQ_RESTORE(d3)
+
+mn10300_local_dcache_inv_range_end:
+	ret	[d2,d3,a2],12
+	.size	mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
+	.size	mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
+	.size	mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2
+
+###############################################################################
+#
+# void mn10300_local_icache_inv_page(unsigned long start)
+# void mn10300_local_icache_inv_range2(unsigned long start, unsigned long size)
+# void mn10300_local_icache_inv_range(unsigned long start, unsigned long end)
+# Invalidate a range of addresses on a page in the icache
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_icache_inv_page
+	.globl	mn10300_local_icache_inv_range
+	.globl	mn10300_local_icache_inv_range2
+	.type	mn10300_local_icache_inv_page,@function
+	.type	mn10300_local_icache_inv_range,@function
+	.type	mn10300_local_icache_inv_range2,@function
+mn10300_local_icache_inv_page:
+	and	~(PAGE_SIZE-1),d0
+	mov	PAGE_SIZE,d1
+mn10300_local_icache_inv_range2:
+	add	d0,d1
+mn10300_local_icache_inv_range:
+	movm	[d2,d3,a2],(sp)
+
+	mov	CHCTR,a0
+	movhu	(a0),d2
+	btst	CHCTR_ICEN,d2
+	beq	mn10300_local_icache_inv_range_reg_end
+
+	/* calculate alignsize
+	 *
+	 * alignsize = L1_CACHE_BYTES;
+	 * for (i = (end - start - 1) / L1_CACHE_BYTES ;  i > 0; i >>= 1) {
+	 *     alignsize <<= 1;
+	 * }
+	 * d2 = alignsize;
+	 */
+	mov	L1_CACHE_BYTES,d2
+	sub	d0,d1,d3
+	add	-1,d3
+	lsr	L1_CACHE_SHIFT,d3
+	beq	2f
+1:
+	add	d2,d2
+	lsr	1,d3
+	bne	1b
+2:
+
+	/* a1 = end */
+	mov	d1,a1
+
+	LOCAL_CLI_SAVE(d3)
+
+	mov	ICIVCR,a0
+	/* wait for busy bit of area invalidation */
+	setlb
+	mov	(a0),d1
+	btst	ICIVCR_ICIVBSY,d1
+	lne
+
+	/* set mask
+	 *
+	 * mask = ~(alignsize-1);
+	 * ICIVMR = mask;
+	 */
+	mov	d2,d1
+	add	-1,d1
+	not	d1
+	mov	d1,(ICIVMR)
+	/* a2 = mask & start */
+	and	d1,d0,a2
+
+icivloop:
+	/* area invalidate
+	 *
+	 * ICIVCR = (mask & start) | ICIVCR_ICI
+	 */
+	mov	a2,d0
+	or	ICIVCR_ICI,d0
+	mov	d0,(a0)
+
+	/* wait for busy bit of area invalidation */
+	setlb
+	mov	(a0),d1
+	btst	ICIVCR_ICIVBSY,d1
+	lne
+
+	/* check invalidating of end address
+	 *
+	 * a2 = a2 + alignsize
+	 * if (a2 < end) {
+	 *     goto icivloop;
+	 * } */
+	add	d2,a2
+	cmp	a1,a2
+	bns	icivloop
+
+	LOCAL_IRQ_RESTORE(d3)
+
+mn10300_local_icache_inv_range_reg_end:
+	ret	[d2,d3,a2],12
+	.size	mn10300_local_icache_inv_page,.-mn10300_local_icache_inv_page
+	.size	mn10300_local_icache_inv_range,.-mn10300_local_icache_inv_range
+	.size	mn10300_local_icache_inv_range2,.-mn10300_local_icache_inv_range2
diff --git a/arch/mn10300/mm/cache-inv-by-tag.S b/arch/mn10300/mm/cache-inv-by-tag.S
new file mode 100644
index 0000000..ccedce9
--- /dev/null
+++ b/arch/mn10300/mm/cache-inv-by-tag.S
@@ -0,0 +1,276 @@
+/* MN10300 CPU core caching routines
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+#define mn10300_local_dcache_inv_range_intr_interval \
+	+((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
+
+#if mn10300_local_dcache_inv_range_intr_interval > 0xff
+#error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
+#endif
+
+	.am33_2
+
+	.globl	mn10300_local_icache_inv_page
+	.globl	mn10300_local_icache_inv_range
+	.globl	mn10300_local_icache_inv_range2
+
+mn10300_local_icache_inv_page	= mn10300_local_icache_inv
+mn10300_local_icache_inv_range	= mn10300_local_icache_inv
+mn10300_local_icache_inv_range2	= mn10300_local_icache_inv
+
+#ifndef CONFIG_SMP
+	.globl	mn10300_icache_inv
+	.globl	mn10300_icache_inv_page
+	.globl	mn10300_icache_inv_range
+	.globl	mn10300_icache_inv_range2
+	.globl	mn10300_dcache_inv
+	.globl	mn10300_dcache_inv_page
+	.globl	mn10300_dcache_inv_range
+	.globl	mn10300_dcache_inv_range2
+
+mn10300_icache_inv		= mn10300_local_icache_inv
+mn10300_icache_inv_page		= mn10300_local_icache_inv_page
+mn10300_icache_inv_range	= mn10300_local_icache_inv_range
+mn10300_icache_inv_range2	= mn10300_local_icache_inv_range2
+mn10300_dcache_inv		= mn10300_local_dcache_inv
+mn10300_dcache_inv_page		= mn10300_local_dcache_inv_page
+mn10300_dcache_inv_range	= mn10300_local_dcache_inv_range
+mn10300_dcache_inv_range2	= mn10300_local_dcache_inv_range2
+
+#endif /* !CONFIG_SMP */
+
+###############################################################################
+#
+# void mn10300_local_icache_inv(void)
+# Invalidate the entire icache
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_icache_inv
+        .type	mn10300_local_icache_inv,@function
+mn10300_local_icache_inv:
+	mov	CHCTR,a0
+
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	mn10300_local_icache_inv_end
+
+	invalidate_icache 1
+
+mn10300_local_icache_inv_end:
+	ret	[],0
+	.size	mn10300_local_icache_inv,.-mn10300_local_icache_inv
+
+###############################################################################
+#
+# void mn10300_local_dcache_inv(void)
+# Invalidate the entire dcache
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_inv
+	.type	mn10300_local_dcache_inv,@function
+mn10300_local_dcache_inv:
+	mov	CHCTR,a0
+
+	movhu	(a0),d0
+	btst	CHCTR_DCEN,d0
+	beq	mn10300_local_dcache_inv_end
+
+	invalidate_dcache 1
+
+mn10300_local_dcache_inv_end:
+	ret	[],0
+	.size	mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
+
+###############################################################################
+#
+# void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
+# void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
+# void mn10300_local_dcache_inv_page(unsigned long start)
+# Invalidate a range of addresses on a page in the dcache
+#
+###############################################################################
+	ALIGN
+	.globl	mn10300_local_dcache_inv_page
+	.globl	mn10300_local_dcache_inv_range
+	.globl	mn10300_local_dcache_inv_range2
+	.type	mn10300_local_dcache_inv_page,@function
+	.type	mn10300_local_dcache_inv_range,@function
+	.type	mn10300_local_dcache_inv_range2,@function
+mn10300_local_dcache_inv_page:
+	and	~(PAGE_SIZE-1),d0
+	mov	PAGE_SIZE,d1
+mn10300_local_dcache_inv_range2:
+	add	d0,d1
+mn10300_local_dcache_inv_range:
+	# If we are in writeback mode we check the start and end alignments,
+	# and if they're not cacheline-aligned, we must flush any bits outside
+	# the range that share cachelines with stuff inside the range
+#ifdef CONFIG_MN10300_CACHE_WBACK
+	btst	~L1_CACHE_TAG_MASK,d0
+	bne	1f
+	btst	~L1_CACHE_TAG_MASK,d1
+	beq	2f
+1:
+	bra	mn10300_local_dcache_flush_inv_range
+2:
+#endif /* CONFIG_MN10300_CACHE_WBACK */
+
+	movm	[d2,d3,a2],(sp)
+
+	mov	CHCTR,a2
+	movhu	(a2),d2
+	btst	CHCTR_DCEN,d2
+	beq	mn10300_local_dcache_inv_range_end
+
+#ifndef CONFIG_MN10300_CACHE_WBACK
+	and	L1_CACHE_TAG_MASK,d0		# round start addr down
+
+	add	L1_CACHE_BYTES,d1		# round end addr up
+	and	L1_CACHE_TAG_MASK,d1
+#endif /* !CONFIG_MN10300_CACHE_WBACK */
+	mov	d0,a1
+
+	clr	d2				# we're going to clear tag RAM
+						# entries
+
+	# read the tags from the tag RAM, and if they indicate a valid dirty
+	# cache line then invalidate that line
+	mov	DCACHE_TAG(0,0),a0
+	mov	a1,d0
+	and	L1_CACHE_TAG_ENTRY,d0
+	add	d0,a0				# starting dcache tag RAM
+						# access address
+
+	sub	a1,d1
+	lsr	L1_CACHE_SHIFT,d1		# total number of entries to
+						# examine
+
+	and	~(L1_CACHE_DISPARITY-1),a1	# determine comparator base
+
+mn10300_local_dcache_inv_range_outer_loop:
+	LOCAL_CLI_SAVE(d3)
+
+	# disable the dcache
+	movhu	(a2),d0
+	and	~CHCTR_DCEN,d0
+	movhu	d0,(a2)
+
+	# and wait for it to calm down
+	setlb
+	movhu	(a2),d0
+	btst	CHCTR_DCBUSY,d0
+	lne
+
+mn10300_local_dcache_inv_range_loop:
+
+	# process the way 0 slot
+	mov	(L1_CACHE_WAYDISP*0,a0),d0	# read the tag in the way 0 slot
+	btst	L1_CACHE_TAG_VALID,d0
+	beq	mn10300_local_dcache_inv_range_skip_0	# jump if this cacheline
+						# is not valid
+
+	xor	a1,d0
+	lsr	12,d0
+	bne	mn10300_local_dcache_inv_range_skip_0	# jump if not this cacheline
+
+	mov	d2,(L1_CACHE_WAYDISP*0,a0)	# kill the tag
+
+mn10300_local_dcache_inv_range_skip_0:
+
+	# process the way 1 slot
+	mov	(L1_CACHE_WAYDISP*1,a0),d0	# read the tag in the way 1 slot
+	btst	L1_CACHE_TAG_VALID,d0
+	beq	mn10300_local_dcache_inv_range_skip_1	# jump if this cacheline
+						# is not valid
+
+	xor	a1,d0
+	lsr	12,d0
+	bne	mn10300_local_dcache_inv_range_skip_1	# jump if not this cacheline
+
+	mov	d2,(L1_CACHE_WAYDISP*1,a0)	# kill the tag
+
+mn10300_local_dcache_inv_range_skip_1:
+
+	# process the way 2 slot
+	mov	(L1_CACHE_WAYDISP*2,a0),d0	# read the tag in the way 2 slot
+	btst	L1_CACHE_TAG_VALID,d0
+	beq	mn10300_local_dcache_inv_range_skip_2	# jump if this cacheline
+						# is not valid
+
+	xor	a1,d0
+	lsr	12,d0
+	bne	mn10300_local_dcache_inv_range_skip_2	# jump if not this cacheline
+
+	mov	d2,(L1_CACHE_WAYDISP*2,a0)	# kill the tag
+
+mn10300_local_dcache_inv_range_skip_2:
+
+	# process the way 3 slot
+	mov	(L1_CACHE_WAYDISP*3,a0),d0	# read the tag in the way 3 slot
+	btst	L1_CACHE_TAG_VALID,d0
+	beq	mn10300_local_dcache_inv_range_skip_3	# jump if this cacheline
+						# is not valid
+
+	xor	a1,d0
+	lsr	12,d0
+	bne	mn10300_local_dcache_inv_range_skip_3	# jump if not this cacheline
+
+	mov	d2,(L1_CACHE_WAYDISP*3,a0)	# kill the tag
+
+mn10300_local_dcache_inv_range_skip_3:
+
+	# approx every N steps we re-enable the cache and see if there are any
+	# interrupts to be processed
+	# we also break out if we've reached the end of the loop
+	# (the bottom nibble of the count is zero in both cases)
+	add	L1_CACHE_BYTES,a0
+	add	L1_CACHE_BYTES,a1
+	and	~L1_CACHE_WAYDISP,a0
+	add	-1,d1
+	btst	mn10300_local_dcache_inv_range_intr_interval,d1
+	bne	mn10300_local_dcache_inv_range_loop
+
+	# wait for the cache to finish what it's doing
+	setlb
+	movhu	(a2),d0
+	btst	CHCTR_DCBUSY,d0
+	lne
+
+	# and reenable it
+	or	CHCTR_DCEN,d0
+	movhu	d0,(a2)
+	movhu	(a2),d0
+
+	# re-enable interrupts
+	# - we don't bother with delay NOPs as we'll have enough instructions
+	#   before we disable interrupts again to give the interrupts a chance
+	#   to happen
+	LOCAL_IRQ_RESTORE(d3)
+
+	# go around again if the counter hasn't yet reached zero
+	add	0,d1
+	bne	mn10300_local_dcache_inv_range_outer_loop
+
+mn10300_local_dcache_inv_range_end:
+	ret	[d2,d3,a2],12
+	.size	mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
+	.size	mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
+	.size	mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2
diff --git a/arch/mn10300/mm/cache-inv-icache.c b/arch/mn10300/mm/cache-inv-icache.c
new file mode 100644
index 0000000..a6b63dd
--- /dev/null
+++ b/arch/mn10300/mm/cache-inv-icache.c
@@ -0,0 +1,129 @@
+/* Invalidate icache when dcache doesn't need invalidation as it's in
+ * write-through mode
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/smp.h>
+#include "cache-smp.h"
+
+/**
+ * flush_icache_page_range - Flush dcache and invalidate icache for part of a
+ *				single page
+ * @start: The starting virtual address of the page part.
+ * @end: The ending virtual address of the page part.
+ *
+ * Invalidate the icache for part of a single page, as determined by the
+ * virtual addresses given.  The page must be in the paged area.  The dcache is
+ * not flushed as the cache must be in write-through mode to get here.
+ */
+static void flush_icache_page_range(unsigned long start, unsigned long end)
+{
+	unsigned long addr, size, off;
+	struct page *page;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *ppte, pte;
+
+	/* work out how much of the page to flush */
+	off = start & ~PAGE_MASK;
+	size = end - start;
+
+	/* get the physical address the page is mapped to from the page
+	 * tables */
+	pgd = pgd_offset(current->mm, start);
+	if (!pgd || !pgd_val(*pgd))
+		return;
+
+	pud = pud_offset(pgd, start);
+	if (!pud || !pud_val(*pud))
+		return;
+
+	pmd = pmd_offset(pud, start);
+	if (!pmd || !pmd_val(*pmd))
+		return;
+
+	ppte = pte_offset_map(pmd, start);
+	if (!ppte)
+		return;
+	pte = *ppte;
+	pte_unmap(ppte);
+
+	if (pte_none(pte))
+		return;
+
+	page = pte_page(pte);
+	if (!page)
+		return;
+
+	addr = page_to_phys(page);
+
+	/* invalidate the icache coverage on that region */
+	mn10300_local_icache_inv_range2(addr + off, size);
+	smp_cache_call(SMP_ICACHE_INV_RANGE, start, end);
+}
+
+/**
+ * flush_icache_range - Globally flush dcache and invalidate icache for region
+ * @start: The starting virtual address of the region.
+ * @end: The ending virtual address of the region.
+ *
+ * This is used by the kernel to globally flush some code it has just written
+ * from the dcache back to RAM and then to globally invalidate the icache over
+ * that region so that that code can be run on all CPUs in the system.
+ */
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+	unsigned long start_page, end_page;
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+
+	if (end > 0x80000000UL) {
+		/* addresses above 0xa0000000 do not go through the cache */
+		if (end > 0xa0000000UL) {
+			end = 0xa0000000UL;
+			if (start >= end)
+				goto done;
+		}
+
+		/* kernel addresses between 0x80000000 and 0x9fffffff do not
+		 * require page tables, so we just map such addresses
+		 * directly */
+		start_page = (start >= 0x80000000UL) ? start : 0x80000000UL;
+		mn10300_icache_inv_range(start_page, end);
+		smp_cache_call(SMP_ICACHE_INV_RANGE, start, end);
+		if (start_page == start)
+			goto done;
+		end = start_page;
+	}
+
+	start_page = start & PAGE_MASK;
+	end_page = (end - 1) & PAGE_MASK;
+
+	if (start_page == end_page) {
+		/* the first and last bytes are on the same page */
+		flush_icache_page_range(start, end);
+	} else if (start_page + 1 == end_page) {
+		/* split over two virtually contiguous pages */
+		flush_icache_page_range(start, end_page);
+		flush_icache_page_range(end_page, end);
+	} else {
+		/* more than 2 pages; just flush the entire cache */
+		mn10300_local_icache_inv();
+		smp_cache_call(SMP_ICACHE_INV, 0, 0);
+	}
+
+done:
+	smp_unlock_cache(flags);
+}
+EXPORT_SYMBOL(flush_icache_range);
diff --git a/arch/mn10300/mm/cache-smp-flush.c b/arch/mn10300/mm/cache-smp-flush.c
new file mode 100644
index 0000000..fd51af5
--- /dev/null
+++ b/arch/mn10300/mm/cache-smp-flush.c
@@ -0,0 +1,156 @@
+/* Functions for global dcache flush when writeback caching in SMP
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include "cache-smp.h"
+
+/**
+ * mn10300_dcache_flush - Globally flush data cache
+ *
+ * Flush the data cache on all CPUs.
+ */
+void mn10300_dcache_flush(void)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_flush();
+	smp_cache_call(SMP_DCACHE_FLUSH, 0, 0);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_dcache_flush_page - Globally flush a page of data cache
+ * @start: The address of the page of memory to be flushed.
+ *
+ * Flush a range of addresses in the data cache on all CPUs covering
+ * the page that includes the given address.
+ */
+void mn10300_dcache_flush_page(unsigned long start)
+{
+	unsigned long flags;
+
+	start &= ~(PAGE_SIZE-1);
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_flush_page(start);
+	smp_cache_call(SMP_DCACHE_FLUSH_RANGE, start, start + PAGE_SIZE);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_dcache_flush_range - Globally flush range of data cache
+ * @start: The start address of the region to be flushed.
+ * @end: The end address of the region to be flushed.
+ *
+ * Flush a range of addresses in the data cache on all CPUs, between start and
+ * end-1 inclusive.
+ */
+void mn10300_dcache_flush_range(unsigned long start, unsigned long end)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_flush_range(start, end);
+	smp_cache_call(SMP_DCACHE_FLUSH_RANGE, start, end);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_dcache_flush_range2 - Globally flush range of data cache
+ * @start: The start address of the region to be flushed.
+ * @size: The size of the region to be flushed.
+ *
+ * Flush a range of addresses in the data cache on all CPUs, between start and
+ * start+size-1 inclusive.
+ */
+void mn10300_dcache_flush_range2(unsigned long start, unsigned long size)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_flush_range2(start, size);
+	smp_cache_call(SMP_DCACHE_FLUSH_RANGE, start, start + size);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_dcache_flush_inv - Globally flush and invalidate data cache
+ *
+ * Flush and invalidate the data cache on all CPUs.
+ */
+void mn10300_dcache_flush_inv(void)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_flush_inv();
+	smp_cache_call(SMP_DCACHE_FLUSH_INV, 0, 0);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_dcache_flush_inv_page - Globally flush and invalidate a page of data
+ *	cache
+ * @start: The address of the page of memory to be flushed and invalidated.
+ *
+ * Flush and invalidate a range of addresses in the data cache on all CPUs
+ * covering the page that includes the given address.
+ */
+void mn10300_dcache_flush_inv_page(unsigned long start)
+{
+	unsigned long flags;
+
+	start &= ~(PAGE_SIZE-1);
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_flush_inv_page(start);
+	smp_cache_call(SMP_DCACHE_FLUSH_INV_RANGE, start, start + PAGE_SIZE);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_dcache_flush_inv_range - Globally flush and invalidate range of data
+ *	cache
+ * @start: The start address of the region to be flushed and invalidated.
+ * @end: The end address of the region to be flushed and invalidated.
+ *
+ * Flush and invalidate a range of addresses in the data cache on all CPUs,
+ * between start and end-1 inclusive.
+ */
+void mn10300_dcache_flush_inv_range(unsigned long start, unsigned long end)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_flush_inv_range(start, end);
+	smp_cache_call(SMP_DCACHE_FLUSH_INV_RANGE, start, end);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_dcache_flush_inv_range2 - Globally flush and invalidate range of data
+ *	cache
+ * @start: The start address of the region to be flushed and invalidated.
+ * @size: The size of the region to be flushed and invalidated.
+ *
+ * Flush and invalidate a range of addresses in the data cache on all CPUs,
+ * between start and start+size-1 inclusive.
+ */
+void mn10300_dcache_flush_inv_range2(unsigned long start, unsigned long size)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_flush_inv_range2(start, size);
+	smp_cache_call(SMP_DCACHE_FLUSH_INV_RANGE, start, start + size);
+	smp_unlock_cache(flags);
+}
diff --git a/arch/mn10300/mm/cache-smp-inv.c b/arch/mn10300/mm/cache-smp-inv.c
new file mode 100644
index 0000000..ff17873
--- /dev/null
+++ b/arch/mn10300/mm/cache-smp-inv.c
@@ -0,0 +1,153 @@
+/* Functions for global i/dcache invalidation when caching in SMP
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include "cache-smp.h"
+
+/**
+ * mn10300_icache_inv - Globally invalidate instruction cache
+ *
+ * Invalidate the instruction cache on all CPUs.
+ */
+void mn10300_icache_inv(void)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_icache_inv();
+	smp_cache_call(SMP_ICACHE_INV, 0, 0);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_icache_inv_page - Globally invalidate a page of instruction cache
+ * @start: The address of the page of memory to be invalidated.
+ *
+ * Invalidate a range of addresses in the instruction cache on all CPUs
+ * covering the page that includes the given address.
+ */
+void mn10300_icache_inv_page(unsigned long start)
+{
+	unsigned long flags;
+
+	start &= ~(PAGE_SIZE-1);
+
+	flags = smp_lock_cache();
+	mn10300_local_icache_inv_page(start);
+	smp_cache_call(SMP_ICACHE_INV_RANGE, start, start + PAGE_SIZE);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_icache_inv_range - Globally invalidate range of instruction cache
+ * @start: The start address of the region to be invalidated.
+ * @end: The end address of the region to be invalidated.
+ *
+ * Invalidate a range of addresses in the instruction cache on all CPUs,
+ * between start and end-1 inclusive.
+ */
+void mn10300_icache_inv_range(unsigned long start, unsigned long end)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_icache_inv_range(start, end);
+	smp_cache_call(SMP_ICACHE_INV_RANGE, start, end);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_icache_inv_range2 - Globally invalidate range of instruction cache
+ * @start: The start address of the region to be invalidated.
+ * @size: The size of the region to be invalidated.
+ *
+ * Invalidate a range of addresses in the instruction cache on all CPUs,
+ * between start and start+size-1 inclusive.
+ */
+void mn10300_icache_inv_range2(unsigned long start, unsigned long size)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_icache_inv_range2(start, size);
+	smp_cache_call(SMP_ICACHE_INV_RANGE, start, start + size);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_dcache_inv - Globally invalidate data cache
+ *
+ * Invalidate the data cache on all CPUs.
+ */
+void mn10300_dcache_inv(void)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_inv();
+	smp_cache_call(SMP_DCACHE_INV, 0, 0);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_dcache_inv_page - Globally invalidate a page of data cache
+ * @start: The address of the page of memory to be invalidated.
+ *
+ * Invalidate a range of addresses in the data cache on all CPUs covering the
+ * page that includes the given address.
+ */
+void mn10300_dcache_inv_page(unsigned long start)
+{
+	unsigned long flags;
+
+	start &= ~(PAGE_SIZE-1);
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_inv_page(start);
+	smp_cache_call(SMP_DCACHE_INV_RANGE, start, start + PAGE_SIZE);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_dcache_inv_range - Globally invalidate range of data cache
+ * @start: The start address of the region to be invalidated.
+ * @end: The end address of the region to be invalidated.
+ *
+ * Invalidate a range of addresses in the data cache on all CPUs, between start
+ * and end-1 inclusive.
+ */
+void mn10300_dcache_inv_range(unsigned long start, unsigned long end)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_inv_range(start, end);
+	smp_cache_call(SMP_DCACHE_INV_RANGE, start, end);
+	smp_unlock_cache(flags);
+}
+
+/**
+ * mn10300_dcache_inv_range2 - Globally invalidate range of data cache
+ * @start: The start address of the region to be invalidated.
+ * @size: The size of the region to be invalidated.
+ *
+ * Invalidate a range of addresses in the data cache on all CPUs, between start
+ * and start+size-1 inclusive.
+ */
+void mn10300_dcache_inv_range2(unsigned long start, unsigned long size)
+{
+	unsigned long flags;
+
+	flags = smp_lock_cache();
+	mn10300_local_dcache_inv_range2(start, size);
+	smp_cache_call(SMP_DCACHE_INV_RANGE, start, start + size);
+	smp_unlock_cache(flags);
+}
diff --git a/arch/mn10300/mm/cache-smp.c b/arch/mn10300/mm/cache-smp.c
new file mode 100644
index 0000000..2d23b9e
--- /dev/null
+++ b/arch/mn10300/mm/cache-smp.c
@@ -0,0 +1,105 @@
+/* SMP global caching code
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/threads.h>
+#include <linux/interrupt.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/smp.h>
+#include "cache-smp.h"
+
+DEFINE_SPINLOCK(smp_cache_lock);
+static unsigned long smp_cache_mask;
+static unsigned long smp_cache_start;
+static unsigned long smp_cache_end;
+static cpumask_t smp_cache_ipi_map;		/* Bitmask of cache IPI done CPUs */
+
+/**
+ * smp_cache_interrupt - Handle IPI request to flush caches.
+ *
+ * Handle a request delivered by IPI to flush the current CPU's
+ * caches.  The parameters are stored in smp_cache_*.
+ */
+void smp_cache_interrupt(void)
+{
+	unsigned long opr_mask = smp_cache_mask;
+
+	switch ((enum smp_dcache_ops)(opr_mask & SMP_DCACHE_OP_MASK)) {
+	case SMP_DCACHE_NOP:
+		break;
+	case SMP_DCACHE_INV:
+		mn10300_local_dcache_inv();
+		break;
+	case SMP_DCACHE_INV_RANGE:
+		mn10300_local_dcache_inv_range(smp_cache_start, smp_cache_end);
+		break;
+	case SMP_DCACHE_FLUSH:
+		mn10300_local_dcache_flush();
+		break;
+	case SMP_DCACHE_FLUSH_RANGE:
+		mn10300_local_dcache_flush_range(smp_cache_start,
+						 smp_cache_end);
+		break;
+	case SMP_DCACHE_FLUSH_INV:
+		mn10300_local_dcache_flush_inv();
+		break;
+	case SMP_DCACHE_FLUSH_INV_RANGE:
+		mn10300_local_dcache_flush_inv_range(smp_cache_start,
+						     smp_cache_end);
+		break;
+	}
+
+	switch ((enum smp_icache_ops)(opr_mask & SMP_ICACHE_OP_MASK)) {
+	case SMP_ICACHE_NOP:
+		break;
+	case SMP_ICACHE_INV:
+		mn10300_local_icache_inv();
+		break;
+	case SMP_ICACHE_INV_RANGE:
+		mn10300_local_icache_inv_range(smp_cache_start, smp_cache_end);
+		break;
+	}
+
+	cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map);
+}
+
+/**
+ * smp_cache_call - Issue an IPI to request the other CPUs flush caches
+ * @opr_mask: Cache operation flags
+ * @start: Start address of request
+ * @end: End address of request
+ *
+ * Send cache flush IPI to other CPUs.  This invokes smp_cache_interrupt()
+ * above on those other CPUs and then waits for them to finish.
+ *
+ * The caller must hold smp_cache_lock.
+ */
+void smp_cache_call(unsigned long opr_mask,
+		    unsigned long start, unsigned long end)
+{
+	smp_cache_mask = opr_mask;
+	smp_cache_start = start;
+	smp_cache_end = end;
+	cpumask_copy(&smp_cache_ipi_map, cpu_online_mask);
+	cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map);
+
+	send_IPI_allbutself(FLUSH_CACHE_IPI);
+
+	while (!cpumask_empty(&smp_cache_ipi_map))
+		/* nothing. lockup detection does not belong here */
+		mb();
+}
diff --git a/arch/mn10300/mm/cache-smp.h b/arch/mn10300/mm/cache-smp.h
new file mode 100644
index 0000000..cb52892
--- /dev/null
+++ b/arch/mn10300/mm/cache-smp.h
@@ -0,0 +1,69 @@
+/* SMP caching definitions
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+
+/*
+ * Operation requests for smp_cache_call().
+ *
+ * One of smp_icache_ops and one of smp_dcache_ops can be OR'd together.
+ */
+enum smp_icache_ops {
+	SMP_ICACHE_NOP			= 0x0000,
+	SMP_ICACHE_INV			= 0x0001,
+	SMP_ICACHE_INV_RANGE		= 0x0002,
+};
+#define SMP_ICACHE_OP_MASK		0x0003
+
+enum smp_dcache_ops {
+	SMP_DCACHE_NOP			= 0x0000,
+	SMP_DCACHE_INV			= 0x0004,
+	SMP_DCACHE_INV_RANGE		= 0x0008,
+	SMP_DCACHE_FLUSH		= 0x000c,
+	SMP_DCACHE_FLUSH_RANGE		= 0x0010,
+	SMP_DCACHE_FLUSH_INV		= 0x0014,
+	SMP_DCACHE_FLUSH_INV_RANGE	= 0x0018,
+};
+#define SMP_DCACHE_OP_MASK		0x001c
+
+#define	SMP_IDCACHE_INV_FLUSH		(SMP_ICACHE_INV | SMP_DCACHE_FLUSH)
+#define SMP_IDCACHE_INV_FLUSH_RANGE	(SMP_ICACHE_INV_RANGE | SMP_DCACHE_FLUSH_RANGE)
+
+/*
+ * cache-smp.c
+ */
+#ifdef CONFIG_SMP
+extern spinlock_t smp_cache_lock;
+
+extern void smp_cache_call(unsigned long opr_mask,
+			   unsigned long addr, unsigned long end);
+
+static inline unsigned long smp_lock_cache(void)
+	__acquires(&smp_cache_lock)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&smp_cache_lock, flags);
+	return flags;
+}
+
+static inline void smp_unlock_cache(unsigned long flags)
+	__releases(&smp_cache_lock)
+{
+	spin_unlock_irqrestore(&smp_cache_lock, flags);
+}
+
+#else
+static inline unsigned long smp_lock_cache(void) { return 0; }
+static inline void smp_unlock_cache(unsigned long flags) {}
+static inline void smp_cache_call(unsigned long opr_mask,
+				  unsigned long addr, unsigned long end)
+{
+}
+#endif /* CONFIG_SMP */
diff --git a/arch/mn10300/mm/cache.c b/arch/mn10300/mm/cache.c
new file mode 100644
index 0000000..0a1f0aa
--- /dev/null
+++ b/arch/mn10300/mm/cache.c
@@ -0,0 +1,54 @@
+/* MN10300 Cache flushing routines
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/threads.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/smp.h>
+#include "cache-smp.h"
+
+EXPORT_SYMBOL(mn10300_icache_inv);
+EXPORT_SYMBOL(mn10300_icache_inv_range);
+EXPORT_SYMBOL(mn10300_icache_inv_range2);
+EXPORT_SYMBOL(mn10300_icache_inv_page);
+EXPORT_SYMBOL(mn10300_dcache_inv);
+EXPORT_SYMBOL(mn10300_dcache_inv_range);
+EXPORT_SYMBOL(mn10300_dcache_inv_range2);
+EXPORT_SYMBOL(mn10300_dcache_inv_page);
+
+#ifdef CONFIG_MN10300_CACHE_WBACK
+EXPORT_SYMBOL(mn10300_dcache_flush);
+EXPORT_SYMBOL(mn10300_dcache_flush_inv);
+EXPORT_SYMBOL(mn10300_dcache_flush_inv_range);
+EXPORT_SYMBOL(mn10300_dcache_flush_inv_range2);
+EXPORT_SYMBOL(mn10300_dcache_flush_inv_page);
+EXPORT_SYMBOL(mn10300_dcache_flush_range);
+EXPORT_SYMBOL(mn10300_dcache_flush_range2);
+EXPORT_SYMBOL(mn10300_dcache_flush_page);
+#endif
+
+/*
+ * allow userspace to flush the instruction cache
+ */
+asmlinkage long sys_cacheflush(unsigned long start, unsigned long end)
+{
+	if (end < start)
+		return -EINVAL;
+
+	flush_icache_range(start, end);
+	return 0;
+}
diff --git a/arch/mn10300/mm/cache.inc b/arch/mn10300/mm/cache.inc
new file mode 100644
index 0000000..394a119
--- /dev/null
+++ b/arch/mn10300/mm/cache.inc
@@ -0,0 +1,133 @@
+/* MN10300 CPU core caching macros -*- asm -*-
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+
+###############################################################################
+#
+# Invalidate the instruction cache.
+#	A0: Should hold CHCTR
+#	D0: Should have been read from CHCTR
+#	D1: Will be clobbered
+#
+# On some cores it is necessary to disable the icache whilst we do this.
+#
+###############################################################################
+	.macro invalidate_icache,disable_irq
+
+#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
+	.if \disable_irq
+	# don't want an interrupt routine seeing a disabled cache
+	mov	epsw,d1
+	and	~EPSW_IE,epsw
+	or	EPSW_NMID,epsw
+	nop
+	nop
+	.endif
+
+	# disable the icache
+	and	~CHCTR_ICEN,d0
+	movhu	d0,(a0)
+
+	# and wait for it to calm down
+	setlb
+	movhu	(a0),d0
+	btst	CHCTR_ICBUSY,d0
+	lne
+
+	# invalidate
+	or	CHCTR_ICINV,d0
+	movhu	d0,(a0)
+
+	# wait for the cache to finish
+	setlb
+	movhu	(a0),d0
+	btst	CHCTR_ICBUSY,d0
+	lne
+
+	# and reenable it
+	or	CHCTR_ICEN,d0
+	movhu	d0,(a0)
+	movhu	(a0),d0
+
+	.if \disable_irq
+	LOCAL_IRQ_RESTORE(d1)
+	.endif
+
+#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+
+	# invalidate
+	or	CHCTR_ICINV,d0
+	movhu	d0,(a0)
+	movhu	(a0),d0
+
+#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+	.endm
+
+###############################################################################
+#
+# Invalidate the data cache.
+#	A0: Should hold CHCTR
+#	D0: Should have been read from CHCTR
+#	D1: Will be clobbered
+#
+# On some cores it is necessary to disable the dcache whilst we do this.
+#
+###############################################################################
+	.macro invalidate_dcache,disable_irq
+
+#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
+	.if \disable_irq
+	# don't want an interrupt routine seeing a disabled cache
+	mov	epsw,d1
+	and	~EPSW_IE,epsw
+	or	EPSW_NMID,epsw
+	nop
+	nop
+	.endif
+	
+	# disable the dcache
+	and	~CHCTR_DCEN,d0
+	movhu	d0,(a0)
+
+	# and wait for it to calm down
+	setlb
+	movhu	(a0),d0
+	btst	CHCTR_DCBUSY,d0
+	lne
+
+	# invalidate
+	or	CHCTR_DCINV,d0
+	movhu	d0,(a0)
+
+	# wait for the cache to finish
+	setlb
+	movhu	(a0),d0
+	btst	CHCTR_DCBUSY,d0
+	lne
+
+	# and reenable it
+	or	CHCTR_DCEN,d0
+	movhu	d0,(a0)
+	movhu	(a0),d0
+
+	.if \disable_irq
+	LOCAL_IRQ_RESTORE(d1)
+	.endif
+
+#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+
+	# invalidate
+	or	CHCTR_DCINV,d0
+	movhu	d0,(a0)
+	movhu	(a0),d0
+
+#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+	.endm
diff --git a/arch/mn10300/mm/dma-alloc.c b/arch/mn10300/mm/dma-alloc.c
new file mode 100644
index 0000000..e244ebe
--- /dev/null
+++ b/arch/mn10300/mm/dma-alloc.c
@@ -0,0 +1,76 @@
+/* MN10300 Dynamic DMA mapping support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * Derived from: arch/i386/kernel/pci-dma.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/gfp.h>
+#include <linux/export.h>
+#include <asm/io.h>
+
+static unsigned long pci_sram_allocated = 0xbc000000;
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+			 dma_addr_t *dma_handle, int gfp)
+{
+	unsigned long addr;
+	void *ret;
+
+	pr_debug("dma_alloc_coherent(%s,%zu,%x)\n",
+		 dev ? dev_name(dev) : "?", size, gfp);
+
+	if (0xbe000000 - pci_sram_allocated >= size) {
+		size = (size + 255) & ~255;
+		addr = pci_sram_allocated;
+		pci_sram_allocated += size;
+		ret = (void *) addr;
+		goto done;
+	}
+
+	/* ignore region specifiers */
+	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+	if (dev == NULL || dev->coherent_dma_mask < 0xffffffff)
+		gfp |= GFP_DMA;
+
+	addr = __get_free_pages(gfp, get_order(size));
+	if (!addr)
+		return NULL;
+
+	/* map the coherent memory through the uncached memory window */
+	ret = (void *) (addr | 0x20000000);
+
+	/* fill the memory with obvious rubbish */
+	memset((void *) addr, 0xfb, size);
+
+	/* write back and evict all cache lines covering this region */
+	mn10300_dcache_flush_inv_range2(virt_to_phys((void *) addr), PAGE_SIZE);
+
+done:
+	*dma_handle = virt_to_bus((void *) addr);
+	printk("dma_alloc_coherent() = %p [%x]\n", ret, *dma_handle);
+	return ret;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+		       dma_addr_t dma_handle)
+{
+	unsigned long addr = (unsigned long) vaddr & ~0x20000000;
+
+	if (addr >= 0x9c000000)
+		return;
+
+	free_pages(addr, get_order(size));
+}
+EXPORT_SYMBOL(dma_free_coherent);
diff --git a/arch/mn10300/mm/extable.c b/arch/mn10300/mm/extable.c
new file mode 100644
index 0000000..25e5485
--- /dev/null
+++ b/arch/mn10300/mm/extable.c
@@ -0,0 +1,26 @@
+/* MN10300 In-kernel exception handling
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+	fixup = search_exception_tables(regs->pc);
+	if (fixup) {
+		regs->pc = fixup->fixup;
+		return 1;
+	}
+
+	return 0;
+}
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c
new file mode 100644
index 0000000..4a1d181
--- /dev/null
+++ b/arch/mn10300/mm/fault.c
@@ -0,0 +1,414 @@
+/* MN10300 MMU Fault handler
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/vt_kern.h>		/* For unblank_screen() */
+#include <linux/uaccess.h>
+
+#include <asm/pgalloc.h>
+#include <asm/hardirq.h>
+#include <asm/cpu-regs.h>
+#include <asm/debugger.h>
+#include <asm/gdb-stub.h>
+
+/*
+ * Unlock any spinlocks which will prevent us from getting the
+ * message out
+ */
+void bust_spinlocks(int yes)
+{
+	if (yes) {
+		oops_in_progress = 1;
+	} else {
+		int loglevel_save = console_loglevel;
+#ifdef CONFIG_VT
+		unblank_screen();
+#endif
+		oops_in_progress = 0;
+		/*
+		 * OK, the message is on the console.  Now we call printk()
+		 * without oops_in_progress set so that printk will give klogd
+		 * a poke.  Hold onto your hats...
+		 */
+		console_loglevel = 15;	/* NMI oopser may have shut the console
+					 * up */
+		printk(" ");
+		console_loglevel = loglevel_save;
+	}
+}
+
+void do_BUG(const char *file, int line)
+{
+	bust_spinlocks(1);
+	printk(KERN_EMERG "------------[ cut here ]------------\n");
+	printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
+}
+
+#if 0
+static void print_pagetable_entries(pgd_t *pgdir, unsigned long address)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	pgd = pgdir + __pgd_offset(address);
+	printk(KERN_DEBUG "pgd entry %p: %016Lx\n",
+	       pgd, (long long) pgd_val(*pgd));
+
+	if (!pgd_present(*pgd)) {
+		printk(KERN_DEBUG "... pgd not present!\n");
+		return;
+	}
+	pmd = pmd_offset(pgd, address);
+	printk(KERN_DEBUG "pmd entry %p: %016Lx\n",
+	       pmd, (long long)pmd_val(*pmd));
+
+	if (!pmd_present(*pmd)) {
+		printk(KERN_DEBUG "... pmd not present!\n");
+		return;
+	}
+	pte = pte_offset(pmd, address);
+	printk(KERN_DEBUG "pte entry %p: %016Lx\n",
+	       pte, (long long) pte_val(*pte));
+
+	if (!pte_present(*pte))
+		printk(KERN_DEBUG "... pte not present!\n");
+}
+#endif
+
+/*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * fault_code:
+ * - LSW: either MMUFCR_IFC or MMUFCR_DFC as appropriate
+ * - MSW: 0 if data access, 1 if instruction access
+ * - bit 0: TLB miss flag
+ * - bit 1: initial write
+ * - bit 2: page invalid
+ * - bit 3: protection violation
+ * - bit 4: accessor (0=user 1=kernel)
+ * - bit 5: 0=read 1=write
+ * - bit 6-8: page protection spec
+ * - bit 9: illegal address
+ * - bit 16: 0=data 1=ins
+ *
+ */
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
+			      unsigned long address)
+{
+	struct vm_area_struct *vma;
+	struct task_struct *tsk;
+	struct mm_struct *mm;
+	unsigned long page;
+	siginfo_t info;
+	int fault;
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
+
+#ifdef CONFIG_GDBSTUB
+	/* handle GDB stub causing a fault */
+	if (gdbstub_busy) {
+		gdbstub_exception(regs, TBR & TBR_INT_CODE);
+		return;
+	}
+#endif
+
+#if 0
+	printk(KERN_DEBUG "--- do_page_fault(%p,%s:%04lx,%08lx)\n",
+	       regs,
+	       fault_code & 0x10000 ? "ins" : "data",
+	       fault_code & 0xffff, address);
+#endif
+
+	tsk = current;
+
+	/*
+	 * We fault-in kernel-space virtual memory on-demand. The
+	 * 'reference' page table is init_mm.pgd.
+	 *
+	 * NOTE! We MUST NOT take any locks for this case. We may
+	 * be in an interrupt or a critical region, and should
+	 * only copy the information from the master page table,
+	 * nothing more.
+	 *
+	 * This verifies that the fault happens in kernel space
+	 * and that the fault was a page not present (invalid) error
+	 */
+	if (address >= VMALLOC_START && address < VMALLOC_END &&
+	    (fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_SR &&
+	    (fault_code & MMUFCR_xFC_PGINVAL) == MMUFCR_xFC_PGINVAL
+	    )
+		goto vmalloc_fault;
+
+	mm = tsk->mm;
+	info.si_code = SEGV_MAPERR;
+
+	/*
+	 * If we're in an interrupt or have no user
+	 * context, we must not take the fault..
+	 */
+	if (faulthandler_disabled() || !mm)
+		goto no_context;
+
+	if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
+		flags |= FAULT_FLAG_USER;
+retry:
+	down_read(&mm->mmap_sem);
+
+	vma = find_vma(mm, address);
+	if (!vma)
+		goto bad_area;
+	if (vma->vm_start <= address)
+		goto good_area;
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+
+	if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) {
+		/* accessing the stack below the stack pointer is always a
+		 * bug */
+		if ((address & PAGE_MASK) + 2 * PAGE_SIZE < regs->sp) {
+#if 0
+			printk(KERN_WARNING
+			       "[%d] ### Access below stack @%lx (sp=%lx)\n",
+			       current->pid, address, regs->sp);
+			printk(KERN_WARNING
+			       "vma [%08x - %08x]\n",
+			       vma->vm_start, vma->vm_end);
+			show_registers(regs);
+			printk(KERN_WARNING
+			       "[%d] ### Code: [%08lx]"
+			       " %02x %02x %02x %02x %02x %02x %02x %02x\n",
+			       current->pid,
+			       regs->pc,
+			       ((u8 *) regs->pc)[0],
+			       ((u8 *) regs->pc)[1],
+			       ((u8 *) regs->pc)[2],
+			       ((u8 *) regs->pc)[3],
+			       ((u8 *) regs->pc)[4],
+			       ((u8 *) regs->pc)[5],
+			       ((u8 *) regs->pc)[6],
+			       ((u8 *) regs->pc)[7]
+			       );
+#endif
+			goto bad_area;
+		}
+	}
+
+	if (expand_stack(vma, address))
+		goto bad_area;
+
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+	info.si_code = SEGV_ACCERR;
+	switch (fault_code & (MMUFCR_xFC_PGINVAL|MMUFCR_xFC_TYPE)) {
+	default:	/* 3: write, present */
+	case MMUFCR_xFC_TYPE_WRITE:
+#ifdef TEST_VERIFY_AREA
+		if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_SR)
+			printk(KERN_DEBUG "WP fault at %08lx\n", regs->pc);
+#endif
+		/* write to absent page */
+	case MMUFCR_xFC_PGINVAL | MMUFCR_xFC_TYPE_WRITE:
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+		flags |= FAULT_FLAG_WRITE;
+		break;
+
+		/* read from protected page */
+	case MMUFCR_xFC_TYPE_READ:
+		goto bad_area;
+
+		/* read from absent page present */
+	case MMUFCR_xFC_PGINVAL | MMUFCR_xFC_TYPE_READ:
+		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			goto bad_area;
+		break;
+	}
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+	fault = handle_mm_fault(mm, vma, address, flags);
+
+	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+		return;
+
+	if (unlikely(fault & VM_FAULT_ERROR)) {
+		if (fault & VM_FAULT_OOM)
+			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGSEGV)
+			goto bad_area;
+		else if (fault & VM_FAULT_SIGBUS)
+			goto do_sigbus;
+		BUG();
+	}
+	if (flags & FAULT_FLAG_ALLOW_RETRY) {
+		if (fault & VM_FAULT_MAJOR)
+			current->maj_flt++;
+		else
+			current->min_flt++;
+		if (fault & VM_FAULT_RETRY) {
+			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+			 /* No need to up_read(&mm->mmap_sem) as we would
+			 * have already released it in __lock_page_or_retry
+			 * in mm/filemap.c.
+			 */
+
+			goto retry;
+		}
+	}
+
+	up_read(&mm->mmap_sem);
+	return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+	up_read(&mm->mmap_sem);
+
+	/* User mode accesses just cause a SIGSEGV */
+	if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) {
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		/* info.si_code has been set above */
+		info.si_addr = (void *)address;
+		force_sig_info(SIGSEGV, &info, tsk);
+		return;
+	}
+
+no_context:
+	/* Are we prepared to handle this kernel fault?  */
+	if (fixup_exception(regs))
+		return;
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+
+	bust_spinlocks(1);
+
+	if (address < PAGE_SIZE)
+		printk(KERN_ALERT
+		       "Unable to handle kernel NULL pointer dereference");
+	else
+		printk(KERN_ALERT
+		       "Unable to handle kernel paging request");
+	printk(" at virtual address %08lx\n", address);
+	printk(" printing pc:\n");
+	printk(KERN_ALERT "%08lx\n", regs->pc);
+
+	debugger_intercept(fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR,
+			   SIGSEGV, SEGV_ACCERR, regs);
+
+	page = PTBR;
+	page = ((unsigned long *) __va(page))[address >> 22];
+	printk(KERN_ALERT "*pde = %08lx\n", page);
+	if (page & 1) {
+		page &= PAGE_MASK;
+		address &= 0x003ff000;
+		page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
+		printk(KERN_ALERT "*pte = %08lx\n", page);
+	}
+
+	die("Oops", regs, fault_code);
+	do_exit(SIGKILL);
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+	up_read(&mm->mmap_sem);
+	if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) {
+		pagefault_out_of_memory();
+		return;
+	}
+	goto no_context;
+
+do_sigbus:
+	up_read(&mm->mmap_sem);
+
+	/*
+	 * Send a sigbus, regardless of whether we were in kernel
+	 * or user mode.
+	 */
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_ADRERR;
+	info.si_addr = (void *)address;
+	force_sig_info(SIGBUS, &info, tsk);
+
+	/* Kernel mode? Handle exceptions or die */
+	if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_SR)
+		goto no_context;
+	return;
+
+vmalloc_fault:
+	{
+		/*
+		 * Synchronize this task's top level page-table
+		 * with the 'reference' page table.
+		 *
+		 * Do _not_ use "tsk" here. We might be inside
+		 * an interrupt in the middle of a task switch..
+		 */
+		int index = pgd_index(address);
+		pgd_t *pgd, *pgd_k;
+		pud_t *pud, *pud_k;
+		pmd_t *pmd, *pmd_k;
+		pte_t *pte_k;
+
+		pgd_k = init_mm.pgd + index;
+
+		if (!pgd_present(*pgd_k))
+			goto no_context;
+
+		pud_k = pud_offset(pgd_k, address);
+		if (!pud_present(*pud_k))
+			goto no_context;
+
+		pmd_k = pmd_offset(pud_k, address);
+		if (!pmd_present(*pmd_k))
+			goto no_context;
+
+		pgd = (pgd_t *) PTBR + index;
+		pud = pud_offset(pgd, address);
+		pmd = pmd_offset(pud, address);
+		set_pmd(pmd, *pmd_k);
+
+		pte_k = pte_offset_kernel(pmd_k, address);
+		if (!pte_present(*pte_k))
+			goto no_context;
+		return;
+	}
+}
diff --git a/arch/mn10300/mm/init.c b/arch/mn10300/mm/init.c
new file mode 100644
index 0000000..97a1ec0
--- /dev/null
+++ b/arch/mn10300/mm/init.c
@@ -0,0 +1,136 @@
+/* MN10300 Memory management initialisation
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
+#include <linux/gfp.h>
+
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/dma.h>
+#include <asm/tlb.h>
+#include <asm/sections.h>
+
+unsigned long highstart_pfn, highend_pfn;
+
+#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
+static struct vm_struct user_iomap_vm;
+#endif
+
+/*
+ * set up paging
+ */
+void __init paging_init(void)
+{
+	unsigned long zones_size[MAX_NR_ZONES] = {0,};
+	pte_t *ppte;
+	int loop;
+
+	/* main kernel space -> RAM mapping is handled as 1:1 transparent by
+	 * the MMU */
+	memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
+	memset(kernel_vmalloc_ptes, 0, sizeof(kernel_vmalloc_ptes));
+
+	/* load the VMALLOC area PTE table addresses into the kernel PGD */
+	ppte = kernel_vmalloc_ptes;
+	for (loop = VMALLOC_START / (PAGE_SIZE * PTRS_PER_PTE);
+	     loop < VMALLOC_END / (PAGE_SIZE * PTRS_PER_PTE);
+	     loop++
+	     ) {
+		set_pgd(swapper_pg_dir + loop, __pgd(__pa(ppte) | _PAGE_TABLE));
+		ppte += PAGE_SIZE / sizeof(pte_t);
+	}
+
+	/* declare the sizes of the RAM zones (only use the normal zone) */
+	zones_size[ZONE_NORMAL] =
+		contig_page_data.bdata->node_low_pfn -
+		contig_page_data.bdata->node_min_pfn;
+
+	/* pass the memory from the bootmem allocator to the main allocator */
+	free_area_init(zones_size);
+
+#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
+	/* The Atomic Operation Unit registers need to be mapped to userspace
+	 * for all processes.  The following uses vm_area_register_early() to
+	 * reserve the first page of the vmalloc area and sets the pte for that
+	 * page.
+	 *
+	 * glibc hardcodes this virtual mapping, so we're pretty much stuck with
+	 * it from now on.
+	 */
+	user_iomap_vm.flags = VM_USERMAP;
+	user_iomap_vm.size = 1 << PAGE_SHIFT;
+	vm_area_register_early(&user_iomap_vm, PAGE_SIZE);
+	ppte = kernel_vmalloc_ptes;
+	set_pte(ppte, pfn_pte(USER_ATOMIC_OPS_PAGE_ADDR >> PAGE_SHIFT,
+			      PAGE_USERIO));
+#endif
+
+	local_flush_tlb_all();
+}
+
+/*
+ * transfer all the memory from the bootmem allocator to the runtime allocator
+ */
+void __init mem_init(void)
+{
+	BUG_ON(!mem_map);
+
+#define START_PFN	(contig_page_data.bdata->node_min_pfn)
+#define MAX_LOW_PFN	(contig_page_data.bdata->node_low_pfn)
+
+	max_mapnr = MAX_LOW_PFN - START_PFN;
+	high_memory = (void *) __va(MAX_LOW_PFN * PAGE_SIZE);
+
+	/* clear the zero-page */
+	memset(empty_zero_page, 0, PAGE_SIZE);
+
+	/* this will put all low memory onto the freelists */
+	free_all_bootmem();
+
+	mem_init_print_info(NULL);
+}
+
+/*
+ * recycle memory containing stuff only required for initialisation
+ */
+void free_initmem(void)
+{
+	free_initmem_default(POISON_FREE_INITMEM);
+}
+
+/*
+ * dispose of the memory on which the initial ramdisk resided
+ */
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM,
+			   "initrd");
+}
+#endif
diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c
new file mode 100644
index 0000000..b9920b1
--- /dev/null
+++ b/arch/mn10300/mm/misalignment.c
@@ -0,0 +1,966 @@
+/* MN10300 Misalignment fixup handler
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <linux/atomic.h>
+#include <asm/smp.h>
+#include <asm/pgalloc.h>
+#include <asm/cpu-regs.h>
+#include <asm/busctl-regs.h>
+#include <asm/fpu.h>
+#include <asm/gdb-stub.h>
+#include <asm/asm-offsets.h>
+
+#if 0
+#define kdebug(FMT, ...) printk(KERN_DEBUG "MISALIGN: "FMT"\n", ##__VA_ARGS__)
+#else
+#define kdebug(FMT, ...) do {} while (0)
+#endif
+
+static int misalignment_addr(unsigned long *registers, unsigned long sp,
+			     unsigned params, unsigned opcode,
+			     unsigned long disp,
+			     void **_address, unsigned long **_postinc,
+			     unsigned long *_inc);
+
+static int misalignment_reg(unsigned long *registers, unsigned params,
+			    unsigned opcode, unsigned long disp,
+			    unsigned long **_register);
+
+static void misalignment_MOV_Lcc(struct pt_regs *regs, uint32_t opcode);
+
+static const unsigned Dreg_index[] = {
+	REG_D0 >> 2, REG_D1 >> 2, REG_D2 >> 2, REG_D3 >> 2
+};
+
+static const unsigned Areg_index[] = {
+	REG_A0 >> 2, REG_A1 >> 2, REG_A2 >> 2, REG_A3 >> 2
+};
+
+static const unsigned Rreg_index[] = {
+	REG_E0 >> 2, REG_E1 >> 2, REG_E2 >> 2, REG_E3 >> 2,
+	REG_E4 >> 2, REG_E5 >> 2, REG_E6 >> 2, REG_E7 >> 2,
+	REG_A0 >> 2, REG_A1 >> 2, REG_A2 >> 2, REG_A3 >> 2,
+	REG_D0 >> 2, REG_D1 >> 2, REG_D2 >> 2, REG_D3 >> 2
+};
+
+enum format_id {
+	FMT_S0,
+	FMT_S1,
+	FMT_S2,
+	FMT_S4,
+	FMT_D0,
+	FMT_D1,
+	FMT_D2,
+	FMT_D4,
+	FMT_D6,
+	FMT_D7,
+	FMT_D8,
+	FMT_D9,
+	FMT_D10,
+};
+
+static const struct {
+	u_int8_t opsz, dispsz;
+} format_tbl[16] = {
+	[FMT_S0]	= { 8,	0	},
+	[FMT_S1]	= { 8,	8	},
+	[FMT_S2]	= { 8,	16	},
+	[FMT_S4]	= { 8,	32	},
+	[FMT_D0]	= { 16,	0	},
+	[FMT_D1]	= { 16,	8	},
+	[FMT_D2]	= { 16,	16	},
+	[FMT_D4]	= { 16,	32	},
+	[FMT_D6]	= { 24,	0	},
+	[FMT_D7]	= { 24,	8	},
+	[FMT_D8]	= { 24,	24	},
+	[FMT_D9]	= { 24,	32	},
+	[FMT_D10]	= { 32,	0	},
+};
+
+enum value_id {
+	DM0,		/* data reg in opcode in bits 0-1 */
+	DM1,		/* data reg in opcode in bits 2-3 */
+	DM2,		/* data reg in opcode in bits 4-5 */
+	AM0,		/* addr reg in opcode in bits 0-1 */
+	AM1,		/* addr reg in opcode in bits 2-3 */
+	AM2,		/* addr reg in opcode in bits 4-5 */
+	RM0,		/* reg in opcode in bits 0-3 */
+	RM1,		/* reg in opcode in bits 2-5 */
+	RM2,		/* reg in opcode in bits 4-7 */
+	RM4,		/* reg in opcode in bits 8-11 */
+	RM6,		/* reg in opcode in bits 12-15 */
+
+	RD0,		/* reg in displacement in bits 0-3 */
+	RD2,		/* reg in displacement in bits 4-7 */
+
+	SP,		/* stack pointer */
+
+	SD8,		/* 8-bit signed displacement */
+	SD16,		/* 16-bit signed displacement */
+	SD24,		/* 24-bit signed displacement */
+	SIMM4_2,	/* 4-bit signed displacement in opcode bits 4-7 */
+	SIMM8,		/* 8-bit signed immediate */
+	IMM8,		/* 8-bit unsigned immediate */
+	IMM16,		/* 16-bit unsigned immediate */
+	IMM24,		/* 24-bit unsigned immediate */
+	IMM32,		/* 32-bit unsigned immediate */
+	IMM32_HIGH8,	/* 32-bit unsigned immediate, LSB in opcode */
+
+	IMM32_MEM,	/* 32-bit unsigned displacement */
+	IMM32_HIGH8_MEM, /* 32-bit unsigned displacement, LSB in opcode */
+
+	DN0	= DM0,
+	DN1	= DM1,
+	DN2	= DM2,
+	AN0	= AM0,
+	AN1	= AM1,
+	AN2	= AM2,
+	RN0	= RM0,
+	RN1	= RM1,
+	RN2	= RM2,
+	RN4	= RM4,
+	RN6	= RM6,
+	DI	= DM1,
+	RI	= RM2,
+
+};
+
+struct mn10300_opcode {
+	const char	name[8];
+	u_int32_t	opcode;
+	u_int32_t	opmask;
+	unsigned	exclusion;
+
+	enum format_id	format;
+
+	unsigned	cpu_mask;
+#define AM33	330
+
+	unsigned	params[2];
+#define MEM(ADDR)		(0x80000000 | (ADDR))
+#define MEM2(ADDR1, ADDR2)	(0x80000000 | (ADDR1) << 8 | (ADDR2))
+#define MEMINC(ADDR)		(0x81000000 | (ADDR))
+#define MEMINC2(ADDR, INC)	(0x81000000 | (ADDR) << 8 | (INC))
+};
+
+/* LIBOPCODES EXCERPT
+   Assemble Matsushita MN10300 instructions.
+   Copyright 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public Licence as published by
+   the Free Software Foundation; either version 2 of the Licence, or
+   (at your option) any later version.
+
+   This program 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 Licence for more details.
+
+   You should have received a copy of the GNU General Public Licence
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+static const struct mn10300_opcode mn10300_opcodes[] = {
+{ "mov",	0x4200,	     0xf300,	  0,    FMT_S1, 0,	{DM1, MEM2(IMM8, SP)}},
+{ "mov",	0x4300,	     0xf300,	  0,    FMT_S1, 0,	{AM1, MEM2(IMM8, SP)}},
+{ "mov",	0x5800,	     0xfc00,	  0,    FMT_S1, 0,	{MEM2(IMM8, SP), DN0}},
+{ "mov",	0x5c00,	     0xfc00,	  0,    FMT_S1, 0,	{MEM2(IMM8, SP), AN0}},
+{ "mov",	0x60,	     0xf0,	  0,    FMT_S0, 0,	{DM1, MEM(AN0)}},
+{ "mov",	0x70,	     0xf0,	  0,    FMT_S0, 0,	{MEM(AM0), DN1}},
+{ "mov",	0xf000,	     0xfff0,	  0,    FMT_D0, 0,	{MEM(AM0), AN1}},
+{ "mov",	0xf010,	     0xfff0,	  0,    FMT_D0, 0,	{AM1, MEM(AN0)}},
+{ "mov",	0xf300,	     0xffc0,	  0,    FMT_D0, 0,	{MEM2(DI, AM0), DN2}},
+{ "mov",	0xf340,	     0xffc0,	  0,    FMT_D0, 0,	{DM2, MEM2(DI, AN0)}},
+{ "mov",	0xf380,	     0xffc0,	  0,    FMT_D0, 0,	{MEM2(DI, AM0), AN2}},
+{ "mov",	0xf3c0,	     0xffc0,	  0,    FMT_D0, 0,	{AM2, MEM2(DI, AN0)}},
+{ "mov",	0xf80000,    0xfff000,    0,    FMT_D1, 0,	{MEM2(SD8, AM0), DN1}},
+{ "mov",	0xf81000,    0xfff000,    0,    FMT_D1, 0,	{DM1, MEM2(SD8, AN0)}},
+{ "mov",	0xf82000,    0xfff000,    0,    FMT_D1, 0,	{MEM2(SD8,AM0), AN1}},
+{ "mov",	0xf83000,    0xfff000,    0,    FMT_D1, 0,	{AM1, MEM2(SD8, AN0)}},
+{ "mov",	0xf90a00,    0xffff00,    0,    FMT_D6, AM33,	{MEM(RM0), RN2}},
+{ "mov",	0xf91a00,    0xffff00,    0,    FMT_D6, AM33,	{RM2, MEM(RN0)}},
+{ "mov",	0xf96a00,    0xffff00,    0x12, FMT_D6, AM33,	{MEMINC(RM0), RN2}},
+{ "mov",	0xf97a00,    0xffff00,    0,	FMT_D6, AM33,	{RM2, MEMINC(RN0)}},
+{ "mov",	0xfa000000,  0xfff00000,  0,    FMT_D2, 0,	{MEM2(SD16, AM0), DN1}},
+{ "mov",	0xfa100000,  0xfff00000,  0,    FMT_D2, 0,	{DM1, MEM2(SD16, AN0)}},
+{ "mov",	0xfa200000,  0xfff00000,  0,    FMT_D2, 0,	{MEM2(SD16, AM0), AN1}},
+{ "mov",	0xfa300000,  0xfff00000,  0,    FMT_D2, 0,	{AM1, MEM2(SD16, AN0)}},
+{ "mov",	0xfa900000,  0xfff30000,  0,    FMT_D2, 0,	{AM1, MEM2(IMM16, SP)}},
+{ "mov",	0xfa910000,  0xfff30000,  0,    FMT_D2, 0,	{DM1, MEM2(IMM16, SP)}},
+{ "mov",	0xfab00000,  0xfffc0000,  0,    FMT_D2, 0,	{MEM2(IMM16, SP), AN0}},
+{ "mov",	0xfab40000,  0xfffc0000,  0,    FMT_D2, 0,	{MEM2(IMM16, SP), DN0}},
+{ "mov",	0xfb0a0000,  0xffff0000,  0,    FMT_D7, AM33,	{MEM2(SD8, RM0), RN2}},
+{ "mov",	0xfb1a0000,  0xffff0000,  0,    FMT_D7, AM33,	{RM2, MEM2(SD8, RN0)}},
+{ "mov",	0xfb6a0000,  0xffff0000,  0x22, FMT_D7, AM33,	{MEMINC2 (RM0, SIMM8), RN2}},
+{ "mov",	0xfb7a0000,  0xffff0000,  0,	FMT_D7, AM33,	{RM2, MEMINC2 (RN0, SIMM8)}},
+{ "mov",	0xfb8a0000,  0xffff0f00,  0,    FMT_D7, AM33,	{MEM2(IMM8, SP), RN2}},
+{ "mov",	0xfb8e0000,  0xffff000f,  0,    FMT_D7, AM33,	{MEM2(RI, RM0), RD2}},
+{ "mov",	0xfb9a0000,  0xffff0f00,  0,    FMT_D7, AM33,	{RM2, MEM2(IMM8, SP)}},
+{ "mov",	0xfb9e0000,  0xffff000f,  0,    FMT_D7, AM33,	{RD2, MEM2(RI, RN0)}},
+{ "mov",	0xfc000000,  0xfff00000,  0,    FMT_D4, 0,	{MEM2(IMM32,AM0), DN1}},
+{ "mov",	0xfc100000,  0xfff00000,  0,    FMT_D4, 0,	{DM1, MEM2(IMM32,AN0)}},
+{ "mov",	0xfc200000,  0xfff00000,  0,    FMT_D4, 0,	{MEM2(IMM32,AM0), AN1}},
+{ "mov",	0xfc300000,  0xfff00000,  0,    FMT_D4, 0,	{AM1, MEM2(IMM32,AN0)}},
+{ "mov",	0xfc800000,  0xfff30000,  0,    FMT_D4, 0,	{AM1, MEM(IMM32_MEM)}},
+{ "mov",	0xfc810000,  0xfff30000,  0,    FMT_D4, 0,	{DM1, MEM(IMM32_MEM)}},
+{ "mov",	0xfc900000,  0xfff30000,  0,    FMT_D4, 0,	{AM1, MEM2(IMM32, SP)}},
+{ "mov",	0xfc910000,  0xfff30000,  0,    FMT_D4, 0,	{DM1, MEM2(IMM32, SP)}},
+{ "mov",	0xfca00000,  0xfffc0000,  0,    FMT_D4, 0,	{MEM(IMM32_MEM), AN0}},
+{ "mov",	0xfca40000,  0xfffc0000,  0,    FMT_D4, 0,	{MEM(IMM32_MEM), DN0}},
+{ "mov",	0xfcb00000,  0xfffc0000,  0,    FMT_D4, 0,	{MEM2(IMM32, SP), AN0}},
+{ "mov",	0xfcb40000,  0xfffc0000,  0,    FMT_D4, 0,	{MEM2(IMM32, SP), DN0}},
+{ "mov",	0xfd0a0000,  0xffff0000,  0,    FMT_D8, AM33,	{MEM2(SD24, RM0), RN2}},
+{ "mov",	0xfd1a0000,  0xffff0000,  0,    FMT_D8, AM33,	{RM2, MEM2(SD24, RN0)}},
+{ "mov",	0xfd6a0000,  0xffff0000,  0x22, FMT_D8, AM33,	{MEMINC2 (RM0, IMM24), RN2}},
+{ "mov",	0xfd7a0000,  0xffff0000,  0,	FMT_D8, AM33,	{RM2, MEMINC2 (RN0, IMM24)}},
+{ "mov",	0xfd8a0000,  0xffff0f00,  0,    FMT_D8, AM33,	{MEM2(IMM24, SP), RN2}},
+{ "mov",	0xfd9a0000,  0xffff0f00,  0,    FMT_D8, AM33,	{RM2, MEM2(IMM24, SP)}},
+{ "mov",	0xfe0a0000,  0xffff0000,  0,    FMT_D9, AM33,	{MEM2(IMM32_HIGH8,RM0), RN2}},
+{ "mov",	0xfe0a0000,  0xffff0000,  0,    FMT_D9, AM33,	{MEM2(IMM32_HIGH8,RM0), RN2}},
+{ "mov",	0xfe0e0000,  0xffff0f00,  0,    FMT_D9, AM33,	{MEM(IMM32_HIGH8_MEM), RN2}},
+{ "mov",	0xfe1a0000,  0xffff0000,  0,    FMT_D9, AM33,	{RM2, MEM2(IMM32_HIGH8, RN0)}},
+{ "mov",	0xfe1a0000,  0xffff0000,  0,    FMT_D9, AM33,	{RM2, MEM2(IMM32_HIGH8, RN0)}},
+{ "mov",	0xfe1e0000,  0xffff0f00,  0,    FMT_D9, AM33,	{RM2, MEM(IMM32_HIGH8_MEM)}},
+{ "mov",	0xfe6a0000,  0xffff0000,  0x22, FMT_D9, AM33,	{MEMINC2 (RM0, IMM32_HIGH8), RN2}},
+{ "mov",	0xfe7a0000,  0xffff0000,  0,	FMT_D9, AM33,	{RN2, MEMINC2 (RM0, IMM32_HIGH8)}},
+{ "mov",	0xfe8a0000,  0xffff0f00,  0,    FMT_D9, AM33,	{MEM2(IMM32_HIGH8, SP), RN2}},
+{ "mov",	0xfe9a0000,  0xffff0f00,  0,    FMT_D9, AM33,	{RM2, MEM2(IMM32_HIGH8, SP)}},
+
+{ "movhu",	0xf060,	     0xfff0,	  0,    FMT_D0, 0,	{MEM(AM0), DN1}},
+{ "movhu",	0xf070,	     0xfff0,	  0,    FMT_D0, 0,	{DM1, MEM(AN0)}},
+{ "movhu",	0xf480,	     0xffc0,	  0,    FMT_D0, 0,	{MEM2(DI, AM0), DN2}},
+{ "movhu",	0xf4c0,	     0xffc0,	  0,    FMT_D0, 0,	{DM2, MEM2(DI, AN0)}},
+{ "movhu",	0xf86000,    0xfff000,    0,    FMT_D1, 0,	{MEM2(SD8, AM0), DN1}},
+{ "movhu",	0xf87000,    0xfff000,    0,    FMT_D1, 0,	{DM1, MEM2(SD8, AN0)}},
+{ "movhu",	0xf89300,    0xfff300,    0,    FMT_D1, 0,	{DM1, MEM2(IMM8, SP)}},
+{ "movhu",	0xf8bc00,    0xfffc00,    0,    FMT_D1, 0,	{MEM2(IMM8, SP), DN0}},
+{ "movhu",	0xf94a00,    0xffff00,    0,    FMT_D6, AM33,	{MEM(RM0), RN2}},
+{ "movhu",	0xf95a00,    0xffff00,    0,    FMT_D6, AM33,	{RM2, MEM(RN0)}},
+{ "movhu",	0xf9ea00,    0xffff00,    0x12, FMT_D6, AM33,	{MEMINC(RM0), RN2}},
+{ "movhu",	0xf9fa00,    0xffff00,    0,	FMT_D6, AM33,	{RM2, MEMINC(RN0)}},
+{ "movhu",	0xfa600000,  0xfff00000,  0,    FMT_D2, 0,	{MEM2(SD16, AM0), DN1}},
+{ "movhu",	0xfa700000,  0xfff00000,  0,    FMT_D2, 0,	{DM1, MEM2(SD16, AN0)}},
+{ "movhu",	0xfa930000,  0xfff30000,  0,    FMT_D2, 0,	{DM1, MEM2(IMM16, SP)}},
+{ "movhu",	0xfabc0000,  0xfffc0000,  0,    FMT_D2, 0,	{MEM2(IMM16, SP), DN0}},
+{ "movhu",	0xfb4a0000,  0xffff0000,  0,    FMT_D7, AM33,	{MEM2(SD8, RM0), RN2}},
+{ "movhu",	0xfb5a0000,  0xffff0000,  0,    FMT_D7, AM33,	{RM2, MEM2(SD8, RN0)}},
+{ "movhu",	0xfbca0000,  0xffff0f00,  0,    FMT_D7, AM33,	{MEM2(IMM8, SP), RN2}},
+{ "movhu",	0xfbce0000,  0xffff000f,  0,    FMT_D7, AM33,	{MEM2(RI, RM0), RD2}},
+{ "movhu",	0xfbda0000,  0xffff0f00,  0,    FMT_D7, AM33,	{RM2, MEM2(IMM8, SP)}},
+{ "movhu",	0xfbde0000,  0xffff000f,  0,    FMT_D7, AM33,	{RD2, MEM2(RI, RN0)}},
+{ "movhu",	0xfbea0000,  0xffff0000,  0x22, FMT_D7, AM33,	{MEMINC2 (RM0, SIMM8), RN2}},
+{ "movhu",	0xfbfa0000,  0xffff0000,  0,	FMT_D7, AM33,	{RM2, MEMINC2 (RN0, SIMM8)}},
+{ "movhu",	0xfc600000,  0xfff00000,  0,    FMT_D4, 0,	{MEM2(IMM32,AM0), DN1}},
+{ "movhu",	0xfc700000,  0xfff00000,  0,    FMT_D4, 0,	{DM1, MEM2(IMM32,AN0)}},
+{ "movhu",	0xfc830000,  0xfff30000,  0,    FMT_D4, 0,	{DM1, MEM(IMM32_MEM)}},
+{ "movhu",	0xfc930000,  0xfff30000,  0,    FMT_D4, 0,	{DM1, MEM2(IMM32, SP)}},
+{ "movhu",	0xfcac0000,  0xfffc0000,  0,    FMT_D4, 0,	{MEM(IMM32_MEM), DN0}},
+{ "movhu",	0xfcbc0000,  0xfffc0000,  0,    FMT_D4, 0,	{MEM2(IMM32, SP), DN0}},
+{ "movhu",	0xfd4a0000,  0xffff0000,  0,    FMT_D8, AM33,	{MEM2(SD24, RM0), RN2}},
+{ "movhu",	0xfd5a0000,  0xffff0000,  0,    FMT_D8, AM33,	{RM2, MEM2(SD24, RN0)}},
+{ "movhu",	0xfdca0000,  0xffff0f00,  0,    FMT_D8, AM33,	{MEM2(IMM24, SP), RN2}},
+{ "movhu",	0xfdda0000,  0xffff0f00,  0,    FMT_D8, AM33,	{RM2, MEM2(IMM24, SP)}},
+{ "movhu",	0xfdea0000,  0xffff0000,  0x22, FMT_D8, AM33,	{MEMINC2 (RM0, IMM24), RN2}},
+{ "movhu",	0xfdfa0000,  0xffff0000,  0,	FMT_D8, AM33,	{RM2, MEMINC2 (RN0, IMM24)}},
+{ "movhu",	0xfe4a0000,  0xffff0000,  0,    FMT_D9, AM33,	{MEM2(IMM32_HIGH8,RM0), RN2}},
+{ "movhu",	0xfe4e0000,  0xffff0f00,  0,    FMT_D9, AM33,	{MEM(IMM32_HIGH8_MEM), RN2}},
+{ "movhu",	0xfe5a0000,  0xffff0000,  0,    FMT_D9, AM33,	{RM2, MEM2(IMM32_HIGH8, RN0)}},
+{ "movhu",	0xfe5e0000,  0xffff0f00,  0,    FMT_D9, AM33,	{RM2, MEM(IMM32_HIGH8_MEM)}},
+{ "movhu",	0xfeca0000,  0xffff0f00,  0,    FMT_D9, AM33,	{MEM2(IMM32_HIGH8, SP), RN2}},
+{ "movhu",	0xfeda0000,  0xffff0f00,  0,    FMT_D9, AM33,	{RM2, MEM2(IMM32_HIGH8, SP)}},
+{ "movhu",	0xfeea0000,  0xffff0000,  0x22, FMT_D9, AM33,	{MEMINC2 (RM0, IMM32_HIGH8), RN2}},
+{ "movhu",	0xfefa0000,  0xffff0000,  0,	FMT_D9, AM33,	{RN2, MEMINC2 (RM0, IMM32_HIGH8)}},
+
+{ "mov_llt",	0xf7e00000,  0xffff000f,  0x22, FMT_D10, AM33,	 {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lgt",	0xf7e00001,  0xffff000f,  0x22, FMT_D10, AM33,	 {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lge",	0xf7e00002,  0xffff000f,  0x22, FMT_D10, AM33,	 {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lle",	0xf7e00003,  0xffff000f,  0x22, FMT_D10, AM33,	 {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lcs",	0xf7e00004,  0xffff000f,  0x22, FMT_D10, AM33,	 {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lhi",	0xf7e00005,  0xffff000f,  0x22, FMT_D10, AM33,	 {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lcc",	0xf7e00006,  0xffff000f,  0x22, FMT_D10, AM33,	 {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lls",	0xf7e00007,  0xffff000f,  0x22, FMT_D10, AM33,	 {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_leq",	0xf7e00008,  0xffff000f,  0x22, FMT_D10, AM33,	 {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lne",	0xf7e00009,  0xffff000f,  0x22, FMT_D10, AM33,	 {MEMINC2 (RN4,SIMM4_2), RM6}},
+{ "mov_lra",	0xf7e0000a,  0xffff000f,  0x22, FMT_D10, AM33,	 {MEMINC2 (RN4,SIMM4_2), RM6}},
+
+{ "", 0, 0, 0, 0, 0, {0}},
+};
+
+/*
+ * fix up misalignment problems where possible
+ */
+asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code)
+{
+	const struct exception_table_entry *fixup;
+	const struct mn10300_opcode *pop;
+	unsigned long *registers = (unsigned long *) regs;
+	unsigned long data, *store, *postinc, disp, inc, sp;
+	mm_segment_t seg;
+	siginfo_t info;
+	uint32_t opcode, noc, xo, xm;
+	uint8_t *pc, byte, datasz;
+	void *address;
+	unsigned tmp, npop, dispsz, loop;
+
+	/* we don't fix up userspace misalignment faults */
+	if (user_mode(regs))
+		goto bus_error;
+
+	sp = (unsigned long) regs + sizeof(*regs);
+
+	kdebug("==>misalignment({pc=%lx,sp=%lx})", regs->pc, sp);
+
+	if (regs->epsw & EPSW_IE)
+		asm volatile("or %0,epsw" : : "i"(EPSW_IE));
+
+	seg = get_fs();
+	set_fs(KERNEL_DS);
+
+	fixup = search_exception_tables(regs->pc);
+
+	/* first thing to do is to match the opcode */
+	pc = (u_int8_t *) regs->pc;
+
+	if (__get_user(byte, pc) != 0)
+		goto fetch_error;
+	opcode = byte;
+	noc = 8;
+
+	for (pop = mn10300_opcodes; pop->name[0]; pop++) {
+		npop = ilog2(pop->opcode | pop->opmask);
+		if (npop <= 0 || npop > 31)
+			continue;
+		npop = (npop + 8) & ~7;
+
+	got_more_bits:
+		if (npop == noc) {
+			if ((opcode & pop->opmask) == pop->opcode)
+				goto found_opcode;
+		} else if (npop > noc) {
+			xo = pop->opcode >> (npop - noc);
+			xm = pop->opmask >> (npop - noc);
+
+			if ((opcode & xm) != xo)
+				continue;
+
+			/* we've got a partial match (an exact match on the
+			 * first N bytes), so we need to get some more data */
+			pc++;
+			if (__get_user(byte, pc) != 0)
+				goto fetch_error;
+			opcode = opcode << 8 | byte;
+			noc += 8;
+			goto got_more_bits;
+		} else {
+			/* there's already been a partial match as long as the
+			 * complete match we're now considering, so this one
+			 * should't match */
+			continue;
+		}
+	}
+
+	/* didn't manage to find a fixup */
+	printk(KERN_CRIT "MISALIGN: %lx: unsupported instruction %x\n",
+	       regs->pc, opcode);
+
+failed:
+	set_fs(seg);
+	if (die_if_no_fixup("misalignment error", regs, code))
+		return;
+
+bus_error:
+	info.si_signo	= SIGBUS;
+	info.si_errno	= 0;
+	info.si_code	= BUS_ADRALN;
+	info.si_addr	= (void *) regs->pc;
+	force_sig_info(SIGBUS, &info, current);
+	return;
+
+	/* error reading opcodes */
+fetch_error:
+	printk(KERN_CRIT
+	       "MISALIGN: %p: fault whilst reading instruction data\n",
+	       pc);
+	goto failed;
+
+bad_addr_mode:
+	printk(KERN_CRIT
+	       "MISALIGN: %lx: unsupported addressing mode %x\n",
+	       regs->pc, opcode);
+	goto failed;
+
+bad_reg_mode:
+	printk(KERN_CRIT
+	       "MISALIGN: %lx: unsupported register mode %x\n",
+	       regs->pc, opcode);
+	goto failed;
+
+unsupported_instruction:
+	printk(KERN_CRIT
+	       "MISALIGN: %lx: unsupported instruction %x (%s)\n",
+	       regs->pc, opcode, pop->name);
+	goto failed;
+
+transfer_failed:
+	set_fs(seg);
+	if (fixup) {
+		regs->pc = fixup->fixup;
+		return;
+	}
+	if (die_if_no_fixup("misalignment fixup", regs, code))
+		return;
+
+	info.si_signo	= SIGSEGV;
+	info.si_errno	= 0;
+	info.si_code	= 0;
+	info.si_addr	= (void *) regs->pc;
+	force_sig_info(SIGSEGV, &info, current);
+	return;
+
+	/* we matched the opcode */
+found_opcode:
+	kdebug("%lx: %x==%x { %x, %x }",
+	       regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]);
+
+	tmp = format_tbl[pop->format].opsz;
+	BUG_ON(tmp > noc); /* match was less complete than it ought to have been */
+
+	if (tmp < noc) {
+		tmp = noc - tmp;
+		opcode >>= tmp;
+		pc -= tmp >> 3;
+	}
+
+	/* grab the extra displacement (note it's LSB first) */
+	disp = 0;
+	dispsz = format_tbl[pop->format].dispsz;
+	for (loop = 0; loop < dispsz; loop += 8) {
+		pc++;
+		if (__get_user(byte, pc) != 0)
+			goto fetch_error;
+		disp |= byte << loop;
+		kdebug("{%p} disp[%02x]=%02x", pc, loop, byte);
+	}
+
+	kdebug("disp=%lx", disp);
+
+	set_fs(KERNEL_XDS);
+	if (fixup)
+		set_fs(seg);
+
+	tmp = (pop->params[0] ^ pop->params[1]) & 0x80000000;
+	if (!tmp) {
+		printk(KERN_CRIT
+		       "MISALIGN: %lx: insn not move to/from memory %x\n",
+		       regs->pc, opcode);
+		goto failed;
+	}
+
+	/* determine the data transfer size of the move */
+	if (pop->name[3] == 0 || /* "mov" */
+	    pop->name[4] == 'l') /* mov_lcc */
+		inc = datasz = 4;
+	else if (pop->name[3] == 'h') /* movhu */
+		inc = datasz = 2;
+	else
+		goto unsupported_instruction;
+
+	if (pop->params[0] & 0x80000000) {
+		/* move memory to register */
+		if (!misalignment_addr(registers, sp,
+				       pop->params[0], opcode, disp,
+				       &address, &postinc, &inc))
+			goto bad_addr_mode;
+
+		if (!misalignment_reg(registers, pop->params[1], opcode, disp,
+				      &store))
+			goto bad_reg_mode;
+
+		kdebug("mov%u (%p),DARn", datasz, address);
+		if (copy_from_user(&data, (void *) address, datasz) != 0)
+			goto transfer_failed;
+		if (pop->params[0] & 0x1000000) {
+			kdebug("inc=%lx", inc);
+			*postinc += inc;
+		}
+
+		*store = data;
+		kdebug("loaded %lx", data);
+	} else {
+		/* move register to memory */
+		if (!misalignment_reg(registers, pop->params[0], opcode, disp,
+				      &store))
+			goto bad_reg_mode;
+
+		if (!misalignment_addr(registers, sp,
+				       pop->params[1], opcode, disp,
+				       &address, &postinc, &inc))
+			goto bad_addr_mode;
+
+		data = *store;
+
+		kdebug("mov%u %lx,(%p)", datasz, data, address);
+		if (copy_to_user((void *) address, &data, datasz) != 0)
+			goto transfer_failed;
+		if (pop->params[1] & 0x1000000)
+			*postinc += inc;
+	}
+
+	tmp = format_tbl[pop->format].opsz + format_tbl[pop->format].dispsz;
+	regs->pc += tmp >> 3;
+
+	/* handle MOV_Lcc, which are currently the only FMT_D10 insns that
+	 * access memory */
+	if (pop->format == FMT_D10)
+		misalignment_MOV_Lcc(regs, opcode);
+
+	set_fs(seg);
+}
+
+/*
+ * determine the address that was being accessed
+ */
+static int misalignment_addr(unsigned long *registers, unsigned long sp,
+			     unsigned params, unsigned opcode,
+			     unsigned long disp,
+			     void **_address, unsigned long **_postinc,
+			     unsigned long *_inc)
+{
+	unsigned long *postinc = NULL, address = 0, tmp;
+
+	if (!(params & 0x1000000)) {
+		kdebug("noinc");
+		*_inc = 0;
+		_inc = NULL;
+	}
+
+	params &= 0x00ffffff;
+
+	do {
+		switch (params & 0xff) {
+		case DM0:
+			postinc = &registers[Dreg_index[opcode & 0x03]];
+			address += *postinc;
+			break;
+		case DM1:
+			postinc = &registers[Dreg_index[opcode >> 2 & 0x03]];
+			address += *postinc;
+			break;
+		case DM2:
+			postinc = &registers[Dreg_index[opcode >> 4 & 0x03]];
+			address += *postinc;
+			break;
+		case AM0:
+			postinc = &registers[Areg_index[opcode & 0x03]];
+			address += *postinc;
+			break;
+		case AM1:
+			postinc = &registers[Areg_index[opcode >> 2 & 0x03]];
+			address += *postinc;
+			break;
+		case AM2:
+			postinc = &registers[Areg_index[opcode >> 4 & 0x03]];
+			address += *postinc;
+			break;
+		case RM0:
+			postinc = &registers[Rreg_index[opcode & 0x0f]];
+			address += *postinc;
+			break;
+		case RM1:
+			postinc = &registers[Rreg_index[opcode >> 2 & 0x0f]];
+			address += *postinc;
+			break;
+		case RM2:
+			postinc = &registers[Rreg_index[opcode >> 4 & 0x0f]];
+			address += *postinc;
+			break;
+		case RM4:
+			postinc = &registers[Rreg_index[opcode >> 8 & 0x0f]];
+			address += *postinc;
+			break;
+		case RM6:
+			postinc = &registers[Rreg_index[opcode >> 12 & 0x0f]];
+			address += *postinc;
+			break;
+		case RD0:
+			postinc = &registers[Rreg_index[disp & 0x0f]];
+			address += *postinc;
+			break;
+		case RD2:
+			postinc = &registers[Rreg_index[disp >> 4 & 0x0f]];
+			address += *postinc;
+			break;
+		case SP:
+			address += sp;
+			break;
+
+			/* displacements are either to be added to the address
+			 * before use, or, in the case of post-inc addressing,
+			 * to be added into the base register after use */
+		case SD8:
+		case SIMM8:
+			disp = (long) (int8_t) (disp & 0xff);
+			goto displace_or_inc;
+		case SD16:
+			disp = (long) (int16_t) (disp & 0xffff);
+			goto displace_or_inc;
+		case SD24:
+			tmp = disp << 8;
+			asm("asr 8,%0" : "=r"(tmp) : "0"(tmp) : "cc");
+			disp = (long) tmp;
+			goto displace_or_inc;
+		case SIMM4_2:
+			tmp = opcode >> 4 & 0x0f;
+			tmp <<= 28;
+			asm("asr 28,%0" : "=r"(tmp) : "0"(tmp) : "cc");
+			disp = (long) tmp;
+			goto displace_or_inc;
+		case IMM8:
+			disp &= 0x000000ff;
+			goto displace_or_inc;
+		case IMM16:
+			disp &= 0x0000ffff;
+			goto displace_or_inc;
+		case IMM24:
+			disp &= 0x00ffffff;
+			goto displace_or_inc;
+		case IMM32:
+		case IMM32_MEM:
+		case IMM32_HIGH8:
+		case IMM32_HIGH8_MEM:
+		displace_or_inc:
+			kdebug("%s %lx", _inc ? "incr" : "disp", disp);
+			if (!_inc)
+				address += disp;
+			else
+				*_inc = disp;
+			break;
+		default:
+			BUG();
+			return 0;
+		}
+	} while ((params >>= 8));
+
+	*_address = (void *) address;
+	*_postinc = postinc;
+	return 1;
+}
+
+/*
+ * determine the register that is acting as source/dest
+ */
+static int misalignment_reg(unsigned long *registers, unsigned params,
+			    unsigned opcode, unsigned long disp,
+			    unsigned long **_register)
+{
+	params &= 0x7fffffff;
+
+	if (params & 0xffffff00)
+		return 0;
+
+	switch (params & 0xff) {
+	case DM0:
+		*_register = &registers[Dreg_index[opcode & 0x03]];
+		break;
+	case DM1:
+		*_register = &registers[Dreg_index[opcode >> 2 & 0x03]];
+		break;
+	case DM2:
+		*_register = &registers[Dreg_index[opcode >> 4 & 0x03]];
+		break;
+	case AM0:
+		*_register = &registers[Areg_index[opcode & 0x03]];
+		break;
+	case AM1:
+		*_register = &registers[Areg_index[opcode >> 2 & 0x03]];
+		break;
+	case AM2:
+		*_register = &registers[Areg_index[opcode >> 4 & 0x03]];
+		break;
+	case RM0:
+		*_register = &registers[Rreg_index[opcode & 0x0f]];
+		break;
+	case RM1:
+		*_register = &registers[Rreg_index[opcode >> 2 & 0x0f]];
+		break;
+	case RM2:
+		*_register = &registers[Rreg_index[opcode >> 4 & 0x0f]];
+		break;
+	case RM4:
+		*_register = &registers[Rreg_index[opcode >> 8 & 0x0f]];
+		break;
+	case RM6:
+		*_register = &registers[Rreg_index[opcode >> 12 & 0x0f]];
+		break;
+	case RD0:
+		*_register = &registers[Rreg_index[disp & 0x0f]];
+		break;
+	case RD2:
+		*_register = &registers[Rreg_index[disp >> 4 & 0x0f]];
+		break;
+	case SP:
+		*_register = &registers[REG_SP >> 2];
+		break;
+
+	default:
+		BUG();
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * handle the conditional loop part of the move-and-loop instructions
+ */
+static void misalignment_MOV_Lcc(struct pt_regs *regs, uint32_t opcode)
+{
+	unsigned long epsw = regs->epsw;
+	unsigned long NxorV;
+
+	kdebug("MOV_Lcc %x [flags=%lx]", opcode, epsw & 0xf);
+
+	/* calculate N^V and shift onto the same bit position as Z */
+	NxorV = ((epsw >> 3) ^ epsw >> 1) & 1;
+
+	switch (opcode & 0xf) {
+	case 0x0: /* MOV_LLT: N^V */
+		if (NxorV)
+			goto take_the_loop;
+		return;
+	case 0x1: /* MOV_LGT: ~(Z or (N^V))*/
+		if (!((epsw & EPSW_FLAG_Z) | NxorV))
+			goto take_the_loop;
+		return;
+	case 0x2: /* MOV_LGE: ~(N^V) */
+		if (!NxorV)
+			goto take_the_loop;
+		return;
+	case 0x3: /* MOV_LLE: Z or (N^V) */
+		if ((epsw & EPSW_FLAG_Z) | NxorV)
+			goto take_the_loop;
+		return;
+
+	case 0x4: /* MOV_LCS: C */
+		if (epsw & EPSW_FLAG_C)
+			goto take_the_loop;
+		return;
+	case 0x5: /* MOV_LHI: ~(C or Z) */
+		if (!(epsw & (EPSW_FLAG_C | EPSW_FLAG_Z)))
+			goto take_the_loop;
+		return;
+	case 0x6: /* MOV_LCC: ~C */
+		if (!(epsw & EPSW_FLAG_C))
+			goto take_the_loop;
+		return;
+	case 0x7: /* MOV_LLS: C or Z */
+		if (epsw & (EPSW_FLAG_C | EPSW_FLAG_Z))
+			goto take_the_loop;
+		return;
+
+	case 0x8: /* MOV_LEQ: Z */
+		if (epsw & EPSW_FLAG_Z)
+			goto take_the_loop;
+		return;
+	case 0x9: /* MOV_LNE: ~Z */
+		if (!(epsw & EPSW_FLAG_Z))
+			goto take_the_loop;
+		return;
+	case 0xa: /* MOV_LRA: always */
+		goto take_the_loop;
+
+	default:
+		BUG();
+	}
+
+take_the_loop:
+	/* wind the PC back to just after the SETLB insn */
+	kdebug("loop LAR=%lx", regs->lar);
+	regs->pc = regs->lar - 4;
+}
+
+/*
+ * misalignment handler tests
+ */
+#ifdef CONFIG_TEST_MISALIGNMENT_HANDLER
+static u8 __initdata testbuf[512] __attribute__((aligned(16))) = {
+	[257] = 0x11,
+	[258] = 0x22,
+	[259] = 0x33,
+	[260] = 0x44,
+};
+
+#define ASSERTCMP(X, OP, Y)						\
+do {									\
+	if (unlikely(!((X) OP (Y)))) {					\
+		printk(KERN_ERR "\n");					\
+		printk(KERN_ERR "MISALIGN: Assertion failed at line %u\n", \
+		       __LINE__);					\
+		printk(KERN_ERR "0x%lx " #OP " 0x%lx is false\n",	\
+		       (unsigned long)(X), (unsigned long)(Y));		\
+		BUG();							\
+	}								\
+} while(0)
+
+static int __init test_misalignment(void)
+{
+	register void *r asm("e0");
+	register u32 y asm("e1");
+	void *p = testbuf, *q;
+	u32 tmp, tmp2, x;
+
+	printk(KERN_NOTICE "==>test_misalignment() [testbuf=%p]\n", p);
+	p++;
+
+	printk(KERN_NOTICE "___ MOV (Am),Dn ___\n");
+	q = p + 256;
+	asm volatile("mov	(%0),%1" : "+a"(q), "=d"(x));
+	ASSERTCMP(q, ==, p + 256);
+	ASSERTCMP(x, ==, 0x44332211);
+
+	printk(KERN_NOTICE "___ MOV (256,Am),Dn ___\n");
+	q = p;
+	asm volatile("mov	(256,%0),%1" : "+a"(q), "=d"(x));
+	ASSERTCMP(q, ==, p);
+	ASSERTCMP(x, ==, 0x44332211);
+
+	printk(KERN_NOTICE "___ MOV (Di,Am),Dn ___\n");
+	tmp = 256;
+	q = p;
+	asm volatile("mov	(%2,%0),%1" : "+a"(q), "=d"(x), "+d"(tmp));
+	ASSERTCMP(q, ==, p);
+	ASSERTCMP(x, ==, 0x44332211);
+	ASSERTCMP(tmp, ==, 256);
+
+	printk(KERN_NOTICE "___ MOV (256,Rm),Rn ___\n");
+	r = p;
+	asm volatile("mov	(256,%0),%1" : "+r"(r), "=r"(y));
+	ASSERTCMP(r, ==, p);
+	ASSERTCMP(y, ==, 0x44332211);
+
+	printk(KERN_NOTICE "___ MOV (Rm+),Rn ___\n");
+	r = p + 256;
+	asm volatile("mov	(%0+),%1" : "+r"(r), "=r"(y));
+	ASSERTCMP(r, ==, p + 256 + 4);
+	ASSERTCMP(y, ==, 0x44332211);
+
+	printk(KERN_NOTICE "___ MOV (Rm+,8),Rn ___\n");
+	r = p + 256;
+	asm volatile("mov	(%0+,8),%1" : "+r"(r), "=r"(y));
+	ASSERTCMP(r, ==, p + 256 + 8);
+	ASSERTCMP(y, ==, 0x44332211);
+
+	printk(KERN_NOTICE "___ MOV (7,SP),Rn ___\n");
+	asm volatile(
+		"add	-16,sp		\n"
+		"mov	+0x11,%0	\n"
+		"movbu	%0,(7,sp)	\n"
+		"mov	+0x22,%0	\n"
+		"movbu	%0,(8,sp)	\n"
+		"mov	+0x33,%0	\n"
+		"movbu	%0,(9,sp)	\n"
+		"mov	+0x44,%0	\n"
+		"movbu	%0,(10,sp)	\n"
+		"mov	(7,sp),%1	\n"
+		"add	+16,sp		\n"
+		: "+a"(q), "=d"(x));
+	ASSERTCMP(x, ==, 0x44332211);
+
+	printk(KERN_NOTICE "___ MOV (259,SP),Rn ___\n");
+	asm volatile(
+		"add	-264,sp		\n"
+		"mov	+0x11,%0	\n"
+		"movbu	%0,(259,sp)	\n"
+		"mov	+0x22,%0	\n"
+		"movbu	%0,(260,sp)	\n"
+		"mov	+0x33,%0	\n"
+		"movbu	%0,(261,sp)	\n"
+		"mov	+0x55,%0	\n"
+		"movbu	%0,(262,sp)	\n"
+		"mov	(259,sp),%1	\n"
+		"add	+264,sp		\n"
+		: "+d"(tmp), "=d"(x));
+	ASSERTCMP(x, ==, 0x55332211);
+
+	printk(KERN_NOTICE "___ MOV (260,SP),Rn ___\n");
+	asm volatile(
+		"add	-264,sp		\n"
+		"mov	+0x11,%0	\n"
+		"movbu	%0,(260,sp)	\n"
+		"mov	+0x22,%0	\n"
+		"movbu	%0,(261,sp)	\n"
+		"mov	+0x33,%0	\n"
+		"movbu	%0,(262,sp)	\n"
+		"mov	+0x55,%0	\n"
+		"movbu	%0,(263,sp)	\n"
+		"mov	(260,sp),%1	\n"
+		"add	+264,sp		\n"
+		: "+d"(tmp), "=d"(x));
+	ASSERTCMP(x, ==, 0x55332211);
+
+
+	printk(KERN_NOTICE "___ MOV_LNE ___\n");
+	tmp = 1;
+	tmp2 = 2;
+	q = p + 256;
+	asm volatile(
+		"setlb			\n"
+		"mov	%2,%3		\n"
+		"mov	%1,%2		\n"
+		"cmp	+0,%1		\n"
+		"mov_lne	(%0+,4),%1"
+		: "+r"(q), "+d"(tmp), "+d"(tmp2), "=d"(x)
+		:
+		: "cc");
+	ASSERTCMP(q, ==, p + 256 + 12);
+	ASSERTCMP(x, ==, 0x44332211);
+
+	printk(KERN_NOTICE "___ MOV in SETLB ___\n");
+	tmp = 1;
+	tmp2 = 2;
+	q = p + 256;
+	asm volatile(
+		"setlb			\n"
+		"mov	%1,%3		\n"
+		"mov	(%0+),%1	\n"
+		"cmp	+0,%1		\n"
+		"lne			"
+		: "+a"(q), "+d"(tmp), "+d"(tmp2), "=d"(x)
+		:
+		: "cc");
+
+	ASSERTCMP(q, ==, p + 256 + 8);
+	ASSERTCMP(x, ==, 0x44332211);
+
+	printk(KERN_NOTICE "<==test_misalignment()\n");
+	return 0;
+}
+
+arch_initcall(test_misalignment);
+
+#endif /* CONFIG_TEST_MISALIGNMENT_HANDLER */
diff --git a/arch/mn10300/mm/mmu-context.c b/arch/mn10300/mm/mmu-context.c
new file mode 100644
index 0000000..a4f7d3d
--- /dev/null
+++ b/arch/mn10300/mm/mmu-context.c
@@ -0,0 +1,62 @@
+/* MN10300 MMU context allocation and management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+
+#ifdef CONFIG_MN10300_TLB_USE_PIDR
+/*
+ * list of the MMU contexts last allocated on each CPU
+ */
+unsigned long mmu_context_cache[NR_CPUS] = {
+	[0 ... NR_CPUS - 1] =
+	MMU_CONTEXT_FIRST_VERSION * 2 - (1 - MMU_CONTEXT_TLBPID_LOCK_NR),
+};
+#endif /* CONFIG_MN10300_TLB_USE_PIDR */
+
+/*
+ * preemptively set a TLB entry
+ */
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
+{
+	unsigned long pteu, ptel, cnx, flags;
+	pte_t pte = *ptep;
+
+	addr &= PAGE_MASK;
+	ptel = pte_val(pte) & ~(xPTEL_UNUSED1 | xPTEL_UNUSED2);
+
+	/* make sure the context doesn't migrate and defend against
+	 * interference from vmalloc'd regions */
+	local_irq_save(flags);
+
+	cnx = ~MMU_NO_CONTEXT;
+#ifdef CONFIG_MN10300_TLB_USE_PIDR
+	cnx = mm_context(vma->vm_mm);
+#endif
+
+	if (cnx != MMU_NO_CONTEXT) {
+		pteu = addr;
+#ifdef CONFIG_MN10300_TLB_USE_PIDR
+		pteu |= cnx & MMU_CONTEXT_TLBPID_MASK;
+#endif
+		if (!(pte_val(pte) & _PAGE_NX)) {
+			IPTEU = pteu;
+			if (IPTEL & xPTEL_V)
+				IPTEL = ptel;
+		}
+		DPTEU = pteu;
+		if (DPTEL & xPTEL_V)
+			DPTEL = ptel;
+	}
+
+	local_irq_restore(flags);
+}
diff --git a/arch/mn10300/mm/pgtable.c b/arch/mn10300/mm/pgtable.c
new file mode 100644
index 0000000..e77a7c7
--- /dev/null
+++ b/arch/mn10300/mm/pgtable.c
@@ -0,0 +1,174 @@
+/* MN10300 Page table management
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/spinlock.h>
+#include <linux/quicklist.h>
+
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+
+/*
+ * Associate a large virtual page frame with a given physical page frame
+ * and protection flags for that frame. pfn is for the base of the page,
+ * vaddr is what the page gets mapped to - both must be properly aligned.
+ * The pmd must already be instantiated. Assumes PAE mode.
+ */
+void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+
+	if (vaddr & (PMD_SIZE-1)) {		/* vaddr is misaligned */
+		printk(KERN_ERR "set_pmd_pfn: vaddr misaligned\n");
+		return; /* BUG(); */
+	}
+	if (pfn & (PTRS_PER_PTE-1)) {		/* pfn is misaligned */
+		printk(KERN_ERR "set_pmd_pfn: pfn misaligned\n");
+		return; /* BUG(); */
+	}
+	pgd = swapper_pg_dir + pgd_index(vaddr);
+	if (pgd_none(*pgd)) {
+		printk(KERN_ERR "set_pmd_pfn: pgd_none\n");
+		return; /* BUG(); */
+	}
+	pud = pud_offset(pgd, vaddr);
+	pmd = pmd_offset(pud, vaddr);
+	set_pmd(pmd, pfn_pmd(pfn, flags));
+	/*
+	 * It's enough to flush this one mapping.
+	 * (PGE mappings get flushed as well)
+	 */
+	local_flush_tlb_one(vaddr);
+}
+
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+	if (pte)
+		clear_page(pte);
+	return pte;
+}
+
+struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+	struct page *pte;
+
+#ifdef CONFIG_HIGHPTE
+	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT, 0);
+#else
+	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+#endif
+	if (!pte)
+		return NULL;
+	clear_highpage(pte);
+	if (!pgtable_page_ctor(pte)) {
+		__free_page(pte);
+		return NULL;
+	}
+	return pte;
+}
+
+/*
+ * List of all pgd's needed for non-PAE so it can invalidate entries
+ * in both cached and uncached pgd's; not needed for PAE since the
+ * kernel pmd is shared. If PAE were not to share the pmd a similar
+ * tactic would be needed. This is essentially codepath-based locking
+ * against pageattr.c; it is the unique case in which a valid change
+ * of kernel pagetables can't be lazily synchronized by vmalloc faults.
+ * vmalloc faults work because attached pagetables are never freed.
+ * If the locking proves to be non-performant, a ticketing scheme with
+ * checks at dup_mmap(), exec(), and other mmlist addition points
+ * could be used. The locking scheme was chosen on the basis of
+ * manfred's recommendations and having no core impact whatsoever.
+ * -- nyc
+ */
+DEFINE_SPINLOCK(pgd_lock);
+struct page *pgd_list;
+
+static inline void pgd_list_add(pgd_t *pgd)
+{
+	struct page *page = virt_to_page(pgd);
+	page->index = (unsigned long) pgd_list;
+	if (pgd_list)
+		set_page_private(pgd_list, (unsigned long) &page->index);
+	pgd_list = page;
+	set_page_private(page, (unsigned long) &pgd_list);
+}
+
+static inline void pgd_list_del(pgd_t *pgd)
+{
+	struct page *next, **pprev, *page = virt_to_page(pgd);
+	next = (struct page *) page->index;
+	pprev = (struct page **) page_private(page);
+	*pprev = next;
+	if (next)
+		set_page_private(next, (unsigned long) pprev);
+}
+
+void pgd_ctor(void *pgd)
+{
+	unsigned long flags;
+
+	if (PTRS_PER_PMD == 1)
+		spin_lock_irqsave(&pgd_lock, flags);
+
+	memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
+			swapper_pg_dir + USER_PTRS_PER_PGD,
+			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+
+	if (PTRS_PER_PMD > 1)
+		return;
+
+	pgd_list_add(pgd);
+	spin_unlock_irqrestore(&pgd_lock, flags);
+	memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+}
+
+/* never called when PTRS_PER_PMD > 1 */
+void pgd_dtor(void *pgd)
+{
+	unsigned long flags; /* can be called from interrupt context */
+
+	spin_lock_irqsave(&pgd_lock, flags);
+	pgd_list_del(pgd);
+	spin_unlock_irqrestore(&pgd_lock, flags);
+}
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	return quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
+}
+
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	quicklist_free(0, pgd_dtor, pgd);
+}
+
+void __init pgtable_cache_init(void)
+{
+}
+
+void check_pgt_cache(void)
+{
+	quicklist_trim(0, pgd_dtor, 25, 16);
+}
diff --git a/arch/mn10300/mm/tlb-mn10300.S b/arch/mn10300/mm/tlb-mn10300.S
new file mode 100644
index 0000000..b994017
--- /dev/null
+++ b/arch/mn10300/mm/tlb-mn10300.S
@@ -0,0 +1,220 @@
+###############################################################################
+#
+# TLB loading functions
+#
+# Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Modified by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/intctl-regs.h>
+#include <asm/frame.inc>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+###############################################################################
+#
+# Instruction TLB Miss handler entry point
+#
+###############################################################################
+	.type	itlb_miss,@function
+ENTRY(itlb_miss)
+#ifdef CONFIG_GDBSTUB
+	movm	[d2,d3,a2],(sp)
+#else
+	or	EPSW_nAR,epsw		# switch D0-D3 & A0-A3 to the alternate
+					# register bank
+	nop
+	nop
+	nop
+#endif
+
+#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
+	mov	(MMUCTR),d2
+	mov	d2,(MMUCTR)
+#endif
+
+	and	~EPSW_NMID,epsw
+	mov	(IPTEU),d3
+	mov	(PTBR),a2
+	mov	d3,d2
+	and	0xffc00000,d2
+	lsr	20,d2
+	mov	(a2,d2),a2		# PTD *ptd = PGD[addr 31..22]
+	btst	_PAGE_VALID,a2
+	beq	itlb_miss_fault		# jump if doesn't point anywhere
+
+	and	~(PAGE_SIZE-1),a2
+	mov	d3,d2
+	and	0x003ff000,d2
+	lsr	10,d2
+	add	d2,a2
+	mov	(a2),d2			# get pte from PTD[addr 21..12]
+	btst	_PAGE_VALID,d2
+	beq	itlb_miss_fault		# jump if doesn't point to a page
+					# (might be a swap id)
+#if	((_PAGE_ACCESSED & 0xffffff00) == 0)
+	bset	_PAGE_ACCESSED,(0,a2)
+#elif	((_PAGE_ACCESSED & 0xffff00ff) == 0)
+	bset	+(_PAGE_ACCESSED >> 8),(1,a2)
+#else
+#error	"_PAGE_ACCESSED value is out of range"
+#endif
+	and	~xPTEL2_UNUSED1,d2
+itlb_miss_set:
+	mov	d2,(IPTEL2)		# change the TLB
+#ifdef CONFIG_GDBSTUB
+	movm	(sp),[d2,d3,a2]
+#endif
+	rti
+
+itlb_miss_fault:
+	mov	_PAGE_VALID,d2		# force address error handler to be
+					# invoked
+	bra	itlb_miss_set
+
+	.size	itlb_miss, . - itlb_miss
+
+###############################################################################
+#
+# Data TLB Miss handler entry point
+#
+###############################################################################
+	.type	dtlb_miss,@function
+ENTRY(dtlb_miss)
+#ifdef CONFIG_GDBSTUB
+	movm	[d2,d3,a2],(sp)
+#else
+	or	EPSW_nAR,epsw		# switch D0-D3 & A0-A3 to the alternate
+					# register bank
+	nop
+	nop
+	nop
+#endif
+
+#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
+	mov	(MMUCTR),d2
+	mov	d2,(MMUCTR)
+#endif
+
+	and	~EPSW_NMID,epsw
+	mov	(DPTEU),d3
+	mov	(PTBR),a2
+	mov	d3,d2
+	and	0xffc00000,d2
+	lsr	20,d2
+	mov	(a2,d2),a2		# PTD *ptd = PGD[addr 31..22]
+	btst	_PAGE_VALID,a2
+	beq	dtlb_miss_fault		# jump if doesn't point anywhere
+
+	and	~(PAGE_SIZE-1),a2
+	mov	d3,d2
+	and	0x003ff000,d2
+	lsr	10,d2
+	add	d2,a2
+	mov	(a2),d2			# get pte from PTD[addr 21..12]
+	btst	_PAGE_VALID,d2
+	beq	dtlb_miss_fault		# jump if doesn't point to a page
+					# (might be a swap id)
+#if	((_PAGE_ACCESSED & 0xffffff00) == 0)
+	bset	_PAGE_ACCESSED,(0,a2)
+#elif	((_PAGE_ACCESSED & 0xffff00ff) == 0)
+	bset	+(_PAGE_ACCESSED >> 8),(1,a2)
+#else
+#error	"_PAGE_ACCESSED value is out of range"
+#endif
+	and	~xPTEL2_UNUSED1,d2
+dtlb_miss_set:
+	mov	d2,(DPTEL2)		# change the TLB
+#ifdef CONFIG_GDBSTUB
+	movm	(sp),[d2,d3,a2]
+#endif
+	rti
+
+dtlb_miss_fault:
+	mov	_PAGE_VALID,d2		# force address error handler to be
+					# invoked
+	bra	dtlb_miss_set
+	.size	dtlb_miss, . - dtlb_miss
+
+###############################################################################
+#
+# Instruction TLB Address Error handler entry point
+#
+###############################################################################
+	.type	itlb_aerror,@function
+ENTRY(itlb_aerror)
+	add	-4,sp
+	SAVE_ALL
+
+#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
+	mov	(MMUCTR),d1
+	mov	d1,(MMUCTR)
+#endif
+
+	and	~EPSW_NMID,epsw
+	add	-4,sp				# need to pass three params
+
+	# calculate the fault code
+	movhu	(MMUFCR_IFC),d1
+	or	0x00010000,d1			# it's an instruction fetch
+
+	# determine the page address
+	mov	(IPTEU),d0
+	and	PAGE_MASK,d0
+	mov	d0,(12,sp)
+
+	clr	d0
+	mov	d0,(IPTEL2)
+
+	or	EPSW_IE,epsw
+	mov	fp,d0
+	call	do_page_fault[],0		# do_page_fault(regs,code,addr
+
+	jmp	ret_from_exception
+	.size	itlb_aerror, . - itlb_aerror
+
+###############################################################################
+#
+# Data TLB Address Error handler entry point
+#
+###############################################################################
+	.type	dtlb_aerror,@function
+ENTRY(dtlb_aerror)
+	add	-4,sp
+	SAVE_ALL
+
+#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
+	mov	(MMUCTR),d1
+	mov	d1,(MMUCTR)
+#endif
+
+	add	-4,sp				# need to pass three params
+	and	~EPSW_NMID,epsw
+
+	# calculate the fault code
+	movhu	(MMUFCR_DFC),d1
+
+	# determine the page address
+	mov	(DPTEU),a2
+	mov	a2,d0
+	and	PAGE_MASK,d0
+	mov	d0,(12,sp)
+
+	clr	d0
+	mov	d0,(DPTEL2)
+
+	or	EPSW_IE,epsw
+	mov	fp,d0
+	call	do_page_fault[],0		# do_page_fault(regs,code,addr
+
+	jmp	ret_from_exception
+	.size	dtlb_aerror, . - dtlb_aerror
diff --git a/arch/mn10300/mm/tlb-smp.c b/arch/mn10300/mm/tlb-smp.c
new file mode 100644
index 0000000..9a39ea9
--- /dev/null
+++ b/arch/mn10300/mm/tlb-smp.c
@@ -0,0 +1,213 @@
+/* SMP TLB support routines.
+ *
+ * Copyright (C) 2006-2008 Panasonic Corporation
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/cpumask.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/profile.h>
+#include <linux/smp.h>
+#include <asm/tlbflush.h>
+#include <asm/bitops.h>
+#include <asm/processor.h>
+#include <asm/bug.h>
+#include <asm/exceptions.h>
+#include <asm/hardirq.h>
+#include <asm/fpu.h>
+#include <asm/mmu_context.h>
+#include <asm/thread_info.h>
+#include <asm/cpu-regs.h>
+#include <asm/intctl-regs.h>
+
+/*
+ * For flush TLB
+ */
+#define FLUSH_ALL	0xffffffff
+
+static cpumask_t flush_cpumask;
+static struct mm_struct *flush_mm;
+static unsigned long flush_va;
+static DEFINE_SPINLOCK(tlbstate_lock);
+
+DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = {
+	&init_mm, 0
+};
+
+static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
+			     unsigned long va);
+static void do_flush_tlb_all(void *info);
+
+/**
+ * smp_flush_tlb - Callback to invalidate the TLB.
+ * @unused: Callback context (ignored).
+ */
+void smp_flush_tlb(void *unused)
+{
+	unsigned long cpu_id;
+
+	cpu_id = get_cpu();
+
+	if (!cpumask_test_cpu(cpu_id, &flush_cpumask))
+		/* This was a BUG() but until someone can quote me the line
+		 * from the intel manual that guarantees an IPI to multiple
+		 * CPUs is retried _only_ on the erroring CPUs its staying as a
+		 * return
+		 *
+		 * BUG();
+		 */
+		goto out;
+
+	if (flush_va == FLUSH_ALL)
+		local_flush_tlb();
+	else
+		local_flush_tlb_page(flush_mm, flush_va);
+
+	smp_mb__before_atomic();
+	cpumask_clear_cpu(cpu_id, &flush_cpumask);
+	smp_mb__after_atomic();
+out:
+	put_cpu();
+}
+
+/**
+ * flush_tlb_others - Tell the specified CPUs to invalidate their TLBs
+ * @cpumask: The list of CPUs to target.
+ * @mm: The VM context to flush from (if va!=FLUSH_ALL).
+ * @va: Virtual address to flush or FLUSH_ALL to flush everything.
+ */
+static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
+			     unsigned long va)
+{
+	cpumask_t tmp;
+
+	/* A couple of sanity checks (to be removed):
+	 * - mask must not be empty
+	 * - current CPU must not be in mask
+	 * - we do not send IPIs to as-yet unbooted CPUs.
+	 */
+	BUG_ON(!mm);
+	BUG_ON(cpumask_empty(&cpumask));
+	BUG_ON(cpumask_test_cpu(smp_processor_id(), &cpumask));
+
+	cpumask_and(&tmp, &cpumask, cpu_online_mask);
+	BUG_ON(!cpumask_equal(&cpumask, &tmp));
+
+	/* I'm not happy about this global shared spinlock in the MM hot path,
+	 * but we'll see how contended it is.
+	 *
+	 * Temporarily this turns IRQs off, so that lockups are detected by the
+	 * NMI watchdog.
+	 */
+	spin_lock(&tlbstate_lock);
+
+	flush_mm = mm;
+	flush_va = va;
+#if NR_CPUS <= BITS_PER_LONG
+	atomic_or(cpumask.bits[0], (atomic_t *)&flush_cpumask.bits[0]);
+#else
+#error Not supported.
+#endif
+
+	/* FIXME: if NR_CPUS>=3, change send_IPI_mask */
+	smp_call_function(smp_flush_tlb, NULL, 1);
+
+	while (!cpumask_empty(&flush_cpumask))
+		/* Lockup detection does not belong here */
+		smp_mb();
+
+	flush_mm = NULL;
+	flush_va = 0;
+	spin_unlock(&tlbstate_lock);
+}
+
+/**
+ * flush_tlb_mm - Invalidate TLB of specified VM context
+ * @mm: The VM context to invalidate.
+ */
+void flush_tlb_mm(struct mm_struct *mm)
+{
+	cpumask_t cpu_mask;
+
+	preempt_disable();
+	cpumask_copy(&cpu_mask, mm_cpumask(mm));
+	cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
+
+	local_flush_tlb();
+	if (!cpumask_empty(&cpu_mask))
+		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
+
+	preempt_enable();
+}
+
+/**
+ * flush_tlb_current_task - Invalidate TLB of current task
+ */
+void flush_tlb_current_task(void)
+{
+	struct mm_struct *mm = current->mm;
+	cpumask_t cpu_mask;
+
+	preempt_disable();
+	cpumask_copy(&cpu_mask, mm_cpumask(mm));
+	cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
+
+	local_flush_tlb();
+	if (!cpumask_empty(&cpu_mask))
+		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
+
+	preempt_enable();
+}
+
+/**
+ * flush_tlb_page - Invalidate TLB of page
+ * @vma: The VM context to invalidate the page for.
+ * @va: The virtual address of the page to invalidate.
+ */
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	cpumask_t cpu_mask;
+
+	preempt_disable();
+	cpumask_copy(&cpu_mask, mm_cpumask(mm));
+	cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
+
+	local_flush_tlb_page(mm, va);
+	if (!cpumask_empty(&cpu_mask))
+		flush_tlb_others(cpu_mask, mm, va);
+
+	preempt_enable();
+}
+
+/**
+ * do_flush_tlb_all - Callback to completely invalidate a TLB
+ * @unused: Callback context (ignored).
+ */
+static void do_flush_tlb_all(void *unused)
+{
+	local_flush_tlb_all();
+}
+
+/**
+ * flush_tlb_all - Completely invalidate TLBs on all CPUs
+ */
+void flush_tlb_all(void)
+{
+	on_each_cpu(do_flush_tlb_all, 0, 1);
+}
diff --git a/arch/mn10300/oprofile/Makefile b/arch/mn10300/oprofile/Makefile
new file mode 100644
index 0000000..918dbe6
--- /dev/null
+++ b/arch/mn10300/oprofile/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the MN10300-specific profiling code
+#
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
+		oprof.o cpu_buffer.o buffer_sync.o \
+		event_buffer.o oprofile_files.o \
+		oprofilefs.o oprofile_stats.o \
+		timer_int.o )
+
+oprofile-y				:= $(DRIVER_OBJS) op_model_null.o
+
diff --git a/arch/mn10300/oprofile/op_model_null.c b/arch/mn10300/oprofile/op_model_null.c
new file mode 100644
index 0000000..cd4ab37
--- /dev/null
+++ b/arch/mn10300/oprofile/op_model_null.c
@@ -0,0 +1,22 @@
+/* Null profiling driver
+ *
+ * Copyright (C) 2003  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * Licence.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/oprofile.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+
+int __init oprofile_arch_init(struct oprofile_operations *ops)
+{
+	return -ENODEV;
+}
+
+void oprofile_arch_exit(void)
+{
+}
+
diff --git a/arch/mn10300/proc-mn103e010/Makefile b/arch/mn10300/proc-mn103e010/Makefile
new file mode 100644
index 0000000..ac2c978
--- /dev/null
+++ b/arch/mn10300/proc-mn103e010/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the MN103E010 processor chip specific code
+#
+obj-y   := proc-init.o
+
diff --git a/arch/mn10300/proc-mn103e010/include/proc/cache.h b/arch/mn10300/proc-mn103e010/include/proc/cache.h
new file mode 100644
index 0000000..967d144
--- /dev/null
+++ b/arch/mn10300/proc-mn103e010/include/proc/cache.h
@@ -0,0 +1,43 @@
+/* MN103E010 Cache specification
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_PROC_CACHE_H
+#define _ASM_PROC_CACHE_H
+
+/* L1 cache */
+
+#define L1_CACHE_NWAYS		4	/* number of ways in caches */
+#define L1_CACHE_NENTRIES	256	/* number of entries in each way */
+#define L1_CACHE_BYTES		16	/* bytes per entry */
+#define L1_CACHE_SHIFT		4	/* shift for bytes per entry */
+#define L1_CACHE_WAYDISP	0x1000	/* displacement of one way from the next */
+
+#define L1_CACHE_TAG_VALID	0x00000001	/* cache tag valid bit */
+#define L1_CACHE_TAG_DIRTY	0x00000008	/* data cache tag dirty bit */
+#define L1_CACHE_TAG_ENTRY	0x00000ff0	/* cache tag entry address mask */
+#define L1_CACHE_TAG_ADDRESS	0xfffff000	/* cache tag line address mask */
+#define L1_CACHE_TAG_MASK	+(L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY)
+
+/*
+ * specification of the interval between interrupt checking intervals whilst
+ * managing the cache with the interrupts disabled
+ */
+#define MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL	4
+
+/*
+ * The size of range at which it becomes more economical to just flush the
+ * whole cache rather than trying to flush the specified range.
+ */
+#define MN10300_DCACHE_FLUSH_BORDER	\
+	+(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES)
+#define MN10300_DCACHE_FLUSH_INV_BORDER	\
+	+(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES)
+
+#endif /* _ASM_PROC_CACHE_H */
diff --git a/arch/mn10300/proc-mn103e010/include/proc/clock.h b/arch/mn10300/proc-mn103e010/include/proc/clock.h
new file mode 100644
index 0000000..704a819
--- /dev/null
+++ b/arch/mn10300/proc-mn103e010/include/proc/clock.h
@@ -0,0 +1,16 @@
+/* MN103E010-specific clocks
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_PROC_CLOCK_H
+#define _ASM_PROC_CLOCK_H
+
+#include <unit/clock.h>
+
+#endif /* _ASM_PROC_CLOCK_H */
diff --git a/arch/mn10300/proc-mn103e010/include/proc/dmactl-regs.h b/arch/mn10300/proc-mn103e010/include/proc/dmactl-regs.h
new file mode 100644
index 0000000..d72d328
--- /dev/null
+++ b/arch/mn10300/proc-mn103e010/include/proc/dmactl-regs.h
@@ -0,0 +1,102 @@
+/* MN103E010 on-board DMA controller registers
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_PROC_DMACTL_REGS_H
+#define _ASM_PROC_DMACTL_REGS_H
+
+#include <asm/cpu-regs.h>
+
+#ifdef __KERNEL__
+
+/* DMA registers */
+#define	DMxCTR(N)		__SYSREG(0xd2000000 + ((N) * 0x100), u32)	/* control reg */
+#define	DMxCTR_BG		0x0000001f	/* transfer request source */
+#define	DMxCTR_BG_SOFT		0x00000000	/* - software source */
+#define	DMxCTR_BG_SC0TX		0x00000002	/* - serial port 0 transmission */
+#define	DMxCTR_BG_SC0RX		0x00000003	/* - serial port 0 reception */
+#define	DMxCTR_BG_SC1TX		0x00000004	/* - serial port 1 transmission */
+#define	DMxCTR_BG_SC1RX		0x00000005	/* - serial port 1 reception */
+#define	DMxCTR_BG_SC2TX		0x00000006	/* - serial port 2 transmission */
+#define	DMxCTR_BG_SC2RX		0x00000007	/* - serial port 2 reception */
+#define	DMxCTR_BG_TM0UFLOW	0x00000008	/* - timer 0 underflow */
+#define	DMxCTR_BG_TM1UFLOW	0x00000009	/* - timer 1 underflow */
+#define	DMxCTR_BG_TM2UFLOW	0x0000000a	/* - timer 2 underflow */
+#define	DMxCTR_BG_TM3UFLOW	0x0000000b	/* - timer 3 underflow */
+#define	DMxCTR_BG_TM6ACMPCAP	0x0000000c	/* - timer 6A compare/capture */
+#define	DMxCTR_BG_AFE		0x0000000d	/* - analogue front-end interrupt source */
+#define	DMxCTR_BG_ADC		0x0000000e	/* - A/D conversion end interrupt source */
+#define	DMxCTR_BG_IRDA		0x0000000f	/* - IrDA interrupt source */
+#define	DMxCTR_BG_RTC		0x00000010	/* - RTC interrupt source */
+#define	DMxCTR_BG_XIRQ0		0x00000011	/* - XIRQ0 pin interrupt source */
+#define	DMxCTR_BG_XIRQ1		0x00000012	/* - XIRQ1 pin interrupt source */
+#define	DMxCTR_BG_XDMR0		0x00000013	/* - external request 0 source (XDMR0 pin) */
+#define	DMxCTR_BG_XDMR1		0x00000014	/* - external request 1 source (XDMR1 pin) */
+#define	DMxCTR_SAM		0x000000e0	/* DMA transfer src addr mode */
+#define	DMxCTR_SAM_INCR		0x00000000	/* - increment */
+#define	DMxCTR_SAM_DECR		0x00000020	/* - decrement */
+#define	DMxCTR_SAM_FIXED	0x00000040	/* - fixed */
+#define	DMxCTR_DAM		0x00000000	/* DMA transfer dest addr mode */
+#define	DMxCTR_DAM_INCR		0x00000000	/* - increment */
+#define	DMxCTR_DAM_DECR		0x00000100	/* - decrement */
+#define	DMxCTR_DAM_FIXED	0x00000200	/* - fixed */
+#define	DMxCTR_TM		0x00001800	/* DMA transfer mode */
+#define	DMxCTR_TM_BATCH		0x00000000	/* - batch transfer */
+#define	DMxCTR_TM_INTERM	0x00001000	/* - intermittent transfer */
+#define	DMxCTR_UT		0x00006000	/* DMA transfer unit */
+#define	DMxCTR_UT_1		0x00000000	/* - 1 byte */
+#define	DMxCTR_UT_2		0x00002000	/* - 2 byte */
+#define	DMxCTR_UT_4		0x00004000	/* - 4 byte */
+#define	DMxCTR_UT_16		0x00006000	/* - 16 byte */
+#define	DMxCTR_TEN		0x00010000	/* DMA channel transfer enable */
+#define	DMxCTR_RQM		0x00060000	/* external request input source mode */
+#define	DMxCTR_RQM_FALLEDGE	0x00000000	/* - falling edge */
+#define	DMxCTR_RQM_RISEEDGE	0x00020000	/* - rising edge */
+#define	DMxCTR_RQM_LOLEVEL	0x00040000	/* - low level */
+#define	DMxCTR_RQM_HILEVEL	0x00060000	/* - high level */
+#define	DMxCTR_RQF		0x01000000	/* DMA transfer request flag */
+#define	DMxCTR_XEND		0x80000000	/* DMA transfer end flag */
+
+#define	DMxSRC(N)		__SYSREG(0xd2000004 + ((N) * 0x100), u32)	/* control reg */
+
+#define	DMxDST(N)		__SYSREG(0xd2000008 + ((N) * 0x100), u32)	/* src addr reg */
+
+#define	DMxSIZ(N)		__SYSREG(0xd200000c + ((N) * 0x100), u32)	/* dest addr reg */
+#define DMxSIZ_CT		0x000fffff	/* number of bytes to transfer */
+
+#define	DMxCYC(N)		__SYSREG(0xd2000010 + ((N) * 0x100), u32)	/* intermittent
+										 * size reg */
+#define DMxCYC_CYC		0x000000ff	/* number of interrmittent transfers -1 */
+
+#define DM0IRQ			16		/* DMA channel 0 complete IRQ */
+#define DM1IRQ			17		/* DMA channel 1 complete IRQ */
+#define DM2IRQ			18		/* DMA channel 2 complete IRQ */
+#define DM3IRQ			19		/* DMA channel 3 complete IRQ */
+
+#define	DM0ICR			GxICR(DM0IRQ)	/* DMA channel 0 complete intr ctrl reg */
+#define	DM1ICR			GxICR(DM0IR1)	/* DMA channel 1 complete intr ctrl reg */
+#define	DM2ICR			GxICR(DM0IR2)	/* DMA channel 2 complete intr ctrl reg */
+#define	DM3ICR			GxICR(DM0IR3)	/* DMA channel 3 complete intr ctrl reg */
+
+#ifndef __ASSEMBLY__
+
+struct mn10300_dmactl_regs {
+	u32		ctr;
+	const void	*src;
+	void		*dst;
+	u32		siz;
+	u32		cyc;
+} __attribute__((aligned(0x100)));
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_PROC_DMACTL_REGS_H */
diff --git a/arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h b/arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h
new file mode 100644
index 0000000..f537801
--- /dev/null
+++ b/arch/mn10300/proc-mn103e010/include/proc/intctl-regs.h
@@ -0,0 +1,29 @@
+#ifndef _ASM_PROC_INTCTL_REGS_H
+#define _ASM_PROC_INTCTL_REGS_H
+
+#ifndef _ASM_INTCTL_REGS_H
+# error "please don't include this file directly"
+#endif
+
+/* intr acceptance group reg */
+#define IAGR			__SYSREG(0xd4000100, u16)
+
+/* group number register */
+#define IAGR_GN			0x00fc
+
+#define __GET_XIRQ_TRIGGER(X, Z) (((Z) >> ((X) * 2)) & 3)
+
+#define __SET_XIRQ_TRIGGER(X, Y, Z)		\
+({						\
+	typeof(Z) x = (Z);			\
+	x &= ~(3 << ((X) * 2));			\
+	x |= ((Y) & 3) << ((X) * 2);		\
+	(Z) = x;				\
+})
+
+/* external pin intr spec reg */
+#define EXTMD			__SYSREG(0xd4000200, u16)
+#define GET_XIRQ_TRIGGER(X)	__GET_XIRQ_TRIGGER(X, EXTMD)
+#define SET_XIRQ_TRIGGER(X, Y)	__SET_XIRQ_TRIGGER(X, Y, EXTMD)
+
+#endif /* _ASM_PROC_INTCTL_REGS_H */
diff --git a/arch/mn10300/proc-mn103e010/include/proc/irq.h b/arch/mn10300/proc-mn103e010/include/proc/irq.h
new file mode 100644
index 0000000..aa6ee8f
--- /dev/null
+++ b/arch/mn10300/proc-mn103e010/include/proc/irq.h
@@ -0,0 +1,34 @@
+/* MN103E010 On-board interrupt controller numbers
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_PROC_IRQ_H
+#define _ASM_PROC_IRQ_H
+
+#ifdef __KERNEL__
+
+#define GxICR_NUM_IRQS		42
+
+#define GxICR_NUM_XIRQS		8
+
+#define XIRQ0		34
+#define XIRQ1		35
+#define XIRQ2		36
+#define XIRQ3		37
+#define XIRQ4		38
+#define XIRQ5		39
+#define XIRQ6		40
+#define XIRQ7		41
+
+#define XIRQ2IRQ(num)	(XIRQ0 + num)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_PROC_IRQ_H */
diff --git a/arch/mn10300/proc-mn103e010/include/proc/proc.h b/arch/mn10300/proc-mn103e010/include/proc/proc.h
new file mode 100644
index 0000000..39c4f8e
--- /dev/null
+++ b/arch/mn10300/proc-mn103e010/include/proc/proc.h
@@ -0,0 +1,18 @@
+/* MN103E010 Processor description
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_PROC_PROC_H
+#define _ASM_PROC_PROC_H
+
+#define PROCESSOR_VENDOR_NAME	"Panasonic"
+#define PROCESSOR_MODEL_NAME	"mn103e010"
+
+#endif /* _ASM_PROC_PROC_H */
diff --git a/arch/mn10300/proc-mn103e010/proc-init.c b/arch/mn10300/proc-mn103e010/proc-init.c
new file mode 100644
index 0000000..27b9798
--- /dev/null
+++ b/arch/mn10300/proc-mn103e010/proc-init.c
@@ -0,0 +1,112 @@
+/* MN103E010 Processor initialisation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <asm/fpu.h>
+#include <asm/rtc.h>
+#include <asm/busctl-regs.h>
+
+/*
+ * initialise the on-silicon processor peripherals
+ */
+asmlinkage void __init processor_init(void)
+{
+	int loop;
+
+	/* set up the exception table first */
+	for (loop = 0x000; loop < 0x400; loop += 8)
+		__set_intr_stub(loop, __common_exception);
+
+	__set_intr_stub(EXCEP_ITLBMISS,		itlb_miss);
+	__set_intr_stub(EXCEP_DTLBMISS,		dtlb_miss);
+	__set_intr_stub(EXCEP_IAERROR,		itlb_aerror);
+	__set_intr_stub(EXCEP_DAERROR,		dtlb_aerror);
+	__set_intr_stub(EXCEP_BUSERROR,		raw_bus_error);
+	__set_intr_stub(EXCEP_DOUBLE_FAULT,	double_fault);
+	__set_intr_stub(EXCEP_FPU_DISABLED,	fpu_disabled);
+	__set_intr_stub(EXCEP_SYSCALL0,		system_call);
+
+	__set_intr_stub(EXCEP_NMI,		nmi_handler);
+	__set_intr_stub(EXCEP_WDT,		nmi_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL0,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL1,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL2,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL3,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL4,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL5,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL6,	irq_handler);
+
+	IVAR0 = EXCEP_IRQ_LEVEL0;
+	IVAR1 = EXCEP_IRQ_LEVEL1;
+	IVAR2 = EXCEP_IRQ_LEVEL2;
+	IVAR3 = EXCEP_IRQ_LEVEL3;
+	IVAR4 = EXCEP_IRQ_LEVEL4;
+	IVAR5 = EXCEP_IRQ_LEVEL5;
+	IVAR6 = EXCEP_IRQ_LEVEL6;
+
+	mn10300_dcache_flush_inv();
+	mn10300_icache_inv();
+
+	/* disable all interrupts and set to priority 6 (lowest) */
+	for (loop = 0; loop < NR_IRQS; loop++)
+		GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
+
+	/* clear the timers */
+	TM0MD	= 0;
+	TM1MD	= 0;
+	TM2MD	= 0;
+	TM3MD	= 0;
+	TM4MD	= 0;
+	TM5MD	= 0;
+	TM6MD	= 0;
+	TM6MDA	= 0;
+	TM6MDB	= 0;
+	TM7MD	= 0;
+	TM8MD	= 0;
+	TM9MD	= 0;
+	TM10MD	= 0;
+	TM11MD	= 0;
+
+	calibrate_clock();
+}
+
+/*
+ * determine the memory size and base from the memory controller regs
+ */
+void __init get_mem_info(unsigned long *mem_base, unsigned long *mem_size)
+{
+	unsigned long base, size;
+
+	*mem_base = 0;
+	*mem_size = 0;
+
+	base = SDBASE(0);
+	if (base & SDBASE_CE) {
+		size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
+		size = ~size + 1;
+		base &= SDBASE_CBA;
+
+		printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base);
+		*mem_size += size;
+		*mem_base = base;
+	}
+
+	base = SDBASE(1);
+	if (base & SDBASE_CE) {
+		size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
+		size = ~size + 1;
+		base &= SDBASE_CBA;
+
+		printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base);
+		*mem_size += size;
+		if (*mem_base == 0)
+			*mem_base = base;
+	}
+}
diff --git a/arch/mn10300/proc-mn2ws0050/Makefile b/arch/mn10300/proc-mn2ws0050/Makefile
new file mode 100644
index 0000000..d4ca133
--- /dev/null
+++ b/arch/mn10300/proc-mn2ws0050/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y   := proc-init.o
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/cache.h b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h
new file mode 100644
index 0000000..bcb5df2
--- /dev/null
+++ b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h
@@ -0,0 +1,49 @@
+/* Cache specification
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * Modified by Matsushita Electric Industrial Co., Ltd.
+ * Modifications:
+ *  13-Nov-2006 MEI Add L1_CACHE_SHIFT_MAX definition.
+ *  29-Jul-2008 MEI Add define for MN10300_HAS_AREAPURGE_REG.
+ *
+ * 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.
+ */
+#ifndef _ASM_PROC_CACHE_H
+#define _ASM_PROC_CACHE_H
+
+/*
+ * L1 cache
+ */
+#define L1_CACHE_NWAYS		4		/* number of ways in caches */
+#define L1_CACHE_NENTRIES	128		/* number of entries in each way */
+#define L1_CACHE_BYTES		32		/* bytes per entry */
+#define L1_CACHE_SHIFT		5		/* shift for bytes per entry */
+#define L1_CACHE_WAYDISP	0x1000		/* distance from one way to the next */
+
+#define L1_CACHE_TAG_VALID	0x00000001	/* cache tag valid bit */
+#define L1_CACHE_TAG_DIRTY	0x00000008	/* data cache tag dirty bit */
+#define L1_CACHE_TAG_ENTRY	0x00000fe0	/* cache tag entry address mask */
+#define L1_CACHE_TAG_ADDRESS	0xfffff000	/* cache tag line address mask */
+#define L1_CACHE_TAG_MASK	+(L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY)
+
+/*
+ * specification of the interval between interrupt checking intervals whilst
+ * managing the cache with the interrupts disabled
+ */
+#define MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL	4
+
+/*
+ * The size of range at which it becomes more economical to just flush the
+ * whole cache rather than trying to flush the specified range.
+ */
+#define MN10300_DCACHE_FLUSH_BORDER \
+	+(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES)
+#define MN10300_DCACHE_FLUSH_INV_BORDER	\
+	+(L1_CACHE_NWAYS * L1_CACHE_NENTRIES * L1_CACHE_BYTES)
+
+#endif /* _ASM_PROC_CACHE_H */
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/clock.h b/arch/mn10300/proc-mn2ws0050/include/proc/clock.h
new file mode 100644
index 0000000..fe4c0a4
--- /dev/null
+++ b/arch/mn10300/proc-mn2ws0050/include/proc/clock.h
@@ -0,0 +1,20 @@
+/* clock.h: proc-specific clocks
+ *
+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * Modified by Matsushita Electric Industrial Co., Ltd.
+ * Modifications:
+ *  23-Feb-2007 MEI Delete define for watchdog timer.
+ *
+ * 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.
+ */
+#ifndef _ASM_PROC_CLOCK_H
+#define _ASM_PROC_CLOCK_H
+
+#include <unit/clock.h>
+
+#endif /* _ASM_PROC_CLOCK_H */
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h
new file mode 100644
index 0000000..4c4319e
--- /dev/null
+++ b/arch/mn10300/proc-mn2ws0050/include/proc/dmactl-regs.h
@@ -0,0 +1,103 @@
+/* MN2WS0050 on-board DMA controller registers
+ *
+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef _ASM_PROC_DMACTL_REGS_H
+#define _ASM_PROC_DMACTL_REGS_H
+
+#include <asm/cpu-regs.h>
+
+#ifdef __KERNEL__
+
+/* DMA registers */
+#define	DMxCTR(N)		__SYSREG(0xd4005000+(N*0x100), u32)	/* control reg */
+#define	DMxCTR_BG		0x0000001f	/* transfer request source */
+#define	DMxCTR_BG_SOFT		0x00000000	/* - software source */
+#define	DMxCTR_BG_SC0TX		0x00000002	/* - serial port 0 transmission */
+#define	DMxCTR_BG_SC0RX		0x00000003	/* - serial port 0 reception */
+#define	DMxCTR_BG_SC1TX		0x00000004	/* - serial port 1 transmission */
+#define	DMxCTR_BG_SC1RX		0x00000005	/* - serial port 1 reception */
+#define	DMxCTR_BG_SC2TX		0x00000006	/* - serial port 2 transmission */
+#define	DMxCTR_BG_SC2RX		0x00000007	/* - serial port 2 reception */
+#define	DMxCTR_BG_TM0UFLOW	0x00000008	/* - timer 0 underflow */
+#define	DMxCTR_BG_TM1UFLOW	0x00000009	/* - timer 1 underflow */
+#define	DMxCTR_BG_TM2UFLOW	0x0000000a	/* - timer 2 underflow */
+#define	DMxCTR_BG_TM3UFLOW	0x0000000b	/* - timer 3 underflow */
+#define	DMxCTR_BG_TM6ACMPCAP	0x0000000c	/* - timer 6A compare/capture */
+#define	DMxCTR_BG_RYBY		0x0000000d	/* - NAND Flash RY/BY request source */
+#define	DMxCTR_BG_RMC		0x0000000e	/* - remote controller output */
+#define	DMxCTR_BG_XIRQ12	0x00000011	/* - XIRQ12 pin interrupt source */
+#define	DMxCTR_BG_XIRQ13	0x00000012	/* - XIRQ13 pin interrupt source */
+#define	DMxCTR_BG_TCK		0x00000014	/* - tick timer underflow */
+#define	DMxCTR_BG_SC4TX		0x00000019	/* - serial port4 transmission */
+#define	DMxCTR_BG_SC4RX		0x0000001a	/* - serial port4 reception */
+#define	DMxCTR_BG_SC5TX		0x0000001b	/* - serial port5 transmission */
+#define	DMxCTR_BG_SC5RX		0x0000001c	/* - serial port5 reception */
+#define	DMxCTR_BG_SC6TX		0x0000001d	/* - serial port6 transmission */
+#define	DMxCTR_BG_SC6RX		0x0000001e	/* - serial port6 reception */
+#define	DMxCTR_BG_TMSUFLOW	0x0000001f	/* - timestamp timer underflow */
+#define	DMxCTR_SAM		0x00000060	/* DMA transfer src addr mode */
+#define	DMxCTR_SAM_INCR		0x00000000	/* - increment */
+#define	DMxCTR_SAM_DECR		0x00000020	/* - decrement */
+#define	DMxCTR_SAM_FIXED	0x00000040	/* - fixed */
+#define	DMxCTR_DAM		0x00000300	/* DMA transfer dest addr mode */
+#define	DMxCTR_DAM_INCR		0x00000000	/* - increment */
+#define	DMxCTR_DAM_DECR		0x00000100	/* - decrement */
+#define	DMxCTR_DAM_FIXED	0x00000200	/* - fixed */
+#define	DMxCTR_UT		0x00006000	/* DMA transfer unit */
+#define	DMxCTR_UT_1		0x00000000	/* - 1 byte */
+#define	DMxCTR_UT_2		0x00002000	/* - 2 byte */
+#define	DMxCTR_UT_4		0x00004000	/* - 4 byte */
+#define	DMxCTR_UT_16		0x00006000	/* - 16 byte */
+#define DMxCTR_RRE		0x00008000	/* DMA round robin enable */
+#define	DMxCTR_TEN		0x00010000	/* DMA channel transfer enable */
+#define	DMxCTR_RQM		0x00060000	/* external request input source mode */
+#define	DMxCTR_RQM_FALLEDGE	0x00000000	/* - falling edge */
+#define	DMxCTR_RQM_RISEEDGE	0x00020000	/* - rising edge */
+#define	DMxCTR_RQM_LOLEVEL	0x00040000	/* - low level */
+#define	DMxCTR_RQM_HILEVEL	0x00060000	/* - high level */
+#define	DMxCTR_RQF		0x01000000	/* DMA transfer request flag */
+#define	DMxCTR_PERR		0x40000000	/* DMA transfer parameter error flag */
+#define	DMxCTR_XEND		0x80000000	/* DMA transfer end flag */
+
+#define	DMxSRC(N)		__SYSREG(0xd4005004+(N*0x100), u32)	/* control reg */
+
+#define	DMxDST(N)		__SYSREG(0xd4005008+(N*0x100), u32)	/* source addr reg */
+
+#define	DMxSIZ(N)		__SYSREG(0xd400500c+(N*0x100), u32)	/* dest addr reg */
+#define DMxSIZ_CT		0x000fffff	/* number of bytes to transfer */
+
+#define	DMxCYC(N)		__SYSREG(0xd4005010+(N*0x100), u32)	/* intermittent size reg */
+#define DMxCYC_CYC		0x000000ff	/* number of interrmittent transfers -1 */
+
+#define DM0IRQ			16		/* DMA channel 0 complete IRQ */
+#define DM1IRQ			17		/* DMA channel 1 complete IRQ */
+#define DM2IRQ			18		/* DMA channel 2 complete IRQ */
+#define DM3IRQ			19		/* DMA channel 3 complete IRQ */
+
+#define	DM0ICR			GxICR(DM0IRQ)	/* DMA channel 0 complete intr ctrl reg */
+#define	DM1ICR			GxICR(DM0IR1)	/* DMA channel 1 complete intr ctrl reg */
+#define	DM2ICR			GxICR(DM0IR2)	/* DMA channel 2 complete intr ctrl reg */
+#define	DM3ICR			GxICR(DM0IR3)	/* DMA channel 3 complete intr ctrl reg */
+
+#ifndef __ASSEMBLY__
+
+struct mn10300_dmactl_regs {
+	u32		ctr;
+	const void	*src;
+	void		*dst;
+	u32		siz;
+	u32		cyc;
+} __attribute__((aligned(0x100)));
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_PROC_DMACTL_REGS_H */
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h
new file mode 100644
index 0000000..a1e9772
--- /dev/null
+++ b/arch/mn10300/proc-mn2ws0050/include/proc/intctl-regs.h
@@ -0,0 +1,29 @@
+#ifndef _ASM_PROC_INTCTL_REGS_H
+#define _ASM_PROC_INTCTL_REGS_H
+
+#ifndef _ASM_INTCTL_REGS_H
+# error "please don't include this file directly"
+#endif
+
+/* intr acceptance group reg */
+#define IAGR			__SYSREG(0xd4000100, u16)
+
+/* group number register */
+#define IAGR_GN			0x003fc
+
+#define __GET_XIRQ_TRIGGER(X, Z) (((Z) >> ((X) * 2)) & 3)
+
+#define __SET_XIRQ_TRIGGER(X, Y, Z)		\
+({						\
+	typeof(Z) x = (Z);			\
+	x &= ~(3 << ((X) * 2));			\
+	x |= ((Y) & 3) << ((X) * 2);		\
+	(Z) = x;				\
+})
+
+/* external pin intr spec reg */
+#define EXTMD0			__SYSREG(0xd4000200, u32)
+#define GET_XIRQ_TRIGGER(X)	__GET_XIRQ_TRIGGER(X, EXTMD0)
+#define SET_XIRQ_TRIGGER(X, Y)	__SET_XIRQ_TRIGGER(X, Y, EXTMD0)
+
+#endif /* _ASM_PROC_INTCTL_REGS_H */
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/irq.h b/arch/mn10300/proc-mn2ws0050/include/proc/irq.h
new file mode 100644
index 0000000..37777a8
--- /dev/null
+++ b/arch/mn10300/proc-mn2ws0050/include/proc/irq.h
@@ -0,0 +1,49 @@
+/* MN2WS0050 on-board interrupt controller registers
+ *
+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * Modified by Matsushita Electric Industrial Co., Ltd.
+ * Modifications:
+ *  13-Nov-2006 MEI Define extended IRQ number for SMP support.
+ *
+ * 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.
+ */
+
+#ifndef _PROC_IRQ_H
+#define _PROC_IRQ_H
+
+#ifdef __KERNEL__
+
+#define GxICR_NUM_IRQS		163
+#ifdef CONFIG_SMP
+#define GxICR_NUM_EXT_IRQS	197
+#endif  /* CONFIG_SMP */
+
+#define GxICR_NUM_XIRQS		16
+
+#define XIRQ0		34
+#define XIRQ1		35
+#define XIRQ2		36
+#define XIRQ3		37
+#define XIRQ4		38
+#define XIRQ5		39
+#define XIRQ6		40
+#define XIRQ7		41
+#define XIRQ8		42
+#define XIRQ9		43
+#define XIRQ10		44
+#define XIRQ11		45
+#define XIRQ12		46
+#define XIRQ13		47
+#define XIRQ14		48
+#define XIRQ15		49
+
+#define XIRQ2IRQ(num)	(XIRQ0 + num)
+
+#endif /* __KERNEL__ */
+
+#endif /* _PROC_IRQ_H */
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h
new file mode 100644
index 0000000..84448f3
--- /dev/null
+++ b/arch/mn10300/proc-mn2ws0050/include/proc/nand-regs.h
@@ -0,0 +1,120 @@
+/* NAND flash interface register definitions
+ *
+ * Copyright (C) 2008-2009 Panasonic Corporation
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+#ifndef	_PROC_NAND_REGS_H_
+#define	_PROC_NAND_REGS_H_
+
+/* command register */
+#define FCOMMAND_0		__SYSREG(0xd8f00000, u8) /* fcommand[24:31] */
+#define FCOMMAND_1		__SYSREG(0xd8f00001, u8) /* fcommand[16:23] */
+#define FCOMMAND_2		__SYSREG(0xd8f00002, u8) /* fcommand[8:15] */
+#define FCOMMAND_3		__SYSREG(0xd8f00003, u8) /* fcommand[0:7] */
+
+/* for dma 16 byte trans, use FCOMMAND2 register */
+#define FCOMMAND2_0		__SYSREG(0xd8f00110, u8) /* fcommand2[24:31] */
+#define FCOMMAND2_1		__SYSREG(0xd8f00111, u8) /* fcommand2[16:23] */
+#define FCOMMAND2_2		__SYSREG(0xd8f00112, u8) /* fcommand2[8:15] */
+#define FCOMMAND2_3		__SYSREG(0xd8f00113, u8) /* fcommand2[0:7] */
+
+#define FCOMMAND_FIEN		0x80		/* nand flash I/F enable */
+#define FCOMMAND_BW_8BIT	0x00		/* 8bit bus width */
+#define FCOMMAND_BW_16BIT	0x40		/* 16bit bus width */
+#define FCOMMAND_BLOCKSZ_SMALL	0x00		/* small block */
+#define FCOMMAND_BLOCKSZ_LARGE	0x20		/* large block */
+#define FCOMMAND_DMASTART	0x10		/* dma start */
+#define FCOMMAND_RYBY		0x08		/* ready/busy flag */
+#define FCOMMAND_RYBYINTMSK	0x04		/* mask ready/busy interrupt */
+#define FCOMMAND_XFWP		0x02		/* write protect enable */
+#define FCOMMAND_XFCE		0x01		/* flash device disable */
+#define FCOMMAND_SEQKILL	0x10		/* stop seq-read */
+#define FCOMMAND_ANUM		0x07		/* address cycle */
+#define FCOMMAND_ANUM_NONE	0x00		/* address cycle none */
+#define FCOMMAND_ANUM_1CYC	0x01		/* address cycle 1cycle */
+#define FCOMMAND_ANUM_2CYC	0x02		/* address cycle 2cycle */
+#define FCOMMAND_ANUM_3CYC	0x03		/* address cycle 3cycle */
+#define FCOMMAND_ANUM_4CYC	0x04		/* address cycle 4cycle */
+#define FCOMMAND_ANUM_5CYC	0x05		/* address cycle 5cycle */
+#define FCOMMAND_FCMD_READ0	0x00		/* read1 command */
+#define FCOMMAND_FCMD_SEQIN	0x80		/* page program 1st command */
+#define FCOMMAND_FCMD_PAGEPROG	0x10		/* page program 2nd command */
+#define FCOMMAND_FCMD_RESET	0xff		/* reset command */
+#define FCOMMAND_FCMD_ERASE1	0x60		/* erase 1st command */
+#define FCOMMAND_FCMD_ERASE2	0xd0		/* erase 2nd command */
+#define FCOMMAND_FCMD_STATUS	0x70		/* read status command */
+#define FCOMMAND_FCMD_READID	0x90		/* read id command */
+#define FCOMMAND_FCMD_READOOB	0x50		/* read3 command */
+/* address register */
+#define FADD			__SYSREG(0xd8f00004, u32)
+/* address register 2 */
+#define FADD2			__SYSREG(0xd8f00008, u32)
+/* error judgement register */
+#define FJUDGE			__SYSREG(0xd8f0000c, u32)
+#define FJUDGE_NOERR		0x0		/* no error */
+#define FJUDGE_1BITERR		0x1		/* 1bit error in data area */
+#define FJUDGE_PARITYERR	0x2		/* parity error */
+#define FJUDGE_UNCORRECTABLE	0x3		/* uncorrectable error */
+#define FJUDGE_ERRJDG_MSK	0x3		/* mask of judgement result */
+/* 1st ECC store register */
+#define FECC11			__SYSREG(0xd8f00010, u32)
+/* 2nd ECC store register */
+#define FECC12			__SYSREG(0xd8f00014, u32)
+/* 3rd ECC store register */
+#define FECC21			__SYSREG(0xd8f00018, u32)
+/* 4th ECC store register */
+#define FECC22			__SYSREG(0xd8f0001c, u32)
+/* 5th ECC store register */
+#define FECC31			__SYSREG(0xd8f00020, u32)
+/* 6th ECC store register */
+#define FECC32			__SYSREG(0xd8f00024, u32)
+/* 7th ECC store register */
+#define FECC41			__SYSREG(0xd8f00028, u32)
+/* 8th ECC store register */
+#define FECC42			__SYSREG(0xd8f0002c, u32)
+/* data register */
+#define FDATA			__SYSREG(0xd8f00030, u32)
+/* access pulse register */
+#define FPWS			__SYSREG(0xd8f00100, u32)
+#define FPWS_PWS1W_2CLK		0x00000000 /* write pulse width 1clock */
+#define FPWS_PWS1W_3CLK		0x01000000 /* write pulse width 2clock */
+#define FPWS_PWS1W_4CLK		0x02000000 /* write pulse width 4clock */
+#define FPWS_PWS1W_5CLK		0x03000000 /* write pulse width 5clock */
+#define FPWS_PWS1W_6CLK		0x04000000 /* write pulse width 6clock */
+#define FPWS_PWS1W_7CLK		0x05000000 /* write pulse width 7clock */
+#define FPWS_PWS1W_8CLK		0x06000000 /* write pulse width 8clock */
+#define FPWS_PWS1R_3CLK		0x00010000 /* read pulse width 3clock */
+#define FPWS_PWS1R_4CLK		0x00020000 /* read pulse width 4clock */
+#define FPWS_PWS1R_5CLK		0x00030000 /* read pulse width 5clock */
+#define FPWS_PWS1R_6CLK		0x00040000 /* read pulse width 6clock */
+#define FPWS_PWS1R_7CLK		0x00050000 /* read pulse width 7clock */
+#define FPWS_PWS1R_8CLK		0x00060000 /* read pulse width 8clock */
+#define FPWS_PWS2W_2CLK		0x00000100 /* write pulse interval 2clock */
+#define FPWS_PWS2W_3CLK		0x00000200 /* write pulse interval 3clock */
+#define FPWS_PWS2W_4CLK		0x00000300 /* write pulse interval 4clock */
+#define FPWS_PWS2W_5CLK		0x00000400 /* write pulse interval 5clock */
+#define FPWS_PWS2W_6CLK		0x00000500 /* write pulse interval 6clock */
+#define FPWS_PWS2R_2CLK		0x00000001 /* read pulse interval 2clock */
+#define FPWS_PWS2R_3CLK		0x00000002 /* read pulse interval 3clock */
+#define FPWS_PWS2R_4CLK		0x00000003 /* read pulse interval 4clock */
+#define FPWS_PWS2R_5CLK		0x00000004 /* read pulse interval 5clock */
+#define FPWS_PWS2R_6CLK		0x00000005 /* read pulse interval 6clock */
+/* command register 2 */
+#define FCOMMAND2		__SYSREG(0xd8f00110, u32)
+/* transfer frequency register */
+#define FNUM			__SYSREG(0xd8f00114, u32)
+#define FSDATA_ADDR		0xd8f00400
+/* active data register */
+#define FSDATA			__SYSREG(FSDATA_ADDR, u32)
+
+#endif /* _PROC_NAND_REGS_H_ */
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/proc.h b/arch/mn10300/proc-mn2ws0050/include/proc/proc.h
new file mode 100644
index 0000000..90d5cad
--- /dev/null
+++ b/arch/mn10300/proc-mn2ws0050/include/proc/proc.h
@@ -0,0 +1,18 @@
+/* proc.h: MN2WS0050 processor description
+ *
+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_PROC_PROC_H
+#define _ASM_PROC_PROC_H
+
+#define PROCESSOR_VENDOR_NAME	"Panasonic"
+#define PROCESSOR_MODEL_NAME	"mn2ws0050"
+
+#endif /* _ASM_PROC_PROC_H */
diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h b/arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h
new file mode 100644
index 0000000..22f277f
--- /dev/null
+++ b/arch/mn10300/proc-mn2ws0050/include/proc/smp-regs.h
@@ -0,0 +1,51 @@
+/* MN10300/AM33v2 Microcontroller SMP registers
+ *
+ * Copyright (C) 2006 Matsushita Electric Industrial Co., Ltd.
+ * All Rights Reserved.
+ * Created:
+ *  13-Nov-2006 MEI Add extended cache and atomic operation register
+ *                  for SMP support.
+ *  23-Feb-2007 MEI Add define for gdbstub SMP.
+ *
+ * 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.
+ */
+
+#ifndef _ASM_PROC_SMP_REGS_H
+#define _ASM_PROC_SMP_REGS_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#endif
+#include <asm/cpu-regs.h>
+
+/*
+ * Reference to the interrupt controllers of other CPUs
+ */
+#define CROSS_ICR_CPU_SHIFT	16
+
+#define CROSS_GxICR(X, CPU)	__SYSREG(0xc4000000 + (X) * 4 + \
+	((X) >= 64 && (X) < 192) * 0xf00 + ((CPU) << CROSS_ICR_CPU_SHIFT), u16)
+#define CROSS_GxICR_u8(X, CPU)	__SYSREG(0xc4000000 + (X) * 4 +		\
+	(((X) >= 64) && ((X) < 192)) * 0xf00 + ((CPU) << CROSS_ICR_CPU_SHIFT), u8)
+
+/* CPU ID register */
+#define CPUID		__SYSREGC(0xc0000054, u32)
+#define CPUID_MASK	0x00000007	/* CPU ID mask */
+
+/* extended cache control register */
+#define ECHCTR		__SYSREG(0xc0000c20, u32)
+#define ECHCTR_IBCM	0x00000001	/* instruction cache broad cast mask */
+#define ECHCTR_DBCM	0x00000002	/* data cache broad cast mask */
+#define ECHCTR_ISPM	0x00000004	/* instruction cache snoop mask */
+#define ECHCTR_DSPM	0x00000008	/* data cache snoop mask */
+
+#define NMIAGR		__SYSREG(0xd400013c, u16)
+#define NMIAGR_GN	0x03fc
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_PROC_SMP_REGS_H */
diff --git a/arch/mn10300/proc-mn2ws0050/proc-init.c b/arch/mn10300/proc-mn2ws0050/proc-init.c
new file mode 100644
index 0000000..ee6d03d
--- /dev/null
+++ b/arch/mn10300/proc-mn2ws0050/proc-init.c
@@ -0,0 +1,133 @@
+/* MN2WS0050 processor initialisation
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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/sched.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <linux/atomic.h>
+#include <asm/smp.h>
+#include <asm/pgalloc.h>
+#include <asm/busctl-regs.h>
+#include <unit/timex.h>
+#include <asm/fpu.h>
+#include <asm/rtc.h>
+
+#define MEMCONF __SYSREGC(0xdf800400, u32)
+
+/*
+ * initialise the on-silicon processor peripherals
+ */
+asmlinkage void __init processor_init(void)
+{
+	int loop;
+
+	/* set up the exception table first */
+	for (loop = 0x000; loop < 0x400; loop += 8)
+		__set_intr_stub(loop, __common_exception);
+
+	__set_intr_stub(EXCEP_ITLBMISS,		itlb_miss);
+	__set_intr_stub(EXCEP_DTLBMISS,		dtlb_miss);
+	__set_intr_stub(EXCEP_IAERROR,		itlb_aerror);
+	__set_intr_stub(EXCEP_DAERROR,		dtlb_aerror);
+	__set_intr_stub(EXCEP_BUSERROR,		raw_bus_error);
+	__set_intr_stub(EXCEP_DOUBLE_FAULT,	double_fault);
+	__set_intr_stub(EXCEP_FPU_DISABLED,	fpu_disabled);
+	__set_intr_stub(EXCEP_SYSCALL0,		system_call);
+
+	__set_intr_stub(EXCEP_NMI,		nmi_handler);
+	__set_intr_stub(EXCEP_WDT,		nmi_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL0,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL1,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL2,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL3,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL4,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL5,	irq_handler);
+	__set_intr_stub(EXCEP_IRQ_LEVEL6,	irq_handler);
+
+	IVAR0 = EXCEP_IRQ_LEVEL0;
+	IVAR1 = EXCEP_IRQ_LEVEL1;
+	IVAR2 = EXCEP_IRQ_LEVEL2;
+	IVAR3 = EXCEP_IRQ_LEVEL3;
+	IVAR4 = EXCEP_IRQ_LEVEL4;
+	IVAR5 = EXCEP_IRQ_LEVEL5;
+	IVAR6 = EXCEP_IRQ_LEVEL6;
+
+#ifndef CONFIG_MN10300_HAS_CACHE_SNOOP
+	mn10300_dcache_flush_inv();
+	mn10300_icache_inv();
+#endif
+
+	/* disable all interrupts and set to priority 6 (lowest) */
+#ifdef	CONFIG_SMP
+	for (loop = 0; loop < GxICR_NUM_IRQS; loop++)
+		GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
+#else	/* !CONFIG_SMP */
+	for (loop = 0; loop < NR_IRQS; loop++)
+		GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
+#endif	/* !CONFIG_SMP */
+
+	/* clear the timers */
+	TM0MD	= 0;
+	TM1MD	= 0;
+	TM2MD	= 0;
+	TM3MD	= 0;
+	TM4MD	= 0;
+	TM5MD	= 0;
+	TM6MD	= 0;
+	TM6MDA	= 0;
+	TM6MDB	= 0;
+	TM7MD	= 0;
+	TM8MD	= 0;
+	TM9MD	= 0;
+	TM10MD	= 0;
+	TM11MD	= 0;
+	TM12MD	= 0;
+	TM13MD	= 0;
+	TM14MD	= 0;
+	TM15MD	= 0;
+
+	calibrate_clock();
+}
+
+/*
+ * determine the memory size and base from the memory controller regs
+ */
+void __init get_mem_info(unsigned long *mem_base, unsigned long *mem_size)
+{
+	unsigned long memconf = MEMCONF;
+	unsigned long size = 0; /* order: MByte */
+
+	*mem_base = 0x90000000; /* fixed address */
+
+	switch (memconf & 0x00000003) {
+	case 0x01:
+		size = 256 / 8;		/* 256 Mbit per chip */
+		break;
+	case 0x02:
+		size = 512 / 8;		/* 512 Mbit per chip */
+		break;
+	case 0x03:
+		size = 1024 / 8;	/*   1 Gbit per chip */
+		break;
+	default:
+		panic("Invalid SDRAM size");
+		break;
+	}
+
+	printk(KERN_INFO "DDR2-SDRAM: %luMB x 2 @%08lx\n", size, *mem_base);
+
+	*mem_size = (size * 2) << 20;
+}
diff --git a/arch/mn10300/unit-asb2303/Makefile b/arch/mn10300/unit-asb2303/Makefile
new file mode 100644
index 0000000..38a5bb4
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/Makefile
@@ -0,0 +1,6 @@
+###############################################################################
+#
+# Makefile for the ASB2303 board
+#
+###############################################################################
+obj-y   := unit-init.o smc91111.o flash.o leds.o
diff --git a/arch/mn10300/unit-asb2303/flash.c b/arch/mn10300/unit-asb2303/flash.c
new file mode 100644
index 0000000..b03d873
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/flash.c
@@ -0,0 +1,99 @@
+/* Handle mapping of the flash on the ASB2303 board
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+#define ASB2303_PROM_ADDR	0xA0000000	/* Boot PROM */
+#define ASB2303_PROM_SIZE	(2 * 1024 * 1024)
+#define ASB2303_FLASH_ADDR	0xA4000000	/* System Flash */
+#define ASB2303_FLASH_SIZE	(32 * 1024 * 1024)
+#define ASB2303_CONFIG_ADDR	0xA6000000	/* System Config EEPROM */
+#define ASB2303_CONFIG_SIZE	(8 * 1024)
+
+/*
+ * default MTD partition table for both main flash devices, expected to be
+ * overridden by RedBoot
+ */
+static struct mtd_partition asb2303_partitions[] = {
+	{
+		.name		= "Bootloader",
+		.size		= 0x00040000,
+		.offset		= 0,
+		.mask_flags	= MTD_CAP_ROM /* force read-only */
+	}, {
+		.name		= "Kernel",
+		.size		= 0x00400000,
+		.offset		= 0x00040000,
+	}, {
+		.name		= "Filesystem",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= 0x00440000
+	}
+};
+
+/*
+ * the ASB2303 Boot PROM definition
+ */
+static struct physmap_flash_data asb2303_bootprom_data = {
+	.width		= 2,
+	.nr_parts	= 1,
+	.parts		= asb2303_partitions,
+};
+
+static struct resource asb2303_bootprom_resource = {
+	.start		= ASB2303_PROM_ADDR,
+	.end		= ASB2303_PROM_ADDR + ASB2303_PROM_SIZE,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device asb2303_bootprom = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev.platform_data = &asb2303_bootprom_data,
+	.num_resources	= 1,
+	.resource	= &asb2303_bootprom_resource,
+};
+
+/*
+ * the ASB2303 System Flash definition
+ */
+static struct physmap_flash_data asb2303_sysflash_data = {
+	.width		= 4,
+	.nr_parts	= 1,
+	.parts		= asb2303_partitions,
+};
+
+static struct resource asb2303_sysflash_resource = {
+	.start		= ASB2303_FLASH_ADDR,
+	.end		= ASB2303_FLASH_ADDR + ASB2303_FLASH_SIZE,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device asb2303_sysflash = {
+	.name		= "physmap-flash",
+	.id		= 1,
+	.dev.platform_data = &asb2303_sysflash_data,
+	.num_resources	= 1,
+	.resource	= &asb2303_sysflash_resource,
+};
+
+/*
+ * register the ASB2303 flashes
+ */
+static int __init asb2303_mtd_init(void)
+{
+	platform_device_register(&asb2303_bootprom);
+	platform_device_register(&asb2303_sysflash);
+	return 0;
+}
+device_initcall(asb2303_mtd_init);
diff --git a/arch/mn10300/unit-asb2303/include/unit/clock.h b/arch/mn10300/unit-asb2303/include/unit/clock.h
new file mode 100644
index 0000000..0316907
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/include/unit/clock.h
@@ -0,0 +1,24 @@
+/* ASB2303-specific clocks
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_UNIT_CLOCK_H
+#define _ASM_UNIT_CLOCK_H
+
+#ifndef __ASSEMBLY__
+
+#define MN10300_IOCLK		33333333UL
+/* #define MN10300_IOBCLK	66666666UL */
+
+#endif /* !__ASSEMBLY__ */
+
+#define MN10300_WDCLK		MN10300_IOCLK
+
+#endif /* _ASM_UNIT_CLOCK_H */
diff --git a/arch/mn10300/unit-asb2303/include/unit/leds.h b/arch/mn10300/unit-asb2303/include/unit/leds.h
new file mode 100644
index 0000000..3a7543e
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/include/unit/leds.h
@@ -0,0 +1,43 @@
+/* ASB2303-specific LEDs
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_UNIT_LEDS_H
+#define _ASM_UNIT_LEDS_H
+
+#include <asm/pio-regs.h>
+#include <asm/cpu-regs.h>
+#include <asm/exceptions.h>
+
+#define ASB2303_GPIO0DEF	__SYSREG(0xDB000000, u32)
+#define ASB2303_7SEGLEDS	__SYSREG(0xDB000008, u32)
+
+/*
+ * use the 7-segment LEDs to indicate states
+ */
+
+/* flip the 7-segment LEDs between "G" and "-" */
+#define mn10300_set_gdbleds(ONOFF)			\
+do {							\
+	ASB2303_7SEGLEDS = (ONOFF) ? 0x85 : 0x7f;	\
+} while (0)
+
+/* indicate double-fault by displaying "d" on the LEDs */
+#define mn10300_set_dbfleds			\
+	mov	0x43,d0			;	\
+	movbu	d0,(ASB2303_7SEGLEDS)
+
+#ifndef __ASSEMBLY__
+extern void peripheral_leds_display_exception(enum exception_code code);
+extern void peripheral_leds_led_chase(void);
+extern void debug_to_serial(const char *p, int n);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_UNIT_LEDS_H */
diff --git a/arch/mn10300/unit-asb2303/include/unit/serial.h b/arch/mn10300/unit-asb2303/include/unit/serial.h
new file mode 100644
index 0000000..991e356
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/include/unit/serial.h
@@ -0,0 +1,141 @@
+/* ASB2303-specific 8250 serial ports
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_UNIT_SERIAL_H
+#define _ASM_UNIT_SERIAL_H
+
+#include <asm/cpu-regs.h>
+#include <proc/irq.h>
+#include <linux/serial_reg.h>
+
+#define SERIAL_PORT0_BASE_ADDRESS	0xA6FB0000
+#define SERIAL_PORT1_BASE_ADDRESS	0xA6FC0000
+
+#define SERIAL_IRQ	XIRQ0	/* Dual serial (PC16552)	(Hi) */
+
+/*
+ * The ASB2303 has an 18.432 MHz clock the UART
+ */
+#define BASE_BAUD	(18432000 / 16)
+
+/*
+ * dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports
+ */
+#ifndef CONFIG_GDBSTUB_ON_TTYSx
+
+#define SERIAL_PORT_DFNS						\
+	{								\
+	.baud_base		= BASE_BAUD,				\
+	.irq			= SERIAL_IRQ,				\
+	.flags			= STD_COM_FLAGS,			\
+	.iomem_base		= (u8 *) SERIAL_PORT0_BASE_ADDRESS,	\
+	.iomem_reg_shift	= 2,					\
+	.io_type		= SERIAL_IO_MEM,			\
+	},								\
+	{								\
+	.baud_base		= BASE_BAUD,				\
+	.irq			= SERIAL_IRQ,				\
+	.flags			= STD_COM_FLAGS,			\
+	.iomem_base		= (u8 *) SERIAL_PORT1_BASE_ADDRESS,	\
+	.iomem_reg_shift	= 2,					\
+	.io_type		= SERIAL_IO_MEM,			\
+	},
+
+#ifndef __ASSEMBLY__
+
+static inline void __debug_to_serial(const char *p, int n)
+{
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#else /* CONFIG_GDBSTUB_ON_TTYSx */
+
+#define SERIAL_PORT_DFNS /* both stolen by gdb-stub because they share an IRQ */
+
+#if defined(CONFIG_GDBSTUB_ON_TTYS0)
+#define GDBPORT_SERIAL_RX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX  * 4, u8)
+#define GDBPORT_SERIAL_TX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX  * 4, u8)
+#define GDBPORT_SERIAL_DLL	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 4, u8)
+#define GDBPORT_SERIAL_DLM	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 4, u8)
+#define GDBPORT_SERIAL_IER	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 4, u8)
+#define GDBPORT_SERIAL_IIR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 4, u8)
+#define GDBPORT_SERIAL_FCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 4, u8)
+#define GDBPORT_SERIAL_LCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 4, u8)
+#define GDBPORT_SERIAL_MCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 4, u8)
+#define GDBPORT_SERIAL_LSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 4, u8)
+#define GDBPORT_SERIAL_MSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 4, u8)
+#define GDBPORT_SERIAL_SCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 4, u8)
+#define GDBPORT_SERIAL_IRQ	SERIAL_IRQ
+
+#elif defined(CONFIG_GDBSTUB_ON_TTYS1)
+#define GDBPORT_SERIAL_RX	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_RX  * 4, u8)
+#define GDBPORT_SERIAL_TX	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_TX  * 4, u8)
+#define GDBPORT_SERIAL_DLL	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_DLL * 4, u8)
+#define GDBPORT_SERIAL_DLM	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_DLM * 4, u8)
+#define GDBPORT_SERIAL_IER	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_IER * 4, u8)
+#define GDBPORT_SERIAL_IIR	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_IIR * 4, u8)
+#define GDBPORT_SERIAL_FCR	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_FCR * 4, u8)
+#define GDBPORT_SERIAL_LCR	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_LCR * 4, u8)
+#define GDBPORT_SERIAL_MCR	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_MCR * 4, u8)
+#define GDBPORT_SERIAL_LSR	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_LSR * 4, u8)
+#define GDBPORT_SERIAL_MSR	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_MSR * 4, u8)
+#define GDBPORT_SERIAL_SCR	__SYSREG(SERIAL_PORT1_BASE_ADDRESS + UART_SCR * 4, u8)
+#define GDBPORT_SERIAL_IRQ	SERIAL_IRQ
+#endif
+
+#ifndef __ASSEMBLY__
+
+#define LSR_WAIT_FOR(STATE)					\
+do {								\
+	while (!(GDBPORT_SERIAL_LSR & UART_LSR_##STATE)) {}	\
+} while (0)
+#define FLOWCTL_WAIT_FOR(LINE)					\
+do {								\
+	while (!(GDBPORT_SERIAL_MSR & UART_MSR_##LINE)) {}	\
+} while (0)
+#define FLOWCTL_CLEAR(LINE)			\
+do {						\
+	GDBPORT_SERIAL_MCR &= ~UART_MCR_##LINE;	\
+} while (0)
+#define FLOWCTL_SET(LINE)			\
+do {						\
+	GDBPORT_SERIAL_MCR |= UART_MCR_##LINE;	\
+} while (0)
+#define FLOWCTL_QUERY(LINE)	({ GDBPORT_SERIAL_MSR & UART_MSR_##LINE; })
+
+static inline void __debug_to_serial(const char *p, int n)
+{
+	char ch;
+
+	FLOWCTL_SET(DTR);
+
+	for (; n > 0; n--) {
+		LSR_WAIT_FOR(THRE);
+		FLOWCTL_WAIT_FOR(CTS);
+
+		ch = *p++;
+		if (ch == 0x0a) {
+			GDBPORT_SERIAL_TX = 0x0d;
+			LSR_WAIT_FOR(THRE);
+			FLOWCTL_WAIT_FOR(CTS);
+		}
+		GDBPORT_SERIAL_TX = ch;
+	}
+
+	FLOWCTL_CLEAR(DTR);
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* CONFIG_GDBSTUB_ON_TTYSx */
+
+#endif /* _ASM_UNIT_SERIAL_H */
diff --git a/arch/mn10300/unit-asb2303/include/unit/smc91111.h b/arch/mn10300/unit-asb2303/include/unit/smc91111.h
new file mode 100644
index 0000000..dd456e9
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/include/unit/smc91111.h
@@ -0,0 +1,50 @@
+/* Support for the SMC91C111 NIC on an ASB2303
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_UNIT_SMC91111_H
+#define _ASM_UNIT_SMC91111_H
+
+#include <asm/intctl-regs.h>
+
+#define SMC91111_BASE		0xAA000300UL
+#define SMC91111_BASE_END	0xAA000400UL
+#define SMC91111_IRQ		XIRQ3
+
+#define SMC_CAN_USE_8BIT	0
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	0
+#define SMC_NOWAIT		1
+#define SMC_IRQ_FLAGS		(0)
+
+#if SMC_CAN_USE_8BIT
+#define SMC_inb(a, r)		inb((unsigned long) ((a) + (r)))
+#define SMC_outb(v, a, r)	outb(v, (unsigned long) ((a) + (r)))
+#endif
+
+#if SMC_CAN_USE_16BIT
+#define SMC_inw(a, r)		inw((unsigned long) ((a) + (r)))
+#define SMC_outw(v, a, r)	outw(v, (unsigned long) ((a) + (r)))
+#define SMC_insw(a, r, p, l)	insw((unsigned long) ((a) + (r)), (p), (l))
+#define SMC_outsw(a, r, p, l)	outsw((unsigned long) ((a) + (r)), (p), (l))
+#endif
+
+#if SMC_CAN_USE_32BIT
+#define SMC_inl(a, r)		inl((unsigned long) ((a) + (r)))
+#define SMC_outl(v, a, r)	outl(v, (unsigned long) ((a) + (r)))
+#define SMC_insl(a, r, p, l)	insl((unsigned long) ((a) + (r)), (p), (l))
+#define SMC_outsl(a, r, p, l)	outsl((unsigned long) ((a) + (r)), (p), (l))
+#endif
+
+#define RPC_LSA_DEFAULT		RPC_LED_100_10
+#define RPC_LSB_DEFAULT		RPC_LED_TX_RX
+
+#define set_irq_type(irq, type)
+
+#endif /*  _ASM_UNIT_SMC91111_H */
diff --git a/arch/mn10300/unit-asb2303/include/unit/timex.h b/arch/mn10300/unit-asb2303/include/unit/timex.h
new file mode 100644
index 0000000..c37f983
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/include/unit/timex.h
@@ -0,0 +1,146 @@
+/* ASB2303-specific timer specifications
+ *
+ * Copyright (C) 2007, 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_UNIT_TIMEX_H
+#define _ASM_UNIT_TIMEX_H
+
+#include <asm/timer-regs.h>
+#include <unit/clock.h>
+#include <asm/param.h>
+
+/*
+ * jiffies counter specifications
+ */
+
+#define	TMJCBR_MAX		0xffff
+#define	TMJCIRQ			TM1IRQ
+#define	TMJCICR			TM1ICR
+
+#ifndef __ASSEMBLY__
+
+#define MN10300_SRC_IOCLK	MN10300_IOCLK
+
+#ifndef HZ
+# error HZ undeclared.
+#endif /* !HZ */
+/* use as little prescaling as possible to avoid losing accuracy */
+#if (MN10300_SRC_IOCLK + HZ / 2) / HZ - 1 <= TMJCBR_MAX
+# define IOCLK_PRESCALE		1
+# define JC_TIMER_CLKSRC	TM0MD_SRC_IOCLK
+# define TSC_TIMER_CLKSRC	TM4MD_SRC_IOCLK
+#elif (MN10300_SRC_IOCLK / 8 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
+# define IOCLK_PRESCALE		8
+# define JC_TIMER_CLKSRC	TM0MD_SRC_IOCLK_8
+# define TSC_TIMER_CLKSRC	TM4MD_SRC_IOCLK_8
+#elif (MN10300_SRC_IOCLK / 32 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
+# define IOCLK_PRESCALE		32
+# define JC_TIMER_CLKSRC	TM0MD_SRC_IOCLK_32
+# define TSC_TIMER_CLKSRC	TM4MD_SRC_IOCLK_32
+#else
+# error You lose.
+#endif
+
+#define MN10300_JCCLK		(MN10300_SRC_IOCLK / IOCLK_PRESCALE)
+#define MN10300_TSCCLK		(MN10300_SRC_IOCLK / IOCLK_PRESCALE)
+
+#define MN10300_JC_PER_HZ	((MN10300_JCCLK + HZ / 2) / HZ)
+#define MN10300_TSC_PER_HZ	((MN10300_TSCCLK + HZ / 2) / HZ)
+
+static inline void stop_jiffies_counter(void)
+{
+	u16 tmp;
+	TM01MD = JC_TIMER_CLKSRC | TM1MD_SRC_TM0CASCADE << 8;
+	tmp = TM01MD;
+}
+
+static inline void reload_jiffies_counter(u32 cnt)
+{
+	u32 tmp;
+
+	TM01BR = cnt;
+	tmp = TM01BR;
+
+	TM01MD = JC_TIMER_CLKSRC |		\
+		 TM1MD_SRC_TM0CASCADE << 8 |	\
+		 TM0MD_INIT_COUNTER |		\
+		 TM1MD_INIT_COUNTER << 8;
+
+
+	TM01MD = JC_TIMER_CLKSRC |		\
+		 TM1MD_SRC_TM0CASCADE << 8 |	\
+		 TM0MD_COUNT_ENABLE |		\
+		 TM1MD_COUNT_ENABLE << 8;
+
+	tmp = TM01MD;
+}
+
+#endif /* !__ASSEMBLY__ */
+
+
+/*
+ * timestamp counter specifications
+ */
+
+#define	TMTSCBR_MAX		0xffffffff
+#define	TMTSCBC			TM45BC
+
+#ifndef __ASSEMBLY__
+
+static inline void startup_timestamp_counter(void)
+{
+	u32 t32;
+
+	/* set up timer 4 & 5 cascaded as a 32-bit counter to count real time
+	 * - count down from 4Gig-1 to 0 and wrap at IOCLK rate
+	 */
+	TM45BR = TMTSCBR_MAX;
+	t32 = TM45BR;
+
+	TM4MD = TSC_TIMER_CLKSRC;
+	TM4MD |= TM4MD_INIT_COUNTER;
+	TM4MD &= ~TM4MD_INIT_COUNTER;
+	TM4ICR = 0;
+	t32 = TM4ICR;
+
+	TM5MD = TM5MD_SRC_TM4CASCADE;
+	TM5MD |= TM5MD_INIT_COUNTER;
+	TM5MD &= ~TM5MD_INIT_COUNTER;
+	TM5ICR = 0;
+	t32 = TM5ICR;
+
+	TM5MD |= TM5MD_COUNT_ENABLE;
+	TM4MD |= TM4MD_COUNT_ENABLE;
+	t32 = TM5MD;
+	t32 = TM4MD;
+}
+
+static inline void shutdown_timestamp_counter(void)
+{
+	u8 t8;
+	TM4MD = 0;
+	TM5MD = 0;
+	t8 = TM4MD;
+	t8 = TM5MD;
+}
+
+/*
+ * we use a cascaded pair of 16-bit down-counting timers to count I/O
+ * clock cycles for the purposes of time keeping
+ */
+typedef unsigned long cycles_t;
+
+static inline cycles_t read_timestamp_counter(void)
+{
+	return (cycles_t)~TMTSCBC;
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_UNIT_TIMEX_H */
diff --git a/arch/mn10300/unit-asb2303/leds.c b/arch/mn10300/unit-asb2303/leds.c
new file mode 100644
index 0000000..c038393
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/leds.c
@@ -0,0 +1,52 @@
+/* ASB2303 peripheral 7-segment LEDs x1 support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/intctl-regs.h>
+#include <asm/rtc-regs.h>
+#include <unit/leds.h>
+
+#if 0
+static const u8 asb2303_led_hex_tbl[16] = {
+	0x80, 0xf2, 0x48, 0x60, 0x32, 0x24, 0x04, 0xf0,
+	0x00, 0x20, 0x10, 0x06, 0x8c, 0x42, 0x0c, 0x1c
+};
+#endif
+
+static const u8 asb2303_led_chase_tbl[6] = {
+	~0x02,	/* top		- segA */
+	~0x04,	/* right top	- segB */
+	~0x08,	/* right bottom	- segC */
+	~0x10,	/* bottom	- segD */
+	~0x20,	/* left bottom	- segE */
+	~0x40,	/* left top	- segF */
+};
+
+static unsigned asb2303_led_chase;
+
+void peripheral_leds_display_exception(enum exception_code code)
+{
+	ASB2303_GPIO0DEF = 0x5555;	/* configure as an output port */
+	ASB2303_7SEGLEDS = 0x6d;	/* triple horizontal bar */
+}
+
+void peripheral_leds_led_chase(void)
+{
+	ASB2303_GPIO0DEF = 0x5555;	/* configure as an output port */
+	ASB2303_7SEGLEDS = asb2303_led_chase_tbl[asb2303_led_chase];
+	asb2303_led_chase++;
+	if (asb2303_led_chase >= 6)
+		asb2303_led_chase = 0;
+}
diff --git a/arch/mn10300/unit-asb2303/smc91111.c b/arch/mn10300/unit-asb2303/smc91111.c
new file mode 100644
index 0000000..5367769
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/smc91111.c
@@ -0,0 +1,53 @@
+/* ASB2303 initialisation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/timex.h>
+#include <asm/processor.h>
+#include <asm/intctl-regs.h>
+#include <unit/smc91111.h>
+
+static struct resource smc91c111_resources[] = {
+	[0] = {
+		.start		= SMC91111_BASE,
+		.end		= SMC91111_BASE_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= SMC91111_IRQ,
+		.end		= SMC91111_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smc91c111_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(smc91c111_resources),
+	.resource	= smc91c111_resources,
+};
+
+/*
+ * add platform devices
+ */
+static int __init unit_device_init(void)
+{
+	platform_device_register(&smc91c111_device);
+	return 0;
+}
+
+device_initcall(unit_device_init);
diff --git a/arch/mn10300/unit-asb2303/unit-init.c b/arch/mn10300/unit-asb2303/unit-init.c
new file mode 100644
index 0000000..834a76a
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/unit-init.c
@@ -0,0 +1,68 @@
+/* ASB2303 initialisation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <asm/intctl-regs.h>
+
+/*
+ * initialise some of the unit hardware before gdbstub is set up
+ */
+asmlinkage void __init unit_init(void)
+{
+	/* set up the external interrupts */
+	SET_XIRQ_TRIGGER(0, XIRQ_TRIGGER_HILEVEL);
+	SET_XIRQ_TRIGGER(2, XIRQ_TRIGGER_LOWLEVEL);
+	SET_XIRQ_TRIGGER(3, XIRQ_TRIGGER_HILEVEL);
+	SET_XIRQ_TRIGGER(4, XIRQ_TRIGGER_LOWLEVEL);
+	SET_XIRQ_TRIGGER(5, XIRQ_TRIGGER_LOWLEVEL);
+
+#ifdef CONFIG_EXT_SERIAL_IRQ_LEVEL
+	set_intr_level(XIRQ0, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL));
+#endif
+
+#ifdef CONFIG_ETHERNET_IRQ_LEVEL
+	set_intr_level(XIRQ3, NUM2GxICR_LEVEL(CONFIG_ETHERNET_IRQ_LEVEL));
+#endif
+}
+
+/*
+ * initialise the rest of the unit hardware after gdbstub is ready
+ */
+void __init unit_setup(void)
+{
+}
+
+/*
+ * initialise the external interrupts used by a unit of this type
+ */
+void __init unit_init_IRQ(void)
+{
+	unsigned int extnum;
+
+	for (extnum = 0; extnum < NR_XIRQS; extnum++) {
+		switch (GET_XIRQ_TRIGGER(extnum)) {
+		case XIRQ_TRIGGER_HILEVEL:
+		case XIRQ_TRIGGER_LOWLEVEL:
+			mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum));
+			break;
+		default:
+			break;
+		}
+	}
+}
diff --git a/arch/mn10300/unit-asb2305/Makefile b/arch/mn10300/unit-asb2305/Makefile
new file mode 100644
index 0000000..cbc5aba
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/Makefile
@@ -0,0 +1,8 @@
+###############################################################################
+#
+# Makefile for the ASB2305 board
+#
+###############################################################################
+obj-y   := unit-init.o leds.o
+
+obj-$(CONFIG_PCI) += pci.o pci-asb2305.o pci-irq.o
diff --git a/arch/mn10300/unit-asb2305/include/unit/clock.h b/arch/mn10300/unit-asb2305/include/unit/clock.h
new file mode 100644
index 0000000..29e3425
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/include/unit/clock.h
@@ -0,0 +1,24 @@
+/* ASB2305-specific clocks
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_UNIT_CLOCK_H
+#define _ASM_UNIT_CLOCK_H
+
+#ifndef __ASSEMBLY__
+
+#define MN10300_IOCLK		33333333UL
+/* #define MN10300_IOBCLK	66666666UL */
+
+#endif /* !__ASSEMBLY__ */
+
+#define MN10300_WDCLK		MN10300_IOCLK
+
+#endif /* _ASM_UNIT_CLOCK_H */
diff --git a/arch/mn10300/unit-asb2305/include/unit/leds.h b/arch/mn10300/unit-asb2305/include/unit/leds.h
new file mode 100644
index 0000000..bc471f6
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/include/unit/leds.h
@@ -0,0 +1,51 @@
+/* ASB2305-specific LEDs
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_UNIT_LEDS_H
+#define _ASM_UNIT_LEDS_H
+
+#include <asm/pio-regs.h>
+#include <asm/cpu-regs.h>
+#include <asm/exceptions.h>
+
+#define ASB2305_7SEGLEDS	__SYSREG(0xA6F90000, u32)
+
+/* perform a hard reset by driving PIO06 low */
+#define mn10300_unit_hard_reset()		\
+do {						\
+	P0OUT &= 0xbf;				\
+	P0MD = (P0MD & P0MD_6) | P0MD_6_OUT;	\
+} while (0)
+
+/*
+ * use the 7-segment LEDs to indicate states
+ */
+/* indicate double-fault by displaying "db-f" on the LEDs */
+#define mn10300_set_dbfleds			\
+	mov	0x43077f1d,d0		;	\
+	mov	d0,(ASB2305_7SEGLEDS)
+
+/* flip the 7-segment LEDs between "Gdb-" and "----" */
+#define mn10300_set_gdbleds(ONOFF)				\
+do {								\
+	ASB2305_7SEGLEDS = (ONOFF) ? 0x8543077f : 0x7f7f7f7f;	\
+} while (0)
+
+#ifndef __ASSEMBLY__
+extern void peripheral_leds_display_exception(enum exception_code);
+extern void peripheral_leds_led_chase(void);
+extern void peripheral_leds7x4_display_dec(unsigned int, unsigned int);
+extern void peripheral_leds7x4_display_hex(unsigned int, unsigned int);
+extern void peripheral_leds7x4_display_minssecs(unsigned int, unsigned int);
+extern void peripheral_leds7x4_display_rtc(void);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_UNIT_LEDS_H */
diff --git a/arch/mn10300/unit-asb2305/include/unit/serial.h b/arch/mn10300/unit-asb2305/include/unit/serial.h
new file mode 100644
index 0000000..88c0821
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/include/unit/serial.h
@@ -0,0 +1,125 @@
+/* ASB2305-specific 8250 serial ports
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_UNIT_SERIAL_H
+#define _ASM_UNIT_SERIAL_H
+
+#include <asm/cpu-regs.h>
+#include <proc/irq.h>
+#include <linux/serial_reg.h>
+
+#define SERIAL_PORT0_BASE_ADDRESS	0xA6FB0000
+#define ASB2305_DEBUG_MCR	__SYSREG(0xA6FB0000 + UART_MCR * 2, u8)
+
+#define SERIAL_IRQ	XIRQ0	/* Dual serial (PC16552)	(Hi) */
+
+/*
+ * The ASB2305 has an 18.432 MHz clock the UART
+ */
+#define BASE_BAUD	(18432000 / 16)
+
+/*
+ * dispose of the /dev/ttyS0 serial port
+ */
+#ifndef CONFIG_GDBSTUB_ON_TTYSx
+
+#define SERIAL_PORT_DFNS						\
+	{								\
+	.baud_base		= BASE_BAUD,				\
+	.irq			= SERIAL_IRQ,				\
+	.flags			= STD_COM_FLAGS,			\
+	.iomem_base		= (u8 *) SERIAL_PORT0_BASE_ADDRESS,	\
+	.iomem_reg_shift	= 2,					\
+	.io_type		= SERIAL_IO_MEM,			\
+	},
+
+#ifndef __ASSEMBLY__
+
+static inline void __debug_to_serial(const char *p, int n)
+{
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#else /* CONFIG_GDBSTUB_ON_TTYSx */
+
+#define SERIAL_PORT_DFNS /* stolen by gdb-stub */
+
+#if defined(CONFIG_GDBSTUB_ON_TTYS0)
+#define GDBPORT_SERIAL_RX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX  * 4, u8)
+#define GDBPORT_SERIAL_TX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX  * 4, u8)
+#define GDBPORT_SERIAL_DLL	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 4, u8)
+#define GDBPORT_SERIAL_DLM	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 4, u8)
+#define GDBPORT_SERIAL_IER	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 4, u8)
+#define GDBPORT_SERIAL_IIR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 4, u8)
+#define GDBPORT_SERIAL_FCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 4, u8)
+#define GDBPORT_SERIAL_LCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 4, u8)
+#define GDBPORT_SERIAL_MCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 4, u8)
+#define GDBPORT_SERIAL_LSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 4, u8)
+#define GDBPORT_SERIAL_MSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 4, u8)
+#define GDBPORT_SERIAL_SCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 4, u8)
+#define GDBPORT_SERIAL_IRQ	SERIAL_IRQ
+
+#elif defined(CONFIG_GDBSTUB_ON_TTYS1)
+#error The ASB2305 doesnt have a /dev/ttyS1
+#endif
+
+#ifndef __ASSEMBLY__
+
+#define TTYS0_TX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX  * 4, u8)
+#define TTYS0_MCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 4, u8)
+#define TTYS0_LSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 4, u8)
+#define TTYS0_MSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 4, u8)
+
+#define LSR_WAIT_FOR(STATE)				\
+do {							\
+	while (!(TTYS0_LSR & UART_LSR_##STATE)) {}	\
+} while (0)
+#define FLOWCTL_WAIT_FOR(LINE)				\
+do {							\
+	while (!(TTYS0_MSR & UART_MSR_##LINE)) {}	\
+} while (0)
+#define FLOWCTL_CLEAR(LINE)			\
+do {						\
+	TTYS0_MCR &= ~UART_MCR_##LINE;		\
+} while (0)
+#define FLOWCTL_SET(LINE)			\
+do {						\
+	TTYS0_MCR |= UART_MCR_##LINE;		\
+} while (0)
+#define FLOWCTL_QUERY(LINE)	({ TTYS0_MSR & UART_MSR_##LINE; })
+
+static inline void __debug_to_serial(const char *p, int n)
+{
+	char ch;
+
+	FLOWCTL_SET(DTR);
+
+	for (; n > 0; n--) {
+		LSR_WAIT_FOR(THRE);
+		FLOWCTL_WAIT_FOR(CTS);
+
+		ch = *p++;
+		if (ch == 0x0a) {
+			TTYS0_TX = 0x0d;
+			LSR_WAIT_FOR(THRE);
+			FLOWCTL_WAIT_FOR(CTS);
+		}
+		TTYS0_TX = ch;
+	}
+
+	FLOWCTL_CLEAR(DTR);
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* CONFIG_GDBSTUB_ON_TTYSx */
+
+#endif /* _ASM_UNIT_SERIAL_H */
diff --git a/arch/mn10300/unit-asb2305/include/unit/timex.h b/arch/mn10300/unit-asb2305/include/unit/timex.h
new file mode 100644
index 0000000..4cefc22
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/include/unit/timex.h
@@ -0,0 +1,146 @@
+/* ASB2305-specific timer specifications
+ *
+ * Copyright (C) 2007, 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_UNIT_TIMEX_H
+#define _ASM_UNIT_TIMEX_H
+
+#include <asm/timer-regs.h>
+#include <unit/clock.h>
+#include <asm/param.h>
+
+/*
+ * jiffies counter specifications
+ */
+
+#define	TMJCBR_MAX		0xffff
+#define	TMJCIRQ			TM1IRQ
+#define	TMJCICR			TM1ICR
+
+#ifndef __ASSEMBLY__
+
+#define MN10300_SRC_IOCLK	MN10300_IOCLK
+
+#ifndef HZ
+# error HZ undeclared.
+#endif /* !HZ */
+/* use as little prescaling as possible to avoid losing accuracy */
+#if (MN10300_SRC_IOCLK + HZ / 2) / HZ - 1 <= TMJCBR_MAX
+# define IOCLK_PRESCALE		1
+# define JC_TIMER_CLKSRC	TM0MD_SRC_IOCLK
+# define TSC_TIMER_CLKSRC	TM4MD_SRC_IOCLK
+#elif (MN10300_SRC_IOCLK / 8 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
+# define IOCLK_PRESCALE		8
+# define JC_TIMER_CLKSRC	TM0MD_SRC_IOCLK_8
+# define TSC_TIMER_CLKSRC	TM4MD_SRC_IOCLK_8
+#elif (MN10300_SRC_IOCLK / 32 + HZ / 2) / HZ - 1 <= TMJCBR_MAX
+# define IOCLK_PRESCALE		32
+# define JC_TIMER_CLKSRC	TM0MD_SRC_IOCLK_32
+# define TSC_TIMER_CLKSRC	TM4MD_SRC_IOCLK_32
+#else
+# error You lose.
+#endif
+
+#define MN10300_JCCLK		(MN10300_SRC_IOCLK / IOCLK_PRESCALE)
+#define MN10300_TSCCLK		(MN10300_SRC_IOCLK / IOCLK_PRESCALE)
+
+#define MN10300_JC_PER_HZ	((MN10300_JCCLK + HZ / 2) / HZ)
+#define MN10300_TSC_PER_HZ	((MN10300_TSCCLK + HZ / 2) / HZ)
+
+static inline void stop_jiffies_counter(void)
+{
+	u16 tmp;
+	TM01MD = JC_TIMER_CLKSRC | TM1MD_SRC_TM0CASCADE << 8;
+	tmp = TM01MD;
+}
+
+static inline void reload_jiffies_counter(u32 cnt)
+{
+	u32 tmp;
+
+	TM01BR = cnt;
+	tmp = TM01BR;
+
+	TM01MD = JC_TIMER_CLKSRC |		\
+		 TM1MD_SRC_TM0CASCADE << 8 |	\
+		 TM0MD_INIT_COUNTER |		\
+		 TM1MD_INIT_COUNTER << 8;
+
+
+	TM01MD = JC_TIMER_CLKSRC |		\
+		 TM1MD_SRC_TM0CASCADE << 8 |	\
+		 TM0MD_COUNT_ENABLE |		\
+		 TM1MD_COUNT_ENABLE << 8;
+
+	tmp = TM01MD;
+}
+
+#endif /* !__ASSEMBLY__ */
+
+
+/*
+ * timestamp counter specifications
+ */
+
+#define	TMTSCBR_MAX		0xffffffff
+#define	TMTSCBC			TM45BC
+
+#ifndef __ASSEMBLY__
+
+static inline void startup_timestamp_counter(void)
+{
+	u32 t32;
+
+	/* set up timer 4 & 5 cascaded as a 32-bit counter to count real time
+	 * - count down from 4Gig-1 to 0 and wrap at IOCLK rate
+	 */
+	TM45BR = TMTSCBR_MAX;
+	t32 = TM45BR;
+
+	TM4MD = TSC_TIMER_CLKSRC;
+	TM4MD |= TM4MD_INIT_COUNTER;
+	TM4MD &= ~TM4MD_INIT_COUNTER;
+	TM4ICR = 0;
+	t32 = TM4ICR;
+
+	TM5MD = TM5MD_SRC_TM4CASCADE;
+	TM5MD |= TM5MD_INIT_COUNTER;
+	TM5MD &= ~TM5MD_INIT_COUNTER;
+	TM5ICR = 0;
+	t32 = TM5ICR;
+
+	TM5MD |= TM5MD_COUNT_ENABLE;
+	TM4MD |= TM4MD_COUNT_ENABLE;
+	t32 = TM5MD;
+	t32 = TM4MD;
+}
+
+static inline void shutdown_timestamp_counter(void)
+{
+	u8 t8;
+	TM4MD = 0;
+	TM5MD = 0;
+	t8 = TM4MD;
+	t8 = TM5MD;
+}
+
+/*
+ * we use a cascaded pair of 16-bit down-counting timers to count I/O
+ * clock cycles for the purposes of time keeping
+ */
+typedef unsigned long cycles_t;
+
+static inline cycles_t read_timestamp_counter(void)
+{
+	return (cycles_t)~TMTSCBC;
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_UNIT_TIMEX_H */
diff --git a/arch/mn10300/unit-asb2305/leds.c b/arch/mn10300/unit-asb2305/leds.c
new file mode 100644
index 0000000..6f8de99
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/leds.c
@@ -0,0 +1,124 @@
+/* ASB2305 Peripheral 7-segment LEDs x4 support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/intctl-regs.h>
+#include <asm/rtc-regs.h>
+#include <unit/leds.h>
+
+static const u8 asb2305_led_hex_tbl[16] = {
+	0x80, 0xf2, 0x48, 0x60, 0x32, 0x24, 0x04, 0xf0,
+	0x00, 0x20, 0x10, 0x06, 0x8c, 0x42, 0x0c, 0x1c
+};
+
+static const u32 asb2305_led_chase_tbl[6] = {
+	~0x02020202,	/* top		- segA */
+	~0x04040404,	/* right top	- segB */
+	~0x08080808,	/* right bottom	- segC */
+	~0x10101010,	/* bottom	- segD */
+	~0x20202020,	/* left bottom	- segE */
+	~0x40404040,	/* left top	- segF */
+};
+
+static unsigned asb2305_led_chase;
+
+void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points)
+{
+	u32 leds;
+
+	leds = asb2305_led_hex_tbl[(val/1000) % 10];
+	leds <<= 8;
+	leds |= asb2305_led_hex_tbl[(val/100) % 10];
+	leds <<= 8;
+	leds |= asb2305_led_hex_tbl[(val/10) % 10];
+	leds <<= 8;
+	leds |= asb2305_led_hex_tbl[val % 10];
+	leds |= points^0x01010101;
+
+	ASB2305_7SEGLEDS = leds;
+}
+
+void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points)
+{
+	u32 leds;
+
+	leds = asb2305_led_hex_tbl[(val/1000) % 10];
+	leds <<= 8;
+	leds |= asb2305_led_hex_tbl[(val/100) % 10];
+	leds <<= 8;
+	leds |= asb2305_led_hex_tbl[(val/10) % 10];
+	leds <<= 8;
+	leds |= asb2305_led_hex_tbl[val % 10];
+	leds |= points^0x01010101;
+
+	ASB2305_7SEGLEDS = leds;
+}
+
+void peripheral_leds_display_exception(enum exception_code code)
+{
+	u32 leds;
+
+	leds = asb2305_led_hex_tbl[(code/0x100) % 0x10];
+	leds <<= 8;
+	leds |= asb2305_led_hex_tbl[(code/0x10) % 0x10];
+	leds <<= 8;
+	leds |= asb2305_led_hex_tbl[code % 0x10];
+	leds |= 0x6d010101;
+
+	ASB2305_7SEGLEDS = leds;
+}
+
+void peripheral_leds7x4_display_minssecs(unsigned int time, unsigned int points)
+{
+	u32 leds;
+
+	leds = asb2305_led_hex_tbl[(time/600) % 6];
+	leds <<= 8;
+	leds |= asb2305_led_hex_tbl[(time/60) % 10];
+	leds <<= 8;
+	leds |= asb2305_led_hex_tbl[(time/10) % 6];
+	leds <<= 8;
+	leds |= asb2305_led_hex_tbl[time % 10];
+	leds |= points^0x01010101;
+
+	ASB2305_7SEGLEDS = leds;
+}
+
+void peripheral_leds7x4_display_rtc(void)
+{
+	unsigned int clock;
+	u8 mins, secs;
+
+	mins = RTMCR;
+	secs = RTSCR;
+
+	clock = ((mins & 0xf0) >> 4);
+	clock *= 10;
+	clock += (mins & 0x0f);
+	clock *= 6;
+
+	clock += ((secs & 0xf0) >> 4);
+	clock *= 10;
+	clock += (secs & 0x0f);
+
+	peripheral_leds7x4_display_minssecs(clock, 0);
+}
+
+void peripheral_leds_led_chase(void)
+{
+	ASB2305_7SEGLEDS = asb2305_led_chase_tbl[asb2305_led_chase];
+	asb2305_led_chase++;
+	if (asb2305_led_chase >= 6)
+		asb2305_led_chase = 0;
+}
diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c
new file mode 100644
index 0000000..b7ab837
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.c
@@ -0,0 +1,235 @@
+/* ASB2305 PCI resource stuff
+ *
+ * Copyright (C) 2001 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from arch/i386/pci-i386.c
+ *   - Copyright 1997--2000 Martin Mares <mj@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include "pci-asb2305.h"
+
+/*
+ * 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..
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	resource_size_t start = res->start;
+
+#if 0
+	struct pci_dev *dev = data;
+
+	printk(KERN_DEBUG
+	       "### PCIBIOS_ALIGN_RESOURCE(%s,,{%08lx-%08lx,%08lx},%lx)\n",
+	       pci_name(dev),
+	       res->start,
+	       res->end,
+	       res->flags,
+	       size
+	       );
+#endif
+
+	if ((res->flags & IORESOURCE_IO) && (start & 0x300))
+		start = (start + 0x3ff) & ~0x3ff;
+
+	return start;
+}
+
+
+/*
+ *  Handle resources of PCI devices.  If the world were perfect, we could
+ *  just allocate all the resource regions and do nothing more.  It isn't.
+ *  On the other hand, we cannot just re-allocate all devices, as it would
+ *  require us to know lots of host bridge internals.  So we attempt to
+ *  keep as much of the original configuration as possible, but tweak it
+ *  when it's found to be wrong.
+ *
+ *  Known BIOS problems we have to work around:
+ *	- I/O or memory regions not configured
+ *	- regions configured, but not enabled in the command register
+ *	- bogus I/O addresses above 64K used
+ *	- expansion ROMs left enabled (this may sound harmless, but given
+ *	  the fact the PCI specs explicitly allow address decoders to be
+ *	  shared between expansion ROMs and other resource regions, it's
+ *	  at least dangerous)
+ *
+ *  Our solution:
+ *	(1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ *	    This gives us fixed barriers on where we can allocate.
+ *	(2) Allocate resources for all enabled devices.  If there is
+ *	    a collision, just mark the resource as unallocated. Also
+ *	    disable expansion ROMs during this step.
+ *	(3) Try to allocate resources for disabled devices.  If the
+ *	    resources were assigned correctly, everything goes well,
+ *	    if they weren't, they won't disturb allocation of other
+ *	    resources.
+ *	(4) Assign new addresses to resources which were either
+ *	    not configured at all or misconfigured.  If explicitly
+ *	    requested by the user, configure expansion ROM address
+ *	    as well.
+ */
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+	struct pci_bus *bus;
+	struct pci_dev *dev;
+	int idx;
+	struct resource *r;
+
+	/* Depth-First Search on bus tree */
+	list_for_each_entry(bus, bus_list, node) {
+		dev = bus->self;
+		if (dev) {
+			for (idx = PCI_BRIDGE_RESOURCES;
+			     idx < PCI_NUM_RESOURCES;
+			     idx++) {
+				r = &dev->resource[idx];
+				if (!r->flags)
+					continue;
+				if (!r->start ||
+				    pci_claim_bridge_resource(dev, idx) < 0) {
+					printk(KERN_ERR "PCI:"
+					       " Cannot allocate resource"
+					       " region %d of bridge %s\n",
+					       idx, pci_name(dev));
+					/* Something is wrong with the region.
+					 * Invalidate the resource to prevent
+					 * child resource allocations in this
+					 * range. */
+					r->start = r->end = 0;
+					r->flags = 0;
+				}
+			}
+		}
+		pcibios_allocate_bus_resources(&bus->children);
+	}
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+	struct pci_dev *dev = NULL;
+	int idx, disabled;
+	u16 command;
+	struct resource *r;
+
+	for_each_pci_dev(dev) {
+		pci_read_config_word(dev, PCI_COMMAND, &command);
+		for (idx = 0; idx < 6; idx++) {
+			r = &dev->resource[idx];
+			if (r->parent)		/* Already allocated */
+				continue;
+			if (!r->start)		/* Address not assigned */
+				continue;
+			if (r->flags & IORESOURCE_IO)
+				disabled = !(command & PCI_COMMAND_IO);
+			else
+				disabled = !(command & PCI_COMMAND_MEMORY);
+			if (pass == disabled) {
+				DBG("PCI[%s]: Resource %08lx-%08lx"
+				    " (f=%lx, d=%d, p=%d)\n",
+				    pci_name(dev), r->start, r->end, r->flags,
+				    disabled, pass);
+				if (pci_claim_resource(dev, idx) < 0) {
+					printk(KERN_ERR "PCI:"
+					       " Cannot allocate resource"
+					       " region %d of device %s\n",
+					       idx, pci_name(dev));
+					/* We'll assign a new address later */
+					r->end -= r->start;
+					r->start = 0;
+				}
+			}
+		}
+		if (!pass) {
+			r = &dev->resource[PCI_ROM_RESOURCE];
+			if (r->flags & IORESOURCE_ROM_ENABLE) {
+				/* Turn the ROM off, leave the resource region,
+				 * but keep it unregistered. */
+				u32 reg;
+				DBG("PCI: Switching off ROM of %s\n",
+				    pci_name(dev));
+				r->flags &= ~IORESOURCE_ROM_ENABLE;
+				pci_read_config_dword(
+					dev, dev->rom_base_reg, &reg);
+				pci_write_config_dword(
+					dev, dev->rom_base_reg,
+					reg & ~PCI_ROM_ADDRESS_ENABLE);
+			}
+		}
+	}
+}
+
+static int __init pcibios_assign_resources(void)
+{
+	struct pci_dev *dev = NULL;
+	struct resource *r;
+
+	/* Try to use BIOS settings for ROMs, otherwise let
+	   pci_assign_unassigned_resources() allocate the new
+	   addresses. */
+	for_each_pci_dev(dev) {
+		r = &dev->resource[PCI_ROM_RESOURCE];
+		if (!r->flags || !r->start)
+			continue;
+		if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
+			r->end -= r->start;
+			r->start = 0;
+		}
+	}
+
+	pci_assign_unassigned_resources();
+
+	return 0;
+}
+
+fs_initcall(pcibios_assign_resources);
+
+void __init pcibios_resource_survey(void)
+{
+	DBG("PCI: Allocating resources\n");
+	pcibios_allocate_bus_resources(&pci_root_buses);
+	pcibios_allocate_resources(0);
+	pcibios_allocate_resources(1);
+}
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state, int write_combine)
+{
+	unsigned long prot;
+
+	/* Leave vm_pgoff as-is, the PCI space address is the physical
+	 * address on this platform.
+	 */
+	vma->vm_flags |= VM_LOCKED;
+
+	prot = pgprot_val(vma->vm_page_prot);
+	prot &= ~_PAGE_CACHE;
+	vma->vm_page_prot = __pgprot(prot);
+
+	/* Write-combine setting is ignored */
+	if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+			       vma->vm_end - vma->vm_start,
+			       vma->vm_page_prot))
+		return -EAGAIN;
+
+	return 0;
+}
diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h
new file mode 100644
index 0000000..96c484b
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.h
@@ -0,0 +1,68 @@
+/* ASB2305 Arch-specific PCI declarations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * Derived from: arch/i386/kernel/pci-i386.h: (c) 1999 Martin Mares <mj@ucw.cz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _PCI_ASB2305_H
+#define _PCI_ASB2305_H
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+extern unsigned int pci_probe;
+
+/* pci-asb2305.c */
+
+extern void pcibios_resource_survey(void);
+
+/* pci.c */
+
+extern struct pci_ops *pci_root_ops;
+
+extern struct irq_routing_table *pcibios_get_irq_routing_table(void);
+extern int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
+
+/* pci-irq.c */
+
+struct irq_info {
+	u8 bus, devfn;			/* Bus, device and function */
+	struct {
+		u8 link;		/* IRQ line ID, chipset dependent,
+					 * 0=not routed */
+		u16 bitmap;		/* Available IRQs */
+	} __attribute__((packed)) irq[4];
+	u8 slot;			/* Slot number, 0=onboard */
+	u8 rfu;
+} __attribute__((packed));
+
+struct irq_routing_table {
+	u32 signature;			/* PIRQ_SIGNATURE should be here */
+	u16 version;			/* PIRQ_VERSION */
+	u16 size;			/* Table size in bytes */
+	u8 rtr_bus, rtr_devfn;		/* Where the interrupt router lies */
+	u16 exclusive_irqs;		/* IRQs devoted exclusively to PCI usage */
+	u16 rtr_vendor, rtr_device;	/* Vendor and device ID of interrupt router */
+	u32 miniport_data;		/* Crap */
+	u8 rfu[11];
+	u8 checksum;			/* Modulo 256 checksum must give zero */
+	struct irq_info slots[0];
+} __attribute__((packed));
+
+extern unsigned int pcibios_irq_mask;
+
+extern void pcibios_irq_init(void);
+extern void pcibios_fixup_irqs(void);
+extern void pcibios_enable_irq(struct pci_dev *dev);
+
+#endif /* PCI_ASB2305_H */
diff --git a/arch/mn10300/unit-asb2305/pci-irq.c b/arch/mn10300/unit-asb2305/pci-irq.c
new file mode 100644
index 0000000..fcb28ce
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/pci-irq.c
@@ -0,0 +1,46 @@
+/* PCI IRQ routing on the MN103E010 based ASB2305
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ *
+ * This is simple: All PCI interrupts route through the CPU's XIRQ1 pin [IRQ 35]
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include "pci-asb2305.h"
+
+void __init pcibios_irq_init(void)
+{
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+	struct pci_dev *dev = NULL;
+	u8 line, pin;
+
+	for_each_pci_dev(dev) {
+		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+		if (pin) {
+			dev->irq = XIRQ1;
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+					      dev->irq);
+		}
+		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
+	}
+}
+
+void pcibios_enable_irq(struct pci_dev *dev)
+{
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+}
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c
new file mode 100644
index 0000000..3dfe2d3
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/pci.c
@@ -0,0 +1,505 @@
+/* ASB2305 PCI support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * Derived from arch/i386/kernel/pci-pc.c
+ *	(c) 1999--2000 Martin Mares <mj@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include "pci-asb2305.h"
+
+unsigned int pci_probe = 1;
+
+struct pci_ops *pci_root_ops;
+
+/*
+ * The accessible PCI window does not cover the entire CPU address space, but
+ * there are devices we want to access outside of that window, so we need to
+ * insert specific PCI bus resources instead of using the platform-level bus
+ * resources directly for the PCI root bus.
+ *
+ * These are configured and inserted by pcibios_init().
+ */
+static struct resource pci_ioport_resource = {
+	.name	= "PCI IO",
+	.start	= 0xbe000000,
+	.end	= 0xbe03ffff,
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource pci_iomem_resource = {
+	.name	= "PCI mem",
+	.start	= 0xb8000000,
+	.end	= 0xbbffffff,
+	.flags	= IORESOURCE_MEM,
+};
+
+/*
+ * Functions for accessing PCI configuration space
+ */
+
+#define CONFIG_CMD(bus, devfn, where) \
+	(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+#define MEM_PAGING_REG	(*(volatile __u32 *) 0xBFFFFFF4)
+#define CONFIG_ADDRESS	(*(volatile __u32 *) 0xBFFFFFF8)
+#define CONFIG_DATAL(X)	(*(volatile __u32 *) 0xBFFFFFFC)
+#define CONFIG_DATAW(X)	(*(volatile __u16 *) (0xBFFFFFFC + ((X) & 2)))
+#define CONFIG_DATAB(X)	(*(volatile __u8  *) (0xBFFFFFFC + ((X) & 3)))
+
+#define BRIDGEREGB(X)	(*(volatile __u8  *) (0xBE040000 + (X)))
+#define BRIDGEREGW(X)	(*(volatile __u16 *) (0xBE040000 + (X)))
+#define BRIDGEREGL(X)	(*(volatile __u32 *) (0xBE040000 + (X)))
+
+static inline int __query(const struct pci_bus *bus, unsigned int devfn)
+{
+#if 0
+	return bus->number == 0 && (devfn == PCI_DEVFN(0, 0));
+	return bus->number == 1;
+	return bus->number == 0 &&
+		(devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(3, 0));
+#endif
+	return 1;
+}
+
+/*
+ *
+ */
+static int pci_ampci_read_config_byte(struct pci_bus *bus, unsigned int devfn,
+				      int where, u32 *_value)
+{
+	u32 rawval, value;
+
+	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+		value = BRIDGEREGB(where);
+		__pcbdebug("=> %02hx", &BRIDGEREGL(where), value);
+	} else {
+		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+		rawval = CONFIG_ADDRESS;
+		value = CONFIG_DATAB(where);
+		if (__query(bus, devfn))
+			__pcidebug("=> %02hx", bus, devfn, where, value);
+	}
+
+	*_value = value;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_read_config_word(struct pci_bus *bus, unsigned int devfn,
+				      int where, u32 *_value)
+{
+	u32 rawval, value;
+
+	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+		value = BRIDGEREGW(where);
+		__pcbdebug("=> %04hx", &BRIDGEREGL(where), value);
+	} else {
+		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+		rawval = CONFIG_ADDRESS;
+		value = CONFIG_DATAW(where);
+		if (__query(bus, devfn))
+			__pcidebug("=> %04hx", bus, devfn, where, value);
+	}
+
+	*_value = value;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
+				       int where, u32 *_value)
+{
+	u32 rawval, value;
+
+	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+		value = BRIDGEREGL(where);
+		__pcbdebug("=> %08x", &BRIDGEREGL(where), value);
+	} else {
+		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+		rawval = CONFIG_ADDRESS;
+		value = CONFIG_DATAL(where);
+		if (__query(bus, devfn))
+			__pcidebug("=> %08x", bus, devfn, where, value);
+	}
+
+	*_value = value;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_write_config_byte(struct pci_bus *bus, unsigned int devfn,
+				       int where, u8 value)
+{
+	u32 rawval;
+
+	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+		__pcbdebug("<= %02x", &BRIDGEREGB(where), value);
+		BRIDGEREGB(where) = value;
+	} else {
+		if (bus->number == 0 &&
+		    (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(3, 0))
+		    )
+			__pcidebug("<= %02x", bus, devfn, where, value);
+		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+		rawval = CONFIG_ADDRESS;
+		CONFIG_DATAB(where) = value;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_write_config_word(struct pci_bus *bus, unsigned int devfn,
+				       int where, u16 value)
+{
+	u32 rawval;
+
+	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+		__pcbdebug("<= %04hx", &BRIDGEREGW(where), value);
+		BRIDGEREGW(where) = value;
+	} else {
+		if (__query(bus, devfn))
+			__pcidebug("<= %04hx", bus, devfn, where, value);
+		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+		rawval = CONFIG_ADDRESS;
+		CONFIG_DATAW(where) = value;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
+					int where, u32 value)
+{
+	u32 rawval;
+
+	if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+		__pcbdebug("<= %08x", &BRIDGEREGL(where), value);
+		BRIDGEREGL(where) = value;
+	} else {
+		if (__query(bus, devfn))
+			__pcidebug("<= %08x", bus, devfn, where, value);
+		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+		rawval = CONFIG_ADDRESS;
+		CONFIG_DATAL(where) = value;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_read_config(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 *val)
+{
+	switch (size) {
+	case 1:
+		return pci_ampci_read_config_byte(bus, devfn, where, val);
+	case 2:
+		return pci_ampci_read_config_word(bus, devfn, where, val);
+	case 4:
+		return pci_ampci_read_config_dword(bus, devfn, where, val);
+	default:
+		BUG();
+		return -EOPNOTSUPP;
+	}
+}
+
+static int pci_ampci_write_config(struct pci_bus *bus, unsigned int devfn,
+				  int where, int size, u32 val)
+{
+	switch (size) {
+	case 1:
+		return pci_ampci_write_config_byte(bus, devfn, where, val);
+	case 2:
+		return pci_ampci_write_config_word(bus, devfn, where, val);
+	case 4:
+		return pci_ampci_write_config_dword(bus, devfn, where, val);
+	default:
+		BUG();
+		return -EOPNOTSUPP;
+	}
+}
+
+static struct pci_ops pci_direct_ampci = {
+	.read = pci_ampci_read_config,
+	.write = pci_ampci_write_config,
+};
+
+/*
+ * Before we decide to use direct hardware access mechanisms, we try to do some
+ * trivial checks to ensure it at least _seems_ to be working -- we just test
+ * whether bus 00 contains a host bridge (this is similar to checking
+ * techniques used in XFree86, but ours should be more reliable since we
+ * attempt to make use of direct access hints provided by the PCI BIOS).
+ *
+ * This should be close to trivial, but it isn't, because there are buggy
+ * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
+ */
+static int __init pci_sanity_check(struct pci_ops *o)
+{
+	struct pci_bus bus;		/* Fake bus and device */
+	u32 x;
+
+	bus.number = 0;
+
+	if ((!o->read(&bus, 0, PCI_CLASS_DEVICE, 2, &x) &&
+	     (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) ||
+	    (!o->read(&bus, 0, PCI_VENDOR_ID, 2, &x) &&
+	     (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)))
+		return 1;
+
+	printk(KERN_ERR "PCI: Sanity check failed\n");
+	return 0;
+}
+
+static int __init pci_check_direct(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/*
+	 * Check if access works.
+	 */
+	if (pci_sanity_check(&pci_direct_ampci)) {
+		local_irq_restore(flags);
+		printk(KERN_INFO "PCI: Using configuration ampci\n");
+		request_mem_region(0xBE040000, 256, "AMPCI bridge");
+		request_mem_region(0xBFFFFFF4, 12, "PCI ampci");
+		request_mem_region(0xBC000000, 32 * 1024 * 1024, "PCI SRAM");
+		return 0;
+	}
+
+	local_irq_restore(flags);
+	return -ENODEV;
+}
+
+static void pcibios_fixup_device_resources(struct pci_dev *dev)
+{
+	int idx;
+
+	if (!dev->bus)
+		return;
+
+	for (idx = 0; idx < PCI_BRIDGE_RESOURCES; idx++) {
+		struct resource *r = &dev->resource[idx];
+
+		if (!r->flags || r->parent || !r->start)
+			continue;
+
+		pci_claim_resource(dev, idx);
+	}
+}
+
+static void pcibios_fixup_bridge_resources(struct pci_dev *dev)
+{
+	int idx;
+
+	if (!dev->bus)
+		return;
+
+	for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
+		struct resource *r = &dev->resource[idx];
+
+		if (!r->flags || r->parent || !r->start)
+			continue;
+
+		pci_claim_bridge_resource(dev, idx);
+	}
+}
+
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+void pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	if (bus->self) {
+		pci_read_bridge_bases(bus);
+		pcibios_fixup_bridge_resources(bus->self);
+	}
+
+	list_for_each_entry(dev, &bus->devices, bus_list)
+		pcibios_fixup_device_resources(dev);
+}
+
+/*
+ * Initialization. Try all known PCI access methods. Note that we support
+ * using both PCI BIOS and direct access: in such cases, we use I/O ports
+ * to access config space, but we still keep BIOS order of cards to be
+ * compatible with 2.0.X. This should go away some day.
+ */
+static int __init pcibios_init(void)
+{
+	resource_size_t io_offset, mem_offset;
+	LIST_HEAD(resources);
+	struct pci_bus *bus;
+
+	ioport_resource.start	= 0xA0000000;
+	ioport_resource.end	= 0xDFFFFFFF;
+	iomem_resource.start	= 0xA0000000;
+	iomem_resource.end	= 0xDFFFFFFF;
+
+	if (insert_resource(&iomem_resource, &pci_iomem_resource) < 0)
+		panic("Unable to insert PCI IOMEM resource\n");
+	if (insert_resource(&ioport_resource, &pci_ioport_resource) < 0)
+		panic("Unable to insert PCI IOPORT resource\n");
+
+	if (!pci_probe)
+		return 0;
+
+	if (pci_check_direct() < 0) {
+		printk(KERN_WARNING "PCI: No PCI bus detected\n");
+		return 0;
+	}
+
+	printk(KERN_INFO "PCI: Probing PCI hardware [mempage %08x]\n",
+	       MEM_PAGING_REG);
+
+	io_offset = pci_ioport_resource.start -
+	    (pci_ioport_resource.start & 0x00ffffff);
+	mem_offset = pci_iomem_resource.start -
+	    ((pci_iomem_resource.start & 0x03ffffff) | MEM_PAGING_REG);
+
+	pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset);
+	pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset);
+	bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
+	if (!bus)
+		return 0;
+
+	pcibios_irq_init();
+	pcibios_fixup_irqs();
+	pcibios_resource_survey();
+	pci_bus_add_devices(bus);
+	return 0;
+}
+
+arch_initcall(pcibios_init);
+
+char *__init pcibios_setup(char *str)
+{
+	if (!strcmp(str, "off")) {
+		pci_probe = 0;
+		return NULL;
+	}
+
+	return str;
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	int err;
+
+	err = pci_enable_resources(dev, mask);
+	if (err == 0)
+		pcibios_enable_irq(dev);
+	return err;
+}
+
+/*
+ * disable the ethernet chipset
+ */
+static void __init unit_disable_pcnet(struct pci_bus *bus, struct pci_ops *o)
+{
+	u32 x;
+
+	bus->number = 0;
+
+	o->read (bus, PCI_DEVFN(2, 0), PCI_VENDOR_ID,		4, &x);
+	o->read (bus, PCI_DEVFN(2, 0), PCI_COMMAND,		2, &x);
+	x |= PCI_COMMAND_MASTER |
+		PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+		PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
+	o->write(bus, PCI_DEVFN(2, 0), PCI_COMMAND,		2, x);
+	o->read (bus, PCI_DEVFN(2, 0), PCI_COMMAND,		2, &x);
+	o->write(bus, PCI_DEVFN(2, 0), PCI_BASE_ADDRESS_0,	4, 0x00030001);
+	o->read (bus, PCI_DEVFN(2, 0), PCI_BASE_ADDRESS_0,	4, &x);
+
+#define RDP (*(volatile u32 *) 0xBE030010)
+#define RAP (*(volatile u32 *) 0xBE030014)
+#define __set_RAP(X) do { RAP = (X); x = RAP; } while (0)
+#define __set_RDP(X) do { RDP = (X); x = RDP; } while (0)
+#define __get_RDP() ({ RDP & 0xffff; })
+
+	__set_RAP(0);
+	__set_RDP(0x0004);	/* CSR0 = STOP */
+
+	__set_RAP(88);		/* check CSR88 indicates an Am79C973 */
+	BUG_ON(__get_RDP() != 0x5003);
+
+	for (x = 0; x < 100; x++)
+		asm volatile("nop");
+
+	__set_RDP(0x0004);	/* CSR0 = STOP */
+}
+
+/*
+ * initialise the unit hardware
+ */
+asmlinkage void __init unit_pci_init(void)
+{
+	struct pci_bus bus;		/* Fake bus and device */
+	struct pci_ops *o = &pci_direct_ampci;
+	u32 x;
+
+	set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_PCI_IRQ_LEVEL));
+
+	memset(&bus, 0, sizeof(bus));
+
+	MEM_PAGING_REG = 0xE8000000;
+
+	/* we need to set up the bridge _now_ or we won't be able to access the
+	 * PCI config registers
+	 */
+	BRIDGEREGW(PCI_COMMAND) |=
+		PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
+		PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER;
+	BRIDGEREGW(PCI_STATUS)		= 0xF800;
+	BRIDGEREGB(PCI_LATENCY_TIMER)	= 0x10;
+	BRIDGEREGL(PCI_BASE_ADDRESS_0)	= 0x80000000;
+	BRIDGEREGB(PCI_INTERRUPT_LINE)	= 1;
+	BRIDGEREGL(0x48)		= 0x98000000;	/* AMPCI base addr */
+	BRIDGEREGB(0x41)		= 0x00;		/* secondary bus
+							 * number */
+	BRIDGEREGB(0x42)		= 0x01;		/* subordinate bus
+							 * number */
+	BRIDGEREGB(0x44)		= 0x01;
+	BRIDGEREGL(0x50)		= 0x00000001;
+	BRIDGEREGL(0x58)		= 0x00001002;
+	BRIDGEREGL(0x5C)		= 0x00000011;
+
+	/* we also need to set up the PCI-PCI bridge */
+	bus.number = 0;
+
+	/* IO: 0x00000000-0x00020000 */
+	o->read (&bus, PCI_DEVFN(3, 0), PCI_COMMAND,		2, &x);
+	x |= PCI_COMMAND_MASTER |
+		PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+		PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
+	o->write(&bus, PCI_DEVFN(3, 0), PCI_COMMAND,		2, x);
+
+	o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE,		1, &x);
+	o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16,	4, &x);
+	o->read (&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE,	4, &x);
+	o->read (&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE,	4, &x);
+
+	o->write(&bus, PCI_DEVFN(3, 0), PCI_IO_BASE,		1, 0x01);
+	o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE,		1, &x);
+	o->write(&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16,	4, 0x00020000);
+	o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16,	4, &x);
+	o->write(&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE,	4, 0xEBB0EA00);
+	o->read (&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE,	4, &x);
+	o->write(&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE,	4, 0xE9F0E800);
+	o->read (&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE,	4, &x);
+
+	unit_disable_pcnet(&bus, o);
+}
diff --git a/arch/mn10300/unit-asb2305/unit-init.c b/arch/mn10300/unit-asb2305/unit-init.c
new file mode 100644
index 0000000..bc4adfa
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/unit-init.c
@@ -0,0 +1,63 @@
+/* ASB2305 Initialisation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/intctl-regs.h>
+#include <asm/serial-regs.h>
+#include <unit/serial.h>
+
+/*
+ * initialise some of the unit hardware before gdbstub is set up
+ */
+asmlinkage void __init unit_init(void)
+{
+#ifndef CONFIG_GDBSTUB_ON_TTYSx
+	/* set the 16550 interrupt line to level 3 if not being used for GDB */
+#ifdef CONFIG_EXT_SERIAL_IRQ_LEVEL
+	set_intr_level(XIRQ0, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL));
+#endif
+#endif /* CONFIG_GDBSTUB_ON_TTYSx */
+}
+
+/*
+ * initialise the rest of the unit hardware after gdbstub is ready
+ */
+void __init unit_setup(void)
+{
+#ifdef CONFIG_PCI
+	unit_pci_init();
+#endif
+}
+
+/*
+ * initialise the external interrupts used by a unit of this type
+ */
+void __init unit_init_IRQ(void)
+{
+	unsigned int extnum;
+
+	for (extnum = 0; extnum < NR_XIRQS; extnum++) {
+		switch (GET_XIRQ_TRIGGER(extnum)) {
+		case XIRQ_TRIGGER_HILEVEL:
+		case XIRQ_TRIGGER_LOWLEVEL:
+			mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum));
+			break;
+		default:
+			break;
+		}
+	}
+}
diff --git a/arch/mn10300/unit-asb2364/Makefile b/arch/mn10300/unit-asb2364/Makefile
new file mode 100644
index 0000000..b3263ec
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+obj-y   := unit-init.o leds.o irq-fpga.o
+
+obj-$(CONFIG_SMSC911X) += smsc911x.o
diff --git a/arch/mn10300/unit-asb2364/include/unit/clock.h b/arch/mn10300/unit-asb2364/include/unit/clock.h
new file mode 100644
index 0000000..d34ac9a
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/clock.h
@@ -0,0 +1,29 @@
+/* clock.h: unit-specific clocks
+ *
+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * Modified by Matsushita Electric Industrial Co., Ltd.
+ * Modifications:
+ *	23-Feb-2007 MEI Add define for watchdog timer.
+ *
+ * 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.
+ */
+
+#ifndef _ASM_UNIT_CLOCK_H
+#define _ASM_UNIT_CLOCK_H
+
+#ifndef __ASSEMBLY__
+
+#define MN10300_IOCLK		100000000UL		/* for DDR800 */
+/*#define MN10300_IOCLK		83333333UL */		/* for DDR667 */
+#define MN10300_IOBCLK		MN10300_IOCLK		/* IOBCLK is equal to IOCLK */
+
+#endif /* !__ASSEMBLY__ */
+
+#define MN10300_WDCLK		27000000UL
+
+#endif /* _ASM_UNIT_CLOCK_H */
diff --git a/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h
new file mode 100644
index 0000000..33f100f
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h
@@ -0,0 +1,52 @@
+/* ASB2364 FPGA registers
+ */
+
+#ifndef _ASM_UNIT_FPGA_REGS_H
+#define _ASM_UNIT_FPGA_REGS_H
+
+#include <asm/cpu-regs.h>
+
+#ifdef __KERNEL__
+
+#define ASB2364_FPGA_REG_RESET_LAN	__SYSREG(0xa9001300, u16)
+#define ASB2364_FPGA_REG_RESET_UART	__SYSREG(0xa9001304, u16)
+#define ASB2364_FPGA_REG_RESET_I2C	__SYSREG(0xa9001308, u16)
+#define ASB2364_FPGA_REG_RESET_USB	__SYSREG(0xa900130c, u16)
+#define ASB2364_FPGA_REG_RESET_AV	__SYSREG(0xa9001310, u16)
+
+#define ASB2364_FPGA_REG_IRQ(X)		__SYSREG(0xa9001510+((X)*4), u16)
+#define ASB2364_FPGA_REG_IRQ_LAN	ASB2364_FPGA_REG_IRQ(0)
+#define ASB2364_FPGA_REG_IRQ_UART	ASB2364_FPGA_REG_IRQ(1)
+#define ASB2364_FPGA_REG_IRQ_I2C	ASB2364_FPGA_REG_IRQ(2)
+#define ASB2364_FPGA_REG_IRQ_USB	ASB2364_FPGA_REG_IRQ(3)
+#define ASB2364_FPGA_REG_IRQ_FPGA	ASB2364_FPGA_REG_IRQ(5)
+
+#define ASB2364_FPGA_REG_MASK(X)	__SYSREG(0xa9001590+((X)*4), u16)
+#define ASB2364_FPGA_REG_MASK_LAN	ASB2364_FPGA_REG_MASK(0)
+#define ASB2364_FPGA_REG_MASK_UART	ASB2364_FPGA_REG_MASK(1)
+#define ASB2364_FPGA_REG_MASK_I2C	ASB2364_FPGA_REG_MASK(2)
+#define ASB2364_FPGA_REG_MASK_USB	ASB2364_FPGA_REG_MASK(3)
+#define ASB2364_FPGA_REG_MASK_FPGA	ASB2364_FPGA_REG_MASK(5)
+
+#define ASB2364_FPGA_REG_CPLD5_SET1	__SYSREG(0xa9002500, u16)
+#define ASB2364_FPGA_REG_CPLD5_SET2	__SYSREG(0xa9002504, u16)
+#define ASB2364_FPGA_REG_CPLD6_SET1	__SYSREG(0xa9002600, u16)
+#define ASB2364_FPGA_REG_CPLD6_SET2	__SYSREG(0xa9002604, u16)
+#define ASB2364_FPGA_REG_CPLD7_SET1	__SYSREG(0xa9002700, u16)
+#define ASB2364_FPGA_REG_CPLD7_SET2	__SYSREG(0xa9002704, u16)
+#define ASB2364_FPGA_REG_CPLD8_SET1	__SYSREG(0xa9002800, u16)
+#define ASB2364_FPGA_REG_CPLD8_SET2	__SYSREG(0xa9002804, u16)
+#define ASB2364_FPGA_REG_CPLD9_SET1	__SYSREG(0xa9002900, u16)
+#define ASB2364_FPGA_REG_CPLD9_SET2	__SYSREG(0xa9002904, u16)
+#define ASB2364_FPGA_REG_CPLD10_SET1	__SYSREG(0xa9002a00, u16)
+#define ASB2364_FPGA_REG_CPLD10_SET2	__SYSREG(0xa9002a04, u16)
+
+#define SyncExBus()					\
+	do {						\
+		unsigned short w;			\
+		w = *(volatile short *)0xa9000000;	\
+	} while (0)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_UNIT_FPGA_REGS_H */
diff --git a/arch/mn10300/unit-asb2364/include/unit/irq.h b/arch/mn10300/unit-asb2364/include/unit/irq.h
new file mode 100644
index 0000000..786148e
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/irq.h
@@ -0,0 +1,35 @@
+/* ASB2364 FPGA irq numbers
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _UNIT_IRQ_H
+#define _UNIT_IRQ_H
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_SMP
+#define NR_CPU_IRQS	GxICR_NUM_EXT_IRQS
+#else
+#define NR_CPU_IRQS	GxICR_NUM_IRQS
+#endif
+
+enum {
+	FPGA_LAN_IRQ	= NR_CPU_IRQS,
+	FPGA_UART_IRQ,
+	FPGA_I2C_IRQ,
+	FPGA_USB_IRQ,
+	FPGA_RESERVED_IRQ,
+	FPGA_FPGA_IRQ,
+	NR_IRQS
+};
+
+extern void __init irq_fpga_init(void);
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _UNIT_IRQ_H */
diff --git a/arch/mn10300/unit-asb2364/include/unit/leds.h b/arch/mn10300/unit-asb2364/include/unit/leds.h
new file mode 100644
index 0000000..03a3933
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/leds.h
@@ -0,0 +1,54 @@
+/* Unit-specific leds
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_UNIT_LEDS_H
+#define _ASM_UNIT_LEDS_H
+
+#include <asm/pio-regs.h>
+#include <asm/cpu-regs.h>
+#include <asm/exceptions.h>
+
+#define MN10300_USE_7SEGLEDS	0
+
+#define ASB2364_7SEGLEDS	__SYSREG(0xA9001630, u32)
+
+/*
+ * use the 7-segment LEDs to indicate states
+ */
+
+#if MN10300_USE_7SEGLEDS
+/* flip the 7-segment LEDs between "Gdb-" and "----" */
+#define mn10300_set_gdbleds(ONOFF)					\
+	do {								\
+		ASB2364_7SEGLEDS = (ONOFF) ? 0x8543077f : 0x7f7f7f7f;	\
+	} while (0)
+#else
+#define mn10300_set_gdbleds(ONOFF) do {} while (0)
+#endif
+
+#if MN10300_USE_7SEGLEDS
+/* indicate double-fault by displaying "db-f" on the LEDs */
+#define mn10300_set_dbfleds			\
+	mov	0x43077f1d,d0		;	\
+	mov	d0,(ASB2364_7SEGLEDS)
+#else
+#define mn10300_set_dbfleds
+#endif
+
+#ifndef __ASSEMBLY__
+extern void peripheral_leds_display_exception(enum exception_code);
+extern void peripheral_leds_led_chase(void);
+extern void peripheral_leds7x4_display_dec(unsigned int, unsigned int);
+extern void peripheral_leds7x4_display_hex(unsigned int, unsigned int);
+extern void debug_to_serial(const char *, int);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_UNIT_LEDS_H */
diff --git a/arch/mn10300/unit-asb2364/include/unit/serial.h b/arch/mn10300/unit-asb2364/include/unit/serial.h
new file mode 100644
index 0000000..92f224a
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/serial.h
@@ -0,0 +1,151 @@
+/* Unit-specific 8250 serial ports
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _ASM_UNIT_SERIAL_H
+#define _ASM_UNIT_SERIAL_H
+
+#include <asm/cpu-regs.h>
+#include <proc/irq.h>
+#include <unit/fpga-regs.h>
+#include <linux/serial_reg.h>
+
+#define SERIAL_PORT0_BASE_ADDRESS	0xA8200000
+
+#define SERIAL_IRQ	XIRQ1	/* single serial (TL16C550C)	(Lo) */
+
+/*
+ * The ASB2364 has an 12.288 MHz clock
+ * for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD (12288000 / 16)
+
+/*
+ * dispose of the /dev/ttyS0 and /dev/ttyS1 serial ports
+ */
+#ifndef CONFIG_GDBSTUB_ON_TTYSx
+
+#define SERIAL_PORT_DFNS						\
+	{								\
+		.baud_base	= BASE_BAUD,				\
+		.irq		= SERIAL_IRQ,				\
+		.flags		= STD_COM_FLAGS,			\
+		.iomem_base	= (u8 *) SERIAL_PORT0_BASE_ADDRESS,	\
+		.iomem_reg_shift = 1,					\
+		.io_type	= SERIAL_IO_MEM,			\
+	},
+
+#ifndef __ASSEMBLY__
+
+static inline void __debug_to_serial(const char *p, int n)
+{
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#else /* CONFIG_GDBSTUB_ON_TTYSx */
+
+#define SERIAL_PORT_DFNS /* stolen by gdb-stub */
+
+#if defined(CONFIG_GDBSTUB_ON_TTYS0)
+#define GDBPORT_SERIAL_RX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX  * 2, u8)
+#define GDBPORT_SERIAL_TX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX  * 2, u8)
+#define GDBPORT_SERIAL_DLL	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 2, u8)
+#define GDBPORT_SERIAL_DLM	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 2, u8)
+#define GDBPORT_SERIAL_IER	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 2, u8)
+#define GDBPORT_SERIAL_IIR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 2, u8)
+#define GDBPORT_SERIAL_FCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 2, u8)
+#define GDBPORT_SERIAL_LCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 2, u8)
+#define GDBPORT_SERIAL_MCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 2, u8)
+#define GDBPORT_SERIAL_LSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 2, u8)
+#define GDBPORT_SERIAL_MSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 2, u8)
+#define GDBPORT_SERIAL_SCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 2, u8)
+#define GDBPORT_SERIAL_IRQ	SERIAL_IRQ
+
+#elif defined(CONFIG_GDBSTUB_ON_TTYS1)
+#error The ASB2364 does not have a /dev/ttyS1
+#endif
+
+#ifndef __ASSEMBLY__
+
+static inline void __debug_to_serial(const char *p, int n)
+{
+	char ch;
+
+#define LSR_WAIT_FOR(STATE)	\
+	do {} while (!(GDBPORT_SERIAL_LSR & UART_LSR_##STATE))
+#define FLOWCTL_QUERY(LINE)	\
+	({ GDBPORT_SERIAL_MSR & UART_MSR_##LINE; })
+#define FLOWCTL_WAIT_FOR(LINE)	\
+	do {} while (!(GDBPORT_SERIAL_MSR & UART_MSR_##LINE))
+#define FLOWCTL_CLEAR(LINE)	\
+	do { GDBPORT_SERIAL_MCR &= ~UART_MCR_##LINE; } while (0)
+#define FLOWCTL_SET(LINE)	\
+	do { GDBPORT_SERIAL_MCR |= UART_MCR_##LINE; } while (0)
+
+	FLOWCTL_SET(DTR);
+
+	for (; n > 0; n--) {
+		LSR_WAIT_FOR(THRE);
+		FLOWCTL_WAIT_FOR(CTS);
+
+		ch = *p++;
+		if (ch == 0x0a) {
+			GDBPORT_SERIAL_TX = 0x0d;
+			LSR_WAIT_FOR(THRE);
+			FLOWCTL_WAIT_FOR(CTS);
+		}
+		GDBPORT_SERIAL_TX = ch;
+	}
+
+	FLOWCTL_CLEAR(DTR);
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* CONFIG_GDBSTUB_ON_TTYSx */
+
+#define SERIAL_INITIALIZE					\
+do {								\
+	/* release reset */					\
+	ASB2364_FPGA_REG_RESET_UART = 0x0001;			\
+	SyncExBus();						\
+} while (0)
+
+#define SERIAL_CHECK_INTERRUPT					\
+do {								\
+	if ((ASB2364_FPGA_REG_IRQ_UART & 0x0001) == 0x0001) {	\
+		return IRQ_NONE;				\
+	}							\
+} while (0)
+
+#define SERIAL_CLEAR_INTERRUPT					\
+do {								\
+	ASB2364_FPGA_REG_IRQ_UART = 0x0001;			\
+	SyncExBus();						\
+} while (0)
+
+#define SERIAL_SET_INT_MASK					\
+do {								\
+	ASB2364_FPGA_REG_MASK_UART = 0x0001;			\
+	SyncExBus();						\
+} while (0)
+
+#define SERIAL_CLEAR_INT_MASK					\
+do {								\
+	ASB2364_FPGA_REG_MASK_UART = 0x0000;			\
+	SyncExBus();						\
+} while (0)
+
+#endif /* _ASM_UNIT_SERIAL_H */
diff --git a/arch/mn10300/unit-asb2364/include/unit/smsc911x.h b/arch/mn10300/unit-asb2364/include/unit/smsc911x.h
new file mode 100644
index 0000000..4c1ede5
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/smsc911x.h
@@ -0,0 +1,171 @@
+/* Support for the SMSC911x NIC
+ *
+ * Copyright (C) 2006 Matsushita Electric Industrial Co., Ltd.
+ * All Rights Reserved.
+ *
+ * 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.
+ */
+#ifndef _ASM_UNIT_SMSC911X_H
+#define _ASM_UNIT_SMSC911X_H
+
+#include <linux/netdevice.h>
+#include <proc/irq.h>
+#include <unit/fpga-regs.h>
+
+#define MN10300_USE_EXT_EEPROM
+
+
+#define SMSC911X_BASE		0xA8000000UL
+#define SMSC911X_BASE_END	0xA8000100UL
+#define SMSC911X_IRQ		FPGA_LAN_IRQ
+
+/*
+ * Allow the FPGA to be initialised by the SMSC911x driver
+ */
+#undef SMSC_INITIALIZE
+#define SMSC_INITIALIZE()					\
+do {								\
+	/* release reset */					\
+	ASB2364_FPGA_REG_RESET_LAN = 0x0001;			\
+	SyncExBus();						\
+} while (0)
+
+#ifdef MN10300_USE_EXT_EEPROM
+#include <linux/delay.h>
+#include <unit/clock.h>
+
+#define EEPROM_ADDRESS	0xA0
+#define MAC_OFFSET	0x0008
+#define USE_IIC_CH	0	/* 0 or 1 */
+#define IIC_OFFSET	(0x80000 * USE_IIC_CH)
+#define IIC_DTRM	__SYSREG(0xd8400000 + IIC_OFFSET, u32)
+#define IIC_DREC	__SYSREG(0xd8400004 + IIC_OFFSET, u32)
+#define IIC_MYADD	__SYSREG(0xd8400008 + IIC_OFFSET, u32)
+#define IIC_CLK		__SYSREG(0xd840000c + IIC_OFFSET, u32)
+#define IIC_BRST	__SYSREG(0xd8400010 + IIC_OFFSET, u32)
+#define IIC_HOLD	__SYSREG(0xd8400014 + IIC_OFFSET, u32)
+#define IIC_BSTS	__SYSREG(0xd8400018 + IIC_OFFSET, u32)
+#define IIC_ICR		__SYSREG(0xd4000080 + 4 * USE_IIC_CH, u16)
+
+#define IIC_CLK_PLS	((unsigned short)(MN10300_IOCLK / 100000 - 1))
+#define IIC_CLK_LOW	((unsigned short)(IIC_CLK_PLS / 2))
+
+#define SYS_IIC_DTRM_Bit_STA	((unsigned short)0x0400)
+#define SYS_IIC_DTRM_Bit_STO	((unsigned short)0x0200)
+#define SYS_IIC_DTRM_Bit_ACK	((unsigned short)0x0100)
+#define SYS_IIC_DTRM_Bit_DATA	((unsigned short)0x00FF)
+
+static inline void POLL_INT_REQ(volatile u16 *icr)
+{
+	unsigned long flags;
+	u16 tmp;
+
+	while (!(*icr & GxICR_REQUEST))
+		;
+	flags = arch_local_cli_save();
+	tmp = *icr;
+	*icr = (tmp & GxICR_LEVEL) | GxICR_DETECT;
+	tmp = *icr;
+	arch_local_irq_restore(flags);
+}
+
+/*
+ * Implement the SMSC911x hook for MAC address retrieval
+ */
+#undef smsc_get_mac
+static inline int smsc_get_mac(struct net_device *dev)
+{
+	unsigned char *mac_buf = dev->dev_addr;
+	int i;
+	unsigned short value;
+	unsigned int data;
+	int mac_length = 6;
+	int check;
+	u16 orig_gicr, tmp;
+	unsigned long flags;
+
+	/* save original GnICR and clear GnICR.IE */
+	flags = arch_local_cli_save();
+	orig_gicr = IIC_ICR;
+	IIC_ICR = orig_gicr & GxICR_LEVEL;
+	tmp = IIC_ICR;
+	arch_local_irq_restore(flags);
+
+	IIC_MYADD = 0x00000008;
+	IIC_CLK = (IIC_CLK_LOW << 16) + (IIC_CLK_PLS);
+	/* bus hung recovery */
+
+	while (1) {
+		check = 0;
+		for (i = 0; i < 3; i++) {
+			if ((IIC_BSTS & 0x00000003) == 0x00000003)
+				check++;
+			udelay(3);
+		}
+
+		if (check == 3) {
+			IIC_BRST = 0x00000003;
+			break;
+		} else {
+			for (i = 0; i < 3; i++) {
+				IIC_BRST = 0x00000002;
+				udelay(8);
+				IIC_BRST = 0x00000003;
+				udelay(8);
+			}
+		}
+	}
+
+	IIC_BRST = 0x00000002;
+	IIC_BRST = 0x00000003;
+
+	value	=  SYS_IIC_DTRM_Bit_STA | SYS_IIC_DTRM_Bit_ACK;
+	value	|= (((unsigned short)EEPROM_ADDRESS & SYS_IIC_DTRM_Bit_DATA) |
+		    (unsigned short)0x0000);
+	IIC_DTRM = value;
+	POLL_INT_REQ(&IIC_ICR);
+
+	/** send offset of MAC address in EEPROM **/
+	IIC_DTRM = (unsigned char)((MAC_OFFSET & 0xFF00) >> 8);
+	POLL_INT_REQ(&IIC_ICR);
+
+	IIC_DTRM = (unsigned char)(MAC_OFFSET & 0x00FF);
+	POLL_INT_REQ(&IIC_ICR);
+
+	udelay(1000);
+
+	value	=  SYS_IIC_DTRM_Bit_STA;
+	value	|= (((unsigned short)EEPROM_ADDRESS & SYS_IIC_DTRM_Bit_DATA) |
+		    (unsigned short)0x0001);
+	IIC_DTRM = value;
+	POLL_INT_REQ(&IIC_ICR);
+
+	IIC_DTRM = 0x00000000;
+	while (mac_length > 0) {
+		POLL_INT_REQ(&IIC_ICR);
+
+		data = IIC_DREC;
+		mac_length--;
+		if (mac_length == 0)
+			value = 0x00000300;	/* stop IIC bus */
+		else if (mac_length == 1)
+			value = 0x00000100;	/* no ack */
+		else
+			value = 0x00000000;	/* ack */
+		IIC_DTRM = value;
+		*mac_buf++ = (unsigned char)(data & 0xff);
+	}
+
+	/* restore GnICR.LV and GnICR.IE */
+	flags = arch_local_cli_save();
+	IIC_ICR = (orig_gicr & (GxICR_LEVEL | GxICR_ENABLE));
+	tmp = IIC_ICR;
+	arch_local_irq_restore(flags);
+
+	return 0;
+}
+#endif /* MN10300_USE_EXT_EEPROM */
+#endif /* _ASM_UNIT_SMSC911X_H */
diff --git a/arch/mn10300/unit-asb2364/include/unit/timex.h b/arch/mn10300/unit-asb2364/include/unit/timex.h
new file mode 100644
index 0000000..42f32db
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/timex.h
@@ -0,0 +1,155 @@
+/* timex.h: MN2WS0038 architecture timer specifications
+ *
+ * Copyright (C) 2002, 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+#ifndef _ASM_UNIT_TIMEX_H
+#define _ASM_UNIT_TIMEX_H
+
+#include <asm/timer-regs.h>
+#include <unit/clock.h>
+#include <asm/param.h>
+
+/*
+ * jiffies counter specifications
+ */
+
+#define	TMJCBR_MAX		0xffffff	/* 24bit */
+#define	TMJCIRQ			TMTIRQ
+
+#ifndef __ASSEMBLY__
+
+#define MN10300_SRC_IOBCLK	MN10300_IOBCLK
+
+#ifndef HZ
+# error HZ undeclared.
+#endif /* !HZ */
+
+#define MN10300_JCCLK		(MN10300_SRC_IOBCLK)
+#define MN10300_TSCCLK		(MN10300_SRC_IOBCLK)
+
+#define MN10300_JC_PER_HZ	((MN10300_JCCLK + HZ / 2) / HZ)
+#define MN10300_TSC_PER_HZ	((MN10300_TSCCLK + HZ / 2) / HZ)
+
+/* Check bit width of MTM interval value that sets base register */
+#if (MN10300_JC_PER_HZ - 1) > TMJCBR_MAX
+# error MTM tick timer interval value is overflow.
+#endif
+
+static inline void stop_jiffies_counter(void)
+{
+	u16 tmp;
+	TMTMD = 0;
+	tmp = TMTMD;
+}
+
+static inline void reload_jiffies_counter(u32 cnt)
+{
+	u32 tmp;
+
+	TMTBR = cnt;
+	tmp = TMTBR;
+
+	TMTMD = TMTMD_TMTLDE;
+	TMTMD = TMTMD_TMTCNE;
+	tmp = TMTMD;
+}
+
+#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_CLOCKEVENTS) && \
+    !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
+/*
+ * If we aren't using broadcasting, each core needs its own event timer.
+ * Since CPU0 uses the tick timer which is 24-bits, we use timer 4 & 5
+ * cascaded to 32-bits for CPU1 (but only really use 24-bits to match
+ * CPU0).
+ */
+
+#define	TMJC1IRQ		TM5IRQ
+
+static inline void stop_jiffies_counter1(void)
+{
+	u8 tmp;
+	TM4MD = 0;
+	TM5MD = 0;
+	tmp = TM4MD;
+	tmp = TM5MD;
+}
+
+static inline void reload_jiffies_counter1(u32 cnt)
+{
+	u32 tmp;
+
+	TM45BR = cnt;
+	tmp = TM45BR;
+
+	TM4MD = TM4MD_INIT_COUNTER;
+	tmp = TM4MD;
+
+	TM5MD = TM5MD_SRC_TM4CASCADE | TM5MD_INIT_COUNTER;
+	TM5MD = TM5MD_SRC_TM4CASCADE | TM5MD_COUNT_ENABLE;
+	tmp = TM5MD;
+
+	TM4MD = TM4MD_COUNT_ENABLE;
+	tmp = TM4MD;
+}
+#endif /* CONFIG_SMP&GENERIC_CLOCKEVENTS&!GENERIC_CLOCKEVENTS_BROADCAST */
+
+#endif /* !__ASSEMBLY__ */
+
+
+/*
+ * timestamp counter specifications
+ */
+#define	TMTSCBR_MAX	0xffffffff
+
+#ifndef __ASSEMBLY__
+
+/* Use 32-bit timestamp counter */
+#define	TMTSCMD		TMSMD
+#define	TMTSCBR		TMSBR
+#define	TMTSCBC		TMSBC
+#define	TMTSCICR	TMSICR
+
+static inline void startup_timestamp_counter(void)
+{
+	u32 sync;
+
+	/* set up TMS(Timestamp) 32bit timer register to count real time
+	 * - count down from 4Gig-1 to 0 and wrap at IOBCLK rate
+	 */
+
+	TMTSCBR = TMTSCBR_MAX;
+	sync = TMTSCBR;
+
+	TMTSCICR = 0;
+	sync = TMTSCICR;
+
+	TMTSCMD = TMTMD_TMTLDE;
+	TMTSCMD = TMTMD_TMTCNE;
+	sync = TMTSCMD;
+}
+
+static inline void shutdown_timestamp_counter(void)
+{
+	TMTSCMD = 0;
+}
+
+/*
+ * we use a cascaded pair of 16-bit down-counting timers to count I/O
+ * clock cycles for the purposes of time keeping
+ */
+typedef unsigned long cycles_t;
+
+static inline cycles_t read_timestamp_counter(void)
+{
+	return (cycles_t)~TMTSCBC;
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_UNIT_TIMEX_H */
diff --git a/arch/mn10300/unit-asb2364/irq-fpga.c b/arch/mn10300/unit-asb2364/irq-fpga.c
new file mode 100644
index 0000000..073e2cc
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/irq-fpga.c
@@ -0,0 +1,108 @@
+/* ASB2364 FPGA interrupt multiplexing
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <unit/fpga-regs.h>
+
+/*
+ * FPGA PIC operations
+ */
+static void asb2364_fpga_mask(struct irq_data *d)
+{
+	ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0001;
+	SyncExBus();
+}
+
+static void asb2364_fpga_ack(struct irq_data *d)
+{
+	ASB2364_FPGA_REG_IRQ(d->irq - NR_CPU_IRQS) = 0x0001;
+	SyncExBus();
+}
+
+static void asb2364_fpga_mask_ack(struct irq_data *d)
+{
+	ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_IRQ(d->irq - NR_CPU_IRQS) = 0x0001;
+	SyncExBus();
+}
+
+static void asb2364_fpga_unmask(struct irq_data *d)
+{
+	ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0000;
+	SyncExBus();
+}
+
+static struct irq_chip asb2364_fpga_pic = {
+	.name		= "fpga",
+	.irq_ack	= asb2364_fpga_ack,
+	.irq_mask	= asb2364_fpga_mask,
+	.irq_mask_ack	= asb2364_fpga_mask_ack,
+	.irq_unmask	= asb2364_fpga_unmask,
+};
+
+/*
+ * FPGA PIC interrupt handler
+ */
+static irqreturn_t fpga_interrupt(int irq, void *_mask)
+{
+	if ((ASB2364_FPGA_REG_IRQ_LAN  & 0x0001) != 0x0001)
+		generic_handle_irq(FPGA_LAN_IRQ);
+	if ((ASB2364_FPGA_REG_IRQ_UART & 0x0001) != 0x0001)
+		generic_handle_irq(FPGA_UART_IRQ);
+	if ((ASB2364_FPGA_REG_IRQ_I2C  & 0x0001) != 0x0001)
+		generic_handle_irq(FPGA_I2C_IRQ);
+	if ((ASB2364_FPGA_REG_IRQ_USB  & 0x0001) != 0x0001)
+		generic_handle_irq(FPGA_USB_IRQ);
+	if ((ASB2364_FPGA_REG_IRQ_FPGA & 0x0001) != 0x0001)
+		generic_handle_irq(FPGA_FPGA_IRQ);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Define an interrupt action for each FPGA PIC output
+ */
+static struct irqaction fpga_irq[]  = {
+	[0] = {
+		.handler	= fpga_interrupt,
+		.flags		= IRQF_SHARED,
+		.name		= "fpga",
+	},
+};
+
+/*
+ * Initialise the FPGA's PIC
+ */
+void __init irq_fpga_init(void)
+{
+	int irq;
+
+	ASB2364_FPGA_REG_MASK_LAN  = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_UART = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_I2C  = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_USB  = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_FPGA = 0x0001;
+	SyncExBus();
+
+	for (irq = NR_CPU_IRQS; irq < NR_IRQS; irq++)
+		irq_set_chip_and_handler(irq, &asb2364_fpga_pic,
+					 handle_level_irq);
+
+	/* the FPGA drives the XIRQ1 input on the CPU PIC */
+	setup_irq(XIRQ1, &fpga_irq[0]);
+}
diff --git a/arch/mn10300/unit-asb2364/leds.c b/arch/mn10300/unit-asb2364/leds.c
new file mode 100644
index 0000000..1ff830c
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/leds.c
@@ -0,0 +1,98 @@
+/* leds.c: ASB2364 peripheral 7seg LEDs x4 support
+ *
+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/intctl-regs.h>
+#include <asm/rtc-regs.h>
+#include <unit/leds.h>
+
+#if MN10300_USE_7SEGLEDS
+static const u8 asb2364_led_hex_tbl[16] = {
+	0x80, 0xf2, 0x48, 0x60, 0x32, 0x24, 0x04, 0xf0,
+	0x00, 0x20, 0x10, 0x06, 0x8c, 0x42, 0x0c, 0x1c
+};
+
+static const u32 asb2364_led_chase_tbl[6] = {
+	~0x02020202,	/* top		- segA */
+	~0x04040404,	/* right top	- segB */
+	~0x08080808,	/* right bottom	- segC */
+	~0x10101010,	/* bottom	- segD */
+	~0x20202020,	/* left bottom	- segE */
+	~0x40404040,	/* left top	- segF */
+};
+
+static unsigned asb2364_led_chase;
+
+void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points)
+{
+	u32 leds;
+
+	leds = asb2364_led_hex_tbl[(val/1000) % 10];
+	leds <<= 8;
+	leds |= asb2364_led_hex_tbl[(val/100) % 10];
+	leds <<= 8;
+	leds |= asb2364_led_hex_tbl[(val/10) % 10];
+	leds <<= 8;
+	leds |= asb2364_led_hex_tbl[val % 10];
+	leds |= points^0x01010101;
+
+	ASB2364_7SEGLEDS = leds;
+}
+
+void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points)
+{
+	u32 leds;
+
+	leds = asb2364_led_hex_tbl[(val/1000) % 10];
+	leds <<= 8;
+	leds |= asb2364_led_hex_tbl[(val/100) % 10];
+	leds <<= 8;
+	leds |= asb2364_led_hex_tbl[(val/10) % 10];
+	leds <<= 8;
+	leds |= asb2364_led_hex_tbl[val % 10];
+	leds |= points^0x01010101;
+
+	ASB2364_7SEGLEDS = leds;
+}
+
+/* display triple horizontal bar and exception code */
+void peripheral_leds_display_exception(enum exception_code code)
+{
+	u32 leds;
+
+	leds = asb2364_led_hex_tbl[(code/0x100) % 0x10];
+	leds <<= 8;
+	leds |= asb2364_led_hex_tbl[(code/0x10) % 0x10];
+	leds <<= 8;
+	leds |= asb2364_led_hex_tbl[code % 0x10];
+	leds |= 0x6d010101;
+
+	ASB2364_7SEGLEDS = leds;
+}
+
+void peripheral_leds_led_chase(void)
+{
+	ASB2364_7SEGLEDS = asb2364_led_chase_tbl[asb2364_led_chase];
+	asb2364_led_chase++;
+	if (asb2364_led_chase >= 6)
+		asb2364_led_chase = 0;
+}
+#else  /* MN10300_USE_7SEGLEDS */
+void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points) { }
+void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points) { }
+void peripheral_leds_display_exception(enum exception_code code) { }
+void peripheral_leds_led_chase(void) { }
+#endif /* MN10300_USE_7SEGLEDS */
diff --git a/arch/mn10300/unit-asb2364/smsc911x.c b/arch/mn10300/unit-asb2364/smsc911x.c
new file mode 100644
index 0000000..544a73e
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/smsc911x.c
@@ -0,0 +1,58 @@
+/* Specification for the SMSC911x NIC
+ *
+ * Copyright (C) 2006 Matsushita Electric Industrial Co., Ltd.
+ * All Rights Reserved.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/smsc911x.h>
+#include <unit/smsc911x.h>
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags		= SMSC911X_USE_32BIT,
+};
+
+static struct resource smsc911x_resources[] = {
+	[0] = {
+		.start	= SMSC911X_BASE,
+		.end	= SMSC911X_BASE_END,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= SMSC911X_IRQ,
+		.end	= SMSC911X_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smsc911x_device = {
+	.name		= "smsc911x",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(smsc911x_resources),
+	.resource	= smsc911x_resources,
+	.dev		= {
+		.platform_data = &smsc911x_config,
+	}
+};
+
+/*
+ * add platform devices
+ */
+static int __init unit_device_init(void)
+{
+	platform_device_register(&smsc911x_device);
+	return 0;
+}
+
+device_initcall(unit_device_init);
diff --git a/arch/mn10300/unit-asb2364/unit-init.c b/arch/mn10300/unit-asb2364/unit-init.c
new file mode 100644
index 0000000..6359b41
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/unit-init.c
@@ -0,0 +1,132 @@
+/* ASB2364 initialisation
+ *
+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <asm/intctl-regs.h>
+#include <asm/serial-regs.h>
+#include <unit/fpga-regs.h>
+#include <unit/serial.h>
+#include <unit/smsc911x.h>
+
+#define TTYS0_SERIAL_IER	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 2, u8)
+#define LAN_IRQ_CFG		__SYSREG(SMSC911X_BASE + 0x54, u32)
+#define LAN_INT_EN		__SYSREG(SMSC911X_BASE + 0x5c, u32)
+
+/*
+ * initialise some of the unit hardware before gdbstub is set up
+ */
+asmlinkage void __init unit_init(void)
+{
+	/* Make sure we aren't going to get unexpected interrupts */
+	TTYS0_SERIAL_IER = 0;
+	SC0RXICR = 0;
+	SC0TXICR = 0;
+	SC1RXICR = 0;
+	SC1TXICR = 0;
+	SC2RXICR = 0;
+	SC2TXICR = 0;
+
+	/* Attempt to reset the FPGA attached peripherals */
+	ASB2364_FPGA_REG_RESET_LAN = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_UART = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_I2C = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_USB = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_AV = 0x0000;
+	SyncExBus();
+
+	/* set up the external interrupts */
+
+	/* XIRQ[0]: NAND RXBY */
+	/* SET_XIRQ_TRIGGER(0, XIRQ_TRIGGER_LOWLEVEL); */
+
+	/* XIRQ[1]: LAN, UART, I2C, USB, PCI, FPGA */
+	SET_XIRQ_TRIGGER(1, XIRQ_TRIGGER_LOWLEVEL);
+
+	/* XIRQ[2]: Extend Slot 1-9 */
+	/* SET_XIRQ_TRIGGER(2, XIRQ_TRIGGER_LOWLEVEL); */
+
+#if defined(CONFIG_EXT_SERIAL_IRQ_LEVEL) &&	\
+    defined(CONFIG_ETHERNET_IRQ_LEVEL) &&	\
+    (CONFIG_EXT_SERIAL_IRQ_LEVEL != CONFIG_ETHERNET_IRQ_LEVEL)
+# error CONFIG_EXT_SERIAL_IRQ_LEVEL != CONFIG_ETHERNET_IRQ_LEVEL
+#endif
+
+#if defined(CONFIG_EXT_SERIAL_IRQ_LEVEL)
+	set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_EXT_SERIAL_IRQ_LEVEL));
+#elif defined(CONFIG_ETHERNET_IRQ_LEVEL)
+	set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_ETHERNET_IRQ_LEVEL));
+#endif
+}
+
+/*
+ * initialise the rest of the unit hardware after gdbstub is ready
+ */
+asmlinkage void __init unit_setup(void)
+{
+	/* Release the reset on the SMSC911X so that it is ready by the time we
+	 * need it */
+	ASB2364_FPGA_REG_RESET_LAN = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_UART = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_I2C = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_USB = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_AV = 0x0001;
+	SyncExBus();
+
+	/* Make sure the ethernet chipset isn't going to give us an interrupt
+	 * storm from stuff it was doing pre-reset */
+	LAN_IRQ_CFG = 0;
+	LAN_INT_EN = 0;
+}
+
+/*
+ * initialise the external interrupts used by a unit of this type
+ */
+void __init unit_init_IRQ(void)
+{
+	unsigned int extnum;
+
+	for (extnum = 0 ; extnum < NR_XIRQS ; extnum++) {
+		switch (GET_XIRQ_TRIGGER(extnum)) {
+			/* LEVEL triggered interrupts should be made
+			 * post-ACK'able as they hold their lines until
+			 * serviced
+			 */
+		case XIRQ_TRIGGER_HILEVEL:
+		case XIRQ_TRIGGER_LOWLEVEL:
+			mn10300_set_lateack_irq_type(XIRQ2IRQ(extnum));
+			break;
+		default:
+			break;
+		}
+	}
+
+#define IRQCTL	__SYSREG(0xd5000090, u32)
+	IRQCTL |= 0x02;
+
+	irq_fpga_init();
+}