Lines Matching +full:msi +full:- +full:x
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Adding PCI-E MSI support for PPC4XX SoCs.
12 #include <linux/msi.h>
19 #include <asm/ppc-pci.h>
21 #include <asm/dcr-regs.h>
51 err = msi_bitmap_alloc(&msi_data->bitmap, msi_irqs, in ppc4xx_msi_init_allocator()
52 dev->dev.of_node); in ppc4xx_msi_init_allocator()
56 err = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap); in ppc4xx_msi_init_allocator()
58 msi_bitmap_free(&msi_data->bitmap); in ppc4xx_msi_init_allocator()
67 int int_no = -ENOMEM; in ppc4xx_setup_msi_irqs()
73 dev_dbg(&dev->dev, "PCIE-MSI:%s called. vec %x type %d\n", in ppc4xx_setup_msi_irqs()
76 pr_debug("ppc4xx msi: MSI-X untested, trying anyway.\n"); in ppc4xx_setup_msi_irqs()
78 msi_data->msi_virqs = kmalloc_array(msi_irqs, sizeof(int), GFP_KERNEL); in ppc4xx_setup_msi_irqs()
79 if (!msi_data->msi_virqs) in ppc4xx_setup_msi_irqs()
80 return -ENOMEM; in ppc4xx_setup_msi_irqs()
83 int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); in ppc4xx_setup_msi_irqs()
87 pr_debug("%s: fail allocating msi interrupt\n", in ppc4xx_setup_msi_irqs()
90 virq = irq_of_parse_and_map(msi_data->msi_dev, int_no); in ppc4xx_setup_msi_irqs()
92 dev_err(&dev->dev, "%s: fail mapping irq\n", __func__); in ppc4xx_setup_msi_irqs()
93 msi_bitmap_free_hwirqs(&msi_data->bitmap, int_no, 1); in ppc4xx_setup_msi_irqs()
94 return -ENOSPC; in ppc4xx_setup_msi_irqs()
96 dev_dbg(&dev->dev, "%s: virq = %d\n", __func__, virq); in ppc4xx_setup_msi_irqs()
98 /* Setup msi address space */ in ppc4xx_setup_msi_irqs()
99 msg.address_hi = msi_data->msi_addr_hi; in ppc4xx_setup_msi_irqs()
100 msg.address_lo = msi_data->msi_addr_lo; in ppc4xx_setup_msi_irqs()
115 dev_dbg(&dev->dev, "PCIE-MSI: tearing down msi irqs\n"); in ppc4xx_teardown_msi_irqs()
118 if (!entry->irq) in ppc4xx_teardown_msi_irqs()
120 hwirq = virq_to_hw(entry->irq); in ppc4xx_teardown_msi_irqs()
121 irq_set_msi_desc(entry->irq, NULL); in ppc4xx_teardown_msi_irqs()
122 irq_dispose_mapping(entry->irq); in ppc4xx_teardown_msi_irqs()
123 msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1); in ppc4xx_teardown_msi_irqs()
128 struct resource res, struct ppc4xx_msi *msi) in ppc4xx_setup_pcieh_hw() argument
137 sdr_addr = of_get_property(dev->dev.of_node, "sdr-base", NULL); in ppc4xx_setup_pcieh_hw()
139 return -EINVAL; in ppc4xx_setup_pcieh_hw()
141 msi_data = of_get_property(dev->dev.of_node, "msi-data", NULL); in ppc4xx_setup_pcieh_hw()
143 return -EINVAL; in ppc4xx_setup_pcieh_hw()
145 msi_mask = of_get_property(dev->dev.of_node, "msi-mask", NULL); in ppc4xx_setup_pcieh_hw()
147 return -EINVAL; in ppc4xx_setup_pcieh_hw()
149 msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi"); in ppc4xx_setup_pcieh_hw()
150 if (!msi->msi_dev) in ppc4xx_setup_pcieh_hw()
151 return -ENODEV; in ppc4xx_setup_pcieh_hw()
153 msi->msi_regs = of_iomap(msi->msi_dev, 0); in ppc4xx_setup_pcieh_hw()
154 if (!msi->msi_regs) { in ppc4xx_setup_pcieh_hw()
155 dev_err(&dev->dev, "of_iomap failed\n"); in ppc4xx_setup_pcieh_hw()
156 err = -ENOMEM; in ppc4xx_setup_pcieh_hw()
159 dev_dbg(&dev->dev, "PCIE-MSI: msi register mapped 0x%x 0x%x\n", in ppc4xx_setup_pcieh_hw()
160 (u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs)); in ppc4xx_setup_pcieh_hw()
162 msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL); in ppc4xx_setup_pcieh_hw()
164 err = -ENOMEM; in ppc4xx_setup_pcieh_hw()
167 msi->msi_addr_hi = upper_32_bits(msi_phys); in ppc4xx_setup_pcieh_hw()
168 msi->msi_addr_lo = lower_32_bits(msi_phys & 0xffffffff); in ppc4xx_setup_pcieh_hw()
169 dev_dbg(&dev->dev, "PCIE-MSI: msi address high 0x%x, low 0x%x\n", in ppc4xx_setup_pcieh_hw()
170 msi->msi_addr_hi, msi->msi_addr_lo); in ppc4xx_setup_pcieh_hw()
176 out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi); in ppc4xx_setup_pcieh_hw()
177 out_be32(msi->msi_regs + PEIH_TERMADL, msi->msi_addr_lo); in ppc4xx_setup_pcieh_hw()
179 /* Program MSI Expected data and Mask bits */ in ppc4xx_setup_pcieh_hw()
180 out_be32(msi->msi_regs + PEIH_MSIED, *msi_data); in ppc4xx_setup_pcieh_hw()
181 out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask); in ppc4xx_setup_pcieh_hw()
183 dma_free_coherent(&dev->dev, 64, msi_virt, msi_phys); in ppc4xx_setup_pcieh_hw()
188 iounmap(msi->msi_regs); in ppc4xx_setup_pcieh_hw()
190 of_node_put(msi->msi_dev); in ppc4xx_setup_pcieh_hw()
196 struct ppc4xx_msi *msi = dev->dev.platform_data; in ppc4xx_of_msi_remove() local
201 virq = msi->msi_virqs[i]; in ppc4xx_of_msi_remove()
206 if (msi->bitmap.bitmap) in ppc4xx_of_msi_remove()
207 msi_bitmap_free(&msi->bitmap); in ppc4xx_of_msi_remove()
208 iounmap(msi->msi_regs); in ppc4xx_of_msi_remove()
209 of_node_put(msi->msi_dev); in ppc4xx_of_msi_remove()
216 struct ppc4xx_msi *msi; in ppc4xx_msi_probe() local
221 dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n"); in ppc4xx_msi_probe()
223 msi = devm_kzalloc(&dev->dev, sizeof(*msi), GFP_KERNEL); in ppc4xx_msi_probe()
224 if (!msi) in ppc4xx_msi_probe()
225 return -ENOMEM; in ppc4xx_msi_probe()
226 dev->dev.platform_data = msi; in ppc4xx_msi_probe()
228 /* Get MSI ranges */ in ppc4xx_msi_probe()
229 err = of_address_to_resource(dev->dev.of_node, 0, &res); in ppc4xx_msi_probe()
231 dev_err(&dev->dev, "%pOF resource error!\n", dev->dev.of_node); in ppc4xx_msi_probe()
235 msi_irqs = of_irq_count(dev->dev.of_node); in ppc4xx_msi_probe()
237 return -ENODEV; in ppc4xx_msi_probe()
239 err = ppc4xx_setup_pcieh_hw(dev, res, msi); in ppc4xx_msi_probe()
243 err = ppc4xx_msi_init_allocator(dev, msi); in ppc4xx_msi_probe()
245 dev_err(&dev->dev, "Error allocating MSI bitmap\n"); in ppc4xx_msi_probe()
248 ppc4xx_msi = *msi; in ppc4xx_msi_probe()
251 phb->controller_ops.setup_msi_irqs = ppc4xx_setup_msi_irqs; in ppc4xx_msi_probe()
252 phb->controller_ops.teardown_msi_irqs = ppc4xx_teardown_msi_irqs; in ppc4xx_msi_probe()
262 .compatible = "amcc,ppc4xx-msi",
270 .name = "ppc4xx-msi",