18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2020 Loongson Technology Corporation Limited 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#include <linux/compiler.h> 68c2ecf20Sopenharmony_ci#include <linux/delay.h> 78c2ecf20Sopenharmony_ci#include <linux/init.h> 88c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 98c2ecf20Sopenharmony_ci#include <linux/irqchip.h> 108c2ecf20Sopenharmony_ci#include <linux/irqdomain.h> 118c2ecf20Sopenharmony_ci#include <linux/mm.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/stddef.h> 148c2ecf20Sopenharmony_ci#include <asm/irq.h> 158c2ecf20Sopenharmony_ci#include <asm/numa.h> 168c2ecf20Sopenharmony_ci#include <asm/setup.h> 178c2ecf20Sopenharmony_ci#include <asm/loongarchregs.h> 188c2ecf20Sopenharmony_ci#include <loongson.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistruct acpi_madt_lio_pic *acpi_liointc; 218c2ecf20Sopenharmony_cistruct acpi_madt_eio_pic *acpi_eiointc[MAX_IO_PICS]; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistruct acpi_madt_ht_pic *acpi_htintc; 248c2ecf20Sopenharmony_cistruct acpi_madt_lpc_pic *acpi_pchlpc; 258c2ecf20Sopenharmony_cistruct acpi_madt_msi_pic *acpi_pchmsi[MAX_IO_PICS]; 268c2ecf20Sopenharmony_cistruct acpi_madt_bio_pic *acpi_pchpic[MAX_IO_PICS]; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistruct irq_domain *cpu_domain; 298c2ecf20Sopenharmony_cistruct irq_domain *liointc_domain; 308c2ecf20Sopenharmony_cistruct irq_domain *pch_lpc_domain; 318c2ecf20Sopenharmony_cistruct irq_domain *pch_msi_domain[MAX_IO_PICS]; 328c2ecf20Sopenharmony_cistruct irq_domain *pch_pic_domain[MAX_IO_PICS]; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ciint find_pch_pic(u32 gsi) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci int i, start, end; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci /* Find the PCH_PIC that manages this GSI. */ 398c2ecf20Sopenharmony_ci for(i = 0; i < loongson_sysconf.nr_io_pics; i++) { 408c2ecf20Sopenharmony_ci struct acpi_madt_bio_pic *irq_cfg = acpi_pchpic[i]; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci start = irq_cfg->gsi_base; 438c2ecf20Sopenharmony_ci end = irq_cfg->gsi_base + irq_cfg->size; 448c2ecf20Sopenharmony_ci if (gsi >= start && gsi < end) 458c2ecf20Sopenharmony_ci return i; 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci printk(KERN_ERR "ERROR: Unable to locate PCH_PIC for GSI %d\n", gsi); 498c2ecf20Sopenharmony_ci return -1; 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_civoid __init setup_IRQ(void) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci int i; 558c2ecf20Sopenharmony_ci struct irq_domain *parent_domain; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci if (!acpi_eiointc[0]) 588c2ecf20Sopenharmony_ci cpu_data[0].options &= ~LOONGARCH_CPU_EXTIOI; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci cpu_domain = loongarch_cpu_irq_init(); 618c2ecf20Sopenharmony_ci liointc_domain = liointc_acpi_init(cpu_domain, acpi_liointc); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (cpu_has_extioi) { 648c2ecf20Sopenharmony_ci pr_info("Using EIOINTC interrupt mode\n"); 658c2ecf20Sopenharmony_ci for(i = 0; i < loongson_sysconf.nr_io_pics; i++) { 668c2ecf20Sopenharmony_ci parent_domain = eiointc_acpi_init(cpu_domain, acpi_eiointc[i]); 678c2ecf20Sopenharmony_ci pch_pic_domain[i] = pch_pic_acpi_init(parent_domain, acpi_pchpic[i]); 688c2ecf20Sopenharmony_ci pch_msi_domain[i] = pch_msi_acpi_init(parent_domain, acpi_pchmsi[i]); 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci } else { 718c2ecf20Sopenharmony_ci pr_info("Using HTVECINTC interrupt mode\n"); 728c2ecf20Sopenharmony_ci parent_domain = htvec_acpi_init(liointc_domain, acpi_htintc); 738c2ecf20Sopenharmony_ci pch_pic_domain[0] = pch_pic_acpi_init(parent_domain, acpi_pchpic[0]); 748c2ecf20Sopenharmony_ci pch_msi_domain[0] = pch_msi_acpi_init(parent_domain, acpi_pchmsi[0]); 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci irq_set_default_host(pch_pic_domain[0]); 788c2ecf20Sopenharmony_ci pch_lpc_domain = pch_lpc_acpi_init(pch_pic_domain[0], acpi_pchlpc); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_civoid __init arch_init_irq(void) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci int r, ipi_irq; 848c2ecf20Sopenharmony_ci static int ipi_dummy_dev; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci clear_csr_ecfg(ECFG0_IM); 878c2ecf20Sopenharmony_ci clear_csr_estat(ESTATF_IP); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci setup_IRQ(); 908c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 918c2ecf20Sopenharmony_ci ipi_irq = get_ipi_irq(); 928c2ecf20Sopenharmony_ci irq_set_percpu_devid(ipi_irq); 938c2ecf20Sopenharmony_ci r = request_percpu_irq(ipi_irq, loongson3_ipi_interrupt, "IPI", &ipi_dummy_dev); 948c2ecf20Sopenharmony_ci if (r < 0) 958c2ecf20Sopenharmony_ci panic("IPI IRQ request failed\n"); 968c2ecf20Sopenharmony_ci#endif 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci set_csr_ecfg(ECFGF_IP0 | ECFGF_IP1 | ECFGF_IP2 | ECFGF_IPI | ECFGF_PMC); 998c2ecf20Sopenharmony_ci} 100