xref: /openbmc/linux/drivers/pci/setup-irq.c (revision 606799cc)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *	drivers/pci/setup-irq.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Extruded from code written by
51da177e4SLinus Torvalds  *      Dave Rusling (david.rusling@reo.mts.dec.com)
61da177e4SLinus Torvalds  *      David Mosberger (davidm@cs.arizona.edu)
71da177e4SLinus Torvalds  *	David Miller (davem@redhat.com)
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * Support routines for initializing a PCI subsystem.
101da177e4SLinus Torvalds  */
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds 
131da177e4SLinus Torvalds #include <linux/kernel.h>
141da177e4SLinus Torvalds #include <linux/pci.h>
151da177e4SLinus Torvalds #include <linux/errno.h>
161da177e4SLinus Torvalds #include <linux/ioport.h>
171da177e4SLinus Torvalds #include <linux/cache.h>
1847a650f2SMatthew Minter #include "pci.h"
191da177e4SLinus Torvalds 
2047a650f2SMatthew Minter void pci_assign_irq(struct pci_dev *dev)
211da177e4SLinus Torvalds {
2247a650f2SMatthew Minter 	u8 pin;
2347a650f2SMatthew Minter 	u8 slot = -1;
24691cd0c2SAndreas Block 	int irq = 0;
2547a650f2SMatthew Minter 	struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus);
2647a650f2SMatthew Minter 
2747a650f2SMatthew Minter 	if (!(hbrg->map_irq)) {
2847a650f2SMatthew Minter 		dev_dbg(&dev->dev, "runtime IRQ mapping not provided by arch\n");
2947a650f2SMatthew Minter 		return;
3047a650f2SMatthew Minter 	}
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds 	/* If this device is not on the primary bus, we need to figure out
331da177e4SLinus Torvalds 	   which interrupt pin it will come in on.   We know which slot it
341da177e4SLinus Torvalds 	   will come in on 'cos that slot is where the bridge is.   Each
351da177e4SLinus Torvalds 	   time the interrupt line passes through a PCI-PCI bridge we must
361da177e4SLinus Torvalds 	   apply the swizzle function.  */
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
39691cd0c2SAndreas Block 	/* Cope with illegal. */
40691cd0c2SAndreas Block 	if (pin > 4)
411da177e4SLinus Torvalds 		pin = 1;
421da177e4SLinus Torvalds 
4347a650f2SMatthew Minter 	if (pin) {
441da177e4SLinus Torvalds 		/* Follow the chain of bridges, swizzling as we go.  */
4547a650f2SMatthew Minter 		if (hbrg->swizzle_irq)
4647a650f2SMatthew Minter 			slot = (*(hbrg->swizzle_irq))(dev, &pin);
471da177e4SLinus Torvalds 
4847a650f2SMatthew Minter 		/*
4947a650f2SMatthew Minter 		 * If a swizzling function is not used map_irq must
5047a650f2SMatthew Minter 		 * ignore slot
5147a650f2SMatthew Minter 		 */
5247a650f2SMatthew Minter 		irq = (*(hbrg->map_irq))(dev, slot, pin);
531da177e4SLinus Torvalds 		if (irq == -1)
541da177e4SLinus Torvalds 			irq = 0;
55691cd0c2SAndreas Block 	}
561da177e4SLinus Torvalds 	dev->irq = irq;
571da177e4SLinus Torvalds 
5847a650f2SMatthew Minter 	dev_dbg(&dev->dev, "assign IRQ: got %d\n", dev->irq);
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds 	/* Always tell the device, so the driver knows what is
611da177e4SLinus Torvalds 	   the real IRQ to use; the device does not use it. */
62606799ccSBjorn Helgaas 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
631da177e4SLinus Torvalds }
64