123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- /*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- * Copyright (C) 2004 Ralf Baechle <ralf@linux-mips.org>
- *
- * 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.
- */
- #include <linux/module.h>
- #include <linux/interrupt.h>
- #include <linux/kernel.h>
- #include <asm/ptrace.h>
- #include <linux/sched.h>
- #include <linux/kernel_stat.h>
- #include <asm/io.h>
- #include <asm/irq.h>
- #include <linux/mv643xx.h>
- static unsigned int irq_base;
- static inline int ls1bit32(unsigned int x)
- {
- int b = 31, s;
- s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
- s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s;
- s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s;
- s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s;
- s = 1; if (x << 1 == 0) s = 0; b -= s;
- return b;
- }
- /* mask off an interrupt -- 1 is enable, 0 is disable */
- static inline void mask_mv64340_irq(unsigned int irq)
- {
- uint32_t value;
- if (irq < (irq_base + 32)) {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
- value &= ~(1 << (irq - irq_base));
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
- } else {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
- value &= ~(1 << (irq - irq_base - 32));
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
- }
- }
- /* unmask an interrupt -- 1 is enable, 0 is disable */
- static inline void unmask_mv64340_irq(unsigned int irq)
- {
- uint32_t value;
- if (irq < (irq_base + 32)) {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
- value |= 1 << (irq - irq_base);
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
- } else {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
- value |= 1 << (irq - irq_base - 32);
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
- }
- }
- /*
- * Enables the IRQ on Marvell Chip
- */
- static void enable_mv64340_irq(unsigned int irq)
- {
- unmask_mv64340_irq(irq);
- }
- /*
- * Initialize the IRQ on Marvell Chip
- */
- static unsigned int startup_mv64340_irq(unsigned int irq)
- {
- unmask_mv64340_irq(irq);
- return 0;
- }
- /*
- * Disables the IRQ on Marvell Chip
- */
- static void disable_mv64340_irq(unsigned int irq)
- {
- mask_mv64340_irq(irq);
- }
- /*
- * Masks and ACKs an IRQ
- */
- static void mask_and_ack_mv64340_irq(unsigned int irq)
- {
- mask_mv64340_irq(irq);
- }
- /*
- * End IRQ processing
- */
- static void end_mv64340_irq(unsigned int irq)
- {
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- unmask_mv64340_irq(irq);
- }
- /*
- * Interrupt handler for interrupts coming from the Marvell chip.
- * It could be built in ethernet ports etc...
- */
- void ll_mv64340_irq(struct pt_regs *regs)
- {
- unsigned int irq_src_low, irq_src_high;
- unsigned int irq_mask_low, irq_mask_high;
- /* read the interrupt status registers */
- irq_mask_low = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
- irq_mask_high = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
- irq_src_low = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_LOW);
- irq_src_high = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_HIGH);
- /* mask for just the interrupts we want */
- irq_src_low &= irq_mask_low;
- irq_src_high &= irq_mask_high;
- if (irq_src_low)
- do_IRQ(ls1bit32(irq_src_low) + irq_base, regs);
- else
- do_IRQ(ls1bit32(irq_src_high) + irq_base + 32, regs);
- }
- #define shutdown_mv64340_irq disable_mv64340_irq
- struct hw_interrupt_type mv64340_irq_type = {
- "MV-64340",
- startup_mv64340_irq,
- shutdown_mv64340_irq,
- enable_mv64340_irq,
- disable_mv64340_irq,
- mask_and_ack_mv64340_irq,
- end_mv64340_irq,
- NULL
- };
- void __init mv64340_irq_init(unsigned int base)
- {
- int i;
- /* Reset irq handlers pointers to NULL */
- for (i = base; i < base + 64; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 2;
- irq_desc[i].handler = &mv64340_irq_type;
- }
- irq_base = base;
- }
|