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 #include <linux/kernel.h> 121da177e4SLinus Torvalds #include <linux/pci.h> 131da177e4SLinus Torvalds #include <linux/errno.h> 141da177e4SLinus Torvalds #include <linux/ioport.h> 151da177e4SLinus Torvalds #include <linux/cache.h> 1647a650f2SMatthew Minter #include "pci.h" 171da177e4SLinus Torvalds 1847a650f2SMatthew Minter void pci_assign_irq(struct pci_dev *dev) 191da177e4SLinus Torvalds { 2047a650f2SMatthew Minter u8 pin; 2147a650f2SMatthew Minter u8 slot = -1; 22691cd0c2SAndreas Block int irq = 0; 2347a650f2SMatthew Minter struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus); 2447a650f2SMatthew Minter 2547a650f2SMatthew Minter if (!(hbrg->map_irq)) { 267506dc79SFrederick Lawler pci_dbg(dev, "runtime IRQ mapping not provided by arch\n"); 2747a650f2SMatthew Minter return; 2847a650f2SMatthew Minter } 291da177e4SLinus Torvalds 30*9a0a1417SPranay Sanghai /* 31*9a0a1417SPranay Sanghai * If this device is not on the primary bus, we need to figure out 32*9a0a1417SPranay Sanghai * which interrupt pin it will come in on. We know which slot it 33*9a0a1417SPranay Sanghai * will come in on because that slot is where the bridge is. Each 34*9a0a1417SPranay Sanghai * time the interrupt line passes through a PCI-PCI bridge we must 35*9a0a1417SPranay Sanghai * apply the swizzle function. 36*9a0a1417SPranay Sanghai */ 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 /* 48*9a0a1417SPranay Sanghai * If a swizzling function is not used, map_irq() must 49*9a0a1417SPranay Sanghai * 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 59*9a0a1417SPranay Sanghai /* 60*9a0a1417SPranay Sanghai * Always tell the device, so the driver knows what is the real IRQ 61*9a0a1417SPranay Sanghai * to use; the device does not use it. 62*9a0a1417SPranay Sanghai */ 63606799ccSBjorn Helgaas pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); 641da177e4SLinus Torvalds } 65