diff --git a/Documentation/devicetree/booting-without-of.txt b/Documentation/devicetree/booting-without-of.txt index 04d34f6a58f3..3f1437fbca6b 100644 --- a/Documentation/devicetree/booting-without-of.txt +++ b/Documentation/devicetree/booting-without-of.txt @@ -16,6 +16,7 @@ Table of Contents 2) Entry point for arch/powerpc 3) Entry point for arch/x86 4) Entry point for arch/mips/bmips + 5) Entry point for arch/sh II - The DT block format 1) Header @@ -316,6 +317,18 @@ it with special cases. This convention is defined for 32-bit systems only, as there are not currently any 64-bit BMIPS implementations. +5) Entry point for arch/sh +-------------------------- + + Device-tree-compatible SH bootloaders are expected to provide the physical + address of the device tree blob in r4. Since legacy bootloaders did not + guarantee any particular initial register state, kernels built to + inter-operate with old bootloaders must either use a builtin DTB or + select a legacy board option (something other than CONFIG_SH_DEVICE_TREE) + that does not use device tree. Support for the latter is being phased out + in favor of device tree. + + II - The DT block format ======================== diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 17a4f1593d65..7ed20fc3fc81 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -1,5 +1,6 @@ config SUPERH def_bool y + select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_MIGHT_HAVE_PC_PARPORT select HAVE_PATA_PLATFORM select CLKDEV_LOOKUP diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 89963d13f930..5e52d5362292 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -6,6 +6,21 @@ config SOLUTION_ENGINE config SH_ALPHA_BOARD bool +config SH_DEVICE_TREE + bool "Board Described by Device Tree" + select OF + select OF_EARLY_FLATTREE + select CLKSRC_OF + select GENERIC_CALIBRATE_DELAY + help + Select Board Described by Device Tree to build a kernel that + does not hard-code any board-specific knowledge but instead uses + a device tree blob provided by the boot-loader. You must enable + drivers for any hardware you want to use separately. At this + time, only boards based on the open-hardware J-Core processors + have sufficient driver coverage to use this option; do not + select it if you are using original SuperH hardware. + config SH_SOLUTION_ENGINE bool "SolutionEngine" select SOLUTION_ENGINE diff --git a/arch/sh/boards/Makefile b/arch/sh/boards/Makefile index 975a0f64ff20..cea300362035 100644 --- a/arch/sh/boards/Makefile +++ b/arch/sh/boards/Makefile @@ -15,3 +15,5 @@ obj-$(CONFIG_SH_TITAN) += board-titan.o obj-$(CONFIG_SH_SH7757LCR) += board-sh7757lcr.o obj-$(CONFIG_SH_APSH4A3A) += board-apsh4a3a.o obj-$(CONFIG_SH_APSH4AD0A) += board-apsh4ad0a.o + +obj-$(CONFIG_SH_DEVICE_TREE) += of-generic.o diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c new file mode 100644 index 000000000000..bf3a166a5407 --- /dev/null +++ b/arch/sh/boards/of-generic.c @@ -0,0 +1,196 @@ +/* + * SH generic board support, using device tree + * + * Copyright (C) 2015-2016 Smart Energy Instruments, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SMP + +static void dummy_smp_setup(void) +{ +} + +static void dummy_prepare_cpus(unsigned int max_cpus) +{ +} + +static void dummy_start_cpu(unsigned int cpu, unsigned long entry_point) +{ +} + +static unsigned int dummy_smp_processor_id(void) +{ + return 0; +} + +static void dummy_send_ipi(unsigned int cpu, unsigned int message) +{ +} + +static struct plat_smp_ops dummy_smp_ops = { + .smp_setup = dummy_smp_setup, + .prepare_cpus = dummy_prepare_cpus, + .start_cpu = dummy_start_cpu, + .smp_processor_id = dummy_smp_processor_id, + .send_ipi = dummy_send_ipi, + .cpu_die = native_cpu_die, + .cpu_disable = native_cpu_disable, + .play_dead = native_play_dead, +}; + +extern const struct of_cpu_method __cpu_method_of_table[]; +const struct of_cpu_method __cpu_method_of_table_sentinel + __section(__cpu_method_of_table_end); + +static void sh_of_smp_probe(void) +{ + struct device_node *np = 0; + const char *method = 0; + const struct of_cpu_method *m = __cpu_method_of_table; + + pr_info("SH generic board support: scanning for cpus\n"); + + init_cpu_possible(cpumask_of(0)); + + while ((np = of_find_node_by_type(np, "cpu"))) { + const __be32 *cell = of_get_property(np, "reg", NULL); + u64 id = -1; + if (cell) id = of_read_number(cell, of_n_addr_cells(np)); + if (id < NR_CPUS) { + if (!method) + of_property_read_string(np, "enable-method", &method); + set_cpu_possible(id, true); + set_cpu_present(id, true); + __cpu_number_map[id] = id; + __cpu_logical_map[id] = id; + } + } + if (!method) { + np = of_find_node_by_name(NULL, "cpus"); + of_property_read_string(np, "enable-method", &method); + } + + pr_info("CPU enable method: %s\n", method); + if (method) + for (; m->method; m++) + if (!strcmp(m->method, method)) { + register_smp_ops(m->ops); + return; + } + + register_smp_ops(&dummy_smp_ops); +} + +#else + +static void sh_of_smp_probe(void) +{ +} + +#endif + +static void noop(void) +{ +} + +static int noopi(void) +{ + return 0; +} + +static void __init sh_of_mem_reserve(void) +{ + early_init_fdt_reserve_self(); + early_init_fdt_scan_reserved_mem(); +} + +static void __init sh_of_time_init(void) +{ + pr_info("SH generic board support: scanning for clocksource devices\n"); + clocksource_probe(); +} + +static void __init sh_of_setup(char **cmdline_p) +{ + unflatten_device_tree(); + + board_time_init = sh_of_time_init; + + sh_mv.mv_name = of_flat_dt_get_machine_name(); + if (!sh_mv.mv_name) + sh_mv.mv_name = "Unknown SH model"; + + sh_of_smp_probe(); +} + +static int sh_of_irq_demux(int irq) +{ + /* FIXME: eventually this should not be used at all; + * the interrupt controller should set_handle_irq(). */ + return irq; +} + +static void __init sh_of_init_irq(void) +{ + pr_info("SH generic board support: scanning for interrupt controllers\n"); + irqchip_init(); +} + +static int __init sh_of_clk_init(void) +{ +#ifdef CONFIG_COMMON_CLK + /* Disabled pending move to COMMON_CLK framework. */ + pr_info("SH generic board support: scanning for clk providers\n"); + of_clk_init(NULL); +#endif + return 0; +} + +static struct sh_machine_vector __initmv sh_of_generic_mv = { + .mv_setup = sh_of_setup, + .mv_name = "devicetree", /* replaced by DT root's model */ + .mv_irq_demux = sh_of_irq_demux, + .mv_init_irq = sh_of_init_irq, + .mv_clk_init = sh_of_clk_init, + .mv_mode_pins = noopi, + .mv_mem_init = noop, + .mv_mem_reserve = sh_of_mem_reserve, +}; + +struct sh_clk_ops; + +void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx) +{ +} + +void __init plat_irq_setup(void) +{ +} + +static int __init sh_of_device_init(void) +{ + pr_info("SH generic board support: populating platform devices\n"); + if (of_have_populated_dt()) { + of_iommu_init(); + of_platform_populate(NULL, of_default_bus_match_table, + NULL, NULL); + } else { + pr_crit("Device tree not populated\n"); + } + return 0; +} +arch_initcall_sync(sh_of_device_init); diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile index 23bc849d9c64..6df826ee7316 100644 --- a/arch/sh/boot/compressed/Makefile +++ b/arch/sh/boot/compressed/Makefile @@ -48,7 +48,7 @@ ifeq ($(BITS),64) lib1funcs-dir := $(addsuffix $(BITS), $(lib1funcs-dir)) endif -KBUILD_CFLAGS += -I$(lib1funcs-dir) +KBUILD_CFLAGS += -I$(lib1funcs-dir) -DDISABLE_BRANCH_PROFILING $(addprefix $(obj)/,$(lib1funcs-y)): $(obj)/%: $(lib1funcs-dir)/% FORCE $(call cmd,shipped) diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index aac452b26aa8..a319745a7b63 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild @@ -1,5 +1,6 @@ generic-y += bitsperlong.h +generic-y += clkdev.h generic-y += cputime.h generic-y += current.h generic-y += delay.h diff --git a/arch/sh/include/asm/clkdev.h b/arch/sh/include/asm/clkdev.h deleted file mode 100644 index c41901465fb0..000000000000 --- a/arch/sh/include/asm/clkdev.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2010 Paul Mundt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Helper for the clk API to assist looking up a struct clk. - */ - -#ifndef __CLKDEV__H_ -#define __CLKDEV__H_ - -#include -#include -#include - -#include - -static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) -{ - if (!slab_is_available()) - return alloc_bootmem_low_pages(size); - else - return kzalloc(size, GFP_KERNEL); -} - -#ifndef CONFIG_COMMON_CLK -#define __clk_put(clk) -#define __clk_get(clk) ({ 1; }) -#endif - -#endif /* __CLKDEV_H__ */ diff --git a/arch/sh/include/asm/smp.h b/arch/sh/include/asm/smp.h index 78b0d0f4b24b..1baf0ba96242 100644 --- a/arch/sh/include/asm/smp.h +++ b/arch/sh/include/asm/smp.h @@ -69,6 +69,16 @@ static inline int hard_smp_processor_id(void) return mp_ops->smp_processor_id(); } +struct of_cpu_method { + const char *method; + struct plat_smp_ops *ops; +}; + +#define CPU_METHOD_OF_DECLARE(name, _method, _ops) \ + static const struct of_cpu_method __cpu_method_of_table_##name \ + __used __section(__cpu_method_of_table) \ + = { .method = _method, .ops = _ops } + #else #define hard_smp_processor_id() (0) diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 2ccf36c824c6..09040fd07d2e 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -46,6 +46,5 @@ obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_callchain.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o -obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o ccflags-y := -Werror diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S index c8a4331d9b8d..a1505956ef28 100644 --- a/arch/sh/kernel/cpu/sh2/entry.S +++ b/arch/sh/kernel/cpu/sh2/entry.S @@ -144,9 +144,9 @@ ENTRY(exception_handler) mov #64,r8 cmp/hs r8,r9 bt interrupt_entry ! vec >= 64 is interrupt - mov #32,r8 + mov #31,r8 cmp/hs r8,r9 - bt trap_entry ! 64 > vec >= 32 is trap + bt trap_entry ! 64 > vec >= 31 is trap mov.l 4f,r8 mov r9,r4 @@ -178,9 +178,9 @@ interrupt_entry: trap_entry: mov #0x30,r8 - cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall + cmp/ge r8,r9 ! vector 0x1f-0x2f is systemcall bt 1f - add #-0x10,r9 ! convert SH2 to SH3/4 ABI + mov #0x1f,r9 ! convert to unified SH2/3/4 trap number 1: shll2 r9 ! TRA bra system_call ! jump common systemcall entry diff --git a/arch/sh/kernel/cpu/sh2a/entry.S b/arch/sh/kernel/cpu/sh2a/entry.S index 222742ddc0d6..da77a8ef4696 100644 --- a/arch/sh/kernel/cpu/sh2a/entry.S +++ b/arch/sh/kernel/cpu/sh2a/entry.S @@ -109,9 +109,9 @@ ENTRY(exception_handler) mov #64,r8 cmp/hs r8,r9 bt interrupt_entry ! vec >= 64 is interrupt - mov #32,r8 + mov #31,r8 cmp/hs r8,r9 - bt trap_entry ! 64 > vec >= 32 is trap + bt trap_entry ! 64 > vec >= 31 is trap mov.l 4f,r8 mov r9,r4 @@ -143,9 +143,9 @@ interrupt_entry: trap_entry: mov #0x30,r8 - cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall + cmp/ge r8,r9 ! vector 0x1f-0x2f is systemcall bt 1f - add #-0x10,r9 ! convert SH2 to SH3/4 ABI + mov #0x1f,r9 ! convert to unified SH2/3/4 trap number 1: shll2 r9 ! TRA bra system_call ! jump common systemcall entry diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index 13047a4facd2..c001f782c5f1 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -268,20 +268,29 @@ debug_trap: * Syscall #: R3 * Arguments #0 to #3: R4--R7 * Arguments #4 to #6: R0, R1, R2 - * TRA: (number of arguments + ABI revision) x 4 + * TRA: See following table. * - * This code also handles delegating other traps to the BIOS/gdb stub - * according to: - * - * Trap number * (TRA>>2) Purpose * -------- ------- * 0x00-0x0f original SH-3/4 syscall ABI (not in general use). * 0x10-0x1f general SH-3/4 syscall ABI. - * 0x20-0x2f syscall ABI for SH-2 parts. + * 0x1f unified SH-2/3/4 syscall ABI (preferred). + * 0x20-0x2f original SH-2 syscall ABI. * 0x30-0x3f debug traps used by the kernel. * 0x40-0xff Not supported by all parts, so left unhandled. * + * For making system calls, any trap number in the range for the + * given cpu model may be used, but the unified trap number 0x1f is + * preferred for compatibility with all models. + * + * The low bits of the trap number were once documented as matching + * the number of arguments, but they were never actually used as such + * by the kernel. SH-2 originally used its own separate trap range + * because several hardware exceptions fell in the range used for the + * SH-3/4 syscall ABI. + * + * This code also handles delegating other traps to the BIOS/gdb stub. + * * Note: When we're first called, the TRA value must be shifted * right 2 bits in order to get the value that was used as the "trapa" * argument. diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S index 7db248936b60..974bc152cc84 100644 --- a/arch/sh/kernel/head_32.S +++ b/arch/sh/kernel/head_32.S @@ -66,6 +66,10 @@ ENTRY(_stext) mov #0, r0 ldc r0, r6_bank #endif + +#ifdef CONFIG_OF + mov r4, r12 ! Store device tree blob pointer in r12 +#endif /* * Prefetch if possible to reduce cache miss penalty. @@ -314,6 +318,12 @@ ENTRY(_stext) 10: #endif +#ifdef CONFIG_OF + mov.l 8f, r0 ! Make flat device tree available early. + jsr @r0 + mov r12, r4 +#endif + ! Additional CPU initialization mov.l 6f, r0 jsr @r0 @@ -339,6 +349,9 @@ ENTRY(stack_start) 5: .long start_kernel 6: .long cpu_init 7: .long init_thread_union +#if defined(CONFIG_OF) +8: .long sh_fdt_init +#endif #ifdef CONFIG_PMB .LPMB_ADDR: .long PMB_ADDR diff --git a/arch/sh/kernel/localtimer.c b/arch/sh/kernel/localtimer.c deleted file mode 100644 index cbb7d4636ec0..000000000000 --- a/arch/sh/kernel/localtimer.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Dummy local timer - * - * Copyright (C) 2008 Paul Mundt - * - * cloned from: - * - * linux/arch/arm/mach-realview/localtimer.c - * - * Copyright (C) 2002 ARM Ltd. - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static DEFINE_PER_CPU(struct clock_event_device, local_clockevent); - -/* - * Used on SMP for either the local timer or SMP_MSG_TIMER - */ -void local_timer_interrupt(void) -{ - struct clock_event_device *clk = this_cpu_ptr(&local_clockevent); - - irq_enter(); - clk->event_handler(clk); - irq_exit(); -} - -void local_timer_setup(unsigned int cpu) -{ - struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); - - clk->name = "dummy_timer"; - clk->features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_DUMMY; - clk->rating = 400; - clk->mult = 1; - clk->broadcast = smp_timer_broadcast; - clk->cpumask = cpumask_of(cpu); - - clockevents_register_device(clk); -} - -void local_timer_stop(unsigned int cpu) -{ -} diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 3f1c18b28e8a..5d34605b58b5 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -172,6 +174,7 @@ void __init check_for_initrd(void) #endif } +#ifndef CONFIG_GENERIC_CALIBRATE_DELAY void calibrate_delay(void) { struct clk *clk = clk_get(NULL, "cpu_clk"); @@ -187,6 +190,7 @@ void calibrate_delay(void) (loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy); } +#endif void __init __add_active_range(unsigned int nid, unsigned long start_pfn, unsigned long end_pfn) @@ -238,6 +242,29 @@ void __init __weak plat_early_device_setup(void) { } +#ifdef CONFIG_OF +void __ref sh_fdt_init(phys_addr_t dt_phys) +{ + static int done = 0; + void *dt_virt; + + /* Avoid calling an __init function on secondary cpus. */ + if (done) return; + + dt_virt = phys_to_virt(dt_phys); + + if (!dt_virt || !early_init_dt_scan(dt_virt)) { + pr_crit("Error: invalid device tree blob" + " at physical address %p\n", (void *)dt_phys); + + while (true) + cpu_relax(); + } + + done = 1; +} +#endif + void __init setup_arch(char **cmdline_p) { enable_mmu(); diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index d77f2f6c7ff0..0b30b9dfc87f 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -34,6 +34,9 @@ DECLARE_EXPORT(__sdivsi3); DECLARE_EXPORT(__lshrsi3); DECLARE_EXPORT(__ashrsi3); DECLARE_EXPORT(__ashlsi3); +DECLARE_EXPORT(__lshrsi3_r0); +DECLARE_EXPORT(__ashrsi3_r0); +DECLARE_EXPORT(__ashlsi3_r0); DECLARE_EXPORT(__ashiftrt_r4_6); DECLARE_EXPORT(__ashiftrt_r4_7); DECLARE_EXPORT(__ashiftrt_r4_8); diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 13f633add29a..38e7860845db 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -140,17 +141,14 @@ int __cpu_disable(void) */ migrate_irqs(); - /* - * Stop the local timer for this CPU. - */ - local_timer_stop(cpu); - /* * Flush user cache and TLB mappings, and then remove this CPU * from the vm mask set of all processes. */ flush_cache_all(); +#ifdef CONFIG_MMU local_flush_tlb_all(); +#endif clear_tasks_mm_cpumask(cpu); @@ -183,8 +181,10 @@ asmlinkage void start_secondary(void) atomic_inc(&mm->mm_count); atomic_inc(&mm->mm_users); current->active_mm = mm; +#ifdef CONFIG_MMU enter_lazy_tlb(mm, current); local_flush_tlb_all(); +#endif per_cpu_trap_init(); @@ -194,8 +194,6 @@ asmlinkage void start_secondary(void) local_irq_enable(); - /* Enable local timers */ - local_timer_setup(cpu); calibrate_delay(); smp_store_cpu_info(cpu); @@ -285,7 +283,8 @@ void arch_send_call_function_single_ipi(int cpu) mp_ops->send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE); } -void smp_timer_broadcast(const struct cpumask *mask) +#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST +void tick_broadcast(const struct cpumask *mask) { int cpu; @@ -296,9 +295,10 @@ void smp_timer_broadcast(const struct cpumask *mask) static void ipi_timer(void) { irq_enter(); - local_timer_interrupt(); + tick_receive_broadcast(); irq_exit(); } +#endif void smp_message_recv(unsigned int msg) { @@ -312,9 +312,11 @@ void smp_message_recv(unsigned int msg) case SMP_MSG_FUNCTION_SINGLE: generic_smp_call_function_single_interrupt(); break; +#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST case SMP_MSG_TIMER: ipi_timer(); break; +#endif default: printk(KERN_WARNING "SMP %d: %s(): unknown IPI %d\n", smp_processor_id(), __func__, msg); @@ -328,6 +330,8 @@ int setup_profiling_timer(unsigned int multiplier) return 0; } +#ifdef CONFIG_MMU + static void flush_tlb_all_ipi(void *info) { local_flush_tlb_all(); @@ -467,3 +471,5 @@ void flush_tlb_one(unsigned long asid, unsigned long vaddr) smp_call_function(flush_tlb_one_ipi, (void *)&fd, 1); local_flush_tlb_one(asid, vaddr); } + +#endif diff --git a/arch/sh/lib/ashlsi3.S b/arch/sh/lib/ashlsi3.S index bd47e9b403a5..70a6434945ab 100644 --- a/arch/sh/lib/ashlsi3.S +++ b/arch/sh/lib/ashlsi3.S @@ -54,21 +54,38 @@ Boston, MA 02110-1301, USA. */ ! ! (none) ! +! __ashlsi3_r0 +! +! Entry: +! +! r4: Value to shift +! r0: Shifts +! +! Exit: +! +! r0: Result +! +! Destroys: +! +! (none) + + .global __ashlsi3 + .global __ashlsi3_r0 .align 2 __ashlsi3: - mov #31,r0 - and r0,r5 + mov r5,r0 + .align 2 +__ashlsi3_r0: + and #31,r0 + mov.l r4,@-r15 + mov r0,r4 mova ashlsi3_table,r0 - mov.b @(r0,r5),r5 -#ifdef __sh1__ - add r5,r0 + mov.b @(r0,r4),r4 + add r4,r0 jmp @r0 -#else - braf r5 -#endif - mov r4,r0 + mov.l @r15+,r0 .align 2 ashlsi3_table: diff --git a/arch/sh/lib/ashrsi3.S b/arch/sh/lib/ashrsi3.S index 6f3cf46b77c2..602599d80209 100644 --- a/arch/sh/lib/ashrsi3.S +++ b/arch/sh/lib/ashrsi3.S @@ -54,22 +54,37 @@ Boston, MA 02110-1301, USA. */ ! ! (none) ! +! __ashrsi3_r0 +! +! Entry: +! +! r4: Value to shift +! r0: Shifts +! +! Exit: +! +! r0: Result +! +! Destroys: +! +! (none) .global __ashrsi3 + .global __ashrsi3_r0 .align 2 __ashrsi3: - mov #31,r0 - and r0,r5 + mov r5,r0 + .align 2 +__ashrsi3_r0: + and #31,r0 + mov.l r4,@-r15 + mov r0,r4 mova ashrsi3_table,r0 - mov.b @(r0,r5),r5 -#ifdef __sh1__ - add r5,r0 + mov.b @(r0,r4),r4 + add r4,r0 jmp @r0 -#else - braf r5 -#endif - mov r4,r0 + mov.l @r15+,r0 .align 2 ashrsi3_table: diff --git a/arch/sh/lib/lshrsi3.S b/arch/sh/lib/lshrsi3.S index 1e7aaa557130..f2a6959f526d 100644 --- a/arch/sh/lib/lshrsi3.S +++ b/arch/sh/lib/lshrsi3.S @@ -53,22 +53,38 @@ Boston, MA 02110-1301, USA. */ ! Destroys: ! ! (none) +! +! __lshrsi3_r0 +! +! Entry: +! +! r0: Value to shift +! r5: Shifts +! +! Exit: +! +! r0: Result +! +! Destroys: +! +! (none) ! .global __lshrsi3 + .global __lshrsi3_r0 .align 2 __lshrsi3: - mov #31,r0 - and r0,r5 + mov r5,r0 + .align 2 +__lshrsi3_r0: + and #31,r0 + mov.l r4,@-r15 + mov r0,r4 mova lshrsi3_table,r0 - mov.b @(r0,r5),r5 -#ifdef __sh1__ - add r5,r0 + mov.b @(r0,r4),r4 + add r4,r0 jmp @r0 -#else - braf r5 -#endif - mov r4,r0 + mov.l @r15+,r0 .align 2 lshrsi3_table: diff --git a/arch/sh/mm/kmap.c b/arch/sh/mm/kmap.c index ec29e14ec5a8..bf25d7c79a2d 100644 --- a/arch/sh/mm/kmap.c +++ b/arch/sh/mm/kmap.c @@ -36,6 +36,7 @@ void *kmap_coherent(struct page *page, unsigned long addr) BUG_ON(!test_bit(PG_dcache_clean, &page->flags)); + preempt_disable(); pagefault_disable(); idx = FIX_CMAP_END - @@ -64,4 +65,5 @@ void kunmap_coherent(void *kvaddr) } pagefault_enable(); + preempt_enable(); }