xref: /openbmc/linux/drivers/pci/setup-irq.c (revision 7328c8f48d1895b3fec98b0b319cfb856b4c4fa1)
1*7328c8f4SBjorn Helgaas // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *	drivers/pci/setup-irq.c
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  * Support routines for initializing a PCI subsystem.
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds 
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds #include <linux/kernel.h>
151da177e4SLinus Torvalds #include <linux/pci.h>
161da177e4SLinus Torvalds #include <linux/errno.h>
171da177e4SLinus Torvalds #include <linux/ioport.h>
181da177e4SLinus Torvalds #include <linux/cache.h>
1947a650f2SMatthew Minter #include "pci.h"
201da177e4SLinus Torvalds 
2147a650f2SMatthew Minter void pci_assign_irq(struct pci_dev *dev)
221da177e4SLinus Torvalds {
2347a650f2SMatthew Minter 	u8 pin;
2447a650f2SMatthew Minter 	u8 slot = -1;
25691cd0c2SAndreas Block 	int irq = 0;
2647a650f2SMatthew Minter 	struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus);
2747a650f2SMatthew Minter 
2847a650f2SMatthew Minter 	if (!(hbrg->map_irq)) {
2947a650f2SMatthew Minter 		dev_dbg(&dev->dev, "runtime IRQ mapping not provided by arch\n");
3047a650f2SMatthew Minter 		return;
3147a650f2SMatthew Minter 	}
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds 	/* If this device is not on the primary bus, we need to figure out
341da177e4SLinus Torvalds 	   which interrupt pin it will come in on.   We know which slot it
351da177e4SLinus Torvalds 	   will come in on 'cos that slot is where the bridge is.   Each
361da177e4SLinus Torvalds 	   time the interrupt line passes through a PCI-PCI bridge we must
371da177e4SLinus Torvalds 	   apply the swizzle function.  */
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
40691cd0c2SAndreas Block 	/* Cope with illegal. */
41691cd0c2SAndreas Block 	if (pin > 4)
421da177e4SLinus Torvalds 		pin = 1;
431da177e4SLinus Torvalds 
4447a650f2SMatthew Minter 	if (pin) {
451da177e4SLinus Torvalds 		/* Follow the chain of bridges, swizzling as we go.  */
4647a650f2SMatthew Minter 		if (hbrg->swizzle_irq)
4747a650f2SMatthew Minter 			slot = (*(hbrg->swizzle_irq))(dev, &pin);
481da177e4SLinus Torvalds 
4947a650f2SMatthew Minter 		/*
5047a650f2SMatthew Minter 		 * If a swizzling function is not used map_irq must
5147a650f2SMatthew Minter 		 * ignore slot
5247a650f2SMatthew Minter 		 */
5347a650f2SMatthew Minter 		irq = (*(hbrg->map_irq))(dev, slot, pin);
541da177e4SLinus Torvalds 		if (irq == -1)
551da177e4SLinus Torvalds 			irq = 0;
56691cd0c2SAndreas Block 	}
571da177e4SLinus Torvalds 	dev->irq = irq;
581da177e4SLinus Torvalds 
5947a650f2SMatthew Minter 	dev_dbg(&dev->dev, "assign IRQ: got %d\n", dev->irq);
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds 	/* Always tell the device, so the driver knows what is
621da177e4SLinus Torvalds 	   the real IRQ to use; the device does not use it. */
63606799ccSBjorn Helgaas 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
641da177e4SLinus Torvalds }
65