blob: 774defe2f7e8c8d7803002cd23316ccfa0a35c37 [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>
Matthew Minter47a650f2017-06-28 15:14:02 -050018#include "pci.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070019
Matthew Minter47a650f2017-06-28 15:14:02 -050020void pci_assign_irq(struct pci_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070021{
Matthew Minter47a650f2017-06-28 15:14:02 -050022 u8 pin;
23 u8 slot = -1;
Andreas Block691cd0c2007-02-05 16:36:07 -080024 int irq = 0;
Matthew Minter47a650f2017-06-28 15:14:02 -050025 struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus);
26
27 if (!(hbrg->map_irq)) {
Frederick Lawler7506dc72018-01-18 12:55:24 -060028 pci_dbg(dev, "runtime IRQ mapping not provided by arch\n");
Matthew Minter47a650f2017-06-28 15:14:02 -050029 return;
30 }
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
Matthew Minter47a650f2017-06-28 15:14:02 -050043 if (pin) {
Andreas Block691cd0c2007-02-05 16:36:07 -080044 /* Follow the chain of bridges, swizzling as we go. */
Matthew Minter47a650f2017-06-28 15:14:02 -050045 if (hbrg->swizzle_irq)
46 slot = (*(hbrg->swizzle_irq))(dev, &pin);
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
Matthew Minter47a650f2017-06-28 15:14:02 -050048 /*
49 * If a swizzling function is not used map_irq must
50 * ignore slot
51 */
52 irq = (*(hbrg->map_irq))(dev, slot, pin);
Andreas Block691cd0c2007-02-05 16:36:07 -080053 if (irq == -1)
54 irq = 0;
55 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 dev->irq = irq;
57
Frederick Lawler7506dc72018-01-18 12:55:24 -060058 pci_dbg(dev, "assign IRQ: got %d\n", dev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60 /* Always tell the device, so the driver knows what is
61 the real IRQ to use; the device does not use it. */
Bjorn Helgaas606799c2017-08-10 12:49:57 -050062 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -070063}