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