mirror of https://github.com/hak5/openwrt.git
11200 lines
295 KiB
Diff
11200 lines
295 KiB
Diff
From c462e1a613c8f84bb503189b0796d036dd1e5376 Mon Sep 17 00:00:00 2001
|
|
From: Jason Jin <jason.jin@freescale.com>
|
|
Date: Thu, 4 Aug 2011 09:59:35 +0800
|
|
Subject: [PATCH 01/52] Coldfire architecture support in Linux 2.6.38
|
|
|
|
Coldfire architecture support in Linux 2.6.38.
|
|
|
|
Signed-off-by: Alison Wang <b18965@freescale.com>
|
|
Signed-off-by: Jason Jin <jason.jin@freescale.com>
|
|
---
|
|
arch/m68k/Kconfig | 279 +++++++++-
|
|
arch/m68k/Kconfig.debug | 9 +
|
|
arch/m68k/Makefile | 48 ++-
|
|
arch/m68k/boot/Makefile | 68 +++
|
|
arch/m68k/coldfire/Makefile | 10 +
|
|
arch/m68k/coldfire/common/Makefile | 7 +
|
|
arch/m68k/coldfire/common/cache.c | 45 ++
|
|
arch/m68k/coldfire/common/clk.c | 51 ++
|
|
arch/m68k/coldfire/common/entry.S | 745 ++++++++++++++++++++++++
|
|
arch/m68k/coldfire/common/head.S | 466 +++++++++++++++
|
|
arch/m68k/coldfire/common/ints.c | 544 ++++++++++++++++++
|
|
arch/m68k/coldfire/common/muldi3.S | 73 +++
|
|
arch/m68k/coldfire/common/signal.c | 991 ++++++++++++++++++++++++++++++++
|
|
arch/m68k/coldfire/common/traps.c | 457 +++++++++++++++
|
|
arch/m68k/include/asm/atomic.h | 33 +-
|
|
arch/m68k/include/asm/bitops_mm.h | 12 +-
|
|
arch/m68k/include/asm/bootinfo.h | 42 ++
|
|
arch/m68k/include/asm/cacheflush_mm.h | 14 +-
|
|
arch/m68k/include/asm/cf-sram.h | 21 +
|
|
arch/m68k/include/asm/cf_bitops.h | 443 ++++++++++++++
|
|
arch/m68k/include/asm/cf_cacheflush.h | 20 +
|
|
arch/m68k/include/asm/cf_entry.h | 153 +++++
|
|
arch/m68k/include/asm/cf_io.h | 185 ++++++
|
|
arch/m68k/include/asm/cf_pgalloc.h | 112 ++++
|
|
arch/m68k/include/asm/cf_pgtable.h | 364 ++++++++++++
|
|
arch/m68k/include/asm/cf_raw_io.h | 188 ++++++
|
|
arch/m68k/include/asm/cf_tlbflush.h | 66 +++
|
|
arch/m68k/include/asm/cf_uaccess.h | 262 +++++++++
|
|
arch/m68k/include/asm/cf_virtconvert.h | 63 ++
|
|
arch/m68k/include/asm/cfcache.h | 146 +++++
|
|
arch/m68k/include/asm/cfmmu.h | 112 ++++
|
|
arch/m68k/include/asm/coldfire.h | 70 ++-
|
|
arch/m68k/include/asm/delay_mm.h | 42 ++-
|
|
arch/m68k/include/asm/div64.h | 11 +-
|
|
arch/m68k/include/asm/dma.h | 109 ++++-
|
|
arch/m68k/include/asm/elf.h | 70 +++-
|
|
arch/m68k/include/asm/io_mm.h | 234 ++++++--
|
|
arch/m68k/include/asm/irq.h | 14 +-
|
|
arch/m68k/include/asm/machdep.h | 15 +-
|
|
arch/m68k/include/asm/mcfdspi.h | 59 ++
|
|
arch/m68k/include/asm/mcfsim.h | 121 ++++
|
|
arch/m68k/include/asm/mcfuart.h | 64 ++
|
|
arch/m68k/include/asm/mmu.h | 15 +-
|
|
arch/m68k/include/asm/mmu_context.h | 184 ++++++-
|
|
arch/m68k/include/asm/page.h | 10 +-
|
|
arch/m68k/include/asm/page_mm.h | 61 ++
|
|
arch/m68k/include/asm/page_offset.h | 21 +-
|
|
arch/m68k/include/asm/pgalloc.h | 12 +-
|
|
arch/m68k/include/asm/pgtable_mm.h | 36 ++-
|
|
arch/m68k/include/asm/processor.h | 45 ++-
|
|
arch/m68k/include/asm/ptrace.h | 48 ++-
|
|
arch/m68k/include/asm/raw_io.h | 15 +-
|
|
arch/m68k/include/asm/segment.h | 17 +
|
|
arch/m68k/include/asm/setup.h | 36 ++
|
|
arch/m68k/include/asm/signal.h | 10 +-
|
|
arch/m68k/include/asm/string.h | 20 +-
|
|
arch/m68k/include/asm/swab.h | 15 +-
|
|
arch/m68k/include/asm/system_mm.h | 23 +-
|
|
arch/m68k/include/asm/tlbflush.h | 24 +-
|
|
arch/m68k/include/asm/uaccess_mm.h | 80 ++--
|
|
arch/m68k/include/asm/unistd.h | 11 +-
|
|
arch/m68k/include/asm/virtconvert.h | 11 +
|
|
arch/m68k/kernel/Makefile | 23 +-
|
|
arch/m68k/kernel/asm-offsets.c | 28 +
|
|
arch/m68k/kernel/dma.c | 47 ++-
|
|
arch/m68k/kernel/process.c | 66 +++
|
|
arch/m68k/kernel/setup.c | 72 ++-
|
|
arch/m68k/kernel/sys_m68k.c | 80 +++
|
|
arch/m68k/kernel/time.c | 142 +++++-
|
|
arch/m68k/kernel/vmlinux-cf.lds | 142 +++++
|
|
arch/m68k/kernel/vmlinux.lds.S | 12 +-
|
|
arch/m68k/lib/checksum.c | 129 +++++
|
|
arch/m68k/lib/muldi3.c | 13 +
|
|
arch/m68k/lib/string.c | 68 +++
|
|
arch/m68k/lib/uaccess.c | 247 ++++++++
|
|
arch/m68k/mm/Makefile | 2 +
|
|
arch/m68k/mm/cache.c | 19 +
|
|
arch/m68k/mm/cf-mmu.c | 311 ++++++++++
|
|
arch/m68k/mm/cf-sram.c | 80 +++
|
|
arch/m68k/mm/hwtest.c | 10 +
|
|
arch/m68k/mm/init.c | 15 +-
|
|
arch/m68k/mm/kmap.c | 82 +++-
|
|
arch/m68k/mm/memory.c | 17 +
|
|
fs/namespace.c | 8 +
|
|
include/linux/fsl_devices.h | 14 +-
|
|
85 files changed, 8962 insertions(+), 197 deletions(-)
|
|
create mode 100644 arch/m68k/boot/Makefile
|
|
create mode 100644 arch/m68k/coldfire/Makefile
|
|
create mode 100644 arch/m68k/coldfire/common/Makefile
|
|
create mode 100644 arch/m68k/coldfire/common/cache.c
|
|
create mode 100644 arch/m68k/coldfire/common/clk.c
|
|
create mode 100644 arch/m68k/coldfire/common/entry.S
|
|
create mode 100644 arch/m68k/coldfire/common/head.S
|
|
create mode 100644 arch/m68k/coldfire/common/ints.c
|
|
create mode 100644 arch/m68k/coldfire/common/muldi3.S
|
|
create mode 100644 arch/m68k/coldfire/common/signal.c
|
|
create mode 100644 arch/m68k/coldfire/common/traps.c
|
|
create mode 100644 arch/m68k/include/asm/cf-sram.h
|
|
create mode 100644 arch/m68k/include/asm/cf_bitops.h
|
|
create mode 100644 arch/m68k/include/asm/cf_cacheflush.h
|
|
create mode 100644 arch/m68k/include/asm/cf_entry.h
|
|
create mode 100644 arch/m68k/include/asm/cf_io.h
|
|
create mode 100644 arch/m68k/include/asm/cf_pgalloc.h
|
|
create mode 100644 arch/m68k/include/asm/cf_pgtable.h
|
|
create mode 100644 arch/m68k/include/asm/cf_raw_io.h
|
|
create mode 100644 arch/m68k/include/asm/cf_tlbflush.h
|
|
create mode 100644 arch/m68k/include/asm/cf_uaccess.h
|
|
create mode 100644 arch/m68k/include/asm/cf_virtconvert.h
|
|
create mode 100644 arch/m68k/include/asm/cfcache.h
|
|
create mode 100644 arch/m68k/include/asm/cfmmu.h
|
|
create mode 100644 arch/m68k/include/asm/mcfdspi.h
|
|
create mode 100644 arch/m68k/kernel/vmlinux-cf.lds
|
|
create mode 100644 arch/m68k/mm/cf-mmu.c
|
|
create mode 100644 arch/m68k/mm/cf-sram.c
|
|
|
|
--- a/arch/m68k/Kconfig
|
|
+++ b/arch/m68k/Kconfig
|
|
@@ -9,6 +9,14 @@ config MMU
|
|
bool
|
|
default y
|
|
|
|
+config GENERIC_TIME
|
|
+ bool "Enable generic timer"
|
|
+ default n
|
|
+
|
|
+config GENERIC_CLOCKEVENTS
|
|
+ bool "Enable generic clockevents"
|
|
+ default n
|
|
+
|
|
config RWSEM_GENERIC_SPINLOCK
|
|
bool
|
|
default y
|
|
@@ -34,7 +42,7 @@ config GENERIC_CALIBRATE_DELAY
|
|
|
|
config TIME_LOW_RES
|
|
bool
|
|
- default y
|
|
+ default n
|
|
|
|
config GENERIC_IOMAP
|
|
bool
|
|
@@ -46,7 +54,7 @@ config ARCH_MAY_HAVE_PC_FDC
|
|
default y
|
|
|
|
config NO_IOPORT
|
|
- def_bool y
|
|
+ def_bool !(M5445X || M547X_8X || M5441X)
|
|
|
|
config NO_DMA
|
|
def_bool SUN3
|
|
@@ -105,6 +113,35 @@ config PCMCIA
|
|
To compile this driver as modules, choose M here: the
|
|
modules will be called pcmcia_core and ds.
|
|
|
|
+config COLDFIRE
|
|
+ bool "ColdFire V4e support"
|
|
+ default y
|
|
+ select CFV4E
|
|
+ help
|
|
+ Say Y if you want to build a kernel to run on one of the ColdFire
|
|
+ V4e boards.
|
|
+
|
|
+config CFV4E
|
|
+ bool
|
|
+ depends on COLDFIRE
|
|
+ select MMU_CFV4E if MMU
|
|
+ default y
|
|
+
|
|
+config FPU
|
|
+ bool "ColdFire V4e FPU support"
|
|
+ default n
|
|
+ help
|
|
+ This enables support for CFV4E FPU feature.
|
|
+
|
|
+config MCD_DMA
|
|
+ bool "ColdFire MCD DMA support"
|
|
+ depends on M547X_8X
|
|
+ default y
|
|
+ help
|
|
+ This enables support for the ColdFire 547x/548x family
|
|
+ multichannel DMA support. Many drivers need it.
|
|
+ If you want it, say Y
|
|
+
|
|
config AMIGA
|
|
bool "Amiga support"
|
|
select MMU_MOTOROLA if MMU
|
|
@@ -122,6 +159,16 @@ config ATARI
|
|
this kernel on an Atari, say Y here and browse the material
|
|
available in <file:Documentation/m68k>; otherwise say N.
|
|
|
|
+config PCI
|
|
+ bool "PCI bus support"
|
|
+ depends on M54455 || M547X_8X
|
|
+ default n
|
|
+ help
|
|
+ Find out whether you have a PCI motherboard. PCI is the name of a
|
|
+ bus system, i.e. the way the CPU talks to the other stuff inside
|
|
+ your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
|
|
+ VESA. If you have PCI, say Y, otherwise N.
|
|
+
|
|
config MAC
|
|
bool "Macintosh support"
|
|
select MMU_MOTOROLA if MMU
|
|
@@ -276,6 +323,147 @@ config M68060
|
|
If you anticipate running this kernel on a computer with a MC68060
|
|
processor, say Y. Otherwise, say N.
|
|
|
|
+config M5445X
|
|
+ bool "MCF5445x support"
|
|
+ depends on COLDFIRE
|
|
+ select GENERIC_TIME
|
|
+ select USB_EHCI_FSL
|
|
+ select HAVE_FSL_USB_DR
|
|
+ help
|
|
+ This option will add support for the MCF544x processor with mmu.
|
|
+
|
|
+config M54451
|
|
+ bool
|
|
+ depends on M5445X
|
|
+ default n
|
|
+
|
|
+config M54455
|
|
+ bool
|
|
+ depends on M5445X
|
|
+ default n
|
|
+
|
|
+choice
|
|
+ prompt "Model"
|
|
+ depends on M5445X
|
|
+ default M54451EVB
|
|
+ config M54451EVB
|
|
+ bool "M54451EVB"
|
|
+ select M54451
|
|
+ config M54455EVB
|
|
+ bool "M54455EVB"
|
|
+ select M54455
|
|
+endchoice
|
|
+
|
|
+config HAVE_FSL_USB_DR
|
|
+ bool
|
|
+ default n
|
|
+
|
|
+config M547X_8X
|
|
+ bool "MCF547x/MCF548x support"
|
|
+ depends on COLDFIRE
|
|
+ help
|
|
+ This option will add support for the MCF547x/MCF548x processor with mmu.
|
|
+
|
|
+config M547X
|
|
+ bool
|
|
+ depends on M547X_8X
|
|
+ default n
|
|
+
|
|
+config M548X
|
|
+ bool
|
|
+ depends on M547X_8X
|
|
+ default n
|
|
+
|
|
+choice
|
|
+ prompt "Model"
|
|
+ depends on M547X_8X
|
|
+ default M5485CFE
|
|
+
|
|
+config M5474LITE
|
|
+ bool "MCF5474LITE"
|
|
+ select M547X
|
|
+config M5475AFE
|
|
+ bool "MCF5475AFE"
|
|
+ select M547X
|
|
+config M5475BFE
|
|
+ bool "MCF5475BFE"
|
|
+ select M547X
|
|
+config M5475CFE
|
|
+ bool "MCF5475CFE"
|
|
+ select M547X
|
|
+config M5475DFE
|
|
+ bool "MCF5475DFE"
|
|
+ select M547X
|
|
+config M5475EFE
|
|
+ bool "MCF5475EFE"
|
|
+ select M547X
|
|
+config M5475FFE
|
|
+ bool "MCF5475FFE"
|
|
+ select M547X
|
|
+config M5484LITE
|
|
+ bool "MCF5484LITE"
|
|
+ select M548X
|
|
+config M5485AFE
|
|
+ bool "MCF5485AFE"
|
|
+ select M548X
|
|
+config M5485BFE
|
|
+ bool "MCF5485BFE"
|
|
+ select M548X
|
|
+config M5485CFE
|
|
+ bool "MCF5485CFE"
|
|
+ select M548X
|
|
+config M5485DFE
|
|
+ bool "MCF5485DFE"
|
|
+ select M548X
|
|
+config M5485EFE
|
|
+ bool "MCF5485EFE"
|
|
+ select M548X
|
|
+config M5485FFE
|
|
+ bool "MCF5485FFE"
|
|
+ select M548X
|
|
+
|
|
+endchoice
|
|
+
|
|
+config M5441X
|
|
+ bool "MCF5441x support"
|
|
+ depends on COLDFIRE
|
|
+ select GENERIC_TIME
|
|
+ select USB_EHCI_FSL
|
|
+ select HAVE_FSL_USB_DR
|
|
+ help
|
|
+ This option will add support for the MCF5441x processor with mmu.
|
|
+
|
|
+config M54418
|
|
+ bool
|
|
+ depends on M5441X
|
|
+ default n
|
|
+choice
|
|
+ prompt "Model"
|
|
+ depends on M5441X
|
|
+ default M54418EVB
|
|
+ config M54418EVB
|
|
+ bool "M54418EVB"
|
|
+ select M54418
|
|
+endchoice
|
|
+
|
|
+config MCFCLK
|
|
+ int
|
|
+ default 240000000 if M54451EVB
|
|
+ default 266666666 if M54455EVB
|
|
+ default 266000000 if M547X
|
|
+ default 200000000 if M548X
|
|
+ default 250000000 if M54418EVB && !USB_M5441X_PLLCLK
|
|
+ default 150000000 if M54418EVB && USB_M5441X_PLLCLK
|
|
+ help
|
|
+ Coldfire System clock.
|
|
+
|
|
+config MCF_USER_HALT
|
|
+ bool "Coldfire User Halt Enable"
|
|
+ depends on M5445X || M547X_8X || M5441X
|
|
+ default n
|
|
+ help
|
|
+ Enables the HALT instruction in User Mode.
|
|
+
|
|
config MMU_MOTOROLA
|
|
bool
|
|
|
|
@@ -283,6 +471,81 @@ config MMU_SUN3
|
|
bool
|
|
depends on MMU && !MMU_MOTOROLA
|
|
|
|
+config MMU_CFV4E
|
|
+ bool
|
|
+
|
|
+config SDRAM_BASE
|
|
+ hex
|
|
+ depends on COLDFIRE
|
|
+ default 0x40000000 if M5445X
|
|
+ default 0x00000000 if M547X_8X
|
|
+ default 0x40000000 if M5441X
|
|
+
|
|
+config SDRAM_SIZE
|
|
+ hex
|
|
+ depends on COLDFIRE
|
|
+ default 0x08000000 if M54451EVB
|
|
+ default 0x10000000 if M54455EVB
|
|
+ default 0x04000000 if M547X_8X
|
|
+ default 0x08000000 if M54418EVB
|
|
+
|
|
+config NOR_FLASH_BASE
|
|
+ hex "NOR Flash Base Address"
|
|
+ depends on COLDFIRE
|
|
+ default 0x00000000 if M54451EVB
|
|
+ default 0x00000000 if M54455EVB
|
|
+ default 0xE0000000 if M5475CFE
|
|
+ default 0xE0000000 if M5485CFE
|
|
+ default 0xFF800000 if M5484LITE
|
|
+ default 0xFF800000 if M5474LITE
|
|
+ default 0x00000000 if M54418EVB
|
|
+
|
|
+config DMA_BASE
|
|
+ hex
|
|
+ depends on COLDFIRE
|
|
+ default 0xef000000 if M5445X
|
|
+ default 0xef000000 if M547X_8X
|
|
+ default 0xdf000000 if M5441X
|
|
+
|
|
+config DMA_SIZE
|
|
+ hex
|
|
+ depends on COLDFIRE
|
|
+ default 0x1000000 if M5445X
|
|
+ default 0x800000 if M547X_8X
|
|
+ default 0x1000000 if M5441X
|
|
+
|
|
+config SRAM
|
|
+ bool "SRAM allocation APIs support on mcfv4 platform"
|
|
+ depends on COLDFIRE && (M5445X || M5441X)
|
|
+ default y
|
|
+ select GENERIC_ALLOCATOR
|
|
+
|
|
+config SRAM_BASE
|
|
+ hex
|
|
+ depends on COLDFIRE && SRAM
|
|
+ default 0x8ff00000 if M5445X
|
|
+ default 0x8ff00000 if M5441X
|
|
+
|
|
+config SRAM_SIZE
|
|
+ hex
|
|
+ depends on COLDFIRE && SRAM
|
|
+ default 0x8000 if M5445X
|
|
+ default 0x10000 if M5441X
|
|
+
|
|
+config SRAM_ALLOC_GRANULARITY
|
|
+ hex
|
|
+ depends on SRAM
|
|
+ default 0x200 if (M5445X || M5441X)
|
|
+
|
|
+config VDSO
|
|
+ bool "Support VDSO page"
|
|
+ depends on MMU
|
|
+ default n
|
|
+ help
|
|
+ This will enable support for the kernel mapping a vDSO page
|
|
+ in process space, and subsequently handing down the entry point
|
|
+ to the libc through the ELF auxiliary vector.
|
|
+
|
|
config M68KFPU_EMU
|
|
bool "Math emulation support (EXPERIMENTAL)"
|
|
depends on EXPERIMENTAL
|
|
@@ -449,6 +712,14 @@ config ZONE_DMA
|
|
source "drivers/pci/Kconfig"
|
|
|
|
source "drivers/zorro/Kconfig"
|
|
+endmenu
|
|
+
|
|
+menu "Power management options"
|
|
+
|
|
+config PM
|
|
+ bool "Power Management support"
|
|
+ help
|
|
+ Support processor power management modes
|
|
|
|
endmenu
|
|
|
|
@@ -583,7 +854,7 @@ config DN_SERIAL
|
|
|
|
config SERIAL_CONSOLE
|
|
bool "Support for serial port console"
|
|
- depends on (AMIGA || ATARI || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
|
|
+ depends on (AMIGA || ATARI || SUN3 || SUN3X || VME || APOLLO || COLDFIRE) && (ATARI_MFPSER=y || ATARI_MIDI=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL || SERIAL_COLDFIRE)
|
|
---help---
|
|
If you say Y here, it will be possible to use a serial port as the
|
|
system console (the system console is the device which receives all
|
|
@@ -606,6 +877,8 @@ config SERIAL_CONSOLE
|
|
|
|
endmenu
|
|
|
|
+source "kernel/time/Kconfig"
|
|
+
|
|
source "fs/Kconfig"
|
|
|
|
source "arch/m68k/Kconfig.debug"
|
|
--- a/arch/m68k/Kconfig.debug
|
|
+++ b/arch/m68k/Kconfig.debug
|
|
@@ -2,4 +2,13 @@ menu "Kernel hacking"
|
|
|
|
source "lib/Kconfig.debug"
|
|
|
|
+config BOOTPARAM
|
|
+ bool 'Compiled-in Kernel Boot Parameter'
|
|
+ depends on COLDFIRE
|
|
+
|
|
+config BOOTPARAM_STRING
|
|
+ string 'Kernel Boot Parameter'
|
|
+ default 'console=ttyS0,115200'
|
|
+ depends on BOOTPARAM
|
|
+
|
|
endmenu
|
|
--- a/arch/m68k/Makefile
|
|
+++ b/arch/m68k/Makefile
|
|
@@ -1,6 +1,8 @@
|
|
#
|
|
# m68k/Makefile
|
|
#
|
|
+# Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+#
|
|
# This file is included by the global makefile so that you can add your own
|
|
# architecture-specific flags and dependencies. Remember to do have actions
|
|
# for "archclean" and "archdep" for cleaning up and making dependencies for
|
|
@@ -10,13 +12,13 @@
|
|
# License. See the file "COPYING" in the main directory of this archive
|
|
# for more details.
|
|
#
|
|
-# Copyright (C) 1994 by Hamish Macdonald
|
|
-#
|
|
|
|
-KBUILD_DEFCONFIG := multi_defconfig
|
|
+KBUILD_DEFCONFIG := amiga_defconfig#multi_defconfig
|
|
|
|
# override top level makefile
|
|
+ifndef CONFIG_COLDFIRE
|
|
AS += -m68020
|
|
+endif
|
|
LDFLAGS := -m m68kelf
|
|
KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
|
|
ifneq ($(SUBARCH),$(ARCH))
|
|
@@ -30,12 +32,18 @@ ifdef CONFIG_SUN3
|
|
LDFLAGS_vmlinux = -N
|
|
endif
|
|
|
|
+ifdef CONFIG_COLDFIRE
|
|
+OBJCOPYFLAGS := -O binary -R .note -R .note.gnu.build-id -R .comment -S
|
|
+# LDFLAGS_vmlinux = --verbose
|
|
+endif
|
|
+
|
|
CHECKFLAGS += -D__mc68000__
|
|
|
|
# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
|
|
KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
|
|
|
|
# enable processor switch if compiled only for a single cpu
|
|
+ifndef CONFIG_COLDFIRE
|
|
ifndef CONFIG_M68020
|
|
ifndef CONFIG_M68030
|
|
|
|
@@ -49,6 +57,22 @@ endif
|
|
|
|
endif
|
|
endif
|
|
+endif
|
|
+
|
|
+ifdef CONFIG_M5445X
|
|
+KBUILD_CFLAGS += -march=isac -mcpu=54455 -msoft-float -g
|
|
+KBUILD_AFLAGS += -march=isac -mcpu=54455 -msoft-float
|
|
+endif
|
|
+
|
|
+ifdef CONFIG_M547X_8X
|
|
+KBUILD_CFLAGS += -mcfv4e -g
|
|
+KBUILD_AFLAGS += -mcfv4e
|
|
+endif
|
|
+
|
|
+ifdef CONFIG_M5441X
|
|
+KBUILD_CFLAGS += -march=isac -mcpu=54418 -msoft-float -g
|
|
+KBUILD_AFLAGS += -march=isac -mcpu=54418 -msoft-float
|
|
+endif
|
|
|
|
ifdef CONFIG_KGDB
|
|
# If configured for kgdb support, include debugging infos and keep the
|
|
@@ -57,8 +81,12 @@ KBUILD_CFLAGS := $(subst -fomit-frame-po
|
|
endif
|
|
|
|
ifndef CONFIG_SUN3
|
|
+ifndef CONFIG_COLDFIRE
|
|
head-y := arch/m68k/kernel/head.o
|
|
else
|
|
+head-y := arch/m68k/coldfire/common/head.o
|
|
+endif
|
|
+else
|
|
head-y := arch/m68k/kernel/sun3-head.o
|
|
endif
|
|
|
|
@@ -79,7 +107,20 @@ core-$(CONFIG_SUN3) += arch/m68k/sun3/
|
|
core-$(CONFIG_M68040) += arch/m68k/fpsp040/
|
|
core-$(CONFIG_M68060) += arch/m68k/ifpsp060/
|
|
core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/
|
|
+core-$(CONFIG_COLDFIRE) += arch/m68k/coldfire/
|
|
+
|
|
+ifdef CONFIG_COLDFIRE
|
|
+boot := arch/m68k/boot
|
|
+
|
|
+all: uImage
|
|
|
|
+zImage zImage.srec uImage uImage.srec vmlinux.srec: vmlinux
|
|
+ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
|
|
+
|
|
+archclean:
|
|
+ $(Q)$(MAKE) $(clean)=$(boot)
|
|
+
|
|
+else
|
|
all: zImage
|
|
|
|
lilo: vmlinux
|
|
@@ -117,6 +158,7 @@ endif
|
|
|
|
archclean:
|
|
rm -f vmlinux.gz vmlinux.bz2
|
|
+endif
|
|
|
|
install:
|
|
sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
|
|
--- /dev/null
|
|
+++ b/arch/m68k/boot/Makefile
|
|
@@ -0,0 +1,68 @@
|
|
+#
|
|
+# arch/m68k/boot/Makefile
|
|
+#
|
|
+# Based on arch/sh/boot/Makefile by Stuart Menefy
|
|
+#
|
|
+# Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+# by Kurt Mahan <kmahan@freescale.com>
|
|
+#
|
|
+# This file is subject to the terms and conditions of the GNU General Public
|
|
+# License. See the file "COPYING" in the main directory of this archive
|
|
+# for more details.
|
|
+#
|
|
+
|
|
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
|
|
+
|
|
+#
|
|
+# Assign safe dummy values if these variables are not defined,
|
|
+# in order to suppress error message.
|
|
+#
|
|
+CONFIG_SDRAM_BASE ?= 0x40000000
|
|
+CONFIG_IMG_START ?= 0x00020000
|
|
+
|
|
+export CONFIG_SDRAM_BASE CONFIG_IMG_START
|
|
+
|
|
+targets := zImage zImage.srec vmlinux.srec uImage uImage.srec
|
|
+
|
|
+$(obj)/zImage: $(obj)/vmlinux.bin FORCE
|
|
+ $(call if_changed,gzip)
|
|
+ @echo ' Image $@ is ready'
|
|
+
|
|
+OBJCOPYFLAGS_zImage.srec := -I binary -O srec
|
|
+$(obj)/zImage.srec: $(obj)/zImage
|
|
+ $(call if_changed,objcopy)
|
|
+
|
|
+KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \
|
|
+ $$[$(CONFIG_SDRAM_BASE) + \
|
|
+ $(CONFIG_IMG_START)]')
|
|
+
|
|
+KERNEL_ENTRY := $(shell /bin/bash -c 'printf "0x%08x" \
|
|
+ $$[$(CONFIG_SDRAM_BASE) + \
|
|
+ $(CONFIG_IMG_START)]')
|
|
+
|
|
+quiet_cmd_uimage = UIMAGE $@
|
|
+ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A m68k -O linux -T kernel \
|
|
+ -C gzip -a $(KERNEL_LOAD) -e $(KERNEL_ENTRY) \
|
|
+ -n 'Linux-$(KERNELRELEASE)' -d $< $@
|
|
+
|
|
+$(obj)/uImage: $(obj)/vmlinux.bin.gz FORCE
|
|
+ $(call if_changed,uimage)
|
|
+ @echo ' Image $@ is ready'
|
|
+
|
|
+$(obj)/vmlinux.bin: vmlinux FORCE
|
|
+ $(call if_changed,objcopy)
|
|
+
|
|
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
|
|
+ $(call if_changed,gzip)
|
|
+
|
|
+OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec
|
|
+$(obj)/vmlinux.srec: $(obj)/vmlinux.bin
|
|
+ $(call if_changed,objcopy)
|
|
+
|
|
+OBJCOPYFLAGS_uImage.srec := -I binary -O srec
|
|
+$(obj)/uImage.srec: $(obj)/uImage
|
|
+ $(call if_changed,objcopy)
|
|
+
|
|
+clean-files += uImage uImage.srec \
|
|
+ zImage zImage.srec \
|
|
+ vmlinux.srec vmlinux.bin vmlinux.bin.gz
|
|
--- /dev/null
|
|
+++ b/arch/m68k/coldfire/Makefile
|
|
@@ -0,0 +1,10 @@
|
|
+#
|
|
+# Makefile for Linux arch/m68k/coldfire source directory
|
|
+#
|
|
+
|
|
+obj-y += common/
|
|
+obj-$(CONFIG_VDSO) += vdso/
|
|
+
|
|
+obj-$(CONFIG_M5445X) += m5445x/
|
|
+obj-$(CONFIG_M547X_8X) += m547x/
|
|
+obj-$(CONFIG_M5441X) += m5441x/
|
|
--- /dev/null
|
|
+++ b/arch/m68k/coldfire/common/Makefile
|
|
@@ -0,0 +1,7 @@
|
|
+#
|
|
+# Makefile for Linux arch/m68k/coldfire/common source directory
|
|
+#
|
|
+
|
|
+obj-y:= entry.o cache.o signal.o muldi3.o traps.o ints.o clk.o
|
|
+extra-y:= head.o
|
|
+
|
|
--- /dev/null
|
|
+++ b/arch/m68k/coldfire/common/cache.c
|
|
@@ -0,0 +1,45 @@
|
|
+/*
|
|
+ * linux/arch/m68k/coldfire/cache.c
|
|
+ *
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Matt Waddel Matt.Waddel@freescale.com
|
|
+ * Kurt Mahan kmahan@freescale.com
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.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/interrupt.h>
|
|
+#include <asm/cfcache.h>
|
|
+#include <asm/coldfire.h>
|
|
+#include <asm/system.h>
|
|
+
|
|
+/* Cache Control Reg shadow reg */
|
|
+unsigned long shadow_cacr;
|
|
+
|
|
+/**
|
|
+ * cacr_set - Set the Cache Control Register
|
|
+ * @x Value to set
|
|
+ */
|
|
+void cacr_set(unsigned long x)
|
|
+{
|
|
+ shadow_cacr = x;
|
|
+
|
|
+ __asm__ __volatile__ ("movec %0, %%cacr"
|
|
+ : /* no outputs */
|
|
+ : "r" (shadow_cacr));
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cacr_get - Get the current value of the Cache Control Register
|
|
+ *
|
|
+ * @return CACR value
|
|
+ */
|
|
+unsigned long cacr_get(void)
|
|
+{
|
|
+ return shadow_cacr;
|
|
+}
|
|
--- /dev/null
|
|
+++ b/arch/m68k/coldfire/common/clk.c
|
|
@@ -0,0 +1,51 @@
|
|
+/***************************************************************************/
|
|
+
|
|
+/*
|
|
+ * clk.c -- general ColdFire CPU kernel clk handling
|
|
+ *
|
|
+ * Copyright (C) 2009, Greg Ungerer (gerg@snapgear.com)
|
|
+ * Copyright (C) 2011 Freescale Semiconductore, 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 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/module.h>
|
|
+#include <linux/clk.h>
|
|
+#include <asm/coldfire.h>
|
|
+
|
|
+/***************************************************************************/
|
|
+
|
|
+struct clk *clk_get(struct device *dev, const char *id)
|
|
+{
|
|
+ return NULL;
|
|
+}
|
|
+EXPORT_SYMBOL(clk_get);
|
|
+
|
|
+int clk_enable(struct clk *clk)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(clk_enable);
|
|
+
|
|
+void clk_disable(struct clk *clk)
|
|
+{
|
|
+}
|
|
+EXPORT_SYMBOL(clk_disable);
|
|
+
|
|
+void clk_put(struct clk *clk)
|
|
+{
|
|
+}
|
|
+EXPORT_SYMBOL(clk_put);
|
|
+
|
|
+unsigned long clk_get_rate(struct clk *clk)
|
|
+{
|
|
+ return MCF_CLK;
|
|
+}
|
|
+EXPORT_SYMBOL(clk_get_rate);
|
|
+/***************************************************************************/
|
|
--- /dev/null
|
|
+++ b/arch/m68k/coldfire/common/entry.S
|
|
@@ -0,0 +1,745 @@
|
|
+/*
|
|
+ * arch/m68k/coldfire/entry.S
|
|
+ *
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Matt Waddel Matt.Waddel@freescale.com
|
|
+ * Kurt Mahan kmahan@freescale.com
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * Based on:
|
|
+ *
|
|
+ * arch/m68knommu/platform/5307/entry.S &
|
|
+ * arch/m68k/kernel/entry.S
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file README.legal in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
+#include <linux/sys.h>
|
|
+#include <linux/linkage.h>
|
|
+#include <asm/cf_entry.h>
|
|
+#include <asm/errno.h>
|
|
+#include <asm/setup.h>
|
|
+#include <asm/segment.h>
|
|
+#include <asm/traps.h>
|
|
+#include <asm/unistd.h>
|
|
+#include <asm/asm-offsets.h>
|
|
+
|
|
+/*
|
|
+ * TASK_INFO:
|
|
+ *
|
|
+ * - TINFO_PREEMPT (struct thread_info / preempt_count)
|
|
+ * Used to keep track of preemptability
|
|
+ * - TINFO_FLAGS (struct thread_info / flags - include/asm-m68k/thread_info.h)
|
|
+ * Various bit flags that are checked for scheduling/tracing
|
|
+ * Bits 0-7 are checked every exception exit
|
|
+ * 8-15 are checked every syscall exit
|
|
+ *
|
|
+ * TIF_SIGPENDING 6
|
|
+ * TIF_NEED_RESCHED 7
|
|
+ * TIF_DELAYED_TRACE 14
|
|
+ * TIF_SYSCALL_TRACE 15
|
|
+ * TIF_MEMDIE 16 (never checked here)
|
|
+ */
|
|
+
|
|
+.bss
|
|
+
|
|
+sw_ksp:
|
|
+.long 0
|
|
+
|
|
+sw_usp:
|
|
+.long 0
|
|
+
|
|
+.text
|
|
+
|
|
+.globl system_call
|
|
+.globl buserr
|
|
+.globl trap
|
|
+.globl resume
|
|
+.globl ret_from_exception
|
|
+.globl ret_from_signal
|
|
+.globl sys_call_table
|
|
+.globl ret_from_interrupt
|
|
+.globl inthandler
|
|
+
|
|
+ENTRY(buserr)
|
|
+#ifdef CONFIG_COLDFIRE_FOO
|
|
+ movew #0x2700,%sr /* lock interrupts */
|
|
+#endif
|
|
+ SAVE_ALL_INT
|
|
+#ifdef CONFIG_COLDFIRE_FOO
|
|
+ movew PT_0FF_SR(%sp),%d3 /* get original %sr */
|
|
+ oril #0x2000,%d3 /* set supervisor mode in it */
|
|
+ movew %d3,%sr /* recover irq state */
|
|
+#endif
|
|
+ GET_CURRENT(%d0)
|
|
+ movel %sp,%sp@- /* stack frame pointer argument */
|
|
+ jsr buserr_c
|
|
+ addql #4,%sp
|
|
+ jra .Lret_from_exception
|
|
+
|
|
+ENTRY(trap)
|
|
+ SAVE_ALL_INT
|
|
+ GET_CURRENT(%d0)
|
|
+ movel %sp,%sp@- /* stack frame pointer argument */
|
|
+ jsr trap_c
|
|
+ addql #4,%sp
|
|
+ jra .Lret_from_exception
|
|
+
|
|
+ /* After a fork we jump here directly from resume,
|
|
+ %d1 contains the previous task schedule_tail */
|
|
+ENTRY(ret_from_fork)
|
|
+ movel %d1,%sp@-
|
|
+ jsr schedule_tail
|
|
+ addql #4,%sp
|
|
+ jra .Lret_from_exception
|
|
+
|
|
+do_trace_entry:
|
|
+ movel #-ENOSYS,%d1 /* needed for strace */
|
|
+ movel %d1,%sp@(PT_OFF_D0)
|
|
+ subql #4,%sp
|
|
+ SAVE_SWITCH_STACK
|
|
+ jbsr syscall_trace
|
|
+ RESTORE_SWITCH_STACK
|
|
+ addql #4,%sp
|
|
+ movel %sp@(PT_OFF_ORIG_D0),%d0
|
|
+ cmpl #NR_syscalls,%d0
|
|
+ jcs syscall
|
|
+badsys:
|
|
+ movel #-ENOSYS,%d1
|
|
+ movel %d1,%sp@(PT_OFF_D0)
|
|
+ jra ret_from_exception
|
|
+
|
|
+do_trace_exit:
|
|
+ subql #4,%sp
|
|
+ SAVE_SWITCH_STACK
|
|
+ jbsr syscall_trace
|
|
+ RESTORE_SWITCH_STACK
|
|
+ addql #4,%sp
|
|
+ jra .Lret_from_exception
|
|
+
|
|
+ENTRY(ret_from_signal)
|
|
+ RESTORE_SWITCH_STACK
|
|
+ addql #4,%sp
|
|
+ jra .Lret_from_exception
|
|
+
|
|
+ENTRY(system_call)
|
|
+ SAVE_ALL_SYS
|
|
+
|
|
+ GET_CURRENT(%d1)
|
|
+ /* save top of frame */
|
|
+ movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
|
|
+
|
|
+ /* syscall trace */
|
|
+ tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
|
|
+ jmi do_trace_entry /* SYSCALL_TRACE is set */
|
|
+ cmpl #NR_syscalls,%d0
|
|
+ jcc badsys
|
|
+syscall:
|
|
+ movel #sys_call_table,%a0
|
|
+ asll #2,%d0
|
|
+ addl %d0,%a0
|
|
+ movel %a0@,%a0
|
|
+ jsr %a0@
|
|
+ movel %d0,%sp@(PT_OFF_D0) /* save the return value */
|
|
+ret_from_syscall:
|
|
+ movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0
|
|
+ jne syscall_exit_work /* flags set so process */
|
|
+1: RESTORE_ALL
|
|
+
|
|
+syscall_exit_work:
|
|
+ btst #5,%sp@(PT_OFF_SR) /* check if returning to kernel */
|
|
+ bnes 1b /* if so, skip resched, signals */
|
|
+
|
|
+ btstl #15,%d0 /* check if SYSCALL_TRACE */
|
|
+ jne do_trace_exit
|
|
+ btstl #14,%d0 /* check if DELAYED_TRACE */
|
|
+ jne do_delayed_trace
|
|
+ btstl #6,%d0 /* check if SIGPENDING */
|
|
+ jne do_signal_return
|
|
+ pea resume_userspace
|
|
+ jra schedule
|
|
+
|
|
+ENTRY(ret_from_exception)
|
|
+.Lret_from_exception:
|
|
+ btst #5,%sp@(PT_OFF_SR) /* check if returning to kernel */
|
|
+ bnes 1f /* if so, skip resched, signals */
|
|
+ movel %d0,%sp@- /* Only allow interrupts when we are */
|
|
+ move %sr,%d0 /* last one on the kernel stack, */
|
|
+ andl #ALLOWINT,%d0 /* otherwise stack overflow can occur */
|
|
+ move %d0,%sr /* during heavy interrupt load. */
|
|
+ movel %sp@+,%d0
|
|
+
|
|
+resume_userspace:
|
|
+ moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0
|
|
+ jne exit_work /* SIGPENDING and/or NEED_RESCHED set */
|
|
+1: RESTORE_ALL
|
|
+
|
|
+exit_work:
|
|
+ /* save top of frame */
|
|
+ movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
|
|
+ btstl #6,%d0 /* check for SIGPENDING in flags */
|
|
+ jne do_signal_return
|
|
+ pea resume_userspace
|
|
+ jra schedule
|
|
+
|
|
+do_signal_return:
|
|
+ subql #4,%sp /* dummy return address */
|
|
+ SAVE_SWITCH_STACK
|
|
+ pea %sp@(SWITCH_STACK_SIZE)
|
|
+ clrl %sp@-
|
|
+ bsrl do_signal
|
|
+ addql #8,%sp
|
|
+ RESTORE_SWITCH_STACK
|
|
+ addql #4,%sp
|
|
+ jbra resume_userspace
|
|
+
|
|
+do_delayed_trace:
|
|
+ bclr #7,%sp@(PT_OFF_SR) /* clear trace bit in SR */
|
|
+ pea 1 /* send SIGTRAP */
|
|
+ movel %curptr,%sp@-
|
|
+ pea LSIGTRAP
|
|
+ jbsr send_sig
|
|
+ addql #8,%sp
|
|
+ addql #4,%sp
|
|
+ jbra resume_userspace
|
|
+
|
|
+/*
|
|
+ * This is the interrupt handler (for all hardware interrupt
|
|
+ * sources). It figures out the vector number and calls the appropriate
|
|
+ * interrupt service routine directly.
|
|
+ */
|
|
+ENTRY(inthandler)
|
|
+ SAVE_ALL_INT
|
|
+ GET_CURRENT(%d0)
|
|
+ movel %curptr@(TASK_INFO+TINFO_PREEMPT),%d0
|
|
+ addil #0x10000,%d0
|
|
+ movel %d0,%curptr@(TASK_INFO+TINFO_PREEMPT)
|
|
+ /* put exception # in d0 */
|
|
+ movel %sp@(PT_VECTOR),%d0
|
|
+ swap %d0 /* extract bits 25:18 */
|
|
+ lsrl #2,%d0
|
|
+ andl #0x0ff,%d0
|
|
+
|
|
+ movel %sp,%sp@-
|
|
+ movel %d0,%sp@- /* put vector # on stack */
|
|
+auto_irqhandler_fixup = . + 2
|
|
+ jbsr process_int /* process the IRQ */
|
|
+ addql #8,%sp /* pop parameters off stack */
|
|
+
|
|
+ret_from_interrupt:
|
|
+
|
|
+ movel %curptr@(TASK_INFO+TINFO_PREEMPT),%d0
|
|
+ subil #0x10000,%d0
|
|
+ movel %d0,%curptr@(TASK_INFO+TINFO_PREEMPT)
|
|
+ jeq ret_from_last_interrupt
|
|
+2: RESTORE_ALL
|
|
+
|
|
+ ALIGN
|
|
+ret_from_last_interrupt:
|
|
+ moveb %sp@(PT_OFF_SR),%d0
|
|
+ andl #(~ALLOWINT>>8)&0xff,%d0
|
|
+ jne 2b
|
|
+
|
|
+ /* check if we need to do software interrupts */
|
|
+ tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING
|
|
+ jeq .Lret_from_exception
|
|
+ pea ret_from_exception
|
|
+ jra do_softirq
|
|
+
|
|
+ENTRY(user_inthandler)
|
|
+ SAVE_ALL_INT
|
|
+ GET_CURRENT(%d0)
|
|
+ movel %curptr@(TASK_INFO+TINFO_PREEMPT),%d0
|
|
+ addil #0x10000,%d0
|
|
+ movel %d0,%curptr@(TASK_INFO+TINFO_PREEMPT)
|
|
+ /* put exception # in d0 */
|
|
+ movel %sp@(PT_VECTOR),%d0
|
|
+user_irqvec_fixup = . + 2
|
|
+ swap %d0 /* extract bits 25:18 */
|
|
+ lsrl #2,%d0
|
|
+ andl #0x0ff,%d0
|
|
+
|
|
+ movel %sp,%sp@-
|
|
+ movel %d0,%sp@- /* put vector # on stack */
|
|
+user_irqhandler_fixup = . + 2
|
|
+ jbsr process_int /* process the IRQ */
|
|
+ addql #8,%sp /* pop parameters off stack */
|
|
+
|
|
+ movel %curptr@(TASK_INFO+TINFO_PREEMPT),%d0
|
|
+ subil #0x10000,%d0
|
|
+ movel %d0,%curptr@(TASK_INFO+TINFO_PREEMPT)
|
|
+ jeq ret_from_last_interrupt
|
|
+ RESTORE_ALL
|
|
+
|
|
+/* Handler for uninitialized and spurious interrupts */
|
|
+
|
|
+ENTRY(bad_inthandler)
|
|
+ SAVE_ALL_INT
|
|
+ GET_CURRENT(%d0)
|
|
+ movel %curptr@(TASK_INFO+TINFO_PREEMPT),%d0
|
|
+ addil #0x10000,%d0
|
|
+ movel %d0,%curptr@(TASK_INFO+TINFO_PREEMPT)
|
|
+
|
|
+ movel %sp,%sp@-
|
|
+ jsr handle_badint
|
|
+ addql #4,%sp
|
|
+
|
|
+ movel %curptr@(TASK_INFO+TINFO_PREEMPT),%d0
|
|
+ subil #0x10000,%d0
|
|
+ movel %d0,%curptr@(TASK_INFO+TINFO_PREEMPT)
|
|
+ jeq ret_from_last_interrupt
|
|
+ RESTORE_ALL
|
|
+
|
|
+ENTRY(sys_fork)
|
|
+ SAVE_SWITCH_STACK
|
|
+ pea %sp@(SWITCH_STACK_SIZE)
|
|
+ jbsr m68k_fork
|
|
+ addql #4,%sp
|
|
+ RESTORE_SWITCH_STACK
|
|
+ rts
|
|
+
|
|
+ENTRY(sys_clone)
|
|
+ SAVE_SWITCH_STACK
|
|
+ pea %sp@(SWITCH_STACK_SIZE)
|
|
+ jbsr m68k_clone
|
|
+ addql #4,%sp
|
|
+ RESTORE_SWITCH_STACK
|
|
+ rts
|
|
+
|
|
+ENTRY(sys_vfork)
|
|
+ SAVE_SWITCH_STACK
|
|
+ pea %sp@(SWITCH_STACK_SIZE)
|
|
+ jbsr m68k_vfork
|
|
+ addql #4,%sp
|
|
+ RESTORE_SWITCH_STACK
|
|
+ rts
|
|
+
|
|
+ENTRY(sys_sigsuspend)
|
|
+ SAVE_SWITCH_STACK
|
|
+ pea %sp@(SWITCH_STACK_SIZE)
|
|
+ jbsr do_sigsuspend
|
|
+ addql #4,%sp
|
|
+ RESTORE_SWITCH_STACK
|
|
+ rts
|
|
+
|
|
+ENTRY(sys_sigreturn)
|
|
+ SAVE_SWITCH_STACK
|
|
+ jbsr do_sigreturn
|
|
+ RESTORE_SWITCH_STACK
|
|
+ rts
|
|
+
|
|
+ENTRY(sys_rt_sigreturn)
|
|
+ SAVE_SWITCH_STACK
|
|
+ jbsr do_rt_sigreturn
|
|
+ RESTORE_SWITCH_STACK
|
|
+ rts
|
|
+
|
|
+resume:
|
|
+ /*
|
|
+ * Beware - when entering resume, prev (the current task) is
|
|
+ * in a0, next (the new task) is in a1,so don't change these
|
|
+ * registers until their contents are no longer needed.
|
|
+ */
|
|
+
|
|
+ /* save sr */
|
|
+ movew %sr,%d0
|
|
+ movew %d0,%a0@(TASK_THREAD+THREAD_SR)
|
|
+
|
|
+ /* save usp */
|
|
+ /* Save USP via %a1 (which is saved/restored from %d0) */
|
|
+ movel %a1,%d0
|
|
+ movel %usp,%a1
|
|
+ movel %a1,%a0@(TASK_THREAD+THREAD_USP)
|
|
+ movel %d0,%a1
|
|
+
|
|
+ /* save non-scratch registers on stack */
|
|
+ SAVE_SWITCH_STACK
|
|
+
|
|
+ /* save current kernel stack pointer */
|
|
+ movel %sp,%a0@(TASK_THREAD+THREAD_KSP)
|
|
+#ifdef CONFIG_FPU
|
|
+ /* save floating point context */
|
|
+ fsave %a0@(TASK_THREAD+THREAD_FPSTATE)
|
|
+
|
|
+1: tstb %a0@(TASK_THREAD+THREAD_FPSTATE)
|
|
+ jeq 3f
|
|
+2:
|
|
+ fmovemd %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
|
|
+3:
|
|
+#endif
|
|
+ /* Return previous task in %d1 */
|
|
+ movel %curptr,%d1
|
|
+
|
|
+ /* switch to new task (a1 contains new task) */
|
|
+ movel %a1,%curptr
|
|
+#ifdef CONFIG_FPU
|
|
+ /* restore floating point context */
|
|
+1: tstb %a1@(TASK_THREAD+THREAD_FPSTATE)
|
|
+ jeq 3f
|
|
+2:
|
|
+ fmovemd %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
|
|
+/* frestore %a1@(TASK_THREAD+THREAD_FPCNTL)*/
|
|
+3: frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
|
|
+#endif
|
|
+ /* restore the kernel stack pointer */
|
|
+ movel %a1@(TASK_THREAD+THREAD_KSP),%sp
|
|
+
|
|
+ /* restore non-scratch registers */
|
|
+ RESTORE_SWITCH_STACK
|
|
+
|
|
+ /* restore user stack pointer */
|
|
+ movel %a1@(TASK_THREAD+THREAD_USP),%a0
|
|
+ movel %a0,%usp
|
|
+
|
|
+ /* restore status register */
|
|
+ movew %a1@(TASK_THREAD+THREAD_SR),%d0
|
|
+ movew %d0,%sr
|
|
+
|
|
+ rts
|
|
+
|
|
+.data
|
|
+ALIGN
|
|
+sys_call_table:
|
|
+ .long sys_ni_syscall /* 0 - old "setup()" system call*/
|
|
+ .long sys_exit
|
|
+ .long sys_fork
|
|
+ .long sys_read
|
|
+ .long sys_write
|
|
+ .long sys_open /* 5 */
|
|
+ .long sys_close
|
|
+ .long sys_waitpid
|
|
+ .long sys_creat
|
|
+ .long sys_link
|
|
+ .long sys_unlink /* 10 */
|
|
+ .long sys_execve
|
|
+ .long sys_chdir
|
|
+ .long sys_time
|
|
+ .long sys_mknod
|
|
+ .long sys_chmod /* 15 */
|
|
+ .long sys_chown16
|
|
+ .long sys_ni_syscall /* old break syscall holder */
|
|
+ .long sys_stat
|
|
+ .long sys_lseek
|
|
+ .long sys_getpid /* 20 */
|
|
+ .long sys_mount
|
|
+ .long sys_oldumount
|
|
+ .long sys_setuid16
|
|
+ .long sys_getuid16
|
|
+ .long sys_stime /* 25 */
|
|
+ .long sys_ptrace
|
|
+ .long sys_alarm
|
|
+ .long sys_fstat
|
|
+ .long sys_pause
|
|
+ .long sys_utime /* 30 */
|
|
+ .long sys_ni_syscall /* old stty syscall holder */
|
|
+ .long sys_ni_syscall /* old gtty syscall holder */
|
|
+ .long sys_access
|
|
+ .long sys_nice
|
|
+ .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
|
|
+ .long sys_sync
|
|
+ .long sys_kill
|
|
+ .long sys_rename
|
|
+ .long sys_mkdir
|
|
+ .long sys_rmdir /* 40 */
|
|
+ .long sys_dup
|
|
+ .long sys_pipe
|
|
+ .long sys_times
|
|
+ .long sys_ni_syscall /* old prof syscall holder */
|
|
+ .long sys_brk /* 45 */
|
|
+ .long sys_setgid16
|
|
+ .long sys_getgid16
|
|
+ .long sys_signal
|
|
+ .long sys_geteuid16
|
|
+ .long sys_getegid16 /* 50 */
|
|
+ .long sys_acct
|
|
+ .long sys_umount /* recycled never used phys() */
|
|
+ .long sys_ni_syscall /* old lock syscall holder */
|
|
+ .long sys_ioctl
|
|
+ .long sys_fcntl /* 55 */
|
|
+ .long sys_ni_syscall /* old mpx syscall holder */
|
|
+ .long sys_setpgid
|
|
+ .long sys_ni_syscall /* old ulimit syscall holder */
|
|
+ .long sys_ni_syscall
|
|
+ .long sys_umask /* 60 */
|
|
+ .long sys_chroot
|
|
+ .long sys_ustat
|
|
+ .long sys_dup2
|
|
+ .long sys_getppid
|
|
+ .long sys_getpgrp /* 65 */
|
|
+ .long sys_setsid
|
|
+ .long sys_sigaction
|
|
+ .long sys_sgetmask
|
|
+ .long sys_ssetmask
|
|
+ .long sys_setreuid16 /* 70 */
|
|
+ .long sys_setregid16
|
|
+ .long sys_sigsuspend
|
|
+ .long sys_sigpending
|
|
+ .long sys_sethostname
|
|
+ .long sys_setrlimit /* 75 */
|
|
+ .long sys_old_getrlimit
|
|
+ .long sys_getrusage
|
|
+ .long sys_gettimeofday
|
|
+ .long sys_settimeofday
|
|
+ .long sys_getgroups16 /* 80 */
|
|
+ .long sys_setgroups16
|
|
+ .long old_select
|
|
+ .long sys_symlink
|
|
+ .long sys_lstat
|
|
+ .long sys_readlink /* 85 */
|
|
+ .long sys_uselib
|
|
+ .long sys_swapon
|
|
+ .long sys_reboot
|
|
+ .long 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 for i386 */
|
|
+ .long sys_socketcall
|
|
+ .long sys_syslog
|
|
+ .long sys_setitimer
|
|
+ .long sys_getitimer /* 105 */
|
|
+ .long sys_newstat
|
|
+ .long sys_newlstat
|
|
+ .long sys_newfstat
|
|
+ .long sys_ni_syscall
|
|
+ .long sys_ni_syscall /* 110 */ /* iopl for i386 */
|
|
+ .long sys_vhangup
|
|
+ .long sys_ni_syscall /* obsolete idle() syscall */
|
|
+ .long sys_ni_syscall /* vm86old for i386 */
|
|
+ .long sys_wait4
|
|
+ .long sys_swapoff /* 115 */
|
|
+ .long sys_sysinfo
|
|
+ .long sys_ipc
|
|
+ .long sys_fsync
|
|
+ .long sys_sigreturn
|
|
+ .long sys_clone /* 120 */
|
|
+ .long sys_setdomainname
|
|
+ .long sys_newuname
|
|
+ .long sys_cacheflush /* modify_ldt for i386 */
|
|
+ .long sys_adjtimex
|
|
+ .long sys_mprotect /* 125 */
|
|
+ .long sys_sigprocmask
|
|
+ .long sys_ni_syscall /* old "create_module" */
|
|
+ .long sys_init_module
|
|
+ .long sys_delete_module
|
|
+ .long sys_ni_syscall /* 130 - old "get_kernel_syms" */
|
|
+ .long sys_quotactl
|
|
+ .long sys_getpgid
|
|
+ .long sys_fchdir
|
|
+ .long sys_bdflush
|
|
+ .long sys_sysfs /* 135 */
|
|
+ .long sys_personality
|
|
+ .long sys_ni_syscall /* for afs_syscall */
|
|
+ .long sys_setfsuid16
|
|
+ .long sys_setfsgid16
|
|
+ .long sys_llseek /* 140 */
|
|
+ .long sys_getdents
|
|
+ .long sys_select
|
|
+ .long sys_flock
|
|
+ .long sys_msync
|
|
+ .long sys_readv /* 145 */
|
|
+ .long sys_writev
|
|
+ .long sys_getsid
|
|
+ .long sys_fdatasync
|
|
+ .long sys_sysctl
|
|
+ .long sys_mlock /* 150 */
|
|
+ .long sys_munlock
|
|
+ .long sys_mlockall
|
|
+ .long sys_munlockall
|
|
+ .long sys_sched_setparam
|
|
+ .long sys_sched_getparam /* 155 */
|
|
+ .long sys_sched_setscheduler
|
|
+ .long sys_sched_getscheduler
|
|
+ .long sys_sched_yield
|
|
+ .long sys_sched_get_priority_max
|
|
+ .long sys_sched_get_priority_min /* 160 */
|
|
+ .long sys_sched_rr_get_interval
|
|
+ .long sys_nanosleep
|
|
+ .long sys_mremap
|
|
+ .long sys_setresuid16
|
|
+ .long sys_getresuid16 /* 165 */
|
|
+ .long sys_getpagesize
|
|
+ .long sys_ni_syscall /* old sys_query_module */
|
|
+ .long sys_poll
|
|
+ .long sys_nfsservctl
|
|
+ .long sys_setresgid16 /* 170 */
|
|
+ .long sys_getresgid16
|
|
+ .long sys_prctl
|
|
+ .long sys_rt_sigreturn
|
|
+ .long sys_rt_sigaction
|
|
+ .long sys_rt_sigprocmask /* 175 */
|
|
+ .long sys_rt_sigpending
|
|
+ .long sys_rt_sigtimedwait
|
|
+ .long sys_rt_sigqueueinfo
|
|
+ .long sys_rt_sigsuspend
|
|
+ .long sys_pread64 /* 180 */
|
|
+ .long sys_pwrite64
|
|
+ .long sys_lchown16;
|
|
+ .long sys_getcwd
|
|
+ .long sys_capget
|
|
+ .long sys_capset /* 185 */
|
|
+ .long sys_sigaltstack
|
|
+ .long sys_sendfile
|
|
+ .long sys_ni_syscall /* streams1 */
|
|
+ .long sys_ni_syscall /* streams2 */
|
|
+ .long sys_vfork /* 190 */
|
|
+ .long sys_getrlimit
|
|
+ .long sys_mmap2
|
|
+ .long sys_truncate64
|
|
+ .long sys_ftruncate64
|
|
+ .long sys_stat64 /* 195 */
|
|
+ .long sys_lstat64
|
|
+ .long sys_fstat64
|
|
+ .long sys_chown
|
|
+ .long sys_getuid
|
|
+ .long sys_getgid /* 200 */
|
|
+ .long sys_geteuid
|
|
+ .long sys_getegid
|
|
+ .long sys_setreuid
|
|
+ .long sys_setregid
|
|
+ .long sys_getgroups /* 205 */
|
|
+ .long sys_setgroups
|
|
+ .long sys_fchown
|
|
+ .long sys_setresuid
|
|
+ .long sys_getresuid
|
|
+ .long sys_setresgid /* 210 */
|
|
+ .long sys_getresgid
|
|
+ .long sys_lchown
|
|
+ .long sys_setuid
|
|
+ .long sys_setgid
|
|
+ .long sys_setfsuid /* 215 */
|
|
+ .long sys_setfsgid
|
|
+ .long sys_pivot_root
|
|
+ .long sys_ni_syscall
|
|
+ .long sys_ni_syscall
|
|
+ .long sys_getdents64 /* 220 */
|
|
+ .long sys_gettid
|
|
+ .long sys_tkill
|
|
+ .long sys_setxattr
|
|
+ .long sys_lsetxattr
|
|
+ .long sys_fsetxattr /* 225 */
|
|
+ .long sys_getxattr
|
|
+ .long sys_lgetxattr
|
|
+ .long sys_fgetxattr
|
|
+ .long sys_listxattr
|
|
+ .long sys_llistxattr /* 230 */
|
|
+ .long sys_flistxattr
|
|
+ .long sys_removexattr
|
|
+ .long sys_lremovexattr
|
|
+ .long sys_fremovexattr
|
|
+ .long sys_futex /* 235 */
|
|
+ .long sys_sendfile64
|
|
+ .long sys_mincore
|
|
+ .long sys_madvise
|
|
+ .long sys_fcntl64
|
|
+ .long sys_readahead /* 240 */
|
|
+ .long sys_io_setup
|
|
+ .long sys_io_destroy
|
|
+ .long sys_io_getevents
|
|
+ .long sys_io_submit
|
|
+ .long sys_io_cancel /* 245 */
|
|
+ .long sys_fadvise64
|
|
+ .long sys_exit_group
|
|
+ .long sys_lookup_dcookie
|
|
+ .long sys_epoll_create
|
|
+ .long sys_epoll_ctl /* 250 */
|
|
+ .long sys_epoll_wait
|
|
+ .long sys_remap_file_pages
|
|
+ .long sys_set_tid_address
|
|
+ .long sys_timer_create
|
|
+ .long sys_timer_settime /* 255 */
|
|
+ .long sys_timer_gettime
|
|
+ .long sys_timer_getoverrun
|
|
+ .long sys_timer_delete
|
|
+ .long sys_clock_settime
|
|
+ .long sys_clock_gettime /* 260 */
|
|
+ .long sys_clock_getres
|
|
+ .long sys_clock_nanosleep
|
|
+ .long sys_statfs64
|
|
+ .long sys_fstatfs64
|
|
+ .long sys_tgkill /* 265 */
|
|
+ .long sys_utimes
|
|
+ .long sys_fadvise64_64
|
|
+ .long sys_mbind
|
|
+ .long sys_get_mempolicy
|
|
+ .long sys_set_mempolicy /* 270 */
|
|
+ .long sys_mq_open
|
|
+ .long sys_mq_unlink
|
|
+ .long sys_mq_timedsend
|
|
+ .long sys_mq_timedreceive
|
|
+ .long sys_mq_notify /* 275 */
|
|
+ .long sys_mq_getsetattr
|
|
+ .long sys_waitid
|
|
+ .long sys_ni_syscall /* for sys_vserver */
|
|
+ .long sys_add_key
|
|
+ .long sys_request_key /* 280 */
|
|
+ .long sys_keyctl
|
|
+ .long sys_ioprio_set
|
|
+ .long sys_ioprio_get
|
|
+ .long sys_inotify_init
|
|
+ .long sys_inotify_add_watch /* 285 */
|
|
+ .long sys_inotify_rm_watch
|
|
+ .long sys_migrate_pages
|
|
+ .long sys_openat
|
|
+ .long sys_mkdirat
|
|
+ .long sys_mknodat /* 290 */
|
|
+ .long sys_fchownat
|
|
+ .long sys_futimesat
|
|
+ .long sys_fstatat64
|
|
+ .long sys_unlinkat
|
|
+ .long sys_renameat /* 295 */
|
|
+ .long sys_linkat
|
|
+ .long sys_symlinkat
|
|
+ .long sys_readlinkat
|
|
+ .long sys_fchmodat
|
|
+ .long sys_faccessat /* 300 */
|
|
+ .long sys_ni_syscall /* Reserved for pselect6 */
|
|
+ .long sys_ni_syscall /* Reserved for ppoll */
|
|
+ .long sys_unshare
|
|
+ .long sys_set_robust_list
|
|
+ .long sys_get_robust_list /* 305 */
|
|
+ .long sys_splice
|
|
+ .long sys_sync_file_range
|
|
+ .long sys_tee
|
|
+ .long sys_vmsplice
|
|
+ .long sys_move_pages /* 310 */
|
|
+ .long sys_sched_setaffinity
|
|
+ .long sys_sched_getaffinity
|
|
+ .long sys_kexec_load
|
|
+ .long sys_getcpu
|
|
+ .long sys_epoll_pwait /* 315 */
|
|
+ .long sys_utimensat
|
|
+ .long sys_signalfd
|
|
+ .long sys_timerfd_create
|
|
+ .long sys_eventfd
|
|
+ .long sys_fallocate /* 320 */
|
|
+ .long sys_timerfd_settime
|
|
+ .long sys_timerfd_gettime
|
|
+ .long sys_signalfd4
|
|
+ .long sys_eventfd2
|
|
+ .long sys_epoll_create1 /* 325 */
|
|
+ .long sys_dup3
|
|
+ .long sys_pipe2
|
|
+ .long sys_inotify_init1
|
|
+ .long sys_preadv
|
|
+ .long sys_pwritev /* 330 */
|
|
+ .long sys_rt_tgsigqueueinfo
|
|
+ .long sys_perf_event_open
|
|
+ .long sys_get_thread_area
|
|
+ .long sys_set_thread_area
|
|
+ .long sys_atomic_cmpxchg_32 /* 335 */
|
|
+ .long sys_atomic_barrier
|
|
+ .long sys_fanotify_init
|
|
+ .long sys_fanotify_mark
|
|
+ .long sys_prlimit64
|
|
--- /dev/null
|
|
+++ b/arch/m68k/coldfire/common/head.S
|
|
@@ -0,0 +1,466 @@
|
|
+/*
|
|
+ * head.S is the MMU enabled ColdFire specific initial boot code
|
|
+ *
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Matt Waddel Matt.Waddel@freescale.com
|
|
+ * Kurt Mahan kmahan@freescale.com
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.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.
|
|
+ *
|
|
+ * Parts of this code came from arch/m68k/kernel/head.S
|
|
+ */
|
|
+#include <linux/linkage.h>
|
|
+#include <linux/init.h>
|
|
+#include <asm/bootinfo.h>
|
|
+#include <asm/setup.h>
|
|
+#include <asm/entry.h>
|
|
+#include <asm/pgtable.h>
|
|
+#include <asm/page.h>
|
|
+#include <asm/coldfire.h>
|
|
+#include <asm/cfcache.h>
|
|
+
|
|
+#define DEBUG
|
|
+
|
|
+.globl kernel_pg_dir
|
|
+.globl availmem
|
|
+.globl set_context
|
|
+.globl set_fpga
|
|
+
|
|
+#ifdef DEBUG
|
|
+/* When debugging use readable names for labels */
|
|
+#ifdef __STDC__
|
|
+#define L(name) .head.S.##name
|
|
+#else
|
|
+#define L(name) .head.S./**/name
|
|
+#endif
|
|
+#else
|
|
+#ifdef __STDC__
|
|
+#define L(name) .L##name
|
|
+#else
|
|
+#define L(name) .L/**/name
|
|
+#endif
|
|
+#endif
|
|
+
|
|
+/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */
|
|
+#ifndef __INITDATA
|
|
+#define __INITDATA .data
|
|
+#define __FINIT .previous
|
|
+#endif
|
|
+
|
|
+/*
|
|
+ * Kernel mapped to physical ram address.
|
|
+ *
|
|
+ * M5445x:
|
|
+ * Data[0]: 0xF0000000 -> 0xFFFFFFFF System regs
|
|
+ * Data[1]: 0x40000000 -> 0x4FFFFFFF SDRAM - cached
|
|
+ * Code[0]: Not Mapped
|
|
+ * Code[1]: 0x40000000 -> 0x4FFFFFFF SDRAM - cached
|
|
+ *
|
|
+ * M547x/M548x
|
|
+ * Data[0]: 0xF0000000 -> 0xFFFFFFFF System regs
|
|
+ * Data[1]: 0x00000000 -> 0x0FFFFFFF SDRAM - uncached
|
|
+ * Code[0]: Not Mapped
|
|
+ * Code[1]: 0x00000000 -> 0x0FFFFFFF SDRAM - cached
|
|
+ *
|
|
+ * M5441X:
|
|
+ * Data[0]: 0xE0000000 -> 0xFFFFFFFF System regs
|
|
+ * Data[1]: 0x40000000 -> 0x4FFFFFFF SDRAM - cached
|
|
+ * Code[0]: Not Mapped
|
|
+ * Code[1]: 0x40000000 -> 0x4FFFFFFF SDRAM - cached
|
|
+ */
|
|
+#if defined(CONFIG_M5445X)
|
|
+#define ACR0_DEFAULT #0xF00FA048 /* System Regs uncached/precise */
|
|
+#define ACR1_DEFAULT #0x400FA028 /* SDRAM cached/copyback */
|
|
+#define ACR2_DEFAULT #0x00000000 /* Not mapped */
|
|
+#define ACR3_DEFAULT #0x400FA028 /* SDRAM cached/copyback */
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+#define ACR0_DEFAULT #0xF00FA048 /* System Regs */
|
|
+#define ACR1_DEFAULT #0x000FA028 /* SDRAM cached/copy-back */
|
|
+#define ACR2_DEFAULT #0x00000000 /* Not mapped */
|
|
+#define ACR3_DEFAULT #0x000FA028 /* Instruction cached/copy-back */
|
|
+#elif defined(CONFIG_M5441X)
|
|
+#define ACR0_DEFAULT #0xE01FA048 /* System Regs */
|
|
+#define ACR1_DEFAULT #0x400FA028 /* SDRAM cached/copyback */
|
|
+#define ACR4_DEFAULT #0x00000000 /* Not mapped */
|
|
+#define ACR5_DEFAULT #0x00000000 /* Not mapped */
|
|
+#define ACR2_DEFAULT #0x00000000 /* Not mapped */
|
|
+#define ACR3_DEFAULT #0x400FA028 /* Instruction cached/copy-back */
|
|
+#define ACR6_DEFAULT #0x00000000 /* Not mapped */
|
|
+#define ACR7_DEFAULT #0x00000000 /* Not mapped */
|
|
+#endif
|
|
+
|
|
+/* ACR mapping for FPGA (maps 0) */
|
|
+#define ACR0_FPGA #0x000FA048 /* ACR0 enable FPGA */
|
|
+
|
|
+/* Several macros to make the writing of subroutines easier:
|
|
+ * - func_start marks the beginning of the routine which setups the frame
|
|
+ * register and saves the registers, it also defines another macro
|
|
+ * to automatically restore the registers again.
|
|
+ * - func_return marks the end of the routine and simply calls the prepared
|
|
+ * macro to restore registers and jump back to the caller.
|
|
+ * - func_define generates another macro to automatically put arguments
|
|
+ * onto the stack call the subroutine and cleanup the stack again.
|
|
+ */
|
|
+
|
|
+.macro load_symbol_address symbol,register
|
|
+ movel #\symbol,\register
|
|
+.endm
|
|
+
|
|
+.macro func_start name,saveregs,savesize,stack=0
|
|
+L(\name):
|
|
+ linkw %a6,#-\stack
|
|
+ subal #(\savesize),%sp
|
|
+ moveml \saveregs,%sp@
|
|
+.set stackstart,-\stack
|
|
+
|
|
+.macro func_return_\name
|
|
+ moveml %sp@,\saveregs
|
|
+ addal #(\savesize),%sp
|
|
+ unlk %a6
|
|
+ rts
|
|
+.endm
|
|
+.endm
|
|
+
|
|
+.macro func_return name
|
|
+ func_return_\name
|
|
+.endm
|
|
+
|
|
+.macro func_call name
|
|
+ jbsr L(\name)
|
|
+.endm
|
|
+
|
|
+.macro move_stack nr,arg1,arg2,arg3,arg4
|
|
+.if \nr
|
|
+ move_stack "(\nr-1)",\arg2,\arg3,\arg4
|
|
+ movel \arg1,%sp@-
|
|
+.endif
|
|
+.endm
|
|
+
|
|
+.macro func_define name,nr=0
|
|
+.macro \name arg1,arg2,arg3,arg4
|
|
+ move_stack \nr,\arg1,\arg2,\arg3,\arg4
|
|
+ func_call \name
|
|
+.if \nr
|
|
+ lea %sp@(\nr*4),%sp
|
|
+.endif
|
|
+.endm
|
|
+.endm
|
|
+
|
|
+func_define serial_putc,1
|
|
+
|
|
+.macro putc ch
|
|
+ pea \ch
|
|
+ func_call serial_putc
|
|
+ addql #4,%sp
|
|
+.endm
|
|
+
|
|
+.macro dputc ch
|
|
+#ifdef DEBUG
|
|
+ putc \ch
|
|
+#endif
|
|
+.endm
|
|
+
|
|
+func_define putn,1
|
|
+
|
|
+.macro dputn nr
|
|
+#ifdef DEBUG
|
|
+ putn \nr
|
|
+#endif
|
|
+.endm
|
|
+
|
|
+/*
|
|
+ mmu_map - creates a new TLB entry
|
|
+
|
|
+ virt_addr Must be on proper boundary
|
|
+ phys_addr Must be on proper boundary
|
|
+ itlb MMUOR_ITLB if instruction TLB or 0
|
|
+ asid address space ID
|
|
+ shared_global MMUTR_SG if shared between different ASIDs or 0
|
|
+ size_code MMUDR_SZ1M 1 MB
|
|
+ MMUDR_SZ4K 4 KB
|
|
+ MMUDR_SZ8K 8 KB
|
|
+ MMUDR_SZ16M 16 MB
|
|
+ cache_mode MMUDR_INC instruction non-cacheable
|
|
+ MMUDR_IC instruction cacheable
|
|
+ MMUDR_DWT data writethrough
|
|
+ MMUDR_DCB data copyback
|
|
+ MMUDR_DNCP data non-cacheable, precise
|
|
+ MMUDR_DNCIP data non-cacheable, imprecise
|
|
+ super_prot MMUDR_SP if user mode generates exception or 0
|
|
+ readable MMUDR_R if permits read access (data TLB) or 0
|
|
+ writable MMUDR_W if permits write access (data TLB) or 0
|
|
+ executable MMUDR_X if permits execute access (instruction TLB) or 0
|
|
+ locked MMUDR_LK prevents TLB entry from being replaced or 0
|
|
+ temp_data_reg a data register to use for temporary values
|
|
+*/
|
|
+.macro mmu_map virt_addr,phys_addr,itlb,asid,shared_global,size_code, \
|
|
+ cache_mode,super_prot,readable,writable,executable,locked,temp_data_reg
|
|
+ /* Set up search of TLB. */
|
|
+ movel #(\virt_addr+1), \temp_data_reg
|
|
+ movel \temp_data_reg, MMUAR
|
|
+ /* Search. */
|
|
+ movel #(MMUOR_STLB + MMUOR_ADR +\itlb), \temp_data_reg
|
|
+ movew \temp_data_reg, (MMUOR)
|
|
+ /* Set up tag value. */
|
|
+ movel #(\virt_addr + \asid + \shared_global + MMUTR_V), \temp_data_reg
|
|
+ movel \temp_data_reg, MMUTR
|
|
+ /* Set up data value. */
|
|
+ movel #(\phys_addr + \size_code + \cache_mode + \super_prot + \
|
|
+ \readable + \writable + \executable + \locked), \temp_data_reg
|
|
+ movel \temp_data_reg, MMUDR
|
|
+ /* Save it. */
|
|
+ movel #(MMUOR_ACC + MMUOR_UAA + \itlb), \temp_data_reg
|
|
+ movew \temp_data_reg, (MMUOR)
|
|
+.endm /* mmu_map */
|
|
+
|
|
+.macro mmu_unmap virt_addr,itlb,temp_data_reg
|
|
+ /* Set up search of TLB. */
|
|
+ movel #(\virt_addr+1), \temp_data_reg
|
|
+ movel \temp_data_reg, MMUAR
|
|
+ /* Search. */
|
|
+ movel #(MMUOR_STLB + MMUOR_ADR +\itlb), \temp_data_reg
|
|
+ movew \temp_data_reg, (MMUOR)
|
|
+ /* Test for hit. */
|
|
+ movel MMUSR,\temp_data_reg
|
|
+ btst #MMUSR_HITN,\temp_data_reg
|
|
+ beq 1f
|
|
+ /* Read the TLB. */
|
|
+ movel #(MMUOR_RW + MMUOR_ACC +\itlb), \temp_data_reg
|
|
+ movew \temp_data_reg, (MMUOR)
|
|
+ movel MMUSR,\temp_data_reg
|
|
+ /* Set up tag value. */
|
|
+ movel #0, \temp_data_reg
|
|
+ movel \temp_data_reg, MMUTR
|
|
+ /* Set up data value. */
|
|
+ movel #0, \temp_data_reg
|
|
+ movel \temp_data_reg, MMUDR
|
|
+ /* Save it. */
|
|
+ movel #(MMUOR_ACC + MMUOR_UAA + \itlb), \temp_data_reg
|
|
+ movew \temp_data_reg, (MMUOR)
|
|
+1:
|
|
+.endm /* mmu_unmap */
|
|
+
|
|
+/* .text */
|
|
+.section ".text.head","ax"
|
|
+ENTRY(_stext)
|
|
+/* Version numbers of the bootinfo interface -- if we later pass info
|
|
+ * from boot ROM we might want to put something real here.
|
|
+ *
|
|
+ * The area from _stext to _start will later be used as kernel pointer table
|
|
+ */
|
|
+ bras 1f /* Jump over bootinfo version numbers */
|
|
+
|
|
+ .long BOOTINFOV_MAGIC
|
|
+ .long 0
|
|
+1: jmp __start
|
|
+
|
|
+.equ kernel_pg_dir,_stext
|
|
+.equ .,_stext+0x1000
|
|
+
|
|
+ENTRY(_start)
|
|
+ jra __start
|
|
+__INIT
|
|
+ENTRY(__start)
|
|
+/* Save the location of u-boot info - cmd line, bd_info, etc. */
|
|
+ movel %a7,%a4 /* Don't use %a4 before cf_early_init */
|
|
+ addl #0x00000004,%a4 /* offset past top */
|
|
+ addl #(PAGE_OFFSET-CONFIG_SDRAM_BASE),%a4 /* high mem offset */
|
|
+
|
|
+/* Setup initial stack pointer */
|
|
+ movel #CONFIG_SDRAM_BASE+0x1000,%sp
|
|
+
|
|
+/* Setup usp */
|
|
+ subl %a0,%a0
|
|
+ movel %a0,%usp
|
|
+
|
|
+#if defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
|
|
+#if defined(CONFIG_SRAM)
|
|
+ movel #(CONFIG_SRAM_BASE+0x221), %d0
|
|
+#else
|
|
+ movel #0x80000000, %d0
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_M5441X
|
|
+ movec %d0, %rambar
|
|
+#else
|
|
+ movec %d0, %rambar1
|
|
+#endif
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+ movel #MCF_MBAR, %d0
|
|
+ movec %d0, %mbar
|
|
+ move.l #(MCF_RAMBAR0 + 0x21), %d0
|
|
+ movec %d0, %rambar0
|
|
+ move.l #(MCF_RAMBAR1 + 0x21), %d0
|
|
+ movec %d0, %rambar1
|
|
+#endif
|
|
+
|
|
+ movew #0x2700,%sr
|
|
+
|
|
+/* reset cache */
|
|
+ movel #(CF_CACR_ICINVA + CF_CACR_DCINVA),%d0
|
|
+ movecl %d0,%cacr
|
|
+
|
|
+ movel #(MMU_BASE+1),%d0
|
|
+ movecl %d0,%mmubar
|
|
+ movel #MMUOR_CA,%a0 /* Clear tlb entries */
|
|
+ movew %a0,(MMUOR)
|
|
+ movel #(MMUOR_CA + MMUOR_ITLB),%a0 /* Use ITLB for searches */
|
|
+ movew %a0,(MMUOR)
|
|
+ movel #0,%a0 /* Clear Addr Space User ID */
|
|
+ movecl %a0,%asid
|
|
+
|
|
+/* setup ACRs */
|
|
+#if defined(CONFIG_M5445X) || defined(CONFIG_M547X_8X) || defined(CONFIG_M5441X)
|
|
+ movel ACR0_DEFAULT, %d0 /* ACR0 (DATA) setup */
|
|
+ movec %d0, %acr0
|
|
+ nop
|
|
+ movel ACR1_DEFAULT, %d0 /* ACR1 (DATA) setup */
|
|
+ movec %d0, %acr1
|
|
+ nop
|
|
+ movel ACR2_DEFAULT, %d0 /* ACR2 (CODE) setup */
|
|
+ movec %d0, %acr2
|
|
+ nop
|
|
+ movel ACR3_DEFAULT, %d0 /* ACR3 (CODE) setup */
|
|
+ movec %d0, %acr3
|
|
+ nop
|
|
+#endif
|
|
+ /* Turn on MMU */
|
|
+ movel #(MMUCR_EN),%a0
|
|
+ movel %a0,MMUCR
|
|
+ nop /* This synchs the pipeline after a write to MMUCR */
|
|
+
|
|
+ movel #__running_high,%a0 /* Get around PC-relative addressing. */
|
|
+ jmp %a0@
|
|
+
|
|
+ENTRY(__running_high)
|
|
+ load_symbol_address _stext,%sp
|
|
+ movel L(memory_start),%a0
|
|
+ movel %a0,availmem
|
|
+ load_symbol_address L(phys_kernel_start),%a0
|
|
+ load_symbol_address _stext,%a1
|
|
+ subl #_stext,%a1
|
|
+ addl #PAGE_OFFSET,%a1
|
|
+ movel %a1,%a0@
|
|
+
|
|
+/* zero bss */
|
|
+ lea _sbss,%a0
|
|
+ lea _ebss,%a1
|
|
+ clrl %d0
|
|
+_loop_bss:
|
|
+ movel %d0,(%a0)+
|
|
+ cmpl %a0,%a1
|
|
+ bne _loop_bss
|
|
+
|
|
+/* create dma memory mirror TLB mapping */
|
|
+#if defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
|
|
+ mmu_map CONFIG_DMA_BASE, \
|
|
+ CONFIG_SDRAM_BASE, 0, 0, \
|
|
+ MMUTR_SG, MMUDR_SZ16M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, MMUDR_W, \
|
|
+ 0, MMUDR_LK, %d0
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+ mmu_map (CONFIG_DMA_BASE + 0*1024*1024), \
|
|
+ (CONFIG_SDRAM_BASE + 0*1024*1024), 0, 0, \
|
|
+ MMUTR_SG, MMUDR_SZ1M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, \
|
|
+ MMUDR_W, 0, MMUDR_LK, %d0
|
|
+ mmu_map (CONFIG_DMA_BASE + 1*1024*1024), \
|
|
+ (CONFIG_SDRAM_BASE + 1*1024*1024), 0, 0, \
|
|
+ MMUTR_SG, MMUDR_SZ1M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, \
|
|
+ MMUDR_W, 0, MMUDR_LK, %d0
|
|
+ mmu_map (CONFIG_DMA_BASE + 2*1024*1024), \
|
|
+ (CONFIG_SDRAM_BASE + 2*1024*1024), 0, 0, \
|
|
+ MMUTR_SG, MMUDR_SZ1M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, \
|
|
+ MMUDR_W, 0, MMUDR_LK, %d0
|
|
+ mmu_map (CONFIG_DMA_BASE + 3*1024*1024), \
|
|
+ (CONFIG_SDRAM_BASE + 3*1024*1024), 0, 0, \
|
|
+ MMUTR_SG, MMUDR_SZ1M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, \
|
|
+ MMUDR_W, 0, MMUDR_LK, %d0
|
|
+ mmu_map (CONFIG_DMA_BASE + 4*1024*1024), \
|
|
+ (CONFIG_SDRAM_BASE + 4*1024*1024), 0, 0, \
|
|
+ MMUTR_SG, MMUDR_SZ1M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, \
|
|
+ MMUDR_W, 0, MMUDR_LK, %d0
|
|
+ mmu_map (CONFIG_DMA_BASE + 5*1024*1024), \
|
|
+ (CONFIG_SDRAM_BASE + 5*1024*1024), 0, 0, \
|
|
+ MMUTR_SG, MMUDR_SZ1M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, \
|
|
+ MMUDR_W, 0, MMUDR_LK, %d0
|
|
+ mmu_map (CONFIG_DMA_BASE + 6*1024*1024), \
|
|
+ (CONFIG_SDRAM_BASE + 6*1024*1024), 0, 0, \
|
|
+ MMUTR_SG, MMUDR_SZ1M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, \
|
|
+ MMUDR_W, 0, MMUDR_LK, %d0
|
|
+ mmu_map (CONFIG_DMA_BASE + 7*1024*1024), \
|
|
+ (CONFIG_SDRAM_BASE + 7*1024*1024), 0, 0, \
|
|
+ MMUTR_SG, MMUDR_SZ1M, MMUDR_DNCP, MMUDR_SP, MMUDR_R, \
|
|
+ MMUDR_W, 0, MMUDR_LK, %d0
|
|
+#endif
|
|
+
|
|
+/* Setup initial stack pointer */
|
|
+ lea init_task,%a2
|
|
+ lea init_thread_union+THREAD_SIZE,%sp
|
|
+ subl %a6,%a6 /* clear a6 for gdb */
|
|
+
|
|
+#ifdef CONFIG_MCF_USER_HALT
|
|
+/* Setup debug control reg to allow halts from user space */
|
|
+ lea wdbg_uhe,%a0
|
|
+ wdebug (%a0)
|
|
+#endif
|
|
+
|
|
+ movel %a4,uboot_info_stk /* save uboot info to variable */
|
|
+ jsr cf_early_init
|
|
+ jmp start_kernel
|
|
+
|
|
+.section ".text.head","ax"
|
|
+set_context:
|
|
+func_start set_context,%d0,(1*4)
|
|
+ movel 12(%sp),%d0
|
|
+ movec %d0,%asid
|
|
+func_return set_context
|
|
+
|
|
+#ifdef CONFIG_M54455
|
|
+/*
|
|
+ * set_fpga(addr,val) on the M5445X
|
|
+ *
|
|
+ * Map in 0x00000000 -> 0x0fffffff and then do the write.
|
|
+ */
|
|
+set_fpga:
|
|
+ movew %sr,%d1
|
|
+ movew #0x2700,%sr
|
|
+ movel ACR0_FPGA, %d0
|
|
+ movec %d0, %acr0
|
|
+ nop
|
|
+ moveal 4(%sp),%a0
|
|
+ movel 8(%sp),%a0@
|
|
+ movel ACR0_DEFAULT, %d0
|
|
+ movec %d0, %acr0
|
|
+ nop
|
|
+ movew %d1,%sr
|
|
+ rts
|
|
+#endif
|
|
+
|
|
+ .data
|
|
+ .align 4
|
|
+
|
|
+availmem:
|
|
+ .long 0
|
|
+L(phys_kernel_start):
|
|
+ .long PAGE_OFFSET
|
|
+L(kernel_end):
|
|
+ .long 0
|
|
+L(memory_start):
|
|
+ .long PAGE_OFFSET_RAW
|
|
+
|
|
+#ifdef CONFIG_MCF_USER_HALT
|
|
+/*
|
|
+ * Enable User Halt Enable in the debug control register.
|
|
+ */
|
|
+wdbg_uhe:
|
|
+ .word 0x2c80 /* DR0 */
|
|
+ .word 0x00b0 /* 31:16 */
|
|
+ .word 0x0400 /* 15:0 -- enable UHE */
|
|
+ .word 0x0000 /* unused */
|
|
+#endif
|
|
+
|
|
+
|
|
--- /dev/null
|
|
+++ b/arch/m68k/coldfire/common/ints.c
|
|
@@ -0,0 +1,544 @@
|
|
+/*
|
|
+ * linux/arch/m68k/coldfire/ints.c -- General interrupt handling code
|
|
+ *
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Matt Waddel Matt.Waddel@freescale.com
|
|
+ * Kurt Mahan kmahan@freescale.com
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * Based on:
|
|
+ * linux/arch/m68k/kernel/ints.c &
|
|
+ * linux/arch/m68knommu/5307/ints.c
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
+#include <linux/module.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/sched.h>
|
|
+#include <linux/kernel_stat.h>
|
|
+#include <linux/errno.h>
|
|
+#include <linux/seq_file.h>
|
|
+#include <linux/interrupt.h>
|
|
+
|
|
+#include <asm/system.h>
|
|
+#include <asm/irq.h>
|
|
+#include <asm/traps.h>
|
|
+#include <asm/page.h>
|
|
+#include <asm/machdep.h>
|
|
+#include <asm/irq_regs.h>
|
|
+
|
|
+#include <asm/mcfsim.h>
|
|
+
|
|
+/*
|
|
+ * IRQ Handler lists.
|
|
+ */
|
|
+static struct irq_node *irq_list[SYS_IRQS];
|
|
+static struct irq_controller *irq_controller[SYS_IRQS];
|
|
+static int irq_depth[SYS_IRQS];
|
|
+
|
|
+#define POOL_SIZE SYS_IRQS
|
|
+static struct irq_node pool[POOL_SIZE];
|
|
+static struct irq_node *get_irq_node(void);
|
|
+
|
|
+/* The number of spurious interrupts */
|
|
+unsigned int num_spurious;
|
|
+asmlinkage void handle_badint(struct pt_regs *regs);
|
|
+
|
|
+/*
|
|
+ * process_int(unsigned long vec, struct pt_regs *fp)
|
|
+ *
|
|
+ * Process an interrupt. Called from entry.S.
|
|
+ */
|
|
+asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
|
|
+{
|
|
+ struct pt_regs *old_regs;
|
|
+ struct irq_node *node;
|
|
+ old_regs = set_irq_regs(fp);
|
|
+ kstat_cpu(0).irqs[vec]++;
|
|
+
|
|
+ node = irq_list[vec];
|
|
+ if (!node)
|
|
+ handle_badint(fp);
|
|
+ else {
|
|
+ do {
|
|
+ node->handler(vec, node->dev_id);
|
|
+ node = node->next;
|
|
+ } while (node);
|
|
+ }
|
|
+
|
|
+ set_irq_regs(old_regs);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * show_interrupts( struct seq_file *p, void *v)
|
|
+ *
|
|
+ * Called to show all the current interrupt information.
|
|
+ */
|
|
+int show_interrupts(struct seq_file *p, void *v)
|
|
+{
|
|
+ struct irq_controller *contr;
|
|
+ struct irq_node *node;
|
|
+ int i = *(loff_t *) v;
|
|
+
|
|
+ if ((i < NR_IRQS) && (irq_list[i])) {
|
|
+ contr = irq_controller[i];
|
|
+ node = irq_list[i];
|
|
+ seq_printf(p, "%-8s %3u: %10u %s", contr->name, i,
|
|
+ kstat_cpu(0).irqs[i], node->devname);
|
|
+ while ((node = node->next))
|
|
+ seq_printf(p, ", %s", node->devname);
|
|
+
|
|
+ seq_printf(p, "\n");
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * get_irq_node(void)
|
|
+ *
|
|
+ * Get an irq node from the pool.
|
|
+ */
|
|
+struct irq_node *get_irq_node(void)
|
|
+{
|
|
+ struct irq_node *p = pool;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < POOL_SIZE; i++, p++) {
|
|
+ if (!p->handler) {
|
|
+ memset(p, 0, sizeof(struct irq_node));
|
|
+ return p;
|
|
+ }
|
|
+ }
|
|
+ printk(KERN_INFO "%s(%s:%d): No more irq nodes, I suggest you \
|
|
+ increase POOL_SIZE", __func__, __FILE__, __LINE__);
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+void init_irq_proc(void)
|
|
+{
|
|
+ /* Insert /proc/irq driver here */
|
|
+}
|
|
+
|
|
+int setup_irq(unsigned int irq, struct irq_node *node)
|
|
+{
|
|
+ struct irq_controller *contr;
|
|
+ struct irq_node **prev;
|
|
+ unsigned long flags;
|
|
+
|
|
+ if (irq >= NR_IRQS || !irq_controller[irq]) {
|
|
+ printk("%s: Incorrect IRQ %d from %s\n",
|
|
+ __func__, irq, node->devname);
|
|
+ return -ENXIO;
|
|
+ }
|
|
+
|
|
+ contr = irq_controller[irq];
|
|
+ spin_lock_irqsave(&contr->lock, flags);
|
|
+
|
|
+ prev = irq_list + irq;
|
|
+ if (*prev) {
|
|
+ /* Can't share interrupts unless both agree to */
|
|
+ if (!((*prev)->flags & node->flags & IRQF_SHARED)) {
|
|
+ spin_unlock_irqrestore(&contr->lock, flags);
|
|
+ printk(KERN_INFO "%s: -BUSY-Incorrect IRQ %d\n",
|
|
+ __func__, irq);
|
|
+ return -EBUSY;
|
|
+ }
|
|
+ while (*prev)
|
|
+ prev = &(*prev)->next;
|
|
+ }
|
|
+
|
|
+ if (!irq_list[irq]) {
|
|
+ if (contr->startup)
|
|
+ contr->startup(irq);
|
|
+ else
|
|
+ contr->enable(irq);
|
|
+ }
|
|
+ node->next = NULL;
|
|
+ *prev = node;
|
|
+
|
|
+ spin_unlock_irqrestore(&contr->lock, flags);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int request_irq(unsigned int irq,
|
|
+ irq_handler_t handler,
|
|
+ unsigned long flags, const char *devname, void *dev_id)
|
|
+{
|
|
+ struct irq_node *node = get_irq_node();
|
|
+ int res;
|
|
+
|
|
+ if (!node) {
|
|
+ printk(KERN_INFO "%s:get_irq_node error %x\n",
|
|
+ __func__, (unsigned int) node);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ node->handler = handler;
|
|
+ node->flags = flags;
|
|
+ node->dev_id = dev_id;
|
|
+ node->devname = devname;
|
|
+
|
|
+ res = setup_irq(irq, node);
|
|
+ if (res)
|
|
+ node->handler = NULL;
|
|
+
|
|
+ return res;
|
|
+}
|
|
+EXPORT_SYMBOL(request_irq);
|
|
+
|
|
+void free_irq(unsigned int irq, void *dev_id)
|
|
+{
|
|
+ struct irq_controller *contr;
|
|
+ struct irq_node **p, *node;
|
|
+ unsigned long flags;
|
|
+
|
|
+ if (irq >= NR_IRQS || !irq_controller[irq]) {
|
|
+ printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __func__, irq);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ contr = irq_controller[irq];
|
|
+ spin_lock_irqsave(&contr->lock, flags);
|
|
+
|
|
+ p = irq_list + irq;
|
|
+ while ((node = *p)) {
|
|
+ if (node->dev_id == dev_id)
|
|
+ break;
|
|
+ p = &node->next;
|
|
+ }
|
|
+
|
|
+ if (node) {
|
|
+ *p = node->next;
|
|
+ node->handler = NULL;
|
|
+ } else
|
|
+ printk(KERN_DEBUG "%s: Removing probably wrong IRQ %d\n",
|
|
+ __func__, irq);
|
|
+
|
|
+ if (!irq_list[irq]) {
|
|
+ if (contr->shutdown)
|
|
+ contr->shutdown(irq);
|
|
+ else
|
|
+ contr->disable(irq);
|
|
+ }
|
|
+
|
|
+ spin_unlock_irqrestore(&contr->lock, flags);
|
|
+}
|
|
+EXPORT_SYMBOL(free_irq);
|
|
+
|
|
+void enable_irq(unsigned int irq)
|
|
+{
|
|
+ struct irq_controller *contr;
|
|
+ unsigned long flags;
|
|
+
|
|
+ if (irq >= NR_IRQS || !irq_controller[irq]) {
|
|
+ printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __func__, irq);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ contr = irq_controller[irq];
|
|
+ spin_lock_irqsave(&contr->lock, flags);
|
|
+ if (irq_depth[irq]) {
|
|
+ if (!--irq_depth[irq]) {
|
|
+ if (contr->enable)
|
|
+ contr->enable(irq);
|
|
+ }
|
|
+ } else
|
|
+ WARN_ON(1);
|
|
+ spin_unlock_irqrestore(&contr->lock, flags);
|
|
+}
|
|
+EXPORT_SYMBOL(enable_irq);
|
|
+
|
|
+void disable_irq(unsigned int irq)
|
|
+{
|
|
+ struct irq_controller *contr;
|
|
+ unsigned long flags;
|
|
+
|
|
+ if (irq >= NR_IRQS || !irq_controller[irq]) {
|
|
+ printk(KERN_DEBUG "%s: Incorrect IRQ %d\n", __func__, irq);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ contr = irq_controller[irq];
|
|
+ spin_lock_irqsave(&contr->lock, flags);
|
|
+ if (!irq_depth[irq]++) {
|
|
+ if (contr->disable)
|
|
+ contr->disable(irq);
|
|
+ }
|
|
+ spin_unlock_irqrestore(&contr->lock, flags);
|
|
+}
|
|
+EXPORT_SYMBOL(disable_irq);
|
|
+
|
|
+void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq")));
|
|
+EXPORT_SYMBOL(disable_irq_nosync);
|
|
+
|
|
+
|
|
+unsigned long probe_irq_on(void)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(probe_irq_on);
|
|
+
|
|
+int probe_irq_off(unsigned long irqs)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(probe_irq_off);
|
|
+
|
|
+asmlinkage void handle_badint(struct pt_regs *regs)
|
|
+{
|
|
+ kstat_cpu(0).irqs[0]++;
|
|
+ num_spurious++;
|
|
+ printk(KERN_DEBUG "unexpected interrupt from %u\n", regs->vector);
|
|
+}
|
|
+EXPORT_SYMBOL(handle_badint);
|
|
+
|
|
+unsigned int irq_canonicalize(unsigned int irq)
|
|
+{
|
|
+#ifdef CONFIG_Q40
|
|
+ if (MACH_IS_Q40 && irq == 11)
|
|
+ irq = 10;
|
|
+#endif
|
|
+ return irq;
|
|
+}
|
|
+EXPORT_SYMBOL(irq_canonicalize);
|
|
+
|
|
+#ifdef CONFIG_M5445X
|
|
+/*
|
|
+ * M5445X Implementation
|
|
+ */
|
|
+void m5445x_irq_enable(unsigned int irq)
|
|
+{
|
|
+ /* enable the interrupt hardware */
|
|
+ if (irq < 64)
|
|
+ return;
|
|
+
|
|
+ /* adjust past non-hardware ints */
|
|
+ irq -= 64;
|
|
+
|
|
+ /* check for eport */
|
|
+ if ((irq > 0) && (irq < 8)) {
|
|
+ /* enable eport */
|
|
+ MCF_EPORT_EPPAR &= ~(3 << (irq*2)); /* level */
|
|
+ MCF_EPORT_EPDDR &= ~(1 << irq); /* input */
|
|
+ MCF_EPORT_EPIER |= 1 << irq; /* irq enabled */
|
|
+ }
|
|
+
|
|
+ if (irq < 64) {
|
|
+ /* controller 0 */
|
|
+ MCF_INTC0_ICR(irq) = 0x02;
|
|
+ MCF_INTC0_CIMR = irq;
|
|
+ } else {
|
|
+ /* controller 1 */
|
|
+ irq -= 64;
|
|
+ MCF_INTC1_ICR(irq) = 0x02;
|
|
+ MCF_INTC1_CIMR = irq;
|
|
+ }
|
|
+}
|
|
+
|
|
+void m5445x_irq_disable(unsigned int irq)
|
|
+{
|
|
+ /* disable the interrupt hardware */
|
|
+ if (irq < 64)
|
|
+ return;
|
|
+
|
|
+ /* adjust past non-hardware ints */
|
|
+ irq -= 64;
|
|
+
|
|
+ /* check for eport */
|
|
+ if ((irq > 0) && (irq < 8)) {
|
|
+ /* disable eport */
|
|
+ MCF_EPORT_EPIER &= ~(1 << irq);
|
|
+ }
|
|
+
|
|
+ if (irq < 64) {
|
|
+ /* controller 0 */
|
|
+ MCF_INTC0_ICR(irq) = 0x00;
|
|
+ MCF_INTC0_SIMR = irq;
|
|
+ } else {
|
|
+ /* controller 1 */
|
|
+ irq -= 64;
|
|
+ MCF_INTC1_ICR(irq) = 0x00;
|
|
+ MCF_INTC1_SIMR = irq;
|
|
+ }
|
|
+}
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+/*
|
|
+ * M547X_8X Implementation
|
|
+ */
|
|
+void m547x_8x_irq_enable(unsigned int irq)
|
|
+{
|
|
+ /* enable the interrupt hardware */
|
|
+ if (irq < 64)
|
|
+ return;
|
|
+
|
|
+ /* adjust past non-hardware ints */
|
|
+ irq -= 64;
|
|
+
|
|
+ /* check for eport */
|
|
+ if ((irq > 0) && (irq < 8)) {
|
|
+ /* enable eport */
|
|
+ MCF_EPPAR &= ~(3 << (irq*2));
|
|
+ /* level */
|
|
+ MCF_EPDDR &= ~(1 << irq);
|
|
+ /* input */
|
|
+ MCF_EPIER |= 1 << irq;
|
|
+ /* irq enabled */
|
|
+ }
|
|
+
|
|
+ if (irq < 32) {
|
|
+ /* *grumble* don't set low bit of IMRL */
|
|
+ MCF_IMRL &= (~(1 << irq) & 0xfffffffe);
|
|
+ } else {
|
|
+ MCF_IMRH &= ~(1 << (irq - 32));
|
|
+ }
|
|
+}
|
|
+
|
|
+void m547x_8x_irq_disable(unsigned int irq)
|
|
+{
|
|
+ /* disable the interrupt hardware */
|
|
+ if (irq < 64)
|
|
+ return;
|
|
+
|
|
+ /* adjust past non-hardware ints */
|
|
+ irq -= 64;
|
|
+
|
|
+ /* check for eport */
|
|
+ if ((irq > 0) && (irq < 8)) {
|
|
+ /* disable eport */
|
|
+ MCF_EPIER &= ~(1 << irq);
|
|
+ }
|
|
+
|
|
+ if (irq < 32)
|
|
+ MCF_IMRL |= (1 << irq);
|
|
+ else
|
|
+ MCF_IMRH |= (1 << (irq - 32));
|
|
+}
|
|
+
|
|
+#elif defined(CONFIG_M5441X)
|
|
+/*
|
|
+ * M5441X Implementation
|
|
+ */
|
|
+void m5441x_irq_enable(unsigned int irq)
|
|
+{
|
|
+ /* enable the interrupt hardware */
|
|
+ if (irq < 64)
|
|
+ return;
|
|
+
|
|
+ /* adjust past non-hardware ints */
|
|
+ irq -= 64;
|
|
+
|
|
+ /* check for eport */
|
|
+ if ((irq > 0) && (irq < 8)) {
|
|
+ /* enable eport */
|
|
+ MCF_EPORT_EPPAR &= ~(3 << (irq*2)); /* level */
|
|
+ MCF_EPORT_EPIER |= 1 << irq; /* irq enabled */
|
|
+ }
|
|
+
|
|
+ if (irq < 64) {
|
|
+ /* controller 0 */
|
|
+ MCF_INTC0_ICR(irq) = 0x02;
|
|
+ MCF_INTC0_CIMR = irq;
|
|
+ } else if (irq >= 64 && irq < 128) {
|
|
+ /* controller 1 */
|
|
+ irq -= 64;
|
|
+ MCF_INTC1_ICR(irq) = 0x02;
|
|
+ MCF_INTC1_CIMR = irq;
|
|
+ } else if (irq >= 128 && irq < 192) {
|
|
+ /* controller 2 */
|
|
+ irq -= 128;
|
|
+ MCF_INTC2_ICR(irq) = 0x02;
|
|
+ MCF_INTC2_CIMR = irq;
|
|
+ } else {
|
|
+ /* invalid irq number */
|
|
+ return;
|
|
+ }
|
|
+}
|
|
+
|
|
+void m5441x_irq_disable(unsigned int irq)
|
|
+{
|
|
+ /* disable the interrupt hardware */
|
|
+ if (irq < 64)
|
|
+ return;
|
|
+
|
|
+ /* adjust past non-hardware ints */
|
|
+ irq -= 64;
|
|
+
|
|
+ /* check for eport */
|
|
+ if ((irq > 0) && (irq < 8)) {
|
|
+ /* disable eport */
|
|
+ MCF_EPORT_EPIER &= ~(1 << irq);
|
|
+ }
|
|
+
|
|
+ if (irq < 64) {
|
|
+ /* controller 0 */
|
|
+ MCF_INTC0_ICR(irq) = 0x00;
|
|
+ MCF_INTC0_SIMR = irq;
|
|
+ } else if (irq >= 64 && irq < 128) {
|
|
+ /* controller 1 */
|
|
+ irq -= 64;
|
|
+ MCF_INTC1_ICR(irq) = 0x00;
|
|
+ MCF_INTC1_SIMR = irq;
|
|
+ } else if (irq >= 128 && irq < 192) {
|
|
+ /* controller 2 */
|
|
+ irq -= 128;
|
|
+ MCF_INTC2_ICR(irq) = 0x00;
|
|
+ MCF_INTC2_SIMR = irq;
|
|
+ }
|
|
+}
|
|
+#endif
|
|
+
|
|
+/*
|
|
+ * IRQ Controller
|
|
+ */
|
|
+#if defined(CONFIG_M5445X)
|
|
+static struct irq_controller m5445x_irq_controller = {
|
|
+ .name = "M5445X",
|
|
+ .lock = __SPIN_LOCK_UNLOCKED(m5445x_irq_controller.lock),
|
|
+ .enable = m5445x_irq_enable,
|
|
+ .disable = m5445x_irq_disable,
|
|
+};
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+static struct irq_controller m547x_8x_irq_controller = {
|
|
+ .name = "M547X_8X",
|
|
+ .lock = __SPIN_LOCK_UNLOCKED(m547x_8x_irq_controller.lock),
|
|
+ .enable = m547x_8x_irq_enable,
|
|
+ .disable = m547x_8x_irq_disable,
|
|
+};
|
|
+#elif defined(CONFIG_M5441X)
|
|
+static struct irq_controller m5441x_irq_controller = {
|
|
+ .name = "M5441X",
|
|
+ .lock = __SPIN_LOCK_UNLOCKED(m5441x_irq_controller.lock),
|
|
+ .enable = m5441x_irq_enable,
|
|
+ .disable = m5441x_irq_disable,
|
|
+};
|
|
+#else
|
|
+# error No IRQ controller defined
|
|
+#endif
|
|
+
|
|
+/*
|
|
+ * void init_IRQ(void)
|
|
+ *
|
|
+ * This function should be called during kernel startup to initialize
|
|
+ * the IRQ handling routines.
|
|
+ */
|
|
+void __init init_IRQ(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+#if defined(CONFIG_M5445X)
|
|
+ for (i = 0; i < SYS_IRQS; i++)
|
|
+ irq_controller[i] = &m5445x_irq_controller;
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+ for (i = 0; i < SYS_IRQS; i++)
|
|
+ irq_controller[i] = &m547x_8x_irq_controller;
|
|
+#elif defined(CONFIG_M5441X)
|
|
+ for (i = 0; i < SYS_IRQS; i++)
|
|
+ irq_controller[i] = &m5441x_irq_controller;
|
|
+#endif
|
|
+}
|
|
--- /dev/null
|
|
+++ b/arch/m68k/coldfire/common/muldi3.S
|
|
@@ -0,0 +1,73 @@
|
|
+/*
|
|
+ * Coldfire muldi3 assembly verion
|
|
+ *
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.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/linkage.h>
|
|
+.globl __muldi3
|
|
+
|
|
+ENTRY(__muldi3)
|
|
+ linkw %fp,#0
|
|
+ lea %sp@(-32),%sp
|
|
+ moveml %d2-%d7/%a2-%a3,%sp@
|
|
+ moveal %fp@(8), %a2
|
|
+ moveal %fp@(12), %a3
|
|
+ moveal %fp@(16), %a0
|
|
+ moveal %fp@(20),%a1
|
|
+ movel %a3,%d2
|
|
+ andil #65535,%d2
|
|
+ movel %a3,%d3
|
|
+ clrw %d3
|
|
+ swap %d3
|
|
+ movel %a1,%d0
|
|
+ andil #65535,%d0
|
|
+ movel %a1,%d1
|
|
+ clrw %d1
|
|
+ swap %d1
|
|
+ movel %d2,%d7
|
|
+ mulsl %d0,%d7
|
|
+ movel %d2,%d4
|
|
+ mulsl %d1,%d4
|
|
+ movel %d3,%d2
|
|
+ mulsl %d0,%d2
|
|
+ mulsl %d1,%d3
|
|
+ movel %d7,%d0
|
|
+ clrw %d0
|
|
+ swap %d0
|
|
+ addl %d0,%d4
|
|
+ addl %d2,%d4
|
|
+ cmpl %d4,%d2
|
|
+ blss 1f
|
|
+ addil #65536,%d3
|
|
+1:
|
|
+ movel %d4,%d0
|
|
+ clrw %d0
|
|
+ swap %d0
|
|
+ movel %d3,%d5
|
|
+ addl %d0,%d5
|
|
+ movew %d4,%d6
|
|
+ swap %d6
|
|
+ movew %d7,%d6
|
|
+ movel %d5,%d0
|
|
+ movel %d6,%d1
|
|
+ movel %a3,%d2
|
|
+ movel %a0,%d3
|
|
+ mulsl %d3,%d2
|
|
+ movel %a2,%d3
|
|
+ movel %a1,%d4
|
|
+ mulsl %d4,%d3
|
|
+ addl %d3,%d2
|
|
+ movel %d2,%d0
|
|
+ addl %d5,%d0
|
|
+ moveml %sp@, %d2-%d7/%a2-%a3
|
|
+ lea %sp@(32),%sp
|
|
+ unlk %fp
|
|
+ rts
|
|
--- /dev/null
|
|
+++ b/arch/m68k/coldfire/common/signal.c
|
|
@@ -0,0 +1,991 @@
|
|
+/*
|
|
+ * linux/arch/m68k/kernel/signal.c
|
|
+ *
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Matt Waddel Matt.Waddel@freescale.com
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ *
|
|
+ * Derived from m68k/kernel/signal.c and the original authors are credited
|
|
+ * there.
|
|
+ */
|
|
+
|
|
+#include <linux/sched.h>
|
|
+#include <linux/mm.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/signal.h>
|
|
+#include <linux/syscalls.h>
|
|
+#include <linux/errno.h>
|
|
+#include <linux/wait.h>
|
|
+#include <linux/ptrace.h>
|
|
+#include <linux/unistd.h>
|
|
+#include <linux/stddef.h>
|
|
+#include <linux/highuid.h>
|
|
+#include <linux/personality.h>
|
|
+#include <linux/tty.h>
|
|
+#include <linux/binfmts.h>
|
|
+
|
|
+#include <asm/setup.h>
|
|
+#include <asm/uaccess.h>
|
|
+#include <asm/cf_pgtable.h>
|
|
+#include <asm/traps.h>
|
|
+#include <asm/ucontext.h>
|
|
+#include <asm/cacheflush.h>
|
|
+
|
|
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
|
+
|
|
+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
|
|
+
|
|
+const int frame_extra_sizes[16] = {
|
|
+ [1] = -1,
|
|
+ [2] = -1,
|
|
+ [3] = -1,
|
|
+ [4] = 0,
|
|
+ [5] = 1,
|
|
+ [6] = 1,
|
|
+ [7] = 2,
|
|
+ [8] = 3,
|
|
+ [9] = -1,
|
|
+ [10] = -1,
|
|
+ [11] = -1,
|
|
+ [12] = -1,
|
|
+ [13] = -1,
|
|
+ [14] = -1,
|
|
+ [15] = -1,
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Atomically swap in the new signal mask, and wait for a signal.
|
|
+ */
|
|
+asmlinkage int do_sigsuspend(struct pt_regs *regs)
|
|
+{
|
|
+ old_sigset_t mask = regs->d3;
|
|
+ sigset_t saveset;
|
|
+
|
|
+ mask &= _BLOCKABLE;
|
|
+ spin_lock_irq(¤t->sighand->siglock);
|
|
+ saveset = current->blocked;
|
|
+ siginitset(¤t->blocked, mask);
|
|
+ recalc_sigpending();
|
|
+ spin_unlock_irq(¤t->sighand->siglock);
|
|
+
|
|
+ regs->d0 = -EINTR;
|
|
+ while (1) {
|
|
+ current->state = TASK_INTERRUPTIBLE;
|
|
+ schedule();
|
|
+ if (do_signal(&saveset, regs))
|
|
+ return -EINTR;
|
|
+ }
|
|
+}
|
|
+
|
|
+asmlinkage int
|
|
+do_rt_sigsuspend(struct pt_regs *regs)
|
|
+{
|
|
+ sigset_t __user *unewset = (sigset_t __user *)regs->d1;
|
|
+ size_t sigsetsize = (size_t)regs->d2;
|
|
+ sigset_t saveset, newset;
|
|
+
|
|
+ /* XXX: Don't preclude handling different sized sigset_t's. */
|
|
+ if (sigsetsize != sizeof(sigset_t))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
|
|
+ return -EFAULT;
|
|
+ sigdelsetmask(&newset, ~_BLOCKABLE);
|
|
+
|
|
+ spin_lock_irq(¤t->sighand->siglock);
|
|
+ saveset = current->blocked;
|
|
+ current->blocked = newset;
|
|
+ recalc_sigpending();
|
|
+ spin_unlock_irq(¤t->sighand->siglock);
|
|
+
|
|
+ regs->d0 = -EINTR;
|
|
+ while (1) {
|
|
+ current->state = TASK_INTERRUPTIBLE;
|
|
+ schedule();
|
|
+ if (do_signal(&saveset, regs))
|
|
+ return -EINTR;
|
|
+ }
|
|
+}
|
|
+
|
|
+asmlinkage int
|
|
+sys_sigaction(int sig, const struct old_sigaction __user *act,
|
|
+ struct old_sigaction __user *oact)
|
|
+{
|
|
+ struct k_sigaction new_ka, old_ka;
|
|
+ int ret;
|
|
+
|
|
+ if (act) {
|
|
+ old_sigset_t mask;
|
|
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
|
+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
|
+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
|
|
+ return -EFAULT;
|
|
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
|
+ __get_user(mask, &act->sa_mask);
|
|
+ siginitset(&new_ka.sa.sa_mask, mask);
|
|
+ }
|
|
+
|
|
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
|
|
+
|
|
+ if (!ret && oact) {
|
|
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
|
+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
|
+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
|
|
+ return -EFAULT;
|
|
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
|
+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+asmlinkage int
|
|
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
|
|
+{
|
|
+ return do_sigaltstack(uss, uoss, rdusp());
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * Do a signal return; undo the signal stack.
|
|
+ *
|
|
+ * Keep the return code on the stack quadword aligned!
|
|
+ * That makes the cache flush below easier.
|
|
+ */
|
|
+
|
|
+struct sigframe {
|
|
+ char __user *pretcode;
|
|
+ int sig;
|
|
+ int code;
|
|
+ struct sigcontext __user *psc;
|
|
+ char retcode[8];
|
|
+ unsigned long extramask[_NSIG_WORDS-1];
|
|
+ struct sigcontext sc;
|
|
+};
|
|
+
|
|
+struct rt_sigframe {
|
|
+ char __user *pretcode;
|
|
+ int sig;
|
|
+ struct siginfo __user *pinfo;
|
|
+ void __user *puc;
|
|
+ char retcode[8];
|
|
+ struct siginfo info;
|
|
+ struct ucontext uc;
|
|
+};
|
|
+
|
|
+#define FPCONTEXT_SIZE 216
|
|
+#define uc_fpstate uc_filler[0]
|
|
+#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
|
|
+#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
|
|
+
|
|
+#ifdef CONFIG_FPU
|
|
+static unsigned char fpu_version; /* version num of fpu, set by setup_frame */
|
|
+
|
|
+static inline int restore_fpu_state(struct sigcontext *sc)
|
|
+{
|
|
+ int err = 1;
|
|
+
|
|
+ if (FPU_IS_EMU) {
|
|
+ /* restore registers */
|
|
+ memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
|
|
+ memcpy(current->thread.fp, sc->sc_fpregs, 24);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
|
|
+ /* Verify the frame format. */
|
|
+ if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
|
|
+ goto out;
|
|
+ if (CPU_IS_020_OR_030) {
|
|
+ if (m68k_fputype & FPU_68881 &&
|
|
+ !(sc->sc_fpstate[1] == 0x18 ||
|
|
+ sc->sc_fpstate[1] == 0xb4))
|
|
+ goto out;
|
|
+ if (m68k_fputype & FPU_68882 &&
|
|
+ !(sc->sc_fpstate[1] == 0x38 ||
|
|
+ sc->sc_fpstate[1] == 0xd4))
|
|
+ goto out;
|
|
+ } else if (CPU_IS_040) {
|
|
+ if (!(sc->sc_fpstate[1] == 0x00 ||
|
|
+ sc->sc_fpstate[1] == 0x28 ||
|
|
+ sc->sc_fpstate[1] == 0x60))
|
|
+ goto out;
|
|
+ } else if (CPU_IS_060) {
|
|
+ if (!(sc->sc_fpstate[3] == 0x00 ||
|
|
+ sc->sc_fpstate[3] == 0x60 ||
|
|
+ sc->sc_fpstate[3] == 0xe0))
|
|
+ goto out;
|
|
+ } else if (CPU_IS_CFV4E) {
|
|
+ pr_debug("restore v4e fpu state at %s\n", __func__);
|
|
+ } else
|
|
+ goto out;
|
|
+#ifdef CONFIG_CFV4E
|
|
+ __asm__ volatile ("fmovem %0,%/fp0-%/fp1\n\t"
|
|
+ QCHIP_RESTORE_DIRECTIVE
|
|
+ : /* no outputs */
|
|
+ : "m" (sc->sc_fpregs[0][0])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %0,%/fpcr"
|
|
+ : : "m" (sc->sc_fpcntl[0])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %0,%/fpsr"
|
|
+ : : "m" (sc->sc_fpcntl[1])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %0,%/fpiar"
|
|
+ : : "m" (sc->sc_fpcntl[2])
|
|
+ : "memory");
|
|
+
|
|
+#endif
|
|
+ }
|
|
+
|
|
+#ifdef CONFIG_CFV4E
|
|
+ __asm__ volatile ("frestore %0\n\t"
|
|
+ QCHIP_RESTORE_DIRECTIVE : : "m" (*sc->sc_fpstate));
|
|
+#endif
|
|
+ err = 0;
|
|
+
|
|
+out:
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static inline int rt_restore_fpu_state(struct ucontext __user *uc)
|
|
+{
|
|
+ unsigned char fpstate[FPCONTEXT_SIZE];
|
|
+ int context_size = CPU_IS_060 ? 8 : 0;
|
|
+ fpregset_t fpregs;
|
|
+ int err = 1;
|
|
+
|
|
+ if (FPU_IS_EMU) {
|
|
+ /* restore fpu control register */
|
|
+ if (__copy_from_user(current->thread.fpcntl,
|
|
+ uc->uc_mcontext.fpregs.f_fpcntl, 12))
|
|
+ goto out;
|
|
+ /* restore all other fpu register */
|
|
+ if (__copy_from_user(current->thread.fp,
|
|
+ uc->uc_mcontext.fpregs.f_fpregs, 96))
|
|
+ goto out;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
|
|
+ goto out;
|
|
+ if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
|
|
+ if (!CPU_IS_060)
|
|
+ context_size = fpstate[1];
|
|
+ /* Verify the frame format. */
|
|
+ if (!CPU_IS_060 && (fpstate[0] != fpu_version))
|
|
+ goto out;
|
|
+ if (CPU_IS_020_OR_030) {
|
|
+ if (m68k_fputype & FPU_68881 &&
|
|
+ !(context_size == 0x18 || context_size == 0xb4))
|
|
+ goto out;
|
|
+ if (m68k_fputype & FPU_68882 &&
|
|
+ !(context_size == 0x38 || context_size == 0xd4))
|
|
+ goto out;
|
|
+ } else if (CPU_IS_040) {
|
|
+ if (!(context_size == 0x00 ||
|
|
+ context_size == 0x28 ||
|
|
+ context_size == 0x60))
|
|
+ goto out;
|
|
+ } else if (CPU_IS_060) {
|
|
+ if (!(fpstate[3] == 0x00 ||
|
|
+ fpstate[3] == 0x60 ||
|
|
+ fpstate[3] == 0xe0))
|
|
+ goto out;
|
|
+ } else if (CPU_IS_CFV4E) {
|
|
+ pr_debug("restore coldfire rt v4e fpu"
|
|
+ " state at %s\n", __func__);
|
|
+ } else
|
|
+ goto out;
|
|
+ if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
|
|
+ sizeof(fpregs)))
|
|
+ goto out;
|
|
+#ifdef CONFIG_CFV4E
|
|
+ __asm__ volatile ("fmovem %0,%/fp0-%/fp7\n\t"
|
|
+ QCHIP_RESTORE_DIRECTIVE
|
|
+ : /* no outputs */
|
|
+ : "m" (fpregs.f_fpregs[0][0])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %0,%/fpcr"
|
|
+ : : "m" (fpregs.f_fpcntl[0])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %0,%/fpsr"
|
|
+ : : "m" (fpregs.f_fpcntl[1])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %0,%/fpiar"
|
|
+ : : "m" (fpregs.f_fpcntl[2])
|
|
+ : "memory");
|
|
+#endif
|
|
+ }
|
|
+ if (context_size &&
|
|
+ __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
|
|
+ context_size))
|
|
+ goto out;
|
|
+#ifdef CONFIG_CFV4E
|
|
+ __asm__ volatile ("frestore %0\n\t"
|
|
+ QCHIP_RESTORE_DIRECTIVE : : "m" (*fpstate));
|
|
+#endif
|
|
+ err = 0;
|
|
+
|
|
+out:
|
|
+ return err;
|
|
+}
|
|
+#endif
|
|
+
|
|
+static inline int
|
|
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc,
|
|
+ void __user *fp, int *pd0)
|
|
+{
|
|
+ int fsize, formatvec;
|
|
+ struct sigcontext context;
|
|
+ int err = 0;
|
|
+
|
|
+ /* get previous context */
|
|
+ if (copy_from_user(&context, usc, sizeof(context)))
|
|
+ goto badframe;
|
|
+
|
|
+ /* restore passed registers */
|
|
+ regs->d1 = context.sc_d1;
|
|
+ regs->a0 = context.sc_a0;
|
|
+ regs->a1 = context.sc_a1;
|
|
+ regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
|
|
+ regs->pc = context.sc_pc;
|
|
+ regs->orig_d0 = -1; /* disable syscall checks */
|
|
+ wrusp(context.sc_usp);
|
|
+ formatvec = context.sc_formatvec;
|
|
+ regs->format = formatvec >> 12;
|
|
+ regs->vector = formatvec & 0xfff;
|
|
+
|
|
+#ifdef CONFIG_FPU
|
|
+ err = restore_fpu_state(&context);
|
|
+#endif
|
|
+
|
|
+ fsize = frame_extra_sizes[regs->format];
|
|
+ if (fsize < 0) {
|
|
+ /*
|
|
+ * user process trying to return with weird frame format
|
|
+ */
|
|
+#ifdef DEBUG
|
|
+ printk(KERN_DEBUG "user process returning with weird \
|
|
+ frame format\n");
|
|
+#endif
|
|
+ goto badframe;
|
|
+ }
|
|
+
|
|
+ /* OK. Make room on the supervisor stack for the extra junk,
|
|
+ * if necessary.
|
|
+ */
|
|
+
|
|
+ {
|
|
+ struct switch_stack *sw = (struct switch_stack *)regs - 1;
|
|
+ regs->d0 = context.sc_d0;
|
|
+#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
|
|
+ __asm__ __volatile__
|
|
+ (" movel %0,%/sp\n\t"
|
|
+ " bra ret_from_signal\n"
|
|
+ "4:\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 2b,4b\n"
|
|
+ ".previous"
|
|
+ : /* no outputs, it doesn't ever return */
|
|
+ : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
|
|
+ "n" (frame_offset), "a" (fp)
|
|
+ : "a0");
|
|
+#undef frame_offset
|
|
+ /*
|
|
+ * If we ever get here an exception occurred while
|
|
+ * building the above stack-frame.
|
|
+ */
|
|
+ goto badframe;
|
|
+ }
|
|
+
|
|
+ *pd0 = context.sc_d0;
|
|
+ return err;
|
|
+
|
|
+badframe:
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static inline int
|
|
+rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
|
|
+ struct ucontext __user *uc, int *pd0)
|
|
+{
|
|
+ int fsize, temp;
|
|
+ greg_t __user *gregs = uc->uc_mcontext.gregs;
|
|
+ unsigned long usp;
|
|
+ int err;
|
|
+
|
|
+ err = __get_user(temp, &uc->uc_mcontext.version);
|
|
+ if (temp != MCONTEXT_VERSION)
|
|
+ goto badframe;
|
|
+ /* restore passed registers */
|
|
+ err |= __get_user(regs->d0, &gregs[0]);
|
|
+ err |= __get_user(regs->d1, &gregs[1]);
|
|
+ err |= __get_user(regs->d2, &gregs[2]);
|
|
+ err |= __get_user(regs->d3, &gregs[3]);
|
|
+ err |= __get_user(regs->d4, &gregs[4]);
|
|
+ err |= __get_user(regs->d5, &gregs[5]);
|
|
+ err |= __get_user(sw->d6, &gregs[6]);
|
|
+ err |= __get_user(sw->d7, &gregs[7]);
|
|
+ err |= __get_user(regs->a0, &gregs[8]);
|
|
+ err |= __get_user(regs->a1, &gregs[9]);
|
|
+ err |= __get_user(regs->a2, &gregs[10]);
|
|
+ err |= __get_user(sw->a3, &gregs[11]);
|
|
+ err |= __get_user(sw->a4, &gregs[12]);
|
|
+ err |= __get_user(sw->a5, &gregs[13]);
|
|
+ err |= __get_user(sw->a6, &gregs[14]);
|
|
+ err |= __get_user(usp, &gregs[15]);
|
|
+ wrusp(usp);
|
|
+ err |= __get_user(regs->pc, &gregs[16]);
|
|
+ err |= __get_user(temp, &gregs[17]);
|
|
+ regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
|
|
+ regs->orig_d0 = -1; /* disable syscall checks */
|
|
+ err |= __get_user(temp, &uc->uc_formatvec);
|
|
+ regs->format = temp >> 12;
|
|
+ regs->vector = temp & 0xfff;
|
|
+
|
|
+#ifdef CONFIG_FPU
|
|
+ err |= rt_restore_fpu_state(uc);
|
|
+#endif
|
|
+
|
|
+ if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
|
|
+ goto badframe;
|
|
+
|
|
+ fsize = frame_extra_sizes[regs->format];
|
|
+ if (fsize < 0) {
|
|
+ /*
|
|
+ * user process trying to return with weird frame format
|
|
+ */
|
|
+#ifdef DEBUG
|
|
+ printk(KERN_DEBUG "user process returning with weird \
|
|
+ frame format\n");
|
|
+#endif
|
|
+ goto badframe;
|
|
+ }
|
|
+
|
|
+ /* OK. Make room on the supervisor stack for the extra junk,
|
|
+ * if necessary.
|
|
+ */
|
|
+
|
|
+ {
|
|
+#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
|
|
+ __asm__ __volatile__
|
|
+ (" movel %0,%/sp\n\t"
|
|
+ " bra ret_from_signal\n"
|
|
+ "4:\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 2b,4b\n"
|
|
+ ".previous"
|
|
+ : /* no outputs, it doesn't ever return */
|
|
+ : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
|
|
+ "n" (frame_offset), "a" (&uc->uc_extra)
|
|
+ : "a0");
|
|
+#undef frame_offset
|
|
+ /*
|
|
+ * If we ever get here an exception occurred while
|
|
+ * building the above stack-frame.
|
|
+ */
|
|
+ goto badframe;
|
|
+ }
|
|
+
|
|
+ *pd0 = regs->d0;
|
|
+ return err;
|
|
+
|
|
+badframe:
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+asmlinkage int do_sigreturn(unsigned long __unused)
|
|
+{
|
|
+ struct switch_stack *sw = (struct switch_stack *) &__unused;
|
|
+ struct pt_regs *regs = (struct pt_regs *) (sw + 1);
|
|
+ unsigned long usp = rdusp();
|
|
+ struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
|
|
+ sigset_t set;
|
|
+ int d0;
|
|
+
|
|
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
|
+ goto badframe;
|
|
+ if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
|
|
+ (_NSIG_WORDS > 1 &&
|
|
+ __copy_from_user(&set.sig[1], &frame->extramask,
|
|
+ sizeof(frame->extramask))))
|
|
+ goto badframe;
|
|
+
|
|
+ sigdelsetmask(&set, ~_BLOCKABLE);
|
|
+ spin_lock_irq(¤t->sighand->siglock);
|
|
+ current->blocked = set;
|
|
+ recalc_sigpending();
|
|
+ spin_unlock_irq(¤t->sighand->siglock);
|
|
+
|
|
+ if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
|
|
+ goto badframe;
|
|
+ return d0;
|
|
+
|
|
+badframe:
|
|
+ force_sig(SIGSEGV, current);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+asmlinkage int do_rt_sigreturn(unsigned long __unused)
|
|
+{
|
|
+ struct switch_stack *sw = (struct switch_stack *) &__unused;
|
|
+ struct pt_regs *regs = (struct pt_regs *) (sw + 1);
|
|
+ unsigned long usp = rdusp();
|
|
+ struct rt_sigframe __user *frame =
|
|
+ (struct rt_sigframe __user *)(usp - 4);
|
|
+ sigset_t set;
|
|
+ int d0;
|
|
+
|
|
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
|
+ goto badframe;
|
|
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
|
|
+ goto badframe;
|
|
+
|
|
+ sigdelsetmask(&set, ~_BLOCKABLE);
|
|
+ spin_lock_irq(¤t->sighand->siglock);
|
|
+ current->blocked = set;
|
|
+ recalc_sigpending();
|
|
+ spin_unlock_irq(¤t->sighand->siglock);
|
|
+
|
|
+ if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
|
|
+ goto badframe;
|
|
+ return d0;
|
|
+
|
|
+badframe:
|
|
+ force_sig(SIGSEGV, current);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#ifdef CONFIG_FPU
|
|
+/*
|
|
+ * Set up a signal frame.
|
|
+ */
|
|
+
|
|
+static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
|
|
+{
|
|
+ if (FPU_IS_EMU) {
|
|
+ /* save registers */
|
|
+ memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
|
|
+ memcpy(sc->sc_fpregs, current->thread.fp, 24);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+#ifdef CONFIG_CFV4E
|
|
+ __asm__ volatile ("fsave %0\n\t"
|
|
+ QCHIP_RESTORE_DIRECTIVE
|
|
+ : : "m" (*sc->sc_fpstate) : "memory");
|
|
+#endif
|
|
+
|
|
+ if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
|
|
+ fpu_version = sc->sc_fpstate[0];
|
|
+ if (CPU_IS_020_OR_030 &&
|
|
+ regs->vector >= (VEC_FPBRUC * 4) &&
|
|
+ regs->vector <= (VEC_FPNAN * 4)) {
|
|
+ /* Clear pending exception in 68882 idle frame */
|
|
+ if (*(unsigned short *) sc->sc_fpstate == 0x1f38)
|
|
+ sc->sc_fpstate[0x38] |= 1 << 3;
|
|
+ }
|
|
+#ifdef CONFIG_CFV4E
|
|
+ __asm__ volatile ("fmovemd %/fp0-%/fp1,%0"
|
|
+ : : "m" (sc->sc_fpregs[0][0])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %/fpcr,%0"
|
|
+ : : "m" (sc->sc_fpcntl[0])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %/fpsr,%0"
|
|
+ : : "m" (sc->sc_fpcntl[1])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %/fpiar,%0"
|
|
+ : : "m" (sc->sc_fpcntl[2])
|
|
+ : "memory");
|
|
+
|
|
+#endif
|
|
+ }
|
|
+}
|
|
+
|
|
+static inline int rt_save_fpu_state(struct ucontext __user *uc,
|
|
+ struct pt_regs *regs)
|
|
+{
|
|
+ unsigned char fpstate[FPCONTEXT_SIZE];
|
|
+ int context_size = CPU_IS_060 ? 8 : 0;
|
|
+ int err = 0;
|
|
+
|
|
+ if (FPU_IS_EMU) {
|
|
+ /* save fpu control register */
|
|
+ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
|
|
+ current->thread.fpcntl, 12);
|
|
+ /* save all other fpu register */
|
|
+ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
|
|
+ current->thread.fp, 96);
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+#ifdef CONFIG_CFV4E
|
|
+ __asm__ volatile ("fsave %0\n\t"
|
|
+ QCHIP_RESTORE_DIRECTIVE
|
|
+ : : "m" (*fpstate) : "memory");
|
|
+#endif
|
|
+ err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
|
|
+ if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
|
|
+ fpregset_t fpregs;
|
|
+ if (!CPU_IS_060)
|
|
+ context_size = fpstate[1];
|
|
+ fpu_version = fpstate[0];
|
|
+#ifdef CONFIG_CFV4E
|
|
+ __asm__ volatile ("fmovemd %/fp0-%/fp7,%0"
|
|
+ : : "m" (fpregs.f_fpregs[0][0])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %/fpcr,%0"
|
|
+ : : "m" (fpregs.f_fpcntl[0])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %/fpsr,%0"
|
|
+ : : "m" (fpregs.f_fpcntl[1])
|
|
+ : "memory");
|
|
+ __asm__ volatile ("fmovel %/fpiar,%0"
|
|
+ : : "m" (fpregs.f_fpcntl[2])
|
|
+ : "memory");
|
|
+#endif
|
|
+ err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
|
|
+ sizeof(fpregs));
|
|
+ }
|
|
+ if (context_size)
|
|
+ err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
|
|
+ context_size);
|
|
+ return err;
|
|
+
|
|
+
|
|
+ return err;
|
|
+}
|
|
+#endif
|
|
+
|
|
+static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
|
|
+ unsigned long mask)
|
|
+{
|
|
+ sc->sc_mask = mask;
|
|
+ sc->sc_usp = rdusp();
|
|
+ sc->sc_d0 = regs->d0;
|
|
+ sc->sc_d1 = regs->d1;
|
|
+ sc->sc_a0 = regs->a0;
|
|
+ sc->sc_a1 = regs->a1;
|
|
+ sc->sc_sr = regs->sr;
|
|
+ sc->sc_pc = regs->pc;
|
|
+ sc->sc_formatvec = regs->format << 12 | regs->vector;
|
|
+#ifdef CONFIG_FPU
|
|
+ save_fpu_state(sc, regs);
|
|
+#endif
|
|
+}
|
|
+
|
|
+static inline int rt_setup_ucontext(struct ucontext __user *uc,
|
|
+ struct pt_regs *regs)
|
|
+{
|
|
+ struct switch_stack *sw = (struct switch_stack *)regs - 1;
|
|
+ greg_t __user *gregs = uc->uc_mcontext.gregs;
|
|
+ int err = 0;
|
|
+
|
|
+ err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
|
|
+ err |= __put_user(regs->d0, &gregs[0]);
|
|
+ err |= __put_user(regs->d1, &gregs[1]);
|
|
+ err |= __put_user(regs->d2, &gregs[2]);
|
|
+ err |= __put_user(regs->d3, &gregs[3]);
|
|
+ err |= __put_user(regs->d4, &gregs[4]);
|
|
+ err |= __put_user(regs->d5, &gregs[5]);
|
|
+ err |= __put_user(sw->d6, &gregs[6]);
|
|
+ err |= __put_user(sw->d7, &gregs[7]);
|
|
+ err |= __put_user(regs->a0, &gregs[8]);
|
|
+ err |= __put_user(regs->a1, &gregs[9]);
|
|
+ err |= __put_user(regs->a2, &gregs[10]);
|
|
+ err |= __put_user(sw->a3, &gregs[11]);
|
|
+ err |= __put_user(sw->a4, &gregs[12]);
|
|
+ err |= __put_user(sw->a5, &gregs[13]);
|
|
+ err |= __put_user(sw->a6, &gregs[14]);
|
|
+ err |= __put_user(rdusp(), &gregs[15]);
|
|
+ err |= __put_user(regs->pc, &gregs[16]);
|
|
+ err |= __put_user(regs->sr, &gregs[17]);
|
|
+ err |= __put_user((regs->format << 12) | regs->vector,
|
|
+ &uc->uc_formatvec);
|
|
+#ifdef CONFIG_FPU
|
|
+ err |= rt_save_fpu_state(uc, regs);
|
|
+#endif
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static inline void push_cache(unsigned long vaddr)
|
|
+{
|
|
+#if defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
|
|
+ pgd_t *pdir;
|
|
+ pmd_t *pmdp;
|
|
+ pte_t *ptep;
|
|
+ unsigned long paddr;
|
|
+
|
|
+ pdir = pgd_offset(current->mm, vaddr);
|
|
+ pmdp = pmd_offset(pdir, vaddr);
|
|
+ ptep = pte_offset_map(pmdp, vaddr);
|
|
+ paddr = ((pte_val(*ptep) & PAGE_MASK) | (vaddr & ~PAGE_MASK));
|
|
+ cf_icache_flush_range(paddr, paddr + 8);
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+ flush_icache_range(vaddr, vaddr + 8);
|
|
+#endif
|
|
+}
|
|
+
|
|
+static inline void __user *
|
|
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
|
|
+{
|
|
+ unsigned long usp;
|
|
+
|
|
+ /* Default to using normal stack. */
|
|
+ usp = rdusp();
|
|
+
|
|
+ /* This is the X/Open sanctioned signal stack switching. */
|
|
+ if (ka->sa.sa_flags & SA_ONSTACK) {
|
|
+ if (!sas_ss_flags(usp))
|
|
+ usp = current->sas_ss_sp + current->sas_ss_size;
|
|
+ }
|
|
+ return (void __user *)((usp - frame_size) & -8UL);
|
|
+}
|
|
+
|
|
+static void setup_frame(int sig, struct k_sigaction *ka,
|
|
+ sigset_t *set, struct pt_regs *regs)
|
|
+{
|
|
+ struct sigframe __user *frame;
|
|
+ int fsize = frame_extra_sizes[regs->format];
|
|
+ struct sigcontext context;
|
|
+ int err = 0;
|
|
+
|
|
+ if (fsize < 0) {
|
|
+#ifdef DEBUG
|
|
+ printk(KERN_DEBUG "setup_frame: Unknown frame format %#x\n",
|
|
+ regs->format);
|
|
+#endif
|
|
+ goto give_sigsegv;
|
|
+ }
|
|
+
|
|
+ frame = get_sigframe(ka, regs, sizeof(*frame));
|
|
+
|
|
+ err |= __put_user((current_thread_info()->exec_domain
|
|
+ && current_thread_info()->exec_domain->signal_invmap
|
|
+ && sig < 32
|
|
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
|
|
+ : sig),
|
|
+ &frame->sig);
|
|
+
|
|
+ err |= __put_user(regs->vector, &frame->code);
|
|
+ err |= __put_user(&frame->sc, &frame->psc);
|
|
+
|
|
+ if (_NSIG_WORDS > 1)
|
|
+ err |= copy_to_user(frame->extramask, &set->sig[1],
|
|
+ sizeof(frame->extramask));
|
|
+
|
|
+ setup_sigcontext(&context, regs, set->sig[0]);
|
|
+ err |= copy_to_user(&frame->sc, &context, sizeof(context));
|
|
+
|
|
+ /* Set up to return from userspace. */
|
|
+ err |= __put_user(frame->retcode, &frame->pretcode);
|
|
+ /* moveq #,d0; trap #0 */
|
|
+ err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
|
|
+ (long __user *)(frame->retcode));
|
|
+
|
|
+ if (err)
|
|
+ goto give_sigsegv;
|
|
+
|
|
+ push_cache((unsigned long) &frame->retcode);
|
|
+
|
|
+ /* Set up registers for signal handler */
|
|
+ wrusp((unsigned long) frame);
|
|
+ regs->pc = (unsigned long) ka->sa.sa_handler;
|
|
+
|
|
+adjust_stack:
|
|
+ /* Prepare to skip over the extra stuff in the exception frame. */
|
|
+ if (regs->stkadj) {
|
|
+ struct pt_regs *tregs =
|
|
+ (struct pt_regs *)((ulong)regs + regs->stkadj);
|
|
+#ifdef DEBUG
|
|
+ printk(KERN_DEBUG "Performing stackadjust=%04x\n",
|
|
+ regs->stkadj);
|
|
+#endif
|
|
+ /* This must be copied with decreasing addresses to
|
|
+ handle overlaps. */
|
|
+ tregs->vector = 0;
|
|
+ tregs->format = 0;
|
|
+ tregs->pc = regs->pc;
|
|
+ tregs->sr = regs->sr;
|
|
+ }
|
|
+ return;
|
|
+
|
|
+give_sigsegv:
|
|
+ force_sigsegv(sig, current);
|
|
+ goto adjust_stack;
|
|
+}
|
|
+
|
|
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|
+ sigset_t *set, struct pt_regs *regs)
|
|
+{
|
|
+ struct rt_sigframe __user *frame;
|
|
+ int fsize = frame_extra_sizes[regs->format];
|
|
+ int err = 0;
|
|
+
|
|
+ if (fsize < 0) {
|
|
+#ifdef DEBUG
|
|
+ printk(KERN_DEBUG "setup_frame: Unknown frame format %#x\n",
|
|
+ regs->format);
|
|
+#endif
|
|
+ goto give_sigsegv;
|
|
+ }
|
|
+
|
|
+ frame = get_sigframe(ka, regs, sizeof(*frame));
|
|
+
|
|
+ if (fsize) {
|
|
+ err |= copy_to_user(&frame->uc.uc_extra, regs + 1, fsize);
|
|
+ regs->stkadj = fsize;
|
|
+ }
|
|
+
|
|
+ err |= __put_user((current_thread_info()->exec_domain
|
|
+ && current_thread_info()->exec_domain->signal_invmap
|
|
+ && sig < 32
|
|
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
|
|
+ : sig),
|
|
+ &frame->sig);
|
|
+ err |= __put_user(&frame->info, &frame->pinfo);
|
|
+ err |= __put_user(&frame->uc, &frame->puc);
|
|
+ err |= copy_siginfo_to_user(&frame->info, info);
|
|
+
|
|
+ /* Create the ucontext. */
|
|
+ err |= __put_user(0, &frame->uc.uc_flags);
|
|
+ err |= __put_user(NULL, &frame->uc.uc_link);
|
|
+ err |= __put_user((void __user *)current->sas_ss_sp,
|
|
+ &frame->uc.uc_stack.ss_sp);
|
|
+ err |= __put_user(sas_ss_flags(rdusp()),
|
|
+ &frame->uc.uc_stack.ss_flags);
|
|
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
|
|
+ err |= rt_setup_ucontext(&frame->uc, regs);
|
|
+ err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
|
+
|
|
+ /* Set up to return from userspace. */
|
|
+ err |= __put_user(frame->retcode, &frame->pretcode);
|
|
+
|
|
+ /* movel #__NR_rt_sigreturn(0xAD),d0; trap #0 */
|
|
+ err |= __put_user(0x203c0000, (long *)(frame->retcode + 0));
|
|
+ err |= __put_user(0x00ad4e40, (long *)(frame->retcode + 4));
|
|
+
|
|
+ if (err)
|
|
+ goto give_sigsegv;
|
|
+
|
|
+ push_cache((unsigned long) &frame->retcode);
|
|
+
|
|
+ /* Set up registers for signal handler */
|
|
+ wrusp((unsigned long) frame);
|
|
+ regs->pc = (unsigned long) ka->sa.sa_handler;
|
|
+
|
|
+adjust_stack:
|
|
+ /* Prepare to skip over the extra stuff in the exception frame. */
|
|
+ if (regs->stkadj) {
|
|
+ struct pt_regs *tregs =
|
|
+ (struct pt_regs *)((ulong)regs + regs->stkadj);
|
|
+#ifdef DEBUG
|
|
+ printk(KERN_DEBUG "Performing stackadjust=%04x\n",
|
|
+ regs->stkadj);
|
|
+#endif
|
|
+ /* This must be copied with decreasing addresses to
|
|
+ handle overlaps. */
|
|
+ tregs->vector = 0;
|
|
+ tregs->format = 0;
|
|
+ tregs->pc = regs->pc;
|
|
+ tregs->sr = regs->sr;
|
|
+ }
|
|
+ return;
|
|
+
|
|
+give_sigsegv:
|
|
+ force_sigsegv(sig, current);
|
|
+ goto adjust_stack;
|
|
+}
|
|
+
|
|
+static inline void
|
|
+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
|
|
+{
|
|
+ switch (regs->d0) {
|
|
+ case -ERESTARTNOHAND:
|
|
+ if (!has_handler)
|
|
+ goto do_restart;
|
|
+ regs->d0 = -EINTR;
|
|
+ break;
|
|
+
|
|
+ case -ERESTARTSYS:
|
|
+ if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
|
|
+ regs->d0 = -EINTR;
|
|
+ break;
|
|
+ }
|
|
+ /* fallthrough */
|
|
+ case -ERESTARTNOINTR:
|
|
+do_restart:
|
|
+ regs->d0 = regs->orig_d0;
|
|
+ regs->pc -= 2;
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * OK, we're invoking a handler
|
|
+ */
|
|
+static void
|
|
+handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|
+ sigset_t *oldset, struct pt_regs *regs)
|
|
+{
|
|
+ /* are we from a system call? */
|
|
+ if (regs->orig_d0 >= 0)
|
|
+ /* If so, check system call restarting.. */
|
|
+ handle_restart(regs, ka, 1);
|
|
+
|
|
+ /* set up the stack frame */
|
|
+ if (ka->sa.sa_flags & SA_SIGINFO)
|
|
+ setup_rt_frame(sig, ka, info, oldset, regs);
|
|
+ else
|
|
+ setup_frame(sig, ka, oldset, regs);
|
|
+
|
|
+ if (ka->sa.sa_flags & SA_ONESHOT)
|
|
+ ka->sa.sa_handler = SIG_DFL;
|
|
+
|
|
+ spin_lock_irq(¤t->sighand->siglock);
|
|
+ sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
|
+ if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
+ sigaddset(¤t->blocked, sig);
|
|
+ recalc_sigpending();
|
|
+ spin_unlock_irq(¤t->sighand->siglock);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
|
|
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
|
|
+ * mistake.
|
|
+ */
|
|
+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
|
+{
|
|
+ siginfo_t info;
|
|
+ struct k_sigaction ka;
|
|
+ int signr;
|
|
+
|
|
+ current->thread.esp0 = (unsigned long) regs;
|
|
+
|
|
+ if (!oldset)
|
|
+ oldset = ¤t->blocked;
|
|
+
|
|
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
|
+ if (signr > 0) {
|
|
+ /* Whee! Actually deliver the signal. */
|
|
+ handle_signal(signr, &ka, &info, oldset, regs);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ /* Did we come from a system call? */
|
|
+ if (regs->orig_d0 >= 0)
|
|
+ /* Restart the system call - no handlers present */
|
|
+ handle_restart(regs, NULL, 0);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
--- /dev/null
|
|
+++ b/arch/m68k/coldfire/common/traps.c
|
|
@@ -0,0 +1,457 @@
|
|
+/*
|
|
+ * linux/arch/m68knommu/kernel/traps.c
|
|
+ *
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Sets up all exception vectors
|
|
+ */
|
|
+#include <linux/sched.h>
|
|
+#include <linux/signal.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/mm.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/a.out.h>
|
|
+#include <linux/user.h>
|
|
+#include <linux/string.h>
|
|
+#include <linux/linkage.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/ptrace.h>
|
|
+#include <linux/kallsyms.h>
|
|
+
|
|
+#include <asm/setup.h>
|
|
+#include <asm/fpu.h>
|
|
+#include <asm/system.h>
|
|
+#include <asm/uaccess.h>
|
|
+#include <asm/traps.h>
|
|
+#include <asm/pgtable.h>
|
|
+#include <asm/machdep.h>
|
|
+#include <asm/siginfo.h>
|
|
+
|
|
+static char const * const vec_names[] = {
|
|
+ "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
|
|
+ "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
|
|
+ "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
|
|
+ "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
|
|
+ "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
|
|
+ "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
|
|
+ "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
|
|
+ "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
|
|
+ "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
|
|
+ "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
|
|
+ "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
|
|
+ "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
|
|
+ "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
|
|
+ "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
|
|
+ "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
|
|
+ "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
|
|
+ "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
|
|
+ "FPCP UNSUPPORTED OPERATION",
|
|
+ "MMU CONFIGURATION ERROR"
|
|
+};
|
|
+
|
|
+asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
|
|
+ unsigned long error_code);
|
|
+asmlinkage void trap_c(struct frame *fp);
|
|
+extern void __init coldfire_trap_init(void);
|
|
+
|
|
+void __init trap_init(void)
|
|
+{
|
|
+ coldfire_trap_init();
|
|
+}
|
|
+
|
|
+/* The following table converts the FS encoding of a ColdFire
|
|
+ exception stack frame into the error_code value needed by
|
|
+ do_fault. */
|
|
+
|
|
+static const unsigned char fs_err_code[] = {
|
|
+ 0, /* 0000 */
|
|
+ 0, /* 0001 */
|
|
+ 0, /* 0010 */
|
|
+ 0, /* 0011 */
|
|
+ 1, /* 0100 */
|
|
+ 0, /* 0101 */
|
|
+ 0, /* 0110 */
|
|
+ 0, /* 0111 */
|
|
+ 2, /* 1000 */
|
|
+ 3, /* 1001 */
|
|
+ 2, /* 1010 */
|
|
+ 0, /* 1011 */
|
|
+ 1, /* 1100 */
|
|
+ 1, /* 1101 */
|
|
+ 0, /* 1110 */
|
|
+ 0 /* 1111 */
|
|
+};
|
|
+
|
|
+#ifdef DEBUG
|
|
+static const char *fs_err_msg[16] = {
|
|
+ "Normal",
|
|
+ "Reserved",
|
|
+ "Interrupt during debug service routine",
|
|
+ "Reserved",
|
|
+ "X Protection",
|
|
+ "TLB X miss (opword)",
|
|
+ "TLB X miss (ext. word)",
|
|
+ "IFP in emulator mode",
|
|
+ "W Protection",
|
|
+ "Write error",
|
|
+ "TLB W miss",
|
|
+ "Reserved",
|
|
+ "R Protection",
|
|
+ "R/RMW Protection",
|
|
+ "TLB R miss",
|
|
+ "OEP in emulator mode",
|
|
+};
|
|
+#endif
|
|
+
|
|
+static inline void access_errorCF(struct frame *fp)
|
|
+{
|
|
+ unsigned long int mmusr, complainingAddress;
|
|
+ unsigned int err_code, fs;
|
|
+ int need_page_fault;
|
|
+
|
|
+ mmusr = fp->ptregs.mmusr;
|
|
+ complainingAddress = fp->ptregs.mmuar;
|
|
+#ifdef DEBUG
|
|
+ printk(KERN_DEBUG "pc %#lx, mmusr %#lx, complainingAddress %#lx\n", \
|
|
+ fp->ptregs.pc, mmusr, complainingAddress);
|
|
+#endif
|
|
+
|
|
+ /*
|
|
+ * error_code:
|
|
+ * bit 0 == 0 means no page found, 1 means protection fault
|
|
+ * bit 1 == 0 means read, 1 means write
|
|
+ */
|
|
+
|
|
+ fs = (fp->ptregs.fs2 << 2) | fp->ptregs.fs1;
|
|
+ switch (fs) {
|
|
+ case 5: /* 0101 TLB opword X miss */
|
|
+ need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 0);
|
|
+ complainingAddress = fp->ptregs.pc;
|
|
+ break;
|
|
+ case 6: /* 0110 TLB extension word X miss */
|
|
+ need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 1);
|
|
+ complainingAddress = fp->ptregs.pc + sizeof(long);
|
|
+ break;
|
|
+ case 10: /* 1010 TLB W miss */
|
|
+ need_page_fault = cf_tlb_miss(&fp->ptregs, 1, 1, 0);
|
|
+ break;
|
|
+ case 14: /* 1110 TLB R miss */
|
|
+ need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 1, 0);
|
|
+ break;
|
|
+ default:
|
|
+ /* 0000 Normal */
|
|
+ /* 0001 Reserved */
|
|
+ /* 0010 Interrupt during debug service routine */
|
|
+ /* 0011 Reserved */
|
|
+ /* 0100 X Protection */
|
|
+ /* 0111 IFP in emulator mode */
|
|
+ /* 1000 W Protection*/
|
|
+ /* 1001 Write error*/
|
|
+ /* 1011 Reserved*/
|
|
+ /* 1100 R Protection*/
|
|
+ /* 1101 R Protection*/
|
|
+ /* 1111 OEP in emulator mode*/
|
|
+ need_page_fault = 1;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (need_page_fault) {
|
|
+ err_code = fs_err_code[fs];
|
|
+ if ((fs == 13) && (mmusr & MMUSR_WF)) /* rd-mod-wr access */
|
|
+ err_code |= 2; /* bit1 - write, bit0 - protection */
|
|
+ do_page_fault(&fp->ptregs, complainingAddress, err_code);
|
|
+ }
|
|
+}
|
|
+
|
|
+void die_if_kernel(char *str, struct pt_regs *fp, int nr)
|
|
+{
|
|
+ if (!(fp->sr & PS_S))
|
|
+ return;
|
|
+
|
|
+ console_verbose();
|
|
+ printk(KERN_EMERG "%s: %08x\n", str, nr);
|
|
+ printk(KERN_EMERG "PC: [<%08lx>]", fp->pc);
|
|
+ print_symbol(" %s", fp->pc);
|
|
+ printk(KERN_EMERG "\nSR: %04x SP: %p a2: %08lx\n",
|
|
+ fp->sr, fp, fp->a2);
|
|
+ printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
|
|
+ fp->d0, fp->d1, fp->d2, fp->d3);
|
|
+ printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
|
|
+ fp->d4, fp->d5, fp->a0, fp->a1);
|
|
+
|
|
+ printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
|
|
+ current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
|
|
+ show_stack(NULL, (unsigned long *)fp);
|
|
+ do_exit(SIGSEGV);
|
|
+}
|
|
+
|
|
+asmlinkage void buserr_c(struct frame *fp)
|
|
+{
|
|
+ unsigned int fs;
|
|
+
|
|
+ /* Only set esp0 if coming from user mode */
|
|
+ if (user_mode(&fp->ptregs))
|
|
+ current->thread.esp0 = (unsigned long) fp;
|
|
+
|
|
+ fs = (fp->ptregs.fs2 << 2) | fp->ptregs.fs1;
|
|
+#if defined(DEBUG)
|
|
+ printk(KERN_DEBUG "*** Bus Error *** (%x)%s\n", fs,
|
|
+ fs_err_msg[fs & 0xf]);
|
|
+#endif
|
|
+ switch (fs) {
|
|
+ case 0x5:
|
|
+ case 0x6:
|
|
+ case 0x7:
|
|
+ case 0x9:
|
|
+ case 0xa:
|
|
+ case 0xd:
|
|
+ case 0xe:
|
|
+ case 0xf:
|
|
+ access_errorCF(fp);
|
|
+ break;
|
|
+ default:
|
|
+ die_if_kernel("bad frame format", &fp->ptregs, 0);
|
|
+#if defined(DEBUG)
|
|
+ printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
|
|
+#endif
|
|
+ force_sig(SIGSEGV, current);
|
|
+ }
|
|
+}
|
|
+
|
|
+void show_trace(unsigned long *stack)
|
|
+{
|
|
+ unsigned long *endstack;
|
|
+ unsigned long addr;
|
|
+ int i;
|
|
+
|
|
+ printk(KERN_INFO "Call Trace:");
|
|
+ addr = (unsigned long)stack + THREAD_SIZE - 1;
|
|
+ endstack = (unsigned long *)(addr & -THREAD_SIZE);
|
|
+ i = 0;
|
|
+ while (stack + 1 <= endstack) {
|
|
+ addr = *stack++;
|
|
+ /*
|
|
+ * If the address is either in the text segment of the
|
|
+ * kernel, or in the region which contains vmalloc'ed
|
|
+ * memory, it *may* be the address of a calling
|
|
+ * routine; if so, print it so that someone tracing
|
|
+ * down the cause of the crash will be able to figure
|
|
+ * out the call path that was taken.
|
|
+ */
|
|
+ if (__kernel_text_address(addr)) {
|
|
+#ifndef CONFIG_KALLSYMS
|
|
+ if (i % 5 == 0)
|
|
+ printk("\n ");
|
|
+#endif
|
|
+ printk(" [<%08lx>] %pS\n", addr, (void *)addr);
|
|
+ i++;
|
|
+ }
|
|
+ }
|
|
+ printk(KERN_INFO "\n");
|
|
+}
|
|
+
|
|
+int kstack_depth_to_print = 48;
|
|
+void show_stack(struct task_struct *task, unsigned long *stack)
|
|
+{
|
|
+ unsigned long *p;
|
|
+ unsigned long *endstack;
|
|
+ int i;
|
|
+
|
|
+ if (!stack) {
|
|
+ if (task)
|
|
+ stack = (unsigned long *)task->thread.esp0;
|
|
+ else
|
|
+ stack = (unsigned long *)&stack;
|
|
+ }
|
|
+ endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1)
|
|
+ & -THREAD_SIZE);
|
|
+
|
|
+ printk(KERN_INFO "Stack from %08lx:", (unsigned long)stack);
|
|
+ p = stack;
|
|
+ for (i = 0; i < kstack_depth_to_print; i++) {
|
|
+ if (p + 1 > endstack)
|
|
+ break;
|
|
+ if (i % 8 == 0)
|
|
+ printk("\n ");
|
|
+ printk(" %08lx", *p++);
|
|
+ }
|
|
+ printk("\n");
|
|
+ show_trace(stack);
|
|
+}
|
|
+
|
|
+void bad_super_trap(struct frame *fp)
|
|
+{
|
|
+ console_verbose();
|
|
+ if (fp->ptregs.vector < sizeof(vec_names)/sizeof(vec_names[0]))
|
|
+ printk(KERN_WARNING "*** %s *** FORMAT=%X\n",
|
|
+ vec_names[fp->ptregs.vector],
|
|
+ fp->ptregs.format);
|
|
+ else
|
|
+ printk(KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
|
|
+ fp->ptregs.vector,
|
|
+ fp->ptregs.format);
|
|
+ printk(KERN_WARNING "Current process id is %d\n", current->pid);
|
|
+ die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
|
|
+}
|
|
+
|
|
+asmlinkage void trap_c(struct frame *fp)
|
|
+{
|
|
+ int sig;
|
|
+ siginfo_t info;
|
|
+
|
|
+ if (fp->ptregs.sr & PS_S) {
|
|
+ if (fp->ptregs.vector == VEC_TRACE) {
|
|
+ /* traced a trapping instruction */
|
|
+ current->ptrace |= PT_DTRACE;
|
|
+ } else
|
|
+ bad_super_trap(fp);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* send the appropriate signal to the user program */
|
|
+ switch (fp->ptregs.vector) {
|
|
+ case VEC_ADDRERR:
|
|
+ info.si_code = BUS_ADRALN;
|
|
+ sig = SIGBUS;
|
|
+ break;
|
|
+ case VEC_ILLEGAL:
|
|
+ case VEC_LINE10:
|
|
+ case VEC_LINE11:
|
|
+ info.si_code = ILL_ILLOPC;
|
|
+ sig = SIGILL;
|
|
+ break;
|
|
+ case VEC_PRIV:
|
|
+ info.si_code = ILL_PRVOPC;
|
|
+ sig = SIGILL;
|
|
+ break;
|
|
+ case VEC_COPROC:
|
|
+ info.si_code = ILL_COPROC;
|
|
+ sig = SIGILL;
|
|
+ break;
|
|
+ case VEC_TRAP1: /* gdbserver breakpoint */
|
|
+ fp->ptregs.pc -= 2;
|
|
+ info.si_code = TRAP_TRACE;
|
|
+ sig = SIGTRAP;
|
|
+ break;
|
|
+ case VEC_TRAP2:
|
|
+ case VEC_TRAP3:
|
|
+ case VEC_TRAP4:
|
|
+ case VEC_TRAP5:
|
|
+ case VEC_TRAP6:
|
|
+ case VEC_TRAP7:
|
|
+ case VEC_TRAP8:
|
|
+ case VEC_TRAP9:
|
|
+ case VEC_TRAP10:
|
|
+ case VEC_TRAP11:
|
|
+ case VEC_TRAP12:
|
|
+ case VEC_TRAP13:
|
|
+ case VEC_TRAP14:
|
|
+ info.si_code = ILL_ILLTRP;
|
|
+ sig = SIGILL;
|
|
+ break;
|
|
+ case VEC_FPBRUC:
|
|
+ case VEC_FPOE:
|
|
+ case VEC_FPNAN:
|
|
+ info.si_code = FPE_FLTINV;
|
|
+ sig = SIGFPE;
|
|
+ break;
|
|
+ case VEC_FPIR:
|
|
+ info.si_code = FPE_FLTRES;
|
|
+ sig = SIGFPE;
|
|
+ break;
|
|
+ case VEC_FPDIVZ:
|
|
+ info.si_code = FPE_FLTDIV;
|
|
+ sig = SIGFPE;
|
|
+ break;
|
|
+ case VEC_FPUNDER:
|
|
+ info.si_code = FPE_FLTUND;
|
|
+ sig = SIGFPE;
|
|
+ break;
|
|
+ case VEC_FPOVER:
|
|
+ info.si_code = FPE_FLTOVF;
|
|
+ sig = SIGFPE;
|
|
+ break;
|
|
+ case VEC_ZERODIV:
|
|
+ info.si_code = FPE_INTDIV;
|
|
+ sig = SIGFPE;
|
|
+ break;
|
|
+ case VEC_CHK:
|
|
+ case VEC_TRAP:
|
|
+ info.si_code = FPE_INTOVF;
|
|
+ sig = SIGFPE;
|
|
+ break;
|
|
+ case VEC_TRACE: /* ptrace single step */
|
|
+ info.si_code = TRAP_TRACE;
|
|
+ sig = SIGTRAP;
|
|
+ break;
|
|
+ case VEC_TRAP15: /* breakpoint */
|
|
+ info.si_code = TRAP_BRKPT;
|
|
+ sig = SIGTRAP;
|
|
+ break;
|
|
+ default:
|
|
+ info.si_code = ILL_ILLOPC;
|
|
+ sig = SIGILL;
|
|
+ break;
|
|
+ }
|
|
+ info.si_signo = sig;
|
|
+ info.si_errno = 0;
|
|
+ switch (fp->ptregs.format) {
|
|
+ default:
|
|
+ info.si_addr = (void *) fp->ptregs.pc;
|
|
+ break;
|
|
+ case 2:
|
|
+ info.si_addr = (void *) fp->un.fmt2.iaddr;
|
|
+ break;
|
|
+ case 7:
|
|
+ info.si_addr = (void *) fp->un.fmt7.effaddr;
|
|
+ break;
|
|
+ case 9:
|
|
+ info.si_addr = (void *) fp->un.fmt9.iaddr;
|
|
+ break;
|
|
+ case 10:
|
|
+ info.si_addr = (void *) fp->un.fmta.daddr;
|
|
+ break;
|
|
+ case 11:
|
|
+ info.si_addr = (void *) fp->un.fmtb.daddr;
|
|
+ break;
|
|
+ }
|
|
+ force_sig_info(sig, &info, current);
|
|
+}
|
|
+
|
|
+asmlinkage void set_esp0(unsigned long ssp)
|
|
+{
|
|
+ current->thread.esp0 = ssp;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * The architecture-independent backtrace generator
|
|
+ */
|
|
+void dump_stack(void)
|
|
+{
|
|
+ unsigned long stack;
|
|
+
|
|
+ show_stack(current, &stack);
|
|
+}
|
|
+EXPORT_SYMBOL(dump_stack);
|
|
+
|
|
+#ifdef CONFIG_M68KFPU_EMU
|
|
+asmlinkage void fpemu_signal(int signal, int code, void *addr)
|
|
+{
|
|
+ siginfo_t info;
|
|
+
|
|
+ info.si_signo = signal;
|
|
+ info.si_errno = 0;
|
|
+ info.si_code = code;
|
|
+ info.si_addr = addr;
|
|
+ force_sig_info(signal, &info, current);
|
|
+}
|
|
+#endif
|
|
--- a/arch/m68k/include/asm/atomic.h
|
|
+++ b/arch/m68k/include/asm/atomic.h
|
|
@@ -1,3 +1,11 @@
|
|
+/*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
#ifndef __ARCH_M68K_ATOMIC__
|
|
#define __ARCH_M68K_ATOMIC__
|
|
|
|
@@ -30,12 +38,20 @@
|
|
|
|
static inline void atomic_add(int i, atomic_t *v)
|
|
{
|
|
- __asm__ __volatile__("addl %1,%0" : "+m" (*v) : ASM_DI (i));
|
|
+#ifndef CONFIG_COLDFIRE
|
|
+ __asm__ __volatile__("addl %1,%0" : "+m" (*v) : ASM_DI(i));
|
|
+#else
|
|
+ __asm__ __volatile__("addl %1,%0" : "=m" (*v) : ASM_DI(i), "m" (*v));
|
|
+#endif
|
|
}
|
|
|
|
static inline void atomic_sub(int i, atomic_t *v)
|
|
{
|
|
- __asm__ __volatile__("subl %1,%0" : "+m" (*v) : ASM_DI (i));
|
|
+#ifndef CONFIG_COLDFIRE
|
|
+ __asm__ __volatile__("subl %1,%0" : "+m" (*v) : ASM_DI(i));
|
|
+#else
|
|
+ __asm__ __volatile__("subl %1,%0" : "=m" (*v) : ASM_DI(i), "m" (*v));
|
|
+#endif
|
|
}
|
|
|
|
static inline void atomic_inc(atomic_t *v)
|
|
@@ -55,6 +71,14 @@ static inline int atomic_dec_and_test(at
|
|
return c != 0;
|
|
}
|
|
|
|
+static inline int atomic_dec_and_test_lt(volatile atomic_t *v)
|
|
+{
|
|
+ char c;
|
|
+ __asm__ __volatile__("subql #1,%1; slt %0" : "=d" (c), "=m" (*v)
|
|
+ : "m" (*v));
|
|
+ return c != 0 ;
|
|
+}
|
|
+
|
|
static inline int atomic_inc_and_test(atomic_t *v)
|
|
{
|
|
char c;
|
|
@@ -167,9 +191,14 @@ static inline int atomic_sub_and_test(in
|
|
static inline int atomic_add_negative(int i, atomic_t *v)
|
|
{
|
|
char c;
|
|
+#ifndef CONFIG_COLDFIRE
|
|
__asm__ __volatile__("addl %2,%1; smi %0"
|
|
: "=d" (c), "+m" (*v)
|
|
: "id" (i));
|
|
+#else
|
|
+ __asm__ __volatile__("addl %2,%1; smi %0" : "=d" (c), "=m" (*v)
|
|
+ : "d" (i) , "m" (*v));
|
|
+#endif
|
|
return c != 0;
|
|
}
|
|
|
|
--- a/arch/m68k/include/asm/bitops_mm.h
|
|
+++ b/arch/m68k/include/asm/bitops_mm.h
|
|
@@ -1,12 +1,18 @@
|
|
-#ifndef _M68K_BITOPS_H
|
|
-#define _M68K_BITOPS_H
|
|
/*
|
|
* Copyright 1992, Linus Torvalds.
|
|
*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file COPYING in the main directory of this archive
|
|
* for more details.
|
|
*/
|
|
+#ifndef _M68K_BITOPS_H
|
|
+#define _M68K_BITOPS_H
|
|
+
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#include <asm/cf_bitops.h>
|
|
+#else
|
|
|
|
#ifndef _LINUX_BITOPS_H
|
|
#error only <linux/bitops.h> can be included directly
|
|
@@ -463,4 +469,6 @@ static inline unsigned long generic_find
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
+
|
|
#endif /* _M68K_BITOPS_H */
|
|
--- a/arch/m68k/include/asm/bootinfo.h
|
|
+++ b/arch/m68k/include/asm/bootinfo.h
|
|
@@ -2,6 +2,7 @@
|
|
** asm/bootinfo.h -- Definition of the Linux/m68k boot information structure
|
|
**
|
|
** Copyright 1992 by Greg Harp
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
**
|
|
** This file is subject to the terms and conditions of the GNU General Public
|
|
** License. See the file COPYING in the main directory of this archive
|
|
@@ -24,6 +25,47 @@
|
|
#ifndef _M68K_BOOTINFO_H
|
|
#define _M68K_BOOTINFO_H
|
|
|
|
+#ifndef __ASSEMBLY__
|
|
+/*
|
|
+ * UBoot Support
|
|
+ *
|
|
+ * bd_info structure from uboot1.3.2/arch/m68k/include/asm/u-boot.h
|
|
+ */
|
|
+struct bd_info {
|
|
+ unsigned long bi_memstart; /* start of DRAM memory */
|
|
+ unsigned long bi_memsize; /* size of DRAM memory in bytes */
|
|
+ unsigned long bi_flashstart; /* start of FLASH memory */
|
|
+ unsigned long bi_flashsize; /* size of FLASH memory */
|
|
+ unsigned long bi_flashoffset; /* reserved area for startup monitor */
|
|
+ unsigned long bi_sramstart; /* start of SRAM memory */
|
|
+ unsigned long bi_sramsize; /* size of SRAM memory */
|
|
+ unsigned long bi_mbar_base; /* base of internal registers */
|
|
+ unsigned long bi_bootflags; /* boot / reboot flag (for LynxOS) */
|
|
+ unsigned long bi_boot_params; /* where this board expects params */
|
|
+ unsigned long bi_ip_addr; /* IP Address */
|
|
+ unsigned char bi_enet0addr[6]; /* Ethernet 0 mac address */
|
|
+ unsigned short bi_ethspeed; /* Ethernet speed in Mbps */
|
|
+ unsigned long bi_intfreq; /* Internal Freq, in MHz */
|
|
+ unsigned long bi_busfreq; /* Bus Freq, in MHz */
|
|
+#ifdef UBOOT_EXTRA_CLOCK
|
|
+ unsigned long bi_inpfreq; /* input Freq in MHz */
|
|
+ unsigned long bi_vcofreq; /* vco Freq in MHz */
|
|
+ unsigned long bi_flbfreq; /* Flexbus Freq in MHz */
|
|
+#endif
|
|
+ unsigned long bi_baudrate; /* Console Baudrate */
|
|
+ unsigned char bi_enet1addr[6]; /* eth1 mac address */
|
|
+ unsigned char bi_enet2addr[6]; /* eth2 mac address */
|
|
+ unsigned char bi_enet3addr[6]; /* eth3 mac address */
|
|
+};
|
|
+
|
|
+struct uboot_record {
|
|
+ struct bd_info *bdi;
|
|
+ unsigned long initrd_start;
|
|
+ unsigned long initrd_end;
|
|
+ unsigned long cmd_line_start;
|
|
+ unsigned long cmd_line_stop;
|
|
+};
|
|
+#endif /* __ASSEMBLY__ */
|
|
|
|
/*
|
|
* Bootinfo definitions
|
|
--- a/arch/m68k/include/asm/cacheflush_mm.h
|
|
+++ b/arch/m68k/include/asm/cacheflush_mm.h
|
|
@@ -1,3 +1,11 @@
|
|
+/*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
#ifndef _M68K_CACHEFLUSH_H
|
|
#define _M68K_CACHEFLUSH_H
|
|
|
|
@@ -6,6 +14,10 @@
|
|
/* cache code */
|
|
#define FLUSH_I_AND_D (0x00000808)
|
|
#define FLUSH_I (0x00000008)
|
|
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#include <asm/cf_cacheflush.h>
|
|
+#else /* !CONFIG_COLDFIRE */
|
|
|
|
/*
|
|
* Cache handling functions
|
|
@@ -128,7 +140,6 @@ static inline void __flush_page_to_ram(v
|
|
}
|
|
}
|
|
|
|
-#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
|
|
#define flush_dcache_page(page) __flush_page_to_ram(page_address(page))
|
|
#define flush_dcache_mmap_lock(mapping) do { } while (0)
|
|
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
|
@@ -154,4 +165,5 @@ static inline void copy_from_user_page(s
|
|
memcpy(dst, src, len);
|
|
}
|
|
|
|
+#endif /* !CONFIG_COLDFIRE */
|
|
#endif /* _M68K_CACHEFLUSH_H */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cf-sram.h
|
|
@@ -0,0 +1,21 @@
|
|
+/*
|
|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Author: Lanttor.Guo@freescale.com
|
|
+ *
|
|
+ * Providing on-chip SRAM allocation and free APIs to kernel
|
|
+ *
|
|
+ * 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 CF_SRAM_H
|
|
+#define CF_SRAM_H
|
|
+
|
|
+extern int declare_sram_pool(void *start, size_t size);
|
|
+
|
|
+extern void *sram_alloc(size_t len);
|
|
+extern void sram_free(void *addr, size_t len);
|
|
+
|
|
+#endif
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cf_bitops.h
|
|
@@ -0,0 +1,443 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+#ifndef __CF_BITOPS__
|
|
+#define __CF_BITOPS__
|
|
+
|
|
+#ifndef _LINUX_BITOPS_H
|
|
+#error only <linux/bitops.h> can be included directly
|
|
+#endif
|
|
+
|
|
+#include <linux/compiler.h>
|
|
+
|
|
+#define test_and_set_bit(nr, vaddr) \
|
|
+ (__builtin_constant_p(nr) ? \
|
|
+ __constant_coldfire_test_and_set_bit(nr, vaddr) : \
|
|
+ __generic_coldfire_test_and_set_bit(nr, vaddr))
|
|
+
|
|
+static inline int __constant_coldfire_test_and_set_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ char retval;
|
|
+ volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
|
|
+ __asm__ __volatile__ ("bset %2,(%4); sne %0"
|
|
+ : "=d" (retval), "=m" (*p)
|
|
+ : "di" (nr & 7), "m" (*p), "a" (p));
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+static inline int __generic_coldfire_test_and_set_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ char retval;
|
|
+
|
|
+ __asm__ __volatile__ ("bset %2,%1; sne %0"
|
|
+ : "=d" (retval), "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
|
|
+ : "d" (nr)
|
|
+ : "memory");
|
|
+ return retval;
|
|
+}
|
|
+#define __test_and_set_bit(nr, vaddr) test_and_set_bit(nr, vaddr)
|
|
+
|
|
+#define set_bit(nr, vaddr) \
|
|
+ (__builtin_constant_p(nr) ? \
|
|
+ __constant_coldfire_set_bit(nr, vaddr) : \
|
|
+ __generic_coldfire_set_bit(nr, vaddr))
|
|
+
|
|
+static inline void __constant_coldfire_set_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
|
|
+ __asm__ __volatile__ ("bset %1,(%3)"
|
|
+ : "=m" (*p) : "di" (nr & 7), "m" (*p), "a" (p));
|
|
+}
|
|
+
|
|
+static inline void __generic_coldfire_set_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ __asm__ __volatile__ ("bset %1,%0"
|
|
+ : "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
|
|
+ : "d" (nr)
|
|
+ : "memory");
|
|
+}
|
|
+#define __set_bit(nr, vaddr) set_bit(nr, vaddr)
|
|
+
|
|
+#define test_and_clear_bit(nr, vaddr) \
|
|
+ (__builtin_constant_p(nr) ? \
|
|
+ __constant_coldfire_test_and_clear_bit(nr, vaddr) : \
|
|
+ __generic_coldfire_test_and_clear_bit(nr, vaddr))
|
|
+
|
|
+static inline int __constant_coldfire_test_and_clear_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ char retval;
|
|
+ volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
|
|
+
|
|
+ __asm__ __volatile__ ("bclr %2,(%4); sne %0"
|
|
+ : "=d" (retval), "=m" (*p)
|
|
+ : "id" (nr & 7), "m" (*p), "a" (p));
|
|
+
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+static inline int __generic_coldfire_test_and_clear_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ char retval;
|
|
+
|
|
+ __asm__ __volatile__ ("bclr %2,%1; sne %0"
|
|
+ : "=d" (retval), "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
|
|
+ : "d" (nr & 7)
|
|
+ : "memory");
|
|
+
|
|
+ return retval;
|
|
+}
|
|
+#define __test_and_clear_bit(nr, vaddr) test_and_clear_bit(nr, vaddr)
|
|
+
|
|
+/*
|
|
+ * clear_bit() doesn't provide any barrier for the compiler.
|
|
+ */
|
|
+#define smp_mb__before_clear_bit() barrier()
|
|
+#define smp_mb__after_clear_bit() barrier()
|
|
+
|
|
+#define clear_bit(nr, vaddr) \
|
|
+ (__builtin_constant_p(nr) ? \
|
|
+ __constant_coldfire_clear_bit(nr, vaddr) : \
|
|
+ __generic_coldfire_clear_bit(nr, vaddr))
|
|
+
|
|
+static inline void __constant_coldfire_clear_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
|
|
+ __asm__ __volatile__ ("bclr %1,(%3)"
|
|
+ : "=m" (*p) : "id" (nr & 7), "m" (*p), "a" (p));
|
|
+}
|
|
+
|
|
+static inline void __generic_coldfire_clear_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ __asm__ __volatile__ ("bclr %1,%0"
|
|
+ : "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
|
|
+ : "d" (nr)
|
|
+ : "memory");
|
|
+}
|
|
+#define __clear_bit(nr, vaddr) clear_bit(nr, vaddr)
|
|
+
|
|
+#define test_and_change_bit(nr, vaddr) \
|
|
+ (__builtin_constant_p(nr) ? \
|
|
+ __constant_coldfire_test_and_change_bit(nr, vaddr) : \
|
|
+ __generic_coldfire_test_and_change_bit(nr, vaddr))
|
|
+
|
|
+static inline int __constant_coldfire_test_and_change_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ char retval;
|
|
+ volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
|
|
+
|
|
+ __asm__ __volatile__ ("bchg %2,(%4); sne %0"
|
|
+ : "=d" (retval), "=m" (*p)
|
|
+ : "id" (nr & 7), "m" (*p), "a" (p));
|
|
+
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+static inline int __generic_coldfire_test_and_change_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ char retval;
|
|
+
|
|
+ __asm__ __volatile__ ("bchg %2,%1; sne %0"
|
|
+ : "=d" (retval), "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
|
|
+ : "id" (nr)
|
|
+ : "memory");
|
|
+
|
|
+ return retval;
|
|
+}
|
|
+#define __test_and_change_bit(nr, vaddr) test_and_change_bit(nr, vaddr)
|
|
+#define __change_bit(nr, vaddr) change_bit(nr, vaddr)
|
|
+
|
|
+#define change_bit(nr, vaddr) \
|
|
+ (__builtin_constant_p(nr) ? \
|
|
+ __constant_coldfire_change_bit(nr, vaddr) : \
|
|
+ __generic_coldfire_change_bit(nr, vaddr))
|
|
+
|
|
+static inline void __constant_coldfire_change_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ volatile char *p = &((volatile char *)vaddr)[(nr^31) >> 3];
|
|
+ __asm__ __volatile__ ("bchg %1,(%3)"
|
|
+ : "=m" (*p) : "id" (nr & 7), "m" (*p), "a" (p));
|
|
+}
|
|
+
|
|
+static inline void __generic_coldfire_change_bit(int nr,
|
|
+ volatile void *vaddr)
|
|
+{
|
|
+ __asm__ __volatile__ ("bchg %1,%0"
|
|
+ : "=m" (((volatile char *)vaddr)[(nr^31) >> 3])
|
|
+ : "d" (nr)
|
|
+ : "memory");
|
|
+}
|
|
+
|
|
+static inline int test_bit(int nr, const unsigned long *vaddr)
|
|
+{
|
|
+ return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0;
|
|
+}
|
|
+
|
|
+static inline unsigned long ffz(unsigned long word)
|
|
+{
|
|
+ unsigned long result = 0;
|
|
+
|
|
+ while (word & 1) {
|
|
+ result++;
|
|
+ word >>= 1;
|
|
+ }
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/* find_next_zero_bit() finds the first zero bit in a bit string of length
|
|
+ * 'size' bits, starting the search at bit 'offset'. This is largely based
|
|
+ * on Linus's ALPHA routines.
|
|
+ */
|
|
+static inline unsigned long find_next_zero_bit(void *addr,
|
|
+ unsigned long size, unsigned long offset)
|
|
+{
|
|
+ unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
|
|
+ unsigned long result = offset & ~31UL;
|
|
+ unsigned long tmp;
|
|
+
|
|
+ if (offset >= size)
|
|
+ return size;
|
|
+ size -= result;
|
|
+ offset &= 31UL;
|
|
+ if (offset) {
|
|
+ tmp = *(p++);
|
|
+ tmp |= ~0UL >> (32-offset);
|
|
+ if (size < 32)
|
|
+ goto found_first;
|
|
+ if (~tmp)
|
|
+ goto found_middle;
|
|
+ size -= 32;
|
|
+ result += 32;
|
|
+ }
|
|
+ while (size & ~31UL) {
|
|
+ tmp = *(p++);
|
|
+ if (~tmp)
|
|
+ goto found_middle;
|
|
+ result += 32;
|
|
+ size -= 32;
|
|
+ }
|
|
+ if (!size)
|
|
+ return result;
|
|
+ tmp = *p;
|
|
+
|
|
+found_first:
|
|
+ tmp |= ~0UL >> size;
|
|
+found_middle:
|
|
+ return result + ffz(tmp);
|
|
+}
|
|
+
|
|
+#define find_first_zero_bit(addr, size) find_next_zero_bit(((void *)addr), \
|
|
+ (size), 0)
|
|
+
|
|
+/* Ported from included/linux/bitops.h */
|
|
+static inline int ffs(int x)
|
|
+{
|
|
+ int r = 1;
|
|
+
|
|
+ if (!x)
|
|
+ return 0;
|
|
+ if (!(x & 0xffff)) {
|
|
+ x >>= 16;
|
|
+ r += 16;
|
|
+ }
|
|
+ if (!(x & 0xff)) {
|
|
+ x >>= 8;
|
|
+ r += 8;
|
|
+ }
|
|
+ if (!(x & 0xf)) {
|
|
+ x >>= 4;
|
|
+ r += 4;
|
|
+ }
|
|
+ if (!(x & 3)) {
|
|
+ x >>= 2;
|
|
+ r += 2;
|
|
+ }
|
|
+ if (!(x & 1)) {
|
|
+ x >>= 1;
|
|
+ r += 1;
|
|
+ }
|
|
+ return r;
|
|
+}
|
|
+#define __ffs(x) (ffs(x) - 1)
|
|
+
|
|
+/* find_next_bit - find the next set bit in a memory region
|
|
+ * (from asm-ppc/bitops.h)
|
|
+ */
|
|
+static inline unsigned long find_next_bit(const unsigned long *addr,
|
|
+ unsigned long size, unsigned long offset)
|
|
+{
|
|
+ unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
|
|
+ unsigned int result = offset & ~31UL;
|
|
+ unsigned int tmp;
|
|
+
|
|
+ if (offset >= size)
|
|
+ return size;
|
|
+ size -= result;
|
|
+ offset &= 31UL;
|
|
+ if (offset) {
|
|
+ tmp = *p++;
|
|
+ tmp &= ~0UL << offset;
|
|
+ if (size < 32)
|
|
+ goto found_first;
|
|
+ if (tmp)
|
|
+ goto found_middle;
|
|
+ size -= 32;
|
|
+ result += 32;
|
|
+ }
|
|
+ while (size >= 32) {
|
|
+ tmp = *p++;
|
|
+ if (tmp != 0)
|
|
+ goto found_middle;
|
|
+ result += 32;
|
|
+ size -= 32;
|
|
+ }
|
|
+ if (!size)
|
|
+ return result;
|
|
+ tmp = *p;
|
|
+
|
|
+found_first:
|
|
+ tmp &= ~0UL >> (32 - size);
|
|
+ if (tmp == 0UL) /* Are any bits set? */
|
|
+ return result + size; /* Nope. */
|
|
+found_middle:
|
|
+ return result + __ffs(tmp);
|
|
+}
|
|
+
|
|
+#define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
|
|
+
|
|
+#ifdef __KERNEL__
|
|
+
|
|
+/* Ported from include/linux/bitops.h */
|
|
+static inline int fls(int x)
|
|
+{
|
|
+ int r = 32;
|
|
+
|
|
+ if (!x)
|
|
+ return 0;
|
|
+ if (!(x & 0xffff0000u)) {
|
|
+ x <<= 16;
|
|
+ r -= 16;
|
|
+ }
|
|
+ if (!(x & 0xff000000u)) {
|
|
+ x <<= 8;
|
|
+ r -= 8;
|
|
+ }
|
|
+ if (!(x & 0xf0000000u)) {
|
|
+ x <<= 4;
|
|
+ r -= 4;
|
|
+ }
|
|
+ if (!(x & 0xc0000000u)) {
|
|
+ x <<= 2;
|
|
+ r -= 2;
|
|
+ }
|
|
+ if (!(x & 0x80000000u)) {
|
|
+ x <<= 1;
|
|
+ r -= 1;
|
|
+ }
|
|
+ return r;
|
|
+}
|
|
+
|
|
+static inline int __fls(int x)
|
|
+{
|
|
+ return fls(x) - 1;
|
|
+}
|
|
+
|
|
+#include <asm-generic/bitops/fls64.h>
|
|
+#include <asm-generic/bitops/sched.h>
|
|
+#include <asm-generic/bitops/hweight.h>
|
|
+#include <asm-generic/bitops/lock.h>
|
|
+
|
|
+#define minix_find_first_zero_bit(addr, size) find_next_zero_bit((addr), \
|
|
+ (size), 0)
|
|
+#define minix_test_and_set_bit(nr, addr) test_and_set_bit((nr), \
|
|
+ (unsigned long *)(addr))
|
|
+#define minix_set_bit(nr, addr) set_bit((nr), \
|
|
+ (unsigned long *)(addr))
|
|
+#define minix_test_and_clear_bit(nr, addr) test_and_clear_bit((nr), \
|
|
+ (unsigned long *)(addr))
|
|
+
|
|
+static inline int minix_test_bit(int nr, const volatile unsigned long *vaddr)
|
|
+{
|
|
+ int *a = (int *)vaddr;
|
|
+ int mask;
|
|
+
|
|
+ a += nr >> 5;
|
|
+ mask = 1 << (nr & 0x1f);
|
|
+ return ((mask & *a) != 0);
|
|
+}
|
|
+
|
|
+#define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 24, \
|
|
+ (unsigned long *)(addr))
|
|
+#define ext2_set_bit_atomic(lock, nr, addr) test_and_set_bit((nr) ^ 24, \
|
|
+ (unsigned long *)(addr))
|
|
+#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 24, \
|
|
+ (unsigned long *)(addr))
|
|
+#define ext2_clear_bit_atomic(lock, nr, addr) test_and_clear_bit((nr) ^ 24, \
|
|
+ (unsigned long *)(addr))
|
|
+
|
|
+static inline int ext2_test_bit(int nr, const void *vaddr)
|
|
+{
|
|
+ const unsigned char *p = vaddr;
|
|
+ return (p[nr >> 3] & (1U << (nr & 7))) != 0;
|
|
+}
|
|
+
|
|
+static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size)
|
|
+{
|
|
+ const unsigned long *p = vaddr, *addr = vaddr;
|
|
+ int res;
|
|
+
|
|
+ if (!size)
|
|
+ return 0;
|
|
+
|
|
+ size = (size >> 5) + ((size & 31) > 0);
|
|
+ while (*p++ == ~0UL) {
|
|
+ if (--size == 0)
|
|
+ return (p - addr) << 5;
|
|
+ }
|
|
+
|
|
+ --p;
|
|
+ for (res = 0; res < 32; res++)
|
|
+ if (!ext2_test_bit(res, p))
|
|
+ break;
|
|
+ return (p - addr) * 32 + res;
|
|
+}
|
|
+
|
|
+static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size,
|
|
+ unsigned offset)
|
|
+{
|
|
+ const unsigned long *addr = vaddr;
|
|
+ const unsigned long *p = addr + (offset >> 5);
|
|
+ int bit = offset & 31UL, res;
|
|
+
|
|
+ if (offset >= size)
|
|
+ return size;
|
|
+
|
|
+ if (bit) {
|
|
+ /* Look for zero in first longword */
|
|
+ for (res = bit; res < 32; res++)
|
|
+ if (!ext2_test_bit(res, p))
|
|
+ return (p - addr) * 32 + res;
|
|
+ p++;
|
|
+ }
|
|
+ /* No zero yet, search remaining full bytes for a zero */
|
|
+ res = ext2_find_first_zero_bit(p, size - 32 * (p - addr));
|
|
+ return (p - addr) * 32 + res;
|
|
+}
|
|
+
|
|
+#endif /* KERNEL */
|
|
+
|
|
+#endif /* __CF_BITOPS__ */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cf_cacheflush.h
|
|
@@ -0,0 +1,20 @@
|
|
+/*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
+#ifndef M68K_CF_CACHEFLUSH_H
|
|
+#define M68K_CF_CACHEFLUSH_H
|
|
+
|
|
+#ifdef CONFIG_M5445X
|
|
+#include "cf_5445x_cacheflush.h"
|
|
+#elif defined(CONFIG_M5441X)
|
|
+#include "cf_5441x_cacheflush.h"
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+#include "cf_548x_cacheflush.h"
|
|
+#endif
|
|
+
|
|
+#endif /* M68K_CF_CACHEFLUSH_H */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cf_entry.h
|
|
@@ -0,0 +1,153 @@
|
|
+/*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
+#ifndef __CF_M68K_ENTRY_H
|
|
+#define __CF_M68K_ENTRY_H
|
|
+
|
|
+#include <asm/setup.h>
|
|
+#include <asm/page.h>
|
|
+#include <asm/coldfire.h>
|
|
+#include <asm/cfmmu.h>
|
|
+
|
|
+/*
|
|
+ * Stack layout in 'ret_from_exception':
|
|
+ *
|
|
+ * This allows access to the syscall arguments in registers d1-d5
|
|
+ *
|
|
+ * 0(sp) - d1
|
|
+ * 4(sp) - d2
|
|
+ * 8(sp) - d3
|
|
+ * C(sp) - d4
|
|
+ * 10(sp) - d5
|
|
+ * 14(sp) - a0
|
|
+ * 18(sp) - a1
|
|
+ * 1C(sp) - a2
|
|
+ * 20(sp) - d0
|
|
+ * 24(sp) - orig_d0
|
|
+ * 28(sp) - stack adjustment
|
|
+ * 2C(sp) - sr
|
|
+ * 2E(sp) - pc
|
|
+ * 32(sp) - format & vector
|
|
+ * 36(sp) - MMUSR
|
|
+ * 3A(sp) - MMUAR
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * 97/05/14 Andreas: Register %a2 is now set to the current task throughout
|
|
+ * the whole kernel.
|
|
+ */
|
|
+
|
|
+/* the following macro is used when enabling interrupts */
|
|
+/* portable version */
|
|
+#define ALLOWINT (~0x700)
|
|
+#define MAX_NOINT_IPL 0
|
|
+
|
|
+#ifdef __ASSEMBLY__
|
|
+
|
|
+#define curptr a2
|
|
+
|
|
+LFLUSH_I_AND_D = 0x00000808
|
|
+LSIGTRAP = 5
|
|
+
|
|
+/* process bits for task_struct.ptrace */
|
|
+PT_TRACESYS_OFF = 3
|
|
+PT_TRACESYS_BIT = 1
|
|
+PT_PTRACED_OFF = 3
|
|
+PT_PTRACED_BIT = 0
|
|
+PT_DTRACE_OFF = 3
|
|
+PT_DTRACE_BIT = 2
|
|
+
|
|
+#define SAVE_ALL_INT save_all_int
|
|
+#define SAVE_ALL_SYS save_all_sys
|
|
+#define RESTORE_ALL restore_all
|
|
+/*
|
|
+ * This defines the normal kernel pt-regs layout.
|
|
+ *
|
|
+ * regs a3-a6 and d6-d7 are preserved by C code
|
|
+ * the kernel doesn't mess with usp unless it needs to
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * a -1 in the orig_d0 field signifies
|
|
+ * that the stack frame is NOT for syscall
|
|
+ */
|
|
+.macro save_all_int
|
|
+ movel MMUSR, % sp@ -
|
|
+ movel MMUAR, % sp@ -
|
|
+ clrl % sp@ - | stk_adj
|
|
+ pea - 1 : w | orig d0
|
|
+ movel % d0, % sp@ - | d0
|
|
+ subal #(8*4), % sp
|
|
+ moveml % d1-%d5/%a0-%a1/%curptr, % sp@
|
|
+.endm
|
|
+
|
|
+.macro save_all_sys
|
|
+ movel MMUSR, % sp@-
|
|
+ movel MMUAR, % sp@-
|
|
+ clrl % sp@ - | stk_adj
|
|
+ movel % d0, % sp@ - | orig d0
|
|
+ movel % d0, % sp@ - | d0
|
|
+ subal #(8*4), % sp
|
|
+ moveml % d1-%d5/%a0-%a1/%curptr, % sp@
|
|
+.endm
|
|
+
|
|
+.macro restore_all
|
|
+ moveml % sp@, % a0-%a1/%curptr/%d1-%d5
|
|
+ addal #(8*4), % sp
|
|
+ movel % sp@+, % d0 | d0
|
|
+ addql #4, % sp | orig d0
|
|
+ addl % sp@+, % sp | stk_adj
|
|
+ addql #8, % sp | MMUAR & MMUSR
|
|
+ rte
|
|
+.endm
|
|
+
|
|
+#define SWITCH_STACK_SIZE (6*4+4) /* includes return address */
|
|
+
|
|
+#define SAVE_SWITCH_STACK save_switch_stack
|
|
+#define RESTORE_SWITCH_STACK restore_switch_stack
|
|
+#define GET_CURRENT(tmp) get_current tmp
|
|
+
|
|
+.macro save_switch_stack
|
|
+ subal #(6*4), % sp
|
|
+ moveml % a3-%a6/%d6-%d7, % sp@
|
|
+.endm
|
|
+
|
|
+.macro restore_switch_stack
|
|
+ moveml % sp@, % a3-%a6/%d6-%d7
|
|
+ addal #(6*4), % sp
|
|
+.endm
|
|
+
|
|
+.macro get_current reg = % d0
|
|
+ movel % sp, \reg
|
|
+ andl #-THREAD_SIZE, \reg
|
|
+ movel \reg, % curptr
|
|
+ movel % curptr@, % curptr
|
|
+.endm
|
|
+
|
|
+#else /* C source */
|
|
+
|
|
+#define STR(X) STR1(X)
|
|
+#define STR1(X) #X
|
|
+
|
|
+#define PT_OFF_ORIG_D0 0x24
|
|
+#define PT_OFF_FORMATVEC 0x32
|
|
+#define PT_OFF_SR 0x2C
|
|
+#define SAVE_ALL_INT \
|
|
+ "clrl %%sp@-;" /* stk_adj */ \
|
|
+ "pea -1:w;" /* orig d0 = -1 */ \
|
|
+ "movel %%d0,%%sp@-;" /* d0 */ \
|
|
+ "subal #(8*4),%sp" \
|
|
+ "moveml %%d1-%%d5/%%a0-%%a2,%%sp@"
|
|
+#define GET_CURRENT(tmp) \
|
|
+ "movel %%sp,"#tmp"\n\t" \
|
|
+ "andw #-"STR(THREAD_SIZE)","#tmp"\n\t" \
|
|
+ "movel "#tmp",%%a2\n\t"
|
|
+
|
|
+#endif
|
|
+
|
|
+#endif /* __CF_M68K_ENTRY_H */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cf_io.h
|
|
@@ -0,0 +1,185 @@
|
|
+/*
|
|
+ * linux/include/asm-m68k/cf_io.h
|
|
+ *
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * 9/30/08 JKM - Separated Coldfire pieces out from m68k.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
+#ifndef __CF_IO__
|
|
+#define __CF_IO__
|
|
+
|
|
+#ifdef __KERNEL__
|
|
+
|
|
+#include <linux/compiler.h>
|
|
+#include <asm/raw_io.h>
|
|
+#include <asm/virtconvert.h>
|
|
+
|
|
+#include <asm-generic/iomap.h>
|
|
+
|
|
+#define readb_relaxed(addr) readb(addr)
|
|
+#define readw_relaxed(addr) readw(addr)
|
|
+#define readl_relaxed(addr) readl(addr)
|
|
+
|
|
+#ifdef CONFIG_PCI
|
|
+
|
|
+/*
|
|
+ * IO space in Coldfire
|
|
+ */
|
|
+#define inb_p inb
|
|
+#define inw_p inw
|
|
+#define inl_p inl
|
|
+#define outb_p outb
|
|
+#define outw_p outw
|
|
+#define outl_p outl
|
|
+
|
|
+#ifndef CONFIG_COLDFIRE
|
|
+#define inb(port) in_8(port)
|
|
+#define outb(val, port) out_8((port), (val))
|
|
+#define inw(port) in_le16(port)
|
|
+#define outw(val, port) out_le16((port), (val))
|
|
+#define inl(port) in_le32(port)
|
|
+#define outl(val, port) out_le32((port), (val))
|
|
+#define insb(port, buf, nr) \
|
|
+ raw_insb((u8 *)(port), (u8 *)(buf), (nr))
|
|
+#define outsb(port, buf, nr) \
|
|
+ raw_outsb((u8 *)(port), (u8 *)(buf), (nr))
|
|
+#define insw(port, buf, nr) \
|
|
+ raw_insw_swapw((u16 *)(port), (u16 *)(buf), (nr))
|
|
+#define outsw(port, buf, nr) \
|
|
+ raw_outsw_swapw((u16 *)(port), (u16 *)(buf), (nr))
|
|
+#define insl(port, buf, nr) \
|
|
+ raw_insw_swapw((u16 *)(port), (u16 *)(buf), (nr)<<1)
|
|
+#define outsl(port, buf, nr) \
|
|
+ raw_outsw_swapw((u16 *)(port), (u16 *)(buf), (nr)<<1)
|
|
+#else
|
|
+#define inb(port) pci_inb(port)
|
|
+#define outb(val, port) pci_outb((val), (port))
|
|
+#define inw(port) pci_inw(port)
|
|
+#define outw(val, port) pci_outw((val), (port))
|
|
+#define insb(a, b, c) \
|
|
+ pci_insb((volatile unsigned char *)a, (unsigned char *)b, c)
|
|
+#define insw(a, b, c) \
|
|
+ pci_insw((volatile unsigned short *)a, (unsigned short *)b, c)
|
|
+#define insl(a, b, c) \
|
|
+ pci_insl((volatile unsigned long *)a, (unsigned long *)b, c)
|
|
+#define outsb(a, b, c) \
|
|
+ pci_outsb((volatile unsigned char *)a, (const unsigned char *)b, c)
|
|
+#define outsw(a, b, c) \
|
|
+ pci_outsw((volatile unsigned short *)a, (const unsigned short *)b, c)
|
|
+#define outsl(a, b, c) \
|
|
+ pci_outsl((volatile unsigned long *)a, (const unsigned long *)b, c)
|
|
+#define inl(port) pci_inl(port)
|
|
+#define outl(val, port) pci_outl((val), (port))
|
|
+#endif
|
|
+
|
|
+#else
|
|
+/* no pci */
|
|
+
|
|
+#define inb(port) in_8(port)
|
|
+#define outb(val, port) out_8((port), (val))
|
|
+#define inw(port) in_le16(port)
|
|
+#define outw(val, port) out_le16((port), (val))
|
|
+#define inl(port) in_le32(port)
|
|
+#define outl(val, port) out_le32((port), (val))
|
|
+#define insb(port, buf, nr) \
|
|
+ raw_insb((u8 *)(port), (u8 *)(buf), (nr))
|
|
+#define outsb(port, buf, nr) \
|
|
+ raw_outsb((u8 *)(port), (u8 *)(buf), (nr))
|
|
+#define insw(port, buf, nr) \
|
|
+ raw_insw_swapw((u16 *)(port), (u16 *)(buf), (nr))
|
|
+#define outsw(port, buf, nr) \
|
|
+ raw_outsw_swapw((u16 *)(port), (u16 *)(buf), (nr))
|
|
+#define insl(port, buf, nr) \
|
|
+ raw_insw_swapw((u16 *)(port), (u16 *)(buf), (nr)<<1)
|
|
+#define outsl(port, buf, nr) \
|
|
+ raw_outsw_swapw((u16 *)(port), (u16 *)(buf), (nr)<<1)
|
|
+
|
|
+#endif /* CONFIG_PCI */
|
|
+
|
|
+#define mmiowb()
|
|
+
|
|
+static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size)
|
|
+{
|
|
+ return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
|
|
+}
|
|
+static inline void __iomem *ioremap_nocache(unsigned long physaddr,
|
|
+ unsigned long size)
|
|
+{
|
|
+ return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
|
|
+}
|
|
+static inline void __iomem *ioremap_writethrough(unsigned long physaddr,
|
|
+ unsigned long size)
|
|
+{
|
|
+ return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
|
|
+}
|
|
+static inline void __iomem *ioremap_fullcache(unsigned long physaddr,
|
|
+ unsigned long size)
|
|
+{
|
|
+ return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
|
|
+}
|
|
+
|
|
+static inline void memset_io(volatile void __iomem *addr,
|
|
+ unsigned char val, int count)
|
|
+{
|
|
+ __builtin_memset((void __force *) addr, val, count);
|
|
+}
|
|
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
|
|
+ int count)
|
|
+{
|
|
+ __builtin_memcpy(dst, (void __force *) src, count);
|
|
+}
|
|
+static inline void memcpy_toio(volatile void __iomem *dst,
|
|
+ const void *src, int count)
|
|
+{
|
|
+ __builtin_memcpy((void __force *) dst, src, count);
|
|
+}
|
|
+
|
|
+#define IO_SPACE_LIMIT 0xffffffff
|
|
+
|
|
+#endif /* __KERNEL__ */
|
|
+
|
|
+#define __ARCH_HAS_NO_PAGE_ZERO_MAPPED 1
|
|
+
|
|
+/*
|
|
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
|
|
+ * access
|
|
+ */
|
|
+#define xlate_dev_mem_ptr(p) __va(p)
|
|
+
|
|
+/*
|
|
+ * Convert a virtual cached pointer to an uncached pointer
|
|
+ */
|
|
+#define xlate_dev_kmem_ptr(p) p
|
|
+
|
|
+#define __raw_readb(addr) \
|
|
+ ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
|
|
+#define __raw_readw(addr) \
|
|
+ ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; })
|
|
+#define __raw_readl(addr) \
|
|
+ ({ unsigned long __v = (*(volatile unsigned long *) (addr)); __v; })
|
|
+#define __raw_writeb(b, addr) (void)((*(volatile unsigned char *) (addr)) = (b))
|
|
+#define __raw_writew(b, addr) \
|
|
+ (void)((*(volatile unsigned short *) (addr)) = (b))
|
|
+#define __raw_writel(b, addr) (void)((*(volatile unsigned int *) (addr)) = (b))
|
|
+
|
|
+#define memset_io(a, b, c) memset((void *)(a), (b), (c))
|
|
+#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c))
|
|
+#define memcpy_toio(a, b, c) memcpy((void *)(a), (b), (c))
|
|
+
|
|
+#if !defined(readb)
|
|
+#define readb(addr) \
|
|
+ ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
|
|
+#define readw(addr) \
|
|
+ ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; })
|
|
+#define readl(addr) \
|
|
+ ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
|
|
+#define writeb(b, addr) (void)((*(volatile unsigned char *) (addr)) = (b))
|
|
+#define writew(b, addr) (void)((*(volatile unsigned short *) (addr)) = (b))
|
|
+#define writel(b, addr) (void)((*(volatile unsigned int *) (addr)) = (b))
|
|
+#endif /* readb */
|
|
+
|
|
+#endif /* _IO_H */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cf_pgalloc.h
|
|
@@ -0,0 +1,112 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
+#ifndef M68K_CF_PGALLOC_H
|
|
+#define M68K_CF_PGALLOC_H
|
|
+#include <linux/highmem.h>
|
|
+#include <asm/coldfire.h>
|
|
+#include <asm/page.h>
|
|
+#include <asm/cf_tlbflush.h>
|
|
+#include <asm/cf_cacheflush.h>
|
|
+
|
|
+extern inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
|
|
+{
|
|
+ free_page((unsigned long) pte);
|
|
+}
|
|
+
|
|
+extern const char bad_pmd_string[];
|
|
+
|
|
+extern inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
+ unsigned long address)
|
|
+{
|
|
+ unsigned long page = __get_free_page(GFP_KERNEL|__GFP_REPEAT);
|
|
+
|
|
+ if (!page)
|
|
+ return NULL;
|
|
+
|
|
+ memset((void *)page, 0, PAGE_SIZE);
|
|
+ return (pte_t *) (page);
|
|
+}
|
|
+
|
|
+extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
|
|
+{
|
|
+ return (pmd_t *) pgd;
|
|
+}
|
|
+
|
|
+#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); })
|
|
+#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); })
|
|
+
|
|
+#define pte_alloc_one_fast(mm, addr) pte_alloc_one(mm, addr)
|
|
+
|
|
+#define pmd_populate(mm, pmd, page) (pmd_val(*pmd) = \
|
|
+ (unsigned long)(page_address(page)))
|
|
+
|
|
+#define pmd_populate_kernel(mm, pmd, pte) (pmd_val(*pmd) = (unsigned long)(pte))
|
|
+
|
|
+#define pmd_pgtable(pmd) pmd_page(pmd)
|
|
+
|
|
+static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *page,
|
|
+ unsigned long address)
|
|
+{
|
|
+ __free_page(page);
|
|
+}
|
|
+
|
|
+#define __pmd_free_tlb(tlb, pmd, address) do { } while (0)
|
|
+
|
|
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
|
|
+ unsigned long address)
|
|
+{
|
|
+ struct page *page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
|
|
+ pte_t *pte;
|
|
+
|
|
+ if (!page)
|
|
+ return NULL;
|
|
+
|
|
+ pte = kmap(page);
|
|
+ if (pte) {
|
|
+ clear_page(pte);
|
|
+ __flush_page_to_ram(pte);
|
|
+ flush_tlb_kernel_page(pte);
|
|
+ nocache_page(pte);
|
|
+ }
|
|
+ kunmap(page);
|
|
+
|
|
+ return page;
|
|
+}
|
|
+
|
|
+extern inline void pte_free(struct mm_struct *mm, struct page *page)
|
|
+{
|
|
+ __free_page(page);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * In our implementation, each pgd entry contains 1 pmd that is never allocated
|
|
+ * or freed. pgd_present is always 1, so this should never be called. -NL
|
|
+ */
|
|
+#define pmd_free(mm, pmd) BUG()
|
|
+
|
|
+extern inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
+{
|
|
+ free_page((unsigned long) pgd);
|
|
+}
|
|
+
|
|
+extern inline pgd_t *pgd_alloc(struct mm_struct *mm)
|
|
+{
|
|
+ pgd_t *new_pgd;
|
|
+
|
|
+ new_pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_NOWARN);
|
|
+ if (!new_pgd)
|
|
+ return NULL;
|
|
+ memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE);
|
|
+ memset(new_pgd, 0, PAGE_OFFSET >> PGDIR_SHIFT);
|
|
+ return new_pgd;
|
|
+}
|
|
+
|
|
+#define pgd_populate(mm, pmd, pte) BUG()
|
|
+
|
|
+#endif /* M68K_CF_PGALLOC_H */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cf_pgtable.h
|
|
@@ -0,0 +1,364 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
+#ifndef _CF_PGTABLE_H
|
|
+#define _CF_PGTABLE_H
|
|
+
|
|
+#include <asm/cfmmu.h>
|
|
+#include <asm/page.h>
|
|
+
|
|
+#ifndef __ASSEMBLY__
|
|
+#include <asm/virtconvert.h>
|
|
+#include <linux/linkage.h>
|
|
+
|
|
+/* For virtual address to physical address conversion */
|
|
+#define VTOP(addr) __pa(addr)
|
|
+#define PTOV(addr) __va(addr)
|
|
+
|
|
+
|
|
+#endif /* !__ASSEMBLY__ */
|
|
+
|
|
+/* Page protection values within PTE. */
|
|
+
|
|
+/* MMUDR bits, in proper place. */
|
|
+#define CF_PAGE_LOCKED (0x00000002)
|
|
+#define CF_PAGE_EXEC (0x00000004)
|
|
+#define CF_PAGE_WRITABLE (0x00000008)
|
|
+#define CF_PAGE_READABLE (0x00000010)
|
|
+#define CF_PAGE_SYSTEM (0x00000020)
|
|
+#define CF_PAGE_COPYBACK (0x00000040)
|
|
+#define CF_PAGE_NOCACHE (0x00000080)
|
|
+
|
|
+#define CF_CACHEMASK (~0x00000040)
|
|
+#define CF_PAGE_MMUDR_MASK (0x000000fe)
|
|
+
|
|
+#define _PAGE_NOCACHE030 (CF_PAGE_NOCACHE)
|
|
+
|
|
+/* MMUTR bits, need shifting down. */
|
|
+#define CF_PAGE_VALID (0x00000400)
|
|
+#define CF_PAGE_SHARED (0x00000800)
|
|
+
|
|
+#define CF_PAGE_MMUTR_MASK (0x00000c00)
|
|
+#define CF_PAGE_MMUTR_SHIFT (10)
|
|
+#define CF_ASID_MMU_SHIFT (2)
|
|
+
|
|
+/* Fake bits, not implemented in CF, will get masked out before
|
|
+ hitting hardware, and might go away altogether once this port is
|
|
+ complete. */
|
|
+#if PAGE_SHIFT < 13
|
|
+#error COLDFIRE Error: Pages must be at least 8k in size
|
|
+#endif
|
|
+#define CF_PAGE_ACCESSED (0x00001000)
|
|
+#define CF_PAGE_FILE (0x00000200)
|
|
+#define CF_PAGE_DIRTY (0x00000001)
|
|
+
|
|
+#define _PAGE_CACHE040 0x020 /* 68040 cache mode, cachable, copyback */
|
|
+#define _PAGE_NOCACHE_S 0x040 /* 68040 no-cache mode, serialized */
|
|
+#define _PAGE_NOCACHE 0x060 /* 68040 cache mode, non-serialized */
|
|
+#define _PAGE_CACHE040W 0x000 /* 68040 cache mode, cachable, write-through */
|
|
+#define _DESCTYPE_MASK 0x003
|
|
+#define _CACHEMASK040 (~0x060)
|
|
+#define _PAGE_GLOBAL040 0x400 /* 68040 global bit, used for kva descs */
|
|
+
|
|
+
|
|
+/* Externally used page protection values. */
|
|
+#define _PAGE_PRESENT (CF_PAGE_VALID)
|
|
+#define _PAGE_ACCESSED (CF_PAGE_ACCESSED)
|
|
+#define _PAGE_DIRTY (CF_PAGE_DIRTY)
|
|
+#define _PAGE_READWRITE (CF_PAGE_WRITABLE \
|
|
+ | CF_PAGE_READABLE \
|
|
+ | CF_PAGE_SHARED \
|
|
+ | CF_PAGE_SYSTEM)
|
|
+
|
|
+/* Compound page protection values. */
|
|
+#define PAGE_NONE __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED)
|
|
+
|
|
+#define PAGE_SHARED __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_READABLE \
|
|
+ | CF_PAGE_WRITABLE \
|
|
+ | CF_PAGE_ACCESSED)
|
|
+
|
|
+#define PAGE_INIT __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_WRITABLE \
|
|
+ | CF_PAGE_READABLE \
|
|
+ | CF_PAGE_EXEC \
|
|
+ | CF_PAGE_SYSTEM \
|
|
+ | CF_PAGE_SHARED)
|
|
+
|
|
+#define PAGE_KERNEL __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_WRITABLE \
|
|
+ | CF_PAGE_READABLE \
|
|
+ | CF_PAGE_EXEC \
|
|
+ | CF_PAGE_SYSTEM \
|
|
+ | CF_PAGE_SHARED \
|
|
+ | CF_PAGE_ACCESSED)
|
|
+
|
|
+#define PAGE_COPY __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED \
|
|
+ | CF_PAGE_READABLE)
|
|
+
|
|
+/*
|
|
+ * Page protections for initialising protection_map. See mm/mmap.c
|
|
+ * for use. In general, the bit positions are xwr, and P-items are
|
|
+ * private, the S-items are shared.
|
|
+ */
|
|
+
|
|
+#define __P000 PAGE_NONE
|
|
+#define __P100 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED \
|
|
+ | CF_PAGE_EXEC)
|
|
+#define __P010 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_WRITABLE \
|
|
+ | CF_PAGE_ACCESSED)
|
|
+#define __P110 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED \
|
|
+ | CF_PAGE_WRITABLE \
|
|
+ | CF_PAGE_EXEC)
|
|
+#define __P001 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED \
|
|
+ | CF_PAGE_READABLE)
|
|
+#define __P101 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED \
|
|
+ | CF_PAGE_READABLE \
|
|
+ | CF_PAGE_EXEC)
|
|
+#define __P011 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_READABLE \
|
|
+ | CF_PAGE_WRITABLE \
|
|
+ | CF_PAGE_ACCESSED)
|
|
+#define __P111 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED \
|
|
+ | CF_PAGE_WRITABLE \
|
|
+ | CF_PAGE_READABLE \
|
|
+ | CF_PAGE_EXEC)
|
|
+
|
|
+#define __S000 PAGE_NONE
|
|
+#define __S100 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED \
|
|
+ | CF_PAGE_EXEC)
|
|
+#define __S010 PAGE_SHARED
|
|
+#define __S110 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED \
|
|
+ | CF_PAGE_WRITABLE \
|
|
+ | CF_PAGE_EXEC)
|
|
+#define __S001 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED \
|
|
+ | CF_PAGE_READABLE)
|
|
+#define __S101 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED \
|
|
+ | CF_PAGE_READABLE \
|
|
+ | CF_PAGE_EXEC)
|
|
+#define __S011 PAGE_SHARED
|
|
+#define __S111 __pgprot(CF_PAGE_VALID \
|
|
+ | CF_PAGE_ACCESSED \
|
|
+ | CF_PAGE_READABLE \
|
|
+ | CF_PAGE_WRITABLE \
|
|
+ | CF_PAGE_EXEC)
|
|
+
|
|
+#define PTE_MASK PAGE_MASK
|
|
+#define CF_PAGE_CHG_MASK (PTE_MASK | CF_PAGE_ACCESSED | CF_PAGE_DIRTY)
|
|
+
|
|
+#ifndef __ASSEMBLY__
|
|
+
|
|
+/*
|
|
+ * 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))
|
|
+
|
|
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
|
+{
|
|
+ pte_val(pte) = (pte_val(pte) & CF_PAGE_CHG_MASK) | pgprot_val(newprot);
|
|
+ return pte;
|
|
+}
|
|
+
|
|
+#define pmd_set(pmdp, ptep) do {} while (0)
|
|
+
|
|
+static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
|
|
+{
|
|
+ pgd_val(*pgdp) = virt_to_phys(pmdp);
|
|
+}
|
|
+
|
|
+#define __pte_page(pte) \
|
|
+ ((unsigned long) ((pte_val(pte) & CF_PAGE_PGNUM_MASK) + PAGE_OFFSET))
|
|
+#define __pmd_page(pmd) ((unsigned long) (pmd_val(pmd)))
|
|
+
|
|
+extern inline int pte_none(pte_t pte)
|
|
+{
|
|
+ return !pte_val(pte);
|
|
+}
|
|
+extern inline int pte_present(pte_t pte)
|
|
+{
|
|
+ return pte_val(pte) & CF_PAGE_VALID;
|
|
+}
|
|
+extern inline void pte_clear(struct mm_struct *mm, unsigned long addr,
|
|
+ pte_t *ptep)
|
|
+{
|
|
+ pte_val(*ptep) = 0;
|
|
+}
|
|
+
|
|
+#define pte_pagenr(pte) ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT)
|
|
+#define pte_page(pte) virt_to_page(__pte_page(pte))
|
|
+
|
|
+extern inline int pmd_none2(pmd_t *pmd) { return !pmd_val(*pmd); }
|
|
+#define pmd_none(pmd) pmd_none2(&(pmd))
|
|
+extern inline int pmd_bad2(pmd_t *pmd) { return 0; }
|
|
+#define pmd_bad(pmd) pmd_bad2(&(pmd))
|
|
+#define pmd_present(pmd) (!pmd_none2(&(pmd)))
|
|
+extern inline void pmd_clear(pmd_t *pmdp) { pmd_val(*pmdp) = 0; }
|
|
+
|
|
+extern inline int pgd_none(pgd_t pgd) { return 0; }
|
|
+extern inline int pgd_bad(pgd_t pgd) { return 0; }
|
|
+extern inline int pgd_present(pgd_t pgd) { return 1; }
|
|
+extern inline void pgd_clear(pgd_t *pgdp) {}
|
|
+
|
|
+
|
|
+#define pte_ERROR(e) \
|
|
+ printk(KERN_ERR "%s:%d: bad pte %08lx.\n", \
|
|
+ __FILE__, __LINE__, pte_val(e))
|
|
+#define pmd_ERROR(e) \
|
|
+ printk(KERN_ERR "%s:%d: bad pmd %08lx.\n", \
|
|
+ __FILE__, __LINE__, pmd_val(e))
|
|
+#define pgd_ERROR(e) \
|
|
+ printk(KERN_ERR "%s:%d: bad pgd %08lx.\n", \
|
|
+ __FILE__, __LINE__, pgd_val(e))
|
|
+
|
|
+
|
|
+/*
|
|
+ * The following only work if pte_present() is true.
|
|
+ * Undefined behaviour if not...
|
|
+ * [we have the full set here even if they don't change from m68k]
|
|
+ */
|
|
+extern inline int pte_read(pte_t pte) \
|
|
+ { return pte_val(pte) & CF_PAGE_READABLE; }
|
|
+extern inline int pte_write(pte_t pte) \
|
|
+ { return pte_val(pte) & CF_PAGE_WRITABLE; }
|
|
+extern inline int pte_exec(pte_t pte) \
|
|
+ { return pte_val(pte) & CF_PAGE_EXEC; }
|
|
+extern inline int pte_dirty(pte_t pte) \
|
|
+ { return pte_val(pte) & CF_PAGE_DIRTY; }
|
|
+extern inline int pte_young(pte_t pte) \
|
|
+ { return pte_val(pte) & CF_PAGE_ACCESSED; }
|
|
+extern inline int pte_file(pte_t pte) \
|
|
+ { return pte_val(pte) & CF_PAGE_FILE; }
|
|
+static inline int pte_special(pte_t pte) { return 0; }
|
|
+
|
|
+
|
|
+extern inline pte_t pte_wrprotect(pte_t pte) \
|
|
+ { pte_val(pte) &= ~CF_PAGE_WRITABLE; return pte; }
|
|
+extern inline pte_t pte_rdprotect(pte_t pte) \
|
|
+ { pte_val(pte) &= ~CF_PAGE_READABLE; return pte; }
|
|
+extern inline pte_t pte_exprotect(pte_t pte) \
|
|
+ { pte_val(pte) &= ~CF_PAGE_EXEC; return pte; }
|
|
+extern inline pte_t pte_mkclean(pte_t pte) \
|
|
+ { pte_val(pte) &= ~CF_PAGE_DIRTY; return pte; }
|
|
+extern inline pte_t pte_mkold(pte_t pte) \
|
|
+ { pte_val(pte) &= ~CF_PAGE_ACCESSED; return pte; }
|
|
+extern inline pte_t pte_mkwrite(pte_t pte) \
|
|
+ { pte_val(pte) |= CF_PAGE_WRITABLE; return pte; }
|
|
+extern inline pte_t pte_mkread(pte_t pte) \
|
|
+ { pte_val(pte) |= CF_PAGE_READABLE; return pte; }
|
|
+extern inline pte_t pte_mkexec(pte_t pte) \
|
|
+ { pte_val(pte) |= CF_PAGE_EXEC; return pte; }
|
|
+extern inline pte_t pte_mkdirty(pte_t pte) \
|
|
+ { pte_val(pte) |= CF_PAGE_DIRTY; return pte; }
|
|
+extern inline pte_t pte_mkyoung(pte_t pte) \
|
|
+ { pte_val(pte) |= CF_PAGE_ACCESSED; return pte; }
|
|
+extern inline pte_t pte_mknocache(pte_t pte) \
|
|
+ { pte_val(pte) |= 0x80 | (pte_val(pte) & ~0x40); return pte; }
|
|
+extern inline pte_t pte_mkcache(pte_t pte) \
|
|
+ { pte_val(pte) &= ~CF_PAGE_NOCACHE; return pte; }
|
|
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
|
|
+
|
|
+
|
|
+#define swapper_pg_dir kernel_pg_dir
|
|
+extern pgd_t kernel_pg_dir[PTRS_PER_PGD];
|
|
+
|
|
+/* Find an entry in a pagetable directory. */
|
|
+#define pgd_index(address) ((address) >> PGDIR_SHIFT)
|
|
+
|
|
+#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
|
|
+
|
|
+/* Find an entry in a kernel pagetable directory. */
|
|
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
|
|
+
|
|
+/* Find an entry in the second-level pagetable. */
|
|
+extern inline pmd_t *pmd_offset(pgd_t *pgd, unsigned long address)
|
|
+{
|
|
+ return (pmd_t *) pgd;
|
|
+}
|
|
+
|
|
+/* Find an entry in the third-level pagetable. */
|
|
+#define __pte_offset(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
|
|
+#define pte_offset_kernel(dir, address) ((pte_t *) __pmd_page(*(dir)) + \
|
|
+ __pte_offset(address))
|
|
+
|
|
+/* Disable caching for page at given kernel virtual address. */
|
|
+static inline void nocache_page(void *vaddr)
|
|
+{
|
|
+ pgd_t *dir;
|
|
+ pmd_t *pmdp;
|
|
+ pte_t *ptep;
|
|
+ unsigned long addr = (unsigned long)vaddr;
|
|
+
|
|
+ dir = pgd_offset_k(addr);
|
|
+ pmdp = pmd_offset(dir, addr);
|
|
+ ptep = pte_offset_kernel(pmdp, addr);
|
|
+ *ptep = pte_mknocache(*ptep);
|
|
+}
|
|
+
|
|
+/* Enable caching for page at given kernel virtual address. */
|
|
+static inline void cache_page(void *vaddr)
|
|
+{
|
|
+ pgd_t *dir;
|
|
+ pmd_t *pmdp;
|
|
+ pte_t *ptep;
|
|
+ unsigned long addr = (unsigned long)vaddr;
|
|
+
|
|
+ dir = pgd_offset_k(addr);
|
|
+ pmdp = pmd_offset(dir, addr);
|
|
+ ptep = pte_offset_kernel(pmdp, addr);
|
|
+ *ptep = pte_mkcache(*ptep);
|
|
+}
|
|
+
|
|
+#define PTE_FILE_MAX_BITS 21
|
|
+#define PTE_FILE_SHIFT 11
|
|
+
|
|
+static inline unsigned long pte_to_pgoff(pte_t pte)
|
|
+{
|
|
+ return pte_val(pte) >> PTE_FILE_SHIFT;
|
|
+}
|
|
+
|
|
+static inline pte_t pgoff_to_pte(unsigned pgoff)
|
|
+{
|
|
+ pte_t pte = __pte((pgoff << PTE_FILE_SHIFT) + CF_PAGE_FILE);
|
|
+ return pte;
|
|
+}
|
|
+
|
|
+/* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */
|
|
+#define __swp_entry(type, offset) ((swp_entry_t) { (type) | \
|
|
+ (offset << PTE_FILE_SHIFT) })
|
|
+#define __swp_type(x) ((x).val & 0xFF)
|
|
+#define __swp_offset(x) ((x).val >> PTE_FILE_SHIFT)
|
|
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
|
|
+#define __swp_entry_to_pte(x) (__pte((x).val))
|
|
+
|
|
+#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
|
|
+
|
|
+#define pte_offset_map(pmdp, address) ((pte_t *)__pmd_page(*pmdp) + \
|
|
+ __pte_offset(address))
|
|
+#define pte_offset_map_nested(pmdp, address) pte_offset_map(pmdp, address)
|
|
+#define pte_unmap(pte) do { } while (0)
|
|
+#define pte_unmap_nested(pte) kunmap(pte)
|
|
+
|
|
+#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
|
|
+#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
|
|
+
|
|
+
|
|
+#endif /* !__ASSEMBLY__ */
|
|
+#endif /* !_CF_PGTABLE_H */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cf_raw_io.h
|
|
@@ -0,0 +1,188 @@
|
|
+/*
|
|
+ * linux/include/asm-m68k/cf_raw_io.h
|
|
+ *
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * 09/30/08 JKM: split Coldfire pieces into separate file
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+#ifndef __CF_RAW_IO__
|
|
+#define __CF_RAW_IO__
|
|
+
|
|
+#ifdef __KERNEL__
|
|
+
|
|
+#include <asm/types.h>
|
|
+
|
|
+/* Values for nocacheflag and cmode */
|
|
+#define IOMAP_FULL_CACHING 0
|
|
+#define IOMAP_NOCACHE_SER 1
|
|
+#define IOMAP_NOCACHE_NONSER 2
|
|
+#define IOMAP_WRITETHROUGH 3
|
|
+
|
|
+extern void iounmap(void __iomem *addr);
|
|
+
|
|
+extern void __iomem *__ioremap(unsigned long physaddr, unsigned long size,
|
|
+ int cacheflag);
|
|
+extern void __iounmap(void *addr, unsigned long size);
|
|
+
|
|
+
|
|
+/* ++roman: The assignments to temp. vars avoid that gcc sometimes generates
|
|
+ * two accesses to memory, which may be undesirable for some devices.
|
|
+ */
|
|
+#define in_8(addr) \
|
|
+ ({ u8 __v = (*(__force volatile u8 *) (addr)); __v; })
|
|
+#define in_be16(addr) \
|
|
+ ({ u16 __v = (*(__force volatile u16 *) (addr)); __v; })
|
|
+#define in_be32(addr) \
|
|
+ ({ u32 __v = (*(__force volatile u32 *) (addr)); __v; })
|
|
+#define in_le16(addr) \
|
|
+ ({ u16 __v = le16_to_cpu(*(__force volatile __le16 *) (addr)); __v; })
|
|
+#define in_le32(addr) \
|
|
+ ({ u32 __v = le32_to_cpu(*(__force volatile __le32 *) (addr)); __v; })
|
|
+
|
|
+#define out_8(addr, b) (void)((*(__force volatile u8 *) (addr)) = (b))
|
|
+#define out_be16(addr, w) (void)((*(__force volatile u16 *) (addr)) = (w))
|
|
+#define out_be32(addr, l) (void)((*(__force volatile u32 *) (addr)) = (l))
|
|
+#define out_le16(addr, w) \
|
|
+ (void)((*(__force volatile __le16 *) (addr)) = cpu_to_le16(w))
|
|
+#define out_le32(addr, l) \
|
|
+ (void)((*(__force volatile __le32 *) (addr)) = cpu_to_le32(l))
|
|
+
|
|
+
|
|
+#ifdef CONFIG_PCI
|
|
+/* pci */
|
|
+unsigned char pci_inb(long addr);
|
|
+unsigned short pci_inw(long addr);
|
|
+unsigned long pci_inl(long addr);
|
|
+
|
|
+void pci_outb(unsigned char val, long addr);
|
|
+void pci_outw(unsigned short val, long addr);
|
|
+void pci_outl(unsigned long val, long addr);
|
|
+
|
|
+void pci_insb(volatile unsigned char *addr,
|
|
+ unsigned char *buf, int len);
|
|
+void pci_insw(volatile unsigned short *addr,
|
|
+ unsigned short *buf, int len);
|
|
+void pci_insl(volatile unsigned long *addr,
|
|
+ unsigned long *buf, int len);
|
|
+
|
|
+void pci_outsb(volatile unsigned char *addr,
|
|
+ const unsigned char *buf, int len);
|
|
+void pci_outsw(volatile unsigned short *addr,
|
|
+ const unsigned short *buf, int len);
|
|
+void pci_outsl(volatile unsigned long *addr,
|
|
+ const unsigned long *buf, int len);
|
|
+
|
|
+unsigned short pci_raw_inw(long addr);
|
|
+unsigned long pci_raw_inl(long addr);
|
|
+void pci_raw_outw(unsigned short val, long addr);
|
|
+void pci_raw_outl(unsigned long val, long addr);
|
|
+
|
|
+#define raw_inb(port) pci_inb((long)((volatile unsigned char *)(port)))
|
|
+#define raw_inw(port) pci_raw_inw((long)((volatile unsigned short *)(port)))
|
|
+#define raw_inl(port) pci_raw_inl((long)((volatile unsigned long *)(port)))
|
|
+
|
|
+#define raw_outb(val, port) \
|
|
+ pci_outb((val), (long)((volatile unsigned char *)(port)))
|
|
+#define raw_outw(val, port) \
|
|
+ pci_raw_outw((val), (long)((volatile unsigned short *)(port)))
|
|
+#define raw_outl(val, port) \
|
|
+ pci_raw_outl((val), (long)((volatile unsigned long *)(port)))
|
|
+
|
|
+#define swap_inw(port) pci_inw((long)((volatile unsigned short *)(port)))
|
|
+#define swap_outw(val, port) \
|
|
+ pci_outw((val), (long)((volatile unsigned short *)(port)))
|
|
+
|
|
+#else
|
|
+/* non-pci */
|
|
+#define raw_inb in_8
|
|
+#define raw_inw in_be16
|
|
+#define raw_inl in_be32
|
|
+
|
|
+#define raw_outb(val, port) out_8((port), (val))
|
|
+#define raw_outw(val, port) out_be16((port), (val))
|
|
+#define raw_outl(val, port) out_be32((port), (val))
|
|
+
|
|
+#define swap_inw(port) in_le16((port))
|
|
+#define swap_outw(val, port) out_le16((port), (val))
|
|
+#endif
|
|
+
|
|
+static inline void raw_insb(volatile u8 __iomem *port,
|
|
+ u8 *buf, unsigned int len)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < len; i++)
|
|
+ *buf++ = in_8(port);
|
|
+}
|
|
+
|
|
+static inline void raw_outsb(volatile u8 __iomem *port, const u8 *buf,
|
|
+ unsigned int len)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < len; i++)
|
|
+ out_8(port, *buf++);
|
|
+}
|
|
+
|
|
+static inline void raw_insw(volatile u16 *port, u16 *buf, unsigned int nr)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < nr; i++)
|
|
+ *buf++ = raw_inw(port);
|
|
+}
|
|
+
|
|
+static inline void raw_outsw(volatile u16 *port, const u16 *buf,
|
|
+ unsigned int nr)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < nr; i++, buf++)
|
|
+ raw_outw(*buf, port);
|
|
+}
|
|
+
|
|
+static inline void raw_insl(volatile u32 *port, u32 *buf, unsigned int nr)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < nr; i++)
|
|
+ *buf++ = raw_inl(port);
|
|
+}
|
|
+
|
|
+static inline void raw_outsl(volatile u32 *port, const u32 *buf,
|
|
+ unsigned int nr)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < nr; i++, buf++)
|
|
+ raw_outl(*buf, port);
|
|
+}
|
|
+
|
|
+static inline void raw_insw_swapw(volatile u16 *port, u16 *buf,
|
|
+ unsigned int nr)
|
|
+{
|
|
+#ifdef UNDEF
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < nr; i++)
|
|
+ *buf++ = in_le16(port);
|
|
+#endif
|
|
+}
|
|
+
|
|
+static inline void raw_outsw_swapw(volatile u16 __iomem *port, const u16 *buf,
|
|
+ unsigned int nr)
|
|
+{
|
|
+#ifdef UNDEF
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < nr; i++, buf++)
|
|
+ out_le16(port, *buf);
|
|
+#endif
|
|
+}
|
|
+
|
|
+#endif /* __KERNEL__ */
|
|
+
|
|
+#endif /* __CF_RAW_IO__ */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cf_tlbflush.h
|
|
@@ -0,0 +1,66 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+#ifndef M68K_CF_TLBFLUSH_H
|
|
+#define M68K_CF_TLBFLUSH_H
|
|
+
|
|
+#include <asm/coldfire.h>
|
|
+
|
|
+/* Flush all userspace mappings. */
|
|
+static inline void flush_tlb_all(void)
|
|
+{
|
|
+ preempt_disable();
|
|
+ *MMUOR = MMUOR_CNL;
|
|
+ preempt_enable();
|
|
+}
|
|
+
|
|
+/* Clear user TLB entries within the context named in mm */
|
|
+static inline void flush_tlb_mm(struct mm_struct *mm)
|
|
+{
|
|
+ preempt_disable();
|
|
+ *MMUOR = MMUOR_CNL;
|
|
+ preempt_enable();
|
|
+}
|
|
+
|
|
+/* Flush a single TLB page. */
|
|
+static inline void flush_tlb_page(struct vm_area_struct *vma,
|
|
+ unsigned long addr)
|
|
+{
|
|
+ preempt_disable();
|
|
+ *MMUOR = MMUOR_CNL;
|
|
+ preempt_enable();
|
|
+}
|
|
+/* Flush a range of pages from TLB. */
|
|
+
|
|
+static inline void flush_tlb_range(struct vm_area_struct *mm,
|
|
+ unsigned long start, unsigned long end)
|
|
+{
|
|
+ preempt_disable();
|
|
+ *MMUOR = MMUOR_CNL;
|
|
+ preempt_enable();
|
|
+}
|
|
+
|
|
+/* Flush kernel page from TLB. */
|
|
+static inline void flush_tlb_kernel_page(void *addr)
|
|
+{
|
|
+ preempt_disable();
|
|
+ *MMUOR = MMUOR_CNL;
|
|
+ preempt_enable();
|
|
+}
|
|
+
|
|
+static inline void flush_tlb_kernel_range(unsigned long start,
|
|
+ unsigned long end)
|
|
+{
|
|
+ flush_tlb_all();
|
|
+}
|
|
+
|
|
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
|
|
+ unsigned long start, unsigned long end)
|
|
+{
|
|
+}
|
|
+
|
|
+#endif /* M68K_CF_TLBFLUSH_H */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cf_uaccess.h
|
|
@@ -0,0 +1,262 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+#ifndef __M68K_CF_UACCESS_H
|
|
+#define __M68K_CF_UACCESS_H
|
|
+
|
|
+/*
|
|
+ * User space memory access functions
|
|
+ */
|
|
+
|
|
+/* The "moves" command is not available in the CF instruction set. */
|
|
+#include <linux/compiler.h>
|
|
+#include <linux/errno.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/sched.h>
|
|
+#include <asm/segment.h>
|
|
+
|
|
+#define VERIFY_READ 0
|
|
+#define VERIFY_WRITE 1
|
|
+
|
|
+/* We let the MMU do all checking */
|
|
+#define access_ok(type, addr, size) 1
|
|
+
|
|
+/*
|
|
+ * 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;
|
|
+};
|
|
+
|
|
+extern int __put_user_bad(void);
|
|
+extern int __get_user_bad(void);
|
|
+
|
|
+#define __put_user_asm(res, x, ptr, bwl, reg, err) \
|
|
+asm volatile ("\n" \
|
|
+ "1: move."#bwl" %2,%1\n" \
|
|
+ "2:\n" \
|
|
+ " .section .fixup,\"ax\"\n" \
|
|
+ " .even\n" \
|
|
+ "10: moveq.l %3,%0\n" \
|
|
+ " jra 2b\n" \
|
|
+ " .previous\n" \
|
|
+ "\n" \
|
|
+ " .section __ex_table,\"a\"\n" \
|
|
+ " .align 4\n" \
|
|
+ " .long 1b,10b\n" \
|
|
+ " .long 2b,10b\n" \
|
|
+ " .previous" \
|
|
+ : "+d" (res), "=m" (*(ptr)) \
|
|
+ : #reg(x), "i" (err))
|
|
+
|
|
+/*
|
|
+ * These are the main single-value transfer routines. They automatically
|
|
+ * use the right size if we just have the right pointer type.
|
|
+ */
|
|
+
|
|
+#define __put_user(x, ptr) \
|
|
+({ \
|
|
+ typeof(*(ptr)) __pu_val = (x); \
|
|
+ int __pu_err = 0; \
|
|
+ __chk_user_ptr(ptr); \
|
|
+ switch (sizeof(*(ptr))) { \
|
|
+ case 1: \
|
|
+ __put_user_asm(__pu_err, __pu_val, ptr, b, d, -EFAULT); \
|
|
+ break; \
|
|
+ case 2: \
|
|
+ __put_user_asm(__pu_err, __pu_val, ptr, w, d, -EFAULT); \
|
|
+ break; \
|
|
+ case 4: \
|
|
+ __put_user_asm(__pu_err, __pu_val, ptr, l, r, -EFAULT); \
|
|
+ break; \
|
|
+ case 8: \
|
|
+ { \
|
|
+ const void __user *__pu_ptr = (ptr); \
|
|
+ asm volatile ("\n" \
|
|
+ "1: move.l %2,(%1)+\n" \
|
|
+ "2: move.l %R2,(%1)\n" \
|
|
+ "3:\n" \
|
|
+ " .section .fixup,\"ax\"\n" \
|
|
+ " .even\n" \
|
|
+ "10: movel %3,%0\n" \
|
|
+ " jra 3b\n" \
|
|
+ " .previous\n" \
|
|
+ "\n" \
|
|
+ " .section __ex_table,\"a\"\n" \
|
|
+ " .align 4\n" \
|
|
+ " .long 1b,10b\n" \
|
|
+ " .long 2b,10b\n" \
|
|
+ " .long 3b,10b\n" \
|
|
+ " .previous" \
|
|
+ : "+d" (__pu_err), "+a" (__pu_ptr) \
|
|
+ : "r" (__pu_val), "i" (-EFAULT) \
|
|
+ : "memory"); \
|
|
+ break; \
|
|
+ } \
|
|
+ default: \
|
|
+ __pu_err = __put_user_bad(); \
|
|
+ break; \
|
|
+ } \
|
|
+ __pu_err; \
|
|
+})
|
|
+#define put_user(x, ptr) __put_user(x, ptr)
|
|
+
|
|
+
|
|
+#define __get_user_asm(res, x, ptr, type, bwl, reg, err) ({ \
|
|
+ type __gu_val; \
|
|
+ asm volatile ("\n" \
|
|
+ "1: move."#bwl" %2,%1\n" \
|
|
+ "2:\n" \
|
|
+ " .section .fixup,\"ax\"\n" \
|
|
+ " .even\n" \
|
|
+ "10: move.l %3,%0\n" \
|
|
+ " subl %1,%1\n" \
|
|
+ " jra 2b\n" \
|
|
+ " .previous\n" \
|
|
+ "\n" \
|
|
+ " .section __ex_table,\"a\"\n" \
|
|
+ " .align 4\n" \
|
|
+ " .long 1b,10b\n" \
|
|
+ " .previous" \
|
|
+ : "+d" (res), "=&" #reg(__gu_val) \
|
|
+ : "m" (*(ptr)), "i" (err)); \
|
|
+ (x) = (typeof(*(ptr)))(unsigned long)__gu_val; \
|
|
+})
|
|
+
|
|
+#define __get_user(x, ptr) \
|
|
+({ \
|
|
+ int __gu_err = 0; \
|
|
+ __chk_user_ptr(ptr); \
|
|
+ switch (sizeof(*(ptr))) { \
|
|
+ case 1: \
|
|
+ __get_user_asm(__gu_err, x, ptr, u8, b, d, -EFAULT); \
|
|
+ break; \
|
|
+ case 2: \
|
|
+ __get_user_asm(__gu_err, x, ptr, u16, w, d, -EFAULT); \
|
|
+ break; \
|
|
+ case 4: \
|
|
+ __get_user_asm(__gu_err, x, ptr, u32, l, r, -EFAULT); \
|
|
+ break; \
|
|
+/* case 8: disabled because gcc-4.1 has a broken typeof \
|
|
+ { \
|
|
+ const void *__gu_ptr = (ptr); \
|
|
+ u64 __gu_val; \
|
|
+ asm volatile ("\n" \
|
|
+ "1: move.l (%2)+,%1\n" \
|
|
+ "2: move.l (%2),%R1\n" \
|
|
+ "3:\n" \
|
|
+ " .section .fixup,\"ax\"\n" \
|
|
+ " .even\n" \
|
|
+ "10: move.l %3,%0\n" \
|
|
+ " subl %1,%1\n" \
|
|
+ " subl %R1,%R1\n" \
|
|
+ " jra 3b\n" \
|
|
+ " .previous\n" \
|
|
+ "\n" \
|
|
+ " .section __ex_table,\"a\"\n" \
|
|
+ " .align 4\n" \
|
|
+ " .long 1b,10b\n" \
|
|
+ " .long 2b,10b\n" \
|
|
+ " .previous" \
|
|
+ : "+d" (__gu_err), "=&r" (__gu_val), \
|
|
+ "+a" (__gu_ptr) \
|
|
+ : "i" (-EFAULT) \
|
|
+ : "memory"); \
|
|
+ (x) = (typeof(*(ptr)))__gu_val; \
|
|
+ break; \
|
|
+ } */ \
|
|
+ default : \
|
|
+ __gu_err = __get_user_bad(); \
|
|
+ break; \
|
|
+ } \
|
|
+ __gu_err; \
|
|
+})
|
|
+#define get_user(x, ptr) __get_user(x, ptr)
|
|
+
|
|
+unsigned long __generic_copy_from_user(void *to, const void __user *from,
|
|
+ unsigned long n);
|
|
+unsigned long __generic_copy_to_user(void __user *to, const void *from,
|
|
+ unsigned long n);
|
|
+
|
|
+#define __constant_copy_from_user_asm(res, to, from, tmp, n, s1, s2, s3)\
|
|
+ asm volatile ("\n" \
|
|
+ "1: move."#s1" (%2)+,%3\n" \
|
|
+ " move."#s1" %3,(%1)+\n" \
|
|
+ "2: move."#s2" (%2)+,%3\n" \
|
|
+ " move."#s2" %3,(%1)+\n" \
|
|
+ " .ifnc \""#s3"\",\"\"\n" \
|
|
+ "3: move."#s3" (%2)+,%3\n" \
|
|
+ " move."#s3" %3,(%1)+\n" \
|
|
+ " .endif\n" \
|
|
+ "4:\n" \
|
|
+ " .section __ex_table,\"a\"\n" \
|
|
+ " .align 4\n" \
|
|
+ " .long 1b,10f\n" \
|
|
+ " .long 2b,20f\n" \
|
|
+ " .ifnc \""#s3"\",\"\"\n" \
|
|
+ " .long 3b,30f\n" \
|
|
+ " .endif\n" \
|
|
+ " .previous\n" \
|
|
+ "\n" \
|
|
+ " .section .fixup,\"ax\"\n" \
|
|
+ " .even\n" \
|
|
+ "10: clr."#s1" (%1)+\n" \
|
|
+ "20: clr."#s2" (%1)+\n" \
|
|
+ " .ifnc \""#s3"\",\"\"\n" \
|
|
+ "30: clr."#s3" (%1)+\n" \
|
|
+ " .endif\n" \
|
|
+ " moveq.l #"#n",%0\n" \
|
|
+ " jra 4b\n" \
|
|
+ " .previous\n" \
|
|
+ : "+d" (res), "+&a" (to), "+a" (from), "=&d" (tmp) \
|
|
+ : : "memory")
|
|
+
|
|
+#define __constant_copy_to_user_asm(res, to, from, tmp, n, s1, s2, s3) \
|
|
+ asm volatile ("\n" \
|
|
+ " move."#s1" (%2)+,%3\n" \
|
|
+ "11: move."#s1" %3,(%1)+\n" \
|
|
+ "12: move."#s2" (%2)+,%3\n" \
|
|
+ "21: move."#s2" %3,(%1)+\n" \
|
|
+ "22:\n" \
|
|
+ " .ifnc \""#s3"\",\"\"\n" \
|
|
+ " move."#s3" (%2)+,%3\n" \
|
|
+ "31: move."#s3" %3,(%1)+\n" \
|
|
+ "32:\n" \
|
|
+ " .endif\n" \
|
|
+ "4:\n" \
|
|
+ "\n" \
|
|
+ " .section __ex_table,\"a\"\n" \
|
|
+ " .align 4\n" \
|
|
+ " .long 11b,5f\n" \
|
|
+ " .long 12b,5f\n" \
|
|
+ " .long 21b,5f\n" \
|
|
+ " .long 22b,5f\n" \
|
|
+ " .ifnc \""#s3"\",\"\"\n" \
|
|
+ " .long 31b,5f\n" \
|
|
+ " .long 32b,5f\n" \
|
|
+ " .endif\n" \
|
|
+ " .previous\n" \
|
|
+ "\n" \
|
|
+ " .section .fixup,\"ax\"\n" \
|
|
+ " .even\n" \
|
|
+ "5: moveq.l #"#n",%0\n" \
|
|
+ " jra 4b\n" \
|
|
+ " .previous\n" \
|
|
+ : "+d" (res), "+a" (to), "+a" (from), "=&d" (tmp) \
|
|
+ : : "memory")
|
|
+
|
|
+#endif /* _M68K_CF_UACCESS_H */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cf_virtconvert.h
|
|
@@ -0,0 +1,63 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+#ifndef __CF_VIRTCONVERT__
|
|
+#define __CF_VIRTCONVERT__
|
|
+
|
|
+/*
|
|
+ * Macros used for converting between virtual and physical mappings.
|
|
+ *
|
|
+ * Coldfire Specific
|
|
+ */
|
|
+
|
|
+#ifdef __KERNEL__
|
|
+
|
|
+#include <linux/compiler.h>
|
|
+#include <linux/mmzone.h>
|
|
+#include <asm/setup.h>
|
|
+#include <asm/page.h>
|
|
+
|
|
+/*
|
|
+ * Change virtual addresses to physical addresses and vv.
|
|
+ */
|
|
+static inline unsigned long virt_to_phys(void *address)
|
|
+{
|
|
+ return __pa(address);
|
|
+}
|
|
+
|
|
+static inline void *phys_to_virt(unsigned long address)
|
|
+{
|
|
+ return __va(address);
|
|
+}
|
|
+
|
|
+/* Permanent address of a page. */
|
|
+#ifdef CONFIG_SINGLE_MEMORY_CHUNK
|
|
+#define page_to_phys(page) \
|
|
+ __pa(PAGE_OFFSET + \
|
|
+ (((page) - pg_data_map[0].node_mem_map) << PAGE_SHIFT))
|
|
+#else
|
|
+#define page_to_phys(_page) ({ \
|
|
+ struct page *__page = _page; \
|
|
+ struct pglist_data *pgdat; \
|
|
+ pgdat = pg_data_table[page_to_nid(__page)]; \
|
|
+ page_to_pfn(__page) << PAGE_SHIFT; \
|
|
+})
|
|
+#endif
|
|
+
|
|
+/*
|
|
+ * IO bus memory addresses are 1:1 with the physical address,
|
|
+ */
|
|
+#ifdef CONFIG_PCI
|
|
+#define virt_to_bus(a) (a + PCI_DMA_BASE)
|
|
+#define bus_to_virt(a) (a - PCI_DMA_BASE)
|
|
+#else
|
|
+#define virt_to_bus(a) (a)
|
|
+#define bus_to_virt(a) (a)
|
|
+#endif
|
|
+
|
|
+#endif /* __KERNEL__ */
|
|
+#endif /* __CF_VIRTCONVERT__ */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cfcache.h
|
|
@@ -0,0 +1,146 @@
|
|
+/*
|
|
+ * include/asm-m68k/cfcache.h - Coldfire Cache Controller
|
|
+ *
|
|
+ * Kurt Mahan kmahan@freescale.com
|
|
+ *
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, 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 License as published by the
|
|
+ * Free Software Foundation; either version 2 of the License, or (at your
|
|
+ * option) any later version.
|
|
+ */
|
|
+#ifndef CF_CFCACHE_H
|
|
+#define CF_CFCACHE_H
|
|
+
|
|
+/*
|
|
+ * CACR Cache Control Register
|
|
+ */
|
|
+#define CF_CACR_DEC (0x80000000) /* Data Cache Enable */
|
|
+#define CF_CACR_DW (0x40000000) /* Data default Write-protect */
|
|
+#define CF_CACR_DESB (0x20000000) /* Data Enable Store Buffer */
|
|
+#define CF_CACR_DPI (0x10000000) /* Data Disable CPUSHL Invalidate */
|
|
+#define CF_CACR_DHLCK (0x08000000) /* 1/2 Data Cache Lock Mode */
|
|
+#define CF_CACR_DDCM_00 (0x00000000) /* Cacheable writethrough imprecise */
|
|
+#define CF_CACR_DDCM_01 (0x02000000) /* Cacheable copyback */
|
|
+#define CF_CACR_DDCM_10 (0x04000000) /* Noncacheable precise */
|
|
+#define CF_CACR_DDCM_11 (0x06000000) /* Noncacheable imprecise */
|
|
+#define CF_CACR_DCINVA (0x01000000) /* Data Cache Invalidate All */
|
|
+#define CF_CACR_DDSP (0x00800000) /* Data default supervisor-protect */
|
|
+#define CF_CACR_IVO (0x00100000) /* Invalidate only */
|
|
+#define CF_CACR_BEC (0x00080000) /* Branch Cache Enable */
|
|
+#define CF_CACR_BCINVA (0x00040000) /* Branch Cache Invalidate All */
|
|
+#define CF_CACR_IEC (0x00008000) /* Instruction Cache Enable */
|
|
+#define CF_CACR_SPA (0x00004000) /* Search by Physical Address */
|
|
+#define CF_CACR_DNFB (0x00002000) /* Default cache-inhibited fill buf */
|
|
+#define CF_CACR_IDPI (0x00001000) /* Instr Disable CPUSHL Invalidate */
|
|
+#define CF_CACR_IHLCK (0x00000800) /* 1/2 Instruction Cache Lock Mode */
|
|
+#define CF_CACR_IDCM (0x00000400) /* Noncacheable Instr default mode */
|
|
+#define CF_CACR_ICINVA (0x00000100) /* Instr Cache Invalidate All */
|
|
+#define CF_CACR_IDSP (0x00000080) /* Ins default supervisor-protect */
|
|
+#define CF_CACR_EUSP (0x00000020) /* Switch stacks in user mode */
|
|
+
|
|
+#ifdef CONFIG_M5445X
|
|
+/*
|
|
+ * M5445x Cache Configuration
|
|
+ * - cache line size is 16 bytes
|
|
+ * - cache is 4-way set associative
|
|
+ * - each cache has 256 sets (64k / 16bytes / 4way)
|
|
+ * - I-Cache size is 16KB
|
|
+ * - D-Cache size is 16KB
|
|
+ */
|
|
+#define ICACHE_SIZE 0x4000 /* instruction - 16k */
|
|
+#define DCACHE_SIZE 0x4000 /* data - 16k */
|
|
+
|
|
+#define CACHE_LINE_SIZE 0x0010 /* 16 bytes */
|
|
+#define CACHE_SETS 0x0100 /* 256 sets */
|
|
+#define CACHE_WAYS 0x0004 /* 4 way */
|
|
+
|
|
+#define CACHE_DISABLE_MODE (CF_CACR_DCINVA+ \
|
|
+ CF_CACR_BCINVA+ \
|
|
+ CF_CACR_ICINVA)
|
|
+
|
|
+#ifndef CONFIG_M5445X_DISABLE_CACHE
|
|
+#define CACHE_INITIAL_MODE (CF_CACR_DEC+ \
|
|
+ CF_CACR_BEC+ \
|
|
+ CF_CACR_IEC+ \
|
|
+ CF_CACR_DESB+ \
|
|
+ CF_CACR_EUSP)
|
|
+#else
|
|
+/* cache disabled for testing */
|
|
+#define CACHE_INITIAL_MODE (CF_CACR_EUSP)
|
|
+#endif /* CONFIG_M5445X_DISABLE_CACHE */
|
|
+
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+/*
|
|
+ * * M547x/M548x Cache Configuration
|
|
+ * * - cache line size is 16 bytes
|
|
+ * * - cache is 4-way set associative
|
|
+ * * - each cache has 512 sets (128k / 16bytes / 4way)
|
|
+ * * - I-Cache size is 32KB
|
|
+ * * - D-Cache size is 32KB
|
|
+ * */
|
|
+#define ICACHE_SIZE 0x8000 /* instruction - 32k */
|
|
+#define DCACHE_SIZE 0x8000 /* data - 32k */
|
|
+
|
|
+#define CACHE_LINE_SIZE 0x0010 /* 16 bytes */
|
|
+#define CACHE_SETS 0x0200 /* 512 sets */
|
|
+#define CACHE_WAYS 0x0004 /* 4 way */
|
|
+
|
|
+/* in for the old cpushl caching code */
|
|
+#define _DCACHE_SET_MASK ((DCACHE_SIZE/64-1)<<CACHE_WAYS)
|
|
+#define _ICACHE_SET_MASK ((ICACHE_SIZE/64-1)<<CACHE_WAYS)
|
|
+#define LAST_DCACHE_ADDR _DCACHE_SET_MASK
|
|
+#define LAST_ICACHE_ADDR _ICACHE_SET_MASK
|
|
+
|
|
+#define CACHE_DISABLE_MODE (CF_CACR_DCINVA+ \
|
|
+ CF_CACR_BCINVA+ \
|
|
+ CF_CACR_ICINVA)
|
|
+
|
|
+#define CACHE_INITIAL_MODE (CF_CACR_DEC+ \
|
|
+ CF_CACR_BEC+ \
|
|
+ CF_CACR_IEC+ \
|
|
+ CF_CACR_DESB+ \
|
|
+ CF_CACR_EUSP)
|
|
+#elif defined(CONFIG_M5441X)
|
|
+/*
|
|
+ * M5441x Cache Configuration
|
|
+ * - cache line size is 16 bytes
|
|
+ * - cache is 4-way set associative
|
|
+ * - each cache has 128 sets (8k / 16bytes / 4way)
|
|
+ * - I-Cache size is 8KB
|
|
+ * - D-Cache size is 8KB
|
|
+ */
|
|
+#define ICACHE_SIZE 0x2000 /* instruction - 8k */
|
|
+#define DCACHE_SIZE 0x2000 /* data - 8k */
|
|
+
|
|
+#define CACHE_LINE_SIZE 0x0010 /* 16 bytes */
|
|
+#define CACHE_SETS 0x0080 /* 128 sets */
|
|
+#define CACHE_WAYS 0x0004 /* 4 way */
|
|
+
|
|
+#define CACHE_DISABLE_MODE (CF_CACR_DCINVA+ \
|
|
+ CF_CACR_BCINVA+ \
|
|
+ CF_CACR_ICINVA)
|
|
+
|
|
+#ifndef CONFIG_M5441X_DISABLE_CACHE
|
|
+#define CACHE_INITIAL_MODE (CF_CACR_DEC+ \
|
|
+ CF_CACR_BEC+ \
|
|
+ CF_CACR_IEC+ \
|
|
+ CF_CACR_DESB+ \
|
|
+ CF_CACR_DDCM_01+ \
|
|
+ CF_CACR_EUSP)
|
|
+#else
|
|
+/* cache disabled for testing */
|
|
+#define CACHE_INITIAL_MODE (CF_CACR_EUSP)
|
|
+#endif /* CONFIG_M5441X_DISABLE_CACHE */
|
|
+
|
|
+#endif
|
|
+
|
|
+#ifndef __ASSEMBLY__
|
|
+
|
|
+extern unsigned long shadow_cacr;
|
|
+extern void cacr_set(unsigned long x);
|
|
+
|
|
+#endif /* !__ASSEMBLY__ */
|
|
+
|
|
+#endif /* CF_CACHE_H */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/cfmmu.h
|
|
@@ -0,0 +1,112 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Definitions for Coldfire V4e MMU
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+#include <asm/movs.h>
|
|
+
|
|
+#ifndef __CF_MMU_H__
|
|
+#define __CF_MMU_H__
|
|
+
|
|
+
|
|
+#if defined(CONFIG_M5445X) || defined(CONFIG_M547X_8X)
|
|
+#define MMU_BASE 0xE8000000
|
|
+#elif defined(CONFIG_M5441X)
|
|
+#define MMU_BASE 0xD8000000
|
|
+#endif
|
|
+
|
|
+#define MMUCR (MMU_BASE+0x00)
|
|
+#define MMUCR_ASMN 1
|
|
+#define MMUCR_ASM (1<<MMUCR_ASMN)
|
|
+#define MMUCR_ENN 0
|
|
+#define MMUCR_EN (1<<MMUCR_ENN)
|
|
+
|
|
+#define MMUOR REG16(MMU_BASE+0x04+0x02)
|
|
+#define MMUOR_AAN 16
|
|
+#define MMUOR_AA (0xffff<<MMUOR_AAN)
|
|
+#define MMUOR_STLBN 8
|
|
+#define MMUOR_STLB (1<<MMUOR_STLBN)
|
|
+#define MMUOR_CAN 7
|
|
+#define MMUOR_CA (1<<MMUOR_CAN)
|
|
+#define MMUOR_CNLN 6
|
|
+#define MMUOR_CNL (1<<MMUOR_CNLN)
|
|
+#define MMUOR_CASN 5
|
|
+#define MMUOR_CAS (1<<MMUOR_CASN)
|
|
+#define MMUOR_ITLBN 4
|
|
+#define MMUOR_ITLB (1<<MMUOR_ITLBN)
|
|
+#define MMUOR_ADRN 3
|
|
+#define MMUOR_ADR (1<<MMUOR_ADRN)
|
|
+#define MMUOR_RWN 2
|
|
+#define MMUOR_RW (1<<MMUOR_RWN)
|
|
+#define MMUOR_ACCN 1
|
|
+#define MMUOR_ACC (1<<MMUOR_ACCN)
|
|
+#define MMUOR_UAAN 0
|
|
+#define MMUOR_UAA (1<<MMUOR_UAAN)
|
|
+
|
|
+#define MMUSR REG32(MMU_BASE+0x08)
|
|
+#define MMUSR_SPFN 5
|
|
+#define MMUSR_SPF (1<<MMUSR_SPFN)
|
|
+#define MMUSR_RFN 4
|
|
+#define MMUSR_RF (1<<MMUSR_RFN)
|
|
+#define MMUSR_WFN 3
|
|
+#define MMUSR_WF (1<<MMUSR_WFN)
|
|
+#define MMUSR_HITN 1
|
|
+#define MMUSR_HIT (1<<MMUSR_HITN)
|
|
+
|
|
+#define MMUAR REG32(MMU_BASE+0x10)
|
|
+#define MMUAR_VPN 1
|
|
+#define MMUAR_VP (0xfffffffe)
|
|
+#define MMUAR_SN 0
|
|
+#define MMUAR_S (1<<MMUAR_SN)
|
|
+
|
|
+#define MMUTR REG32(MMU_BASE+0x14)
|
|
+#define MMUTR_VAN 10
|
|
+#define MMUTR_VA (0xfffffc00)
|
|
+#define MMUTR_IDN 2
|
|
+#define MMUTR_ID (0xff<<MMUTR_IDN)
|
|
+#define MMUTR_SGN 1
|
|
+#define MMUTR_SG (1<<MMUTR_SGN)
|
|
+#define MMUTR_VN 0
|
|
+#define MMUTR_V (1<<MMUTR_VN)
|
|
+
|
|
+#define MMUDR REG32(MMU_BASE+0x18)
|
|
+#define MMUDR_PAN 10
|
|
+#define MMUDR_PA (0xfffffc00)
|
|
+#define MMUDR_SZN 8
|
|
+#define MMUDR_SZ_MASK (0x2<<MMUDR_SZN)
|
|
+#define MMUDR_SZ1M (0<<MMUDR_SZN)
|
|
+#define MMUDR_SZ4K (1<<MMUDR_SZN)
|
|
+#define MMUDR_SZ8K (2<<MMUDR_SZN)
|
|
+#define MMUDR_SZ16M (3<<MMUDR_SZN)
|
|
+#define MMUDR_CMN 6
|
|
+#define MMUDR_INC (2<<MMUDR_CMN)
|
|
+#define MMUDR_IC (0<<MMUDR_CMN)
|
|
+#define MMUDR_DWT (0<<MMUDR_CMN)
|
|
+#define MMUDR_DCB (1<<MMUDR_CMN)
|
|
+#define MMUDR_DNCP (2<<MMUDR_CMN)
|
|
+#define MMUDR_DNCIP (3<<MMUDR_CMN)
|
|
+#define MMUDR_SPN 5
|
|
+#define MMUDR_SP (1<<MMUDR_SPN)
|
|
+#define MMUDR_RN 4
|
|
+#define MMUDR_R (1<<MMUDR_RN)
|
|
+#define MMUDR_WN 3
|
|
+#define MMUDR_W (1<<MMUDR_WN)
|
|
+#define MMUDR_XN 2
|
|
+#define MMUDR_X (1<<MMUDR_XN)
|
|
+#define MMUDR_LKN 1
|
|
+#define MMUDR_LK (1<<MMUDR_LKN)
|
|
+
|
|
+
|
|
+#ifndef __ASSEMBLY__
|
|
+#define CF_PMEGS_NUM 256
|
|
+#define CF_INVALID_CONTEXT 255
|
|
+#define CF_PAGE_PGNUM_MASK (PAGE_MASK)
|
|
+
|
|
+extern int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb,
|
|
+ int extension_word);
|
|
+#endif /* __ASSEMBLY__*/
|
|
+
|
|
+#endif /* !__CF_MMU_H__ */
|
|
--- a/arch/m68k/include/asm/coldfire.h
|
|
+++ b/arch/m68k/include/asm/coldfire.h
|
|
@@ -5,6 +5,13 @@
|
|
*
|
|
* (C) Copyright 1999-2006, Greg Ungerer (gerg@snapgear.com)
|
|
* (C) Copyright 2000, Lineo (www.lineo.com)
|
|
+ *
|
|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Right Reserved.
|
|
+ * Shrek Wu b16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*/
|
|
|
|
/****************************************************************************/
|
|
@@ -19,27 +26,78 @@
|
|
* here. Also the peripheral clock (bus clock) divide ratio is set
|
|
* at config time too.
|
|
*/
|
|
+/*FIXME Jason*/
|
|
+#if 0
|
|
#ifdef CONFIG_CLOCK_SET
|
|
#define MCF_CLK CONFIG_CLOCK_FREQ
|
|
#define MCF_BUSCLK (CONFIG_CLOCK_FREQ / CONFIG_CLOCK_DIV)
|
|
#else
|
|
#error "Don't know what your ColdFire CPU clock frequency is??"
|
|
#endif
|
|
+#endif
|
|
+
|
|
+
|
|
+#define MCF_CLK CONFIG_MCFCLK
|
|
+#define MCF_BUSCLK (CONFIG_MCFCLK/2)
|
|
+
|
|
+
|
|
+#if defined(CONFIG_M520x)
|
|
+#define MCF_IPSBAR 0xFC000000
|
|
+#else
|
|
+#define MCF_IPSBAR 0x40000000
|
|
+#endif
|
|
|
|
+#if defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
|
|
+#define MCF_MBAR 0x0
|
|
+/*
|
|
+ * Even though RAMBAR1 macro should be in the 0x8xxxxxxx range,
|
|
+ * here set the CONFIG_SDRAM_BASE value to it to use
|
|
+ * SDRAM memory, not SRAM memory.
|
|
+ */
|
|
+#define MCF_RAMBAR1 (CONFIG_SDRAM_BASE)
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+#define MCF_MBAR 0xF0000000
|
|
+#define MCF_MMUBAR 0xF1000000
|
|
+#define MCF_RAMBAR0 0xF3000000
|
|
+#define MCF_RAMBAR1 0xF3001000
|
|
+#else
|
|
/*
|
|
* Define the processor support peripherals base address.
|
|
* This is generally setup by the boards start up code.
|
|
*/
|
|
#define MCF_MBAR 0x10000000
|
|
#define MCF_MBAR2 0x80000000
|
|
-#if defined(CONFIG_M54xx)
|
|
-#define MCF_IPSBAR MCF_MBAR
|
|
-#elif defined(CONFIG_M520x)
|
|
-#define MCF_IPSBAR 0xFC000000
|
|
-#else
|
|
-#define MCF_IPSBAR 0x40000000
|
|
#endif
|
|
|
|
+#ifdef __ASSEMBLY__
|
|
+#define REG32
|
|
+#define REG16
|
|
+#define REG08
|
|
+#else /* __ASSEMBLY__ */
|
|
+#define REG32(x) ((volatile unsigned long *)(x))
|
|
+#define REG16(x) ((volatile unsigned short *)(x))
|
|
+#define REG08(x) ((volatile unsigned char *)(x))
|
|
+
|
|
+#define MCF_REG32(x) (*(volatile unsigned long *)(MCF_MBAR+(x)))
|
|
+#define MCF_REG16(x) (*(volatile unsigned short *)(MCF_MBAR+(x)))
|
|
+#define MCF_REG08(x) (*(volatile unsigned char *)(MCF_MBAR+(x)))
|
|
+
|
|
+void cacr_set(unsigned long);
|
|
+unsigned long cacr_get(void);
|
|
+
|
|
+#define coldfire_enable_irq0(irq) MCF_INTC0_CIMR = (irq);
|
|
+
|
|
+#define coldfire_enable_irq1(irq) MCF_INTC1_CIMR = (irq);
|
|
+
|
|
+#define coldfire_disable_irq0(irq) MCF_INTC0_SIMR = (irq);
|
|
+
|
|
+#define coldfire_disable_irq1(irq) MCF_INTC1_SIMR = (irq);
|
|
+
|
|
+#define getiprh() MCF_INTC0_IPRH
|
|
+
|
|
+#endif /* __ASSEMBLY__ */
|
|
+
|
|
+
|
|
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
|
|
defined(CONFIG_M520x)
|
|
#undef MCF_MBAR
|
|
--- a/arch/m68k/include/asm/delay_mm.h
|
|
+++ b/arch/m68k/include/asm/delay_mm.h
|
|
@@ -1,18 +1,41 @@
|
|
-#ifndef _M68K_DELAY_H
|
|
-#define _M68K_DELAY_H
|
|
-
|
|
-#include <asm/param.h>
|
|
-
|
|
/*
|
|
* Copyright (C) 1994 Hamish Macdonald
|
|
*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ *
|
|
* Delay routines, using a pre-computed "loops_per_jiffy" value.
|
|
*/
|
|
|
|
+#ifndef _M68K_DELAY_H
|
|
+#define _M68K_DELAY_H
|
|
+
|
|
+#include <asm/param.h>
|
|
+
|
|
static inline void __delay(unsigned long loops)
|
|
{
|
|
+#if defined(CONFIG_COLDFIRE)
|
|
+ /* The coldfire runs this loop at significantly different speeds
|
|
+ * depending upon long word alignment or not. We'll pad it to
|
|
+ * long word alignment which is the faster version.
|
|
+ * The 0x4a8e is of course a 'tstl %fp' instruction. This is better
|
|
+ * than using a NOP (0x4e71) instruction because it executes in one
|
|
+ * cycle not three and doesn't allow for an arbitary delay waiting
|
|
+ * for bus cycles to finish. Also fp/a6 isn't likely to cause a
|
|
+ * stall waiting for the register to become valid if such is added
|
|
+ * to the coldfire at some stage.
|
|
+ */
|
|
+ __asm__ __volatile__ (".balignw 4, 0x4a8e\n\t"
|
|
+ "1: subql #1, %0\n\t"
|
|
+ "jcc 1b"
|
|
+ : "=d" (loops) : "0" (loops));
|
|
+#else
|
|
__asm__ __volatile__ ("1: subql #1,%0; jcc 1b"
|
|
: "=d" (loops) : "0" (loops));
|
|
+#endif
|
|
}
|
|
|
|
extern void __bad_udelay(void);
|
|
@@ -26,12 +49,17 @@ extern void __bad_udelay(void);
|
|
*/
|
|
static inline void __const_udelay(unsigned long xloops)
|
|
{
|
|
+#if defined(CONFIG_COLDFIRE)
|
|
+
|
|
+ __delay(((((unsigned long long) xloops * loops_per_jiffy))>>32)*HZ);
|
|
+#else
|
|
unsigned long tmp;
|
|
|
|
__asm__ ("mulul %2,%0:%1"
|
|
: "=d" (xloops), "=d" (tmp)
|
|
: "d" (xloops), "1" (loops_per_jiffy));
|
|
__delay(xloops * HZ);
|
|
+#endif
|
|
}
|
|
|
|
static inline void __udelay(unsigned long usecs)
|
|
@@ -46,12 +74,16 @@ static inline void __udelay(unsigned lon
|
|
static inline unsigned long muldiv(unsigned long a, unsigned long b,
|
|
unsigned long c)
|
|
{
|
|
+#if defined(CONFIG_COLDFIRE)
|
|
+ return (long)(((unsigned long long)a * b)/c);
|
|
+#else
|
|
unsigned long tmp;
|
|
|
|
__asm__ ("mulul %2,%0:%1; divul %3,%0:%1"
|
|
: "=d" (tmp), "=d" (a)
|
|
: "d" (b), "d" (c), "1" (a));
|
|
return a;
|
|
+#endif
|
|
}
|
|
|
|
#endif /* defined(_M68K_DELAY_H) */
|
|
--- a/arch/m68k/include/asm/div64.h
|
|
+++ b/arch/m68k/include/asm/div64.h
|
|
@@ -1,12 +1,17 @@
|
|
+/*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_DIV64_H
|
|
#define _M68K_DIV64_H
|
|
|
|
-#ifdef CONFIG_MMU
|
|
-
|
|
+#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE)
|
|
#include <linux/types.h>
|
|
|
|
/* n = n / base; return rem; */
|
|
-
|
|
#define do_div(n, base) ({ \
|
|
union { \
|
|
unsigned long n32[2]; \
|
|
--- a/arch/m68k/include/asm/dma.h
|
|
+++ b/arch/m68k/include/asm/dma.h
|
|
@@ -1,7 +1,10 @@
|
|
-#ifndef _M68K_DMA_H
|
|
-#define _M68K_DMA_H 1
|
|
-
|
|
-#ifdef CONFIG_COLDFIRE
|
|
+/*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
/*
|
|
* ColdFire DMA Model:
|
|
* ColdFire DMA supports two forms of DMA: Single and Dual address. Single
|
|
@@ -25,6 +28,11 @@
|
|
* Arthur Shipkowski (art@videon-central.com)
|
|
*/
|
|
|
|
+#ifndef _M68K_DMA_H
|
|
+#define _M68K_DMA_H 1
|
|
+
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+
|
|
#include <asm/coldfire.h>
|
|
#include <asm/mcfsim.h>
|
|
#include <asm/mcfdma.h>
|
|
@@ -479,13 +487,106 @@ static __inline__ int get_dma_residue(un
|
|
|
|
/* it's useless on the m68k, but unfortunately needed by the new
|
|
bootmem allocator (but this should do it for this) */
|
|
+#if defined(CONFIG_M5445X) || defined(CONFIG_M547X_8X)
|
|
+#define MAX_DMA_ADDRESS 0xefffffff
|
|
+#elif defined(CONFIG_M5441X)
|
|
+#define MAX_DMA_ADDRESS 0xdfffffff
|
|
+#else
|
|
#define MAX_DMA_ADDRESS PAGE_OFFSET
|
|
+#endif
|
|
|
|
+#ifndef CONFIG_COLDFIRE
|
|
#define MAX_DMA_CHANNELS 8
|
|
|
|
extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */
|
|
extern void free_dma(unsigned int dmanr); /* release it again */
|
|
|
|
+#else /* not (defined(CONFIG_MCF5474) || defined(CONFIG_MCF5484)
|
|
+ || defined(CONFIG_MCF5475) || defined(CONFIG_MCF5485)) */
|
|
+/************************************************
|
|
+ * Multichannel DMA definitions *
|
|
+ ************************************************/
|
|
+#ifdef CONFIG_MCD_DMA
|
|
+#include <asm/MCD_dma.h>
|
|
+#include <asm/m5485dma.h>
|
|
+
|
|
+struct scatterlist;
|
|
+
|
|
+#define MAX_DMA_CHANNELS NCHANNELS
|
|
+/*
|
|
+ * identifiers for each initiator/requestor
|
|
+ */
|
|
+#define DMA_ALWAYS (0)
|
|
+#define DMA_DSPI_RX (1)
|
|
+#define DMA_DSPI_TX (2)
|
|
+#define DMA_DREQ0 (3)
|
|
+#define DMA_PSC0_RX (4)
|
|
+#define DMA_PSC0_TX (5)
|
|
+#define DMA_USBEP0 (6)
|
|
+#define DMA_USBEP1 (7)
|
|
+#define DMA_USBEP2 (8)
|
|
+#define DMA_USBEP3 (9)
|
|
+#define DMA_PCI_TX (10)
|
|
+#define DMA_PCI_RX (11)
|
|
+#define DMA_PSC1_RX (12)
|
|
+#define DMA_PSC1_TX (13)
|
|
+#define DMA_I2C_RX (14)
|
|
+#define DMA_I2C_TX (15)
|
|
+#define DMA_FEC0_RX (16)
|
|
+#define DMA_FEC0_TX (17)
|
|
+#define DMA_FEC1_RX (18)
|
|
+#define DMA_FEC1_TX (19)
|
|
+#define DMA_DREQ1 (20)
|
|
+#define DMA_CTM0 (21)
|
|
+#define DMA_CTM1 (22)
|
|
+#define DMA_CTM2 (23)
|
|
+#define DMA_CTM3 (24)
|
|
+#define DMA_CTM4 (25)
|
|
+#define DMA_CTM5 (26)
|
|
+#define DMA_CTM6 (27)
|
|
+#define DMA_CTM7 (28)
|
|
+#define DMA_USBEP4 (29)
|
|
+#define DMA_USBEP5 (30)
|
|
+#define DMA_USBEP6 (31)
|
|
+#define DMA_PSC2_RX (32)
|
|
+#define DMA_PSC2_TX (33)
|
|
+#define DMA_PSC3_RX (34)
|
|
+#define DMA_PSC3_TX (35)
|
|
+#define DMA_FEC_RX(x) ((x == 0) ? DMA_FEC0_RX : DMA_FEC1_RX)
|
|
+#define DMA_FEC_TX(x) ((x == 0) ? DMA_FEC0_TX : DMA_FEC1_TX)
|
|
+
|
|
+int dma_set_initiator(int);
|
|
+unsigned int dma_get_initiator(int);
|
|
+void dma_remove_initiator(int);
|
|
+int dma_set_channel(int);
|
|
+int dma_get_channel(int);
|
|
+void dma_remove_channel(int);
|
|
+int dma_set_channel_fec(int requestor);
|
|
+int dma_connect(int channel, int address);
|
|
+int dma_disconnect(int channel);
|
|
+void dma_remove_channel_by_number(int channel);
|
|
+int dma_init(void);
|
|
+#endif
|
|
+
|
|
+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);
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_PCI
|
|
+extern int isa_dma_bridge_buggy;
|
|
+#else
|
|
#define isa_dma_bridge_buggy (0)
|
|
+#endif
|
|
|
|
#endif /* _M68K_DMA_H */
|
|
--- a/arch/m68k/include/asm/elf.h
|
|
+++ b/arch/m68k/include/asm/elf.h
|
|
@@ -1,10 +1,17 @@
|
|
-#ifndef __ASMm68k_ELF_H
|
|
-#define __ASMm68k_ELF_H
|
|
-
|
|
+/*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
/*
|
|
* ELF register definitions..
|
|
*/
|
|
|
|
+#ifndef __ASMm68k_ELF_H
|
|
+#define __ASMm68k_ELF_H
|
|
+
|
|
#include <asm/ptrace.h>
|
|
#include <asm/user.h>
|
|
|
|
@@ -34,6 +41,26 @@
|
|
#define R_68K_GLOB_DAT 20
|
|
#define R_68K_JMP_SLOT 21
|
|
#define R_68K_RELATIVE 22
|
|
+/* TLS static relocations */
|
|
+#define R_68K_TLS_GD32 25
|
|
+#define R_68K_TLS_GD16 26
|
|
+#define R_68K_TLS_GD8 27
|
|
+#define R_68K_TLS_LDM32 28
|
|
+#define R_68K_TLS_LDM16 29
|
|
+#define R_68K_TLS_LDM8 30
|
|
+#define R_68K_TLS_LDO32 31
|
|
+#define R_68K_TLS_LDO16 32
|
|
+#define R_68K_TLS_LDO8 33
|
|
+#define R_68K_TLS_IE32 34
|
|
+#define R_68K_TLS_IE16 35
|
|
+#define R_68K_TLS_IE8 36
|
|
+#define R_68K_TLS_LE32 37
|
|
+#define R_68K_TLS_LE16 38
|
|
+#define R_68K_TLS_LE8 39
|
|
+/* TLS dynamic relocations */
|
|
+#define R_68K_TLS_DTPMOD32 40
|
|
+#define R_68K_TLS_DTPREL32 41
|
|
+#define R_68K_TLS_TPREL32 42
|
|
|
|
typedef unsigned long elf_greg_t;
|
|
|
|
@@ -59,7 +86,7 @@ typedef struct user_m68kfp_struct elf_fp
|
|
is actually used on ASV. */
|
|
#define ELF_PLAT_INIT(_r, load_addr) _r->a1 = 0
|
|
|
|
-#ifndef CONFIG_SUN3
|
|
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
|
|
#define ELF_EXEC_PAGESIZE 4096
|
|
#else
|
|
#define ELF_EXEC_PAGESIZE 8192
|
|
@@ -70,8 +97,10 @@ typedef struct user_m68kfp_struct elf_fp
|
|
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. */
|
|
|
|
-#ifndef CONFIG_SUN3
|
|
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
|
|
#define ELF_ET_DYN_BASE 0xD0000000UL
|
|
+#elif defined(CONFIG_COLDFIRE)
|
|
+#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x10000000)
|
|
#else
|
|
#define ELF_ET_DYN_BASE 0x0D800000UL
|
|
#endif
|
|
@@ -115,4 +144,35 @@ typedef struct user_m68kfp_struct elf_fp
|
|
|
|
#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
|
|
|
|
+/*
|
|
+ * VDSO
|
|
+ */
|
|
+#ifdef CONFIG_VDSO
|
|
+extern unsigned int vdso_enabled;
|
|
+
|
|
+#define VDSO_BASE ((unsigned long)current->mm->context.vdso)
|
|
+#define VDSO_SYM(x) (VDSO_BASE + (unsigned long)(x))
|
|
+
|
|
+#define VDSO_AUX_ENT \
|
|
+ if (vdso_enabled) \
|
|
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE);
|
|
+
|
|
+/* additional pages */
|
|
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
|
|
+
|
|
+struct linux_binprm;
|
|
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
|
|
+ int executable_stack);
|
|
+
|
|
+#else
|
|
+/* no VDSO_AUX_ENT */
|
|
+#define VDSO_AUX_ENT
|
|
+#endif
|
|
+
|
|
+#define ARCH_DLINFO \
|
|
+do { \
|
|
+ /* vdso entry */ \
|
|
+ VDSO_AUX_ENT; \
|
|
+} while (0);
|
|
+
|
|
#endif
|
|
--- a/arch/m68k/include/asm/io_mm.h
|
|
+++ b/arch/m68k/include/asm/io_mm.h
|
|
@@ -1,23 +1,36 @@
|
|
/*
|
|
* linux/include/asm-m68k/io.h
|
|
*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ *
|
|
* 4/1/00 RZ: - rewritten to avoid clashes between ISA/PCI and other
|
|
* IO access
|
|
* - added Q40 support
|
|
* - added skeleton for GG-II and Amiga PCMCIA
|
|
* 2/3/01 RZ: - moved a few more defs into raw_io.h
|
|
*
|
|
- * inX/outX should not be used by any driver unless it does
|
|
- * ISA access. Other drivers should use function defined in raw_io.h
|
|
+ * inX/outX/readX/writeX should not be used by any driver unless it does
|
|
+ * ISA or PCI access. Other drivers should use function defined in raw_io.h
|
|
* or define its own macros on top of these.
|
|
*
|
|
- * inX(),outX() are for ISA I/O
|
|
+ * inX(),outX() are for PCI and ISA I/O
|
|
+ * readX(),writeX() are for PCI memory
|
|
* isa_readX(),isa_writeX() are for ISA memory
|
|
+ *
|
|
+ * moved mem{cpy,set}_*io inside CONFIG_PCI
|
|
*/
|
|
|
|
#ifndef _IO_H
|
|
#define _IO_H
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#include <asm/cf_io.h>
|
|
+#else
|
|
+
|
|
#ifdef __KERNEL__
|
|
|
|
#include <linux/compiler.h>
|
|
@@ -49,6 +62,27 @@
|
|
#define MULTI_ISA 0
|
|
#endif /* Q40 */
|
|
|
|
+/* GG-II Zorro to ISA bridge */
|
|
+#ifdef CONFIG_GG2
|
|
+
|
|
+extern unsigned long gg2_isa_base;
|
|
+#define GG2_ISA_IO_B(ioaddr) \
|
|
+ (gg2_isa_base + 1 + ((unsigned long)(ioaddr) * 4))
|
|
+#define GG2_ISA_IO_W(ioaddr) \
|
|
+ (gg2_isa_base + ((unsigned long)(ioaddr) * 4))
|
|
+#define GG2_ISA_MEM_B(madr) \
|
|
+ (gg2_isa_base + 1 + (((unsigned long)(madr) * 4) & 0xfffff))
|
|
+#define GG2_ISA_MEM_W(madr) \
|
|
+ (gg2_isa_base + (((unsigned long)(madr) * 4) & 0xfffff))
|
|
+
|
|
+#ifndef MULTI_ISA
|
|
+#define MULTI_ISA 0
|
|
+#else
|
|
+#undef MULTI_ISA
|
|
+#define MULTI_ISA 1
|
|
+#endif
|
|
+#endif /* GG2 */
|
|
+
|
|
#ifdef CONFIG_AMIGA_PCMCIA
|
|
#include <asm/amigayle.h>
|
|
|
|
@@ -71,17 +105,22 @@
|
|
#undef MULTI_ISA
|
|
#endif
|
|
|
|
-#define ISA_TYPE_Q40 (1)
|
|
-#define ISA_TYPE_AG (2)
|
|
+#define Q40_ISA (1)
|
|
+#define GG2_ISA (2)
|
|
+#define AG_ISA (3)
|
|
|
|
#if defined(CONFIG_Q40) && !defined(MULTI_ISA)
|
|
-#define ISA_TYPE ISA_TYPE_Q40
|
|
+#define ISA_TYPE Q40_ISA
|
|
#define ISA_SEX 0
|
|
#endif
|
|
#if defined(CONFIG_AMIGA_PCMCIA) && !defined(MULTI_ISA)
|
|
-#define ISA_TYPE ISA_TYPE_AG
|
|
+#define ISA_TYPE AG_ISA
|
|
#define ISA_SEX 1
|
|
#endif
|
|
+#if defined(CONFIG_GG2) && !defined(MULTI_ISA)
|
|
+#define ISA_TYPE GG2_ISA
|
|
+#define ISA_SEX 0
|
|
+#endif
|
|
|
|
#ifdef MULTI_ISA
|
|
extern int isa_type;
|
|
@@ -98,65 +137,72 @@ extern int isa_sex;
|
|
|
|
static inline u8 __iomem *isa_itb(unsigned long addr)
|
|
{
|
|
- switch(ISA_TYPE)
|
|
- {
|
|
+ switch (ISA_TYPE) {
|
|
#ifdef CONFIG_Q40
|
|
- case ISA_TYPE_Q40: return (u8 __iomem *)Q40_ISA_IO_B(addr);
|
|
+ case Q40_ISA: return (u8 __iomem *)Q40_ISA_IO_B(addr);
|
|
+#endif
|
|
+#ifdef CONFIG_GG2
|
|
+ case GG2_ISA: return (u8 __iomem *)GG2_ISA_IO_B(addr);
|
|
#endif
|
|
#ifdef CONFIG_AMIGA_PCMCIA
|
|
- case ISA_TYPE_AG: return (u8 __iomem *)AG_ISA_IO_B(addr);
|
|
+ case AG_ISA: return (u8 __iomem *)AG_ISA_IO_B(addr);
|
|
#endif
|
|
- default: return NULL; /* avoid warnings, just in case */
|
|
- }
|
|
+ default: return NULL; /* avoid warnings, just in case */
|
|
+ }
|
|
}
|
|
static inline u16 __iomem *isa_itw(unsigned long addr)
|
|
{
|
|
- switch(ISA_TYPE)
|
|
- {
|
|
+ switch (ISA_TYPE) {
|
|
#ifdef CONFIG_Q40
|
|
- case ISA_TYPE_Q40: return (u16 __iomem *)Q40_ISA_IO_W(addr);
|
|
+ case Q40_ISA: return (u16 __iomem *)Q40_ISA_IO_W(addr);
|
|
+#endif
|
|
+#ifdef CONFIG_GG2
|
|
+ case GG2_ISA: return (u16 __iomem *)GG2_ISA_IO_W(addr);
|
|
#endif
|
|
#ifdef CONFIG_AMIGA_PCMCIA
|
|
- case ISA_TYPE_AG: return (u16 __iomem *)AG_ISA_IO_W(addr);
|
|
+ case AG_ISA: return (u16 __iomem *)AG_ISA_IO_W(addr);
|
|
#endif
|
|
- default: return NULL; /* avoid warnings, just in case */
|
|
- }
|
|
+ default: return NULL; /* avoid warnings, just in case */
|
|
+ }
|
|
}
|
|
static inline u32 __iomem *isa_itl(unsigned long addr)
|
|
{
|
|
- switch(ISA_TYPE)
|
|
- {
|
|
+ switch (ISA_TYPE) {
|
|
#ifdef CONFIG_AMIGA_PCMCIA
|
|
- case ISA_TYPE_AG: return (u32 __iomem *)AG_ISA_IO_W(addr);
|
|
+ case AG_ISA: return (u32 __iomem *)AG_ISA_IO_W(addr);
|
|
#endif
|
|
- default: return 0; /* avoid warnings, just in case */
|
|
- }
|
|
+ default: return 0; /* avoid warnings, just in case */
|
|
+ }
|
|
}
|
|
static inline u8 __iomem *isa_mtb(unsigned long addr)
|
|
{
|
|
- switch(ISA_TYPE)
|
|
- {
|
|
+ switch (ISA_TYPE) {
|
|
#ifdef CONFIG_Q40
|
|
- case ISA_TYPE_Q40: return (u8 __iomem *)Q40_ISA_MEM_B(addr);
|
|
+ case Q40_ISA: return (u8 __iomem *)Q40_ISA_MEM_B(addr);
|
|
+#endif
|
|
+#ifdef CONFIG_GG2
|
|
+ case GG2_ISA: return (u8 __iomem *)GG2_ISA_MEM_B(addr);
|
|
#endif
|
|
#ifdef CONFIG_AMIGA_PCMCIA
|
|
- case ISA_TYPE_AG: return (u8 __iomem *)addr;
|
|
+ case AG_ISA: return (u8 __iomem *)addr;
|
|
#endif
|
|
- default: return NULL; /* avoid warnings, just in case */
|
|
- }
|
|
+ default: return NULL; /* avoid warnings, just in case */
|
|
+ }
|
|
}
|
|
static inline u16 __iomem *isa_mtw(unsigned long addr)
|
|
{
|
|
- switch(ISA_TYPE)
|
|
- {
|
|
+ switch (ISA_TYPE) {
|
|
#ifdef CONFIG_Q40
|
|
- case ISA_TYPE_Q40: return (u16 __iomem *)Q40_ISA_MEM_W(addr);
|
|
+ case Q40_ISA: return (u16 __iomem *)Q40_ISA_MEM_W(addr);
|
|
+#endif
|
|
+#ifdef CONFIG_GG2
|
|
+ case GG2_ISA: return (u16 __iomem *)GG2_ISA_MEM_W(addr);
|
|
#endif
|
|
#ifdef CONFIG_AMIGA_PCMCIA
|
|
- case ISA_TYPE_AG: return (u16 __iomem *)addr;
|
|
+ case AG_ISA: return (u16 __iomem *)addr;
|
|
#endif
|
|
- default: return NULL; /* avoid warnings, just in case */
|
|
- }
|
|
+ default: return NULL; /* avoid warnings, just in case */
|
|
+ }
|
|
}
|
|
|
|
|
|
@@ -167,27 +213,30 @@ static inline u16 __iomem *isa_mtw(unsig
|
|
#define isa_outw(val,port) (ISA_SEX ? out_be16(isa_itw(port),(val)) : out_le16(isa_itw(port),(val)))
|
|
#define isa_outl(val,port) (ISA_SEX ? out_be32(isa_itl(port),(val)) : out_le32(isa_itl(port),(val)))
|
|
|
|
-#define isa_readb(p) in_8(isa_mtb((unsigned long)(p)))
|
|
-#define isa_readw(p) \
|
|
- (ISA_SEX ? in_be16(isa_mtw((unsigned long)(p))) \
|
|
- : in_le16(isa_mtw((unsigned long)(p))))
|
|
-#define isa_writeb(val,p) out_8(isa_mtb((unsigned long)(p)),(val))
|
|
-#define isa_writew(val,p) \
|
|
- (ISA_SEX ? out_be16(isa_mtw((unsigned long)(p)),(val)) \
|
|
- : out_le16(isa_mtw((unsigned long)(p)),(val)))
|
|
-
|
|
+#define isa_readb(p) in_8(isa_mtb(p))
|
|
+#define isa_readw(p) (ISA_SEX ? in_be16(isa_mtw(p)) : in_le16(isa_mtw(p)))
|
|
+#define isa_writeb(val, p) out_8(isa_mtb(p), (val))
|
|
+#define isa_writew(val, p) \
|
|
+ (ISA_SEX ? out_be16(isa_mtw(p), (val)) : out_le16(isa_mtw(p), (val)))
|
|
static inline void isa_delay(void)
|
|
{
|
|
- switch(ISA_TYPE)
|
|
- {
|
|
+ switch (ISA_TYPE) {
|
|
#ifdef CONFIG_Q40
|
|
- case ISA_TYPE_Q40: isa_outb(0,0x80); break;
|
|
+ case Q40_ISA:
|
|
+ isa_outb(0, 0x80);
|
|
+ break;
|
|
+#endif
|
|
+#ifdef CONFIG_GG2
|
|
+ case GG2_ISA:
|
|
+ break;
|
|
#endif
|
|
#ifdef CONFIG_AMIGA_PCMCIA
|
|
- case ISA_TYPE_AG: break;
|
|
+ case AG_ISA:
|
|
+ break;
|
|
#endif
|
|
- default: break; /* avoid warnings */
|
|
- }
|
|
+ default:
|
|
+ break; /* avoid warnings */
|
|
+ }
|
|
}
|
|
|
|
#define isa_inb_p(p) ({u8 v=isa_inb(p);isa_delay();v;})
|
|
@@ -216,7 +265,10 @@ static inline void isa_delay(void)
|
|
(ISA_SEX ? raw_outsl(isa_itl(port), (u32 *)(buf), (nr)) : \
|
|
raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
|
|
|
|
+#endif /* CONFIG_ISA */
|
|
|
|
+
|
|
+#if defined(CONFIG_ISA) && !defined(CONFIG_PCI)
|
|
#define inb isa_inb
|
|
#define inb_p isa_inb_p
|
|
#define outb isa_outb
|
|
@@ -239,9 +291,80 @@ static inline void isa_delay(void)
|
|
#define readw isa_readw
|
|
#define writeb isa_writeb
|
|
#define writew isa_writew
|
|
+#endif /* CONFIG_ISA */
|
|
+
|
|
+#if defined(CONFIG_PCI)
|
|
+
|
|
+#define readl(addr) in_le32(addr)
|
|
+#define writel(val, addr) out_le32((addr), (val))
|
|
+
|
|
+/* those can be defined for both ISA and PCI - it won't work though */
|
|
+#define readb(addr) in_8(addr)
|
|
+#define readw(addr) in_le16(addr)
|
|
+#define writeb(val, addr) out_8((addr), (val))
|
|
+#define writew(val, addr) out_le16((addr), (val))
|
|
+
|
|
+#define readb_relaxed(addr) readb(addr)
|
|
+#define readw_relaxed(addr) readw(addr)
|
|
+#define readl_relaxed(addr) readl(addr)
|
|
+
|
|
+#ifndef CONFIG_ISA
|
|
+#define inb(port) in_8(port)
|
|
+#define outb(val, port) out_8((port), (val))
|
|
+#define inw(port) in_le16(port)
|
|
+#define outw(val, port) out_le16((port), (val))
|
|
+#define inl(port) in_le32(port)
|
|
+#define outl(val, port) out_le32((port), (val))
|
|
+#define insb(port, buf, nr) \
|
|
+ raw_insb((u8 *)(port), (u8 *)(buf), (nr))
|
|
+#define outsb(port, buf, nr) \
|
|
+ raw_outsb((u8 *)(port), (u8 *)(buf), (nr))
|
|
+#define insw(port, buf, nr) \
|
|
+ raw_insw_swapw((u16 *)(port), (u16 *)(buf), (nr))
|
|
+#define outsw(port, buf, nr) \
|
|
+ raw_outsw_swapw((u16 *)(port), (u16 *)(buf), (nr))
|
|
+#define insl(port, buf, nr) \
|
|
+ raw_insw_swapw((u16 *)(port), (u16 *)(buf), (nr)<<1)
|
|
+#define outsl(port, buf, nr) \
|
|
+ raw_outsw_swapw((u16 *)(port), (u16 *)(buf), (nr)<<1)
|
|
+
|
|
+#define __raw_readb readb
|
|
+#define __raw_readw readw
|
|
+#define __raw_readl readl
|
|
+#define __raw_writeb writeb
|
|
+#define __raw_writew writew
|
|
+#define __raw_writel writel
|
|
|
|
-#else /* CONFIG_ISA */
|
|
+#else
|
|
+/*
|
|
+ * kernel with both ISA and PCI compiled in, those have
|
|
+ * conflicting defs for in/out. Simply consider port < 1024
|
|
+ * ISA and everything else PCI. read,write not defined
|
|
+ * in this case
|
|
+ */
|
|
+#define inb(port) ((port) < 1024 ? isa_inb(port) : in_8(port))
|
|
+#define inb_p(port) ((port) < 1024 ? isa_inb_p(port) : in_8(port))
|
|
+#define inw(port) ((port) < 1024 ? isa_inw(port) : in_le16(port))
|
|
+#define inw_p(port) ((port) < 1024 ? isa_inw_p(port) : in_le16(port))
|
|
+#define inl(port) ((port) < 1024 ? isa_inl(port) : in_le32(port))
|
|
+#define inl_p(port) ((port) < 1024 ? isa_inl_p(port) : in_le32(port))
|
|
+
|
|
+#define outb(val, port) (((port) < 1024) ? isa_outb((val), (port))
|
|
+ : out_8((port), (val)))
|
|
+#define outb_p(val, port) (((port) < 1024) ? isa_outb_p((val), (port))
|
|
+ : out_8((port), (val)))
|
|
+#define outw(val, port) (((port) < 1024) ? isa_outw((val), (port))
|
|
+ : out_le16((port), (val)))
|
|
+#define outw_p(val, port) (((port) < 1024) ? isa_outw_p((val), (port))
|
|
+ : out_le16((port), (val)))
|
|
+#define outl(val, port) (((port) < 1024) ? isa_outl((val), (port))
|
|
+ : out_le32((port), (val)))
|
|
+#define outl_p(val, port) (((port) < 1024) ? isa_outl_p((val), (port))
|
|
+ : out_le32((port), (val)))
|
|
+#endif
|
|
+#endif /* CONFIG_PCI */
|
|
|
|
+#if !defined(CONFIG_ISA) && !defined(CONFIG_PCI)
|
|
/*
|
|
* We need to define dummy functions for GENERIC_IOMAP support.
|
|
*/
|
|
@@ -272,11 +395,11 @@ static inline void isa_delay(void)
|
|
#define writeb(val,addr) out_8((addr),(val))
|
|
#define readw(addr) in_le16(addr)
|
|
#define writew(val,addr) out_le16((addr),(val))
|
|
-
|
|
-#endif /* CONFIG_ISA */
|
|
-
|
|
+#endif
|
|
+#if !defined(CONFIG_PCI)
|
|
#define readl(addr) in_le32(addr)
|
|
#define writel(val,addr) out_le32((addr),(val))
|
|
+#endif
|
|
|
|
#define mmiowb()
|
|
|
|
@@ -333,4 +456,5 @@ static inline void memcpy_toio(volatile
|
|
*/
|
|
#define xlate_dev_kmem_ptr(p) p
|
|
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
#endif /* _IO_H */
|
|
--- a/arch/m68k/include/asm/irq.h
|
|
+++ b/arch/m68k/include/asm/irq.h
|
|
@@ -1,14 +1,20 @@
|
|
-#ifndef _M68K_IRQ_H_
|
|
-#define _M68K_IRQ_H_
|
|
-
|
|
/*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ *
|
|
* This should be the same as the max(NUM_X_SOURCES) for all the
|
|
* different m68k hosts compiled into the kernel.
|
|
* Currently the Atari has 72 and the Amiga 24, but if both are
|
|
* supported in the kernel it is better to make room for 72.
|
|
*/
|
|
+#ifndef _M68K_IRQ_H_
|
|
+#define _M68K_IRQ_H_
|
|
#if defined(CONFIG_COLDFIRE)
|
|
-#define NR_IRQS 256
|
|
+#define SYS_IRQS 256
|
|
+#define NR_IRQS SYS_IRQS
|
|
#elif defined(CONFIG_VME) || defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
|
|
#define NR_IRQS 200
|
|
#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
|
|
--- a/arch/m68k/include/asm/machdep.h
|
|
+++ b/arch/m68k/include/asm/machdep.h
|
|
@@ -1,6 +1,12 @@
|
|
+/*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_MACHDEP_H
|
|
#define _M68K_MACHDEP_H
|
|
-
|
|
#include <linux/seq_file.h>
|
|
#include <linux/interrupt.h>
|
|
|
|
@@ -42,4 +48,11 @@ extern irqreturn_t arch_timer_interrupt(
|
|
extern void config_BSP(char *command, int len);
|
|
extern void do_IRQ(int irq, struct pt_regs *fp);
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+extern void __init config_coldfire(void);
|
|
+extern void __init mmu_context_init(void);
|
|
+extern irq_handler_t mach_default_handler;
|
|
+extern void (*mach_tick)(void);
|
|
+#endif
|
|
+
|
|
#endif /* _M68K_MACHDEP_H */
|
|
--- /dev/null
|
|
+++ b/arch/m68k/include/asm/mcfdspi.h
|
|
@@ -0,0 +1,59 @@
|
|
+/*
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Author: Andrey Butok
|
|
+ *
|
|
+ * This file is based on mcfqspi.h
|
|
+ *
|
|
+ * 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.
|
|
+ *
|
|
+ * 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.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
+ *
|
|
+ ***************************************************************************
|
|
+ * Changes:
|
|
+ * v0.001 25 March 2008 Andrey Butok
|
|
+ * Initial Release - developed on uClinux with 2.6.23 kernel.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#ifndef MCFDSPI_H_
|
|
+#define MCFDSPI_H_
|
|
+
|
|
+struct coldfire_dspi_chip {
|
|
+ u8 mode;
|
|
+ u8 bits_per_word;
|
|
+ u16 void_write_data;
|
|
+ /* Only used in master mode */
|
|
+ u8 dbr; /* Double baud rate */
|
|
+ u8 pbr; /* Baud rate prescaler */
|
|
+ u8 br; /* Baud rate scaler */
|
|
+ u8 pcssck; /* PCS to SCK delay prescaler */
|
|
+ u8 pasc; /* After SCK delay prescaler */
|
|
+ u8 pdt; /* Delay after transfer prescaler */
|
|
+ u8 cssck; /* PCS to SCK delay scaler */
|
|
+ u8 asc; /* After SCK delay scaler */
|
|
+ u8 dt; /* Delay after transfer scaler */
|
|
+};
|
|
+
|
|
+struct coldfire_spi_master {
|
|
+ u16 bus_num;
|
|
+ u16 num_chipselect;
|
|
+ u8 irq_source;
|
|
+ u32 irq_vector;
|
|
+ u32 irq_mask;
|
|
+ u8 irq_lp;
|
|
+ u8 par_val;
|
|
+ u16 par_val16;
|
|
+ u32 *irq_list;
|
|
+ void (*cs_control)(u8 cs, u8 command);
|
|
+};
|
|
+#endif /*MCFDSPI_H_*/
|
|
--- a/arch/m68k/include/asm/mcfsim.h
|
|
+++ b/arch/m68k/include/asm/mcfsim.h
|
|
@@ -5,6 +5,12 @@
|
|
*
|
|
* (C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com)
|
|
* (C) Copyright 2000, Lineo Inc. (www.lineo.com)
|
|
+ *
|
|
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*/
|
|
|
|
/****************************************************************************/
|
|
@@ -45,5 +51,120 @@
|
|
#include <asm/m54xxsim.h>
|
|
#endif
|
|
|
|
+#if defined(CONFIG_COLDFIRE)
|
|
+#include <asm/coldfire.h>
|
|
+#endif
|
|
+
|
|
+#if defined(CONFIG_M5445X)
|
|
+#include <asm/mcf5445x_intc.h>
|
|
+#include <asm/mcf5445x_gpio.h>
|
|
+#include <asm/mcf5445x_ccm.h>
|
|
+#include <asm/mcf5445x_eport.h>
|
|
+#include <asm/mcf5445x_fbcs.h>
|
|
+#include <asm/mcf5445x_xbs.h>
|
|
+#include <asm/mcf5445x_dtim.h>
|
|
+#include <asm/mcf5445x_rtc.h>
|
|
+#include <asm/mcf5445x_scm.h>
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+#include <asm/m5485sim.h>
|
|
+#include <asm/m5485gpio.h>
|
|
+#include <asm/m5485gpt.h>
|
|
+#elif defined(CONFIG_M5441X)
|
|
+#include <asm/mcf5441x_intc.h>
|
|
+#include <asm/mcf5441x_gpio.h>
|
|
+#include <asm/mcf5441x_ccm.h>
|
|
+#include <asm/mcf5441x_eport.h>
|
|
+#include <asm/mcf5441x_fbcs.h>
|
|
+#include <asm/mcf5441x_xbs.h>
|
|
+#include <asm/mcf5441x_dtim.h>
|
|
+#include <asm/mcf5441x_rtc.h>
|
|
+#include <asm/mcf5441x_scm.h>
|
|
+#include <asm/mcf5441x_pm.h>
|
|
+#include <asm/mcf5441x_flexcan.h>
|
|
+#include <asm/mcf5441x_clock.h>
|
|
+#endif
|
|
+
|
|
+/*
|
|
+ * Define the base address of the SIM within the MBAR address space.
|
|
+ */
|
|
+#define MCFSIM_BASE 0x0 /* Base address of SIM */
|
|
+
|
|
+
|
|
+/*
|
|
+ * Bit definitions for the ICR family of registers.
|
|
+ */
|
|
+#define MCFSIM_ICR_AUTOVEC 0x80 /* Auto-vectored intr */
|
|
+#define MCFSIM_ICR_LEVEL0 0x00 /* Level 0 intr */
|
|
+#define MCFSIM_ICR_LEVEL1 0x04 /* Level 1 intr */
|
|
+#define MCFSIM_ICR_LEVEL2 0x08 /* Level 2 intr */
|
|
+#define MCFSIM_ICR_LEVEL3 0x0c /* Level 3 intr */
|
|
+#define MCFSIM_ICR_LEVEL4 0x10 /* Level 4 intr */
|
|
+#define MCFSIM_ICR_LEVEL5 0x14 /* Level 5 intr */
|
|
+#define MCFSIM_ICR_LEVEL6 0x18 /* Level 6 intr */
|
|
+#define MCFSIM_ICR_LEVEL7 0x1c /* Level 7 intr */
|
|
+
|
|
+#define MCFSIM_ICR_PRI0 0x00 /* Priority 0 intr */
|
|
+#define MCFSIM_ICR_PRI1 0x01 /* Priority 1 intr */
|
|
+#define MCFSIM_ICR_PRI2 0x02 /* Priority 2 intr */
|
|
+#define MCFSIM_ICR_PRI3 0x03 /* Priority 3 intr */
|
|
+
|
|
+/*
|
|
+ * Bit definitions for the Interrupt Mask register (IMR).
|
|
+ */
|
|
+#define MCFSIM_IMR_EINT1 0x0002 /* External intr # 1 */
|
|
+#define MCFSIM_IMR_EINT2 0x0004 /* External intr # 2 */
|
|
+#define MCFSIM_IMR_EINT3 0x0008 /* External intr # 3 */
|
|
+#define MCFSIM_IMR_EINT4 0x0010 /* External intr # 4 */
|
|
+#define MCFSIM_IMR_EINT5 0x0020 /* External intr # 5 */
|
|
+#define MCFSIM_IMR_EINT6 0x0040 /* External intr # 6 */
|
|
+#define MCFSIM_IMR_EINT7 0x0080 /* External intr # 7 */
|
|
+
|
|
+#define MCFSIM_IMR_SWD 0x0100 /* Software Watchdog intr */
|
|
+#define MCFSIM_IMR_TIMER1 0x0200 /* TIMER 1 intr */
|
|
+#define MCFSIM_IMR_TIMER2 0x0400 /* TIMER 2 intr */
|
|
+#define MCFSIM_IMR_MBUS 0x0800 /* MBUS intr */
|
|
+#define MCFSIM_IMR_UART1 0x1000 /* UART 1 intr */
|
|
+#define MCFSIM_IMR_UART2 0x2000 /* UART 2 intr */
|
|
+
|
|
+#if defined(CONFIG_M5206e)
|
|
+#define MCFSIM_IMR_DMA1 0x4000 /* DMA 1 intr */
|
|
+#define MCFSIM_IMR_DMA2 0x8000 /* DMA 2 intr */
|
|
+#elif defined(CONFIG_M5249) || defined(CONFIG_M5307)
|
|
+#define MCFSIM_IMR_DMA0 0x4000 /* DMA 0 intr */
|
|
+#define MCFSIM_IMR_DMA1 0x8000 /* DMA 1 intr */
|
|
+#define MCFSIM_IMR_DMA2 0x10000 /* DMA 2 intr */
|
|
+#define MCFSIM_IMR_DMA3 0x20000 /* DMA 3 intr */
|
|
+#endif
|
|
+
|
|
+/*
|
|
+ * Mask for all of the SIM devices. Some parts have more or less
|
|
+ * SIM devices. This is a catchall for the sandard set.
|
|
+ */
|
|
+#ifndef MCFSIM_IMR_MASKALL
|
|
+#define MCFSIM_IMR_MASKALL 0x3ffe /* All intr sources */
|
|
+#endif
|
|
+
|
|
+
|
|
+/*
|
|
+ * PIT interrupt settings, if not found in mXXXXsim.h file.
|
|
+ */
|
|
+#ifndef ICR_INTRCONF
|
|
+#define ICR_INTRCONF 0x2b /* PIT1 level 5, priority 3 */
|
|
+#endif
|
|
+#ifndef MCFPIT_IMR
|
|
+#define MCFPIT_IMR MCFINTC_IMRH
|
|
+#endif
|
|
+#ifndef MCFPIT_IMR_IBIT
|
|
+#define MCFPIT_IMR_IBIT (1 << (MCFINT_PIT1 - 32))
|
|
+#endif
|
|
+
|
|
+
|
|
+#ifndef __ASSEMBLY__
|
|
+/*
|
|
+ * Definition for the interrupt auto-vectoring support.
|
|
+ */
|
|
+extern void mcf_autovector(unsigned int vec);
|
|
+#endif /* __ASSEMBLY__ */
|
|
+
|
|
/****************************************************************************/
|
|
#endif /* mcfsim_h */
|
|
--- a/arch/m68k/include/asm/mcfuart.h
|
|
+++ b/arch/m68k/include/asm/mcfuart.h
|
|
@@ -5,6 +5,11 @@
|
|
*
|
|
* (C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com)
|
|
* (C) Copyright 2000, Lineo Inc. (www.lineo.com)
|
|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*/
|
|
|
|
/****************************************************************************/
|
|
@@ -12,6 +17,59 @@
|
|
#define mcfuart_h
|
|
/****************************************************************************/
|
|
|
|
+#if defined(CONFIG_M5445X)
|
|
+#include <asm/mcf5445x_intc.h>
|
|
+#define MCFUART_BASE1 0xfc060000 /* Base address of UART1 */
|
|
+#define MCFUART_BASE2 0xfc064000 /* Base address of UART2 */
|
|
+#define MCFUART_BASE3 0xfc068000 /* Base address of UART3 */
|
|
+#define MCFINT_VECBASE 64
|
|
+#define MCFINT_UART0 26
|
|
+#define MCFINT_UART1 27
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+#define MCFUART_BASE1 0x8600 /* Base address of UART1 */
|
|
+#define MCFUART_BASE2 0x8700 /* Base address of UART2 */
|
|
+#define MCFUART_BASE3 0x8800 /* Base address of UART3 */
|
|
+#define MCFUART_BASE4 0x8900 /* Base address of UART4 */
|
|
+#define MCFINT_VECBASE 64
|
|
+#define MCFINT_UART0 35
|
|
+#define MCFINT_UART1 34
|
|
+#define MCFINT_UART2 33
|
|
+#define MCFINT_UART3 32
|
|
+#elif defined(CONFIG_M5441X)
|
|
+#define MCFUART_BASE0 0xfc060000 /* Base address of UART1 */
|
|
+#define MCFUART_BASE1 0xfc064000 /* Base address of UART2 */
|
|
+#define MCFUART_BASE2 0xfc068000 /* Base address of UART3 */
|
|
+#define MCFUART_BASE3 0xfc06C000 /* Base address of UART4 */
|
|
+#define MCFUART_BASE4 0xec060000
|
|
+#define MCFUART_BASE5 0xec064000
|
|
+#define MCFUART_BASE6 0xec068000
|
|
+#define MCFUART_BASE7 0xec06C000
|
|
+#define MCFUART_BASE8 0xec070000
|
|
+#define MCFUART_BASE9 0xec074000
|
|
+
|
|
+#define MCFINT0_VECBASE 64
|
|
+#define MCFINT1_VECBASE (64 + 64)
|
|
+#define MCFINT_UART0 26
|
|
+#define MCFINT_UART1 27
|
|
+#define MCFINT_UART2 28
|
|
+#define MCFINT_UART3 29
|
|
+#define MCFINT_UART4 48
|
|
+#define MCFINT_UART5 49
|
|
+#define MCFINT_UART6 50
|
|
+#define MCFINT_UART7 51
|
|
+#define MCFINT_UART8 52
|
|
+#define MCFINT_UART9 53
|
|
+#endif
|
|
+
|
|
+#if defined(CONFIG_M5441X)
|
|
+#define MAX_PORT_NUM 10
|
|
+#elif defined(CONFIG_M547X_8X)
|
|
+#define MAX_PORT_NUM 4
|
|
+#else
|
|
+#define MAX_PORT_NUM 3
|
|
+#endif
|
|
+
|
|
+#ifndef __ASSEMBLY__
|
|
#include <linux/serial_core.h>
|
|
#include <linux/platform_device.h>
|
|
|
|
@@ -21,6 +79,7 @@ struct mcf_platform_uart {
|
|
unsigned int irq; /* Interrupt vector */
|
|
unsigned int uartclk; /* UART clock rate */
|
|
};
|
|
+#endif
|
|
|
|
/*
|
|
* Define the ColdFire UART register set addresses.
|
|
@@ -94,6 +153,11 @@ struct mcf_platform_uart {
|
|
#define MCFUART_USR_RXFULL 0x02 /* Receiver full */
|
|
#define MCFUART_USR_RXREADY 0x01 /* Receiver ready */
|
|
|
|
+#if defined(CONFIG_M547X_8X)
|
|
+#define MCFUART_USR_TXREADY_BN 0x0a
|
|
+#define MCFUART_USR_TXEMPTY_BN 0x0b
|
|
+#endif
|
|
+
|
|
#define MCFUART_USR_RXERR (MCFUART_USR_RXBREAK | MCFUART_USR_RXFRAMING | \
|
|
MCFUART_USR_RXPARITY | MCFUART_USR_RXOVERRUN)
|
|
|
|
--- a/arch/m68k/include/asm/mmu.h
|
|
+++ b/arch/m68k/include/asm/mmu.h
|
|
@@ -1,9 +1,22 @@
|
|
+/*
|
|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef __MMU_H
|
|
#define __MMU_H
|
|
-
|
|
#ifdef CONFIG_MMU
|
|
+#ifdef CONFIG_VDSO
|
|
+typedef struct {
|
|
+ unsigned long id;
|
|
+ void *vdso;
|
|
+} mm_context_t;
|
|
+#else
|
|
/* Default "unsigned long" context */
|
|
typedef unsigned long mm_context_t;
|
|
+#endif
|
|
#else
|
|
typedef struct {
|
|
unsigned long end_brk;
|
|
--- a/arch/m68k/include/asm/mmu_context.h
|
|
+++ b/arch/m68k/include/asm/mmu_context.h
|
|
@@ -1,14 +1,21 @@
|
|
+/*
|
|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef __M68K_MMU_CONTEXT_H
|
|
#define __M68K_MMU_CONTEXT_H
|
|
-
|
|
#include <asm-generic/mm_hooks.h>
|
|
+#include <asm-generic/pgtable.h>
|
|
|
|
static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
|
|
{
|
|
}
|
|
|
|
#ifdef CONFIG_MMU
|
|
-#ifndef CONFIG_SUN3
|
|
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
|
|
|
|
#include <asm/setup.h>
|
|
#include <asm/page.h>
|
|
@@ -103,7 +110,7 @@ static inline void activate_mm(struct mm
|
|
switch_mm_0460(next_mm);
|
|
}
|
|
|
|
-#else /* CONFIG_SUN3 */
|
|
+#elif defined(CONFIG_SUN3)
|
|
#include <asm/sun3mmu.h>
|
|
#include <linux/sched.h>
|
|
|
|
@@ -151,7 +158,178 @@ static inline void activate_mm(struct mm
|
|
activate_context(next_mm);
|
|
}
|
|
|
|
+#else /* CONFIG_COLDFIRE */
|
|
+
|
|
+#include <asm/coldfire.h>
|
|
+#include <asm/atomic.h>
|
|
+#include <asm/bitops.h>
|
|
+#include <asm/mmu.h>
|
|
+
|
|
+#define NO_CONTEXT 256
|
|
+#define LAST_CONTEXT 255
|
|
+#define FIRST_CONTEXT 1
|
|
+
|
|
+#ifdef CONFIG_VDSO
|
|
+#define cpu_context(mm) ((mm)->context.id)
|
|
+#else
|
|
+#define cpu_context(mm) ((mm)->context)
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_VDSO
|
|
+extern void set_context(unsigned long context, pgd_t *pgd);
|
|
+#else
|
|
+extern void set_context(mm_context_t context, pgd_t *pgd);
|
|
#endif
|
|
+extern unsigned long context_map[];
|
|
+#ifdef CONFIG_VDSO
|
|
+extern unsigned long next_mmu_context;
|
|
+#else
|
|
+extern mm_context_t next_mmu_context;
|
|
+#endif
|
|
+
|
|
+extern atomic_t nr_free_contexts;
|
|
+extern struct mm_struct *context_mm[LAST_CONTEXT+1];
|
|
+extern void steal_context(void);
|
|
+
|
|
+static inline void get_mmu_context(struct mm_struct *mm)
|
|
+{
|
|
+#ifdef CONFIG_VDSO
|
|
+ unsigned long ctx;
|
|
+#else
|
|
+ mm_context_t ctx;
|
|
+#endif
|
|
+
|
|
+ if (cpu_context(mm) != NO_CONTEXT)
|
|
+ return;
|
|
+ while (atomic_dec_and_test_lt(&nr_free_contexts)) {
|
|
+ atomic_inc(&nr_free_contexts);
|
|
+ steal_context();
|
|
+ }
|
|
+ ctx = next_mmu_context;
|
|
+ while (test_and_set_bit(ctx, context_map)) {
|
|
+ ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
|
|
+ if (ctx > LAST_CONTEXT)
|
|
+ ctx = 0;
|
|
+ }
|
|
+ next_mmu_context = (ctx + 1) & LAST_CONTEXT;
|
|
+ cpu_context(mm) = ctx;
|
|
+ context_mm[ctx] = mm;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set up the context for a new address space.
|
|
+ */
|
|
+#define init_new_context(tsk, mm) ((cpu_context(mm) = NO_CONTEXT), 0)
|
|
+/* #define init_new_context(tsk, mm) (((mm)->context = NO_CONTEXT), 0) */
|
|
+
|
|
+/*
|
|
+ * We're finished using the context for an address space.
|
|
+ */
|
|
+static inline void destroy_context(struct mm_struct *mm)
|
|
+{
|
|
+ if (cpu_context(mm) != NO_CONTEXT) {
|
|
+ clear_bit(cpu_context(mm), context_map);
|
|
+ cpu_context(mm) = NO_CONTEXT;
|
|
+ atomic_inc(&nr_free_contexts);
|
|
+ }
|
|
+}
|
|
+
|
|
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
|
+ struct task_struct *tsk)
|
|
+{
|
|
+ get_mmu_context(tsk->mm);
|
|
+ set_context(cpu_context(tsk->mm), next->pgd);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * 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_mm(struct mm_struct *active_mm,
|
|
+ struct mm_struct *mm)
|
|
+{
|
|
+ get_mmu_context(mm);
|
|
+ set_context(cpu_context(mm), mm->pgd);
|
|
+}
|
|
+
|
|
+#define deactivate_mm(tsk, mm) do { } while (0)
|
|
+
|
|
+extern void mmu_context_init(void);
|
|
+#if defined(CONFIG_M547X_8X)
|
|
+#define prepare_arch_switch(next) load_ksp_mmu(next)
|
|
+
|
|
+static inline void load_ksp_mmu(struct task_struct *task)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ struct mm_struct *mm;
|
|
+ int asid;
|
|
+ pgd_t *pgd;
|
|
+ pmd_t *pmd;
|
|
+ pte_t *pte;
|
|
+ unsigned long mmuar;
|
|
+
|
|
+ local_irq_save(flags);
|
|
+ mmuar = task->thread.ksp;
|
|
+
|
|
+ /* Search for a valid TLB entry, if one is found, don't remap */
|
|
+ *MMUAR = mmuar;
|
|
+ *MMUOR = MMUOR_STLB | MMUOR_ADR;
|
|
+ if ((*MMUSR) & MMUSR_HIT)
|
|
+ goto end;
|
|
+
|
|
+ if (mmuar >= PAGE_OFFSET) {
|
|
+ mm = &init_mm;
|
|
+ } else {
|
|
+ printk(KERN_INFO "load_ksp_mmu: non-kernel"
|
|
+ " mm found: 0x%08x\n",
|
|
+ (unsigned int) task->mm);
|
|
+ mm = task->mm;
|
|
+ }
|
|
+
|
|
+ if (!mm)
|
|
+ goto bug;
|
|
+
|
|
+ pgd = pgd_offset(mm, mmuar);
|
|
+ if (pgd_none(*pgd))
|
|
+ goto bug;
|
|
+
|
|
+ pmd = pmd_offset(pgd, mmuar);
|
|
+ if (pmd_none(*pmd))
|
|
+ goto bug;
|
|
+
|
|
+ pte = (mmuar >= PAGE_OFFSET) ? pte_offset_kernel(pmd, mmuar)
|
|
+ : pte_offset_map(pmd, mmuar);
|
|
+ if (pte_none(*pte) || !pte_present(*pte))
|
|
+ goto bug;
|
|
+
|
|
+ set_pte(pte, pte_mkyoung(*pte));
|
|
+ asid = cpu_context(mm) & 0xff;
|
|
+ if (!pte_dirty(*pte) && mmuar <= PAGE_OFFSET)
|
|
+ set_pte(pte, pte_wrprotect(*pte));
|
|
+
|
|
+ *MMUTR = (mmuar & PAGE_MASK) | (asid << CF_ASID_MMU_SHIFT)
|
|
+ | (((int)(pte->pte) & (int)CF_PAGE_MMUTR_MASK)
|
|
+ >> CF_PAGE_MMUTR_SHIFT)
|
|
+ | MMUTR_V;
|
|
+
|
|
+ *MMUDR = (pte_val(*pte) & PAGE_MASK)
|
|
+ | ((pte->pte) & CF_PAGE_MMUDR_MASK)
|
|
+ | MMUDR_SZ8K | MMUDR_X;
|
|
+
|
|
+ *MMUOR = MMUOR_ACC | MMUOR_UAA;
|
|
+ asm ("nop");
|
|
+
|
|
+ goto end;
|
|
+
|
|
+bug:
|
|
+ printk(KERN_ERR "ksp load failed: mm=0x%08x ksp=0x%08x\n",
|
|
+ (unsigned int) mm, (unsigned int) mmuar);
|
|
+end:
|
|
+ local_irq_restore(flags);
|
|
+}
|
|
+#endif /* CONFIG_M547X_8X */
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
+
|
|
#else /* !CONFIG_MMU */
|
|
|
|
static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
|
--- a/arch/m68k/include/asm/page.h
|
|
+++ b/arch/m68k/include/asm/page.h
|
|
@@ -1,12 +1,18 @@
|
|
+/*
|
|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_PAGE_H
|
|
#define _M68K_PAGE_H
|
|
-
|
|
#include <linux/const.h>
|
|
#include <asm/setup.h>
|
|
#include <asm/page_offset.h>
|
|
|
|
/* PAGE_SHIFT determines the page size */
|
|
-#ifndef CONFIG_SUN3
|
|
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
|
|
#define PAGE_SHIFT (12)
|
|
#else
|
|
#define PAGE_SHIFT (13)
|
|
--- a/arch/m68k/include/asm/page_mm.h
|
|
+++ b/arch/m68k/include/asm/page_mm.h
|
|
@@ -1,5 +1,17 @@
|
|
+/*
|
|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_PAGE_MM_H
|
|
#define _M68K_PAGE_MM_H
|
|
+#if PAGE_SHIFT < 13
|
|
+#define THREAD_SIZE (8192)
|
|
+#else
|
|
+#define THREAD_SIZE PAGE_SIZE
|
|
+#endif
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
@@ -70,6 +82,49 @@ extern unsigned long m68k_memoffset;
|
|
|
|
#define WANT_PAGE_VIRTUAL
|
|
|
|
+#if defined(CONFIG_COLDFIRE)
|
|
+extern unsigned long cf_dma_base;
|
|
+extern unsigned long cf_dma_end;
|
|
+
|
|
+static inline unsigned long ___pa(void *vaddr)
|
|
+{
|
|
+#if CONFIG_SDRAM_BASE != PAGE_OFFSET
|
|
+ return ((unsigned long)vaddr & 0x0fffffff) + CONFIG_SDRAM_BASE;
|
|
+#else
|
|
+ if ((unsigned long)vaddr >= CONFIG_DMA_BASE &&
|
|
+ (unsigned long)vaddr < (CONFIG_DMA_BASE + CONFIG_DMA_SIZE)) {
|
|
+ /* address is in carved out DMA range */
|
|
+ return ((unsigned long)vaddr - CONFIG_DMA_BASE)
|
|
+ + CONFIG_SDRAM_BASE;
|
|
+ } else if ((unsigned long)vaddr >= PAGE_OFFSET &&
|
|
+ (unsigned long)vaddr < (PAGE_OFFSET + CONFIG_SDRAM_SIZE)) {
|
|
+ /* normal mapping */
|
|
+ return ((unsigned long)vaddr - PAGE_OFFSET) + CONFIG_SDRAM_BASE;
|
|
+ }
|
|
+
|
|
+ return (unsigned long)vaddr;
|
|
+#endif
|
|
+}
|
|
+#define __pa(vaddr) ___pa((void *)(vaddr))
|
|
+
|
|
+static inline void *__va(unsigned long paddr)
|
|
+{
|
|
+#if CONFIG_SDRAM_BASE != PAGE_OFFSET
|
|
+ return (void *)((paddr & 0x0fffffff) + PAGE_OFFSET);
|
|
+#else
|
|
+ if (paddr >= cf_dma_base && paddr <= cf_dma_end) {
|
|
+ /* mapped address for DMA */
|
|
+ return (void *)((paddr - CONFIG_SDRAM_BASE) + CONFIG_DMA_BASE);
|
|
+ } else if (paddr >= cf_dma_end &&
|
|
+ paddr < (CONFIG_SDRAM_BASE + CONFIG_SDRAM_SIZE)) {
|
|
+ /* normal mapping */
|
|
+ return (void *)((paddr - CONFIG_SDRAM_BASE) + PAGE_OFFSET);
|
|
+ }
|
|
+ return (void *)paddr;
|
|
+#endif
|
|
+}
|
|
+
|
|
+#else
|
|
static inline unsigned long ___pa(void *vaddr)
|
|
{
|
|
unsigned long paddr;
|
|
@@ -91,6 +146,7 @@ static inline void *__va(unsigned long p
|
|
: "0" (paddr), "i" (m68k_fixup_memoffset));
|
|
return vaddr;
|
|
}
|
|
+#endif
|
|
|
|
#else /* !CONFIG_SUN3 */
|
|
/* This #define is a horrible hack to suppress lots of warnings. --m */
|
|
@@ -176,4 +232,9 @@ static inline __attribute_const__ int __
|
|
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
|
|
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
|
|
|
|
+#ifdef CONFIG_VDSO
|
|
+/* vDSO support */
|
|
+#define __HAVE_ARCH_GATE_AREA
|
|
+#endif
|
|
+
|
|
#endif /* _M68K_PAGE_MM_H */
|
|
--- a/arch/m68k/include/asm/page_offset.h
|
|
+++ b/arch/m68k/include/asm/page_offset.h
|
|
@@ -1,10 +1,21 @@
|
|
-/* This handles the memory map.. */
|
|
-
|
|
+/*
|
|
+ * Page and physical memory maps.
|
|
+ *
|
|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifdef CONFIG_MMU
|
|
-#ifndef CONFIG_SUN3
|
|
-#define PAGE_OFFSET_RAW 0x00000000
|
|
-#else
|
|
+#if defined(CONFIG_SUN3)
|
|
#define PAGE_OFFSET_RAW 0x0E000000
|
|
+#elif defined(CONFIG_M5445X) || defined(CONFIG_M547X_8X) \
|
|
+ || defined(CONFIG_M5441X)
|
|
+#define PHYS_OFFSET CONFIG_SDRAM_BASE
|
|
+#define PAGE_OFFSET_RAW (PHYS_OFFSET)
|
|
+#else
|
|
+#define PAGE_OFFSET_RAW 0x00000000
|
|
#endif
|
|
#else
|
|
#define PAGE_OFFSET_RAW CONFIG_RAMBASE
|
|
--- a/arch/m68k/include/asm/pgalloc.h
|
|
+++ b/arch/m68k/include/asm/pgalloc.h
|
|
@@ -1,14 +1,22 @@
|
|
+/*
|
|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef M68K_PGALLOC_H
|
|
#define M68K_PGALLOC_H
|
|
-
|
|
#include <linux/mm.h>
|
|
#include <linux/highmem.h>
|
|
#include <asm/setup.h>
|
|
|
|
#ifdef CONFIG_MMU
|
|
#include <asm/virtconvert.h>
|
|
-#ifdef CONFIG_SUN3
|
|
+#if defined(CONFIG_SUN3)
|
|
#include <asm/sun3_pgalloc.h>
|
|
+#elif defined(CONFIG_COLDFIRE)
|
|
+#include <asm/cf_pgalloc.h>
|
|
#else
|
|
#include <asm/motorola_pgalloc.h>
|
|
#endif
|
|
--- a/arch/m68k/include/asm/pgtable_mm.h
|
|
+++ b/arch/m68k/include/asm/pgtable_mm.h
|
|
@@ -1,6 +1,12 @@
|
|
+/*
|
|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_PGTABLE_H
|
|
#define _M68K_PGTABLE_H
|
|
-
|
|
#include <asm-generic/4level-fixup.h>
|
|
|
|
#include <asm/setup.h>
|
|
@@ -40,6 +46,8 @@
|
|
/* PGDIR_SHIFT determines what a third-level page table entry can map */
|
|
#ifdef CONFIG_SUN3
|
|
#define PGDIR_SHIFT 17
|
|
+#elif defined(CONFIG_COLDFIRE)
|
|
+#define PGDIR_SHIFT 22
|
|
#else
|
|
#define PGDIR_SHIFT 25
|
|
#endif
|
|
@@ -54,6 +62,10 @@
|
|
#define PTRS_PER_PTE 16
|
|
#define PTRS_PER_PMD 1
|
|
#define PTRS_PER_PGD 2048
|
|
+#elif defined(CONFIG_COLDFIRE)
|
|
+#define PTRS_PER_PTE 512
|
|
+#define PTRS_PER_PMD 1
|
|
+#define PTRS_PER_PGD 1024
|
|
#else
|
|
#define PTRS_PER_PTE 1024
|
|
#define PTRS_PER_PMD 8
|
|
@@ -66,6 +78,18 @@
|
|
#ifdef CONFIG_SUN3
|
|
#define KMAP_START 0x0DC00000
|
|
#define KMAP_END 0x0E000000
|
|
+#elif defined(CONFIG_COLDFIRE)
|
|
+#if defined(CONFIG_M5445X) || defined(CONFIG_M547X_8X)
|
|
+#define VMALLOC_START 0xc0000000
|
|
+#define VMALLOC_END 0xcfffffff
|
|
+#define KMAP_START (VMALLOC_END + 1)
|
|
+#define KMAP_END (0xe8000000 - 1)
|
|
+#elif defined(CONFIG_M5441X)
|
|
+#define VMALLOC_START 0xc0000000
|
|
+#define VMALLOC_END 0xcfffffff
|
|
+#define KMAP_START (VMALLOC_END + 1)
|
|
+#define KMAP_END (0xd8000000 - 1)
|
|
+#endif
|
|
#else
|
|
#define KMAP_START 0xd0000000
|
|
#define KMAP_END 0xf0000000
|
|
@@ -79,9 +103,11 @@
|
|
* The vmalloc() routines leaves a hole of 4kB between each vmalloced
|
|
* area for the same reason. ;)
|
|
*/
|
|
+#if !defined(CONFIG_COLDFIRE)
|
|
#define VMALLOC_OFFSET (8*1024*1024)
|
|
#define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
|
|
#define VMALLOC_END KMAP_START
|
|
+#endif
|
|
#else
|
|
extern unsigned long m68k_vmalloc_end;
|
|
#define VMALLOC_START 0x0f800000
|
|
@@ -130,6 +156,8 @@ static inline void update_mmu_cache(stru
|
|
|
|
#ifdef CONFIG_SUN3
|
|
#include <asm/sun3_pgtable.h>
|
|
+#elif defined(CONFIG_COLDFIRE)
|
|
+#include <asm/cf_pgtable.h>
|
|
#else
|
|
#include <asm/motorola_pgtable.h>
|
|
#endif
|
|
@@ -143,6 +171,10 @@ static inline void update_mmu_cache(stru
|
|
#else
|
|
# define __SUN3_PAGE_NOCACHE 0
|
|
#endif
|
|
+
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+# define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | CF_PAGE_NOCACHE))
|
|
+#else /* CONFIG_COLDFIRE */
|
|
#define pgprot_noncached(prot) \
|
|
(MMU_IS_SUN3 \
|
|
? (__pgprot(pgprot_val(prot) | __SUN3_PAGE_NOCACHE)) \
|
|
@@ -151,7 +183,7 @@ static inline void update_mmu_cache(stru
|
|
: (MMU_IS_040 || MMU_IS_060) \
|
|
? (__pgprot((pgprot_val(prot) & _CACHEMASK040) | _PAGE_NOCACHE_S)) \
|
|
: (prot)))
|
|
-
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
#include <asm-generic/pgtable.h>
|
|
#endif /* !__ASSEMBLY__ */
|
|
|
|
--- a/arch/m68k/include/asm/processor.h
|
|
+++ b/arch/m68k/include/asm/processor.h
|
|
@@ -2,6 +2,11 @@
|
|
* include/asm-m68k/processor.h
|
|
*
|
|
* Copyright (C) 1995 Hamish Macdonald
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*/
|
|
|
|
#ifndef __ASM_M68K_PROCESSOR_H
|
|
@@ -23,6 +28,10 @@ static inline unsigned long rdusp(void)
|
|
#ifdef CONFIG_COLDFIRE_SW_A7
|
|
extern unsigned int sw_usp;
|
|
return sw_usp;
|
|
+#elif defined(CONFIG_COLDFIRE)
|
|
+ unsigned long usp;
|
|
+ __asm__ __volatile__("movel %/usp,%0" : "=a" (usp));
|
|
+ return usp;
|
|
#else
|
|
register unsigned long usp __asm__("a0");
|
|
/* move %usp,%a0 */
|
|
@@ -36,6 +45,8 @@ static inline void wrusp(unsigned long u
|
|
#ifdef CONFIG_COLDFIRE_SW_A7
|
|
extern unsigned int sw_usp;
|
|
sw_usp = usp;
|
|
+#elif defined(CONFIG_COLDFIRE)
|
|
+ __asm__ __volatile__("movel %0,%/usp" : : "a" (usp));
|
|
#else
|
|
register unsigned long a0 __asm__("a0") = usp;
|
|
/* move %a0,%usp */
|
|
@@ -48,11 +59,17 @@ static inline void wrusp(unsigned long u
|
|
* so don't change it unless you know what you are doing.
|
|
*/
|
|
#ifdef CONFIG_MMU
|
|
-#ifndef CONFIG_SUN3
|
|
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
|
|
#define TASK_SIZE (0xF0000000UL)
|
|
+#elif defined(CONFIG_COLDFIRE)
|
|
+#define TASK_SIZE (0xC0000000UL)
|
|
+#else /* CONFIG_SUN3 */
|
|
+#ifdef __ASSEMBLY__
|
|
+#define TASK_SIZE (0x0E000000)
|
|
#else
|
|
#define TASK_SIZE (0x0E000000UL)
|
|
#endif
|
|
+#endif
|
|
#else
|
|
#define TASK_SIZE (0xFFFFFFFFUL)
|
|
#endif
|
|
@@ -66,8 +83,10 @@ static inline void wrusp(unsigned long u
|
|
* space during mmap's.
|
|
*/
|
|
#ifdef CONFIG_MMU
|
|
-#ifndef CONFIG_SUN3
|
|
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
|
|
#define TASK_UNMAPPED_BASE 0xC0000000UL
|
|
+#elif defined(CONFIG_COLDFIRE)
|
|
+#define TASK_UNMAPPED_BASE 0x60000000UL
|
|
#else
|
|
#define TASK_UNMAPPED_BASE 0x0A000000UL
|
|
#endif
|
|
@@ -80,7 +99,11 @@ struct thread_struct {
|
|
unsigned long ksp; /* kernel stack pointer */
|
|
unsigned long usp; /* user stack pointer */
|
|
unsigned short sr; /* saved status register */
|
|
+#ifndef CONFIG_COLDFIRE
|
|
unsigned short fs; /* saved fs (sfc, dfc) */
|
|
+#else
|
|
+ mm_segment_t fs;
|
|
+#endif
|
|
unsigned long crp[2]; /* cpu root pointer */
|
|
unsigned long esp0; /* points to SR of stack frame */
|
|
unsigned long faddr; /* info about last fault */
|
|
@@ -102,6 +125,7 @@ struct thread_struct {
|
|
/*
|
|
* Do necessary setup to start up a newly executed thread.
|
|
*/
|
|
+#ifndef CONFIG_COLDFIRE
|
|
static inline void start_thread(struct pt_regs * regs, unsigned long pc,
|
|
unsigned long usp)
|
|
{
|
|
@@ -112,7 +136,24 @@ static inline void start_thread(struct p
|
|
regs->sr &= ~0x2000;
|
|
wrusp(usp);
|
|
}
|
|
+#else
|
|
+/*
|
|
+ * Do necessary setup to start up a newly executed thread.
|
|
+ *
|
|
+ * pass the data segment into user programs if it exists,
|
|
+ * it can't hurt anything as far as I can tell
|
|
+ */
|
|
+#define start_thread(_regs, _pc, _usp) \
|
|
+do { \
|
|
+ set_fs(USER_DS); /* reads from user space */ \
|
|
+ (_regs)->pc = (_pc); \
|
|
+ if (current->mm) \
|
|
+ (_regs)->d5 = current->mm->start_data; \
|
|
+ (_regs)->sr &= ~0x2000; \
|
|
+ wrusp(_usp); \
|
|
+} while (0)
|
|
|
|
+#endif
|
|
#else
|
|
|
|
/*
|
|
--- a/arch/m68k/include/asm/ptrace.h
|
|
+++ b/arch/m68k/include/asm/ptrace.h
|
|
@@ -1,3 +1,10 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_PTRACE_H
|
|
#define _M68K_PTRACE_H
|
|
|
|
@@ -27,27 +34,38 @@
|
|
stack during a system call. */
|
|
|
|
struct pt_regs {
|
|
- long d1;
|
|
- long d2;
|
|
- long d3;
|
|
- long d4;
|
|
- long d5;
|
|
- long a0;
|
|
- long a1;
|
|
- long a2;
|
|
- long d0;
|
|
- long orig_d0;
|
|
- long stkadj;
|
|
+ long d1;
|
|
+ long d2;
|
|
+ long d3;
|
|
+ long d4;
|
|
+ long d5;
|
|
+ long a0;
|
|
+ long a1;
|
|
+ long a2;
|
|
+ long d0;
|
|
+ long orig_d0;
|
|
+ long stkadj;
|
|
#ifdef CONFIG_COLDFIRE
|
|
+#if 0
|
|
unsigned format : 4; /* frame format specifier */
|
|
unsigned vector : 12; /* vector offset */
|
|
unsigned short sr;
|
|
unsigned long pc;
|
|
+#endif
|
|
+/*FROM BSP*/
|
|
+ unsigned long mmuar;
|
|
+ unsigned long mmusr;
|
|
+ unsigned format:4; /* frame format specifier */
|
|
+ unsigned fs2:2;
|
|
+ unsigned vector:8;
|
|
+ unsigned fs1:2;
|
|
+ unsigned short sr;
|
|
+ unsigned long pc;
|
|
#else
|
|
- unsigned short sr;
|
|
- unsigned long pc;
|
|
- unsigned format : 4; /* frame format specifier */
|
|
- unsigned vector : 12; /* vector offset */
|
|
+ unsigned short sr;
|
|
+ unsigned long pc;
|
|
+ unsigned format:4; /* frame format specifier */
|
|
+ unsigned vector:12; /* vector offset */
|
|
#endif
|
|
};
|
|
|
|
--- a/arch/m68k/include/asm/raw_io.h
|
|
+++ b/arch/m68k/include/asm/raw_io.h
|
|
@@ -3,11 +3,19 @@
|
|
*
|
|
* 10/20/00 RZ: - created from bits of io.h and ide.h to cleanup namespace
|
|
*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*/
|
|
-
|
|
#ifndef _RAW_IO_H
|
|
#define _RAW_IO_H
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#include <asm/cf_raw_io.h>
|
|
+#else
|
|
+
|
|
#ifdef __KERNEL__
|
|
|
|
#include <asm/types.h>
|
|
@@ -60,6 +68,9 @@ extern void __iounmap(void *addr, unsign
|
|
#define __raw_writew(val,addr) out_be16((addr),(val))
|
|
#define __raw_writel(val,addr) out_be32((addr),(val))
|
|
|
|
+#define swap_inw(port) in_le16((port))
|
|
+#define swap_outw(val, port) out_le16((port), (val))
|
|
+
|
|
static inline void raw_insb(volatile u8 __iomem *port, u8 *buf, unsigned int len)
|
|
{
|
|
unsigned int i;
|
|
@@ -344,4 +355,6 @@ static inline void raw_outsw_swapw(volat
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
+
|
|
#endif /* _RAW_IO_H */
|
|
--- a/arch/m68k/include/asm/segment.h
|
|
+++ b/arch/m68k/include/asm/segment.h
|
|
@@ -1,3 +1,10 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_SEGMENT_H
|
|
#define _M68K_SEGMENT_H
|
|
|
|
@@ -29,6 +36,7 @@ typedef struct {
|
|
* Get/set the SFC/DFC registers for MOVES instructions
|
|
*/
|
|
|
|
+#ifndef CONFIG_COLDFIRE
|
|
static inline mm_segment_t get_fs(void)
|
|
{
|
|
#ifdef CONFIG_MMU
|
|
@@ -56,6 +64,15 @@ static inline void set_fs(mm_segment_t v
|
|
#endif
|
|
}
|
|
|
|
+#else /* CONFIG_COLDFIRE */
|
|
+
|
|
+#include <asm/current.h>
|
|
+#define get_fs() (current->thread.fs)
|
|
+#define set_fs(val) (current->thread.fs = (val))
|
|
+#define get_ds() (KERNEL_DS)
|
|
+
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
+
|
|
#define segment_eq(a,b) ((a).seg == (b).seg)
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
--- a/arch/m68k/include/asm/setup.h
|
|
+++ b/arch/m68k/include/asm/setup.h
|
|
@@ -2,6 +2,7 @@
|
|
** asm/setup.h -- Definition of the Linux/m68k setup information
|
|
**
|
|
** Copyright 1992 by Greg Harp
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
**
|
|
** This file is subject to the terms and conditions of the GNU General Public
|
|
** License. See the file COPYING in the main directory of this archive
|
|
@@ -40,6 +41,7 @@
|
|
#define MACH_HP300 9
|
|
#define MACH_Q40 10
|
|
#define MACH_SUN3X 11
|
|
+#define MACH_CFMMU 12
|
|
|
|
#define COMMAND_LINE_SIZE 256
|
|
|
|
@@ -189,6 +191,14 @@ extern unsigned long m68k_machtype;
|
|
# define MACH_TYPE (MACH_SUN3X)
|
|
#endif
|
|
|
|
+#if !defined(CONFIG_COLDFIRE)
|
|
+# define MACH_IS_COLDFIRE (0)
|
|
+#else
|
|
+# define CONFIG_COLDFIRE_ONLY
|
|
+# define MACH_IS_COLDFIRE (1)
|
|
+# define MACH_TYPE (MACH_CFMMU)
|
|
+#endif
|
|
+
|
|
#ifndef MACH_TYPE
|
|
# define MACH_TYPE (m68k_machtype)
|
|
#endif
|
|
@@ -211,23 +221,31 @@ extern unsigned long m68k_machtype;
|
|
#define CPUB_68030 1
|
|
#define CPUB_68040 2
|
|
#define CPUB_68060 3
|
|
+#define CPUB_CFV4E 4
|
|
|
|
#define CPU_68020 (1<<CPUB_68020)
|
|
#define CPU_68030 (1<<CPUB_68030)
|
|
#define CPU_68040 (1<<CPUB_68040)
|
|
#define CPU_68060 (1<<CPUB_68060)
|
|
+#define CPU_CFV4E (1<<CPUB_CFV4E)
|
|
|
|
#define FPUB_68881 0
|
|
#define FPUB_68882 1
|
|
#define FPUB_68040 2 /* Internal FPU */
|
|
#define FPUB_68060 3 /* Internal FPU */
|
|
#define FPUB_SUNFPA 4 /* Sun-3 FPA */
|
|
+#define FPUB_CFV4E 5
|
|
|
|
#define FPU_68881 (1<<FPUB_68881)
|
|
#define FPU_68882 (1<<FPUB_68882)
|
|
#define FPU_68040 (1<<FPUB_68040)
|
|
#define FPU_68060 (1<<FPUB_68060)
|
|
#define FPU_SUNFPA (1<<FPUB_SUNFPA)
|
|
+#ifdef CONFIG_M547X_8X
|
|
+#define FPU_CFV4E (1<<FPUB_CFV4E)
|
|
+#else
|
|
+#define FPU_CFV4E 0
|
|
+#endif
|
|
|
|
#define MMUB_68851 0
|
|
#define MMUB_68030 1 /* Internal MMU */
|
|
@@ -235,6 +253,7 @@ extern unsigned long m68k_machtype;
|
|
#define MMUB_68060 3 /* Internal MMU */
|
|
#define MMUB_APOLLO 4 /* Custom Apollo */
|
|
#define MMUB_SUN3 5 /* Custom Sun-3 */
|
|
+#define MMUB_CFV4E 6
|
|
|
|
#define MMU_68851 (1<<MMUB_68851)
|
|
#define MMU_68030 (1<<MMUB_68030)
|
|
@@ -242,6 +261,7 @@ extern unsigned long m68k_machtype;
|
|
#define MMU_68060 (1<<MMUB_68060)
|
|
#define MMU_SUN3 (1<<MMUB_SUN3)
|
|
#define MMU_APOLLO (1<<MMUB_APOLLO)
|
|
+#define MMU_CFV4E (1<<MMUB_CFV4E)
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
@@ -341,6 +361,14 @@ extern int m68k_is040or060;
|
|
# endif
|
|
#endif
|
|
|
|
+#if !defined(CONFIG_CFV4E)
|
|
+# define CPU_IS_COLDFIRE (0)
|
|
+#else
|
|
+# define CPU_IS_COLDFIRE (m68k_cputype & CPU_CFV4E)
|
|
+# define CPU_IS_CFV4E (m68k_cputype & CPU_CFV4E)
|
|
+# define MMU_IS_CFV4E (m68k_mmutype & MMU_CFV4E)
|
|
+#endif
|
|
+
|
|
#define CPU_TYPE (m68k_cputype)
|
|
|
|
#ifdef CONFIG_M68KFPU_EMU
|
|
@@ -371,6 +399,14 @@ extern int m68k_realnum_memory; /* real
|
|
extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
|
|
#endif
|
|
|
|
+#ifdef CONFIG_CFV4E
|
|
+#define QCHIP_RESTORE_DIRECTIVE ".chip 547x"
|
|
+#define CHIP_RESTORE_DIRECTIVE .chip 547x
|
|
+#else
|
|
+#define QCHIP_RESTORE_DIRECTIVE ".chip 68k"
|
|
+#define CHIP_RESTORE_DIRECTIVE .chip 68k
|
|
+#endif
|
|
+
|
|
#endif /* __KERNEL__ */
|
|
|
|
#endif /* _M68K_SETUP_H */
|
|
--- a/arch/m68k/include/asm/signal.h
|
|
+++ b/arch/m68k/include/asm/signal.h
|
|
@@ -1,6 +1,12 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_SIGNAL_H
|
|
#define _M68K_SIGNAL_H
|
|
-
|
|
#include <linux/types.h>
|
|
|
|
/* Avoid too many header ordering problems. */
|
|
@@ -150,7 +156,7 @@ typedef struct sigaltstack {
|
|
#ifdef __KERNEL__
|
|
#include <asm/sigcontext.h>
|
|
|
|
-#ifndef __uClinux__
|
|
+#ifndef CONFIG_COLDFIRE /*FIXME Jason*/
|
|
#define __HAVE_ARCH_SIG_BITOPS
|
|
|
|
static inline void sigaddset(sigset_t *set, int _sig)
|
|
--- a/arch/m68k/include/asm/string.h
|
|
+++ b/arch/m68k/include/asm/string.h
|
|
@@ -1,6 +1,12 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_STRING_H_
|
|
#define _M68K_STRING_H_
|
|
-
|
|
#include <linux/types.h>
|
|
#include <linux/compiler.h>
|
|
|
|
@@ -81,6 +87,18 @@ static inline char *strncpy(char *dest,
|
|
strcpy(__d + strlen(__d), (s)); \
|
|
})
|
|
|
|
+#define __HAVE_ARCH_STRCHR
|
|
+static inline char *strchr(const char *s, int c)
|
|
+{
|
|
+ char sc, ch = c;
|
|
+
|
|
+ for (; (sc = *s++) != ch; ) {
|
|
+ if (!sc)
|
|
+ return NULL;
|
|
+ }
|
|
+ return (char *)s - 1;
|
|
+}
|
|
+
|
|
#ifndef CONFIG_COLDFIRE
|
|
#define __HAVE_ARCH_STRCMP
|
|
static inline int strcmp(const char *cs, const char *ct)
|
|
--- a/arch/m68k/include/asm/swab.h
|
|
+++ b/arch/m68k/include/asm/swab.h
|
|
@@ -1,11 +1,18 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_SWAB_H
|
|
#define _M68K_SWAB_H
|
|
-
|
|
#include <linux/types.h>
|
|
#include <linux/compiler.h>
|
|
|
|
#define __SWAB_64_THRU_32__
|
|
|
|
+#if defined(__GNUC__)
|
|
#if defined (__mcfisaaplus__) || defined (__mcfisac__)
|
|
static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
|
|
{
|
|
@@ -23,5 +30,11 @@ static inline __attribute_const__ __u32
|
|
}
|
|
#define __arch_swab32 __arch_swab32
|
|
#endif
|
|
+#endif
|
|
+
|
|
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
|
|
+# define __BYTEORDER_HAS_U64__
|
|
+# define __SWAB_64_THRU_32__
|
|
+#endif
|
|
|
|
#endif /* _M68K_SWAB_H */
|
|
--- a/arch/m68k/include/asm/system_mm.h
|
|
+++ b/arch/m68k/include/asm/system_mm.h
|
|
@@ -1,14 +1,35 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_SYSTEM_H
|
|
#define _M68K_SYSTEM_H
|
|
-
|
|
#include <linux/linkage.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/irqflags.h>
|
|
#include <asm/segment.h>
|
|
#include <asm/entry.h>
|
|
+#include <asm/cfcache.h>
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#define FLUSH_BC (0x00040000)
|
|
+
|
|
+#define finish_arch_switch(prev) do { \
|
|
+ unsigned long tmpreg; \
|
|
+ asm volatile ("move.l %2,%0\n" \
|
|
+ "orl %1,%0\n" \
|
|
+ "movec %0,%%cacr" \
|
|
+ : "=&d" (tmpreg) \
|
|
+ : "id" (FLUSH_BC), "m" (shadow_cacr)); \
|
|
+ } while (0)
|
|
+
|
|
+#endif
|
|
+
|
|
/*
|
|
* switch_to(n) should switch tasks to task ptr, first checking that
|
|
* ptr isn't the current task, in which case it does nothing. This
|
|
--- a/arch/m68k/include/asm/tlbflush.h
|
|
+++ b/arch/m68k/include/asm/tlbflush.h
|
|
@@ -1,8 +1,14 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _M68K_TLBFLUSH_H
|
|
#define _M68K_TLBFLUSH_H
|
|
-
|
|
#ifdef CONFIG_MMU
|
|
-#ifndef CONFIG_SUN3
|
|
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
|
|
|
|
#include <asm/current.h>
|
|
|
|
@@ -92,7 +98,12 @@ static inline void flush_tlb_kernel_rang
|
|
flush_tlb_all();
|
|
}
|
|
|
|
-#else
|
|
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
|
|
+ unsigned long start, unsigned long end)
|
|
+{
|
|
+}
|
|
+
|
|
+#elif defined(CONFIG_SUN3)
|
|
|
|
|
|
/* Reserved PMEGs. */
|
|
@@ -214,6 +225,13 @@ static inline void flush_tlb_kernel_page
|
|
sun3_put_segmap (addr & ~(SUN3_PMEG_SIZE - 1), SUN3_INVALID_PMEG);
|
|
}
|
|
|
|
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
|
|
+ unsigned long start, unsigned long end)
|
|
+{
|
|
+}
|
|
+
|
|
+#else /* CONFIG_COLDFIRE */
|
|
+#include <asm/cf_tlbflush.h>
|
|
#endif
|
|
|
|
#else /* !CONFIG_MMU */
|
|
--- a/arch/m68k/include/asm/uaccess_mm.h
|
|
+++ b/arch/m68k/include/asm/uaccess_mm.h
|
|
@@ -1,6 +1,15 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef __M68K_UACCESS_H
|
|
#define __M68K_UACCESS_H
|
|
-
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#include <asm/cf_uaccess.h>
|
|
+#else
|
|
/*
|
|
* User space memory access functions
|
|
*/
|
|
@@ -219,6 +228,41 @@ unsigned long __generic_copy_to_user(voi
|
|
: "+d" (res), "+&a" (to), "+a" (from), "=&d" (tmp) \
|
|
: : "memory")
|
|
|
|
+#define __constant_copy_to_user_asm(res, to, from, tmp, n, s1, s2, s3) \
|
|
+ asm volatile ("\n" \
|
|
+ " move."#s1" (%2)+,%3\n" \
|
|
+ "11: moves."#s1" %3,(%1)+\n" \
|
|
+ "12: move."#s2" (%2)+,%3\n" \
|
|
+ "21: moves."#s2" %3,(%1)+\n" \
|
|
+ "22:\n" \
|
|
+ " .ifnc \""#s3"\",\"\"\n" \
|
|
+ " move."#s3" (%2)+,%3\n" \
|
|
+ "31: moves."#s3" %3,(%1)+\n" \
|
|
+ "32:\n" \
|
|
+ " .endif\n" \
|
|
+ "4:\n" \
|
|
+ "\n" \
|
|
+ " .section __ex_table,\"a\"\n" \
|
|
+ " .align 4\n" \
|
|
+ " .long 11b,5f\n" \
|
|
+ " .long 12b,5f\n" \
|
|
+ " .long 21b,5f\n" \
|
|
+ " .long 22b,5f\n" \
|
|
+ " .ifnc \""#s3"\",\"\"\n" \
|
|
+ " .long 31b,5f\n" \
|
|
+ " .long 32b,5f\n" \
|
|
+ " .endif\n" \
|
|
+ " .previous\n" \
|
|
+ "\n" \
|
|
+ " .section .fixup,\"ax\"\n" \
|
|
+ " .even\n" \
|
|
+ "5: moveq.l #"#n",%0\n" \
|
|
+ " jra 4b\n" \
|
|
+ " .previous\n" \
|
|
+ : "+d" (res), "+a" (to), "+a" (from), "=&d" (tmp) \
|
|
+ : : "memory")
|
|
+
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
static __always_inline unsigned long
|
|
__constant_copy_from_user(void *to, const void __user *from, unsigned long n)
|
|
{
|
|
@@ -266,40 +310,6 @@ __constant_copy_from_user(void *to, cons
|
|
return res;
|
|
}
|
|
|
|
-#define __constant_copy_to_user_asm(res, to, from, tmp, n, s1, s2, s3) \
|
|
- asm volatile ("\n" \
|
|
- " move."#s1" (%2)+,%3\n" \
|
|
- "11: moves."#s1" %3,(%1)+\n" \
|
|
- "12: move."#s2" (%2)+,%3\n" \
|
|
- "21: moves."#s2" %3,(%1)+\n" \
|
|
- "22:\n" \
|
|
- " .ifnc \""#s3"\",\"\"\n" \
|
|
- " move."#s3" (%2)+,%3\n" \
|
|
- "31: moves."#s3" %3,(%1)+\n" \
|
|
- "32:\n" \
|
|
- " .endif\n" \
|
|
- "4:\n" \
|
|
- "\n" \
|
|
- " .section __ex_table,\"a\"\n" \
|
|
- " .align 4\n" \
|
|
- " .long 11b,5f\n" \
|
|
- " .long 12b,5f\n" \
|
|
- " .long 21b,5f\n" \
|
|
- " .long 22b,5f\n" \
|
|
- " .ifnc \""#s3"\",\"\"\n" \
|
|
- " .long 31b,5f\n" \
|
|
- " .long 32b,5f\n" \
|
|
- " .endif\n" \
|
|
- " .previous\n" \
|
|
- "\n" \
|
|
- " .section .fixup,\"ax\"\n" \
|
|
- " .even\n" \
|
|
- "5: moveq.l #"#n",%0\n" \
|
|
- " jra 4b\n" \
|
|
- " .previous\n" \
|
|
- : "+d" (res), "+a" (to), "+a" (from), "=&d" (tmp) \
|
|
- : : "memory")
|
|
-
|
|
static __always_inline unsigned long
|
|
__constant_copy_to_user(void __user *to, const void *from, unsigned long n)
|
|
{
|
|
--- a/arch/m68k/include/asm/unistd.h
|
|
+++ b/arch/m68k/include/asm/unistd.h
|
|
@@ -1,6 +1,12 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef _ASM_M68K_UNISTD_H_
|
|
#define _ASM_M68K_UNISTD_H_
|
|
-
|
|
/*
|
|
* This file contains the system call numbers.
|
|
*/
|
|
@@ -343,10 +349,11 @@
|
|
#define __NR_fanotify_init 337
|
|
#define __NR_fanotify_mark 338
|
|
#define __NR_prlimit64 339
|
|
+#define __NR_recvmmsg 340
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
-#define NR_syscalls 340
|
|
+#define NR_syscalls 341
|
|
|
|
#define __ARCH_WANT_IPC_PARSE_VERSION
|
|
#define __ARCH_WANT_OLD_READDIR
|
|
--- a/arch/m68k/include/asm/virtconvert.h
|
|
+++ b/arch/m68k/include/asm/virtconvert.h
|
|
@@ -1,5 +1,15 @@
|
|
+/*
|
|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
#ifndef __VIRT_CONVERT__
|
|
#define __VIRT_CONVERT__
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#include <asm/cf_virtconvert.h>
|
|
+#else
|
|
|
|
/*
|
|
* Macros used for converting between virtual and physical mappings.
|
|
@@ -45,3 +55,4 @@ static inline void *phys_to_virt(unsigne
|
|
|
|
#endif
|
|
#endif
|
|
+#endif
|
|
--- a/arch/m68k/kernel/Makefile
|
|
+++ b/arch/m68k/kernel/Makefile
|
|
@@ -2,16 +2,27 @@
|
|
# Makefile for the linux kernel.
|
|
#
|
|
|
|
-ifndef CONFIG_SUN3
|
|
- extra-y := head.o
|
|
+ifdef CONFIG_SUN3
|
|
+ extra-y := sun3-head.o vmlinux.lds
|
|
+ obj-y := entry.o signal.o ints.o time.o
|
|
else
|
|
- extra-y := sun3-head.o
|
|
+ifndef CONFIG_COLDFIRE
|
|
+ extra-y := head.o vmlinux.lds
|
|
+ obj-y := entry.o signal.o traps.o ints.o time.o
|
|
+else # CONFIG_COLDFIRE
|
|
+ extra-y := vmlinux.lds
|
|
+ obj-y := time.o
|
|
+ ifdef CONFIG_M547X_8X
|
|
+ obj-$(CONFIG_PCI) += bios32_mcf548x.o
|
|
+ endif
|
|
+endif
|
|
endif
|
|
-extra-y += vmlinux.lds
|
|
|
|
-obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
|
|
- sys_m68k.o time.o setup.o m68k_ksyms.o devres.o
|
|
+obj-y += process.o ptrace.o module.o \
|
|
+ sys_m68k.o setup.o m68k_ksyms.o devres.o# semaphore.o
|
|
|
|
devres-y = ../../../kernel/irq/devres.o
|
|
|
|
obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo
|
|
+
|
|
+EXTRA_AFLAGS := -traditional
|
|
--- a/arch/m68k/kernel/asm-offsets.c
|
|
+++ b/arch/m68k/kernel/asm-offsets.c
|
|
@@ -2,6 +2,15 @@
|
|
* This program is used to generate definitions needed by
|
|
* assembly language modules.
|
|
*
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ * Add Codlfire support
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ *
|
|
* We use the technique used in the OSF Mach kernel code:
|
|
* generate asm statements containing #defines,
|
|
* compile this file to assembler, and then extract the
|
|
@@ -22,6 +31,9 @@
|
|
int main(void)
|
|
{
|
|
/* offsets into the task struct */
|
|
+ DEFINE(TASK_STATE, offsetof(struct task_struct, state));
|
|
+ DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
|
|
+ DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
|
|
DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
|
|
DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info));
|
|
DEFINE(TASK_MM, offsetof(struct task_struct, mm));
|
|
@@ -43,6 +55,7 @@ int main(void)
|
|
/* offsets into the thread_info struct */
|
|
DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count));
|
|
DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags));
|
|
+ DEFINE(TINFO_TP_VALUE, offsetof(struct thread_info, tp_value));
|
|
|
|
/* offsets into the pt_regs */
|
|
DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0));
|
|
@@ -57,8 +70,23 @@ int main(void)
|
|
DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2));
|
|
DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc));
|
|
DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr));
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+ /* Need to get the context out of struct mm for ASID setting */
|
|
+ DEFINE(MM_CONTEXT, offsetof(struct mm_struct, context));
|
|
+ /* Coldfire exception frame has vector *before* pc */
|
|
+ DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) - 4);
|
|
+#else
|
|
/* bitfields are a bit difficult */
|
|
DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
|
|
+#endif
|
|
+
|
|
+ /* offsets into the irq_handler struct */
|
|
+ DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
|
|
+ DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id));
|
|
+ DEFINE(IRQ_NEXT, offsetof(struct irq_node, next));
|
|
+
|
|
+ /* offsets into the kernel_stat struct */
|
|
+ DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
|
|
|
|
/* offsets into the irq_cpustat_t struct */
|
|
DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
|
|
--- a/arch/m68k/kernel/dma.c
|
|
+++ b/arch/m68k/kernel/dma.c
|
|
@@ -1,4 +1,7 @@
|
|
/*
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file COPYING in the main directory of this archive
|
|
* for more details.
|
|
@@ -12,12 +15,25 @@
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/vmalloc.h>
|
|
-
|
|
+#include <linux/pci.h>
|
|
#include <asm/pgalloc.h>
|
|
|
|
void *dma_alloc_coherent(struct device *dev, size_t size,
|
|
dma_addr_t *handle, gfp_t flag)
|
|
{
|
|
+#if defined(CONFIG_M5445X) || defined(CONFIG_M547X_8X) || \
|
|
+ defined(CONFIG_M5441X)
|
|
+ /*
|
|
+ * On the M5445x platform the memory allocated with GFP_DMA
|
|
+ * is guaranteed to be DMA'able.
|
|
+ */
|
|
+ void *addr;
|
|
+
|
|
+ size = PAGE_ALIGN(size);
|
|
+ addr = kmalloc(size, GFP_DMA);
|
|
+ *handle = virt_to_phys(addr);
|
|
+ return addr;
|
|
+#else
|
|
struct page *page, **map;
|
|
pgprot_t pgprot;
|
|
void *addr;
|
|
@@ -56,6 +72,7 @@ void *dma_alloc_coherent(struct device *
|
|
kfree(map);
|
|
|
|
return addr;
|
|
+#endif
|
|
}
|
|
EXPORT_SYMBOL(dma_alloc_coherent);
|
|
|
|
@@ -63,7 +80,12 @@ void dma_free_coherent(struct device *de
|
|
void *addr, dma_addr_t handle)
|
|
{
|
|
pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
|
|
+#if defined(CONFIG_M5445X) || defined(CONFIG_M547X_8X) || \
|
|
+ defined(CONFIG_M5441X)
|
|
+ kfree((void *)handle);
|
|
+#else
|
|
vfree(addr);
|
|
+#endif
|
|
}
|
|
EXPORT_SYMBOL(dma_free_coherent);
|
|
|
|
@@ -77,6 +99,9 @@ void dma_sync_single_for_device(struct d
|
|
case DMA_FROM_DEVICE:
|
|
cache_clear(handle, size);
|
|
break;
|
|
+ case PCI_DMA_BIDIRECTIONAL:
|
|
+ flush_dcache();
|
|
+ break;
|
|
default:
|
|
if (printk_ratelimit())
|
|
printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
|
|
@@ -89,16 +114,23 @@ void dma_sync_sg_for_device(struct devic
|
|
enum dma_data_direction dir)
|
|
{
|
|
int i;
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+ struct scatterlist *_sg;
|
|
|
|
+ for_each_sg(sg, _sg, nents, i)
|
|
+ dma_sync_single_for_device(dev, _sg->dma_address,
|
|
+ _sg->length, dir);
|
|
+#else
|
|
for (i = 0; i < nents; sg++, i++)
|
|
dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
|
|
+#endif
|
|
}
|
|
EXPORT_SYMBOL(dma_sync_sg_for_device);
|
|
|
|
dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
|
|
enum dma_data_direction dir)
|
|
{
|
|
- dma_addr_t handle = virt_to_bus(addr);
|
|
+ dma_addr_t handle = (dma_addr_t)virt_to_bus(addr);
|
|
|
|
dma_sync_single_for_device(dev, handle, size, dir);
|
|
return handle;
|
|
@@ -120,10 +152,19 @@ int dma_map_sg(struct device *dev, struc
|
|
enum dma_data_direction dir)
|
|
{
|
|
int i;
|
|
-
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+ struct scatterlist *_sg;
|
|
+#endif
|
|
+#ifndef CONFIG_COLDFIRE
|
|
for (i = 0; i < nents; sg++, i++) {
|
|
sg->dma_address = sg_phys(sg);
|
|
dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
|
|
+#else
|
|
+ for_each_sg(sg, _sg, nents, i) {
|
|
+ _sg->dma_address = sg_phys(_sg);
|
|
+ dma_sync_single_for_device(dev, _sg->dma_address,
|
|
+ _sg->length, dir);
|
|
+#endif
|
|
}
|
|
return nents;
|
|
}
|
|
--- a/arch/m68k/kernel/process.c
|
|
+++ b/arch/m68k/kernel/process.c
|
|
@@ -4,6 +4,15 @@
|
|
* Copyright (C) 1995 Hamish Macdonald
|
|
*
|
|
* 68060 fixes by Jesper Skov
|
|
+ *
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Kurt.Mahan@freescale.com
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*/
|
|
|
|
/*
|
|
@@ -185,12 +194,21 @@ EXPORT_SYMBOL(kernel_thread);
|
|
void flush_thread(void)
|
|
{
|
|
unsigned long zero = 0;
|
|
+#if !defined(CONFIG_COLDFIRE)
|
|
set_fs(USER_DS);
|
|
current->thread.fs = __USER_DS;
|
|
if (!FPU_IS_EMU)
|
|
asm volatile (".chip 68k/68881\n\t"
|
|
"frestore %0@\n\t"
|
|
".chip 68k" : : "a" (&zero));
|
|
+#else
|
|
+ set_fs(USER_DS);
|
|
+ current->thread.fs = USER_DS;
|
|
+#if defined(CONFIG_FPU)
|
|
+ if (!FPU_IS_EMU)
|
|
+ asm volatile ("frestore %0@\n\t" : : "a" (&zero));
|
|
+#endif
|
|
+#endif
|
|
}
|
|
|
|
/*
|
|
@@ -258,6 +276,7 @@ int copy_thread(unsigned long clone_flag
|
|
* Must save the current SFC/DFC value, NOT the value when
|
|
* the parent was last descheduled - RGH 10-08-96
|
|
*/
|
|
+#if !defined(CONFIG_COLDFIRE)
|
|
p->thread.fs = get_fs().seg;
|
|
|
|
if (!FPU_IS_EMU) {
|
|
@@ -269,9 +288,34 @@ int copy_thread(unsigned long clone_flag
|
|
"fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
|
|
: : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
|
|
: "memory");
|
|
+#else
|
|
+ p->thread.fs = get_fs();
|
|
+
|
|
+#if defined(CONFIG_FPU)
|
|
+ if (!FPU_IS_EMU) {
|
|
+ /* Copy the current fpu state */
|
|
+ asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0])
|
|
+ : "memory");
|
|
+
|
|
+ if (p->thread.fpstate[0]) {
|
|
+ asm volatile ("fmovemd %/fp0-%/fp7,%0"
|
|
+ : : "m" (p->thread.fp[0])
|
|
+ : "memory");
|
|
+ asm volatile ("fmovel %/fpiar,%0"
|
|
+ : : "m" (p->thread.fpcntl[0])
|
|
+ : "memory");
|
|
+ asm volatile ("fmovel %/fpcr,%0"
|
|
+ : : "m" (p->thread.fpcntl[1])
|
|
+ : "memory");
|
|
+ asm volatile ("fmovel %/fpsr,%0"
|
|
+ : : "m" (p->thread.fpcntl[2])
|
|
+ : "memory");
|
|
+ }
|
|
/* Restore the state in case the fpu was busy */
|
|
asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
|
|
}
|
|
+#endif
|
|
+#endif
|
|
|
|
return 0;
|
|
}
|
|
@@ -280,7 +324,9 @@ int copy_thread(unsigned long clone_flag
|
|
|
|
int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
|
|
{
|
|
+#if !defined(CONFIG_COLDFIRE) || defined(CONFIG_FPU)
|
|
char fpustate[216];
|
|
+#endif
|
|
|
|
if (FPU_IS_EMU) {
|
|
int i;
|
|
@@ -297,6 +343,7 @@ int dump_fpu (struct pt_regs *regs, stru
|
|
}
|
|
|
|
/* First dump the fpu context to avoid protocol violation. */
|
|
+#if !defined(CONFIG_COLDFIRE)
|
|
asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
|
|
if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
|
|
return 0;
|
|
@@ -307,6 +354,25 @@ int dump_fpu (struct pt_regs *regs, stru
|
|
asm volatile ("fmovemx %/fp0-%/fp7,%0"
|
|
:: "m" (fpu->fpregs[0])
|
|
: "memory");
|
|
+#elif defined(CONFIG_FPU)
|
|
+ asm volatile ("fsave %0" : : "m" (fpustate[0]) : "memory");
|
|
+ if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
|
|
+ return 0;
|
|
+
|
|
+ asm volatile ("fmovel %/fpiar,%0"
|
|
+ : : "m" (fpu->fpcntl[0])
|
|
+ : "memory");
|
|
+ asm volatile ("fmovel %/fpcr,%0"
|
|
+ : : "m" (fpu->fpcntl[1])
|
|
+ : "memory");
|
|
+ asm volatile ("fmovel %/fpsr,%0"
|
|
+ : : "m" (fpu->fpcntl[2])
|
|
+ : "memory");
|
|
+ asm volatile ("fmovemd %/fp0-%/fp7,%0"
|
|
+ : : "m" (fpu->fpregs[0])
|
|
+ : "memory");
|
|
+#endif
|
|
+
|
|
return 1;
|
|
}
|
|
EXPORT_SYMBOL(dump_fpu);
|
|
--- a/arch/m68k/kernel/setup.c
|
|
+++ b/arch/m68k/kernel/setup.c
|
|
@@ -2,7 +2,14 @@
|
|
* linux/arch/m68k/kernel/setup.c
|
|
*
|
|
* Copyright (C) 1995 Hamish Macdonald
|
|
- */
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+*/
|
|
|
|
/*
|
|
* This file handles the architecture-dependent parts of system setup
|
|
@@ -74,14 +81,26 @@ struct mem_info m68k_memory[NUM_MEMINFO]
|
|
EXPORT_SYMBOL(m68k_memory);
|
|
|
|
struct mem_info m68k_ramdisk;
|
|
+EXPORT_SYMBOL(m68k_ramdisk);
|
|
|
|
+#if !defined(CONFIG_COLDFIRE)
|
|
static char m68k_command_line[CL_SIZE];
|
|
+#else
|
|
+char m68k_command_line[CL_SIZE];
|
|
+unsigned long uboot_info_stk;
|
|
+EXPORT_SYMBOL(uboot_info_stk);
|
|
+#endif
|
|
|
|
void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
|
|
/* machine dependent irq functions */
|
|
void (*mach_init_IRQ) (void) __initdata = NULL;
|
|
void (*mach_get_model) (char *model);
|
|
void (*mach_get_hardware_list) (struct seq_file *m);
|
|
+
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+void (*mach_tick)(void);
|
|
+#endif
|
|
+
|
|
/* machine dependent timer functions */
|
|
unsigned long (*mach_gettimeoffset) (void);
|
|
int (*mach_hwclk) (int, struct rtc_time*);
|
|
@@ -137,13 +156,17 @@ extern void config_hp300(void);
|
|
extern void config_q40(void);
|
|
extern void config_sun3x(void);
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+void coldfire_sort_memrec(void);
|
|
+#endif
|
|
+
|
|
#define MASK_256K 0xfffc0000
|
|
|
|
extern void paging_init(void);
|
|
|
|
static void __init m68k_parse_bootinfo(const struct bi_record *record)
|
|
{
|
|
- while (record->tag != BI_LAST) {
|
|
+ while ((record->tag != BI_LAST) && !(CONFIG_COLDFIRE)) {
|
|
int unknown = 0;
|
|
const unsigned long *data = record->data;
|
|
|
|
@@ -203,6 +226,10 @@ static void __init m68k_parse_bootinfo(c
|
|
record->size);
|
|
}
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+ coldfire_sort_memrec();
|
|
+#endif
|
|
+
|
|
m68k_realnum_memory = m68k_num_memory;
|
|
#ifdef CONFIG_SINGLE_MEMORY_CHUNK
|
|
if (m68k_num_memory > 1) {
|
|
@@ -215,7 +242,9 @@ static void __init m68k_parse_bootinfo(c
|
|
|
|
void __init setup_arch(char **cmdline_p)
|
|
{
|
|
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
|
|
int i;
|
|
+#endif
|
|
|
|
/* The bootinfo is located right after the kernel bss */
|
|
m68k_parse_bootinfo((const struct bi_record *)_end);
|
|
@@ -230,9 +259,10 @@ void __init setup_arch(char **cmdline_p)
|
|
* We should really do our own FPU check at startup.
|
|
* [what do we do with buggy 68LC040s? if we have problems
|
|
* with them, we should add a test to check_bugs() below] */
|
|
-#ifndef CONFIG_M68KFPU_EMU_ONLY
|
|
+#if !defined(CONFIG_M68KFPU_EMU_ONLY) && defined(CONFIG_FPU)
|
|
/* clear the fpu if we have one */
|
|
- if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
|
|
+ if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060|
|
|
+ FPU_CFV4E)) {
|
|
volatile int zero = 0;
|
|
asm volatile ("frestore %0" : : "m" (zero));
|
|
}
|
|
@@ -320,16 +350,17 @@ void __init setup_arch(char **cmdline_p)
|
|
config_sun3x();
|
|
break;
|
|
#endif
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+ case MACH_CFMMU:
|
|
+ config_coldfire();
|
|
+ break;
|
|
+#endif
|
|
default:
|
|
panic("No configuration setup");
|
|
}
|
|
|
|
paging_init();
|
|
|
|
-#ifndef CONFIG_SUN3
|
|
- for (i = 1; i < m68k_num_memory; i++)
|
|
- free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
|
|
- m68k_memory[i].size);
|
|
#ifdef CONFIG_BLK_DEV_INITRD
|
|
if (m68k_ramdisk.size) {
|
|
reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
|
|
@@ -341,6 +372,10 @@ void __init setup_arch(char **cmdline_p)
|
|
}
|
|
#endif
|
|
|
|
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
|
|
+ for (i = 1; i < m68k_num_memory; i++)
|
|
+ free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
|
|
+ m68k_memory[i].size);
|
|
#ifdef CONFIG_ATARI
|
|
if (MACH_IS_ATARI)
|
|
atari_stram_reserve_pages((void *)availmem);
|
|
@@ -353,12 +388,22 @@ void __init setup_arch(char **cmdline_p)
|
|
|
|
#endif /* !CONFIG_SUN3 */
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+ mmu_context_init();
|
|
+#endif
|
|
+
|
|
/* set ISA defs early as possible */
|
|
#if defined(CONFIG_ISA) && defined(MULTI_ISA)
|
|
if (MACH_IS_Q40) {
|
|
isa_type = ISA_TYPE_Q40;
|
|
isa_sex = 0;
|
|
}
|
|
+#ifdef CONFIG_GG2
|
|
+ if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)) {
|
|
+ isa_type = ISA_TYPE_GG2;
|
|
+ isa_sex = 0;
|
|
+ }
|
|
+#endif
|
|
#ifdef CONFIG_AMIGA_PCMCIA
|
|
if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
|
|
isa_type = ISA_TYPE_AG;
|
|
@@ -377,6 +422,7 @@ static int show_cpuinfo(struct seq_file
|
|
#define LOOP_CYCLES_68030 (8)
|
|
#define LOOP_CYCLES_68040 (3)
|
|
#define LOOP_CYCLES_68060 (1)
|
|
+#define LOOP_CYCLES_COLDFIRE (2)
|
|
|
|
if (CPU_IS_020) {
|
|
cpu = "68020";
|
|
@@ -390,6 +436,9 @@ static int show_cpuinfo(struct seq_file
|
|
} else if (CPU_IS_060) {
|
|
cpu = "68060";
|
|
clockfactor = LOOP_CYCLES_68060;
|
|
+ } else if (CPU_IS_CFV4E) {
|
|
+ cpu = "ColdFire V4e";
|
|
+ clockfactor = LOOP_CYCLES_COLDFIRE;
|
|
} else {
|
|
cpu = "680x0";
|
|
clockfactor = 0;
|
|
@@ -408,6 +457,8 @@ static int show_cpuinfo(struct seq_file
|
|
fpu = "68060";
|
|
else if (m68k_fputype & FPU_SUNFPA)
|
|
fpu = "Sun FPA";
|
|
+ else if (m68k_fputype & FPU_CFV4E)
|
|
+ fpu = "ColdFire V4e";
|
|
else
|
|
fpu = "none";
|
|
#endif
|
|
@@ -424,6 +475,8 @@ static int show_cpuinfo(struct seq_file
|
|
mmu = "Sun-3";
|
|
else if (m68k_mmutype & MMU_APOLLO)
|
|
mmu = "Apollo";
|
|
+ else if (m68k_mmutype & MMU_CFV4E)
|
|
+ mmu = "ColdFire";
|
|
else
|
|
mmu = "unknown";
|
|
|
|
@@ -506,7 +559,8 @@ module_init(proc_hardware_init);
|
|
|
|
void check_bugs(void)
|
|
{
|
|
-#ifndef CONFIG_M68KFPU_EMU
|
|
+#if !defined(CONFIG_M68KFPU_EMU) && !defined(CONFIG_M5445X) && \
|
|
+ !defined(CONFIG_M5441X)
|
|
if (m68k_fputype == 0) {
|
|
printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
|
|
"WHICH IS REQUIRED BY LINUX/M68K ***\n");
|
|
--- a/arch/m68k/kernel/sys_m68k.c
|
|
+++ b/arch/m68k/kernel/sys_m68k.c
|
|
@@ -1,5 +1,12 @@
|
|
/*
|
|
* linux/arch/m68k/kernel/sys_m68k.c
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*
|
|
* This file contains various random system calls that
|
|
* have a non-standard calling sequence on the Linux/m68k
|
|
@@ -29,6 +36,9 @@
|
|
#include <asm/unistd.h>
|
|
#include <linux/elf.h>
|
|
#include <asm/tlb.h>
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#include <asm/cacheflush.h>
|
|
+#endif
|
|
|
|
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
|
|
unsigned long error_code);
|
|
@@ -45,6 +55,59 @@ asmlinkage long sys_mmap2(unsigned long
|
|
return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
|
|
}
|
|
|
|
+/*
|
|
+ * Perform the select(nd, in, out, ex, tv) and mmap() system
|
|
+ * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
|
|
+ * handle more than 4 system call parameters, so these system calls
|
|
+ * used a memory block for parameter passing..
|
|
+ */
|
|
+
|
|
+struct mmap_arg_struct {
|
|
+ unsigned long addr;
|
|
+ unsigned long len;
|
|
+ unsigned long prot;
|
|
+ unsigned long flags;
|
|
+ unsigned long fd;
|
|
+ unsigned long offset;
|
|
+};
|
|
+
|
|
+asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
|
|
+{
|
|
+ struct mmap_arg_struct a;
|
|
+ int error = -EFAULT;
|
|
+
|
|
+ if (copy_from_user(&a, arg, sizeof(a)))
|
|
+ goto out;
|
|
+
|
|
+ error = -EINVAL;
|
|
+ if (a.offset & ~PAGE_MASK)
|
|
+ goto out;
|
|
+
|
|
+ a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
|
|
+
|
|
+ error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags,
|
|
+ a.fd, a.offset >> PAGE_SHIFT);
|
|
+out:
|
|
+ return error;
|
|
+}
|
|
+
|
|
+struct sel_arg_struct {
|
|
+ unsigned long n;
|
|
+ fd_set __user *inp, *outp, *exp;
|
|
+ struct timeval __user *tvp;
|
|
+};
|
|
+
|
|
+asmlinkage int old_select(struct sel_arg_struct __user *arg)
|
|
+{
|
|
+ struct sel_arg_struct a;
|
|
+
|
|
+ if (copy_from_user(&a, arg, sizeof(a)))
|
|
+ return -EFAULT;
|
|
+ /* sys_select() does the appropriate kernel locking */
|
|
+ return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
|
|
+}
|
|
+
|
|
+#ifndef CONFIG_COLDFIRE
|
|
/* Convert virtual (user) address VADDR to physical address PADDR */
|
|
#define virt_to_phys_040(vaddr) \
|
|
({ \
|
|
@@ -368,6 +431,7 @@ cache_flush_060 (unsigned long addr, int
|
|
}
|
|
return 0;
|
|
}
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
|
|
/* sys_cacheflush -- flush (part of) the processor cache. */
|
|
asmlinkage int
|
|
@@ -399,6 +463,7 @@ sys_cacheflush (unsigned long addr, int
|
|
goto out;
|
|
}
|
|
|
|
+#ifndef CONFIG_COLDFIRE
|
|
if (CPU_IS_020_OR_030) {
|
|
if (scope == FLUSH_SCOPE_LINE && len < 256) {
|
|
unsigned long cacr;
|
|
@@ -443,6 +508,16 @@ sys_cacheflush (unsigned long addr, int
|
|
ret = cache_flush_060 (addr, scope, cache, len);
|
|
}
|
|
}
|
|
+#else /* CONFIG_COLDFIRE */
|
|
+ if ((cache & FLUSH_CACHE_INSN) && (cache & FLUSH_CACHE_DATA))
|
|
+ flush_bcache();
|
|
+ else if (cache & FLUSH_CACHE_INSN)
|
|
+ flush_icache();
|
|
+ else
|
|
+ flush_dcache();
|
|
+
|
|
+ ret = 0;
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
out:
|
|
return ret;
|
|
}
|
|
@@ -474,9 +549,14 @@ asmlinkage unsigned long sys_get_thread_
|
|
return current_thread_info()->tp_value;
|
|
}
|
|
|
|
+extern void *_vdso_tp;
|
|
+
|
|
asmlinkage int sys_set_thread_area(unsigned long tp)
|
|
{
|
|
current_thread_info()->tp_value = tp;
|
|
+#ifdef CONFIG_VDSO
|
|
+ *(unsigned long *)_vdso_tp = tp;
|
|
+#endif
|
|
return 0;
|
|
}
|
|
|
|
--- a/arch/m68k/kernel/time.c
|
|
+++ b/arch/m68k/kernel/time.c
|
|
@@ -2,6 +2,14 @@
|
|
* linux/arch/m68k/kernel/time.c
|
|
*
|
|
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ * Alison Wang b18965@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*
|
|
* This file contains the m68k-specific time handling details.
|
|
* Most of the stuff is located in the machine specific files.
|
|
@@ -9,9 +17,12 @@
|
|
* 1997-09-10 Updated NTP code according to technical memorandum Jan '96
|
|
* "A Kernel Model for Precision Timekeeping" by Dave Mills
|
|
*/
|
|
-
|
|
+#include <linux/clk.h>
|
|
+#include <linux/clocksource.h>
|
|
+#include <linux/clockchips.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/module.h>
|
|
+#include <linux/sysdev.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/param.h>
|
|
@@ -27,6 +38,7 @@
|
|
#include <linux/time.h>
|
|
#include <linux/timex.h>
|
|
#include <linux/profile.h>
|
|
+#include <asm/mcfsim.h>
|
|
|
|
static inline int set_rtc_mmss(unsigned long nowtime)
|
|
{
|
|
@@ -35,12 +47,18 @@ static inline int set_rtc_mmss(unsigned
|
|
return -1;
|
|
}
|
|
|
|
+#ifndef CONFIG_GENERIC_CLOCKEVENTS
|
|
/*
|
|
* timer_interrupt() needs to keep up the real-time clock,
|
|
* as well as call the "do_timer()" routine every clocktick
|
|
*/
|
|
static irqreturn_t timer_interrupt(int irq, void *dummy)
|
|
{
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+ /* kick hardware timer if necessary */
|
|
+ if (mach_tick)
|
|
+ mach_tick();
|
|
+#endif
|
|
do_timer(1);
|
|
update_process_times(user_mode(get_irq_regs()));
|
|
profile_tick(CPU_PROFILING);
|
|
@@ -91,11 +109,133 @@ void __init time_init(void)
|
|
{
|
|
mach_sched_init(timer_interrupt);
|
|
}
|
|
+#endif
|
|
|
|
+#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
|
|
u32 arch_gettimeoffset(void)
|
|
{
|
|
return mach_gettimeoffset() * 1000;
|
|
}
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
|
|
+
|
|
+extern unsigned long long sys_dtim2_read(void);
|
|
+extern void sys_dtim2_init(void);
|
|
+static int cfv4_set_next_event(unsigned long evt,
|
|
+ struct clock_event_device *dev);
|
|
+static void cfv4_set_mode(enum clock_event_mode mode,
|
|
+ struct clock_event_device *dev);
|
|
+
|
|
+#if defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
|
|
+#define FREQ (MCF_BUSCLK / 16)
|
|
+#else
|
|
+#define FREQ (MCF_BUSCLK)
|
|
+#endif
|
|
+
|
|
+/*
|
|
+ * Clock Evnt setup
|
|
+ */
|
|
+static struct clock_event_device clockevent_cfv4 = {
|
|
+ .name = "CFV4 timer2even",
|
|
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
|
+ .rating = 200,
|
|
+ .shift = 20,
|
|
+ .set_mode = cfv4_set_mode,
|
|
+ .set_next_event = cfv4_set_next_event,
|
|
+};
|
|
+
|
|
+static int cfv4_set_next_event(unsigned long evt,
|
|
+ struct clock_event_device *dev)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void cfv4_set_mode(enum clock_event_mode mode,
|
|
+ struct clock_event_device *dev)
|
|
+{
|
|
+ if (mode != CLOCK_EVT_MODE_ONESHOT)
|
|
+ cfv4_set_next_event((FREQ / HZ), dev);
|
|
+}
|
|
+
|
|
+static int __init cfv4_clockevent_init(void)
|
|
+{
|
|
+ clockevent_cfv4.mult =
|
|
+ div_sc(FREQ, NSEC_PER_SEC,
|
|
+ clockevent_cfv4.shift);
|
|
+ clockevent_cfv4.max_delta_ns =
|
|
+ clockevent_delta2ns((FREQ / HZ),
|
|
+ &clockevent_cfv4);
|
|
+ clockevent_cfv4.min_delta_ns =
|
|
+ clockevent_delta2ns(1, &clockevent_cfv4);
|
|
+
|
|
+ clockevent_cfv4.cpumask = &cpumask_of_cpu(0);
|
|
+
|
|
+ printk(KERN_INFO "timer: register clockevent\n");
|
|
+ clockevents_register_device(&clockevent_cfv4);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * clocksource setup
|
|
+ */
|
|
+
|
|
+struct clocksource clocksource_cfv4 = {
|
|
+ .name = "ColdfireV4",
|
|
+ .rating = 250,
|
|
+ .mask = CLOCKSOURCE_MASK(32),
|
|
+ .read = sys_dtim2_read,
|
|
+ .shift = 20,
|
|
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Initialize time subsystem. Called from linux/init/main.c
|
|
+ */
|
|
+void __init time_init(void)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ printk(KERN_INFO "Initializing time\n");
|
|
+
|
|
+ cfv4_clockevent_init();
|
|
+ /* initialize the system timer */
|
|
+ sys_dtim2_init();
|
|
+
|
|
+ /* JKM */
|
|
+ clocksource_cfv4.mult = clocksource_hz2mult(FREQ,
|
|
+ clocksource_cfv4.shift);
|
|
+
|
|
+ /* register our clocksource */
|
|
+ ret = clocksource_register(&clocksource_cfv4);
|
|
+ if (ret)
|
|
+ printk(KERN_ERR "timer: unable to "
|
|
+ "register clocksource - %d\n", ret);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * sysfs pieces
|
|
+ */
|
|
+
|
|
+static struct sysdev_class timer_class = {
|
|
+ .name = "timer",
|
|
+};
|
|
+
|
|
+static struct sys_device timer_device = {
|
|
+ .id = 0,
|
|
+ .cls = &timer_class,
|
|
+};
|
|
+
|
|
+static int __init timer_init_sysfs(void)
|
|
+{
|
|
+ int err = sysdev_class_register(&timer_class);
|
|
+ if (!err)
|
|
+ err = sysdev_register(&timer_device);
|
|
+ return err;
|
|
+}
|
|
+device_initcall(timer_init_sysfs);
|
|
+#endif /* CONFIG_GENERIC_CLOCKEVENTS */
|
|
|
|
static int __init rtc_init(void)
|
|
{
|
|
--- /dev/null
|
|
+++ b/arch/m68k/kernel/vmlinux-cf.lds
|
|
@@ -0,0 +1,142 @@
|
|
+/* ld script to make m68k Coldfire Linux kernel
|
|
+ *
|
|
+ * Derived from arch/m68k/kernel/vmlinux-std.lds
|
|
+ *
|
|
+ * Updated 11/26/2007 for new CodeSourcery toolset
|
|
+ * by Kurt Mahan <kmahan@freescale.com>
|
|
+ *
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
+#define LOAD_OFFSET 0x00000000
|
|
+
|
|
+#include <asm-generic/vmlinux.lds.h>
|
|
+#include <asm/page_offset.h>
|
|
+
|
|
+#define START_OFFSET 0x00020000
|
|
+#define IMAGE_START PAGE_OFFSET_RAW + START_OFFSET
|
|
+
|
|
+OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
|
|
+OUTPUT_ARCH(m68k)
|
|
+ENTRY(_stext)
|
|
+jiffies = jiffies_64 + 4;
|
|
+
|
|
+SECTIONS
|
|
+{
|
|
+ . = IMAGE_START;
|
|
+ .text.head : AT(ADDR(.text.head) - LOAD_OFFSET) {
|
|
+ _text = .; /* Text and read-only data */
|
|
+ *(.text.head)
|
|
+ } :text = 0x4e75
|
|
+
|
|
+ .text : AT(ADDR(.text) - LOAD_OFFSET) {
|
|
+ TEXT_TEXT
|
|
+ SCHED_TEXT
|
|
+ LOCK_TEXT
|
|
+ *(.fixup)
|
|
+ *(.gnu.warning)
|
|
+ } :text = 0x4e75
|
|
+ _etext = .; /* End of text section */
|
|
+
|
|
+ . = ALIGN(16);
|
|
+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
|
|
+ __start___ex_table = .;
|
|
+ *(__ex_table)
|
|
+ __stop___ex_table = .;
|
|
+ }
|
|
+
|
|
+ RODATA
|
|
+
|
|
+ . = ALIGN(8192);
|
|
+ .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
|
|
+ DATA_DATA
|
|
+ CONSTRUCTORS
|
|
+ } :data
|
|
+
|
|
+
|
|
+ . = ALIGN(16);
|
|
+ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET ) {
|
|
+ *(.data.cacheline_aligned)
|
|
+ } :data
|
|
+
|
|
+ _edata = .; /* End of data section */
|
|
+
|
|
+ NOTES /* support ld --build-id */
|
|
+
|
|
+ . = ALIGN(8192); /* Initrd */
|
|
+ .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
|
|
+ __init_begin = .;
|
|
+ _sinittext = .;
|
|
+ *(.init.text)
|
|
+ _einittext = .;
|
|
+ }
|
|
+
|
|
+ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
|
|
+ *(.init.data)
|
|
+ }
|
|
+
|
|
+ . = ALIGN(16);
|
|
+ .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
|
|
+ __setup_start = .;
|
|
+ *(.init.setup)
|
|
+ __setup_end = .;
|
|
+ }
|
|
+
|
|
+ .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
|
|
+ __initcall_start = .;
|
|
+ INITCALLS
|
|
+ __initcall_end = .;
|
|
+ }
|
|
+
|
|
+ .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
|
|
+ __con_initcall_start = .;
|
|
+ *(.con_initcall.init)
|
|
+ __con_initcall_end = .;
|
|
+ }
|
|
+
|
|
+ SECURITY_INIT
|
|
+
|
|
+#ifdef CONFIG_BLK_DEV_INITRD
|
|
+ . = ALIGN(8192);
|
|
+ .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
|
|
+ __initramfs_start = .;
|
|
+ *(.init.ramfs)
|
|
+ __initramfs_end = .;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ . = ALIGN(8192);
|
|
+ __init_end = .;
|
|
+
|
|
+ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
|
|
+ *(.data.init_task) /* The initial task and kernel stack */
|
|
+ }
|
|
+
|
|
+ _sbss = .;
|
|
+ .bss : AT(ADDR(.bss) - LOAD_OFFSET) { /* BSS */
|
|
+ *(.bss)
|
|
+ }
|
|
+ _ebss = .;
|
|
+
|
|
+ _end = . ;
|
|
+
|
|
+ __ctors_start = . ;
|
|
+
|
|
+ __ctors_end = . ;
|
|
+
|
|
+ /* Sections to be discarded */
|
|
+ /DISCARD/ : {
|
|
+ *(.exit.text)
|
|
+ *(.exit.data)
|
|
+ *(.exitcall.exit)
|
|
+ }
|
|
+
|
|
+ /* Stabs debugging sections. */
|
|
+ STABS_DEBUG
|
|
+}
|
|
--- a/arch/m68k/kernel/vmlinux.lds.S
|
|
+++ b/arch/m68k/kernel/vmlinux.lds.S
|
|
@@ -1,10 +1,20 @@
|
|
+/*
|
|
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
PHDRS
|
|
{
|
|
- text PT_LOAD FILEHDR PHDRS FLAGS (7);
|
|
+ headers PT_PHDR PHDRS ;
|
|
+ text PT_LOAD FILEHDR PHDRS FLAGS (5);
|
|
data PT_LOAD FLAGS (7);
|
|
}
|
|
#ifdef CONFIG_SUN3
|
|
#include "vmlinux-sun3.lds"
|
|
+#elif CONFIG_COLDFIRE
|
|
+#include "vmlinux-cf.lds"
|
|
#else
|
|
#include "vmlinux-std.lds"
|
|
#endif
|
|
--- a/arch/m68k/lib/checksum.c
|
|
+++ b/arch/m68k/lib/checksum.c
|
|
@@ -30,6 +30,10 @@
|
|
* 1998/8/31 Andreas Schwab:
|
|
* Zero out rest of buffer on exception in
|
|
* csum_partial_copy_from_user.
|
|
+ *
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
@@ -39,8 +43,132 @@
|
|
* computes a partial checksum, e.g. for TCP/UDP fragments
|
|
*/
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+
|
|
+static inline unsigned short from32to16(unsigned long x)
|
|
+{
|
|
+ /* add up 16-bit and 16-bit for 16+c bit */
|
|
+ x = (x & 0xffff) + (x >> 16);
|
|
+ /* add up carry.. */
|
|
+ x = (x & 0xffff) + (x >> 16);
|
|
+ return x;
|
|
+}
|
|
+
|
|
+static unsigned long do_csum(const unsigned char *buff, int len)
|
|
+{
|
|
+ int odd, count;
|
|
+ unsigned long result = 0;
|
|
+
|
|
+ if (len <= 0)
|
|
+ goto out;
|
|
+ odd = 1 & (unsigned long) buff;
|
|
+ if (odd) {
|
|
+ result = *buff;
|
|
+ len--;
|
|
+ buff++;
|
|
+ }
|
|
+ count = len >> 1; /* nr of 16-bit words.. */
|
|
+ if (count) {
|
|
+ if (2 & (unsigned long) buff) {
|
|
+ result += *(unsigned short *) buff;
|
|
+ count--;
|
|
+ len -= 2;
|
|
+ buff += 2;
|
|
+ }
|
|
+ count >>= 1; /* nr of 32-bit words.. */
|
|
+ if (count) {
|
|
+ unsigned long carry = 0;
|
|
+ do {
|
|
+ unsigned long w = *(unsigned long *) buff;
|
|
+ count--;
|
|
+ buff += 4;
|
|
+ result += carry;
|
|
+ result += w;
|
|
+ carry = (w > result);
|
|
+ } while (count);
|
|
+ result += carry;
|
|
+ result = (result & 0xffff) + (result >> 16);
|
|
+ }
|
|
+ if (len & 2) {
|
|
+ result += *(unsigned short *) buff;
|
|
+ buff += 2;
|
|
+ }
|
|
+ }
|
|
+ if (len & 1)
|
|
+ result += (*buff << 8);
|
|
+ result = from32to16(result);
|
|
+ if (odd)
|
|
+ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
|
|
+out:
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * This is a version of ip_compute_csum() optimized for IP headers,
|
|
+ * which always checksum on 4 octet boundaries.
|
|
+ */
|
|
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
|
|
+{
|
|
+ return ~do_csum(iph, ihl*4);
|
|
+}
|
|
+EXPORT_SYMBOL(ip_fast_csum);
|
|
+
|
|
+/*
|
|
+ * computes the checksum of a memory block at buff, length len,
|
|
+ * and adds in "sum" (32-bit)
|
|
+ *
|
|
+ * returns a 32-bit number suitable for feeding into itself
|
|
+ * or csum_tcpudp_magic
|
|
+ *
|
|
+ * this function must be called with even lengths, except
|
|
+ * for the last fragment, which may be odd
|
|
+ *
|
|
+ * it's best to have buff aligned on a 32-bit boundary
|
|
+ */
|
|
__wsum csum_partial(const void *buff, int len, __wsum sum)
|
|
{
|
|
+ unsigned int result = do_csum(buff, len);
|
|
+
|
|
+ /* add in old sum, and carry.. */
|
|
+ result += sum;
|
|
+ if (sum > result)
|
|
+ result += 1;
|
|
+ return result;
|
|
+}
|
|
+EXPORT_SYMBOL(csum_partial);
|
|
+
|
|
+/*
|
|
+ * copy from fs while checksumming, otherwise like csum_partial
|
|
+ */
|
|
+
|
|
+__wsum
|
|
+csum_partial_copy_from_user(const void __user *src, void *dst, int len,
|
|
+ __wsum sum, int *csum_err)
|
|
+{
|
|
+ if (csum_err)
|
|
+ *csum_err = 0;
|
|
+ memcpy(dst, src, len);
|
|
+ return csum_partial(dst, len, sum);
|
|
+}
|
|
+EXPORT_SYMBOL(csum_partial_copy_from_user);
|
|
+
|
|
+/*
|
|
+ * copy from ds while checksumming, otherwise like csum_partial
|
|
+ */
|
|
+
|
|
+__wsum
|
|
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
|
|
+{
|
|
+ memcpy(dst, src, len);
|
|
+ return csum_partial(dst, len, sum);
|
|
+}
|
|
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
|
|
+
|
|
+#else /* !CONFIG_COLDFIRE */
|
|
+
|
|
+unsigned int
|
|
+csum_partial(const unsigned char *buff, int len, unsigned int sum)
|
|
+{
|
|
unsigned long tmp1, tmp2;
|
|
/*
|
|
* Experiments with ethernet and slip connections show that buff
|
|
@@ -423,3 +551,4 @@ csum_partial_copy_nocheck(const void *sr
|
|
return(sum);
|
|
}
|
|
EXPORT_SYMBOL(csum_partial_copy_nocheck);
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
--- a/arch/m68k/lib/muldi3.c
|
|
+++ b/arch/m68k/lib/muldi3.c
|
|
@@ -1,6 +1,9 @@
|
|
/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
|
|
gcc-2.7.2.3/longlong.h which is: */
|
|
/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
|
|
+ Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ Jason Jin Jason.Jin@freescale.com
|
|
+ Shrek Wu B16972@freescale.com
|
|
|
|
This file is part of GNU CC.
|
|
|
|
@@ -21,12 +24,22 @@ Boston, MA 02111-1307, USA. */
|
|
|
|
#define BITS_PER_UNIT 8
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#define umul_ppmm(w1, w0, u, v) \
|
|
+ do { \
|
|
+ unsigned long long x; \
|
|
+ x = (unsigned long long)u * v; \
|
|
+ w0 = (unsigned long)(x & 0x00000000ffffffff); \
|
|
+ w1 = (unsigned long)(x & 0xffffffff00000000) >> 32; \
|
|
+ } while (0)
|
|
+#else /* CONFIG_COLDFIRE */
|
|
#define umul_ppmm(w1, w0, u, v) \
|
|
__asm__ ("mulu%.l %3,%1:%0" \
|
|
: "=d" ((USItype)(w0)), \
|
|
"=d" ((USItype)(w1)) \
|
|
: "%0" ((USItype)(u)), \
|
|
"dmi" ((USItype)(v)))
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
|
|
#define __umulsidi3(u, v) \
|
|
({DIunion __w; \
|
|
--- a/arch/m68k/lib/string.c
|
|
+++ b/arch/m68k/lib/string.c
|
|
@@ -1,4 +1,8 @@
|
|
/*
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file COPYING in the main directory of this archive
|
|
* for more details.
|
|
@@ -21,6 +25,7 @@ char *strcat(char *dest, const char *src
|
|
}
|
|
EXPORT_SYMBOL(strcat);
|
|
|
|
+#ifndef CONFIG_COLDFIRE
|
|
void *memset(void *s, int c, size_t count)
|
|
{
|
|
void *xs = s;
|
|
@@ -149,6 +154,69 @@ void *memcpy(void *to, const void *from,
|
|
}
|
|
EXPORT_SYMBOL(memcpy);
|
|
|
|
+#else /* CONFIG_COLDFIRE */
|
|
+
|
|
+void *memset(void *s, int c, size_t count)
|
|
+{
|
|
+ unsigned long x;
|
|
+ void *originalTo = s;
|
|
+
|
|
+ for (x = 0; x < count; x++)
|
|
+ *(unsigned char *)s++ = (unsigned char)c;
|
|
+
|
|
+ return originalTo;
|
|
+}
|
|
+EXPORT_SYMBOL(memset);
|
|
+
|
|
+void *memcpy(void *to, const void *from, size_t n)
|
|
+{
|
|
+ void *xto = to;
|
|
+ size_t temp;
|
|
+
|
|
+ if (!n)
|
|
+ return xto;
|
|
+ if ((long) to & 1) {
|
|
+ char *cto = to;
|
|
+ const char *cfrom = from;
|
|
+ *cto++ = *cfrom++;
|
|
+ to = cto;
|
|
+ from = cfrom;
|
|
+ n--;
|
|
+ }
|
|
+ if (n > 2 && (long) to & 2) {
|
|
+ short *sto = to;
|
|
+ const short *sfrom = from;
|
|
+ *sto++ = *sfrom++;
|
|
+ to = sto;
|
|
+ from = sfrom;
|
|
+ n -= 2;
|
|
+ }
|
|
+ temp = n >> 2;
|
|
+ if (temp) {
|
|
+ long *lto = to;
|
|
+ const long *lfrom = from;
|
|
+ for (; temp; temp--)
|
|
+ *lto++ = *lfrom++;
|
|
+ to = lto;
|
|
+ from = lfrom;
|
|
+ }
|
|
+ if (n & 2) {
|
|
+ short *sto = to;
|
|
+ const short *sfrom = from;
|
|
+ *sto++ = *sfrom++;
|
|
+ to = sto;
|
|
+ from = sfrom;
|
|
+ }
|
|
+ if (n & 1) {
|
|
+ char *cto = to;
|
|
+ const char *cfrom = from;
|
|
+ *cto = *cfrom;
|
|
+ }
|
|
+ return xto;
|
|
+}
|
|
+EXPORT_SYMBOL(memcpy);
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
+
|
|
void *memmove(void *dest, const void *src, size_t n)
|
|
{
|
|
void *xdest = dest;
|
|
--- a/arch/m68k/lib/uaccess.c
|
|
+++ b/arch/m68k/lib/uaccess.c
|
|
@@ -1,10 +1,15 @@
|
|
/*
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file COPYING in the main directory of this archive
|
|
* for more details.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
+#ifndef CONFIG_COLDFIRE
|
|
#include <asm/uaccess.h>
|
|
|
|
unsigned long __generic_copy_from_user(void *to, const void __user *from,
|
|
@@ -220,3 +225,245 @@ unsigned long __clear_user(void __user *
|
|
return res;
|
|
}
|
|
EXPORT_SYMBOL(__clear_user);
|
|
+
|
|
+#else /* CONFIG_COLDFIRE */
|
|
+
|
|
+#include <asm/cf_uaccess.h>
|
|
+
|
|
+unsigned long __generic_copy_from_user(void *to, const void *from,
|
|
+ unsigned long n)
|
|
+{
|
|
+ unsigned long tmp;
|
|
+ __asm__ __volatile__
|
|
+ (" tstl %2\n"
|
|
+ " jeq 2f\n"
|
|
+ "1: movel (%1)+,%3\n"
|
|
+ " movel %3,(%0)+\n"
|
|
+ " subql #1,%2\n"
|
|
+ " jne 1b\n"
|
|
+ "2: movel %4,%2\n"
|
|
+ " bclr #1,%2\n"
|
|
+ " jeq 4f\n"
|
|
+ "3: movew (%1)+,%3\n"
|
|
+ " movew %3,(%0)+\n"
|
|
+ "4: bclr #0,%2\n"
|
|
+ " jeq 6f\n"
|
|
+ "5: moveb (%1)+,%3\n"
|
|
+ " moveb %3,(%0)+\n"
|
|
+ "6:\n"
|
|
+ ".section .fixup,\"ax\"\n"
|
|
+ " .even\n"
|
|
+ "7: movel %2,%%d0\n"
|
|
+ "71:clrl (%0)+\n"
|
|
+ " subql #1,%%d0\n"
|
|
+ " jne 71b\n"
|
|
+ " lsll #2,%2\n"
|
|
+ " addl %4,%2\n"
|
|
+ " btst #1,%4\n"
|
|
+ " jne 81f\n"
|
|
+ " btst #0,%4\n"
|
|
+ " jne 91f\n"
|
|
+ " jra 6b\n"
|
|
+ "8: addql #2,%2\n"
|
|
+ "81:clrw (%0)+\n"
|
|
+ " btst #0,%4\n"
|
|
+ " jne 91f\n"
|
|
+ " jra 6b\n"
|
|
+ "9: addql #1,%2\n"
|
|
+ "91:clrb (%0)+\n"
|
|
+ " jra 6b\n"
|
|
+ ".previous\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 1b,7b\n"
|
|
+ " .long 3b,8b\n"
|
|
+ " .long 5b,9b\n"
|
|
+ ".previous"
|
|
+ : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
|
|
+ : "d"(n & 3), "0"(to), "1"(from), "2"(n/4)
|
|
+ : "d0", "memory");
|
|
+ return n;
|
|
+}
|
|
+EXPORT_SYMBOL(__generic_copy_from_user);
|
|
+
|
|
+
|
|
+unsigned long __generic_copy_to_user(void *to, const void *from,
|
|
+ unsigned long n)
|
|
+{
|
|
+ unsigned long tmp;
|
|
+ __asm__ __volatile__
|
|
+ (" tstl %2\n"
|
|
+ " jeq 3f\n"
|
|
+ "1: movel (%1)+,%3\n"
|
|
+ "22:movel %3,(%0)+\n"
|
|
+ "2: subql #1,%2\n"
|
|
+ " jne 1b\n"
|
|
+ "3: movel %4,%2\n"
|
|
+ " bclr #1,%2\n"
|
|
+ " jeq 4f\n"
|
|
+ " movew (%1)+,%3\n"
|
|
+ "24:movew %3,(%0)+\n"
|
|
+ "4: bclr #0,%2\n"
|
|
+ " jeq 5f\n"
|
|
+ " moveb (%1)+,%3\n"
|
|
+ "25:moveb %3,(%0)+\n"
|
|
+ "5:\n"
|
|
+ ".section .fixup,\"ax\"\n"
|
|
+ " .even\n"
|
|
+ "60:addql #1,%2\n"
|
|
+ "6: lsll #2,%2\n"
|
|
+ " addl %4,%2\n"
|
|
+ " jra 5b\n"
|
|
+ "7: addql #2,%2\n"
|
|
+ " jra 5b\n"
|
|
+ "8: addql #1,%2\n"
|
|
+ " jra 5b\n"
|
|
+ ".previous\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 1b,60b\n"
|
|
+ " .long 22b,6b\n"
|
|
+ " .long 2b,6b\n"
|
|
+ " .long 24b,7b\n"
|
|
+ " .long 3b,60b\n"
|
|
+ " .long 4b,7b\n"
|
|
+ " .long 25b,8b\n"
|
|
+ " .long 5b,8b\n"
|
|
+ ".previous"
|
|
+ : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
|
|
+ : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4)
|
|
+ : "memory");
|
|
+ return n;
|
|
+}
|
|
+EXPORT_SYMBOL(__generic_copy_to_user);
|
|
+
|
|
+/*
|
|
+ * Copy a null terminated string from userspace.
|
|
+ */
|
|
+
|
|
+long strncpy_from_user(char *dst, const char *src, long count)
|
|
+{
|
|
+ long res = -EFAULT;
|
|
+ if (!(access_ok(VERIFY_READ, src, 1))) /* --tym-- */
|
|
+ return res;
|
|
+ if (count == 0)
|
|
+ return count;
|
|
+ __asm__ __volatile__
|
|
+ ("1: moveb (%2)+,%%d0\n"
|
|
+ "12:moveb %%d0,(%1)+\n"
|
|
+ " jeq 2f\n"
|
|
+ " subql #1,%3\n"
|
|
+ " jne 1b\n"
|
|
+ "2: subl %3,%0\n"
|
|
+ "3:\n"
|
|
+ ".section .fixup,\"ax\"\n"
|
|
+ " .even\n"
|
|
+ "4: movel %4,%0\n"
|
|
+ " jra 3b\n"
|
|
+ ".previous\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 1b,4b\n"
|
|
+ " .long 12b,4b\n"
|
|
+ ".previous"
|
|
+ : "=d"(res), "=a"(dst), "=a"(src), "=d"(count)
|
|
+ : "i"(-EFAULT), "0"(count), "1"(dst), "2"(src), "3"(count)
|
|
+ : "d0", "memory");
|
|
+ return res;
|
|
+}
|
|
+EXPORT_SYMBOL(strncpy_from_user);
|
|
+
|
|
+/*
|
|
+ * 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 *src, long n)
|
|
+{
|
|
+ long res = -EFAULT;
|
|
+ if (!(access_ok(VERIFY_READ, src, 1))) /* --tym-- */
|
|
+ return res;
|
|
+
|
|
+ res = -(long)src;
|
|
+ __asm__ __volatile__
|
|
+ ("1:\n"
|
|
+ " tstl %2\n"
|
|
+ " jeq 3f\n"
|
|
+ "2: moveb (%1)+,%%d0\n"
|
|
+ "22:\n"
|
|
+ " subql #1,%2\n"
|
|
+ " tstb %%d0\n"
|
|
+ " jne 1b\n"
|
|
+ " jra 4f\n"
|
|
+ "3:\n"
|
|
+ " addql #1,%0\n"
|
|
+ "4:\n"
|
|
+ " addl %1,%0\n"
|
|
+ "5:\n"
|
|
+ ".section .fixup,\"ax\"\n"
|
|
+ " .even\n"
|
|
+ "6: moveq %3,%0\n"
|
|
+ " jra 5b\n"
|
|
+ ".previous\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 2b,6b\n"
|
|
+ " .long 22b,6b\n"
|
|
+ ".previous"
|
|
+ : "=d"(res), "=a"(src), "=d"(n)
|
|
+ : "i"(0), "0"(res), "1"(src), "2"(n)
|
|
+ : "d0");
|
|
+ return res;
|
|
+}
|
|
+EXPORT_SYMBOL(strnlen_user);
|
|
+
|
|
+
|
|
+/*
|
|
+ * Zero Userspace
|
|
+ */
|
|
+
|
|
+unsigned long __clear_user(void *to, unsigned long n)
|
|
+{
|
|
+ __asm__ __volatile__
|
|
+ (" tstl %1\n"
|
|
+ " jeq 3f\n"
|
|
+ "1: movel %3,(%0)+\n"
|
|
+ "2: subql #1,%1\n"
|
|
+ " jne 1b\n"
|
|
+ "3: movel %2,%1\n"
|
|
+ " bclr #1,%1\n"
|
|
+ " jeq 4f\n"
|
|
+ "24:movew %3,(%0)+\n"
|
|
+ "4: bclr #0,%1\n"
|
|
+ " jeq 5f\n"
|
|
+ "25:moveb %3,(%0)+\n"
|
|
+ "5:\n"
|
|
+ ".section .fixup,\"ax\"\n"
|
|
+ " .even\n"
|
|
+ "61:addql #1,%1\n"
|
|
+ "6: lsll #2,%1\n"
|
|
+ " addl %2,%1\n"
|
|
+ " jra 5b\n"
|
|
+ "7: addql #2,%1\n"
|
|
+ " jra 5b\n"
|
|
+ "8: addql #1,%1\n"
|
|
+ " jra 5b\n"
|
|
+ ".previous\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 1b,61b\n"
|
|
+ " .long 2b,6b\n"
|
|
+ " .long 3b,61b\n"
|
|
+ " .long 24b,7b\n"
|
|
+ " .long 4b,7b\n"
|
|
+ " .long 25b,8b\n"
|
|
+ " .long 5b,8b\n"
|
|
+ ".previous"
|
|
+ : "=a"(to), "=d"(n)
|
|
+ : "r"(n & 3), "d"(0), "0"(to), "1"(n/4));
|
|
+ return n;
|
|
+}
|
|
+EXPORT_SYMBOL(__clear_user);
|
|
+
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
+
|
|
--- a/arch/m68k/mm/Makefile
|
|
+++ b/arch/m68k/mm/Makefile
|
|
@@ -6,3 +6,5 @@ obj-y := cache.o init.o fault.o hwtest.
|
|
|
|
obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o
|
|
obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o
|
|
+obj-$(CONFIG_MMU_CFV4E) += cf-mmu.o kmap.o memory.o
|
|
+obj-$(CONFIG_SRAM) += cf-sram.o
|
|
--- a/arch/m68k/mm/cache.c
|
|
+++ b/arch/m68k/mm/cache.c
|
|
@@ -4,13 +4,24 @@
|
|
* Instruction cache handling
|
|
*
|
|
* Copyright (C) 1995 Hamish Macdonald
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <asm/pgalloc.h>
|
|
#include <asm/traps.h>
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#include <asm/cfcache.h>
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
|
|
+#ifndef CONFIG_COLDFIRE
|
|
static unsigned long virt_to_phys_slow(unsigned long vaddr)
|
|
{
|
|
if (CPU_IS_060) {
|
|
@@ -69,11 +80,16 @@ static unsigned long virt_to_phys_slow(u
|
|
}
|
|
return 0;
|
|
}
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
+
|
|
|
|
/* Push n pages at kernel virtual address and clear the icache */
|
|
/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
|
|
void flush_icache_range(unsigned long address, unsigned long endaddr)
|
|
{
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+ flush_icache();
|
|
+#else /* !CONFIG_COLDFIRE */
|
|
|
|
if (CPU_IS_040_OR_060) {
|
|
address &= PAGE_MASK;
|
|
@@ -94,9 +110,11 @@ void flush_icache_range(unsigned long ad
|
|
: "=&d" (tmp)
|
|
: "di" (FLUSH_I));
|
|
}
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
}
|
|
EXPORT_SYMBOL(flush_icache_range);
|
|
|
|
+#ifndef CONFIG_COLDFIRE
|
|
void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
|
|
unsigned long addr, int len)
|
|
{
|
|
@@ -115,4 +133,5 @@ void flush_icache_user_range(struct vm_a
|
|
: "di" (FLUSH_I));
|
|
}
|
|
}
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
|
|
--- /dev/null
|
|
+++ b/arch/m68k/mm/cf-mmu.c
|
|
@@ -0,0 +1,311 @@
|
|
+/*
|
|
+ * linux/arch/m68k/mm/cf-mmu.c
|
|
+ *
|
|
+ * Based upon linux/arch/m68k/mm/sun3mmu.c
|
|
+ * Based upon linux/arch/ppc/mm/mmu_context.c
|
|
+ *
|
|
+ * Implementations of mm routines specific to the Coldfire MMU.
|
|
+ *
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
+ */
|
|
+
|
|
+#include <linux/signal.h>
|
|
+#include <linux/sched.h>
|
|
+#include <linux/mm.h>
|
|
+#include <linux/swap.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/string.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/init.h>
|
|
+#ifdef CONFIG_BLK_DEV_RAM
|
|
+#include <linux/blkdev.h>
|
|
+#endif
|
|
+#include <linux/bootmem.h>
|
|
+
|
|
+#include <asm/setup.h>
|
|
+#include <asm/uaccess.h>
|
|
+#include <asm/page.h>
|
|
+#include <asm/pgtable.h>
|
|
+#include <asm/system.h>
|
|
+#include <asm/machdep.h>
|
|
+#include <asm/io.h>
|
|
+#include <asm/mmu_context.h>
|
|
+#include <asm/cf_pgalloc.h>
|
|
+
|
|
+#include <asm/coldfire.h>
|
|
+#include <asm/tlbflush.h>
|
|
+
|
|
+#define KMAPAREA(x) ((x >= VMALLOC_START) && (x < KMAP_END))
|
|
+
|
|
+#undef DEBUG
|
|
+
|
|
+#ifdef CONFIG_VDSO
|
|
+unsigned long next_mmu_context;
|
|
+#else
|
|
+mm_context_t next_mmu_context;
|
|
+#endif
|
|
+
|
|
+unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
|
|
+
|
|
+atomic_t nr_free_contexts;
|
|
+struct mm_struct *context_mm[LAST_CONTEXT+1];
|
|
+const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
|
|
+
|
|
+extern unsigned long num_pages;
|
|
+EXPORT_SYMBOL(num_pages);
|
|
+/*
|
|
+ * Free memory used for system initialization.
|
|
+ */
|
|
+void free_initmem(void)
|
|
+{
|
|
+#if 0
|
|
+ unsigned long addr;
|
|
+ unsigned long start = (unsigned long)&__init_begin;
|
|
+ unsigned long end = (unsigned long)&__init_end;
|
|
+
|
|
+ printk(KERN_INFO "free_initmem: __init_begin = 0x%lx"
|
|
+ " __init_end = 0x%lx\n", start, end);
|
|
+
|
|
+ addr = (unsigned long)&__init_begin;
|
|
+ for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) {
|
|
+ /* not currently used */
|
|
+ virt_to_page(addr)->flags &= ~(1 << PG_reserved);
|
|
+ init_page_count(virt_to_page(addr));
|
|
+ free_page(addr);
|
|
+ totalram_pages++;
|
|
+ }
|
|
+#endif
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Initialize the paging system.
|
|
+ */
|
|
+void __init paging_init(void)
|
|
+{
|
|
+ pgd_t *pg_dir;
|
|
+ pte_t *pg_table;
|
|
+ int i;
|
|
+ unsigned long address;
|
|
+ unsigned long next_pgtable;
|
|
+ unsigned long zones_size[MAX_NR_ZONES];
|
|
+ unsigned long size;
|
|
+ enum zone_type zone;
|
|
+
|
|
+ /* allocate zero page */
|
|
+ empty_zero_page = (void *)alloc_bootmem_pages(PAGE_SIZE);
|
|
+ memset((void *)empty_zero_page, 0, PAGE_SIZE);
|
|
+
|
|
+ /* zero kernel page directory */
|
|
+ pg_dir = swapper_pg_dir;
|
|
+ memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
|
|
+ /*
|
|
+ * setup page tables for PHYSRAM
|
|
+ */
|
|
+
|
|
+ /* starting loc in page directory */
|
|
+ pg_dir += PAGE_OFFSET >> PGDIR_SHIFT;
|
|
+
|
|
+ /* allocate page tables */
|
|
+ size = num_pages * sizeof(pte_t);
|
|
+ size = (size + PAGE_SIZE) & ~(PAGE_SIZE-1);
|
|
+ next_pgtable = (unsigned long)alloc_bootmem_pages(size);
|
|
+ address = PAGE_OFFSET;
|
|
+ while (address < (unsigned long)high_memory) {
|
|
+ /* setup page table in page directory */
|
|
+ pg_table = (pte_t *)next_pgtable;
|
|
+ next_pgtable += PTRS_PER_PTE * sizeof(pte_t);
|
|
+ pgd_val(*pg_dir) = (unsigned long)pg_table;
|
|
+ pg_dir++;
|
|
+
|
|
+ /* create PTEs in page table */
|
|
+ for (i = 0; i < PTRS_PER_PTE; ++i, ++pg_table) {
|
|
+ pte_t pte = pfn_pte(virt_to_pfn(address), PAGE_INIT);
|
|
+ if (address >= (unsigned long)high_memory)
|
|
+ pte_val(pte) = 0;
|
|
+
|
|
+ set_pte(pg_table, pte);
|
|
+ address += PAGE_SIZE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * setup page tables for DMA area
|
|
+ */
|
|
+
|
|
+ /* starting loc in page directory */
|
|
+ pg_dir = swapper_pg_dir;
|
|
+ pg_dir += CONFIG_DMA_BASE >> PGDIR_SHIFT;
|
|
+
|
|
+ /* allocate page tables */
|
|
+ size = (CONFIG_DMA_SIZE >> PAGE_SHIFT) * sizeof(pte_t);
|
|
+ size = (size + PAGE_SIZE) & ~(PAGE_SIZE-1);
|
|
+ next_pgtable = (unsigned long)alloc_bootmem_pages(size);
|
|
+ address = CONFIG_DMA_BASE;
|
|
+ while (address < (CONFIG_DMA_BASE + CONFIG_DMA_SIZE)) {
|
|
+ /* setup page table in page directory */
|
|
+ pg_table = (pte_t *)next_pgtable;
|
|
+ next_pgtable += PTRS_PER_PTE * sizeof(pte_t);
|
|
+ pgd_val(*pg_dir) = (unsigned long)pg_table;
|
|
+ pg_dir++;
|
|
+
|
|
+ /* create PTEs in page table */
|
|
+ for (i = 0; i < PTRS_PER_PTE; ++i, ++pg_table) {
|
|
+ pte_t pte = pfn_pte(virt_to_pfn(address), PAGE_INIT);
|
|
+ if (address >= (CONFIG_DMA_BASE + CONFIG_DMA_SIZE))
|
|
+ pte_val(pte) = 0;
|
|
+
|
|
+ set_pte(pg_table, pte);
|
|
+ address += PAGE_SIZE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * setup zones
|
|
+ */
|
|
+
|
|
+ current->mm = NULL;
|
|
+
|
|
+ /* clear zones */
|
|
+ for (zone = 0; zone < MAX_NR_ZONES; zone++)
|
|
+ zones_size[zone] = 0x0;
|
|
+
|
|
+ zones_size[ZONE_DMA] = CONFIG_DMA_SIZE >> PAGE_SHIFT;
|
|
+ zones_size[ZONE_NORMAL] = (((unsigned long)high_memory -
|
|
+ PAGE_OFFSET) >> PAGE_SHIFT) -
|
|
+ zones_size[ZONE_DMA];
|
|
+
|
|
+ free_area_init(zones_size);
|
|
+}
|
|
+/*
|
|
+ * Handle a missed TLB
|
|
+ */
|
|
+int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
|
|
+{
|
|
+ struct mm_struct *mm;
|
|
+ pgd_t *pgd;
|
|
+ pmd_t *pmd;
|
|
+ pte_t *pte;
|
|
+ unsigned long mmuar;
|
|
+ int asid;
|
|
+ unsigned long flags;
|
|
+
|
|
+ local_save_flags(flags);
|
|
+ local_irq_disable();
|
|
+
|
|
+ mmuar = (dtlb) ? regs->mmuar
|
|
+ : regs->pc + (extension_word * sizeof(long));
|
|
+
|
|
+ mm = (!user_mode(regs) && KMAPAREA(mmuar)) ? &init_mm : current->mm;
|
|
+
|
|
+ if (!mm) {
|
|
+ local_irq_restore(flags);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ pgd = pgd_offset(mm, mmuar);
|
|
+ if (pgd_none(*pgd)) {
|
|
+ local_irq_restore(flags);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ pmd = pmd_offset(pgd, mmuar);
|
|
+ if (pmd_none(*pmd)) {
|
|
+ local_irq_restore(flags);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ pte = (KMAPAREA(mmuar)) ? pte_offset_kernel(pmd, mmuar)
|
|
+ : pte_offset_map(pmd, mmuar);
|
|
+ if (pte_none(*pte) || !pte_present(*pte)) {
|
|
+ local_irq_restore(flags);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (write) {
|
|
+ if (!pte_write(*pte)) {
|
|
+ local_irq_restore(flags);
|
|
+ return -1;
|
|
+ }
|
|
+ set_pte(pte, pte_mkdirty(*pte));
|
|
+ }
|
|
+
|
|
+ set_pte(pte, pte_mkyoung(*pte));
|
|
+ asid = cpu_context(mm) & 0xff;
|
|
+ if (!pte_dirty(*pte) && !KMAPAREA(mmuar))
|
|
+ set_pte(pte, pte_wrprotect(*pte));
|
|
+
|
|
+ *MMUTR = (mmuar & PAGE_MASK) | (asid << CF_ASID_MMU_SHIFT)
|
|
+ | (((int)(pte->pte) & (int)CF_PAGE_MMUTR_MASK)
|
|
+ >> CF_PAGE_MMUTR_SHIFT) | MMUTR_V;
|
|
+
|
|
+ *MMUDR = (pte_val(*pte) & PAGE_MASK)
|
|
+ | ((pte->pte) & CF_PAGE_MMUDR_MASK)
|
|
+ | MMUDR_SZ8K | MMUDR_X;
|
|
+
|
|
+ if (dtlb)
|
|
+ *MMUOR = MMUOR_ACC | MMUOR_UAA;
|
|
+ else
|
|
+ *MMUOR = MMUOR_ITLB | MMUOR_ACC | MMUOR_UAA;
|
|
+
|
|
+ asm("nop");
|
|
+
|
|
+#ifdef DEBUG
|
|
+ printk(KERN_INFO "cf_tlb_miss: va=%lx, pa=%lx\n", (mmuar & PAGE_MASK),
|
|
+ (pte_val(*pte) & PAGE_MASK));
|
|
+#endif
|
|
+ local_irq_restore(flags);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * Context Management
|
|
+ *
|
|
+ * Based on arch/ppc/mmu_context.c
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Initialize the context management system.
|
|
+ */
|
|
+void __init mmu_context_init(void)
|
|
+{
|
|
+ /*
|
|
+ * Some processors have too few contexts to reserve one for
|
|
+ * init_mm, and require using context 0 for a normal task.
|
|
+ * Other processors reserve the use of context zero for the kernel.
|
|
+ * This code assumes FIRST_CONTEXT < 32.
|
|
+ */
|
|
+ context_map[0] = (1 << FIRST_CONTEXT) - 1;
|
|
+ next_mmu_context = FIRST_CONTEXT;
|
|
+ atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Steal a context from a task that has one at the moment.
|
|
+ * This is only used on 8xx and 4xx and we presently assume that
|
|
+ * they don't do SMP. If they do then thicfpgalloc.hs will have to check
|
|
+ * whether the MM we steal is in use.
|
|
+ * We also assume that this is only used on systems that don't
|
|
+ * use an MMU hash table - this is true for 8xx and 4xx.
|
|
+ * This isn't an LRU system, it just frees up each context in
|
|
+ * turn (sort-of pseudo-random replacement :). This would be the
|
|
+ * place to implement an LRU scheme if anyone was motivated to do it.
|
|
+ * -- paulus
|
|
+ */
|
|
+void steal_context(void)
|
|
+{
|
|
+ struct mm_struct *mm;
|
|
+ /* free up context `next_mmu_context' */
|
|
+ /* if we shouldn't free context 0, don't... */
|
|
+ if (next_mmu_context < FIRST_CONTEXT)
|
|
+ next_mmu_context = FIRST_CONTEXT;
|
|
+ mm = context_mm[next_mmu_context];
|
|
+ flush_tlb_mm(mm);
|
|
+ destroy_context(mm);
|
|
+}
|
|
--- /dev/null
|
|
+++ b/arch/m68k/mm/cf-sram.c
|
|
@@ -0,0 +1,80 @@
|
|
+/*
|
|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Author: Lanttor.Guo@freescale.com
|
|
+ *
|
|
+ * Providing on-chip SRAM allocation and free APIs to kernel
|
|
+ * The implemention uses gen_pool_alloc/gen_pool_free interface
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ */
|
|
+
|
|
+#include <linux/module.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/genalloc.h>
|
|
+
|
|
+/* sram memory min allocation size per once */
|
|
+static long blk_size = CONFIG_SRAM_ALLOC_GRANULARITY;
|
|
+static struct gen_pool *sram_pool;
|
|
+
|
|
+/*
|
|
+ * Set up memory pools to manage on-chip sram.
|
|
+ * @ start the start address of SRAM
|
|
+ * @ size the size of SRAM
|
|
+ * return return 0 express success
|
|
+ */
|
|
+int declare_sram_pool(void *start, size_t size)
|
|
+{
|
|
+ int status = 0;
|
|
+
|
|
+ pr_debug("%s %p %d\n", __func__, start, size);
|
|
+
|
|
+ sram_pool = gen_pool_create(ilog2(blk_size), -1);
|
|
+ if (!sram_pool) {
|
|
+ printk(KERN_ERR "gen_pool_creat faile at %s()\n", __func__);
|
|
+ status = -ENOMEM;
|
|
+ }
|
|
+
|
|
+ status = gen_pool_add(sram_pool, (unsigned long)start, size, -1);
|
|
+ if (status < 0)
|
|
+ printk(KERN_ERR "gen_pool_add failed at %s()\n", __func__);
|
|
+
|
|
+ return status;
|
|
+
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Allocate memory from sram pool
|
|
+ * @ len the size of allocated memory
|
|
+ * return return the start addr of allocated memory
|
|
+ */
|
|
+void *sram_alloc(size_t len)
|
|
+{
|
|
+ unsigned long vaddr;
|
|
+
|
|
+ if (!len) {
|
|
+ printk(KERN_ERR "the len parameter of sram_alloc() is zero\n");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ vaddr = gen_pool_alloc(sram_pool, len);
|
|
+ if (!vaddr)
|
|
+ return NULL;
|
|
+
|
|
+ return (void *)vaddr;
|
|
+}
|
|
+EXPORT_SYMBOL(sram_alloc);
|
|
+
|
|
+/*
|
|
+ * Free memory to sram pool
|
|
+ * @ addr the addr of allocated memory
|
|
+ * @ len the size of allocated memory
|
|
+ */
|
|
+void sram_free(void *addr, size_t len)
|
|
+{
|
|
+ gen_pool_free(sram_pool, (unsigned long)addr, len);
|
|
+}
|
|
+EXPORT_SYMBOL(sram_free);
|
|
--- a/arch/m68k/mm/hwtest.c
|
|
+++ b/arch/m68k/mm/hwtest.c
|
|
@@ -12,6 +12,14 @@
|
|
* them here complete with the comments from the original atari
|
|
* config.c...
|
|
* -- PMM <pmaydell@chiark.greenend.org.uk>, 05/1998
|
|
+ *
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*/
|
|
|
|
/* This function tests for the presence of an address, specially a
|
|
@@ -25,6 +33,7 @@
|
|
|
|
#include <linux/module.h>
|
|
|
|
+#ifndef CONFIG_COLDFIRE
|
|
int hwreg_present( volatile void *regp )
|
|
{
|
|
int ret = 0;
|
|
@@ -82,4 +91,5 @@ int hwreg_write( volatile void *regp, un
|
|
return( ret );
|
|
}
|
|
EXPORT_SYMBOL(hwreg_write);
|
|
+#endif
|
|
|
|
--- a/arch/m68k/mm/init.c
|
|
+++ b/arch/m68k/mm/init.c
|
|
@@ -2,6 +2,13 @@
|
|
* linux/arch/m68k/mm/init.c
|
|
*
|
|
* Copyright (C) 1995 Hamish Macdonald
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*
|
|
* Contains common initialization routines, specific init code moved
|
|
* to motorola.c and sun3mmu.c
|
|
@@ -32,6 +39,7 @@
|
|
#include <asm/sections.h>
|
|
#include <asm/tlb.h>
|
|
|
|
+
|
|
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
|
|
|
|
pg_data_t pg_data_map[MAX_NUMNODES];
|
|
@@ -113,7 +121,7 @@ void __init mem_init(void)
|
|
}
|
|
}
|
|
|
|
-#ifndef CONFIG_SUN3
|
|
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
|
|
/* insert pointer tables allocated so far into the tablelist */
|
|
init_pointer_table((unsigned long)kernel_pg_dir);
|
|
for (i = 0; i < PTRS_PER_PGD; i++) {
|
|
@@ -132,6 +140,11 @@ void __init mem_init(void)
|
|
codepages << (PAGE_SHIFT-10),
|
|
datapages << (PAGE_SHIFT-10),
|
|
initpages << (PAGE_SHIFT-10));
|
|
+
|
|
+#ifdef CONFIG_VDSO
|
|
+ /* init the vdso page */
|
|
+ vdso_init();
|
|
+#endif
|
|
}
|
|
|
|
#ifdef CONFIG_BLK_DEV_INITRD
|
|
--- a/arch/m68k/mm/kmap.c
|
|
+++ b/arch/m68k/mm/kmap.c
|
|
@@ -2,6 +2,13 @@
|
|
* linux/arch/m68k/mm/kmap.c
|
|
*
|
|
* Copyright (C) 1997 Roman Hodek
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*
|
|
* 10/01/99 cleaned up the code and changing to the same interface
|
|
* used by other architectures /Roman Zippel
|
|
@@ -24,7 +31,11 @@
|
|
|
|
#undef DEBUG
|
|
|
|
+#ifndef CONFIG_COLDFIRE
|
|
#define PTRTREESIZE (256*1024)
|
|
+#else
|
|
+#define PTRTREESIZE PAGE_SIZE
|
|
+#endif
|
|
|
|
/*
|
|
* For 040/060 we can use the virtual memory area like other architectures,
|
|
@@ -50,7 +61,11 @@ static inline void free_io_area(void *ad
|
|
|
|
#else
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#define IO_SIZE PAGE_SIZE
|
|
+#else
|
|
#define IO_SIZE (256*1024)
|
|
+#endif
|
|
|
|
static struct vm_struct *iolist;
|
|
|
|
@@ -126,8 +141,58 @@ void __iomem *__ioremap(unsigned long ph
|
|
}
|
|
#endif
|
|
|
|
+#ifdef CONFIG_M5445X
|
|
+ if (physaddr >= 0xf0000000) {
|
|
+ /*
|
|
+ * On the M5445x processors an ACR is setup to map
|
|
+ * the 0xF0000000 range into kernel memory as
|
|
+ * non-cacheable.
|
|
+ */
|
|
+ return (void __iomem *)physaddr;
|
|
+ }
|
|
+ if ((physaddr >= KMAP_START) && (physaddr <= KMAP_END)) {
|
|
+ /* if physaddr belongs to virtual address range for ioremap,
|
|
+ * then return physaddr because it has been ioremapped
|
|
+ */
|
|
+ return (void __iomem *)physaddr;
|
|
+ }
|
|
+#endif
|
|
+#ifdef CONFIG_M547X_8X
|
|
+ if (physaddr >= 0xf0000000) {
|
|
+ /*
|
|
+ * On the M547x/M548x processors an ACR is setup to map
|
|
+ * the 0xF0000000 range into kernel memory as
|
|
+ * non-cacheable.
|
|
+ */
|
|
+ return (void __iomem *)physaddr;
|
|
+ }
|
|
+
|
|
+ if ((physaddr >= 0xd0000000) && (physaddr + size < 0xd800ffff)) {
|
|
+ printk(KERN_ERR "ioremap:PCI 0x%lx,0x%lx(%d)"
|
|
+ " - PCI area hit\n", physaddr, size, cacheflag);
|
|
+ return (void *)physaddr;
|
|
+ }
|
|
+#endif
|
|
+#ifdef CONFIG_M5441X
|
|
+ if (physaddr >= 0xe0000000) {
|
|
+ /*
|
|
+ * On the M5441x processors an ACR is setup to map
|
|
+ * the 0xe0000000 range into kernel memory as
|
|
+ * non-cacheable.
|
|
+ */
|
|
+ return (void __iomem *)physaddr;
|
|
+ }
|
|
+ if ((physaddr >= KMAP_START) && (physaddr <= KMAP_END)) {
|
|
+ /* if physaddr belongs to virtual address range for ioremap,
|
|
+ * then return physaddr because it has been ioremapped
|
|
+ */
|
|
+ return (void __iomem *)physaddr;
|
|
+ }
|
|
+#endif
|
|
+
|
|
#ifdef DEBUG
|
|
- printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
|
|
+ printk(KERN_ERR "ioremap: paddr=0x%lx,size=0x%lx(%d) - ",
|
|
+ physaddr, size, cacheflag);
|
|
#endif
|
|
/*
|
|
* Mappings have to be aligned
|
|
@@ -146,7 +211,8 @@ void __iomem *__ioremap(unsigned long ph
|
|
virtaddr = (unsigned long)area->addr;
|
|
retaddr = virtaddr + offset;
|
|
#ifdef DEBUG
|
|
- printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr);
|
|
+ printk(KERN_ERR " paddr=0x%lx,vaddr=0x%lx,retaddr=0x%lx",
|
|
+ physaddr, virtaddr, retaddr);
|
|
#endif
|
|
|
|
/*
|
|
@@ -171,7 +237,12 @@ void __iomem *__ioremap(unsigned long ph
|
|
break;
|
|
}
|
|
} else {
|
|
+#ifndef CONFIG_COLDFIRE
|
|
physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
|
|
+#else
|
|
+ physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY | \
|
|
+ _PAGE_READWRITE);
|
|
+#endif
|
|
switch (cacheflag) {
|
|
case IOMAP_NOCACHE_SER:
|
|
case IOMAP_NOCACHE_NONSER:
|
|
@@ -251,6 +322,13 @@ void __iounmap(void *addr, unsigned long
|
|
pmd_t *pmd_dir;
|
|
pte_t *pte_dir;
|
|
|
|
+#ifdef CONFIG_M547X_8X
|
|
+ if ((addr >= (void *)0xd0000000)
|
|
+ && (addr + size < (void *)0xd800ffff)) {
|
|
+ printk(KERN_ERR "%s: PCI address\n", __func__);
|
|
+ return;
|
|
+ }
|
|
+#endif
|
|
while ((long)size > 0) {
|
|
pgd_dir = pgd_offset_k(virtaddr);
|
|
if (pgd_bad(*pgd_dir)) {
|
|
--- a/arch/m68k/mm/memory.c
|
|
+++ b/arch/m68k/mm/memory.c
|
|
@@ -2,6 +2,13 @@
|
|
* linux/arch/m68k/mm/memory.c
|
|
*
|
|
* Copyright (C) 1995 Hamish Macdonald
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file COPYING in the main directory of this archive
|
|
+ * for more details.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
@@ -127,6 +134,7 @@ int free_pointer_table (pmd_t *ptable)
|
|
return 0;
|
|
}
|
|
|
|
+#ifndef CONFIG_COLDFIRE
|
|
/* invalidate page in both caches */
|
|
static inline void clear040(unsigned long paddr)
|
|
{
|
|
@@ -173,6 +181,7 @@ static inline void pushcl040(unsigned lo
|
|
clear040(paddr);
|
|
local_irq_restore(flags);
|
|
}
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
|
|
/*
|
|
* 040: Hit every page containing an address in the range paddr..paddr+len-1.
|
|
@@ -203,6 +212,9 @@ static inline void pushcl040(unsigned lo
|
|
|
|
void cache_clear (unsigned long paddr, int len)
|
|
{
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+ flush_bcache();
|
|
+#else
|
|
if (CPU_IS_040_OR_060) {
|
|
int tmp;
|
|
|
|
@@ -237,6 +249,7 @@ void cache_clear (unsigned long paddr, i
|
|
if(mach_l2_flush)
|
|
mach_l2_flush(0);
|
|
#endif
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
}
|
|
EXPORT_SYMBOL(cache_clear);
|
|
|
|
@@ -250,6 +263,9 @@ EXPORT_SYMBOL(cache_clear);
|
|
|
|
void cache_push (unsigned long paddr, int len)
|
|
{
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+ flush_bcache();
|
|
+#else
|
|
if (CPU_IS_040_OR_060) {
|
|
int tmp = PAGE_SIZE;
|
|
|
|
@@ -290,6 +306,7 @@ void cache_push (unsigned long paddr, in
|
|
if(mach_l2_flush)
|
|
mach_l2_flush(1);
|
|
#endif
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
}
|
|
EXPORT_SYMBOL(cache_push);
|
|
|
|
--- a/fs/namespace.c
|
|
+++ b/fs/namespace.c
|
|
@@ -3,6 +3,10 @@
|
|
*
|
|
* (C) Copyright Al Viro 2000, 2001
|
|
* Released under GPL v2.
|
|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
+ * Change to align on page size for coldfire
|
|
+ * Jason Jin Jason.Jin@freescale.com
|
|
+ * Shrek Wu B16972@freescale.com
|
|
*
|
|
* Based on code from fs/super.c, copyright Linus Torvalds and others.
|
|
* Heavily rewritten.
|
|
@@ -2161,7 +2165,11 @@ int copy_mount_options(const void __user
|
|
/* copy_from_user cannot cross TASK_SIZE ! */
|
|
size = TASK_SIZE - (unsigned long)data;
|
|
if (size > PAGE_SIZE)
|
|
+#ifndef CONFIG_COLDFIRE
|
|
size = PAGE_SIZE;
|
|
+#else
|
|
+ size = PAGE_SIZE - ((unsigned long)data & ~PAGE_MASK);
|
|
+#endif
|
|
|
|
i = size - exact_copy_from_user((void *)page, data, size);
|
|
if (!i) {
|
|
--- a/include/linux/fsl_devices.h
|
|
+++ b/include/linux/fsl_devices.h
|
|
@@ -6,7 +6,7 @@
|
|
*
|
|
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
|
|
*
|
|
- * Copyright 2004 Freescale Semiconductor, Inc
|
|
+ * Copyright (C) 2004-2011 Freescale Semiconductor, 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 License as published by the
|
|
@@ -18,7 +18,7 @@
|
|
#define _FSL_DEVICE_H_
|
|
|
|
#include <linux/types.h>
|
|
-
|
|
+#include <linux/interrupt.h>
|
|
/*
|
|
* Some conventions on how we handle peripherals on Freescale chips
|
|
*
|
|
@@ -119,4 +119,14 @@ int fsl_deep_sleep(void);
|
|
static inline int fsl_deep_sleep(void) { return 0; }
|
|
#endif
|
|
|
|
+struct fsl_ata_platform_data {
|
|
+#ifdef CONFIG_FSL_PATA_USE_DMA
|
|
+ int udma_mask; /* UDMA modes h/w can handle */
|
|
+ int fifo_alarm; /* value for fifo_alarm reg */
|
|
+ int max_sg; /* longest sglist h/w can handle */
|
|
+#endif
|
|
+ int (*init)(struct platform_device *pdev);
|
|
+ void (*exit)(void);
|
|
+ int (*get_clk_rate)(void);
|
|
+};
|
|
#endif /* _FSL_DEVICE_H_ */
|