diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 19:21:23 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 19:21:23 -0700 |
commit | dd6d1844af33acb4edd0a40b1770d091a22c94be (patch) | |
tree | e6bd3549919773a13b770324a4dddb51b194b452 /arch/mips/kernel/irq-gt641xx.c | |
parent | 19f71153b9be219756c6b2757921433a69b7975c (diff) | |
parent | aaf76a3245c02faba51c96b9a340c14d6bb0dcc0 (diff) | |
download | op-kernel-dev-dd6d1844af33acb4edd0a40b1770d091a22c94be.zip op-kernel-dev-dd6d1844af33acb4edd0a40b1770d091a22c94be.tar.gz |
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (80 commits)
[MIPS] tlbex.c: Cleanup __init usage.
[MIPS] WRPPMC serial support move to platform device
[MIPS] R1: Fix hazard barriers to make kernels work on R2 also.
[MIPS] VPE: reimplement ELF loader.
[MIPS] cleanup WRPPMC include files
[MIPS] Add BUG_ON assertion for attempt to run kernel on the wrong CPU type.
[MIPS] SMP: Use ISO C struct initializer for local structs.
[MIPS] SMP: Kill useless casts.
[MIPS] Kill num_online_cpus() loops.
[MIPS] SMP: Implement smp_call_function_mask().
[MIPS] Make facility to convert CPU types to strings generally available.
[MIPS] Convert list of CPU types from #define to enum.
[MIPS] Optimize get_unaligned / put_unaligned implementations.
[MIPS] checkfiles: Fix "need space after that ','" errors.
[MIPS] Fix "no space between function name and open parenthesis" warnings.
[MIPS] Allow hardwiring of the CPU type to a single type for optimization.
[MIPS] tlbex: Size optimize code by declaring a few functions inline.
[MIPS] pg-r4k.c: Dump the generated code
[MIPS] Cobalt: Remove cobalt_machine_power_off()
[MIPS] Cobalt: Move reset port definition to arch/mips/cobalt/reset.c
...
Diffstat (limited to 'arch/mips/kernel/irq-gt641xx.c')
-rw-r--r-- | arch/mips/kernel/irq-gt641xx.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/arch/mips/kernel/irq-gt641xx.c b/arch/mips/kernel/irq-gt641xx.c new file mode 100644 index 0000000..1b81b13 --- /dev/null +++ b/arch/mips/kernel/irq-gt641xx.c @@ -0,0 +1,131 @@ +/* + * GT641xx IRQ routines. + * + * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * + * 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; 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/hardirq.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/spinlock.h> +#include <linux/types.h> + +#include <asm/gt64120.h> + +#define GT641XX_IRQ_TO_BIT(irq) (1U << (irq - GT641XX_IRQ_BASE)) + +static DEFINE_SPINLOCK(gt641xx_irq_lock); + +static void ack_gt641xx_irq(unsigned int irq) +{ + unsigned long flags; + u32 cause; + + spin_lock_irqsave(>641xx_irq_lock, flags); + cause = GT_READ(GT_INTRCAUSE_OFS); + cause &= ~GT641XX_IRQ_TO_BIT(irq); + GT_WRITE(GT_INTRCAUSE_OFS, cause); + spin_unlock_irqrestore(>641xx_irq_lock, flags); +} + +static void mask_gt641xx_irq(unsigned int irq) +{ + unsigned long flags; + u32 mask; + + spin_lock_irqsave(>641xx_irq_lock, flags); + mask = GT_READ(GT_INTRMASK_OFS); + mask &= ~GT641XX_IRQ_TO_BIT(irq); + GT_WRITE(GT_INTRMASK_OFS, mask); + spin_unlock_irqrestore(>641xx_irq_lock, flags); +} + +static void mask_ack_gt641xx_irq(unsigned int irq) +{ + unsigned long flags; + u32 cause, mask; + + spin_lock_irqsave(>641xx_irq_lock, flags); + mask = GT_READ(GT_INTRMASK_OFS); + mask &= ~GT641XX_IRQ_TO_BIT(irq); + GT_WRITE(GT_INTRMASK_OFS, mask); + + cause = GT_READ(GT_INTRCAUSE_OFS); + cause &= ~GT641XX_IRQ_TO_BIT(irq); + GT_WRITE(GT_INTRCAUSE_OFS, cause); + spin_unlock_irqrestore(>641xx_irq_lock, flags); +} + +static void unmask_gt641xx_irq(unsigned int irq) +{ + unsigned long flags; + u32 mask; + + spin_lock_irqsave(>641xx_irq_lock, flags); + mask = GT_READ(GT_INTRMASK_OFS); + mask |= GT641XX_IRQ_TO_BIT(irq); + GT_WRITE(GT_INTRMASK_OFS, mask); + spin_unlock_irqrestore(>641xx_irq_lock, flags); +} + +static struct irq_chip gt641xx_irq_chip = { + .name = "GT641xx", + .ack = ack_gt641xx_irq, + .mask = mask_gt641xx_irq, + .mask_ack = mask_ack_gt641xx_irq, + .unmask = unmask_gt641xx_irq, +}; + +void gt641xx_irq_dispatch(void) +{ + u32 cause, mask; + int i; + + cause = GT_READ(GT_INTRCAUSE_OFS); + mask = GT_READ(GT_INTRMASK_OFS); + cause &= mask; + + /* + * bit0 : logical or of all the interrupt bits. + * bit30: logical or of bits[29:26,20:1]. + * bit31: logical or of bits[25:1]. + */ + for (i = 1; i < 30; i++) { + if (cause & (1U << i)) { + do_IRQ(GT641XX_IRQ_BASE + i); + return; + } + } + + atomic_inc(&irq_err_count); +} + +void __init gt641xx_irq_init(void) +{ + int i; + + GT_WRITE(GT_INTRMASK_OFS, 0); + GT_WRITE(GT_INTRCAUSE_OFS, 0); + + /* + * bit0 : logical or of all the interrupt bits. + * bit30: logical or of bits[29:26,20:1]. + * bit31: logical or of bits[25:1]. + */ + for (i = 1; i < 30; i++) + set_irq_chip_and_handler(GT641XX_IRQ_BASE + i, + >641xx_irq_chip, handle_level_irq); +} |