From 4a4a9be3ebdbf17957d29e3521f328a1145f9431 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 12 Nov 2008 13:17:38 +0900 Subject: sh: Move arch_get_unmapped_area() in to arch/sh/mm/mmap.c. Now that arch/sh/mm/mmap.c exists, move arch_get_unmapped_area() there. Follows the ARM change. Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/init.c | 2 ++ arch/sh/kernel/sys_sh.c | 92 ----------------------------------------------- 2 files changed, 2 insertions(+), 92 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index 75fb03d35670..d29e69c156f0 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -261,9 +261,11 @@ asmlinkage void __init sh_cpu_init(void) cache_init(); if (raw_smp_processor_id() == 0) { +#ifdef CONFIG_MMU shm_align_mask = max_t(unsigned long, current_cpu_data.dcache.way_size - 1, PAGE_SIZE - 1); +#endif /* Boot CPU sets the cache shape */ detect_cache_shape(); diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 38f098c9c72d..58dfc02c7af1 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c @@ -22,102 +22,10 @@ #include #include #include -#include #include #include #include -unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ -EXPORT_SYMBOL(shm_align_mask); - -#ifdef CONFIG_MMU -/* - * To avoid cache aliases, we map the shared page with same color. - */ -#define COLOUR_ALIGN(addr, pgoff) \ - ((((addr) + shm_align_mask) & ~shm_align_mask) + \ - (((pgoff) << PAGE_SHIFT) & shm_align_mask)) - -unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) -{ - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - unsigned long start_addr; - int do_colour_align; - - if (flags & MAP_FIXED) { - /* We do not accept a shared mapping if it would violate - * cache aliasing constraints. - */ - if ((flags & MAP_SHARED) && (addr & shm_align_mask)) - return -EINVAL; - return addr; - } - - if (unlikely(len > TASK_SIZE)) - return -ENOMEM; - - do_colour_align = 0; - if (filp || (flags & MAP_SHARED)) - do_colour_align = 1; - - if (addr) { - if (do_colour_align) - addr = COLOUR_ALIGN(addr, pgoff); - else - addr = PAGE_ALIGN(addr); - - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && - (!vma || addr + len <= vma->vm_start)) - return addr; - } - - if (len > mm->cached_hole_size) { - start_addr = addr = mm->free_area_cache; - } else { - mm->cached_hole_size = 0; - start_addr = addr = TASK_UNMAPPED_BASE; - } - -full_search: - if (do_colour_align) - addr = COLOUR_ALIGN(addr, pgoff); - else - addr = PAGE_ALIGN(mm->free_area_cache); - - for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { - /* At this point: (!vma || addr < vma->vm_end). */ - if (unlikely(TASK_SIZE - len < addr)) { - /* - * Start a new search - just in case we missed - * some holes. - */ - if (start_addr != TASK_UNMAPPED_BASE) { - start_addr = addr = TASK_UNMAPPED_BASE; - mm->cached_hole_size = 0; - goto full_search; - } - return -ENOMEM; - } - if (likely(!vma || addr + len <= vma->vm_start)) { - /* - * Remember the place where we stopped the search: - */ - mm->free_area_cache = addr + len; - return addr; - } - if (addr + mm->cached_hole_size < vma->vm_start) - mm->cached_hole_size = vma->vm_start - addr; - - addr = vma->vm_end; - if (do_colour_align) - addr = COLOUR_ALIGN(addr, pgoff); - } -} -#endif /* CONFIG_MMU */ - static inline long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, int fd, unsigned long pgoff) -- cgit v1.2.1 From d12cfac146d2b512496bf974b83ee1210032065f Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:13:32 +0900 Subject: sh: enable and disable clocks recursively Recurse and make sure parent clocks get enabled/disabled. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/clock.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index b7e46d5bba43..717056b3d400 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -117,6 +117,11 @@ int clk_enable(struct clk *clk) unsigned long flags; int ret; + if (!clk) + return -EINVAL; + + clk_enable(clk->parent); + spin_lock_irqsave(&clock_lock, flags); ret = __clk_enable(clk); spin_unlock_irqrestore(&clock_lock, flags); @@ -147,9 +152,14 @@ void clk_disable(struct clk *clk) { unsigned long flags; + if (!clk) + return -EINVAL; + spin_lock_irqsave(&clock_lock, flags); __clk_disable(clk); spin_unlock_irqrestore(&clock_lock, flags); + + clk_disable(clk->parent); } EXPORT_SYMBOL_GPL(clk_disable); -- cgit v1.2.1 From d902d04f5410176bdec77bfefa032516326eb542 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:14:03 +0900 Subject: sh: sh_mobile clock divider index fix Use divider index value instead of divider value. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index db913855c2fd..ebf1e1d7de00 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -229,7 +229,7 @@ struct frqcr_context sh7722_get_clk_context(const char *name) } /** - * sh7722_find_divisors - find divisor for setting rate + * sh7722_find_div_index - find divisor for setting rate * * All sh7722 clocks use the same set of multipliers/divisors. This function * chooses correct divisor to set the rate of clock with parent clock that @@ -238,7 +238,7 @@ struct frqcr_context sh7722_get_clk_context(const char *name) * @parent_rate: rate of parent clock * @rate: requested rate to be set */ -static int sh7722_find_divisors(unsigned long parent_rate, unsigned rate) +static int sh7722_find_div_index(unsigned long parent_rate, unsigned rate) { unsigned div2 = parent_rate * 2 / rate; int index; @@ -247,12 +247,12 @@ static int sh7722_find_divisors(unsigned long parent_rate, unsigned rate) return -EINVAL; for (index = 1; index < ARRAY_SIZE(divisors2); index++) { - if (div2 > divisors2[index] && div2 <= divisors2[index]) + if (div2 > divisors2[index - 1] && div2 <= divisors2[index]) break; } if (index >= ARRAY_SIZE(divisors2)) index = ARRAY_SIZE(divisors2) - 1; - return divisors2[index]; + return index; } static void sh7722_frqcr_recalc(struct clk *clk) @@ -279,12 +279,12 @@ static int sh7722_frqcr_set_rate(struct clk *clk, unsigned long rate, return -EINVAL; /* look for multiplier/divisor pair */ - div = sh7722_find_divisors(parent_rate, rate); + div = sh7722_find_div_index(parent_rate, rate); if (div<0) return div; /* calculate new value of clock rate */ - clk->rate = parent_rate * 2 / div; + clk->rate = parent_rate * 2 / divisors2[div]; frqcr = ctrl_inl(FRQCR); /* FIXME: adjust as algo_id specifies */ @@ -353,7 +353,7 @@ static int sh7722_frqcr_set_rate(struct clk *clk, unsigned long rate, int part_div; if (likely(!err)) { - part_div = sh7722_find_divisors(parent_rate, + part_div = sh7722_find_div_index(parent_rate, rate); if (part_div > 0) { part_ctx = sh7722_get_clk_context( @@ -394,12 +394,12 @@ static long sh7722_frqcr_round_rate(struct clk *clk, unsigned long rate) int div; /* look for multiplier/divisor pair */ - div = sh7722_find_divisors(parent_rate, rate); + div = sh7722_find_div_index(parent_rate, rate); if (div < 0) return clk->rate; /* calculate new value of clock rate */ - return parent_rate * 2 / div; + return parent_rate * 2 / divisors2[div]; } static struct clk_ops sh7722_frqcr_clk_ops = { @@ -421,7 +421,7 @@ static int sh7722_siu_set_rate(struct clk *clk, unsigned long rate, int algo_id) int div; r = ctrl_inl(clk->arch_flags); - div = sh7722_find_divisors(clk->parent->rate, rate); + div = sh7722_find_div_index(clk->parent->rate, rate); if (div < 0) return div; r = (r & ~0xF) | div; -- cgit v1.2.1 From 1dc7b776d91ac9f016982e418e74cb14f63c5b02 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:14:28 +0900 Subject: sh: use arch_flags for sh_mobile mstpcr clock bits Use arch_flags to keep track of register and flag number. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 72 ++++++++++++++-------------------- 1 file changed, 30 insertions(+), 42 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index ebf1e1d7de00..69ab62dd0158 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -567,12 +567,30 @@ static struct clk sh7722_video_clock = { .ops = &sh7722_video_clk_ops, }; -static int sh7722_mstpcr_start_stop(struct clk *clk, unsigned long reg, - int enable) +#define MSTPCR_ARCH_FLAGS(reg, bit) (((reg) << 8) | (bit)) +#define MSTPCR_ARCH_FLAGS_REG(value) ((value) >> 8) +#define MSTPCR_ARCH_FLAGS_BIT(value) ((value) & 0xff) + +static int sh7722_mstpcr_start_stop(struct clk *clk, int enable) { - unsigned long bit = clk->arch_flags; + unsigned long bit = MSTPCR_ARCH_FLAGS_BIT(clk->arch_flags); + unsigned long reg; unsigned long r; + switch(MSTPCR_ARCH_FLAGS_REG(clk->arch_flags)) { + case 0: + reg = MSTPCR0; + break; + case 1: + reg = MSTPCR1; + break; + case 2: + reg = MSTPCR2; + break; + default: + return -EINVAL; + } + r = ctrl_inl(reg); if (enable) @@ -584,56 +602,26 @@ static int sh7722_mstpcr_start_stop(struct clk *clk, unsigned long reg, return 0; } -static void sh7722_mstpcr0_enable(struct clk *clk) -{ - sh7722_mstpcr_start_stop(clk, MSTPCR0, 1); -} - -static void sh7722_mstpcr0_disable(struct clk *clk) +static void sh7722_mstpcr_enable(struct clk *clk) { - sh7722_mstpcr_start_stop(clk, MSTPCR0, 0); + sh7722_mstpcr_start_stop(clk, 1); } -static void sh7722_mstpcr1_enable(struct clk *clk) +static void sh7722_mstpcr_disable(struct clk *clk) { - sh7722_mstpcr_start_stop(clk, MSTPCR1, 1); + sh7722_mstpcr_start_stop(clk, 0); } -static void sh7722_mstpcr1_disable(struct clk *clk) -{ - sh7722_mstpcr_start_stop(clk, MSTPCR1, 0); -} - -static void sh7722_mstpcr2_enable(struct clk *clk) -{ - sh7722_mstpcr_start_stop(clk, MSTPCR2, 1); -} - -static void sh7722_mstpcr2_disable(struct clk *clk) -{ - sh7722_mstpcr_start_stop(clk, MSTPCR2, 0); -} - -static struct clk_ops sh7722_mstpcr0_clk_ops = { - .enable = sh7722_mstpcr0_enable, - .disable = sh7722_mstpcr0_disable, -}; - -static struct clk_ops sh7722_mstpcr1_clk_ops = { - .enable = sh7722_mstpcr1_enable, - .disable = sh7722_mstpcr1_disable, -}; - -static struct clk_ops sh7722_mstpcr2_clk_ops = { - .enable = sh7722_mstpcr2_enable, - .disable = sh7722_mstpcr2_disable, +static struct clk_ops sh7722_mstpcr_clk_ops = { + .enable = sh7722_mstpcr_enable, + .disable = sh7722_mstpcr_disable, }; #define DECLARE_MSTPCRN(regnr, bitnr, bitstr) \ { \ .name = "mstp" __stringify(regnr) bitstr, \ - .arch_flags = bitnr, \ - .ops = &sh7722_mstpcr ## regnr ## _clk_ops, \ + .arch_flags = MSTPCR_ARCH_FLAGS(regnr, bitnr), \ + .ops = &sh7722_mstpcr_clk_ops, \ } #define DECLARE_MSTPCR(regnr) \ -- cgit v1.2.1 From 7c7e02a28b4e7212dcdcc24bbd2b137790504a84 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:15:07 +0900 Subject: sh: new sh_mobile mstpcr clocks base code Add base code to handle new mstpcr clocks. Make sure clock rates propagate. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 45 +++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 69ab62dd0158..c7155f9b10f5 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -516,16 +516,19 @@ static struct clk_ops sh7722_video_clk_ops = { static struct clk sh7722_umem_clock = { .name = "umem_clk", .ops = &sh7722_frqcr_clk_ops, + .flags = CLK_RATE_PROPAGATES, }; static struct clk sh7722_sh_clock = { .name = "sh_clk", .ops = &sh7722_frqcr_clk_ops, + .flags = CLK_RATE_PROPAGATES, }; static struct clk sh7722_peripheral_clock = { .name = "peripheral_clk", .ops = &sh7722_frqcr_clk_ops, + .flags = CLK_RATE_PROPAGATES, }; static struct clk sh7722_sdram_clock = { @@ -533,6 +536,11 @@ static struct clk sh7722_sdram_clock = { .ops = &sh7722_frqcr_clk_ops, }; +static struct clk sh7722_r_clock = { + .name = "r_clk", + .rate = 32768, + .flags = CLK_RATE_PROPAGATES, +}; #ifndef CONFIG_CPU_SUBTYPE_SH7343 @@ -612,9 +620,16 @@ static void sh7722_mstpcr_disable(struct clk *clk) sh7722_mstpcr_start_stop(clk, 0); } +static void sh7722_mstpcr_recalc(struct clk *clk) +{ + if (clk->parent) + clk->rate = clk->parent->rate; +} + static struct clk_ops sh7722_mstpcr_clk_ops = { .enable = sh7722_mstpcr_enable, .disable = sh7722_mstpcr_disable, + .recalc = sh7722_mstpcr_recalc, }; #define DECLARE_MSTPCRN(regnr, bitnr, bitstr) \ @@ -664,6 +679,16 @@ static struct clk sh7722_mstpcr[] = { DECLARE_MSTPCR(2), }; +#define MSTPCR(_name, _parent, regnr, bitnr) \ +{ \ + .name = _name, \ + .arch_flags = MSTPCR_ARCH_FLAGS(regnr, bitnr), \ + .ops = (void *)_parent, \ +} + +static struct clk sh7722_mstpcr_clocks[] = { +}; + static struct clk *sh7722_clocks[] = { &sh7722_umem_clock, &sh7722_sh_clock, @@ -698,16 +723,28 @@ arch_init_clk_ops(struct clk_ops **ops, int type) int __init arch_clk_init(void) { - struct clk *master; + struct clk *clk; int i; - master = clk_get(NULL, "master_clk"); + clk = clk_get(NULL, "master_clk"); for (i = 0; i < ARRAY_SIZE(sh7722_clocks); i++) { pr_debug( "Registering clock '%s'\n", sh7722_clocks[i]->name); - sh7722_clocks[i]->parent = master; + sh7722_clocks[i]->parent = clk; clk_register(sh7722_clocks[i]); } - clk_put(master); + clk_put(clk); + + clk_register(&sh7722_r_clock); + + for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr_clocks); i++) { + pr_debug( "Registering mstpcr clock '%s'\n", + sh7722_mstpcr_clocks[i].name); + clk = clk_get(NULL, (void *) sh7722_mstpcr_clocks[i].ops); + sh7722_mstpcr_clocks[i].parent = clk; + sh7722_mstpcr_clocks[i].ops = &sh7722_mstpcr_clk_ops; + clk_register(&sh7722_mstpcr_clocks[i]); + clk_put(clk); + } for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr); i++) { pr_debug( "Registering mstpcr '%s'\n", sh7722_mstpcr[i].name); -- cgit v1.2.1 From ecf399bdafb83b6c0091837dd2a0612470e9c8d2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:15:48 +0900 Subject: sh: sh_mobile mstpcr clocks for sh7722 Add sh7722 mstpcr bits and information about their parent clocks. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index c7155f9b10f5..3ef5825ffa9e 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -687,6 +687,31 @@ static struct clk sh7722_mstpcr[] = { } static struct clk sh7722_mstpcr_clocks[] = { +#if defined(CONFIG_CPU_SUBTYPE_SH7722) + MSTPCR("uram0", "umem_clk", 0, 28), + MSTPCR("xymem0", "bus_clk", 0, 26), + MSTPCR("tmu0", "peripheral_clk", 0, 15), + MSTPCR("cmt0", "r_clk", 0, 14), + MSTPCR("rwdt0", "r_clk", 0, 13), + MSTPCR("flctl0", "peripheral_clk", 0, 10), + MSTPCR("scif0", "peripheral_clk", 0, 7), + MSTPCR("scif1", "peripheral_clk", 0, 6), + MSTPCR("scif2", "peripheral_clk", 0, 5), + MSTPCR("i2c0", "peripheral_clk", 1, 9), + MSTPCR("rtc0", "r_clk", 1, 8), + MSTPCR("sdhi0", "peripheral_clk", 2, 18), + MSTPCR("keysc0", "r_clk", 2, 14), + MSTPCR("usbf0", "peripheral_clk", 2, 11), + MSTPCR("2dg0", "bus_clk", 2, 9), + MSTPCR("siu0", "bus_clk", 2, 8), + MSTPCR("vou0", "bus_clk", 2, 5), + MSTPCR("jpu0", "bus_clk", 2, 6), + MSTPCR("beu0", "bus_clk", 2, 4), + MSTPCR("ceu0", "bus_clk", 2, 3), + MSTPCR("veu0", "bus_clk", 2, 2), + MSTPCR("vpu0", "bus_clk", 2, 1), + MSTPCR("lcdc0", "bus_clk", 2, 0), +#endif }; static struct clk *sh7722_clocks[] = { -- cgit v1.2.1 From f14c017d6b2e9e97b0d5f0b33f573797dde4d4f1 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:16:08 +0900 Subject: sh: sh_mobile mstpcr clocks for sh7723 Add sh7723 mstpcr bits and information about their parent clocks. The datasheet is pretty clear about the clocks on this device. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 3ef5825ffa9e..9ff8a448a0a3 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -712,6 +712,56 @@ static struct clk sh7722_mstpcr_clocks[] = { MSTPCR("vpu0", "bus_clk", 2, 1), MSTPCR("lcdc0", "bus_clk", 2, 0), #endif +#if defined(CONFIG_CPU_SUBTYPE_SH7723) + /* See page 60 of Datasheet V1.0: Overview -> Block Diagram */ + MSTPCR("tlb0", "cpu_clk", 0, 31), + MSTPCR("ic0", "cpu_clk", 0, 30), + MSTPCR("oc0", "cpu_clk", 0, 29), + MSTPCR("l2c0", "sh_clk", 0, 28), + MSTPCR("ilmem0", "cpu_clk", 0, 27), + MSTPCR("fpu0", "cpu_clk", 0, 24), + MSTPCR("intc0", "cpu_clk", 0, 22), + MSTPCR("dmac0", "bus_clk", 0, 21), + MSTPCR("sh0", "sh_clk", 0, 20), + MSTPCR("hudi0", "peripheral_clk", 0, 19), + MSTPCR("ubc0", "cpu_clk", 0, 17), + MSTPCR("tmu0", "peripheral_clk", 0, 15), + MSTPCR("cmt0", "r_clk", 0, 14), + MSTPCR("rwdt0", "r_clk", 0, 13), + MSTPCR("dmac1", "bus_clk", 0, 12), + MSTPCR("tmu1", "peripheral_clk", 0, 11), + MSTPCR("flctl0", "peripheral_clk", 0, 10), + MSTPCR("scif0", "peripheral_clk", 0, 9), + MSTPCR("scif1", "peripheral_clk", 0, 8), + MSTPCR("scif2", "peripheral_clk", 0, 7), + MSTPCR("scif3", "bus_clk", 0, 6), + MSTPCR("scif4", "bus_clk", 0, 5), + MSTPCR("scif5", "bus_clk", 0, 4), + MSTPCR("msiof0", "bus_clk", 0, 2), + MSTPCR("msiof1", "bus_clk", 0, 1), + MSTPCR("meram0", "sh_clk", 0, 0), + MSTPCR("i2c0", "peripheral_clk", 1, 9), + MSTPCR("rtc0", "r_clk", 1, 8), + MSTPCR("atapi0", "sh_clk", 2, 28), + MSTPCR("adc0", "peripheral_clk", 2, 28), + MSTPCR("tpu0", "bus_clk", 2, 25), + MSTPCR("irda0", "peripheral_clk", 2, 24), + MSTPCR("tsif0", "bus_clk", 2, 22), + MSTPCR("icb0", "bus_clk", 2, 21), + MSTPCR("sdhi0", "bus_clk", 2, 18), + MSTPCR("sdhi1", "bus_clk", 2, 17), + MSTPCR("keysc0", "r_clk", 2, 14), + MSTPCR("usb0", "bus_clk", 2, 11), + MSTPCR("2dg0", "bus_clk", 2, 10), + MSTPCR("siu0", "bus_clk", 2, 8), + MSTPCR("veu1", "bus_clk", 2, 6), + MSTPCR("vou0", "bus_clk", 2, 5), + MSTPCR("beu0", "bus_clk", 2, 4), + MSTPCR("ceu0", "bus_clk", 2, 3), + MSTPCR("veu0", "bus_clk", 2, 2), + MSTPCR("vpu0", "bus_clk", 2, 1), + MSTPCR("lcdc0", "bus_clk", 2, 0), +#endif }; static struct clk *sh7722_clocks[] = { -- cgit v1.2.1 From 6e88d030a1491ec0f130dc4765d06b22f7db6610 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:19:38 +0900 Subject: sh: sh_mobile mstpcr clocks for sh7343 Add sh7343 mstpcr bits and information about their parent clocks. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 9ff8a448a0a3..595afc396224 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -762,6 +762,30 @@ static struct clk sh7722_mstpcr_clocks[] = { MSTPCR("vpu0", "bus_clk", 2, 1), MSTPCR("lcdc0", "bus_clk", 2, 0), #endif +#if defined(CONFIG_CPU_SUBTYPE_SH7343) + MSTPCR("uram0", "umem_clk", 0, 28), + MSTPCR("xymem0", "bus_clk", 0, 26), + MSTPCR("tmu0", "peripheral_clk", 0, 15), + MSTPCR("cmt0", "r_clk", 0, 14), + MSTPCR("rwdt0", "r_clk", 0, 13), + MSTPCR("scif0", "peripheral_clk", 0, 7), + MSTPCR("scif1", "peripheral_clk", 0, 6), + MSTPCR("scif2", "peripheral_clk", 0, 5), + MSTPCR("scif3", "peripheral_clk", 0, 4), + MSTPCR("i2c0", "peripheral_clk", 1, 9), + MSTPCR("i2c1", "peripheral_clk", 1, 8), + MSTPCR("sdhi0", "peripheral_clk", 2, 18), + MSTPCR("keysc0", "r_clk", 2, 14), + MSTPCR("usbf0", "peripheral_clk", 2, 11), + MSTPCR("siu0", "bus_clk", 2, 8), + MSTPCR("jpu0", "bus_clk", 2, 6), + MSTPCR("vou0", "bus_clk", 2, 5), + MSTPCR("beu0", "bus_clk", 2, 4), + MSTPCR("ceu0", "bus_clk", 2, 3), + MSTPCR("veu0", "bus_clk", 2, 2), + MSTPCR("vpu0", "bus_clk", 2, 1), + MSTPCR("lcdc0", "bus_clk", 2, 0), +#endif }; static struct clk *sh7722_clocks[] = { -- cgit v1.2.1 From f2eb0109fb4268505b0737cfe661542eb6151907 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:20:23 +0900 Subject: sh: sh_mobile mstpcr clocks for sh7366 Add sh7366 mstpcr bits and information about their parent clocks. The datasheet is pretty clear about the clocks on this device. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 595afc396224..fc69e18ddd63 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -786,6 +786,46 @@ static struct clk sh7722_mstpcr_clocks[] = { MSTPCR("vpu0", "bus_clk", 2, 1), MSTPCR("lcdc0", "bus_clk", 2, 0), #endif +#if defined(CONFIG_CPU_SUBTYPE_SH7366) + /* See page 52 of Datasheet V0.40: Overview -> Block Diagram */ + MSTPCR("tlb0", "cpu_clk", 0, 31), + MSTPCR("ic0", "cpu_clk", 0, 30), + MSTPCR("oc0", "cpu_clk", 0, 29), + MSTPCR("rsmem0", "sh_clk", 0, 28), + MSTPCR("xymem0", "cpu_clk", 0, 26), + MSTPCR("intc30", "peripheral_clk", 0, 23), + MSTPCR("intc0", "peripheral_clk", 0, 22), + MSTPCR("dmac0", "bus_clk", 0, 21), + MSTPCR("sh0", "sh_clk", 0, 20), + MSTPCR("hudi0", "peripheral_clk", 0, 19), + MSTPCR("ubc0", "cpu_clk", 0, 17), + MSTPCR("tmu0", "peripheral_clk", 0, 15), + MSTPCR("cmt0", "r_clk", 0, 14), + MSTPCR("rwdt0", "r_clk", 0, 13), + MSTPCR("flctl0", "peripheral_clk", 0, 10), + MSTPCR("scif0", "peripheral_clk", 0, 7), + MSTPCR("scif1", "bus_clk", 0, 6), + MSTPCR("scif2", "bus_clk", 0, 5), + MSTPCR("msiof0", "peripheral_clk", 0, 2), + MSTPCR("sbr0", "peripheral_clk", 0, 1), + MSTPCR("i2c0", "peripheral_clk", 1, 9), + MSTPCR("icb0", "bus_clk", 2, 27), + MSTPCR("meram0", "sh_clk", 2, 26), + MSTPCR("dacc0", "peripheral_clk", 2, 24), + MSTPCR("dacy0", "peripheral_clk", 2, 23), + MSTPCR("tsif0", "bus_clk", 2, 22), + MSTPCR("sdhi0", "bus_clk", 2, 18), + MSTPCR("mmcif0", "bus_clk", 2, 17), + MSTPCR("usb0", "bus_clk", 2, 11), + MSTPCR("siu0", "bus_clk", 2, 8), + MSTPCR("veu1", "bus_clk", 2, 7), + MSTPCR("vou0", "bus_clk", 2, 5), + MSTPCR("beu0", "bus_clk", 2, 4), + MSTPCR("ceu0", "bus_clk", 2, 3), + MSTPCR("veu0", "bus_clk", 2, 2), + MSTPCR("vpu0", "bus_clk", 2, 1), + MSTPCR("lcdc0", "bus_clk", 2, 0), +#endif }; static struct clk *sh7722_clocks[] = { -- cgit v1.2.1 From a5616bd0f19730a780c354110454ce37209f1ded Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:20:55 +0900 Subject: sh: sh_mobile i2c clock framework support Add clock framework support to the sh_mobile i2c driver and adjust the processor specific code accordingly. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7343.c | 4 ++-- arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index 78881b4214da..e88577f4074a 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c @@ -30,6 +30,7 @@ static struct resource iic0_resources[] = { static struct platform_device iic0_device = { .name = "i2c-sh_mobile", + .id = 0, /* "i2c0" clock */ .num_resources = ARRAY_SIZE(iic0_resources), .resource = iic0_resources, }; @@ -50,6 +51,7 @@ static struct resource iic1_resources[] = { static struct platform_device iic1_device = { .name = "i2c-sh_mobile", + .id = 1, /* "i2c1" clock */ .num_resources = ARRAY_SIZE(iic1_resources), .resource = iic1_resources, }; @@ -147,8 +149,6 @@ static int __init sh7343_devices_setup(void) clk_always_enable("mstp023"); /* INTC3 */ clk_always_enable("mstp022"); /* INTC */ clk_always_enable("mstp020"); /* SuperHyway */ - clk_always_enable("mstp109"); /* I2C0 */ - clk_always_enable("mstp108"); /* I2C1 */ clk_always_enable("mstp202"); /* VEU */ clk_always_enable("mstp201"); /* VPU */ diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index e17db39b97aa..2f0905a1b211 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -32,6 +32,7 @@ static struct resource iic_resources[] = { static struct platform_device iic_device = { .name = "i2c-sh_mobile", + .id = 0, /* "i2c0" clock */ .num_resources = ARRAY_SIZE(iic_resources), .resource = iic_resources, }; @@ -184,7 +185,6 @@ static int __init sh7366_devices_setup(void) clk_always_enable("mstp023"); /* INTC3 */ clk_always_enable("mstp022"); /* INTC */ clk_always_enable("mstp020"); /* SuperHyway */ - clk_always_enable("mstp109"); /* I2C */ clk_always_enable("mstp211"); /* USB */ clk_always_enable("mstp207"); /* VEU-2 */ clk_always_enable("mstp202"); /* VEU-1 */ diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index ef77ee1d9f53..786eaf1cf4c3 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -87,6 +87,7 @@ static struct resource iic_resources[] = { static struct platform_device iic_device = { .name = "i2c-sh_mobile", + .id = 0, /* "i2c0" clock */ .num_resources = ARRAY_SIZE(iic_resources), .resource = iic_resources, }; @@ -197,7 +198,6 @@ static int __init sh7722_devices_setup(void) clk_always_enable("mstp026"); /* XYMEM */ clk_always_enable("mstp022"); /* INTC */ clk_always_enable("mstp020"); /* SuperHyway */ - clk_always_enable("mstp109"); /* I2C */ clk_always_enable("mstp211"); /* USB */ clk_always_enable("mstp202"); /* VEU */ clk_always_enable("mstp201"); /* VPU */ diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 6d9e6972cfc9..63ec348dec70 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -215,6 +215,7 @@ static struct resource iic_resources[] = { static struct platform_device iic_device = { .name = "i2c-sh_mobile", + .id = 0, /* "i2c0" clock */ .num_resources = ARRAY_SIZE(iic_resources), .resource = iic_resources, }; @@ -238,7 +239,6 @@ static int __init sh7723_devices_setup(void) clk_always_enable("mstp022"); /* INTC */ clk_always_enable("mstp020"); /* SuperHyway */ clk_always_enable("mstp000"); /* MERAM */ - clk_always_enable("mstp109"); /* I2C */ clk_always_enable("mstp108"); /* RTC */ clk_always_enable("mstp211"); /* USB */ clk_always_enable("mstp206"); /* VEU2H1 */ -- cgit v1.2.1 From af5be79a7f8d7067588dc2863d37f7cd22e5f2de Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:22:13 +0900 Subject: sh: sh_mobile usbf clock framework support Add clock framework support to the usbf/m66592 driver and adjust the cpu specific code accordingly. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 786eaf1cf4c3..4953e74f9193 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -62,7 +62,7 @@ static struct resource usbf_resources[] = { static struct platform_device usbf_device = { .name = "m66592_udc", - .id = -1, + .id = 0, /* "usbf0" clock */ .dev = { .dma_mask = NULL, .coherent_dma_mask = 0xffffffff, @@ -198,7 +198,6 @@ static int __init sh7722_devices_setup(void) clk_always_enable("mstp026"); /* XYMEM */ clk_always_enable("mstp022"); /* INTC */ clk_always_enable("mstp020"); /* SuperHyway */ - clk_always_enable("mstp211"); /* USB */ clk_always_enable("mstp202"); /* VEU */ clk_always_enable("mstp201"); /* VPU */ -- cgit v1.2.1 From 765786e0aead7faf6c333176d22948c6f155fff1 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:22:38 +0900 Subject: sh: sh_mobile usb clock framework support Add clock framework support to the usb/r8a66597 driver and adjust the cpu specific code accordingly. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 1 - arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 1 - 2 files changed, 2 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index 2f0905a1b211..5f92c864d7bc 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -185,7 +185,6 @@ static int __init sh7366_devices_setup(void) clk_always_enable("mstp023"); /* INTC3 */ clk_always_enable("mstp022"); /* INTC */ clk_always_enable("mstp020"); /* SuperHyway */ - clk_always_enable("mstp211"); /* USB */ clk_always_enable("mstp207"); /* VEU-2 */ clk_always_enable("mstp202"); /* VEU-1 */ clk_always_enable("mstp201"); /* VPU */ diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 63ec348dec70..e9c9d7ead2b3 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -240,7 +240,6 @@ static int __init sh7723_devices_setup(void) clk_always_enable("mstp020"); /* SuperHyway */ clk_always_enable("mstp000"); /* MERAM */ clk_always_enable("mstp108"); /* RTC */ - clk_always_enable("mstp211"); /* USB */ clk_always_enable("mstp206"); /* VEU2H1 */ clk_always_enable("mstp202"); /* VEU2H0 */ clk_always_enable("mstp201"); /* VPU */ -- cgit v1.2.1 From ef6aff6884408db95ceb0f678f583536e0bd48f8 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Oct 2008 20:24:01 +0900 Subject: sh: remove old sh_mobile mstpc clocks Remove the old sh_mobile mstpcr clocks. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 52 ---------------------------------- arch/sh/kernel/cpu/sh4a/setup-sh7343.c | 14 +++------ arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 16 ++++------- arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 14 ++++----- arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 16 ++++------- 5 files changed, 19 insertions(+), 93 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index fc69e18ddd63..83b69196bc1a 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -632,53 +632,6 @@ static struct clk_ops sh7722_mstpcr_clk_ops = { .recalc = sh7722_mstpcr_recalc, }; -#define DECLARE_MSTPCRN(regnr, bitnr, bitstr) \ -{ \ - .name = "mstp" __stringify(regnr) bitstr, \ - .arch_flags = MSTPCR_ARCH_FLAGS(regnr, bitnr), \ - .ops = &sh7722_mstpcr_clk_ops, \ -} - -#define DECLARE_MSTPCR(regnr) \ - DECLARE_MSTPCRN(regnr, 31, "31"), \ - DECLARE_MSTPCRN(regnr, 30, "30"), \ - DECLARE_MSTPCRN(regnr, 29, "29"), \ - DECLARE_MSTPCRN(regnr, 28, "28"), \ - DECLARE_MSTPCRN(regnr, 27, "27"), \ - DECLARE_MSTPCRN(regnr, 26, "26"), \ - DECLARE_MSTPCRN(regnr, 25, "25"), \ - DECLARE_MSTPCRN(regnr, 24, "24"), \ - DECLARE_MSTPCRN(regnr, 23, "23"), \ - DECLARE_MSTPCRN(regnr, 22, "22"), \ - DECLARE_MSTPCRN(regnr, 21, "21"), \ - DECLARE_MSTPCRN(regnr, 20, "20"), \ - DECLARE_MSTPCRN(regnr, 19, "19"), \ - DECLARE_MSTPCRN(regnr, 18, "18"), \ - DECLARE_MSTPCRN(regnr, 17, "17"), \ - DECLARE_MSTPCRN(regnr, 16, "16"), \ - DECLARE_MSTPCRN(regnr, 15, "15"), \ - DECLARE_MSTPCRN(regnr, 14, "14"), \ - DECLARE_MSTPCRN(regnr, 13, "13"), \ - DECLARE_MSTPCRN(regnr, 12, "12"), \ - DECLARE_MSTPCRN(regnr, 11, "11"), \ - DECLARE_MSTPCRN(regnr, 10, "10"), \ - DECLARE_MSTPCRN(regnr, 9, "09"), \ - DECLARE_MSTPCRN(regnr, 8, "08"), \ - DECLARE_MSTPCRN(regnr, 7, "07"), \ - DECLARE_MSTPCRN(regnr, 6, "06"), \ - DECLARE_MSTPCRN(regnr, 5, "05"), \ - DECLARE_MSTPCRN(regnr, 4, "04"), \ - DECLARE_MSTPCRN(regnr, 3, "03"), \ - DECLARE_MSTPCRN(regnr, 2, "02"), \ - DECLARE_MSTPCRN(regnr, 1, "01"), \ - DECLARE_MSTPCRN(regnr, 0, "00") - -static struct clk sh7722_mstpcr[] = { - DECLARE_MSTPCR(0), - DECLARE_MSTPCR(1), - DECLARE_MSTPCR(2), -}; - #define MSTPCR(_name, _parent, regnr, bitnr) \ { \ .name = _name, \ @@ -885,10 +838,5 @@ int __init arch_clk_init(void) clk_put(clk); } - for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr); i++) { - pr_debug( "Registering mstpcr '%s'\n", sh7722_mstpcr[i].name); - clk_register(&sh7722_mstpcr[i]); - } - return 0; } diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index e88577f4074a..75b9c819e442 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c @@ -141,16 +141,10 @@ static struct platform_device *sh7343_devices[] __initdata = { static int __init sh7343_devices_setup(void) { - clk_always_enable("mstp031"); /* TLB */ - clk_always_enable("mstp030"); /* IC */ - clk_always_enable("mstp029"); /* OC */ - clk_always_enable("mstp028"); /* URAM */ - clk_always_enable("mstp026"); /* XYMEM */ - clk_always_enable("mstp023"); /* INTC3 */ - clk_always_enable("mstp022"); /* INTC */ - clk_always_enable("mstp020"); /* SuperHyway */ - clk_always_enable("mstp202"); /* VEU */ - clk_always_enable("mstp201"); /* VPU */ + clk_always_enable("uram0"); /* URAM */ + clk_always_enable("xymem0"); /* XYMEM */ + clk_always_enable("veu0"); /* VEU */ + clk_always_enable("vpu0"); /* VPU */ platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20); platform_resource_setup_memory(&veu_device, "veu", 2 << 20); diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index 5f92c864d7bc..839ae97a7fd2 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -177,17 +177,11 @@ static struct platform_device *sh7366_devices[] __initdata = { static int __init sh7366_devices_setup(void) { - clk_always_enable("mstp031"); /* TLB */ - clk_always_enable("mstp030"); /* IC */ - clk_always_enable("mstp029"); /* OC */ - clk_always_enable("mstp028"); /* RSMEM */ - clk_always_enable("mstp026"); /* XYMEM */ - clk_always_enable("mstp023"); /* INTC3 */ - clk_always_enable("mstp022"); /* INTC */ - clk_always_enable("mstp020"); /* SuperHyway */ - clk_always_enable("mstp207"); /* VEU-2 */ - clk_always_enable("mstp202"); /* VEU-1 */ - clk_always_enable("mstp201"); /* VPU */ + clk_always_enable("rsmem0"); /* RSMEM */ + clk_always_enable("xymem0"); /* XYMEM */ + clk_always_enable("veu1"); /* VEU-2 */ + clk_always_enable("veu0"); /* VEU-1 */ + clk_always_enable("vpu0"); /* VPU */ platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20); platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20); diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 4953e74f9193..9162013ec695 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -191,15 +191,11 @@ static struct platform_device *sh7722_devices[] __initdata = { static int __init sh7722_devices_setup(void) { - clk_always_enable("mstp031"); /* TLB */ - clk_always_enable("mstp030"); /* IC */ - clk_always_enable("mstp029"); /* OC */ - clk_always_enable("mstp028"); /* URAM */ - clk_always_enable("mstp026"); /* XYMEM */ - clk_always_enable("mstp022"); /* INTC */ - clk_always_enable("mstp020"); /* SuperHyway */ - clk_always_enable("mstp202"); /* VEU */ - clk_always_enable("mstp201"); /* VPU */ + clk_always_enable("uram0"); /* URAM */ + clk_always_enable("xymem0"); /* XYMEM */ + clk_always_enable("rtc0"); /* RTC */ + clk_always_enable("veu0"); /* VEU */ + clk_always_enable("vpu0"); /* VPU */ platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20); platform_resource_setup_memory(&veu_device, "veu", 2 << 20); diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index e9c9d7ead2b3..849770d780ae 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -232,17 +232,11 @@ static struct platform_device *sh7723_devices[] __initdata = { static int __init sh7723_devices_setup(void) { - clk_always_enable("mstp031"); /* TLB */ - clk_always_enable("mstp030"); /* IC */ - clk_always_enable("mstp029"); /* OC */ - clk_always_enable("mstp024"); /* FPU */ - clk_always_enable("mstp022"); /* INTC */ - clk_always_enable("mstp020"); /* SuperHyway */ - clk_always_enable("mstp000"); /* MERAM */ - clk_always_enable("mstp108"); /* RTC */ - clk_always_enable("mstp206"); /* VEU2H1 */ - clk_always_enable("mstp202"); /* VEU2H0 */ - clk_always_enable("mstp201"); /* VPU */ + clk_always_enable("meram0"); /* MERAM */ + clk_always_enable("rtc0"); /* RTC */ + clk_always_enable("veu1"); /* VEU2H1 */ + clk_always_enable("veu0"); /* VEU2H0 */ + clk_always_enable("vpu0"); /* VPU */ platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20); platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20); -- cgit v1.2.1 From fad57feba77d2e5b183e068cb6b90693e4567b40 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Wed, 12 Nov 2008 20:11:47 +0900 Subject: sh: dynamic ftrace support. First cut at dynamic ftrace support. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/kernel/Makefile_32 | 6 +++ arch/sh/kernel/entry-common.S | 44 ----------------- arch/sh/kernel/ftrace.c | 109 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 44 deletions(-) create mode 100644 arch/sh/kernel/ftrace.c (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index 48edfb145fb4..76fcac1596ce 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -4,6 +4,11 @@ extra-y := head_32.o init_task.o vmlinux.lds +ifdef CONFIG_FUNCTION_TRACER +# Do not profile debug and lowlevel utilities +CFLAGS_REMOVE_ftrace.o = -pg +endif + obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process_32.o \ ptrace_32.o setup.o signal_32.o sys_sh.o sys_sh32.o \ syscalls_32.o time_32.o topology.o traps.o traps_32.o @@ -24,5 +29,6 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_IO_TRAPPED) += io_trapped.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o +obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o EXTRA_CFLAGS += -Werror diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index 5b7efc4016fa..efbb4268875e 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -371,47 +371,3 @@ syscall_exit: #endif 7: .long do_syscall_trace_enter 8: .long do_syscall_trace_leave - -#ifdef CONFIG_FUNCTION_TRACER - .align 2 - .globl _mcount - .type _mcount,@function - .globl mcount - .type mcount,@function -_mcount: -mcount: - mov.l r4, @-r15 - mov.l r5, @-r15 - mov.l r6, @-r15 - mov.l r7, @-r15 - sts.l pr, @-r15 - - mov.l @(20,r15),r4 - sts pr, r5 - - mov.l 1f, r6 - mov.l ftrace_stub, r7 - cmp/eq r6, r7 - bt skip_trace - - mov.l @r6, r6 - jsr @r6 - nop - -skip_trace: - - lds.l @r15+, pr - mov.l @r15+, r7 - mov.l @r15+, r6 - mov.l @r15+, r5 - rts - mov.l @r15+, r4 - - .align 2 -1: .long ftrace_trace_function - - .globl ftrace_stub -ftrace_stub: - rts - nop -#endif /* CONFIG_FUNCTION_TRACER */ diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c new file mode 100644 index 000000000000..6c193d56c2e7 --- /dev/null +++ b/arch/sh/kernel/ftrace.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2008 Matt Fleming + * + * Code for replacing ftrace calls with jumps. + * + * Copyright (C) 2007-2008 Steven Rostedt + * + * Thanks goes to Ingo Molnar, for suggesting the idea. + * Mathieu Desnoyers, for suggesting postponing the modifications. + * Arjan van de Ven, for keeping me straight, and explaining to me + * the dangers of modifying code on the run. + */ +#include +#include +#include +#include +#include +#include +#include + +static unsigned char ftrace_nop[] = { + 0x09, 0x00, /* nop */ + 0x09, 0x00, /* nop */ +}; + +static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE]; + +unsigned char *ftrace_nop_replace(void) +{ + return ftrace_nop; +} + +static int is_sh_nop(unsigned char *ip) +{ + return strncmp(ip, ftrace_nop, sizeof(ftrace_nop)); +} + +unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) +{ + /* Place the address in the memory table. */ + if (addr == CALLER_ADDR) + __raw_writel(addr + MCOUNT_INSN_OFFSET, ftrace_replaced_code); + else + __raw_writel(addr, ftrace_replaced_code); + + /* + * No locking needed, this must be called via kstop_machine + * which in essence is like running on a uniprocessor machine. + */ + return ftrace_replaced_code; +} + +int ftrace_modify_code(unsigned long ip, unsigned char *old_code, + unsigned char *new_code) +{ + unsigned char replaced[MCOUNT_INSN_SIZE]; + + /* + * Note: Due to modules and __init, code can + * disappear and change, we need to protect against faulting + * as well as code changing. We do this by using the + * probe_kernel_* functions. + * + * No real locking needed, this code is run through + * kstop_machine, or before SMP starts. + */ + + /* + * If we're trying to nop out a call to a function, we instead + * place a call to the address after the memory table. + */ + if (is_sh_nop(new_code) == 0) + __raw_writel(ip + MCOUNT_INSN_SIZE, (unsigned long)new_code); + + /* read the text we want to modify */ + if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE)) + return -EFAULT; + + /* Make sure it is what we expect it to be */ + if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0) + return -EINVAL; + + /* replace the text with the new text */ + if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE)) + return -EPERM; + + flush_icache_range(ip, ip + MCOUNT_INSN_SIZE); + + return 0; +} + +int ftrace_update_ftrace_func(ftrace_func_t func) +{ + unsigned long ip = (unsigned long)(&ftrace_call); + unsigned char old[MCOUNT_INSN_SIZE], *new; + + memcpy(old, (unsigned char *)(ip + MCOUNT_INSN_OFFSET), MCOUNT_INSN_SIZE); + new = ftrace_call_replace(ip, (unsigned long)func); + + return ftrace_modify_code(ip + MCOUNT_INSN_OFFSET, old, new); +} + +int __init ftrace_dyn_arch_init(void *data) +{ + /* The return code is retured via data */ + __raw_writel(0, (unsigned long)data); + + return 0; +} -- cgit v1.2.1 From 00e825c6b99b39f12751ea45d38bb4d900de70f4 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 18 Nov 2008 14:21:34 +0900 Subject: sh: Fix clock framework compiler warnings. CC arch/sh/kernel/cpu/clock.o arch/sh/kernel/cpu/clock.c: In function 'clk_disable': arch/sh/kernel/cpu/clock.c:156: warning: 'return' with a value, in function returning void Introduced by ("sh: enable and disable clocks recursively"). Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 717056b3d400..7b17137536d6 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -153,7 +153,7 @@ void clk_disable(struct clk *clk) unsigned long flags; if (!clk) - return -EINVAL; + return; spin_lock_irqsave(&clock_lock, flags); __clk_disable(clk); -- cgit v1.2.1 From e9bf51e5ccc7703226c79888603e157066213700 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 18 Nov 2008 14:22:39 +0900 Subject: sh: __udivdi3 -> do_div() in softfloat lib. Inhibit the generation of __udivdi3 for the softfloat lib, use do_div() outright. Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4/softfloat.c | 73 +++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 32 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4/softfloat.c b/arch/sh/kernel/cpu/sh4/softfloat.c index 2b747f3b02bd..42edf2e54e85 100644 --- a/arch/sh/kernel/cpu/sh4/softfloat.c +++ b/arch/sh/kernel/cpu/sh4/softfloat.c @@ -37,6 +37,7 @@ */ #include #include +#include #define LIT64( a ) a##LL @@ -67,16 +68,16 @@ typedef unsigned long long float64; extern void float_raise(unsigned int flags); /* in fpu.c */ extern int float_rounding_mode(void); /* in fpu.c */ -inline bits64 extractFloat64Frac(float64 a); -inline flag extractFloat64Sign(float64 a); -inline int16 extractFloat64Exp(float64 a); -inline int16 extractFloat32Exp(float32 a); -inline flag extractFloat32Sign(float32 a); -inline bits32 extractFloat32Frac(float32 a); -inline float64 packFloat64(flag zSign, int16 zExp, bits64 zSig); -inline void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr); -inline float32 packFloat32(flag zSign, int16 zExp, bits32 zSig); -inline void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr); +bits64 extractFloat64Frac(float64 a); +flag extractFloat64Sign(float64 a); +int16 extractFloat64Exp(float64 a); +int16 extractFloat32Exp(float32 a); +flag extractFloat32Sign(float32 a); +bits32 extractFloat32Frac(float32 a); +float64 packFloat64(flag zSign, int16 zExp, bits64 zSig); +void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr); +float32 packFloat32(flag zSign, int16 zExp, bits32 zSig); +void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr); float64 float64_sub(float64 a, float64 b); float32 float32_sub(float32 a, float32 b); float32 float32_add(float32 a, float32 b); @@ -86,11 +87,11 @@ float32 float32_div(float32 a, float32 b); float32 float32_mul(float32 a, float32 b); float64 float64_mul(float64 a, float64 b); float32 float64_to_float32(float64 a); -inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, +void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, bits64 * z1Ptr); -inline void sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, +void sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, bits64 * z1Ptr); -inline void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr); +void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr); static int8 countLeadingZeros32(bits32 a); static int8 countLeadingZeros64(bits64 a); @@ -110,42 +111,42 @@ static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b); static void normalizeFloat32Subnormal(bits32 aSig, int16 * zExpPtr, bits32 * zSigPtr); -inline bits64 extractFloat64Frac(float64 a) +bits64 extractFloat64Frac(float64 a) { return a & LIT64(0x000FFFFFFFFFFFFF); } -inline flag extractFloat64Sign(float64 a) +flag extractFloat64Sign(float64 a) { return a >> 63; } -inline int16 extractFloat64Exp(float64 a) +int16 extractFloat64Exp(float64 a) { return (a >> 52) & 0x7FF; } -inline int16 extractFloat32Exp(float32 a) +int16 extractFloat32Exp(float32 a) { return (a >> 23) & 0xFF; } -inline flag extractFloat32Sign(float32 a) +flag extractFloat32Sign(float32 a) { return a >> 31; } -inline bits32 extractFloat32Frac(float32 a) +bits32 extractFloat32Frac(float32 a) { return a & 0x007FFFFF; } -inline float64 packFloat64(flag zSign, int16 zExp, bits64 zSig) +float64 packFloat64(flag zSign, int16 zExp, bits64 zSig) { return (((bits64) zSign) << 63) + (((bits64) zExp) << 52) + zSig; } -inline void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr) +void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr) { bits64 z; @@ -338,12 +339,12 @@ static float64 addFloat64Sigs(float64 a, float64 b, flag zSign) } -inline float32 packFloat32(flag zSign, int16 zExp, bits32 zSig) +float32 packFloat32(flag zSign, int16 zExp, bits32 zSig) { return (((bits32) zSign) << 31) + (((bits32) zExp) << 23) + zSig; } -inline void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr) +void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr) { bits32 z; if (count == 0) { @@ -634,7 +635,7 @@ normalizeFloat64Subnormal(bits64 aSig, int16 * zExpPtr, bits64 * zSigPtr) *zExpPtr = 1 - shiftCount; } -inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, +void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, bits64 * z1Ptr) { bits64 z1; @@ -644,7 +645,7 @@ inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, *z0Ptr = a0 + b0 + (z1 < a1); } -inline void +void sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, bits64 * z1Ptr) { @@ -656,11 +657,14 @@ static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b) { bits64 b0, b1; bits64 rem0, rem1, term0, term1; - bits64 z; + bits64 z, tmp; if (b <= a0) return LIT64(0xFFFFFFFFFFFFFFFF); b0 = b >> 32; - z = (b0 << 32 <= a0) ? LIT64(0xFFFFFFFF00000000) : (a0 / b0) << 32; + tmp = a0; + do_div(tmp, b0); + + z = (b0 << 32 <= a0) ? LIT64(0xFFFFFFFF00000000) : tmp << 32; mul64To128(b, z, &term0, &term1); sub128(a0, a1, term0, term1, &rem0, &rem1); while (((sbits64) rem0) < 0) { @@ -669,11 +673,13 @@ static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b) add128(rem0, rem1, b0, b1, &rem0, &rem1); } rem0 = (rem0 << 32) | (rem1 >> 32); - z |= (b0 << 32 <= rem0) ? 0xFFFFFFFF : rem0 / b0; + tmp = rem0; + do_div(tmp, b0); + z |= (b0 << 32 <= rem0) ? 0xFFFFFFFF : tmp; return z; } -inline void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr) +void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr) { bits32 aHigh, aLow, bHigh, bLow; bits64 z0, zMiddleA, zMiddleB, z1; @@ -769,7 +775,8 @@ float32 float32_div(float32 a, float32 b) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; + bits32 aSig, bSig; + uint64_t zSig; aSig = extractFloat32Frac(a); aExp = extractFloat32Exp(a); @@ -804,11 +811,13 @@ float32 float32_div(float32 a, float32 b) aSig >>= 1; ++zExp; } - zSig = (((bits64) aSig) << 32) / bSig; + zSig = (((bits64) aSig) << 32); + do_div(zSig, bSig); + if ((zSig & 0x3F) == 0) { zSig |= (((bits64) bSig) * zSig != ((bits64) aSig) << 32); } - return roundAndPackFloat32(zSign, zExp, zSig); + return roundAndPackFloat32(zSign, zExp, (bits32)zSig); } -- cgit v1.2.1 From 1aad54a99b6ce316c851ba99b2efe41998cfd37d Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 18 Nov 2008 17:33:48 +0900 Subject: sh: Migrate necessary libgcc bits in to arch/sh/lib for SUPERH32. This moves in the necessary libgcc bits for SUPERH32 and drops the libgcc linking for the regular targets. This in turn allows us to rip out quite a few hacks both in sh_ksyms_32 and arch/sh/Makefile. Signed-off-by: Paul Mundt --- arch/sh/kernel/sh_ksyms_32.c | 36 +++++------------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 92ae5e6c099e..9c5ae7b9cd98 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -52,16 +52,10 @@ EXPORT_SYMBOL(__const_udelay); #define DECLARE_EXPORT(name) \ extern void name(void);EXPORT_SYMBOL(name) -#define MAYBE_DECLARE_EXPORT(name) \ - extern void name(void) __weak;EXPORT_SYMBOL(name) -/* These symbols are generated by the compiler itself */ -DECLARE_EXPORT(__udivsi3); -DECLARE_EXPORT(__sdivsi3); +DECLARE_EXPORT(__lshrsi3); DECLARE_EXPORT(__ashrsi3); DECLARE_EXPORT(__ashlsi3); -DECLARE_EXPORT(__ashrdi3); -DECLARE_EXPORT(__ashldi3); DECLARE_EXPORT(__ashiftrt_r4_6); DECLARE_EXPORT(__ashiftrt_r4_7); DECLARE_EXPORT(__ashiftrt_r4_8); @@ -79,8 +73,7 @@ DECLARE_EXPORT(__ashiftrt_r4_23); DECLARE_EXPORT(__ashiftrt_r4_24); DECLARE_EXPORT(__ashiftrt_r4_27); DECLARE_EXPORT(__ashiftrt_r4_30); -DECLARE_EXPORT(__lshrsi3); -DECLARE_EXPORT(__lshrdi3); +DECLARE_EXPORT(__movstr); DECLARE_EXPORT(__movstrSI8); DECLARE_EXPORT(__movstrSI12); DECLARE_EXPORT(__movstrSI16); @@ -95,31 +88,12 @@ DECLARE_EXPORT(__movstrSI48); DECLARE_EXPORT(__movstrSI52); DECLARE_EXPORT(__movstrSI56); DECLARE_EXPORT(__movstrSI60); -#if __GNUC__ == 4 -DECLARE_EXPORT(__movmem); -#else -DECLARE_EXPORT(__movstr); -#endif - -#if __GNUC__ == 4 -DECLARE_EXPORT(__movmem_i4_even); -DECLARE_EXPORT(__movmem_i4_odd); -DECLARE_EXPORT(__movmemSI12_i4); - -#if (__GNUC_MINOR__ >= 2 || defined(__GNUC_STM_RELEASE__)) -/* - * GCC >= 4.2 emits these for division, as do GCC 4.1.x versions of the ST - * compiler which include backported patches. - */ -DECLARE_EXPORT(__udiv_qrnnd_16); -MAYBE_DECLARE_EXPORT(__sdivsi3_i4i); -MAYBE_DECLARE_EXPORT(__udivsi3_i4i); -#endif -#else /* GCC 3.x */ DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); DECLARE_EXPORT(__movstrSI12_i4); -#endif /* __GNUC__ == 4 */ +DECLARE_EXPORT(__udiv_qrnnd_16); +DECLARE_EXPORT(__sdivsi3_i4i); +DECLARE_EXPORT(__udivsi3_i4i); #if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ defined(CONFIG_SH7705_CACHE_32KB)) -- cgit v1.2.1 From 9ef100287afa8e134de50258b8382cbc9d20f954 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 20 Nov 2008 15:26:35 +0900 Subject: sh: Add exports for __udivsi3/__sdivsi3 and the _i4 versions. Needed by older compilers. Signed-off-by: Paul Mundt --- arch/sh/kernel/sh_ksyms_32.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 9c5ae7b9cd98..490c40218ed7 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -53,6 +53,8 @@ EXPORT_SYMBOL(__const_udelay); #define DECLARE_EXPORT(name) \ extern void name(void);EXPORT_SYMBOL(name) +DECLARE_EXPORT(__udivsi3); +DECLARE_EXPORT(__sdivsi3); DECLARE_EXPORT(__lshrsi3); DECLARE_EXPORT(__ashrsi3); DECLARE_EXPORT(__ashlsi3); @@ -92,6 +94,8 @@ DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); DECLARE_EXPORT(__movstrSI12_i4); DECLARE_EXPORT(__udiv_qrnnd_16); +DECLARE_EXPORT(__sdivsi3_i4); +DECLARE_EXPORT(__udivsi3_i4); DECLARE_EXPORT(__sdivsi3_i4i); DECLARE_EXPORT(__udivsi3_i4i); -- cgit v1.2.1 From 624c6a6750c502981d92de4579647fe2549451dd Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 26 Nov 2008 03:44:07 +0900 Subject: sh: More movmem alias symbol exports for older compilers. Signed-off-by: Paul Mundt --- arch/sh/kernel/sh_ksyms_32.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 490c40218ed7..528de2955c81 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -93,6 +93,9 @@ DECLARE_EXPORT(__movstrSI60); DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); DECLARE_EXPORT(__movstrSI12_i4); +DECLARE_EXPORT(__movmem_i4_even); +DECLARE_EXPORT(__movmem_i4_odd); +DECLARE_EXPORT(__movmemSI12_i4); DECLARE_EXPORT(__udiv_qrnnd_16); DECLARE_EXPORT(__sdivsi3_i4); DECLARE_EXPORT(__udivsi3_i4); -- cgit v1.2.1 From edfd6da0405520b147ab1473ad183a5b32be7082 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 26 Nov 2008 13:06:04 +0900 Subject: sh: Add a few more branch types to the branch emulator. This plugs in some extra encodings for matching more bsr/bsrf/jsr branches. Signed-off-by: Paul Mundt --- arch/sh/kernel/traps_32.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 1e5c74efbacc..f2497585cac0 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -689,7 +689,7 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, } #ifdef CONFIG_SH_FPU_EMU -static int emulate_branch(unsigned short inst, struct pt_regs* regs) +static int emulate_branch(unsigned short inst, struct pt_regs *regs) { /* * bfs: 8fxx: PC+=d*2+4; @@ -702,27 +702,32 @@ static int emulate_branch(unsigned short inst, struct pt_regs* regs) * jsr: 4x0b: PC=Rn after PR=PC+4; * rts: 000b: PC=PR; */ - if ((inst & 0xfd00) == 0x8d00) { + if (((inst & 0xf000) == 0xb000) || /* bsr */ + ((inst & 0xf0ff) == 0x0003) || /* bsrf */ + ((inst & 0xf0ff) == 0x400b)) /* jsr */ + regs->pr = regs->pc + 4; + + if ((inst & 0xfd00) == 0x8d00) { /* bfs, bts */ regs->pc += SH_PC_8BIT_OFFSET(inst); return 0; } - if ((inst & 0xe000) == 0xa000) { + if ((inst & 0xe000) == 0xa000) { /* bra, bsr */ regs->pc += SH_PC_12BIT_OFFSET(inst); return 0; } - if ((inst & 0xf0df) == 0x0003) { + if ((inst & 0xf0df) == 0x0003) { /* braf, bsrf */ regs->pc += regs->regs[(inst & 0x0f00) >> 8] + 4; return 0; } - if ((inst & 0xf0df) == 0x400b) { + if ((inst & 0xf0df) == 0x400b) { /* jmp, jsr */ regs->pc = regs->regs[(inst & 0x0f00) >> 8]; return 0; } - if ((inst & 0xffff) == 0x000b) { + if ((inst & 0xffff) == 0x000b) { /* rts */ regs->pc = regs->pr; return 0; } -- cgit v1.2.1 From 9cfc9a9b6fff9ea7a19814b4472b3cb18b7bbdcc Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 26 Nov 2008 14:31:03 +0900 Subject: sh: Add a simple code dumper for SUPERH32 show_regs(). This implements a simple show_code() that is in turn plugged in to show_regs() to provide minimal code dumping at the end of the trace. Built on top of a simple instruction disassembler derived from the binutils opcode table. Signed-off-by: Paul Mundt --- arch/sh/kernel/Makefile_32 | 7 +- arch/sh/kernel/disassemble.c | 573 +++++++++++++++++++++++++++++++++++++++++++ arch/sh/kernel/process_32.c | 1 + 3 files changed, 578 insertions(+), 3 deletions(-) create mode 100644 arch/sh/kernel/disassemble.c (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index 76fcac1596ce..d3f2726b07dc 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -9,9 +9,10 @@ ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_ftrace.o = -pg endif -obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process_32.o \ - ptrace_32.o setup.o signal_32.o sys_sh.o sys_sh32.o \ - syscalls_32.o time_32.o topology.o traps.o traps_32.o +obj-y := debugtraps.o disassemble.o io.o io_generic.o irq.o \ + machvec.o process_32.o ptrace_32.o setup.o signal_32.o \ + sys_sh.o sys_sh32.o syscalls_32.o time_32.o topology.o \ + traps.o traps_32.o obj-y += cpu/ timers/ obj-$(CONFIG_VSYSCALL) += vsyscall/ diff --git a/arch/sh/kernel/disassemble.c b/arch/sh/kernel/disassemble.c new file mode 100644 index 000000000000..64d5d8dded7c --- /dev/null +++ b/arch/sh/kernel/disassemble.c @@ -0,0 +1,573 @@ +/* + * Disassemble SuperH instructions. + * + * Copyright (C) 1999 kaz Kojima + * Copyright (C) 2008 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include + +/* + * Format of an instruction in memory. + */ +typedef enum { + HEX_0, HEX_1, HEX_2, HEX_3, HEX_4, HEX_5, HEX_6, HEX_7, + HEX_8, HEX_9, HEX_A, HEX_B, HEX_C, HEX_D, HEX_E, HEX_F, + REG_N, REG_M, REG_NM, REG_B, + BRANCH_12, BRANCH_8, + DISP_8, DISP_4, + IMM_4, IMM_4BY2, IMM_4BY4, PCRELIMM_8BY2, PCRELIMM_8BY4, + IMM_8, IMM_8BY2, IMM_8BY4, +} sh_nibble_type; + +typedef enum { + A_END, A_BDISP12, A_BDISP8, + A_DEC_M, A_DEC_N, + A_DISP_GBR, A_DISP_PC, A_DISP_REG_M, A_DISP_REG_N, + A_GBR, + A_IMM, + A_INC_M, A_INC_N, + A_IND_M, A_IND_N, A_IND_R0_REG_M, A_IND_R0_REG_N, + A_MACH, A_MACL, + A_PR, A_R0, A_R0_GBR, A_REG_M, A_REG_N, A_REG_B, + A_SR, A_VBR, A_SSR, A_SPC, A_SGR, A_DBR, + F_REG_N, F_REG_M, D_REG_N, D_REG_M, + X_REG_N, /* Only used for argument parsing */ + X_REG_M, /* Only used for argument parsing */ + DX_REG_N, DX_REG_M, V_REG_N, V_REG_M, + FD_REG_N, + XMTRX_M4, + F_FR0, + FPUL_N, FPUL_M, FPSCR_N, FPSCR_M, +} sh_arg_type; + +static struct sh_opcode_info { + char *name; + sh_arg_type arg[7]; + sh_nibble_type nibbles[4]; +} sh_table[] = { + {"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM_8}}, + {"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}}, + {"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}}, + {"addv",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_F}}, + {"and",{A_IMM,A_R0},{HEX_C,HEX_9,IMM_8}}, + {"and",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_9}}, + {"and.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_D,IMM_8}}, + {"bra",{A_BDISP12},{HEX_A,BRANCH_12}}, + {"bsr",{A_BDISP12},{HEX_B,BRANCH_12}}, + {"bt",{A_BDISP8},{HEX_8,HEX_9,BRANCH_8}}, + {"bf",{A_BDISP8},{HEX_8,HEX_B,BRANCH_8}}, + {"bt.s",{A_BDISP8},{HEX_8,HEX_D,BRANCH_8}}, + {"bt/s",{A_BDISP8},{HEX_8,HEX_D,BRANCH_8}}, + {"bf.s",{A_BDISP8},{HEX_8,HEX_F,BRANCH_8}}, + {"bf/s",{A_BDISP8},{HEX_8,HEX_F,BRANCH_8}}, + {"clrmac",{0},{HEX_0,HEX_0,HEX_2,HEX_8}}, + {"clrs",{0},{HEX_0,HEX_0,HEX_4,HEX_8}}, + {"clrt",{0},{HEX_0,HEX_0,HEX_0,HEX_8}}, + {"cmp/eq",{A_IMM,A_R0},{HEX_8,HEX_8,IMM_8}}, + {"cmp/eq",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_0}}, + {"cmp/ge",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_3}}, + {"cmp/gt",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_7}}, + {"cmp/hi",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_6}}, + {"cmp/hs",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_2}}, + {"cmp/pl",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_5}}, + {"cmp/pz",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_1}}, + {"cmp/str",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_C}}, + {"div0s",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_7}}, + {"div0u",{0},{HEX_0,HEX_0,HEX_1,HEX_9}}, + {"div1",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_4}}, + {"exts.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_E}}, + {"exts.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_F}}, + {"extu.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_C}}, + {"extu.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_D}}, + {"jmp",{A_IND_N},{HEX_4,REG_N,HEX_2,HEX_B}}, + {"jsr",{A_IND_N},{HEX_4,REG_N,HEX_0,HEX_B}}, + {"ldc",{A_REG_N,A_SR},{HEX_4,REG_N,HEX_0,HEX_E}}, + {"ldc",{A_REG_N,A_GBR},{HEX_4,REG_N,HEX_1,HEX_E}}, + {"ldc",{A_REG_N,A_VBR},{HEX_4,REG_N,HEX_2,HEX_E}}, + {"ldc",{A_REG_N,A_SSR},{HEX_4,REG_N,HEX_3,HEX_E}}, + {"ldc",{A_REG_N,A_SPC},{HEX_4,REG_N,HEX_4,HEX_E}}, + {"ldc",{A_REG_N,A_DBR},{HEX_4,REG_N,HEX_7,HEX_E}}, + {"ldc",{A_REG_N,A_REG_B},{HEX_4,REG_N,REG_B,HEX_E}}, + {"ldc.l",{A_INC_N,A_SR},{HEX_4,REG_N,HEX_0,HEX_7}}, + {"ldc.l",{A_INC_N,A_GBR},{HEX_4,REG_N,HEX_1,HEX_7}}, + {"ldc.l",{A_INC_N,A_VBR},{HEX_4,REG_N,HEX_2,HEX_7}}, + {"ldc.l",{A_INC_N,A_SSR},{HEX_4,REG_N,HEX_3,HEX_7}}, + {"ldc.l",{A_INC_N,A_SPC},{HEX_4,REG_N,HEX_4,HEX_7}}, + {"ldc.l",{A_INC_N,A_DBR},{HEX_4,REG_N,HEX_7,HEX_7}}, + {"ldc.l",{A_INC_N,A_REG_B},{HEX_4,REG_N,REG_B,HEX_7}}, + {"lds",{A_REG_N,A_MACH},{HEX_4,REG_N,HEX_0,HEX_A}}, + {"lds",{A_REG_N,A_MACL},{HEX_4,REG_N,HEX_1,HEX_A}}, + {"lds",{A_REG_N,A_PR},{HEX_4,REG_N,HEX_2,HEX_A}}, + {"lds",{A_REG_M,FPUL_N},{HEX_4,REG_M,HEX_5,HEX_A}}, + {"lds",{A_REG_M,FPSCR_N},{HEX_4,REG_M,HEX_6,HEX_A}}, + {"lds.l",{A_INC_N,A_MACH},{HEX_4,REG_N,HEX_0,HEX_6}}, + {"lds.l",{A_INC_N,A_MACL},{HEX_4,REG_N,HEX_1,HEX_6}}, + {"lds.l",{A_INC_N,A_PR},{HEX_4,REG_N,HEX_2,HEX_6}}, + {"lds.l",{A_INC_M,FPUL_N},{HEX_4,REG_M,HEX_5,HEX_6}}, + {"lds.l",{A_INC_M,FPSCR_N},{HEX_4,REG_M,HEX_6,HEX_6}}, + {"ldtlb",{0},{HEX_0,HEX_0,HEX_3,HEX_8}}, + {"mac.w",{A_INC_M,A_INC_N},{HEX_4,REG_N,REG_M,HEX_F}}, + {"mov",{A_IMM,A_REG_N},{HEX_E,REG_N,IMM_8}}, + {"mov",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_3}}, + {"mov.b",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_4}}, + {"mov.b",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_4}}, + {"mov.b",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_0}}, + {"mov.b",{A_DISP_REG_M,A_R0},{HEX_8,HEX_4,REG_M,IMM_4}}, + {"mov.b",{A_DISP_GBR,A_R0},{HEX_C,HEX_4,IMM_8}}, + {"mov.b",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_C}}, + {"mov.b",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_4}}, + {"mov.b",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_0}}, + {"mov.b",{A_R0,A_DISP_REG_M},{HEX_8,HEX_0,REG_M,IMM_4}}, + {"mov.b",{A_R0,A_DISP_GBR},{HEX_C,HEX_0,IMM_8}}, + {"mov.l",{ A_REG_M,A_DISP_REG_N},{HEX_1,REG_N,REG_M,IMM_4BY4}}, + {"mov.l",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_6}}, + {"mov.l",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_6}}, + {"mov.l",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_2}}, + {"mov.l",{A_DISP_REG_M,A_REG_N},{HEX_5,REG_N,REG_M,IMM_4BY4}}, + {"mov.l",{A_DISP_GBR,A_R0},{HEX_C,HEX_6,IMM_8BY4}}, + {"mov.l",{A_DISP_PC,A_REG_N},{HEX_D,REG_N,PCRELIMM_8BY4}}, + {"mov.l",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_E}}, + {"mov.l",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_6}}, + {"mov.l",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_2}}, + {"mov.l",{A_R0,A_DISP_GBR},{HEX_C,HEX_2,IMM_8BY4}}, + {"mov.w",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_5}}, + {"mov.w",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_5}}, + {"mov.w",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_1}}, + {"mov.w",{A_DISP_REG_M,A_R0},{HEX_8,HEX_5,REG_M,IMM_4BY2}}, + {"mov.w",{A_DISP_GBR,A_R0},{HEX_C,HEX_5,IMM_8BY2}}, + {"mov.w",{A_DISP_PC,A_REG_N},{HEX_9,REG_N,PCRELIMM_8BY2}}, + {"mov.w",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_D}}, + {"mov.w",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_5}}, + {"mov.w",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_1}}, + {"mov.w",{A_R0,A_DISP_REG_M},{HEX_8,HEX_1,REG_M,IMM_4BY2}}, + {"mov.w",{A_R0,A_DISP_GBR},{HEX_C,HEX_1,IMM_8BY2}}, + {"mova",{A_DISP_PC,A_R0},{HEX_C,HEX_7,PCRELIMM_8BY4}}, + {"movca.l",{A_R0,A_IND_N},{HEX_0,REG_N,HEX_C,HEX_3}}, + {"movt",{A_REG_N},{HEX_0,REG_N,HEX_2,HEX_9}}, + {"muls",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_F}}, + {"mul.l",{ A_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_7}}, + {"mulu",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_E}}, + {"neg",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_B}}, + {"negc",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_A}}, + {"nop",{0},{HEX_0,HEX_0,HEX_0,HEX_9}}, + {"not",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_7}}, + {"ocbi",{A_IND_N},{HEX_0,REG_N,HEX_9,HEX_3}}, + {"ocbp",{A_IND_N},{HEX_0,REG_N,HEX_A,HEX_3}}, + {"ocbwb",{A_IND_N},{HEX_0,REG_N,HEX_B,HEX_3}}, + {"or",{A_IMM,A_R0},{HEX_C,HEX_B,IMM_8}}, + {"or",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_B}}, + {"or.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_F,IMM_8}}, + {"pref",{A_IND_N},{HEX_0,REG_N,HEX_8,HEX_3}}, + {"rotcl",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_4}}, + {"rotcr",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_5}}, + {"rotl",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_4}}, + {"rotr",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_5}}, + {"rte",{0},{HEX_0,HEX_0,HEX_2,HEX_B}}, + {"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}}, + {"sets",{0},{HEX_0,HEX_0,HEX_5,HEX_8}}, + {"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}}, + {"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}}, + {"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}}, + {"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}}, + {"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}}, + {"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}}, + {"shll16",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_8}}, + {"shll2",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_8}}, + {"shll8",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_8}}, + {"shlr",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_1}}, + {"shlr16",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_9}}, + {"shlr2",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_9}}, + {"shlr8",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_9}}, + {"sleep",{0},{HEX_0,HEX_0,HEX_1,HEX_B}}, + {"stc",{A_SR,A_REG_N},{HEX_0,REG_N,HEX_0,HEX_2}}, + {"stc",{A_GBR,A_REG_N},{HEX_0,REG_N,HEX_1,HEX_2}}, + {"stc",{A_VBR,A_REG_N},{HEX_0,REG_N,HEX_2,HEX_2}}, + {"stc",{A_SSR,A_REG_N},{HEX_0,REG_N,HEX_3,HEX_2}}, + {"stc",{A_SPC,A_REG_N},{HEX_0,REG_N,HEX_4,HEX_2}}, + {"stc",{A_SGR,A_REG_N},{HEX_0,REG_N,HEX_6,HEX_2}}, + {"stc",{A_DBR,A_REG_N},{HEX_0,REG_N,HEX_7,HEX_2}}, + {"stc",{A_REG_B,A_REG_N},{HEX_0,REG_N,REG_B,HEX_2}}, + {"stc.l",{A_SR,A_DEC_N},{HEX_4,REG_N,HEX_0,HEX_3}}, + {"stc.l",{A_GBR,A_DEC_N},{HEX_4,REG_N,HEX_1,HEX_3}}, + {"stc.l",{A_VBR,A_DEC_N},{HEX_4,REG_N,HEX_2,HEX_3}}, + {"stc.l",{A_SSR,A_DEC_N},{HEX_4,REG_N,HEX_3,HEX_3}}, + {"stc.l",{A_SPC,A_DEC_N},{HEX_4,REG_N,HEX_4,HEX_3}}, + {"stc.l",{A_SGR,A_DEC_N},{HEX_4,REG_N,HEX_6,HEX_3}}, + {"stc.l",{A_DBR,A_DEC_N},{HEX_4,REG_N,HEX_7,HEX_3}}, + {"stc.l",{A_REG_B,A_DEC_N},{HEX_4,REG_N,REG_B,HEX_3}}, + {"sts",{A_MACH,A_REG_N},{HEX_0,REG_N,HEX_0,HEX_A}}, + {"sts",{A_MACL,A_REG_N},{HEX_0,REG_N,HEX_1,HEX_A}}, + {"sts",{A_PR,A_REG_N},{HEX_0,REG_N,HEX_2,HEX_A}}, + {"sts",{FPUL_M,A_REG_N},{HEX_0,REG_N,HEX_5,HEX_A}}, + {"sts",{FPSCR_M,A_REG_N},{HEX_0,REG_N,HEX_6,HEX_A}}, + {"sts.l",{A_MACH,A_DEC_N},{HEX_4,REG_N,HEX_0,HEX_2}}, + {"sts.l",{A_MACL,A_DEC_N},{HEX_4,REG_N,HEX_1,HEX_2}}, + {"sts.l",{A_PR,A_DEC_N},{HEX_4,REG_N,HEX_2,HEX_2}}, + {"sts.l",{FPUL_M,A_DEC_N},{HEX_4,REG_N,HEX_5,HEX_2}}, + {"sts.l",{FPSCR_M,A_DEC_N},{HEX_4,REG_N,HEX_6,HEX_2}}, + {"sub",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_8}}, + {"subc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_A}}, + {"subv",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_B}}, + {"swap.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_8}}, + {"swap.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_9}}, + {"tas.b",{A_IND_N},{HEX_4,REG_N,HEX_1,HEX_B}}, + {"trapa",{A_IMM},{HEX_C,HEX_3,IMM_8}}, + {"tst",{A_IMM,A_R0},{HEX_C,HEX_8,IMM_8}}, + {"tst",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_8}}, + {"tst.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_C,IMM_8}}, + {"xor",{A_IMM,A_R0},{HEX_C,HEX_A,IMM_8}}, + {"xor",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_A}}, + {"xor.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_E,IMM_8}}, + {"xtrct",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_D}}, + {"mul.l",{ A_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_7}}, + {"dt",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_0}}, + {"dmuls.l",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_D}}, + {"dmulu.l",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_5}}, + {"mac.l",{A_INC_M,A_INC_N},{HEX_0,REG_N,REG_M,HEX_F}}, + {"braf",{A_REG_N},{HEX_0,REG_N,HEX_2,HEX_3}}, + {"bsrf",{A_REG_N},{HEX_0,REG_N,HEX_0,HEX_3}}, + {"fabs",{FD_REG_N},{HEX_F,REG_N,HEX_5,HEX_D}}, + {"fadd",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_0}}, + {"fadd",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_0}}, + {"fcmp/eq",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_4}}, + {"fcmp/eq",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_4}}, + {"fcmp/gt",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_5}}, + {"fcmp/gt",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_5}}, + {"fcnvds",{D_REG_N,FPUL_M},{HEX_F,REG_N,HEX_B,HEX_D}}, + {"fcnvsd",{FPUL_M,D_REG_N},{HEX_F,REG_N,HEX_A,HEX_D}}, + {"fdiv",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_3}}, + {"fdiv",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_3}}, + {"fipr",{V_REG_M,V_REG_N},{HEX_F,REG_NM,HEX_E,HEX_D}}, + {"fldi0",{F_REG_N},{HEX_F,REG_N,HEX_8,HEX_D}}, + {"fldi1",{F_REG_N},{HEX_F,REG_N,HEX_9,HEX_D}}, + {"flds",{F_REG_N,FPUL_M},{HEX_F,REG_N,HEX_1,HEX_D}}, + {"float",{FPUL_M,FD_REG_N},{HEX_F,REG_N,HEX_2,HEX_D}}, + {"fmac",{F_FR0,F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_E}}, + {"fmov",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_C}}, + {"fmov",{DX_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_C}}, + {"fmov",{A_IND_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, + {"fmov",{A_IND_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, + {"fmov",{F_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, + {"fmov",{DX_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, + {"fmov",{A_INC_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, + {"fmov",{A_INC_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, + {"fmov",{F_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, + {"fmov",{DX_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, + {"fmov",{A_IND_R0_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, + {"fmov",{A_IND_R0_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, + {"fmov",{F_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, + {"fmov",{DX_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, + {"fmov.d",{A_IND_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, + {"fmov.d",{DX_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, + {"fmov.d",{A_INC_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, + {"fmov.d",{DX_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, + {"fmov.d",{A_IND_R0_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, + {"fmov.d",{DX_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, + {"fmov.s",{A_IND_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, + {"fmov.s",{F_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, + {"fmov.s",{A_INC_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, + {"fmov.s",{F_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, + {"fmov.s",{A_IND_R0_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, + {"fmov.s",{F_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, + {"fmul",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_2}}, + {"fmul",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_2}}, + {"fneg",{FD_REG_N},{HEX_F,REG_N,HEX_4,HEX_D}}, + {"frchg",{0},{HEX_F,HEX_B,HEX_F,HEX_D}}, + {"fschg",{0},{HEX_F,HEX_3,HEX_F,HEX_D}}, + {"fsqrt",{FD_REG_N},{HEX_F,REG_N,HEX_6,HEX_D}}, + {"fsts",{FPUL_M,F_REG_N},{HEX_F,REG_N,HEX_0,HEX_D}}, + {"fsub",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_1}}, + {"fsub",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_1}}, + {"ftrc",{FD_REG_N,FPUL_M},{HEX_F,REG_N,HEX_3,HEX_D}}, + {"ftrv",{XMTRX_M4,V_REG_N},{HEX_F,REG_NM,HEX_F,HEX_D}}, + { 0 }, +}; + +static void print_sh_insn(u32 memaddr, u16 insn) +{ + int relmask = ~0; + int nibs[4] = { (insn >> 12) & 0xf, (insn >> 8) & 0xf, (insn >> 4) & 0xf, insn & 0xf}; + int lastsp; + struct sh_opcode_info *op = sh_table; + + for (; op->name; op++) { + int n; + int imm = 0; + int rn = 0; + int rm = 0; + int rb = 0; + int disp_pc; + int disp_pc_addr = 0; + + for (n = 0; n < 4; n++) { + int i = op->nibbles[n]; + + if (i < 16) { + if (nibs[n] == i) + continue; + goto fail; + } + switch (i) { + case BRANCH_8: + imm = (nibs[2] << 4) | (nibs[3]); + if (imm & 0x80) + imm |= ~0xff; + imm = ((char)imm) * 2 + 4 ; + goto ok; + case BRANCH_12: + imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]); + if (imm & 0x800) + imm |= ~0xfff; + imm = imm * 2 + 4; + goto ok; + case IMM_4: + imm = nibs[3]; + goto ok; + case IMM_4BY2: + imm = nibs[3] <<1; + goto ok; + case IMM_4BY4: + imm = nibs[3] <<2; + goto ok; + case IMM_8: + imm = (nibs[2] << 4) | nibs[3]; + goto ok; + case PCRELIMM_8BY2: + imm = ((nibs[2] << 4) | nibs[3]) <<1; + relmask = ~1; + goto ok; + case PCRELIMM_8BY4: + imm = ((nibs[2] << 4) | nibs[3]) <<2; + relmask = ~3; + goto ok; + case IMM_8BY2: + imm = ((nibs[2] << 4) | nibs[3]) <<1; + goto ok; + case IMM_8BY4: + imm = ((nibs[2] << 4) | nibs[3]) <<2; + goto ok; + case DISP_8: + imm = (nibs[2] << 4) | (nibs[3]); + goto ok; + case DISP_4: + imm = nibs[3]; + goto ok; + case REG_N: + rn = nibs[n]; + break; + case REG_M: + rm = nibs[n]; + break; + case REG_NM: + rn = (nibs[n] & 0xc) >> 2; + rm = (nibs[n] & 0x3); + break; + case REG_B: + rb = nibs[n] & 0x07; + break; + default: + return; + } + } + + ok: + printk("%-8s ", op->name); + lastsp = (op->arg[0] == A_END); + disp_pc = 0; + for (n = 0; n < 6 && op->arg[n] != A_END; n++) { + if (n && op->arg[1] != A_END) + printk(", "); + switch (op->arg[n]) { + case A_IMM: + printk("#%d", (char)(imm)); + break; + case A_R0: + printk("r0"); + break; + case A_REG_N: + printk("r%d", rn); + break; + case A_INC_N: + printk("@r%d+", rn); + break; + case A_DEC_N: + printk("@-r%d", rn); + break; + case A_IND_N: + printk("@r%d", rn); + break; + case A_DISP_REG_N: + printk("@(%d,r%d)", imm, rn); + break; + case A_REG_M: + printk("r%d", rm); + break; + case A_INC_M: + printk("@r%d+", rm); + break; + case A_DEC_M: + printk("@-r%d", rm); + break; + case A_IND_M: + printk("@r%d", rm); + break; + case A_DISP_REG_M: + printk("@(%d,r%d)", imm, rm); + break; + case A_REG_B: + printk("r%d_bank", rb); + break; + case A_DISP_PC: + disp_pc = 1; + disp_pc_addr = imm + 4 + (memaddr & relmask); + printk("%08x <%pS>", disp_pc_addr, + (void *)disp_pc_addr); + break; + case A_IND_R0_REG_N: + printk("@(r0,r%d)", rn); + break; + case A_IND_R0_REG_M: + printk("@(r0,r%d)", rm); + break; + case A_DISP_GBR: + printk("@(%d,gbr)",imm); + break; + case A_R0_GBR: + printk("@(r0,gbr)"); + break; + case A_BDISP12: + case A_BDISP8: + printk("%08x", imm + memaddr); + break; + case A_SR: + printk("sr"); + break; + case A_GBR: + printk("gbr"); + break; + case A_VBR: + printk("vbr"); + break; + case A_SSR: + printk("ssr"); + break; + case A_SPC: + printk("spc"); + break; + case A_MACH: + printk("mach"); + break; + case A_MACL: + printk("macl"); + break; + case A_PR: + printk("pr"); + break; + case A_SGR: + printk("sgr"); + break; + case A_DBR: + printk("dbr"); + break; + case FD_REG_N: + if (0) + goto d_reg_n; + case F_REG_N: + printk("fr%d", rn); + break; + case F_REG_M: + printk("fr%d", rm); + break; + case DX_REG_N: + if (rn & 1) { + printk("xd%d", rn & ~1); + break; + } + d_reg_n: + case D_REG_N: + printk("dr%d", rn); + break; + case DX_REG_M: + if (rm & 1) { + printk("xd%d", rm & ~1); + break; + } + case D_REG_M: + printk("dr%d", rm); + break; + case FPSCR_M: + case FPSCR_N: + printk("fpscr"); + break; + case FPUL_M: + case FPUL_N: + printk("fpul"); + break; + case F_FR0: + printk("fr0"); + break; + case V_REG_N: + printk("fv%d", rn*4); + break; + case V_REG_M: + printk("fv%d", rm*4); + break; + case XMTRX_M4: + printk("xmtrx"); + break; + default: + return; + } + } + + if (disp_pc && strcmp(op->name, "mova") != 0) { + u32 val; + + if (relmask == ~1) + __get_user(val, (u16 *)disp_pc_addr); + else + __get_user(val, (u32 *)disp_pc_addr); + + printk(" ! %08x <%pS>", val, (void *)val); + } + + return; + fail: + ; + + } + + printk(".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]); +} + +void show_code(struct pt_regs *regs) +{ + unsigned short *pc = (unsigned short *)regs->pc; + long i; + + if (regs->pc & 0x1) + return; + + printk("Code:\n"); + + for (i = -3 ; i < 6 ; i++) { + unsigned short insn; + + if (__get_user(insn, pc + i)) { + printk(" (Bad address in pc)\n"); + break; + } + + printk("%s%08lx: ", (i ? " ": "->"), (unsigned long)(pc + i)); + print_sh_insn((unsigned long)(pc + i), insn); + printk("\n"); + } + + printk("\n"); +} diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index b965f0282c7d..57de3f168102 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -148,6 +148,7 @@ void show_regs(struct pt_regs * regs) regs->mach, regs->macl, regs->gbr, regs->pr); show_trace(NULL, (unsigned long *)regs->regs[15], regs); + show_code(regs); } /* -- cgit v1.2.1 From 75fd24c1073adcd1e8ea43048d946bbfa34dfc64 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 26 Nov 2008 15:20:35 +0900 Subject: sh: Tidy up backtrace formatting with kallsyms disabled. Signed-off-by: Paul Mundt --- arch/sh/kernel/process_32.c | 4 ++-- arch/sh/kernel/traps_32.c | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 57de3f168102..908731c49afb 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -115,8 +115,8 @@ void machine_power_off(void) void show_regs(struct pt_regs * regs) { printk("\n"); - printk("Pid : %d, Comm: %20s\n", task_pid_nr(current), current->comm); - printk("CPU : %d %s (%s %.*s)\n", + printk("Pid : %d, Comm: \t\t%s\n", task_pid_nr(current), current->comm); + printk("CPU : %d \t\t%s (%s %.*s)\n\n", smp_processor_id(), print_tainted(), init_utsname()->release, (int)strcspn(init_utsname()->version, " "), init_utsname()->version); diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index f2497585cac0..6094fc13beea 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -873,10 +873,7 @@ void show_trace(struct task_struct *tsk, unsigned long *sp, if (regs && user_mode(regs)) return; - printk("\nCall trace: "); -#ifdef CONFIG_KALLSYMS - printk("\n"); -#endif + printk("\nCall trace:\n"); while (!kstack_end(sp)) { addr = *sp++; -- cgit v1.2.1 From f74c034d52d0f908d5b929423a680962a2586199 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 26 Nov 2008 15:22:50 +0900 Subject: sh: do not latency trace idle. Description snipped from Steven Rostedt's PPC patch: When idle is called, interrupts are blocked, but the idle function will still wake up on an interrupt. The problem is that the interrupt disabled latency tracer will take this call to idle as a latency. This patch disables the latency tracing when going into idle. Signed-off-by: Paul Mundt --- arch/sh/kernel/process_32.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 908731c49afb..e781540bd991 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -59,8 +59,12 @@ static void default_idle(void) clear_thread_flag(TIF_POLLING_NRFLAG); smp_mb__after_clear_bit(); set_bl_bit(); + stop_critical_timings(); + while (!need_resched()) cpu_sleep(); + + start_critical_timings(); clear_bl_bit(); set_thread_flag(TIF_POLLING_NRFLAG); } else -- cgit v1.2.1 From 1da1180c6e28cf21be356e2701978727558fa198 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 26 Nov 2008 15:52:44 +0900 Subject: sh: Split out the idle loop for reuse between _32/_64 variants. Signed-off-by: Paul Mundt --- arch/sh/kernel/Makefile_32 | 2 +- arch/sh/kernel/Makefile_64 | 2 +- arch/sh/kernel/idle.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ arch/sh/kernel/process_32.c | 61 ---------------------------------- arch/sh/kernel/process_64.c | 60 --------------------------------- 5 files changed, 83 insertions(+), 123 deletions(-) create mode 100644 arch/sh/kernel/idle.c (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index d3f2726b07dc..d9df9e567946 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -9,7 +9,7 @@ ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_ftrace.o = -pg endif -obj-y := debugtraps.o disassemble.o io.o io_generic.o irq.o \ +obj-y := debugtraps.o disassemble.o idle.o io.o io_generic.o irq.o \ machvec.o process_32.o ptrace_32.o setup.o signal_32.o \ sys_sh.o sys_sh32.o syscalls_32.o time_32.o topology.o \ traps.o traps_32.o diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64 index c97660b2b48d..4304b2593c2c 100644 --- a/arch/sh/kernel/Makefile_64 +++ b/arch/sh/kernel/Makefile_64 @@ -1,6 +1,6 @@ extra-y := head_64.o init_task.o vmlinux.lds -obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process_64.o \ +obj-y := debugtraps.o idle.o io.o io_generic.o irq.o machvec.o process_64.o \ ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \ syscalls_64.o time_64.o topology.o traps.o traps_64.o diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c new file mode 100644 index 000000000000..fe59ccfc1152 --- /dev/null +++ b/arch/sh/kernel/idle.c @@ -0,0 +1,81 @@ +/* + * The idle loop for all SuperH platforms. + * + * Copyright (C) 2002 - 2008 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int hlt_counter; +void (*pm_idle)(void); +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); + +static int __init nohlt_setup(char *__unused) +{ + hlt_counter = 1; + return 1; +} +__setup("nohlt", nohlt_setup); + +static int __init hlt_setup(char *__unused) +{ + hlt_counter = 0; + return 1; +} +__setup("hlt", hlt_setup); + +static void default_idle(void) +{ + if (!hlt_counter) { + clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb__after_clear_bit(); + set_bl_bit(); + stop_critical_timings(); + + while (!need_resched()) + cpu_sleep(); + + start_critical_timings(); + clear_bl_bit(); + set_thread_flag(TIF_POLLING_NRFLAG); + } else + while (!need_resched()) + cpu_relax(); +} + +void cpu_idle(void) +{ + set_thread_flag(TIF_POLLING_NRFLAG); + + /* endless idle loop with no priority at all */ + while (1) { + void (*idle)(void) = pm_idle; + + if (!idle) + idle = default_idle; + + tick_nohz_stop_sched_tick(1); + while (!need_resched()) + idle(); + tick_nohz_restart_sched_tick(); + + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + check_pgt_cache(); + } +} diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index e781540bd991..130817affa64 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -32,69 +32,8 @@ #include #include -static int hlt_counter; int ubc_usercnt = 0; -void (*pm_idle)(void); -void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); - -static int __init nohlt_setup(char *__unused) -{ - hlt_counter = 1; - return 1; -} -__setup("nohlt", nohlt_setup); - -static int __init hlt_setup(char *__unused) -{ - hlt_counter = 0; - return 1; -} -__setup("hlt", hlt_setup); - -static void default_idle(void) -{ - if (!hlt_counter) { - clear_thread_flag(TIF_POLLING_NRFLAG); - smp_mb__after_clear_bit(); - set_bl_bit(); - stop_critical_timings(); - - while (!need_resched()) - cpu_sleep(); - - start_critical_timings(); - clear_bl_bit(); - set_thread_flag(TIF_POLLING_NRFLAG); - } else - while (!need_resched()) - cpu_relax(); -} - -void cpu_idle(void) -{ - set_thread_flag(TIF_POLLING_NRFLAG); - - /* endless idle loop with no priority at all */ - while (1) { - void (*idle)(void) = pm_idle; - - if (!idle) - idle = default_idle; - - tick_nohz_stop_sched_tick(1); - while (!need_resched()) - idle(); - tick_nohz_restart_sched_tick(); - - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - check_pgt_cache(); - } -} - void machine_restart(char * __unused) { /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index b7aa09235b51..597cf02db3fc 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c @@ -33,56 +33,6 @@ struct task_struct *last_task_used_math = NULL; -static int hlt_counter = 1; - -#define HARD_IDLE_TIMEOUT (HZ / 3) - -static int __init nohlt_setup(char *__unused) -{ - hlt_counter = 1; - return 1; -} - -static int __init hlt_setup(char *__unused) -{ - hlt_counter = 0; - return 1; -} - -__setup("nohlt", nohlt_setup); -__setup("hlt", hlt_setup); - -static inline void hlt(void) -{ - __asm__ __volatile__ ("sleep" : : : "memory"); -} - -/* - * The idle loop on a uniprocessor SH.. - */ -void cpu_idle(void) -{ - /* endless idle loop with no priority at all */ - while (1) { - if (hlt_counter) { - while (!need_resched()) - cpu_relax(); - } else { - local_irq_disable(); - while (!need_resched()) { - local_irq_enable(); - hlt(); - local_irq_disable(); - } - local_irq_enable(); - } - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } - -} - void machine_restart(char * __unused) { extern void phys_stext(void); @@ -97,13 +47,6 @@ void machine_halt(void) void machine_power_off(void) { -#if 0 - /* Disable watchdog timer */ - ctrl_outl(0xa5000000, WTCSR); - /* Configure deep standby on sleep */ - ctrl_outl(0x03, STBCR); -#endif - __asm__ __volatile__ ( "sleep\n\t" "synci\n\t" @@ -113,9 +56,6 @@ void machine_power_off(void) panic("Unexpected wakeup!\n"); } -void (*pm_power_off)(void) = machine_power_off; -EXPORT_SYMBOL(pm_power_off); - void show_regs(struct pt_regs * regs) { unsigned long long ah, al, bh, bl, ch, cl; -- cgit v1.2.1 From 2825999e8a9bd7ab7e25a7e7475c7cdd10371a13 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Fri, 28 Nov 2008 22:48:20 +0900 Subject: sh: Add support for SH7201 CPU subtype. This patch adds support for the SH-2A FPU based SH7201 processor subtype. Signed-off-by: Peter Griffin Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh2a/Makefile | 3 +- arch/sh/kernel/cpu/sh2a/clock-sh7201.c | 85 +++++++++ arch/sh/kernel/cpu/sh2a/probe.c | 7 +- arch/sh/kernel/cpu/sh2a/setup-sh7201.c | 331 +++++++++++++++++++++++++++++++++ arch/sh/kernel/setup.c | 1 + arch/sh/kernel/timers/timer-mtu2.c | 5 + 6 files changed, 428 insertions(+), 4 deletions(-) create mode 100644 arch/sh/kernel/cpu/sh2a/clock-sh7201.c create mode 100644 arch/sh/kernel/cpu/sh2a/setup-sh7201.c (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile index 428450cc0809..45f85c77ef75 100644 --- a/arch/sh/kernel/cpu/sh2a/Makefile +++ b/arch/sh/kernel/cpu/sh2a/Makefile @@ -8,9 +8,10 @@ common-y += ex.o entry.o obj-$(CONFIG_SH_FPU) += fpu.o -obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o +obj-$(CONFIG_CPU_SUBTYPE_SH7201) += setup-sh7201.o clock-sh7201.o obj-$(CONFIG_CPU_SUBTYPE_SH7203) += setup-sh7203.o clock-sh7203.o obj-$(CONFIG_CPU_SUBTYPE_SH7263) += setup-sh7203.o clock-sh7203.o +obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o obj-$(CONFIG_CPU_SUBTYPE_MXG) += setup-mxg.o clock-sh7206.o # Pinmux setup diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c new file mode 100644 index 000000000000..020a96fe961a --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c @@ -0,0 +1,85 @@ +/* + * arch/sh/kernel/cpu/sh2a/clock-sh7201.c + * + * SH7201 support for the clock framework + * + * Copyright (C) 2008 Peter Griffin + * + * Based on clock-sh4.c + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +const static int pll1rate[]={1,2,3,4,6,8}; +const static int pfc_divisors[]={1,2,3,4,6,8,12}; +#define ifc_divisors pfc_divisors + +#if (CONFIG_SH_CLK_MD == 0) +#define PLL2 (4) +#elif (CONFIG_SH_CLK_MD == 2) +#define PLL2 (2) +#elif (CONFIG_SH_CLK_MD == 3) +#define PLL2 (1) +#else +#error "Illegal Clock Mode!" +#endif + +static void master_clk_init(struct clk *clk) +{ + clk->rate = 10000000 * PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; +} + +static struct clk_ops sh7201_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7201_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7201_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inw(FREQCR) >> 4) & 0x0007); + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7201_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7201_clk_ops[] = { + &sh7201_master_clk_ops, + &sh7201_module_clk_ops, + &sh7201_bus_clk_ops, + &sh7201_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7201_clk_ops)) + *ops = sh7201_clk_ops[idx]; +} diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c index 6e79132f6f30..e098e2f6aa08 100644 --- a/arch/sh/kernel/cpu/sh2a/probe.c +++ b/arch/sh/kernel/cpu/sh2a/probe.c @@ -18,16 +18,17 @@ int __init detect_cpu_and_cache_system(void) /* All SH-2A CPUs have support for 16 and 32-bit opcodes.. */ boot_cpu_data.flags |= CPU_HAS_OP32; -#if defined(CONFIG_CPU_SUBTYPE_SH7203) +#if defined(CONFIG_CPU_SUBTYPE_SH7201) + boot_cpu_data.type = CPU_SH7201; + boot_cpu_data.flags |= CPU_HAS_FPU; +#elif defined(CONFIG_CPU_SUBTYPE_SH7203) boot_cpu_data.type = CPU_SH7203; - /* SH7203 has an FPU.. */ boot_cpu_data.flags |= CPU_HAS_FPU; #elif defined(CONFIG_CPU_SUBTYPE_SH7263) boot_cpu_data.type = CPU_SH7263; boot_cpu_data.flags |= CPU_HAS_FPU; #elif defined(CONFIG_CPU_SUBTYPE_SH7206) boot_cpu_data.type = CPU_SH7206; - /* While SH7206 has a DSP.. */ boot_cpu_data.flags |= CPU_HAS_DSP; #elif defined(CONFIG_CPU_SUBTYPE_MXG) boot_cpu_data.type = CPU_MXG; diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c new file mode 100644 index 000000000000..0631e421c022 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c @@ -0,0 +1,331 @@ +/* + * SH7201 setup + * + * Copyright (C) 2008 Peter Griffin pgriffin@mpc-data.co.uk + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include + +enum { + UNUSED = 0, + + /* interrupt sources */ + IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, + PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7, + ADC_ADI, + MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D, + MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F, + MTU2_TGI1A, MTU2_TGI1B, MTU2_TCI1V, MTU2_TCI1U, + MTU2_TGI2A, MTU2_TGI2B, MTU2_TCI2V, MTU2_TCI2U, + MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D, MTU2_TCI3V, + MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D, MTU2_TCI4V, + MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W, + RTC_ARM, RTC_PRD, RTC_CUP, + WDT, + IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI, IIC30_TEI, + IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI, IIC31_TEI, + IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI, IIC32_TEI, + + DMAC0_DMINT0, DMAC1_DMINT1, + DMAC2_DMINT2, DMAC3_DMINT3, + + SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI, + SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI, + SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI, + SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI, + SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI, + SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI, + SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI, + SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI, + + DMAC0_DMINTA, DMAC4_DMINT4, DMAC5_DMINT5, DMAC6_DMINT6, + DMAC7_DMINT7, + + RCAN0_ERS, RCAN0_OVR, + RCAN0_SLE, + RCAN0_RM0, RCAN0_RM1, + + RCAN1_ERS, RCAN1_OVR, + RCAN1_SLE, + RCAN1_RM0, RCAN1_RM1, + + SSI0_SSII, SSI1_SSII, + + TMR0_CMIA0, TMR0_CMIB0, TMR0_OVI0, + TMR1_CMIA1, TMR1_CMIB1, TMR1_OVI1, + + /* interrupt groups */ + + IRQ, PINT, ADC, + MTU20_ABCD, MTU20_VEF, MTU21_AB, MTU21_VU, MTU22_AB, MTU22_VU, + MTU23_ABCD, MTU24_ABCD, MTU25_UVW, + RTC, IIC30, IIC31, IIC32, + SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7, + RCAN0, RCAN1, TMR0, TMR1 + +}; + +static struct intc_vect vectors[] __initdata = { + INTC_IRQ(IRQ0, 64), INTC_IRQ(IRQ1, 65), + INTC_IRQ(IRQ2, 66), INTC_IRQ(IRQ3, 67), + INTC_IRQ(IRQ4, 68), INTC_IRQ(IRQ5, 69), + INTC_IRQ(IRQ6, 70), INTC_IRQ(IRQ7, 71), + INTC_IRQ(PINT0, 80), INTC_IRQ(PINT1, 81), + INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83), + INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85), + INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87), + + INTC_IRQ(ADC_ADI, 92), + + INTC_IRQ(MTU2_TGI0A, 108), INTC_IRQ(MTU2_TGI0B, 109), + INTC_IRQ(MTU2_TGI0C, 110), INTC_IRQ(MTU2_TGI0D, 111), + INTC_IRQ(MTU2_TCI0V, 112), + INTC_IRQ(MTU2_TGI0E, 113), INTC_IRQ(MTU2_TGI0F, 114), + + INTC_IRQ(MTU2_TGI1A, 116), INTC_IRQ(MTU2_TGI1B, 117), + INTC_IRQ(MTU2_TCI1V, 120), INTC_IRQ(MTU2_TCI1U, 121), + + INTC_IRQ(MTU2_TGI2A, 124), INTC_IRQ(MTU2_TGI2B, 125), + INTC_IRQ(MTU2_TCI2V, 128), INTC_IRQ(MTU2_TCI2U, 129), + + INTC_IRQ(MTU2_TGI3A, 132), INTC_IRQ(MTU2_TGI3B, 133), + INTC_IRQ(MTU2_TGI3C, 134), INTC_IRQ(MTU2_TGI3D, 135), + INTC_IRQ(MTU2_TCI3V, 136), + + INTC_IRQ(MTU2_TGI4A, 140), INTC_IRQ(MTU2_TGI4B, 141), + INTC_IRQ(MTU2_TGI4C, 142), INTC_IRQ(MTU2_TGI4D, 143), + INTC_IRQ(MTU2_TCI4V, 144), + + INTC_IRQ(MTU2_TGI5U, 148), INTC_IRQ(MTU2_TGI5V, 149), + INTC_IRQ(MTU2_TGI5W, 150), + + INTC_IRQ(RTC_ARM, 152), INTC_IRQ(RTC_PRD, 153), + INTC_IRQ(RTC_CUP, 154), INTC_IRQ(WDT, 156), + + INTC_IRQ(IIC30_STPI, 157), INTC_IRQ(IIC30_NAKI, 158), + INTC_IRQ(IIC30_RXI, 159), INTC_IRQ(IIC30_TXI, 160), + INTC_IRQ(IIC30_TEI, 161), + + INTC_IRQ(IIC31_STPI, 164), INTC_IRQ(IIC31_NAKI, 165), + INTC_IRQ(IIC31_RXI, 166), INTC_IRQ(IIC31_TXI, 167), + INTC_IRQ(IIC31_TEI, 168), + + INTC_IRQ(IIC32_STPI, 170), INTC_IRQ(IIC32_NAKI, 171), + INTC_IRQ(IIC32_RXI, 172), INTC_IRQ(IIC32_TXI, 173), + INTC_IRQ(IIC32_TEI, 174), + + INTC_IRQ(DMAC0_DMINT0, 176), INTC_IRQ(DMAC1_DMINT1, 177), + INTC_IRQ(DMAC2_DMINT2, 178), INTC_IRQ(DMAC3_DMINT3, 179), + + INTC_IRQ(SCIF0_BRI, 180), INTC_IRQ(SCIF0_ERI, 181), + INTC_IRQ(SCIF0_RXI, 182), INTC_IRQ(SCIF0_TXI, 183), + INTC_IRQ(SCIF1_BRI, 184), INTC_IRQ(SCIF1_ERI, 185), + INTC_IRQ(SCIF1_RXI, 186), INTC_IRQ(SCIF1_TXI, 187), + INTC_IRQ(SCIF2_BRI, 188), INTC_IRQ(SCIF2_ERI, 189), + INTC_IRQ(SCIF2_RXI, 190), INTC_IRQ(SCIF2_TXI, 191), + INTC_IRQ(SCIF3_BRI, 192), INTC_IRQ(SCIF3_ERI, 193), + INTC_IRQ(SCIF3_RXI, 194), INTC_IRQ(SCIF3_TXI, 195), + INTC_IRQ(SCIF4_BRI, 196), INTC_IRQ(SCIF4_ERI, 197), + INTC_IRQ(SCIF4_RXI, 198), INTC_IRQ(SCIF4_TXI, 199), + INTC_IRQ(SCIF5_BRI, 200), INTC_IRQ(SCIF5_ERI, 201), + INTC_IRQ(SCIF5_RXI, 202), INTC_IRQ(SCIF5_TXI, 203), + INTC_IRQ(SCIF6_BRI, 204), INTC_IRQ(SCIF6_ERI, 205), + INTC_IRQ(SCIF6_RXI, 206), INTC_IRQ(SCIF6_TXI, 207), + INTC_IRQ(SCIF7_BRI, 208), INTC_IRQ(SCIF7_ERI, 209), + INTC_IRQ(SCIF7_RXI, 210), INTC_IRQ(SCIF7_TXI, 211), + + INTC_IRQ(DMAC0_DMINTA, 212), INTC_IRQ(DMAC4_DMINT4, 216), + INTC_IRQ(DMAC5_DMINT5, 217), INTC_IRQ(DMAC6_DMINT6, 218), + INTC_IRQ(DMAC7_DMINT7, 219), + + INTC_IRQ(RCAN0_ERS, 228), INTC_IRQ(RCAN0_OVR, 229), + INTC_IRQ(RCAN0_SLE, 230), + INTC_IRQ(RCAN0_RM0, 231), INTC_IRQ(RCAN0_RM1, 232), + + INTC_IRQ(RCAN1_ERS, 234), INTC_IRQ(RCAN1_OVR, 235), + INTC_IRQ(RCAN1_SLE, 236), + INTC_IRQ(RCAN1_RM0, 237), INTC_IRQ(RCAN1_RM1, 238), + + INTC_IRQ(SSI0_SSII, 244), INTC_IRQ(SSI1_SSII, 245), + + INTC_IRQ(TMR0_CMIA0, 246), INTC_IRQ(TMR0_CMIB0, 247), + INTC_IRQ(TMR0_OVI0, 248), + + INTC_IRQ(TMR1_CMIA1, 252), INTC_IRQ(TMR1_CMIB1, 253), + INTC_IRQ(TMR1_OVI1, 254), + +}; + +static struct intc_group groups[] __initdata = { + INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3, + PINT4, PINT5, PINT6, PINT7), + INTC_GROUP(MTU20_ABCD, MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D), + INTC_GROUP(MTU20_VEF, MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F), + + INTC_GROUP(MTU21_AB, MTU2_TGI1A, MTU2_TGI1B), + INTC_GROUP(MTU21_VU, MTU2_TCI1V, MTU2_TCI1U), + INTC_GROUP(MTU22_AB, MTU2_TGI2A, MTU2_TGI2B), + INTC_GROUP(MTU22_VU, MTU2_TCI2V, MTU2_TCI2U), + INTC_GROUP(MTU23_ABCD, MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D), + INTC_GROUP(MTU24_ABCD, MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D), + INTC_GROUP(MTU25_UVW, MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W), + INTC_GROUP(RTC, RTC_ARM, RTC_PRD, RTC_CUP ), + + INTC_GROUP(IIC30, IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI, + IIC30_TEI), + INTC_GROUP(IIC31, IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI, + IIC31_TEI), + INTC_GROUP(IIC32, IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI, + IIC32_TEI), + + INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI), + INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI), + INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI), + INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI), + INTC_GROUP(SCIF4, SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI), + INTC_GROUP(SCIF5, SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI), + INTC_GROUP(SCIF6, SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI), + INTC_GROUP(SCIF7, SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI), + + INTC_GROUP(RCAN0, RCAN0_ERS, RCAN0_OVR, RCAN0_RM0, RCAN0_RM1, + RCAN0_SLE), + INTC_GROUP(RCAN1, RCAN1_ERS, RCAN1_OVR, RCAN1_RM0, RCAN1_RM1, + RCAN1_SLE), + + INTC_GROUP(TMR0, TMR0_CMIA0, TMR0_CMIB0, TMR0_OVI0), + INTC_GROUP(TMR1, TMR1_CMIA1, TMR1_CMIB1, TMR1_OVI1), +}; + +static struct intc_prio_reg prio_registers[] __initdata = { + { 0xfffe9418, 0, 16, 4, /* IPR01 */ { IRQ0, IRQ1, IRQ2, IRQ3 } }, + { 0xfffe941a, 0, 16, 4, /* IPR02 */ { IRQ4, IRQ5, IRQ6, IRQ7 } }, + { 0xfffe9420, 0, 16, 4, /* IPR05 */ { PINT, 0, ADC_ADI, 0 } }, + { 0xfffe9800, 0, 16, 4, /* IPR06 */ { 0, MTU20_ABCD, MTU20_VEF, MTU21_AB } }, + { 0xfffe9802, 0, 16, 4, /* IPR07 */ { MTU21_VU, MTU22_AB, MTU22_VU, MTU23_ABCD } }, + { 0xfffe9804, 0, 16, 4, /* IPR08 */ { MTU2_TCI3V, MTU24_ABCD, MTU2_TCI4V, MTU25_UVW } }, + + { 0xfffe9806, 0, 16, 4, /* IPR09 */ { RTC, WDT, IIC30, 0 } }, + { 0xfffe9808, 0, 16, 4, /* IPR10 */ { IIC31, IIC32, DMAC0_DMINT0, DMAC1_DMINT1 } }, + { 0xfffe980a, 0, 16, 4, /* IPR11 */ { DMAC2_DMINT2, DMAC3_DMINT3, SCIF0 , SCIF1 } }, + { 0xfffe980c, 0, 16, 4, /* IPR12 */ { SCIF2, SCIF3, SCIF4, SCIF5 } }, + { 0xfffe980e, 0, 16, 4, /* IPR13 */ { SCIF6, SCIF7, DMAC0_DMINTA, DMAC4_DMINT4 } }, + { 0xfffe9810, 0, 16, 4, /* IPR14 */ { DMAC5_DMINT5, DMAC6_DMINT6, DMAC7_DMINT7, 0 } }, + { 0xfffe9812, 0, 16, 4, /* IPR15 */ { 0, RCAN0, RCAN1, 0 } }, + { 0xfffe9814, 0, 16, 4, /* IPR16 */ { SSI0_SSII, SSI1_SSII, TMR0, TMR1 } }, +}; + +static struct intc_mask_reg mask_registers[] __initdata = { + { 0xfffe9408, 0, 16, /* PINTER */ + { 0, 0, 0, 0, 0, 0, 0, 0, + PINT7, PINT6, PINT5, PINT4, PINT3, PINT2, PINT1, PINT0 } }, +}; + +static DECLARE_INTC_DESC(intc_desc, "sh7201", vectors, groups, + mask_registers, prio_registers, NULL); + +static struct plat_sci_port sci_platform_data[] = { + { + .mapbase = 0xfffe8000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 181, 182, 183, 180} + }, { + .mapbase = 0xfffe8800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 185, 186, 187, 184} + }, { + .mapbase = 0xfffe9000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 189, 186, 187, 188} + }, { + .mapbase = 0xfffe9800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 193, 194, 195, 192} + }, { + .mapbase = 0xfffea000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 196, 198, 199, 196} + }, { + .mapbase = 0xfffea800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 201, 202, 203, 200} + }, { + .mapbase = 0xfffeb000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 205, 206, 207, 204} + }, { + .mapbase = 0xfffeb800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 209, 210, 211, 208} + }, { + .flags = 0, + } +}; + +static struct platform_device sci_device = { + .name = "sh-sci", + .id = -1, + .dev = { + .platform_data = sci_platform_data, + }, +}; + +static struct resource rtc_resources[] = { + [0] = { + .start = 0xffff0800, + .end = 0xffff2000 + 0x58 - 1, + .flags = IORESOURCE_IO, + }, + [1] = { + /* Period IRQ */ + .start = 153, + .flags = IORESOURCE_IRQ, + }, + [2] = { + /* Carry IRQ */ + .start = 154, + .flags = IORESOURCE_IRQ, + }, + [3] = { + /* Alarm IRQ */ + .start = 152, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device rtc_device = { + .name = "sh-rtc", + .id = -1, + .num_resources = ARRAY_SIZE(rtc_resources), + .resource = rtc_resources, +}; + +static struct platform_device *sh7201_devices[] __initdata = { + &sci_device, + &rtc_device, +}; + +static int __init sh7201_devices_setup(void) +{ + return platform_add_devices(sh7201_devices, + ARRAY_SIZE(sh7201_devices)); +} +__initcall(sh7201_devices_setup); + +void __init plat_irq_setup(void) +{ + register_intc_controller(&intc_desc); +} diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index e7152cc6930e..534247508572 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -417,6 +417,7 @@ void __init setup_arch(char **cmdline_p) } static const char *cpu_name[] = { + [CPU_SH7201] = "SH7201", [CPU_SH7203] = "SH7203", [CPU_SH7263] = "SH7263", [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c index fe453c01f9c9..c3d237e1d566 100644 --- a/arch/sh/kernel/timers/timer-mtu2.c +++ b/arch/sh/kernel/timers/timer-mtu2.c @@ -34,7 +34,12 @@ #define MTU2_TIER_1 0xfffe4384 #define MTU2_TSR_1 0xfffe4385 #define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */ + +#if defined(CONFIG_CPU_SUBTYPE_SH7201) +#define MTU2_TGRA_1 0xfffe4388 +#else #define MTU2_TGRA_1 0xfffe438a +#endif #define STBCR3 0xfffe0408 -- cgit v1.2.1 From 0c0daec7ca4f6a67daeafc4343bb453a4a246dbd Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 1 Dec 2008 15:40:33 +0900 Subject: sh: propagate r_clk Make sure the 32 KHz r_clk rate gets propagated correctly. Without this fix the clocks for RTC, CMT, KEYSC and RWDT are stuck at 0 Hz. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 83b69196bc1a..0e174af21874 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -838,5 +838,7 @@ int __init arch_clk_init(void) clk_put(clk); } + clk_recalc_rate(&sh7722_r_clock); /* make sure rate gets propagated */ + return 0; } -- cgit v1.2.1 From 551ea2b40ecf75e0035406fe75ba995233737e76 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 4 Dec 2008 17:59:54 +0900 Subject: sh: sh7343 scif configuration update Fix interrupt values for the first sh7343 SCIF port and update the configuration to include the remaining 3 ones. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7343.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index 75b9c819e442..0623e377f488 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c @@ -117,7 +117,22 @@ static struct plat_sci_port sci_platform_data[] = { .mapbase = 0xffe00000, .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, - .irqs = { 80, 81, 83, 82 }, + .irqs = { 80, 80, 80, 80 }, + }, { + .mapbase = 0xffe10000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 81, 81, 81, 81 }, + }, { + .mapbase = 0xffe20000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 82, 82, 82, 82 }, + }, { + .mapbase = 0xffe30000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 83, 83, 83, 83 }, }, { .flags = 0, } @@ -165,7 +180,7 @@ enum { MMC_ERR, MMC_TRAN, MMC_FSTAT, MMC_FRDY, DMAC4, DMAC5, DMAC_DADERR, KEYSC, - SCIF, SCIF1, SCIF2, SCIF3, SCIF4, + SCIF, SCIF1, SCIF2, SCIF3, SIOF0, SIOF1, SIO, FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI, -- cgit v1.2.1 From 3e51762759db9e26c6c3e4e1010d80a50c62ca03 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 4 Dec 2008 22:45:03 +0900 Subject: sh: move the hp6xx pm code Move the not-so-generic pm code from arch/sh/kernel/pm.c to the platform directory together with the rest of the hp6xx pm code. This is done to let non-hp6xx platforms enable CONFIG_PM. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/Makefile_32 | 1 - arch/sh/kernel/Makefile_64 | 1 - arch/sh/kernel/pm.c | 88 ---------------------------------------------- 3 files changed, 90 deletions(-) delete mode 100644 arch/sh/kernel/pm.c (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index d9df9e567946..10a34c3ae647 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -25,7 +25,6 @@ obj-$(CONFIG_MODULES) += sh_ksyms_32.o module.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o -obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_IO_TRAPPED) += io_trapped.o obj-$(CONFIG_KPROBES) += kprobes.o diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64 index 4304b2593c2c..ae4afc090062 100644 --- a/arch/sh/kernel/Makefile_64 +++ b/arch/sh/kernel/Makefile_64 @@ -15,7 +15,6 @@ obj-$(CONFIG_MODULES) += sh_ksyms_64.o module.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o -obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_IO_TRAPPED) += io_trapped.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o diff --git a/arch/sh/kernel/pm.c b/arch/sh/kernel/pm.c deleted file mode 100644 index 10ab62c9aede..000000000000 --- a/arch/sh/kernel/pm.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Generic Power Management Routine - * - * Copyright (c) 2006 Andriy Skulysh - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - */ -#include -#include -#include -#include -#include -#include -#include - -#define INTR_OFFSET 0x600 - -#define STBCR 0xffffff82 -#define STBCR2 0xffffff88 - -#define STBCR_STBY 0x80 -#define STBCR_MSTP2 0x04 - -#define MCR 0xffffff68 -#define RTCNT 0xffffff70 - -#define MCR_RMODE 2 -#define MCR_RFSH 4 - -void pm_enter(void) -{ - u8 stbcr, csr; - u16 frqcr, mcr; - u32 vbr_new, vbr_old; - - set_bl_bit(); - - /* set wdt */ - csr = sh_wdt_read_csr(); - csr &= ~WTCSR_TME; - csr |= WTCSR_CKS_4096; - sh_wdt_write_csr(csr); - csr = sh_wdt_read_csr(); - sh_wdt_write_cnt(0); - - /* disable PLL1 */ - frqcr = ctrl_inw(FRQCR); - frqcr &= ~(FRQCR_PLLEN | FRQCR_PSTBY); - ctrl_outw(frqcr, FRQCR); - - /* enable standby */ - stbcr = ctrl_inb(STBCR); - ctrl_outb(stbcr | STBCR_STBY | STBCR_MSTP2, STBCR); - - /* set self-refresh */ - mcr = ctrl_inw(MCR); - ctrl_outw(mcr & ~MCR_RFSH, MCR); - - /* set interrupt handler */ - asm volatile("stc vbr, %0" : "=r" (vbr_old)); - vbr_new = get_zeroed_page(GFP_ATOMIC); - udelay(50); - memcpy((void*)(vbr_new + INTR_OFFSET), - &wakeup_start, &wakeup_end - &wakeup_start); - asm volatile("ldc %0, vbr" : : "r" (vbr_new)); - - ctrl_outw(0, RTCNT); - ctrl_outw(mcr | MCR_RFSH | MCR_RMODE, MCR); - - cpu_sleep(); - - asm volatile("ldc %0, vbr" : : "r" (vbr_old)); - - free_page(vbr_new); - - /* enable PLL1 */ - frqcr = ctrl_inw(FRQCR); - frqcr |= FRQCR_PSTBY; - ctrl_outw(frqcr, FRQCR); - udelay(50); - frqcr |= FRQCR_PLLEN; - ctrl_outw(frqcr, FRQCR); - - ctrl_outb(stbcr, STBCR); - - clear_bl_bit(); -} -- cgit v1.2.1 From b5cfeac990cc164a3d3422aab88ac5b138fa822d Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 8 Dec 2008 12:02:28 +0900 Subject: sh: Provide ftrace_make_call()/ftrace_make_nop(). Signed-off-by: Paul Mundt --- arch/sh/kernel/ftrace.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c index 6c193d56c2e7..4c3247477aa3 100644 --- a/arch/sh/kernel/ftrace.c +++ b/arch/sh/kernel/ftrace.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Matt Fleming + * Copyright (C) 2008 Paul Mundt * * Code for replacing ftrace calls with jumps. * @@ -100,6 +101,29 @@ int ftrace_update_ftrace_func(ftrace_func_t func) return ftrace_modify_code(ip + MCOUNT_INSN_OFFSET, old, new); } +int ftrace_make_nop(struct module *mod, + struct dyn_ftrace *rec, unsigned long addr) +{ + unsigned char *new, *old; + unsigned long ip = rec->ip; + + old = ftrace_call_replace(ip, addr); + new = ftrace_nop_replace(); + + return ftrace_modify_code(rec->ip, old, new); +} + +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) +{ + unsigned char *new, *old; + unsigned long ip = rec->ip; + + old = ftrace_nop_replace(); + new = ftrace_call_replace(ip, addr); + + return ftrace_modify_code(rec->ip, old, new); +} + int __init ftrace_dyn_arch_init(void *data) { /* The return code is retured via data */ -- cgit v1.2.1 From bd40e8132336fbc3f2857f24720e11b6c1c9ac26 Mon Sep 17 00:00:00 2001 From: Aoi Shinkai Date: Wed, 10 Dec 2008 13:30:28 +0900 Subject: sh: Delete unnecessary mov in the interrupt exception entry point. The INTEVT read at interrupt exception entry is uneccessary, as the read is deferred until we are ready to enter do_IRQ(). The kgdb nmi path still requires it, so move it there. Signed-off-by: Aoi Shinkai Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh3/entry.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index 3fe482dd05c1..f112faa219c3 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -376,9 +376,9 @@ tlb_miss: ! .balign 512,0,512 interrupt: - mov.l 2f, k2 mov.l 3f, k3 #if defined(CONFIG_KGDB_NMI) + mov.l 2f, k2 ! Debounce (filter nested NMI) mov.l @k2, k0 mov.l 5f, k1 @@ -390,6 +390,7 @@ interrupt: rte nop .align 2 +2: .long INTEVT 5: .long NMI_VEC 6: .long in_nmi 0: @@ -399,7 +400,6 @@ interrupt: .align 2 1: .long EXPEVT -2: .long INTEVT 3: .long ret_from_irq 4: .long ret_from_exception -- cgit v1.2.1 From 4d1f3bbec49a080cae753aaa44dc1fc7277b3e50 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 10 Dec 2008 17:16:09 +0900 Subject: sh: Kill off sh64's unused alloc/free_task_struct() definitions. These were left over from some time ago, sh64 never got around to defining __HAVE_ARCH_TASK_STRUCT_ALLOCATOR during the conversion, and it has no need to. Kill these off and use the generic versions instead. Signed-off-by: Paul Mundt --- arch/sh/kernel/process_64.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index 597cf02db3fc..e9bf2548d6d4 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c @@ -305,18 +305,6 @@ void show_regs(struct pt_regs * regs) } } -struct task_struct * alloc_task_struct(void) -{ - /* Get task descriptor pages */ - return (struct task_struct *) - __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)); -} - -void free_task_struct(struct task_struct *p) -{ - free_pages((unsigned long) p, get_order(THREAD_SIZE)); -} - /* * Create a kernel thread */ -- cgit v1.2.1 From a99d6fde69dd9c73ac0b4e42a77ed1ebc714e56a Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 10 Dec 2008 18:06:36 +0900 Subject: sh: Convert sh64 /proc/asids to debugfs and generic sh. This converts the sh64 /proc/asids entry to debugfs and enables it for all SH parts that have debugfs enabled. On MMU systems this can be used to determine which processes are using which ASIDs which in turn can be used for finer grained cache tag analysis. Signed-off-by: Paul Mundt --- arch/sh/kernel/process_64.c | 39 --------------------------------------- 1 file changed, 39 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index e9bf2548d6d4..a7e5f2e74bac 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -590,41 +589,3 @@ unsigned long get_wchan(struct task_struct *p) #endif return pc; } - -/* Provide a /proc/asids file that lists out the - ASIDs currently associated with the processes. (If the DM.PC register is - examined through the debug link, this shows ASID + PC. To make use of this, - the PID->ASID relationship needs to be known. This is primarily for - debugging.) - */ - -#if defined(CONFIG_SH64_PROC_ASIDS) -static int -asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void *data) -{ - int len=0; - struct task_struct *p; - read_lock(&tasklist_lock); - for_each_process(p) { - int pid = p->pid; - - if (!pid) - continue; - if (p->mm) - len += sprintf(buf+len, "%5d : %02lx\n", pid, - asid_cache(smp_processor_id())); - else - len += sprintf(buf+len, "%5d : (none)\n", pid); - } - read_unlock(&tasklist_lock); - *eof = 1; - return len; -} - -static int __init register_proc_asids(void) -{ - create_proc_read_entry("asids", 0, NULL, asids_proc_info, NULL); - return 0; -} -__initcall(register_proc_asids); -#endif -- cgit v1.2.1 From 6ac034375fe8b4341137657adf5e6ff0dcb5a99f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 10 Dec 2008 19:26:44 +0900 Subject: sh: Handle cases where setup{_rt,}_frame() fail on SH-5 signal delivery. Presently these cases are not handled properly due to the return value not being passed back. This needs to be correct to get proper behaviour out of things like the tracehook signal notifier, amongst others. Signed-off-by: Paul Mundt --- arch/sh/kernel/signal_64.c | 93 ++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 45 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index ce3e851dffcb..08828ddd97ff 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c @@ -2,7 +2,7 @@ * arch/sh/kernel/signal_64.c * * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt + * Copyright (C) 2003 - 2008 Paul Mundt * Copyright (C) 2004 Richard Curnow * * This file is subject to the terms and conditions of the GNU General Public @@ -43,7 +43,7 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -static void +static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs); @@ -80,21 +80,20 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, 0); - if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, &ka, oldset, regs); - - /* - * If a signal was successfully delivered, the saved sigmask - * is in its frame, and we can clear the TIF_RESTORE_SIGMASK - * flag. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - - tracehook_signal_handler(signr, &info, &ka, regs, 0); - return 1; + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* + * If a signal was successfully delivered, the + * saved sigmask is in its frame, and we can + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + tracehook_signal_handler(signr, &info, &ka, regs, 0); + return 1; + } } no_signal: @@ -504,8 +503,8 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) void sa_default_restorer(void); /* See comments below */ void sa_default_rt_restorer(void); /* See comments below */ -static void setup_frame(int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs *regs) +static int setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs) { struct sigframe __user *frame; int err = 0; @@ -596,23 +595,21 @@ static void setup_frame(int sig, struct k_sigaction *ka, set_fs(USER_DS); -#if DEBUG_SIG /* Broken %016Lx */ - printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", - signal, - current->comm, current->pid, frame, - regs->pc >> 32, regs->pc & 0xffffffff, - DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); -#endif + pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", + signal, current->comm, current->pid, frame, + regs->pc >> 32, regs->pc & 0xffffffff, + DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); - return; + return 0; give_sigsegv: force_sigsegv(sig, current); + return -EFAULT; } -static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs) +static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0; @@ -702,29 +699,28 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, set_fs(USER_DS); -#if DEBUG_SIG - /* Broken %016Lx */ - printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", - signal, - current->comm, current->pid, frame, - regs->pc >> 32, regs->pc & 0xffffffff, - DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); -#endif + pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", + signal, current->comm, current->pid, frame, + regs->pc >> 32, regs->pc & 0xffffffff, + DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); - return; + return 0; give_sigsegv: force_sigsegv(sig, current); + return -EFAULT; } /* * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) { + int ret; + /* Are we from a system call? */ if (regs->syscall_nr >= 0) { /* If so, check system call restarting.. */ @@ -748,16 +744,23 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(sig, ka, info, oldset, regs); + ret = setup_rt_frame(sig, ka, info, oldset, regs); else - setup_frame(sig, ka, oldset, regs); + ret = setup_frame(sig, ka, oldset, regs); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + + if (ret == 0) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + return ret; } asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) -- cgit v1.2.1 From 94e2fb3d3e1f4cb6bad2b13c572c4c99ad734a37 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 10 Dec 2008 19:46:18 +0900 Subject: sh: Provide asm/syscall.h for SH-5. This provides the asm/syscall.h implementation for sh64 parts. Signed-off-by: Paul Mundt --- arch/sh/kernel/signal_32.c | 1 - arch/sh/kernel/signal_64.c | 63 ++++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 31 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index 69d09c0b3498..77c21bde376a 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c @@ -533,7 +533,6 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, { int ret; - /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) ret = setup_rt_frame(sig, ka, info, oldset, regs); diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index 08828ddd97ff..b22fdfaaa191 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c @@ -47,6 +47,34 @@ static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs); +static inline void +handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) +{ + /* If we're not from a syscall, bail out */ + if (regs->syscall_nr < 0) + return; + + /* check for system call restart.. */ + switch (regs->regs[REG_RET]) { + case -ERESTART_RESTARTBLOCK: + case -ERESTARTNOHAND: + no_system_call_restart: + regs->regs[REG_RET] = -EINTR; + regs->sr |= 1; + break; + + case -ERESTARTSYS: + if (!(sa->sa_flags & SA_RESTART)) + goto no_system_call_restart; + /* fallthrough */ + case -ERESTARTNOINTR: + /* Decode syscall # */ + regs->regs[REG_RET] = regs->syscall_nr; + regs->pc -= 4; + break; + } +} + /* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by @@ -81,6 +109,9 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) signr = get_signal_to_deliver(&info, &ka, regs, 0); if (signr > 0) { + if (regs->sr & 1) + handle_syscall_restart(regs, &ka.sa); + /* Whee! Actually deliver the signal. */ if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { /* @@ -128,7 +159,6 @@ no_signal: /* * Atomically swap in the new signal mask, and wait for a signal. */ - asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r3, unsigned long r4, unsigned long r5, @@ -234,20 +264,16 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, return do_sigaltstack(uss, uoss, REF_REG_SP); } - /* * Do a signal return; undo the signal stack. */ - -struct sigframe -{ +struct sigframe { struct sigcontext sc; unsigned long extramask[_NSIG_WORDS-1]; long long retcode[2]; }; -struct rt_sigframe -{ +struct rt_sigframe { struct siginfo __user *pinfo; void *puc; struct siginfo info; @@ -449,7 +475,6 @@ badframe: /* * Set up a signal frame. */ - static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask) @@ -714,34 +739,12 @@ give_sigsegv: /* * OK, we're invoking a handler */ - static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) { int ret; - /* Are we from a system call? */ - if (regs->syscall_nr >= 0) { - /* If so, check system call restarting.. */ - switch (regs->regs[REG_RET]) { - case -ERESTART_RESTARTBLOCK: - case -ERESTARTNOHAND: - no_system_call_restart: - regs->regs[REG_RET] = -EINTR; - break; - - case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) - goto no_system_call_restart; - /* fallthrough */ - case -ERESTARTNOINTR: - /* Decode syscall # */ - regs->regs[REG_RET] = regs->syscall_nr; - regs->pc -= 4; - } - } - /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) ret = setup_rt_frame(sig, ka, info, oldset, regs); -- cgit v1.2.1 From dd76279b47dce2c0bd7c54997938ec4cb9f16884 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 10 Dec 2008 20:14:15 +0900 Subject: sh: Provide linux/regset.h interface for SH-5. Plugs in general and FPU regsets. Signed-off-by: Paul Mundt --- arch/sh/kernel/ptrace_64.c | 186 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 185 insertions(+), 1 deletion(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index e15b099c1f06..695097438f02 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c @@ -2,7 +2,7 @@ * arch/sh/kernel/ptrace_64.c * * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 - 2007 Paul Mundt + * Copyright (C) 2003 - 2008 Paul Mundt * * Started from SH3/4 version: * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -137,6 +139,165 @@ void user_disable_single_step(struct task_struct *child) regs->sr &= ~SR_SSTEP; } +static int genregs_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + const struct pt_regs *regs = task_pt_regs(target); + int ret; + + /* PC, SR, SYSCALL */ + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, + ®s->pc, + 0, 3 * sizeof(unsigned long long)); + + /* R1 -> R63 */ + if (!ret) + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, + regs->regs, + offsetof(struct pt_regs, regs[0]), + 63 * sizeof(unsigned long long)); + /* TR0 -> TR7 */ + if (!ret) + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, + regs->tregs, + offsetof(struct pt_regs, tregs[0]), + 8 * sizeof(unsigned long long)); + + if (!ret) + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, + sizeof(struct pt_regs), -1); + + return ret; +} + +static int genregs_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + struct pt_regs *regs = task_pt_regs(target); + int ret; + + /* PC, SR, SYSCALL */ + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + ®s->pc, + 0, 3 * sizeof(unsigned long long)); + + /* R1 -> R63 */ + if (!ret && count > 0) + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + regs->regs, + offsetof(struct pt_regs, regs[0]), + 63 * sizeof(unsigned long long)); + + /* TR0 -> TR7 */ + if (!ret && count > 0) + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + regs->tregs, + offsetof(struct pt_regs, tregs[0]), + 8 * sizeof(unsigned long long)); + + if (!ret) + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, + sizeof(struct pt_regs), -1); + + return ret; +} + +#ifdef CONFIG_SH_FPU +int fpregs_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + int ret; + + ret = init_fpu(target); + if (ret) + return ret; + + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, + &target->thread.fpu.hard, 0, -1); +} + +static int fpregs_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + int ret; + + ret = init_fpu(target); + if (ret) + return ret; + + set_stopped_child_used_math(target); + + return user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &target->thread.fpu.hard, 0, -1); +} + +static int fpregs_active(struct task_struct *target, + const struct user_regset *regset) +{ + return tsk_used_math(target) ? regset->n : 0; +} +#endif + +/* + * These are our native regset flavours. + */ +enum sh_regset { + REGSET_GENERAL, +#ifdef CONFIG_SH_FPU + REGSET_FPU, +#endif +}; + +static const struct user_regset sh_regsets[] = { + /* + * Format is: + * PC, SR, SYSCALL, + * R1 --> R63, + * TR0 --> TR7, + */ + [REGSET_GENERAL] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(long long), + .align = sizeof(long long), + .get = genregs_get, + .set = genregs_set, + }, + +#ifdef CONFIG_SH_FPU + [REGSET_FPU] = { + .core_note_type = NT_PRFPREG, + .n = sizeof(struct user_fpu_struct) / + sizeof(long long), + .size = sizeof(long long), + .align = sizeof(long long), + .get = fpregs_get, + .set = fpregs_set, + .active = fpregs_active, + }, +#endif +}; + +static const struct user_regset_view user_sh64_native_view = { + .name = "sh64", + .e_machine = EM_SH, + .regsets = sh_regsets, + .n = ARRAY_SIZE(sh_regsets), +}; + +const struct user_regset_view *task_user_regset_view(struct task_struct *task) +{ + return &user_sh64_native_view; +} + long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret; @@ -195,10 +356,33 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } break; + case PTRACE_GETREGS: + return copy_regset_to_user(child, &user_sh64_native_view, + REGSET_GENERAL, + 0, sizeof(struct pt_regs), + (void __user *)data); + case PTRACE_SETREGS: + return copy_regset_from_user(child, &user_sh64_native_view, + REGSET_GENERAL, + 0, sizeof(struct pt_regs), + (const void __user *)data); +#ifdef CONFIG_SH_FPU + case PTRACE_GETFPREGS: + return copy_regset_to_user(child, &user_sh64_native_view, + REGSET_FPU, + 0, sizeof(struct user_fpu_struct), + (void __user *)data); + case PTRACE_SETFPREGS: + return copy_regset_from_user(child, &user_sh64_native_view, + REGSET_FPU, + 0, sizeof(struct user_fpu_struct), + (const void __user *)data); +#endif default: ret = ptrace_request(child, request, addr, data); break; } + return ret; } -- cgit v1.2.1 From ab6e570ba33dbee18c2520d386e0f367a9b573c3 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 11 Dec 2008 18:46:46 +0900 Subject: sh: Generic kgdb stub support. This migrates from the old bitrotted kgdb stub implementation and moves to the generic stub. In the process support for SH-2/SH-2A is also added, which the old stub never provided. Signed-off-by: Paul Mundt --- arch/sh/kernel/Makefile_32 | 2 +- arch/sh/kernel/cpu/sh3/entry.S | 10 +- arch/sh/kernel/cpu/sh3/ex.S | 2 +- arch/sh/kernel/debugtraps.S | 13 +- arch/sh/kernel/entry-common.S | 10 +- arch/sh/kernel/kgdb.c | 285 +++++++++++ arch/sh/kernel/kgdb_jmp.S | 33 -- arch/sh/kernel/kgdb_stub.c | 1052 ---------------------------------------- arch/sh/kernel/time_32.c | 7 - arch/sh/kernel/traps_32.c | 14 - 10 files changed, 306 insertions(+), 1122 deletions(-) create mode 100644 arch/sh/kernel/kgdb.c delete mode 100644 arch/sh/kernel/kgdb_jmp.S delete mode 100644 arch/sh/kernel/kgdb_stub.c (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index 10a34c3ae647..df25304ad780 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -19,7 +19,7 @@ obj-$(CONFIG_VSYSCALL) += vsyscall/ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_CF_ENABLER) += cf-enabler.o obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o -obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o +obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o obj-$(CONFIG_MODULES) += sh_ksyms_32.o module.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index f112faa219c3..b4106d0c68ec 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -52,7 +52,7 @@ * syscall # * */ -#if defined(CONFIG_KGDB_NMI) +#if defined(CONFIG_KGDB) NMI_VEC = 0x1c0 ! Must catch early for debounce #endif @@ -307,7 +307,7 @@ skip_restore: 6: or k0, k2 ! Set the IMASK-bits ldc k2, ssr ! -#if defined(CONFIG_KGDB_NMI) +#if defined(CONFIG_KGDB) ! Clear in_nmi mov.l 6f, k0 mov #0, k1 @@ -320,7 +320,7 @@ skip_restore: .align 2 5: .long 0x00001000 ! DSP -#ifdef CONFIG_KGDB_NMI +#ifdef CONFIG_KGDB 6: .long in_nmi #endif 7: .long 0x30000000 @@ -377,7 +377,7 @@ tlb_miss: .balign 512,0,512 interrupt: mov.l 3f, k3 -#if defined(CONFIG_KGDB_NMI) +#if defined(CONFIG_KGDB) mov.l 2f, k2 ! Debounce (filter nested NMI) mov.l @k2, k0 @@ -394,7 +394,7 @@ interrupt: 5: .long NMI_VEC 6: .long in_nmi 0: -#endif /* defined(CONFIG_KGDB_NMI) */ +#endif /* defined(CONFIG_KGDB) */ bra handle_exception mov #-1, k2 ! interrupt exception marker diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S index dac429726899..e5a0de39a2db 100644 --- a/arch/sh/kernel/cpu/sh3/ex.S +++ b/arch/sh/kernel/cpu/sh3/ex.S @@ -26,7 +26,7 @@ #define fpu_error_trap_handler exception_error #endif -#if !defined(CONFIG_KGDB_NMI) +#if !defined(CONFIG_KGDB) #define kgdb_handle_exception exception_error #endif diff --git a/arch/sh/kernel/debugtraps.S b/arch/sh/kernel/debugtraps.S index 13b66746410a..591741383ee6 100644 --- a/arch/sh/kernel/debugtraps.S +++ b/arch/sh/kernel/debugtraps.S @@ -3,7 +3,7 @@ * * Debug trap jump tables for SuperH * - * Copyright (C) 2006 Paul Mundt + * Copyright (C) 2006 - 2008 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -12,12 +12,13 @@ #include #include -#if !defined(CONFIG_SH_KGDB) -#define kgdb_handle_exception debug_trap_handler +#if !defined(CONFIG_KGDB) +#define breakpoint_trap_handler debug_trap_handler +#define singlestep_trap_handler debug_trap_handler #endif #if !defined(CONFIG_SH_STANDARD_BIOS) -#define sh_bios_handler debug_trap_handler +#define sh_bios_handler debug_trap_handler #endif .data @@ -35,7 +36,7 @@ ENTRY(debug_trap_table) .long debug_trap_handler /* 0x39 */ .long debug_trap_handler /* 0x3a */ .long debug_trap_handler /* 0x3b */ - .long kgdb_handle_exception /* 0x3c */ - .long debug_trap_handler /* 0x3d */ + .long breakpoint_trap_handler /* 0x3c */ + .long singlestep_trap_handler /* 0x3d */ .long bug_trap_handler /* 0x3e */ .long sh_bios_handler /* 0x3f */ diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index efbb4268875e..d62359cfbbe2 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -308,15 +308,19 @@ ENTRY(system_call) mov.l 1f, r9 mov.l @r9, r8 ! Read from TRA (Trap Address) Register #endif + + mov #OFF_TRA, r10 + add r15, r10 + mov.l r8, @r10 ! set TRA value to tra + /* * Check the trap type */ mov #((0x20 << 2) - 1), r9 cmp/hi r9, r8 bt/s debug_trap ! it's a debug trap.. - mov #OFF_TRA, r9 - add r15, r9 - mov.l r8, @r9 ! set TRA value to tra + nop + #ifdef CONFIG_TRACE_IRQFLAGS mov.l 5f, r10 jsr @r10 diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c new file mode 100644 index 000000000000..7c747e7d71b8 --- /dev/null +++ b/arch/sh/kernel/kgdb.c @@ -0,0 +1,285 @@ +/* + * SuperH KGDB support + * + * Copyright (C) 2008 Paul Mundt + * + * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +char in_nmi = 0; /* Set during NMI to prevent re-entry */ + +/* Macros for single step instruction identification */ +#define OPCODE_BT(op) (((op) & 0xff00) == 0x8900) +#define OPCODE_BF(op) (((op) & 0xff00) == 0x8b00) +#define OPCODE_BTF_DISP(op) (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \ + (((op) & 0x7f ) << 1)) +#define OPCODE_BFS(op) (((op) & 0xff00) == 0x8f00) +#define OPCODE_BTS(op) (((op) & 0xff00) == 0x8d00) +#define OPCODE_BRA(op) (((op) & 0xf000) == 0xa000) +#define OPCODE_BRA_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ + (((op) & 0x7ff) << 1)) +#define OPCODE_BRAF(op) (((op) & 0xf0ff) == 0x0023) +#define OPCODE_BRAF_REG(op) (((op) & 0x0f00) >> 8) +#define OPCODE_BSR(op) (((op) & 0xf000) == 0xb000) +#define OPCODE_BSR_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ + (((op) & 0x7ff) << 1)) +#define OPCODE_BSRF(op) (((op) & 0xf0ff) == 0x0003) +#define OPCODE_BSRF_REG(op) (((op) >> 8) & 0xf) +#define OPCODE_JMP(op) (((op) & 0xf0ff) == 0x402b) +#define OPCODE_JMP_REG(op) (((op) >> 8) & 0xf) +#define OPCODE_JSR(op) (((op) & 0xf0ff) == 0x400b) +#define OPCODE_JSR_REG(op) (((op) >> 8) & 0xf) +#define OPCODE_RTS(op) ((op) == 0xb) +#define OPCODE_RTE(op) ((op) == 0x2b) + +#define SR_T_BIT_MASK 0x1 +#define STEP_OPCODE 0xc33d + +/* Calculate the new address for after a step */ +static short *get_step_address(struct pt_regs *linux_regs) +{ + opcode_t op = __raw_readw(linux_regs->pc); + long addr; + + /* BT */ + if (OPCODE_BT(op)) { + if (linux_regs->sr & SR_T_BIT_MASK) + addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); + else + addr = linux_regs->pc + 2; + } + + /* BTS */ + else if (OPCODE_BTS(op)) { + if (linux_regs->sr & SR_T_BIT_MASK) + addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); + else + addr = linux_regs->pc + 4; /* Not in delay slot */ + } + + /* BF */ + else if (OPCODE_BF(op)) { + if (!(linux_regs->sr & SR_T_BIT_MASK)) + addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); + else + addr = linux_regs->pc + 2; + } + + /* BFS */ + else if (OPCODE_BFS(op)) { + if (!(linux_regs->sr & SR_T_BIT_MASK)) + addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); + else + addr = linux_regs->pc + 4; /* Not in delay slot */ + } + + /* BRA */ + else if (OPCODE_BRA(op)) + addr = linux_regs->pc + 4 + OPCODE_BRA_DISP(op); + + /* BRAF */ + else if (OPCODE_BRAF(op)) + addr = linux_regs->pc + 4 + + linux_regs->regs[OPCODE_BRAF_REG(op)]; + + /* BSR */ + else if (OPCODE_BSR(op)) + addr = linux_regs->pc + 4 + OPCODE_BSR_DISP(op); + + /* BSRF */ + else if (OPCODE_BSRF(op)) + addr = linux_regs->pc + 4 + + linux_regs->regs[OPCODE_BSRF_REG(op)]; + + /* JMP */ + else if (OPCODE_JMP(op)) + addr = linux_regs->regs[OPCODE_JMP_REG(op)]; + + /* JSR */ + else if (OPCODE_JSR(op)) + addr = linux_regs->regs[OPCODE_JSR_REG(op)]; + + /* RTS */ + else if (OPCODE_RTS(op)) + addr = linux_regs->pr; + + /* RTE */ + else if (OPCODE_RTE(op)) + addr = linux_regs->regs[15]; + + /* Other */ + else + addr = linux_regs->pc + instruction_size(op); + + flush_icache_range(addr, addr + instruction_size(op)); + return (short *)addr; +} + +/* + * Replace the instruction immediately after the current instruction + * (i.e. next in the expected flow of control) with a trap instruction, + * so that returning will cause only a single instruction to be executed. + * Note that this model is slightly broken for instructions with delay + * slots (e.g. B[TF]S, BSR, BRA etc), where both the branch and the + * instruction in the delay slot will be executed. + */ + +static unsigned long stepped_address; +static opcode_t stepped_opcode; + +static void do_single_step(struct pt_regs *linux_regs) +{ + /* Determine where the target instruction will send us to */ + unsigned short *addr = get_step_address(linux_regs); + + stepped_address = (int)addr; + + /* Replace it */ + stepped_opcode = __raw_readw((long)addr); + *addr = STEP_OPCODE; + + /* Flush and return */ + flush_icache_range((long)addr, (long)addr + + instruction_size(stepped_opcode)); +} + +/* Undo a single step */ +static void undo_single_step(struct pt_regs *linux_regs) +{ + /* If we have stepped, put back the old instruction */ + /* Use stepped_address in case we stopped elsewhere */ + if (stepped_opcode != 0) { + __raw_writew(stepped_opcode, stepped_address); + flush_icache_range(stepped_address, stepped_address + 2); + } + + stepped_opcode = 0; +} + +void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) +{ + int i; + + for (i = 0; i < 16; i++) + gdb_regs[GDB_R0 + i] = regs->regs[i]; + + gdb_regs[GDB_PC] = regs->pc; + gdb_regs[GDB_PR] = regs->pr; + gdb_regs[GDB_SR] = regs->sr; + gdb_regs[GDB_GBR] = regs->gbr; + gdb_regs[GDB_MACH] = regs->mach; + gdb_regs[GDB_MACL] = regs->macl; + + __asm__ __volatile__ ("stc vbr, %0" : "=r" (gdb_regs[GDB_VBR])); +} + +void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) +{ + int i; + + for (i = 0; i < 16; i++) + regs->regs[GDB_R0 + i] = gdb_regs[GDB_R0 + i]; + + regs->pc = gdb_regs[GDB_PC]; + regs->pr = gdb_regs[GDB_PR]; + regs->sr = gdb_regs[GDB_SR]; + regs->gbr = gdb_regs[GDB_GBR]; + regs->mach = gdb_regs[GDB_MACH]; + regs->macl = gdb_regs[GDB_MACL]; + + __asm__ __volatile__ ("ldc %0, vbr" : : "r" (gdb_regs[GDB_VBR])); +} + +void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) +{ + gdb_regs[GDB_R15] = p->thread.sp; + gdb_regs[GDB_PC] = p->thread.pc; +} + +int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, + char *remcomInBuffer, char *remcomOutBuffer, + struct pt_regs *linux_regs) +{ + unsigned long addr; + char *ptr; + + /* Undo any stepping we may have done */ + undo_single_step(linux_regs); + + switch (remcomInBuffer[0]) { + case 'c': + case 's': + /* try to read optional parameter, pc unchanged if no parm */ + ptr = &remcomInBuffer[1]; + if (kgdb_hex2long(&ptr, &addr)) + linux_regs->pc = addr; + case 'D': + case 'k': + atomic_set(&kgdb_cpu_doing_single_step, -1); + + if (remcomInBuffer[0] == 's') { + do_single_step(linux_regs); + kgdb_single_step = 1; + + atomic_set(&kgdb_cpu_doing_single_step, + raw_smp_processor_id()); + } + + return 0; + } + + /* this means that we do not want to exit from the handler: */ + return -1; +} + +/* + * The primary entry points for the kgdb debug trap table entries. + */ +BUILD_TRAP_HANDLER(singlestep) +{ + unsigned long flags; + TRAP_HANDLER_DECL; + + local_irq_save(flags); + regs->pc -= instruction_size(__raw_readw(regs->pc - 4)); + kgdb_handle_exception(vec >> 2, SIGTRAP, 0, regs); + local_irq_restore(flags); +} + + +BUILD_TRAP_HANDLER(breakpoint) +{ + unsigned long flags; + TRAP_HANDLER_DECL; + + local_irq_save(flags); + kgdb_handle_exception(vec >> 2, SIGTRAP, 0, regs); + local_irq_restore(flags); +} + +int kgdb_arch_init(void) +{ + return 0; +} + +void kgdb_arch_exit(void) +{ +} + +struct kgdb_arch arch_kgdb_ops = { + /* Breakpoint instruction: trapa #0x3c */ +#ifdef CONFIG_CPU_LITTLE_ENDIAN + .gdb_bpt_instr = { 0x3c, 0xc3 }, +#else + .gdb_bpt_instr = { 0xc3, 0x3c }, +#endif +}; diff --git a/arch/sh/kernel/kgdb_jmp.S b/arch/sh/kernel/kgdb_jmp.S deleted file mode 100644 index 339bb1d7ff0b..000000000000 --- a/arch/sh/kernel/kgdb_jmp.S +++ /dev/null @@ -1,33 +0,0 @@ -#include - -ENTRY(setjmp) - add #(9*4), r4 - sts.l pr, @-r4 - mov.l r15, @-r4 - mov.l r14, @-r4 - mov.l r13, @-r4 - mov.l r12, @-r4 - mov.l r11, @-r4 - mov.l r10, @-r4 - mov.l r9, @-r4 - mov.l r8, @-r4 - rts - mov #0, r0 - -ENTRY(longjmp) - mov.l @r4+, r8 - mov.l @r4+, r9 - mov.l @r4+, r10 - mov.l @r4+, r11 - mov.l @r4+, r12 - mov.l @r4+, r13 - mov.l @r4+, r14 - mov.l @r4+, r15 - lds.l @r4+, pr - mov r5, r0 - tst r0, r0 - bf 1f - mov #1, r0 ! in case val==0 -1: rts - nop - diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c deleted file mode 100644 index bf8ac4c71640..000000000000 --- a/arch/sh/kernel/kgdb_stub.c +++ /dev/null @@ -1,1052 +0,0 @@ -/* - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Contains extracts from code by Glenn Engel, Jim Kingdon, - * David Grothe , Tigran Aivazian , - * Amit S. Kale , William Gatliff , - * Ben Lee, Steve Chamberlain and Benoit Miller . - * - * This version by Henry Bell - * Minor modifications by Jeremy Siegel - * - * Contains low-level support for remote debug using GDB. - * - * To enable debugger support, two things need to happen. A call to - * set_debug_traps() is necessary in order to allow any breakpoints - * or error conditions to be properly intercepted and reported to gdb. - * A breakpoint also needs to be generated to begin communication. This - * is most easily accomplished by a call to breakpoint() which does - * a trapa if the initialisation phase has been successfully completed. - * - * In this case, set_debug_traps() is not used to "take over" exceptions; - * other kernel code is modified instead to enter the kgdb functions here - * when appropriate (see entry.S for breakpoint traps and NMI interrupts, - * see traps.c for kernel error exceptions). - * - * The following gdb commands are supported: - * - * Command Function Return value - * - * g return the value of the CPU registers hex data or ENN - * G set the value of the CPU registers OK or ENN - * - * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN - * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN - * XAA..AA,LLLL: Same, but data is binary (not hex) OK or ENN - * - * c Resume at current address SNN ( signal NN) - * cAA..AA Continue at address AA..AA SNN - * CNN; Resume at current address with signal SNN - * CNN;AA..AA Resume at address AA..AA with signal SNN - * - * s Step one instruction SNN - * sAA..AA Step one instruction from AA..AA SNN - * SNN; Step one instruction with signal SNN - * SNNAA..AA Step one instruction from AA..AA w/NN SNN - * - * k kill (Detach GDB) - * - * d Toggle debug flag - * D Detach GDB - * - * Hct Set thread t for operations, OK or ENN - * c = 'c' (step, cont), c = 'g' (other - * operations) - * - * qC Query current thread ID QCpid - * qfThreadInfo Get list of current threads (first) m - * qsThreadInfo " " " " " (subsequent) - * qOffsets Get section offsets Text=x;Data=y;Bss=z - * - * TXX Find if thread XX is alive OK or ENN - * ? What was the last sigval ? SNN (signal NN) - * O Output to GDB console - * - * Remote communication protocol. - * - * A debug packet whose contents are is encapsulated for - * transmission in the form: - * - * $ # CSUM1 CSUM2 - * - * must be ASCII alphanumeric and cannot include characters - * '$' or '#'. If starts with two characters followed by - * ':', then the existing stubs interpret this as a sequence number. - * - * CSUM1 and CSUM2 are ascii hex representation of an 8-bit - * checksum of , the most significant nibble is sent first. - * the hex digits 0-9,a-f are used. - * - * Receiver responds with: - * - * + - if CSUM is correct and ready for next packet - * - - if CSUM is incorrect - * - * Responses can be run-length encoded to save space. A '*' means that - * the next character is an ASCII encoding giving a repeat count which - * stands for that many repetitions of the character preceding the '*'. - * The encoding is n+29, yielding a printable character where n >=3 - * (which is where RLE starts to win). Don't use an n > 126. - * - * So "0* " means the same as "0000". - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Function pointers for linkage */ -kgdb_debug_hook_t *kgdb_debug_hook; -kgdb_bus_error_hook_t *kgdb_bus_err_hook; - -int (*kgdb_getchar)(void); -EXPORT_SYMBOL_GPL(kgdb_getchar); -void (*kgdb_putchar)(int); -EXPORT_SYMBOL_GPL(kgdb_putchar); - -static void put_debug_char(int c) -{ - if (!kgdb_putchar) - return; - (*kgdb_putchar)(c); -} -static int get_debug_char(void) -{ - if (!kgdb_getchar) - return -1; - return (*kgdb_getchar)(); -} - -/* Num chars in in/out bound buffers, register packets need NUMREGBYTES * 2 */ -#define BUFMAX 1024 -#define NUMREGBYTES (MAXREG*4) -#define OUTBUFMAX (NUMREGBYTES*2+512) - -enum { - R0 = 0, R1, R2, R3, R4, R5, R6, R7, - R8, R9, R10, R11, R12, R13, R14, R15, - PC, PR, GBR, VBR, MACH, MACL, SR, - /* */ - MAXREG -}; - -static unsigned int registers[MAXREG]; -struct kgdb_regs trap_registers; - -char kgdb_in_gdb_mode; -char in_nmi; /* Set during NMI to prevent reentry */ -int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */ - -/* Default values for SCI (can override via kernel args in setup.c) */ -#ifndef CONFIG_KGDB_DEFPORT -#define CONFIG_KGDB_DEFPORT 1 -#endif - -#ifndef CONFIG_KGDB_DEFBAUD -#define CONFIG_KGDB_DEFBAUD 115200 -#endif - -#if defined(CONFIG_KGDB_DEFPARITY_E) -#define CONFIG_KGDB_DEFPARITY 'E' -#elif defined(CONFIG_KGDB_DEFPARITY_O) -#define CONFIG_KGDB_DEFPARITY 'O' -#else /* CONFIG_KGDB_DEFPARITY_N */ -#define CONFIG_KGDB_DEFPARITY 'N' -#endif - -#ifdef CONFIG_KGDB_DEFBITS_7 -#define CONFIG_KGDB_DEFBITS '7' -#else /* CONFIG_KGDB_DEFBITS_8 */ -#define CONFIG_KGDB_DEFBITS '8' -#endif - -/* SCI/UART settings, used in kgdb_console_setup() */ -int kgdb_portnum = CONFIG_KGDB_DEFPORT; -EXPORT_SYMBOL_GPL(kgdb_portnum); -int kgdb_baud = CONFIG_KGDB_DEFBAUD; -EXPORT_SYMBOL_GPL(kgdb_baud); -char kgdb_parity = CONFIG_KGDB_DEFPARITY; -EXPORT_SYMBOL_GPL(kgdb_parity); -char kgdb_bits = CONFIG_KGDB_DEFBITS; -EXPORT_SYMBOL_GPL(kgdb_bits); - -/* Jump buffer for setjmp/longjmp */ -static jmp_buf rem_com_env; - -/* TRA differs sh3/4 */ -#if defined(CONFIG_CPU_SH3) -#define TRA 0xffffffd0 -#elif defined(CONFIG_CPU_SH4) -#define TRA 0xff000020 -#endif - -/* Macros for single step instruction identification */ -#define OPCODE_BT(op) (((op) & 0xff00) == 0x8900) -#define OPCODE_BF(op) (((op) & 0xff00) == 0x8b00) -#define OPCODE_BTF_DISP(op) (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \ - (((op) & 0x7f ) << 1)) -#define OPCODE_BFS(op) (((op) & 0xff00) == 0x8f00) -#define OPCODE_BTS(op) (((op) & 0xff00) == 0x8d00) -#define OPCODE_BRA(op) (((op) & 0xf000) == 0xa000) -#define OPCODE_BRA_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ - (((op) & 0x7ff) << 1)) -#define OPCODE_BRAF(op) (((op) & 0xf0ff) == 0x0023) -#define OPCODE_BRAF_REG(op) (((op) & 0x0f00) >> 8) -#define OPCODE_BSR(op) (((op) & 0xf000) == 0xb000) -#define OPCODE_BSR_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ - (((op) & 0x7ff) << 1)) -#define OPCODE_BSRF(op) (((op) & 0xf0ff) == 0x0003) -#define OPCODE_BSRF_REG(op) (((op) >> 8) & 0xf) -#define OPCODE_JMP(op) (((op) & 0xf0ff) == 0x402b) -#define OPCODE_JMP_REG(op) (((op) >> 8) & 0xf) -#define OPCODE_JSR(op) (((op) & 0xf0ff) == 0x400b) -#define OPCODE_JSR_REG(op) (((op) >> 8) & 0xf) -#define OPCODE_RTS(op) ((op) == 0xb) -#define OPCODE_RTE(op) ((op) == 0x2b) - -#define SR_T_BIT_MASK 0x1 -#define STEP_OPCODE 0xc320 -#define BIOS_CALL_TRAP 0x3f - -/* Exception codes as per SH-4 core manual */ -#define ADDRESS_ERROR_LOAD_VEC 7 -#define ADDRESS_ERROR_STORE_VEC 8 -#define TRAP_VEC 11 -#define INVALID_INSN_VEC 12 -#define INVALID_SLOT_VEC 13 -#define NMI_VEC 14 -#define USER_BREAK_VEC 15 -#define SERIAL_BREAK_VEC 58 - -/* Misc static */ -static int stepped_address; -static short stepped_opcode; -static char in_buffer[BUFMAX]; -static char out_buffer[OUTBUFMAX]; - -static void kgdb_to_gdb(const char *s); - -/* Convert ch to hex */ -static int hex(const char ch) -{ - if ((ch >= 'a') && (ch <= 'f')) - return (ch - 'a' + 10); - if ((ch >= '0') && (ch <= '9')) - return (ch - '0'); - if ((ch >= 'A') && (ch <= 'F')) - return (ch - 'A' + 10); - return (-1); -} - -/* Convert the memory pointed to by mem into hex, placing result in buf. - Returns a pointer to the last char put in buf (null) */ -static char *mem_to_hex(const char *mem, char *buf, const int count) -{ - int i; - int ch; - unsigned short s_val; - unsigned long l_val; - - /* Check for 16 or 32 */ - if (count == 2 && ((long) mem & 1) == 0) { - s_val = *(unsigned short *) mem; - mem = (char *) &s_val; - } else if (count == 4 && ((long) mem & 3) == 0) { - l_val = *(unsigned long *) mem; - mem = (char *) &l_val; - } - for (i = 0; i < count; i++) { - ch = *mem++; - buf = pack_hex_byte(buf, ch); - } - *buf = 0; - return (buf); -} - -/* Convert the hex array pointed to by buf into binary, to be placed in mem. - Return a pointer to the character after the last byte written */ -static char *hex_to_mem(const char *buf, char *mem, const int count) -{ - int i; - unsigned char ch; - - for (i = 0; i < count; i++) { - ch = hex(*buf++) << 4; - ch = ch + hex(*buf++); - *mem++ = ch; - } - return (mem); -} - -/* While finding valid hex chars, convert to an integer, then return it */ -static int hex_to_int(char **ptr, int *int_value) -{ - int num_chars = 0; - int hex_value; - - *int_value = 0; - - while (**ptr) { - hex_value = hex(**ptr); - if (hex_value >= 0) { - *int_value = (*int_value << 4) | hex_value; - num_chars++; - } else - break; - (*ptr)++; - } - return num_chars; -} - -/* Copy the binary array pointed to by buf into mem. Fix $, #, - and 0x7d escaped with 0x7d. Return a pointer to the character - after the last byte written. */ -static char *ebin_to_mem(const char *buf, char *mem, int count) -{ - for (; count > 0; count--, buf++) { - if (*buf == 0x7d) - *mem++ = *(++buf) ^ 0x20; - else - *mem++ = *buf; - } - return mem; -} - -/* Scan for the start char '$', read the packet and check the checksum */ -static void get_packet(char *buffer, int buflen) -{ - unsigned char checksum; - unsigned char xmitcsum; - int i; - int count; - char ch; - - do { - /* Ignore everything until the start character */ - while ((ch = get_debug_char()) != '$'); - - checksum = 0; - xmitcsum = -1; - count = 0; - - /* Now, read until a # or end of buffer is found */ - while (count < (buflen - 1)) { - ch = get_debug_char(); - - if (ch == '#') - break; - - checksum = checksum + ch; - buffer[count] = ch; - count = count + 1; - } - - buffer[count] = 0; - - /* Continue to read checksum following # */ - if (ch == '#') { - xmitcsum = hex(get_debug_char()) << 4; - xmitcsum += hex(get_debug_char()); - - /* Checksum */ - if (checksum != xmitcsum) - put_debug_char('-'); /* Failed checksum */ - else { - /* Ack successful transfer */ - put_debug_char('+'); - - /* If a sequence char is present, reply - the sequence ID */ - if (buffer[2] == ':') { - put_debug_char(buffer[0]); - put_debug_char(buffer[1]); - - /* Remove sequence chars from buffer */ - count = strlen(buffer); - for (i = 3; i <= count; i++) - buffer[i - 3] = buffer[i]; - } - } - } - } - while (checksum != xmitcsum); /* Keep trying while we fail */ -} - -/* Send the packet in the buffer with run-length encoding */ -static void put_packet(char *buffer) -{ - int checksum; - char *src; - int runlen; - int encode; - - do { - src = buffer; - put_debug_char('$'); - checksum = 0; - - /* Continue while we still have chars left */ - while (*src) { - /* Check for runs up to 99 chars long */ - for (runlen = 1; runlen < 99; runlen++) { - if (src[0] != src[runlen]) - break; - } - - if (runlen > 3) { - /* Got a useful amount, send encoding */ - encode = runlen + ' ' - 4; - put_debug_char(*src); checksum += *src; - put_debug_char('*'); checksum += '*'; - put_debug_char(encode); checksum += encode; - src += runlen; - } else { - /* Otherwise just send the current char */ - put_debug_char(*src); checksum += *src; - src += 1; - } - } - - /* '#' Separator, put high and low components of checksum */ - put_debug_char('#'); - put_debug_char(hex_asc_hi(checksum)); - put_debug_char(hex_asc_lo(checksum)); - } - while ((get_debug_char()) != '+'); /* While no ack */ -} - -/* A bus error has occurred - perform a longjmp to return execution and - allow handling of the error */ -static void kgdb_handle_bus_error(void) -{ - longjmp(rem_com_env, 1); -} - -/* Translate SH-3/4 exception numbers to unix-like signal values */ -static int compute_signal(const int excep_code) -{ - int sigval; - - switch (excep_code) { - - case INVALID_INSN_VEC: - case INVALID_SLOT_VEC: - sigval = SIGILL; - break; - case ADDRESS_ERROR_LOAD_VEC: - case ADDRESS_ERROR_STORE_VEC: - sigval = SIGSEGV; - break; - - case SERIAL_BREAK_VEC: - case NMI_VEC: - sigval = SIGINT; - break; - - case USER_BREAK_VEC: - case TRAP_VEC: - sigval = SIGTRAP; - break; - - default: - sigval = SIGBUS; /* "software generated" */ - break; - } - - return (sigval); -} - -/* Make a local copy of the registers passed into the handler (bletch) */ -static void kgdb_regs_to_gdb_regs(const struct kgdb_regs *regs, - int *gdb_regs) -{ - gdb_regs[R0] = regs->regs[R0]; - gdb_regs[R1] = regs->regs[R1]; - gdb_regs[R2] = regs->regs[R2]; - gdb_regs[R3] = regs->regs[R3]; - gdb_regs[R4] = regs->regs[R4]; - gdb_regs[R5] = regs->regs[R5]; - gdb_regs[R6] = regs->regs[R6]; - gdb_regs[R7] = regs->regs[R7]; - gdb_regs[R8] = regs->regs[R8]; - gdb_regs[R9] = regs->regs[R9]; - gdb_regs[R10] = regs->regs[R10]; - gdb_regs[R11] = regs->regs[R11]; - gdb_regs[R12] = regs->regs[R12]; - gdb_regs[R13] = regs->regs[R13]; - gdb_regs[R14] = regs->regs[R14]; - gdb_regs[R15] = regs->regs[R15]; - gdb_regs[PC] = regs->pc; - gdb_regs[PR] = regs->pr; - gdb_regs[GBR] = regs->gbr; - gdb_regs[MACH] = regs->mach; - gdb_regs[MACL] = regs->macl; - gdb_regs[SR] = regs->sr; - gdb_regs[VBR] = regs->vbr; -} - -/* Copy local gdb registers back to kgdb regs, for later copy to kernel */ -static void gdb_regs_to_kgdb_regs(const int *gdb_regs, - struct kgdb_regs *regs) -{ - regs->regs[R0] = gdb_regs[R0]; - regs->regs[R1] = gdb_regs[R1]; - regs->regs[R2] = gdb_regs[R2]; - regs->regs[R3] = gdb_regs[R3]; - regs->regs[R4] = gdb_regs[R4]; - regs->regs[R5] = gdb_regs[R5]; - regs->regs[R6] = gdb_regs[R6]; - regs->regs[R7] = gdb_regs[R7]; - regs->regs[R8] = gdb_regs[R8]; - regs->regs[R9] = gdb_regs[R9]; - regs->regs[R10] = gdb_regs[R10]; - regs->regs[R11] = gdb_regs[R11]; - regs->regs[R12] = gdb_regs[R12]; - regs->regs[R13] = gdb_regs[R13]; - regs->regs[R14] = gdb_regs[R14]; - regs->regs[R15] = gdb_regs[R15]; - regs->pc = gdb_regs[PC]; - regs->pr = gdb_regs[PR]; - regs->gbr = gdb_regs[GBR]; - regs->mach = gdb_regs[MACH]; - regs->macl = gdb_regs[MACL]; - regs->sr = gdb_regs[SR]; - regs->vbr = gdb_regs[VBR]; -} - -/* Calculate the new address for after a step */ -static short *get_step_address(void) -{ - short op = *(short *) trap_registers.pc; - long addr; - - /* BT */ - if (OPCODE_BT(op)) { - if (trap_registers.sr & SR_T_BIT_MASK) - addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); - else - addr = trap_registers.pc + 2; - } - - /* BTS */ - else if (OPCODE_BTS(op)) { - if (trap_registers.sr & SR_T_BIT_MASK) - addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); - else - addr = trap_registers.pc + 4; /* Not in delay slot */ - } - - /* BF */ - else if (OPCODE_BF(op)) { - if (!(trap_registers.sr & SR_T_BIT_MASK)) - addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); - else - addr = trap_registers.pc + 2; - } - - /* BFS */ - else if (OPCODE_BFS(op)) { - if (!(trap_registers.sr & SR_T_BIT_MASK)) - addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); - else - addr = trap_registers.pc + 4; /* Not in delay slot */ - } - - /* BRA */ - else if (OPCODE_BRA(op)) - addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op); - - /* BRAF */ - else if (OPCODE_BRAF(op)) - addr = trap_registers.pc + 4 - + trap_registers.regs[OPCODE_BRAF_REG(op)]; - - /* BSR */ - else if (OPCODE_BSR(op)) - addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op); - - /* BSRF */ - else if (OPCODE_BSRF(op)) - addr = trap_registers.pc + 4 - + trap_registers.regs[OPCODE_BSRF_REG(op)]; - - /* JMP */ - else if (OPCODE_JMP(op)) - addr = trap_registers.regs[OPCODE_JMP_REG(op)]; - - /* JSR */ - else if (OPCODE_JSR(op)) - addr = trap_registers.regs[OPCODE_JSR_REG(op)]; - - /* RTS */ - else if (OPCODE_RTS(op)) - addr = trap_registers.pr; - - /* RTE */ - else if (OPCODE_RTE(op)) - addr = trap_registers.regs[15]; - - /* Other */ - else - addr = trap_registers.pc + 2; - - flush_icache_range(addr, addr + 2); - return (short *) addr; -} - -/* Set up a single-step. Replace the instruction immediately after the - current instruction (i.e. next in the expected flow of control) with a - trap instruction, so that returning will cause only a single instruction - to be executed. Note that this model is slightly broken for instructions - with delay slots (e.g. B[TF]S, BSR, BRA etc), where both the branch - and the instruction in the delay slot will be executed. */ -static void do_single_step(void) -{ - unsigned short *addr = 0; - - /* Determine where the target instruction will send us to */ - addr = get_step_address(); - stepped_address = (int)addr; - - /* Replace it */ - stepped_opcode = *(short *)addr; - *addr = STEP_OPCODE; - - /* Flush and return */ - flush_icache_range((long) addr, (long) addr + 2); -} - -/* Undo a single step */ -static void undo_single_step(void) -{ - /* If we have stepped, put back the old instruction */ - /* Use stepped_address in case we stopped elsewhere */ - if (stepped_opcode != 0) { - *(short*)stepped_address = stepped_opcode; - flush_icache_range(stepped_address, stepped_address + 2); - } - stepped_opcode = 0; -} - -/* Send a signal message */ -static void send_signal_msg(const int signum) -{ - out_buffer[0] = 'S'; - out_buffer[1] = hex_asc_hi(signum); - out_buffer[2] = hex_asc_lo(signum); - out_buffer[3] = 0; - put_packet(out_buffer); -} - -/* Reply that all was well */ -static void send_ok_msg(void) -{ - strcpy(out_buffer, "OK"); - put_packet(out_buffer); -} - -/* Reply that an error occurred */ -static void send_err_msg(void) -{ - strcpy(out_buffer, "E01"); - put_packet(out_buffer); -} - -/* Empty message indicates unrecognised command */ -static void send_empty_msg(void) -{ - put_packet(""); -} - -/* Read memory due to 'm' message */ -static void read_mem_msg(void) -{ - char *ptr; - int addr; - int length; - - /* Jmp, disable bus error handler */ - if (setjmp(rem_com_env) == 0) { - - kgdb_nofault = 1; - - /* Walk through, have m, */ - ptr = &in_buffer[1]; - if (hex_to_int(&ptr, &addr) && (*ptr++ == ',')) - if (hex_to_int(&ptr, &length)) { - ptr = 0; - if (length * 2 > OUTBUFMAX) - length = OUTBUFMAX / 2; - mem_to_hex((char *) addr, out_buffer, length); - } - if (ptr) - send_err_msg(); - else - put_packet(out_buffer); - } else - send_err_msg(); - - /* Restore bus error handler */ - kgdb_nofault = 0; -} - -/* Write memory due to 'M' or 'X' message */ -static void write_mem_msg(int binary) -{ - char *ptr; - int addr; - int length; - - if (setjmp(rem_com_env) == 0) { - - kgdb_nofault = 1; - - /* Walk through, have M,: */ - ptr = &in_buffer[1]; - if (hex_to_int(&ptr, &addr) && (*ptr++ == ',')) - if (hex_to_int(&ptr, &length) && (*ptr++ == ':')) { - if (binary) - ebin_to_mem(ptr, (char*)addr, length); - else - hex_to_mem(ptr, (char*)addr, length); - flush_icache_range(addr, addr + length); - ptr = 0; - send_ok_msg(); - } - if (ptr) - send_err_msg(); - } else - send_err_msg(); - - /* Restore bus error handler */ - kgdb_nofault = 0; -} - -/* Continue message */ -static void continue_msg(void) -{ - /* Try to read optional parameter, PC unchanged if none */ - char *ptr = &in_buffer[1]; - int addr; - - if (hex_to_int(&ptr, &addr)) - trap_registers.pc = addr; -} - -/* Continue message with signal */ -static void continue_with_sig_msg(void) -{ - int signal; - char *ptr = &in_buffer[1]; - int addr; - - /* Report limitation */ - kgdb_to_gdb("Cannot force signal in kgdb, continuing anyway.\n"); - - /* Signal */ - hex_to_int(&ptr, &signal); - if (*ptr == ';') - ptr++; - - /* Optional address */ - if (hex_to_int(&ptr, &addr)) - trap_registers.pc = addr; -} - -/* Step message */ -static void step_msg(void) -{ - continue_msg(); - do_single_step(); -} - -/* Step message with signal */ -static void step_with_sig_msg(void) -{ - continue_with_sig_msg(); - do_single_step(); -} - -/* Send register contents */ -static void send_regs_msg(void) -{ - kgdb_regs_to_gdb_regs(&trap_registers, registers); - mem_to_hex((char *) registers, out_buffer, NUMREGBYTES); - put_packet(out_buffer); -} - -/* Set register contents - currently can't set other thread's registers */ -static void set_regs_msg(void) -{ - kgdb_regs_to_gdb_regs(&trap_registers, registers); - hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES); - gdb_regs_to_kgdb_regs(registers, &trap_registers); - send_ok_msg(); -} - -#ifdef CONFIG_SH_KGDB_CONSOLE -/* - * Bring up the ports.. - */ -static int __init kgdb_serial_setup(void) -{ - struct console dummy; - return kgdb_console_setup(&dummy, 0); -} -#else -#define kgdb_serial_setup() 0 -#endif - -/* The command loop, read and act on requests */ -static void kgdb_command_loop(const int excep_code, const int trapa_value) -{ - int sigval; - - /* Enter GDB mode (e.g. after detach) */ - if (!kgdb_in_gdb_mode) { - /* Do serial setup, notify user, issue preemptive ack */ - printk(KERN_NOTICE "KGDB: Waiting for GDB\n"); - kgdb_in_gdb_mode = 1; - put_debug_char('+'); - } - - /* Reply to host that an exception has occurred */ - sigval = compute_signal(excep_code); - send_signal_msg(sigval); - - /* TRAP_VEC exception indicates a software trap inserted in place of - code by GDB so back up PC by one instruction, as this instruction - will later be replaced by its original one. Do NOT do this for - trap 0xff, since that indicates a compiled-in breakpoint which - will not be replaced (and we would retake the trap forever) */ - if ((excep_code == TRAP_VEC) && (trapa_value != (0x3c << 2))) - trap_registers.pc -= 2; - - /* Undo any stepping we may have done */ - undo_single_step(); - - while (1) { - out_buffer[0] = 0; - get_packet(in_buffer, BUFMAX); - - /* Examine first char of buffer to see what we need to do */ - switch (in_buffer[0]) { - case '?': /* Send which signal we've received */ - send_signal_msg(sigval); - break; - - case 'g': /* Return the values of the CPU registers */ - send_regs_msg(); - break; - - case 'G': /* Set the value of the CPU registers */ - set_regs_msg(); - break; - - case 'm': /* Read LLLL bytes address AA..AA */ - read_mem_msg(); - break; - - case 'M': /* Write LLLL bytes address AA..AA, ret OK */ - write_mem_msg(0); /* 0 = data in hex */ - break; - - case 'X': /* Write LLLL bytes esc bin address AA..AA */ - if (kgdb_bits == '8') - write_mem_msg(1); /* 1 = data in binary */ - else - send_empty_msg(); - break; - - case 'C': /* Continue, signum included, we ignore it */ - continue_with_sig_msg(); - return; - - case 'c': /* Continue at address AA..AA (optional) */ - continue_msg(); - return; - - case 'S': /* Step, signum included, we ignore it */ - step_with_sig_msg(); - return; - - case 's': /* Step one instruction from AA..AA */ - step_msg(); - return; - - case 'k': /* 'Kill the program' with a kernel ? */ - break; - - case 'D': /* Detach from program, send reply OK */ - kgdb_in_gdb_mode = 0; - send_ok_msg(); - get_debug_char(); - return; - - default: - send_empty_msg(); - break; - } - } -} - -/* There has been an exception, most likely a breakpoint. */ -static void handle_exception(struct pt_regs *regs) -{ - int excep_code, vbr_val; - int count; - int trapa_value = ctrl_inl(TRA); - - /* Copy kernel regs (from stack) */ - for (count = 0; count < 16; count++) - trap_registers.regs[count] = regs->regs[count]; - trap_registers.pc = regs->pc; - trap_registers.pr = regs->pr; - trap_registers.sr = regs->sr; - trap_registers.gbr = regs->gbr; - trap_registers.mach = regs->mach; - trap_registers.macl = regs->macl; - - asm("stc vbr, %0":"=r"(vbr_val)); - trap_registers.vbr = vbr_val; - - /* Get excode for command loop call, user access */ - asm("stc r2_bank, %0":"=r"(excep_code)); - - /* Act on the exception */ - kgdb_command_loop(excep_code, trapa_value); - - /* Copy back the (maybe modified) registers */ - for (count = 0; count < 16; count++) - regs->regs[count] = trap_registers.regs[count]; - regs->pc = trap_registers.pc; - regs->pr = trap_registers.pr; - regs->sr = trap_registers.sr; - regs->gbr = trap_registers.gbr; - regs->mach = trap_registers.mach; - regs->macl = trap_registers.macl; - - vbr_val = trap_registers.vbr; - asm("ldc %0, vbr": :"r"(vbr_val)); -} - -asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - handle_exception(regs); -} - -/* Initialise the KGDB data structures and serial configuration */ -int __init kgdb_init(void) -{ - in_nmi = 0; - kgdb_nofault = 0; - stepped_opcode = 0; - kgdb_in_gdb_mode = 0; - - if (kgdb_serial_setup() != 0) { - printk(KERN_NOTICE "KGDB: serial setup error\n"); - return -1; - } - - /* Init ptr to exception handler */ - kgdb_debug_hook = handle_exception; - kgdb_bus_err_hook = kgdb_handle_bus_error; - - /* Enter kgdb now if requested, or just report init done */ - printk(KERN_NOTICE "KGDB: stub is initialized.\n"); - - return 0; -} - -/* Make function available for "user messages"; console will use it too. */ - -char gdbmsgbuf[BUFMAX]; -#define MAXOUT ((BUFMAX-2)/2) - -static void kgdb_msg_write(const char *s, unsigned count) -{ - int i; - int wcount; - char *bufptr; - - /* 'O'utput */ - gdbmsgbuf[0] = 'O'; - - /* Fill and send buffers... */ - while (count > 0) { - bufptr = gdbmsgbuf + 1; - - /* Calculate how many this time */ - wcount = (count > MAXOUT) ? MAXOUT : count; - - /* Pack in hex chars */ - for (i = 0; i < wcount; i++) - bufptr = pack_hex_byte(bufptr, s[i]); - *bufptr = '\0'; - - /* Move up */ - s += wcount; - count -= wcount; - - /* Write packet */ - put_packet(gdbmsgbuf); - } -} - -static void kgdb_to_gdb(const char *s) -{ - kgdb_msg_write(s, strlen(s)); -} - -#ifdef CONFIG_SH_KGDB_CONSOLE -void kgdb_console_write(struct console *co, const char *s, unsigned count) -{ - /* Bail if we're not talking to GDB */ - if (!kgdb_in_gdb_mode) - return; - - kgdb_msg_write(s, count); -} -#endif - -#ifdef CONFIG_KGDB_SYSRQ -static void sysrq_handle_gdb(int key, struct tty_struct *tty) -{ - printk("Entering GDB stub\n"); - breakpoint(); -} - -static struct sysrq_key_op sysrq_gdb_op = { - .handler = sysrq_handle_gdb, - .help_msg = "Gdb", - .action_msg = "GDB", -}; - -static int gdb_register_sysrq(void) -{ - printk("Registering GDB sysrq handler\n"); - register_sysrq_key('g', &sysrq_gdb_op); - return 0; -} -module_init(gdb_register_sysrq); -#endif diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c index 23ca711c27d2..1336f275326c 100644 --- a/arch/sh/kernel/time_32.c +++ b/arch/sh/kernel/time_32.c @@ -277,11 +277,4 @@ void __init time_init(void) ((sh_hpt_frequency + 500) / 1000) / 1000, ((sh_hpt_frequency + 500) / 1000) % 1000); -#if defined(CONFIG_SH_KGDB) - /* - * Set up kgdb as requested. We do it here because the serial - * init uses the timer vars we just set up for figuring baud. - */ - kgdb_init(); -#endif } diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 6094fc13beea..88807a2aacc3 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -28,17 +28,6 @@ #include #include -#ifdef CONFIG_SH_KGDB -#include -#define CHK_REMOTE_DEBUG(regs) \ -{ \ - if (kgdb_debug_hook && !user_mode(regs))\ - (*kgdb_debug_hook)(regs); \ -} -#else -#define CHK_REMOTE_DEBUG(regs) -#endif - #ifdef CONFIG_CPU_SH2 # define TRAP_RESERVED_INST 4 # define TRAP_ILLEGAL_SLOT_INST 6 @@ -94,7 +83,6 @@ void die(const char * str, struct pt_regs * regs, long err) printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); - CHK_REMOTE_DEBUG(regs); print_modules(); show_regs(regs); @@ -683,7 +671,6 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, error_code = lookup_exception_vector(); local_irq_enable(); - CHK_REMOTE_DEBUG(regs); force_sig(SIGILL, tsk); die_if_no_fixup("reserved instruction", regs, error_code); } @@ -761,7 +748,6 @@ asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5, inst = lookup_exception_vector(); local_irq_enable(); - CHK_REMOTE_DEBUG(regs); force_sig(SIGILL, tsk); die_if_no_fixup("illegal slot instruction", regs, inst); } -- cgit v1.2.1 From 776d6c298aad42c2b8f191fa9ad826075e4d588c Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 11 Dec 2008 19:15:14 +0900 Subject: sh: Kill off remaining CONFIG_SH_KGDB bits. Now that we use the generic stub, kill off all of the left over references. Signed-off-by: Paul Mundt --- arch/sh/kernel/Makefile_64 | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64 index ae4afc090062..678408cc35ca 100644 --- a/arch/sh/kernel/Makefile_64 +++ b/arch/sh/kernel/Makefile_64 @@ -9,7 +9,6 @@ obj-$(CONFIG_VSYSCALL) += vsyscall/ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_CF_ENABLER) += cf-enabler.o obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o -obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o obj-$(CONFIG_MODULES) += sh_ksyms_64.o module.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -- cgit v1.2.1 From 4466b20cfcfa718ff515b9e3886749cc025e2005 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 12 Dec 2008 16:34:44 +0900 Subject: sh: Add SH-5 optimized memcpy()/memset()/strcpy()/strlen(). Adopted from the uClibc optimized string versions. Signed-off-by: Paul Mundt --- arch/sh/kernel/sh_ksyms_64.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c index 9324d32adacc..ab7adaa95f77 100644 --- a/arch/sh/kernel/sh_ksyms_64.c +++ b/arch/sh/kernel/sh_ksyms_64.c @@ -65,9 +65,12 @@ EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(__copy_user); EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__ndelay); EXPORT_SYMBOL(__const_udelay); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strcpy); /* Ugh. These come in from libgcc.a at link time. */ #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) -- cgit v1.2.1 From 180ae2037f5bc33b0597ddbb76d36b08a74a238a Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 12 Dec 2008 16:53:14 +0900 Subject: sh: Provide sdivsi3/udivsi3/udivdi3 for sh64, kill off libgcc linking. This moves in the necessary libgcc bits and kills off the libgcc linking for sh64 kernels as well. Signed-off-by: Paul Mundt --- arch/sh/kernel/sh_ksyms_64.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c index ab7adaa95f77..0d74d6b8774e 100644 --- a/arch/sh/kernel/sh_ksyms_64.c +++ b/arch/sh/kernel/sh_ksyms_64.c @@ -76,7 +76,5 @@ EXPORT_SYMBOL(strcpy); #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) DECLARE_EXPORT(__sdivsi3); -DECLARE_EXPORT(__sdivsi3_2); -DECLARE_EXPORT(__muldi3); DECLARE_EXPORT(__udivsi3); DECLARE_EXPORT(__div_table); -- cgit v1.2.1 From 8e32018b0428038b492dad5b19e80bf7d6dc002d Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 17 Dec 2008 11:37:51 +0900 Subject: sh: Run sh_bios through a long overdue Lindent. Signed-off-by: Paul Mundt --- arch/sh/kernel/sh_bios.c | 70 +++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 36 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c index d1bcac4fa269..7c8c58ec5dec 100644 --- a/arch/sh/kernel/sh_bios.c +++ b/arch/sh/kernel/sh_bios.c @@ -8,69 +8,67 @@ #include #include -#define BIOS_CALL_CONSOLE_WRITE 0 -#define BIOS_CALL_READ_BLOCK 1 +#define BIOS_CALL_CONSOLE_WRITE 0 +#define BIOS_CALL_READ_BLOCK 1 #define BIOS_CALL_ETH_NODE_ADDR 10 #define BIOS_CALL_SHUTDOWN 11 -#define BIOS_CALL_CHAR_OUT 0x1f /* TODO: hack */ -#define BIOS_CALL_GDB_GET_MODE_PTR 0xfe -#define BIOS_CALL_GDB_DETACH 0xff +#define BIOS_CALL_CHAR_OUT 0x1f /* TODO: hack */ +#define BIOS_CALL_GDB_GET_MODE_PTR 0xfe +#define BIOS_CALL_GDB_DETACH 0xff -static __inline__ long sh_bios_call(long func, long arg0, long arg1, long arg2, long arg3) +static inline long sh_bios_call(long func, long arg0, long arg1, long arg2, + long arg3) { - register long r0 __asm__("r0") = func; - register long r4 __asm__("r4") = arg0; - register long r5 __asm__("r5") = arg1; - register long r6 __asm__("r6") = arg2; - register long r7 __asm__("r7") = arg3; - __asm__ __volatile__("trapa #0x3f" - : "=z" (r0) - : "0" (r0), "r" (r4), "r" (r5), "r" (r6), "r" (r7) - : "memory"); - return r0; -} + register long r0 __asm__("r0") = func; + register long r4 __asm__("r4") = arg0; + register long r5 __asm__("r5") = arg1; + register long r6 __asm__("r6") = arg2; + register long r7 __asm__("r7") = arg3; + __asm__ __volatile__("trapa #0x3f":"=z"(r0) + :"0"(r0), "r"(r4), "r"(r5), "r"(r6), "r"(r7) + :"memory"); + return r0; +} void sh_bios_console_write(const char *buf, unsigned int len) { - sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0); + sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0); } - void sh_bios_char_out(char ch) { - sh_bios_call(BIOS_CALL_CHAR_OUT, ch, 0, 0, 0); + sh_bios_call(BIOS_CALL_CHAR_OUT, ch, 0, 0, 0); } - int sh_bios_in_gdb_mode(void) { - static char queried = 0; - static char *gdb_mode_p = 0; + static char queried = 0; + static char *gdb_mode_p = 0; - if (!queried) - { - /* Query the gdb stub for address of its gdb mode variable */ - long r = sh_bios_call(BIOS_CALL_GDB_GET_MODE_PTR, 0, 0, 0, 0); - if (r != ~0) /* BIOS returns -1 for unknown function */ - gdb_mode_p = (char *)r; - queried = 1; - } - return (gdb_mode_p != 0 ? *gdb_mode_p : 0); + if (!queried) { + /* Query the gdb stub for address of its gdb mode variable */ + long r = sh_bios_call(BIOS_CALL_GDB_GET_MODE_PTR, 0, 0, 0, 0); + if (r != ~0) /* BIOS returns -1 for unknown function */ + gdb_mode_p = (char *)r; + queried = 1; + } + return (gdb_mode_p != 0 ? *gdb_mode_p : 0); } void sh_bios_gdb_detach(void) { - sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0); + sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0); } + EXPORT_SYMBOL(sh_bios_gdb_detach); -void sh_bios_get_node_addr (unsigned char *node_addr) +void sh_bios_get_node_addr(unsigned char *node_addr) { - sh_bios_call(BIOS_CALL_ETH_NODE_ADDR, 0, (long)node_addr, 0, 0); + sh_bios_call(BIOS_CALL_ETH_NODE_ADDR, 0, (long)node_addr, 0, 0); } void sh_bios_shutdown(unsigned int how) { - sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0); + sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0); } -- cgit v1.2.1 From a9df1ed92fc46cb7c9a9c6b74dbd8bbdc41f69ce Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 17 Dec 2008 11:39:33 +0900 Subject: sh: export sh_bios_get_node_addr() symbol for stnic module. Signed-off-by: Paul Mundt --- arch/sh/kernel/sh_bios.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c index 7c8c58ec5dec..ae64e6df2957 100644 --- a/arch/sh/kernel/sh_bios.c +++ b/arch/sh/kernel/sh_bios.c @@ -60,13 +60,13 @@ void sh_bios_gdb_detach(void) { sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0); } - -EXPORT_SYMBOL(sh_bios_gdb_detach); +EXPORT_SYMBOL_GPL(sh_bios_gdb_detach); void sh_bios_get_node_addr(unsigned char *node_addr) { sh_bios_call(BIOS_CALL_ETH_NODE_ADDR, 0, (long)node_addr, 0, 0); } +EXPORT_SYMBOL_GPL(sh_bios_get_node_addr); void sh_bios_shutdown(unsigned int how) { -- cgit v1.2.1 From ca0c14e447a399eb90a1c9a4357560c2a29ef499 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 17 Dec 2008 11:47:59 +0900 Subject: sh: Kill off sh_bios_in_gdb_mode(). With the reworked kgdb support, we always detach and reinitialize the stub. This was mostly a feature for handoffs between sh-ipl+g and the kgdb stub, but virtually no sh-ipl+g versions ever had this working right in the first place. Given that the sh-ipl+g stubs in general use today don't even support the GDB stub, and we have already killed off the special casing in the sh-sci serial driver, kill off this now unused symbol too. Signed-off-by: Paul Mundt --- arch/sh/kernel/sh_bios.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c index ae64e6df2957..c852f7805728 100644 --- a/arch/sh/kernel/sh_bios.c +++ b/arch/sh/kernel/sh_bios.c @@ -9,11 +9,9 @@ #include #define BIOS_CALL_CONSOLE_WRITE 0 -#define BIOS_CALL_READ_BLOCK 1 #define BIOS_CALL_ETH_NODE_ADDR 10 #define BIOS_CALL_SHUTDOWN 11 #define BIOS_CALL_CHAR_OUT 0x1f /* TODO: hack */ -#define BIOS_CALL_GDB_GET_MODE_PTR 0xfe #define BIOS_CALL_GDB_DETACH 0xff static inline long sh_bios_call(long func, long arg0, long arg1, long arg2, @@ -41,21 +39,6 @@ void sh_bios_char_out(char ch) sh_bios_call(BIOS_CALL_CHAR_OUT, ch, 0, 0, 0); } -int sh_bios_in_gdb_mode(void) -{ - static char queried = 0; - static char *gdb_mode_p = 0; - - if (!queried) { - /* Query the gdb stub for address of its gdb mode variable */ - long r = sh_bios_call(BIOS_CALL_GDB_GET_MODE_PTR, 0, 0, 0, 0); - if (r != ~0) /* BIOS returns -1 for unknown function */ - gdb_mode_p = (char *)r; - queried = 1; - } - return (gdb_mode_p != 0 ? *gdb_mode_p : 0); -} - void sh_bios_gdb_detach(void) { sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0); -- cgit v1.2.1 From 7b80fb32b39a51ce3e1afa051f5a616eb8ecbed3 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 17 Dec 2008 12:19:30 +0900 Subject: sh: Kill off mv_heartbeat() from the machvec. Nothing is using this any more, so get rid of it before anyone gets the bright idea to start using it again. Signed-off-by: Paul Mundt --- arch/sh/kernel/time_32.c | 5 ----- arch/sh/kernel/time_64.c | 5 ----- 2 files changed, 10 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c index 1336f275326c..8457f83242c5 100644 --- a/arch/sh/kernel/time_32.c +++ b/arch/sh/kernel/time_32.c @@ -125,11 +125,6 @@ void handle_timer_tick(void) if (current->pid) profile_tick(CPU_PROFILING); -#ifdef CONFIG_HEARTBEAT - if (sh_mv.mv_heartbeat != NULL) - sh_mv.mv_heartbeat(); -#endif - /* * Here we are in the timer irq handler. We just have irqs locally * disabled but we don't know if the timer_bh is running on the other diff --git a/arch/sh/kernel/time_64.c b/arch/sh/kernel/time_64.c index bbb2af1004d9..59d2a03e8b3c 100644 --- a/arch/sh/kernel/time_64.c +++ b/arch/sh/kernel/time_64.c @@ -240,11 +240,6 @@ static inline void do_timer_interrupt(void) do_timer(1); -#ifdef CONFIG_HEARTBEAT - if (sh_mv.mv_heartbeat != NULL) - sh_mv.mv_heartbeat(); -#endif - /* * If we have an externally synchronized Linux clock, then update * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be -- cgit v1.2.1 From 43f8f9b95b65dc05368cd82268895b9508b17d50 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 17 Dec 2008 12:20:15 +0900 Subject: sh: Simplify kernel_thread_helper() for sh32. This can use the same implementation as sh64, the generated assembly is the same between the new and old version, so there is not much point in leaving it open coded in inline assembly. This is preparatory work for future consolidation of the _32/_64 variants. Signed-off-by: Paul Mundt --- arch/sh/kernel/process_32.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 130817affa64..ddafbbbab2ab 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -97,21 +97,10 @@ void show_regs(struct pt_regs * regs) /* * Create a kernel thread */ - -/* - * This is the mechanism for creating a new kernel thread. - * - */ -extern void kernel_thread_helper(void); -__asm__(".align 5\n" - "kernel_thread_helper:\n\t" - "jsr @r5\n\t" - " nop\n\t" - "mov.l 1f, r1\n\t" - "jsr @r1\n\t" - " mov r0, r4\n\t" - ".align 2\n\t" - "1:.long do_exit"); +ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) +{ + do_exit(fn(arg)); +} /* Don't use this in BL=1(cli). Or else, CPU resets! */ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -- cgit v1.2.1 From 073da9c0de401e8683b6bc76c008a7e0850045d5 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 17 Dec 2008 14:41:54 +0900 Subject: sh: Kill off cf-enabler with extreme prejudice. Now that the rest of the boards that were using cf-enabler "generically" have switched to setting up their mappings on their own, only the mach-se boards were left using it. All of the cf-enabler using mach-se boards use a special initialization of the MRSHPC windows rather than going through the special PTE as other SH-4 platforms do. This consolidates the MRSHPC setup logic, hooks it up on the boards that care, and gets rid of any and all remaining references to cf-enabler. This has been long overdue, as cf-enabler has been the bane of arch/sh/kernel for the last 7 years. Good riddance. Signed-off-by: Paul Mundt --- arch/sh/kernel/Makefile_32 | 1 - arch/sh/kernel/Makefile_64 | 1 - arch/sh/kernel/cf-enabler.c | 168 -------------------------------------------- 3 files changed, 170 deletions(-) delete mode 100644 arch/sh/kernel/cf-enabler.c (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index df25304ad780..3c975ab45590 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -17,7 +17,6 @@ obj-y := debugtraps.o disassemble.o idle.o io.o io_generic.o irq.o \ obj-y += cpu/ timers/ obj-$(CONFIG_VSYSCALL) += vsyscall/ obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_CF_ENABLER) += cf-enabler.o obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64 index 678408cc35ca..fe425d7f6871 100644 --- a/arch/sh/kernel/Makefile_64 +++ b/arch/sh/kernel/Makefile_64 @@ -7,7 +7,6 @@ obj-y := debugtraps.o idle.o io.o io_generic.o irq.o machvec.o process_64.o \ obj-y += cpu/ timers/ obj-$(CONFIG_VSYSCALL) += vsyscall/ obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_CF_ENABLER) += cf-enabler.o obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o obj-$(CONFIG_MODULES) += sh_ksyms_64.o module.o diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c deleted file mode 100644 index bea40339919b..000000000000 --- a/arch/sh/kernel/cf-enabler.c +++ /dev/null @@ -1,168 +0,0 @@ -/* $Id: cf-enabler.c,v 1.4 2004/02/22 22:44:36 kkojima Exp $ - * - * linux/drivers/block/cf-enabler.c - * - * Copyright (C) 1999 Niibe Yutaka - * Copyright (C) 2000 Toshiharu Nozawa - * Copyright (C) 2001 A&D Co., Ltd. - * - * Enable the CF configuration. - */ - -#include -#include -#include -#include -#include -#include - -/* - * You can connect Compact Flash directly to the bus of SuperH. - * This is the enabler for that. - * - * SIM: How generic is this really? It looks pretty board, or at - * least SH sub-type, specific to me. - * I know it doesn't work on the Overdrive! - */ - -/* - * 0xB8000000 : Attribute - * 0xB8001000 : Common Memory - * 0xBA000000 : I/O - */ -#if defined(CONFIG_CPU_SH4) -/* SH4 can't access PCMCIA interface through P2 area. - * we must remap it with appropriate attribute bit of the page set. - * this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */ - -#if defined(CONFIG_CF_AREA6) -#define slot_no 0 -#else -#define slot_no 1 -#endif - -/* use this pointer to access to directly connected compact flash io area*/ -void *cf_io_base; - -static int __init allocate_cf_area(void) -{ - pgprot_t prot; - unsigned long paddrbase, psize; - - /* open I/O area window */ - paddrbase = virt_to_phys((void*)CONFIG_CF_BASE_ADDR); - psize = PAGE_SIZE; - prot = PAGE_KERNEL_PCC(slot_no, _PAGE_PCC_IO16); - cf_io_base = p3_ioremap(paddrbase, psize, prot.pgprot); - if (!cf_io_base) { - printk("allocate_cf_area : can't open CF I/O window!\n"); - return -ENOMEM; - } -/* printk("p3_ioremap(paddr=0x%08lx, psize=0x%08lx, prot=0x%08lx)=0x%08lx\n", - paddrbase, psize, prot.pgprot, cf_io_base);*/ - - /* XXX : do we need attribute and common-memory area also? */ - - return 0; -} -#endif - -static int __init cf_init_default(void) -{ -/* You must have enabled the card, and set the level interrupt - * before reaching this point. Possibly in boot ROM or boot loader. - */ -#if defined(CONFIG_CPU_SH4) - allocate_cf_area(); -#endif - - return 0; -} - -#if defined(CONFIG_SH_SOLUTION_ENGINE) -#include -#elif defined(CONFIG_SH_7722_SOLUTION_ENGINE) -#include -#elif defined(CONFIG_SH_7721_SOLUTION_ENGINE) -#include -#endif - -/* - * SolutionEngine Seriese - * - * about MS770xSE - * 0xB8400000 : Common Memory - * 0xB8500000 : Attribute - * 0xB8600000 : I/O - * - * about MS7722SE - * 0xB0400000 : Common Memory - * 0xB0500000 : Attribute - * 0xB0600000 : I/O - */ - -#if defined(CONFIG_SH_SOLUTION_ENGINE) || \ - defined(CONFIG_SH_7722_SOLUTION_ENGINE) || \ - defined(CONFIG_SH_7721_SOLUTION_ENGINE) -static int __init cf_init_se(void) -{ - if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0) - return 0; /* Not detected */ - - if ((ctrl_inw(MRSHPC_CSR) & 0x0080) == 0) { - ctrl_outw(0x0674, MRSHPC_CPWCR); /* Card Vcc is 3.3v? */ - } else { - ctrl_outw(0x0678, MRSHPC_CPWCR); /* Card Vcc is 5V */ - } - - /* - * PC-Card window open - * flag == COMMON/ATTRIBUTE/IO - */ - /* common window open */ - ctrl_outw(0x8a84, MRSHPC_MW0CR1); - if((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0) - /* common mode & bus width 16bit SWAP = 1*/ - ctrl_outw(0x0b00, MRSHPC_MW0CR2); - else - /* common mode & bus width 16bit SWAP = 0*/ - ctrl_outw(0x0300, MRSHPC_MW0CR2); - - /* attribute window open */ - ctrl_outw(0x8a85, MRSHPC_MW1CR1); - if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0) - /* attribute mode & bus width 16bit SWAP = 1*/ - ctrl_outw(0x0a00, MRSHPC_MW1CR2); - else - /* attribute mode & bus width 16bit SWAP = 0*/ - ctrl_outw(0x0200, MRSHPC_MW1CR2); - - /* I/O window open */ - ctrl_outw(0x8a86, MRSHPC_IOWCR1); - ctrl_outw(0x0008, MRSHPC_CDCR); /* I/O card mode */ - if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0) - ctrl_outw(0x0a00, MRSHPC_IOWCR2); /* bus width 16bit SWAP = 1*/ - else - ctrl_outw(0x0200, MRSHPC_IOWCR2); /* bus width 16bit SWAP = 0*/ - - ctrl_outw(0x2000, MRSHPC_ICR); - ctrl_outb(0x00, PA_MRSHPC_MW2 + 0x206); - ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200); - return 0; -} -#else -static int __init cf_init_se(void) -{ - return -1; -} -#endif - -static int __init cf_init(void) -{ - if (mach_is_se() || mach_is_7722se() || mach_is_7721se()) - return cf_init_se(); - - return cf_init_default(); -} - -__initcall (cf_init); -- cgit v1.2.1 From 740a3e677b70181d5e2b1458a27891209e3bf635 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 17 Dec 2008 15:33:43 +0900 Subject: sh: Enable skipping of bss on debug platforms for sh32 also. This enables the same functionality that sh64 has for sh32. When running on simulated hardware or via remote memory via the debug interface, memory is gauranteed to be zero on boot already, and skipping the zeroing of BSS has measurable boot time benefits. Signed-off-by: Paul Mundt --- arch/sh/kernel/head_32.S | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S index ae0a382a82eb..788605ff7088 100644 --- a/arch/sh/kernel/head_32.S +++ b/arch/sh/kernel/head_32.S @@ -80,8 +80,14 @@ ENTRY(_stext) mov.l 7f, r0 ldc r0, r7_bank ! ... and initial thread_info #endif - - ! Clear BSS area + +#ifndef CONFIG_SH_NO_BSS_INIT + /* + * Don't clear BSS if running on slow platforms such as an RTL simulation, + * remote memory via SHdebug link, etc. For these the memory can be guaranteed + * to be all zero on boot anyway. + */ + ! Clear BSS area #ifdef CONFIG_SMP mov.l 3f, r0 cmp/eq #0, r0 ! skip clear if set to zero @@ -97,6 +103,8 @@ ENTRY(_stext) mov.l r0,@-r2 10: +#endif + ! Additional CPU initialization mov.l 6f, r0 jsr @r0 -- cgit v1.2.1 From 5d2685d0b3edc51ecc92604d5b7f5ca9b29b90bb Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 17 Dec 2008 15:56:06 +0900 Subject: sh: Conditionalize the code dumper on CONFIG_DUMP_CODE. We don't really want this enabled by default, but it is still quite useful for debugging. So, make it conditional and leave it off by default. Signed-off-by: Paul Mundt --- arch/sh/kernel/Makefile_32 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index 3c975ab45590..2e1b86e16ab5 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -9,7 +9,7 @@ ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_ftrace.o = -pg endif -obj-y := debugtraps.o disassemble.o idle.o io.o io_generic.o irq.o \ +obj-y := debugtraps.o idle.o io.o io_generic.o irq.o \ machvec.o process_32.o ptrace_32.o setup.o signal_32.o \ sys_sh.o sys_sh32.o syscalls_32.o time_32.o topology.o \ traps.o traps_32.o @@ -29,5 +29,6 @@ obj-$(CONFIG_IO_TRAPPED) += io_trapped.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o +obj-$(CONFIG_DUMP_CODE) += disassemble.o EXTRA_CFLAGS += -Werror -- cgit v1.2.1 From 7d91fcfcb91dde7bc4586154942862c1724b3519 Mon Sep 17 00:00:00 2001 From: Takanari Hayama Date: Mon, 22 Dec 2008 11:05:03 +0900 Subject: sh: add UIO support for JPU on SH7722. Add JPU support on Migo-R via UIO. This make use of Magnus's generic UIO platform driver. Chunk of contiguous memory to hold intermediate image and compressed data during encode and decode. Signed-off-by: Takanari Hayama Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 9162013ec695..50cf6838ec41 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -148,6 +148,34 @@ static struct platform_device veu_device = { .num_resources = ARRAY_SIZE(veu_resources), }; +static struct uio_info jpu_platform_data = { + .name = "JPU", + .version = "0", + .irq = 27, +}; + +static struct resource jpu_resources[] = { + [0] = { + .name = "JPU", + .start = 0xfea00000, + .end = 0xfea102d0, + .flags = IORESOURCE_MEM, + }, + [1] = { + /* place holder for contiguous memory */ + }, +}; + +static struct platform_device jpu_device = { + .name = "uio_pdrv_genirq", + .id = 2, + .dev = { + .platform_data = &jpu_platform_data, + }, + .resource = jpu_resources, + .num_resources = ARRAY_SIZE(jpu_resources), +}; + static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xffe00000, @@ -187,6 +215,7 @@ static struct platform_device *sh7722_devices[] __initdata = { &sci_device, &vpu_device, &veu_device, + &jpu_device, }; static int __init sh7722_devices_setup(void) @@ -196,9 +225,11 @@ static int __init sh7722_devices_setup(void) clk_always_enable("rtc0"); /* RTC */ clk_always_enable("veu0"); /* VEU */ clk_always_enable("vpu0"); /* VPU */ + clk_always_enable("jpu0"); /* JPU */ platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20); platform_resource_setup_memory(&veu_device, "veu", 2 << 20); + platform_resource_setup_memory(&jpu_device, "jpu", 2 << 20); return platform_add_devices(sh7722_devices, ARRAY_SIZE(sh7722_devices)); -- cgit v1.2.1 From fc5243d98ac2575ad14a974b3c097e9ba874c03d Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 25 Dec 2008 13:38:35 +0100 Subject: [S390] arch_setup_additional_pages arguments arch_setup_additional_pages currently gets two arguments, the binary format descripton and an indication if the process uses an executable stack or not. The second argument is not used by anybody, it could be removed without replacement. What actually does make sense is to pass an indication if the process uses the elf interpreter or not. The glibc code will not use anything from the vdso if the process does not use the dynamic linker, so for statically linked binaries the architecture backend can choose not to map the vdso. Acked-by: Ingo Molnar Signed-off-by: Martin Schwidefsky --- arch/sh/kernel/vsyscall/vsyscall.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c index 95f4de0800ec..3f7e415be86a 100644 --- a/arch/sh/kernel/vsyscall/vsyscall.c +++ b/arch/sh/kernel/vsyscall/vsyscall.c @@ -59,8 +59,7 @@ int __init vsyscall_init(void) } /* Setup a VMA at program startup for the vsyscall page */ -int arch_setup_additional_pages(struct linux_binprm *bprm, - int executable_stack) +int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { struct mm_struct *mm = current->mm; unsigned long addr; -- cgit v1.2.1