11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * drivers/pci/setup-irq.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Extruded from code written by 51da177e4SLinus Torvalds * Dave Rusling (david.rusling@reo.mts.dec.com) 61da177e4SLinus Torvalds * David Mosberger (davidm@cs.arizona.edu) 71da177e4SLinus Torvalds * David Miller (davem@redhat.com) 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * Support routines for initializing a PCI subsystem. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds #include <linux/kernel.h> 141da177e4SLinus Torvalds #include <linux/pci.h> 151da177e4SLinus Torvalds #include <linux/errno.h> 161da177e4SLinus Torvalds #include <linux/ioport.h> 171da177e4SLinus Torvalds #include <linux/cache.h> 18*47a650f2SMatthew Minter #include "pci.h" 191da177e4SLinus Torvalds 208885b7b6SThierry Reding void __weak pcibios_update_irq(struct pci_dev *dev, int irq) 218885b7b6SThierry Reding { 228885b7b6SThierry Reding dev_dbg(&dev->dev, "assigning IRQ %02d\n", irq); 238885b7b6SThierry Reding pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); 248885b7b6SThierry Reding } 251da177e4SLinus Torvalds 26*47a650f2SMatthew Minter void pci_assign_irq(struct pci_dev *dev) 271da177e4SLinus Torvalds { 28*47a650f2SMatthew Minter u8 pin; 29*47a650f2SMatthew Minter u8 slot = -1; 30691cd0c2SAndreas Block int irq = 0; 31*47a650f2SMatthew Minter struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus); 32*47a650f2SMatthew Minter 33*47a650f2SMatthew Minter if (!(hbrg->map_irq)) { 34*47a650f2SMatthew Minter dev_dbg(&dev->dev, "runtime IRQ mapping not provided by arch\n"); 35*47a650f2SMatthew Minter return; 36*47a650f2SMatthew Minter } 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds /* If this device is not on the primary bus, we need to figure out 391da177e4SLinus Torvalds which interrupt pin it will come in on. We know which slot it 401da177e4SLinus Torvalds will come in on 'cos that slot is where the bridge is. Each 411da177e4SLinus Torvalds time the interrupt line passes through a PCI-PCI bridge we must 421da177e4SLinus Torvalds apply the swizzle function. */ 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); 45691cd0c2SAndreas Block /* Cope with illegal. */ 46691cd0c2SAndreas Block if (pin > 4) 471da177e4SLinus Torvalds pin = 1; 481da177e4SLinus Torvalds 49*47a650f2SMatthew Minter if (pin) { 501da177e4SLinus Torvalds /* Follow the chain of bridges, swizzling as we go. */ 51*47a650f2SMatthew Minter if (hbrg->swizzle_irq) 52*47a650f2SMatthew Minter slot = (*(hbrg->swizzle_irq))(dev, &pin); 531da177e4SLinus Torvalds 54*47a650f2SMatthew Minter /* 55*47a650f2SMatthew Minter * If a swizzling function is not used map_irq must 56*47a650f2SMatthew Minter * ignore slot 57*47a650f2SMatthew Minter */ 58*47a650f2SMatthew Minter irq = (*(hbrg->map_irq))(dev, slot, pin); 591da177e4SLinus Torvalds if (irq == -1) 601da177e4SLinus Torvalds irq = 0; 61691cd0c2SAndreas Block } 621da177e4SLinus Torvalds dev->irq = irq; 631da177e4SLinus Torvalds 64*47a650f2SMatthew Minter dev_dbg(&dev->dev, "assign IRQ: got %d\n", dev->irq); 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds /* Always tell the device, so the driver knows what is 671da177e4SLinus Torvalds the real IRQ to use; the device does not use it. */ 681da177e4SLinus Torvalds pcibios_update_irq(dev, irq); 691da177e4SLinus Torvalds } 701da177e4SLinus Torvalds 713c78bc61SRyan Desfosses void pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *), 72d5341942SRalf Baechle int (*map_irq)(const struct pci_dev *, u8, u8)) 731da177e4SLinus Torvalds { 74*47a650f2SMatthew Minter /* 75*47a650f2SMatthew Minter * Implement pci_fixup_irqs() through pci_assign_irq(). 76*47a650f2SMatthew Minter * This code should be remove eventually, it is a wrapper 77*47a650f2SMatthew Minter * around pci_assign_irq() interface to keep current 78*47a650f2SMatthew Minter * pci_fixup_irqs() behaviour unchanged on architecture 79*47a650f2SMatthew Minter * code still relying on its interface. 80*47a650f2SMatthew Minter */ 811da177e4SLinus Torvalds struct pci_dev *dev = NULL; 82*47a650f2SMatthew Minter struct pci_host_bridge *hbrg = NULL; 833c78bc61SRyan Desfosses 84*47a650f2SMatthew Minter for_each_pci_dev(dev) { 85*47a650f2SMatthew Minter hbrg = pci_find_host_bridge(dev->bus); 86*47a650f2SMatthew Minter hbrg->swizzle_irq = swizzle; 87*47a650f2SMatthew Minter hbrg->map_irq = map_irq; 88*47a650f2SMatthew Minter pci_assign_irq(dev); 89*47a650f2SMatthew Minter hbrg->swizzle_irq = NULL; 90*47a650f2SMatthew Minter hbrg->map_irq = NULL; 91*47a650f2SMatthew Minter } 921da177e4SLinus Torvalds } 93e6b29deaSRay Jui EXPORT_SYMBOL_GPL(pci_fixup_irqs); 94