blob: 7129494754dd7396000789f0e2e297365d639f79 [file] [log] [blame]
Bjorn Helgaas7328c8f2018-01-26 11:45:16 -06001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
Bjorn Helgaasdf62ab52018-03-09 16:36:33 -06003 * Support routines for initializing a PCI subsystem
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
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)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
11
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/kernel.h>
13#include <linux/pci.h>
14#include <linux/errno.h>
15#include <linux/ioport.h>
16#include <linux/cache.h>
Matthew Minter47a650f2017-06-28 15:14:02 -050017#include "pci.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Matthew Minter47a650f2017-06-28 15:14:02 -050019void pci_assign_irq(struct pci_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070020{
Matthew Minter47a650f2017-06-28 15:14:02 -050021 u8 pin;
22 u8 slot = -1;
Andreas Block691cd0c2007-02-05 16:36:07 -080023 int irq = 0;
Matthew Minter47a650f2017-06-28 15:14:02 -050024 struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus);
25
26 if (!(hbrg->map_irq)) {
Frederick Lawler7506dc72018-01-18 12:55:24 -060027 pci_dbg(dev, "runtime IRQ mapping not provided by arch\n");
Matthew Minter47a650f2017-06-28 15:14:02 -050028 return;
29 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
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 'cos 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, &pin);
Andreas Block691cd0c2007-02-05 16:36:07 -080038 /* Cope with illegal. */
39 if (pin > 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 pin = 1;
41
Matthew Minter47a650f2017-06-28 15:14:02 -050042 if (pin) {
Andreas Block691cd0c2007-02-05 16:36:07 -080043 /* Follow the chain of bridges, swizzling as we go. */
Matthew Minter47a650f2017-06-28 15:14:02 -050044 if (hbrg->swizzle_irq)
45 slot = (*(hbrg->swizzle_irq))(dev, &pin);
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Matthew Minter47a650f2017-06-28 15:14:02 -050047 /*
48 * If a swizzling function is not used map_irq must
49 * ignore slot
50 */
51 irq = (*(hbrg->map_irq))(dev, slot, pin);
Andreas Block691cd0c2007-02-05 16:36:07 -080052 if (irq == -1)
53 irq = 0;
54 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 dev->irq = irq;
56
Frederick Lawler7506dc72018-01-18 12:55:24 -060057 pci_dbg(dev, "assign IRQ: got %d\n", dev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
59 /* Always tell the device, so the driver knows what is
60 the real IRQ to use; the device does not use it. */
Bjorn Helgaas606799c2017-08-10 12:49:57 -050061 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062}