Skip to content

Commit

Permalink
metag: IRQ handling
Browse files Browse the repository at this point in the history
Add core IRQ handling for metag. The code in irq.c exposes the TBX
signal numbers as Linux IRQs.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
  • Loading branch information
James Hogan committed Mar 2, 2013
1 parent ac919f0 commit 63047ea
Show file tree
Hide file tree
Showing 3 changed files with 444 additions and 0 deletions.
32 changes: 32 additions & 0 deletions arch/metag/include/asm/irq.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef __ASM_METAG_IRQ_H
#define __ASM_METAG_IRQ_H

#ifdef CONFIG_4KSTACKS
extern void irq_ctx_init(int cpu);
extern void irq_ctx_exit(int cpu);
# define __ARCH_HAS_DO_SOFTIRQ
#else
# define irq_ctx_init(cpu) do { } while (0)
# define irq_ctx_exit(cpu) do { } while (0)
#endif

void tbi_startup_interrupt(int);
void tbi_shutdown_interrupt(int);

struct pt_regs;

int tbisig_map(unsigned int hw);
extern void do_IRQ(int irq, struct pt_regs *regs);

#ifdef CONFIG_METAG_SUSPEND_MEM
int traps_save_context(void);
int traps_restore_context(void);
#endif

#include <asm-generic/irq.h>

#ifdef CONFIG_HOTPLUG_CPU
extern void migrate_irqs(void);
#endif

#endif /* __ASM_METAG_IRQ_H */
94 changes: 94 additions & 0 deletions arch/metag/include/asm/irqflags.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* IRQ flags handling
*
* This file gets included from lowlevel asm headers too, to provide
* wrapped versions of the local_irq_*() APIs, based on the
* raw_local_irq_*() functions from the lowlevel headers.
*/
#ifndef _ASM_IRQFLAGS_H
#define _ASM_IRQFLAGS_H

#ifndef __ASSEMBLY__

#include <asm/core_reg.h>
#include <asm/metag_regs.h>

#define INTS_OFF_MASK TXSTATI_BGNDHALT_BIT

#ifdef CONFIG_SMP
extern unsigned int get_trigger_mask(void);
#else

extern unsigned int global_trigger_mask;

static inline unsigned int get_trigger_mask(void)
{
return global_trigger_mask;
}
#endif

static inline unsigned long arch_local_save_flags(void)
{
return __core_reg_get(TXMASKI);
}

static inline int arch_irqs_disabled_flags(unsigned long flags)
{
return (flags & ~INTS_OFF_MASK) == 0;
}

static inline int arch_irqs_disabled(void)
{
unsigned long flags = arch_local_save_flags();

return arch_irqs_disabled_flags(flags);
}

static inline unsigned long __irqs_disabled(void)
{
/*
* We shouldn't enable exceptions if they are not already
* enabled. This is required for chancalls to work correctly.
*/
return arch_local_save_flags() & INTS_OFF_MASK;
}

/*
* For spinlocks, etc:
*/
static inline unsigned long arch_local_irq_save(void)
{
unsigned long flags = __irqs_disabled();

asm volatile("SWAP %0,TXMASKI\n" : "=r" (flags) : "0" (flags)
: "memory");

return flags;
}

static inline void arch_local_irq_restore(unsigned long flags)
{
asm volatile("MOV TXMASKI,%0\n" : : "r" (flags) : "memory");
}

static inline void arch_local_irq_disable(void)
{
unsigned long flags = __irqs_disabled();

asm volatile("MOV TXMASKI,%0\n" : : "r" (flags) : "memory");
}

static inline void arch_local_irq_enable(void)
{
#ifdef CONFIG_SMP
preempt_disable();
arch_local_irq_restore(get_trigger_mask());
preempt_enable_no_resched();
#else
arch_local_irq_restore(get_trigger_mask());
#endif
}

#endif /* (__ASSEMBLY__) */

#endif /* !(_ASM_IRQFLAGS_H) */
Loading

0 comments on commit 63047ea

Please sign in to comment.