patch-2.4.21 linux-2.4.21/arch/ppc/8xx_io/commproc.c
Next file: linux-2.4.21/arch/ppc/8xx_io/enet.c
Previous file: linux-2.4.21/arch/ppc/8xx_io/Makefile
Back to the patch index
Back to the overall index
- Lines: 252
- Date:
2003-06-13 07:51:31.000000000 -0700
- Orig file:
linux-2.4.20/arch/ppc/8xx_io/commproc.c
- Orig date:
2001-11-02 17:43:54.000000000 -0800
diff -urN linux-2.4.20/arch/ppc/8xx_io/commproc.c linux-2.4.21/arch/ppc/8xx_io/commproc.c
@@ -1,8 +1,4 @@
/*
- * BK Id: SCCS/s.commproc.c 1.15 10/16/01 16:21:52 trini
- */
-
-/*
* General Purpose functions for the global management of the
* Communication Processor Module.
* Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
@@ -31,7 +27,7 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
#include <asm/mpc8xx.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -47,14 +43,65 @@
cpm8xx_t *cpmp; /* Pointer to comm processor space */
/* CPM interrupt vector functions.
-*/
+ *
+ * The cpm_vecs structure is only needed to support the cpm_install_handler()
+ * mechanism of installing CPM interrupt handlers.
+ */
struct cpm_action {
void (*handler)(void *, struct pt_regs * regs);
void *dev_id;
};
static struct cpm_action cpm_vecs[CPMVEC_NR];
static void cpm_interrupt(int irq, void * dev, struct pt_regs * regs);
-static void cpm_error_interrupt(void *, struct pt_regs * regs);
+static void cpm_error_interrupt(int irq, void *, struct pt_regs * regs);
+
+/* Define a table of names to identify CPM interrupt handlers in
+ * /proc/interrupts.
+ */
+const char *cpm_int_name[] =
+ { "error", "PC4", "PC5", "SMC2",
+ "SMC1", "SPI", "PC6", "Timer 4",
+ "", "PC7", "PC8", "PC9",
+ "Timer 3", "", "PC10", "PC11",
+ "I2C", "RISC Timer", "Timer 2", "",
+ "IDMA2", "IDMA1", "SDMA error", "PC12",
+ "PC13", "Timer 1", "PC14", "SCC4",
+ "SCC3", "SCC2", "SCC1", "PC15"
+ };
+
+static void
+cpm_mask_irq(unsigned int irq)
+{
+ int cpm_vec = irq - CPM_IRQ_OFFSET;
+
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << cpm_vec);
+}
+
+static void
+cpm_unmask_irq(unsigned int irq)
+{
+ int cpm_vec = irq - CPM_IRQ_OFFSET;
+
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << cpm_vec);
+}
+
+static void
+cpm_eoi(unsigned int irq)
+{
+ int cpm_vec = irq - CPM_IRQ_OFFSET;
+
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr = (1 << cpm_vec);
+}
+
+struct hw_interrupt_type cpm_pic = {
+ " CPM ",
+ NULL,
+ NULL,
+ cpm_unmask_irq,
+ cpm_mask_irq,
+ NULL,
+ cpm_eoi
+};
void
m8xx_cpm_reset(uint host_page_addr)
@@ -118,6 +165,8 @@
void
cpm_interrupt_init(void)
{
+ int i;
+
/* Initialize the CPM interrupt controller.
*/
((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr =
@@ -125,41 +174,54 @@
((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
+ /* install the CPM interrupt controller routines for the CPM
+ * interrupt vectors
+ */
+ for ( i = CPM_IRQ_OFFSET ; i < CPM_IRQ_OFFSET + NR_CPM_INTS ; i++ )
+ irq_desc[i].handler = &cpm_pic;
+
/* Set our interrupt handler with the core CPU.
*/
- if (request_8xxirq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0)
+ if (request_irq(CPM_INTERRUPT, cpm_interrupt, 0, "CPM cascade",
+ NULL) != 0)
panic("Could not allocate CPM IRQ!");
/* Install our own error handler.
*/
- cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL);
+ if (request_irq(CPM_IRQ_OFFSET + CPMVEC_ERROR, cpm_error_interrupt,
+ 0, cpm_int_name[CPMVEC_ERROR], NULL) != 0)
+ panic("Could not allocate CPM error IRQ!");
+
((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
}
-/* CPM interrupt controller interrupt.
-*/
-static void
-cpm_interrupt(int irq, void * dev, struct pt_regs * regs)
+/*
+ * Get the CPM interrupt vector.
+ */
+int
+cpm_get_irq(struct pt_regs *regs)
{
- uint vec;
+ int cpm_vec;
/* Get the vector by setting the ACK bit and then reading
* the register.
*/
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;
- vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr;
- vec >>= 11;
+ cpm_vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr;
+ cpm_vec >>= 11;
- if (cpm_vecs[vec].handler != 0)
- (*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id, regs);
- else
- ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);
+ return cpm_vec;
+}
- /* After servicing the interrupt, we have to remove the status
- * indicator.
+/* CPM interrupt controller cascade interrupt.
+*/
+static void
+cpm_interrupt(int irq, void * dev, struct pt_regs * regs)
+{
+ /* This interrupt handler never actually gets called. It is
+ * installed only to unmask the CPM cascade interrupt in the SIU
+ * and to make the CPM cascade interrupt visible in /proc/interrupts.
*/
- ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr = (1 << vec);
-
}
/* The CPM can generate the error interrupt when there is a race condition
@@ -168,40 +230,69 @@
* tests in the interrupt handler.
*/
static void
-cpm_error_interrupt(void *dev, struct pt_regs *regs)
+cpm_error_interrupt(int irq, void *dev, struct pt_regs *regs)
{
}
+/* A helper function to translate the handler prototype required by
+ * request_irq() to the handler prototype required by cpm_install_handler().
+ */
+static void
+cpm_handler_helper(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int cpm_vec = irq - CPM_IRQ_OFFSET;
+
+ (*cpm_vecs[cpm_vec].handler)(dev_id, regs);
+}
+
/* Install a CPM interrupt handler.
-*/
+ * This routine accepts a CPM interrupt vector in the range 0 to 31.
+ * This routine is retained for backward compatibility. Rather than using
+ * this routine to install a CPM interrupt handler, you can now use
+ * request_irq() with an IRQ in the range CPM_IRQ_OFFSET to
+ * CPM_IRQ_OFFSET + NR_CPM_INTS - 1 (16 to 47).
+ *
+ * Notice that the prototype of the interrupt handler function must be
+ * different depending on whether you install the handler with
+ * request_irq() or cpm_install_handler().
+ */
void
-cpm_install_handler(int vec, void (*handler)(void *, struct pt_regs *regs),
+cpm_install_handler(int cpm_vec, void (*handler)(void *, struct pt_regs *regs),
void *dev_id)
{
+ int err;
/* If null handler, assume we are trying to free the IRQ.
*/
if (!handler) {
- cpm_free_handler(vec);
+ free_irq(CPM_IRQ_OFFSET + cpm_vec, dev_id);
return;
}
- if (cpm_vecs[vec].handler != 0)
- printk("CPM interrupt %x replacing %x\n",
- (uint)handler, (uint)cpm_vecs[vec].handler);
- cpm_vecs[vec].handler = handler;
- cpm_vecs[vec].dev_id = dev_id;
- ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec);
+ if (cpm_vecs[cpm_vec].handler != 0)
+ printk(KERN_INFO "CPM interrupt %x replacing %x\n",
+ (uint)handler, (uint)cpm_vecs[cpm_vec].handler);
+ cpm_vecs[cpm_vec].handler = handler;
+ cpm_vecs[cpm_vec].dev_id = dev_id;
+
+ if ((err = request_irq(CPM_IRQ_OFFSET + cpm_vec, cpm_handler_helper,
+ 0, cpm_int_name[cpm_vec], dev_id)))
+ printk(KERN_ERR "request_irq() returned %d for CPM vector %d\n",
+ err, cpm_vec);
}
/* Free a CPM interrupt handler.
-*/
+ * This routine accepts a CPM interrupt vector in the range 0 to 31.
+ * This routine is retained for backward compatibility.
+ */
void
-cpm_free_handler(int vec)
+cpm_free_handler(int cpm_vec)
{
- cpm_vecs[vec].handler = NULL;
- cpm_vecs[vec].dev_id = NULL;
- ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);
+ request_irq(CPM_IRQ_OFFSET + cpm_vec, NULL, 0, 0,
+ cpm_vecs[cpm_vec].dev_id);
+
+ cpm_vecs[cpm_vec].handler = NULL;
+ cpm_vecs[cpm_vec].dev_id = NULL;
}
/* Allocate some memory from the dual ported ram. We may want to
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)