root/arch/powerpc/sysdev/mpic_u3msi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mpic_u3msi_mask_irq
  2. mpic_u3msi_unmask_irq
  3. read_ht_magic_addr
  4. find_ht_magic_addr
  5. find_u4_magic_addr
  6. u3msi_teardown_msi_irqs
  7. u3msi_setup_msi_irqs
  8. mpic_u3msi_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright 2006, Segher Boessenkool, IBM Corporation.
   4  * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
   5  */
   6 
   7 #include <linux/irq.h>
   8 #include <linux/msi.h>
   9 #include <asm/mpic.h>
  10 #include <asm/prom.h>
  11 #include <asm/hw_irq.h>
  12 #include <asm/ppc-pci.h>
  13 #include <asm/msi_bitmap.h>
  14 
  15 #include "mpic.h"
  16 
  17 /* A bit ugly, can we get this from the pci_dev somehow? */
  18 static struct mpic *msi_mpic;
  19 
  20 static void mpic_u3msi_mask_irq(struct irq_data *data)
  21 {
  22         pci_msi_mask_irq(data);
  23         mpic_mask_irq(data);
  24 }
  25 
  26 static void mpic_u3msi_unmask_irq(struct irq_data *data)
  27 {
  28         mpic_unmask_irq(data);
  29         pci_msi_unmask_irq(data);
  30 }
  31 
  32 static struct irq_chip mpic_u3msi_chip = {
  33         .irq_shutdown           = mpic_u3msi_mask_irq,
  34         .irq_mask               = mpic_u3msi_mask_irq,
  35         .irq_unmask             = mpic_u3msi_unmask_irq,
  36         .irq_eoi                = mpic_end_irq,
  37         .irq_set_type           = mpic_set_irq_type,
  38         .irq_set_affinity       = mpic_set_affinity,
  39         .name                   = "MPIC-U3MSI",
  40 };
  41 
  42 static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
  43 {
  44         u8 flags;
  45         u32 tmp;
  46         u64 addr;
  47 
  48         pci_read_config_byte(pdev, pos + HT_MSI_FLAGS, &flags);
  49 
  50         if (flags & HT_MSI_FLAGS_FIXED)
  51                 return HT_MSI_FIXED_ADDR;
  52 
  53         pci_read_config_dword(pdev, pos + HT_MSI_ADDR_LO, &tmp);
  54         addr = tmp & HT_MSI_ADDR_LO_MASK;
  55         pci_read_config_dword(pdev, pos + HT_MSI_ADDR_HI, &tmp);
  56         addr = addr | ((u64)tmp << 32);
  57 
  58         return addr;
  59 }
  60 
  61 static u64 find_ht_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
  62 {
  63         struct pci_bus *bus;
  64         unsigned int pos;
  65 
  66         for (bus = pdev->bus; bus && bus->self; bus = bus->parent) {
  67                 pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING);
  68                 if (pos)
  69                         return read_ht_magic_addr(bus->self, pos);
  70         }
  71 
  72         return 0;
  73 }
  74 
  75 static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
  76 {
  77         struct pci_controller *hose = pci_bus_to_host(pdev->bus);
  78 
  79         /* U4 PCIe MSIs need to write to the special register in
  80          * the bridge that generates interrupts. There should be
  81          * theorically a register at 0xf8005000 where you just write
  82          * the MSI number and that triggers the right interrupt, but
  83          * unfortunately, this is busted in HW, the bridge endian swaps
  84          * the value and hits the wrong nibble in the register.
  85          *
  86          * So instead we use another register set which is used normally
  87          * for converting HT interrupts to MPIC interrupts, which decodes
  88          * the interrupt number as part of the low address bits
  89          *
  90          * This will not work if we ever use more than one legacy MSI in
  91          * a block but we never do. For one MSI or multiple MSI-X where
  92          * each interrupt address can be specified separately, it works
  93          * just fine.
  94          */
  95         if (of_device_is_compatible(hose->dn, "u4-pcie") ||
  96             of_device_is_compatible(hose->dn, "U4-pcie"))
  97                 return 0xf8004000 | (hwirq << 4);
  98 
  99         return 0;
 100 }
 101 
 102 static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
 103 {
 104         struct msi_desc *entry;
 105         irq_hw_number_t hwirq;
 106 
 107         for_each_pci_msi_entry(entry, pdev) {
 108                 if (!entry->irq)
 109                         continue;
 110 
 111                 hwirq = virq_to_hw(entry->irq);
 112                 irq_set_msi_desc(entry->irq, NULL);
 113                 irq_dispose_mapping(entry->irq);
 114                 msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1);
 115         }
 116 
 117         return;
 118 }
 119 
 120 static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 121 {
 122         unsigned int virq;
 123         struct msi_desc *entry;
 124         struct msi_msg msg;
 125         u64 addr;
 126         int hwirq;
 127 
 128         if (type == PCI_CAP_ID_MSIX)
 129                 pr_debug("u3msi: MSI-X untested, trying anyway.\n");
 130 
 131         /* If we can't find a magic address then MSI ain't gonna work */
 132         if (find_ht_magic_addr(pdev, 0) == 0 &&
 133             find_u4_magic_addr(pdev, 0) == 0) {
 134                 pr_debug("u3msi: no magic address found for %s\n",
 135                          pci_name(pdev));
 136                 return -ENXIO;
 137         }
 138 
 139         for_each_pci_msi_entry(entry, pdev) {
 140                 hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
 141                 if (hwirq < 0) {
 142                         pr_debug("u3msi: failed allocating hwirq\n");
 143                         return hwirq;
 144                 }
 145 
 146                 addr = find_ht_magic_addr(pdev, hwirq);
 147                 if (addr == 0)
 148                         addr = find_u4_magic_addr(pdev, hwirq);
 149                 msg.address_lo = addr & 0xFFFFFFFF;
 150                 msg.address_hi = addr >> 32;
 151 
 152                 virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
 153                 if (!virq) {
 154                         pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq);
 155                         msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1);
 156                         return -ENOSPC;
 157                 }
 158 
 159                 irq_set_msi_desc(virq, entry);
 160                 irq_set_chip(virq, &mpic_u3msi_chip);
 161                 irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
 162 
 163                 pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
 164                           virq, hwirq, (unsigned long)addr);
 165 
 166                 printk("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
 167                           virq, hwirq, (unsigned long)addr);
 168                 msg.data = hwirq;
 169                 pci_write_msi_msg(virq, &msg);
 170 
 171                 hwirq++;
 172         }
 173 
 174         return 0;
 175 }
 176 
 177 int mpic_u3msi_init(struct mpic *mpic)
 178 {
 179         int rc;
 180         struct pci_controller *phb;
 181 
 182         rc = mpic_msi_init_allocator(mpic);
 183         if (rc) {
 184                 pr_debug("u3msi: Error allocating bitmap!\n");
 185                 return rc;
 186         }
 187 
 188         pr_debug("u3msi: Registering MPIC U3 MSI callbacks.\n");
 189 
 190         BUG_ON(msi_mpic);
 191         msi_mpic = mpic;
 192 
 193         list_for_each_entry(phb, &hose_list, list_node) {
 194                 WARN_ON(phb->controller_ops.setup_msi_irqs);
 195                 phb->controller_ops.setup_msi_irqs = u3msi_setup_msi_irqs;
 196                 phb->controller_ops.teardown_msi_irqs = u3msi_teardown_msi_irqs;
 197         }
 198 
 199         return 0;
 200 }

/* [<][>][^][v][top][bottom][index][help] */