aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/sh/Kconfig7
-rw-r--r--arch/sh/Kconfig.debug22
-rw-r--r--arch/sh/Makefile25
-rw-r--r--arch/sh/boards/Kconfig7
-rw-r--r--arch/sh/boards/mach-highlander/setup.c7
-rw-r--r--arch/sh/boards/mach-kfr2r09/Makefile2
-rw-r--r--arch/sh/boards/mach-kfr2r09/lcd_wqvga.c332
-rw-r--r--arch/sh/boards/mach-kfr2r09/setup.c270
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c55
-rw-r--r--arch/sh/boards/mach-x3proto/setup.c7
-rw-r--r--arch/sh/boot/.gitignore5
-rw-r--r--arch/sh/boot/Makefile48
-rw-r--r--arch/sh/boot/compressed/.gitignore1
-rw-r--r--arch/sh/boot/compressed/Makefile21
-rw-r--r--arch/sh/boot/compressed/misc.c149
-rw-r--r--arch/sh/boot/compressed/misc_32.c206
-rw-r--r--arch/sh/boot/compressed/misc_64.c210
-rw-r--r--arch/sh/boot/compressed/piggy.S8
-rw-r--r--arch/sh/boot/compressed/vmlinux.scr10
-rw-r--r--arch/sh/boot/romimage/Makefile19
-rw-r--r--arch/sh/boot/romimage/head.S10
-rw-r--r--arch/sh/boot/romimage/vmlinux.scr6
-rw-r--r--arch/sh/configs/kfr2r09_defconfig877
-rw-r--r--arch/sh/include/asm/dma-sh.h1
-rw-r--r--arch/sh/include/asm/dwarf.h402
-rw-r--r--arch/sh/include/asm/entry-macros.S84
-rw-r--r--arch/sh/include/asm/ftrace.h7
-rw-r--r--arch/sh/include/asm/hardirq.h13
-rw-r--r--arch/sh/include/asm/hwblk.h70
-rw-r--r--arch/sh/include/asm/lmb.h6
-rw-r--r--arch/sh/include/asm/pgtable_32.h14
-rw-r--r--arch/sh/include/asm/sections.h1
-rw-r--r--arch/sh/include/asm/stacktrace.h25
-rw-r--r--arch/sh/include/asm/suspend.h9
-rw-r--r--arch/sh/include/asm/syscall_32.h1
-rw-r--r--arch/sh/include/asm/thread_info.h11
-rw-r--r--arch/sh/include/asm/unwinder.h25
-rw-r--r--arch/sh/include/asm/vmlinux.lds.h17
-rw-r--r--arch/sh/include/cpu-sh4/cpu/dma-sh4a.h3
-rw-r--r--arch/sh/include/cpu-sh4/cpu/sh7722.h14
-rw-r--r--arch/sh/include/cpu-sh4/cpu/sh7723.h17
-rw-r--r--arch/sh/include/cpu-sh4/cpu/sh7724.h17
-rw-r--r--arch/sh/include/mach-common/mach/migor.h64
-rw-r--r--arch/sh/include/mach-common/mach/romimage.h1
-rw-r--r--arch/sh/include/mach-kfr2r09/mach/kfr2r09.h21
-rw-r--r--arch/sh/include/mach-kfr2r09/mach/partner-jet-setup.txt134
-rw-r--r--arch/sh/include/mach-kfr2r09/mach/romimage.h75
-rw-r--r--arch/sh/include/mach-migor/mach/migor.h14
-rw-r--r--arch/sh/kernel/Makefile_329
-rw-r--r--arch/sh/kernel/Makefile_643
-rw-r--r--arch/sh/kernel/asm-offsets.c1
-rw-r--r--arch/sh/kernel/cpu/Makefile2
-rw-r--r--arch/sh/kernel/cpu/hwblk.c155
-rw-r--r--arch/sh/kernel/cpu/init.c34
-rw-r--r--arch/sh/kernel/cpu/sh2/entry.S3
-rw-r--r--arch/sh/kernel/cpu/sh2a/entry.S3
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S1
-rw-r--r--arch/sh/kernel/cpu/sh4a/Makefile6
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7722.c63
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7723.c113
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7724.c122
-rw-r--r--arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c106
-rw-r--r--arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c117
-rw-r--r--arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c121
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7366.c2
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c8
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7723.c2
-rw-r--r--arch/sh/kernel/cpu/shmobile/Makefile1
-rw-r--r--arch/sh/kernel/cpu/shmobile/cpuidle.c102
-rw-r--r--arch/sh/kernel/cpu/shmobile/pm.c26
-rw-r--r--arch/sh/kernel/dumpstack.c123
-rw-r--r--arch/sh/kernel/dwarf.c902
-rw-r--r--arch/sh/kernel/early_printk.c5
-rw-r--r--arch/sh/kernel/entry-common.S89
-rw-r--r--arch/sh/kernel/ftrace.c190
-rw-r--r--arch/sh/kernel/io_trapped.c7
-rw-r--r--arch/sh/kernel/irq.c21
-rw-r--r--arch/sh/kernel/process_32.c5
-rw-r--r--arch/sh/kernel/ptrace_32.c8
-rw-r--r--arch/sh/kernel/setup.c71
-rw-r--r--arch/sh/kernel/sh_ksyms_32.c4
-rw-r--r--arch/sh/kernel/stacktrace.c98
-rw-r--r--arch/sh/kernel/time.c29
-rw-r--r--arch/sh/kernel/traps_32.c24
-rw-r--r--arch/sh/kernel/unwinder.c162
-rw-r--r--arch/sh/kernel/vmlinux.lds.S90
-rw-r--r--arch/sh/lib/Makefile2
-rw-r--r--arch/sh/lib/mcount.S228
-rw-r--r--arch/sh/mm/fault_32.c164
-rw-r--r--arch/sh/mm/ioremap_64.c6
-rw-r--r--arch/sh/mm/numa.c36
-rw-r--r--arch/sh/oprofile/backtrace.c84
-rw-r--r--arch/sh/tools/mach-types1
93 files changed, 5613 insertions, 1086 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index e2bdd7b94fd..c4a955d2545 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -10,12 +10,16 @@ config SUPERH
select EMBEDDED
select HAVE_CLK
select HAVE_IDE
+ select HAVE_LMB
select HAVE_OPROFILE
select HAVE_GENERIC_DMA_COHERENT
select HAVE_IOREMAP_PROT if MMU
select HAVE_ARCH_TRACEHOOK
select HAVE_DMA_API_DEBUG
select HAVE_PERF_COUNTERS
+ select HAVE_KERNEL_GZIP
+ select HAVE_KERNEL_BZIP2
+ select HAVE_KERNEL_LZMA
select RTC_LIB
select GENERIC_ATOMIC64
help
@@ -31,6 +35,9 @@ config SUPERH32
select HAVE_FUNCTION_TRACER
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_DYNAMIC_FTRACE
+ select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+ select HAVE_FTRACE_SYSCALLS
+ select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_ARCH_KGDB
select ARCH_HIBERNATION_POSSIBLE if MMU
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 39224b57c6e..741d20fab2e 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -38,11 +38,12 @@ config EARLY_SCIF_CONSOLE_PORT
default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \
CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 || \
CPU_SUBTYPE_SH7343
- default "0xffea0000" if CPU_SUBTYPE_SH7785
+ default "0xffeb0000" if CPU_SUBTYPE_SH7785
default "0xffeb0000" if CPU_SUBTYPE_SH7786
default "0xfffe8000" if CPU_SUBTYPE_SH7203
default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
default "0xffe80000" if CPU_SH4
+ default "0xa4000150" if CPU_SH3
default "0x00000000"
config EARLY_PRINTK
@@ -61,12 +62,14 @@ config EARLY_PRINTK
select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
the kernel command line option to toggle back and forth.
-config DEBUG_STACKOVERFLOW
+config STACK_DEBUG
bool "Check for stack overflows"
depends on DEBUG_KERNEL && SUPERH32
help
This option will cause messages to be printed if free stack space
- drops below a certain limit.
+ drops below a certain limit. Saying Y here will add overhead to
+ every function call and will therefore incur a major
+ performance hit. Most users should say N.
config DEBUG_STACK_USAGE
bool "Stack utilization instrumentation"
@@ -107,6 +110,14 @@ config DUMP_CODE
Those looking for more verbose debugging output should say Y.
+config DWARF_UNWINDER
+ bool "Enable the DWARF unwinder for stacktraces"
+ select FRAME_POINTER
+ default n
+ help
+ Enabling this option will make stacktraces more accurate, at
+ the cost of an increase in overall kernel size.
+
config SH_NO_BSS_INIT
bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)"
depends on DEBUG_KERNEL
@@ -123,4 +134,9 @@ config SH64_SR_WATCH
bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
depends on SUPERH64
+config MCOUNT
+ def_bool y
+ depends on SUPERH32
+ depends on STACK_DEBUG || FUNCTION_TRACER
+
endmenu
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 75d049b03f7..e26421bf997 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -136,6 +136,7 @@ machdir-$(CONFIG_SH_7751_SYSTEMH) += mach-systemh
machdir-$(CONFIG_SH_EDOSK7705) += mach-edosk7705
machdir-$(CONFIG_SH_HIGHLANDER) += mach-highlander
machdir-$(CONFIG_SH_MIGOR) += mach-migor
+machdir-$(CONFIG_SH_KFR2R09) += mach-kfr2r09
machdir-$(CONFIG_SH_SDK7780) += mach-sdk7780
machdir-$(CONFIG_SH_X3PROTO) += mach-x3proto
machdir-$(CONFIG_SH_SH7763RDP) += mach-sh7763rdp
@@ -186,17 +187,27 @@ KBUILD_CFLAGS += -pipe $(cflags-y)
KBUILD_CPPFLAGS += $(cflags-y)
KBUILD_AFLAGS += $(cflags-y)
+ifeq ($(CONFIG_MCOUNT),y)
+ KBUILD_CFLAGS += -pg
+endif
+
+ifeq ($(CONFIG_DWARF_UNWINDER),y)
+ KBUILD_CFLAGS += -fasynchronous-unwind-tables
+endif
+
libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y)
libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y)
-PHONY += maketools FORCE
+BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.srec \
+ zImage vmlinux.srec romImage
+PHONY += maketools $(BOOT_TARGETS) FORCE
maketools: include/linux/version.h FORCE
$(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h
all: $(KBUILD_IMAGE)
-zImage uImage uImage.srec vmlinux.srec: vmlinux
+$(BOOT_TARGETS): vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
compressed: zImage
@@ -208,10 +219,14 @@ archclean:
$(Q)$(MAKE) $(clean)=arch/sh/kernel/vsyscall
define archhelp
- @echo '* zImage - Compressed kernel image'
+ @echo ' zImage - Compressed kernel image'
+ @echo ' romImage - Compressed ROM image, if supported'
@echo ' vmlinux.srec - Create an ELF S-record'
- @echo ' uImage - Create a bootable image for U-Boot'
- @echo ' uImage.srec - Create an S-record for U-Boot'
+ @echo '* uImage - Alias to bootable U-Boot image'
+ @echo ' uImage.srec - Create an S-record for U-Boot'
+ @echo '* uImage.gz - Kernel-only image for U-Boot (gzip)'
+ @echo ' uImage.bz2 - Kernel-only image for U-Boot (bzip2)'
+ @echo ' uImage.lzma - Kernel-only image for U-Boot (lzma)'
endef
CLEAN_FILES += include/asm-sh/machtypes.h
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index 2b1af0eefa6..db04c85971a 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -193,6 +193,13 @@ config SH_AP325RXA
Renesas "AP-325RXA" support.
Compatible with ALGO SYSTEM CO.,LTD. "AP-320A"
+config SH_KFR2R09
+ bool "KFR2R09"
+ depends on CPU_SUBTYPE_SH7724
+ select ARCH_REQUIRE_GPIOLIB
+ help
+ "Kit For R2R for 2009" support.
+
config SH_SH7763RDP
bool "SH7763RDP"
depends on CPU_SUBTYPE_SH7763
diff --git a/arch/sh/boards/mach-highlander/setup.c b/arch/sh/boards/mach-highlander/setup.c
index 1639f891500..566e69d8d72 100644
--- a/arch/sh/boards/mach-highlander/setup.c
+++ b/arch/sh/boards/mach-highlander/setup.c
@@ -22,6 +22,7 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/usb/r8a66597.h>
+#include <linux/usb/m66592.h>
#include <net/ax88796.h>
#include <asm/machvec.h>
#include <mach/highlander.h>
@@ -60,6 +61,11 @@ static struct platform_device r8a66597_usb_host_device = {
.resource = r8a66597_usb_host_resources,
};
+static struct m66592_platdata usbf_platdata = {
+ .xtal = M66592_PLATDATA_XTAL_24MHZ,
+ .vif = 1,
+};
+
static struct resource m66592_usb_peripheral_resources[] = {
[0] = {
.name = "m66592_udc",
@@ -81,6 +87,7 @@ static struct platform_device m66592_usb_peripheral_device = {
.dev = {
.dma_mask = NULL, /* don't use dma */
.coherent_dma_mask = 0xffffffff,
+ .platform_data = &usbf_platdata,
},
.num_resources = ARRAY_SIZE(m66592_usb_peripheral_resources),
.resource = m66592_usb_peripheral_resources,
diff --git a/arch/sh/boards/mach-kfr2r09/Makefile b/arch/sh/boards/mach-kfr2r09/Makefile
new file mode 100644
index 00000000000..5d5867826e3
--- /dev/null
+++ b/arch/sh/boards/mach-kfr2r09/Makefile
@@ -0,0 +1,2 @@
+obj-y := setup.o
+obj-$(CONFIG_FB_SH_MOBILE_LCDC) += lcd_wqvga.o
diff --git a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
new file mode 100644
index 00000000000..8ccb1cc8b58
--- /dev/null
+++ b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
@@ -0,0 +1,332 @@
+/*
+ * KFR2R09 LCD panel support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * Register settings based on the out-of-tree t33fb.c driver
+ * Copyright (C) 2008 Lineo Solutions, 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 <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <video/sh_mobile_lcdc.h>
+#include <mach/kfr2r09.h>
+#include <cpu/sh7724.h>
+
+/* The on-board LCD module is a Hitachi TX07D34VM0AAA. This module is made
+ * up of a 240x400 LCD hooked up to a R61517 driver IC. The driver IC is
+ * communicating with the main port of the LCDC using an 18-bit SYS interface.
+ *
+ * The device code for this LCD module is 0x01221517.
+ */
+
+static const unsigned char data_frame_if[] = {
+ 0x02, /* WEMODE: 1=cont, 0=one-shot */
+ 0x00, 0x00,
+ 0x00, /* EPF, DFM */
+ 0x02, /* RIM[1] : 1 (18bpp) */
+};
+
+static const unsigned char data_panel[] = {
+ 0x0b,
+ 0x63, /* 400 lines */
+ 0x04, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00,
+};
+
+static const unsigned char data_timing[] = {
+ 0x00, 0x00, 0x13, 0x08, 0x08,
+};
+
+static const unsigned char data_timing_src[] = {
+ 0x11, 0x01, 0x00, 0x01,
+};
+
+static const unsigned char data_gamma[] = {
+ 0x01, 0x02, 0x08, 0x23, 0x03, 0x0c, 0x00, 0x06, 0x00, 0x00,
+ 0x01, 0x00, 0x0c, 0x23, 0x03, 0x08, 0x02, 0x06, 0x00, 0x00,
+};
+
+static const unsigned char data_power[] = {
+ 0x07, 0xc5, 0xdc, 0x02, 0x33, 0x0a,
+};
+
+static unsigned long read_reg(void *sohandle,
+ struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+ return so->read_data(sohandle);
+}
+
+static void write_reg(void *sohandle,
+ struct sh_mobile_lcdc_sys_bus_ops *so,
+ int i, unsigned long v)
+{
+ if (i)
+ so->write_data(sohandle, v); /* PTH4/LCDRS High [param, 17:0] */
+ else
+ so->write_index(sohandle, v); /* PTH4/LCDRS Low [cmd, 7:0] */
+}
+
+static void write_data(void *sohandle,
+ struct sh_mobile_lcdc_sys_bus_ops *so,
+ unsigned char const *data, int no_data)
+{
+ int i;
+
+ for (i = 0; i < no_data; i++)
+ write_reg(sohandle, so, 1, data[i]);
+}
+
+static unsigned long read_device_code(void *sohandle,
+ struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+ unsigned long device_code;
+
+ /* access protect OFF */
+ write_reg(sohandle, so, 0, 0xb0);
+ write_reg(sohandle, so, 1, 0x00);
+
+ /* deep standby OFF */
+ write_reg(sohandle, so, 0, 0xb1);
+ write_reg(sohandle, so, 1, 0x00);
+
+ /* device code command */
+ write_reg(sohandle, so, 0, 0xbf);
+ mdelay(50);
+
+ /* dummy read */
+ read_reg(sohandle, so);
+
+ /* read device code */
+ device_code = ((read_reg(sohandle, so) & 0xff) << 24);
+ device_code |= ((read_reg(sohandle, so) & 0xff) << 16);
+ device_code |= ((read_reg(sohandle, so) & 0xff) << 8);
+ device_code |= (read_reg(sohandle, so) & 0xff);
+
+ return device_code;
+}
+
+static void write_memory_start(void *sohandle,
+ struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+ write_reg(sohandle, so, 0, 0x2c);
+}
+
+static void clear_memory(void *sohandle,
+ struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+ int i;
+
+ /* write start */
+ write_memory_start(sohandle, so);
+
+ /* paint it black */
+ for (i = 0; i < (240 * 400); i++)
+ write_reg(sohandle, so, 1, 0x00);
+}
+
+static void display_on(void *sohandle,
+ struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+ /* access protect off */
+ write_reg(sohandle, so, 0, 0xb0);
+ write_reg(sohandle, so, 1, 0x00);
+
+ /* exit deep standby mode */
+ write_reg(sohandle, so, 0, 0xb1);
+ write_reg(sohandle, so, 1, 0x00);
+
+ /* frame memory I/F */
+ write_reg(sohandle, so, 0, 0xb3);
+ write_data(sohandle, so, data_frame_if, ARRAY_SIZE(data_frame_if));
+
+ /* display mode and frame memory write mode */
+ write_reg(sohandle, so, 0, 0xb4);
+ write_reg(sohandle, so, 1, 0x00); /* DBI, internal clock */
+
+ /* panel */
+ write_reg(sohandle, so, 0, 0xc0);
+ write_data(sohandle, so, data_panel, ARRAY_SIZE(data_panel));
+
+ /* timing (normal) */
+ write_reg(sohandle, so, 0, 0xc1);
+ write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
+
+ /* timing (partial) */
+ write_reg(sohandle, so, 0, 0xc2);
+ write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
+
+ /* timing (idle) */
+ write_reg(sohandle, so, 0, 0xc3);
+ write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));
+
+ /* timing (source/VCOM/gate driving) */
+ write_reg(sohandle, so, 0, 0xc4);
+ write_data(sohandle, so, data_timing_src, ARRAY_SIZE(data_timing_src));
+
+ /* gamma (red) */
+ write_reg(sohandle, so, 0, 0xc8);
+ write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
+
+ /* gamma (green) */
+ write_reg(sohandle, so, 0, 0xc9);
+ write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
+
+ /* gamma (blue) */
+ write_reg(sohandle, so, 0, 0xca);
+ write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));
+
+ /* power (common) */
+ write_reg(sohandle, so, 0, 0xd0);
+ write_data(sohandle, so, data_power, ARRAY_SIZE(data_power));
+
+ /* VCOM */
+ write_reg(sohandle, so, 0, 0xd1);
+ write_reg(sohandle, so, 1, 0x00);
+ write_reg(sohandle, so, 1, 0x0f);
+ write_reg(sohandle, so, 1, 0x02);
+
+ /* power (normal) */
+ write_reg(sohandle, so, 0, 0xd2);
+ write_reg(sohandle, so, 1, 0x63);
+ write_reg(sohandle, so, 1, 0x24);
+
+ /* power (partial) */
+ write_reg(sohandle, so, 0, 0xd3);
+ write_reg(sohandle, so, 1, 0x63);
+ write_reg(sohandle, so, 1, 0x24);
+
+ /* power (idle) */
+ write_reg(sohandle, so, 0, 0xd4);
+ write_reg(sohandle, so, 1, 0x63);
+ write_reg(sohandle, so, 1, 0x24);
+
+ write_reg(sohandle, so, 0, 0xd8);
+ write_reg(sohandle, so, 1, 0x77);
+ write_reg(sohandle, so, 1, 0x77);
+
+ /* TE signal */
+ write_reg(sohandle, so, 0, 0x35);
+ write_reg(sohandle, so, 1, 0x00);
+
+ /* TE signal line */
+ write_reg(sohandle, so, 0, 0x44);
+ write_reg(sohandle, so, 1, 0x00);
+ write_reg(sohandle, so, 1, 0x00);
+
+ /* column address */
+ write_reg(sohandle, so, 0, 0x2a);
+ write_reg(sohandle, so, 1, 0x00);
+ write_reg(sohandle, so, 1, 0x00);
+ write_reg(sohandle, so, 1, 0x00);
+ write_reg(sohandle, so, 1, 0xef);
+
+ /* page address */
+ write_reg(sohandle, so, 0, 0x2b);
+ write_reg(sohandle, so, 1, 0x00);
+ write_reg(sohandle, so, 1, 0x00);
+ write_reg(sohandle, so, 1, 0x01);
+ write_reg(sohandle, so, 1, 0x8f);
+
+ /* exit sleep mode */
+ write_reg(sohandle, so, 0, 0x11);
+
+ mdelay(120);
+
+ /* clear vram */
+ clear_memory(sohandle, so);
+
+ /* display ON */
+ write_reg(sohandle, so, 0, 0x29);
+ mdelay(1);
+
+ write_memory_start(sohandle, so);
+}
+
+int kfr2r09_lcd_setup(void *board_data, void *sohandle,
+ struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+ /* power on */
+ gpio_set_value(GPIO_PTF4, 0); /* PROTECT/ -> L */
+ gpio_set_value(GPIO_PTE4, 0); /* LCD_RST/ -> L */
+ gpio_set_value(GPIO_PTF4, 1); /* PROTECT/ -> H */
+ udelay(1100);
+ gpio_set_value(GPIO_PTE4, 1); /* LCD_RST/ -> H */
+ udelay(10);
+ gpio_set_value(GPIO_PTF4, 0); /* PROTECT/ -> L */
+ mdelay(20);
+
+ if (read_device_code(sohandle, so) != 0x01221517)
+ return -ENODEV;
+
+ pr_info("KFR2R09 WQVGA LCD Module detected.\n");
+
+ display_on(sohandle, so);
+ return 0;
+}
+
+#define CTRL_CKSW 0x10
+#define CTRL_C10 0x20
+#define CTRL_CPSW 0x80
+#define MAIN_MLED4 0x40
+#define MAIN_MSW 0x80
+
+static int kfr2r09_lcd_backlight(int on)
+{
+ struct i2c_adapter *a;
+ struct i2c_msg msg;
+ unsigned char buf[2];
+ int ret;
+
+ a = i2c_get_adapter(0);
+ if (!a)
+ return -ENODEV;
+
+ buf[0] = 0x00;
+ if (on)
+ buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW;
+ else
+ buf[1] = 0;
+
+ msg.addr = 0x75;
+ msg.buf = buf;
+ msg.len = 2;
+ msg.flags = 0;
+ ret = i2c_transfer(a, &msg, 1);
+ if (ret != 1)
+ return -ENODEV;
+
+ buf[0] = 0x01;
+ if (on)
+ buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c;
+ else
+ buf[1] = 0;
+
+ msg.addr = 0x75;
+ msg.buf = buf;
+ msg.len = 2;
+ msg.flags = 0;
+ ret = i2c_transfer(a, &msg, 1);
+ if (ret != 1)
+ return -ENODEV;
+
+ return 0;
+}
+
+void kfr2r09_lcd_on(void *board_data)
+{
+ kfr2r09_lcd_backlight(1);
+}
+
+void kfr2r09_lcd_off(void *board_data)
+{
+ kfr2r09_lcd_backlight(0);
+}
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
new file mode 100644
index 00000000000..bdb10c29ef1
--- /dev/null
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -0,0 +1,270 @@
+/*
+ * KFR2R09 board support code
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/onenand.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <video/sh_mobile_lcdc.h>
+#include <asm/clock.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/sh_keysc.h>
+#include <cpu/sh7724.h>
+#include <mach/kfr2r09.h>
+
+static struct mtd_partition kfr2r09_nor_flash_partitions[] =
+{
+ {
+ .name = "boot",
+ .offset = 0,
+ .size = (4 * 1024 * 1024),
+ .mask_flags = MTD_WRITEABLE, /* Read-only */
+ },
+ {
+ .name = "other",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct physmap_flash_data kfr2r09_nor_flash_data = {
+ .width = 2,
+ .parts = kfr2r09_nor_flash_partitions,
+ .nr_parts = ARRAY_SIZE(kfr2r09_nor_flash_partitions),
+};
+
+static struct resource kfr2r09_nor_flash_resources[] = {
+ [0] = {
+ .name = "NOR Flash",
+ .start = 0x00000000,
+ .end = 0x03ffffff,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device kfr2r09_nor_flash_device = {
+ .name = "physmap-flash",
+ .resource = kfr2r09_nor_flash_resources,
+ .num_resources = ARRAY_SIZE(kfr2r09_nor_flash_resources),
+ .dev = {
+ .platform_data = &kfr2r09_nor_flash_data,
+ },
+};
+
+static struct resource kfr2r09_nand_flash_resources[] = {
+ [0] = {
+ .name = "NAND Flash",
+ .start = 0x10000000,
+ .end = 0x1001ffff,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device kfr2r09_nand_flash_device = {
+ .name = "onenand-flash",
+ .resource = kfr2r09_nand_flash_resources,
+ .num_resources = ARRAY_SIZE(kfr2r09_nand_flash_resources),
+};
+
+static struct sh_keysc_info kfr2r09_sh_keysc_info = {
+ .mode = SH_KEYSC_MODE_1, /* KEYOUT0->4, KEYIN0->4 */
+ .scan_timing = 3,
+ .delay = 10,
+ .keycodes = {
+ KEY_PHONE, KEY_CLEAR, KEY_MAIL, KEY_WWW, KEY_ENTER,
+ KEY_1, KEY_2, KEY_3, 0, KEY_UP,
+ KEY_4, KEY_5, KEY_6, 0, KEY_LEFT,
+ KEY_7, KEY_8, KEY_9, KEY_PROG1, KEY_RIGHT,
+ KEY_S, KEY_0, KEY_P, KEY_PROG2, KEY_DOWN,
+ 0, 0, 0, 0, 0
+ },
+};
+
+static struct resource kfr2r09_sh_keysc_resources[] = {
+ [0] = {
+ .name = "KEYSC",
+ .start = 0x044b0000,
+ .end = 0x044b000f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 79,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device kfr2r09_sh_keysc_device = {
+ .name = "sh_keysc",
+ .id = 0, /* "keysc0" clock */
+ .num_resources = ARRAY_SIZE(kfr2r09_sh_keysc_resources),
+ .resource = kfr2r09_sh_keysc_resources,
+ .dev = {
+ .platform_data = &kfr2r09_sh_keysc_info,
+ },
+};
+
+static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
+ .clock_source = LCDC_CLK_BUS,
+ .ch[0] = {
+ .chan = LCDC_CHAN_MAINLCD,
+ .bpp = 16,
+ .interface_type = SYS18,
+ .clock_divider = 6,
+ .flags = LCDC_FLAGS_DWPOL,
+ .lcd_cfg = {
+ .name = "TX07D34VM0AAA",
+ .xres = 240,
+ .yres = 400,
+ .left_margin = 0,
+ .right_margin = 16,
+ .hsync_len = 8,
+ .upper_margin = 0,
+ .lower_margin = 1,
+ .vsync_len = 1,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ },
+ .lcd_size_cfg = {
+ .width = 35,
+ .height = 58,
+ },
+ .board_cfg = {
+ .setup_sys = kfr2r09_lcd_setup,
+ .display_on = kfr2r09_lcd_on,
+ .display_off = kfr2r09_lcd_off,
+ },
+ .sys_bus_cfg = {
+ .ldmt2r = 0x07010904,
+ .ldmt3r = 0x14012914,
+ /* set 1s delay to encourage fsync() */
+ .deferred_io_msec = 1000,
+ },
+ }
+};
+
+static struct resource kfr2r09_sh_lcdc_resources[] = {
+ [0] = {
+ .name = "LCDC",
+ .start = 0xfe940000, /* P4-only space */
+ .end = 0xfe941fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 106,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device kfr2r09_sh_lcdc_device = {
+ .name = "sh_mobile_lcdc_fb",
+ .num_resources = ARRAY_SIZE(kfr2r09_sh_lcdc_resources),
+ .resource = kfr2r09_sh_lcdc_resources,
+ .dev = {
+ .platform_data = &kfr2r09_sh_lcdc_info,
+ },
+};
+
+static struct platform_device *kfr2r09_devices[] __initdata = {
+ &kfr2r09_nor_flash_device,
+ &kfr2r09_nand_flash_device,
+ &kfr2r09_sh_keysc_device,
+ &kfr2r09_sh_lcdc_device,
+};
+
+#define BSC_CS0BCR 0xfec10004
+#define BSC_CS0WCR 0xfec10024
+#define BSC_CS4BCR 0xfec10010
+#define BSC_CS4WCR 0xfec10030
+
+static int __init kfr2r09_devices_setup(void)
+{
+ /* enable SCIF1 serial port for YC401 console support */
+ gpio_request(GPIO_FN_SCIF1_RXD, NULL);
+ gpio_request(GPIO_FN_SCIF1_TXD, NULL);
+
+ /* setup NOR flash at CS0 */
+ ctrl_outl(0x36db0400, BSC_CS0BCR);
+ ctrl_outl(0x00000500, BSC_CS0WCR);
+
+ /* setup NAND flash at CS4 */
+ ctrl_outl(0x36db0400, BSC_CS4BCR);
+ ctrl_outl(0x00000500, BSC_CS4WCR);
+
+ /* setup KEYSC pins */
+ gpio_request(GPIO_FN_KEYOUT0, NULL);
+ gpio_request(GPIO_FN_KEYOUT1, NULL);
+ gpio_request(GPIO_FN_KEYOUT2, NULL);
+ gpio_request(GPIO_FN_KEYOUT3, NULL);
+ gpio_request(GPIO_FN_KEYOUT4_IN6, NULL);
+ gpio_request(GPIO_FN_KEYIN0, NULL);
+ gpio_request(GPIO_FN_KEYIN1, NULL);
+ gpio_request(GPIO_FN_KEYIN2, NULL);
+ gpio_request(GPIO_FN_KEYIN3, NULL);
+ gpio_request(GPIO_FN_KEYIN4, NULL);
+ gpio_request(GPIO_FN_KEYOUT5_IN5, NULL);
+
+ /* setup LCDC pins for SYS panel */
+ gpio_request(GPIO_FN_LCDD17, NULL);
+ gpio_request(GPIO_FN_LCDD16, NULL);
+ gpio_request(GPIO_FN_LCDD15, NULL);
+ gpio_request(GPIO_FN_LCDD14, NULL);
+ gpio_request(GPIO_FN_LCDD13, NULL);
+ gpio_request(GPIO_FN_LCDD12, NULL);
+ gpio_request(GPIO_FN_LCDD11, NULL);
+ gpio_request(GPIO_FN_LCDD10, NULL);
+ gpio_request(GPIO_FN_LCDD9, NULL);
+ gpio_request(GPIO_FN_LCDD8, NULL);
+ gpio_request(GPIO_FN_LCDD7, NULL);
+ gpio_request(GPIO_FN_LCDD6, NULL);
+ gpio_request(GPIO_FN_LCDD5, NULL);
+ gpio_request(GPIO_FN_LCDD4, NULL);
+ gpio_request(GPIO_FN_LCDD3, NULL);
+ gpio_request(GPIO_FN_LCDD2, NULL);
+ gpio_request(GPIO_FN_LCDD1, NULL);
+ gpio_request(GPIO_FN_LCDD0, NULL);
+ gpio_request(GPIO_FN_LCDRS, NULL); /* LCD_RS */
+ gpio_request(GPIO_FN_LCDCS, NULL); /* LCD_CS/ */
+ gpio_request(GPIO_FN_LCDRD, NULL); /* LCD_RD/ */
+ gpio_request(GPIO_FN_LCDWR, NULL); /* LCD_WR/ */
+ gpio_request(GPIO_FN_LCDVSYN, NULL); /* LCD_VSYNC */
+ gpio_request(GPIO_PTE4, NULL); /* LCD_RST/ */
+ gpio_direction_output(GPIO_PTE4, 1);
+ gpio_request(GPIO_PTF4, NULL); /* PROTECT/ */
+ gpio_direction_output(GPIO_PTF4, 1);
+ gpio_request(GPIO_PTU0, NULL); /* LEDSTDBY/ */
+ gpio_direction_output(GPIO_PTU0, 1);
+
+ return platform_add_devices(kfr2r09_devices,
+ ARRAY_SIZE(kfr2r09_devices));
+}
+device_initcall(kfr2r09_devices_setup);
+
+/* Return the board specific boot mode pin configuration */
+static int kfr2r09_mode_pins(void)
+{
+ /* MD0=1, MD1=1, MD2=0: Clock Mode 3
+ * MD3=0: 16-bit Area0 Bus Width
+ * MD5=1: Little Endian
+ * MD8=1: Test Mode Disabled
+ */
+ return MODE_PIN0 | MODE_PIN1 | MODE_PIN5 | MODE_PIN8;
+}
+
+/*
+ * The Machine Vector
+ */
+static struct sh_machine_vector mv_kfr2r09 __initmv = {
+ .mv_name = "kfr2r09",
+ .mv_mode_pins = kfr2r09_mode_pins,
+};
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 15456a0773b..9162081504e 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -39,7 +39,15 @@
* SW41 : abxx xxxx -> a = 0 : Analog monitor
* 1 : Digital monitor
* b = 0 : VGA
- * 1 : SVGA
+ * 1 : 720p
+ */
+
+/*
+ * about 720p
+ *
+ * When you use 1280 x 720 lcdc output,
+ * you should change OSC6 lcdc clock from 25.175MHz to 74.25MHz,
+ * and change SW41 to use 720p
*/
/* Heartbeat */
@@ -305,6 +313,7 @@ static struct platform_device sh_eth_device = {
};
static struct r8a66597_platdata sh7724_usb0_host_data = {
+ .on_chip = 1,
};
static struct resource sh7724_usb0_host_resources[] = {
@@ -421,6 +430,32 @@ static int __init devices_setup(void)
/* turn on USB clocks, use external clock */
ctrl_outw((ctrl_inw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
+#ifdef CONFIG_PM
+ /* Let LED9 show STATUS2 */
+ gpio_request(GPIO_FN_STATUS2, NULL);
+
+ /* Lit LED10 show STATUS0 */
+ gpio_request(GPIO_FN_STATUS0, NULL);
+
+ /* Lit LED11 show PDSTATUS */
+ gpio_request(GPIO_FN_PDSTATUS, NULL);
+#else
+ /* Lit LED9 */
+ gpio_request(GPIO_PTJ6, NULL);
+ gpio_direction_output(GPIO_PTJ6, 1);
+ gpio_export(GPIO_PTJ6, 0);
+
+ /* Lit LED10 */
+ gpio_request(GPIO_PTJ5, NULL);
+ gpio_direction_output(GPIO_PTJ5, 1);
+ gpio_export(GPIO_PTJ5, 0);
+
+ /* Lit LED11 */
+ gpio_request(GPIO_PTJ7, NULL);
+ gpio_direction_output(GPIO_PTJ7, 1);
+ gpio_export(GPIO_PTJ7, 0);
+#endif
+
/* enable USB0 port */
ctrl_outw(0x0600, 0xa40501d4);
@@ -546,15 +581,15 @@ static int __init devices_setup(void)
sh_eth_init();
if (sw & SW41_B) {
- /* SVGA */
- lcdc_info.ch[0].lcd_cfg.xres = 800;
- lcdc_info.ch[0].lcd_cfg.yres = 600;
- lcdc_info.ch[0].lcd_cfg.left_margin = 142;
- lcdc_info.ch[0].lcd_cfg.right_margin = 52;
- lcdc_info.ch[0].lcd_cfg.hsync_len = 96;
- lcdc_info.ch[0].lcd_cfg.upper_margin = 24;
- lcdc_info.ch[0].lcd_cfg.lower_margin = 2;
- lcdc_info.ch[0].lcd_cfg.vsync_len = 2;
+ /* 720p */
+ lcdc_info.ch[0].lcd_cfg.xres = 1280;
+ lcdc_info.ch[0].lcd_cfg.yres = 720;
+ lcdc_info.ch[0].lcd_cfg.left_margin = 220;
+ lcdc_info.ch[0].lcd_cfg.right_margin = 110;
+ lcdc_info.ch[0].lcd_cfg.hsync_len = 40;
+ lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
+ lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
+ lcdc_info.ch[0].lcd_cfg.vsync_len = 5;
} else {
/* VGA */
lcdc_info.ch[0].lcd_cfg.xres = 640;
diff --git a/arch/sh/boards/mach-x3proto/setup.c b/arch/sh/boards/mach-x3proto/setup.c
index 8913ae39a80..efe4cb9f8a7 100644
--- a/arch/sh/boards/mach-x3proto/setup.c
+++ b/arch/sh/boards/mach-x3proto/setup.c
@@ -17,6 +17,7 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/usb/r8a66597.h>
+#include <linux/usb/m66592.h>
#include <asm/ilsel.h>
static struct resource heartbeat_resources[] = {
@@ -89,6 +90,11 @@ static struct platform_device r8a66597_usb_host_device = {
.resource = r8a66597_usb_host_resources,
};
+static struct m66592_platdata usbf_platdata = {
+ .xtal = M66592_PLATDATA_XTAL_24MHZ,
+ .vif = 1,
+};
+
static struct resource m66592_usb_peripheral_resources[] = {
[0] = {
.name = "m66592_udc",
@@ -109,6 +115,7 @@ static struct platform_device m66592_usb_peripheral_device = {
.dev = {
.dma_mask = NULL, /* don't use dma */
.coherent_dma_mask = 0xffffffff,
+ .platform_data = &usbf_platdata,
},
.num_resources = ARRAY_SIZE(m66592_usb_peripheral_resources),
.resource = m66592_usb_peripheral_resources,
diff --git a/arch/sh/boot/.gitignore b/arch/sh/boot/.gitignore
index aad5edddf93..541087d2029 100644
--- a/arch/sh/boot/.gitignore
+++ b/arch/sh/boot/.gitignore
@@ -1,4 +1,3 @@
zImage
-vmlinux.srec
-uImage
-uImage.srec
+vmlinux*
+uImage*
diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile
index 78efb04c28f..a1316872be6 100644
--- a/arch/sh/boot/Makefile
+++ b/arch/sh/boot/Makefile
@@ -20,8 +20,13 @@ CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
CONFIG_ZERO_PAGE_OFFSET ?= 0x00001000
CONFIG_ENTRY_OFFSET ?= 0x00001000
-targets := zImage vmlinux.srec uImage uImage.srec
-subdir- := compressed
+suffix-$(CONFIG_KERNEL_GZIP) := gz
+suffix-$(CONFIG_KERNEL_BZIP2) := bz2
+suffix-$(CONFIG_KERNEL_LZMA) := lzma
+
+targets := zImage vmlinux.srec romImage uImage uImage.srec uImage.gz uImage.bz2 uImage.lzma
+extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma
+subdir- := compressed romimage
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
@@ -30,6 +35,13 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(obj)/compressed/vmlinux: FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed $@
+$(obj)/romImage: $(obj)/romimage/vmlinux FORCE
+ $(call if_changed,objcopy)
+ @echo ' Kernel: $@ is ready'
+
+$(obj)/romimage/vmlinux: $(obj)/zImage FORCE
+ $(Q)$(MAKE) $(build)=$(obj)/romimage $@
+
KERNEL_MEMORY := 0x00000000
ifeq ($(CONFIG_PMB_FIXED),y)
KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
@@ -40,9 +52,6 @@ KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
$$[$(CONFIG_MEMORY_START)]')
endif
-export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
- CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY
-
KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \
$$[$(CONFIG_PAGE_OFFSET) + \
$(KERNEL_MEMORY) + \
@@ -55,19 +64,30 @@ KERNEL_ENTRY := $(shell /bin/bash -c 'printf "0x%08x" \
quiet_cmd_uimage = UIMAGE $@
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sh -O linux -T kernel \
- -C gzip -a $(KERNEL_LOAD) -e $(KERNEL_ENTRY) \
+ -C $(2) -a $(KERNEL_LOAD) -e $(KERNEL_ENTRY) \
-n 'Linux-$(KERNELRELEASE)' -d $< $@
-$(obj)/uImage: $(obj)/vmlinux.bin.gz FORCE
- $(call if_changed,uimage)
- @echo ' Image $@ is ready'
-
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
$(call if_changed,gzip)
+$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
+ $(call if_changed,bzip2)
+
+$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
+ $(call if_changed,lzma)
+
+$(obj)/uImage.bz2: $(obj)/vmlinux.bin.bz2
+ $(call if_changed,uimage,bzip2)
+
+$(obj)/uImage.gz: $(obj)/vmlinux.bin.gz
+ $(call if_changed,uimage,gzip)
+
+$(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma
+ $(call if_changed,uimage,lzma)
+
OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec
$(obj)/vmlinux.srec: $(obj)/compressed/vmlinux
$(call if_changed,objcopy)
@@ -76,5 +96,9 @@ OBJCOPYFLAGS_uImage.srec := -I binary -O srec
$(obj)/uImage.srec: $(obj)/uImage
$(call if_changed,objcopy)
-clean-files += uImage uImage.srec vmlinux.srec \
- vmlinux.bin vmlinux.bin.gz
+$(obj)/uImage: $(obj)/uImage.$(suffix-y)
+ @ln -sf $(notdir $<) $@
+ @echo ' Image $@ is ready'
+
+export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
+ CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY suffix-y
diff --git a/arch/sh/boot/compressed/.gitignore b/arch/sh/boot/compressed/.gitignore
new file mode 100644
index 00000000000..2374a83d87b
--- /dev/null
+++ b/arch/sh/boot/compressed/.gitignore
@@ -0,0 +1 @@
+vmlinux.bin.*
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
index 9531bf1b7c2..6182eca5180 100644
--- a/arch/sh/boot/compressed/Makefile
+++ b/arch/sh/boot/compressed/Makefile
@@ -5,9 +5,10 @@
#
targets := vmlinux vmlinux.bin vmlinux.bin.gz \
- head_$(BITS).o misc_$(BITS).o piggy.o
+ vmlinux.bin.bz2 vmlinux.bin.lzma \
+ head_$(BITS).o misc.o piggy.o
-OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc_$(BITS).o $(obj)/cache.o
+OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o
ifdef CONFIG_SH_STANDARD_BIOS
OBJECTS += $(obj)/../../kernel/sh_bios.o
@@ -23,7 +24,7 @@ IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \
LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
-ifeq ($(CONFIG_FUNCTION_TRACER),y)
+ifeq ($(CONFIG_MCOUNT),y)
ORIG_CFLAGS := $(KBUILD_CFLAGS)
KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
endif
@@ -38,10 +39,18 @@ $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+vmlinux.bin.all-y := $(obj)/vmlinux.bin
+
+$(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) FORCE
$(call if_changed,gzip)
+$(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) FORCE
+ $(call if_changed,bzip2)
+$(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE
+ $(call if_changed,lzma)
OBJCOPYFLAGS += -R .empty_zero_page
-$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE
- $(call if_changed,as_o_S)
+LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) FORCE
+ $(call if_changed,ld)
diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c
new file mode 100644
index 00000000000..fd56a71ca9d
--- /dev/null
+++ b/arch/sh/boot/compressed/misc.c
@@ -0,0 +1,149 @@
+/*
+ * arch/sh/boot/compressed/misc.c
+ *
+ * This is a collection of several routines from gzip-1.0.3
+ * adapted for Linux.
+ *
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ *
+ * Adapted for SH by Stuart Menefy, Aug 1999
+ *
+ * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
+ */
+
+#include <asm/uaccess.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/sh_bios.h>
+
+/*
+ * gzip declarations
+ */
+
+#define STATIC static
+
+#undef memset
+#undef memcpy
+#define memzero(s, n) memset ((s), 0, (n))
+
+/* cache.c */
+#define CACHE_ENABLE 0
+#define CACHE_DISABLE 1
+int cache_control(unsigned int command);
+
+extern char input_data[];
+extern int input_len;
+static unsigned char *output;
+
+static void error(char *m);
+
+int puts(const char *);
+
+extern int _text; /* Defined in vmlinux.lds.S */
+extern int _end;
+static unsigned long free_mem_ptr;
+static unsigned long free_mem_end_ptr;
+
+#ifdef CONFIG_HAVE_KERNEL_BZIP2
+#define HEAP_SIZE 0x400000
+#else
+#define HEAP_SIZE 0x10000
+#endif
+
+#ifdef CONFIG_KERNEL_GZIP
+#include "../../../../lib/decompress_inflate.c"
+#endif
+
+#ifdef CONFIG_KERNEL_BZIP2
+#include "../../../../lib/decompress_bunzip2.c"
+#endif
+
+#ifdef CONFIG_KERNEL_LZMA
+#include "../../../../lib/decompress_unlzma.c"
+#endif
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+size_t strlen(const char *s)
+{
+ int i = 0;
+
+ while (*s++)
+ i++;
+ return i;
+}
+
+int puts(const char *s)
+{
+ int len = strlen(s);
+ sh_bios_console_write(s, len);
+ return len;
+}
+#else
+int puts(const char *s)
+{
+ /* This should be updated to use the sh-sci routines */
+ return 0;
+}
+#endif
+
+void* memset(void* s, int c, size_t n)
+{
+ int i;
+ char *ss = (char*)s;
+
+ for (i=0;i<n;i++) ss[i] = c;
+ return s;
+}
+
+void* memcpy(void* __dest, __const void* __src,
+ size_t __n)
+{
+ int i;
+ char *d = (char *)__dest, *s = (char *)__src;
+
+ for (i=0;i<__n;i++) d[i] = s[i];
+ return __dest;
+}
+
+static void error(char *x)
+{
+ puts("\n\n");
+ puts(x);
+ puts("\n\n -- System halted");
+
+ while(1); /* Halt */
+}
+
+#ifdef CONFIG_SUPERH64
+#define stackalign 8
+#else
+#define stackalign 4
+#endif
+
+#define STACK_SIZE (4096)
+long __attribute__ ((aligned(stackalign))) user_stack[STACK_SIZE];
+long *stack_start = &user_stack[STACK_SIZE];
+
+void decompress_kernel(void)
+{
+ unsigned long output_addr;
+
+#ifdef CONFIG_SUPERH64
+ output_addr = (CONFIG_MEMORY_START + 0x2000);
+#else
+ output_addr = PHYSADDR((unsigned long)&_text+PAGE_SIZE);
+#ifdef CONFIG_29BIT
+ output_addr |= P2SEG;
+#endif
+#endif
+
+ output = (unsigned char *)output_addr;
+ free_mem_ptr = (unsigned long)&_end;
+ free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
+
+ puts("Uncompressing Linux... ");
+ cache_control(CACHE_ENABLE);
+ decompress(input_data, input_len, NULL, NULL, output, NULL, error);
+ cache_control(CACHE_DISABLE);
+ puts("Ok, booting the kernel.\n");
+}
diff --git a/arch/sh/boot/compressed/misc_32.c b/arch/sh/boot/compressed/misc_32.c
deleted file mode 100644
index efdba6b2957..00000000000
--- a/arch/sh/boot/compressed/misc_32.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * arch/sh/boot/compressed/misc.c
- *
- * This is a collection of several routines from gzip-1.0.3
- * adapted for Linux.
- *
- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
- *
- * Adapted for SH by Stuart Menefy, Aug 1999
- *
- * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
- */
-
-#include <asm/uaccess.h>
-#include <asm/addrspace.h>
-#include <asm/page.h>
-#ifdef CONFIG_SH_STANDARD_BIOS
-#include <asm/sh_bios.h>
-#endif
-
-/*
- * gzip declarations
- */
-
-#define OF(args) args
-#define STATIC static
-
-#undef memset
-#undef memcpy
-#define memzero(s, n) memset ((s), 0, (n))
-
-typedef unsigned char uch;
-typedef unsigned short ush;
-typedef unsigned long ulg;
-
-#define WSIZE 0x8000 /* Window size must be at least 32k, */
- /* and a power of two */
-
-static uch *inbuf; /* input buffer */
-static uch window[WSIZE]; /* Sliding window buffer */
-
-static unsigned insize = 0; /* valid bytes in inbuf */
-static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0; /* bytes in output buffer */
-
-/* gzip flag byte */
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
-#define COMMENT 0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
-#define RESERVED 0xC0 /* bit 6,7: reserved */
-
-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions */
-#ifdef DEBUG
-# define Assert(cond,msg) {if(!(cond)) error(msg);}
-# define Trace(x) fprintf x
-# define Tracev(x) {if (verbose) fprintf x ;}
-# define Tracevv(x) {if (verbose>1) fprintf x ;}
-# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-# define Assert(cond,msg)
-# define Trace(x)
-# define Tracev(x)
-# define Tracevv(x)
-# define Tracec(c,x)
-# define Tracecv(c,x)
-#endif
-
-static int fill_inbuf(void);
-static void flush_window(void);
-static void error(char *m);
-
-extern char input_data[];
-extern int input_len;
-
-static long bytes_out = 0;
-static uch *output_data;
-static unsigned long output_ptr = 0;
-
-static void error(char *m);
-
-int puts(const char *);
-
-extern int _text; /* Defined in vmlinux.lds.S */
-extern int _end;
-static unsigned long free_mem_ptr;
-static unsigned long free_mem_end_ptr;
-
-#define HEAP_SIZE 0x10000
-
-#include "../../../../lib/inflate.c"
-
-#ifdef CONFIG_SH_STANDARD_BIOS
-size_t strlen(const char *s)
-{
- int i = 0;
-
- while (*s++)
- i++;
- return i;
-}
-
-int puts(const char *s)
-{
- int len = strlen(s);
- sh_bios_console_write(s, len);
- return len;
-}
-#else
-int puts(const char *s)
-{
- /* This should be updated to use the sh-sci routines */
- return 0;
-}
-#endif
-
-void* memset(void* s, int c, size_t n)
-{
- int i;
- char *ss = (char*)s;
-
- for (i=0;i<n;i++) ss[i] = c;
- return s;
-}
-
-void* memcpy(void* __dest, __const void* __src,
- size_t __n)
-{
- int i;
- char *d = (char *)__dest, *s = (char *)__src;
-
- for (i=0;i<__n;i++) d[i] = s[i];
- return __dest;
-}
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf(void)
-{
- if (insize != 0) {
- error("ran out of input data");
- }
-
- inbuf = input_data;
- insize = input_len;
- inptr = 1;
- return inbuf[0];
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void flush_window(void)
-{
- ulg c = crc; /* temporary variable */
- unsigned n;
- uch *in, *out, ch;
-
- in = window;
- out = &output_data[output_ptr];
- for (n = 0; n < outcnt; n++) {
- ch = *out++ = *in++;
- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
- }
- crc = c;
- bytes_out += (ulg)outcnt;
- output_ptr += (ulg)outcnt;
- outcnt = 0;
-}
-
-static void error(char *x)
-{
- puts("\n\n");
- puts(x);
- puts("\n\n -- System halted");
-
- while(1); /* Halt */
-}
-
-#define STACK_SIZE (4096)
-long user_stack [STACK_SIZE];
-long* stack_start = &user_stack[STACK_SIZE];
-
-void decompress_kernel(void)
-{
- output_data = NULL;
- output_ptr = PHYSADDR((unsigned long)&_text+PAGE_SIZE);
-#ifdef CONFIG_29BIT
- output_ptr |= P2SEG;
-#endif
- free_mem_ptr = (unsigned long)&_end;
- free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
-
- makecrc();
- puts("Uncompressing Linux... ");
- gunzip();
- puts("Ok, booting the kernel.\n");
-}
diff --git a/arch/sh/boot/compressed/misc_64.c b/arch/sh/boot/compressed/misc_64.c
deleted file mode 100644
index 2941657e18a..00000000000
--- a/arch/sh/boot/compressed/misc_64.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * arch/sh/boot/compressed/misc_64.c
- *
- * This is a collection of several routines from gzip-1.0.3
- * adapted for Linux.
- *
- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
- *
- * Adapted for SHmedia from sh by Stuart Menefy, May 2002
- */
-
-#include <asm/uaccess.h>
-
-/* cache.c */
-#define CACHE_ENABLE 0
-#define CACHE_DISABLE 1
-int cache_control(unsigned int command);
-
-/*
- * gzip declarations
- */
-
-#define OF(args) args
-#define STATIC static
-
-#undef memset
-#undef memcpy
-#define memzero(s, n) memset ((s), 0, (n))
-
-typedef unsigned char uch;
-typedef unsigned short ush;
-typedef unsigned long ulg;
-
-#define WSIZE 0x8000 /* Window size must be at least 32k, */
- /* and a power of two */
-
-static uch *inbuf; /* input buffer */
-static uch window[WSIZE]; /* Sliding window buffer */
-
-static unsigned insize = 0; /* valid bytes in inbuf */
-static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0; /* bytes in output buffer */
-
-/* gzip flag byte */
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
-#define COMMENT 0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
-#define RESERVED 0xC0 /* bit 6,7: reserved */
-
-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions */
-#ifdef DEBUG
-# define Assert(cond,msg) {if(!(cond)) error(msg);}
-# define Trace(x) fprintf x
-# define Tracev(x) {if (verbose) fprintf x ;}
-# define Tracevv(x) {if (verbose>1) fprintf x ;}
-# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-# define Assert(cond,msg)
-# define Trace(x)
-# define Tracev(x)
-# define Tracevv(x)
-# define Tracec(c,x)
-# define Tracecv(c,x)
-#endif
-
-static int fill_inbuf(void);
-static void flush_window(void);
-static void error(char *m);
-
-extern char input_data[];
-extern int input_len;
-
-static long bytes_out = 0;
-static uch *output_data;
-static unsigned long output_ptr = 0;
-
-static void error(char *m);
-
-static void puts(const char *);
-
-extern int _text; /* Defined in vmlinux.lds.S */
-extern int _end;
-static unsigned long free_mem_ptr;
-static unsigned long free_mem_end_ptr;
-
-#define HEAP_SIZE 0x10000
-
-#include "../../../../lib/inflate.c"
-
-void puts(const char *s)
-{
-}
-
-void *memset(void *s, int c, size_t n)
-{
- int i;
- char *ss = (char *) s;
-
- for (i = 0; i < n; i++)
- ss[i] = c;
- return s;
-}
-
-void *memcpy(void *__dest, __const void *__src, size_t __n)
-{
- int i;
- char *d = (char *) __dest, *s = (char *) __src;
-
- for (i = 0; i < __n; i++)
- d[i] = s[i];
- return __dest;
-}
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf(void)
-{
- if (insize != 0) {
- error("ran out of input data\n");
- }
-
- inbuf = input_data;
- insize = input_len;
- inptr = 1;
- return inbuf[0];
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void flush_window(void)
-{
- ulg c = crc; /* temporary variable */
- unsigned n;
- uch *in, *out, ch;
-
- in = window;
- out = &output_data[output_ptr];
- for (n = 0; n < outcnt; n++) {
- ch = *out++ = *in++;
- c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8);
- }
- crc = c;
- bytes_out += (ulg) outcnt;
- output_ptr += (ulg) outcnt;
- outcnt = 0;
- puts(".");
-}
-
-static void error(char *x)
-{
- puts("\n\n");
- puts(x);
- puts("\n\n -- System halted");
-
- while (1) ; /* Halt */
-}
-
-#define STACK_SIZE (4096)
-long __attribute__ ((aligned(8))) user_stack[STACK_SIZE];
-long *stack_start = &user_stack[STACK_SIZE];
-
-void decompress_kernel(void)
-{
- output_data = (uch *) (CONFIG_MEMORY_START + 0x2000);
- free_mem_ptr = (unsigned long) &_end;
- free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
-
- makecrc();
- puts("Uncompressing Linux... ");
- cache_control(CACHE_ENABLE);
- gunzip();
- puts("\n");
-
-#if 0
- /* When booting from ROM may want to do something like this if the
- * boot loader doesn't.
- */
-
- /* Set up the parameters and command line */
- {
- volatile unsigned int *parambase =
- (int *) (CONFIG_MEMORY_START + 0x1000);
-
- parambase[0] = 0x1; /* MOUNT_ROOT_RDONLY */
- parambase[1] = 0x0; /* RAMDISK_FLAGS */
- parambase[2] = 0x0200; /* ORIG_ROOT_DEV */
- parambase[3] = 0x0; /* LOADER_TYPE */
- parambase[4] = 0x0; /* INITRD_START */
- parambase[5] = 0x0; /* INITRD_SIZE */
- parambase[6] = 0;
-
- strcpy((char *) ((int) parambase + 0x100),
- "console=ttySC0,38400");
- }
-#endif
-
- puts("Ok, booting the kernel.\n");
-
- cache_control(CACHE_DISABLE);
-}
diff --git a/arch/sh/boot/compressed/piggy.S b/arch/sh/boot/compressed/piggy.S
deleted file mode 100644
index 566071926b1..00000000000
--- a/arch/sh/boot/compressed/piggy.S
+++ /dev/null
@@ -1,8 +0,0 @@
- .global input_len, input_data
- .data
-input_len:
- .long input_data_end - input_data
-input_data:
- .incbin "arch/sh/boot/compressed/vmlinux.bin.gz"
-input_data_end:
- .end
diff --git a/arch/sh/boot/compressed/vmlinux.scr b/arch/sh/boot/compressed/vmlinux.scr
new file mode 100644
index 00000000000..f02382ae5c4
--- /dev/null
+++ b/arch/sh/boot/compressed/vmlinux.scr
@@ -0,0 +1,10 @@
+SECTIONS
+{
+ .rodata.compressed : {
+ input_len = .;
+ LONG(input_data_end - input_data) input_data = .;
+ *(.data)
+ output_len = . - 4;
+ input_data_end = .;
+ }
+}
diff --git a/arch/sh/boot/romimage/Makefile b/arch/sh/boot/romimage/Makefile
new file mode 100644
index 00000000000..5806eee84f6
--- /dev/null
+++ b/arch/sh/boot/romimage/Makefile
@@ -0,0 +1,19 @@
+#
+# linux/arch/sh/boot/romimage/Makefile
+#
+# create an image suitable for burning to flash from zImage
+#
+
+targets := vmlinux head.o
+
+OBJECTS = $(obj)/head.o
+LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext 0 -e romstart
+
+$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
+ $(call if_changed,ld)
+ @:
+
+LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr arch/sh/boot/zImage FORCE
+ $(call if_changed,ld)
diff --git a/arch/sh/boot/romimage/head.S b/arch/sh/boot/romimage/head.S
new file mode 100644
index 00000000000..219bc626dd7
--- /dev/null
+++ b/arch/sh/boot/romimage/head.S
@@ -0,0 +1,10 @@
+/*
+ * linux/arch/sh/boot/romimage/head.S
+ *
+ * Board specific setup code, executed before zImage loader
+ */
+
+.text
+ .global romstart
+romstart:
+#include <mach/romimage.h>
diff --git a/arch/sh/boot/romimage/vmlinux.scr b/arch/sh/boot/romimage/vmlinux.scr
new file mode 100644
index 00000000000..287c08f8b4b
--- /dev/null
+++ b/arch/sh/boot/romimage/vmlinux.scr
@@ -0,0 +1,6 @@
+SECTIONS
+{
+ .text : {
+ *(.data)
+ }
+}
diff --git a/arch/sh/configs/kfr2r09_defconfig b/arch/sh/configs/kfr2r09_defconfig
new file mode 100644
index 00000000000..90e575c34d5
--- /dev/null
+++ b/arch/sh/configs/kfr2r09_defconfig
@@ -0,0 +1,877 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc3
+# Thu Jul 23 17:45:09 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY 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"
+# CONFIG_FREEZER is not set
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+CONFIG_ARCH_SHMOBILE=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG 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
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# 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
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+CONFIG_CPU_SUBTYPE_SH7724=y
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH7786 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_29BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+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=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+
+#
+# Cache configuration
+#
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+# CONFIG_SH_7724_SOLUTION_ENGINE is not set
+CONFIG_SH_KFR2R09=y
+
+#
+# Timer and clock configuration
+#
+# CONFIG_SH_TIMER_TMU is not set
+CONFIG_SH_TIMER_CMT=y
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,115200"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_HIBERNATION is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# 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 is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_MTD_OOPS 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=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# 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
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT 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
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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 is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+CONFIG_KEYBOARD_SH_KEYSC=y
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# 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=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_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_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_FSNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE 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_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FTRACE_SYSCALLS=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h
index 0c8f8e14622..68a5f4cb034 100644
--- a/arch/sh/include/asm/dma-sh.h
+++ b/arch/sh/include/asm/dma-sh.h
@@ -16,6 +16,7 @@
/* DMAOR contorl: The DMAOR access size is different by CPU.*/
#if defined(CONFIG_CPU_SUBTYPE_SH7723) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7724) || \
defined(CONFIG_CPU_SUBTYPE_SH7780) || \
defined(CONFIG_CPU_SUBTYPE_SH7785)
#define dmaor_read_reg(n) \
diff --git a/arch/sh/include/asm/dwarf.h b/arch/sh/include/asm/dwarf.h
new file mode 100644
index 00000000000..60b180728d8
--- /dev/null
+++ b/arch/sh/include/asm/dwarf.h
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2009 Matt Fleming <matt@console-pimps.org>
+ *
+ * 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_SH_DWARF_H
+#define __ASM_SH_DWARF_H
+
+#ifdef CONFIG_DWARF_UNWINDER
+
+/*
+ * DWARF expression operations
+ */
+#define DW_OP_addr 0x03
+#define DW_OP_deref 0x06
+#define DW_OP_const1u 0x08
+#define DW_OP_const1s 0x09
+#define DW_OP_const2u 0x0a
+#define DW_OP_const2s 0x0b
+#define DW_OP_const4u 0x0c
+#define DW_OP_const4s 0x0d
+#define DW_OP_const8u 0x0e
+#define DW_OP_const8s 0x0f
+#define DW_OP_constu 0x10
+#define DW_OP_consts 0x11
+#define DW_OP_dup 0x12
+#define DW_OP_drop 0x13
+#define DW_OP_over 0x14
+#define DW_OP_pick 0x15
+#define DW_OP_swap 0x16
+#define DW_OP_rot 0x17
+#define DW_OP_xderef 0x18
+#define DW_OP_abs 0x19
+#define DW_OP_and 0x1a
+#define DW_OP_div 0x1b
+#define DW_OP_minus 0x1c
+#define DW_OP_mod 0x1d
+#define DW_OP_mul 0x1e
+#define DW_OP_neg 0x1f
+#define DW_OP_not 0x20
+#define DW_OP_or 0x21
+#define DW_OP_plus 0x22
+#define DW_OP_plus_uconst 0x23
+#define DW_OP_shl 0x24
+#define DW_OP_shr 0x25
+#define DW_OP_shra 0x26
+#define DW_OP_xor 0x27
+#define DW_OP_skip 0x2f
+#define DW_OP_bra 0x28
+#define DW_OP_eq 0x29
+#define DW_OP_ge 0x2a
+#define DW_OP_gt 0x2b
+#define DW_OP_le 0x2c
+#define DW_OP_lt 0x2d
+#define DW_OP_ne 0x2e
+#define DW_OP_lit0 0x30
+#define DW_OP_lit1 0x31
+#define DW_OP_lit2 0x32
+#define DW_OP_lit3 0x33
+#define DW_OP_lit4 0x34
+#define DW_OP_lit5 0x35
+#define DW_OP_lit6 0x36
+#define DW_OP_lit7 0x37
+#define DW_OP_lit8 0x38
+#define DW_OP_lit9 0x39
+#define DW_OP_lit10 0x3a
+#define DW_OP_lit11 0x3b
+#define DW_OP_lit12 0x3c
+#define DW_OP_lit13 0x3d
+#define DW_OP_lit14 0x3e
+#define DW_OP_lit15 0x3f
+#define DW_OP_lit16 0x40
+#define DW_OP_lit17 0x41
+#define DW_OP_lit18 0x42
+#define DW_OP_lit19 0x43
+#define DW_OP_lit20 0x44
+#define DW_OP_lit21 0x45
+#define DW_OP_lit22 0x46
+#define DW_OP_lit23 0x47
+#define DW_OP_lit24 0x48
+#define DW_OP_lit25 0x49
+#define DW_OP_lit26 0x4a
+#define DW_OP_lit27 0x4b
+#define DW_OP_lit28 0x4c
+#define DW_OP_lit29 0x4d
+#define DW_OP_lit30 0x4e
+#define DW_OP_lit31 0x4f
+#define DW_OP_reg0 0x50
+#define DW_OP_reg1 0x51
+#define DW_OP_reg2 0x52
+#define DW_OP_reg3 0x53
+#define DW_OP_reg4 0x54
+#define DW_OP_reg5 0x55
+#define DW_OP_reg6 0x56
+#define DW_OP_reg7 0x57
+#define DW_OP_reg8 0x58
+#define DW_OP_reg9 0x59
+#define DW_OP_reg10 0x5a
+#define DW_OP_reg11 0x5b
+#define DW_OP_reg12 0x5c
+#define DW_OP_reg13 0x5d
+#define DW_OP_reg14 0x5e
+#define DW_OP_reg15 0x5f
+#define DW_OP_reg16 0x60
+#define DW_OP_reg17 0x61
+#define DW_OP_reg18 0x62
+#define DW_OP_reg19 0x63
+#define DW_OP_reg20 0x64
+#define DW_OP_reg21 0x65
+#define DW_OP_reg22 0x66
+#define DW_OP_reg23 0x67
+#define DW_OP_reg24 0x68
+#define DW_OP_reg25 0x69
+#define DW_OP_reg26 0x6a
+#define DW_OP_reg27 0x6b
+#define DW_OP_reg28 0x6c
+#define DW_OP_reg29 0x6d
+#define DW_OP_reg30 0x6e
+#define DW_OP_reg31 0x6f
+#define DW_OP_breg0 0x70
+#define DW_OP_breg1 0x71
+#define DW_OP_breg2 0x72
+#define DW_OP_breg3 0x73
+#define DW_OP_breg4 0x74
+#define DW_OP_breg5 0x75
+#define DW_OP_breg6 0x76
+#define DW_OP_breg7 0x77
+#define DW_OP_breg8 0x78
+#define DW_OP_breg9 0x79
+#define DW_OP_breg10 0x7a
+#define DW_OP_breg11 0x7b
+#define DW_OP_breg12 0x7c
+#define DW_OP_breg13 0x7d
+#define DW_OP_breg14 0x7e
+#define DW_OP_breg15 0x7f
+#define DW_OP_breg16 0x80
+#define DW_OP_breg17 0x81
+#define DW_OP_breg18 0x82
+#define DW_OP_breg19 0x83
+#define DW_OP_breg20 0x84
+#define DW_OP_breg21 0x85
+#define DW_OP_breg22 0x86
+#define DW_OP_breg23 0x87
+#define DW_OP_breg24 0x88
+#define DW_OP_breg25 0x89
+#define DW_OP_breg26 0x8a
+#define DW_OP_breg27 0x8b
+#define DW_OP_breg28 0x8c
+#define DW_OP_breg29 0x8d
+#define DW_OP_breg30 0x8e
+#define DW_OP_breg31 0x8f
+#define DW_OP_regx 0x90
+#define DW_OP_fbreg 0x91
+#define DW_OP_bregx 0x92
+#define DW_OP_piece 0x93
+#define DW_OP_deref_size 0x94
+#define DW_OP_xderef_size 0x95
+#define DW_OP_nop 0x96
+#define DW_OP_push_object_address 0x97
+#define DW_OP_call2 0x98
+#define DW_OP_call4 0x99
+#define DW_OP_call_ref 0x9a
+#define DW_OP_form_tls_address 0x9b
+#define DW_OP_call_frame_cfa 0x9c
+#define DW_OP_bit_piece 0x9d
+#define DW_OP_lo_user 0xe0
+#define DW_OP_hi_user 0xff
+
+/*
+ * Addresses used in FDE entries in the .eh_frame section may be encoded
+ * using one of the following encodings.
+ */
+#define DW_EH_PE_absptr 0x00
+#define DW_EH_PE_omit 0xff
+#define DW_EH_PE_uleb128 0x01
+#define DW_EH_PE_udata2 0x02
+#define DW_EH_PE_udata4 0x03
+#define DW_EH_PE_udata8 0x04
+#define DW_EH_PE_sleb128 0x09
+#define DW_EH_PE_sdata2 0x0a
+#define DW_EH_PE_sdata4 0x0b
+#define DW_EH_PE_sdata8 0x0c
+#define DW_EH_PE_signed 0x09
+
+#define DW_EH_PE_pcrel 0x10
+
+/*
+ * The architecture-specific register number that contains the return
+ * address in the .debug_frame table.
+ */
+#define DWARF_ARCH_RA_REG 17
+
+#ifndef __ASSEMBLY__
+/*
+ * Read either the frame pointer (r14) or the stack pointer (r15).
+ * NOTE: this MUST be inlined.
+ */
+static __always_inline unsigned long dwarf_read_arch_reg(unsigned int reg)
+{
+ unsigned long value;
+
+ switch (reg) {
+ case 14:
+ __asm__ __volatile__("mov r14, %0\n" : "=r" (value));
+ break;
+ case 15:
+ __asm__ __volatile__("mov r15, %0\n" : "=r" (value));
+ break;
+ default:
+ BUG();
+ }
+
+ return value;
+}
+
+/**
+ * dwarf_cie - Common Information Entry
+ */
+struct dwarf_cie {
+ unsigned long length;
+ unsigned long cie_id;
+ unsigned char version;
+ const char *augmentation;
+ unsigned int code_alignment_factor;
+ int data_alignment_factor;
+
+ /* Which column in the rule table represents return addr of func. */
+ unsigned int return_address_reg;
+
+ unsigned char *initial_instructions;
+ unsigned char *instructions_end;
+
+ unsigned char encoding;
+
+ unsigned long cie_pointer;
+
+ struct list_head link;
+
+ unsigned long flags;
+#define DWARF_CIE_Z_AUGMENTATION (1 << 0)
+};
+
+/**
+ * dwarf_fde - Frame Description Entry
+ */
+struct dwarf_fde {
+ unsigned long length;
+ unsigned long cie_pointer;
+ struct dwarf_cie *cie;
+ unsigned long initial_location;
+ unsigned long address_range;
+ unsigned char *instructions;
+ unsigned char *end;
+ struct list_head link;
+};
+
+/**
+ * dwarf_frame - DWARF information for a frame in the call stack
+ */
+struct dwarf_frame {
+ struct dwarf_frame *prev, *next;
+
+ unsigned long pc;
+
+ struct dwarf_reg *regs;
+ unsigned int num_regs; /* how many regs are allocated? */
+
+ unsigned int depth; /* what level are we in the callstack? */
+
+ unsigned long cfa;
+
+ /* Valid when DW_FRAME_CFA_REG_OFFSET is set in flags */
+ unsigned int cfa_register;
+ unsigned int cfa_offset;
+
+ /* Valid when DW_FRAME_CFA_REG_EXP is set in flags */
+ unsigned char *cfa_expr;
+ unsigned int cfa_expr_len;
+
+ unsigned long flags;
+#define DWARF_FRAME_CFA_REG_OFFSET (1 << 0)
+#define DWARF_FRAME_CFA_REG_EXP (1 << 1)
+
+ unsigned long return_addr;
+};
+
+/**
+ * dwarf_reg - DWARF register
+ * @flags: Describes how to calculate the value of this register
+ */
+struct dwarf_reg {
+ unsigned long addr;
+ unsigned long flags;
+#define DWARF_REG_OFFSET (1 << 0)
+};
+
+/**
+ * dwarf_stack - a DWARF stack contains a collection of DWARF frames
+ * @depth: the number of frames in the stack
+ * @level: an array of DWARF frames, indexed by stack level
+ *
+ */
+struct dwarf_stack {
+ unsigned int depth;
+ struct dwarf_frame **level;
+};
+
+/*
+ * Call Frame instruction opcodes.
+ */
+#define DW_CFA_advance_loc 0x40
+#define DW_CFA_offset 0x80
+#define DW_CFA_restore 0xc0
+#define DW_CFA_nop 0x00
+#define DW_CFA_set_loc 0x01
+#define DW_CFA_advance_loc1 0x02
+#define DW_CFA_advance_loc2 0x03
+#define DW_CFA_advance_loc4 0x04
+#define DW_CFA_offset_extended 0x05
+#define DW_CFA_restore_extended 0x06
+#define DW_CFA_undefined 0x07
+#define DW_CFA_same_value 0x08
+#define DW_CFA_register 0x09
+#define DW_CFA_remember_state 0x0a
+#define DW_CFA_restore_state 0x0b
+#define DW_CFA_def_cfa 0x0c
+#define DW_CFA_def_cfa_register 0x0d
+#define DW_CFA_def_cfa_offset 0x0e
+#define DW_CFA_def_cfa_expression 0x0f
+#define DW_CFA_expression 0x10
+#define DW_CFA_offset_extended_sf 0x11
+#define DW_CFA_def_cfa_sf 0x12
+#define DW_CFA_def_cfa_offset_sf 0x13
+#define DW_CFA_val_offset 0x14
+#define DW_CFA_val_offset_sf 0x15
+#define DW_CFA_val_expression 0x16
+#define DW_CFA_lo_user 0x1c
+#define DW_CFA_hi_user 0x3f
+
+/*
+ * Some call frame instructions encode their operands in the opcode. We
+ * need some helper functions to extract both the opcode and operands
+ * from an instruction.
+ */
+static inline unsigned int DW_CFA_opcode(unsigned long insn)
+{
+ return (insn & 0xc0);
+}
+
+static inline unsigned int DW_CFA_operand(unsigned long insn)
+{
+ return (insn & 0x3f);
+}
+
+#define DW_EH_FRAME_CIE 0 /* .eh_frame CIE IDs are 0 */
+#define DW_CIE_ID 0xffffffff
+#define DW64_CIE_ID 0xffffffffffffffffULL
+
+/*
+ * DWARF FDE/CIE length field values.
+ */
+#define DW_EXT_LO 0xfffffff0
+#define DW_EXT_HI 0xffffffff
+#define DW_EXT_DWARF64 DW_EXT_HI
+
+extern void dwarf_unwinder_init(void);
+
+extern struct dwarf_frame *dwarf_unwind_stack(unsigned long,
+ struct dwarf_frame *);
+#endif /* __ASSEMBLY__ */
+
+#define CFI_STARTPROC .cfi_startproc
+#define CFI_ENDPROC .cfi_endproc
+#define CFI_DEF_CFA .cfi_def_cfa
+#define CFI_REGISTER .cfi_register
+#define CFI_REL_OFFSET .cfi_rel_offset
+
+#else
+
+/*
+ * Use the asm comment character to ignore the rest of the line.
+ */
+#define CFI_IGNORE !
+
+#define CFI_STARTPROC CFI_IGNORE
+#define CFI_ENDPROC CFI_IGNORE
+#define CFI_DEF_CFA CFI_IGNORE
+#define CFI_REGISTER CFI_IGNORE
+#define CFI_REL_OFFSET CFI_IGNORE
+
+#ifndef __ASSEMBLY__
+static inline void dwarf_unwinder_init(void)
+{
+}
+#endif
+
+#endif /* CONFIG_DWARF_UNWINDER */
+
+#endif /* __ASM_SH_DWARF_H */
diff --git a/arch/sh/include/asm/entry-macros.S b/arch/sh/include/asm/entry-macros.S
index 3a4752a6572..64fd0de24da 100644
--- a/arch/sh/include/asm/entry-macros.S
+++ b/arch/sh/include/asm/entry-macros.S
@@ -31,8 +31,92 @@
#endif
.endm
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+ .macro TRACE_IRQS_ON
+ mov.l r0, @-r15
+ mov.l r1, @-r15
+ mov.l r2, @-r15
+ mov.l r3, @-r15
+ mov.l r4, @-r15
+ mov.l r5, @-r15
+ mov.l r6, @-r15
+ mov.l r7, @-r15
+
+ mov.l 7834f, r0
+ jsr @r0
+ nop
+
+ mov.l @r15+, r7
+ mov.l @r15+, r6
+ mov.l @r15+, r5
+ mov.l @r15+, r4
+ mov.l @r15+, r3
+ mov.l @r15+, r2
+ mov.l @r15+, r1
+ mov.l @r15+, r0
+ mov.l 7834f, r0
+
+ bra 7835f
+ nop
+ .balign 4
+7834: .long trace_hardirqs_on
+7835:
+ .endm
+ .macro TRACE_IRQS_OFF
+
+ mov.l r0, @-r15
+ mov.l r1, @-r15
+ mov.l r2, @-r15
+ mov.l r3, @-r15
+ mov.l r4, @-r15
+ mov.l r5, @-r15
+ mov.l r6, @-r15
+ mov.l r7, @-r15
+
+ mov.l 7834f, r0
+ jsr @r0
+ nop
+
+ mov.l @r15+, r7
+ mov.l @r15+, r6
+ mov.l @r15+, r5
+ mov.l @r15+, r4
+ mov.l @r15+, r3
+ mov.l @r15+, r2
+ mov.l @r15+, r1
+ mov.l @r15+, r0
+ mov.l 7834f, r0
+
+ bra 7835f
+ nop
+ .balign 4
+7834: .long trace_hardirqs_off
+7835:
+ .endm
+
+#else
+ .macro TRACE_IRQS_ON
+ .endm
+
+ .macro TRACE_IRQS_OFF
+ .endm
+#endif
+
#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4)
# define PREF(x) pref @x
#else
# define PREF(x) nop
#endif
+
+ /*
+ * Macro for use within assembly. Because the DWARF unwinder
+ * needs to use the frame register to unwind the stack, we
+ * need to setup r14 with the value of the stack pointer as
+ * the return address is usually on the stack somewhere.
+ */
+ .macro setup_frame_reg
+#ifdef CONFIG_DWARF_UNWINDER
+ mov r15, r14
+#endif
+ .endm
diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
index 8fea7d8c825..7e0bcc4d4a9 100644
--- a/arch/sh/include/asm/ftrace.h
+++ b/arch/sh/include/asm/ftrace.h
@@ -11,10 +11,13 @@ extern void mcount(void);
#define MCOUNT_ADDR ((long)(mcount))
#ifdef CONFIG_DYNAMIC_FTRACE
-#define CALLER_ADDR ((long)(ftrace_caller))
+#define CALL_ADDR ((long)(ftrace_call))
#define STUB_ADDR ((long)(ftrace_stub))
+#define GRAPH_ADDR ((long)(ftrace_graph_call))
+#define CALLER_ADDR ((long)(ftrace_caller))
-#define MCOUNT_INSN_OFFSET ((STUB_ADDR - CALLER_ADDR) >> 1)
+#define MCOUNT_INSN_OFFSET ((STUB_ADDR - CALL_ADDR) - 4)
+#define GRAPH_INSN_OFFSET ((CALLER_ADDR - GRAPH_ADDR) - 4)
struct dyn_arch_ftrace {
/* No extra data needed on sh */
diff --git a/arch/sh/include/asm/hardirq.h b/arch/sh/include/asm/hardirq.h
index 715ee237fc7..a5be4afa790 100644
--- a/arch/sh/include/asm/hardirq.h
+++ b/arch/sh/include/asm/hardirq.h
@@ -1,16 +1,9 @@
#ifndef __ASM_SH_HARDIRQ_H
#define __ASM_SH_HARDIRQ_H
-#include <linux/threads.h>
-#include <linux/irq.h>
-
-/* entry.S is sensitive to the offsets of these fields */
-typedef struct {
- unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
-
extern void ack_bad_irq(unsigned int irq);
+#define ack_bad_irq ack_bad_irq
+
+#include <asm-generic/hardirq.h>
#endif /* __ASM_SH_HARDIRQ_H */
diff --git a/arch/sh/include/asm/hwblk.h b/arch/sh/include/asm/hwblk.h
new file mode 100644
index 00000000000..c01d72cb675
--- /dev/null
+++ b/arch/sh/include/asm/hwblk.h
@@ -0,0 +1,70 @@
+#ifndef __ASM_SH_HWBLK_H
+#define __ASM_SH_HWBLK_H
+
+#include <asm/clock.h>
+#include <asm/io.h>
+
+#define HWBLK_CNT_USAGE 0
+#define HWBLK_CNT_NR 1
+
+#define HWBLK_AREA_FLAG_PARENT (1 << 0) /* valid parent */
+
+#define HWBLK_AREA(_flags, _parent) \
+{ \
+ .flags = _flags, \
+ .parent = _parent, \
+}
+
+struct hwblk_area {
+ int cnt[HWBLK_CNT_NR];
+ unsigned char parent;
+ unsigned char flags;
+};
+
+#define HWBLK(_mstp, _bit, _area) \
+{ \
+ .mstp = (void __iomem *)_mstp, \
+ .bit = _bit, \
+ .area = _area, \
+}
+
+struct hwblk {
+ void __iomem *mstp;
+ unsigned char bit;
+ unsigned char area;
+ int cnt[HWBLK_CNT_NR];
+};
+
+struct hwblk_info {
+ struct hwblk_area *areas;
+ int nr_areas;
+ struct hwblk *hwblks;
+ int nr_hwblks;
+};
+
+/* Should be defined by processor-specific code */
+int arch_hwblk_init(void);
+int arch_hwblk_sleep_mode(void);
+
+int hwblk_register(struct hwblk_info *info);
+int hwblk_init(void);
+
+void hwblk_enable(struct hwblk_info *info, int hwblk);
+void hwblk_disable(struct hwblk_info *info, int hwblk);
+
+void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int cnt);
+void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int cnt);
+
+/* allow clocks to enable and disable hardware blocks */
+#define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags) \
+{ \
+ .name = _name, \
+ .id = _id, \
+ .parent = _parent, \
+ .arch_flags = _hwblk, \
+ .flags = _flags, \
+}
+
+int sh_hwblk_clk_register(struct clk *clks, int nr);
+
+#endif /* __ASM_SH_HWBLK_H */
diff --git a/arch/sh/include/asm/lmb.h b/arch/sh/include/asm/lmb.h
new file mode 100644
index 00000000000..9b437f657ff
--- /dev/null
+++ b/arch/sh/include/asm/lmb.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH_LMB_H
+#define __ASM_SH_LMB_H
+
+#define LMB_REAL_LIMIT 0
+
+#endif /* __ASM_SH_LMB_H */
diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h
index 72ea209195b..0db19db913c 100644
--- a/arch/sh/include/asm/pgtable_32.h
+++ b/arch/sh/include/asm/pgtable_32.h
@@ -20,7 +20,7 @@
* - Bit 9 is reserved by everyone and used by _PAGE_PROTNONE.
*
* - Bits 10 and 11 are low bits of the PPN that are reserved on >= 4K pages.
- * Bit 10 is used for _PAGE_ACCESSED, bit 11 remains unused.
+ * Bit 10 is used for _PAGE_ACCESSED, and bit 11 is used for _PAGE_SPECIAL.
*
* - On 29 bit platforms, bits 31 to 29 are used for the space attributes
* and timing control which (together with bit 0) are moved into the
@@ -52,6 +52,7 @@
#define _PAGE_PROTNONE 0x200 /* software: if not present */
#define _PAGE_ACCESSED 0x400 /* software: page referenced */
#define _PAGE_FILE _PAGE_WT /* software: pagecache or swap? */
+#define _PAGE_SPECIAL 0x800 /* software: special page */
#define _PAGE_SZ_MASK (_PAGE_SZ0 | _PAGE_SZ1)
#define _PAGE_PR_MASK (_PAGE_RW | _PAGE_USER)
@@ -148,8 +149,12 @@
# define _PAGE_SZHUGE (_PAGE_FLAGS_HARD)
#endif
+/*
+ * Mask of bits that are to be preserved accross pgprot changes.
+ */
#define _PAGE_CHG_MASK \
- (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY)
+ (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | \
+ _PAGE_DIRTY | _PAGE_SPECIAL)
#ifndef __ASSEMBLY__
@@ -328,7 +333,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
#define pte_dirty(pte) ((pte).pte_low & _PAGE_DIRTY)
#define pte_young(pte) ((pte).pte_low & _PAGE_ACCESSED)
#define pte_file(pte) ((pte).pte_low & _PAGE_FILE)
-#define pte_special(pte) (0)
+#define pte_special(pte) ((pte).pte_low & _PAGE_SPECIAL)
#ifdef CONFIG_X2TLB
#define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE)
@@ -358,8 +363,9 @@ 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);
+PTE_BIT_FUNC(low, mkspecial, |= _PAGE_SPECIAL);
-static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+#define __HAVE_ARCH_PTE_SPECIAL
/*
* Macro and implementation to make a page protection as uncachable.
diff --git a/arch/sh/include/asm/sections.h b/arch/sh/include/asm/sections.h
index 01a4076a371..a78701da775 100644
--- a/arch/sh/include/asm/sections.h
+++ b/arch/sh/include/asm/sections.h
@@ -7,6 +7,7 @@ extern void __nosave_begin, __nosave_end;
extern long __machvec_start, __machvec_end;
extern char __uncached_start, __uncached_end;
extern char _ebss[];
+extern char __start_eh_frame[], __stop_eh_frame[];
#endif /* __ASM_SH_SECTIONS_H */
diff --git a/arch/sh/include/asm/stacktrace.h b/arch/sh/include/asm/stacktrace.h
new file mode 100644
index 00000000000..79701821371
--- /dev/null
+++ b/arch/sh/include/asm/stacktrace.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009 Matt Fleming
+ *
+ * Based on:
+ * The x86 implementation - arch/x86/include/asm/stacktrace.h
+ */
+#ifndef _ASM_SH_STACKTRACE_H
+#define _ASM_SH_STACKTRACE_H
+
+/* Generic stack tracer with callbacks */
+
+struct stacktrace_ops {
+ void (*warning)(void *data, char *msg);
+ /* msg must contain %s for the symbol */
+ void (*warning_symbol)(void *data, char *msg, unsigned long symbol);
+ void (*address)(void *data, unsigned long address, int reliable);
+ /* On negative return stop dumping */
+ int (*stack)(void *data, char *name);
+};
+
+void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
+ unsigned long *stack,
+ const struct stacktrace_ops *ops, void *data);
+
+#endif /* _ASM_SH_STACKTRACE_H */
diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h
index b1b995370e7..5c8ea28ff7a 100644
--- a/arch/sh/include/asm/suspend.h
+++ b/arch/sh/include/asm/suspend.h
@@ -10,6 +10,15 @@ struct swsusp_arch_regs {
struct pt_regs user_regs;
unsigned long bank1_regs[8];
};
+
+void sh_mobile_call_standby(unsigned long mode);
+
+#ifdef CONFIG_CPU_IDLE
+void sh_mobile_setup_cpuidle(void);
+#else
+static inline void sh_mobile_setup_cpuidle(void) {}
+#endif
+
#endif
/* flags passed to assembly suspend code */
diff --git a/arch/sh/include/asm/syscall_32.h b/arch/sh/include/asm/syscall_32.h
index 6f83f2cc45c..7d80df4f09c 100644
--- a/arch/sh/include/asm/syscall_32.h
+++ b/arch/sh/include/asm/syscall_32.h
@@ -65,6 +65,7 @@ static inline void syscall_get_arguments(struct task_struct *task,
case 3: args[2] = regs->regs[6];
case 2: args[1] = regs->regs[5];
case 1: args[0] = regs->regs[4];
+ case 0:
break;
default:
BUG();
diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h
index d570ac2e5cb..5123bcaa850 100644
--- a/arch/sh/include/asm/thread_info.h
+++ b/arch/sh/include/asm/thread_info.h
@@ -97,7 +97,7 @@ static inline struct thread_info *current_thread_info(void)
extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
extern void free_thread_info(struct thread_info *ti);
-
+
#endif /* THREAD_SHIFT < PAGE_SHIFT */
#endif /* __ASSEMBLY__ */
@@ -116,6 +116,7 @@ extern void free_thread_info(struct thread_info *ti);
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
#define TIF_SECCOMP 6 /* secure computing */
#define TIF_NOTIFY_RESUME 7 /* callback before returning to user */
+#define TIF_SYSCALL_FTRACE 8 /* for ftrace syscall instrumentation */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 18
@@ -129,25 +130,27 @@ extern void free_thread_info(struct thread_info *ti);
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
+#define _TIF_SYSCALL_FTRACE (1 << TIF_SYSCALL_FTRACE)
#define _TIF_USEDFPU (1 << TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_FREEZE (1 << TIF_FREEZE)
/*
- * _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within a byte, or we
+ * _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within 2 bytes, or we
* blow the tst immediate size constraints and need to fix up
* arch/sh/kernel/entry-common.S.
*/
/* work to do in syscall trace */
#define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
- _TIF_SYSCALL_AUDIT | _TIF_SECCOMP)
+ _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
+ _TIF_SYSCALL_FTRACE)
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \
_TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \
_TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK | \
- _TIF_NOTIFY_RESUME)
+ _TIF_NOTIFY_RESUME | _TIF_SYSCALL_FTRACE)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
diff --git a/arch/sh/include/asm/unwinder.h b/arch/sh/include/asm/unwinder.h
new file mode 100644
index 00000000000..3dc551453e2
--- /dev/null
+++ b/arch/sh/include/asm/unwinder.h
@@ -0,0 +1,25 @@
+#ifndef _LINUX_UNWINDER_H
+#define _LINUX_UNWINDER_H
+
+#include <asm/stacktrace.h>
+
+struct unwinder {
+ const char *name;
+ struct list_head list;
+ int rating;
+ void (*dump)(struct task_struct *, struct pt_regs *,
+ unsigned long *, const struct stacktrace_ops *, void *);
+};
+
+extern int unwinder_init(void);
+extern int unwinder_register(struct unwinder *);
+
+extern void unwind_stack(struct task_struct *, struct pt_regs *,
+ unsigned long *, const struct stacktrace_ops *,
+ void *);
+
+extern void stack_reader_dump(struct task_struct *, struct pt_regs *,
+ unsigned long *, const struct stacktrace_ops *,
+ void *);
+
+#endif /* _LINUX_UNWINDER_H */
diff --git a/arch/sh/include/asm/vmlinux.lds.h b/arch/sh/include/asm/vmlinux.lds.h
new file mode 100644
index 00000000000..244ec4ad9a7
--- /dev/null
+++ b/arch/sh/include/asm/vmlinux.lds.h
@@ -0,0 +1,17 @@
+#ifndef __ASM_SH_VMLINUX_LDS_H
+#define __ASM_SH_VMLINUX_LDS_H
+
+#include <asm-generic/vmlinux.lds.h>
+
+#ifdef CONFIG_DWARF_UNWINDER
+#define DWARF_EH_FRAME \
+ .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start_eh_frame) = .; \
+ *(.eh_frame) \
+ VMLINUX_SYMBOL(__stop_eh_frame) = .; \
+ }
+#else
+#define DWARF_EH_FRAME
+#endif
+
+#endif /* __ASM_SH_VMLINUX_LDS_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
index 0ed5178fed6..f0886bc880e 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
@@ -16,7 +16,8 @@
#define DMAE0_IRQ 38
#define SH_DMAC_BASE0 0xFF608020
#define SH_DMARS_BASE 0xFF609000
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7724)
#define DMTE0_IRQ 48 /* DMAC0A*/
#define DMTE4_IRQ 40 /* DMAC0B */
#define DMTE6_IRQ 42
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7722.h b/arch/sh/include/cpu-sh4/cpu/sh7722.h
index 738ea43c503..48560407cbe 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7722.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7722.h
@@ -221,4 +221,18 @@ enum {
GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYOUT5_IN5,
};
+enum {
+ HWBLK_UNKNOWN = 0,
+ HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_URAM, HWBLK_XYMEM,
+ HWBLK_INTC, HWBLK_DMAC, HWBLK_SHYWAY, HWBLK_HUDI,
+ HWBLK_UBC, HWBLK_TMU, HWBLK_CMT, HWBLK_RWDT, HWBLK_FLCTL,
+ HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, HWBLK_SIO,
+ HWBLK_SIOF0, HWBLK_SIOF1, HWBLK_IIC, HWBLK_RTC,
+ HWBLK_TPU, HWBLK_IRDA, HWBLK_SDHI, HWBLK_SIM, HWBLK_KEYSC,
+ HWBLK_TSIF, HWBLK_USBF, HWBLK_2DG, HWBLK_SIU, HWBLK_VOU,
+ HWBLK_JPU, HWBLK_BEU, HWBLK_CEU, HWBLK_VEU, HWBLK_VPU,
+ HWBLK_LCDC,
+ HWBLK_NR,
+};
+
#endif /* __ASM_SH7722_H__ */
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7723.h b/arch/sh/include/cpu-sh4/cpu/sh7723.h
index 14c8ca93678..9b36fae7232 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7723.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7723.h
@@ -265,4 +265,21 @@ enum {
GPIO_FN_IDEA1, GPIO_FN_IDEA0,
};
+enum {
+ HWBLK_UNKNOWN = 0,
+ HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_L2C, HWBLK_ILMEM, HWBLK_FPU,
+ HWBLK_INTC, HWBLK_DMAC0, HWBLK_SHYWAY,
+ HWBLK_HUDI, HWBLK_DBG, HWBLK_UBC, HWBLK_SUBC,
+ HWBLK_TMU0, HWBLK_CMT, HWBLK_RWDT, HWBLK_DMAC1, HWBLK_TMU1,
+ HWBLK_FLCTL,
+ HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2,
+ HWBLK_SCIF3, HWBLK_SCIF4, HWBLK_SCIF5,
+ HWBLK_MSIOF0, HWBLK_MSIOF1, HWBLK_MERAM, HWBLK_IIC, HWBLK_RTC,
+ HWBLK_ATAPI, HWBLK_ADC, HWBLK_TPU, HWBLK_IRDA, HWBLK_TSIF, HWBLK_ICB,
+ HWBLK_SDHI0, HWBLK_SDHI1, HWBLK_KEYSC, HWBLK_USB,
+ HWBLK_2DG, HWBLK_SIU, HWBLK_VEU2H1, HWBLK_VOU, HWBLK_BEU, HWBLK_CEU,
+ HWBLK_VEU2H0, HWBLK_VPU, HWBLK_LCDC,
+ HWBLK_NR,
+};
+
#endif /* __ASM_SH7723_H__ */
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7724.h b/arch/sh/include/cpu-sh4/cpu/sh7724.h
index 66fd1184359..0cd1f71a111 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7724.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7724.h
@@ -266,4 +266,21 @@ enum {
GPIO_FN_INTC_IRQ1, GPIO_FN_INTC_IRQ0,
};
+enum {
+ HWBLK_UNKNOWN = 0,
+ HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_RSMEM, HWBLK_ILMEM, HWBLK_L2C,
+ HWBLK_FPU, HWBLK_INTC, HWBLK_DMAC0, HWBLK_SHYWAY,
+ HWBLK_HUDI, HWBLK_DBG, HWBLK_UBC,
+ HWBLK_TMU0, HWBLK_CMT, HWBLK_RWDT, HWBLK_DMAC1, HWBLK_TMU1,
+ HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, HWBLK_SCIF3,
+ HWBLK_SCIF4, HWBLK_SCIF5, HWBLK_MSIOF0, HWBLK_MSIOF1,
+ HWBLK_KEYSC, HWBLK_RTC, HWBLK_IIC0, HWBLK_IIC1,
+ HWBLK_MMC, HWBLK_ETHER, HWBLK_ATAPI, HWBLK_TPU, HWBLK_IRDA,
+ HWBLK_TSIF, HWBLK_USB1, HWBLK_USB0, HWBLK_2DG,
+ HWBLK_SDHI0, HWBLK_SDHI1, HWBLK_VEU1, HWBLK_CEU1, HWBLK_BEU1,
+ HWBLK_2DDMAC, HWBLK_SPU, HWBLK_JPU, HWBLK_VOU,
+ HWBLK_BEU0, HWBLK_CEU0, HWBLK_VEU0, HWBLK_VPU, HWBLK_LCDC,
+ HWBLK_NR,
+};
+
#endif /* __ASM_SH7724_H__ */
diff --git a/arch/sh/include/mach-common/mach/migor.h b/arch/sh/include/mach-common/mach/migor.h
deleted file mode 100644
index e451f0229e0..00000000000
--- a/arch/sh/include/mach-common/mach/migor.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef __ASM_SH_MIGOR_H
-#define __ASM_SH_MIGOR_H
-
-/*
- * linux/include/asm-sh/migor.h
- *
- * Copyright (C) 2008 Renesas Solutions
- *
- * Portions Copyright (C) 2007 Nobuhiro Iwamatsu
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
-#include <asm/addrspace.h>
-
-/* GPIO */
-#define PORT_PACR 0xa4050100
-#define PORT_PDCR 0xa4050106
-#define PORT_PECR 0xa4050108
-#define PORT_PHCR 0xa405010e
-#define PORT_PJCR 0xa4050110
-#define PORT_PKCR 0xa4050112
-#define PORT_PLCR 0xa4050114
-#define PORT_PMCR 0xa4050116
-#define PORT_PRCR 0xa405011c
-#define PORT_PTCR 0xa4050140
-#define PORT_PUCR 0xa4050142
-#define PORT_PVCR 0xa4050144
-#define PORT_PWCR 0xa4050146
-#define PORT_PXCR 0xa4050148
-#define PORT_PYCR 0xa405014a
-#define PORT_PZCR 0xa405014c
-#define PORT_PADR 0xa4050120
-#define PORT_PHDR 0xa405012e
-#define PORT_PTDR 0xa4050160
-#define PORT_PWDR 0xa4050166
-
-#define PORT_HIZCRA 0xa4050158
-#define PORT_HIZCRC 0xa405015c
-
-#define PORT_MSELCRB 0xa4050182
-
-#define PORT_PSELA 0xa405014e
-#define PORT_PSELB 0xa4050150
-#define PORT_PSELC 0xa4050152
-#define PORT_PSELD 0xa4050154
-#define PORT_PSELE 0xa4050156
-
-#define PORT_HIZCRA 0xa4050158
-#define PORT_HIZCRB 0xa405015a
-#define PORT_HIZCRC 0xa405015c
-
-#define BSC_CS4BCR 0xfec10010
-#define BSC_CS6ABCR 0xfec1001c
-#define BSC_CS4WCR 0xfec10030
-
-#include <video/sh_mobile_lcdc.h>
-
-int migor_lcd_qvga_setup(void *board_data, void *sys_ops_handle,
- struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
-
-#endif /* __ASM_SH_MIGOR_H */
diff --git a/arch/sh/include/mach-common/mach/romimage.h b/arch/sh/include/mach-common/mach/romimage.h
new file mode 100644
index 00000000000..267e24112d8
--- /dev/null
+++ b/arch/sh/include/mach-common/mach/romimage.h
@@ -0,0 +1 @@
+/* do nothing here by default */
diff --git a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
new file mode 100644
index 00000000000..174374e1954
--- /dev/null
+++ b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
@@ -0,0 +1,21 @@
+#ifndef __ASM_SH_KFR2R09_H
+#define __ASM_SH_KFR2R09_H
+
+#include <video/sh_mobile_lcdc.h>
+
+#ifdef CONFIG_FB_SH_MOBILE_LCDC
+void kfr2r09_lcd_on(void *board_data);
+void kfr2r09_lcd_off(void *board_data);
+int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle,
+ struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
+#else
+static inline void kfr2r09_lcd_on(void *board_data) {}
+static inline void kfr2r09_lcd_off(void *board_data) {}
+static inline int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle,
+ struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
+{
+ return -ENODEV;
+}
+#endif
+
+#endif /* __ASM_SH_KFR2R09_H */
diff --git a/arch/sh/include/mach-kfr2r09/mach/partner-jet-setup.txt b/arch/sh/include/mach-kfr2r09/mach/partner-jet-setup.txt
new file mode 100644
index 00000000000..9c85088728a
--- /dev/null
+++ b/arch/sh/include/mach-kfr2r09/mach/partner-jet-setup.txt
@@ -0,0 +1,134 @@
+LIST "partner-jet-setup.txt - 20090729 Magnus Damm"
+LIST "set up enough of the kfr2r09 hardware to boot the kernel"
+
+LIST "zImage (RAM boot)"
+LIST "This script can be used to boot the kernel from RAM via JTAG:"
+LIST "> < partner-jet-setup.txt"
+LIST "> RD zImage, 0xa8800000"
+LIST "> G=0xa8800000"
+
+LIST "romImage (Flash boot)"
+LIST "Use the following command to burn the zImage to flash via JTAG:"
+LIST "> RD romImage, 0"
+
+LIST "--------------------------------"
+
+LIST "disable watchdog"
+EW 0xa4520004, 0xa507
+
+LIST "select mode for cs5 + cs6"
+ED 0xff800020, 0xa5a50001
+ED 0xfec10000, 0x0000001b
+
+LIST "setup clocks"
+ED 0xa4150004, 0x00000050
+ED 0xa4150000, 0x91053508
+WAIT 1
+ED 0xa4150024, 0x00005000
+
+LIST "setup pins"
+EB 0xa4050120, 0x00
+EB 0xa4050122, 0x00
+EB 0xa4050124, 0x00
+EB 0xa4050126, 0x00
+EB 0xa4050128, 0xA0
+EB 0xa405012A, 0x10
+EB 0xa405012C, 0x00
+EB 0xa405012E, 0x00
+EB 0xa4050130, 0x00
+EB 0xa4050132, 0x00
+EB 0xa4050134, 0x01
+EB 0xa4050136, 0x40
+EB 0xa4050138, 0x00
+EB 0xa405013A, 0x00
+EB 0xa405013C, 0x00
+EB 0xa405013E, 0x20
+EB 0xa4050160, 0x00
+EB 0xa4050162, 0x40
+EB 0xa4050164, 0x03
+EB 0xa4050166, 0x00
+EB 0xa4050168, 0x00
+EB 0xa405016A, 0x00
+EB 0xa405016C, 0x00
+
+EW 0xa405014E, 0x5660
+EW 0xa4050150, 0x0145
+EW 0xa4050152, 0x1550
+EW 0xa4050154, 0x0200
+EW 0xa4050156, 0x0040
+
+EW 0xa4050158, 0x0000
+EW 0xa405015a, 0x0000
+EW 0xa405015c, 0x0000
+EW 0xa405015e, 0x0000
+
+EW 0xa4050180, 0x0000
+EW 0xa4050182, 0x8002
+EW 0xa4050184, 0x0000
+
+EW 0xa405018a, 0x9991
+EW 0xa405018c, 0x8011
+EW 0xa405018e, 0x9550
+
+EW 0xa4050100, 0x0000
+EW 0xa4050102, 0x5540
+EW 0xa4050104, 0x0000
+EW 0xa4050106, 0x0000
+EW 0xa4050108, 0x4550
+EW 0xa405010a, 0x0130
+EW 0xa405010c, 0x0555
+EW 0xa405010e, 0x0000
+EW 0xa4050110, 0x0000
+EW 0xa4050112, 0xAAA8
+EW 0xa4050114, 0x8305
+EW 0xa4050116, 0x10F0
+EW 0xa4050118, 0x0F50
+EW 0xa405011a, 0x0000
+EW 0xa405011c, 0x0000
+EW 0xa405011e, 0x0555
+EW 0xa4050140, 0x0000
+EW 0xa4050142, 0x5141
+EW 0xa4050144, 0x5005
+EW 0xa4050146, 0xAAA9
+EW 0xa4050148, 0xFAA9
+EW 0xa405014a, 0x3000
+EW 0xa405014c, 0x0000
+
+LIST "setup sdram"
+ED 0xFD000108, 0x40000301
+ED 0xFD000020, 0x011B0002
+ED 0xFD000030, 0x03060E02
+ED 0xFD000034, 0x01020102
+ED 0xFD000038, 0x01090406
+ED 0xFD000008, 0x00000004
+ED 0xFD000040, 0x00000001
+ED 0xFD000040, 0x00000000
+ED 0xFD000018, 0x00000001
+
+WAIT 1
+
+ED 0xFD000014, 0x00000002
+ED 0xFD000060, 0x00000032
+ED 0xFD000060, 0x00020000
+ED 0xFD000014, 0x00000004
+ED 0xFD000014, 0x00000004
+ED 0xFD000010, 0x00000001
+ED 0xFD000044, 0x000004AF
+ED 0xFD000048, 0x20CF0037
+
+LIST "read 16 bytes from sdram"
+DD 0xa8000000, 0xa8000000, 1
+DD 0xa8000004, 0xa8000004, 1
+DD 0xa8000008, 0xa8000008, 1
+DD 0xa800000c, 0xa800000c, 1
+
+ED 0xFD000014, 0x00000002
+ED 0xFD000014, 0x00000004
+ED 0xFD000108, 0x40000300
+ED 0xFD000040, 0x00010000
+
+LIST "write to internal ram"
+ED 0xfd8007fc, 0
+
+LIST "setup cache"
+ED 0xff00001c, 0x0000090b
diff --git a/arch/sh/include/mach-kfr2r09/mach/romimage.h b/arch/sh/include/mach-kfr2r09/mach/romimage.h
new file mode 100644
index 00000000000..f5aa8e16770
--- /dev/null
+++ b/arch/sh/include/mach-kfr2r09/mach/romimage.h
@@ -0,0 +1,75 @@
+/* kfr2r09 board specific boot code:
+ * converts the "partner-jet-script.txt" script into assembly
+ * the assembly code is the first code to be executed in the romImage
+ */
+
+/* The LIST command is used to include comments in the script */
+.macro LIST comment
+.endm
+
+/* The ED command is used to write a 32-bit word */
+.macro ED, addr, data
+ mov.l 1f ,r1
+ mov.l 2f ,r0
+ mov.l r0, @r1
+ bra 3f
+ nop
+ .align 2
+1: .long \addr
+2: .long \data
+3:
+.endm
+
+/* The EW command is used to write a 16-bit word */
+.macro EW, addr, data
+ mov.l 1f ,r1
+ mov.l 2f ,r0
+ mov.w r0, @r1
+ bra 3f
+ nop
+ .align 2
+1: .long \addr
+2: .long \data
+3:
+.endm
+
+/* The EB command is used to write an 8-bit word */
+.macro EB, addr, data
+ mov.l 1f ,r1
+ mov.l 2f ,r0
+ mov.b r0, @r1
+ bra 3f
+ nop
+ .align 2
+1: .long \addr
+2: .long \data
+3:
+.endm
+
+/* The WAIT command is used to delay the execution */
+.macro WAIT, time
+ mov.l 2f ,r3
+1:
+ nop
+ tst r3, r3
+ bf/s 1b
+ dt r3
+ bra 3f
+ nop
+ .align 2
+2: .long \time * 100
+3:
+.endm
+
+/* The DD command is used to read a 32-bit word */
+.macro DD, addr, addr2, nr
+ mov.l 1f ,r1
+ mov.l @r1, r0
+ bra 2f
+ nop
+ .align 2
+1: .long \addr
+2:
+.endm
+
+#include "partner-jet-setup.txt"
diff --git a/arch/sh/include/mach-migor/mach/migor.h b/arch/sh/include/mach-migor/mach/migor.h
new file mode 100644
index 00000000000..cee6cb88e02
--- /dev/null
+++ b/arch/sh/include/mach-migor/mach/migor.h
@@ -0,0 +1,14 @@
+#ifndef __ASM_SH_MIGOR_H
+#define __ASM_SH_MIGOR_H
+
+#define PORT_MSELCRB 0xa4050182
+#define BSC_CS4BCR 0xfec10010
+#define BSC_CS6ABCR 0xfec1001c
+#define BSC_CS4WCR 0xfec10030
+
+#include <video/sh_mobile_lcdc.h>
+
+int migor_lcd_qvga_setup(void *board_data, void *sys_ops_handle,
+ struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
+
+#endif /* __ASM_SH_MIGOR_H */
diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32
index 9411e3e31e6..f2245ebf0b3 100644
--- a/arch/sh/kernel/Makefile_32
+++ b/arch/sh/kernel/Makefile_32
@@ -9,10 +9,10 @@ ifdef CONFIG_FUNCTION_TRACER
CFLAGS_REMOVE_ftrace.o = -pg
endif
-obj-y := debugtraps.o idle.o io.o io_generic.o irq.o \
+obj-y := debugtraps.o dumpstack.o idle.o io.o io_generic.o irq.o \
machvec.o process_32.o ptrace_32.o setup.o signal_32.o \
- sys_sh.o sys_sh32.o syscalls_32.o time.o topology.o \
- traps.o traps_32.o
+ sys_sh.o sys_sh32.o syscalls_32.o time.o topology.o \
+ traps.o traps_32.o unwinder.o
obj-y += cpu/
obj-$(CONFIG_VSYSCALL) += vsyscall/
@@ -29,8 +29,11 @@ obj-$(CONFIG_IO_TRAPPED) += io_trapped.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_GENERIC_GPIO) += gpio.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
+obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_DUMP_CODE) += disassemble.o
obj-$(CONFIG_HIBERNATION) += swsusp.o
+obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o
obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o
diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64
index 67b9f6c6326..639ee514266 100644
--- a/arch/sh/kernel/Makefile_64
+++ b/arch/sh/kernel/Makefile_64
@@ -2,7 +2,7 @@ extra-y := head_64.o init_task.o vmlinux.lds
obj-y := debugtraps.o idle.o io.o io_generic.o irq.o machvec.o process_64.o \
ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \
- syscalls_64.o time.o topology.o traps.o traps_64.o
+ syscalls_64.o time.o topology.o traps.o traps_64.o unwinder.o
obj-y += cpu/
obj-$(CONFIG_SMP) += smp.o
@@ -13,6 +13,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_IO_TRAPPED) += io_trapped.o
obj-$(CONFIG_GENERIC_GPIO) += gpio.o
+obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o
obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o
diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c
index 99aceb28ee2..d218e808294 100644
--- a/arch/sh/kernel/asm-offsets.c
+++ b/arch/sh/kernel/asm-offsets.c
@@ -26,6 +26,7 @@ int main(void)
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
+ DEFINE(TI_SIZE, sizeof(struct thread_info));
#ifdef CONFIG_HIBERNATION
DEFINE(PBE_ADDRESS, offsetof(struct pbe, address));
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index eecad7cbd61..3d6b9312dc4 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -19,4 +19,4 @@ obj-$(CONFIG_UBC_WAKEUP) += ubc.o
obj-$(CONFIG_SH_ADC) += adc.o
obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o
-obj-y += irq/ init.o clock.o
+obj-y += irq/ init.o clock.o hwblk.o
diff --git a/arch/sh/kernel/cpu/hwblk.c b/arch/sh/kernel/cpu/hwblk.c
new file mode 100644
index 00000000000..c0ad7d46e78
--- /dev/null
+++ b/arch/sh/kernel/cpu/hwblk.c
@@ -0,0 +1,155 @@
+#include <linux/clk.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <asm/clock.h>
+
+static DEFINE_SPINLOCK(hwblk_lock);
+
+static void hwblk_area_mod_cnt(struct hwblk_info *info,
+ int area, int counter, int value, int goal)
+{
+ struct hwblk_area *hap = info->areas + area;
+
+ hap->cnt[counter] += value;
+
+ if (hap->cnt[counter] != goal)
+ return;
+
+ if (hap->flags & HWBLK_AREA_FLAG_PARENT)
+ hwblk_area_mod_cnt(info, hap->parent, counter, value, goal);
+}
+
+
+static int __hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
+ int counter, int value, int goal)
+{
+ struct hwblk *hp = info->hwblks + hwblk;
+
+ hp->cnt[counter] += value;
+ if (hp->cnt[counter] == goal)
+ hwblk_area_mod_cnt(info, hp->area, counter, value, goal);
+
+ return hp->cnt[counter];
+}
+
+static void hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
+ int counter, int value, int goal)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hwblk_lock, flags);
+ __hwblk_mod_cnt(info, hwblk, counter, value, goal);
+ spin_unlock_irqrestore(&hwblk_lock, flags);
+}
+
+void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int counter)
+{
+ hwblk_mod_cnt(info, hwblk, counter, 1, 1);
+}
+
+void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int counter)
+{
+ hwblk_mod_cnt(info, hwblk, counter, -1, 0);
+}
+
+void hwblk_enable(struct hwblk_info *info, int hwblk)
+{
+ struct hwblk *hp = info->hwblks + hwblk;
+ unsigned long tmp;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&hwblk_lock, flags);
+
+ ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, 1, 1);
+ if (ret == 1) {
+ tmp = __raw_readl(hp->mstp);
+ tmp &= ~(1 << hp->bit);
+ __raw_writel(tmp, hp->mstp);
+ }
+
+ spin_unlock_irqrestore(&hwblk_lock, flags);
+}
+
+void hwblk_disable(struct hwblk_info *info, int hwblk)
+{
+ struct hwblk *hp = info->hwblks + hwblk;
+ unsigned long tmp;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&hwblk_lock, flags);
+
+ ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, -1, 0);
+ if (ret == 0) {
+ tmp = __raw_readl(hp->mstp);
+ tmp |= 1 << hp->bit;
+ __raw_writel(tmp, hp->mstp);
+ }
+
+ spin_unlock_irqrestore(&hwblk_lock, flags);
+}
+
+struct hwblk_info *hwblk_info;
+
+int __init hwblk_register(struct hwblk_info *info)
+{
+ hwblk_info = info;
+ return 0;
+}
+
+int __init __weak arch_hwblk_init(void)
+{
+ return 0;
+}
+
+int __weak arch_hwblk_sleep_mode(void)
+{
+ return SUSP_SH_SLEEP;
+}
+
+int __init hwblk_init(void)
+{
+ return arch_hwblk_init();
+}
+
+/* allow clocks to enable and disable hardware blocks */
+static int sh_hwblk_clk_enable(struct clk *clk)
+{
+ if (!hwblk_info)
+ return -ENOENT;
+
+ hwblk_enable(hwblk_info, clk->arch_flags);
+ return 0;
+}
+
+static void sh_hwblk_clk_disable(struct clk *clk)
+{
+ if (hwblk_info)
+ hwblk_disable(hwblk_info, clk->arch_flags);
+}
+
+static struct clk_ops sh_hwblk_clk_ops = {
+ .enable = sh_hwblk_clk_enable,
+ .disable = sh_hwblk_clk_disable,
+ .recalc = followparent_recalc,
+};
+
+int __init sh_hwblk_clk_register(struct clk *clks, int nr)
+{
+ struct clk *clkp;
+ int ret = 0;
+ int k;
+
+ for (k = 0; !ret && (k < nr); k++) {
+ clkp = clks + k;
+ clkp->ops = &sh_hwblk_clk_ops;
+ ret |= clk_register(clkp);
+ }
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index ad85421099c..d40b9db5be0 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -3,7 +3,7 @@
*
* CPU init code
*
- * Copyright (C) 2002 - 2007 Paul Mundt
+ * Copyright (C) 2002 - 2009 Paul Mundt
* Copyright (C) 2003 Richard Curnow
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -62,6 +62,37 @@ static void __init speculative_execution_init(void)
#define speculative_execution_init() do { } while (0)
#endif
+#ifdef CONFIG_CPU_SH4A
+#define EXPMASK 0xff2f0004
+#define EXPMASK_RTEDS (1 << 0)
+#define EXPMASK_BRDSSLP (1 << 1)
+#define EXPMASK_MMCAW (1 << 4)
+
+static void __init expmask_init(void)
+{
+ unsigned long expmask = __raw_readl(EXPMASK);
+
+ /*
+ * Future proofing.
+ *
+ * Disable support for slottable sleep instruction
+ * and non-nop instructions in the rte delay slot.
+ */
+ expmask &= ~(EXPMASK_RTEDS | EXPMASK_BRDSSLP);
+
+ /*
+ * Enable associative writes to the memory-mapped cache array
+ * until the cache flush ops have been rewritten.
+ */
+ expmask |= EXPMASK_MMCAW;
+
+ __raw_writel(expmask, EXPMASK);
+ ctrl_barrier();
+}
+#else
+#define expmask_init() do { } while (0)
+#endif
+
/* 2nd-level cache init */
void __uses_jump_to_uncached __attribute__ ((weak)) l2_cache_init(void)
{
@@ -321,4 +352,5 @@ asmlinkage void __init sh_cpu_init(void)
#endif
speculative_execution_init();
+ expmask_init();
}
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index becc54c4569..c8a4331d9b8 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -227,8 +227,9 @@ ENTRY(sh_bios_handler)
mov.l @r15+, r14
add #8,r15
lds.l @r15+, pr
+ mov.l @r15+,r15
rte
- mov.l @r15+,r15
+ nop
.align 2
1: .long gdb_vbr_vector
#endif /* CONFIG_SH_STANDARD_BIOS */
diff --git a/arch/sh/kernel/cpu/sh2a/entry.S b/arch/sh/kernel/cpu/sh2a/entry.S
index ab3903eeda5..222742ddc0d 100644
--- a/arch/sh/kernel/cpu/sh2a/entry.S
+++ b/arch/sh/kernel/cpu/sh2a/entry.S
@@ -176,8 +176,9 @@ ENTRY(sh_bios_handler)
movml.l @r15+,r14
add #8,r15
lds.l @r15+, pr
+ mov.l @r15+,r15
rte
- mov.l @r15+,r15
+ nop
.align 2
1: .long gdb_vbr_vector
#endif /* CONFIG_SH_STANDARD_BIOS */
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 3cb531f233f..67ad6467c69 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -137,6 +137,7 @@ ENTRY(tlb_protection_violation_store)
mov #1, r5
call_dpf:
+ setup_frame_reg
mov.l 1f, r0
mov r5, r8
mov.l @r0, r6
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index ebdd391d5f4..12cddf4c721 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -25,9 +25,9 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o
clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o hwblk-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o hwblk-sh7723.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o hwblk-sh7724.o
clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o
clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index 40f859354f7..5b1bbbe63b1 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -22,6 +22,8 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <asm/clock.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7722.h>
/* SH7722 registers */
#define FRQCR 0xa4150000
@@ -30,9 +32,6 @@
#define SCLKBCR 0xa415000c
#define IRDACLKCR 0xa4150018
#define PLLCR 0xa4150024
-#define MSTPCR0 0xa4150030
-#define MSTPCR1 0xa4150034
-#define MSTPCR2 0xa4150038
#define DLLFRQ 0xa4150050
/* Fixed 32 KHz root clock for RTC and Power Management purposes */
@@ -140,35 +139,37 @@ struct clk div6_clks[] = {
SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
};
-#define MSTP(_str, _parent, _reg, _bit, _flags) \
- SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags)
+#define R_CLK &r_clk
+#define P_CLK &div4_clks[DIV4_P]
+#define B_CLK &div4_clks[DIV4_B]
+#define U_CLK &div4_clks[DIV4_U]
static struct clk mstp_clks[] = {
- MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
- MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
- MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0),
- MSTP("cmt0", &r_clk, MSTPCR0, 14, 0),
- MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0),
- MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0),
- MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0),
- MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0),
- MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0),
-
- MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0),
- MSTP("rtc0", &r_clk, MSTPCR1, 8, 0),
-
- MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0),
- MSTP("keysc0", &r_clk, MSTPCR2, 14, 0),
- MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0),
- MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 9, 0),
- MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0),
- MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0),
- MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
- MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0),
- MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0),
- MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
- MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
- MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0),
+ SH_HWBLK_CLK("uram0", -1, U_CLK, HWBLK_URAM, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("xymem0", -1, B_CLK, HWBLK_XYMEM, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU, 0),
+ SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
+ SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
+ SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
+ SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
+ SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
+ SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
+
+ SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
+ SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
+
+ SH_HWBLK_CLK("sdhi0", -1, P_CLK, HWBLK_SDHI, 0),
+ SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
+ SH_HWBLK_CLK("usbf0", -1, P_CLK, HWBLK_USBF, 0),
+ SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
+ SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
+ SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
+ SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
+ SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
+ SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0),
};
int __init arch_clk_init(void)
@@ -191,7 +192,7 @@ int __init arch_clk_init(void)
ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
if (!ret)
- ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+ ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
return ret;
}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
index e67c2678b8a..e5c63911403 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
@@ -22,6 +22,8 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <asm/clock.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7723.h>
/* SH7723 registers */
#define FRQCR 0xa4150000
@@ -30,9 +32,6 @@
#define SCLKBCR 0xa415000c
#define IRDACLKCR 0xa4150018
#define PLLCR 0xa4150024
-#define MSTPCR0 0xa4150030
-#define MSTPCR1 0xa4150034
-#define MSTPCR2 0xa4150038
#define DLLFRQ 0xa4150050
/* Fixed 32 KHz root clock for RTC and Power Management purposes */
@@ -140,60 +139,64 @@ struct clk div6_clks[] = {
SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
};
-#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \
- SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT)
+#define R_CLK (&r_clk)
+#define P_CLK (&div4_clks[DIV4_P])
+#define B_CLK (&div4_clks[DIV4_B])
+#define U_CLK (&div4_clks[DIV4_U])
+#define I_CLK (&div4_clks[DIV4_I])
+#define SH_CLK (&div4_clks[DIV4_SH])
static struct clk mstp_clks[] = {
/* See page 60 of Datasheet V1.0: Overview -> Block Diagram */
- MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0),
- MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0),
- MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0),
- MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 28, 1, 1, 0),
- MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0),
- MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0),
- MSTP("intc0", &div4_clks[DIV4_I], MSTPCR0, 22, 1, 1, 0),
- MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1),
- MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0),
- MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0),
- MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0),
- MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0),
- MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0),
- MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0),
- MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1),
- MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 11, 0, 1, 0),
- MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0),
- MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0),
- MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0),
- MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0),
- MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0),
- MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0),
- MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0),
- MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0),
- MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0),
- MSTP("meram0", &div4_clks[DIV4_SH], MSTPCR0, 0, 1, 1, 0),
-
- MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0),
- MSTP("rtc0", &r_clk, MSTPCR1, 8, 0, 0, 0),
-
- MSTP("atapi0", &div4_clks[DIV4_SH], MSTPCR2, 28, 0, 1, 0),
- MSTP("adc0", &div4_clks[DIV4_P], MSTPCR2, 27, 0, 1, 0),
- MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0),
- MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0),
- MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0),
- MSTP("icb0", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1),
- MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0),
- MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0),
- MSTP("keysc0", &r_clk, MSTPCR2, 14, 0, 0, 0),
- MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 11, 0, 1, 0),
- MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 10, 0, 1, 1),
- MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0, 1, 0),
- MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1),
- MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1),
- MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1),
- MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1),
- MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1),
- MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1),
- MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1),
+ SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("intc0", -1, I_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0),
+ SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0),
+ SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0),
+ SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0),
+ SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
+ SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
+ SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0),
+ SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0),
+ SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
+ SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
+ SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
+ SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
+ SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0),
+ SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0),
+ SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0),
+ SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0),
+ SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0),
+ SH_HWBLK_CLK("meram0", -1, SH_CLK, HWBLK_MERAM, 0),
+
+ SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
+ SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
+
+ SH_HWBLK_CLK("atapi0", -1, SH_CLK, HWBLK_ATAPI, 0),
+ SH_HWBLK_CLK("adc0", -1, P_CLK, HWBLK_ADC, 0),
+ SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0),
+ SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0),
+ SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0),
+ SH_HWBLK_CLK("icb0", -1, B_CLK, HWBLK_ICB, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0),
+ SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0),
+ SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
+ SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB, 0),
+ SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
+ SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
+ SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU2H1, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
+ SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
+ SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
+ SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU2H0, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0),
};
int __init arch_clk_init(void)
@@ -216,7 +219,7 @@ int __init arch_clk_init(void)
ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
if (!ret)
- ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+ ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
return ret;
}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
index 5d5c9b95288..34611d97378 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
@@ -22,6 +22,8 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <asm/clock.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7724.h>
/* SH7724 registers */
#define FRQCRA 0xa4150000
@@ -31,9 +33,6 @@
#define FCLKBCR 0xa415000c
#define IRDACLKCR 0xa4150018
#define PLLCR 0xa4150024
-#define MSTPCR0 0xa4150030
-#define MSTPCR1 0xa4150034
-#define MSTPCR2 0xa4150038
#define SPUCLKCR 0xa415003c
#define FLLFRQ 0xa4150050
#define LSTATS 0xa4150060
@@ -156,64 +155,67 @@ struct clk div6_clks[] = {
SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, 0),
};
-#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \
- SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT)
+#define R_CLK (&r_clk)
+#define P_CLK (&div4_clks[DIV4_P])
+#define B_CLK (&div4_clks[DIV4_B])
+#define I_CLK (&div4_clks[DIV4_I])
+#define SH_CLK (&div4_clks[DIV4_SH])
static struct clk mstp_clks[] = {
- MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0),
- MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0),
- MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0),
- MSTP("rs0", &div4_clks[DIV4_B], MSTPCR0, 28, 1, 1, 0),
- MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0),
- MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 26, 1, 1, 0),
- MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0),
- MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 1, 1, 0),
- MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1),
- MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0),
- MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0),
- MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0),
- MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0),
- MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0),
- MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0),
- MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1),
- MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0),
- MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0),
- MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0),
- MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0),
- MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0),
- MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0),
- MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0),
- MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0),
- MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0),
-
- MSTP("keysc0", &r_clk, MSTPCR1, 12, 0, 0, 0),
- MSTP("rtc0", &r_clk, MSTPCR1, 11, 0, 0, 0),
- MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0),
- MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 0, 1, 0),
-
- MSTP("mmc0", &div4_clks[DIV4_B], MSTPCR2, 29, 0, 1, 0),
- MSTP("eth0", &div4_clks[DIV4_B], MSTPCR2, 28, 0, 1, 0),
- MSTP("atapi0", &div4_clks[DIV4_B], MSTPCR2, 26, 0, 1, 0),
- MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0),
- MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0),
- MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0),
- MSTP("usb1", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1),
- MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 20, 0, 1, 1),
- MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 19, 0, 1, 1),
- MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0),
- MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0),
- MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 15, 1, 1, 1),
- MSTP("ceu1", &div4_clks[DIV4_B], MSTPCR2, 13, 0, 1, 1),
- MSTP("beu1", &div4_clks[DIV4_B], MSTPCR2, 12, 0, 1, 1),
- MSTP("2ddmac0", &div4_clks[DIV4_SH], MSTPCR2, 10, 0, 1, 1),
- MSTP("spu0", &div4_clks[DIV4_B], MSTPCR2, 9, 0, 1, 0),
- MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1),
- MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1),
- MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1),
- MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1),
- MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1),
- MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1),
- MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1),
+ SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("rs0", -1, B_CLK, HWBLK_RSMEM, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("intc0", -1, P_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0),
+ SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0),
+ SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0),
+ SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0),
+ SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
+ SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
+ SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0),
+ SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0),
+ SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
+ SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
+ SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
+ SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0),
+ SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0),
+ SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0),
+ SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0),
+ SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0),
+
+ SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
+ SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
+ SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC0, 0),
+ SH_HWBLK_CLK("i2c1", -1, P_CLK, HWBLK_IIC1, 0),
+
+ SH_HWBLK_CLK("mmc0", -1, B_CLK, HWBLK_MMC, 0),
+ SH_HWBLK_CLK("eth0", -1, B_CLK, HWBLK_ETHER, 0),
+ SH_HWBLK_CLK("atapi0", -1, B_CLK, HWBLK_ATAPI, 0),
+ SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0),
+ SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0),
+ SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0),
+ SH_HWBLK_CLK("usb1", -1, B_CLK, HWBLK_USB1, 0),
+ SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB0, 0),
+ SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
+ SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0),
+ SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0),
+ SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU1, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("ceu1", -1, B_CLK, HWBLK_CEU1, 0),
+ SH_HWBLK_CLK("beu1", -1, B_CLK, HWBLK_BEU1, 0),
+ SH_HWBLK_CLK("2ddmac0", -1, SH_CLK, HWBLK_2DDMAC, 0),
+ SH_HWBLK_CLK("spu0", -1, B_CLK, HWBLK_SPU, 0),
+ SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
+ SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU0, 0),
+ SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU0, 0),
+ SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU0, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
+ SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0),
};
int __init arch_clk_init(void)
@@ -236,7 +238,7 @@ int __init arch_clk_init(void)
ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
if (!ret)
- ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+ ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
return ret;
}
diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
new file mode 100644
index 00000000000..a288b5d9234
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
@@ -0,0 +1,106 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
+ *
+ * SH7722 hardware block support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7722.h>
+
+/* SH7722 registers */
+#define MSTPCR0 0xa4150030
+#define MSTPCR1 0xa4150034
+#define MSTPCR2 0xa4150038
+
+/* SH7722 Power Domains */
+enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
+static struct hwblk_area sh7722_hwblk_area[] = {
+ [CORE_AREA] = HWBLK_AREA(0, 0),
+ [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
+ [SUB_AREA] = HWBLK_AREA(0, 0),
+};
+
+/* Table mapping HWBLK to Module Stop Bit and Power Domain */
+static struct hwblk sh7722_hwblk[HWBLK_NR] = {
+ [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
+ [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
+ [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
+ [HWBLK_URAM] = HWBLK(MSTPCR0, 28, CORE_AREA),
+ [HWBLK_XYMEM] = HWBLK(MSTPCR0, 26, CORE_AREA),
+ [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
+ [HWBLK_DMAC] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
+ [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
+ [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
+ [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
+ [HWBLK_TMU] = HWBLK(MSTPCR0, 15, CORE_AREA),
+ [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
+ [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
+ [HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA),
+ [HWBLK_SCIF0] = HWBLK(MSTPCR0, 7, CORE_AREA),
+ [HWBLK_SCIF1] = HWBLK(MSTPCR0, 6, CORE_AREA),
+ [HWBLK_SCIF2] = HWBLK(MSTPCR0, 5, CORE_AREA),
+ [HWBLK_SIO] = HWBLK(MSTPCR0, 3, CORE_AREA),
+ [HWBLK_SIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
+ [HWBLK_SIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
+
+ [HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA),
+ [HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA),
+
+ [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
+ [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
+ [HWBLK_SDHI] = HWBLK(MSTPCR2, 18, CORE_AREA),
+ [HWBLK_SIM] = HWBLK(MSTPCR2, 16, CORE_AREA),
+ [HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA),
+ [HWBLK_TSIF] = HWBLK(MSTPCR2, 13, SUB_AREA),
+ [HWBLK_USBF] = HWBLK(MSTPCR2, 11, CORE_AREA),
+ [HWBLK_2DG] = HWBLK(MSTPCR2, 9, CORE_AREA_BM),
+ [HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA),
+ [HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
+ [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
+ [HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
+ [HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
+ [HWBLK_VEU] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
+ [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
+ [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
+};
+
+static struct hwblk_info sh7722_hwblk_info = {
+ .areas = sh7722_hwblk_area,
+ .nr_areas = ARRAY_SIZE(sh7722_hwblk_area),
+ .hwblks = sh7722_hwblk,
+ .nr_hwblks = ARRAY_SIZE(sh7722_hwblk),
+};
+
+int arch_hwblk_sleep_mode(void)
+{
+ if (!sh7722_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
+ return SUSP_SH_STANDBY | SUSP_SH_SF;
+
+ if (!sh7722_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
+ return SUSP_SH_SLEEP | SUSP_SH_SF;
+
+ return SUSP_SH_SLEEP;
+}
+
+int __init arch_hwblk_init(void)
+{
+ return hwblk_register(&sh7722_hwblk_info);
+}
diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
new file mode 100644
index 00000000000..a7f4684d203
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
@@ -0,0 +1,117 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
+ *
+ * SH7723 hardware block support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7723.h>
+
+/* SH7723 registers */
+#define MSTPCR0 0xa4150030
+#define MSTPCR1 0xa4150034
+#define MSTPCR2 0xa4150038
+
+/* SH7723 Power Domains */
+enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
+static struct hwblk_area sh7723_hwblk_area[] = {
+ [CORE_AREA] = HWBLK_AREA(0, 0),
+ [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
+ [SUB_AREA] = HWBLK_AREA(0, 0),
+};
+
+/* Table mapping HWBLK to Module Stop Bit and Power Domain */
+static struct hwblk sh7723_hwblk[HWBLK_NR] = {
+ [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
+ [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
+ [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
+ [HWBLK_L2C] = HWBLK(MSTPCR0, 28, CORE_AREA),
+ [HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA),
+ [HWBLK_FPU] = HWBLK(MSTPCR0, 24, CORE_AREA),
+ [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
+ [HWBLK_DMAC0] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
+ [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
+ [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
+ [HWBLK_DBG] = HWBLK(MSTPCR0, 18, CORE_AREA),
+ [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
+ [HWBLK_SUBC] = HWBLK(MSTPCR0, 16, CORE_AREA),
+ [HWBLK_TMU0] = HWBLK(MSTPCR0, 15, CORE_AREA),
+ [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
+ [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
+ [HWBLK_DMAC1] = HWBLK(MSTPCR0, 12, CORE_AREA_BM),
+ [HWBLK_TMU1] = HWBLK(MSTPCR0, 11, CORE_AREA),
+ [HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA),
+ [HWBLK_SCIF0] = HWBLK(MSTPCR0, 9, CORE_AREA),
+ [HWBLK_SCIF1] = HWBLK(MSTPCR0, 8, CORE_AREA),
+ [HWBLK_SCIF2] = HWBLK(MSTPCR0, 7, CORE_AREA),
+ [HWBLK_SCIF3] = HWBLK(MSTPCR0, 6, CORE_AREA),
+ [HWBLK_SCIF4] = HWBLK(MSTPCR0, 5, CORE_AREA),
+ [HWBLK_SCIF5] = HWBLK(MSTPCR0, 4, CORE_AREA),
+ [HWBLK_MSIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
+ [HWBLK_MSIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
+ [HWBLK_MERAM] = HWBLK(MSTPCR0, 0, CORE_AREA),
+
+ [HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA),
+ [HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA),
+
+ [HWBLK_ATAPI] = HWBLK(MSTPCR2, 28, CORE_AREA_BM),
+ [HWBLK_ADC] = HWBLK(MSTPCR2, 27, CORE_AREA),
+ [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
+ [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
+ [HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA),
+ [HWBLK_ICB] = HWBLK(MSTPCR2, 21, CORE_AREA_BM),
+ [HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA),
+ [HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA),
+ [HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA),
+ [HWBLK_USB] = HWBLK(MSTPCR2, 11, CORE_AREA),
+ [HWBLK_2DG] = HWBLK(MSTPCR2, 10, CORE_AREA_BM),
+ [HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA),
+ [HWBLK_VEU2H1] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
+ [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
+ [HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
+ [HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
+ [HWBLK_VEU2H0] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
+ [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
+ [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
+};
+
+static struct hwblk_info sh7723_hwblk_info = {
+ .areas = sh7723_hwblk_area,
+ .nr_areas = ARRAY_SIZE(sh7723_hwblk_area),
+ .hwblks = sh7723_hwblk,
+ .nr_hwblks = ARRAY_SIZE(sh7723_hwblk),
+};
+
+int arch_hwblk_sleep_mode(void)
+{
+ if (!sh7723_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
+ return SUSP_SH_STANDBY | SUSP_SH_SF;
+
+ if (!sh7723_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
+ return SUSP_SH_SLEEP | SUSP_SH_SF;
+
+ return SUSP_SH_SLEEP;
+}
+
+int __init arch_hwblk_init(void)
+{
+ return hwblk_register(&sh7723_hwblk_info);
+}
diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c
new file mode 100644
index 00000000000..1613ad6013c
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c
@@ -0,0 +1,121 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c
+ *
+ * SH7724 hardware block support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/suspend.h>
+#include <asm/hwblk.h>
+#include <cpu/sh7724.h>
+
+/* SH7724 registers */
+#define MSTPCR0 0xa4150030
+#define MSTPCR1 0xa4150034
+#define MSTPCR2 0xa4150038
+
+/* SH7724 Power Domains */
+enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
+static struct hwblk_area sh7724_hwblk_area[] = {
+ [CORE_AREA] = HWBLK_AREA(0, 0),
+ [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
+ [SUB_AREA] = HWBLK_AREA(0, 0),
+};
+
+/* Table mapping HWBLK to Module Stop Bit and Power Domain */
+static struct hwblk sh7724_hwblk[HWBLK_NR] = {
+ [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
+ [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
+ [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
+ [HWBLK_RSMEM] = HWBLK(MSTPCR0, 28, CORE_AREA),
+ [HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA),
+ [HWBLK_L2C] = HWBLK(MSTPCR0, 26, CORE_AREA),
+ [HWBLK_FPU] = HWBLK(MSTPCR0, 24, CORE_AREA),
+ [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
+ [HWBLK_DMAC0] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
+ [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
+ [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
+ [HWBLK_DBG] = HWBLK(MSTPCR0, 18, CORE_AREA),
+ [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
+ [HWBLK_TMU0] = HWBLK(MSTPCR0, 15, CORE_AREA),
+ [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
+ [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
+ [HWBLK_DMAC1] = HWBLK(MSTPCR0, 12, CORE_AREA_BM),
+ [HWBLK_TMU1] = HWBLK(MSTPCR0, 10, CORE_AREA),
+ [HWBLK_SCIF0] = HWBLK(MSTPCR0, 9, CORE_AREA),
+ [HWBLK_SCIF1] = HWBLK(MSTPCR0, 8, CORE_AREA),
+ [HWBLK_SCIF2] = HWBLK(MSTPCR0, 7, CORE_AREA),
+ [HWBLK_SCIF3] = HWBLK(MSTPCR0, 6, CORE_AREA),
+ [HWBLK_SCIF4] = HWBLK(MSTPCR0, 5, CORE_AREA),
+ [HWBLK_SCIF5] = HWBLK(MSTPCR0, 4, CORE_AREA),
+ [HWBLK_MSIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
+ [HWBLK_MSIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
+
+ [HWBLK_KEYSC] = HWBLK(MSTPCR1, 12, SUB_AREA),
+ [HWBLK_RTC] = HWBLK(MSTPCR1, 11, SUB_AREA),
+ [HWBLK_IIC0] = HWBLK(MSTPCR1, 9, CORE_AREA),
+ [HWBLK_IIC1] = HWBLK(MSTPCR1, 8, CORE_AREA),
+
+ [HWBLK_MMC] = HWBLK(MSTPCR2, 29, CORE_AREA),
+ [HWBLK_ETHER] = HWBLK(MSTPCR2, 28, CORE_AREA_BM),
+ [HWBLK_ATAPI] = HWBLK(MSTPCR2, 26, CORE_AREA_BM),
+ [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
+ [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
+ [HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA),
+ [HWBLK_USB1] = HWBLK(MSTPCR2, 21, CORE_AREA),
+ [HWBLK_USB0] = HWBLK(MSTPCR2, 20, CORE_AREA),
+ [HWBLK_2DG] = HWBLK(MSTPCR2, 19, CORE_AREA_BM),
+ [HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA),
+ [HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA),
+ [HWBLK_VEU1] = HWBLK(MSTPCR2, 15, CORE_AREA_BM),
+ [HWBLK_CEU1] = HWBLK(MSTPCR2, 13, CORE_AREA_BM),
+ [HWBLK_BEU1] = HWBLK(MSTPCR2, 12, CORE_AREA_BM),
+ [HWBLK_2DDMAC] = HWBLK(MSTPCR2, 10, CORE_AREA_BM),
+ [HWBLK_SPU] = HWBLK(MSTPCR2, 9, CORE_AREA_BM),
+ [HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
+ [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
+ [HWBLK_BEU0] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
+ [HWBLK_CEU0] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
+ [HWBLK_VEU0] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
+ [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
+ [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
+};
+
+static struct hwblk_info sh7724_hwblk_info = {
+ .areas = sh7724_hwblk_area,
+ .nr_areas = ARRAY_SIZE(sh7724_hwblk_area),
+ .hwblks = sh7724_hwblk,
+ .nr_hwblks = ARRAY_SIZE(sh7724_hwblk),
+};
+
+int arch_hwblk_sleep_mode(void)
+{
+ if (!sh7724_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
+ return SUSP_SH_STANDBY | SUSP_SH_SF;
+
+ if (!sh7724_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
+ return SUSP_SH_SLEEP | SUSP_SH_SF;
+
+ return SUSP_SH_SLEEP;
+}
+
+int __init arch_hwblk_init(void)
+{
+ return hwblk_register(&sh7724_hwblk_info);
+}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index 1a956b1becc..4a9010bf4fd 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -40,7 +40,7 @@ static struct platform_device iic_device = {
};
static struct r8a66597_platdata r8a66597_data = {
- /* This set zero to all members */
+ .on_chip = 1,
};
static struct resource usb_host_resources[] = {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index cda76ebf87c..67b0d87fcb2 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -13,6 +13,7 @@
#include <linux/serial_sci.h>
#include <linux/mm.h>
#include <linux/uio_driver.h>
+#include <linux/usb/m66592.h>
#include <linux/sh_timer.h>
#include <asm/clock.h>
#include <asm/mmzone.h>
@@ -47,9 +48,13 @@ static struct platform_device rtc_device = {
.resource = rtc_resources,
};
+static struct m66592_platdata usbf_platdata = {
+ .on_chip = 1,
+};
+
static struct resource usbf_resources[] = {
[0] = {
- .name = "m66592_udc",
+ .name = "USBF",
.start = 0x04480000,
.end = 0x044800FF,
.flags = IORESOURCE_MEM,
@@ -67,6 +72,7 @@ static struct platform_device usbf_device = {
.dev = {
.dma_mask = NULL,
.coherent_dma_mask = 0xffffffff,
+ .platform_data = &usbf_platdata,
},
.num_resources = ARRAY_SIZE(usbf_resources),
.resource = usbf_resources,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index b45dace9539..26dc4d32325 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -398,7 +398,7 @@ static struct platform_device rtc_device = {
};
static struct r8a66597_platdata r8a66597_data = {
- /* This set zero to all members */
+ .on_chip = 1,
};
static struct resource sh7723_usb_host_resources[] = {
diff --git a/arch/sh/kernel/cpu/shmobile/Makefile b/arch/sh/kernel/cpu/shmobile/Makefile
index 08bfa7c7db2..e8a5111e848 100644
--- a/arch/sh/kernel/cpu/shmobile/Makefile
+++ b/arch/sh/kernel/cpu/shmobile/Makefile
@@ -4,3 +4,4 @@
# Power Management & Sleep mode
obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_CPU_IDLE) += cpuidle.o
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
new file mode 100644
index 00000000000..4afdd975cc6
--- /dev/null
+++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
@@ -0,0 +1,102 @@
+/*
+ * arch/sh/kernel/cpu/shmobile/cpuidle.c
+ *
+ * Cpuidle support code for SuperH Mobile
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+#include <linux/cpuidle.h>
+#include <asm/suspend.h>
+#include <asm/uaccess.h>
+#include <asm/hwblk.h>
+
+static unsigned long cpuidle_mode[] = {
+ SUSP_SH_SLEEP, /* regular sleep mode */
+ SUSP_SH_SLEEP | SUSP_SH_SF, /* sleep mode + self refresh */
+};
+
+static int cpuidle_sleep_enter(struct cpuidle_device *dev,
+ struct cpuidle_state *state)
+{
+ unsigned long allowed_mode = arch_hwblk_sleep_mode();
+ ktime_t before, after;
+ int requested_state = state - &dev->states[0];
+ int allowed_state;
+ int k;
+
+ /* convert allowed mode to allowed state */
+ for (k = ARRAY_SIZE(cpuidle_mode) - 1; k > 0; k--)
+ if (cpuidle_mode[k] == allowed_mode)
+ break;
+
+ allowed_state = k;
+
+ /* take the following into account for sleep mode selection:
+ * - allowed_state: best mode allowed by hardware (clock deps)
+ * - requested_state: best mode allowed by software (latencies)
+ */
+ k = min_t(int, allowed_state, requested_state);
+
+ dev->last_state = &dev->states[k];
+ before = ktime_get();
+ sh_mobile_call_standby(cpuidle_mode[k]);
+ after = ktime_get();
+ return ktime_to_ns(ktime_sub(after, before)) >> 10;
+}
+
+static struct cpuidle_device cpuidle_dev;
+static struct cpuidle_driver cpuidle_driver = {
+ .name = "sh_idle",
+ .owner = THIS_MODULE,
+};
+
+void sh_mobile_setup_cpuidle(void)
+{
+ struct cpuidle_device *dev = &cpuidle_dev;
+ struct cpuidle_state *state;
+ int i;
+
+ cpuidle_register_driver(&cpuidle_driver);
+
+ for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
+ dev->states[i].name[0] = '\0';
+ dev->states[i].desc[0] = '\0';
+ }
+
+ i = CPUIDLE_DRIVER_STATE_START;
+
+ state = &dev->states[i++];
+ snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
+ strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
+ state->exit_latency = 1;
+ state->target_residency = 1 * 2;
+ state->power_usage = 3;
+ state->flags = 0;
+ state->flags |= CPUIDLE_FLAG_SHALLOW;
+ state->flags |= CPUIDLE_FLAG_TIME_VALID;
+ state->enter = cpuidle_sleep_enter;
+
+ dev->safe_state = state;
+
+ state = &dev->states[i++];
+ snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
+ strncpy(state->desc, "SuperH Sleep Mode [SF]", CPUIDLE_DESC_LEN);
+ state->exit_latency = 100;
+ state->target_residency = 1 * 2;
+ state->power_usage = 1;
+ state->flags = 0;
+ state->flags |= CPUIDLE_FLAG_TIME_VALID;
+ state->enter = cpuidle_sleep_enter;
+
+ dev->state_count = i;
+
+ cpuidle_register_device(dev);
+}
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
index 8c067adf683..de078d24ce5 100644
--- a/arch/sh/kernel/cpu/shmobile/pm.c
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -1,5 +1,5 @@
/*
- * arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c
+ * arch/sh/kernel/cpu/shmobile/pm.c
*
* Power management support code for SuperH Mobile
*
@@ -32,20 +32,17 @@
*
* R-standby mode is unsupported, but will be added in the future
* U-standby mode is low priority since it needs bootloader hacks
- *
- * All modes should be tied in with cpuidle. But before that can
- * happen we need to keep track of enabled hardware blocks so we
- * can avoid entering sleep modes that stop clocks to hardware
- * blocks that are in use even though the cpu core is idle.
*/
+#define ILRAM_BASE 0xe5200000
+
extern const unsigned char sh_mobile_standby[];
extern const unsigned int sh_mobile_standby_size;
-static void sh_mobile_call_standby(unsigned long mode)
+void sh_mobile_call_standby(unsigned long mode)
{
extern void *vbr_base;
- void *onchip_mem = (void *)0xe5200000; /* ILRAM */
+ void *onchip_mem = (void *)ILRAM_BASE;
void (*standby_onchip_mem)(unsigned long) = onchip_mem;
/* Note: Wake up from sleep may generate exceptions!
@@ -55,11 +52,6 @@ static void sh_mobile_call_standby(unsigned long mode)
if (mode & SUSP_SH_SF)
asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory");
- /* Copy the assembly snippet to the otherwise ununsed ILRAM */
- memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
- wmb();
- ctrl_barrier();
-
/* Let assembly snippet in on-chip memory handle the rest */
standby_onchip_mem(mode);
@@ -85,7 +77,15 @@ static struct platform_suspend_ops sh_pm_ops = {
static int __init sh_pm_init(void)
{
+ void *onchip_mem = (void *)ILRAM_BASE;
+
+ /* Copy the assembly snippet to the otherwise ununsed ILRAM */
+ memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
+ wmb();
+ ctrl_barrier();
+
suspend_set_ops(&sh_pm_ops);
+ sh_mobile_setup_cpuidle();
return 0;
}
diff --git a/arch/sh/kernel/dumpstack.c b/arch/sh/kernel/dumpstack.c
new file mode 100644
index 00000000000..6f5ad151340
--- /dev/null
+++ b/arch/sh/kernel/dumpstack.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+ * Copyright (C) 2009 Matt Fleming
+ */
+#include <linux/kallsyms.h>
+#include <linux/ftrace.h>
+#include <linux/debug_locks.h>
+#include <asm/unwinder.h>
+#include <asm/stacktrace.h>
+
+void printk_address(unsigned long address, int reliable)
+{
+ printk(" [<%p>] %s%pS\n", (void *) address,
+ reliable ? "" : "? ", (void *) address);
+}
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+static void
+print_ftrace_graph_addr(unsigned long addr, void *data,
+ const struct stacktrace_ops *ops,
+ struct thread_info *tinfo, int *graph)
+{
+ struct task_struct *task = tinfo->task;
+ unsigned long ret_addr;
+ int index = task->curr_ret_stack;
+
+ if (addr != (unsigned long)return_to_handler)
+ return;
+
+ if (!task->ret_stack || index < *graph)
+ return;
+
+ index -= *graph;
+ ret_addr = task->ret_stack[index].ret;
+
+ ops->address(data, ret_addr, 1);
+
+ (*graph)++;
+}
+#else
+static inline void
+print_ftrace_graph_addr(unsigned long addr, void *data,
+ const struct stacktrace_ops *ops,
+ struct thread_info *tinfo, int *graph)
+{ }
+#endif
+
+void
+stack_reader_dump(struct task_struct *task, struct pt_regs *regs,
+ unsigned long *sp, const struct stacktrace_ops *ops,
+ void *data)
+{
+ struct thread_info *context;
+ int graph = 0;
+
+ context = (struct thread_info *)
+ ((unsigned long)sp & (~(THREAD_SIZE - 1)));
+
+ while (!kstack_end(sp)) {
+ unsigned long addr = *sp++;
+
+ if (__kernel_text_address(addr)) {
+ ops->address(data, addr, 1);
+
+ print_ftrace_graph_addr(addr, data, ops,
+ context, &graph);
+ }
+ }
+}
+
+static void
+print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+ printk(data);
+ print_symbol(msg, symbol);
+ printk("\n");
+}
+
+static void print_trace_warning(void *data, char *msg)
+{
+ printk("%s%s\n", (char *)data, msg);
+}
+
+static int print_trace_stack(void *data, char *name)
+{
+ printk("%s <%s> ", (char *)data, name);
+ return 0;
+}
+
+/*
+ * Print one address/symbol entries per line.
+ */
+static void print_trace_address(void *data, unsigned long addr, int reliable)
+{
+ printk(data);
+ printk_address(addr, reliable);
+}
+
+static const struct stacktrace_ops print_trace_ops = {
+ .warning = print_trace_warning,
+ .warning_symbol = print_trace_warning_symbol,
+ .stack = print_trace_stack,
+ .address = print_trace_address,
+};
+
+void show_trace(struct task_struct *tsk, unsigned long *sp,
+ struct pt_regs *regs)
+{
+ if (regs && user_mode(regs))
+ return;
+
+ printk("\nCall trace:\n");
+
+ unwind_stack(tsk, regs, sp, &print_trace_ops, "");
+
+ printk("\n");
+
+ if (!tsk)
+ tsk = current;
+
+ debug_show_held_locks(tsk);
+}
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
new file mode 100644
index 00000000000..c6c5764a8ab
--- /dev/null
+++ b/arch/sh/kernel/dwarf.c
@@ -0,0 +1,902 @@
+/*
+ * Copyright (C) 2009 Matt Fleming <matt@console-pimps.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * This is an implementation of a DWARF unwinder. Its main purpose is
+ * for generating stacktrace information. Based on the DWARF 3
+ * specification from http://www.dwarfstd.org.
+ *
+ * TODO:
+ * - DWARF64 doesn't work.
+ */
+
+/* #define DEBUG */
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <asm/dwarf.h>
+#include <asm/unwinder.h>
+#include <asm/sections.h>
+#include <asm/unaligned.h>
+#include <asm/dwarf.h>
+#include <asm/stacktrace.h>
+
+static LIST_HEAD(dwarf_cie_list);
+DEFINE_SPINLOCK(dwarf_cie_lock);
+
+static LIST_HEAD(dwarf_fde_list);
+DEFINE_SPINLOCK(dwarf_fde_lock);
+
+static struct dwarf_cie *cached_cie;
+
+/*
+ * Figure out whether we need to allocate some dwarf registers. If dwarf
+ * registers have already been allocated then we may need to realloc
+ * them. "reg" is a register number that we need to be able to access
+ * after this call.
+ *
+ * Register numbers start at zero, therefore we need to allocate space
+ * for "reg" + 1 registers.
+ */
+static void dwarf_frame_alloc_regs(struct dwarf_frame *frame,
+ unsigned int reg)
+{
+ struct dwarf_reg *regs;
+ unsigned int num_regs = reg + 1;
+ size_t new_size;
+ size_t old_size;
+
+ new_size = num_regs * sizeof(*regs);
+ old_size = frame->num_regs * sizeof(*regs);
+
+ /* Fast path: don't allocate any regs if we've already got enough. */
+ if (frame->num_regs >= num_regs)
+ return;
+
+ regs = kzalloc(new_size, GFP_ATOMIC);
+ if (!regs) {
+ printk(KERN_WARNING "Unable to allocate DWARF registers\n");
+ /*
+ * Let's just bomb hard here, we have no way to
+ * gracefully recover.
+ */
+ BUG();
+ }
+
+ if (frame->regs) {
+ memcpy(regs, frame->regs, old_size);
+ kfree(frame->regs);
+ }
+
+ frame->regs = regs;
+ frame->num_regs = num_regs;
+}
+
+/**
+ * dwarf_read_addr - read dwarf data
+ * @src: source address of data
+ * @dst: destination address to store the data to
+ *
+ * Read 'n' bytes from @src, where 'n' is the size of an address on
+ * the native machine. We return the number of bytes read, which
+ * should always be 'n'. We also have to be careful when reading
+ * from @src and writing to @dst, because they can be arbitrarily
+ * aligned. Return 'n' - the number of bytes read.
+ */
+static inline int dwarf_read_addr(unsigned long *src, unsigned long *dst)
+{
+ u32 val = get_unaligned(src);
+ put_unaligned(val, dst);
+ return sizeof(unsigned long *);
+}
+
+/**
+ * dwarf_read_uleb128 - read unsigned LEB128 data
+ * @addr: the address where the ULEB128 data is stored
+ * @ret: address to store the result
+ *
+ * Decode an unsigned LEB128 encoded datum. The algorithm is taken
+ * from Appendix C of the DWARF 3 spec. For information on the
+ * encodings refer to section "7.6 - Variable Length Data". Return
+ * the number of bytes read.
+ */
+static inline unsigned long dwarf_read_uleb128(char *addr, unsigned int *ret)
+{
+ unsigned int result;
+ unsigned char byte;
+ int shift, count;
+
+ result = 0;
+ shift = 0;
+ count = 0;
+
+ while (1) {
+ byte = __raw_readb(addr);
+ addr++;
+ count++;
+
+ result |= (byte & 0x7f) << shift;
+ shift += 7;
+
+ if (!(byte & 0x80))
+ break;
+ }
+
+ *ret = result;
+
+ return count;
+}
+
+/**
+ * dwarf_read_leb128 - read signed LEB128 data
+ * @addr: the address of the LEB128 encoded data
+ * @ret: address to store the result
+ *
+ * Decode signed LEB128 data. The algorithm is taken from Appendix
+ * C of the DWARF 3 spec. Return the number of bytes read.
+ */
+static inline unsigned long dwarf_read_leb128(char *addr, int *ret)
+{
+ unsigned char byte;
+ int result, shift;
+ int num_bits;
+ int count;
+
+ result = 0;
+ shift = 0;
+ count = 0;
+
+ while (1) {
+ byte = __raw_readb(addr);
+ addr++;
+ result |= (byte & 0x7f) << shift;
+ shift += 7;
+ count++;
+
+ if (!(byte & 0x80))
+ break;
+ }
+
+ /* The number of bits in a signed integer. */
+ num_bits = 8 * sizeof(result);
+
+ if ((shift < num_bits) && (byte & 0x40))
+ result |= (-1 << shift);
+
+ *ret = result;
+
+ return count;
+}
+
+/**
+ * dwarf_read_encoded_value - return the decoded value at @addr
+ * @addr: the address of the encoded value
+ * @val: where to write the decoded value
+ * @encoding: the encoding with which we can decode @addr
+ *
+ * GCC emits encoded address in the .eh_frame FDE entries. Decode
+ * the value at @addr using @encoding. The decoded value is written
+ * to @val and the number of bytes read is returned.
+ */
+static int dwarf_read_encoded_value(char *addr, unsigned long *val,
+ char encoding)
+{
+ unsigned long decoded_addr = 0;
+ int count = 0;
+
+ switch (encoding & 0x70) {
+ case DW_EH_PE_absptr:
+ break;
+ case DW_EH_PE_pcrel:
+ decoded_addr = (unsigned long)addr;
+ break;
+ default:
+ pr_debug("encoding=0x%x\n", (encoding & 0x70));
+ BUG();
+ }
+
+ if ((encoding & 0x07) == 0x00)
+ encoding |= DW_EH_PE_udata4;
+
+ switch (encoding & 0x0f) {
+ case DW_EH_PE_sdata4:
+ case DW_EH_PE_udata4:
+ count += 4;
+ decoded_addr += get_unaligned((u32 *)addr);
+ __raw_writel(decoded_addr, val);
+ break;
+ default:
+ pr_debug("encoding=0x%x\n", encoding);
+ BUG();
+ }
+
+ return count;
+}
+
+/**
+ * dwarf_entry_len - return the length of an FDE or CIE
+ * @addr: the address of the entry
+ * @len: the length of the entry
+ *
+ * Read the initial_length field of the entry and store the size of
+ * the entry in @len. We return the number of bytes read. Return a
+ * count of 0 on error.
+ */
+static inline int dwarf_entry_len(char *addr, unsigned long *len)
+{
+ u32 initial_len;
+ int count;
+
+ initial_len = get_unaligned((u32 *)addr);
+ count = 4;
+
+ /*
+ * An initial length field value in the range DW_LEN_EXT_LO -
+ * DW_LEN_EXT_HI indicates an extension, and should not be
+ * interpreted as a length. The only extension that we currently
+ * understand is the use of DWARF64 addresses.
+ */
+ if (initial_len >= DW_EXT_LO && initial_len <= DW_EXT_HI) {
+ /*
+ * The 64-bit length field immediately follows the
+ * compulsory 32-bit length field.
+ */
+ if (initial_len == DW_EXT_DWARF64) {
+ *len = get_unaligned((u64 *)addr + 4);
+ count = 12;
+ } else {
+ printk(KERN_WARNING "Unknown DWARF extension\n");
+ count = 0;
+ }
+ } else
+ *len = initial_len;
+
+ return count;
+}
+
+/**
+ * dwarf_lookup_cie - locate the cie
+ * @cie_ptr: pointer to help with lookup
+ */
+static struct dwarf_cie *dwarf_lookup_cie(unsigned long cie_ptr)
+{
+ struct dwarf_cie *cie, *n;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dwarf_cie_lock, flags);
+
+ /*
+ * We've cached the last CIE we looked up because chances are
+ * that the FDE wants this CIE.
+ */
+ if (cached_cie && cached_cie->cie_pointer == cie_ptr) {
+ cie = cached_cie;
+ goto out;
+ }
+
+ list_for_each_entry_safe(cie, n, &dwarf_cie_list, link) {
+ if (cie->cie_pointer == cie_ptr) {
+ cached_cie = cie;
+ break;
+ }
+ }
+
+ /* Couldn't find the entry in the list. */
+ if (&cie->link == &dwarf_cie_list)
+ cie = NULL;
+out:
+ spin_unlock_irqrestore(&dwarf_cie_lock, flags);
+ return cie;
+}
+
+/**
+ * dwarf_lookup_fde - locate the FDE that covers pc
+ * @pc: the program counter
+ */
+struct dwarf_fde *dwarf_lookup_fde(unsigned long pc)
+{
+ unsigned long flags;
+ struct dwarf_fde *fde, *n;
+
+ spin_lock_irqsave(&dwarf_fde_lock, flags);
+ list_for_each_entry_safe(fde, n, &dwarf_fde_list, link) {
+ unsigned long start, end;
+
+ start = fde->initial_location;
+ end = fde->initial_location + fde->address_range;
+
+ if (pc >= start && pc < end)
+ break;
+ }
+
+ /* Couldn't find the entry in the list. */
+ if (&fde->link == &dwarf_fde_list)
+ fde = NULL;
+
+ spin_unlock_irqrestore(&dwarf_fde_lock, flags);
+
+ return fde;
+}
+
+/**
+ * dwarf_cfa_execute_insns - execute instructions to calculate a CFA
+ * @insn_start: address of the first instruction
+ * @insn_end: address of the last instruction
+ * @cie: the CIE for this function
+ * @fde: the FDE for this function
+ * @frame: the instructions calculate the CFA for this frame
+ * @pc: the program counter of the address we're interested in
+ * @define_ra: keep executing insns until the return addr reg is defined?
+ *
+ * Execute the Call Frame instruction sequence starting at
+ * @insn_start and ending at @insn_end. The instructions describe
+ * how to calculate the Canonical Frame Address of a stackframe.
+ * Store the results in @frame.
+ */
+static int dwarf_cfa_execute_insns(unsigned char *insn_start,
+ unsigned char *insn_end,
+ struct dwarf_cie *cie,
+ struct dwarf_fde *fde,
+ struct dwarf_frame *frame,
+ unsigned long pc,
+ bool define_ra)
+{
+ unsigned char insn;
+ unsigned char *current_insn;
+ unsigned int count, delta, reg, expr_len, offset;
+ bool seen_ra_reg;
+
+ current_insn = insn_start;
+
+ /*
+ * If we're executing instructions for the dwarf_unwind_stack()
+ * FDE we need to keep executing instructions until the value of
+ * DWARF_ARCH_RA_REG is defined. See the comment in
+ * dwarf_unwind_stack() for more details.
+ */
+ if (define_ra)
+ seen_ra_reg = false;
+ else
+ seen_ra_reg = true;
+
+ while (current_insn < insn_end && (frame->pc <= pc || !seen_ra_reg) ) {
+ insn = __raw_readb(current_insn++);
+
+ if (!seen_ra_reg) {
+ if (frame->num_regs >= DWARF_ARCH_RA_REG &&
+ frame->regs[DWARF_ARCH_RA_REG].flags)
+ seen_ra_reg = true;
+ }
+
+ /*
+ * Firstly, handle the opcodes that embed their operands
+ * in the instructions.
+ */
+ switch (DW_CFA_opcode(insn)) {
+ case DW_CFA_advance_loc:
+ delta = DW_CFA_operand(insn);
+ delta *= cie->code_alignment_factor;
+ frame->pc += delta;
+ continue;
+ /* NOTREACHED */
+ case DW_CFA_offset:
+ reg = DW_CFA_operand(insn);
+ count = dwarf_read_uleb128(current_insn, &offset);
+ current_insn += count;
+ offset *= cie->data_alignment_factor;
+ dwarf_frame_alloc_regs(frame, reg);
+ frame->regs[reg].addr = offset;
+ frame->regs[reg].flags |= DWARF_REG_OFFSET;
+ continue;
+ /* NOTREACHED */
+ case DW_CFA_restore:
+ reg = DW_CFA_operand(insn);
+ continue;
+ /* NOTREACHED */
+ }
+
+ /*
+ * Secondly, handle the opcodes that don't embed their
+ * operands in the instruction.
+ */
+ switch (insn) {
+ case DW_CFA_nop:
+ continue;
+ case DW_CFA_advance_loc1:
+ delta = *current_insn++;
+ frame->pc += delta * cie->code_alignment_factor;
+ break;
+ case DW_CFA_advance_loc2:
+ delta = get_unaligned((u16 *)current_insn);
+ current_insn += 2;
+ frame->pc += delta * cie->code_alignment_factor;
+ break;
+ case DW_CFA_advance_loc4:
+ delta = get_unaligned((u32 *)current_insn);
+ current_insn += 4;
+ frame->pc += delta * cie->code_alignment_factor;
+ break;
+ case DW_CFA_offset_extended:
+ count = dwarf_read_uleb128(current_insn, &reg);
+ current_insn += count;
+ count = dwarf_read_uleb128(current_insn, &offset);
+ current_insn += count;
+ offset *= cie->data_alignment_factor;
+ break;
+ case DW_CFA_restore_extended:
+ count = dwarf_read_uleb128(current_insn, &reg);
+ current_insn += count;
+ break;
+ case DW_CFA_undefined:
+ count = dwarf_read_uleb128(current_insn, &reg);
+ current_insn += count;
+ break;
+ case DW_CFA_def_cfa:
+ count = dwarf_read_uleb128(current_insn,
+ &frame->cfa_register);
+ current_insn += count;
+ count = dwarf_read_uleb128(current_insn,
+ &frame->cfa_offset);
+ current_insn += count;
+
+ frame->flags |= DWARF_FRAME_CFA_REG_OFFSET;
+ break;
+ case DW_CFA_def_cfa_register:
+ count = dwarf_read_uleb128(current_insn,
+ &frame->cfa_register);
+ current_insn += count;
+ frame->cfa_offset = 0;
+ frame->flags |= DWARF_FRAME_CFA_REG_OFFSET;
+ break;
+ case DW_CFA_def_cfa_offset:
+ count = dwarf_read_uleb128(current_insn, &offset);
+ current_insn += count;
+ frame->cfa_offset = offset;
+ break;
+ case DW_CFA_def_cfa_expression:
+ count = dwarf_read_uleb128(current_insn, &expr_len);
+ current_insn += count;
+
+ frame->cfa_expr = current_insn;
+ frame->cfa_expr_len = expr_len;
+ current_insn += expr_len;
+
+ frame->flags |= DWARF_FRAME_CFA_REG_EXP;
+ break;
+ case DW_CFA_offset_extended_sf:
+ count = dwarf_read_uleb128(current_insn, &reg);
+ current_insn += count;
+ count = dwarf_read_leb128(current_insn, &offset);
+ current_insn += count;
+ offset *= cie->data_alignment_factor;
+ dwarf_frame_alloc_regs(frame, reg);
+ frame->regs[reg].flags |= DWARF_REG_OFFSET;
+ frame->regs[reg].addr = offset;
+ break;
+ case DW_CFA_val_offset:
+ count = dwarf_read_uleb128(current_insn, &reg);
+ current_insn += count;
+ count = dwarf_read_leb128(current_insn, &offset);
+ offset *= cie->data_alignment_factor;
+ frame->regs[reg].flags |= DWARF_REG_OFFSET;
+ frame->regs[reg].addr = offset;
+ break;
+ default:
+ pr_debug("unhandled DWARF instruction 0x%x\n", insn);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * dwarf_unwind_stack - recursively unwind the stack
+ * @pc: address of the function to unwind
+ * @prev: struct dwarf_frame of the previous stackframe on the callstack
+ *
+ * Return a struct dwarf_frame representing the most recent frame
+ * on the callstack. Each of the lower (older) stack frames are
+ * linked via the "prev" member.
+ */
+struct dwarf_frame *dwarf_unwind_stack(unsigned long pc,
+ struct dwarf_frame *prev)
+{
+ struct dwarf_frame *frame;
+ struct dwarf_cie *cie;
+ struct dwarf_fde *fde;
+ unsigned long addr;
+ int i, offset;
+ bool define_ra = false;
+
+ /*
+ * If this is the first invocation of this recursive function we
+ * need get the contents of a physical register to get the CFA
+ * in order to begin the virtual unwinding of the stack.
+ *
+ * Setting "define_ra" to true indictates that we want
+ * dwarf_cfa_execute_insns() to continue executing instructions
+ * until we know how to calculate the value of DWARF_ARCH_RA_REG
+ * (which we need in order to kick off the whole unwinding
+ * process).
+ *
+ * NOTE: the return address is guaranteed to be setup by the
+ * time this function makes its first function call.
+ */
+ if (!pc && !prev) {
+ pc = (unsigned long)&dwarf_unwind_stack;
+ define_ra = true;
+ }
+
+ frame = kzalloc(sizeof(*frame), GFP_ATOMIC);
+ if (!frame)
+ return NULL;
+
+ frame->prev = prev;
+
+ fde = dwarf_lookup_fde(pc);
+ if (!fde) {
+ /*
+ * This is our normal exit path - the one that stops the
+ * recursion. There's two reasons why we might exit
+ * here,
+ *
+ * a) pc has no asscociated DWARF frame info and so
+ * we don't know how to unwind this frame. This is
+ * usually the case when we're trying to unwind a
+ * frame that was called from some assembly code
+ * that has no DWARF info, e.g. syscalls.
+ *
+ * b) the DEBUG info for pc is bogus. There's
+ * really no way to distinguish this case from the
+ * case above, which sucks because we could print a
+ * warning here.
+ */
+ return NULL;
+ }
+
+ cie = dwarf_lookup_cie(fde->cie_pointer);
+
+ frame->pc = fde->initial_location;
+
+ /* CIE initial instructions */
+ dwarf_cfa_execute_insns(cie->initial_instructions,
+ cie->instructions_end, cie, fde,
+ frame, pc, false);
+
+ /* FDE instructions */
+ dwarf_cfa_execute_insns(fde->instructions, fde->end, cie,
+ fde, frame, pc, define_ra);
+
+ /* Calculate the CFA */
+ switch (frame->flags) {
+ case DWARF_FRAME_CFA_REG_OFFSET:
+ if (prev) {
+ BUG_ON(!prev->regs[frame->cfa_register].flags);
+
+ addr = prev->cfa;
+ addr += prev->regs[frame->cfa_register].addr;
+ frame->cfa = __raw_readl(addr);
+
+ } else {
+ /*
+ * Again, this is the first invocation of this
+ * recurisve function. We need to physically
+ * read the contents of a register in order to
+ * get the Canonical Frame Address for this
+ * function.
+ */
+ frame->cfa = dwarf_read_arch_reg(frame->cfa_register);
+ }
+
+ frame->cfa += frame->cfa_offset;
+ break;
+ default:
+ BUG();
+ }
+
+ /* If we haven't seen the return address reg, we're screwed. */
+ BUG_ON(!frame->regs[DWARF_ARCH_RA_REG].flags);
+
+ for (i = 0; i <= frame->num_regs; i++) {
+ struct dwarf_reg *reg = &frame->regs[i];
+
+ if (!reg->flags)
+ continue;
+
+ offset = reg->addr;
+ offset += frame->cfa;
+ }
+
+ addr = frame->cfa + frame->regs[DWARF_ARCH_RA_REG].addr;
+ frame->return_addr = __raw_readl(addr);
+
+ frame->next = dwarf_unwind_stack(frame->return_addr, frame);
+ return frame;
+}
+
+static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
+ unsigned char *end)
+{
+ struct dwarf_cie *cie;
+ unsigned long flags;
+ int count;
+
+ cie = kzalloc(sizeof(*cie), GFP_KERNEL);
+ if (!cie)
+ return -ENOMEM;
+
+ cie->length = len;
+
+ /*
+ * Record the offset into the .eh_frame section
+ * for this CIE. It allows this CIE to be
+ * quickly and easily looked up from the
+ * corresponding FDE.
+ */
+ cie->cie_pointer = (unsigned long)entry;
+
+ cie->version = *(char *)p++;
+ BUG_ON(cie->version != 1);
+
+ cie->augmentation = p;
+ p += strlen(cie->augmentation) + 1;
+
+ count = dwarf_read_uleb128(p, &cie->code_alignment_factor);
+ p += count;
+
+ count = dwarf_read_leb128(p, &cie->data_alignment_factor);
+ p += count;
+
+ /*
+ * Which column in the rule table contains the
+ * return address?
+ */
+ if (cie->version == 1) {
+ cie->return_address_reg = __raw_readb(p);
+ p++;
+ } else {
+ count = dwarf_read_uleb128(p, &cie->return_address_reg);
+ p += count;
+ }
+
+ if (cie->augmentation[0] == 'z') {
+ unsigned int length, count;
+ cie->flags |= DWARF_CIE_Z_AUGMENTATION;
+
+ count = dwarf_read_uleb128(p, &length);
+ p += count;
+
+ BUG_ON((unsigned char *)p > end);
+
+ cie->initial_instructions = p + length;
+ cie->augmentation++;
+ }
+
+ while (*cie->augmentation) {
+ /*
+ * "L" indicates a byte showing how the
+ * LSDA pointer is encoded. Skip it.
+ */
+ if (*cie->augmentation == 'L') {
+ p++;
+ cie->augmentation++;
+ } else if (*cie->augmentation == 'R') {
+ /*
+ * "R" indicates a byte showing
+ * how FDE addresses are
+ * encoded.
+ */
+ cie->encoding = *(char *)p++;
+ cie->augmentation++;
+ } else if (*cie->augmentation == 'P') {
+ /*
+ * "R" indicates a personality
+ * routine in the CIE
+ * augmentation.
+ */
+ BUG();
+ } else if (*cie->augmentation == 'S') {
+ BUG();
+ } else {
+ /*
+ * Unknown augmentation. Assume
+ * 'z' augmentation.
+ */
+ p = cie->initial_instructions;
+ BUG_ON(!p);
+ break;
+ }
+ }
+
+ cie->initial_instructions = p;
+ cie->instructions_end = end;
+
+ /* Add to list */
+ spin_lock_irqsave(&dwarf_cie_lock, flags);
+ list_add_tail(&cie->link, &dwarf_cie_list);
+ spin_unlock_irqrestore(&dwarf_cie_lock, flags);
+
+ return 0;
+}
+
+static int dwarf_parse_fde(void *entry, u32 entry_type,
+ void *start, unsigned long len)
+{
+ struct dwarf_fde *fde;
+ struct dwarf_cie *cie;
+ unsigned long flags;
+ int count;
+ void *p = start;
+
+ fde = kzalloc(sizeof(*fde), GFP_KERNEL);
+ if (!fde)
+ return -ENOMEM;
+
+ fde->length = len;
+
+ /*
+ * In a .eh_frame section the CIE pointer is the
+ * delta between the address within the FDE
+ */
+ fde->cie_pointer = (unsigned long)(p - entry_type - 4);
+
+ cie = dwarf_lookup_cie(fde->cie_pointer);
+ fde->cie = cie;
+
+ if (cie->encoding)
+ count = dwarf_read_encoded_value(p, &fde->initial_location,
+ cie->encoding);
+ else
+ count = dwarf_read_addr(p, &fde->initial_location);
+
+ p += count;
+
+ if (cie->encoding)
+ count = dwarf_read_encoded_value(p, &fde->address_range,
+ cie->encoding & 0x0f);
+ else
+ count = dwarf_read_addr(p, &fde->address_range);
+
+ p += count;
+
+ if (fde->cie->flags & DWARF_CIE_Z_AUGMENTATION) {
+ unsigned int length;
+ count = dwarf_read_uleb128(p, &length);
+ p += count + length;
+ }
+
+ /* Call frame instructions. */
+ fde->instructions = p;
+ fde->end = start + len;
+
+ /* Add to list. */
+ spin_lock_irqsave(&dwarf_fde_lock, flags);
+ list_add_tail(&fde->link, &dwarf_fde_list);
+ spin_unlock_irqrestore(&dwarf_fde_lock, flags);
+
+ return 0;
+}
+
+static void dwarf_unwinder_dump(struct task_struct *task, struct pt_regs *regs,
+ unsigned long *sp,
+ const struct stacktrace_ops *ops, void *data)
+{
+ struct dwarf_frame *frame;
+
+ frame = dwarf_unwind_stack(0, NULL);
+
+ while (frame && frame->return_addr) {
+ ops->address(data, frame->return_addr, 1);
+ frame = frame->next;
+ }
+}
+
+static struct unwinder dwarf_unwinder = {
+ .name = "dwarf-unwinder",
+ .dump = dwarf_unwinder_dump,
+ .rating = 150,
+};
+
+static void dwarf_unwinder_cleanup(void)
+{
+ struct dwarf_cie *cie, *m;
+ struct dwarf_fde *fde, *n;
+ unsigned long flags;
+
+ /*
+ * Deallocate all the memory allocated for the DWARF unwinder.
+ * Traverse all the FDE/CIE lists and remove and free all the
+ * memory associated with those data structures.
+ */
+ spin_lock_irqsave(&dwarf_cie_lock, flags);
+ list_for_each_entry_safe(cie, m, &dwarf_cie_list, link)
+ kfree(cie);
+ spin_unlock_irqrestore(&dwarf_cie_lock, flags);
+
+ spin_lock_irqsave(&dwarf_fde_lock, flags);
+ list_for_each_entry_safe(fde, n, &dwarf_fde_list, link)
+ kfree(fde);
+ spin_unlock_irqrestore(&dwarf_fde_lock, flags);
+}
+
+/**
+ * dwarf_unwinder_init - initialise the dwarf unwinder
+ *
+ * Build the data structures describing the .dwarf_frame section to
+ * make it easier to lookup CIE and FDE entries. Because the
+ * .eh_frame section is packed as tightly as possible it is not
+ * easy to lookup the FDE for a given PC, so we build a list of FDE
+ * and CIE entries that make it easier.
+ */
+void dwarf_unwinder_init(void)
+{
+ u32 entry_type;
+ void *p, *entry;
+ int count, err;
+ unsigned long len;
+ unsigned int c_entries, f_entries;
+ unsigned char *end;
+ INIT_LIST_HEAD(&dwarf_cie_list);
+ INIT_LIST_HEAD(&dwarf_fde_list);
+
+ c_entries = 0;
+ f_entries = 0;
+ entry = &__start_eh_frame;
+
+ while ((char *)entry < __stop_eh_frame) {
+ p = entry;
+
+ count = dwarf_entry_len(p, &len);
+ if (count == 0) {
+ /*
+ * We read a bogus length field value. There is
+ * nothing we can do here apart from disabling
+ * the DWARF unwinder. We can't even skip this
+ * entry and move to the next one because 'len'
+ * tells us where our next entry is.
+ */
+ goto out;
+ } else
+ p += count;
+
+ /* initial length does not include itself */
+ end = p + len;
+
+ entry_type = get_unaligned((u32 *)p);
+ p += 4;
+
+ if (entry_type == DW_EH_FRAME_CIE) {
+ err = dwarf_parse_cie(entry, p, len, end);
+ if (err < 0)
+ goto out;
+ else
+ c_entries++;
+ } else {
+ err = dwarf_parse_fde(entry, entry_type, p, len);
+ if (err < 0)
+ goto out;
+ else
+ f_entries++;
+ }
+
+ entry = (char *)entry + len + 4;
+ }
+
+ printk(KERN_INFO "DWARF unwinder initialised: read %u CIEs, %u FDEs\n",
+ c_entries, f_entries);
+
+ err = unwinder_register(&dwarf_unwinder);
+ if (err)
+ goto out;
+
+ return;
+
+out:
+ printk(KERN_ERR "Failed to initialise DWARF unwinder: %d\n", err);
+ dwarf_unwinder_cleanup();
+}
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index a952dcf9999..81a46145ffa 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -134,7 +134,7 @@ static void scif_sercon_init(char *s)
sci_out(&scif_port, SCFCR, 0x0030); /* TTRG=b'11 */
sci_out(&scif_port, SCSCR, 0x0030); /* TE, RE */
}
-#elif defined(CONFIG_CPU_SH4)
+#elif defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
#define DEFAULT_BAUD 115200
/*
* Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
@@ -220,8 +220,7 @@ static int __init setup_early_printk(char *buf)
early_console = &scif_console;
#if !defined(CONFIG_SH_STANDARD_BIOS)
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721)
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
scif_sercon_init(buf + 6);
#endif
#endif
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index d62359cfbbe..e63178fefb9 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -43,9 +43,10 @@
* syscall #
*
*/
+#include <asm/dwarf.h>
#if defined(CONFIG_PREEMPT)
-# define preempt_stop() cli
+# define preempt_stop() cli ; TRACE_IRQS_OFF
#else
# define preempt_stop()
# define resume_kernel __restore_all
@@ -55,11 +56,7 @@
.align 2
ENTRY(exception_error)
!
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 2f, r0
- jsr @r0
- nop
-#endif
+ TRACE_IRQS_ON
sti
mov.l 1f, r0
jmp @r0
@@ -67,22 +64,28 @@ ENTRY(exception_error)
.align 2
1: .long do_exception_error
-#ifdef CONFIG_TRACE_IRQFLAGS
-2: .long trace_hardirqs_on
-#endif
.align 2
ret_from_exception:
+ CFI_STARTPROC simple
+ CFI_DEF_CFA r14, 0
+ CFI_REL_OFFSET 17, 64
+ CFI_REL_OFFSET 15, 0
+ CFI_REL_OFFSET 14, 56
preempt_stop()
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 4f, r0
- jsr @r0
- nop
-#endif
ENTRY(ret_from_irq)
!
mov #OFF_SR, r0
mov.l @(r0,r15), r0 ! get status register
+
+ shlr2 r0
+ and #0x3c, r0
+ cmp/eq #0x3c, r0
+ bt 9f
+ TRACE_IRQS_ON
+9:
+ mov #OFF_SR, r0
+ mov.l @(r0,r15), r0 ! get status register
shll r0
shll r0 ! kernel space?
get_current_thread_info r8, r0
@@ -125,13 +128,9 @@ noresched:
ENTRY(resume_userspace)
! r8: current_thread_info
cli
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 5f, r0
- jsr @r0
- nop
-#endif
+ TRACE_IRQS_OfF
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
- tst #_TIF_WORK_MASK, r0
+ tst #(_TIF_WORK_MASK & 0xff), r0
bt/s __restore_all
tst #_TIF_NEED_RESCHED, r0
@@ -156,14 +155,10 @@ work_resched:
jsr @r1 ! schedule
nop
cli
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 5f, r0
- jsr @r0
- nop
-#endif
+ TRACE_IRQS_OFF
!
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
- tst #_TIF_WORK_MASK, r0
+ tst #(_TIF_WORK_MASK & 0xff), r0
bt __restore_all
bra work_pending
tst #_TIF_NEED_RESCHED, r0
@@ -172,23 +167,15 @@ work_resched:
1: .long schedule
2: .long do_notify_resume
3: .long resume_userspace
-#ifdef CONFIG_TRACE_IRQFLAGS
-4: .long trace_hardirqs_on
-5: .long trace_hardirqs_off
-#endif
.align 2
syscall_exit_work:
! r0: current_thread_info->flags
! r8: current_thread_info
- tst #_TIF_WORK_SYSCALL_MASK, r0
+ tst #(_TIF_WORK_SYSCALL_MASK & 0xff), r0
bt/s work_pending
tst #_TIF_NEED_RESCHED, r0
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 5f, r0
- jsr @r0
- nop
-#endif
+ TRACE_IRQS_ON
sti
mov r15, r4
mov.l 8f, r0 ! do_syscall_trace_leave
@@ -259,6 +246,7 @@ debug_trap:
nop
bra __restore_all
nop
+ CFI_ENDPROC
.align 2
1: .long debug_trap_table
@@ -304,6 +292,7 @@ ret_from_fork:
* system calls and debug traps through their respective jump tables.
*/
ENTRY(system_call)
+ setup_frame_reg
#if !defined(CONFIG_CPU_SH2)
mov.l 1f, r9
mov.l @r9, r8 ! Read from TRA (Trap Address) Register
@@ -321,18 +310,18 @@ ENTRY(system_call)
bt/s debug_trap ! it's a debug trap..
nop
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 5f, r10
- jsr @r10
- nop
-#endif
+ TRACE_IRQS_ON
sti
!
get_current_thread_info r8, r10
mov.l @(TI_FLAGS,r8), r8
- mov #_TIF_WORK_SYSCALL_MASK, r10
+ mov #(_TIF_WORK_SYSCALL_MASK & 0xff), r10
+ mov #(_TIF_WORK_SYSCALL_MASK >> 8), r9
tst r10, r8
+ shll8 r9
+ bf syscall_trace_entry
+ tst r9, r8
bf syscall_trace_entry
!
mov.l 2f, r8 ! Number of syscalls
@@ -351,15 +340,15 @@ syscall_call:
!
syscall_exit:
cli
-#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 6f, r0
- jsr @r0
- nop
-#endif
+ TRACE_IRQS_OFF
!
get_current_thread_info r8, r0
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
- tst #_TIF_ALLWORK_MASK, r0
+ tst #(_TIF_ALLWORK_MASK & 0xff), r0
+ mov #(_TIF_ALLWORK_MASK >> 8), r1
+ bf syscall_exit_work
+ shlr8 r0
+ tst r0, r1
bf syscall_exit_work
bra __restore_all
nop
@@ -369,9 +358,5 @@ syscall_exit:
#endif
2: .long NR_syscalls
3: .long sys_call_table
-#ifdef CONFIG_TRACE_IRQFLAGS
-5: .long trace_hardirqs_on
-6: .long trace_hardirqs_off
-#endif
7: .long do_syscall_trace_enter
8: .long do_syscall_trace_leave
diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c
index 066f37dc32a..6647dfcb781 100644
--- a/arch/sh/kernel/ftrace.c
+++ b/arch/sh/kernel/ftrace.c
@@ -16,9 +16,13 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/kernel.h>
#include <asm/ftrace.h>
#include <asm/cacheflush.h>
+#include <asm/unistd.h>
+#include <trace/syscall.h>
+#ifdef CONFIG_DYNAMIC_FTRACE
static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE];
static unsigned char ftrace_nop[4];
@@ -131,3 +135,189 @@ int __init ftrace_dyn_arch_init(void *data)
return 0;
}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#ifdef CONFIG_DYNAMIC_FTRACE
+extern void ftrace_graph_call(void);
+
+static int ftrace_mod(unsigned long ip, unsigned long old_addr,
+ unsigned long new_addr)
+{
+ unsigned char code[MCOUNT_INSN_SIZE];
+
+ if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
+ return -EFAULT;
+
+ if (old_addr != __raw_readl((unsigned long *)code))
+ return -EINVAL;
+
+ __raw_writel(new_addr, ip);
+ return 0;
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+ unsigned long ip, old_addr, new_addr;
+
+ ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET;
+ old_addr = (unsigned long)(&skip_trace);
+ new_addr = (unsigned long)(&ftrace_graph_caller);
+
+ return ftrace_mod(ip, old_addr, new_addr);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+ unsigned long ip, old_addr, new_addr;
+
+ ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET;
+ old_addr = (unsigned long)(&ftrace_graph_caller);
+ new_addr = (unsigned long)(&skip_trace);
+
+ return ftrace_mod(ip, old_addr, new_addr);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+/*
+ * Hook the return address and push it in the stack of return addrs
+ * in the current thread info.
+ *
+ * This is the main routine for the function graph tracer. The function
+ * graph tracer essentially works like this:
+ *
+ * parent is the stack address containing self_addr's return address.
+ * We pull the real return address out of parent and store it in
+ * current's ret_stack. Then, we replace the return address on the stack
+ * with the address of return_to_handler. self_addr is the function that
+ * called mcount.
+ *
+ * When self_addr returns, it will jump to return_to_handler which calls
+ * ftrace_return_to_handler. ftrace_return_to_handler will pull the real
+ * return address off of current's ret_stack and jump to it.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
+{
+ unsigned long old;
+ int faulted, err;
+ struct ftrace_graph_ent trace;
+ unsigned long return_hooker = (unsigned long)&return_to_handler;
+
+ if (unlikely(atomic_read(&current->tracing_graph_pause)))
+ return;
+
+ /*
+ * Protect against fault, even if it shouldn't
+ * happen. This tool is too much intrusive to
+ * ignore such a protection.
+ */
+ __asm__ __volatile__(
+ "1: \n\t"
+ "mov.l @%2, %0 \n\t"
+ "2: \n\t"
+ "mov.l %3, @%2 \n\t"
+ "mov #0, %1 \n\t"
+ "3: \n\t"
+ ".section .fixup, \"ax\" \n\t"
+ "4: \n\t"
+ "mov.l 5f, %0 \n\t"
+ "jmp @%0 \n\t"
+ " mov #1, %1 \n\t"
+ ".balign 4 \n\t"
+ "5: .long 3b \n\t"
+ ".previous \n\t"
+ ".section __ex_table,\"a\" \n\t"
+ ".long 1b, 4b \n\t"
+ ".long 2b, 4b \n\t"
+ ".previous \n\t"
+ : "=&r" (old), "=r" (faulted)
+ : "r" (parent), "r" (return_hooker)
+ );
+
+ if (unlikely(faulted)) {
+ ftrace_graph_stop();
+ WARN_ON(1);
+ return;
+ }
+
+ err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0);
+ if (err == -EBUSY) {
+ __raw_writel(old, parent);
+ return;
+ }
+
+ trace.func = self_addr;
+
+ /* Only trace if the calling function expects to */
+ if (!ftrace_graph_entry(&trace)) {
+ current->curr_ret_stack--;
+ __raw_writel(old, parent);
+ }
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_FTRACE_SYSCALLS
+
+extern unsigned long __start_syscalls_metadata[];
+extern unsigned long __stop_syscalls_metadata[];
+extern unsigned long *sys_call_table;
+
+static struct syscall_metadata **syscalls_metadata;
+
+static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
+{
+ struct syscall_metadata *start;
+ struct syscall_metadata *stop;
+ char str[KSYM_SYMBOL_LEN];
+
+
+ start = (struct syscall_metadata *)__start_syscalls_metadata;
+ stop = (struct syscall_metadata *)__stop_syscalls_metadata;
+ kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
+
+ for ( ; start < stop; start++) {
+ if (start->name && !strcmp(start->name, str))
+ return start;
+ }
+
+ return NULL;
+}
+
+#define FTRACE_SYSCALL_MAX (NR_syscalls - 1)
+
+struct syscall_metadata *syscall_nr_to_meta(int nr)
+{
+ if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0)
+ return NULL;
+
+ return syscalls_metadata[nr];
+}
+
+void arch_init_ftrace_syscalls(void)
+{
+ int i;
+ struct syscall_metadata *meta;
+ unsigned long **psys_syscall_table = &sys_call_table;
+ static atomic_t refs;
+
+ if (atomic_inc_return(&refs) != 1)
+ goto end;
+
+ syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
+ FTRACE_SYSCALL_MAX, GFP_KERNEL);
+ if (!syscalls_metadata) {
+ WARN_ON(1);
+ return;
+ }
+
+ for (i = 0; i < FTRACE_SYSCALL_MAX; i++) {
+ meta = find_syscall_meta(psys_syscall_table[i]);
+ syscalls_metadata[i] = meta;
+ }
+ return;
+
+ /* Paranoid: avoid overflow */
+end:
+ atomic_dec(&refs);
+}
+#endif /* CONFIG_FTRACE_SYSCALLS */
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c
index 77dfecb6437..e27a19e1f46 100644
--- a/arch/sh/kernel/io_trapped.c
+++ b/arch/sh/kernel/io_trapped.c
@@ -112,14 +112,15 @@ void __iomem *match_trapped_io_handler(struct list_head *list,
struct trapped_io *tiop;
struct resource *res;
int k, len;
+ unsigned long flags;
- spin_lock_irq(&trapped_lock);
+ spin_lock_irqsave(&trapped_lock, flags);
list_for_each_entry(tiop, list, list) {
voffs = 0;
for (k = 0; k < tiop->num_resources; k++) {
res = tiop->resource + k;
if (res->start == offset) {
- spin_unlock_irq(&trapped_lock);
+ spin_unlock_irqrestore(&trapped_lock, flags);
return tiop->virt_base + voffs;
}
@@ -127,7 +128,7 @@ void __iomem *match_trapped_io_handler(struct list_head *list,
voffs += roundup(len, PAGE_SIZE);
}
}
- spin_unlock_irq(&trapped_lock);
+ spin_unlock_irqrestore(&trapped_lock, flags);
return NULL;
}
EXPORT_SYMBOL_GPL(match_trapped_io_handler);
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 3d09062f468..2bb43dc74f2 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -14,6 +14,7 @@
#include <asm/processor.h>
#include <asm/machvec.h>
#include <asm/uaccess.h>
+#include <asm/dwarf.h>
#include <asm/thread_info.h>
#include <cpu/mmu_context.h>
@@ -114,23 +115,6 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
#endif
irq_enter();
-
-#ifdef CONFIG_DEBUG_STACKOVERFLOW
- /* Debugging check for stack overflow: is there less than 1KB free? */
- {
- long sp;
-
- __asm__ __volatile__ ("and r15, %0" :
- "=r" (sp) : "0" (THREAD_SIZE - 1));
-
- if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
- printk("do_IRQ: stack overflow: %ld\n",
- sp - sizeof(struct thread_info));
- dump_stack();
- }
- }
-#endif
-
irq = irq_demux(intc_evt2irq(irq));
#ifdef CONFIG_IRQSTACKS
@@ -278,6 +262,9 @@ void __init init_IRQ(void)
sh_mv.mv_init_irq();
irq_ctx_init(smp_processor_id());
+
+ /* This needs to be early, but not too early.. */
+ dwarf_unwinder_init();
}
#ifdef CONFIG_SPARSE_IRQ
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index 92d7740faab..9fee977f176 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -23,6 +23,7 @@
#include <linux/tick.h>
#include <linux/reboot.h>
#include <linux/fs.h>
+#include <linux/ftrace.h>
#include <linux/preempt.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
@@ -264,8 +265,8 @@ static void ubc_set_tracing(int asid, unsigned long pc)
* switch_to(x,y) should switch tasks from x to y.
*
*/
-struct task_struct *__switch_to(struct task_struct *prev,
- struct task_struct *next)
+__notrace_funcgraph struct task_struct *
+__switch_to(struct task_struct *prev, struct task_struct *next)
{
#if defined(CONFIG_SH_FPU)
unlazy_fpu(prev, task_pt_regs(prev));
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 3392e835a37..c198eceaee9 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -34,6 +34,8 @@
#include <asm/syscalls.h>
#include <asm/fpu.h>
+#include <trace/syscall.h>
+
/*
* This routine will get a word off of the process kernel stack.
*/
@@ -459,6 +461,9 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
*/
ret = -1L;
+ if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+ ftrace_syscall_enter(regs);
+
if (unlikely(current->audit_context))
audit_syscall_entry(audit_arch(), regs->regs[3],
regs->regs[4], regs->regs[5],
@@ -475,6 +480,9 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
regs->regs[0]);
+ if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+ ftrace_syscall_exit(regs);
+
step = test_thread_flag(TIF_SINGLESTEP);
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
tracehook_report_syscall_exit(regs, step);
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index dd38338553e..ceb409bf774 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -30,6 +30,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include <linux/lmb.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/page.h>
@@ -233,39 +234,45 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
void __init setup_bootmem_allocator(unsigned long free_pfn)
{
unsigned long bootmap_size;
+ unsigned long bootmap_pages, bootmem_paddr;
+ u64 total_pages = (lmb_end_of_DRAM() - __MEMORY_START) >> PAGE_SHIFT;
+ int i;
+
+ bootmap_pages = bootmem_bootmap_pages(total_pages);
+
+ bootmem_paddr = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
/*
* Find a proper area for the bootmem bitmap. After this
* bootstrap step all allocations (until the page allocator
* is intact) must be done via bootmem_alloc().
*/
- bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn,
+ bootmap_size = init_bootmem_node(NODE_DATA(0),
+ bootmem_paddr >> PAGE_SHIFT,
min_low_pfn, max_low_pfn);
- __add_active_range(0, min_low_pfn, max_low_pfn);
- register_bootmem_low_pages();
-
- node_set_online(0);
+ /* Add active regions with valid PFNs. */
+ for (i = 0; i < lmb.memory.cnt; i++) {
+ unsigned long start_pfn, end_pfn;
+ start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
+ end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
+ __add_active_range(0, start_pfn, end_pfn);
+ }
/*
- * Reserve the kernel text and
- * Reserve the bootmem bitmap. We do this in two steps (first step
- * was init_bootmem()), because this catches the (definitely buggy)
- * case of us accidentally initializing the bootmem allocator with
- * an invalid RAM area.
+ * Add all physical memory to the bootmem map and mark each
+ * area as present.
*/
- reserve_bootmem(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
- (PFN_PHYS(free_pfn) + bootmap_size + PAGE_SIZE - 1) -
- (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET),
- BOOTMEM_DEFAULT);
+ register_bootmem_low_pages();
- /*
- * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
- */
- if (CONFIG_ZERO_PAGE_OFFSET != 0)
- reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
+ /* Reserve the sections we're already using. */
+ for (i = 0; i < lmb.reserved.cnt; i++)
+ reserve_bootmem(lmb.reserved.region[i].base,
+ lmb_size_bytes(&lmb.reserved, i),
BOOTMEM_DEFAULT);
+ node_set_online(0);
+
sparse_memory_present_with_active_regions(0);
#ifdef CONFIG_BLK_DEV_INITRD
@@ -296,12 +303,37 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
static void __init setup_memory(void)
{
unsigned long start_pfn;
+ u64 base = min_low_pfn << PAGE_SHIFT;
+ u64 size = (max_low_pfn << PAGE_SHIFT) - base;
/*
* Partially used pages are not usable - thus
* we are rounding upwards:
*/
start_pfn = PFN_UP(__pa(_end));
+
+ lmb_add(base, size);
+
+ /*
+ * Reserve the kernel text and
+ * Reserve the bootmem bitmap. We do this in two steps (first step
+ * was init_bootmem()), because this catches the (definitely buggy)
+ * case of us accidentally initializing the bootmem allocator with
+ * an invalid RAM area.
+ */
+ lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
+ (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) -
+ (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
+
+ /*
+ * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
+ */
+ if (CONFIG_ZERO_PAGE_OFFSET != 0)
+ lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET);
+
+ lmb_analyze();
+ lmb_dump_all();
+
setup_bootmem_allocator(start_pfn);
}
#else
@@ -402,6 +434,7 @@ void __init setup_arch(char **cmdline_p)
nodes_clear(node_online_map);
/* Setup bootmem with available RAM */
+ lmb_init();
setup_memory();
sparse_init();
diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c
index fcc5de31f83..cec610888e2 100644
--- a/arch/sh/kernel/sh_ksyms_32.c
+++ b/arch/sh/kernel/sh_ksyms_32.c
@@ -106,8 +106,8 @@ EXPORT_SYMBOL(flush_dcache_page);
EXPORT_SYMBOL(clear_user_page);
#endif
-#ifdef CONFIG_FUNCTION_TRACER
-EXPORT_SYMBOL(mcount);
+#ifdef CONFIG_MCOUNT
+DECLARE_EXPORT(mcount);
#endif
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_generic);
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
index 1a2a5eb76e4..c2e45c48409 100644
--- a/arch/sh/kernel/stacktrace.c
+++ b/arch/sh/kernel/stacktrace.c
@@ -13,47 +13,93 @@
#include <linux/stacktrace.h>
#include <linux/thread_info.h>
#include <linux/module.h>
+#include <asm/unwinder.h>
#include <asm/ptrace.h>
+#include <asm/stacktrace.h>
+
+static void save_stack_warning(void *data, char *msg)
+{
+}
+
+static void
+save_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+}
+
+static int save_stack_stack(void *data, char *name)
+{
+ return 0;
+}
/*
* Save stack-backtrace addresses into a stack_trace buffer.
*/
+static void save_stack_address(void *data, unsigned long addr, int reliable)
+{
+ struct stack_trace *trace = data;
+
+ if (!reliable)
+ return;
+
+ if (trace->skip > 0) {
+ trace->skip--;
+ return;
+ }
+
+ if (trace->nr_entries < trace->max_entries)
+ trace->entries[trace->nr_entries++] = addr;
+}
+
+static const struct stacktrace_ops save_stack_ops = {
+ .warning = save_stack_warning,
+ .warning_symbol = save_stack_warning_symbol,
+ .stack = save_stack_stack,
+ .address = save_stack_address,
+};
+
void save_stack_trace(struct stack_trace *trace)
{
unsigned long *sp = (unsigned long *)current_stack_pointer;
- while (!kstack_end(sp)) {
- unsigned long addr = *sp++;
-
- if (__kernel_text_address(addr)) {
- if (trace->skip > 0)
- trace->skip--;
- else
- trace->entries[trace->nr_entries++] = addr;
- if (trace->nr_entries >= trace->max_entries)
- break;
- }
- }
+ unwind_stack(current, NULL, sp, &save_stack_ops, trace);
+ if (trace->nr_entries < trace->max_entries)
+ trace->entries[trace->nr_entries++] = ULONG_MAX;
}
EXPORT_SYMBOL_GPL(save_stack_trace);
+static void
+save_stack_address_nosched(void *data, unsigned long addr, int reliable)
+{
+ struct stack_trace *trace = (struct stack_trace *)data;
+
+ if (!reliable)
+ return;
+
+ if (in_sched_functions(addr))
+ return;
+
+ if (trace->skip > 0) {
+ trace->skip--;
+ return;
+ }
+
+ if (trace->nr_entries < trace->max_entries)
+ trace->entries[trace->nr_entries++] = addr;
+}
+
+static const struct stacktrace_ops save_stack_ops_nosched = {
+ .warning = save_stack_warning,
+ .warning_symbol = save_stack_warning_symbol,
+ .stack = save_stack_stack,
+ .address = save_stack_address_nosched,
+};
+
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
unsigned long *sp = (unsigned long *)tsk->thread.sp;
- while (!kstack_end(sp)) {
- unsigned long addr = *sp++;
-
- if (__kernel_text_address(addr)) {
- if (in_sched_functions(addr))
- break;
- if (trace->skip > 0)
- trace->skip--;
- else
- trace->entries[trace->nr_entries++] = addr;
- if (trace->nr_entries >= trace->max_entries)
- break;
- }
- }
+ unwind_stack(current, NULL, sp, &save_stack_ops_nosched, trace);
+ if (trace->nr_entries < trace->max_entries)
+ trace->entries[trace->nr_entries++] = ULONG_MAX;
}
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 9b352a1e3fb..7f95f479060 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -21,6 +21,7 @@
#include <linux/smp.h>
#include <linux/rtc.h>
#include <asm/clock.h>
+#include <asm/hwblk.h>
#include <asm/rtc.h>
/* Dummy RTC ops */
@@ -91,11 +92,27 @@ module_init(rtc_generic_init);
void (*board_time_init)(void);
+static void __init sh_late_time_init(void)
+{
+ /*
+ * Make sure all compiled-in early timers register themselves.
+ *
+ * Run probe() for two "earlytimer" devices, these will be the
+ * clockevents and clocksource devices respectively. In the event
+ * that only a clockevents device is available, we -ENODEV on the
+ * clocksource and the jiffies clocksource is used transparently
+ * instead. No error handling is necessary here.
+ */
+ early_platform_driver_register_all("earlytimer");
+ early_platform_driver_probe("earlytimer", 2, 0);
+}
+
void __init time_init(void)
{
if (board_time_init)
board_time_init();
+ hwblk_init();
clk_init();
rtc_sh_get_time(&xtime);
@@ -106,15 +123,5 @@ void __init time_init(void)
local_timer_setup(smp_processor_id());
#endif
- /*
- * Make sure all compiled-in early timers register themselves.
- *
- * Run probe() for two "earlytimer" devices, these will be the
- * clockevents and clocksource devices respectively. In the event
- * that only a clockevents device is available, we -ENODEV on the
- * clocksource and the jiffies clocksource is used transparently
- * instead. No error handling is necessary here.
- */
- early_platform_driver_register_all("earlytimer");
- early_platform_driver_probe("earlytimer", 2, 0);
+ late_time_init = sh_late_time_init;
}
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 2b772776fcd..563426487c6 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -858,30 +858,6 @@ void __init trap_init(void)
per_cpu_trap_init();
}
-void show_trace(struct task_struct *tsk, unsigned long *sp,
- struct pt_regs *regs)
-{
- unsigned long addr;
-
- if (regs && user_mode(regs))
- return;
-
- printk("\nCall trace:\n");
-
- while (!kstack_end(sp)) {
- addr = *sp++;
- if (kernel_text_address(addr))
- print_ip_sym(addr);
- }
-
- printk("\n");
-
- if (!tsk)
- tsk = current;
-
- debug_show_held_locks(tsk);
-}
-
void show_stack(struct task_struct *tsk, unsigned long *sp)
{
unsigned long stack;
diff --git a/arch/sh/kernel/unwinder.c b/arch/sh/kernel/unwinder.c
new file mode 100644
index 00000000000..2b30fa28b44
--- /dev/null
+++ b/arch/sh/kernel/unwinder.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2009 Matt Fleming
+ *
+ * Based, in part, on kernel/time/clocksource.c.
+ *
+ * This file provides arbitration code for stack unwinders.
+ *
+ * Multiple stack unwinders can be available on a system, usually with
+ * the most accurate unwinder being the currently active one.
+ */
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/unwinder.h>
+#include <asm/atomic.h>
+
+/*
+ * This is the most basic stack unwinder an architecture can
+ * provide. For architectures without reliable frame pointers, e.g.
+ * RISC CPUs, it can be implemented by looking through the stack for
+ * addresses that lie within the kernel text section.
+ *
+ * Other CPUs, e.g. x86, can use their frame pointer register to
+ * construct more accurate stack traces.
+ */
+static struct list_head unwinder_list;
+static struct unwinder stack_reader = {
+ .name = "stack-reader",
+ .dump = stack_reader_dump,
+ .rating = 50,
+ .list = {
+ .next = &unwinder_list,
+ .prev = &unwinder_list,
+ },
+};
+
+/*
+ * "curr_unwinder" points to the stack unwinder currently in use. This
+ * is the unwinder with the highest rating.
+ *
+ * "unwinder_list" is a linked-list of all available unwinders, sorted
+ * by rating.
+ *
+ * All modifications of "curr_unwinder" and "unwinder_list" must be
+ * performed whilst holding "unwinder_lock".
+ */
+static struct unwinder *curr_unwinder = &stack_reader;
+
+static struct list_head unwinder_list = {
+ .next = &stack_reader.list,
+ .prev = &stack_reader.list,
+};
+
+static DEFINE_SPINLOCK(unwinder_lock);
+
+static atomic_t unwinder_running = ATOMIC_INIT(0);
+
+/**
+ * select_unwinder - Select the best registered stack unwinder.
+ *
+ * Private function. Must hold unwinder_lock when called.
+ *
+ * Select the stack unwinder with the best rating. This is useful for
+ * setting up curr_unwinder.
+ */
+static struct unwinder *select_unwinder(void)
+{
+ struct unwinder *best;
+
+ if (list_empty(&unwinder_list))
+ return NULL;
+
+ best = list_entry(unwinder_list.next, struct unwinder, list);
+ if (best == curr_unwinder)
+ return NULL;
+
+ return best;
+}
+
+/*
+ * Enqueue the stack unwinder sorted by rating.
+ */
+static int unwinder_enqueue(struct unwinder *ops)
+{
+ struct list_head *tmp, *entry = &unwinder_list;
+
+ list_for_each(tmp, &unwinder_list) {
+ struct unwinder *o;
+
+ o = list_entry(tmp, struct unwinder, list);
+ if (o == ops)
+ return -EBUSY;
+ /* Keep track of the place, where to insert */
+ if (o->rating >= ops->rating)
+ entry = tmp;
+ }
+ list_add(&ops->list, entry);
+
+ return 0;
+}
+
+/**
+ * unwinder_register - Used to install new stack unwinder
+ * @u: unwinder to be registered
+ *
+ * Install the new stack unwinder on the unwinder list, which is sorted
+ * by rating.
+ *
+ * Returns -EBUSY if registration fails, zero otherwise.
+ */
+int unwinder_register(struct unwinder *u)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&unwinder_lock, flags);
+ ret = unwinder_enqueue(u);
+ if (!ret)
+ curr_unwinder = select_unwinder();
+ spin_unlock_irqrestore(&unwinder_lock, flags);
+
+ return ret;
+}
+
+/*
+ * Unwind the call stack and pass information to the stacktrace_ops
+ * functions. Also handle the case where we need to switch to a new
+ * stack dumper because the current one faulted unexpectedly.
+ */
+void unwind_stack(struct task_struct *task, struct pt_regs *regs,
+ unsigned long *sp, const struct stacktrace_ops *ops,
+ void *data)
+{
+ unsigned long flags;
+
+ /*
+ * The problem with unwinders with high ratings is that they are
+ * inherently more complicated than the simple ones with lower
+ * ratings. We are therefore more likely to fault in the
+ * complicated ones, e.g. hitting BUG()s. If we fault in the
+ * code for the current stack unwinder we try to downgrade to
+ * one with a lower rating.
+ *
+ * Hopefully this will give us a semi-reliable stacktrace so we
+ * can diagnose why curr_unwinder->dump() faulted.
+ */
+ if (atomic_inc_return(&unwinder_running) != 1) {
+ spin_lock_irqsave(&unwinder_lock, flags);
+
+ if (!list_is_singular(&unwinder_list)) {
+ list_del(&curr_unwinder->list);
+ curr_unwinder = select_unwinder();
+ }
+
+ spin_unlock_irqrestore(&unwinder_lock, flags);
+ atomic_dec(&unwinder_running);
+ }
+
+ curr_unwinder->dump(task, regs, sp, ops, data);
+
+ atomic_dec(&unwinder_running);
+}
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index f53c76acaed..1b7d9d541e0 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -12,7 +12,7 @@ OUTPUT_ARCH(sh)
#include <asm/thread_info.h>
#include <asm/cache.h>
-#include <asm-generic/vmlinux.lds.h>
+#include <asm/vmlinux.lds.h>
ENTRY(_start)
SECTIONS
@@ -50,12 +50,7 @@ SECTIONS
_etext = .; /* End of text section */
} = 0x0009
- . = ALIGN(16); /* Exception table */
- __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
- __start___ex_table = .;
- *(__ex_table)
- __stop___ex_table = .;
- }
+ EXCEPTION_TABLE(16)
NOTES
RO_DATA(PAGE_SIZE)
@@ -71,69 +66,16 @@ SECTIONS
__uncached_end = .;
}
- . = ALIGN(THREAD_SIZE);
- .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
- *(.data.init_task)
-
- . = ALIGN(L1_CACHE_BYTES);
- *(.data.cacheline_aligned)
-
- . = ALIGN(L1_CACHE_BYTES);
- *(.data.read_mostly)
-
- . = ALIGN(PAGE_SIZE);
- *(.data.page_aligned)
-
- __nosave_begin = .;
- *(.data.nosave)
- . = ALIGN(PAGE_SIZE);
- __nosave_end = .;
-
- DATA_DATA
- CONSTRUCTORS
- }
+ RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
_edata = .; /* End of data section */
- . = ALIGN(PAGE_SIZE); /* Init code and data */
- .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
- __init_begin = .;
- _sinittext = .;
- INIT_TEXT
- _einittext = .;
- }
-
- .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { INIT_DATA }
-
- . = ALIGN(16);
- .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
- __setup_start = .;
- *(.init.setup)
- __setup_end = .;
- }
-
- .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
- __initcall_start = .;
- INITCALLS
- __initcall_end = .;
- }
-
- .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
- __con_initcall_start = .;
- *(.con_initcall.init)
- __con_initcall_end = .;
- }
-
- SECURITY_INIT
+ DWARF_EH_FRAME
-#ifdef CONFIG_BLK_DEV_INITRD
- . = ALIGN(PAGE_SIZE);
- .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
- __initramfs_start = .;
- *(.init.ramfs)
- __initramfs_end = .;
- }
-#endif
+ . = ALIGN(PAGE_SIZE); /* Init code and data */
+ __init_begin = .;
+ INIT_TEXT_SECTION(PAGE_SIZE)
+ INIT_DATA_SECTION(16)
. = ALIGN(4);
.machvec.init : AT(ADDR(.machvec.init) - LOAD_OFFSET) {
@@ -152,16 +94,10 @@ SECTIONS
.exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { EXIT_DATA }
. = ALIGN(PAGE_SIZE);
- .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
- __init_end = .;
- __bss_start = .; /* BSS */
- *(.bss.page_aligned)
- *(.bss)
- *(COMMON)
- . = ALIGN(4);
- _ebss = .; /* uClinux MTD sucks */
- _end = . ;
- }
+ __init_end = .;
+ BSS_SECTION(0, PAGE_SIZE, 4)
+ _ebss = .; /* uClinux MTD sucks */
+ _end = . ;
/*
* When something in the kernel is NOT compiled as a module, the
@@ -170,7 +106,7 @@ SECTIONS
* it's a module.
*/
/DISCARD/ : {
- *(.exitcall.exit)
+ EXIT_CALL
}
STABS_DEBUG
diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile
index aaea580b65b..c2b28d8b2dd 100644
--- a/arch/sh/lib/Makefile
+++ b/arch/sh/lib/Makefile
@@ -24,7 +24,7 @@ memcpy-y := memcpy.o
memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o
lib-$(CONFIG_MMU) += copy_page.o clear_page.o
-lib-$(CONFIG_FUNCTION_TRACER) += mcount.o
+lib-$(CONFIG_MCOUNT) += mcount.o
lib-y += $(memcpy-y) $(udivsi3-y)
EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S
index 110fbfe1831..84a57761f17 100644
--- a/arch/sh/lib/mcount.S
+++ b/arch/sh/lib/mcount.S
@@ -1,14 +1,16 @@
/*
* arch/sh/lib/mcount.S
*
- * Copyright (C) 2008 Paul Mundt
- * Copyright (C) 2008 Matt Fleming
+ * Copyright (C) 2008, 2009 Paul Mundt
+ * Copyright (C) 2008, 2009 Matt Fleming
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <asm/ftrace.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
#define MCOUNT_ENTER() \
mov.l r4, @-r15; \
@@ -28,6 +30,55 @@
rts; \
mov.l @r15+, r4
+#ifdef CONFIG_STACK_DEBUG
+/*
+ * Perform diagnostic checks on the state of the kernel stack.
+ *
+ * Check for stack overflow. If there is less than 1KB free
+ * then it has overflowed.
+ *
+ * Make sure the stack pointer contains a valid address. Valid
+ * addresses for kernel stacks are anywhere after the bss
+ * (after _ebss) and anywhere in init_thread_union (init_stack).
+ */
+#define STACK_CHECK() \
+ mov #(THREAD_SIZE >> 10), r0; \
+ shll8 r0; \
+ shll2 r0; \
+ \
+ /* r1 = sp & (THREAD_SIZE - 1) */ \
+ mov #-1, r1; \
+ add r0, r1; \
+ and r15, r1; \
+ \
+ mov #TI_SIZE, r3; \
+ mov #(STACK_WARN >> 8), r2; \
+ shll8 r2; \
+ add r3, r2; \
+ \
+ /* Is the stack overflowing? */ \
+ cmp/hi r2, r1; \
+ bf stack_panic; \
+ \
+ /* If sp > _ebss then we're OK. */ \
+ mov.l .L_ebss, r1; \
+ cmp/hi r1, r15; \
+ bt 1f; \
+ \
+ /* If sp < init_stack, we're not OK. */ \
+ mov.l .L_init_thread_union, r1; \
+ cmp/hs r1, r15; \
+ bf stack_panic; \
+ \
+ /* If sp > init_stack && sp < _ebss, not OK. */ \
+ add r0, r1; \
+ cmp/hs r1, r15; \
+ bt stack_panic; \
+1:
+#else
+#define STACK_CHECK()
+#endif /* CONFIG_STACK_DEBUG */
+
.align 2
.globl _mcount
.type _mcount,@function
@@ -35,6 +86,19 @@
.type mcount,@function
_mcount:
mcount:
+ STACK_CHECK()
+
+#ifndef CONFIG_FUNCTION_TRACER
+ rts
+ nop
+#else
+#ifndef CONFIG_DYNAMIC_FTRACE
+ mov.l .Lfunction_trace_stop, r0
+ mov.l @r0, r0
+ tst r0, r0
+ bf ftrace_stub
+#endif
+
MCOUNT_ENTER()
#ifdef CONFIG_DYNAMIC_FTRACE
@@ -52,16 +116,69 @@ mcount_call:
jsr @r6
nop
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ mov.l .Lftrace_graph_return, r6
+ mov.l .Lftrace_stub, r7
+ cmp/eq r6, r7
+ bt 1f
+
+ mov.l .Lftrace_graph_caller, r0
+ jmp @r0
+ nop
+
+1:
+ mov.l .Lftrace_graph_entry, r6
+ mov.l .Lftrace_graph_entry_stub, r7
+ cmp/eq r6, r7
+ bt skip_trace
+
+ mov.l .Lftrace_graph_caller, r0
+ jmp @r0
+ nop
+
+ .align 2
+.Lftrace_graph_return:
+ .long ftrace_graph_return
+.Lftrace_graph_entry:
+ .long ftrace_graph_entry
+.Lftrace_graph_entry_stub:
+ .long ftrace_graph_entry_stub
+.Lftrace_graph_caller:
+ .long ftrace_graph_caller
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+ .globl skip_trace
skip_trace:
MCOUNT_LEAVE()
.align 2
.Lftrace_trace_function:
- .long ftrace_trace_function
+ .long ftrace_trace_function
#ifdef CONFIG_DYNAMIC_FTRACE
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * NOTE: Do not move either ftrace_graph_call or ftrace_caller
+ * as this will affect the calculation of GRAPH_INSN_OFFSET.
+ */
+ .globl ftrace_graph_call
+ftrace_graph_call:
+ mov.l .Lskip_trace, r0
+ jmp @r0
+ nop
+
+ .align 2
+.Lskip_trace:
+ .long skip_trace
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
.globl ftrace_caller
ftrace_caller:
+ mov.l .Lfunction_trace_stop, r0
+ mov.l @r0, r0
+ tst r0, r0
+ bf ftrace_stub
+
MCOUNT_ENTER()
.globl ftrace_call
@@ -70,9 +187,18 @@ ftrace_call:
jsr @r6
nop
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ bra ftrace_graph_call
+ nop
+#else
MCOUNT_LEAVE()
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
#endif /* CONFIG_DYNAMIC_FTRACE */
+ .align 2
+.Lfunction_trace_stop:
+ .long function_trace_stop
+
/*
* NOTE: From here on the locations of the .Lftrace_stub label and
* ftrace_stub itself are fixed. Adding additional data here will skew
@@ -80,7 +206,6 @@ ftrace_call:
* Place new labels either after the ftrace_stub body, or before
* ftrace_caller. You have been warned.
*/
- .align 2
.Lftrace_stub:
.long ftrace_stub
@@ -88,3 +213,98 @@ ftrace_call:
ftrace_stub:
rts
nop
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ .globl ftrace_graph_caller
+ftrace_graph_caller:
+ mov.l 2f, r0
+ mov.l @r0, r0
+ tst r0, r0
+ bt 1f
+
+ mov.l 3f, r1
+ jmp @r1
+ nop
+1:
+ /*
+ * MCOUNT_ENTER() pushed 5 registers onto the stack, so
+ * the stack address containing our return address is
+ * r15 + 20.
+ */
+ mov #20, r0
+ add r15, r0
+ mov r0, r4
+
+ mov.l .Lprepare_ftrace_return, r0
+ jsr @r0
+ nop
+
+ MCOUNT_LEAVE()
+
+ .align 2
+2: .long function_trace_stop
+3: .long skip_trace
+.Lprepare_ftrace_return:
+ .long prepare_ftrace_return
+
+ .globl return_to_handler
+return_to_handler:
+ /*
+ * Save the return values.
+ */
+ mov.l r0, @-r15
+ mov.l r1, @-r15
+
+ mov #0, r4
+
+ mov.l .Lftrace_return_to_handler, r0
+ jsr @r0
+ nop
+
+ /*
+ * The return value from ftrace_return_handler has the real
+ * address that we should return to.
+ */
+ lds r0, pr
+ mov.l @r15+, r1
+ rts
+ mov.l @r15+, r0
+
+
+ .align 2
+.Lftrace_return_to_handler:
+ .long ftrace_return_to_handler
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#endif /* CONFIG_FUNCTION_TRACER */
+
+#ifdef CONFIG_STACK_DEBUG
+ .globl stack_panic
+stack_panic:
+ mov.l .Ldump_stack, r0
+ jsr @r0
+ nop
+
+ mov.l .Lpanic, r0
+ jsr @r0
+ mov.l .Lpanic_s, r4
+
+ rts
+ nop
+
+ .align 2
+.L_ebss:
+ .long _ebss
+.L_init_thread_union:
+ .long init_thread_union
+.Lpanic:
+ .long panic
+.Lpanic_s:
+ .long .Lpanic_str
+.Ldump_stack:
+ .long dump_stack
+
+ .section .rodata
+ .align 2
+.Lpanic_str:
+ .string "Stack error"
+#endif /* CONFIG_STACK_DEBUG */
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
index 71925946f1e..dbbdeba2cee 100644
--- a/arch/sh/mm/fault_32.c
+++ b/arch/sh/mm/fault_32.c
@@ -2,7 +2,7 @@
* Page fault handler for SH with an MMU.
*
* Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2003 - 2008 Paul Mundt
+ * Copyright (C) 2003 - 2009 Paul Mundt
*
* Based on linux/arch/i386/mm/fault.c:
* Copyright (C) 1995 Linus Torvalds
@@ -25,18 +25,91 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap)
{
int ret = 0;
-#ifdef CONFIG_KPROBES
- if (!user_mode(regs)) {
+ if (kprobes_built_in() && !user_mode(regs)) {
preempt_disable();
if (kprobe_running() && kprobe_fault_handler(regs, trap))
ret = 1;
preempt_enable();
}
-#endif
return ret;
}
+static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
+{
+ unsigned index = pgd_index(address);
+ pgd_t *pgd_k;
+ pud_t *pud, *pud_k;
+ pmd_t *pmd, *pmd_k;
+
+ pgd += index;
+ pgd_k = init_mm.pgd + index;
+
+ if (!pgd_present(*pgd_k))
+ return NULL;
+
+ pud = pud_offset(pgd, address);
+ pud_k = pud_offset(pgd_k, address);
+ if (!pud_present(*pud_k))
+ return NULL;
+
+ pmd = pmd_offset(pud, address);
+ pmd_k = pmd_offset(pud_k, address);
+ if (!pmd_present(*pmd_k))
+ return NULL;
+
+ if (!pmd_present(*pmd))
+ set_pmd(pmd, *pmd_k);
+ else {
+ /*
+ * The page tables are fully synchronised so there must
+ * be another reason for the fault. Return NULL here to
+ * signal that we have not taken care of the fault.
+ */
+ BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+ return NULL;
+ }
+
+ return pmd_k;
+}
+
+/*
+ * Handle a fault on the vmalloc or module mapping area
+ */
+static noinline int vmalloc_fault(unsigned long address)
+{
+ pgd_t *pgd_k;
+ pmd_t *pmd_k;
+ pte_t *pte_k;
+
+ /* Make sure we are in vmalloc area: */
+ if (!(address >= VMALLOC_START && address < VMALLOC_END))
+ return -1;
+
+ /*
+ * Synchronize this task's top level page-table
+ * with the 'reference' page table.
+ *
+ * Do _not_ use "current" here. We might be inside
+ * an interrupt in the middle of a task switch..
+ */
+ pgd_k = get_TTB();
+ pmd_k = vmalloc_sync_one(pgd_k, address);
+ if (!pmd_k)
+ return -1;
+
+ pte_k = pte_offset_kernel(pmd_k, address);
+ if (!pte_present(*pte_k))
+ return -1;
+
+ return 0;
+}
+
+static int fault_in_kernel_space(unsigned long address)
+{
+ return address >= TASK_SIZE;
+}
+
/*
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
@@ -46,6 +119,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
unsigned long writeaccess,
unsigned long address)
{
+ unsigned long vec;
struct task_struct *tsk;
struct mm_struct *mm;
struct vm_area_struct * vma;
@@ -53,59 +127,30 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
int fault;
siginfo_t info;
- /*
- * We don't bother with any notifier callbacks here, as they are
- * all handled through the __do_page_fault() fast-path.
- */
-
tsk = current;
+ mm = tsk->mm;
si_code = SEGV_MAPERR;
+ vec = lookup_exception_vector();
- 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;
-
- if (!pgd_present(*pgd)) {
- if (!pgd_present(*pgd_k))
- goto bad_area_nosemaphore;
- set_pgd(pgd, *pgd_k);
+ /*
+ * We fault-in kernel-space virtual memory on-demand. The
+ * 'reference' page table is init_mm.pgd.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may
+ * be in an interrupt or a critical region, and should
+ * only copy the information from the master page table,
+ * nothing more.
+ */
+ if (unlikely(fault_in_kernel_space(address))) {
+ if (vmalloc_fault(address) >= 0)
return;
- }
-
- pud = pud_offset(pgd, address);
- pud_k = pud_offset(pgd_k, address);
-
- if (!pud_present(*pud)) {
- if (!pud_present(*pud_k))
- goto bad_area_nosemaphore;
- set_pud(pud, *pud_k);
+ if (notify_page_fault(regs, vec))
return;
- }
- 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;
+ goto bad_area_nosemaphore;
}
- mm = tsk->mm;
-
- if (unlikely(notify_page_fault(regs, lookup_exception_vector())))
+ if (unlikely(notify_page_fault(regs, vec)))
return;
/* Only enable interrupts if they were on before the fault */
@@ -115,8 +160,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
/*
- * If we're in an interrupt or have no user
- * context, we must not take the fault..
+ * If we're in an interrupt, have no user context or are running
+ * in an atomic region then we must not take the fault:
*/
if (in_atomic() || !mm)
goto no_context;
@@ -132,10 +177,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
goto bad_area;
if (expand_stack(vma, address))
goto bad_area;
-/*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
+
+ /*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
good_area:
si_code = SEGV_ACCERR;
if (writeaccess) {
@@ -173,10 +219,10 @@ survive:
up_read(&mm->mmap_sem);
return;
-/*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
+ /*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
bad_area:
up_read(&mm->mmap_sem);
diff --git a/arch/sh/mm/ioremap_64.c b/arch/sh/mm/ioremap_64.c
index 828c8597219..b16843d02b7 100644
--- a/arch/sh/mm/ioremap_64.c
+++ b/arch/sh/mm/ioremap_64.c
@@ -94,7 +94,6 @@ static struct resource *shmedia_find_resource(struct resource *root,
static void __iomem *shmedia_alloc_io(unsigned long phys, unsigned long size,
const char *name, unsigned long flags)
{
- static int printed_full;
struct xresource *xres;
struct resource *res;
char *tack;
@@ -108,11 +107,8 @@ static void __iomem *shmedia_alloc_io(unsigned long phys, unsigned long size,
tack = xres->xname;
res = &xres->xres;
} else {
- if (!printed_full) {
- printk(KERN_NOTICE "%s: done with statics, "
+ printk_once(KERN_NOTICE "%s: done with statics, "
"switching to kmalloc\n", __func__);
- printed_full = 1;
- }
tlen = strlen(name);
tack = kmalloc(sizeof(struct resource) + tlen + 1, GFP_KERNEL);
if (!tack)
diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c
index 095d93bec7c..9b784fdb947 100644
--- a/arch/sh/mm/numa.c
+++ b/arch/sh/mm/numa.c
@@ -9,6 +9,7 @@
*/
#include <linux/module.h>
#include <linux/bootmem.h>
+#include <linux/lmb.h>
#include <linux/mm.h>
#include <linux/numa.h>
#include <linux/pfn.h>
@@ -26,6 +27,15 @@ EXPORT_SYMBOL_GPL(node_data);
void __init setup_memory(void)
{
unsigned long free_pfn = PFN_UP(__pa(_end));
+ u64 base = min_low_pfn << PAGE_SHIFT;
+ u64 size = (max_low_pfn << PAGE_SHIFT) - min_low_pfn;
+
+ lmb_add(base, size);
+
+ /* Reserve the LMB regions used by the kernel, initrd, etc.. */
+ lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
+ (PFN_PHYS(free_pfn) + PAGE_SIZE - 1) -
+ (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
/*
* Node 0 sets up its pgdat at the first available pfn,
@@ -45,24 +55,23 @@ void __init setup_memory(void)
void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
{
- unsigned long bootmap_pages, bootmap_start, bootmap_size;
- unsigned long start_pfn, free_pfn, end_pfn;
+ unsigned long bootmap_pages;
+ unsigned long start_pfn, end_pfn;
+ unsigned long bootmem_paddr;
/* Don't allow bogus node assignment */
BUG_ON(nid > MAX_NUMNODES || nid == 0);
- /*
- * The free pfn starts at the beginning of the range, and is
- * advanced as necessary for pgdat and node map allocations.
- */
- free_pfn = start_pfn = start >> PAGE_SHIFT;
+ start_pfn = start >> PAGE_SHIFT;
end_pfn = end >> PAGE_SHIFT;
+ lmb_add(start, end - start);
+
__add_active_range(nid, start_pfn, end_pfn);
/* Node-local pgdat */
- NODE_DATA(nid) = pfn_to_kaddr(free_pfn);
- free_pfn += PFN_UP(sizeof(struct pglist_data));
+ NODE_DATA(nid) = __va(lmb_alloc_base(sizeof(struct pglist_data),
+ SMP_CACHE_BYTES, end_pfn));
memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
@@ -71,16 +80,17 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
/* Node-local bootmap */
bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
- bootmap_start = (unsigned long)pfn_to_kaddr(free_pfn);
- bootmap_size = init_bootmem_node(NODE_DATA(nid), free_pfn, start_pfn,
- end_pfn);
+ bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT,
+ PAGE_SIZE, end_pfn);
+ init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
+ start_pfn, end_pfn);
free_bootmem_with_active_regions(nid, end_pfn);
/* Reserve the pgdat and bootmap space with the bootmem allocator */
reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
sizeof(struct pglist_data), BOOTMEM_DEFAULT);
- reserve_bootmem_node(NODE_DATA(nid), free_pfn << PAGE_SHIFT,
+ reserve_bootmem_node(NODE_DATA(nid), bootmem_paddr,
bootmap_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
/* It's up */
diff --git a/arch/sh/oprofile/backtrace.c b/arch/sh/oprofile/backtrace.c
index 9499a2914f8..2bc74de23f0 100644
--- a/arch/sh/oprofile/backtrace.c
+++ b/arch/sh/oprofile/backtrace.c
@@ -17,9 +17,43 @@
#include <linux/sched.h>
#include <linux/kallsyms.h>
#include <linux/mm.h>
+#include <asm/unwinder.h>
#include <asm/ptrace.h>
#include <asm/uaccess.h>
#include <asm/sections.h>
+#include <asm/stacktrace.h>
+
+static void backtrace_warning_symbol(void *data, char *msg,
+ unsigned long symbol)
+{
+ /* Ignore warnings */
+}
+
+static void backtrace_warning(void *data, char *msg)
+{
+ /* Ignore warnings */
+}
+
+static int backtrace_stack(void *data, char *name)
+{
+ /* Yes, we want all stacks */
+ return 0;
+}
+
+static void backtrace_address(void *data, unsigned long addr, int reliable)
+{
+ unsigned int *depth = data;
+
+ if ((*depth)--)
+ oprofile_add_trace(addr);
+}
+
+static struct stacktrace_ops backtrace_ops = {
+ .warning = backtrace_warning,
+ .warning_symbol = backtrace_warning_symbol,
+ .stack = backtrace_stack,
+ .address = backtrace_address,
+};
/* Limit to stop backtracing too far. */
static int backtrace_limit = 20;
@@ -47,50 +81,6 @@ user_backtrace(unsigned long *stackaddr, struct pt_regs *regs)
return stackaddr;
}
-/*
- * | | /\ Higher addresses
- * | |
- * --------------- stack base (address of current_thread_info)
- * | thread info |
- * . .
- * | stack |
- * --------------- saved regs->regs[15] value if valid
- * . .
- * --------------- struct pt_regs stored on stack (struct pt_regs *)
- * | |
- * . .
- * | |
- * --------------- ???
- * | |
- * | | \/ Lower addresses
- *
- * Thus, &pt_regs <-> stack base restricts the valid(ish) fp values
- */
-static int valid_kernel_stack(unsigned long *stackaddr, struct pt_regs *regs)
-{
- unsigned long stack = (unsigned long)regs;
- unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE;
-
- return ((unsigned long)stackaddr > stack) && ((unsigned long)stackaddr < stack_base);
-}
-
-static unsigned long *
-kernel_backtrace(unsigned long *stackaddr, struct pt_regs *regs)
-{
- unsigned long addr;
-
- /*
- * If not a valid kernel address, keep going till we find one
- * or the SP stops being a valid address.
- */
- do {
- addr = *stackaddr++;
- oprofile_add_trace(addr);
- } while (valid_kernel_stack(stackaddr, regs));
-
- return stackaddr;
-}
-
void sh_backtrace(struct pt_regs * const regs, unsigned int depth)
{
unsigned long *stackaddr;
@@ -103,9 +93,9 @@ void sh_backtrace(struct pt_regs * const regs, unsigned int depth)
stackaddr = (unsigned long *)regs->regs[15];
if (!user_mode(regs)) {
- while (depth-- && valid_kernel_stack(stackaddr, regs))
- stackaddr = kernel_backtrace(stackaddr, regs);
-
+ if (depth)
+ unwind_stack(NULL, regs, stackaddr,
+ &backtrace_ops, &depth);
return;
}
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index fec3a53b865..09eef360dde 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -56,3 +56,4 @@ SH7785LCR SH_SH7785LCR
URQUELL SH_URQUELL
ESPT SH_ESPT
POLARIS SH_POLARIS
+KFR2R09 SH_KFR2R09