diff options
Diffstat (limited to 'drivers/pcmcia/ti113x.h')
-rw-r--r-- | drivers/pcmcia/ti113x.h | 40 |
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 */ | ||
446 | static 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 | */ |
450 | static int ti12xx_tie_interrupts(struct yenta_socket *socket, int *old_irq) | 469 | static 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 | */ |
490 | static void ti12xx_irqroute_func1(struct yenta_socket *socket) | 505 | static 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 | ||