[PATCH] Support for TI1031 PCI -> PCMCIA bridges

Tim Small tim_small at yahoo.com
Sun May 18 01:16:41 BST 2003


Hi Pavel et al,

I've got my TI1031 working under 2.4.20 now..  This is built on Pavel's 
original patch here:

http://lists.insecure.org/lists/linux-kernel/2003/Mar/0012.html

Pavel suggested this different change to pci.c (although I think that if you are presenting a CARDBUS header type then the cardbus vendor and device IDs should be present), but I don't know which is correct:

--- linux.orig/drivers/pci/pci.c
+++ linux/drivers/pci/pci.c
@@ -1405,12 +1405,17 @@ int pci_setup_device(struct pci_dev * de
 		break;
 
 	case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */
-		if (class != PCI_CLASS_BRIDGE_CARDBUS)
+		switch (class) {
+		case PCI_CLASS_BRIDGE_CARDBUS:
+			pci_read_bases(dev, 1, 0);
+			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
+			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);
+			/* fallthrough */
+		case PCI_CLASS_BRIDGE_PCMCIA:
+			pci_read_irq(dev);
+		default:
 			goto bad;
-		pci_read_irq(dev);
-		pci_read_bases(dev, 1, 0);
-		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
-		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);
+		}
 		break;
 
 	default:				    /* unknown header */


The patch below is against a stock 2.4.20 (and so includes Pavel's 
original)...  I'd be glad of any feedback - particularly if you have a 
TI PCI1031 based device (pretty rare, I think).  The sypnosis is:

. Change pci.c to allow PCMCIA bridge devices which present CARDBUS PCI 
header types (all TI PCI1031s do this, and possibly other similar devices)
. Change the yenta driver to correctly init the 1031, principally 
routing interrupts correctly, but also so that PCI <-> PCMCIA bridges 
are picked up (this is the only part of the patch that I'm not 
particularly sure about)..

Thanks!

Tim.
-------------- next part --------------
--- linux-2.4.20-old/drivers/pcmcia/yenta.c	2003-01-18 22:20:34.000000000 +0000
+++ linux-2.4.20-miniitx/drivers/pcmcia/yenta.c	2003-05-17 23:31:29.000000000 +0100
@@ -798,7 +798,7 @@
 	struct pci_socket_ops *op;
 } cardbus_override[] = {
 	{ PD(TI,1130),	&ti113x_ops },
-	{ PD(TI,1031),	&ti_ops },
+	{ PD(TI,1031),	&ti113x_ops },
 	{ PD(TI,1131),	&ti113x_ops },
 	{ PD(TI,1250),	&ti1250_ops },
 	{ PD(TI,1220),	&ti_ops },
--- linux-2.4.20-old/drivers/pcmcia/ti113x.h	2003-01-18 22:45:57.000000000 +0000
+++ linux-2.4.20-miniitx/drivers/pcmcia/ti113x.h	2003-05-17 23:30:28.000000000 +0100
@@ -32,6 +32,12 @@
 
 #include <linux/config.h>
 
+/* Register definitions for TI 103X PCI-to-PCMCIA bridges */ 
+
+#define TI103X_BRIDGE_CONTROL		0x003e  /* 16 bit */
+#define  TI103X_BRC_WRITEPOST_ENA	0x0400
+#define  TI103X_BRC_PCI_IREQ_ENA	0x0080
+
 /* Register definitions for TI 113X PCI-to-CardBus bridges */
 
 /* System Control Register */
@@ -167,6 +173,43 @@
 		new |= I365_INTR_ENA;
 	if (new != reg)
 		exca_writeb(socket, I365_INTCTL, new);
+
+/*
+ * If ISA interrupts don't work, then fall back to routing card
+ * interrupts to the PCI INTA/B interrupt lines (other methods
+ * are the PCI IRQSER pin, or direct connection to the ISA bus
+ * IRQ lines).
+ */
+	if (!socket->cap.irq_mask) {
+		printk (KERN_INFO "ti113x: Routing card interrupts to PCI\n");
+		if (socket->dev->device == PCI_DEVICE_ID_TI_1031) {
+			/* The 1030 may have this interface as well. */
+			int devctl;
+			u16 bridgectl;
+			devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
+			devctl &= ~TI113X_DCR_IMODE_SERIAL;
+
+			/* Route functional interrupts to PCI */
+			bridgectl = config_readw(socket, TI103X_BRIDGE_CONTROL);
+			bridgectl &= ~TI103X_BRC_PCI_IREQ_ENA;
+
+			config_writeb(socket, TI113X_DEVICE_CONTROL, devctl);
+			config_writew(socket, TI103X_BRIDGE_CONTROL, bridgectl);
+		} else {
+			int devctl, irqmux;
+			
+			devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
+			devctl &= ~TI113X_DCR_IMODE_MASK;
+			
+			/* Is twiddling this register safe on earlier chips? */
+			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);
+		}
+	}		
 	return 0;
 }
 
--- linux-2.4.20-old/drivers/pci/pci.c	2003-01-18 22:21:11.000000000 +0000
+++ linux-2.4.20-miniitx/drivers/pci/pci.c	2003-05-09 13:12:06.000000000 +0100
@@ -1391,7 +1391,7 @@
 		break;
 
 	case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */
-		if (class != PCI_CLASS_BRIDGE_CARDBUS)
+		if ((class != PCI_CLASS_BRIDGE_CARDBUS) && (class != PCI_CLASS_BRIDGE_PCMCIA))
 			goto bad;
 		pci_read_irq(dev);
 		pci_read_bases(dev, 1, 0);
--- linux-2.4.20-old/drivers/pcmcia/pci_socket.c	2001-12-21 17:41:55.000000000 +0000
+++ linux-2.4.20-miniitx/drivers/pcmcia/pci_socket.c	2003-05-17 23:49:14.000000000 +0100
@@ -235,7 +235,7 @@
 
 static struct pci_device_id cardbus_table [] __devinitdata = { {
 	class:		PCI_CLASS_BRIDGE_CARDBUS << 8,
-	class_mask:	~0,
+	class_mask:	~(0x02 << 8), /* also allow PCMCIA BRIDGES */
 
 	vendor:		PCI_ANY_ID,
 	device:		PCI_ANY_ID,


More information about the linux-pcmcia mailing list