TI IRQ routing - safer approach

Pavel Roskin proski at gnu.org
Wed Sep 3 20:00:38 BST 2003


Hello!

This patch against Linux 2.4.0-test4-bk5 reenabled the kludge for certain
PCI cards that are not initialized to route interrupts to the PCI bus.
This patch is very conservative to avoid the past problems.

First of all, irqmux is a 32-bit register.  The old code was buggy because
it could lose upper bytes from the register.  That alone may be sufficient
to fix the problem with laptops.

The main concern is not to reconfigure any cards except those that are
found to be unconfigured by BIOS or on-board EEPROM.  Following measures
have been taken:

1) irqmux tweaking is only done in ti1250_override, so it applies to
TI1250 and TI1410.  Similar workarounds for other cards may need to be
written and tested separately.

2) All 32 bits of irqmux must be 0, which is the default value.  This
indicates that irqmux wasn't initialized.  The scenario described in the
old comment when MFUNC0 is reprogrammed from INT3 to INT2 becomes
impossible because in the default configuration no ISA interrupts are
routed to MFUNC pins.

3) Interrupt configuration bits in devctl must be set to 6 - serial ISA
and serial PCI.  Again, that's the default, and it's likely that devctl
wasn't initialized properly.  To be on the safe side, devctl is
reprogrammed to 4 - serial ISA and parallel PCI.  If by any chance serial
ISA interrupts are used, they would still be available.  Actually, I find
it unlikely because serial interrupts require INTA to be decoded, and
irqmux is not routing it.

4) Only MFUNC0 is programmed, but not MFUNC1.  The documentation for
TI1410 doesn't mention INTB in the irqmux description.  My card has only
one slot.  If somebody has a two-slot PCI card, they are welcome to test
and fix the driver.

The patch is attached.  Please test and apply.

-- 
Regards,
Pavel Roskin-------------- next part --------------
--- linux.orig/drivers/pcmcia/ti113x.h
+++ linux/drivers/pcmcia/ti113x.h
@@ -281,33 +281,6 @@
 
 	ti_set_zv(socket);
 
-#if 0
-	/*
-	 * If ISA interrupts don't work, then fall back to routing card
-	 * interrupts to the PCI interrupt of the socket.
-	 *
-	 * Tweaking this when we are using serial PCI IRQs causes hangs
-	 *   --rmk
-	 */
-	if (!socket->socket.irq_mask) {
-		u8 irqmux, devctl;
-
-		devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
-		if ((devctl & TI113X_DCR_IMODE_MASK) != TI12XX_DCR_IMODE_ALL_SERIAL) {
-			printk (KERN_INFO "ti113x: Routing card interrupts to PCI\n");
-
-			devctl &= ~TI113X_DCR_IMODE_MASK;
-
-			irqmux = config_readl(socket, TI122X_IRQMUX);
-			irqmux = (irqmux & ~0x0f) | 0x02; /* route INTA */
-			irqmux = (irqmux & ~0xf0) | 0x20; /* route INTB */
-
-			config_writel(socket, TI122X_IRQMUX, irqmux);
-			config_writeb(socket, TI113X_DEVICE_CONTROL, devctl);
-		}
-	}
-#endif
-
 	return 0;
 }
 
@@ -366,25 +339,36 @@
 		config_writeb(socket, TI1250_DIAGNOSTIC, diag);
 	}
 
-#if 0
 	/*
-	 * This is highly machine specific, and we should NOT touch
-	 * this register - we have no knowledge how the hardware
-	 * is actually wired.
-	 *
-	 * If we're going to do this, we should probably look into
-	 * using the subsystem IDs.
-	 *
-	 * On ThinkPad 380XD, this changes MFUNC0 from the ISA IRQ3
-	 * output (which it is) to IRQ2.  We also change MFUNC1
-	 * from ISA IRQ4 to IRQ6.
+	 * If ISA interrupts don't work, fall back to routing card
+	 * interrupts to the PCI interrupt of the socket.  Only do it if
+	 * both devctl (interrupt mode bits) and irqmux are in the
+	 * default state, i.e. the card wasn't initialized.
+	 * This is a kludge for certain PCI cards.
 	 */
-	irqmux = config_readl(socket, TI122X_IRQMUX);
-	irqmux = (irqmux & ~0x0f) | 0x02; /* route INTA */
-	if (!(ti_sysctl(socket) & TI122X_SCR_INTRTIE))
-		irqmux = (irqmux & ~0xf0) | 0x20; /* route INTB */
-	config_writel(socket, TI122X_IRQMUX, irqmux);
-#endif
+	if (!socket->socket.irq_mask) {
+		u32 irqmux;
+		u8 devctl;
+
+		devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
+		if ((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) {
+			irqmux = config_readl(socket, TI122X_IRQMUX);
+
+			if (irqmux == 0) {
+				printk (KERN_INFO "ti113x: Enabling PCI interrupts\n");
+
+				/* Route INTA to MFUNC0 */
+				config_writel(socket, TI122X_IRQMUX, 0x02);
+
+				/*
+				 * Enable parallel PCI interrupts but leave
+				 * serial ISA interrupts enabled just in case.
+				 */
+				devctl &= ~TI113X_DCR_IMODE_ISA;
+				config_writeb(socket, TI113X_DEVICE_CONTROL, devctl);
+			}
+		}
+	}
 
 	return ti12xx_override(socket);
 }


More information about the linux-pcmcia mailing list