[PATCH] pcmcia: yenta TI: align irq of func1 to func0 if INTRTIE is set
Daniel Ritz [Thu, 5 May 2005 23:15:57 +0000 (16:15 -0700)]
Make sure that if the INTRTIE bit is set both functions of the cardbus
bridge use the same IRQ before doing any probing...

[ yes i hate the TI bridges for the fact that they are very flexible
  so that so many BIOS vendors get it wrong. ]

Signed-off-by: Daniel Ritz <daniel.ritz@gmx.ch>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

drivers/pcmcia/ti113x.h

index 52c073a..a8a1d10 100644 (file)
@@ -442,6 +442,25 @@ out:
 }
 
 
+/* changes the irq of func1 to match that of func0 */
+static int ti12xx_align_irqs(struct yenta_socket *socket, int *old_irq)
+{
+       struct pci_dev *func0;
+
+       /* find func0 device */
+       func0 = pci_get_slot(socket->dev->bus, socket->dev->devfn & ~0x07);
+       if (!func0)
+               return 0;
+
+       if (old_irq)
+               *old_irq = socket->cb_irq;
+       socket->cb_irq = socket->dev->irq = func0->irq;
+
+       pci_dev_put(func0);
+
+       return 1;
+}
+
 /*
  * ties INTA and INTB together. also changes the devices irq to that of
  * the function 0 device. call from func1 only.
@@ -449,26 +468,22 @@ out:
  */
 static int ti12xx_tie_interrupts(struct yenta_socket *socket, int *old_irq)
 {
-       struct pci_dev *func0;
        u32 sysctl;
+       int ret;
 
        sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
        if (sysctl & TI122X_SCR_INTRTIE)
                return 0;
 
-       /* find func0 device */
-       func0 = pci_get_slot(socket->dev->bus, socket->dev->devfn & ~0x07);
-       if (!func0)
+       /* align */
+       ret = ti12xx_align_irqs(socket, old_irq);
+       if (!ret)
                return 0;
 
-       /* change the interrupt to match func0, tie 'em up */
-       *old_irq = socket->cb_irq;
-       socket->cb_irq = socket->dev->irq = func0->irq;
+       /* tie */
        sysctl |= TI122X_SCR_INTRTIE;
        config_writel(socket, TI113X_SYSTEM_CONTROL, sysctl);
 
-       pci_dev_put(func0);
-
        return 1;
 }
 
@@ -489,7 +504,7 @@ static void ti12xx_untie_interrupts(struct yenta_socket *socket, int old_irq)
  */
 static void ti12xx_irqroute_func1(struct yenta_socket *socket)
 {
-       u32 mfunc, mfunc_old, devctl;
+       u32 mfunc, mfunc_old, devctl, sysctl;
        int pci_irq_status;
 
        mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC);
@@ -497,6 +512,11 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
        printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n",
               pci_name(socket->dev), mfunc, devctl);
 
+       /* if IRQs are configured as tied, align irq of func1 with func0 */
+       sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
+       if (sysctl & TI122X_SCR_INTRTIE)
+               ti12xx_align_irqs(socket, NULL);
+
        /* make sure PCI interrupts are enabled before probing */
        ti_init(socket);