Kaynağa Gözat

[ARM] 3086/1: ixp2xxx error irq handling

Patch from Dave Jiang

This provides support for IXP2xxx error interrupt handling. Previously there was a patch to remove this (although the original stuff was broken). Well, now the error bits are needed again. These are used extensively by the micro-engine drivers according to Deepak and also we will need it for the new EDAC code that Alan Cox is trying to push into the main kernel.

Re-submit of 3072/1, generated against git tree pulled today. AFAICT, this git tree pulled in all the ARM changes that's in arm.diff. Please let me know if there are additional changes. Thx!

Signed-off-by: Dave Jiang <djiang@mvista.com>
Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Dave Jiang 19 yıl önce
ebeveyn
işleme
7866f64928

+ 46 - 0
arch/arm/mach-ixp2000/core.c

@@ -402,6 +402,40 @@ static void ixp2000_pci_irq_unmask(unsigned int irq)
 		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27)));
 }
 
+/*
+ * Error interrupts. These are used extensively by the microengine drivers
+ */
+static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc,  struct pt_regs *regs)
+{
+	int i;
+	unsigned long status = *IXP2000_IRQ_ERR_STATUS;
+
+	for(i = 31; i >= 0; i--) {
+		if(status & (1 << i)) {
+			desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i;
+			desc->handle(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs);
+		}
+	}
+}
+
+static void ixp2000_err_irq_mask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_CLR,
+			(1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
+}
+
+static void ixp2000_err_irq_unmask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_SET,
+			(1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
+}
+
+static struct irqchip ixp2000_err_irq_chip = {
+	.ack	= ixp2000_err_irq_mask,
+	.mask	= ixp2000_err_irq_mask,
+	.unmask	= ixp2000_err_irq_unmask
+};
+
 static struct irqchip ixp2000_pci_irq_chip = {
 	.ack	= ixp2000_pci_irq_mask,
 	.mask	= ixp2000_pci_irq_mask,
@@ -459,6 +493,18 @@ void __init ixp2000_init_irq(void)
 		} else set_irq_flags(irq, 0);
 	}
 
+	for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) {
+		if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) &
+				IXP2000_VALID_ERR_IRQ_MASK) {
+			set_irq_chip(irq, &ixp2000_err_irq_chip);
+			set_irq_handler(irq, do_level_IRQ);
+			set_irq_flags(irq, IRQF_VALID);
+		}
+		else
+			set_irq_flags(irq, 0);
+	}
+	set_irq_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler);
+
 	/*
 	 * GPIO IRQs are invalid until someone sets the interrupt mode
 	 * by calling set_irq_type().

+ 34 - 1
include/asm-arm/arch-ixp2000/irqs.h

@@ -67,12 +67,45 @@
 #define IRQ_IXP2000_PCIA		40
 #define IRQ_IXP2000_PCIB		41
 
-#define NR_IXP2000_IRQS                 42
+/* Int sources from IRQ_ERROR_STATUS */
+#define IRQ_IXP2000_DRAM0_MIN_ERR	42
+#define IRQ_IXP2000_DRAM0_MAJ_ERR	43
+#define IRQ_IXP2000_DRAM1_MIN_ERR	44
+#define IRQ_IXP2000_DRAM1_MAJ_ERR	45
+#define IRQ_IXP2000_DRAM2_MIN_ERR	46
+#define IRQ_IXP2000_DRAM2_MAJ_ERR	47
+/* 48-57 reserved */
+#define IRQ_IXP2000_SRAM0_ERR		58
+#define IRQ_IXP2000_SRAM1_ERR		59
+#define IRQ_IXP2000_SRAM2_ERR		60
+#define IRQ_IXP2000_SRAM3_ERR		61
+/* 62-65 reserved */
+#define IRQ_IXP2000_MEDIA_ERR		66
+#define IRQ_IXP2000_PCI_ERR			67
+#define IRQ_IXP2000_SP_INT			68
+
+#define NR_IXP2000_IRQS				69
 
 #define	IXP2000_BOARD_IRQ(x)		(NR_IXP2000_IRQS + (x))
 
 #define	IXP2000_BOARD_IRQ_MASK(irq)	(1 << (irq - NR_IXP2000_IRQS))	
 
+#define IXP2000_ERR_IRQ_MASK(irq) ( 1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR))
+#define IXP2000_VALID_ERR_IRQ_MASK (\
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM0_MIN_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM0_MAJ_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM1_MIN_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM1_MAJ_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM2_MIN_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_DRAM2_MAJ_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM0_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM1_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM2_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SRAM3_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_MEDIA_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_PCI_ERR) | \
+		IXP2000_ERR_IRQ_MASK(IRQ_IXP2000_SP_INT)	)
+
 /*
  * This allows for all the on-chip sources plus up to 32 CPLD based
  * IRQs. Should be more than enough.