GIT 5854179676877dc73737acf9f1efc8b09bddaff9 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git commit Author: Stuart Menefy Date: Tue Nov 21 15:38:05 2006 +0900 sh: pmd rework. Remove extra bits from the pmd structure and store a kernel logical address rather than a physical address. This allows it to be directly dereferenced. Another piece of wierdness inherited from x86. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 2041a5298daafa8a93359cb1d6d5365f7e17e823 Author: Stuart Menefy Date: Tue Nov 21 13:53:44 2006 +0900 sh: Use MMU.TTB register as pointer to current pgd. Add TTB accessor functions and give it a sensible default value. We will use this later for optimizing the fault path. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 67db65193798f97e4d732c8ad6ff9c0d37831349 Author: Stuart Menefy Date: Tue Nov 21 13:34:04 2006 +0900 sh: Set up correct siginfo structures for page faults. Remove the previous saving of fault codes into the thread_struct as they are never used, and appeared to be inherited from x86. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 65abc6db88f9ac9867442ad566c9de583dec217e Author: Stuart Menefy Date: Tue Nov 21 11:16:57 2006 +0900 sh: gcc4 support. This fixes up the kernel for gcc4. The existing exception handlers needed some wrapping for pt_regs access, acessing the registers via a RELOC_HIDE() pointer. The strcpy() issues popped up here too, so add -ffreestanding and kill off the symbol export. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 2fbc3782a26f1b0ba3348356536a23adaef5b2cd Author: Paul Mundt Date: Tue Nov 21 11:12:19 2006 +0900 sh: Explicit endian selection support. Previously big endian was simply assumed if little endian was not set, which led to some cflags ordering issues. There's not much point to not having a big endian option, so shove one in a choice and wire it up in the Makefile. This lets us clean up some of the cflags ordering while we're at it. Signed-off-by: Paul Mundt commit c4da9d0b27b445cdd29d3211aff405c7a326b6df Author: Paul Mundt Date: Tue Nov 21 11:09:41 2006 +0900 sh: p3map_sem sem2mutex conversion. Simple sem2mutex conversion for the p3map semaphores. Signed-off-by: Paul Mundt commit 3d1f2cb6d07ae4fe24fc303e04ed8b23917c2660 Author: Paul Mundt Date: Mon Nov 20 14:30:26 2006 +0900 sh: Preliminary support for SH-X2 MMU. This adds some preliminary support for the SH-X2 MMU, used by newer SH-4A parts (particularly SH7785). This MMU implements a 'compat' mode with SH-X MMUs and an 'extended' mode for SH-X2 extended features. Extended features include additional page sizes (8kB, 4MB, 64MB), as well as the addition of page execute permissions. The extended mode attributes are placed in a second data array, which requires us to switch to 64-bit PTEs when in X2 mode. With the addition of the exec perms, we also overhaul the mmap prots somewhat, now that it's possible to handle them more intelligently. Signed-off-by: Paul Mundt commit 3b629455db1ae2961216004f5fe24e87304c661f Author: Paul Mundt Date: Mon Nov 20 14:14:29 2006 +0900 sh: Hook SH7785 in to the build system. Simple 7785 placeholders to start hooking up other bits of code. Signed-off-by: Paul Mundt commit 7d199fb7ec1cf76a91bc87ea4c8d99627fda25d0 Author: Paul Mundt Date: Mon Nov 20 13:55:34 2006 +0900 sh: Drop CPU subtype IRQ headers. This drops the various IRQ headers that were floating around and primarily providing hardcoded IRQ definitions for the various CPU subtypes. This quickly got to be an unmaintainable mess, made even more evident by the subtle breakage introduced by the SH-2 and SH-2A changes. Now that subtypes are able to register IRQ maps directly, just rip all of the headers out. Signed-off-by: Paul Mundt commit d8bd023dcf885dbf692108087188ec93f99b36c2 Author: Paul Mundt Date: Mon Nov 20 11:18:30 2006 +0900 sh: Configurable timer IRQ. All of the various CPU subtypes currently hardcode TIMER_IRQ, switch this to a config option in the few places we need this. This allows further removal of hardcoded IRQ headers.. Signed-off-by: Paul Mundt commit c0cf95140f4d652879216bf36fa7224b16c1d891 Author: Paul Mundt Date: Tue Nov 7 10:29:23 2006 +0000 sh: Fixup entry-common path breakage for SH-3. The nommu patches broke the path for the common bits, get it building for the SH-3/4 case again. Signed-off-by: Paul Mundt commit e2cf429221a4216984d1ef528129c495fd1264c1 Author: Paul Mundt Date: Sun Nov 5 16:48:42 2006 +0900 sh: SE7206 build fixes. A number of API changes happened underneath the 7206 patches, update for everything that broke. Signed-off-by: Paul Mundt commit 55796961e830c999e390d87e1ef4f58c4eae67e1 Author: Yoshinori Sato Date: Sun Nov 5 16:21:09 2006 +0900 sh: Add support for Solution Engine 7206 and 7619 boards. This adds support for the Solution Engine 7206 and 7619. Signed-off-by: Yoshinori Sato Signed-off-by: Paul Mundt commit c4db8514aedd0278f392253b45b09609c1e51148 Author: Yoshinori Sato Date: Sun Nov 5 16:18:08 2006 +0900 sh: Add SH-2A platform headers. Mostly SH-2 wrappers.. Signed-off-by: Yoshinori Sato Signed-off-by: Paul Mundt commit 947b188d024f22b1df59c107f38b6e24a3f5b259 Author: Yoshinori Sato Date: Sun Nov 5 16:15:19 2006 +0900 sh: Exception vector rework and SH-2/SH-2A support. This splits out common bits from the existing exception handler for use between SH-2/SH-2A and SH-3/4, and adds support for the SH-2/2A exceptions. Signed-off-by: Yoshinori Sato Signed-off-by: Paul Mundt commit 7166f32672f428f1e0ac0e2b2014269c80bd53c2 Author: Yoshinori Sato Date: Sun Nov 5 15:58:47 2006 +0900 sh: Wire up division and address error exceptions on SH-2A. SH-2A has special division hardware as opposed to a full-fledged FPU, wire up the exception handlers for this. Signed-off-by: Yoshinori Sato Signed-off-by: Paul Mundt commit 2c0085a14698466c0fc0e1746dfcbdb3a7341c89 Author: Yoshinori Sato Date: Sun Nov 5 15:40:13 2006 +0900 sh: Add support for SH7206 and SH7619 CPU subtypes. This implements initial support for the SH7206 (SH-2A) and SH7619 (SH-2) MMU-less CPUs. Signed-off-by: Yoshinori Sato Signed-off-by: Paul Mundt arch/sh/Kconfig | 66 ++- arch/sh/Makefile | 22 - arch/sh/boards/renesas/r7780rp/irq.c | 1 arch/sh/boards/se/7206/Makefile | 7 arch/sh/boards/se/7206/io.c | 123 +++++ arch/sh/boards/se/7206/irq.c | 139 +++++ arch/sh/boards/se/7206/led.c | 57 ++ arch/sh/boards/se/7206/setup.c | 79 +++ arch/sh/boards/se/7619/Makefile | 5 arch/sh/boards/se/7619/io.c | 102 ++++ arch/sh/boards/se/7619/setup.c | 43 ++ arch/sh/boot/compressed/misc.c | 3 arch/sh/configs/se7206_defconfig | 826 +++++++++++++++++++++++++++++++ arch/sh/drivers/pci/pci-sh7780.c | 14 + arch/sh/kernel/Makefile | 2 arch/sh/kernel/cpu/Makefile | 11 arch/sh/kernel/cpu/init.c | 2 arch/sh/kernel/cpu/irq/imask.c | 5 arch/sh/kernel/cpu/irq/intc2.c | 25 + arch/sh/kernel/cpu/irq/ipr.c | 22 + arch/sh/kernel/cpu/sh2/Makefile | 3 arch/sh/kernel/cpu/sh2/clock-sh7619.c | 81 +++ arch/sh/kernel/cpu/sh2/entry.S | 325 ++++++++++++ arch/sh/kernel/cpu/sh2/ex.S | 46 ++ arch/sh/kernel/cpu/sh2/probe.c | 16 - arch/sh/kernel/cpu/sh2/setup-sh7619.c | 53 ++ arch/sh/kernel/cpu/sh2a/Makefile | 10 arch/sh/kernel/cpu/sh2a/clock-sh7206.c | 85 +++ arch/sh/kernel/cpu/sh2a/probe.c | 39 + arch/sh/kernel/cpu/sh2a/setup-sh7206.c | 58 ++ arch/sh/kernel/cpu/sh3/Makefile | 2 arch/sh/kernel/cpu/sh3/entry.S | 526 ++++++++++++++++++++ arch/sh/kernel/cpu/sh4/Makefile | 3 arch/sh/kernel/cpu/sh4/fpu.c | 25 - arch/sh/kernel/cpu/sh4/setup-sh7780.c | 36 + arch/sh/kernel/entry-common.S | 372 ++++++++++++++ arch/sh/kernel/entry.S | 843 -------------------------------- arch/sh/kernel/head.S | 12 arch/sh/kernel/irq.c | 5 arch/sh/kernel/process.c | 32 + arch/sh/kernel/setup.c | 2 arch/sh/kernel/sh_ksyms.c | 2 arch/sh/kernel/signal.c | 36 + arch/sh/kernel/sys_sh.c | 7 arch/sh/kernel/timers/Makefile | 2 arch/sh/kernel/timers/timer-cmt.c | 203 ++++++++ arch/sh/kernel/timers/timer-mtu2.c | 208 ++++++++ arch/sh/kernel/timers/timer-tmu.c | 2 arch/sh/kernel/timers/timer.c | 6 arch/sh/kernel/traps.c | 194 +++++-- arch/sh/mm/Kconfig | 71 +++ arch/sh/mm/cache-sh2.c | 69 +-- arch/sh/mm/cache-sh4.c | 14 - arch/sh/mm/fault.c | 66 ++- arch/sh/mm/init.c | 44 +- arch/sh/mm/ioremap.c | 4 arch/sh/mm/pg-sh4.c | 35 - arch/sh/tools/mach-types | 2 drivers/serial/sh-sci.h | 36 + include/asm-sh/bugs.h | 8 include/asm-sh/cpu-sh2/cache.h | 22 + include/asm-sh/cpu-sh2/freq.h | 18 + include/asm-sh/cpu-sh2/mmu_context.h | 16 + include/asm-sh/cpu-sh2/timer.h | 6 include/asm-sh/cpu-sh2a/addrspace.h | 1 include/asm-sh/cpu-sh2a/cache.h | 39 + include/asm-sh/cpu-sh2a/cacheflush.h | 1 include/asm-sh/cpu-sh2a/dma.h | 1 include/asm-sh/cpu-sh2a/freq.h | 18 + include/asm-sh/cpu-sh2a/mmu_context.h | 1 include/asm-sh/cpu-sh2a/timer.h | 1 include/asm-sh/cpu-sh2a/ubc.h | 1 include/asm-sh/cpu-sh2a/watchdog.h | 1 include/asm-sh/elf.h | 2 include/asm-sh/entry-macros.S | 32 + include/asm-sh/irq-sh73180.h | 314 ------------ include/asm-sh/irq-sh7343.h | 317 ------------ include/asm-sh/irq-sh7780.h | 311 ------------ include/asm-sh/irq.h | 592 ---------------------- include/asm-sh/mmu_context.h | 44 +- include/asm-sh/page.h | 35 + include/asm-sh/pgalloc.h | 20 + include/asm-sh/pgtable-2level.h | 70 --- include/asm-sh/pgtable.h | 359 +++++++++++--- include/asm-sh/processor.h | 20 - include/asm-sh/se7206.h | 13 include/asm-sh/timer.h | 2 include/asm-sh/unistd.h | 32 + 88 files changed, 4580 insertions(+), 2846 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 6a461d4..6d2b1be 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -219,6 +219,20 @@ config SH_SHMIN help Select SHMIN if configureing for the SHMIN board +config SH_7206_SOLUTION_ENGINE + bool "SolutionEngine7206" + select CPU_SUBTYPE_SH7206 + help + Select 7206 SolutionEngine if configuring for a Hitachi SH7206 + evaluation board. + +config SH_7619_SOLUTION_ENGINE + bool "SolutionEngine7619" + select CPU_SUBTYPE_SH7619 + help + Select 7619 SolutionEngine if configuring for a Hitachi SH7619 + evaluation board. + config SH_UNKNOWN bool "BareCPU" help @@ -280,12 +294,20 @@ config CF_BASE_ADDR menu "Processor features" -config CPU_LITTLE_ENDIAN - bool "Little Endian" +choice + prompt "Endianess selection" + default CPU_LITTLE_ENDIAN help Some SuperH machines can be configured for either little or big - endian byte order. These modes require different kernels. Say Y if - your machine is little endian, N if it's a big endian machine. + endian byte order. These modes require different kernels. + +config CPU_LITTLE_ENDIAN + bool "Little Endian" + +config CPU_BIG_ENDIAN + bool "Big Endian" + +endchoice config SH_FPU bool "FPU support" @@ -364,10 +386,25 @@ depends on !GENERIC_TIME config SH_TMU bool "TMU timer support" + depends on CPU_SH3 || CPU_SH4 default y help This enables the use of the TMU as the system timer. +config SH_CMT + bool "CMT timer support" + depends on CPU_SH2 + default y + help + This enables the use of the CMT as the system timer. + +config SH_MTU2 + bool "MTU2 timer support" + depends on CPU_SH2A + default n + help + This enables the use of the MTU2 as the system timer. + endmenu source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" @@ -376,19 +413,34 @@ source "arch/sh/boards/renesas/rts7751r2 source "arch/sh/boards/renesas/r7780rp/Kconfig" +config SH_TIMER_IRQ + int + default "28" if CPU_SUBTYPE_SH7780 + default "86" if CPU_SUBTYPE_SH7619 + default "140" if CPU_SUBTYPE_SH7206 + default "16" + config SH_PCLK_FREQ int "Peripheral clock frequency (in Hz)" + default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343 + default "31250000" if CPU_SUBTYPE_SH7619 + default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \ + CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \ + CPU_SUBTYPE_SH7206 default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 default "60000000" if CPU_SUBTYPE_SH7751 - default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \ - CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 - default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343 default "66000000" if CPU_SUBTYPE_SH4_202 help This option is used to specify the peripheral clock frequency. This is necessary for determining the reference clock value on platforms lacking an RTC. +config SH_CLK_MD + int "CPU Mode Pin Setting" + depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206 + help + MD2 - MD0 Setting. + menu "CPU Frequency scaling" source "drivers/cpufreq/Kconfig" diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 26d62ff..7f4516c 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -13,10 +13,6 @@ # architecture-specific flags and depend # for "archclean" and "archdep" for cleaning up and making dependencies for # this architecture # - -cflags-y := -mb -cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml - isa-y := any isa-$(CONFIG_SH_DSP) := sh isa-$(CONFIG_CPU_SH2) := sh2 @@ -38,13 +34,16 @@ isa-y := $(isa-y)-nofpu endif endif -cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) - -cflags-$(CONFIG_CPU_SH2) += -m2 -cflags-$(CONFIG_CPU_SH3) += -m3 -cflags-$(CONFIG_CPU_SH4) += -m4 \ +cflags-$(CONFIG_CPU_SH2) := -m2 +cflags-$(CONFIG_CPU_SH3) := -m3 +cflags-$(CONFIG_CPU_SH4) := -m4 \ $(call cc-option,-mno-implicit-fp,-m4-nofpu) -cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,) +cflags-$(CONFIG_CPU_SH4A) := -m4a $(call cc-option,-m4a-nofpu,) + +cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mb +cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml + +cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding cflags-$(CONFIG_SH_DSP) += -Wa,-dsp cflags-$(CONFIG_SH_KGDB) += -g @@ -109,6 +108,8 @@ machdir-$(CONFIG_SH_SH4202_MICRODEV) := machdir-$(CONFIG_SH_LANDISK) := landisk machdir-$(CONFIG_SH_TITAN) := titan machdir-$(CONFIG_SH_SHMIN) := shmin +machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE) := se/7206 +machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE) := se/7619 machdir-$(CONFIG_SH_UNKNOWN) := unknown incdir-y := $(notdir $(machdir-y)) @@ -124,6 +125,7 @@ core-$(CONFIG_HD64465) += arch/sh/cchip core-$(CONFIG_VOYAGERGX) += arch/sh/cchips/voyagergx/ cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2 +cpuincdir-$(CONFIG_CPU_SH2A) := cpu-sh2a cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3 cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4 diff --git a/arch/sh/boards/renesas/r7780rp/irq.c b/arch/sh/boards/renesas/r7780rp/irq.c index aa15ec5..cc381e1 100644 --- a/arch/sh/boards/renesas/r7780rp/irq.c +++ b/arch/sh/boards/renesas/r7780rp/irq.c @@ -10,6 +10,7 @@ */ #include #include +#include #include #include diff --git a/arch/sh/boards/se/7206/Makefile b/arch/sh/boards/se/7206/Makefile new file mode 100644 index 0000000..63950f4 --- /dev/null +++ b/arch/sh/boards/se/7206/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the 7206 SolutionEngine specific parts of the kernel +# + +obj-y := setup.o io.o irq.o +obj-$(CONFIG_HEARTBEAT) += led.o + diff --git a/arch/sh/boards/se/7206/io.c b/arch/sh/boards/se/7206/io.c new file mode 100644 index 0000000..b557273 --- /dev/null +++ b/arch/sh/boards/se/7206/io.c @@ -0,0 +1,123 @@ +/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $ + * + * linux/arch/sh/boards/se/7206/io.c + * + * Copyright (C) 2006 Yoshinori Sato + * + * I/O routine for Hitachi 7206 SolutionEngine. + * + */ + +#include +#include +#include +#include + + +static inline void delay(void) +{ + ctrl_inw(0x20000000); /* P2 ROM Area */ +} + +/* MS7750 requires special versions of in*, out* routines, since + PC-like io ports are located at upper half byte of 16-bit word which + can be accessed only with 16-bit wide. */ + +static inline volatile __u16 * +port2adr(unsigned int port) +{ + if (port >= 0x2000) + return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); + else if (port >= 0x300 || port < 0x310) + return (volatile __u16 *) (PA_SMSC + (port - 0x300)); +} + +unsigned char se7206_inb(unsigned long port) +{ + return (*port2adr(port))&0xff; +} + +unsigned char se7206_inb_p(unsigned long port) +{ + unsigned long v; + + v = (*port2adr(port))&0xff; + delay(); + return v; +} + +unsigned short se7206_inw(unsigned long port) +{ + return *port2adr(port);; +} + +unsigned int se7206_inl(unsigned long port) +{ + maybebadio(port); + return 0; +} + +void se7206_outb(unsigned char value, unsigned long port) +{ + *(port2adr(port)) = value; +} + +void se7206_outb_p(unsigned char value, unsigned long port) +{ + *(port2adr(port)) = value; + delay(); +} + +void se7206_outw(unsigned short value, unsigned long port) +{ + *port2adr(port) = value; +} + +void se7206_outl(unsigned int value, unsigned long port) +{ + maybebadio(port); +} + +void se7206_insb(unsigned long port, void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + __u8 *ap = addr; + + while (count--) + *ap++ = *p; +} + +void se7206_insw(unsigned long port, void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + __u16 *ap = addr; + while (count--) + *ap++ = *p; +} + +void se7206_insl(unsigned long port, void *addr, unsigned long count) +{ + maybebadio(port); +} + +void se7206_outsb(unsigned long port, const void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + const __u8 *ap = addr; + + while (count--) + *p = *ap++; +} + +void se7206_outsw(unsigned long port, const void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + const __u16 *ap = addr; + while (count--) + *p = *ap++; +} + +void se7206_outsl(unsigned long port, const void *addr, unsigned long count) +{ + maybebadio(port); +} diff --git a/arch/sh/boards/se/7206/irq.c b/arch/sh/boards/se/7206/irq.c new file mode 100644 index 0000000..3fb0c5f --- /dev/null +++ b/arch/sh/boards/se/7206/irq.c @@ -0,0 +1,139 @@ +/* + * linux/arch/sh/boards/se/7206/irq.c + * + * Copyright (C) 2005,2006 Yoshinori Sato + * + * Hitachi SolutionEngine Support. + * + */ +#include +#include +#include +#include +#include + +#define INTSTS0 0x31800000 +#define INTSTS1 0x31800002 +#define INTMSK0 0x31800004 +#define INTMSK1 0x31800006 +#define INTSEL 0x31800008 + +static void disable_se7206_irq(unsigned int irq) +{ + unsigned short val; + unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq))); + unsigned short msk0,msk1; + + /* Set the priority in IPR to 0 */ + val = ctrl_inw(INTC_IPR01); + val &= mask; + ctrl_outw(val, INTC_IPR01); + /* FPGA mask set */ + msk0 = ctrl_inw(INTMSK0); + msk1 = ctrl_inw(INTMSK1); + + switch (irq) { + case IRQ0_IRQ: + msk0 |= 0x0010; + break; + case IRQ1_IRQ: + msk0 |= 0x000f; + break; + case IRQ2_IRQ: + msk0 |= 0x0f00; + msk1 |= 0x00ff; + break; + } + ctrl_outw(msk0, INTMSK0); + ctrl_outw(msk1, INTMSK1); +} + +static void enable_se7206_irq(unsigned int irq) +{ + unsigned short val; + unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq))); + unsigned short msk0,msk1; + + /* Set priority in IPR back to original value */ + val = ctrl_inw(INTC_IPR01); + val |= value; + ctrl_outw(val, INTC_IPR01); + + /* FPGA mask reset */ + msk0 = ctrl_inw(INTMSK0); + msk1 = ctrl_inw(INTMSK1); + + switch (irq) { + case IRQ0_IRQ: + msk0 &= ~0x0010; + break; + case IRQ1_IRQ: + msk0 &= ~0x000f; + break; + case IRQ2_IRQ: + msk0 &= ~0x0f00; + msk1 &= ~0x00ff; + break; + } + ctrl_outw(msk0, INTMSK0); + ctrl_outw(msk1, INTMSK1); +} + +static void eoi_se7206_irq(unsigned int irq) +{ + unsigned short sts0,sts1; + + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_se7206_irq(irq); + /* FPGA isr clear */ + sts0 = ctrl_inw(INTSTS0); + sts1 = ctrl_inw(INTSTS1); + + switch (irq) { + case IRQ0_IRQ: + sts0 &= ~0x0010; + break; + case IRQ1_IRQ: + sts0 &= ~0x000f; + break; + case IRQ2_IRQ: + sts0 &= ~0x0f00; + sts1 &= ~0x00ff; + break; + } + ctrl_outw(sts0, INTSTS0); + ctrl_outw(sts1, INTSTS1); +} + +static struct irq_chip se7206_irq_chip __read_mostly = { + .name = "SE7206-FPGA-IRQ", + .mask = disable_se7206_irq, + .unmask = enable_se7206_irq, + .mask_ack = disable_se7206_irq, + .eoi = eoi_se7206_irq, +}; + +static void make_se7206_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + set_irq_chip_and_handler_name(irq, &se7206_irq_chip, + handle_level_irq, "level"); + disable_se7206_irq(irq); +} + +/* + * Initialize IRQ setting + */ +void __init init_se7206_IRQ(void) +{ + make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */ + make_se7206_irq(IRQ1_IRQ); /* ATA */ + make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ + ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */ + + /* FPGA System register setup*/ + ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */ + ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */ + /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ + ctrl_outw(0x0001,INTSEL); +} diff --git a/arch/sh/boards/se/7206/led.c b/arch/sh/boards/se/7206/led.c new file mode 100644 index 0000000..ef79460 --- /dev/null +++ b/arch/sh/boards/se/7206/led.c @@ -0,0 +1,57 @@ +/* + * linux/arch/sh/kernel/led_se.c + * + * Copyright (C) 2000 Stuart Menefy + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains Solution Engine specific LED code. + */ + +#include +#include + +#ifdef CONFIG_HEARTBEAT + +#include + +/* Cycle the LED's in the clasic Knightrider/Sun pattern */ +void heartbeat_se(void) +{ + static unsigned int cnt = 0, period = 0; + volatile unsigned short* p = (volatile unsigned short*)PA_LED; + static unsigned bit = 0, up = 1; + + cnt += 1; + if (cnt < period) { + return; + } + + cnt = 0; + + /* Go through the points (roughly!): + * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 + */ + period = 110 - ( (300< +#include +#include +#include +#include + +static struct resource smc91x_resources[] = { + [0] = { + .start = 0x300, + .end = 0x300 + 0x020 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 64, + .end = 64, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = -1, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + +static int __init se7206_devices_setup(void) +{ + return platform_device_register(&smc91x_device); +} + +__initcall(se7206_devices_setup); + +void heartbeat_se(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_se __initmv = { + .mv_name = "SolutionEngine", + .mv_nr_irqs = 256, + .mv_inb = se7206_inb, + .mv_inw = se7206_inw, + .mv_inl = se7206_inl, + .mv_outb = se7206_outb, + .mv_outw = se7206_outw, + .mv_outl = se7206_outl, + + .mv_inb_p = se7206_inb_p, + .mv_inw_p = se7206_inw, + .mv_inl_p = se7206_inl, + .mv_outb_p = se7206_outb_p, + .mv_outw_p = se7206_outw, + .mv_outl_p = se7206_outl, + + .mv_insb = se7206_insb, + .mv_insw = se7206_insw, + .mv_insl = se7206_insl, + .mv_outsb = se7206_outsb, + .mv_outsw = se7206_outsw, + .mv_outsl = se7206_outsl, + + .mv_init_irq = init_se7206_IRQ, +#ifdef CONFIG_HEARTBEAT + .mv_heartbeat = heartbeat_se, +#endif +}; +ALIAS_MV(se) diff --git a/arch/sh/boards/se/7619/Makefile b/arch/sh/boards/se/7619/Makefile new file mode 100644 index 0000000..3666eca --- /dev/null +++ b/arch/sh/boards/se/7619/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the 7619 SolutionEngine specific parts of the kernel +# + +obj-y := setup.o io.o diff --git a/arch/sh/boards/se/7619/io.c b/arch/sh/boards/se/7619/io.c new file mode 100644 index 0000000..176f1f3 --- /dev/null +++ b/arch/sh/boards/se/7619/io.c @@ -0,0 +1,102 @@ +/* + * + * linux/arch/sh/boards/se/7619/io.c + * + * Copyright (C) 2006 Yoshinori Sato + * + * I/O routine for Hitachi 7619 SolutionEngine. + * + */ + +#include +#include +#include +#include +#include + +/* FIXME: M3A-ZAB7 Compact Flash Slot support */ + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); /* Uncached ROM area (P2) */ +} + +#define badio(name,port) \ + printk("bad I/O operation (%s) for port 0x%lx at 0x%08x\n", \ + #name, (port), (__u32) __builtin_return_address(0)) + +unsigned char se7619___inb(unsigned long port) +{ + badio(inb, port); + return 0; +} + +unsigned char se7619___inb_p(unsigned long port) +{ + badio(inb_p, port); + delay(); + return 0; +} + +unsigned short se7619___inw(unsigned long port) +{ + badio(inw, port); + return 0; +} + +unsigned int se7619___inl(unsigned long port) +{ + badio(inl, port); + return 0; +} + +void se7619___outb(unsigned char value, unsigned long port) +{ + badio(outb, port); +} + +void se7619___outb_p(unsigned char value, unsigned long port) +{ + badio(outb_p, port); + delay(); +} + +void se7619___outw(unsigned short value, unsigned long port) +{ + badio(outw, port); +} + +void se7619___outl(unsigned int value, unsigned long port) +{ + badio(outl, port); +} + +void se7619___insb(unsigned long port, void *addr, unsigned long count) +{ + badio(inw, port); +} + +void se7619___insw(unsigned long port, void *addr, unsigned long count) +{ + badio(inw, port); +} + +void se7619___insl(unsigned long port, void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsb(unsigned long port, const void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsw(unsigned long port, const void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsl(unsigned long port, const void *addr, unsigned long count) +{ + badio(outsw, port); +} diff --git a/arch/sh/boards/se/7619/setup.c b/arch/sh/boards/se/7619/setup.c new file mode 100644 index 0000000..e627b26 --- /dev/null +++ b/arch/sh/boards/se/7619/setup.c @@ -0,0 +1,43 @@ +/* + * arch/sh/boards/se/7619/setup.c + * + * Copyright (C) 2006 Yoshinori Sato + * + * Hitachi SH7619 SolutionEngine Support. + */ + +#include +#include +#include +#include +#include + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_se __initmv = { + .mv_name = "SolutionEngine", + .mv_nr_irqs = 108, + .mv_inb = se7619___inb, + .mv_inw = se7619___inw, + .mv_inl = se7619___inl, + .mv_outb = se7619___outb, + .mv_outw = se7619___outw, + .mv_outl = se7619___outl, + + .mv_inb_p = se7619___inb_p, + .mv_inw_p = se7619___inw, + .mv_inl_p = se7619___inl, + .mv_outb_p = se7619___outb_p, + .mv_outw_p = se7619___outw, + .mv_outl_p = se7619___outl, + + .mv_insb = se7619___insb, + .mv_insw = se7619___insw, + .mv_insl = se7619___insl, + .mv_outsb = se7619___outsb, + .mv_outsw = se7619___outsw, + .mv_outsl = se7619___outsl, +}; +ALIAS_MV(se) diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c index f2fed5c..35452d8 100644 --- a/arch/sh/boot/compressed/misc.c +++ b/arch/sh/boot/compressed/misc.c @@ -12,6 +12,7 @@ */ #include +#include #ifdef CONFIG_SH_STANDARD_BIOS #include #endif @@ -228,7 +229,7 @@ long* stack_start = &user_stack[STACK_SI void decompress_kernel(void) { output_data = 0; - output_ptr = (unsigned long)&_text+0x20001000; + output_ptr = P2SEGADDR((unsigned long)&_text+0x1000); free_mem_ptr = (unsigned long)&_end; free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig new file mode 100644 index 0000000..36cec0b --- /dev/null +++ b/arch/sh/configs/se7206_defconfig @@ -0,0 +1,826 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.19-rc4 +# Sun Nov 5 16:20:10 2006 +# +CONFIG_SUPERH=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_TIME is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_HOTPLUG is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_TINY_SHMEM=y +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" + +# +# System type +# +# CONFIG_SH_SOLUTION_ENGINE is not set +# CONFIG_SH_7751_SOLUTION_ENGINE is not set +# CONFIG_SH_7300_SOLUTION_ENGINE is not set +# CONFIG_SH_7343_SOLUTION_ENGINE is not set +# CONFIG_SH_73180_SOLUTION_ENGINE is not set +# CONFIG_SH_7751_SYSTEMH is not set +# CONFIG_SH_HP6XX is not set +# CONFIG_SH_EC3104 is not set +# CONFIG_SH_SATURN is not set +# CONFIG_SH_DREAMCAST is not set +# CONFIG_SH_BIGSUR is not set +# CONFIG_SH_MPC1211 is not set +# CONFIG_SH_SH03 is not set +# CONFIG_SH_SECUREEDGE5410 is not set +# CONFIG_SH_HS7751RVOIP is not set +# CONFIG_SH_7710VOIPGW is not set +# CONFIG_SH_RTS7751R2D is not set +# CONFIG_SH_R7780RP is not set +# CONFIG_SH_EDOSK7705 is not set +# CONFIG_SH_SH4202_MICRODEV is not set +# CONFIG_SH_LANDISK is not set +# CONFIG_SH_TITAN is not set +# CONFIG_SH_SHMIN is not set +CONFIG_SH_7206_SOLUTION_ENGINE=y +# CONFIG_SH_7619_SOLUTION_ENGINE is not set +# CONFIG_SH_UNKNOWN is not set + +# +# Processor selection +# +CONFIG_CPU_SH2=y +CONFIG_CPU_SH2A=y + +# +# SH-2 Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7604 is not set +# CONFIG_CPU_SUBTYPE_SH7619 is not set + +# +# SH-2A Processor Support +# +CONFIG_CPU_SUBTYPE_SH7206=y + +# +# SH-3 Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7300 is not set +# CONFIG_CPU_SUBTYPE_SH7705 is not set +# CONFIG_CPU_SUBTYPE_SH7706 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7710 is not set + +# +# SH-4 Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set + +# +# ST40 Processor Support +# +# CONFIG_CPU_SUBTYPE_ST40STB1 is not set +# CONFIG_CPU_SUBTYPE_ST40GX1 is not set + +# +# SH-4A Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set + +# +# SH4AL-DSP Processor Support +# +# CONFIG_CPU_SUBTYPE_SH73180 is not set +# CONFIG_CPU_SUBTYPE_SH7343 is not set + +# +# Memory management options +# +CONFIG_PAGE_OFFSET=0x00000000 +CONFIG_MEMORY_START=0x0c000000 +CONFIG_MEMORY_SIZE=0x02000000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set + +# +# Processor features +# +# CONFIG_CPU_LITTLE_ENDIAN is not set +# CONFIG_SH_FPU is not set +# CONFIG_SH_FPU_EMU is not set +# CONFIG_SH_DSP is not set + +# +# Timer support +# +CONFIG_SH_CMT=y +# CONFIG_SH_MTU2 is not set +CONFIG_SH_PCLK_FREQ=33333333 +CONFIG_SH_CLK_MD=6 + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# DMA support +# +# CONFIG_SH_DMA is not set + +# +# Companion Chips +# +# CONFIG_HD6446X_SERIES is not set + +# +# Kernel features +# +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +# CONFIG_KEXEC is not set +# CONFIG_SMP is not set +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set + +# +# Boot options +# +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +# CONFIG_UBC_WAKEUP is not set +# CONFIG_CMDLINE_BOOL is not set + +# +# Bus options +# +# CONFIG_PCI is not set + +# +# PCCARD (PCMCIA/CardBus) support +# + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_FLAT=y +CONFIG_BINFMT_ZFLAT=y +# CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options (EXPERIMENTAL) +# +# CONFIG_PM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +# CONFIG_PACKET is not set +# CONFIG_UNIX is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x20000000 +CONFIG_MTD_PHYSMAP_LEN=0x1000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=4 +# CONFIG_MTD_SOLUTIONENGINE is not set +# CONFIG_MTD_UCLINUX is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# Misc devices +# +# CONFIG_TIFM_CORE is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_NETLINK is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +# CONFIG_ATA is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +# CONFIG_NETDEVICES is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SH_SCI=y +CONFIG_SERIAL_SH_SCI_NR_UARTS=4 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_UNIX98_PTYS is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_HW_RANDOM=y +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +# CONFIG_SYSFS is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_UNWIND_INFO is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_EARLY_SCIF_CONSOLE is not set +# CONFIG_KGDB is not set + +# +# Security options +# +# CONFIG_KEYS is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c index d6e6352..602b644 100644 --- a/arch/sh/drivers/pci/pci-sh7780.c +++ b/arch/sh/drivers/pci/pci-sh7780.c @@ -22,6 +22,20 @@ #include #include #include "pci-sh4.h" +#define INTC_BASE 0xffd00000 +#define INTC_ICR0 (INTC_BASE+0x0) +#define INTC_ICR1 (INTC_BASE+0x1c) +#define INTC_INTPRI (INTC_BASE+0x10) +#define INTC_INTREQ (INTC_BASE+0x24) +#define INTC_INTMSK0 (INTC_BASE+0x44) +#define INTC_INTMSK1 (INTC_BASE+0x48) +#define INTC_INTMSK2 (INTC_BASE+0x40080) +#define INTC_INTMSKCLR0 (INTC_BASE+0x64) +#define INTC_INTMSKCLR1 (INTC_BASE+0x68) +#define INTC_INTMSKCLR2 (INTC_BASE+0x40084) +#define INTC_INT2MSKR (INTC_BASE+0x40038) +#define INTC_INT2MSKCR (INTC_BASE+0x4003c) + /* * Initialization. Try all known PCI access methods. Note that we support * using both PCI BIOS and direct access: in such cases, we use I/O ports diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 5da88a4..50d54c2 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -4,7 +4,7 @@ # extra-y := head.o init_task.o vmlinux.lds -obj-y := process.o signal.o entry.o traps.o irq.o \ +obj-y := process.o signal.o traps.o irq.o \ ptrace.o setup.o time.o sys_sh.o semaphore.o \ io.o io_generic.o sh_ksyms.o syscalls.o diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index fb5dac0..0582e67 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -2,11 +2,12 @@ # # Makefile for the Linux/SuperH CPU-specifc backends. # -obj-y += irq/ init.o clock.o - -obj-$(CONFIG_CPU_SH2) += sh2/ -obj-$(CONFIG_CPU_SH3) += sh3/ -obj-$(CONFIG_CPU_SH4) += sh4/ +obj-$(CONFIG_CPU_SH2) = sh2/ +obj-$(CONFIG_CPU_SH2A) = sh2a/ +obj-$(CONFIG_CPU_SH3) = sh3/ +obj-$(CONFIG_CPU_SH4) = sh4/ obj-$(CONFIG_UBC_WAKEUP) += ubc.o obj-$(CONFIG_SH_ADC) += adc.o + +obj-y += irq/ init.o clock.o diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index bfb90eb..4812176 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -68,12 +68,14 @@ static void __init cache_init(void) waysize = cpu_data->dcache.sets; +#ifdef CCR_CACHE_ORA /* * If the OC is already in RAM mode, we only have * half of the entries to flush.. */ if (ccr & CCR_CACHE_ORA) waysize >>= 1; +#endif waysize <<= cpu_data->dcache.entry_shift; diff --git a/arch/sh/kernel/cpu/irq/imask.c b/arch/sh/kernel/cpu/irq/imask.c index a33ae3e..301b505 100644 --- a/arch/sh/kernel/cpu/irq/imask.c +++ b/arch/sh/kernel/cpu/irq/imask.c @@ -53,7 +53,10 @@ void static inline set_interrupt_registe { unsigned long __dummy; - asm volatile("ldc %2, r6_bank\n\t" + asm volatile( +#ifdef CONFIG_CPU_HAS_SR_RB + "ldc %2, r6_bank\n\t" +#endif "stc sr, %0\n\t" "and #0xf0, %0\n\t" "shlr2 %0\n\t" diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c index 74ca576..74defe7 100644 --- a/arch/sh/kernel/cpu/irq/intc2.c +++ b/arch/sh/kernel/cpu/irq/intc2.c @@ -11,22 +11,29 @@ * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. */ #include -#include +#include #include -#include + +#if defined(CONFIG_CPU_SUBTYPE_SH7760) +#define INTC2_BASE 0xfe080000 +#define INTC2_INTMSK (INTC2_BASE + 0x40) +#define INTC2_INTMSKCLR (INTC2_BASE + 0x60) +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) +#define INTC2_BASE 0xffd40000 +#define INTC2_INTMSK (INTC2_BASE + 0x38) +#define INTC2_INTMSKCLR (INTC2_BASE + 0x3c) +#endif static void disable_intc2_irq(unsigned int irq) { struct intc2_data *p = get_irq_chip_data(irq); - ctrl_outl(1 << p->msk_shift, - INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset); + ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset); } static void enable_intc2_irq(unsigned int irq) { struct intc2_data *p = get_irq_chip_data(irq); - ctrl_outl(1 << p->msk_shift, - INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset); + ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset); } static struct irq_chip intc2_irq_chip = { @@ -61,12 +68,10 @@ void make_intc2_irq(struct intc2_data *t /* Set the priority level */ local_irq_save(flags); - ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + - p->ipr_offset); + ipr = ctrl_inl(INTC2_BASE + p->ipr_offset); ipr &= ~(0xf << p->ipr_shift); ipr |= p->priority << p->ipr_shift; - ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + - p->ipr_offset); + ctrl_outl(ipr, INTC2_BASE + p->ipr_offset); local_irq_restore(flags); diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index a008956..a181ccd 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c @@ -19,10 +19,8 @@ #include #include #include -#include -#include -#include - +#include +#include static void disable_ipr_irq(unsigned int irq) { @@ -62,6 +60,10 @@ void make_ipr_irq(struct ipr_data *table } EXPORT_SYMBOL(make_ipr_irq); +/* + * XXX: Move this garbage in to the drivers, and kill off the ridiculous CPU + * subtype checks. + */ static struct ipr_data sys_ipr_map[] = { #ifndef CONFIG_CPU_SUBTYPE_SH7780 { TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY }, @@ -80,6 +82,18 @@ #ifdef SCIF1_ERI_IRQ { SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, { SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, #endif +#ifdef SCIF2_ERI_IRQ + { SCIF2_ERI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY }, + { SCIF2_RXI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY }, + { SCIF2_BRI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY }, + { SCIF2_TXI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY }, +#endif +#ifdef SCIF3_ERI_IRQ + { SCIF3_ERI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY }, + { SCIF3_RXI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY }, + { SCIF3_BRI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY }, + { SCIF3_TXI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY }, +#endif #if defined(CONFIG_CPU_SUBTYPE_SH7300) { SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, diff --git a/arch/sh/kernel/cpu/sh2/Makefile b/arch/sh/kernel/cpu/sh2/Makefile index 389353f..f0f059a 100644 --- a/arch/sh/kernel/cpu/sh2/Makefile +++ b/arch/sh/kernel/cpu/sh2/Makefile @@ -2,5 +2,6 @@ # # Makefile for the Linux/SuperH SH-2 backends. # -obj-y := probe.o +obj-y := ex.o probe.o entry.o +obj-$(CONFIG_CPU_SUBTYPE_SH7619) += setup-sh7619.o clock-sh7619.o diff --git a/arch/sh/kernel/cpu/sh2/clock-sh7619.c b/arch/sh/kernel/cpu/sh2/clock-sh7619.c new file mode 100644 index 0000000..d0440b2 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/clock-sh7619.c @@ -0,0 +1,81 @@ +/* + * arch/sh/kernel/cpu/sh2/clock-sh7619.c + * + * SH7619 support for the clock framework + * + * Copyright (C) 2006 Yoshinori Sato + * + * Based on clock-sh4.c + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +const static int pll1rate[]={1,2}; +const static int pfc_divisors[]={1,2,0,4}; + +#if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2) +#define PLL2 (4) +#elif (CONFIG_SH_CLK_MD == 5) || (CONFIG_SH_CLK_MD == 6) +#define PLL2 (2) +#else +#error "Illigal Clock Mode!" +#endif + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; +} + +static struct clk_ops sh7619_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7619_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; +} + +static struct clk_ops sh7619_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate; +} + +static struct clk_ops sh7619_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7619_clk_ops[] = { + &sh7619_master_clk_ops, + &sh7619_module_clk_ops, + &sh7619_bus_clk_ops, + &sh7619_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7619_clk_ops)) + *ops = sh7619_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S new file mode 100644 index 0000000..298d919 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/entry.S @@ -0,0 +1,325 @@ +/* + * arch/sh/kernel/cpu/sh2/entry.S + * + * The SH-2 exception entry + * + * Copyright (C) 2005,2006 Yoshinori Sato + * Copyright (C) 2005 AXE,Inc. + * + * 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 +#include +#include +#include +#include +#include +#include + +/* Offsets to the stack */ +OFF_R0 = 0 /* Return value. New ABI also arg4 */ +OFF_R1 = 4 /* New ABI: arg5 */ +OFF_R2 = 8 /* New ABI: arg6 */ +OFF_R3 = 12 /* New ABI: syscall_nr */ +OFF_R4 = 16 /* New ABI: arg0 */ +OFF_R5 = 20 /* New ABI: arg1 */ +OFF_R6 = 24 /* New ABI: arg2 */ +OFF_R7 = 28 /* New ABI: arg3 */ +OFF_SP = (15*4) +OFF_PC = (16*4) +OFF_SR = (16*4+2*4) +OFF_TRA = (16*4+6*4) + +#include + +ENTRY(exception_handler) + ! already saved r0/r1 + mov.l r2,@-sp + mov.l r3,@-sp + mov r0,r1 + cli + mov.l $cpu_mode,r2 + mov.l @r2,r0 + mov.l @(5*4,r15),r3 ! previous SR + shll2 r3 ! set "S" flag + rotl r0 ! T <- "S" flag + rotl r0 ! "S" flag is LSB + rotcr r3 ! T -> r3:b30 + shlr r3 + shlr r0 + bt/s 1f + mov.l r3,@(5*4,r15) ! copy cpu mode to SR + ! switch to kernel mode + mov #1,r0 + rotr r0 + rotr r0 + mov.l r0,@r2 ! enter kernel mode + mov.l $current_thread_info,r2 + mov.l @r2,r2 + mov #0x20,r0 + shll8 r0 + add r2,r0 + mov r15,r2 ! r2 = user stack top + mov r0,r15 ! switch kernel stack + add #-4,r15 ! dummy + mov.l r1,@-r15 ! TRA + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + mov.l @(4*4,r2),r0 + mov.l @(5*4,r2),r1 + mov.l r1,@-r15 ! original SR + sts.l pr,@-r15 + mov.l r0,@-r15 ! original PC + mov r2,r3 + add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame + mov.l r3,@-r15 ! original SP + mov.l r14,@-r15 + mov.l r13,@-r15 + mov.l r12,@-r15 + mov.l r11,@-r15 + mov.l r10,@-r15 + mov.l r9,@-r15 + mov.l r8,@-r15 + mov.l r7,@-r15 + mov.l r6,@-r15 + mov.l r5,@-r15 + mov.l r4,@-r15 + mov r2,r8 ! copy user -> kernel stack + mov.l @r8+,r3 + mov.l r3,@-r15 + mov.l @r8+,r2 + mov.l r2,@-r15 + mov.l @r8+,r1 + mov.l r1,@-r15 + mov.l @r8+,r0 + bra 2f + mov.l r0,@-r15 +1: + ! in kernel exception + mov #(22-4-4-1)*4+4,r0 + mov r15,r2 + sub r0,r15 + mov.l @r2+,r0 ! old R3 + mov.l r0,@-r15 + mov.l @r2+,r0 ! old R2 + mov.l r0,@-r15 + mov.l @r2+,r0 ! old R1 + mov.l r0,@-r15 + mov.l @r2+,r0 ! old R0 + mov.l r0,@-r15 + mov.l @r2+,r3 ! old PC + mov.l @r2+,r0 ! old SR + add #-4,r2 ! exception frame stub (sr) + mov.l r1,@-r2 ! TRA + sts.l macl, @-r2 + sts.l mach, @-r2 + stc.l gbr, @-r2 + mov.l r0,@-r2 ! save old SR + sts.l pr,@-r2 + mov.l r3,@-r2 ! save old PC + mov r2,r0 + add #8*4,r0 + mov.l r0,@-r2 ! save old SP + mov.l r14,@-r2 + mov.l r13,@-r2 + mov.l r12,@-r2 + mov.l r11,@-r2 + mov.l r10,@-r2 + mov.l r9,@-r2 + mov.l r8,@-r2 + mov.l r7,@-r2 + mov.l r6,@-r2 + mov.l r5,@-r2 + mov.l r4,@-r2 + mov.l @(OFF_R0,r15),r0 + mov.l @(OFF_R1,r15),r1 + mov.l @(OFF_R2,r15),r2 + mov.l @(OFF_R3,r15),r3 +2: + mov #OFF_TRA,r8 + add r15,r8 + mov.l @r8,r9 + mov #64,r8 + cmp/hs r8,r9 + bt interrupt_entry ! vec >= 64 is interrupt + mov #32,r8 + cmp/hs r8,r9 + bt trap_entry ! 64 > vec >= 32 is trap + mov.l 4f,r8 + mov r9,r4 + shll2 r9 + add r9,r8 + mov.l @r8,r8 + mov #0,r9 + cmp/eq r9,r8 + bf 3f + mov.l 8f,r8 ! unhandled exception +3: + mov.l 5f,r10 + jmp @r8 + lds r10,pr + +interrupt_entry: + mov r9,r4 + mov.l 6f,r9 + mov.l 7f,r8 + jmp @r8 + lds r9,pr + + .align 2 +4: .long exception_handling_table +5: .long ret_from_exception +6: .long ret_from_irq +7: .long do_IRQ +8: .long do_exception_error + +trap_entry: + add #-0x10,r9 + shll2 r9 ! TRA + mov #OFF_TRA,r8 + add r15,r8 + mov.l r9,@r8 + mov r9,r8 + sti + bra system_call + nop + + .align 2 +1: .long syscall_exit +2: .long break_point_trap_software +3: .long NR_syscalls +4: .long sys_call_table + +#if defined(CONFIG_SH_STANDARD_BIOS) + /* Unwind the stack and jmp to the debug entry */ +debug_kernel_fw: + mov r15,r0 + add #(22-4)*4-4,r0 + ldc.l @r0+,gbr + lds.l @r0+,mach + lds.l @r0+,macl + mov r15,r0 + mov.l @(OFF_SP,r0),r1 + mov #OFF_SR,r2 + mov.l @(r0,r2),r3 + mov.l r3,@-r1 + mov #OFF_SP,r2 + mov.l @(r0,r2),r3 + mov.l r3,@-r1 + mov r15,r0 + add #(22-4)*4-8,r0 + mov.l 1f,r2 + mov.l @r2,r2 + stc sr,r3 + mov.l r2,@r0 + mov.l r3,@r0 + mov.l r1,@(8,r0) + mov.l @r15+, r0 + mov.l @r15+, r1 + mov.l @r15+, r2 + mov.l @r15+, r3 + mov.l @r15+, r4 + mov.l @r15+, r5 + mov.l @r15+, r6 + mov.l @r15+, r7 + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r11 + mov.l @r15+, r12 + mov.l @r15+, r13 + mov.l @r15+, r14 + add #8,r15 + lds.l @r15+, pr + rte + mov.l @r15+,r15 + .align 2 +1: .long gdb_vbr_vector +#endif /* CONFIG_SH_STANDARD_BIOS */ + +ENTRY(address_error_handler) + mov r15,r4 ! regs + add #4,r4 + mov #OFF_PC,r0 + mov.l @(r0,r15),r6 ! pc + mov.l 1f,r0 + jmp @r0 + mov #0,r5 ! writeaccess is unknown + .align 2 + +1: .long do_address_error + +restore_all: + cli + mov r15,r0 + mov.l $cpu_mode,r2 + mov #OFF_SR,r3 + mov.l @(r0,r3),r1 + mov.l r1,@r2 + shll2 r1 ! clear MD bit + shlr2 r1 + mov.l @(OFF_SP,r0),r2 + add #-8,r2 + mov.l r2,@(OFF_SP,r0) ! point exception frame top + mov.l r1,@(4,r2) ! set sr + mov #OFF_PC,r3 + mov.l @(r0,r3),r1 + mov.l r1,@r2 ! set pc + add #4*16+4,r0 + lds.l @r0+,pr + add #4,r0 ! skip sr + ldc.l @r0+,gbr + lds.l @r0+,mach + lds.l @r0+,macl + get_current_thread_info r0, r1 + mov.l $current_thread_info,r1 + mov.l r0,@r1 + mov.l @r15+,r0 + mov.l @r15+,r1 + mov.l @r15+,r2 + mov.l @r15+,r3 + mov.l @r15+,r4 + mov.l @r15+,r5 + mov.l @r15+,r6 + mov.l @r15+,r7 + mov.l @r15+,r8 + mov.l @r15+,r9 + mov.l @r15+,r10 + mov.l @r15+,r11 + mov.l @r15+,r12 + mov.l @r15+,r13 + mov.l @r15+,r14 + mov.l @r15,r15 + rte + nop +2: + mov.l 1f,r8 + mov.l 2f,r9 + jmp @r9 + lds r8,pr + + .align 2 +$current_thread_info: + .long __current_thread_info +$cpu_mode: + .long __cpu_mode + +! common exception handler +#include "../../entry-common.S" + + .data +! cpu operation mode +! bit30 = MD (compatible SH3/4) +__cpu_mode: + .long 0x40000000 + + .section .bss +__current_thread_info: + .long 0 + +ENTRY(exception_handling_table) + .space 4*32 diff --git a/arch/sh/kernel/cpu/sh2/ex.S b/arch/sh/kernel/cpu/sh2/ex.S new file mode 100644 index 0000000..6d285af --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/ex.S @@ -0,0 +1,46 @@ +/* + * arch/sh/kernel/cpu/sh2/ex.S + * + * The SH-2 exception vector table + * + * Copyright (C) 2005 Yoshinori Sato + * + * 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 + +! +! convert Exception Vector to Exception Number +! +exception_entry: +no = 0 + .rept 256 + mov.l r0,@-sp + mov #no,r0 + bra exception_trampoline + and #0xff,r0 +no = no + 1 + .endr +exception_trampoline: + mov.l r1,@-sp + mov.l $exception_handler,r1 + jmp @r1 + + .align 2 +$exception_entry: + .long exception_entry +$exception_handler: + .long exception_handler +! +! Exception Vector Base +! + .align 2 +ENTRY(vbr_base) +vector = 0 + .rept 256 + .long exception_entry + vector * 8 +vector = vector + 1 + .endr diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c index f17a2a0..ba527d9 100644 --- a/arch/sh/kernel/cpu/sh2/probe.c +++ b/arch/sh/kernel/cpu/sh2/probe.c @@ -17,17 +17,23 @@ #include int __init detect_cpu_and_cache_system(void) { - /* - * For now, assume SH7604 .. fix this later. - */ +#if defined(CONFIG_CPU_SUBTYPE_SH7604) cpu_data->type = CPU_SH7604; cpu_data->dcache.ways = 4; - cpu_data->dcache.way_shift = 6; + cpu_data->dcache.way_incr = (1<<10); cpu_data->dcache.sets = 64; cpu_data->dcache.entry_shift = 4; cpu_data->dcache.linesz = L1_CACHE_BYTES; cpu_data->dcache.flags = 0; - +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) + cpu_data->type = CPU_SH7619; + cpu_data->dcache.ways = 4; + cpu_data->dcache.way_incr = (1<<12); + cpu_data->dcache.sets = 256; + cpu_data->dcache.entry_shift = 4; + cpu_data->dcache.linesz = L1_CACHE_BYTES; + cpu_data->dcache.flags = 0; +#endif /* * SH-2 doesn't have separate caches */ diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c new file mode 100644 index 0000000..82c2d90 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c @@ -0,0 +1,53 @@ +/* + * SH7619 Setup + * + * Copyright (C) 2006 Yoshinori Sato + * + * 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 +#include +#include +#include + +static struct plat_sci_port sci_platform_data[] = { + { + .mapbase = 0xf8400000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 88, 89, 91, 90}, + }, { + .mapbase = 0xf8410000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 92, 93, 95, 94}, + }, { + .mapbase = 0xf8420000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 96, 97, 99, 98}, + }, { + .flags = 0, + } +}; + +static struct platform_device sci_device = { + .name = "sh-sci", + .id = -1, + .dev = { + .platform_data = sci_platform_data, + }, +}; + +static struct platform_device *sh7619_devices[] __initdata = { + &sci_device, +}; + +static int __init sh7619_devices_setup(void) +{ + return platform_add_devices(sh7619_devices, + ARRAY_SIZE(sh7619_devices)); +} +__initcall(sh7619_devices_setup); diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile new file mode 100644 index 0000000..350972a --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the Linux/SuperH SH-2A backends. +# + +obj-y := common.o probe.o + +common-y += $(addprefix ../sh2/, ex.o) +common-y += $(addprefix ../sh2/, entry.o) + +obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c new file mode 100644 index 0000000..a9ad309 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c @@ -0,0 +1,85 @@ +/* + * arch/sh/kernel/cpu/sh2a/clock-sh7206.c + * + * SH7206 support for the clock framework + * + * Copyright (C) 2006 Yoshinori Sato + * + * Based on clock-sh4.c + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +const static int pll1rate[]={1,2,3,4,6,8}; +const static int pfc_divisors[]={1,2,3,4,6,8,12}; +#define ifc_divisors pfc_divisors + +#if (CONFIG_SH_CLK_MD == 2) +#define PLL2 (4) +#elif (CONFIG_SH_CLK_MD == 6) +#define PLL2 (2) +#elif (CONFIG_SH_CLK_MD == 7) +#define PLL2 (1) +#else +#error "Illigal Clock Mode!" +#endif + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; +} + +static struct clk_ops sh7206_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7206_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; +} + +static struct clk_ops sh7206_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7206_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7206_clk_ops[] = { + &sh7206_master_clk_ops, + &sh7206_module_clk_ops, + &sh7206_bus_clk_ops, + &sh7206_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7206_clk_ops)) + *ops = sh7206_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c new file mode 100644 index 0000000..87c6c05 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/probe.c @@ -0,0 +1,39 @@ +/* + * arch/sh/kernel/cpu/sh2a/probe.c + * + * CPU Subtype Probing for SH-2A. + * + * Copyright (C) 2004, 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include + +int __init detect_cpu_and_cache_system(void) +{ + /* Just SH7206 for now .. */ + cpu_data->type = CPU_SH7206; + + cpu_data->dcache.ways = 4; + cpu_data->dcache.way_incr = (1 << 11); + cpu_data->dcache.sets = 128; + cpu_data->dcache.entry_shift = 4; + cpu_data->dcache.linesz = L1_CACHE_BYTES; + cpu_data->dcache.flags = 0; + + /* + * The icache is the same as the dcache as far as this setup is + * concerned. The only real difference in hardware is that the icache + * lacks the U bit that the dcache has, none of this has any bearing + * on the cache info. + */ + cpu_data->icache = cpu_data->dcache; + + return 0; +} + diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c new file mode 100644 index 0000000..cdfeef4 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c @@ -0,0 +1,58 @@ +/* + * SH7206 Setup + * + * Copyright (C) 2006 Yoshinori Sato + * + * 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 +#include +#include +#include + +static struct plat_sci_port sci_platform_data[] = { + { + .mapbase = 0xfffe8000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 240, 241, 242, 243}, + }, { + .mapbase = 0xfffe8800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 244, 245, 246, 247}, + }, { + .mapbase = 0xfffe9000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 248, 249, 250, 251}, + }, { + .mapbase = 0xfffe9800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 252, 253, 254, 255}, + }, { + .flags = 0, + } +}; + +static struct platform_device sci_device = { + .name = "sh-sci", + .id = -1, + .dev = { + .platform_data = sci_platform_data, + }, +}; + +static struct platform_device *sh7206_devices[] __initdata = { + &sci_device, +}; + +static int __init sh7206_devices_setup(void) +{ + return platform_add_devices(sh7206_devices, + ARRAY_SIZE(sh7206_devices)); +} +__initcall(sh7206_devices_setup); diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index 58d3815..83905e4 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -2,7 +2,7 @@ # # Makefile for the Linux/SuperH SH-3 backends. # -obj-y := ex.o probe.o +obj-y := ex.o probe.o entry.o # CPU subtype setup obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S new file mode 100644 index 0000000..869d56f --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -0,0 +1,526 @@ +/* + * arch/sh/kernel/entry.S + * + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka + * Copyright (C) 2003 - 2006 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include + +! NOTE: +! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address +! to be jumped is too far, but it causes illegal slot exception. + +/* + * entry.S contains the system-call and fault low-level handling routines. + * This also contains the timer-interrupt handler, as well as all interrupts + * and faults that can result in a task-switch. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. + * + * NOTE: This code uses a convention that instructions in the delay slot + * of a transfer-control instruction are indented by an extra space, thus: + * + * jmp @k0 ! control-transfer instruction + * ldc k1, ssr ! delay slot + * + * Stack layout in 'ret_from_syscall': + * ptrace needs to have all regs on the stack. + * if the order here is changed, it needs to be + * updated in ptrace.c and ptrace.h + * + * r0 + * ... + * r15 = stack pointer + * spc + * pr + * ssr + * gbr + * mach + * macl + * syscall # + * + */ +#if defined(CONFIG_KGDB_NMI) +NMI_VEC = 0x1c0 ! Must catch early for debounce +#endif + +/* Offsets to the stack */ +OFF_R0 = 0 /* Return value. New ABI also arg4 */ +OFF_R1 = 4 /* New ABI: arg5 */ +OFF_R2 = 8 /* New ABI: arg6 */ +OFF_R3 = 12 /* New ABI: syscall_nr */ +OFF_R4 = 16 /* New ABI: arg0 */ +OFF_R5 = 20 /* New ABI: arg1 */ +OFF_R6 = 24 /* New ABI: arg2 */ +OFF_R7 = 28 /* New ABI: arg3 */ +OFF_SP = (15*4) +OFF_PC = (16*4) +OFF_SR = (16*4+8) +OFF_TRA = (16*4+6*4) + + +#define k0 r0 +#define k1 r1 +#define k2 r2 +#define k3 r3 +#define k4 r4 + +#define g_imask r6 /* r6_bank1 */ +#define k_g_imask r6_bank /* r6_bank1 */ +#define current r7 /* r7_bank1 */ + +#include + +/* + * Kernel mode register usage: + * k0 scratch + * k1 scratch + * k2 scratch (Exception code) + * k3 scratch (Return address) + * k4 scratch + * k5 reserved + * k6 Global Interrupt Mask (0--15 << 4) + * k7 CURRENT_THREAD_INFO (pointer to current thread info) + */ + +! +! TLB Miss / Initial Page write exception handling +! _and_ +! TLB hits, but the access violate the protection. +! It can be valid access, such as stack grow and/or C-O-W. +! +! +! Find the pmd/pte entry and loadtlb +! If it's not found, cause address error (SEGV) +! +! Although this could be written in assembly language (and it'd be faster), +! this first version depends *much* on C implementation. +! + +#if defined(CONFIG_MMU) + .align 2 +ENTRY(tlb_miss_load) + bra call_dpf + mov #0, r5 + + .align 2 +ENTRY(tlb_miss_store) + bra call_dpf + mov #1, r5 + + .align 2 +ENTRY(initial_page_write) + bra call_dpf + mov #1, r5 + + .align 2 +ENTRY(tlb_protection_violation_load) + bra call_dpf + mov #0, r5 + + .align 2 +ENTRY(tlb_protection_violation_store) + bra call_dpf + mov #1, r5 + +call_dpf: + mov.l 1f, r0 + mov r5, r8 + mov.l @r0, r6 + mov r6, r9 + mov.l 2f, r0 + sts pr, r10 + jsr @r0 + mov r15, r4 + ! + tst r0, r0 + bf/s 0f + lds r10, pr + rts + nop +0: sti + mov.l 3f, r0 + mov r9, r6 + mov r8, r5 + jmp @r0 + mov r15, r4 + + .align 2 +1: .long MMU_TEA +2: .long __do_page_fault +3: .long do_page_fault + + .align 2 +ENTRY(address_error_load) + bra call_dae + mov #0,r5 ! writeaccess = 0 + + .align 2 +ENTRY(address_error_store) + bra call_dae + mov #1,r5 ! writeaccess = 1 + + .align 2 +call_dae: + mov.l 1f, r0 + mov.l @r0, r6 ! address + mov.l 2f, r0 + jmp @r0 + mov r15, r4 ! regs + + .align 2 +1: .long MMU_TEA +2: .long do_address_error +#endif /* CONFIG_MMU */ + +#if defined(CONFIG_SH_STANDARD_BIOS) + /* Unwind the stack and jmp to the debug entry */ +debug_kernel_fw: + mov.l @r15+, r0 + mov.l @r15+, r1 + mov.l @r15+, r2 + mov.l @r15+, r3 + mov.l @r15+, r4 + mov.l @r15+, r5 + mov.l @r15+, r6 + mov.l @r15+, r7 + stc sr, r8 + mov.l 1f, r9 ! BL =1, RB=1, IMASK=0x0F + or r9, r8 + ldc r8, sr ! here, change the register bank + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r11 + mov.l @r15+, r12 + mov.l @r15+, r13 + mov.l @r15+, r14 + mov.l @r15+, k0 + ldc.l @r15+, spc + lds.l @r15+, pr + mov.l @r15+, k1 + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + mov k0, r15 + ! + mov.l 2f, k0 + mov.l @k0, k0 + jmp @k0 + ldc k1, ssr + .align 2 +1: .long 0x300000f0 +2: .long gdb_vbr_vector +#endif /* CONFIG_SH_STANDARD_BIOS */ + +restore_all: + mov.l @r15+, r0 + mov.l @r15+, r1 + mov.l @r15+, r2 + mov.l @r15+, r3 + mov.l @r15+, r4 + mov.l @r15+, r5 + mov.l @r15+, r6 + mov.l @r15+, r7 + ! + stc sr, r8 + mov.l 7f, r9 + or r9, r8 ! BL =1, RB=1 + ldc r8, sr ! here, change the register bank + ! + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r11 + mov.l @r15+, r12 + mov.l @r15+, r13 + mov.l @r15+, r14 + mov.l @r15+, k4 ! original stack pointer + ldc.l @r15+, spc + lds.l @r15+, pr + mov.l @r15+, k3 ! original SR + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + add #4, r15 ! Skip syscall number + ! +#ifdef CONFIG_SH_DSP + mov.l @r15+, k0 ! DSP mode marker + mov.l 5f, k1 + cmp/eq k0, k1 ! Do we have a DSP stack frame? + bf skip_restore + + stc sr, k0 ! Enable CPU DSP mode + or k1, k0 ! (within kernel it may be disabled) + ldc k0, sr + mov r2, k0 ! Backup r2 + + ! Restore DSP registers from stack + mov r15, r2 + movs.l @r2+, a1 + movs.l @r2+, a0g + movs.l @r2+, a1g + movs.l @r2+, m0 + movs.l @r2+, m1 + mov r2, r15 + + lds.l @r15+, a0 + lds.l @r15+, x0 + lds.l @r15+, x1 + lds.l @r15+, y0 + lds.l @r15+, y1 + lds.l @r15+, dsr + ldc.l @r15+, rs + ldc.l @r15+, re + ldc.l @r15+, mod + + mov k0, r2 ! Restore r2 +skip_restore: +#endif + ! + ! Calculate new SR value + mov k3, k2 ! original SR value + mov #0xf0, k1 + extu.b k1, k1 + not k1, k1 + and k1, k2 ! Mask orignal SR value + ! + mov k3, k0 ! Calculate IMASK-bits + shlr2 k0 + and #0x3c, k0 + cmp/eq #0x3c, k0 + bt/s 6f + shll2 k0 + mov g_imask, k0 + ! +6: or k0, k2 ! Set the IMASK-bits + ldc k2, ssr + ! +#if defined(CONFIG_KGDB_NMI) + ! Clear in_nmi + mov.l 6f, k0 + mov #0, k1 + mov.b k1, @k0 +#endif + mov.l @r15+, k2 ! restore EXPEVT + mov k4, r15 + rte + nop + + .align 2 +5: .long 0x00001000 ! DSP +7: .long 0x30000000 + +! common exception handler +#include "../../entry-common.S" + +! Exception Vector Base +! +! Should be aligned page boundary. +! + .balign 4096,0,4096 +ENTRY(vbr_base) + .long 0 +! + .balign 256,0,256 +general_exception: + mov.l 1f, k2 + mov.l 2f, k3 + bra handle_exception + mov.l @k2, k2 + .align 2 +1: .long EXPEVT +2: .long ret_from_exception +! +! + .balign 1024,0,1024 +tlb_miss: + mov.l 1f, k2 + mov.l 4f, k3 + bra handle_exception + mov.l @k2, k2 +! + .balign 512,0,512 +interrupt: + mov.l 2f, k2 + mov.l 3f, k3 +#if defined(CONFIG_KGDB_NMI) + ! Debounce (filter nested NMI) + mov.l @k2, k0 + mov.l 5f, k1 + cmp/eq k1, k0 + bf 0f + mov.l 6f, k1 + tas.b @k1 + bt 0f + rte + nop + .align 2 +5: .long NMI_VEC +6: .long in_nmi +0: +#endif /* defined(CONFIG_KGDB_NMI) */ + bra handle_exception + mov #-1, k2 ! interrupt exception marker + + .align 2 +1: .long EXPEVT +2: .long INTEVT +3: .long ret_from_irq +4: .long ret_from_exception + +! +! + .align 2 +ENTRY(handle_exception) + ! Using k0, k1 for scratch registers (r0_bank1, r1_bank), + ! save all registers onto stack. + ! + stc ssr, k0 ! Is it from kernel space? + shll k0 ! Check MD bit (bit30) by shifting it into... + shll k0 ! ...the T bit + bt/s 1f ! It's a kernel to kernel transition. + mov r15, k0 ! save original stack to k0 + /* User space to kernel */ + mov #(THREAD_SIZE >> 8), k1 + shll8 k1 ! k1 := THREAD_SIZE + add current, k1 + mov k1, r15 ! change to kernel stack + ! +1: mov.l 2f, k1 + ! +#ifdef CONFIG_SH_DSP + mov.l r2, @-r15 ! Save r2, we need another reg + stc sr, k4 + mov.l 1f, r2 + tst r2, k4 ! Check if in DSP mode + mov.l @r15+, r2 ! Restore r2 now + bt/s skip_save + mov #0, k4 ! Set marker for no stack frame + + mov r2, k4 ! Backup r2 (in k4) for later + + ! Save DSP registers on stack + stc.l mod, @-r15 + stc.l re, @-r15 + stc.l rs, @-r15 + sts.l dsr, @-r15 + sts.l y1, @-r15 + sts.l y0, @-r15 + sts.l x1, @-r15 + sts.l x0, @-r15 + sts.l a0, @-r15 + + ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr. + + ! FIXME: Make sure that this is still the case with newer toolchains, + ! as we're not at all interested in supporting ancient toolchains at + ! this point. -- PFM. + + mov r15, r2 + .word 0xf653 ! movs.l a1, @-r2 + .word 0xf6f3 ! movs.l a0g, @-r2 + .word 0xf6d3 ! movs.l a1g, @-r2 + .word 0xf6c3 ! movs.l m0, @-r2 + .word 0xf6e3 ! movs.l m1, @-r2 + mov r2, r15 + + mov k4, r2 ! Restore r2 + mov.l 1f, k4 ! Force DSP stack frame +skip_save: + mov.l k4, @-r15 ! Push DSP mode marker onto stack +#endif + ! Save the user registers on the stack. + mov.l k2, @-r15 ! EXPEVT + + mov #-1, k4 + mov.l k4, @-r15 ! set TRA (default: -1) + ! + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + stc.l ssr, @-r15 + sts.l pr, @-r15 + stc.l spc, @-r15 + ! + lds k3, pr ! Set the return address to pr + ! + mov.l k0, @-r15 ! save orignal stack + mov.l r14, @-r15 + mov.l r13, @-r15 + mov.l r12, @-r15 + mov.l r11, @-r15 + mov.l r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + ! + stc sr, r8 ! Back to normal register bank, and + or k1, r8 ! Block all interrupts + mov.l 3f, k1 + and k1, r8 ! ... + ldc r8, sr ! ...changed here. + ! + mov.l r7, @-r15 + mov.l r6, @-r15 + mov.l r5, @-r15 + mov.l r4, @-r15 + mov.l r3, @-r15 + mov.l r2, @-r15 + mov.l r1, @-r15 + mov.l r0, @-r15 + + /* + * This gets a bit tricky.. in the INTEVT case we don't want to use + * the VBR offset as a destination in the jump call table, since all + * of the destinations are the same. In this case, (interrupt) sets + * a marker in r2 (now r2_bank since SR.RB changed), which we check + * to determine the exception type. For all other exceptions, we + * forcibly read EXPEVT from memory and fix up the jump address, in + * the interrupt exception case we jump to do_IRQ() and defer the + * INTEVT read until there. As a bonus, we can also clean up the SR.RB + * checks that do_IRQ() was doing.. + */ + stc r2_bank, r8 + cmp/pz r8 + bf interrupt_exception + shlr2 r8 + shlr r8 + mov.l 4f, r9 + add r8, r9 + mov.l @r9, r9 + jmp @r9 + nop + rts + nop + + .align 2 +1: .long 0x00001000 ! DSP=1 +2: .long 0x000080f0 ! FD=1, IMASK=15 +3: .long 0xcfffffff ! RB=0, BL=0 +4: .long exception_handling_table + +interrupt_exception: + mov.l 1f, r9 + jmp @r9 + nop + rts + nop + + .align 2 +1: .long do_IRQ + + .align 2 +ENTRY(exception_none) + rts + nop diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index 8dbf389..6e415ba 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile @@ -2,7 +2,8 @@ # # Makefile for the Linux/SuperH SH-4 backends. # -obj-y := ex.o probe.o +obj-y := ex.o probe.o common.o +common-y += $(addprefix ../sh3/, entry.o) obj-$(CONFIG_SH_FPU) += fpu.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c index f486c07..7624677 100644 --- a/arch/sh/kernel/cpu/sh4/fpu.c +++ b/arch/sh/kernel/cpu/sh4/fpu.c @@ -282,11 +282,8 @@ ieee_fpe_handler (struct pt_regs *regs) grab_fpu(regs); restore_fpu(tsk); set_tsk_thread_flag(tsk, TIF_USEDFPU); - } else { - tsk->thread.trap_no = 11; - tsk->thread.error_code = 0; + } else force_sig(SIGFPE, tsk); - } regs->pc = nextpc; return 1; @@ -296,29 +293,29 @@ ieee_fpe_handler (struct pt_regs *regs) } asmlinkage void -do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) +do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, + unsigned long r7, struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); struct task_struct *tsk = current; - if (ieee_fpe_handler (®s)) + if (ieee_fpe_handler(regs)) return; - regs.pc += 2; - save_fpu(tsk, ®s); - tsk->thread.trap_no = 11; - tsk->thread.error_code = 0; + regs->pc += 2; + save_fpu(tsk, regs); force_sig(SIGFPE, tsk); } asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, - unsigned long r7, struct pt_regs regs) + unsigned long r7, struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); struct task_struct *tsk = current; - grab_fpu(®s); - if (!user_mode(®s)) { + grab_fpu(regs); + if (!user_mode(regs)) { printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); return; } diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4/setup-sh7780.c index 814ddb2..9aeaa2d 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7780.c @@ -79,25 +79,27 @@ static int __init sh7780_devices_setup(v __initcall(sh7780_devices_setup); static struct intc2_data intc2_irq_table[] = { - { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2 }, - { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { 28, 0, 24, 0, 0, 2 }, /* TMU0 */ - { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { 21, 1, 0, 0, 2, 2 }, + { 22, 1, 1, 0, 2, 2 }, + { 23, 1, 2, 0, 2, 2 }, - { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY }, - { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY }, - { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY }, - { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY }, - { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY }, + { 40, 8, 24, 0, 3, 3 }, /* SCIF0 ERI */ + { 41, 8, 24, 0, 3, 3 }, /* SCIF0 RXI */ + { 42, 8, 24, 0, 3, 3 }, /* SCIF0 BRI */ + { 43, 8, 24, 0, 3, 3 }, /* SCIF0 TXI */ + + { 76, 8, 16, 0, 4, 3 }, /* SCIF1 ERI */ + { 77, 8, 16, 0, 4, 3 }, /* SCIF1 RXI */ + { 78, 8, 16, 0, 4, 3 }, /* SCIF1 BRI */ + { 79, 8, 16, 0, 4, 3 }, /* SCIF1 TXI */ + + { 64, 0x10, 8, 0, 14, 2 }, /* PCIC0 */ + { 65, 0x10, 0, 0, 15, 2 }, /* PCIC1 */ + { 66, 0x14, 24, 0, 16, 2 }, /* PCIC2 */ + { 67, 0x14, 16, 0, 17, 2 }, /* PCIC3 */ + { 68, 0x14, 8, 0, 18, 2 }, /* PCIC4 */ }; void __init init_IRQ_intc2(void) diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S new file mode 100644 index 0000000..5bc7fa9 --- /dev/null +++ b/arch/sh/kernel/entry-common.S @@ -0,0 +1,372 @@ +/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $ + * + * linux/arch/sh/entry.S + * + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +! NOTE: +! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address +! to be jumped is too far, but it causes illegal slot exception. + +/* + * entry.S contains the system-call and fault low-level handling routines. + * This also contains the timer-interrupt handler, as well as all interrupts + * and faults that can result in a task-switch. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. + * + * NOTE: This code uses a convention that instructions in the delay slot + * of a transfer-control instruction are indented by an extra space, thus: + * + * jmp @k0 ! control-transfer instruction + * ldc k1, ssr ! delay slot + * + * Stack layout in 'ret_from_syscall': + * ptrace needs to have all regs on the stack. + * if the order here is changed, it needs to be + * updated in ptrace.c and ptrace.h + * + * r0 + * ... + * r15 = stack pointer + * spc + * pr + * ssr + * gbr + * mach + * macl + * syscall # + * + */ + +#if defined(CONFIG_PREEMPT) +# define preempt_stop() cli +#else +# define preempt_stop() +# define resume_kernel __restore_all +#endif + +#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) +! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. +! If both are configured, handle the debug traps (breakpoints) in SW, +! but still allow BIOS traps to FW. + + .align 2 +debug_kernel: +#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) + /* Force BIOS call to FW (debug_trap put TRA in r8) */ + mov r8,r0 + shlr2 r0 + cmp/eq #0x3f,r0 + bt debug_kernel_fw +#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ + +debug_enter: +#if defined(CONFIG_SH_KGDB) + /* Jump to kgdb, pass stacked regs as arg */ +debug_kernel_sw: + mov.l 3f, r0 + jmp @r0 + mov r15, r4 + .align 2 +3: .long kgdb_handle_exception +#endif /* CONFIG_SH_KGDB */ + +#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ + + + .align 2 +debug_trap: +#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + shll r0 + shll r0 ! kernel space? + bt/s debug_kernel +#endif + mov.l @r15, r0 ! Restore R0 value + mov.l 1f, r8 + jmp @r8 + nop + + .align 2 +ENTRY(exception_error) + ! + sti + mov.l 2f, r0 + jmp @r0 + nop + +! + .align 2 +1: .long break_point_trap_software +2: .long do_exception_error + + .align 2 +ret_from_exception: + preempt_stop() +ENTRY(ret_from_irq) + ! + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + shll r0 + shll r0 ! kernel space? + get_current_thread_info r8, r0 + bt resume_kernel ! Yes, it's from kernel, go back soon + +#ifdef CONFIG_PREEMPT + bra resume_userspace + nop +ENTRY(resume_kernel) + mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count + tst r0, r0 + bf noresched +need_resched: + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_NEED_RESCHED, r0 ! need_resched set? + bt noresched + + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + and #0xf0, r0 ! interrupts off (exception path)? + cmp/eq #0xf0, r0 + bt noresched + + mov.l 1f, r0 + mov.l r0, @(TI_PRE_COUNT,r8) + + sti + mov.l 2f, r0 + jsr @r0 + nop + mov #0, r0 + mov.l r0, @(TI_PRE_COUNT,r8) + cli + + bra need_resched + nop +noresched: + bra __restore_all + nop + + .align 2 +1: .long PREEMPT_ACTIVE +2: .long schedule +#endif + +ENTRY(resume_userspace) + ! r8: current_thread_info + cli + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_WORK_MASK, r0 + bt/s __restore_all + tst #_TIF_NEED_RESCHED, r0 + + .align 2 +work_pending: + ! r0: current_thread_info->flags + ! r8: current_thread_info + ! t: result of "tst #_TIF_NEED_RESCHED, r0" + bf/s work_resched + tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 +work_notifysig: + bt/s __restore_all + mov r15, r4 + mov r12, r5 ! set arg1(save_r0) + mov r0, r6 + mov.l 2f, r1 + mov.l 3f, r0 + jmp @r1 + lds r0, pr +work_resched: +#ifndef CONFIG_PREEMPT + ! gUSA handling + mov.l @(OFF_SP,r15), r0 ! get user space stack pointer + mov r0, r1 + shll r0 + bf/s 1f + shll r0 + bf/s 1f + mov #OFF_PC, r0 + ! SP >= 0xc0000000 : gUSA mark + mov.l @(r0,r15), r2 ! get user space PC (program counter) + mov.l @(OFF_R0,r15), r3 ! end point + cmp/hs r3, r2 ! r2 >= r3? + bt 1f + add r3, r1 ! rewind point #2 + mov.l r1, @(r0,r15) ! reset PC to rewind point #2 + ! +1: +#endif + mov.l 1f, r1 + jsr @r1 ! schedule + nop + cli + ! + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_WORK_MASK, r0 + bt __restore_all + bra work_pending + tst #_TIF_NEED_RESCHED, r0 + + .align 2 +1: .long schedule +2: .long do_notify_resume +3: .long restore_all + + .align 2 +syscall_exit_work: + ! r0: current_thread_info->flags + ! r8: current_thread_info + tst #_TIF_SYSCALL_TRACE, r0 + bt/s work_pending + tst #_TIF_NEED_RESCHED, r0 + sti + ! XXX setup arguments... + mov.l 4f, r0 ! do_syscall_trace + jsr @r0 + nop + bra resume_userspace + nop + + .align 2 +syscall_trace_entry: + ! Yes it is traced. + ! XXX setup arguments... + mov.l 4f, r11 ! Call do_syscall_trace which notifies + jsr @r11 ! superior (will chomp R[0-7]) + nop + ! Reload R0-R4 from kernel stack, where the + ! parent may have modified them using + ! ptrace(POKEUSR). (Note that R0-R2 are + ! used by the system call handler directly + ! from the kernel stack anyway, so don't need + ! to be reloaded here.) This allows the parent + ! to rewrite system calls and args on the fly. + mov.l @(OFF_R4,r15), r4 ! arg0 + mov.l @(OFF_R5,r15), r5 + mov.l @(OFF_R6,r15), r6 + mov.l @(OFF_R7,r15), r7 ! arg3 + mov.l @(OFF_R3,r15), r3 ! syscall_nr + ! Arrange for do_syscall_trace to be called + ! again as the system call returns. + mov.l 2f, r10 ! Number of syscalls + cmp/hs r10, r3 + bf syscall_call + mov #-ENOSYS, r0 + bra syscall_exit + mov.l r0, @(OFF_R0,r15) ! Return value + +__restore_all: + mov.l 1f,r0 + jmp @r0 + nop + + .align 2 +1: .long restore_all + +/* + * Syscall interface: + * + * Syscall #: R3 + * Arguments #0 to #3: R4--R7 + * Arguments #4 to #6: R0, R1, R2 + * TRA: (number of arguments + 0x10) x 4 + * + * This code also handles delegating other traps to the BIOS/gdb stub + * according to: + * + * Trap number + * (TRA>>2) Purpose + * -------- ------- + * 0x0-0xf old syscall ABI + * 0x10-0x1f new syscall ABI + * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. + * + * Note: When we're first called, the TRA value must be shifted + * right 2 bits in order to get the value that was used as the "trapa" + * argument. + */ + + .align 2 + .globl ret_from_fork +ret_from_fork: + mov.l 1f, r8 + jsr @r8 + mov r0, r4 + bra syscall_exit + nop + .align 2 +1: .long schedule_tail + ! +ENTRY(system_call) +#if !defined(CONFIG_CPU_SH2) + mov.l 1f, r9 + mov.l @r9, r8 ! Read from TRA (Trap Address) Register +#endif + ! + ! Is the trap argument >= 0x20? (TRA will be >= 0x80) + mov #0x7f, r9 + cmp/hi r9, r8 + bt/s 0f + mov #OFF_TRA, r9 + add r15, r9 + ! + mov.l r8, @r9 ! set TRA value to tra + sti + ! Call the system call handler through the table. + ! First check for bad syscall number + mov r3, r9 + mov.l 2f, r8 ! Number of syscalls + cmp/hs r8, r9 + get_current_thread_info r8, r10 + bf good_system_call +syscall_badsys: ! Bad syscall number + mov #-ENOSYS, r0 + bra resume_userspace + mov.l r0, @(OFF_R0,r15) ! Return value + ! +0: + bra debug_trap + nop + ! +good_system_call: ! Good syscall number + mov.l @(TI_FLAGS,r8), r8 + mov #_TIF_SYSCALL_TRACE, r10 + tst r10, r8 + bf syscall_trace_entry + ! +syscall_call: + shll2 r9 ! x4 + mov.l 3f, r8 ! Load the address of sys_call_table + add r8, r9 + mov.l @r9, r8 + jsr @r8 ! jump to specific syscall handler + nop + mov.l @(OFF_R0,r15), r12 ! save r0 + mov.l r0, @(OFF_R0,r15) ! save the return value + ! +syscall_exit: + cli + ! + get_current_thread_info r8, r0 + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_ALLWORK_MASK, r0 + bf syscall_exit_work + bra __restore_all + nop + .align 2 +#if !defined(CONFIG_CPU_SH2) +1: .long TRA +#endif +2: .long NR_syscalls +3: .long sys_call_table +4: .long do_syscall_trace diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S deleted file mode 100644 index 39aaefb..0000000 --- a/arch/sh/kernel/entry.S +++ /dev/null @@ -1,843 +0,0 @@ -/* - * linux/arch/sh/entry.S - * - * Copyright (C) 1999, 2000, 2002 Niibe Yutaka - * Copyright (C) 2003 - 2006 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - */ -#include -#include -#include -#include -#include -#include -#include - -! NOTE: -! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address -! to be jumped is too far, but it causes illegal slot exception. - -/* - * entry.S contains the system-call and fault low-level handling routines. - * This also contains the timer-interrupt handler, as well as all interrupts - * and faults that can result in a task-switch. - * - * NOTE: This code handles signal-recognition, which happens every time - * after a timer-interrupt and after each system call. - * - * NOTE: This code uses a convention that instructions in the delay slot - * of a transfer-control instruction are indented by an extra space, thus: - * - * jmp @k0 ! control-transfer instruction - * ldc k1, ssr ! delay slot - * - * Stack layout in 'ret_from_syscall': - * ptrace needs to have all regs on the stack. - * if the order here is changed, it needs to be - * updated in ptrace.c and ptrace.h - * - * r0 - * ... - * r15 = stack pointer - * spc - * pr - * ssr - * gbr - * mach - * macl - * syscall # - * - */ -#if defined(CONFIG_KGDB_NMI) -NMI_VEC = 0x1c0 ! Must catch early for debounce -#endif - -/* Offsets to the stack */ -OFF_R0 = 0 /* Return value. New ABI also arg4 */ -OFF_R1 = 4 /* New ABI: arg5 */ -OFF_R2 = 8 /* New ABI: arg6 */ -OFF_R3 = 12 /* New ABI: syscall_nr */ -OFF_R4 = 16 /* New ABI: arg0 */ -OFF_R5 = 20 /* New ABI: arg1 */ -OFF_R6 = 24 /* New ABI: arg2 */ -OFF_R7 = 28 /* New ABI: arg3 */ -OFF_SP = (15*4) -OFF_PC = (16*4) -OFF_SR = (16*4+8) -OFF_TRA = (16*4+6*4) - - -#define k0 r0 -#define k1 r1 -#define k2 r2 -#define k3 r3 -#define k4 r4 - -#define g_imask r6 /* r6_bank1 */ -#define k_g_imask r6_bank /* r6_bank1 */ -#define current r7 /* r7_bank1 */ - -/* - * Kernel mode register usage: - * k0 scratch - * k1 scratch - * k2 scratch (Exception code) - * k3 scratch (Return address) - * k4 scratch - * k5 reserved - * k6 Global Interrupt Mask (0--15 << 4) - * k7 CURRENT_THREAD_INFO (pointer to current thread info) - */ - -! -! TLB Miss / Initial Page write exception handling -! _and_ -! TLB hits, but the access violate the protection. -! It can be valid access, such as stack grow and/or C-O-W. -! -! -! Find the pmd/pte entry and loadtlb -! If it's not found, cause address error (SEGV) -! -! Although this could be written in assembly language (and it'd be faster), -! this first version depends *much* on C implementation. -! - -#define CLI() \ - stc sr, r0; \ - or #0xf0, r0; \ - ldc r0, sr - -#define STI() \ - mov.l __INV_IMASK, r11; \ - stc sr, r10; \ - and r11, r10; \ - stc k_g_imask, r11; \ - or r11, r10; \ - ldc r10, sr - -#if defined(CONFIG_PREEMPT) -# define preempt_stop() CLI() -#else -# define preempt_stop() -# define resume_kernel restore_all -#endif - -#if defined(CONFIG_MMU) - .align 2 -ENTRY(tlb_miss_load) - bra call_dpf - mov #0, r5 - - .align 2 -ENTRY(tlb_miss_store) - bra call_dpf - mov #1, r5 - - .align 2 -ENTRY(initial_page_write) - bra call_dpf - mov #1, r5 - - .align 2 -ENTRY(tlb_protection_violation_load) - bra call_dpf - mov #0, r5 - - .align 2 -ENTRY(tlb_protection_violation_store) - bra call_dpf - mov #1, r5 - -call_dpf: - mov.l 1f, r0 - mov r5, r8 - mov.l @r0, r6 - mov r6, r9 - mov.l 2f, r0 - sts pr, r10 - jsr @r0 - mov r15, r4 - ! - tst r0, r0 - bf/s 0f - lds r10, pr - rts - nop -0: STI() - mov.l 3f, r0 - mov r9, r6 - mov r8, r5 - jmp @r0 - mov r15, r4 - - .align 2 -1: .long MMU_TEA -2: .long __do_page_fault -3: .long do_page_fault - - .align 2 -ENTRY(address_error_load) - bra call_dae - mov #0,r5 ! writeaccess = 0 - - .align 2 -ENTRY(address_error_store) - bra call_dae - mov #1,r5 ! writeaccess = 1 - - .align 2 -call_dae: - mov.l 1f, r0 - mov.l @r0, r6 ! address - mov.l 2f, r0 - jmp @r0 - mov r15, r4 ! regs - - .align 2 -1: .long MMU_TEA -2: .long do_address_error -#endif /* CONFIG_MMU */ - -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) -! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. -! If both are configured, handle the debug traps (breakpoints) in SW, -! but still allow BIOS traps to FW. - - .align 2 -debug_kernel: -#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) - /* Force BIOS call to FW (debug_trap put TRA in r8) */ - mov r8,r0 - shlr2 r0 - cmp/eq #0x3f,r0 - bt debug_kernel_fw -#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ - -debug_enter: -#if defined(CONFIG_SH_KGDB) - /* Jump to kgdb, pass stacked regs as arg */ -debug_kernel_sw: - mov.l 3f, r0 - jmp @r0 - mov r15, r4 - .align 2 -3: .long kgdb_handle_exception -#endif /* CONFIG_SH_KGDB */ - -#if defined(CONFIG_SH_STANDARD_BIOS) - /* Unwind the stack and jmp to the debug entry */ -debug_kernel_fw: - mov.l @r15+, r0 - mov.l @r15+, r1 - mov.l @r15+, r2 - mov.l @r15+, r3 - mov.l @r15+, r4 - mov.l @r15+, r5 - mov.l @r15+, r6 - mov.l @r15+, r7 - stc sr, r8 - mov.l 1f, r9 ! BL =1, RB=1, IMASK=0x0F - or r9, r8 - ldc r8, sr ! here, change the register bank - mov.l @r15+, r8 - mov.l @r15+, r9 - mov.l @r15+, r10 - mov.l @r15+, r11 - mov.l @r15+, r12 - mov.l @r15+, r13 - mov.l @r15+, r14 - mov.l @r15+, k0 - ldc.l @r15+, spc - lds.l @r15+, pr - mov.l @r15+, k1 - ldc.l @r15+, gbr - lds.l @r15+, mach - lds.l @r15+, macl - mov k0, r15 - ! - mov.l 2f, k0 - mov.l @k0, k0 - jmp @k0 - ldc k1, ssr - .align 2 -1: .long 0x300000f0 -2: .long gdb_vbr_vector -#endif /* CONFIG_SH_STANDARD_BIOS */ - -#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ - - - .align 2 -debug_trap: -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - shll r0 - shll r0 ! kernel space? - bt/s debug_kernel -#endif - mov.l @r15, r0 ! Restore R0 value - mov.l 1f, r8 - jmp @r8 - nop - - .align 2 -ENTRY(exception_error) - ! - STI() - mov.l 2f, r0 - jmp @r0 - nop - -! - .align 2 -1: .long break_point_trap_software -2: .long do_exception_error - - .align 2 -ret_from_exception: - preempt_stop() -ENTRY(ret_from_irq) - ! - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - shll r0 - shll r0 ! kernel space? - bt/s resume_kernel ! Yes, it's from kernel, go back soon - GET_THREAD_INFO(r8) - -#ifdef CONFIG_PREEMPT - bra resume_userspace - nop -ENTRY(resume_kernel) - mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count - tst r0, r0 - bf noresched -need_resched: - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_NEED_RESCHED, r0 ! need_resched set? - bt noresched - - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - and #0xf0, r0 ! interrupts off (exception path)? - cmp/eq #0xf0, r0 - bt noresched - - mov.l 1f, r0 - mov.l r0, @(TI_PRE_COUNT,r8) - - STI() - mov.l 2f, r0 - jsr @r0 - nop - mov #0, r0 - mov.l r0, @(TI_PRE_COUNT,r8) - CLI() - - bra need_resched - nop -noresched: - bra restore_all - nop - - .align 2 -1: .long PREEMPT_ACTIVE -2: .long schedule -#endif - -ENTRY(resume_userspace) - ! r8: current_thread_info - CLI() - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_WORK_MASK, r0 - bt/s restore_all - tst #_TIF_NEED_RESCHED, r0 - - .align 2 -work_pending: - ! r0: current_thread_info->flags - ! r8: current_thread_info - ! t: result of "tst #_TIF_NEED_RESCHED, r0" - bf/s work_resched - tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 -work_notifysig: - bt/s restore_all - mov r15, r4 - mov r12, r5 ! set arg1(save_r0) - mov r0, r6 - mov.l 2f, r1 - mova restore_all, r0 - jmp @r1 - lds r0, pr -work_resched: -#ifndef CONFIG_PREEMPT - ! gUSA handling - mov.l @(OFF_SP,r15), r0 ! get user space stack pointer - mov r0, r1 - shll r0 - bf/s 1f - shll r0 - bf/s 1f - mov #OFF_PC, r0 - ! SP >= 0xc0000000 : gUSA mark - mov.l @(r0,r15), r2 ! get user space PC (program counter) - mov.l @(OFF_R0,r15), r3 ! end point - cmp/hs r3, r2 ! r2 >= r3? - bt 1f - add r3, r1 ! rewind point #2 - mov.l r1, @(r0,r15) ! reset PC to rewind point #2 - ! -1: -#endif - mov.l 1f, r1 - jsr @r1 ! schedule - nop - CLI() - ! - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_WORK_MASK, r0 - bt restore_all - bra work_pending - tst #_TIF_NEED_RESCHED, r0 - - .align 2 -1: .long schedule -2: .long do_notify_resume - - .align 2 -syscall_exit_work: - ! r0: current_thread_info->flags - ! r8: current_thread_info - tst #_TIF_SYSCALL_TRACE, r0 - bt/s work_pending - tst #_TIF_NEED_RESCHED, r0 - STI() - ! XXX setup arguments... - mov.l 4f, r0 ! do_syscall_trace - jsr @r0 - nop - bra resume_userspace - nop - - .align 2 -syscall_trace_entry: - ! Yes it is traced. - ! XXX setup arguments... - mov.l 4f, r11 ! Call do_syscall_trace which notifies - jsr @r11 ! superior (will chomp R[0-7]) - nop - ! Reload R0-R4 from kernel stack, where the - ! parent may have modified them using - ! ptrace(POKEUSR). (Note that R0-R2 are - ! used by the system call handler directly - ! from the kernel stack anyway, so don't need - ! to be reloaded here.) This allows the parent - ! to rewrite system calls and args on the fly. - mov.l @(OFF_R4,r15), r4 ! arg0 - mov.l @(OFF_R5,r15), r5 - mov.l @(OFF_R6,r15), r6 - mov.l @(OFF_R7,r15), r7 ! arg3 - mov.l @(OFF_R3,r15), r3 ! syscall_nr - ! Arrange for do_syscall_trace to be called - ! again as the system call returns. - mov.l 2f, r10 ! Number of syscalls - cmp/hs r10, r3 - bf syscall_call - mov #-ENOSYS, r0 - bra syscall_exit - mov.l r0, @(OFF_R0,r15) ! Return value - -/* - * Syscall interface: - * - * Syscall #: R3 - * Arguments #0 to #3: R4--R7 - * Arguments #4 to #6: R0, R1, R2 - * TRA: (number of arguments + 0x10) x 4 - * - * This code also handles delegating other traps to the BIOS/gdb stub - * according to: - * - * Trap number - * (TRA>>2) Purpose - * -------- ------- - * 0x0-0xf old syscall ABI - * 0x10-0x1f new syscall ABI - * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. - * - * Note: When we're first called, the TRA value must be shifted - * right 2 bits in order to get the value that was used as the "trapa" - * argument. - */ - - .align 2 - .globl ret_from_fork -ret_from_fork: - mov.l 1f, r8 - jsr @r8 - mov r0, r4 - bra syscall_exit - nop - .align 2 -1: .long schedule_tail - ! -ENTRY(system_call) - mov.l 1f, r9 - mov.l @r9, r8 ! Read from TRA (Trap Address) Register - ! - ! Is the trap argument >= 0x20? (TRA will be >= 0x80) - mov #0x7f, r9 - cmp/hi r9, r8 - bt/s 0f - mov #OFF_TRA, r9 - add r15, r9 - ! - mov.l r8, @r9 ! set TRA value to tra - STI() - ! Call the system call handler through the table. - ! First check for bad syscall number - mov r3, r9 - mov.l 2f, r8 ! Number of syscalls - cmp/hs r8, r9 - bf/s good_system_call - GET_THREAD_INFO(r8) -syscall_badsys: ! Bad syscall number - mov #-ENOSYS, r0 - bra resume_userspace - mov.l r0, @(OFF_R0,r15) ! Return value - ! -0: - bra debug_trap - nop - ! -good_system_call: ! Good syscall number - mov.l @(TI_FLAGS,r8), r8 - mov #_TIF_SYSCALL_TRACE, r10 - tst r10, r8 - bf syscall_trace_entry - ! -syscall_call: - shll2 r9 ! x4 - mov.l 3f, r8 ! Load the address of sys_call_table - add r8, r9 - mov.l @r9, r8 - jsr @r8 ! jump to specific syscall handler - nop - mov.l @(OFF_R0,r15), r12 ! save r0 - mov.l r0, @(OFF_R0,r15) ! save the return value - ! -syscall_exit: - CLI() - ! - GET_THREAD_INFO(r8) - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_ALLWORK_MASK, r0 - bf syscall_exit_work -restore_all: - mov.l @r15+, r0 - mov.l @r15+, r1 - mov.l @r15+, r2 - mov.l @r15+, r3 - mov.l @r15+, r4 - mov.l @r15+, r5 - mov.l @r15+, r6 - mov.l @r15+, r7 - ! - stc sr, r8 - mov.l 7f, r9 - or r9, r8 ! BL =1, RB=1 - ldc r8, sr ! here, change the register bank - ! - mov.l @r15+, r8 - mov.l @r15+, r9 - mov.l @r15+, r10 - mov.l @r15+, r11 - mov.l @r15+, r12 - mov.l @r15+, r13 - mov.l @r15+, r14 - mov.l @r15+, k4 ! original stack pointer - ldc.l @r15+, spc - lds.l @r15+, pr - mov.l @r15+, k3 ! original SR - ldc.l @r15+, gbr - lds.l @r15+, mach - lds.l @r15+, macl - add #4, r15 ! Skip syscall number - ! -#ifdef CONFIG_SH_DSP - mov.l @r15+, k0 ! DSP mode marker - mov.l 5f, k1 - cmp/eq k0, k1 ! Do we have a DSP stack frame? - bf skip_restore - - stc sr, k0 ! Enable CPU DSP mode - or k1, k0 ! (within kernel it may be disabled) - ldc k0, sr - mov r2, k0 ! Backup r2 - - ! Restore DSP registers from stack - mov r15, r2 - movs.l @r2+, a1 - movs.l @r2+, a0g - movs.l @r2+, a1g - movs.l @r2+, m0 - movs.l @r2+, m1 - mov r2, r15 - - lds.l @r15+, a0 - lds.l @r15+, x0 - lds.l @r15+, x1 - lds.l @r15+, y0 - lds.l @r15+, y1 - lds.l @r15+, dsr - ldc.l @r15+, rs - ldc.l @r15+, re - ldc.l @r15+, mod - - mov k0, r2 ! Restore r2 -skip_restore: -#endif - ! - ! Calculate new SR value - mov k3, k2 ! original SR value - mov.l 9f, k1 - and k1, k2 ! Mask orignal SR value - ! - mov k3, k0 ! Calculate IMASK-bits - shlr2 k0 - and #0x3c, k0 - cmp/eq #0x3c, k0 - bt/s 6f - shll2 k0 - mov g_imask, k0 - ! -6: or k0, k2 ! Set the IMASK-bits - ldc k2, ssr - ! -#if defined(CONFIG_KGDB_NMI) - ! Clear in_nmi - mov.l 6f, k0 - mov #0, k1 - mov.b k1, @k0 -#endif - mov.l @r15+, k2 ! restore EXPEVT - mov k4, r15 - rte - nop - - .align 2 -1: .long TRA -2: .long NR_syscalls -3: .long sys_call_table -4: .long do_syscall_trace -5: .long 0x00001000 ! DSP -7: .long 0x30000000 -9: -__INV_IMASK: - .long 0xffffff0f ! ~(IMASK) - -! Exception Vector Base -! -! Should be aligned page boundary. -! - .balign 4096,0,4096 -ENTRY(vbr_base) - .long 0 -! - .balign 256,0,256 -general_exception: - mov.l 1f, k2 - mov.l 2f, k3 - bra handle_exception - mov.l @k2, k2 - .align 2 -1: .long EXPEVT -2: .long ret_from_exception -! -! - .balign 1024,0,1024 -tlb_miss: - mov.l 1f, k2 - mov.l 4f, k3 - bra handle_exception - mov.l @k2, k2 -! - .balign 512,0,512 -interrupt: - mov.l 2f, k2 - mov.l 3f, k3 -#if defined(CONFIG_KGDB_NMI) - ! Debounce (filter nested NMI) - mov.l @k2, k0 - mov.l 5f, k1 - cmp/eq k1, k0 - bf 0f - mov.l 6f, k1 - tas.b @k1 - bt 0f - rte - nop - .align 2 -5: .long NMI_VEC -6: .long in_nmi -0: -#endif /* defined(CONFIG_KGDB_NMI) */ - bra handle_exception - mov #-1, k2 ! interrupt exception marker - - .align 2 -1: .long EXPEVT -2: .long INTEVT -3: .long ret_from_irq -4: .long ret_from_exception - -! -! - .align 2 -ENTRY(handle_exception) - ! Using k0, k1 for scratch registers (r0_bank1, r1_bank), - ! save all registers onto stack. - ! - stc ssr, k0 ! Is it from kernel space? - shll k0 ! Check MD bit (bit30) by shifting it into... - shll k0 ! ...the T bit - bt/s 1f ! It's a kernel to kernel transition. - mov r15, k0 ! save original stack to k0 - /* User space to kernel */ - mov #(THREAD_SIZE >> 8), k1 - shll8 k1 ! k1 := THREAD_SIZE - add current, k1 - mov k1, r15 ! change to kernel stack - ! -1: mov.l 2f, k1 - ! -#ifdef CONFIG_SH_DSP - mov.l r2, @-r15 ! Save r2, we need another reg - stc sr, k4 - mov.l 1f, r2 - tst r2, k4 ! Check if in DSP mode - mov.l @r15+, r2 ! Restore r2 now - bt/s skip_save - mov #0, k4 ! Set marker for no stack frame - - mov r2, k4 ! Backup r2 (in k4) for later - - ! Save DSP registers on stack - stc.l mod, @-r15 - stc.l re, @-r15 - stc.l rs, @-r15 - sts.l dsr, @-r15 - sts.l y1, @-r15 - sts.l y0, @-r15 - sts.l x1, @-r15 - sts.l x0, @-r15 - sts.l a0, @-r15 - - ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr. - - ! FIXME: Make sure that this is still the case with newer toolchains, - ! as we're not at all interested in supporting ancient toolchains at - ! this point. -- PFM. - - mov r15, r2 - .word 0xf653 ! movs.l a1, @-r2 - .word 0xf6f3 ! movs.l a0g, @-r2 - .word 0xf6d3 ! movs.l a1g, @-r2 - .word 0xf6c3 ! movs.l m0, @-r2 - .word 0xf6e3 ! movs.l m1, @-r2 - mov r2, r15 - - mov k4, r2 ! Restore r2 - mov.l 1f, k4 ! Force DSP stack frame -skip_save: - mov.l k4, @-r15 ! Push DSP mode marker onto stack -#endif - ! Save the user registers on the stack. - mov.l k2, @-r15 ! EXPEVT - - mov #-1, k4 - mov.l k4, @-r15 ! set TRA (default: -1) - ! - sts.l macl, @-r15 - sts.l mach, @-r15 - stc.l gbr, @-r15 - stc.l ssr, @-r15 - sts.l pr, @-r15 - stc.l spc, @-r15 - ! - lds k3, pr ! Set the return address to pr - ! - mov.l k0, @-r15 ! save orignal stack - mov.l r14, @-r15 - mov.l r13, @-r15 - mov.l r12, @-r15 - mov.l r11, @-r15 - mov.l r10, @-r15 - mov.l r9, @-r15 - mov.l r8, @-r15 - ! - stc sr, r8 ! Back to normal register bank, and - or k1, r8 ! Block all interrupts - mov.l 3f, k1 - and k1, r8 ! ... - ldc r8, sr ! ...changed here. - ! - mov.l r7, @-r15 - mov.l r6, @-r15 - mov.l r5, @-r15 - mov.l r4, @-r15 - mov.l r3, @-r15 - mov.l r2, @-r15 - mov.l r1, @-r15 - mov.l r0, @-r15 - - /* - * This gets a bit tricky.. in the INTEVT case we don't want to use - * the VBR offset as a destination in the jump call table, since all - * of the destinations are the same. In this case, (interrupt) sets - * a marker in r2 (now r2_bank since SR.RB changed), which we check - * to determine the exception type. For all other exceptions, we - * forcibly read EXPEVT from memory and fix up the jump address, in - * the interrupt exception case we jump to do_IRQ() and defer the - * INTEVT read until there. As a bonus, we can also clean up the SR.RB - * checks that do_IRQ() was doing.. - */ - stc r2_bank, r8 - cmp/pz r8 - bf interrupt_exception - shlr2 r8 - shlr r8 - mov.l 4f, r9 - add r8, r9 - mov.l @r9, r9 - jmp @r9 - nop - rts - nop - - .align 2 -1: .long 0x00001000 ! DSP=1 -2: .long 0x000080f0 ! FD=1, IMASK=15 -3: .long 0xcfffffff ! RB=0, BL=0 -4: .long exception_handling_table - -interrupt_exception: - mov.l 1f, r9 - jmp @r9 - nop - rts - nop - - .align 2 -1: .long do_IRQ - - .align 2 -ENTRY(exception_none) - rts - nop diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S index f5f53d1..b5ff232 100644 --- a/arch/sh/kernel/head.S +++ b/arch/sh/kernel/head.S @@ -53,8 +53,10 @@ ENTRY(_stext) ldc r0, sr ! Initialize global interrupt mask mov #0, r0 +#ifdef CONFIG_CPU_HAS_SR_RB ldc r0, r6_bank - +#endif + /* * Prefetch if possible to reduce cache miss penalty. * @@ -71,8 +73,10 @@ ENTRY(_stext) mov #(THREAD_SIZE >> 8), r1 shll8 r1 ! r1 = THREAD_SIZE sub r1, r0 ! +#ifdef CONFIG_CPU_HAS_SR_RB ldc r0, r7_bank ! ... and initial thread_info - +#endif + ! Clear BSS area mov.l 3f, r1 add #4, r1 @@ -95,7 +99,11 @@ ENTRY(_stext) nop .balign 4 +#if defined(CONFIG_CPU_SH2) +1: .long 0x000000F0 ! IMASK=0xF +#else 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF +#endif 2: .long init_thread_union+THREAD_SIZE 3: .long __bss_start 4: .long _end diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 944128c..edf4d2d 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -84,9 +84,10 @@ #endif asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - struct pt_regs *old_regs = set_irq_regs(®s); + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + struct pt_regs *old_regs = set_irq_regs(regs); int irq; #ifdef CONFIG_4KSTACKS union irq_ctx *curctx, *irqctx; diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index a52b13a..f3e2631 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -385,10 +385,11 @@ #endif asmlinkage int sys_fork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); #ifdef CONFIG_MMU - return do_fork(SIGCHLD, regs.regs[15], ®s, 0, NULL, NULL); + return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); #else /* fork almost works, enough to trick you into looking elsewhere :-( */ return -EINVAL; @@ -398,11 +399,12 @@ #endif asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, unsigned long parent_tidptr, unsigned long child_tidptr, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); if (!newsp) - newsp = regs.regs[15]; - return do_fork(clone_flags, newsp, ®s, 0, + newsp = regs->regs[15]; + return do_fork(clone_flags, newsp, regs, 0, (int __user *)parent_tidptr, (int __user *)child_tidptr); } @@ -418,9 +420,10 @@ asmlinkage int sys_clone(unsigned long c */ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], ®s, + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); } @@ -429,8 +432,9 @@ asmlinkage int sys_vfork(unsigned long r */ asmlinkage int sys_execve(char *ufilename, char **uargv, char **uenvp, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); int error; char *filename; @@ -442,7 +446,7 @@ asmlinkage int sys_execve(char *ufilenam error = do_execve(filename, (char __user * __user *)uargv, (char __user * __user *)uenvp, - ®s); + regs); if (error == 0) { task_lock(current); current->ptrace &= ~PT_DTRACE; @@ -472,9 +476,7 @@ unsigned long get_wchan(struct task_stru return pc; } -asmlinkage void break_point_trap(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs regs) +asmlinkage void break_point_trap(void) { /* Clear tracing. */ #if defined(CONFIG_CPU_SH4A) @@ -492,8 +494,10 @@ #endif asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - regs.pc -= 2; + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + + regs->pc -= 2; force_sig(SIGTRAP, current); } diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 36d86f9..696ca75 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -392,6 +392,7 @@ static int __init topology_init(void) subsys_initcall(topology_init); static const char *cpu_name[] = { + [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", [CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300", [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", @@ -404,6 +405,7 @@ static const char *cpu_name[] = { [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501", [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", + [CPU_SH7785] = "SH7785", [CPU_SH_NONE] = "Unknown" }; diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c index 9daad70..29872a8 100644 --- a/arch/sh/kernel/sh_ksyms.c +++ b/arch/sh/kernel/sh_ksyms.c @@ -74,8 +74,6 @@ DECLARE_EXPORT(__lshrdi3); DECLARE_EXPORT(__movstr); DECLARE_EXPORT(__movstrSI16); -EXPORT_SYMBOL(strcpy); - #ifdef CONFIG_CPU_SH4 DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index 5213f5b..50d7c49 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c @@ -37,7 +37,7 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); @@ -52,7 +52,7 @@ sys_sigsuspend(old_sigset_t mask, return -ERESTARTNOHAND; } -asmlinkage int +asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) { @@ -87,9 +87,11 @@ sys_sigaction(int sig, const struct old_ asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - return do_sigaltstack(uss, uoss, regs.regs[15]); + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + + return do_sigaltstack(uss, uoss, regs->regs[15]); } @@ -98,7 +100,11 @@ sys_sigaltstack(const stack_t __user *us */ #define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */ -#define TRAP16 0xc310 /* Syscall w/no args (NR in R3) */ +#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A) +#define TRAP_NOARG 0xc320 /* Syscall w/no args (NR in R3) */ +#else +#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) */ +#endif #define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */ struct sigframe @@ -194,9 +200,10 @@ #endif asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - struct sigframe __user *frame = (struct sigframe __user *)regs.regs[15]; + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + struct sigframe __user *frame = (struct sigframe __user *)regs->regs[15]; sigset_t set; int r0; @@ -216,7 +223,7 @@ asmlinkage int sys_sigreturn(unsigned lo recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(®s, &frame->sc, &r0)) + if (restore_sigcontext(regs, &frame->sc, &r0)) goto badframe; return r0; @@ -227,9 +234,10 @@ badframe: asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.regs[15]; + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15]; sigset_t set; stack_t st; int r0; @@ -246,14 +254,14 @@ asmlinkage int sys_rt_sigreturn(unsigned recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(®s, &frame->uc.uc_mcontext, &r0)) + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) goto badframe; if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack(&st, NULL, regs.regs[15]); + do_sigaltstack(&st, NULL, regs->regs[15]); return r0; @@ -350,7 +358,7 @@ #endif } else { /* Generate return code (system call to sigreturn) */ err |= __put_user(MOVW(7), &frame->retcode[0]); - err |= __put_user(TRAP16, &frame->retcode[1]); + err |= __put_user(TRAP_NOARG, &frame->retcode[1]); err |= __put_user(OR_R0_R0, &frame->retcode[2]); err |= __put_user(OR_R0_R0, &frame->retcode[3]); err |= __put_user(OR_R0_R0, &frame->retcode[4]); @@ -430,7 +438,7 @@ #endif } else { /* Generate return code (system call to rt_sigreturn) */ err |= __put_user(MOVW(7), &frame->retcode[0]); - err |= __put_user(TRAP16, &frame->retcode[1]); + err |= __put_user(TRAP_NOARG, &frame->retcode[1]); err |= __put_user(OR_R0_R0, &frame->retcode[2]); err |= __put_user(OR_R0_R0, &frame->retcode[3]); err |= __put_user(OR_R0_R0, &frame->retcode[4]); diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 8fde950..5083b6e 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c @@ -33,14 +33,15 @@ #include */ asmlinkage int sys_pipe(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); int fd[2]; int error; error = do_pipe(fd); if (!error) { - regs.regs[1] = fd[1]; + regs->regs[1] = fd[1]; return fd[0]; } return error; @@ -50,6 +51,7 @@ unsigned long shm_align_mask = PAGE_SIZE EXPORT_SYMBOL(shm_align_mask); +#ifdef CONFIG_MMU /* * To avoid cache aliases, we map the shared page with same color. */ @@ -135,6 +137,7 @@ full_search: addr = COLOUR_ALIGN(addr, pgoff); } } +#endif /* CONFIG_MMU */ static inline long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, diff --git a/arch/sh/kernel/timers/Makefile b/arch/sh/kernel/timers/Makefile index 151a6a3..bcf244f 100644 --- a/arch/sh/kernel/timers/Makefile +++ b/arch/sh/kernel/timers/Makefile @@ -5,4 +5,6 @@ # obj-y := timer.o obj-$(CONFIG_SH_TMU) += timer-tmu.o +obj-$(CONFIG_SH_MTU2) += timer-mtu2.o +obj-$(CONFIG_SH_CMT) += timer-cmt.o diff --git a/arch/sh/kernel/timers/timer-cmt.c b/arch/sh/kernel/timers/timer-cmt.c new file mode 100644 index 0000000..24b0399 --- /dev/null +++ b/arch/sh/kernel/timers/timer-cmt.c @@ -0,0 +1,203 @@ +/* + * arch/sh/kernel/timers/timer-cmt.c - CMT Timer Support + * + * Copyright (C) 2005 Yoshinori Sato + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_CPU_SUBTYPE_SH7619) +#define CMT_CMSTR 0xf84a0070 +#define CMT_CMCSR_0 0xf84a0072 +#define CMT_CMCNT_0 0xf84a0074 +#define CMT_CMCOR_0 0xf84a0076 +#define CMT_CMCSR_1 0xf84a0078 +#define CMT_CMCNT_1 0xf84a007a +#define CMT_CMCOR_1 0xf84a007c + +#define STBCR3 0xf80a0000 +#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR3) & ~0x10, STBCR3); } while(0) +#define CMT_CMCSR_INIT 0x0040 +#define CMT_CMCSR_CALIB 0x0000 +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +#define CMT_CMSTR 0xfffec000 +#define CMT_CMCSR_0 0xfffec002 +#define CMT_CMCNT_0 0xfffec004 +#define CMT_CMCOR_0 0xfffec006 + +#define STBCR4 0xfffe040c +#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR4) & ~0x04, STBCR4); } while(0) +#define CMT_CMCSR_INIT 0x0040 +#define CMT_CMCSR_CALIB 0x0000 +#else +#error "Unknown CPU SUBTYPE" +#endif + +static DEFINE_SPINLOCK(cmt0_lock); + +static unsigned long cmt_timer_get_offset(void) +{ + int count; + unsigned long flags; + + static unsigned short count_p = 0xffff; /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + spin_lock_irqsave(&cmt0_lock, flags); + /* timer count may underflow right here */ + count = ctrl_inw(CMT_CMCOR_0); + count -= ctrl_inw(CMT_CMCNT_0); + + jiffies_t = jiffies; + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there is one kind of problem that must be avoided here: + * 1. the timer counter underflows + */ + + if (jiffies_t == jiffies_p) { + if (count > count_p) { + /* the nutcase */ + if (ctrl_inw(CMT_CMCSR_0) & 0x80) { /* Check CMF bit */ + count -= LATCH; + } else { + printk("%s (): hardware timer problem?\n", + __FUNCTION__); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + spin_unlock_irqrestore(&cmt0_lock, flags); + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; +} + +static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id) +{ + unsigned long timer_status; + + /* Clear CMF bit */ + timer_status = ctrl_inw(CMT_CMCSR_0); + timer_status &= ~0x80; + ctrl_outw(timer_status, CMT_CMCSR_0); + + /* + * Here we are in the timer irq handler. We just have irqs locally + * disabled but we don't know if the timer_bh is running on the other + * CPU. We need to avoid to SMP race with it. NOTE: we don' t need + * the irq version of write_lock because as just said we have irq + * locally disabled. -arca + */ + write_seqlock(&xtime_lock); + handle_timer_tick(); + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; +} + +static struct irqaction cmt_irq = { + .name = "timer", + .handler = cmt_timer_interrupt, + .flags = IRQF_DISABLED, + .mask = CPU_MASK_NONE, +}; + +static void cmt_clk_init(struct clk *clk) +{ + u8 divisor = CMT_CMCSR_INIT & 0x3; + ctrl_inw(CMT_CMCSR_0); + ctrl_outw(CMT_CMCSR_INIT, CMT_CMCSR_0); + clk->parent = clk_get("module_clk"); + clk->rate = clk->parent->rate / (8 << (divisor << 1)); +} + +static void cmt_clk_recalc(struct clk *clk) +{ + u8 divisor = ctrl_inw(CMT_CMCSR_0) & 0x3; + clk->rate = clk->parent->rate / (8 << (divisor << 1)); +} + +static struct clk_ops cmt_clk_ops = { + .init = cmt_clk_init, + .recalc = cmt_clk_recalc, +}; + +static struct clk cmt0_clk = { + .name = "cmt0_clk", + .ops = &cmt_clk_ops, +}; + +static int cmt_timer_start(void) +{ + ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR); + return 0; +} + +static int cmt_timer_stop(void) +{ + ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR); + return 0; +} + +static int cmt_timer_init(void) +{ + unsigned long interval; + + cmt_clock_enable(); + + setup_irq(CONFIG_SH_TIMER_IRQ, &cmt_irq); + + cmt0_clk.parent = clk_get("module_clk"); + + cmt_timer_stop(); + + interval = cmt0_clk.parent->rate / 8 / HZ; + printk(KERN_INFO "Interval = %ld\n", interval); + + ctrl_outw(interval, CMT_CMCOR_0); + + clk_register(&cmt0_clk); + clk_enable(&cmt0_clk); + + cmt_timer_start(); + + return 0; +} + +struct sys_timer_ops cmt_timer_ops = { + .init = cmt_timer_init, + .start = cmt_timer_start, + .stop = cmt_timer_stop, +#ifndef CONFIG_GENERIC_TIME + .get_offset = cmt_timer_get_offset, +#endif +}; + +struct sys_timer cmt_timer = { + .name = "cmt", + .ops = &cmt_timer_ops, +}; diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c new file mode 100644 index 0000000..92c98b5 --- /dev/null +++ b/arch/sh/kernel/timers/timer-mtu2.c @@ -0,0 +1,208 @@ +/* + * arch/sh/kernel/timers/timer-mtu2.c - MTU2 Timer Support + * + * Copyright (C) 2005 Paul Mundt + * + * Based off of arch/sh/kernel/timers/timer-tmu.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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * We use channel 1 for our lowly system timer. Channel 2 would be the other + * likely candidate, but we leave it alone as it has higher divisors that + * would be of more use to other more interesting applications. + * + * TODO: Presently we only implement a 16-bit single-channel system timer. + * However, we can implement channel cascade if we go the overflow route and + * get away with using 2 MTU2 channels as a 32-bit timer. + */ + +static DEFINE_SPINLOCK(mtu2_lock); + +#define MTU2_TSTR 0xfffe4280 +#define MTU2_TCR_1 0xfffe4380 +#define MTU2_TMDR_1 0xfffe4381 +#define MTU2_TIOR_1 0xfffe4382 +#define MTU2_TIER_1 0xfffe4384 +#define MTU2_TSR_1 0xfffe4385 +#define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */ +#define MTU2_TGRA_1 0xfffe438a + +#define STBCR3 0xfffe0408 + +#define MTU2_TSTR_CST1 (1 << 1) /* Counter Start 1 */ + +#define MTU2_TSR_TGFA (1 << 0) /* GRA compare match */ + +#define MTU2_TIER_TGIEA (1 << 0) /* GRA compare match interrupt enable */ + +#define MTU2_TCR_INIT 0x22 + +#define MTU2_TCR_CALIB 0x00 + +static unsigned long mtu2_timer_get_offset(void) +{ + int count; + unsigned long flags; + + static int count_p = 0x7fff; /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + spin_lock_irqsave(&mtu2_lock, flags); + /* timer count may underflow right here */ + count = ctrl_inw(MTU2_TCNT_1); /* read the latched count */ + + jiffies_t = jiffies; + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there is one kind of problem that must be avoided here: + * 1. the timer counter underflows + */ + + if (jiffies_t == jiffies_p) { + if (count > count_p) { + if (ctrl_inb(MTU2_TSR_1) & MTU2_TSR_TGFA) { + count -= LATCH; + } else { + printk("%s (): hardware timer problem?\n", + __FUNCTION__); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + spin_unlock_irqrestore(&mtu2_lock, flags); + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; +} + +static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id) +{ + unsigned long timer_status; + + /* Clear TGFA bit */ + timer_status = ctrl_inb(MTU2_TSR_1); + timer_status &= ~MTU2_TSR_TGFA; + ctrl_outb(timer_status, MTU2_TSR_1); + + /* Do timer tick */ + write_seqlock(&xtime_lock); + handle_timer_tick(); + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; +} + +static struct irqaction mtu2_irq = { + .name = "timer", + .handler = mtu2_timer_interrupt, + .flags = IRQF_DISABLED, + .mask = CPU_MASK_NONE, +}; + +static unsigned int divisors[] = { 1, 4, 16, 64, 1, 1, 256 }; + +static void mtu2_clk_init(struct clk *clk) +{ + u8 idx = MTU2_TCR_INIT & 0x7; + + clk->rate = clk->parent->rate / divisors[idx]; + /* Start TCNT counting */ + ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR); + +} + +static void mtu2_clk_recalc(struct clk *clk) +{ + u8 idx = ctrl_inb(MTU2_TCR_1) & 0x7; + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops mtu2_clk_ops = { + .init = mtu2_clk_init, + .recalc = mtu2_clk_recalc, +}; + +static struct clk mtu2_clk1 = { + .name = "mtu2_clk1", + .ops = &mtu2_clk_ops, +}; + +static int mtu2_timer_start(void) +{ + ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR); + return 0; +} + +static int mtu2_timer_stop(void) +{ + ctrl_outb(ctrl_inb(MTU2_TSTR) & ~MTU2_TSTR_CST1, MTU2_TSTR); + return 0; +} + +static int mtu2_timer_init(void) +{ + u8 tmp; + unsigned long interval; + + setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq); + + mtu2_clk1.parent = clk_get("module_clk"); + + ctrl_outb(ctrl_inb(STBCR3) & (~0x20), STBCR3); + + /* Normal operation */ + ctrl_outb(0, MTU2_TMDR_1); + ctrl_outb(MTU2_TCR_INIT, MTU2_TCR_1); + ctrl_outb(0x01, MTU2_TIOR_1); + + /* Enable underflow interrupt */ + ctrl_outb(ctrl_inb(MTU2_TIER_1) | MTU2_TIER_TGIEA, MTU2_TIER_1); + + interval = CONFIG_SH_PCLK_FREQ / 16 / HZ; + printk(KERN_INFO "Interval = %ld\n", interval); + + ctrl_outw(interval, MTU2_TGRA_1); + ctrl_outw(0, MTU2_TCNT_1); + + clk_register(&mtu2_clk1); + clk_enable(&mtu2_clk1); + + return 0; +} + +struct sys_timer_ops mtu2_timer_ops = { + .init = mtu2_timer_init, + .start = mtu2_timer_start, + .stop = mtu2_timer_stop, +#ifndef CONFIG_GENERIC_TIME + .get_offset = mtu2_timer_get_offset, +#endif +}; + +struct sys_timer mtu2_timer = { + .name = "mtu2", + .ops = &mtu2_timer_ops, +}; diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c index 2492701..06a70db 100644 --- a/arch/sh/kernel/timers/timer-tmu.c +++ b/arch/sh/kernel/timers/timer-tmu.c @@ -149,7 +149,7 @@ static int tmu_timer_init(void) { unsigned long interval; - setup_irq(TIMER_IRQ, &tmu_irq); + setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq); tmu0_clk.parent = clk_get("module_clk"); diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c index dc1f631..a6bcc91 100644 --- a/arch/sh/kernel/timers/timer.c +++ b/arch/sh/kernel/timers/timer.c @@ -17,6 +17,12 @@ static struct sys_timer *sys_timers[] __ #ifdef CONFIG_SH_TMU &tmu_timer, #endif +#ifdef CONFIG_SH_MTU2 + &mtu2_timer, +#endif +#ifdef CONFIG_SH_CMT + &cmt_timer, +#endif NULL, }; diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 53dfa55..0ee2980 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -23,8 +23,8 @@ #include #ifdef CONFIG_SH_KGDB #include -#define CHK_REMOTE_DEBUG(regs) \ -{ \ +#define CHK_REMOTE_DEBUG(regs) \ +{ \ if (kgdb_debug_hook && !user_mode(regs))\ (*kgdb_debug_hook)(regs); \ } @@ -33,8 +33,13 @@ #define CHK_REMOTE_DEBUG(regs) #endif #ifdef CONFIG_CPU_SH2 -#define TRAP_RESERVED_INST 4 -#define TRAP_ILLEGAL_SLOT_INST 6 +# define TRAP_RESERVED_INST 4 +# define TRAP_ILLEGAL_SLOT_INST 6 +# define TRAP_ADDRESS_ERROR 9 +# ifdef CONFIG_CPU_SH2A +# define TRAP_DIVZERO_ERROR 17 +# define TRAP_DIVOVF_ERROR 18 +# endif #else #define TRAP_RESERVED_INST 12 #define TRAP_ILLEGAL_SLOT_INST 13 @@ -88,7 +93,7 @@ void die(const char * str, struct pt_reg if (!user_mode(regs) || in_interrupt()) dump_mem("Stack: ", regs->regs[15], THREAD_SIZE + - (unsigned long)task_stack_page(current)); + (unsigned long)task_stack_page(current)); bust_spinlocks(0); spin_unlock_irq(&die_lock); @@ -102,8 +107,6 @@ static inline void die_if_kernel(const c die(str, regs, err); } -static int handle_unaligned_notify_count = 10; - /* * try and fix up kernelspace address errors * - userspace errors just cause EFAULT to be returned, resulting in SEGV @@ -198,7 +201,7 @@ #endif if (copy_to_user(dst,src,4)) goto fetch_fault; ret = 0; - break; + break; case 2: /* mov.[bwl] to memory, possibly with pre-decrement */ if (instruction & 4) @@ -222,7 +225,7 @@ #endif if (copy_from_user(dst,src,4)) goto fetch_fault; ret = 0; - break; + break; case 6: /* mov.[bwl] from memory, possibly with post-increment */ src = (unsigned char*) *rm; @@ -230,7 +233,7 @@ #endif *rm += count; dst = (unsigned char*) rn; *(unsigned long*)dst = 0; - + #ifdef __LITTLE_ENDIAN__ if (copy_from_user(dst, src, count)) goto fetch_fault; @@ -241,7 +244,7 @@ #ifdef __LITTLE_ENDIAN__ } #else dst += 4-count; - + if (copy_from_user(dst, src, count)) goto fetch_fault; @@ -320,7 +323,8 @@ static inline int handle_unaligned_delay return -EFAULT; /* kernel */ - die("delay-slot-insn faulting in handle_unaligned_delayslot", regs, 0); + die("delay-slot-insn faulting in handle_unaligned_delayslot", + regs, 0); } return handle_unaligned_ins(instruction,regs); @@ -342,6 +346,13 @@ static inline int handle_unaligned_delay #define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4) #define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4) +/* + * XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit + * opcodes.. + */ +#ifndef CONFIG_CPU_SH2A +static int handle_unaligned_notify_count = 10; + static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) { u_int rm; @@ -354,7 +365,8 @@ static int handle_unaligned_access(u16 i if (user_mode(regs) && handle_unaligned_notify_count>0) { handle_unaligned_notify_count--; - printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", + printk(KERN_NOTICE "Fixing up unaligned userspace access " + "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", current->comm,current->pid,(u16*)regs->pc,instruction); } @@ -478,32 +490,58 @@ #endif regs->pc += 2; return ret; } +#endif /* CONFIG_CPU_SH2A */ + +#ifdef CONFIG_CPU_HAS_SR_RB +#define lookup_exception_vector(x) \ + __asm__ __volatile__ ("stc r2_bank, %0\n\t" : "=r" ((x))) +#else +#define lookup_exception_vector(x) \ + __asm__ __volatile__ ("mov r4, %0\n\t" : "=r" ((x))) +#endif /* - * Handle various address error exceptions + * Handle various address error exceptions: + * - instruction address error: + * misaligned PC + * PC >= 0x80000000 in user mode + * - data address error (read and write) + * misaligned data access + * access to >= 0x80000000 is user mode + * Unfortuntaly we can't distinguish between instruction address error + * and data address errors caused by read acceses. */ -asmlinkage void do_address_error(struct pt_regs *regs, +asmlinkage void do_address_error(struct pt_regs *regs, unsigned long writeaccess, unsigned long address) { - unsigned long error_code; + unsigned long error_code = 0; mm_segment_t oldfs; + siginfo_t info; +#ifndef CONFIG_CPU_SH2A u16 instruction; int tmp; +#endif - asm volatile("stc r2_bank,%0": "=r" (error_code)); + /* Intentional ifdef */ +#ifdef CONFIG_CPU_HAS_SR_RB + lookup_exception_vector(error_code); +#endif oldfs = get_fs(); if (user_mode(regs)) { + int si_code = BUS_ADRERR; + local_irq_enable(); - current->thread.error_code = error_code; - current->thread.trap_no = (writeaccess) ? 8 : 7; /* bad PC is not something we can fix */ - if (regs->pc & 1) + if (regs->pc & 1) { + si_code = BUS_ADRALN; goto uspace_segv; + } +#ifndef CONFIG_CPU_SH2A set_fs(USER_DS); if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { /* Argh. Fault on the instruction itself. @@ -518,14 +556,23 @@ asmlinkage void do_address_error(struct if (tmp==0) return; /* sorted */ +#endif - uspace_segv: - printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm); - force_sig(SIGSEGV, current); +uspace_segv: + printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " + "access (PC %lx PR %lx)\n", current->comm, regs->pc, + regs->pr); + + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = si_code; + info.si_addr = (void *) address; + force_sig_info(SIGBUS, &info, current); } else { if (regs->pc & 1) die("unaligned program counter", regs, error_code); +#ifndef CONFIG_CPU_SH2A set_fs(KERNEL_DS); if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { /* Argh. Fault on the instruction itself. @@ -537,6 +584,12 @@ asmlinkage void do_address_error(struct handle_unaligned_access(instruction, regs); set_fs(oldfs); +#else + printk(KERN_NOTICE "Killing process \"%s\" due to unaligned " + "access\n", current->comm); + + force_sig(SIGSEGV, current); +#endif } } @@ -548,7 +601,7 @@ int is_dsp_inst(struct pt_regs *regs) { unsigned short inst; - /* + /* * Safe guard if DSP mode is already enabled or we're lacking * the DSP altogether. */ @@ -569,27 +622,49 @@ #else #define is_dsp_inst(regs) (0) #endif /* CONFIG_SH_DSP */ +#ifdef CONFIG_CPU_SH2A +asmlinkage void do_divide_error(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + siginfo_t info; + + switch (r4) { + case TRAP_DIVZERO_ERROR: + info.si_code = FPE_INTDIV; + break; + case TRAP_DIVOVF_ERROR: + info.si_code = FPE_INTOVF; + break; + } + + force_sig_info(SIGFPE, &info, current); +} +#endif + /* arch/sh/kernel/cpu/sh4/fpu.c */ extern int do_fpu_inst(unsigned short, struct pt_regs *); extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, struct pt_regs regs); + unsigned long r6, unsigned long r7, struct pt_regs __regs); asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); unsigned long error_code; struct task_struct *tsk = current; #ifdef CONFIG_SH_FPU_EMU - unsigned short inst; + unsigned short inst = 0; int err; - get_user(inst, (unsigned short*)regs.pc); + get_user(inst, (unsigned short*)regs->pc); - err = do_fpu_inst(inst, ®s); + err = do_fpu_inst(inst, regs); if (!err) { - regs.pc += 2; + regs->pc += 2; return; } /* not a FPU inst. */ @@ -597,20 +672,19 @@ #endif #ifdef CONFIG_SH_DSP /* Check if it's a DSP instruction */ - if (is_dsp_inst(®s)) { + if (is_dsp_inst(regs)) { /* Enable DSP mode, and restart instruction. */ - regs.sr |= SR_DSP; + regs->sr |= SR_DSP; return; } #endif - asm volatile("stc r2_bank, %0": "=r" (error_code)); + lookup_exception_vector(error_code); + local_irq_enable(); - tsk->thread.error_code = error_code; - tsk->thread.trap_no = TRAP_RESERVED_INST; - CHK_REMOTE_DEBUG(®s); + CHK_REMOTE_DEBUG(regs); force_sig(SIGILL, tsk); - die_if_no_fixup("reserved instruction", ®s, error_code); + die_if_no_fixup("reserved instruction", regs, error_code); } #ifdef CONFIG_SH_FPU_EMU @@ -658,39 +732,41 @@ #endif asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); unsigned long error_code; struct task_struct *tsk = current; #ifdef CONFIG_SH_FPU_EMU - unsigned short inst; + unsigned short inst = 0; - get_user(inst, (unsigned short *)regs.pc + 1); - if (!do_fpu_inst(inst, ®s)) { - get_user(inst, (unsigned short *)regs.pc); - if (!emulate_branch(inst, ®s)) + get_user(inst, (unsigned short *)regs->pc + 1); + if (!do_fpu_inst(inst, regs)) { + get_user(inst, (unsigned short *)regs->pc); + if (!emulate_branch(inst, regs)) return; /* fault in branch.*/ } /* not a FPU inst. */ #endif - asm volatile("stc r2_bank, %0": "=r" (error_code)); + lookup_exception_vector(error_code); + local_irq_enable(); - tsk->thread.error_code = error_code; - tsk->thread.trap_no = TRAP_RESERVED_INST; - CHK_REMOTE_DEBUG(®s); + CHK_REMOTE_DEBUG(regs); force_sig(SIGILL, tsk); - die_if_no_fixup("illegal slot instruction", ®s, error_code); + die_if_no_fixup("illegal slot instruction", regs, error_code); } asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); long ex; - asm volatile("stc r2_bank, %0" : "=r" (ex)); - die_if_kernel("exception", ®s, ex); + + lookup_exception_vector(ex); + die_if_kernel("exception", regs, ex); } #if defined(CONFIG_SH_STANDARD_BIOS) @@ -735,12 +811,16 @@ void *set_exception_table_vec(unsigned i { extern void *exception_handling_table[]; void *old_handler; - + old_handler = exception_handling_table[vec]; exception_handling_table[vec] = handler; return old_handler; } +extern asmlinkage void address_error_handler(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs); + void __init trap_init(void) { set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst); @@ -759,7 +839,15 @@ #elif defined(CONFIG_SH_FPU) set_exception_table_evt(0x800, do_fpu_state_restore); set_exception_table_evt(0x820, do_fpu_state_restore); #endif - + +#ifdef CONFIG_CPU_SH2 + set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_handler); +#endif +#ifdef CONFIG_CPU_SH2A + set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error); + set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error); +#endif + /* Setup VBR for boot cpu */ per_cpu_trap_init(); } diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig index 9dd6064..88e9663 100644 --- a/arch/sh/mm/Kconfig +++ b/arch/sh/mm/Kconfig @@ -4,8 +4,12 @@ # # Processor families # config CPU_SH2 + select SH_WRITETHROUGH if !CPU_SH2A bool - select SH_WRITETHROUGH + +config CPU_SH2A + bool + select CPU_SH2 config CPU_SH3 bool @@ -40,6 +44,16 @@ config CPU_SUBTYPE_SH7604 bool "Support SH7604 processor" select CPU_SH2 +config CPU_SUBTYPE_SH7619 + bool "Support SH7619 processor" + select CPU_SH2 + +comment "SH-2A Processor Support" + +config CPU_SUBTYPE_SH7206 + bool "Support SH7206 processor" + select CPU_SH2A + comment "SH-3 Processor Support" config CPU_SUBTYPE_SH7300 @@ -157,6 +171,11 @@ config CPU_SUBTYPE_SH7780 select CPU_SH4A select CPU_HAS_INTC2_IRQ +config CPU_SUBTYPE_SH7785 + bool "Support SH7785 processor" + select CPU_SH4A + select CPU_HAS_INTC2_IRQ + comment "SH4AL-DSP Processor Support" config CPU_SUBTYPE_SH73180 @@ -216,13 +235,22 @@ config MEMORY_SIZE config 32BIT bool "Support 32-bit physical addressing through PMB" - depends on CPU_SH4A && MMU + depends on CPU_SH4A && MMU && (!X2TLB || BROKEN) default y help If you say Y here, physical addressing will be extended to 32-bits through the SH-4A PMB. If this is not set, legacy 29-bit physical addressing will be used. +config X2TLB + bool "Enable extended TLB mode" + depends on CPU_SUBTYPE_SH7785 && MMU && EXPERIMENTAL + help + Selecting this option will enable the extended mode of the SH-X2 + TLB. For legacy SH-X behaviour and interoperability, say N. For + all of the fun new features and a willingless to submit bug reports, + say Y. + config VSYSCALL bool "Support vsyscall page" depends on MMU @@ -237,16 +265,52 @@ config VSYSCALL (the default value) say Y. choice + prompt "Kernel page size" + default PAGE_SIZE_4KB + +config PAGE_SIZE_4KB + bool "4kB" + help + This is the default page size used by all SuperH CPUs. + +config PAGE_SIZE_8KB + bool "8kB" + depends on EXPERIMENTAL && X2TLB + help + This enables 8kB pages as supported by SH-X2 and later MMUs. + +config PAGE_SIZE_64KB + bool "64kB" + depends on EXPERIMENTAL && CPU_SH4 + help + This enables support for 64kB pages, possible on all SH-4 + CPUs and later. Highly experimental, not recommended. + +endchoice + +choice prompt "HugeTLB page size" depends on HUGETLB_PAGE && CPU_SH4 && MMU default HUGETLB_PAGE_SIZE_64K config HUGETLB_PAGE_SIZE_64K - bool "64K" + bool "64kB" + +config HUGETLB_PAGE_SIZE_256K + bool "256kB" + depends on X2TLB config HUGETLB_PAGE_SIZE_1MB bool "1MB" +config HUGETLB_PAGE_SIZE_4MB + bool "4MB" + depends on X2TLB + +config HUGETLB_PAGE_SIZE_64MB + bool "64MB" + depends on X2TLB + endchoice source "mm/Kconfig" @@ -274,7 +338,6 @@ config SH_DIRECT_MAPPED config SH_WRITETHROUGH bool "Use write-through caching" - default y if CPU_SH2 help Selecting this option will configure the caches in write-through mode, as opposed to the default write-back configuration. diff --git a/arch/sh/mm/cache-sh2.c b/arch/sh/mm/cache-sh2.c index 2689cb2..6614033 100644 --- a/arch/sh/mm/cache-sh2.c +++ b/arch/sh/mm/cache-sh2.c @@ -5,6 +5,7 @@ * * Released under the terms of the GNU GPL v2.0. */ + #include #include @@ -14,37 +15,43 @@ #include #include #include -/* - * Calculate the OC address and set the way bit on the SH-2. - * - * We must have already jump_to_P2()'ed prior to calling this - * function, since we rely on CCR manipulation to do the - * Right Thing(tm). - */ -unsigned long __get_oc_addr(unsigned long set, unsigned long way) +void __flush_wback_region(void *start, int size) { - unsigned long ccr; - - /* - * On SH-2 the way bit isn't tracked in the address field - * if we're doing address array access .. instead, we need - * to manually switch out the way in the CCR. - */ - ccr = ctrl_inl(CCR); - ccr &= ~0x00c0; - ccr |= way << cpu_data->dcache.way_shift; - - /* - * Despite the number of sets being halved, we end up losing - * the first 2 ways to OCRAM instead of the last 2 (if we're - * 4-way). As a result, forcibly setting the W1 bit handily - * bumps us up 2 ways. - */ - if (ccr & CCR_CACHE_ORA) - ccr |= 1 << (cpu_data->dcache.way_shift + 1); - - ctrl_outl(ccr, CCR); - - return CACHE_OC_ADDRESS_ARRAY | (set << cpu_data->dcache.entry_shift); + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + /* FIXME cache purge */ + ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008); + } +} + +void __flush_purge_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008); + } +} + +void __flush_invalidate_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008); + } } diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index e48cc22..7e62ba0 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c @@ -11,12 +11,8 @@ */ #include #include -#include -#include -#include -#include -#include -#include +#include +#include #include #include @@ -83,9 +79,9 @@ static void __init emit_cache_params(voi */ /* Worst case assumed to be 64k cache, direct-mapped i.e. 4 synonym bits. */ -#define MAX_P3_SEMAPHORES 16 +#define MAX_P3_MUTEXES 16 -struct semaphore p3map_sem[MAX_P3_SEMAPHORES]; +struct mutex p3map_mutex[MAX_P3_MUTEXES]; void __init p3_cache_init(void) { @@ -115,7 +111,7 @@ void __init p3_cache_init(void) panic("%s failed.", __FUNCTION__); for (i = 0; i < cpu_data->dcache.n_aliases; i++) - sema_init(&p3map_sem[i], 1); + mutex_init(&p3map_mutex[i]); } /* diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index 68663b8..128907e 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c @@ -26,13 +26,16 @@ extern void die(const char *,struct pt_r * and the problem, and then passes it off to one of the appropriate * routines. */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, - unsigned long address) +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, + unsigned long writeaccess, + unsigned long address) { struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; unsigned long page; + int si_code; + siginfo_t info; #ifdef CONFIG_SH_KGDB if (kgdb_nofault && kgdb_bus_err_hook) @@ -41,6 +44,46 @@ #endif tsk = current; mm = tsk->mm; + si_code = SEGV_MAPERR; + + if (unlikely(address >= TASK_SIZE)) { + /* + * Synchronize this task's top level page-table + * with the 'reference' page table. + * + * Do _not_ use "tsk" here. We might be inside + * an interrupt in the middle of a task switch.. + */ + int offset = pgd_index(address); + pgd_t *pgd, *pgd_k; + pud_t *pud, *pud_k; + pmd_t *pmd, *pmd_k; + + pgd = get_TTB() + offset; + pgd_k = swapper_pg_dir + offset; + + /* This will never happen with the folded page table. */ + if (!pgd_present(*pgd)) { + if (!pgd_present(*pgd_k)) + goto bad_area_nosemaphore; + set_pgd(pgd, *pgd_k); + return; + } + + pud = pud_offset(pgd, address); + pud_k = pud_offset(pgd_k, address); + if (pud_present(*pud) || !pud_present(*pud_k)) + goto bad_area_nosemaphore; + set_pud(pud, *pud_k); + + pmd = pmd_offset(pud, address); + pmd_k = pmd_offset(pud_k, address); + if (pmd_present(*pmd) || !pmd_present(*pmd_k)) + goto bad_area_nosemaphore; + set_pmd(pmd, *pmd_k); + + return; + } /* * If we're in an interrupt or have no user @@ -65,6 +108,7 @@ #endif * we can handle it.. */ good_area: + si_code = SEGV_ACCERR; if (writeaccess) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; @@ -104,10 +148,13 @@ survive: bad_area: up_read(&mm->mmap_sem); +bad_area_nosemaphore: if (user_mode(regs)) { - tsk->thread.address = address; - tsk->thread.error_code = writeaccess; - force_sig(SIGSEGV, tsk); + info.si_signo = SIGSEGV; + info.si_errno = 0; + info.si_code = si_code; + info.si_addr = (void *) address; + force_sig_info(SIGSEGV, &info, tsk); return; } @@ -166,10 +213,11 @@ do_sigbus: * Send a sigbus, regardless of whether we were in kernel * or user mode. */ - tsk->thread.address = address; - tsk->thread.error_code = writeaccess; - tsk->thread.trap_no = 14; - force_sig(SIGBUS, tsk); + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *)address; + force_sig_info(SIGBUS, &info, tsk); /* Kernel mode? Handle exceptions or die */ if (!user_mode(regs)) diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 7154d1c..462bfea 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -84,30 +84,22 @@ static void set_pte_phys(unsigned long a pmd_t *pmd; pte_t *pte; - pgd = swapper_pg_dir + pgd_index(addr); + pgd = pgd_offset_k(addr); if (pgd_none(*pgd)) { pgd_ERROR(*pgd); return; } - pud = pud_offset(pgd, addr); - if (pud_none(*pud)) { - pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC); - set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER)); - if (pmd != pmd_offset(pud, 0)) { - pud_ERROR(*pud); - return; - } + pud = pud_alloc(NULL, pgd, addr); + if (unlikely(!pud)) { + pud_ERROR(*pud); + return; } - pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) { - pte = (pte_t *)get_zeroed_page(GFP_ATOMIC); - set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER)); - if (pte != pte_offset_kernel(pmd, 0)) { - pmd_ERROR(*pmd); - return; - } + pmd = pmd_alloc(NULL, pud, addr); + if (unlikely(!pmd)) { + pmd_ERROR(*pmd); + return; } pte = pte_offset_kernel(pmd, addr); @@ -155,9 +147,6 @@ extern char __init_begin, __init_end; /* * paging_init() sets up the page tables - * - * This routines also unmaps the page at virtual kernel address 0, so - * that we can trap those pesky NULL-reference errors in the kernel. */ void __init paging_init(void) { @@ -180,14 +169,11 @@ #ifdef CONFIG_MMU */ { unsigned long max_dma, low, start_pfn; - pgd_t *pg_dir; - int i; - - /* We don't need kernel mapping as hardware support that. */ - pg_dir = swapper_pg_dir; - for (i = 0; i < PTRS_PER_PGD; i++) - pgd_val(pg_dir[i]) = 0; + /* We don't need to map the kernel through the TLB, as + * it is permanatly mapped using P1. So clear the + * entire pgd. */ + memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir)); /* Turn on the MMU */ enable_mmu(); @@ -206,6 +192,10 @@ #ifdef CONFIG_MMU } } + /* Set an initial value for the MMU.TTB so we don't have to + * check for a null value. */ + set_TTB(swapper_pg_dir); + #elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4) /* * If we don't have CONFIG_MMU set and the processor in question diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index a9fe80c..11d54c1 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c @@ -28,9 +28,7 @@ static inline void remap_area_pte(pte_t { unsigned long end; unsigned long pfn; - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | - _PAGE_DIRTY | _PAGE_ACCESSED | - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | flags); + pgprot_t pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags); address &= ~PMD_MASK; end = address + size; diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c index 07371ed..3f98d2a 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-sh4.c @@ -6,22 +6,12 @@ * * Released under the terms of the GNU GPL v2.0. */ -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include -extern struct semaphore p3map_sem[]; +extern struct mutex p3map_mutex[]; #define CACHE_ALIAS (cpu_data->dcache.alias_mask) @@ -37,10 +27,6 @@ void clear_user_page(void *to, unsigned if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) clear_page(to); else { - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | - _PAGE_RW | _PAGE_CACHABLE | - _PAGE_DIRTY | _PAGE_ACCESSED | - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD); unsigned long phys_addr = PHYSADDR(to); unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); pgd_t *pgd = pgd_offset_k(p3_addr); @@ -50,8 +36,8 @@ void clear_user_page(void *to, unsigned pte_t entry; unsigned long flags; - entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot); - down(&p3map_sem[(address & CACHE_ALIAS)>>12]); + entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL); + mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); set_pte(pte, entry); local_irq_save(flags); __flush_tlb_page(get_asid(), p3_addr); @@ -59,7 +45,7 @@ void clear_user_page(void *to, unsigned update_mmu_cache(NULL, p3_addr, entry); __clear_user_page((void *)p3_addr, to); pte_clear(&init_mm, p3_addr, pte); - up(&p3map_sem[(address & CACHE_ALIAS)>>12]); + mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); } } @@ -77,10 +63,6 @@ void copy_user_page(void *to, void *from if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) copy_page(to, from); else { - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | - _PAGE_RW | _PAGE_CACHABLE | - _PAGE_DIRTY | _PAGE_ACCESSED | - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD); unsigned long phys_addr = PHYSADDR(to); unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); pgd_t *pgd = pgd_offset_k(p3_addr); @@ -90,8 +72,8 @@ void copy_user_page(void *to, void *from pte_t entry; unsigned long flags; - entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot); - down(&p3map_sem[(address & CACHE_ALIAS)>>12]); + entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL); + mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); set_pte(pte, entry); local_irq_save(flags); __flush_tlb_page(get_asid(), p3_addr); @@ -99,7 +81,7 @@ void copy_user_page(void *to, void *from update_mmu_cache(NULL, p3_addr, entry); __copy_user_page((void *)p3_addr, from, to); pte_clear(&init_mm, p3_addr, pte); - up(&p3map_sem[(address & CACHE_ALIAS)>>12]); + mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); } } @@ -122,4 +104,3 @@ inline pte_t ptep_get_and_clear(struct m } return pte; } - diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index ac57638..0571755 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -30,3 +30,5 @@ R7780MP SH_R7780MP TITAN SH_TITAN SHMIN SH_SHMIN 7710VOIPGW SH_7710VOIPGW +7206SE SH_7206_SOLUTION_ENGINE +7619SE SH_7619_SOLUTION_ENGINE diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 7ee9921..b2bc0cf 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -133,6 +133,20 @@ # define SCSPTR1 0xffe10024 /* 16 bit SC # define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */ +# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */ +# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */ +# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +# define SCSPTR0 0xf8400020 /* 16 bit SCIF */ +# define SCSPTR1 0xf8410020 /* 16 bit SCIF */ +# define SCSPTR2 0xf8420020 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001 /* overrun error bit */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY #else # error CPU subtype not defined #endif @@ -544,6 +558,28 @@ static inline int sci_rxd_in(struct uart if (port->mapbase == 0xffe10000) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ } +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xfffe8000) + return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe8800) + return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe9000) + return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe9800) + return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ +} +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xf8400000) + return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xf8410000) + return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xf8420000) + return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ +} #endif /* diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h index beeea40..795047d 100644 --- a/include/asm-sh/bugs.h +++ b/include/asm-sh/bugs.h @@ -23,16 +23,20 @@ static void __init check_bugs(void) cpu_data->loops_per_jiffy = loops_per_jiffy; switch (cpu_data->type) { - case CPU_SH7604: + case CPU_SH7604 ... CPU_SH7619: *p++ = '2'; break; + case CPU_SH7206: + *p++ = '2'; + *p++ = 'a'; + break; case CPU_SH7705 ... CPU_SH7300: *p++ = '3'; break; case CPU_SH7750 ... CPU_SH4_501: *p++ = '4'; break; - case CPU_SH7770 ... CPU_SH7781: + case CPU_SH7770 ... CPU_SH7785: *p++ = '4'; *p++ = 'a'; break; diff --git a/include/asm-sh/cpu-sh2/cache.h b/include/asm-sh/cpu-sh2/cache.h index cd96402..20b9796 100644 --- a/include/asm-sh/cpu-sh2/cache.h +++ b/include/asm-sh/cpu-sh2/cache.h @@ -12,6 +12,7 @@ #define __ASM_CPU_SH2_CACHE_H #define L1_CACHE_SHIFT 4 +#if defined(CONFIG_CPU_SUBTYPE_SH7604) #define CCR 0xfffffe92 /* Address of Cache Control Register */ #define CCR_CACHE_CE 0x01 /* Cache enable */ @@ -27,5 +28,26 @@ #define CCR_CACHE_INVALIDATE CCR_CACHE_C #define CCR_CACHE_ORA CCR_CACHE_TW #define CCR_CACHE_WT 0x00 /* SH-2 is _always_ write-through */ +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +#define CCR1 0xffffffec +#define CCR CCR1 + +#define CCR_CACHE_CE 0x01 /* Cache enable */ +#define CCR_CACHE_WT 0x06 /* CCR[bit1=1,bit2=1] */ + /* 0x00000000-0x7fffffff: Write-through */ + /* 0x80000000-0x9fffffff: Write-back */ + /* 0xc0000000-0xdfffffff: Write-through */ +#define CCR_CACHE_CB 0x00 /* CCR[bit1=0,bit2=0] */ + /* 0x00000000-0x7fffffff: Write-back */ + /* 0x80000000-0x9fffffff: Write-through */ + /* 0xc0000000-0xdfffffff: Write-back */ +#define CCR_CACHE_CF 0x08 /* Cache invalidate */ + +#define CACHE_OC_ADDRESS_ARRAY 0xf0000000 +#define CACHE_OC_DATA_ARRAY 0xf1000000 + +#define CCR_CACHE_ENABLE CCR_CACHE_CE +#define CCR_CACHE_INVALIDATE CCR_CACHE_CF +#endif #endif /* __ASM_CPU_SH2_CACHE_H */ diff --git a/include/asm-sh/cpu-sh2/freq.h b/include/asm-sh/cpu-sh2/freq.h new file mode 100644 index 0000000..31de475 --- /dev/null +++ b/include/asm-sh/cpu-sh2/freq.h @@ -0,0 +1,18 @@ +/* + * include/asm-sh/cpu-sh2/freq.h + * + * Copyright (C) 2006 Yoshinori Sato + * + * 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_CPU_SH2_FREQ_H +#define __ASM_CPU_SH2_FREQ_H + +#if defined(CONFIG_CPU_SUBTYPE_SH7619) +#define FREQCR 0xf815ff80 +#endif + +#endif /* __ASM_CPU_SH2_FREQ_H */ + diff --git a/include/asm-sh/cpu-sh2/mmu_context.h b/include/asm-sh/cpu-sh2/mmu_context.h new file mode 100644 index 0000000..beeb299 --- /dev/null +++ b/include/asm-sh/cpu-sh2/mmu_context.h @@ -0,0 +1,16 @@ +/* + * include/asm-sh/cpu-sh2/mmu_context.h + * + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_CPU_SH2_MMU_CONTEXT_H +#define __ASM_CPU_SH2_MMU_CONTEXT_H + +/* No MMU */ + +#endif /* __ASM_CPU_SH2_MMU_CONTEXT_H */ + diff --git a/include/asm-sh/cpu-sh2/timer.h b/include/asm-sh/cpu-sh2/timer.h new file mode 100644 index 0000000..a39c241 --- /dev/null +++ b/include/asm-sh/cpu-sh2/timer.h @@ -0,0 +1,6 @@ +#ifndef __ASM_CPU_SH2_TIMER_H +#define __ASM_CPU_SH2_TIMER_H + +/* Nothing needed yet */ + +#endif /* __ASM_CPU_SH2_TIMER_H */ diff --git a/include/asm-sh/cpu-sh2a/addrspace.h b/include/asm-sh/cpu-sh2a/addrspace.h new file mode 100644 index 0000000..3d2e9aa --- /dev/null +++ b/include/asm-sh/cpu-sh2a/addrspace.h @@ -0,0 +1 @@ +#include diff --git a/include/asm-sh/cpu-sh2a/cache.h b/include/asm-sh/cpu-sh2a/cache.h new file mode 100644 index 0000000..3e4b9e4 --- /dev/null +++ b/include/asm-sh/cpu-sh2a/cache.h @@ -0,0 +1,39 @@ +/* + * include/asm-sh/cpu-sh2a/cache.h + * + * Copyright (C) 2004 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_CPU_SH2A_CACHE_H +#define __ASM_CPU_SH2A_CACHE_H + +#define L1_CACHE_SHIFT 4 + +#define CCR1 0xfffc1000 +#define CCR2 0xfffc1004 + +/* CCR1 behaves more like the traditional CCR */ +#define CCR CCR1 + +/* + * Most of the SH-2A CCR1 definitions resemble the SH-4 ones. All others not + * listed here are reserved. + */ +#define CCR_CACHE_CB 0x0000 /* Hack */ +#define CCR_CACHE_OCE 0x0001 +#define CCR_CACHE_WT 0x0002 +#define CCR_CACHE_OCI 0x0008 /* OCF */ +#define CCR_CACHE_ICE 0x0100 +#define CCR_CACHE_ICI 0x0800 /* ICF */ + +#define CACHE_IC_ADDRESS_ARRAY 0xf0000000 +#define CACHE_OC_ADDRESS_ARRAY 0xf0800000 + +#define CCR_CACHE_ENABLE (CCR_CACHE_OCE | CCR_CACHE_ICE) +#define CCR_CACHE_INVALIDATE (CCR_CACHE_OCI | CCR_CACHE_ICI) + +#endif /* __ASM_CPU_SH2A_CACHE_H */ + diff --git a/include/asm-sh/cpu-sh2a/cacheflush.h b/include/asm-sh/cpu-sh2a/cacheflush.h new file mode 100644 index 0000000..fa3186c --- /dev/null +++ b/include/asm-sh/cpu-sh2a/cacheflush.h @@ -0,0 +1 @@ +#include diff --git a/include/asm-sh/cpu-sh2a/dma.h b/include/asm-sh/cpu-sh2a/dma.h new file mode 100644 index 0000000..0d5ad85 --- /dev/null +++ b/include/asm-sh/cpu-sh2a/dma.h @@ -0,0 +1 @@ +#include diff --git a/include/asm-sh/cpu-sh2a/freq.h b/include/asm-sh/cpu-sh2a/freq.h new file mode 100644 index 0000000..e518fff --- /dev/null +++ b/include/asm-sh/cpu-sh2a/freq.h @@ -0,0 +1,18 @@ +/* + * include/asm-sh/cpu-sh2a/freq.h + * + * Copyright (C) 2006 Yoshinori Sato + * + * 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_CPU_SH2A_FREQ_H +#define __ASM_CPU_SH2A_FREQ_H + +#if defined(CONFIG_CPU_SUBTYPE_SH7206) +#define FREQCR 0xfffe0010 +#endif + +#endif /* __ASM_CPU_SH2A_FREQ_H */ + diff --git a/include/asm-sh/cpu-sh2a/mmu_context.h b/include/asm-sh/cpu-sh2a/mmu_context.h new file mode 100644 index 0000000..cd2387f --- /dev/null +++ b/include/asm-sh/cpu-sh2a/mmu_context.h @@ -0,0 +1 @@ +#include diff --git a/include/asm-sh/cpu-sh2a/timer.h b/include/asm-sh/cpu-sh2a/timer.h new file mode 100644 index 0000000..fee504a --- /dev/null +++ b/include/asm-sh/cpu-sh2a/timer.h @@ -0,0 +1 @@ +#include diff --git a/include/asm-sh/cpu-sh2a/ubc.h b/include/asm-sh/cpu-sh2a/ubc.h new file mode 100644 index 0000000..cf28062 --- /dev/null +++ b/include/asm-sh/cpu-sh2a/ubc.h @@ -0,0 +1 @@ +#include diff --git a/include/asm-sh/cpu-sh2a/watchdog.h b/include/asm-sh/cpu-sh2a/watchdog.h new file mode 100644 index 0000000..c1b3e24 --- /dev/null +++ b/include/asm-sh/cpu-sh2a/watchdog.h @@ -0,0 +1 @@ +#include diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h index fc050fd..43ca244 100644 --- a/include/asm-sh/elf.h +++ b/include/asm-sh/elf.h @@ -74,7 +74,7 @@ #endif #define ELF_ARCH EM_SH #define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 +#define ELF_EXEC_PAGESIZE PAGE_SIZE /* This is the location that an ET_DYN program is loaded if exec'ed. Typical use of this is to invoke "./ld.so someprog" to test out a new version of diff --git a/include/asm-sh/entry-macros.S b/include/asm-sh/entry-macros.S new file mode 100644 index 0000000..099fe81 --- /dev/null +++ b/include/asm-sh/entry-macros.S @@ -0,0 +1,32 @@ +! entry.S macro define + + .macro cli + stc sr, r0 + or #0xf0, r0 + ldc r0, sr + .endm + + .macro sti + mov #0xf0, r11 + extu.b r11, r11 + not r11, r11 + stc sr, r10 + and r11, r10 +#ifdef CONFIG_HAS_SR_RB + stc k_g_imask, r11 + or r11, r10 +#endif + ldc r10, sr + .endm + + .macro get_current_thread_info, ti, tmp +#ifdef CONFIG_HAS_SR_RB + stc r7_bank, \ti +#else + mov #((THREAD_SIZE - 1)>> 8) ^ 0xff, \tmp + shll8 \tmp + mov r15, \ti + and \tmp, \ti +#endif + .endm + diff --git a/include/asm-sh/irq-sh73180.h b/include/asm-sh/irq-sh73180.h deleted file mode 100644 index b28af9a..0000000 --- a/include/asm-sh/irq-sh73180.h +++ /dev/null @@ -1,314 +0,0 @@ -#ifndef __ASM_SH_IRQ_SH73180_H -#define __ASM_SH_IRQ_SH73180_H - -/* - * linux/include/asm-sh/irq-sh73180.h - * - * Copyright (C) 2004 Takashi SHUDO - */ - -#undef INTC_IPRA -#undef INTC_IPRB -#undef INTC_IPRC -#undef INTC_IPRD - -#undef DMTE0_IRQ -#undef DMTE1_IRQ -#undef DMTE2_IRQ -#undef DMTE3_IRQ -#undef DMTE4_IRQ -#undef DMTE5_IRQ -#undef DMTE6_IRQ -#undef DMTE7_IRQ -#undef DMAE_IRQ -#undef DMA_IPR_ADDR -#undef DMA_IPR_POS -#undef DMA_PRIORITY - -#undef INTC_IMCR0 -#undef INTC_IMCR1 -#undef INTC_IMCR2 -#undef INTC_IMCR3 -#undef INTC_IMCR4 -#undef INTC_IMCR5 -#undef INTC_IMCR6 -#undef INTC_IMCR7 -#undef INTC_IMCR8 -#undef INTC_IMCR9 -#undef INTC_IMCR10 - - -#define INTC_IPRA 0xA4080000UL -#define INTC_IPRB 0xA4080004UL -#define INTC_IPRC 0xA4080008UL -#define INTC_IPRD 0xA408000CUL -#define INTC_IPRE 0xA4080010UL -#define INTC_IPRF 0xA4080014UL -#define INTC_IPRG 0xA4080018UL -#define INTC_IPRH 0xA408001CUL -#define INTC_IPRI 0xA4080020UL -#define INTC_IPRJ 0xA4080024UL -#define INTC_IPRK 0xA4080028UL - -#define INTC_IMR0 0xA4080080UL -#define INTC_IMR1 0xA4080084UL -#define INTC_IMR2 0xA4080088UL -#define INTC_IMR3 0xA408008CUL -#define INTC_IMR4 0xA4080090UL -#define INTC_IMR5 0xA4080094UL -#define INTC_IMR6 0xA4080098UL -#define INTC_IMR7 0xA408009CUL -#define INTC_IMR8 0xA40800A0UL -#define INTC_IMR9 0xA40800A4UL -#define INTC_IMR10 0xA40800A8UL -#define INTC_IMR11 0xA40800ACUL - -#define INTC_IMCR0 0xA40800C0UL -#define INTC_IMCR1 0xA40800C4UL -#define INTC_IMCR2 0xA40800C8UL -#define INTC_IMCR3 0xA40800CCUL -#define INTC_IMCR4 0xA40800D0UL -#define INTC_IMCR5 0xA40800D4UL -#define INTC_IMCR6 0xA40800D8UL -#define INTC_IMCR7 0xA40800DCUL -#define INTC_IMCR8 0xA40800E0UL -#define INTC_IMCR9 0xA40800E4UL -#define INTC_IMCR10 0xA40800E8UL -#define INTC_IMCR11 0xA40800ECUL - -#define INTC_ICR0 0xA4140000UL -#define INTC_ICR1 0xA414001CUL - -#define INTMSK0 0xa4140044 -#define INTMSKCLR0 0xa4140064 -#define INTC_INTPRI0 0xa4140010 - -/* - NOTE: - - *_IRQ = (INTEVT2 - 0x200)/0x20 -*/ - -/* TMU0 */ -#define TMU0_IRQ 16 -#define TMU0_IPR_ADDR INTC_IPRA -#define TMU0_IPR_POS 3 -#define TMU0_PRIORITY 2 - -#define TIMER_IRQ 16 -#define TIMER_IPR_ADDR INTC_IPRA -#define TIMER_IPR_POS 3 -#define TIMER_PRIORITY 2 - -/* TMU1 */ -#define TMU1_IRQ 17 -#define TMU1_IPR_ADDR INTC_IPRA -#define TMU1_IPR_POS 2 -#define TMU1_PRIORITY 2 - -/* TMU2 */ -#define TMU2_IRQ 18 -#define TMU2_IPR_ADDR INTC_IPRA -#define TMU2_IPR_POS 1 -#define TMU2_PRIORITY 2 - -/* LCDC */ -#define LCDC_IRQ 28 -#define LCDC_IPR_ADDR INTC_IPRB -#define LCDC_IPR_POS 2 -#define LCDC_PRIORITY 2 - -/* VIO (Video I/O) */ -#define CEU_IRQ 52 -#define BEU_IRQ 53 -#define VEU_IRQ 54 -#define VOU_IRQ 55 -#define VIO_IPR_ADDR INTC_IPRE -#define VIO_IPR_POS 2 -#define VIO_PRIORITY 2 - -/* MFI (Multi Functional Interface) */ -#define MFI_IRQ 56 -#define MFI_IPR_ADDR INTC_IPRE -#define MFI_IPR_POS 1 -#define MFI_PRIORITY 2 - -/* VPU (Video Processing Unit) */ -#define VPU_IRQ 60 -#define VPU_IPR_ADDR INTC_IPRE -#define VPU_IPR_POS 0 -#define VPU_PRIORITY 2 - -/* 3DG */ -#define TDG_IRQ 63 -#define TDG_IPR_ADDR INTC_IPRJ -#define TDG_IPR_POS 2 -#define TDG_PRIORITY 2 - -/* DMAC(1) */ -#define DMTE0_IRQ 48 -#define DMTE1_IRQ 49 -#define DMTE2_IRQ 50 -#define DMTE3_IRQ 51 -#define DMA1_IPR_ADDR INTC_IPRE -#define DMA1_IPR_POS 3 -#define DMA1_PRIORITY 7 - -/* DMAC(2) */ -#define DMTE4_IRQ 76 -#define DMTE5_IRQ 77 -#define DMA2_IPR_ADDR INTC_IPRF -#define DMA2_IPR_POS 2 -#define DMA2_PRIORITY 7 - -/* SCIF0 */ -#define SCIF_ERI_IRQ 80 -#define SCIF_RXI_IRQ 81 -#define SCIF_BRI_IRQ 82 -#define SCIF_TXI_IRQ 83 -#define SCIF_IPR_ADDR INTC_IPRG -#define SCIF_IPR_POS 3 -#define SCIF_PRIORITY 3 - -/* SIOF0 */ -#define SIOF0_IRQ 84 -#define SIOF0_IPR_ADDR INTC_IPRH -#define SIOF0_IPR_POS 3 -#define SIOF0_PRIORITY 3 - -/* FLCTL (Flash Memory Controller) */ -#define FLSTE_IRQ 92 -#define FLTEND_IRQ 93 -#define FLTRQ0_IRQ 94 -#define FLTRQ1_IRQ 95 -#define FLCTL_IPR_ADDR INTC_IPRH -#define FLCTL_IPR_POS 1 -#define FLCTL_PRIORITY 3 - -/* IIC(0) (IIC Bus Interface) */ -#define IIC0_ALI_IRQ 96 -#define IIC0_TACKI_IRQ 97 -#define IIC0_WAITI_IRQ 98 -#define IIC0_DTEI_IRQ 99 -#define IIC0_IPR_ADDR INTC_IPRH -#define IIC0_IPR_POS 0 -#define IIC0_PRIORITY 3 - -/* IIC(1) (IIC Bus Interface) */ -#define IIC1_ALI_IRQ 44 -#define IIC1_TACKI_IRQ 45 -#define IIC1_WAITI_IRQ 46 -#define IIC1_DTEI_IRQ 47 -#define IIC1_IPR_ADDR INTC_IPRG -#define IIC1_IPR_POS 0 -#define IIC1_PRIORITY 3 - -/* SIO0 */ -#define SIO0_IRQ 88 -#define SIO0_IPR_ADDR INTC_IPRI -#define SIO0_IPR_POS 3 -#define SIO0_PRIORITY 3 - -/* SDHI */ -#define SDHI_SDHII0_IRQ 100 -#define SDHI_SDHII1_IRQ 101 -#define SDHI_SDHII2_IRQ 102 -#define SDHI_SDHII3_IRQ 103 -#define SDHI_IPR_ADDR INTC_IPRK -#define SDHI_IPR_POS 0 -#define SDHI_PRIORITY 3 - -/* SIU (Sound Interface Unit) */ -#define SIU_IRQ 108 -#define SIU_IPR_ADDR INTC_IPRJ -#define SIU_IPR_POS 1 -#define SIU_PRIORITY 3 - -#define PORT_PACR 0xA4050100UL -#define PORT_PBCR 0xA4050102UL -#define PORT_PCCR 0xA4050104UL -#define PORT_PDCR 0xA4050106UL -#define PORT_PECR 0xA4050108UL -#define PORT_PFCR 0xA405010AUL -#define PORT_PGCR 0xA405010CUL -#define PORT_PHCR 0xA405010EUL -#define PORT_PJCR 0xA4050110UL -#define PORT_PKCR 0xA4050112UL -#define PORT_PLCR 0xA4050114UL -#define PORT_SCPCR 0xA4050116UL -#define PORT_PMCR 0xA4050118UL -#define PORT_PNCR 0xA405011AUL -#define PORT_PQCR 0xA405011CUL -#define PORT_PRCR 0xA405011EUL -#define PORT_PTCR 0xA405014CUL -#define PORT_PUCR 0xA405014EUL -#define PORT_PVCR 0xA4050150UL - -#define PORT_PSELA 0xA4050140UL -#define PORT_PSELB 0xA4050142UL -#define PORT_PSELC 0xA4050144UL -#define PORT_PSELE 0xA4050158UL - -#define PORT_HIZCRA 0xA4050146UL -#define PORT_HIZCRB 0xA4050148UL -#define PORT_DRVCR 0xA405014AUL - -#define PORT_PADR 0xA4050120UL -#define PORT_PBDR 0xA4050122UL -#define PORT_PCDR 0xA4050124UL -#define PORT_PDDR 0xA4050126UL -#define PORT_PEDR 0xA4050128UL -#define PORT_PFDR 0xA405012AUL -#define PORT_PGDR 0xA405012CUL -#define PORT_PHDR 0xA405012EUL -#define PORT_PJDR 0xA4050130UL -#define PORT_PKDR 0xA4050132UL -#define PORT_PLDR 0xA4050134UL -#define PORT_SCPDR 0xA4050136UL -#define PORT_PMDR 0xA4050138UL -#define PORT_PNDR 0xA405013AUL -#define PORT_PQDR 0xA405013CUL -#define PORT_PRDR 0xA405013EUL -#define PORT_PTDR 0xA405016CUL -#define PORT_PUDR 0xA405016EUL -#define PORT_PVDR 0xA4050170UL - -#define IRQ0_IRQ 32 -#define IRQ1_IRQ 33 -#define IRQ2_IRQ 34 -#define IRQ3_IRQ 35 -#define IRQ4_IRQ 36 -#define IRQ5_IRQ 37 -#define IRQ6_IRQ 38 -#define IRQ7_IRQ 39 - -#define INTPRI00 0xA4140010UL - -#define IRQ0_IPR_ADDR INTPRI00 -#define IRQ1_IPR_ADDR INTPRI00 -#define IRQ2_IPR_ADDR INTPRI00 -#define IRQ3_IPR_ADDR INTPRI00 -#define IRQ4_IPR_ADDR INTPRI00 -#define IRQ5_IPR_ADDR INTPRI00 -#define IRQ6_IPR_ADDR INTPRI00 -#define IRQ7_IPR_ADDR INTPRI00 - -#define IRQ0_IPR_POS 7 -#define IRQ1_IPR_POS 6 -#define IRQ2_IPR_POS 5 -#define IRQ3_IPR_POS 4 -#define IRQ4_IPR_POS 3 -#define IRQ5_IPR_POS 2 -#define IRQ6_IPR_POS 1 -#define IRQ7_IPR_POS 0 - -#define IRQ0_PRIORITY 1 -#define IRQ1_PRIORITY 1 -#define IRQ2_PRIORITY 1 -#define IRQ3_PRIORITY 1 -#define IRQ4_PRIORITY 1 -#define IRQ5_PRIORITY 1 -#define IRQ6_PRIORITY 1 -#define IRQ7_PRIORITY 1 - -#endif /* __ASM_SH_IRQ_SH73180_H */ diff --git a/include/asm-sh/irq-sh7343.h b/include/asm-sh/irq-sh7343.h deleted file mode 100644 index 5d15419..0000000 --- a/include/asm-sh/irq-sh7343.h +++ /dev/null @@ -1,317 +0,0 @@ -#ifndef __ASM_SH_IRQ_SH7343_H -#define __ASM_SH_IRQ_SH7343_H - -/* - * linux/include/asm-sh/irq-sh7343.h - * - * Copyright (C) 2006 Kenati Technologies Inc. - * Andre Mccurdy - * Ranjit Deshpande - */ - -#undef INTC_IPRA -#undef INTC_IPRB -#undef INTC_IPRC -#undef INTC_IPRD - -#undef DMTE0_IRQ -#undef DMTE1_IRQ -#undef DMTE2_IRQ -#undef DMTE3_IRQ -#undef DMTE4_IRQ -#undef DMTE5_IRQ -#undef DMTE6_IRQ -#undef DMTE7_IRQ -#undef DMAE_IRQ -#undef DMA_IPR_ADDR -#undef DMA_IPR_POS -#undef DMA_PRIORITY - -#undef INTC_IMCR0 -#undef INTC_IMCR1 -#undef INTC_IMCR2 -#undef INTC_IMCR3 -#undef INTC_IMCR4 -#undef INTC_IMCR5 -#undef INTC_IMCR6 -#undef INTC_IMCR7 -#undef INTC_IMCR8 -#undef INTC_IMCR9 -#undef INTC_IMCR10 - - -#define INTC_IPRA 0xA4080000UL -#define INTC_IPRB 0xA4080004UL -#define INTC_IPRC 0xA4080008UL -#define INTC_IPRD 0xA408000CUL -#define INTC_IPRE 0xA4080010UL -#define INTC_IPRF 0xA4080014UL -#define INTC_IPRG 0xA4080018UL -#define INTC_IPRH 0xA408001CUL -#define INTC_IPRI 0xA4080020UL -#define INTC_IPRJ 0xA4080024UL -#define INTC_IPRK 0xA4080028UL -#define INTC_IPRL 0xA408002CUL - -#define INTC_IMR0 0xA4080080UL -#define INTC_IMR1 0xA4080084UL -#define INTC_IMR2 0xA4080088UL -#define INTC_IMR3 0xA408008CUL -#define INTC_IMR4 0xA4080090UL -#define INTC_IMR5 0xA4080094UL -#define INTC_IMR6 0xA4080098UL -#define INTC_IMR7 0xA408009CUL -#define INTC_IMR8 0xA40800A0UL -#define INTC_IMR9 0xA40800A4UL -#define INTC_IMR10 0xA40800A8UL -#define INTC_IMR11 0xA40800ACUL - -#define INTC_IMCR0 0xA40800C0UL -#define INTC_IMCR1 0xA40800C4UL -#define INTC_IMCR2 0xA40800C8UL -#define INTC_IMCR3 0xA40800CCUL -#define INTC_IMCR4 0xA40800D0UL -#define INTC_IMCR5 0xA40800D4UL -#define INTC_IMCR6 0xA40800D8UL -#define INTC_IMCR7 0xA40800DCUL -#define INTC_IMCR8 0xA40800E0UL -#define INTC_IMCR9 0xA40800E4UL -#define INTC_IMCR10 0xA40800E8UL -#define INTC_IMCR11 0xA40800ECUL - -#define INTC_ICR0 0xA4140000UL -#define INTC_ICR1 0xA414001CUL - -#define INTMSK0 0xa4140044 -#define INTMSKCLR0 0xa4140064 -#define INTC_INTPRI0 0xa4140010 - -/* - NOTE: - - *_IRQ = (INTEVT2 - 0x200)/0x20 -*/ - -/* TMU0 */ -#define TMU0_IRQ 16 -#define TMU0_IPR_ADDR INTC_IPRA -#define TMU0_IPR_POS 3 -#define TMU0_PRIORITY 2 - -#define TIMER_IRQ 16 -#define TIMER_IPR_ADDR INTC_IPRA -#define TIMER_IPR_POS 3 -#define TIMER_PRIORITY 2 - -/* TMU1 */ -#define TMU1_IRQ 17 -#define TMU1_IPR_ADDR INTC_IPRA -#define TMU1_IPR_POS 2 -#define TMU1_PRIORITY 2 - -/* TMU2 */ -#define TMU2_IRQ 18 -#define TMU2_IPR_ADDR INTC_IPRA -#define TMU2_IPR_POS 1 -#define TMU2_PRIORITY 2 - -/* LCDC */ -#define LCDC_IRQ 28 -#define LCDC_IPR_ADDR INTC_IPRB -#define LCDC_IPR_POS 2 -#define LCDC_PRIORITY 2 - -/* VIO (Video I/O) */ -#define CEU_IRQ 52 -#define BEU_IRQ 53 -#define VEU_IRQ 54 -#define VOU_IRQ 55 -#define VIO_IPR_ADDR INTC_IPRE -#define VIO_IPR_POS 2 -#define VIO_PRIORITY 2 - -/* MFI (Multi Functional Interface) */ -#define MFI_IRQ 56 -#define MFI_IPR_ADDR INTC_IPRE -#define MFI_IPR_POS 1 -#define MFI_PRIORITY 2 - -/* VPU (Video Processing Unit) */ -#define VPU_IRQ 60 -#define VPU_IPR_ADDR INTC_IPRE -#define VPU_IPR_POS 0 -#define VPU_PRIORITY 2 - -/* 3DG */ -#define TDG_IRQ 63 -#define TDG_IPR_ADDR INTC_IPRJ -#define TDG_IPR_POS 2 -#define TDG_PRIORITY 2 - -/* DMAC(1) */ -#define DMTE0_IRQ 48 -#define DMTE1_IRQ 49 -#define DMTE2_IRQ 50 -#define DMTE3_IRQ 51 -#define DMA1_IPR_ADDR INTC_IPRE -#define DMA1_IPR_POS 3 -#define DMA1_PRIORITY 7 - -/* DMAC(2) */ -#define DMTE4_IRQ 76 -#define DMTE5_IRQ 77 -#define DMA2_IPR_ADDR INTC_IPRF -#define DMA2_IPR_POS 2 -#define DMA2_PRIORITY 7 - -/* SCIF0 */ -#define SCIF_ERI_IRQ 80 -#define SCIF_RXI_IRQ 81 -#define SCIF_BRI_IRQ 82 -#define SCIF_TXI_IRQ 83 -#define SCIF_IPR_ADDR INTC_IPRG -#define SCIF_IPR_POS 3 -#define SCIF_PRIORITY 3 - -/* SIOF0 */ -#define SIOF0_IRQ 84 -#define SIOF0_IPR_ADDR INTC_IPRH -#define SIOF0_IPR_POS 3 -#define SIOF0_PRIORITY 3 - -/* FLCTL (Flash Memory Controller) */ -#define FLSTE_IRQ 92 -#define FLTEND_IRQ 93 -#define FLTRQ0_IRQ 94 -#define FLTRQ1_IRQ 95 -#define FLCTL_IPR_ADDR INTC_IPRH -#define FLCTL_IPR_POS 1 -#define FLCTL_PRIORITY 3 - -/* IIC(0) (IIC Bus Interface) */ -#define IIC0_ALI_IRQ 96 -#define IIC0_TACKI_IRQ 97 -#define IIC0_WAITI_IRQ 98 -#define IIC0_DTEI_IRQ 99 -#define IIC0_IPR_ADDR INTC_IPRH -#define IIC0_IPR_POS 0 -#define IIC0_PRIORITY 3 - -/* IIC(1) (IIC Bus Interface) */ -#define IIC1_ALI_IRQ 44 -#define IIC1_TACKI_IRQ 45 -#define IIC1_WAITI_IRQ 46 -#define IIC1_DTEI_IRQ 47 -#define IIC1_IPR_ADDR INTC_IPRI -#define IIC1_IPR_POS 0 -#define IIC1_PRIORITY 3 - -/* SIO0 */ -#define SIO0_IRQ 88 -#define SIO0_IPR_ADDR INTC_IPRI -#define SIO0_IPR_POS 3 -#define SIO0_PRIORITY 3 - -/* SDHI */ -#define SDHI_SDHII0_IRQ 100 -#define SDHI_SDHII1_IRQ 101 -#define SDHI_SDHII2_IRQ 102 -#define SDHI_SDHII3_IRQ 103 -#define SDHI_IPR_ADDR INTC_IPRK -#define SDHI_IPR_POS 0 -#define SDHI_PRIORITY 3 - -/* SIU (Sound Interface Unit) */ -#define SIU_IRQ 108 -#define SIU_IPR_ADDR INTC_IPRJ -#define SIU_IPR_POS 1 -#define SIU_PRIORITY 3 - -#define PORT_PACR 0xA4050100UL -#define PORT_PBCR 0xA4050102UL -#define PORT_PCCR 0xA4050104UL -#define PORT_PDCR 0xA4050106UL -#define PORT_PECR 0xA4050108UL -#define PORT_PFCR 0xA405010AUL -#define PORT_PGCR 0xA405010CUL -#define PORT_PHCR 0xA405010EUL -#define PORT_PJCR 0xA4050110UL -#define PORT_PKCR 0xA4050112UL -#define PORT_PLCR 0xA4050114UL -#define PORT_SCPCR 0xA4050116UL -#define PORT_PMCR 0xA4050118UL -#define PORT_PNCR 0xA405011AUL -#define PORT_PQCR 0xA405011CUL -#define PORT_PRCR 0xA405011EUL -#define PORT_PTCR 0xA405014CUL -#define PORT_PUCR 0xA405014EUL -#define PORT_PVCR 0xA4050150UL - -#define PORT_PSELA 0xA4050140UL -#define PORT_PSELB 0xA4050142UL -#define PORT_PSELC 0xA4050144UL -#define PORT_PSELE 0xA4050158UL - -#define PORT_HIZCRA 0xA4050146UL -#define PORT_HIZCRB 0xA4050148UL -#define PORT_DRVCR 0xA405014AUL - -#define PORT_PADR 0xA4050120UL -#define PORT_PBDR 0xA4050122UL -#define PORT_PCDR 0xA4050124UL -#define PORT_PDDR 0xA4050126UL -#define PORT_PEDR 0xA4050128UL -#define PORT_PFDR 0xA405012AUL -#define PORT_PGDR 0xA405012CUL -#define PORT_PHDR 0xA405012EUL -#define PORT_PJDR 0xA4050130UL -#define PORT_PKDR 0xA4050132UL -#define PORT_PLDR 0xA4050134UL -#define PORT_SCPDR 0xA4050136UL -#define PORT_PMDR 0xA4050138UL -#define PORT_PNDR 0xA405013AUL -#define PORT_PQDR 0xA405013CUL -#define PORT_PRDR 0xA405013EUL -#define PORT_PTDR 0xA405016CUL -#define PORT_PUDR 0xA405016EUL -#define PORT_PVDR 0xA4050170UL - -#define IRQ0_IRQ 32 -#define IRQ1_IRQ 33 -#define IRQ2_IRQ 34 -#define IRQ3_IRQ 35 -#define IRQ4_IRQ 36 -#define IRQ5_IRQ 37 -#define IRQ6_IRQ 38 -#define IRQ7_IRQ 39 - -#define INTPRI00 0xA4140010UL - -#define IRQ0_IPR_ADDR INTPRI00 -#define IRQ1_IPR_ADDR INTPRI00 -#define IRQ2_IPR_ADDR INTPRI00 -#define IRQ3_IPR_ADDR INTPRI00 -#define IRQ4_IPR_ADDR INTPRI00 -#define IRQ5_IPR_ADDR INTPRI00 -#define IRQ6_IPR_ADDR INTPRI00 -#define IRQ7_IPR_ADDR INTPRI00 - -#define IRQ0_IPR_POS 7 -#define IRQ1_IPR_POS 6 -#define IRQ2_IPR_POS 5 -#define IRQ3_IPR_POS 4 -#define IRQ4_IPR_POS 3 -#define IRQ5_IPR_POS 2 -#define IRQ6_IPR_POS 1 -#define IRQ7_IPR_POS 0 - -#define IRQ0_PRIORITY 1 -#define IRQ1_PRIORITY 1 -#define IRQ2_PRIORITY 1 -#define IRQ3_PRIORITY 1 -#define IRQ4_PRIORITY 1 -#define IRQ5_PRIORITY 1 -#define IRQ6_PRIORITY 1 -#define IRQ7_PRIORITY 1 - -#endif /* __ASM_SH_IRQ_SH7343_H */ diff --git a/include/asm-sh/irq-sh7780.h b/include/asm-sh/irq-sh7780.h deleted file mode 100644 index 19912ae..0000000 --- a/include/asm-sh/irq-sh7780.h +++ /dev/null @@ -1,311 +0,0 @@ -#ifndef __ASM_SH_IRQ_SH7780_H -#define __ASM_SH_IRQ_SH7780_H - -/* - * linux/include/asm-sh/irq-sh7780.h - * - * Copyright (C) 2004 Takashi SHUDO - */ -#define INTC_BASE 0xffd00000 -#define INTC_ICR0 (INTC_BASE+0x0) -#define INTC_ICR1 (INTC_BASE+0x1c) -#define INTC_INTPRI (INTC_BASE+0x10) -#define INTC_INTREQ (INTC_BASE+0x24) -#define INTC_INTMSK0 (INTC_BASE+0x44) -#define INTC_INTMSK1 (INTC_BASE+0x48) -#define INTC_INTMSK2 (INTC_BASE+0x40080) -#define INTC_INTMSKCLR0 (INTC_BASE+0x64) -#define INTC_INTMSKCLR1 (INTC_BASE+0x68) -#define INTC_INTMSKCLR2 (INTC_BASE+0x40084) -#define INTC_NMIFCR (INTC_BASE+0xc0) -#define INTC_USERIMASK (INTC_BASE+0x30000) - -#define INTC_INT2PRI0 (INTC_BASE+0x40000) -#define INTC_INT2PRI1 (INTC_BASE+0x40004) -#define INTC_INT2PRI2 (INTC_BASE+0x40008) -#define INTC_INT2PRI3 (INTC_BASE+0x4000c) -#define INTC_INT2PRI4 (INTC_BASE+0x40010) -#define INTC_INT2PRI5 (INTC_BASE+0x40014) -#define INTC_INT2PRI6 (INTC_BASE+0x40018) -#define INTC_INT2PRI7 (INTC_BASE+0x4001c) -#define INTC_INT2A0 (INTC_BASE+0x40030) -#define INTC_INT2A1 (INTC_BASE+0x40034) -#define INTC_INT2MSKR (INTC_BASE+0x40038) -#define INTC_INT2MSKCR (INTC_BASE+0x4003c) -#define INTC_INT2B0 (INTC_BASE+0x40040) -#define INTC_INT2B1 (INTC_BASE+0x40044) -#define INTC_INT2B2 (INTC_BASE+0x40048) -#define INTC_INT2B3 (INTC_BASE+0x4004c) -#define INTC_INT2B4 (INTC_BASE+0x40050) -#define INTC_INT2B5 (INTC_BASE+0x40054) -#define INTC_INT2B6 (INTC_BASE+0x40058) -#define INTC_INT2B7 (INTC_BASE+0x4005c) -#define INTC_INT2GPIC (INTC_BASE+0x40090) -/* - NOTE: - *_IRQ = (INTEVT2 - 0x200)/0x20 -*/ -/* IRQ 0-7 line external int*/ -#define IRQ0_IRQ 2 -#define IRQ0_IPR_ADDR INTC_INTPRI -#define IRQ0_IPR_POS 7 -#define IRQ0_PRIORITY 2 - -#define IRQ1_IRQ 4 -#define IRQ1_IPR_ADDR INTC_INTPRI -#define IRQ1_IPR_POS 6 -#define IRQ1_PRIORITY 2 - -#define IRQ2_IRQ 6 -#define IRQ2_IPR_ADDR INTC_INTPRI -#define IRQ2_IPR_POS 5 -#define IRQ2_PRIORITY 2 - -#define IRQ3_IRQ 8 -#define IRQ3_IPR_ADDR INTC_INTPRI -#define IRQ3_IPR_POS 4 -#define IRQ3_PRIORITY 2 - -#define IRQ4_IRQ 10 -#define IRQ4_IPR_ADDR INTC_INTPRI -#define IRQ4_IPR_POS 3 -#define IRQ4_PRIORITY 2 - -#define IRQ5_IRQ 12 -#define IRQ5_IPR_ADDR INTC_INTPRI -#define IRQ5_IPR_POS 2 -#define IRQ5_PRIORITY 2 - -#define IRQ6_IRQ 14 -#define IRQ6_IPR_ADDR INTC_INTPRI -#define IRQ6_IPR_POS 1 -#define IRQ6_PRIORITY 2 - -#define IRQ7_IRQ 0 -#define IRQ7_IPR_ADDR INTC_INTPRI -#define IRQ7_IPR_POS 0 -#define IRQ7_PRIORITY 2 - -/* TMU */ -/* ch0 */ -#define TMU_IRQ 28 -#define TMU_IPR_ADDR INTC_INT2PRI0 -#define TMU_IPR_POS 3 -#define TMU_PRIORITY 2 - -#define TIMER_IRQ 28 -#define TIMER_IPR_ADDR INTC_INT2PRI0 -#define TIMER_IPR_POS 3 -#define TIMER_PRIORITY 2 - -/* ch 1*/ -#define TMU_CH1_IRQ 29 -#define TMU_CH1_IPR_ADDR INTC_INT2PRI0 -#define TMU_CH1_IPR_POS 2 -#define TMU_CH1_PRIORITY 2 - -#define TIMER1_IRQ 29 -#define TIMER1_IPR_ADDR INTC_INT2PRI0 -#define TIMER1_IPR_POS 2 -#define TIMER1_PRIORITY 2 - -/* ch 2*/ -#define TMU_CH2_IRQ 30 -#define TMU_CH2_IPR_ADDR INTC_INT2PRI0 -#define TMU_CH2_IPR_POS 1 -#define TMU_CH2_PRIORITY 2 -/* ch 2 Input capture */ -#define TMU_CH2IC_IRQ 31 -#define TMU_CH2IC_IPR_ADDR INTC_INT2PRI0 -#define TMU_CH2IC_IPR_POS 0 -#define TMU_CH2IC_PRIORITY 2 -/* ch 3 */ -#define TMU_CH3_IRQ 96 -#define TMU_CH3_IPR_ADDR INTC_INT2PRI1 -#define TMU_CH3_IPR_POS 3 -#define TMU_CH3_PRIORITY 2 -/* ch 4 */ -#define TMU_CH4_IRQ 97 -#define TMU_CH4_IPR_ADDR INTC_INT2PRI1 -#define TMU_CH4_IPR_POS 2 -#define TMU_CH4_PRIORITY 2 -/* ch 5*/ -#define TMU_CH5_IRQ 98 -#define TMU_CH5_IPR_ADDR INTC_INT2PRI1 -#define TMU_CH5_IPR_POS 1 -#define TMU_CH5_PRIORITY 2 - -/* SCIF0 */ -#define SCIF0_ERI_IRQ 40 -#define SCIF0_RXI_IRQ 41 -#define SCIF0_BRI_IRQ 42 -#define SCIF0_TXI_IRQ 43 -#define SCIF0_IPR_ADDR INTC_INT2PRI2 -#define SCIF0_IPR_POS 3 -#define SCIF0_PRIORITY 3 - -/* SCIF1 */ -#define SCIF1_ERI_IRQ 76 -#define SCIF1_RXI_IRQ 77 -#define SCIF1_BRI_IRQ 78 -#define SCIF1_TXI_IRQ 79 -#define SCIF1_IPR_ADDR INTC_INT2PRI2 -#define SCIF1_IPR_POS 2 -#define SCIF1_PRIORITY 3 - -#define WDT_IRQ 27 -#define WDT_IPR_ADDR INTC_INT2PRI2 -#define WDT_IPR_POS 1 -#define WDT_PRIORITY 2 - -/* DMAC(0) */ -#define DMINT0_IRQ 34 -#define DMINT1_IRQ 35 -#define DMINT2_IRQ 36 -#define DMINT3_IRQ 37 -#define DMINT4_IRQ 44 -#define DMINT5_IRQ 45 -#define DMINT6_IRQ 46 -#define DMINT7_IRQ 47 -#define DMAE_IRQ 38 -#define DMA0_IPR_ADDR INTC_INT2PRI3 -#define DMA0_IPR_POS 2 -#define DMA0_PRIORITY 7 - -/* DMAC(1) */ -#define DMINT8_IRQ 92 -#define DMINT9_IRQ 93 -#define DMINT10_IRQ 94 -#define DMINT11_IRQ 95 -#define DMA1_IPR_ADDR INTC_INT2PRI3 -#define DMA1_IPR_POS 1 -#define DMA1_PRIORITY 7 - -#define DMTE0_IRQ DMINT0_IRQ -#define DMTE4_IRQ DMINT4_IRQ -#define DMA_IPR_ADDR DMA0_IPR_ADDR -#define DMA_IPR_POS DMA0_IPR_POS -#define DMA_PRIORITY DMA0_PRIORITY - -/* CMT */ -#define CMT_IRQ 56 -#define CMT_IPR_ADDR INTC_INT2PRI4 -#define CMT_IPR_POS 3 -#define CMT_PRIORITY 0 - -/* HAC */ -#define HAC_IRQ 60 -#define HAC_IPR_ADDR INTC_INT2PRI4 -#define HAC_IPR_POS 2 -#define CMT_PRIORITY 0 - -/* PCIC(0) */ -#define PCIC0_IRQ 64 -#define PCIC0_IPR_ADDR INTC_INT2PRI4 -#define PCIC0_IPR_POS 1 -#define PCIC0_PRIORITY 2 - -/* PCIC(1) */ -#define PCIC1_IRQ 65 -#define PCIC1_IPR_ADDR INTC_INT2PRI4 -#define PCIC1_IPR_POS 0 -#define PCIC1_PRIORITY 2 - -/* PCIC(2) */ -#define PCIC2_IRQ 66 -#define PCIC2_IPR_ADDR INTC_INT2PRI5 -#define PCIC2_IPR_POS 3 -#define PCIC2_PRIORITY 2 - -/* PCIC(3) */ -#define PCIC3_IRQ 67 -#define PCIC3_IPR_ADDR INTC_INT2PRI5 -#define PCIC3_IPR_POS 2 -#define PCIC3_PRIORITY 2 - -/* PCIC(4) */ -#define PCIC4_IRQ 68 -#define PCIC4_IPR_ADDR INTC_INT2PRI5 -#define PCIC4_IPR_POS 1 -#define PCIC4_PRIORITY 2 - -/* PCIC(5) */ -#define PCICERR_IRQ 69 -#define PCICPWD3_IRQ 70 -#define PCICPWD2_IRQ 71 -#define PCICPWD1_IRQ 72 -#define PCICPWD0_IRQ 73 -#define PCIC5_IPR_ADDR INTC_INT2PRI5 -#define PCIC5_IPR_POS 0 -#define PCIC5_PRIORITY 2 - -/* SIOF */ -#define SIOF_IRQ 80 -#define SIOF_IPR_ADDR INTC_INT2PRI6 -#define SIOF_IPR_POS 3 -#define SIOF_PRIORITY 3 - -/* HSPI */ -#define HSPI_IRQ 84 -#define HSPI_IPR_ADDR INTC_INT2PRI6 -#define HSPI_IPR_POS 2 -#define HSPI_PRIORITY 3 - -/* MMCIF */ -#define MMCIF_FSTAT_IRQ 88 -#define MMCIF_TRAN_IRQ 89 -#define MMCIF_ERR_IRQ 90 -#define MMCIF_FRDY_IRQ 91 -#define MMCIF_IPR_ADDR INTC_INT2PRI6 -#define MMCIF_IPR_POS 1 -#define HSPI_PRIORITY 3 - -/* SSI */ -#define SSI_IRQ 100 -#define SSI_IPR_ADDR INTC_INT2PRI6 -#define SSI_IPR_POS 0 -#define SSI_PRIORITY 3 - -/* FLCTL */ -#define FLCTL_FLSTE_IRQ 104 -#define FLCTL_FLTEND_IRQ 105 -#define FLCTL_FLTRQ0_IRQ 106 -#define FLCTL_FLTRQ1_IRQ 107 -#define FLCTL_IPR_ADDR INTC_INT2PRI7 -#define FLCTL_IPR_POS 3 -#define FLCTL_PRIORITY 3 - -/* GPIO */ -#define GPIO0_IRQ 108 -#define GPIO1_IRQ 109 -#define GPIO2_IRQ 110 -#define GPIO3_IRQ 111 -#define GPIO_IPR_ADDR INTC_INT2PRI7 -#define GPIO_IPR_POS 2 -#define GPIO_PRIORITY 3 - -#define INTC_TMU0_MSK 0 -#define INTC_TMU3_MSK 1 -#define INTC_RTC_MSK 2 -#define INTC_SCIF0_MSK 3 -#define INTC_SCIF1_MSK 4 -#define INTC_WDT_MSK 5 -#define INTC_HUID_MSK 7 -#define INTC_DMAC0_MSK 8 -#define INTC_DMAC1_MSK 9 -#define INTC_CMT_MSK 12 -#define INTC_HAC_MSK 13 -#define INTC_PCIC0_MSK 14 -#define INTC_PCIC1_MSK 15 -#define INTC_PCIC2_MSK 16 -#define INTC_PCIC3_MSK 17 -#define INTC_PCIC4_MSK 18 -#define INTC_PCIC5_MSK 19 -#define INTC_SIOF_MSK 20 -#define INTC_HSPI_MSK 21 -#define INTC_MMCIF_MSK 22 -#define INTC_SSI_MSK 23 -#define INTC_FLCTL_MSK 24 -#define INTC_GPIO_MSK 25 - -#endif /* __ASM_SH_IRQ_SH7780_H */ diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h index 6cd3e9e..f10cfc1 100644 --- a/include/asm-sh/irq.h +++ b/include/asm-sh/irq.h @@ -1,233 +1,9 @@ #ifndef __ASM_SH_IRQ_H #define __ASM_SH_IRQ_H -/* - * - * linux/include/asm-sh/irq.h - * - * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi - * Copyright (C) 2000 Kazumoto Kojima - * Copyright (C) 2003 Paul Mundt - * - */ - #include #include /* for pt_regs */ -#ifndef CONFIG_CPU_SUBTYPE_SH7780 - -#define INTC_DMAC0_MSK 0 - -#if defined(CONFIG_CPU_SH3) -#define INTC_IPRA 0xfffffee2UL -#define INTC_IPRB 0xfffffee4UL -#elif defined(CONFIG_CPU_SH4) -#define INTC_IPRA 0xffd00004UL -#define INTC_IPRB 0xffd00008UL -#define INTC_IPRC 0xffd0000cUL -#define INTC_IPRD 0xffd00010UL -#endif - -#define TIMER_IRQ 16 -#define TIMER_IPR_ADDR INTC_IPRA -#define TIMER_IPR_POS 3 -#define TIMER_PRIORITY 2 - -#define TIMER1_IRQ 17 -#define TIMER1_IPR_ADDR INTC_IPRA -#define TIMER1_IPR_POS 2 -#define TIMER1_PRIORITY 4 - -#define RTC_IRQ 22 -#define RTC_IPR_ADDR INTC_IPRA -#define RTC_IPR_POS 0 -#define RTC_PRIORITY TIMER_PRIORITY - -#if defined(CONFIG_CPU_SH3) -#define DMTE0_IRQ 48 -#define DMTE1_IRQ 49 -#define DMTE2_IRQ 50 -#define DMTE3_IRQ 51 -#define DMA_IPR_ADDR INTC_IPRE -#define DMA_IPR_POS 3 -#define DMA_PRIORITY 7 -#if defined(CONFIG_CPU_SUBTYPE_SH7300) -/* TMU2 */ -#define TIMER2_IRQ 18 -#define TIMER2_IPR_ADDR INTC_IPRA -#define TIMER2_IPR_POS 1 -#define TIMER2_PRIORITY 2 - -/* WDT */ -#define WDT_IRQ 27 -#define WDT_IPR_ADDR INTC_IPRB -#define WDT_IPR_POS 3 -#define WDT_PRIORITY 2 - -/* SIM (SIM Card Module) */ -#define SIM_ERI_IRQ 23 -#define SIM_RXI_IRQ 24 -#define SIM_TXI_IRQ 25 -#define SIM_TEND_IRQ 26 -#define SIM_IPR_ADDR INTC_IPRB -#define SIM_IPR_POS 1 -#define SIM_PRIORITY 2 - -/* VIO (Video I/O) */ -#define VIO_IRQ 52 -#define VIO_IPR_ADDR INTC_IPRE -#define VIO_IPR_POS 2 -#define VIO_PRIORITY 2 - -/* MFI (Multi Functional Interface) */ -#define MFI_IRQ 56 -#define MFI_IPR_ADDR INTC_IPRE -#define MFI_IPR_POS 1 -#define MFI_PRIORITY 2 - -/* VPU (Video Processing Unit) */ -#define VPU_IRQ 60 -#define VPU_IPR_ADDR INTC_IPRE -#define VPU_IPR_POS 0 -#define VPU_PRIORITY 2 - -/* KEY (Key Scan Interface) */ -#define KEY_IRQ 79 -#define KEY_IPR_ADDR INTC_IPRF -#define KEY_IPR_POS 3 -#define KEY_PRIORITY 2 - -/* CMT (Compare Match Timer) */ -#define CMT_IRQ 104 -#define CMT_IPR_ADDR INTC_IPRF -#define CMT_IPR_POS 0 -#define CMT_PRIORITY 2 - -/* DMAC(1) */ -#define DMTE0_IRQ 48 -#define DMTE1_IRQ 49 -#define DMTE2_IRQ 50 -#define DMTE3_IRQ 51 -#define DMA1_IPR_ADDR INTC_IPRE -#define DMA1_IPR_POS 3 -#define DMA1_PRIORITY 7 - -/* DMAC(2) */ -#define DMTE4_IRQ 76 -#define DMTE5_IRQ 77 -#define DMA2_IPR_ADDR INTC_IPRF -#define DMA2_IPR_POS 2 -#define DMA2_PRIORITY 7 - -/* SIOF0 */ -#define SIOF0_IRQ 84 -#define SIOF0_IPR_ADDR INTC_IPRH -#define SIOF0_IPR_POS 3 -#define SIOF0_PRIORITY 3 - -/* FLCTL (Flash Memory Controller) */ -#define FLSTE_IRQ 92 -#define FLTEND_IRQ 93 -#define FLTRQ0_IRQ 94 -#define FLTRQ1_IRQ 95 -#define FLCTL_IPR_ADDR INTC_IPRH -#define FLCTL_IPR_POS 1 -#define FLCTL_PRIORITY 3 - -/* IIC (IIC Bus Interface) */ -#define IIC_ALI_IRQ 96 -#define IIC_TACKI_IRQ 97 -#define IIC_WAITI_IRQ 98 -#define IIC_DTEI_IRQ 99 -#define IIC_IPR_ADDR INTC_IPRH -#define IIC_IPR_POS 0 -#define IIC_PRIORITY 3 - -/* SIO0 */ -#define SIO0_IRQ 88 -#define SIO0_IPR_ADDR INTC_IPRI -#define SIO0_IPR_POS 3 -#define SIO0_PRIORITY 3 - -/* SIU (Sound Interface Unit) */ -#define SIU_IRQ 108 -#define SIU_IPR_ADDR INTC_IPRJ -#define SIU_IPR_POS 1 -#define SIU_PRIORITY 3 - -#endif -#elif defined(CONFIG_CPU_SH4) -#define DMTE0_IRQ 34 -#define DMTE1_IRQ 35 -#define DMTE2_IRQ 36 -#define DMTE3_IRQ 37 -#define DMTE4_IRQ 44 /* 7751R only */ -#define DMTE5_IRQ 45 /* 7751R only */ -#define DMTE6_IRQ 46 /* 7751R only */ -#define DMTE7_IRQ 47 /* 7751R only */ -#define DMAE_IRQ 38 -#define DMA_IPR_ADDR INTC_IPRC -#define DMA_IPR_POS 2 -#define DMA_PRIORITY 7 -#endif - -#if defined (CONFIG_CPU_SUBTYPE_SH7707) || defined (CONFIG_CPU_SUBTYPE_SH7708) || \ - defined (CONFIG_CPU_SUBTYPE_SH7709) || defined (CONFIG_CPU_SUBTYPE_SH7750) || \ - defined (CONFIG_CPU_SUBTYPE_SH7751) || defined (CONFIG_CPU_SUBTYPE_SH7706) -#define SCI_ERI_IRQ 23 -#define SCI_RXI_IRQ 24 -#define SCI_TXI_IRQ 25 -#define SCI_IPR_ADDR INTC_IPRB -#define SCI_IPR_POS 1 -#define SCI_PRIORITY 3 -#endif - -#if defined(CONFIG_CPU_SUBTYPE_SH7300) -#define SCIF0_IRQ 80 -#define SCIF0_IPR_ADDR INTC_IPRG -#define SCIF0_IPR_POS 3 -#define SCIF0_PRIORITY 3 -#elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7706) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) -#define SCIF_ERI_IRQ 56 -#define SCIF_RXI_IRQ 57 -#define SCIF_BRI_IRQ 58 -#define SCIF_TXI_IRQ 59 -#define SCIF_IPR_ADDR INTC_IPRE -#define SCIF_IPR_POS 1 -#define SCIF_PRIORITY 3 - -#define IRDA_ERI_IRQ 52 -#define IRDA_RXI_IRQ 53 -#define IRDA_BRI_IRQ 54 -#define IRDA_TXI_IRQ 55 -#define IRDA_IPR_ADDR INTC_IPRE -#define IRDA_IPR_POS 2 -#define IRDA_PRIORITY 3 -#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \ - defined(CONFIG_CPU_SUBTYPE_ST40STB1) || defined(CONFIG_CPU_SUBTYPE_SH4_202) -#define SCIF_ERI_IRQ 40 -#define SCIF_RXI_IRQ 41 -#define SCIF_BRI_IRQ 42 -#define SCIF_TXI_IRQ 43 -#define SCIF_IPR_ADDR INTC_IPRC -#define SCIF_IPR_POS 1 -#define SCIF_PRIORITY 3 -#if defined(CONFIG_CPU_SUBTYPE_ST40STB1) -#define SCIF1_ERI_IRQ 23 -#define SCIF1_RXI_IRQ 24 -#define SCIF1_BRI_IRQ 25 -#define SCIF1_TXI_IRQ 26 -#define SCIF1_IPR_ADDR INTC_IPRB -#define SCIF1_IPR_POS 1 -#define SCIF1_PRIORITY 3 -#endif /* ST40STB1 */ - -#endif /* 775x / SH4-202 / ST40STB1 */ -#endif /* 7780 */ - /* NR_IRQS is made from three components: * 1. ONCHIP_NR_IRQS - number of IRLS + on-chip peripherial modules * 2. PINT_NR_IRQS - number of PINT interrupts @@ -265,6 +41,10 @@ #elif defined(CONFIG_CPU_SUBTYPE_SH7300) # define ONCHIP_NR_IRQS 109 #elif defined(CONFIG_CPU_SUBTYPE_SH7780) # define ONCHIP_NR_IRQS 111 +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +# define ONCHIP_NR_IRQS 256 +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +# define ONCHIP_NR_IRQS 128 #elif defined(CONFIG_SH_UNKNOWN) /* Most be last */ # define ONCHIP_NR_IRQS 144 #endif @@ -312,10 +92,6 @@ #endif /* NR_IRQS. 1+2+3 */ #define NR_IRQS (ONCHIP_NR_IRQS + PINT_NR_IRQS + OFFCHIP_NR_IRQS) -extern void disable_irq(unsigned int); -extern void disable_irq_nosync(unsigned int); -extern void enable_irq(unsigned int); - /* * Simple Mask Register Support */ @@ -340,350 +116,6 @@ struct ipr_data { extern void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs); extern void make_imask_irq(unsigned int irq); -#if defined(CONFIG_CPU_SUBTYPE_SH7300) -#undef INTC_IPRA -#undef INTC_IPRB -#define INTC_IPRA 0xA414FEE2UL -#define INTC_IPRB 0xA414FEE4UL -#define INTC_IPRC 0xA4140016UL -#define INTC_IPRD 0xA4140018UL -#define INTC_IPRE 0xA414001AUL -#define INTC_IPRF 0xA4080000UL -#define INTC_IPRG 0xA4080002UL -#define INTC_IPRH 0xA4080004UL -#define INTC_IPRI 0xA4080006UL -#define INTC_IPRJ 0xA4080008UL - -#define INTC_IMR0 0xA4080040UL -#define INTC_IMR1 0xA4080042UL -#define INTC_IMR2 0xA4080044UL -#define INTC_IMR3 0xA4080046UL -#define INTC_IMR4 0xA4080048UL -#define INTC_IMR5 0xA408004AUL -#define INTC_IMR6 0xA408004CUL -#define INTC_IMR7 0xA408004EUL -#define INTC_IMR8 0xA4080050UL -#define INTC_IMR9 0xA4080052UL -#define INTC_IMR10 0xA4080054UL - -#define INTC_IMCR0 0xA4080060UL -#define INTC_IMCR1 0xA4080062UL -#define INTC_IMCR2 0xA4080064UL -#define INTC_IMCR3 0xA4080066UL -#define INTC_IMCR4 0xA4080068UL -#define INTC_IMCR5 0xA408006AUL -#define INTC_IMCR6 0xA408006CUL -#define INTC_IMCR7 0xA408006EUL -#define INTC_IMCR8 0xA4080070UL -#define INTC_IMCR9 0xA4080072UL -#define INTC_IMCR10 0xA4080074UL - -#define INTC_ICR0 0xA414FEE0UL -#define INTC_ICR1 0xA4140010UL - -#define INTC_IRR0 0xA4140004UL - -#define PORT_PACR 0xA4050100UL -#define PORT_PBCR 0xA4050102UL -#define PORT_PCCR 0xA4050104UL -#define PORT_PDCR 0xA4050106UL -#define PORT_PECR 0xA4050108UL -#define PORT_PFCR 0xA405010AUL -#define PORT_PGCR 0xA405010CUL -#define PORT_PHCR 0xA405010EUL -#define PORT_PJCR 0xA4050110UL -#define PORT_PKCR 0xA4050112UL -#define PORT_PLCR 0xA4050114UL -#define PORT_SCPCR 0xA4050116UL -#define PORT_PMCR 0xA4050118UL -#define PORT_PNCR 0xA405011AUL -#define PORT_PQCR 0xA405011CUL - -#define PORT_PSELA 0xA4050140UL -#define PORT_PSELB 0xA4050142UL -#define PORT_PSELC 0xA4050144UL - -#define PORT_HIZCRA 0xA4050146UL -#define PORT_HIZCRB 0xA4050148UL -#define PORT_DRVCR 0xA4050150UL - -#define PORT_PADR 0xA4050120UL -#define PORT_PBDR 0xA4050122UL -#define PORT_PCDR 0xA4050124UL -#define PORT_PDDR 0xA4050126UL -#define PORT_PEDR 0xA4050128UL -#define PORT_PFDR 0xA405012AUL -#define PORT_PGDR 0xA405012CUL -#define PORT_PHDR 0xA405012EUL -#define PORT_PJDR 0xA4050130UL -#define PORT_PKDR 0xA4050132UL -#define PORT_PLDR 0xA4050134UL -#define PORT_SCPDR 0xA4050136UL -#define PORT_PMDR 0xA4050138UL -#define PORT_PNDR 0xA405013AUL -#define PORT_PQDR 0xA405013CUL - -#define IRQ0_IRQ 32 -#define IRQ1_IRQ 33 -#define IRQ2_IRQ 34 -#define IRQ3_IRQ 35 -#define IRQ4_IRQ 36 -#define IRQ5_IRQ 37 - -#define IRQ0_IPR_ADDR INTC_IPRC -#define IRQ1_IPR_ADDR INTC_IPRC -#define IRQ2_IPR_ADDR INTC_IPRC -#define IRQ3_IPR_ADDR INTC_IPRC -#define IRQ4_IPR_ADDR INTC_IPRD -#define IRQ5_IPR_ADDR INTC_IPRD - -#define IRQ0_IPR_POS 0 -#define IRQ1_IPR_POS 1 -#define IRQ2_IPR_POS 2 -#define IRQ3_IPR_POS 3 -#define IRQ4_IPR_POS 0 -#define IRQ5_IPR_POS 1 - -#define IRQ0_PRIORITY 1 -#define IRQ1_PRIORITY 1 -#define IRQ2_PRIORITY 1 -#define IRQ3_PRIORITY 1 -#define IRQ4_PRIORITY 1 -#define IRQ5_PRIORITY 1 - -extern int ipr_irq_demux(int irq); -#define __irq_demux(irq) ipr_irq_demux(irq) - -#elif defined(CONFIG_CPU_SUBTYPE_SH7604) -#define INTC_IPRA 0xfffffee2UL -#define INTC_IPRB 0xfffffe60UL - -#define INTC_VCRA 0xfffffe62UL -#define INTC_VCRB 0xfffffe64UL -#define INTC_VCRC 0xfffffe66UL -#define INTC_VCRD 0xfffffe68UL - -#define INTC_VCRWDT 0xfffffee4UL -#define INTC_VCRDIV 0xffffff0cUL -#define INTC_VCRDMA0 0xffffffa0UL -#define INTC_VCRDMA1 0xffffffa8UL - -#define INTC_ICR 0xfffffee0UL -#elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7706) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7710) -#define INTC_IRR0 0xa4000004UL -#define INTC_IRR1 0xa4000006UL -#define INTC_IRR2 0xa4000008UL - -#define INTC_ICR0 0xfffffee0UL -#define INTC_ICR1 0xa4000010UL -#define INTC_ICR2 0xa4000012UL -#define INTC_INTER 0xa4000014UL - -#define INTC_IPRC 0xa4000016UL -#define INTC_IPRD 0xa4000018UL -#define INTC_IPRE 0xa400001aUL -#if defined(CONFIG_CPU_SUBTYPE_SH7707) -#define INTC_IPRF 0xa400001cUL -#elif defined(CONFIG_CPU_SUBTYPE_SH7705) -#define INTC_IPRF 0xa4080000UL -#define INTC_IPRG 0xa4080002UL -#define INTC_IPRH 0xa4080004UL -#elif defined(CONFIG_CPU_SUBTYPE_SH7710) -/* Interrupt Controller Registers */ -#undef INTC_IPRA -#undef INTC_IPRB -#define INTC_IPRA 0xA414FEE2UL -#define INTC_IPRB 0xA414FEE4UL -#define INTC_IPRF 0xA4080000UL -#define INTC_IPRG 0xA4080002UL -#define INTC_IPRH 0xA4080004UL -#define INTC_IPRI 0xA4080006UL - -#undef INTC_ICR0 -#undef INTC_ICR1 -#define INTC_ICR0 0xA414FEE0UL -#define INTC_ICR1 0xA4140010UL - -#define INTC_IRR0 0xa4000004UL -#define INTC_IRR1 0xa4000006UL -#define INTC_IRR2 0xa4000008UL -#define INTC_IRR3 0xa400000AUL -#define INTC_IRR4 0xa400000CUL -#define INTC_IRR5 0xa4080020UL -#define INTC_IRR7 0xa4080024UL -#define INTC_IRR8 0xa4080026UL - -/* Interrupt numbers */ -#define TIMER2_IRQ 18 -#define TIMER2_IPR_ADDR INTC_IPRA -#define TIMER2_IPR_POS 1 -#define TIMER2_PRIORITY 2 - -/* WDT */ -#define WDT_IRQ 27 -#define WDT_IPR_ADDR INTC_IPRB -#define WDT_IPR_POS 3 -#define WDT_PRIORITY 2 - -#define SCIF0_ERI_IRQ 52 -#define SCIF0_RXI_IRQ 53 -#define SCIF0_BRI_IRQ 54 -#define SCIF0_TXI_IRQ 55 -#define SCIF0_IPR_ADDR INTC_IPRE -#define SCIF0_IPR_POS 2 -#define SCIF0_PRIORITY 3 - -#define DMTE4_IRQ 76 -#define DMTE5_IRQ 77 -#define DMA2_IPR_ADDR INTC_IPRF -#define DMA2_IPR_POS 2 -#define DMA2_PRIORITY 7 - -#define IPSEC_IRQ 79 -#define IPSEC_IPR_ADDR INTC_IPRF -#define IPSEC_IPR_POS 3 -#define IPSEC_PRIORITY 3 - -/* EDMAC */ -#define EDMAC0_IRQ 80 -#define EDMAC0_IPR_ADDR INTC_IPRG -#define EDMAC0_IPR_POS 3 -#define EDMAC0_PRIORITY 3 - -#define EDMAC1_IRQ 81 -#define EDMAC1_IPR_ADDR INTC_IPRG -#define EDMAC1_IPR_POS 2 -#define EDMAC1_PRIORITY 3 - -#define EDMAC2_IRQ 82 -#define EDMAC2_IPR_ADDR INTC_IPRG -#define EDMAC2_IPR_POS 1 -#define EDMAC2_PRIORITY 3 - -/* SIOF */ -#define SIOF0_ERI_IRQ 96 -#define SIOF0_TXI_IRQ 97 -#define SIOF0_RXI_IRQ 98 -#define SIOF0_CCI_IRQ 99 -#define SIOF0_IPR_ADDR INTC_IPRH -#define SIOF0_IPR_POS 0 -#define SIOF0_PRIORITY 7 - -#define SIOF1_ERI_IRQ 100 -#define SIOF1_TXI_IRQ 101 -#define SIOF1_RXI_IRQ 102 -#define SIOF1_CCI_IRQ 103 -#define SIOF1_IPR_ADDR INTC_IPRI -#define SIOF1_IPR_POS 1 -#define SIOF1_PRIORITY 7 -#endif /* CONFIG_CPU_SUBTYPE_SH7710 */ - -#if defined(CONFIG_CPU_SUBTYPE_SH7710) -#define PORT_PACR 0xa4050100UL -#define PORT_PBCR 0xa4050102UL -#define PORT_PCCR 0xa4050104UL -#define PORT_PETCR 0xa4050106UL -#define PORT_PADR 0xa4050120UL -#define PORT_PBDR 0xa4050122UL -#define PORT_PCDR 0xa4050124UL -#else -#define PORT_PACR 0xa4000100UL -#define PORT_PBCR 0xa4000102UL -#define PORT_PCCR 0xa4000104UL -#define PORT_PFCR 0xa400010aUL -#define PORT_PADR 0xa4000120UL -#define PORT_PBDR 0xa4000122UL -#define PORT_PCDR 0xa4000124UL -#define PORT_PFDR 0xa400012aUL -#endif - -#define IRQ0_IRQ 32 -#define IRQ1_IRQ 33 -#define IRQ2_IRQ 34 -#define IRQ3_IRQ 35 -#define IRQ4_IRQ 36 -#define IRQ5_IRQ 37 - -#define IRQ0_IPR_ADDR INTC_IPRC -#define IRQ1_IPR_ADDR INTC_IPRC -#define IRQ2_IPR_ADDR INTC_IPRC -#define IRQ3_IPR_ADDR INTC_IPRC -#define IRQ4_IPR_ADDR INTC_IPRD -#define IRQ5_IPR_ADDR INTC_IPRD - -#define IRQ0_IPR_POS 0 -#define IRQ1_IPR_POS 1 -#define IRQ2_IPR_POS 2 -#define IRQ3_IPR_POS 3 -#define IRQ4_IPR_POS 0 -#define IRQ5_IPR_POS 1 - -#define IRQ0_PRIORITY 1 -#define IRQ1_PRIORITY 1 -#define IRQ2_PRIORITY 1 -#define IRQ3_PRIORITY 1 -#define IRQ4_PRIORITY 1 -#define IRQ5_PRIORITY 1 - -#define PINT0_IRQ 40 -#define PINT8_IRQ 41 - -#define PINT0_IPR_ADDR INTC_IPRD -#define PINT8_IPR_ADDR INTC_IPRD - -#define PINT0_IPR_POS 3 -#define PINT8_IPR_POS 2 -#define PINT0_PRIORITY 2 -#define PINT8_PRIORITY 2 - -extern int ipr_irq_demux(int irq); -#define __irq_demux(irq) ipr_irq_demux(irq) -#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */ - -#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \ - defined(CONFIG_CPU_SUBTYPE_ST40STB1) || defined(CONFIG_CPU_SUBTYPE_SH4_202) -#define INTC_ICR 0xffd00000 -#define INTC_ICR_NMIL (1<<15) -#define INTC_ICR_MAI (1<<14) -#define INTC_ICR_NMIB (1<<9) -#define INTC_ICR_NMIE (1<<8) -#define INTC_ICR_IRLM (1<<7) -#endif - -#ifdef CONFIG_CPU_SUBTYPE_SH7780 -#include -#endif - -/* SH with INTC2-style interrupts */ -#ifdef CONFIG_CPU_HAS_INTC2_IRQ -#if defined(CONFIG_CPU_SUBTYPE_ST40STB1) -#define INTC2_BASE 0xfe080000 -#define INTC2_FIRST_IRQ 64 -#define INTC2_INTREQ_OFFSET 0x20 -#define INTC2_INTMSK_OFFSET 0x40 -#define INTC2_INTMSKCLR_OFFSET 0x60 -#define NR_INTC2_IRQS 25 -#elif defined(CONFIG_CPU_SUBTYPE_SH7760) -#define INTC2_BASE 0xfe080000 -#define INTC2_FIRST_IRQ 48 /* INTEVT 0x800 */ -#define INTC2_INTREQ_OFFSET 0x20 -#define INTC2_INTMSK_OFFSET 0x40 -#define INTC2_INTMSKCLR_OFFSET 0x60 -#define NR_INTC2_IRQS 64 -#elif defined(CONFIG_CPU_SUBTYPE_SH7780) -#define INTC2_BASE 0xffd40000 -#define INTC2_FIRST_IRQ 21 -#define INTC2_INTMSK_OFFSET (0x38) -#define INTC2_INTMSKCLR_OFFSET (0x3c) -#define NR_INTC2_IRQS 60 -#endif - -#define INTC2_INTPRI_OFFSET 0x00 - struct intc2_data { unsigned short irq; unsigned char ipr_offset, ipr_shift; @@ -693,20 +125,14 @@ struct intc2_data { void make_intc2_irq(struct intc2_data *, unsigned int nr_irqs); void init_IRQ_intc2(void); -#endif - -extern int shmse_irq_demux(int irq); static inline int generic_irq_demux(int irq) { return irq; } -#ifndef __irq_demux -#define __irq_demux(irq) (irq) -#endif #define irq_canonicalize(irq) (irq) -#define irq_demux(irq) __irq_demux(sh_mv.mv_irq_demux(irq)) +#define irq_demux(irq) sh_mv.mv_irq_demux(irq) #ifdef CONFIG_4KSTACKS extern void irq_ctx_init(int cpu); @@ -717,12 +143,4 @@ # define irq_ctx_init(cpu) do { } while # define irq_ctx_exit(cpu) do { } while (0) #endif -#if defined(CONFIG_CPU_SUBTYPE_SH73180) -#include -#endif - -#if defined(CONFIG_CPU_SUBTYPE_SH7343) -#include -#endif - #endif /* __ASM_SH_IRQ_H */ diff --git a/include/asm-sh/mmu_context.h b/include/asm-sh/mmu_context.h index c7088ef..46f04e2 100644 --- a/include/asm-sh/mmu_context.h +++ b/include/asm-sh/mmu_context.h @@ -10,7 +10,6 @@ #ifdef __KERNEL__ #include #include -#include #include #include @@ -42,10 +41,8 @@ #ifdef CONFIG_MMU /* * Get MMU context if needed. */ -static __inline__ void -get_mmu_context(struct mm_struct *mm) +static inline void get_mmu_context(struct mm_struct *mm) { - extern void flush_tlb_all(void); unsigned long mc = mmu_context_cache; /* Check if we have old version of context. */ @@ -61,6 +58,7 @@ get_mmu_context(struct mm_struct *mm) * Flush all TLB and start new cycle. */ flush_tlb_all(); + /* * Fix version; Note that we avoid version #0 * to distingush NO_CONTEXT. @@ -75,11 +73,10 @@ get_mmu_context(struct mm_struct *mm) * Initialize the context related info for a new mm_struct * instance. */ -static __inline__ int init_new_context(struct task_struct *tsk, +static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { mm->context.id = NO_CONTEXT; - return 0; } @@ -87,12 +84,12 @@ static __inline__ int init_new_context(s * Destroy context related info for an mm_struct that is about * to be put to rest. */ -static __inline__ void destroy_context(struct mm_struct *mm) +static inline void destroy_context(struct mm_struct *mm) { /* Do nothing */ } -static __inline__ void set_asid(unsigned long asid) +static inline void set_asid(unsigned long asid) { unsigned long __dummy; @@ -105,7 +102,7 @@ static __inline__ void set_asid(unsigned "r" (0xffffff00)); } -static __inline__ unsigned long get_asid(void) +static inline unsigned long get_asid(void) { unsigned long asid; @@ -120,24 +117,29 @@ static __inline__ unsigned long get_asid * After we have set current->mm to a new value, this activates * the context for the new mm so we see the new mappings. */ -static __inline__ void activate_context(struct mm_struct *mm) +static inline void activate_context(struct mm_struct *mm) { get_mmu_context(mm); set_asid(mm->context.id & MMU_CONTEXT_ASID_MASK); } -/* MMU_TTB can be used for optimizing the fault handling. - (Currently not used) */ -static __inline__ void switch_mm(struct mm_struct *prev, - struct mm_struct *next, - struct task_struct *tsk) +/* MMU_TTB is used for optimizing the fault handling. */ +static inline void set_TTB(pgd_t *pgd) { - if (likely(prev != next)) { - unsigned long __pgdir = (unsigned long)next->pgd; + ctrl_outl((unsigned long)pgd, MMU_TTB); +} - __asm__ __volatile__("mov.l %0, %1" - : /* no output */ - : "r" (__pgdir), "m" (__m(MMU_TTB))); +static inline pgd_t *get_TTB(void) +{ + return (pgd_t *)ctrl_inl(MMU_TTB); +} + +static inline void switch_mm(struct mm_struct *prev, + struct mm_struct *next, + struct task_struct *tsk) +{ + if (likely(prev != next)) { + set_TTB(next->pgd); activate_context(next); } } @@ -147,7 +149,7 @@ #define deactivate_mm(tsk,mm) do { } whi #define activate_mm(prev, next) \ switch_mm((prev),(next),NULL) -static __inline__ void +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { } diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h index ca8b26d..380fd62 100644 --- a/include/asm-sh/page.h +++ b/include/asm-sh/page.h @@ -13,9 +13,16 @@ #define __ASM_SH_PAGE_H [ P4 control ] 0xE0000000 */ - /* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT 12 +#if defined(CONFIG_PAGE_SIZE_4KB) +# define PAGE_SHIFT 12 +#elif defined(CONFIG_PAGE_SIZE_8KB) +# define PAGE_SHIFT 13 +#elif defined(CONFIG_PAGE_SIZE_64KB) +# define PAGE_SHIFT 16 +#else +# error "Bogus kernel page size?" +#endif #ifdef __ASSEMBLY__ #define PAGE_SIZE (1 << PAGE_SHIFT) @@ -28,8 +35,14 @@ #define PTE_MASK PAGE_MASK #if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) #define HPAGE_SHIFT 16 +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K) +#define HPAGE_SHIFT 18 #elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) #define HPAGE_SHIFT 20 +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB) +#define HPAGE_SHIFT 22 +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB) +#define HPAGE_SHIFT 26 #endif #ifdef CONFIG_HUGETLB_PAGE @@ -69,15 +82,25 @@ #endif /* * These are used to make use of C type-checking.. */ -typedef struct { unsigned long pte; } pte_t; -typedef struct { unsigned long pgd; } pgd_t; +#ifdef CONFIG_X2TLB +typedef struct { unsigned long pte_low, pte_high; } pte_t; +typedef struct { unsigned long long pgprot; } pgprot_t; +#define pte_val(x) \ + ((x).pte_low | ((unsigned long long)(x).pte_high << 32)) +#define __pte(x) \ + ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; }) +#else +typedef struct { unsigned long pte_low; } pte_t; typedef struct { unsigned long pgprot; } pgprot_t; +#define pte_val(x) ((x).pte_low) +#define __pte(x) ((pte_t) { (x) } ) +#endif + +typedef struct { unsigned long pgd; } pgd_t; -#define pte_val(x) ((x).pte) #define pgd_val(x) ((x).pgd) #define pgprot_val(x) ((x).pgprot) -#define __pte(x) ((pte_t) { (x) } ) #define __pgd(x) ((pgd_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } ) diff --git a/include/asm-sh/pgalloc.h b/include/asm-sh/pgalloc.h index e841465..888e452 100644 --- a/include/asm-sh/pgalloc.h +++ b/include/asm-sh/pgalloc.h @@ -1,13 +1,16 @@ #ifndef __ASM_SH_PGALLOC_H #define __ASM_SH_PGALLOC_H -#define pmd_populate_kernel(mm, pmd, pte) \ - set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) +static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, + pte_t *pte) +{ + set_pmd(pmd, __pmd((unsigned long)pte)); +} static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte) { - set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte))); + set_pmd(pmd, __pmd((unsigned long)page_address(pte))); } /* @@ -15,7 +18,16 @@ static inline void pmd_populate(struct m */ static inline pgd_t *pgd_alloc(struct mm_struct *mm) { - return (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO); + pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT); + + if (pgd) { + memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); + memcpy(pgd + USER_PTRS_PER_PGD, + swapper_pg_dir + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); + } + + return pgd; } static inline void pgd_free(pgd_t *pgd) diff --git a/include/asm-sh/pgtable-2level.h b/include/asm-sh/pgtable-2level.h deleted file mode 100644 index b525db6..0000000 --- a/include/asm-sh/pgtable-2level.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef __ASM_SH_PGTABLE_2LEVEL_H -#define __ASM_SH_PGTABLE_2LEVEL_H - -/* - * traditional two-level paging structure: - */ - -#define PGDIR_SHIFT 22 -#define PTRS_PER_PGD 1024 - -/* - * this is two-level, so we don't really have any - * PMD directory physically. - */ -#define PMD_SHIFT 22 -#define PTRS_PER_PMD 1 - -#define PTRS_PER_PTE 1024 - -#ifndef __ASSEMBLY__ -#define pte_ERROR(e) \ - printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) -#define pmd_ERROR(e) \ - printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) -#define pgd_ERROR(e) \ - printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) - -/* - * The "pgd_xxx()" functions here are trivial for a folded two-level - * setup: the pgd is never bad, and a pmd always exists (as it's folded - * into the pgd entry) - */ -static inline int pgd_none(pgd_t pgd) { return 0; } -static inline int pgd_bad(pgd_t pgd) { return 0; } -static inline int pgd_present(pgd_t pgd) { return 1; } -static inline void pgd_clear (pgd_t * pgdp) { } - -/* - * Certain architectures need to do special things when PTEs - * within a page table are directly modified. Thus, the following - * hook is made available. - */ -#define set_pte(pteptr, pteval) (*(pteptr) = pteval) -#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) - -/* - * (pmds are folded into pgds so this doesn't get actually called, - * but the define is needed for a generic inline function.) - */ -#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) -#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval) - -#define pgd_page_vaddr(pgd) \ -((unsigned long) __va(pgd_val(pgd) & PAGE_MASK)) - -#define pgd_page(pgd) \ - (phys_to_page(pgd_val(pgd))) - -static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) -{ - return (pmd_t *) dir; -} - -#define pte_pfn(x) ((unsigned long)(((x).pte >> PAGE_SHIFT))) -#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) -#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) - -#endif /* !__ASSEMBLY__ */ - -#endif /* __ASM_SH_PGTABLE_2LEVEL_H */ diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index 2c8682a..b1f21e7 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -15,15 +15,10 @@ #define __ASM_SH_PGTABLE_H #include #include -#define PTRS_PER_PGD 1024 - #ifndef __ASSEMBLY__ #include #include -extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; -extern void paging_init(void); - /* * ZERO_PAGE is a global shared page that is always zero: used * for zero-mapped memory areas etc.. @@ -33,15 +28,28 @@ #define ZERO_PAGE(vaddr) (virt_to_page(e #endif /* !__ASSEMBLY__ */ -/* traditional two-level paging structure */ -#define PGDIR_SHIFT 22 -#define PTRS_PER_PMD 1 -#define PTRS_PER_PTE 1024 -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE-1)) +/* + * traditional two-level paging structure + */ +/* PTE bits */ +#ifdef CONFIG_X2TLB +# define PTE_MAGNITUDE 3 /* 64-bit PTEs on extended mode SH-X2 TLB */ +#else +# define PTE_MAGNITUDE 2 /* 32-bit PTEs */ +#endif +#define PTE_SHIFT PAGE_SHIFT +#define PTE_BITS (PTE_SHIFT - PTE_MAGNITUDE) + +/* PGD bits */ +#define PGDIR_SHIFT (PTE_SHIFT + PTE_BITS) +#define PGDIR_BITS (32 - PGDIR_SHIFT) #define PGDIR_SIZE (1UL << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) +/* Entries per level */ +#define PTRS_PER_PTE (1UL << PTE_BITS) +#define PTRS_PER_PGD (1UL << PGDIR_BITS) + #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) #define FIRST_USER_ADDRESS 0 @@ -57,7 +65,8 @@ #define VMALLOC_END (FIXADDR_START-2*PAG /* * Linux PTEL encoding. * - * Hardware and software bit definitions for the PTEL value: + * Hardware and software bit definitions for the PTEL value (see below for + * notes on SH-X2 MMUs and 64-bit PTEs): * * - Bits 0 and 7 are reserved on SH-3 (_PAGE_WT and _PAGE_SZ1 on SH-4). * @@ -76,20 +85,57 @@ #define VMALLOC_END (FIXADDR_START-2*PAG * * - Bits 31, 30, and 29 remain unused by everyone and can be used for future * software flags, although care must be taken to update _PAGE_CLEAR_FLAGS. + * + * XXX: Leave the _PAGE_FILE and _PAGE_WT overhaul for a rainy day. + * + * SH-X2 MMUs and extended PTEs + * + * SH-X2 supports an extended mode TLB with split data arrays due to the + * number of bits needed for PR and SZ (now EPR and ESZ) encodings. The PR and + * SZ bit placeholders still exist in data array 1, but are implemented as + * reserved bits, with the real logic existing in data array 2. + * + * The downside to this is that we can no longer fit everything in to a 32-bit + * PTE encoding, so a 64-bit pte_t is necessary for these parts. On the plus + * side, this gives us quite a few spare bits to play with for future usage. */ +/* Legacy and compat mode bits */ #define _PAGE_WT 0x001 /* WT-bit on SH-4, 0 on SH-3 */ #define _PAGE_HW_SHARED 0x002 /* SH-bit : shared among processes */ #define _PAGE_DIRTY 0x004 /* D-bit : page changed */ #define _PAGE_CACHABLE 0x008 /* C-bit : cachable */ -#define _PAGE_SZ0 0x010 /* SZ0-bit : Size of page */ -#define _PAGE_RW 0x020 /* PR0-bit : write access allowed */ -#define _PAGE_USER 0x040 /* PR1-bit : user space access allowed */ -#define _PAGE_SZ1 0x080 /* SZ1-bit : Size of page (on SH-4) */ +#ifndef CONFIG_X2TLB +# define _PAGE_SZ0 0x010 /* SZ0-bit : Size of page */ +# define _PAGE_RW 0x020 /* PR0-bit : write access allowed */ +# define _PAGE_USER 0x040 /* PR1-bit : user space access allowed*/ +# define _PAGE_SZ1 0x080 /* SZ1-bit : Size of page (on SH-4) */ +#endif #define _PAGE_PRESENT 0x100 /* V-bit : page is valid */ #define _PAGE_PROTNONE 0x200 /* software: if not present */ #define _PAGE_ACCESSED 0x400 /* software: page referenced */ #define _PAGE_FILE _PAGE_WT /* software: pagecache or swap? */ +/* Extended mode bits */ +#define _PAGE_EXT_ESZ0 0x0010 /* ESZ0-bit: Size of page */ +#define _PAGE_EXT_ESZ1 0x0020 /* ESZ1-bit: Size of page */ +#define _PAGE_EXT_ESZ2 0x0040 /* ESZ2-bit: Size of page */ +#define _PAGE_EXT_ESZ3 0x0080 /* ESZ3-bit: Size of page */ + +#define _PAGE_EXT_USER_EXEC 0x0100 /* EPR0-bit: User space executable */ +#define _PAGE_EXT_USER_WRITE 0x0200 /* EPR1-bit: User space writable */ +#define _PAGE_EXT_USER_READ 0x0400 /* EPR2-bit: User space readable */ + +#define _PAGE_EXT_KERN_EXEC 0x0800 /* EPR3-bit: Kernel space executable */ +#define _PAGE_EXT_KERN_WRITE 0x1000 /* EPR4-bit: Kernel space writable */ +#define _PAGE_EXT_KERN_READ 0x2000 /* EPR5-bit: Kernel space readable */ + +/* Wrapper for extended mode pgprot twiddling */ +#ifdef CONFIG_X2TLB +# define _PAGE_EXT(x) ((unsigned long long)(x) << 32) +#else +# define _PAGE_EXT(x) (0) +#endif + /* software: moves to PTEA.TC (Timing Control) */ #define _PAGE_PCC_AREA5 0x00000000 /* use BSC registers for area5 */ #define _PAGE_PCC_AREA6 0x80000000 /* use BSC registers for area6 */ @@ -114,37 +160,152 @@ #endif #define _PAGE_FLAGS_HARDWARE_MASK (0x1fffffff & ~(_PAGE_CLEAR_FLAGS)) -/* Hardware flags: SZ0=1 (4k-byte) */ -#define _PAGE_FLAGS_HARD _PAGE_SZ0 +/* Hardware flags, page size encoding */ +#if defined(CONFIG_X2TLB) +# if defined(CONFIG_PAGE_SIZE_4KB) +# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ0) +# elif defined(CONFIG_PAGE_SIZE_8KB) +# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ1) +# elif defined(CONFIG_PAGE_SIZE_64KB) +# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ2) +# endif +#else +# if defined(CONFIG_PAGE_SIZE_4KB) +# define _PAGE_FLAGS_HARD _PAGE_SZ0 +# elif defined(CONFIG_PAGE_SIZE_64KB) +# define _PAGE_FLAGS_HARD _PAGE_SZ1 +# endif +#endif -#if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) -#define _PAGE_SZHUGE (_PAGE_SZ1) -#elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) -#define _PAGE_SZHUGE (_PAGE_SZ0 | _PAGE_SZ1) +#if defined(CONFIG_X2TLB) +# if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ2) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ0 | _PAGE_EXT_ESZ2) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ0 | _PAGE_EXT_ESZ1 | _PAGE_EXT_ESZ2) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ3) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ2 | _PAGE_EXT_ESZ3) +# endif +#else +# if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) +# define _PAGE_SZHUGE (_PAGE_SZ1) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) +# define _PAGE_SZHUGE (_PAGE_SZ0 | _PAGE_SZ1) +# endif #endif -#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) -#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) -#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY) +#define _PAGE_CHG_MASK \ + (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY) #ifndef __ASSEMBLY__ -#ifdef CONFIG_MMU -#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_FLAGS_HARD) -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_FLAGS_HARD) -#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_FLAGS_HARD) -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_FLAGS_HARD) -#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_CACHABLE | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) +#if defined(CONFIG_X2TLB) /* SH-X2 TLB */ +#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_USER_READ | \ + _PAGE_EXT_USER_WRITE)) + +#define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_USER_EXEC | \ + _PAGE_EXT_USER_READ)) + +#define PAGE_COPY PAGE_EXECREAD + +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_USER_READ)) + +#define PAGE_WRITEONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_USER_WRITE)) + +#define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_USER_WRITE | \ + _PAGE_EXT_USER_READ | \ + _PAGE_EXT_USER_EXEC)) + +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_KERN_EXEC)) + +#define PAGE_KERNEL_NOCACHE \ + __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_HW_SHARED | \ + _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_KERN_EXEC)) + +#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_EXEC)) + +#define PAGE_KERNEL_PCC(slot, type) \ + __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_KERN_EXEC) \ + (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \ + (type)) + +#elif defined(CONFIG_MMU) /* SH-X TLB */ +#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \ + _PAGE_CACHABLE | _PAGE_ACCESSED | \ + _PAGE_FLAGS_HARD) + +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_EXECREAD PAGE_READONLY +#define PAGE_RWX PAGE_SHARED +#define PAGE_WRITEONLY PAGE_SHARED + +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) + #define PAGE_KERNEL_NOCACHE \ - __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) -#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) + __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_HW_SHARED | \ + _PAGE_FLAGS_HARD) + +#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) + #define PAGE_KERNEL_PCC(slot, type) \ - __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_FLAGS_HARD | (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | (type)) + __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD | \ + (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \ + (type)) #else /* no mmu */ #define PAGE_NONE __pgprot(0) #define PAGE_SHARED __pgprot(0) #define PAGE_COPY __pgprot(0) +#define PAGE_EXECREAD __pgprot(0) +#define PAGE_RWX __pgprot(0) #define PAGE_READONLY __pgprot(0) +#define PAGE_WRITEONLY __pgprot(0) #define PAGE_KERNEL __pgprot(0) #define PAGE_KERNEL_NOCACHE __pgprot(0) #define PAGE_KERNEL_RO __pgprot(0) @@ -154,27 +315,32 @@ #endif #endif /* __ASSEMBLY__ */ /* - * As i386 and MIPS, SuperH can't do page protection for execute, and - * considers that the same as a read. Also, write permissions imply - * read permissions. This is the closest we can get.. + * SH-X and lower (legacy) SuperH parts (SH-3, SH-4, some SH-4A) can't do page + * protection for execute, and considers it the same as a read. Also, write + * permission implies read permission. This is the closest we can get.. + * + * SH-X2 (SH7785) and later parts take this to the opposite end of the extreme, + * not only supporting separate execute, read, and write bits, but having + * completely separate permission bits for user and kernel space. */ + /*xwr*/ #define __P000 PAGE_NONE #define __P001 PAGE_READONLY #define __P010 PAGE_COPY #define __P011 PAGE_COPY -#define __P100 PAGE_READONLY -#define __P101 PAGE_READONLY +#define __P100 PAGE_EXECREAD +#define __P101 PAGE_EXECREAD #define __P110 PAGE_COPY #define __P111 PAGE_COPY #define __S000 PAGE_NONE #define __S001 PAGE_READONLY -#define __S010 PAGE_SHARED +#define __S010 PAGE_WRITEONLY #define __S011 PAGE_SHARED -#define __S100 PAGE_READONLY -#define __S101 PAGE_READONLY -#define __S110 PAGE_SHARED -#define __S111 PAGE_SHARED +#define __S100 PAGE_EXECREAD +#define __S101 PAGE_EXECREAD +#define __S110 PAGE_RWX +#define __S111 PAGE_RWX #ifndef __ASSEMBLY__ @@ -183,7 +349,17 @@ #ifndef __ASSEMBLY__ * within a page table are directly modified. Thus, the following * hook is made available. */ +#ifdef CONFIG_X2TLB +static inline void set_pte(pte_t *ptep, pte_t pte) +{ + ptep->pte_high = pte.pte_high; + smp_wmb(); + ptep->pte_low = pte.pte_low; +} +#else #define set_pte(pteptr, pteval) (*(pteptr) = pteval) +#endif + #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) /* @@ -192,18 +368,18 @@ #define set_pte_at(mm,addr,ptep,pteval) */ #define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) -#define pte_pfn(x) ((unsigned long)(((x).pte >> PAGE_SHIFT))) +#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT))) #define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) #define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) #define pte_none(x) (!pte_val(x)) #define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) -#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) +#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) #define pmd_none(x) (!pmd_val(x)) -#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) +#define pmd_present(x) (pmd_val(x)) #define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) -#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) +#define pmd_bad(x) (pmd_val(x) & ~PAGE_MASK) #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) #define pte_page(x) phys_to_page(pte_val(x)&PTE_PHYS_MASK) @@ -212,28 +388,52 @@ #define pte_page(x) phys_to_page(pte_val * The following only work if pte_present() is true. * Undefined behaviour if not.. */ -static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } -static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } -static inline int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; } -static inline int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; } -static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } -static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_RW; } -static inline int pte_not_present(pte_t pte){ return !(pte_val(pte) & _PAGE_PRESENT); } - -static inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; } -static inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; } -static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; } -static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; } -static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; } -static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; } -static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; } -static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; } -static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; } -static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; } -#ifdef CONFIG_HUGETLB_PAGE -static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; } +#define pte_not_present(pte) (!(pte_val(pte) & _PAGE_PRESENT)) +#define pte_dirty(pte) (pte_val(pte) & _PAGE_DIRTY) +#define pte_young(pte) (pte_val(pte) & _PAGE_ACCESSED) +#define pte_file(pte) (pte_val(pte) & _PAGE_FILE) + +#ifdef CONFIG_X2TLB +#define pte_read(pte) ((pte).pte_high & _PAGE_EXT_USER_READ) +#define pte_exec(pte) ((pte).pte_high & _PAGE_EXT_USER_EXEC) +#define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE) +#else +#define pte_read(pte) (pte_val(pte) & _PAGE_USER) +#define pte_exec(pte) (pte_val(pte) & _PAGE_USER) +#define pte_write(pte) (pte_val(pte) & _PAGE_RW) +#endif + +#define PTE_BIT_FUNC(h,fn,op) \ +static inline pte_t pte_##fn(pte_t pte) { pte.pte_##h op; return pte; } + +#ifdef CONFIG_X2TLB +/* + * We cheat a bit in the SH-X2 TLB case. As the permission bits are + * individually toggled (and user permissions are entirely decoupled from + * kernel permissions), we attempt to couple them a bit more sanely here. + */ +PTE_BIT_FUNC(high, rdprotect, &= ~_PAGE_EXT_USER_READ); +PTE_BIT_FUNC(high, mkread, |= _PAGE_EXT_USER_READ | _PAGE_EXT_KERN_READ); +PTE_BIT_FUNC(high, wrprotect, &= ~_PAGE_EXT_USER_WRITE); +PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE); +PTE_BIT_FUNC(high, exprotect, &= ~_PAGE_EXT_USER_EXEC); +PTE_BIT_FUNC(high, mkexec, |= _PAGE_EXT_USER_EXEC | _PAGE_EXT_KERN_EXEC); +PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE); +#else +PTE_BIT_FUNC(low, rdprotect, &= ~_PAGE_USER); +PTE_BIT_FUNC(low, mkread, |= _PAGE_USER); +PTE_BIT_FUNC(low, wrprotect, &= ~_PAGE_RW); +PTE_BIT_FUNC(low, mkwrite, |= _PAGE_RW); +PTE_BIT_FUNC(low, exprotect, &= ~_PAGE_USER); +PTE_BIT_FUNC(low, mkexec, |= _PAGE_USER); +PTE_BIT_FUNC(low, mkhuge, |= _PAGE_SZHUGE); #endif +PTE_BIT_FUNC(low, mkclean, &= ~_PAGE_DIRTY); +PTE_BIT_FUNC(low, mkdirty, |= _PAGE_DIRTY); +PTE_BIT_FUNC(low, mkold, &= ~_PAGE_ACCESSED); +PTE_BIT_FUNC(low, mkyoung, |= _PAGE_ACCESSED); + /* * Macro and implementation to make a page protection as uncachable. */ @@ -258,13 +458,14 @@ #define pgprot_writecombine(prot) __pgpr #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -{ set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; } - -#define pmd_page_vaddr(pmd) \ -((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) +{ + set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | + pgprot_val(newprot))); + return pte; +} -#define pmd_page(pmd) \ - (phys_to_page(pmd_val(pmd))) +#define pmd_page_vaddr(pmd) pmd_val(pmd) +#define pmd_page(pmd) (virt_to_page(pmd_val(pmd))) /* to find an entry in a page-table-directory. */ #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) @@ -283,8 +484,15 @@ #define pte_offset_map_nested(dir, addre #define pte_unmap(pte) do { } while (0) #define pte_unmap_nested(pte) do { } while (0) +#ifdef CONFIG_X2TLB +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %p(%08lx%08lx).\n", __FILE__, __LINE__, \ + &(e), (e).pte_high, (e).pte_low) +#else #define pte_ERROR(e) \ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) +#endif + #define pgd_ERROR(e) \ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) @@ -337,6 +545,9 @@ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); #endif +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; +extern void paging_init(void); + #include #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h index 45bb74e..4a90e7c 100644 --- a/include/asm-sh/processor.h +++ b/include/asm-sh/processor.h @@ -36,7 +36,10 @@ #define CCN_PRR 0xff000044 */ enum cpu_type { /* SH-2 types */ - CPU_SH7604, + CPU_SH7604, CPU_SH7619, + + /* SH-2A types */ + CPU_SH7206, /* SH-3 types */ CPU_SH7705, CPU_SH7706, CPU_SH7707, @@ -47,7 +50,10 @@ enum cpu_type { /* SH-4 types */ CPU_SH7750, CPU_SH7750S, CPU_SH7750R, CPU_SH7751, CPU_SH7751R, CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501, + + /* SH-4A types */ CPU_SH73180, CPU_SH7343, CPU_SH7770, CPU_SH7780, CPU_SH7781, + CPU_SH7785, /* Unknown subtype */ CPU_SH_NONE @@ -130,12 +136,11 @@ union sh_fpu_union { }; struct thread_struct { + /* Saved registers when thread is descheduled */ unsigned long sp; unsigned long pc; - unsigned long trap_no, error_code; - unsigned long address; - /* Hardware debugging registers may come here */ + /* Hardware debugging registers */ unsigned long ubc_pc; /* floating point info */ @@ -150,12 +155,7 @@ typedef struct { extern int ubc_usercnt; #define INIT_THREAD { \ - sizeof(init_stack) + (long) &init_stack, /* sp */ \ - 0, /* pc */ \ - 0, 0, \ - 0, \ - 0, \ - {{{0,}},} /* fpu state */ \ + .sp = sizeof(init_stack) + (long) &init_stack, \ } /* diff --git a/include/asm-sh/se7206.h b/include/asm-sh/se7206.h new file mode 100644 index 0000000..698eb80 --- /dev/null +++ b/include/asm-sh/se7206.h @@ -0,0 +1,13 @@ +#ifndef __ASM_SH_SE7206_H +#define __ASM_SH_SE7206_H + +#define PA_SMSC 0x30000000 +#define PA_MRSHPC 0x34000000 +#define PA_LED 0x31400000 + +void init_se7206_IRQ(void); + +#define __IO_PREFIX se7206 +#include + +#endif /* __ASM_SH_SE7206_H */ diff --git a/include/asm-sh/timer.h b/include/asm-sh/timer.h index 5df842b..5a014bc 100644 --- a/include/asm-sh/timer.h +++ b/include/asm-sh/timer.h @@ -22,7 +22,7 @@ struct sys_timer { #define TICK_SIZE (tick_nsec / 1000) -extern struct sys_timer tmu_timer; +extern struct sys_timer tmu_timer, cmt_timer, mtu2_timer; extern struct sys_timer *sys_timer; #ifndef CONFIG_GENERIC_TIME diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h index 1c2abde..0cae1d2 100644 --- a/include/asm-sh/unistd.h +++ b/include/asm-sh/unistd.h @@ -349,12 +349,30 @@ do { \ return (type) (res); \ } while (0) +#if defined(__sh2__) || defined(__SH2E__) || defined(__SH2A__) +#define SYSCALL_ARG0 "trapa #0x20" +#define SYSCALL_ARG1 "trapa #0x21" +#define SYSCALL_ARG2 "trapa #0x22" +#define SYSCALL_ARG3 "trapa #0x23" +#define SYSCALL_ARG4 "trapa #0x24" +#define SYSCALL_ARG5 "trapa #0x25" +#define SYSCALL_ARG6 "trapa #0x26" +#else +#define SYSCALL_ARG0 "trapa #0x10" +#define SYSCALL_ARG1 "trapa #0x11" +#define SYSCALL_ARG2 "trapa #0x12" +#define SYSCALL_ARG3 "trapa #0x13" +#define SYSCALL_ARG4 "trapa #0x14" +#define SYSCALL_ARG5 "trapa #0x15" +#define SYSCALL_ARG6 "trapa #0x16" +#endif + /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ #define _syscall0(type,name) \ type name(void) \ { \ register long __sc0 __asm__ ("r3") = __NR_##name; \ -__asm__ __volatile__ ("trapa #0x10" \ +__asm__ __volatile__ (SYSCALL_ARG0 \ : "=z" (__sc0) \ : "0" (__sc0) \ : "memory" ); \ @@ -366,7 +384,7 @@ type name(type1 arg1) \ { \ register long __sc0 __asm__ ("r3") = __NR_##name; \ register long __sc4 __asm__ ("r4") = (long) arg1; \ -__asm__ __volatile__ ("trapa #0x11" \ +__asm__ __volatile__ (SYSCALL_ARG1 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4) \ : "memory"); \ @@ -379,7 +397,7 @@ type name(type1 arg1,type2 arg2) \ register long __sc0 __asm__ ("r3") = __NR_##name; \ register long __sc4 __asm__ ("r4") = (long) arg1; \ register long __sc5 __asm__ ("r5") = (long) arg2; \ -__asm__ __volatile__ ("trapa #0x12" \ +__asm__ __volatile__ (SYSCALL_ARG2 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5) \ : "memory"); \ @@ -393,7 +411,7 @@ register long __sc0 __asm__ ("r3") = __N register long __sc4 __asm__ ("r4") = (long) arg1; \ register long __sc5 __asm__ ("r5") = (long) arg2; \ register long __sc6 __asm__ ("r6") = (long) arg3; \ -__asm__ __volatile__ ("trapa #0x13" \ +__asm__ __volatile__ (SYSCALL_ARG3 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) \ : "memory"); \ @@ -408,7 +426,7 @@ register long __sc4 __asm__ ("r4") = (lo register long __sc5 __asm__ ("r5") = (long) arg2; \ register long __sc6 __asm__ ("r6") = (long) arg3; \ register long __sc7 __asm__ ("r7") = (long) arg4; \ -__asm__ __volatile__ ("trapa #0x14" \ +__asm__ __volatile__ (SYSCALL_ARG4 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), \ "r" (__sc7) \ @@ -425,7 +443,7 @@ register long __sc5 __asm__ ("r5") = (lo register long __sc6 __asm__ ("r6") = (long) arg3; \ register long __sc7 __asm__ ("r7") = (long) arg4; \ register long __sc0 __asm__ ("r0") = (long) arg5; \ -__asm__ __volatile__ ("trapa #0x15" \ +__asm__ __volatile__ (SYSCALL_ARG5 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7), \ "r" (__sc3) \ @@ -443,7 +461,7 @@ register long __sc6 __asm__ ("r6") = (lo register long __sc7 __asm__ ("r7") = (long) arg4; \ register long __sc0 __asm__ ("r0") = (long) arg5; \ register long __sc1 __asm__ ("r1") = (long) arg6; \ -__asm__ __volatile__ ("trapa #0x16" \ +__asm__ __volatile__ (SYSCALL_ARG6 \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7), \ "r" (__sc3), "r" (__sc1) \