diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /arch/sh/kernel | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'arch/sh/kernel')
130 files changed, 6836 insertions, 3553 deletions
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index a2d0a40f3848..02fd3ae8b0ee 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile | |||
@@ -9,8 +9,13 @@ ifdef CONFIG_FUNCTION_TRACER | |||
9 | CFLAGS_REMOVE_ftrace.o = -pg | 9 | CFLAGS_REMOVE_ftrace.o = -pg |
10 | endif | 10 | endif |
11 | 11 | ||
12 | obj-y := debugtraps.o dumpstack.o idle.o io.o io_generic.o irq.o \ | 12 | CFLAGS_REMOVE_return_address.o = -pg |
13 | machvec.o nmi_debug.o process_$(BITS).o ptrace_$(BITS).o \ | 13 | |
14 | obj-y := debugtraps.o dma-nommu.o dumpstack.o \ | ||
15 | idle.o io.o io_generic.o irq.o \ | ||
16 | irq_$(BITS).o machvec.o nmi_debug.o process.o \ | ||
17 | process_$(BITS).o ptrace_$(BITS).o \ | ||
18 | reboot.o return_address.o \ | ||
14 | setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ | 19 | setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ |
15 | syscalls_$(BITS).o time.o topology.o traps.o \ | 20 | syscalls_$(BITS).o time.o topology.o traps.o \ |
16 | traps_$(BITS).o unwinder.o | 21 | traps_$(BITS).o unwinder.o |
@@ -22,20 +27,20 @@ obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o | |||
22 | obj-$(CONFIG_KGDB) += kgdb.o | 27 | obj-$(CONFIG_KGDB) += kgdb.o |
23 | obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o | 28 | obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o |
24 | obj-$(CONFIG_MODULES) += sh_ksyms_$(BITS).o module.o | 29 | obj-$(CONFIG_MODULES) += sh_ksyms_$(BITS).o module.o |
25 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | ||
26 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 30 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
27 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 31 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
28 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 32 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
29 | obj-$(CONFIG_IO_TRAPPED) += io_trapped.o | 33 | obj-$(CONFIG_IO_TRAPPED) += io_trapped.o |
30 | obj-$(CONFIG_KPROBES) += kprobes.o | 34 | obj-$(CONFIG_KPROBES) += kprobes.o |
31 | obj-$(CONFIG_GENERIC_GPIO) += gpio.o | ||
32 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 35 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
33 | obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o | 36 | obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o |
34 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | 37 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o |
35 | obj-$(CONFIG_DUMP_CODE) += disassemble.o | 38 | obj-$(CONFIG_DUMP_CODE) += disassemble.o |
36 | obj-$(CONFIG_HIBERNATION) += swsusp.o | 39 | obj-$(CONFIG_HIBERNATION) += swsusp.o |
37 | obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o | 40 | obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o |
41 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_callchain.o | ||
38 | 42 | ||
43 | obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o | ||
39 | obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o | 44 | obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o |
40 | 45 | ||
41 | EXTRA_CFLAGS += -Werror | 46 | EXTRA_CFLAGS += -Werror |
diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c index d218e808294e..08a2be775b6c 100644 --- a/arch/sh/kernel/asm-offsets.c +++ b/arch/sh/kernel/asm-offsets.c | |||
@@ -34,5 +34,28 @@ int main(void) | |||
34 | DEFINE(PBE_NEXT, offsetof(struct pbe, next)); | 34 | DEFINE(PBE_NEXT, offsetof(struct pbe, next)); |
35 | DEFINE(SWSUSP_ARCH_REGS_SIZE, sizeof(struct swsusp_arch_regs)); | 35 | DEFINE(SWSUSP_ARCH_REGS_SIZE, sizeof(struct swsusp_arch_regs)); |
36 | #endif | 36 | #endif |
37 | |||
38 | DEFINE(SH_SLEEP_MODE, offsetof(struct sh_sleep_data, mode)); | ||
39 | DEFINE(SH_SLEEP_SF_PRE, offsetof(struct sh_sleep_data, sf_pre)); | ||
40 | DEFINE(SH_SLEEP_SF_POST, offsetof(struct sh_sleep_data, sf_post)); | ||
41 | DEFINE(SH_SLEEP_RESUME, offsetof(struct sh_sleep_data, resume)); | ||
42 | DEFINE(SH_SLEEP_VBR, offsetof(struct sh_sleep_data, vbr)); | ||
43 | DEFINE(SH_SLEEP_SPC, offsetof(struct sh_sleep_data, spc)); | ||
44 | DEFINE(SH_SLEEP_SR, offsetof(struct sh_sleep_data, sr)); | ||
45 | DEFINE(SH_SLEEP_SP, offsetof(struct sh_sleep_data, sp)); | ||
46 | DEFINE(SH_SLEEP_BASE_ADDR, offsetof(struct sh_sleep_data, addr)); | ||
47 | DEFINE(SH_SLEEP_BASE_DATA, offsetof(struct sh_sleep_data, data)); | ||
48 | DEFINE(SH_SLEEP_REG_STBCR, offsetof(struct sh_sleep_regs, stbcr)); | ||
49 | DEFINE(SH_SLEEP_REG_BAR, offsetof(struct sh_sleep_regs, bar)); | ||
50 | DEFINE(SH_SLEEP_REG_PTEH, offsetof(struct sh_sleep_regs, pteh)); | ||
51 | DEFINE(SH_SLEEP_REG_PTEL, offsetof(struct sh_sleep_regs, ptel)); | ||
52 | DEFINE(SH_SLEEP_REG_TTB, offsetof(struct sh_sleep_regs, ttb)); | ||
53 | DEFINE(SH_SLEEP_REG_TEA, offsetof(struct sh_sleep_regs, tea)); | ||
54 | DEFINE(SH_SLEEP_REG_MMUCR, offsetof(struct sh_sleep_regs, mmucr)); | ||
55 | DEFINE(SH_SLEEP_REG_PTEA, offsetof(struct sh_sleep_regs, ptea)); | ||
56 | DEFINE(SH_SLEEP_REG_PASCR, offsetof(struct sh_sleep_regs, pascr)); | ||
57 | DEFINE(SH_SLEEP_REG_IRMCR, offsetof(struct sh_sleep_regs, irmcr)); | ||
58 | DEFINE(SH_SLEEP_REG_CCR, offsetof(struct sh_sleep_regs, ccr)); | ||
59 | DEFINE(SH_SLEEP_REG_RAMCR, offsetof(struct sh_sleep_regs, ramcr)); | ||
37 | return 0; | 60 | return 0; |
38 | } | 61 | } |
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index 3d6b9312dc47..0e48bc61c272 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile | |||
@@ -15,8 +15,9 @@ obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/ | |||
15 | 15 | ||
16 | # Common interfaces. | 16 | # Common interfaces. |
17 | 17 | ||
18 | obj-$(CONFIG_UBC_WAKEUP) += ubc.o | ||
19 | obj-$(CONFIG_SH_ADC) += adc.o | 18 | obj-$(CONFIG_SH_ADC) += adc.o |
20 | obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o | 19 | obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o |
20 | obj-$(CONFIG_SH_FPU) += fpu.o | ||
21 | obj-$(CONFIG_SH_FPU_EMU) += fpu.o | ||
21 | 22 | ||
22 | obj-y += irq/ init.o clock.o hwblk.o | 23 | obj-y += irq/ init.o clock.o hwblk.o |
diff --git a/arch/sh/kernel/cpu/adc.c b/arch/sh/kernel/cpu/adc.c index da3d6877f93d..d307571d54b6 100644 --- a/arch/sh/kernel/cpu/adc.c +++ b/arch/sh/kernel/cpu/adc.c | |||
@@ -18,19 +18,19 @@ int adc_single(unsigned int channel) | |||
18 | 18 | ||
19 | off = (channel & 0x03) << 2; | 19 | off = (channel & 0x03) << 2; |
20 | 20 | ||
21 | csr = ctrl_inb(ADCSR); | 21 | csr = __raw_readb(ADCSR); |
22 | csr = channel | ADCSR_ADST | ADCSR_CKS; | 22 | csr = channel | ADCSR_ADST | ADCSR_CKS; |
23 | ctrl_outb(csr, ADCSR); | 23 | __raw_writeb(csr, ADCSR); |
24 | 24 | ||
25 | do { | 25 | do { |
26 | csr = ctrl_inb(ADCSR); | 26 | csr = __raw_readb(ADCSR); |
27 | } while ((csr & ADCSR_ADF) == 0); | 27 | } while ((csr & ADCSR_ADF) == 0); |
28 | 28 | ||
29 | csr &= ~(ADCSR_ADF | ADCSR_ADST); | 29 | csr &= ~(ADCSR_ADF | ADCSR_ADST); |
30 | ctrl_outb(csr, ADCSR); | 30 | __raw_writeb(csr, ADCSR); |
31 | 31 | ||
32 | return (((ctrl_inb(ADDRAH + off) << 8) | | 32 | return (((__raw_readb(ADDRAH + off) << 8) | |
33 | ctrl_inb(ADDRAL + off)) >> 6); | 33 | __raw_readb(ADDRAL + off)) >> 6); |
34 | } | 34 | } |
35 | 35 | ||
36 | EXPORT_SYMBOL(adc_single); | 36 | EXPORT_SYMBOL(adc_single); |
diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index 6dfe2cced3fc..eed5eaff96ba 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c | |||
@@ -149,7 +149,8 @@ int __init sh_clk_div6_register(struct clk *clks, int nr) | |||
149 | 149 | ||
150 | static unsigned long sh_clk_div4_recalc(struct clk *clk) | 150 | static unsigned long sh_clk_div4_recalc(struct clk *clk) |
151 | { | 151 | { |
152 | struct clk_div_mult_table *table = clk->priv; | 152 | struct clk_div4_table *d4t = clk->priv; |
153 | struct clk_div_mult_table *table = d4t->div_mult_table; | ||
153 | unsigned int idx; | 154 | unsigned int idx; |
154 | 155 | ||
155 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | 156 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, |
@@ -160,17 +161,90 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk) | |||
160 | return clk->freq_table[idx].frequency; | 161 | return clk->freq_table[idx].frequency; |
161 | } | 162 | } |
162 | 163 | ||
164 | static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) | ||
165 | { | ||
166 | struct clk_div4_table *d4t = clk->priv; | ||
167 | struct clk_div_mult_table *table = d4t->div_mult_table; | ||
168 | u32 value; | ||
169 | int ret; | ||
170 | |||
171 | if (!strcmp("pll_clk", parent->name)) | ||
172 | value = __raw_readl(clk->enable_reg) & ~(1 << 7); | ||
173 | else | ||
174 | value = __raw_readl(clk->enable_reg) | (1 << 7); | ||
175 | |||
176 | ret = clk_reparent(clk, parent); | ||
177 | if (ret < 0) | ||
178 | return ret; | ||
179 | |||
180 | __raw_writel(value, clk->enable_reg); | ||
181 | |||
182 | /* Rebiuld the frequency table */ | ||
183 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | ||
184 | table, &clk->arch_flags); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id) | ||
190 | { | ||
191 | struct clk_div4_table *d4t = clk->priv; | ||
192 | unsigned long value; | ||
193 | int idx = clk_rate_table_find(clk, clk->freq_table, rate); | ||
194 | if (idx < 0) | ||
195 | return idx; | ||
196 | |||
197 | value = __raw_readl(clk->enable_reg); | ||
198 | value &= ~(0xf << clk->enable_bit); | ||
199 | value |= (idx << clk->enable_bit); | ||
200 | __raw_writel(value, clk->enable_reg); | ||
201 | |||
202 | if (d4t->kick) | ||
203 | d4t->kick(clk); | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int sh_clk_div4_enable(struct clk *clk) | ||
209 | { | ||
210 | __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static void sh_clk_div4_disable(struct clk *clk) | ||
215 | { | ||
216 | __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg); | ||
217 | } | ||
218 | |||
163 | static struct clk_ops sh_clk_div4_clk_ops = { | 219 | static struct clk_ops sh_clk_div4_clk_ops = { |
164 | .recalc = sh_clk_div4_recalc, | 220 | .recalc = sh_clk_div4_recalc, |
221 | .set_rate = sh_clk_div4_set_rate, | ||
165 | .round_rate = sh_clk_div_round_rate, | 222 | .round_rate = sh_clk_div_round_rate, |
166 | }; | 223 | }; |
167 | 224 | ||
168 | int __init sh_clk_div4_register(struct clk *clks, int nr, | 225 | static struct clk_ops sh_clk_div4_enable_clk_ops = { |
169 | struct clk_div_mult_table *table) | 226 | .recalc = sh_clk_div4_recalc, |
227 | .set_rate = sh_clk_div4_set_rate, | ||
228 | .round_rate = sh_clk_div_round_rate, | ||
229 | .enable = sh_clk_div4_enable, | ||
230 | .disable = sh_clk_div4_disable, | ||
231 | }; | ||
232 | |||
233 | static struct clk_ops sh_clk_div4_reparent_clk_ops = { | ||
234 | .recalc = sh_clk_div4_recalc, | ||
235 | .set_rate = sh_clk_div4_set_rate, | ||
236 | .round_rate = sh_clk_div_round_rate, | ||
237 | .enable = sh_clk_div4_enable, | ||
238 | .disable = sh_clk_div4_disable, | ||
239 | .set_parent = sh_clk_div4_set_parent, | ||
240 | }; | ||
241 | |||
242 | static int __init sh_clk_div4_register_ops(struct clk *clks, int nr, | ||
243 | struct clk_div4_table *table, struct clk_ops *ops) | ||
170 | { | 244 | { |
171 | struct clk *clkp; | 245 | struct clk *clkp; |
172 | void *freq_table; | 246 | void *freq_table; |
173 | int nr_divs = table->nr_divisors; | 247 | int nr_divs = table->div_mult_table->nr_divisors; |
174 | int freq_table_size = sizeof(struct cpufreq_frequency_table); | 248 | int freq_table_size = sizeof(struct cpufreq_frequency_table); |
175 | int ret = 0; | 249 | int ret = 0; |
176 | int k; | 250 | int k; |
@@ -185,7 +259,7 @@ int __init sh_clk_div4_register(struct clk *clks, int nr, | |||
185 | for (k = 0; !ret && (k < nr); k++) { | 259 | for (k = 0; !ret && (k < nr); k++) { |
186 | clkp = clks + k; | 260 | clkp = clks + k; |
187 | 261 | ||
188 | clkp->ops = &sh_clk_div4_clk_ops; | 262 | clkp->ops = ops; |
189 | clkp->id = -1; | 263 | clkp->id = -1; |
190 | clkp->priv = table; | 264 | clkp->priv = table; |
191 | 265 | ||
@@ -198,6 +272,26 @@ int __init sh_clk_div4_register(struct clk *clks, int nr, | |||
198 | return ret; | 272 | return ret; |
199 | } | 273 | } |
200 | 274 | ||
275 | int __init sh_clk_div4_register(struct clk *clks, int nr, | ||
276 | struct clk_div4_table *table) | ||
277 | { | ||
278 | return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops); | ||
279 | } | ||
280 | |||
281 | int __init sh_clk_div4_enable_register(struct clk *clks, int nr, | ||
282 | struct clk_div4_table *table) | ||
283 | { | ||
284 | return sh_clk_div4_register_ops(clks, nr, table, | ||
285 | &sh_clk_div4_enable_clk_ops); | ||
286 | } | ||
287 | |||
288 | int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, | ||
289 | struct clk_div4_table *table) | ||
290 | { | ||
291 | return sh_clk_div4_register_ops(clks, nr, table, | ||
292 | &sh_clk_div4_reparent_clk_ops); | ||
293 | } | ||
294 | |||
201 | #ifdef CONFIG_SH_CLK_CPG_LEGACY | 295 | #ifdef CONFIG_SH_CLK_CPG_LEGACY |
202 | static struct clk master_clk = { | 296 | static struct clk master_clk = { |
203 | .name = "master_clk", | 297 | .name = "master_clk", |
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index f3a46be2ae81..e9fa1bfed53e 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c | |||
@@ -404,7 +404,7 @@ EXPORT_SYMBOL_GPL(clk_round_rate); | |||
404 | * If an entry has a device ID, it must match | 404 | * If an entry has a device ID, it must match |
405 | * If an entry has a connection ID, it must match | 405 | * If an entry has a connection ID, it must match |
406 | * Then we take the most specific entry - with the following | 406 | * Then we take the most specific entry - with the following |
407 | * order of precidence: dev+con > dev only > con only. | 407 | * order of precedence: dev+con > dev only > con only. |
408 | */ | 408 | */ |
409 | static struct clk *clk_find(const char *dev_id, const char *con_id) | 409 | static struct clk *clk_find(const char *dev_id, const char *con_id) |
410 | { | 410 | { |
@@ -598,7 +598,7 @@ static struct dentry *clk_debugfs_root; | |||
598 | static int clk_debugfs_register_one(struct clk *c) | 598 | static int clk_debugfs_register_one(struct clk *c) |
599 | { | 599 | { |
600 | int err; | 600 | int err; |
601 | struct dentry *d, *child; | 601 | struct dentry *d, *child, *child_tmp; |
602 | struct clk *pa = c->parent; | 602 | struct clk *pa = c->parent; |
603 | char s[255]; | 603 | char s[255]; |
604 | char *p = s; | 604 | char *p = s; |
@@ -630,7 +630,7 @@ static int clk_debugfs_register_one(struct clk *c) | |||
630 | 630 | ||
631 | err_out: | 631 | err_out: |
632 | d = c->dentry; | 632 | d = c->dentry; |
633 | list_for_each_entry(child, &d->d_subdirs, d_u.d_child) | 633 | list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) |
634 | debugfs_remove(child); | 634 | debugfs_remove(child); |
635 | debugfs_remove(c->dentry); | 635 | debugfs_remove(c->dentry); |
636 | return err; | 636 | return err; |
diff --git a/arch/sh/kernel/cpu/fpu.c b/arch/sh/kernel/cpu/fpu.c new file mode 100644 index 000000000000..7f1b70cace35 --- /dev/null +++ b/arch/sh/kernel/cpu/fpu.c | |||
@@ -0,0 +1,85 @@ | |||
1 | #include <linux/sched.h> | ||
2 | #include <linux/slab.h> | ||
3 | #include <asm/processor.h> | ||
4 | #include <asm/fpu.h> | ||
5 | |||
6 | int init_fpu(struct task_struct *tsk) | ||
7 | { | ||
8 | if (tsk_used_math(tsk)) { | ||
9 | if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current) | ||
10 | unlazy_fpu(tsk, task_pt_regs(tsk)); | ||
11 | return 0; | ||
12 | } | ||
13 | |||
14 | /* | ||
15 | * Memory allocation at the first usage of the FPU and other state. | ||
16 | */ | ||
17 | if (!tsk->thread.xstate) { | ||
18 | tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep, | ||
19 | GFP_KERNEL); | ||
20 | if (!tsk->thread.xstate) | ||
21 | return -ENOMEM; | ||
22 | } | ||
23 | |||
24 | if (boot_cpu_data.flags & CPU_HAS_FPU) { | ||
25 | struct sh_fpu_hard_struct *fp = &tsk->thread.xstate->hardfpu; | ||
26 | memset(fp, 0, xstate_size); | ||
27 | fp->fpscr = FPSCR_INIT; | ||
28 | } else { | ||
29 | struct sh_fpu_soft_struct *fp = &tsk->thread.xstate->softfpu; | ||
30 | memset(fp, 0, xstate_size); | ||
31 | fp->fpscr = FPSCR_INIT; | ||
32 | } | ||
33 | |||
34 | set_stopped_child_used_math(tsk); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | #ifdef CONFIG_SH_FPU | ||
39 | void __fpu_state_restore(void) | ||
40 | { | ||
41 | struct task_struct *tsk = current; | ||
42 | |||
43 | restore_fpu(tsk); | ||
44 | |||
45 | task_thread_info(tsk)->status |= TS_USEDFPU; | ||
46 | tsk->fpu_counter++; | ||
47 | } | ||
48 | |||
49 | void fpu_state_restore(struct pt_regs *regs) | ||
50 | { | ||
51 | struct task_struct *tsk = current; | ||
52 | |||
53 | if (unlikely(!user_mode(regs))) { | ||
54 | printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); | ||
55 | BUG(); | ||
56 | return; | ||
57 | } | ||
58 | |||
59 | if (!tsk_used_math(tsk)) { | ||
60 | local_irq_enable(); | ||
61 | /* | ||
62 | * does a slab alloc which can sleep | ||
63 | */ | ||
64 | if (init_fpu(tsk)) { | ||
65 | /* | ||
66 | * ran out of memory! | ||
67 | */ | ||
68 | do_group_exit(SIGKILL); | ||
69 | return; | ||
70 | } | ||
71 | local_irq_disable(); | ||
72 | } | ||
73 | |||
74 | grab_fpu(regs); | ||
75 | |||
76 | __fpu_state_restore(); | ||
77 | } | ||
78 | |||
79 | BUILD_TRAP_HANDLER(fpu_state_restore) | ||
80 | { | ||
81 | TRAP_HANDLER_DECL; | ||
82 | |||
83 | fpu_state_restore(regs); | ||
84 | } | ||
85 | #endif /* CONFIG_SH_FPU */ | ||
diff --git a/arch/sh/kernel/cpu/hwblk.c b/arch/sh/kernel/cpu/hwblk.c index c0ad7d46e784..67a1e811cfe8 100644 --- a/arch/sh/kernel/cpu/hwblk.c +++ b/arch/sh/kernel/cpu/hwblk.c | |||
@@ -1,6 +1,5 @@ | |||
1 | #include <linux/clk.h> | 1 | #include <linux/clk.h> |
2 | #include <linux/compiler.h> | 2 | #include <linux/compiler.h> |
3 | #include <linux/slab.h> | ||
4 | #include <linux/io.h> | 3 | #include <linux/io.h> |
5 | #include <linux/spinlock.h> | 4 | #include <linux/spinlock.h> |
6 | #include <asm/suspend.h> | 5 | #include <asm/suspend.h> |
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index e932ebef4738..c736422344eb 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c | |||
@@ -24,22 +24,32 @@ | |||
24 | #include <asm/elf.h> | 24 | #include <asm/elf.h> |
25 | #include <asm/io.h> | 25 | #include <asm/io.h> |
26 | #include <asm/smp.h> | 26 | #include <asm/smp.h> |
27 | #ifdef CONFIG_SUPERH32 | 27 | #include <asm/sh_bios.h> |
28 | #include <asm/ubc.h> | 28 | |
29 | #ifdef CONFIG_SH_FPU | ||
30 | #define cpu_has_fpu 1 | ||
31 | #else | ||
32 | #define cpu_has_fpu 0 | ||
33 | #endif | ||
34 | |||
35 | #ifdef CONFIG_SH_DSP | ||
36 | #define cpu_has_dsp 1 | ||
37 | #else | ||
38 | #define cpu_has_dsp 0 | ||
29 | #endif | 39 | #endif |
30 | 40 | ||
31 | /* | 41 | /* |
32 | * Generic wrapper for command line arguments to disable on-chip | 42 | * Generic wrapper for command line arguments to disable on-chip |
33 | * peripherals (nofpu, nodsp, and so forth). | 43 | * peripherals (nofpu, nodsp, and so forth). |
34 | */ | 44 | */ |
35 | #define onchip_setup(x) \ | 45 | #define onchip_setup(x) \ |
36 | static int x##_disabled __initdata = 0; \ | 46 | static int x##_disabled __initdata = !cpu_has_##x; \ |
37 | \ | 47 | \ |
38 | static int __init x##_setup(char *opts) \ | 48 | static int __init x##_setup(char *opts) \ |
39 | { \ | 49 | { \ |
40 | x##_disabled = 1; \ | 50 | x##_disabled = 1; \ |
41 | return 1; \ | 51 | return 1; \ |
42 | } \ | 52 | } \ |
43 | __setup("no" __stringify(x), x##_setup); | 53 | __setup("no" __stringify(x), x##_setup); |
44 | 54 | ||
45 | onchip_setup(fpu); | 55 | onchip_setup(fpu); |
@@ -52,10 +62,10 @@ onchip_setup(dsp); | |||
52 | static void __init speculative_execution_init(void) | 62 | static void __init speculative_execution_init(void) |
53 | { | 63 | { |
54 | /* Clear RABD */ | 64 | /* Clear RABD */ |
55 | ctrl_outl(ctrl_inl(CPUOPM) & ~CPUOPM_RABD, CPUOPM); | 65 | __raw_writel(__raw_readl(CPUOPM) & ~CPUOPM_RABD, CPUOPM); |
56 | 66 | ||
57 | /* Flush the update */ | 67 | /* Flush the update */ |
58 | (void)ctrl_inl(CPUOPM); | 68 | (void)__raw_readl(CPUOPM); |
59 | ctrl_barrier(); | 69 | ctrl_barrier(); |
60 | } | 70 | } |
61 | #else | 71 | #else |
@@ -75,16 +85,11 @@ static void __init expmask_init(void) | |||
75 | /* | 85 | /* |
76 | * Future proofing. | 86 | * Future proofing. |
77 | * | 87 | * |
78 | * Disable support for slottable sleep instruction | 88 | * Disable support for slottable sleep instruction, non-nop |
79 | * and non-nop instructions in the rte delay slot. | 89 | * instructions in the rte delay slot, and associative writes to |
90 | * the memory-mapped cache array. | ||
80 | */ | 91 | */ |
81 | expmask &= ~(EXPMASK_RTEDS | EXPMASK_BRDSSLP); | 92 | expmask &= ~(EXPMASK_RTEDS | EXPMASK_BRDSSLP | EXPMASK_MMCAW); |
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 | 93 | ||
89 | __raw_writel(expmask, EXPMASK); | 94 | __raw_writel(expmask, EXPMASK); |
90 | ctrl_barrier(); | 95 | ctrl_barrier(); |
@@ -94,7 +99,7 @@ static void __init expmask_init(void) | |||
94 | #endif | 99 | #endif |
95 | 100 | ||
96 | /* 2nd-level cache init */ | 101 | /* 2nd-level cache init */ |
97 | void __uses_jump_to_uncached __attribute__ ((weak)) l2_cache_init(void) | 102 | void __attribute__ ((weak)) l2_cache_init(void) |
98 | { | 103 | { |
99 | } | 104 | } |
100 | 105 | ||
@@ -102,12 +107,12 @@ void __uses_jump_to_uncached __attribute__ ((weak)) l2_cache_init(void) | |||
102 | * Generic first-level cache init | 107 | * Generic first-level cache init |
103 | */ | 108 | */ |
104 | #ifdef CONFIG_SUPERH32 | 109 | #ifdef CONFIG_SUPERH32 |
105 | static void __uses_jump_to_uncached cache_init(void) | 110 | static void cache_init(void) |
106 | { | 111 | { |
107 | unsigned long ccr, flags; | 112 | unsigned long ccr, flags; |
108 | 113 | ||
109 | jump_to_uncached(); | 114 | jump_to_uncached(); |
110 | ccr = ctrl_inl(CCR); | 115 | ccr = __raw_readl(CCR); |
111 | 116 | ||
112 | /* | 117 | /* |
113 | * At this point we don't know whether the cache is enabled or not - a | 118 | * At this point we don't know whether the cache is enabled or not - a |
@@ -151,7 +156,7 @@ static void __uses_jump_to_uncached cache_init(void) | |||
151 | for (addr = addrstart; | 156 | for (addr = addrstart; |
152 | addr < addrstart + waysize; | 157 | addr < addrstart + waysize; |
153 | addr += current_cpu_data.dcache.linesz) | 158 | addr += current_cpu_data.dcache.linesz) |
154 | ctrl_outl(0, addr); | 159 | __raw_writel(0, addr); |
155 | 160 | ||
156 | addrstart += current_cpu_data.dcache.way_incr; | 161 | addrstart += current_cpu_data.dcache.way_incr; |
157 | } while (--ways); | 162 | } while (--ways); |
@@ -184,7 +189,7 @@ static void __uses_jump_to_uncached cache_init(void) | |||
184 | 189 | ||
185 | l2_cache_init(); | 190 | l2_cache_init(); |
186 | 191 | ||
187 | ctrl_outl(flags, CCR); | 192 | __raw_writel(flags, CCR); |
188 | back_to_cached(); | 193 | back_to_cached(); |
189 | } | 194 | } |
190 | #else | 195 | #else |
@@ -212,6 +217,18 @@ static void detect_cache_shape(void) | |||
212 | l2_cache_shape = -1; /* No S-cache */ | 217 | l2_cache_shape = -1; /* No S-cache */ |
213 | } | 218 | } |
214 | 219 | ||
220 | static void __init fpu_init(void) | ||
221 | { | ||
222 | /* Disable the FPU */ | ||
223 | if (fpu_disabled && (current_cpu_data.flags & CPU_HAS_FPU)) { | ||
224 | printk("FPU Disabled\n"); | ||
225 | current_cpu_data.flags &= ~CPU_HAS_FPU; | ||
226 | } | ||
227 | |||
228 | disable_fpu(); | ||
229 | clear_used_math(); | ||
230 | } | ||
231 | |||
215 | #ifdef CONFIG_SH_DSP | 232 | #ifdef CONFIG_SH_DSP |
216 | static void __init release_dsp(void) | 233 | static void __init release_dsp(void) |
217 | { | 234 | { |
@@ -249,28 +266,35 @@ static void __init dsp_init(void) | |||
249 | if (sr & SR_DSP) | 266 | if (sr & SR_DSP) |
250 | current_cpu_data.flags |= CPU_HAS_DSP; | 267 | current_cpu_data.flags |= CPU_HAS_DSP; |
251 | 268 | ||
269 | /* Disable the DSP */ | ||
270 | if (dsp_disabled && (current_cpu_data.flags & CPU_HAS_DSP)) { | ||
271 | printk("DSP Disabled\n"); | ||
272 | current_cpu_data.flags &= ~CPU_HAS_DSP; | ||
273 | } | ||
274 | |||
252 | /* Now that we've determined the DSP status, clear the DSP bit. */ | 275 | /* Now that we've determined the DSP status, clear the DSP bit. */ |
253 | release_dsp(); | 276 | release_dsp(); |
254 | } | 277 | } |
278 | #else | ||
279 | static inline void __init dsp_init(void) { } | ||
255 | #endif /* CONFIG_SH_DSP */ | 280 | #endif /* CONFIG_SH_DSP */ |
256 | 281 | ||
257 | /** | 282 | /** |
258 | * sh_cpu_init | 283 | * sh_cpu_init |
259 | * | 284 | * |
260 | * This is our initial entry point for each CPU, and is invoked on the boot | 285 | * This is our initial entry point for each CPU, and is invoked on the |
261 | * CPU prior to calling start_kernel(). For SMP, a combination of this and | 286 | * boot CPU prior to calling start_kernel(). For SMP, a combination of |
262 | * start_secondary() will bring up each processor to a ready state prior | 287 | * this and start_secondary() will bring up each processor to a ready |
263 | * to hand forking the idle loop. | 288 | * state prior to hand forking the idle loop. |
264 | * | 289 | * |
265 | * We do all of the basic processor init here, including setting up the | 290 | * We do all of the basic processor init here, including setting up |
266 | * caches, FPU, DSP, kicking the UBC, etc. By the time start_kernel() is | 291 | * the caches, FPU, DSP, etc. By the time start_kernel() is hit (and |
267 | * hit (and subsequently platform_setup()) things like determining the | 292 | * subsequently platform_setup()) things like determining the CPU |
268 | * CPU subtype and initial configuration will all be done. | 293 | * subtype and initial configuration will all be done. |
269 | * | 294 | * |
270 | * Each processor family is still responsible for doing its own probing | 295 | * Each processor family is still responsible for doing its own probing |
271 | * and cache configuration in detect_cpu_and_cache_system(). | 296 | * and cache configuration in detect_cpu_and_cache_system(). |
272 | */ | 297 | */ |
273 | |||
274 | asmlinkage void __init sh_cpu_init(void) | 298 | asmlinkage void __init sh_cpu_init(void) |
275 | { | 299 | { |
276 | current_thread_info()->cpu = hard_smp_processor_id(); | 300 | current_thread_info()->cpu = hard_smp_processor_id(); |
@@ -307,18 +331,8 @@ asmlinkage void __init sh_cpu_init(void) | |||
307 | detect_cache_shape(); | 331 | detect_cache_shape(); |
308 | } | 332 | } |
309 | 333 | ||
310 | /* Disable the FPU */ | 334 | fpu_init(); |
311 | if (fpu_disabled) { | 335 | dsp_init(); |
312 | printk("FPU Disabled\n"); | ||
313 | current_cpu_data.flags &= ~CPU_HAS_FPU; | ||
314 | disable_fpu(); | ||
315 | } | ||
316 | |||
317 | /* FPU initialization */ | ||
318 | if ((current_cpu_data.flags & CPU_HAS_FPU)) { | ||
319 | clear_thread_flag(TIF_USEDFPU); | ||
320 | clear_used_math(); | ||
321 | } | ||
322 | 336 | ||
323 | /* | 337 | /* |
324 | * Initialize the per-CPU ASID cache very early, since the | 338 | * Initialize the per-CPU ASID cache very early, since the |
@@ -326,29 +340,24 @@ asmlinkage void __init sh_cpu_init(void) | |||
326 | */ | 340 | */ |
327 | current_cpu_data.asid_cache = NO_CONTEXT; | 341 | current_cpu_data.asid_cache = NO_CONTEXT; |
328 | 342 | ||
329 | #ifdef CONFIG_SH_DSP | 343 | speculative_execution_init(); |
330 | /* Probe for DSP */ | 344 | expmask_init(); |
331 | dsp_init(); | ||
332 | 345 | ||
333 | /* Disable the DSP */ | 346 | /* Do the rest of the boot processor setup */ |
334 | if (dsp_disabled) { | 347 | if (raw_smp_processor_id() == 0) { |
335 | printk("DSP Disabled\n"); | 348 | /* Save off the BIOS VBR, if there is one */ |
336 | current_cpu_data.flags &= ~CPU_HAS_DSP; | 349 | sh_bios_vbr_init(); |
337 | release_dsp(); | ||
338 | } | ||
339 | #endif | ||
340 | 350 | ||
341 | /* | 351 | /* |
342 | * Some brain-damaged loaders decided it would be a good idea to put | 352 | * Setup VBR for boot CPU. Secondary CPUs do this through |
343 | * the UBC to sleep. This causes some issues when it comes to things | 353 | * start_secondary(). |
344 | * like PTRACE_SINGLESTEP or doing hardware watchpoints in GDB. So .. | 354 | */ |
345 | * we wake it up and hope that all is well. | 355 | per_cpu_trap_init(); |
346 | */ | ||
347 | #ifdef CONFIG_SUPERH32 | ||
348 | if (raw_smp_processor_id() == 0) | ||
349 | ubc_wakeup(); | ||
350 | #endif | ||
351 | 356 | ||
352 | speculative_execution_init(); | 357 | /* |
353 | expmask_init(); | 358 | * Boot processor to setup the FP and extended state |
359 | * context info. | ||
360 | */ | ||
361 | init_thread_xstate(); | ||
362 | } | ||
354 | } | 363 | } |
diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c index 06e7e2959b54..96a239583948 100644 --- a/arch/sh/kernel/cpu/irq/intc-sh5.c +++ b/arch/sh/kernel/cpu/irq/intc-sh5.c | |||
@@ -123,7 +123,7 @@ static void enable_intc_irq(unsigned int irq) | |||
123 | bitmask = 1 << (irq - 32); | 123 | bitmask = 1 << (irq - 32); |
124 | } | 124 | } |
125 | 125 | ||
126 | ctrl_outl(bitmask, reg); | 126 | __raw_writel(bitmask, reg); |
127 | } | 127 | } |
128 | 128 | ||
129 | static void disable_intc_irq(unsigned int irq) | 129 | static void disable_intc_irq(unsigned int irq) |
@@ -139,7 +139,7 @@ static void disable_intc_irq(unsigned int irq) | |||
139 | bitmask = 1 << (irq - 32); | 139 | bitmask = 1 << (irq - 32); |
140 | } | 140 | } |
141 | 141 | ||
142 | ctrl_outl(bitmask, reg); | 142 | __raw_writel(bitmask, reg); |
143 | } | 143 | } |
144 | 144 | ||
145 | static void mask_and_ack_intc(unsigned int irq) | 145 | static void mask_and_ack_intc(unsigned int irq) |
@@ -170,11 +170,11 @@ void __init plat_irq_setup(void) | |||
170 | 170 | ||
171 | 171 | ||
172 | /* Disable all interrupts and set all priorities to 0 to avoid trouble */ | 172 | /* Disable all interrupts and set all priorities to 0 to avoid trouble */ |
173 | ctrl_outl(-1, INTC_INTDSB_0); | 173 | __raw_writel(-1, INTC_INTDSB_0); |
174 | ctrl_outl(-1, INTC_INTDSB_1); | 174 | __raw_writel(-1, INTC_INTDSB_1); |
175 | 175 | ||
176 | for (reg = INTC_INTPRI_0, i = 0; i < INTC_INTPRI_PREGS; i++, reg += 8) | 176 | for (reg = INTC_INTPRI_0, i = 0; i < INTC_INTPRI_PREGS; i++, reg += 8) |
177 | ctrl_outl( NO_PRIORITY, reg); | 177 | __raw_writel( NO_PRIORITY, reg); |
178 | 178 | ||
179 | 179 | ||
180 | #ifdef CONFIG_SH_CAYMAN | 180 | #ifdef CONFIG_SH_CAYMAN |
@@ -199,7 +199,7 @@ void __init plat_irq_setup(void) | |||
199 | reg = INTC_ICR_SET; | 199 | reg = INTC_ICR_SET; |
200 | i = IRQ_IRL0; | 200 | i = IRQ_IRL0; |
201 | } | 201 | } |
202 | ctrl_outl(INTC_ICR_IRLM, reg); | 202 | __raw_writel(INTC_ICR_IRLM, reg); |
203 | 203 | ||
204 | /* Set interrupt priorities according to platform description */ | 204 | /* Set interrupt priorities according to platform description */ |
205 | for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) { | 205 | for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) { |
@@ -207,7 +207,7 @@ void __init plat_irq_setup(void) | |||
207 | ((i % INTC_INTPRI_PPREG) * 4); | 207 | ((i % INTC_INTPRI_PPREG) * 4); |
208 | if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) { | 208 | if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) { |
209 | /* Upon the 7th, set Priority Register */ | 209 | /* Upon the 7th, set Priority Register */ |
210 | ctrl_outl(data, reg); | 210 | __raw_writel(data, reg); |
211 | data = 0; | 211 | data = 0; |
212 | reg += 8; | 212 | reg += 8; |
213 | } | 213 | } |
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index c1508a90fc6a..9282d965a1b6 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c | |||
@@ -17,16 +17,17 @@ | |||
17 | * for more details. | 17 | * for more details. |
18 | */ | 18 | */ |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/io.h> | ||
20 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
23 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | 24 | #include <linux/module.h> |
22 | #include <linux/io.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/topology.h> | 25 | #include <linux/topology.h> |
25 | 26 | ||
26 | static inline struct ipr_desc *get_ipr_desc(unsigned int irq) | 27 | static inline struct ipr_desc *get_ipr_desc(unsigned int irq) |
27 | { | 28 | { |
28 | struct irq_chip *chip = get_irq_chip(irq); | 29 | struct irq_chip *chip = get_irq_chip(irq); |
29 | return (void *)((char *)chip - offsetof(struct ipr_desc, chip)); | 30 | return container_of(chip, struct ipr_desc, chip); |
30 | } | 31 | } |
31 | 32 | ||
32 | static void disable_ipr_irq(unsigned int irq) | 33 | static void disable_ipr_irq(unsigned int irq) |
diff --git a/arch/sh/kernel/cpu/sh2/clock-sh7619.c b/arch/sh/kernel/cpu/sh2/clock-sh7619.c index 4fe863170e31..0c9f24d7a02f 100644 --- a/arch/sh/kernel/cpu/sh2/clock-sh7619.c +++ b/arch/sh/kernel/cpu/sh2/clock-sh7619.c | |||
@@ -31,7 +31,7 @@ static const int pfc_divisors[] = {1,2,0,4}; | |||
31 | 31 | ||
32 | static void master_clk_init(struct clk *clk) | 32 | static void master_clk_init(struct clk *clk) |
33 | { | 33 | { |
34 | clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; | 34 | clk->rate *= PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 7]; |
35 | } | 35 | } |
36 | 36 | ||
37 | static struct clk_ops sh7619_master_clk_ops = { | 37 | static struct clk_ops sh7619_master_clk_ops = { |
@@ -40,7 +40,7 @@ static struct clk_ops sh7619_master_clk_ops = { | |||
40 | 40 | ||
41 | static unsigned long module_clk_recalc(struct clk *clk) | 41 | static unsigned long module_clk_recalc(struct clk *clk) |
42 | { | 42 | { |
43 | int idx = (ctrl_inw(FREQCR) & 0x0007); | 43 | int idx = (__raw_readw(FREQCR) & 0x0007); |
44 | return clk->parent->rate / pfc_divisors[idx]; | 44 | return clk->parent->rate / pfc_divisors[idx]; |
45 | } | 45 | } |
46 | 46 | ||
@@ -50,7 +50,7 @@ static struct clk_ops sh7619_module_clk_ops = { | |||
50 | 50 | ||
51 | static unsigned long bus_clk_recalc(struct clk *clk) | 51 | static unsigned long bus_clk_recalc(struct clk *clk) |
52 | { | 52 | { |
53 | return clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; | 53 | return clk->parent->rate / pll1rate[(__raw_readw(FREQCR) >> 8) & 7]; |
54 | } | 54 | } |
55 | 55 | ||
56 | static struct clk_ops sh7619_bus_clk_ops = { | 56 | static struct clk_ops sh7619_bus_clk_ops = { |
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c index 8555c05e8667..114c7cee7184 100644 --- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c +++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c | |||
@@ -59,32 +59,48 @@ static struct intc_prio_reg prio_registers[] __initdata = { | |||
59 | static DECLARE_INTC_DESC(intc_desc, "sh7619", vectors, NULL, | 59 | static DECLARE_INTC_DESC(intc_desc, "sh7619", vectors, NULL, |
60 | NULL, prio_registers, NULL); | 60 | NULL, prio_registers, NULL); |
61 | 61 | ||
62 | static struct plat_sci_port sci_platform_data[] = { | 62 | static struct plat_sci_port scif0_platform_data = { |
63 | { | 63 | .mapbase = 0xf8400000, |
64 | .mapbase = 0xf8400000, | 64 | .flags = UPF_BOOT_AUTOCONF, |
65 | .flags = UPF_BOOT_AUTOCONF, | 65 | .type = PORT_SCIF, |
66 | .type = PORT_SCIF, | 66 | .irqs = { 88, 88, 88, 88 }, |
67 | .irqs = { 88, 88, 88, 88 }, | 67 | }; |
68 | }, { | 68 | |
69 | .mapbase = 0xf8410000, | 69 | static struct platform_device scif0_device = { |
70 | .flags = UPF_BOOT_AUTOCONF, | 70 | .name = "sh-sci", |
71 | .type = PORT_SCIF, | 71 | .id = 0, |
72 | .irqs = { 92, 92, 92, 92 }, | 72 | .dev = { |
73 | }, { | 73 | .platform_data = &scif0_platform_data, |
74 | .mapbase = 0xf8420000, | 74 | }, |
75 | .flags = UPF_BOOT_AUTOCONF, | 75 | }; |
76 | .type = PORT_SCIF, | 76 | |
77 | .irqs = { 96, 96, 96, 96 }, | 77 | static struct plat_sci_port scif1_platform_data = { |
78 | }, { | 78 | .mapbase = 0xf8410000, |
79 | .flags = 0, | 79 | .flags = UPF_BOOT_AUTOCONF, |
80 | } | 80 | .type = PORT_SCIF, |
81 | }; | 81 | .irqs = { 92, 92, 92, 92 }, |
82 | 82 | }; | |
83 | static struct platform_device sci_device = { | 83 | |
84 | static struct platform_device scif1_device = { | ||
85 | .name = "sh-sci", | ||
86 | .id = 1, | ||
87 | .dev = { | ||
88 | .platform_data = &scif1_platform_data, | ||
89 | }, | ||
90 | }; | ||
91 | |||
92 | static struct plat_sci_port scif2_platform_data = { | ||
93 | .mapbase = 0xf8420000, | ||
94 | .flags = UPF_BOOT_AUTOCONF, | ||
95 | .type = PORT_SCIF, | ||
96 | .irqs = { 96, 96, 96, 96 }, | ||
97 | }; | ||
98 | |||
99 | static struct platform_device scif2_device = { | ||
84 | .name = "sh-sci", | 100 | .name = "sh-sci", |
85 | .id = -1, | 101 | .id = 2, |
86 | .dev = { | 102 | .dev = { |
87 | .platform_data = sci_platform_data, | 103 | .platform_data = &scif2_platform_data, |
88 | }, | 104 | }, |
89 | }; | 105 | }; |
90 | 106 | ||
@@ -176,7 +192,9 @@ static struct platform_device cmt1_device = { | |||
176 | }; | 192 | }; |
177 | 193 | ||
178 | static struct platform_device *sh7619_devices[] __initdata = { | 194 | static struct platform_device *sh7619_devices[] __initdata = { |
179 | &sci_device, | 195 | &scif0_device, |
196 | &scif1_device, | ||
197 | &scif2_device, | ||
180 | ð_device, | 198 | ð_device, |
181 | &cmt0_device, | 199 | &cmt0_device, |
182 | &cmt1_device, | 200 | &cmt1_device, |
@@ -195,6 +213,9 @@ void __init plat_irq_setup(void) | |||
195 | } | 213 | } |
196 | 214 | ||
197 | static struct platform_device *sh7619_early_devices[] __initdata = { | 215 | static struct platform_device *sh7619_early_devices[] __initdata = { |
216 | &scif0_device, | ||
217 | &scif1_device, | ||
218 | &scif2_device, | ||
198 | &cmt0_device, | 219 | &cmt0_device, |
199 | &cmt1_device, | 220 | &cmt1_device, |
200 | }; | 221 | }; |
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c index 7814c76159a7..b26264dc2aef 100644 --- a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c | |||
@@ -34,7 +34,7 @@ static const int pfc_divisors[]={1,2,3,4,6,8,12}; | |||
34 | 34 | ||
35 | static void master_clk_init(struct clk *clk) | 35 | static void master_clk_init(struct clk *clk) |
36 | { | 36 | { |
37 | return 10000000 * PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; | 37 | return 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007]; |
38 | } | 38 | } |
39 | 39 | ||
40 | static struct clk_ops sh7201_master_clk_ops = { | 40 | static struct clk_ops sh7201_master_clk_ops = { |
@@ -43,7 +43,7 @@ static struct clk_ops sh7201_master_clk_ops = { | |||
43 | 43 | ||
44 | static unsigned long module_clk_recalc(struct clk *clk) | 44 | static unsigned long module_clk_recalc(struct clk *clk) |
45 | { | 45 | { |
46 | int idx = (ctrl_inw(FREQCR) & 0x0007); | 46 | int idx = (__raw_readw(FREQCR) & 0x0007); |
47 | return clk->parent->rate / pfc_divisors[idx]; | 47 | return clk->parent->rate / pfc_divisors[idx]; |
48 | } | 48 | } |
49 | 49 | ||
@@ -53,7 +53,7 @@ static struct clk_ops sh7201_module_clk_ops = { | |||
53 | 53 | ||
54 | static unsigned long bus_clk_recalc(struct clk *clk) | 54 | static unsigned long bus_clk_recalc(struct clk *clk) |
55 | { | 55 | { |
56 | int idx = (ctrl_inw(FREQCR) & 0x0007); | 56 | int idx = (__raw_readw(FREQCR) & 0x0007); |
57 | return clk->parent->rate / pfc_divisors[idx]; | 57 | return clk->parent->rate / pfc_divisors[idx]; |
58 | } | 58 | } |
59 | 59 | ||
@@ -63,7 +63,7 @@ static struct clk_ops sh7201_bus_clk_ops = { | |||
63 | 63 | ||
64 | static unsigned long cpu_clk_recalc(struct clk *clk) | 64 | static unsigned long cpu_clk_recalc(struct clk *clk) |
65 | { | 65 | { |
66 | int idx = ((ctrl_inw(FREQCR) >> 4) & 0x0007); | 66 | int idx = ((__raw_readw(FREQCR) >> 4) & 0x0007); |
67 | return clk->parent->rate / ifc_divisors[idx]; | 67 | return clk->parent->rate / ifc_divisors[idx]; |
68 | } | 68 | } |
69 | 69 | ||
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7203.c b/arch/sh/kernel/cpu/sh2a/clock-sh7203.c index 940986965102..7e75d8f79502 100644 --- a/arch/sh/kernel/cpu/sh2a/clock-sh7203.c +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7203.c | |||
@@ -39,7 +39,7 @@ static const int pfc_divisors[]={1,2,3,4,6,8,12}; | |||
39 | 39 | ||
40 | static void master_clk_init(struct clk *clk) | 40 | static void master_clk_init(struct clk *clk) |
41 | { | 41 | { |
42 | clk->rate *= pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0003] * PLL2 ; | 42 | clk->rate *= pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0003] * PLL2 ; |
43 | } | 43 | } |
44 | 44 | ||
45 | static struct clk_ops sh7203_master_clk_ops = { | 45 | static struct clk_ops sh7203_master_clk_ops = { |
@@ -48,7 +48,7 @@ static struct clk_ops sh7203_master_clk_ops = { | |||
48 | 48 | ||
49 | static unsigned long module_clk_recalc(struct clk *clk) | 49 | static unsigned long module_clk_recalc(struct clk *clk) |
50 | { | 50 | { |
51 | int idx = (ctrl_inw(FREQCR) & 0x0007); | 51 | int idx = (__raw_readw(FREQCR) & 0x0007); |
52 | return clk->parent->rate / pfc_divisors[idx]; | 52 | return clk->parent->rate / pfc_divisors[idx]; |
53 | } | 53 | } |
54 | 54 | ||
@@ -58,7 +58,7 @@ static struct clk_ops sh7203_module_clk_ops = { | |||
58 | 58 | ||
59 | static unsigned long bus_clk_recalc(struct clk *clk) | 59 | static unsigned long bus_clk_recalc(struct clk *clk) |
60 | { | 60 | { |
61 | int idx = (ctrl_inw(FREQCR) & 0x0007); | 61 | int idx = (__raw_readw(FREQCR) & 0x0007); |
62 | return clk->parent->rate / pfc_divisors[idx-2]; | 62 | return clk->parent->rate / pfc_divisors[idx-2]; |
63 | } | 63 | } |
64 | 64 | ||
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c index c2268bdeceeb..b27a5e2687ab 100644 --- a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c | |||
@@ -34,7 +34,7 @@ static const int pfc_divisors[]={1,2,3,4,6,8,12}; | |||
34 | 34 | ||
35 | static void master_clk_init(struct clk *clk) | 35 | static void master_clk_init(struct clk *clk) |
36 | { | 36 | { |
37 | clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; | 37 | clk->rate *= PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007]; |
38 | } | 38 | } |
39 | 39 | ||
40 | static struct clk_ops sh7206_master_clk_ops = { | 40 | static struct clk_ops sh7206_master_clk_ops = { |
@@ -43,7 +43,7 @@ static struct clk_ops sh7206_master_clk_ops = { | |||
43 | 43 | ||
44 | static unsigned long module_clk_recalc(struct clk *clk) | 44 | static unsigned long module_clk_recalc(struct clk *clk) |
45 | { | 45 | { |
46 | int idx = (ctrl_inw(FREQCR) & 0x0007); | 46 | int idx = (__raw_readw(FREQCR) & 0x0007); |
47 | return clk->parent->rate / pfc_divisors[idx]; | 47 | return clk->parent->rate / pfc_divisors[idx]; |
48 | } | 48 | } |
49 | 49 | ||
@@ -53,7 +53,7 @@ static struct clk_ops sh7206_module_clk_ops = { | |||
53 | 53 | ||
54 | static unsigned long bus_clk_recalc(struct clk *clk) | 54 | static unsigned long bus_clk_recalc(struct clk *clk) |
55 | { | 55 | { |
56 | return clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; | 56 | return clk->parent->rate / pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007]; |
57 | } | 57 | } |
58 | 58 | ||
59 | static struct clk_ops sh7206_bus_clk_ops = { | 59 | static struct clk_ops sh7206_bus_clk_ops = { |
@@ -62,7 +62,7 @@ static struct clk_ops sh7206_bus_clk_ops = { | |||
62 | 62 | ||
63 | static unsigned long cpu_clk_recalc(struct clk *clk) | 63 | static unsigned long cpu_clk_recalc(struct clk *clk) |
64 | { | 64 | { |
65 | int idx = (ctrl_inw(FREQCR) & 0x0007); | 65 | int idx = (__raw_readw(FREQCR) & 0x0007); |
66 | return clk->parent->rate / ifc_divisors[idx]; | 66 | return clk->parent->rate / ifc_divisors[idx]; |
67 | } | 67 | } |
68 | 68 | ||
diff --git a/arch/sh/kernel/cpu/sh2a/fpu.c b/arch/sh/kernel/cpu/sh2a/fpu.c index 6df2fb98eb30..488d24e0cdf0 100644 --- a/arch/sh/kernel/cpu/sh2a/fpu.c +++ b/arch/sh/kernel/cpu/sh2a/fpu.c | |||
@@ -25,14 +25,11 @@ | |||
25 | 25 | ||
26 | /* | 26 | /* |
27 | * Save FPU registers onto task structure. | 27 | * Save FPU registers onto task structure. |
28 | * Assume called with FPU enabled (SR.FD=0). | ||
29 | */ | 28 | */ |
30 | void | 29 | void save_fpu(struct task_struct *tsk) |
31 | save_fpu(struct task_struct *tsk, struct pt_regs *regs) | ||
32 | { | 30 | { |
33 | unsigned long dummy; | 31 | unsigned long dummy; |
34 | 32 | ||
35 | clear_tsk_thread_flag(tsk, TIF_USEDFPU); | ||
36 | enable_fpu(); | 33 | enable_fpu(); |
37 | asm volatile("sts.l fpul, @-%0\n\t" | 34 | asm volatile("sts.l fpul, @-%0\n\t" |
38 | "sts.l fpscr, @-%0\n\t" | 35 | "sts.l fpscr, @-%0\n\t" |
@@ -54,17 +51,15 @@ save_fpu(struct task_struct *tsk, struct pt_regs *regs) | |||
54 | "fmov.s fr0, @-%0\n\t" | 51 | "fmov.s fr0, @-%0\n\t" |
55 | "lds %3, fpscr\n\t" | 52 | "lds %3, fpscr\n\t" |
56 | : "=r" (dummy) | 53 | : "=r" (dummy) |
57 | : "0" ((char *)(&tsk->thread.fpu.hard.status)), | 54 | : "0" ((char *)(&tsk->thread.xstate->hardfpu.status)), |
58 | "r" (FPSCR_RCHG), | 55 | "r" (FPSCR_RCHG), |
59 | "r" (FPSCR_INIT) | 56 | "r" (FPSCR_INIT) |
60 | : "memory"); | 57 | : "memory"); |
61 | 58 | ||
62 | disable_fpu(); | 59 | disable_fpu(); |
63 | release_fpu(regs); | ||
64 | } | 60 | } |
65 | 61 | ||
66 | static void | 62 | void restore_fpu(struct task_struct *tsk) |
67 | restore_fpu(struct task_struct *tsk) | ||
68 | { | 63 | { |
69 | unsigned long dummy; | 64 | unsigned long dummy; |
70 | 65 | ||
@@ -88,45 +83,12 @@ restore_fpu(struct task_struct *tsk) | |||
88 | "lds.l @%0+, fpscr\n\t" | 83 | "lds.l @%0+, fpscr\n\t" |
89 | "lds.l @%0+, fpul\n\t" | 84 | "lds.l @%0+, fpul\n\t" |
90 | : "=r" (dummy) | 85 | : "=r" (dummy) |
91 | : "0" (&tsk->thread.fpu), "r" (FPSCR_RCHG) | 86 | : "0" (tsk->thread.xstate), "r" (FPSCR_RCHG) |
92 | : "memory"); | 87 | : "memory"); |
93 | disable_fpu(); | 88 | disable_fpu(); |
94 | } | 89 | } |
95 | 90 | ||
96 | /* | 91 | /* |
97 | * Load the FPU with signalling NANS. This bit pattern we're using | ||
98 | * has the property that no matter wether considered as single or as | ||
99 | * double precission represents signaling NANS. | ||
100 | */ | ||
101 | |||
102 | static void | ||
103 | fpu_init(void) | ||
104 | { | ||
105 | enable_fpu(); | ||
106 | asm volatile("lds %0, fpul\n\t" | ||
107 | "fsts fpul, fr0\n\t" | ||
108 | "fsts fpul, fr1\n\t" | ||
109 | "fsts fpul, fr2\n\t" | ||
110 | "fsts fpul, fr3\n\t" | ||
111 | "fsts fpul, fr4\n\t" | ||
112 | "fsts fpul, fr5\n\t" | ||
113 | "fsts fpul, fr6\n\t" | ||
114 | "fsts fpul, fr7\n\t" | ||
115 | "fsts fpul, fr8\n\t" | ||
116 | "fsts fpul, fr9\n\t" | ||
117 | "fsts fpul, fr10\n\t" | ||
118 | "fsts fpul, fr11\n\t" | ||
119 | "fsts fpul, fr12\n\t" | ||
120 | "fsts fpul, fr13\n\t" | ||
121 | "fsts fpul, fr14\n\t" | ||
122 | "fsts fpul, fr15\n\t" | ||
123 | "lds %2, fpscr\n\t" | ||
124 | : /* no output */ | ||
125 | : "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT)); | ||
126 | disable_fpu(); | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Emulate arithmetic ops on denormalized number for some FPU insns. | 92 | * Emulate arithmetic ops on denormalized number for some FPU insns. |
131 | */ | 93 | */ |
132 | 94 | ||
@@ -493,9 +455,9 @@ ieee_fpe_handler (struct pt_regs *regs) | |||
493 | if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */ | 455 | if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */ |
494 | struct task_struct *tsk = current; | 456 | struct task_struct *tsk = current; |
495 | 457 | ||
496 | if ((tsk->thread.fpu.hard.fpscr & FPSCR_FPU_ERROR)) { | 458 | if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_FPU_ERROR)) { |
497 | /* FPU error */ | 459 | /* FPU error */ |
498 | denormal_to_double (&tsk->thread.fpu.hard, | 460 | denormal_to_double (&tsk->thread.xstate->hardfpu, |
499 | (finsn >> 8) & 0xf); | 461 | (finsn >> 8) & 0xf); |
500 | } else | 462 | } else |
501 | return 0; | 463 | return 0; |
@@ -510,9 +472,9 @@ ieee_fpe_handler (struct pt_regs *regs) | |||
510 | 472 | ||
511 | n = (finsn >> 8) & 0xf; | 473 | n = (finsn >> 8) & 0xf; |
512 | m = (finsn >> 4) & 0xf; | 474 | m = (finsn >> 4) & 0xf; |
513 | hx = tsk->thread.fpu.hard.fp_regs[n]; | 475 | hx = tsk->thread.xstate->hardfpu.fp_regs[n]; |
514 | hy = tsk->thread.fpu.hard.fp_regs[m]; | 476 | hy = tsk->thread.xstate->hardfpu.fp_regs[m]; |
515 | fpscr = tsk->thread.fpu.hard.fpscr; | 477 | fpscr = tsk->thread.xstate->hardfpu.fpscr; |
516 | prec = fpscr & (1 << 19); | 478 | prec = fpscr & (1 << 19); |
517 | 479 | ||
518 | if ((fpscr & FPSCR_FPU_ERROR) | 480 | if ((fpscr & FPSCR_FPU_ERROR) |
@@ -522,15 +484,15 @@ ieee_fpe_handler (struct pt_regs *regs) | |||
522 | 484 | ||
523 | /* FPU error because of denormal */ | 485 | /* FPU error because of denormal */ |
524 | llx = ((long long) hx << 32) | 486 | llx = ((long long) hx << 32) |
525 | | tsk->thread.fpu.hard.fp_regs[n+1]; | 487 | | tsk->thread.xstate->hardfpu.fp_regs[n+1]; |
526 | lly = ((long long) hy << 32) | 488 | lly = ((long long) hy << 32) |
527 | | tsk->thread.fpu.hard.fp_regs[m+1]; | 489 | | tsk->thread.xstate->hardfpu.fp_regs[m+1]; |
528 | if ((hx & 0x7fffffff) >= 0x00100000) | 490 | if ((hx & 0x7fffffff) >= 0x00100000) |
529 | llx = denormal_muld(lly, llx); | 491 | llx = denormal_muld(lly, llx); |
530 | else | 492 | else |
531 | llx = denormal_muld(llx, lly); | 493 | llx = denormal_muld(llx, lly); |
532 | tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; | 494 | tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32; |
533 | tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff; | 495 | tsk->thread.xstate->hardfpu.fp_regs[n+1] = llx & 0xffffffff; |
534 | } else if ((fpscr & FPSCR_FPU_ERROR) | 496 | } else if ((fpscr & FPSCR_FPU_ERROR) |
535 | && (!prec && ((hx & 0x7fffffff) < 0x00800000 | 497 | && (!prec && ((hx & 0x7fffffff) < 0x00800000 |
536 | || (hy & 0x7fffffff) < 0x00800000))) { | 498 | || (hy & 0x7fffffff) < 0x00800000))) { |
@@ -539,7 +501,7 @@ ieee_fpe_handler (struct pt_regs *regs) | |||
539 | hx = denormal_mulf(hy, hx); | 501 | hx = denormal_mulf(hy, hx); |
540 | else | 502 | else |
541 | hx = denormal_mulf(hx, hy); | 503 | hx = denormal_mulf(hx, hy); |
542 | tsk->thread.fpu.hard.fp_regs[n] = hx; | 504 | tsk->thread.xstate->hardfpu.fp_regs[n] = hx; |
543 | } else | 505 | } else |
544 | return 0; | 506 | return 0; |
545 | 507 | ||
@@ -553,9 +515,9 @@ ieee_fpe_handler (struct pt_regs *regs) | |||
553 | 515 | ||
554 | n = (finsn >> 8) & 0xf; | 516 | n = (finsn >> 8) & 0xf; |
555 | m = (finsn >> 4) & 0xf; | 517 | m = (finsn >> 4) & 0xf; |
556 | hx = tsk->thread.fpu.hard.fp_regs[n]; | 518 | hx = tsk->thread.xstate->hardfpu.fp_regs[n]; |
557 | hy = tsk->thread.fpu.hard.fp_regs[m]; | 519 | hy = tsk->thread.xstate->hardfpu.fp_regs[m]; |
558 | fpscr = tsk->thread.fpu.hard.fpscr; | 520 | fpscr = tsk->thread.xstate->hardfpu.fpscr; |
559 | prec = fpscr & (1 << 19); | 521 | prec = fpscr & (1 << 19); |
560 | 522 | ||
561 | if ((fpscr & FPSCR_FPU_ERROR) | 523 | if ((fpscr & FPSCR_FPU_ERROR) |
@@ -565,15 +527,15 @@ ieee_fpe_handler (struct pt_regs *regs) | |||
565 | 527 | ||
566 | /* FPU error because of denormal */ | 528 | /* FPU error because of denormal */ |
567 | llx = ((long long) hx << 32) | 529 | llx = ((long long) hx << 32) |
568 | | tsk->thread.fpu.hard.fp_regs[n+1]; | 530 | | tsk->thread.xstate->hardfpu.fp_regs[n+1]; |
569 | lly = ((long long) hy << 32) | 531 | lly = ((long long) hy << 32) |
570 | | tsk->thread.fpu.hard.fp_regs[m+1]; | 532 | | tsk->thread.xstate->hardfpu.fp_regs[m+1]; |
571 | if ((finsn & 0xf00f) == 0xf000) | 533 | if ((finsn & 0xf00f) == 0xf000) |
572 | llx = denormal_addd(llx, lly); | 534 | llx = denormal_addd(llx, lly); |
573 | else | 535 | else |
574 | llx = denormal_addd(llx, lly ^ (1LL << 63)); | 536 | llx = denormal_addd(llx, lly ^ (1LL << 63)); |
575 | tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; | 537 | tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32; |
576 | tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff; | 538 | tsk->thread.xstate->hardfpu.fp_regs[n+1] = llx & 0xffffffff; |
577 | } else if ((fpscr & FPSCR_FPU_ERROR) | 539 | } else if ((fpscr & FPSCR_FPU_ERROR) |
578 | && (!prec && ((hx & 0x7fffffff) < 0x00800000 | 540 | && (!prec && ((hx & 0x7fffffff) < 0x00800000 |
579 | || (hy & 0x7fffffff) < 0x00800000))) { | 541 | || (hy & 0x7fffffff) < 0x00800000))) { |
@@ -582,7 +544,7 @@ ieee_fpe_handler (struct pt_regs *regs) | |||
582 | hx = denormal_addf(hx, hy); | 544 | hx = denormal_addf(hx, hy); |
583 | else | 545 | else |
584 | hx = denormal_addf(hx, hy ^ 0x80000000); | 546 | hx = denormal_addf(hx, hy ^ 0x80000000); |
585 | tsk->thread.fpu.hard.fp_regs[n] = hx; | 547 | tsk->thread.xstate->hardfpu.fp_regs[n] = hx; |
586 | } else | 548 | } else |
587 | return 0; | 549 | return 0; |
588 | 550 | ||
@@ -598,37 +560,15 @@ BUILD_TRAP_HANDLER(fpu_error) | |||
598 | struct task_struct *tsk = current; | 560 | struct task_struct *tsk = current; |
599 | TRAP_HANDLER_DECL; | 561 | TRAP_HANDLER_DECL; |
600 | 562 | ||
601 | save_fpu(tsk, regs); | 563 | __unlazy_fpu(tsk, regs); |
602 | if (ieee_fpe_handler(regs)) { | 564 | if (ieee_fpe_handler(regs)) { |
603 | tsk->thread.fpu.hard.fpscr &= | 565 | tsk->thread.xstate->hardfpu.fpscr &= |
604 | ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); | 566 | ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); |
605 | grab_fpu(regs); | 567 | grab_fpu(regs); |
606 | restore_fpu(tsk); | 568 | restore_fpu(tsk); |
607 | set_tsk_thread_flag(tsk, TIF_USEDFPU); | 569 | task_thread_info(tsk)->status |= TS_USEDFPU; |
608 | return; | 570 | return; |
609 | } | 571 | } |
610 | 572 | ||
611 | force_sig(SIGFPE, tsk); | 573 | force_sig(SIGFPE, tsk); |
612 | } | 574 | } |
613 | |||
614 | BUILD_TRAP_HANDLER(fpu_state_restore) | ||
615 | { | ||
616 | struct task_struct *tsk = current; | ||
617 | TRAP_HANDLER_DECL; | ||
618 | |||
619 | grab_fpu(regs); | ||
620 | if (!user_mode(regs)) { | ||
621 | printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); | ||
622 | return; | ||
623 | } | ||
624 | |||
625 | if (used_math()) { | ||
626 | /* Using the FPU again. */ | ||
627 | restore_fpu(tsk); | ||
628 | } else { | ||
629 | /* First time FPU user. */ | ||
630 | fpu_init(); | ||
631 | set_used_math(); | ||
632 | } | ||
633 | set_tsk_thread_flag(tsk, TIF_USEDFPU); | ||
634 | } | ||
diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c index b67376445315..8f669dc9b0da 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-mxg.c +++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c | |||
@@ -207,27 +207,23 @@ static struct platform_device mtu2_2_device = { | |||
207 | .num_resources = ARRAY_SIZE(mtu2_2_resources), | 207 | .num_resources = ARRAY_SIZE(mtu2_2_resources), |
208 | }; | 208 | }; |
209 | 209 | ||
210 | static struct plat_sci_port sci_platform_data[] = { | 210 | static struct plat_sci_port scif0_platform_data = { |
211 | { | 211 | .mapbase = 0xff804000, |
212 | .mapbase = 0xff804000, | 212 | .flags = UPF_BOOT_AUTOCONF, |
213 | .flags = UPF_BOOT_AUTOCONF, | 213 | .type = PORT_SCIF, |
214 | .type = PORT_SCIF, | 214 | .irqs = { 220, 220, 220, 220 }, |
215 | .irqs = { 220, 220, 220, 220 }, | ||
216 | }, { | ||
217 | .flags = 0, | ||
218 | } | ||
219 | }; | 215 | }; |
220 | 216 | ||
221 | static struct platform_device sci_device = { | 217 | static struct platform_device scif0_device = { |
222 | .name = "sh-sci", | 218 | .name = "sh-sci", |
223 | .id = -1, | 219 | .id = 0, |
224 | .dev = { | 220 | .dev = { |
225 | .platform_data = sci_platform_data, | 221 | .platform_data = &scif0_platform_data, |
226 | }, | 222 | }, |
227 | }; | 223 | }; |
228 | 224 | ||
229 | static struct platform_device *mxg_devices[] __initdata = { | 225 | static struct platform_device *mxg_devices[] __initdata = { |
230 | &sci_device, | 226 | &scif0_device, |
231 | &mtu2_0_device, | 227 | &mtu2_0_device, |
232 | &mtu2_1_device, | 228 | &mtu2_1_device, |
233 | &mtu2_2_device, | 229 | &mtu2_2_device, |
@@ -246,6 +242,7 @@ void __init plat_irq_setup(void) | |||
246 | } | 242 | } |
247 | 243 | ||
248 | static struct platform_device *mxg_early_devices[] __initdata = { | 244 | static struct platform_device *mxg_early_devices[] __initdata = { |
245 | &scif0_device, | ||
249 | &mtu2_0_device, | 246 | &mtu2_0_device, |
250 | &mtu2_1_device, | 247 | &mtu2_1_device, |
251 | &mtu2_2_device, | 248 | &mtu2_2_device, |
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c index fbde5b75deb9..4ccfeb59eb1a 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c | |||
@@ -177,57 +177,123 @@ static struct intc_mask_reg mask_registers[] __initdata = { | |||
177 | static DECLARE_INTC_DESC(intc_desc, "sh7201", vectors, groups, | 177 | static DECLARE_INTC_DESC(intc_desc, "sh7201", vectors, groups, |
178 | mask_registers, prio_registers, NULL); | 178 | mask_registers, prio_registers, NULL); |
179 | 179 | ||
180 | static struct plat_sci_port sci_platform_data[] = { | 180 | static struct plat_sci_port scif0_platform_data = { |
181 | { | 181 | .mapbase = 0xfffe8000, |
182 | .mapbase = 0xfffe8000, | 182 | .flags = UPF_BOOT_AUTOCONF, |
183 | .flags = UPF_BOOT_AUTOCONF, | 183 | .type = PORT_SCIF, |
184 | .type = PORT_SCIF, | 184 | .irqs = { 180, 180, 180, 180 } |
185 | .irqs = { 180, 180, 180, 180 } | 185 | }; |
186 | }, { | 186 | |
187 | .mapbase = 0xfffe8800, | 187 | static struct platform_device scif0_device = { |
188 | .flags = UPF_BOOT_AUTOCONF, | ||
189 | .type = PORT_SCIF, | ||
190 | .irqs = { 184, 184, 184, 184 } | ||
191 | }, { | ||
192 | .mapbase = 0xfffe9000, | ||
193 | .flags = UPF_BOOT_AUTOCONF, | ||
194 | .type = PORT_SCIF, | ||
195 | .irqs = { 188, 188, 188, 188 } | ||
196 | }, { | ||
197 | .mapbase = 0xfffe9800, | ||
198 | .flags = UPF_BOOT_AUTOCONF, | ||
199 | .type = PORT_SCIF, | ||
200 | .irqs = { 192, 192, 192, 192 } | ||
201 | }, { | ||
202 | .mapbase = 0xfffea000, | ||
203 | .flags = UPF_BOOT_AUTOCONF, | ||
204 | .type = PORT_SCIF, | ||
205 | .irqs = { 196, 196, 196, 196 } | ||
206 | }, { | ||
207 | .mapbase = 0xfffea800, | ||
208 | .flags = UPF_BOOT_AUTOCONF, | ||
209 | .type = PORT_SCIF, | ||
210 | .irqs = { 200, 200, 200, 200 } | ||
211 | }, { | ||
212 | .mapbase = 0xfffeb000, | ||
213 | .flags = UPF_BOOT_AUTOCONF, | ||
214 | .type = PORT_SCIF, | ||
215 | .irqs = { 204, 204, 204, 204 } | ||
216 | }, { | ||
217 | .mapbase = 0xfffeb800, | ||
218 | .flags = UPF_BOOT_AUTOCONF, | ||
219 | .type = PORT_SCIF, | ||
220 | .irqs = { 208, 208, 208, 208 } | ||
221 | }, { | ||
222 | .flags = 0, | ||
223 | } | ||
224 | }; | ||
225 | |||
226 | static struct platform_device sci_device = { | ||
227 | .name = "sh-sci", | 188 | .name = "sh-sci", |
228 | .id = -1, | 189 | .id = 0, |
190 | .dev = { | ||
191 | .platform_data = &scif0_platform_data, | ||
192 | }, | ||
193 | }; | ||
194 | |||
195 | static struct plat_sci_port scif1_platform_data = { | ||
196 | .mapbase = 0xfffe8800, | ||
197 | .flags = UPF_BOOT_AUTOCONF, | ||
198 | .type = PORT_SCIF, | ||
199 | .irqs = { 184, 184, 184, 184 } | ||
200 | }; | ||
201 | |||
202 | static struct platform_device scif1_device = { | ||
203 | .name = "sh-sci", | ||
204 | .id = 1, | ||
205 | .dev = { | ||
206 | .platform_data = &scif1_platform_data, | ||
207 | }, | ||
208 | }; | ||
209 | |||
210 | static struct plat_sci_port scif2_platform_data = { | ||
211 | .mapbase = 0xfffe9000, | ||
212 | .flags = UPF_BOOT_AUTOCONF, | ||
213 | .type = PORT_SCIF, | ||
214 | .irqs = { 188, 188, 188, 188 } | ||
215 | }; | ||
216 | |||
217 | static struct platform_device scif2_device = { | ||
218 | .name = "sh-sci", | ||
219 | .id = 2, | ||
220 | .dev = { | ||
221 | .platform_data = &scif2_platform_data, | ||
222 | }, | ||
223 | }; | ||
224 | |||
225 | static struct plat_sci_port scif3_platform_data = { | ||
226 | .mapbase = 0xfffe9800, | ||
227 | .flags = UPF_BOOT_AUTOCONF, | ||
228 | .type = PORT_SCIF, | ||
229 | .irqs = { 192, 192, 192, 192 } | ||
230 | }; | ||
231 | |||
232 | static struct platform_device scif3_device = { | ||
233 | .name = "sh-sci", | ||
234 | .id = 3, | ||
235 | .dev = { | ||
236 | .platform_data = &scif3_platform_data, | ||
237 | }, | ||
238 | }; | ||
239 | |||
240 | static struct plat_sci_port scif4_platform_data = { | ||
241 | .mapbase = 0xfffea000, | ||
242 | .flags = UPF_BOOT_AUTOCONF, | ||
243 | .type = PORT_SCIF, | ||
244 | .irqs = { 196, 196, 196, 196 } | ||
245 | }; | ||
246 | |||
247 | static struct platform_device scif4_device = { | ||
248 | .name = "sh-sci", | ||
249 | .id = 4, | ||
250 | .dev = { | ||
251 | .platform_data = &scif4_platform_data, | ||
252 | }, | ||
253 | }; | ||
254 | |||
255 | static struct plat_sci_port scif5_platform_data = { | ||
256 | .mapbase = 0xfffea800, | ||
257 | .flags = UPF_BOOT_AUTOCONF, | ||
258 | .type = PORT_SCIF, | ||
259 | .irqs = { 200, 200, 200, 200 } | ||
260 | }; | ||
261 | |||
262 | static struct platform_device scif5_device = { | ||
263 | .name = "sh-sci", | ||
264 | .id = 5, | ||
265 | .dev = { | ||
266 | .platform_data = &scif5_platform_data, | ||
267 | }, | ||
268 | }; | ||
269 | |||
270 | static struct plat_sci_port scif6_platform_data = { | ||
271 | .mapbase = 0xfffeb000, | ||
272 | .flags = UPF_BOOT_AUTOCONF, | ||
273 | .type = PORT_SCIF, | ||
274 | .irqs = { 204, 204, 204, 204 } | ||
275 | }; | ||
276 | |||
277 | static struct platform_device scif6_device = { | ||
278 | .name = "sh-sci", | ||
279 | .id = 6, | ||
280 | .dev = { | ||
281 | .platform_data = &scif6_platform_data, | ||
282 | }, | ||
283 | }; | ||
284 | |||
285 | static struct plat_sci_port scif7_platform_data = { | ||
286 | .mapbase = 0xfffeb800, | ||
287 | .flags = UPF_BOOT_AUTOCONF, | ||
288 | .type = PORT_SCIF, | ||
289 | .irqs = { 208, 208, 208, 208 } | ||
290 | }; | ||
291 | |||
292 | static struct platform_device scif7_device = { | ||
293 | .name = "sh-sci", | ||
294 | .id = 7, | ||
229 | .dev = { | 295 | .dev = { |
230 | .platform_data = sci_platform_data, | 296 | .platform_data = &scif7_platform_data, |
231 | }, | 297 | }, |
232 | }; | 298 | }; |
233 | 299 | ||
@@ -345,7 +411,14 @@ static struct platform_device mtu2_2_device = { | |||
345 | }; | 411 | }; |
346 | 412 | ||
347 | static struct platform_device *sh7201_devices[] __initdata = { | 413 | static struct platform_device *sh7201_devices[] __initdata = { |
348 | &sci_device, | 414 | &scif0_device, |
415 | &scif1_device, | ||
416 | &scif2_device, | ||
417 | &scif3_device, | ||
418 | &scif4_device, | ||
419 | &scif5_device, | ||
420 | &scif6_device, | ||
421 | &scif7_device, | ||
349 | &rtc_device, | 422 | &rtc_device, |
350 | &mtu2_0_device, | 423 | &mtu2_0_device, |
351 | &mtu2_1_device, | 424 | &mtu2_1_device, |
@@ -365,6 +438,14 @@ void __init plat_irq_setup(void) | |||
365 | } | 438 | } |
366 | 439 | ||
367 | static struct platform_device *sh7201_early_devices[] __initdata = { | 440 | static struct platform_device *sh7201_early_devices[] __initdata = { |
441 | &scif0_device, | ||
442 | &scif1_device, | ||
443 | &scif2_device, | ||
444 | &scif3_device, | ||
445 | &scif4_device, | ||
446 | &scif5_device, | ||
447 | &scif6_device, | ||
448 | &scif7_device, | ||
368 | &mtu2_0_device, | 449 | &mtu2_0_device, |
369 | &mtu2_1_device, | 450 | &mtu2_1_device, |
370 | &mtu2_2_device, | 451 | &mtu2_2_device, |
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c index d3fd536c9a84..3136966cc9b3 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c | |||
@@ -173,37 +173,63 @@ static struct intc_mask_reg mask_registers[] __initdata = { | |||
173 | static DECLARE_INTC_DESC(intc_desc, "sh7203", vectors, groups, | 173 | static DECLARE_INTC_DESC(intc_desc, "sh7203", vectors, groups, |
174 | mask_registers, prio_registers, NULL); | 174 | mask_registers, prio_registers, NULL); |
175 | 175 | ||
176 | static struct plat_sci_port sci_platform_data[] = { | 176 | static struct plat_sci_port scif0_platform_data = { |
177 | { | 177 | .mapbase = 0xfffe8000, |
178 | .mapbase = 0xfffe8000, | 178 | .flags = UPF_BOOT_AUTOCONF, |
179 | .flags = UPF_BOOT_AUTOCONF, | 179 | .type = PORT_SCIF, |
180 | .type = PORT_SCIF, | 180 | .irqs = { 192, 192, 192, 192 }, |
181 | .irqs = { 192, 192, 192, 192 }, | ||
182 | }, { | ||
183 | .mapbase = 0xfffe8800, | ||
184 | .flags = UPF_BOOT_AUTOCONF, | ||
185 | .type = PORT_SCIF, | ||
186 | .irqs = { 196, 196, 196, 196 }, | ||
187 | }, { | ||
188 | .mapbase = 0xfffe9000, | ||
189 | .flags = UPF_BOOT_AUTOCONF, | ||
190 | .type = PORT_SCIF, | ||
191 | .irqs = { 200, 200, 200, 200 }, | ||
192 | }, { | ||
193 | .mapbase = 0xfffe9800, | ||
194 | .flags = UPF_BOOT_AUTOCONF, | ||
195 | .type = PORT_SCIF, | ||
196 | .irqs = { 204, 204, 204, 204 }, | ||
197 | }, { | ||
198 | .flags = 0, | ||
199 | } | ||
200 | }; | 181 | }; |
201 | 182 | ||
202 | static struct platform_device sci_device = { | 183 | static struct platform_device scif0_device = { |
203 | .name = "sh-sci", | 184 | .name = "sh-sci", |
204 | .id = -1, | 185 | .id = 0, |
186 | .dev = { | ||
187 | .platform_data = &scif0_platform_data, | ||
188 | }, | ||
189 | }; | ||
190 | |||
191 | static struct plat_sci_port scif1_platform_data = { | ||
192 | .mapbase = 0xfffe8800, | ||
193 | .flags = UPF_BOOT_AUTOCONF, | ||
194 | .type = PORT_SCIF, | ||
195 | .irqs = { 196, 196, 196, 196 }, | ||
196 | }; | ||
197 | |||
198 | static struct platform_device scif1_device = { | ||
199 | .name = "sh-sci", | ||
200 | .id = 1, | ||
201 | .dev = { | ||
202 | .platform_data = &scif1_platform_data, | ||
203 | }, | ||
204 | }; | ||
205 | |||
206 | static struct plat_sci_port scif2_platform_data = { | ||
207 | .mapbase = 0xfffe9000, | ||
208 | .flags = UPF_BOOT_AUTOCONF, | ||
209 | .type = PORT_SCIF, | ||
210 | .irqs = { 200, 200, 200, 200 }, | ||
211 | }; | ||
212 | |||
213 | static struct platform_device scif2_device = { | ||
214 | .name = "sh-sci", | ||
215 | .id = 2, | ||
216 | .dev = { | ||
217 | .platform_data = &scif2_platform_data, | ||
218 | }, | ||
219 | }; | ||
220 | |||
221 | static struct plat_sci_port scif3_platform_data = { | ||
222 | .mapbase = 0xfffe9800, | ||
223 | .flags = UPF_BOOT_AUTOCONF, | ||
224 | .type = PORT_SCIF, | ||
225 | .irqs = { 204, 204, 204, 204 }, | ||
226 | }; | ||
227 | |||
228 | static struct platform_device scif3_device = { | ||
229 | .name = "sh-sci", | ||
230 | .id = 3, | ||
205 | .dev = { | 231 | .dev = { |
206 | .platform_data = sci_platform_data, | 232 | .platform_data = &scif3_platform_data, |
207 | }, | 233 | }, |
208 | }; | 234 | }; |
209 | 235 | ||
@@ -354,7 +380,10 @@ static struct platform_device rtc_device = { | |||
354 | }; | 380 | }; |
355 | 381 | ||
356 | static struct platform_device *sh7203_devices[] __initdata = { | 382 | static struct platform_device *sh7203_devices[] __initdata = { |
357 | &sci_device, | 383 | &scif0_device, |
384 | &scif1_device, | ||
385 | &scif2_device, | ||
386 | &scif3_device, | ||
358 | &cmt0_device, | 387 | &cmt0_device, |
359 | &cmt1_device, | 388 | &cmt1_device, |
360 | &mtu2_0_device, | 389 | &mtu2_0_device, |
@@ -375,6 +404,10 @@ void __init plat_irq_setup(void) | |||
375 | } | 404 | } |
376 | 405 | ||
377 | static struct platform_device *sh7203_early_devices[] __initdata = { | 406 | static struct platform_device *sh7203_early_devices[] __initdata = { |
407 | &scif0_device, | ||
408 | &scif1_device, | ||
409 | &scif2_device, | ||
410 | &scif3_device, | ||
378 | &cmt0_device, | 411 | &cmt0_device, |
379 | &cmt1_device, | 412 | &cmt1_device, |
380 | &mtu2_0_device, | 413 | &mtu2_0_device, |
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c index a9ccc5e8d9e9..064873585a8b 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c | |||
@@ -133,37 +133,63 @@ static struct intc_mask_reg mask_registers[] __initdata = { | |||
133 | static DECLARE_INTC_DESC(intc_desc, "sh7206", vectors, groups, | 133 | static DECLARE_INTC_DESC(intc_desc, "sh7206", vectors, groups, |
134 | mask_registers, prio_registers, NULL); | 134 | mask_registers, prio_registers, NULL); |
135 | 135 | ||
136 | static struct plat_sci_port sci_platform_data[] = { | 136 | static struct plat_sci_port scif0_platform_data = { |
137 | { | 137 | .mapbase = 0xfffe8000, |
138 | .mapbase = 0xfffe8000, | 138 | .flags = UPF_BOOT_AUTOCONF, |
139 | .flags = UPF_BOOT_AUTOCONF, | 139 | .type = PORT_SCIF, |
140 | .type = PORT_SCIF, | 140 | .irqs = { 240, 240, 240, 240 }, |
141 | .irqs = { 240, 240, 240, 240 }, | ||
142 | }, { | ||
143 | .mapbase = 0xfffe8800, | ||
144 | .flags = UPF_BOOT_AUTOCONF, | ||
145 | .type = PORT_SCIF, | ||
146 | .irqs = { 244, 244, 244, 244 }, | ||
147 | }, { | ||
148 | .mapbase = 0xfffe9000, | ||
149 | .flags = UPF_BOOT_AUTOCONF, | ||
150 | .type = PORT_SCIF, | ||
151 | .irqs = { 248, 248, 248, 248 }, | ||
152 | }, { | ||
153 | .mapbase = 0xfffe9800, | ||
154 | .flags = UPF_BOOT_AUTOCONF, | ||
155 | .type = PORT_SCIF, | ||
156 | .irqs = { 252, 252, 252, 252 }, | ||
157 | }, { | ||
158 | .flags = 0, | ||
159 | } | ||
160 | }; | 141 | }; |
161 | 142 | ||
162 | static struct platform_device sci_device = { | 143 | static struct platform_device scif0_device = { |
163 | .name = "sh-sci", | 144 | .name = "sh-sci", |
164 | .id = -1, | 145 | .id = 0, |
146 | .dev = { | ||
147 | .platform_data = &scif0_platform_data, | ||
148 | }, | ||
149 | }; | ||
150 | |||
151 | static struct plat_sci_port scif1_platform_data = { | ||
152 | .mapbase = 0xfffe8800, | ||
153 | .flags = UPF_BOOT_AUTOCONF, | ||
154 | .type = PORT_SCIF, | ||
155 | .irqs = { 244, 244, 244, 244 }, | ||
156 | }; | ||
157 | |||
158 | static struct platform_device scif1_device = { | ||
159 | .name = "sh-sci", | ||
160 | .id = 1, | ||
161 | .dev = { | ||
162 | .platform_data = &scif1_platform_data, | ||
163 | }, | ||
164 | }; | ||
165 | |||
166 | static struct plat_sci_port scif2_platform_data = { | ||
167 | .mapbase = 0xfffe9000, | ||
168 | .flags = UPF_BOOT_AUTOCONF, | ||
169 | .type = PORT_SCIF, | ||
170 | .irqs = { 248, 248, 248, 248 }, | ||
171 | }; | ||
172 | |||
173 | static struct platform_device scif2_device = { | ||
174 | .name = "sh-sci", | ||
175 | .id = 2, | ||
176 | .dev = { | ||
177 | .platform_data = &scif2_platform_data, | ||
178 | }, | ||
179 | }; | ||
180 | |||
181 | static struct plat_sci_port scif3_platform_data = { | ||
182 | .mapbase = 0xfffe9800, | ||
183 | .flags = UPF_BOOT_AUTOCONF, | ||
184 | .type = PORT_SCIF, | ||
185 | .irqs = { 252, 252, 252, 252 }, | ||
186 | }; | ||
187 | |||
188 | static struct platform_device scif3_device = { | ||
189 | .name = "sh-sci", | ||
190 | .id = 3, | ||
165 | .dev = { | 191 | .dev = { |
166 | .platform_data = sci_platform_data, | 192 | .platform_data = &scif3_platform_data, |
167 | }, | 193 | }, |
168 | }; | 194 | }; |
169 | 195 | ||
@@ -325,7 +351,10 @@ static struct platform_device mtu2_2_device = { | |||
325 | }; | 351 | }; |
326 | 352 | ||
327 | static struct platform_device *sh7206_devices[] __initdata = { | 353 | static struct platform_device *sh7206_devices[] __initdata = { |
328 | &sci_device, | 354 | &scif0_device, |
355 | &scif1_device, | ||
356 | &scif2_device, | ||
357 | &scif3_device, | ||
329 | &cmt0_device, | 358 | &cmt0_device, |
330 | &cmt1_device, | 359 | &cmt1_device, |
331 | &mtu2_0_device, | 360 | &mtu2_0_device, |
@@ -346,6 +375,10 @@ void __init plat_irq_setup(void) | |||
346 | } | 375 | } |
347 | 376 | ||
348 | static struct platform_device *sh7206_early_devices[] __initdata = { | 377 | static struct platform_device *sh7206_early_devices[] __initdata = { |
378 | &scif0_device, | ||
379 | &scif1_device, | ||
380 | &scif2_device, | ||
381 | &scif3_device, | ||
349 | &cmt0_device, | 382 | &cmt0_device, |
350 | &cmt1_device, | 383 | &cmt1_device, |
351 | &mtu2_0_device, | 384 | &mtu2_0_device, |
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh3.c b/arch/sh/kernel/cpu/sh3/clock-sh3.c index 27b8738f0b09..b78384afac09 100644 --- a/arch/sh/kernel/cpu/sh3/clock-sh3.c +++ b/arch/sh/kernel/cpu/sh3/clock-sh3.c | |||
@@ -28,7 +28,7 @@ static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; | |||
28 | 28 | ||
29 | static void master_clk_init(struct clk *clk) | 29 | static void master_clk_init(struct clk *clk) |
30 | { | 30 | { |
31 | int frqcr = ctrl_inw(FRQCR); | 31 | int frqcr = __raw_readw(FRQCR); |
32 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); | 32 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); |
33 | 33 | ||
34 | clk->rate *= pfc_divisors[idx]; | 34 | clk->rate *= pfc_divisors[idx]; |
@@ -40,7 +40,7 @@ static struct clk_ops sh3_master_clk_ops = { | |||
40 | 40 | ||
41 | static unsigned long module_clk_recalc(struct clk *clk) | 41 | static unsigned long module_clk_recalc(struct clk *clk) |
42 | { | 42 | { |
43 | int frqcr = ctrl_inw(FRQCR); | 43 | int frqcr = __raw_readw(FRQCR); |
44 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); | 44 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); |
45 | 45 | ||
46 | return clk->parent->rate / pfc_divisors[idx]; | 46 | return clk->parent->rate / pfc_divisors[idx]; |
@@ -52,7 +52,7 @@ static struct clk_ops sh3_module_clk_ops = { | |||
52 | 52 | ||
53 | static unsigned long bus_clk_recalc(struct clk *clk) | 53 | static unsigned long bus_clk_recalc(struct clk *clk) |
54 | { | 54 | { |
55 | int frqcr = ctrl_inw(FRQCR); | 55 | int frqcr = __raw_readw(FRQCR); |
56 | int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4); | 56 | int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4); |
57 | 57 | ||
58 | return clk->parent->rate / stc_multipliers[idx]; | 58 | return clk->parent->rate / stc_multipliers[idx]; |
@@ -64,7 +64,7 @@ static struct clk_ops sh3_bus_clk_ops = { | |||
64 | 64 | ||
65 | static unsigned long cpu_clk_recalc(struct clk *clk) | 65 | static unsigned long cpu_clk_recalc(struct clk *clk) |
66 | { | 66 | { |
67 | int frqcr = ctrl_inw(FRQCR); | 67 | int frqcr = __raw_readw(FRQCR); |
68 | int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); | 68 | int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); |
69 | 69 | ||
70 | return clk->parent->rate / ifc_divisors[idx]; | 70 | return clk->parent->rate / ifc_divisors[idx]; |
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7705.c b/arch/sh/kernel/cpu/sh3/clock-sh7705.c index 0ca8f2c3646c..0ecea1451c6f 100644 --- a/arch/sh/kernel/cpu/sh3/clock-sh7705.c +++ b/arch/sh/kernel/cpu/sh3/clock-sh7705.c | |||
@@ -32,7 +32,7 @@ static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; | |||
32 | 32 | ||
33 | static void master_clk_init(struct clk *clk) | 33 | static void master_clk_init(struct clk *clk) |
34 | { | 34 | { |
35 | clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0003]; | 35 | clk->rate *= pfc_divisors[__raw_readw(FRQCR) & 0x0003]; |
36 | } | 36 | } |
37 | 37 | ||
38 | static struct clk_ops sh7705_master_clk_ops = { | 38 | static struct clk_ops sh7705_master_clk_ops = { |
@@ -41,7 +41,7 @@ static struct clk_ops sh7705_master_clk_ops = { | |||
41 | 41 | ||
42 | static unsigned long module_clk_recalc(struct clk *clk) | 42 | static unsigned long module_clk_recalc(struct clk *clk) |
43 | { | 43 | { |
44 | int idx = ctrl_inw(FRQCR) & 0x0003; | 44 | int idx = __raw_readw(FRQCR) & 0x0003; |
45 | return clk->parent->rate / pfc_divisors[idx]; | 45 | return clk->parent->rate / pfc_divisors[idx]; |
46 | } | 46 | } |
47 | 47 | ||
@@ -51,7 +51,7 @@ static struct clk_ops sh7705_module_clk_ops = { | |||
51 | 51 | ||
52 | static unsigned long bus_clk_recalc(struct clk *clk) | 52 | static unsigned long bus_clk_recalc(struct clk *clk) |
53 | { | 53 | { |
54 | int idx = (ctrl_inw(FRQCR) & 0x0300) >> 8; | 54 | int idx = (__raw_readw(FRQCR) & 0x0300) >> 8; |
55 | return clk->parent->rate / stc_multipliers[idx]; | 55 | return clk->parent->rate / stc_multipliers[idx]; |
56 | } | 56 | } |
57 | 57 | ||
@@ -61,7 +61,7 @@ static struct clk_ops sh7705_bus_clk_ops = { | |||
61 | 61 | ||
62 | static unsigned long cpu_clk_recalc(struct clk *clk) | 62 | static unsigned long cpu_clk_recalc(struct clk *clk) |
63 | { | 63 | { |
64 | int idx = (ctrl_inw(FRQCR) & 0x0030) >> 4; | 64 | int idx = (__raw_readw(FRQCR) & 0x0030) >> 4; |
65 | return clk->parent->rate / ifc_divisors[idx]; | 65 | return clk->parent->rate / ifc_divisors[idx]; |
66 | } | 66 | } |
67 | 67 | ||
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7706.c b/arch/sh/kernel/cpu/sh3/clock-sh7706.c index 4bf7887d310a..6f9ff8b57dd6 100644 --- a/arch/sh/kernel/cpu/sh3/clock-sh7706.c +++ b/arch/sh/kernel/cpu/sh3/clock-sh7706.c | |||
@@ -24,7 +24,7 @@ static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 }; | |||
24 | 24 | ||
25 | static void master_clk_init(struct clk *clk) | 25 | static void master_clk_init(struct clk *clk) |
26 | { | 26 | { |
27 | int frqcr = ctrl_inw(FRQCR); | 27 | int frqcr = __raw_readw(FRQCR); |
28 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); | 28 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); |
29 | 29 | ||
30 | clk->rate *= pfc_divisors[idx]; | 30 | clk->rate *= pfc_divisors[idx]; |
@@ -36,7 +36,7 @@ static struct clk_ops sh7706_master_clk_ops = { | |||
36 | 36 | ||
37 | static unsigned long module_clk_recalc(struct clk *clk) | 37 | static unsigned long module_clk_recalc(struct clk *clk) |
38 | { | 38 | { |
39 | int frqcr = ctrl_inw(FRQCR); | 39 | int frqcr = __raw_readw(FRQCR); |
40 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); | 40 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); |
41 | 41 | ||
42 | return clk->parent->rate / pfc_divisors[idx]; | 42 | return clk->parent->rate / pfc_divisors[idx]; |
@@ -48,7 +48,7 @@ static struct clk_ops sh7706_module_clk_ops = { | |||
48 | 48 | ||
49 | static unsigned long bus_clk_recalc(struct clk *clk) | 49 | static unsigned long bus_clk_recalc(struct clk *clk) |
50 | { | 50 | { |
51 | int frqcr = ctrl_inw(FRQCR); | 51 | int frqcr = __raw_readw(FRQCR); |
52 | int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4); | 52 | int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4); |
53 | 53 | ||
54 | return clk->parent->rate / stc_multipliers[idx]; | 54 | return clk->parent->rate / stc_multipliers[idx]; |
@@ -60,7 +60,7 @@ static struct clk_ops sh7706_bus_clk_ops = { | |||
60 | 60 | ||
61 | static unsigned long cpu_clk_recalc(struct clk *clk) | 61 | static unsigned long cpu_clk_recalc(struct clk *clk) |
62 | { | 62 | { |
63 | int frqcr = ctrl_inw(FRQCR); | 63 | int frqcr = __raw_readw(FRQCR); |
64 | int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); | 64 | int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); |
65 | 65 | ||
66 | return clk->parent->rate / ifc_divisors[idx]; | 66 | return clk->parent->rate / ifc_divisors[idx]; |
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7709.c b/arch/sh/kernel/cpu/sh3/clock-sh7709.c index e8749505bd2a..f302ba09e681 100644 --- a/arch/sh/kernel/cpu/sh3/clock-sh7709.c +++ b/arch/sh/kernel/cpu/sh3/clock-sh7709.c | |||
@@ -24,7 +24,7 @@ static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 }; | |||
24 | 24 | ||
25 | static void master_clk_init(struct clk *clk) | 25 | static void master_clk_init(struct clk *clk) |
26 | { | 26 | { |
27 | int frqcr = ctrl_inw(FRQCR); | 27 | int frqcr = __raw_readw(FRQCR); |
28 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); | 28 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); |
29 | 29 | ||
30 | clk->rate *= pfc_divisors[idx]; | 30 | clk->rate *= pfc_divisors[idx]; |
@@ -36,7 +36,7 @@ static struct clk_ops sh7709_master_clk_ops = { | |||
36 | 36 | ||
37 | static unsigned long module_clk_recalc(struct clk *clk) | 37 | static unsigned long module_clk_recalc(struct clk *clk) |
38 | { | 38 | { |
39 | int frqcr = ctrl_inw(FRQCR); | 39 | int frqcr = __raw_readw(FRQCR); |
40 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); | 40 | int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); |
41 | 41 | ||
42 | return clk->parent->rate / pfc_divisors[idx]; | 42 | return clk->parent->rate / pfc_divisors[idx]; |
@@ -48,7 +48,7 @@ static struct clk_ops sh7709_module_clk_ops = { | |||
48 | 48 | ||
49 | static unsigned long bus_clk_recalc(struct clk *clk) | 49 | static unsigned long bus_clk_recalc(struct clk *clk) |
50 | { | 50 | { |
51 | int frqcr = ctrl_inw(FRQCR); | 51 | int frqcr = __raw_readw(FRQCR); |
52 | int idx = (frqcr & 0x0080) ? | 52 | int idx = (frqcr & 0x0080) ? |
53 | ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4) : 1; | 53 | ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4) : 1; |
54 | 54 | ||
@@ -61,7 +61,7 @@ static struct clk_ops sh7709_bus_clk_ops = { | |||
61 | 61 | ||
62 | static unsigned long cpu_clk_recalc(struct clk *clk) | 62 | static unsigned long cpu_clk_recalc(struct clk *clk) |
63 | { | 63 | { |
64 | int frqcr = ctrl_inw(FRQCR); | 64 | int frqcr = __raw_readw(FRQCR); |
65 | int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); | 65 | int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); |
66 | 66 | ||
67 | return clk->parent->rate / ifc_divisors[idx]; | 67 | return clk->parent->rate / ifc_divisors[idx]; |
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7710.c b/arch/sh/kernel/cpu/sh3/clock-sh7710.c index 030a58ba18a5..29a87d8946a4 100644 --- a/arch/sh/kernel/cpu/sh3/clock-sh7710.c +++ b/arch/sh/kernel/cpu/sh3/clock-sh7710.c | |||
@@ -26,7 +26,7 @@ static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 }; | |||
26 | 26 | ||
27 | static void master_clk_init(struct clk *clk) | 27 | static void master_clk_init(struct clk *clk) |
28 | { | 28 | { |
29 | clk->rate *= md_table[ctrl_inw(FRQCR) & 0x0007]; | 29 | clk->rate *= md_table[__raw_readw(FRQCR) & 0x0007]; |
30 | } | 30 | } |
31 | 31 | ||
32 | static struct clk_ops sh7710_master_clk_ops = { | 32 | static struct clk_ops sh7710_master_clk_ops = { |
@@ -35,7 +35,7 @@ static struct clk_ops sh7710_master_clk_ops = { | |||
35 | 35 | ||
36 | static unsigned long module_clk_recalc(struct clk *clk) | 36 | static unsigned long module_clk_recalc(struct clk *clk) |
37 | { | 37 | { |
38 | int idx = (ctrl_inw(FRQCR) & 0x0007); | 38 | int idx = (__raw_readw(FRQCR) & 0x0007); |
39 | return clk->parent->rate / md_table[idx]; | 39 | return clk->parent->rate / md_table[idx]; |
40 | } | 40 | } |
41 | 41 | ||
@@ -45,7 +45,7 @@ static struct clk_ops sh7710_module_clk_ops = { | |||
45 | 45 | ||
46 | static unsigned long bus_clk_recalc(struct clk *clk) | 46 | static unsigned long bus_clk_recalc(struct clk *clk) |
47 | { | 47 | { |
48 | int idx = (ctrl_inw(FRQCR) & 0x0700) >> 8; | 48 | int idx = (__raw_readw(FRQCR) & 0x0700) >> 8; |
49 | return clk->parent->rate / md_table[idx]; | 49 | return clk->parent->rate / md_table[idx]; |
50 | } | 50 | } |
51 | 51 | ||
@@ -55,7 +55,7 @@ static struct clk_ops sh7710_bus_clk_ops = { | |||
55 | 55 | ||
56 | static unsigned long cpu_clk_recalc(struct clk *clk) | 56 | static unsigned long cpu_clk_recalc(struct clk *clk) |
57 | { | 57 | { |
58 | int idx = (ctrl_inw(FRQCR) & 0x0070) >> 4; | 58 | int idx = (__raw_readw(FRQCR) & 0x0070) >> 4; |
59 | return clk->parent->rate / md_table[idx]; | 59 | return clk->parent->rate / md_table[idx]; |
60 | } | 60 | } |
61 | 61 | ||
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7712.c b/arch/sh/kernel/cpu/sh3/clock-sh7712.c index 6428ee6c77ed..b0d0c5203996 100644 --- a/arch/sh/kernel/cpu/sh3/clock-sh7712.c +++ b/arch/sh/kernel/cpu/sh3/clock-sh7712.c | |||
@@ -23,7 +23,7 @@ static int divisors[] = { 1, 2, 3, 4, 6 }; | |||
23 | 23 | ||
24 | static void master_clk_init(struct clk *clk) | 24 | static void master_clk_init(struct clk *clk) |
25 | { | 25 | { |
26 | int frqcr = ctrl_inw(FRQCR); | 26 | int frqcr = __raw_readw(FRQCR); |
27 | int idx = (frqcr & 0x0300) >> 8; | 27 | int idx = (frqcr & 0x0300) >> 8; |
28 | 28 | ||
29 | clk->rate *= multipliers[idx]; | 29 | clk->rate *= multipliers[idx]; |
@@ -35,7 +35,7 @@ static struct clk_ops sh7712_master_clk_ops = { | |||
35 | 35 | ||
36 | static unsigned long module_clk_recalc(struct clk *clk) | 36 | static unsigned long module_clk_recalc(struct clk *clk) |
37 | { | 37 | { |
38 | int frqcr = ctrl_inw(FRQCR); | 38 | int frqcr = __raw_readw(FRQCR); |
39 | int idx = frqcr & 0x0007; | 39 | int idx = frqcr & 0x0007; |
40 | 40 | ||
41 | return clk->parent->rate / divisors[idx]; | 41 | return clk->parent->rate / divisors[idx]; |
@@ -47,7 +47,7 @@ static struct clk_ops sh7712_module_clk_ops = { | |||
47 | 47 | ||
48 | static unsigned long cpu_clk_recalc(struct clk *clk) | 48 | static unsigned long cpu_clk_recalc(struct clk *clk) |
49 | { | 49 | { |
50 | int frqcr = ctrl_inw(FRQCR); | 50 | int frqcr = __raw_readw(FRQCR); |
51 | int idx = (frqcr & 0x0030) >> 4; | 51 | int idx = (frqcr & 0x0030) >> 4; |
52 | 52 | ||
53 | return clk->parent->rate / divisors[idx]; | 53 | return clk->parent->rate / divisors[idx]; |
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index bb407ef0b91e..f6a389c996cb 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
@@ -132,7 +132,6 @@ ENTRY(tlb_protection_violation_store) | |||
132 | mov #1, r5 | 132 | mov #1, r5 |
133 | 133 | ||
134 | call_handle_tlbmiss: | 134 | call_handle_tlbmiss: |
135 | setup_frame_reg | ||
136 | mov.l 1f, r0 | 135 | mov.l 1f, r0 |
137 | mov r5, r8 | 136 | mov r5, r8 |
138 | mov.l @r0, r6 | 137 | mov.l @r0, r6 |
@@ -297,41 +296,8 @@ ENTRY(vbr_base) | |||
297 | ! | 296 | ! |
298 | .balign 256,0,256 | 297 | .balign 256,0,256 |
299 | general_exception: | 298 | general_exception: |
300 | #ifndef CONFIG_CPU_SUBTYPE_SHX3 | ||
301 | bra handle_exception | 299 | bra handle_exception |
302 | sts pr, k3 ! save original pr value in k3 | 300 | sts pr, k3 ! save original pr value in k3 |
303 | #else | ||
304 | mov.l 1f, k4 | ||
305 | mov.l @k4, k4 | ||
306 | |||
307 | ! Is EXPEVT larger than 0x800? | ||
308 | mov #0x8, k0 | ||
309 | shll8 k0 | ||
310 | cmp/hs k0, k4 | ||
311 | bf 0f | ||
312 | |||
313 | ! then add 0x580 (k2 is 0xd80 or 0xda0) | ||
314 | mov #0x58, k0 | ||
315 | shll2 k0 | ||
316 | shll2 k0 | ||
317 | add k0, k4 | ||
318 | 0: | ||
319 | ! Setup stack and save DSP context (k0 contains original r15 on return) | ||
320 | bsr prepare_stack | ||
321 | nop | ||
322 | |||
323 | ! Save registers / Switch to bank 0 | ||
324 | mov k4, k2 ! keep vector in k2 | ||
325 | mov.l 1f, k4 ! SR bits to clear in k4 | ||
326 | bsr save_regs ! needs original pr value in k3 | ||
327 | nop | ||
328 | |||
329 | bra handle_exception_special | ||
330 | nop | ||
331 | |||
332 | .align 2 | ||
333 | 1: .long EXPEVT | ||
334 | #endif | ||
335 | 301 | ||
336 | ! prepare_stack() | 302 | ! prepare_stack() |
337 | ! - roll back gRB | 303 | ! - roll back gRB |
@@ -398,6 +364,8 @@ handle_exception: | |||
398 | mov.l @k2, k2 ! read out vector and keep in k2 | 364 | mov.l @k2, k2 ! read out vector and keep in k2 |
399 | 365 | ||
400 | handle_exception_special: | 366 | handle_exception_special: |
367 | setup_frame_reg | ||
368 | |||
401 | ! Setup return address and jump to exception handler | 369 | ! Setup return address and jump to exception handler |
402 | mov.l 7f, r9 ! fetch return address | 370 | mov.l 7f, r9 ! fetch return address |
403 | stc r2_bank, r0 ! k2 (vector) | 371 | stc r2_bank, r0 ! k2 (vector) |
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S index 46610c35c232..99b4d020179a 100644 --- a/arch/sh/kernel/cpu/sh3/ex.S +++ b/arch/sh/kernel/cpu/sh3/ex.S | |||
@@ -49,7 +49,7 @@ ENTRY(exception_handling_table) | |||
49 | .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ | 49 | .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ |
50 | .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ | 50 | .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ |
51 | .long nmi_trap_handler /* 1C0 */ ! Allow trap to debugger | 51 | .long nmi_trap_handler /* 1C0 */ ! Allow trap to debugger |
52 | .long break_point_trap /* 1E0 */ | 52 | .long breakpoint_trap_handler /* 1E0 */ |
53 | 53 | ||
54 | /* | 54 | /* |
55 | * Pad the remainder of the table out, exceptions residing in far | 55 | * Pad the remainder of the table out, exceptions residing in far |
diff --git a/arch/sh/kernel/cpu/sh3/probe.c b/arch/sh/kernel/cpu/sh3/probe.c index f9c7df64eb01..295ec4c99e98 100644 --- a/arch/sh/kernel/cpu/sh3/probe.c +++ b/arch/sh/kernel/cpu/sh3/probe.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <asm/cache.h> | 16 | #include <asm/cache.h> |
17 | #include <asm/io.h> | 17 | #include <asm/io.h> |
18 | 18 | ||
19 | int __uses_jump_to_uncached detect_cpu_and_cache_system(void) | 19 | int detect_cpu_and_cache_system(void) |
20 | { | 20 | { |
21 | unsigned long addr0, addr1, data0, data1, data2, data3; | 21 | unsigned long addr0, addr1, data0, data1, data2, data3; |
22 | 22 | ||
@@ -30,23 +30,23 @@ int __uses_jump_to_uncached detect_cpu_and_cache_system(void) | |||
30 | addr1 = CACHE_OC_ADDRESS_ARRAY + (1 << 12); | 30 | addr1 = CACHE_OC_ADDRESS_ARRAY + (1 << 12); |
31 | 31 | ||
32 | /* First, write back & invalidate */ | 32 | /* First, write back & invalidate */ |
33 | data0 = ctrl_inl(addr0); | 33 | data0 = __raw_readl(addr0); |
34 | ctrl_outl(data0&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr0); | 34 | __raw_writel(data0&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr0); |
35 | data1 = ctrl_inl(addr1); | 35 | data1 = __raw_readl(addr1); |
36 | ctrl_outl(data1&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr1); | 36 | __raw_writel(data1&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr1); |
37 | 37 | ||
38 | /* Next, check if there's shadow or not */ | 38 | /* Next, check if there's shadow or not */ |
39 | data0 = ctrl_inl(addr0); | 39 | data0 = __raw_readl(addr0); |
40 | data0 ^= SH_CACHE_VALID; | 40 | data0 ^= SH_CACHE_VALID; |
41 | ctrl_outl(data0, addr0); | 41 | __raw_writel(data0, addr0); |
42 | data1 = ctrl_inl(addr1); | 42 | data1 = __raw_readl(addr1); |
43 | data2 = data1 ^ SH_CACHE_VALID; | 43 | data2 = data1 ^ SH_CACHE_VALID; |
44 | ctrl_outl(data2, addr1); | 44 | __raw_writel(data2, addr1); |
45 | data3 = ctrl_inl(addr0); | 45 | data3 = __raw_readl(addr0); |
46 | 46 | ||
47 | /* Lastly, invaliate them. */ | 47 | /* Lastly, invaliate them. */ |
48 | ctrl_outl(data0&~SH_CACHE_VALID, addr0); | 48 | __raw_writel(data0&~SH_CACHE_VALID, addr0); |
49 | ctrl_outl(data2&~SH_CACHE_VALID, addr1); | 49 | __raw_writel(data2&~SH_CACHE_VALID, addr1); |
50 | 50 | ||
51 | back_to_cached(); | 51 | back_to_cached(); |
52 | 52 | ||
@@ -94,9 +94,9 @@ int __uses_jump_to_uncached detect_cpu_and_cache_system(void) | |||
94 | boot_cpu_data.dcache.way_incr = (1 << 13); | 94 | boot_cpu_data.dcache.way_incr = (1 << 13); |
95 | boot_cpu_data.dcache.entry_mask = 0x1ff0; | 95 | boot_cpu_data.dcache.entry_mask = 0x1ff0; |
96 | boot_cpu_data.dcache.sets = 512; | 96 | boot_cpu_data.dcache.sets = 512; |
97 | ctrl_outl(CCR_CACHE_32KB, CCR3_REG); | 97 | __raw_writel(CCR_CACHE_32KB, CCR3_REG); |
98 | #else | 98 | #else |
99 | ctrl_outl(CCR_CACHE_16KB, CCR3_REG); | 99 | __raw_writel(CCR_CACHE_16KB, CCR3_REG); |
100 | #endif | 100 | #endif |
101 | #endif | 101 | #endif |
102 | } | 102 | } |
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh3.c b/arch/sh/kernel/cpu/sh3/setup-sh3.c index c98846857855..53be70b98116 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh3.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh3.c | |||
@@ -58,7 +58,7 @@ static DECLARE_INTC_DESC_ACK(intc_desc_irq45, "sh3-irq45", | |||
58 | void __init plat_irq_setup_pins(int mode) | 58 | void __init plat_irq_setup_pins(int mode) |
59 | { | 59 | { |
60 | if (mode == IRQ_MODE_IRQ) { | 60 | if (mode == IRQ_MODE_IRQ) { |
61 | ctrl_outw(ctrl_inw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1); | 61 | __raw_writew(__raw_readw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1); |
62 | register_intc_controller(&intc_desc_irq0123); | 62 | register_intc_controller(&intc_desc_irq0123); |
63 | return; | 63 | return; |
64 | } | 64 | } |
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c index c23105983878..7b892d60e3a0 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c | |||
@@ -67,27 +67,33 @@ static struct intc_prio_reg prio_registers[] __initdata = { | |||
67 | static DECLARE_INTC_DESC(intc_desc, "sh7705", vectors, NULL, | 67 | static DECLARE_INTC_DESC(intc_desc, "sh7705", vectors, NULL, |
68 | NULL, prio_registers, NULL); | 68 | NULL, prio_registers, NULL); |
69 | 69 | ||
70 | static struct plat_sci_port sci_platform_data[] = { | 70 | static struct plat_sci_port scif0_platform_data = { |
71 | { | 71 | .mapbase = 0xa4410000, |
72 | .mapbase = 0xa4410000, | 72 | .flags = UPF_BOOT_AUTOCONF, |
73 | .flags = UPF_BOOT_AUTOCONF, | 73 | .type = PORT_SCIF, |
74 | .type = PORT_SCIF, | 74 | .irqs = { 56, 56, 56 }, |
75 | .irqs = { 56, 56, 56 }, | 75 | }; |
76 | }, { | 76 | |
77 | .mapbase = 0xa4400000, | 77 | static struct platform_device scif0_device = { |
78 | .flags = UPF_BOOT_AUTOCONF, | ||
79 | .type = PORT_SCIF, | ||
80 | .irqs = { 52, 52, 52 }, | ||
81 | }, { | ||
82 | .flags = 0, | ||
83 | } | ||
84 | }; | ||
85 | |||
86 | static struct platform_device sci_device = { | ||
87 | .name = "sh-sci", | 78 | .name = "sh-sci", |
88 | .id = -1, | 79 | .id = 0, |
80 | .dev = { | ||
81 | .platform_data = &scif0_platform_data, | ||
82 | }, | ||
83 | }; | ||
84 | |||
85 | static struct plat_sci_port scif1_platform_data = { | ||
86 | .mapbase = 0xa4400000, | ||
87 | .flags = UPF_BOOT_AUTOCONF, | ||
88 | .type = PORT_SCIF, | ||
89 | .irqs = { 52, 52, 52 }, | ||
90 | }; | ||
91 | |||
92 | static struct platform_device scif1_device = { | ||
93 | .name = "sh-sci", | ||
94 | .id = 1, | ||
89 | .dev = { | 95 | .dev = { |
90 | .platform_data = sci_platform_data, | 96 | .platform_data = &scif1_platform_data, |
91 | }, | 97 | }, |
92 | }; | 98 | }; |
93 | 99 | ||
@@ -210,10 +216,11 @@ static struct platform_device tmu2_device = { | |||
210 | }; | 216 | }; |
211 | 217 | ||
212 | static struct platform_device *sh7705_devices[] __initdata = { | 218 | static struct platform_device *sh7705_devices[] __initdata = { |
219 | &scif0_device, | ||
220 | &scif1_device, | ||
213 | &tmu0_device, | 221 | &tmu0_device, |
214 | &tmu1_device, | 222 | &tmu1_device, |
215 | &tmu2_device, | 223 | &tmu2_device, |
216 | &sci_device, | ||
217 | &rtc_device, | 224 | &rtc_device, |
218 | }; | 225 | }; |
219 | 226 | ||
@@ -225,6 +232,8 @@ static int __init sh7705_devices_setup(void) | |||
225 | arch_initcall(sh7705_devices_setup); | 232 | arch_initcall(sh7705_devices_setup); |
226 | 233 | ||
227 | static struct platform_device *sh7705_early_devices[] __initdata = { | 234 | static struct platform_device *sh7705_early_devices[] __initdata = { |
235 | &scif0_device, | ||
236 | &scif1_device, | ||
228 | &tmu0_device, | 237 | &tmu0_device, |
229 | &tmu1_device, | 238 | &tmu1_device, |
230 | &tmu2_device, | 239 | &tmu2_device, |
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c index 347ab35d0697..bc0c4f68c7c7 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c | |||
@@ -106,44 +106,55 @@ static struct platform_device rtc_device = { | |||
106 | .resource = rtc_resources, | 106 | .resource = rtc_resources, |
107 | }; | 107 | }; |
108 | 108 | ||
109 | static struct plat_sci_port sci_platform_data[] = { | 109 | static struct plat_sci_port scif0_platform_data = { |
110 | { | 110 | .mapbase = 0xfffffe80, |
111 | .mapbase = 0xfffffe80, | 111 | .flags = UPF_BOOT_AUTOCONF, |
112 | .flags = UPF_BOOT_AUTOCONF, | 112 | .type = PORT_SCI, |
113 | .type = PORT_SCI, | 113 | .irqs = { 23, 23, 23, 0 }, |
114 | .irqs = { 23, 23, 23, 0 }, | 114 | }; |
115 | |||
116 | static struct platform_device scif0_device = { | ||
117 | .name = "sh-sci", | ||
118 | .id = 0, | ||
119 | .dev = { | ||
120 | .platform_data = &scif0_platform_data, | ||
115 | }, | 121 | }, |
122 | }; | ||
116 | #if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ | 123 | #if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ |
117 | defined(CONFIG_CPU_SUBTYPE_SH7707) || \ | 124 | defined(CONFIG_CPU_SUBTYPE_SH7707) || \ |
118 | defined(CONFIG_CPU_SUBTYPE_SH7709) | 125 | defined(CONFIG_CPU_SUBTYPE_SH7709) |
119 | { | 126 | static struct plat_sci_port scif1_platform_data = { |
120 | .mapbase = 0xa4000150, | 127 | .mapbase = 0xa4000150, |
121 | .flags = UPF_BOOT_AUTOCONF, | 128 | .flags = UPF_BOOT_AUTOCONF, |
122 | .type = PORT_SCIF, | 129 | .type = PORT_SCIF, |
123 | .irqs = { 56, 56, 56, 56 }, | 130 | .irqs = { 56, 56, 56, 56 }, |
131 | }; | ||
132 | |||
133 | static struct platform_device scif1_device = { | ||
134 | .name = "sh-sci", | ||
135 | .id = 1, | ||
136 | .dev = { | ||
137 | .platform_data = &scif1_platform_data, | ||
124 | }, | 138 | }, |
139 | }; | ||
125 | #endif | 140 | #endif |
126 | #if defined(CONFIG_CPU_SUBTYPE_SH7707) || \ | 141 | #if defined(CONFIG_CPU_SUBTYPE_SH7707) || \ |
127 | defined(CONFIG_CPU_SUBTYPE_SH7709) | 142 | defined(CONFIG_CPU_SUBTYPE_SH7709) |
128 | { | 143 | static struct plat_sci_port scif2_platform_data = { |
129 | .mapbase = 0xa4000140, | 144 | .mapbase = 0xa4000140, |
130 | .flags = UPF_BOOT_AUTOCONF, | 145 | .flags = UPF_BOOT_AUTOCONF, |
131 | .type = PORT_IRDA, | 146 | .type = PORT_IRDA, |
132 | .irqs = { 52, 52, 52, 52 }, | 147 | .irqs = { 52, 52, 52, 52 }, |
133 | }, | ||
134 | #endif | ||
135 | { | ||
136 | .flags = 0, | ||
137 | } | ||
138 | }; | 148 | }; |
139 | 149 | ||
140 | static struct platform_device sci_device = { | 150 | static struct platform_device scif2_device = { |
141 | .name = "sh-sci", | 151 | .name = "sh-sci", |
142 | .id = -1, | 152 | .id = 2, |
143 | .dev = { | 153 | .dev = { |
144 | .platform_data = sci_platform_data, | 154 | .platform_data = &scif2_platform_data, |
145 | }, | 155 | }, |
146 | }; | 156 | }; |
157 | #endif | ||
147 | 158 | ||
148 | static struct sh_timer_config tmu0_platform_data = { | 159 | static struct sh_timer_config tmu0_platform_data = { |
149 | .name = "TMU0", | 160 | .name = "TMU0", |
@@ -238,10 +249,19 @@ static struct platform_device tmu2_device = { | |||
238 | }; | 249 | }; |
239 | 250 | ||
240 | static struct platform_device *sh770x_devices[] __initdata = { | 251 | static struct platform_device *sh770x_devices[] __initdata = { |
252 | &scif0_device, | ||
253 | #if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ | ||
254 | defined(CONFIG_CPU_SUBTYPE_SH7707) || \ | ||
255 | defined(CONFIG_CPU_SUBTYPE_SH7709) | ||
256 | &scif1_device, | ||
257 | #endif | ||
258 | #if defined(CONFIG_CPU_SUBTYPE_SH7707) || \ | ||
259 | defined(CONFIG_CPU_SUBTYPE_SH7709) | ||
260 | &scif2_device, | ||
261 | #endif | ||
241 | &tmu0_device, | 262 | &tmu0_device, |
242 | &tmu1_device, | 263 | &tmu1_device, |
243 | &tmu2_device, | 264 | &tmu2_device, |
244 | &sci_device, | ||
245 | &rtc_device, | 265 | &rtc_device, |
246 | }; | 266 | }; |
247 | 267 | ||
@@ -253,6 +273,16 @@ static int __init sh770x_devices_setup(void) | |||
253 | arch_initcall(sh770x_devices_setup); | 273 | arch_initcall(sh770x_devices_setup); |
254 | 274 | ||
255 | static struct platform_device *sh770x_early_devices[] __initdata = { | 275 | static struct platform_device *sh770x_early_devices[] __initdata = { |
276 | &scif0_device, | ||
277 | #if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ | ||
278 | defined(CONFIG_CPU_SUBTYPE_SH7707) || \ | ||
279 | defined(CONFIG_CPU_SUBTYPE_SH7709) | ||
280 | &scif1_device, | ||
281 | #endif | ||
282 | #if defined(CONFIG_CPU_SUBTYPE_SH7707) || \ | ||
283 | defined(CONFIG_CPU_SUBTYPE_SH7709) | ||
284 | &scif2_device, | ||
285 | #endif | ||
256 | &tmu0_device, | 286 | &tmu0_device, |
257 | &tmu1_device, | 287 | &tmu1_device, |
258 | &tmu2_device, | 288 | &tmu2_device, |
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c index 717e90ae1097..0845a3ad006d 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c | |||
@@ -96,28 +96,33 @@ static struct platform_device rtc_device = { | |||
96 | }, | 96 | }, |
97 | }; | 97 | }; |
98 | 98 | ||
99 | static struct plat_sci_port sci_platform_data[] = { | 99 | static struct plat_sci_port scif0_platform_data = { |
100 | { | 100 | .mapbase = 0xa4400000, |
101 | .mapbase = 0xa4400000, | 101 | .flags = UPF_BOOT_AUTOCONF, |
102 | .flags = UPF_BOOT_AUTOCONF, | 102 | .type = PORT_SCIF, |
103 | .type = PORT_SCIF, | 103 | .irqs = { 52, 52, 52, 52 }, |
104 | .irqs = { 52, 52, 52, 52 }, | 104 | }; |
105 | }, { | 105 | |
106 | .mapbase = 0xa4410000, | 106 | static struct platform_device scif0_device = { |
107 | .flags = UPF_BOOT_AUTOCONF, | ||
108 | .type = PORT_SCIF, | ||
109 | .irqs = { 56, 56, 56, 56 }, | ||
110 | }, { | ||
111 | |||
112 | .flags = 0, | ||
113 | } | ||
114 | }; | ||
115 | |||
116 | static struct platform_device sci_device = { | ||
117 | .name = "sh-sci", | 107 | .name = "sh-sci", |
118 | .id = -1, | 108 | .id = 0, |
109 | .dev = { | ||
110 | .platform_data = &scif0_platform_data, | ||
111 | }, | ||
112 | }; | ||
113 | |||
114 | static struct plat_sci_port scif1_platform_data = { | ||
115 | .mapbase = 0xa4410000, | ||
116 | .flags = UPF_BOOT_AUTOCONF, | ||
117 | .type = PORT_SCIF, | ||
118 | .irqs = { 56, 56, 56, 56 }, | ||
119 | }; | ||
120 | |||
121 | static struct platform_device scif1_device = { | ||
122 | .name = "sh-sci", | ||
123 | .id = 1, | ||
119 | .dev = { | 124 | .dev = { |
120 | .platform_data = sci_platform_data, | 125 | .platform_data = &scif1_platform_data, |
121 | }, | 126 | }, |
122 | }; | 127 | }; |
123 | 128 | ||
@@ -214,10 +219,11 @@ static struct platform_device tmu2_device = { | |||
214 | }; | 219 | }; |
215 | 220 | ||
216 | static struct platform_device *sh7710_devices[] __initdata = { | 221 | static struct platform_device *sh7710_devices[] __initdata = { |
222 | &scif0_device, | ||
223 | &scif1_device, | ||
217 | &tmu0_device, | 224 | &tmu0_device, |
218 | &tmu1_device, | 225 | &tmu1_device, |
219 | &tmu2_device, | 226 | &tmu2_device, |
220 | &sci_device, | ||
221 | &rtc_device, | 227 | &rtc_device, |
222 | }; | 228 | }; |
223 | 229 | ||
@@ -229,6 +235,8 @@ static int __init sh7710_devices_setup(void) | |||
229 | arch_initcall(sh7710_devices_setup); | 235 | arch_initcall(sh7710_devices_setup); |
230 | 236 | ||
231 | static struct platform_device *sh7710_early_devices[] __initdata = { | 237 | static struct platform_device *sh7710_early_devices[] __initdata = { |
238 | &scif0_device, | ||
239 | &scif1_device, | ||
232 | &tmu0_device, | 240 | &tmu0_device, |
233 | &tmu1_device, | 241 | &tmu1_device, |
234 | &tmu2_device, | 242 | &tmu2_device, |
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c index 74d8baaf8e96..a718a6231091 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c | |||
@@ -48,28 +48,33 @@ static struct platform_device rtc_device = { | |||
48 | }, | 48 | }, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static struct plat_sci_port sci_platform_data[] = { | 51 | static struct plat_sci_port scif0_platform_data = { |
52 | { | 52 | .mapbase = 0xa4430000, |
53 | .mapbase = 0xa4430000, | 53 | .flags = UPF_BOOT_AUTOCONF, |
54 | .flags = UPF_BOOT_AUTOCONF, | 54 | .type = PORT_SCIF, |
55 | .type = PORT_SCIF, | 55 | .irqs = { 80, 80, 80, 80 }, |
56 | .irqs = { 80, 80, 80, 80 }, | 56 | }; |
57 | }, { | 57 | |
58 | .mapbase = 0xa4438000, | 58 | static struct platform_device scif0_device = { |
59 | .flags = UPF_BOOT_AUTOCONF, | ||
60 | .type = PORT_SCIF, | ||
61 | .irqs = { 81, 81, 81, 81 }, | ||
62 | }, { | ||
63 | |||
64 | .flags = 0, | ||
65 | } | ||
66 | }; | ||
67 | |||
68 | static struct platform_device sci_device = { | ||
69 | .name = "sh-sci", | 59 | .name = "sh-sci", |
70 | .id = -1, | 60 | .id = 0, |
61 | .dev = { | ||
62 | .platform_data = &scif0_platform_data, | ||
63 | }, | ||
64 | }; | ||
65 | |||
66 | static struct plat_sci_port scif1_platform_data = { | ||
67 | .mapbase = 0xa4438000, | ||
68 | .flags = UPF_BOOT_AUTOCONF, | ||
69 | .type = PORT_SCIF, | ||
70 | .irqs = { 81, 81, 81, 81 }, | ||
71 | }; | ||
72 | |||
73 | static struct platform_device scif1_device = { | ||
74 | .name = "sh-sci", | ||
75 | .id = 1, | ||
71 | .dev = { | 76 | .dev = { |
72 | .platform_data = sci_platform_data, | 77 | .platform_data = &scif1_platform_data, |
73 | }, | 78 | }, |
74 | }; | 79 | }; |
75 | 80 | ||
@@ -369,6 +374,8 @@ static struct platform_device tmu2_device = { | |||
369 | }; | 374 | }; |
370 | 375 | ||
371 | static struct platform_device *sh7720_devices[] __initdata = { | 376 | static struct platform_device *sh7720_devices[] __initdata = { |
377 | &scif0_device, | ||
378 | &scif1_device, | ||
372 | &cmt0_device, | 379 | &cmt0_device, |
373 | &cmt1_device, | 380 | &cmt1_device, |
374 | &cmt2_device, | 381 | &cmt2_device, |
@@ -378,7 +385,6 @@ static struct platform_device *sh7720_devices[] __initdata = { | |||
378 | &tmu1_device, | 385 | &tmu1_device, |
379 | &tmu2_device, | 386 | &tmu2_device, |
380 | &rtc_device, | 387 | &rtc_device, |
381 | &sci_device, | ||
382 | &usb_ohci_device, | 388 | &usb_ohci_device, |
383 | &usbf_device, | 389 | &usbf_device, |
384 | }; | 390 | }; |
@@ -391,6 +397,8 @@ static int __init sh7720_devices_setup(void) | |||
391 | arch_initcall(sh7720_devices_setup); | 397 | arch_initcall(sh7720_devices_setup); |
392 | 398 | ||
393 | static struct platform_device *sh7720_early_devices[] __initdata = { | 399 | static struct platform_device *sh7720_early_devices[] __initdata = { |
400 | &scif0_device, | ||
401 | &scif1_device, | ||
394 | &cmt0_device, | 402 | &cmt0_device, |
395 | &cmt1_device, | 403 | &cmt1_device, |
396 | &cmt2_device, | 404 | &cmt2_device, |
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index 203b18347b83..3a1dbc709831 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile | |||
@@ -9,6 +9,11 @@ obj-$(CONFIG_HIBERNATION) += $(addprefix ../sh3/, swsusp.o) | |||
9 | obj-$(CONFIG_SH_FPU) += fpu.o softfloat.o | 9 | obj-$(CONFIG_SH_FPU) += fpu.o softfloat.o |
10 | obj-$(CONFIG_SH_STORE_QUEUES) += sq.o | 10 | obj-$(CONFIG_SH_STORE_QUEUES) += sq.o |
11 | 11 | ||
12 | # Perf events | ||
13 | perf-$(CONFIG_CPU_SUBTYPE_SH7750) := perf_event.o | ||
14 | perf-$(CONFIG_CPU_SUBTYPE_SH7750S) := perf_event.o | ||
15 | perf-$(CONFIG_CPU_SUBTYPE_SH7091) := perf_event.o | ||
16 | |||
12 | # CPU subtype setup | 17 | # CPU subtype setup |
13 | obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o | 18 | obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o |
14 | obj-$(CONFIG_CPU_SUBTYPE_SH7750R) += setup-sh7750.o | 19 | obj-$(CONFIG_CPU_SUBTYPE_SH7750R) += setup-sh7750.o |
@@ -27,4 +32,5 @@ endif | |||
27 | # Additional clocks by subtype | 32 | # Additional clocks by subtype |
28 | clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o | 33 | clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o |
29 | 34 | ||
30 | obj-y += $(clock-y) | 35 | obj-y += $(clock-y) |
36 | obj-$(CONFIG_PERF_EVENTS) += $(perf-y) | ||
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c index 21421e34e7d5..6b80850294da 100644 --- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c +++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c | |||
@@ -23,7 +23,7 @@ static int frqcr3_values[] = { 0, 1, 2, 3, 4, 5, 6 }; | |||
23 | 23 | ||
24 | static unsigned long emi_clk_recalc(struct clk *clk) | 24 | static unsigned long emi_clk_recalc(struct clk *clk) |
25 | { | 25 | { |
26 | int idx = ctrl_inl(CPG2_FRQCR3) & 0x0007; | 26 | int idx = __raw_readl(CPG2_FRQCR3) & 0x0007; |
27 | return clk->parent->rate / frqcr3_divisors[idx]; | 27 | return clk->parent->rate / frqcr3_divisors[idx]; |
28 | } | 28 | } |
29 | 29 | ||
@@ -52,7 +52,7 @@ static struct clk sh4202_emi_clk = { | |||
52 | 52 | ||
53 | static unsigned long femi_clk_recalc(struct clk *clk) | 53 | static unsigned long femi_clk_recalc(struct clk *clk) |
54 | { | 54 | { |
55 | int idx = (ctrl_inl(CPG2_FRQCR3) >> 3) & 0x0007; | 55 | int idx = (__raw_readl(CPG2_FRQCR3) >> 3) & 0x0007; |
56 | return clk->parent->rate / frqcr3_divisors[idx]; | 56 | return clk->parent->rate / frqcr3_divisors[idx]; |
57 | } | 57 | } |
58 | 58 | ||
@@ -92,7 +92,7 @@ static void shoc_clk_init(struct clk *clk) | |||
92 | 92 | ||
93 | static unsigned long shoc_clk_recalc(struct clk *clk) | 93 | static unsigned long shoc_clk_recalc(struct clk *clk) |
94 | { | 94 | { |
95 | int idx = (ctrl_inl(CPG2_FRQCR3) >> 6) & 0x0007; | 95 | int idx = (__raw_readl(CPG2_FRQCR3) >> 6) & 0x0007; |
96 | return clk->parent->rate / frqcr3_divisors[idx]; | 96 | return clk->parent->rate / frqcr3_divisors[idx]; |
97 | } | 97 | } |
98 | 98 | ||
@@ -122,10 +122,10 @@ static int shoc_clk_set_rate(struct clk *clk, unsigned long rate, int algo_id) | |||
122 | 122 | ||
123 | tmp = frqcr3_lookup(clk, rate); | 123 | tmp = frqcr3_lookup(clk, rate); |
124 | 124 | ||
125 | frqcr3 = ctrl_inl(CPG2_FRQCR3); | 125 | frqcr3 = __raw_readl(CPG2_FRQCR3); |
126 | frqcr3 &= ~(0x0007 << 6); | 126 | frqcr3 &= ~(0x0007 << 6); |
127 | frqcr3 |= tmp << 6; | 127 | frqcr3 |= tmp << 6; |
128 | ctrl_outl(frqcr3, CPG2_FRQCR3); | 128 | __raw_writel(frqcr3, CPG2_FRQCR3); |
129 | 129 | ||
130 | clk->rate = clk->parent->rate / frqcr3_divisors[tmp]; | 130 | clk->rate = clk->parent->rate / frqcr3_divisors[tmp]; |
131 | 131 | ||
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4.c b/arch/sh/kernel/cpu/sh4/clock-sh4.c index 73294d9cd049..5add75c1f539 100644 --- a/arch/sh/kernel/cpu/sh4/clock-sh4.c +++ b/arch/sh/kernel/cpu/sh4/clock-sh4.c | |||
@@ -28,7 +28,7 @@ static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 }; | |||
28 | 28 | ||
29 | static void master_clk_init(struct clk *clk) | 29 | static void master_clk_init(struct clk *clk) |
30 | { | 30 | { |
31 | clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0007]; | 31 | clk->rate *= pfc_divisors[__raw_readw(FRQCR) & 0x0007]; |
32 | } | 32 | } |
33 | 33 | ||
34 | static struct clk_ops sh4_master_clk_ops = { | 34 | static struct clk_ops sh4_master_clk_ops = { |
@@ -37,7 +37,7 @@ static struct clk_ops sh4_master_clk_ops = { | |||
37 | 37 | ||
38 | static unsigned long module_clk_recalc(struct clk *clk) | 38 | static unsigned long module_clk_recalc(struct clk *clk) |
39 | { | 39 | { |
40 | int idx = (ctrl_inw(FRQCR) & 0x0007); | 40 | int idx = (__raw_readw(FRQCR) & 0x0007); |
41 | return clk->parent->rate / pfc_divisors[idx]; | 41 | return clk->parent->rate / pfc_divisors[idx]; |
42 | } | 42 | } |
43 | 43 | ||
@@ -47,7 +47,7 @@ static struct clk_ops sh4_module_clk_ops = { | |||
47 | 47 | ||
48 | static unsigned long bus_clk_recalc(struct clk *clk) | 48 | static unsigned long bus_clk_recalc(struct clk *clk) |
49 | { | 49 | { |
50 | int idx = (ctrl_inw(FRQCR) >> 3) & 0x0007; | 50 | int idx = (__raw_readw(FRQCR) >> 3) & 0x0007; |
51 | return clk->parent->rate / bfc_divisors[idx]; | 51 | return clk->parent->rate / bfc_divisors[idx]; |
52 | } | 52 | } |
53 | 53 | ||
@@ -57,7 +57,7 @@ static struct clk_ops sh4_bus_clk_ops = { | |||
57 | 57 | ||
58 | static unsigned long cpu_clk_recalc(struct clk *clk) | 58 | static unsigned long cpu_clk_recalc(struct clk *clk) |
59 | { | 59 | { |
60 | int idx = (ctrl_inw(FRQCR) >> 6) & 0x0007; | 60 | int idx = (__raw_readw(FRQCR) >> 6) & 0x0007; |
61 | return clk->parent->rate / ifc_divisors[idx]; | 61 | return clk->parent->rate / ifc_divisors[idx]; |
62 | } | 62 | } |
63 | 63 | ||
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c index e3ea5411da6d..447482d7f65e 100644 --- a/arch/sh/kernel/cpu/sh4/fpu.c +++ b/arch/sh/kernel/cpu/sh4/fpu.c | |||
@@ -41,13 +41,11 @@ static unsigned int fpu_exception_flags; | |||
41 | 41 | ||
42 | /* | 42 | /* |
43 | * Save FPU registers onto task structure. | 43 | * Save FPU registers onto task structure. |
44 | * Assume called with FPU enabled (SR.FD=0). | ||
45 | */ | 44 | */ |
46 | void save_fpu(struct task_struct *tsk, struct pt_regs *regs) | 45 | void save_fpu(struct task_struct *tsk) |
47 | { | 46 | { |
48 | unsigned long dummy; | 47 | unsigned long dummy; |
49 | 48 | ||
50 | clear_tsk_thread_flag(tsk, TIF_USEDFPU); | ||
51 | enable_fpu(); | 49 | enable_fpu(); |
52 | asm volatile ("sts.l fpul, @-%0\n\t" | 50 | asm volatile ("sts.l fpul, @-%0\n\t" |
53 | "sts.l fpscr, @-%0\n\t" | 51 | "sts.l fpscr, @-%0\n\t" |
@@ -87,15 +85,14 @@ void save_fpu(struct task_struct *tsk, struct pt_regs *regs) | |||
87 | "fmov.s fr1, @-%0\n\t" | 85 | "fmov.s fr1, @-%0\n\t" |
88 | "fmov.s fr0, @-%0\n\t" | 86 | "fmov.s fr0, @-%0\n\t" |
89 | "lds %3, fpscr\n\t":"=r" (dummy) | 87 | "lds %3, fpscr\n\t":"=r" (dummy) |
90 | :"0"((char *)(&tsk->thread.fpu.hard.status)), | 88 | :"0"((char *)(&tsk->thread.xstate->hardfpu.status)), |
91 | "r"(FPSCR_RCHG), "r"(FPSCR_INIT) | 89 | "r"(FPSCR_RCHG), "r"(FPSCR_INIT) |
92 | :"memory"); | 90 | :"memory"); |
93 | 91 | ||
94 | disable_fpu(); | 92 | disable_fpu(); |
95 | release_fpu(regs); | ||
96 | } | 93 | } |
97 | 94 | ||
98 | static void restore_fpu(struct task_struct *tsk) | 95 | void restore_fpu(struct task_struct *tsk) |
99 | { | 96 | { |
100 | unsigned long dummy; | 97 | unsigned long dummy; |
101 | 98 | ||
@@ -138,62 +135,11 @@ static void restore_fpu(struct task_struct *tsk) | |||
138 | "lds.l @%0+, fpscr\n\t" | 135 | "lds.l @%0+, fpscr\n\t" |
139 | "lds.l @%0+, fpul\n\t" | 136 | "lds.l @%0+, fpul\n\t" |
140 | :"=r" (dummy) | 137 | :"=r" (dummy) |
141 | :"0"(&tsk->thread.fpu), "r"(FPSCR_RCHG) | 138 | :"0" (tsk->thread.xstate), "r" (FPSCR_RCHG) |
142 | :"memory"); | 139 | :"memory"); |
143 | disable_fpu(); | 140 | disable_fpu(); |
144 | } | 141 | } |
145 | 142 | ||
146 | /* | ||
147 | * Load the FPU with signalling NANS. This bit pattern we're using | ||
148 | * has the property that no matter wether considered as single or as | ||
149 | * double precision represents signaling NANS. | ||
150 | */ | ||
151 | |||
152 | static void fpu_init(void) | ||
153 | { | ||
154 | enable_fpu(); | ||
155 | asm volatile ( "lds %0, fpul\n\t" | ||
156 | "lds %1, fpscr\n\t" | ||
157 | "fsts fpul, fr0\n\t" | ||
158 | "fsts fpul, fr1\n\t" | ||
159 | "fsts fpul, fr2\n\t" | ||
160 | "fsts fpul, fr3\n\t" | ||
161 | "fsts fpul, fr4\n\t" | ||
162 | "fsts fpul, fr5\n\t" | ||
163 | "fsts fpul, fr6\n\t" | ||
164 | "fsts fpul, fr7\n\t" | ||
165 | "fsts fpul, fr8\n\t" | ||
166 | "fsts fpul, fr9\n\t" | ||
167 | "fsts fpul, fr10\n\t" | ||
168 | "fsts fpul, fr11\n\t" | ||
169 | "fsts fpul, fr12\n\t" | ||
170 | "fsts fpul, fr13\n\t" | ||
171 | "fsts fpul, fr14\n\t" | ||
172 | "fsts fpul, fr15\n\t" | ||
173 | "frchg\n\t" | ||
174 | "fsts fpul, fr0\n\t" | ||
175 | "fsts fpul, fr1\n\t" | ||
176 | "fsts fpul, fr2\n\t" | ||
177 | "fsts fpul, fr3\n\t" | ||
178 | "fsts fpul, fr4\n\t" | ||
179 | "fsts fpul, fr5\n\t" | ||
180 | "fsts fpul, fr6\n\t" | ||
181 | "fsts fpul, fr7\n\t" | ||
182 | "fsts fpul, fr8\n\t" | ||
183 | "fsts fpul, fr9\n\t" | ||
184 | "fsts fpul, fr10\n\t" | ||
185 | "fsts fpul, fr11\n\t" | ||
186 | "fsts fpul, fr12\n\t" | ||
187 | "fsts fpul, fr13\n\t" | ||
188 | "fsts fpul, fr14\n\t" | ||
189 | "fsts fpul, fr15\n\t" | ||
190 | "frchg\n\t" | ||
191 | "lds %2, fpscr\n\t" | ||
192 | : /* no output */ | ||
193 | :"r" (0), "r"(FPSCR_RCHG), "r"(FPSCR_INIT)); | ||
194 | disable_fpu(); | ||
195 | } | ||
196 | |||
197 | /** | 143 | /** |
198 | * denormal_to_double - Given denormalized float number, | 144 | * denormal_to_double - Given denormalized float number, |
199 | * store double float | 145 | * store double float |
@@ -285,10 +231,9 @@ static int ieee_fpe_handler(struct pt_regs *regs) | |||
285 | /* fcnvsd */ | 231 | /* fcnvsd */ |
286 | struct task_struct *tsk = current; | 232 | struct task_struct *tsk = current; |
287 | 233 | ||
288 | save_fpu(tsk, regs); | 234 | if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_CAUSE_ERROR)) |
289 | if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)) | ||
290 | /* FPU error */ | 235 | /* FPU error */ |
291 | denormal_to_double(&tsk->thread.fpu.hard, | 236 | denormal_to_double(&tsk->thread.xstate->hardfpu, |
292 | (finsn >> 8) & 0xf); | 237 | (finsn >> 8) & 0xf); |
293 | else | 238 | else |
294 | return 0; | 239 | return 0; |
@@ -304,9 +249,9 @@ static int ieee_fpe_handler(struct pt_regs *regs) | |||
304 | 249 | ||
305 | n = (finsn >> 8) & 0xf; | 250 | n = (finsn >> 8) & 0xf; |
306 | m = (finsn >> 4) & 0xf; | 251 | m = (finsn >> 4) & 0xf; |
307 | hx = tsk->thread.fpu.hard.fp_regs[n]; | 252 | hx = tsk->thread.xstate->hardfpu.fp_regs[n]; |
308 | hy = tsk->thread.fpu.hard.fp_regs[m]; | 253 | hy = tsk->thread.xstate->hardfpu.fp_regs[m]; |
309 | fpscr = tsk->thread.fpu.hard.fpscr; | 254 | fpscr = tsk->thread.xstate->hardfpu.fpscr; |
310 | prec = fpscr & FPSCR_DBL_PRECISION; | 255 | prec = fpscr & FPSCR_DBL_PRECISION; |
311 | 256 | ||
312 | if ((fpscr & FPSCR_CAUSE_ERROR) | 257 | if ((fpscr & FPSCR_CAUSE_ERROR) |
@@ -316,18 +261,18 @@ static int ieee_fpe_handler(struct pt_regs *regs) | |||
316 | 261 | ||
317 | /* FPU error because of denormal (doubles) */ | 262 | /* FPU error because of denormal (doubles) */ |
318 | llx = ((long long)hx << 32) | 263 | llx = ((long long)hx << 32) |
319 | | tsk->thread.fpu.hard.fp_regs[n + 1]; | 264 | | tsk->thread.xstate->hardfpu.fp_regs[n + 1]; |
320 | lly = ((long long)hy << 32) | 265 | lly = ((long long)hy << 32) |
321 | | tsk->thread.fpu.hard.fp_regs[m + 1]; | 266 | | tsk->thread.xstate->hardfpu.fp_regs[m + 1]; |
322 | llx = float64_mul(llx, lly); | 267 | llx = float64_mul(llx, lly); |
323 | tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; | 268 | tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32; |
324 | tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff; | 269 | tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff; |
325 | } else if ((fpscr & FPSCR_CAUSE_ERROR) | 270 | } else if ((fpscr & FPSCR_CAUSE_ERROR) |
326 | && (!prec && ((hx & 0x7fffffff) < 0x00800000 | 271 | && (!prec && ((hx & 0x7fffffff) < 0x00800000 |
327 | || (hy & 0x7fffffff) < 0x00800000))) { | 272 | || (hy & 0x7fffffff) < 0x00800000))) { |
328 | /* FPU error because of denormal (floats) */ | 273 | /* FPU error because of denormal (floats) */ |
329 | hx = float32_mul(hx, hy); | 274 | hx = float32_mul(hx, hy); |
330 | tsk->thread.fpu.hard.fp_regs[n] = hx; | 275 | tsk->thread.xstate->hardfpu.fp_regs[n] = hx; |
331 | } else | 276 | } else |
332 | return 0; | 277 | return 0; |
333 | 278 | ||
@@ -342,9 +287,9 @@ static int ieee_fpe_handler(struct pt_regs *regs) | |||
342 | 287 | ||
343 | n = (finsn >> 8) & 0xf; | 288 | n = (finsn >> 8) & 0xf; |
344 | m = (finsn >> 4) & 0xf; | 289 | m = (finsn >> 4) & 0xf; |
345 | hx = tsk->thread.fpu.hard.fp_regs[n]; | 290 | hx = tsk->thread.xstate->hardfpu.fp_regs[n]; |
346 | hy = tsk->thread.fpu.hard.fp_regs[m]; | 291 | hy = tsk->thread.xstate->hardfpu.fp_regs[m]; |
347 | fpscr = tsk->thread.fpu.hard.fpscr; | 292 | fpscr = tsk->thread.xstate->hardfpu.fpscr; |
348 | prec = fpscr & FPSCR_DBL_PRECISION; | 293 | prec = fpscr & FPSCR_DBL_PRECISION; |
349 | 294 | ||
350 | if ((fpscr & FPSCR_CAUSE_ERROR) | 295 | if ((fpscr & FPSCR_CAUSE_ERROR) |
@@ -354,15 +299,15 @@ static int ieee_fpe_handler(struct pt_regs *regs) | |||
354 | 299 | ||
355 | /* FPU error because of denormal (doubles) */ | 300 | /* FPU error because of denormal (doubles) */ |
356 | llx = ((long long)hx << 32) | 301 | llx = ((long long)hx << 32) |
357 | | tsk->thread.fpu.hard.fp_regs[n + 1]; | 302 | | tsk->thread.xstate->hardfpu.fp_regs[n + 1]; |
358 | lly = ((long long)hy << 32) | 303 | lly = ((long long)hy << 32) |
359 | | tsk->thread.fpu.hard.fp_regs[m + 1]; | 304 | | tsk->thread.xstate->hardfpu.fp_regs[m + 1]; |
360 | if ((finsn & 0xf00f) == 0xf000) | 305 | if ((finsn & 0xf00f) == 0xf000) |
361 | llx = float64_add(llx, lly); | 306 | llx = float64_add(llx, lly); |
362 | else | 307 | else |
363 | llx = float64_sub(llx, lly); | 308 | llx = float64_sub(llx, lly); |
364 | tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; | 309 | tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32; |
365 | tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff; | 310 | tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff; |
366 | } else if ((fpscr & FPSCR_CAUSE_ERROR) | 311 | } else if ((fpscr & FPSCR_CAUSE_ERROR) |
367 | && (!prec && ((hx & 0x7fffffff) < 0x00800000 | 312 | && (!prec && ((hx & 0x7fffffff) < 0x00800000 |
368 | || (hy & 0x7fffffff) < 0x00800000))) { | 313 | || (hy & 0x7fffffff) < 0x00800000))) { |
@@ -371,7 +316,7 @@ static int ieee_fpe_handler(struct pt_regs *regs) | |||
371 | hx = float32_add(hx, hy); | 316 | hx = float32_add(hx, hy); |
372 | else | 317 | else |
373 | hx = float32_sub(hx, hy); | 318 | hx = float32_sub(hx, hy); |
374 | tsk->thread.fpu.hard.fp_regs[n] = hx; | 319 | tsk->thread.xstate->hardfpu.fp_regs[n] = hx; |
375 | } else | 320 | } else |
376 | return 0; | 321 | return 0; |
377 | 322 | ||
@@ -386,9 +331,9 @@ static int ieee_fpe_handler(struct pt_regs *regs) | |||
386 | 331 | ||
387 | n = (finsn >> 8) & 0xf; | 332 | n = (finsn >> 8) & 0xf; |
388 | m = (finsn >> 4) & 0xf; | 333 | m = (finsn >> 4) & 0xf; |
389 | hx = tsk->thread.fpu.hard.fp_regs[n]; | 334 | hx = tsk->thread.xstate->hardfpu.fp_regs[n]; |
390 | hy = tsk->thread.fpu.hard.fp_regs[m]; | 335 | hy = tsk->thread.xstate->hardfpu.fp_regs[m]; |
391 | fpscr = tsk->thread.fpu.hard.fpscr; | 336 | fpscr = tsk->thread.xstate->hardfpu.fpscr; |
392 | prec = fpscr & FPSCR_DBL_PRECISION; | 337 | prec = fpscr & FPSCR_DBL_PRECISION; |
393 | 338 | ||
394 | if ((fpscr & FPSCR_CAUSE_ERROR) | 339 | if ((fpscr & FPSCR_CAUSE_ERROR) |
@@ -398,20 +343,20 @@ static int ieee_fpe_handler(struct pt_regs *regs) | |||
398 | 343 | ||
399 | /* FPU error because of denormal (doubles) */ | 344 | /* FPU error because of denormal (doubles) */ |
400 | llx = ((long long)hx << 32) | 345 | llx = ((long long)hx << 32) |
401 | | tsk->thread.fpu.hard.fp_regs[n + 1]; | 346 | | tsk->thread.xstate->hardfpu.fp_regs[n + 1]; |
402 | lly = ((long long)hy << 32) | 347 | lly = ((long long)hy << 32) |
403 | | tsk->thread.fpu.hard.fp_regs[m + 1]; | 348 | | tsk->thread.xstate->hardfpu.fp_regs[m + 1]; |
404 | 349 | ||
405 | llx = float64_div(llx, lly); | 350 | llx = float64_div(llx, lly); |
406 | 351 | ||
407 | tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; | 352 | tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32; |
408 | tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff; | 353 | tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff; |
409 | } else if ((fpscr & FPSCR_CAUSE_ERROR) | 354 | } else if ((fpscr & FPSCR_CAUSE_ERROR) |
410 | && (!prec && ((hx & 0x7fffffff) < 0x00800000 | 355 | && (!prec && ((hx & 0x7fffffff) < 0x00800000 |
411 | || (hy & 0x7fffffff) < 0x00800000))) { | 356 | || (hy & 0x7fffffff) < 0x00800000))) { |
412 | /* FPU error because of denormal (floats) */ | 357 | /* FPU error because of denormal (floats) */ |
413 | hx = float32_div(hx, hy); | 358 | hx = float32_div(hx, hy); |
414 | tsk->thread.fpu.hard.fp_regs[n] = hx; | 359 | tsk->thread.xstate->hardfpu.fp_regs[n] = hx; |
415 | } else | 360 | } else |
416 | return 0; | 361 | return 0; |
417 | 362 | ||
@@ -424,17 +369,17 @@ static int ieee_fpe_handler(struct pt_regs *regs) | |||
424 | unsigned int hx; | 369 | unsigned int hx; |
425 | 370 | ||
426 | m = (finsn >> 8) & 0x7; | 371 | m = (finsn >> 8) & 0x7; |
427 | hx = tsk->thread.fpu.hard.fp_regs[m]; | 372 | hx = tsk->thread.xstate->hardfpu.fp_regs[m]; |
428 | 373 | ||
429 | if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR) | 374 | if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_CAUSE_ERROR) |
430 | && ((hx & 0x7fffffff) < 0x00100000)) { | 375 | && ((hx & 0x7fffffff) < 0x00100000)) { |
431 | /* subnormal double to float conversion */ | 376 | /* subnormal double to float conversion */ |
432 | long long llx; | 377 | long long llx; |
433 | 378 | ||
434 | llx = ((long long)tsk->thread.fpu.hard.fp_regs[m] << 32) | 379 | llx = ((long long)tsk->thread.xstate->hardfpu.fp_regs[m] << 32) |
435 | | tsk->thread.fpu.hard.fp_regs[m + 1]; | 380 | | tsk->thread.xstate->hardfpu.fp_regs[m + 1]; |
436 | 381 | ||
437 | tsk->thread.fpu.hard.fpul = float64_to_float32(llx); | 382 | tsk->thread.xstate->hardfpu.fpul = float64_to_float32(llx); |
438 | } else | 383 | } else |
439 | return 0; | 384 | return 0; |
440 | 385 | ||
@@ -453,7 +398,7 @@ void float_raise(unsigned int flags) | |||
453 | int float_rounding_mode(void) | 398 | int float_rounding_mode(void) |
454 | { | 399 | { |
455 | struct task_struct *tsk = current; | 400 | struct task_struct *tsk = current; |
456 | int roundingMode = FPSCR_ROUNDING_MODE(tsk->thread.fpu.hard.fpscr); | 401 | int roundingMode = FPSCR_ROUNDING_MODE(tsk->thread.xstate->hardfpu.fpscr); |
457 | return roundingMode; | 402 | return roundingMode; |
458 | } | 403 | } |
459 | 404 | ||
@@ -462,19 +407,19 @@ BUILD_TRAP_HANDLER(fpu_error) | |||
462 | struct task_struct *tsk = current; | 407 | struct task_struct *tsk = current; |
463 | TRAP_HANDLER_DECL; | 408 | TRAP_HANDLER_DECL; |
464 | 409 | ||
465 | save_fpu(tsk, regs); | 410 | __unlazy_fpu(tsk, regs); |
466 | fpu_exception_flags = 0; | 411 | fpu_exception_flags = 0; |
467 | if (ieee_fpe_handler(regs)) { | 412 | if (ieee_fpe_handler(regs)) { |
468 | tsk->thread.fpu.hard.fpscr &= | 413 | tsk->thread.xstate->hardfpu.fpscr &= |
469 | ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); | 414 | ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); |
470 | tsk->thread.fpu.hard.fpscr |= fpu_exception_flags; | 415 | tsk->thread.xstate->hardfpu.fpscr |= fpu_exception_flags; |
471 | /* Set the FPSCR flag as well as cause bits - simply | 416 | /* Set the FPSCR flag as well as cause bits - simply |
472 | * replicate the cause */ | 417 | * replicate the cause */ |
473 | tsk->thread.fpu.hard.fpscr |= (fpu_exception_flags >> 10); | 418 | tsk->thread.xstate->hardfpu.fpscr |= (fpu_exception_flags >> 10); |
474 | grab_fpu(regs); | 419 | grab_fpu(regs); |
475 | restore_fpu(tsk); | 420 | restore_fpu(tsk); |
476 | set_tsk_thread_flag(tsk, TIF_USEDFPU); | 421 | task_thread_info(tsk)->status |= TS_USEDFPU; |
477 | if ((((tsk->thread.fpu.hard.fpscr & FPSCR_ENABLE_MASK) >> 7) & | 422 | if ((((tsk->thread.xstate->hardfpu.fpscr & FPSCR_ENABLE_MASK) >> 7) & |
478 | (fpu_exception_flags >> 2)) == 0) { | 423 | (fpu_exception_flags >> 2)) == 0) { |
479 | return; | 424 | return; |
480 | } | 425 | } |
@@ -482,25 +427,3 @@ BUILD_TRAP_HANDLER(fpu_error) | |||
482 | 427 | ||
483 | force_sig(SIGFPE, tsk); | 428 | force_sig(SIGFPE, tsk); |
484 | } | 429 | } |
485 | |||
486 | BUILD_TRAP_HANDLER(fpu_state_restore) | ||
487 | { | ||
488 | struct task_struct *tsk = current; | ||
489 | TRAP_HANDLER_DECL; | ||
490 | |||
491 | grab_fpu(regs); | ||
492 | if (!user_mode(regs)) { | ||
493 | printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); | ||
494 | return; | ||
495 | } | ||
496 | |||
497 | if (used_math()) { | ||
498 | /* Using the FPU again. */ | ||
499 | restore_fpu(tsk); | ||
500 | } else { | ||
501 | /* First time FPU user. */ | ||
502 | fpu_init(); | ||
503 | set_used_math(); | ||
504 | } | ||
505 | set_tsk_thread_flag(tsk, TIF_USEDFPU); | ||
506 | } | ||
diff --git a/arch/sh/kernel/cpu/sh4/perf_event.c b/arch/sh/kernel/cpu/sh4/perf_event.c new file mode 100644 index 000000000000..7f9ecc9c2d02 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/perf_event.c | |||
@@ -0,0 +1,253 @@ | |||
1 | /* | ||
2 | * Performance events support for SH7750-style performance counters | ||
3 | * | ||
4 | * Copyright (C) 2009 Paul Mundt | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/perf_event.h> | ||
15 | #include <asm/processor.h> | ||
16 | |||
17 | #define PM_CR_BASE 0xff000084 /* 16-bit */ | ||
18 | #define PM_CTR_BASE 0xff100004 /* 32-bit */ | ||
19 | |||
20 | #define PMCR(n) (PM_CR_BASE + ((n) * 0x04)) | ||
21 | #define PMCTRH(n) (PM_CTR_BASE + 0x00 + ((n) * 0x08)) | ||
22 | #define PMCTRL(n) (PM_CTR_BASE + 0x04 + ((n) * 0x08)) | ||
23 | |||
24 | #define PMCR_PMM_MASK 0x0000003f | ||
25 | |||
26 | #define PMCR_CLKF 0x00000100 | ||
27 | #define PMCR_PMCLR 0x00002000 | ||
28 | #define PMCR_PMST 0x00004000 | ||
29 | #define PMCR_PMEN 0x00008000 | ||
30 | |||
31 | static struct sh_pmu sh7750_pmu; | ||
32 | |||
33 | /* | ||
34 | * There are a number of events supported by each counter (33 in total). | ||
35 | * Since we have 2 counters, each counter will take the event code as it | ||
36 | * corresponds to the PMCR PMM setting. Each counter can be configured | ||
37 | * independently. | ||
38 | * | ||
39 | * Event Code Description | ||
40 | * ---------- ----------- | ||
41 | * | ||
42 | * 0x01 Operand read access | ||
43 | * 0x02 Operand write access | ||
44 | * 0x03 UTLB miss | ||
45 | * 0x04 Operand cache read miss | ||
46 | * 0x05 Operand cache write miss | ||
47 | * 0x06 Instruction fetch (w/ cache) | ||
48 | * 0x07 Instruction TLB miss | ||
49 | * 0x08 Instruction cache miss | ||
50 | * 0x09 All operand accesses | ||
51 | * 0x0a All instruction accesses | ||
52 | * 0x0b OC RAM operand access | ||
53 | * 0x0d On-chip I/O space access | ||
54 | * 0x0e Operand access (r/w) | ||
55 | * 0x0f Operand cache miss (r/w) | ||
56 | * 0x10 Branch instruction | ||
57 | * 0x11 Branch taken | ||
58 | * 0x12 BSR/BSRF/JSR | ||
59 | * 0x13 Instruction execution | ||
60 | * 0x14 Instruction execution in parallel | ||
61 | * 0x15 FPU Instruction execution | ||
62 | * 0x16 Interrupt | ||
63 | * 0x17 NMI | ||
64 | * 0x18 trapa instruction execution | ||
65 | * 0x19 UBCA match | ||
66 | * 0x1a UBCB match | ||
67 | * 0x21 Instruction cache fill | ||
68 | * 0x22 Operand cache fill | ||
69 | * 0x23 Elapsed time | ||
70 | * 0x24 Pipeline freeze by I-cache miss | ||
71 | * 0x25 Pipeline freeze by D-cache miss | ||
72 | * 0x27 Pipeline freeze by branch instruction | ||
73 | * 0x28 Pipeline freeze by CPU register | ||
74 | * 0x29 Pipeline freeze by FPU | ||
75 | */ | ||
76 | |||
77 | static const int sh7750_general_events[] = { | ||
78 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0023, | ||
79 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x000a, | ||
80 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0006, /* I-cache */ | ||
81 | [PERF_COUNT_HW_CACHE_MISSES] = 0x0008, /* I-cache */ | ||
82 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x0010, | ||
83 | [PERF_COUNT_HW_BRANCH_MISSES] = -1, | ||
84 | [PERF_COUNT_HW_BUS_CYCLES] = -1, | ||
85 | }; | ||
86 | |||
87 | #define C(x) PERF_COUNT_HW_CACHE_##x | ||
88 | |||
89 | static const int sh7750_cache_events | ||
90 | [PERF_COUNT_HW_CACHE_MAX] | ||
91 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
92 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
93 | { | ||
94 | [ C(L1D) ] = { | ||
95 | [ C(OP_READ) ] = { | ||
96 | [ C(RESULT_ACCESS) ] = 0x0001, | ||
97 | [ C(RESULT_MISS) ] = 0x0004, | ||
98 | }, | ||
99 | [ C(OP_WRITE) ] = { | ||
100 | [ C(RESULT_ACCESS) ] = 0x0002, | ||
101 | [ C(RESULT_MISS) ] = 0x0005, | ||
102 | }, | ||
103 | [ C(OP_PREFETCH) ] = { | ||
104 | [ C(RESULT_ACCESS) ] = 0, | ||
105 | [ C(RESULT_MISS) ] = 0, | ||
106 | }, | ||
107 | }, | ||
108 | |||
109 | [ C(L1I) ] = { | ||
110 | [ C(OP_READ) ] = { | ||
111 | [ C(RESULT_ACCESS) ] = 0x0006, | ||
112 | [ C(RESULT_MISS) ] = 0x0008, | ||
113 | }, | ||
114 | [ C(OP_WRITE) ] = { | ||
115 | [ C(RESULT_ACCESS) ] = -1, | ||
116 | [ C(RESULT_MISS) ] = -1, | ||
117 | }, | ||
118 | [ C(OP_PREFETCH) ] = { | ||
119 | [ C(RESULT_ACCESS) ] = 0, | ||
120 | [ C(RESULT_MISS) ] = 0, | ||
121 | }, | ||
122 | }, | ||
123 | |||
124 | [ C(LL) ] = { | ||
125 | [ C(OP_READ) ] = { | ||
126 | [ C(RESULT_ACCESS) ] = 0, | ||
127 | [ C(RESULT_MISS) ] = 0, | ||
128 | }, | ||
129 | [ C(OP_WRITE) ] = { | ||
130 | [ C(RESULT_ACCESS) ] = 0, | ||
131 | [ C(RESULT_MISS) ] = 0, | ||
132 | }, | ||
133 | [ C(OP_PREFETCH) ] = { | ||
134 | [ C(RESULT_ACCESS) ] = 0, | ||
135 | [ C(RESULT_MISS) ] = 0, | ||
136 | }, | ||
137 | }, | ||
138 | |||
139 | [ C(DTLB) ] = { | ||
140 | [ C(OP_READ) ] = { | ||
141 | [ C(RESULT_ACCESS) ] = 0, | ||
142 | [ C(RESULT_MISS) ] = 0x0003, | ||
143 | }, | ||
144 | [ C(OP_WRITE) ] = { | ||
145 | [ C(RESULT_ACCESS) ] = 0, | ||
146 | [ C(RESULT_MISS) ] = 0, | ||
147 | }, | ||
148 | [ C(OP_PREFETCH) ] = { | ||
149 | [ C(RESULT_ACCESS) ] = 0, | ||
150 | [ C(RESULT_MISS) ] = 0, | ||
151 | }, | ||
152 | }, | ||
153 | |||
154 | [ C(ITLB) ] = { | ||
155 | [ C(OP_READ) ] = { | ||
156 | [ C(RESULT_ACCESS) ] = 0, | ||
157 | [ C(RESULT_MISS) ] = 0x0007, | ||
158 | }, | ||
159 | [ C(OP_WRITE) ] = { | ||
160 | [ C(RESULT_ACCESS) ] = -1, | ||
161 | [ C(RESULT_MISS) ] = -1, | ||
162 | }, | ||
163 | [ C(OP_PREFETCH) ] = { | ||
164 | [ C(RESULT_ACCESS) ] = -1, | ||
165 | [ C(RESULT_MISS) ] = -1, | ||
166 | }, | ||
167 | }, | ||
168 | |||
169 | [ C(BPU) ] = { | ||
170 | [ C(OP_READ) ] = { | ||
171 | [ C(RESULT_ACCESS) ] = -1, | ||
172 | [ C(RESULT_MISS) ] = -1, | ||
173 | }, | ||
174 | [ C(OP_WRITE) ] = { | ||
175 | [ C(RESULT_ACCESS) ] = -1, | ||
176 | [ C(RESULT_MISS) ] = -1, | ||
177 | }, | ||
178 | [ C(OP_PREFETCH) ] = { | ||
179 | [ C(RESULT_ACCESS) ] = -1, | ||
180 | [ C(RESULT_MISS) ] = -1, | ||
181 | }, | ||
182 | }, | ||
183 | }; | ||
184 | |||
185 | static int sh7750_event_map(int event) | ||
186 | { | ||
187 | return sh7750_general_events[event]; | ||
188 | } | ||
189 | |||
190 | static u64 sh7750_pmu_read(int idx) | ||
191 | { | ||
192 | return (u64)((u64)(__raw_readl(PMCTRH(idx)) & 0xffff) << 32) | | ||
193 | __raw_readl(PMCTRL(idx)); | ||
194 | } | ||
195 | |||
196 | static void sh7750_pmu_disable(struct hw_perf_event *hwc, int idx) | ||
197 | { | ||
198 | unsigned int tmp; | ||
199 | |||
200 | tmp = __raw_readw(PMCR(idx)); | ||
201 | tmp &= ~(PMCR_PMM_MASK | PMCR_PMEN); | ||
202 | __raw_writew(tmp, PMCR(idx)); | ||
203 | } | ||
204 | |||
205 | static void sh7750_pmu_enable(struct hw_perf_event *hwc, int idx) | ||
206 | { | ||
207 | __raw_writew(__raw_readw(PMCR(idx)) | PMCR_PMCLR, PMCR(idx)); | ||
208 | __raw_writew(hwc->config | PMCR_PMEN | PMCR_PMST, PMCR(idx)); | ||
209 | } | ||
210 | |||
211 | static void sh7750_pmu_disable_all(void) | ||
212 | { | ||
213 | int i; | ||
214 | |||
215 | for (i = 0; i < sh7750_pmu.num_events; i++) | ||
216 | __raw_writew(__raw_readw(PMCR(i)) & ~PMCR_PMEN, PMCR(i)); | ||
217 | } | ||
218 | |||
219 | static void sh7750_pmu_enable_all(void) | ||
220 | { | ||
221 | int i; | ||
222 | |||
223 | for (i = 0; i < sh7750_pmu.num_events; i++) | ||
224 | __raw_writew(__raw_readw(PMCR(i)) | PMCR_PMEN, PMCR(i)); | ||
225 | } | ||
226 | |||
227 | static struct sh_pmu sh7750_pmu = { | ||
228 | .name = "SH7750", | ||
229 | .num_events = 2, | ||
230 | .event_map = sh7750_event_map, | ||
231 | .max_events = ARRAY_SIZE(sh7750_general_events), | ||
232 | .raw_event_mask = PMCR_PMM_MASK, | ||
233 | .cache_events = &sh7750_cache_events, | ||
234 | .read = sh7750_pmu_read, | ||
235 | .disable = sh7750_pmu_disable, | ||
236 | .enable = sh7750_pmu_enable, | ||
237 | .disable_all = sh7750_pmu_disable_all, | ||
238 | .enable_all = sh7750_pmu_enable_all, | ||
239 | }; | ||
240 | |||
241 | static int __init sh7750_pmu_init(void) | ||
242 | { | ||
243 | /* | ||
244 | * Make sure this CPU actually has perf counters. | ||
245 | */ | ||
246 | if (!(boot_cpu_data.flags & CPU_HAS_PERF_COUNTER)) { | ||
247 | pr_notice("HW perf events unsupported, software events only.\n"); | ||
248 | return -ENODEV; | ||
249 | } | ||
250 | |||
251 | return register_sh_pmu(&sh7750_pmu); | ||
252 | } | ||
253 | arch_initcall(sh7750_pmu_init); | ||
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index d36f0c45f55f..822977a06d84 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c | |||
@@ -28,9 +28,9 @@ int __init detect_cpu_and_cache_system(void) | |||
28 | [9] = (1 << 16) | 28 | [9] = (1 << 16) |
29 | }; | 29 | }; |
30 | 30 | ||
31 | pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffffff; | 31 | pvr = (__raw_readl(CCN_PVR) >> 8) & 0xffffff; |
32 | prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff; | 32 | prr = (__raw_readl(CCN_PRR) >> 4) & 0xff; |
33 | cvr = (ctrl_inl(CCN_CVR)); | 33 | cvr = (__raw_readl(CCN_CVR)); |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * Setup some sane SH-4 defaults for the icache | 36 | * Setup some sane SH-4 defaults for the icache |
@@ -71,11 +71,11 @@ int __init detect_cpu_and_cache_system(void) | |||
71 | boot_cpu_data.dcache.ways = 4; | 71 | boot_cpu_data.dcache.ways = 4; |
72 | } else { | 72 | } else { |
73 | /* And some SH-4 defaults.. */ | 73 | /* And some SH-4 defaults.. */ |
74 | boot_cpu_data.flags |= CPU_HAS_PTEA; | 74 | boot_cpu_data.flags |= CPU_HAS_PTEA | CPU_HAS_FPU; |
75 | boot_cpu_data.family = CPU_FAMILY_SH4; | 75 | boot_cpu_data.family = CPU_FAMILY_SH4; |
76 | } | 76 | } |
77 | 77 | ||
78 | /* FPU detection works for everyone */ | 78 | /* FPU detection works for almost everyone */ |
79 | if ((cvr & 0x20000000)) | 79 | if ((cvr & 0x20000000)) |
80 | boot_cpu_data.flags |= CPU_HAS_FPU; | 80 | boot_cpu_data.flags |= CPU_HAS_FPU; |
81 | 81 | ||
@@ -124,6 +124,7 @@ int __init detect_cpu_and_cache_system(void) | |||
124 | boot_cpu_data.type = CPU_SH7785; | 124 | boot_cpu_data.type = CPU_SH7785; |
125 | break; | 125 | break; |
126 | case 0x4004: | 126 | case 0x4004: |
127 | case 0x4005: | ||
127 | boot_cpu_data.type = CPU_SH7786; | 128 | boot_cpu_data.type = CPU_SH7786; |
128 | boot_cpu_data.flags |= CPU_HAS_PTEAEX | CPU_HAS_L2_CACHE; | 129 | boot_cpu_data.flags |= CPU_HAS_PTEAEX | CPU_HAS_L2_CACHE; |
129 | break; | 130 | break; |
@@ -160,6 +161,7 @@ int __init detect_cpu_and_cache_system(void) | |||
160 | break; | 161 | break; |
161 | case 0x700: | 162 | case 0x700: |
162 | boot_cpu_data.type = CPU_SH4_501; | 163 | boot_cpu_data.type = CPU_SH4_501; |
164 | boot_cpu_data.flags &= ~CPU_HAS_FPU; | ||
163 | boot_cpu_data.icache.ways = 2; | 165 | boot_cpu_data.icache.ways = 2; |
164 | boot_cpu_data.dcache.ways = 2; | 166 | boot_cpu_data.dcache.ways = 2; |
165 | break; | 167 | break; |
@@ -227,7 +229,7 @@ int __init detect_cpu_and_cache_system(void) | |||
227 | * Size calculation is much more sensible | 229 | * Size calculation is much more sensible |
228 | * than it is for the L1. | 230 | * than it is for the L1. |
229 | * | 231 | * |
230 | * Sizes are 128KB, 258KB, 512KB, and 1MB. | 232 | * Sizes are 128KB, 256KB, 512KB, and 1MB. |
231 | */ | 233 | */ |
232 | size = (cvr & 0xf) << 17; | 234 | size = (cvr & 0xf) << 17; |
233 | 235 | ||
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c index de4827df19aa..b9b7e10ad68f 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c | |||
@@ -15,22 +15,18 @@ | |||
15 | #include <linux/sh_timer.h> | 15 | #include <linux/sh_timer.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | 17 | ||
18 | static struct plat_sci_port sci_platform_data[] = { | 18 | static struct plat_sci_port scif0_platform_data = { |
19 | { | 19 | .mapbase = 0xffe80000, |
20 | .mapbase = 0xffe80000, | 20 | .flags = UPF_BOOT_AUTOCONF, |
21 | .flags = UPF_BOOT_AUTOCONF, | 21 | .type = PORT_SCIF, |
22 | .type = PORT_SCIF, | 22 | .irqs = { 40, 41, 43, 42 }, |
23 | .irqs = { 40, 41, 43, 42 }, | ||
24 | }, { | ||
25 | .flags = 0, | ||
26 | } | ||
27 | }; | 23 | }; |
28 | 24 | ||
29 | static struct platform_device sci_device = { | 25 | static struct platform_device scif0_device = { |
30 | .name = "sh-sci", | 26 | .name = "sh-sci", |
31 | .id = -1, | 27 | .id = 0, |
32 | .dev = { | 28 | .dev = { |
33 | .platform_data = sci_platform_data, | 29 | .platform_data = &scif0_platform_data, |
34 | }, | 30 | }, |
35 | }; | 31 | }; |
36 | 32 | ||
@@ -127,7 +123,7 @@ static struct platform_device tmu2_device = { | |||
127 | }; | 123 | }; |
128 | 124 | ||
129 | static struct platform_device *sh4202_devices[] __initdata = { | 125 | static struct platform_device *sh4202_devices[] __initdata = { |
130 | &sci_device, | 126 | &scif0_device, |
131 | &tmu0_device, | 127 | &tmu0_device, |
132 | &tmu1_device, | 128 | &tmu1_device, |
133 | &tmu2_device, | 129 | &tmu2_device, |
@@ -141,6 +137,7 @@ static int __init sh4202_devices_setup(void) | |||
141 | arch_initcall(sh4202_devices_setup); | 137 | arch_initcall(sh4202_devices_setup); |
142 | 138 | ||
143 | static struct platform_device *sh4202_early_devices[] __initdata = { | 139 | static struct platform_device *sh4202_early_devices[] __initdata = { |
140 | &scif0_device, | ||
144 | &tmu0_device, | 141 | &tmu0_device, |
145 | &tmu1_device, | 142 | &tmu1_device, |
146 | &tmu2_device, | 143 | &tmu2_device, |
@@ -201,7 +198,7 @@ void __init plat_irq_setup_pins(int mode) | |||
201 | { | 198 | { |
202 | switch (mode) { | 199 | switch (mode) { |
203 | case IRQ_MODE_IRQ: /* individual interrupt mode for IRL3-0 */ | 200 | case IRQ_MODE_IRQ: /* individual interrupt mode for IRL3-0 */ |
204 | ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); | 201 | __raw_writew(__raw_readw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); |
205 | register_intc_controller(&intc_desc_irlm); | 202 | register_intc_controller(&intc_desc_irlm); |
206 | break; | 203 | break; |
207 | default: | 204 | default: |
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c index 1b8b122e8f3d..ffd79e57254f 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c | |||
@@ -35,29 +35,33 @@ static struct platform_device rtc_device = { | |||
35 | .resource = rtc_resources, | 35 | .resource = rtc_resources, |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static struct plat_sci_port sci_platform_data[] = { | 38 | static struct plat_sci_port scif0_platform_data = { |
39 | { | 39 | .mapbase = 0xffe00000, |
40 | #ifndef CONFIG_SH_RTS7751R2D | 40 | .flags = UPF_BOOT_AUTOCONF, |
41 | .mapbase = 0xffe00000, | 41 | .type = PORT_SCI, |
42 | .flags = UPF_BOOT_AUTOCONF, | 42 | .irqs = { 23, 23, 23, 0 }, |
43 | .type = PORT_SCI, | ||
44 | .irqs = { 23, 23, 23, 0 }, | ||
45 | }, { | ||
46 | #endif | ||
47 | .mapbase = 0xffe80000, | ||
48 | .flags = UPF_BOOT_AUTOCONF, | ||
49 | .type = PORT_SCIF, | ||
50 | .irqs = { 40, 40, 40, 40 }, | ||
51 | }, { | ||
52 | .flags = 0, | ||
53 | } | ||
54 | }; | 43 | }; |
55 | 44 | ||
56 | static struct platform_device sci_device = { | 45 | static struct platform_device scif0_device = { |
57 | .name = "sh-sci", | 46 | .name = "sh-sci", |
58 | .id = -1, | 47 | .id = 0, |
48 | .dev = { | ||
49 | .platform_data = &scif0_platform_data, | ||
50 | }, | ||
51 | }; | ||
52 | |||
53 | static struct plat_sci_port scif1_platform_data = { | ||
54 | .mapbase = 0xffe80000, | ||
55 | .flags = UPF_BOOT_AUTOCONF, | ||
56 | .type = PORT_SCIF, | ||
57 | .irqs = { 40, 40, 40, 40 }, | ||
58 | }; | ||
59 | |||
60 | static struct platform_device scif1_device = { | ||
61 | .name = "sh-sci", | ||
62 | .id = 1, | ||
59 | .dev = { | 63 | .dev = { |
60 | .platform_data = sci_platform_data, | 64 | .platform_data = &scif1_platform_data, |
61 | }, | 65 | }, |
62 | }; | 66 | }; |
63 | 67 | ||
@@ -221,8 +225,9 @@ static struct platform_device tmu4_device = { | |||
221 | #endif | 225 | #endif |
222 | 226 | ||
223 | static struct platform_device *sh7750_devices[] __initdata = { | 227 | static struct platform_device *sh7750_devices[] __initdata = { |
228 | &scif0_device, | ||
229 | &scif1_device, | ||
224 | &rtc_device, | 230 | &rtc_device, |
225 | &sci_device, | ||
226 | &tmu0_device, | 231 | &tmu0_device, |
227 | &tmu1_device, | 232 | &tmu1_device, |
228 | &tmu2_device, | 233 | &tmu2_device, |
@@ -242,6 +247,8 @@ static int __init sh7750_devices_setup(void) | |||
242 | arch_initcall(sh7750_devices_setup); | 247 | arch_initcall(sh7750_devices_setup); |
243 | 248 | ||
244 | static struct platform_device *sh7750_early_devices[] __initdata = { | 249 | static struct platform_device *sh7750_early_devices[] __initdata = { |
250 | &scif0_device, | ||
251 | &scif1_device, | ||
245 | &tmu0_device, | 252 | &tmu0_device, |
246 | &tmu1_device, | 253 | &tmu1_device, |
247 | &tmu2_device, | 254 | &tmu2_device, |
@@ -435,7 +442,7 @@ void __init plat_irq_setup_pins(int mode) | |||
435 | 442 | ||
436 | switch (mode) { | 443 | switch (mode) { |
437 | case IRQ_MODE_IRQ: /* individual interrupt mode for IRL3-0 */ | 444 | case IRQ_MODE_IRQ: /* individual interrupt mode for IRL3-0 */ |
438 | ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); | 445 | __raw_writew(__raw_readw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); |
439 | register_intc_controller(&intc_desc_irlm); | 446 | register_intc_controller(&intc_desc_irlm); |
440 | break; | 447 | break; |
441 | default: | 448 | default: |
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c index 7fbb7be9284c..a16eb3656f4b 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c | |||
@@ -126,37 +126,63 @@ static struct intc_vect vectors_irq[] __initdata = { | |||
126 | static DECLARE_INTC_DESC(intc_desc_irq, "sh7760-irq", vectors_irq, groups, | 126 | static DECLARE_INTC_DESC(intc_desc_irq, "sh7760-irq", vectors_irq, groups, |
127 | mask_registers, prio_registers, NULL); | 127 | mask_registers, prio_registers, NULL); |
128 | 128 | ||
129 | static struct plat_sci_port sci_platform_data[] = { | 129 | static struct plat_sci_port scif0_platform_data = { |
130 | { | 130 | .mapbase = 0xfe600000, |
131 | .mapbase = 0xfe600000, | 131 | .flags = UPF_BOOT_AUTOCONF, |
132 | .flags = UPF_BOOT_AUTOCONF, | 132 | .type = PORT_SCIF, |
133 | .type = PORT_SCIF, | 133 | .irqs = { 52, 53, 55, 54 }, |
134 | .irqs = { 52, 53, 55, 54 }, | 134 | }; |
135 | }, { | 135 | |
136 | .mapbase = 0xfe610000, | 136 | static struct platform_device scif0_device = { |
137 | .flags = UPF_BOOT_AUTOCONF, | 137 | .name = "sh-sci", |
138 | .type = PORT_SCIF, | 138 | .id = 0, |
139 | .irqs = { 72, 73, 75, 74 }, | 139 | .dev = { |
140 | }, { | 140 | .platform_data = &scif0_platform_data, |
141 | .mapbase = 0xfe620000, | 141 | }, |
142 | .flags = UPF_BOOT_AUTOCONF, | 142 | }; |
143 | .type = PORT_SCIF, | 143 | |
144 | .irqs = { 76, 77, 79, 78 }, | 144 | static struct plat_sci_port scif1_platform_data = { |
145 | }, { | 145 | .mapbase = 0xfe610000, |
146 | .mapbase = 0xfe480000, | 146 | .flags = UPF_BOOT_AUTOCONF, |
147 | .flags = UPF_BOOT_AUTOCONF, | 147 | .type = PORT_SCIF, |
148 | .type = PORT_SCI, | 148 | .irqs = { 72, 73, 75, 74 }, |
149 | .irqs = { 80, 81, 82, 0 }, | 149 | }; |
150 | }, { | 150 | |
151 | .flags = 0, | 151 | static struct platform_device scif1_device = { |
152 | } | 152 | .name = "sh-sci", |
153 | .id = 1, | ||
154 | .dev = { | ||
155 | .platform_data = &scif1_platform_data, | ||
156 | }, | ||
157 | }; | ||
158 | |||
159 | static struct plat_sci_port scif2_platform_data = { | ||
160 | .mapbase = 0xfe620000, | ||
161 | .flags = UPF_BOOT_AUTOCONF, | ||
162 | .type = PORT_SCIF, | ||
163 | .irqs = { 76, 77, 79, 78 }, | ||
164 | }; | ||
165 | |||
166 | static struct platform_device scif2_device = { | ||
167 | .name = "sh-sci", | ||
168 | .id = 2, | ||
169 | .dev = { | ||
170 | .platform_data = &scif2_platform_data, | ||
171 | }, | ||
172 | }; | ||
173 | |||
174 | static struct plat_sci_port scif3_platform_data = { | ||
175 | .mapbase = 0xfe480000, | ||
176 | .flags = UPF_BOOT_AUTOCONF, | ||
177 | .type = PORT_SCI, | ||
178 | .irqs = { 80, 81, 82, 0 }, | ||
153 | }; | 179 | }; |
154 | 180 | ||
155 | static struct platform_device sci_device = { | 181 | static struct platform_device scif3_device = { |
156 | .name = "sh-sci", | 182 | .name = "sh-sci", |
157 | .id = -1, | 183 | .id = 3, |
158 | .dev = { | 184 | .dev = { |
159 | .platform_data = sci_platform_data, | 185 | .platform_data = &scif3_platform_data, |
160 | }, | 186 | }, |
161 | }; | 187 | }; |
162 | 188 | ||
@@ -254,7 +280,10 @@ static struct platform_device tmu2_device = { | |||
254 | 280 | ||
255 | 281 | ||
256 | static struct platform_device *sh7760_devices[] __initdata = { | 282 | static struct platform_device *sh7760_devices[] __initdata = { |
257 | &sci_device, | 283 | &scif0_device, |
284 | &scif1_device, | ||
285 | &scif2_device, | ||
286 | &scif3_device, | ||
258 | &tmu0_device, | 287 | &tmu0_device, |
259 | &tmu1_device, | 288 | &tmu1_device, |
260 | &tmu2_device, | 289 | &tmu2_device, |
@@ -268,6 +297,10 @@ static int __init sh7760_devices_setup(void) | |||
268 | arch_initcall(sh7760_devices_setup); | 297 | arch_initcall(sh7760_devices_setup); |
269 | 298 | ||
270 | static struct platform_device *sh7760_early_devices[] __initdata = { | 299 | static struct platform_device *sh7760_early_devices[] __initdata = { |
300 | &scif0_device, | ||
301 | &scif1_device, | ||
302 | &scif2_device, | ||
303 | &scif3_device, | ||
271 | &tmu0_device, | 304 | &tmu0_device, |
272 | &tmu1_device, | 305 | &tmu1_device, |
273 | &tmu2_device, | 306 | &tmu2_device, |
@@ -286,7 +319,7 @@ void __init plat_irq_setup_pins(int mode) | |||
286 | { | 319 | { |
287 | switch (mode) { | 320 | switch (mode) { |
288 | case IRQ_MODE_IRQ: | 321 | case IRQ_MODE_IRQ: |
289 | ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); | 322 | __raw_writew(__raw_readw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); |
290 | register_intc_controller(&intc_desc_irq); | 323 | register_intc_controller(&intc_desc_irq); |
291 | break; | 324 | break; |
292 | default: | 325 | default: |
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c index 8a8a993f55ea..14726eef1ce0 100644 --- a/arch/sh/kernel/cpu/sh4/sq.c +++ b/arch/sh/kernel/cpu/sh4/sq.c | |||
@@ -43,9 +43,9 @@ static unsigned long *sq_bitmap; | |||
43 | 43 | ||
44 | #define store_queue_barrier() \ | 44 | #define store_queue_barrier() \ |
45 | do { \ | 45 | do { \ |
46 | (void)ctrl_inl(P4SEG_STORE_QUE); \ | 46 | (void)__raw_readl(P4SEG_STORE_QUE); \ |
47 | ctrl_outl(0, P4SEG_STORE_QUE + 0); \ | 47 | __raw_writel(0, P4SEG_STORE_QUE + 0); \ |
48 | ctrl_outl(0, P4SEG_STORE_QUE + 8); \ | 48 | __raw_writel(0, P4SEG_STORE_QUE + 8); \ |
49 | } while (0); | 49 | } while (0); |
50 | 50 | ||
51 | /** | 51 | /** |
@@ -100,7 +100,7 @@ static inline void sq_mapping_list_del(struct sq_mapping *map) | |||
100 | spin_unlock_irq(&sq_mapping_lock); | 100 | spin_unlock_irq(&sq_mapping_lock); |
101 | } | 101 | } |
102 | 102 | ||
103 | static int __sq_remap(struct sq_mapping *map, unsigned long flags) | 103 | static int __sq_remap(struct sq_mapping *map, pgprot_t prot) |
104 | { | 104 | { |
105 | #if defined(CONFIG_MMU) | 105 | #if defined(CONFIG_MMU) |
106 | struct vm_struct *vma; | 106 | struct vm_struct *vma; |
@@ -113,7 +113,7 @@ static int __sq_remap(struct sq_mapping *map, unsigned long flags) | |||
113 | 113 | ||
114 | if (ioremap_page_range((unsigned long)vma->addr, | 114 | if (ioremap_page_range((unsigned long)vma->addr, |
115 | (unsigned long)vma->addr + map->size, | 115 | (unsigned long)vma->addr + map->size, |
116 | vma->phys_addr, __pgprot(flags))) { | 116 | vma->phys_addr, prot)) { |
117 | vunmap(vma->addr); | 117 | vunmap(vma->addr); |
118 | return -EAGAIN; | 118 | return -EAGAIN; |
119 | } | 119 | } |
@@ -123,8 +123,8 @@ static int __sq_remap(struct sq_mapping *map, unsigned long flags) | |||
123 | * straightforward, as we can just load up each queue's QACR with | 123 | * straightforward, as we can just load up each queue's QACR with |
124 | * the physical address appropriately masked. | 124 | * the physical address appropriately masked. |
125 | */ | 125 | */ |
126 | ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0); | 126 | __raw_writel(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0); |
127 | ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1); | 127 | __raw_writel(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1); |
128 | #endif | 128 | #endif |
129 | 129 | ||
130 | return 0; | 130 | return 0; |
@@ -135,14 +135,14 @@ static int __sq_remap(struct sq_mapping *map, unsigned long flags) | |||
135 | * @phys: Physical address of mapping. | 135 | * @phys: Physical address of mapping. |
136 | * @size: Length of mapping. | 136 | * @size: Length of mapping. |
137 | * @name: User invoking mapping. | 137 | * @name: User invoking mapping. |
138 | * @flags: Protection flags. | 138 | * @prot: Protection bits. |
139 | * | 139 | * |
140 | * Remaps the physical address @phys through the next available store queue | 140 | * Remaps the physical address @phys through the next available store queue |
141 | * address of @size length. @name is logged at boot time as well as through | 141 | * address of @size length. @name is logged at boot time as well as through |
142 | * the sysfs interface. | 142 | * the sysfs interface. |
143 | */ | 143 | */ |
144 | unsigned long sq_remap(unsigned long phys, unsigned int size, | 144 | unsigned long sq_remap(unsigned long phys, unsigned int size, |
145 | const char *name, unsigned long flags) | 145 | const char *name, pgprot_t prot) |
146 | { | 146 | { |
147 | struct sq_mapping *map; | 147 | struct sq_mapping *map; |
148 | unsigned long end; | 148 | unsigned long end; |
@@ -177,7 +177,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size, | |||
177 | 177 | ||
178 | map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT); | 178 | map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT); |
179 | 179 | ||
180 | ret = __sq_remap(map, pgprot_val(PAGE_KERNEL_NOCACHE) | flags); | 180 | ret = __sq_remap(map, prot); |
181 | if (unlikely(ret != 0)) | 181 | if (unlikely(ret != 0)) |
182 | goto out; | 182 | goto out; |
183 | 183 | ||
@@ -309,8 +309,7 @@ static ssize_t mapping_store(const char *buf, size_t count) | |||
309 | return -EIO; | 309 | return -EIO; |
310 | 310 | ||
311 | if (likely(len)) { | 311 | if (likely(len)) { |
312 | int ret = sq_remap(base, len, "Userspace", | 312 | int ret = sq_remap(base, len, "Userspace", PAGE_SHARED); |
313 | pgprot_val(PAGE_SHARED)); | ||
314 | if (ret < 0) | 313 | if (ret < 0) |
315 | return ret; | 314 | return ret; |
316 | } else | 315 | } else |
@@ -327,7 +326,7 @@ static struct attribute *sq_sysfs_attrs[] = { | |||
327 | NULL, | 326 | NULL, |
328 | }; | 327 | }; |
329 | 328 | ||
330 | static struct sysfs_ops sq_sysfs_ops = { | 329 | static const struct sysfs_ops sq_sysfs_ops = { |
331 | .show = sq_sysfs_show, | 330 | .show = sq_sysfs_show, |
332 | .store = sq_sysfs_store, | 331 | .store = sq_sysfs_store, |
333 | }; | 332 | }; |
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index 490d5dc9e372..b144e8af89dc 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile | |||
@@ -41,6 +41,8 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7757) := pinmux-sh7757.o | |||
41 | pinmux-$(CONFIG_CPU_SUBTYPE_SH7785) := pinmux-sh7785.o | 41 | pinmux-$(CONFIG_CPU_SUBTYPE_SH7785) := pinmux-sh7785.o |
42 | pinmux-$(CONFIG_CPU_SUBTYPE_SH7786) := pinmux-sh7786.o | 42 | pinmux-$(CONFIG_CPU_SUBTYPE_SH7786) := pinmux-sh7786.o |
43 | 43 | ||
44 | obj-y += $(clock-y) | 44 | obj-y += $(clock-y) |
45 | obj-$(CONFIG_SMP) += $(smp-y) | 45 | obj-$(CONFIG_SMP) += $(smp-y) |
46 | obj-$(CONFIG_GENERIC_GPIO) += $(pinmux-y) | 46 | obj-$(CONFIG_GENERIC_GPIO) += $(pinmux-y) |
47 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o | ||
48 | obj-$(CONFIG_HAVE_HW_BREAKPOINT) += ubc.o | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index 0ee3ee861252..2c16df37eda6 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c | |||
@@ -107,13 +107,17 @@ struct clk *main_clks[] = { | |||
107 | static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; | 107 | static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; |
108 | static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; | 108 | static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; |
109 | 109 | ||
110 | static struct clk_div_mult_table div4_table = { | 110 | static struct clk_div_mult_table div4_div_mult_table = { |
111 | .divisors = divisors, | 111 | .divisors = divisors, |
112 | .nr_divisors = ARRAY_SIZE(divisors), | 112 | .nr_divisors = ARRAY_SIZE(divisors), |
113 | .multipliers = multipliers, | 113 | .multipliers = multipliers, |
114 | .nr_multipliers = ARRAY_SIZE(multipliers), | 114 | .nr_multipliers = ARRAY_SIZE(multipliers), |
115 | }; | 115 | }; |
116 | 116 | ||
117 | static struct clk_div4_table div4_table = { | ||
118 | .div_mult_table = &div4_div_mult_table, | ||
119 | }; | ||
120 | |||
117 | enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, | 121 | enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, |
118 | DIV4_SIUA, DIV4_SIUB, DIV4_NR }; | 122 | DIV4_SIUA, DIV4_SIUB, DIV4_NR }; |
119 | 123 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index a95ebaba095c..91588d280cd8 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c | |||
@@ -110,13 +110,17 @@ struct clk *main_clks[] = { | |||
110 | static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; | 110 | static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; |
111 | static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; | 111 | static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; |
112 | 112 | ||
113 | static struct clk_div_mult_table div4_table = { | 113 | static struct clk_div_mult_table div4_div_mult_table = { |
114 | .divisors = divisors, | 114 | .divisors = divisors, |
115 | .nr_divisors = ARRAY_SIZE(divisors), | 115 | .nr_divisors = ARRAY_SIZE(divisors), |
116 | .multipliers = multipliers, | 116 | .multipliers = multipliers, |
117 | .nr_multipliers = ARRAY_SIZE(multipliers), | 117 | .nr_multipliers = ARRAY_SIZE(multipliers), |
118 | }; | 118 | }; |
119 | 119 | ||
120 | static struct clk_div4_table div4_table = { | ||
121 | .div_mult_table = &div4_div_mult_table, | ||
122 | }; | ||
123 | |||
120 | enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, | 124 | enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, |
121 | DIV4_SIUA, DIV4_SIUB, DIV4_NR }; | 125 | DIV4_SIUA, DIV4_SIUB, DIV4_NR }; |
122 | 126 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index ea38b554dc05..15db6d521c5c 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c | |||
@@ -110,19 +110,22 @@ struct clk *main_clks[] = { | |||
110 | static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; | 110 | static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; |
111 | static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; | 111 | static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; |
112 | 112 | ||
113 | static struct clk_div_mult_table div4_table = { | 113 | static struct clk_div_mult_table div4_div_mult_table = { |
114 | .divisors = divisors, | 114 | .divisors = divisors, |
115 | .nr_divisors = ARRAY_SIZE(divisors), | 115 | .nr_divisors = ARRAY_SIZE(divisors), |
116 | .multipliers = multipliers, | 116 | .multipliers = multipliers, |
117 | .nr_multipliers = ARRAY_SIZE(multipliers), | 117 | .nr_multipliers = ARRAY_SIZE(multipliers), |
118 | }; | 118 | }; |
119 | 119 | ||
120 | enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, | 120 | static struct clk_div4_table div4_table = { |
121 | DIV4_SIUA, DIV4_SIUB, DIV4_IRDA, DIV4_NR }; | 121 | .div_mult_table = &div4_div_mult_table, |
122 | }; | ||
122 | 123 | ||
123 | #define DIV4(_str, _reg, _bit, _mask, _flags) \ | 124 | #define DIV4(_str, _reg, _bit, _mask, _flags) \ |
124 | SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) | 125 | SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) |
125 | 126 | ||
127 | enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR }; | ||
128 | |||
126 | struct clk div4_clks[DIV4_NR] = { | 129 | struct clk div4_clks[DIV4_NR] = { |
127 | [DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT), | 130 | [DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT), |
128 | [DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT), | 131 | [DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT), |
@@ -130,9 +133,19 @@ struct clk div4_clks[DIV4_NR] = { | |||
130 | [DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT), | 133 | [DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT), |
131 | [DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT), | 134 | [DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT), |
132 | [DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0), | 135 | [DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0), |
136 | }; | ||
137 | |||
138 | enum { DIV4_IRDA, DIV4_ENABLE_NR }; | ||
139 | |||
140 | struct clk div4_enable_clks[DIV4_ENABLE_NR] = { | ||
141 | [DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x1fff, 0), | ||
142 | }; | ||
143 | |||
144 | enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR }; | ||
145 | |||
146 | struct clk div4_reparent_clks[DIV4_REPARENT_NR] = { | ||
133 | [DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0), | 147 | [DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0), |
134 | [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0), | 148 | [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0), |
135 | [DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x1fff, 0), | ||
136 | }; | 149 | }; |
137 | 150 | ||
138 | struct clk div6_clks[] = { | 151 | struct clk div6_clks[] = { |
@@ -189,6 +202,14 @@ int __init arch_clk_init(void) | |||
189 | ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); | 202 | ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); |
190 | 203 | ||
191 | if (!ret) | 204 | if (!ret) |
205 | ret = sh_clk_div4_enable_register(div4_enable_clks, | ||
206 | DIV4_ENABLE_NR, &div4_table); | ||
207 | |||
208 | if (!ret) | ||
209 | ret = sh_clk_div4_reparent_register(div4_reparent_clks, | ||
210 | DIV4_REPARENT_NR, &div4_table); | ||
211 | |||
212 | if (!ret) | ||
192 | ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); | 213 | ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); |
193 | 214 | ||
194 | if (!ret) | 215 | if (!ret) |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index 20a31c2255a8..50babe01fe44 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c | |||
@@ -110,15 +110,18 @@ struct clk *main_clks[] = { | |||
110 | static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; | 110 | static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; |
111 | static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; | 111 | static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 }; |
112 | 112 | ||
113 | static struct clk_div_mult_table div4_table = { | 113 | static struct clk_div_mult_table div4_div_mult_table = { |
114 | .divisors = divisors, | 114 | .divisors = divisors, |
115 | .nr_divisors = ARRAY_SIZE(divisors), | 115 | .nr_divisors = ARRAY_SIZE(divisors), |
116 | .multipliers = multipliers, | 116 | .multipliers = multipliers, |
117 | .nr_multipliers = ARRAY_SIZE(multipliers), | 117 | .nr_multipliers = ARRAY_SIZE(multipliers), |
118 | }; | 118 | }; |
119 | 119 | ||
120 | enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, | 120 | static struct clk_div4_table div4_table = { |
121 | DIV4_SIUA, DIV4_SIUB, DIV4_IRDA, DIV4_NR }; | 121 | .div_mult_table = &div4_div_mult_table, |
122 | }; | ||
123 | |||
124 | enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR }; | ||
122 | 125 | ||
123 | #define DIV4(_str, _reg, _bit, _mask, _flags) \ | 126 | #define DIV4(_str, _reg, _bit, _mask, _flags) \ |
124 | SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) | 127 | SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) |
@@ -130,11 +133,20 @@ struct clk div4_clks[DIV4_NR] = { | |||
130 | [DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x0dbf, CLK_ENABLE_ON_INIT), | 133 | [DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x0dbf, CLK_ENABLE_ON_INIT), |
131 | [DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x0db4, CLK_ENABLE_ON_INIT), | 134 | [DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x0db4, CLK_ENABLE_ON_INIT), |
132 | [DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x0dbf, 0), | 135 | [DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x0dbf, 0), |
133 | [DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x0dbf, 0), | 136 | }; |
134 | [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x0dbf, 0), | 137 | |
138 | enum { DIV4_IRDA, DIV4_ENABLE_NR }; | ||
139 | |||
140 | struct clk div4_enable_clks[DIV4_ENABLE_NR] = { | ||
135 | [DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x0dbf, 0), | 141 | [DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x0dbf, 0), |
136 | }; | 142 | }; |
137 | 143 | ||
144 | enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR }; | ||
145 | |||
146 | struct clk div4_reparent_clks[DIV4_REPARENT_NR] = { | ||
147 | [DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x0dbf, 0), | ||
148 | [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x0dbf, 0), | ||
149 | }; | ||
138 | struct clk div6_clks[] = { | 150 | struct clk div6_clks[] = { |
139 | SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), | 151 | SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), |
140 | }; | 152 | }; |
@@ -216,6 +228,14 @@ int __init arch_clk_init(void) | |||
216 | ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); | 228 | ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); |
217 | 229 | ||
218 | if (!ret) | 230 | if (!ret) |
231 | ret = sh_clk_div4_enable_register(div4_enable_clks, | ||
232 | DIV4_ENABLE_NR, &div4_table); | ||
233 | |||
234 | if (!ret) | ||
235 | ret = sh_clk_div4_reparent_register(div4_reparent_clks, | ||
236 | DIV4_REPARENT_NR, &div4_table); | ||
237 | |||
238 | if (!ret) | ||
219 | ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); | 239 | ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); |
220 | 240 | ||
221 | if (!ret) | 241 | if (!ret) |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index dfe9192be63e..6707061fbf54 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c | |||
@@ -127,13 +127,28 @@ struct clk *main_clks[] = { | |||
127 | &div3_clk, | 127 | &div3_clk, |
128 | }; | 128 | }; |
129 | 129 | ||
130 | static void div4_kick(struct clk *clk) | ||
131 | { | ||
132 | unsigned long value; | ||
133 | |||
134 | /* set KICK bit in FRQCRA to update hardware setting */ | ||
135 | value = __raw_readl(FRQCRA); | ||
136 | value |= (1 << 31); | ||
137 | __raw_writel(value, FRQCRA); | ||
138 | } | ||
139 | |||
130 | static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 0, 24, 32, 36, 48, 0, 72 }; | 140 | static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 0, 24, 32, 36, 48, 0, 72 }; |
131 | 141 | ||
132 | static struct clk_div_mult_table div4_table = { | 142 | static struct clk_div_mult_table div4_div_mult_table = { |
133 | .divisors = divisors, | 143 | .divisors = divisors, |
134 | .nr_divisors = ARRAY_SIZE(divisors), | 144 | .nr_divisors = ARRAY_SIZE(divisors), |
135 | }; | 145 | }; |
136 | 146 | ||
147 | static struct clk_div4_table div4_table = { | ||
148 | .div_mult_table = &div4_div_mult_table, | ||
149 | .kick = div4_kick, | ||
150 | }; | ||
151 | |||
137 | enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_P, DIV4_M1, DIV4_NR }; | 152 | enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_P, DIV4_M1, DIV4_NR }; |
138 | 153 | ||
139 | #define DIV4(_str, _reg, _bit, _mask, _flags) \ | 154 | #define DIV4(_str, _reg, _bit, _mask, _flags) \ |
@@ -144,7 +159,7 @@ struct clk div4_clks[DIV4_NR] = { | |||
144 | [DIV4_SH] = DIV4("shyway_clk", FRQCRA, 12, 0x2f7c, CLK_ENABLE_ON_INIT), | 159 | [DIV4_SH] = DIV4("shyway_clk", FRQCRA, 12, 0x2f7c, CLK_ENABLE_ON_INIT), |
145 | [DIV4_B] = DIV4("bus_clk", FRQCRA, 8, 0x2f7c, CLK_ENABLE_ON_INIT), | 160 | [DIV4_B] = DIV4("bus_clk", FRQCRA, 8, 0x2f7c, CLK_ENABLE_ON_INIT), |
146 | [DIV4_P] = DIV4("peripheral_clk", FRQCRA, 0, 0x2f7c, 0), | 161 | [DIV4_P] = DIV4("peripheral_clk", FRQCRA, 0, 0x2f7c, 0), |
147 | [DIV4_M1] = DIV4("vpu_clk", FRQCRB, 4, 0x2f7c, 0), | 162 | [DIV4_M1] = DIV4("vpu_clk", FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT), |
148 | }; | 163 | }; |
149 | 164 | ||
150 | struct clk div6_clks[] = { | 165 | struct clk div6_clks[] = { |
@@ -152,7 +167,7 @@ struct clk div6_clks[] = { | |||
152 | SH_CLK_DIV6("fsia_clk", &div3_clk, FCLKACR, 0), | 167 | SH_CLK_DIV6("fsia_clk", &div3_clk, FCLKACR, 0), |
153 | SH_CLK_DIV6("fsib_clk", &div3_clk, FCLKBCR, 0), | 168 | SH_CLK_DIV6("fsib_clk", &div3_clk, FCLKBCR, 0), |
154 | SH_CLK_DIV6("irda_clk", &div3_clk, IRDACLKCR, 0), | 169 | SH_CLK_DIV6("irda_clk", &div3_clk, IRDACLKCR, 0), |
155 | SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, 0), | 170 | SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, CLK_ENABLE_ON_INIT), |
156 | }; | 171 | }; |
157 | 172 | ||
158 | #define R_CLK (&r_clk) | 173 | #define R_CLK (&r_clk) |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c index ddc235ca9664..86aae60677dc 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c | |||
@@ -35,7 +35,7 @@ static struct clk_ops sh7757_master_clk_ops = { | |||
35 | 35 | ||
36 | static void module_clk_recalc(struct clk *clk) | 36 | static void module_clk_recalc(struct clk *clk) |
37 | { | 37 | { |
38 | int idx = ctrl_inl(FRQCR) & 0x0000000f; | 38 | int idx = __raw_readl(FRQCR) & 0x0000000f; |
39 | clk->rate = clk->parent->rate / p1fc_divisors[idx]; | 39 | clk->rate = clk->parent->rate / p1fc_divisors[idx]; |
40 | } | 40 | } |
41 | 41 | ||
@@ -45,7 +45,7 @@ static struct clk_ops sh7757_module_clk_ops = { | |||
45 | 45 | ||
46 | static void bus_clk_recalc(struct clk *clk) | 46 | static void bus_clk_recalc(struct clk *clk) |
47 | { | 47 | { |
48 | int idx = (ctrl_inl(FRQCR) >> 8) & 0x0000000f; | 48 | int idx = (__raw_readl(FRQCR) >> 8) & 0x0000000f; |
49 | clk->rate = clk->parent->rate / bfc_divisors[idx]; | 49 | clk->rate = clk->parent->rate / bfc_divisors[idx]; |
50 | } | 50 | } |
51 | 51 | ||
@@ -55,7 +55,7 @@ static struct clk_ops sh7757_bus_clk_ops = { | |||
55 | 55 | ||
56 | static void cpu_clk_recalc(struct clk *clk) | 56 | static void cpu_clk_recalc(struct clk *clk) |
57 | { | 57 | { |
58 | int idx = (ctrl_inl(FRQCR) >> 20) & 0x0000000f; | 58 | int idx = (__raw_readl(FRQCR) >> 20) & 0x0000000f; |
59 | clk->rate = clk->parent->rate / ifc_divisors[idx]; | 59 | clk->rate = clk->parent->rate / ifc_divisors[idx]; |
60 | } | 60 | } |
61 | 61 | ||
@@ -78,7 +78,7 @@ void __init arch_init_clk_ops(struct clk_ops **ops, int idx) | |||
78 | 78 | ||
79 | static void shyway_clk_recalc(struct clk *clk) | 79 | static void shyway_clk_recalc(struct clk *clk) |
80 | { | 80 | { |
81 | int idx = (ctrl_inl(FRQCR) >> 12) & 0x0000000f; | 81 | int idx = (__raw_readl(FRQCR) >> 12) & 0x0000000f; |
82 | clk->rate = clk->parent->rate / sfc_divisors[idx]; | 82 | clk->rate = clk->parent->rate / sfc_divisors[idx]; |
83 | } | 83 | } |
84 | 84 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c index 370cd47642ef..9f401163e71e 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c | |||
@@ -22,7 +22,7 @@ static int cfc_divisors[] = { 1, 1, 4, 1, 1, 1, 1, 1 }; | |||
22 | 22 | ||
23 | static void master_clk_init(struct clk *clk) | 23 | static void master_clk_init(struct clk *clk) |
24 | { | 24 | { |
25 | clk->rate *= p0fc_divisors[(ctrl_inl(FRQCR) >> 4) & 0x07]; | 25 | clk->rate *= p0fc_divisors[(__raw_readl(FRQCR) >> 4) & 0x07]; |
26 | } | 26 | } |
27 | 27 | ||
28 | static struct clk_ops sh7763_master_clk_ops = { | 28 | static struct clk_ops sh7763_master_clk_ops = { |
@@ -31,7 +31,7 @@ static struct clk_ops sh7763_master_clk_ops = { | |||
31 | 31 | ||
32 | static unsigned long module_clk_recalc(struct clk *clk) | 32 | static unsigned long module_clk_recalc(struct clk *clk) |
33 | { | 33 | { |
34 | int idx = ((ctrl_inl(FRQCR) >> 4) & 0x07); | 34 | int idx = ((__raw_readl(FRQCR) >> 4) & 0x07); |
35 | return clk->parent->rate / p0fc_divisors[idx]; | 35 | return clk->parent->rate / p0fc_divisors[idx]; |
36 | } | 36 | } |
37 | 37 | ||
@@ -41,7 +41,7 @@ static struct clk_ops sh7763_module_clk_ops = { | |||
41 | 41 | ||
42 | static unsigned long bus_clk_recalc(struct clk *clk) | 42 | static unsigned long bus_clk_recalc(struct clk *clk) |
43 | { | 43 | { |
44 | int idx = ((ctrl_inl(FRQCR) >> 16) & 0x07); | 44 | int idx = ((__raw_readl(FRQCR) >> 16) & 0x07); |
45 | return clk->parent->rate / bfc_divisors[idx]; | 45 | return clk->parent->rate / bfc_divisors[idx]; |
46 | } | 46 | } |
47 | 47 | ||
@@ -68,7 +68,7 @@ void __init arch_init_clk_ops(struct clk_ops **ops, int idx) | |||
68 | 68 | ||
69 | static unsigned long shyway_clk_recalc(struct clk *clk) | 69 | static unsigned long shyway_clk_recalc(struct clk *clk) |
70 | { | 70 | { |
71 | int idx = ((ctrl_inl(FRQCR) >> 20) & 0x07); | 71 | int idx = ((__raw_readl(FRQCR) >> 20) & 0x07); |
72 | return clk->parent->rate / cfc_divisors[idx]; | 72 | return clk->parent->rate / cfc_divisors[idx]; |
73 | } | 73 | } |
74 | 74 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7770.c b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c index e0b896769205..9e3354365d40 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7770.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c | |||
@@ -21,7 +21,7 @@ static int pfc_divisors[] = { 1, 8, 1,10,12,16, 1, 1 }; | |||
21 | 21 | ||
22 | static void master_clk_init(struct clk *clk) | 22 | static void master_clk_init(struct clk *clk) |
23 | { | 23 | { |
24 | clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> 28) & 0x000f]; | 24 | clk->rate *= pfc_divisors[(__raw_readl(FRQCR) >> 28) & 0x000f]; |
25 | } | 25 | } |
26 | 26 | ||
27 | static struct clk_ops sh7770_master_clk_ops = { | 27 | static struct clk_ops sh7770_master_clk_ops = { |
@@ -30,7 +30,7 @@ static struct clk_ops sh7770_master_clk_ops = { | |||
30 | 30 | ||
31 | static unsigned long module_clk_recalc(struct clk *clk) | 31 | static unsigned long module_clk_recalc(struct clk *clk) |
32 | { | 32 | { |
33 | int idx = ((ctrl_inl(FRQCR) >> 28) & 0x000f); | 33 | int idx = ((__raw_readl(FRQCR) >> 28) & 0x000f); |
34 | return clk->parent->rate / pfc_divisors[idx]; | 34 | return clk->parent->rate / pfc_divisors[idx]; |
35 | } | 35 | } |
36 | 36 | ||
@@ -40,7 +40,7 @@ static struct clk_ops sh7770_module_clk_ops = { | |||
40 | 40 | ||
41 | static unsigned long bus_clk_recalc(struct clk *clk) | 41 | static unsigned long bus_clk_recalc(struct clk *clk) |
42 | { | 42 | { |
43 | int idx = (ctrl_inl(FRQCR) & 0x000f); | 43 | int idx = (__raw_readl(FRQCR) & 0x000f); |
44 | return clk->parent->rate / bfc_divisors[idx]; | 44 | return clk->parent->rate / bfc_divisors[idx]; |
45 | } | 45 | } |
46 | 46 | ||
@@ -50,7 +50,7 @@ static struct clk_ops sh7770_bus_clk_ops = { | |||
50 | 50 | ||
51 | static unsigned long cpu_clk_recalc(struct clk *clk) | 51 | static unsigned long cpu_clk_recalc(struct clk *clk) |
52 | { | 52 | { |
53 | int idx = ((ctrl_inl(FRQCR) >> 24) & 0x000f); | 53 | int idx = ((__raw_readl(FRQCR) >> 24) & 0x000f); |
54 | return clk->parent->rate / ifc_divisors[idx]; | 54 | return clk->parent->rate / ifc_divisors[idx]; |
55 | } | 55 | } |
56 | 56 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c index a249d823578e..150963a6001e 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c | |||
@@ -22,7 +22,7 @@ static int cfc_divisors[] = { 1, 1, 4, 1, 6, 1, 1, 1 }; | |||
22 | 22 | ||
23 | static void master_clk_init(struct clk *clk) | 23 | static void master_clk_init(struct clk *clk) |
24 | { | 24 | { |
25 | clk->rate *= pfc_divisors[ctrl_inl(FRQCR) & 0x0003]; | 25 | clk->rate *= pfc_divisors[__raw_readl(FRQCR) & 0x0003]; |
26 | } | 26 | } |
27 | 27 | ||
28 | static struct clk_ops sh7780_master_clk_ops = { | 28 | static struct clk_ops sh7780_master_clk_ops = { |
@@ -31,7 +31,7 @@ static struct clk_ops sh7780_master_clk_ops = { | |||
31 | 31 | ||
32 | static unsigned long module_clk_recalc(struct clk *clk) | 32 | static unsigned long module_clk_recalc(struct clk *clk) |
33 | { | 33 | { |
34 | int idx = (ctrl_inl(FRQCR) & 0x0003); | 34 | int idx = (__raw_readl(FRQCR) & 0x0003); |
35 | return clk->parent->rate / pfc_divisors[idx]; | 35 | return clk->parent->rate / pfc_divisors[idx]; |
36 | } | 36 | } |
37 | 37 | ||
@@ -41,7 +41,7 @@ static struct clk_ops sh7780_module_clk_ops = { | |||
41 | 41 | ||
42 | static unsigned long bus_clk_recalc(struct clk *clk) | 42 | static unsigned long bus_clk_recalc(struct clk *clk) |
43 | { | 43 | { |
44 | int idx = ((ctrl_inl(FRQCR) >> 16) & 0x0007); | 44 | int idx = ((__raw_readl(FRQCR) >> 16) & 0x0007); |
45 | return clk->parent->rate / bfc_divisors[idx]; | 45 | return clk->parent->rate / bfc_divisors[idx]; |
46 | } | 46 | } |
47 | 47 | ||
@@ -51,7 +51,7 @@ static struct clk_ops sh7780_bus_clk_ops = { | |||
51 | 51 | ||
52 | static unsigned long cpu_clk_recalc(struct clk *clk) | 52 | static unsigned long cpu_clk_recalc(struct clk *clk) |
53 | { | 53 | { |
54 | int idx = ((ctrl_inl(FRQCR) >> 24) & 0x0001); | 54 | int idx = ((__raw_readl(FRQCR) >> 24) & 0x0001); |
55 | return clk->parent->rate / ifc_divisors[idx]; | 55 | return clk->parent->rate / ifc_divisors[idx]; |
56 | } | 56 | } |
57 | 57 | ||
@@ -74,7 +74,7 @@ void __init arch_init_clk_ops(struct clk_ops **ops, int idx) | |||
74 | 74 | ||
75 | static unsigned long shyway_clk_recalc(struct clk *clk) | 75 | static unsigned long shyway_clk_recalc(struct clk *clk) |
76 | { | 76 | { |
77 | int idx = ((ctrl_inl(FRQCR) >> 20) & 0x0007); | 77 | int idx = ((__raw_readl(FRQCR) >> 20) & 0x0007); |
78 | return clk->parent->rate / cfc_divisors[idx]; | 78 | return clk->parent->rate / cfc_divisors[idx]; |
79 | } | 79 | } |
80 | 80 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index 73abfbf2f16d..d997f0a25b10 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c | |||
@@ -57,11 +57,15 @@ static struct clk *clks[] = { | |||
57 | static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18, | 57 | static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18, |
58 | 24, 32, 36, 48 }; | 58 | 24, 32, 36, 48 }; |
59 | 59 | ||
60 | static struct clk_div_mult_table div4_table = { | 60 | static struct clk_div_mult_table div4_div_mult_table = { |
61 | .divisors = div2, | 61 | .divisors = div2, |
62 | .nr_divisors = ARRAY_SIZE(div2), | 62 | .nr_divisors = ARRAY_SIZE(div2), |
63 | }; | 63 | }; |
64 | 64 | ||
65 | static struct clk_div4_table div4_table = { | ||
66 | .div_mult_table = &div4_div_mult_table, | ||
67 | }; | ||
68 | |||
65 | enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_GA, | 69 | enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_GA, |
66 | DIV4_DU, DIV4_P, DIV4_NR }; | 70 | DIV4_DU, DIV4_P, DIV4_NR }; |
67 | 71 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index a0e8869071ac..af69fd468703 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c | |||
@@ -3,11 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SH7786 support for the clock framework | 4 | * SH7786 support for the clock framework |
5 | * | 5 | * |
6 | * Copyright (C) 2008, 2009 Renesas Solutions Corp. | 6 | * Copyright (C) 2010 Paul Mundt |
7 | * Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
8 | * | ||
9 | * Based on SH7785 | ||
10 | * Copyright (C) 2007 Paul Mundt | ||
11 | * | 7 | * |
12 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
13 | * License. See the file "COPYING" in the main directory of this archive | 9 | * License. See the file "COPYING" in the main directory of this archive |
@@ -15,127 +11,127 @@ | |||
15 | */ | 11 | */ |
16 | #include <linux/init.h> | 12 | #include <linux/init.h> |
17 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/clk.h> | ||
15 | #include <linux/io.h> | ||
18 | #include <asm/clock.h> | 16 | #include <asm/clock.h> |
19 | #include <asm/freq.h> | 17 | #include <asm/freq.h> |
20 | #include <asm/io.h> | ||
21 | |||
22 | static int ifc_divisors[] = { 1, 2, 4, 1 }; | ||
23 | static int sfc_divisors[] = { 1, 1, 4, 1 }; | ||
24 | static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 1, | ||
25 | 24, 32, 1, 1, 1, 1, 1, 1 }; | ||
26 | static int mfc_divisors[] = { 1, 1, 4, 1 }; | ||
27 | static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 16, 1, | ||
28 | 24, 32, 1, 48, 1, 1, 1, 1 }; | ||
29 | 18 | ||
30 | static void master_clk_init(struct clk *clk) | 19 | /* |
31 | { | 20 | * Default rate for the root input clock, reset this with clk_set_rate() |
32 | clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f]; | 21 | * from the platform code. |
33 | } | 22 | */ |
34 | 23 | static struct clk extal_clk = { | |
35 | static struct clk_ops sh7786_master_clk_ops = { | 24 | .name = "extal", |
36 | .init = master_clk_init, | 25 | .id = -1, |
26 | .rate = 33333333, | ||
37 | }; | 27 | }; |
38 | 28 | ||
39 | static unsigned long module_clk_recalc(struct clk *clk) | 29 | static unsigned long pll_recalc(struct clk *clk) |
40 | { | 30 | { |
41 | int idx = (ctrl_inl(FRQMR1) & 0x000f); | 31 | int multiplier; |
42 | return clk->parent->rate / pfc_divisors[idx]; | ||
43 | } | ||
44 | 32 | ||
45 | static struct clk_ops sh7786_module_clk_ops = { | 33 | /* |
46 | .recalc = module_clk_recalc, | 34 | * Clock modes 0, 1, and 2 use an x64 multiplier against PLL1, |
47 | }; | 35 | * while modes 3, 4, and 5 use an x32. |
36 | */ | ||
37 | multiplier = (sh_mv.mv_mode_pins() & 0xf) < 3 ? 64 : 32; | ||
48 | 38 | ||
49 | static unsigned long bus_clk_recalc(struct clk *clk) | 39 | return clk->parent->rate * multiplier; |
50 | { | ||
51 | int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f); | ||
52 | return clk->parent->rate / bfc_divisors[idx]; | ||
53 | } | 40 | } |
54 | 41 | ||
55 | static struct clk_ops sh7786_bus_clk_ops = { | 42 | static struct clk_ops pll_clk_ops = { |
56 | .recalc = bus_clk_recalc, | 43 | .recalc = pll_recalc, |
57 | }; | 44 | }; |
58 | 45 | ||
59 | static unsigned long cpu_clk_recalc(struct clk *clk) | 46 | static struct clk pll_clk = { |
60 | { | 47 | .name = "pll_clk", |
61 | int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003); | 48 | .id = -1, |
62 | return clk->parent->rate / ifc_divisors[idx]; | 49 | .ops = &pll_clk_ops, |
63 | } | 50 | .parent = &extal_clk, |
64 | 51 | .flags = CLK_ENABLE_ON_INIT, | |
65 | static struct clk_ops sh7786_cpu_clk_ops = { | ||
66 | .recalc = cpu_clk_recalc, | ||
67 | }; | 52 | }; |
68 | 53 | ||
69 | static struct clk_ops *sh7786_clk_ops[] = { | 54 | static struct clk *clks[] = { |
70 | &sh7786_master_clk_ops, | 55 | &extal_clk, |
71 | &sh7786_module_clk_ops, | 56 | &pll_clk, |
72 | &sh7786_bus_clk_ops, | ||
73 | &sh7786_cpu_clk_ops, | ||
74 | }; | 57 | }; |
75 | 58 | ||
76 | void __init arch_init_clk_ops(struct clk_ops **ops, int idx) | 59 | static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18, |
77 | { | 60 | 24, 32, 36, 48 }; |
78 | if (idx < ARRAY_SIZE(sh7786_clk_ops)) | ||
79 | *ops = sh7786_clk_ops[idx]; | ||
80 | } | ||
81 | 61 | ||
82 | static unsigned long shyway_clk_recalc(struct clk *clk) | 62 | static struct clk_div_mult_table div4_div_mult_table = { |
83 | { | 63 | .divisors = div2, |
84 | int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003); | 64 | .nr_divisors = ARRAY_SIZE(div2), |
85 | return clk->parent->rate / sfc_divisors[idx]; | ||
86 | } | ||
87 | |||
88 | static struct clk_ops sh7786_shyway_clk_ops = { | ||
89 | .recalc = shyway_clk_recalc, | ||
90 | }; | 65 | }; |
91 | 66 | ||
92 | static struct clk sh7786_shyway_clk = { | 67 | static struct clk_div4_table div4_table = { |
93 | .name = "shyway_clk", | 68 | .div_mult_table = &div4_div_mult_table, |
94 | .flags = CLK_ENABLE_ON_INIT, | ||
95 | .ops = &sh7786_shyway_clk_ops, | ||
96 | }; | 69 | }; |
97 | 70 | ||
98 | static unsigned long ddr_clk_recalc(struct clk *clk) | 71 | enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_DU, DIV4_P, DIV4_NR }; |
99 | { | ||
100 | int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003); | ||
101 | return clk->parent->rate / mfc_divisors[idx]; | ||
102 | } | ||
103 | 72 | ||
104 | static struct clk_ops sh7786_ddr_clk_ops = { | 73 | #define DIV4(_str, _bit, _mask, _flags) \ |
105 | .recalc = ddr_clk_recalc, | 74 | SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags) |
106 | }; | ||
107 | 75 | ||
108 | static struct clk sh7786_ddr_clk = { | 76 | struct clk div4_clks[DIV4_NR] = { |
109 | .name = "ddr_clk", | 77 | [DIV4_P] = DIV4("peripheral_clk", 0, 0x0b40, 0), |
110 | .flags = CLK_ENABLE_ON_INIT, | 78 | [DIV4_DU] = DIV4("du_clk", 4, 0x0010, 0), |
111 | .ops = &sh7786_ddr_clk_ops, | 79 | [DIV4_DDR] = DIV4("ddr_clk", 12, 0x0002, CLK_ENABLE_ON_INIT), |
80 | [DIV4_B] = DIV4("bus_clk", 16, 0x0360, CLK_ENABLE_ON_INIT), | ||
81 | [DIV4_SH] = DIV4("shyway_clk", 20, 0x0002, CLK_ENABLE_ON_INIT), | ||
82 | [DIV4_I] = DIV4("cpu_clk", 28, 0x0006, CLK_ENABLE_ON_INIT), | ||
112 | }; | 83 | }; |
113 | 84 | ||
114 | /* | 85 | #define MSTPCR0 0xffc40030 |
115 | * Additional SH7786-specific on-chip clocks that aren't already part of the | 86 | #define MSTPCR1 0xffc40034 |
116 | * clock framework | 87 | |
117 | */ | 88 | static struct clk mstp_clks[] = { |
118 | static struct clk *sh7786_onchip_clocks[] = { | 89 | /* MSTPCR0 */ |
119 | &sh7786_shyway_clk, | 90 | SH_CLK_MSTP32("scif_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), |
120 | &sh7786_ddr_clk, | 91 | SH_CLK_MSTP32("scif_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), |
92 | SH_CLK_MSTP32("scif_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), | ||
93 | SH_CLK_MSTP32("scif_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), | ||
94 | SH_CLK_MSTP32("scif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), | ||
95 | SH_CLK_MSTP32("scif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), | ||
96 | SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0), | ||
97 | SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0), | ||
98 | SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), | ||
99 | SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), | ||
100 | SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), | ||
101 | SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), | ||
102 | SH_CLK_MSTP32("i2c_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 15, 0), | ||
103 | SH_CLK_MSTP32("i2c_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 14, 0), | ||
104 | SH_CLK_MSTP32("tmu9_11_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 11, 0), | ||
105 | SH_CLK_MSTP32("tmu678_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 10, 0), | ||
106 | SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), | ||
107 | SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), | ||
108 | SH_CLK_MSTP32("sdif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 5, 0), | ||
109 | SH_CLK_MSTP32("sdif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 4, 0), | ||
110 | SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), | ||
111 | |||
112 | /* MSTPCR1 */ | ||
113 | SH_CLK_MSTP32("usb_fck", -1, NULL, MSTPCR1, 12, 0), | ||
114 | SH_CLK_MSTP32("pcie_fck", 2, NULL, MSTPCR1, 10, 0), | ||
115 | SH_CLK_MSTP32("pcie_fck", 1, NULL, MSTPCR1, 9, 0), | ||
116 | SH_CLK_MSTP32("pcie_fck", 0, NULL, MSTPCR1, 8, 0), | ||
117 | SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), | ||
118 | SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), | ||
119 | SH_CLK_MSTP32("du_fck", -1, NULL, MSTPCR1, 3, 0), | ||
120 | SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0), | ||
121 | }; | 121 | }; |
122 | 122 | ||
123 | int __init arch_clk_init(void) | 123 | int __init arch_clk_init(void) |
124 | { | 124 | { |
125 | struct clk *clk; | ||
126 | int i, ret = 0; | 125 | int i, ret = 0; |
127 | 126 | ||
128 | cpg_clk_init(); | 127 | for (i = 0; i < ARRAY_SIZE(clks); i++) |
129 | 128 | ret |= clk_register(clks[i]); | |
130 | clk = clk_get(NULL, "master_clk"); | ||
131 | for (i = 0; i < ARRAY_SIZE(sh7786_onchip_clocks); i++) { | ||
132 | struct clk *clkp = sh7786_onchip_clocks[i]; | ||
133 | |||
134 | clkp->parent = clk; | ||
135 | ret |= clk_register(clkp); | ||
136 | } | ||
137 | 129 | ||
138 | clk_put(clk); | 130 | if (!ret) |
131 | ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), | ||
132 | &div4_table); | ||
133 | if (!ret) | ||
134 | ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); | ||
139 | 135 | ||
140 | return ret; | 136 | return ret; |
141 | } | 137 | } |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c index 23c27d32d982..e75c57bdfa5e 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c | |||
@@ -33,7 +33,7 @@ static int cfc_divisors[] = { 1, 1, 4, 6 }; | |||
33 | 33 | ||
34 | static void master_clk_init(struct clk *clk) | 34 | static void master_clk_init(struct clk *clk) |
35 | { | 35 | { |
36 | clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK]; | 36 | clk->rate *= pfc_divisors[(__raw_readl(FRQCR) >> PFC_POS) & PFC_MSK]; |
37 | } | 37 | } |
38 | 38 | ||
39 | static struct clk_ops shx3_master_clk_ops = { | 39 | static struct clk_ops shx3_master_clk_ops = { |
@@ -42,7 +42,7 @@ static struct clk_ops shx3_master_clk_ops = { | |||
42 | 42 | ||
43 | static unsigned long module_clk_recalc(struct clk *clk) | 43 | static unsigned long module_clk_recalc(struct clk *clk) |
44 | { | 44 | { |
45 | int idx = ((ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK); | 45 | int idx = ((__raw_readl(FRQCR) >> PFC_POS) & PFC_MSK); |
46 | return clk->parent->rate / pfc_divisors[idx]; | 46 | return clk->parent->rate / pfc_divisors[idx]; |
47 | } | 47 | } |
48 | 48 | ||
@@ -52,7 +52,7 @@ static struct clk_ops shx3_module_clk_ops = { | |||
52 | 52 | ||
53 | static unsigned long bus_clk_recalc(struct clk *clk) | 53 | static unsigned long bus_clk_recalc(struct clk *clk) |
54 | { | 54 | { |
55 | int idx = ((ctrl_inl(FRQCR) >> BFC_POS) & BFC_MSK); | 55 | int idx = ((__raw_readl(FRQCR) >> BFC_POS) & BFC_MSK); |
56 | return clk->parent->rate / bfc_divisors[idx]; | 56 | return clk->parent->rate / bfc_divisors[idx]; |
57 | } | 57 | } |
58 | 58 | ||
@@ -62,7 +62,7 @@ static struct clk_ops shx3_bus_clk_ops = { | |||
62 | 62 | ||
63 | static unsigned long cpu_clk_recalc(struct clk *clk) | 63 | static unsigned long cpu_clk_recalc(struct clk *clk) |
64 | { | 64 | { |
65 | int idx = ((ctrl_inl(FRQCR) >> IFC_POS) & IFC_MSK); | 65 | int idx = ((__raw_readl(FRQCR) >> IFC_POS) & IFC_MSK); |
66 | return clk->parent->rate / ifc_divisors[idx]; | 66 | return clk->parent->rate / ifc_divisors[idx]; |
67 | } | 67 | } |
68 | 68 | ||
@@ -85,7 +85,7 @@ void __init arch_init_clk_ops(struct clk_ops **ops, int idx) | |||
85 | 85 | ||
86 | static unsigned long shyway_clk_recalc(struct clk *clk) | 86 | static unsigned long shyway_clk_recalc(struct clk *clk) |
87 | { | 87 | { |
88 | int idx = ((ctrl_inl(FRQCR) >> CFC_POS) & CFC_MSK); | 88 | int idx = ((__raw_readl(FRQCR) >> CFC_POS) & CFC_MSK); |
89 | return clk->parent->rate / cfc_divisors[idx]; | 89 | return clk->parent->rate / cfc_divisors[idx]; |
90 | } | 90 | } |
91 | 91 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/perf_event.c b/arch/sh/kernel/cpu/sh4a/perf_event.c new file mode 100644 index 000000000000..eddc21973fa1 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/perf_event.c | |||
@@ -0,0 +1,269 @@ | |||
1 | /* | ||
2 | * Performance events support for SH-4A performance counters | ||
3 | * | ||
4 | * Copyright (C) 2009 Paul Mundt | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/perf_event.h> | ||
15 | #include <asm/processor.h> | ||
16 | |||
17 | #define PPC_CCBR(idx) (0xff200800 + (sizeof(u32) * idx)) | ||
18 | #define PPC_PMCTR(idx) (0xfc100000 + (sizeof(u32) * idx)) | ||
19 | |||
20 | #define CCBR_CIT_MASK (0x7ff << 6) | ||
21 | #define CCBR_DUC (1 << 3) | ||
22 | #define CCBR_CMDS (1 << 1) | ||
23 | #define CCBR_PPCE (1 << 0) | ||
24 | |||
25 | #define PPC_PMCAT 0xfc100080 | ||
26 | |||
27 | #define PMCAT_OVF3 (1 << 27) | ||
28 | #define PMCAT_CNN3 (1 << 26) | ||
29 | #define PMCAT_CLR3 (1 << 25) | ||
30 | #define PMCAT_OVF2 (1 << 19) | ||
31 | #define PMCAT_CLR2 (1 << 17) | ||
32 | #define PMCAT_OVF1 (1 << 11) | ||
33 | #define PMCAT_CNN1 (1 << 10) | ||
34 | #define PMCAT_CLR1 (1 << 9) | ||
35 | #define PMCAT_OVF0 (1 << 3) | ||
36 | #define PMCAT_CLR0 (1 << 1) | ||
37 | |||
38 | static struct sh_pmu sh4a_pmu; | ||
39 | |||
40 | /* | ||
41 | * Supported raw event codes: | ||
42 | * | ||
43 | * Event Code Description | ||
44 | * ---------- ----------- | ||
45 | * | ||
46 | * 0x0000 number of elapsed cycles | ||
47 | * 0x0200 number of elapsed cycles in privileged mode | ||
48 | * 0x0280 number of elapsed cycles while SR.BL is asserted | ||
49 | * 0x0202 instruction execution | ||
50 | * 0x0203 instruction execution in parallel | ||
51 | * 0x0204 number of unconditional branches | ||
52 | * 0x0208 number of exceptions | ||
53 | * 0x0209 number of interrupts | ||
54 | * 0x0220 UTLB miss caused by instruction fetch | ||
55 | * 0x0222 UTLB miss caused by operand access | ||
56 | * 0x02a0 number of ITLB misses | ||
57 | * 0x0028 number of accesses to instruction memories | ||
58 | * 0x0029 number of accesses to instruction cache | ||
59 | * 0x002a instruction cache miss | ||
60 | * 0x022e number of access to instruction X/Y memory | ||
61 | * 0x0030 number of reads to operand memories | ||
62 | * 0x0038 number of writes to operand memories | ||
63 | * 0x0031 number of operand cache read accesses | ||
64 | * 0x0039 number of operand cache write accesses | ||
65 | * 0x0032 operand cache read miss | ||
66 | * 0x003a operand cache write miss | ||
67 | * 0x0236 number of reads to operand X/Y memory | ||
68 | * 0x023e number of writes to operand X/Y memory | ||
69 | * 0x0237 number of reads to operand U memory | ||
70 | * 0x023f number of writes to operand U memory | ||
71 | * 0x0337 number of U memory read buffer misses | ||
72 | * 0x02b4 number of wait cycles due to operand read access | ||
73 | * 0x02bc number of wait cycles due to operand write access | ||
74 | * 0x0033 number of wait cycles due to operand cache read miss | ||
75 | * 0x003b number of wait cycles due to operand cache write miss | ||
76 | */ | ||
77 | |||
78 | /* | ||
79 | * Special reserved bits used by hardware emulators, read values will | ||
80 | * vary, but writes must always be 0. | ||
81 | */ | ||
82 | #define PMCAT_EMU_CLR_MASK ((1 << 24) | (1 << 16) | (1 << 8) | (1 << 0)) | ||
83 | |||
84 | static const int sh4a_general_events[] = { | ||
85 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0000, | ||
86 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x0202, | ||
87 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0029, /* I-cache */ | ||
88 | [PERF_COUNT_HW_CACHE_MISSES] = 0x002a, /* I-cache */ | ||
89 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x0204, | ||
90 | [PERF_COUNT_HW_BRANCH_MISSES] = -1, | ||
91 | [PERF_COUNT_HW_BUS_CYCLES] = -1, | ||
92 | }; | ||
93 | |||
94 | #define C(x) PERF_COUNT_HW_CACHE_##x | ||
95 | |||
96 | static const int sh4a_cache_events | ||
97 | [PERF_COUNT_HW_CACHE_MAX] | ||
98 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
99 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = | ||
100 | { | ||
101 | [ C(L1D) ] = { | ||
102 | [ C(OP_READ) ] = { | ||
103 | [ C(RESULT_ACCESS) ] = 0x0031, | ||
104 | [ C(RESULT_MISS) ] = 0x0032, | ||
105 | }, | ||
106 | [ C(OP_WRITE) ] = { | ||
107 | [ C(RESULT_ACCESS) ] = 0x0039, | ||
108 | [ C(RESULT_MISS) ] = 0x003a, | ||
109 | }, | ||
110 | [ C(OP_PREFETCH) ] = { | ||
111 | [ C(RESULT_ACCESS) ] = 0, | ||
112 | [ C(RESULT_MISS) ] = 0, | ||
113 | }, | ||
114 | }, | ||
115 | |||
116 | [ C(L1I) ] = { | ||
117 | [ C(OP_READ) ] = { | ||
118 | [ C(RESULT_ACCESS) ] = 0x0029, | ||
119 | [ C(RESULT_MISS) ] = 0x002a, | ||
120 | }, | ||
121 | [ C(OP_WRITE) ] = { | ||
122 | [ C(RESULT_ACCESS) ] = -1, | ||
123 | [ C(RESULT_MISS) ] = -1, | ||
124 | }, | ||
125 | [ C(OP_PREFETCH) ] = { | ||
126 | [ C(RESULT_ACCESS) ] = 0, | ||
127 | [ C(RESULT_MISS) ] = 0, | ||
128 | }, | ||
129 | }, | ||
130 | |||
131 | [ C(LL) ] = { | ||
132 | [ C(OP_READ) ] = { | ||
133 | [ C(RESULT_ACCESS) ] = 0x0030, | ||
134 | [ C(RESULT_MISS) ] = 0, | ||
135 | }, | ||
136 | [ C(OP_WRITE) ] = { | ||
137 | [ C(RESULT_ACCESS) ] = 0x0038, | ||
138 | [ C(RESULT_MISS) ] = 0, | ||
139 | }, | ||
140 | [ C(OP_PREFETCH) ] = { | ||
141 | [ C(RESULT_ACCESS) ] = 0, | ||
142 | [ C(RESULT_MISS) ] = 0, | ||
143 | }, | ||
144 | }, | ||
145 | |||
146 | [ C(DTLB) ] = { | ||
147 | [ C(OP_READ) ] = { | ||
148 | [ C(RESULT_ACCESS) ] = 0x0222, | ||
149 | [ C(RESULT_MISS) ] = 0x0220, | ||
150 | }, | ||
151 | [ C(OP_WRITE) ] = { | ||
152 | [ C(RESULT_ACCESS) ] = 0, | ||
153 | [ C(RESULT_MISS) ] = 0, | ||
154 | }, | ||
155 | [ C(OP_PREFETCH) ] = { | ||
156 | [ C(RESULT_ACCESS) ] = 0, | ||
157 | [ C(RESULT_MISS) ] = 0, | ||
158 | }, | ||
159 | }, | ||
160 | |||
161 | [ C(ITLB) ] = { | ||
162 | [ C(OP_READ) ] = { | ||
163 | [ C(RESULT_ACCESS) ] = 0, | ||
164 | [ C(RESULT_MISS) ] = 0x02a0, | ||
165 | }, | ||
166 | [ C(OP_WRITE) ] = { | ||
167 | [ C(RESULT_ACCESS) ] = -1, | ||
168 | [ C(RESULT_MISS) ] = -1, | ||
169 | }, | ||
170 | [ C(OP_PREFETCH) ] = { | ||
171 | [ C(RESULT_ACCESS) ] = -1, | ||
172 | [ C(RESULT_MISS) ] = -1, | ||
173 | }, | ||
174 | }, | ||
175 | |||
176 | [ C(BPU) ] = { | ||
177 | [ C(OP_READ) ] = { | ||
178 | [ C(RESULT_ACCESS) ] = -1, | ||
179 | [ C(RESULT_MISS) ] = -1, | ||
180 | }, | ||
181 | [ C(OP_WRITE) ] = { | ||
182 | [ C(RESULT_ACCESS) ] = -1, | ||
183 | [ C(RESULT_MISS) ] = -1, | ||
184 | }, | ||
185 | [ C(OP_PREFETCH) ] = { | ||
186 | [ C(RESULT_ACCESS) ] = -1, | ||
187 | [ C(RESULT_MISS) ] = -1, | ||
188 | }, | ||
189 | }, | ||
190 | }; | ||
191 | |||
192 | static int sh4a_event_map(int event) | ||
193 | { | ||
194 | return sh4a_general_events[event]; | ||
195 | } | ||
196 | |||
197 | static u64 sh4a_pmu_read(int idx) | ||
198 | { | ||
199 | return __raw_readl(PPC_PMCTR(idx)); | ||
200 | } | ||
201 | |||
202 | static void sh4a_pmu_disable(struct hw_perf_event *hwc, int idx) | ||
203 | { | ||
204 | unsigned int tmp; | ||
205 | |||
206 | tmp = __raw_readl(PPC_CCBR(idx)); | ||
207 | tmp &= ~(CCBR_CIT_MASK | CCBR_DUC); | ||
208 | __raw_writel(tmp, PPC_CCBR(idx)); | ||
209 | } | ||
210 | |||
211 | static void sh4a_pmu_enable(struct hw_perf_event *hwc, int idx) | ||
212 | { | ||
213 | unsigned int tmp; | ||
214 | |||
215 | tmp = __raw_readl(PPC_PMCAT); | ||
216 | tmp &= ~PMCAT_EMU_CLR_MASK; | ||
217 | tmp |= idx ? PMCAT_CLR1 : PMCAT_CLR0; | ||
218 | __raw_writel(tmp, PPC_PMCAT); | ||
219 | |||
220 | tmp = __raw_readl(PPC_CCBR(idx)); | ||
221 | tmp |= (hwc->config << 6) | CCBR_CMDS | CCBR_PPCE; | ||
222 | __raw_writel(tmp, PPC_CCBR(idx)); | ||
223 | |||
224 | __raw_writel(__raw_readl(PPC_CCBR(idx)) | CCBR_DUC, PPC_CCBR(idx)); | ||
225 | } | ||
226 | |||
227 | static void sh4a_pmu_disable_all(void) | ||
228 | { | ||
229 | int i; | ||
230 | |||
231 | for (i = 0; i < sh4a_pmu.num_events; i++) | ||
232 | __raw_writel(__raw_readl(PPC_CCBR(i)) & ~CCBR_DUC, PPC_CCBR(i)); | ||
233 | } | ||
234 | |||
235 | static void sh4a_pmu_enable_all(void) | ||
236 | { | ||
237 | int i; | ||
238 | |||
239 | for (i = 0; i < sh4a_pmu.num_events; i++) | ||
240 | __raw_writel(__raw_readl(PPC_CCBR(i)) | CCBR_DUC, PPC_CCBR(i)); | ||
241 | } | ||
242 | |||
243 | static struct sh_pmu sh4a_pmu = { | ||
244 | .name = "SH-4A", | ||
245 | .num_events = 2, | ||
246 | .event_map = sh4a_event_map, | ||
247 | .max_events = ARRAY_SIZE(sh4a_general_events), | ||
248 | .raw_event_mask = 0x3ff, | ||
249 | .cache_events = &sh4a_cache_events, | ||
250 | .read = sh4a_pmu_read, | ||
251 | .disable = sh4a_pmu_disable, | ||
252 | .enable = sh4a_pmu_enable, | ||
253 | .disable_all = sh4a_pmu_disable_all, | ||
254 | .enable_all = sh4a_pmu_enable_all, | ||
255 | }; | ||
256 | |||
257 | static int __init sh4a_pmu_init(void) | ||
258 | { | ||
259 | /* | ||
260 | * Make sure this CPU actually has perf counters. | ||
261 | */ | ||
262 | if (!(boot_cpu_data.flags & CPU_HAS_PERF_COUNTER)) { | ||
263 | pr_notice("HW perf events unsupported, software events only.\n"); | ||
264 | return -ENODEV; | ||
265 | } | ||
266 | |||
267 | return register_sh_pmu(&sh4a_pmu); | ||
268 | } | ||
269 | arch_initcall(sh4a_pmu_init); | ||
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c index cb9d07bd59f8..0688a7502f86 100644 --- a/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c | |||
@@ -278,6 +278,7 @@ enum { | |||
278 | HIZA8_LCDC, HIZA8_HIZ, | 278 | HIZA8_LCDC, HIZA8_HIZ, |
279 | HIZA7_LCDC, HIZA7_HIZ, | 279 | HIZA7_LCDC, HIZA7_HIZ, |
280 | HIZA6_LCDC, HIZA6_HIZ, | 280 | HIZA6_LCDC, HIZA6_HIZ, |
281 | HIZB4_SIUA, HIZB4_HIZ, | ||
281 | HIZB1_VIO, HIZB1_HIZ, | 282 | HIZB1_VIO, HIZB1_HIZ, |
282 | HIZB0_VIO, HIZB0_HIZ, | 283 | HIZB0_VIO, HIZB0_HIZ, |
283 | HIZC15_IRQ7, HIZC15_HIZ, | 284 | HIZC15_IRQ7, HIZC15_HIZ, |
@@ -546,7 +547,7 @@ static pinmux_enum_t pinmux_data[] = { | |||
546 | PINMUX_DATA(VIO_VD2_MARK, PSE3_VIO, MSELB9_VIO2, | 547 | PINMUX_DATA(VIO_VD2_MARK, PSE3_VIO, MSELB9_VIO2, |
547 | HIZB0_VIO, FOE_VIO_VD2), | 548 | HIZB0_VIO, FOE_VIO_VD2), |
548 | PINMUX_DATA(VIO_HD2_MARK, PSE3_VIO, MSELB9_VIO2, | 549 | PINMUX_DATA(VIO_HD2_MARK, PSE3_VIO, MSELB9_VIO2, |
549 | HIZB1_VIO, HIZB1_VIO, FCE_VIO_HD2), | 550 | HIZB1_VIO, FCE_VIO_HD2), |
550 | PINMUX_DATA(VIO_CLK2_MARK, PSE3_VIO, MSELB9_VIO2, | 551 | PINMUX_DATA(VIO_CLK2_MARK, PSE3_VIO, MSELB9_VIO2, |
551 | HIZB1_VIO, FRB_VIO_CLK2), | 552 | HIZB1_VIO, FRB_VIO_CLK2), |
552 | 553 | ||
@@ -658,14 +659,14 @@ static pinmux_enum_t pinmux_data[] = { | |||
658 | PINMUX_DATA(SDHICLK_MARK, SDHICLK), | 659 | PINMUX_DATA(SDHICLK_MARK, SDHICLK), |
659 | 660 | ||
660 | /* SIU - Port A */ | 661 | /* SIU - Port A */ |
661 | PINMUX_DATA(SIUAOLR_MARK, PSC13_SIUAOLR, SIUAOLR_SIOF1_SYNC), | 662 | PINMUX_DATA(SIUAOLR_MARK, PSC13_SIUAOLR, HIZB4_SIUA, SIUAOLR_SIOF1_SYNC), |
662 | PINMUX_DATA(SIUAOBT_MARK, PSC14_SIUAOBT, SIUAOBT_SIOF1_SCK), | 663 | PINMUX_DATA(SIUAOBT_MARK, PSC14_SIUAOBT, HIZB4_SIUA, SIUAOBT_SIOF1_SCK), |
663 | PINMUX_DATA(SIUAISLD_MARK, PSC15_SIUAISLD, SIUAISLD_SIOF1_RXD), | 664 | PINMUX_DATA(SIUAISLD_MARK, PSC15_SIUAISLD, HIZB4_SIUA, SIUAISLD_SIOF1_RXD), |
664 | PINMUX_DATA(SIUAILR_MARK, PSC11_SIUAILR, SIUAILR_SIOF1_SS2), | 665 | PINMUX_DATA(SIUAILR_MARK, PSC11_SIUAILR, HIZB4_SIUA, SIUAILR_SIOF1_SS2), |
665 | PINMUX_DATA(SIUAIBT_MARK, PSC12_SIUAIBT, SIUAIBT_SIOF1_SS1), | 666 | PINMUX_DATA(SIUAIBT_MARK, PSC12_SIUAIBT, HIZB4_SIUA, SIUAIBT_SIOF1_SS1), |
666 | PINMUX_DATA(SIUAOSLD_MARK, PSB0_SIUAOSLD, SIUAOSLD_SIOF1_TXD), | 667 | PINMUX_DATA(SIUAOSLD_MARK, PSB0_SIUAOSLD, HIZB4_SIUA, SIUAOSLD_SIOF1_TXD), |
667 | PINMUX_DATA(SIUMCKA_MARK, PSE11_SIUMCKA_SIOF1_MCK, PSB1_SIUMCKA, PTK0), | 668 | PINMUX_DATA(SIUMCKA_MARK, PSE11_SIUMCKA_SIOF1_MCK, HIZB4_SIUA, PSB1_SIUMCKA, PTK0), |
668 | PINMUX_DATA(SIUFCKA_MARK, PSE11_SIUFCKA, PTK0), | 669 | PINMUX_DATA(SIUFCKA_MARK, PSE11_SIUFCKA, HIZB4_SIUA, PTK0), |
669 | 670 | ||
670 | /* SIU - Port B */ | 671 | /* SIU - Port B */ |
671 | PINMUX_DATA(SIUBOLR_MARK, PSB11_SIUBOLR, SIOSTRB1_SIUBOLR), | 672 | PINMUX_DATA(SIUBOLR_MARK, PSB11_SIUBOLR, SIOSTRB1_SIUBOLR), |
@@ -1612,7 +1613,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = { | |||
1612 | 0, 0, | 1613 | 0, 0, |
1613 | 0, 0, | 1614 | 0, 0, |
1614 | 0, 0, | 1615 | 0, 0, |
1615 | 0, 0, | 1616 | HIZB4_SIUA, HIZB4_HIZ, |
1616 | 0, 0, | 1617 | 0, 0, |
1617 | 0, 0, | 1618 | 0, 0, |
1618 | HIZB1_VIO, HIZB1_HIZ, | 1619 | HIZB1_VIO, HIZB1_HIZ, |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index ac4d5672ec1a..45eb1bfd42c9 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c | |||
@@ -15,6 +15,71 @@ | |||
15 | #include <linux/sh_timer.h> | 15 | #include <linux/sh_timer.h> |
16 | #include <asm/clock.h> | 16 | #include <asm/clock.h> |
17 | 17 | ||
18 | /* Serial */ | ||
19 | static struct plat_sci_port scif0_platform_data = { | ||
20 | .mapbase = 0xffe00000, | ||
21 | .flags = UPF_BOOT_AUTOCONF, | ||
22 | .type = PORT_SCIF, | ||
23 | .irqs = { 80, 80, 80, 80 }, | ||
24 | .clk = "scif0", | ||
25 | }; | ||
26 | |||
27 | static struct platform_device scif0_device = { | ||
28 | .name = "sh-sci", | ||
29 | .id = 0, | ||
30 | .dev = { | ||
31 | .platform_data = &scif0_platform_data, | ||
32 | }, | ||
33 | }; | ||
34 | |||
35 | static struct plat_sci_port scif1_platform_data = { | ||
36 | .mapbase = 0xffe10000, | ||
37 | .flags = UPF_BOOT_AUTOCONF, | ||
38 | .type = PORT_SCIF, | ||
39 | .irqs = { 81, 81, 81, 81 }, | ||
40 | .clk = "scif1", | ||
41 | }; | ||
42 | |||
43 | static struct platform_device scif1_device = { | ||
44 | .name = "sh-sci", | ||
45 | .id = 1, | ||
46 | .dev = { | ||
47 | .platform_data = &scif1_platform_data, | ||
48 | }, | ||
49 | }; | ||
50 | |||
51 | static struct plat_sci_port scif2_platform_data = { | ||
52 | .mapbase = 0xffe20000, | ||
53 | .flags = UPF_BOOT_AUTOCONF, | ||
54 | .type = PORT_SCIF, | ||
55 | .irqs = { 82, 82, 82, 82 }, | ||
56 | .clk = "scif2", | ||
57 | }; | ||
58 | |||
59 | static struct platform_device scif2_device = { | ||
60 | .name = "sh-sci", | ||
61 | .id = 2, | ||
62 | .dev = { | ||
63 | .platform_data = &scif2_platform_data, | ||
64 | }, | ||
65 | }; | ||
66 | |||
67 | static struct plat_sci_port scif3_platform_data = { | ||
68 | .mapbase = 0xffe30000, | ||
69 | .flags = UPF_BOOT_AUTOCONF, | ||
70 | .type = PORT_SCIF, | ||
71 | .irqs = { 83, 83, 83, 83 }, | ||
72 | .clk = "scif3", | ||
73 | }; | ||
74 | |||
75 | static struct platform_device scif3_device = { | ||
76 | .name = "sh-sci", | ||
77 | .id = 3, | ||
78 | .dev = { | ||
79 | .platform_data = &scif3_platform_data, | ||
80 | }, | ||
81 | }; | ||
82 | |||
18 | static struct resource iic0_resources[] = { | 83 | static struct resource iic0_resources[] = { |
19 | [0] = { | 84 | [0] = { |
20 | .name = "IIC0", | 85 | .name = "IIC0", |
@@ -265,52 +330,17 @@ static struct platform_device tmu2_device = { | |||
265 | .num_resources = ARRAY_SIZE(tmu2_resources), | 330 | .num_resources = ARRAY_SIZE(tmu2_resources), |
266 | }; | 331 | }; |
267 | 332 | ||
268 | static struct plat_sci_port sci_platform_data[] = { | ||
269 | { | ||
270 | .mapbase = 0xffe00000, | ||
271 | .flags = UPF_BOOT_AUTOCONF, | ||
272 | .type = PORT_SCIF, | ||
273 | .irqs = { 80, 80, 80, 80 }, | ||
274 | .clk = "scif0", | ||
275 | }, { | ||
276 | .mapbase = 0xffe10000, | ||
277 | .flags = UPF_BOOT_AUTOCONF, | ||
278 | .type = PORT_SCIF, | ||
279 | .irqs = { 81, 81, 81, 81 }, | ||
280 | .clk = "scif1", | ||
281 | }, { | ||
282 | .mapbase = 0xffe20000, | ||
283 | .flags = UPF_BOOT_AUTOCONF, | ||
284 | .type = PORT_SCIF, | ||
285 | .irqs = { 82, 82, 82, 82 }, | ||
286 | .clk = "scif2", | ||
287 | }, { | ||
288 | .mapbase = 0xffe30000, | ||
289 | .flags = UPF_BOOT_AUTOCONF, | ||
290 | .type = PORT_SCIF, | ||
291 | .irqs = { 83, 83, 83, 83 }, | ||
292 | .clk = "scif3", | ||
293 | }, { | ||
294 | .flags = 0, | ||
295 | } | ||
296 | }; | ||
297 | |||
298 | static struct platform_device sci_device = { | ||
299 | .name = "sh-sci", | ||
300 | .id = -1, | ||
301 | .dev = { | ||
302 | .platform_data = sci_platform_data, | ||
303 | }, | ||
304 | }; | ||
305 | |||
306 | static struct platform_device *sh7343_devices[] __initdata = { | 333 | static struct platform_device *sh7343_devices[] __initdata = { |
334 | &scif0_device, | ||
335 | &scif1_device, | ||
336 | &scif2_device, | ||
337 | &scif3_device, | ||
307 | &cmt_device, | 338 | &cmt_device, |
308 | &tmu0_device, | 339 | &tmu0_device, |
309 | &tmu1_device, | 340 | &tmu1_device, |
310 | &tmu2_device, | 341 | &tmu2_device, |
311 | &iic0_device, | 342 | &iic0_device, |
312 | &iic1_device, | 343 | &iic1_device, |
313 | &sci_device, | ||
314 | &vpu_device, | 344 | &vpu_device, |
315 | &veu_device, | 345 | &veu_device, |
316 | &jpu_device, | 346 | &jpu_device, |
@@ -328,6 +358,10 @@ static int __init sh7343_devices_setup(void) | |||
328 | arch_initcall(sh7343_devices_setup); | 358 | arch_initcall(sh7343_devices_setup); |
329 | 359 | ||
330 | static struct platform_device *sh7343_early_devices[] __initdata = { | 360 | static struct platform_device *sh7343_early_devices[] __initdata = { |
361 | &scif0_device, | ||
362 | &scif1_device, | ||
363 | &scif2_device, | ||
364 | &scif3_device, | ||
331 | &cmt_device, | 365 | &cmt_device, |
332 | &tmu0_device, | 366 | &tmu0_device, |
333 | &tmu1_device, | 367 | &tmu1_device, |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index 4a9010bf4fd3..c494c193e3b6 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c | |||
@@ -18,6 +18,22 @@ | |||
18 | #include <linux/usb/r8a66597.h> | 18 | #include <linux/usb/r8a66597.h> |
19 | #include <asm/clock.h> | 19 | #include <asm/clock.h> |
20 | 20 | ||
21 | static struct plat_sci_port scif0_platform_data = { | ||
22 | .mapbase = 0xffe00000, | ||
23 | .flags = UPF_BOOT_AUTOCONF, | ||
24 | .type = PORT_SCIF, | ||
25 | .irqs = { 80, 80, 80, 80 }, | ||
26 | .clk = "scif0", | ||
27 | }; | ||
28 | |||
29 | static struct platform_device scif0_device = { | ||
30 | .name = "sh-sci", | ||
31 | .id = 0, | ||
32 | .dev = { | ||
33 | .platform_data = &scif0_platform_data, | ||
34 | }, | ||
35 | }; | ||
36 | |||
21 | static struct resource iic_resources[] = { | 37 | static struct resource iic_resources[] = { |
22 | [0] = { | 38 | [0] = { |
23 | .name = "IIC", | 39 | .name = "IIC", |
@@ -276,33 +292,13 @@ static struct platform_device tmu2_device = { | |||
276 | .num_resources = ARRAY_SIZE(tmu2_resources), | 292 | .num_resources = ARRAY_SIZE(tmu2_resources), |
277 | }; | 293 | }; |
278 | 294 | ||
279 | static struct plat_sci_port sci_platform_data[] = { | ||
280 | { | ||
281 | .mapbase = 0xffe00000, | ||
282 | .flags = UPF_BOOT_AUTOCONF, | ||
283 | .type = PORT_SCIF, | ||
284 | .irqs = { 80, 80, 80, 80 }, | ||
285 | .clk = "scif0", | ||
286 | }, { | ||
287 | .flags = 0, | ||
288 | } | ||
289 | }; | ||
290 | |||
291 | static struct platform_device sci_device = { | ||
292 | .name = "sh-sci", | ||
293 | .id = -1, | ||
294 | .dev = { | ||
295 | .platform_data = sci_platform_data, | ||
296 | }, | ||
297 | }; | ||
298 | |||
299 | static struct platform_device *sh7366_devices[] __initdata = { | 295 | static struct platform_device *sh7366_devices[] __initdata = { |
296 | &scif0_device, | ||
300 | &cmt_device, | 297 | &cmt_device, |
301 | &tmu0_device, | 298 | &tmu0_device, |
302 | &tmu1_device, | 299 | &tmu1_device, |
303 | &tmu2_device, | 300 | &tmu2_device, |
304 | &iic_device, | 301 | &iic_device, |
305 | &sci_device, | ||
306 | &usb_host_device, | 302 | &usb_host_device, |
307 | &vpu_device, | 303 | &vpu_device, |
308 | &veu0_device, | 304 | &veu0_device, |
@@ -321,6 +317,7 @@ static int __init sh7366_devices_setup(void) | |||
321 | arch_initcall(sh7366_devices_setup); | 317 | arch_initcall(sh7366_devices_setup); |
322 | 318 | ||
323 | static struct platform_device *sh7366_early_devices[] __initdata = { | 319 | static struct platform_device *sh7366_early_devices[] __initdata = { |
320 | &scif0_device, | ||
324 | &cmt_device, | 321 | &cmt_device, |
325 | &tmu0_device, | 322 | &tmu0_device, |
326 | &tmu1_device, | 323 | &tmu1_device, |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 5491b094cf05..fd7e3639e845 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c | |||
@@ -7,19 +7,216 @@ | |||
7 | * License. See the file "COPYING" in the main directory of this archive | 7 | * License. See the file "COPYING" in the main directory of this archive |
8 | * for more details. | 8 | * for more details. |
9 | */ | 9 | */ |
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/mm.h> | ||
12 | #include <linux/platform_device.h> | ||
12 | #include <linux/serial.h> | 13 | #include <linux/serial.h> |
13 | #include <linux/serial_sci.h> | 14 | #include <linux/serial_sci.h> |
14 | #include <linux/mm.h> | 15 | #include <linux/sh_timer.h> |
15 | #include <linux/uio_driver.h> | 16 | #include <linux/uio_driver.h> |
16 | #include <linux/usb/m66592.h> | 17 | #include <linux/usb/m66592.h> |
17 | #include <linux/sh_timer.h> | 18 | |
18 | #include <asm/clock.h> | 19 | #include <asm/clock.h> |
20 | #include <asm/dmaengine.h> | ||
19 | #include <asm/mmzone.h> | 21 | #include <asm/mmzone.h> |
20 | #include <asm/dma-sh.h> | 22 | #include <asm/siu.h> |
23 | |||
24 | #include <cpu/dma-register.h> | ||
21 | #include <cpu/sh7722.h> | 25 | #include <cpu/sh7722.h> |
22 | 26 | ||
27 | static struct sh_dmae_slave_config sh7722_dmae_slaves[] = { | ||
28 | { | ||
29 | .slave_id = SHDMA_SLAVE_SCIF0_TX, | ||
30 | .addr = 0xffe0000c, | ||
31 | .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), | ||
32 | .mid_rid = 0x21, | ||
33 | }, { | ||
34 | .slave_id = SHDMA_SLAVE_SCIF0_RX, | ||
35 | .addr = 0xffe00014, | ||
36 | .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), | ||
37 | .mid_rid = 0x22, | ||
38 | }, { | ||
39 | .slave_id = SHDMA_SLAVE_SCIF1_TX, | ||
40 | .addr = 0xffe1000c, | ||
41 | .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), | ||
42 | .mid_rid = 0x25, | ||
43 | }, { | ||
44 | .slave_id = SHDMA_SLAVE_SCIF1_RX, | ||
45 | .addr = 0xffe10014, | ||
46 | .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), | ||
47 | .mid_rid = 0x26, | ||
48 | }, { | ||
49 | .slave_id = SHDMA_SLAVE_SCIF2_TX, | ||
50 | .addr = 0xffe2000c, | ||
51 | .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), | ||
52 | .mid_rid = 0x29, | ||
53 | }, { | ||
54 | .slave_id = SHDMA_SLAVE_SCIF2_RX, | ||
55 | .addr = 0xffe20014, | ||
56 | .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), | ||
57 | .mid_rid = 0x2a, | ||
58 | }, { | ||
59 | .slave_id = SHDMA_SLAVE_SIUA_TX, | ||
60 | .addr = 0xa454c098, | ||
61 | .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), | ||
62 | .mid_rid = 0xb1, | ||
63 | }, { | ||
64 | .slave_id = SHDMA_SLAVE_SIUA_RX, | ||
65 | .addr = 0xa454c090, | ||
66 | .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), | ||
67 | .mid_rid = 0xb2, | ||
68 | }, { | ||
69 | .slave_id = SHDMA_SLAVE_SIUB_TX, | ||
70 | .addr = 0xa454c09c, | ||
71 | .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), | ||
72 | .mid_rid = 0xb5, | ||
73 | }, { | ||
74 | .slave_id = SHDMA_SLAVE_SIUB_RX, | ||
75 | .addr = 0xa454c094, | ||
76 | .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), | ||
77 | .mid_rid = 0xb6, | ||
78 | }, | ||
79 | }; | ||
80 | |||
81 | static struct sh_dmae_channel sh7722_dmae_channels[] = { | ||
82 | { | ||
83 | .offset = 0, | ||
84 | .dmars = 0, | ||
85 | .dmars_bit = 0, | ||
86 | }, { | ||
87 | .offset = 0x10, | ||
88 | .dmars = 0, | ||
89 | .dmars_bit = 8, | ||
90 | }, { | ||
91 | .offset = 0x20, | ||
92 | .dmars = 4, | ||
93 | .dmars_bit = 0, | ||
94 | }, { | ||
95 | .offset = 0x30, | ||
96 | .dmars = 4, | ||
97 | .dmars_bit = 8, | ||
98 | }, { | ||
99 | .offset = 0x50, | ||
100 | .dmars = 8, | ||
101 | .dmars_bit = 0, | ||
102 | }, { | ||
103 | .offset = 0x60, | ||
104 | .dmars = 8, | ||
105 | .dmars_bit = 8, | ||
106 | } | ||
107 | }; | ||
108 | |||
109 | static unsigned int ts_shift[] = TS_SHIFT; | ||
110 | |||
111 | static struct sh_dmae_pdata dma_platform_data = { | ||
112 | .slave = sh7722_dmae_slaves, | ||
113 | .slave_num = ARRAY_SIZE(sh7722_dmae_slaves), | ||
114 | .channel = sh7722_dmae_channels, | ||
115 | .channel_num = ARRAY_SIZE(sh7722_dmae_channels), | ||
116 | .ts_low_shift = CHCR_TS_LOW_SHIFT, | ||
117 | .ts_low_mask = CHCR_TS_LOW_MASK, | ||
118 | .ts_high_shift = CHCR_TS_HIGH_SHIFT, | ||
119 | .ts_high_mask = CHCR_TS_HIGH_MASK, | ||
120 | .ts_shift = ts_shift, | ||
121 | .ts_shift_num = ARRAY_SIZE(ts_shift), | ||
122 | .dmaor_init = DMAOR_INIT, | ||
123 | }; | ||
124 | |||
125 | static struct resource sh7722_dmae_resources[] = { | ||
126 | [0] = { | ||
127 | /* Channel registers and DMAOR */ | ||
128 | .start = 0xfe008020, | ||
129 | .end = 0xfe00808f, | ||
130 | .flags = IORESOURCE_MEM, | ||
131 | }, | ||
132 | [1] = { | ||
133 | /* DMARSx */ | ||
134 | .start = 0xfe009000, | ||
135 | .end = 0xfe00900b, | ||
136 | .flags = IORESOURCE_MEM, | ||
137 | }, | ||
138 | { | ||
139 | /* DMA error IRQ */ | ||
140 | .start = 78, | ||
141 | .end = 78, | ||
142 | .flags = IORESOURCE_IRQ, | ||
143 | }, | ||
144 | { | ||
145 | /* IRQ for channels 0-3 */ | ||
146 | .start = 48, | ||
147 | .end = 51, | ||
148 | .flags = IORESOURCE_IRQ, | ||
149 | }, | ||
150 | { | ||
151 | /* IRQ for channels 4-5 */ | ||
152 | .start = 76, | ||
153 | .end = 77, | ||
154 | .flags = IORESOURCE_IRQ, | ||
155 | }, | ||
156 | }; | ||
157 | |||
158 | struct platform_device dma_device = { | ||
159 | .name = "sh-dma-engine", | ||
160 | .id = -1, | ||
161 | .resource = sh7722_dmae_resources, | ||
162 | .num_resources = ARRAY_SIZE(sh7722_dmae_resources), | ||
163 | .dev = { | ||
164 | .platform_data = &dma_platform_data, | ||
165 | }, | ||
166 | .archdata = { | ||
167 | .hwblk_id = HWBLK_DMAC, | ||
168 | }, | ||
169 | }; | ||
170 | |||
171 | /* Serial */ | ||
172 | static struct plat_sci_port scif0_platform_data = { | ||
173 | .mapbase = 0xffe00000, | ||
174 | .flags = UPF_BOOT_AUTOCONF, | ||
175 | .type = PORT_SCIF, | ||
176 | .irqs = { 80, 80, 80, 80 }, | ||
177 | .clk = "scif0", | ||
178 | }; | ||
179 | |||
180 | static struct platform_device scif0_device = { | ||
181 | .name = "sh-sci", | ||
182 | .id = 0, | ||
183 | .dev = { | ||
184 | .platform_data = &scif0_platform_data, | ||
185 | }, | ||
186 | }; | ||
187 | |||
188 | static struct plat_sci_port scif1_platform_data = { | ||
189 | .mapbase = 0xffe10000, | ||
190 | .flags = UPF_BOOT_AUTOCONF, | ||
191 | .type = PORT_SCIF, | ||
192 | .irqs = { 81, 81, 81, 81 }, | ||
193 | .clk = "scif1", | ||
194 | }; | ||
195 | |||
196 | static struct platform_device scif1_device = { | ||
197 | .name = "sh-sci", | ||
198 | .id = 1, | ||
199 | .dev = { | ||
200 | .platform_data = &scif1_platform_data, | ||
201 | }, | ||
202 | }; | ||
203 | |||
204 | static struct plat_sci_port scif2_platform_data = { | ||
205 | .mapbase = 0xffe20000, | ||
206 | .flags = UPF_BOOT_AUTOCONF, | ||
207 | .type = PORT_SCIF, | ||
208 | .irqs = { 82, 82, 82, 82 }, | ||
209 | .clk = "scif2", | ||
210 | }; | ||
211 | |||
212 | static struct platform_device scif2_device = { | ||
213 | .name = "sh-sci", | ||
214 | .id = 2, | ||
215 | .dev = { | ||
216 | .platform_data = &scif2_platform_data, | ||
217 | }, | ||
218 | }; | ||
219 | |||
23 | static struct resource rtc_resources[] = { | 220 | static struct resource rtc_resources[] = { |
24 | [0] = { | 221 | [0] = { |
25 | .start = 0xa465fec0, | 222 | .start = 0xa465fec0, |
@@ -339,54 +536,43 @@ static struct platform_device tmu2_device = { | |||
339 | }, | 536 | }, |
340 | }; | 537 | }; |
341 | 538 | ||
342 | static struct plat_sci_port sci_platform_data[] = { | 539 | static struct siu_platform siu_platform_data = { |
343 | { | 540 | .dma_dev = &dma_device.dev, |
344 | .mapbase = 0xffe00000, | 541 | .dma_slave_tx_a = SHDMA_SLAVE_SIUA_TX, |
345 | .flags = UPF_BOOT_AUTOCONF, | 542 | .dma_slave_rx_a = SHDMA_SLAVE_SIUA_RX, |
346 | .type = PORT_SCIF, | 543 | .dma_slave_tx_b = SHDMA_SLAVE_SIUB_TX, |
347 | .irqs = { 80, 80, 80, 80 }, | 544 | .dma_slave_rx_b = SHDMA_SLAVE_SIUB_RX, |
348 | .clk = "scif0", | ||
349 | }, | ||
350 | { | ||
351 | .mapbase = 0xffe10000, | ||
352 | .flags = UPF_BOOT_AUTOCONF, | ||
353 | .type = PORT_SCIF, | ||
354 | .irqs = { 81, 81, 81, 81 }, | ||
355 | .clk = "scif1", | ||
356 | }, | ||
357 | { | ||
358 | .mapbase = 0xffe20000, | ||
359 | .flags = UPF_BOOT_AUTOCONF, | ||
360 | .type = PORT_SCIF, | ||
361 | .irqs = { 82, 82, 82, 82 }, | ||
362 | .clk = "scif2", | ||
363 | }, | ||
364 | { | ||
365 | .flags = 0, | ||
366 | } | ||
367 | }; | 545 | }; |
368 | 546 | ||
369 | static struct platform_device sci_device = { | 547 | static struct resource siu_resources[] = { |
370 | .name = "sh-sci", | 548 | [0] = { |
371 | .id = -1, | 549 | .start = 0xa4540000, |
372 | .dev = { | 550 | .end = 0xa454c10f, |
373 | .platform_data = sci_platform_data, | 551 | .flags = IORESOURCE_MEM, |
552 | }, | ||
553 | [1] = { | ||
554 | .start = 108, | ||
555 | .flags = IORESOURCE_IRQ, | ||
374 | }, | 556 | }, |
375 | }; | 557 | }; |
376 | 558 | ||
377 | static struct sh_dmae_pdata dma_platform_data = { | 559 | static struct platform_device siu_device = { |
378 | .mode = 0, | 560 | .name = "sh_siu", |
379 | }; | ||
380 | |||
381 | static struct platform_device dma_device = { | ||
382 | .name = "sh-dma-engine", | ||
383 | .id = -1, | 561 | .id = -1, |
384 | .dev = { | 562 | .dev = { |
385 | .platform_data = &dma_platform_data, | 563 | .platform_data = &siu_platform_data, |
564 | }, | ||
565 | .resource = siu_resources, | ||
566 | .num_resources = ARRAY_SIZE(siu_resources), | ||
567 | .archdata = { | ||
568 | .hwblk_id = HWBLK_SIU, | ||
386 | }, | 569 | }, |
387 | }; | 570 | }; |
388 | 571 | ||
389 | static struct platform_device *sh7722_devices[] __initdata = { | 572 | static struct platform_device *sh7722_devices[] __initdata = { |
573 | &scif0_device, | ||
574 | &scif1_device, | ||
575 | &scif2_device, | ||
390 | &cmt_device, | 576 | &cmt_device, |
391 | &tmu0_device, | 577 | &tmu0_device, |
392 | &tmu1_device, | 578 | &tmu1_device, |
@@ -394,10 +580,10 @@ static struct platform_device *sh7722_devices[] __initdata = { | |||
394 | &rtc_device, | 580 | &rtc_device, |
395 | &usbf_device, | 581 | &usbf_device, |
396 | &iic_device, | 582 | &iic_device, |
397 | &sci_device, | ||
398 | &vpu_device, | 583 | &vpu_device, |
399 | &veu_device, | 584 | &veu_device, |
400 | &jpu_device, | 585 | &jpu_device, |
586 | &siu_device, | ||
401 | &dma_device, | 587 | &dma_device, |
402 | }; | 588 | }; |
403 | 589 | ||
@@ -413,6 +599,9 @@ static int __init sh7722_devices_setup(void) | |||
413 | arch_initcall(sh7722_devices_setup); | 599 | arch_initcall(sh7722_devices_setup); |
414 | 600 | ||
415 | static struct platform_device *sh7722_early_devices[] __initdata = { | 601 | static struct platform_device *sh7722_early_devices[] __initdata = { |
602 | &scif0_device, | ||
603 | &scif1_device, | ||
604 | &scif2_device, | ||
416 | &cmt_device, | 605 | &cmt_device, |
417 | &tmu0_device, | 606 | &tmu0_device, |
418 | &tmu1_device, | 607 | &tmu1_device, |
@@ -427,6 +616,8 @@ void __init plat_early_device_setup(void) | |||
427 | 616 | ||
428 | enum { | 617 | enum { |
429 | UNUSED=0, | 618 | UNUSED=0, |
619 | ENABLED, | ||
620 | DISABLED, | ||
430 | 621 | ||
431 | /* interrupt sources */ | 622 | /* interrupt sources */ |
432 | IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, | 623 | IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, |
@@ -442,7 +633,6 @@ enum { | |||
442 | SCIF0, SCIF1, SCIF2, SIOF0, SIOF1, SIO, | 633 | SCIF0, SCIF1, SCIF2, SIOF0, SIOF1, SIO, |
443 | FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, | 634 | FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, |
444 | I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI, | 635 | I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI, |
445 | SDHI0, SDHI1, SDHI2, SDHI3, | ||
446 | CMT, TSIF, SIU, TWODG, | 636 | CMT, TSIF, SIU, TWODG, |
447 | TMU0, TMU1, TMU2, | 637 | TMU0, TMU1, TMU2, |
448 | IRDA, JPU, LCDC, | 638 | IRDA, JPU, LCDC, |
@@ -475,8 +665,8 @@ static struct intc_vect vectors[] __initdata = { | |||
475 | INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0), | 665 | INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0), |
476 | INTC_VECT(I2C_ALI, 0xe00), INTC_VECT(I2C_TACKI, 0xe20), | 666 | INTC_VECT(I2C_ALI, 0xe00), INTC_VECT(I2C_TACKI, 0xe20), |
477 | INTC_VECT(I2C_WAITI, 0xe40), INTC_VECT(I2C_DTEI, 0xe60), | 667 | INTC_VECT(I2C_WAITI, 0xe40), INTC_VECT(I2C_DTEI, 0xe60), |
478 | INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0), | 668 | INTC_VECT(SDHI, 0xe80), INTC_VECT(SDHI, 0xea0), |
479 | INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0), | 669 | INTC_VECT(SDHI, 0xec0), INTC_VECT(SDHI, 0xee0), |
480 | INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20), | 670 | INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20), |
481 | INTC_VECT(SIU, 0xf80), INTC_VECT(TWODG, 0xfa0), | 671 | INTC_VECT(SIU, 0xf80), INTC_VECT(TWODG, 0xfa0), |
482 | INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420), | 672 | INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420), |
@@ -494,7 +684,6 @@ static struct intc_group groups[] __initdata = { | |||
494 | INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLENDI, | 684 | INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLENDI, |
495 | FLCTL_FLTREQ0I, FLCTL_FLTREQ1I), | 685 | FLCTL_FLTREQ0I, FLCTL_FLTREQ1I), |
496 | INTC_GROUP(I2C, I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI), | 686 | INTC_GROUP(I2C, I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI), |
497 | INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3), | ||
498 | }; | 687 | }; |
499 | 688 | ||
500 | static struct intc_mask_reg mask_registers[] __initdata = { | 689 | static struct intc_mask_reg mask_registers[] __initdata = { |
@@ -516,7 +705,7 @@ static struct intc_mask_reg mask_registers[] __initdata = { | |||
516 | { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI, | 705 | { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI, |
517 | FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } }, | 706 | FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } }, |
518 | { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */ | 707 | { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */ |
519 | { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, TWODG, SIU } }, | 708 | { DISABLED, DISABLED, ENABLED, ENABLED, 0, 0, TWODG, SIU } }, |
520 | { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */ | 709 | { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */ |
521 | { 0, 0, 0, CMT, 0, USB_USBI1, USB_USBI0, } }, | 710 | { 0, 0, 0, CMT, 0, USB_USBI1, USB_USBI0, } }, |
522 | { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */ | 711 | { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */ |
@@ -554,9 +743,13 @@ static struct intc_mask_reg ack_registers[] __initdata = { | |||
554 | { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, | 743 | { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, |
555 | }; | 744 | }; |
556 | 745 | ||
557 | static DECLARE_INTC_DESC_ACK(intc_desc, "sh7722", vectors, groups, | 746 | static struct intc_desc intc_desc __initdata = { |
558 | mask_registers, prio_registers, sense_registers, | 747 | .name = "sh7722", |
559 | ack_registers); | 748 | .force_enable = ENABLED, |
749 | .force_disable = DISABLED, | ||
750 | .hw = INTC_HW_DESC(vectors, groups, mask_registers, | ||
751 | prio_registers, sense_registers, ack_registers), | ||
752 | }; | ||
560 | 753 | ||
561 | void __init plat_irq_setup(void) | 754 | void __init plat_irq_setup(void) |
562 | { | 755 | { |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 4caa5a7ca86e..85c61f624702 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c | |||
@@ -20,6 +20,103 @@ | |||
20 | #include <asm/mmzone.h> | 20 | #include <asm/mmzone.h> |
21 | #include <cpu/sh7723.h> | 21 | #include <cpu/sh7723.h> |
22 | 22 | ||
23 | /* Serial */ | ||
24 | static struct plat_sci_port scif0_platform_data = { | ||
25 | .mapbase = 0xffe00000, | ||
26 | .flags = UPF_BOOT_AUTOCONF, | ||
27 | .type = PORT_SCIF, | ||
28 | .irqs = { 80, 80, 80, 80 }, | ||
29 | .clk = "scif0", | ||
30 | }; | ||
31 | |||
32 | static struct platform_device scif0_device = { | ||
33 | .name = "sh-sci", | ||
34 | .id = 0, | ||
35 | .dev = { | ||
36 | .platform_data = &scif0_platform_data, | ||
37 | }, | ||
38 | }; | ||
39 | |||
40 | static struct plat_sci_port scif1_platform_data = { | ||
41 | .mapbase = 0xffe10000, | ||
42 | .flags = UPF_BOOT_AUTOCONF, | ||
43 | .type = PORT_SCIF, | ||
44 | .irqs = { 81, 81, 81, 81 }, | ||
45 | .clk = "scif1", | ||
46 | }; | ||
47 | |||
48 | static struct platform_device scif1_device = { | ||
49 | .name = "sh-sci", | ||
50 | .id = 1, | ||
51 | .dev = { | ||
52 | .platform_data = &scif1_platform_data, | ||
53 | }, | ||
54 | }; | ||
55 | |||
56 | static struct plat_sci_port scif2_platform_data = { | ||
57 | .mapbase = 0xffe20000, | ||
58 | .flags = UPF_BOOT_AUTOCONF, | ||
59 | .type = PORT_SCIF, | ||
60 | .irqs = { 82, 82, 82, 82 }, | ||
61 | .clk = "scif2", | ||
62 | }; | ||
63 | |||
64 | static struct platform_device scif2_device = { | ||
65 | .name = "sh-sci", | ||
66 | .id = 2, | ||
67 | .dev = { | ||
68 | .platform_data = &scif2_platform_data, | ||
69 | }, | ||
70 | }; | ||
71 | |||
72 | static struct plat_sci_port scif3_platform_data = { | ||
73 | .mapbase = 0xa4e30000, | ||
74 | .flags = UPF_BOOT_AUTOCONF, | ||
75 | .type = PORT_SCIFA, | ||
76 | .irqs = { 56, 56, 56, 56 }, | ||
77 | .clk = "scif3", | ||
78 | }; | ||
79 | |||
80 | static struct platform_device scif3_device = { | ||
81 | .name = "sh-sci", | ||
82 | .id = 3, | ||
83 | .dev = { | ||
84 | .platform_data = &scif3_platform_data, | ||
85 | }, | ||
86 | }; | ||
87 | |||
88 | static struct plat_sci_port scif4_platform_data = { | ||
89 | .mapbase = 0xa4e40000, | ||
90 | .flags = UPF_BOOT_AUTOCONF, | ||
91 | .type = PORT_SCIFA, | ||
92 | .irqs = { 88, 88, 88, 88 }, | ||
93 | .clk = "scif4", | ||
94 | }; | ||
95 | |||
96 | static struct platform_device scif4_device = { | ||
97 | .name = "sh-sci", | ||
98 | .id = 4, | ||
99 | .dev = { | ||
100 | .platform_data = &scif4_platform_data, | ||
101 | }, | ||
102 | }; | ||
103 | |||
104 | static struct plat_sci_port scif5_platform_data = { | ||
105 | .mapbase = 0xa4e50000, | ||
106 | .flags = UPF_BOOT_AUTOCONF, | ||
107 | .type = PORT_SCIFA, | ||
108 | .irqs = { 109, 109, 109, 109 }, | ||
109 | .clk = "scif5", | ||
110 | }; | ||
111 | |||
112 | static struct platform_device scif5_device = { | ||
113 | .name = "sh-sci", | ||
114 | .id = 5, | ||
115 | .dev = { | ||
116 | .platform_data = &scif5_platform_data, | ||
117 | }, | ||
118 | }; | ||
119 | |||
23 | static struct uio_info vpu_platform_data = { | 120 | static struct uio_info vpu_platform_data = { |
24 | .name = "VPU5", | 121 | .name = "VPU5", |
25 | .version = "0", | 122 | .version = "0", |
@@ -348,56 +445,6 @@ static struct platform_device tmu5_device = { | |||
348 | }, | 445 | }, |
349 | }; | 446 | }; |
350 | 447 | ||
351 | static struct plat_sci_port sci_platform_data[] = { | ||
352 | { | ||
353 | .mapbase = 0xffe00000, | ||
354 | .flags = UPF_BOOT_AUTOCONF, | ||
355 | .type = PORT_SCIF, | ||
356 | .irqs = { 80, 80, 80, 80 }, | ||
357 | .clk = "scif0", | ||
358 | },{ | ||
359 | .mapbase = 0xffe10000, | ||
360 | .flags = UPF_BOOT_AUTOCONF, | ||
361 | .type = PORT_SCIF, | ||
362 | .irqs = { 81, 81, 81, 81 }, | ||
363 | .clk = "scif1", | ||
364 | },{ | ||
365 | .mapbase = 0xffe20000, | ||
366 | .flags = UPF_BOOT_AUTOCONF, | ||
367 | .type = PORT_SCIF, | ||
368 | .irqs = { 82, 82, 82, 82 }, | ||
369 | .clk = "scif2", | ||
370 | },{ | ||
371 | .mapbase = 0xa4e30000, | ||
372 | .flags = UPF_BOOT_AUTOCONF, | ||
373 | .type = PORT_SCIFA, | ||
374 | .irqs = { 56, 56, 56, 56 }, | ||
375 | .clk = "scif3", | ||
376 | },{ | ||
377 | .mapbase = 0xa4e40000, | ||
378 | .flags = UPF_BOOT_AUTOCONF, | ||
379 | .type = PORT_SCIFA, | ||
380 | .irqs = { 88, 88, 88, 88 }, | ||
381 | .clk = "scif4", | ||
382 | },{ | ||
383 | .mapbase = 0xa4e50000, | ||
384 | .flags = UPF_BOOT_AUTOCONF, | ||
385 | .type = PORT_SCIFA, | ||
386 | .irqs = { 109, 109, 109, 109 }, | ||
387 | .clk = "scif5", | ||
388 | }, { | ||
389 | .flags = 0, | ||
390 | } | ||
391 | }; | ||
392 | |||
393 | static struct platform_device sci_device = { | ||
394 | .name = "sh-sci", | ||
395 | .id = -1, | ||
396 | .dev = { | ||
397 | .platform_data = sci_platform_data, | ||
398 | }, | ||
399 | }; | ||
400 | |||
401 | static struct resource rtc_resources[] = { | 448 | static struct resource rtc_resources[] = { |
402 | [0] = { | 449 | [0] = { |
403 | .start = 0xa465fec0, | 450 | .start = 0xa465fec0, |
@@ -488,6 +535,12 @@ static struct platform_device iic_device = { | |||
488 | }; | 535 | }; |
489 | 536 | ||
490 | static struct platform_device *sh7723_devices[] __initdata = { | 537 | static struct platform_device *sh7723_devices[] __initdata = { |
538 | &scif0_device, | ||
539 | &scif1_device, | ||
540 | &scif2_device, | ||
541 | &scif3_device, | ||
542 | &scif4_device, | ||
543 | &scif5_device, | ||
491 | &cmt_device, | 544 | &cmt_device, |
492 | &tmu0_device, | 545 | &tmu0_device, |
493 | &tmu1_device, | 546 | &tmu1_device, |
@@ -495,7 +548,6 @@ static struct platform_device *sh7723_devices[] __initdata = { | |||
495 | &tmu3_device, | 548 | &tmu3_device, |
496 | &tmu4_device, | 549 | &tmu4_device, |
497 | &tmu5_device, | 550 | &tmu5_device, |
498 | &sci_device, | ||
499 | &rtc_device, | 551 | &rtc_device, |
500 | &iic_device, | 552 | &iic_device, |
501 | &sh7723_usb_host_device, | 553 | &sh7723_usb_host_device, |
@@ -516,6 +568,12 @@ static int __init sh7723_devices_setup(void) | |||
516 | arch_initcall(sh7723_devices_setup); | 568 | arch_initcall(sh7723_devices_setup); |
517 | 569 | ||
518 | static struct platform_device *sh7723_early_devices[] __initdata = { | 570 | static struct platform_device *sh7723_early_devices[] __initdata = { |
571 | &scif0_device, | ||
572 | &scif1_device, | ||
573 | &scif2_device, | ||
574 | &scif3_device, | ||
575 | &scif4_device, | ||
576 | &scif5_device, | ||
519 | &cmt_device, | 577 | &cmt_device, |
520 | &tmu0_device, | 578 | &tmu0_device, |
521 | &tmu1_device, | 579 | &tmu1_device, |
@@ -534,14 +592,17 @@ void __init plat_early_device_setup(void) | |||
534 | #define RAMCR_CACHE_L2FC 0x0002 | 592 | #define RAMCR_CACHE_L2FC 0x0002 |
535 | #define RAMCR_CACHE_L2E 0x0001 | 593 | #define RAMCR_CACHE_L2E 0x0001 |
536 | #define L2_CACHE_ENABLE (RAMCR_CACHE_L2E|RAMCR_CACHE_L2FC) | 594 | #define L2_CACHE_ENABLE (RAMCR_CACHE_L2E|RAMCR_CACHE_L2FC) |
537 | void __uses_jump_to_uncached l2_cache_init(void) | 595 | |
596 | void l2_cache_init(void) | ||
538 | { | 597 | { |
539 | /* Enable L2 cache */ | 598 | /* Enable L2 cache */ |
540 | ctrl_outl(L2_CACHE_ENABLE, RAMCR); | 599 | __raw_writel(L2_CACHE_ENABLE, RAMCR); |
541 | } | 600 | } |
542 | 601 | ||
543 | enum { | 602 | enum { |
544 | UNUSED=0, | 603 | UNUSED=0, |
604 | ENABLED, | ||
605 | DISABLED, | ||
545 | 606 | ||
546 | /* interrupt sources */ | 607 | /* interrupt sources */ |
547 | IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, | 608 | IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, |
@@ -564,7 +625,6 @@ enum { | |||
564 | SCIFA_SCIFA1, | 625 | SCIFA_SCIFA1, |
565 | FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I, | 626 | FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I, |
566 | I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI, | 627 | I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI, |
567 | SDHI0_SDHII0,SDHI0_SDHII1,SDHI0_SDHII2, | ||
568 | CMT_CMTI, | 628 | CMT_CMTI, |
569 | TSIF_TSIFI, | 629 | TSIF_TSIFI, |
570 | SIU_SIUI, | 630 | SIU_SIUI, |
@@ -572,7 +632,6 @@ enum { | |||
572 | TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2, | 632 | TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2, |
573 | IRDA_IRDAI, | 633 | IRDA_IRDAI, |
574 | ATAPI_ATAPII, | 634 | ATAPI_ATAPII, |
575 | SDHI1_SDHII0,SDHI1_SDHII1,SDHI1_SDHII2, | ||
576 | VEU2H1_VEU2HI, | 635 | VEU2H1_VEU2HI, |
577 | LCDC_LCDCI, | 636 | LCDC_LCDCI, |
578 | TMU1_TUNI0,TMU1_TUNI1,TMU1_TUNI2, | 637 | TMU1_TUNI0,TMU1_TUNI1,TMU1_TUNI2, |
@@ -643,9 +702,9 @@ static struct intc_vect vectors[] __initdata = { | |||
643 | INTC_VECT(I2C_WAITI,0xE40), | 702 | INTC_VECT(I2C_WAITI,0xE40), |
644 | INTC_VECT(I2C_DTEI,0xE60), | 703 | INTC_VECT(I2C_DTEI,0xE60), |
645 | 704 | ||
646 | INTC_VECT(SDHI0_SDHII0,0xE80), | 705 | INTC_VECT(SDHI0, 0xE80), |
647 | INTC_VECT(SDHI0_SDHII1,0xEA0), | 706 | INTC_VECT(SDHI0, 0xEA0), |
648 | INTC_VECT(SDHI0_SDHII2,0xEC0), | 707 | INTC_VECT(SDHI0, 0xEC0), |
649 | 708 | ||
650 | INTC_VECT(CMT_CMTI,0xF00), | 709 | INTC_VECT(CMT_CMTI,0xF00), |
651 | INTC_VECT(TSIF_TSIFI,0xF20), | 710 | INTC_VECT(TSIF_TSIFI,0xF20), |
@@ -659,9 +718,9 @@ static struct intc_vect vectors[] __initdata = { | |||
659 | INTC_VECT(IRDA_IRDAI,0x480), | 718 | INTC_VECT(IRDA_IRDAI,0x480), |
660 | INTC_VECT(ATAPI_ATAPII,0x4A0), | 719 | INTC_VECT(ATAPI_ATAPII,0x4A0), |
661 | 720 | ||
662 | INTC_VECT(SDHI1_SDHII0,0x4E0), | 721 | INTC_VECT(SDHI1, 0x4E0), |
663 | INTC_VECT(SDHI1_SDHII1,0x500), | 722 | INTC_VECT(SDHI1, 0x500), |
664 | INTC_VECT(SDHI1_SDHII2,0x520), | 723 | INTC_VECT(SDHI1, 0x520), |
665 | 724 | ||
666 | INTC_VECT(VEU2H1_VEU2HI,0x560), | 725 | INTC_VECT(VEU2H1_VEU2HI,0x560), |
667 | INTC_VECT(LCDC_LCDCI,0x580), | 726 | INTC_VECT(LCDC_LCDCI,0x580), |
@@ -680,15 +739,14 @@ static struct intc_group groups[] __initdata = { | |||
680 | INTC_GROUP(FLCTL,FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I), | 739 | INTC_GROUP(FLCTL,FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I), |
681 | INTC_GROUP(I2C,I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI), | 740 | INTC_GROUP(I2C,I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI), |
682 | INTC_GROUP(_2DG, _2DG_TRI,_2DG_INI,_2DG_CEI), | 741 | INTC_GROUP(_2DG, _2DG_TRI,_2DG_INI,_2DG_CEI), |
683 | INTC_GROUP(SDHI1, SDHI1_SDHII0,SDHI1_SDHII1,SDHI1_SDHII2), | ||
684 | INTC_GROUP(RTC, RTC_ATI,RTC_PRI,RTC_CUI), | 742 | INTC_GROUP(RTC, RTC_ATI,RTC_PRI,RTC_CUI), |
685 | INTC_GROUP(DMAC1B, DMAC1B_DEI4,DMAC1B_DEI5,DMAC1B_DADERR), | 743 | INTC_GROUP(DMAC1B, DMAC1B_DEI4,DMAC1B_DEI5,DMAC1B_DADERR), |
686 | INTC_GROUP(SDHI0,SDHI0_SDHII0,SDHI0_SDHII1,SDHI0_SDHII2), | ||
687 | }; | 744 | }; |
688 | 745 | ||
689 | static struct intc_mask_reg mask_registers[] __initdata = { | 746 | static struct intc_mask_reg mask_registers[] __initdata = { |
690 | { 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */ | 747 | { 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */ |
691 | { 0, TMU1_TUNI2,TMU1_TUNI1,TMU1_TUNI0,0,SDHI1_SDHII2,SDHI1_SDHII1,SDHI1_SDHII0} }, | 748 | { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0, |
749 | 0, DISABLED, ENABLED, ENABLED } }, | ||
692 | { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */ | 750 | { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */ |
693 | { VIO_VOUI, VIO_VEU2HI,VIO_BEUI,VIO_CEUI,DMAC0A_DEI3,DMAC0A_DEI2,DMAC0A_DEI1,DMAC0A_DEI0 } }, | 751 | { VIO_VOUI, VIO_VEU2HI,VIO_BEUI,VIO_CEUI,DMAC0A_DEI3,DMAC0A_DEI2,DMAC0A_DEI1,DMAC0A_DEI0 } }, |
694 | { 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */ | 752 | { 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */ |
@@ -705,7 +763,8 @@ static struct intc_mask_reg mask_registers[] __initdata = { | |||
705 | { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI, | 763 | { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI, |
706 | FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } }, | 764 | FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } }, |
707 | { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */ | 765 | { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */ |
708 | { 0,SDHI0_SDHII2,SDHI0_SDHII1,SDHI0_SDHII0,0,0,SCIFA_SCIFA2,SIU_SIUI } }, | 766 | { 0, DISABLED, ENABLED, ENABLED, |
767 | 0, 0, SCIFA_SCIFA2, SIU_SIUI } }, | ||
709 | { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */ | 768 | { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */ |
710 | { 0, 0, 0, CMT_CMTI, 0, 0, USB_USI0,0 } }, | 769 | { 0, 0, 0, CMT_CMTI, 0, 0, USB_USI0,0 } }, |
711 | { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */ | 770 | { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */ |
@@ -745,9 +804,13 @@ static struct intc_mask_reg ack_registers[] __initdata = { | |||
745 | { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, | 804 | { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, |
746 | }; | 805 | }; |
747 | 806 | ||
748 | static DECLARE_INTC_DESC_ACK(intc_desc, "sh7723", vectors, groups, | 807 | static struct intc_desc intc_desc __initdata = { |
749 | mask_registers, prio_registers, sense_registers, | 808 | .name = "sh7723", |
750 | ack_registers); | 809 | .force_enable = ENABLED, |
810 | .force_disable = DISABLED, | ||
811 | .hw = INTC_HW_DESC(vectors, groups, mask_registers, | ||
812 | prio_registers, sense_registers, ack_registers), | ||
813 | }; | ||
751 | 814 | ||
752 | void __init plat_irq_setup(void) | 815 | void __init plat_irq_setup(void) |
753 | { | 816 | { |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index f3851fd757ec..e7fa2a92fc1f 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c | |||
@@ -20,58 +20,287 @@ | |||
20 | #include <linux/uio_driver.h> | 20 | #include <linux/uio_driver.h> |
21 | #include <linux/sh_timer.h> | 21 | #include <linux/sh_timer.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/notifier.h> | ||
24 | |||
25 | #include <asm/suspend.h> | ||
23 | #include <asm/clock.h> | 26 | #include <asm/clock.h> |
27 | #include <asm/dmaengine.h> | ||
24 | #include <asm/mmzone.h> | 28 | #include <asm/mmzone.h> |
29 | |||
30 | #include <cpu/dma-register.h> | ||
25 | #include <cpu/sh7724.h> | 31 | #include <cpu/sh7724.h> |
26 | 32 | ||
27 | /* Serial */ | 33 | /* DMA */ |
28 | static struct plat_sci_port sci_platform_data[] = { | 34 | static struct sh_dmae_channel sh7724_dmae0_channels[] = { |
29 | { | 35 | { |
30 | .mapbase = 0xffe00000, | 36 | .offset = 0, |
31 | .flags = UPF_BOOT_AUTOCONF, | 37 | .dmars = 0, |
32 | .type = PORT_SCIF, | 38 | .dmars_bit = 0, |
33 | .irqs = { 80, 80, 80, 80 }, | 39 | }, { |
34 | .clk = "scif0", | 40 | .offset = 0x10, |
41 | .dmars = 0, | ||
42 | .dmars_bit = 8, | ||
43 | }, { | ||
44 | .offset = 0x20, | ||
45 | .dmars = 4, | ||
46 | .dmars_bit = 0, | ||
47 | }, { | ||
48 | .offset = 0x30, | ||
49 | .dmars = 4, | ||
50 | .dmars_bit = 8, | ||
35 | }, { | 51 | }, { |
36 | .mapbase = 0xffe10000, | 52 | .offset = 0x50, |
37 | .flags = UPF_BOOT_AUTOCONF, | 53 | .dmars = 8, |
38 | .type = PORT_SCIF, | 54 | .dmars_bit = 0, |
39 | .irqs = { 81, 81, 81, 81 }, | 55 | }, { |
40 | .clk = "scif1", | 56 | .offset = 0x60, |
57 | .dmars = 8, | ||
58 | .dmars_bit = 8, | ||
59 | } | ||
60 | }; | ||
61 | |||
62 | static struct sh_dmae_channel sh7724_dmae1_channels[] = { | ||
63 | { | ||
64 | .offset = 0, | ||
65 | .dmars = 0, | ||
66 | .dmars_bit = 0, | ||
41 | }, { | 67 | }, { |
42 | .mapbase = 0xffe20000, | 68 | .offset = 0x10, |
43 | .flags = UPF_BOOT_AUTOCONF, | 69 | .dmars = 0, |
44 | .type = PORT_SCIF, | 70 | .dmars_bit = 8, |
45 | .irqs = { 82, 82, 82, 82 }, | ||
46 | .clk = "scif2", | ||
47 | }, { | 71 | }, { |
48 | .mapbase = 0xa4e30000, | 72 | .offset = 0x20, |
49 | .flags = UPF_BOOT_AUTOCONF, | 73 | .dmars = 4, |
50 | .type = PORT_SCIFA, | 74 | .dmars_bit = 0, |
51 | .irqs = { 56, 56, 56, 56 }, | ||
52 | .clk = "scif3", | ||
53 | }, { | 75 | }, { |
54 | .mapbase = 0xa4e40000, | 76 | .offset = 0x30, |
55 | .flags = UPF_BOOT_AUTOCONF, | 77 | .dmars = 4, |
56 | .type = PORT_SCIFA, | 78 | .dmars_bit = 8, |
57 | .irqs = { 88, 88, 88, 88 }, | ||
58 | .clk = "scif4", | ||
59 | }, { | 79 | }, { |
60 | .mapbase = 0xa4e50000, | 80 | .offset = 0x50, |
61 | .flags = UPF_BOOT_AUTOCONF, | 81 | .dmars = 8, |
62 | .type = PORT_SCIFA, | 82 | .dmars_bit = 0, |
63 | .irqs = { 109, 109, 109, 109 }, | ||
64 | .clk = "scif5", | ||
65 | }, { | 83 | }, { |
66 | .flags = 0, | 84 | .offset = 0x60, |
85 | .dmars = 8, | ||
86 | .dmars_bit = 8, | ||
67 | } | 87 | } |
68 | }; | 88 | }; |
69 | 89 | ||
70 | static struct platform_device sci_device = { | 90 | static unsigned int ts_shift[] = TS_SHIFT; |
91 | |||
92 | static struct sh_dmae_pdata dma0_platform_data = { | ||
93 | .channel = sh7724_dmae0_channels, | ||
94 | .channel_num = ARRAY_SIZE(sh7724_dmae0_channels), | ||
95 | .ts_low_shift = CHCR_TS_LOW_SHIFT, | ||
96 | .ts_low_mask = CHCR_TS_LOW_MASK, | ||
97 | .ts_high_shift = CHCR_TS_HIGH_SHIFT, | ||
98 | .ts_high_mask = CHCR_TS_HIGH_MASK, | ||
99 | .ts_shift = ts_shift, | ||
100 | .ts_shift_num = ARRAY_SIZE(ts_shift), | ||
101 | .dmaor_init = DMAOR_INIT, | ||
102 | }; | ||
103 | |||
104 | static struct sh_dmae_pdata dma1_platform_data = { | ||
105 | .channel = sh7724_dmae1_channels, | ||
106 | .channel_num = ARRAY_SIZE(sh7724_dmae1_channels), | ||
107 | .ts_low_shift = CHCR_TS_LOW_SHIFT, | ||
108 | .ts_low_mask = CHCR_TS_LOW_MASK, | ||
109 | .ts_high_shift = CHCR_TS_HIGH_SHIFT, | ||
110 | .ts_high_mask = CHCR_TS_HIGH_MASK, | ||
111 | .ts_shift = ts_shift, | ||
112 | .ts_shift_num = ARRAY_SIZE(ts_shift), | ||
113 | .dmaor_init = DMAOR_INIT, | ||
114 | }; | ||
115 | |||
116 | /* Resource order important! */ | ||
117 | static struct resource sh7724_dmae0_resources[] = { | ||
118 | { | ||
119 | /* Channel registers and DMAOR */ | ||
120 | .start = 0xfe008020, | ||
121 | .end = 0xfe00808f, | ||
122 | .flags = IORESOURCE_MEM, | ||
123 | }, | ||
124 | { | ||
125 | /* DMARSx */ | ||
126 | .start = 0xfe009000, | ||
127 | .end = 0xfe00900b, | ||
128 | .flags = IORESOURCE_MEM, | ||
129 | }, | ||
130 | { | ||
131 | /* DMA error IRQ */ | ||
132 | .start = 78, | ||
133 | .end = 78, | ||
134 | .flags = IORESOURCE_IRQ, | ||
135 | }, | ||
136 | { | ||
137 | /* IRQ for channels 0-3 */ | ||
138 | .start = 48, | ||
139 | .end = 51, | ||
140 | .flags = IORESOURCE_IRQ, | ||
141 | }, | ||
142 | { | ||
143 | /* IRQ for channels 4-5 */ | ||
144 | .start = 76, | ||
145 | .end = 77, | ||
146 | .flags = IORESOURCE_IRQ, | ||
147 | }, | ||
148 | }; | ||
149 | |||
150 | /* Resource order important! */ | ||
151 | static struct resource sh7724_dmae1_resources[] = { | ||
152 | { | ||
153 | /* Channel registers and DMAOR */ | ||
154 | .start = 0xfdc08020, | ||
155 | .end = 0xfdc0808f, | ||
156 | .flags = IORESOURCE_MEM, | ||
157 | }, | ||
158 | { | ||
159 | /* DMARSx */ | ||
160 | .start = 0xfdc09000, | ||
161 | .end = 0xfdc0900b, | ||
162 | .flags = IORESOURCE_MEM, | ||
163 | }, | ||
164 | { | ||
165 | /* DMA error IRQ */ | ||
166 | .start = 74, | ||
167 | .end = 74, | ||
168 | .flags = IORESOURCE_IRQ, | ||
169 | }, | ||
170 | { | ||
171 | /* IRQ for channels 0-3 */ | ||
172 | .start = 40, | ||
173 | .end = 43, | ||
174 | .flags = IORESOURCE_IRQ, | ||
175 | }, | ||
176 | { | ||
177 | /* IRQ for channels 4-5 */ | ||
178 | .start = 72, | ||
179 | .end = 73, | ||
180 | .flags = IORESOURCE_IRQ, | ||
181 | }, | ||
182 | }; | ||
183 | |||
184 | static struct platform_device dma0_device = { | ||
185 | .name = "sh-dma-engine", | ||
186 | .id = 0, | ||
187 | .resource = sh7724_dmae0_resources, | ||
188 | .num_resources = ARRAY_SIZE(sh7724_dmae0_resources), | ||
189 | .dev = { | ||
190 | .platform_data = &dma0_platform_data, | ||
191 | }, | ||
192 | .archdata = { | ||
193 | .hwblk_id = HWBLK_DMAC0, | ||
194 | }, | ||
195 | }; | ||
196 | |||
197 | static struct platform_device dma1_device = { | ||
198 | .name = "sh-dma-engine", | ||
199 | .id = 1, | ||
200 | .resource = sh7724_dmae1_resources, | ||
201 | .num_resources = ARRAY_SIZE(sh7724_dmae1_resources), | ||
202 | .dev = { | ||
203 | .platform_data = &dma1_platform_data, | ||
204 | }, | ||
205 | .archdata = { | ||
206 | .hwblk_id = HWBLK_DMAC1, | ||
207 | }, | ||
208 | }; | ||
209 | |||
210 | /* Serial */ | ||
211 | static struct plat_sci_port scif0_platform_data = { | ||
212 | .mapbase = 0xffe00000, | ||
213 | .flags = UPF_BOOT_AUTOCONF, | ||
214 | .type = PORT_SCIF, | ||
215 | .irqs = { 80, 80, 80, 80 }, | ||
216 | .clk = "scif0", | ||
217 | }; | ||
218 | |||
219 | static struct platform_device scif0_device = { | ||
71 | .name = "sh-sci", | 220 | .name = "sh-sci", |
72 | .id = -1, | 221 | .id = 0, |
222 | .dev = { | ||
223 | .platform_data = &scif0_platform_data, | ||
224 | }, | ||
225 | }; | ||
226 | |||
227 | static struct plat_sci_port scif1_platform_data = { | ||
228 | .mapbase = 0xffe10000, | ||
229 | .flags = UPF_BOOT_AUTOCONF, | ||
230 | .type = PORT_SCIF, | ||
231 | .irqs = { 81, 81, 81, 81 }, | ||
232 | .clk = "scif1", | ||
233 | }; | ||
234 | |||
235 | static struct platform_device scif1_device = { | ||
236 | .name = "sh-sci", | ||
237 | .id = 1, | ||
73 | .dev = { | 238 | .dev = { |
74 | .platform_data = sci_platform_data, | 239 | .platform_data = &scif1_platform_data, |
240 | }, | ||
241 | }; | ||
242 | |||
243 | static struct plat_sci_port scif2_platform_data = { | ||
244 | .mapbase = 0xffe20000, | ||
245 | .flags = UPF_BOOT_AUTOCONF, | ||
246 | .type = PORT_SCIF, | ||
247 | .irqs = { 82, 82, 82, 82 }, | ||
248 | .clk = "scif2", | ||
249 | }; | ||
250 | |||
251 | static struct platform_device scif2_device = { | ||
252 | .name = "sh-sci", | ||
253 | .id = 2, | ||
254 | .dev = { | ||
255 | .platform_data = &scif2_platform_data, | ||
256 | }, | ||
257 | }; | ||
258 | |||
259 | static struct plat_sci_port scif3_platform_data = { | ||
260 | .mapbase = 0xa4e30000, | ||
261 | .flags = UPF_BOOT_AUTOCONF, | ||
262 | .type = PORT_SCIFA, | ||
263 | .irqs = { 56, 56, 56, 56 }, | ||
264 | .clk = "scif3", | ||
265 | }; | ||
266 | |||
267 | static struct platform_device scif3_device = { | ||
268 | .name = "sh-sci", | ||
269 | .id = 3, | ||
270 | .dev = { | ||
271 | .platform_data = &scif3_platform_data, | ||
272 | }, | ||
273 | }; | ||
274 | |||
275 | static struct plat_sci_port scif4_platform_data = { | ||
276 | .mapbase = 0xa4e40000, | ||
277 | .flags = UPF_BOOT_AUTOCONF, | ||
278 | .type = PORT_SCIFA, | ||
279 | .irqs = { 88, 88, 88, 88 }, | ||
280 | .clk = "scif4", | ||
281 | }; | ||
282 | |||
283 | static struct platform_device scif4_device = { | ||
284 | .name = "sh-sci", | ||
285 | .id = 4, | ||
286 | .dev = { | ||
287 | .platform_data = &scif4_platform_data, | ||
288 | }, | ||
289 | }; | ||
290 | |||
291 | static struct plat_sci_port scif5_platform_data = { | ||
292 | .mapbase = 0xa4e50000, | ||
293 | .flags = UPF_BOOT_AUTOCONF, | ||
294 | .type = PORT_SCIFA, | ||
295 | .irqs = { 109, 109, 109, 109 }, | ||
296 | .clk = "scif5", | ||
297 | }; | ||
298 | |||
299 | static struct platform_device scif5_device = { | ||
300 | .name = "sh-sci", | ||
301 | .id = 5, | ||
302 | .dev = { | ||
303 | .platform_data = &scif5_platform_data, | ||
75 | }, | 304 | }, |
76 | }; | 305 | }; |
77 | 306 | ||
@@ -202,7 +431,7 @@ static struct resource veu0_resources[] = { | |||
202 | [0] = { | 431 | [0] = { |
203 | .name = "VEU3F0", | 432 | .name = "VEU3F0", |
204 | .start = 0xfe920000, | 433 | .start = 0xfe920000, |
205 | .end = 0xfe9200cb - 1, | 434 | .end = 0xfe9200cb, |
206 | .flags = IORESOURCE_MEM, | 435 | .flags = IORESOURCE_MEM, |
207 | }, | 436 | }, |
208 | [1] = { | 437 | [1] = { |
@@ -234,7 +463,7 @@ static struct resource veu1_resources[] = { | |||
234 | [0] = { | 463 | [0] = { |
235 | .name = "VEU3F1", | 464 | .name = "VEU3F1", |
236 | .start = 0xfe924000, | 465 | .start = 0xfe924000, |
237 | .end = 0xfe9240cb - 1, | 466 | .end = 0xfe9240cb, |
238 | .flags = IORESOURCE_MEM, | 467 | .flags = IORESOURCE_MEM, |
239 | }, | 468 | }, |
240 | [1] = { | 469 | [1] = { |
@@ -523,7 +752,77 @@ static struct platform_device jpu_device = { | |||
523 | }, | 752 | }, |
524 | }; | 753 | }; |
525 | 754 | ||
755 | /* SPU2DSP0 */ | ||
756 | static struct uio_info spu0_platform_data = { | ||
757 | .name = "SPU2DSP0", | ||
758 | .version = "0", | ||
759 | .irq = 86, | ||
760 | }; | ||
761 | |||
762 | static struct resource spu0_resources[] = { | ||
763 | [0] = { | ||
764 | .name = "SPU2DSP0", | ||
765 | .start = 0xFE200000, | ||
766 | .end = 0xFE2FFFFF, | ||
767 | .flags = IORESOURCE_MEM, | ||
768 | }, | ||
769 | [1] = { | ||
770 | /* place holder for contiguous memory */ | ||
771 | }, | ||
772 | }; | ||
773 | |||
774 | static struct platform_device spu0_device = { | ||
775 | .name = "uio_pdrv_genirq", | ||
776 | .id = 4, | ||
777 | .dev = { | ||
778 | .platform_data = &spu0_platform_data, | ||
779 | }, | ||
780 | .resource = spu0_resources, | ||
781 | .num_resources = ARRAY_SIZE(spu0_resources), | ||
782 | .archdata = { | ||
783 | .hwblk_id = HWBLK_SPU, | ||
784 | }, | ||
785 | }; | ||
786 | |||
787 | /* SPU2DSP1 */ | ||
788 | static struct uio_info spu1_platform_data = { | ||
789 | .name = "SPU2DSP1", | ||
790 | .version = "0", | ||
791 | .irq = 87, | ||
792 | }; | ||
793 | |||
794 | static struct resource spu1_resources[] = { | ||
795 | [0] = { | ||
796 | .name = "SPU2DSP1", | ||
797 | .start = 0xFE300000, | ||
798 | .end = 0xFE3FFFFF, | ||
799 | .flags = IORESOURCE_MEM, | ||
800 | }, | ||
801 | [1] = { | ||
802 | /* place holder for contiguous memory */ | ||
803 | }, | ||
804 | }; | ||
805 | |||
806 | static struct platform_device spu1_device = { | ||
807 | .name = "uio_pdrv_genirq", | ||
808 | .id = 5, | ||
809 | .dev = { | ||
810 | .platform_data = &spu1_platform_data, | ||
811 | }, | ||
812 | .resource = spu1_resources, | ||
813 | .num_resources = ARRAY_SIZE(spu1_resources), | ||
814 | .archdata = { | ||
815 | .hwblk_id = HWBLK_SPU, | ||
816 | }, | ||
817 | }; | ||
818 | |||
526 | static struct platform_device *sh7724_devices[] __initdata = { | 819 | static struct platform_device *sh7724_devices[] __initdata = { |
820 | &scif0_device, | ||
821 | &scif1_device, | ||
822 | &scif2_device, | ||
823 | &scif3_device, | ||
824 | &scif4_device, | ||
825 | &scif5_device, | ||
527 | &cmt_device, | 826 | &cmt_device, |
528 | &tmu0_device, | 827 | &tmu0_device, |
529 | &tmu1_device, | 828 | &tmu1_device, |
@@ -531,7 +830,8 @@ static struct platform_device *sh7724_devices[] __initdata = { | |||
531 | &tmu3_device, | 830 | &tmu3_device, |
532 | &tmu4_device, | 831 | &tmu4_device, |
533 | &tmu5_device, | 832 | &tmu5_device, |
534 | &sci_device, | 833 | &dma0_device, |
834 | &dma1_device, | ||
535 | &rtc_device, | 835 | &rtc_device, |
536 | &iic0_device, | 836 | &iic0_device, |
537 | &iic1_device, | 837 | &iic1_device, |
@@ -539,6 +839,8 @@ static struct platform_device *sh7724_devices[] __initdata = { | |||
539 | &veu0_device, | 839 | &veu0_device, |
540 | &veu1_device, | 840 | &veu1_device, |
541 | &jpu_device, | 841 | &jpu_device, |
842 | &spu0_device, | ||
843 | &spu1_device, | ||
542 | }; | 844 | }; |
543 | 845 | ||
544 | static int __init sh7724_devices_setup(void) | 846 | static int __init sh7724_devices_setup(void) |
@@ -547,6 +849,8 @@ static int __init sh7724_devices_setup(void) | |||
547 | platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20); | 849 | platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20); |
548 | platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20); | 850 | platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20); |
549 | platform_resource_setup_memory(&jpu_device, "jpu", 2 << 20); | 851 | platform_resource_setup_memory(&jpu_device, "jpu", 2 << 20); |
852 | platform_resource_setup_memory(&spu0_device, "spu0", 2 << 20); | ||
853 | platform_resource_setup_memory(&spu1_device, "spu1", 2 << 20); | ||
550 | 854 | ||
551 | return platform_add_devices(sh7724_devices, | 855 | return platform_add_devices(sh7724_devices, |
552 | ARRAY_SIZE(sh7724_devices)); | 856 | ARRAY_SIZE(sh7724_devices)); |
@@ -554,6 +858,12 @@ static int __init sh7724_devices_setup(void) | |||
554 | arch_initcall(sh7724_devices_setup); | 858 | arch_initcall(sh7724_devices_setup); |
555 | 859 | ||
556 | static struct platform_device *sh7724_early_devices[] __initdata = { | 860 | static struct platform_device *sh7724_early_devices[] __initdata = { |
861 | &scif0_device, | ||
862 | &scif1_device, | ||
863 | &scif2_device, | ||
864 | &scif3_device, | ||
865 | &scif4_device, | ||
866 | &scif5_device, | ||
557 | &cmt_device, | 867 | &cmt_device, |
558 | &tmu0_device, | 868 | &tmu0_device, |
559 | &tmu1_device, | 869 | &tmu1_device, |
@@ -572,14 +882,17 @@ void __init plat_early_device_setup(void) | |||
572 | #define RAMCR_CACHE_L2FC 0x0002 | 882 | #define RAMCR_CACHE_L2FC 0x0002 |
573 | #define RAMCR_CACHE_L2E 0x0001 | 883 | #define RAMCR_CACHE_L2E 0x0001 |
574 | #define L2_CACHE_ENABLE (RAMCR_CACHE_L2E|RAMCR_CACHE_L2FC) | 884 | #define L2_CACHE_ENABLE (RAMCR_CACHE_L2E|RAMCR_CACHE_L2FC) |
575 | void __uses_jump_to_uncached l2_cache_init(void) | 885 | |
886 | void l2_cache_init(void) | ||
576 | { | 887 | { |
577 | /* Enable L2 cache */ | 888 | /* Enable L2 cache */ |
578 | ctrl_outl(L2_CACHE_ENABLE, RAMCR); | 889 | __raw_writel(L2_CACHE_ENABLE, RAMCR); |
579 | } | 890 | } |
580 | 891 | ||
581 | enum { | 892 | enum { |
582 | UNUSED = 0, | 893 | UNUSED = 0, |
894 | ENABLED, | ||
895 | DISABLED, | ||
583 | 896 | ||
584 | /* interrupt sources */ | 897 | /* interrupt sources */ |
585 | IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, | 898 | IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, |
@@ -608,14 +921,12 @@ enum { | |||
608 | ETHI, | 921 | ETHI, |
609 | I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI, | 922 | I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI, |
610 | I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI, | 923 | I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI, |
611 | SDHI0_SDHII0, SDHI0_SDHII1, SDHI0_SDHII2, SDHI0_SDHII3, | ||
612 | CMT, | 924 | CMT, |
613 | TSIF, | 925 | TSIF, |
614 | FSI, | 926 | FSI, |
615 | SCIFA5, | 927 | SCIFA5, |
616 | TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2, | 928 | TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2, |
617 | IRDA, | 929 | IRDA, |
618 | SDHI1_SDHII0, SDHI1_SDHII1, SDHI1_SDHII2, | ||
619 | JPU, | 930 | JPU, |
620 | _2DDMAC, | 931 | _2DDMAC, |
621 | MMC_MMC2I, MMC_MMC3I, | 932 | MMC_MMC2I, MMC_MMC3I, |
@@ -697,10 +1008,10 @@ static struct intc_vect vectors[] __initdata = { | |||
697 | INTC_VECT(I2C0_WAITI, 0xE40), | 1008 | INTC_VECT(I2C0_WAITI, 0xE40), |
698 | INTC_VECT(I2C0_DTEI, 0xE60), | 1009 | INTC_VECT(I2C0_DTEI, 0xE60), |
699 | 1010 | ||
700 | INTC_VECT(SDHI0_SDHII0, 0xE80), | 1011 | INTC_VECT(SDHI0, 0xE80), |
701 | INTC_VECT(SDHI0_SDHII1, 0xEA0), | 1012 | INTC_VECT(SDHI0, 0xEA0), |
702 | INTC_VECT(SDHI0_SDHII2, 0xEC0), | 1013 | INTC_VECT(SDHI0, 0xEC0), |
703 | INTC_VECT(SDHI0_SDHII3, 0xEE0), | 1014 | INTC_VECT(SDHI0, 0xEE0), |
704 | 1015 | ||
705 | INTC_VECT(CMT, 0xF00), | 1016 | INTC_VECT(CMT, 0xF00), |
706 | INTC_VECT(TSIF, 0xF20), | 1017 | INTC_VECT(TSIF, 0xF20), |
@@ -713,9 +1024,9 @@ static struct intc_vect vectors[] __initdata = { | |||
713 | 1024 | ||
714 | INTC_VECT(IRDA, 0x480), | 1025 | INTC_VECT(IRDA, 0x480), |
715 | 1026 | ||
716 | INTC_VECT(SDHI1_SDHII0, 0x4E0), | 1027 | INTC_VECT(SDHI1, 0x4E0), |
717 | INTC_VECT(SDHI1_SDHII1, 0x500), | 1028 | INTC_VECT(SDHI1, 0x500), |
718 | INTC_VECT(SDHI1_SDHII2, 0x520), | 1029 | INTC_VECT(SDHI1, 0x520), |
719 | 1030 | ||
720 | INTC_VECT(JPU, 0x560), | 1031 | INTC_VECT(JPU, 0x560), |
721 | INTC_VECT(_2DDMAC, 0x4A0), | 1032 | INTC_VECT(_2DDMAC, 0x4A0), |
@@ -741,8 +1052,6 @@ static struct intc_group groups[] __initdata = { | |||
741 | INTC_GROUP(DMAC0B, DMAC0B_DEI4, DMAC0B_DEI5, DMAC0B_DADERR), | 1052 | INTC_GROUP(DMAC0B, DMAC0B_DEI4, DMAC0B_DEI5, DMAC0B_DADERR), |
742 | INTC_GROUP(I2C0, I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI), | 1053 | INTC_GROUP(I2C0, I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI), |
743 | INTC_GROUP(I2C1, I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI), | 1054 | INTC_GROUP(I2C1, I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI), |
744 | INTC_GROUP(SDHI0, SDHI0_SDHII0, SDHI0_SDHII1, SDHI0_SDHII2, SDHI0_SDHII3), | ||
745 | INTC_GROUP(SDHI1, SDHI1_SDHII0, SDHI1_SDHII1, SDHI1_SDHII2), | ||
746 | INTC_GROUP(SPU, SPU_SPUI0, SPU_SPUI1), | 1055 | INTC_GROUP(SPU, SPU_SPUI0, SPU_SPUI1), |
747 | INTC_GROUP(MMCIF, MMC_MMC2I, MMC_MMC3I), | 1056 | INTC_GROUP(MMCIF, MMC_MMC2I, MMC_MMC3I), |
748 | }; | 1057 | }; |
@@ -750,7 +1059,7 @@ static struct intc_group groups[] __initdata = { | |||
750 | static struct intc_mask_reg mask_registers[] __initdata = { | 1059 | static struct intc_mask_reg mask_registers[] __initdata = { |
751 | { 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */ | 1060 | { 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */ |
752 | { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0, | 1061 | { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0, |
753 | 0, SDHI1_SDHII2, SDHI1_SDHII1, SDHI1_SDHII0 } }, | 1062 | 0, DISABLED, ENABLED, ENABLED } }, |
754 | { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */ | 1063 | { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */ |
755 | { VIO_VOU, VIO_VEU1, VIO_BEU0, VIO_CEU0, | 1064 | { VIO_VOU, VIO_VEU1, VIO_BEU0, VIO_CEU0, |
756 | DMAC0A_DEI3, DMAC0A_DEI2, DMAC0A_DEI1, DMAC0A_DEI0 } }, | 1065 | DMAC0A_DEI3, DMAC0A_DEI2, DMAC0A_DEI1, DMAC0A_DEI0 } }, |
@@ -772,7 +1081,7 @@ static struct intc_mask_reg mask_registers[] __initdata = { | |||
772 | { I2C0_DTEI, I2C0_WAITI, I2C0_TACKI, I2C0_ALI, | 1081 | { I2C0_DTEI, I2C0_WAITI, I2C0_TACKI, I2C0_ALI, |
773 | I2C1_DTEI, I2C1_WAITI, I2C1_TACKI, I2C1_ALI } }, | 1082 | I2C1_DTEI, I2C1_WAITI, I2C1_TACKI, I2C1_ALI } }, |
774 | { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */ | 1083 | { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */ |
775 | { SDHI0_SDHII3, SDHI0_SDHII2, SDHI0_SDHII1, SDHI0_SDHII0, | 1084 | { DISABLED, DISABLED, ENABLED, ENABLED, |
776 | 0, 0, SCIFA5, FSI } }, | 1085 | 0, 0, SCIFA5, FSI } }, |
777 | { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */ | 1086 | { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */ |
778 | { 0, 0, 0, CMT, 0, USB1, USB0, 0 } }, | 1087 | { 0, 0, 0, CMT, 0, USB1, USB0, 0 } }, |
@@ -819,11 +1128,205 @@ static struct intc_mask_reg ack_registers[] __initdata = { | |||
819 | { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, | 1128 | { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, |
820 | }; | 1129 | }; |
821 | 1130 | ||
822 | static DECLARE_INTC_DESC_ACK(intc_desc, "sh7724", vectors, groups, | 1131 | static struct intc_desc intc_desc __initdata = { |
823 | mask_registers, prio_registers, sense_registers, | 1132 | .name = "sh7724", |
824 | ack_registers); | 1133 | .force_enable = ENABLED, |
1134 | .force_disable = DISABLED, | ||
1135 | .hw = INTC_HW_DESC(vectors, groups, mask_registers, | ||
1136 | prio_registers, sense_registers, ack_registers), | ||
1137 | }; | ||
825 | 1138 | ||
826 | void __init plat_irq_setup(void) | 1139 | void __init plat_irq_setup(void) |
827 | { | 1140 | { |
828 | register_intc_controller(&intc_desc); | 1141 | register_intc_controller(&intc_desc); |
829 | } | 1142 | } |
1143 | |||
1144 | static struct { | ||
1145 | /* BSC */ | ||
1146 | unsigned long mmselr; | ||
1147 | unsigned long cs0bcr; | ||
1148 | unsigned long cs4bcr; | ||
1149 | unsigned long cs5abcr; | ||
1150 | unsigned long cs5bbcr; | ||
1151 | unsigned long cs6abcr; | ||
1152 | unsigned long cs6bbcr; | ||
1153 | unsigned long cs4wcr; | ||
1154 | unsigned long cs5awcr; | ||
1155 | unsigned long cs5bwcr; | ||
1156 | unsigned long cs6awcr; | ||
1157 | unsigned long cs6bwcr; | ||
1158 | /* INTC */ | ||
1159 | unsigned short ipra; | ||
1160 | unsigned short iprb; | ||
1161 | unsigned short iprc; | ||
1162 | unsigned short iprd; | ||
1163 | unsigned short ipre; | ||
1164 | unsigned short iprf; | ||
1165 | unsigned short iprg; | ||
1166 | unsigned short iprh; | ||
1167 | unsigned short ipri; | ||
1168 | unsigned short iprj; | ||
1169 | unsigned short iprk; | ||
1170 | unsigned short iprl; | ||
1171 | unsigned char imr0; | ||
1172 | unsigned char imr1; | ||
1173 | unsigned char imr2; | ||
1174 | unsigned char imr3; | ||
1175 | unsigned char imr4; | ||
1176 | unsigned char imr5; | ||
1177 | unsigned char imr6; | ||
1178 | unsigned char imr7; | ||
1179 | unsigned char imr8; | ||
1180 | unsigned char imr9; | ||
1181 | unsigned char imr10; | ||
1182 | unsigned char imr11; | ||
1183 | unsigned char imr12; | ||
1184 | /* RWDT */ | ||
1185 | unsigned short rwtcnt; | ||
1186 | unsigned short rwtcsr; | ||
1187 | /* CPG */ | ||
1188 | unsigned long irdaclk; | ||
1189 | unsigned long spuclk; | ||
1190 | } sh7724_rstandby_state; | ||
1191 | |||
1192 | static int sh7724_pre_sleep_notifier_call(struct notifier_block *nb, | ||
1193 | unsigned long flags, void *unused) | ||
1194 | { | ||
1195 | if (!(flags & SUSP_SH_RSTANDBY)) | ||
1196 | return NOTIFY_DONE; | ||
1197 | |||
1198 | /* BCR */ | ||
1199 | sh7724_rstandby_state.mmselr = __raw_readl(0xff800020); /* MMSELR */ | ||
1200 | sh7724_rstandby_state.mmselr |= 0xa5a50000; | ||
1201 | sh7724_rstandby_state.cs0bcr = __raw_readl(0xfec10004); /* CS0BCR */ | ||
1202 | sh7724_rstandby_state.cs4bcr = __raw_readl(0xfec10010); /* CS4BCR */ | ||
1203 | sh7724_rstandby_state.cs5abcr = __raw_readl(0xfec10014); /* CS5ABCR */ | ||
1204 | sh7724_rstandby_state.cs5bbcr = __raw_readl(0xfec10018); /* CS5BBCR */ | ||
1205 | sh7724_rstandby_state.cs6abcr = __raw_readl(0xfec1001c); /* CS6ABCR */ | ||
1206 | sh7724_rstandby_state.cs6bbcr = __raw_readl(0xfec10020); /* CS6BBCR */ | ||
1207 | sh7724_rstandby_state.cs4wcr = __raw_readl(0xfec10030); /* CS4WCR */ | ||
1208 | sh7724_rstandby_state.cs5awcr = __raw_readl(0xfec10034); /* CS5AWCR */ | ||
1209 | sh7724_rstandby_state.cs5bwcr = __raw_readl(0xfec10038); /* CS5BWCR */ | ||
1210 | sh7724_rstandby_state.cs6awcr = __raw_readl(0xfec1003c); /* CS6AWCR */ | ||
1211 | sh7724_rstandby_state.cs6bwcr = __raw_readl(0xfec10040); /* CS6BWCR */ | ||
1212 | |||
1213 | /* INTC */ | ||
1214 | sh7724_rstandby_state.ipra = __raw_readw(0xa4080000); /* IPRA */ | ||
1215 | sh7724_rstandby_state.iprb = __raw_readw(0xa4080004); /* IPRB */ | ||
1216 | sh7724_rstandby_state.iprc = __raw_readw(0xa4080008); /* IPRC */ | ||
1217 | sh7724_rstandby_state.iprd = __raw_readw(0xa408000c); /* IPRD */ | ||
1218 | sh7724_rstandby_state.ipre = __raw_readw(0xa4080010); /* IPRE */ | ||
1219 | sh7724_rstandby_state.iprf = __raw_readw(0xa4080014); /* IPRF */ | ||
1220 | sh7724_rstandby_state.iprg = __raw_readw(0xa4080018); /* IPRG */ | ||
1221 | sh7724_rstandby_state.iprh = __raw_readw(0xa408001c); /* IPRH */ | ||
1222 | sh7724_rstandby_state.ipri = __raw_readw(0xa4080020); /* IPRI */ | ||
1223 | sh7724_rstandby_state.iprj = __raw_readw(0xa4080024); /* IPRJ */ | ||
1224 | sh7724_rstandby_state.iprk = __raw_readw(0xa4080028); /* IPRK */ | ||
1225 | sh7724_rstandby_state.iprl = __raw_readw(0xa408002c); /* IPRL */ | ||
1226 | sh7724_rstandby_state.imr0 = __raw_readb(0xa4080080); /* IMR0 */ | ||
1227 | sh7724_rstandby_state.imr1 = __raw_readb(0xa4080084); /* IMR1 */ | ||
1228 | sh7724_rstandby_state.imr2 = __raw_readb(0xa4080088); /* IMR2 */ | ||
1229 | sh7724_rstandby_state.imr3 = __raw_readb(0xa408008c); /* IMR3 */ | ||
1230 | sh7724_rstandby_state.imr4 = __raw_readb(0xa4080090); /* IMR4 */ | ||
1231 | sh7724_rstandby_state.imr5 = __raw_readb(0xa4080094); /* IMR5 */ | ||
1232 | sh7724_rstandby_state.imr6 = __raw_readb(0xa4080098); /* IMR6 */ | ||
1233 | sh7724_rstandby_state.imr7 = __raw_readb(0xa408009c); /* IMR7 */ | ||
1234 | sh7724_rstandby_state.imr8 = __raw_readb(0xa40800a0); /* IMR8 */ | ||
1235 | sh7724_rstandby_state.imr9 = __raw_readb(0xa40800a4); /* IMR9 */ | ||
1236 | sh7724_rstandby_state.imr10 = __raw_readb(0xa40800a8); /* IMR10 */ | ||
1237 | sh7724_rstandby_state.imr11 = __raw_readb(0xa40800ac); /* IMR11 */ | ||
1238 | sh7724_rstandby_state.imr12 = __raw_readb(0xa40800b0); /* IMR12 */ | ||
1239 | |||
1240 | /* RWDT */ | ||
1241 | sh7724_rstandby_state.rwtcnt = __raw_readb(0xa4520000); /* RWTCNT */ | ||
1242 | sh7724_rstandby_state.rwtcnt |= 0x5a00; | ||
1243 | sh7724_rstandby_state.rwtcsr = __raw_readb(0xa4520004); /* RWTCSR */ | ||
1244 | sh7724_rstandby_state.rwtcsr |= 0xa500; | ||
1245 | __raw_writew(sh7724_rstandby_state.rwtcsr & 0x07, 0xa4520004); | ||
1246 | |||
1247 | /* CPG */ | ||
1248 | sh7724_rstandby_state.irdaclk = __raw_readl(0xa4150018); /* IRDACLKCR */ | ||
1249 | sh7724_rstandby_state.spuclk = __raw_readl(0xa415003c); /* SPUCLKCR */ | ||
1250 | |||
1251 | return NOTIFY_DONE; | ||
1252 | } | ||
1253 | |||
1254 | static int sh7724_post_sleep_notifier_call(struct notifier_block *nb, | ||
1255 | unsigned long flags, void *unused) | ||
1256 | { | ||
1257 | if (!(flags & SUSP_SH_RSTANDBY)) | ||
1258 | return NOTIFY_DONE; | ||
1259 | |||
1260 | /* BCR */ | ||
1261 | __raw_writel(sh7724_rstandby_state.mmselr, 0xff800020); /* MMSELR */ | ||
1262 | __raw_writel(sh7724_rstandby_state.cs0bcr, 0xfec10004); /* CS0BCR */ | ||
1263 | __raw_writel(sh7724_rstandby_state.cs4bcr, 0xfec10010); /* CS4BCR */ | ||
1264 | __raw_writel(sh7724_rstandby_state.cs5abcr, 0xfec10014); /* CS5ABCR */ | ||
1265 | __raw_writel(sh7724_rstandby_state.cs5bbcr, 0xfec10018); /* CS5BBCR */ | ||
1266 | __raw_writel(sh7724_rstandby_state.cs6abcr, 0xfec1001c); /* CS6ABCR */ | ||
1267 | __raw_writel(sh7724_rstandby_state.cs6bbcr, 0xfec10020); /* CS6BBCR */ | ||
1268 | __raw_writel(sh7724_rstandby_state.cs4wcr, 0xfec10030); /* CS4WCR */ | ||
1269 | __raw_writel(sh7724_rstandby_state.cs5awcr, 0xfec10034); /* CS5AWCR */ | ||
1270 | __raw_writel(sh7724_rstandby_state.cs5bwcr, 0xfec10038); /* CS5BWCR */ | ||
1271 | __raw_writel(sh7724_rstandby_state.cs6awcr, 0xfec1003c); /* CS6AWCR */ | ||
1272 | __raw_writel(sh7724_rstandby_state.cs6bwcr, 0xfec10040); /* CS6BWCR */ | ||
1273 | |||
1274 | /* INTC */ | ||
1275 | __raw_writew(sh7724_rstandby_state.ipra, 0xa4080000); /* IPRA */ | ||
1276 | __raw_writew(sh7724_rstandby_state.iprb, 0xa4080004); /* IPRB */ | ||
1277 | __raw_writew(sh7724_rstandby_state.iprc, 0xa4080008); /* IPRC */ | ||
1278 | __raw_writew(sh7724_rstandby_state.iprd, 0xa408000c); /* IPRD */ | ||
1279 | __raw_writew(sh7724_rstandby_state.ipre, 0xa4080010); /* IPRE */ | ||
1280 | __raw_writew(sh7724_rstandby_state.iprf, 0xa4080014); /* IPRF */ | ||
1281 | __raw_writew(sh7724_rstandby_state.iprg, 0xa4080018); /* IPRG */ | ||
1282 | __raw_writew(sh7724_rstandby_state.iprh, 0xa408001c); /* IPRH */ | ||
1283 | __raw_writew(sh7724_rstandby_state.ipri, 0xa4080020); /* IPRI */ | ||
1284 | __raw_writew(sh7724_rstandby_state.iprj, 0xa4080024); /* IPRJ */ | ||
1285 | __raw_writew(sh7724_rstandby_state.iprk, 0xa4080028); /* IPRK */ | ||
1286 | __raw_writew(sh7724_rstandby_state.iprl, 0xa408002c); /* IPRL */ | ||
1287 | __raw_writeb(sh7724_rstandby_state.imr0, 0xa4080080); /* IMR0 */ | ||
1288 | __raw_writeb(sh7724_rstandby_state.imr1, 0xa4080084); /* IMR1 */ | ||
1289 | __raw_writeb(sh7724_rstandby_state.imr2, 0xa4080088); /* IMR2 */ | ||
1290 | __raw_writeb(sh7724_rstandby_state.imr3, 0xa408008c); /* IMR3 */ | ||
1291 | __raw_writeb(sh7724_rstandby_state.imr4, 0xa4080090); /* IMR4 */ | ||
1292 | __raw_writeb(sh7724_rstandby_state.imr5, 0xa4080094); /* IMR5 */ | ||
1293 | __raw_writeb(sh7724_rstandby_state.imr6, 0xa4080098); /* IMR6 */ | ||
1294 | __raw_writeb(sh7724_rstandby_state.imr7, 0xa408009c); /* IMR7 */ | ||
1295 | __raw_writeb(sh7724_rstandby_state.imr8, 0xa40800a0); /* IMR8 */ | ||
1296 | __raw_writeb(sh7724_rstandby_state.imr9, 0xa40800a4); /* IMR9 */ | ||
1297 | __raw_writeb(sh7724_rstandby_state.imr10, 0xa40800a8); /* IMR10 */ | ||
1298 | __raw_writeb(sh7724_rstandby_state.imr11, 0xa40800ac); /* IMR11 */ | ||
1299 | __raw_writeb(sh7724_rstandby_state.imr12, 0xa40800b0); /* IMR12 */ | ||
1300 | |||
1301 | /* RWDT */ | ||
1302 | __raw_writew(sh7724_rstandby_state.rwtcnt, 0xa4520000); /* RWTCNT */ | ||
1303 | __raw_writew(sh7724_rstandby_state.rwtcsr, 0xa4520004); /* RWTCSR */ | ||
1304 | |||
1305 | /* CPG */ | ||
1306 | __raw_writel(sh7724_rstandby_state.irdaclk, 0xa4150018); /* IRDACLKCR */ | ||
1307 | __raw_writel(sh7724_rstandby_state.spuclk, 0xa415003c); /* SPUCLKCR */ | ||
1308 | |||
1309 | return NOTIFY_DONE; | ||
1310 | } | ||
1311 | |||
1312 | static struct notifier_block sh7724_pre_sleep_notifier = { | ||
1313 | .notifier_call = sh7724_pre_sleep_notifier_call, | ||
1314 | .priority = SH_MOBILE_PRE(SH_MOBILE_SLEEP_CPU), | ||
1315 | }; | ||
1316 | |||
1317 | static struct notifier_block sh7724_post_sleep_notifier = { | ||
1318 | .notifier_call = sh7724_post_sleep_notifier_call, | ||
1319 | .priority = SH_MOBILE_POST(SH_MOBILE_SLEEP_CPU), | ||
1320 | }; | ||
1321 | |||
1322 | static int __init sh7724_sleep_setup(void) | ||
1323 | { | ||
1324 | atomic_notifier_chain_register(&sh_mobile_pre_sleep_notifier_list, | ||
1325 | &sh7724_pre_sleep_notifier); | ||
1326 | |||
1327 | atomic_notifier_chain_register(&sh_mobile_post_sleep_notifier_list, | ||
1328 | &sh7724_post_sleep_notifier); | ||
1329 | return 0; | ||
1330 | } | ||
1331 | arch_initcall(sh7724_sleep_setup); | ||
1332 | |||
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index c470e15f2e03..e75edf58796a 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c | |||
@@ -17,6 +17,51 @@ | |||
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/sh_timer.h> | 18 | #include <linux/sh_timer.h> |
19 | 19 | ||
20 | static struct plat_sci_port scif2_platform_data = { | ||
21 | .mapbase = 0xfe4b0000, /* SCIF2 */ | ||
22 | .flags = UPF_BOOT_AUTOCONF, | ||
23 | .type = PORT_SCIF, | ||
24 | .irqs = { 40, 40, 40, 40 }, | ||
25 | }; | ||
26 | |||
27 | static struct platform_device scif2_device = { | ||
28 | .name = "sh-sci", | ||
29 | .id = 2, | ||
30 | .dev = { | ||
31 | .platform_data = &scif2_platform_data, | ||
32 | }, | ||
33 | }; | ||
34 | |||
35 | static struct plat_sci_port scif3_platform_data = { | ||
36 | .mapbase = 0xfe4c0000, /* SCIF3 */ | ||
37 | .flags = UPF_BOOT_AUTOCONF, | ||
38 | .type = PORT_SCIF, | ||
39 | .irqs = { 76, 76, 76, 76 }, | ||
40 | }; | ||
41 | |||
42 | static struct platform_device scif3_device = { | ||
43 | .name = "sh-sci", | ||
44 | .id = 3, | ||
45 | .dev = { | ||
46 | .platform_data = &scif3_platform_data, | ||
47 | }, | ||
48 | }; | ||
49 | |||
50 | static struct plat_sci_port scif4_platform_data = { | ||
51 | .mapbase = 0xfe4d0000, /* SCIF4 */ | ||
52 | .flags = UPF_BOOT_AUTOCONF, | ||
53 | .type = PORT_SCIF, | ||
54 | .irqs = { 104, 104, 104, 104 }, | ||
55 | }; | ||
56 | |||
57 | static struct platform_device scif4_device = { | ||
58 | .name = "sh-sci", | ||
59 | .id = 4, | ||
60 | .dev = { | ||
61 | .platform_data = &scif4_platform_data, | ||
62 | }, | ||
63 | }; | ||
64 | |||
20 | static struct sh_timer_config tmu0_platform_data = { | 65 | static struct sh_timer_config tmu0_platform_data = { |
21 | .name = "TMU0", | 66 | .name = "TMU0", |
22 | .channel_offset = 0x04, | 67 | .channel_offset = 0x04, |
@@ -79,39 +124,12 @@ static struct platform_device tmu1_device = { | |||
79 | .num_resources = ARRAY_SIZE(tmu1_resources), | 124 | .num_resources = ARRAY_SIZE(tmu1_resources), |
80 | }; | 125 | }; |
81 | 126 | ||
82 | static struct plat_sci_port sci_platform_data[] = { | ||
83 | { | ||
84 | .mapbase = 0xfe4b0000, /* SCIF2 */ | ||
85 | .flags = UPF_BOOT_AUTOCONF, | ||
86 | .type = PORT_SCIF, | ||
87 | .irqs = { 40, 40, 40, 40 }, | ||
88 | }, { | ||
89 | .mapbase = 0xfe4c0000, /* SCIF3 */ | ||
90 | .flags = UPF_BOOT_AUTOCONF, | ||
91 | .type = PORT_SCIF, | ||
92 | .irqs = { 76, 76, 76, 76 }, | ||
93 | }, { | ||
94 | .mapbase = 0xfe4d0000, /* SCIF4 */ | ||
95 | .flags = UPF_BOOT_AUTOCONF, | ||
96 | .type = PORT_SCIF, | ||
97 | .irqs = { 104, 104, 104, 104 }, | ||
98 | }, { | ||
99 | .flags = 0, | ||
100 | } | ||
101 | }; | ||
102 | |||
103 | static struct platform_device sci_device = { | ||
104 | .name = "sh-sci", | ||
105 | .id = -1, | ||
106 | .dev = { | ||
107 | .platform_data = sci_platform_data, | ||
108 | }, | ||
109 | }; | ||
110 | |||
111 | static struct platform_device *sh7757_devices[] __initdata = { | 127 | static struct platform_device *sh7757_devices[] __initdata = { |
128 | &scif2_device, | ||
129 | &scif3_device, | ||
130 | &scif4_device, | ||
112 | &tmu0_device, | 131 | &tmu0_device, |
113 | &tmu1_device, | 132 | &tmu1_device, |
114 | &sci_device, | ||
115 | }; | 133 | }; |
116 | 134 | ||
117 | static int __init sh7757_devices_setup(void) | 135 | static int __init sh7757_devices_setup(void) |
@@ -121,6 +139,20 @@ static int __init sh7757_devices_setup(void) | |||
121 | } | 139 | } |
122 | arch_initcall(sh7757_devices_setup); | 140 | arch_initcall(sh7757_devices_setup); |
123 | 141 | ||
142 | static struct platform_device *sh7757_early_devices[] __initdata = { | ||
143 | &scif2_device, | ||
144 | &scif3_device, | ||
145 | &scif4_device, | ||
146 | &tmu0_device, | ||
147 | &tmu1_device, | ||
148 | }; | ||
149 | |||
150 | void __init plat_early_device_setup(void) | ||
151 | { | ||
152 | early_platform_add_devices(sh7757_early_devices, | ||
153 | ARRAY_SIZE(sh7757_early_devices)); | ||
154 | } | ||
155 | |||
124 | enum { | 156 | enum { |
125 | UNUSED = 0, | 157 | UNUSED = 0, |
126 | 158 | ||
@@ -455,17 +487,17 @@ static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7757-irl4567", vectors_irl4567, | |||
455 | void __init plat_irq_setup(void) | 487 | void __init plat_irq_setup(void) |
456 | { | 488 | { |
457 | /* disable IRQ3-0 + IRQ7-4 */ | 489 | /* disable IRQ3-0 + IRQ7-4 */ |
458 | ctrl_outl(0xff000000, INTC_INTMSK0); | 490 | __raw_writel(0xff000000, INTC_INTMSK0); |
459 | 491 | ||
460 | /* disable IRL3-0 + IRL7-4 */ | 492 | /* disable IRL3-0 + IRL7-4 */ |
461 | ctrl_outl(0xc0000000, INTC_INTMSK1); | 493 | __raw_writel(0xc0000000, INTC_INTMSK1); |
462 | ctrl_outl(0xfffefffe, INTC_INTMSK2); | 494 | __raw_writel(0xfffefffe, INTC_INTMSK2); |
463 | 495 | ||
464 | /* select IRL mode for IRL3-0 + IRL7-4 */ | 496 | /* select IRL mode for IRL3-0 + IRL7-4 */ |
465 | ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); | 497 | __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); |
466 | 498 | ||
467 | /* disable holding function, ie enable "SH-4 Mode" */ | 499 | /* disable holding function, ie enable "SH-4 Mode" */ |
468 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0); | 500 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0); |
469 | 501 | ||
470 | register_intc_controller(&intc_desc); | 502 | register_intc_controller(&intc_desc); |
471 | } | 503 | } |
@@ -475,32 +507,32 @@ void __init plat_irq_setup_pins(int mode) | |||
475 | switch (mode) { | 507 | switch (mode) { |
476 | case IRQ_MODE_IRQ7654: | 508 | case IRQ_MODE_IRQ7654: |
477 | /* select IRQ mode for IRL7-4 */ | 509 | /* select IRQ mode for IRL7-4 */ |
478 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00400000, INTC_ICR0); | 510 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00400000, INTC_ICR0); |
479 | register_intc_controller(&intc_desc_irq4567); | 511 | register_intc_controller(&intc_desc_irq4567); |
480 | break; | 512 | break; |
481 | case IRQ_MODE_IRQ3210: | 513 | case IRQ_MODE_IRQ3210: |
482 | /* select IRQ mode for IRL3-0 */ | 514 | /* select IRQ mode for IRL3-0 */ |
483 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00800000, INTC_ICR0); | 515 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00800000, INTC_ICR0); |
484 | register_intc_controller(&intc_desc_irq0123); | 516 | register_intc_controller(&intc_desc_irq0123); |
485 | break; | 517 | break; |
486 | case IRQ_MODE_IRL7654: | 518 | case IRQ_MODE_IRL7654: |
487 | /* enable IRL7-4 but don't provide any masking */ | 519 | /* enable IRL7-4 but don't provide any masking */ |
488 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 520 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
489 | ctrl_outl(0x0000fffe, INTC_INTMSKCLR2); | 521 | __raw_writel(0x0000fffe, INTC_INTMSKCLR2); |
490 | break; | 522 | break; |
491 | case IRQ_MODE_IRL3210: | 523 | case IRQ_MODE_IRL3210: |
492 | /* enable IRL0-3 but don't provide any masking */ | 524 | /* enable IRL0-3 but don't provide any masking */ |
493 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 525 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
494 | ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); | 526 | __raw_writel(0xfffe0000, INTC_INTMSKCLR2); |
495 | break; | 527 | break; |
496 | case IRQ_MODE_IRL7654_MASK: | 528 | case IRQ_MODE_IRL7654_MASK: |
497 | /* enable IRL7-4 and mask using cpu intc controller */ | 529 | /* enable IRL7-4 and mask using cpu intc controller */ |
498 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 530 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
499 | register_intc_controller(&intc_desc_irl4567); | 531 | register_intc_controller(&intc_desc_irl4567); |
500 | break; | 532 | break; |
501 | case IRQ_MODE_IRL3210_MASK: | 533 | case IRQ_MODE_IRL3210_MASK: |
502 | /* enable IRL0-3 and mask using cpu intc controller */ | 534 | /* enable IRL0-3 and mask using cpu intc controller */ |
503 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 535 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
504 | register_intc_controller(&intc_desc_irl0123); | 536 | register_intc_controller(&intc_desc_irl0123); |
505 | break; | 537 | break; |
506 | default: | 538 | default: |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c index 4659fff6b842..7f6b0a5f7f82 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c | |||
@@ -16,6 +16,51 @@ | |||
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/serial_sci.h> | 17 | #include <linux/serial_sci.h> |
18 | 18 | ||
19 | static struct plat_sci_port scif0_platform_data = { | ||
20 | .mapbase = 0xffe00000, | ||
21 | .flags = UPF_BOOT_AUTOCONF, | ||
22 | .type = PORT_SCIF, | ||
23 | .irqs = { 40, 40, 40, 40 }, | ||
24 | }; | ||
25 | |||
26 | static struct platform_device scif0_device = { | ||
27 | .name = "sh-sci", | ||
28 | .id = 0, | ||
29 | .dev = { | ||
30 | .platform_data = &scif0_platform_data, | ||
31 | }, | ||
32 | }; | ||
33 | |||
34 | static struct plat_sci_port scif1_platform_data = { | ||
35 | .mapbase = 0xffe08000, | ||
36 | .flags = UPF_BOOT_AUTOCONF, | ||
37 | .type = PORT_SCIF, | ||
38 | .irqs = { 76, 76, 76, 76 }, | ||
39 | }; | ||
40 | |||
41 | static struct platform_device scif1_device = { | ||
42 | .name = "sh-sci", | ||
43 | .id = 1, | ||
44 | .dev = { | ||
45 | .platform_data = &scif1_platform_data, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | static struct plat_sci_port scif2_platform_data = { | ||
50 | .mapbase = 0xffe10000, | ||
51 | .flags = UPF_BOOT_AUTOCONF, | ||
52 | .type = PORT_SCIF, | ||
53 | .irqs = { 104, 104, 104, 104 }, | ||
54 | }; | ||
55 | |||
56 | static struct platform_device scif2_device = { | ||
57 | .name = "sh-sci", | ||
58 | .id = 2, | ||
59 | .dev = { | ||
60 | .platform_data = &scif2_platform_data, | ||
61 | }, | ||
62 | }; | ||
63 | |||
19 | static struct resource rtc_resources[] = { | 64 | static struct resource rtc_resources[] = { |
20 | [0] = { | 65 | [0] = { |
21 | .start = 0xffe80000, | 66 | .start = 0xffe80000, |
@@ -36,35 +81,6 @@ static struct platform_device rtc_device = { | |||
36 | .resource = rtc_resources, | 81 | .resource = rtc_resources, |
37 | }; | 82 | }; |
38 | 83 | ||
39 | static struct plat_sci_port sci_platform_data[] = { | ||
40 | { | ||
41 | .mapbase = 0xffe00000, | ||
42 | .flags = UPF_BOOT_AUTOCONF, | ||
43 | .type = PORT_SCIF, | ||
44 | .irqs = { 40, 40, 40, 40 }, | ||
45 | }, { | ||
46 | .mapbase = 0xffe08000, | ||
47 | .flags = UPF_BOOT_AUTOCONF, | ||
48 | .type = PORT_SCIF, | ||
49 | .irqs = { 76, 76, 76, 76 }, | ||
50 | }, { | ||
51 | .mapbase = 0xffe10000, | ||
52 | .flags = UPF_BOOT_AUTOCONF, | ||
53 | .type = PORT_SCIF, | ||
54 | .irqs = { 104, 104, 104, 104 }, | ||
55 | }, { | ||
56 | .flags = 0, | ||
57 | } | ||
58 | }; | ||
59 | |||
60 | static struct platform_device sci_device = { | ||
61 | .name = "sh-sci", | ||
62 | .id = -1, | ||
63 | .dev = { | ||
64 | .platform_data = sci_platform_data, | ||
65 | }, | ||
66 | }; | ||
67 | |||
68 | static struct resource usb_ohci_resources[] = { | 84 | static struct resource usb_ohci_resources[] = { |
69 | [0] = { | 85 | [0] = { |
70 | .start = 0xffec8000, | 86 | .start = 0xffec8000, |
@@ -297,6 +313,9 @@ static struct platform_device tmu5_device = { | |||
297 | }; | 313 | }; |
298 | 314 | ||
299 | static struct platform_device *sh7763_devices[] __initdata = { | 315 | static struct platform_device *sh7763_devices[] __initdata = { |
316 | &scif0_device, | ||
317 | &scif1_device, | ||
318 | &scif2_device, | ||
300 | &tmu0_device, | 319 | &tmu0_device, |
301 | &tmu1_device, | 320 | &tmu1_device, |
302 | &tmu2_device, | 321 | &tmu2_device, |
@@ -304,7 +323,6 @@ static struct platform_device *sh7763_devices[] __initdata = { | |||
304 | &tmu4_device, | 323 | &tmu4_device, |
305 | &tmu5_device, | 324 | &tmu5_device, |
306 | &rtc_device, | 325 | &rtc_device, |
307 | &sci_device, | ||
308 | &usb_ohci_device, | 326 | &usb_ohci_device, |
309 | &usbf_device, | 327 | &usbf_device, |
310 | }; | 328 | }; |
@@ -317,6 +335,9 @@ static int __init sh7763_devices_setup(void) | |||
317 | arch_initcall(sh7763_devices_setup); | 335 | arch_initcall(sh7763_devices_setup); |
318 | 336 | ||
319 | static struct platform_device *sh7763_early_devices[] __initdata = { | 337 | static struct platform_device *sh7763_early_devices[] __initdata = { |
338 | &scif0_device, | ||
339 | &scif1_device, | ||
340 | &scif2_device, | ||
320 | &tmu0_device, | 341 | &tmu0_device, |
321 | &tmu1_device, | 342 | &tmu1_device, |
322 | &tmu2_device, | 343 | &tmu2_device, |
@@ -517,11 +538,11 @@ static DECLARE_INTC_DESC(intc_irl3210_desc, "sh7763-irl3210", irl_vectors, | |||
517 | void __init plat_irq_setup(void) | 538 | void __init plat_irq_setup(void) |
518 | { | 539 | { |
519 | /* disable IRQ7-0 */ | 540 | /* disable IRQ7-0 */ |
520 | ctrl_outl(0xff000000, INTC_INTMSK0); | 541 | __raw_writel(0xff000000, INTC_INTMSK0); |
521 | 542 | ||
522 | /* disable IRL3-0 + IRL7-4 */ | 543 | /* disable IRL3-0 + IRL7-4 */ |
523 | ctrl_outl(0xc0000000, INTC_INTMSK1); | 544 | __raw_writel(0xc0000000, INTC_INTMSK1); |
524 | ctrl_outl(0xfffefffe, INTC_INTMSK2); | 545 | __raw_writel(0xfffefffe, INTC_INTMSK2); |
525 | 546 | ||
526 | register_intc_controller(&intc_desc); | 547 | register_intc_controller(&intc_desc); |
527 | } | 548 | } |
@@ -531,27 +552,27 @@ void __init plat_irq_setup_pins(int mode) | |||
531 | switch (mode) { | 552 | switch (mode) { |
532 | case IRQ_MODE_IRQ: | 553 | case IRQ_MODE_IRQ: |
533 | /* select IRQ mode for IRL3-0 + IRL7-4 */ | 554 | /* select IRQ mode for IRL3-0 + IRL7-4 */ |
534 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00c00000, INTC_ICR0); | 555 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00c00000, INTC_ICR0); |
535 | register_intc_controller(&intc_irq_desc); | 556 | register_intc_controller(&intc_irq_desc); |
536 | break; | 557 | break; |
537 | case IRQ_MODE_IRL7654: | 558 | case IRQ_MODE_IRL7654: |
538 | /* enable IRL7-4 but don't provide any masking */ | 559 | /* enable IRL7-4 but don't provide any masking */ |
539 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 560 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
540 | ctrl_outl(0x0000fffe, INTC_INTMSKCLR2); | 561 | __raw_writel(0x0000fffe, INTC_INTMSKCLR2); |
541 | break; | 562 | break; |
542 | case IRQ_MODE_IRL3210: | 563 | case IRQ_MODE_IRL3210: |
543 | /* enable IRL0-3 but don't provide any masking */ | 564 | /* enable IRL0-3 but don't provide any masking */ |
544 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 565 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
545 | ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); | 566 | __raw_writel(0xfffe0000, INTC_INTMSKCLR2); |
546 | break; | 567 | break; |
547 | case IRQ_MODE_IRL7654_MASK: | 568 | case IRQ_MODE_IRL7654_MASK: |
548 | /* enable IRL7-4 and mask using cpu intc controller */ | 569 | /* enable IRL7-4 and mask using cpu intc controller */ |
549 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 570 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
550 | register_intc_controller(&intc_irl7654_desc); | 571 | register_intc_controller(&intc_irl7654_desc); |
551 | break; | 572 | break; |
552 | case IRQ_MODE_IRL3210_MASK: | 573 | case IRQ_MODE_IRL3210_MASK: |
553 | /* enable IRL0-3 and mask using cpu intc controller */ | 574 | /* enable IRL0-3 and mask using cpu intc controller */ |
554 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 575 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
555 | register_intc_controller(&intc_irl3210_desc); | 576 | register_intc_controller(&intc_irl3210_desc); |
556 | break; | 577 | break; |
557 | default: | 578 | default: |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c index eead08d89d32..86d681ecf90e 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c | |||
@@ -14,67 +14,153 @@ | |||
14 | #include <linux/sh_timer.h> | 14 | #include <linux/sh_timer.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | 16 | ||
17 | static struct plat_sci_port sci_platform_data[] = { | 17 | static struct plat_sci_port scif0_platform_data = { |
18 | { | 18 | .mapbase = 0xff923000, |
19 | .mapbase = 0xff923000, | 19 | .flags = UPF_BOOT_AUTOCONF, |
20 | .flags = UPF_BOOT_AUTOCONF, | 20 | .type = PORT_SCIF, |
21 | .type = PORT_SCIF, | 21 | .irqs = { 61, 61, 61, 61 }, |
22 | .irqs = { 61, 61, 61, 61 }, | 22 | }; |
23 | }, { | 23 | |
24 | .mapbase = 0xff924000, | 24 | static struct platform_device scif0_device = { |
25 | .flags = UPF_BOOT_AUTOCONF, | 25 | .name = "sh-sci", |
26 | .type = PORT_SCIF, | 26 | .id = 0, |
27 | .irqs = { 62, 62, 62, 62 }, | 27 | .dev = { |
28 | }, { | 28 | .platform_data = &scif0_platform_data, |
29 | .mapbase = 0xff925000, | 29 | }, |
30 | .flags = UPF_BOOT_AUTOCONF, | 30 | }; |
31 | .type = PORT_SCIF, | 31 | |
32 | .irqs = { 63, 63, 63, 63 }, | 32 | static struct plat_sci_port scif1_platform_data = { |
33 | }, { | 33 | .mapbase = 0xff924000, |
34 | .mapbase = 0xff926000, | 34 | .flags = UPF_BOOT_AUTOCONF, |
35 | .flags = UPF_BOOT_AUTOCONF, | 35 | .type = PORT_SCIF, |
36 | .type = PORT_SCIF, | 36 | .irqs = { 62, 62, 62, 62 }, |
37 | .irqs = { 64, 64, 64, 64 }, | 37 | }; |
38 | }, { | 38 | |
39 | .mapbase = 0xff927000, | 39 | static struct platform_device scif1_device = { |
40 | .flags = UPF_BOOT_AUTOCONF, | 40 | .name = "sh-sci", |
41 | .type = PORT_SCIF, | 41 | .id = 1, |
42 | .irqs = { 65, 65, 65, 65 }, | 42 | .dev = { |
43 | }, { | 43 | .platform_data = &scif1_platform_data, |
44 | .mapbase = 0xff928000, | 44 | }, |
45 | .flags = UPF_BOOT_AUTOCONF, | 45 | }; |
46 | .type = PORT_SCIF, | 46 | |
47 | .irqs = { 66, 66, 66, 66 }, | 47 | static struct plat_sci_port scif2_platform_data = { |
48 | }, { | 48 | .mapbase = 0xff925000, |
49 | .mapbase = 0xff929000, | 49 | .flags = UPF_BOOT_AUTOCONF, |
50 | .flags = UPF_BOOT_AUTOCONF, | 50 | .type = PORT_SCIF, |
51 | .type = PORT_SCIF, | 51 | .irqs = { 63, 63, 63, 63 }, |
52 | .irqs = { 67, 67, 67, 67 }, | 52 | }; |
53 | }, { | 53 | |
54 | .mapbase = 0xff92a000, | 54 | static struct platform_device scif2_device = { |
55 | .flags = UPF_BOOT_AUTOCONF, | 55 | .name = "sh-sci", |
56 | .type = PORT_SCIF, | 56 | .id = 2, |
57 | .irqs = { 68, 68, 68, 68 }, | 57 | .dev = { |
58 | }, { | 58 | .platform_data = &scif2_platform_data, |
59 | .mapbase = 0xff92b000, | 59 | }, |
60 | .flags = UPF_BOOT_AUTOCONF, | 60 | }; |
61 | .type = PORT_SCIF, | 61 | |
62 | .irqs = { 69, 69, 69, 69 }, | 62 | static struct plat_sci_port scif3_platform_data = { |
63 | }, { | 63 | .mapbase = 0xff926000, |
64 | .mapbase = 0xff92c000, | 64 | .flags = UPF_BOOT_AUTOCONF, |
65 | .flags = UPF_BOOT_AUTOCONF, | 65 | .type = PORT_SCIF, |
66 | .type = PORT_SCIF, | 66 | .irqs = { 64, 64, 64, 64 }, |
67 | .irqs = { 70, 70, 70, 70 }, | 67 | }; |
68 | }, { | 68 | |
69 | .flags = 0, | 69 | static struct platform_device scif3_device = { |
70 | } | 70 | .name = "sh-sci", |
71 | .id = 3, | ||
72 | .dev = { | ||
73 | .platform_data = &scif3_platform_data, | ||
74 | }, | ||
75 | }; | ||
76 | |||
77 | static struct plat_sci_port scif4_platform_data = { | ||
78 | .mapbase = 0xff927000, | ||
79 | .flags = UPF_BOOT_AUTOCONF, | ||
80 | .type = PORT_SCIF, | ||
81 | .irqs = { 65, 65, 65, 65 }, | ||
82 | }; | ||
83 | |||
84 | static struct platform_device scif4_device = { | ||
85 | .name = "sh-sci", | ||
86 | .id = 4, | ||
87 | .dev = { | ||
88 | .platform_data = &scif4_platform_data, | ||
89 | }, | ||
90 | }; | ||
91 | |||
92 | static struct plat_sci_port scif5_platform_data = { | ||
93 | .mapbase = 0xff928000, | ||
94 | .flags = UPF_BOOT_AUTOCONF, | ||
95 | .type = PORT_SCIF, | ||
96 | .irqs = { 66, 66, 66, 66 }, | ||
97 | }; | ||
98 | |||
99 | static struct platform_device scif5_device = { | ||
100 | .name = "sh-sci", | ||
101 | .id = 5, | ||
102 | .dev = { | ||
103 | .platform_data = &scif5_platform_data, | ||
104 | }, | ||
105 | }; | ||
106 | |||
107 | static struct plat_sci_port scif6_platform_data = { | ||
108 | .mapbase = 0xff929000, | ||
109 | .flags = UPF_BOOT_AUTOCONF, | ||
110 | .type = PORT_SCIF, | ||
111 | .irqs = { 67, 67, 67, 67 }, | ||
112 | }; | ||
113 | |||
114 | static struct platform_device scif6_device = { | ||
115 | .name = "sh-sci", | ||
116 | .id = 6, | ||
117 | .dev = { | ||
118 | .platform_data = &scif6_platform_data, | ||
119 | }, | ||
120 | }; | ||
121 | |||
122 | static struct plat_sci_port scif7_platform_data = { | ||
123 | .mapbase = 0xff92a000, | ||
124 | .flags = UPF_BOOT_AUTOCONF, | ||
125 | .type = PORT_SCIF, | ||
126 | .irqs = { 68, 68, 68, 68 }, | ||
127 | }; | ||
128 | |||
129 | static struct platform_device scif7_device = { | ||
130 | .name = "sh-sci", | ||
131 | .id = 7, | ||
132 | .dev = { | ||
133 | .platform_data = &scif7_platform_data, | ||
134 | }, | ||
135 | }; | ||
136 | |||
137 | static struct plat_sci_port scif8_platform_data = { | ||
138 | .mapbase = 0xff92b000, | ||
139 | .flags = UPF_BOOT_AUTOCONF, | ||
140 | .type = PORT_SCIF, | ||
141 | .irqs = { 69, 69, 69, 69 }, | ||
142 | }; | ||
143 | |||
144 | static struct platform_device scif8_device = { | ||
145 | .name = "sh-sci", | ||
146 | .id = 8, | ||
147 | .dev = { | ||
148 | .platform_data = &scif8_platform_data, | ||
149 | }, | ||
150 | }; | ||
151 | |||
152 | static struct plat_sci_port scif9_platform_data = { | ||
153 | .mapbase = 0xff92c000, | ||
154 | .flags = UPF_BOOT_AUTOCONF, | ||
155 | .type = PORT_SCIF, | ||
156 | .irqs = { 70, 70, 70, 70 }, | ||
71 | }; | 157 | }; |
72 | 158 | ||
73 | static struct platform_device sci_device = { | 159 | static struct platform_device scif9_device = { |
74 | .name = "sh-sci", | 160 | .name = "sh-sci", |
75 | .id = -1, | 161 | .id = 9, |
76 | .dev = { | 162 | .dev = { |
77 | .platform_data = sci_platform_data, | 163 | .platform_data = &scif9_platform_data, |
78 | }, | 164 | }, |
79 | }; | 165 | }; |
80 | 166 | ||
@@ -351,6 +437,16 @@ static struct platform_device tmu8_device = { | |||
351 | }; | 437 | }; |
352 | 438 | ||
353 | static struct platform_device *sh7770_devices[] __initdata = { | 439 | static struct platform_device *sh7770_devices[] __initdata = { |
440 | &scif0_device, | ||
441 | &scif1_device, | ||
442 | &scif2_device, | ||
443 | &scif3_device, | ||
444 | &scif4_device, | ||
445 | &scif5_device, | ||
446 | &scif6_device, | ||
447 | &scif7_device, | ||
448 | &scif8_device, | ||
449 | &scif9_device, | ||
354 | &tmu0_device, | 450 | &tmu0_device, |
355 | &tmu1_device, | 451 | &tmu1_device, |
356 | &tmu2_device, | 452 | &tmu2_device, |
@@ -360,7 +456,6 @@ static struct platform_device *sh7770_devices[] __initdata = { | |||
360 | &tmu6_device, | 456 | &tmu6_device, |
361 | &tmu7_device, | 457 | &tmu7_device, |
362 | &tmu8_device, | 458 | &tmu8_device, |
363 | &sci_device, | ||
364 | }; | 459 | }; |
365 | 460 | ||
366 | static int __init sh7770_devices_setup(void) | 461 | static int __init sh7770_devices_setup(void) |
@@ -371,6 +466,16 @@ static int __init sh7770_devices_setup(void) | |||
371 | arch_initcall(sh7770_devices_setup); | 466 | arch_initcall(sh7770_devices_setup); |
372 | 467 | ||
373 | static struct platform_device *sh7770_early_devices[] __initdata = { | 468 | static struct platform_device *sh7770_early_devices[] __initdata = { |
469 | &scif0_device, | ||
470 | &scif1_device, | ||
471 | &scif2_device, | ||
472 | &scif3_device, | ||
473 | &scif4_device, | ||
474 | &scif5_device, | ||
475 | &scif6_device, | ||
476 | &scif7_device, | ||
477 | &scif8_device, | ||
478 | &scif9_device, | ||
374 | &tmu0_device, | 479 | &tmu0_device, |
375 | &tmu1_device, | 480 | &tmu1_device, |
376 | &tmu2_device, | 481 | &tmu2_device, |
@@ -589,17 +694,17 @@ static DECLARE_INTC_DESC(intc_irl3210_desc, "sh7780-irl3210", irl_vectors, | |||
589 | void __init plat_irq_setup(void) | 694 | void __init plat_irq_setup(void) |
590 | { | 695 | { |
591 | /* disable IRQ7-0 */ | 696 | /* disable IRQ7-0 */ |
592 | ctrl_outl(0xff000000, INTC_INTMSK0); | 697 | __raw_writel(0xff000000, INTC_INTMSK0); |
593 | 698 | ||
594 | /* disable IRL3-0 + IRL7-4 */ | 699 | /* disable IRL3-0 + IRL7-4 */ |
595 | ctrl_outl(0xc0000000, INTC_INTMSK1); | 700 | __raw_writel(0xc0000000, INTC_INTMSK1); |
596 | ctrl_outl(0xfffefffe, INTC_INTMSK2); | 701 | __raw_writel(0xfffefffe, INTC_INTMSK2); |
597 | 702 | ||
598 | /* select IRL mode for IRL3-0 + IRL7-4 */ | 703 | /* select IRL mode for IRL3-0 + IRL7-4 */ |
599 | ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); | 704 | __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); |
600 | 705 | ||
601 | /* disable holding function, ie enable "SH-4 Mode" */ | 706 | /* disable holding function, ie enable "SH-4 Mode" */ |
602 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0); | 707 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0); |
603 | 708 | ||
604 | register_intc_controller(&intc_desc); | 709 | register_intc_controller(&intc_desc); |
605 | } | 710 | } |
@@ -609,27 +714,27 @@ void __init plat_irq_setup_pins(int mode) | |||
609 | switch (mode) { | 714 | switch (mode) { |
610 | case IRQ_MODE_IRQ: | 715 | case IRQ_MODE_IRQ: |
611 | /* select IRQ mode for IRL3-0 + IRL7-4 */ | 716 | /* select IRQ mode for IRL3-0 + IRL7-4 */ |
612 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00c00000, INTC_ICR0); | 717 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00c00000, INTC_ICR0); |
613 | register_intc_controller(&intc_irq_desc); | 718 | register_intc_controller(&intc_irq_desc); |
614 | break; | 719 | break; |
615 | case IRQ_MODE_IRL7654: | 720 | case IRQ_MODE_IRL7654: |
616 | /* enable IRL7-4 but don't provide any masking */ | 721 | /* enable IRL7-4 but don't provide any masking */ |
617 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 722 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
618 | ctrl_outl(0x0000fffe, INTC_INTMSKCLR2); | 723 | __raw_writel(0x0000fffe, INTC_INTMSKCLR2); |
619 | break; | 724 | break; |
620 | case IRQ_MODE_IRL3210: | 725 | case IRQ_MODE_IRL3210: |
621 | /* enable IRL0-3 but don't provide any masking */ | 726 | /* enable IRL0-3 but don't provide any masking */ |
622 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 727 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
623 | ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); | 728 | __raw_writel(0xfffe0000, INTC_INTMSKCLR2); |
624 | break; | 729 | break; |
625 | case IRQ_MODE_IRL7654_MASK: | 730 | case IRQ_MODE_IRL7654_MASK: |
626 | /* enable IRL7-4 and mask using cpu intc controller */ | 731 | /* enable IRL7-4 and mask using cpu intc controller */ |
627 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 732 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
628 | register_intc_controller(&intc_irl7654_desc); | 733 | register_intc_controller(&intc_irl7654_desc); |
629 | break; | 734 | break; |
630 | case IRQ_MODE_IRL3210_MASK: | 735 | case IRQ_MODE_IRL3210_MASK: |
631 | /* enable IRL0-3 and mask using cpu intc controller */ | 736 | /* enable IRL0-3 and mask using cpu intc controller */ |
632 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 737 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
633 | register_intc_controller(&intc_irl3210_desc); | 738 | register_intc_controller(&intc_irl3210_desc); |
634 | break; | 739 | break; |
635 | default: | 740 | default: |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c index 12ff56f19c5c..02e792c90de6 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c | |||
@@ -13,7 +13,40 @@ | |||
13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/serial_sci.h> | 14 | #include <linux/serial_sci.h> |
15 | #include <linux/sh_timer.h> | 15 | #include <linux/sh_timer.h> |
16 | #include <asm/dma-sh.h> | 16 | |
17 | #include <asm/dmaengine.h> | ||
18 | |||
19 | #include <cpu/dma-register.h> | ||
20 | |||
21 | static struct plat_sci_port scif0_platform_data = { | ||
22 | .mapbase = 0xffe00000, | ||
23 | .flags = UPF_BOOT_AUTOCONF, | ||
24 | .type = PORT_SCIF, | ||
25 | .irqs = { 40, 40, 40, 40 }, | ||
26 | }; | ||
27 | |||
28 | static struct platform_device scif0_device = { | ||
29 | .name = "sh-sci", | ||
30 | .id = 0, | ||
31 | .dev = { | ||
32 | .platform_data = &scif0_platform_data, | ||
33 | }, | ||
34 | }; | ||
35 | |||
36 | static struct plat_sci_port scif1_platform_data = { | ||
37 | .mapbase = 0xffe10000, | ||
38 | .flags = UPF_BOOT_AUTOCONF, | ||
39 | .type = PORT_SCIF, | ||
40 | .irqs = { 76, 76, 76, 76 }, | ||
41 | }; | ||
42 | |||
43 | static struct platform_device scif1_device = { | ||
44 | .name = "sh-sci", | ||
45 | .id = 1, | ||
46 | .dev = { | ||
47 | .platform_data = &scif1_platform_data, | ||
48 | }, | ||
49 | }; | ||
17 | 50 | ||
18 | static struct sh_timer_config tmu0_platform_data = { | 51 | static struct sh_timer_config tmu0_platform_data = { |
19 | .name = "TMU0", | 52 | .name = "TMU0", |
@@ -217,43 +250,137 @@ static struct platform_device rtc_device = { | |||
217 | .resource = rtc_resources, | 250 | .resource = rtc_resources, |
218 | }; | 251 | }; |
219 | 252 | ||
220 | static struct plat_sci_port sci_platform_data[] = { | 253 | /* DMA */ |
254 | static struct sh_dmae_channel sh7780_dmae0_channels[] = { | ||
221 | { | 255 | { |
222 | .mapbase = 0xffe00000, | 256 | .offset = 0, |
223 | .flags = UPF_BOOT_AUTOCONF, | 257 | .dmars = 0, |
224 | .type = PORT_SCIF, | 258 | .dmars_bit = 0, |
225 | .irqs = { 40, 40, 40, 40 }, | 259 | }, { |
260 | .offset = 0x10, | ||
261 | .dmars = 0, | ||
262 | .dmars_bit = 8, | ||
263 | }, { | ||
264 | .offset = 0x20, | ||
265 | .dmars = 4, | ||
266 | .dmars_bit = 0, | ||
267 | }, { | ||
268 | .offset = 0x30, | ||
269 | .dmars = 4, | ||
270 | .dmars_bit = 8, | ||
226 | }, { | 271 | }, { |
227 | .mapbase = 0xffe10000, | 272 | .offset = 0x50, |
228 | .flags = UPF_BOOT_AUTOCONF, | 273 | .dmars = 8, |
229 | .type = PORT_SCIF, | 274 | .dmars_bit = 0, |
230 | .irqs = { 76, 76, 76, 76 }, | ||
231 | }, { | 275 | }, { |
232 | .flags = 0, | 276 | .offset = 0x60, |
277 | .dmars = 8, | ||
278 | .dmars_bit = 8, | ||
233 | } | 279 | } |
234 | }; | 280 | }; |
235 | 281 | ||
236 | static struct platform_device sci_device = { | 282 | static struct sh_dmae_channel sh7780_dmae1_channels[] = { |
237 | .name = "sh-sci", | 283 | { |
238 | .id = -1, | 284 | .offset = 0, |
239 | .dev = { | 285 | }, { |
240 | .platform_data = sci_platform_data, | 286 | .offset = 0x10, |
287 | }, { | ||
288 | .offset = 0x20, | ||
289 | }, { | ||
290 | .offset = 0x30, | ||
291 | }, { | ||
292 | .offset = 0x50, | ||
293 | }, { | ||
294 | .offset = 0x60, | ||
295 | } | ||
296 | }; | ||
297 | |||
298 | static unsigned int ts_shift[] = TS_SHIFT; | ||
299 | |||
300 | static struct sh_dmae_pdata dma0_platform_data = { | ||
301 | .channel = sh7780_dmae0_channels, | ||
302 | .channel_num = ARRAY_SIZE(sh7780_dmae0_channels), | ||
303 | .ts_low_shift = CHCR_TS_LOW_SHIFT, | ||
304 | .ts_low_mask = CHCR_TS_LOW_MASK, | ||
305 | .ts_high_shift = CHCR_TS_HIGH_SHIFT, | ||
306 | .ts_high_mask = CHCR_TS_HIGH_MASK, | ||
307 | .ts_shift = ts_shift, | ||
308 | .ts_shift_num = ARRAY_SIZE(ts_shift), | ||
309 | .dmaor_init = DMAOR_INIT, | ||
310 | }; | ||
311 | |||
312 | static struct sh_dmae_pdata dma1_platform_data = { | ||
313 | .channel = sh7780_dmae1_channels, | ||
314 | .channel_num = ARRAY_SIZE(sh7780_dmae1_channels), | ||
315 | .ts_low_shift = CHCR_TS_LOW_SHIFT, | ||
316 | .ts_low_mask = CHCR_TS_LOW_MASK, | ||
317 | .ts_high_shift = CHCR_TS_HIGH_SHIFT, | ||
318 | .ts_high_mask = CHCR_TS_HIGH_MASK, | ||
319 | .ts_shift = ts_shift, | ||
320 | .ts_shift_num = ARRAY_SIZE(ts_shift), | ||
321 | .dmaor_init = DMAOR_INIT, | ||
322 | }; | ||
323 | |||
324 | static struct resource sh7780_dmae0_resources[] = { | ||
325 | [0] = { | ||
326 | /* Channel registers and DMAOR */ | ||
327 | .start = 0xfc808020, | ||
328 | .end = 0xfc80808f, | ||
329 | .flags = IORESOURCE_MEM, | ||
330 | }, | ||
331 | [1] = { | ||
332 | /* DMARSx */ | ||
333 | .start = 0xfc809000, | ||
334 | .end = 0xfc80900b, | ||
335 | .flags = IORESOURCE_MEM, | ||
336 | }, | ||
337 | { | ||
338 | /* Real DMA error IRQ is 38, and channel IRQs are 34-37, 44-45 */ | ||
339 | .start = 34, | ||
340 | .end = 34, | ||
341 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, | ||
241 | }, | 342 | }, |
242 | }; | 343 | }; |
243 | 344 | ||
244 | static struct sh_dmae_pdata dma_platform_data = { | 345 | static struct resource sh7780_dmae1_resources[] = { |
245 | .mode = (SHDMA_MIX_IRQ | SHDMA_DMAOR1), | 346 | [0] = { |
347 | /* Channel registers and DMAOR */ | ||
348 | .start = 0xfc818020, | ||
349 | .end = 0xfc81808f, | ||
350 | .flags = IORESOURCE_MEM, | ||
351 | }, | ||
352 | /* DMAC1 has no DMARS */ | ||
353 | { | ||
354 | /* Real DMA error IRQ is 38, and channel IRQs are 46-47, 92-95 */ | ||
355 | .start = 46, | ||
356 | .end = 46, | ||
357 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, | ||
358 | }, | ||
246 | }; | 359 | }; |
247 | 360 | ||
248 | static struct platform_device dma_device = { | 361 | static struct platform_device dma0_device = { |
249 | .name = "sh-dma-engine", | 362 | .name = "sh-dma-engine", |
250 | .id = -1, | 363 | .id = 0, |
364 | .resource = sh7780_dmae0_resources, | ||
365 | .num_resources = ARRAY_SIZE(sh7780_dmae0_resources), | ||
251 | .dev = { | 366 | .dev = { |
252 | .platform_data = &dma_platform_data, | 367 | .platform_data = &dma0_platform_data, |
368 | }, | ||
369 | }; | ||
370 | |||
371 | static struct platform_device dma1_device = { | ||
372 | .name = "sh-dma-engine", | ||
373 | .id = 1, | ||
374 | .resource = sh7780_dmae1_resources, | ||
375 | .num_resources = ARRAY_SIZE(sh7780_dmae1_resources), | ||
376 | .dev = { | ||
377 | .platform_data = &dma1_platform_data, | ||
253 | }, | 378 | }, |
254 | }; | 379 | }; |
255 | 380 | ||
256 | static struct platform_device *sh7780_devices[] __initdata = { | 381 | static struct platform_device *sh7780_devices[] __initdata = { |
382 | &scif0_device, | ||
383 | &scif1_device, | ||
257 | &tmu0_device, | 384 | &tmu0_device, |
258 | &tmu1_device, | 385 | &tmu1_device, |
259 | &tmu2_device, | 386 | &tmu2_device, |
@@ -261,8 +388,8 @@ static struct platform_device *sh7780_devices[] __initdata = { | |||
261 | &tmu4_device, | 388 | &tmu4_device, |
262 | &tmu5_device, | 389 | &tmu5_device, |
263 | &rtc_device, | 390 | &rtc_device, |
264 | &sci_device, | 391 | &dma0_device, |
265 | &dma_device, | 392 | &dma1_device, |
266 | }; | 393 | }; |
267 | 394 | ||
268 | static int __init sh7780_devices_setup(void) | 395 | static int __init sh7780_devices_setup(void) |
@@ -271,8 +398,9 @@ static int __init sh7780_devices_setup(void) | |||
271 | ARRAY_SIZE(sh7780_devices)); | 398 | ARRAY_SIZE(sh7780_devices)); |
272 | } | 399 | } |
273 | arch_initcall(sh7780_devices_setup); | 400 | arch_initcall(sh7780_devices_setup); |
274 | |||
275 | static struct platform_device *sh7780_early_devices[] __initdata = { | 401 | static struct platform_device *sh7780_early_devices[] __initdata = { |
402 | &scif0_device, | ||
403 | &scif1_device, | ||
276 | &tmu0_device, | 404 | &tmu0_device, |
277 | &tmu1_device, | 405 | &tmu1_device, |
278 | &tmu2_device, | 406 | &tmu2_device, |
@@ -453,17 +581,17 @@ static DECLARE_INTC_DESC(intc_irl3210_desc, "sh7780-irl3210", irl_vectors, | |||
453 | void __init plat_irq_setup(void) | 581 | void __init plat_irq_setup(void) |
454 | { | 582 | { |
455 | /* disable IRQ7-0 */ | 583 | /* disable IRQ7-0 */ |
456 | ctrl_outl(0xff000000, INTC_INTMSK0); | 584 | __raw_writel(0xff000000, INTC_INTMSK0); |
457 | 585 | ||
458 | /* disable IRL3-0 + IRL7-4 */ | 586 | /* disable IRL3-0 + IRL7-4 */ |
459 | ctrl_outl(0xc0000000, INTC_INTMSK1); | 587 | __raw_writel(0xc0000000, INTC_INTMSK1); |
460 | ctrl_outl(0xfffefffe, INTC_INTMSK2); | 588 | __raw_writel(0xfffefffe, INTC_INTMSK2); |
461 | 589 | ||
462 | /* select IRL mode for IRL3-0 + IRL7-4 */ | 590 | /* select IRL mode for IRL3-0 + IRL7-4 */ |
463 | ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); | 591 | __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); |
464 | 592 | ||
465 | /* disable holding function, ie enable "SH-4 Mode" */ | 593 | /* disable holding function, ie enable "SH-4 Mode" */ |
466 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0); | 594 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0); |
467 | 595 | ||
468 | register_intc_controller(&intc_desc); | 596 | register_intc_controller(&intc_desc); |
469 | } | 597 | } |
@@ -473,27 +601,27 @@ void __init plat_irq_setup_pins(int mode) | |||
473 | switch (mode) { | 601 | switch (mode) { |
474 | case IRQ_MODE_IRQ: | 602 | case IRQ_MODE_IRQ: |
475 | /* select IRQ mode for IRL3-0 + IRL7-4 */ | 603 | /* select IRQ mode for IRL3-0 + IRL7-4 */ |
476 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00c00000, INTC_ICR0); | 604 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00c00000, INTC_ICR0); |
477 | register_intc_controller(&intc_irq_desc); | 605 | register_intc_controller(&intc_irq_desc); |
478 | break; | 606 | break; |
479 | case IRQ_MODE_IRL7654: | 607 | case IRQ_MODE_IRL7654: |
480 | /* enable IRL7-4 but don't provide any masking */ | 608 | /* enable IRL7-4 but don't provide any masking */ |
481 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 609 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
482 | ctrl_outl(0x0000fffe, INTC_INTMSKCLR2); | 610 | __raw_writel(0x0000fffe, INTC_INTMSKCLR2); |
483 | break; | 611 | break; |
484 | case IRQ_MODE_IRL3210: | 612 | case IRQ_MODE_IRL3210: |
485 | /* enable IRL0-3 but don't provide any masking */ | 613 | /* enable IRL0-3 but don't provide any masking */ |
486 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 614 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
487 | ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); | 615 | __raw_writel(0xfffe0000, INTC_INTMSKCLR2); |
488 | break; | 616 | break; |
489 | case IRQ_MODE_IRL7654_MASK: | 617 | case IRQ_MODE_IRL7654_MASK: |
490 | /* enable IRL7-4 and mask using cpu intc controller */ | 618 | /* enable IRL7-4 and mask using cpu intc controller */ |
491 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 619 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
492 | register_intc_controller(&intc_irl7654_desc); | 620 | register_intc_controller(&intc_irl7654_desc); |
493 | break; | 621 | break; |
494 | case IRQ_MODE_IRL3210_MASK: | 622 | case IRQ_MODE_IRL3210_MASK: |
495 | /* enable IRL0-3 and mask using cpu intc controller */ | 623 | /* enable IRL0-3 and mask using cpu intc controller */ |
496 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 624 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
497 | register_intc_controller(&intc_irl3210_desc); | 625 | register_intc_controller(&intc_irl3210_desc); |
498 | break; | 626 | break; |
499 | default: | 627 | default: |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c index 7f6c718b6c36..1fcd88b1671e 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c | |||
@@ -14,8 +14,108 @@ | |||
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
16 | #include <linux/sh_timer.h> | 16 | #include <linux/sh_timer.h> |
17 | |||
18 | #include <asm/dmaengine.h> | ||
17 | #include <asm/mmzone.h> | 19 | #include <asm/mmzone.h> |
18 | 20 | ||
21 | #include <cpu/dma-register.h> | ||
22 | |||
23 | static struct plat_sci_port scif0_platform_data = { | ||
24 | .mapbase = 0xffea0000, | ||
25 | .flags = UPF_BOOT_AUTOCONF, | ||
26 | .type = PORT_SCIF, | ||
27 | .irqs = { 40, 40, 40, 40 }, | ||
28 | .clk = "scif_fck", | ||
29 | }; | ||
30 | |||
31 | static struct platform_device scif0_device = { | ||
32 | .name = "sh-sci", | ||
33 | .id = 0, | ||
34 | .dev = { | ||
35 | .platform_data = &scif0_platform_data, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | static struct plat_sci_port scif1_platform_data = { | ||
40 | .mapbase = 0xffeb0000, | ||
41 | .flags = UPF_BOOT_AUTOCONF, | ||
42 | .type = PORT_SCIF, | ||
43 | .irqs = { 44, 44, 44, 44 }, | ||
44 | .clk = "scif_fck", | ||
45 | }; | ||
46 | |||
47 | static struct platform_device scif1_device = { | ||
48 | .name = "sh-sci", | ||
49 | .id = 1, | ||
50 | .dev = { | ||
51 | .platform_data = &scif1_platform_data, | ||
52 | }, | ||
53 | }; | ||
54 | |||
55 | static struct plat_sci_port scif2_platform_data = { | ||
56 | .mapbase = 0xffec0000, | ||
57 | .flags = UPF_BOOT_AUTOCONF, | ||
58 | .type = PORT_SCIF, | ||
59 | .irqs = { 60, 60, 60, 60 }, | ||
60 | .clk = "scif_fck", | ||
61 | }; | ||
62 | |||
63 | static struct platform_device scif2_device = { | ||
64 | .name = "sh-sci", | ||
65 | .id = 2, | ||
66 | .dev = { | ||
67 | .platform_data = &scif2_platform_data, | ||
68 | }, | ||
69 | }; | ||
70 | |||
71 | static struct plat_sci_port scif3_platform_data = { | ||
72 | .mapbase = 0xffed0000, | ||
73 | .flags = UPF_BOOT_AUTOCONF, | ||
74 | .type = PORT_SCIF, | ||
75 | .irqs = { 61, 61, 61, 61 }, | ||
76 | .clk = "scif_fck", | ||
77 | }; | ||
78 | |||
79 | static struct platform_device scif3_device = { | ||
80 | .name = "sh-sci", | ||
81 | .id = 3, | ||
82 | .dev = { | ||
83 | .platform_data = &scif3_platform_data, | ||
84 | }, | ||
85 | }; | ||
86 | |||
87 | static struct plat_sci_port scif4_platform_data = { | ||
88 | .mapbase = 0xffee0000, | ||
89 | .flags = UPF_BOOT_AUTOCONF, | ||
90 | .type = PORT_SCIF, | ||
91 | .irqs = { 62, 62, 62, 62 }, | ||
92 | .clk = "scif_fck", | ||
93 | }; | ||
94 | |||
95 | static struct platform_device scif4_device = { | ||
96 | .name = "sh-sci", | ||
97 | .id = 4, | ||
98 | .dev = { | ||
99 | .platform_data = &scif4_platform_data, | ||
100 | }, | ||
101 | }; | ||
102 | |||
103 | static struct plat_sci_port scif5_platform_data = { | ||
104 | .mapbase = 0xffef0000, | ||
105 | .flags = UPF_BOOT_AUTOCONF, | ||
106 | .type = PORT_SCIF, | ||
107 | .irqs = { 63, 63, 63, 63 }, | ||
108 | .clk = "scif_fck", | ||
109 | }; | ||
110 | |||
111 | static struct platform_device scif5_device = { | ||
112 | .name = "sh-sci", | ||
113 | .id = 5, | ||
114 | .dev = { | ||
115 | .platform_data = &scif5_platform_data, | ||
116 | }, | ||
117 | }; | ||
118 | |||
19 | static struct sh_timer_config tmu0_platform_data = { | 119 | static struct sh_timer_config tmu0_platform_data = { |
20 | .name = "TMU0", | 120 | .name = "TMU0", |
21 | .channel_offset = 0x04, | 121 | .channel_offset = 0x04, |
@@ -198,64 +298,149 @@ static struct platform_device tmu5_device = { | |||
198 | .num_resources = ARRAY_SIZE(tmu5_resources), | 298 | .num_resources = ARRAY_SIZE(tmu5_resources), |
199 | }; | 299 | }; |
200 | 300 | ||
201 | static struct plat_sci_port sci_platform_data[] = { | 301 | /* DMA */ |
302 | static struct sh_dmae_channel sh7785_dmae0_channels[] = { | ||
202 | { | 303 | { |
203 | .mapbase = 0xffea0000, | 304 | .offset = 0, |
204 | .flags = UPF_BOOT_AUTOCONF, | 305 | .dmars = 0, |
205 | .type = PORT_SCIF, | 306 | .dmars_bit = 0, |
206 | .irqs = { 40, 40, 40, 40 }, | ||
207 | .clk = "scif_fck", | ||
208 | }, { | 307 | }, { |
209 | .mapbase = 0xffeb0000, | 308 | .offset = 0x10, |
210 | .flags = UPF_BOOT_AUTOCONF, | 309 | .dmars = 0, |
211 | .type = PORT_SCIF, | 310 | .dmars_bit = 8, |
212 | .irqs = { 44, 44, 44, 44 }, | ||
213 | .clk = "scif_fck", | ||
214 | }, { | 311 | }, { |
215 | .mapbase = 0xffec0000, | 312 | .offset = 0x20, |
216 | .flags = UPF_BOOT_AUTOCONF, | 313 | .dmars = 4, |
217 | .type = PORT_SCIF, | 314 | .dmars_bit = 0, |
218 | .irqs = { 60, 60, 60, 60 }, | ||
219 | .clk = "scif_fck", | ||
220 | }, { | 315 | }, { |
221 | .mapbase = 0xffed0000, | 316 | .offset = 0x30, |
222 | .flags = UPF_BOOT_AUTOCONF, | 317 | .dmars = 4, |
223 | .type = PORT_SCIF, | 318 | .dmars_bit = 8, |
224 | .irqs = { 61, 61, 61, 61 }, | ||
225 | .clk = "scif_fck", | ||
226 | }, { | 319 | }, { |
227 | .mapbase = 0xffee0000, | 320 | .offset = 0x50, |
228 | .flags = UPF_BOOT_AUTOCONF, | 321 | .dmars = 8, |
229 | .type = PORT_SCIF, | 322 | .dmars_bit = 0, |
230 | .irqs = { 62, 62, 62, 62 }, | ||
231 | .clk = "scif_fck", | ||
232 | }, { | 323 | }, { |
233 | .mapbase = 0xffef0000, | 324 | .offset = 0x60, |
234 | .flags = UPF_BOOT_AUTOCONF, | 325 | .dmars = 8, |
235 | .type = PORT_SCIF, | 326 | .dmars_bit = 8, |
236 | .irqs = { 63, 63, 63, 63 }, | 327 | } |
237 | .clk = "scif_fck", | 328 | }; |
329 | |||
330 | static struct sh_dmae_channel sh7785_dmae1_channels[] = { | ||
331 | { | ||
332 | .offset = 0, | ||
238 | }, { | 333 | }, { |
239 | .flags = 0, | 334 | .offset = 0x10, |
335 | }, { | ||
336 | .offset = 0x20, | ||
337 | }, { | ||
338 | .offset = 0x30, | ||
339 | }, { | ||
340 | .offset = 0x50, | ||
341 | }, { | ||
342 | .offset = 0x60, | ||
240 | } | 343 | } |
241 | }; | 344 | }; |
242 | 345 | ||
243 | static struct platform_device sci_device = { | 346 | static unsigned int ts_shift[] = TS_SHIFT; |
244 | .name = "sh-sci", | 347 | |
245 | .id = -1, | 348 | static struct sh_dmae_pdata dma0_platform_data = { |
349 | .channel = sh7785_dmae0_channels, | ||
350 | .channel_num = ARRAY_SIZE(sh7785_dmae0_channels), | ||
351 | .ts_low_shift = CHCR_TS_LOW_SHIFT, | ||
352 | .ts_low_mask = CHCR_TS_LOW_MASK, | ||
353 | .ts_high_shift = CHCR_TS_HIGH_SHIFT, | ||
354 | .ts_high_mask = CHCR_TS_HIGH_MASK, | ||
355 | .ts_shift = ts_shift, | ||
356 | .ts_shift_num = ARRAY_SIZE(ts_shift), | ||
357 | .dmaor_init = DMAOR_INIT, | ||
358 | }; | ||
359 | |||
360 | static struct sh_dmae_pdata dma1_platform_data = { | ||
361 | .channel = sh7785_dmae1_channels, | ||
362 | .channel_num = ARRAY_SIZE(sh7785_dmae1_channels), | ||
363 | .ts_low_shift = CHCR_TS_LOW_SHIFT, | ||
364 | .ts_low_mask = CHCR_TS_LOW_MASK, | ||
365 | .ts_high_shift = CHCR_TS_HIGH_SHIFT, | ||
366 | .ts_high_mask = CHCR_TS_HIGH_MASK, | ||
367 | .ts_shift = ts_shift, | ||
368 | .ts_shift_num = ARRAY_SIZE(ts_shift), | ||
369 | .dmaor_init = DMAOR_INIT, | ||
370 | }; | ||
371 | |||
372 | static struct resource sh7785_dmae0_resources[] = { | ||
373 | [0] = { | ||
374 | /* Channel registers and DMAOR */ | ||
375 | .start = 0xfc808020, | ||
376 | .end = 0xfc80808f, | ||
377 | .flags = IORESOURCE_MEM, | ||
378 | }, | ||
379 | [1] = { | ||
380 | /* DMARSx */ | ||
381 | .start = 0xfc809000, | ||
382 | .end = 0xfc80900b, | ||
383 | .flags = IORESOURCE_MEM, | ||
384 | }, | ||
385 | { | ||
386 | /* Real DMA error IRQ is 39, and channel IRQs are 33-38 */ | ||
387 | .start = 33, | ||
388 | .end = 33, | ||
389 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, | ||
390 | }, | ||
391 | }; | ||
392 | |||
393 | static struct resource sh7785_dmae1_resources[] = { | ||
394 | [0] = { | ||
395 | /* Channel registers and DMAOR */ | ||
396 | .start = 0xfcc08020, | ||
397 | .end = 0xfcc0808f, | ||
398 | .flags = IORESOURCE_MEM, | ||
399 | }, | ||
400 | /* DMAC1 has no DMARS */ | ||
401 | { | ||
402 | /* Real DMA error IRQ is 58, and channel IRQs are 52-57 */ | ||
403 | .start = 52, | ||
404 | .end = 52, | ||
405 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE, | ||
406 | }, | ||
407 | }; | ||
408 | |||
409 | static struct platform_device dma0_device = { | ||
410 | .name = "sh-dma-engine", | ||
411 | .id = 0, | ||
412 | .resource = sh7785_dmae0_resources, | ||
413 | .num_resources = ARRAY_SIZE(sh7785_dmae0_resources), | ||
414 | .dev = { | ||
415 | .platform_data = &dma0_platform_data, | ||
416 | }, | ||
417 | }; | ||
418 | |||
419 | static struct platform_device dma1_device = { | ||
420 | .name = "sh-dma-engine", | ||
421 | .id = 1, | ||
422 | .resource = sh7785_dmae1_resources, | ||
423 | .num_resources = ARRAY_SIZE(sh7785_dmae1_resources), | ||
246 | .dev = { | 424 | .dev = { |
247 | .platform_data = sci_platform_data, | 425 | .platform_data = &dma1_platform_data, |
248 | }, | 426 | }, |
249 | }; | 427 | }; |
250 | 428 | ||
251 | static struct platform_device *sh7785_devices[] __initdata = { | 429 | static struct platform_device *sh7785_devices[] __initdata = { |
430 | &scif0_device, | ||
431 | &scif1_device, | ||
432 | &scif2_device, | ||
433 | &scif3_device, | ||
434 | &scif4_device, | ||
435 | &scif5_device, | ||
252 | &tmu0_device, | 436 | &tmu0_device, |
253 | &tmu1_device, | 437 | &tmu1_device, |
254 | &tmu2_device, | 438 | &tmu2_device, |
255 | &tmu3_device, | 439 | &tmu3_device, |
256 | &tmu4_device, | 440 | &tmu4_device, |
257 | &tmu5_device, | 441 | &tmu5_device, |
258 | &sci_device, | 442 | &dma0_device, |
443 | &dma1_device, | ||
259 | }; | 444 | }; |
260 | 445 | ||
261 | static int __init sh7785_devices_setup(void) | 446 | static int __init sh7785_devices_setup(void) |
@@ -266,6 +451,12 @@ static int __init sh7785_devices_setup(void) | |||
266 | arch_initcall(sh7785_devices_setup); | 451 | arch_initcall(sh7785_devices_setup); |
267 | 452 | ||
268 | static struct platform_device *sh7785_early_devices[] __initdata = { | 453 | static struct platform_device *sh7785_early_devices[] __initdata = { |
454 | &scif0_device, | ||
455 | &scif1_device, | ||
456 | &scif2_device, | ||
457 | &scif3_device, | ||
458 | &scif4_device, | ||
459 | &scif5_device, | ||
269 | &tmu0_device, | 460 | &tmu0_device, |
270 | &tmu1_device, | 461 | &tmu1_device, |
271 | &tmu2_device, | 462 | &tmu2_device, |
@@ -470,17 +661,17 @@ static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7785-irl4567", vectors_irl4567, | |||
470 | void __init plat_irq_setup(void) | 661 | void __init plat_irq_setup(void) |
471 | { | 662 | { |
472 | /* disable IRQ3-0 + IRQ7-4 */ | 663 | /* disable IRQ3-0 + IRQ7-4 */ |
473 | ctrl_outl(0xff000000, INTC_INTMSK0); | 664 | __raw_writel(0xff000000, INTC_INTMSK0); |
474 | 665 | ||
475 | /* disable IRL3-0 + IRL7-4 */ | 666 | /* disable IRL3-0 + IRL7-4 */ |
476 | ctrl_outl(0xc0000000, INTC_INTMSK1); | 667 | __raw_writel(0xc0000000, INTC_INTMSK1); |
477 | ctrl_outl(0xfffefffe, INTC_INTMSK2); | 668 | __raw_writel(0xfffefffe, INTC_INTMSK2); |
478 | 669 | ||
479 | /* select IRL mode for IRL3-0 + IRL7-4 */ | 670 | /* select IRL mode for IRL3-0 + IRL7-4 */ |
480 | ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); | 671 | __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); |
481 | 672 | ||
482 | /* disable holding function, ie enable "SH-4 Mode" */ | 673 | /* disable holding function, ie enable "SH-4 Mode" */ |
483 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0); | 674 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0); |
484 | 675 | ||
485 | register_intc_controller(&intc_desc); | 676 | register_intc_controller(&intc_desc); |
486 | } | 677 | } |
@@ -490,32 +681,32 @@ void __init plat_irq_setup_pins(int mode) | |||
490 | switch (mode) { | 681 | switch (mode) { |
491 | case IRQ_MODE_IRQ7654: | 682 | case IRQ_MODE_IRQ7654: |
492 | /* select IRQ mode for IRL7-4 */ | 683 | /* select IRQ mode for IRL7-4 */ |
493 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00400000, INTC_ICR0); | 684 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00400000, INTC_ICR0); |
494 | register_intc_controller(&intc_desc_irq4567); | 685 | register_intc_controller(&intc_desc_irq4567); |
495 | break; | 686 | break; |
496 | case IRQ_MODE_IRQ3210: | 687 | case IRQ_MODE_IRQ3210: |
497 | /* select IRQ mode for IRL3-0 */ | 688 | /* select IRQ mode for IRL3-0 */ |
498 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00800000, INTC_ICR0); | 689 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00800000, INTC_ICR0); |
499 | register_intc_controller(&intc_desc_irq0123); | 690 | register_intc_controller(&intc_desc_irq0123); |
500 | break; | 691 | break; |
501 | case IRQ_MODE_IRL7654: | 692 | case IRQ_MODE_IRL7654: |
502 | /* enable IRL7-4 but don't provide any masking */ | 693 | /* enable IRL7-4 but don't provide any masking */ |
503 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 694 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
504 | ctrl_outl(0x0000fffe, INTC_INTMSKCLR2); | 695 | __raw_writel(0x0000fffe, INTC_INTMSKCLR2); |
505 | break; | 696 | break; |
506 | case IRQ_MODE_IRL3210: | 697 | case IRQ_MODE_IRL3210: |
507 | /* enable IRL0-3 but don't provide any masking */ | 698 | /* enable IRL0-3 but don't provide any masking */ |
508 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 699 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
509 | ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); | 700 | __raw_writel(0xfffe0000, INTC_INTMSKCLR2); |
510 | break; | 701 | break; |
511 | case IRQ_MODE_IRL7654_MASK: | 702 | case IRQ_MODE_IRL7654_MASK: |
512 | /* enable IRL7-4 and mask using cpu intc controller */ | 703 | /* enable IRL7-4 and mask using cpu intc controller */ |
513 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 704 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
514 | register_intc_controller(&intc_desc_irl4567); | 705 | register_intc_controller(&intc_desc_irl4567); |
515 | break; | 706 | break; |
516 | case IRQ_MODE_IRL3210_MASK: | 707 | case IRQ_MODE_IRL3210_MASK: |
517 | /* enable IRL0-3 and mask using cpu intc controller */ | 708 | /* enable IRL0-3 and mask using cpu intc controller */ |
518 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 709 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
519 | register_intc_controller(&intc_desc_irl0123); | 710 | register_intc_controller(&intc_desc_irl0123); |
520 | break; | 711 | break; |
521 | default: | 712 | default: |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index 0104a8ec5369..7e585320710a 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c | |||
@@ -23,51 +23,96 @@ | |||
23 | #include <linux/sh_timer.h> | 23 | #include <linux/sh_timer.h> |
24 | #include <asm/mmzone.h> | 24 | #include <asm/mmzone.h> |
25 | 25 | ||
26 | static struct plat_sci_port sci_platform_data[] = { | 26 | static struct plat_sci_port scif0_platform_data = { |
27 | { | 27 | .mapbase = 0xffea0000, |
28 | .mapbase = 0xffea0000, | 28 | .flags = UPF_BOOT_AUTOCONF, |
29 | .flags = UPF_BOOT_AUTOCONF, | 29 | .type = PORT_SCIF, |
30 | .type = PORT_SCIF, | 30 | .irqs = { 40, 41, 43, 42 }, |
31 | .irqs = { 40, 41, 43, 42 }, | 31 | }; |
32 | |||
33 | static struct platform_device scif0_device = { | ||
34 | .name = "sh-sci", | ||
35 | .id = 0, | ||
36 | .dev = { | ||
37 | .platform_data = &scif0_platform_data, | ||
32 | }, | 38 | }, |
33 | /* | ||
34 | * The rest of these all have multiplexed IRQs | ||
35 | */ | ||
36 | { | ||
37 | .mapbase = 0xffeb0000, | ||
38 | .flags = UPF_BOOT_AUTOCONF, | ||
39 | .type = PORT_SCIF, | ||
40 | .irqs = { 44, 44, 44, 44 }, | ||
41 | }, { | ||
42 | .mapbase = 0xffec0000, | ||
43 | .flags = UPF_BOOT_AUTOCONF, | ||
44 | .type = PORT_SCIF, | ||
45 | .irqs = { 50, 50, 50, 50 }, | ||
46 | }, { | ||
47 | .mapbase = 0xffed0000, | ||
48 | .flags = UPF_BOOT_AUTOCONF, | ||
49 | .type = PORT_SCIF, | ||
50 | .irqs = { 51, 51, 51, 51 }, | ||
51 | }, { | ||
52 | .mapbase = 0xffee0000, | ||
53 | .flags = UPF_BOOT_AUTOCONF, | ||
54 | .type = PORT_SCIF, | ||
55 | .irqs = { 52, 52, 52, 52 }, | ||
56 | }, { | ||
57 | .mapbase = 0xffef0000, | ||
58 | .flags = UPF_BOOT_AUTOCONF, | ||
59 | .type = PORT_SCIF, | ||
60 | .irqs = { 53, 53, 53, 53 }, | ||
61 | }, { | ||
62 | .flags = 0, | ||
63 | } | ||
64 | }; | 39 | }; |
65 | 40 | ||
66 | static struct platform_device sci_device = { | 41 | /* |
42 | * The rest of these all have multiplexed IRQs | ||
43 | */ | ||
44 | static struct plat_sci_port scif1_platform_data = { | ||
45 | .mapbase = 0xffeb0000, | ||
46 | .flags = UPF_BOOT_AUTOCONF, | ||
47 | .type = PORT_SCIF, | ||
48 | .irqs = { 44, 44, 44, 44 }, | ||
49 | }; | ||
50 | |||
51 | static struct platform_device scif1_device = { | ||
67 | .name = "sh-sci", | 52 | .name = "sh-sci", |
68 | .id = -1, | 53 | .id = 1, |
54 | .dev = { | ||
55 | .platform_data = &scif1_platform_data, | ||
56 | }, | ||
57 | }; | ||
58 | |||
59 | static struct plat_sci_port scif2_platform_data = { | ||
60 | .mapbase = 0xffec0000, | ||
61 | .flags = UPF_BOOT_AUTOCONF, | ||
62 | .type = PORT_SCIF, | ||
63 | .irqs = { 50, 50, 50, 50 }, | ||
64 | }; | ||
65 | |||
66 | static struct platform_device scif2_device = { | ||
67 | .name = "sh-sci", | ||
68 | .id = 2, | ||
69 | .dev = { | ||
70 | .platform_data = &scif2_platform_data, | ||
71 | }, | ||
72 | }; | ||
73 | |||
74 | static struct plat_sci_port scif3_platform_data = { | ||
75 | .mapbase = 0xffed0000, | ||
76 | .flags = UPF_BOOT_AUTOCONF, | ||
77 | .type = PORT_SCIF, | ||
78 | .irqs = { 51, 51, 51, 51 }, | ||
79 | }; | ||
80 | |||
81 | static struct platform_device scif3_device = { | ||
82 | .name = "sh-sci", | ||
83 | .id = 3, | ||
84 | .dev = { | ||
85 | .platform_data = &scif3_platform_data, | ||
86 | }, | ||
87 | }; | ||
88 | |||
89 | static struct plat_sci_port scif4_platform_data = { | ||
90 | .mapbase = 0xffee0000, | ||
91 | .flags = UPF_BOOT_AUTOCONF, | ||
92 | .type = PORT_SCIF, | ||
93 | .irqs = { 52, 52, 52, 52 }, | ||
94 | }; | ||
95 | |||
96 | static struct platform_device scif4_device = { | ||
97 | .name = "sh-sci", | ||
98 | .id = 4, | ||
99 | .dev = { | ||
100 | .platform_data = &scif4_platform_data, | ||
101 | }, | ||
102 | }; | ||
103 | |||
104 | static struct plat_sci_port scif5_platform_data = { | ||
105 | .mapbase = 0xffef0000, | ||
106 | .flags = UPF_BOOT_AUTOCONF, | ||
107 | .type = PORT_SCIF, | ||
108 | .irqs = { 53, 53, 53, 53 }, | ||
109 | }; | ||
110 | |||
111 | static struct platform_device scif5_device = { | ||
112 | .name = "sh-sci", | ||
113 | .id = 5, | ||
69 | .dev = { | 114 | .dev = { |
70 | .platform_data = sci_platform_data, | 115 | .platform_data = &scif5_platform_data, |
71 | }, | 116 | }, |
72 | }; | 117 | }; |
73 | 118 | ||
@@ -459,6 +504,12 @@ static struct platform_device usb_ohci_device = { | |||
459 | }; | 504 | }; |
460 | 505 | ||
461 | static struct platform_device *sh7786_early_devices[] __initdata = { | 506 | static struct platform_device *sh7786_early_devices[] __initdata = { |
507 | &scif0_device, | ||
508 | &scif1_device, | ||
509 | &scif2_device, | ||
510 | &scif3_device, | ||
511 | &scif4_device, | ||
512 | &scif5_device, | ||
462 | &tmu0_device, | 513 | &tmu0_device, |
463 | &tmu1_device, | 514 | &tmu1_device, |
464 | &tmu2_device, | 515 | &tmu2_device, |
@@ -474,7 +525,6 @@ static struct platform_device *sh7786_early_devices[] __initdata = { | |||
474 | }; | 525 | }; |
475 | 526 | ||
476 | static struct platform_device *sh7786_devices[] __initdata = { | 527 | static struct platform_device *sh7786_devices[] __initdata = { |
477 | &sci_device, | ||
478 | &usb_ohci_device, | 528 | &usb_ohci_device, |
479 | }; | 529 | }; |
480 | 530 | ||
@@ -817,14 +867,14 @@ static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7786-irl4567", vectors_irl4567, | |||
817 | void __init plat_irq_setup(void) | 867 | void __init plat_irq_setup(void) |
818 | { | 868 | { |
819 | /* disable IRQ3-0 + IRQ7-4 */ | 869 | /* disable IRQ3-0 + IRQ7-4 */ |
820 | ctrl_outl(0xff000000, INTC_INTMSK0); | 870 | __raw_writel(0xff000000, INTC_INTMSK0); |
821 | 871 | ||
822 | /* disable IRL3-0 + IRL7-4 */ | 872 | /* disable IRL3-0 + IRL7-4 */ |
823 | ctrl_outl(0xc0000000, INTC_INTMSK1); | 873 | __raw_writel(0xc0000000, INTC_INTMSK1); |
824 | ctrl_outl(0xfffefffe, INTC_INTMSK2); | 874 | __raw_writel(0xfffefffe, INTC_INTMSK2); |
825 | 875 | ||
826 | /* select IRL mode for IRL3-0 + IRL7-4 */ | 876 | /* select IRL mode for IRL3-0 + IRL7-4 */ |
827 | ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); | 877 | __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); |
828 | 878 | ||
829 | register_intc_controller(&intc_desc); | 879 | register_intc_controller(&intc_desc); |
830 | } | 880 | } |
@@ -834,32 +884,32 @@ void __init plat_irq_setup_pins(int mode) | |||
834 | switch (mode) { | 884 | switch (mode) { |
835 | case IRQ_MODE_IRQ7654: | 885 | case IRQ_MODE_IRQ7654: |
836 | /* select IRQ mode for IRL7-4 */ | 886 | /* select IRQ mode for IRL7-4 */ |
837 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00400000, INTC_ICR0); | 887 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00400000, INTC_ICR0); |
838 | register_intc_controller(&intc_desc_irq4567); | 888 | register_intc_controller(&intc_desc_irq4567); |
839 | break; | 889 | break; |
840 | case IRQ_MODE_IRQ3210: | 890 | case IRQ_MODE_IRQ3210: |
841 | /* select IRQ mode for IRL3-0 */ | 891 | /* select IRQ mode for IRL3-0 */ |
842 | ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00800000, INTC_ICR0); | 892 | __raw_writel(__raw_readl(INTC_ICR0) | 0x00800000, INTC_ICR0); |
843 | register_intc_controller(&intc_desc_irq0123); | 893 | register_intc_controller(&intc_desc_irq0123); |
844 | break; | 894 | break; |
845 | case IRQ_MODE_IRL7654: | 895 | case IRQ_MODE_IRL7654: |
846 | /* enable IRL7-4 but don't provide any masking */ | 896 | /* enable IRL7-4 but don't provide any masking */ |
847 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 897 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
848 | ctrl_outl(0x0000fffe, INTC_INTMSKCLR2); | 898 | __raw_writel(0x0000fffe, INTC_INTMSKCLR2); |
849 | break; | 899 | break; |
850 | case IRQ_MODE_IRL3210: | 900 | case IRQ_MODE_IRL3210: |
851 | /* enable IRL0-3 but don't provide any masking */ | 901 | /* enable IRL0-3 but don't provide any masking */ |
852 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 902 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
853 | ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); | 903 | __raw_writel(0xfffe0000, INTC_INTMSKCLR2); |
854 | break; | 904 | break; |
855 | case IRQ_MODE_IRL7654_MASK: | 905 | case IRQ_MODE_IRL7654_MASK: |
856 | /* enable IRL7-4 and mask using cpu intc controller */ | 906 | /* enable IRL7-4 and mask using cpu intc controller */ |
857 | ctrl_outl(0x40000000, INTC_INTMSKCLR1); | 907 | __raw_writel(0x40000000, INTC_INTMSKCLR1); |
858 | register_intc_controller(&intc_desc_irl4567); | 908 | register_intc_controller(&intc_desc_irl4567); |
859 | break; | 909 | break; |
860 | case IRQ_MODE_IRL3210_MASK: | 910 | case IRQ_MODE_IRL3210_MASK: |
861 | /* enable IRL0-3 and mask using cpu intc controller */ | 911 | /* enable IRL0-3 and mask using cpu intc controller */ |
862 | ctrl_outl(0x80000000, INTC_INTMSKCLR1); | 912 | __raw_writel(0x80000000, INTC_INTMSKCLR1); |
863 | register_intc_controller(&intc_desc_irl0123); | 913 | register_intc_controller(&intc_desc_irl0123); |
864 | break; | 914 | break; |
865 | default: | 915 | default: |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c index e848443deeb9..780ba17a5599 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c | |||
@@ -15,37 +15,57 @@ | |||
15 | #include <linux/sh_timer.h> | 15 | #include <linux/sh_timer.h> |
16 | #include <asm/mmzone.h> | 16 | #include <asm/mmzone.h> |
17 | 17 | ||
18 | static struct plat_sci_port sci_platform_data[] = { | 18 | /* |
19 | { | 19 | * This intentionally only registers SCIF ports 0, 1, and 3. SCIF 2 |
20 | .mapbase = 0xffc30000, | 20 | * INTEVT values overlap with the FPU EXPEVT ones, requiring special |
21 | .flags = UPF_BOOT_AUTOCONF, | 21 | * demuxing in the exception dispatch path. |
22 | .type = PORT_SCIF, | 22 | * |
23 | .irqs = { 40, 41, 43, 42 }, | 23 | * As this overlap is something that never should have made it in to |
24 | }, { | 24 | * silicon in the first place, we just refuse to deal with the port at |
25 | .mapbase = 0xffc40000, | 25 | * all rather than adding infrastructure to hack around it. |
26 | .flags = UPF_BOOT_AUTOCONF, | 26 | */ |
27 | .type = PORT_SCIF, | 27 | static struct plat_sci_port scif0_platform_data = { |
28 | .irqs = { 44, 45, 47, 46 }, | 28 | .mapbase = 0xffc30000, |
29 | }, { | 29 | .flags = UPF_BOOT_AUTOCONF, |
30 | .mapbase = 0xffc50000, | 30 | .type = PORT_SCIF, |
31 | .flags = UPF_BOOT_AUTOCONF, | 31 | .irqs = { 40, 41, 43, 42 }, |
32 | .type = PORT_SCIF, | ||
33 | .irqs = { 48, 49, 51, 50 }, | ||
34 | }, { | ||
35 | .mapbase = 0xffc60000, | ||
36 | .flags = UPF_BOOT_AUTOCONF, | ||
37 | .type = PORT_SCIF, | ||
38 | .irqs = { 52, 53, 55, 54 }, | ||
39 | }, { | ||
40 | .flags = 0, | ||
41 | } | ||
42 | }; | 32 | }; |
43 | 33 | ||
44 | static struct platform_device sci_device = { | 34 | static struct platform_device scif0_device = { |
45 | .name = "sh-sci", | 35 | .name = "sh-sci", |
46 | .id = -1, | 36 | .id = 0, |
37 | .dev = { | ||
38 | .platform_data = &scif0_platform_data, | ||
39 | }, | ||
40 | }; | ||
41 | |||
42 | static struct plat_sci_port scif1_platform_data = { | ||
43 | .mapbase = 0xffc40000, | ||
44 | .flags = UPF_BOOT_AUTOCONF, | ||
45 | .type = PORT_SCIF, | ||
46 | .irqs = { 44, 45, 47, 46 }, | ||
47 | }; | ||
48 | |||
49 | static struct platform_device scif1_device = { | ||
50 | .name = "sh-sci", | ||
51 | .id = 1, | ||
47 | .dev = { | 52 | .dev = { |
48 | .platform_data = sci_platform_data, | 53 | .platform_data = &scif1_platform_data, |
54 | }, | ||
55 | }; | ||
56 | |||
57 | static struct plat_sci_port scif2_platform_data = { | ||
58 | .mapbase = 0xffc60000, | ||
59 | .flags = UPF_BOOT_AUTOCONF, | ||
60 | .type = PORT_SCIF, | ||
61 | .irqs = { 52, 53, 55, 54 }, | ||
62 | }; | ||
63 | |||
64 | static struct platform_device scif2_device = { | ||
65 | .name = "sh-sci", | ||
66 | .id = 2, | ||
67 | .dev = { | ||
68 | .platform_data = &scif2_platform_data, | ||
49 | }, | 69 | }, |
50 | }; | 70 | }; |
51 | 71 | ||
@@ -232,6 +252,9 @@ static struct platform_device tmu5_device = { | |||
232 | }; | 252 | }; |
233 | 253 | ||
234 | static struct platform_device *shx3_early_devices[] __initdata = { | 254 | static struct platform_device *shx3_early_devices[] __initdata = { |
255 | &scif0_device, | ||
256 | &scif1_device, | ||
257 | &scif2_device, | ||
235 | &tmu0_device, | 258 | &tmu0_device, |
236 | &tmu1_device, | 259 | &tmu1_device, |
237 | &tmu2_device, | 260 | &tmu2_device, |
@@ -240,21 +263,10 @@ static struct platform_device *shx3_early_devices[] __initdata = { | |||
240 | &tmu5_device, | 263 | &tmu5_device, |
241 | }; | 264 | }; |
242 | 265 | ||
243 | static struct platform_device *shx3_devices[] __initdata = { | ||
244 | &sci_device, | ||
245 | }; | ||
246 | |||
247 | static int __init shx3_devices_setup(void) | 266 | static int __init shx3_devices_setup(void) |
248 | { | 267 | { |
249 | int ret; | 268 | return platform_add_devices(shx3_early_devices, |
250 | |||
251 | ret = platform_add_devices(shx3_early_devices, | ||
252 | ARRAY_SIZE(shx3_early_devices)); | 269 | ARRAY_SIZE(shx3_early_devices)); |
253 | if (unlikely(ret != 0)) | ||
254 | return ret; | ||
255 | |||
256 | return platform_add_devices(shx3_devices, | ||
257 | ARRAY_SIZE(shx3_devices)); | ||
258 | } | 270 | } |
259 | arch_initcall(shx3_devices_setup); | 271 | arch_initcall(shx3_devices_setup); |
260 | 272 | ||
@@ -268,7 +280,11 @@ enum { | |||
268 | UNUSED = 0, | 280 | UNUSED = 0, |
269 | 281 | ||
270 | /* interrupt sources */ | 282 | /* interrupt sources */ |
271 | IRL, IRQ0, IRQ1, IRQ2, IRQ3, | 283 | IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH, |
284 | IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH, | ||
285 | IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH, | ||
286 | IRL_HHLL, IRL_HHLH, IRL_HHHL, | ||
287 | IRQ0, IRQ1, IRQ2, IRQ3, | ||
272 | HUDII, | 288 | HUDII, |
273 | TMU0, TMU1, TMU2, TMU3, TMU4, TMU5, | 289 | TMU0, TMU1, TMU2, TMU3, TMU4, TMU5, |
274 | PCII0, PCII1, PCII2, PCII3, PCII4, | 290 | PCII0, PCII1, PCII2, PCII3, PCII4, |
@@ -291,7 +307,7 @@ enum { | |||
291 | INTICI4, INTICI5, INTICI6, INTICI7, | 307 | INTICI4, INTICI5, INTICI6, INTICI7, |
292 | 308 | ||
293 | /* interrupt groups */ | 309 | /* interrupt groups */ |
294 | PCII56789, SCIF0, SCIF1, SCIF2, SCIF3, | 310 | IRL, PCII56789, SCIF0, SCIF1, SCIF2, SCIF3, |
295 | DMAC0, DMAC1, | 311 | DMAC0, DMAC1, |
296 | }; | 312 | }; |
297 | 313 | ||
@@ -309,8 +325,6 @@ static struct intc_vect vectors[] __initdata = { | |||
309 | INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760), | 325 | INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760), |
310 | INTC_VECT(SCIF1_ERI, 0x780), INTC_VECT(SCIF1_RXI, 0x7a0), | 326 | INTC_VECT(SCIF1_ERI, 0x780), INTC_VECT(SCIF1_RXI, 0x7a0), |
311 | INTC_VECT(SCIF1_BRI, 0x7c0), INTC_VECT(SCIF1_TXI, 0x7e0), | 327 | INTC_VECT(SCIF1_BRI, 0x7c0), INTC_VECT(SCIF1_TXI, 0x7e0), |
312 | INTC_VECT(SCIF2_ERI, 0x800), INTC_VECT(SCIF2_RXI, 0x820), | ||
313 | INTC_VECT(SCIF2_BRI, 0x840), INTC_VECT(SCIF2_TXI, 0x860), | ||
314 | INTC_VECT(SCIF3_ERI, 0x880), INTC_VECT(SCIF3_RXI, 0x8a0), | 328 | INTC_VECT(SCIF3_ERI, 0x880), INTC_VECT(SCIF3_RXI, 0x8a0), |
315 | INTC_VECT(SCIF3_BRI, 0x8c0), INTC_VECT(SCIF3_TXI, 0x8e0), | 329 | INTC_VECT(SCIF3_BRI, 0x8c0), INTC_VECT(SCIF3_TXI, 0x8e0), |
316 | INTC_VECT(DMAC0_DMINT0, 0x900), INTC_VECT(DMAC0_DMINT1, 0x920), | 330 | INTC_VECT(DMAC0_DMINT0, 0x900), INTC_VECT(DMAC0_DMINT1, 0x920), |
@@ -344,10 +358,13 @@ static struct intc_vect vectors[] __initdata = { | |||
344 | }; | 358 | }; |
345 | 359 | ||
346 | static struct intc_group groups[] __initdata = { | 360 | static struct intc_group groups[] __initdata = { |
361 | INTC_GROUP(IRL, IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH, | ||
362 | IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH, | ||
363 | IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH, | ||
364 | IRL_HHLL, IRL_HHLH, IRL_HHHL), | ||
347 | INTC_GROUP(PCII56789, PCII5, PCII6, PCII7, PCII8, PCII9), | 365 | INTC_GROUP(PCII56789, PCII5, PCII6, PCII7, PCII8, PCII9), |
348 | INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI), | 366 | INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI), |
349 | INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI), | 367 | INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI), |
350 | INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI), | ||
351 | INTC_GROUP(SCIF3, SCIF3_ERI, SCIF3_RXI, SCIF3_BRI, SCIF3_TXI), | 368 | INTC_GROUP(SCIF3, SCIF3_ERI, SCIF3_RXI, SCIF3_BRI, SCIF3_TXI), |
352 | INTC_GROUP(DMAC0, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, | 369 | INTC_GROUP(DMAC0, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, |
353 | DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE), | 370 | DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE), |
@@ -419,14 +436,14 @@ static DECLARE_INTC_DESC(intc_desc_irq, "shx3-irq", vectors_irq, groups, | |||
419 | 436 | ||
420 | /* External interrupt pins in IRL mode */ | 437 | /* External interrupt pins in IRL mode */ |
421 | static struct intc_vect vectors_irl[] __initdata = { | 438 | static struct intc_vect vectors_irl[] __initdata = { |
422 | INTC_VECT(IRL, 0x200), INTC_VECT(IRL, 0x220), | 439 | INTC_VECT(IRL_LLLL, 0x200), INTC_VECT(IRL_LLLH, 0x220), |
423 | INTC_VECT(IRL, 0x240), INTC_VECT(IRL, 0x260), | 440 | INTC_VECT(IRL_LLHL, 0x240), INTC_VECT(IRL_LLHH, 0x260), |
424 | INTC_VECT(IRL, 0x280), INTC_VECT(IRL, 0x2a0), | 441 | INTC_VECT(IRL_LHLL, 0x280), INTC_VECT(IRL_LHLH, 0x2a0), |
425 | INTC_VECT(IRL, 0x2c0), INTC_VECT(IRL, 0x2e0), | 442 | INTC_VECT(IRL_LHHL, 0x2c0), INTC_VECT(IRL_LHHH, 0x2e0), |
426 | INTC_VECT(IRL, 0x300), INTC_VECT(IRL, 0x320), | 443 | INTC_VECT(IRL_HLLL, 0x300), INTC_VECT(IRL_HLLH, 0x320), |
427 | INTC_VECT(IRL, 0x340), INTC_VECT(IRL, 0x360), | 444 | INTC_VECT(IRL_HLHL, 0x340), INTC_VECT(IRL_HLHH, 0x360), |
428 | INTC_VECT(IRL, 0x380), INTC_VECT(IRL, 0x3a0), | 445 | INTC_VECT(IRL_HHLL, 0x380), INTC_VECT(IRL_HHLH, 0x3a0), |
429 | INTC_VECT(IRL, 0x3c0), | 446 | INTC_VECT(IRL_HHHL, 0x3c0), |
430 | }; | 447 | }; |
431 | 448 | ||
432 | static DECLARE_INTC_DESC(intc_desc_irl, "shx3-irl", vectors_irl, groups, | 449 | static DECLARE_INTC_DESC(intc_desc_irl, "shx3-irl", vectors_irl, groups, |
diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index 185ec3976a25..11bf4c1e25c0 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c | |||
@@ -14,6 +14,13 @@ | |||
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | 16 | ||
17 | #define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12)) | ||
18 | #define RESET_REG(phys_id) (0xfe400008 | (phys_id << 12)) | ||
19 | |||
20 | #define STBCR_MSTP 0x00000001 | ||
21 | #define STBCR_RESET 0x00000002 | ||
22 | #define STBCR_LTSLP 0x80000000 | ||
23 | |||
17 | static irqreturn_t ipi_interrupt_handler(int irq, void *arg) | 24 | static irqreturn_t ipi_interrupt_handler(int irq, void *arg) |
18 | { | 25 | { |
19 | unsigned int message = (unsigned int)(long)arg; | 26 | unsigned int message = (unsigned int)(long)arg; |
@@ -21,9 +28,9 @@ static irqreturn_t ipi_interrupt_handler(int irq, void *arg) | |||
21 | unsigned int offs = 4 * cpu; | 28 | unsigned int offs = 4 * cpu; |
22 | unsigned int x; | 29 | unsigned int x; |
23 | 30 | ||
24 | x = ctrl_inl(0xfe410070 + offs); /* C0INITICI..CnINTICI */ | 31 | x = __raw_readl(0xfe410070 + offs); /* C0INITICI..CnINTICI */ |
25 | x &= (1 << (message << 2)); | 32 | x &= (1 << (message << 2)); |
26 | ctrl_outl(x, 0xfe410080 + offs); /* C0INTICICLR..CnINTICICLR */ | 33 | __raw_writel(x, 0xfe410080 + offs); /* C0INTICICLR..CnINTICICLR */ |
27 | 34 | ||
28 | smp_message_recv(message); | 35 | smp_message_recv(message); |
29 | 36 | ||
@@ -37,6 +44,9 @@ void __init plat_smp_setup(void) | |||
37 | 44 | ||
38 | init_cpu_possible(cpumask_of(cpu)); | 45 | init_cpu_possible(cpumask_of(cpu)); |
39 | 46 | ||
47 | /* Enable light sleep for the boot CPU */ | ||
48 | __raw_writel(__raw_readl(STBCR_REG(cpu)) | STBCR_LTSLP, STBCR_REG(cpu)); | ||
49 | |||
40 | __cpu_number_map[0] = 0; | 50 | __cpu_number_map[0] = 0; |
41 | __cpu_logical_map[0] = 0; | 51 | __cpu_logical_map[0] = 0; |
42 | 52 | ||
@@ -66,32 +76,26 @@ void __init plat_prepare_cpus(unsigned int max_cpus) | |||
66 | "IPI", (void *)(long)i); | 76 | "IPI", (void *)(long)i); |
67 | } | 77 | } |
68 | 78 | ||
69 | #define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12)) | ||
70 | #define RESET_REG(phys_id) (0xfe400008 | (phys_id << 12)) | ||
71 | |||
72 | #define STBCR_MSTP 0x00000001 | ||
73 | #define STBCR_RESET 0x00000002 | ||
74 | #define STBCR_LTSLP 0x80000000 | ||
75 | |||
76 | #define STBCR_AP_VAL (STBCR_RESET | STBCR_LTSLP) | ||
77 | |||
78 | void plat_start_cpu(unsigned int cpu, unsigned long entry_point) | 79 | void plat_start_cpu(unsigned int cpu, unsigned long entry_point) |
79 | { | 80 | { |
80 | ctrl_outl(entry_point, RESET_REG(cpu)); | 81 | if (__in_29bit_mode()) |
82 | __raw_writel(entry_point, RESET_REG(cpu)); | ||
83 | else | ||
84 | __raw_writel(virt_to_phys(entry_point), RESET_REG(cpu)); | ||
81 | 85 | ||
82 | if (!(ctrl_inl(STBCR_REG(cpu)) & STBCR_MSTP)) | 86 | if (!(__raw_readl(STBCR_REG(cpu)) & STBCR_MSTP)) |
83 | ctrl_outl(STBCR_MSTP, STBCR_REG(cpu)); | 87 | __raw_writel(STBCR_MSTP, STBCR_REG(cpu)); |
84 | 88 | ||
85 | while (!(ctrl_inl(STBCR_REG(cpu)) & STBCR_MSTP)) | 89 | while (!(__raw_readl(STBCR_REG(cpu)) & STBCR_MSTP)) |
86 | cpu_relax(); | 90 | cpu_relax(); |
87 | 91 | ||
88 | /* Start up secondary processor by sending a reset */ | 92 | /* Start up secondary processor by sending a reset */ |
89 | ctrl_outl(STBCR_AP_VAL, STBCR_REG(cpu)); | 93 | __raw_writel(STBCR_RESET | STBCR_LTSLP, STBCR_REG(cpu)); |
90 | } | 94 | } |
91 | 95 | ||
92 | int plat_smp_processor_id(void) | 96 | int plat_smp_processor_id(void) |
93 | { | 97 | { |
94 | return ctrl_inl(0xff000048); /* CPIDR */ | 98 | return __raw_readl(0xff000048); /* CPIDR */ |
95 | } | 99 | } |
96 | 100 | ||
97 | void plat_send_ipi(unsigned int cpu, unsigned int message) | 101 | void plat_send_ipi(unsigned int cpu, unsigned int message) |
@@ -100,5 +104,5 @@ void plat_send_ipi(unsigned int cpu, unsigned int message) | |||
100 | 104 | ||
101 | BUG_ON(cpu >= 4); | 105 | BUG_ON(cpu >= 4); |
102 | 106 | ||
103 | ctrl_outl(1 << (message << 2), addr); /* C0INTICI..CnINTICI */ | 107 | __raw_writel(1 << (message << 2), addr); /* C0INTICI..CnINTICI */ |
104 | } | 108 | } |
diff --git a/arch/sh/kernel/cpu/sh4a/ubc.c b/arch/sh/kernel/cpu/sh4a/ubc.c new file mode 100644 index 000000000000..efb2745bcb36 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/ubc.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpu/sh4a/ubc.c | ||
3 | * | ||
4 | * On-chip UBC support for SH-4A CPUs. | ||
5 | * | ||
6 | * Copyright (C) 2009 - 2010 Paul Mundt | ||
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/err.h> | ||
14 | #include <linux/clk.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <asm/hw_breakpoint.h> | ||
17 | |||
18 | #define UBC_CBR(idx) (0xff200000 + (0x20 * idx)) | ||
19 | #define UBC_CRR(idx) (0xff200004 + (0x20 * idx)) | ||
20 | #define UBC_CAR(idx) (0xff200008 + (0x20 * idx)) | ||
21 | #define UBC_CAMR(idx) (0xff20000c + (0x20 * idx)) | ||
22 | |||
23 | #define UBC_CCMFR 0xff200600 | ||
24 | #define UBC_CBCR 0xff200620 | ||
25 | |||
26 | /* CRR */ | ||
27 | #define UBC_CRR_PCB (1 << 1) | ||
28 | #define UBC_CRR_BIE (1 << 0) | ||
29 | |||
30 | /* CBR */ | ||
31 | #define UBC_CBR_CE (1 << 0) | ||
32 | |||
33 | static struct sh_ubc sh4a_ubc; | ||
34 | |||
35 | static void sh4a_ubc_enable(struct arch_hw_breakpoint *info, int idx) | ||
36 | { | ||
37 | __raw_writel(UBC_CBR_CE | info->len | info->type, UBC_CBR(idx)); | ||
38 | __raw_writel(info->address, UBC_CAR(idx)); | ||
39 | } | ||
40 | |||
41 | static void sh4a_ubc_disable(struct arch_hw_breakpoint *info, int idx) | ||
42 | { | ||
43 | __raw_writel(0, UBC_CBR(idx)); | ||
44 | __raw_writel(0, UBC_CAR(idx)); | ||
45 | } | ||
46 | |||
47 | static void sh4a_ubc_enable_all(unsigned long mask) | ||
48 | { | ||
49 | int i; | ||
50 | |||
51 | for (i = 0; i < sh4a_ubc.num_events; i++) | ||
52 | if (mask & (1 << i)) | ||
53 | __raw_writel(__raw_readl(UBC_CBR(i)) | UBC_CBR_CE, | ||
54 | UBC_CBR(i)); | ||
55 | } | ||
56 | |||
57 | static void sh4a_ubc_disable_all(void) | ||
58 | { | ||
59 | int i; | ||
60 | |||
61 | for (i = 0; i < sh4a_ubc.num_events; i++) | ||
62 | __raw_writel(__raw_readl(UBC_CBR(i)) & ~UBC_CBR_CE, | ||
63 | UBC_CBR(i)); | ||
64 | } | ||
65 | |||
66 | static unsigned long sh4a_ubc_active_mask(void) | ||
67 | { | ||
68 | unsigned long active = 0; | ||
69 | int i; | ||
70 | |||
71 | for (i = 0; i < sh4a_ubc.num_events; i++) | ||
72 | if (__raw_readl(UBC_CBR(i)) & UBC_CBR_CE) | ||
73 | active |= (1 << i); | ||
74 | |||
75 | return active; | ||
76 | } | ||
77 | |||
78 | static unsigned long sh4a_ubc_triggered_mask(void) | ||
79 | { | ||
80 | return __raw_readl(UBC_CCMFR); | ||
81 | } | ||
82 | |||
83 | static void sh4a_ubc_clear_triggered_mask(unsigned long mask) | ||
84 | { | ||
85 | __raw_writel(__raw_readl(UBC_CCMFR) & ~mask, UBC_CCMFR); | ||
86 | } | ||
87 | |||
88 | static struct sh_ubc sh4a_ubc = { | ||
89 | .name = "SH-4A", | ||
90 | .num_events = 2, | ||
91 | .trap_nr = 0x1e0, | ||
92 | .enable = sh4a_ubc_enable, | ||
93 | .disable = sh4a_ubc_disable, | ||
94 | .enable_all = sh4a_ubc_enable_all, | ||
95 | .disable_all = sh4a_ubc_disable_all, | ||
96 | .active_mask = sh4a_ubc_active_mask, | ||
97 | .triggered_mask = sh4a_ubc_triggered_mask, | ||
98 | .clear_triggered_mask = sh4a_ubc_clear_triggered_mask, | ||
99 | }; | ||
100 | |||
101 | static int __init sh4a_ubc_init(void) | ||
102 | { | ||
103 | struct clk *ubc_iclk = clk_get(NULL, "ubc0"); | ||
104 | int i; | ||
105 | |||
106 | /* | ||
107 | * The UBC MSTP bit is optional, as not all platforms will have | ||
108 | * it. Just ignore it if we can't find it. | ||
109 | */ | ||
110 | if (IS_ERR(ubc_iclk)) | ||
111 | ubc_iclk = NULL; | ||
112 | |||
113 | clk_enable(ubc_iclk); | ||
114 | |||
115 | __raw_writel(0, UBC_CBCR); | ||
116 | |||
117 | for (i = 0; i < sh4a_ubc.num_events; i++) { | ||
118 | __raw_writel(0, UBC_CAMR(i)); | ||
119 | __raw_writel(0, UBC_CBR(i)); | ||
120 | |||
121 | __raw_writel(UBC_CRR_BIE | UBC_CRR_PCB, UBC_CRR(i)); | ||
122 | |||
123 | /* dummy read for write posting */ | ||
124 | (void)__raw_readl(UBC_CRR(i)); | ||
125 | } | ||
126 | |||
127 | clk_disable(ubc_iclk); | ||
128 | |||
129 | sh4a_ubc.clk = ubc_iclk; | ||
130 | |||
131 | return register_sh_ubc(&sh4a_ubc); | ||
132 | } | ||
133 | arch_initcall(sh4a_ubc_init); | ||
diff --git a/arch/sh/kernel/cpu/sh5/clock-sh5.c b/arch/sh/kernel/cpu/sh5/clock-sh5.c index 7f864ebc51d3..9cfc19b8dbe4 100644 --- a/arch/sh/kernel/cpu/sh5/clock-sh5.c +++ b/arch/sh/kernel/cpu/sh5/clock-sh5.c | |||
@@ -24,7 +24,7 @@ static unsigned long cprc_base; | |||
24 | 24 | ||
25 | static void master_clk_init(struct clk *clk) | 25 | static void master_clk_init(struct clk *clk) |
26 | { | 26 | { |
27 | int idx = (ctrl_inl(cprc_base + 0x00) >> 6) & 0x0007; | 27 | int idx = (__raw_readl(cprc_base + 0x00) >> 6) & 0x0007; |
28 | clk->rate *= ifc_table[idx]; | 28 | clk->rate *= ifc_table[idx]; |
29 | } | 29 | } |
30 | 30 | ||
@@ -34,7 +34,7 @@ static struct clk_ops sh5_master_clk_ops = { | |||
34 | 34 | ||
35 | static unsigned long module_clk_recalc(struct clk *clk) | 35 | static unsigned long module_clk_recalc(struct clk *clk) |
36 | { | 36 | { |
37 | int idx = (ctrl_inw(cprc_base) >> 12) & 0x0007; | 37 | int idx = (__raw_readw(cprc_base) >> 12) & 0x0007; |
38 | return clk->parent->rate / ifc_table[idx]; | 38 | return clk->parent->rate / ifc_table[idx]; |
39 | } | 39 | } |
40 | 40 | ||
@@ -44,7 +44,7 @@ static struct clk_ops sh5_module_clk_ops = { | |||
44 | 44 | ||
45 | static unsigned long bus_clk_recalc(struct clk *clk) | 45 | static unsigned long bus_clk_recalc(struct clk *clk) |
46 | { | 46 | { |
47 | int idx = (ctrl_inw(cprc_base) >> 3) & 0x0007; | 47 | int idx = (__raw_readw(cprc_base) >> 3) & 0x0007; |
48 | return clk->parent->rate / ifc_table[idx]; | 48 | return clk->parent->rate / ifc_table[idx]; |
49 | } | 49 | } |
50 | 50 | ||
@@ -54,7 +54,7 @@ static struct clk_ops sh5_bus_clk_ops = { | |||
54 | 54 | ||
55 | static unsigned long cpu_clk_recalc(struct clk *clk) | 55 | static unsigned long cpu_clk_recalc(struct clk *clk) |
56 | { | 56 | { |
57 | int idx = (ctrl_inw(cprc_base) & 0x0007); | 57 | int idx = (__raw_readw(cprc_base) & 0x0007); |
58 | return clk->parent->rate / ifc_table[idx]; | 58 | return clk->parent->rate / ifc_table[idx]; |
59 | } | 59 | } |
60 | 60 | ||
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index b0aacf675258..6b80295dd7a4 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S | |||
@@ -187,7 +187,7 @@ trap_jtable: | |||
187 | .rept 6 | 187 | .rept 6 |
188 | .long do_exception_error /* 0x880 - 0x920 */ | 188 | .long do_exception_error /* 0x880 - 0x920 */ |
189 | .endr | 189 | .endr |
190 | .long do_software_break_point /* 0x940 */ | 190 | .long breakpoint_trap_handler /* 0x940 */ |
191 | .long do_exception_error /* 0x960 */ | 191 | .long do_exception_error /* 0x960 */ |
192 | .long do_single_step /* 0x980 */ | 192 | .long do_single_step /* 0x980 */ |
193 | 193 | ||
@@ -933,7 +933,7 @@ ret_with_reschedule: | |||
933 | 933 | ||
934 | pta restore_all, tr1 | 934 | pta restore_all, tr1 |
935 | 935 | ||
936 | movi (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r8 | 936 | movi _TIF_SIGPENDING, r8 |
937 | and r8, r7, r8 | 937 | and r8, r7, r8 |
938 | pta work_notifysig, tr0 | 938 | pta work_notifysig, tr0 |
939 | bne r8, ZERO, tr0 | 939 | bne r8, ZERO, tr0 |
@@ -1124,7 +1124,7 @@ fpu_error_or_IRQA: | |||
1124 | pta its_IRQ, tr0 | 1124 | pta its_IRQ, tr0 |
1125 | beqi/l r4, EVENT_INTERRUPT, tr0 | 1125 | beqi/l r4, EVENT_INTERRUPT, tr0 |
1126 | #ifdef CONFIG_SH_FPU | 1126 | #ifdef CONFIG_SH_FPU |
1127 | movi do_fpu_state_restore, r6 | 1127 | movi fpu_state_restore_trap_handler, r6 |
1128 | #else | 1128 | #else |
1129 | movi do_exception_error, r6 | 1129 | movi do_exception_error, r6 |
1130 | #endif | 1130 | #endif |
@@ -1135,7 +1135,7 @@ fpu_error_or_IRQB: | |||
1135 | pta its_IRQ, tr0 | 1135 | pta its_IRQ, tr0 |
1136 | beqi/l r4, EVENT_INTERRUPT, tr0 | 1136 | beqi/l r4, EVENT_INTERRUPT, tr0 |
1137 | #ifdef CONFIG_SH_FPU | 1137 | #ifdef CONFIG_SH_FPU |
1138 | movi do_fpu_state_restore, r6 | 1138 | movi fpu_state_restore_trap_handler, r6 |
1139 | #else | 1139 | #else |
1140 | movi do_exception_error, r6 | 1140 | movi do_exception_error, r6 |
1141 | #endif | 1141 | #endif |
diff --git a/arch/sh/kernel/cpu/sh5/fpu.c b/arch/sh/kernel/cpu/sh5/fpu.c index dd4f51ffb50e..4b3bb35e99f3 100644 --- a/arch/sh/kernel/cpu/sh5/fpu.c +++ b/arch/sh/kernel/cpu/sh5/fpu.c | |||
@@ -15,26 +15,8 @@ | |||
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/signal.h> | 16 | #include <linux/signal.h> |
17 | #include <asm/processor.h> | 17 | #include <asm/processor.h> |
18 | #include <asm/user.h> | ||
19 | #include <asm/io.h> | ||
20 | #include <asm/fpu.h> | ||
21 | 18 | ||
22 | /* | 19 | void save_fpu(struct task_struct *tsk) |
23 | * Initially load the FPU with signalling NANS. This bit pattern | ||
24 | * has the property that no matter whether considered as single or as | ||
25 | * double precision, it still represents a signalling NAN. | ||
26 | */ | ||
27 | #define sNAN64 0xFFFFFFFFFFFFFFFFULL | ||
28 | #define sNAN32 0xFFFFFFFFUL | ||
29 | |||
30 | static union sh_fpu_union init_fpuregs = { | ||
31 | .hard = { | ||
32 | .fp_regs = { [0 ... 63] = sNAN32 }, | ||
33 | .fpscr = FPSCR_INIT | ||
34 | } | ||
35 | }; | ||
36 | |||
37 | void save_fpu(struct task_struct *tsk, struct pt_regs *regs) | ||
38 | { | 20 | { |
39 | asm volatile("fst.p %0, (0*8), fp0\n\t" | 21 | asm volatile("fst.p %0, (0*8), fp0\n\t" |
40 | "fst.p %0, (1*8), fp2\n\t" | 22 | "fst.p %0, (1*8), fp2\n\t" |
@@ -72,12 +54,11 @@ void save_fpu(struct task_struct *tsk, struct pt_regs *regs) | |||
72 | "fgetscr fr63\n\t" | 54 | "fgetscr fr63\n\t" |
73 | "fst.s %0, (32*8), fr63\n\t" | 55 | "fst.s %0, (32*8), fr63\n\t" |
74 | : /* no output */ | 56 | : /* no output */ |
75 | : "r" (&tsk->thread.fpu.hard) | 57 | : "r" (&tsk->thread.xstate->hardfpu) |
76 | : "memory"); | 58 | : "memory"); |
77 | } | 59 | } |
78 | 60 | ||
79 | static inline void | 61 | void restore_fpu(struct task_struct *tsk) |
80 | fpload(struct sh_fpu_hard_struct *fpregs) | ||
81 | { | 62 | { |
82 | asm volatile("fld.p %0, (0*8), fp0\n\t" | 63 | asm volatile("fld.p %0, (0*8), fp0\n\t" |
83 | "fld.p %0, (1*8), fp2\n\t" | 64 | "fld.p %0, (1*8), fp2\n\t" |
@@ -116,16 +97,11 @@ fpload(struct sh_fpu_hard_struct *fpregs) | |||
116 | 97 | ||
117 | "fld.p %0, (31*8), fp62\n\t" | 98 | "fld.p %0, (31*8), fp62\n\t" |
118 | : /* no output */ | 99 | : /* no output */ |
119 | : "r" (fpregs) ); | 100 | : "r" (&tsk->thread.xstate->hardfpu) |
120 | } | 101 | : "memory"); |
121 | |||
122 | void fpinit(struct sh_fpu_hard_struct *fpregs) | ||
123 | { | ||
124 | *fpregs = init_fpuregs.hard; | ||
125 | } | 102 | } |
126 | 103 | ||
127 | asmlinkage void | 104 | asmlinkage void do_fpu_error(unsigned long ex, struct pt_regs *regs) |
128 | do_fpu_error(unsigned long ex, struct pt_regs *regs) | ||
129 | { | 105 | { |
130 | struct task_struct *tsk = current; | 106 | struct task_struct *tsk = current; |
131 | 107 | ||
@@ -133,35 +109,6 @@ do_fpu_error(unsigned long ex, struct pt_regs *regs) | |||
133 | 109 | ||
134 | tsk->thread.trap_no = 11; | 110 | tsk->thread.trap_no = 11; |
135 | tsk->thread.error_code = 0; | 111 | tsk->thread.error_code = 0; |
136 | force_sig(SIGFPE, tsk); | ||
137 | } | ||
138 | |||
139 | |||
140 | asmlinkage void | ||
141 | do_fpu_state_restore(unsigned long ex, struct pt_regs *regs) | ||
142 | { | ||
143 | void die(const char *str, struct pt_regs *regs, long err); | ||
144 | |||
145 | if (! user_mode(regs)) | ||
146 | die("FPU used in kernel", regs, ex); | ||
147 | 112 | ||
148 | regs->sr &= ~SR_FD; | 113 | force_sig(SIGFPE, tsk); |
149 | |||
150 | if (last_task_used_math == current) | ||
151 | return; | ||
152 | |||
153 | enable_fpu(); | ||
154 | if (last_task_used_math != NULL) | ||
155 | /* Other processes fpu state, save away */ | ||
156 | save_fpu(last_task_used_math, regs); | ||
157 | |||
158 | last_task_used_math = current; | ||
159 | if (used_math()) { | ||
160 | fpload(¤t->thread.fpu.hard); | ||
161 | } else { | ||
162 | /* First time FPU user. */ | ||
163 | fpload(&init_fpuregs.hard); | ||
164 | set_used_math(); | ||
165 | } | ||
166 | disable_fpu(); | ||
167 | } | 114 | } |
diff --git a/arch/sh/kernel/cpu/sh5/setup-sh5.c b/arch/sh/kernel/cpu/sh5/setup-sh5.c index 6a0f82f70032..e7a3c1e4b604 100644 --- a/arch/sh/kernel/cpu/sh5/setup-sh5.c +++ b/arch/sh/kernel/cpu/sh5/setup-sh5.c | |||
@@ -16,22 +16,18 @@ | |||
16 | #include <linux/sh_timer.h> | 16 | #include <linux/sh_timer.h> |
17 | #include <asm/addrspace.h> | 17 | #include <asm/addrspace.h> |
18 | 18 | ||
19 | static struct plat_sci_port sci_platform_data[] = { | 19 | static struct plat_sci_port scif0_platform_data = { |
20 | { | 20 | .mapbase = PHYS_PERIPHERAL_BLOCK + 0x01030000, |
21 | .mapbase = PHYS_PERIPHERAL_BLOCK + 0x01030000, | 21 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, |
22 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, | 22 | .type = PORT_SCIF, |
23 | .type = PORT_SCIF, | 23 | .irqs = { 39, 40, 42, 0 }, |
24 | .irqs = { 39, 40, 42, 0 }, | ||
25 | }, { | ||
26 | .flags = 0, | ||
27 | } | ||
28 | }; | 24 | }; |
29 | 25 | ||
30 | static struct platform_device sci_device = { | 26 | static struct platform_device scif0_device = { |
31 | .name = "sh-sci", | 27 | .name = "sh-sci", |
32 | .id = -1, | 28 | .id = 0, |
33 | .dev = { | 29 | .dev = { |
34 | .platform_data = sci_platform_data, | 30 | .platform_data = &scif0_platform_data, |
35 | }, | 31 | }, |
36 | }; | 32 | }; |
37 | 33 | ||
@@ -164,13 +160,13 @@ static struct platform_device tmu2_device = { | |||
164 | }; | 160 | }; |
165 | 161 | ||
166 | static struct platform_device *sh5_early_devices[] __initdata = { | 162 | static struct platform_device *sh5_early_devices[] __initdata = { |
163 | &scif0_device, | ||
167 | &tmu0_device, | 164 | &tmu0_device, |
168 | &tmu1_device, | 165 | &tmu1_device, |
169 | &tmu2_device, | 166 | &tmu2_device, |
170 | }; | 167 | }; |
171 | 168 | ||
172 | static struct platform_device *sh5_devices[] __initdata = { | 169 | static struct platform_device *sh5_devices[] __initdata = { |
173 | &sci_device, | ||
174 | &rtc_device, | 170 | &rtc_device, |
175 | }; | 171 | }; |
176 | 172 | ||
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c index 1c504bd972c3..83972aa319c2 100644 --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c | |||
@@ -87,25 +87,31 @@ void sh_mobile_setup_cpuidle(void) | |||
87 | 87 | ||
88 | dev->safe_state = state; | 88 | dev->safe_state = state; |
89 | 89 | ||
90 | state = &dev->states[i++]; | 90 | if (sh_mobile_sleep_supported & SUSP_SH_SF) { |
91 | snprintf(state->name, CPUIDLE_NAME_LEN, "C1"); | 91 | state = &dev->states[i++]; |
92 | strncpy(state->desc, "SuperH Sleep Mode [SF]", CPUIDLE_DESC_LEN); | 92 | snprintf(state->name, CPUIDLE_NAME_LEN, "C1"); |
93 | state->exit_latency = 100; | 93 | strncpy(state->desc, "SuperH Sleep Mode [SF]", |
94 | state->target_residency = 1 * 2; | 94 | CPUIDLE_DESC_LEN); |
95 | state->power_usage = 1; | 95 | state->exit_latency = 100; |
96 | state->flags = 0; | 96 | state->target_residency = 1 * 2; |
97 | state->flags |= CPUIDLE_FLAG_TIME_VALID; | 97 | state->power_usage = 1; |
98 | state->enter = cpuidle_sleep_enter; | 98 | state->flags = 0; |
99 | state->flags |= CPUIDLE_FLAG_TIME_VALID; | ||
100 | state->enter = cpuidle_sleep_enter; | ||
101 | } | ||
99 | 102 | ||
100 | state = &dev->states[i++]; | 103 | if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) { |
101 | snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); | 104 | state = &dev->states[i++]; |
102 | strncpy(state->desc, "SuperH Mobile Standby Mode [SF]", CPUIDLE_DESC_LEN); | 105 | snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); |
103 | state->exit_latency = 2300; | 106 | strncpy(state->desc, "SuperH Mobile Standby Mode [SF]", |
104 | state->target_residency = 1 * 2; | 107 | CPUIDLE_DESC_LEN); |
105 | state->power_usage = 1; | 108 | state->exit_latency = 2300; |
106 | state->flags = 0; | 109 | state->target_residency = 1 * 2; |
107 | state->flags |= CPUIDLE_FLAG_TIME_VALID; | 110 | state->power_usage = 1; |
108 | state->enter = cpuidle_sleep_enter; | 111 | state->flags = 0; |
112 | state->flags |= CPUIDLE_FLAG_TIME_VALID; | ||
113 | state->enter = cpuidle_sleep_enter; | ||
114 | } | ||
109 | 115 | ||
110 | dev->state_count = i; | 116 | dev->state_count = i; |
111 | 117 | ||
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c index ee3c2aaf66fb..e55968712706 100644 --- a/arch/sh/kernel/cpu/shmobile/pm.c +++ b/arch/sh/kernel/cpu/shmobile/pm.c | |||
@@ -15,6 +15,13 @@ | |||
15 | #include <linux/suspend.h> | 15 | #include <linux/suspend.h> |
16 | #include <asm/suspend.h> | 16 | #include <asm/suspend.h> |
17 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
18 | #include <asm/cacheflush.h> | ||
19 | |||
20 | /* | ||
21 | * Notifier lists for pre/post sleep notification | ||
22 | */ | ||
23 | ATOMIC_NOTIFIER_HEAD(sh_mobile_pre_sleep_notifier_list); | ||
24 | ATOMIC_NOTIFIER_HEAD(sh_mobile_post_sleep_notifier_list); | ||
18 | 25 | ||
19 | /* | 26 | /* |
20 | * Sleep modes available on SuperH Mobile: | 27 | * Sleep modes available on SuperH Mobile: |
@@ -26,30 +33,106 @@ | |||
26 | #define SUSP_MODE_SLEEP (SUSP_SH_SLEEP) | 33 | #define SUSP_MODE_SLEEP (SUSP_SH_SLEEP) |
27 | #define SUSP_MODE_SLEEP_SF (SUSP_SH_SLEEP | SUSP_SH_SF) | 34 | #define SUSP_MODE_SLEEP_SF (SUSP_SH_SLEEP | SUSP_SH_SF) |
28 | #define SUSP_MODE_STANDBY_SF (SUSP_SH_STANDBY | SUSP_SH_SF) | 35 | #define SUSP_MODE_STANDBY_SF (SUSP_SH_STANDBY | SUSP_SH_SF) |
36 | #define SUSP_MODE_RSTANDBY_SF \ | ||
37 | (SUSP_SH_RSTANDBY | SUSP_SH_MMU | SUSP_SH_REGS | SUSP_SH_SF) | ||
38 | /* | ||
39 | * U-standby mode is unsupported since it needs bootloader hacks | ||
40 | */ | ||
29 | 41 | ||
30 | /* | 42 | #ifdef CONFIG_CPU_SUBTYPE_SH7724 |
31 | * The following modes are not there yet: | 43 | #define RAM_BASE 0xfd800000 /* RSMEM */ |
32 | * | 44 | #else |
33 | * R-standby mode is unsupported, but will be added in the future | 45 | #define RAM_BASE 0xe5200000 /* ILRAM */ |
34 | * U-standby mode is low priority since it needs bootloader hacks | 46 | #endif |
35 | */ | ||
36 | |||
37 | #define ILRAM_BASE 0xe5200000 | ||
38 | |||
39 | extern const unsigned char sh_mobile_standby[]; | ||
40 | extern const unsigned int sh_mobile_standby_size; | ||
41 | 47 | ||
42 | void sh_mobile_call_standby(unsigned long mode) | 48 | void sh_mobile_call_standby(unsigned long mode) |
43 | { | 49 | { |
44 | void *onchip_mem = (void *)ILRAM_BASE; | 50 | void *onchip_mem = (void *)RAM_BASE; |
45 | void (*standby_onchip_mem)(unsigned long, unsigned long) = onchip_mem; | 51 | struct sh_sleep_data *sdp = onchip_mem; |
52 | void (*standby_onchip_mem)(unsigned long, unsigned long); | ||
53 | |||
54 | /* code located directly after data structure */ | ||
55 | standby_onchip_mem = (void *)(sdp + 1); | ||
56 | |||
57 | atomic_notifier_call_chain(&sh_mobile_pre_sleep_notifier_list, | ||
58 | mode, NULL); | ||
59 | |||
60 | /* flush the caches if MMU flag is set */ | ||
61 | if (mode & SUSP_SH_MMU) | ||
62 | flush_cache_all(); | ||
46 | 63 | ||
47 | /* Let assembly snippet in on-chip memory handle the rest */ | 64 | /* Let assembly snippet in on-chip memory handle the rest */ |
48 | standby_onchip_mem(mode, ILRAM_BASE); | 65 | standby_onchip_mem(mode, RAM_BASE); |
66 | |||
67 | atomic_notifier_call_chain(&sh_mobile_post_sleep_notifier_list, | ||
68 | mode, NULL); | ||
69 | } | ||
70 | |||
71 | extern char sh_mobile_sleep_enter_start; | ||
72 | extern char sh_mobile_sleep_enter_end; | ||
73 | |||
74 | extern char sh_mobile_sleep_resume_start; | ||
75 | extern char sh_mobile_sleep_resume_end; | ||
76 | |||
77 | unsigned long sh_mobile_sleep_supported = SUSP_SH_SLEEP; | ||
78 | |||
79 | void sh_mobile_register_self_refresh(unsigned long flags, | ||
80 | void *pre_start, void *pre_end, | ||
81 | void *post_start, void *post_end) | ||
82 | { | ||
83 | void *onchip_mem = (void *)RAM_BASE; | ||
84 | void *vp; | ||
85 | struct sh_sleep_data *sdp; | ||
86 | int n; | ||
87 | |||
88 | /* part 0: data area */ | ||
89 | sdp = onchip_mem; | ||
90 | sdp->addr.stbcr = 0xa4150020; /* STBCR */ | ||
91 | sdp->addr.bar = 0xa4150040; /* BAR */ | ||
92 | sdp->addr.pteh = 0xff000000; /* PTEH */ | ||
93 | sdp->addr.ptel = 0xff000004; /* PTEL */ | ||
94 | sdp->addr.ttb = 0xff000008; /* TTB */ | ||
95 | sdp->addr.tea = 0xff00000c; /* TEA */ | ||
96 | sdp->addr.mmucr = 0xff000010; /* MMUCR */ | ||
97 | sdp->addr.ptea = 0xff000034; /* PTEA */ | ||
98 | sdp->addr.pascr = 0xff000070; /* PASCR */ | ||
99 | sdp->addr.irmcr = 0xff000078; /* IRMCR */ | ||
100 | sdp->addr.ccr = 0xff00001c; /* CCR */ | ||
101 | sdp->addr.ramcr = 0xff000074; /* RAMCR */ | ||
102 | vp = sdp + 1; | ||
103 | |||
104 | /* part 1: common code to enter sleep mode */ | ||
105 | n = &sh_mobile_sleep_enter_end - &sh_mobile_sleep_enter_start; | ||
106 | memcpy(vp, &sh_mobile_sleep_enter_start, n); | ||
107 | vp += roundup(n, 4); | ||
108 | |||
109 | /* part 2: board specific code to enter self-refresh mode */ | ||
110 | n = pre_end - pre_start; | ||
111 | memcpy(vp, pre_start, n); | ||
112 | sdp->sf_pre = (unsigned long)vp; | ||
113 | vp += roundup(n, 4); | ||
114 | |||
115 | /* part 3: board specific code to resume from self-refresh mode */ | ||
116 | n = post_end - post_start; | ||
117 | memcpy(vp, post_start, n); | ||
118 | sdp->sf_post = (unsigned long)vp; | ||
119 | vp += roundup(n, 4); | ||
120 | |||
121 | /* part 4: common code to resume from sleep mode */ | ||
122 | WARN_ON(vp > (onchip_mem + 0x600)); | ||
123 | vp = onchip_mem + 0x600; /* located at interrupt vector */ | ||
124 | n = &sh_mobile_sleep_resume_end - &sh_mobile_sleep_resume_start; | ||
125 | memcpy(vp, &sh_mobile_sleep_resume_start, n); | ||
126 | sdp->resume = (unsigned long)vp; | ||
127 | |||
128 | sh_mobile_sleep_supported |= flags; | ||
49 | } | 129 | } |
50 | 130 | ||
51 | static int sh_pm_enter(suspend_state_t state) | 131 | static int sh_pm_enter(suspend_state_t state) |
52 | { | 132 | { |
133 | if (!(sh_mobile_sleep_supported & SUSP_MODE_STANDBY_SF)) | ||
134 | return -ENXIO; | ||
135 | |||
53 | local_irq_disable(); | 136 | local_irq_disable(); |
54 | set_bl_bit(); | 137 | set_bl_bit(); |
55 | sh_mobile_call_standby(SUSP_MODE_STANDBY_SF); | 138 | sh_mobile_call_standby(SUSP_MODE_STANDBY_SF); |
@@ -65,13 +148,6 @@ static struct platform_suspend_ops sh_pm_ops = { | |||
65 | 148 | ||
66 | static int __init sh_pm_init(void) | 149 | static int __init sh_pm_init(void) |
67 | { | 150 | { |
68 | void *onchip_mem = (void *)ILRAM_BASE; | ||
69 | |||
70 | /* Copy the assembly snippet to the otherwise ununsed ILRAM */ | ||
71 | memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size); | ||
72 | wmb(); | ||
73 | ctrl_barrier(); | ||
74 | |||
75 | suspend_set_ops(&sh_pm_ops); | 151 | suspend_set_ops(&sh_pm_ops); |
76 | sh_mobile_setup_cpuidle(); | 152 | sh_mobile_setup_cpuidle(); |
77 | return 0; | 153 | return 0; |
diff --git a/arch/sh/kernel/cpu/shmobile/pm_runtime.c b/arch/sh/kernel/cpu/shmobile/pm_runtime.c index 7c615b17e209..6dcb8166a64d 100644 --- a/arch/sh/kernel/cpu/shmobile/pm_runtime.c +++ b/arch/sh/kernel/cpu/shmobile/pm_runtime.c | |||
@@ -45,12 +45,14 @@ static int __platform_pm_runtime_resume(struct platform_device *pdev) | |||
45 | 45 | ||
46 | dev_dbg(d, "__platform_pm_runtime_resume() [%d]\n", hwblk); | 46 | dev_dbg(d, "__platform_pm_runtime_resume() [%d]\n", hwblk); |
47 | 47 | ||
48 | if (d->driver && d->driver->pm && d->driver->pm->runtime_resume) { | 48 | if (d->driver) { |
49 | hwblk_enable(hwblk_info, hwblk); | 49 | hwblk_enable(hwblk_info, hwblk); |
50 | ret = 0; | 50 | ret = 0; |
51 | 51 | ||
52 | if (test_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags)) { | 52 | if (test_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags)) { |
53 | ret = d->driver->pm->runtime_resume(d); | 53 | if (d->driver->pm && d->driver->pm->runtime_resume) |
54 | ret = d->driver->pm->runtime_resume(d); | ||
55 | |||
54 | if (!ret) | 56 | if (!ret) |
55 | clear_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags); | 57 | clear_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags); |
56 | else | 58 | else |
@@ -73,12 +75,15 @@ static int __platform_pm_runtime_suspend(struct platform_device *pdev) | |||
73 | 75 | ||
74 | dev_dbg(d, "__platform_pm_runtime_suspend() [%d]\n", hwblk); | 76 | dev_dbg(d, "__platform_pm_runtime_suspend() [%d]\n", hwblk); |
75 | 77 | ||
76 | if (d->driver && d->driver->pm && d->driver->pm->runtime_suspend) { | 78 | if (d->driver) { |
77 | BUG_ON(!test_bit(PDEV_ARCHDATA_FLAG_IDLE, &ad->flags)); | 79 | BUG_ON(!test_bit(PDEV_ARCHDATA_FLAG_IDLE, &ad->flags)); |
80 | ret = 0; | ||
78 | 81 | ||
79 | hwblk_enable(hwblk_info, hwblk); | 82 | if (d->driver->pm && d->driver->pm->runtime_suspend) { |
80 | ret = d->driver->pm->runtime_suspend(d); | 83 | hwblk_enable(hwblk_info, hwblk); |
81 | hwblk_disable(hwblk_info, hwblk); | 84 | ret = d->driver->pm->runtime_suspend(d); |
85 | hwblk_disable(hwblk_info, hwblk); | ||
86 | } | ||
82 | 87 | ||
83 | if (!ret) { | 88 | if (!ret) { |
84 | set_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags); | 89 | set_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags); |
diff --git a/arch/sh/kernel/cpu/shmobile/sleep.S b/arch/sh/kernel/cpu/shmobile/sleep.S index a439e6c7824f..e6aac65f5750 100644 --- a/arch/sh/kernel/cpu/shmobile/sleep.S +++ b/arch/sh/kernel/cpu/shmobile/sleep.S | |||
@@ -20,79 +20,143 @@ | |||
20 | * Kernel mode register usage, see entry.S: | 20 | * Kernel mode register usage, see entry.S: |
21 | * k0 scratch | 21 | * k0 scratch |
22 | * k1 scratch | 22 | * k1 scratch |
23 | * k4 scratch | ||
24 | */ | 23 | */ |
25 | #define k0 r0 | 24 | #define k0 r0 |
26 | #define k1 r1 | 25 | #define k1 r1 |
27 | #define k4 r4 | ||
28 | 26 | ||
29 | /* manage self-refresh and enter standby mode. | 27 | /* manage self-refresh and enter standby mode. must be self-contained. |
30 | * this code will be copied to on-chip memory and executed from there. | 28 | * this code will be copied to on-chip memory and executed from there. |
31 | */ | 29 | */ |
30 | .balign 4 | ||
31 | ENTRY(sh_mobile_sleep_enter_start) | ||
32 | 32 | ||
33 | .balign 4096,0,4096 | 33 | /* save mode flags */ |
34 | ENTRY(sh_mobile_standby) | 34 | mov.l r4, @(SH_SLEEP_MODE, r5) |
35 | 35 | ||
36 | /* save original vbr */ | 36 | /* save original vbr */ |
37 | stc vbr, r1 | 37 | stc vbr, r0 |
38 | mova saved_vbr, r0 | 38 | mov.l r0, @(SH_SLEEP_VBR, r5) |
39 | mov.l r1, @r0 | ||
40 | 39 | ||
41 | /* point vbr to our on-chip memory page */ | 40 | /* point vbr to our on-chip memory page */ |
42 | ldc r5, vbr | 41 | ldc r5, vbr |
43 | 42 | ||
44 | /* save return address */ | 43 | /* save return address */ |
45 | mova saved_spc, r0 | 44 | sts pr, r0 |
46 | sts pr, r5 | 45 | mov.l r0, @(SH_SLEEP_SPC, r5) |
47 | mov.l r5, @r0 | ||
48 | 46 | ||
49 | /* save sr */ | 47 | /* save sr */ |
50 | mova saved_sr, r0 | 48 | stc sr, r0 |
51 | stc sr, r5 | 49 | mov.l r0, @(SH_SLEEP_SR, r5) |
52 | mov.l r5, @r0 | 50 | |
51 | /* save general purpose registers to stack if needed */ | ||
52 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
53 | tst #SUSP_SH_REGS, r0 | ||
54 | bt skip_regs_save | ||
55 | |||
56 | sts.l pr, @-r15 | ||
57 | mov.l r14, @-r15 | ||
58 | mov.l r13, @-r15 | ||
59 | mov.l r12, @-r15 | ||
60 | mov.l r11, @-r15 | ||
61 | mov.l r10, @-r15 | ||
62 | mov.l r9, @-r15 | ||
63 | mov.l r8, @-r15 | ||
64 | |||
65 | /* make sure bank0 is selected, save low registers */ | ||
66 | mov.l rb_bit, r9 | ||
67 | not r9, r9 | ||
68 | bsr set_sr | ||
69 | mov #0, r10 | ||
70 | |||
71 | bsr save_low_regs | ||
72 | nop | ||
53 | 73 | ||
54 | /* save mode flags */ | 74 | /* switch to bank 1, save low registers */ |
55 | mova saved_mode, r0 | 75 | mov.l rb_bit, r10 |
56 | mov.l r4, @r0 | 76 | bsr set_sr |
77 | mov #-1, r9 | ||
78 | |||
79 | bsr save_low_regs | ||
80 | nop | ||
81 | |||
82 | /* switch back to bank 0 */ | ||
83 | mov.l rb_bit, r9 | ||
84 | not r9, r9 | ||
85 | bsr set_sr | ||
86 | mov #0, r10 | ||
87 | |||
88 | skip_regs_save: | ||
89 | |||
90 | /* save sp, also set to internal ram */ | ||
91 | mov.l r15, @(SH_SLEEP_SP, r5) | ||
92 | mov r5, r15 | ||
93 | |||
94 | /* save stbcr */ | ||
95 | bsr save_register | ||
96 | mov #SH_SLEEP_REG_STBCR, r0 | ||
97 | |||
98 | /* save mmu and cache context if needed */ | ||
99 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
100 | tst #SUSP_SH_MMU, r0 | ||
101 | bt skip_mmu_save_disable | ||
102 | |||
103 | /* save mmu state */ | ||
104 | bsr save_register | ||
105 | mov #SH_SLEEP_REG_PTEH, r0 | ||
106 | |||
107 | bsr save_register | ||
108 | mov #SH_SLEEP_REG_PTEL, r0 | ||
109 | |||
110 | bsr save_register | ||
111 | mov #SH_SLEEP_REG_TTB, r0 | ||
112 | |||
113 | bsr save_register | ||
114 | mov #SH_SLEEP_REG_TEA, r0 | ||
115 | |||
116 | bsr save_register | ||
117 | mov #SH_SLEEP_REG_MMUCR, r0 | ||
118 | |||
119 | bsr save_register | ||
120 | mov #SH_SLEEP_REG_PTEA, r0 | ||
121 | |||
122 | bsr save_register | ||
123 | mov #SH_SLEEP_REG_PASCR, r0 | ||
57 | 124 | ||
58 | /* put mode flags in r0 */ | 125 | bsr save_register |
59 | mov r4, r0 | 126 | mov #SH_SLEEP_REG_IRMCR, r0 |
60 | 127 | ||
128 | /* invalidate TLBs and disable the MMU */ | ||
129 | bsr get_register | ||
130 | mov #SH_SLEEP_REG_MMUCR, r0 | ||
131 | mov #4, r1 | ||
132 | mov.l r1, @r0 | ||
133 | icbi @r0 | ||
134 | |||
135 | /* save cache registers and disable caches */ | ||
136 | bsr save_register | ||
137 | mov #SH_SLEEP_REG_CCR, r0 | ||
138 | |||
139 | bsr save_register | ||
140 | mov #SH_SLEEP_REG_RAMCR, r0 | ||
141 | |||
142 | bsr get_register | ||
143 | mov #SH_SLEEP_REG_CCR, r0 | ||
144 | mov #0, r1 | ||
145 | mov.l r1, @r0 | ||
146 | icbi @r0 | ||
147 | |||
148 | skip_mmu_save_disable: | ||
149 | /* call self-refresh entering code if needed */ | ||
150 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
61 | tst #SUSP_SH_SF, r0 | 151 | tst #SUSP_SH_SF, r0 |
62 | bt skip_set_sf | 152 | bt skip_set_sf |
63 | #ifdef CONFIG_CPU_SUBTYPE_SH7724 | 153 | |
64 | /* DBSC: put memory in self-refresh mode */ | 154 | mov.l @(SH_SLEEP_SF_PRE, r5), r0 |
65 | mov.l dben_reg, r4 | 155 | jsr @r0 |
66 | mov.l dben_data0, r1 | 156 | nop |
67 | mov.l r1, @r4 | ||
68 | |||
69 | mov.l dbrfpdn0_reg, r4 | ||
70 | mov.l dbrfpdn0_data0, r1 | ||
71 | mov.l r1, @r4 | ||
72 | |||
73 | mov.l dbcmdcnt_reg, r4 | ||
74 | mov.l dbcmdcnt_data0, r1 | ||
75 | mov.l r1, @r4 | ||
76 | |||
77 | mov.l dbcmdcnt_reg, r4 | ||
78 | mov.l dbcmdcnt_data1, r1 | ||
79 | mov.l r1, @r4 | ||
80 | |||
81 | mov.l dbrfpdn0_reg, r4 | ||
82 | mov.l dbrfpdn0_data1, r1 | ||
83 | mov.l r1, @r4 | ||
84 | #else | ||
85 | /* SBSC: disable power down and put in self-refresh mode */ | ||
86 | mov.l 1f, r4 | ||
87 | mov.l 2f, r1 | ||
88 | mov.l @r4, r2 | ||
89 | or r1, r2 | ||
90 | mov.l 3f, r3 | ||
91 | and r3, r2 | ||
92 | mov.l r2, @r4 | ||
93 | #endif | ||
94 | 157 | ||
95 | skip_set_sf: | 158 | skip_set_sf: |
159 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
96 | tst #SUSP_SH_STANDBY, r0 | 160 | tst #SUSP_SH_STANDBY, r0 |
97 | bt test_rstandby | 161 | bt test_rstandby |
98 | 162 | ||
@@ -104,6 +168,12 @@ test_rstandby: | |||
104 | tst #SUSP_SH_RSTANDBY, r0 | 168 | tst #SUSP_SH_RSTANDBY, r0 |
105 | bt test_ustandby | 169 | bt test_ustandby |
106 | 170 | ||
171 | /* setup BAR register */ | ||
172 | bsr get_register | ||
173 | mov #SH_SLEEP_REG_BAR, r0 | ||
174 | mov.l @(SH_SLEEP_RESUME, r5), r1 | ||
175 | mov.l r1, @r0 | ||
176 | |||
107 | /* set mode to "r-standby mode" */ | 177 | /* set mode to "r-standby mode" */ |
108 | bra do_sleep | 178 | bra do_sleep |
109 | mov #0x20, r1 | 179 | mov #0x20, r1 |
@@ -123,124 +193,213 @@ force_sleep: | |||
123 | 193 | ||
124 | do_sleep: | 194 | do_sleep: |
125 | /* setup and enter selected standby mode */ | 195 | /* setup and enter selected standby mode */ |
126 | mov.l 5f, r4 | 196 | bsr get_register |
127 | mov.l r1, @r4 | 197 | mov #SH_SLEEP_REG_STBCR, r0 |
198 | mov.l r1, @r0 | ||
128 | again: | 199 | again: |
129 | sleep | 200 | sleep |
130 | bra again | 201 | bra again |
131 | nop | 202 | nop |
132 | 203 | ||
133 | restore_jump_vbr: | 204 | save_register: |
205 | add #SH_SLEEP_BASE_ADDR, r0 | ||
206 | mov.l @(r0, r5), r1 | ||
207 | add #-SH_SLEEP_BASE_ADDR, r0 | ||
208 | mov.l @r1, r1 | ||
209 | add #SH_SLEEP_BASE_DATA, r0 | ||
210 | mov.l r1, @(r0, r5) | ||
211 | add #-SH_SLEEP_BASE_DATA, r0 | ||
212 | rts | ||
213 | nop | ||
214 | |||
215 | get_register: | ||
216 | add #SH_SLEEP_BASE_ADDR, r0 | ||
217 | mov.l @(r0, r5), r0 | ||
218 | rts | ||
219 | nop | ||
220 | |||
221 | set_sr: | ||
222 | stc sr, r8 | ||
223 | and r9, r8 | ||
224 | or r10, r8 | ||
225 | ldc r8, sr | ||
226 | rts | ||
227 | nop | ||
228 | |||
229 | save_low_regs: | ||
230 | mov.l r7, @-r15 | ||
231 | mov.l r6, @-r15 | ||
232 | mov.l r5, @-r15 | ||
233 | mov.l r4, @-r15 | ||
234 | mov.l r3, @-r15 | ||
235 | mov.l r2, @-r15 | ||
236 | mov.l r1, @-r15 | ||
237 | rts | ||
238 | mov.l r0, @-r15 | ||
239 | |||
240 | .balign 4 | ||
241 | rb_bit: .long 0x20000000 ! RB=1 | ||
242 | |||
243 | ENTRY(sh_mobile_sleep_enter_end) | ||
244 | |||
245 | .balign 4 | ||
246 | ENTRY(sh_mobile_sleep_resume_start) | ||
247 | |||
248 | /* figure out start address */ | ||
249 | bsr 0f | ||
250 | nop | ||
251 | 0: | ||
252 | sts pr, k1 | ||
253 | mov.l 1f, k0 | ||
254 | and k0, k1 | ||
255 | |||
256 | /* store pointer to data area in VBR */ | ||
257 | ldc k1, vbr | ||
258 | |||
259 | /* setup sr with saved sr */ | ||
260 | mov.l @(SH_SLEEP_SR, k1), k0 | ||
261 | ldc k0, sr | ||
262 | |||
263 | /* now: user register set! */ | ||
264 | stc vbr, r5 | ||
265 | |||
134 | /* setup spc with return address to c code */ | 266 | /* setup spc with return address to c code */ |
135 | mov.l saved_spc, k0 | 267 | mov.l @(SH_SLEEP_SPC, r5), r0 |
136 | ldc k0, spc | 268 | ldc r0, spc |
137 | 269 | ||
138 | /* restore vbr */ | 270 | /* restore vbr */ |
139 | mov.l saved_vbr, k0 | 271 | mov.l @(SH_SLEEP_VBR, r5), r0 |
140 | ldc k0, vbr | 272 | ldc r0, vbr |
141 | 273 | ||
142 | /* setup ssr with saved sr */ | 274 | /* setup ssr with saved sr */ |
143 | mov.l saved_sr, k0 | 275 | mov.l @(SH_SLEEP_SR, r5), r0 |
144 | ldc k0, ssr | 276 | ldc r0, ssr |
145 | 277 | ||
146 | /* get mode flags */ | 278 | /* restore sp */ |
147 | mov.l saved_mode, k0 | 279 | mov.l @(SH_SLEEP_SP, r5), r15 |
148 | 280 | ||
149 | done_sleep: | 281 | /* restore sleep mode register */ |
150 | /* reset standby mode to sleep mode */ | 282 | bsr restore_register |
151 | mov.l 5f, k4 | 283 | mov #SH_SLEEP_REG_STBCR, r0 |
152 | mov #0x00, k1 | ||
153 | mov.l k1, @k4 | ||
154 | 284 | ||
155 | tst #SUSP_SH_SF, k0 | 285 | /* call self-refresh resume code if needed */ |
286 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
287 | tst #SUSP_SH_SF, r0 | ||
156 | bt skip_restore_sf | 288 | bt skip_restore_sf |
157 | 289 | ||
158 | #ifdef CONFIG_CPU_SUBTYPE_SH7724 | 290 | mov.l @(SH_SLEEP_SF_POST, r5), r0 |
159 | /* DBSC: put memory in auto-refresh mode */ | 291 | jsr @r0 |
160 | mov.l dbrfpdn0_reg, k4 | 292 | nop |
161 | mov.l dbrfpdn0_data0, k1 | 293 | |
162 | mov.l k1, @k4 | ||
163 | |||
164 | nop /* sleep 140 ns */ | ||
165 | nop | ||
166 | nop | ||
167 | nop | ||
168 | |||
169 | mov.l dbcmdcnt_reg, k4 | ||
170 | mov.l dbcmdcnt_data0, k1 | ||
171 | mov.l k1, @k4 | ||
172 | |||
173 | mov.l dbcmdcnt_reg, k4 | ||
174 | mov.l dbcmdcnt_data1, k1 | ||
175 | mov.l k1, @k4 | ||
176 | |||
177 | mov.l dben_reg, k4 | ||
178 | mov.l dben_data1, k1 | ||
179 | mov.l k1, @k4 | ||
180 | |||
181 | mov.l dbrfpdn0_reg, k4 | ||
182 | mov.l dbrfpdn0_data2, k1 | ||
183 | mov.l k1, @k4 | ||
184 | #else | ||
185 | /* SBSC: set auto-refresh mode */ | ||
186 | mov.l 1f, k4 | ||
187 | mov.l @k4, k0 | ||
188 | mov.l 4f, k1 | ||
189 | and k1, k0 | ||
190 | mov.l k0, @k4 | ||
191 | mov.l 6f, k4 | ||
192 | mov.l 8f, k0 | ||
193 | mov.l @k4, k1 | ||
194 | mov #-1, k4 | ||
195 | add k4, k1 | ||
196 | or k1, k0 | ||
197 | mov.l 7f, k1 | ||
198 | mov.l k0, @k1 | ||
199 | #endif | ||
200 | skip_restore_sf: | 294 | skip_restore_sf: |
201 | /* jump to vbr vector */ | 295 | /* restore mmu and cache state if needed */ |
202 | mov.l saved_vbr, k0 | 296 | mov.l @(SH_SLEEP_MODE, r5), r0 |
203 | mov.l offset_vbr, k4 | 297 | tst #SUSP_SH_MMU, r0 |
204 | add k4, k0 | 298 | bt skip_restore_mmu |
205 | jmp @k0 | 299 | |
300 | /* restore mmu state */ | ||
301 | bsr restore_register | ||
302 | mov #SH_SLEEP_REG_PTEH, r0 | ||
303 | |||
304 | bsr restore_register | ||
305 | mov #SH_SLEEP_REG_PTEL, r0 | ||
306 | |||
307 | bsr restore_register | ||
308 | mov #SH_SLEEP_REG_TTB, r0 | ||
309 | |||
310 | bsr restore_register | ||
311 | mov #SH_SLEEP_REG_TEA, r0 | ||
312 | |||
313 | bsr restore_register | ||
314 | mov #SH_SLEEP_REG_PTEA, r0 | ||
315 | |||
316 | bsr restore_register | ||
317 | mov #SH_SLEEP_REG_PASCR, r0 | ||
318 | |||
319 | bsr restore_register | ||
320 | mov #SH_SLEEP_REG_IRMCR, r0 | ||
321 | |||
322 | bsr restore_register | ||
323 | mov #SH_SLEEP_REG_MMUCR, r0 | ||
324 | icbi @r0 | ||
325 | |||
326 | /* restore cache settings */ | ||
327 | bsr restore_register | ||
328 | mov #SH_SLEEP_REG_RAMCR, r0 | ||
329 | icbi @r0 | ||
330 | |||
331 | bsr restore_register | ||
332 | mov #SH_SLEEP_REG_CCR, r0 | ||
333 | icbi @r0 | ||
334 | |||
335 | skip_restore_mmu: | ||
336 | |||
337 | /* restore general purpose registers if needed */ | ||
338 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
339 | tst #SUSP_SH_REGS, r0 | ||
340 | bt skip_restore_regs | ||
341 | |||
342 | /* switch to bank 1, restore low registers */ | ||
343 | mov.l _rb_bit, r10 | ||
344 | bsr _set_sr | ||
345 | mov #-1, r9 | ||
346 | |||
347 | bsr restore_low_regs | ||
206 | nop | 348 | nop |
207 | 349 | ||
208 | .balign 4 | 350 | /* switch to bank0, restore low registers */ |
209 | saved_mode: .long 0 | 351 | mov.l _rb_bit, r9 |
210 | saved_spc: .long 0 | 352 | not r9, r9 |
211 | saved_sr: .long 0 | 353 | bsr _set_sr |
212 | saved_vbr: .long 0 | 354 | mov #0, r10 |
213 | offset_vbr: .long 0x600 | 355 | |
214 | #ifdef CONFIG_CPU_SUBTYPE_SH7724 | 356 | bsr restore_low_regs |
215 | dben_reg: .long 0xfd000010 /* DBEN */ | ||
216 | dben_data0: .long 0 | ||
217 | dben_data1: .long 1 | ||
218 | dbrfpdn0_reg: .long 0xfd000040 /* DBRFPDN0 */ | ||
219 | dbrfpdn0_data0: .long 0 | ||
220 | dbrfpdn0_data1: .long 1 | ||
221 | dbrfpdn0_data2: .long 0x00010000 | ||
222 | dbcmdcnt_reg: .long 0xfd000014 /* DBCMDCNT */ | ||
223 | dbcmdcnt_data0: .long 2 | ||
224 | dbcmdcnt_data1: .long 4 | ||
225 | #else | ||
226 | 1: .long 0xfe400008 /* SDCR0 */ | ||
227 | 2: .long 0x00000400 | ||
228 | 3: .long 0xffff7fff | ||
229 | 4: .long 0xfffffbff | ||
230 | #endif | ||
231 | 5: .long 0xa4150020 /* STBCR */ | ||
232 | 6: .long 0xfe40001c /* RTCOR */ | ||
233 | 7: .long 0xfe400018 /* RTCNT */ | ||
234 | 8: .long 0xa55a0000 | ||
235 | |||
236 | |||
237 | /* interrupt vector @ 0x600 */ | ||
238 | .balign 0x400,0,0x400 | ||
239 | .long 0xdeadbeef | ||
240 | .balign 0x200,0,0x200 | ||
241 | bra restore_jump_vbr | ||
242 | nop | 357 | nop |
243 | sh_mobile_standby_end: | ||
244 | 358 | ||
245 | ENTRY(sh_mobile_standby_size) | 359 | /* restore the rest of the registers */ |
246 | .long sh_mobile_standby_end - sh_mobile_standby | 360 | mov.l @r15+, r8 |
361 | mov.l @r15+, r9 | ||
362 | mov.l @r15+, r10 | ||
363 | mov.l @r15+, r11 | ||
364 | mov.l @r15+, r12 | ||
365 | mov.l @r15+, r13 | ||
366 | mov.l @r15+, r14 | ||
367 | lds.l @r15+, pr | ||
368 | |||
369 | skip_restore_regs: | ||
370 | rte | ||
371 | nop | ||
372 | |||
373 | restore_register: | ||
374 | add #SH_SLEEP_BASE_DATA, r0 | ||
375 | mov.l @(r0, r5), r1 | ||
376 | add #-SH_SLEEP_BASE_DATA, r0 | ||
377 | add #SH_SLEEP_BASE_ADDR, r0 | ||
378 | mov.l @(r0, r5), r0 | ||
379 | mov.l r1, @r0 | ||
380 | rts | ||
381 | nop | ||
382 | |||
383 | _set_sr: | ||
384 | stc sr, r8 | ||
385 | and r9, r8 | ||
386 | or r10, r8 | ||
387 | ldc r8, sr | ||
388 | rts | ||
389 | nop | ||
390 | |||
391 | restore_low_regs: | ||
392 | mov.l @r15+, r0 | ||
393 | mov.l @r15+, r1 | ||
394 | mov.l @r15+, r2 | ||
395 | mov.l @r15+, r3 | ||
396 | mov.l @r15+, r4 | ||
397 | mov.l @r15+, r5 | ||
398 | mov.l @r15+, r6 | ||
399 | rts | ||
400 | mov.l @r15+, r7 | ||
401 | |||
402 | .balign 4 | ||
403 | _rb_bit: .long 0x20000000 ! RB=1 | ||
404 | 1: .long ~0x7ff | ||
405 | ENTRY(sh_mobile_sleep_resume_end) | ||
diff --git a/arch/sh/kernel/cpu/ubc.S b/arch/sh/kernel/cpu/ubc.S deleted file mode 100644 index 81923079fa12..000000000000 --- a/arch/sh/kernel/cpu/ubc.S +++ /dev/null | |||
@@ -1,59 +0,0 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpu/ubc.S | ||
3 | * | ||
4 | * Set of management routines for the User Break Controller (UBC) | ||
5 | * | ||
6 | * Copyright (C) 2002 Paul Mundt | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | #include <linux/linkage.h> | ||
14 | #include <asm/ubc.h> | ||
15 | |||
16 | #define STBCR2 0xffc00010 | ||
17 | |||
18 | ENTRY(ubc_sleep) | ||
19 | mov #0, r0 | ||
20 | |||
21 | mov.l 1f, r1 ! Zero out UBC_BBRA .. | ||
22 | mov.w r0, @r1 | ||
23 | |||
24 | mov.l 2f, r1 ! .. same for BBRB .. | ||
25 | mov.w r0, @r1 | ||
26 | |||
27 | mov.l 3f, r1 ! .. and again for BRCR. | ||
28 | mov.w r0, @r1 | ||
29 | |||
30 | mov.w @r1, r0 ! Dummy read BRCR | ||
31 | |||
32 | mov.l 4f, r1 ! Set MSTP5 in STBCR2 | ||
33 | mov.b @r1, r0 | ||
34 | or #0x01, r0 | ||
35 | mov.b r0, @r1 | ||
36 | |||
37 | mov.b @r1, r0 ! Two dummy reads .. | ||
38 | mov.b @r1, r0 | ||
39 | |||
40 | rts | ||
41 | nop | ||
42 | |||
43 | ENTRY(ubc_wakeup) | ||
44 | mov.l 4f, r1 ! Clear MSTP5 | ||
45 | mov.b @r1, r0 | ||
46 | and #0xfe, r0 | ||
47 | mov.b r0, @r1 | ||
48 | |||
49 | mov.b @r1, r0 ! Two more dummy reads .. | ||
50 | mov.b @r1, r0 | ||
51 | |||
52 | rts | ||
53 | nop | ||
54 | |||
55 | 1: .long UBC_BBRA | ||
56 | 2: .long UBC_BBRB | ||
57 | 3: .long UBC_BRCR | ||
58 | 4: .long STBCR2 | ||
59 | |||
diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c index dce4f3ff0932..0fffacea6ed9 100644 --- a/arch/sh/kernel/cpufreq.c +++ b/arch/sh/kernel/cpufreq.c | |||
@@ -48,7 +48,7 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy, | |||
48 | return -ENODEV; | 48 | return -ENODEV; |
49 | 49 | ||
50 | cpus_allowed = current->cpus_allowed; | 50 | cpus_allowed = current->cpus_allowed; |
51 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | 51 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); |
52 | 52 | ||
53 | BUG_ON(smp_processor_id() != cpu); | 53 | BUG_ON(smp_processor_id() != cpu); |
54 | 54 | ||
@@ -66,7 +66,7 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy, | |||
66 | freqs.flags = 0; | 66 | freqs.flags = 0; |
67 | 67 | ||
68 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 68 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); |
69 | set_cpus_allowed(current, cpus_allowed); | 69 | set_cpus_allowed_ptr(current, &cpus_allowed); |
70 | clk_set_rate(cpuclk, freq); | 70 | clk_set_rate(cpuclk, freq); |
71 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 71 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |
72 | 72 | ||
diff --git a/arch/sh/kernel/debugtraps.S b/arch/sh/kernel/debugtraps.S index 591741383ee6..7a1b46fec0f4 100644 --- a/arch/sh/kernel/debugtraps.S +++ b/arch/sh/kernel/debugtraps.S | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | 14 | ||
15 | #if !defined(CONFIG_KGDB) | 15 | #if !defined(CONFIG_KGDB) |
16 | #define breakpoint_trap_handler debug_trap_handler | ||
17 | #define singlestep_trap_handler debug_trap_handler | 16 | #define singlestep_trap_handler debug_trap_handler |
18 | #endif | 17 | #endif |
19 | 18 | ||
diff --git a/arch/sh/kernel/dma-nommu.c b/arch/sh/kernel/dma-nommu.c new file mode 100644 index 000000000000..3c55b87f8b63 --- /dev/null +++ b/arch/sh/kernel/dma-nommu.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * DMA mapping support for platforms lacking IOMMUs. | ||
3 | * | ||
4 | * Copyright (C) 2009 Paul Mundt | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | #include <linux/dma-mapping.h> | ||
11 | #include <linux/io.h> | ||
12 | |||
13 | static dma_addr_t nommu_map_page(struct device *dev, struct page *page, | ||
14 | unsigned long offset, size_t size, | ||
15 | enum dma_data_direction dir, | ||
16 | struct dma_attrs *attrs) | ||
17 | { | ||
18 | dma_addr_t addr = page_to_phys(page) + offset; | ||
19 | |||
20 | WARN_ON(size == 0); | ||
21 | dma_cache_sync(dev, page_address(page) + offset, size, dir); | ||
22 | |||
23 | return addr; | ||
24 | } | ||
25 | |||
26 | static int nommu_map_sg(struct device *dev, struct scatterlist *sg, | ||
27 | int nents, enum dma_data_direction dir, | ||
28 | struct dma_attrs *attrs) | ||
29 | { | ||
30 | struct scatterlist *s; | ||
31 | int i; | ||
32 | |||
33 | WARN_ON(nents == 0 || sg[0].length == 0); | ||
34 | |||
35 | for_each_sg(sg, s, nents, i) { | ||
36 | BUG_ON(!sg_page(s)); | ||
37 | |||
38 | dma_cache_sync(dev, sg_virt(s), s->length, dir); | ||
39 | |||
40 | s->dma_address = sg_phys(s); | ||
41 | s->dma_length = s->length; | ||
42 | } | ||
43 | |||
44 | return nents; | ||
45 | } | ||
46 | |||
47 | #ifdef CONFIG_DMA_NONCOHERENT | ||
48 | static void nommu_sync_single(struct device *dev, dma_addr_t addr, | ||
49 | size_t size, enum dma_data_direction dir) | ||
50 | { | ||
51 | dma_cache_sync(dev, phys_to_virt(addr), size, dir); | ||
52 | } | ||
53 | |||
54 | static void nommu_sync_sg(struct device *dev, struct scatterlist *sg, | ||
55 | int nelems, enum dma_data_direction dir) | ||
56 | { | ||
57 | struct scatterlist *s; | ||
58 | int i; | ||
59 | |||
60 | for_each_sg(sg, s, nelems, i) | ||
61 | dma_cache_sync(dev, sg_virt(s), s->length, dir); | ||
62 | } | ||
63 | #endif | ||
64 | |||
65 | struct dma_map_ops nommu_dma_ops = { | ||
66 | .alloc_coherent = dma_generic_alloc_coherent, | ||
67 | .free_coherent = dma_generic_free_coherent, | ||
68 | .map_page = nommu_map_page, | ||
69 | .map_sg = nommu_map_sg, | ||
70 | #ifdef CONFIG_DMA_NONCOHERENT | ||
71 | .sync_single_for_device = nommu_sync_single, | ||
72 | .sync_sg_for_device = nommu_sync_sg, | ||
73 | #endif | ||
74 | .is_phys = 1, | ||
75 | }; | ||
76 | |||
77 | void __init no_iommu_init(void) | ||
78 | { | ||
79 | if (dma_ops) | ||
80 | return; | ||
81 | dma_ops = &nommu_dma_ops; | ||
82 | } | ||
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c index d76a23170dbb..a8234b2010d1 100644 --- a/arch/sh/kernel/dwarf.c +++ b/arch/sh/kernel/dwarf.c | |||
@@ -20,7 +20,9 @@ | |||
20 | #include <linux/list.h> | 20 | #include <linux/list.h> |
21 | #include <linux/mempool.h> | 21 | #include <linux/mempool.h> |
22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
23 | #include <linux/elf.h> | ||
23 | #include <linux/ftrace.h> | 24 | #include <linux/ftrace.h> |
25 | #include <linux/slab.h> | ||
24 | #include <asm/dwarf.h> | 26 | #include <asm/dwarf.h> |
25 | #include <asm/unwinder.h> | 27 | #include <asm/unwinder.h> |
26 | #include <asm/sections.h> | 28 | #include <asm/sections.h> |
@@ -38,10 +40,10 @@ static mempool_t *dwarf_frame_pool; | |||
38 | static struct kmem_cache *dwarf_reg_cachep; | 40 | static struct kmem_cache *dwarf_reg_cachep; |
39 | static mempool_t *dwarf_reg_pool; | 41 | static mempool_t *dwarf_reg_pool; |
40 | 42 | ||
41 | static LIST_HEAD(dwarf_cie_list); | 43 | static struct rb_root cie_root; |
42 | static DEFINE_SPINLOCK(dwarf_cie_lock); | 44 | static DEFINE_SPINLOCK(dwarf_cie_lock); |
43 | 45 | ||
44 | static LIST_HEAD(dwarf_fde_list); | 46 | static struct rb_root fde_root; |
45 | static DEFINE_SPINLOCK(dwarf_fde_lock); | 47 | static DEFINE_SPINLOCK(dwarf_fde_lock); |
46 | 48 | ||
47 | static struct dwarf_cie *cached_cie; | 49 | static struct dwarf_cie *cached_cie; |
@@ -300,7 +302,8 @@ static inline int dwarf_entry_len(char *addr, unsigned long *len) | |||
300 | */ | 302 | */ |
301 | static struct dwarf_cie *dwarf_lookup_cie(unsigned long cie_ptr) | 303 | static struct dwarf_cie *dwarf_lookup_cie(unsigned long cie_ptr) |
302 | { | 304 | { |
303 | struct dwarf_cie *cie; | 305 | struct rb_node **rb_node = &cie_root.rb_node; |
306 | struct dwarf_cie *cie = NULL; | ||
304 | unsigned long flags; | 307 | unsigned long flags; |
305 | 308 | ||
306 | spin_lock_irqsave(&dwarf_cie_lock, flags); | 309 | spin_lock_irqsave(&dwarf_cie_lock, flags); |
@@ -314,16 +317,24 @@ static struct dwarf_cie *dwarf_lookup_cie(unsigned long cie_ptr) | |||
314 | goto out; | 317 | goto out; |
315 | } | 318 | } |
316 | 319 | ||
317 | list_for_each_entry(cie, &dwarf_cie_list, link) { | 320 | while (*rb_node) { |
318 | if (cie->cie_pointer == cie_ptr) { | 321 | struct dwarf_cie *cie_tmp; |
319 | cached_cie = cie; | 322 | |
320 | break; | 323 | cie_tmp = rb_entry(*rb_node, struct dwarf_cie, node); |
324 | BUG_ON(!cie_tmp); | ||
325 | |||
326 | if (cie_ptr == cie_tmp->cie_pointer) { | ||
327 | cie = cie_tmp; | ||
328 | cached_cie = cie_tmp; | ||
329 | goto out; | ||
330 | } else { | ||
331 | if (cie_ptr < cie_tmp->cie_pointer) | ||
332 | rb_node = &(*rb_node)->rb_left; | ||
333 | else | ||
334 | rb_node = &(*rb_node)->rb_right; | ||
321 | } | 335 | } |
322 | } | 336 | } |
323 | 337 | ||
324 | /* Couldn't find the entry in the list. */ | ||
325 | if (&cie->link == &dwarf_cie_list) | ||
326 | cie = NULL; | ||
327 | out: | 338 | out: |
328 | spin_unlock_irqrestore(&dwarf_cie_lock, flags); | 339 | spin_unlock_irqrestore(&dwarf_cie_lock, flags); |
329 | return cie; | 340 | return cie; |
@@ -335,25 +346,34 @@ out: | |||
335 | */ | 346 | */ |
336 | struct dwarf_fde *dwarf_lookup_fde(unsigned long pc) | 347 | struct dwarf_fde *dwarf_lookup_fde(unsigned long pc) |
337 | { | 348 | { |
338 | struct dwarf_fde *fde; | 349 | struct rb_node **rb_node = &fde_root.rb_node; |
350 | struct dwarf_fde *fde = NULL; | ||
339 | unsigned long flags; | 351 | unsigned long flags; |
340 | 352 | ||
341 | spin_lock_irqsave(&dwarf_fde_lock, flags); | 353 | spin_lock_irqsave(&dwarf_fde_lock, flags); |
342 | 354 | ||
343 | list_for_each_entry(fde, &dwarf_fde_list, link) { | 355 | while (*rb_node) { |
344 | unsigned long start, end; | 356 | struct dwarf_fde *fde_tmp; |
357 | unsigned long tmp_start, tmp_end; | ||
345 | 358 | ||
346 | start = fde->initial_location; | 359 | fde_tmp = rb_entry(*rb_node, struct dwarf_fde, node); |
347 | end = fde->initial_location + fde->address_range; | 360 | BUG_ON(!fde_tmp); |
348 | 361 | ||
349 | if (pc >= start && pc < end) | 362 | tmp_start = fde_tmp->initial_location; |
350 | break; | 363 | tmp_end = fde_tmp->initial_location + fde_tmp->address_range; |
351 | } | ||
352 | 364 | ||
353 | /* Couldn't find the entry in the list. */ | 365 | if (pc < tmp_start) { |
354 | if (&fde->link == &dwarf_fde_list) | 366 | rb_node = &(*rb_node)->rb_left; |
355 | fde = NULL; | 367 | } else { |
368 | if (pc < tmp_end) { | ||
369 | fde = fde_tmp; | ||
370 | goto out; | ||
371 | } else | ||
372 | rb_node = &(*rb_node)->rb_right; | ||
373 | } | ||
374 | } | ||
356 | 375 | ||
376 | out: | ||
357 | spin_unlock_irqrestore(&dwarf_fde_lock, flags); | 377 | spin_unlock_irqrestore(&dwarf_fde_lock, flags); |
358 | 378 | ||
359 | return fde; | 379 | return fde; |
@@ -530,7 +550,20 @@ static int dwarf_cfa_execute_insns(unsigned char *insn_start, | |||
530 | } | 550 | } |
531 | 551 | ||
532 | /** | 552 | /** |
533 | * dwarf_unwind_stack - recursively unwind the stack | 553 | * dwarf_free_frame - free the memory allocated for @frame |
554 | * @frame: the frame to free | ||
555 | */ | ||
556 | void dwarf_free_frame(struct dwarf_frame *frame) | ||
557 | { | ||
558 | dwarf_frame_free_regs(frame); | ||
559 | mempool_free(frame, dwarf_frame_pool); | ||
560 | } | ||
561 | |||
562 | extern void ret_from_irq(void); | ||
563 | |||
564 | /** | ||
565 | * dwarf_unwind_stack - unwind the stack | ||
566 | * | ||
534 | * @pc: address of the function to unwind | 567 | * @pc: address of the function to unwind |
535 | * @prev: struct dwarf_frame of the previous stackframe on the callstack | 568 | * @prev: struct dwarf_frame of the previous stackframe on the callstack |
536 | * | 569 | * |
@@ -538,8 +571,8 @@ static int dwarf_cfa_execute_insns(unsigned char *insn_start, | |||
538 | * on the callstack. Each of the lower (older) stack frames are | 571 | * on the callstack. Each of the lower (older) stack frames are |
539 | * linked via the "prev" member. | 572 | * linked via the "prev" member. |
540 | */ | 573 | */ |
541 | struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, | 574 | struct dwarf_frame *dwarf_unwind_stack(unsigned long pc, |
542 | struct dwarf_frame *prev) | 575 | struct dwarf_frame *prev) |
543 | { | 576 | { |
544 | struct dwarf_frame *frame; | 577 | struct dwarf_frame *frame; |
545 | struct dwarf_cie *cie; | 578 | struct dwarf_cie *cie; |
@@ -548,9 +581,9 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, | |||
548 | unsigned long addr; | 581 | unsigned long addr; |
549 | 582 | ||
550 | /* | 583 | /* |
551 | * If this is the first invocation of this recursive function we | 584 | * If we're starting at the top of the stack we need get the |
552 | * need get the contents of a physical register to get the CFA | 585 | * contents of a physical register to get the CFA in order to |
553 | * in order to begin the virtual unwinding of the stack. | 586 | * begin the virtual unwinding of the stack. |
554 | * | 587 | * |
555 | * NOTE: the return address is guaranteed to be setup by the | 588 | * NOTE: the return address is guaranteed to be setup by the |
556 | * time this function makes its first function call. | 589 | * time this function makes its first function call. |
@@ -593,9 +626,8 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, | |||
593 | fde = dwarf_lookup_fde(pc); | 626 | fde = dwarf_lookup_fde(pc); |
594 | if (!fde) { | 627 | if (!fde) { |
595 | /* | 628 | /* |
596 | * This is our normal exit path - the one that stops the | 629 | * This is our normal exit path. There are two reasons |
597 | * recursion. There's two reasons why we might exit | 630 | * why we might exit here, |
598 | * here, | ||
599 | * | 631 | * |
600 | * a) pc has no asscociated DWARF frame info and so | 632 | * a) pc has no asscociated DWARF frame info and so |
601 | * we don't know how to unwind this frame. This is | 633 | * we don't know how to unwind this frame. This is |
@@ -637,10 +669,10 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, | |||
637 | 669 | ||
638 | } else { | 670 | } else { |
639 | /* | 671 | /* |
640 | * Again, this is the first invocation of this | 672 | * Again, we're starting from the top of the |
641 | * recurisve function. We need to physically | 673 | * stack. We need to physically read |
642 | * read the contents of a register in order to | 674 | * the contents of a register in order to get |
643 | * get the Canonical Frame Address for this | 675 | * the Canonical Frame Address for this |
644 | * function. | 676 | * function. |
645 | */ | 677 | */ |
646 | frame->cfa = dwarf_read_arch_reg(frame->cfa_register); | 678 | frame->cfa = dwarf_read_arch_reg(frame->cfa_register); |
@@ -667,17 +699,36 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, | |||
667 | addr = frame->cfa + reg->addr; | 699 | addr = frame->cfa + reg->addr; |
668 | frame->return_addr = __raw_readl(addr); | 700 | frame->return_addr = __raw_readl(addr); |
669 | 701 | ||
702 | /* | ||
703 | * Ah, the joys of unwinding through interrupts. | ||
704 | * | ||
705 | * Interrupts are tricky - the DWARF info needs to be _really_ | ||
706 | * accurate and unfortunately I'm seeing a lot of bogus DWARF | ||
707 | * info. For example, I've seen interrupts occur in epilogues | ||
708 | * just after the frame pointer (r14) had been restored. The | ||
709 | * problem was that the DWARF info claimed that the CFA could be | ||
710 | * reached by using the value of the frame pointer before it was | ||
711 | * restored. | ||
712 | * | ||
713 | * So until the compiler can be trusted to produce reliable | ||
714 | * DWARF info when it really matters, let's stop unwinding once | ||
715 | * we've calculated the function that was interrupted. | ||
716 | */ | ||
717 | if (prev && prev->pc == (unsigned long)ret_from_irq) | ||
718 | frame->return_addr = 0; | ||
719 | |||
670 | return frame; | 720 | return frame; |
671 | 721 | ||
672 | bail: | 722 | bail: |
673 | dwarf_frame_free_regs(frame); | 723 | dwarf_free_frame(frame); |
674 | mempool_free(frame, dwarf_frame_pool); | ||
675 | return NULL; | 724 | return NULL; |
676 | } | 725 | } |
677 | 726 | ||
678 | static int dwarf_parse_cie(void *entry, void *p, unsigned long len, | 727 | static int dwarf_parse_cie(void *entry, void *p, unsigned long len, |
679 | unsigned char *end) | 728 | unsigned char *end, struct module *mod) |
680 | { | 729 | { |
730 | struct rb_node **rb_node = &cie_root.rb_node; | ||
731 | struct rb_node *parent = *rb_node; | ||
681 | struct dwarf_cie *cie; | 732 | struct dwarf_cie *cie; |
682 | unsigned long flags; | 733 | unsigned long flags; |
683 | int count; | 734 | int count; |
@@ -774,7 +825,28 @@ static int dwarf_parse_cie(void *entry, void *p, unsigned long len, | |||
774 | 825 | ||
775 | /* Add to list */ | 826 | /* Add to list */ |
776 | spin_lock_irqsave(&dwarf_cie_lock, flags); | 827 | spin_lock_irqsave(&dwarf_cie_lock, flags); |
777 | list_add_tail(&cie->link, &dwarf_cie_list); | 828 | |
829 | while (*rb_node) { | ||
830 | struct dwarf_cie *cie_tmp; | ||
831 | |||
832 | cie_tmp = rb_entry(*rb_node, struct dwarf_cie, node); | ||
833 | |||
834 | parent = *rb_node; | ||
835 | |||
836 | if (cie->cie_pointer < cie_tmp->cie_pointer) | ||
837 | rb_node = &parent->rb_left; | ||
838 | else if (cie->cie_pointer >= cie_tmp->cie_pointer) | ||
839 | rb_node = &parent->rb_right; | ||
840 | else | ||
841 | WARN_ON(1); | ||
842 | } | ||
843 | |||
844 | rb_link_node(&cie->node, parent, rb_node); | ||
845 | rb_insert_color(&cie->node, &cie_root); | ||
846 | |||
847 | if (mod != NULL) | ||
848 | list_add_tail(&cie->link, &mod->arch.cie_list); | ||
849 | |||
778 | spin_unlock_irqrestore(&dwarf_cie_lock, flags); | 850 | spin_unlock_irqrestore(&dwarf_cie_lock, flags); |
779 | 851 | ||
780 | return 0; | 852 | return 0; |
@@ -782,8 +854,10 @@ static int dwarf_parse_cie(void *entry, void *p, unsigned long len, | |||
782 | 854 | ||
783 | static int dwarf_parse_fde(void *entry, u32 entry_type, | 855 | static int dwarf_parse_fde(void *entry, u32 entry_type, |
784 | void *start, unsigned long len, | 856 | void *start, unsigned long len, |
785 | unsigned char *end) | 857 | unsigned char *end, struct module *mod) |
786 | { | 858 | { |
859 | struct rb_node **rb_node = &fde_root.rb_node; | ||
860 | struct rb_node *parent = *rb_node; | ||
787 | struct dwarf_fde *fde; | 861 | struct dwarf_fde *fde; |
788 | struct dwarf_cie *cie; | 862 | struct dwarf_cie *cie; |
789 | unsigned long flags; | 863 | unsigned long flags; |
@@ -833,7 +907,36 @@ static int dwarf_parse_fde(void *entry, u32 entry_type, | |||
833 | 907 | ||
834 | /* Add to list. */ | 908 | /* Add to list. */ |
835 | spin_lock_irqsave(&dwarf_fde_lock, flags); | 909 | spin_lock_irqsave(&dwarf_fde_lock, flags); |
836 | list_add_tail(&fde->link, &dwarf_fde_list); | 910 | |
911 | while (*rb_node) { | ||
912 | struct dwarf_fde *fde_tmp; | ||
913 | unsigned long tmp_start, tmp_end; | ||
914 | unsigned long start, end; | ||
915 | |||
916 | fde_tmp = rb_entry(*rb_node, struct dwarf_fde, node); | ||
917 | |||
918 | start = fde->initial_location; | ||
919 | end = fde->initial_location + fde->address_range; | ||
920 | |||
921 | tmp_start = fde_tmp->initial_location; | ||
922 | tmp_end = fde_tmp->initial_location + fde_tmp->address_range; | ||
923 | |||
924 | parent = *rb_node; | ||
925 | |||
926 | if (start < tmp_start) | ||
927 | rb_node = &parent->rb_left; | ||
928 | else if (start >= tmp_end) | ||
929 | rb_node = &parent->rb_right; | ||
930 | else | ||
931 | WARN_ON(1); | ||
932 | } | ||
933 | |||
934 | rb_link_node(&fde->node, parent, rb_node); | ||
935 | rb_insert_color(&fde->node, &fde_root); | ||
936 | |||
937 | if (mod != NULL) | ||
938 | list_add_tail(&fde->link, &mod->arch.fde_list); | ||
939 | |||
837 | spin_unlock_irqrestore(&dwarf_fde_lock, flags); | 940 | spin_unlock_irqrestore(&dwarf_fde_lock, flags); |
838 | 941 | ||
839 | return 0; | 942 | return 0; |
@@ -854,10 +957,8 @@ static void dwarf_unwinder_dump(struct task_struct *task, | |||
854 | while (1) { | 957 | while (1) { |
855 | frame = dwarf_unwind_stack(return_addr, _frame); | 958 | frame = dwarf_unwind_stack(return_addr, _frame); |
856 | 959 | ||
857 | if (_frame) { | 960 | if (_frame) |
858 | dwarf_frame_free_regs(_frame); | 961 | dwarf_free_frame(_frame); |
859 | mempool_free(_frame, dwarf_frame_pool); | ||
860 | } | ||
861 | 962 | ||
862 | _frame = frame; | 963 | _frame = frame; |
863 | 964 | ||
@@ -867,6 +968,9 @@ static void dwarf_unwinder_dump(struct task_struct *task, | |||
867 | return_addr = frame->return_addr; | 968 | return_addr = frame->return_addr; |
868 | ops->address(data, return_addr, 1); | 969 | ops->address(data, return_addr, 1); |
869 | } | 970 | } |
971 | |||
972 | if (frame) | ||
973 | dwarf_free_frame(frame); | ||
870 | } | 974 | } |
871 | 975 | ||
872 | static struct unwinder dwarf_unwinder = { | 976 | static struct unwinder dwarf_unwinder = { |
@@ -877,67 +981,57 @@ static struct unwinder dwarf_unwinder = { | |||
877 | 981 | ||
878 | static void dwarf_unwinder_cleanup(void) | 982 | static void dwarf_unwinder_cleanup(void) |
879 | { | 983 | { |
880 | struct dwarf_cie *cie; | 984 | struct rb_node **fde_rb_node = &fde_root.rb_node; |
881 | struct dwarf_fde *fde; | 985 | struct rb_node **cie_rb_node = &cie_root.rb_node; |
882 | 986 | ||
883 | /* | 987 | /* |
884 | * Deallocate all the memory allocated for the DWARF unwinder. | 988 | * Deallocate all the memory allocated for the DWARF unwinder. |
885 | * Traverse all the FDE/CIE lists and remove and free all the | 989 | * Traverse all the FDE/CIE lists and remove and free all the |
886 | * memory associated with those data structures. | 990 | * memory associated with those data structures. |
887 | */ | 991 | */ |
888 | list_for_each_entry(cie, &dwarf_cie_list, link) | 992 | while (*fde_rb_node) { |
889 | kfree(cie); | 993 | struct dwarf_fde *fde; |
890 | 994 | ||
891 | list_for_each_entry(fde, &dwarf_fde_list, link) | 995 | fde = rb_entry(*fde_rb_node, struct dwarf_fde, node); |
996 | rb_erase(*fde_rb_node, &fde_root); | ||
892 | kfree(fde); | 997 | kfree(fde); |
998 | } | ||
999 | |||
1000 | while (*cie_rb_node) { | ||
1001 | struct dwarf_cie *cie; | ||
1002 | |||
1003 | cie = rb_entry(*cie_rb_node, struct dwarf_cie, node); | ||
1004 | rb_erase(*cie_rb_node, &cie_root); | ||
1005 | kfree(cie); | ||
1006 | } | ||
893 | 1007 | ||
894 | kmem_cache_destroy(dwarf_reg_cachep); | 1008 | kmem_cache_destroy(dwarf_reg_cachep); |
895 | kmem_cache_destroy(dwarf_frame_cachep); | 1009 | kmem_cache_destroy(dwarf_frame_cachep); |
896 | } | 1010 | } |
897 | 1011 | ||
898 | /** | 1012 | /** |
899 | * dwarf_unwinder_init - initialise the dwarf unwinder | 1013 | * dwarf_parse_section - parse DWARF section |
1014 | * @eh_frame_start: start address of the .eh_frame section | ||
1015 | * @eh_frame_end: end address of the .eh_frame section | ||
1016 | * @mod: the kernel module containing the .eh_frame section | ||
900 | * | 1017 | * |
901 | * Build the data structures describing the .dwarf_frame section to | 1018 | * Parse the information in a .eh_frame section. |
902 | * make it easier to lookup CIE and FDE entries. Because the | ||
903 | * .eh_frame section is packed as tightly as possible it is not | ||
904 | * easy to lookup the FDE for a given PC, so we build a list of FDE | ||
905 | * and CIE entries that make it easier. | ||
906 | */ | 1019 | */ |
907 | static int __init dwarf_unwinder_init(void) | 1020 | static int dwarf_parse_section(char *eh_frame_start, char *eh_frame_end, |
1021 | struct module *mod) | ||
908 | { | 1022 | { |
909 | u32 entry_type; | 1023 | u32 entry_type; |
910 | void *p, *entry; | 1024 | void *p, *entry; |
911 | int count, err = 0; | 1025 | int count, err = 0; |
912 | unsigned long len; | 1026 | unsigned long len = 0; |
913 | unsigned int c_entries, f_entries; | 1027 | unsigned int c_entries, f_entries; |
914 | unsigned char *end; | 1028 | unsigned char *end; |
915 | INIT_LIST_HEAD(&dwarf_cie_list); | ||
916 | INIT_LIST_HEAD(&dwarf_fde_list); | ||
917 | 1029 | ||
918 | c_entries = 0; | 1030 | c_entries = 0; |
919 | f_entries = 0; | 1031 | f_entries = 0; |
920 | entry = &__start_eh_frame; | 1032 | entry = eh_frame_start; |
921 | |||
922 | dwarf_frame_cachep = kmem_cache_create("dwarf_frames", | ||
923 | sizeof(struct dwarf_frame), 0, | ||
924 | SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL); | ||
925 | |||
926 | dwarf_reg_cachep = kmem_cache_create("dwarf_regs", | ||
927 | sizeof(struct dwarf_reg), 0, | ||
928 | SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL); | ||
929 | 1033 | ||
930 | dwarf_frame_pool = mempool_create(DWARF_FRAME_MIN_REQ, | 1034 | while ((char *)entry < eh_frame_end) { |
931 | mempool_alloc_slab, | ||
932 | mempool_free_slab, | ||
933 | dwarf_frame_cachep); | ||
934 | |||
935 | dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ, | ||
936 | mempool_alloc_slab, | ||
937 | mempool_free_slab, | ||
938 | dwarf_reg_cachep); | ||
939 | |||
940 | while ((char *)entry < __stop_eh_frame) { | ||
941 | p = entry; | 1035 | p = entry; |
942 | 1036 | ||
943 | count = dwarf_entry_len(p, &len); | 1037 | count = dwarf_entry_len(p, &len); |
@@ -949,6 +1043,7 @@ static int __init dwarf_unwinder_init(void) | |||
949 | * entry and move to the next one because 'len' | 1043 | * entry and move to the next one because 'len' |
950 | * tells us where our next entry is. | 1044 | * tells us where our next entry is. |
951 | */ | 1045 | */ |
1046 | err = -EINVAL; | ||
952 | goto out; | 1047 | goto out; |
953 | } else | 1048 | } else |
954 | p += count; | 1049 | p += count; |
@@ -960,13 +1055,14 @@ static int __init dwarf_unwinder_init(void) | |||
960 | p += 4; | 1055 | p += 4; |
961 | 1056 | ||
962 | if (entry_type == DW_EH_FRAME_CIE) { | 1057 | if (entry_type == DW_EH_FRAME_CIE) { |
963 | err = dwarf_parse_cie(entry, p, len, end); | 1058 | err = dwarf_parse_cie(entry, p, len, end, mod); |
964 | if (err < 0) | 1059 | if (err < 0) |
965 | goto out; | 1060 | goto out; |
966 | else | 1061 | else |
967 | c_entries++; | 1062 | c_entries++; |
968 | } else { | 1063 | } else { |
969 | err = dwarf_parse_fde(entry, entry_type, p, len, end); | 1064 | err = dwarf_parse_fde(entry, entry_type, p, len, |
1065 | end, mod); | ||
970 | if (err < 0) | 1066 | if (err < 0) |
971 | goto out; | 1067 | goto out; |
972 | else | 1068 | else |
@@ -979,6 +1075,117 @@ static int __init dwarf_unwinder_init(void) | |||
979 | printk(KERN_INFO "DWARF unwinder initialised: read %u CIEs, %u FDEs\n", | 1075 | printk(KERN_INFO "DWARF unwinder initialised: read %u CIEs, %u FDEs\n", |
980 | c_entries, f_entries); | 1076 | c_entries, f_entries); |
981 | 1077 | ||
1078 | return 0; | ||
1079 | |||
1080 | out: | ||
1081 | return err; | ||
1082 | } | ||
1083 | |||
1084 | #ifdef CONFIG_MODULES | ||
1085 | int module_dwarf_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, | ||
1086 | struct module *me) | ||
1087 | { | ||
1088 | unsigned int i, err; | ||
1089 | unsigned long start, end; | ||
1090 | char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
1091 | |||
1092 | start = end = 0; | ||
1093 | |||
1094 | for (i = 1; i < hdr->e_shnum; i++) { | ||
1095 | /* Alloc bit cleared means "ignore it." */ | ||
1096 | if ((sechdrs[i].sh_flags & SHF_ALLOC) | ||
1097 | && !strcmp(secstrings+sechdrs[i].sh_name, ".eh_frame")) { | ||
1098 | start = sechdrs[i].sh_addr; | ||
1099 | end = start + sechdrs[i].sh_size; | ||
1100 | break; | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1104 | /* Did we find the .eh_frame section? */ | ||
1105 | if (i != hdr->e_shnum) { | ||
1106 | INIT_LIST_HEAD(&me->arch.cie_list); | ||
1107 | INIT_LIST_HEAD(&me->arch.fde_list); | ||
1108 | err = dwarf_parse_section((char *)start, (char *)end, me); | ||
1109 | if (err) { | ||
1110 | printk(KERN_WARNING "%s: failed to parse DWARF info\n", | ||
1111 | me->name); | ||
1112 | return err; | ||
1113 | } | ||
1114 | } | ||
1115 | |||
1116 | return 0; | ||
1117 | } | ||
1118 | |||
1119 | /** | ||
1120 | * module_dwarf_cleanup - remove FDE/CIEs associated with @mod | ||
1121 | * @mod: the module that is being unloaded | ||
1122 | * | ||
1123 | * Remove any FDEs and CIEs from the global lists that came from | ||
1124 | * @mod's .eh_frame section because @mod is being unloaded. | ||
1125 | */ | ||
1126 | void module_dwarf_cleanup(struct module *mod) | ||
1127 | { | ||
1128 | struct dwarf_fde *fde, *ftmp; | ||
1129 | struct dwarf_cie *cie, *ctmp; | ||
1130 | unsigned long flags; | ||
1131 | |||
1132 | spin_lock_irqsave(&dwarf_cie_lock, flags); | ||
1133 | |||
1134 | list_for_each_entry_safe(cie, ctmp, &mod->arch.cie_list, link) { | ||
1135 | list_del(&cie->link); | ||
1136 | rb_erase(&cie->node, &cie_root); | ||
1137 | kfree(cie); | ||
1138 | } | ||
1139 | |||
1140 | spin_unlock_irqrestore(&dwarf_cie_lock, flags); | ||
1141 | |||
1142 | spin_lock_irqsave(&dwarf_fde_lock, flags); | ||
1143 | |||
1144 | list_for_each_entry_safe(fde, ftmp, &mod->arch.fde_list, link) { | ||
1145 | list_del(&fde->link); | ||
1146 | rb_erase(&fde->node, &fde_root); | ||
1147 | kfree(fde); | ||
1148 | } | ||
1149 | |||
1150 | spin_unlock_irqrestore(&dwarf_fde_lock, flags); | ||
1151 | } | ||
1152 | #endif /* CONFIG_MODULES */ | ||
1153 | |||
1154 | /** | ||
1155 | * dwarf_unwinder_init - initialise the dwarf unwinder | ||
1156 | * | ||
1157 | * Build the data structures describing the .dwarf_frame section to | ||
1158 | * make it easier to lookup CIE and FDE entries. Because the | ||
1159 | * .eh_frame section is packed as tightly as possible it is not | ||
1160 | * easy to lookup the FDE for a given PC, so we build a list of FDE | ||
1161 | * and CIE entries that make it easier. | ||
1162 | */ | ||
1163 | static int __init dwarf_unwinder_init(void) | ||
1164 | { | ||
1165 | int err; | ||
1166 | |||
1167 | dwarf_frame_cachep = kmem_cache_create("dwarf_frames", | ||
1168 | sizeof(struct dwarf_frame), 0, | ||
1169 | SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL); | ||
1170 | |||
1171 | dwarf_reg_cachep = kmem_cache_create("dwarf_regs", | ||
1172 | sizeof(struct dwarf_reg), 0, | ||
1173 | SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL); | ||
1174 | |||
1175 | dwarf_frame_pool = mempool_create(DWARF_FRAME_MIN_REQ, | ||
1176 | mempool_alloc_slab, | ||
1177 | mempool_free_slab, | ||
1178 | dwarf_frame_cachep); | ||
1179 | |||
1180 | dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ, | ||
1181 | mempool_alloc_slab, | ||
1182 | mempool_free_slab, | ||
1183 | dwarf_reg_cachep); | ||
1184 | |||
1185 | err = dwarf_parse_section(__start_eh_frame, __stop_eh_frame, NULL); | ||
1186 | if (err) | ||
1187 | goto out; | ||
1188 | |||
982 | err = unwinder_register(&dwarf_unwinder); | 1189 | err = unwinder_register(&dwarf_unwinder); |
983 | if (err) | 1190 | if (err) |
984 | goto out; | 1191 | goto out; |
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c deleted file mode 100644 index 81a46145ffa5..000000000000 --- a/arch/sh/kernel/early_printk.c +++ /dev/null | |||
@@ -1,240 +0,0 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/early_printk.c | ||
3 | * | ||
4 | * Copyright (C) 1999, 2000 Niibe Yutaka | ||
5 | * Copyright (C) 2002 M. R. Brown | ||
6 | * Copyright (C) 2004 - 2007 Paul Mundt | ||
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/console.h> | ||
13 | #include <linux/tty.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/delay.h> | ||
17 | |||
18 | #ifdef CONFIG_SH_STANDARD_BIOS | ||
19 | #include <asm/sh_bios.h> | ||
20 | |||
21 | /* | ||
22 | * Print a string through the BIOS | ||
23 | */ | ||
24 | static void sh_console_write(struct console *co, const char *s, | ||
25 | unsigned count) | ||
26 | { | ||
27 | sh_bios_console_write(s, count); | ||
28 | } | ||
29 | |||
30 | /* | ||
31 | * Setup initial baud/bits/parity. We do two things here: | ||
32 | * - construct a cflag setting for the first rs_open() | ||
33 | * - initialize the serial port | ||
34 | * Return non-zero if we didn't find a serial port. | ||
35 | */ | ||
36 | static int __init sh_console_setup(struct console *co, char *options) | ||
37 | { | ||
38 | int cflag = CREAD | HUPCL | CLOCAL; | ||
39 | |||
40 | /* | ||
41 | * Now construct a cflag setting. | ||
42 | * TODO: this is a totally bogus cflag, as we have | ||
43 | * no idea what serial settings the BIOS is using, or | ||
44 | * even if its using the serial port at all. | ||
45 | */ | ||
46 | cflag |= B115200 | CS8 | /*no parity*/0; | ||
47 | |||
48 | co->cflag = cflag; | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static struct console bios_console = { | ||
54 | .name = "bios", | ||
55 | .write = sh_console_write, | ||
56 | .setup = sh_console_setup, | ||
57 | .flags = CON_PRINTBUFFER, | ||
58 | .index = -1, | ||
59 | }; | ||
60 | #endif | ||
61 | |||
62 | #ifdef CONFIG_EARLY_SCIF_CONSOLE | ||
63 | #include <linux/serial_core.h> | ||
64 | #include "../../../drivers/serial/sh-sci.h" | ||
65 | |||
66 | #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | ||
67 | defined(CONFIG_CPU_SUBTYPE_SH7721) | ||
68 | #define EPK_SCSMR_VALUE 0x000 | ||
69 | #define EPK_SCBRR_VALUE 0x00C | ||
70 | #define EPK_FIFO_SIZE 64 | ||
71 | #define EPK_FIFO_BITS (0x7f00 >> 8) | ||
72 | #else | ||
73 | #define EPK_FIFO_SIZE 16 | ||
74 | #define EPK_FIFO_BITS (0x1f00 >> 8) | ||
75 | #endif | ||
76 | |||
77 | static struct uart_port scif_port = { | ||
78 | .type = PORT_SCIF, | ||
79 | .mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT, | ||
80 | .membase = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT, | ||
81 | }; | ||
82 | |||
83 | static void scif_sercon_putc(int c) | ||
84 | { | ||
85 | while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE)) | ||
86 | ; | ||
87 | |||
88 | sci_in(&scif_port, SCxSR); | ||
89 | sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40)); | ||
90 | sci_out(&scif_port, SCxTDR, c); | ||
91 | |||
92 | while ((sci_in(&scif_port, SCxSR) & 0x40) == 0) | ||
93 | ; | ||
94 | |||
95 | if (c == '\n') | ||
96 | scif_sercon_putc('\r'); | ||
97 | } | ||
98 | |||
99 | static void scif_sercon_write(struct console *con, const char *s, | ||
100 | unsigned count) | ||
101 | { | ||
102 | while (count-- > 0) | ||
103 | scif_sercon_putc(*s++); | ||
104 | } | ||
105 | |||
106 | static int __init scif_sercon_setup(struct console *con, char *options) | ||
107 | { | ||
108 | con->cflag = CREAD | HUPCL | CLOCAL | B115200 | CS8; | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static struct console scif_console = { | ||
114 | .name = "sercon", | ||
115 | .write = scif_sercon_write, | ||
116 | .setup = scif_sercon_setup, | ||
117 | .flags = CON_PRINTBUFFER, | ||
118 | .index = -1, | ||
119 | }; | ||
120 | |||
121 | #if !defined(CONFIG_SH_STANDARD_BIOS) | ||
122 | #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | ||
123 | defined(CONFIG_CPU_SUBTYPE_SH7721) | ||
124 | static void scif_sercon_init(char *s) | ||
125 | { | ||
126 | sci_out(&scif_port, SCSCR, 0x0000); /* clear TE and RE */ | ||
127 | sci_out(&scif_port, SCFCR, 0x4006); /* reset */ | ||
128 | sci_out(&scif_port, SCSCR, 0x0000); /* select internal clock */ | ||
129 | sci_out(&scif_port, SCSMR, EPK_SCSMR_VALUE); | ||
130 | sci_out(&scif_port, SCBRR, EPK_SCBRR_VALUE); | ||
131 | |||
132 | mdelay(1); /* wait 1-bit time */ | ||
133 | |||
134 | sci_out(&scif_port, SCFCR, 0x0030); /* TTRG=b'11 */ | ||
135 | sci_out(&scif_port, SCSCR, 0x0030); /* TE, RE */ | ||
136 | } | ||
137 | #elif defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3) | ||
138 | #define DEFAULT_BAUD 115200 | ||
139 | /* | ||
140 | * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4 | ||
141 | * devices that aren't using sh-ipl+g. | ||
142 | */ | ||
143 | static void scif_sercon_init(char *s) | ||
144 | { | ||
145 | struct uart_port *port = &scif_port; | ||
146 | unsigned baud = DEFAULT_BAUD; | ||
147 | unsigned int status; | ||
148 | char *e; | ||
149 | |||
150 | if (*s == ',') | ||
151 | ++s; | ||
152 | |||
153 | if (*s) { | ||
154 | /* ignore ioport/device name */ | ||
155 | s += strcspn(s, ","); | ||
156 | if (*s == ',') | ||
157 | s++; | ||
158 | } | ||
159 | |||
160 | if (*s) { | ||
161 | baud = simple_strtoul(s, &e, 0); | ||
162 | if (baud == 0 || s == e) | ||
163 | baud = DEFAULT_BAUD; | ||
164 | } | ||
165 | |||
166 | do { | ||
167 | status = sci_in(port, SCxSR); | ||
168 | } while (!(status & SCxSR_TEND(port))); | ||
169 | |||
170 | sci_out(port, SCSCR, 0); /* TE=0, RE=0 */ | ||
171 | sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); | ||
172 | sci_out(port, SCSMR, 0); | ||
173 | |||
174 | /* Set baud rate */ | ||
175 | sci_out(port, SCBRR, (CONFIG_SH_PCLK_FREQ + 16 * baud) / | ||
176 | (32 * baud) - 1); | ||
177 | udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */ | ||
178 | |||
179 | sci_out(port, SCSPTR, 0); | ||
180 | sci_out(port, SCxSR, 0x60); | ||
181 | sci_out(port, SCLSR, 0); | ||
182 | |||
183 | sci_out(port, SCFCR, 0); | ||
184 | sci_out(port, SCSCR, 0x30); /* TE=1, RE=1 */ | ||
185 | } | ||
186 | #endif /* defined(CONFIG_CPU_SUBTYPE_SH7720) */ | ||
187 | #endif /* !defined(CONFIG_SH_STANDARD_BIOS) */ | ||
188 | #endif /* CONFIG_EARLY_SCIF_CONSOLE */ | ||
189 | |||
190 | /* | ||
191 | * Setup a default console, if more than one is compiled in, rely on the | ||
192 | * earlyprintk= parsing to give priority. | ||
193 | */ | ||
194 | static struct console *early_console = | ||
195 | #ifdef CONFIG_SH_STANDARD_BIOS | ||
196 | &bios_console | ||
197 | #elif defined(CONFIG_EARLY_SCIF_CONSOLE) | ||
198 | &scif_console | ||
199 | #else | ||
200 | NULL | ||
201 | #endif | ||
202 | ; | ||
203 | |||
204 | static int __init setup_early_printk(char *buf) | ||
205 | { | ||
206 | int keep_early = 0; | ||
207 | |||
208 | if (!buf) | ||
209 | return 0; | ||
210 | |||
211 | if (strstr(buf, "keep")) | ||
212 | keep_early = 1; | ||
213 | |||
214 | #ifdef CONFIG_SH_STANDARD_BIOS | ||
215 | if (!strncmp(buf, "bios", 4)) | ||
216 | early_console = &bios_console; | ||
217 | #endif | ||
218 | #if defined(CONFIG_EARLY_SCIF_CONSOLE) | ||
219 | if (!strncmp(buf, "serial", 6)) { | ||
220 | early_console = &scif_console; | ||
221 | |||
222 | #if !defined(CONFIG_SH_STANDARD_BIOS) | ||
223 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3) | ||
224 | scif_sercon_init(buf + 6); | ||
225 | #endif | ||
226 | #endif | ||
227 | } | ||
228 | #endif | ||
229 | |||
230 | if (likely(early_console)) { | ||
231 | if (keep_early) | ||
232 | early_console->flags &= ~CON_BOOT; | ||
233 | else | ||
234 | early_console->flags |= CON_BOOT; | ||
235 | register_console(early_console); | ||
236 | } | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | early_param("earlyprintk", setup_early_printk); | ||
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index 3eb84931d2aa..2b15ae60c3a0 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S | |||
@@ -70,8 +70,14 @@ ret_from_exception: | |||
70 | CFI_STARTPROC simple | 70 | CFI_STARTPROC simple |
71 | CFI_DEF_CFA r14, 0 | 71 | CFI_DEF_CFA r14, 0 |
72 | CFI_REL_OFFSET 17, 64 | 72 | CFI_REL_OFFSET 17, 64 |
73 | CFI_REL_OFFSET 15, 0 | 73 | CFI_REL_OFFSET 15, 60 |
74 | CFI_REL_OFFSET 14, 56 | 74 | CFI_REL_OFFSET 14, 56 |
75 | CFI_REL_OFFSET 13, 52 | ||
76 | CFI_REL_OFFSET 12, 48 | ||
77 | CFI_REL_OFFSET 11, 44 | ||
78 | CFI_REL_OFFSET 10, 40 | ||
79 | CFI_REL_OFFSET 9, 36 | ||
80 | CFI_REL_OFFSET 8, 32 | ||
75 | preempt_stop() | 81 | preempt_stop() |
76 | ENTRY(ret_from_irq) | 82 | ENTRY(ret_from_irq) |
77 | ! | 83 | ! |
@@ -133,7 +139,7 @@ work_pending: | |||
133 | ! r8: current_thread_info | 139 | ! r8: current_thread_info |
134 | ! t: result of "tst #_TIF_NEED_RESCHED, r0" | 140 | ! t: result of "tst #_TIF_NEED_RESCHED, r0" |
135 | bf/s work_resched | 141 | bf/s work_resched |
136 | tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 | 142 | tst #_TIF_SIGPENDING, r0 |
137 | work_notifysig: | 143 | work_notifysig: |
138 | bt/s __restore_all | 144 | bt/s __restore_all |
139 | mov r15, r4 | 145 | mov r15, r4 |
diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c index 2c48e267256e..30e13196d35b 100644 --- a/arch/sh/kernel/ftrace.c +++ b/arch/sh/kernel/ftrace.c | |||
@@ -62,6 +62,150 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) | |||
62 | return ftrace_replaced_code; | 62 | return ftrace_replaced_code; |
63 | } | 63 | } |
64 | 64 | ||
65 | /* | ||
66 | * Modifying code must take extra care. On an SMP machine, if | ||
67 | * the code being modified is also being executed on another CPU | ||
68 | * that CPU will have undefined results and possibly take a GPF. | ||
69 | * We use kstop_machine to stop other CPUS from exectuing code. | ||
70 | * But this does not stop NMIs from happening. We still need | ||
71 | * to protect against that. We separate out the modification of | ||
72 | * the code to take care of this. | ||
73 | * | ||
74 | * Two buffers are added: An IP buffer and a "code" buffer. | ||
75 | * | ||
76 | * 1) Put the instruction pointer into the IP buffer | ||
77 | * and the new code into the "code" buffer. | ||
78 | * 2) Wait for any running NMIs to finish and set a flag that says | ||
79 | * we are modifying code, it is done in an atomic operation. | ||
80 | * 3) Write the code | ||
81 | * 4) clear the flag. | ||
82 | * 5) Wait for any running NMIs to finish. | ||
83 | * | ||
84 | * If an NMI is executed, the first thing it does is to call | ||
85 | * "ftrace_nmi_enter". This will check if the flag is set to write | ||
86 | * and if it is, it will write what is in the IP and "code" buffers. | ||
87 | * | ||
88 | * The trick is, it does not matter if everyone is writing the same | ||
89 | * content to the code location. Also, if a CPU is executing code | ||
90 | * it is OK to write to that code location if the contents being written | ||
91 | * are the same as what exists. | ||
92 | */ | ||
93 | #define MOD_CODE_WRITE_FLAG (1 << 31) /* set when NMI should do the write */ | ||
94 | static atomic_t nmi_running = ATOMIC_INIT(0); | ||
95 | static int mod_code_status; /* holds return value of text write */ | ||
96 | static void *mod_code_ip; /* holds the IP to write to */ | ||
97 | static void *mod_code_newcode; /* holds the text to write to the IP */ | ||
98 | |||
99 | static unsigned nmi_wait_count; | ||
100 | static atomic_t nmi_update_count = ATOMIC_INIT(0); | ||
101 | |||
102 | int ftrace_arch_read_dyn_info(char *buf, int size) | ||
103 | { | ||
104 | int r; | ||
105 | |||
106 | r = snprintf(buf, size, "%u %u", | ||
107 | nmi_wait_count, | ||
108 | atomic_read(&nmi_update_count)); | ||
109 | return r; | ||
110 | } | ||
111 | |||
112 | static void clear_mod_flag(void) | ||
113 | { | ||
114 | int old = atomic_read(&nmi_running); | ||
115 | |||
116 | for (;;) { | ||
117 | int new = old & ~MOD_CODE_WRITE_FLAG; | ||
118 | |||
119 | if (old == new) | ||
120 | break; | ||
121 | |||
122 | old = atomic_cmpxchg(&nmi_running, old, new); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static void ftrace_mod_code(void) | ||
127 | { | ||
128 | /* | ||
129 | * Yes, more than one CPU process can be writing to mod_code_status. | ||
130 | * (and the code itself) | ||
131 | * But if one were to fail, then they all should, and if one were | ||
132 | * to succeed, then they all should. | ||
133 | */ | ||
134 | mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode, | ||
135 | MCOUNT_INSN_SIZE); | ||
136 | |||
137 | /* if we fail, then kill any new writers */ | ||
138 | if (mod_code_status) | ||
139 | clear_mod_flag(); | ||
140 | } | ||
141 | |||
142 | void ftrace_nmi_enter(void) | ||
143 | { | ||
144 | if (atomic_inc_return(&nmi_running) & MOD_CODE_WRITE_FLAG) { | ||
145 | smp_rmb(); | ||
146 | ftrace_mod_code(); | ||
147 | atomic_inc(&nmi_update_count); | ||
148 | } | ||
149 | /* Must have previous changes seen before executions */ | ||
150 | smp_mb(); | ||
151 | } | ||
152 | |||
153 | void ftrace_nmi_exit(void) | ||
154 | { | ||
155 | /* Finish all executions before clearing nmi_running */ | ||
156 | smp_mb(); | ||
157 | atomic_dec(&nmi_running); | ||
158 | } | ||
159 | |||
160 | static void wait_for_nmi_and_set_mod_flag(void) | ||
161 | { | ||
162 | if (!atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG)) | ||
163 | return; | ||
164 | |||
165 | do { | ||
166 | cpu_relax(); | ||
167 | } while (atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG)); | ||
168 | |||
169 | nmi_wait_count++; | ||
170 | } | ||
171 | |||
172 | static void wait_for_nmi(void) | ||
173 | { | ||
174 | if (!atomic_read(&nmi_running)) | ||
175 | return; | ||
176 | |||
177 | do { | ||
178 | cpu_relax(); | ||
179 | } while (atomic_read(&nmi_running)); | ||
180 | |||
181 | nmi_wait_count++; | ||
182 | } | ||
183 | |||
184 | static int | ||
185 | do_ftrace_mod_code(unsigned long ip, void *new_code) | ||
186 | { | ||
187 | mod_code_ip = (void *)ip; | ||
188 | mod_code_newcode = new_code; | ||
189 | |||
190 | /* The buffers need to be visible before we let NMIs write them */ | ||
191 | smp_mb(); | ||
192 | |||
193 | wait_for_nmi_and_set_mod_flag(); | ||
194 | |||
195 | /* Make sure all running NMIs have finished before we write the code */ | ||
196 | smp_mb(); | ||
197 | |||
198 | ftrace_mod_code(); | ||
199 | |||
200 | /* Make sure the write happens before clearing the bit */ | ||
201 | smp_mb(); | ||
202 | |||
203 | clear_mod_flag(); | ||
204 | wait_for_nmi(); | ||
205 | |||
206 | return mod_code_status; | ||
207 | } | ||
208 | |||
65 | static int ftrace_modify_code(unsigned long ip, unsigned char *old_code, | 209 | static int ftrace_modify_code(unsigned long ip, unsigned char *old_code, |
66 | unsigned char *new_code) | 210 | unsigned char *new_code) |
67 | { | 211 | { |
@@ -86,7 +230,7 @@ static int ftrace_modify_code(unsigned long ip, unsigned char *old_code, | |||
86 | return -EINVAL; | 230 | return -EINVAL; |
87 | 231 | ||
88 | /* replace the text with the new text */ | 232 | /* replace the text with the new text */ |
89 | if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE)) | 233 | if (do_ftrace_mod_code(ip, new_code)) |
90 | return -EPERM; | 234 | return -EPERM; |
91 | 235 | ||
92 | flush_icache_range(ip, ip + MCOUNT_INSN_SIZE); | 236 | flush_icache_range(ip, ip + MCOUNT_INSN_SIZE); |
@@ -255,84 +399,3 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) | |||
255 | } | 399 | } |
256 | } | 400 | } |
257 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 401 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
258 | |||
259 | #ifdef CONFIG_FTRACE_SYSCALLS | ||
260 | |||
261 | extern unsigned long __start_syscalls_metadata[]; | ||
262 | extern unsigned long __stop_syscalls_metadata[]; | ||
263 | extern unsigned long *sys_call_table; | ||
264 | |||
265 | static struct syscall_metadata **syscalls_metadata; | ||
266 | |||
267 | static 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 | struct syscall_metadata *syscall_nr_to_meta(int nr) | ||
287 | { | ||
288 | if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0) | ||
289 | return NULL; | ||
290 | |||
291 | return syscalls_metadata[nr]; | ||
292 | } | ||
293 | |||
294 | int syscall_name_to_nr(char *name) | ||
295 | { | ||
296 | int i; | ||
297 | |||
298 | if (!syscalls_metadata) | ||
299 | return -1; | ||
300 | for (i = 0; i < NR_syscalls; i++) | ||
301 | if (syscalls_metadata[i]) | ||
302 | if (!strcmp(syscalls_metadata[i]->name, name)) | ||
303 | return i; | ||
304 | return -1; | ||
305 | } | ||
306 | |||
307 | void set_syscall_enter_id(int num, int id) | ||
308 | { | ||
309 | syscalls_metadata[num]->enter_id = id; | ||
310 | } | ||
311 | |||
312 | void set_syscall_exit_id(int num, int id) | ||
313 | { | ||
314 | syscalls_metadata[num]->exit_id = id; | ||
315 | } | ||
316 | |||
317 | static int __init arch_init_ftrace_syscalls(void) | ||
318 | { | ||
319 | int i; | ||
320 | struct syscall_metadata *meta; | ||
321 | unsigned long **psys_syscall_table = &sys_call_table; | ||
322 | |||
323 | syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * | ||
324 | FTRACE_SYSCALL_MAX, GFP_KERNEL); | ||
325 | if (!syscalls_metadata) { | ||
326 | WARN_ON(1); | ||
327 | return -ENOMEM; | ||
328 | } | ||
329 | |||
330 | for (i = 0; i < FTRACE_SYSCALL_MAX; i++) { | ||
331 | meta = find_syscall_meta(psys_syscall_table[i]); | ||
332 | syscalls_metadata[i] = meta; | ||
333 | } | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | arch_initcall(arch_init_ftrace_syscalls); | ||
338 | #endif /* CONFIG_FTRACE_SYSCALLS */ | ||
diff --git a/arch/sh/kernel/gpio.c b/arch/sh/kernel/gpio.c deleted file mode 100644 index d22e5af699f9..000000000000 --- a/arch/sh/kernel/gpio.c +++ /dev/null | |||
@@ -1,584 +0,0 @@ | |||
1 | /* | ||
2 | * Pinmuxed GPIO support for SuperH. | ||
3 | * | ||
4 | * Copyright (C) 2008 Magnus Damm | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/errno.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/list.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/bitops.h> | ||
20 | #include <linux/gpio.h> | ||
21 | |||
22 | static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) | ||
23 | { | ||
24 | if (enum_id < r->begin) | ||
25 | return 0; | ||
26 | |||
27 | if (enum_id > r->end) | ||
28 | return 0; | ||
29 | |||
30 | return 1; | ||
31 | } | ||
32 | |||
33 | static unsigned long gpio_read_raw_reg(unsigned long reg, | ||
34 | unsigned long reg_width) | ||
35 | { | ||
36 | switch (reg_width) { | ||
37 | case 8: | ||
38 | return ctrl_inb(reg); | ||
39 | case 16: | ||
40 | return ctrl_inw(reg); | ||
41 | case 32: | ||
42 | return ctrl_inl(reg); | ||
43 | } | ||
44 | |||
45 | BUG(); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static void gpio_write_raw_reg(unsigned long reg, | ||
50 | unsigned long reg_width, | ||
51 | unsigned long data) | ||
52 | { | ||
53 | switch (reg_width) { | ||
54 | case 8: | ||
55 | ctrl_outb(data, reg); | ||
56 | return; | ||
57 | case 16: | ||
58 | ctrl_outw(data, reg); | ||
59 | return; | ||
60 | case 32: | ||
61 | ctrl_outl(data, reg); | ||
62 | return; | ||
63 | } | ||
64 | |||
65 | BUG(); | ||
66 | } | ||
67 | |||
68 | static void gpio_write_bit(struct pinmux_data_reg *dr, | ||
69 | unsigned long in_pos, unsigned long value) | ||
70 | { | ||
71 | unsigned long pos; | ||
72 | |||
73 | pos = dr->reg_width - (in_pos + 1); | ||
74 | |||
75 | #ifdef DEBUG | ||
76 | pr_info("write_bit addr = %lx, value = %ld, pos = %ld, " | ||
77 | "r_width = %ld\n", | ||
78 | dr->reg, !!value, pos, dr->reg_width); | ||
79 | #endif | ||
80 | |||
81 | if (value) | ||
82 | set_bit(pos, &dr->reg_shadow); | ||
83 | else | ||
84 | clear_bit(pos, &dr->reg_shadow); | ||
85 | |||
86 | gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow); | ||
87 | } | ||
88 | |||
89 | static int gpio_read_reg(unsigned long reg, unsigned long reg_width, | ||
90 | unsigned long field_width, unsigned long in_pos) | ||
91 | { | ||
92 | unsigned long data, mask, pos; | ||
93 | |||
94 | data = 0; | ||
95 | mask = (1 << field_width) - 1; | ||
96 | pos = reg_width - ((in_pos + 1) * field_width); | ||
97 | |||
98 | #ifdef DEBUG | ||
99 | pr_info("read_reg: addr = %lx, pos = %ld, " | ||
100 | "r_width = %ld, f_width = %ld\n", | ||
101 | reg, pos, reg_width, field_width); | ||
102 | #endif | ||
103 | |||
104 | data = gpio_read_raw_reg(reg, reg_width); | ||
105 | return (data >> pos) & mask; | ||
106 | } | ||
107 | |||
108 | static void gpio_write_reg(unsigned long reg, unsigned long reg_width, | ||
109 | unsigned long field_width, unsigned long in_pos, | ||
110 | unsigned long value) | ||
111 | { | ||
112 | unsigned long mask, pos; | ||
113 | |||
114 | mask = (1 << field_width) - 1; | ||
115 | pos = reg_width - ((in_pos + 1) * field_width); | ||
116 | |||
117 | #ifdef DEBUG | ||
118 | pr_info("write_reg addr = %lx, value = %ld, pos = %ld, " | ||
119 | "r_width = %ld, f_width = %ld\n", | ||
120 | reg, value, pos, reg_width, field_width); | ||
121 | #endif | ||
122 | |||
123 | mask = ~(mask << pos); | ||
124 | value = value << pos; | ||
125 | |||
126 | switch (reg_width) { | ||
127 | case 8: | ||
128 | ctrl_outb((ctrl_inb(reg) & mask) | value, reg); | ||
129 | break; | ||
130 | case 16: | ||
131 | ctrl_outw((ctrl_inw(reg) & mask) | value, reg); | ||
132 | break; | ||
133 | case 32: | ||
134 | ctrl_outl((ctrl_inl(reg) & mask) | value, reg); | ||
135 | break; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio) | ||
140 | { | ||
141 | struct pinmux_gpio *gpiop = &gpioc->gpios[gpio]; | ||
142 | struct pinmux_data_reg *data_reg; | ||
143 | int k, n; | ||
144 | |||
145 | if (!enum_in_range(gpiop->enum_id, &gpioc->data)) | ||
146 | return -1; | ||
147 | |||
148 | k = 0; | ||
149 | while (1) { | ||
150 | data_reg = gpioc->data_regs + k; | ||
151 | |||
152 | if (!data_reg->reg_width) | ||
153 | break; | ||
154 | |||
155 | for (n = 0; n < data_reg->reg_width; n++) { | ||
156 | if (data_reg->enum_ids[n] == gpiop->enum_id) { | ||
157 | gpiop->flags &= ~PINMUX_FLAG_DREG; | ||
158 | gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT); | ||
159 | gpiop->flags &= ~PINMUX_FLAG_DBIT; | ||
160 | gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT); | ||
161 | return 0; | ||
162 | } | ||
163 | } | ||
164 | k++; | ||
165 | } | ||
166 | |||
167 | BUG(); | ||
168 | |||
169 | return -1; | ||
170 | } | ||
171 | |||
172 | static void setup_data_regs(struct pinmux_info *gpioc) | ||
173 | { | ||
174 | struct pinmux_data_reg *drp; | ||
175 | int k; | ||
176 | |||
177 | for (k = gpioc->first_gpio; k <= gpioc->last_gpio; k++) | ||
178 | setup_data_reg(gpioc, k); | ||
179 | |||
180 | k = 0; | ||
181 | while (1) { | ||
182 | drp = gpioc->data_regs + k; | ||
183 | |||
184 | if (!drp->reg_width) | ||
185 | break; | ||
186 | |||
187 | drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width); | ||
188 | k++; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, | ||
193 | struct pinmux_data_reg **drp, int *bitp) | ||
194 | { | ||
195 | struct pinmux_gpio *gpiop = &gpioc->gpios[gpio]; | ||
196 | int k, n; | ||
197 | |||
198 | if (!enum_in_range(gpiop->enum_id, &gpioc->data)) | ||
199 | return -1; | ||
200 | |||
201 | k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT; | ||
202 | n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT; | ||
203 | *drp = gpioc->data_regs + k; | ||
204 | *bitp = n; | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, | ||
209 | struct pinmux_cfg_reg **crp, int *indexp, | ||
210 | unsigned long **cntp) | ||
211 | { | ||
212 | struct pinmux_cfg_reg *config_reg; | ||
213 | unsigned long r_width, f_width; | ||
214 | int k, n; | ||
215 | |||
216 | k = 0; | ||
217 | while (1) { | ||
218 | config_reg = gpioc->cfg_regs + k; | ||
219 | |||
220 | r_width = config_reg->reg_width; | ||
221 | f_width = config_reg->field_width; | ||
222 | |||
223 | if (!r_width) | ||
224 | break; | ||
225 | for (n = 0; n < (r_width / f_width) * 1 << f_width; n++) { | ||
226 | if (config_reg->enum_ids[n] == enum_id) { | ||
227 | *crp = config_reg; | ||
228 | *indexp = n; | ||
229 | *cntp = &config_reg->cnt[n / (1 << f_width)]; | ||
230 | return 0; | ||
231 | } | ||
232 | } | ||
233 | k++; | ||
234 | } | ||
235 | |||
236 | return -1; | ||
237 | } | ||
238 | |||
239 | static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio, | ||
240 | int pos, pinmux_enum_t *enum_idp) | ||
241 | { | ||
242 | pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id; | ||
243 | pinmux_enum_t *data = gpioc->gpio_data; | ||
244 | int k; | ||
245 | |||
246 | if (!enum_in_range(enum_id, &gpioc->data)) { | ||
247 | if (!enum_in_range(enum_id, &gpioc->mark)) { | ||
248 | pr_err("non data/mark enum_id for gpio %d\n", gpio); | ||
249 | return -1; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | if (pos) { | ||
254 | *enum_idp = data[pos + 1]; | ||
255 | return pos + 1; | ||
256 | } | ||
257 | |||
258 | for (k = 0; k < gpioc->gpio_data_size; k++) { | ||
259 | if (data[k] == enum_id) { | ||
260 | *enum_idp = data[k + 1]; | ||
261 | return k + 1; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio); | ||
266 | return -1; | ||
267 | } | ||
268 | |||
269 | static void write_config_reg(struct pinmux_info *gpioc, | ||
270 | struct pinmux_cfg_reg *crp, | ||
271 | int index) | ||
272 | { | ||
273 | unsigned long ncomb, pos, value; | ||
274 | |||
275 | ncomb = 1 << crp->field_width; | ||
276 | pos = index / ncomb; | ||
277 | value = index % ncomb; | ||
278 | |||
279 | gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value); | ||
280 | } | ||
281 | |||
282 | static int check_config_reg(struct pinmux_info *gpioc, | ||
283 | struct pinmux_cfg_reg *crp, | ||
284 | int index) | ||
285 | { | ||
286 | unsigned long ncomb, pos, value; | ||
287 | |||
288 | ncomb = 1 << crp->field_width; | ||
289 | pos = index / ncomb; | ||
290 | value = index % ncomb; | ||
291 | |||
292 | if (gpio_read_reg(crp->reg, crp->reg_width, | ||
293 | crp->field_width, pos) == value) | ||
294 | return 0; | ||
295 | |||
296 | return -1; | ||
297 | } | ||
298 | |||
299 | enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE }; | ||
300 | |||
301 | static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, | ||
302 | int pinmux_type, int cfg_mode) | ||
303 | { | ||
304 | struct pinmux_cfg_reg *cr = NULL; | ||
305 | pinmux_enum_t enum_id; | ||
306 | struct pinmux_range *range; | ||
307 | int in_range, pos, index; | ||
308 | unsigned long *cntp; | ||
309 | |||
310 | switch (pinmux_type) { | ||
311 | |||
312 | case PINMUX_TYPE_FUNCTION: | ||
313 | range = NULL; | ||
314 | break; | ||
315 | |||
316 | case PINMUX_TYPE_OUTPUT: | ||
317 | range = &gpioc->output; | ||
318 | break; | ||
319 | |||
320 | case PINMUX_TYPE_INPUT: | ||
321 | range = &gpioc->input; | ||
322 | break; | ||
323 | |||
324 | case PINMUX_TYPE_INPUT_PULLUP: | ||
325 | range = &gpioc->input_pu; | ||
326 | break; | ||
327 | |||
328 | case PINMUX_TYPE_INPUT_PULLDOWN: | ||
329 | range = &gpioc->input_pd; | ||
330 | break; | ||
331 | |||
332 | default: | ||
333 | goto out_err; | ||
334 | } | ||
335 | |||
336 | pos = 0; | ||
337 | enum_id = 0; | ||
338 | index = 0; | ||
339 | while (1) { | ||
340 | pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id); | ||
341 | if (pos <= 0) | ||
342 | goto out_err; | ||
343 | |||
344 | if (!enum_id) | ||
345 | break; | ||
346 | |||
347 | in_range = enum_in_range(enum_id, &gpioc->function); | ||
348 | if (!in_range && range) { | ||
349 | in_range = enum_in_range(enum_id, range); | ||
350 | |||
351 | if (in_range && enum_id == range->force) | ||
352 | continue; | ||
353 | } | ||
354 | |||
355 | if (!in_range) | ||
356 | continue; | ||
357 | |||
358 | if (get_config_reg(gpioc, enum_id, &cr, &index, &cntp) != 0) | ||
359 | goto out_err; | ||
360 | |||
361 | switch (cfg_mode) { | ||
362 | case GPIO_CFG_DRYRUN: | ||
363 | if (!*cntp || !check_config_reg(gpioc, cr, index)) | ||
364 | continue; | ||
365 | break; | ||
366 | |||
367 | case GPIO_CFG_REQ: | ||
368 | write_config_reg(gpioc, cr, index); | ||
369 | *cntp = *cntp + 1; | ||
370 | break; | ||
371 | |||
372 | case GPIO_CFG_FREE: | ||
373 | *cntp = *cntp - 1; | ||
374 | break; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | return 0; | ||
379 | out_err: | ||
380 | return -1; | ||
381 | } | ||
382 | |||
383 | static DEFINE_SPINLOCK(gpio_lock); | ||
384 | |||
385 | static struct pinmux_info *chip_to_pinmux(struct gpio_chip *chip) | ||
386 | { | ||
387 | return container_of(chip, struct pinmux_info, chip); | ||
388 | } | ||
389 | |||
390 | static int sh_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
391 | { | ||
392 | struct pinmux_info *gpioc = chip_to_pinmux(chip); | ||
393 | struct pinmux_data_reg *dummy; | ||
394 | unsigned long flags; | ||
395 | int i, ret, pinmux_type; | ||
396 | |||
397 | ret = -EINVAL; | ||
398 | |||
399 | if (!gpioc) | ||
400 | goto err_out; | ||
401 | |||
402 | spin_lock_irqsave(&gpio_lock, flags); | ||
403 | |||
404 | if ((gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE) | ||
405 | goto err_unlock; | ||
406 | |||
407 | /* setup pin function here if no data is associated with pin */ | ||
408 | |||
409 | if (get_data_reg(gpioc, offset, &dummy, &i) != 0) | ||
410 | pinmux_type = PINMUX_TYPE_FUNCTION; | ||
411 | else | ||
412 | pinmux_type = PINMUX_TYPE_GPIO; | ||
413 | |||
414 | if (pinmux_type == PINMUX_TYPE_FUNCTION) { | ||
415 | if (pinmux_config_gpio(gpioc, offset, | ||
416 | pinmux_type, | ||
417 | GPIO_CFG_DRYRUN) != 0) | ||
418 | goto err_unlock; | ||
419 | |||
420 | if (pinmux_config_gpio(gpioc, offset, | ||
421 | pinmux_type, | ||
422 | GPIO_CFG_REQ) != 0) | ||
423 | BUG(); | ||
424 | } | ||
425 | |||
426 | gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; | ||
427 | gpioc->gpios[offset].flags |= pinmux_type; | ||
428 | |||
429 | ret = 0; | ||
430 | err_unlock: | ||
431 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
432 | err_out: | ||
433 | return ret; | ||
434 | } | ||
435 | |||
436 | static void sh_gpio_free(struct gpio_chip *chip, unsigned offset) | ||
437 | { | ||
438 | struct pinmux_info *gpioc = chip_to_pinmux(chip); | ||
439 | unsigned long flags; | ||
440 | int pinmux_type; | ||
441 | |||
442 | if (!gpioc) | ||
443 | return; | ||
444 | |||
445 | spin_lock_irqsave(&gpio_lock, flags); | ||
446 | |||
447 | pinmux_type = gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE; | ||
448 | pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_FREE); | ||
449 | gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; | ||
450 | gpioc->gpios[offset].flags |= PINMUX_TYPE_NONE; | ||
451 | |||
452 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
453 | } | ||
454 | |||
455 | static int pinmux_direction(struct pinmux_info *gpioc, | ||
456 | unsigned gpio, int new_pinmux_type) | ||
457 | { | ||
458 | int pinmux_type; | ||
459 | int ret = -EINVAL; | ||
460 | |||
461 | if (!gpioc) | ||
462 | goto err_out; | ||
463 | |||
464 | pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE; | ||
465 | |||
466 | switch (pinmux_type) { | ||
467 | case PINMUX_TYPE_GPIO: | ||
468 | break; | ||
469 | case PINMUX_TYPE_OUTPUT: | ||
470 | case PINMUX_TYPE_INPUT: | ||
471 | case PINMUX_TYPE_INPUT_PULLUP: | ||
472 | case PINMUX_TYPE_INPUT_PULLDOWN: | ||
473 | pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE); | ||
474 | break; | ||
475 | default: | ||
476 | goto err_out; | ||
477 | } | ||
478 | |||
479 | if (pinmux_config_gpio(gpioc, gpio, | ||
480 | new_pinmux_type, | ||
481 | GPIO_CFG_DRYRUN) != 0) | ||
482 | goto err_out; | ||
483 | |||
484 | if (pinmux_config_gpio(gpioc, gpio, | ||
485 | new_pinmux_type, | ||
486 | GPIO_CFG_REQ) != 0) | ||
487 | BUG(); | ||
488 | |||
489 | gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE; | ||
490 | gpioc->gpios[gpio].flags |= new_pinmux_type; | ||
491 | |||
492 | ret = 0; | ||
493 | err_out: | ||
494 | return ret; | ||
495 | } | ||
496 | |||
497 | static int sh_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
498 | { | ||
499 | struct pinmux_info *gpioc = chip_to_pinmux(chip); | ||
500 | unsigned long flags; | ||
501 | int ret; | ||
502 | |||
503 | spin_lock_irqsave(&gpio_lock, flags); | ||
504 | ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_INPUT); | ||
505 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
506 | |||
507 | return ret; | ||
508 | } | ||
509 | |||
510 | static void sh_gpio_set_value(struct pinmux_info *gpioc, | ||
511 | unsigned gpio, int value) | ||
512 | { | ||
513 | struct pinmux_data_reg *dr = NULL; | ||
514 | int bit = 0; | ||
515 | |||
516 | if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) | ||
517 | BUG(); | ||
518 | else | ||
519 | gpio_write_bit(dr, bit, value); | ||
520 | } | ||
521 | |||
522 | static int sh_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
523 | int value) | ||
524 | { | ||
525 | struct pinmux_info *gpioc = chip_to_pinmux(chip); | ||
526 | unsigned long flags; | ||
527 | int ret; | ||
528 | |||
529 | sh_gpio_set_value(gpioc, offset, value); | ||
530 | spin_lock_irqsave(&gpio_lock, flags); | ||
531 | ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_OUTPUT); | ||
532 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
533 | |||
534 | return ret; | ||
535 | } | ||
536 | |||
537 | static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio) | ||
538 | { | ||
539 | struct pinmux_data_reg *dr = NULL; | ||
540 | int bit = 0; | ||
541 | |||
542 | if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) { | ||
543 | BUG(); | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | return gpio_read_reg(dr->reg, dr->reg_width, 1, bit); | ||
548 | } | ||
549 | |||
550 | static int sh_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
551 | { | ||
552 | return sh_gpio_get_value(chip_to_pinmux(chip), offset); | ||
553 | } | ||
554 | |||
555 | static void sh_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
556 | { | ||
557 | sh_gpio_set_value(chip_to_pinmux(chip), offset, value); | ||
558 | } | ||
559 | |||
560 | int register_pinmux(struct pinmux_info *pip) | ||
561 | { | ||
562 | struct gpio_chip *chip = &pip->chip; | ||
563 | |||
564 | pr_info("sh pinmux: %s handling gpio %d -> %d\n", | ||
565 | pip->name, pip->first_gpio, pip->last_gpio); | ||
566 | |||
567 | setup_data_regs(pip); | ||
568 | |||
569 | chip->request = sh_gpio_request; | ||
570 | chip->free = sh_gpio_free; | ||
571 | chip->direction_input = sh_gpio_direction_input; | ||
572 | chip->get = sh_gpio_get; | ||
573 | chip->direction_output = sh_gpio_direction_output; | ||
574 | chip->set = sh_gpio_set; | ||
575 | |||
576 | WARN_ON(pip->first_gpio != 0); /* needs testing */ | ||
577 | |||
578 | chip->label = pip->name; | ||
579 | chip->owner = THIS_MODULE; | ||
580 | chip->base = pip->first_gpio; | ||
581 | chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1; | ||
582 | |||
583 | return gpiochip_add(chip); | ||
584 | } | ||
diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S index a78be74b8d3e..fe0b743881b0 100644 --- a/arch/sh/kernel/head_32.S +++ b/arch/sh/kernel/head_32.S | |||
@@ -3,6 +3,7 @@ | |||
3 | * arch/sh/kernel/head.S | 3 | * arch/sh/kernel/head.S |
4 | * | 4 | * |
5 | * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima | 5 | * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima |
6 | * Copyright (C) 2010 Matt Fleming | ||
6 | * | 7 | * |
7 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
8 | * License. See the file "COPYING" in the main directory of this archive | 9 | * License. See the file "COPYING" in the main directory of this archive |
@@ -13,6 +14,8 @@ | |||
13 | #include <linux/init.h> | 14 | #include <linux/init.h> |
14 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> |
15 | #include <asm/thread_info.h> | 16 | #include <asm/thread_info.h> |
17 | #include <asm/mmu.h> | ||
18 | #include <cpu/mmu_context.h> | ||
16 | 19 | ||
17 | #ifdef CONFIG_CPU_SH4A | 20 | #ifdef CONFIG_CPU_SH4A |
18 | #define SYNCO() synco | 21 | #define SYNCO() synco |
@@ -82,6 +85,209 @@ ENTRY(_stext) | |||
82 | ldc r0, r7_bank ! ... and initial thread_info | 85 | ldc r0, r7_bank ! ... and initial thread_info |
83 | #endif | 86 | #endif |
84 | 87 | ||
88 | #ifdef CONFIG_PMB | ||
89 | /* | ||
90 | * Reconfigure the initial PMB mappings setup by the hardware. | ||
91 | * | ||
92 | * When we boot in 32-bit MMU mode there are 2 PMB entries already | ||
93 | * setup for us. | ||
94 | * | ||
95 | * Entry VPN PPN V SZ C UB WT | ||
96 | * --------------------------------------------------------------- | ||
97 | * 0 0x80000000 0x00000000 1 512MB 1 0 1 | ||
98 | * 1 0xA0000000 0x00000000 1 512MB 0 0 0 | ||
99 | * | ||
100 | * But we reprogram them here because we want complete control over | ||
101 | * our address space and the initial mappings may not map PAGE_OFFSET | ||
102 | * to __MEMORY_START (or even map all of our RAM). | ||
103 | * | ||
104 | * Once we've setup cached and uncached mappings we clear the rest of the | ||
105 | * PMB entries. This clearing also deals with the fact that PMB entries | ||
106 | * can persist across reboots. The PMB could have been left in any state | ||
107 | * when the reboot occurred, so to be safe we clear all entries and start | ||
108 | * with with a clean slate. | ||
109 | * | ||
110 | * The uncached mapping is constructed using the smallest possible | ||
111 | * mapping with a single unbufferable page. Only the kernel text needs to | ||
112 | * be covered via the uncached mapping so that certain functions can be | ||
113 | * run uncached. | ||
114 | * | ||
115 | * Drivers and the like that have previously abused the 1:1 identity | ||
116 | * mapping are unsupported in 32-bit mode and must specify their caching | ||
117 | * preference when page tables are constructed. | ||
118 | * | ||
119 | * This frees up the P2 space for more nefarious purposes. | ||
120 | * | ||
121 | * Register utilization is as follows: | ||
122 | * | ||
123 | * r0 = PMB_DATA data field | ||
124 | * r1 = PMB_DATA address field | ||
125 | * r2 = PMB_ADDR data field | ||
126 | * r3 = PMB_ADDR address field | ||
127 | * r4 = PMB_E_SHIFT | ||
128 | * r5 = remaining amount of RAM to map | ||
129 | * r6 = PMB mapping size we're trying to use | ||
130 | * r7 = cached_to_uncached | ||
131 | * r8 = scratch register | ||
132 | * r9 = scratch register | ||
133 | * r10 = number of PMB entries we've setup | ||
134 | */ | ||
135 | |||
136 | mov.l .LMMUCR, r1 /* Flush the TLB */ | ||
137 | mov.l @r1, r0 | ||
138 | or #MMUCR_TI, r0 | ||
139 | mov.l r0, @r1 | ||
140 | |||
141 | mov.l .LMEMORY_SIZE, r5 | ||
142 | |||
143 | mov #PMB_E_SHIFT, r0 | ||
144 | mov #0x1, r4 | ||
145 | shld r0, r4 | ||
146 | |||
147 | mov.l .LFIRST_DATA_ENTRY, r0 | ||
148 | mov.l .LPMB_DATA, r1 | ||
149 | mov.l .LFIRST_ADDR_ENTRY, r2 | ||
150 | mov.l .LPMB_ADDR, r3 | ||
151 | |||
152 | /* | ||
153 | * First we need to walk the PMB and figure out if there are any | ||
154 | * existing mappings that match the initial mappings VPN/PPN. | ||
155 | * If these have already been established by the bootloader, we | ||
156 | * don't bother setting up new entries here, and let the late PMB | ||
157 | * initialization take care of things instead. | ||
158 | * | ||
159 | * Note that we may need to coalesce and merge entries in order | ||
160 | * to reclaim more available PMB slots, which is much more than | ||
161 | * we want to do at this early stage. | ||
162 | */ | ||
163 | mov #0, r10 | ||
164 | mov #NR_PMB_ENTRIES, r9 | ||
165 | |||
166 | mov r1, r7 /* temporary PMB_DATA iter */ | ||
167 | |||
168 | .Lvalidate_existing_mappings: | ||
169 | |||
170 | mov.l @r7, r8 | ||
171 | and r0, r8 | ||
172 | cmp/eq r0, r8 /* Check for valid __MEMORY_START mappings */ | ||
173 | bt .Lpmb_done | ||
174 | |||
175 | add #1, r10 /* Increment the loop counter */ | ||
176 | cmp/eq r9, r10 | ||
177 | bf/s .Lvalidate_existing_mappings | ||
178 | add r4, r7 /* Increment to the next PMB_DATA entry */ | ||
179 | |||
180 | /* | ||
181 | * If we've fallen through, continue with setting up the initial | ||
182 | * mappings. | ||
183 | */ | ||
184 | |||
185 | mov r5, r7 /* cached_to_uncached */ | ||
186 | mov #0, r10 | ||
187 | |||
188 | #ifdef CONFIG_UNCACHED_MAPPING | ||
189 | /* | ||
190 | * Uncached mapping | ||
191 | */ | ||
192 | mov #(PMB_SZ_16M >> 2), r9 | ||
193 | shll2 r9 | ||
194 | |||
195 | mov #(PMB_UB >> 8), r8 | ||
196 | shll8 r8 | ||
197 | |||
198 | or r0, r8 | ||
199 | or r9, r8 | ||
200 | mov.l r8, @r1 | ||
201 | mov r2, r8 | ||
202 | add r7, r8 | ||
203 | mov.l r8, @r3 | ||
204 | |||
205 | add r4, r1 | ||
206 | add r4, r3 | ||
207 | add #1, r10 | ||
208 | #endif | ||
209 | |||
210 | /* | ||
211 | * Iterate over all of the available sizes from largest to | ||
212 | * smallest for constructing the cached mapping. | ||
213 | */ | ||
214 | #define __PMB_ITER_BY_SIZE(size) \ | ||
215 | .L##size: \ | ||
216 | mov #(size >> 4), r6; \ | ||
217 | shll16 r6; \ | ||
218 | shll8 r6; \ | ||
219 | \ | ||
220 | cmp/hi r5, r6; \ | ||
221 | bt 9999f; \ | ||
222 | \ | ||
223 | mov #(PMB_SZ_##size##M >> 2), r9; \ | ||
224 | shll2 r9; \ | ||
225 | \ | ||
226 | /* \ | ||
227 | * Cached mapping \ | ||
228 | */ \ | ||
229 | mov #PMB_C, r8; \ | ||
230 | or r0, r8; \ | ||
231 | or r9, r8; \ | ||
232 | mov.l r8, @r1; \ | ||
233 | mov.l r2, @r3; \ | ||
234 | \ | ||
235 | /* Increment to the next PMB_DATA entry */ \ | ||
236 | add r4, r1; \ | ||
237 | /* Increment to the next PMB_ADDR entry */ \ | ||
238 | add r4, r3; \ | ||
239 | /* Increment number of PMB entries */ \ | ||
240 | add #1, r10; \ | ||
241 | \ | ||
242 | sub r6, r5; \ | ||
243 | add r6, r0; \ | ||
244 | add r6, r2; \ | ||
245 | \ | ||
246 | bra .L##size; \ | ||
247 | 9999: | ||
248 | |||
249 | __PMB_ITER_BY_SIZE(512) | ||
250 | __PMB_ITER_BY_SIZE(128) | ||
251 | __PMB_ITER_BY_SIZE(64) | ||
252 | __PMB_ITER_BY_SIZE(16) | ||
253 | |||
254 | #ifdef CONFIG_UNCACHED_MAPPING | ||
255 | /* | ||
256 | * Now that we can access it, update cached_to_uncached and | ||
257 | * uncached_size. | ||
258 | */ | ||
259 | mov.l .Lcached_to_uncached, r0 | ||
260 | mov.l r7, @r0 | ||
261 | |||
262 | mov.l .Luncached_size, r0 | ||
263 | mov #1, r7 | ||
264 | shll16 r7 | ||
265 | shll8 r7 | ||
266 | mov.l r7, @r0 | ||
267 | #endif | ||
268 | |||
269 | /* | ||
270 | * Clear the remaining PMB entries. | ||
271 | * | ||
272 | * r3 = entry to begin clearing from | ||
273 | * r10 = number of entries we've setup so far | ||
274 | */ | ||
275 | mov #0, r1 | ||
276 | mov #NR_PMB_ENTRIES, r0 | ||
277 | |||
278 | .Lagain: | ||
279 | mov.l r1, @r3 /* Clear PMB_ADDR entry */ | ||
280 | add #1, r10 /* Increment the loop counter */ | ||
281 | cmp/eq r0, r10 | ||
282 | bf/s .Lagain | ||
283 | add r4, r3 /* Increment to the next PMB_ADDR entry */ | ||
284 | |||
285 | mov.l 6f, r0 | ||
286 | icbi @r0 | ||
287 | |||
288 | .Lpmb_done: | ||
289 | #endif /* CONFIG_PMB */ | ||
290 | |||
85 | #ifndef CONFIG_SH_NO_BSS_INIT | 291 | #ifndef CONFIG_SH_NO_BSS_INIT |
86 | /* | 292 | /* |
87 | * Don't clear BSS if running on slow platforms such as an RTL simulation, | 293 | * Don't clear BSS if running on slow platforms such as an RTL simulation, |
@@ -131,3 +337,16 @@ ENTRY(stack_start) | |||
131 | 5: .long start_kernel | 337 | 5: .long start_kernel |
132 | 6: .long sh_cpu_init | 338 | 6: .long sh_cpu_init |
133 | 7: .long init_thread_union | 339 | 7: .long init_thread_union |
340 | |||
341 | #ifdef CONFIG_PMB | ||
342 | .LPMB_ADDR: .long PMB_ADDR | ||
343 | .LPMB_DATA: .long PMB_DATA | ||
344 | .LFIRST_ADDR_ENTRY: .long PAGE_OFFSET | PMB_V | ||
345 | .LFIRST_DATA_ENTRY: .long __MEMORY_START | PMB_V | ||
346 | .LMMUCR: .long MMUCR | ||
347 | .LMEMORY_SIZE: .long __MEMORY_SIZE | ||
348 | #ifdef CONFIG_UNCACHED_MAPPING | ||
349 | .Lcached_to_uncached: .long cached_to_uncached | ||
350 | .Luncached_size: .long uncached_size | ||
351 | #endif | ||
352 | #endif | ||
diff --git a/arch/sh/kernel/head_64.S b/arch/sh/kernel/head_64.S index 3ea765844c74..defd851abefa 100644 --- a/arch/sh/kernel/head_64.S +++ b/arch/sh/kernel/head_64.S | |||
@@ -220,7 +220,6 @@ clear_DTLB: | |||
220 | add.l r22, r63, r22 /* Sign extend */ | 220 | add.l r22, r63, r22 /* Sign extend */ |
221 | putcfg r21, 0, r22 /* Set MMUDR[0].PTEH */ | 221 | putcfg r21, 0, r22 /* Set MMUDR[0].PTEH */ |
222 | 222 | ||
223 | #ifdef CONFIG_EARLY_PRINTK | ||
224 | /* | 223 | /* |
225 | * Setup a DTLB translation for SCIF phys. | 224 | * Setup a DTLB translation for SCIF phys. |
226 | */ | 225 | */ |
@@ -231,7 +230,6 @@ clear_DTLB: | |||
231 | movi 0xfa03, r22 /* 0xfa030000, fixed SCIF virt */ | 230 | movi 0xfa03, r22 /* 0xfa030000, fixed SCIF virt */ |
232 | shori 0x0003, r22 | 231 | shori 0x0003, r22 |
233 | putcfg r21, 0, r22 /* PTEH last */ | 232 | putcfg r21, 0, r22 /* PTEH last */ |
234 | #endif | ||
235 | 233 | ||
236 | /* | 234 | /* |
237 | * Set cache behaviours. | 235 | * Set cache behaviours. |
diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c new file mode 100644 index 000000000000..675eea7785d9 --- /dev/null +++ b/arch/sh/kernel/hw_breakpoint.c | |||
@@ -0,0 +1,445 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/hw_breakpoint.c | ||
3 | * | ||
4 | * Unified kernel/user-space hardware breakpoint facility for the on-chip UBC. | ||
5 | * | ||
6 | * Copyright (C) 2009 - 2010 Paul Mundt | ||
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/perf_event.h> | ||
14 | #include <linux/hw_breakpoint.h> | ||
15 | #include <linux/percpu.h> | ||
16 | #include <linux/kallsyms.h> | ||
17 | #include <linux/notifier.h> | ||
18 | #include <linux/kprobes.h> | ||
19 | #include <linux/kdebug.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/clk.h> | ||
22 | #include <asm/hw_breakpoint.h> | ||
23 | #include <asm/mmu_context.h> | ||
24 | #include <asm/ptrace.h> | ||
25 | |||
26 | /* | ||
27 | * Stores the breakpoints currently in use on each breakpoint address | ||
28 | * register for each cpus | ||
29 | */ | ||
30 | static DEFINE_PER_CPU(struct perf_event *, bp_per_reg[HBP_NUM]); | ||
31 | |||
32 | /* | ||
33 | * A dummy placeholder for early accesses until the CPUs get a chance to | ||
34 | * register their UBCs later in the boot process. | ||
35 | */ | ||
36 | static struct sh_ubc ubc_dummy = { .num_events = 0 }; | ||
37 | |||
38 | static struct sh_ubc *sh_ubc __read_mostly = &ubc_dummy; | ||
39 | |||
40 | /* | ||
41 | * Install a perf counter breakpoint. | ||
42 | * | ||
43 | * We seek a free UBC channel and use it for this breakpoint. | ||
44 | * | ||
45 | * Atomic: we hold the counter->ctx->lock and we only handle variables | ||
46 | * and registers local to this cpu. | ||
47 | */ | ||
48 | int arch_install_hw_breakpoint(struct perf_event *bp) | ||
49 | { | ||
50 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
51 | int i; | ||
52 | |||
53 | for (i = 0; i < sh_ubc->num_events; i++) { | ||
54 | struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]); | ||
55 | |||
56 | if (!*slot) { | ||
57 | *slot = bp; | ||
58 | break; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | if (WARN_ONCE(i == sh_ubc->num_events, "Can't find any breakpoint slot")) | ||
63 | return -EBUSY; | ||
64 | |||
65 | clk_enable(sh_ubc->clk); | ||
66 | sh_ubc->enable(info, i); | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * Uninstall the breakpoint contained in the given counter. | ||
73 | * | ||
74 | * First we search the debug address register it uses and then we disable | ||
75 | * it. | ||
76 | * | ||
77 | * Atomic: we hold the counter->ctx->lock and we only handle variables | ||
78 | * and registers local to this cpu. | ||
79 | */ | ||
80 | void arch_uninstall_hw_breakpoint(struct perf_event *bp) | ||
81 | { | ||
82 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
83 | int i; | ||
84 | |||
85 | for (i = 0; i < sh_ubc->num_events; i++) { | ||
86 | struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]); | ||
87 | |||
88 | if (*slot == bp) { | ||
89 | *slot = NULL; | ||
90 | break; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | if (WARN_ONCE(i == sh_ubc->num_events, "Can't find any breakpoint slot")) | ||
95 | return; | ||
96 | |||
97 | sh_ubc->disable(info, i); | ||
98 | clk_disable(sh_ubc->clk); | ||
99 | } | ||
100 | |||
101 | static int get_hbp_len(u16 hbp_len) | ||
102 | { | ||
103 | unsigned int len_in_bytes = 0; | ||
104 | |||
105 | switch (hbp_len) { | ||
106 | case SH_BREAKPOINT_LEN_1: | ||
107 | len_in_bytes = 1; | ||
108 | break; | ||
109 | case SH_BREAKPOINT_LEN_2: | ||
110 | len_in_bytes = 2; | ||
111 | break; | ||
112 | case SH_BREAKPOINT_LEN_4: | ||
113 | len_in_bytes = 4; | ||
114 | break; | ||
115 | case SH_BREAKPOINT_LEN_8: | ||
116 | len_in_bytes = 8; | ||
117 | break; | ||
118 | } | ||
119 | return len_in_bytes; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * Check for virtual address in user space. | ||
124 | */ | ||
125 | int arch_check_va_in_userspace(unsigned long va, u16 hbp_len) | ||
126 | { | ||
127 | unsigned int len; | ||
128 | |||
129 | len = get_hbp_len(hbp_len); | ||
130 | |||
131 | return (va <= TASK_SIZE - len); | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Check for virtual address in kernel space. | ||
136 | */ | ||
137 | static int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len) | ||
138 | { | ||
139 | unsigned int len; | ||
140 | |||
141 | len = get_hbp_len(hbp_len); | ||
142 | |||
143 | return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); | ||
144 | } | ||
145 | |||
146 | int arch_bp_generic_fields(int sh_len, int sh_type, | ||
147 | int *gen_len, int *gen_type) | ||
148 | { | ||
149 | /* Len */ | ||
150 | switch (sh_len) { | ||
151 | case SH_BREAKPOINT_LEN_1: | ||
152 | *gen_len = HW_BREAKPOINT_LEN_1; | ||
153 | break; | ||
154 | case SH_BREAKPOINT_LEN_2: | ||
155 | *gen_len = HW_BREAKPOINT_LEN_2; | ||
156 | break; | ||
157 | case SH_BREAKPOINT_LEN_4: | ||
158 | *gen_len = HW_BREAKPOINT_LEN_4; | ||
159 | break; | ||
160 | case SH_BREAKPOINT_LEN_8: | ||
161 | *gen_len = HW_BREAKPOINT_LEN_8; | ||
162 | break; | ||
163 | default: | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
167 | /* Type */ | ||
168 | switch (sh_type) { | ||
169 | case SH_BREAKPOINT_READ: | ||
170 | *gen_type = HW_BREAKPOINT_R; | ||
171 | case SH_BREAKPOINT_WRITE: | ||
172 | *gen_type = HW_BREAKPOINT_W; | ||
173 | break; | ||
174 | case SH_BREAKPOINT_RW: | ||
175 | *gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R; | ||
176 | break; | ||
177 | default: | ||
178 | return -EINVAL; | ||
179 | } | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int arch_build_bp_info(struct perf_event *bp) | ||
185 | { | ||
186 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
187 | |||
188 | info->address = bp->attr.bp_addr; | ||
189 | |||
190 | /* Len */ | ||
191 | switch (bp->attr.bp_len) { | ||
192 | case HW_BREAKPOINT_LEN_1: | ||
193 | info->len = SH_BREAKPOINT_LEN_1; | ||
194 | break; | ||
195 | case HW_BREAKPOINT_LEN_2: | ||
196 | info->len = SH_BREAKPOINT_LEN_2; | ||
197 | break; | ||
198 | case HW_BREAKPOINT_LEN_4: | ||
199 | info->len = SH_BREAKPOINT_LEN_4; | ||
200 | break; | ||
201 | case HW_BREAKPOINT_LEN_8: | ||
202 | info->len = SH_BREAKPOINT_LEN_8; | ||
203 | break; | ||
204 | default: | ||
205 | return -EINVAL; | ||
206 | } | ||
207 | |||
208 | /* Type */ | ||
209 | switch (bp->attr.bp_type) { | ||
210 | case HW_BREAKPOINT_R: | ||
211 | info->type = SH_BREAKPOINT_READ; | ||
212 | break; | ||
213 | case HW_BREAKPOINT_W: | ||
214 | info->type = SH_BREAKPOINT_WRITE; | ||
215 | break; | ||
216 | case HW_BREAKPOINT_W | HW_BREAKPOINT_R: | ||
217 | info->type = SH_BREAKPOINT_RW; | ||
218 | break; | ||
219 | default: | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * Validate the arch-specific HW Breakpoint register settings | ||
228 | */ | ||
229 | int arch_validate_hwbkpt_settings(struct perf_event *bp, | ||
230 | struct task_struct *tsk) | ||
231 | { | ||
232 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
233 | unsigned int align; | ||
234 | int ret; | ||
235 | |||
236 | ret = arch_build_bp_info(bp); | ||
237 | if (ret) | ||
238 | return ret; | ||
239 | |||
240 | ret = -EINVAL; | ||
241 | |||
242 | switch (info->len) { | ||
243 | case SH_BREAKPOINT_LEN_1: | ||
244 | align = 0; | ||
245 | break; | ||
246 | case SH_BREAKPOINT_LEN_2: | ||
247 | align = 1; | ||
248 | break; | ||
249 | case SH_BREAKPOINT_LEN_4: | ||
250 | align = 3; | ||
251 | break; | ||
252 | case SH_BREAKPOINT_LEN_8: | ||
253 | align = 7; | ||
254 | break; | ||
255 | default: | ||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * For kernel-addresses, either the address or symbol name can be | ||
261 | * specified. | ||
262 | */ | ||
263 | if (info->name) | ||
264 | info->address = (unsigned long)kallsyms_lookup_name(info->name); | ||
265 | |||
266 | /* | ||
267 | * Check that the low-order bits of the address are appropriate | ||
268 | * for the alignment implied by len. | ||
269 | */ | ||
270 | if (info->address & align) | ||
271 | return -EINVAL; | ||
272 | |||
273 | /* Check that the virtual address is in the proper range */ | ||
274 | if (tsk) { | ||
275 | if (!arch_check_va_in_userspace(info->address, info->len)) | ||
276 | return -EFAULT; | ||
277 | } else { | ||
278 | if (!arch_check_va_in_kernelspace(info->address, info->len)) | ||
279 | return -EFAULT; | ||
280 | } | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * Release the user breakpoints used by ptrace | ||
287 | */ | ||
288 | void flush_ptrace_hw_breakpoint(struct task_struct *tsk) | ||
289 | { | ||
290 | int i; | ||
291 | struct thread_struct *t = &tsk->thread; | ||
292 | |||
293 | for (i = 0; i < sh_ubc->num_events; i++) { | ||
294 | unregister_hw_breakpoint(t->ptrace_bps[i]); | ||
295 | t->ptrace_bps[i] = NULL; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | static int __kprobes hw_breakpoint_handler(struct die_args *args) | ||
300 | { | ||
301 | int cpu, i, rc = NOTIFY_STOP; | ||
302 | struct perf_event *bp; | ||
303 | unsigned int cmf, resume_mask; | ||
304 | |||
305 | /* | ||
306 | * Do an early return if none of the channels triggered. | ||
307 | */ | ||
308 | cmf = sh_ubc->triggered_mask(); | ||
309 | if (unlikely(!cmf)) | ||
310 | return NOTIFY_DONE; | ||
311 | |||
312 | /* | ||
313 | * By default, resume all of the active channels. | ||
314 | */ | ||
315 | resume_mask = sh_ubc->active_mask(); | ||
316 | |||
317 | /* | ||
318 | * Disable breakpoints during exception handling. | ||
319 | */ | ||
320 | sh_ubc->disable_all(); | ||
321 | |||
322 | cpu = get_cpu(); | ||
323 | for (i = 0; i < sh_ubc->num_events; i++) { | ||
324 | unsigned long event_mask = (1 << i); | ||
325 | |||
326 | if (likely(!(cmf & event_mask))) | ||
327 | continue; | ||
328 | |||
329 | /* | ||
330 | * The counter may be concurrently released but that can only | ||
331 | * occur from a call_rcu() path. We can then safely fetch | ||
332 | * the breakpoint, use its callback, touch its counter | ||
333 | * while we are in an rcu_read_lock() path. | ||
334 | */ | ||
335 | rcu_read_lock(); | ||
336 | |||
337 | bp = per_cpu(bp_per_reg[i], cpu); | ||
338 | if (bp) | ||
339 | rc = NOTIFY_DONE; | ||
340 | |||
341 | /* | ||
342 | * Reset the condition match flag to denote completion of | ||
343 | * exception handling. | ||
344 | */ | ||
345 | sh_ubc->clear_triggered_mask(event_mask); | ||
346 | |||
347 | /* | ||
348 | * bp can be NULL due to concurrent perf counter | ||
349 | * removing. | ||
350 | */ | ||
351 | if (!bp) { | ||
352 | rcu_read_unlock(); | ||
353 | break; | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * Don't restore the channel if the breakpoint is from | ||
358 | * ptrace, as it always operates in one-shot mode. | ||
359 | */ | ||
360 | if (bp->overflow_handler == ptrace_triggered) | ||
361 | resume_mask &= ~(1 << i); | ||
362 | |||
363 | perf_bp_event(bp, args->regs); | ||
364 | |||
365 | /* Deliver the signal to userspace */ | ||
366 | if (arch_check_va_in_userspace(bp->attr.bp_addr, | ||
367 | bp->attr.bp_len)) { | ||
368 | siginfo_t info; | ||
369 | |||
370 | info.si_signo = args->signr; | ||
371 | info.si_errno = notifier_to_errno(rc); | ||
372 | info.si_code = TRAP_HWBKPT; | ||
373 | |||
374 | force_sig_info(args->signr, &info, current); | ||
375 | } | ||
376 | |||
377 | rcu_read_unlock(); | ||
378 | } | ||
379 | |||
380 | if (cmf == 0) | ||
381 | rc = NOTIFY_DONE; | ||
382 | |||
383 | sh_ubc->enable_all(resume_mask); | ||
384 | |||
385 | put_cpu(); | ||
386 | |||
387 | return rc; | ||
388 | } | ||
389 | |||
390 | BUILD_TRAP_HANDLER(breakpoint) | ||
391 | { | ||
392 | unsigned long ex = lookup_exception_vector(); | ||
393 | TRAP_HANDLER_DECL; | ||
394 | |||
395 | notify_die(DIE_BREAKPOINT, "breakpoint", regs, 0, ex, SIGTRAP); | ||
396 | } | ||
397 | |||
398 | /* | ||
399 | * Handle debug exception notifications. | ||
400 | */ | ||
401 | int __kprobes hw_breakpoint_exceptions_notify(struct notifier_block *unused, | ||
402 | unsigned long val, void *data) | ||
403 | { | ||
404 | struct die_args *args = data; | ||
405 | |||
406 | if (val != DIE_BREAKPOINT) | ||
407 | return NOTIFY_DONE; | ||
408 | |||
409 | /* | ||
410 | * If the breakpoint hasn't been triggered by the UBC, it's | ||
411 | * probably from a debugger, so don't do anything more here. | ||
412 | * | ||
413 | * This also permits the UBC interface clock to remain off for | ||
414 | * non-UBC breakpoints, as we don't need to check the triggered | ||
415 | * or active channel masks. | ||
416 | */ | ||
417 | if (args->trapnr != sh_ubc->trap_nr) | ||
418 | return NOTIFY_DONE; | ||
419 | |||
420 | return hw_breakpoint_handler(data); | ||
421 | } | ||
422 | |||
423 | void hw_breakpoint_pmu_read(struct perf_event *bp) | ||
424 | { | ||
425 | /* TODO */ | ||
426 | } | ||
427 | |||
428 | void hw_breakpoint_pmu_unthrottle(struct perf_event *bp) | ||
429 | { | ||
430 | /* TODO */ | ||
431 | } | ||
432 | |||
433 | int register_sh_ubc(struct sh_ubc *ubc) | ||
434 | { | ||
435 | /* Bail if it's already assigned */ | ||
436 | if (sh_ubc != &ubc_dummy) | ||
437 | return -EBUSY; | ||
438 | sh_ubc = ubc; | ||
439 | |||
440 | pr_info("HW Breakpoints: %s UBC support registered\n", ubc->name); | ||
441 | |||
442 | WARN_ON(ubc->num_events > HBP_NUM); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c index 27ff2dc093c7..273f890b17ae 100644 --- a/arch/sh/kernel/idle.c +++ b/arch/sh/kernel/idle.c | |||
@@ -20,10 +20,9 @@ | |||
20 | #include <asm/system.h> | 20 | #include <asm/system.h> |
21 | #include <asm/atomic.h> | 21 | #include <asm/atomic.h> |
22 | 22 | ||
23 | void (*pm_idle)(void) = NULL; | ||
24 | |||
23 | static int hlt_counter; | 25 | static int hlt_counter; |
24 | void (*pm_idle)(void); | ||
25 | void (*pm_power_off)(void); | ||
26 | EXPORT_SYMBOL(pm_power_off); | ||
27 | 26 | ||
28 | static int __init nohlt_setup(char *__unused) | 27 | static int __init nohlt_setup(char *__unused) |
29 | { | 28 | { |
@@ -39,52 +38,107 @@ static int __init hlt_setup(char *__unused) | |||
39 | } | 38 | } |
40 | __setup("hlt", hlt_setup); | 39 | __setup("hlt", hlt_setup); |
41 | 40 | ||
41 | static inline int hlt_works(void) | ||
42 | { | ||
43 | return !hlt_counter; | ||
44 | } | ||
45 | |||
46 | /* | ||
47 | * On SMP it's slightly faster (but much more power-consuming!) | ||
48 | * to poll the ->work.need_resched flag instead of waiting for the | ||
49 | * cross-CPU IPI to arrive. Use this option with caution. | ||
50 | */ | ||
51 | static void poll_idle(void) | ||
52 | { | ||
53 | local_irq_enable(); | ||
54 | while (!need_resched()) | ||
55 | cpu_relax(); | ||
56 | } | ||
57 | |||
42 | void default_idle(void) | 58 | void default_idle(void) |
43 | { | 59 | { |
44 | if (!hlt_counter) { | 60 | if (hlt_works()) { |
45 | clear_thread_flag(TIF_POLLING_NRFLAG); | 61 | clear_thread_flag(TIF_POLLING_NRFLAG); |
46 | smp_mb__after_clear_bit(); | 62 | smp_mb__after_clear_bit(); |
47 | set_bl_bit(); | ||
48 | stop_critical_timings(); | ||
49 | 63 | ||
50 | while (!need_resched()) | 64 | set_bl_bit(); |
65 | if (!need_resched()) { | ||
66 | local_irq_enable(); | ||
51 | cpu_sleep(); | 67 | cpu_sleep(); |
68 | } else | ||
69 | local_irq_enable(); | ||
52 | 70 | ||
53 | start_critical_timings(); | ||
54 | clear_bl_bit(); | ||
55 | set_thread_flag(TIF_POLLING_NRFLAG); | 71 | set_thread_flag(TIF_POLLING_NRFLAG); |
72 | clear_bl_bit(); | ||
56 | } else | 73 | } else |
57 | while (!need_resched()) | 74 | poll_idle(); |
58 | cpu_relax(); | ||
59 | } | 75 | } |
60 | 76 | ||
77 | /* | ||
78 | * The idle thread. There's no useful work to be done, so just try to conserve | ||
79 | * power and have a low exit latency (ie sit in a loop waiting for somebody to | ||
80 | * say that they'd like to reschedule) | ||
81 | */ | ||
61 | void cpu_idle(void) | 82 | void cpu_idle(void) |
62 | { | 83 | { |
84 | unsigned int cpu = smp_processor_id(); | ||
85 | |||
63 | set_thread_flag(TIF_POLLING_NRFLAG); | 86 | set_thread_flag(TIF_POLLING_NRFLAG); |
64 | 87 | ||
65 | /* endless idle loop with no priority at all */ | 88 | /* endless idle loop with no priority at all */ |
66 | while (1) { | 89 | while (1) { |
67 | void (*idle)(void) = pm_idle; | 90 | tick_nohz_stop_sched_tick(1); |
68 | 91 | ||
69 | if (!idle) | 92 | while (!need_resched() && cpu_online(cpu)) { |
70 | idle = default_idle; | 93 | check_pgt_cache(); |
94 | rmb(); | ||
71 | 95 | ||
72 | tick_nohz_stop_sched_tick(1); | 96 | local_irq_disable(); |
73 | while (!need_resched()) | 97 | /* Don't trace irqs off for idle */ |
74 | idle(); | 98 | stop_critical_timings(); |
75 | tick_nohz_restart_sched_tick(); | 99 | pm_idle(); |
100 | /* | ||
101 | * Sanity check to ensure that pm_idle() returns | ||
102 | * with IRQs enabled | ||
103 | */ | ||
104 | WARN_ON(irqs_disabled()); | ||
105 | start_critical_timings(); | ||
106 | } | ||
76 | 107 | ||
108 | tick_nohz_restart_sched_tick(); | ||
77 | preempt_enable_no_resched(); | 109 | preempt_enable_no_resched(); |
78 | schedule(); | 110 | schedule(); |
79 | preempt_disable(); | 111 | preempt_disable(); |
80 | check_pgt_cache(); | ||
81 | } | 112 | } |
82 | } | 113 | } |
83 | 114 | ||
115 | void __init select_idle_routine(void) | ||
116 | { | ||
117 | /* | ||
118 | * If a platform has set its own idle routine, leave it alone. | ||
119 | */ | ||
120 | if (pm_idle) | ||
121 | return; | ||
122 | |||
123 | if (hlt_works()) | ||
124 | pm_idle = default_idle; | ||
125 | else | ||
126 | pm_idle = poll_idle; | ||
127 | } | ||
128 | |||
84 | static void do_nothing(void *unused) | 129 | static void do_nothing(void *unused) |
85 | { | 130 | { |
86 | } | 131 | } |
87 | 132 | ||
133 | void stop_this_cpu(void *unused) | ||
134 | { | ||
135 | local_irq_disable(); | ||
136 | cpu_clear(smp_processor_id(), cpu_online_map); | ||
137 | |||
138 | for (;;) | ||
139 | cpu_sleep(); | ||
140 | } | ||
141 | |||
88 | /* | 142 | /* |
89 | * cpu_idle_wait - Used to ensure that all the CPUs discard old value of | 143 | * cpu_idle_wait - Used to ensure that all the CPUs discard old value of |
90 | * pm_idle and update to new pm_idle value. Required while changing pm_idle | 144 | * pm_idle and update to new pm_idle value. Required while changing pm_idle |
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index b8fa6524760a..e1e1dbd19557 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #define dummy_read() | 24 | #define dummy_read() |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | unsigned long generic_io_base; | 27 | unsigned long generic_io_base = 0; |
28 | 28 | ||
29 | u8 generic_inb(unsigned long port) | 29 | u8 generic_inb(unsigned long port) |
30 | { | 30 | { |
@@ -147,8 +147,10 @@ void generic_outsl(unsigned long port, const void *src, unsigned long count) | |||
147 | 147 | ||
148 | void __iomem *generic_ioport_map(unsigned long addr, unsigned int size) | 148 | void __iomem *generic_ioport_map(unsigned long addr, unsigned int size) |
149 | { | 149 | { |
150 | #ifdef P1SEG | ||
150 | if (PXSEG(addr) >= P1SEG) | 151 | if (PXSEG(addr) >= P1SEG) |
151 | return (void __iomem *)addr; | 152 | return (void __iomem *)addr; |
153 | #endif | ||
152 | 154 | ||
153 | return (void __iomem *)(addr + generic_io_base); | 155 | return (void __iomem *)(addr + generic_io_base); |
154 | } | 156 | } |
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c index 69be603aa2d7..4a8bb4eeb8ad 100644 --- a/arch/sh/kernel/io_trapped.c +++ b/arch/sh/kernel/io_trapped.c | |||
@@ -184,31 +184,31 @@ static unsigned long long copy_word(unsigned long src_addr, int src_len, | |||
184 | 184 | ||
185 | switch (src_len) { | 185 | switch (src_len) { |
186 | case 1: | 186 | case 1: |
187 | tmp = ctrl_inb(src_addr); | 187 | tmp = __raw_readb(src_addr); |
188 | break; | 188 | break; |
189 | case 2: | 189 | case 2: |
190 | tmp = ctrl_inw(src_addr); | 190 | tmp = __raw_readw(src_addr); |
191 | break; | 191 | break; |
192 | case 4: | 192 | case 4: |
193 | tmp = ctrl_inl(src_addr); | 193 | tmp = __raw_readl(src_addr); |
194 | break; | 194 | break; |
195 | case 8: | 195 | case 8: |
196 | tmp = ctrl_inq(src_addr); | 196 | tmp = __raw_readq(src_addr); |
197 | break; | 197 | break; |
198 | } | 198 | } |
199 | 199 | ||
200 | switch (dst_len) { | 200 | switch (dst_len) { |
201 | case 1: | 201 | case 1: |
202 | ctrl_outb(tmp, dst_addr); | 202 | __raw_writeb(tmp, dst_addr); |
203 | break; | 203 | break; |
204 | case 2: | 204 | case 2: |
205 | ctrl_outw(tmp, dst_addr); | 205 | __raw_writew(tmp, dst_addr); |
206 | break; | 206 | break; |
207 | case 4: | 207 | case 4: |
208 | ctrl_outl(tmp, dst_addr); | 208 | __raw_writel(tmp, dst_addr); |
209 | break; | 209 | break; |
210 | case 8: | 210 | case 8: |
211 | ctrl_outq(tmp, dst_addr); | 211 | __raw_writeq(tmp, dst_addr); |
212 | break; | 212 | break; |
213 | } | 213 | } |
214 | 214 | ||
@@ -271,6 +271,8 @@ int handle_trapped_io(struct pt_regs *regs, unsigned long address) | |||
271 | insn_size_t instruction; | 271 | insn_size_t instruction; |
272 | int tmp; | 272 | int tmp; |
273 | 273 | ||
274 | if (trapped_io_disable) | ||
275 | return 0; | ||
274 | if (!lookup_tiop(address)) | 276 | if (!lookup_tiop(address)) |
275 | return 0; | 277 | return 0; |
276 | 278 | ||
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index eac7da772fc2..d2d41d046657 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c | |||
@@ -37,7 +37,15 @@ void ack_bad_irq(unsigned int irq) | |||
37 | */ | 37 | */ |
38 | static int show_other_interrupts(struct seq_file *p, int prec) | 38 | static int show_other_interrupts(struct seq_file *p, int prec) |
39 | { | 39 | { |
40 | int j; | ||
41 | |||
42 | seq_printf(p, "%*s: ", prec, "NMI"); | ||
43 | for_each_online_cpu(j) | ||
44 | seq_printf(p, "%10u ", irq_stat[j].__nmi_count); | ||
45 | seq_printf(p, " Non-maskable interrupts\n"); | ||
46 | |||
40 | seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); | 47 | seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); |
48 | |||
41 | return 0; | 49 | return 0; |
42 | } | 50 | } |
43 | 51 | ||
@@ -68,7 +76,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
68 | if (!desc) | 76 | if (!desc) |
69 | return 0; | 77 | return 0; |
70 | 78 | ||
71 | spin_lock_irqsave(&desc->lock, flags); | 79 | raw_spin_lock_irqsave(&desc->lock, flags); |
72 | for_each_online_cpu(j) | 80 | for_each_online_cpu(j) |
73 | any_count |= kstat_irqs_cpu(i, j); | 81 | any_count |= kstat_irqs_cpu(i, j); |
74 | action = desc->action; | 82 | action = desc->action; |
@@ -89,7 +97,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
89 | 97 | ||
90 | seq_putc(p, '\n'); | 98 | seq_putc(p, '\n'); |
91 | out: | 99 | out: |
92 | spin_unlock_irqrestore(&desc->lock, flags); | 100 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
93 | return 0; | 101 | return 0; |
94 | } | 102 | } |
95 | #endif | 103 | #endif |
@@ -255,6 +263,12 @@ void __init init_IRQ(void) | |||
255 | { | 263 | { |
256 | plat_irq_setup(); | 264 | plat_irq_setup(); |
257 | 265 | ||
266 | /* | ||
267 | * Pin any of the legacy IRQ vectors that haven't already been | ||
268 | * grabbed by the platform | ||
269 | */ | ||
270 | reserve_irq_legacy(); | ||
271 | |||
258 | /* Perform the machine specific initialisation */ | 272 | /* Perform the machine specific initialisation */ |
259 | if (sh_mv.mv_init_irq) | 273 | if (sh_mv.mv_init_irq) |
260 | sh_mv.mv_init_irq(); | 274 | sh_mv.mv_init_irq(); |
diff --git a/arch/sh/kernel/irq_32.c b/arch/sh/kernel/irq_32.c new file mode 100644 index 000000000000..e33ab15831f9 --- /dev/null +++ b/arch/sh/kernel/irq_32.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * SHcompact irqflags support | ||
3 | * | ||
4 | * Copyright (C) 2006 - 2009 Paul Mundt | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | #include <linux/irqflags.h> | ||
11 | #include <linux/module.h> | ||
12 | |||
13 | void notrace raw_local_irq_restore(unsigned long flags) | ||
14 | { | ||
15 | unsigned long __dummy0, __dummy1; | ||
16 | |||
17 | if (flags == RAW_IRQ_DISABLED) { | ||
18 | __asm__ __volatile__ ( | ||
19 | "stc sr, %0\n\t" | ||
20 | "or #0xf0, %0\n\t" | ||
21 | "ldc %0, sr\n\t" | ||
22 | : "=&z" (__dummy0) | ||
23 | : /* no inputs */ | ||
24 | : "memory" | ||
25 | ); | ||
26 | } else { | ||
27 | __asm__ __volatile__ ( | ||
28 | "stc sr, %0\n\t" | ||
29 | "and %1, %0\n\t" | ||
30 | #ifdef CONFIG_CPU_HAS_SR_RB | ||
31 | "stc r6_bank, %1\n\t" | ||
32 | "or %1, %0\n\t" | ||
33 | #endif | ||
34 | "ldc %0, sr\n\t" | ||
35 | : "=&r" (__dummy0), "=r" (__dummy1) | ||
36 | : "1" (~RAW_IRQ_DISABLED) | ||
37 | : "memory" | ||
38 | ); | ||
39 | } | ||
40 | } | ||
41 | EXPORT_SYMBOL(raw_local_irq_restore); | ||
42 | |||
43 | unsigned long notrace __raw_local_save_flags(void) | ||
44 | { | ||
45 | unsigned long flags; | ||
46 | |||
47 | __asm__ __volatile__ ( | ||
48 | "stc sr, %0\n\t" | ||
49 | "and #0xf0, %0\n\t" | ||
50 | : "=&z" (flags) | ||
51 | : /* no inputs */ | ||
52 | : "memory" | ||
53 | ); | ||
54 | |||
55 | return flags; | ||
56 | } | ||
57 | EXPORT_SYMBOL(__raw_local_save_flags); | ||
diff --git a/arch/sh/kernel/irq_64.c b/arch/sh/kernel/irq_64.c new file mode 100644 index 000000000000..32365ba0e039 --- /dev/null +++ b/arch/sh/kernel/irq_64.c | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * SHmedia irqflags support | ||
3 | * | ||
4 | * Copyright (C) 2006 - 2009 Paul Mundt | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | #include <linux/irqflags.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <cpu/registers.h> | ||
13 | |||
14 | void notrace raw_local_irq_restore(unsigned long flags) | ||
15 | { | ||
16 | unsigned long long __dummy; | ||
17 | |||
18 | if (flags == RAW_IRQ_DISABLED) { | ||
19 | __asm__ __volatile__ ( | ||
20 | "getcon " __SR ", %0\n\t" | ||
21 | "or %0, %1, %0\n\t" | ||
22 | "putcon %0, " __SR "\n\t" | ||
23 | : "=&r" (__dummy) | ||
24 | : "r" (RAW_IRQ_DISABLED) | ||
25 | ); | ||
26 | } else { | ||
27 | __asm__ __volatile__ ( | ||
28 | "getcon " __SR ", %0\n\t" | ||
29 | "and %0, %1, %0\n\t" | ||
30 | "putcon %0, " __SR "\n\t" | ||
31 | : "=&r" (__dummy) | ||
32 | : "r" (~RAW_IRQ_DISABLED) | ||
33 | ); | ||
34 | } | ||
35 | } | ||
36 | EXPORT_SYMBOL(raw_local_irq_restore); | ||
37 | |||
38 | unsigned long notrace __raw_local_save_flags(void) | ||
39 | { | ||
40 | unsigned long flags; | ||
41 | |||
42 | __asm__ __volatile__ ( | ||
43 | "getcon " __SR ", %0\n\t" | ||
44 | "and %0, %1, %0" | ||
45 | : "=&r" (flags) | ||
46 | : "r" (RAW_IRQ_DISABLED) | ||
47 | ); | ||
48 | |||
49 | return flags; | ||
50 | } | ||
51 | EXPORT_SYMBOL(__raw_local_save_flags); | ||
diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c index 3e532d0d4a5c..70c69659b846 100644 --- a/arch/sh/kernel/kgdb.c +++ b/arch/sh/kernel/kgdb.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * SuperH KGDB support | 2 | * SuperH KGDB support |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Paul Mundt | 4 | * Copyright (C) 2008 - 2009 Paul Mundt |
5 | * | 5 | * |
6 | * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel. | 6 | * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel. |
7 | * | 7 | * |
@@ -251,24 +251,60 @@ BUILD_TRAP_HANDLER(singlestep) | |||
251 | local_irq_restore(flags); | 251 | local_irq_restore(flags); |
252 | } | 252 | } |
253 | 253 | ||
254 | static int __kgdb_notify(struct die_args *args, unsigned long cmd) | ||
255 | { | ||
256 | int ret; | ||
257 | |||
258 | switch (cmd) { | ||
259 | case DIE_BREAKPOINT: | ||
260 | /* | ||
261 | * This means a user thread is single stepping | ||
262 | * a system call which should be ignored | ||
263 | */ | ||
264 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
265 | return NOTIFY_DONE; | ||
266 | |||
267 | ret = kgdb_handle_exception(args->trapnr & 0xff, args->signr, | ||
268 | args->err, args->regs); | ||
269 | if (ret) | ||
270 | return NOTIFY_DONE; | ||
271 | |||
272 | break; | ||
273 | } | ||
254 | 274 | ||
255 | BUILD_TRAP_HANDLER(breakpoint) | 275 | return NOTIFY_STOP; |
276 | } | ||
277 | |||
278 | static int | ||
279 | kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) | ||
256 | { | 280 | { |
257 | unsigned long flags; | 281 | unsigned long flags; |
258 | TRAP_HANDLER_DECL; | 282 | int ret; |
259 | 283 | ||
260 | local_irq_save(flags); | 284 | local_irq_save(flags); |
261 | kgdb_handle_exception(vec >> 2, SIGTRAP, 0, regs); | 285 | ret = __kgdb_notify(ptr, cmd); |
262 | local_irq_restore(flags); | 286 | local_irq_restore(flags); |
287 | |||
288 | return ret; | ||
263 | } | 289 | } |
264 | 290 | ||
291 | static struct notifier_block kgdb_notifier = { | ||
292 | .notifier_call = kgdb_notify, | ||
293 | |||
294 | /* | ||
295 | * Lowest-prio notifier priority, we want to be notified last: | ||
296 | */ | ||
297 | .priority = -INT_MAX, | ||
298 | }; | ||
299 | |||
265 | int kgdb_arch_init(void) | 300 | int kgdb_arch_init(void) |
266 | { | 301 | { |
267 | return 0; | 302 | return register_die_notifier(&kgdb_notifier); |
268 | } | 303 | } |
269 | 304 | ||
270 | void kgdb_arch_exit(void) | 305 | void kgdb_arch_exit(void) |
271 | { | 306 | { |
307 | unregister_die_notifier(&kgdb_notifier); | ||
272 | } | 308 | } |
273 | 309 | ||
274 | struct kgdb_arch arch_kgdb_ops = { | 310 | struct kgdb_arch arch_kgdb_ops = { |
diff --git a/arch/sh/kernel/kprobes.c b/arch/sh/kernel/kprobes.c index c96850b061fb..4049d99f76e1 100644 --- a/arch/sh/kernel/kprobes.c +++ b/arch/sh/kernel/kprobes.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/ptrace.h> | 13 | #include <linux/ptrace.h> |
14 | #include <linux/preempt.h> | 14 | #include <linux/preempt.h> |
15 | #include <linux/kdebug.h> | 15 | #include <linux/kdebug.h> |
16 | #include <linux/slab.h> | ||
16 | #include <asm/cacheflush.h> | 17 | #include <asm/cacheflush.h> |
17 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
18 | 19 | ||
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index 7ea2704ea033..7672141c841b 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <asm/mmu_context.h> | 21 | #include <asm/mmu_context.h> |
22 | #include <asm/io.h> | 22 | #include <asm/io.h> |
23 | #include <asm/cacheflush.h> | 23 | #include <asm/cacheflush.h> |
24 | #include <asm/sh_bios.h> | ||
25 | #include <asm/reboot.h> | ||
24 | 26 | ||
25 | typedef void (*relocate_new_kernel_t)(unsigned long indirection_page, | 27 | typedef void (*relocate_new_kernel_t)(unsigned long indirection_page, |
26 | unsigned long reboot_code_buffer, | 28 | unsigned long reboot_code_buffer, |
@@ -28,15 +30,11 @@ typedef void (*relocate_new_kernel_t)(unsigned long indirection_page, | |||
28 | 30 | ||
29 | extern const unsigned char relocate_new_kernel[]; | 31 | extern const unsigned char relocate_new_kernel[]; |
30 | extern const unsigned int relocate_new_kernel_size; | 32 | extern const unsigned int relocate_new_kernel_size; |
31 | extern void *gdb_vbr_vector; | ||
32 | extern void *vbr_base; | 33 | extern void *vbr_base; |
33 | 34 | ||
34 | void machine_shutdown(void) | 35 | void native_machine_crash_shutdown(struct pt_regs *regs) |
35 | { | ||
36 | } | ||
37 | |||
38 | void machine_crash_shutdown(struct pt_regs *regs) | ||
39 | { | 36 | { |
37 | /* Nothing to do for UP, but definitely broken for SMP.. */ | ||
40 | } | 38 | } |
41 | 39 | ||
42 | /* | 40 | /* |
@@ -46,12 +44,6 @@ void machine_crash_shutdown(struct pt_regs *regs) | |||
46 | */ | 44 | */ |
47 | int machine_kexec_prepare(struct kimage *image) | 45 | int machine_kexec_prepare(struct kimage *image) |
48 | { | 46 | { |
49 | /* older versions of kexec-tools are passing | ||
50 | * the zImage entry point as a virtual address. | ||
51 | */ | ||
52 | if (image->start != PHYSADDR(image->start)) | ||
53 | return -EINVAL; /* upgrade your kexec-tools */ | ||
54 | |||
55 | return 0; | 47 | return 0; |
56 | } | 48 | } |
57 | 49 | ||
@@ -123,11 +115,7 @@ void machine_kexec(struct kimage *image) | |||
123 | kexec_info(image); | 115 | kexec_info(image); |
124 | flush_cache_all(); | 116 | flush_cache_all(); |
125 | 117 | ||
126 | #if defined(CONFIG_SH_STANDARD_BIOS) | 118 | sh_bios_vbr_reload(); |
127 | asm volatile("ldc %0, vbr" : | ||
128 | : "r" (((unsigned long) gdb_vbr_vector) - 0x100) | ||
129 | : "memory"); | ||
130 | #endif | ||
131 | 119 | ||
132 | /* now call it */ | 120 | /* now call it */ |
133 | rnk = (relocate_new_kernel_t) reboot_code_buffer; | 121 | rnk = (relocate_new_kernel_t) reboot_code_buffer; |
diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c index cbce639b108a..1652340ba3f2 100644 --- a/arch/sh/kernel/machvec.c +++ b/arch/sh/kernel/machvec.c | |||
@@ -135,5 +135,9 @@ void __init sh_mv_setup(void) | |||
135 | if (!sh_mv.mv_nr_irqs) | 135 | if (!sh_mv.mv_nr_irqs) |
136 | sh_mv.mv_nr_irqs = NR_IRQS; | 136 | sh_mv.mv_nr_irqs = NR_IRQS; |
137 | 137 | ||
138 | #ifdef P2SEG | ||
138 | __set_io_port_base(P2SEG); | 139 | __set_io_port_base(P2SEG); |
140 | #else | ||
141 | __set_io_port_base(0); | ||
142 | #endif | ||
139 | } | 143 | } |
diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c index c2efdcde266f..43adddfe4c04 100644 --- a/arch/sh/kernel/module.c +++ b/arch/sh/kernel/module.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/string.h> | 32 | #include <linux/string.h> |
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <asm/unaligned.h> | 34 | #include <asm/unaligned.h> |
35 | #include <asm/dwarf.h> | ||
35 | 36 | ||
36 | void *module_alloc(unsigned long size) | 37 | void *module_alloc(unsigned long size) |
37 | { | 38 | { |
@@ -145,10 +146,16 @@ int module_finalize(const Elf_Ehdr *hdr, | |||
145 | const Elf_Shdr *sechdrs, | 146 | const Elf_Shdr *sechdrs, |
146 | struct module *me) | 147 | struct module *me) |
147 | { | 148 | { |
148 | return module_bug_finalize(hdr, sechdrs, me); | 149 | int ret = 0; |
150 | |||
151 | ret |= module_dwarf_finalize(hdr, sechdrs, me); | ||
152 | ret |= module_bug_finalize(hdr, sechdrs, me); | ||
153 | |||
154 | return ret; | ||
149 | } | 155 | } |
150 | 156 | ||
151 | void module_arch_cleanup(struct module *mod) | 157 | void module_arch_cleanup(struct module *mod) |
152 | { | 158 | { |
153 | module_bug_cleanup(mod); | 159 | module_bug_cleanup(mod); |
160 | module_dwarf_cleanup(mod); | ||
154 | } | 161 | } |
diff --git a/arch/sh/kernel/perf_callchain.c b/arch/sh/kernel/perf_callchain.c new file mode 100644 index 000000000000..a9dd3abde28e --- /dev/null +++ b/arch/sh/kernel/perf_callchain.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * Performance event callchain support - SuperH architecture code | ||
3 | * | ||
4 | * Copyright (C) 2009 Paul Mundt | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/sched.h> | ||
12 | #include <linux/perf_event.h> | ||
13 | #include <linux/percpu.h> | ||
14 | #include <asm/unwinder.h> | ||
15 | #include <asm/ptrace.h> | ||
16 | |||
17 | static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip) | ||
18 | { | ||
19 | if (entry->nr < PERF_MAX_STACK_DEPTH) | ||
20 | entry->ip[entry->nr++] = ip; | ||
21 | } | ||
22 | |||
23 | static void callchain_warning(void *data, char *msg) | ||
24 | { | ||
25 | } | ||
26 | |||
27 | static void | ||
28 | callchain_warning_symbol(void *data, char *msg, unsigned long symbol) | ||
29 | { | ||
30 | } | ||
31 | |||
32 | static int callchain_stack(void *data, char *name) | ||
33 | { | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static void callchain_address(void *data, unsigned long addr, int reliable) | ||
38 | { | ||
39 | struct perf_callchain_entry *entry = data; | ||
40 | |||
41 | if (reliable) | ||
42 | callchain_store(entry, addr); | ||
43 | } | ||
44 | |||
45 | static const struct stacktrace_ops callchain_ops = { | ||
46 | .warning = callchain_warning, | ||
47 | .warning_symbol = callchain_warning_symbol, | ||
48 | .stack = callchain_stack, | ||
49 | .address = callchain_address, | ||
50 | }; | ||
51 | |||
52 | static void | ||
53 | perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry) | ||
54 | { | ||
55 | callchain_store(entry, PERF_CONTEXT_KERNEL); | ||
56 | callchain_store(entry, regs->pc); | ||
57 | |||
58 | unwind_stack(NULL, regs, NULL, &callchain_ops, entry); | ||
59 | } | ||
60 | |||
61 | static void | ||
62 | perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry) | ||
63 | { | ||
64 | int is_user; | ||
65 | |||
66 | if (!regs) | ||
67 | return; | ||
68 | |||
69 | is_user = user_mode(regs); | ||
70 | |||
71 | if (is_user && current->state != TASK_RUNNING) | ||
72 | return; | ||
73 | |||
74 | /* | ||
75 | * Only the kernel side is implemented for now. | ||
76 | */ | ||
77 | if (!is_user) | ||
78 | perf_callchain_kernel(regs, entry); | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * No need for separate IRQ and NMI entries. | ||
83 | */ | ||
84 | static DEFINE_PER_CPU(struct perf_callchain_entry, callchain); | ||
85 | |||
86 | struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | ||
87 | { | ||
88 | struct perf_callchain_entry *entry = &__get_cpu_var(callchain); | ||
89 | |||
90 | entry->nr = 0; | ||
91 | |||
92 | perf_do_callchain(regs, entry); | ||
93 | |||
94 | return entry; | ||
95 | } | ||
diff --git a/arch/sh/kernel/perf_event.c b/arch/sh/kernel/perf_event.c new file mode 100644 index 000000000000..81b6de41ae5d --- /dev/null +++ b/arch/sh/kernel/perf_event.c | |||
@@ -0,0 +1,330 @@ | |||
1 | /* | ||
2 | * Performance event support framework for SuperH hardware counters. | ||
3 | * | ||
4 | * Copyright (C) 2009 Paul Mundt | ||
5 | * | ||
6 | * Heavily based on the x86 and PowerPC implementations. | ||
7 | * | ||
8 | * x86: | ||
9 | * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de> | ||
10 | * Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar | ||
11 | * Copyright (C) 2009 Jaswinder Singh Rajput | ||
12 | * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter | ||
13 | * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> | ||
14 | * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com> | ||
15 | * | ||
16 | * ppc: | ||
17 | * Copyright 2008-2009 Paul Mackerras, IBM Corporation. | ||
18 | * | ||
19 | * This file is subject to the terms and conditions of the GNU General Public | ||
20 | * License. See the file "COPYING" in the main directory of this archive | ||
21 | * for more details. | ||
22 | */ | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/perf_event.h> | ||
28 | #include <asm/processor.h> | ||
29 | |||
30 | struct cpu_hw_events { | ||
31 | struct perf_event *events[MAX_HWEVENTS]; | ||
32 | unsigned long used_mask[BITS_TO_LONGS(MAX_HWEVENTS)]; | ||
33 | unsigned long active_mask[BITS_TO_LONGS(MAX_HWEVENTS)]; | ||
34 | }; | ||
35 | |||
36 | DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); | ||
37 | |||
38 | static struct sh_pmu *sh_pmu __read_mostly; | ||
39 | |||
40 | /* Number of perf_events counting hardware events */ | ||
41 | static atomic_t num_events; | ||
42 | /* Used to avoid races in calling reserve/release_pmc_hardware */ | ||
43 | static DEFINE_MUTEX(pmc_reserve_mutex); | ||
44 | |||
45 | /* | ||
46 | * Stub these out for now, do something more profound later. | ||
47 | */ | ||
48 | int reserve_pmc_hardware(void) | ||
49 | { | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | void release_pmc_hardware(void) | ||
54 | { | ||
55 | } | ||
56 | |||
57 | static inline int sh_pmu_initialized(void) | ||
58 | { | ||
59 | return !!sh_pmu; | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Release the PMU if this is the last perf_event. | ||
64 | */ | ||
65 | static void hw_perf_event_destroy(struct perf_event *event) | ||
66 | { | ||
67 | if (!atomic_add_unless(&num_events, -1, 1)) { | ||
68 | mutex_lock(&pmc_reserve_mutex); | ||
69 | if (atomic_dec_return(&num_events) == 0) | ||
70 | release_pmc_hardware(); | ||
71 | mutex_unlock(&pmc_reserve_mutex); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | static int hw_perf_cache_event(int config, int *evp) | ||
76 | { | ||
77 | unsigned long type, op, result; | ||
78 | int ev; | ||
79 | |||
80 | if (!sh_pmu->cache_events) | ||
81 | return -EINVAL; | ||
82 | |||
83 | /* unpack config */ | ||
84 | type = config & 0xff; | ||
85 | op = (config >> 8) & 0xff; | ||
86 | result = (config >> 16) & 0xff; | ||
87 | |||
88 | if (type >= PERF_COUNT_HW_CACHE_MAX || | ||
89 | op >= PERF_COUNT_HW_CACHE_OP_MAX || | ||
90 | result >= PERF_COUNT_HW_CACHE_RESULT_MAX) | ||
91 | return -EINVAL; | ||
92 | |||
93 | ev = (*sh_pmu->cache_events)[type][op][result]; | ||
94 | if (ev == 0) | ||
95 | return -EOPNOTSUPP; | ||
96 | if (ev == -1) | ||
97 | return -EINVAL; | ||
98 | *evp = ev; | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static int __hw_perf_event_init(struct perf_event *event) | ||
103 | { | ||
104 | struct perf_event_attr *attr = &event->attr; | ||
105 | struct hw_perf_event *hwc = &event->hw; | ||
106 | int config = -1; | ||
107 | int err; | ||
108 | |||
109 | if (!sh_pmu_initialized()) | ||
110 | return -ENODEV; | ||
111 | |||
112 | /* | ||
113 | * All of the on-chip counters are "limited", in that they have | ||
114 | * no interrupts, and are therefore unable to do sampling without | ||
115 | * further work and timer assistance. | ||
116 | */ | ||
117 | if (hwc->sample_period) | ||
118 | return -EINVAL; | ||
119 | |||
120 | /* | ||
121 | * See if we need to reserve the counter. | ||
122 | * | ||
123 | * If no events are currently in use, then we have to take a | ||
124 | * mutex to ensure that we don't race with another task doing | ||
125 | * reserve_pmc_hardware or release_pmc_hardware. | ||
126 | */ | ||
127 | err = 0; | ||
128 | if (!atomic_inc_not_zero(&num_events)) { | ||
129 | mutex_lock(&pmc_reserve_mutex); | ||
130 | if (atomic_read(&num_events) == 0 && | ||
131 | reserve_pmc_hardware()) | ||
132 | err = -EBUSY; | ||
133 | else | ||
134 | atomic_inc(&num_events); | ||
135 | mutex_unlock(&pmc_reserve_mutex); | ||
136 | } | ||
137 | |||
138 | if (err) | ||
139 | return err; | ||
140 | |||
141 | event->destroy = hw_perf_event_destroy; | ||
142 | |||
143 | switch (attr->type) { | ||
144 | case PERF_TYPE_RAW: | ||
145 | config = attr->config & sh_pmu->raw_event_mask; | ||
146 | break; | ||
147 | case PERF_TYPE_HW_CACHE: | ||
148 | err = hw_perf_cache_event(attr->config, &config); | ||
149 | if (err) | ||
150 | return err; | ||
151 | break; | ||
152 | case PERF_TYPE_HARDWARE: | ||
153 | if (attr->config >= sh_pmu->max_events) | ||
154 | return -EINVAL; | ||
155 | |||
156 | config = sh_pmu->event_map(attr->config); | ||
157 | break; | ||
158 | } | ||
159 | |||
160 | if (config == -1) | ||
161 | return -EINVAL; | ||
162 | |||
163 | hwc->config |= config; | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static void sh_perf_event_update(struct perf_event *event, | ||
169 | struct hw_perf_event *hwc, int idx) | ||
170 | { | ||
171 | u64 prev_raw_count, new_raw_count; | ||
172 | s64 delta; | ||
173 | int shift = 0; | ||
174 | |||
175 | /* | ||
176 | * Depending on the counter configuration, they may or may not | ||
177 | * be chained, in which case the previous counter value can be | ||
178 | * updated underneath us if the lower-half overflows. | ||
179 | * | ||
180 | * Our tactic to handle this is to first atomically read and | ||
181 | * exchange a new raw count - then add that new-prev delta | ||
182 | * count to the generic counter atomically. | ||
183 | * | ||
184 | * As there is no interrupt associated with the overflow events, | ||
185 | * this is the simplest approach for maintaining consistency. | ||
186 | */ | ||
187 | again: | ||
188 | prev_raw_count = atomic64_read(&hwc->prev_count); | ||
189 | new_raw_count = sh_pmu->read(idx); | ||
190 | |||
191 | if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count, | ||
192 | new_raw_count) != prev_raw_count) | ||
193 | goto again; | ||
194 | |||
195 | /* | ||
196 | * Now we have the new raw value and have updated the prev | ||
197 | * timestamp already. We can now calculate the elapsed delta | ||
198 | * (counter-)time and add that to the generic counter. | ||
199 | * | ||
200 | * Careful, not all hw sign-extends above the physical width | ||
201 | * of the count. | ||
202 | */ | ||
203 | delta = (new_raw_count << shift) - (prev_raw_count << shift); | ||
204 | delta >>= shift; | ||
205 | |||
206 | atomic64_add(delta, &event->count); | ||
207 | } | ||
208 | |||
209 | static void sh_pmu_disable(struct perf_event *event) | ||
210 | { | ||
211 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
212 | struct hw_perf_event *hwc = &event->hw; | ||
213 | int idx = hwc->idx; | ||
214 | |||
215 | clear_bit(idx, cpuc->active_mask); | ||
216 | sh_pmu->disable(hwc, idx); | ||
217 | |||
218 | barrier(); | ||
219 | |||
220 | sh_perf_event_update(event, &event->hw, idx); | ||
221 | |||
222 | cpuc->events[idx] = NULL; | ||
223 | clear_bit(idx, cpuc->used_mask); | ||
224 | |||
225 | perf_event_update_userpage(event); | ||
226 | } | ||
227 | |||
228 | static int sh_pmu_enable(struct perf_event *event) | ||
229 | { | ||
230 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
231 | struct hw_perf_event *hwc = &event->hw; | ||
232 | int idx = hwc->idx; | ||
233 | |||
234 | if (test_and_set_bit(idx, cpuc->used_mask)) { | ||
235 | idx = find_first_zero_bit(cpuc->used_mask, sh_pmu->num_events); | ||
236 | if (idx == sh_pmu->num_events) | ||
237 | return -EAGAIN; | ||
238 | |||
239 | set_bit(idx, cpuc->used_mask); | ||
240 | hwc->idx = idx; | ||
241 | } | ||
242 | |||
243 | sh_pmu->disable(hwc, idx); | ||
244 | |||
245 | cpuc->events[idx] = event; | ||
246 | set_bit(idx, cpuc->active_mask); | ||
247 | |||
248 | sh_pmu->enable(hwc, idx); | ||
249 | |||
250 | perf_event_update_userpage(event); | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static void sh_pmu_read(struct perf_event *event) | ||
256 | { | ||
257 | sh_perf_event_update(event, &event->hw, event->hw.idx); | ||
258 | } | ||
259 | |||
260 | static const struct pmu pmu = { | ||
261 | .enable = sh_pmu_enable, | ||
262 | .disable = sh_pmu_disable, | ||
263 | .read = sh_pmu_read, | ||
264 | }; | ||
265 | |||
266 | const struct pmu *hw_perf_event_init(struct perf_event *event) | ||
267 | { | ||
268 | int err = __hw_perf_event_init(event); | ||
269 | if (unlikely(err)) { | ||
270 | if (event->destroy) | ||
271 | event->destroy(event); | ||
272 | return ERR_PTR(err); | ||
273 | } | ||
274 | |||
275 | return &pmu; | ||
276 | } | ||
277 | |||
278 | static void sh_pmu_setup(int cpu) | ||
279 | { | ||
280 | struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu); | ||
281 | |||
282 | memset(cpuhw, 0, sizeof(struct cpu_hw_events)); | ||
283 | } | ||
284 | |||
285 | static int __cpuinit | ||
286 | sh_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) | ||
287 | { | ||
288 | unsigned int cpu = (long)hcpu; | ||
289 | |||
290 | switch (action & ~CPU_TASKS_FROZEN) { | ||
291 | case CPU_UP_PREPARE: | ||
292 | sh_pmu_setup(cpu); | ||
293 | break; | ||
294 | |||
295 | default: | ||
296 | break; | ||
297 | } | ||
298 | |||
299 | return NOTIFY_OK; | ||
300 | } | ||
301 | |||
302 | void hw_perf_enable(void) | ||
303 | { | ||
304 | if (!sh_pmu_initialized()) | ||
305 | return; | ||
306 | |||
307 | sh_pmu->enable_all(); | ||
308 | } | ||
309 | |||
310 | void hw_perf_disable(void) | ||
311 | { | ||
312 | if (!sh_pmu_initialized()) | ||
313 | return; | ||
314 | |||
315 | sh_pmu->disable_all(); | ||
316 | } | ||
317 | |||
318 | int __cpuinit register_sh_pmu(struct sh_pmu *pmu) | ||
319 | { | ||
320 | if (sh_pmu) | ||
321 | return -EBUSY; | ||
322 | sh_pmu = pmu; | ||
323 | |||
324 | pr_info("Performance Events: %s support registered\n", pmu->name); | ||
325 | |||
326 | WARN_ON(pmu->num_events > MAX_HWEVENTS); | ||
327 | |||
328 | perf_cpu_notifier(sh_pmu_notifier); | ||
329 | return 0; | ||
330 | } | ||
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c new file mode 100644 index 000000000000..17f89aa4e1b3 --- /dev/null +++ b/arch/sh/kernel/process.c | |||
@@ -0,0 +1,101 @@ | |||
1 | #include <linux/mm.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/slab.h> | ||
4 | #include <linux/sched.h> | ||
5 | |||
6 | struct kmem_cache *task_xstate_cachep = NULL; | ||
7 | unsigned int xstate_size; | ||
8 | |||
9 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | ||
10 | { | ||
11 | *dst = *src; | ||
12 | |||
13 | if (src->thread.xstate) { | ||
14 | dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep, | ||
15 | GFP_KERNEL); | ||
16 | if (!dst->thread.xstate) | ||
17 | return -ENOMEM; | ||
18 | memcpy(dst->thread.xstate, src->thread.xstate, xstate_size); | ||
19 | } | ||
20 | |||
21 | return 0; | ||
22 | } | ||
23 | |||
24 | void free_thread_xstate(struct task_struct *tsk) | ||
25 | { | ||
26 | if (tsk->thread.xstate) { | ||
27 | kmem_cache_free(task_xstate_cachep, tsk->thread.xstate); | ||
28 | tsk->thread.xstate = NULL; | ||
29 | } | ||
30 | } | ||
31 | |||
32 | #if THREAD_SHIFT < PAGE_SHIFT | ||
33 | static struct kmem_cache *thread_info_cache; | ||
34 | |||
35 | struct thread_info *alloc_thread_info(struct task_struct *tsk) | ||
36 | { | ||
37 | struct thread_info *ti; | ||
38 | |||
39 | ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL); | ||
40 | if (unlikely(ti == NULL)) | ||
41 | return NULL; | ||
42 | #ifdef CONFIG_DEBUG_STACK_USAGE | ||
43 | memset(ti, 0, THREAD_SIZE); | ||
44 | #endif | ||
45 | return ti; | ||
46 | } | ||
47 | |||
48 | void free_thread_info(struct thread_info *ti) | ||
49 | { | ||
50 | free_thread_xstate(ti->task); | ||
51 | kmem_cache_free(thread_info_cache, ti); | ||
52 | } | ||
53 | |||
54 | void thread_info_cache_init(void) | ||
55 | { | ||
56 | thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE, | ||
57 | THREAD_SIZE, SLAB_PANIC, NULL); | ||
58 | } | ||
59 | #else | ||
60 | struct thread_info *alloc_thread_info(struct task_struct *tsk) | ||
61 | { | ||
62 | #ifdef CONFIG_DEBUG_STACK_USAGE | ||
63 | gfp_t mask = GFP_KERNEL | __GFP_ZERO; | ||
64 | #else | ||
65 | gfp_t mask = GFP_KERNEL; | ||
66 | #endif | ||
67 | return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER); | ||
68 | } | ||
69 | |||
70 | void free_thread_info(struct thread_info *ti) | ||
71 | { | ||
72 | free_thread_xstate(ti->task); | ||
73 | free_pages((unsigned long)ti, THREAD_SIZE_ORDER); | ||
74 | } | ||
75 | #endif /* THREAD_SHIFT < PAGE_SHIFT */ | ||
76 | |||
77 | void arch_task_cache_init(void) | ||
78 | { | ||
79 | if (!xstate_size) | ||
80 | return; | ||
81 | |||
82 | task_xstate_cachep = kmem_cache_create("task_xstate", xstate_size, | ||
83 | __alignof__(union thread_xstate), | ||
84 | SLAB_PANIC | SLAB_NOTRACK, NULL); | ||
85 | } | ||
86 | |||
87 | #ifdef CONFIG_SH_FPU_EMU | ||
88 | # define HAVE_SOFTFP 1 | ||
89 | #else | ||
90 | # define HAVE_SOFTFP 0 | ||
91 | #endif | ||
92 | |||
93 | void init_thread_xstate(void) | ||
94 | { | ||
95 | if (boot_cpu_data.flags & CPU_HAS_FPU) | ||
96 | xstate_size = sizeof(struct sh_fpu_hard_struct); | ||
97 | else if (HAVE_SOFTFP) | ||
98 | xstate_size = sizeof(struct sh_fpu_soft_struct); | ||
99 | else | ||
100 | xstate_size = 0; | ||
101 | } | ||
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 0673c4746be3..052981972ae6 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c | |||
@@ -15,66 +15,17 @@ | |||
15 | */ | 15 | */ |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/slab.h> | ||
18 | #include <linux/elfcore.h> | 19 | #include <linux/elfcore.h> |
19 | #include <linux/pm.h> | ||
20 | #include <linux/kallsyms.h> | 20 | #include <linux/kallsyms.h> |
21 | #include <linux/kexec.h> | ||
22 | #include <linux/kdebug.h> | ||
23 | #include <linux/tick.h> | ||
24 | #include <linux/reboot.h> | ||
25 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
26 | #include <linux/ftrace.h> | 22 | #include <linux/ftrace.h> |
27 | #include <linux/preempt.h> | 23 | #include <linux/hw_breakpoint.h> |
28 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
29 | #include <asm/mmu_context.h> | 25 | #include <asm/mmu_context.h> |
30 | #include <asm/pgalloc.h> | ||
31 | #include <asm/system.h> | 26 | #include <asm/system.h> |
32 | #include <asm/ubc.h> | ||
33 | #include <asm/fpu.h> | 27 | #include <asm/fpu.h> |
34 | #include <asm/syscalls.h> | 28 | #include <asm/syscalls.h> |
35 | #include <asm/watchdog.h> | ||
36 | |||
37 | int ubc_usercnt = 0; | ||
38 | |||
39 | #ifdef CONFIG_32BIT | ||
40 | static void watchdog_trigger_immediate(void) | ||
41 | { | ||
42 | sh_wdt_write_cnt(0xFF); | ||
43 | sh_wdt_write_csr(0xC2); | ||
44 | } | ||
45 | |||
46 | void machine_restart(char * __unused) | ||
47 | { | ||
48 | local_irq_disable(); | ||
49 | |||
50 | /* Use watchdog timer to trigger reset */ | ||
51 | watchdog_trigger_immediate(); | ||
52 | |||
53 | while (1) | ||
54 | cpu_sleep(); | ||
55 | } | ||
56 | #else | ||
57 | void machine_restart(char * __unused) | ||
58 | { | ||
59 | /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ | ||
60 | asm volatile("ldc %0, sr\n\t" | ||
61 | "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001)); | ||
62 | } | ||
63 | #endif | ||
64 | |||
65 | void machine_halt(void) | ||
66 | { | ||
67 | local_irq_disable(); | ||
68 | |||
69 | while (1) | ||
70 | cpu_sleep(); | ||
71 | } | ||
72 | |||
73 | void machine_power_off(void) | ||
74 | { | ||
75 | if (pm_power_off) | ||
76 | pm_power_off(); | ||
77 | } | ||
78 | 29 | ||
79 | void show_regs(struct pt_regs * regs) | 30 | void show_regs(struct pt_regs * regs) |
80 | { | 31 | { |
@@ -91,7 +42,7 @@ void show_regs(struct pt_regs * regs) | |||
91 | printk("PC : %08lx SP : %08lx SR : %08lx ", | 42 | printk("PC : %08lx SP : %08lx SR : %08lx ", |
92 | regs->pc, regs->regs[15], regs->sr); | 43 | regs->pc, regs->regs[15], regs->sr); |
93 | #ifdef CONFIG_MMU | 44 | #ifdef CONFIG_MMU |
94 | printk("TEA : %08x\n", ctrl_inl(MMU_TEA)); | 45 | printk("TEA : %08x\n", __raw_readl(MMU_TEA)); |
95 | #else | 46 | #else |
96 | printk("\n"); | 47 | printk("\n"); |
97 | #endif | 48 | #endif |
@@ -134,7 +85,10 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |||
134 | regs.regs[5] = (unsigned long)fn; | 85 | regs.regs[5] = (unsigned long)fn; |
135 | 86 | ||
136 | regs.pc = (unsigned long)kernel_thread_helper; | 87 | regs.pc = (unsigned long)kernel_thread_helper; |
137 | regs.sr = (1 << 30); | 88 | regs.sr = SR_MD; |
89 | #if defined(CONFIG_SH_FPU) | ||
90 | regs.sr |= SR_FD; | ||
91 | #endif | ||
138 | 92 | ||
139 | /* Ok, create the new process.. */ | 93 | /* Ok, create the new process.. */ |
140 | pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, | 94 | pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, |
@@ -142,22 +96,36 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |||
142 | 96 | ||
143 | return pid; | 97 | return pid; |
144 | } | 98 | } |
99 | EXPORT_SYMBOL(kernel_thread); | ||
100 | |||
101 | void start_thread(struct pt_regs *regs, unsigned long new_pc, | ||
102 | unsigned long new_sp) | ||
103 | { | ||
104 | set_fs(USER_DS); | ||
105 | |||
106 | regs->pr = 0; | ||
107 | regs->sr = SR_FD; | ||
108 | regs->pc = new_pc; | ||
109 | regs->regs[15] = new_sp; | ||
110 | |||
111 | free_thread_xstate(current); | ||
112 | } | ||
113 | EXPORT_SYMBOL(start_thread); | ||
145 | 114 | ||
146 | /* | 115 | /* |
147 | * Free current thread data structures etc.. | 116 | * Free current thread data structures etc.. |
148 | */ | 117 | */ |
149 | void exit_thread(void) | 118 | void exit_thread(void) |
150 | { | 119 | { |
151 | if (current->thread.ubc_pc) { | ||
152 | current->thread.ubc_pc = 0; | ||
153 | ubc_usercnt -= 1; | ||
154 | } | ||
155 | } | 120 | } |
156 | 121 | ||
157 | void flush_thread(void) | 122 | void flush_thread(void) |
158 | { | 123 | { |
159 | #if defined(CONFIG_SH_FPU) | ||
160 | struct task_struct *tsk = current; | 124 | struct task_struct *tsk = current; |
125 | |||
126 | flush_ptrace_hw_breakpoint(tsk); | ||
127 | |||
128 | #if defined(CONFIG_SH_FPU) | ||
161 | /* Forget lazy FPU state */ | 129 | /* Forget lazy FPU state */ |
162 | clear_fpu(tsk, task_pt_regs(tsk)); | 130 | clear_fpu(tsk, task_pt_regs(tsk)); |
163 | clear_used_math(); | 131 | clear_used_math(); |
@@ -186,6 +154,16 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | |||
186 | 154 | ||
187 | return fpvalid; | 155 | return fpvalid; |
188 | } | 156 | } |
157 | EXPORT_SYMBOL(dump_fpu); | ||
158 | |||
159 | /* | ||
160 | * This gets called before we allocate a new thread and copy | ||
161 | * the current task into it. | ||
162 | */ | ||
163 | void prepare_to_copy(struct task_struct *tsk) | ||
164 | { | ||
165 | unlazy_fpu(tsk, task_pt_regs(tsk)); | ||
166 | } | ||
189 | 167 | ||
190 | asmlinkage void ret_from_fork(void); | 168 | asmlinkage void ret_from_fork(void); |
191 | 169 | ||
@@ -195,17 +173,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
195 | { | 173 | { |
196 | struct thread_info *ti = task_thread_info(p); | 174 | struct thread_info *ti = task_thread_info(p); |
197 | struct pt_regs *childregs; | 175 | struct pt_regs *childregs; |
198 | #if defined(CONFIG_SH_FPU) || defined(CONFIG_SH_DSP) | ||
199 | struct task_struct *tsk = current; | ||
200 | #endif | ||
201 | |||
202 | #if defined(CONFIG_SH_FPU) | ||
203 | unlazy_fpu(tsk, regs); | ||
204 | p->thread.fpu = tsk->thread.fpu; | ||
205 | copy_to_stopped_child_used_math(p); | ||
206 | #endif | ||
207 | 176 | ||
208 | #if defined(CONFIG_SH_DSP) | 177 | #if defined(CONFIG_SH_DSP) |
178 | struct task_struct *tsk = current; | ||
179 | |||
209 | if (is_dsp_enabled(tsk)) { | 180 | if (is_dsp_enabled(tsk)) { |
210 | /* We can use the __save_dsp or just copy the struct: | 181 | /* We can use the __save_dsp or just copy the struct: |
211 | * __save_dsp(p); | 182 | * __save_dsp(p); |
@@ -224,6 +195,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
224 | } else { | 195 | } else { |
225 | childregs->regs[15] = (unsigned long)childregs; | 196 | childregs->regs[15] = (unsigned long)childregs; |
226 | ti->addr_limit = KERNEL_DS; | 197 | ti->addr_limit = KERNEL_DS; |
198 | ti->status &= ~TS_USEDFPU; | ||
199 | p->fpu_counter = 0; | ||
227 | } | 200 | } |
228 | 201 | ||
229 | if (clone_flags & CLONE_SETTLS) | 202 | if (clone_flags & CLONE_SETTLS) |
@@ -234,53 +207,11 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
234 | p->thread.sp = (unsigned long) childregs; | 207 | p->thread.sp = (unsigned long) childregs; |
235 | p->thread.pc = (unsigned long) ret_from_fork; | 208 | p->thread.pc = (unsigned long) ret_from_fork; |
236 | 209 | ||
237 | p->thread.ubc_pc = 0; | 210 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); |
238 | 211 | ||
239 | return 0; | 212 | return 0; |
240 | } | 213 | } |
241 | 214 | ||
242 | /* Tracing by user break controller. */ | ||
243 | static void ubc_set_tracing(int asid, unsigned long pc) | ||
244 | { | ||
245 | #if defined(CONFIG_CPU_SH4A) | ||
246 | unsigned long val; | ||
247 | |||
248 | val = (UBC_CBR_ID_INST | UBC_CBR_RW_READ | UBC_CBR_CE); | ||
249 | val |= (UBC_CBR_AIE | UBC_CBR_AIV_SET(asid)); | ||
250 | |||
251 | ctrl_outl(val, UBC_CBR0); | ||
252 | ctrl_outl(pc, UBC_CAR0); | ||
253 | ctrl_outl(0x0, UBC_CAMR0); | ||
254 | ctrl_outl(0x0, UBC_CBCR); | ||
255 | |||
256 | val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE); | ||
257 | ctrl_outl(val, UBC_CRR0); | ||
258 | |||
259 | /* Read UBC register that we wrote last, for checking update */ | ||
260 | val = ctrl_inl(UBC_CRR0); | ||
261 | |||
262 | #else /* CONFIG_CPU_SH4A */ | ||
263 | ctrl_outl(pc, UBC_BARA); | ||
264 | |||
265 | #ifdef CONFIG_MMU | ||
266 | ctrl_outb(asid, UBC_BASRA); | ||
267 | #endif | ||
268 | |||
269 | ctrl_outl(0, UBC_BAMRA); | ||
270 | |||
271 | if (current_cpu_data.type == CPU_SH7729 || | ||
272 | current_cpu_data.type == CPU_SH7710 || | ||
273 | current_cpu_data.type == CPU_SH7712 || | ||
274 | current_cpu_data.type == CPU_SH7203){ | ||
275 | ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA); | ||
276 | ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR); | ||
277 | } else { | ||
278 | ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA); | ||
279 | ctrl_outw(BRCR_PCBA, UBC_BRCR); | ||
280 | } | ||
281 | #endif /* CONFIG_CPU_SH4A */ | ||
282 | } | ||
283 | |||
284 | /* | 215 | /* |
285 | * switch_to(x,y) should switch tasks from x to y. | 216 | * switch_to(x,y) should switch tasks from x to y. |
286 | * | 217 | * |
@@ -288,9 +219,13 @@ static void ubc_set_tracing(int asid, unsigned long pc) | |||
288 | __notrace_funcgraph struct task_struct * | 219 | __notrace_funcgraph struct task_struct * |
289 | __switch_to(struct task_struct *prev, struct task_struct *next) | 220 | __switch_to(struct task_struct *prev, struct task_struct *next) |
290 | { | 221 | { |
291 | #if defined(CONFIG_SH_FPU) | 222 | struct thread_struct *next_t = &next->thread; |
223 | |||
292 | unlazy_fpu(prev, task_pt_regs(prev)); | 224 | unlazy_fpu(prev, task_pt_regs(prev)); |
293 | #endif | 225 | |
226 | /* we're going to use this soon, after a few expensive things */ | ||
227 | if (next->fpu_counter > 5) | ||
228 | prefetch(next_t->xstate); | ||
294 | 229 | ||
295 | #ifdef CONFIG_MMU | 230 | #ifdef CONFIG_MMU |
296 | /* | 231 | /* |
@@ -302,24 +237,13 @@ __switch_to(struct task_struct *prev, struct task_struct *next) | |||
302 | : "r" (task_thread_info(next))); | 237 | : "r" (task_thread_info(next))); |
303 | #endif | 238 | #endif |
304 | 239 | ||
305 | /* If no tasks are using the UBC, we're done */ | 240 | /* |
306 | if (ubc_usercnt == 0) | 241 | * If the task has used fpu the last 5 timeslices, just do a full |
307 | /* If no tasks are using the UBC, we're done */; | 242 | * restore of the math state immediately to avoid the trap; the |
308 | else if (next->thread.ubc_pc && next->mm) { | 243 | * chances of needing FPU soon are obviously high now |
309 | int asid = 0; | 244 | */ |
310 | #ifdef CONFIG_MMU | 245 | if (next->fpu_counter > 5) |
311 | asid |= cpu_asid(smp_processor_id(), next->mm); | 246 | __fpu_state_restore(); |
312 | #endif | ||
313 | ubc_set_tracing(asid, next->thread.ubc_pc); | ||
314 | } else { | ||
315 | #if defined(CONFIG_CPU_SH4A) | ||
316 | ctrl_outl(UBC_CBR_INIT, UBC_CBR0); | ||
317 | ctrl_outl(UBC_CRR_INIT, UBC_CRR0); | ||
318 | #else | ||
319 | ctrl_outw(0, UBC_BBRA); | ||
320 | ctrl_outw(0, UBC_BBRB); | ||
321 | #endif | ||
322 | } | ||
323 | 247 | ||
324 | return prev; | 248 | return prev; |
325 | } | 249 | } |
@@ -412,20 +336,3 @@ unsigned long get_wchan(struct task_struct *p) | |||
412 | 336 | ||
413 | return pc; | 337 | return pc; |
414 | } | 338 | } |
415 | |||
416 | asmlinkage void break_point_trap(void) | ||
417 | { | ||
418 | /* Clear tracing. */ | ||
419 | #if defined(CONFIG_CPU_SH4A) | ||
420 | ctrl_outl(UBC_CBR_INIT, UBC_CBR0); | ||
421 | ctrl_outl(UBC_CRR_INIT, UBC_CRR0); | ||
422 | #else | ||
423 | ctrl_outw(0, UBC_BBRA); | ||
424 | ctrl_outw(0, UBC_BBRB); | ||
425 | ctrl_outl(0, UBC_BRCR); | ||
426 | #endif | ||
427 | current->thread.ubc_pc = 0; | ||
428 | ubc_usercnt -= 1; | ||
429 | |||
430 | force_sig(SIGTRAP, current); | ||
431 | } | ||
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index 1192398ef582..d4ca6480e355 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/ptrace.h> | 22 | #include <linux/ptrace.h> |
23 | #include <linux/reboot.h> | 23 | #include <linux/reboot.h> |
24 | #include <linux/slab.h> | ||
24 | #include <linux/init.h> | 25 | #include <linux/init.h> |
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
26 | #include <linux/io.h> | 27 | #include <linux/io.h> |
@@ -32,30 +33,7 @@ | |||
32 | 33 | ||
33 | struct task_struct *last_task_used_math = NULL; | 34 | struct task_struct *last_task_used_math = NULL; |
34 | 35 | ||
35 | void machine_restart(char * __unused) | 36 | void show_regs(struct pt_regs *regs) |
36 | { | ||
37 | extern void phys_stext(void); | ||
38 | |||
39 | phys_stext(); | ||
40 | } | ||
41 | |||
42 | void machine_halt(void) | ||
43 | { | ||
44 | for (;;); | ||
45 | } | ||
46 | |||
47 | void machine_power_off(void) | ||
48 | { | ||
49 | __asm__ __volatile__ ( | ||
50 | "sleep\n\t" | ||
51 | "synci\n\t" | ||
52 | "nop;nop;nop;nop\n\t" | ||
53 | ); | ||
54 | |||
55 | panic("Unexpected wakeup!\n"); | ||
56 | } | ||
57 | |||
58 | void show_regs(struct pt_regs * regs) | ||
59 | { | 37 | { |
60 | unsigned long long ah, al, bh, bl, ch, cl; | 38 | unsigned long long ah, al, bh, bl, ch, cl; |
61 | 39 | ||
@@ -335,6 +313,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |||
335 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, | 313 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, |
336 | ®s, 0, NULL, NULL); | 314 | ®s, 0, NULL, NULL); |
337 | } | 315 | } |
316 | EXPORT_SYMBOL(kernel_thread); | ||
338 | 317 | ||
339 | /* | 318 | /* |
340 | * Free current thread data structures etc.. | 319 | * Free current thread data structures etc.. |
@@ -367,7 +346,7 @@ void exit_thread(void) | |||
367 | void flush_thread(void) | 346 | void flush_thread(void) |
368 | { | 347 | { |
369 | 348 | ||
370 | /* Called by fs/exec.c (flush_old_exec) to remove traces of a | 349 | /* Called by fs/exec.c (setup_new_exec) to remove traces of a |
371 | * previously running executable. */ | 350 | * previously running executable. */ |
372 | #ifdef CONFIG_SH_FPU | 351 | #ifdef CONFIG_SH_FPU |
373 | if (last_task_used_math == current) { | 352 | if (last_task_used_math == current) { |
@@ -403,13 +382,13 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | |||
403 | if (fpvalid) { | 382 | if (fpvalid) { |
404 | if (current == last_task_used_math) { | 383 | if (current == last_task_used_math) { |
405 | enable_fpu(); | 384 | enable_fpu(); |
406 | save_fpu(tsk, regs); | 385 | save_fpu(tsk); |
407 | disable_fpu(); | 386 | disable_fpu(); |
408 | last_task_used_math = 0; | 387 | last_task_used_math = 0; |
409 | regs->sr |= SR_FD; | 388 | regs->sr |= SR_FD; |
410 | } | 389 | } |
411 | 390 | ||
412 | memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); | 391 | memcpy(fpu, &tsk->thread.xstate->hardfpu, sizeof(*fpu)); |
413 | } | 392 | } |
414 | 393 | ||
415 | return fpvalid; | 394 | return fpvalid; |
@@ -417,6 +396,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | |||
417 | return 0; /* Task didn't use the fpu at all. */ | 396 | return 0; /* Task didn't use the fpu at all. */ |
418 | #endif | 397 | #endif |
419 | } | 398 | } |
399 | EXPORT_SYMBOL(dump_fpu); | ||
420 | 400 | ||
421 | asmlinkage void ret_from_fork(void); | 401 | asmlinkage void ret_from_fork(void); |
422 | 402 | ||
@@ -429,7 +409,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
429 | #ifdef CONFIG_SH_FPU | 409 | #ifdef CONFIG_SH_FPU |
430 | if(last_task_used_math == current) { | 410 | if(last_task_used_math == current) { |
431 | enable_fpu(); | 411 | enable_fpu(); |
432 | save_fpu(current, regs); | 412 | save_fpu(current); |
433 | disable_fpu(); | 413 | disable_fpu(); |
434 | last_task_used_math = NULL; | 414 | last_task_used_math = NULL; |
435 | regs->sr |= SR_FD; | 415 | regs->sr |= SR_FD; |
@@ -525,13 +505,6 @@ out: | |||
525 | return error; | 505 | return error; |
526 | } | 506 | } |
527 | 507 | ||
528 | /* | ||
529 | * These bracket the sleeping functions.. | ||
530 | */ | ||
531 | extern void interruptible_sleep_on(wait_queue_head_t *q); | ||
532 | |||
533 | #define mid_sched ((unsigned long) interruptible_sleep_on) | ||
534 | |||
535 | #ifdef CONFIG_FRAME_POINTER | 508 | #ifdef CONFIG_FRAME_POINTER |
536 | static int in_sh64_switch_to(unsigned long pc) | 509 | static int in_sh64_switch_to(unsigned long pc) |
537 | { | 510 | { |
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index 9be35f348093..7759a9a93211 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * SuperH process tracing | 2 | * SuperH process tracing |
3 | * | 3 | * |
4 | * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka | 4 | * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka |
5 | * Copyright (C) 2002 - 2008 Paul Mundt | 5 | * Copyright (C) 2002 - 2009 Paul Mundt |
6 | * | 6 | * |
7 | * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp> | 7 | * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp> |
8 | * | 8 | * |
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <linux/ptrace.h> | 18 | #include <linux/ptrace.h> |
19 | #include <linux/user.h> | 19 | #include <linux/user.h> |
20 | #include <linux/slab.h> | ||
21 | #include <linux/security.h> | 20 | #include <linux/security.h> |
22 | #include <linux/signal.h> | 21 | #include <linux/signal.h> |
23 | #include <linux/io.h> | 22 | #include <linux/io.h> |
@@ -26,6 +25,7 @@ | |||
26 | #include <linux/tracehook.h> | 25 | #include <linux/tracehook.h> |
27 | #include <linux/elf.h> | 26 | #include <linux/elf.h> |
28 | #include <linux/regset.h> | 27 | #include <linux/regset.h> |
28 | #include <linux/hw_breakpoint.h> | ||
29 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
30 | #include <asm/pgtable.h> | 30 | #include <asm/pgtable.h> |
31 | #include <asm/system.h> | 31 | #include <asm/system.h> |
@@ -63,33 +63,64 @@ static inline int put_stack_long(struct task_struct *task, int offset, | |||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | void user_enable_single_step(struct task_struct *child) | 66 | void ptrace_triggered(struct perf_event *bp, int nmi, |
67 | struct perf_sample_data *data, struct pt_regs *regs) | ||
67 | { | 68 | { |
68 | /* Next scheduling will set up UBC */ | 69 | struct perf_event_attr attr; |
69 | if (child->thread.ubc_pc == 0) | 70 | |
70 | ubc_usercnt += 1; | 71 | /* |
72 | * Disable the breakpoint request here since ptrace has defined a | ||
73 | * one-shot behaviour for breakpoint exceptions. | ||
74 | */ | ||
75 | attr = bp->attr; | ||
76 | attr.disabled = true; | ||
77 | modify_user_hw_breakpoint(bp, &attr); | ||
78 | } | ||
79 | |||
80 | static int set_single_step(struct task_struct *tsk, unsigned long addr) | ||
81 | { | ||
82 | struct thread_struct *thread = &tsk->thread; | ||
83 | struct perf_event *bp; | ||
84 | struct perf_event_attr attr; | ||
85 | |||
86 | bp = thread->ptrace_bps[0]; | ||
87 | if (!bp) { | ||
88 | hw_breakpoint_init(&attr); | ||
89 | |||
90 | attr.bp_addr = addr; | ||
91 | attr.bp_len = HW_BREAKPOINT_LEN_2; | ||
92 | attr.bp_type = HW_BREAKPOINT_R; | ||
93 | |||
94 | bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk); | ||
95 | if (IS_ERR(bp)) | ||
96 | return PTR_ERR(bp); | ||
97 | |||
98 | thread->ptrace_bps[0] = bp; | ||
99 | } else { | ||
100 | int err; | ||
101 | |||
102 | attr = bp->attr; | ||
103 | attr.bp_addr = addr; | ||
104 | err = modify_user_hw_breakpoint(bp, &attr); | ||
105 | if (unlikely(err)) | ||
106 | return err; | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | } | ||
71 | 111 | ||
72 | child->thread.ubc_pc = get_stack_long(child, | 112 | void user_enable_single_step(struct task_struct *child) |
73 | offsetof(struct pt_regs, pc)); | 113 | { |
114 | unsigned long pc = get_stack_long(child, offsetof(struct pt_regs, pc)); | ||
74 | 115 | ||
75 | set_tsk_thread_flag(child, TIF_SINGLESTEP); | 116 | set_tsk_thread_flag(child, TIF_SINGLESTEP); |
117 | |||
118 | set_single_step(child, pc); | ||
76 | } | 119 | } |
77 | 120 | ||
78 | void user_disable_single_step(struct task_struct *child) | 121 | void user_disable_single_step(struct task_struct *child) |
79 | { | 122 | { |
80 | clear_tsk_thread_flag(child, TIF_SINGLESTEP); | 123 | clear_tsk_thread_flag(child, TIF_SINGLESTEP); |
81 | |||
82 | /* | ||
83 | * Ensure the UBC is not programmed at the next context switch. | ||
84 | * | ||
85 | * Normally this is not needed but there are sequences such as | ||
86 | * singlestep, signal delivery, and continue that leave the | ||
87 | * ubc_pc non-zero leading to spurious SIGTRAPs. | ||
88 | */ | ||
89 | if (child->thread.ubc_pc != 0) { | ||
90 | ubc_usercnt -= 1; | ||
91 | child->thread.ubc_pc = 0; | ||
92 | } | ||
93 | } | 124 | } |
94 | 125 | ||
95 | /* | 126 | /* |
@@ -163,10 +194,10 @@ int fpregs_get(struct task_struct *target, | |||
163 | 194 | ||
164 | if ((boot_cpu_data.flags & CPU_HAS_FPU)) | 195 | if ((boot_cpu_data.flags & CPU_HAS_FPU)) |
165 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 196 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
166 | &target->thread.fpu.hard, 0, -1); | 197 | &target->thread.xstate->hardfpu, 0, -1); |
167 | 198 | ||
168 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 199 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
169 | &target->thread.fpu.soft, 0, -1); | 200 | &target->thread.xstate->softfpu, 0, -1); |
170 | } | 201 | } |
171 | 202 | ||
172 | static int fpregs_set(struct task_struct *target, | 203 | static int fpregs_set(struct task_struct *target, |
@@ -184,10 +215,10 @@ static int fpregs_set(struct task_struct *target, | |||
184 | 215 | ||
185 | if ((boot_cpu_data.flags & CPU_HAS_FPU)) | 216 | if ((boot_cpu_data.flags & CPU_HAS_FPU)) |
186 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 217 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
187 | &target->thread.fpu.hard, 0, -1); | 218 | &target->thread.xstate->hardfpu, 0, -1); |
188 | 219 | ||
189 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 220 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
190 | &target->thread.fpu.soft, 0, -1); | 221 | &target->thread.xstate->softfpu, 0, -1); |
191 | } | 222 | } |
192 | 223 | ||
193 | static int fpregs_active(struct task_struct *target, | 224 | static int fpregs_active(struct task_struct *target, |
@@ -333,7 +364,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
333 | else | 364 | else |
334 | tmp = 0; | 365 | tmp = 0; |
335 | } else | 366 | } else |
336 | tmp = ((long *)&child->thread.fpu) | 367 | tmp = ((long *)child->thread.xstate) |
337 | [(addr - (long)&dummy->fpu) >> 2]; | 368 | [(addr - (long)&dummy->fpu) >> 2]; |
338 | } else if (addr == (long) &dummy->u_fpvalid) | 369 | } else if (addr == (long) &dummy->u_fpvalid) |
339 | tmp = !!tsk_used_math(child); | 370 | tmp = !!tsk_used_math(child); |
@@ -362,7 +393,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
362 | else if (addr >= (long) &dummy->fpu && | 393 | else if (addr >= (long) &dummy->fpu && |
363 | addr < (long) &dummy->u_fpvalid) { | 394 | addr < (long) &dummy->u_fpvalid) { |
364 | set_stopped_child_used_math(child); | 395 | set_stopped_child_used_math(child); |
365 | ((long *)&child->thread.fpu) | 396 | ((long *)child->thread.xstate) |
366 | [(addr - (long)&dummy->fpu) >> 2] = data; | 397 | [(addr - (long)&dummy->fpu) >> 2] = data; |
367 | ret = 0; | 398 | ret = 0; |
368 | } else if (addr == (long) &dummy->u_fpvalid) { | 399 | } else if (addr == (long) &dummy->u_fpvalid) { |
diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index 952da83903da..5fd644da7f02 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c | |||
@@ -82,13 +82,13 @@ get_fpu_long(struct task_struct *task, unsigned long addr) | |||
82 | 82 | ||
83 | if (last_task_used_math == task) { | 83 | if (last_task_used_math == task) { |
84 | enable_fpu(); | 84 | enable_fpu(); |
85 | save_fpu(task, regs); | 85 | save_fpu(task); |
86 | disable_fpu(); | 86 | disable_fpu(); |
87 | last_task_used_math = 0; | 87 | last_task_used_math = 0; |
88 | regs->sr |= SR_FD; | 88 | regs->sr |= SR_FD; |
89 | } | 89 | } |
90 | 90 | ||
91 | tmp = ((long *)&task->thread.fpu)[addr / sizeof(unsigned long)]; | 91 | tmp = ((long *)task->thread.xstate)[addr / sizeof(unsigned long)]; |
92 | return tmp; | 92 | return tmp; |
93 | } | 93 | } |
94 | 94 | ||
@@ -114,17 +114,16 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) | |||
114 | regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; | 114 | regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; |
115 | 115 | ||
116 | if (!tsk_used_math(task)) { | 116 | if (!tsk_used_math(task)) { |
117 | fpinit(&task->thread.fpu.hard); | 117 | init_fpu(task); |
118 | set_stopped_child_used_math(task); | ||
119 | } else if (last_task_used_math == task) { | 118 | } else if (last_task_used_math == task) { |
120 | enable_fpu(); | 119 | enable_fpu(); |
121 | save_fpu(task, regs); | 120 | save_fpu(task); |
122 | disable_fpu(); | 121 | disable_fpu(); |
123 | last_task_used_math = 0; | 122 | last_task_used_math = 0; |
124 | regs->sr |= SR_FD; | 123 | regs->sr |= SR_FD; |
125 | } | 124 | } |
126 | 125 | ||
127 | ((long *)&task->thread.fpu)[addr / sizeof(unsigned long)] = data; | 126 | ((long *)task->thread.xstate)[addr / sizeof(unsigned long)] = data; |
128 | return 0; | 127 | return 0; |
129 | } | 128 | } |
130 | 129 | ||
@@ -133,6 +132,8 @@ void user_enable_single_step(struct task_struct *child) | |||
133 | struct pt_regs *regs = child->thread.uregs; | 132 | struct pt_regs *regs = child->thread.uregs; |
134 | 133 | ||
135 | regs->sr |= SR_SSTEP; /* auto-resetting upon exception */ | 134 | regs->sr |= SR_SSTEP; /* auto-resetting upon exception */ |
135 | |||
136 | set_tsk_thread_flag(child, TIF_SINGLESTEP); | ||
136 | } | 137 | } |
137 | 138 | ||
138 | void user_disable_single_step(struct task_struct *child) | 139 | void user_disable_single_step(struct task_struct *child) |
@@ -140,6 +141,8 @@ void user_disable_single_step(struct task_struct *child) | |||
140 | struct pt_regs *regs = child->thread.uregs; | 141 | struct pt_regs *regs = child->thread.uregs; |
141 | 142 | ||
142 | regs->sr &= ~SR_SSTEP; | 143 | regs->sr &= ~SR_SSTEP; |
144 | |||
145 | clear_tsk_thread_flag(child, TIF_SINGLESTEP); | ||
143 | } | 146 | } |
144 | 147 | ||
145 | static int genregs_get(struct task_struct *target, | 148 | static int genregs_get(struct task_struct *target, |
@@ -222,7 +225,7 @@ int fpregs_get(struct task_struct *target, | |||
222 | return ret; | 225 | return ret; |
223 | 226 | ||
224 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 227 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
225 | &target->thread.fpu.hard, 0, -1); | 228 | &target->thread.xstate->hardfpu, 0, -1); |
226 | } | 229 | } |
227 | 230 | ||
228 | static int fpregs_set(struct task_struct *target, | 231 | static int fpregs_set(struct task_struct *target, |
@@ -239,7 +242,7 @@ static int fpregs_set(struct task_struct *target, | |||
239 | set_stopped_child_used_math(target); | 242 | set_stopped_child_used_math(target); |
240 | 243 | ||
241 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 244 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
242 | &target->thread.fpu.hard, 0, -1); | 245 | &target->thread.xstate->hardfpu, 0, -1); |
243 | } | 246 | } |
244 | 247 | ||
245 | static int fpregs_active(struct task_struct *target, | 248 | static int fpregs_active(struct task_struct *target, |
@@ -454,6 +457,8 @@ asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs) | |||
454 | 457 | ||
455 | asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) | 458 | asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) |
456 | { | 459 | { |
460 | int step; | ||
461 | |||
457 | if (unlikely(current->audit_context)) | 462 | if (unlikely(current->audit_context)) |
458 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]), | 463 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]), |
459 | regs->regs[9]); | 464 | regs->regs[9]); |
@@ -461,8 +466,9 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) | |||
461 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) | 466 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
462 | trace_sys_exit(regs, regs->regs[9]); | 467 | trace_sys_exit(regs, regs->regs[9]); |
463 | 468 | ||
464 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | 469 | step = test_thread_flag(TIF_SINGLESTEP); |
465 | tracehook_report_syscall_exit(regs, 0); | 470 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) |
471 | tracehook_report_syscall_exit(regs, step); | ||
466 | } | 472 | } |
467 | 473 | ||
468 | /* Called with interrupts disabled */ | 474 | /* Called with interrupts disabled */ |
@@ -479,9 +485,10 @@ asmlinkage void do_single_step(unsigned long long vec, struct pt_regs *regs) | |||
479 | } | 485 | } |
480 | 486 | ||
481 | /* Called with interrupts disabled */ | 487 | /* Called with interrupts disabled */ |
482 | asmlinkage void do_software_break_point(unsigned long long vec, | 488 | BUILD_TRAP_HANDLER(breakpoint) |
483 | struct pt_regs *regs) | ||
484 | { | 489 | { |
490 | TRAP_HANDLER_DECL; | ||
491 | |||
485 | /* We need to forward step the PC, to counteract the backstep done | 492 | /* We need to forward step the PC, to counteract the backstep done |
486 | in signal.c. */ | 493 | in signal.c. */ |
487 | local_irq_enable(); | 494 | local_irq_enable(); |
diff --git a/arch/sh/kernel/reboot.c b/arch/sh/kernel/reboot.c new file mode 100644 index 000000000000..b1fca66bb92e --- /dev/null +++ b/arch/sh/kernel/reboot.c | |||
@@ -0,0 +1,98 @@ | |||
1 | #include <linux/pm.h> | ||
2 | #include <linux/kexec.h> | ||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/reboot.h> | ||
5 | #include <linux/module.h> | ||
6 | #ifdef CONFIG_SUPERH32 | ||
7 | #include <asm/watchdog.h> | ||
8 | #endif | ||
9 | #include <asm/addrspace.h> | ||
10 | #include <asm/reboot.h> | ||
11 | #include <asm/system.h> | ||
12 | |||
13 | void (*pm_power_off)(void); | ||
14 | EXPORT_SYMBOL(pm_power_off); | ||
15 | |||
16 | #ifdef CONFIG_SUPERH32 | ||
17 | static void watchdog_trigger_immediate(void) | ||
18 | { | ||
19 | sh_wdt_write_cnt(0xFF); | ||
20 | sh_wdt_write_csr(0xC2); | ||
21 | } | ||
22 | #endif | ||
23 | |||
24 | static void native_machine_restart(char * __unused) | ||
25 | { | ||
26 | local_irq_disable(); | ||
27 | |||
28 | /* Address error with SR.BL=1 first. */ | ||
29 | trigger_address_error(); | ||
30 | |||
31 | #ifdef CONFIG_SUPERH32 | ||
32 | /* If that fails or is unsupported, go for the watchdog next. */ | ||
33 | watchdog_trigger_immediate(); | ||
34 | #endif | ||
35 | |||
36 | /* | ||
37 | * Give up and sleep. | ||
38 | */ | ||
39 | while (1) | ||
40 | cpu_sleep(); | ||
41 | } | ||
42 | |||
43 | static void native_machine_shutdown(void) | ||
44 | { | ||
45 | smp_send_stop(); | ||
46 | } | ||
47 | |||
48 | static void native_machine_power_off(void) | ||
49 | { | ||
50 | if (pm_power_off) | ||
51 | pm_power_off(); | ||
52 | } | ||
53 | |||
54 | static void native_machine_halt(void) | ||
55 | { | ||
56 | /* stop other cpus */ | ||
57 | machine_shutdown(); | ||
58 | |||
59 | /* stop this cpu */ | ||
60 | stop_this_cpu(NULL); | ||
61 | } | ||
62 | |||
63 | struct machine_ops machine_ops = { | ||
64 | .power_off = native_machine_power_off, | ||
65 | .shutdown = native_machine_shutdown, | ||
66 | .restart = native_machine_restart, | ||
67 | .halt = native_machine_halt, | ||
68 | #ifdef CONFIG_KEXEC | ||
69 | .crash_shutdown = native_machine_crash_shutdown, | ||
70 | #endif | ||
71 | }; | ||
72 | |||
73 | void machine_power_off(void) | ||
74 | { | ||
75 | machine_ops.power_off(); | ||
76 | } | ||
77 | |||
78 | void machine_shutdown(void) | ||
79 | { | ||
80 | machine_ops.shutdown(); | ||
81 | } | ||
82 | |||
83 | void machine_restart(char *cmd) | ||
84 | { | ||
85 | machine_ops.restart(cmd); | ||
86 | } | ||
87 | |||
88 | void machine_halt(void) | ||
89 | { | ||
90 | machine_ops.halt(); | ||
91 | } | ||
92 | |||
93 | #ifdef CONFIG_KEXEC | ||
94 | void machine_crash_shutdown(struct pt_regs *regs) | ||
95 | { | ||
96 | machine_ops.crash_shutdown(regs); | ||
97 | } | ||
98 | #endif | ||
diff --git a/arch/sh/kernel/return_address.c b/arch/sh/kernel/return_address.c new file mode 100644 index 000000000000..cbf1dd5372b2 --- /dev/null +++ b/arch/sh/kernel/return_address.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/return_address.c | ||
3 | * | ||
4 | * Copyright (C) 2009 Matt Fleming | ||
5 | * Copyright (C) 2009 Paul Mundt | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file "COPYING" in the main directory of this archive | ||
9 | * for more details. | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <asm/dwarf.h> | ||
14 | |||
15 | #ifdef CONFIG_DWARF_UNWINDER | ||
16 | |||
17 | void *return_address(unsigned int depth) | ||
18 | { | ||
19 | struct dwarf_frame *frame; | ||
20 | unsigned long ra; | ||
21 | int i; | ||
22 | |||
23 | for (i = 0, frame = NULL, ra = 0; i <= depth; i++) { | ||
24 | struct dwarf_frame *tmp; | ||
25 | |||
26 | tmp = dwarf_unwind_stack(ra, frame); | ||
27 | |||
28 | if (frame) | ||
29 | dwarf_free_frame(frame); | ||
30 | |||
31 | frame = tmp; | ||
32 | |||
33 | if (!frame || !frame->return_addr) | ||
34 | break; | ||
35 | |||
36 | ra = frame->return_addr; | ||
37 | } | ||
38 | |||
39 | /* Failed to unwind the stack to the specified depth. */ | ||
40 | WARN_ON(i != depth + 1); | ||
41 | |||
42 | if (frame) | ||
43 | dwarf_free_frame(frame); | ||
44 | |||
45 | return (void *)ra; | ||
46 | } | ||
47 | |||
48 | #else | ||
49 | |||
50 | void *return_address(unsigned int depth) | ||
51 | { | ||
52 | return NULL; | ||
53 | } | ||
54 | |||
55 | #endif | ||
56 | |||
57 | EXPORT_SYMBOL_GPL(return_address); | ||
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 99b4fb553bf1..8870d6ba64bf 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -421,8 +421,13 @@ void __init setup_arch(char **cmdline_p) | |||
421 | 421 | ||
422 | parse_early_param(); | 422 | parse_early_param(); |
423 | 423 | ||
424 | uncached_init(); | ||
425 | |||
424 | plat_early_device_setup(); | 426 | plat_early_device_setup(); |
425 | 427 | ||
428 | /* Let earlyprintk output early console messages */ | ||
429 | early_platform_driver_probe("earlyprintk", 1, 1); | ||
430 | |||
426 | sh_mv_setup(); | 431 | sh_mv_setup(); |
427 | 432 | ||
428 | /* | 433 | /* |
@@ -438,7 +443,7 @@ void __init setup_arch(char **cmdline_p) | |||
438 | 443 | ||
439 | nodes_clear(node_online_map); | 444 | nodes_clear(node_online_map); |
440 | 445 | ||
441 | /* Setup bootmem with available RAM */ | 446 | pmb_init(); |
442 | lmb_init(); | 447 | lmb_init(); |
443 | setup_memory(); | 448 | setup_memory(); |
444 | sparse_init(); | 449 | sparse_init(); |
@@ -446,13 +451,14 @@ void __init setup_arch(char **cmdline_p) | |||
446 | #ifdef CONFIG_DUMMY_CONSOLE | 451 | #ifdef CONFIG_DUMMY_CONSOLE |
447 | conswitchp = &dummy_con; | 452 | conswitchp = &dummy_con; |
448 | #endif | 453 | #endif |
454 | paging_init(); | ||
455 | |||
456 | ioremap_fixed_init(); | ||
449 | 457 | ||
450 | /* Perform the machine specific initialisation */ | 458 | /* Perform the machine specific initialisation */ |
451 | if (likely(sh_mv.mv_setup)) | 459 | if (likely(sh_mv.mv_setup)) |
452 | sh_mv.mv_setup(cmdline_p); | 460 | sh_mv.mv_setup(cmdline_p); |
453 | 461 | ||
454 | paging_init(); | ||
455 | |||
456 | #ifdef CONFIG_SMP | 462 | #ifdef CONFIG_SMP |
457 | plat_smp_setup(); | 463 | plat_smp_setup(); |
458 | #endif | 464 | #endif |
diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c index c852f7805728..47475cca068a 100644 --- a/arch/sh/kernel/sh_bios.c +++ b/arch/sh/kernel/sh_bios.c | |||
@@ -1,19 +1,30 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/sh/kernel/sh_bios.c | ||
3 | * C interface for trapping into the standard LinuxSH BIOS. | 2 | * C interface for trapping into the standard LinuxSH BIOS. |
4 | * | 3 | * |
5 | * Copyright (C) 2000 Greg Banks, Mitch Davis | 4 | * Copyright (C) 2000 Greg Banks, Mitch Davis |
5 | * Copyright (C) 1999, 2000 Niibe Yutaka | ||
6 | * Copyright (C) 2002 M. R. Brown | ||
7 | * Copyright (C) 2004 - 2010 Paul Mundt | ||
6 | * | 8 | * |
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
7 | */ | 12 | */ |
8 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/console.h> | ||
15 | #include <linux/tty.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/delay.h> | ||
9 | #include <asm/sh_bios.h> | 19 | #include <asm/sh_bios.h> |
10 | 20 | ||
11 | #define BIOS_CALL_CONSOLE_WRITE 0 | 21 | #define BIOS_CALL_CONSOLE_WRITE 0 |
12 | #define BIOS_CALL_ETH_NODE_ADDR 10 | 22 | #define BIOS_CALL_ETH_NODE_ADDR 10 |
13 | #define BIOS_CALL_SHUTDOWN 11 | 23 | #define BIOS_CALL_SHUTDOWN 11 |
14 | #define BIOS_CALL_CHAR_OUT 0x1f /* TODO: hack */ | ||
15 | #define BIOS_CALL_GDB_DETACH 0xff | 24 | #define BIOS_CALL_GDB_DETACH 0xff |
16 | 25 | ||
26 | void *gdb_vbr_vector = NULL; | ||
27 | |||
17 | static inline long sh_bios_call(long func, long arg0, long arg1, long arg2, | 28 | static inline long sh_bios_call(long func, long arg0, long arg1, long arg2, |
18 | long arg3) | 29 | long arg3) |
19 | { | 30 | { |
@@ -23,6 +34,9 @@ static inline long sh_bios_call(long func, long arg0, long arg1, long arg2, | |||
23 | register long r6 __asm__("r6") = arg2; | 34 | register long r6 __asm__("r6") = arg2; |
24 | register long r7 __asm__("r7") = arg3; | 35 | register long r7 __asm__("r7") = arg3; |
25 | 36 | ||
37 | if (!gdb_vbr_vector) | ||
38 | return -ENOSYS; | ||
39 | |||
26 | __asm__ __volatile__("trapa #0x3f":"=z"(r0) | 40 | __asm__ __volatile__("trapa #0x3f":"=z"(r0) |
27 | :"0"(r0), "r"(r4), "r"(r5), "r"(r6), "r"(r7) | 41 | :"0"(r0), "r"(r4), "r"(r5), "r"(r6), "r"(r7) |
28 | :"memory"); | 42 | :"memory"); |
@@ -34,11 +48,6 @@ void sh_bios_console_write(const char *buf, unsigned int len) | |||
34 | sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0); | 48 | sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0); |
35 | } | 49 | } |
36 | 50 | ||
37 | void sh_bios_char_out(char ch) | ||
38 | { | ||
39 | sh_bios_call(BIOS_CALL_CHAR_OUT, ch, 0, 0, 0); | ||
40 | } | ||
41 | |||
42 | void sh_bios_gdb_detach(void) | 51 | void sh_bios_gdb_detach(void) |
43 | { | 52 | { |
44 | sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0); | 53 | sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0); |
@@ -55,3 +64,109 @@ void sh_bios_shutdown(unsigned int how) | |||
55 | { | 64 | { |
56 | sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0); | 65 | sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0); |
57 | } | 66 | } |
67 | |||
68 | /* | ||
69 | * Read the old value of the VBR register to initialise the vector | ||
70 | * through which debug and BIOS traps are delegated by the Linux trap | ||
71 | * handler. | ||
72 | */ | ||
73 | void sh_bios_vbr_init(void) | ||
74 | { | ||
75 | unsigned long vbr; | ||
76 | |||
77 | if (unlikely(gdb_vbr_vector)) | ||
78 | return; | ||
79 | |||
80 | __asm__ __volatile__ ("stc vbr, %0" : "=r" (vbr)); | ||
81 | |||
82 | if (vbr) { | ||
83 | gdb_vbr_vector = (void *)(vbr + 0x100); | ||
84 | printk(KERN_NOTICE "Setting GDB trap vector to %p\n", | ||
85 | gdb_vbr_vector); | ||
86 | } else | ||
87 | printk(KERN_NOTICE "SH-BIOS not detected\n"); | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * sh_bios_vbr_reload - Re-load the system VBR from the BIOS vector. | ||
92 | * | ||
93 | * This can be used by save/restore code to reinitialize the system VBR | ||
94 | * from the fixed BIOS VBR. A no-op if no BIOS VBR is known. | ||
95 | */ | ||
96 | void sh_bios_vbr_reload(void) | ||
97 | { | ||
98 | if (gdb_vbr_vector) | ||
99 | __asm__ __volatile__ ( | ||
100 | "ldc %0, vbr" | ||
101 | : | ||
102 | : "r" (((unsigned long) gdb_vbr_vector) - 0x100) | ||
103 | : "memory" | ||
104 | ); | ||
105 | } | ||
106 | |||
107 | /* | ||
108 | * Print a string through the BIOS | ||
109 | */ | ||
110 | static void sh_console_write(struct console *co, const char *s, | ||
111 | unsigned count) | ||
112 | { | ||
113 | sh_bios_console_write(s, count); | ||
114 | } | ||
115 | |||
116 | /* | ||
117 | * Setup initial baud/bits/parity. We do two things here: | ||
118 | * - construct a cflag setting for the first rs_open() | ||
119 | * - initialize the serial port | ||
120 | * Return non-zero if we didn't find a serial port. | ||
121 | */ | ||
122 | static int __init sh_console_setup(struct console *co, char *options) | ||
123 | { | ||
124 | int cflag = CREAD | HUPCL | CLOCAL; | ||
125 | |||
126 | /* | ||
127 | * Now construct a cflag setting. | ||
128 | * TODO: this is a totally bogus cflag, as we have | ||
129 | * no idea what serial settings the BIOS is using, or | ||
130 | * even if its using the serial port at all. | ||
131 | */ | ||
132 | cflag |= B115200 | CS8 | /*no parity*/0; | ||
133 | |||
134 | co->cflag = cflag; | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static struct console bios_console = { | ||
140 | .name = "bios", | ||
141 | .write = sh_console_write, | ||
142 | .setup = sh_console_setup, | ||
143 | .flags = CON_PRINTBUFFER, | ||
144 | .index = -1, | ||
145 | }; | ||
146 | |||
147 | static struct console *early_console; | ||
148 | |||
149 | static int __init setup_early_printk(char *buf) | ||
150 | { | ||
151 | int keep_early = 0; | ||
152 | |||
153 | if (!buf) | ||
154 | return 0; | ||
155 | |||
156 | if (strstr(buf, "keep")) | ||
157 | keep_early = 1; | ||
158 | |||
159 | if (!strncmp(buf, "bios", 4)) | ||
160 | early_console = &bios_console; | ||
161 | |||
162 | if (likely(early_console)) { | ||
163 | if (keep_early) | ||
164 | early_console->flags &= ~CON_BOOT; | ||
165 | else | ||
166 | early_console->flags |= CON_BOOT; | ||
167 | register_console(early_console); | ||
168 | } | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | early_param("earlyprintk", setup_early_printk); | ||
diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 444cce3ae921..3896f26efa4a 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c | |||
@@ -1,37 +1,11 @@ | |||
1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
2 | #include <linux/smp.h> | 2 | #include <linux/string.h> |
3 | #include <linux/user.h> | 3 | #include <linux/uaccess.h> |
4 | #include <linux/elfcore.h> | 4 | #include <linux/delay.h> |
5 | #include <linux/sched.h> | 5 | #include <linux/mm.h> |
6 | #include <linux/in6.h> | ||
7 | #include <linux/interrupt.h> | ||
8 | #include <linux/vmalloc.h> | ||
9 | #include <linux/pci.h> | ||
10 | #include <linux/irq.h> | ||
11 | #include <asm/sections.h> | ||
12 | #include <asm/processor.h> | ||
13 | #include <asm/uaccess.h> | ||
14 | #include <asm/checksum.h> | 6 | #include <asm/checksum.h> |
15 | #include <asm/io.h> | 7 | #include <asm/sections.h> |
16 | #include <asm/delay.h> | ||
17 | #include <asm/tlbflush.h> | ||
18 | #include <asm/cacheflush.h> | ||
19 | #include <asm/ftrace.h> | ||
20 | |||
21 | extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); | ||
22 | |||
23 | /* platform dependent support */ | ||
24 | EXPORT_SYMBOL(dump_fpu); | ||
25 | EXPORT_SYMBOL(kernel_thread); | ||
26 | EXPORT_SYMBOL(strlen); | ||
27 | |||
28 | /* PCI exports */ | ||
29 | #ifdef CONFIG_PCI | ||
30 | EXPORT_SYMBOL(pci_alloc_consistent); | ||
31 | EXPORT_SYMBOL(pci_free_consistent); | ||
32 | #endif | ||
33 | 8 | ||
34 | /* mem exports */ | ||
35 | EXPORT_SYMBOL(memchr); | 9 | EXPORT_SYMBOL(memchr); |
36 | EXPORT_SYMBOL(memcpy); | 10 | EXPORT_SYMBOL(memcpy); |
37 | EXPORT_SYMBOL(memset); | 11 | EXPORT_SYMBOL(memset); |
@@ -40,6 +14,13 @@ EXPORT_SYMBOL(__copy_user); | |||
40 | EXPORT_SYMBOL(__udelay); | 14 | EXPORT_SYMBOL(__udelay); |
41 | EXPORT_SYMBOL(__ndelay); | 15 | EXPORT_SYMBOL(__ndelay); |
42 | EXPORT_SYMBOL(__const_udelay); | 16 | EXPORT_SYMBOL(__const_udelay); |
17 | EXPORT_SYMBOL(strlen); | ||
18 | EXPORT_SYMBOL(csum_partial); | ||
19 | EXPORT_SYMBOL(csum_partial_copy_generic); | ||
20 | EXPORT_SYMBOL(copy_page); | ||
21 | EXPORT_SYMBOL(__clear_user); | ||
22 | EXPORT_SYMBOL(_ebss); | ||
23 | EXPORT_SYMBOL(empty_zero_page); | ||
43 | 24 | ||
44 | #define DECLARE_EXPORT(name) \ | 25 | #define DECLARE_EXPORT(name) \ |
45 | extern void name(void);EXPORT_SYMBOL(name) | 26 | extern void name(void);EXPORT_SYMBOL(name) |
@@ -107,30 +88,6 @@ DECLARE_EXPORT(__sdivsi3_i4); | |||
107 | DECLARE_EXPORT(__udivsi3_i4); | 88 | DECLARE_EXPORT(__udivsi3_i4); |
108 | DECLARE_EXPORT(__sdivsi3_i4i); | 89 | DECLARE_EXPORT(__sdivsi3_i4i); |
109 | DECLARE_EXPORT(__udivsi3_i4i); | 90 | DECLARE_EXPORT(__udivsi3_i4i); |
110 | |||
111 | #if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ | ||
112 | defined(CONFIG_SH7705_CACHE_32KB)) | ||
113 | /* needed by some modules */ | ||
114 | EXPORT_SYMBOL(flush_cache_all); | ||
115 | EXPORT_SYMBOL(flush_cache_range); | ||
116 | EXPORT_SYMBOL(flush_dcache_page); | ||
117 | #endif | ||
118 | |||
119 | #ifdef CONFIG_MCOUNT | 91 | #ifdef CONFIG_MCOUNT |
120 | DECLARE_EXPORT(mcount); | 92 | DECLARE_EXPORT(mcount); |
121 | #endif | 93 | #endif |
122 | EXPORT_SYMBOL(csum_partial); | ||
123 | EXPORT_SYMBOL(csum_partial_copy_generic); | ||
124 | #ifdef CONFIG_IPV6 | ||
125 | EXPORT_SYMBOL(csum_ipv6_magic); | ||
126 | #endif | ||
127 | EXPORT_SYMBOL(copy_page); | ||
128 | EXPORT_SYMBOL(__clear_user); | ||
129 | EXPORT_SYMBOL(_ebss); | ||
130 | EXPORT_SYMBOL(empty_zero_page); | ||
131 | |||
132 | #ifndef CONFIG_CACHE_OFF | ||
133 | EXPORT_SYMBOL(__flush_purge_region); | ||
134 | EXPORT_SYMBOL(__flush_wback_region); | ||
135 | EXPORT_SYMBOL(__flush_invalidate_region); | ||
136 | #endif | ||
diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c index d008e17eb257..45afa5c51f67 100644 --- a/arch/sh/kernel/sh_ksyms_64.c +++ b/arch/sh/kernel/sh_ksyms_64.c | |||
@@ -24,16 +24,6 @@ | |||
24 | #include <asm/delay.h> | 24 | #include <asm/delay.h> |
25 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
26 | 26 | ||
27 | extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); | ||
28 | |||
29 | /* platform dependent support */ | ||
30 | EXPORT_SYMBOL(dump_fpu); | ||
31 | EXPORT_SYMBOL(kernel_thread); | ||
32 | |||
33 | #ifdef CONFIG_VT | ||
34 | EXPORT_SYMBOL(screen_info); | ||
35 | #endif | ||
36 | |||
37 | EXPORT_SYMBOL(__put_user_asm_b); | 27 | EXPORT_SYMBOL(__put_user_asm_b); |
38 | EXPORT_SYMBOL(__put_user_asm_w); | 28 | EXPORT_SYMBOL(__put_user_asm_w); |
39 | EXPORT_SYMBOL(__put_user_asm_l); | 29 | EXPORT_SYMBOL(__put_user_asm_l); |
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index 3db37425210d..579cd2ca358d 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c | |||
@@ -67,7 +67,8 @@ sys_sigsuspend(old_sigset_t mask, | |||
67 | 67 | ||
68 | current->state = TASK_INTERRUPTIBLE; | 68 | current->state = TASK_INTERRUPTIBLE; |
69 | schedule(); | 69 | schedule(); |
70 | set_thread_flag(TIF_RESTORE_SIGMASK); | 70 | set_restore_sigmask(); |
71 | |||
71 | return -ERESTARTNOHAND; | 72 | return -ERESTARTNOHAND; |
72 | } | 73 | } |
73 | 74 | ||
@@ -149,7 +150,7 @@ static inline int restore_sigcontext_fpu(struct sigcontext __user *sc) | |||
149 | return 0; | 150 | return 0; |
150 | 151 | ||
151 | set_used_math(); | 152 | set_used_math(); |
152 | return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0], | 153 | return __copy_from_user(&tsk->thread.xstate->hardfpu, &sc->sc_fpregs[0], |
153 | sizeof(long)*(16*2+2)); | 154 | sizeof(long)*(16*2+2)); |
154 | } | 155 | } |
155 | 156 | ||
@@ -174,7 +175,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc, | |||
174 | clear_used_math(); | 175 | clear_used_math(); |
175 | 176 | ||
176 | unlazy_fpu(tsk, regs); | 177 | unlazy_fpu(tsk, regs); |
177 | return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard, | 178 | return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.xstate->hardfpu, |
178 | sizeof(long)*(16*2+2)); | 179 | sizeof(long)*(16*2+2)); |
179 | } | 180 | } |
180 | #endif /* CONFIG_SH_FPU */ | 181 | #endif /* CONFIG_SH_FPU */ |
@@ -527,7 +528,7 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs, | |||
527 | /* fallthrough */ | 528 | /* fallthrough */ |
528 | case -ERESTARTNOINTR: | 529 | case -ERESTARTNOINTR: |
529 | regs->regs[0] = save_r0; | 530 | regs->regs[0] = save_r0; |
530 | regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); | 531 | regs->pc -= instruction_size(__raw_readw(regs->pc - 4)); |
531 | break; | 532 | break; |
532 | } | 533 | } |
533 | } | 534 | } |
@@ -590,7 +591,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) | |||
590 | if (try_to_freeze()) | 591 | if (try_to_freeze()) |
591 | goto no_signal; | 592 | goto no_signal; |
592 | 593 | ||
593 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 594 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) |
594 | oldset = ¤t->saved_sigmask; | 595 | oldset = ¤t->saved_sigmask; |
595 | else | 596 | else |
596 | oldset = ¤t->blocked; | 597 | oldset = ¤t->blocked; |
@@ -602,12 +603,13 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) | |||
602 | /* Whee! Actually deliver the signal. */ | 603 | /* Whee! Actually deliver the signal. */ |
603 | if (handle_signal(signr, &ka, &info, oldset, | 604 | if (handle_signal(signr, &ka, &info, oldset, |
604 | regs, save_r0) == 0) { | 605 | regs, save_r0) == 0) { |
605 | /* a signal was successfully delivered; the saved | 606 | /* |
607 | * A signal was successfully delivered; the saved | ||
606 | * sigmask will have been stored in the signal frame, | 608 | * sigmask will have been stored in the signal frame, |
607 | * and will be restored by sigreturn, so we can simply | 609 | * and will be restored by sigreturn, so we can simply |
608 | * clear the TIF_RESTORE_SIGMASK flag */ | 610 | * clear the TS_RESTORE_SIGMASK flag |
609 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 611 | */ |
610 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 612 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
611 | 613 | ||
612 | tracehook_signal_handler(signr, &info, &ka, regs, | 614 | tracehook_signal_handler(signr, &info, &ka, regs, |
613 | test_thread_flag(TIF_SINGLESTEP)); | 615 | test_thread_flag(TIF_SINGLESTEP)); |
@@ -624,17 +626,19 @@ no_signal: | |||
624 | regs->regs[0] == -ERESTARTSYS || | 626 | regs->regs[0] == -ERESTARTSYS || |
625 | regs->regs[0] == -ERESTARTNOINTR) { | 627 | regs->regs[0] == -ERESTARTNOINTR) { |
626 | regs->regs[0] = save_r0; | 628 | regs->regs[0] = save_r0; |
627 | regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); | 629 | regs->pc -= instruction_size(__raw_readw(regs->pc - 4)); |
628 | } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { | 630 | } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { |
629 | regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); | 631 | regs->pc -= instruction_size(__raw_readw(regs->pc - 4)); |
630 | regs->regs[3] = __NR_restart_syscall; | 632 | regs->regs[3] = __NR_restart_syscall; |
631 | } | 633 | } |
632 | } | 634 | } |
633 | 635 | ||
634 | /* if there's no signal to deliver, we just put the saved sigmask | 636 | /* |
635 | * back */ | 637 | * If there's no signal to deliver, we just put the saved sigmask |
636 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | 638 | * back. |
637 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 639 | */ |
640 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) { | ||
641 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | ||
638 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 642 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
639 | } | 643 | } |
640 | } | 644 | } |
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index 74793c80a57a..5a9f1f10ebf4 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c | |||
@@ -101,7 +101,7 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
101 | if (try_to_freeze()) | 101 | if (try_to_freeze()) |
102 | goto no_signal; | 102 | goto no_signal; |
103 | 103 | ||
104 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 104 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) |
105 | oldset = ¤t->saved_sigmask; | 105 | oldset = ¤t->saved_sigmask; |
106 | else if (!oldset) | 106 | else if (!oldset) |
107 | oldset = ¤t->blocked; | 107 | oldset = ¤t->blocked; |
@@ -115,12 +115,12 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
115 | /* | 115 | /* |
116 | * If a signal was successfully delivered, the | 116 | * If a signal was successfully delivered, the |
117 | * saved sigmask is in its frame, and we can | 117 | * saved sigmask is in its frame, and we can |
118 | * clear the TIF_RESTORE_SIGMASK flag. | 118 | * clear the TS_RESTORE_SIGMASK flag. |
119 | */ | 119 | */ |
120 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 120 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
121 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
122 | 121 | ||
123 | tracehook_signal_handler(signr, &info, &ka, regs, 0); | 122 | tracehook_signal_handler(signr, &info, &ka, regs, |
123 | test_thread_flag(TIF_SINGLESTEP)); | ||
124 | return 1; | 124 | return 1; |
125 | } | 125 | } |
126 | } | 126 | } |
@@ -146,8 +146,8 @@ no_signal: | |||
146 | } | 146 | } |
147 | 147 | ||
148 | /* No signal to deliver -- put the saved sigmask back */ | 148 | /* No signal to deliver -- put the saved sigmask back */ |
149 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | 149 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) { |
150 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 150 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
151 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 151 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
152 | } | 152 | } |
153 | 153 | ||
@@ -176,6 +176,7 @@ sys_sigsuspend(old_sigset_t mask, | |||
176 | while (1) { | 176 | while (1) { |
177 | current->state = TASK_INTERRUPTIBLE; | 177 | current->state = TASK_INTERRUPTIBLE; |
178 | schedule(); | 178 | schedule(); |
179 | set_restore_sigmask(); | ||
179 | regs->pc += 4; /* because sys_sigreturn decrements the pc */ | 180 | regs->pc += 4; /* because sys_sigreturn decrements the pc */ |
180 | if (do_signal(regs, &saveset)) { | 181 | if (do_signal(regs, &saveset)) { |
181 | /* pc now points at signal handler. Need to decrement | 182 | /* pc now points at signal handler. Need to decrement |
@@ -296,7 +297,7 @@ restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) | |||
296 | regs->sr |= SR_FD; | 297 | regs->sr |= SR_FD; |
297 | } | 298 | } |
298 | 299 | ||
299 | err |= __copy_from_user(¤t->thread.fpu.hard, &sc->sc_fpregs[0], | 300 | err |= __copy_from_user(¤t->thread.xstate->hardfpu, &sc->sc_fpregs[0], |
300 | (sizeof(long long) * 32) + (sizeof(int) * 1)); | 301 | (sizeof(long long) * 32) + (sizeof(int) * 1)); |
301 | 302 | ||
302 | return err; | 303 | return err; |
@@ -315,13 +316,13 @@ setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) | |||
315 | 316 | ||
316 | if (current == last_task_used_math) { | 317 | if (current == last_task_used_math) { |
317 | enable_fpu(); | 318 | enable_fpu(); |
318 | save_fpu(current, regs); | 319 | save_fpu(current); |
319 | disable_fpu(); | 320 | disable_fpu(); |
320 | last_task_used_math = NULL; | 321 | last_task_used_math = NULL; |
321 | regs->sr |= SR_FD; | 322 | regs->sr |= SR_FD; |
322 | } | 323 | } |
323 | 324 | ||
324 | err |= __copy_to_user(&sc->sc_fpregs[0], ¤t->thread.fpu.hard, | 325 | err |= __copy_to_user(&sc->sc_fpregs[0], ¤t->thread.xstate->hardfpu, |
325 | (sizeof(long long) * 32) + (sizeof(int) * 1)); | 326 | (sizeof(long long) * 32) + (sizeof(int) * 1)); |
326 | clear_used_math(); | 327 | clear_used_math(); |
327 | 328 | ||
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 160db1003cfb..002cc612deef 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c | |||
@@ -69,6 +69,7 @@ asmlinkage void __cpuinit start_secondary(void) | |||
69 | unsigned int cpu; | 69 | unsigned int cpu; |
70 | struct mm_struct *mm = &init_mm; | 70 | struct mm_struct *mm = &init_mm; |
71 | 71 | ||
72 | enable_mmu(); | ||
72 | atomic_inc(&mm->mm_count); | 73 | atomic_inc(&mm->mm_count); |
73 | atomic_inc(&mm->mm_users); | 74 | atomic_inc(&mm->mm_users); |
74 | current->active_mm = mm; | 75 | current->active_mm = mm; |
@@ -122,7 +123,9 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
122 | stack_start.bss_start = 0; /* don't clear bss for secondary cpus */ | 123 | stack_start.bss_start = 0; /* don't clear bss for secondary cpus */ |
123 | stack_start.start_kernel_fn = start_secondary; | 124 | stack_start.start_kernel_fn = start_secondary; |
124 | 125 | ||
125 | flush_cache_all(); | 126 | flush_icache_range((unsigned long)&stack_start, |
127 | (unsigned long)&stack_start + sizeof(stack_start)); | ||
128 | wmb(); | ||
126 | 129 | ||
127 | plat_start_cpu(cpu, (unsigned long)_stext); | 130 | plat_start_cpu(cpu, (unsigned long)_stext); |
128 | 131 | ||
@@ -159,15 +162,6 @@ void smp_send_reschedule(int cpu) | |||
159 | plat_send_ipi(cpu, SMP_MSG_RESCHEDULE); | 162 | plat_send_ipi(cpu, SMP_MSG_RESCHEDULE); |
160 | } | 163 | } |
161 | 164 | ||
162 | static void stop_this_cpu(void *unused) | ||
163 | { | ||
164 | cpu_clear(smp_processor_id(), cpu_online_map); | ||
165 | local_irq_disable(); | ||
166 | |||
167 | for (;;) | ||
168 | cpu_relax(); | ||
169 | } | ||
170 | |||
171 | void smp_send_stop(void) | 165 | void smp_send_stop(void) |
172 | { | 166 | { |
173 | smp_call_function(stop_this_cpu, 0, 0); | 167 | smp_call_function(stop_this_cpu, 0, 0); |
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 8aa5d1ceaf14..81f58371613d 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c | |||
@@ -28,37 +28,13 @@ | |||
28 | #include <asm/cacheflush.h> | 28 | #include <asm/cacheflush.h> |
29 | #include <asm/cachectl.h> | 29 | #include <asm/cachectl.h> |
30 | 30 | ||
31 | static inline long | ||
32 | do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, | ||
33 | unsigned long flags, int fd, unsigned long pgoff) | ||
34 | { | ||
35 | int error = -EBADF; | ||
36 | struct file *file = NULL; | ||
37 | |||
38 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
39 | if (!(flags & MAP_ANONYMOUS)) { | ||
40 | file = fget(fd); | ||
41 | if (!file) | ||
42 | goto out; | ||
43 | } | ||
44 | |||
45 | down_write(¤t->mm->mmap_sem); | ||
46 | error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
47 | up_write(¤t->mm->mmap_sem); | ||
48 | |||
49 | if (file) | ||
50 | fput(file); | ||
51 | out: | ||
52 | return error; | ||
53 | } | ||
54 | |||
55 | asmlinkage int old_mmap(unsigned long addr, unsigned long len, | 31 | asmlinkage int old_mmap(unsigned long addr, unsigned long len, |
56 | unsigned long prot, unsigned long flags, | 32 | unsigned long prot, unsigned long flags, |
57 | int fd, unsigned long off) | 33 | int fd, unsigned long off) |
58 | { | 34 | { |
59 | if (off & ~PAGE_MASK) | 35 | if (off & ~PAGE_MASK) |
60 | return -EINVAL; | 36 | return -EINVAL; |
61 | return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT); | 37 | return sys_mmap_pgoff(addr, len, prot, flags, fd, off>>PAGE_SHIFT); |
62 | } | 38 | } |
63 | 39 | ||
64 | asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, | 40 | asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, |
@@ -74,111 +50,7 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, | |||
74 | 50 | ||
75 | pgoff >>= PAGE_SHIFT - 12; | 51 | pgoff >>= PAGE_SHIFT - 12; |
76 | 52 | ||
77 | return do_mmap2(addr, len, prot, flags, fd, pgoff); | 53 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); |
78 | } | ||
79 | |||
80 | /* | ||
81 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
82 | * | ||
83 | * This is really horribly ugly. | ||
84 | */ | ||
85 | asmlinkage int sys_ipc(uint call, int first, int second, | ||
86 | int third, void __user *ptr, long fifth) | ||
87 | { | ||
88 | int version, ret; | ||
89 | |||
90 | version = call >> 16; /* hack for backward compatibility */ | ||
91 | call &= 0xffff; | ||
92 | |||
93 | if (call <= SEMTIMEDOP) | ||
94 | switch (call) { | ||
95 | case SEMOP: | ||
96 | return sys_semtimedop(first, | ||
97 | (struct sembuf __user *)ptr, | ||
98 | second, NULL); | ||
99 | case SEMTIMEDOP: | ||
100 | return sys_semtimedop(first, | ||
101 | (struct sembuf __user *)ptr, second, | ||
102 | (const struct timespec __user *)fifth); | ||
103 | case SEMGET: | ||
104 | return sys_semget (first, second, third); | ||
105 | case SEMCTL: { | ||
106 | union semun fourth; | ||
107 | if (!ptr) | ||
108 | return -EINVAL; | ||
109 | if (get_user(fourth.__pad, (void __user * __user *) ptr)) | ||
110 | return -EFAULT; | ||
111 | return sys_semctl (first, second, third, fourth); | ||
112 | } | ||
113 | default: | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | |||
117 | if (call <= MSGCTL) | ||
118 | switch (call) { | ||
119 | case MSGSND: | ||
120 | return sys_msgsnd (first, (struct msgbuf __user *) ptr, | ||
121 | second, third); | ||
122 | case MSGRCV: | ||
123 | switch (version) { | ||
124 | case 0: | ||
125 | { | ||
126 | struct ipc_kludge tmp; | ||
127 | |||
128 | if (!ptr) | ||
129 | return -EINVAL; | ||
130 | |||
131 | if (copy_from_user(&tmp, | ||
132 | (struct ipc_kludge __user *) ptr, | ||
133 | sizeof (tmp))) | ||
134 | return -EFAULT; | ||
135 | |||
136 | return sys_msgrcv (first, tmp.msgp, second, | ||
137 | tmp.msgtyp, third); | ||
138 | } | ||
139 | default: | ||
140 | return sys_msgrcv (first, | ||
141 | (struct msgbuf __user *) ptr, | ||
142 | second, fifth, third); | ||
143 | } | ||
144 | case MSGGET: | ||
145 | return sys_msgget ((key_t) first, second); | ||
146 | case MSGCTL: | ||
147 | return sys_msgctl (first, second, | ||
148 | (struct msqid_ds __user *) ptr); | ||
149 | default: | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | if (call <= SHMCTL) | ||
153 | switch (call) { | ||
154 | case SHMAT: | ||
155 | switch (version) { | ||
156 | default: { | ||
157 | ulong raddr; | ||
158 | ret = do_shmat (first, (char __user *) ptr, | ||
159 | second, &raddr); | ||
160 | if (ret) | ||
161 | return ret; | ||
162 | return put_user (raddr, (ulong __user *) third); | ||
163 | } | ||
164 | case 1: /* iBCS2 emulator entry point */ | ||
165 | if (!segment_eq(get_fs(), get_ds())) | ||
166 | return -EINVAL; | ||
167 | return do_shmat (first, (char __user *) ptr, | ||
168 | second, (ulong *) third); | ||
169 | } | ||
170 | case SHMDT: | ||
171 | return sys_shmdt ((char __user *)ptr); | ||
172 | case SHMGET: | ||
173 | return sys_shmget (first, second, third); | ||
174 | case SHMCTL: | ||
175 | return sys_shmctl (first, second, | ||
176 | (struct shmid_ds __user *) ptr); | ||
177 | default: | ||
178 | return -EINVAL; | ||
179 | } | ||
180 | |||
181 | return -EINVAL; | ||
182 | } | 54 | } |
183 | 55 | ||
184 | /* sys_cacheflush -- flush (part of) the processor cache. */ | 56 | /* sys_cacheflush -- flush (part of) the processor cache. */ |
@@ -221,14 +93,3 @@ asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op) | |||
221 | up_read(¤t->mm->mmap_sem); | 93 | up_read(¤t->mm->mmap_sem); |
222 | return 0; | 94 | return 0; |
223 | } | 95 | } |
224 | |||
225 | asmlinkage int sys_uname(struct old_utsname __user *name) | ||
226 | { | ||
227 | int err; | ||
228 | if (!name) | ||
229 | return -EFAULT; | ||
230 | down_read(&uts_sem); | ||
231 | err = copy_to_user(name, utsname(), sizeof(*name)); | ||
232 | up_read(&uts_sem); | ||
233 | return err?-EFAULT:0; | ||
234 | } | ||
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 5bfde6c77498..2048a20d7c80 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S | |||
@@ -391,3 +391,5 @@ sys_call_table: | |||
391 | .long sys_pwritev | 391 | .long sys_pwritev |
392 | .long sys_rt_tgsigqueueinfo | 392 | .long sys_rt_tgsigqueueinfo |
393 | .long sys_perf_event_open | 393 | .long sys_perf_event_open |
394 | .long sys_recvmmsg /* 365 */ | ||
395 | .long sys_accept4 | ||
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 953fa1613312..8a0072de2bcc 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c | |||
@@ -39,12 +39,12 @@ static int null_rtc_set_time(const time_t secs) | |||
39 | void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; | 39 | void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; |
40 | int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; | 40 | int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; |
41 | 41 | ||
42 | #ifdef CONFIG_GENERIC_CMOS_UPDATE | ||
43 | void read_persistent_clock(struct timespec *ts) | 42 | void read_persistent_clock(struct timespec *ts) |
44 | { | 43 | { |
45 | rtc_sh_get_time(ts); | 44 | rtc_sh_get_time(ts); |
46 | } | 45 | } |
47 | 46 | ||
47 | #ifdef CONFIG_GENERIC_CMOS_UPDATE | ||
48 | int update_persistent_clock(struct timespec now) | 48 | int update_persistent_clock(struct timespec now) |
49 | { | 49 | { |
50 | return rtc_sh_set_time(now.tv_sec); | 50 | return rtc_sh_set_time(now.tv_sec); |
@@ -113,9 +113,5 @@ void __init time_init(void) | |||
113 | hwblk_init(); | 113 | hwblk_init(); |
114 | clk_init(); | 114 | clk_init(); |
115 | 115 | ||
116 | rtc_sh_get_time(&xtime); | ||
117 | set_normalized_timespec(&wall_to_monotonic, | ||
118 | -xtime.tv_sec, -xtime.tv_nsec); | ||
119 | |||
120 | late_time_init = sh_late_time_init; | 116 | late_time_init = sh_late_time_init; |
121 | } | 117 | } |
diff --git a/arch/sh/kernel/topology.c b/arch/sh/kernel/topology.c index 0838942b7083..9b0b633b6c92 100644 --- a/arch/sh/kernel/topology.c +++ b/arch/sh/kernel/topology.c | |||
@@ -16,6 +16,32 @@ | |||
16 | 16 | ||
17 | static DEFINE_PER_CPU(struct cpu, cpu_devices); | 17 | static DEFINE_PER_CPU(struct cpu, cpu_devices); |
18 | 18 | ||
19 | cpumask_t cpu_core_map[NR_CPUS]; | ||
20 | |||
21 | static cpumask_t cpu_coregroup_map(unsigned int cpu) | ||
22 | { | ||
23 | /* | ||
24 | * Presently all SH-X3 SMP cores are multi-cores, so just keep it | ||
25 | * simple until we have a method for determining topology.. | ||
26 | */ | ||
27 | return cpu_possible_map; | ||
28 | } | ||
29 | |||
30 | const struct cpumask *cpu_coregroup_mask(unsigned int cpu) | ||
31 | { | ||
32 | return &cpu_core_map[cpu]; | ||
33 | } | ||
34 | |||
35 | int arch_update_cpu_topology(void) | ||
36 | { | ||
37 | unsigned int cpu; | ||
38 | |||
39 | for_each_possible_cpu(cpu) | ||
40 | cpu_core_map[cpu] = cpu_coregroup_map(cpu); | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
19 | static int __init topology_init(void) | 45 | static int __init topology_init(void) |
20 | { | 46 | { |
21 | int i, ret; | 47 | int i, ret; |
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index a8396f36bd14..0830c2a9f712 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c | |||
@@ -9,8 +9,8 @@ | |||
9 | #include <asm/unwinder.h> | 9 | #include <asm/unwinder.h> |
10 | #include <asm/system.h> | 10 | #include <asm/system.h> |
11 | 11 | ||
12 | #ifdef CONFIG_BUG | 12 | #ifdef CONFIG_GENERIC_BUG |
13 | void handle_BUG(struct pt_regs *regs) | 13 | static void handle_BUG(struct pt_regs *regs) |
14 | { | 14 | { |
15 | const struct bug_entry *bug; | 15 | const struct bug_entry *bug; |
16 | unsigned long bugaddr = regs->pc; | 16 | unsigned long bugaddr = regs->pc; |
@@ -58,7 +58,7 @@ BUILD_TRAP_HANDLER(debug) | |||
58 | TRAP_HANDLER_DECL; | 58 | TRAP_HANDLER_DECL; |
59 | 59 | ||
60 | /* Rewind */ | 60 | /* Rewind */ |
61 | regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); | 61 | regs->pc -= instruction_size(__raw_readw(regs->pc - 4)); |
62 | 62 | ||
63 | if (notify_die(DIE_TRAP, "debug trap", regs, 0, vec & 0xff, | 63 | if (notify_die(DIE_TRAP, "debug trap", regs, 0, vec & 0xff, |
64 | SIGTRAP) == NOTIFY_STOP) | 64 | SIGTRAP) == NOTIFY_STOP) |
@@ -75,13 +75,13 @@ BUILD_TRAP_HANDLER(bug) | |||
75 | TRAP_HANDLER_DECL; | 75 | TRAP_HANDLER_DECL; |
76 | 76 | ||
77 | /* Rewind */ | 77 | /* Rewind */ |
78 | regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); | 78 | regs->pc -= instruction_size(__raw_readw(regs->pc - 4)); |
79 | 79 | ||
80 | if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff, | 80 | if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff, |
81 | SIGTRAP) == NOTIFY_STOP) | 81 | SIGTRAP) == NOTIFY_STOP) |
82 | return; | 82 | return; |
83 | 83 | ||
84 | #ifdef CONFIG_BUG | 84 | #ifdef CONFIG_GENERIC_BUG |
85 | if (__kernel_text_address(instruction_pointer(regs))) { | 85 | if (__kernel_text_address(instruction_pointer(regs))) { |
86 | insn_size_t insn = *(insn_size_t *)instruction_pointer(regs); | 86 | insn_size_t insn = *(insn_size_t *)instruction_pointer(regs); |
87 | if (insn == TRAPA_BUG_OPCODE) | 87 | if (insn == TRAPA_BUG_OPCODE) |
@@ -95,9 +95,11 @@ BUILD_TRAP_HANDLER(bug) | |||
95 | 95 | ||
96 | BUILD_TRAP_HANDLER(nmi) | 96 | BUILD_TRAP_HANDLER(nmi) |
97 | { | 97 | { |
98 | unsigned int cpu = smp_processor_id(); | ||
98 | TRAP_HANDLER_DECL; | 99 | TRAP_HANDLER_DECL; |
99 | 100 | ||
100 | nmi_enter(); | 101 | nmi_enter(); |
102 | nmi_count(cpu)++; | ||
101 | 103 | ||
102 | switch (notify_die(DIE_NMI, "NMI", regs, 0, vec & 0xff, SIGINT)) { | 104 | switch (notify_die(DIE_NMI, "NMI", regs, 0, vec & 0xff, SIGINT)) { |
103 | case NOTIFY_OK: | 105 | case NOTIFY_OK: |
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 7a2ee3a6b8e7..c3d86fa71ddf 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c | |||
@@ -24,10 +24,10 @@ | |||
24 | #include <linux/kdebug.h> | 24 | #include <linux/kdebug.h> |
25 | #include <linux/kexec.h> | 25 | #include <linux/kexec.h> |
26 | #include <linux/limits.h> | 26 | #include <linux/limits.h> |
27 | #include <linux/proc_fs.h> | ||
28 | #include <linux/sysfs.h> | 27 | #include <linux/sysfs.h> |
28 | #include <linux/uaccess.h> | ||
29 | #include <asm/system.h> | 29 | #include <asm/system.h> |
30 | #include <asm/uaccess.h> | 30 | #include <asm/alignment.h> |
31 | #include <asm/fpu.h> | 31 | #include <asm/fpu.h> |
32 | #include <asm/kprobes.h> | 32 | #include <asm/kprobes.h> |
33 | 33 | ||
@@ -46,85 +46,6 @@ | |||
46 | #define TRAP_ILLEGAL_SLOT_INST 13 | 46 | #define TRAP_ILLEGAL_SLOT_INST 13 |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | static unsigned long se_user; | ||
50 | static unsigned long se_sys; | ||
51 | static unsigned long se_half; | ||
52 | static unsigned long se_word; | ||
53 | static unsigned long se_dword; | ||
54 | static unsigned long se_multi; | ||
55 | /* bitfield: 1: warn 2: fixup 4: signal -> combinations 2|4 && 1|2|4 are not | ||
56 | valid! */ | ||
57 | static int se_usermode = 3; | ||
58 | /* 0: no warning 1: print a warning message, disabled by default */ | ||
59 | static int se_kernmode_warn; | ||
60 | |||
61 | #ifdef CONFIG_PROC_FS | ||
62 | static const char *se_usermode_action[] = { | ||
63 | "ignored", | ||
64 | "warn", | ||
65 | "fixup", | ||
66 | "fixup+warn", | ||
67 | "signal", | ||
68 | "signal+warn" | ||
69 | }; | ||
70 | |||
71 | static int | ||
72 | proc_alignment_read(char *page, char **start, off_t off, int count, int *eof, | ||
73 | void *data) | ||
74 | { | ||
75 | char *p = page; | ||
76 | int len; | ||
77 | |||
78 | p += sprintf(p, "User:\t\t%lu\n", se_user); | ||
79 | p += sprintf(p, "System:\t\t%lu\n", se_sys); | ||
80 | p += sprintf(p, "Half:\t\t%lu\n", se_half); | ||
81 | p += sprintf(p, "Word:\t\t%lu\n", se_word); | ||
82 | p += sprintf(p, "DWord:\t\t%lu\n", se_dword); | ||
83 | p += sprintf(p, "Multi:\t\t%lu\n", se_multi); | ||
84 | p += sprintf(p, "User faults:\t%i (%s)\n", se_usermode, | ||
85 | se_usermode_action[se_usermode]); | ||
86 | p += sprintf(p, "Kernel faults:\t%i (fixup%s)\n", se_kernmode_warn, | ||
87 | se_kernmode_warn ? "+warn" : ""); | ||
88 | |||
89 | len = (p - page) - off; | ||
90 | if (len < 0) | ||
91 | len = 0; | ||
92 | |||
93 | *eof = (len <= count) ? 1 : 0; | ||
94 | *start = page + off; | ||
95 | |||
96 | return len; | ||
97 | } | ||
98 | |||
99 | static int proc_alignment_write(struct file *file, const char __user *buffer, | ||
100 | unsigned long count, void *data) | ||
101 | { | ||
102 | char mode; | ||
103 | |||
104 | if (count > 0) { | ||
105 | if (get_user(mode, buffer)) | ||
106 | return -EFAULT; | ||
107 | if (mode >= '0' && mode <= '5') | ||
108 | se_usermode = mode - '0'; | ||
109 | } | ||
110 | return count; | ||
111 | } | ||
112 | |||
113 | static int proc_alignment_kern_write(struct file *file, const char __user *buffer, | ||
114 | unsigned long count, void *data) | ||
115 | { | ||
116 | char mode; | ||
117 | |||
118 | if (count > 0) { | ||
119 | if (get_user(mode, buffer)) | ||
120 | return -EFAULT; | ||
121 | if (mode >= '0' && mode <= '1') | ||
122 | se_kernmode_warn = mode - '0'; | ||
123 | } | ||
124 | return count; | ||
125 | } | ||
126 | #endif | ||
127 | |||
128 | static void dump_mem(const char *str, unsigned long bottom, unsigned long top) | 49 | static void dump_mem(const char *str, unsigned long bottom, unsigned long top) |
129 | { | 50 | { |
130 | unsigned long p; | 51 | unsigned long p; |
@@ -276,10 +197,10 @@ static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs, | |||
276 | count = 1<<(instruction&3); | 197 | count = 1<<(instruction&3); |
277 | 198 | ||
278 | switch (count) { | 199 | switch (count) { |
279 | case 1: se_half += 1; break; | 200 | case 1: inc_unaligned_byte_access(); break; |
280 | case 2: se_word += 1; break; | 201 | case 2: inc_unaligned_word_access(); break; |
281 | case 4: se_dword += 1; break; | 202 | case 4: inc_unaligned_dword_access(); break; |
282 | case 8: se_multi += 1; break; /* ??? */ | 203 | case 8: inc_unaligned_multi_access(); break; |
283 | } | 204 | } |
284 | 205 | ||
285 | ret = -EFAULT; | 206 | ret = -EFAULT; |
@@ -463,12 +384,8 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, | |||
463 | rm = regs->regs[index]; | 384 | rm = regs->regs[index]; |
464 | 385 | ||
465 | /* shout about fixups */ | 386 | /* shout about fixups */ |
466 | if (!expected && printk_ratelimit()) | 387 | if (!expected) |
467 | printk(KERN_NOTICE "Fixing up unaligned %s access " | 388 | unaligned_fixups_notify(current, instruction, regs); |
468 | "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", | ||
469 | user_mode(regs) ? "userspace" : "kernel", | ||
470 | current->comm, task_pid_nr(current), | ||
471 | (void *)regs->pc, instruction); | ||
472 | 389 | ||
473 | ret = -EFAULT; | 390 | ret = -EFAULT; |
474 | switch (instruction&0xF000) { | 391 | switch (instruction&0xF000) { |
@@ -621,10 +538,10 @@ asmlinkage void do_address_error(struct pt_regs *regs, | |||
621 | 538 | ||
622 | if (user_mode(regs)) { | 539 | if (user_mode(regs)) { |
623 | int si_code = BUS_ADRERR; | 540 | int si_code = BUS_ADRERR; |
541 | unsigned int user_action; | ||
624 | 542 | ||
625 | local_irq_enable(); | 543 | local_irq_enable(); |
626 | 544 | inc_unaligned_user_access(); | |
627 | se_user += 1; | ||
628 | 545 | ||
629 | set_fs(USER_DS); | 546 | set_fs(USER_DS); |
630 | if (copy_from_user(&instruction, (insn_size_t *)(regs->pc & ~1), | 547 | if (copy_from_user(&instruction, (insn_size_t *)(regs->pc & ~1), |
@@ -635,16 +552,12 @@ asmlinkage void do_address_error(struct pt_regs *regs, | |||
635 | set_fs(oldfs); | 552 | set_fs(oldfs); |
636 | 553 | ||
637 | /* shout about userspace fixups */ | 554 | /* shout about userspace fixups */ |
638 | if (se_usermode & 1) | 555 | unaligned_fixups_notify(current, instruction, regs); |
639 | printk(KERN_NOTICE "Unaligned userspace access " | ||
640 | "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", | ||
641 | current->comm, current->pid, (void *)regs->pc, | ||
642 | instruction); | ||
643 | 556 | ||
644 | if (se_usermode & 2) | 557 | user_action = unaligned_user_action(); |
558 | if (user_action & UM_FIXUP) | ||
645 | goto fixup; | 559 | goto fixup; |
646 | 560 | if (user_action & UM_SIGNAL) | |
647 | if (se_usermode & 4) | ||
648 | goto uspace_segv; | 561 | goto uspace_segv; |
649 | else { | 562 | else { |
650 | /* ignore */ | 563 | /* ignore */ |
@@ -664,7 +577,7 @@ fixup: | |||
664 | &user_mem_access, 0); | 577 | &user_mem_access, 0); |
665 | set_fs(oldfs); | 578 | set_fs(oldfs); |
666 | 579 | ||
667 | if (tmp==0) | 580 | if (tmp == 0) |
668 | return; /* sorted */ | 581 | return; /* sorted */ |
669 | uspace_segv: | 582 | uspace_segv: |
670 | printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " | 583 | printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " |
@@ -677,7 +590,7 @@ uspace_segv: | |||
677 | info.si_addr = (void __user *)address; | 590 | info.si_addr = (void __user *)address; |
678 | force_sig_info(SIGBUS, &info, current); | 591 | force_sig_info(SIGBUS, &info, current); |
679 | } else { | 592 | } else { |
680 | se_sys += 1; | 593 | inc_unaligned_kernel_access(); |
681 | 594 | ||
682 | if (regs->pc & 1) | 595 | if (regs->pc & 1) |
683 | die("unaligned program counter", regs, error_code); | 596 | die("unaligned program counter", regs, error_code); |
@@ -692,11 +605,7 @@ uspace_segv: | |||
692 | die("insn faulting in do_address_error", regs, 0); | 605 | die("insn faulting in do_address_error", regs, 0); |
693 | } | 606 | } |
694 | 607 | ||
695 | if (se_kernmode_warn) | 608 | unaligned_fixups_notify(current, instruction, regs); |
696 | printk(KERN_NOTICE "Unaligned kernel access " | ||
697 | "on behalf of \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", | ||
698 | current->comm, current->pid, (void *)regs->pc, | ||
699 | instruction); | ||
700 | 609 | ||
701 | handle_unaligned_access(instruction, regs, | 610 | handle_unaligned_access(instruction, regs, |
702 | &user_mem_access, 0); | 611 | &user_mem_access, 0); |
@@ -881,35 +790,10 @@ asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, | |||
881 | die_if_kernel("exception", regs, ex); | 790 | die_if_kernel("exception", regs, ex); |
882 | } | 791 | } |
883 | 792 | ||
884 | #if defined(CONFIG_SH_STANDARD_BIOS) | ||
885 | void *gdb_vbr_vector; | ||
886 | |||
887 | static inline void __init gdb_vbr_init(void) | ||
888 | { | ||
889 | register unsigned long vbr; | ||
890 | |||
891 | /* | ||
892 | * Read the old value of the VBR register to initialise | ||
893 | * the vector through which debug and BIOS traps are | ||
894 | * delegated by the Linux trap handler. | ||
895 | */ | ||
896 | asm volatile("stc vbr, %0" : "=r" (vbr)); | ||
897 | |||
898 | gdb_vbr_vector = (void *)(vbr + 0x100); | ||
899 | printk("Setting GDB trap vector to 0x%08lx\n", | ||
900 | (unsigned long)gdb_vbr_vector); | ||
901 | } | ||
902 | #endif | ||
903 | |||
904 | void __cpuinit per_cpu_trap_init(void) | 793 | void __cpuinit per_cpu_trap_init(void) |
905 | { | 794 | { |
906 | extern void *vbr_base; | 795 | extern void *vbr_base; |
907 | 796 | ||
908 | #ifdef CONFIG_SH_STANDARD_BIOS | ||
909 | if (raw_smp_processor_id() == 0) | ||
910 | gdb_vbr_init(); | ||
911 | #endif | ||
912 | |||
913 | /* NOTE: The VBR value should be at P1 | 797 | /* NOTE: The VBR value should be at P1 |
914 | (or P2, virtural "fixed" address space). | 798 | (or P2, virtural "fixed" address space). |
915 | It's definitely should not in physical address. */ | 799 | It's definitely should not in physical address. */ |
@@ -945,14 +829,9 @@ void __init trap_init(void) | |||
945 | set_exception_table_evt(0x800, do_reserved_inst); | 829 | set_exception_table_evt(0x800, do_reserved_inst); |
946 | set_exception_table_evt(0x820, do_illegal_slot_inst); | 830 | set_exception_table_evt(0x820, do_illegal_slot_inst); |
947 | #elif defined(CONFIG_SH_FPU) | 831 | #elif defined(CONFIG_SH_FPU) |
948 | #ifdef CONFIG_CPU_SUBTYPE_SHX3 | ||
949 | set_exception_table_evt(0xd80, fpu_state_restore_trap_handler); | ||
950 | set_exception_table_evt(0xda0, fpu_state_restore_trap_handler); | ||
951 | #else | ||
952 | set_exception_table_evt(0x800, fpu_state_restore_trap_handler); | 832 | set_exception_table_evt(0x800, fpu_state_restore_trap_handler); |
953 | set_exception_table_evt(0x820, fpu_state_restore_trap_handler); | 833 | set_exception_table_evt(0x820, fpu_state_restore_trap_handler); |
954 | #endif | 834 | #endif |
955 | #endif | ||
956 | 835 | ||
957 | #ifdef CONFIG_CPU_SH2 | 836 | #ifdef CONFIG_CPU_SH2 |
958 | set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_trap_handler); | 837 | set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_trap_handler); |
@@ -966,11 +845,8 @@ void __init trap_init(void) | |||
966 | #endif | 845 | #endif |
967 | 846 | ||
968 | #ifdef TRAP_UBC | 847 | #ifdef TRAP_UBC |
969 | set_exception_table_vec(TRAP_UBC, break_point_trap); | 848 | set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler); |
970 | #endif | 849 | #endif |
971 | |||
972 | /* Setup VBR for boot cpu */ | ||
973 | per_cpu_trap_init(); | ||
974 | } | 850 | } |
975 | 851 | ||
976 | void show_stack(struct task_struct *tsk, unsigned long *sp) | 852 | void show_stack(struct task_struct *tsk, unsigned long *sp) |
@@ -995,38 +871,3 @@ void dump_stack(void) | |||
995 | show_stack(NULL, NULL); | 871 | show_stack(NULL, NULL); |
996 | } | 872 | } |
997 | EXPORT_SYMBOL(dump_stack); | 873 | EXPORT_SYMBOL(dump_stack); |
998 | |||
999 | #ifdef CONFIG_PROC_FS | ||
1000 | /* | ||
1001 | * This needs to be done after sysctl_init, otherwise sys/ will be | ||
1002 | * overwritten. Actually, this shouldn't be in sys/ at all since | ||
1003 | * it isn't a sysctl, and it doesn't contain sysctl information. | ||
1004 | * We now locate it in /proc/cpu/alignment instead. | ||
1005 | */ | ||
1006 | static int __init alignment_init(void) | ||
1007 | { | ||
1008 | struct proc_dir_entry *dir, *res; | ||
1009 | |||
1010 | dir = proc_mkdir("cpu", NULL); | ||
1011 | if (!dir) | ||
1012 | return -ENOMEM; | ||
1013 | |||
1014 | res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, dir); | ||
1015 | if (!res) | ||
1016 | return -ENOMEM; | ||
1017 | |||
1018 | res->read_proc = proc_alignment_read; | ||
1019 | res->write_proc = proc_alignment_write; | ||
1020 | |||
1021 | res = create_proc_entry("kernel_alignment", S_IWUSR | S_IRUGO, dir); | ||
1022 | if (!res) | ||
1023 | return -ENOMEM; | ||
1024 | |||
1025 | res->read_proc = proc_alignment_read; | ||
1026 | res->write_proc = proc_alignment_kern_write; | ||
1027 | |||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | fs_initcall(alignment_init); | ||
1032 | #endif | ||
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c index 267e5ebbb475..e3f92eb05ffd 100644 --- a/arch/sh/kernel/traps_64.c +++ b/arch/sh/kernel/traps_64.c | |||
@@ -600,7 +600,7 @@ static int misaligned_fpu_load(struct pt_regs *regs, | |||
600 | indexed by register number. */ | 600 | indexed by register number. */ |
601 | if (last_task_used_math == current) { | 601 | if (last_task_used_math == current) { |
602 | enable_fpu(); | 602 | enable_fpu(); |
603 | save_fpu(current, regs); | 603 | save_fpu(current); |
604 | disable_fpu(); | 604 | disable_fpu(); |
605 | last_task_used_math = NULL; | 605 | last_task_used_math = NULL; |
606 | regs->sr |= SR_FD; | 606 | regs->sr |= SR_FD; |
@@ -611,19 +611,19 @@ static int misaligned_fpu_load(struct pt_regs *regs, | |||
611 | 611 | ||
612 | switch (width_shift) { | 612 | switch (width_shift) { |
613 | case 2: | 613 | case 2: |
614 | current->thread.fpu.hard.fp_regs[destreg] = buflo; | 614 | current->thread.xstate->hardfpu.fp_regs[destreg] = buflo; |
615 | break; | 615 | break; |
616 | case 3: | 616 | case 3: |
617 | if (do_paired_load) { | 617 | if (do_paired_load) { |
618 | current->thread.fpu.hard.fp_regs[destreg] = buflo; | 618 | current->thread.xstate->hardfpu.fp_regs[destreg] = buflo; |
619 | current->thread.fpu.hard.fp_regs[destreg+1] = bufhi; | 619 | current->thread.xstate->hardfpu.fp_regs[destreg+1] = bufhi; |
620 | } else { | 620 | } else { |
621 | #if defined(CONFIG_CPU_LITTLE_ENDIAN) | 621 | #if defined(CONFIG_CPU_LITTLE_ENDIAN) |
622 | current->thread.fpu.hard.fp_regs[destreg] = bufhi; | 622 | current->thread.xstate->hardfpu.fp_regs[destreg] = bufhi; |
623 | current->thread.fpu.hard.fp_regs[destreg+1] = buflo; | 623 | current->thread.xstate->hardfpu.fp_regs[destreg+1] = buflo; |
624 | #else | 624 | #else |
625 | current->thread.fpu.hard.fp_regs[destreg] = buflo; | 625 | current->thread.xstate->hardfpu.fp_regs[destreg] = buflo; |
626 | current->thread.fpu.hard.fp_regs[destreg+1] = bufhi; | 626 | current->thread.xstate->hardfpu.fp_regs[destreg+1] = bufhi; |
627 | #endif | 627 | #endif |
628 | } | 628 | } |
629 | break; | 629 | break; |
@@ -673,7 +673,7 @@ static int misaligned_fpu_store(struct pt_regs *regs, | |||
673 | indexed by register number. */ | 673 | indexed by register number. */ |
674 | if (last_task_used_math == current) { | 674 | if (last_task_used_math == current) { |
675 | enable_fpu(); | 675 | enable_fpu(); |
676 | save_fpu(current, regs); | 676 | save_fpu(current); |
677 | disable_fpu(); | 677 | disable_fpu(); |
678 | last_task_used_math = NULL; | 678 | last_task_used_math = NULL; |
679 | regs->sr |= SR_FD; | 679 | regs->sr |= SR_FD; |
@@ -681,19 +681,19 @@ static int misaligned_fpu_store(struct pt_regs *regs, | |||
681 | 681 | ||
682 | switch (width_shift) { | 682 | switch (width_shift) { |
683 | case 2: | 683 | case 2: |
684 | buflo = current->thread.fpu.hard.fp_regs[srcreg]; | 684 | buflo = current->thread.xstate->hardfpu.fp_regs[srcreg]; |
685 | break; | 685 | break; |
686 | case 3: | 686 | case 3: |
687 | if (do_paired_load) { | 687 | if (do_paired_load) { |
688 | buflo = current->thread.fpu.hard.fp_regs[srcreg]; | 688 | buflo = current->thread.xstate->hardfpu.fp_regs[srcreg]; |
689 | bufhi = current->thread.fpu.hard.fp_regs[srcreg+1]; | 689 | bufhi = current->thread.xstate->hardfpu.fp_regs[srcreg+1]; |
690 | } else { | 690 | } else { |
691 | #if defined(CONFIG_CPU_LITTLE_ENDIAN) | 691 | #if defined(CONFIG_CPU_LITTLE_ENDIAN) |
692 | bufhi = current->thread.fpu.hard.fp_regs[srcreg]; | 692 | bufhi = current->thread.xstate->hardfpu.fp_regs[srcreg]; |
693 | buflo = current->thread.fpu.hard.fp_regs[srcreg+1]; | 693 | buflo = current->thread.xstate->hardfpu.fp_regs[srcreg+1]; |
694 | #else | 694 | #else |
695 | buflo = current->thread.fpu.hard.fp_regs[srcreg]; | 695 | buflo = current->thread.xstate->hardfpu.fp_regs[srcreg]; |
696 | bufhi = current->thread.fpu.hard.fp_regs[srcreg+1]; | 696 | bufhi = current->thread.xstate->hardfpu.fp_regs[srcreg+1]; |
697 | #endif | 697 | #endif |
698 | } | 698 | } |
699 | break; | 699 | break; |
@@ -877,44 +877,39 @@ static int misaligned_fixup(struct pt_regs *regs) | |||
877 | 877 | ||
878 | static ctl_table unaligned_table[] = { | 878 | static ctl_table unaligned_table[] = { |
879 | { | 879 | { |
880 | .ctl_name = CTL_UNNUMBERED, | ||
881 | .procname = "kernel_reports", | 880 | .procname = "kernel_reports", |
882 | .data = &kernel_mode_unaligned_fixup_count, | 881 | .data = &kernel_mode_unaligned_fixup_count, |
883 | .maxlen = sizeof(int), | 882 | .maxlen = sizeof(int), |
884 | .mode = 0644, | 883 | .mode = 0644, |
885 | .proc_handler = &proc_dointvec | 884 | .proc_handler = proc_dointvec |
886 | }, | 885 | }, |
887 | { | 886 | { |
888 | .ctl_name = CTL_UNNUMBERED, | ||
889 | .procname = "user_reports", | 887 | .procname = "user_reports", |
890 | .data = &user_mode_unaligned_fixup_count, | 888 | .data = &user_mode_unaligned_fixup_count, |
891 | .maxlen = sizeof(int), | 889 | .maxlen = sizeof(int), |
892 | .mode = 0644, | 890 | .mode = 0644, |
893 | .proc_handler = &proc_dointvec | 891 | .proc_handler = proc_dointvec |
894 | }, | 892 | }, |
895 | { | 893 | { |
896 | .ctl_name = CTL_UNNUMBERED, | ||
897 | .procname = "user_enable", | 894 | .procname = "user_enable", |
898 | .data = &user_mode_unaligned_fixup_enable, | 895 | .data = &user_mode_unaligned_fixup_enable, |
899 | .maxlen = sizeof(int), | 896 | .maxlen = sizeof(int), |
900 | .mode = 0644, | 897 | .mode = 0644, |
901 | .proc_handler = &proc_dointvec}, | 898 | .proc_handler = proc_dointvec}, |
902 | {} | 899 | {} |
903 | }; | 900 | }; |
904 | 901 | ||
905 | static ctl_table unaligned_root[] = { | 902 | static ctl_table unaligned_root[] = { |
906 | { | 903 | { |
907 | .ctl_name = CTL_UNNUMBERED, | ||
908 | .procname = "unaligned_fixup", | 904 | .procname = "unaligned_fixup", |
909 | .mode = 0555, | 905 | .mode = 0555, |
910 | unaligned_table | 906 | .child = unaligned_table |
911 | }, | 907 | }, |
912 | {} | 908 | {} |
913 | }; | 909 | }; |
914 | 910 | ||
915 | static ctl_table sh64_root[] = { | 911 | static ctl_table sh64_root[] = { |
916 | { | 912 | { |
917 | .ctl_name = CTL_UNNUMBERED, | ||
918 | .procname = "sh64", | 913 | .procname = "sh64", |
919 | .mode = 0555, | 914 | .mode = 0555, |
920 | .child = unaligned_root | 915 | .child = unaligned_root |
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index a1e4ec24f1f5..7f8a709c3ada 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S | |||
@@ -3,7 +3,7 @@ | |||
3 | * Written by Niibe Yutaka and Paul Mundt | 3 | * Written by Niibe Yutaka and Paul Mundt |
4 | */ | 4 | */ |
5 | #ifdef CONFIG_SUPERH64 | 5 | #ifdef CONFIG_SUPERH64 |
6 | #define LOAD_OFFSET CONFIG_PAGE_OFFSET | 6 | #define LOAD_OFFSET PAGE_OFFSET |
7 | OUTPUT_ARCH(sh:sh5) | 7 | OUTPUT_ARCH(sh:sh5) |
8 | #else | 8 | #else |
9 | #define LOAD_OFFSET 0 | 9 | #define LOAD_OFFSET 0 |
@@ -14,17 +14,16 @@ OUTPUT_ARCH(sh) | |||
14 | #include <asm/cache.h> | 14 | #include <asm/cache.h> |
15 | #include <asm/vmlinux.lds.h> | 15 | #include <asm/vmlinux.lds.h> |
16 | 16 | ||
17 | #ifdef CONFIG_PMB | ||
18 | #define MEMORY_OFFSET 0 | ||
19 | #else | ||
20 | #define MEMORY_OFFSET __MEMORY_START | ||
21 | #endif | ||
22 | |||
17 | ENTRY(_start) | 23 | ENTRY(_start) |
18 | SECTIONS | 24 | SECTIONS |
19 | { | 25 | { |
20 | #ifdef CONFIG_PMB_FIXED | 26 | . = PAGE_OFFSET + MEMORY_OFFSET + CONFIG_ZERO_PAGE_OFFSET; |
21 | . = CONFIG_PAGE_OFFSET + (CONFIG_MEMORY_START & 0x1fffffff) + | ||
22 | CONFIG_ZERO_PAGE_OFFSET; | ||
23 | #elif defined(CONFIG_32BIT) | ||
24 | . = CONFIG_PAGE_OFFSET + CONFIG_ZERO_PAGE_OFFSET; | ||
25 | #else | ||
26 | . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET; | ||
27 | #endif | ||
28 | 27 | ||
29 | _text = .; /* Text and read-only data */ | 28 | _text = .; /* Text and read-only data */ |
30 | 29 | ||
@@ -35,12 +34,7 @@ SECTIONS | |||
35 | .text : AT(ADDR(.text) - LOAD_OFFSET) { | 34 | .text : AT(ADDR(.text) - LOAD_OFFSET) { |
36 | HEAD_TEXT | 35 | HEAD_TEXT |
37 | TEXT_TEXT | 36 | TEXT_TEXT |
38 | 37 | EXTRA_TEXT | |
39 | #ifdef CONFIG_SUPERH64 | ||
40 | *(.text64) | ||
41 | *(.text..SHmedia32) | ||
42 | #endif | ||
43 | |||
44 | SCHED_TEXT | 38 | SCHED_TEXT |
45 | LOCK_TEXT | 39 | LOCK_TEXT |
46 | KPROBES_TEXT | 40 | KPROBES_TEXT |
@@ -51,24 +45,12 @@ SECTIONS | |||
51 | } = 0x0009 | 45 | } = 0x0009 |
52 | 46 | ||
53 | EXCEPTION_TABLE(16) | 47 | EXCEPTION_TABLE(16) |
54 | |||
55 | NOTES | 48 | NOTES |
56 | RO_DATA(PAGE_SIZE) | ||
57 | |||
58 | /* | ||
59 | * Code which must be executed uncached and the associated data | ||
60 | */ | ||
61 | . = ALIGN(PAGE_SIZE); | ||
62 | .uncached : AT(ADDR(.uncached) - LOAD_OFFSET) { | ||
63 | __uncached_start = .; | ||
64 | *(.uncached.text) | ||
65 | *(.uncached.data) | ||
66 | __uncached_end = .; | ||
67 | } | ||
68 | 49 | ||
50 | _sdata = .; | ||
51 | RO_DATA(PAGE_SIZE) | ||
69 | RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) | 52 | RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) |
70 | 53 | _edata = .; | |
71 | _edata = .; /* End of data section */ | ||
72 | 54 | ||
73 | DWARF_EH_FRAME | 55 | DWARF_EH_FRAME |
74 | 56 | ||
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c index 3f7e415be86a..242117cbad67 100644 --- a/arch/sh/kernel/vsyscall/vsyscall.c +++ b/arch/sh/kernel/vsyscall/vsyscall.c | |||
@@ -11,7 +11,6 @@ | |||
11 | * for more details. | 11 | * for more details. |
12 | */ | 12 | */ |
13 | #include <linux/mm.h> | 13 | #include <linux/mm.h> |
14 | #include <linux/slab.h> | ||
15 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
16 | #include <linux/init.h> | 15 | #include <linux/init.h> |
17 | #include <linux/gfp.h> | 16 | #include <linux/gfp.h> |