blob: 95c225be49d17c82483ce12aef9aca2cddcdb7d1 [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
Ryan Desfosses3c78bc62014-04-18 20:13:49 -040025static void pdev_fixup_irq(struct pci_dev *dev,
26 u8 (*swizzle)(struct pci_dev *, u8 *),
27 int (*map_irq)(const struct pci_dev *, u8, u8))
Linus Torvalds1da177e2005-04-16 15:20:36 -070028{
29 u8 pin, slot;
Andreas Block691cd0c2007-02-05 16:36:07 -080030 int irq = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32 /* If this device is not on the primary bus, we need to figure out
33 which interrupt pin it will come in on. We know which slot it
34 will come in on 'cos that slot is where the bridge is. Each
35 time the interrupt line passes through a PCI-PCI bridge we must
36 apply the swizzle function. */
37
38 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
Andreas Block691cd0c2007-02-05 16:36:07 -080039 /* Cope with illegal. */
40 if (pin > 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 pin = 1;
42
Andreas Block691cd0c2007-02-05 16:36:07 -080043 if (pin != 0) {
44 /* Follow the chain of bridges, swizzling as we go. */
45 slot = (*swizzle)(dev, &pin);
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Andreas Block691cd0c2007-02-05 16:36:07 -080047 irq = (*map_irq)(dev, slot, pin);
48 if (irq == -1)
49 irq = 0;
50 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 dev->irq = irq;
52
Bjorn Helgaas80ccba12008-06-13 10:52:11 -060053 dev_dbg(&dev->dev, "fixup irq: got %d\n", dev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55 /* Always tell the device, so the driver knows what is
56 the real IRQ to use; the device does not use it. */
57 pcibios_update_irq(dev, irq);
58}
59
Ryan Desfosses3c78bc62014-04-18 20:13:49 -040060void pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
61 int (*map_irq)(const struct pci_dev *, u8, u8))
Linus Torvalds1da177e2005-04-16 15:20:36 -070062{
63 struct pci_dev *dev = NULL;
Ryan Desfosses3c78bc62014-04-18 20:13:49 -040064
Kulikov Vasiliy4e344b12010-07-03 20:04:39 +040065 for_each_pci_dev(dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 pdev_fixup_irq(dev, swizzle, map_irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067}
Ray Juie6b29de2015-04-08 11:21:33 -070068EXPORT_SYMBOL_GPL(pci_fixup_irqs);