xref: /openbmc/linux/drivers/pci/setup-irq.c (revision df62ab5e)
17328c8f4SBjorn Helgaas // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
3df62ab5eSBjorn Helgaas  * Support routines for initializing a PCI subsystem
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Extruded from code written by
61da177e4SLinus Torvalds  *      Dave Rusling (david.rusling@reo.mts.dec.com)
71da177e4SLinus Torvalds  *      David Mosberger (davidm@cs.arizona.edu)
81da177e4SLinus Torvalds  *	David Miller (davem@redhat.com)
91da177e4SLinus Torvalds  */
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds #include <linux/kernel.h>
131da177e4SLinus Torvalds #include <linux/pci.h>
141da177e4SLinus Torvalds #include <linux/errno.h>
151da177e4SLinus Torvalds #include <linux/ioport.h>
161da177e4SLinus Torvalds #include <linux/cache.h>
1747a650f2SMatthew Minter #include "pci.h"
181da177e4SLinus Torvalds 
1947a650f2SMatthew Minter void pci_assign_irq(struct pci_dev *dev)
201da177e4SLinus Torvalds {
2147a650f2SMatthew Minter 	u8 pin;
2247a650f2SMatthew Minter 	u8 slot = -1;
23691cd0c2SAndreas Block 	int irq = 0;
2447a650f2SMatthew Minter 	struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus);
2547a650f2SMatthew Minter 
2647a650f2SMatthew Minter 	if (!(hbrg->map_irq)) {
277506dc79SFrederick Lawler 		pci_dbg(dev, "runtime IRQ mapping not provided by arch\n");
2847a650f2SMatthew Minter 		return;
2947a650f2SMatthew Minter 	}
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds 	/* If this device is not on the primary bus, we need to figure out
321da177e4SLinus Torvalds 	   which interrupt pin it will come in on.   We know which slot it
331da177e4SLinus Torvalds 	   will come in on 'cos that slot is where the bridge is.   Each
341da177e4SLinus Torvalds 	   time the interrupt line passes through a PCI-PCI bridge we must
351da177e4SLinus Torvalds 	   apply the swizzle function.  */
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
38691cd0c2SAndreas Block 	/* Cope with illegal. */
39691cd0c2SAndreas Block 	if (pin > 4)
401da177e4SLinus Torvalds 		pin = 1;
411da177e4SLinus Torvalds 
4247a650f2SMatthew Minter 	if (pin) {
431da177e4SLinus Torvalds 		/* Follow the chain of bridges, swizzling as we go.  */
4447a650f2SMatthew Minter 		if (hbrg->swizzle_irq)
4547a650f2SMatthew Minter 			slot = (*(hbrg->swizzle_irq))(dev, &pin);
461da177e4SLinus Torvalds 
4747a650f2SMatthew Minter 		/*
4847a650f2SMatthew Minter 		 * If a swizzling function is not used map_irq must
4947a650f2SMatthew Minter 		 * ignore slot
5047a650f2SMatthew Minter 		 */
5147a650f2SMatthew Minter 		irq = (*(hbrg->map_irq))(dev, slot, pin);
521da177e4SLinus Torvalds 		if (irq == -1)
531da177e4SLinus Torvalds 			irq = 0;
54691cd0c2SAndreas Block 	}
551da177e4SLinus Torvalds 	dev->irq = irq;
561da177e4SLinus Torvalds 
577506dc79SFrederick Lawler 	pci_dbg(dev, "assign IRQ: got %d\n", dev->irq);
581da177e4SLinus Torvalds 
591da177e4SLinus Torvalds 	/* Always tell the device, so the driver knows what is
601da177e4SLinus Torvalds 	   the real IRQ to use; the device does not use it. */
61606799ccSBjorn Helgaas 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
621da177e4SLinus Torvalds }
63