1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Support routines for initializing a PCI subsystem |
4 | * |
5 | * Extruded from code written by |
6 | * Dave Rusling (david.rusling@reo.mts.dec.com) |
7 | * David Mosberger (davidm@cs.arizona.edu) |
8 | * David Miller (davem@redhat.com) |
9 | */ |
10 | |
11 | #include <linux/kernel.h> |
12 | #include <linux/pci.h> |
13 | #include <linux/errno.h> |
14 | #include <linux/ioport.h> |
15 | #include <linux/cache.h> |
16 | #include "pci.h" |
17 | |
18 | void pci_assign_irq(struct pci_dev *dev) |
19 | { |
20 | u8 pin; |
21 | u8 slot = -1; |
22 | int irq = 0; |
23 | struct pci_host_bridge *hbrg = pci_find_host_bridge(bus: dev->bus); |
24 | |
25 | if (!(hbrg->map_irq)) { |
26 | pci_dbg(dev, "runtime IRQ mapping not provided by arch\n" ); |
27 | return; |
28 | } |
29 | |
30 | /* |
31 | * If this device is not on the primary bus, we need to figure out |
32 | * which interrupt pin it will come in on. We know which slot it |
33 | * will come in on because that slot is where the bridge is. Each |
34 | * time the interrupt line passes through a PCI-PCI bridge we must |
35 | * apply the swizzle function. |
36 | */ |
37 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, val: &pin); |
38 | /* Cope with illegal. */ |
39 | if (pin > 4) |
40 | pin = 1; |
41 | |
42 | if (pin) { |
43 | /* Follow the chain of bridges, swizzling as we go. */ |
44 | if (hbrg->swizzle_irq) |
45 | slot = (*(hbrg->swizzle_irq))(dev, &pin); |
46 | |
47 | /* |
48 | * If a swizzling function is not used, map_irq() must |
49 | * ignore slot. |
50 | */ |
51 | irq = (*(hbrg->map_irq))(dev, slot, pin); |
52 | if (irq == -1) |
53 | irq = 0; |
54 | } |
55 | dev->irq = irq; |
56 | |
57 | pci_dbg(dev, "assign IRQ: got %d\n" , dev->irq); |
58 | |
59 | /* |
60 | * Always tell the device, so the driver knows what is the real IRQ |
61 | * to use; the device does not use it. |
62 | */ |
63 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, val: irq); |
64 | } |
65 | |