blob: dbc4ffcf42decd31fbc2fd595cfc3bbbb08a9196 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * drivers/pci/setup-irq.c
3 *
4 * Extruded from code written by
5 * Dave Rusling (david.rusling@reo.mts.dec.com)
6 * David Mosberger (davidm@cs.arizona.edu)
7 * David Miller (davem@redhat.com)
8 *
9 * Support routines for initializing a PCI subsystem.
10 */
11
12
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/kernel.h>
14#include <linux/pci.h>
15#include <linux/errno.h>
16#include <linux/ioport.h>
17#include <linux/cache.h>
18
Thierry Reding8885b7b2012-09-17 13:22:54 +020019void __weak pcibios_update_irq(struct pci_dev *dev, int irq)
20{
21 dev_dbg(&dev->dev, "assigning IRQ %02d\n", irq);
22 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
23}
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
Thierry Reding3ddbebf2012-09-17 13:22:53 +020025static void
Linus Torvalds1da177e2005-04-16 15:20:36 -070026pdev_fixup_irq(struct pci_dev *dev,
27 u8 (*swizzle)(struct pci_dev *, u8 *),
Ralf Baechled5341942011-06-10 15:30:21 +010028 int (*map_irq)(const struct pci_dev *, u8, u8))
Linus Torvalds1da177e2005-04-16 15:20:36 -070029{
30 u8 pin, slot;
Andreas Block691cd0c2007-02-05 16:36:07 -080031 int irq = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
33 /* If this device is not on the primary bus, we need to figure out
34 which interrupt pin it will come in on. We know which slot it
35 will come in on 'cos that slot is where the bridge is. Each
36 time the interrupt line passes through a PCI-PCI bridge we must
37 apply the swizzle function. */
38
39 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
Andreas Block691cd0c2007-02-05 16:36:07 -080040 /* Cope with illegal. */
41 if (pin > 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -070042 pin = 1;
43
Andreas Block691cd0c2007-02-05 16:36:07 -080044 if (pin != 0) {
45 /* Follow the chain of bridges, swizzling as we go. */
46 slot = (*swizzle)(dev, &pin);
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
Andreas Block691cd0c2007-02-05 16:36:07 -080048 irq = (*map_irq)(dev, slot, pin);
49 if (irq == -1)
50 irq = 0;
51 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 dev->irq = irq;
53
Bjorn Helgaas80ccba12008-06-13 10:52:11 -060054 dev_dbg(&dev->dev, "fixup irq: got %d\n", dev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56 /* Always tell the device, so the driver knows what is
57 the real IRQ to use; the device does not use it. */
58 pcibios_update_irq(dev, irq);
59}
60
Thierry Reding3ddbebf2012-09-17 13:22:53 +020061void
Linus Torvalds1da177e2005-04-16 15:20:36 -070062pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
Ralf Baechled5341942011-06-10 15:30:21 +010063 int (*map_irq)(const struct pci_dev *, u8, u8))
Linus Torvalds1da177e2005-04-16 15:20:36 -070064{
65 struct pci_dev *dev = NULL;
Kulikov Vasiliy4e344b12010-07-03 20:04:39 +040066 for_each_pci_dev(dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 pdev_fixup_irq(dev, swizzle, map_irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068}