summaryrefslogtreecommitdiffstats
path: root/arch/mips/gt64120
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/gt64120')
-rw-r--r--arch/mips/gt64120/common/Makefile2
-rw-r--r--arch/mips/gt64120/common/gt_irq.c7
-rw-r--r--arch/mips/gt64120/common/irq.c300
-rw-r--r--arch/mips/gt64120/momenco_ocelot/int-handler.S43
-rw-r--r--arch/mips/gt64120/momenco_ocelot/irq.c150
-rw-r--r--arch/mips/gt64120/momenco_ocelot/pci.c6
-rw-r--r--arch/mips/gt64120/momenco_ocelot/setup.c2
7 files changed, 133 insertions, 377 deletions
diff --git a/arch/mips/gt64120/common/Makefile b/arch/mips/gt64120/common/Makefile
index ccf50a55b..e1c4e42a0 100644
--- a/arch/mips/gt64120/common/Makefile
+++ b/arch/mips/gt64120/common/Makefile
@@ -13,6 +13,6 @@
O_TARGET:= gt64120.o
-obj-y := gt_irq.o irq.o pci.o
+obj-y := gt_irq.o pci.o
include $(TOPDIR)/Rules.make
diff --git a/arch/mips/gt64120/common/gt_irq.c b/arch/mips/gt64120/common/gt_irq.c
index afd91e4ba..caefccbfd 100644
--- a/arch/mips/gt64120/common/gt_irq.c
+++ b/arch/mips/gt64120/common/gt_irq.c
@@ -1,4 +1,4 @@
-/***********************************************************************
+/*
*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
@@ -10,10 +10,7 @@
* 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>
@@ -198,7 +195,7 @@ static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs)
* that is passed in as *irq (=irq0 in ../kernel/time.c).
* We will do our own timer interrupt handling.
*/
-void gt64120_time_init(struct irqaction *irq)
+void gt64120_time_init(void)
{
extern irq_desc_t irq_desc[NR_IRQS];
static struct irqaction timer;
diff --git a/arch/mips/gt64120/common/irq.c b/arch/mips/gt64120/common/irq.c
deleted file mode 100644
index 8fc47ede0..000000000
--- a/arch/mips/gt64120/common/irq.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * arch/mips/gt64120/common/irq.c
- * Top-level irq code. This is really common among all MIPS boards.
- * Should be "upgraded" to arch/mips/kernel/irq.c
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/irq.h>
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-#include <asm/pmc/ev64120int.h>
-
-
-#undef IRQ_DEBUG
-
-#ifdef IRQ_DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-void (*irq_setup)(void);
-
-/*
- * Generic no controller code
- */
-
-static void no_irq_enable_disable(unsigned int irq)
-{
-}
-
-static unsigned int no_irq_startup(unsigned int irq)
-{
- return 0;
-}
-
-static void no_irq_ack(unsigned int irq)
-{
- printk(KERN_CRIT "Unexpected IRQ trap at vector %u\n", irq);
-}
-
-struct hw_interrupt_type no_irq_type = {
- typename: "none",
- startup: no_irq_startup,
- shutdown: no_irq_enable_disable,
- enable: no_irq_enable_disable,
- disable: no_irq_enable_disable,
- // ack: no_irq_ack,
- // [jsun] cannot use it yet. gt64120 does not have its own handler
- ack: NULL,
- end: no_irq_enable_disable,
-};
-
-
-
-/*
- * Controller mappings for all interrupt sources:
- */
-irq_desc_t irq_desc[NR_IRQS];
-
-unsigned long spurious_count = 0;
-
-int get_irq_list(char *buf)
-{
- int i, len = 0, j;
- struct irqaction *action;
-
- len += sprintf(buf + len, " ");
- for (j = 0; j < smp_num_cpus; j++)
- len += sprintf(buf + len, "CPU%d ", j);
- *(char *) (buf + len++) = '\n';
-
- for (i = 0; i < NR_IRQS; i++) {
- action = irq_desc[i].action;
- if (!action || !action->handler)
- continue;
- len += sprintf(buf + len, "%3d: ", i);
- len += sprintf(buf + len, "%10u ", kstat_irqs(i));
- if (irq_desc[i].handler)
- len +=
- sprintf(buf + len, " %s ",
- irq_desc[i].handler->typename);
- else
- len += sprintf(buf + len, " None ");
- len += sprintf(buf + len, " %s", action->name);
- for (action = action->next; action; action = action->next) {
- len += sprintf(buf + len, ", %s", action->name);
- }
- len += sprintf(buf + len, "\n");
- }
- len += sprintf(buf + len, "BAD: %10lu\n", spurious_count);
- return len;
-}
-
-asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
-{
- struct irqaction *action;
- int cpu;
- cpu = smp_processor_id();
- irq_enter(cpu, irq);
- kstat.irqs[cpu][irq]++;
- if (irq_desc[irq].handler->ack) {
- irq_desc[irq].handler->ack(irq);
- }
-
- disable_irq(irq);
-
- action = irq_desc[irq].action;
- if (action && action->handler) {
-#ifdef IRQ_DEBUG
- if (irq != TIMER)
- DBG(KERN_INFO
- "rr: irq %d action %p and handler %p\n", irq,
- action, action->handler);
-#endif
- if (!(action->flags & SA_INTERRUPT))
- __sti();
- do {
- action->handler(irq, action->dev_id, regs);
- action = action->next;
- } while (action);
- __cli();
- if (irq_desc[irq].handler) {
- if (irq_desc[irq].handler->end)
- irq_desc[irq].handler->end(irq);
- else if (irq_desc[irq].handler->enable)
- irq_desc[irq].handler->enable(irq);
- }
- }
-
- enable_irq(irq);
- irq_exit(cpu, irq);
-
- if (softirq_active(cpu) & softirq_mask(cpu))
- do_softirq();
-
- /* unmasking and bottom half handling is done magically for us. */
-}
-
-int request_irq(unsigned int irq,
- void (*handler) (int, void *, struct pt_regs *),
- unsigned long irqflags, const char *devname, void *dev_id)
-{
- struct irqaction *old, **p, *action;
- unsigned long flags;
- if (irq >= NR_IRQS)
- return -EINVAL;
-
- action = (struct irqaction *)
- kmalloc(sizeof(struct irqaction), GFP_KERNEL);
- if (!action)
- return -ENOMEM;
-
- action->handler = handler;
- action->flags = irqflags;
- action->mask = 0;
- action->name = devname;
- action->dev_id = dev_id;
- action->next = NULL;
-
- save_flags(flags);
- cli();
-
- p = &irq_desc[irq].action;
-
- if ((old = *p) != NULL) {
- /* Can't share interrupts unless both agree to */
- if (!(old->flags & action->flags & SA_SHIRQ))
- return -EBUSY;
- /* add new interrupt at end of irq queue */
- do {
- p = &old->next;
- old = *p;
- } while (old);
- }
- *p = action;
-
- restore_flags(flags);
- enable_irq(irq);
-
- return 0;
-}
-
-
-void free_irq(unsigned int irq, void *dev_id)
-{
- struct irqaction *p, *old = NULL;
- unsigned long flags;
- int count, tmp, removed = 0;
-
- for (p = irq_desc[irq].action; p != NULL; old = p, p = p->next) {
- /* Found the IRQ, is it the correct dev_id? */
- if (dev_id == p->dev_id) {
- save_flags(flags);
- cli();
-
- // remove link from list
- if (old)
- old->next = p->next;
- else
- irq_desc[irq].action = p->next;
-
- restore_flags(flags);
- kfree(p);
- removed = 1;
- break;
- }
- }
-}
-
-unsigned long probe_irq_on(void)
-{
- printk(KERN_INFO "probe_irq_on\n");
- return 0;
-}
-
-int probe_irq_off(unsigned long irqs)
-{
- printk(KERN_INFO "probe_irq_off\n");
- return 0;
-}
-
-void __init init_IRQ(void)
-{
- int i;
-
- DBG(KERN_INFO "rr:init_IRQ\n");
-
- /* Let's initialize our IRQ descriptors */
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].status = 0;
- irq_desc[i].handler = &no_irq_type;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 0;
- irq_desc[i].lock = SPIN_LOCK_UNLOCKED;
- }
-
- irq_setup();
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
diff --git a/arch/mips/gt64120/momenco_ocelot/int-handler.S b/arch/mips/gt64120/momenco_ocelot/int-handler.S
index df0525833..4d8f82d54 100644
--- a/arch/mips/gt64120/momenco_ocelot/int-handler.S
+++ b/arch/mips/gt64120/momenco_ocelot/int-handler.S
@@ -43,6 +43,26 @@
bnez t1, ll_galileo_irq
andi t1, t0, STATUSF_IP7 /* cpu timer */
bnez t1, ll_cputimer_irq
+
+ /* now look at the extended interrupts */
+ mfc0 t0, CP0_CAUSE
+ cfc0 t1, CP0_S1_INTCONTROL
+
+ /* shift the mask 8 bits left to line up the bits */
+ sll t2, t1, 8
+
+ and t0, t2
+ srl t0, t0, 16
+
+ andi t1, t0, STATUSF_IP8 /* int6 hardware line */
+ bnez t1, ll_pmc1_irq
+ andi t1, t0, STATUSF_IP9 /* int7 hardware line */
+ bnez t1, ll_pmc2_irq
+ andi t1, t0, STATUSF_IP10 /* int8 hardware line */
+ bnez t1, ll_cpci_abcd_irq
+ andi t1, t0, STATUSF_IP11 /* int9 hardware line */
+ bnez t1, ll_uart2_irq
+
.set reorder
/* wrong alarm or masked ... */
@@ -87,3 +107,26 @@ ll_cputimer_irq:
jal do_IRQ
j ret_from_irq
+ll_pmc1_irq:
+ li a0, 8
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_pmc2_irq:
+ li a0, 9
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpci_abcd_irq:
+ li a0, 10
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_uart2_irq:
+ li a0, 11
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
diff --git a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c
index c6c01b0d3..e28be4037 100644
--- a/arch/mips/gt64120/momenco_ocelot/irq.c
+++ b/arch/mips/gt64120/momenco_ocelot/irq.c
@@ -5,6 +5,7 @@
*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.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
@@ -48,116 +49,125 @@
#include <asm/system.h>
-#undef IRQ_DEBUG
-
-#ifdef IRQ_DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
+static spinlock_t rm7000_irq_lock = SPIN_LOCK_UNLOCKED;
/* Function for careful CP0 interrupt mask access */
-static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
+static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in)
{
- unsigned long status = read_32bit_cp0_register(CP0_STATUS);
- DBG(KERN_INFO "modify_cp0_intmask clr %x, set %x\n", clr_mask,
- set_mask);
- DBG(KERN_INFO "modify_cp0_intmask status %x\n", status);
+ unsigned long status;
+ unsigned clr_mask;
+ unsigned set_mask;
+
+ /* do the low 8 bits first */
+ clr_mask = 0xff & clr_mask_in;
+ set_mask = 0xff & set_mask_in;
+ status = read_32bit_cp0_register(CP0_STATUS);
status &= ~((clr_mask & 0xFF) << 8);
status |= (set_mask & 0xFF) << 8;
- DBG(KERN_INFO "modify_cp0_intmask status %x\n", status);
write_32bit_cp0_register(CP0_STATUS, status);
+
+ /* do the high 8 bits */
+ clr_mask = 0xff & (clr_mask_in >> 8);
+ set_mask = 0xff & (set_mask_in >> 8);
+ status = read_32bit_cp0_set1_register(CP0_S1_INTCONTROL);
+ status &= ~((clr_mask & 0xFF) << 8);
+ status |= (set_mask & 0xFF) << 8;
+ write_32bit_cp0_set1_register(CP0_S1_INTCONTROL, status);
}
-static inline void mask_irq(unsigned int irq_nr)
+static inline void mask_irq(unsigned int irq)
{
- modify_cp0_intmask(irq_nr, 0);
+ modify_cp0_intmask(irq, 0);
}
-static inline void unmask_irq(unsigned int irq_nr)
+static inline void unmask_irq(unsigned int irq)
{
- modify_cp0_intmask(0, irq_nr);
+ modify_cp0_intmask(0, irq);
}
-void disable_irq(unsigned int irq_nr)
+static void enable_cp7000_irq(unsigned int irq)
{
unsigned long flags;
- DBG(KERN_INFO "disable_irq, irq %d\n", irq_nr);
- save_and_cli(flags);
- /* we don't support higher interrupts, nor cascaded interrupts */
- if (irq_nr >= 8)
- panic("irq_nr is greater than 8");
-
- mask_irq(1 << irq_nr);
- restore_flags(flags);
+ spin_lock_irqsave(&rm7000_irq_lock, flags);
+ unmask_irq(1 << irq);
+ spin_unlock_irqrestore(&rm7000_irq_lock, flags);
+}
+
+static unsigned int startup_cp7000_irq(unsigned int irq)
+{
+ enable_cp7000_irq(irq);
+
+ return 0; /* never anything pending */
}
-void enable_irq(unsigned int irq_nr)
+static void disable_cp7000_irq(unsigned int irq)
{
unsigned long flags;
- save_and_cli(flags);
-
- if ( irq_nr >= 8 )
- panic("irq_nr is greater than 8");
-
- unmask_irq( 1 << irq_nr );
- restore_flags(flags);
+ spin_lock_irqsave(&rm7000_irq_lock, flags);
+ mask_irq(1 << irq);
+ spin_unlock_irqrestore(&rm7000_irq_lock, flags);
}
-/*
- * Ocelot irq setup -
- *
- * Initializes CPU interrupts
- *
- *
- * Inputs :
- *
- * Outpus :
- *
- */
-void momenco_ocelot_irq_setup(void)
+#define shutdown_cp7000_irq disable_cp7000_irq
+
+static void mask_and_ack_cp7000_irq(unsigned int irq)
+{
+ mask_irq(1 << irq);
+}
+
+static void end_cp7000_irq(unsigned int irq)
{
- extern asmlinkage void ocelot_handle_int(void);
- extern void gt64120_irq_init(void);
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ unmask_irq(1 << irq);
+}
- DBG(KERN_INFO "rr: momenco_ocelot_irq_setup entry\n");
+static struct hw_interrupt_type cp7000_hpcdma_irq_type = {
+ "CP7000",
+ startup_cp7000_irq,
+ shutdown_cp7000_irq,
+ enable_cp7000_irq,
+ disable_cp7000_irq,
+ mask_and_ack_cp7000_irq,
+ end_cp7000_irq,
+ NULL
+};
- gt64120_irq_init();
+
+extern asmlinkage void ocelot_handle_int(void);
+extern void gt64120_irq_init(void);
+
+void __init init_IRQ(void)
+{
+ int i;
/*
* Clear all of the interrupts while we change the able around a bit.
* int-handler is not on bootstrap
*/
clear_cp0_status(ST0_IM | ST0_BEV);
+ __cli();
/* Sets the first-level interrupt dispatcher. */
set_except_vector(0, ocelot_handle_int);
+ init_generic_irq();
- cli();
-
- /*
- * Enable timer. Other interrupts will be enabled as they are
- * registered.
- */
- // change_cp0_status(ST0_IM, IE_IRQ4);
+ for (i = 0; i <= 15; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &cp7000_hpcdma_irq_type;
+ }
+ gt64120_irq_init();
#ifdef CONFIG_REMOTE_DEBUG
- {
- /*
- extern int DEBUG_CHANNEL;
- serial_init(DEBUG_CHANNEL);
- serial_set(DEBUG_CHANNEL, 115200);
- */
- printk("start kgdb ...\n");
- set_debug_traps();
- breakpoint(); /* you may move this line to whereever you want :-) */
-#ifdef CONFIG_GDB_CONSOLE
- register_gdb_console();
+ printk("start kgdb ...\n");
+ set_debug_traps();
+ breakpoint(); /* you may move this line to whereever you want :-) */
#endif
- }
+#ifdef CONFIG_GDB_CONSOLE
+ register_gdb_console();
#endif
}
diff --git a/arch/mips/gt64120/momenco_ocelot/pci.c b/arch/mips/gt64120/momenco_ocelot/pci.c
index 04727f885..4b8e41b2b 100644
--- a/arch/mips/gt64120/momenco_ocelot/pci.c
+++ b/arch/mips/gt64120/momenco_ocelot/pci.c
@@ -53,6 +53,12 @@ void __init gt64120_board_pcibios_fixup_bus(struct pci_bus *bus)
"found unexpected PCI device in slot 2.");
}
devices->irq = 3; /* irq_nr is 3 for INT1 */
+ } else if (PCI_SLOT(devices->devfn) == 4) {
+ /* PMC Slot 1 */
+ devices->irq = 8; /* irq_nr is 8 for INT6 */
+ } else if (PCI_SLOT(devices->devfn) == 5) {
+ /* PMC Slot 1 */
+ devices->irq = 9; /* irq_nr is 9 for INT7 */
} else {
/* We don't have assign interrupts for other devices. */
devices->irq = 0xff;
diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c
index f08f32074..4bfc71b8f 100644
--- a/arch/mips/gt64120/momenco_ocelot/setup.c
+++ b/arch/mips/gt64120/momenco_ocelot/setup.c
@@ -88,7 +88,7 @@ void __init momenco_ocelot_setup(void)
{
void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache);
unsigned int tmpword;
- irq_setup = momenco_ocelot_irq_setup;
+
board_time_init = gt64120_time_init;
_machine_restart = momenco_ocelot_restart;