aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorDaniel Ritz <daniel.ritz@gmx.ch>2005-05-05 19:15:57 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-05 19:36:43 -0400
commitc835a388968f5437491e3fe6e9b0332bc3c52e0e (patch)
treecdc6c80289327999e23996c07abe68a869534783 /drivers/pcmcia
parentc35e66a4216c99fe94868ed3f714bd2708d0032a (diff)
[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: 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>
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/ti113x.h40
1 files changed, 30 insertions, 10 deletions
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index 52c073a9d7e4..a8a1d104524a 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -442,6 +442,25 @@ out:
442} 442}
443 443
444 444
445/* changes the irq of func1 to match that of func0 */
446static int ti12xx_align_irqs(struct yenta_socket *socket, int *old_irq)
447{
448 struct pci_dev *func0;
449
450 /* find func0 device */
451 func0 = pci_get_slot(socket->dev->bus, socket->dev->devfn & ~0x07);
452 if (!func0)
453 return 0;
454
455 if (old_irq)
456 *old_irq = socket->cb_irq;
457 socket->cb_irq = socket->dev->irq = func0->irq;
458
459 pci_dev_put(func0);
460
461 return 1;
462}
463
445/* 464/*
446 * ties INTA and INTB together. also changes the devices irq to that of 465 * ties INTA and INTB together. also changes the devices irq to that of
447 * the function 0 device. call from func1 only. 466 * the function 0 device. call from func1 only.
@@ -449,26 +468,22 @@ out:
449 */ 468 */
450static int ti12xx_tie_interrupts(struct yenta_socket *socket, int *old_irq) 469static int ti12xx_tie_interrupts(struct yenta_socket *socket, int *old_irq)
451{ 470{
452 struct pci_dev *func0;
453 u32 sysctl; 471 u32 sysctl;
472 int ret;
454 473
455 sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL); 474 sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
456 if (sysctl & TI122X_SCR_INTRTIE) 475 if (sysctl & TI122X_SCR_INTRTIE)
457 return 0; 476 return 0;
458 477
459 /* find func0 device */ 478 /* align */
460 func0 = pci_get_slot(socket->dev->bus, socket->dev->devfn & ~0x07); 479 ret = ti12xx_align_irqs(socket, old_irq);
461 if (!func0) 480 if (!ret)
462 return 0; 481 return 0;
463 482
464 /* change the interrupt to match func0, tie 'em up */ 483 /* tie */
465 *old_irq = socket->cb_irq;
466 socket->cb_irq = socket->dev->irq = func0->irq;
467 sysctl |= TI122X_SCR_INTRTIE; 484 sysctl |= TI122X_SCR_INTRTIE;
468 config_writel(socket, TI113X_SYSTEM_CONTROL, sysctl); 485 config_writel(socket, TI113X_SYSTEM_CONTROL, sysctl);
469 486
470 pci_dev_put(func0);
471
472 return 1; 487 return 1;
473} 488}
474 489
@@ -489,7 +504,7 @@ static void ti12xx_untie_interrupts(struct yenta_socket *socket, int old_irq)
489 */ 504 */
490static void ti12xx_irqroute_func1(struct yenta_socket *socket) 505static void ti12xx_irqroute_func1(struct yenta_socket *socket)
491{ 506{
492 u32 mfunc, mfunc_old, devctl; 507 u32 mfunc, mfunc_old, devctl, sysctl;
493 int pci_irq_status; 508 int pci_irq_status;
494 509
495 mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC); 510 mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC);
@@ -497,6 +512,11 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
497 printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n", 512 printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n",
498 pci_name(socket->dev), mfunc, devctl); 513 pci_name(socket->dev), mfunc, devctl);
499 514
515 /* if IRQs are configured as tied, align irq of func1 with func0 */
516 sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
517 if (sysctl & TI122X_SCR_INTRTIE)
518 ti12xx_align_irqs(socket, NULL);
519
500 /* make sure PCI interrupts are enabled before probing */ 520 /* make sure PCI interrupts are enabled before probing */
501 ti_init(socket); 521 ti_init(socket);
502 522