18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2006-2007, Michael Ellerman, IBM Corporation. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/irq.h> 78c2ecf20Sopenharmony_ci#include <linux/bitmap.h> 88c2ecf20Sopenharmony_ci#include <linux/msi.h> 98c2ecf20Sopenharmony_ci#include <asm/mpic.h> 108c2ecf20Sopenharmony_ci#include <asm/prom.h> 118c2ecf20Sopenharmony_ci#include <asm/hw_irq.h> 128c2ecf20Sopenharmony_ci#include <asm/ppc-pci.h> 138c2ecf20Sopenharmony_ci#include <asm/msi_bitmap.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <sysdev/mpic.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_civoid mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci /* The mpic calls this even when there is no allocator setup */ 208c2ecf20Sopenharmony_ci if (!mpic->msi_bitmap.bitmap) 218c2ecf20Sopenharmony_ci return; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq); 248c2ecf20Sopenharmony_ci} 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#ifdef CONFIG_MPIC_U3_HT_IRQS 278c2ecf20Sopenharmony_cistatic int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci irq_hw_number_t hwirq; 308c2ecf20Sopenharmony_ci const struct irq_domain_ops *ops = mpic->irqhost->ops; 318c2ecf20Sopenharmony_ci struct device_node *np; 328c2ecf20Sopenharmony_ci int flags, index, i; 338c2ecf20Sopenharmony_ci struct of_phandle_args oirq; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci pr_debug("mpic: found U3, guessing msi allocator setup\n"); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci /* Reserve source numbers we know are reserved in the HW. 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * This is a bit of a mix of U3 and U4 reserves but that's going 408c2ecf20Sopenharmony_ci * to work fine, we have plenty enugh numbers left so let's just 418c2ecf20Sopenharmony_ci * mark anything we don't like reserved. 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 448c2ecf20Sopenharmony_ci msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci for (i = 42; i < 46; i++) 478c2ecf20Sopenharmony_ci msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci for (i = 100; i < 105; i++) 508c2ecf20Sopenharmony_ci msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci for (i = 124; i < mpic->num_sources; i++) 538c2ecf20Sopenharmony_ci msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci np = NULL; 578c2ecf20Sopenharmony_ci while ((np = of_find_all_nodes(np))) { 588c2ecf20Sopenharmony_ci pr_debug("mpic: mapping hwirqs for %pOF\n", np); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci index = 0; 618c2ecf20Sopenharmony_ci while (of_irq_parse_one(np, index++, &oirq) == 0) { 628c2ecf20Sopenharmony_ci ops->xlate(mpic->irqhost, NULL, oirq.args, 638c2ecf20Sopenharmony_ci oirq.args_count, &hwirq, &flags); 648c2ecf20Sopenharmony_ci msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq); 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci return 0; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci#else 718c2ecf20Sopenharmony_cistatic int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci return -1; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci#endif 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ciint mpic_msi_init_allocator(struct mpic *mpic) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci int rc; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->num_sources, 828c2ecf20Sopenharmony_ci irq_domain_get_of_node(mpic->irqhost)); 838c2ecf20Sopenharmony_ci if (rc) 848c2ecf20Sopenharmony_ci return rc; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci rc = msi_bitmap_reserve_dt_hwirqs(&mpic->msi_bitmap); 878c2ecf20Sopenharmony_ci if (rc > 0) { 888c2ecf20Sopenharmony_ci if (mpic->flags & MPIC_U3_HT_IRQS) 898c2ecf20Sopenharmony_ci rc = mpic_msi_reserve_u3_hwirqs(mpic); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci if (rc) { 928c2ecf20Sopenharmony_ci msi_bitmap_free(&mpic->msi_bitmap); 938c2ecf20Sopenharmony_ci return rc; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci return 0; 988c2ecf20Sopenharmony_ci} 99