Commit c835a388 authored by Daniel Ritz's avatar Daniel Ritz Committed by Linus Torvalds

[PATCH] pcmcia: yenta TI: align irq of func1 to func0 if INTRTIE is set

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: default avatarDaniel Ritz <daniel.ritz@gmx.ch>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent c35e66a4
...@@ -442,6 +442,25 @@ out: ...@@ -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 * ties INTA and INTB together. also changes the devices irq to that of
* the function 0 device. call from func1 only. * the function 0 device. call from func1 only.
...@@ -449,26 +468,22 @@ out: ...@@ -449,26 +468,22 @@ out:
*/ */
static int ti12xx_tie_interrupts(struct yenta_socket *socket, int *old_irq) static int ti12xx_tie_interrupts(struct yenta_socket *socket, int *old_irq)
{ {
struct pci_dev *func0;
u32 sysctl; u32 sysctl;
int ret;
sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL); sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
if (sysctl & TI122X_SCR_INTRTIE) if (sysctl & TI122X_SCR_INTRTIE)
return 0; return 0;
/* find func0 device */ /* align */
func0 = pci_get_slot(socket->dev->bus, socket->dev->devfn & ~0x07); ret = ti12xx_align_irqs(socket, old_irq);
if (!func0) if (!ret)
return 0; return 0;
/* change the interrupt to match func0, tie 'em up */ /* tie */
*old_irq = socket->cb_irq;
socket->cb_irq = socket->dev->irq = func0->irq;
sysctl |= TI122X_SCR_INTRTIE; sysctl |= TI122X_SCR_INTRTIE;
config_writel(socket, TI113X_SYSTEM_CONTROL, sysctl); config_writel(socket, TI113X_SYSTEM_CONTROL, sysctl);
pci_dev_put(func0);
return 1; return 1;
} }
...@@ -489,7 +504,7 @@ static void ti12xx_untie_interrupts(struct yenta_socket *socket, int old_irq) ...@@ -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) static void ti12xx_irqroute_func1(struct yenta_socket *socket)
{ {
u32 mfunc, mfunc_old, devctl; u32 mfunc, mfunc_old, devctl, sysctl;
int pci_irq_status; int pci_irq_status;
mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC); mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC);
...@@ -497,6 +512,11 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket) ...@@ -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", printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n",
pci_name(socket->dev), mfunc, devctl); 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 */ /* make sure PCI interrupts are enabled before probing */
ti_init(socket); ti_init(socket);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment