Received: by 2002:ad5:4acb:0:0:0:0:0 with SMTP id n11csp5347878imw; Wed, 20 Jul 2022 04:06:18 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tsPWsqt6rNrX1992n+iR5ysh0nbSm8PhOEN2NC5Dspb9kAhN7ibaa1HyXfLzRyM11plPB3 X-Received: by 2002:aca:b506:0:b0:33a:71a1:a733 with SMTP id e6-20020acab506000000b0033a71a1a733mr2010872oif.61.1658315178259; Wed, 20 Jul 2022 04:06:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1658315178; cv=none; d=google.com; s=arc-20160816; b=h9IeuDN17kqOT0CUdJR2Tsl4R14iH1jx0pCIFmad/vktKWlSzGJNzjW/Yv9JgtV74s y/qEr08V2gyIGgP5ISRcbr5SgpUaj9MVcyfH47KseXUtPmEIg9YiXh5+HwPSBRbvs1PX T5nO4j/36pNMjfvMd5NATwJ+LhoPZdZvDjIU9YfSIkDhgMHG0KdaIW1pyDyGi0MtLhRb TVCfQcgc4Hat3wLjqoHg6TggVawm4vXWDNFJrqgaqVE9N1QJMJ47YzogfdARI8UTnQX7 jQbVz8UsaXkMe6mHA7QAOAFWIQVaXuwH1F4ruKDGVcnLvuxhcUzwJpSrXw84NBFyHwxz TXCw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=i+FFevN2H/6pMlI6oKJ2v9YRd6lf6sNjqKn2nY3u+VE=; b=R8sJrHzl7HQapRiqxPAaVJkNE/+OAikJmw4NwbLsls+ZLb0M6Yz0n8CdT0ndT1Bbr9 6Qbsf9fo9sEJZLsixPNbpzeqN8Ui+tD2JyPcBWdC43L+fX9Z0egH3i3+4JqHPuL7lfX7 npzk4V+WnDH3W5cEUOdINrPgPaEw/7mA3VZw0ZCpcJXo7xnN4jiD+r0Anfthkh8yPgL0 iaAavV/8O2QxYxneMkOCYMx+oV49aKfNU4ZzBaSDXmMnekpfwJir3CFkQ+XiEAoMCNCP 1pxMXpDPPShCrosiU/H2WgTnbEW0W66kwdAGSzACXU8Jx9KzlLTrJ41mY9pwB2pKcqcI B8yA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id 17-20020aca2111000000b0033a73c78ecbsi7929296oiz.44.2022.07.20.04.06.04; Wed, 20 Jul 2022 04:06:18 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240231AbiGTKwY (ORCPT + 99 others); Wed, 20 Jul 2022 06:52:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33976 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239416AbiGTKvs (ORCPT ); Wed, 20 Jul 2022 06:51:48 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id A903B6D2EB for ; Wed, 20 Jul 2022 03:51:46 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxH9E13tdiwnUqAA--.39621S14; Wed, 20 Jul 2022 18:51:40 +0800 (CST) From: Jianmin Lv To: Thomas Gleixner , Marc Zyngier Cc: linux-kernel@vger.kernel.org, loongarch@lists.linux.dev, Hanjun Guo , Lorenzo Pieralisi , Jiaxun Yang , Huacai Chen Subject: [PATCH V18 12/13] irqchip: Add LoongArch CPU interrupt controller support Date: Wed, 20 Jul 2022 18:51:31 +0800 Message-Id: <1658314292-35346-13-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1658314292-35346-1-git-send-email-lvjianmin@loongson.cn> References: <1658314292-35346-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9DxH9E13tdiwnUqAA--.39621S14 X-Coremail-Antispam: 1UD129KBjvJXoW3WFyftFW7GrykCFyrGrW3Jrb_yoWfZrW7pF W3AwsFqr4UJFy8Xr9Yka98Wry3Z3WxW3y2qayfGa43Ar4DtryqqF4vyr9FvFyYy3y8Gay2 vF4rtFW8uF4UA3JanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUvY1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UM28EF7xvwVC2 z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0DM2AIxVAIcxkEcV Aq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r10 6r15McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64 vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkIecxEwVCm-wCF04k20xvY0x0EwIxGrwCF 04k20xvE74AGY7Cv6cx26ryrJr1UJwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F4 0E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFyl IxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvEc7CjxV AFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_ Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x0J UZa9-UUUUU= X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_PASS, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Huacai Chen LoongArch CPUINTC stands for CSR.ECFG/CSR.ESTAT and related interrupt controller that described in Section 7.4 of "LoongArch Reference Manual, Vol 1". For more information please refer Documentation/loongarch/irq- chip-model.rst. LoongArch CPUINTC has 13 interrupt sources: SWI0~1, HWI0~7, IPI, TI (Timer) and PCOV (PMC). IRQ mappings of HWI0~7 are configurable (can be created from DT/ACPI), but IPI, TI (Timer) and PCOV (PMC) are hardcoded bits, so we expose the fwnode_handle to map them, and get mapped irq by irq_create_mapping when using them. Co-developed-by: Jianmin Lv Signed-off-by: Jianmin Lv Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/irq.h | 7 +-- arch/loongarch/kernel/irq.c | 16 +++++- arch/loongarch/kernel/time.c | 14 ++++- drivers/irqchip/Kconfig | 10 ++++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-loongarch-cpu.c | 111 ++++++++++++++++++++++++++++++++++++ 6 files changed, 149 insertions(+), 10 deletions(-) create mode 100644 drivers/irqchip/irq-loongarch-cpu.c diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index 67ebcc5..149b212 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -35,9 +35,6 @@ static inline bool on_irq_stack(int cpu, unsigned long sp) return (low <= sp && sp <= high); } -int get_ipi_irq(void); -int get_pmc_irq(void); -int get_timer_irq(void); void spurious_interrupt(void); #define NR_IRQS_LEGACY 16 @@ -94,8 +91,6 @@ struct acpi_vector_group { struct acpi_madt_msi_pic; struct acpi_madt_lpc_pic; -struct irq_domain *loongarch_cpu_irq_init(void); - int liointc_acpi_init(struct irq_domain *parent, struct acpi_madt_lio_pic *acpi_liointc); int eiointc_acpi_init(struct irq_domain *parent, @@ -128,7 +123,7 @@ int pch_pic_acpi_init(struct irq_domain *parent, extern struct acpi_madt_msi_pic *acpi_pchmsi[MAX_IO_PICS]; extern struct acpi_madt_bio_pic *acpi_pchpic[MAX_IO_PICS]; -extern struct irq_domain *cpu_domain; +extern struct fwnode_handle *cpuintc_handle; extern struct fwnode_handle *liointc_handle; extern struct fwnode_handle *pch_lpc_handle; extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS]; diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index da131f5..1ba19c7 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -25,8 +25,6 @@ DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); EXPORT_PER_CPU_SYMBOL(irq_stat); -struct irq_domain *cpu_domain; - struct acpi_vector_group pch_group[MAX_IO_PICS]; struct acpi_vector_group msi_group[MAX_IO_PICS]; /* @@ -89,6 +87,16 @@ static void __init init_vec_parent_group(void) acpi_table_parse(ACPI_SIG_MCFG, early_pci_mcfg_parse); } +static int __init get_ipi_irq(void) +{ + struct irq_domain *d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY); + + if (d) + return irq_create_mapping(d, EXCCODE_IPI - EXCCODE_INT_START); + + return -EINVAL; +} + void __init init_IRQ(void) { int i; @@ -105,7 +113,9 @@ void __init init_IRQ(void) init_vec_parent_group(); irqchip_init(); #ifdef CONFIG_SMP - ipi_irq = EXCCODE_IPI - EXCCODE_INT_START; + ipi_irq = get_ipi_irq(); + if (ipi_irq < 0) + panic("IPI IRQ mapping failed\n"); irq_set_percpu_devid(ipi_irq); r = request_percpu_irq(ipi_irq, loongson3_ipi_interrupt, "IPI", &ipi_dummy_dev); if (r < 0) diff --git a/arch/loongarch/kernel/time.c b/arch/loongarch/kernel/time.c index fe68238..79dc5ed 100644 --- a/arch/loongarch/kernel/time.c +++ b/arch/loongarch/kernel/time.c @@ -123,6 +123,16 @@ void sync_counter(void) csr_write64(-init_timeval, LOONGARCH_CSR_CNTC); } +static int get_timer_irq(void) +{ + struct irq_domain *d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY); + + if (d) + return irq_create_mapping(d, EXCCODE_TIMER - EXCCODE_INT_START); + + return -EINVAL; +} + int constant_clockevent_init(void) { unsigned int irq; @@ -132,7 +142,9 @@ int constant_clockevent_init(void) struct clock_event_device *cd; static int timer_irq_installed = 0; - irq = EXCCODE_TIMER - EXCCODE_INT_START; + irq = get_timer_irq(); + if (irq < 0) + pr_err("Failed to map irq %d (timer)\n", irq); cd = &per_cpu(constant_clockevent_device, cpu); diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 8f077d3..f53164c 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -546,6 +546,16 @@ config EXYNOS_IRQ_COMBINER Say yes here to add support for the IRQ combiner devices embedded in Samsung Exynos chips. +config IRQ_LOONGARCH_CPU + bool + select GENERIC_IRQ_CHIP + select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK + help + Support for the LoongArch CPU Interrupt Controller. For details of + irq chip hierarchy on LoongArch platforms please read the document + Documentation/loongarch/irq-chip-model.rst. + config LOONGSON_LIOINTC bool "Loongson Local I/O Interrupt Controller" depends on MACH_LOONGSON64 diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 0cfd4f0..e559007 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -103,6 +103,7 @@ obj-$(CONFIG_LS1X_IRQ) += irq-ls1x.o obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) += irq-ti-sci-intr.o obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) += irq-ti-sci-inta.o obj-$(CONFIG_TI_PRUSS_INTC) += irq-pruss-intc.o +obj-$(CONFIG_IRQ_LOONGARCH_CPU) += irq-loongarch-cpu.o obj-$(CONFIG_LOONGSON_LIOINTC) += irq-loongson-liointc.o obj-$(CONFIG_LOONGSON_EIOINTC) += irq-loongson-eiointc.o obj-$(CONFIG_LOONGSON_HTPIC) += irq-loongson-htpic.o diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c new file mode 100644 index 0000000..28ddc60 --- /dev/null +++ b/drivers/irqchip/irq-loongarch-cpu.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +static struct irq_domain *irq_domain; +struct fwnode_handle *cpuintc_handle; + +static void mask_loongarch_irq(struct irq_data *d) +{ + clear_csr_ecfg(ECFGF(d->hwirq)); +} + +static void unmask_loongarch_irq(struct irq_data *d) +{ + set_csr_ecfg(ECFGF(d->hwirq)); +} + +static struct irq_chip cpu_irq_controller = { + .name = "CPUINTC", + .irq_mask = mask_loongarch_irq, + .irq_unmask = unmask_loongarch_irq, +}; + +static void handle_cpu_irq(struct pt_regs *regs) +{ + int hwirq; + unsigned int estat = read_csr_estat() & CSR_ESTAT_IS; + + while ((hwirq = ffs(estat))) { + estat &= ~BIT(hwirq - 1); + generic_handle_domain_irq(irq_domain, hwirq - 1); + } +} + +static int loongarch_cpu_intc_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) +{ + irq_set_noprobe(irq); + irq_set_chip_and_handler(irq, &cpu_irq_controller, handle_percpu_irq); + + return 0; +} + +static const struct irq_domain_ops loongarch_cpu_intc_irq_domain_ops = { + .map = loongarch_cpu_intc_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int __init +liointc_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_lio_pic *liointc_entry = (struct acpi_madt_lio_pic *)header; + + return liointc_acpi_init(irq_domain, liointc_entry); +} + +static int __init +eiointc_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_eio_pic *eiointc_entry = (struct acpi_madt_eio_pic *)header; + + return eiointc_acpi_init(irq_domain, eiointc_entry); +} + +static int __init acpi_cascade_irqdomain_init(void) +{ + acpi_table_parse_madt(ACPI_MADT_TYPE_LIO_PIC, + liointc_parse_madt, 0); + acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC, + eiointc_parse_madt, 0); + return 0; +} + +static int __init cpuintc_acpi_init(union acpi_subtable_headers *header, + const unsigned long end) +{ + if (irq_domain) + return 0; + + /* Mask interrupts. */ + clear_csr_ecfg(ECFG0_IM); + clear_csr_estat(ESTATF_IP); + + cpuintc_handle = irq_domain_alloc_fwnode(NULL); + irq_domain = irq_domain_create_linear(cpuintc_handle, EXCCODE_INT_NUM, + &loongarch_cpu_intc_irq_domain_ops, NULL); + + if (!irq_domain) + panic("Failed to add irqdomain for LoongArch CPU"); + + set_handle_irq(&handle_cpu_irq); + acpi_cascade_irqdomain_init(); + + return 0; +} + +IRQCHIP_ACPI_DECLARE(cpuintc_v1, ACPI_MADT_TYPE_CORE_PIC, + NULL, ACPI_MADT_CORE_PIC_VERSION_V1, cpuintc_acpi_init); -- 1.8.3.1