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