aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel')
-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.c39
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7723.c42
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7724.c43
-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
39 files changed, 2533 insertions, 409 deletions
diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32
index 9411e3e31e68..f2245ebf0b31 100644
--- a/arch/sh/kernel/Makefile_32
+++ b/arch/sh/kernel/Makefile_32
@@ -9,10 +9,10 @@ ifdef CONFIG_FUNCTION_TRACER
9CFLAGS_REMOVE_ftrace.o = -pg 9CFLAGS_REMOVE_ftrace.o = -pg
10endif 10endif
11 11
12obj-y := debugtraps.o idle.o io.o io_generic.o irq.o \ 12obj-y := debugtraps.o dumpstack.o idle.o io.o io_generic.o irq.o \
13 machvec.o process_32.o ptrace_32.o setup.o signal_32.o \ 13 machvec.o process_32.o ptrace_32.o setup.o signal_32.o \
14 sys_sh.o sys_sh32.o syscalls_32.o time.o topology.o \ 14 sys_sh.o sys_sh32.o syscalls_32.o time.o topology.o \
15 traps.o traps_32.o 15 traps.o traps_32.o unwinder.o
16 16
17obj-y += cpu/ 17obj-y += cpu/
18obj-$(CONFIG_VSYSCALL) += vsyscall/ 18obj-$(CONFIG_VSYSCALL) += vsyscall/
@@ -29,8 +29,11 @@ obj-$(CONFIG_IO_TRAPPED) += io_trapped.o
29obj-$(CONFIG_KPROBES) += kprobes.o 29obj-$(CONFIG_KPROBES) += kprobes.o
30obj-$(CONFIG_GENERIC_GPIO) += gpio.o 30obj-$(CONFIG_GENERIC_GPIO) += gpio.o
31obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 31obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
32obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
33obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
32obj-$(CONFIG_DUMP_CODE) += disassemble.o 34obj-$(CONFIG_DUMP_CODE) += disassemble.o
33obj-$(CONFIG_HIBERNATION) += swsusp.o 35obj-$(CONFIG_HIBERNATION) += swsusp.o
36obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o
34 37
35obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o 38obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o
36 39
diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64
index 67b9f6c6326b..639ee514266c 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
2 2
3obj-y := debugtraps.o idle.o io.o io_generic.o irq.o machvec.o process_64.o \ 3obj-y := debugtraps.o idle.o io.o io_generic.o irq.o machvec.o process_64.o \
4 ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \ 4 ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \
5 syscalls_64.o time.o topology.o traps.o traps_64.o 5 syscalls_64.o time.o topology.o traps.o traps_64.o unwinder.o
6 6
7obj-y += cpu/ 7obj-y += cpu/
8obj-$(CONFIG_SMP) += smp.o 8obj-$(CONFIG_SMP) += smp.o
@@ -13,6 +13,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
13obj-$(CONFIG_STACKTRACE) += stacktrace.o 13obj-$(CONFIG_STACKTRACE) += stacktrace.o
14obj-$(CONFIG_IO_TRAPPED) += io_trapped.o 14obj-$(CONFIG_IO_TRAPPED) += io_trapped.o
15obj-$(CONFIG_GENERIC_GPIO) += gpio.o 15obj-$(CONFIG_GENERIC_GPIO) += gpio.o
16obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o
16 17
17obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o 18obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o
18 19
diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c
index 99aceb28ee24..d218e808294e 100644
--- a/arch/sh/kernel/asm-offsets.c
+++ b/arch/sh/kernel/asm-offsets.c
@@ -26,6 +26,7 @@ int main(void)
26 DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); 26 DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
27 DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); 27 DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
28 DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block)); 28 DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
29 DEFINE(TI_SIZE, sizeof(struct thread_info));
29 30
30#ifdef CONFIG_HIBERNATION 31#ifdef CONFIG_HIBERNATION
31 DEFINE(PBE_ADDRESS, offsetof(struct pbe, address)); 32 DEFINE(PBE_ADDRESS, offsetof(struct pbe, address));
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index eecad7cbd61e..3d6b9312dc47 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -19,4 +19,4 @@ obj-$(CONFIG_UBC_WAKEUP) += ubc.o
19obj-$(CONFIG_SH_ADC) += adc.o 19obj-$(CONFIG_SH_ADC) += adc.o
20obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o 20obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o
21 21
22obj-y += irq/ init.o clock.o 22obj-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 000000000000..c0ad7d46e784
--- /dev/null
+++ b/arch/sh/kernel/cpu/hwblk.c
@@ -0,0 +1,155 @@
1#include <linux/clk.h>
2#include <linux/compiler.h>
3#include <linux/slab.h>
4#include <linux/io.h>
5#include <linux/spinlock.h>
6#include <asm/suspend.h>
7#include <asm/hwblk.h>
8#include <asm/clock.h>
9
10static DEFINE_SPINLOCK(hwblk_lock);
11
12static void hwblk_area_mod_cnt(struct hwblk_info *info,
13 int area, int counter, int value, int goal)
14{
15 struct hwblk_area *hap = info->areas + area;
16
17 hap->cnt[counter] += value;
18
19 if (hap->cnt[counter] != goal)
20 return;
21
22 if (hap->flags & HWBLK_AREA_FLAG_PARENT)
23 hwblk_area_mod_cnt(info, hap->parent, counter, value, goal);
24}
25
26
27static int __hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
28 int counter, int value, int goal)
29{
30 struct hwblk *hp = info->hwblks + hwblk;
31
32 hp->cnt[counter] += value;
33 if (hp->cnt[counter] == goal)
34 hwblk_area_mod_cnt(info, hp->area, counter, value, goal);
35
36 return hp->cnt[counter];
37}
38
39static void hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
40 int counter, int value, int goal)
41{
42 unsigned long flags;
43
44 spin_lock_irqsave(&hwblk_lock, flags);
45 __hwblk_mod_cnt(info, hwblk, counter, value, goal);
46 spin_unlock_irqrestore(&hwblk_lock, flags);
47}
48
49void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int counter)
50{
51 hwblk_mod_cnt(info, hwblk, counter, 1, 1);
52}
53
54void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int counter)
55{
56 hwblk_mod_cnt(info, hwblk, counter, -1, 0);
57}
58
59void hwblk_enable(struct hwblk_info *info, int hwblk)
60{
61 struct hwblk *hp = info->hwblks + hwblk;
62 unsigned long tmp;
63 unsigned long flags;
64 int ret;
65
66 spin_lock_irqsave(&hwblk_lock, flags);
67
68 ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, 1, 1);
69 if (ret == 1) {
70 tmp = __raw_readl(hp->mstp);
71 tmp &= ~(1 << hp->bit);
72 __raw_writel(tmp, hp->mstp);
73 }
74
75 spin_unlock_irqrestore(&hwblk_lock, flags);
76}
77
78void hwblk_disable(struct hwblk_info *info, int hwblk)
79{
80 struct hwblk *hp = info->hwblks + hwblk;
81 unsigned long tmp;
82 unsigned long flags;
83 int ret;
84
85 spin_lock_irqsave(&hwblk_lock, flags);
86
87 ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, -1, 0);
88 if (ret == 0) {
89 tmp = __raw_readl(hp->mstp);
90 tmp |= 1 << hp->bit;
91 __raw_writel(tmp, hp->mstp);
92 }
93
94 spin_unlock_irqrestore(&hwblk_lock, flags);
95}
96
97struct hwblk_info *hwblk_info;
98
99int __init hwblk_register(struct hwblk_info *info)
100{
101 hwblk_info = info;
102 return 0;
103}
104
105int __init __weak arch_hwblk_init(void)
106{
107 return 0;
108}
109
110int __weak arch_hwblk_sleep_mode(void)
111{
112 return SUSP_SH_SLEEP;
113}
114
115int __init hwblk_init(void)
116{
117 return arch_hwblk_init();
118}
119
120/* allow clocks to enable and disable hardware blocks */
121static int sh_hwblk_clk_enable(struct clk *clk)
122{
123 if (!hwblk_info)
124 return -ENOENT;
125
126 hwblk_enable(hwblk_info, clk->arch_flags);
127 return 0;
128}
129
130static void sh_hwblk_clk_disable(struct clk *clk)
131{
132 if (hwblk_info)
133 hwblk_disable(hwblk_info, clk->arch_flags);
134}
135
136static struct clk_ops sh_hwblk_clk_ops = {
137 .enable = sh_hwblk_clk_enable,
138 .disable = sh_hwblk_clk_disable,
139 .recalc = followparent_recalc,
140};
141
142int __init sh_hwblk_clk_register(struct clk *clks, int nr)
143{
144 struct clk *clkp;
145 int ret = 0;
146 int k;
147
148 for (k = 0; !ret && (k < nr); k++) {
149 clkp = clks + k;
150 clkp->ops = &sh_hwblk_clk_ops;
151 ret |= clk_register(clkp);
152 }
153
154 return ret;
155}
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index ad85421099cd..d40b9db5be03 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * CPU init code 4 * CPU init code
5 * 5 *
6 * Copyright (C) 2002 - 2007 Paul Mundt 6 * Copyright (C) 2002 - 2009 Paul Mundt
7 * Copyright (C) 2003 Richard Curnow 7 * Copyright (C) 2003 Richard Curnow
8 * 8 *
9 * This file is subject to the terms and conditions of the GNU General Public 9 * 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)
62#define speculative_execution_init() do { } while (0) 62#define speculative_execution_init() do { } while (0)
63#endif 63#endif
64 64
65#ifdef CONFIG_CPU_SH4A
66#define EXPMASK 0xff2f0004
67#define EXPMASK_RTEDS (1 << 0)
68#define EXPMASK_BRDSSLP (1 << 1)
69#define EXPMASK_MMCAW (1 << 4)
70
71static void __init expmask_init(void)
72{
73 unsigned long expmask = __raw_readl(EXPMASK);
74
75 /*
76 * Future proofing.
77 *
78 * Disable support for slottable sleep instruction
79 * and non-nop instructions in the rte delay slot.
80 */
81 expmask &= ~(EXPMASK_RTEDS | EXPMASK_BRDSSLP);
82
83 /*
84 * Enable associative writes to the memory-mapped cache array
85 * until the cache flush ops have been rewritten.
86 */
87 expmask |= EXPMASK_MMCAW;
88
89 __raw_writel(expmask, EXPMASK);
90 ctrl_barrier();
91}
92#else
93#define expmask_init() do { } while (0)
94#endif
95
65/* 2nd-level cache init */ 96/* 2nd-level cache init */
66void __uses_jump_to_uncached __attribute__ ((weak)) l2_cache_init(void) 97void __uses_jump_to_uncached __attribute__ ((weak)) l2_cache_init(void)
67{ 98{
@@ -321,4 +352,5 @@ asmlinkage void __init sh_cpu_init(void)
321#endif 352#endif
322 353
323 speculative_execution_init(); 354 speculative_execution_init();
355 expmask_init();
324} 356}
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index becc54c45692..c8a4331d9b8d 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)
227 mov.l @r15+, r14 227 mov.l @r15+, r14
228 add #8,r15 228 add #8,r15
229 lds.l @r15+, pr 229 lds.l @r15+, pr
230 mov.l @r15+,r15
230 rte 231 rte
231 mov.l @r15+,r15 232 nop
232 .align 2 233 .align 2
2331: .long gdb_vbr_vector 2341: .long gdb_vbr_vector
234#endif /* CONFIG_SH_STANDARD_BIOS */ 235#endif /* CONFIG_SH_STANDARD_BIOS */
diff --git a/arch/sh/kernel/cpu/sh2a/entry.S b/arch/sh/kernel/cpu/sh2a/entry.S
index ab3903eeda5c..222742ddc0d6 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)
176 movml.l @r15+,r14 176 movml.l @r15+,r14
177 add #8,r15 177 add #8,r15
178 lds.l @r15+, pr 178 lds.l @r15+, pr
179 mov.l @r15+,r15
179 rte 180 rte
180 mov.l @r15+,r15 181 nop
181 .align 2 182 .align 2
1821: .long gdb_vbr_vector 1831: .long gdb_vbr_vector
183#endif /* CONFIG_SH_STANDARD_BIOS */ 184#endif /* CONFIG_SH_STANDARD_BIOS */
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 3cb531f233f2..67ad6467c694 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)
137 mov #1, r5 137 mov #1, r5
138 138
139call_dpf: 139call_dpf:
140 setup_frame_reg
140 mov.l 1f, r0 141 mov.l 1f, r0
141 mov r5, r8 142 mov r5, r8
142 mov.l @r0, r6 143 mov.l @r0, r6
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index ebdd391d5f42..12cddf4c721d 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
25clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o 25clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
26clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o 26clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o
27clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o 27clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
28clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o 28clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o hwblk-sh7722.o
29clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o 29clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o hwblk-sh7723.o
30clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o 30clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o hwblk-sh7724.o
31clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o 31clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o
32clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o 32clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o
33 33
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index 40f859354f79..5b1bbbe63b1b 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -22,6 +22,8 @@
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <asm/clock.h> 24#include <asm/clock.h>
25#include <asm/hwblk.h>
26#include <cpu/sh7722.h>
25 27
26/* SH7722 registers */ 28/* SH7722 registers */
27#define FRQCR 0xa4150000 29#define FRQCR 0xa4150000
@@ -30,9 +32,6 @@
30#define SCLKBCR 0xa415000c 32#define SCLKBCR 0xa415000c
31#define IRDACLKCR 0xa4150018 33#define IRDACLKCR 0xa4150018
32#define PLLCR 0xa4150024 34#define PLLCR 0xa4150024
33#define MSTPCR0 0xa4150030
34#define MSTPCR1 0xa4150034
35#define MSTPCR2 0xa4150038
36#define DLLFRQ 0xa4150050 35#define DLLFRQ 0xa4150050
37 36
38/* Fixed 32 KHz root clock for RTC and Power Management purposes */ 37/* Fixed 32 KHz root clock for RTC and Power Management purposes */
@@ -140,35 +139,37 @@ struct clk div6_clks[] = {
140 SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), 139 SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
141}; 140};
142 141
143#define MSTP(_str, _parent, _reg, _bit, _flags) \ 142#define R_CLK &r_clk
144 SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags) 143#define P_CLK &div4_clks[DIV4_P]
144#define B_CLK &div4_clks[DIV4_B]
145#define U_CLK &div4_clks[DIV4_U]
145 146
146static struct clk mstp_clks[] = { 147static struct clk mstp_clks[] = {
147 MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT), 148 SH_HWBLK_CLK("uram0", -1, U_CLK, HWBLK_URAM, CLK_ENABLE_ON_INIT),
148 MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), 149 SH_HWBLK_CLK("xymem0", -1, B_CLK, HWBLK_XYMEM, CLK_ENABLE_ON_INIT),
149 MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0), 150 SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU, 0),
150 MSTP("cmt0", &r_clk, MSTPCR0, 14, 0), 151 SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
151 MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), 152 SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
152 MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), 153 SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
153 MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0), 154 SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
154 MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0), 155 SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
155 MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0), 156 SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
156 157
157 MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0), 158 SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
158 MSTP("rtc0", &r_clk, MSTPCR1, 8, 0), 159 SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
159 160
160 MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0), 161 SH_HWBLK_CLK("sdhi0", -1, P_CLK, HWBLK_SDHI, 0),
161 MSTP("keysc0", &r_clk, MSTPCR2, 14, 0), 162 SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
162 MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0), 163 SH_HWBLK_CLK("usbf0", -1, P_CLK, HWBLK_USBF, 0),
163 MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 9, 0), 164 SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
164 MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0), 165 SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
165 MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0), 166 SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
166 MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT), 167 SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, CLK_ENABLE_ON_INIT),
167 MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0), 168 SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
168 MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0), 169 SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
169 MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), 170 SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU, CLK_ENABLE_ON_INIT),
170 MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), 171 SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
171 MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0), 172 SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0),
172}; 173};
173 174
174int __init arch_clk_init(void) 175int __init arch_clk_init(void)
@@ -191,7 +192,7 @@ int __init arch_clk_init(void)
191 ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); 192 ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
192 193
193 if (!ret) 194 if (!ret)
194 ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); 195 ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
195 196
196 return ret; 197 return ret;
197} 198}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
index e67c2678b8ae..e5c63911403c 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
@@ -22,6 +22,8 @@
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <asm/clock.h> 24#include <asm/clock.h>
25#include <asm/hwblk.h>
26#include <cpu/sh7723.h>
25 27
26/* SH7723 registers */ 28/* SH7723 registers */
27#define FRQCR 0xa4150000 29#define FRQCR 0xa4150000
@@ -30,9 +32,6 @@
30#define SCLKBCR 0xa415000c 32#define SCLKBCR 0xa415000c
31#define IRDACLKCR 0xa4150018 33#define IRDACLKCR 0xa4150018
32#define PLLCR 0xa4150024 34#define PLLCR 0xa4150024
33#define MSTPCR0 0xa4150030
34#define MSTPCR1 0xa4150034
35#define MSTPCR2 0xa4150038
36#define DLLFRQ 0xa4150050 35#define DLLFRQ 0xa4150050
37 36
38/* Fixed 32 KHz root clock for RTC and Power Management purposes */ 37/* Fixed 32 KHz root clock for RTC and Power Management purposes */
@@ -140,60 +139,64 @@ struct clk div6_clks[] = {
140 SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), 139 SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
141}; 140};
142 141
143#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \ 142#define R_CLK (&r_clk)
144 SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT) 143#define P_CLK (&div4_clks[DIV4_P])
144#define B_CLK (&div4_clks[DIV4_B])
145#define U_CLK (&div4_clks[DIV4_U])
146#define I_CLK (&div4_clks[DIV4_I])
147#define SH_CLK (&div4_clks[DIV4_SH])
145 148
146static struct clk mstp_clks[] = { 149static struct clk mstp_clks[] = {
147 /* See page 60 of Datasheet V1.0: Overview -> Block Diagram */ 150 /* See page 60 of Datasheet V1.0: Overview -> Block Diagram */
148 MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0), 151 SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT),
149 MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0), 152 SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT),
150 MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0), 153 SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT),
151 MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 28, 1, 1, 0), 154 SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT),
152 MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0), 155 SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT),
153 MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0), 156 SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT),
154 MSTP("intc0", &div4_clks[DIV4_I], MSTPCR0, 22, 1, 1, 0), 157 SH_HWBLK_CLK("intc0", -1, I_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT),
155 MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1), 158 SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0),
156 MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0), 159 SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT),
157 MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0), 160 SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0),
158 MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0), 161 SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0),
159 MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0), 162 SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0),
160 MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0), 163 SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
161 MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0), 164 SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
162 MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1), 165 SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0),
163 MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 11, 0, 1, 0), 166 SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0),
164 MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0), 167 SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
165 MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0), 168 SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
166 MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0), 169 SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
167 MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0), 170 SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
168 MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0), 171 SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0),
169 MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0), 172 SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0),
170 MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0), 173 SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0),
171 MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0), 174 SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0),
172 MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0), 175 SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0),
173 MSTP("meram0", &div4_clks[DIV4_SH], MSTPCR0, 0, 1, 1, 0), 176 SH_HWBLK_CLK("meram0", -1, SH_CLK, HWBLK_MERAM, 0),
174 177
175 MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0), 178 SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
176 MSTP("rtc0", &r_clk, MSTPCR1, 8, 0, 0, 0), 179 SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
177 180
178 MSTP("atapi0", &div4_clks[DIV4_SH], MSTPCR2, 28, 0, 1, 0), 181 SH_HWBLK_CLK("atapi0", -1, SH_CLK, HWBLK_ATAPI, 0),
179 MSTP("adc0", &div4_clks[DIV4_P], MSTPCR2, 27, 0, 1, 0), 182 SH_HWBLK_CLK("adc0", -1, P_CLK, HWBLK_ADC, 0),
180 MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0), 183 SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0),
181 MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0), 184 SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0),
182 MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0), 185 SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0),
183 MSTP("icb0", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1), 186 SH_HWBLK_CLK("icb0", -1, B_CLK, HWBLK_ICB, CLK_ENABLE_ON_INIT),
184 MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0), 187 SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0),
185 MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0), 188 SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0),
186 MSTP("keysc0", &r_clk, MSTPCR2, 14, 0, 0, 0), 189 SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
187 MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 11, 0, 1, 0), 190 SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB, 0),
188 MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 10, 0, 1, 1), 191 SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
189 MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0, 1, 0), 192 SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
190 MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1), 193 SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU2H1, CLK_ENABLE_ON_INIT),
191 MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1), 194 SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
192 MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1), 195 SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
193 MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1), 196 SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
194 MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1), 197 SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU2H0, CLK_ENABLE_ON_INIT),
195 MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1), 198 SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
196 MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1), 199 SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0),
197}; 200};
198 201
199int __init arch_clk_init(void) 202int __init arch_clk_init(void)
@@ -216,7 +219,7 @@ int __init arch_clk_init(void)
216 ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); 219 ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
217 220
218 if (!ret) 221 if (!ret)
219 ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); 222 ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
220 223
221 return ret; 224 return ret;
222} 225}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
index 5d5c9b952883..34611d97378e 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
@@ -22,6 +22,8 @@
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <asm/clock.h> 24#include <asm/clock.h>
25#include <asm/hwblk.h>
26#include <cpu/sh7724.h>
25 27
26/* SH7724 registers */ 28/* SH7724 registers */
27#define FRQCRA 0xa4150000 29#define FRQCRA 0xa4150000
@@ -31,9 +33,6 @@
31#define FCLKBCR 0xa415000c 33#define FCLKBCR 0xa415000c
32#define IRDACLKCR 0xa4150018 34#define IRDACLKCR 0xa4150018
33#define PLLCR 0xa4150024 35#define PLLCR 0xa4150024
34#define MSTPCR0 0xa4150030
35#define MSTPCR1 0xa4150034
36#define MSTPCR2 0xa4150038
37#define SPUCLKCR 0xa415003c 36#define SPUCLKCR 0xa415003c
38#define FLLFRQ 0xa4150050 37#define FLLFRQ 0xa4150050
39#define LSTATS 0xa4150060 38#define LSTATS 0xa4150060
@@ -156,64 +155,67 @@ struct clk div6_clks[] = {
156 SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, 0), 155 SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, 0),
157}; 156};
158 157
159#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \ 158#define R_CLK (&r_clk)
160 SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT) 159#define P_CLK (&div4_clks[DIV4_P])
160#define B_CLK (&div4_clks[DIV4_B])
161#define I_CLK (&div4_clks[DIV4_I])
162#define SH_CLK (&div4_clks[DIV4_SH])
161 163
162static struct clk mstp_clks[] = { 164static struct clk mstp_clks[] = {
163 MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0), 165 SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT),
164 MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0), 166 SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT),
165 MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0), 167 SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT),
166 MSTP("rs0", &div4_clks[DIV4_B], MSTPCR0, 28, 1, 1, 0), 168 SH_HWBLK_CLK("rs0", -1, B_CLK, HWBLK_RSMEM, CLK_ENABLE_ON_INIT),
167 MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0), 169 SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT),
168 MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 26, 1, 1, 0), 170 SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT),
169 MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0), 171 SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT),
170 MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 1, 1, 0), 172 SH_HWBLK_CLK("intc0", -1, P_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT),
171 MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1), 173 SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0),
172 MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0), 174 SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT),
173 MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0), 175 SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0),
174 MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0), 176 SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0),
175 MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0), 177 SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0),
176 MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0), 178 SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
177 MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0), 179 SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
178 MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1), 180 SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0),
179 MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0), 181 SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0),
180 MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0), 182 SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
181 MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0), 183 SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
182 MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0), 184 SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
183 MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0), 185 SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0),
184 MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0), 186 SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0),
185 MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0), 187 SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0),
186 MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0), 188 SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0),
187 MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0), 189 SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0),
188 190
189 MSTP("keysc0", &r_clk, MSTPCR1, 12, 0, 0, 0), 191 SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
190 MSTP("rtc0", &r_clk, MSTPCR1, 11, 0, 0, 0), 192 SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
191 MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0), 193 SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC0, 0),
192 MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 0, 1, 0), 194 SH_HWBLK_CLK("i2c1", -1, P_CLK, HWBLK_IIC1, 0),
193 195
194 MSTP("mmc0", &div4_clks[DIV4_B], MSTPCR2, 29, 0, 1, 0), 196 SH_HWBLK_CLK("mmc0", -1, B_CLK, HWBLK_MMC, 0),
195 MSTP("eth0", &div4_clks[DIV4_B], MSTPCR2, 28, 0, 1, 0), 197 SH_HWBLK_CLK("eth0", -1, B_CLK, HWBLK_ETHER, 0),
196 MSTP("atapi0", &div4_clks[DIV4_B], MSTPCR2, 26, 0, 1, 0), 198 SH_HWBLK_CLK("atapi0", -1, B_CLK, HWBLK_ATAPI, 0),
197 MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0), 199 SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0),
198 MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0), 200 SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0),
199 MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0), 201 SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0),
200 MSTP("usb1", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1), 202 SH_HWBLK_CLK("usb1", -1, B_CLK, HWBLK_USB1, 0),
201 MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 20, 0, 1, 1), 203 SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB0, 0),
202 MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 19, 0, 1, 1), 204 SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
203 MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0), 205 SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0),
204 MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0), 206 SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0),
205 MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 15, 1, 1, 1), 207 SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU1, CLK_ENABLE_ON_INIT),
206 MSTP("ceu1", &div4_clks[DIV4_B], MSTPCR2, 13, 0, 1, 1), 208 SH_HWBLK_CLK("ceu1", -1, B_CLK, HWBLK_CEU1, 0),
207 MSTP("beu1", &div4_clks[DIV4_B], MSTPCR2, 12, 0, 1, 1), 209 SH_HWBLK_CLK("beu1", -1, B_CLK, HWBLK_BEU1, 0),
208 MSTP("2ddmac0", &div4_clks[DIV4_SH], MSTPCR2, 10, 0, 1, 1), 210 SH_HWBLK_CLK("2ddmac0", -1, SH_CLK, HWBLK_2DDMAC, 0),
209 MSTP("spu0", &div4_clks[DIV4_B], MSTPCR2, 9, 0, 1, 0), 211 SH_HWBLK_CLK("spu0", -1, B_CLK, HWBLK_SPU, 0),
210 MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1), 212 SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, CLK_ENABLE_ON_INIT),
211 MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1), 213 SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
212 MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1), 214 SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU0, 0),
213 MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1), 215 SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU0, 0),
214 MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1), 216 SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU0, CLK_ENABLE_ON_INIT),
215 MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1), 217 SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
216 MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1), 218 SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0),
217}; 219};
218 220
219int __init arch_clk_init(void) 221int __init arch_clk_init(void)
@@ -236,7 +238,7 @@ int __init arch_clk_init(void)
236 ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); 238 ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
237 239
238 if (!ret) 240 if (!ret)
239 ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); 241 ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
240 242
241 return ret; 243 return ret;
242} 244}
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 000000000000..a288b5d92341
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
@@ -0,0 +1,106 @@
1/*
2 * arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
3 *
4 * SH7722 hardware block support
5 *
6 * Copyright (C) 2009 Magnus Damm
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/init.h>
22#include <linux/kernel.h>
23#include <linux/io.h>
24#include <asm/suspend.h>
25#include <asm/hwblk.h>
26#include <cpu/sh7722.h>
27
28/* SH7722 registers */
29#define MSTPCR0 0xa4150030
30#define MSTPCR1 0xa4150034
31#define MSTPCR2 0xa4150038
32
33/* SH7722 Power Domains */
34enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
35static struct hwblk_area sh7722_hwblk_area[] = {
36 [CORE_AREA] = HWBLK_AREA(0, 0),
37 [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
38 [SUB_AREA] = HWBLK_AREA(0, 0),
39};
40
41/* Table mapping HWBLK to Module Stop Bit and Power Domain */
42static struct hwblk sh7722_hwblk[HWBLK_NR] = {
43 [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
44 [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
45 [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
46 [HWBLK_URAM] = HWBLK(MSTPCR0, 28, CORE_AREA),
47 [HWBLK_XYMEM] = HWBLK(MSTPCR0, 26, CORE_AREA),
48 [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
49 [HWBLK_DMAC] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
50 [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
51 [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
52 [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
53 [HWBLK_TMU] = HWBLK(MSTPCR0, 15, CORE_AREA),
54 [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
55 [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
56 [HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA),
57 [HWBLK_SCIF0] = HWBLK(MSTPCR0, 7, CORE_AREA),
58 [HWBLK_SCIF1] = HWBLK(MSTPCR0, 6, CORE_AREA),
59 [HWBLK_SCIF2] = HWBLK(MSTPCR0, 5, CORE_AREA),
60 [HWBLK_SIO] = HWBLK(MSTPCR0, 3, CORE_AREA),
61 [HWBLK_SIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
62 [HWBLK_SIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
63
64 [HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA),
65 [HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA),
66
67 [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
68 [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
69 [HWBLK_SDHI] = HWBLK(MSTPCR2, 18, CORE_AREA),
70 [HWBLK_SIM] = HWBLK(MSTPCR2, 16, CORE_AREA),
71 [HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA),
72 [HWBLK_TSIF] = HWBLK(MSTPCR2, 13, SUB_AREA),
73 [HWBLK_USBF] = HWBLK(MSTPCR2, 11, CORE_AREA),
74 [HWBLK_2DG] = HWBLK(MSTPCR2, 9, CORE_AREA_BM),
75 [HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA),
76 [HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
77 [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
78 [HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
79 [HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
80 [HWBLK_VEU] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
81 [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
82 [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
83};
84
85static struct hwblk_info sh7722_hwblk_info = {
86 .areas = sh7722_hwblk_area,
87 .nr_areas = ARRAY_SIZE(sh7722_hwblk_area),
88 .hwblks = sh7722_hwblk,
89 .nr_hwblks = ARRAY_SIZE(sh7722_hwblk),
90};
91
92int arch_hwblk_sleep_mode(void)
93{
94 if (!sh7722_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
95 return SUSP_SH_STANDBY | SUSP_SH_SF;
96
97 if (!sh7722_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
98 return SUSP_SH_SLEEP | SUSP_SH_SF;
99
100 return SUSP_SH_SLEEP;
101}
102
103int __init arch_hwblk_init(void)
104{
105 return hwblk_register(&sh7722_hwblk_info);
106}
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 000000000000..a7f4684d2032
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
@@ -0,0 +1,117 @@
1/*
2 * arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
3 *
4 * SH7723 hardware block support
5 *
6 * Copyright (C) 2009 Magnus Damm
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/init.h>
22#include <linux/kernel.h>
23#include <linux/io.h>
24#include <asm/suspend.h>
25#include <asm/hwblk.h>
26#include <cpu/sh7723.h>
27
28/* SH7723 registers */
29#define MSTPCR0 0xa4150030
30#define MSTPCR1 0xa4150034
31#define MSTPCR2 0xa4150038
32
33/* SH7723 Power Domains */
34enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
35static struct hwblk_area sh7723_hwblk_area[] = {
36 [CORE_AREA] = HWBLK_AREA(0, 0),
37 [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
38 [SUB_AREA] = HWBLK_AREA(0, 0),
39};
40
41/* Table mapping HWBLK to Module Stop Bit and Power Domain */
42static struct hwblk sh7723_hwblk[HWBLK_NR] = {
43 [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
44 [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
45 [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
46 [HWBLK_L2C] = HWBLK(MSTPCR0, 28, CORE_AREA),
47 [HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA),
48 [HWBLK_FPU] = HWBLK(MSTPCR0, 24, CORE_AREA),
49 [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
50 [HWBLK_DMAC0] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
51 [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
52 [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
53 [HWBLK_DBG] = HWBLK(MSTPCR0, 18, CORE_AREA),
54 [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
55 [HWBLK_SUBC] = HWBLK(MSTPCR0, 16, CORE_AREA),
56 [HWBLK_TMU0] = HWBLK(MSTPCR0, 15, CORE_AREA),
57 [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
58 [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
59 [HWBLK_DMAC1] = HWBLK(MSTPCR0, 12, CORE_AREA_BM),
60 [HWBLK_TMU1] = HWBLK(MSTPCR0, 11, CORE_AREA),
61 [HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA),
62 [HWBLK_SCIF0] = HWBLK(MSTPCR0, 9, CORE_AREA),
63 [HWBLK_SCIF1] = HWBLK(MSTPCR0, 8, CORE_AREA),
64 [HWBLK_SCIF2] = HWBLK(MSTPCR0, 7, CORE_AREA),
65 [HWBLK_SCIF3] = HWBLK(MSTPCR0, 6, CORE_AREA),
66 [HWBLK_SCIF4] = HWBLK(MSTPCR0, 5, CORE_AREA),
67 [HWBLK_SCIF5] = HWBLK(MSTPCR0, 4, CORE_AREA),
68 [HWBLK_MSIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
69 [HWBLK_MSIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
70 [HWBLK_MERAM] = HWBLK(MSTPCR0, 0, CORE_AREA),
71
72 [HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA),
73 [HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA),
74
75 [HWBLK_ATAPI] = HWBLK(MSTPCR2, 28, CORE_AREA_BM),
76 [HWBLK_ADC] = HWBLK(MSTPCR2, 27, CORE_AREA),
77 [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
78 [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
79 [HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA),
80 [HWBLK_ICB] = HWBLK(MSTPCR2, 21, CORE_AREA_BM),
81 [HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA),
82 [HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA),
83 [HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA),
84 [HWBLK_USB] = HWBLK(MSTPCR2, 11, CORE_AREA),
85 [HWBLK_2DG] = HWBLK(MSTPCR2, 10, CORE_AREA_BM),
86 [HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA),
87 [HWBLK_VEU2H1] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
88 [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
89 [HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
90 [HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
91 [HWBLK_VEU2H0] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
92 [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
93 [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
94};
95
96static struct hwblk_info sh7723_hwblk_info = {
97 .areas = sh7723_hwblk_area,
98 .nr_areas = ARRAY_SIZE(sh7723_hwblk_area),
99 .hwblks = sh7723_hwblk,
100 .nr_hwblks = ARRAY_SIZE(sh7723_hwblk),
101};
102
103int arch_hwblk_sleep_mode(void)
104{
105 if (!sh7723_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
106 return SUSP_SH_STANDBY | SUSP_SH_SF;
107
108 if (!sh7723_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
109 return SUSP_SH_SLEEP | SUSP_SH_SF;
110
111 return SUSP_SH_SLEEP;
112}
113
114int __init arch_hwblk_init(void)
115{
116 return hwblk_register(&sh7723_hwblk_info);
117}
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 000000000000..1613ad6013c3
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c
@@ -0,0 +1,121 @@
1/*
2 * arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c
3 *
4 * SH7724 hardware block support
5 *
6 * Copyright (C) 2009 Magnus Damm
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/init.h>
22#include <linux/kernel.h>
23#include <linux/io.h>
24#include <asm/suspend.h>
25#include <asm/hwblk.h>
26#include <cpu/sh7724.h>
27
28/* SH7724 registers */
29#define MSTPCR0 0xa4150030
30#define MSTPCR1 0xa4150034
31#define MSTPCR2 0xa4150038
32
33/* SH7724 Power Domains */
34enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
35static struct hwblk_area sh7724_hwblk_area[] = {
36 [CORE_AREA] = HWBLK_AREA(0, 0),
37 [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
38 [SUB_AREA] = HWBLK_AREA(0, 0),
39};
40
41/* Table mapping HWBLK to Module Stop Bit and Power Domain */
42static struct hwblk sh7724_hwblk[HWBLK_NR] = {
43 [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
44 [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
45 [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
46 [HWBLK_RSMEM] = HWBLK(MSTPCR0, 28, CORE_AREA),
47 [HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA),
48 [HWBLK_L2C] = HWBLK(MSTPCR0, 26, CORE_AREA),
49 [HWBLK_FPU] = HWBLK(MSTPCR0, 24, CORE_AREA),
50 [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
51 [HWBLK_DMAC0] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
52 [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
53 [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
54 [HWBLK_DBG] = HWBLK(MSTPCR0, 18, CORE_AREA),
55 [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
56 [HWBLK_TMU0] = HWBLK(MSTPCR0, 15, CORE_AREA),
57 [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
58 [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
59 [HWBLK_DMAC1] = HWBLK(MSTPCR0, 12, CORE_AREA_BM),
60 [HWBLK_TMU1] = HWBLK(MSTPCR0, 10, CORE_AREA),
61 [HWBLK_SCIF0] = HWBLK(MSTPCR0, 9, CORE_AREA),
62 [HWBLK_SCIF1] = HWBLK(MSTPCR0, 8, CORE_AREA),
63 [HWBLK_SCIF2] = HWBLK(MSTPCR0, 7, CORE_AREA),
64 [HWBLK_SCIF3] = HWBLK(MSTPCR0, 6, CORE_AREA),
65 [HWBLK_SCIF4] = HWBLK(MSTPCR0, 5, CORE_AREA),
66 [HWBLK_SCIF5] = HWBLK(MSTPCR0, 4, CORE_AREA),
67 [HWBLK_MSIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
68 [HWBLK_MSIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
69
70 [HWBLK_KEYSC] = HWBLK(MSTPCR1, 12, SUB_AREA),
71 [HWBLK_RTC] = HWBLK(MSTPCR1, 11, SUB_AREA),
72 [HWBLK_IIC0] = HWBLK(MSTPCR1, 9, CORE_AREA),
73 [HWBLK_IIC1] = HWBLK(MSTPCR1, 8, CORE_AREA),
74
75 [HWBLK_MMC] = HWBLK(MSTPCR2, 29, CORE_AREA),
76 [HWBLK_ETHER] = HWBLK(MSTPCR2, 28, CORE_AREA_BM),
77 [HWBLK_ATAPI] = HWBLK(MSTPCR2, 26, CORE_AREA_BM),
78 [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
79 [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
80 [HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA),
81 [HWBLK_USB1] = HWBLK(MSTPCR2, 21, CORE_AREA),
82 [HWBLK_USB0] = HWBLK(MSTPCR2, 20, CORE_AREA),
83 [HWBLK_2DG] = HWBLK(MSTPCR2, 19, CORE_AREA_BM),
84 [HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA),
85 [HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA),
86 [HWBLK_VEU1] = HWBLK(MSTPCR2, 15, CORE_AREA_BM),
87 [HWBLK_CEU1] = HWBLK(MSTPCR2, 13, CORE_AREA_BM),
88 [HWBLK_BEU1] = HWBLK(MSTPCR2, 12, CORE_AREA_BM),
89 [HWBLK_2DDMAC] = HWBLK(MSTPCR2, 10, CORE_AREA_BM),
90 [HWBLK_SPU] = HWBLK(MSTPCR2, 9, CORE_AREA_BM),
91 [HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
92 [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
93 [HWBLK_BEU0] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
94 [HWBLK_CEU0] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
95 [HWBLK_VEU0] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
96 [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
97 [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
98};
99
100static struct hwblk_info sh7724_hwblk_info = {
101 .areas = sh7724_hwblk_area,
102 .nr_areas = ARRAY_SIZE(sh7724_hwblk_area),
103 .hwblks = sh7724_hwblk,
104 .nr_hwblks = ARRAY_SIZE(sh7724_hwblk),
105};
106
107int arch_hwblk_sleep_mode(void)
108{
109 if (!sh7724_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
110 return SUSP_SH_STANDBY | SUSP_SH_SF;
111
112 if (!sh7724_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
113 return SUSP_SH_SLEEP | SUSP_SH_SF;
114
115 return SUSP_SH_SLEEP;
116}
117
118int __init arch_hwblk_init(void)
119{
120 return hwblk_register(&sh7724_hwblk_info);
121}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index 1a956b1beccc..4a9010bf4fd3 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 = {
40}; 40};
41 41
42static struct r8a66597_platdata r8a66597_data = { 42static struct r8a66597_platdata r8a66597_data = {
43 /* This set zero to all members */ 43 .on_chip = 1,
44}; 44};
45 45
46static struct resource usb_host_resources[] = { 46static 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 cda76ebf87c3..35097753456c 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -13,9 +13,11 @@
13#include <linux/serial_sci.h> 13#include <linux/serial_sci.h>
14#include <linux/mm.h> 14#include <linux/mm.h>
15#include <linux/uio_driver.h> 15#include <linux/uio_driver.h>
16#include <linux/usb/m66592.h>
16#include <linux/sh_timer.h> 17#include <linux/sh_timer.h>
17#include <asm/clock.h> 18#include <asm/clock.h>
18#include <asm/mmzone.h> 19#include <asm/mmzone.h>
20#include <cpu/sh7722.h>
19 21
20static struct resource rtc_resources[] = { 22static struct resource rtc_resources[] = {
21 [0] = { 23 [0] = {
@@ -45,11 +47,18 @@ static struct platform_device rtc_device = {
45 .id = -1, 47 .id = -1,
46 .num_resources = ARRAY_SIZE(rtc_resources), 48 .num_resources = ARRAY_SIZE(rtc_resources),
47 .resource = rtc_resources, 49 .resource = rtc_resources,
50 .archdata = {
51 .hwblk_id = HWBLK_RTC,
52 },
53};
54
55static struct m66592_platdata usbf_platdata = {
56 .on_chip = 1,
48}; 57};
49 58
50static struct resource usbf_resources[] = { 59static struct resource usbf_resources[] = {
51 [0] = { 60 [0] = {
52 .name = "m66592_udc", 61 .name = "USBF",
53 .start = 0x04480000, 62 .start = 0x04480000,
54 .end = 0x044800FF, 63 .end = 0x044800FF,
55 .flags = IORESOURCE_MEM, 64 .flags = IORESOURCE_MEM,
@@ -67,9 +76,13 @@ static struct platform_device usbf_device = {
67 .dev = { 76 .dev = {
68 .dma_mask = NULL, 77 .dma_mask = NULL,
69 .coherent_dma_mask = 0xffffffff, 78 .coherent_dma_mask = 0xffffffff,
79 .platform_data = &usbf_platdata,
70 }, 80 },
71 .num_resources = ARRAY_SIZE(usbf_resources), 81 .num_resources = ARRAY_SIZE(usbf_resources),
72 .resource = usbf_resources, 82 .resource = usbf_resources,
83 .archdata = {
84 .hwblk_id = HWBLK_USBF,
85 },
73}; 86};
74 87
75static struct resource iic_resources[] = { 88static struct resource iic_resources[] = {
@@ -91,6 +104,9 @@ static struct platform_device iic_device = {
91 .id = 0, /* "i2c0" clock */ 104 .id = 0, /* "i2c0" clock */
92 .num_resources = ARRAY_SIZE(iic_resources), 105 .num_resources = ARRAY_SIZE(iic_resources),
93 .resource = iic_resources, 106 .resource = iic_resources,
107 .archdata = {
108 .hwblk_id = HWBLK_IIC,
109 },
94}; 110};
95 111
96static struct uio_info vpu_platform_data = { 112static struct uio_info vpu_platform_data = {
@@ -119,6 +135,9 @@ static struct platform_device vpu_device = {
119 }, 135 },
120 .resource = vpu_resources, 136 .resource = vpu_resources,
121 .num_resources = ARRAY_SIZE(vpu_resources), 137 .num_resources = ARRAY_SIZE(vpu_resources),
138 .archdata = {
139 .hwblk_id = HWBLK_VPU,
140 },
122}; 141};
123 142
124static struct uio_info veu_platform_data = { 143static struct uio_info veu_platform_data = {
@@ -147,6 +166,9 @@ static struct platform_device veu_device = {
147 }, 166 },
148 .resource = veu_resources, 167 .resource = veu_resources,
149 .num_resources = ARRAY_SIZE(veu_resources), 168 .num_resources = ARRAY_SIZE(veu_resources),
169 .archdata = {
170 .hwblk_id = HWBLK_VEU,
171 },
150}; 172};
151 173
152static struct uio_info jpu_platform_data = { 174static struct uio_info jpu_platform_data = {
@@ -175,6 +197,9 @@ static struct platform_device jpu_device = {
175 }, 197 },
176 .resource = jpu_resources, 198 .resource = jpu_resources,
177 .num_resources = ARRAY_SIZE(jpu_resources), 199 .num_resources = ARRAY_SIZE(jpu_resources),
200 .archdata = {
201 .hwblk_id = HWBLK_JPU,
202 },
178}; 203};
179 204
180static struct sh_timer_config cmt_platform_data = { 205static struct sh_timer_config cmt_platform_data = {
@@ -207,6 +232,9 @@ static struct platform_device cmt_device = {
207 }, 232 },
208 .resource = cmt_resources, 233 .resource = cmt_resources,
209 .num_resources = ARRAY_SIZE(cmt_resources), 234 .num_resources = ARRAY_SIZE(cmt_resources),
235 .archdata = {
236 .hwblk_id = HWBLK_CMT,
237 },
210}; 238};
211 239
212static struct sh_timer_config tmu0_platform_data = { 240static struct sh_timer_config tmu0_platform_data = {
@@ -238,6 +266,9 @@ static struct platform_device tmu0_device = {
238 }, 266 },
239 .resource = tmu0_resources, 267 .resource = tmu0_resources,
240 .num_resources = ARRAY_SIZE(tmu0_resources), 268 .num_resources = ARRAY_SIZE(tmu0_resources),
269 .archdata = {
270 .hwblk_id = HWBLK_TMU,
271 },
241}; 272};
242 273
243static struct sh_timer_config tmu1_platform_data = { 274static struct sh_timer_config tmu1_platform_data = {
@@ -269,6 +300,9 @@ static struct platform_device tmu1_device = {
269 }, 300 },
270 .resource = tmu1_resources, 301 .resource = tmu1_resources,
271 .num_resources = ARRAY_SIZE(tmu1_resources), 302 .num_resources = ARRAY_SIZE(tmu1_resources),
303 .archdata = {
304 .hwblk_id = HWBLK_TMU,
305 },
272}; 306};
273 307
274static struct sh_timer_config tmu2_platform_data = { 308static struct sh_timer_config tmu2_platform_data = {
@@ -299,6 +333,9 @@ static struct platform_device tmu2_device = {
299 }, 333 },
300 .resource = tmu2_resources, 334 .resource = tmu2_resources,
301 .num_resources = ARRAY_SIZE(tmu2_resources), 335 .num_resources = ARRAY_SIZE(tmu2_resources),
336 .archdata = {
337 .hwblk_id = HWBLK_TMU,
338 },
302}; 339};
303 340
304static struct plat_sci_port sci_platform_data[] = { 341static struct plat_sci_port sci_platform_data[] = {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index b45dace9539f..4caa5a7ca86e 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -18,6 +18,7 @@
18#include <linux/io.h> 18#include <linux/io.h>
19#include <asm/clock.h> 19#include <asm/clock.h>
20#include <asm/mmzone.h> 20#include <asm/mmzone.h>
21#include <cpu/sh7723.h>
21 22
22static struct uio_info vpu_platform_data = { 23static struct uio_info vpu_platform_data = {
23 .name = "VPU5", 24 .name = "VPU5",
@@ -45,6 +46,9 @@ static struct platform_device vpu_device = {
45 }, 46 },
46 .resource = vpu_resources, 47 .resource = vpu_resources,
47 .num_resources = ARRAY_SIZE(vpu_resources), 48 .num_resources = ARRAY_SIZE(vpu_resources),
49 .archdata = {
50 .hwblk_id = HWBLK_VPU,
51 },
48}; 52};
49 53
50static struct uio_info veu0_platform_data = { 54static struct uio_info veu0_platform_data = {
@@ -73,6 +77,9 @@ static struct platform_device veu0_device = {
73 }, 77 },
74 .resource = veu0_resources, 78 .resource = veu0_resources,
75 .num_resources = ARRAY_SIZE(veu0_resources), 79 .num_resources = ARRAY_SIZE(veu0_resources),
80 .archdata = {
81 .hwblk_id = HWBLK_VEU2H0,
82 },
76}; 83};
77 84
78static struct uio_info veu1_platform_data = { 85static struct uio_info veu1_platform_data = {
@@ -101,6 +108,9 @@ static struct platform_device veu1_device = {
101 }, 108 },
102 .resource = veu1_resources, 109 .resource = veu1_resources,
103 .num_resources = ARRAY_SIZE(veu1_resources), 110 .num_resources = ARRAY_SIZE(veu1_resources),
111 .archdata = {
112 .hwblk_id = HWBLK_VEU2H1,
113 },
104}; 114};
105 115
106static struct sh_timer_config cmt_platform_data = { 116static struct sh_timer_config cmt_platform_data = {
@@ -133,6 +143,9 @@ static struct platform_device cmt_device = {
133 }, 143 },
134 .resource = cmt_resources, 144 .resource = cmt_resources,
135 .num_resources = ARRAY_SIZE(cmt_resources), 145 .num_resources = ARRAY_SIZE(cmt_resources),
146 .archdata = {
147 .hwblk_id = HWBLK_CMT,
148 },
136}; 149};
137 150
138static struct sh_timer_config tmu0_platform_data = { 151static struct sh_timer_config tmu0_platform_data = {
@@ -164,6 +177,9 @@ static struct platform_device tmu0_device = {
164 }, 177 },
165 .resource = tmu0_resources, 178 .resource = tmu0_resources,
166 .num_resources = ARRAY_SIZE(tmu0_resources), 179 .num_resources = ARRAY_SIZE(tmu0_resources),
180 .archdata = {
181 .hwblk_id = HWBLK_TMU0,
182 },
167}; 183};
168 184
169static struct sh_timer_config tmu1_platform_data = { 185static struct sh_timer_config tmu1_platform_data = {
@@ -195,6 +211,9 @@ static struct platform_device tmu1_device = {
195 }, 211 },
196 .resource = tmu1_resources, 212 .resource = tmu1_resources,
197 .num_resources = ARRAY_SIZE(tmu1_resources), 213 .num_resources = ARRAY_SIZE(tmu1_resources),
214 .archdata = {
215 .hwblk_id = HWBLK_TMU0,
216 },
198}; 217};
199 218
200static struct sh_timer_config tmu2_platform_data = { 219static struct sh_timer_config tmu2_platform_data = {
@@ -225,6 +244,9 @@ static struct platform_device tmu2_device = {
225 }, 244 },
226 .resource = tmu2_resources, 245 .resource = tmu2_resources,
227 .num_resources = ARRAY_SIZE(tmu2_resources), 246 .num_resources = ARRAY_SIZE(tmu2_resources),
247 .archdata = {
248 .hwblk_id = HWBLK_TMU0,
249 },
228}; 250};
229 251
230static struct sh_timer_config tmu3_platform_data = { 252static struct sh_timer_config tmu3_platform_data = {
@@ -255,6 +277,9 @@ static struct platform_device tmu3_device = {
255 }, 277 },
256 .resource = tmu3_resources, 278 .resource = tmu3_resources,
257 .num_resources = ARRAY_SIZE(tmu3_resources), 279 .num_resources = ARRAY_SIZE(tmu3_resources),
280 .archdata = {
281 .hwblk_id = HWBLK_TMU1,
282 },
258}; 283};
259 284
260static struct sh_timer_config tmu4_platform_data = { 285static struct sh_timer_config tmu4_platform_data = {
@@ -285,6 +310,9 @@ static struct platform_device tmu4_device = {
285 }, 310 },
286 .resource = tmu4_resources, 311 .resource = tmu4_resources,
287 .num_resources = ARRAY_SIZE(tmu4_resources), 312 .num_resources = ARRAY_SIZE(tmu4_resources),
313 .archdata = {
314 .hwblk_id = HWBLK_TMU1,
315 },
288}; 316};
289 317
290static struct sh_timer_config tmu5_platform_data = { 318static struct sh_timer_config tmu5_platform_data = {
@@ -315,6 +343,9 @@ static struct platform_device tmu5_device = {
315 }, 343 },
316 .resource = tmu5_resources, 344 .resource = tmu5_resources,
317 .num_resources = ARRAY_SIZE(tmu5_resources), 345 .num_resources = ARRAY_SIZE(tmu5_resources),
346 .archdata = {
347 .hwblk_id = HWBLK_TMU1,
348 },
318}; 349};
319 350
320static struct plat_sci_port sci_platform_data[] = { 351static struct plat_sci_port sci_platform_data[] = {
@@ -395,10 +426,13 @@ static struct platform_device rtc_device = {
395 .id = -1, 426 .id = -1,
396 .num_resources = ARRAY_SIZE(rtc_resources), 427 .num_resources = ARRAY_SIZE(rtc_resources),
397 .resource = rtc_resources, 428 .resource = rtc_resources,
429 .archdata = {
430 .hwblk_id = HWBLK_RTC,
431 },
398}; 432};
399 433
400static struct r8a66597_platdata r8a66597_data = { 434static struct r8a66597_platdata r8a66597_data = {
401 /* This set zero to all members */ 435 .on_chip = 1,
402}; 436};
403 437
404static struct resource sh7723_usb_host_resources[] = { 438static struct resource sh7723_usb_host_resources[] = {
@@ -424,6 +458,9 @@ static struct platform_device sh7723_usb_host_device = {
424 }, 458 },
425 .num_resources = ARRAY_SIZE(sh7723_usb_host_resources), 459 .num_resources = ARRAY_SIZE(sh7723_usb_host_resources),
426 .resource = sh7723_usb_host_resources, 460 .resource = sh7723_usb_host_resources,
461 .archdata = {
462 .hwblk_id = HWBLK_USB,
463 },
427}; 464};
428 465
429static struct resource iic_resources[] = { 466static struct resource iic_resources[] = {
@@ -445,6 +482,9 @@ static struct platform_device iic_device = {
445 .id = 0, /* "i2c0" clock */ 482 .id = 0, /* "i2c0" clock */
446 .num_resources = ARRAY_SIZE(iic_resources), 483 .num_resources = ARRAY_SIZE(iic_resources),
447 .resource = iic_resources, 484 .resource = iic_resources,
485 .archdata = {
486 .hwblk_id = HWBLK_IIC,
487 },
448}; 488};
449 489
450static struct platform_device *sh7723_devices[] __initdata = { 490static struct platform_device *sh7723_devices[] __initdata = {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index a04edaab9a29..f3851fd757ec 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -22,6 +22,7 @@
22#include <linux/io.h> 22#include <linux/io.h>
23#include <asm/clock.h> 23#include <asm/clock.h>
24#include <asm/mmzone.h> 24#include <asm/mmzone.h>
25#include <cpu/sh7724.h>
25 26
26/* Serial */ 27/* Serial */
27static struct plat_sci_port sci_platform_data[] = { 28static struct plat_sci_port sci_platform_data[] = {
@@ -103,6 +104,9 @@ static struct platform_device rtc_device = {
103 .id = -1, 104 .id = -1,
104 .num_resources = ARRAY_SIZE(rtc_resources), 105 .num_resources = ARRAY_SIZE(rtc_resources),
105 .resource = rtc_resources, 106 .resource = rtc_resources,
107 .archdata = {
108 .hwblk_id = HWBLK_RTC,
109 },
106}; 110};
107 111
108/* I2C0 */ 112/* I2C0 */
@@ -125,6 +129,9 @@ static struct platform_device iic0_device = {
125 .id = 0, /* "i2c0" clock */ 129 .id = 0, /* "i2c0" clock */
126 .num_resources = ARRAY_SIZE(iic0_resources), 130 .num_resources = ARRAY_SIZE(iic0_resources),
127 .resource = iic0_resources, 131 .resource = iic0_resources,
132 .archdata = {
133 .hwblk_id = HWBLK_IIC0,
134 },
128}; 135};
129 136
130/* I2C1 */ 137/* I2C1 */
@@ -147,6 +154,9 @@ static struct platform_device iic1_device = {
147 .id = 1, /* "i2c1" clock */ 154 .id = 1, /* "i2c1" clock */
148 .num_resources = ARRAY_SIZE(iic1_resources), 155 .num_resources = ARRAY_SIZE(iic1_resources),
149 .resource = iic1_resources, 156 .resource = iic1_resources,
157 .archdata = {
158 .hwblk_id = HWBLK_IIC1,
159 },
150}; 160};
151 161
152/* VPU */ 162/* VPU */
@@ -176,6 +186,9 @@ static struct platform_device vpu_device = {
176 }, 186 },
177 .resource = vpu_resources, 187 .resource = vpu_resources,
178 .num_resources = ARRAY_SIZE(vpu_resources), 188 .num_resources = ARRAY_SIZE(vpu_resources),
189 .archdata = {
190 .hwblk_id = HWBLK_VPU,
191 },
179}; 192};
180 193
181/* VEU0 */ 194/* VEU0 */
@@ -205,6 +218,9 @@ static struct platform_device veu0_device = {
205 }, 218 },
206 .resource = veu0_resources, 219 .resource = veu0_resources,
207 .num_resources = ARRAY_SIZE(veu0_resources), 220 .num_resources = ARRAY_SIZE(veu0_resources),
221 .archdata = {
222 .hwblk_id = HWBLK_VEU0,
223 },
208}; 224};
209 225
210/* VEU1 */ 226/* VEU1 */
@@ -234,6 +250,9 @@ static struct platform_device veu1_device = {
234 }, 250 },
235 .resource = veu1_resources, 251 .resource = veu1_resources,
236 .num_resources = ARRAY_SIZE(veu1_resources), 252 .num_resources = ARRAY_SIZE(veu1_resources),
253 .archdata = {
254 .hwblk_id = HWBLK_VEU1,
255 },
237}; 256};
238 257
239static struct sh_timer_config cmt_platform_data = { 258static struct sh_timer_config cmt_platform_data = {
@@ -266,6 +285,9 @@ static struct platform_device cmt_device = {
266 }, 285 },
267 .resource = cmt_resources, 286 .resource = cmt_resources,
268 .num_resources = ARRAY_SIZE(cmt_resources), 287 .num_resources = ARRAY_SIZE(cmt_resources),
288 .archdata = {
289 .hwblk_id = HWBLK_CMT,
290 },
269}; 291};
270 292
271static struct sh_timer_config tmu0_platform_data = { 293static struct sh_timer_config tmu0_platform_data = {
@@ -297,6 +319,9 @@ static struct platform_device tmu0_device = {
297 }, 319 },
298 .resource = tmu0_resources, 320 .resource = tmu0_resources,
299 .num_resources = ARRAY_SIZE(tmu0_resources), 321 .num_resources = ARRAY_SIZE(tmu0_resources),
322 .archdata = {
323 .hwblk_id = HWBLK_TMU0,
324 },
300}; 325};
301 326
302static struct sh_timer_config tmu1_platform_data = { 327static struct sh_timer_config tmu1_platform_data = {
@@ -328,6 +353,9 @@ static struct platform_device tmu1_device = {
328 }, 353 },
329 .resource = tmu1_resources, 354 .resource = tmu1_resources,
330 .num_resources = ARRAY_SIZE(tmu1_resources), 355 .num_resources = ARRAY_SIZE(tmu1_resources),
356 .archdata = {
357 .hwblk_id = HWBLK_TMU0,
358 },
331}; 359};
332 360
333static struct sh_timer_config tmu2_platform_data = { 361static struct sh_timer_config tmu2_platform_data = {
@@ -358,6 +386,9 @@ static struct platform_device tmu2_device = {
358 }, 386 },
359 .resource = tmu2_resources, 387 .resource = tmu2_resources,
360 .num_resources = ARRAY_SIZE(tmu2_resources), 388 .num_resources = ARRAY_SIZE(tmu2_resources),
389 .archdata = {
390 .hwblk_id = HWBLK_TMU0,
391 },
361}; 392};
362 393
363 394
@@ -389,6 +420,9 @@ static struct platform_device tmu3_device = {
389 }, 420 },
390 .resource = tmu3_resources, 421 .resource = tmu3_resources,
391 .num_resources = ARRAY_SIZE(tmu3_resources), 422 .num_resources = ARRAY_SIZE(tmu3_resources),
423 .archdata = {
424 .hwblk_id = HWBLK_TMU1,
425 },
392}; 426};
393 427
394static struct sh_timer_config tmu4_platform_data = { 428static struct sh_timer_config tmu4_platform_data = {
@@ -419,6 +453,9 @@ static struct platform_device tmu4_device = {
419 }, 453 },
420 .resource = tmu4_resources, 454 .resource = tmu4_resources,
421 .num_resources = ARRAY_SIZE(tmu4_resources), 455 .num_resources = ARRAY_SIZE(tmu4_resources),
456 .archdata = {
457 .hwblk_id = HWBLK_TMU1,
458 },
422}; 459};
423 460
424static struct sh_timer_config tmu5_platform_data = { 461static struct sh_timer_config tmu5_platform_data = {
@@ -449,6 +486,9 @@ static struct platform_device tmu5_device = {
449 }, 486 },
450 .resource = tmu5_resources, 487 .resource = tmu5_resources,
451 .num_resources = ARRAY_SIZE(tmu5_resources), 488 .num_resources = ARRAY_SIZE(tmu5_resources),
489 .archdata = {
490 .hwblk_id = HWBLK_TMU1,
491 },
452}; 492};
453 493
454/* JPU */ 494/* JPU */
@@ -478,6 +518,9 @@ static struct platform_device jpu_device = {
478 }, 518 },
479 .resource = jpu_resources, 519 .resource = jpu_resources,
480 .num_resources = ARRAY_SIZE(jpu_resources), 520 .num_resources = ARRAY_SIZE(jpu_resources),
521 .archdata = {
522 .hwblk_id = HWBLK_JPU,
523 },
481}; 524};
482 525
483static struct platform_device *sh7724_devices[] __initdata = { 526static struct platform_device *sh7724_devices[] __initdata = {
diff --git a/arch/sh/kernel/cpu/shmobile/Makefile b/arch/sh/kernel/cpu/shmobile/Makefile
index 08bfa7c7db29..e8a5111e848a 100644
--- a/arch/sh/kernel/cpu/shmobile/Makefile
+++ b/arch/sh/kernel/cpu/shmobile/Makefile
@@ -4,3 +4,4 @@
4 4
5# Power Management & Sleep mode 5# Power Management & Sleep mode
6obj-$(CONFIG_PM) += pm.o sleep.o 6obj-$(CONFIG_PM) += pm.o sleep.o
7obj-$(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 000000000000..4afdd975cc66
--- /dev/null
+++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
@@ -0,0 +1,102 @@
1/*
2 * arch/sh/kernel/cpu/shmobile/cpuidle.c
3 *
4 * Cpuidle support code for SuperH Mobile
5 *
6 * Copyright (C) 2009 Magnus Damm
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/io.h>
15#include <linux/suspend.h>
16#include <linux/cpuidle.h>
17#include <asm/suspend.h>
18#include <asm/uaccess.h>
19#include <asm/hwblk.h>
20
21static unsigned long cpuidle_mode[] = {
22 SUSP_SH_SLEEP, /* regular sleep mode */
23 SUSP_SH_SLEEP | SUSP_SH_SF, /* sleep mode + self refresh */
24};
25
26static int cpuidle_sleep_enter(struct cpuidle_device *dev,
27 struct cpuidle_state *state)
28{
29 unsigned long allowed_mode = arch_hwblk_sleep_mode();
30 ktime_t before, after;
31 int requested_state = state - &dev->states[0];
32 int allowed_state;
33 int k;
34
35 /* convert allowed mode to allowed state */
36 for (k = ARRAY_SIZE(cpuidle_mode) - 1; k > 0; k--)
37 if (cpuidle_mode[k] == allowed_mode)
38 break;
39
40 allowed_state = k;
41
42 /* take the following into account for sleep mode selection:
43 * - allowed_state: best mode allowed by hardware (clock deps)
44 * - requested_state: best mode allowed by software (latencies)
45 */
46 k = min_t(int, allowed_state, requested_state);
47
48 dev->last_state = &dev->states[k];
49 before = ktime_get();
50 sh_mobile_call_standby(cpuidle_mode[k]);
51 after = ktime_get();
52 return ktime_to_ns(ktime_sub(after, before)) >> 10;
53}
54
55static struct cpuidle_device cpuidle_dev;
56static struct cpuidle_driver cpuidle_driver = {
57 .name = "sh_idle",
58 .owner = THIS_MODULE,
59};
60
61void sh_mobile_setup_cpuidle(void)
62{
63 struct cpuidle_device *dev = &cpuidle_dev;
64 struct cpuidle_state *state;
65 int i;
66
67 cpuidle_register_driver(&cpuidle_driver);
68
69 for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
70 dev->states[i].name[0] = '\0';
71 dev->states[i].desc[0] = '\0';
72 }
73
74 i = CPUIDLE_DRIVER_STATE_START;
75
76 state = &dev->states[i++];
77 snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
78 strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
79 state->exit_latency = 1;
80 state->target_residency = 1 * 2;
81 state->power_usage = 3;
82 state->flags = 0;
83 state->flags |= CPUIDLE_FLAG_SHALLOW;
84 state->flags |= CPUIDLE_FLAG_TIME_VALID;
85 state->enter = cpuidle_sleep_enter;
86
87 dev->safe_state = state;
88
89 state = &dev->states[i++];
90 snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
91 strncpy(state->desc, "SuperH Sleep Mode [SF]", CPUIDLE_DESC_LEN);
92 state->exit_latency = 100;
93 state->target_residency = 1 * 2;
94 state->power_usage = 1;
95 state->flags = 0;
96 state->flags |= CPUIDLE_FLAG_TIME_VALID;
97 state->enter = cpuidle_sleep_enter;
98
99 dev->state_count = i;
100
101 cpuidle_register_device(dev);
102}
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
index 8c067adf6830..de078d24ce56 100644
--- a/arch/sh/kernel/cpu/shmobile/pm.c
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c 2 * arch/sh/kernel/cpu/shmobile/pm.c
3 * 3 *
4 * Power management support code for SuperH Mobile 4 * Power management support code for SuperH Mobile
5 * 5 *
@@ -32,20 +32,17 @@
32 * 32 *
33 * R-standby mode is unsupported, but will be added in the future 33 * R-standby mode is unsupported, but will be added in the future
34 * U-standby mode is low priority since it needs bootloader hacks 34 * U-standby mode is low priority since it needs bootloader hacks
35 *
36 * All modes should be tied in with cpuidle. But before that can
37 * happen we need to keep track of enabled hardware blocks so we
38 * can avoid entering sleep modes that stop clocks to hardware
39 * blocks that are in use even though the cpu core is idle.
40 */ 35 */
41 36
37#define ILRAM_BASE 0xe5200000
38
42extern const unsigned char sh_mobile_standby[]; 39extern const unsigned char sh_mobile_standby[];
43extern const unsigned int sh_mobile_standby_size; 40extern const unsigned int sh_mobile_standby_size;
44 41
45static void sh_mobile_call_standby(unsigned long mode) 42void sh_mobile_call_standby(unsigned long mode)
46{ 43{
47 extern void *vbr_base; 44 extern void *vbr_base;
48 void *onchip_mem = (void *)0xe5200000; /* ILRAM */ 45 void *onchip_mem = (void *)ILRAM_BASE;
49 void (*standby_onchip_mem)(unsigned long) = onchip_mem; 46 void (*standby_onchip_mem)(unsigned long) = onchip_mem;
50 47
51 /* Note: Wake up from sleep may generate exceptions! 48 /* Note: Wake up from sleep may generate exceptions!
@@ -55,11 +52,6 @@ static void sh_mobile_call_standby(unsigned long mode)
55 if (mode & SUSP_SH_SF) 52 if (mode & SUSP_SH_SF)
56 asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory"); 53 asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory");
57 54
58 /* Copy the assembly snippet to the otherwise ununsed ILRAM */
59 memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
60 wmb();
61 ctrl_barrier();
62
63 /* Let assembly snippet in on-chip memory handle the rest */ 55 /* Let assembly snippet in on-chip memory handle the rest */
64 standby_onchip_mem(mode); 56 standby_onchip_mem(mode);
65 57
@@ -85,7 +77,15 @@ static struct platform_suspend_ops sh_pm_ops = {
85 77
86static int __init sh_pm_init(void) 78static int __init sh_pm_init(void)
87{ 79{
80 void *onchip_mem = (void *)ILRAM_BASE;
81
82 /* Copy the assembly snippet to the otherwise ununsed ILRAM */
83 memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
84 wmb();
85 ctrl_barrier();
86
88 suspend_set_ops(&sh_pm_ops); 87 suspend_set_ops(&sh_pm_ops);
88 sh_mobile_setup_cpuidle();
89 return 0; 89 return 0;
90} 90}
91 91
diff --git a/arch/sh/kernel/dumpstack.c b/arch/sh/kernel/dumpstack.c
new file mode 100644
index 000000000000..6f5ad1513409
--- /dev/null
+++ b/arch/sh/kernel/dumpstack.c
@@ -0,0 +1,123 @@
1/*
2 * Copyright (C) 1991, 1992 Linus Torvalds
3 * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
4 * Copyright (C) 2009 Matt Fleming
5 */
6#include <linux/kallsyms.h>
7#include <linux/ftrace.h>
8#include <linux/debug_locks.h>
9#include <asm/unwinder.h>
10#include <asm/stacktrace.h>
11
12void printk_address(unsigned long address, int reliable)
13{
14 printk(" [<%p>] %s%pS\n", (void *) address,
15 reliable ? "" : "? ", (void *) address);
16}
17
18#ifdef CONFIG_FUNCTION_GRAPH_TRACER
19static void
20print_ftrace_graph_addr(unsigned long addr, void *data,
21 const struct stacktrace_ops *ops,
22 struct thread_info *tinfo, int *graph)
23{
24 struct task_struct *task = tinfo->task;
25 unsigned long ret_addr;
26 int index = task->curr_ret_stack;
27
28 if (addr != (unsigned long)return_to_handler)
29 return;
30
31 if (!task->ret_stack || index < *graph)
32 return;
33
34 index -= *graph;
35 ret_addr = task->ret_stack[index].ret;
36
37 ops->address(data, ret_addr, 1);
38
39 (*graph)++;
40}
41#else
42static inline void
43print_ftrace_graph_addr(unsigned long addr, void *data,
44 const struct stacktrace_ops *ops,
45 struct thread_info *tinfo, int *graph)
46{ }
47#endif
48
49void
50stack_reader_dump(struct task_struct *task, struct pt_regs *regs,
51 unsigned long *sp, const struct stacktrace_ops *ops,
52 void *data)
53{
54 struct thread_info *context;
55 int graph = 0;
56
57 context = (struct thread_info *)
58 ((unsigned long)sp & (~(THREAD_SIZE - 1)));
59
60 while (!kstack_end(sp)) {
61 unsigned long addr = *sp++;
62
63 if (__kernel_text_address(addr)) {
64 ops->address(data, addr, 1);
65
66 print_ftrace_graph_addr(addr, data, ops,
67 context, &graph);
68 }
69 }
70}
71
72static void
73print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
74{
75 printk(data);
76 print_symbol(msg, symbol);
77 printk("\n");
78}
79
80static void print_trace_warning(void *data, char *msg)
81{
82 printk("%s%s\n", (char *)data, msg);
83}
84
85static int print_trace_stack(void *data, char *name)
86{
87 printk("%s <%s> ", (char *)data, name);
88 return 0;
89}
90
91/*
92 * Print one address/symbol entries per line.
93 */
94static void print_trace_address(void *data, unsigned long addr, int reliable)
95{
96 printk(data);
97 printk_address(addr, reliable);
98}
99
100static const struct stacktrace_ops print_trace_ops = {
101 .warning = print_trace_warning,
102 .warning_symbol = print_trace_warning_symbol,
103 .stack = print_trace_stack,
104 .address = print_trace_address,
105};
106
107void show_trace(struct task_struct *tsk, unsigned long *sp,
108 struct pt_regs *regs)
109{
110 if (regs && user_mode(regs))
111 return;
112
113 printk("\nCall trace:\n");
114
115 unwind_stack(tsk, regs, sp, &print_trace_ops, "");
116
117 printk("\n");
118
119 if (!tsk)
120 tsk = current;
121
122 debug_show_held_locks(tsk);
123}
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
new file mode 100644
index 000000000000..c6c5764a8ab1
--- /dev/null
+++ b/arch/sh/kernel/dwarf.c
@@ -0,0 +1,902 @@
1/*
2 * Copyright (C) 2009 Matt Fleming <matt@console-pimps.org>
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * This is an implementation of a DWARF unwinder. Its main purpose is
9 * for generating stacktrace information. Based on the DWARF 3
10 * specification from http://www.dwarfstd.org.
11 *
12 * TODO:
13 * - DWARF64 doesn't work.
14 */
15
16/* #define DEBUG */
17#include <linux/kernel.h>
18#include <linux/io.h>
19#include <linux/list.h>
20#include <linux/mm.h>
21#include <asm/dwarf.h>
22#include <asm/unwinder.h>
23#include <asm/sections.h>
24#include <asm/unaligned.h>
25#include <asm/dwarf.h>
26#include <asm/stacktrace.h>
27
28static LIST_HEAD(dwarf_cie_list);
29DEFINE_SPINLOCK(dwarf_cie_lock);
30
31static LIST_HEAD(dwarf_fde_list);
32DEFINE_SPINLOCK(dwarf_fde_lock);
33
34static struct dwarf_cie *cached_cie;
35
36/*
37 * Figure out whether we need to allocate some dwarf registers. If dwarf
38 * registers have already been allocated then we may need to realloc
39 * them. "reg" is a register number that we need to be able to access
40 * after this call.
41 *
42 * Register numbers start at zero, therefore we need to allocate space
43 * for "reg" + 1 registers.
44 */
45static void dwarf_frame_alloc_regs(struct dwarf_frame *frame,
46 unsigned int reg)
47{
48 struct dwarf_reg *regs;
49 unsigned int num_regs = reg + 1;
50 size_t new_size;
51 size_t old_size;
52
53 new_size = num_regs * sizeof(*regs);
54 old_size = frame->num_regs * sizeof(*regs);
55
56 /* Fast path: don't allocate any regs if we've already got enough. */
57 if (frame->num_regs >= num_regs)
58 return;
59
60 regs = kzalloc(new_size, GFP_ATOMIC);
61 if (!regs) {
62 printk(KERN_WARNING "Unable to allocate DWARF registers\n");
63 /*
64 * Let's just bomb hard here, we have no way to
65 * gracefully recover.
66 */
67 BUG();
68 }
69
70 if (frame->regs) {
71 memcpy(regs, frame->regs, old_size);
72 kfree(frame->regs);
73 }
74
75 frame->regs = regs;
76 frame->num_regs = num_regs;
77}
78
79/**
80 * dwarf_read_addr - read dwarf data
81 * @src: source address of data
82 * @dst: destination address to store the data to
83 *
84 * Read 'n' bytes from @src, where 'n' is the size of an address on
85 * the native machine. We return the number of bytes read, which
86 * should always be 'n'. We also have to be careful when reading
87 * from @src and writing to @dst, because they can be arbitrarily
88 * aligned. Return 'n' - the number of bytes read.
89 */
90static inline int dwarf_read_addr(unsigned long *src, unsigned long *dst)
91{
92 u32 val = get_unaligned(src);
93 put_unaligned(val, dst);
94 return sizeof(unsigned long *);
95}
96
97/**
98 * dwarf_read_uleb128 - read unsigned LEB128 data
99 * @addr: the address where the ULEB128 data is stored
100 * @ret: address to store the result
101 *
102 * Decode an unsigned LEB128 encoded datum. The algorithm is taken
103 * from Appendix C of the DWARF 3 spec. For information on the
104 * encodings refer to section "7.6 - Variable Length Data". Return
105 * the number of bytes read.
106 */
107static inline unsigned long dwarf_read_uleb128(char *addr, unsigned int *ret)
108{
109 unsigned int result;
110 unsigned char byte;
111 int shift, count;
112
113 result = 0;
114 shift = 0;
115 count = 0;
116
117 while (1) {
118 byte = __raw_readb(addr);
119 addr++;
120 count++;
121
122 result |= (byte & 0x7f) << shift;
123 shift += 7;
124
125 if (!(byte & 0x80))
126 break;
127 }
128
129 *ret = result;
130
131 return count;
132}
133
134/**
135 * dwarf_read_leb128 - read signed LEB128 data
136 * @addr: the address of the LEB128 encoded data
137 * @ret: address to store the result
138 *
139 * Decode signed LEB128 data. The algorithm is taken from Appendix
140 * C of the DWARF 3 spec. Return the number of bytes read.
141 */
142static inline unsigned long dwarf_read_leb128(char *addr, int *ret)
143{
144 unsigned char byte;
145 int result, shift;
146 int num_bits;
147 int count;
148
149 result = 0;
150 shift = 0;
151 count = 0;
152
153 while (1) {
154 byte = __raw_readb(addr);
155 addr++;
156 result |= (byte & 0x7f) << shift;
157 shift += 7;
158 count++;
159
160 if (!(byte & 0x80))
161 break;
162 }
163
164 /* The number of bits in a signed integer. */
165 num_bits = 8 * sizeof(result);
166
167 if ((shift < num_bits) && (byte & 0x40))
168 result |= (-1 << shift);
169
170 *ret = result;
171
172 return count;
173}
174
175/**
176 * dwarf_read_encoded_value - return the decoded value at @addr
177 * @addr: the address of the encoded value
178 * @val: where to write the decoded value
179 * @encoding: the encoding with which we can decode @addr
180 *
181 * GCC emits encoded address in the .eh_frame FDE entries. Decode
182 * the value at @addr using @encoding. The decoded value is written
183 * to @val and the number of bytes read is returned.
184 */
185static int dwarf_read_encoded_value(char *addr, unsigned long *val,
186 char encoding)
187{
188 unsigned long decoded_addr = 0;
189 int count = 0;
190
191 switch (encoding & 0x70) {
192 case DW_EH_PE_absptr:
193 break;
194 case DW_EH_PE_pcrel:
195 decoded_addr = (unsigned long)addr;
196 break;
197 default:
198 pr_debug("encoding=0x%x\n", (encoding & 0x70));
199 BUG();
200 }
201
202 if ((encoding & 0x07) == 0x00)
203 encoding |= DW_EH_PE_udata4;
204
205 switch (encoding & 0x0f) {
206 case DW_EH_PE_sdata4:
207 case DW_EH_PE_udata4:
208 count += 4;
209 decoded_addr += get_unaligned((u32 *)addr);
210 __raw_writel(decoded_addr, val);
211 break;
212 default:
213 pr_debug("encoding=0x%x\n", encoding);
214 BUG();
215 }
216
217 return count;
218}
219
220/**
221 * dwarf_entry_len - return the length of an FDE or CIE
222 * @addr: the address of the entry
223 * @len: the length of the entry
224 *
225 * Read the initial_length field of the entry and store the size of
226 * the entry in @len. We return the number of bytes read. Return a
227 * count of 0 on error.
228 */
229static inline int dwarf_entry_len(char *addr, unsigned long *len)
230{
231 u32 initial_len;
232 int count;
233
234 initial_len = get_unaligned((u32 *)addr);
235 count = 4;
236
237 /*
238 * An initial length field value in the range DW_LEN_EXT_LO -
239 * DW_LEN_EXT_HI indicates an extension, and should not be
240 * interpreted as a length. The only extension that we currently
241 * understand is the use of DWARF64 addresses.
242 */
243 if (initial_len >= DW_EXT_LO && initial_len <= DW_EXT_HI) {
244 /*
245 * The 64-bit length field immediately follows the
246 * compulsory 32-bit length field.
247 */
248 if (initial_len == DW_EXT_DWARF64) {
249 *len = get_unaligned((u64 *)addr + 4);
250 count = 12;
251 } else {
252 printk(KERN_WARNING "Unknown DWARF extension\n");
253 count = 0;
254 }
255 } else
256 *len = initial_len;
257
258 return count;
259}
260
261/**
262 * dwarf_lookup_cie - locate the cie
263 * @cie_ptr: pointer to help with lookup
264 */
265static struct dwarf_cie *dwarf_lookup_cie(unsigned long cie_ptr)
266{
267 struct dwarf_cie *cie, *n;
268 unsigned long flags;
269
270 spin_lock_irqsave(&dwarf_cie_lock, flags);
271
272 /*
273 * We've cached the last CIE we looked up because chances are
274 * that the FDE wants this CIE.
275 */
276 if (cached_cie && cached_cie->cie_pointer == cie_ptr) {
277 cie = cached_cie;
278 goto out;
279 }
280
281 list_for_each_entry_safe(cie, n, &dwarf_cie_list, link) {
282 if (cie->cie_pointer == cie_ptr) {
283 cached_cie = cie;
284 break;
285 }
286 }
287
288 /* Couldn't find the entry in the list. */
289 if (&cie->link == &dwarf_cie_list)
290 cie = NULL;
291out:
292 spin_unlock_irqrestore(&dwarf_cie_lock, flags);
293 return cie;
294}
295
296/**
297 * dwarf_lookup_fde - locate the FDE that covers pc
298 * @pc: the program counter
299 */
300struct dwarf_fde *dwarf_lookup_fde(unsigned long pc)
301{
302 unsigned long flags;
303 struct dwarf_fde *fde, *n;
304
305 spin_lock_irqsave(&dwarf_fde_lock, flags);
306 list_for_each_entry_safe(fde, n, &dwarf_fde_list, link) {
307 unsigned long start, end;
308
309 start = fde->initial_location;
310 end = fde->initial_location + fde->address_range;
311
312 if (pc >= start && pc < end)
313 break;
314 }
315
316 /* Couldn't find the entry in the list. */
317 if (&fde->link == &dwarf_fde_list)
318 fde = NULL;
319
320 spin_unlock_irqrestore(&dwarf_fde_lock, flags);
321
322 return fde;
323}
324
325/**
326 * dwarf_cfa_execute_insns - execute instructions to calculate a CFA
327 * @insn_start: address of the first instruction
328 * @insn_end: address of the last instruction
329 * @cie: the CIE for this function
330 * @fde: the FDE for this function
331 * @frame: the instructions calculate the CFA for this frame
332 * @pc: the program counter of the address we're interested in
333 * @define_ra: keep executing insns until the return addr reg is defined?
334 *
335 * Execute the Call Frame instruction sequence starting at
336 * @insn_start and ending at @insn_end. The instructions describe
337 * how to calculate the Canonical Frame Address of a stackframe.
338 * Store the results in @frame.
339 */
340static int dwarf_cfa_execute_insns(unsigned char *insn_start,
341 unsigned char *insn_end,
342 struct dwarf_cie *cie,
343 struct dwarf_fde *fde,
344 struct dwarf_frame *frame,
345 unsigned long pc,
346 bool define_ra)
347{
348 unsigned char insn;
349 unsigned char *current_insn;
350 unsigned int count, delta, reg, expr_len, offset;
351 bool seen_ra_reg;
352
353 current_insn = insn_start;
354
355 /*
356 * If we're executing instructions for the dwarf_unwind_stack()
357 * FDE we need to keep executing instructions until the value of
358 * DWARF_ARCH_RA_REG is defined. See the comment in
359 * dwarf_unwind_stack() for more details.
360 */
361 if (define_ra)
362 seen_ra_reg = false;
363 else
364 seen_ra_reg = true;
365
366 while (current_insn < insn_end && (frame->pc <= pc || !seen_ra_reg) ) {
367 insn = __raw_readb(current_insn++);
368
369 if (!seen_ra_reg) {
370 if (frame->num_regs >= DWARF_ARCH_RA_REG &&
371 frame->regs[DWARF_ARCH_RA_REG].flags)
372 seen_ra_reg = true;
373 }
374
375 /*
376 * Firstly, handle the opcodes that embed their operands
377 * in the instructions.
378 */
379 switch (DW_CFA_opcode(insn)) {
380 case DW_CFA_advance_loc:
381 delta = DW_CFA_operand(insn);
382 delta *= cie->code_alignment_factor;
383 frame->pc += delta;
384 continue;
385 /* NOTREACHED */
386 case DW_CFA_offset:
387 reg = DW_CFA_operand(insn);
388 count = dwarf_read_uleb128(current_insn, &offset);
389 current_insn += count;
390 offset *= cie->data_alignment_factor;
391 dwarf_frame_alloc_regs(frame, reg);
392 frame->regs[reg].addr = offset;
393 frame->regs[reg].flags |= DWARF_REG_OFFSET;
394 continue;
395 /* NOTREACHED */
396 case DW_CFA_restore:
397 reg = DW_CFA_operand(insn);
398 continue;
399 /* NOTREACHED */
400 }
401
402 /*
403 * Secondly, handle the opcodes that don't embed their
404 * operands in the instruction.
405 */
406 switch (insn) {
407 case DW_CFA_nop:
408 continue;
409 case DW_CFA_advance_loc1:
410 delta = *current_insn++;
411 frame->pc += delta * cie->code_alignment_factor;
412 break;
413 case DW_CFA_advance_loc2:
414 delta = get_unaligned((u16 *)current_insn);
415 current_insn += 2;
416 frame->pc += delta * cie->code_alignment_factor;
417 break;
418 case DW_CFA_advance_loc4:
419 delta = get_unaligned((u32 *)current_insn);
420 current_insn += 4;
421 frame->pc += delta * cie->code_alignment_factor;
422 break;
423 case DW_CFA_offset_extended:
424 count = dwarf_read_uleb128(current_insn, &reg);
425 current_insn += count;
426 count = dwarf_read_uleb128(current_insn, &offset);
427 current_insn += count;
428 offset *= cie->data_alignment_factor;
429 break;
430 case DW_CFA_restore_extended:
431 count = dwarf_read_uleb128(current_insn, &reg);
432 current_insn += count;
433 break;
434 case DW_CFA_undefined:
435 count = dwarf_read_uleb128(current_insn, &reg);
436 current_insn += count;
437 break;
438 case DW_CFA_def_cfa:
439 count = dwarf_read_uleb128(current_insn,
440 &frame->cfa_register);
441 current_insn += count;
442 count = dwarf_read_uleb128(current_insn,
443 &frame->cfa_offset);
444 current_insn += count;
445
446 frame->flags |= DWARF_FRAME_CFA_REG_OFFSET;
447 break;
448 case DW_CFA_def_cfa_register:
449 count = dwarf_read_uleb128(current_insn,
450 &frame->cfa_register);
451 current_insn += count;
452 frame->cfa_offset = 0;
453 frame->flags |= DWARF_FRAME_CFA_REG_OFFSET;
454 break;
455 case DW_CFA_def_cfa_offset:
456 count = dwarf_read_uleb128(current_insn, &offset);
457 current_insn += count;
458 frame->cfa_offset = offset;
459 break;
460 case DW_CFA_def_cfa_expression:
461 count = dwarf_read_uleb128(current_insn, &expr_len);
462 current_insn += count;
463
464 frame->cfa_expr = current_insn;
465 frame->cfa_expr_len = expr_len;
466 current_insn += expr_len;
467
468 frame->flags |= DWARF_FRAME_CFA_REG_EXP;
469 break;
470 case DW_CFA_offset_extended_sf:
471 count = dwarf_read_uleb128(current_insn, &reg);
472 current_insn += count;
473 count = dwarf_read_leb128(current_insn, &offset);
474 current_insn += count;
475 offset *= cie->data_alignment_factor;
476 dwarf_frame_alloc_regs(frame, reg);
477 frame->regs[reg].flags |= DWARF_REG_OFFSET;
478 frame->regs[reg].addr = offset;
479 break;
480 case DW_CFA_val_offset:
481 count = dwarf_read_uleb128(current_insn, &reg);
482 current_insn += count;
483 count = dwarf_read_leb128(current_insn, &offset);
484 offset *= cie->data_alignment_factor;
485 frame->regs[reg].flags |= DWARF_REG_OFFSET;
486 frame->regs[reg].addr = offset;
487 break;
488 default:
489 pr_debug("unhandled DWARF instruction 0x%x\n", insn);
490 break;
491 }
492 }
493
494 return 0;
495}
496
497/**
498 * dwarf_unwind_stack - recursively unwind the stack
499 * @pc: address of the function to unwind
500 * @prev: struct dwarf_frame of the previous stackframe on the callstack
501 *
502 * Return a struct dwarf_frame representing the most recent frame
503 * on the callstack. Each of the lower (older) stack frames are
504 * linked via the "prev" member.
505 */
506struct dwarf_frame *dwarf_unwind_stack(unsigned long pc,
507 struct dwarf_frame *prev)
508{
509 struct dwarf_frame *frame;
510 struct dwarf_cie *cie;
511 struct dwarf_fde *fde;
512 unsigned long addr;
513 int i, offset;
514 bool define_ra = false;
515
516 /*
517 * If this is the first invocation of this recursive function we
518 * need get the contents of a physical register to get the CFA
519 * in order to begin the virtual unwinding of the stack.
520 *
521 * Setting "define_ra" to true indictates that we want
522 * dwarf_cfa_execute_insns() to continue executing instructions
523 * until we know how to calculate the value of DWARF_ARCH_RA_REG
524 * (which we need in order to kick off the whole unwinding
525 * process).
526 *
527 * NOTE: the return address is guaranteed to be setup by the
528 * time this function makes its first function call.
529 */
530 if (!pc && !prev) {
531 pc = (unsigned long)&dwarf_unwind_stack;
532 define_ra = true;
533 }
534
535 frame = kzalloc(sizeof(*frame), GFP_ATOMIC);
536 if (!frame)
537 return NULL;
538
539 frame->prev = prev;
540
541 fde = dwarf_lookup_fde(pc);
542 if (!fde) {
543 /*
544 * This is our normal exit path - the one that stops the
545 * recursion. There's two reasons why we might exit
546 * here,
547 *
548 * a) pc has no asscociated DWARF frame info and so
549 * we don't know how to unwind this frame. This is
550 * usually the case when we're trying to unwind a
551 * frame that was called from some assembly code
552 * that has no DWARF info, e.g. syscalls.
553 *
554 * b) the DEBUG info for pc is bogus. There's
555 * really no way to distinguish this case from the
556 * case above, which sucks because we could print a
557 * warning here.
558 */
559 return NULL;
560 }
561
562 cie = dwarf_lookup_cie(fde->cie_pointer);
563
564 frame->pc = fde->initial_location;
565
566 /* CIE initial instructions */
567 dwarf_cfa_execute_insns(cie->initial_instructions,
568 cie->instructions_end, cie, fde,
569 frame, pc, false);
570
571 /* FDE instructions */
572 dwarf_cfa_execute_insns(fde->instructions, fde->end, cie,
573 fde, frame, pc, define_ra);
574
575 /* Calculate the CFA */
576 switch (frame->flags) {
577 case DWARF_FRAME_CFA_REG_OFFSET:
578 if (prev) {
579 BUG_ON(!prev->regs[frame->cfa_register].flags);
580
581 addr = prev->cfa;
582 addr += prev->regs[frame->cfa_register].addr;
583 frame->cfa = __raw_readl(addr);
584
585 } else {
586 /*
587 * Again, this is the first invocation of this
588 * recurisve function. We need to physically
589 * read the contents of a register in order to
590 * get the Canonical Frame Address for this
591 * function.
592 */
593 frame->cfa = dwarf_read_arch_reg(frame->cfa_register);
594 }
595
596 frame->cfa += frame->cfa_offset;
597 break;
598 default:
599 BUG();
600 }
601
602 /* If we haven't seen the return address reg, we're screwed. */
603 BUG_ON(!frame->regs[DWARF_ARCH_RA_REG].flags);
604
605 for (i = 0; i <= frame->num_regs; i++) {
606 struct dwarf_reg *reg = &frame->regs[i];
607
608 if (!reg->flags)
609 continue;
610
611 offset = reg->addr;
612 offset += frame->cfa;
613 }
614
615 addr = frame->cfa + frame->regs[DWARF_ARCH_RA_REG].addr;
616 frame->return_addr = __raw_readl(addr);
617
618 frame->next = dwarf_unwind_stack(frame->return_addr, frame);
619 return frame;
620}
621
622static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
623 unsigned char *end)
624{
625 struct dwarf_cie *cie;
626 unsigned long flags;
627 int count;
628
629 cie = kzalloc(sizeof(*cie), GFP_KERNEL);
630 if (!cie)
631 return -ENOMEM;
632
633 cie->length = len;
634
635 /*
636 * Record the offset into the .eh_frame section
637 * for this CIE. It allows this CIE to be
638 * quickly and easily looked up from the
639 * corresponding FDE.
640 */
641 cie->cie_pointer = (unsigned long)entry;
642
643 cie->version = *(char *)p++;
644 BUG_ON(cie->version != 1);
645
646 cie->augmentation = p;
647 p += strlen(cie->augmentation) + 1;
648
649 count = dwarf_read_uleb128(p, &cie->code_alignment_factor);
650 p += count;
651
652 count = dwarf_read_leb128(p, &cie->data_alignment_factor);
653 p += count;
654
655 /*
656 * Which column in the rule table contains the
657 * return address?
658 */
659 if (cie->version == 1) {
660 cie->return_address_reg = __raw_readb(p);
661 p++;
662 } else {
663 count = dwarf_read_uleb128(p, &cie->return_address_reg);
664 p += count;
665 }
666
667 if (cie->augmentation[0] == 'z') {
668 unsigned int length, count;
669 cie->flags |= DWARF_CIE_Z_AUGMENTATION;
670
671 count = dwarf_read_uleb128(p, &length);
672 p += count;
673
674 BUG_ON((unsigned char *)p > end);
675
676 cie->initial_instructions = p + length;
677 cie->augmentation++;
678 }
679
680 while (*cie->augmentation) {
681 /*
682 * "L" indicates a byte showing how the
683 * LSDA pointer is encoded. Skip it.
684 */
685 if (*cie->augmentation == 'L') {
686 p++;
687 cie->augmentation++;
688 } else if (*cie->augmentation == 'R') {
689 /*
690 * "R" indicates a byte showing
691 * how FDE addresses are
692 * encoded.
693 */
694 cie->encoding = *(char *)p++;
695 cie->augmentation++;
696 } else if (*cie->augmentation == 'P') {
697 /*
698 * "R" indicates a personality
699 * routine in the CIE
700 * augmentation.
701 */
702 BUG();
703 } else if (*cie->augmentation == 'S') {
704 BUG();
705 } else {
706 /*
707 * Unknown augmentation. Assume
708 * 'z' augmentation.
709 */
710 p = cie->initial_instructions;
711 BUG_ON(!p);
712 break;
713 }
714 }
715
716 cie->initial_instructions = p;
717 cie->instructions_end = end;
718
719 /* Add to list */
720 spin_lock_irqsave(&dwarf_cie_lock, flags);
721 list_add_tail(&cie->link, &dwarf_cie_list);
722 spin_unlock_irqrestore(&dwarf_cie_lock, flags);
723
724 return 0;
725}
726
727static int dwarf_parse_fde(void *entry, u32 entry_type,
728 void *start, unsigned long len)
729{
730 struct dwarf_fde *fde;
731 struct dwarf_cie *cie;
732 unsigned long flags;
733 int count;
734 void *p = start;
735
736 fde = kzalloc(sizeof(*fde), GFP_KERNEL);
737 if (!fde)
738 return -ENOMEM;
739
740 fde->length = len;
741
742 /*
743 * In a .eh_frame section the CIE pointer is the
744 * delta between the address within the FDE
745 */
746 fde->cie_pointer = (unsigned long)(p - entry_type - 4);
747
748 cie = dwarf_lookup_cie(fde->cie_pointer);
749 fde->cie = cie;
750
751 if (cie->encoding)
752 count = dwarf_read_encoded_value(p, &fde->initial_location,
753 cie->encoding);
754 else
755 count = dwarf_read_addr(p, &fde->initial_location);
756
757 p += count;
758
759 if (cie->encoding)
760 count = dwarf_read_encoded_value(p, &fde->address_range,
761 cie->encoding & 0x0f);
762 else
763 count = dwarf_read_addr(p, &fde->address_range);
764
765 p += count;
766
767 if (fde->cie->flags & DWARF_CIE_Z_AUGMENTATION) {
768 unsigned int length;
769 count = dwarf_read_uleb128(p, &length);
770 p += count + length;
771 }
772
773 /* Call frame instructions. */
774 fde->instructions = p;
775 fde->end = start + len;
776
777 /* Add to list. */
778 spin_lock_irqsave(&dwarf_fde_lock, flags);
779 list_add_tail(&fde->link, &dwarf_fde_list);
780 spin_unlock_irqrestore(&dwarf_fde_lock, flags);
781
782 return 0;
783}
784
785static void dwarf_unwinder_dump(struct task_struct *task, struct pt_regs *regs,
786 unsigned long *sp,
787 const struct stacktrace_ops *ops, void *data)
788{
789 struct dwarf_frame *frame;
790
791 frame = dwarf_unwind_stack(0, NULL);
792
793 while (frame && frame->return_addr) {
794 ops->address(data, frame->return_addr, 1);
795 frame = frame->next;
796 }
797}
798
799static struct unwinder dwarf_unwinder = {
800 .name = "dwarf-unwinder",
801 .dump = dwarf_unwinder_dump,
802 .rating = 150,
803};
804
805static void dwarf_unwinder_cleanup(void)
806{
807 struct dwarf_cie *cie, *m;
808 struct dwarf_fde *fde, *n;
809 unsigned long flags;
810
811 /*
812 * Deallocate all the memory allocated for the DWARF unwinder.
813 * Traverse all the FDE/CIE lists and remove and free all the
814 * memory associated with those data structures.
815 */
816 spin_lock_irqsave(&dwarf_cie_lock, flags);
817 list_for_each_entry_safe(cie, m, &dwarf_cie_list, link)
818 kfree(cie);
819 spin_unlock_irqrestore(&dwarf_cie_lock, flags);
820
821 spin_lock_irqsave(&dwarf_fde_lock, flags);
822 list_for_each_entry_safe(fde, n, &dwarf_fde_list, link)
823 kfree(fde);
824 spin_unlock_irqrestore(&dwarf_fde_lock, flags);
825}
826
827/**
828 * dwarf_unwinder_init - initialise the dwarf unwinder
829 *
830 * Build the data structures describing the .dwarf_frame section to
831 * make it easier to lookup CIE and FDE entries. Because the
832 * .eh_frame section is packed as tightly as possible it is not
833 * easy to lookup the FDE for a given PC, so we build a list of FDE
834 * and CIE entries that make it easier.
835 */
836void dwarf_unwinder_init(void)
837{
838 u32 entry_type;
839 void *p, *entry;
840 int count, err;
841 unsigned long len;
842 unsigned int c_entries, f_entries;
843 unsigned char *end;
844 INIT_LIST_HEAD(&dwarf_cie_list);
845 INIT_LIST_HEAD(&dwarf_fde_list);
846
847 c_entries = 0;
848 f_entries = 0;
849 entry = &__start_eh_frame;
850
851 while ((char *)entry < __stop_eh_frame) {
852 p = entry;
853
854 count = dwarf_entry_len(p, &len);
855 if (count == 0) {
856 /*
857 * We read a bogus length field value. There is
858 * nothing we can do here apart from disabling
859 * the DWARF unwinder. We can't even skip this
860 * entry and move to the next one because 'len'
861 * tells us where our next entry is.
862 */
863 goto out;
864 } else
865 p += count;
866
867 /* initial length does not include itself */
868 end = p + len;
869
870 entry_type = get_unaligned((u32 *)p);
871 p += 4;
872
873 if (entry_type == DW_EH_FRAME_CIE) {
874 err = dwarf_parse_cie(entry, p, len, end);
875 if (err < 0)
876 goto out;
877 else
878 c_entries++;
879 } else {
880 err = dwarf_parse_fde(entry, entry_type, p, len);
881 if (err < 0)
882 goto out;
883 else
884 f_entries++;
885 }
886
887 entry = (char *)entry + len + 4;
888 }
889
890 printk(KERN_INFO "DWARF unwinder initialised: read %u CIEs, %u FDEs\n",
891 c_entries, f_entries);
892
893 err = unwinder_register(&dwarf_unwinder);
894 if (err)
895 goto out;
896
897 return;
898
899out:
900 printk(KERN_ERR "Failed to initialise DWARF unwinder: %d\n", err);
901 dwarf_unwinder_cleanup();
902}
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index a952dcf9999d..81a46145ffa5 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)
134 sci_out(&scif_port, SCFCR, 0x0030); /* TTRG=b'11 */ 134 sci_out(&scif_port, SCFCR, 0x0030); /* TTRG=b'11 */
135 sci_out(&scif_port, SCSCR, 0x0030); /* TE, RE */ 135 sci_out(&scif_port, SCSCR, 0x0030); /* TE, RE */
136} 136}
137#elif defined(CONFIG_CPU_SH4) 137#elif defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
138#define DEFAULT_BAUD 115200 138#define DEFAULT_BAUD 115200
139/* 139/*
140 * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4 140 * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
@@ -220,8 +220,7 @@ static int __init setup_early_printk(char *buf)
220 early_console = &scif_console; 220 early_console = &scif_console;
221 221
222#if !defined(CONFIG_SH_STANDARD_BIOS) 222#if !defined(CONFIG_SH_STANDARD_BIOS)
223#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SUBTYPE_SH7720) || \ 223#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
224 defined(CONFIG_CPU_SUBTYPE_SH7721)
225 scif_sercon_init(buf + 6); 224 scif_sercon_init(buf + 6);
226#endif 225#endif
227#endif 226#endif
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index d62359cfbbe2..e63178fefb9b 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -43,9 +43,10 @@
43 * syscall # 43 * syscall #
44 * 44 *
45 */ 45 */
46#include <asm/dwarf.h>
46 47
47#if defined(CONFIG_PREEMPT) 48#if defined(CONFIG_PREEMPT)
48# define preempt_stop() cli 49# define preempt_stop() cli ; TRACE_IRQS_OFF
49#else 50#else
50# define preempt_stop() 51# define preempt_stop()
51# define resume_kernel __restore_all 52# define resume_kernel __restore_all
@@ -55,11 +56,7 @@
55 .align 2 56 .align 2
56ENTRY(exception_error) 57ENTRY(exception_error)
57 ! 58 !
58#ifdef CONFIG_TRACE_IRQFLAGS 59 TRACE_IRQS_ON
59 mov.l 2f, r0
60 jsr @r0
61 nop
62#endif
63 sti 60 sti
64 mov.l 1f, r0 61 mov.l 1f, r0
65 jmp @r0 62 jmp @r0
@@ -67,22 +64,28 @@ ENTRY(exception_error)
67 64
68 .align 2 65 .align 2
691: .long do_exception_error 661: .long do_exception_error
70#ifdef CONFIG_TRACE_IRQFLAGS
712: .long trace_hardirqs_on
72#endif
73 67
74 .align 2 68 .align 2
75ret_from_exception: 69ret_from_exception:
70 CFI_STARTPROC simple
71 CFI_DEF_CFA r14, 0
72 CFI_REL_OFFSET 17, 64
73 CFI_REL_OFFSET 15, 0
74 CFI_REL_OFFSET 14, 56
76 preempt_stop() 75 preempt_stop()
77#ifdef CONFIG_TRACE_IRQFLAGS
78 mov.l 4f, r0
79 jsr @r0
80 nop
81#endif
82ENTRY(ret_from_irq) 76ENTRY(ret_from_irq)
83 ! 77 !
84 mov #OFF_SR, r0 78 mov #OFF_SR, r0
85 mov.l @(r0,r15), r0 ! get status register 79 mov.l @(r0,r15), r0 ! get status register
80
81 shlr2 r0
82 and #0x3c, r0
83 cmp/eq #0x3c, r0
84 bt 9f
85 TRACE_IRQS_ON
869:
87 mov #OFF_SR, r0
88 mov.l @(r0,r15), r0 ! get status register
86 shll r0 89 shll r0
87 shll r0 ! kernel space? 90 shll r0 ! kernel space?
88 get_current_thread_info r8, r0 91 get_current_thread_info r8, r0
@@ -125,13 +128,9 @@ noresched:
125ENTRY(resume_userspace) 128ENTRY(resume_userspace)
126 ! r8: current_thread_info 129 ! r8: current_thread_info
127 cli 130 cli
128#ifdef CONFIG_TRACE_IRQFLAGS 131 TRACE_IRQS_OfF
129 mov.l 5f, r0
130 jsr @r0
131 nop
132#endif
133 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags 132 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
134 tst #_TIF_WORK_MASK, r0 133 tst #(_TIF_WORK_MASK & 0xff), r0
135 bt/s __restore_all 134 bt/s __restore_all
136 tst #_TIF_NEED_RESCHED, r0 135 tst #_TIF_NEED_RESCHED, r0
137 136
@@ -156,14 +155,10 @@ work_resched:
156 jsr @r1 ! schedule 155 jsr @r1 ! schedule
157 nop 156 nop
158 cli 157 cli
159#ifdef CONFIG_TRACE_IRQFLAGS 158 TRACE_IRQS_OFF
160 mov.l 5f, r0
161 jsr @r0
162 nop
163#endif
164 ! 159 !
165 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags 160 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
166 tst #_TIF_WORK_MASK, r0 161 tst #(_TIF_WORK_MASK & 0xff), r0
167 bt __restore_all 162 bt __restore_all
168 bra work_pending 163 bra work_pending
169 tst #_TIF_NEED_RESCHED, r0 164 tst #_TIF_NEED_RESCHED, r0
@@ -172,23 +167,15 @@ work_resched:
1721: .long schedule 1671: .long schedule
1732: .long do_notify_resume 1682: .long do_notify_resume
1743: .long resume_userspace 1693: .long resume_userspace
175#ifdef CONFIG_TRACE_IRQFLAGS
1764: .long trace_hardirqs_on
1775: .long trace_hardirqs_off
178#endif
179 170
180 .align 2 171 .align 2
181syscall_exit_work: 172syscall_exit_work:
182 ! r0: current_thread_info->flags 173 ! r0: current_thread_info->flags
183 ! r8: current_thread_info 174 ! r8: current_thread_info
184 tst #_TIF_WORK_SYSCALL_MASK, r0 175 tst #(_TIF_WORK_SYSCALL_MASK & 0xff), r0
185 bt/s work_pending 176 bt/s work_pending
186 tst #_TIF_NEED_RESCHED, r0 177 tst #_TIF_NEED_RESCHED, r0
187#ifdef CONFIG_TRACE_IRQFLAGS 178 TRACE_IRQS_ON
188 mov.l 5f, r0
189 jsr @r0
190 nop
191#endif
192 sti 179 sti
193 mov r15, r4 180 mov r15, r4
194 mov.l 8f, r0 ! do_syscall_trace_leave 181 mov.l 8f, r0 ! do_syscall_trace_leave
@@ -259,6 +246,7 @@ debug_trap:
259 nop 246 nop
260 bra __restore_all 247 bra __restore_all
261 nop 248 nop
249 CFI_ENDPROC
262 250
263 .align 2 251 .align 2
2641: .long debug_trap_table 2521: .long debug_trap_table
@@ -304,6 +292,7 @@ ret_from_fork:
304 * system calls and debug traps through their respective jump tables. 292 * system calls and debug traps through their respective jump tables.
305 */ 293 */
306ENTRY(system_call) 294ENTRY(system_call)
295 setup_frame_reg
307#if !defined(CONFIG_CPU_SH2) 296#if !defined(CONFIG_CPU_SH2)
308 mov.l 1f, r9 297 mov.l 1f, r9
309 mov.l @r9, r8 ! Read from TRA (Trap Address) Register 298 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
@@ -321,18 +310,18 @@ ENTRY(system_call)
321 bt/s debug_trap ! it's a debug trap.. 310 bt/s debug_trap ! it's a debug trap..
322 nop 311 nop
323 312
324#ifdef CONFIG_TRACE_IRQFLAGS 313 TRACE_IRQS_ON
325 mov.l 5f, r10
326 jsr @r10
327 nop
328#endif
329 sti 314 sti
330 315
331 ! 316 !
332 get_current_thread_info r8, r10 317 get_current_thread_info r8, r10
333 mov.l @(TI_FLAGS,r8), r8 318 mov.l @(TI_FLAGS,r8), r8
334 mov #_TIF_WORK_SYSCALL_MASK, r10 319 mov #(_TIF_WORK_SYSCALL_MASK & 0xff), r10
320 mov #(_TIF_WORK_SYSCALL_MASK >> 8), r9
335 tst r10, r8 321 tst r10, r8
322 shll8 r9
323 bf syscall_trace_entry
324 tst r9, r8
336 bf syscall_trace_entry 325 bf syscall_trace_entry
337 ! 326 !
338 mov.l 2f, r8 ! Number of syscalls 327 mov.l 2f, r8 ! Number of syscalls
@@ -351,15 +340,15 @@ syscall_call:
351 ! 340 !
352syscall_exit: 341syscall_exit:
353 cli 342 cli
354#ifdef CONFIG_TRACE_IRQFLAGS 343 TRACE_IRQS_OFF
355 mov.l 6f, r0
356 jsr @r0
357 nop
358#endif
359 ! 344 !
360 get_current_thread_info r8, r0 345 get_current_thread_info r8, r0
361 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags 346 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
362 tst #_TIF_ALLWORK_MASK, r0 347 tst #(_TIF_ALLWORK_MASK & 0xff), r0
348 mov #(_TIF_ALLWORK_MASK >> 8), r1
349 bf syscall_exit_work
350 shlr8 r0
351 tst r0, r1
363 bf syscall_exit_work 352 bf syscall_exit_work
364 bra __restore_all 353 bra __restore_all
365 nop 354 nop
@@ -369,9 +358,5 @@ syscall_exit:
369#endif 358#endif
3702: .long NR_syscalls 3592: .long NR_syscalls
3713: .long sys_call_table 3603: .long sys_call_table
372#ifdef CONFIG_TRACE_IRQFLAGS
3735: .long trace_hardirqs_on
3746: .long trace_hardirqs_off
375#endif
3767: .long do_syscall_trace_enter 3617: .long do_syscall_trace_enter
3778: .long do_syscall_trace_leave 3628: .long do_syscall_trace_leave
diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c
index 066f37dc32a9..6647dfcb781d 100644
--- a/arch/sh/kernel/ftrace.c
+++ b/arch/sh/kernel/ftrace.c
@@ -16,9 +16,13 @@
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/kernel.h>
19#include <asm/ftrace.h> 20#include <asm/ftrace.h>
20#include <asm/cacheflush.h> 21#include <asm/cacheflush.h>
22#include <asm/unistd.h>
23#include <trace/syscall.h>
21 24
25#ifdef CONFIG_DYNAMIC_FTRACE
22static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE]; 26static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE];
23 27
24static unsigned char ftrace_nop[4]; 28static unsigned char ftrace_nop[4];
@@ -131,3 +135,189 @@ int __init ftrace_dyn_arch_init(void *data)
131 135
132 return 0; 136 return 0;
133} 137}
138#endif /* CONFIG_DYNAMIC_FTRACE */
139
140#ifdef CONFIG_FUNCTION_GRAPH_TRACER
141#ifdef CONFIG_DYNAMIC_FTRACE
142extern void ftrace_graph_call(void);
143
144static int ftrace_mod(unsigned long ip, unsigned long old_addr,
145 unsigned long new_addr)
146{
147 unsigned char code[MCOUNT_INSN_SIZE];
148
149 if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
150 return -EFAULT;
151
152 if (old_addr != __raw_readl((unsigned long *)code))
153 return -EINVAL;
154
155 __raw_writel(new_addr, ip);
156 return 0;
157}
158
159int ftrace_enable_ftrace_graph_caller(void)
160{
161 unsigned long ip, old_addr, new_addr;
162
163 ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET;
164 old_addr = (unsigned long)(&skip_trace);
165 new_addr = (unsigned long)(&ftrace_graph_caller);
166
167 return ftrace_mod(ip, old_addr, new_addr);
168}
169
170int ftrace_disable_ftrace_graph_caller(void)
171{
172 unsigned long ip, old_addr, new_addr;
173
174 ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET;
175 old_addr = (unsigned long)(&ftrace_graph_caller);
176 new_addr = (unsigned long)(&skip_trace);
177
178 return ftrace_mod(ip, old_addr, new_addr);
179}
180#endif /* CONFIG_DYNAMIC_FTRACE */
181
182/*
183 * Hook the return address and push it in the stack of return addrs
184 * in the current thread info.
185 *
186 * This is the main routine for the function graph tracer. The function
187 * graph tracer essentially works like this:
188 *
189 * parent is the stack address containing self_addr's return address.
190 * We pull the real return address out of parent and store it in
191 * current's ret_stack. Then, we replace the return address on the stack
192 * with the address of return_to_handler. self_addr is the function that
193 * called mcount.
194 *
195 * When self_addr returns, it will jump to return_to_handler which calls
196 * ftrace_return_to_handler. ftrace_return_to_handler will pull the real
197 * return address off of current's ret_stack and jump to it.
198 */
199void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
200{
201 unsigned long old;
202 int faulted, err;
203 struct ftrace_graph_ent trace;
204 unsigned long return_hooker = (unsigned long)&return_to_handler;
205
206 if (unlikely(atomic_read(&current->tracing_graph_pause)))
207 return;
208
209 /*
210 * Protect against fault, even if it shouldn't
211 * happen. This tool is too much intrusive to
212 * ignore such a protection.
213 */
214 __asm__ __volatile__(
215 "1: \n\t"
216 "mov.l @%2, %0 \n\t"
217 "2: \n\t"
218 "mov.l %3, @%2 \n\t"
219 "mov #0, %1 \n\t"
220 "3: \n\t"
221 ".section .fixup, \"ax\" \n\t"
222 "4: \n\t"
223 "mov.l 5f, %0 \n\t"
224 "jmp @%0 \n\t"
225 " mov #1, %1 \n\t"
226 ".balign 4 \n\t"
227 "5: .long 3b \n\t"
228 ".previous \n\t"
229 ".section __ex_table,\"a\" \n\t"
230 ".long 1b, 4b \n\t"
231 ".long 2b, 4b \n\t"
232 ".previous \n\t"
233 : "=&r" (old), "=r" (faulted)
234 : "r" (parent), "r" (return_hooker)
235 );
236
237 if (unlikely(faulted)) {
238 ftrace_graph_stop();
239 WARN_ON(1);
240 return;
241 }
242
243 err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0);
244 if (err == -EBUSY) {
245 __raw_writel(old, parent);
246 return;
247 }
248
249 trace.func = self_addr;
250
251 /* Only trace if the calling function expects to */
252 if (!ftrace_graph_entry(&trace)) {
253 current->curr_ret_stack--;
254 __raw_writel(old, parent);
255 }
256}
257#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
258
259#ifdef CONFIG_FTRACE_SYSCALLS
260
261extern unsigned long __start_syscalls_metadata[];
262extern unsigned long __stop_syscalls_metadata[];
263extern unsigned long *sys_call_table;
264
265static struct syscall_metadata **syscalls_metadata;
266
267static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
268{
269 struct syscall_metadata *start;
270 struct syscall_metadata *stop;
271 char str[KSYM_SYMBOL_LEN];
272
273
274 start = (struct syscall_metadata *)__start_syscalls_metadata;
275 stop = (struct syscall_metadata *)__stop_syscalls_metadata;
276 kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
277
278 for ( ; start < stop; start++) {
279 if (start->name && !strcmp(start->name, str))
280 return start;
281 }
282
283 return NULL;
284}
285
286#define FTRACE_SYSCALL_MAX (NR_syscalls - 1)
287
288struct syscall_metadata *syscall_nr_to_meta(int nr)
289{
290 if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0)
291 return NULL;
292
293 return syscalls_metadata[nr];
294}
295
296void arch_init_ftrace_syscalls(void)
297{
298 int i;
299 struct syscall_metadata *meta;
300 unsigned long **psys_syscall_table = &sys_call_table;
301 static atomic_t refs;
302
303 if (atomic_inc_return(&refs) != 1)
304 goto end;
305
306 syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
307 FTRACE_SYSCALL_MAX, GFP_KERNEL);
308 if (!syscalls_metadata) {
309 WARN_ON(1);
310 return;
311 }
312
313 for (i = 0; i < FTRACE_SYSCALL_MAX; i++) {
314 meta = find_syscall_meta(psys_syscall_table[i]);
315 syscalls_metadata[i] = meta;
316 }
317 return;
318
319 /* Paranoid: avoid overflow */
320end:
321 atomic_dec(&refs);
322}
323#endif /* CONFIG_FTRACE_SYSCALLS */
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c
index 77dfecb64373..e27a19e1f46e 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,
112 struct trapped_io *tiop; 112 struct trapped_io *tiop;
113 struct resource *res; 113 struct resource *res;
114 int k, len; 114 int k, len;
115 unsigned long flags;
115 116
116 spin_lock_irq(&trapped_lock); 117 spin_lock_irqsave(&trapped_lock, flags);
117 list_for_each_entry(tiop, list, list) { 118 list_for_each_entry(tiop, list, list) {
118 voffs = 0; 119 voffs = 0;
119 for (k = 0; k < tiop->num_resources; k++) { 120 for (k = 0; k < tiop->num_resources; k++) {
120 res = tiop->resource + k; 121 res = tiop->resource + k;
121 if (res->start == offset) { 122 if (res->start == offset) {
122 spin_unlock_irq(&trapped_lock); 123 spin_unlock_irqrestore(&trapped_lock, flags);
123 return tiop->virt_base + voffs; 124 return tiop->virt_base + voffs;
124 } 125 }
125 126
@@ -127,7 +128,7 @@ void __iomem *match_trapped_io_handler(struct list_head *list,
127 voffs += roundup(len, PAGE_SIZE); 128 voffs += roundup(len, PAGE_SIZE);
128 } 129 }
129 } 130 }
130 spin_unlock_irq(&trapped_lock); 131 spin_unlock_irqrestore(&trapped_lock, flags);
131 return NULL; 132 return NULL;
132} 133}
133EXPORT_SYMBOL_GPL(match_trapped_io_handler); 134EXPORT_SYMBOL_GPL(match_trapped_io_handler);
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 3d09062f4682..2bb43dc74f22 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -14,6 +14,7 @@
14#include <asm/processor.h> 14#include <asm/processor.h>
15#include <asm/machvec.h> 15#include <asm/machvec.h>
16#include <asm/uaccess.h> 16#include <asm/uaccess.h>
17#include <asm/dwarf.h>
17#include <asm/thread_info.h> 18#include <asm/thread_info.h>
18#include <cpu/mmu_context.h> 19#include <cpu/mmu_context.h>
19 20
@@ -114,23 +115,6 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
114#endif 115#endif
115 116
116 irq_enter(); 117 irq_enter();
117
118#ifdef CONFIG_DEBUG_STACKOVERFLOW
119 /* Debugging check for stack overflow: is there less than 1KB free? */
120 {
121 long sp;
122
123 __asm__ __volatile__ ("and r15, %0" :
124 "=r" (sp) : "0" (THREAD_SIZE - 1));
125
126 if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
127 printk("do_IRQ: stack overflow: %ld\n",
128 sp - sizeof(struct thread_info));
129 dump_stack();
130 }
131 }
132#endif
133
134 irq = irq_demux(intc_evt2irq(irq)); 118 irq = irq_demux(intc_evt2irq(irq));
135 119
136#ifdef CONFIG_IRQSTACKS 120#ifdef CONFIG_IRQSTACKS
@@ -278,6 +262,9 @@ void __init init_IRQ(void)
278 sh_mv.mv_init_irq(); 262 sh_mv.mv_init_irq();
279 263
280 irq_ctx_init(smp_processor_id()); 264 irq_ctx_init(smp_processor_id());
265
266 /* This needs to be early, but not too early.. */
267 dwarf_unwinder_init();
281} 268}
282 269
283#ifdef CONFIG_SPARSE_IRQ 270#ifdef CONFIG_SPARSE_IRQ
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index 92d7740faab1..9fee977f176b 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -23,6 +23,7 @@
23#include <linux/tick.h> 23#include <linux/tick.h>
24#include <linux/reboot.h> 24#include <linux/reboot.h>
25#include <linux/fs.h> 25#include <linux/fs.h>
26#include <linux/ftrace.h>
26#include <linux/preempt.h> 27#include <linux/preempt.h>
27#include <asm/uaccess.h> 28#include <asm/uaccess.h>
28#include <asm/mmu_context.h> 29#include <asm/mmu_context.h>
@@ -264,8 +265,8 @@ static void ubc_set_tracing(int asid, unsigned long pc)
264 * switch_to(x,y) should switch tasks from x to y. 265 * switch_to(x,y) should switch tasks from x to y.
265 * 266 *
266 */ 267 */
267struct task_struct *__switch_to(struct task_struct *prev, 268__notrace_funcgraph struct task_struct *
268 struct task_struct *next) 269__switch_to(struct task_struct *prev, struct task_struct *next)
269{ 270{
270#if defined(CONFIG_SH_FPU) 271#if defined(CONFIG_SH_FPU)
271 unlazy_fpu(prev, task_pt_regs(prev)); 272 unlazy_fpu(prev, task_pt_regs(prev));
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 3392e835a374..c198eceaee94 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -34,6 +34,8 @@
34#include <asm/syscalls.h> 34#include <asm/syscalls.h>
35#include <asm/fpu.h> 35#include <asm/fpu.h>
36 36
37#include <trace/syscall.h>
38
37/* 39/*
38 * This routine will get a word off of the process kernel stack. 40 * This routine will get a word off of the process kernel stack.
39 */ 41 */
@@ -459,6 +461,9 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
459 */ 461 */
460 ret = -1L; 462 ret = -1L;
461 463
464 if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
465 ftrace_syscall_enter(regs);
466
462 if (unlikely(current->audit_context)) 467 if (unlikely(current->audit_context))
463 audit_syscall_entry(audit_arch(), regs->regs[3], 468 audit_syscall_entry(audit_arch(), regs->regs[3],
464 regs->regs[4], regs->regs[5], 469 regs->regs[4], regs->regs[5],
@@ -475,6 +480,9 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
475 audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), 480 audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
476 regs->regs[0]); 481 regs->regs[0]);
477 482
483 if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
484 ftrace_syscall_exit(regs);
485
478 step = test_thread_flag(TIF_SINGLESTEP); 486 step = test_thread_flag(TIF_SINGLESTEP);
479 if (step || test_thread_flag(TIF_SYSCALL_TRACE)) 487 if (step || test_thread_flag(TIF_SYSCALL_TRACE))
480 tracehook_report_syscall_exit(regs, step); 488 tracehook_report_syscall_exit(regs, step);
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index dd38338553ef..ceb409bf7741 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -30,6 +30,7 @@
30#include <linux/clk.h> 30#include <linux/clk.h>
31#include <linux/delay.h> 31#include <linux/delay.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/lmb.h>
33#include <asm/uaccess.h> 34#include <asm/uaccess.h>
34#include <asm/io.h> 35#include <asm/io.h>
35#include <asm/page.h> 36#include <asm/page.h>
@@ -233,39 +234,45 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
233void __init setup_bootmem_allocator(unsigned long free_pfn) 234void __init setup_bootmem_allocator(unsigned long free_pfn)
234{ 235{
235 unsigned long bootmap_size; 236 unsigned long bootmap_size;
237 unsigned long bootmap_pages, bootmem_paddr;
238 u64 total_pages = (lmb_end_of_DRAM() - __MEMORY_START) >> PAGE_SHIFT;
239 int i;
240
241 bootmap_pages = bootmem_bootmap_pages(total_pages);
242
243 bootmem_paddr = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
236 244
237 /* 245 /*
238 * Find a proper area for the bootmem bitmap. After this 246 * Find a proper area for the bootmem bitmap. After this
239 * bootstrap step all allocations (until the page allocator 247 * bootstrap step all allocations (until the page allocator
240 * is intact) must be done via bootmem_alloc(). 248 * is intact) must be done via bootmem_alloc().
241 */ 249 */
242 bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn, 250 bootmap_size = init_bootmem_node(NODE_DATA(0),
251 bootmem_paddr >> PAGE_SHIFT,
243 min_low_pfn, max_low_pfn); 252 min_low_pfn, max_low_pfn);
244 253
245 __add_active_range(0, min_low_pfn, max_low_pfn); 254 /* Add active regions with valid PFNs. */
246 register_bootmem_low_pages(); 255 for (i = 0; i < lmb.memory.cnt; i++) {
247 256 unsigned long start_pfn, end_pfn;
248 node_set_online(0); 257 start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
258 end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
259 __add_active_range(0, start_pfn, end_pfn);
260 }
249 261
250 /* 262 /*
251 * Reserve the kernel text and 263 * Add all physical memory to the bootmem map and mark each
252 * Reserve the bootmem bitmap. We do this in two steps (first step 264 * area as present.
253 * was init_bootmem()), because this catches the (definitely buggy)
254 * case of us accidentally initializing the bootmem allocator with
255 * an invalid RAM area.
256 */ 265 */
257 reserve_bootmem(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET, 266 register_bootmem_low_pages();
258 (PFN_PHYS(free_pfn) + bootmap_size + PAGE_SIZE - 1) -
259 (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET),
260 BOOTMEM_DEFAULT);
261 267
262 /* 268 /* Reserve the sections we're already using. */
263 * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET. 269 for (i = 0; i < lmb.reserved.cnt; i++)
264 */ 270 reserve_bootmem(lmb.reserved.region[i].base,
265 if (CONFIG_ZERO_PAGE_OFFSET != 0) 271 lmb_size_bytes(&lmb.reserved, i),
266 reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
267 BOOTMEM_DEFAULT); 272 BOOTMEM_DEFAULT);
268 273
274 node_set_online(0);
275
269 sparse_memory_present_with_active_regions(0); 276 sparse_memory_present_with_active_regions(0);
270 277
271#ifdef CONFIG_BLK_DEV_INITRD 278#ifdef CONFIG_BLK_DEV_INITRD
@@ -296,12 +303,37 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
296static void __init setup_memory(void) 303static void __init setup_memory(void)
297{ 304{
298 unsigned long start_pfn; 305 unsigned long start_pfn;
306 u64 base = min_low_pfn << PAGE_SHIFT;
307 u64 size = (max_low_pfn << PAGE_SHIFT) - base;
299 308
300 /* 309 /*
301 * Partially used pages are not usable - thus 310 * Partially used pages are not usable - thus
302 * we are rounding upwards: 311 * we are rounding upwards:
303 */ 312 */
304 start_pfn = PFN_UP(__pa(_end)); 313 start_pfn = PFN_UP(__pa(_end));
314
315 lmb_add(base, size);
316
317 /*
318 * Reserve the kernel text and
319 * Reserve the bootmem bitmap. We do this in two steps (first step
320 * was init_bootmem()), because this catches the (definitely buggy)
321 * case of us accidentally initializing the bootmem allocator with
322 * an invalid RAM area.
323 */
324 lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
325 (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) -
326 (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
327
328 /*
329 * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
330 */
331 if (CONFIG_ZERO_PAGE_OFFSET != 0)
332 lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET);
333
334 lmb_analyze();
335 lmb_dump_all();
336
305 setup_bootmem_allocator(start_pfn); 337 setup_bootmem_allocator(start_pfn);
306} 338}
307#else 339#else
@@ -402,6 +434,7 @@ void __init setup_arch(char **cmdline_p)
402 nodes_clear(node_online_map); 434 nodes_clear(node_online_map);
403 435
404 /* Setup bootmem with available RAM */ 436 /* Setup bootmem with available RAM */
437 lmb_init();
405 setup_memory(); 438 setup_memory();
406 sparse_init(); 439 sparse_init();
407 440
diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c
index fcc5de31f83b..cec610888e28 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);
106EXPORT_SYMBOL(clear_user_page); 106EXPORT_SYMBOL(clear_user_page);
107#endif 107#endif
108 108
109#ifdef CONFIG_FUNCTION_TRACER 109#ifdef CONFIG_MCOUNT
110EXPORT_SYMBOL(mcount); 110DECLARE_EXPORT(mcount);
111#endif 111#endif
112EXPORT_SYMBOL(csum_partial); 112EXPORT_SYMBOL(csum_partial);
113EXPORT_SYMBOL(csum_partial_copy_generic); 113EXPORT_SYMBOL(csum_partial_copy_generic);
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
index 1a2a5eb76e41..c2e45c48409c 100644
--- a/arch/sh/kernel/stacktrace.c
+++ b/arch/sh/kernel/stacktrace.c
@@ -13,47 +13,93 @@
13#include <linux/stacktrace.h> 13#include <linux/stacktrace.h>
14#include <linux/thread_info.h> 14#include <linux/thread_info.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <asm/unwinder.h>
16#include <asm/ptrace.h> 17#include <asm/ptrace.h>
18#include <asm/stacktrace.h>
19
20static void save_stack_warning(void *data, char *msg)
21{
22}
23
24static void
25save_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
26{
27}
28
29static int save_stack_stack(void *data, char *name)
30{
31 return 0;
32}
17 33
18/* 34/*
19 * Save stack-backtrace addresses into a stack_trace buffer. 35 * Save stack-backtrace addresses into a stack_trace buffer.
20 */ 36 */
37static void save_stack_address(void *data, unsigned long addr, int reliable)
38{
39 struct stack_trace *trace = data;
40
41 if (!reliable)
42 return;
43
44 if (trace->skip > 0) {
45 trace->skip--;
46 return;
47 }
48
49 if (trace->nr_entries < trace->max_entries)
50 trace->entries[trace->nr_entries++] = addr;
51}
52
53static const struct stacktrace_ops save_stack_ops = {
54 .warning = save_stack_warning,
55 .warning_symbol = save_stack_warning_symbol,
56 .stack = save_stack_stack,
57 .address = save_stack_address,
58};
59
21void save_stack_trace(struct stack_trace *trace) 60void save_stack_trace(struct stack_trace *trace)
22{ 61{
23 unsigned long *sp = (unsigned long *)current_stack_pointer; 62 unsigned long *sp = (unsigned long *)current_stack_pointer;
24 63
25 while (!kstack_end(sp)) { 64 unwind_stack(current, NULL, sp, &save_stack_ops, trace);
26 unsigned long addr = *sp++; 65 if (trace->nr_entries < trace->max_entries)
27 66 trace->entries[trace->nr_entries++] = ULONG_MAX;
28 if (__kernel_text_address(addr)) {
29 if (trace->skip > 0)
30 trace->skip--;
31 else
32 trace->entries[trace->nr_entries++] = addr;
33 if (trace->nr_entries >= trace->max_entries)
34 break;
35 }
36 }
37} 67}
38EXPORT_SYMBOL_GPL(save_stack_trace); 68EXPORT_SYMBOL_GPL(save_stack_trace);
39 69
70static void
71save_stack_address_nosched(void *data, unsigned long addr, int reliable)
72{
73 struct stack_trace *trace = (struct stack_trace *)data;
74
75 if (!reliable)
76 return;
77
78 if (in_sched_functions(addr))
79 return;
80
81 if (trace->skip > 0) {
82 trace->skip--;
83 return;
84 }
85
86 if (trace->nr_entries < trace->max_entries)
87 trace->entries[trace->nr_entries++] = addr;
88}
89
90static const struct stacktrace_ops save_stack_ops_nosched = {
91 .warning = save_stack_warning,
92 .warning_symbol = save_stack_warning_symbol,
93 .stack = save_stack_stack,
94 .address = save_stack_address_nosched,
95};
96
40void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 97void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
41{ 98{
42 unsigned long *sp = (unsigned long *)tsk->thread.sp; 99 unsigned long *sp = (unsigned long *)tsk->thread.sp;
43 100
44 while (!kstack_end(sp)) { 101 unwind_stack(current, NULL, sp, &save_stack_ops_nosched, trace);
45 unsigned long addr = *sp++; 102 if (trace->nr_entries < trace->max_entries)
46 103 trace->entries[trace->nr_entries++] = ULONG_MAX;
47 if (__kernel_text_address(addr)) {
48 if (in_sched_functions(addr))
49 break;
50 if (trace->skip > 0)
51 trace->skip--;
52 else
53 trace->entries[trace->nr_entries++] = addr;
54 if (trace->nr_entries >= trace->max_entries)
55 break;
56 }
57 }
58} 104}
59EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 105EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 9b352a1e3fb4..7f95f479060f 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -21,6 +21,7 @@
21#include <linux/smp.h> 21#include <linux/smp.h>
22#include <linux/rtc.h> 22#include <linux/rtc.h>
23#include <asm/clock.h> 23#include <asm/clock.h>
24#include <asm/hwblk.h>
24#include <asm/rtc.h> 25#include <asm/rtc.h>
25 26
26/* Dummy RTC ops */ 27/* Dummy RTC ops */
@@ -91,11 +92,27 @@ module_init(rtc_generic_init);
91 92
92void (*board_time_init)(void); 93void (*board_time_init)(void);
93 94
95static void __init sh_late_time_init(void)
96{
97 /*
98 * Make sure all compiled-in early timers register themselves.
99 *
100 * Run probe() for two "earlytimer" devices, these will be the
101 * clockevents and clocksource devices respectively. In the event
102 * that only a clockevents device is available, we -ENODEV on the
103 * clocksource and the jiffies clocksource is used transparently
104 * instead. No error handling is necessary here.
105 */
106 early_platform_driver_register_all("earlytimer");
107 early_platform_driver_probe("earlytimer", 2, 0);
108}
109
94void __init time_init(void) 110void __init time_init(void)
95{ 111{
96 if (board_time_init) 112 if (board_time_init)
97 board_time_init(); 113 board_time_init();
98 114
115 hwblk_init();
99 clk_init(); 116 clk_init();
100 117
101 rtc_sh_get_time(&xtime); 118 rtc_sh_get_time(&xtime);
@@ -106,15 +123,5 @@ void __init time_init(void)
106 local_timer_setup(smp_processor_id()); 123 local_timer_setup(smp_processor_id());
107#endif 124#endif
108 125
109 /* 126 late_time_init = sh_late_time_init;
110 * Make sure all compiled-in early timers register themselves.
111 *
112 * Run probe() for two "earlytimer" devices, these will be the
113 * clockevents and clocksource devices respectively. In the event
114 * that only a clockevents device is available, we -ENODEV on the
115 * clocksource and the jiffies clocksource is used transparently
116 * instead. No error handling is necessary here.
117 */
118 early_platform_driver_register_all("earlytimer");
119 early_platform_driver_probe("earlytimer", 2, 0);
120} 127}
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 2b772776fcda..563426487c6b 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -858,30 +858,6 @@ void __init trap_init(void)
858 per_cpu_trap_init(); 858 per_cpu_trap_init();
859} 859}
860 860
861void show_trace(struct task_struct *tsk, unsigned long *sp,
862 struct pt_regs *regs)
863{
864 unsigned long addr;
865
866 if (regs && user_mode(regs))
867 return;
868
869 printk("\nCall trace:\n");
870
871 while (!kstack_end(sp)) {
872 addr = *sp++;
873 if (kernel_text_address(addr))
874 print_ip_sym(addr);
875 }
876
877 printk("\n");
878
879 if (!tsk)
880 tsk = current;
881
882 debug_show_held_locks(tsk);
883}
884
885void show_stack(struct task_struct *tsk, unsigned long *sp) 861void show_stack(struct task_struct *tsk, unsigned long *sp)
886{ 862{
887 unsigned long stack; 863 unsigned long stack;
diff --git a/arch/sh/kernel/unwinder.c b/arch/sh/kernel/unwinder.c
new file mode 100644
index 000000000000..2b30fa28b440
--- /dev/null
+++ b/arch/sh/kernel/unwinder.c
@@ -0,0 +1,162 @@
1/*
2 * Copyright (C) 2009 Matt Fleming
3 *
4 * Based, in part, on kernel/time/clocksource.c.
5 *
6 * This file provides arbitration code for stack unwinders.
7 *
8 * Multiple stack unwinders can be available on a system, usually with
9 * the most accurate unwinder being the currently active one.
10 */
11#include <linux/errno.h>
12#include <linux/list.h>
13#include <linux/spinlock.h>
14#include <asm/unwinder.h>
15#include <asm/atomic.h>
16
17/*
18 * This is the most basic stack unwinder an architecture can
19 * provide. For architectures without reliable frame pointers, e.g.
20 * RISC CPUs, it can be implemented by looking through the stack for
21 * addresses that lie within the kernel text section.
22 *
23 * Other CPUs, e.g. x86, can use their frame pointer register to
24 * construct more accurate stack traces.
25 */
26static struct list_head unwinder_list;
27static struct unwinder stack_reader = {
28 .name = "stack-reader",
29 .dump = stack_reader_dump,
30 .rating = 50,
31 .list = {
32 .next = &unwinder_list,
33 .prev = &unwinder_list,
34 },
35};
36
37/*
38 * "curr_unwinder" points to the stack unwinder currently in use. This
39 * is the unwinder with the highest rating.
40 *
41 * "unwinder_list" is a linked-list of all available unwinders, sorted
42 * by rating.
43 *
44 * All modifications of "curr_unwinder" and "unwinder_list" must be
45 * performed whilst holding "unwinder_lock".
46 */
47static struct unwinder *curr_unwinder = &stack_reader;
48
49static struct list_head unwinder_list = {
50 .next = &stack_reader.list,
51 .prev = &stack_reader.list,
52};
53
54static DEFINE_SPINLOCK(unwinder_lock);
55
56static atomic_t unwinder_running = ATOMIC_INIT(0);
57
58/**
59 * select_unwinder - Select the best registered stack unwinder.
60 *
61 * Private function. Must hold unwinder_lock when called.
62 *
63 * Select the stack unwinder with the best rating. This is useful for
64 * setting up curr_unwinder.
65 */
66static struct unwinder *select_unwinder(void)
67{
68 struct unwinder *best;
69
70 if (list_empty(&unwinder_list))
71 return NULL;
72
73 best = list_entry(unwinder_list.next, struct unwinder, list);
74 if (best == curr_unwinder)
75 return NULL;
76
77 return best;
78}
79
80/*
81 * Enqueue the stack unwinder sorted by rating.
82 */
83static int unwinder_enqueue(struct unwinder *ops)
84{
85 struct list_head *tmp, *entry = &unwinder_list;
86
87 list_for_each(tmp, &unwinder_list) {
88 struct unwinder *o;
89
90 o = list_entry(tmp, struct unwinder, list);
91 if (o == ops)
92 return -EBUSY;
93 /* Keep track of the place, where to insert */
94 if (o->rating >= ops->rating)
95 entry = tmp;
96 }
97 list_add(&ops->list, entry);
98
99 return 0;
100}
101
102/**
103 * unwinder_register - Used to install new stack unwinder
104 * @u: unwinder to be registered
105 *
106 * Install the new stack unwinder on the unwinder list, which is sorted
107 * by rating.
108 *
109 * Returns -EBUSY if registration fails, zero otherwise.
110 */
111int unwinder_register(struct unwinder *u)
112{
113 unsigned long flags;
114 int ret;
115
116 spin_lock_irqsave(&unwinder_lock, flags);
117 ret = unwinder_enqueue(u);
118 if (!ret)
119 curr_unwinder = select_unwinder();
120 spin_unlock_irqrestore(&unwinder_lock, flags);
121
122 return ret;
123}
124
125/*
126 * Unwind the call stack and pass information to the stacktrace_ops
127 * functions. Also handle the case where we need to switch to a new
128 * stack dumper because the current one faulted unexpectedly.
129 */
130void unwind_stack(struct task_struct *task, struct pt_regs *regs,
131 unsigned long *sp, const struct stacktrace_ops *ops,
132 void *data)
133{
134 unsigned long flags;
135
136 /*
137 * The problem with unwinders with high ratings is that they are
138 * inherently more complicated than the simple ones with lower
139 * ratings. We are therefore more likely to fault in the
140 * complicated ones, e.g. hitting BUG()s. If we fault in the
141 * code for the current stack unwinder we try to downgrade to
142 * one with a lower rating.
143 *
144 * Hopefully this will give us a semi-reliable stacktrace so we
145 * can diagnose why curr_unwinder->dump() faulted.
146 */
147 if (atomic_inc_return(&unwinder_running) != 1) {
148 spin_lock_irqsave(&unwinder_lock, flags);
149
150 if (!list_is_singular(&unwinder_list)) {
151 list_del(&curr_unwinder->list);
152 curr_unwinder = select_unwinder();
153 }
154
155 spin_unlock_irqrestore(&unwinder_lock, flags);
156 atomic_dec(&unwinder_running);
157 }
158
159 curr_unwinder->dump(task, regs, sp, ops, data);
160
161 atomic_dec(&unwinder_running);
162}
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index f53c76acaede..1b7d9d541e01 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -12,7 +12,7 @@ OUTPUT_ARCH(sh)
12 12
13#include <asm/thread_info.h> 13#include <asm/thread_info.h>
14#include <asm/cache.h> 14#include <asm/cache.h>
15#include <asm-generic/vmlinux.lds.h> 15#include <asm/vmlinux.lds.h>
16 16
17ENTRY(_start) 17ENTRY(_start)
18SECTIONS 18SECTIONS
@@ -50,12 +50,7 @@ SECTIONS
50 _etext = .; /* End of text section */ 50 _etext = .; /* End of text section */
51 } = 0x0009 51 } = 0x0009
52 52
53 . = ALIGN(16); /* Exception table */ 53 EXCEPTION_TABLE(16)
54 __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
55 __start___ex_table = .;
56 *(__ex_table)
57 __stop___ex_table = .;
58 }
59 54
60 NOTES 55 NOTES
61 RO_DATA(PAGE_SIZE) 56 RO_DATA(PAGE_SIZE)
@@ -71,69 +66,16 @@ SECTIONS
71 __uncached_end = .; 66 __uncached_end = .;
72 } 67 }
73 68
74 . = ALIGN(THREAD_SIZE); 69 RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
75 .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
76 *(.data.init_task)
77
78 . = ALIGN(L1_CACHE_BYTES);
79 *(.data.cacheline_aligned)
80
81 . = ALIGN(L1_CACHE_BYTES);
82 *(.data.read_mostly)
83
84 . = ALIGN(PAGE_SIZE);
85 *(.data.page_aligned)
86
87 __nosave_begin = .;
88 *(.data.nosave)
89 . = ALIGN(PAGE_SIZE);
90 __nosave_end = .;
91
92 DATA_DATA
93 CONSTRUCTORS
94 }
95 70
96 _edata = .; /* End of data section */ 71 _edata = .; /* End of data section */
97 72
98 . = ALIGN(PAGE_SIZE); /* Init code and data */ 73 DWARF_EH_FRAME
99 .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
100 __init_begin = .;
101 _sinittext = .;
102 INIT_TEXT
103 _einittext = .;
104 }
105
106 .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { INIT_DATA }
107
108 . = ALIGN(16);
109 .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
110 __setup_start = .;
111 *(.init.setup)
112 __setup_end = .;
113 }
114
115 .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
116 __initcall_start = .;
117 INITCALLS
118 __initcall_end = .;
119 }
120
121 .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
122 __con_initcall_start = .;
123 *(.con_initcall.init)
124 __con_initcall_end = .;
125 }
126
127 SECURITY_INIT
128 74
129#ifdef CONFIG_BLK_DEV_INITRD 75 . = ALIGN(PAGE_SIZE); /* Init code and data */
130 . = ALIGN(PAGE_SIZE); 76 __init_begin = .;
131 .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { 77 INIT_TEXT_SECTION(PAGE_SIZE)
132 __initramfs_start = .; 78 INIT_DATA_SECTION(16)
133 *(.init.ramfs)
134 __initramfs_end = .;
135 }
136#endif
137 79
138 . = ALIGN(4); 80 . = ALIGN(4);
139 .machvec.init : AT(ADDR(.machvec.init) - LOAD_OFFSET) { 81 .machvec.init : AT(ADDR(.machvec.init) - LOAD_OFFSET) {
@@ -152,16 +94,10 @@ SECTIONS
152 .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { EXIT_DATA } 94 .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { EXIT_DATA }
153 95
154 . = ALIGN(PAGE_SIZE); 96 . = ALIGN(PAGE_SIZE);
155 .bss : AT(ADDR(.bss) - LOAD_OFFSET) { 97 __init_end = .;
156 __init_end = .; 98 BSS_SECTION(0, PAGE_SIZE, 4)
157 __bss_start = .; /* BSS */ 99 _ebss = .; /* uClinux MTD sucks */
158 *(.bss.page_aligned) 100 _end = . ;
159 *(.bss)
160 *(COMMON)
161 . = ALIGN(4);
162 _ebss = .; /* uClinux MTD sucks */
163 _end = . ;
164 }
165 101
166 /* 102 /*
167 * When something in the kernel is NOT compiled as a module, the 103 * When something in the kernel is NOT compiled as a module, the
@@ -170,7 +106,7 @@ SECTIONS
170 * it's a module. 106 * it's a module.
171 */ 107 */
172 /DISCARD/ : { 108 /DISCARD/ : {
173 *(.exitcall.exit) 109 EXIT_CALL
174 } 110 }
175 111
176 STABS_DEBUG 112 STABS_DEBUG