From 45d1564cceea8105c51b065acc8ec1312b81fbc1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 25 May 2011 11:10:59 +0200 Subject: m68knommu: Make empty_zero_page "void *", like on m68k This allows to get rid of the casts. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Ungerer diff --git a/arch/m68k/mm/init_no.c b/arch/m68k/mm/init_no.c index 7cbd7bd..fdbe679 100644 --- a/arch/m68k/mm/init_no.c +++ b/arch/m68k/mm/init_no.c @@ -42,7 +42,7 @@ * ZERO_PAGE is a special page that is used for zero-initialized * data and COW. */ -unsigned long empty_zero_page; +void *empty_zero_page; extern unsigned long memory_start; extern unsigned long memory_end; @@ -62,8 +62,8 @@ void __init paging_init(void) unsigned long end_mem = memory_end & PAGE_MASK; unsigned long zones_size[MAX_NR_ZONES] = {0, }; - empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); - memset((void *)empty_zero_page, 0, PAGE_SIZE); + empty_zero_page = alloc_bootmem_pages(PAGE_SIZE); + memset(empty_zero_page, 0, PAGE_SIZE); /* * Set up SFC/DFC registers (user data space). -- cgit v0.10.2 From 6617eaf33d04836d31ea687e79ba9fef02fdbbe9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 26 May 2011 14:44:10 +1000 Subject: m68knommu: Fix printk() format in free_initrd_mem() arch/m68k/mm/init_no.c:123: warning: format "%d" expects type "int", but argument 2 has type "long unsigned int" And use pr_notice() while we're at it. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Ungerer diff --git a/arch/m68k/mm/init_no.c b/arch/m68k/mm/init_no.c index fdbe679..50cd12c 100644 --- a/arch/m68k/mm/init_no.c +++ b/arch/m68k/mm/init_no.c @@ -120,7 +120,8 @@ void free_initrd_mem(unsigned long start, unsigned long end) totalram_pages++; pages++; } - printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages * (PAGE_SIZE / 1024)); + pr_notice("Freeing initrd memory: %luk freed\n", + pages * (PAGE_SIZE / 1024)); } #endif @@ -141,7 +142,7 @@ void free_initmem(void) free_page(addr); totalram_pages++; } - printk(KERN_NOTICE "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n", + pr_notice("Freeing unused kernel memory: %luk freed (0x%x - 0x%x)\n", (addr - PAGE_ALIGN((long) &__init_begin)) >> 10, (int)(PAGE_ALIGN((unsigned long)(&__init_begin))), (int)(addr - PAGE_SIZE)); -- cgit v0.10.2 From a66af29876b086d8279b48515b83ced66803fb15 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Tue, 29 Mar 2011 15:23:51 +1000 Subject: m68k: merge the non-mmu and mmu versions of module.c The non-mmu and mmu versions of the module loader module.c are nearly identical. Merge them back to a single module.c. There is a little bit of re-ordering of the struct and enum definitions in module.h to keep the ifdefery to a minimum. Signed-off-by: Greg Ungerer diff --git a/arch/m68k/include/asm/module.h b/arch/m68k/include/asm/module.h index 5f21e11..edffe66 100644 --- a/arch/m68k/include/asm/module.h +++ b/arch/m68k/include/asm/module.h @@ -1,46 +1,41 @@ #ifndef _ASM_M68K_MODULE_H #define _ASM_M68K_MODULE_H -#ifdef CONFIG_MMU +enum m68k_fixup_type { + m68k_fixup_memoffset, + m68k_fixup_vnode_shift, +}; + +struct m68k_fixup_info { + enum m68k_fixup_type type; + void *addr; +}; struct mod_arch_specific { struct m68k_fixup_info *fixup_start, *fixup_end; }; +#ifdef CONFIG_MMU + #define MODULE_ARCH_INIT { \ .fixup_start = __start_fixup, \ .fixup_end = __stop_fixup, \ } -enum m68k_fixup_type { - m68k_fixup_memoffset, - m68k_fixup_vnode_shift, -}; - -struct m68k_fixup_info { - enum m68k_fixup_type type; - void *addr; -}; - #define m68k_fixup(type, addr) \ " .section \".m68k_fixup\",\"aw\"\n" \ " .long " #type "," #addr "\n" \ " .previous\n" +#endif /* CONFIG_MMU */ + extern struct m68k_fixup_info __start_fixup[], __stop_fixup[]; struct module; extern void module_fixup(struct module *mod, struct m68k_fixup_info *start, struct m68k_fixup_info *end); -#else - -struct mod_arch_specific { -}; - -#endif /* CONFIG_MMU */ - #define Elf_Shdr Elf32_Shdr #define Elf_Sym Elf32_Sym #define Elf_Ehdr Elf32_Ehdr diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c index 7ea203c..34849c4 100644 --- a/arch/m68k/kernel/module.c +++ b/arch/m68k/kernel/module.c @@ -1,5 +1,129 @@ -#ifdef CONFIG_MMU -#include "module_mm.c" +/* + * 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 + +#if 0 +#define DEBUGP printk #else -#include "module_no.c" +#define DEBUGP(fmt...) +#endif + +#ifdef CONFIG_MODULES + +int apply_relocate(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_68K_32: + /* We add the value into the location given */ + *location += sym->st_value; + break; + case R_68K_PC32: + /* Add the value, subtract its postition */ + *location += sym->st_value - (uint32_t)location; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + + DEBUGP("Applying relocate_add section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_68K_32: + /* We add the value into the location given */ + *location = rel[i].r_addend + sym->st_value; + break; + case R_68K_PC32: + /* Add the value, subtract its postition */ + *location = rel[i].r_addend + sym->st_value - (uint32_t)location; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *mod) +{ + module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end); + return 0; +} + +#endif /* CONFIG_MODULES */ + +void module_fixup(struct module *mod, struct m68k_fixup_info *start, + struct m68k_fixup_info *end) +{ +#ifdef CONFIG_MMU + struct m68k_fixup_info *fixup; + + for (fixup = start; fixup < end; fixup++) { + switch (fixup->type) { + case m68k_fixup_memoffset: + *(u32 *)fixup->addr = m68k_memoffset; + break; + case m68k_fixup_vnode_shift: + *(u16 *)fixup->addr += m68k_virt_to_node_shift; + break; + } + } #endif +} diff --git a/arch/m68k/kernel/module_mm.c b/arch/m68k/kernel/module_mm.c deleted file mode 100644 index ceafc47..0000000 --- a/arch/m68k/kernel/module_mm.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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 - -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(fmt...) -#endif - -#ifdef CONFIG_MODULES - -int apply_relocate(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; - Elf32_Sym *sym; - uint32_t *location; - - DEBUGP("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rel[i].r_info); - - switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_68K_32: - /* We add the value into the location given */ - *location += sym->st_value; - break; - case R_68K_PC32: - /* Add the value, subtract its postition */ - *location += sym->st_value - (uint32_t)location; - break; - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } - } - return 0; -} - -int apply_relocate_add(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; - Elf32_Sym *sym; - uint32_t *location; - - DEBUGP("Applying relocate_add section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rel[i].r_info); - - switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_68K_32: - /* We add the value into the location given */ - *location = rel[i].r_addend + sym->st_value; - break; - case R_68K_PC32: - /* Add the value, subtract its postition */ - *location = rel[i].r_addend + sym->st_value - (uint32_t)location; - break; - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } - } - return 0; -} - -int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *mod) -{ - module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end); - - return 0; -} - -#endif /* CONFIG_MODULES */ - -void module_fixup(struct module *mod, struct m68k_fixup_info *start, - struct m68k_fixup_info *end) -{ - struct m68k_fixup_info *fixup; - - for (fixup = start; fixup < end; fixup++) { - switch (fixup->type) { - case m68k_fixup_memoffset: - *(u32 *)fixup->addr = m68k_memoffset; - break; - case m68k_fixup_vnode_shift: - *(u16 *)fixup->addr += m68k_virt_to_node_shift; - break; - } - } -} diff --git a/arch/m68k/kernel/module_no.c b/arch/m68k/kernel/module_no.c deleted file mode 100644 index 5a097c6..0000000 --- a/arch/m68k/kernel/module_no.c +++ /dev/null @@ -1,92 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(fmt...) -#endif - -int apply_relocate(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; - Elf32_Sym *sym; - uint32_t *location; - - DEBUGP("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rel[i].r_info); - - switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_68K_32: - /* We add the value into the location given */ - *location += sym->st_value; - break; - case R_68K_PC32: - /* Add the value, subtract its postition */ - *location += sym->st_value - (uint32_t)location; - break; - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } - } - return 0; -} - -int apply_relocate_add(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; - Elf32_Sym *sym; - uint32_t *location; - - DEBUGP("Applying relocate_add section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rel[i].r_info); - - switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_68K_32: - /* We add the value into the location given */ - *location = rel[i].r_addend + sym->st_value; - break; - case R_68K_PC32: - /* Add the value, subtract its postition */ - *location = rel[i].r_addend + sym->st_value - (uint32_t)location; - break; - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } - } - return 0; -} -- cgit v0.10.2 From 10f939ff3ab80514da3bd96357bb54a8a59b9225 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Wed, 4 May 2011 13:55:56 +1000 Subject: m68k: merge MMU and non-MMU versions of asm/hardirq.h The contents of asm/hardirq.h are pretty strait forward for both the MMU (hardirq_mm.h) and non-MMU (hardirq_no.h) include files. Merge the two back into a single file. Signed-off-by: Greg Ungerer diff --git a/arch/m68k/include/asm/hardirq.h b/arch/m68k/include/asm/hardirq.h index 56d0d5d..870e534 100644 --- a/arch/m68k/include/asm/hardirq.h +++ b/arch/m68k/include/asm/hardirq.h @@ -1,5 +1,34 @@ -#ifdef __uClinux__ -#include "hardirq_no.h" +#ifndef __M68K_HARDIRQ_H +#define __M68K_HARDIRQ_H + +#include +#include +#include + +#define HARDIRQ_BITS 8 + +/* + * The hardirq mask has to be large enough to have + * space for potentially all IRQ sources in the system + * nesting on a single CPU: + */ +#if (1 << HARDIRQ_BITS) < NR_IRQS +# error HARDIRQ_BITS is too low! +#endif + +#ifdef CONFIG_MMU + +/* entry.S is sensitive to the offsets of these fields */ +typedef struct { + unsigned int __softirq_pending; +} ____cacheline_aligned irq_cpustat_t; + +#include /* Standard mappings for irq_cpustat_t above */ + #else -#include "hardirq_mm.h" + +#include + +#endif /* !CONFIG_MMU */ + #endif diff --git a/arch/m68k/include/asm/hardirq_mm.h b/arch/m68k/include/asm/hardirq_mm.h deleted file mode 100644 index 394ee94..0000000 --- a/arch/m68k/include/asm/hardirq_mm.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __M68K_HARDIRQ_H -#define __M68K_HARDIRQ_H - -#include -#include - -/* entry.S is sensitive to the offsets of these fields */ -typedef struct { - unsigned int __softirq_pending; -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - -#define HARDIRQ_BITS 8 - -#endif diff --git a/arch/m68k/include/asm/hardirq_no.h b/arch/m68k/include/asm/hardirq_no.h deleted file mode 100644 index b44b14b..0000000 --- a/arch/m68k/include/asm/hardirq_no.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __M68K_HARDIRQ_H -#define __M68K_HARDIRQ_H - -#include - -#define HARDIRQ_BITS 8 - -/* - * The hardirq mask has to be large enough to have - * space for potentially all IRQ sources in the system - * nesting on a single CPU: - */ -#if (1 << HARDIRQ_BITS) < NR_IRQS -# error HARDIRQ_BITS is too low! -#endif - -#include - -#endif /* __M68K_HARDIRQ_H */ diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 907eff1..67c9738 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -33,15 +33,6 @@ #include /* - * The hardirq mask has to be large enough to have - * space for potentially all IRQ sources in the system - * nesting on a single CPU: - */ -#if (1 << HARDIRQ_BITS) < NR_IRQS -# error HARDIRQ_BITS is too low! -#endif - -/* * Interrupt source definitions * General interrupt sources are the level 1-7. * Adding an interrupt service routine for one of these sources -- cgit v0.10.2 From f941f5caa0e947f4ed060a751ca4a3bf552af625 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Thu, 5 May 2011 22:32:12 +1000 Subject: m68k: merge MMU and non MMU versions of system.h The non-MMU m68k targets can use the same asm/system.h as the MMU targets. So switch the current system_mm.h to be system.h and remove system_no.h. The assembly support code for the non-MMU resume functions needs to be modified to match the now common switch_to() macro. Specifically this means correctly saving and restoring the status flags in the case of the ColdFire resume, and some reordering of the code to not use registers before they are saved or after they are restored. Signed-off-by: Greg Ungerer diff --git a/arch/m68k/include/asm/entry_no.h b/arch/m68k/include/asm/entry_no.h index 627d69b..68611e3 100644 --- a/arch/m68k/include/asm/entry_no.h +++ b/arch/m68k/include/asm/entry_no.h @@ -96,11 +96,11 @@ .endm .macro RDUSP - movel sw_usp,%a2 + movel sw_usp,%a3 .endm .macro WRUSP - movel %a0,sw_usp + movel %a3,sw_usp .endm #else /* !CONFIG_COLDFIRE_SW_A7 */ @@ -127,13 +127,13 @@ .endm .macro RDUSP - /*move %usp,%a2*/ - .word 0x4e6a + /*move %usp,%a3*/ + .word 0x4e6b .endm .macro WRUSP - /*move %a0,%usp*/ - .word 0x4e60 + /*move %a3,%usp*/ + .word 0x4e63 .endm #endif /* !CONFIG_COLDFIRE_SW_A7 */ diff --git a/arch/m68k/include/asm/system.h b/arch/m68k/include/asm/system.h index ccea925..47b01f47 100644 --- a/arch/m68k/include/asm/system.h +++ b/arch/m68k/include/asm/system.h @@ -1,5 +1,193 @@ -#ifdef __uClinux__ -#include "system_no.h" +#ifndef _M68K_SYSTEM_H +#define _M68K_SYSTEM_H + +#include +#include +#include +#include +#include + +#ifdef __KERNEL__ + +/* + * switch_to(n) should switch tasks to task ptr, first checking that + * ptr isn't the current task, in which case it does nothing. This + * also clears the TS-flag if the task we switched to has used the + * math co-processor latest. + */ +/* + * switch_to() saves the extra registers, that are not saved + * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and + * a0-a1. Some of these are used by schedule() and its predecessors + * and so we might get see unexpected behaviors when a task returns + * with unexpected register values. + * + * syscall stores these registers itself and none of them are used + * by syscall after the function in the syscall has been called. + * + * Beware that resume now expects *next to be in d1 and the offset of + * tss to be in a1. This saves a few instructions as we no longer have + * to push them onto the stack and read them back right after. + * + * 02/17/96 - Jes Sorensen (jds@kom.auc.dk) + * + * Changed 96/09/19 by Andreas Schwab + * pass prev in a0, next in a1 + */ +asmlinkage void resume(void); +#define switch_to(prev,next,last) do { \ + register void *_prev __asm__ ("a0") = (prev); \ + register void *_next __asm__ ("a1") = (next); \ + register void *_last __asm__ ("d1"); \ + __asm__ __volatile__("jbsr resume" \ + : "=a" (_prev), "=a" (_next), "=d" (_last) \ + : "0" (_prev), "1" (_next) \ + : "d0", "d2", "d3", "d4", "d5"); \ + (last) = _last; \ +} while (0) + + +/* + * Force strict CPU ordering. + * Not really required on m68k... + */ +#define nop() do { asm volatile ("nop"); barrier(); } while (0) +#define mb() barrier() +#define rmb() barrier() +#define wmb() barrier() +#define read_barrier_depends() ((void)0) +#define set_mb(var, value) ({ (var) = (value); wmb(); }) + +#define smp_mb() barrier() +#define smp_rmb() barrier() +#define smp_wmb() barrier() +#define smp_read_barrier_depends() ((void)0) + +#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) + +struct __xchg_dummy { unsigned long a[100]; }; +#define __xg(x) ((volatile struct __xchg_dummy *)(x)) + +#ifndef CONFIG_RMW_INSNS +static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) +{ + unsigned long flags, tmp; + + local_irq_save(flags); + + switch (size) { + case 1: + tmp = *(u8 *)ptr; + *(u8 *)ptr = x; + x = tmp; + break; + case 2: + tmp = *(u16 *)ptr; + *(u16 *)ptr = x; + x = tmp; + break; + case 4: + tmp = *(u32 *)ptr; + *(u32 *)ptr = x; + x = tmp; + break; + default: + BUG(); + } + + local_irq_restore(flags); + return x; +} #else -#include "system_mm.h" +static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) +{ + switch (size) { + case 1: + __asm__ __volatile__ + ("moveb %2,%0\n\t" + "1:\n\t" + "casb %0,%1,%2\n\t" + "jne 1b" + : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); + break; + case 2: + __asm__ __volatile__ + ("movew %2,%0\n\t" + "1:\n\t" + "casw %0,%1,%2\n\t" + "jne 1b" + : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); + break; + case 4: + __asm__ __volatile__ + ("movel %2,%0\n\t" + "1:\n\t" + "casl %0,%1,%2\n\t" + "jne 1b" + : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); + break; + } + return x; +} #endif + +#include + +#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) + +/* + * Atomic compare and exchange. Compare OLD with MEM, if identical, + * store NEW in MEM. Return the initial value in MEM. Success is + * indicated by comparing RETURN with OLD. + */ +#ifdef CONFIG_RMW_INSNS +#define __HAVE_ARCH_CMPXCHG 1 + +static inline unsigned long __cmpxchg(volatile void *p, unsigned long old, + unsigned long new, int size) +{ + switch (size) { + case 1: + __asm__ __volatile__ ("casb %0,%2,%1" + : "=d" (old), "=m" (*(char *)p) + : "d" (new), "0" (old), "m" (*(char *)p)); + break; + case 2: + __asm__ __volatile__ ("casw %0,%2,%1" + : "=d" (old), "=m" (*(short *)p) + : "d" (new), "0" (old), "m" (*(short *)p)); + break; + case 4: + __asm__ __volatile__ ("casl %0,%2,%1" + : "=d" (old), "=m" (*(int *)p) + : "d" (new), "0" (old), "m" (*(int *)p)); + break; + } + return old; +} + +#define cmpxchg(ptr, o, n) \ + ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ + (unsigned long)(n), sizeof(*(ptr)))) +#define cmpxchg_local(ptr, o, n) \ + ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ + (unsigned long)(n), sizeof(*(ptr)))) +#else + +/* + * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make + * them available. + */ +#define cmpxchg_local(ptr, o, n) \ + ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\ + (unsigned long)(n), sizeof(*(ptr)))) + +#include + +#endif + +#define arch_align_stack(x) (x) + +#endif /* __KERNEL__ */ + +#endif /* _M68K_SYSTEM_H */ diff --git a/arch/m68k/include/asm/system_mm.h b/arch/m68k/include/asm/system_mm.h deleted file mode 100644 index 47b01f47..0000000 --- a/arch/m68k/include/asm/system_mm.h +++ /dev/null @@ -1,193 +0,0 @@ -#ifndef _M68K_SYSTEM_H -#define _M68K_SYSTEM_H - -#include -#include -#include -#include -#include - -#ifdef __KERNEL__ - -/* - * switch_to(n) should switch tasks to task ptr, first checking that - * ptr isn't the current task, in which case it does nothing. This - * also clears the TS-flag if the task we switched to has used the - * math co-processor latest. - */ -/* - * switch_to() saves the extra registers, that are not saved - * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and - * a0-a1. Some of these are used by schedule() and its predecessors - * and so we might get see unexpected behaviors when a task returns - * with unexpected register values. - * - * syscall stores these registers itself and none of them are used - * by syscall after the function in the syscall has been called. - * - * Beware that resume now expects *next to be in d1 and the offset of - * tss to be in a1. This saves a few instructions as we no longer have - * to push them onto the stack and read them back right after. - * - * 02/17/96 - Jes Sorensen (jds@kom.auc.dk) - * - * Changed 96/09/19 by Andreas Schwab - * pass prev in a0, next in a1 - */ -asmlinkage void resume(void); -#define switch_to(prev,next,last) do { \ - register void *_prev __asm__ ("a0") = (prev); \ - register void *_next __asm__ ("a1") = (next); \ - register void *_last __asm__ ("d1"); \ - __asm__ __volatile__("jbsr resume" \ - : "=a" (_prev), "=a" (_next), "=d" (_last) \ - : "0" (_prev), "1" (_next) \ - : "d0", "d2", "d3", "d4", "d5"); \ - (last) = _last; \ -} while (0) - - -/* - * Force strict CPU ordering. - * Not really required on m68k... - */ -#define nop() do { asm volatile ("nop"); barrier(); } while (0) -#define mb() barrier() -#define rmb() barrier() -#define wmb() barrier() -#define read_barrier_depends() ((void)0) -#define set_mb(var, value) ({ (var) = (value); wmb(); }) - -#define smp_mb() barrier() -#define smp_rmb() barrier() -#define smp_wmb() barrier() -#define smp_read_barrier_depends() ((void)0) - -#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) - -struct __xchg_dummy { unsigned long a[100]; }; -#define __xg(x) ((volatile struct __xchg_dummy *)(x)) - -#ifndef CONFIG_RMW_INSNS -static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) -{ - unsigned long flags, tmp; - - local_irq_save(flags); - - switch (size) { - case 1: - tmp = *(u8 *)ptr; - *(u8 *)ptr = x; - x = tmp; - break; - case 2: - tmp = *(u16 *)ptr; - *(u16 *)ptr = x; - x = tmp; - break; - case 4: - tmp = *(u32 *)ptr; - *(u32 *)ptr = x; - x = tmp; - break; - default: - BUG(); - } - - local_irq_restore(flags); - return x; -} -#else -static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) -{ - switch (size) { - case 1: - __asm__ __volatile__ - ("moveb %2,%0\n\t" - "1:\n\t" - "casb %0,%1,%2\n\t" - "jne 1b" - : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); - break; - case 2: - __asm__ __volatile__ - ("movew %2,%0\n\t" - "1:\n\t" - "casw %0,%1,%2\n\t" - "jne 1b" - : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); - break; - case 4: - __asm__ __volatile__ - ("movel %2,%0\n\t" - "1:\n\t" - "casl %0,%1,%2\n\t" - "jne 1b" - : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); - break; - } - return x; -} -#endif - -#include - -#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) - -/* - * Atomic compare and exchange. Compare OLD with MEM, if identical, - * store NEW in MEM. Return the initial value in MEM. Success is - * indicated by comparing RETURN with OLD. - */ -#ifdef CONFIG_RMW_INSNS -#define __HAVE_ARCH_CMPXCHG 1 - -static inline unsigned long __cmpxchg(volatile void *p, unsigned long old, - unsigned long new, int size) -{ - switch (size) { - case 1: - __asm__ __volatile__ ("casb %0,%2,%1" - : "=d" (old), "=m" (*(char *)p) - : "d" (new), "0" (old), "m" (*(char *)p)); - break; - case 2: - __asm__ __volatile__ ("casw %0,%2,%1" - : "=d" (old), "=m" (*(short *)p) - : "d" (new), "0" (old), "m" (*(short *)p)); - break; - case 4: - __asm__ __volatile__ ("casl %0,%2,%1" - : "=d" (old), "=m" (*(int *)p) - : "d" (new), "0" (old), "m" (*(int *)p)); - break; - } - return old; -} - -#define cmpxchg(ptr, o, n) \ - ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr)))) -#define cmpxchg_local(ptr, o, n) \ - ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr)))) -#else - -/* - * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make - * them available. - */ -#define cmpxchg_local(ptr, o, n) \ - ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\ - (unsigned long)(n), sizeof(*(ptr)))) - -#include - -#endif - -#define arch_align_stack(x) (x) - -#endif /* __KERNEL__ */ - -#endif /* _M68K_SYSTEM_H */ diff --git a/arch/m68k/include/asm/system_no.h b/arch/m68k/include/asm/system_no.h deleted file mode 100644 index 6fe9f93..0000000 --- a/arch/m68k/include/asm/system_no.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef _M68KNOMMU_SYSTEM_H -#define _M68KNOMMU_SYSTEM_H - -#include -#include -#include -#include - -/* - * switch_to(n) should switch tasks to task ptr, first checking that - * ptr isn't the current task, in which case it does nothing. This - * also clears the TS-flag if the task we switched to has used the - * math co-processor latest. - */ -/* - * switch_to() saves the extra registers, that are not saved - * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and - * a0-a1. Some of these are used by schedule() and its predecessors - * and so we might get see unexpected behaviors when a task returns - * with unexpected register values. - * - * syscall stores these registers itself and none of them are used - * by syscall after the function in the syscall has been called. - * - * Beware that resume now expects *next to be in d1 and the offset of - * tss to be in a1. This saves a few instructions as we no longer have - * to push them onto the stack and read them back right after. - * - * 02/17/96 - Jes Sorensen (jds@kom.auc.dk) - * - * Changed 96/09/19 by Andreas Schwab - * pass prev in a0, next in a1, offset of tss in d1, and whether - * the mm structures are shared in d2 (to avoid atc flushing). - */ -asmlinkage void resume(void); -#define switch_to(prev,next,last) \ -{ \ - void *_last; \ - __asm__ __volatile__( \ - "movel %1, %%a0\n\t" \ - "movel %2, %%a1\n\t" \ - "jbsr resume\n\t" \ - "movel %%d1, %0\n\t" \ - : "=d" (_last) \ - : "d" (prev), "d" (next) \ - : "cc", "d0", "d1", "d2", "d3", "d4", "d5", "a0", "a1"); \ - (last) = _last; \ -} - -#define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc") - -/* - * Force strict CPU ordering. - * Not really required on m68k... - */ -#define nop() asm volatile ("nop"::) -#define mb() asm volatile ("" : : :"memory") -#define rmb() asm volatile ("" : : :"memory") -#define wmb() asm volatile ("" : : :"memory") -#define set_mb(var, value) ({ (var) = (value); wmb(); }) - -#define smp_mb() barrier() -#define smp_rmb() barrier() -#define smp_wmb() barrier() -#define smp_read_barrier_depends() do { } while(0) - -#define read_barrier_depends() ((void)0) - -#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) - -struct __xchg_dummy { unsigned long a[100]; }; -#define __xg(x) ((volatile struct __xchg_dummy *)(x)) - -#ifndef CONFIG_RMW_INSNS -static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) -{ - unsigned long tmp, flags; - - local_irq_save(flags); - - switch (size) { - case 1: - __asm__ __volatile__ - ("moveb %2,%0\n\t" - "moveb %1,%2" - : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory"); - break; - case 2: - __asm__ __volatile__ - ("movew %2,%0\n\t" - "movew %1,%2" - : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory"); - break; - case 4: - __asm__ __volatile__ - ("movel %2,%0\n\t" - "movel %1,%2" - : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory"); - break; - } - local_irq_restore(flags); - return tmp; -} -#else -static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) -{ - switch (size) { - case 1: - __asm__ __volatile__ - ("moveb %2,%0\n\t" - "1:\n\t" - "casb %0,%1,%2\n\t" - "jne 1b" - : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); - break; - case 2: - __asm__ __volatile__ - ("movew %2,%0\n\t" - "1:\n\t" - "casw %0,%1,%2\n\t" - "jne 1b" - : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); - break; - case 4: - __asm__ __volatile__ - ("movel %2,%0\n\t" - "1:\n\t" - "casl %0,%1,%2\n\t" - "jne 1b" - : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); - break; - } - return x; -} -#endif - -#include - -/* - * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make - * them available. - */ -#define cmpxchg_local(ptr, o, n) \ - ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\ - (unsigned long)(n), sizeof(*(ptr)))) -#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) - -#include - -#define arch_align_stack(x) (x) - - -#endif /* _M68KNOMMU_SYSTEM_H */ diff --git a/arch/m68k/platform/68328/entry.S b/arch/m68k/platform/68328/entry.S index f68dce7..4ed7a65 100644 --- a/arch/m68k/platform/68328/entry.S +++ b/arch/m68k/platform/68328/entry.S @@ -241,22 +241,21 @@ ENTRY(bad_interrupt) /* * Beware - when entering resume, prev (the current task) is - * in a0, next (the new task) is in a1,so don't change these + * in a0, next (the new task) is in a1, so don't change these * registers until their contents are no longer needed. */ ENTRY(resume) movel %a0,%d1 /* save prev thread in d1 */ movew %sr,%a0@(TASK_THREAD+THREAD_SR) /* save sr */ - movel %usp,%a2 /* save usp */ - movel %a2,%a0@(TASK_THREAD+THREAD_USP) - SAVE_SWITCH_STACK movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */ + movel %usp,%a3 /* save usp */ + movel %a3,%a0@(TASK_THREAD+THREAD_USP) + + movel %a1@(TASK_THREAD+THREAD_USP),%a3 /* restore user stack */ + movel %a3,%usp movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */ RESTORE_SWITCH_STACK - - movel %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore user stack */ - movel %a0,%usp movew %a1@(TASK_THREAD+THREAD_SR),%sr /* restore thread status reg */ rts diff --git a/arch/m68k/platform/68360/entry.S b/arch/m68k/platform/68360/entry.S index a07b14f..0ede670 100644 --- a/arch/m68k/platform/68360/entry.S +++ b/arch/m68k/platform/68360/entry.S @@ -162,22 +162,21 @@ bad_interrupt: /* * Beware - when entering resume, prev (the current task) is - * in a0, next (the new task) is in a1,so don't change these + * in a0, next (the new task) is in a1, so don't change these * registers until their contents are no longer needed. */ ENTRY(resume) movel %a0,%d1 /* save prev thread in d1 */ movew %sr,%a0@(TASK_THREAD+THREAD_SR) /* save sr */ - movel %usp,%a2 /* save usp */ - movel %a2,%a0@(TASK_THREAD+THREAD_USP) - SAVE_SWITCH_STACK movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */ + movel %usp,%a3 /* save usp */ + movel %a3,%a0@(TASK_THREAD+THREAD_USP) + + movel %a1@(TASK_THREAD+THREAD_USP),%a3 /* restore user stack */ + movel %a3,%usp movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */ RESTORE_SWITCH_STACK - - movel %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore user stack */ - movel %a0,%usp movew %a1@(TASK_THREAD+THREAD_SR),%sr /* restore thread status reg */ rts diff --git a/arch/m68k/platform/coldfire/entry.S b/arch/m68k/platform/coldfire/entry.S index 27c2b00..bd27242 100644 --- a/arch/m68k/platform/coldfire/entry.S +++ b/arch/m68k/platform/coldfire/entry.S @@ -182,21 +182,23 @@ ENTRY(inthandler) /* * Beware - when entering resume, prev (the current task) is - * in a0, next (the new task) is in a1,so don't change these + * in a0, next (the new task) is in a1, so don't change these * registers until their contents are no longer needed. - * This is always called in supervisor mode, so don't bother to save - * and restore sr; user's process sr is actually in the stack. */ ENTRY(resume) - movel %a0, %d1 /* get prev thread in d1 */ - RDUSP - movel %a2,%a0@(TASK_THREAD+THREAD_USP) - + movew %sr,%d1 /* save current status */ + movew %d1,%a0@(TASK_THREAD+THREAD_SR) + movel %a0,%d1 /* get prev thread in d1 */ SAVE_SWITCH_STACK movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */ - movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */ + RDUSP /* movel %usp,%a3 */ + movel %a3,%a0@(TASK_THREAD+THREAD_USP) /* save thread user stack */ + + movel %a1@(TASK_THREAD+THREAD_USP),%a3 /* restore thread user stack */ + WRUSP /* movel %a3,%usp */ + movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new kernel stack */ + movew %a1@(TASK_THREAD+THREAD_SR),%d7 /* restore new status */ + movew %d7,%sr RESTORE_SWITCH_STACK - - movel %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */ - WRUSP rts + -- cgit v0.10.2 From 171d809df1896c1022f9778cd2788be6c255a7dc Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Tue, 17 May 2011 16:45:00 +1000 Subject: m68k: merge mmu and non-mmu bitops.h The following patch merges the mmu and non-mmu versions of the m68k bitops.h files. Now there is a good deal of difference between the two files, but none of it is actually an mmu specific difference. It is all about the specific m68k/coldfire varient we are targeting. So it makes an awful lot of sense to merge these into a single bitops.h. There is a number of ways I can see to factor this code. The approach I have taken here is to keep the various versions of each macro/function type together. This means that there is some ifdefery with each to handle each CPU type. I have added some comments in a couple of appropriate places to try and make it clear what the differences we are dealing with are. Specifically the instruction and addressing mode differences we have to deal with. The merged form keeps the same underlying optimizations for each CPU type for all the general bit clear/set/change and find bit operations. It does switch to using the generic le operations though, instead of any local varients. Build tested on ColdFire, 68328, 68360 (which is cpu32) and 68020+. Run tested on ColdFire and ARAnyM. Signed-off-by: Greg Ungerer Acked-by: Geert Uytterhoeven diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index d66e34c..284cd37 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -41,6 +41,10 @@ config NO_DMA config ZONE_DMA bool default y + +config CPU_HAS_NO_BITFIELDS + bool + config HZ int default 1000 if CLEOPATRA diff --git a/arch/m68k/Kconfig.nommu b/arch/m68k/Kconfig.nommu index b004dc1..ff46383 100644 --- a/arch/m68k/Kconfig.nommu +++ b/arch/m68k/Kconfig.nommu @@ -16,6 +16,7 @@ config GENERIC_CLOCKEVENTS config M68000 bool + select CPU_HAS_NO_BITFIELDS help The Freescale (was Motorola) 68000 CPU is the first generation of the well known M68K family of processors. The CPU core as well as @@ -25,6 +26,7 @@ config M68000 config MCPU32 bool + select CPU_HAS_NO_BITFIELDS help The Freescale (was then Motorola) CPU32 is a CPU core that is based on the 68020 processor. For the most part it is used in @@ -34,6 +36,7 @@ config COLDFIRE bool select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB + select CPU_HAS_NO_BITFIELDS help The Freescale ColdFire family of processors is a modern derivitive of the 68000 processor family. They are mainly targeted at embedded diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h index ce163ab..c6baa91 100644 --- a/arch/m68k/include/asm/bitops.h +++ b/arch/m68k/include/asm/bitops.h @@ -1,5 +1,530 @@ -#ifdef __uClinux__ -#include "bitops_no.h" +#ifndef _M68K_BITOPS_H +#define _M68K_BITOPS_H +/* + * Copyright 1992, Linus Torvalds. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#ifndef _LINUX_BITOPS_H +#error only can be included directly +#endif + +#include + +/* + * Bit access functions vary across the ColdFire and 68k families. + * So we will break them out here, and then macro in the ones we want. + * + * ColdFire - supports standard bset/bclr/bchg with register operand only + * 68000 - supports standard bset/bclr/bchg with memory operand + * >= 68020 - also supports the bfset/bfclr/bfchg instructions + * + * Although it is possible to use only the bset/bclr/bchg with register + * operands on all platforms you end up with larger generated code. + * So we use the best form possible on a given platform. + */ + +static inline void bset_reg_set_bit(int nr, volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + + __asm__ __volatile__ ("bset %1,(%0)" + : + : "a" (p), "di" (nr & 7) + : "memory"); +} + +static inline void bset_mem_set_bit(int nr, volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + + __asm__ __volatile__ ("bset %1,%0" + : "+m" (*p) + : "di" (nr & 7)); +} + +static inline void bfset_mem_set_bit(int nr, volatile unsigned long *vaddr) +{ + __asm__ __volatile__ ("bfset %1{%0:#1}" + : + : "d" (nr ^ 31), "o" (*vaddr) + : "memory"); +} + +#if defined(CONFIG_COLDFIRE) +#define set_bit(nr, vaddr) bset_reg_set_bit(nr, vaddr) +#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) +#define set_bit(nr, vaddr) bset_mem_set_bit(nr, vaddr) +#else +#define set_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ + bset_mem_set_bit(nr, vaddr) : \ + bfset_mem_set_bit(nr, vaddr)) +#endif + +#define __set_bit(nr, vaddr) set_bit(nr, vaddr) + + +/* + * clear_bit() doesn't provide any barrier for the compiler. + */ +#define smp_mb__before_clear_bit() barrier() +#define smp_mb__after_clear_bit() barrier() + +static inline void bclr_reg_clear_bit(int nr, volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + + __asm__ __volatile__ ("bclr %1,(%0)" + : + : "a" (p), "di" (nr & 7) + : "memory"); +} + +static inline void bclr_mem_clear_bit(int nr, volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + + __asm__ __volatile__ ("bclr %1,%0" + : "+m" (*p) + : "di" (nr & 7)); +} + +static inline void bfclr_mem_clear_bit(int nr, volatile unsigned long *vaddr) +{ + __asm__ __volatile__ ("bfclr %1{%0:#1}" + : + : "d" (nr ^ 31), "o" (*vaddr) + : "memory"); +} + +#if defined(CONFIG_COLDFIRE) +#define clear_bit(nr, vaddr) bclr_reg_clear_bit(nr, vaddr) +#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) +#define clear_bit(nr, vaddr) bclr_mem_clear_bit(nr, vaddr) +#else +#define clear_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ + bclr_mem_clear_bit(nr, vaddr) : \ + bfclr_mem_clear_bit(nr, vaddr)) +#endif + +#define __clear_bit(nr, vaddr) clear_bit(nr, vaddr) + + +static inline void bchg_reg_change_bit(int nr, volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + + __asm__ __volatile__ ("bchg %1,(%0)" + : + : "a" (p), "di" (nr & 7) + : "memory"); +} + +static inline void bchg_mem_change_bit(int nr, volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + + __asm__ __volatile__ ("bchg %1,%0" + : "+m" (*p) + : "di" (nr & 7)); +} + +static inline void bfchg_mem_change_bit(int nr, volatile unsigned long *vaddr) +{ + __asm__ __volatile__ ("bfchg %1{%0:#1}" + : + : "d" (nr ^ 31), "o" (*vaddr) + : "memory"); +} + +#if defined(CONFIG_COLDFIRE) +#define change_bit(nr, vaddr) bchg_reg_change_bit(nr, vaddr) +#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) +#define change_bit(nr, vaddr) bchg_mem_change_bit(nr, vaddr) +#else +#define change_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ + bchg_mem_change_bit(nr, vaddr) : \ + bfchg_mem_change_bit(nr, vaddr)) +#endif + +#define __change_bit(nr, vaddr) change_bit(nr, vaddr) + + +static inline int test_bit(int nr, const unsigned long *vaddr) +{ + return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0; +} + + +static inline int bset_reg_test_and_set_bit(int nr, + volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + char retval; + + __asm__ __volatile__ ("bset %2,(%1); sne %0" + : "=d" (retval) + : "a" (p), "di" (nr & 7) + : "memory"); + return retval; +} + +static inline int bset_mem_test_and_set_bit(int nr, + volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + char retval; + + __asm__ __volatile__ ("bset %2,%1; sne %0" + : "=d" (retval), "+m" (*p) + : "di" (nr & 7)); + return retval; +} + +static inline int bfset_mem_test_and_set_bit(int nr, + volatile unsigned long *vaddr) +{ + char retval; + + __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0" + : "=d" (retval) + : "d" (nr ^ 31), "o" (*vaddr) + : "memory"); + return retval; +} + +#if defined(CONFIG_COLDFIRE) +#define test_and_set_bit(nr, vaddr) bset_reg_test_and_set_bit(nr, vaddr) +#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) +#define test_and_set_bit(nr, vaddr) bset_mem_test_and_set_bit(nr, vaddr) +#else +#define test_and_set_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ + bset_mem_test_and_set_bit(nr, vaddr) : \ + bfset_mem_test_and_set_bit(nr, vaddr)) +#endif + +#define __test_and_set_bit(nr, vaddr) test_and_set_bit(nr, vaddr) + + +static inline int bclr_reg_test_and_clear_bit(int nr, + volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + char retval; + + __asm__ __volatile__ ("bclr %2,(%1); sne %0" + : "=d" (retval) + : "a" (p), "di" (nr & 7) + : "memory"); + return retval; +} + +static inline int bclr_mem_test_and_clear_bit(int nr, + volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + char retval; + + __asm__ __volatile__ ("bclr %2,%1; sne %0" + : "=d" (retval), "+m" (*p) + : "di" (nr & 7)); + return retval; +} + +static inline int bfclr_mem_test_and_clear_bit(int nr, + volatile unsigned long *vaddr) +{ + char retval; + + __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0" + : "=d" (retval) + : "d" (nr ^ 31), "o" (*vaddr) + : "memory"); + return retval; +} + +#if defined(CONFIG_COLDFIRE) +#define test_and_clear_bit(nr, vaddr) bclr_reg_test_and_clear_bit(nr, vaddr) +#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) +#define test_and_clear_bit(nr, vaddr) bclr_mem_test_and_clear_bit(nr, vaddr) +#else +#define test_and_clear_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ + bclr_mem_test_and_clear_bit(nr, vaddr) : \ + bfclr_mem_test_and_clear_bit(nr, vaddr)) +#endif + +#define __test_and_clear_bit(nr, vaddr) test_and_clear_bit(nr, vaddr) + + +static inline int bchg_reg_test_and_change_bit(int nr, + volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + char retval; + + __asm__ __volatile__ ("bchg %2,(%1); sne %0" + : "=d" (retval) + : "a" (p), "di" (nr & 7) + : "memory"); + return retval; +} + +static inline int bchg_mem_test_and_change_bit(int nr, + volatile unsigned long *vaddr) +{ + char *p = (char *)vaddr + (nr ^ 31) / 8; + char retval; + + __asm__ __volatile__ ("bchg %2,%1; sne %0" + : "=d" (retval), "+m" (*p) + : "di" (nr & 7)); + return retval; +} + +static inline int bfchg_mem_test_and_change_bit(int nr, + volatile unsigned long *vaddr) +{ + char retval; + + __asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0" + : "=d" (retval) + : "d" (nr ^ 31), "o" (*vaddr) + : "memory"); + return retval; +} + +#if defined(CONFIG_COLDFIRE) +#define test_and_change_bit(nr, vaddr) bchg_reg_test_and_change_bit(nr, vaddr) +#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS) +#define test_and_change_bit(nr, vaddr) bchg_mem_test_and_change_bit(nr, vaddr) +#else +#define test_and_change_bit(nr, vaddr) (__builtin_constant_p(nr) ? \ + bchg_mem_test_and_change_bit(nr, vaddr) : \ + bfchg_mem_test_and_change_bit(nr, vaddr)) +#endif + +#define __test_and_change_bit(nr, vaddr) test_and_change_bit(nr, vaddr) + + +/* + * The true 68020 and more advanced processors support the "bfffo" + * instruction for finding bits. ColdFire and simple 68000 parts + * (including CPU32) do not support this. They simply use the generic + * functions. + */ +#if defined(CONFIG_CPU_HAS_NO_BITFIELDS) +#include +#include +#else + +static inline int find_first_zero_bit(const unsigned long *vaddr, + unsigned size) +{ + const unsigned long *p = vaddr; + int res = 32; + unsigned int words; + unsigned long num; + + if (!size) + return 0; + + words = (size + 31) >> 5; + while (!(num = ~*p++)) { + if (!--words) + goto out; + } + + __asm__ __volatile__ ("bfffo %1{#0,#0},%0" + : "=d" (res) : "d" (num & -num)); + res ^= 31; +out: + res += ((long)p - (long)vaddr - 4) * 8; + return res < size ? res : size; +} +#define find_first_zero_bit find_first_zero_bit + +static inline int find_next_zero_bit(const unsigned long *vaddr, int size, + int offset) +{ + const unsigned long *p = vaddr + (offset >> 5); + int bit = offset & 31UL, res; + + if (offset >= size) + return size; + + if (bit) { + unsigned long num = ~*p++ & (~0UL << bit); + offset -= bit; + + /* Look for zero in first longword */ + __asm__ __volatile__ ("bfffo %1{#0,#0},%0" + : "=d" (res) : "d" (num & -num)); + if (res < 32) { + offset += res ^ 31; + return offset < size ? offset : size; + } + offset += 32; + + if (offset >= size) + return size; + } + /* No zero yet, search remaining full bytes for a zero */ + return offset + find_first_zero_bit(p, size - offset); +} +#define find_next_zero_bit find_next_zero_bit + +static inline int find_first_bit(const unsigned long *vaddr, unsigned size) +{ + const unsigned long *p = vaddr; + int res = 32; + unsigned int words; + unsigned long num; + + if (!size) + return 0; + + words = (size + 31) >> 5; + while (!(num = *p++)) { + if (!--words) + goto out; + } + + __asm__ __volatile__ ("bfffo %1{#0,#0},%0" + : "=d" (res) : "d" (num & -num)); + res ^= 31; +out: + res += ((long)p - (long)vaddr - 4) * 8; + return res < size ? res : size; +} +#define find_first_bit find_first_bit + +static inline int find_next_bit(const unsigned long *vaddr, int size, + int offset) +{ + const unsigned long *p = vaddr + (offset >> 5); + int bit = offset & 31UL, res; + + if (offset >= size) + return size; + + if (bit) { + unsigned long num = *p++ & (~0UL << bit); + offset -= bit; + + /* Look for one in first longword */ + __asm__ __volatile__ ("bfffo %1{#0,#0},%0" + : "=d" (res) : "d" (num & -num)); + if (res < 32) { + offset += res ^ 31; + return offset < size ? offset : size; + } + offset += 32; + + if (offset >= size) + return size; + } + /* No one yet, search remaining full bytes for a one */ + return offset + find_first_bit(p, size - offset); +} +#define find_next_bit find_next_bit + +/* + * ffz = Find First Zero in word. Undefined if no zero exists, + * so code should check against ~0UL first.. + */ +static inline unsigned long ffz(unsigned long word) +{ + int res; + + __asm__ __volatile__ ("bfffo %1{#0,#0},%0" + : "=d" (res) : "d" (~word & -~word)); + return res ^ 31; +} + +#endif + +#ifdef __KERNEL__ + +#if defined(CONFIG_CPU_HAS_NO_BITFIELDS) + +/* + * The newer ColdFire family members support a "bitrev" instruction + * and we can use that to implement a fast ffs. Older Coldfire parts, + * and normal 68000 parts don't have anything special, so we use the + * generic functions for those. + */ +#if (defined(__mcfisaaplus__) || defined(__mcfisac__)) && \ + !defined(CONFIG_M68000) && !defined(CONFIG_MCPU32) +static inline int __ffs(int x) +{ + __asm__ __volatile__ ("bitrev %0; ff1 %0" + : "=d" (x) + : "0" (x)); + return x; +} + +static inline int ffs(int x) +{ + if (!x) + return 0; + return __ffs(x) + 1; +} + +#else +#include +#include +#endif + +#include +#include + #else -#include "bitops_mm.h" + +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +static inline int ffs(int x) +{ + int cnt; + + __asm__ ("bfffo %1{#0:#0},%0" + : "=d" (cnt) + : "dm" (x & -x)); + return 32 - cnt; +} +#define __ffs(x) (ffs(x) - 1) + +/* + * fls: find last bit set. + */ +static inline int fls(int x) +{ + int cnt; + + __asm__ ("bfffo %1{#0,#0},%0" + : "=d" (cnt) + : "dm" (x)); + return 32 - cnt; +} + +static inline int __fls(int x) +{ + return fls(x) - 1; +} + #endif + +#include +#include +#include +#include +#include +#include +#endif /* __KERNEL__ */ + +#endif /* _M68K_BITOPS_H */ diff --git a/arch/m68k/include/asm/bitops_mm.h b/arch/m68k/include/asm/bitops_mm.h deleted file mode 100644 index 89cf5b8..0000000 --- a/arch/m68k/include/asm/bitops_mm.h +++ /dev/null @@ -1,501 +0,0 @@ -#ifndef _M68K_BITOPS_H -#define _M68K_BITOPS_H -/* - * Copyright 1992, Linus Torvalds. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#ifndef _LINUX_BITOPS_H -#error only can be included directly -#endif - -#include - -/* - * Require 68020 or better. - * - * They use the standard big-endian m680x0 bit ordering. - */ - -#define test_and_set_bit(nr,vaddr) \ - (__builtin_constant_p(nr) ? \ - __constant_test_and_set_bit(nr, vaddr) : \ - __generic_test_and_set_bit(nr, vaddr)) - -#define __test_and_set_bit(nr,vaddr) test_and_set_bit(nr,vaddr) - -static inline int __constant_test_and_set_bit(int nr, unsigned long *vaddr) -{ - char *p = (char *)vaddr + (nr ^ 31) / 8; - char retval; - - __asm__ __volatile__ ("bset %2,%1; sne %0" - : "=d" (retval), "+m" (*p) - : "di" (nr & 7)); - - return retval; -} - -static inline int __generic_test_and_set_bit(int nr, unsigned long *vaddr) -{ - char retval; - - __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory"); - - return retval; -} - -#define set_bit(nr,vaddr) \ - (__builtin_constant_p(nr) ? \ - __constant_set_bit(nr, vaddr) : \ - __generic_set_bit(nr, vaddr)) - -#define __set_bit(nr,vaddr) set_bit(nr,vaddr) - -static inline void __constant_set_bit(int nr, volatile unsigned long *vaddr) -{ - char *p = (char *)vaddr + (nr ^ 31) / 8; - __asm__ __volatile__ ("bset %1,%0" - : "+m" (*p) : "di" (nr & 7)); -} - -static inline void __generic_set_bit(int nr, volatile unsigned long *vaddr) -{ - __asm__ __volatile__ ("bfset %1{%0:#1}" - : : "d" (nr^31), "o" (*vaddr) : "memory"); -} - -#define test_and_clear_bit(nr,vaddr) \ - (__builtin_constant_p(nr) ? \ - __constant_test_and_clear_bit(nr, vaddr) : \ - __generic_test_and_clear_bit(nr, vaddr)) - -#define __test_and_clear_bit(nr,vaddr) test_and_clear_bit(nr,vaddr) - -static inline int __constant_test_and_clear_bit(int nr, unsigned long *vaddr) -{ - char *p = (char *)vaddr + (nr ^ 31) / 8; - char retval; - - __asm__ __volatile__ ("bclr %2,%1; sne %0" - : "=d" (retval), "+m" (*p) - : "di" (nr & 7)); - - return retval; -} - -static inline int __generic_test_and_clear_bit(int nr, unsigned long *vaddr) -{ - char retval; - - __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory"); - - return retval; -} - -/* - * clear_bit() doesn't provide any barrier for the compiler. - */ -#define smp_mb__before_clear_bit() barrier() -#define smp_mb__after_clear_bit() barrier() - -#define clear_bit(nr,vaddr) \ - (__builtin_constant_p(nr) ? \ - __constant_clear_bit(nr, vaddr) : \ - __generic_clear_bit(nr, vaddr)) -#define __clear_bit(nr,vaddr) clear_bit(nr,vaddr) - -static inline void __constant_clear_bit(int nr, volatile unsigned long *vaddr) -{ - char *p = (char *)vaddr + (nr ^ 31) / 8; - __asm__ __volatile__ ("bclr %1,%0" - : "+m" (*p) : "di" (nr & 7)); -} - -static inline void __generic_clear_bit(int nr, volatile unsigned long *vaddr) -{ - __asm__ __volatile__ ("bfclr %1{%0:#1}" - : : "d" (nr^31), "o" (*vaddr) : "memory"); -} - -#define test_and_change_bit(nr,vaddr) \ - (__builtin_constant_p(nr) ? \ - __constant_test_and_change_bit(nr, vaddr) : \ - __generic_test_and_change_bit(nr, vaddr)) - -#define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr) -#define __change_bit(nr,vaddr) change_bit(nr,vaddr) - -static inline int __constant_test_and_change_bit(int nr, unsigned long *vaddr) -{ - char *p = (char *)vaddr + (nr ^ 31) / 8; - char retval; - - __asm__ __volatile__ ("bchg %2,%1; sne %0" - : "=d" (retval), "+m" (*p) - : "di" (nr & 7)); - - return retval; -} - -static inline int __generic_test_and_change_bit(int nr, unsigned long *vaddr) -{ - char retval; - - __asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory"); - - return retval; -} - -#define change_bit(nr,vaddr) \ - (__builtin_constant_p(nr) ? \ - __constant_change_bit(nr, vaddr) : \ - __generic_change_bit(nr, vaddr)) - -static inline void __constant_change_bit(int nr, unsigned long *vaddr) -{ - char *p = (char *)vaddr + (nr ^ 31) / 8; - __asm__ __volatile__ ("bchg %1,%0" - : "+m" (*p) : "di" (nr & 7)); -} - -static inline void __generic_change_bit(int nr, unsigned long *vaddr) -{ - __asm__ __volatile__ ("bfchg %1{%0:#1}" - : : "d" (nr^31), "o" (*vaddr) : "memory"); -} - -static inline int test_bit(int nr, const unsigned long *vaddr) -{ - return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0; -} - -static inline int find_first_zero_bit(const unsigned long *vaddr, - unsigned size) -{ - const unsigned long *p = vaddr; - int res = 32; - unsigned int words; - unsigned long num; - - if (!size) - return 0; - - words = (size + 31) >> 5; - while (!(num = ~*p++)) { - if (!--words) - goto out; - } - - __asm__ __volatile__ ("bfffo %1{#0,#0},%0" - : "=d" (res) : "d" (num & -num)); - res ^= 31; -out: - res += ((long)p - (long)vaddr - 4) * 8; - return res < size ? res : size; -} -#define find_first_zero_bit find_first_zero_bit - -static inline int find_next_zero_bit(const unsigned long *vaddr, int size, - int offset) -{ - const unsigned long *p = vaddr + (offset >> 5); - int bit = offset & 31UL, res; - - if (offset >= size) - return size; - - if (bit) { - unsigned long num = ~*p++ & (~0UL << bit); - offset -= bit; - - /* Look for zero in first longword */ - __asm__ __volatile__ ("bfffo %1{#0,#0},%0" - : "=d" (res) : "d" (num & -num)); - if (res < 32) { - offset += res ^ 31; - return offset < size ? offset : size; - } - offset += 32; - - if (offset >= size) - return size; - } - /* No zero yet, search remaining full bytes for a zero */ - return offset + find_first_zero_bit(p, size - offset); -} -#define find_next_zero_bit find_next_zero_bit - -static inline int find_first_bit(const unsigned long *vaddr, unsigned size) -{ - const unsigned long *p = vaddr; - int res = 32; - unsigned int words; - unsigned long num; - - if (!size) - return 0; - - words = (size + 31) >> 5; - while (!(num = *p++)) { - if (!--words) - goto out; - } - - __asm__ __volatile__ ("bfffo %1{#0,#0},%0" - : "=d" (res) : "d" (num & -num)); - res ^= 31; -out: - res += ((long)p - (long)vaddr - 4) * 8; - return res < size ? res : size; -} -#define find_first_bit find_first_bit - -static inline int find_next_bit(const unsigned long *vaddr, int size, - int offset) -{ - const unsigned long *p = vaddr + (offset >> 5); - int bit = offset & 31UL, res; - - if (offset >= size) - return size; - - if (bit) { - unsigned long num = *p++ & (~0UL << bit); - offset -= bit; - - /* Look for one in first longword */ - __asm__ __volatile__ ("bfffo %1{#0,#0},%0" - : "=d" (res) : "d" (num & -num)); - if (res < 32) { - offset += res ^ 31; - return offset < size ? offset : size; - } - offset += 32; - - if (offset >= size) - return size; - } - /* No one yet, search remaining full bytes for a one */ - return offset + find_first_bit(p, size - offset); -} -#define find_next_bit find_next_bit - -/* - * ffz = Find First Zero in word. Undefined if no zero exists, - * so code should check against ~0UL first.. - */ -static inline unsigned long ffz(unsigned long word) -{ - int res; - - __asm__ __volatile__ ("bfffo %1{#0,#0},%0" - : "=d" (res) : "d" (~word & -~word)); - return res ^ 31; -} - -#ifdef __KERNEL__ - -/* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ - -static inline int ffs(int x) -{ - int cnt; - - asm ("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x)); - - return 32 - cnt; -} -#define __ffs(x) (ffs(x) - 1) - -/* - * fls: find last bit set. - */ - -static inline int fls(int x) -{ - int cnt; - - asm ("bfffo %1{#0,#0},%0" : "=d" (cnt) : "dm" (x)); - - return 32 - cnt; -} - -static inline int __fls(int x) -{ - return fls(x) - 1; -} - -#include -#include -#include -#include - -/* Bitmap functions for the little endian bitmap. */ - -static inline void __set_bit_le(int nr, void *addr) -{ - __set_bit(nr ^ 24, addr); -} - -static inline void __clear_bit_le(int nr, void *addr) -{ - __clear_bit(nr ^ 24, addr); -} - -static inline int __test_and_set_bit_le(int nr, void *addr) -{ - return __test_and_set_bit(nr ^ 24, addr); -} - -static inline int test_and_set_bit_le(int nr, void *addr) -{ - return test_and_set_bit(nr ^ 24, addr); -} - -static inline int __test_and_clear_bit_le(int nr, void *addr) -{ - return __test_and_clear_bit(nr ^ 24, addr); -} - -static inline int test_and_clear_bit_le(int nr, void *addr) -{ - return test_and_clear_bit(nr ^ 24, addr); -} - -static inline int test_bit_le(int nr, const void *vaddr) -{ - const unsigned char *p = vaddr; - return (p[nr >> 3] & (1U << (nr & 7))) != 0; -} - -static inline int find_first_zero_bit_le(const void *vaddr, unsigned size) -{ - const unsigned long *p = vaddr, *addr = vaddr; - int res = 0; - unsigned int words; - - if (!size) - return 0; - - words = (size >> 5) + ((size & 31) > 0); - while (*p++ == ~0UL) { - if (--words == 0) - goto out; - } - - --p; - for (res = 0; res < 32; res++) - if (!test_bit_le(res, p)) - break; -out: - res += (p - addr) * 32; - return res < size ? res : size; -} -#define find_first_zero_bit_le find_first_zero_bit_le - -static inline unsigned long find_next_zero_bit_le(const void *addr, - unsigned long size, unsigned long offset) -{ - const unsigned long *p = addr; - int bit = offset & 31UL, res; - - if (offset >= size) - return size; - - p += offset >> 5; - - if (bit) { - offset -= bit; - /* Look for zero in first longword */ - for (res = bit; res < 32; res++) - if (!test_bit_le(res, p)) { - offset += res; - return offset < size ? offset : size; - } - p++; - offset += 32; - - if (offset >= size) - return size; - } - /* No zero yet, search remaining full bytes for a zero */ - return offset + find_first_zero_bit_le(p, size - offset); -} -#define find_next_zero_bit_le find_next_zero_bit_le - -static inline int find_first_bit_le(const void *vaddr, unsigned size) -{ - const unsigned long *p = vaddr, *addr = vaddr; - int res = 0; - unsigned int words; - - if (!size) - return 0; - - words = (size >> 5) + ((size & 31) > 0); - while (*p++ == 0UL) { - if (--words == 0) - goto out; - } - - --p; - for (res = 0; res < 32; res++) - if (test_bit_le(res, p)) - break; -out: - res += (p - addr) * 32; - return res < size ? res : size; -} -#define find_first_bit_le find_first_bit_le - -static inline unsigned long find_next_bit_le(const void *addr, - unsigned long size, unsigned long offset) -{ - const unsigned long *p = addr; - int bit = offset & 31UL, res; - - if (offset >= size) - return size; - - p += offset >> 5; - - if (bit) { - offset -= bit; - /* Look for one in first longword */ - for (res = bit; res < 32; res++) - if (test_bit_le(res, p)) { - offset += res; - return offset < size ? offset : size; - } - p++; - offset += 32; - - if (offset >= size) - return size; - } - /* No set bit yet, search remaining full bytes for a set bit */ - return offset + find_first_bit_le(p, size - offset); -} -#define find_next_bit_le find_next_bit_le - -/* Bitmap functions for the ext2 filesystem. */ - -#define ext2_set_bit_atomic(lock, nr, addr) \ - test_and_set_bit_le(nr, addr) -#define ext2_clear_bit_atomic(lock, nr, addr) \ - test_and_clear_bit_le(nr, addr) - -#endif /* __KERNEL__ */ - -#endif /* _M68K_BITOPS_H */ diff --git a/arch/m68k/include/asm/bitops_no.h b/arch/m68k/include/asm/bitops_no.h deleted file mode 100644 index 72e85ac..0000000 --- a/arch/m68k/include/asm/bitops_no.h +++ /dev/null @@ -1,333 +0,0 @@ -#ifndef _M68KNOMMU_BITOPS_H -#define _M68KNOMMU_BITOPS_H - -/* - * Copyright 1992, Linus Torvalds. - */ - -#include -#include /* swab32 */ - -#ifdef __KERNEL__ - -#ifndef _LINUX_BITOPS_H -#error only can be included directly -#endif - -#if defined (__mcfisaaplus__) || defined (__mcfisac__) -static inline int ffs(unsigned int val) -{ - if (!val) - return 0; - - asm volatile( - "bitrev %0\n\t" - "ff1 %0\n\t" - : "=d" (val) - : "0" (val) - ); - val++; - return val; -} - -static inline int __ffs(unsigned int val) -{ - asm volatile( - "bitrev %0\n\t" - "ff1 %0\n\t" - : "=d" (val) - : "0" (val) - ); - return val; -} - -#else -#include -#include -#endif - -#include -#include - -static __inline__ void set_bit(int nr, volatile unsigned long * addr) -{ -#ifdef CONFIG_COLDFIRE - __asm__ __volatile__ ("lea %0,%%a0; bset %1,(%%a0)" - : "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "d" (nr) - : "%a0", "cc"); -#else - __asm__ __volatile__ ("bset %1,%0" - : "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "di" (nr) - : "cc"); -#endif -} - -#define __set_bit(nr, addr) set_bit(nr, addr) - -/* - * clear_bit() doesn't provide any barrier for the compiler. - */ -#define smp_mb__before_clear_bit() barrier() -#define smp_mb__after_clear_bit() barrier() - -static __inline__ void clear_bit(int nr, volatile unsigned long * addr) -{ -#ifdef CONFIG_COLDFIRE - __asm__ __volatile__ ("lea %0,%%a0; bclr %1,(%%a0)" - : "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "d" (nr) - : "%a0", "cc"); -#else - __asm__ __volatile__ ("bclr %1,%0" - : "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "di" (nr) - : "cc"); -#endif -} - -#define __clear_bit(nr, addr) clear_bit(nr, addr) - -static __inline__ void change_bit(int nr, volatile unsigned long * addr) -{ -#ifdef CONFIG_COLDFIRE - __asm__ __volatile__ ("lea %0,%%a0; bchg %1,(%%a0)" - : "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "d" (nr) - : "%a0", "cc"); -#else - __asm__ __volatile__ ("bchg %1,%0" - : "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "di" (nr) - : "cc"); -#endif -} - -#define __change_bit(nr, addr) change_bit(nr, addr) - -static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr) -{ - char retval; - -#ifdef CONFIG_COLDFIRE - __asm__ __volatile__ ("lea %1,%%a0; bset %2,(%%a0); sne %0" - : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "d" (nr) - : "%a0"); -#else - __asm__ __volatile__ ("bset %2,%1; sne %0" - : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "di" (nr) - /* No clobber */); -#endif - - return retval; -} - -#define __test_and_set_bit(nr, addr) test_and_set_bit(nr, addr) - -static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr) -{ - char retval; - -#ifdef CONFIG_COLDFIRE - __asm__ __volatile__ ("lea %1,%%a0; bclr %2,(%%a0); sne %0" - : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "d" (nr) - : "%a0"); -#else - __asm__ __volatile__ ("bclr %2,%1; sne %0" - : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "di" (nr) - /* No clobber */); -#endif - - return retval; -} - -#define __test_and_clear_bit(nr, addr) test_and_clear_bit(nr, addr) - -static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr) -{ - char retval; - -#ifdef CONFIG_COLDFIRE - __asm__ __volatile__ ("lea %1,%%a0\n\tbchg %2,(%%a0)\n\tsne %0" - : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "d" (nr) - : "%a0"); -#else - __asm__ __volatile__ ("bchg %2,%1; sne %0" - : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3]) - : "di" (nr) - /* No clobber */); -#endif - - return retval; -} - -#define __test_and_change_bit(nr, addr) test_and_change_bit(nr, addr) - -/* - * This routine doesn't need to be atomic. - */ -static __inline__ int __constant_test_bit(int nr, const volatile unsigned long * addr) -{ - return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; -} - -static __inline__ int __test_bit(int nr, const volatile unsigned long * addr) -{ - int * a = (int *) addr; - int mask; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - return ((mask & *a) != 0); -} - -#define test_bit(nr,addr) \ -(__builtin_constant_p(nr) ? \ - __constant_test_bit((nr),(addr)) : \ - __test_bit((nr),(addr))) - -#include -#include -#include - -#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) - -static inline void __set_bit_le(int nr, void *addr) -{ - __set_bit(nr ^ BITOP_LE_SWIZZLE, addr); -} - -static inline void __clear_bit_le(int nr, void *addr) -{ - __clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); -} - -static inline int __test_and_set_bit_le(int nr, volatile void *addr) -{ - char retval; - -#ifdef CONFIG_COLDFIRE - __asm__ __volatile__ ("lea %1,%%a0; bset %2,(%%a0); sne %0" - : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3]) - : "d" (nr) - : "%a0"); -#else - __asm__ __volatile__ ("bset %2,%1; sne %0" - : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3]) - : "di" (nr) - /* No clobber */); -#endif - - return retval; -} - -static inline int __test_and_clear_bit_le(int nr, volatile void *addr) -{ - char retval; - -#ifdef CONFIG_COLDFIRE - __asm__ __volatile__ ("lea %1,%%a0; bclr %2,(%%a0); sne %0" - : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3]) - : "d" (nr) - : "%a0"); -#else - __asm__ __volatile__ ("bclr %2,%1; sne %0" - : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3]) - : "di" (nr) - /* No clobber */); -#endif - - return retval; -} - -#include - -static inline int test_bit_le(int nr, const volatile void *addr) -{ - char retval; - -#ifdef CONFIG_COLDFIRE - __asm__ __volatile__ ("lea %1,%%a0; btst %2,(%%a0); sne %0" - : "=d" (retval) - : "m" (((const volatile char *)addr)[nr >> 3]), "d" (nr) - : "%a0"); -#else - __asm__ __volatile__ ("btst %2,%1; sne %0" - : "=d" (retval) - : "m" (((const volatile char *)addr)[nr >> 3]), "di" (nr) - /* No clobber */); -#endif - - return retval; -} - -#define find_first_zero_bit_le(addr, size) \ - find_next_zero_bit_le((addr), (size), 0) - -static inline unsigned long find_next_zero_bit_le(void *addr, unsigned long size, unsigned long offset) -{ - unsigned long *p = ((unsigned long *) addr) + (offset >> 5); - unsigned long result = offset & ~31UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31UL; - if(offset) { - /* We hold the little endian value in tmp, but then the - * shift is illegal. So we could keep a big endian value - * in tmp, like this: - * - * tmp = __swab32(*(p++)); - * tmp |= ~0UL >> (32-offset); - * - * but this would decrease performance, so we change the - * shift: - */ - tmp = *(p++); - tmp |= __swab32(~0UL >> (32-offset)); - if(size < 32) - goto found_first; - if(~tmp) - goto found_middle; - size -= 32; - result += 32; - } - while(size & ~31UL) { - if(~(tmp = *(p++))) - goto found_middle; - result += 32; - size -= 32; - } - if(!size) - return result; - tmp = *p; - -found_first: - /* tmp is little endian, so we would have to swab the shift, - * see above. But then we have to swab tmp below for ffz, so - * we might as well do this here. - */ - return result + ffz(__swab32(tmp) | (~0UL << size)); -found_middle: - return result + ffz(__swab32(tmp)); -} -#define find_next_zero_bit_le find_next_zero_bit_le - -extern unsigned long find_next_bit_le(const void *addr, - unsigned long size, unsigned long offset); - -#endif /* __KERNEL__ */ - -#include -#include -#include - -#endif /* _M68KNOMMU_BITOPS_H */ -- cgit v0.10.2 From f4a5437333e405e967be660430e58fc2355c62c8 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 6 Jun 2011 13:33:11 +1000 Subject: m68knommu: merge ColdFire 5206 and 5206e platform code The ColdFire 5206 and 5206e CPU families are almost identical, we can easily merge the platform support code for them. All the differences are dealt with in the current include/asm/5206sim.h. Signed-off-by: Greg Ungerer diff --git a/arch/m68k/Makefile_no b/arch/m68k/Makefile_no index 81652ab..844d3f1 100644 --- a/arch/m68k/Makefile_no +++ b/arch/m68k/Makefile_no @@ -13,7 +13,7 @@ platform-$(CONFIG_M68EZ328) := 68EZ328 platform-$(CONFIG_M68VZ328) := 68VZ328 platform-$(CONFIG_M68360) := 68360 platform-$(CONFIG_M5206) := 5206 -platform-$(CONFIG_M5206e) := 5206e +platform-$(CONFIG_M5206e) := 5206 platform-$(CONFIG_M520x) := 520x platform-$(CONFIG_M523x) := 523x platform-$(CONFIG_M5249) := 5249 diff --git a/arch/m68k/platform/5206/config.c b/arch/m68k/platform/5206/config.c index 9c33546..6fa3f80 100644 --- a/arch/m68k/platform/5206/config.c +++ b/arch/m68k/platform/5206/config.c @@ -98,6 +98,12 @@ void m5206_cpu_reset(void) void __init config_BSP(char *commandp, int size) { +#if defined(CONFIG_NETtel) + /* Copy command line from FLASH to local buffer... */ + memcpy(commandp, (char *) 0xf0004000, size); + commandp[size-1] = 0; +#endif /* CONFIG_NETtel */ + mach_reset = m5206_cpu_reset; m5206_timers_init(); m5206_uarts_init(); diff --git a/arch/m68k/platform/5206e/Makefile b/arch/m68k/platform/5206e/Makefile deleted file mode 100644 index b5db056..0000000 --- a/arch/m68k/platform/5206e/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# -# Makefile for the m68knommu linux kernel. -# - -# -# If you want to play with the HW breakpoints then you will -# need to add define this, which will give you a stack backtrace -# on the console port whenever a DBG interrupt occurs. You have to -# set up you HW breakpoints to trigger a DBG interrupt: -# -# ccflags-y := -DTRAP_DBG_INTERRUPT -# asflags-y := -DTRAP_DBG_INTERRUPT -# - -asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 - -obj-y := config.o gpio.o - diff --git a/arch/m68k/platform/5206e/config.c b/arch/m68k/platform/5206e/config.c deleted file mode 100644 index 9423979..0000000 --- a/arch/m68k/platform/5206e/config.c +++ /dev/null @@ -1,127 +0,0 @@ -/***************************************************************************/ - -/* - * linux/arch/m68knommu/platform/5206e/config.c - * - * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) - */ - -/***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/***************************************************************************/ - -static struct mcf_platform_uart m5206e_uart_platform[] = { - { - .mapbase = MCF_MBAR + MCFUART_BASE1, - .irq = 73, - }, - { - .mapbase = MCF_MBAR + MCFUART_BASE2, - .irq = 74, - }, - { }, -}; - -static struct platform_device m5206e_uart = { - .name = "mcfuart", - .id = 0, - .dev.platform_data = m5206e_uart_platform, -}; - -static struct platform_device *m5206e_devices[] __initdata = { - &m5206e_uart, -}; - -/***************************************************************************/ - -static void __init m5206e_uart_init_line(int line, int irq) -{ - if (line == 0) { - writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR); - writeb(irq, MCFUART_BASE1 + MCFUART_UIVR); - mcf_mapirq2imr(irq, MCFINTC_UART0); - } else if (line == 1) { - writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR); - writeb(irq, MCFUART_BASE2 + MCFUART_UIVR); - mcf_mapirq2imr(irq, MCFINTC_UART1); - } -} - -static void __init m5206e_uarts_init(void) -{ - const int nrlines = ARRAY_SIZE(m5206e_uart_platform); - int line; - - for (line = 0; (line < nrlines); line++) - m5206e_uart_init_line(line, m5206e_uart_platform[line].irq); -} - -/***************************************************************************/ - -static void __init m5206e_timers_init(void) -{ - /* Timer1 is always used as system timer */ - writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3, - MCF_MBAR + MCFSIM_TIMER1ICR); - mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1); - -#ifdef CONFIG_HIGHPROFILE - /* Timer2 is to be used as a high speed profile timer */ - writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3, - MCF_MBAR + MCFSIM_TIMER2ICR); - mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2); -#endif -} - -/***************************************************************************/ - -void m5206e_cpu_reset(void) -{ - local_irq_disable(); - /* Set watchdog to soft reset, and enabled */ - __raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR); - for (;;) - /* wait for watchdog to timeout */; -} - -/***************************************************************************/ - -void __init config_BSP(char *commandp, int size) -{ -#if defined(CONFIG_NETtel) - /* Copy command line from FLASH to local buffer... */ - memcpy(commandp, (char *) 0xf0004000, size); - commandp[size-1] = 0; -#endif /* CONFIG_NETtel */ - - mach_reset = m5206e_cpu_reset; - m5206e_timers_init(); - m5206e_uarts_init(); - - /* Only support the external interrupts on their primary level */ - mcf_mapirq2imr(25, MCFINTC_EINT1); - mcf_mapirq2imr(28, MCFINTC_EINT4); - mcf_mapirq2imr(31, MCFINTC_EINT7); -} - -/***************************************************************************/ - -static int __init init_BSP(void) -{ - platform_add_devices(m5206e_devices, ARRAY_SIZE(m5206e_devices)); - return 0; -} - -arch_initcall(init_BSP); - -/***************************************************************************/ diff --git a/arch/m68k/platform/5206e/gpio.c b/arch/m68k/platform/5206e/gpio.c deleted file mode 100644 index b9ab4a1..0000000 --- a/arch/m68k/platform/5206e/gpio.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Coldfire generic GPIO support - * - * (C) Copyright 2009, Steven King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. -*/ - -#include -#include - -#include -#include -#include - -static struct mcf_gpio_chip mcf_gpio_chips[] = { - { - .gpio_chip = { - .label = "PP", - .request = mcf_gpio_request, - .free = mcf_gpio_free, - .direction_input = mcf_gpio_direction_input, - .direction_output = mcf_gpio_direction_output, - .get = mcf_gpio_get_value, - .set = mcf_gpio_set_value, - .ngpio = 8, - }, - .pddr = (void __iomem *) MCFSIM_PADDR, - .podr = (void __iomem *) MCFSIM_PADAT, - .ppdr = (void __iomem *) MCFSIM_PADAT, - }, -}; - -static int __init mcf_gpio_init(void) -{ - unsigned i = 0; - while (i < ARRAY_SIZE(mcf_gpio_chips)) - (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]); - return 0; -} - -core_initcall(mcf_gpio_init); -- cgit v0.10.2 From 622e9472dd723d5c7dc034510faae4b113e5bbc2 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Thu, 23 Jun 2011 15:52:25 +1000 Subject: m68knommu: correctly use trap_init Currently trap_init() is an empty function for m68knommu. Instead the vectors are being setup as part of the IRQ initialization. This is inconsistent with m68k and other architectures. Change the local init_vectors() to be trap_init(), and init the vectors at the correct time during startup. This will help merge of m68k and m68knommu trap code in the furture. Signed-off-by: Greg Ungerer diff --git a/arch/m68k/include/asm/traps.h b/arch/m68k/include/asm/traps.h index 0bffb17..151068f 100644 --- a/arch/m68k/include/asm/traps.h +++ b/arch/m68k/include/asm/traps.h @@ -22,7 +22,6 @@ extern e_vector vectors[]; asmlinkage void auto_inthandler(void); asmlinkage void user_inthandler(void); asmlinkage void bad_inthandler(void); -extern void init_vectors(void); #endif diff --git a/arch/m68k/kernel/traps_no.c b/arch/m68k/kernel/traps_no.c index a768008..e67b8c8 100644 --- a/arch/m68k/kernel/traps_no.c +++ b/arch/m68k/kernel/traps_no.c @@ -60,10 +60,6 @@ static char const * const vec_names[] = { "MMU CONFIGURATION ERROR" }; -void __init trap_init(void) -{ -} - void die_if_kernel(char *str, struct pt_regs *fp, int nr) { if (!(fp->sr & PS_S)) diff --git a/arch/m68k/platform/5272/intc.c b/arch/m68k/platform/5272/intc.c index 7e715df..7160e61 100644 --- a/arch/m68k/platform/5272/intc.c +++ b/arch/m68k/platform/5272/intc.c @@ -162,8 +162,6 @@ void __init init_IRQ(void) { int irq, edge; - init_vectors(); - /* Mask all interrupt sources */ writel(0x88888888, MCF_MBAR + MCFSIM_ICR1); writel(0x88888888, MCF_MBAR + MCFSIM_ICR2); diff --git a/arch/m68k/platform/68328/ints.c b/arch/m68k/platform/68328/ints.c index a90288c..22acb60 100644 --- a/arch/m68k/platform/68328/ints.c +++ b/arch/m68k/platform/68328/ints.c @@ -155,7 +155,7 @@ static struct irq_chip intc_irq_chip = { * This function should be called during kernel startup to initialize * the machine vector table. */ -void __init init_IRQ(void) +void __init trap_init(void) { int i; @@ -172,6 +172,11 @@ void __init init_IRQ(void) _ramvec[69] = (e_vector) inthandler5; _ramvec[70] = (e_vector) inthandler6; _ramvec[71] = (e_vector) inthandler7; +} + +void __init init_IRQ(void) +{ + int i; IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */ diff --git a/arch/m68k/platform/68360/ints.c b/arch/m68k/platform/68360/ints.c index 4af0f4e..4444382 100644 --- a/arch/m68k/platform/68360/ints.c +++ b/arch/m68k/platform/68360/ints.c @@ -63,9 +63,8 @@ static struct irq_chip intc_irq_chip = { * This function should be called during kernel startup to initialize * the vector table. */ -void init_IRQ(void) +void __init trap_init(void) { - int i; int vba = (CPM_VECTOR_BASE<<4); /* set up the vectors */ @@ -130,6 +129,11 @@ void init_IRQ(void) /* turn off all CPM interrupts */ pquicc->intr_cimr = 0x00000000; +} + +void init_IRQ(void) +{ + int i; for (i = 0; (i < NR_IRQS); i++) { irq_set_chip(i, &intc_irq_chip); diff --git a/arch/m68k/platform/coldfire/intc-2.c b/arch/m68k/platform/coldfire/intc-2.c index 74b55cf..9950933 100644 --- a/arch/m68k/platform/coldfire/intc-2.c +++ b/arch/m68k/platform/coldfire/intc-2.c @@ -194,8 +194,6 @@ void __init init_IRQ(void) { int irq; - init_vectors(); - /* Mask all interrupt sources */ __raw_writel(0x1, MCFICM_INTC0 + MCFINTC_IMRL); #ifdef MCFICM_INTC1 diff --git a/arch/m68k/platform/coldfire/intc-simr.c b/arch/m68k/platform/coldfire/intc-simr.c index d6a4d9d..650d52e 100644 --- a/arch/m68k/platform/coldfire/intc-simr.c +++ b/arch/m68k/platform/coldfire/intc-simr.c @@ -171,8 +171,6 @@ void __init init_IRQ(void) { int irq, eirq; - init_vectors(); - /* Mask all interrupt sources */ __raw_writeb(0xff, MCFINTC0_SIMR); if (MCFINTC1_SIMR) diff --git a/arch/m68k/platform/coldfire/intc.c b/arch/m68k/platform/coldfire/intc.c index 0bbb414..5c0c150 100644 --- a/arch/m68k/platform/coldfire/intc.c +++ b/arch/m68k/platform/coldfire/intc.c @@ -139,7 +139,6 @@ void __init init_IRQ(void) { int irq; - init_vectors(); mcf_maskimr(0xffffffff); for (irq = 0; (irq < NR_IRQS); irq++) { diff --git a/arch/m68k/platform/coldfire/vectors.c b/arch/m68k/platform/coldfire/vectors.c index a21d3f8..3a7cc52 100644 --- a/arch/m68k/platform/coldfire/vectors.c +++ b/arch/m68k/platform/coldfire/vectors.c @@ -35,21 +35,13 @@ asmlinkage void dbginterrupt_c(struct frame *fp) extern e_vector *_ramvec; -void set_evector(int vecnum, void (*handler)(void)) -{ - if (vecnum >= 0 && vecnum <= 255) - _ramvec[vecnum] = handler; -} - -/***************************************************************************/ - /* Assembler routines */ asmlinkage void buserr(void); asmlinkage void trap(void); asmlinkage void system_call(void); asmlinkage void inthandler(void); -void __init init_vectors(void) +void __init trap_init(void) { int i; -- cgit v0.10.2 From 7c946199cd5eab2917bb053ca6fdc6997d27aa7a Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Fri, 1 Jul 2011 16:47:13 +1000 Subject: m68k: merge and clean up delay.h files The real difference between the mmu and non-mmu varients of the delay.h files has nothing to do with having an mmu or not. It is processor family differences that means slightly different code. Merge the delay_mm.h and delay_no.h files back into a single file. The primarly difference we need to deal with is whether the processor supports a 32bit * 32bit -> 64bit multiply. Without it we need to do some shift scaling as well as use a 32bit * 32bit -> 32bit multiply. If building for a multi-CPU type kernel then we must use the simpler mult/shift scaling. This version of delay code allows the CPU32 family to use a 64bit mul, since it supports this instruction, the old code did not. The changes use macros where appropriate to try and optimize constant sized udelay times. And it removes the use of a fixed lib function for the non-mmu case. Code size on typical kernel configurations is similar, or only larger by a few tens of bytes. Also removed the unused muldiv() code from delay_mm.h. Build and run tested on ColdFire and ARAnyM. Build tested only on 68328 and 68360 (CPU32). Signed-off-by: Greg Ungerer diff --git a/arch/m68k/include/asm/delay.h b/arch/m68k/include/asm/delay.h index d2598e3..9c09bec 100644 --- a/arch/m68k/include/asm/delay.h +++ b/arch/m68k/include/asm/delay.h @@ -1,5 +1,96 @@ -#ifdef __uClinux__ -#include "delay_no.h" +#ifndef _M68K_DELAY_H +#define _M68K_DELAY_H + +#include + +/* + * Copyright (C) 1994 Hamish Macdonald + * Copyright (C) 2004 Greg Ungerer + * + * Delay routines, using a pre-computed "loops_per_jiffy" value. + */ + +#if defined(CONFIG_COLDFIRE) +/* + * The ColdFire runs the delay loop at significantly different speeds + * depending upon long word alignment or not. We'll pad it to + * long word alignment which is the faster version. + * The 0x4a8e is of course a 'tstl %fp' instruction. This is better + * than using a NOP (0x4e71) instruction because it executes in one + * cycle not three and doesn't allow for an arbitrary delay waiting + * for bus cycles to finish. Also fp/a6 isn't likely to cause a + * stall waiting for the register to become valid if such is added + * to the coldfire at some stage. + */ +#define DELAY_ALIGN ".balignw 4, 0x4a8e\n\t" #else -#include "delay_mm.h" +/* + * No instruction alignment required for other m68k types. + */ +#define DELAY_ALIGN #endif + +static inline void __delay(unsigned long loops) +{ + __asm__ __volatile__ ( + DELAY_ALIGN + "1: subql #1,%0\n\t" + "jcc 1b" + : "=d" (loops) + : "0" (loops)); +} + +extern void __bad_udelay(void); + + +#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) +/* + * The simpler m68k and ColdFire processors do not have a 32*32->64 + * multiply instruction. So we need to handle them a little differently. + * We use a bit of shifting and a single 32*32->32 multiply to get close. + * This is a macro so that the const version can factor out the first + * multiply and shift. + */ +#define HZSCALE (268435456 / (1000000 / HZ)) + +#define __const_udelay(u) \ + __delay(((((u) * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6) + +#else + +static inline void __xdelay(unsigned long xloops) +{ + unsigned long tmp; + + __asm__ ("mulul %2,%0:%1" + : "=d" (xloops), "=d" (tmp) + : "d" (xloops), "1" (loops_per_jiffy)); + __delay(xloops * HZ); +} + +/* + * The definition of __const_udelay is specifically made a macro so that + * the const factor (4295 = 2**32 / 1000000) can be optimized out when + * the delay is a const. + */ +#define __const_udelay(n) (__xdelay((n) * 4295)) + +#endif + +static inline void __udelay(unsigned long usecs) +{ + __const_udelay(usecs); +} + +/* + * Use only for very small delays ( < 1 msec). Should probably use a + * lookup table, really, as the multiplications take much too long with + * short delays. This is a "reasonable" implementation, though (and the + * first constant multiplications gets optimized away if the delay is + * a constant) + */ +#define udelay(n) (__builtin_constant_p(n) ? \ + ((n) > 20000 ? __bad_udelay() : __const_udelay(n)) : __udelay(n)) + + +#endif /* defined(_M68K_DELAY_H) */ diff --git a/arch/m68k/include/asm/delay_mm.h b/arch/m68k/include/asm/delay_mm.h deleted file mode 100644 index 5ed9285..0000000 --- a/arch/m68k/include/asm/delay_mm.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _M68K_DELAY_H -#define _M68K_DELAY_H - -#include - -/* - * Copyright (C) 1994 Hamish Macdonald - * - * Delay routines, using a pre-computed "loops_per_jiffy" value. - */ - -static inline void __delay(unsigned long loops) -{ - __asm__ __volatile__ ("1: subql #1,%0; jcc 1b" - : "=d" (loops) : "0" (loops)); -} - -extern void __bad_udelay(void); - -/* - * Use only for very small delays ( < 1 msec). Should probably use a - * lookup table, really, as the multiplications take much too long with - * short delays. This is a "reasonable" implementation, though (and the - * first constant multiplications gets optimized away if the delay is - * a constant) - */ -static inline void __const_udelay(unsigned long xloops) -{ - unsigned long tmp; - - __asm__ ("mulul %2,%0:%1" - : "=d" (xloops), "=d" (tmp) - : "d" (xloops), "1" (loops_per_jiffy)); - __delay(xloops * HZ); -} - -static inline void __udelay(unsigned long usecs) -{ - __const_udelay(usecs * 4295); /* 2**32 / 1000000 */ -} - -#define udelay(n) (__builtin_constant_p(n) ? \ - ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 4295)) : \ - __udelay(n)) - -static inline unsigned long muldiv(unsigned long a, unsigned long b, - unsigned long c) -{ - unsigned long tmp; - - __asm__ ("mulul %2,%0:%1; divul %3,%0:%1" - : "=d" (tmp), "=d" (a) - : "d" (b), "d" (c), "1" (a)); - return a; -} - -#endif /* defined(_M68K_DELAY_H) */ diff --git a/arch/m68k/include/asm/delay_no.h b/arch/m68k/include/asm/delay_no.h deleted file mode 100644 index c3a0edc..0000000 --- a/arch/m68k/include/asm/delay_no.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef _M68KNOMMU_DELAY_H -#define _M68KNOMMU_DELAY_H - -/* - * Copyright (C) 1994 Hamish Macdonald - * Copyright (C) 2004 Greg Ungerer - */ - -#include - -static inline void __delay(unsigned long loops) -{ -#if defined(CONFIG_COLDFIRE) - /* The coldfire runs this loop at significantly different speeds - * depending upon long word alignment or not. We'll pad it to - * long word alignment which is the faster version. - * The 0x4a8e is of course a 'tstl %fp' instruction. This is better - * than using a NOP (0x4e71) instruction because it executes in one - * cycle not three and doesn't allow for an arbitrary delay waiting - * for bus cycles to finish. Also fp/a6 isn't likely to cause a - * stall waiting for the register to become valid if such is added - * to the coldfire at some stage. - */ - __asm__ __volatile__ ( ".balignw 4, 0x4a8e\n\t" - "1: subql #1, %0\n\t" - "jcc 1b" - : "=d" (loops) : "0" (loops)); -#else - __asm__ __volatile__ ( "1: subql #1, %0\n\t" - "jcc 1b" - : "=d" (loops) : "0" (loops)); -#endif -} - -/* - * Ideally we use a 32*32->64 multiply to calculate the number of - * loop iterations, but the older standard 68k and ColdFire do not - * have this instruction. So for them we have a clsoe approximation - * loop using 32*32->32 multiplies only. This calculation based on - * the ARM version of delay. - * - * We want to implement: - * - * loops = (usecs * 0x10c6 * HZ * loops_per_jiffy) / 2^32 - */ - -#define HZSCALE (268435456 / (1000000/HZ)) - -extern unsigned long loops_per_jiffy; - -static inline void _udelay(unsigned long usecs) -{ -#if defined(CONFIG_M68328) || defined(CONFIG_M68EZ328) || \ - defined(CONFIG_M68VZ328) || defined(CONFIG_M68360) || \ - defined(CONFIG_COLDFIRE) - __delay((((usecs * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6); -#else - unsigned long tmp; - - usecs *= 4295; /* 2**32 / 1000000 */ - __asm__ ("mulul %2,%0:%1" - : "=d" (usecs), "=d" (tmp) - : "d" (usecs), "1" (loops_per_jiffy*HZ)); - __delay(usecs); -#endif -} - -/* - * Moved the udelay() function into library code, no longer inlined. - * I had to change the algorithm because we are overflowing now on - * the faster ColdFire parts. The code is a little bigger, so it makes - * sense to library it. - */ -extern void udelay(unsigned long usecs); - -#endif /* defined(_M68KNOMMU_DELAY_H) */ diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile index df421e5..1a1bd90 100644 --- a/arch/m68k/lib/Makefile +++ b/arch/m68k/lib/Makefile @@ -9,6 +9,6 @@ lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ ifdef CONFIG_MMU lib-y += string.o uaccess.o checksum_mm.o else -lib-y += mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o delay.o checksum_no.o +lib-y += mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o checksum_no.o endif diff --git a/arch/m68k/lib/delay.c b/arch/m68k/lib/delay.c deleted file mode 100644 index 5bd5472..0000000 --- a/arch/m68k/lib/delay.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * arch/m68knommu/lib/delay.c - * - * (C) Copyright 2004, Greg Ungerer - * - * 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 - -EXPORT_SYMBOL(udelay); - -void udelay(unsigned long usecs) -{ - _udelay(usecs); -} - -- cgit v0.10.2 From f3c23a28ace0a42ea06b5860b3bd25f71fc14c89 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 4 Jul 2011 14:23:09 +1000 Subject: m68k: use CPU_HAS_NO_BITFIELDS for signal functions When reworking bitops.h to be clean for all processor types we introduced a CONFIG_CPU_HAS_NO_BITFIELDS define to signal whether this processor type supported the bit field instructions. The ARCH_SIG_BITOPS functions for m68k use these instruction types. We should base the use of these functions (or the generic versions) on the CONFIG_CPU_HAS_NO_BITFIELDS define. Signed-off-by: Greg Ungerer diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h index 5bc09c7..60e8866 100644 --- a/arch/m68k/include/asm/signal.h +++ b/arch/m68k/include/asm/signal.h @@ -150,7 +150,7 @@ typedef struct sigaltstack { #ifdef __KERNEL__ #include -#ifndef __uClinux__ +#ifndef CONFIG_CPU_HAS_NO_BITFIELDS #define __HAVE_ARCH_SIG_BITOPS static inline void sigaddset(sigset_t *set, int _sig) @@ -199,15 +199,14 @@ static inline int sigfindinword(unsigned long word) return word ^ 31; } -struct pt_regs; -extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie); +#endif /* !CONFIG_CPU_HAS_NO_BITFIELDS */ -#else - -#undef __HAVE_ARCH_SIG_BITOPS +#ifdef __uClinux__ #define ptrace_signal_deliver(regs, cookie) do { } while (0) - +#else +struct pt_regs; +extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie); #endif /* __uClinux__ */ -#endif /* __KERNEL__ */ +#endif /* __KERNEL__ */ #endif /* _M68K_SIGNAL_H */ -- cgit v0.10.2 From 35de674982aa13de98cf470c640895164017563e Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 4 Jul 2011 15:30:55 +1000 Subject: m68k: fix some atomic operation asm address modes for ColdFire The ColdFire processors have a much more limited set of addressing modes that can be used for most instructions. A number of the atomic operations have already been fixed to limit the addressing modes used with add and sub instructions when building for ColdFire. But we missed a few. Fix the remaining atomic operations to be clean for ColdFire processors. Signed-off-by: Greg Ungerer diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h index 03ae3d1..307a573 100644 --- a/arch/m68k/include/asm/atomic.h +++ b/arch/m68k/include/asm/atomic.h @@ -169,18 +169,18 @@ static inline int atomic_add_negative(int i, atomic_t *v) char c; __asm__ __volatile__("addl %2,%1; smi %0" : "=d" (c), "+m" (*v) - : "id" (i)); + : ASM_DI (i)); return c != 0; } static inline void atomic_clear_mask(unsigned long mask, unsigned long *v) { - __asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask))); + __asm__ __volatile__("andl %1,%0" : "+m" (*v) : ASM_DI (~(mask))); } static inline void atomic_set_mask(unsigned long mask, unsigned long *v) { - __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask)); + __asm__ __volatile__("orl %1,%0" : "+m" (*v) : ASM_DI (mask)); } static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) -- cgit v0.10.2 From 739735d5fea3c3997b2a659068a618b07bc9a73a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 3 Jul 2011 11:09:57 +0200 Subject: m68knommu: Move forward declaration of do_IRQ() from machdep.h to irq.h It is not machine-specific, but common irq infrastructure. Also add the missing asmlinkage, to match its definition. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Ungerer diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 67c9738..69ed0d74 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -122,4 +122,6 @@ asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *); #define irq_canonicalize(irq) (irq) #endif /* CONFIG_MMU */ +asmlinkage void do_IRQ(int irq, struct pt_regs *regs); + #endif /* _M68K_IRQ_H_ */ diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h index 415d548..789f3b2 100644 --- a/arch/m68k/include/asm/machdep.h +++ b/arch/m68k/include/asm/machdep.h @@ -40,6 +40,5 @@ extern unsigned long hw_timer_offset(void); extern irqreturn_t arch_timer_interrupt(int irq, void *dummy); extern void config_BSP(char *command, int len); -extern void do_IRQ(int irq, struct pt_regs *fp); #endif /* _M68K_MACHDEP_H */ -- cgit v0.10.2 From 8c9f08f9de38c9af3a946faf0cccd7fc46978443 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Jul 2011 20:29:24 +0200 Subject: m68k: Revive reporting of spurious interrupts commit 2502b667ea835ee16685c74b2a0d89ba8afe117a ("Change the m68knommu irq handling to use the generic irq framework.") removed the reporting of spurious interrupts on nommu (68328 and 68360). Bring it back in a generic way, using "atomic_t irq_err_count", as that's what most of the other architectures are using. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Ungerer diff --git a/arch/m68k/kernel/irq.c b/arch/m68k/kernel/irq.c index 544b871..c73988c 100644 --- a/arch/m68k/kernel/irq.c +++ b/arch/m68k/kernel/irq.c @@ -28,3 +28,13 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs) set_irq_regs(oldregs); } + + +/* The number of spurious interrupts */ +atomic_t irq_err_count; + +int arch_show_interrupts(struct seq_file *p, int prec) +{ + seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); + return 0; +} diff --git a/arch/m68k/platform/68328/entry.S b/arch/m68k/platform/68328/entry.S index 4ed7a65..293e1eb 100644 --- a/arch/m68k/platform/68328/entry.S +++ b/arch/m68k/platform/68328/entry.S @@ -236,7 +236,7 @@ ret_from_interrupt: * Handler for uninitialized and spurious interrupts. */ ENTRY(bad_interrupt) - addql #1,num_spurious + addql #1,irq_err_count rte /* diff --git a/arch/m68k/platform/68328/ints.c b/arch/m68k/platform/68328/ints.c index 22acb60..4bd4565 100644 --- a/arch/m68k/platform/68328/ints.c +++ b/arch/m68k/platform/68328/ints.c @@ -70,9 +70,6 @@ asmlinkage irqreturn_t inthandler7(void); extern e_vector *_ramvec; -/* The number of spurious interrupts */ -volatile unsigned int num_spurious; - /* The 68k family did not have a good way to determine the source * of interrupts until later in the family. The EC000 core does * not provide the vector number on the stack, we vector everything diff --git a/arch/m68k/platform/68360/entry.S b/arch/m68k/platform/68360/entry.S index 0ede670..abbb896 100644 --- a/arch/m68k/platform/68360/entry.S +++ b/arch/m68k/platform/68360/entry.S @@ -157,7 +157,7 @@ ret_from_interrupt: * Handler for uninitialized and spurious interrupts. */ bad_interrupt: - addql #1,num_spurious + addql #1,irq_err_count rte /* diff --git a/arch/m68k/platform/68360/ints.c b/arch/m68k/platform/68360/ints.c index 4444382..7b40202 100644 --- a/arch/m68k/platform/68360/ints.c +++ b/arch/m68k/platform/68360/ints.c @@ -34,9 +34,6 @@ asmlinkage void inthandler(void); extern void *_ramvec[]; -/* The number of spurious interrupts */ -volatile unsigned int num_spurious; - static void intc_irq_unmask(struct irq_data *d) { pquicc->intr_cimr |= (1 << d->irq); -- cgit v0.10.2