diff options
author | Yi Li <yi.li@analog.com> | 2009-01-07 23:14:39 +0800 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2009-01-07 23:14:39 +0800 |
commit | 6a01f230339321292cf065551f8cf55361052461 (patch) | |
tree | 7ac2ac8fc9f05a7315ef6a7f6f0a387433c62c14 /arch/blackfin/include | |
parent | 5105432a3201e3f0e6c219cd0a74feee1e5e262b (diff) |
Blackfin arch: merge adeos blackfin part to arch/blackfin/
[Mike Frysinger <vapier.adi@gmail.com>:
- handle bf531/bf532/bf534/bf536 variants in ipipe.h
- cleanup IPIPE logic for bfin_set_irq_handler()
- cleanup ipipe asm code a bit and add missing ENDPROC()
- simplify IPIPE code in trap_c
- unify some of the IPIPE code and fix style
- simplify DO_IRQ_L1 handling with ipipe code
- revert IRQ_SW_INT# addition from ipipe merge
- remove duplicate get_{c,s}clk() prototypes
]
Signed-off-by: Yi Li <yi.li@analog.com>
Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin/include')
-rw-r--r-- | arch/blackfin/include/asm/atomic.h | 32 | ||||
-rw-r--r-- | arch/blackfin/include/asm/bitops.h | 24 | ||||
-rw-r--r-- | arch/blackfin/include/asm/entry.h | 9 | ||||
-rw-r--r-- | arch/blackfin/include/asm/ipipe.h | 278 | ||||
-rw-r--r-- | arch/blackfin/include/asm/ipipe_base.h | 80 | ||||
-rw-r--r-- | arch/blackfin/include/asm/irq.h | 223 | ||||
-rw-r--r-- | arch/blackfin/include/asm/system.h | 4 |
7 files changed, 593 insertions, 57 deletions
diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h index d76275e5638c..94b2a9b19451 100644 --- a/arch/blackfin/include/asm/atomic.h +++ b/arch/blackfin/include/asm/atomic.h @@ -92,18 +92,18 @@ static inline void atomic_add(int i, atomic_t *v) { long flags; - local_irq_save(flags); + local_irq_save_hw(flags); v->counter += i; - local_irq_restore(flags); + local_irq_restore_hw(flags); } static inline void atomic_sub(int i, atomic_t *v) { long flags; - local_irq_save(flags); + local_irq_save_hw(flags); v->counter -= i; - local_irq_restore(flags); + local_irq_restore_hw(flags); } @@ -112,10 +112,10 @@ static inline int atomic_add_return(int i, atomic_t *v) int __temp = 0; long flags; - local_irq_save(flags); + local_irq_save_hw(flags); v->counter += i; __temp = v->counter; - local_irq_restore(flags); + local_irq_restore_hw(flags); return __temp; @@ -126,10 +126,10 @@ static inline int atomic_sub_return(int i, atomic_t *v) int __temp = 0; long flags; - local_irq_save(flags); + local_irq_save_hw(flags); v->counter -= i; __temp = v->counter; - local_irq_restore(flags); + local_irq_restore_hw(flags); return __temp; } @@ -138,36 +138,36 @@ static inline void atomic_inc(volatile atomic_t *v) { long flags; - local_irq_save(flags); + local_irq_save_hw(flags); v->counter++; - local_irq_restore(flags); + local_irq_restore_hw(flags); } static inline void atomic_dec(volatile atomic_t *v) { long flags; - local_irq_save(flags); + local_irq_save_hw(flags); v->counter--; - local_irq_restore(flags); + local_irq_restore_hw(flags); } static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) { long flags; - local_irq_save(flags); + local_irq_save_hw(flags); v->counter &= ~mask; - local_irq_restore(flags); + local_irq_restore_hw(flags); } static inline void atomic_set_mask(unsigned int mask, atomic_t *v) { long flags; - local_irq_save(flags); + local_irq_save_hw(flags); v->counter |= mask; - local_irq_restore(flags); + local_irq_restore_hw(flags); } /* Atomic operations are already serializing */ diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h index 9964e17232e9..21b036eadab1 100644 --- a/arch/blackfin/include/asm/bitops.h +++ b/arch/blackfin/include/asm/bitops.h @@ -90,9 +90,9 @@ static inline void set_bit(int nr, volatile unsigned long *addr) unsigned long flags; a += nr >> 5; mask = 1 << (nr & 0x1f); - local_irq_save(flags); + local_irq_save_hw(flags); *a |= mask; - local_irq_restore(flags); + local_irq_restore_hw(flags); } static inline void clear_bit(int nr, volatile unsigned long *addr) @@ -102,9 +102,9 @@ static inline void clear_bit(int nr, volatile unsigned long *addr) unsigned long flags; a += nr >> 5; mask = 1 << (nr & 0x1f); - local_irq_save(flags); + local_irq_save_hw(flags); *a &= ~mask; - local_irq_restore(flags); + local_irq_restore_hw(flags); } static inline void change_bit(int nr, volatile unsigned long *addr) @@ -114,9 +114,9 @@ static inline void change_bit(int nr, volatile unsigned long *addr) ADDR += nr >> 5; mask = 1 << (nr & 31); - local_irq_save(flags); + local_irq_save_hw(flags); *ADDR ^= mask; - local_irq_restore(flags); + local_irq_restore_hw(flags); } static inline int test_and_set_bit(int nr, volatile unsigned long *addr) @@ -127,10 +127,10 @@ static inline int test_and_set_bit(int nr, volatile unsigned long *addr) a += nr >> 5; mask = 1 << (nr & 0x1f); - local_irq_save(flags); + local_irq_save_hw(flags); retval = (mask & *a) != 0; *a |= mask; - local_irq_restore(flags); + local_irq_restore_hw(flags); return retval; } @@ -143,10 +143,10 @@ static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) a += nr >> 5; mask = 1 << (nr & 0x1f); - local_irq_save(flags); + local_irq_save_hw(flags); retval = (mask & *a) != 0; *a &= ~mask; - local_irq_restore(flags); + local_irq_restore_hw(flags); return retval; } @@ -159,10 +159,10 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr) a += nr >> 5; mask = 1 << (nr & 0x1f); - local_irq_save(flags); + local_irq_save_hw(flags); retval = (mask & *a) != 0; *a ^= mask; - local_irq_restore(flags); + local_irq_restore_hw(flags); return retval; } diff --git a/arch/blackfin/include/asm/entry.h b/arch/blackfin/include/asm/entry.h index d94e4f5139d2..b30a2968e274 100644 --- a/arch/blackfin/include/asm/entry.h +++ b/arch/blackfin/include/asm/entry.h @@ -27,6 +27,14 @@ #define SAVE_ALL_SYS save_context_no_interrupts /* This is used for all normal interrupts. It saves a minimum of registers to the stack, loads the IRQ number, and jumps to common code. */ +#ifdef CONFIG_IPIPE +# define LOAD_IPIPE_IPEND \ + P0.l = lo(IPEND); \ + P0.h = hi(IPEND); \ + R1 = [P0]; +#else +# define LOAD_IPIPE_IPEND +#endif #define INTERRUPT_ENTRY(N) \ [--sp] = SYSCFG; \ \ @@ -34,6 +42,7 @@ [--sp] = R0; /*orig_r0*/ \ [--sp] = (R7:0,P5:0); \ R0 = (N); \ + LOAD_IPIPE_IPEND \ jump __common_int_entry; /* For timer interrupts, we need to save IPEND, since the user_mode diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h new file mode 100644 index 000000000000..76f53d8b9a0d --- /dev/null +++ b/arch/blackfin/include/asm/ipipe.h @@ -0,0 +1,278 @@ +/* -*- linux-c -*- + * include/asm-blackfin/ipipe.h + * + * Copyright (C) 2002-2007 Philippe Gerum. + * + * 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, Inc., 675 Mass Ave, Cambridge MA 02139, + * USA; either version 2 of the License, or (at your option) any later + * version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __ASM_BLACKFIN_IPIPE_H +#define __ASM_BLACKFIN_IPIPE_H + +#ifdef CONFIG_IPIPE + +#include <linux/cpumask.h> +#include <linux/list.h> +#include <linux/threads.h> +#include <linux/irq.h> +#include <linux/ipipe_percpu.h> +#include <asm/ptrace.h> +#include <asm/irq.h> +#include <asm/bitops.h> +#include <asm/atomic.h> +#include <asm/traps.h> + +#define IPIPE_ARCH_STRING "1.8-00" +#define IPIPE_MAJOR_NUMBER 1 +#define IPIPE_MINOR_NUMBER 8 +#define IPIPE_PATCH_NUMBER 0 + +#ifdef CONFIG_SMP +#error "I-pipe/blackfin: SMP not implemented" +#else /* !CONFIG_SMP */ +#define ipipe_processor_id() 0 +#endif /* CONFIG_SMP */ + +#define prepare_arch_switch(next) \ +do { \ + ipipe_schedule_notify(current, next); \ + local_irq_disable_hw(); \ +} while (0) + +#define task_hijacked(p) \ + ({ \ + int __x__ = ipipe_current_domain != ipipe_root_domain; \ + /* We would need to clear the SYNC flag for the root domain */ \ + /* over the current processor in SMP mode. */ \ + local_irq_enable_hw(); __x__; \ + }) + +struct ipipe_domain; + +struct ipipe_sysinfo { + + int ncpus; /* Number of CPUs on board */ + u64 cpufreq; /* CPU frequency (in Hz) */ + + /* Arch-dependent block */ + + struct { + unsigned tmirq; /* Timer tick IRQ */ + u64 tmfreq; /* Timer frequency */ + } archdep; +}; + +#define ipipe_read_tsc(t) \ + ({ \ + unsigned long __cy2; \ + __asm__ __volatile__ ("1: %0 = CYCLES2\n" \ + "%1 = CYCLES\n" \ + "%2 = CYCLES2\n" \ + "CC = %2 == %0\n" \ + "if ! CC jump 1b\n" \ + : "=r" (((unsigned long *)&t)[1]), \ + "=r" (((unsigned long *)&t)[0]), \ + "=r" (__cy2) \ + : /*no input*/ : "CC"); \ + t; \ + }) + +#define ipipe_cpu_freq() __ipipe_core_clock +#define ipipe_tsc2ns(_t) (((unsigned long)(_t)) * __ipipe_freq_scale) +#define ipipe_tsc2us(_t) (ipipe_tsc2ns(_t) / 1000 + 1) + +/* Private interface -- Internal use only */ + +#define __ipipe_check_platform() do { } while (0) + +#define __ipipe_init_platform() do { } while (0) + +extern atomic_t __ipipe_irq_lvdepth[IVG15 + 1]; + +extern unsigned long __ipipe_irq_lvmask; + +extern struct ipipe_domain ipipe_root; + +/* enable/disable_irqdesc _must_ be used in pairs. */ + +void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, + unsigned irq); + +void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, + unsigned irq); + +#define __ipipe_enable_irq(irq) (irq_desc[irq].chip->unmask(irq)) + +#define __ipipe_disable_irq(irq) (irq_desc[irq].chip->mask(irq)) + +#define __ipipe_lock_root() \ + set_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags) + +#define __ipipe_unlock_root() \ + clear_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags) + +void __ipipe_enable_pipeline(void); + +#define __ipipe_hook_critical_ipi(ipd) do { } while (0) + +#define __ipipe_sync_pipeline(syncmask) \ + do { \ + struct ipipe_domain *ipd = ipipe_current_domain; \ + if (likely(ipd != ipipe_root_domain || !test_bit(IPIPE_ROOTLOCK_FLAG, &ipd->flags))) \ + __ipipe_sync_stage(syncmask); \ + } while (0) + +void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs); + +int __ipipe_get_irq_priority(unsigned irq); + +int __ipipe_get_irqthread_priority(unsigned irq); + +void __ipipe_stall_root_raw(void); + +void __ipipe_unstall_root_raw(void); + +void __ipipe_serial_debug(const char *fmt, ...); + +DECLARE_PER_CPU(struct pt_regs, __ipipe_tick_regs); + +extern unsigned long __ipipe_core_clock; + +extern unsigned long __ipipe_freq_scale; + +extern unsigned long __ipipe_irq_tail_hook; + +static inline unsigned long __ipipe_ffnz(unsigned long ul) +{ + return ffs(ul) - 1; +} + +#define __ipipe_run_irqtail() /* Must be a macro */ \ + do { \ + asmlinkage void __ipipe_call_irqtail(void); \ + unsigned long __pending; \ + CSYNC(); \ + __pending = bfin_read_IPEND(); \ + if (__pending & 0x8000) { \ + __pending &= ~0x8010; \ + if (__pending && (__pending & (__pending - 1)) == 0) \ + __ipipe_call_irqtail(); \ + } \ + } while (0) + +#define __ipipe_run_isr(ipd, irq) \ + do { \ + if (ipd == ipipe_root_domain) { \ + /* \ + * Note: the I-pipe implements a threaded interrupt model on \ + * this arch for Linux external IRQs. The interrupt handler we \ + * call here only wakes up the associated IRQ thread. \ + */ \ + if (ipipe_virtual_irq_p(irq)) { \ + /* No irqtail here; virtual interrupts have no effect \ + on IPEND so there is no need for processing \ + deferral. */ \ + local_irq_enable_nohead(ipd); \ + ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \ + local_irq_disable_nohead(ipd); \ + } else \ + /* \ + * No need to run the irqtail here either; \ + * we can't be preempted by hw IRQs, so \ + * non-Linux IRQs cannot stack over the short \ + * thread wakeup code. Which in turn means \ + * that no irqtail condition could be pending \ + * for domains above Linux in the pipeline. \ + */ \ + ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \ + } else { \ + __clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \ + local_irq_enable_nohead(ipd); \ + ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \ + /* Attempt to exit the outer interrupt level before \ + * starting the deferred IRQ processing. */ \ + local_irq_disable_nohead(ipd); \ + __ipipe_run_irqtail(); \ + __set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \ + } \ + } while (0) + +#define __ipipe_syscall_watched_p(p, sc) \ + (((p)->flags & PF_EVNOTIFY) || (unsigned long)sc >= NR_syscalls) + +void ipipe_init_irq_threads(void); + +int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc); + +#define IS_SYSIRQ(irq) ((irq) > IRQ_CORETMR && (irq) <= SYS_IRQS) +#define IS_GPIOIRQ(irq) ((irq) >= GPIO_IRQ_BASE && (irq) < NR_IRQS) + +#define IRQ_SYSTMR IRQ_TIMER0 +#define IRQ_PRIOTMR CONFIG_IRQ_TIMER0 + +#if defined(CONFIG_BF531) || defined(CONFIG_BF532) || defined(CONFIG_BF533) +#define PRIO_GPIODEMUX(irq) CONFIG_PFA +#elif defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537) +#define PRIO_GPIODEMUX(irq) CONFIG_IRQ_PROG_INTA +#elif defined(CONFIG_BF52x) +#define PRIO_GPIODEMUX(irq) ((irq) == IRQ_PORTF_INTA ? CONFIG_IRQ_PORTF_INTA : \ + (irq) == IRQ_PORTG_INTA ? CONFIG_IRQ_PORTG_INTA : \ + (irq) == IRQ_PORTH_INTA ? CONFIG_IRQ_PORTH_INTA : \ + -1) +#elif defined(CONFIG_BF561) +#define PRIO_GPIODEMUX(irq) ((irq) == IRQ_PROG0_INTA ? CONFIG_IRQ_PROG0_INTA : \ + (irq) == IRQ_PROG1_INTA ? CONFIG_IRQ_PROG1_INTA : \ + (irq) == IRQ_PROG2_INTA ? CONFIG_IRQ_PROG2_INTA : \ + -1) +#define bfin_write_TIMER_DISABLE(val) bfin_write_TMRS8_DISABLE(val) +#define bfin_write_TIMER_ENABLE(val) bfin_write_TMRS8_ENABLE(val) +#define bfin_write_TIMER_STATUS(val) bfin_write_TMRS8_STATUS(val) +#define bfin_read_TIMER_STATUS() bfin_read_TMRS8_STATUS() +#elif defined(CONFIG_BF54x) +#define PRIO_GPIODEMUX(irq) ((irq) == IRQ_PINT0 ? CONFIG_IRQ_PINT0 : \ + (irq) == IRQ_PINT1 ? CONFIG_IRQ_PINT1 : \ + (irq) == IRQ_PINT2 ? CONFIG_IRQ_PINT2 : \ + (irq) == IRQ_PINT3 ? CONFIG_IRQ_PINT3 : \ + -1) +#define bfin_write_TIMER_DISABLE(val) bfin_write_TIMER_DISABLE0(val) +#define bfin_write_TIMER_ENABLE(val) bfin_write_TIMER_ENABLE0(val) +#define bfin_write_TIMER_STATUS(val) bfin_write_TIMER_STATUS0(val) +#define bfin_read_TIMER_STATUS(val) bfin_read_TIMER_STATUS0(val) +#else +# error "no PRIO_GPIODEMUX() for this part" +#endif + +#define __ipipe_root_tick_p(regs) ((regs->ipend & 0x10) != 0) + +#else /* !CONFIG_IPIPE */ + +#define task_hijacked(p) 0 +#define ipipe_trap_notify(t, r) 0 + +#define __ipipe_stall_root_raw() do { } while (0) +#define __ipipe_unstall_root_raw() do { } while (0) + +#define ipipe_init_irq_threads() do { } while (0) +#define ipipe_start_irq_thread(irq, desc) 0 + +#define IRQ_SYSTMR IRQ_CORETMR +#define IRQ_PRIOTMR IRQ_CORETMR + +#define __ipipe_root_tick_p(regs) 1 + +#endif /* !CONFIG_IPIPE */ + +#endif /* !__ASM_BLACKFIN_IPIPE_H */ diff --git a/arch/blackfin/include/asm/ipipe_base.h b/arch/blackfin/include/asm/ipipe_base.h new file mode 100644 index 000000000000..cb1025aeabcf --- /dev/null +++ b/arch/blackfin/include/asm/ipipe_base.h @@ -0,0 +1,80 @@ +/* -*- linux-c -*- + * include/asm-blackfin/_baseipipe.h + * + * Copyright (C) 2007 Philippe Gerum. + * + * 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, Inc., 675 Mass Ave, Cambridge MA 02139, + * USA; either version 2 of the License, or (at your option) any later + * version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __ASM_BLACKFIN_IPIPE_BASE_H +#define __ASM_BLACKFIN_IPIPE_BASE_H + +#ifdef CONFIG_IPIPE + +#define IPIPE_NR_XIRQS NR_IRQS +#define IPIPE_IRQ_ISHIFT 5 /* 2^5 for 32bits arch. */ + +/* Blackfin-specific, global domain flags */ +#define IPIPE_ROOTLOCK_FLAG 1 /* Lock pipeline for root */ + + /* Blackfin traps -- i.e. exception vector numbers */ +#define IPIPE_NR_FAULTS 52 /* We leave a gap after VEC_ILL_RES. */ +/* Pseudo-vectors used for kernel events */ +#define IPIPE_FIRST_EVENT IPIPE_NR_FAULTS +#define IPIPE_EVENT_SYSCALL (IPIPE_FIRST_EVENT) +#define IPIPE_EVENT_SCHEDULE (IPIPE_FIRST_EVENT + 1) +#define IPIPE_EVENT_SIGWAKE (IPIPE_FIRST_EVENT + 2) +#define IPIPE_EVENT_SETSCHED (IPIPE_FIRST_EVENT + 3) +#define IPIPE_EVENT_INIT (IPIPE_FIRST_EVENT + 4) +#define IPIPE_EVENT_EXIT (IPIPE_FIRST_EVENT + 5) +#define IPIPE_EVENT_CLEANUP (IPIPE_FIRST_EVENT + 6) +#define IPIPE_LAST_EVENT IPIPE_EVENT_CLEANUP +#define IPIPE_NR_EVENTS (IPIPE_LAST_EVENT + 1) + +#define IPIPE_TIMER_IRQ IRQ_CORETMR + +#ifndef __ASSEMBLY__ + +#include <linux/bitops.h> + +extern int test_bit(int nr, const void *addr); + + +extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */ + +static inline void __ipipe_stall_root(void) +{ + volatile unsigned long *p = &__ipipe_root_status; + set_bit(0, p); +} + +static inline unsigned long __ipipe_test_and_stall_root(void) +{ + volatile unsigned long *p = &__ipipe_root_status; + return test_and_set_bit(0, p); +} + +static inline unsigned long __ipipe_test_root(void) +{ + const unsigned long *p = &__ipipe_root_status; + return test_bit(0, p); +} + +#endif /* !__ASSEMBLY__ */ + +#endif /* CONFIG_IPIPE */ + +#endif /* !__ASM_BLACKFIN_IPIPE_BASE_H */ diff --git a/arch/blackfin/include/asm/irq.h b/arch/blackfin/include/asm/irq.h index 21e25f778a63..3d977909ce7d 100644 --- a/arch/blackfin/include/asm/irq.h +++ b/arch/blackfin/include/asm/irq.h @@ -22,11 +22,176 @@ #include <asm/pda.h> #include <asm/processor.h> -static __inline__ int irq_canonicalize(int irq) +#ifdef CONFIG_SMP +/* Forward decl needed due to cdef inter dependencies */ +static inline uint32_t __pure bfin_dspid(void); +# define blackfin_core_id() (bfin_dspid() & 0xff) +# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask +#else +extern unsigned long bfin_irq_flags; +#endif + +#ifdef CONFIG_IPIPE + +#include <linux/ipipe_trace.h> + +void __ipipe_unstall_root(void); + +void __ipipe_restore_root(unsigned long flags); + +#ifdef CONFIG_DEBUG_HWERR +# define __all_masked_irq_flags 0x3f +# define __save_and_cli_hw(x) \ + __asm__ __volatile__( \ + "cli %0;" \ + "sti %1;" \ + : "=&d"(x) \ + : "d" (0x3F) \ + ) +#else +# define __all_masked_irq_flags 0x1f +# define __save_and_cli_hw(x) \ + __asm__ __volatile__( \ + "cli %0;" \ + : "=&d"(x) \ + ) +#endif + +#define irqs_enabled_from_flags_hw(x) ((x) != __all_masked_irq_flags) +#define raw_irqs_disabled_flags(flags) (!irqs_enabled_from_flags_hw(flags)) +#define local_test_iflag_hw(x) irqs_enabled_from_flags_hw(x) + +#define local_save_flags(x) \ + do { \ + (x) = __ipipe_test_root() ? \ + __all_masked_irq_flags : bfin_irq_flags; \ + } while (0) + +#define local_irq_save(x) \ + do { \ + (x) = __ipipe_test_and_stall_root(); \ + } while (0) + +#define local_irq_restore(x) __ipipe_restore_root(x) +#define local_irq_disable() __ipipe_stall_root() +#define local_irq_enable() __ipipe_unstall_root() +#define irqs_disabled() __ipipe_test_root() + +#define local_save_flags_hw(x) \ + __asm__ __volatile__( \ + "cli %0;" \ + "sti %0;" \ + : "=d"(x) \ + ) + +#define irqs_disabled_hw() \ + ({ \ + unsigned long flags; \ + local_save_flags_hw(flags); \ + !irqs_enabled_from_flags_hw(flags); \ + }) + +static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real) { - return irq; + /* Merge virtual and real interrupt mask bits into a single + 32bit word. */ + return (real & ~(1 << 31)) | ((virt != 0) << 31); } +static inline int raw_demangle_irq_bits(unsigned long *x) +{ + int virt = (*x & (1 << 31)) != 0; + *x &= ~(1L << 31); + return virt; +} + +#ifdef CONFIG_IPIPE_TRACE_IRQSOFF + +#define local_irq_disable_hw() \ + do { \ + int _tmp_dummy; \ + if (!irqs_disabled_hw()) \ + ipipe_trace_begin(0x80000000); \ + __asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : ); \ + } while (0) + +#define local_irq_enable_hw() \ + do { \ + if (irqs_disabled_hw()) \ + ipipe_trace_end(0x80000000); \ + __asm__ __volatile__ ("sti %0;" : : "d"(bfin_irq_flags)); \ + } while (0) + +#define local_irq_save_hw(x) \ + do { \ + __save_and_cli_hw(x); \ + if (local_test_iflag_hw(x)) \ + ipipe_trace_begin(0x80000001); \ + } while (0) + +#define local_irq_restore_hw(x) \ + do { \ + if (local_test_iflag_hw(x)) { \ + ipipe_trace_end(0x80000001); \ + local_irq_enable_hw_notrace(); \ + } \ + } while (0) + +#define local_irq_disable_hw_notrace() \ + do { \ + int _tmp_dummy; \ + __asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : ); \ + } while (0) + +#define local_irq_enable_hw_notrace() \ + __asm__ __volatile__( \ + "sti %0;" \ + : \ + : "d"(bfin_irq_flags) \ + ) + +#define local_irq_save_hw_notrace(x) __save_and_cli_hw(x) + +#define local_irq_restore_hw_notrace(x) \ + do { \ + if (local_test_iflag_hw(x)) \ + local_irq_enable_hw_notrace(); \ + } while (0) + +#else /* CONFIG_IPIPE_TRACE_IRQSOFF */ + +#define local_irq_enable_hw() \ + __asm__ __volatile__( \ + "sti %0;" \ + : \ + : "d"(bfin_irq_flags) \ + ) + +#define local_irq_disable_hw() \ + do { \ + int _tmp_dummy; \ + __asm__ __volatile__ ( \ + "cli %0;" \ + : "=d" (_tmp_dummy)); \ + } while (0) + +#define local_irq_restore_hw(x) \ + do { \ + if (irqs_enabled_from_flags_hw(x)) \ + local_irq_enable_hw(); \ + } while (0) + +#define local_irq_save_hw(x) __save_and_cli_hw(x) + +#define local_irq_disable_hw_notrace() local_irq_disable_hw() +#define local_irq_enable_hw_notrace() local_irq_enable_hw() +#define local_irq_save_hw_notrace(x) local_irq_save_hw(x) +#define local_irq_restore_hw_notrace(x) local_irq_restore_hw(x) + +#endif /* CONFIG_IPIPE_TRACE_IRQSOFF */ + +#else /* !CONFIG_IPIPE */ + /* * Interrupt configuring macros. */ @@ -39,21 +204,6 @@ static __inline__ int irq_canonicalize(int irq) ); \ } while (0) -#if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE) -# define NOP_PAD_ANOMALY_05000244 "nop; nop;" -#else -# define NOP_PAD_ANOMALY_05000244 -#endif - -#ifdef CONFIG_SMP -/* Forward decl needed due to cdef inter dependencies */ -static inline uint32_t __pure bfin_dspid(void); -# define blackfin_core_id() (bfin_dspid() & 0xff) -# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask -#else -extern unsigned long bfin_irq_flags; -#endif - #define local_irq_enable() \ __asm__ __volatile__( \ "sti %0;" \ @@ -61,16 +211,6 @@ extern unsigned long bfin_irq_flags; : "d" (bfin_irq_flags) \ ) -#define idle_with_irq_disabled() \ - __asm__ __volatile__( \ - NOP_PAD_ANOMALY_05000244 \ - ".align 8;" \ - "sti %0;" \ - "idle;" \ - : \ - : "d" (bfin_irq_flags) \ - ) - #ifdef CONFIG_DEBUG_HWERR # define __save_and_cli(x) \ __asm__ __volatile__( \ @@ -116,4 +256,33 @@ extern unsigned long bfin_irq_flags; !irqs_enabled_from_flags(flags); \ }) +#define local_irq_save_hw(x) local_irq_save(x) +#define local_irq_restore_hw(x) local_irq_restore(x) +#define local_irq_enable_hw() local_irq_enable() +#define local_irq_disable_hw() local_irq_disable() +#define irqs_disabled_hw() irqs_disabled() + +#endif /* !CONFIG_IPIPE */ + +#if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE) +# define NOP_PAD_ANOMALY_05000244 "nop; nop;" +#else +# define NOP_PAD_ANOMALY_05000244 +#endif + +#define idle_with_irq_disabled() \ + __asm__ __volatile__( \ + NOP_PAD_ANOMALY_05000244 \ + ".align 8;" \ + "sti %0;" \ + "idle;" \ + : \ + : "d" (bfin_irq_flags) \ + ) + +static inline int irq_canonicalize(int irq) +{ + return irq; +} + #endif /* _BFIN_IRQ_H_ */ diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h index 812e6e6e2cee..a4c8254bec55 100644 --- a/arch/blackfin/include/asm/system.h +++ b/arch/blackfin/include/asm/system.h @@ -141,7 +141,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, unsigned long tmp = 0; unsigned long flags = 0; - local_irq_save(flags); + local_irq_save_hw(flags); switch (size) { case 1: @@ -163,7 +163,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory"); break; } - local_irq_restore(flags); + local_irq_restore_hw(flags); return tmp; } |